diff -u --recursive --new-file v2.4.5/linux/CREDITS linux/CREDITS --- v2.4.5/linux/CREDITS Tue May 22 19:54:04 2001 +++ linux/CREDITS Thu Jun 28 14:58:05 2001 @@ -454,6 +454,11 @@ E: xavyer@ix.netcom.com D: USB Serial Empeg Empeg-car Mark I/II Driver +N: Matthias Bruestle +E: m@mbsks.franken.de +D: REINER SCT cyberJack pinpad/e-com USB chipcard reader driver +S: Germany + N: Ray Burr E: ryb@nightmare.com D: Original author of Amiga FFS filesystem @@ -1136,13 +1141,11 @@ S: USA N: Benjamin Herrenschmidt -E: bh40@calva.net +E: benh@kernel.crashing.org E: benh@mipsys.com -D: PowerMac booter (BootX) -D: Additional PowerBook support -D: Apple "Core99" machines support (ibook,g4,...) -S: 22, rue des Marguettes -S: 75012 Paris +D: Various parts of PPC & PowerMac +S: 122, boulevard Baille +S: 13005 Marseille S: France N: Sebastian Hetze @@ -1356,13 +1359,15 @@ E: davej@suse.de W: http://www.suse.de/~davej D: Moved PCI bridge tuning to userspace (Powertweak). -D: Centaur/IDT Winchip/Winchip 2 tweaks. +D: Various x86 (& clones) setup code hacking. D: AFFS fixes for 2.3.x -D: Misc clean ups and other random hacking. -S: 28, Laura Street, -S: Treforest, Pontypridd, -S: Mid Glamorgan, CF37 1NW, -S: Wales, United Kingdom +D: Various Janitorial hacks. (kernel-janitor.sourceforge.net) +S: c/o SuSE Linux UK Ltd +S: The Kinetic Centre +S: Theobald Street +S: Borehamwood +S: Herts, WD6 4PJ +S: United Kingdom N: Ani Joshi E: ajoshi@shell.unixbox.com @@ -1518,6 +1523,17 @@ S: L3R 8B2 S: Canada +N: Maxim Krasnyansky +E: maxk@qualcomm.com +W: http://vtun.sf.net +W: http://bluez.sf.net +D: Author of the Universal TUN/TAP driver +D: Author of the Linux Bluetooth Subsystem (BlueZ) +D: Various other kernel patches, cleanups and fixes +S: 2213 La Terrace Circle +S: San Jose, CA 95123 +S: USA + N: Andreas S. Krebs E: akrebs@altavista.net D: CYPRESS CY82C693 chipset IDE, Digital's PC-Alpha 164SX boards @@ -1742,6 +1758,8 @@ N: Paul Mackerras E: paulus@samba.org +D: PPP driver +D: Linux for PowerPC D: Linux port for PCI Power Macintosh N: Pat Mackinlay @@ -1975,6 +1993,13 @@ S: Richardson, Texas 75081 S: USA +N: Patrick Mochel +E: mochel@transmeta.com +D: PCI Power Management, ACPI work +S: 3940 Freedom Circle +S: Santa Clara, CA 95054 +S: USA + N: Eberhard Moenkeberg E: emoenke@gwdg.de D: CDROM driver "sbpcd" (Matsushita/Panasonic/Soundblaster) @@ -2697,9 +2722,7 @@ N: Marcelo W. Tosatti E: marcelo@conectiva.com.br W: http://bazar.conectiva.com.br/~marcelo/ -D: Miscellaneous kernel hacker -D: Cyclom 2X driver, drbd hacker -D: linuxconf apache & proftpd module maintainer +D: Miscellaneous kernel hacker (mostly VM/MM work) S: Conectiva S.A. S: R. Tocantins, 89 - Cristo Rei S: 80050-430 - Curitiba - Paraná @@ -2883,6 +2906,14 @@ S: X/OS Experts in Open Systems BV S: Kruislaan 419 S: 1098 VA Amsterdam +S: The Netherlands + +N: Jeroen Vreeken +E: pe1rxq@amsat.org +W: http://www.chello.nl/~j.vreeken/ +D: SE401 usb webcam driver +S: Maastrichterweg 63 +S: 5554 GG Valkenswaard S: The Netherlands N: Peter Shaobo Wang diff -u --recursive --new-file v2.4.5/linux/Documentation/Changes linux/Documentation/Changes --- v2.4.5/linux/Documentation/Changes Sat May 19 17:43:05 2001 +++ linux/Documentation/Changes Wed Jun 27 13:37:05 2001 @@ -320,7 +320,7 @@ LVM toolset ----------- -o +o Pcmcia-cs --------- @@ -347,7 +347,7 @@ PPP --- -o +o Isdn4k-utils ------------ diff -u --recursive --new-file v2.4.5/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.4.5/linux/Documentation/Configure.help Thu May 24 15:03:06 2001 +++ linux/Documentation/Configure.help Mon Jul 2 14:07:55 2001 @@ -7537,6 +7537,40 @@ configure your card and that /etc/pcmcia/wireless.opts works : http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html +Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards +CONFIG_AIRO + This is the standard Linux driver to support Cisco/Aironet ISA + and PCI 802.11 wireless cards. + It supports the new 802.11b cards from Cisco (Cisco 34X, Cisco 35X + - with or without encryption) as well as card before the Cisco + aquisition (Aironet 4500, Aironet 4800, Aironet 4800B). + + This driver support both the standard Linux Wireless Extensions + and Cisco proprietary API, so both the Linux Wireless Tools and the + Cisco Linux utilities can be used to configure the card. + + The driver can be compiled as a module and will be named "airo.o". + +Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards +CONFIG_AIRO_CS + This is the standard Linux driver to support Cisco/Aironet PCMCIA + 802.11 wireless cards. This driver is the same as the Aironet + driver part of the Linux Pcmcia package. + It supports the new 802.11b cards from Cisco (Cisco 34X, Cisco 35X + - with or without encryption) as well as card before the Cisco + aquisition (Aironet 4500, Aironet 4800, Aironet 4800B). It also + supports OEM of Cisco such as the DELL TrueMobile 4800 and Xircom + 802.11b cards. + + This driver support both the standard Linux Wireless Extensions + and Cisco proprietary API, so both the Linux Wireless Tools and the + Cisco Linux utilities can be used to configure the card. + + To use your PC-cards, you will need supporting software from David + Hinds' pcmcia-cs package (see the file Documentation/Changes for + location). You also want to check out the PCMCIA-HOWTO, available + from http://www.linuxdoc.org/docs.html#howto . + Aviator/Raytheon 2.4MHz wireless support CONFIG_PCMCIA_RAYCS Say Y here if you intend to attach an Aviator/Raytheon PCMCIA @@ -9423,6 +9457,15 @@ module, say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. +New Tulip bus configuration (EXPERIMENTAL) +CONFIG_TULIP_MWI + This configures your Tulip card specifically for the card and + system cache line size type you are using. + + This is experimental code, not yet tested on many boards. + + If unsure, say N. + Digi Intl. RightSwitch support CONFIG_DGRS This is support for the Digi International RightSwitch series of @@ -10182,91 +10225,150 @@ Memory Technology Device (MTD) support CONFIG_MTD Memory Technology Devices are flash, RAM and similar chips, often - used for solid state file systems on embedded devices. This option + used for solid state filesystems on embedded devices. This option will provide the generic support for MTD drivers to register themselves with the kernel and for potential users of MTD devices to enumerate the devices which are present and obtain a handle on them. It will also allow you to select individual drivers for - particular hardware and users of MTD device. If unsure, say N. + particular hardware and users of MTD devices. If unsure, say N. MTD debugging support CONFIG_MTD_DEBUG This turns on low-level debugging for the entire MTD sub-system. + Normally, you should say 'N'. + +MTD partitioning support +CONFIG_MTD_PARTITIONS + If you have a device which needs to divide its flash chip(s) up + into multiple 'partitions', each of which appears to the user as + a separate MTD device, you require this option to be enabled. If + unsure, say 'Y'. + + Note, however, that you don't need this option for the DiskOnChip + devices. Partitioning on NFTL 'devices' is a different - that's the + 'normal' form of partitioning used on a block device. + +RedBoot partition table parsing +CONFIG_MTD_REDBOOT_PARTS + RedBoot is a ROM monitor and bootloader which deals with multiple + 'images' in flash devices by putting a table in the last erase + block of the device, similar to a partition table, which gives + the offsets, lengths and names of all the images stored in the + flash. + + If you need code which can detect and parse this table, and register + MTD 'partitions' corresponding to each image in the table, enable + this option. + + You will still need the parsing functions to be called by the driver + for your particular device. It won't happen automatically. The + SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for + example. + +Compaq bootldr partition table parsing +CONFIG_MTD_BOOTLDR_PARTS + The Compaq bootldr deals with multiple 'images' in flash devices + by putting a table in one of the first erase blocks of the device, + similar to a partition table, which gives the offsets, lengths and + names of all the images stored in the flash. + + If you need code which can detect and parse this table, and register + MTD 'partitions' corresponding to each image in the table, enable + this option. + + You will still need the parsing functions to be called by the driver + for your particular device. It won't happen automatically. The + SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for + example. + +ARM Firmware Suite flash layout / partition parsing +CONFIG_MTD_AFS_PARTS + The ARM Firmware Suite allows the user to divide flash devices into + multiple 'images'. Each such image has a header containing its name + and offset/size etc. + + If you need code which can detect and parse these tables, and register + MTD 'partitions' corresponding to each image detected, enable + this option. + + You will still need the parsing functions to be called by the driver + for your particular device. It won't happen automatically. The + 'armflash' map driver (CONFIG_MTD_ARMFLASH) does this, for example. MTD debugging verbosity CONFIG_MTD_DEBUG_VERBOSE Determines the verbosity level of the MTD debugging messages. -M-Systems Disk-On-Chip 1000 support -CONFIG_MTD_DOC1000 - This provides an MTD device driver for the M-Systems DiskOnChip - 1000 devices, which are obsolete so you probably want to say 'N'. -M-Systems Disk-On-Chip 2000 and Millennium support -CONFIG_MTD_DOC2000 - This provides an MTD device driver for the M-Systems DiskOnChip - 2000 and Millennium devices. Originally designed for the DiskOnChip - 2000, it also now includes support for the DiskOnChip Millennium. - If you have problems with this driver and the DiskOnChip Millennium, - you may wish to try the alternative Millennium driver below. To use - the alternative driver, you will need to undefine DOC_SINGLE_DRIVER - in the drivers/mtd/docprobe.c source code. +Direct chardevice access to MTD devices +CONFIG_MTD_CHAR + This provides a character device for each MTD device present in + the system, allowing the user to read and write directly to the + memory chips, and also use ioctl() to obtain information about + the device, or to erase parts of it. - If you use this device, you probably also want to enable the NFTL - 'NAND Flash Translation Layer' option below, which is used to emulate - a block device by using a kind of filesystem on the flash chips. +Caching block device access to MTD devices +CONFIG_MTD_BLOCK + Although most flash chips have an erase size too large to be useful + as block devices, it is possible to use MTD devices which are based + on RAM chips in this manner. This block device is a user of MTD devices + performing that function. + + At the moment, it is also required for the Journalling Flash File + System(s) to obtain a handle on the MTD device when it's mounted + (although JFFS and JFFS2 don't actually use any of the functionality + of the mtdblock device). -Alternative Disk-On-Chip Millennium support -CONFIG_MTD_DOC2001 - This provides an alternative MTD device driver for the M-Systems - DiskOnChip Millennium devices. Use this if you have problems with - the combined DiskOnChip 2000 and Millennium driver above. To get - the DiskOnChip probe code to load and use this driver instead of - the other one, you will need to undefine DOC_SINGLE_DRIVER near - the beginning of drivers/mtd/docprobe.c + Later, it may be extended to perform read/erase/modify/write cycles + on flash chips to emulate a smaller block size. Needless to say, + this is very unsafe, but could be useful for filesystems which are + almost never written to. - If you use this device, you probably also want to enable the NFTL - 'NAND Flash Translation Layer' option below, which is used to emulate - a block device by using a kind of filesystem on the flash chips. + You do not need this option for use with the DiskOnChip devices. For + those, enable NFTL support (CONFIG_NFTL) instead. -Ramix PMC551 PCI Mezzanine ram card support -CONFIG_MTD_PMC551 - This provides a MTD device driver for the Ramix PMC551 RAM PCI card - from Ramix Inc. (http://www.ramix.com/products/memory/pmc551.html). - These devices come in memory configurations from 32M - 1G. If you - have one, you probably want to enable this. +Readonly block device access to MTD devices +CONFIG_MTD_BLOCK_RO + This allows you to mount read-only filesystems (such as cramfs) from + an MTD device, without the overhead (and danger) of the caching + driver. - If this driver is compiled as a module you get the ability to select the - size of the aperture window pointing into the devices memory. What this - means is that if you have a 1G card, normally the kernel will use a 1G - memory map as it's view of the device. As a module, you can select a - 1M window into the memory and the driver will "slide" the window around - the PMC551's memory. This was particularly useful on the 2.2 kernels - on PPC architectures as there was limited kernel space to deal with. + You do not need this option for use with the DiskOnChip devices. For + those, enable NFTL support (CONFIG_NFTL) instead. -Use extra onboard system memory as MTD device -CONFIG_MTD_SLRAM - If your CPU cannot cache all of the physical memory in your machine, - you can still use it for storage or swap by using this driver to - present it to the system as a Memory Technology Device. +FTL (Flash Translation Layer) support +CONFIG_FTL + This provides support for the original Flash Translation Layer which + is part of the PCMCIA specification. It uses a kind of pseudo- + filesystem on a flash device to emulate a block device with 512-byte + sectors, on top of which you put a 'normal' filesystem. -PMC551 256M DRAM Bugfix -CONFIG_MTD_PMC551_BUGFIX - Some of Ramix's PMC551 boards with 256M configurations have invalid - column and row mux values. This option will fix them, but will break - other memory configurations. If unsure say N. + You may find that the algorithms used in this code are patented + unless you live in the Free World where software patents aren't + legal - in the USA you are only permitted to use this on PCMCIA + hardware, although under the terms of the GPL you're obviously + permitted to copy, modify and distribute the code as you wish. Just + not use it. -PMC551 Debugging -CONFIG_MTD_PMC551_DEBUG - This option makes the PMC551 more verbose during it's operation and is - only really useful if you are developing on this driver or suspect a - possible hardware or driver bug. If unsure say N. +NFTL (NAND Flash Translation Layer) support +CONFIG_NFTL + This provides support for the NAND Flash Translation Layer which is + used on M-Systems' DiskOnChip devices. It uses a kind of pseudo- + filesystem on a flash device to emulate a block device with 512-byte + sectors, on top of which you put a 'normal' filesystem. -Debugging RAM test driver -CONFIG_MTD_MTDRAM - This enables a test MTD device driver which uses vmalloc() to - provide storage. You probably want to say 'N' unless you're - testing stuff. + You may find that the algorithms used in this code are patented + unless you live in the Free World where software patents aren't + legal - in the USA you are only permitted to use this on DiskOnChip + hardware, although under the terms of the GPL you're obviously + permitted to copy, modify and distribute the code as you wish. Just + not use it. + +Write support for NFTL (EXPERIMENTAL) +CONFIG_NFTL_RW + If you're lucky, this will actually work. Don't whinge if it doesn't. + Send mail to the MTD mailing list if + you want to help to make it more reliable. Common Flash Interface (CFI) support CONFIG_MTD_CFI @@ -10277,12 +10379,135 @@ option. Visit (http://www.amd.com/products/nvd/overview/cfi.html) for more information on CFI. -CFI support for Intel/Sharp Extended Command Set chips +CFI Advanced configuration options +CONFIG_MTD_CFI_ADV_OPTIONS + If you need to specify a specific endianness for access to flash + chips, or if you wish to reduce the size of the kernel by including + support for only specific arrangements of flash chips, say 'Y'. This + option does not directly affect the code, but will enable other + configuration options which allow you to do so. + + If unsure, say 'N'. + +Specific CFI Flash geometry selection +CONFIG_MTD_CFI_GEOMETRY + This option does not affect the code directly, but will enable + some other configuration options which would allow you to reduce + the size of the kernel by including support for only certain + arrangements of CFI chips. If unsure, say 'N' and all options + which are supported by the current code will be enabled. + +Support 8-bit buswidth +CONFIG_MTD_CFI_B1 + If you wish to support CFI devices on a physical bus which is + 8 bits wide, say 'Y'. + +Support 16-bit buswidth +CONFIG_MTD_CFI_B2 + If you wish to support CFI devices on a physical bus which is + 16 bits wide, say 'Y'. + +Support 32-bit buswidth +CONFIG_MTD_CFI_B4 + If you wish to support CFI devices on a physical bus which is + 32 bits wide, say 'Y'. + +Support 1-chip flash interleave +CONFIG_MTD_CFI_I1 + If your flash chips are not interleaved - i.e. you only have one + flash chip addressed by each bus cycle, then say 'Y'. + +Support 2-chip flash interleave +CONFIG_MTD_CFI_I2 + If your flash chips are interleaved in pairs - i.e. you have two + flash chips addressed by each bus cycle, then say 'Y'. + +Support 4-chip flash interleave +CONFIG_MTD_CFI_I4 + If your flash chips are interleaved in fours - i.e. you have four + flash chips addressed by each bus cycle, then say 'Y'. + +Flash cmd/query data swapping +CONFIG_MTD_CFI_NOSWAP + This option defines the way in which the CPU attempts to arrange + data bits when writing the 'magic' commands to the chips. Saying + 'NO', which is the default when CONFIG_MTD_CFI_ADV_OPTIONS isn't + enabled, means that the CPU will not do any swapping; the chips + are expected to be wired to the CPU in 'host-endian' form. + Specific arrangements are possible with the BIG_ENDIAN_BYTE and + LITTLE_ENDIAN_BYTE, if the bytes are reversed. + + If you have a LART, on which the data (and address) lines were + connected in a fashion which ensured that the nets were as short + as possible, resulting in a bit-shuffling which seems utterly + random to the untrained eye, you need the LART_ENDIAN_BYTE option. + + Yes, there really exists something sicker than PDP-endian :) + +CFI support for Intel/Sharp Extended Commands CONFIG_MTD_CFI_INTELEXT The Common Flash Interface defines a number of different command sets which a CFI-compliant chip may claim to implement. This code provides support for one of those command sets, used on Intel - Strataflash and other parts. + StrataFlash and other parts. + +CFI support for AMD/Fujitsu Standard Commands +CONFIG_MTD_CFI_AMDSTD + The Common Flash Interface defines a number of different command + sets which a CFI-compliant chip may claim to implement. This code + provides support for one of those command sets, used on chips + chips including the AMD Am29LV320. + +CFI support for Intel/Sharp Standard Commands +CONFIG_MTD_CFI_INTELSTD + The Common Flash Interface defines a number of different command + sets which a CFI-compliant chip may claim to implement. This code + provides support for one of those command sets. + +pre-CFI Sharp chip support +CONFIG_MTD_SHARP + This option enables support for flash chips using Sharp-compatible + commands, including some which are not CFI-compatible and hence + cannot be used with the CONFIG_MTD_CFI_INTELxxx options. + +AMD compatible flash chip support (non-CFI) +CONFIG_MTD_AMDSTD + This option enables support for flash chips using AMD-compatible + commands, including some which are not CFI-compatible and hence + cannot be used with the CONFIG_MTD_CFI_AMDSTD option. + + It also works on AMD compatible chips that do conform to CFI. + +Support for RAM chips in bus mapping +CONFIG_MTD_RAM + This option enables basic support for RAM chips accessed through + a bus mapping driver. + +Support for ROM chips in bus mapping +CONFIG_MTD_ROM + This option enables basic support for ROM chips accessed through + a bus mapping driver. + +CONFIG_MTD_JEDEC + Enable older older JEDEC flash interface devices for self programming + flash. It is commonly used in older AMD chips. It is only called + JEDEC because the JEDEC association (http://www.jedec.org/) + distributes the identification codes for the chips. WARNING!!!! This + code does not compile and is incomplete as are the specific JEDEC + devices drivers. + +CFI Flash device mapped on StrongARM SA11x0 +CONFIG_MTD_SA1100 + This enables access to the flash chips on most platforms based on the + SA1100 and SA1110, including the Assabet and the Compaq iPAQ. If you + have such a board, say 'Y'. + +CONFIG_MTD_SA1100_REDBOOT_PARTITIONS + Enabling this option will cause the kernel to look for a RedBoot + FIS (Flash Image System) table in the last erase block of the flash + chips detected. If you are using RedBoot on your SA11x0-based board + and want Linux to present 'partitions' matching the images which + RedBoot has listed, say 'Y'. Flash chip mapping in physical memory CONFIG_MTD_PHYSMAP @@ -10295,18 +10520,18 @@ Physical start location of flash chip mapping CONFIG_MTD_PHYSMAP_START This is the physical memory location at which the flash chips - are mapped on your particular target board. Refer to the + are mapped on your particular target board. Refer to the memory map which should hopefully be in the documentation for your board. Physical length of flash chip mapping CONFIG_MTD_PHYSMAP_LEN This is the total length of the mapping of the flash chips on - your particular board. If there is space, or aliases, in the + your particular board. If there is space, or aliases, in the physical memory map between the chips, this could be larger than the total amount of flash present. Refer to the memory map which should hopefully be in the documentation for your - board. + board. CONFIG_MTD_PHYSMAP_BUSWIDTH This is the total width of the data bus of the flash devices @@ -10314,14 +10539,12 @@ bits, you would set the bus width octect value to 4. This is used internally by the CFI drivers. -Flash chip mapping on Mixcom piggyback card -CONFIG_MTD_MIXMEM - This supports the paging arrangement for access to flash chips - on the MixCOM piggyback card, allowing the flash chip drivers - to get on with their job of driving the flash chips without - having to know about the paging. If you have one of these boards, - you probably want to enable this mapping driver. More info is at - (http://www.itc.hu/). +Flash chip mapping on Sun Microsystems boardsets +CONFIG_MTD_SUN_UFLASH + This provides a 'mapping' driver which supports the way in + which user-programmable flash chips are connected on various + Sun Microsystems boardsets. This driver will require CFI support + in the kernel, so if you did not enable CFI previously, do that now. Flash chip mapping on Nora CONFIG_MTD_NORA @@ -10332,13 +10555,6 @@ PNC-2000 is the name of Network Camera product from PHOTRON Ltd. in Japan. It uses CFI-compliant flash. -Flash chip mapping on Octagon 5066 SBC -CONFIG_MTD_OCTAGON - This provides a 'mapping' driver which supports the way in which - the flash chips are connected in the Octagon-5066 Single Board - Computer. More information on the board is available at - (http://www.octagonsystems.com/Products/5066/5066.html). - Flash chip mapping on RPXlite PPC board CONFIG_MTD_RPXLITE The RPXLite PowerPC board has CFI-compliant chips mapped in @@ -10347,6 +10563,89 @@ to communicate with the chips on the RPXLite board. More at (http://www.embeddedplanet.com/rpx_lite_specification_sheet.htm). +Flash chip mapping on AMD SC520 CDP board +CONFIG_MTD_SC520CDP + The SC520 CDP board has two banks of CFI-compliant chips and one + Dual-in-line JEDEC chip. This 'mapping' driver supports that + arrangement, implementing three MTD devices. + +Flash chip mapping on Arcom Control Systems' SBC-MediaGX +CONFIG_MTD_SBC_MEDIAGX + This provides a driver for the on-board flash of Arcom Control + Systems' SBC-MediaGX development board. By default the flash + is split into 3 partitions which are accessed as separate MTD + devices. This board utilizes Intel StrataFlash. More info at + (http://www.arcomcontrols.com/products/icp/pc104/processors/). + +Flash chip mapping on Arcom Control Systems' ELAN-104NC +CONFIG_MTD_ELAN_104NC + This provides a driver for the on-board flash of the Arcom Control + System's ELAN-104NC development board. By default the flash + is split into 3 partitions which are accessed as separate MTD + devices. This board utilizes Intel StrataFlash. More info at + (http://www.arcomcontrols.com/products/icp/pc104/processors/). + +Flash chip mapping on Compaq iPAQ/Bitsy +CONFIG_MTD_BITSY + This provides a driver for the on-board flash found in Compaq's + iPAQ Palm PC and their research prototype the Itsy. iPAQ info at + (http://www5.compaq.com/products/handhelds/pocketpc/) and the + Itsy (http://www.research.digital.com/wrl/projects/Itsy/index.html). + +Flash chip mapping on Compaq iPAQ/Bitsy +CONFIG_MTD_DC21285 + This provides a driver for the flash accessed using Intel's + 21285 bridge used with Intel's StrongARM processors. More info at + (http://developer.intel.com/design/bridge/quicklist/dsc-21285.htm). + +Flash chip mapping on ITE QED-4N-S01B, Globespan IVR or custom board +CONFIG_MTD_CSTM_MIPS_IXX + This provides a mapping driver for the Integrated Tecnology + Express, Inc (ITE) QED-4N-S01B eval board and the Globespan IVR Reference + Board. It provides the necessary addressing, length, buswidth, vpp code + and addition setup of the flash device for these boards. In addition, + this mapping driver can be used for other boards via setting of the + CONFIG_MTD_CSTM_MIPS_IXX_START/LEN/BUSWIDTH parameters. This mapping + will provide one mtd device using one partition. The start address can + be offset from the beginning of flash and the len can be less than the + total flash device size to allow a window into the flash. Both CFI and + JEDEC probes are called. + +Physical start location of flash mapping +CONFIG_MTD_CSTM_MIPS_IXX_START + This is the physical memory location that the MTD driver will + use for the flash chips on your particular target board. + Refer to the memory map which should hopefully be in the + documentation for your board. + +Physical length of flash mapping +CONFIG_MTD_CSTM_MIPS_IXX_LEN + This is the total length that the MTD driver will use for the + flash chips on your particular board. Refer to the memory + map which should hopefully be in the documentation for your + board. + +Physical bus width of flash mapping +CONFIG_MTD_CSTM_MIPS_IXX_BUSWIDTH + This is the total bus width of the mapping of the flash chips + on your particular board. + +Flash chip mapping on Mixcom piggyback card +CONFIG_MTD_MIXMEM + This supports the paging arrangement for access to flash chips + on the MixCOM piggyback card, allowing the flash chip drivers + to get on with their job of driving the flash chips without + having to know about the paging. If you have one of these boards, + you probably want to enable this mapping driver. More info is at + (http://www.itc.hu/). + +Flash chip mapping on Octagon 5066 SBC +CONFIG_MTD_OCTAGON + This provides a 'mapping' driver which supports the way in which + the flash chips are connected in the Octagon-5066 Single Board + Computer. More information on the board is available at + (http://www.octagonsystems.com/Products/5066/5066.html). + Flash chip mapping on Tempustech VMAX SBC301 CONFIG_MTD_VMAX This provides a 'mapping' driver which supports the way in which @@ -10354,57 +10653,168 @@ Board Computer. More information on the board is available at (http://www.tempustech.com/tt301.htm). -Direct chardevice access to MTD devices -CONFIG_MTD_CHAR - This provides a character device for each MTD device present in - the system, allowing the user to read and write directly to the - memory chips, and also use ioctl() to obtain information about - the device, or to erase parts of it. +Support for NAND flash devices +CONFIG_MTD_NAND + This enables support for accessing all type of NAND flash + devices. + +Support for software ECC algorithm +CONFIG_MTD_NAND_ECC + This enables software-based ECC for use with NAND flash chips. It + can detect and correct 1 bit errors per 256 byte blocks. This + should be used to increase the reliability of the data stored and + read on the device. + +Support for verify read after write +CONFIG_MTD_NAND_VERIFY_WRITE + This adds an extra check when data is written to the flash. The + NAND flash device internally checks only bits transitioning + from 1 to 0. There is a rare possibility that even though the + device thinks the write was successful, a bit could have been + flipped accidentaly due to device wear, gamma rays, whatever. + Enable this if you are really paranoid. -Pseudo-blockdevice access to MTD devices -CONFIG_MTD_BLOCK - Although flash chips have an erase size too large to useful as - block devices, it is possible to use MTD devices which are based - on RAM chips in this manner. This blockdevice user of MTD devices - performs that function. At the moment, it is also required for - the Journalling Flash File System to obtain a handle on the MTD - device when it's mounted - although the JFFS doesn't actually use - any of the functions of the mtdblock device. +Support for the SPIA board +CONFIG_MTD_NAND_SPIA + If you had to ask, you don't have one. Say 'N'. - Later, it may be extended to perform read/erase/modify/write cycles - on flash chips to emulate a smaller block size. Needless to say, - this is very unsafe, but could be useful for file systems which are - almost never written to. +M-Systems Disk-On-Chip 1000 support +CONFIG_MTD_DOC1000 + This provides an MTD device driver for the M-Systems DiskOnChip + 1000 devices, which are obsolete so you probably want to say 'N'. -FTL (Flash Translation Layer) support -CONFIG_FTL - This provides support for the original Flash Translation Layer which - is part of the PCMCIA specification. It uses a kind of pseudo- - file system on a flash device to emulate a block device with 512-byte - sectors, on top of which you put a 'normal' file system. You may find - that the algorithms used in this code are patented unless you live - in the Free World where software patents aren't legal - in the USA - you are only permitted to use this on PCMCIA hardware, although - under the terms of the GPL you're obviously permitted to copy, - modify and distribute the code as you wish. Just not use it. +M-Systems Disk-On-Chip 2000 and Millennium support +CONFIG_MTD_DOC2000 + This provides an MTD device driver for the M-Systems DiskOnChip + 2000 and Millennium devices. Originally designed for the DiskOnChip + 2000, it also now includes support for the DiskOnChip Millennium. + If you have problems with this driver and the DiskOnChip Millennium, + you may wish to try the alternative Millennium driver below. To use + the alternative driver, you will need to undefine DOC_SINGLE_DRIVER + in the drivers/mtd/devices/docprobe.c source code. -NFTL (NAND Flash Translation Layer) support -CONFIG_NFTL - This provides support for the NAND Flash Translation Layer which is - used on M-Systems' DiskOnChip devices. It uses a kind of pseudo- - file system on a flash device to emulate a block device with 512-byte - sectors, on top of which you put a 'normal' file system. You may find - that the algorithms used in this code are patented unless you live - in the Free World where software patents aren't legal - in the USA - you are only permitted to use this on DiskOnChip hardware, although - under the terms of the GPL you're obviously permitted to copy, - modify and distribute the code as you wish. Just not use it. + If you use this device, you probably also want to enable the NFTL + 'NAND Flash Translation Layer' option below, which is used to emulate + a block device by using a kind of filesystem on the flash chips. -Write support for NFTL (EXPERIMENTAL) -CONFIG_NFTL_RW - If you're lucky, this will actually work. Don't whine if it doesn't. - Contact (dwmw2@infradead.org) if you want to help to make it more - reliable. +Alternative Disk-On-Chip Millennium support +CONFIG_MTD_DOC2001 + This provides an alternative MTD device driver for the M-Systems + DiskOnChip Millennium devices. Use this if you have problems with + the combined DiskOnChip 2000 and Millennium driver above. To get + the DiskOnChip probe code to load and use this driver instead of + the other one, you will need to undefine DOC_SINGLE_DRIVER near + the beginning of drivers/mtd/devices/docprobe.c + + If you use this device, you probably also want to enable the NFTL + 'NAND Flash Translation Layer' option below, which is used to emulate + a block device by using a kind of filesystem on the flash chips. + +Probe for DiskOnChip devices +CONFIG_MTD_DOCPROBE + This isn't a real config option, it's derived. + +Advanced detection options for DiskOnChip +CONFIG_MTD_DOCPROBE_ADVANCED + This option allows you to specify nonstandard address at which to + probe for a DiskOnChip, or to change the detection options. You're + unlikely to need any of this unless you're using LinuxBIOS. Say 'N'. + +Probe for 0x55 0xAA BIOS Extension Signature. +CONFIG_MTD_DOCPROBE_55AA + Check for the 0x55 0xAA signature of a DiskOnChip, and do not continue + with probing if it is absent. The signature will always be present for + a DiskOnChip 2000 or a normal DiskOnChip Millennium. Only if you have + overwritten the first block of a DiskOnChip Millennium will it be + absent. Enable this option if you are using LinuxBIOS or if you need + to recover a DiskOnChip Millennium on which you have managed to wipe + the first block. + +Physical address of DiskOnChip +CONFIG_MTD_DOCPROBE_ADDRESS + By default, the probe for DiskOnChip devices will look for a DiskOnChip + at every multiple of 0x2000 between 0xC8000 and 0xEE000. This option + allows you to specify a single address at which to probe for the device, + which is useful if you have other devices in that range which get upset + when they're probed. + + (Note that on PowerPC, the normal probe will only check at 0xE4000000.) + + Normally, you should leave this set to zero, to allow the probe at the + normal addresses. + +Probe high addresses +CONFIG_MTD_DOCPROBE_HIGH + By default, the probe for DiskOnChip devices will look for a DiskOnChip + at every multiple of 0x2000 between 0xC8000 and 0xEE000. This option + changes to make it probe between 0xFFFC8000 and 0xFFFEE000. Unless + you're using LinuxBIOS, this is unlikely to be useful to you. Say 'N'. + +Ramix PMC551 PCI Mezzanine ram card support +CONFIG_MTD_PMC551 + This provides a MTD device driver for the Ramix PMC551 RAM PCI card + from Ramix Inc. (http://www.ramix.com/products/memory/pmc551.html). + These devices come in memory configurations from 32M - 1G. If you + have one, you probably want to enable this. + + If this driver is compiled as a module you get the ability to select the + size of the aperture window pointing into the devices memory. What this + means is that if you have a 1G card, normally the kernel will use a 1G + memory map as it's view of the device. As a module, you can select a + 1M window into the memory and the driver will "slide" the window around + the PMC551's memory. This was particularly useful on the 2.2 kernels + on PPC architectures as there was limited kernel space to deal with. + +PMC551 256M DRAM Bugfix +CONFIG_MTD_PMC551_BUGFIX + Some of Ramix's PMC551 boards with 256M configurations have invalid column + and row mux values. This option will fix them, but will break other memory + configurations. If unsure say N. + +PMC551 Debugging +CONFIG_MTD_PMC551_DEBUG + This option makes the PMC551 more verbose during it's operation and is only + really usefull if you are developing on this driver or suspect a possible + hardware or driver bug. If unsure say N. + +Use extra onboard system memory as MTD device +CONFIG_MTD_SLRAM + If your CPU cannot cache all of the physical memory in your machine, + you can still use it for storage or swap by using this driver to + present it to the system as a Memory Technology Device. + +Debugging RAM test driver +CONFIG_MTD_MTDRAM + This enables a test MTD device driver which uses vmalloc() to + provide storage. You probably want to say 'N' unless you're + testing stuff. + +MTDRAM erase block size in KiB +CONFIG_MTDRAM_ERASE_SIZE + This allows you to configure the size of the erase blocks in the + device emulated by the MTDRAM driver. If the MTDRAM driver is built + as a module, it is also possible to specify this as a parameter when + loading the module. + +MTDRAM device size in KiB +CONFIG_MTDRAM_TOTAL_SIZE + This allows you to configure the total size of the MTD device + emulated by the MTDRAM driver. If the MTDRAM driver is built + as a module, it is also possible to specify this as a parameter when + loading the module. + +SRAM absolute position +CONFIG_MTDRAM_ABS_POS + If you have system RAM accessible by the CPU but not used by Linux + in normal operation, you can give the physical address at which the + available RAM starts, and the MTDRAM driver will use it instead of + allocating space from Linux's available memory. Otherwise, leave + this set to zero. Most people will want to leave this as zero. + +Flash chip mapping on the Flaga Digital Module +CONFIG_MTD_CFI_FLAGADM + Mapping for the Flaga digital module. If you don´t have one, ignore this + setting. Support for USB CONFIG_USB @@ -10709,9 +11119,10 @@ USB Handspring Visor Driver CONFIG_USB_SERIAL_VISOR - Say Y here if you want to connect to your HandSpring Visor through - its USB docking station. See http://usbvisor.sourceforge.net for - more information on using this driver. + Say Y here if you want to connect to your HandSpring Visor, Palm m500 + or m505 through its USB docking station. + See http://usbvisor.sourceforge.net for more information on using this + driver. This code is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -10841,6 +11252,29 @@ The module will be called mct_u232.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. +USB Prolific 2303 Single Port Serial Driver +CONFIG_USB_SERIAL_PL2303 + Say Y here if you want to use the PL2303 USB Serial single port + adapter from Prolific. + + This code 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 pl2303.o. If you want to compile it as + a module, say M here and read Documentation/modules.txt. + +USB REINER SCT cyberJack pinpad/e-com chipcard reader +CONFIG_USB_SERIAL_CYBERJACK + Say Y here if you want to use a cyberJack pinpad/e-com USB chipcard + reader. This is an interface to ISO 7816 compatible contactbased + chipcards, e.g. GSM SIMs. + + This code 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 cyberjack.o. If you want to compile it as + a module, say M here and read Documentation/modules.txt. + + If unsure, say N. + USB Edgeport Serial Driver CONFIG_USB_SERIAL_EDGEPORT Say Y here if you want to use any of the following devices from @@ -10946,6 +11380,22 @@ module, say M here and read Documentation/modules.txt. +USB SE401 Camera support +CONFIG_USB_SE401 + Say Y here if you want to connect this type of camera to your + computer's USB port. See Documentation/usb/se401.txt for more + information and for a list of supported cameras. + + This driver uses the Video For Linux API. You must say Y or M to + "Video For Linux" (under Multimedia Devices) to use this driver. + Information on this API and pointers to "v4l" programs may be found + on the WWW at http://roadrunner.swansea.uk.linux.org/v4l.shtml . + + This code 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 se401.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. + USB ADMtek Pegasus-based ethernet device support CONFIG_USB_PEGASUS Say Y if you want to use your USB ethernet device. Supported @@ -10972,6 +11422,20 @@ The module will be called pegasus.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. +USB CATC NetMate-based Ethernet device support +CONFIG_USB_CATC + Say Y if you want to use one of the following 10Mbps USB Ethernet + device based on the EL1210A chip. Supported devices are: + Belkin F5U111 + CATC NetMate + CATC NetMate II + smartBridges smartNIC + + This code 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 catc.o. If you want to compile it as a + module, say M here and read . + USB Kodak DC-2xx Camera support CONFIG_USB_DC2XX Say Y here if you want to connect this type of still camera to @@ -11128,12 +11592,13 @@ Microtek USB scanner support CONFIG_USB_MICROTEK - Say Y here if you want support for the Microtek X6USB and possibly - some other scanners by that vendor. The scanner will appear as a - scsi generic device to the rest of the system. - A patched version of SANE is necessary to use the - scanner. It's available at - http://fachschaft.cup.uni-muenchen.de/~neukum/scanner.html + Say Y here if you want support for the Microtek X6USB and + possibly the Phantom 336CX, Phantom C6 and ScanMaker V6U(S)L. + Support for anything but the X6 is experimetal. + Please report failures and successes. + The scanner will appear as a scsi generic device to the rest + of the system. Scsi support is required for this driver to compile + and work. SANE 1.0.4 or newer is needed to make use of your scanner. This driver can be compiled as a module. USB Bluetooth support @@ -11724,12 +12189,13 @@ If unsure, say N. -System V and Coherent file system support (read only) +System V, Version 7, Xenix and Coherent filesystem support (read only) CONFIG_SYSV_FS SCO, Xenix and Coherent are commercial Unix systems for Intel - machines. Saying Y here would allow you to read from their floppies - and hard disk partitions. If you also want to write to these media, - say Y to "SYSV file system write support" below. + machines, and Version 7 was used on the DEC PDP-11. Saying Y + here would allow you to read from their floppies and hard disk + partitions. If you also want to write to these media, say Y to + "SYSV file system write support" below. If you have floppies or hard disk partitions like that, it is likely that they contain binaries from those other Unix systems; in order @@ -11738,7 +12204,9 @@ Xenix, Wyse, UnixWare, Dell Unix and System V programs under Linux and is often needed to run commercial software that's only available for those systems. It's available via FTP (user: anonymous) from - ftp://tsx-11.mit.edu/pub/linux/BETA ). + ftp://tsx-11.mit.edu/pub/linux/BETA ). NOTE: that will work only for + binaries from Intel-based systems; PDP ones will have to wait until + somebody ports Linux to -11 ;-) If you only intend to mount files from some other Unix over the network using NFS, you don't need the System V file system support @@ -13241,8 +13709,8 @@ Apple Desktop Bus support CONFIG_ADB Apple Desktop Bus (ADB) support is for support of devices which - are connected to the to an ADB port. ADB devices tend to have - 4 pins. If you have an Apple Macintosh prior to the iMac, or a + are connected to an ADB port. ADB devices tend to have 4 pins. + If you have an Apple Macintosh prior to the iMac, or a "Blue and White G3", you probably want to say Y here. Otherwise say N. @@ -13730,7 +14198,7 @@ will issue the hlt instruction if nothing is to be done, thereby sending the processor to sleep and saving power. -ACPI Support +ACPI support CONFIG_ACPI ACPI/OSPM support for Linux is currently under development. As such, this support is preliminary and EXPERIMENTAL. Configuring ACPI support @@ -13760,6 +14228,57 @@ The ACPI mailing list may also be of interest: http://phobos.fs.tum.de/acpi/index.html +ACPI Debug Statements +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. + +ACPI Bus Manager +CONFIG_ACPI_BUSMGR + The ACPI Bus Manager enumerates devices in the ACPI namespace, and + handles PnP messages. All ACPI devices use its services, so using them + requires saying Y here. + +ACPI System Driver +CONFIG_ACPI_SYS + This driver will enable your system to shut down using ACPI, and dump + your ACPI DSDT table using /proc/acpi/dsdt. + +ACPI Processor Driver +CONFIG_ACPI_CPU + This driver installs ACPI as the idle handler for Linux, and uses ACPI + C2 and C3 processor states to save power, on systems that support it. + +ACPI Button +CONFIG_ACPI_BUTTON + This driver registers for events based on buttons, such as the power, + sleep, and lid switch. In the future, a daemon will read + /proc/acpi/event and perform user-defined actions such as shutting + down the system. Until then, you can cat it, and see output when + a button is pressed. + +ACPI AC Adapter +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. + +ACPI Embedded Controller +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. + +ACPI Control Method Battery +CONFIG_ACPI_CMBATT + This driver adds support for battery information through + /proc/acpi/battery. If you have a laptop with a battery, say Y. + +ACPI Thermal +CONFIG_ACPI_THERMAL + This driver handles overheating conditions on laptops. It is HIGHLY + recommended, as your laptop CPU may be damaged without it. + Advanced Power Management BIOS support CONFIG_APM APM is a BIOS specification for saving power using several different @@ -14883,17 +15402,20 @@ If unsure, say Y. -ACI mixer (miroPCM12/PCM20) +ACI mixer (miroSOUND PCM1-pro/PCM12/PCM20 radio) CONFIG_SOUND_ACI_MIXER ACI (Audio Command Interface) is a protocol used to communicate with - the microcontroller on some sound cards produced by miro, e.g. the - miroSOUND PCM12 and PCM20. The main function of the ACI is to - control the mixer and to get a product identification. - - This Voxware ACI driver currently only supports the ACI functions on - the miroSOUND PCM12 and PCM20 cards. On the PCM20, ACI also controls - the radio tuner. This is supported in the video4linux - radio-miropcm20 driver. + the microcontroller on some sound cards produced by miro and Cardinal + Technologies. The main function of the ACI is to control the mixer + and to get a product identification. + + This Voxware ACI driver currently supports the ACI functions on the + miroSOUND PCM1-pro, PCM12 and PCM20 radio. On the PCM20 radio, ACI + also controls the radio tuner. This is supported in the video4linux + miropcm20 driver (say M or Y here and go back to "Multimedia devices" + -> "Radio Adapters"). + + This driver is also available as a module and will be called aci.o. SB32/AWE support CONFIG_SOUND_AWE32_SYNTH @@ -15618,6 +16140,20 @@ isdn4k-utils package. Please read the file Documentation/isdn/README.act2000 for more information. +Auvertech TurboPAM support +CONFIG_ISDN_DRV_TPAM + This enables support for the Auvertech TurboPAM ISDN-card. + For running this card, additional firmware is necessary, which has + to be downloaded into the card using a utility which is distributed + separately from the Auvertech's web site: http://www.auvertech.fr. + + Please redirect all support questions to support@auvertech.fr. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called tpam.o. + Hypercope HYSDN cards (Champ, Ergo, Metro) support (module) CONFIG_HYSDN Say Y here if you have one of Hypercope's active PCI ISDN cards @@ -16711,11 +17247,11 @@ say M here and read Documentation/modules.txt. The module will be called i2c-parport.o. -Miro PCM20 Radio +miroSOUND PCM20 radio CONFIG_RADIO_MIROPCM20 - Choose Y here if you have this FM radio card. You also need to say Y - to "ACI mixer (miroPCM12/PCM20)" (in "additional low level sound - drivers") for this to work. + Choose Y here if you have this sound card. You also need to say Y + to "ACI mixer (miroSOUND PCM1-pro/PCM12/PCM20 radio)" (in "Sound") + for this to work. In order to control your radio card, you will need to use programs that are compatible with the Video for Linux API. Information on @@ -16725,7 +17261,21 @@ If you want to compile this driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt. The module will be - called radio-miropcm20.o + called miropcm20.o + +miroSOUND PCM20 radio RDS user interface (EXPERIMENTAL) +CONFIG_RADIO_MIROPCM20_RDS + Choose Y here if you want to see RDS/RBDS information like RadioText, + Programme Service name, Clock Time and date, Programme TYpe and + Traffic Announcement/Programme identification. You also need to say + Y to "miroSOUND PCM20 radio" and devfs! + + It's not possible to read the raw RDS packets from the device, so + the driver cant provide an V4L interface for this. But the + availability of RDS is reported over V4L by the basic driver already. + Here RDS can be read from files in /dev/v4l/rds. + + As module the driver will be called miropcm20-rds.o. GemTek Radio Card CONFIG_RADIO_GEMTEK diff -u --recursive --new-file v2.4.5/linux/Documentation/DocBook/Makefile linux/Documentation/DocBook/Makefile --- v2.4.5/linux/Documentation/DocBook/Makefile Mon May 7 12:14:56 2001 +++ linux/Documentation/DocBook/Makefile Mon Jul 2 13:56:40 2001 @@ -1,7 +1,7 @@ BOOKS := wanbook.sgml z8530book.sgml mcabook.sgml videobook.sgml \ kernel-api.sgml parportbook.sgml kernel-hacking.sgml \ kernel-locking.sgml via-audio.sgml mousedrivers.sgml sis900.sgml \ - deviceiobook.sgml + deviceiobook.sgml procfs-guide.sgml PS := $(patsubst %.sgml, %.ps, $(BOOKS)) PDF := $(patsubst %.sgml, %.pdf, $(BOOKS)) @@ -9,6 +9,7 @@ IMG-parportbook := parport-share.fig parport-multi.fig parport-structure.fig EPS-parportbook := $(patsubst %.fig, %.eps, $(IMG-parportbook)) JPG-parportbook := $(patsubst %.fig, %.jpeg, $(IMG-parportbook)) +C-procfs-example = procfs_example.sgml books: $(BOOKS) @@ -28,6 +29,15 @@ %.jpeg: %.fig -fig2dev -Ljpeg $< $@ +%.sgml: %.c + echo "" > $@ + expand --tabs=8 < $< | \ + sed -e "s/&/\\&/g" \ + -e "s//\\>/g" >> $@ + echo "" >> $@ + + $(TOPDIR)/scripts/docproc: $(MAKE) -C $(TOPDIR)/scripts docproc @@ -67,6 +77,9 @@ $(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/media/video/videodev.c \ videobook.sgml +procfs-guide.sgml: procfs-guide.tmpl procfs_example.sgml + $(TOPDIR)/scripts/docgen < procfs-guide.tmpl >$@ + APISOURCES := $(TOPDIR)/drivers/media/video/videodev.c \ $(TOPDIR)/arch/i386/kernel/irq.c \ $(TOPDIR)/arch/i386/kernel/mca.c \ @@ -128,6 +141,7 @@ -$(RM) $(BOOKS) -$(RM) $(DVI) $(AUX) $(TEX) $(LOG) $(OUT) -$(RM) $(JPG-parportbook) $(EPS-parportbook) + -$(RM) $(C-procfs-example) mrproper: clean -$(RM) $(PS) $(PDF) diff -u --recursive --new-file v2.4.5/linux/Documentation/DocBook/procfs-guide.tmpl linux/Documentation/DocBook/procfs-guide.tmpl --- v2.4.5/linux/Documentation/DocBook/procfs-guide.tmpl Wed Dec 31 16:00:00 1969 +++ linux/Documentation/DocBook/procfs-guide.tmpl Mon Jul 2 13:56:40 2001 @@ -0,0 +1,625 @@ + + +]> + + + + Linux Kernel Procfs Guide + + + + Erik + (J.A.K.) + Mouw + + Delft University of Technology + Faculty of Information Technology and Systems +
+ J.A.K.Mouw@its.tudelft.nl + PO BOX 5031 + 2600 GA + Delft + The Netherlands +
+
+
+
+ + + + 1.0  + May 30, 2001 + Initial revision posted to linux-kernel + + + 1.1  + June 3, 2001 + Revised after comments from linux-kernel + + + + + 2001 + Erik Mouw + + + + + + This documentation 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 documentation 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 + + + + For more details see the file COPYING in the source + distribution of Linux. + + +
+ + + + + + + + + + + + Preface + + + This guide describes the use of the procfs file system from + within the Linux kernel. The idea to write this guide came up on + the #kernelnewbies IRC channel (see http://www.kernelnewbies.org/), + when Jeff Garzik explained the use of procfs and forwarded me a + message Alexander Viro wrote to the linux-kernel mailing list. I + agreed to write it up nicely, so here it is. + + + + I'd like to thank Jeff Garzik + jgarzik@mandrakesoft.com and Alexander Viro + viro@math.psu.edu for their input, Tim Waugh + twaugh@redhat.com for his Selfdocbook, + and Marc Joosen marcj@historia.et.tudelft.nl for + proofreading. + + + + This documentation was written while working on the LART + computing board (http://www.lart.tudelft.nl/), + which is sponsored by the Mobile Multi-media Communications + (http://www.mmc.tudelft.nl/) + and Ubiquitous Communications (http://www.ubicom.tudelft.nl/) + projects. + + + + Erik + + + + + + + + Introduction + + + The /proc file system + (procfs) is a special file system in the linux kernel. It's a + virtual file system: it is not associated with a block device + but exists only in memory. The files in the procfs are there to + allow userland programs access to certain information from the + kernel (like process information in /proc/[0-9]+/), but also for debug + purposes (like /proc/ksyms). + + + + This guide describes the use of the procfs file system from + within the Linux kernel. It starts by introducing all relevant + functions to manage the files within the file system. After that + it shows how to communicate with userland, and some tips and + tricks will be pointed out. Finally a complete example will be + shown. + + + + Note that the files in /proc/sys are sysctl files: they + don't belong to procfs and are governed by a completely + different API described in the Kernel API book. + + + + + + + + Managing procfs entries + + + This chapter describes the functions that various kernel + components use to populate the procfs with files, symlinks, + device nodes, and directories. + + + + A minor note before we start: if you want to use any of the + procfs functions, be sure to include the correct header file! + This should be one of the first lines in your code: + + + +#include <linux/proc_fs.h> + + + + + + + Creating a regular file + + + + struct proc_dir_entry* create_proc_entry + const char* name + mode_t mode + struct proc_dir_entry* parent + + + + + This function creates a regular file with the name + name, file mode + mode in the directory + parent. To create a file in the root of + the procfs, use NULL as + parent parameter. When successful, the + function will return a pointer to the freshly created + struct proc_dir_entry; otherwise it + will return NULL. describes how to do something useful with + regular files. + + + + Note that it is specifically supported that you can pass a + path that spans multiple directories. For example + create_proc_entry("drivers/via0/info") + will create the via0 + directory if necessary, with standard + 0755 permissions. + + + + If you only want to be able to read the file, the function + create_proc_read_entry described in may be used to create and initialise + the procfs entry in one single call. + + + + + + + + Creating a symlink + + + + struct proc_dir_entry* + proc_symlink const + char* name + struct proc_dir_entry* + parent const + char* dest + + + + + This creates a symlink in the procfs directory + parent that points from + name to + dest. This translates in userland to + ln -s dest + name. + + + + + + + + Creating a device + + + + struct proc_dir_entry* proc_mknod + const char* name + mode_t mode + struct proc_dir_entry* parent + kdev_t rdev + + + + + Creates a device file name with mode + mode in the procfs directory + parent. The device file will work on + the device rdev, which can be generated + by using the MKDEV macro from + linux/kdev_t.h. The + mode parameter + must contain S_IFBLK + or S_IFCHR to create a device + node. Compare with userland mknod + --mode=mode + name rdev. + + + + + + + + Creating a directory + + + + struct proc_dir_entry* proc_mkdir + const char* name + struct proc_dir_entry* parent + + + + + Create a directory name in the procfs + directory parent. + + + + + + + + Removing an entry + + + + void remove_proc_entry + const char* name + struct proc_dir_entry* parent + + + + + Removes the entry name in the directory + parent from the procfs. Entries are + removed by their name, not by the + struct proc_dir_entry returned by the + various create functions. Note that this function doesn't + recursively remove entries. + + + + Be sure to free the data entry from + the struct proc_dir_entry before + remove_proc_entry is called (that is: if + there was some data allocated, of + course). See for more information + on using the data entry. + + + + + + + + + Communicating with userland + + + Instead of reading (or writing) information directly from + kernel memory, procfs works with call back + functions for files: functions that are called when + a specific file is being read or written. Such functions have + to be initialised after the procfs file is created by setting + the read_proc and/or + write_proc fields in the + struct proc_dir_entry* that the + function create_proc_entry returned: + + + +struct proc_dir_entry* entry; + +entry->read_proc = read_proc_foo; +entry->write_proc = write_proc_foo; + + + + If you only want to use a the + read_proc, the function + create_proc_read_entry described in may be used to create and initialise the + procfs entry in one single call. + + + + + + Reading data + + + The read function is a call back function that allows userland + processes to read data from the kernel. The read function + should have the following format: + + + + + int read_func + char* page + char** start + off_t off + int count + int* eof + void* data + + + + + The read function should write its information into the + page. For proper use, the function + should start writing at an offset of + off in page and + write at most count bytes, but because + most read functions are quite simple and only return a small + amount of information, these two parameters are usually + ignored (it breaks pagers like more and + less, but cat still + works). + + + + If the off and + count parameters are properly used, + eof should be used to signal that the + end of the file has been reached by writing + 1 to the memory location + eof points to. + + + + The parameter start doesn't seem to be + used anywhere in the kernel. The data + parameter can be used to create a single call back function for + several files, see . + + + + The read_func function must return the + number of bytes written into the page. + + + + shows how to use a read call back + function. + + + + + + + + Writing data + + + The write call back function allows a userland process to write + data to the kernel, so it has some kind of control over the + kernel. The write function should have the following format: + + + + + int write_func + struct file* file + const char* buffer + unsigned long count + void* data + + + + + The write function should read count + bytes at maximum from the buffer. Note + that the buffer doesn't live in the + kernel's memory space, so it should first be copied to kernel + space with copy_from_user. The + file parameter is usually + ignored. shows how to use the + data parameter. + + + + Again, shows how to use this call back + function. + + + + + + + + A single call back for many files + + + When a large number of almost identical files is used, it's + quite inconvenient to use a separate call back function for + each file. A better approach is to have a single call back + function that distinguishes between the files by using the + data field in struct + proc_dir_entry. First of all, the + data field has to be initialised: + + + +struct proc_dir_entry* entry; +struct my_file_data *file_data; + +file_data = kmalloc(sizeof(struct my_file_data), GFP_KERNEL); +entry->data = file_data; + + + + The data field is a void + *, so it can be initialised with anything. + + + + Now that the data field is set, the + read_proc and + write_proc can use it to distinguish + between files because they get it passed into their + data parameter: + + + +int foo_read_func(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len; + + if(data == file_data) { + /* special case for this file */ + } else { + /* normal processing */ + } + + return len; +} + + + + Be sure to free the data data field + when removing the procfs entry. + + + + + + + + + Tips and tricks + + + + + + Convenience functions + + + + struct proc_dir_entry* create_proc_read_entry + const char* name + mode_t mode + struct proc_dir_entry* parent + read_proc_t* read_proc + void* data + + + + + This function creates a regular file in exactly the same way + as create_proc_entry from does, but also allows to set the read + function read_proc in one call. This + function can set the data as well, like + explained in . + + + + + + + Modules + + + If procfs is being used from within a module, be sure to set + the owner field in the + struct proc_dir_entry to + THIS_MODULE. + + + +struct proc_dir_entry* entry; + +entry->owner = THIS_MODULE; + + + + + + + + Mode and ownership + + + Sometimes it is useful to change the mode and/or ownership of + a procfs entry. Here is an example that shows how to achieve + that: + + + +struct proc_dir_entry* entry; + +entry->mode = S_IWUSR |S_IRUSR | S_IRGRP | S_IROTH; +entry->uid = 0; +entry->gid = 100; + + + + + + + + + + Example + + + +&procfsexample; + + +
diff -u --recursive --new-file v2.4.5/linux/Documentation/DocBook/procfs_example.c linux/Documentation/DocBook/procfs_example.c --- v2.4.5/linux/Documentation/DocBook/procfs_example.c Wed Dec 31 16:00:00 1969 +++ linux/Documentation/DocBook/procfs_example.c Mon Jul 2 13:56:40 2001 @@ -0,0 +1,249 @@ +/* + * procfs_example.c: an example proc interface + * + * Copyright (C) 2001, Erik Mouw (J.A.K.Mouw@its.tudelft.nl) + * + * This file accompanies the procfs-guide in the Linux kernel + * source. Its main use is to demonstrate the concepts and + * functions described in the guide. + * + * This software has been developed while working on the LART + * computing board (http://www.lart.tudelft.nl/), which is + * sponsored by the Mobile Multi-media Communications + * (http://www.mmc.tudelft.nl/) and Ubiquitous Communications + * (http://www.ubicom.tudelft.nl/) projects. + * + * The author can be reached at: + * + * Erik Mouw + * Information and Communication Theory Group + * Faculty of Information Technology and Systems + * Delft University of Technology + * P.O. Box 5031 + * 2600 GA Delft + * The Netherlands + * + * + * 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 + + +#define MODULE_VERSION "1.0" +#define MODULE_NAME "procfs_example" + +#define FOOBAR_LEN 8 + +struct fb_data_t { + char name[FOOBAR_LEN + 1]; + char value[FOOBAR_LEN + 1]; +}; + + +static struct proc_dir_entry *example_dir, *foo_file, + *bar_file, *jiffies_file, *tty_device, *symlink; + + +struct fb_data_t foo_data, bar_data; + + +static int proc_read_jiffies(char *page, char **start, + off_t off, int count, + int *eof, void *data) +{ + int len; + + MOD_INC_USE_COUNT; + + len = sprintf(page, "jiffies = %ld\n", + jiffies); + + MOD_DEC_USE_COUNT; + + return len; +} + + +static int proc_read_foobar(char *page, char **start, + off_t off, int count, + int *eof, void *data) +{ + int len; + struct fb_data_t *fb_data = (struct fb_data_t *)data; + + MOD_INC_USE_COUNT; + + len = sprintf(page, "%s = '%s'\n", + fb_data->name, fb_data->value); + + MOD_DEC_USE_COUNT; + + return len; +} + + +static int proc_write_foobar(struct file *file, + const char *buffer, + unsigned long count, + void *data) +{ + int len; + struct fb_data_t *fb_data = (struct fb_data_t *)data; + + MOD_INC_USE_COUNT; + + if(count > FOOBAR_LEN) + len = FOOBAR_LEN; + else + len = count; + + if(copy_from_user(fb_data->value, buffer, len)) { + MOD_DEC_USE_COUNT; + return -EFAULT; + } + + fb_data->value[len] = '\0'; + + MOD_DEC_USE_COUNT; + + return len; +} + + +static int __init init_procfs_example(void) +{ + int rv = 0; + + /* create directory */ + example_dir = proc_mkdir(MODULE_NAME, NULL); + if(example_dir == NULL) { + rv = -ENOMEM; + goto out; + } + + example_dir->owner = THIS_MODULE; + + /* create jiffies using convenience function */ + jiffies_file = create_proc_read_entry("jiffies", + 0444, example_dir, + proc_read_jiffies, + NULL); + if(jiffies_file == NULL) { + rv = -ENOMEM; + goto no_jiffies; + } + + jiffies_file->owner = THIS_MODULE; + + /* create foo and bar files using same callback + * functions + */ + foo_file = create_proc_entry("foo", 0644, example_dir); + if(foo_file == NULL) { + rv = -ENOMEM; + goto no_foo; + } + + strcpy(foo_data.name, "foo"); + strcpy(foo_data.value, "foo"); + foo_file->data = &foo_data; + foo_file->read_proc = proc_read_foobar; + foo_file->write_proc = proc_write_foobar; + foo_file->owner = THIS_MODULE; + + bar_file = create_proc_entry("bar", 0644, example_dir); + if(bar_file == NULL) { + rv = -ENOMEM; + goto no_bar; + } + + strcpy(bar_data.name, "bar"); + strcpy(bar_data.value, "bar"); + bar_file->data = &bar_data; + bar_file->read_proc = proc_read_foobar; + bar_file->write_proc = proc_write_foobar; + bar_file->owner = THIS_MODULE; + + /* create tty device */ + tty_device = proc_mknod("tty", S_IFCHR | 0666, + example_dir, MKDEV(5, 0)); + if(tty_device == NULL) { + rv = -ENOMEM; + goto no_tty; + } + + tty_device->owner = THIS_MODULE; + + /* create symlink */ + symlink = proc_symlink("jiffies_too", example_dir, + "jiffies"); + if(symlink == NULL) { + rv = -ENOMEM; + goto no_symlink; + } + + symlink->owner = THIS_MODULE; + + /* everything OK */ + printk(KERN_INFO "%s %s initialised\n", + MODULE_NAME, MODULE_VERSION); + return 0; + +no_symlink: + remove_proc_entry("tty", example_dir); +no_tty: + remove_proc_entry("bar", example_dir); +no_bar: + remove_proc_entry("foo", example_dir); +no_foo: + remove_proc_entry("jiffies", example_dir); +no_jiffies: + remove_proc_entry(MODULE_NAME, NULL); +out: + return rv; +} + + +static void __exit cleanup_procfs_example(void) +{ + remove_proc_entry("jiffies_too", example_dir); + remove_proc_entry("tty", example_dir); + remove_proc_entry("bar", example_dir); + remove_proc_entry("foo", example_dir); + remove_proc_entry("jiffies", example_dir); + remove_proc_entry(MODULE_NAME, NULL); + + printk(KERN_INFO "%s %s removed\n", + MODULE_NAME, MODULE_VERSION); +} + + +module_init(init_procfs_example); +module_exit(cleanup_procfs_example); + +MODULE_AUTHOR("Erik Mouw"); +MODULE_DESCRIPTION("procfs examples"); + +EXPORT_NO_SYMBOLS; diff -u --recursive --new-file v2.4.5/linux/Documentation/fb/matroxfb.txt linux/Documentation/fb/matroxfb.txt --- v2.4.5/linux/Documentation/fb/matroxfb.txt Sat Nov 11 18:47:40 2000 +++ linux/Documentation/fb/matroxfb.txt Mon Jul 2 13:56:40 2001 @@ -173,9 +173,9 @@ mtrr - enables write combining on frame buffer. It speeds up video accesses much. It is default. You must have MTRR support enabled in kernel and your CPU must have MTRR (f.e. Pentium II have them). -sgram - tells to driver that you have G200 with SGRAM memory. It has no +sgram - tells to driver that you have Gxx0 with SGRAM memory. It has no effect without `init'. -sdram - tells to driver that you have G200 with SDRAM memory. +sdram - tells to driver that you have Gxx0 with SDRAM memory. It is a default. inv24 - change timings parameters for 24bpp modes on Millenium and Millenium II. Specify this if you see strange color shadows around @@ -279,7 +279,7 @@ + 24bpp does not support correctly XF-FBDev on big-endian architectures. + interlaced text mode is not supported; it looks like hardware limitation, but I'm not sure. - + G200 SGRAM/SDRAM is not autodetected. + + Gxx0 SGRAM/SDRAM is not autodetected. + maybe more... And following misfeatures: + SVGALib does not restore screen on exit. @@ -336,7 +336,7 @@ ACCEL, nofastfont 8x16 12x22 6x11 - Millennium I G200 Millennium I G200 Millennium I G200 + Millennium I G200 Millennium I G200 Millennium I G200 8bpp 7.79 7.24 13.55 7.78 30.00 21.01 16bpp 9.13 7.78 16.16 7.78 30.00 21.01 24bpp 14.17 10.72 18.69 10.24 34.99 21.01 @@ -344,7 +344,7 @@ ACCEL, fastfont 8x16 12x22 6x11 - Millennium I G200 Millennium I G200 Millennium I G200 + Millennium I G200 Millennium I G200 Millennium I G200 8bpp 8.41 6.01 6.54 4.37 16.00 10.51 16bpp 9.54 9.12 8.76 6.17 17.52 14.01 24bpp 15.00 12.36 11.67 10.00 22.01 18.32 @@ -355,6 +355,8 @@ Millennium I G200 TEXT 3.29 1.50 +* Yes, it is slower than Millennium I. + Dualhead G400 ============= @@ -376,7 +378,22 @@ + if you compiled it as module, you must insert i2c-matroxfb, matroxfb_maven and matroxfb_crtc2 into kernel. + +Dualhead G450 +============= +Driver supports dualhead G450 with some limitations: + + secondary head shares videomemory with primary head. It is not problem + if you have 32MB of videoram, but if you have only 16MB, you may have + to think twice before choosing videomode. + + due to hardware limitation, secondary head can use only 16 and 32bpp + videomodes. + + secondary head is not accelerated. + + secondary head always powerups in 640x480@60-32 videomode. You have to use + fbset to change this mode. + + TV output is not supported + + kernel is not fully multihead ready, so some things are impossible to do. + + if you compiled it as module, you must insert matroxfb_g450 and matroxfb_crtc2 + into kernel. -* Yes, it is slower than Millennium I. -- Petr Vandrovec diff -u --recursive --new-file v2.4.5/linux/Documentation/filesystems/00-INDEX linux/Documentation/filesystems/00-INDEX --- v2.4.5/linux/Documentation/filesystems/00-INDEX Thu Feb 8 16:32:44 2001 +++ linux/Documentation/filesystems/00-INDEX Wed Jun 20 11:10:27 2001 @@ -33,7 +33,7 @@ smbfs.txt - info on using filesystems with the SMB protocol (Windows 3.11 and NT) sysv-fs.txt - - info on the SystemV/Coherent filesystem. + - info on the SystemV/V7/Xenix/Coherent filesystem. udf.txt - info and mount options for the UDF filesystem. ufs.txt diff -u --recursive --new-file v2.4.5/linux/Documentation/filesystems/devfs/ChangeLog linux/Documentation/filesystems/devfs/ChangeLog --- v2.4.5/linux/Documentation/filesystems/devfs/ChangeLog Fri Apr 6 10:42:48 2001 +++ linux/Documentation/filesystems/devfs/ChangeLog Wed Jun 20 10:54:31 2001 @@ -1613,3 +1613,51 @@ - Updated README from master HTML file - Ported to kernel 2.4.0-test3-pre4 (which had devfs-patch-v174) +=============================================================================== +Changes for patch v177 + +- Updated README from master HTML file + +- Documentation cleanups + +- Ensure terminates string for root entry + Thanks to Tim Jansen + +- Exported to modules + +- Make send events to devfsd + +- Cleaned up option processing in + +- Fixed bugs in handling symlinks: could leak or cause Oops + +- Cleaned up directory handling by separating fops + Thanks to Alexander Viro +=============================================================================== +Changes for patch v178 + +- Fixed handling of inverted options in +=============================================================================== +Changes for patch v179 + +- Adjusted to account for fix +=============================================================================== +Changes for patch v180 + +- Fixed !CONFIG_DEVFS_FS stub declaration of +=============================================================================== +Changes for patch v181 + +- Answered question posed by Al Viro and removed his comments from + +- Moved setting of registered flag after other fields are changed + +- Fixed race between and + +- Global VFS changes added bogus BKL to devfsd_close(): removed + +- Widened locking in and + +- Replaced stack usage with kmalloc + +- Simplified locking in and fixed memory leak diff -u --recursive --new-file v2.4.5/linux/Documentation/filesystems/devfs/README linux/Documentation/filesystems/devfs/README --- v2.4.5/linux/Documentation/filesystems/devfs/README Wed Nov 29 10:11:38 2000 +++ linux/Documentation/filesystems/devfs/README Tue Jun 12 10:57:46 2001 @@ -3,7 +3,7 @@ Linux Devfs (Device File System) FAQ Richard Gooch -3-JUL-2000 +26-APR-2001 ----------------------------------------------------------------------------- @@ -18,7 +18,7 @@ http://www.atnf.csiro.au/~rgooch/linux/ -NEWFLASH: The official 2.3.46 kernel has +NEWSFLASH: The official 2.3.46 kernel has included the devfs patch. Future patches will be released which build on this. These patches are rolled into Linus' tree from time to time. @@ -54,6 +54,7 @@ Other Issues Kernel Naming Scheme Devfsd Naming Scheme +Old Compatibility Names SCSI Host Probing Issues @@ -99,6 +100,7 @@ can easily mount the root filesystem by referring to an entry in the devfs namespace. + The cost of devfs is a small increase in kernel code size and memory usage. About 7 pages of code (some of that in __init sections) and 72 bytes for each entry in the namespace. A modest system has only a @@ -157,6 +159,7 @@ of nodes. This means that changes in the kernel must be reflected by changes in the MAKEDEV programme, or else the system administrator creates device nodes by hand. + The basic problem is that there are two separate databases of major and minor numbers. One is in the kernel and one is in /dev (or in a MAKEDEV programme, if you want to look at it that way). This is @@ -192,6 +195,7 @@ 256 kBytes of /dev inodes, but you could argue that embedded systems would have hand-tuned /dev directories. I've had to do just that on my embedded systems, but I would rather just leave it to devfs. + Another issue is the time taken to lookup an inode when first referenced. Not only does this take time in scanning through a list in memory, but also the seek times to read the inodes off disc. @@ -212,7 +216,7 @@ likely be implemented in an ad-hoc fashion, as different drivers will provide their information in different ways. -Devfs is much cleaner, because it (natually) has a uniform mechanism +Devfs is much cleaner, because it (naturally) has a uniform mechanism to provide this information: the device nodes themselves! @@ -253,7 +257,7 @@ But why do that search at all if you don't have to? Once again, it seems pointless. -Note thate devfs doesn't use the major&minor system. For devfs +Note that devfs doesn't use the major&minor system. For devfs entries, the connection is done when you lookup the /dev entry. When devfs_register() is called, an internal table is appended which has the entry name and the file_operations. If the dentry cache doesn't @@ -274,9 +278,9 @@ /dev as a system administration tool Right now /dev contains a list of conceivable devices, most of which I -don't have. A devfs would only show those devices available on my -system. This means that listing /dev would be a handy way of checking -what devices were available. +don't have. Devfs only shows those devices available on my +system. This means that listing /dev is a handy way of checking what +devices are available. Major&minor size @@ -289,9 +293,9 @@ each device entry, which can be used to give an effective 32 bit device identifier (i.e. that's like having a 32 bit minor number). Since this is private to the kernel, there are no C library -compatibility which you would have with increasing major and minor -number sizes. See the section on "Allocation of Device Numbers" for -details on maintaining compatibility with userspace. +compatibility issues which you would have with increasing major and +minor number sizes. See the section on "Allocation of Device Numbers" +for details on maintaining compatibility with userspace. Solving this requires a kernel change. @@ -375,9 +379,9 @@ devfsd on any event, such as registration/unregistration of device entries, opening and closing devices, looking up inodes, scanning directories and more. This has many possibilities. Some of these are -already implemented. +already implemented. See: + -See: http://www.atnf.csiro.au/~rgooch/linux/ Device entry registration events can be used by devfsd to change @@ -414,6 +418,7 @@ requests. Instead of using kmod directly, the event is sent to devfsd which can implement an arbitrary authentication before loading the module itself. + Inode lookup events can also be used to construct arbitrary namespaces, without having to resort to populating devfs with symlinks to devices that don't exist. @@ -447,10 +452,10 @@ Who else does it? -FreeBSD has a devfs implementation. Solaris 2 has a pseudo-devfs -(something akin to scsidev but for all devices, with some unspecified -kernel support). BeOS, Plan9 and QNX also have it. SGI's IRIX 6.4 and -above also have a device filesystem. +FreeBSD has a devfs implementation. Solaris and AIX each have a +pseudo-devfs (something akin to scsidev but for all devices, with some +unspecified kernel support). BeOS, Plan9 and QNX also have it. SGI's +IRIX 6.4 and above also have a device filesystem. While we shouldn't just automatically do something because others do it, we should not ignore the work of others either. FreeBSD has a lot @@ -613,6 +618,21 @@ are problems with dealing with symlinks, I'm suspicious of the level of security offered in any case. +A better solution is to install util-linux-2.10.h or later, which +fixes a bug with ttyname handling in the login programme. Then append +the following lines to your /etc/securetty file: + +vc/1 +vc/2 +vc/3 +vc/4 +vc/5 +vc/6 +vc/7 +vc/8 + +This will not weaken security. + XFree86 While not essential, it's probably a good idea to upgrade to XFree86 4.0, as patches went in to make it more devfs-friendly. If you don't, @@ -627,17 +647,25 @@ # file classes -- these are regular expressions -=tty[0-9][0-9]* :[0-9]\.[0-9] :[0-9] -+=tty[0-9][0-9]* [0-9][0-9]* :[0-9]\.[0-9] :[0-9] ++=tty[0-9][0-9]* vc/[0-9][0-9]* :[0-9]\.[0-9] :[0-9] # device classes -- these are shell-style globs =/dev/fd[0-1]* +If the patch does not apply, then change the line: + +=tty[0-9][0-9]* :[0-9]\.[0-9] :[0-9] + +with: + +=tty[0-9][0-9]* vc/[0-9][0-9]* :[0-9]\.[0-9] :[0-9] + Disable devpts I've had a report of devpts mounted on /dev/pts not working correctly. Since devfs will also manage /dev/pts, there is no need to mount devpts as well. You should either edit your -/etc/fstab so devpts is not mounted, or disable devfs from +/etc/fstab so devpts is not mounted, or disable devpts from your kernel configuration. Unsupported drivers @@ -664,15 +692,23 @@ The Kernel Finally, you need to make sure devfs is compiled into your -kernel. Set CONFIG_DEVFS_FS=y and recompile your kernel. Next, you -need to make sure devfs is mounted. The best solution is to pass -devfs=mount at the kernel boot command line. You can edit -/etc/lilo.conf and add the line: - -append = "devfs=mount" +kernel. Set CONFIG_DEVFS_FS=y and CONFIG_DEVFS_MOUNT=y and recompile +your kernel. At boot, devfs will be mounted onto /dev. - -This will make the kernel mount devfs at boot time onto /dev. +If you encounter problems booting (for example if you forgot a +configuration step), you can pass devfs=nomount at the kernel +boot command line. This will prevent the kernel from mounting devfs at +boot time onto /dev. + +In general, a kernel built with CONFIG_DEVFS_FS=y but without mounting +devfs onto /dev is completely safe, and requires no +configuration changes. One exception to take note of is when +LABEL= directives are used in /etc/fstab. In this +case you will be unable to boot properly. This is because the +mount(8) programme uses /proc/partitions as part of +the volume label search process, and the device names it finds are not +available, because setting CONFIG_DEVFS_FS=y changes the names in +/proc/partitions, irrespective of whether devfs is mounted. Now you've finished all the steps required. You're now ready to boot your shiny new kernel. Enjoy. @@ -701,7 +737,7 @@ permissions. It may be configured to record changes in permissions and will save them in a database (in fact a directory tree), and restore these upon boot. This is an efficient method and results in immediate -saving of current permissions (unlike the tar approach, which save +saving of current permissions (unlike the tar approach, which saves permissions at some unspecified future time). The default configuration file supplied with devfsd has config entries @@ -745,8 +781,11 @@ + add the following lines to your /etc/devfsd.conf file: +REGISTER ^pt[sy]/.* IGNORE +CHANGE ^pt[sy]/.* IGNORE REGISTER .* COPY /dev-state/$devname $devpath CHANGE .* COPY $devpath /dev-state/$devname CREATE .* COPY $devpath /dev-state/$devname @@ -758,6 +797,17 @@ +Permissions database stored in normal directory + +If you are using an older kernel which doesn't support VFS binding, +then you won't be able to have the permissions database in a +mounted-over /dev. However, you can still use a regular +directory to store the database. The sample /etc/devfsd.conf +file above may still be used. You will need to create the +/dev-state directory prior to installing devfsd. If you have +old permissions in /dev, then just copy the device nodes over +to the new directory. + Dealing with drivers without devfs support @@ -910,13 +960,48 @@ configuration file is installed, which is used by the MODLOAD action. This should be sufficient for most configurations. If you require further configuration, edit your /etc/modules.conf -file. +file. The way module autoloading work with devfs is: + + +a process attempts to lookup a device node (e.g. /dev/fred) + + +if that device node does not exist, the full pathname is passed to +devfsd as a string + + +devfsd will pass the string to the modprobe programme (provided the +configuration line shown above is present), and specifies that +/etc/modules.devfs is the configuration file + + +/etc/modules.devfs includes /etc/modules.conf to +access local configurations + +modprobe will search it's configuration files, looking for an alias +that translates the pathname into a module name + + +the translated pathname is then used to load the module. + + +If you wanted a lookup of /dev/fred to load the +mymod module, you would require the following configuration +line in /etc/modules.conf: + +alias /dev/fred mymod + +The /etc/modules.devfs configuration file provides many such +aliases for standard device names. If you look closely at this file, +you will note that some modules require multiple alias configuration +lines. This is required to support module autoloading for old and new +device names. Mounting root off a devfs device If you wish to mount root off a devfs device when you pass the -"devfs=only" boot option, then you need to pass in the "root=" -option to the kernel when booting. If you use LILO, then you must have -this in lilo.conf: +"devfs=only" boot option, then you need to pass in the +"root=" option to the kernel when booting. If you use +LILO, then you must have this in lilo.conf: append = "root=" @@ -926,12 +1011,12 @@ root = -then LILO will determine the device number of and will write -that device number into a special place in the kernel image before -starting the kernel, and the kernel will use that device number to -mount the root filesystem. So, using the "append" variety ensures that -LILO passes the root filesystem device as a string, which devfs can -then use. +then LILO will determine the device number of and will +write that device number into a special place in the kernel image +before starting the kernel, and the kernel will use that device number +to mount the root filesystem. So, using the "append" variety ensures +that LILO passes the root filesystem device as a string, which devfs +can then use. Note that this isn't an issue if you don't pass "devfs=only". @@ -1067,7 +1152,8 @@ -------- -------- ----------- /dev/tts/{0,1,...} /dev/ttyS{0,1,...} Serial ports /dev/cua/{0,1,...} /dev/cua{0,1,...} Call out devices - /dev/vc/{0,1,...} /dev/tty{1...63} Virtual consoles + /dev/vc/0 /dev/tty Current virtual console + /dev/vc/{1,2,...} /dev/tty{1...63} Virtual consoles /dev/vcc/{0,1,...} /dev/vcs{1...63} Virtual consoles /dev/pty/m{0,1,...} /dev/ptyp?? PTY masters /dev/pty/s{0,1,...} /dev/ttyp?? PTY slaves @@ -1109,7 +1195,8 @@ cases, the kernel-supplied naming scheme is quite convenient, so devfsd does not provide another naming scheme. The convenience names that devfsd creates are in fact the same names as the original devfs -kernel patch created (before Linus mandated the Big Name Change). +kernel patch created (before Linus mandated the Big Name +Change). These are referred to as "new compatibility entries". In order to configure devfsd to create these convenience names, the following lines should be placed in your /etc/devfsd.conf: @@ -1198,6 +1285,24 @@ would appear as /dev/xd/c0t0. +Old Compatibility Names + +The old compatibility names are the legacy device names, such as +/dev/hda, /dev/sda, /dev/rtc and so on. +Devfsd can be configured to create compatibility symlinks so that you +may continue to use the old names in your configuration files and so +that old applications will continue to function correctly. + +In order to configure devfsd to create these legacy names, the +following lines should be placed in your /etc/devfsd.conf: + +REGISTER .* MKOLDCOMPAT +UNREGISTER .* RMOLDCOMPAT + +This will cause devfsd to create (and destroy) symbolic links which +point to the kernel-supplied names. + + SCSI Host Probing Issues Devfs allows you to identify SCSI discs based in part on SCSI host @@ -1220,14 +1325,15 @@ means that devices connected to -- first aha1542 controller - will be c0b#t#u# -- first parallel port ZIP - will be c1b#t#u# -- second aha1542 controller - will be c2b#t#u# -- first NCR53C7xx controller - will be c4b#t#u# -- any extra controller - will be c5b#t#u#, c6b#t#u#, etc +- first aha1542 controller - will be /dev/scsi/host0/bus#/target#/lun# +- first parallel port ZIP - will be /dev/scsi/host1/bus#/target#/lun# +- second aha1542 controller - will be /dev/scsi/host2/bus#/target#/lun# +- first NCR53C7xx controller - will be /dev/scsi/host4/bus#/target#/lun# +- any extra controller - will be /dev/scsi/host5/bus#/target#/lun#, + /dev/scsi/host6/bus#/target#/lun#, etc - if any of above controllers will not be found - the reserved names will not be used by any other device. -- c3b#t#u# names will never be used +- /dev/scsi/host3/bus#/target#/lun# names will never be used You can use ',' instead of ':' as the separator character if you @@ -1343,6 +1449,7 @@ Making things work Alternatives to devfs +What I don't like about devfs @@ -1518,6 +1625,54 @@ + +What I don't like about devfs + +Here are some common complaints about devfs, and some suggestions and +solutions that may make it more palatable for you. I can't please +everybody, but I do try :-) + +I hate the naming scheme + +First, remember that no naming scheme will please everybody. You hate +the scheme, others love it. Who's to say who's right and who's wrong? +Ultimately, the person who writes the code gets to choose, and what +exists now is a combination of the the choices made by the +devfs author and the +kernel maintainer (Linus). + +However, not all is lost. If you want to create your own naming +scheme, it is a simple matter to write a standalone script, hack +devfsd, or write a script called by devfsd. You can create whatever +naming scheme you like. + +Further, if you want to remove all traces of the devfs naming scheme +from /dev, you can mount devfs elsewhere (say +/devfs) and populate /dev with links into +/devfs. This population can be automated using devfsd if you +wish. + +You can even use the VFS binding facility to make the links, rather +than using symbolic links. This way, you don't even have to see the +"destination" of these symbolic links. + +Devfs puts policy into the kernel + +There's already policy in the kernel. Device numbers are in fact +policy (why should the kernel dictate what device numbers I use?). +Face it, some policy has to be in the kernel. The real difference +between device names as policy and device numbers as policy is that +no one will use device numbers directly, because device +numbers are devoid of meaning to humans and are ugly. At least with +the devfs device names, (even though you can add your own naming +scheme) some people will use the devfs-supplied names directly. This +offends some people :-) + +Devfs is bloatware + +This is not even remotely true. As shown above, +both code and data size are quite modest. + ----------------------------------------------------------------------------- @@ -1550,6 +1705,14 @@ http://johannes.erdfelt.com/hotswap.txt. Johannes has promised a HTML version will follow. + + +I presented an invited +paper +at the + +2nd Annual Storage Management Workshop held in Miamia, Florida, +U.S.A. in October 2000. diff -u --recursive --new-file v2.4.5/linux/Documentation/filesystems/hpfs.txt linux/Documentation/filesystems/hpfs.txt --- v2.4.5/linux/Documentation/filesystems/hpfs.txt Fri Jul 28 12:50:51 2000 +++ linux/Documentation/filesystems/hpfs.txt Mon Jun 11 19:15:27 2001 @@ -1,5 +1,5 @@ -Read/Write HPFS 2.00 -1998-1999, Mikulas Patocka +Read/Write HPFS 2.05 +1998-2001, Mikulas Patocka email: mikulas@artax.karlin.mff.cuni.cz homepage: http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi @@ -269,6 +269,20 @@ Removed a lot of redundant code 2.00 Fixed a bug in rename (it was there since 1.96) Better anti-fragmentation strategy +2.01 Fixed problem with directory listing over NFS + Directory lseek now checks for proper parameters + Fixed race-condition in buffer code - it is in all filesystems in Linux; + when reading device (cat /dev/hda) while creating files on it, files + could be damaged +2.02 Woraround for bug in breada in Linux. breada could cause accesses beyond + end of partition +2.03 Char, block devices and pipes are correctly created + Fixed non-crashing race in unlink (Alexander Viro) + Now it works with Japanese version of OS/2 +2.04 Fixed error when ftruncate used to extend file +2.05 Fixed crash when got mount parameters without = + Fixed crash when allocation of anode failed due to full disk + Fixed some crashes when block io or inode allocation failed vim: set textwidth=80: diff -u --recursive --new-file v2.4.5/linux/Documentation/filesystems/udf.txt linux/Documentation/filesystems/udf.txt --- v2.4.5/linux/Documentation/filesystems/udf.txt Thu Mar 2 11:17:32 2000 +++ linux/Documentation/filesystems/udf.txt Mon Jun 11 19:15:27 2001 @@ -1,10 +1,10 @@ * * ./Documentation/filesystems/udf.txt * -UDF Filesystem version 0.9.1 +UDF Filesystem version 0.9.4 If you encounter problems with reading UDF discs using this driver, -please report them to linux_udf@hootie.lvld.hp.com, which is the +please report them to linux_udf@hpesjro.fc.hp.com, which is the developer's list. Write support requires a block driver which supports writing. The current @@ -23,7 +23,8 @@ noadinicb Don't embed data in the inode shortad Use short ad's longad Use long ad's (default) - strict Set strict conformance (unused) + strict Set strict conformance + iocharset= Set the NLS character set The remaining are for debugging and disaster recovery: diff -u --recursive --new-file v2.4.5/linux/Documentation/java.txt linux/Documentation/java.txt --- v2.4.5/linux/Documentation/java.txt Thu Jul 1 10:47:08 1999 +++ linux/Documentation/java.txt Wed Jun 27 13:52:16 2001 @@ -1,4 +1,4 @@ - Java(tm) Binary Kernel Support for Linux v1.02 + Java(tm) Binary Kernel Support for Linux v1.03 ---------------------------------------------- Linux beats them ALL! While all other OS's are TALKING about direct @@ -30,6 +30,8 @@ (you should really have read binfmt_misc.txt now): support for Java applications: ':Java:M::\xca\xfe\xba\xbe::/usr/local/bin/javawrapper:' + support for executable Jar files: + ':ExecutableJAR:E::jar::/usr/local/bin/jarwrapper:' support for Java Applets: ':Applet:E::html::/usr/bin/appletviewer:' or the following, if you want to be more selective: @@ -343,7 +345,15 @@ ====================== Cut here =================== -Now simply chmod +x the .class and/or .html files you want to execute. +====================== Cut here =================== +#!/bin/bash +# /usr/local/java/bin/jarwrapper - the wrapper for binfmt_misc/jar + +java -jar $1 +====================== Cut here =================== + + +Now simply chmod +x the .class, .jar and/or .html files you want to execute. To add a Java program to your path best put a symbolic link to the main .class file into /usr/bin (or another place you like) omitting the .class extension. The directory containing the original .class file will be @@ -369,6 +379,11 @@ ./HelloWorld.class +To execute Java Jar files, simple chmod the *.jar files to include +the execution bit, then just do + ./Application.jar + + To execute Java Applets, simple chmod the *.html files to include the execution bit, then just do ./Applet.html @@ -376,5 +391,6 @@ originally by Brian A. Lantz, brian@lantz.com heavily edited for binfmt_misc by Richard Günther -new scripts by Colin J. Watson . +new scripts by Colin J. Watson +added executable Jar file support by Kurt Huwig diff -u --recursive --new-file v2.4.5/linux/Documentation/kernel-docs.txt linux/Documentation/kernel-docs.txt --- v2.4.5/linux/Documentation/kernel-docs.txt Fri Apr 6 10:42:48 2001 +++ linux/Documentation/kernel-docs.txt Thu Jun 28 14:45:07 2001 @@ -3,7 +3,7 @@ Understanding the Linux Kernel. - Juan-Mariano de Goyeneche < jmseyas@dit.upm.es> + Juan-Mariano de Goyeneche /* * The latest version of this document may be found at: @@ -41,7 +41,7 @@ * Title: "The Linux Kernel" Author: David A. Rusling. - URL: http://sunsite.unc.edu/linux/LDP/tlk/tlk.html + URL: http://www.linuxdoc.org/LDP/tlk/tlk.html Keywords: everything!, book. Description: On line, 200 pages book describing most aspects of the Linux Kernel. Probably, the first reference for beginners. @@ -57,7 +57,7 @@ * Title: "The Linux Kernel Hackers' Guide" Author: Michael K.Johnson and others. - URL: http://khg.redhat.com/HyperNews/get/khg.html + URL: http://www.linuxdoc.org/LDP/khg/HyperNews/get/khg.html Keywords: everything! Description: No more Postscript book-like version. Only HTML now. Many people have contributed. The interface is similar to web @@ -99,15 +99,15 @@ Author: Richard Gooch. URL: http://www.atnf.csiro.au/~rgooch/linux/vfs.txt Keywords: VFS, File System, mounting filesystems, opening files, - dentries, - dcache. Description: Brief introduction to the Linux Virtual File - System. What is it, how it works, operations taken when opening a - file or mounting a file system and description of important data + dentries, dcache. + Description: Brief introduction to the Linux Virtual File System. + What is it, how it works, operations taken when opening a file or + mounting a file system and description of important data structures explaining the purpose of each of their entries. * Title: "The Linux RAID-1, 4, 5 Code" Author: Ingo Molnar, Gadi Oxman and Miguel de Icaza. - URL: http://www.ssc.com/lj/issue44/2391.html + URL: http://www2.linuxjournal.com/lj-issues/issue44/2391.html Keywords: RAID, MD driver. Description: Linux Journal Kernel Korner article. Here is it's abstract: "A description of the implementation of the RAID-1, @@ -117,7 +117,7 @@ * Title: "Dynamic Kernels: Modularized Device Drivers" Author: Alessandro Rubini. - URL: http://www.ssc.com/lj/issue23/1219.html + URL: http://www2.linuxjournal.com/lj-issues/issue23/1219.html Keywords: device driver, module, loading/unloading modules, allocating resources. Description: Linux Journal Kernel Korner article. Here is it's @@ -132,8 +132,8 @@ Author: Alessandro Rubini. URL: http://www2.linuxjournal.com/lj-issues/issue24/1220.html Keywords: character driver, init_module, clean_up module, - autodetection, - mayor number, minor number, file operations, open(), close(). + autodetection, mayor number, minor number, file operations, + open(), close(). Description: Linux Journal Kernel Korner article. Here is it's abstract: "This article, the second of four, introduces part of the actual code to create custom module implementing a character @@ -152,7 +152,7 @@ * Title: "Dissecting Interrupts and Browsing DMA" Author: Alessandro Rubini and Georg v. Zezschwitz. - URL: http://www.ssc.com/lj/issue26/interrupt.html + URL: http://www2.linuxjournal.com/lj-issues/issue26/1222.html Keywords: interrupts, irqs, DMA, bottom halves, task queues. Description: Linux Journal Kernel Korner article. Here is it's abstract: "This is the fourth in a series of articles about @@ -187,26 +187,9 @@ simple---most of the complexity (other than talking to the hardware) involves managing network packets in memory". - * Title: "An Introduction to the Linux 1.3.x Networking Code" - Author: Vipul Gupta. - URL: http://anchor.cs.binghamton.edu/courses/cs628/linux-net.html - Keywords: files, sk_buffs. - Description: A short description of files under the net/ - directory. Each file has a one or two lines paragraph description. - sk_buffs explained, too, with some beautiful pictures. A little - bit outdated. - - * Title: "Linux ioctl() Primer" - Author: Vipul Gupta. - URL: http://anchor.cs.binghamton.edu/courses/cs628/ioctl.html - Keywords: ioctl, socket. - Description: Little description and examples on the use and - implementation of the ioctl() system call. A little bit biased - towards sockets. - * Title: "Writing Linux Device Drivers" Author: Michael K. Johnson. - URL: http://www.redhat.com/~johnsonm/devices.html + URL: http://people.redhat.com/johnsonm/devices.html Keywords: files, VFS, file operations, kernel interface, character vs block devices, I/O access, hardware interrupts, DMA, access to user memory, memory allocation, timers. @@ -241,7 +224,7 @@ URL: ftp://ftp.llp.fu-berlin.de/pub/linux/LINUX-LAB/whitepapers/drivers .ps.gz - Keywords: character device drivers, I/O, signals, DMA, accesing + Keywords: character device drivers, I/O, signals, DMA, accessing ports in user space, kernel environment. Description: 68 pages paper on writing character drivers. A little bit old (1.993, 1.994) although still useful. @@ -260,24 +243,17 @@ Notes: This paper was first published in the Proceedings of the First Dutch International Symposium on Linux, ISBN 90-367-0385-9. - * Title: "The Second Extended Filesystem" - Author: Matthew Wilcox. - URL: http://pocket.fluff.org/~mrw/linux/ext2.txt - Keywords: ext2, filesystem. - Description: Description of ext2's blocks, directories, inodes... - Notes: Seems to be DOWN. Anyone knows another link for it? - * Title: "Analysis of the Ext2fs structure" Author: Louis-Dominique Dubeau. URL: http://step.polymtl.ca/~ldd/ext2fs/ext2fs_toc.html Keywords: ext2, filesystem, ext2fs. Description: Description of ext2's blocks, directories, inodes, - bitmaps, invariants ... + bitmaps, invariants... * Title: "Journaling the Linux ext2fs Filesystem" Author: Stephen C. Tweedie. URL: - ftp://ftp.uk.linux.org:/pub/linux/sct/fs/jfs/journal-design.ps.gz + ftp://ftp.uk.linux.org/pub/linux/sct/fs/jfs/journal-design.ps.gz Keywords: ext3, journaling. Description: Excellent 8-pages paper explaining the journaling capabilities added to ext2 by the author, showing different @@ -291,13 +267,13 @@ Description: Kernel functions/structures/variables which changed from 2.0.x to 2.2.x. - * Title: "Kernel API changes from 2.2 to 2.3" + * Title: "Kernel API changes from 2.2 to 2.4" Author: Richard Gooch. URL: - http://www.atnf.csiro.au/~rgooch/linux/docs/porting-to-2.3.html - Keywords: 2.3, changes. + http://www.atnf.csiro.au/~rgooch/linux/docs/porting-to-2.4.html + Keywords: 2.4, changes. Description: Kernel functions/structures/variables which changed - from 2.2.x to 2.3.x. + from 2.2.x to 2.4.x. * Title: "Linux Kernel Module Programming Guide" Author: Ori Pomerantz. @@ -333,7 +309,9 @@ * Title: "The Kernel Hacking HOWTO" Author: Various Talented People, and Rusty. - URL: http://www.samba.org/~netfilter/kernel-hacking-HOWTO.html + URL: + http://www.lisoleg.net/doc/Kernel-Hacking-HOWTO/kernel-hacking-HOW + TO.html Keywords: HOWTO, kernel contexts, deadlock, locking, modules, symbols, return conventions. Description: From the Introduction: "Please understand that I @@ -345,7 +323,7 @@ routines. This document assumes familiarity with C, and an understanding of what the kernel is, and how it is used. It was originally written for the 2.3 kernels, but nearly all of it - applies to 2.2 too; 2.0 is slightly different. ". + applies to 2.2 too; 2.0 is slightly different". * Title: "ALSA 0.5.0 Developer documentation" Author: Stephan 'Jumpy' Bartels . @@ -476,23 +454,103 @@ URL: http://www.linux-mag.com/2000-03/gear_01.html Keywords: PCI, bus, bus-mastering. Description: The title says it all. - + * Title: "Linux 2.4 Kernel Internals" - Author: Tigran Aivazian. + Author: Tigran Aivazian and Christoph Hellwig. URL: http://www.moses.uklinux.net/patches/lki.html - Keywords: Linux, kernel, VFS, SMP boot - Description: A little book used for a short training course - I gave on this subject at VERITAS. Covers building the kernel - image, booting (including SMP), process management, VFS and more. + Keywords: Linux, kernel, booting, SMB boot, VFS, page cache. + Description: A little book used for a short training course. + Covers building the kernel image, booting (including SMP bootup), + process management, VFS and more. + + * Title: "Linux IP Networking. A Guide to the Implementation and + Modification of the Linux Protocol Stack." + Author: Glenn Herrin. + URL: + http://kernelnewbies.org/documents/ipnetworking/linuxipnetworking. + html + Keywords: network, networking, protocol, IP, UDP, TCP, connection, + socket, receiving, transmitting, forwarding, routing, packets, + modules, /proc, sk_buff, FIB, tags. + Description: Excellent paper devoted to the Linux IP Networking, + explaining anything from the kernel's to the user space + configuration tools' code. Very good to get a general overview of + the kernel networking implementation and understand all steps + packets follow from the time they are received at the network + device till they are delivered to applications. The studied kernel + code is from 2.2.14 version. Provides code for a working packet + dropper example. + + * Title: "Get those boards talking under Linux." + Author: Alex Ivchenko. + URL: http://www.ednmag.com/ednmag/reg/2000/06222000/13df2.htm + Keywords: data-acquisition boards, drivers, modules, interrupts, + memory allocation. + Description: Article written for people wishing to make their data + acquisition boards work on their GNU/Linux machines. Gives a basic + overview on writting drivers, from the naming of functions to + interrupt handling. + Notes: Two-parts article. Part II is at + http://www.ednmag.com/ednmag/reg/2000/07062000/14df.htm + + * Title: "Linux PCMCIA Programmer's Guide" + Author: David Hinds. + URL: http://pcmcia-cs.sourceforge.net/ftp/doc/PCMCIA-PROG.html + Keywords: PCMCIA. + Description: "This document describes how to write kernel device + drivers for the Linux PCMCIA Card Services interface. It also + describes how to write user-mode utilities for communicating with + Card Services. + + * Title: "The Linux Kernel NFSD Implementation" + Author: Neil Brown. + URL: + http://www.cse.unsw.edu.au/~neilb/oss/linux-commentary/nfsd.html + Keywords: knfsd, nfsd, NFS, RPC, lockd, mountd, statd. + Description: The title says it all. + Notes: Covers knfsd's version 1.4.7 (patch against 2.2.7 kernel). + + * Title: "A Linux vm README" + Author: Kanoj Sarcar. + URL: http://reality.sgi.com/kanoj_engr/vm229.html + Keywords: virtual memory, mm, pgd, vma, page, page flags, page + cache, swap cache, kswapd. + Description: Telegraphic, short descriptions and definitions + relating the Linux virtual memory implementation. + + * Title: "(nearly) Complete Linux Loadable Kernel Modules. The + definitive guide for hackers, virus coders and system + administrators." + Author: pragmatic/THC. + URL: http://packetstorm.securify.com/groups/thc/LKM_HACKING.html + Keywords: syscalls, intercept, hide, abuse, symbol table. + Description: Interesting paper on how to abuse the Linux kernel in + order to intercept and modify syscalls, make + files/directories/processes invisible, become root, hijack ttys, + write kernel modules based virus... and solutions for admins to + avoid all those abuses. + Notes: For 2.0.x kernels. Gives guidances to port it to 2.2.x + kernels. Also available in txt format at + http://www.blacknemesis.org/hacking/txt/cllkm.txt BOOKS: (Not on-line) * Title: "Linux Device Drivers" Author: Alessandro Rubini. - Publisher: O'Reilly &Associates. + Publisher: O'Reilly & Associates. Date: 1998. + Pages: 439. ISBN: 1-56592-292-1 + * Title: "Linux Device Drivers, 2nd Edition" + Author: Alessandro Rubini and Jonathan Corbet. + Publisher: O'Reilly & Associates. + Date: 2001. + Pages: 586. + ISBN: 0-59600-008-1 + Notes: Further information in + http://www.oreilly.com/catalog/linuxdrive2/ + * Title: "Linux Kernel Internals" Author: Michael Beck. Publisher: Addison-Wesley. @@ -580,8 +638,26 @@ Notes: Though not being directly about Linux, Linux aims to be POSIX. Good reference. + * Title: "Understanding the Linux Kernel" + Author: Daniel P. Bovet and Marco Cesati. + Publisher: O'Reilly & Associates, Inc.. + Date: 2000. + Pages: 702. + ISBN: 0-596-00002-2 + Notes: Further information in + http://www.oreilly.com/catalog/linuxkernel/ + MISCELLANEOUS: + * Name: linux/Documentation + Author: Many. + URL: Just look inside your kernel sources. + Keywords: anything, DocBook. + Description: Documentation that comes with the kernel sources, + inside the Documentation directory. Some pages from this document + (including this document itself) have been moved there, and might + be more up to date than the web version. + * Name: "Linux Source Driver" URL: http://lsd.linux.cz Keywords: Browsing source code. @@ -593,6 +669,16 @@ and variables) and LSD can generate patches for you on the fly (files, directories or kernel)". + * Name: "Linux Kernel Source Reference" + Author: Thomas Graichen. + URL: http://innominate.org/~graichen/projects/lksr/ + Keywords: CVS, web, cvsweb, browsing source code. + Description: Web interface to a CVS server with the kernel + sources. "Here you can have a look at any file of the Linux kernel + sources of any version starting from 1.0 up to the (daily updated) + current version available. Also you can check the differences + between two versions of a file". + * Name: "Cross-Referencing Linux" URL: http://lxr.linux.no/source/ Keywords: Browsing source code. @@ -608,7 +694,7 @@ produced during the week. Published every Thursday. * Name: "Kernel Traffic" - URL: http://kt.zork.net + URL: http://kt.zork.net/kernel-traffic/ Keywords: linux-kernel mailing list, weekly kernel news. Description: Weekly newsletter covering the most relevant discussions of the linux-kernel mailing list. @@ -622,10 +708,7 @@ too. * Name: "New linux-kernel Mailing List FAQ" - URL: Original site: - http://www.altern.org/andrebalsa/doc/lkml-faq.html - URL: U.S. mirror site: - http://www.ececs.uc.edu/~rreilova/linux/lkml-faq.html + URL: http://www.tux.org/lkml/ Keywords: linux-kernel mailing list FAQ. Description: linux-kernel is a mailing list for developers to communicate. This FAQ builds on the previous linux-kernel mailing @@ -636,34 +719,34 @@ * Name: "Linux Virtual File System" Author: Peter J. Braam. - URL: http://www.coda.cs.cmu.edu/doc/talks/linuxvfs + URL: http://www.coda.cs.cmu.edu/doc/talks/linuxvfs/ Keywords: slides, VFS, inode, superblock, dentry, dcache. Description: Set of slides, presumably from a presentation on the Linux VFS layer. Covers version 2.1.x, with dentries and the dcache. - * Name: "Gary's Enciclopedia - The Linux Kernel" + * Name: "Gary's Encyclopedia - The Linux Kernel" Author: Gary (I suppose...). URL: http://members.aa.net/~swear/pedia/kernel.html Keywords: links, not found here?. - Description: Gary's Enciclopedia exists to allow the rapid finding + Description: Gary's Encyclopedia exists to allow the rapid finding of documentation and other information of interest to GNU/Linux users. It has about 4000 links to external pages in 150 major categories. This link is for kernel-specific links, documents, - sites... Look there if you could not find here whar you were + sites... Look there if you could not find here what you were looking for. * Name: "The home page of Linux-MM" Author: The Linux-MM team. - URL: http://www.linux.eu.org/Linux-MM/ + URL: http://linux-mm.org/ Keywords: memory management, Linux-MM, mm patches, TODO, docs, mailing list. - Description: Site devoted to Linux Memory Mangement development. + Description: Site devoted to Linux Memory Management development. Memory related patches, HOWTOs, links, mm developers... Don't miss it if you are interested in memory management development! * Name: "Kernel Newbies IRC Channel" - URL: http://www.surriel.com/kernelnewbies.shtml + URL: http://www.kernelnewbies.org Keywords: IRC, newbies, channel, asking doubts. Description: #kernelnewbies on irc.openprojects.net. From the web page: "#kernelnewbies is an IRC network dedicated to the 'newbie' @@ -672,7 +755,8 @@ professional kernel hackers that want to help less seasoned kernel people. [...] #kernelnewbies is on the Open Projects IRC Network, try irc.openprojects.net or irc..openprojects.net as your - server and then /join #kernelnewbies". + server and then /join #kernelnewbies". It also hosts articles, + documents, FAQs... * Name: "linux-kernel mailing list archives and search engines" URL: http://www.uwsg.indiana.edu/hypermail/linux/kernel/index.html @@ -683,4 +767,4 @@ you have a better/another one, please let me know. _________________________________________________________________ - Document last updated on Thu Jun 1 21:58:18 CEST 2000DATE$ + Document last updated on Thu Jun 28 15:09:39 CEST 2001 diff -u --recursive --new-file v2.4.5/linux/Documentation/kernel-parameters.txt linux/Documentation/kernel-parameters.txt --- v2.4.5/linux/Documentation/kernel-parameters.txt Wed Apr 18 11:49:11 2001 +++ linux/Documentation/kernel-parameters.txt Wed Jun 20 11:21:33 2001 @@ -455,6 +455,10 @@ lastbus=N [IA-32] Scan all buses till bus #N. Can be useful if the kernel is unable to find your secondary buses and you want to tell it explicitly which ones they are. + assign-busses [IA-32] Always assign all PCI bus + numbers ourselves, overriding + whatever the firmware may have + done. pd. [PARIDE] diff -u --recursive --new-file v2.4.5/linux/Documentation/networking/TODO linux/Documentation/networking/TODO --- v2.4.5/linux/Documentation/networking/TODO Thu Apr 19 13:43:40 2001 +++ linux/Documentation/networking/TODO Mon Jul 2 14:03:04 2001 @@ -14,12 +14,5 @@ * Add ETHTOOL_GDRVINFO ioctl support to all ethernet drivers. - - -To-do items to consider for network drivers -------------------------------------------- -* Make a single function which handles the ethtool ioctl for - most MII-compatible devices? Ideally the driver would pass function - pointers to its existing mdio_{read,write} functions when calling the - generic ioctl handler. +* dmfe PCI DMA is totally wrong and only works on x86 diff -u --recursive --new-file v2.4.5/linux/Documentation/networking/alias.txt linux/Documentation/networking/alias.txt --- v2.4.5/linux/Documentation/networking/alias.txt Tue Apr 28 14:22:04 1998 +++ linux/Documentation/networking/alias.txt Fri Jun 29 19:38:26 2001 @@ -2,40 +2,43 @@ IP-Aliasing: ============ +IP-aliases are additional IP-adresses/masks hooked up to a base +interface by adding a colon and a string when running ifconfig. +This string is usually numeric, but this is not a must. + +IP-Aliases are avail if CONFIG_INET (`standard' IPv4 networking) +is configured in the kernel. -o For IP aliasing you must have IP_ALIAS support included by static - linking. o Alias creation. - Alias creation is done by 'magic' iface naming: eg. to create a + Alias creation is done by 'magic' interface naming: eg. to create a 200.1.1.1 alias for eth0 ... # ifconfig eth0:0 200.1.1.1 etc,etc.... ~~ -> request alias #0 creation (if not yet exists) for eth0 - and routing stuff also ... - # route add -host 200.1.1.1 dev eth0:0 (if same IP network as - main device) - - # route add -net 200.1.1.0 dev eth0:0 (if completely new network wanted - for eth0:0) + + The corresponding route is also set up by this command. + Please note: The route always points to the base interface. + o Alias deletion. - Also done by shutting the interface down: + The alias is removed by shutting the alias down: # ifconfig eth0:0 down ~~~~~~~~~~ -> will delete alias -Alias (re-)configuring +o Alias (re-)configuring - Aliases are not real devices, but programs` should be able to configure and + Aliases are not real devices, but programs should be able to configure and refer to them as usual (ifconfig, route, etc). -Relationship with main device ------------------------------ - - the main device is an alias itself like additional aliases and can - be shut down without deleting other aliases. +o Relationship with main device + + If the base device is shut down the added aliases will be deleted + too. + Contact ------- diff -u --recursive --new-file v2.4.5/linux/Documentation/networking/sk98lin.txt linux/Documentation/networking/sk98lin.txt --- v2.4.5/linux/Documentation/networking/sk98lin.txt Fri Sep 15 14:34:19 2000 +++ linux/Documentation/networking/sk98lin.txt Mon Jul 2 13:56:40 2001 @@ -1,16 +1,17 @@ -(C)Copyright 1999-2000 SysKonnect. +(C)Copyright 1999-2001 SysKonnect GmbH. +All rights reserved =========================================================================== -sk98lin.txt created 12-Sept-2000 +sk98lin.txt created 28-May-2001 -Readme File for sk98lin.o v3.05 -SK-NET Gigabit Ethernet Adapter SK-98xx Driver for Linux +Readme File for sk98lin v4.06 +SK-NET Gigabit Ethernet PCI driver for LINUX This file contains (1) OVERVIEW (2) REQUIRED FILES (3) INSTALLATION -(4) INCLUSION OF THE ADAPTER AT SYSTEM START +(4) INCLUSION OF ADAPTER AT SYSTEM START (5) DRIVER PARAMETERS (6) LARGE FRAME SUPPORT (7) TROUBLESHOOTING @@ -19,13 +20,12 @@ =========================================================================== - (1) OVERVIEW ============ The sk98lin driver supports the SysKonnect SK-NET Gigabit Ethernet Adapter SK-98xx family on Linux 2.2.x and above. -It has been tested with Linux on Intel/x86, ALPHA and UltraSPARC machines. +It has been tested with Linux on Intel/x86 machines. From v3.02 on, the driver is integrated in the linux kernel source. *** @@ -64,8 +64,8 @@ "make modules_install". Reboot your system. -4) Load the module manually by entering: - insmod sk98lin.o +2) Load the module manually by entering: + modprobe sk98lin If the SysKonnect SK-98xx adapter is installed in your computer and you have a /proc filesystem, running the command 'more /proc/net/dev' should produce an output containing a @@ -75,7 +75,7 @@ NOTE 1: If you have more than one SysKonnect SK-98xx adapter, the adapters will be listed as 'eth0', 'eth1', 'eth2', etc. - For each adapter, repeat the steps 5) and 6). + For each adapter, repeat the steps 3) and 4). NOTE 2: If you have other Ethernet adapters installed, your SysKonnect SK-98xx adapter can be mapped to 'eth1' or 'eth2' ... @@ -84,7 +84,7 @@ for each adapter that is found, containing the corresponding 'ethX'. -5) Select an IP address and assign it to the respective adapter by +3) Select an IP address and assign it to the respective adapter by entering: ifconfig eth0 This causes the adapter to connect to the ethernet. The solitary @@ -99,22 +99,22 @@ NOTE: If you are in doubt about IP addresses, ask your network administrator for assistance. -6) Your adapter should now be fully operational. +4) Your adapter should now be fully operational. Use 'ping ' to verify the connection to other computers on your network. - By entering 'ifconfig', you can check the number of packets sent - and received by your adapter and additional some other information - regarding the adapter configuration. + By viewing /proc/net/sk98lin/[devicename], you can check some + information regarding to the adapter configuration. + -7) The driver module can be stopped and unloaded using the following +5) The driver module can be stopped and unloaded using the following commands: ifconfig eth0 down rmmod sk98lin *** -(4) INCLUSION OF THE ADAPTER AT SYSTEM START -============================================ +(4) INCLUSION OF ADAPTER AT SYSTEM START +======================================== Since a large number of different Linux distributions are available, we are unable to describe a general installation procedure @@ -129,7 +129,7 @@ ===================== Parameters can be set at the command line while loading the -module with 'insmod'. The configuration tools of some distributions +module with 'modprobe'. The configuration tools of some distributions can also give parameters to the driver module. If you use the kernel module loader, you can set driver parameters in the file /etc/modules.conf (or old name: /etc/conf.modules). @@ -138,12 +138,12 @@ options sk98lin ... For "...", use the same syntax as described below for the command -line parameters of insmod. +line paramaters of modprobe. You either have to reboot your computer or unload and reload the driver to activate the new parameters. The syntax of the driver parameters is: -insmod sk98lin parameter=value1[,value2[,value3...]] +modprobe sk98lin parameter=value1[,value2[,value3...]] value1 is for the first adapter, value2 for the second one etc. All Parameters are case sensitive, so write them exactly as @@ -156,7 +156,7 @@ adapter to FULL and on Port A of the second adapter to HALF. You must enter: - insmod sk98lin.o AutoNeg_A=On,Off DupCap_A=Full,Half + modprobe sk98lin AutoNeg_A=On,Off DupCap_A=Full,Half NOTE: The number of adapters that can be configured this way is limited in the driver (file skge.c, constant SK_MAX_CARD_PARAM). @@ -187,7 +187,7 @@ this port is not "Sense". If autonegotiation is "On", all three values are possible. If it is "Off", only "Full" and "Half" are allowed. - It is useful if your link partner does not support all + It is usefull if your link partner does not support all possible combinations. - Flow Control @@ -234,7 +234,7 @@ - RLMT (Redundant Link Management Technology) Mode Parameter: RlmtMode - Values: CheckLinkState,CheckLocalPort, CheckSeg + Values: CheckLinkState,CheckLocalPort, CheckSeg, DualNet Default: CheckLinkState RLMT (the driver part that decides which port to use) knows three @@ -257,6 +257,13 @@ Ethernet switches installed in your network that have been configured to use the Spanning Tree protocol. +-- DualNet - Both ports A and B are used as separate devices at the same + time. So if you have a dual port adapter, port A will show up as eth0 + and port B as eth1. Both ports can be used independend with distinct + IP addresses. + The preferred port setting is not used. Rlmt is turned off. + + NOTE: The modes CheckLocalPort and CheckSeg are meant to operate in configurations where a network path between the ports on one adapter exists. Especially, they are not designed to work where @@ -269,7 +276,7 @@ Large frames (also called jumbo frames) are now supported by the driver. This can result in a greatly improved throughput if -transferring large amounts of data. +transfering large amounts of data. To enable large frames, set the MTU (maximum transfer unit) of the interface to the value you wish (up to 9000). The command for this is: @@ -285,7 +292,7 @@ You can switch back to the standard ethernet frame size with: ifconfig eth0 mtu 1500 -To make this setting persistent, add a script with the 'ifconfig' +To make this setting persitent, add a script with the 'ifconfig' line to the system startup sequence (named something like "S99sk98lin" in /etc/rc.d/rc2.d). *** @@ -373,11 +380,27 @@ (8) HISTORY =========== -VERSION 3.05 (In-Kernel version) +VERSION 4.02 (In-Kernel version) +New Features: +- Add Kernel 2.4 changes +Known limitations: +- None + +VERSION 4.01 (In-Kernel version) +Problems fixed: +- Full statistics support for DualNet mode +Known limitations: +- None + +VERSION 4.00 (In-Kernel version) Problems fixed: -- Failed for multiple adapters in kernel 2.4.0 -New features: -- New versions of several common modules +- Memory leak found +New Features: +- Proc filesystem integration +- DualNet functionality integrated +- Rlmt networks added +Known limitations: +- statistics partially incorrect in DualNet mode VERSION 3.04 (In-Kernel version) Problems fixed: diff -u --recursive --new-file v2.4.5/linux/Documentation/networking/vortex.txt linux/Documentation/networking/vortex.txt --- v2.4.5/linux/Documentation/networking/vortex.txt Tue Mar 6 19:13:51 2001 +++ linux/Documentation/networking/vortex.txt Wed Jun 20 11:15:44 2001 @@ -230,6 +230,23 @@ other media types does not occur. +Transmit error, Tx status register 82 +------------------------------------- + +This is a common error which is almost always caused by another host on +the same network being in full-duplex mode, while this host is in +half-duplex mode. You need to find that other host and make it run in +half-duplex mode or fix this host to run in full-duplex mode. + +As a last resort, you can force the 3c59x driver into full-duplex mode +with + + options 3c59x full_duplex=1 + +but this has to be viewed as a workaround for broken network gear and +should only really be used for equipment which cannot autonegotiate. + + Additional resources -------------------- diff -u --recursive --new-file v2.4.5/linux/Documentation/pci.txt linux/Documentation/pci.txt --- v2.4.5/linux/Documentation/pci.txt Sat May 19 17:43:05 2001 +++ linux/Documentation/pci.txt Thu Jun 28 14:58:05 2001 @@ -62,8 +62,13 @@ deregistration of the driver or when it's manually pulled out of a hot-pluggable slot). This function always gets called from process context, so it can sleep. - suspend, Power management hooks -- called when the device goes to - resume sleep or is resumed. + save_state Save a device's state before it's suspend. + suspend Put device into low power state. + resume Wake device from low power state. + enable_wake Enable device to generate wake events from a low power state. + + (Please see Documentation/power/pci.txt for descriptions + of PCI Power Management and the related functions) The ID table is an array of struct pci_device_id ending with a all-zero entry. Each entry consists of: diff -u --recursive --new-file v2.4.5/linux/Documentation/power/pci.txt linux/Documentation/power/pci.txt --- v2.4.5/linux/Documentation/power/pci.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/power/pci.txt Thu Jun 28 14:58:05 2001 @@ -0,0 +1,306 @@ + +PCI Power Management +~~~~~~~~~~~~~~~~~~~~ + +An overview of the concepts and the related functions in the Linux kernel + +Patrick Mochel + +--------------------------------------------------------------------------- + +1. Overview +2. How the PCI Subsystem Does Power Management +3. PCI Utility Functions +4. PCI Device Drivers +5. Resources + +1. Overview +~~~~~~~~~~~ + +The PCI Power Management Specification was introduced between the PCI 2.1 and +PCI 2.2 Specifications. It a standard interface for controlling various +power management operations. + +Implementation of the PCI PM Spec is optional, as are several sub-components of +it. If a device supports the PCI PM Spec, the device will have an 8 byte +capability field in its PCI configuration space. This field is used to describe +and control the standard PCI power management features. + +The PCI PM spec defines 4 operating states for devices (D0 - D3) and for buses +(B0 - B3). The higher the number, the less power the device consumes. However, +the higher the number, the longer the latency is for the device to return to +an operational state (D0). + +Bus power management is not covered in this version of this document. + +Note that all PCI devices support D0 and D3 by default, regardless of whether or +not they implement any of the PCI PM spec. + +The possible state transitions that a device can undergo are: + ++---------------------------+ +| Current State | New State | ++---------------------------+ +| D0 | D1, D2, D3| ++---------------------------+ +| D1 | D2, D3 | ++---------------------------+ +| D2 | D3 | ++---------------------------+ +| D1, D2, D3 | D0 | ++---------------------------+ + +Note that when the system is entering a global suspend state, all devices will be +placed into D3 and when resuming, all devices will be placed into D0. However, +when the system is running, other state transitions are possible. + +2. How The PCI Subsystem Handles Power Management +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The PCI suspend/resume functionality is accessed indirectly via the Power Management +subsystem. At boot, the PCI driver registers a power management callback with that layer. +Upon entering a suspend state, the PM layer iterates through all of its registered +callbacks. This currently takes place only during APM state transitions. + +Upon going to sleep, the PCI subsystem walks its device tree twice. Both times, it does +a depth first walk of the device tree. The first walk saves each of the device's state +and checks for devices that will prevent the system from entering a global power state. +The next walk then places the devices in a low power state. + +The first walk allows a graceful recovery in the event of a failure, since none of the +devices have actually been powered down. + +In both walks, in particular the second, all children of a bridge are touched before the +actual bridge itself. This allows the bridge to retain power while its children are being +accessed. + +Upon resuming from sleep, just the opposite must be true: all bridges must be powered on +and restored before their children are powered on. This is easily accomplished with a +breadth-first walk of the PCI device tree. + + +3. PCI Utility Functions +~~~~~~~~~~~~~~~~~~~~~~~~ + +These are helper functions designed to be called by individual device drivers. +Assuming that a device behaves as advertised, these should be applicable in most +cases. However, results may vary. + +Note that these functions are never implicitly called for the driver. The driver is always +responsible for deciding when and if to call these. + + +pci_save_state +-------------- + +Usage: + pci_save_state(dev, buffer); + +Description: + Save first 64 bytes of PCI config space. Buffer must be allocated by caller. + + +pci_restore_state +----------------- + +Usage: + pci_restore_state(dev,buffer); + +Description: + Restore previously saved config space. (First 64 bytes only); + + If buffer is NULL, then restore what information we know about the device + from bootup: BARs and interrupt line. + + +pci_set_power_state +------------------- + +Usage: + pci_set_power_state(dev,state); + +Description: + Transition device to low power state using PCI PM Capabilities registers. + + Will fail under one of the following conditions: + - If state is less than current state, but not D0 (illegal transition) + - Device doesn't support PM Capabilities + - Device does not support requested state + + +pci_enable_wake +--------------- + +Usage: + pci_enable_wake(dev,state,enable); + +Description: + Enable device to generate PME# during low power state using PCI PM + Capabilities. + + Checks whether if device supports generating PME# from requested state and fail + if it does not, unless enable == 0 (request is to disable wake events, which + is implicit if it doesn't even support it in the first place). + + Note that the PMC Register in the device's PM Capabilties has a bitmask of + the states it supports generating PME# from. D3hot is bit 3 and D3cold is bit + 4. So, while a value of 4 as the state may not seem semantically correct, it + is. + + +4. PCI Device Drivers +~~~~~~~~~~~~~~~~~~~~~ + +These functions are intended for use by individual drivers, and are defined in +struct pci_driver: + + int (*save_state) (struct pci_dev *dev, u32 state); + int (*suspend)(struct pci_dev *dev, u32 state); + int (*resume) (struct pci_dev *dev); + int (*enable_wake) (struct pci_dev *dev, u32 state, int enable); + + +save_state +---------- + +Usage: + +if (dev->driver && dev->driver->save_state) + dev->driver->save_state(dev,state); + +The driver should use this callback to save device state. It should take into +account the current state of the device and the requested state in order to avoid +any unnecessary operations. + +For example, a video card that supports all 4 states (D0-D3), all controller context +is preserved when entering D1, but the screen is placed into a low power state +(blanked). + +The driver can also interpret this function as a notification that it may be entering +a sleep state in the near future. If it knows that the device cannot enter the +requested state, either because of lack of support for it, or because the devices is +middle of some critical operation, then it should fail. + +This function should not be used to set any state in the device or the driver because +the device may not actually enter the sleep state (e.g. another driver later causes +causes a global state transition to fail). + +Note that in intermediate low power states, a device's I/O and memory spaces may be +disabled and may not be available in subsequent transitions to lower power states. + + +suspend +------- + +Usage: + +if (dev->driver && dev->driver->suspend) + dev->driver->suspend(dev,state); + +A driver uses this function to actually transition the device into a low power +state. This may include disabling I/O, memory and bus-mastering, as well as physically +transitioning the device to a lower power state. + +Bus mastering may be disabled by doing: + +pci_disable_device(dev); + +For devices that support the PCI PM Spec, this may be used to set the device's power +state: + +pci_set_power_state(dev,state); + +The driver is also responsible for disabling any other device-specific features +(e.g blanking screen, turning off on-card memory, etc). + +The driver should be sure to track the current state of the device, as it may obviate +the need for some operations. + +The driver should update the current_state field in its pci_dev structure in this +function. + +resume +------ + +Usage: + +if (dev->driver && dev->driver->suspend) + dev->driver->resume(dev) + +The resume callback may be called from any power state, and is always meant to +transition the device to the D0 state. + +The driver is responsible for reenabling any features of the device that had +been disabled during previous suspend calls and restoring all state that was saved +in previous save_state calls. + +If the device is currently in D3, it must be completely reinitialized, as it must be +assumed that the device has lost all of its context (even that of its PCI config +space). For almost all current drivers, this means that the initialization code that +the driver does at boot must be separated out and called again from the resume +callback. Note that some values for the device may not have to be probed for this +time around if they are saved before entering the low power state. + +If the device supports the PCI PM Spec, it can use this to physically transition the +device to D0: + +pci_set_power_state(dev,0); + +Note that if the entire system is transitioning out of a global sleep state, all +devices will be placed in the D0 state, so this is not necessary. However, in the +event that the device is placed in the D3 state during normal operation, this call +is necessary. It is impossible to determine which of the two events is taking place +in the driver, so it is always a good idea to make that call. + +The driver should take note of the state that it is resuming from in order to ensure +correct (and speedy) operation. + +The driver should update the current_state field in its pci_dev structure in this +function. + + +enable_wake +----------- + +Usage: + +if (dev->driver && dev->driver->enable_wake) + dev->driver->enable_wake(dev,state,enable); + +This callback is generally only relevant for devices that support the PCI PM +spec and have the ability to generate a PME# (Power Management Event Signal) +to wake the system up. (However, it is possible that a device may support +some non-standard way of generating a wake event on sleep.) + +Bits 15:11 of the PMC (Power Mgmt Capabilities) Register in a device's +PM Capabilties describe what power states the device supports generating a +wake event from: + ++------------------+ +| Bit | State | ++------------------+ +| 15 | D0 | +| 14 | D1 | +| 13 | D2 | +| 12 | D3hot | +| 11 | D3cold | ++------------------+ + +A device can use this to enable wake events: + + pci_enable_wake(dev,state,enable); + +Note that to enable PME# from D3cold, a value of 4 should be passed to +pci_enable_wake (since it uses an index into a bitmask). If a driver gets +a request to enable wake events from D3, two calls should be made to +pci_enable_wake (one for both D3hot and D3cold). + + +5. Resources +~~~~~~~~~~~~ + +PCI Local Bus Specification +PCI Bus Power Management Interface Specification + + http://pcisig.org + diff -u --recursive --new-file v2.4.5/linux/Documentation/sound/README.OSS linux/Documentation/sound/README.OSS --- v2.4.5/linux/Documentation/sound/README.OSS Wed Apr 11 19:02:27 2001 +++ linux/Documentation/sound/README.OSS Tue Jun 12 10:56:11 2001 @@ -17,7 +17,7 @@ document can be still interesting and very helpful. [ File edited 17.01.1999 - Riccardo Facchetti ] -[ Edited miroSOUND section 17.09.2000 - Robert Siemer ] +[ Edited miroSOUND section 19.04.2001 - Robert Siemer ] OSS/Free version 3.8 release notes ---------------------------------- @@ -1327,7 +1327,7 @@ --------- The miroSOUND PCM1-pro, PCM12 and PCM20 radio has been used -successfully. This card is based on the MAD16, OPL4, and CS4231A chips +successfully. These cards are based on the MAD16, OPL4, and CS4231A chips and everything said in the section about MAD16 cards applies here, too. The only major difference between the PCMxx and other MAD16 cards is that instead of the mixer in the CS4231 codec a separate mixer @@ -1337,8 +1337,8 @@ you compile this ACI driver together with the normal MAD16 support when you use a miroSOUND PCMxx card. The ACI mixer is controlled by /dev/mixer and the CS4231 mixer by /dev/mixer1 (depends on load -time). Only in special cases you want to change something on the CS4231 -mixer. +time). Only in special cases you want to change something regularly on +the CS4231 mixer. The miroSOUND PCM12 and PCM20 radio is capable of full duplex operation (simultaneous PCM replay and recording), which allows you to @@ -1354,10 +1354,9 @@ miropcm20.o module. Also the 7-band equalizer is integrated (limited by the OSS-design). Developement has started and maybe finished for the RDS decoder on this card, too. You will be able to -read radio text, the program service name, program type and +read RadioText, the Programme Service name, Programme TYpe and others. Even the v4l radio module benefits from it with a refined -strength value. See aci.c, radio-miropcm20.c and rds-miropcm20.c for -more details. +strength value. See aci.[ch] and miropcm20*.[ch] for more details. The following configuration parameters have worked fine for the PCM12 in Markus Kuhn's system, many other configurations might work, too: diff -u --recursive --new-file v2.4.5/linux/Documentation/usb/se401.txt linux/Documentation/usb/se401.txt --- v2.4.5/linux/Documentation/usb/se401.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/usb/se401.txt Wed Jun 27 13:59:32 2001 @@ -0,0 +1,54 @@ +Linux driver for SE401 based USB cameras + +Copyright, 2001, Jeroen Vreeken + + +INTRODUCTION: + +The SE401 chip is the used in low-cost usb webcams. +It is produced by Endpoints Inc. (www.endpoints.com). +It interfaces directly to a cmos image sensor and USB. The only other major +part in a se401 based camera is a dram chip. + +The following cameras are known to work with this driver: + +Aox se401 (non-branded) cameras +Philips PVCV665 USB VGA webcam 'Vesta Fun' +Kensington VideoCAM PC Camera Model 67014 +Kensington VideoCAM PC Camera Model 67015 +Kensington VideoCAM PC Camera Model 67016 +Kensington VideoCAM PC Camera Model 67017 + + +WHAT YOU NEED: + +- USB support +- VIDEO4LINUX support + +More information about USB support for linux can be found at: +http://www.linux-usb.org + + +MODULE OPTIONS: + +When the driver is compiled as a module you can also use the 'flickerless' +option. With it exposure is limited to values that do not interfere with the +net frequency. Valid options for this option are 0, 50 and 60. (0=disable, +50=50hz, 60=60hz) + + +KNOWN PROBLEMS: + +The driver works fine with the usb-ohci and uhci host controller drivers, +the default settings also work with usb-uhci. But sending more then one bulk +transfer at a time with usb-uhci doesn't work yet. +Users of usb-ohci and uhci can safely enlarge SE401_NUMSBUF in se401.h in +order to increase the throughput (and thus framerate). + + +HELP: + +The latest info on this driver can be found at: +http://www.chello.nl/~j.vreeken/se401/ +And questions to me can be send to: +pe1rxq@amsat.org diff -u --recursive --new-file v2.4.5/linux/Documentation/usb/usb-serial.txt linux/Documentation/usb/usb-serial.txt --- v2.4.5/linux/Documentation/usb/usb-serial.txt Mon Mar 19 17:21:54 2001 +++ linux/Documentation/usb/usb-serial.txt Wed Jun 27 13:59:32 2001 @@ -245,6 +245,17 @@ Edgeport/16 Dual +REINER SCT cyberJack pinpad/e-com USB chipcard reader + + Interface to ISO 7816 compatible contactbased chipcards, e.g. GSM SIMs. + +Current status: + This is the kernel part of the driver for this USB card reader. + There is also a user part for a CT-API driver available. A site + for downloading is TBA. For now, you can request it from the + maintainer (linux-usb@sii.li). + + Generic Serial driver If your device is not one of the above listed devices, compatible with diff -u --recursive --new-file v2.4.5/linux/MAINTAINERS linux/MAINTAINERS --- v2.4.5/linux/MAINTAINERS Sun May 20 12:11:38 2001 +++ linux/MAINTAINERS Wed Jun 27 13:59:32 2001 @@ -231,7 +231,7 @@ CIRRUS LOGIC GENERIC FBDEV DRIVER P: Jeff Garzik M: jgarzik@mandrakesoft.com -L: linux-fbdev@vuser.vu.union.edu +L: linux-fbdev-devel@lists.sourceforge.net S: Odd Fixes CIRRUS LOGIC CS4280/CS461x SOUNDDRIVER @@ -712,16 +712,11 @@ M: perex@suse.cz S: Maintained -ISDN SUBSYSTEM (general) -P: Fritz Elfert -M: fritz@isdn4linux.de -L: isdn4linux@listserv.isdn4linux.de -W: http://www.isdn4linux.de -S: Maintained - -ISDN SUBSYSTEM (card drivers) +ISDN SUBSYSTEM P: Karsten Keil M: kkeil@suse.de +P: Kai Germaschewski +M: kai.germaschewski@gmx.de L: isdn4linux@listserv.isdn4linux.de W: http://www.isdn4linux.de S: Maintained @@ -764,8 +759,8 @@ M: kaos@ocs.com.au P: Michael Elizabeth Chastain M: mec@shout.net -L: linux-kbuild@torque.net -W: http://www.kernel.org/pub/linux/kernel/projects/kbuild/ +L: kbuild-devel@lists.sourceforge.net +W: http://kbuild.sourceforge.net S: Maintained KERNEL NFSD @@ -789,24 +784,30 @@ L: linux-x25@vger.kernel.org S: Maintained +LINUX FOR IBM pSERIES (RS/6000) +P: Paul Mackerras +M: paulus@au.ibm.com +W: http://www.ibm.com/linux/ltc/projects/ppc +S: Supported + LINUX FOR POWERPC -P: Cort Dougan -M: cort@fsmlabs.com +P: Paul Mackerras +M: paulus@samba.org W: http://www.fsmlabs.com/linuxppcbk.html -S: Maintained +S: Supported LINUX FOR POWER MACINTOSH -P: Paul Mackerras -M: paulus@samba.org +P: Benjamin Herrenschmidt +M: benh@kernel.crashing.org W: http://www.linuxppc.org/ L: linuxppc-dev@lists.linuxppc.org S: Maintained LOGICAL VOLUME MANAGER P: Heinz Mauelshagen -M: linux-LVM@EZ-Darmstadt.Telekom.de -L: linux-LVM@msede.com -W: http://linux.msede.com/lvm +M: mge@sistina.de +L: linux-LVM@sistina.com +W: http://www.sistina.com/lvm S: Maintained M68K @@ -1087,9 +1088,9 @@ S: Maintained RAGE128 FRAMEBUFFER DISPLAY DRIVER -P: Brad Douglas -M: brad@neruo.com -L: linux-fbdev@vuser.vu.union.edu +P: Ani Joshi +M: ajoshi@shell.unixbox.com +L: linux-fbdev-devel@lists.sourceforge.net S: Maintained RAYLINK/WEBGEAR 802.11 WIRELESS LAN DRIVER @@ -1169,7 +1170,7 @@ S: Unmaintained SCSI TAPE DRIVER -P: Kai Mdkisara +P: Kai Mäkisara M: Kai.Makisara@metla.fi L: linux-scsi@vger.kernel.org S: Maintained @@ -1194,12 +1195,6 @@ L: samba@samba.org S: Maintained -SMP: (except SPARC) -P: Linus Torvalds -M: torvalds@transmeta.com -L: linux-smp@vger.kernel.org -S: Maintained - SOFTWARE RAID (Multiple Disks) SUPPORT P: Ingo Molnar M: mingo@redhat.com @@ -1347,8 +1342,8 @@ M: bfennema@falcon.csc.calpoly.edu P: Dave Boynton M: dave@trylinux.com -L: linux_udf@hootie.lvld.hp.com -W: http://www.trylinux.com/projects/udf/index.html +L: linux_udf@hpesjro.fc.hp.com +W: http://linux-udf.sourceforge.net S: Maintained UMSDOS FILESYSTEM @@ -1473,6 +1468,12 @@ L: linux-usb-devel@lists.sourceforge.net S: Maintained +USB SERIAL CYBERJACK PINPAD/E-COM DRIVER +M: linux-usb@sii.li +L: linux-usb-users@lists.sourceforge.net +L: linux-usb-devel@lists.sourceforge.net +S: Supported + USB MASS STORAGE DRIVER P: Matthew Dharm M: mdharm-usb@one-eyed-alien.net @@ -1571,6 +1572,12 @@ M: middelin@polyware.nl W: http://www.polyware.nl/~middelin/En/hobbies.html W: http://www.polyware.nl/~middelin/hobbies.html +S: Maintained + +Bluetooth Subsystem (BlueZ) +P: Maxim Krasnyansky +M: maxk@qualcomm.com +W: http://bluez.sf.net S: Maintained THE REST diff -u --recursive --new-file v2.4.5/linux/Makefile linux/Makefile --- v2.4.5/linux/Makefile Fri May 25 09:51:33 2001 +++ linux/Makefile Mon Jul 2 17:46:42 2001 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 4 -SUBLEVEL = 5 +SUBLEVEL = 6 EXTRAVERSION = KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) @@ -87,7 +87,8 @@ CPPFLAGS := -D__KERNEL__ -I$(HPATH) -CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing +CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -O2 \ + -fomit-frame-pointer -fno-strict-aliasing AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS) # @@ -127,6 +128,7 @@ DRIVERS-m := DRIVERS- := +DRIVERS-$(CONFIG_ACPI) += drivers/acpi/acpi.o DRIVERS-$(CONFIG_PARPORT) += drivers/parport/driver.o DRIVERS-y += drivers/char/char.o \ drivers/block/block.o \ @@ -155,7 +157,8 @@ DRIVERS-$(CONFIG_PCI) += drivers/pci/driver.o DRIVERS-$(CONFIG_MTD) += drivers/mtd/mtdlink.o DRIVERS-$(CONFIG_PCMCIA) += drivers/pcmcia/pcmcia.o -DRIVERS-$(CONFIG_PCMCIA_NETCARD) += drivers/net/pcmcia/pcmcia_net.o +DRIVERS-$(CONFIG_NET_PCMCIA) += drivers/net/pcmcia/pcmcia_net.o +DRIVERS-$(CONFIG_NET_WIRELESS) += drivers/net/wireless/wireless_net.o DRIVERS-$(CONFIG_PCMCIA_CHRDEV) += drivers/char/pcmcia/pcmcia_char.o DRIVERS-$(CONFIG_DIO) += drivers/dio/dio.a DRIVERS-$(CONFIG_SBUS) += drivers/sbus/sbus_all.o @@ -175,8 +178,8 @@ DRIVERS-$(CONFIG_IRDA) += drivers/net/irda/irda.o DRIVERS-$(CONFIG_I2C) += drivers/i2c/i2c.o DRIVERS-$(CONFIG_PHONE) += drivers/telephony/telephony.o -DRIVERS-$(CONFIG_ACPI) += drivers/acpi/acpi.o DRIVERS-$(CONFIG_MD) += drivers/md/mddev.o +DRIVERS-$(CONFIG_BLUEZ) += drivers/bluetooth/bluetooth.o DRIVERS := $(DRIVERS-y) diff -u --recursive --new-file v2.4.5/linux/arch/alpha/boot/bootloader.lds linux/arch/alpha/boot/bootloader.lds --- v2.4.5/linux/arch/alpha/boot/bootloader.lds Sun Sep 6 10:34:33 1998 +++ linux/arch/alpha/boot/bootloader.lds Mon Jul 2 14:40:14 2001 @@ -6,7 +6,7 @@ .text : { *(.text) } _etext = .; PROVIDE (etext = .); - .rodata : { *(.rodata) } + .rodata : { *(.rodata) *(.rodata.*) } .data : { *(.data) CONSTRUCTORS } .got : { *(.got) } .sdata : { *(.sdata) } diff -u --recursive --new-file v2.4.5/linux/arch/alpha/config.in linux/arch/alpha/config.in --- v2.4.5/linux/arch/alpha/config.in Fri May 25 09:55:36 2001 +++ linux/arch/alpha/config.in Mon Jun 11 19:15:27 2001 @@ -348,6 +348,10 @@ source drivers/usb/Config.in source drivers/input/Config.in +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + source net/bluetooth/Config.in +fi + mainmenu_option next_comment comment 'Kernel hacking' diff -u --recursive --new-file v2.4.5/linux/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c --- v2.4.5/linux/arch/alpha/kernel/alpha_ksyms.c Fri May 25 09:54:50 2001 +++ linux/arch/alpha/kernel/alpha_ksyms.c Wed Jun 20 11:10:27 2001 @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -100,6 +101,10 @@ EXPORT_SYMBOL(__constant_c_memset); EXPORT_SYMBOL(copy_page); EXPORT_SYMBOL(clear_page); + +EXPORT_SYMBOL(__delay); +EXPORT_SYMBOL(__udelay); +EXPORT_SYMBOL(udelay); EXPORT_SYMBOL(__direct_map_base); EXPORT_SYMBOL(__direct_map_size); diff -u --recursive --new-file v2.4.5/linux/arch/alpha/kernel/core_tsunami.c linux/arch/alpha/kernel/core_tsunami.c --- v2.4.5/linux/arch/alpha/kernel/core_tsunami.c Thu May 24 15:24:37 2001 +++ linux/arch/alpha/kernel/core_tsunami.c Mon Jun 11 19:15:27 2001 @@ -11,7 +11,6 @@ #include #include #include -#include #include #include @@ -21,6 +20,8 @@ #include #include #undef __EXTERN_INLINE + +#include #include "proto.h" #include "pci_impl.h" diff -u --recursive --new-file v2.4.5/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S --- v2.4.5/linux/arch/alpha/kernel/entry.S Thu May 24 15:20:18 2001 +++ linux/arch/alpha/kernel/entry.S Mon Jun 11 19:15:27 2001 @@ -31,7 +31,7 @@ #define TASK_STATE 0 #define TASK_FLAGS 8 #define TASK_SIGPENDING 16 -#define TASK_ADDR_LIMIT 24 +#define TASK_ADDR_LIMIT 24 #define TASK_EXEC_DOMAIN 32 #define TASK_NEED_RESCHED 40 #define TASK_PTRACE 48 @@ -576,13 +576,15 @@ .align 3 ret_from_sys_call: cmovne $26,0,$19 /* $19 = 0 => non-restartable */ +#ifdef CONFIG_SMP ldl $3,TASK_PROCESSOR($8) - lda $4,irq_stat /* softirq_active */ sll $3,L1_CACHE_SHIFT,$3 +#endif + lda $4,irq_stat +#ifdef CONFIG_SMP addq $3,$4,$4 - ldq $4,0($4) /* softirq_active[32] + softirq_mask[32] */ - sll $4,32,$3 - and $4,$3,$4 +#endif + ldq $4,0($4) /* __softirq_pending */ bne $4,handle_softirq ret_from_softirq: ldq $0,SP_OFF($30) diff -u --recursive --new-file v2.4.5/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c --- v2.4.5/linux/arch/alpha/kernel/irq.c Fri Feb 9 11:29:44 2001 +++ linux/arch/alpha/kernel/irq.c Wed Jun 20 11:10:27 2001 @@ -359,7 +359,9 @@ static void register_irq_proc (unsigned int irq) { +#ifdef CONFIG_SMP struct proc_dir_entry *entry; +#endif char name [MAX_NAMELEN]; if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type)) @@ -389,7 +391,9 @@ void init_irq_proc (void) { +#ifdef CONFIG_SMP struct proc_dir_entry *entry; +#endif int i; /* create /proc/irq */ @@ -512,7 +516,10 @@ int get_irq_list(char *buf) { - int i, j; +#ifdef CONFIG_SMP + int j; +#endif + int i; struct irqaction * action; char *p = buf; @@ -569,7 +576,7 @@ /* - * do_IRQ handles all normal device IRQ's (the special + * handle_irq handles all normal device IRQ's (the special * SMP cross-CPU interrupts have their own specific * handlers). */ @@ -632,7 +639,7 @@ /* * Edge triggered interrupts need to remember pending events. * This applies to any hw interrupts that allow a second - * instance of the same irq to arrive while we are in do_IRQ + * instance of the same irq to arrive while we are in handle_irq * or in the handler. But the code here only handles the _second_ * instance of the irq, not the third or fourth. So it is mostly * useful for irq hardware that does not mask cleanly in an @@ -656,6 +663,9 @@ */ desc->handler->end(irq); spin_unlock(&desc->lock); + + if (softirq_pending(cpu)) + do_softirq(); } /* diff -u --recursive --new-file v2.4.5/linux/arch/alpha/kernel/irq_alpha.c linux/arch/alpha/kernel/irq_alpha.c --- v2.4.5/linux/arch/alpha/kernel/irq_alpha.c Tue Feb 13 14:13:43 2001 +++ linux/arch/alpha/kernel/irq_alpha.c Mon Jul 2 14:03:04 2001 @@ -18,6 +18,8 @@ unsigned long __irq_attempt[NR_IRQS]; #endif +extern unsigned long irq_err_count; + /* Hack minimum IPL during interrupt processing for broken hardware. */ #ifdef CONFIG_ALPHA_BROKEN_IRQ_MASK int __min_ipl; diff -u --recursive --new-file v2.4.5/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c --- v2.4.5/linux/arch/alpha/kernel/osf_sys.c Mon Mar 19 12:35:09 2001 +++ linux/arch/alpha/kernel/osf_sys.c Tue Jun 12 10:26:14 2001 @@ -44,7 +44,6 @@ extern int do_pipe(int *); -extern asmlinkage int sys_swapon(const char *specialfile, int swap_flags); extern asmlinkage unsigned long sys_brk(unsigned long); /* diff -u --recursive --new-file v2.4.5/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c --- v2.4.5/linux/arch/alpha/kernel/process.c Thu May 24 15:20:18 2001 +++ linux/arch/alpha/kernel/process.c Wed Jun 20 11:10:27 2001 @@ -28,6 +28,7 @@ #include #include #include +#include #include #include diff -u --recursive --new-file v2.4.5/linux/arch/alpha/kernel/smp.c linux/arch/alpha/kernel/smp.c --- v2.4.5/linux/arch/alpha/kernel/smp.c Thu May 24 15:24:37 2001 +++ linux/arch/alpha/kernel/smp.c Mon Jun 11 19:15:27 2001 @@ -682,6 +682,9 @@ data->prof_counter = data->prof_multiplier; irq_exit(cpu, RTC_IRQ); + + if (softirq_pending(cpu)) + do_softirq(); } } diff -u --recursive --new-file v2.4.5/linux/arch/alpha/kernel/sys_alcor.c linux/arch/alpha/kernel/sys_alcor.c --- v2.4.5/linux/arch/alpha/kernel/sys_alcor.c Fri Oct 27 10:55:01 2000 +++ linux/arch/alpha/kernel/sys_alcor.c Wed Jun 27 16:18:13 2001 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -219,11 +220,21 @@ static void alcor_kill_arch(int mode) { - /* Who said DEC engineer's have no sense of humor? ;-) */ - if (alpha_using_srm) { - *(vuip) GRU_RESET = 0x0000dead; - mb(); + switch(mode) { + case LINUX_REBOOT_CMD_RESTART: + /* Who said DEC engineer's have no sense of humor? ;-) */ + if (alpha_using_srm) { + *(vuip) GRU_RESET = 0x0000dead; + mb(); + } + break; + case LINUX_REBOOT_CMD_HALT: + break; + case LINUX_REBOOT_CMD_POWER_OFF: + break; } + + halt(); } diff -u --recursive --new-file v2.4.5/linux/arch/alpha/kernel/sys_dp264.c linux/arch/alpha/kernel/sys_dp264.c --- v2.4.5/linux/arch/alpha/kernel/sys_dp264.c Fri May 25 09:54:50 2001 +++ linux/arch/alpha/kernel/sys_dp264.c Mon Jun 11 19:15:27 2001 @@ -16,18 +16,15 @@ #include #include -#define __EXTERN_INLINE inline -#include -#include -#undef __EXTERN_INLINE - #include #include #include #include #include #include +#include #include +#include #include #include "proto.h" diff -u --recursive --new-file v2.4.5/linux/arch/alpha/kernel/sys_rawhide.c linux/arch/alpha/kernel/sys_rawhide.c --- v2.4.5/linux/arch/alpha/kernel/sys_rawhide.c Fri Mar 2 11:12:07 2001 +++ linux/arch/alpha/kernel/sys_rawhide.c Mon Jun 11 19:15:27 2001 @@ -59,10 +59,11 @@ irq -= 16; hose = irq / 24; irq -= hose * 24; + mask = 1 << irq; spin_lock(&rawhide_irq_lock); - mask = cached_irq_masks[hose] |= 1 << irq; - mask |= hose_irq_masks[hose]; + mask |= cached_irq_masks[hose]; + cached_irq_masks[hose] = mask; rawhide_update_irq_hw(hose, mask); spin_unlock(&rawhide_irq_lock); } @@ -75,14 +76,37 @@ irq -= 16; hose = irq / 24; irq -= hose * 24; + mask = ~(1 << irq) | hose_irq_masks[hose]; spin_lock(&rawhide_irq_lock); - mask = cached_irq_masks[hose] &= ~(1 << irq); - mask |= hose_irq_masks[hose]; + mask &= cached_irq_masks[hose]; + cached_irq_masks[hose] = mask; rawhide_update_irq_hw(hose, mask); spin_unlock(&rawhide_irq_lock); } +static void +rawhide_mask_and_ack_irq(unsigned int irq) +{ + unsigned int mask, mask1, hose; + + irq -= 16; + hose = irq / 24; + irq -= hose * 24; + mask1 = 1 << irq; + mask = ~mask1 | hose_irq_masks[hose]; + + spin_lock(&rawhide_irq_lock); + + mask &= cached_irq_masks[hose]; + cached_irq_masks[hose] = mask; + rawhide_update_irq_hw(hose, mask); + + /* Clear the interrupt. */ + *(vuip)MCPCIA_INT_REQ(MCPCIA_HOSE2MID(hose)) = mask1; + + spin_unlock(&rawhide_irq_lock); +} static unsigned int rawhide_startup_irq(unsigned int irq) @@ -104,7 +128,7 @@ shutdown: rawhide_disable_irq, enable: rawhide_enable_irq, disable: rawhide_disable_irq, - ack: rawhide_disable_irq, + ack: rawhide_mask_and_ack_irq, end: rawhide_end_irq, }; @@ -145,8 +169,12 @@ mcpcia_init_hoses(); for (hose = hose_head; hose; hose = hose->next) { - int h = hose->index; - rawhide_update_irq_hw(h, hose_irq_masks[h]); + unsigned int h = hose->index; + unsigned int mask = hose_irq_masks[h]; + + cached_irq_masks[h] = mask; + *(vuip)MCPCIA_INT_MASK0(MCPCIA_HOSE2MID(h)) = mask; + *(vuip)MCPCIA_INT_MASK1(MCPCIA_HOSE2MID(h)) = 0; } for (i = 16; i < 128; ++i) { diff -u --recursive --new-file v2.4.5/linux/arch/alpha/kernel/sys_sable.c linux/arch/alpha/kernel/sys_sable.c --- v2.4.5/linux/arch/alpha/kernel/sys_sable.c Fri Oct 27 10:55:01 2000 +++ linux/arch/alpha/kernel/sys_sable.c Tue Jun 12 11:44:59 2001 @@ -96,7 +96,7 @@ static inline void sable_update_irq_hw(unsigned long bit, unsigned long mask) { - int port = 0x536; + int port = 0x537; if (bit >= 16) { port = 0x53d; @@ -121,7 +121,7 @@ } else if (bit >= 8) { port = 0x53a; val1 = 0xE0 | (bit - 8); - val2 = 0xE0 | 2; + val2 = 0xE0 | 3; } else { port = 0x536; val1 = 0xE0 | (bit - 0); diff -u --recursive --new-file v2.4.5/linux/arch/alpha/kernel/sys_sio.c linux/arch/alpha/kernel/sys_sio.c --- v2.4.5/linux/arch/alpha/kernel/sys_sio.c Fri Oct 27 10:55:01 2000 +++ linux/arch/alpha/kernel/sys_sio.c Wed Jun 20 11:10:27 2001 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include diff -u --recursive --new-file v2.4.5/linux/arch/alpha/lib/Makefile linux/arch/alpha/lib/Makefile --- v2.4.5/linux/arch/alpha/lib/Makefile Thu Feb 8 12:56:29 2001 +++ linux/arch/alpha/lib/Makefile Wed Jun 20 11:10:27 2001 @@ -21,6 +21,7 @@ endif OBJS = __divqu.o __remqu.o __divlu.o __remlu.o \ + udelay.o \ $(ev6)memset.o \ $(ev6)memcpy.o \ memmove.o \ diff -u --recursive --new-file v2.4.5/linux/arch/alpha/lib/udelay.c linux/arch/alpha/lib/udelay.c --- v2.4.5/linux/arch/alpha/lib/udelay.c Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/lib/udelay.c Wed Jun 20 11:10:27 2001 @@ -0,0 +1,47 @@ +#include +#include /* for udelay's use of smp_processor_id */ +#include +#include +#include + +/* + * Copyright (C) 1993, 2000 Linus Torvalds + * + * Delay routines, using a pre-computed "loops_per_jiffy" value. + */ + +/* + * Use only for very small delays (< 1 msec). + * + * The active part of our cycle counter is only 32-bits wide, and + * we're treating the difference between two marks as signed. On + * a 1GHz box, that's about 2 seconds. + */ + +void __delay(int loops) +{ + int tmp; + __asm__ __volatile__( + " rpcc %0\n" + " addl %1,%0,%1\n" + "1: rpcc %0\n" + " subl %1,%0,%0\n" + " bgt %0,1b" + : "=&r" (tmp), "=r" (loops) : "1"(loops)); +} + +void __udelay(unsigned long usecs, unsigned long lpj) +{ + usecs *= (((unsigned long)HZ << 32) / 1000000) * lpj; + __delay((long)usecs >> 32); +} + +void udelay(unsigned long usecs) +{ +#ifdef CONFIG_SMP + __udelay(usecs, cpu_data[smp_processor_id()].loops_per_jiffy); +#else + __udelay(usecs, loops_per_jiffy); +#endif +} + diff -u --recursive --new-file v2.4.5/linux/arch/alpha/vmlinux.lds.in linux/arch/alpha/vmlinux.lds.in --- v2.4.5/linux/arch/alpha/vmlinux.lds.in Mon Jun 26 11:26:56 2000 +++ linux/arch/alpha/vmlinux.lds.in Mon Jul 2 14:40:14 2001 @@ -53,7 +53,7 @@ /* Global data */ _data = .; .data.cacheline_aligned : { *(.data.cacheline_aligned) } - .rodata : { *(.rodata) } + .rodata : { *(.rodata) *(.rodata.*) } .data : { *(.data) CONSTRUCTORS } .got : { *(.got) } .sdata : { *(.sdata) } diff -u --recursive --new-file v2.4.5/linux/arch/arm/Makefile linux/arch/arm/Makefile --- v2.4.5/linux/arch/arm/Makefile Thu Apr 12 12:20:31 2001 +++ linux/arch/arm/Makefile Wed Jun 27 14:12:04 2001 @@ -26,7 +26,7 @@ apcs-$(CONFIG_CPU_26) :=-mcpu=arm3 -Os arch-y := -arch-$(CONFIG_CPU_32v3) :=-march=armv3m +arch-$(CONFIG_CPU_32v3) :=-march=armv3 arch-$(CONFIG_CPU_32v4) :=-march=armv4 arch-$(CONFIG_CPU_32v5) :=-march=armv5 @@ -123,6 +123,10 @@ MACHINE = clps711x endif +ifeq ($(CONFIG_ARCH_ANAKIN),y) +MACHINE = anakin +endif + export LIBGCC MACHINE PROCESSOR TEXTADDR GZFLAGS # Only set INCDIR if its not already defined above @@ -156,7 +160,7 @@ LIBS := arch/arm/fastfpe/fast-math-emu.o $(LIBS) endif -ifeq ($(CONFIG_ARCH_CLPS7500),y) +ifeq ($(findstring y,$(CONFIG_ARCH_CLPS7500) $(CONFIG_ARCH_L7200)),y) SUBDIRS += drivers/acorn/char DRIVERS += drivers/acorn/char/acorn-char.o endif @@ -237,8 +241,8 @@ @( \ CFG=$(@:_config=); \ if [ -f arch/arm/def-configs/$$CFG ]; then \ - $(RM) arch/arm/defconfig; \ - cp arch/arm/def-configs/$$CFG arch/arm/defconfig; \ + [ -f .config ] && $(MV) .config .config.old; \ + cp arch/arm/def-configs/$$CFG .config; \ echo "*** Default configuration for $$CFG installed"; \ echo "*** Next, you may run 'make oldconfig'"; \ else \ diff -u --recursive --new-file v2.4.5/linux/arch/arm/boot/Makefile linux/arch/arm/boot/Makefile --- v2.4.5/linux/arch/arm/boot/Makefile Thu Apr 12 12:03:50 2001 +++ linux/arch/arm/boot/Makefile Wed Jun 27 14:12:04 2001 @@ -90,9 +90,17 @@ ifeq ($(CONFIG_SA1100_GRAPHICSCLIENT),y) ZTEXTADDR = 0xC0200000 endif +ifeq ($(CONFIG_SA1100_YOPY),y) + ZTEXTADDR = 0x00080000 + ZBSSADDR = 0xc0200000 +endif ifeq ($(CONFIG_SA1111),y) ZRELADDR = 0xc0208000 endif +endif + +ifeq ($(CONFIG_ARCH_ANAKIN),y) +ZTEXTADDR = 0x20008000 endif # diff -u --recursive --new-file v2.4.5/linux/arch/arm/boot/compressed/Makefile linux/arch/arm/boot/compressed/Makefile --- v2.4.5/linux/arch/arm/boot/compressed/Makefile Thu Apr 12 12:03:50 2001 +++ linux/arch/arm/boot/compressed/Makefile Wed Jun 27 14:12:04 2001 @@ -30,7 +30,7 @@ endif ifeq ($(CONFIG_ARCH_INTEGRATOR),y) -OBJS += head-netwinder.o +OBJS += head-integrator.o endif ifeq ($(CONFIG_ARCH_FTVPCI),y) diff -u --recursive --new-file v2.4.5/linux/arch/arm/boot/compressed/head-integrator.S linux/arch/arm/boot/compressed/head-integrator.S --- v2.4.5/linux/arch/arm/boot/compressed/head-integrator.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/boot/compressed/head-integrator.S Wed Jun 27 14:12:04 2001 @@ -0,0 +1,4 @@ +#include + + .section ".start", #alloc, #execinstr + mov r7, #MACH_TYPE_INTEGRATOR diff -u --recursive --new-file v2.4.5/linux/arch/arm/boot/compressed/head.S linux/arch/arm/boot/compressed/head.S --- v2.4.5/linux/arch/arm/boot/compressed/head.S Thu Apr 12 12:03:50 2001 +++ linux/arch/arm/boot/compressed/head.S Wed Jun 27 14:12:04 2001 @@ -12,7 +12,39 @@ /* * Debugging stuff + * + * Note that these macros must not contain any code which is not + * 100% relocatable. Any attempt to do so will result in a crash. + * Please select one of the following when turning on debugging. */ +#ifdef DEBUG +#if 0 /* DC21285-type */ + .macro loadsp, rb + mov \rb, #0x7c000000 + .endm + .macro writeb, rb + strb \rb, [r3, #0x3f8] + .endm +#elif 0 /* RiscPC-type */ + .macro loadsp, rb + mov \rb, #0x03000000 + orr \rb, \rb, #0x00010000 + .endm + .macro writeb, rb + strb \rb, [r3, #0x3f8 << 2] + .endm +#elif 0 /* integrator-type */ + .macro loadsp, rb + mov \rb, #0x16000000 + .endm + .macro writeb, rb + strb \rb, [r3, #0] + .endm +#else +#error no serial architecture defined +#endif +#endif + .macro kputc,val mov r0, \val bl putc @@ -27,53 +59,31 @@ .macro debug_reloc_start #ifdef DEBUG kputc #'\n' - kphex r6, 8 + kphex r6, 8 /* processor id */ kputc #':' - kphex r5, 8 + kphex r7, 8 /* architecture id */ + kputc #':' + mrc p15, 0, r0, c1, c0 + kphex r0, 8 /* control reg + kputc #'\n' + kphex r5, 8 /* decompressed kernel start */ kputc #'-' - kphex r8, 8 + kphex r8, 8 /* decompressed kernel end */ kputc #'>' - kphex r4, 8 + kphex r4, 8 /* kernel execution address */ kputc #'\n' #endif .endm .macro debug_reloc_end #ifdef DEBUG - mov r8, r0 - kphex r5, 8 - kputc #'-' - kphex r8, 8 + kphex r5, 8 /* end of kernel */ kputc #'\n' mov r0, r4 - bl memdump + bl memdump /* dump 256 bytes at start of kernel */ #endif .endm -/* - * Note that these macros must not contain any code which is not - * 100% relocatable. Any attempt to do so will result in a crash. - */ -#if 0 - .macro loadsp, rb - mov \rb, #0x7c000000 - .endm - - .macro writeb, rb - strb \rb, [r3, #0x3f8] - .endm -#else - .macro loadsp, rb - mov \rb, #0x03000000 - orr \rb, \rb, #0x00010000 - .endm - - .macro writeb, rb - strb \rb, [r3, #0x3f8 << 2] - .endm -#endif - - .section ".start", #alloc, #execinstr /* * sort out different calling conventions @@ -91,14 +101,18 @@ .word _edata @ zImage end address 1: mov r7, r1 @ save architecture ID mov r8, #0 @ save r0 -#ifdef CONFIG_ANGELBOOT + /* * Booting from Angel - need to enter SVC mode and disable - * FIQs/IRQs (numeric definitions from angel arm.h source) + * FIQs/IRQs (numeric definitions from angel arm.h source). + * We only do this if we were in user mode on entry. */ + mrs r0, cpsr @ get current mode + tst r0, #3 @ not user? + bne not_angel mov r0, #0x17 @ angel_SWIreason_EnterSVC swi 0x123456 @ angel_SWI_ARM - mrs r0, cpsr @ turn off interrupts to +not_angel: mrs r0, cpsr @ turn off interrupts to orr r0, r0, #0xc0 @ prevent angel from running msr cpsr_c, r0 @@ -106,7 +120,7 @@ * Note that some cache flushing and other stuff may * be needed here - is there an Angel SWI call for this? */ -#endif + /* * some architecture specific code can be inserted * by the linker here, but it should preserve r7 and r8. @@ -300,30 +314,46 @@ .size proc_sa1110_type, . - proc_sa1110_type /* - * Turn off StrongARM cache and MMU. It is safe to - * leave the I-cache on. + * Turn off the Cache and MMU. ARMv3 does not support + * reading the control register, but ARMv4 does. * - * On entry, - * r6 = processor ID - * On exit, - * r0, r1 corrupted - * This routine must preserve: - * r4, r6, r7 + * On entry, r6 = processor ID + * On exit, r0, r1 corrupted + * This routine must preserve: r4, r6, r7 */ .align 5 -cache_off: ldr r1, proc_sa110_type - eor r1, r1, r6 - movs r1, r1, lsr #5 @ catch SA110 and SA1100 - beq 1f - ldr r1, proc_sa1110_type - eor r1, r1, r6 - movs r1, r1, lsr #4 - movne pc, lr -1: +cache_off: +#ifdef CONFIG_CPU_ARM610 + eor r1, r6, #0x41000000 + eor r1, r1, #0x00560000 + bic r1, r1, #0x0000001f + teq r1, #0x00000600 + mov r0, #0x00000060 @ ARM6 control reg. + beq __armv3_cache_off +#endif +#ifdef CONFIG_CPU_ARM710 + eor r1, r6, #0x41000000 + bic r1, r1, #0x00070000 + bic r1, r1, #0x000000ff + teq r1, #0x00007000 @ ARM7 + teqne r1, #0x00007100 @ ARM710 + mov r0, #0x00000070 @ ARM7 control reg. + beq __armv3_cache_off +#endif mrc p15, 0, r0, c1, c0 bic r0, r0, #0x000d - mcr p15, 0, r0, c1, c0 - mov pc, lr + mcr p15, 0, r0, c1, c0 @ turn MMU and cache off + mov r0, #0 + mcr p15, 0, r0, c7, c7 @ invalidate whole cache v4 + mcr p15, 0, r0, c8, c7 @ invalidate whole TLB v4 + mov pc, lr + +__armv3_cache_off: + mcr p15, 0, r0, c1, c0 @ turn MMU and cache off + mov r0, #0 + mcr p15, 0, r0, c7, c0 @ invalidate whole cache v3 + mcr p15, 0, r0, c5, c0 @ invalidate whole TLB v3 + mov pc, lr /* * Clean and flush the cache to maintain consistency. @@ -401,13 +431,10 @@ memdump: mov r12, r0 mov r10, lr - mov r1, #8 - bl phex - mov r0, #'\n' - bl putc mov r11, #0 2: mov r0, r11, lsl #2 - mov r1, #4 + add r0, r0, r12 + mov r1, #8 bl phex mov r0, #':' bl putc diff -u --recursive --new-file v2.4.5/linux/arch/arm/boot/compressed/setup-sa1100.S linux/arch/arm/boot/compressed/setup-sa1100.S --- v2.4.5/linux/arch/arm/boot/compressed/setup-sa1100.S Thu Apr 12 12:03:50 2001 +++ linux/arch/arm/boot/compressed/setup-sa1100.S Wed Jun 27 14:12:04 2001 @@ -16,16 +16,16 @@ .text GPIO_BASE: .long 0x90040000 -#define GPLR 0x00 -#define GPDR 0x04 -#define GPSR 0x08 -#define GAFR 0x1c +#define GPLR 0x00 +#define GPDR 0x04 +#define GPSR 0x08 +#define GAFR 0x1c PPC_BASE: .long 0x90060000 -#define PPAR 0x08 +#define PPAR 0x08 IC_BASE: .long 0x90050000 -#define ICMR 0x04 +#define ICMR 0x04 UART1_BASE: .long 0x80010000 UART3_BASE: .long 0x80050000 @@ -95,7 +95,11 @@ @ Initialize UART (if bootloader has not done it yet)... teq r3, #MACH_TYPE_BRUTUS teqne r3, #MACH_TYPE_ASSABET + teqne r3, #MACH_TYPE_ITSY + teqne r3, #MACH_TYPE_OMNIMETER + teqne r3, #MACH_TYPE_JORNADA720 teqne r3, #MACH_TYPE_GRAPHICSCLIENT + teqne r3, #MACH_TYPE_FLEXANET bne skip_uart @ UART3 if Assabet is used with Neponset diff -u --recursive --new-file v2.4.5/linux/arch/arm/boot/compressed/vmlinux.lds.in linux/arch/arm/boot/compressed/vmlinux.lds.in --- v2.4.5/linux/arch/arm/boot/compressed/vmlinux.lds.in Thu Feb 8 16:32:44 2001 +++ linux/arch/arm/boot/compressed/vmlinux.lds.in Mon Jul 2 14:40:14 2001 @@ -24,6 +24,7 @@ *(.fixup) *(.gnu.warning) *(.rodata) + *(.rodata.*) *(.glue_7) *(.glue_7t) input_data = .; diff -u --recursive --new-file v2.4.5/linux/arch/arm/config.in linux/arch/arm/config.in --- v2.4.5/linux/arch/arm/config.in Tue Apr 17 17:19:24 2001 +++ linux/arch/arm/config.in Mon Jun 11 19:15:27 2001 @@ -482,6 +482,9 @@ source drivers/usb/Config.in +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + source net/bluetooth/Config.in +fi mainmenu_option next_comment comment 'Kernel hacking' diff -u --recursive --new-file v2.4.5/linux/arch/arm/kernel/calls.S linux/arch/arm/kernel/calls.S --- v2.4.5/linux/arch/arm/kernel/calls.S Mon Sep 18 15:15:24 2000 +++ linux/arch/arm/kernel/calls.S Wed Jun 27 14:12:04 2001 @@ -13,6 +13,7 @@ #define NR_syscalls 256 #else +__syscall_start: /* 0 */ .long SYMBOL_NAME(sys_ni_syscall) .long SYMBOL_NAME(sys_exit) .long SYMBOL_NAME(sys_fork_wrapper) @@ -176,7 +177,7 @@ /* 160 */ .long SYMBOL_NAME(sys_sched_get_priority_min) .long SYMBOL_NAME(sys_sched_rr_get_interval) .long SYMBOL_NAME(sys_nanosleep) - .long SYMBOL_NAME(sys_mremap) + .long SYMBOL_NAME(sys_arm_mremap) .long SYMBOL_NAME(sys_setresuid16) /* 165 */ .long SYMBOL_NAME(sys_getresuid16) .long SYMBOL_NAME(sys_ni_syscall) @@ -231,8 +232,13 @@ /* 215 */ .long SYMBOL_NAME(sys_setfsuid) .long SYMBOL_NAME(sys_setfsgid) .long SYMBOL_NAME(sys_getdents64) + .long SYMBOL_NAME(sys_pivot_root) + .long SYMBOL_NAME(sys_mincore) +/* 220 */ .long SYMBOL_NAME(sys_madvise) + .long SYMBOL_NAME(sys_fcntl64) +__syscall_end: - .rept NR_syscalls-217 + .rept NR_syscalls - (__syscall_end - __syscall_start) / 4 .long SYMBOL_NAME(sys_ni_syscall) .endr #endif diff -u --recursive --new-file v2.4.5/linux/arch/arm/kernel/ecard.c linux/arch/arm/kernel/ecard.c --- v2.4.5/linux/arch/arm/kernel/ecard.c Thu Apr 12 12:20:31 2001 +++ linux/arch/arm/kernel/ecard.c Wed Jun 27 14:12:04 2001 @@ -1,7 +1,7 @@ /* * linux/arch/arm/kernel/ecard.c * - * Copyright 1995-1998 Russell King + * Copyright 1995-2001 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 @@ -26,7 +26,6 @@ * 17-Apr-1999 RMK Support for EASI Type C cycles. */ #define ECARD_C -#define __KERNEL_SYSCALLS__ #include #include @@ -34,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -382,12 +382,12 @@ * We ignore all calls, unless it is a SYS_RESTART call - power down/halts * will be followed by a SYS_RESTART if ctrl-alt-del is pressed again. */ -static void ecard_reboot(struct notifier_block *me, unsigned long val, void *v) +static int ecard_reboot(struct notifier_block *me, unsigned long val, void *v) { struct ecard_request req; if (val != SYS_RESTART) - return; + return 0; /* * Disable the expansion card interrupt @@ -414,6 +414,7 @@ have_expmask = ~0; __raw_writeb(have_expmask, EXPMASK_ENABLE); #endif + return 0; } static struct notifier_block ecard_reboot_notifier = { diff -u --recursive --new-file v2.4.5/linux/arch/arm/kernel/entry-armv.S linux/arch/arm/kernel/entry-armv.S --- v2.4.5/linux/arch/arm/kernel/entry-armv.S Thu Apr 12 12:20:31 2001 +++ linux/arch/arm/kernel/entry-armv.S Wed Jun 27 14:12:04 2001 @@ -1179,7 +1179,6 @@ stmfd sp!, {r4 - r6, lr} adr r1, .LCvectors @ set up the vectors - mov r0, #0 ldmia r1, {r1, r2, r3, r4, r5, r6, ip, lr} stmia r0, {r1, r2, r3, r4, r5, r6, ip, lr} diff -u --recursive --new-file v2.4.5/linux/arch/arm/kernel/fiq.c linux/arch/arm/kernel/fiq.c --- v2.4.5/linux/arch/arm/kernel/fiq.c Thu Apr 12 12:20:31 2001 +++ linux/arch/arm/kernel/fiq.c Wed Jun 27 14:12:04 2001 @@ -48,7 +48,7 @@ #include #include -#define FIQ_VECTOR 0x1c +#define FIQ_VECTOR (vectors_base() + 0x1c) static unsigned long no_fiq_insn; diff -u --recursive --new-file v2.4.5/linux/arch/arm/kernel/sys_arm.c linux/arch/arm/kernel/sys_arm.c --- v2.4.5/linux/arch/arm/kernel/sys_arm.c Mon Mar 19 12:35:10 2001 +++ linux/arch/arm/kernel/sys_arm.c Wed Jun 27 14:12:04 2001 @@ -55,10 +55,19 @@ unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { - int error = -EBADF; + int error = -EINVAL; struct file * file = NULL; flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); + + /* + * If we are doing a fixed mapping, and address < PAGE_SIZE, + * then deny it. + */ + if (flags & MAP_FIXED && addr < PAGE_SIZE && vectors_base() == 0) + goto out; + + error = -EBADF; if (!(flags & MAP_ANONYMOUS)) { file = fget(fd); if (!file) @@ -99,6 +108,29 @@ error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); out: return error; +} + +asmlinkage unsigned long +sys_arm_mremap(unsigned long addr, unsigned long old_len, + unsigned long new_len, unsigned long flags, + unsigned long new_addr) +{ + unsigned long ret = -EINVAL; + + /* + * If we are doing a fixed mapping, and address < PAGE_SIZE, + * then deny it. + */ + if (flags & MREMAP_FIXED && new_addr < PAGE_SIZE && + vectors_base() == 0) + goto out; + + down_write(¤t->mm->mmap_sem); + ret = do_mremap(addr, old_len, new_len, flags, new_addr); + up_write(¤t->mm->mmap_sem); + +out: + return ret; } /* diff -u --recursive --new-file v2.4.5/linux/arch/arm/kernel/traps.c linux/arch/arm/kernel/traps.c --- v2.4.5/linux/arch/arm/kernel/traps.c Thu Feb 8 16:32:44 2001 +++ linux/arch/arm/kernel/traps.c Wed Jun 27 14:12:04 2001 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -27,6 +28,7 @@ #include #include #include +#include #include "ptrace.h" @@ -143,12 +145,24 @@ c_backtrace(fp, processor_mode(regs)); } +/* + * This is called from SysRq-T (show_task) to display the current + * call trace for each process. Very useful. + */ +void show_trace_task(struct task_struct *tsk) +{ + if (tsk != current) { + unsigned int fp = tsk->thread.save->fp; + c_backtrace(fp, 0x10); + } +} + spinlock_t die_lock = SPIN_LOCK_UNLOCKED; /* * This function is protected against re-entrancy. */ -void die(const char *str, struct pt_regs *regs, int err) +NORET_TYPE void die(const char *str, struct pt_regs *regs, int err) { struct task_struct *tsk = current; @@ -173,9 +187,9 @@ fs = get_fs(); set_fs(KERNEL_DS); - dump_instr(regs); dump_stack(tsk, (unsigned long)(regs + 1)); dump_backtrace(regs, tsk); + dump_instr(regs); set_fs(fs); } @@ -448,9 +462,12 @@ void __init trap_init(void) { - extern void __trap_init(void); + extern void __trap_init(void *); - __trap_init(); + __trap_init((void *)vectors_base()); + if (vectors_base() != 0) + printk("Relocating machine vectors to 0x%08x\n", + vectors_base()); #ifdef CONFIG_CPU_32 modify_domain(DOMAIN_USER, DOMAIN_CLIENT); #endif diff -u --recursive --new-file v2.4.5/linux/arch/arm/mach-ebsa110/arch.c linux/arch/arm/mach-ebsa110/arch.c --- v2.4.5/linux/arch/arm/mach-ebsa110/arch.c Thu Apr 12 12:20:31 2001 +++ linux/arch/arm/mach-ebsa110/arch.c Wed Jun 27 14:12:04 2001 @@ -1,10 +1,7 @@ /* * linux/arch/arm/mach-ebsa110/arch.c * - * Architecture specific fixups. This is where any - * parameters in the params struct are fixed up, or - * any additional architecture specific information - * is pulled from the params struct. + * Architecture specific fixups. */ #include #include diff -u --recursive --new-file v2.4.5/linux/arch/arm/mach-ebsa110/hardware.h linux/arch/arm/mach-ebsa110/hardware.h --- v2.4.5/linux/arch/arm/mach-ebsa110/hardware.h Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/mach-ebsa110/hardware.h Wed Jun 27 14:12:04 2001 @@ -0,0 +1,16 @@ +/* + * linux/arch/arm/mach-ebsa110/hardware.h + * + * Copyright (C) 2001 Russell King + * + * Local hardware definitions. + */ +#ifndef HARDWARE_H +#define HARDWARE_H + +#define IRQ_MASK 0xfe000000 /* read */ +#define IRQ_MSET 0xfe000000 /* write */ +#define IRQ_STAT 0xff000000 /* read */ +#define IRQ_MCLR 0xff000000 /* write */ + +#endif diff -u --recursive --new-file v2.4.5/linux/arch/arm/mach-ebsa110/io.c linux/arch/arm/mach-ebsa110/io.c --- v2.4.5/linux/arch/arm/mach-ebsa110/io.c Sun May 20 12:11:38 2001 +++ linux/arch/arm/mach-ebsa110/io.c Wed Jun 27 14:12:04 2001 @@ -188,6 +188,7 @@ u32 __inl(int port) { BUG(); + return 0; } EXPORT_SYMBOL(__inb); diff -u --recursive --new-file v2.4.5/linux/arch/arm/mm/consistent.c linux/arch/arm/mm/consistent.c --- v2.4.5/linux/arch/arm/mm/consistent.c Thu Apr 12 12:20:31 2001 +++ linux/arch/arm/mm/consistent.c Wed Jun 27 14:12:04 2001 @@ -67,18 +67,21 @@ #endif /* - * free wasted pages. We skip the first page since - * we know that it will have count = 1 and won't - * require freeing. + * free wasted pages. We skip the first page since we know + * that it will have count = 1 and won't require freeing. + * We also mark the pages in use as reserved so that + * remap_page_range works. */ page = virt_to_page(virt); free = page + (size >> PAGE_SHIFT); end = page + (1 << order); - while (++page < end) { + for (; page < end; page++) { set_page_count(page, 1); if (page >= free) __free_page(page); + else + SetPageReserved(page); } return ret; @@ -108,10 +111,26 @@ * free a page as defined by the above mapping. We expressly forbid * calling this from interrupt context. */ -void consistent_free(void *vaddr) +void consistent_free(void *vaddr, size_t size, dma_addr_t handle) { + struct page *page, *end; + void *virt; + if (in_interrupt()) BUG(); + + virt = bus_to_virt(handle); + + /* + * More messing around with the MM internals. This is + * sick, but then so is remap_page_range(). + */ + size = PAGE_ALIGN(size); + page = virt_to_page(virt); + end = page + (size >> PAGE_SHIFT); + + for (; page < end; page++) + ClearPageReserved(page); __iounmap(vaddr); } diff -u --recursive --new-file v2.4.5/linux/arch/arm/mm/fault-armv.c linux/arch/arm/mm/fault-armv.c --- v2.4.5/linux/arch/arm/mm/fault-armv.c Wed May 16 15:25:16 2001 +++ linux/arch/arm/mm/fault-armv.c Wed Jun 27 14:12:04 2001 @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -45,9 +46,8 @@ * * Speed optimisations and better fault handling by Russell King. * - * NOTE!!! This is not portable onto the ARM6/ARM7 processors yet. Also, - * it seems to give a severe performance impact (1 abort/ms - NW runs at - * ARM6 speeds) with GCC 2.7.2.2 - needs checking with a later GCC/EGCS. + * *** NOTE *** + * This code is not portable to processors with late data abort handling. */ #define CODING_BITS(i) (i & 0x0e000000) @@ -57,6 +57,8 @@ #define LDST_W_BIT(i) (i & (1 << 21)) /* Writeback */ #define LDST_L_BIT(i) (i & (1 << 20)) /* Load */ +#define LDST_P_EQ_U(i) ((((i) ^ ((i) >> 1)) & (1 << 23)) == 0) + #define LDSTH_I_BIT(i) (i & (1 << 22)) /* half-word immed */ #define LDM_S_BIT(i) (i & (1 << 22)) /* write CPSR from SPSR */ @@ -336,29 +338,48 @@ return TYPE_FAULT; } +/* + * LDM/STM alignment handler. + * + * There are 4 variants of this instruction: + * + * B = rn pointer before instruction, A = rn pointer after instruction + * ------ increasing address -----> + * | | r0 | r1 | ... | rx | | + * PU = 01 B A + * PU = 11 B A + * PU = 00 A B + * PU = 10 A B + */ static int do_alignment_ldmstm(unsigned long addr, unsigned long instr, struct pt_regs *regs) { unsigned int rd, rn, correction, nr_regs, regbits; - unsigned long eaddr; - - correction = 4; /* sometimes 8 on ARMv3 */ - regs->ARM_pc += correction; - - rd = RD_BITS(instr); - rn = RN_BITS(instr); - eaddr = regs->uregs[rn]; + unsigned long eaddr, newaddr; if (LDM_S_BIT(instr)) goto bad; + correction = 4; /* processor implementation defined */ + regs->ARM_pc += correction; + ai_multi += 1; + /* count the number of registers in the mask to be transferred */ for (regbits = REGMASK_BITS(instr), nr_regs = 0; regbits; regbits >>= 1) nr_regs += 4; + rn = RN_BITS(instr); + newaddr = eaddr = regs->uregs[rn]; + if (!LDST_U_BIT(instr)) - eaddr -= nr_regs; + nr_regs = -nr_regs; + newaddr += nr_regs; + if (!LDST_U_BIT(instr)) + eaddr = newaddr; + + if (LDST_P_EQ_U(instr)) /* U = P */ + eaddr += 4; /* * This is a "hint" - we already have eaddr worked out by the @@ -369,34 +390,23 @@ "addr = %08lx, eaddr = %08lx\n", instruction_pointer(regs), instr, addr, eaddr); - if ((LDST_U_BIT(instr) == 0 && LDST_P_BIT(instr) == 0) || - (LDST_U_BIT(instr) && LDST_P_BIT(instr))) - eaddr += 4; - for (regbits = REGMASK_BITS(instr), rd = 0; regbits; regbits >>= 1, rd += 1) if (regbits & 1) { - if (LDST_L_BIT(instr)) { + if (LDST_L_BIT(instr)) get32_unaligned_check(regs->uregs[rd], eaddr); - if (rd == 15) - correction = 0; - } else + else put32_unaligned_check(regs->uregs[rd], eaddr); eaddr += 4; } - if (LDST_W_BIT(instr)) { - if (LDST_P_BIT(instr) && !LDST_U_BIT(instr)) - eaddr -= nr_regs; - else if (LDST_P_BIT(instr)) - eaddr -= 4; - else if (!LDST_U_BIT(instr)) - eaddr -= 4 + nr_regs; - regs->uregs[rn] = eaddr; - } - regs->ARM_pc -= correction; + if (LDST_W_BIT(instr)) + regs->uregs[rn] = newaddr; + if (!LDST_L_BIT(instr) || !(REGMASK_BITS(instr) & (1 << 15))) + regs->ARM_pc -= correction; return TYPE_DONE; fault: + regs->ARM_pc -= correction; return TYPE_FAULT; bad: diff -u --recursive --new-file v2.4.5/linux/arch/arm/mm/mm-armv.c linux/arch/arm/mm/mm-armv.c --- v2.4.5/linux/arch/arm/mm/mm-armv.c Thu Apr 12 12:20:31 2001 +++ linux/arch/arm/mm/mm-armv.c Wed Jun 27 14:12:04 2001 @@ -79,37 +79,40 @@ memzero(new_pgd, FIRST_KERNEL_PGD_NR * sizeof(pgd_t)); - /* - * This lock is here just to satisfy pmd_alloc and pte_lock - */ - spin_lock(&mm->page_table_lock); + init_pgd = pgd_offset_k(0); - /* - * On ARM, first page must always be allocated since it contains - * the machine vectors. - */ - new_pmd = pmd_alloc(mm, new_pgd, 0); - if (!new_pmd) - goto no_pmd; - - new_pte = pte_alloc(mm, new_pmd, 0); - if (!new_pte) - goto no_pte; + if (vectors_base() == 0) { + init_pmd = pmd_offset(init_pgd, 0); + init_pte = pte_offset(init_pmd, 0); + + /* + * This lock is here just to satisfy pmd_alloc and pte_lock + */ + spin_lock(&mm->page_table_lock); + + /* + * On ARM, first page must always be allocated since it + * contains the machine vectors. + */ + new_pmd = pmd_alloc(mm, new_pgd, 0); + if (!new_pmd) + goto no_pmd; + + new_pte = pte_alloc(mm, new_pmd, 0); + if (!new_pte) + goto no_pte; - init_pgd = pgd_offset_k(0); - init_pmd = pmd_offset(init_pgd, 0); - init_pte = pte_offset(init_pmd, 0); + set_pte(new_pte, *init_pte); - set_pte(new_pte, *init_pte); + spin_unlock(&mm->page_table_lock); + } /* * Copy over the kernel and IO PGD entries */ - memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR, + memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR, (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t)); - spin_unlock(&mm->page_table_lock); - /* * FIXME: this should not be necessary */ @@ -134,25 +137,26 @@ void free_pgd_slow(pgd_t *pgd) { - if (pgd) { /* can pgd be NULL? */ - pmd_t *pmd; - pte_t *pte; - - /* pgd is always present and good */ - pmd = (pmd_t *)pgd; - if (pmd_none(*pmd)) - goto free; - if (pmd_bad(*pmd)) { - pmd_ERROR(*pmd); - pmd_clear(pmd); - goto free; - } + pmd_t *pmd; + pte_t *pte; - pte = pte_offset(pmd, 0); + if (!pgd) + return; + + /* pgd is always present and good */ + pmd = (pmd_t *)pgd; + if (pmd_none(*pmd)) + goto free; + if (pmd_bad(*pmd)) { + pmd_ERROR(*pmd); pmd_clear(pmd); - pte_free(pte); - pmd_free(pmd); + goto free; } + + pte = pte_offset(pmd, 0); + pmd_clear(pmd); + pte_free(pte); + pmd_free(pmd); free: free_pages((unsigned long) pgd, 2); } @@ -296,17 +300,6 @@ init_maps = p = alloc_bootmem_low_pages(PAGE_SIZE); - p->physical = virt_to_phys(init_maps); - p->virtual = 0; - p->length = PAGE_SIZE; - p->domain = DOMAIN_USER; - p->prot_read = 0; - p->prot_write = 0; - p->cacheable = 1; - p->bufferable = 0; - - p ++; - for (i = 0; i < mi->nr_banks; i++) { if (mi->bank[i].size == 0) continue; @@ -350,16 +343,9 @@ #endif /* - * We may have a mapping in virtual address 0. - * Clear it out. - */ - clear_mapping(0); - - /* * Go through the initial mappings, but clear out any * pgdir entries that are not in the description. */ - i = 0; q = init_maps; do { if (address < q->virtual || q == p) { @@ -374,6 +360,21 @@ q ++; } } while (address != 0); + + /* + * Create a mapping for the machine vectors at virtual address 0 + * or 0xffff0000. We should always try the high mapping. + */ + init_maps->physical = virt_to_phys(init_maps); + init_maps->virtual = vectors_base(); + init_maps->length = PAGE_SIZE; + init_maps->domain = DOMAIN_USER; + init_maps->prot_read = 0; + init_maps->prot_write = 0; + init_maps->cacheable = 1; + init_maps->bufferable = 0; + + create_mapping(init_maps); flush_cache_all(); } diff -u --recursive --new-file v2.4.5/linux/arch/arm/mm/mm-l7200.c linux/arch/arm/mm/mm-l7200.c --- v2.4.5/linux/arch/arm/mm/mm-l7200.c Thu Apr 12 12:20:31 2001 +++ linux/arch/arm/mm/mm-l7200.c Wed Jun 27 14:12:04 2001 @@ -10,7 +10,6 @@ #include #include #include -#include #include diff -u --recursive --new-file v2.4.5/linux/arch/arm/tools/Makefile linux/arch/arm/tools/Makefile --- v2.4.5/linux/arch/arm/tools/Makefile Tue Mar 6 19:44:35 2001 +++ linux/arch/arm/tools/Makefile Wed Jun 27 14:12:04 2001 @@ -16,7 +16,7 @@ $(TOPDIR)/include/asm-arm/constants.h: constants-hdr getconstants.c $(CC) $(CFLAGS) -S -o - getconstants.c | \ - sed 's/^\(#define .* \)#\(.*\)/\1\2/;/^#define/!d' | \ + sed 's/^\(#define .* \)[#$$]\(.*\)/\1\2/;/^#define/!d' | \ cat constants-hdr - > $@.tmp cmp $@.tmp $@ >/dev/null 2>&1 || mv $@.tmp $@; $(RM) $@.tmp diff -u --recursive --new-file v2.4.5/linux/arch/arm/tools/getconstants.c linux/arch/arm/tools/getconstants.c --- v2.4.5/linux/arch/arm/tools/getconstants.c Wed Apr 11 19:02:27 2001 +++ linux/arch/arm/tools/getconstants.c Wed Jun 27 14:12:04 2001 @@ -60,7 +60,5 @@ DEFN("PAGE_SZ", PAGE_SIZE); -DEFN("KSWI_BASE", 0x900000); -DEFN("KSWI_SYS_BASE", 0x9f0000); DEFN("SYS_ERROR0", 0x9f0000); } diff -u --recursive --new-file v2.4.5/linux/arch/arm/tools/mach-types linux/arch/arm/tools/mach-types --- v2.4.5/linux/arch/arm/tools/mach-types Wed Apr 11 19:02:27 2001 +++ linux/arch/arm/tools/mach-types Wed Jun 27 14:12:04 2001 @@ -6,7 +6,7 @@ # To add an entry into this database, please see Documentation/arm/README, # or contact rmk@arm.linux.org.uk # -# Last update: Sat Apr 7 09:45:09 2001 +# Last update: Sun Jun 17 00:53:17 2001 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -63,7 +63,7 @@ citygo SA1100_CITYGO CITYGO 51 pfs168 SA1100_PFS168 PFS168 52 spot SA1100_SPOT SPOT 53 -flexanet ARCH_FLEXANET FLEXANET 54 +flexanet SA1100_FLEXANET FLEXANET 54 webpal ARCH_WEBPAL WEBPAL 55 linpda SA1100_LINPDA LINPDA 56 anakin ARCH_ANAKIN ANAKIN 57 @@ -77,6 +77,26 @@ xfile SA1100_XFILE XFILE 65 accelent_ep9312 ARCH_ACCELENT_EP9312 ACCELENT_EP9312 66 ic200 ARCH_IC200 IC200 67 +creditlart SA1100_CREDITLART CREDITLART 68 +htm SA1100_HTM HTM 69 +iq80310 ARCH_IQ80310 IQ80310 70 +freebot SA1100_FREEBOT FREEBOT 71 +entel ARCH_ENTEL ENTEL 72 +enp3510 ARCH_ENP3510 ENP3510 73 +trizeps SA1100_TRIZEPS TRIZEPS 74 +nesa SA1100_NESA NESA 75 +venus ARCH_VENUS VENUS 76 +tardis ARCH_TARDIS TARDIS 77 +mercury ARCH_MERCURY MERCURY 78 +empeg SA1100_EMPEG EMPEG 79 +adi_eb ARCH_I80200FCC I80200FCC 80 +itt_cpb SA1100_ITT_CPB ITT_CPB 81 +sa1110_svc ARCH_SA1110_SVC SA1110_SVC 82 +alpha2 SA1100_ALPHA2 ALPHA2 84 +alpha1 SA1100_ALPHA1 ALPHA1 85 +netarm ARCH_NETARM NETARM 86 +simpad SA1100_SIMPAD SIMPAD 87 +pda1 ARCH_PDA1 PDA1 88 +lubbock ARCH_LUBBOCK LUBBOCK 89 # The following are unallocated -empeg SA1100_EMPEG EMPEG diff -u --recursive --new-file v2.4.5/linux/arch/arm/vmlinux-armo.lds.in linux/arch/arm/vmlinux-armo.lds.in --- v2.4.5/linux/arch/arm/vmlinux-armo.lds.in Thu Feb 8 16:32:44 2001 +++ linux/arch/arm/vmlinux-armo.lds.in Mon Jul 2 14:40:14 2001 @@ -47,6 +47,7 @@ *(.gnu.warning) *(.text.lock) /* out-of-line lock text */ *(.rodata) + *(.rodata.*) *(.glue_7) *(.glue_7t) *(.kstrtab) diff -u --recursive --new-file v2.4.5/linux/arch/arm/vmlinux-armv.lds.in linux/arch/arm/vmlinux-armv.lds.in --- v2.4.5/linux/arch/arm/vmlinux-armv.lds.in Wed May 16 15:25:16 2001 +++ linux/arch/arm/vmlinux-armv.lds.in Mon Jul 2 14:40:14 2001 @@ -42,6 +42,7 @@ *(.gnu.warning) *(.text.lock) /* out-of-line lock text */ *(.rodata) + *(.rodata.*) *(.glue_7) *(.glue_7t) *(.got) /* Global offset table */ diff -u --recursive --new-file v2.4.5/linux/arch/cris/boot/compressed/decompress.ld linux/arch/cris/boot/compressed/decompress.ld --- v2.4.5/linux/arch/cris/boot/compressed/decompress.ld Fri Apr 6 10:42:55 2001 +++ linux/arch/cris/boot/compressed/decompress.ld Mon Jul 2 14:40:14 2001 @@ -13,6 +13,7 @@ _stext = . ; *(.text) *(.rodata) + *(.rodata.*) _etext = . ; } > dram .data : diff -u --recursive --new-file v2.4.5/linux/arch/cris/cris.ld linux/arch/cris/cris.ld --- v2.4.5/linux/arch/cris/cris.ld Tue May 1 16:04:56 2001 +++ linux/arch/cris/cris.ld Mon Jul 2 14:40:14 2001 @@ -24,7 +24,7 @@ *(.fixup) *(.text.__*) *(.rodata) - *(.rodata.__*) + *(.rodata.*) } . = ALIGN(4); /* Exception table */ diff -u --recursive --new-file v2.4.5/linux/arch/cris/drivers/ide.c linux/arch/cris/drivers/ide.c --- v2.4.5/linux/arch/cris/drivers/ide.c Fri Apr 6 10:42:55 2001 +++ linux/arch/cris/drivers/ide.c Mon Jun 11 19:15:27 2001 @@ -1,4 +1,4 @@ -/* $Id: ide.c,v 1.9 2001/03/01 13:11:18 bjornw Exp $ +/* $Id: ide.c,v 1.16 2001/04/05 08:30:07 matsfg Exp $ * * Etrax specific IDE functions, like init and PIO-mode setting etc. * Almost the entire ide.c is used for the rest of the Etrax ATA driver. @@ -8,6 +8,28 @@ * Mikael Starvik (pio setup stuff) * * $Log: ide.c,v $ + * Revision 1.16 2001/04/05 08:30:07 matsfg + * Corrected cse1 and csp0 reset. + * + * Revision 1.15 2001/04/04 14:34:06 bjornw + * Re-instated code that mysteriously disappeared during review updates. + * + * Revision 1.14 2001/04/04 13:45:12 matsfg + * Calls REG_SHADOW_SET for cse1 reset so only the resetbit is affected + * + * Revision 1.13 2001/04/04 13:26:40 matsfg + * memmapping is done in init.c + * + * Revision 1.12 2001/04/04 11:37:56 markusl + * Updated according to review remarks + * + * Revision 1.11 2001/03/29 12:49:14 matsfg + * Changed check for ata_tot_size from >= to >. + * Sets sw_len to 0 if size is exactly 65536. + * + * Revision 1.10 2001/03/16 09:39:30 matsfg + * Support for reset on port CSP0 + * * Revision 1.9 2001/03/01 13:11:18 bjornw * 100 -> HZ * @@ -158,6 +180,10 @@ #define ATA_PIO0_STROBE 19 #define ATA_PIO0_HOLD 4 +static int e100_dmaproc (ide_dma_action_t func, ide_drive_t *drive); +static void e100_ideproc (ide_ide_action_t func, ide_drive_t *drive, + void *buffer, unsigned int length); + /* * good_dma_drives() lists the model names (from "hdparm -i") * of drives which do not support mword2 DMA but which are @@ -174,7 +200,7 @@ unsigned long flags; pio = 4; - //pio = ide_get_best_pio_mode(drive, pio, 4, NULL); + /* pio = ide_get_best_pio_mode(drive, pio, 4, NULL); */ save_flags(flags); cli(); @@ -226,10 +252,6 @@ restore_flags(flags); } -static int e100_dmaproc (ide_dma_action_t func, ide_drive_t *drive); /* defined below */ -static void e100_ideproc (ide_ide_action_t func, ide_drive_t *drive, - void *buffer, unsigned int length); /* defined below */ - void __init init_e100_ide (void) { @@ -277,26 +299,23 @@ *R_GEN_CONFIG = genconfig_shadow; #ifdef CONFIG_ETRAX_IDE_CSE1_16_RESET -#ifndef CONFIG_CRIS_LOW_MAP - /* remap the I/O-mapped reset-bit from CSE1 to something inside our kernel space */ - reset_addr = (unsigned long *)ioremap((unsigned long)(MEM_CSE1_START | - MEM_NON_CACHEABLE), 16); - *reset_addr = 0; -#else - /* LOW_MAP, can't do the ioremap, but it's already mapped straight over */ - reset_addr = (unsigned long *)(MEM_CSE1_START | MEM_NON_CACHEABLE); - *reset_addr = 0; + init_ioremap(); + REG_SHADOW_SET(port_cse1_addr, port_cse1_shadow, 16, 0); #endif + +#ifdef CONFIG_ETRAX_IDE_CSP0_8_RESET + init_ioremap(); + REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, 8, 0); #endif /* wait some */ - - dummy = 1; - dummy = 2; - dummy = 3; + udelay(25); #ifdef CONFIG_ETRAX_IDE_CSE1_16_RESET - *reset_addr = 1 << 16; + REG_SHADOW_SET(port_cse1_addr, port_cse1_shadow, 16, 1); +#endif +#ifdef CONFIG_ETRAX_IDE_CSP0_8_RESET + REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, 8, 1); #endif #ifdef CONFIG_ETRAX_IDE_G27_RESET *R_PORT_G_DATA = 0; /* de-assert bus-reset */ @@ -349,7 +368,6 @@ e100_atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount) { ide_ioreg_t data_reg = IDE_DATA_REG; - unsigned long status; D(printk("atapi_input_bytes, dreg 0x%x, buffer 0x%x, count %d\n", data_reg, buffer, bytecount)); @@ -376,7 +394,7 @@ /* initiate a multi word dma read using PIO handshaking */ - *R_ATA_TRANSFER_CNT = bytecount >> 1; + *R_ATA_TRANSFER_CNT = IO_FIELD(R_ATA_TRANSFER_CNT, count, bytecount >> 1); *R_ATA_CTRL_DATA = data_reg | IO_STATE(R_ATA_CTRL_DATA, rw, read) | @@ -390,35 +408,38 @@ LED_DISK_READ(1); WAIT_DMA(3); LED_DISK_READ(0); - + #if 0 - /* old polled transfer code */ - - /* initiate a multi word read */ - - *R_ATA_TRANSFER_CNT = wcount << 1; - - *R_ATA_CTRL_DATA = data_reg | - IO_STATE(R_ATA_CTRL_DATA, rw, read) | - IO_STATE(R_ATA_CTRL_DATA, src_dst, register) | - IO_STATE(R_ATA_CTRL_DATA, handsh, pio) | - IO_STATE(R_ATA_CTRL_DATA, multi, on) | - IO_STATE(R_ATA_CTRL_DATA, dma_size, word); - - /* svinto has a latency until the busy bit actually is set */ - - nop(); nop(); - nop(); nop(); - nop(); nop(); - nop(); nop(); - nop(); nop(); - - /* unit should be busy during multi transfer */ - while((status = *R_ATA_STATUS_DATA) & IO_MASK(R_ATA_STATUS_DATA, busy)) { - while(!(status & IO_MASK(R_ATA_STATUS_DATA, dav))) - status = *R_ATA_STATUS_DATA; - *ptr++ = (unsigned short)(status & 0xffff); - } + /* old polled transfer code + * this should be moved into a new function that can do polled + * transfers if DMA is not available + */ + + /* initiate a multi word read */ + + *R_ATA_TRANSFER_CNT = wcount << 1; + + *R_ATA_CTRL_DATA = data_reg | + IO_STATE(R_ATA_CTRL_DATA, rw, read) | + IO_STATE(R_ATA_CTRL_DATA, src_dst, register) | + IO_STATE(R_ATA_CTRL_DATA, handsh, pio) | + IO_STATE(R_ATA_CTRL_DATA, multi, on) | + IO_STATE(R_ATA_CTRL_DATA, dma_size, word); + + /* svinto has a latency until the busy bit actually is set */ + + nop(); nop(); + nop(); nop(); + nop(); nop(); + nop(); nop(); + nop(); nop(); + + /* unit should be busy during multi transfer */ + while((status = *R_ATA_STATUS_DATA) & IO_MASK(R_ATA_STATUS_DATA, busy)) { + while(!(status & IO_MASK(R_ATA_STATUS_DATA, dav))) + status = *R_ATA_STATUS_DATA; + *ptr++ = (unsigned short)(status & 0xffff); + } #endif } @@ -426,8 +447,6 @@ e100_atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount) { ide_ioreg_t data_reg = IDE_DATA_REG; - unsigned short *ptr = (unsigned short *)buffer; - unsigned long ctrl; D(printk("atapi_output_bytes, dreg 0x%x, buffer 0x%x, count %d\n", data_reg, buffer, bytecount)); @@ -454,7 +473,7 @@ /* initiate a multi word dma write using PIO handshaking */ - *R_ATA_TRANSFER_CNT = bytecount >> 1; + *R_ATA_TRANSFER_CNT = IO_FIELD(R_ATA_TRANSFER_CNT, count, bytecount >> 1); *R_ATA_CTRL_DATA = data_reg | IO_STATE(R_ATA_CTRL_DATA, rw, write) | @@ -470,40 +489,42 @@ LED_DISK_WRITE(0); #if 0 - /* old polled write code */ + /* old polled write code - see comment in input_bytes */ - while(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy)); /* wait for busy flag */ + /* wait for busy flag */ + while(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy)); - /* initiate a multi word write */ + /* initiate a multi word write */ - *R_ATA_TRANSFER_CNT = bytecount >> 1; + *R_ATA_TRANSFER_CNT = bytecount >> 1; - ctrl = data_reg | - IO_STATE(R_ATA_CTRL_DATA, rw, write) | - IO_STATE(R_ATA_CTRL_DATA, src_dst, register) | - IO_STATE(R_ATA_CTRL_DATA, handsh, pio) | - IO_STATE(R_ATA_CTRL_DATA, multi, on) | - IO_STATE(R_ATA_CTRL_DATA, dma_size, word); - - LED_DISK_WRITE(1); - - /* Etrax will set busy = 1 until the multi pio transfer has finished - * and tr_rdy = 1 after each succesful word transfer. - * When the last byte has been transferred Etrax will first set tr_tdy = 1 - * and then busy = 0 (not in the same cycle). If we read busy before it - * has been set to 0 we will think that we should transfer more bytes - * and then tr_rdy would be 0 forever. This is solved by checking busy - * in the inner loop. - */ - - do { - *R_ATA_CTRL_DATA = ctrl | *ptr++; - while(!(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, tr_rdy)) && - (*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy))); - } while(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy)); + ctrl = data_reg | + IO_STATE(R_ATA_CTRL_DATA, rw, write) | + IO_STATE(R_ATA_CTRL_DATA, src_dst, register) | + IO_STATE(R_ATA_CTRL_DATA, handsh, pio) | + IO_STATE(R_ATA_CTRL_DATA, multi, on) | + IO_STATE(R_ATA_CTRL_DATA, dma_size, word); + + LED_DISK_WRITE(1); + + /* Etrax will set busy = 1 until the multi pio transfer has finished + * and tr_rdy = 1 after each succesful word transfer. + * When the last byte has been transferred Etrax will first set tr_tdy = 1 + * and then busy = 0 (not in the same cycle). If we read busy before it + * has been set to 0 we will think that we should transfer more bytes + * and then tr_rdy would be 0 forever. This is solved by checking busy + * in the inner loop. + */ + + do { + *R_ATA_CTRL_DATA = ctrl | *ptr++; + while(!(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, tr_rdy)) && + (*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy))); + } while(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy)); + + LED_DISK_WRITE(0); +#endif - LED_DISK_WRITE(0); -#endif } /* @@ -604,7 +625,7 @@ those blocks that were actually set-up for transfer. */ - if(ata_tot_size + size >= 131072) { + if(ata_tot_size + size > 131072) { printk("too large total ATA DMA request, %d + %d!\n", ata_tot_size, size); return 1; } @@ -625,7 +646,12 @@ addr += 65536; } /* ok we want to do IO at addr, size bytes. set up a new descriptor entry */ - ata_descrs[count].sw_len = size; + if(size == 65536) { + ata_descrs[count].sw_len = 0; /* 0 means 65536, this is a 16-bit field */ + } + else { + ata_descrs[count].sw_len = size; + } ata_descrs[count].ctrl = 0; ata_descrs[count].buf = addr; ata_descrs[count].next = virt_to_phys(&ata_descrs[count + 1]); @@ -793,9 +819,11 @@ /* initiate a multi word dma read using DMA handshaking */ - *R_ATA_TRANSFER_CNT = ata_tot_size >> 1; + *R_ATA_TRANSFER_CNT = + IO_FIELD(R_ATA_TRANSFER_CNT, count, ata_tot_size >> 1); - *R_ATA_CTRL_DATA = IDE_DATA_REG | + *R_ATA_CTRL_DATA = + IO_FIELD(R_ATA_CTRL_DATA, data, IDE_DATA_REG) | IO_STATE(R_ATA_CTRL_DATA, rw, read) | IO_STATE(R_ATA_CTRL_DATA, src_dst, dma) | IO_STATE(R_ATA_CTRL_DATA, handsh, dma) | @@ -834,9 +862,11 @@ /* initiate a multi word dma write using DMA handshaking */ - *R_ATA_TRANSFER_CNT = ata_tot_size >> 1; + *R_ATA_TRANSFER_CNT = + IO_FIELD(R_ATA_TRANSFER_CNT, count, ata_tot_size >> 1); - *R_ATA_CTRL_DATA = IDE_DATA_REG | + *R_ATA_CTRL_DATA = + IO_FIELD(R_ATA_CTRL_DATA, data, IDE_DATA_REG) | IO_STATE(R_ATA_CTRL_DATA, rw, write) | IO_STATE(R_ATA_CTRL_DATA, src_dst, dma) | IO_STATE(R_ATA_CTRL_DATA, handsh, dma) | diff -u --recursive --new-file v2.4.5/linux/arch/i386/boot/tools/build.c linux/arch/i386/boot/tools/build.c --- v2.4.5/linux/arch/i386/boot/tools/build.c Mon Mar 13 09:35:06 2000 +++ linux/arch/i386/boot/tools/build.c Mon Jul 2 13:56:40 2001 @@ -154,7 +154,7 @@ if (sys_size > (is_big_kernel ? 0x28000 : DEF_SYSSIZE)) die("System is too big. Try using %smodules.", is_big_kernel ? "" : "bzImage or "); - if (sys_size > 0xffff) + if (sys_size > 0xefff) fprintf(stderr,"warning: kernel is too big for standalone boot " "from floppy\n"); while (sz > 0) { diff -u --recursive --new-file v2.4.5/linux/arch/i386/config.in linux/arch/i386/config.in --- v2.4.5/linux/arch/i386/config.in Thu May 24 15:14:08 2001 +++ linux/arch/i386/config.in Wed Jun 20 17:47:39 2001 @@ -245,6 +245,10 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then dep_bool ' ACPI support' CONFIG_ACPI $CONFIG_PM + + if [ "$CONFIG_ACPI" != "n" ]; then + source drivers/acpi/Config.in + fi fi dep_tristate ' Advanced Power Management BIOS support' CONFIG_APM $CONFIG_PM @@ -374,6 +378,10 @@ endmenu source drivers/usb/Config.in + +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + source net/bluetooth/Config.in +fi mainmenu_option next_comment comment 'Kernel hacking' diff -u --recursive --new-file v2.4.5/linux/arch/i386/defconfig linux/arch/i386/defconfig --- v2.4.5/linux/arch/i386/defconfig Tue May 22 10:53:06 2001 +++ linux/arch/i386/defconfig Mon Jul 2 16:08:28 2001 @@ -192,7 +192,7 @@ # CONFIG_BLK_DEV_HD_IDE is not set # CONFIG_BLK_DEV_HD is not set CONFIG_BLK_DEV_IDEDISK=y -# CONFIG_IDEDISK_MULTI_MODE is not set +CONFIG_IDEDISK_MULTI_MODE=y # CONFIG_BLK_DEV_IDEDISK_VENDOR is not set # CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set # CONFIG_BLK_DEV_IDEDISK_IBM is not set @@ -217,10 +217,10 @@ CONFIG_BLK_DEV_RZ1000=y CONFIG_BLK_DEV_IDEPCI=y CONFIG_IDEPCI_SHARE_IRQ=y -# CONFIG_BLK_DEV_IDEDMA_PCI is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_OFFBOARD is not set -# CONFIG_IDEDMA_PCI_AUTO is not set -# CONFIG_BLK_DEV_IDEDMA is not set +CONFIG_IDEDMA_PCI_AUTO=y +CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_PCI_WIP is not set # CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set # CONFIG_BLK_DEV_AEC62XX is not set @@ -235,8 +235,8 @@ # CONFIG_BLK_DEV_HPT34X is not set # CONFIG_HPT34X_AUTODMA is not set # CONFIG_BLK_DEV_HPT366 is not set -# CONFIG_BLK_DEV_PIIX is not set -# CONFIG_PIIX_TUNING is not set +CONFIG_BLK_DEV_PIIX=y +CONFIG_PIIX_TUNING=y # CONFIG_BLK_DEV_NS87415 is not set # CONFIG_BLK_DEV_OPTI621 is not set # CONFIG_BLK_DEV_PDC202XX is not set @@ -247,7 +247,8 @@ # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set # CONFIG_IDE_CHIPSETS is not set -# CONFIG_IDEDMA_AUTO is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_IDEDMA_IVB is not set # CONFIG_DMA_NONPCI is not set CONFIG_BLK_DEV_IDE_MODES=y @@ -362,10 +363,18 @@ # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y +# CONFIG_ARM_AM79C961A is not set +# CONFIG_SUNLANCE is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNLANCE is not set +# CONFIG_SUNGEM is not set # CONFIG_NET_VENDOR_3COM is not set # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_AT1700 is not set # CONFIG_DEPCA is not set # CONFIG_HP100 is not set # CONFIG_NET_ISA is not set @@ -376,11 +385,12 @@ # CONFIG_APRICOT is not set # CONFIG_CS89x0 is not set # CONFIG_TULIP is not set +# CONFIG_TULIP_MWI is not set +# CONFIG_TULIP_MMIO is not set # CONFIG_DE4X5 is not set # CONFIG_DGRS is not set # CONFIG_DM9102 is not set CONFIG_EEPRO100=y -# CONFIG_EEPRO100_PM is not set # CONFIG_LNE390 is not set # CONFIG_FEALNX is not set # CONFIG_NATSEMI is not set @@ -397,16 +407,19 @@ # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set # CONFIG_WINBOND_840 is not set -# CONFIG_HAPPYMEAL is not set # CONFIG_NET_POCKET is not set # # Ethernet (1000 Mbit) # # CONFIG_ACENIC is not set +# CONFIG_ACENIC_OMIT_TIGON_I is not set +# CONFIG_MYRI_SBUS is not set # CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set # CONFIG_SK98LIN is not set # CONFIG_FDDI is not set +# CONFIG_PLIP is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -445,7 +458,6 @@ # CONFIG_PCMCIA_NETWAVE is not set # CONFIG_PCMCIA_WAVELAN is not set # CONFIG_AIRONET4500_CS is not set -CONFIG_PCMCIA_NETCARD=y # # Amateur Radio support @@ -530,6 +542,7 @@ CONFIG_AGP_AMD=y CONFIG_AGP_SIS=y CONFIG_AGP_ALI=y +# CONFIG_AGP_SWORKS is not set CONFIG_DRM=y CONFIG_DRM_TDFX=y # CONFIG_DRM_GAMMA is not set @@ -587,7 +600,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 @@ -648,6 +660,7 @@ # CONFIG_SOUND_MSNDCLAS is not set # CONFIG_SOUND_MSNDPIN is not set # CONFIG_SOUND_VIA82CXXX is not set +# CONFIG_MIDI_VIA82CXXX is not set # CONFIG_SOUND_OSS is not set # CONFIG_SOUND_TVMIXER is not set @@ -703,6 +716,7 @@ # 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_DSBR is not set # CONFIG_USB_DABUSB is not set @@ -711,6 +725,7 @@ # # CONFIG_USB_PLUSB is not set # CONFIG_USB_PEGASUS is not set +# CONFIG_USB_CATC is not set # CONFIG_USB_NET1080 is not set # diff -u --recursive --new-file v2.4.5/linux/arch/i386/kernel/apic.c linux/arch/i386/kernel/apic.c --- v2.4.5/linux/arch/i386/kernel/apic.c Tue Dec 5 12:43:48 2000 +++ linux/arch/i386/kernel/apic.c Wed Jun 20 11:06:38 2001 @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -270,7 +271,13 @@ * PCI Ne2000 networking cards and PII/PIII processors, dual * BX chipset. ] */ -#if 0 + /* + * Actually disabling the focus CPU check just makes the hang less + * frequent as it makes the interrupt distributon model be more + * like LRU than MRU (the short-term load is more even across CPUs). + * See also the comment in end_level_ioapic_irq(). --macro + */ +#if 1 /* Enable focus processor (bit==0) */ value &= ~(1<<9); #else @@ -728,6 +735,9 @@ irq_enter(cpu, 0); smp_local_timer_interrupt(regs); irq_exit(cpu, 0); + + if (softirq_pending(cpu)) + do_softirq(); } /* @@ -764,7 +774,7 @@ apic_write(APIC_ESR, 0); v1 = apic_read(APIC_ESR); ack_APIC_irq(); - irq_err_count++; + atomic_inc(&irq_err_count); /* Here is what the APIC error bits mean: 0: Send CS error diff -u --recursive --new-file v2.4.5/linux/arch/i386/kernel/bluesmoke.c linux/arch/i386/kernel/bluesmoke.c --- v2.4.5/linux/arch/i386/kernel/bluesmoke.c Mon May 21 12:34:50 2001 +++ linux/arch/i386/kernel/bluesmoke.c Sun Jul 1 19:52:45 2001 @@ -182,7 +182,7 @@ * Set up machine check reporting on the Winchip C6 series */ -static void winchip_mcheck_init(struct cpuinfo_x86 *c) +static void __init winchip_mcheck_init(struct cpuinfo_x86 *c) { u32 lo, hi; /* Not supported on C3 */ @@ -207,8 +207,14 @@ * This has to be run for each processor */ + +static int mce_disabled = 0; + void __init mcheck_init(struct cpuinfo_x86 *c) { + if(mce_disabled) + return; + switch(c->x86_vendor) { case X86_VENDOR_AMD: @@ -226,3 +232,10 @@ break; } } + +static int __init mcheck_disable(char *str) +{ + mce_disabled = 1; + return 1; +} +__setup("nomce", mcheck_disable); diff -u --recursive --new-file v2.4.5/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S --- v2.4.5/linux/arch/i386/kernel/entry.S Wed Nov 8 17:09:50 2000 +++ linux/arch/i386/kernel/entry.S Tue Jun 12 11:47:28 2001 @@ -203,18 +203,7 @@ call *SYMBOL_NAME(sys_call_table)(,%eax,4) movl %eax,EAX(%esp) # save the return value ENTRY(ret_from_sys_call) -#ifdef CONFIG_SMP - movl processor(%ebx),%eax - shll $CONFIG_X86_L1_CACHE_SHIFT,%eax - movl SYMBOL_NAME(irq_stat)(,%eax),%ecx # softirq_active - testl SYMBOL_NAME(irq_stat)+4(,%eax),%ecx # softirq_mask -#else - movl SYMBOL_NAME(irq_stat),%ecx # softirq_active - testl SYMBOL_NAME(irq_stat)+4,%ecx # softirq_mask -#endif - jne handle_softirq - -ret_with_reschedule: + cli # need_resched and signals atomic test cmpl $0,need_resched(%ebx) jne reschedule cmpl $0,sigpending(%ebx) @@ -257,33 +246,16 @@ jmp ret_from_sys_call ALIGN -ret_from_exception: -#ifdef CONFIG_SMP - GET_CURRENT(%ebx) - movl processor(%ebx),%eax - shll $CONFIG_X86_L1_CACHE_SHIFT,%eax - movl SYMBOL_NAME(irq_stat)(,%eax),%ecx # softirq_active - testl SYMBOL_NAME(irq_stat)+4(,%eax),%ecx # softirq_mask -#else - movl SYMBOL_NAME(irq_stat),%ecx # softirq_active - testl SYMBOL_NAME(irq_stat)+4,%ecx # softirq_mask -#endif - jne handle_softirq - ENTRY(ret_from_intr) GET_CURRENT(%ebx) +ret_from_exception: movl EFLAGS(%esp),%eax # mix EFLAGS and CS movb CS(%esp),%al testl $(VM_MASK | 3),%eax # return to VM86 mode or non-supervisor? - jne ret_with_reschedule + jne ret_from_sys_call jmp restore_all ALIGN -handle_softirq: - call SYMBOL_NAME(do_softirq) - jmp ret_from_intr - - ALIGN reschedule: call SYMBOL_NAME(schedule) # test jmp ret_from_sys_call @@ -334,14 +306,16 @@ pushl $-1 # mark this as an int SAVE_ALL GET_CURRENT(%ebx) - pushl $ret_from_exception movl %cr0,%eax testl $0x4,%eax # EM (math emulation bit) - je SYMBOL_NAME(math_state_restore) + jne device_not_available_emulate + call SYMBOL_NAME(math_state_restore) + jmp ret_from_exception +device_not_available_emulate: pushl $0 # temporary storage for ORIG_EIP call SYMBOL_NAME(math_emulate) addl $4,%esp - ret + jmp ret_from_exception ENTRY(debug) pushl $0 diff -u --recursive --new-file v2.4.5/linux/arch/i386/kernel/head.S linux/arch/i386/kernel/head.S --- v2.4.5/linux/arch/i386/kernel/head.S Fri Apr 20 16:23:30 2001 +++ linux/arch/i386/kernel/head.S Wed Jun 20 11:00:53 2001 @@ -41,8 +41,6 @@ * * On entry, %esi points to the real-mode code as a 32-bit pointer. */ -ENTRY(stext) -ENTRY(_stext) startup_32: /* * Set segments to known values @@ -409,6 +407,12 @@ ENTRY(empty_zero_page) .org 0x5000 + +/* + * Real beginning of normal "text" segment + */ +ENTRY(stext) +ENTRY(_stext) /* * This starts the data section. Note that the above is all diff -u --recursive --new-file v2.4.5/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c --- v2.4.5/linux/arch/i386/kernel/i386_ksyms.c Tue May 15 08:46:20 2001 +++ linux/arch/i386/kernel/i386_ksyms.c Mon Jul 2 14:49:24 2001 @@ -90,9 +90,6 @@ EXPORT_SYMBOL_NOVERS(__get_user_1); EXPORT_SYMBOL_NOVERS(__get_user_2); EXPORT_SYMBOL_NOVERS(__get_user_4); -EXPORT_SYMBOL_NOVERS(__put_user_1); -EXPORT_SYMBOL_NOVERS(__put_user_2); -EXPORT_SYMBOL_NOVERS(__put_user_4); EXPORT_SYMBOL(strtok); EXPORT_SYMBOL(strpbrk); diff -u --recursive --new-file v2.4.5/linux/arch/i386/kernel/i8259.c linux/arch/i386/kernel/i8259.c --- v2.4.5/linux/arch/i386/kernel/i8259.c Fri Feb 9 11:29:44 2001 +++ linux/arch/i386/kernel/i8259.c Wed Jun 20 11:06:38 2001 @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -321,7 +322,7 @@ printk("spurious 8259A interrupt: IRQ%d.\n", irq); spurious_irq_mask |= irqmask; } - irq_err_count++; + atomic_inc(&irq_err_count); /* * Theoretically we do not have to handle this IRQ, * but in Linux this does not cause problems and is diff -u --recursive --new-file v2.4.5/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c --- v2.4.5/linux/arch/i386/kernel/io_apic.c Fri Feb 9 11:28:31 2001 +++ linux/arch/i386/kernel/io_apic.c Wed Jun 20 11:06:38 2001 @@ -33,6 +33,8 @@ #include #include +#define APIC_LOCKUP_DEBUG + static spinlock_t ioapic_lock = SPIN_LOCK_UNLOCKED; /* @@ -122,8 +124,14 @@ static void name##_IO_APIC_irq (unsigned int irq) \ __DO_ACTION(R, ACTION, FINAL) -DO_ACTION( __mask, 0, |= 0x00010000, io_apic_sync(entry->apic))/* mask = 1 */ -DO_ACTION( __unmask, 0, &= 0xfffeffff, ) /* mask = 0 */ +DO_ACTION( __mask, 0, |= 0x00010000, io_apic_sync(entry->apic) ) + /* mask = 1 */ +DO_ACTION( __unmask, 0, &= 0xfffeffff, ) + /* mask = 0 */ +DO_ACTION( __mask_and_edge, 0, = (reg & 0xffff7fff) | 0x00010000, ) + /* mask = 1, trigger = 0 */ +DO_ACTION( __unmask_and_level, 0, = (reg & 0xfffeffff) | 0x00008000, ) + /* mask = 0, trigger = 1 */ static void mask_IO_APIC_irq (unsigned int irq) { @@ -255,10 +263,16 @@ */ static int pin_2_irq(int idx, int apic, int pin); -int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pci_pin) +int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin) { int apic, i, best_guess = -1; + Dprintk("querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n", + bus, slot, pin); + if (mp_bus_id_to_pci_bus[bus] == -1) { + printk(KERN_WARNING "PCI BIOS passed nonexistent PCI bus %d!\n", bus); + return -1; + } for (i = 0; i < mp_irq_entries; i++) { int lbus = mp_irqs[i].mpc_srcbus; @@ -269,14 +283,14 @@ if ((mp_bus_id_to_type[lbus] == MP_BUS_PCI) && !mp_irqs[i].mpc_irqtype && - (bus == mp_bus_id_to_pci_bus[mp_irqs[i].mpc_srcbus]) && + (bus == lbus) && (slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f))) { int irq = pin_2_irq(i,apic,mp_irqs[i].mpc_dstirq); if (!(apic || IO_APIC_IRQ(irq))) continue; - if (pci_pin == (mp_irqs[i].mpc_srcbusirq & 3)) + if (pin == (mp_irqs[i].mpc_srcbusirq & 3)) return irq; /* * Use the first all-but-pin matching entry as a @@ -728,9 +742,11 @@ printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)®_01); printk(KERN_DEBUG "....... : max redirection entries: %04X\n", reg_01.entries); if ( (reg_01.entries != 0x0f) && /* older (Neptune) boards */ + (reg_01.entries != 0x11) && (reg_01.entries != 0x17) && /* typical ISA+PCI boards */ (reg_01.entries != 0x1b) && /* Compaq Proliant boards */ (reg_01.entries != 0x1f) && /* dual Xeon boards */ + (reg_01.entries != 0x20) && (reg_01.entries != 0x22) && /* bigger Xeon boards */ (reg_01.entries != 0x2E) && (reg_01.entries != 0x3F) @@ -847,6 +863,8 @@ v = apic_read(APIC_EOI); printk(KERN_DEBUG "... APIC EOI: %08x\n", v); + v = apic_read(APIC_RRR); + printk(KERN_DEBUG "... APIC RRR: %08x\n", v); v = apic_read(APIC_LDR); printk(KERN_DEBUG "... APIC LDR: %08x\n", v); v = apic_read(APIC_DFR); @@ -1191,12 +1209,61 @@ #define enable_level_ioapic_irq unmask_IO_APIC_irq #define disable_level_ioapic_irq mask_IO_APIC_irq -static void end_level_ioapic_irq (unsigned int i) +static void end_level_ioapic_irq (unsigned int irq) { + unsigned long v; + +/* + * It appears there is an erratum which affects at least version 0x11 + * of I/O APIC (that's the 82093AA and cores integrated into various + * chipsets). Under certain conditions a level-triggered interrupt is + * erroneously delivered as edge-triggered one but the respective IRR + * bit gets set nevertheless. As a result the I/O unit expects an EOI + * message but it will never arrive and further interrupts are blocked + * from the source. The exact reason is so far unknown, but the + * phenomenon was observed when two consecutive interrupt requests + * from a given source get delivered to the same CPU and the source is + * temporarily disabled in between. + * + * A workaround is to simulate an EOI message manually. We achieve it + * by setting the trigger mode to edge and then to level when the edge + * trigger mode gets detected in the TMR of a local APIC for a + * level-triggered interrupt. We mask the source for the time of the + * operation to prevent an edge-triggered interrupt escaping meanwhile. + * The idea is from Manfred Spraul. --macro + */ + v = apic_read(APIC_TMR + ((IO_APIC_VECTOR(irq) & ~0x1f) >> 1)); + ack_APIC_irq(); + + if (!(v & (1 << (IO_APIC_VECTOR(irq) & 0x1f)))) { +#ifdef APIC_MISMATCH_DEBUG + atomic_inc(&irq_mis_count); +#endif + spin_lock(&ioapic_lock); + __mask_and_edge_IO_APIC_irq(irq); +#ifdef APIC_LOCKUP_DEBUG + for (;;) { + struct irq_pin_list *entry = irq_2_pin + irq; + unsigned int reg; + + if (entry->pin == -1) + break; + reg = io_apic_read(entry->apic, 0x10 + entry->pin * 2); + if (reg & 0x00004000) + printk(KERN_CRIT "Aieee!!! Remote IRR" + " still set after unlock!\n"); + if (!entry->next) + break; + entry = irq_2_pin + entry->next; + } +#endif + __unmask_and_level_IO_APIC_irq(irq); + spin_unlock(&ioapic_lock); + } } -static void mask_and_ack_level_ioapic_irq (unsigned int i) { /* nothing */ } +static void mask_and_ack_level_ioapic_irq (unsigned int irq) { /* nothing */ } static void set_ioapic_affinity (unsigned int irq, unsigned long mask) { @@ -1426,7 +1493,7 @@ pin1 = find_isa_irq_pin(0, mp_INT); pin2 = find_isa_irq_pin(0, mp_ExtINT); - printk(KERN_INFO "..TIMER: vector=%d pin1=%d pin2=%d\n", vector, pin1, pin2); + printk(KERN_INFO "..TIMER: vector=%02X pin1=%d pin2=%d\n", vector, pin1, pin2); if (pin1 != -1) { /* diff -u --recursive --new-file v2.4.5/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c --- v2.4.5/linux/arch/i386/kernel/irq.c Fri Feb 9 11:29:44 2001 +++ linux/arch/i386/kernel/irq.c Wed Jun 20 11:06:38 2001 @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -119,7 +120,12 @@ end_none }; -volatile unsigned long irq_err_count; +atomic_t irq_err_count; +#ifdef CONFIG_X86_IO_APIC +#ifdef APIC_MISMATCH_DEBUG +atomic_t irq_mis_count; +#endif +#endif /* * Generic, controller-independent functions: @@ -167,7 +173,12 @@ apic_timer_irqs[cpu_logical_map(j)]); p += sprintf(p, "\n"); #endif - p += sprintf(p, "ERR: %10lu\n", irq_err_count); + p += sprintf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); +#ifdef CONFIG_X86_IO_APIC +#ifdef APIC_MISMATCH_DEBUG + p += sprintf(p, "MIS: %10u\n", atomic_read(&irq_mis_count)); +#endif +#endif return p - buf; } @@ -623,7 +634,7 @@ desc->handler->end(irq); spin_unlock(&desc->lock); - if (softirq_active(cpu) & softirq_mask(cpu)) + if (softirq_pending(cpu)) do_softirq(); return 1; } diff -u --recursive --new-file v2.4.5/linux/arch/i386/kernel/mpparse.c linux/arch/i386/kernel/mpparse.c --- v2.4.5/linux/arch/i386/kernel/mpparse.c Tue Nov 14 21:25:34 2000 +++ linux/arch/i386/kernel/mpparse.c Mon Jun 11 19:15:27 2001 @@ -36,7 +36,7 @@ */ int apic_version [MAX_APICS]; int mp_bus_id_to_type [MAX_MP_BUSSES]; -int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { -1, }; +int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 }; int mp_current_pci_id; int pic_mode; unsigned long mp_lapic_addr; diff -u --recursive --new-file v2.4.5/linux/arch/i386/kernel/pci-i386.h linux/arch/i386/kernel/pci-i386.h --- v2.4.5/linux/arch/i386/kernel/pci-i386.h Thu Jun 22 07:17:16 2000 +++ linux/arch/i386/kernel/pci-i386.h Wed Jun 20 11:21:33 2001 @@ -12,14 +12,15 @@ #define DBG(x...) #endif -#define PCI_PROBE_BIOS 1 -#define PCI_PROBE_CONF1 2 -#define PCI_PROBE_CONF2 4 -#define PCI_NO_SORT 0x100 -#define PCI_BIOS_SORT 0x200 -#define PCI_NO_CHECKS 0x400 -#define PCI_ASSIGN_ROMS 0x1000 -#define PCI_BIOS_IRQ_SCAN 0x2000 +#define PCI_PROBE_BIOS 0x0001 +#define PCI_PROBE_CONF1 0x0002 +#define PCI_PROBE_CONF2 0x0004 +#define PCI_NO_SORT 0x0100 +#define PCI_BIOS_SORT 0x0200 +#define PCI_NO_CHECKS 0x0400 +#define PCI_ASSIGN_ROMS 0x1000 +#define PCI_BIOS_IRQ_SCAN 0x2000 +#define PCI_ASSIGN_ALL_BUSSES 0x4000 extern unsigned int pci_probe; diff -u --recursive --new-file v2.4.5/linux/arch/i386/kernel/pci-irq.c linux/arch/i386/kernel/pci-irq.c --- v2.4.5/linux/arch/i386/kernel/pci-irq.c Wed May 16 10:25:39 2001 +++ linux/arch/i386/kernel/pci-irq.c Wed Jun 20 11:16:01 2001 @@ -411,7 +411,7 @@ { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, pirq_piix_get, pirq_piix_set }, { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX, pirq_piix_get, pirq_piix_set }, { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_0, pirq_piix_get, pirq_piix_set }, - { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82820FW_0, pirq_piix_get, pirq_piix_set }, + { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, pirq_piix_get, pirq_piix_set }, { "ALI", PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, pirq_ali_get, pirq_ali_set }, @@ -587,13 +587,14 @@ if (info->irq[pin].link == pirq) { /* We refuse to override the dev->irq information. Give a warning! */ if (dev2->irq && dev2->irq != irq) { - printk(KERN_INFO "IRQ routing conflict in pirq table for device %s\n", dev2->slot_name); + printk(KERN_INFO "IRQ routing conflict for %s, have irq %d, want irq %d\n", + dev2->slot_name, dev2->irq, irq); continue; } dev2->irq = irq; pirq_penalty[irq]++; if (dev != dev2) - printk(KERN_INFO "PCI: The same IRQ used for device %s\n", dev2->slot_name); + printk(KERN_INFO "PCI: Sharing IRQ %d with %s\n", irq, dev2->slot_name); } } return 1; @@ -656,10 +657,12 @@ if (pin) { pin--; /* interrupt pins are numbered starting from 1 */ irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin); -/* - * Will be removed completely if things work out well with fuzzy parsing - */ -#if 0 + /* + * Busses behind bridges are typically not listed in the MP-table. + * In this case we have to look up the IRQ based on the parent bus, + * parent slot, and pin number. The SMP code detects such bridged + * busses itself so we should get into this branch reliably. + */ if (irq < 0 && dev->bus->parent) { /* go back to the bridge */ struct pci_dev * bridge = dev->bus->self; @@ -670,7 +673,6 @@ printk(KERN_WARNING "PCI: using PPB(B%d,I%d,P%d) to get irq %d\n", bridge->bus->number, PCI_SLOT(bridge->devfn), pin, irq); } -#endif if (irq >= 0) { printk(KERN_INFO "PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %d\n", dev->bus->number, PCI_SLOT(dev->devfn), pin, irq); diff -u --recursive --new-file v2.4.5/linux/arch/i386/kernel/pci-pc.c linux/arch/i386/kernel/pci-pc.c --- v2.4.5/linux/arch/i386/kernel/pci-pc.c Thu Apr 19 22:57:06 2001 +++ linux/arch/i386/kernel/pci-pc.c Wed Jun 20 11:21:33 2001 @@ -940,18 +940,6 @@ pcibios_max_latency = 32; } -static void __init pci_fixup_via_acpi(struct pci_dev *d) -{ - /* - * VIA ACPI device: IRQ line in PCI config byte 0x42 - */ - u8 irq; - pci_read_config_byte(d, 0x42, &irq); - irq &= 0x0f; - if (irq && (irq != 2)) - d->irq = irq; -} - static void __init pci_fixup_piix4_acpi(struct pci_dev *d) { /* @@ -1006,8 +994,6 @@ { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, pci_fixup_latency }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5598, pci_fixup_latency }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, pci_fixup_via_acpi }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, pci_fixup_via_acpi }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C691, pci_fixup_via691 }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C598_1, pci_fixup_via691_2 }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, pci_fixup_piix4_acpi }, @@ -1104,6 +1090,9 @@ else if (!strcmp(str, "rom")) { pci_probe |= PCI_ASSIGN_ROMS; return NULL; + } else if (!strcmp(str, "assign-busses")) { + pci_probe |= PCI_ASSIGN_ALL_BUSSES; + return NULL; } else if (!strncmp(str, "irqmask=", 8)) { pcibios_irq_mask = simple_strtol(str+8, NULL, 0); return NULL; @@ -1112,6 +1101,11 @@ return NULL; } return str; +} + +unsigned int pcibios_assign_all_busses(void) +{ + return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0; } int pcibios_enable_device(struct pci_dev *dev) diff -u --recursive --new-file v2.4.5/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c --- v2.4.5/linux/arch/i386/kernel/traps.c Mon May 7 14:15:21 2001 +++ linux/arch/i386/kernel/traps.c Wed Jun 20 13:59:44 2001 @@ -105,6 +105,7 @@ i = 1; module_start = VMALLOC_START; module_end = VMALLOC_END; + module_end = 0; while (((long) stack & (THREAD_SIZE-1)) != 0) { addr = *stack++; /* @@ -129,7 +130,12 @@ void show_trace_task(struct task_struct *tsk) { - show_trace(&tsk->thread.esp); + unsigned long esp = tsk->thread.esp; + + /* User space on another CPU? */ + if ((esp ^ (unsigned long)tsk) & (PAGE_MASK<<1)) + return; + show_trace((unsigned long *)esp); } void show_stack(unsigned long * esp) diff -u --recursive --new-file v2.4.5/linux/arch/i386/lib/Makefile linux/arch/i386/lib/Makefile --- v2.4.5/linux/arch/i386/lib/Makefile Wed Apr 25 13:31:03 2001 +++ linux/arch/i386/lib/Makefile Mon Jul 2 16:15:33 2001 @@ -8,7 +8,7 @@ L_TARGET = lib.a obj-y = checksum.o old-checksum.o delay.o \ - usercopy.o getuser.o putuser.o \ + usercopy.o getuser.o \ memcpy.o strstr.o obj-$(CONFIG_X86_USE_3DNOW) += mmx.o diff -u --recursive --new-file v2.4.5/linux/arch/i386/lib/putuser.S linux/arch/i386/lib/putuser.S --- v2.4.5/linux/arch/i386/lib/putuser.S Mon Jan 12 13:37:26 1998 +++ linux/arch/i386/lib/putuser.S Wed Dec 31 16:00:00 1969 @@ -1,71 +0,0 @@ -/* - * __put_user functions. - * - * (C) Copyright 1998 Linus Torvalds - * - * These functions have a non-standard call interface - * to make them more efficient. - */ - -/* - * __put_user_X - * - * Inputs: %eax contains the address - * %edx contains the value - * - * Outputs: %eax is error code (0 or -EFAULT) - * %ecx is corrupted (will contain "current_task"). - * - * These functions should not modify any other registers, - * as they get called from within inline assembly. - */ - -addr_limit = 12 - -.text -.align 4 -.globl __put_user_1 -__put_user_1: - movl %esp,%ecx - andl $0xffffe000,%ecx - cmpl addr_limit(%ecx),%eax - jae bad_put_user -1: movb %dl,(%eax) - xorl %eax,%eax - ret - -.align 4 -.globl __put_user_2 -__put_user_2: - addl $1,%eax - movl %esp,%ecx - jc bad_put_user - andl $0xffffe000,%ecx - cmpl addr_limit(%ecx),%eax - jae bad_put_user -2: movw %dx,-1(%eax) - xorl %eax,%eax - ret - -.align 4 -.globl __put_user_4 -__put_user_4: - addl $3,%eax - movl %esp,%ecx - jc bad_put_user - andl $0xffffe000,%ecx - cmpl addr_limit(%ecx),%eax - jae bad_put_user -3: movl %edx,-3(%eax) - xorl %eax,%eax - ret - -bad_put_user: - movl $-14,%eax - ret - -.section __ex_table,"a" - .long 1b,bad_put_user - .long 2b,bad_put_user - .long 3b,bad_put_user -.previous diff -u --recursive --new-file v2.4.5/linux/arch/i386/math-emu/fpu_trig.c linux/arch/i386/math-emu/fpu_trig.c --- v2.4.5/linux/arch/i386/math-emu/fpu_trig.c Fri Apr 6 10:42:47 2001 +++ linux/arch/i386/math-emu/fpu_trig.c Tue Jun 12 11:06:54 2001 @@ -1543,6 +1543,7 @@ EXCEPTION(EX_INTERNAL | 0x116); return; #endif /* PARANOID */ + break; } } else if ( (st0_tag == TAG_Valid) || (st0_tag == TW_Denormal) ) diff -u --recursive --new-file v2.4.5/linux/arch/i386/vmlinux.lds linux/arch/i386/vmlinux.lds --- v2.4.5/linux/arch/i386/vmlinux.lds Wed Jan 3 20:45:26 2001 +++ linux/arch/i386/vmlinux.lds Mon Jul 2 14:40:14 2001 @@ -17,7 +17,7 @@ _etext = .; /* End of text section */ - .rodata : { *(.rodata) } + .rodata : { *(.rodata) *(.rodata.*) } .kstrtab : { *(.kstrtab) } . = ALIGN(16); /* Exception table */ diff -u --recursive --new-file v2.4.5/linux/arch/ia64/boot/bootloader.lds linux/arch/ia64/boot/bootloader.lds --- v2.4.5/linux/arch/ia64/boot/bootloader.lds Sun Feb 6 18:42:40 2000 +++ linux/arch/ia64/boot/bootloader.lds Mon Jul 2 14:40:14 2001 @@ -12,7 +12,7 @@ /* Global data */ _data = .; - .rodata : { *(.rodata) } + .rodata : { *(.rodata) *(.rodata.*) } .data : { *(.data) *(.gnu.linkonce.d*) CONSTRUCTORS } __gp = ALIGN (8) + 0x200000; .got : { *(.got.plt) *(.got) } diff -u --recursive --new-file v2.4.5/linux/arch/ia64/sn/fprom/fprom.lds linux/arch/ia64/sn/fprom/fprom.lds --- v2.4.5/linux/arch/ia64/sn/fprom/fprom.lds Thu Jan 4 13:00:15 2001 +++ linux/arch/ia64/sn/fprom/fprom.lds Mon Jul 2 14:40:14 2001 @@ -24,7 +24,7 @@ _data = .; .rodata : AT(ADDR(.rodata) - 0x0000000000000000 ) - { *(.rodata) } + { *(.rodata) *(.rodata.*) } .opd : AT(ADDR(.opd) - 0x0000000000000000 ) { *(.opd) } .data : AT(ADDR(.data) - 0x0000000000000000 ) diff -u --recursive --new-file v2.4.5/linux/arch/ia64/vmlinux.lds.S linux/arch/ia64/vmlinux.lds.S --- v2.4.5/linux/arch/ia64/vmlinux.lds.S Thu Apr 5 12:51:47 2001 +++ linux/arch/ia64/vmlinux.lds.S Mon Jul 2 14:40:14 2001 @@ -83,7 +83,7 @@ ia64_unw_end = .; .rodata : AT(ADDR(.rodata) - PAGE_OFFSET) - { *(.rodata) } + { *(.rodata) *(.rodata.*) } .kstrtab : AT(ADDR(.kstrtab) - PAGE_OFFSET) { *(.kstrtab) } .opd : AT(ADDR(.opd) - PAGE_OFFSET) diff -u --recursive --new-file v2.4.5/linux/arch/m68k/Makefile linux/arch/m68k/Makefile --- v2.4.5/linux/arch/m68k/Makefile Thu Jan 4 13:00:55 2001 +++ linux/arch/m68k/Makefile Mon Jun 11 19:15:27 2001 @@ -110,8 +110,8 @@ endif ifdef CONFIG_SUN3X -CORE_FILES := $(CORE_FILES) arch/m68k/sun3x/sun3x.o -SUBDIRS := $(SUBDIRS) arch/m68k/sun3x +CORE_FILES := $(CORE_FILES) arch/m68k/sun3x/sun3x.o arch/m68k/sun3/sun3.o +SUBDIRS := $(SUBDIRS) arch/m68k/sun3x arch/m68k/sun3 endif ifdef CONFIG_SUN3 diff -u --recursive --new-file v2.4.5/linux/arch/m68k/amiga/amisound.c linux/arch/m68k/amiga/amisound.c --- v2.4.5/linux/arch/m68k/amiga/amisound.c Thu Jan 4 13:00:55 2001 +++ linux/arch/m68k/amiga/amisound.c Mon Jun 11 19:15:27 2001 @@ -16,7 +16,7 @@ #include #include -static u_short *snd_data = NULL; +static unsigned short *snd_data = NULL; static const signed char sine_data[] = { 0, 39, 75, 103, 121, 127, 121, 103, 75, 39, 0, -39, -75, -103, -121, -127, -121, -103, -75, -39 @@ -28,7 +28,7 @@ * device since it depends on htotal (for OCS/ECS/AGA) */ -volatile u_short amiga_audio_min_period = 124; /* Default for pre-OCS */ +volatile unsigned short amiga_audio_min_period = 124; /* Default for pre-OCS */ #define MAX_PERIOD (65535) @@ -37,9 +37,9 @@ * Current period (set by dmasound.c) */ -u_short amiga_audio_period = MAX_PERIOD; +unsigned short amiga_audio_period = MAX_PERIOD; -static u_long clock_constant; +static unsigned long clock_constant; void __init amiga_init_sound(void) { @@ -76,7 +76,7 @@ del_timer( &sound_timer ); if (hz > 20 && hz < 32767) { - u_long period = (clock_constant / hz); + unsigned long period = (clock_constant / hz); if (period < amiga_audio_min_period) period = amiga_audio_min_period; @@ -86,7 +86,7 @@ /* setup pointer to data, period, length and volume */ custom.aud[2].audlc = snd_data; custom.aud[2].audlen = sizeof(sine_data)/2; - custom.aud[2].audper = (u_short)period; + custom.aud[2].audper = (unsigned short)period; custom.aud[2].audvol = 32; /* 50% of maxvol */ if (ticks) { diff -u --recursive --new-file v2.4.5/linux/arch/m68k/amiga/cia.c linux/arch/m68k/amiga/cia.c --- v2.4.5/linux/arch/m68k/amiga/cia.c Mon Nov 27 17:57:34 2000 +++ linux/arch/m68k/amiga/cia.c Mon Jun 11 19:15:27 2001 @@ -23,8 +23,8 @@ struct ciabase { volatile struct CIA *cia; - u_char icr_mask, icr_data; - u_short int_mask; + unsigned char icr_mask, icr_data; + unsigned short int_mask; int handler_irq, cia_irq, server_irq; char *name; irq_handler_t irq_list[CIA_IRQS]; @@ -46,7 +46,7 @@ unsigned char cia_set_irq(struct ciabase *base, unsigned char mask) { - u_char old; + unsigned char old; old = (base->icr_data |= base->cia->icr); if (mask & CIA_ICR_SETCLR) @@ -65,7 +65,7 @@ unsigned char cia_able_irq(struct ciabase *base, unsigned char mask) { - u_char old, tmp; + unsigned char old, tmp; int i; old = base->icr_mask; @@ -91,7 +91,7 @@ void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id) { - u_char mask; + unsigned char mask; base->irq_list[irq].handler = handler; base->irq_list[irq].flags = flags; diff -u --recursive --new-file v2.4.5/linux/arch/m68k/amiga/config.c linux/arch/m68k/amiga/config.c --- v2.4.5/linux/arch/m68k/amiga/config.c Fri Apr 13 20:26:07 2001 +++ linux/arch/m68k/amiga/config.c Mon Jun 11 19:15:27 2001 @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -31,6 +30,7 @@ #include #include #include +#include #include #include #include diff -u --recursive --new-file v2.4.5/linux/arch/m68k/amiga/pcmcia.c linux/arch/m68k/amiga/pcmcia.c --- v2.4.5/linux/arch/m68k/amiga/pcmcia.c Thu Dec 17 09:06:25 1998 +++ linux/arch/m68k/amiga/pcmcia.c Mon Jun 11 19:15:27 2001 @@ -19,7 +19,7 @@ #include /* gayle config byte for program voltage and access speed */ -static u_char cfg_byte = GAYLE_CFG_0V|GAYLE_CFG_150NS; +static unsigned char cfg_byte = GAYLE_CFG_0V|GAYLE_CFG_150NS; void pcmcia_reset(void) { @@ -64,7 +64,7 @@ void pcmcia_program_voltage(int voltage) { - u_char v; + unsigned char v; switch (voltage) { case PCMCIA_0V: @@ -87,7 +87,7 @@ void pcmcia_access_speed(int speed) { - u_char s; + unsigned char s; if (speed <= PCMCIA_SPEED_100NS) s = GAYLE_CFG_100NS; diff -u --recursive --new-file v2.4.5/linux/arch/m68k/apollo/config.c linux/arch/m68k/apollo/config.c --- v2.4.5/linux/arch/m68k/apollo/config.c Wed Jan 26 12:44:20 2000 +++ linux/arch/m68k/apollo/config.c Mon Jun 11 19:15:27 2001 @@ -2,7 +2,6 @@ #include #include #include -#include #include #include @@ -12,6 +11,7 @@ #include #include #include +#include #include u_long sio01_physaddr; diff -u --recursive --new-file v2.4.5/linux/arch/m68k/atari/time.c linux/arch/m68k/atari/time.c --- v2.4.5/linux/arch/m68k/atari/time.c Thu Aug 26 12:42:31 1999 +++ linux/arch/m68k/atari/time.c Mon Jun 11 19:15:27 2001 @@ -12,10 +12,10 @@ #include #include -#include #include #include +#include void __init atari_sched_init(void (*timer_routine)(int, void *, struct pt_regs *)) diff -u --recursive --new-file v2.4.5/linux/arch/m68k/bvme6000/config.c linux/arch/m68k/bvme6000/config.c --- v2.4.5/linux/arch/m68k/bvme6000/config.c Mon Jan 31 10:32:53 2000 +++ linux/arch/m68k/bvme6000/config.c Mon Jun 11 19:15:27 2001 @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -30,6 +29,7 @@ #include #include #include +#include #include #include diff -u --recursive --new-file v2.4.5/linux/arch/m68k/bvme6000/rtc.c linux/arch/m68k/bvme6000/rtc.c --- v2.4.5/linux/arch/m68k/bvme6000/rtc.c Fri Feb 9 11:29:44 2001 +++ linux/arch/m68k/bvme6000/rtc.c Mon Jun 11 19:15:27 2001 @@ -76,7 +76,7 @@ unsigned char mon, day, hrs, min, sec, leap_yr; unsigned int yrs; - if (!suser()) + if (!capable(CAP_SYS_ADMIN)) return -EACCES; if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, diff -u --recursive --new-file v2.4.5/linux/arch/m68k/config.in linux/arch/m68k/config.in --- v2.4.5/linux/arch/m68k/config.in Mon May 21 18:12:09 2001 +++ linux/arch/m68k/config.in Mon Jun 11 19:15:27 2001 @@ -55,8 +55,8 @@ if [ "$CONFIG_HP300" = "y" ]; then bool ' DIO bus support' CONFIG_DIO fi -bool 'Sun3 support' CONFIG_SUN3 bool 'Sun3x support' CONFIG_SUN3X +bool 'Sun3 support' CONFIG_SUN3 bool 'Q40/Q60 support' CONFIG_Q40 @@ -112,7 +112,7 @@ bool 'Support for ST-RAM as swap space' CONFIG_STRAM_SWAP bool 'ST-RAM statistics in /proc' CONFIG_STRAM_PROC fi -if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_ATARI" = "y" ]; then +if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_ATARI" = "y" -o "$CONFIG_Q40" = "y" ]; then bool 'Use power LED as a heartbeat' CONFIG_HEARTBEAT else if [ "$CONFIG_HP300" = "y" ]; then @@ -142,13 +142,17 @@ fi dep_tristate ' Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT if [ "$CONFIG_PRINTER" != "n" ]; then - bool ' Support IEEE1284 status readback' CONFIG_PRINTER_READBACK + bool ' Support IEEE1284 status readback' CONFIG_PARPORT_1284 fi fi source drivers/pci/Config.in source drivers/zorro/Config.in +if [ "$CONFIG_Q40" = "y" ]; then +source drivers/pnp/Config.in +fi + endmenu source drivers/mtd/Config.in @@ -264,11 +268,11 @@ fi if [ "$CONFIG_SUN3" = "y" ]; then - dep_tristate 'Sun3 NCR5380 SCSI' CONFIG_SUN3_SCSI $CONFIG_SCSI + dep_tristate 'Sun3 NCR5380 OBIO SCSI' CONFIG_SUN3_SCSI $CONFIG_SCSI fi if [ "$CONFIG_SUN3X" = "y" ]; then - bool 'ESP SCSI driver' CONFIG_SUN3X_ESP + bool 'Sun3x ESP SCSI' CONFIG_SUN3X_ESP fi endmenu @@ -338,6 +342,9 @@ if [ "$CONFIG_SUN3" = "y" -o "$CONFIG_SUN3X" = "y" ]; then tristate ' Sun3/Sun3x on-board LANCE support' CONFIG_SUN3LANCE fi + if [ "$CONFIG_SUN3" = "y" ]; then + tristate ' Sun3 on-board Intel 82586 support' CONFIG_SUN3_82586 + fi if [ "$CONFIG_HP300" = "y" ]; then bool ' HP on-board LANCE support' CONFIG_HPLANCE fi @@ -367,7 +374,6 @@ if [ "$CONFIG_SERIAL_EXTENDED" = "y" ]; then bool ' Support more than 4 serial ports' CONFIG_SERIAL_MANY_PORTS bool ' Support for sharing serial interrupts' CONFIG_SERIAL_SHARE_IRQ -# bool ' Autodetect IRQ - do not yet enable !!' CONFIG_SERIAL_DETECT_IRQ bool ' Support special multiport boards' CONFIG_SERIAL_MULTIPORT bool ' Support the Bell Technologies HUB6 card' CONFIG_HUB6 fi @@ -451,16 +457,16 @@ else define_bool CONFIG_SUN3X_ZS n fi -dep_bool ' Sun keyboard support' CONFIG_SUN_KEYBOARD $CONFIG_SUN3X_ZS -dep_bool ' Sun mouse support' CONFIG_SUN_MOUSE $CONFIG_SUN3X_ZS -if [ "$CONFIG_SUN_MOUSE" = "y" ]; then - define_bool CONFIG_BUSMOUSE y -fi if [ "$CONFIG_SUN3X_ZS" = "y" ]; then + define_bool CONFIG_SUN_KEYBOARD y + define_bool CONFIG_SUN_MOUSE y + define_bool CONFIG_BUSMOUSE y define_bool CONFIG_SBUS y define_bool CONFIG_SBUSCHAR y define_bool CONFIG_SUN_SERIAL y else + define_bool CONFIG_SUN_KEYBOARD n + define_bool CONFIG_SUN_MOUSE n define_bool CONFIG_SBUS n fi @@ -508,9 +514,6 @@ else bool 'Generic /dev/rtc emulation' CONFIG_GEN_RTC fi -fi -if [ "$CONFIG_Q40" = "y" ]; then - bool 'Q40 Real Time Clock Support' CONFIG_Q40RTC fi bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then diff -u --recursive --new-file v2.4.5/linux/arch/m68k/kernel/head.S linux/arch/m68k/kernel/head.S --- v2.4.5/linux/arch/m68k/kernel/head.S Tue Mar 6 19:44:36 2001 +++ linux/arch/m68k/kernel/head.S Mon Jun 11 19:15:27 2001 @@ -1178,8 +1178,45 @@ #ifdef CONFIG_SUN3X is_not_sun3x(L(notsun3x)) + /* oh, the pain.. We're gonna want the prom code after + * starting the MMU, so we copy the mappings, translating + * from 8k -> 4k pages as we go. + */ + + /* copy maps from 0xfee00000 to 0xff000000 */ + movel #0xfee00000, %d0 + moveq #ROOT_INDEX_SHIFT, %d1 + lsrl %d1,%d0 + mmu_get_root_table_entry %d0 + + movel #0xfee00000, %d0 + moveq #PTR_INDEX_SHIFT, %d1 + lsrl %d1,%d0 + andl #PTR_TABLE_SIZE-1, %d0 + mmu_get_ptr_table_entry %a0,%d0 + + movel #0xfee00000, %d0 + moveq #PAGE_INDEX_SHIFT, %d1 + lsrl %d1,%d0 + andl #PAGE_TABLE_SIZE-1, %d0 + mmu_get_page_table_entry %a0,%d0 + + /* this is where the prom page table lives */ + movel 0xfefe00d4, %a1 + movel %a1@, %a1 + + movel #((0x200000 >> 13)-1), %d1 + +1: + movel %a1@+, %d3 + movel %d3,%a0@+ + addl #0x1000,%d3 + movel %d3,%a0@+ + + dbra %d1,1b + /* setup tt1 for I/O */ - mmu_map_tt #1,#0x40000000,#0x40000000,#_PAGE_NOCACHE_S + mmu_map_tt #1,#0x40000000,#0x40000000,#_PAGE_NOCACHE_S jbra L(mmu_init_done) L(notsun3x): @@ -1363,7 +1400,7 @@ is_not_sun3x(1f) /* enable copro */ - oriw #0x4000,0x61000000 + oriw #0x4000,0x61000000 1: #endif @@ -3061,6 +3098,16 @@ 2: #endif +#ifdef CONFIG_SUN3X + is_not_sun3x(2f) + movel %d0,-(%sp) + movel 0xFEFE0018,%a1 + jbsr (%a1) + addq #4,%sp + jbra L(serial_putc_done) +2: +#endif + #ifdef CONFIG_Q40 is_not_q40(2f) tst.l %pc@(L(q40_do_debug)) /* only debug if requested */ diff -u --recursive --new-file v2.4.5/linux/arch/m68k/kernel/ptrace.c linux/arch/m68k/kernel/ptrace.c --- v2.4.5/linux/arch/m68k/kernel/ptrace.c Mon Nov 27 18:02:06 2000 +++ linux/arch/m68k/kernel/ptrace.c Mon Jun 11 19:15:27 2001 @@ -107,15 +107,19 @@ ret = -ESRCH; read_lock(&tasklist_lock); child = find_task_by_pid(pid); - read_unlock(&tasklist_lock); /* FIXME!!! */ + if (child) + get_task_struct(child); + read_unlock(&tasklist_lock); if (!child) goto out; + ret = -EPERM; if (pid == 1) /* you may not mess with init */ - goto out; + goto out_tsk; + if (request == PTRACE_ATTACH) { if (child == current) - goto out; + goto out_tsk; if ((!child->dumpable || (current->uid != child->euid) || (current->uid != child->suid) || @@ -124,10 +128,10 @@ (current->gid != child->sgid) || (!cap_issubset(child->cap_permitted, current->cap_permitted)) || (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) - goto out; + goto out_tsk; /* the same process cannot be attached many times */ if (child->ptrace & PT_PTRACED) - goto out; + goto out_tsk; child->ptrace |= PT_PTRACED; write_lock_irqsave(&tasklist_lock, flags); @@ -140,17 +144,17 @@ send_sig(SIGSTOP, child, 1); ret = 0; - goto out; + goto out_tsk; } ret = -ESRCH; if (!(child->ptrace & PT_PTRACED)) - goto out; + goto out_tsk; if (child->state != TASK_STOPPED) { if (request != PTRACE_KILL) - goto out; + goto out_tsk; } if (child->p_pptr != current) - goto out; + goto out_tsk; switch (request) { /* when I and D space are separate, these will need to be fixed. */ @@ -162,9 +166,9 @@ copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); ret = -EIO; if (copied != sizeof(tmp)) - goto out; + break; ret = put_user(tmp,(unsigned long *) data); - goto out; + break; } /* read the word at location addr in the USER area. */ @@ -172,8 +176,9 @@ unsigned long tmp; ret = -EIO; - if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) - goto out; + if ((addr & 3) || addr < 0 || + addr > sizeof(struct user) - 3) + break; tmp = 0; /* Default return condition */ addr = addr >> 2; /* temporary hack. */ @@ -193,9 +198,9 @@ ((tmp & 0x0000ffff) << 16); #endif } else - goto out; + break; ret = put_user(tmp,(unsigned long *) data); - goto out; + break; } /* when I and D space are separate, this will have to be fixed. */ @@ -203,14 +208,15 @@ case PTRACE_POKEDATA: ret = 0; if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) - goto out; + break; ret = -EIO; - goto out; + break; case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ ret = -EIO; - if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) - goto out; + if ((addr & 3) || addr < 0 || + addr > sizeof(struct user) - 3) + break; addr = addr >> 2; /* temporary hack. */ @@ -221,9 +227,9 @@ } if (addr < 19) { if (put_reg(child, addr, data)) - goto out; + break; ret = 0; - goto out; + break; } if (addr >= 21 && addr < 48) { @@ -240,7 +246,7 @@ child->thread.fp[addr - 21] = data; ret = 0; } - goto out; + break; case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: { /* restart after signal. */ @@ -248,7 +254,7 @@ ret = -EIO; if ((unsigned long) data > _NSIG) - goto out; + break; if (request == PTRACE_SYSCALL) child->ptrace |= PT_TRACESYS; else @@ -259,7 +265,7 @@ put_reg(child, PT_SR, tmp); wake_up_process(child); ret = 0; - goto out; + break; } /* @@ -272,13 +278,13 @@ ret = 0; if (child->state == TASK_ZOMBIE) /* already dead */ - goto out; + break; child->exit_code = SIGKILL; /* make sure the single step bit is not set. */ tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); put_reg(child, PT_SR, tmp); wake_up_process(child); - goto out; + break; } case PTRACE_SINGLESTEP: { /* set the trap flag. */ @@ -286,7 +292,7 @@ ret = -EIO; if ((unsigned long) data > _NSIG) - goto out; + break; child->ptrace &= ~PT_TRACESYS; tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16); put_reg(child, PT_SR, tmp); @@ -295,7 +301,7 @@ /* give it a chance to run. */ wake_up_process(child); ret = 0; - goto out; + break; } case PTRACE_DETACH: { /* detach a process that was attached. */ @@ -303,7 +309,7 @@ ret = -EIO; if ((unsigned long) data > _NSIG) - goto out; + break; child->ptrace &= ~(PT_PTRACED|PT_TRACESYS); child->exit_code = data; write_lock_irqsave(&tasklist_lock, flags); @@ -316,7 +322,7 @@ put_reg(child, PT_SR, tmp); wake_up_process(child); ret = 0; - goto out; + break; } case PTRACE_GETREGS: { /* Get all gp regs from the child. */ @@ -328,12 +334,12 @@ tmp >>= 16; if (put_user(tmp, (unsigned long *) data)) { ret = -EFAULT; - goto out; + break; } data += sizeof(long); } ret = 0; - goto out; + break; } case PTRACE_SETREGS: { /* Set all gp regs in the child. */ @@ -342,7 +348,7 @@ for (i = 0; i < 19; i++) { if (get_user(tmp, (unsigned long *) data)) { ret = -EFAULT; - goto out; + break; } if (i == PT_SR) { tmp &= SR_MASK; @@ -353,7 +359,7 @@ data += sizeof(long); } ret = 0; - goto out; + break; } case PTRACE_GETFPREGS: { /* Get the child FPU state. */ @@ -361,7 +367,7 @@ if (copy_to_user((void *)data, &child->thread.fp, sizeof(struct user_m68kfp_struct))) ret = -EFAULT; - goto out; + break; } case PTRACE_SETFPREGS: { /* Set the child FPU state. */ @@ -369,13 +375,15 @@ if (copy_from_user(&child->thread.fp, (void *)data, sizeof(struct user_m68kfp_struct))) ret = -EFAULT; - goto out; + break; } default: ret = -EIO; - goto out; + break; } +out_tsk: + free_task_struct(child); out: unlock_kernel(); return ret; @@ -383,10 +391,9 @@ asmlinkage void syscall_trace(void) { - lock_kernel(); if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) != (PT_PTRACED|PT_TRACESYS)) - goto out; + return; current->exit_code = SIGTRAP; current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); @@ -400,6 +407,4 @@ send_sig(current->exit_code, current, 1); current->exit_code = 0; } -out: - unlock_kernel(); } diff -u --recursive --new-file v2.4.5/linux/arch/m68k/kernel/setup.c linux/arch/m68k/kernel/setup.c --- v2.4.5/linux/arch/m68k/kernel/setup.c Fri Apr 13 20:26:07 2001 +++ linux/arch/m68k/kernel/setup.c Mon Jun 11 19:15:27 2001 @@ -34,6 +34,10 @@ #ifdef CONFIG_ATARI #include #endif +#ifdef CONFIG_SUN3X +#include +extern void sun_serial_setup(void); +#endif #ifdef CONFIG_BLK_DEV_INITRD #include @@ -106,6 +110,11 @@ char *mach_sysrq_xlate = NULL; #endif +#if defined(CONFIG_ISA) +int isa_type; +int isa_sex; +#endif + extern int amiga_parse_bootinfo(const struct bi_record *); extern int atari_parse_bootinfo(const struct bi_record *); extern int mac_parse_bootinfo(const struct bi_record *); @@ -137,7 +146,7 @@ { while (record->tag != BI_LAST) { int unknown = 0; - const u_long *data = record->data; + const unsigned long *data = record->data; switch (record->tag) { case BI_MACHTYPE: case BI_CPUTYPE: @@ -186,7 +195,7 @@ if (unknown) printk("m68k_parse_bootinfo: unknown tag 0x%04x ignored\n", record->tag); - record = (struct bi_record *)((u_long)record+record->size); + record = (struct bi_record *)((unsigned long)record+record->size); } m68k_realnum_memory = m68k_num_memory; @@ -365,14 +374,44 @@ if (MACH_IS_ATARI) atari_stram_reserve_pages(availmem); #endif +#ifdef CONFIG_SUN3X + if (MACH_IS_SUN3X) { + dvma_init(); +#ifdef CONFIG_SUN3X_ZS + sun_serial_setup(); +#endif + } +#endif + #endif /* !CONFIG_SUN3 */ + paging_init(); + +/* set ISA defs early as possible */ +#if defined(CONFIG_ISA) +#if defined(CONFIG_Q40) + if (MACH_IS_Q40) { + isa_type = Q40_ISA; + isa_sex = 0; + } +#elif defined(CONFIG_GG2) + if (MACH_IS_AMIGA && AMIGAHW_PRESENT(GG2_ISA)){ + isa_type = GG2_ISA; + isa_sex = 0; + } +#elif defined(CONFIG_AMIGA_PCMCIA) + if (MACH_IS_AMIGA && AMIGAHW_PRESENT(PCMCIA)){ + isa_type = AG_ISA; + isa_sex = 1; + } +#endif +#endif } int get_cpuinfo(char * buffer) { const char *cpu, *mmu, *fpu; - u_long clockfreq, clockfactor; + unsigned long clockfreq, clockfactor; #define LOOP_CYCLES_68020 (8) #define LOOP_CYCLES_68030 (8) @@ -447,7 +486,7 @@ { int len = 0; char model[80]; - u_long mem; + unsigned long mem; int i; if (mach_get_model) diff -u --recursive --new-file v2.4.5/linux/arch/m68k/kernel/sys_m68k.c linux/arch/m68k/kernel/sys_m68k.c --- v2.4.5/linux/arch/m68k/kernel/sys_m68k.c Mon Mar 19 12:35:09 2001 +++ linux/arch/m68k/kernel/sys_m68k.c Mon Jun 11 19:15:27 2001 @@ -267,7 +267,8 @@ return -ENOSYS; } -/* Convert virtual address VADDR to physical address PADDR */ + +/* Convert virtual (user) address VADDR to physical address PADDR */ #define virt_to_phys_040(vaddr) \ ({ \ unsigned long _mmusr, _paddr; \ @@ -447,6 +448,12 @@ { unsigned long paddr, i; + /* + * 68060 manual says: + * cpush %dc : flush DC, remains valid (with our %cacr setup) + * cpush %ic : invalidate IC + * cpush %bc : flush DC + invalidate IC + */ switch (scope) { case FLUSH_SCOPE_ALL: @@ -455,20 +462,17 @@ case FLUSH_CACHE_DATA: __asm__ __volatile__ (".chip 68060\n\t" "cpusha %dc\n\t" - "cinva %dc\n\t" ".chip 68k"); break; case FLUSH_CACHE_INSN: __asm__ __volatile__ (".chip 68060\n\t" "cpusha %ic\n\t" - "cinva %ic\n\t" ".chip 68k"); break; default: case FLUSH_CACHE_BOTH: __asm__ __volatile__ (".chip 68060\n\t" "cpusha %bc\n\t" - "cinva %bc\n\t" ".chip 68k"); break; } @@ -506,14 +510,12 @@ case FLUSH_CACHE_DATA: __asm__ __volatile__ (".chip 68060\n\t" "cpushl %%dc,(%0)\n\t" - "cinvl %%dc,(%0)\n\t" ".chip 68k" : : "a" (paddr)); break; case FLUSH_CACHE_INSN: __asm__ __volatile__ (".chip 68060\n\t" "cpushl %%ic,(%0)\n\t" - "cinvl %%ic,(%0)\n\t" ".chip 68k" : : "a" (paddr)); break; @@ -521,7 +523,6 @@ case FLUSH_CACHE_BOTH: __asm__ __volatile__ (".chip 68060\n\t" "cpushl %%bc,(%0)\n\t" - "cinvl %%bc,(%0)\n\t" ".chip 68k" : : "a" (paddr)); break; @@ -568,14 +569,12 @@ case FLUSH_CACHE_DATA: __asm__ __volatile__ (".chip 68060\n\t" "cpushp %%dc,(%0)\n\t" - "cinvp %%dc,(%0)\n\t" ".chip 68k" : : "a" (paddr)); break; case FLUSH_CACHE_INSN: __asm__ __volatile__ (".chip 68060\n\t" "cpushp %%ic,(%0)\n\t" - "cinvp %%ic,(%0)\n\t" ".chip 68k" : : "a" (paddr)); break; @@ -583,7 +582,6 @@ case FLUSH_CACHE_BOTH: __asm__ __volatile__ (".chip 68060\n\t" "cpushp %%bc,(%0)\n\t" - "cinvp %%bc,(%0)\n\t" ".chip 68k" : : "a" (paddr)); break; @@ -607,13 +605,14 @@ goto out; if (scope == FLUSH_SCOPE_ALL) { - /* Only the superuser may flush the whole cache. */ + /* Only the superuser may explicitly flush the whole cache. */ ret = -EPERM; if (!capable(CAP_SYS_ADMIN)) goto out; } else { - /* Verify that the specified address region actually belongs to - * this process. + /* + * Verify that the specified address region actually belongs + * to this process. */ vma = find_vma (current->mm, addr); ret = -EINVAL; @@ -652,10 +651,21 @@ } ret = 0; goto out; - } else if (CPU_IS_040) { + } else { + /* + * 040 or 060: don't blindly trust 'scope', someone could + * try to flush a few megs of memory. + */ + + if (len>=3*PAGE_SIZE && scope=10*PAGE_SIZE && scopeun.fmt7.faddr = current->thread.faddr; + fp->un.fmt7.faddr = wba; fp->un.fmt7.ssw = wbs & 0xff; + if (wba != current->thread.faddr) + fp->un.fmt7.ssw |= MA_040; } static inline void do_040writebacks(struct frame *fp) @@ -312,7 +331,7 @@ res = do_040writeback1(fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d); if (res) - fix_xframe040(fp, fp->un.fmt7.wb2s); + fix_xframe040(fp, fp->un.fmt7.wb2a, fp->un.fmt7.wb2s); else fp->un.fmt7.wb2s = 0; } @@ -322,7 +341,14 @@ res = do_040writeback1(fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d); if (res) - fix_xframe040(fp, fp->un.fmt7.wb3s); + { + fix_xframe040(fp, fp->un.fmt7.wb3a, fp->un.fmt7.wb3s); + + fp->un.fmt7.wb2s = fp->un.fmt7.wb3s; + fp->un.fmt7.wb3s &= (~WBV_040); + fp->un.fmt7.wb2a = fp->un.fmt7.wb3a; + fp->un.fmt7.wb2d = fp->un.fmt7.wb3d; + } else fp->un.fmt7.wb3s = 0; } @@ -339,19 +365,15 @@ */ asmlinkage void berr_040cleanup(struct frame *fp) { - mm_segment_t old_fs = get_fs(); - fp->un.fmt7.wb2s &= ~4; fp->un.fmt7.wb3s &= ~4; do_040writebacks(fp); - set_fs(old_fs); } static inline void access_error040(struct frame *fp) { unsigned short ssw = fp->un.fmt7.ssw; - mm_segment_t old_fs = get_fs(); unsigned long mmusr; #ifdef DEBUG @@ -374,9 +396,8 @@ if (ssw & MA_040) addr = (addr + 7) & -8; - set_fs(MAKE_MM_SEG(ssw)); /* MMU error, get the MMUSR info for this access */ - mmusr = probe040(!(ssw & RW_040), addr); + mmusr = probe040(!(ssw & RW_040), addr, ssw); #ifdef DEBUG printk("mmusr = %lx\n", mmusr); #endif @@ -386,8 +407,12 @@ __flush_tlb040_one(addr); errorcode = 0; } - if (!(ssw & RW_040)) + + /* despite what documentation seems to say, RMW + * accesses have always both the LK and RW bits set */ + if (!(ssw & RW_040) || (ssw & LK_040)) errorcode |= 2; + if (do_page_fault(&fp->ptregs, addr, errorcode)) { #ifdef DEBUG printk("do_page_fault() !=0 \n"); @@ -415,7 +440,6 @@ } do_040writebacks(fp); - set_fs(old_fs); } #endif /* CONFIG_M68040 */ diff -u --recursive --new-file v2.4.5/linux/arch/m68k/mac/config.c linux/arch/m68k/mac/config.c --- v2.4.5/linux/arch/m68k/mac/config.c Sun Dec 3 17:48:19 2000 +++ linux/arch/m68k/mac/config.c Mon Jun 11 19:15:27 2001 @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -31,6 +30,7 @@ #include #include #include +#include #include #include @@ -78,8 +78,6 @@ extern void (*kd_mksound)(unsigned int, unsigned int); extern void mac_mksound(unsigned int, unsigned int); -extern int mac_floppy_init(void); -extern void mac_floppy_setup(char *,int *); extern void nubus_sweep_video(void); @@ -122,8 +120,6 @@ } #endif -extern struct fb_info *mac_fb_init(long *); - extern void mac_default_handler(int, void *, struct pt_regs *); void (*mac_handlers[8])(int, void *, struct pt_regs *)= @@ -387,8 +383,7 @@ { MAC_MODEL_P460, "Performa 460", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_P475, "Performa 475", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_P475F, "Performa 475", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_P520, "Performa 520", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, - + { MAC_MODEL_P520, "Performa 520", MAC_ADB_CUDA, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_P550, "Performa 550", MAC_ADB_CUDA, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_P575, "Performa 575", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, /* These have the comm slot, and therefore the possibility of SONIC ethernet */ diff -u --recursive --new-file v2.4.5/linux/arch/m68k/mac/debug.c linux/arch/m68k/mac/debug.c --- v2.4.5/linux/arch/m68k/mac/debug.c Thu Oct 12 14:20:48 2000 +++ linux/arch/m68k/mac/debug.c Mon Jun 11 19:15:27 2001 @@ -187,7 +187,7 @@ -/* Mac: loops_per_sec min. 1900000 ^= .5 us; MFPDELAY was 0.6 us*/ +/* Mac: loops_per_jiffy min. 19000 ^= .5 us; MFPDELAY was 0.6 us*/ #define uSEC 1 @@ -286,9 +286,9 @@ barrier(); \ } while(0) -/* loops_per_sec isn't initialized yet, so we can't use udelay(). This does a +/* loops_per_jiffy isn't initialized yet, so we can't use udelay(). This does a * delay of ~ 60us. */ -/* Mac: loops_per_sec min. 1900000 ^= .5 us; MFPDELAY was 0.6 us*/ +/* Mac: loops_per_jiffy min. 19000 ^= .5 us; MFPDELAY was 0.6 us*/ #define LONG_DELAY() \ do { \ int i; \ diff -u --recursive --new-file v2.4.5/linux/arch/m68k/mac/iop.c linux/arch/m68k/mac/iop.c --- v2.4.5/linux/arch/m68k/mac/iop.c Sun Feb 13 11:21:42 2000 +++ linux/arch/m68k/mac/iop.c Mon Jun 11 19:15:27 2001 @@ -51,9 +51,6 @@ * IOP hasn't died. * o Some of the IOP manager routines need better error checking and * return codes. Nothing major, just prettying up. - * - * + share the stuff you were smoking when you wrote the iop_get_proc_info() - * for case when CONFIG_PROC_FS is undefined. */ /* @@ -129,9 +126,6 @@ #ifdef CONFIG_PROC_FS static int iop_get_proc_info(char *, char **, off_t, int); -#else -/* What the bloody hell is THAT ??? */ -static int iop_get_proc_info(char *, char **, off_t, int) {} #endif /* CONFIG_PROC_FS */ /* structure for tracking channel listeners */ @@ -307,7 +301,11 @@ iop_listeners[IOP_NUM_ISM][i].handler = NULL; } - create_proc_info_entry("mac_iop",0,0,iop_get_proc_info); +#if 0 /* Crashing in 2.4 now, not yet sure why. --jmt */ +#ifdef CONFIG_PROC_FS + create_proc_info_entry("mac_iop", 0, &proc_root, iop_get_proc_info); +#endif +#endif } /* diff -u --recursive --new-file v2.4.5/linux/arch/m68k/mac/macints.c linux/arch/m68k/mac/macints.c --- v2.4.5/linux/arch/m68k/mac/macints.c Sun Dec 3 17:48:19 2000 +++ linux/arch/m68k/mac/macints.c Mon Jun 11 19:15:27 2001 @@ -129,9 +129,13 @@ #include #include #include +#include #include +#define DEBUG_SPURIOUS +#define SHUTUP_SONIC + /* * The mac_irq_list array is an array of linked lists of irq_node_t nodes. * Each node contains one handler to be called whenever the interrupt @@ -233,6 +237,17 @@ scc_mask = 0; + /* Make sure the SONIC interrupt is cleared or things get ugly */ +#ifdef SHUTUP_SONIC + printk("Killing onboard sonic... "); + /* This address should hopefully be mapped already */ + if (hwreg_present((void*)(0x50f0a000))) { + *(long *)(0x50f0a014) = 0x7fffL; + *(long *)(0x50f0a010) = 0L; + } + printk("Done.\n"); +#endif /* SHUTUP_SONIC */ + /* * Now register the handlers for the the master IRQ handlers * at levels 1-7. Most of the work is done elsewhere. @@ -627,9 +642,7 @@ void mac_default_handler(int irq, void *dev_id, struct pt_regs *regs) { #ifdef DEBUG_SPURIOUS - if (console_loglevel > 6) { - printk("Unexpected IRQ %d on device %p\n", irq, dev_id); - } + printk("Unexpected IRQ %d on device %p\n", irq, dev_id); #endif } diff -u --recursive --new-file v2.4.5/linux/arch/m68k/mac/misc.c linux/arch/m68k/mac/misc.c --- v2.4.5/linux/arch/m68k/mac/misc.c Fri Feb 9 11:29:44 2001 +++ linux/arch/m68k/mac/misc.c Mon Jun 11 19:15:27 2001 @@ -2,7 +2,6 @@ * Miscellaneous Mac68K-specific stuff */ -#include #include #include #include @@ -12,7 +11,7 @@ #include #include #include -#include + #include #include @@ -21,6 +20,7 @@ #include #include +#include #include #include #include diff -u --recursive --new-file v2.4.5/linux/arch/m68k/mac/psc.c linux/arch/m68k/mac/psc.c --- v2.4.5/linux/arch/m68k/mac/psc.c Sun Dec 3 17:48:19 2000 +++ linux/arch/m68k/mac/psc.c Mon Jun 11 19:15:27 2001 @@ -139,7 +139,6 @@ int irq_bit,i; unsigned char events; - irq -= VEC_SPUR; base_irq = irq << 3; #ifdef DEBUG_IRQS diff -u --recursive --new-file v2.4.5/linux/arch/m68k/mac/via.c linux/arch/m68k/mac/via.c --- v2.4.5/linux/arch/m68k/mac/via.c Sun Dec 3 17:45:20 2000 +++ linux/arch/m68k/mac/via.c Mon Jun 11 19:15:27 2001 @@ -410,8 +410,6 @@ int irq_bit, i; unsigned char events, mask; - irq -= VEC_SPUR; - mask = via1[vIER] & 0x7F; if (!(events = via1[vIFR] & mask)) return; @@ -423,6 +421,7 @@ via1[vIER] = irq_bit | 0x80; } +#if 0 /* freakin' pmu is doing weird stuff */ if (!oss_present) { /* This (still) seems to be necessary to get IDE working. However, if you enable VBL interrupts, @@ -435,14 +434,13 @@ mac_do_irq_list(IRQ_MAC_NUBUS, regs); via_irq_enable(IRQ_MAC_NUBUS); } +#endif } void via2_irq(int irq, void *dev_id, struct pt_regs *regs) { int irq_bit, i; unsigned char events, mask; - - irq -= VEC_SPUR; mask = via2[gIER] & 0x7F; if (!(events = via2[gIFR] & mask)) return; diff -u --recursive --new-file v2.4.5/linux/arch/m68k/math-emu/multi_arith.h linux/arch/m68k/math-emu/multi_arith.h --- v2.4.5/linux/arch/m68k/math-emu/multi_arith.h Sun Aug 15 11:47:29 1999 +++ linux/arch/m68k/math-emu/multi_arith.h Mon Jun 11 19:15:27 2001 @@ -329,7 +329,7 @@ int carry; /* we assume here, gcc only insert move and a clr instr */ - asm volatile ("add.b %1,%0" : "=d,=g" (dest->lowmant) + asm volatile ("add.b %1,%0" : "=d,g" (dest->lowmant) : "g,d" (src->lowmant), "0,0" (dest->lowmant)); asm volatile ("addx.l %1,%0" : "=d" (dest->mant.m32[1]) : "d" (src->mant.m32[1]), "0" (dest->mant.m32[1])); @@ -360,7 +360,7 @@ extern inline void fp_submant(struct fp_ext *dest, struct fp_ext *src1, struct fp_ext *src2) { /* we assume here, gcc only insert move and a clr instr */ - asm volatile ("sub.b %1,%0" : "=d,=g" (dest->lowmant) + asm volatile ("sub.b %1,%0" : "=d,g" (dest->lowmant) : "g,d" (src2->lowmant), "0,0" (src1->lowmant)); asm volatile ("subx.l %1,%0" : "=d" (dest->mant.m32[1]) : "d" (src2->mant.m32[1]), "0" (src1->mant.m32[1])); @@ -383,7 +383,7 @@ }) #define fp_addx96(dest, src) ({ \ /* we assume here, gcc only insert move and a clr instr */ \ - asm volatile ("add.l %1,%0" : "=d,=g" (dest->m32[2]) \ + asm volatile ("add.l %1,%0" : "=d,g" (dest->m32[2]) \ : "g,d" (temp.m32[1]), "0,0" (dest->m32[2])); \ asm volatile ("addx.l %1,%0" : "=d" (dest->m32[1]) \ : "d" (temp.m32[0]), "0" (dest->m32[1])); \ diff -u --recursive --new-file v2.4.5/linux/arch/m68k/mm/init.c linux/arch/m68k/mm/init.c --- v2.4.5/linux/arch/m68k/mm/init.c Mon Oct 16 12:58:51 2000 +++ linux/arch/m68k/mm/init.c Mon Jun 11 19:15:27 2001 @@ -32,11 +32,7 @@ #include #endif -static unsigned long totalram_pages; - -#ifdef CONFIG_SUN3 -void mmu_emu_reserve_pages(unsigned long max_page); -#endif +unsigned long totalram_pages = 0; int do_check_pgt_cache(int low, int high) { @@ -86,7 +82,7 @@ void show_mem(void) { unsigned long i; - int free = 0, total = 0, reserved = 0, nonshared = 0, shared = 0; + int free = 0, total = 0, reserved = 0, shared = 0; int cached = 0; printk("\nMem-info:\n"); @@ -101,15 +97,12 @@ cached++; else if (!page_count(mem_map+i)) free++; - else if (page_count(mem_map+i) == 1) - nonshared++; else shared += page_count(mem_map+i) - 1; } printk("%d pages of RAM\n",total); printk("%d free pages\n",free); printk("%d reserved pages\n",reserved); - printk("%d pages nonshared\n",nonshared); printk("%d pages shared\n",shared); printk("%d pages swap cached\n",cached); printk("%ld pages in page table cache\n",pgtable_cache_size); @@ -137,17 +130,11 @@ #ifdef CONFIG_ATARI if (MACH_IS_ATARI) - atari_stram_reserve_pages( start_mem ); -#endif - -#ifdef CONFIG_SUN3 - /* reserve rom pages */ - mmu_emu_reserve_pages(max_mapnr); + atari_stram_mem_init_hook(); #endif /* this will put all memory onto the freelists */ totalram_pages = free_all_bootmem(); - printk("tp:%ld\n", totalram_pages); for (tmp = PAGE_OFFSET ; tmp < (unsigned long)high_memory; tmp += PAGE_SIZE) { #if 0 @@ -201,13 +188,15 @@ #ifdef CONFIG_BLK_DEV_INITRD void free_initrd_mem(unsigned long start, unsigned long end) { + int pages = 0; for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); set_page_count(virt_to_page(start), 1); free_page(start); totalram_pages++; + pages++; } - printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); + printk ("Freeing initrd memory: %dk freed\n", pages); } #endif @@ -220,15 +209,8 @@ val->sharedram = 0; val->freeram = nr_free_pages(); val->bufferram = atomic_read(&buffermem_pages); - while (i-- > 0) { - if (PageReserved(mem_map+i)) - continue; - val->totalram++; - if (!page_count(mem_map+i)) - continue; - val->sharedram += page_count(mem_map+i) - 1; - } val->totalhigh = 0; val->freehigh = 0; + val->mem_unit = PAGE_SIZE; return; } diff -u --recursive --new-file v2.4.5/linux/arch/m68k/mm/memory.c linux/arch/m68k/mm/memory.c --- v2.4.5/linux/arch/m68k/mm/memory.c Sat May 19 17:43:05 2001 +++ linux/arch/m68k/mm/memory.c Mon Jun 11 19:15:27 2001 @@ -39,6 +39,7 @@ pgd_set(pgd, (pmd_t *)BAD_PAGETABLE); } +#if 0 pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset) { pte_t *pte; @@ -63,7 +64,9 @@ } return (pte_t *)__pmd_page(*pmd) + offset; } +#endif +#if 0 pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long offset) { pmd_t *pmd; @@ -84,7 +87,7 @@ } return (pmd_t *)__pgd_page(*pgd) + offset; } - +#endif /* ++andreas: {get,free}_pointer_table rewritten to use unused fields from struct page instead of separately kmalloced struct. Stolen from @@ -250,6 +253,10 @@ if (voff == 0) return m68k_memory[i-1].addr + m68k_memory[i-1].size; + /* As a special case allow `__pa(high_memory)'. */ + if (voff == 0) + return m68k_memory[i-1].addr + m68k_memory[i-1].size; + return mm_vtop_fallback(vaddr); } #endif @@ -454,16 +461,21 @@ ".chip 68k" \ : : "a" (paddr)) -/* push and invalidate page in both caches */ +/* push and invalidate page in both caches, must disable ints + * to avoid invalidating valid data */ #define pushcl040(paddr) \ - do { push040(paddr); \ + do { unsigned long flags; \ + save_flags(flags); \ + cli(); \ + push040(paddr); \ if (CPU_IS_060) clear040(paddr); \ + restore_flags(flags); \ } while(0) /* push page in both caches, invalidate in i-cache */ +/* RZ: cpush %bc DOES invalidate %ic, regardless of DPI */ #define pushcli040(paddr) \ do { push040(paddr); \ - if (CPU_IS_060) cleari040(paddr); \ } while(0) diff -u --recursive --new-file v2.4.5/linux/arch/m68k/mvme147/config.c linux/arch/m68k/mvme147/config.c --- v2.4.5/linux/arch/m68k/mvme147/config.c Mon Nov 27 17:11:26 2000 +++ linux/arch/m68k/mvme147/config.c Mon Jun 11 19:15:27 2001 @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -29,6 +28,7 @@ #include #include #include +#include #include #include diff -u --recursive --new-file v2.4.5/linux/arch/m68k/mvme16x/config.c linux/arch/m68k/mvme16x/config.c --- v2.4.5/linux/arch/m68k/mvme16x/config.c Mon Jan 31 10:32:53 2000 +++ linux/arch/m68k/mvme16x/config.c Mon Jun 11 19:15:27 2001 @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -30,11 +29,10 @@ #include #include #include +#include #include #include -int atari_SCC_reset_done = 1; /* So SCC doesn't get reset */ -u_long atari_mch_cookie = 0; extern t_bdid mvme_bdid; static MK48T08ptr_t volatile rtc = (MK48T08ptr_t)MVME_RTC_BASE; diff -u --recursive --new-file v2.4.5/linux/arch/m68k/mvme16x/rtc.c linux/arch/m68k/mvme16x/rtc.c --- v2.4.5/linux/arch/m68k/mvme16x/rtc.c Fri Feb 9 11:29:44 2001 +++ linux/arch/m68k/mvme16x/rtc.c Mon Jun 11 19:15:27 2001 @@ -72,7 +72,7 @@ unsigned char mon, day, hrs, min, sec, leap_yr; unsigned int yrs; - if (!suser()) + if (!capable(CAP_SYS_ADMIN)) return -EACCES; if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, diff -u --recursive --new-file v2.4.5/linux/arch/m68k/q40/README linux/arch/m68k/q40/README --- v2.4.5/linux/arch/m68k/q40/README Tue Mar 6 19:44:36 2001 +++ linux/arch/m68k/q40/README Mon Jun 11 19:15:27 2001 @@ -3,43 +3,48 @@ You may try http://www.geocities.com/SiliconValley/Bay/2602/ for some up to date information. Booter and other tools will be also -available from this place and ftp.uni-erlangen.de/linux/680x0/q40/ +available from this place or ftp.uni-erlangen.de/linux/680x0/q40/ and mirrors. Hints to documentation usually refer to the linux source tree in /usr/src/linux/Documentation unless URL given. -It seems IRQ unmasking can't be safely done on a Q40. Autoprobing is -not yet implemented - do not try it! (See below) +It seems IRQ unmasking can't be safely done on a Q40. IRQ probing +is not implemented - do not try it! (See below) -For a list of kernel commandline options read the documentation for the +For a list of kernel command-line options read the documentation for the particular device drivers. The floppy imposes a very high interrupt load on the CPU, approx 30K/s. When something blocks interrupts (HD) it will loose some of them, so far -this is not known to have caused any data loss. On hihgly loaded systems -it can make the floppy very slow or practicaly stop. Other Q40 OS' simply +this is not known to have caused any data loss. On highly loaded systems +it can make the floppy very slow or practically stop. Other Q40 OS' simply poll the floppy for this reason - something that can't be done in Linux. -Only possible cure is getting a 82072 contoler with fifo instead of -the 8272A +Only possible cure is getting a 82072 controller with fifo instead of +the 8272A. -drivers used by the Q40, appart from the very obvious (console etc.): +drivers used by the Q40, apart from the very obvious (console etc.): drivers/char/q40_keyb.c # use PC keymaps for national keyboards serial.c # normal PC driver - any speed lp.c # printer driver - char/joystick/* # most of this should work + genrtc.c # RTC + char/joystick/* # most of this should work, not + # in default config.in block/q40ide.c # startup for ide ide* # see Documentation/ide.txt floppy.c # normal PC driver, DMA emu in asm/floppy.h # and arch/m68k/kernel/entry.S # see drivers/block/README.fd + net/ne.c video/q40fb.c - misc/parport_pc.c + parport/* + sound/dmasound_core.c + dmasound_q40.c Various other PC drivers can be enabled simply by adding them to arch/m68k/config.in, especially 8 bit devices should be without any problems. For cards using 16bit io/mem more care is required, like -checking byteorder issues, hacking memcpy_*_io etc. +checking byte order issues, hacking memcpy_*_io etc. Debugging @@ -47,7 +52,7 @@ Upon startup the kernel will usually output "ABCQGHIJ" into the SRAM, preceded by the booter signature. This is a trace just in case something -went wrong during earliest setup stages. +went wrong during earliest setup stages of head.S. **Changed** to preserve SRAM contents by default, this is only done when requested - SRAM must start with '%LX$' signature to do this. '-d' option to 'lxx' loader enables this. @@ -55,13 +60,15 @@ SRAM can also be used as additional console device, use debug=mem. This will save kernel startup msgs into SRAM, the screen will display only the penguin - and shell prompt if it gets that far.. +Unfortunately only 2000 bytes are available. Serial console works and can also be used for debugging, see loader_txt Most problems seem to be caused by fawlty or badly configured io-cards or -harddrives anyway..there are so many things that can go wrong here. -Make sure to configure the parallel port as SPP for first testing..the -Q40 may have trouble with parallel interrupts. +hard drives anyway. +Make sure to configure the parallel port as SPP and remove IRQ/DMA jumpers +for first testing. The Q40 does not support DMA and may have trouble with +parallel ports version of interrupts. Q40 Hardware Description @@ -71,30 +78,27 @@ questions. The Q40 consists of a 68040@40 MHz, 1MB video RAM, up to 32MB RAM, AT-style -keyboard interface, 1 Programmable LED, 2 8bit DACs and up to 1MB ROM, 1MB +keyboard interface, 1 Programmable LED, 2x8bit DACs and up to 1MB ROM, 1MB shadow ROM. +The Q60 has any of 68060 or 68LC060 and up to 128 MB RAM. -Most interfacing like floppy, hd, serial, parallel ports is done via ISA +Most interfacing like floppy, IDE, serial and parallel ports is done via ISA slots. The ISA io and mem range is mapped (sparse&byteswapped!) into separate regions of the memory. The main interrupt register IIRQ_REG will indicate whether an IRQ was internal or from some ISA devices, EIRQ_REG can distinguish up to 8 ISA IRQs. The Q40 custom chip is programmable to provide 2 periodic timers: - - 50 or 200 Hz - level 2, - - 10 or 20 KHz - level 4 - !!THIS CANT BE DISABLED!! - + - 50 or 200 Hz - level 2, !!THIS CANT BE DISABLED!! + - 10 or 20 KHz - level 4, used for dma-sound + Linux uses the 200 Hz interrupt for timer and beep by default. Interrupts ========== -q40 master chip handles only level triggered interrupts :-(( - -IRQ sharing is not yet implemented but this should be only a minor -problem.. +q40 master chip handles only a subset of level triggered interrupts. Linux has some requirements wrt interrupt architecture, these are to my knowledge: @@ -103,27 +107,28 @@ (b) working enable/disable_irq Luckily these requirements are only important for drivers shared -with other architectures - ide,serial,parallel, ethernet.. +with other architectures - ide,serial,parallel, ethernet. q40ints.c now contains a trivial hack for (a), (b) is more difficult -because only irq's 4-15 can be disabled - and only all o them at once. +because only irq's 4-15 can be disabled - and only all of them at once. Thus disable_irq() can effectively block the machine if the driver goes asleep. -One thing to keep in minde when hacking around the interrupt code is -that there is no way to find out which IRQ caused a request. +One thing to keep in mind when hacking around the interrupt code is +that there is no way to find out which IRQ caused a request, [EI]IRQ_REG +displays current state of the various IRQ lines. Keyboard ======== q40 receives AT make/break codes from the keyboard, these are translated to the PC scancodes x86 Linux uses. So by theory every national keyboard should -work just by loading the apropriate x86 keytable - see any national-HOWTO. +work just by loading the appropriate x86 keytable - see any national-HOWTO. Unfortunately the AT->PC translation isn't quite trivial and even worse, my documentation of it is absolutely minimal - thus some exotic keys may not behave exactly as expected. There is still hope that it can be fixed completely though. If you encounter -problems, email me idealy this: +problems, email me ideally this: - exact keypress/release sequence - 'showkey -s' run on q40, non-X session - 'showkey -s' run on a PC, non-X session diff -u --recursive --new-file v2.4.5/linux/arch/m68k/q40/config.c linux/arch/m68k/q40/config.c --- v2.4.5/linux/arch/m68k/q40/config.c Fri Apr 6 10:42:48 2001 +++ linux/arch/m68k/q40/config.c Mon Jun 11 19:15:27 2001 @@ -13,11 +13,9 @@ */ #include -#include #include #include #include -#include #include #include #include @@ -25,6 +23,7 @@ #include #include +#include #include #include #include @@ -32,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +39,8 @@ extern void floppy_eject(void); extern void floppy_setup(char *str, int *ints); +extern int q40kbd_translate(unsigned char scancode, unsigned char *keycode, + char raw_mode); extern void q40_process_int (int level, struct pt_regs *regs); extern void (*q40_sys_default_handler[]) (int, void *, struct pt_regs *); /* added just for debugging */ extern void q40_init_IRQ (void); @@ -50,16 +52,17 @@ static int q40_get_hardware_list(char *buffer); extern int q40_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id); extern void q40_sched_init(void (*handler)(int, void *, struct pt_regs *)); -extern int q40_keyb_init(void); -extern int q40_kbdrate (struct kbd_repeat *); + extern unsigned long q40_gettimeoffset (void); extern void q40_gettod (int *year, int *mon, int *day, int *hour, int *min, int *sec); extern int q40_hwclk (int, struct hwclk_time *); extern int q40_set_clock_mmss (unsigned long); extern void q40_reset (void); +void q40_halt(void); extern void q40_waitbut(void); void q40_set_vectors (void); + extern void (*kd_mksound)(unsigned int, unsigned int); void q40_mksound(unsigned int /*freq*/, unsigned int /*ticks*/ ); @@ -67,16 +70,9 @@ extern char m68k_debug_device[]; static void q40_mem_console_write(struct console *co, const char *b, unsigned int count); -#if 0 -extern int ql_ticks=0; -extern int sound_ticks=0; -#endif extern int ql_ticks; -static unsigned char bcd2bin (unsigned char b); -static unsigned char bin2bcd (unsigned char b); - static int q40_wait_key(struct console *co){return 0;} static struct console q40_console_driver = { name: "debug", @@ -90,11 +86,13 @@ extern char *q40_mem_cptr; /*=(char *)0xff020000;*/ static int _cpleft; +#if 0 int q40_kbd_translate(unsigned char keycode, unsigned char *keycodep, char raw_mode) { *keycodep = keycode; return 1; } +#endif static void q40_mem_console_write(struct console *co, const char *s, unsigned int count) @@ -130,13 +128,36 @@ } #endif -void q40_reset() +static int halted=0; + +#ifdef CONFIG_HEARTBEAT +static void q40_heartbeat(int on) { + if (halted) return; + if (on) + Q40_LED_ON(); + else + Q40_LED_OFF(); +} +#endif + +void q40_reset() +{ + halted=1; printk ("\n\n*******************************************\n" "Called q40_reset : press the RESET button!! \n" "*******************************************\n"); - + Q40_LED_ON(); + while(1) ; +} +void q40_halt() +{ + halted=1; + printk ("\n\n*******************\n" + " Called q40_halt\n" + "*******************\n"); + Q40_LED_ON(); while(1) ; } @@ -202,17 +223,17 @@ void __init config_q40(void) { - mach_sched_init = q40_sched_init; /* ok */ - /*mach_kbdrate = q40_kbdrate;*/ /* unneeded ?*/ - mach_keyb_init = q40_keyb_init; /* OK */ - mach_kbd_translate = q40_kbd_translate; + mach_sched_init = q40_sched_init; + + mach_keyb_init = q40kbd_init_hw; + mach_kbd_translate = q40kbd_translate; mach_init_IRQ = q40_init_IRQ; mach_gettimeoffset = q40_gettimeoffset; mach_gettod = q40_gettod; mach_hwclk = q40_hwclk; mach_set_clock_mmss = q40_set_clock_mmss; -/* mach_mksound = q40_mksound; */ - mach_reset = q40_reset; /* use reset button instead !*/ + + mach_reset = q40_reset; mach_free_irq = q40_free_irq; mach_process_int = q40_process_int; mach_get_irq_list = q40_get_irq_list; @@ -220,26 +241,28 @@ enable_irq = q40_enable_irq; disable_irq = q40_disable_irq; mach_default_handler = &q40_sys_default_handler; - mach_get_model = q40_get_model; /* no use..*/ - mach_get_hardware_list = q40_get_hardware_list; /* no use */ + mach_get_model = q40_get_model; + mach_get_hardware_list = q40_get_hardware_list; kd_mksound = q40_mksound; - /*mach_kbd_leds = q40kbd_leds;*/ + #ifdef CONFIG_MAGIC_SYSRQ mach_sysrq_key = 0x54; #endif - conswitchp = &dummy_con; -#if 0 /*def CONFIG_BLK_DEV_FD*/ - mach_floppy_setup = floppy_setup; - mach_floppy_eject = floppy_eject; - /**/ +#ifdef CONFIG_HEARTBEAT + mach_heartbeat = q40_heartbeat; #endif + mach_halt = q40_halt; + conswitchp = &dummy_con; + /* disable a few things that SMSQ might have left enabled */ q40_disable_irqs(); - mach_max_dma_address = 32*1024*1024; /* no DMA at all, but ide-scsi requires it.. */ + /* no DMA at all, but ide-scsi requires it.. make sure + * all physical RAM fits into the boundary - otherwise + * allocator may play costly and useless tricks */ + mach_max_dma_address = 1024*1024*1024; -/* useful for early debugging stages - writes kernel messages into SRAM */ - + /* useful for early debugging stages - writes kernel messages into SRAM */ if (!strncmp( m68k_debug_device,"mem",3 )) { /*printk("using NVRAM debug, q40_mem_cptr=%p\n",q40_mem_cptr);*/ @@ -252,109 +275,24 @@ int q40_parse_bootinfo(const struct bi_record *rec) { - return 1; /* unknown */ + return 1; } -#if 0 -#define DAC_LEFT ((unsigned char *)0xff008000) -#define DAC_RIGHT ((unsigned char *)0xff008004) -void q40_mksound(unsigned int hz, unsigned int ticks) -{ - /* for now ignore hz, except that hz==0 switches off sound */ - /* simply alternate the ampl 0-255-0-.. at 200Hz */ - if (hz==0) - { - if (sound_ticks) - sound_ticks=1; /* atomic - no irq spinlock used */ - - *DAC_LEFT=0; - *DAC_RIGHT=0; - return; - } - /* sound itself is done in q40_timer_int */ - if (sound_ticks == 0) sound_ticks=1000; /* pretty long beep */ - sound_ticks=ticks<<1; -} - -static void (*q40_timer_routine)(int, void *, struct pt_regs *); -static short rtc_oldsecs=0; -unsigned rtc_irq_flags=0; -unsigned rtc_irq_ctrl=0; - -static void q40_timer_int (int irq, void *dev_id, struct pt_regs *fp) -{ -#if (HZ==10000) - master_outb(-1,SAMPLE_CLEAR_REG); -#else /* must be 50 or 100 */ - master_outb(-1,FRAME_CLEAR_REG); -#endif - -#if (HZ==100) - ql_ticks = ql_ticks ? 0 : 1; - if (sound_ticks) - { - unsigned char sval=(sound_ticks & 1) ? 0 : 255; - sound_ticks--; - *DAC_LEFT=sval; - *DAC_RIGHT=sval; - } -#ifdef CONFIG_Q40RTC - if (rtc_irq_ctrl && (rtc_oldsecs != RTC_SECS)) - { - rtc_oldsecs = RTC_SECS; - rtc_irq_flags = RTC_UIE; - rtc_interrupt(); - } -#endif - if (ql_ticks) return; -#endif - q40_timer_routine(irq, dev_id, fp); +static inline unsigned char bcd2bin (unsigned char b) +{ + return ((b>>4)*10 + (b&15)); } -#endif -#if 0 -extern void (*q40_timer_routine)(int, void *, struct pt_regs *); -extern void q40_timer_int(); - -void q40_sched_init (void (*timer_routine)(int, void *, struct pt_regs *)) +static inline unsigned char bin2bcd (unsigned char b) { - int timer_irq; - - q40_timer_routine = timer_routine; - -#if (HZ==10000) - timer_irq=Q40_IRQ_TIMER; -#else - timer_irq=Q40_IRQ_FRAME; -#endif - - /*printk("registering sched/timer IRQ %d\n", timer_irq);*/ - - if (request_irq(timer_irq, q40_timer_int, 0, - "timer", q40_timer_int)) - panic ("Couldn't register timer int"); - -#if (HZ==10000) - master_outb(SAMPLE_LOW,SAMPLE_RATE_REG); - master_outb(-1,SAMPLE_CLEAR_REG); - master_outb(1,SAMPLE_ENABLE_REG); -#else - master_outb(-1,FRAME_CLEAR_REG); /* not necessary ? */ -#if (HZ==100) - master_outb( 1,FRAME_RATE_REG); -#endif -#endif + return (((b/10)*16) + (b%10)); } -#endif + unsigned long q40_gettimeoffset (void) { -#if (HZ==100) return 5000*(ql_ticks!=0); -#else - return 0; -#endif } extern void q40_gettod (int *year, int *mon, int *day, int *hour, @@ -362,7 +300,7 @@ { RTC_CTRL |= RTC_READ; *year = bcd2bin (RTC_YEAR); - *mon = bcd2bin (RTC_MNTH)-1; + *mon = bcd2bin (RTC_MNTH); *day = bcd2bin (RTC_DATE); *hour = bcd2bin (RTC_HOUR); *min = bcd2bin (RTC_MINS); @@ -371,15 +309,6 @@ } -static unsigned char bcd2bin (unsigned char b) -{ - return ((b>>4)*10 + (b&15)); -} - -static unsigned char bin2bcd (unsigned char b) -{ - return (((b/10)*16) + (b%10)); -} /* @@ -439,8 +368,6 @@ /* * Set the minutes and seconds from seconds value 'nowtime'. Fail if * clock is out by > 30 minutes. Logic lifted from atari code. - * Algorithm is to wait for the 10ms register to change, and then to - * wait a short while, and then set it. */ int q40_set_clock_mmss (unsigned long nowtime) @@ -469,18 +396,3 @@ return retval; } -extern void q40kbd_init_hw(void); - -int q40_keyb_init (void) -{ - q40kbd_init_hw(); - return 0; -} - -#if 0 -/* dummy to cause */ -void q40_slow_io() -{ - return; -} -#endif diff -u --recursive --new-file v2.4.5/linux/arch/m68k/q40/q40ints.c linux/arch/m68k/q40/q40ints.c --- v2.4.5/linux/arch/m68k/q40/q40ints.c Mon Nov 27 17:11:26 2000 +++ linux/arch/m68k/q40/q40ints.c Mon Jun 11 19:15:27 2001 @@ -1,7 +1,7 @@ /* * arch/m68k/q40/q40ints.c * - * Copyright (C) 1999 Richard Zidlicky + * Copyright (C) 1999,2001 Richard Zidlicky * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive @@ -44,7 +44,7 @@ void q40_irq2_handler (int, void *, struct pt_regs *fp); -extern void (*q40_sys_default_handler[]) (int, void *, struct pt_regs *); /* added just for debugging */ +extern void (*q40_sys_default_handler[]) (int, void *, struct pt_regs *); static void q40_defhand (int irq, void *dev_id, struct pt_regs *fp); static void sys_default_handler(int lev, void *dev_id, struct pt_regs *regs); @@ -97,9 +97,9 @@ sys_request_irq(IRQ2,q40_irq2_handler, 0, "q40 ISA and master chip", NULL); /* now enable some ints.. */ - master_outb(1,EXT_ENABLE_REG); /* hm, aint that too early? */ + master_outb(1,EXT_ENABLE_REG); /* ISA IRQ 5-15 */ - /* would be spurious ints by now, q40kbd_init_hw() does that */ + /* make sure keyboard IRQ is disabled */ master_outb(0,KEY_IRQ_ENABLE_REG); } @@ -139,7 +139,7 @@ if (dev_id==NULL) { printk("WARNING: dev_id == NULL in request_irq\n"); - dev_id=1; + dev_id=(void*)1; } irq_tab[irq].handler = handler; irq_tab[irq].flags = flags; @@ -202,7 +202,8 @@ /* * this stuff doesn't really belong here.. */ -int ql_ticks=0; + +int ql_ticks=0; /* 200Hz ticks since last jiffie */ static int sound_ticks=0; #define SVOL 45 @@ -214,7 +215,7 @@ if (hz==0) { if (sound_ticks) - sound_ticks=1; /* atomic - no irq spinlock used */ + sound_ticks=1; *DAC_LEFT=128; *DAC_RIGHT=128; @@ -227,14 +228,9 @@ } static void (*q40_timer_routine)(int, void *, struct pt_regs *); -static short rtc_oldsecs=0; -unsigned rtc_irq_flags=0; -unsigned rtc_irq_ctrl=0; static void q40_timer_int (int irq, void * dev, struct pt_regs * regs) { - - #if (HZ==100) ql_ticks = ql_ticks ? 0 : 1; if (sound_ticks) @@ -244,12 +240,12 @@ *DAC_LEFT=sval; *DAC_RIGHT=sval; } -#ifdef CONFIG_Q40RTC - if (rtc_irq_ctrl && (rtc_oldsecs != RTC_SECS)) +#if defined(CONFIG_Q40RTC) || defined(CONFIG_GEN_RTC) + if (gen_rtc_irq_ctrl && (q40rtc_oldsecs != RTC_SECS)) { - rtc_oldsecs = RTC_SECS; - rtc_irq_flags = RTC_UIE; - rtc_interrupt(); + q40rtc_oldsecs = RTC_SECS; + gen_rtc_irq_flags = RTC_UIE; + gen_rtc_interrupt(0); } #endif if (ql_ticks) return; @@ -322,16 +318,14 @@ static int ccleirq=60; /* ISA dev IRQ's*/ /*static int cclirq=60;*/ /* internal */ -/* FIX: add shared ints,mask,unmask,probing.... */ - +/* FIXME: add shared ints,mask,unmask,probing.... */ #define IRQ_INPROGRESS 1 /*static unsigned short saved_mask;*/ static int do_tint=0; #define DEBUG_Q40INT -#define IP_USE_DISABLE /* would be nice, but crashes ???? */ -/*static int dd_count=0;*/ +/*#define IP_USE_DISABLE *//* would be nice, but crashes ???? */ static int mext_disabled=0; /* ext irq disabled by master chip? */ static int aliased_irq=0; /* how many times inside handler ?*/ @@ -404,40 +398,36 @@ if ( disabled ) { #ifdef IP_USE_DISABLE - if (irq>4){ - disabled=0; - /*dd_count--;*/ - enable_irq(irq);} + if (irq>4){ + disabled=0; + enable_irq(irq);} #else - disabled=0; + disabled=0; /*printk("reenabling irq %d\n",irq); */ -#if 0 - fp->sr = ((fp->sr) & (~0x700)); /* unneeded ?! */ -#endif #endif } goto repeat; /* return; */ } } - if (mer && ccleirq>0 && !aliased_irq) + if (mer && ccleirq>0 && !aliased_irq) printk("ISA interrupt from unknown source? EIRQ_REG = %x\n",mer),ccleirq--; } iirq: - mir=master_inb(IIRQ_REG); - if (mir&IRQ_FRAME_MASK) + mir=master_inb(IIRQ_REG); + if (mir&IRQ_FRAME_MASK) { - do_tint++; - master_outb(-1,FRAME_CLEAR_REG); - } - for(;do_tint>0;do_tint--) - { - irq_tab[Q40_IRQ_FRAME].count++; - irq_tab[Q40_IRQ_FRAME].handler(Q40_IRQ_FRAME,irq_tab[Q40_IRQ_FRAME].dev_id,fp); - } - if (mir&IRQ_KEYB_MASK) /* may handle it even if actually disabled*/ - { - irq_tab[Q40_IRQ_KEYBOARD].count++; - irq_tab[Q40_IRQ_KEYBOARD].handler(Q40_IRQ_KEYBOARD,irq_tab[Q40_IRQ_KEYBOARD].dev_id,fp); + do_tint++; + master_outb(-1,FRAME_CLEAR_REG); + } + for(;do_tint>0;do_tint--) + { + irq_tab[Q40_IRQ_FRAME].count++; + irq_tab[Q40_IRQ_FRAME].handler(Q40_IRQ_FRAME,irq_tab[Q40_IRQ_FRAME].dev_id,fp); + } + if (mir&IRQ_KEYB_MASK) /* may handle it even if actually disabled*/ + { + irq_tab[Q40_IRQ_KEYBOARD].count++; + irq_tab[Q40_IRQ_KEYBOARD].handler(Q40_IRQ_KEYBOARD,irq_tab[Q40_IRQ_KEYBOARD].dev_id,fp); } } @@ -499,7 +489,7 @@ void q40_disable_irq (unsigned int irq) { /* disable ISA iqs : only do something if the driver has been - * verified to be Q40 "compatible" - right now only IDE + * verified to be Q40 "compatible" - right now IDE, NE2K * Any driver should not attempt to sleep accross disable_irq !! */ diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3/Makefile linux/arch/m68k/sun3/Makefile --- v2.4.5/linux/arch/m68k/sun3/Makefile Fri Dec 29 14:07:20 2000 +++ linux/arch/m68k/sun3/Makefile Mon Jun 11 19:15:27 2001 @@ -14,7 +14,9 @@ export-objs := sun3_ksyms.o -obj-y := config.o idprom.o mmu_emu.o sun3ints.o leds.o dvma.o \ - sbus.o intersil.o sun3_ksyms.o +obj-y := sun3_ksyms.o sun3ints.o sun3dvma.o sbus.o + +obj-$(CONFIG_SUN3) += config.o idprom.o mmu_emu.o leds.o dvma.o \ + intersil.o include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3/config.c linux/arch/m68k/sun3/config.c --- v2.4.5/linux/arch/m68k/sun3/config.c Fri Dec 29 14:07:20 2000 +++ linux/arch/m68k/sun3/config.c Mon Jun 11 19:15:27 2001 @@ -8,13 +8,10 @@ * for more details. */ -#include - #include #include #include #include -#include #include #include #include @@ -27,10 +24,12 @@ #include #include #include +#include #include #include #include #include +#include extern char _text, _end; @@ -39,15 +38,6 @@ extern unsigned long sun3_gettimeoffset(void); extern int sun3_get_irq_list (char *); extern void sun3_sched_init(void (*handler)(int, void *, struct pt_regs *)); -extern void sun3_init_IRQ (void); -extern void (*sun3_default_handler[]) (int, void *, struct pt_regs *); -extern int sun3_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_regs *), - unsigned long flags, const char *devname, void *dev_id); -extern void sun3_free_irq (unsigned int irq, void *dev_id); -extern void sun3_enable_irq (unsigned int); -extern void sun3_disable_irq (unsigned int); -extern void sun3_enable_interrupts (void); -extern void sun3_disable_interrupts (void); extern void sun3_get_model (char* model); extern void idprom_init (void); extern void sun3_gettod (int *yearp, int *monp, int *dayp, @@ -56,7 +46,7 @@ extern void sun_serial_setup(void); volatile char* clock_va; -extern unsigned char* sun3_intreg; +extern volatile unsigned char* sun3_intreg; extern unsigned long availmem; unsigned long num_pages; @@ -76,7 +66,7 @@ prom_init((void *)LINUX_OPPROM_BEGVM); GET_CONTROL_BYTE(AC_SENABLE,enable_register); - enable_register |= 0x40; /* Enable FPU */ + enable_register |= 0x50; /* Enable FPU */ SET_CONTROL_BYTE(AC_SENABLE,enable_register); GET_CONTROL_BYTE(AC_SENABLE,enable_register); @@ -154,6 +144,7 @@ // mach_keyb_init = sun3_keyb_init; enable_irq = sun3_enable_irq; disable_irq = sun3_disable_irq; + mach_process_int = sun3_process_int; mach_get_irq_list = sun3_get_irq_list; mach_gettod = sun3_gettod; mach_reset = sun3_reboot; @@ -161,7 +152,7 @@ mach_get_model = sun3_get_model; mach_hwclk = sun3_hwclk; mach_halt = sun3_halt; -#ifndef CONFIG_SERIAL_CONSOLE +#if !defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_FB) conswitchp = &dummy_con; #endif diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3/dvma.c linux/arch/m68k/sun3/dvma.c --- v2.4.5/linux/arch/m68k/sun3/dvma.c Fri Dec 29 14:07:20 2000 +++ linux/arch/m68k/sun3/dvma.c Mon Jun 11 19:15:27 2001 @@ -4,42 +4,62 @@ #include #include #include +#include #include #include #include #include -unsigned long dvma_next_free = DVMA_START; -unsigned long dvma_region_end = DVMA_START + (DVMA_RESERVED_PMEGS * SUN3_PMEG_SIZE); +static unsigned long ptelist[120]; -/* reserve such dma memory as we see fit */ -void sun3_dvma_init(void) +inline unsigned long dvma_page(unsigned long kaddr, unsigned long vaddr) { - unsigned long dvma_phys_start; - - dvma_phys_start = (sun3_get_pte(DVMA_START) & - SUN3_PAGE_PGNUM_MASK); - dvma_phys_start <<= PAGE_SHIFT; + unsigned long pte; + unsigned long j; + pte_t ptep; - reserve_bootmem(dvma_phys_start, - (DVMA_RESERVED_PMEGS * SUN3_PMEG_SIZE)); + j = *(volatile unsigned long *)kaddr; + *(volatile unsigned long *)kaddr = j; -} + ptep = __mk_pte(kaddr, PAGE_KERNEL); + pte = pte_val(ptep); +// printk("dvma_remap: addr %lx -> %lx pte %08lx len %x\n", +// kaddr, vaddr, pte, len); + if(ptelist[(vaddr & 0xff000) >> PAGE_SHIFT] != pte) { + sun3_put_pte(vaddr, pte); + ptelist[(vaddr & 0xff000) >> PAGE_SHIFT] = pte; + } -/* get needed number of free dma pages, or panic if not enough */ + return (vaddr + (kaddr & ~PAGE_MASK)); -void *sun3_dvma_malloc(int len) +} + +int dvma_map_iommu(unsigned long kaddr, unsigned long baddr, + int len) { + + unsigned long end; unsigned long vaddr; - if((dvma_next_free + len) > dvma_region_end) - panic("sun3_dvma_malloc: out of dvma pages"); + vaddr = dvma_btov(baddr); + + end = vaddr + len; - vaddr = dvma_next_free; - dvma_next_free = DVMA_ALIGN(dvma_next_free + len); + while(vaddr < end) { + dvma_page(kaddr, vaddr); + kaddr += PAGE_SIZE; + vaddr += PAGE_SIZE; + } + + return 0; - return (void *)vaddr; } - +void sun3_dvma_init(void) +{ + + memset(ptelist, 0, sizeof(ptelist)); + + +} diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3/intersil.c linux/arch/m68k/sun3/intersil.c --- v2.4.5/linux/arch/m68k/sun3/intersil.c Wed Jan 26 12:44:21 2000 +++ linux/arch/m68k/sun3/intersil.c Mon Jun 11 19:15:27 2001 @@ -11,9 +11,9 @@ */ #include -#include #include +#include #include @@ -30,7 +30,7 @@ void sun3_gettod (int *yearp, int *monp, int *dayp, int *hourp, int *minp, int *secp) { - u_char wday; + unsigned char wday; volatile struct intersil_dt* todintersil; unsigned long flags; diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3/mmu_emu.c linux/arch/m68k/sun3/mmu_emu.c --- v2.4.5/linux/arch/m68k/sun3/mmu_emu.c Fri Dec 29 14:07:20 2000 +++ linux/arch/m68k/sun3/mmu_emu.c Mon Jun 11 19:15:27 2001 @@ -29,6 +29,7 @@ extern void prom_reboot (char *) __attribute__ ((__noreturn__)); #undef DEBUG_MMU_EMU +#define DEBUG_PROM_MAPS /* ** Defines @@ -157,9 +158,12 @@ j = 0; for (num=0, seg=0x0F800000; seg<0x10000000; seg+=16*PAGE_SIZE) { if (sun3_get_segmap (seg) != SUN3_INVALID_PMEG) { -#ifdef DEBUG_MMU_EMU - printk ("mapped:"); - print_pte_vaddr (seg); +#ifdef DEBUG_PROM_MAPS + for(i = 0; i < 16; i++) { + printk ("mapped:"); + print_pte_vaddr (seg + (i*PAGE_SIZE)); + break; + } #endif // the lowest mapping here is the end of our // vmalloc region @@ -174,7 +178,7 @@ } - sun3_dvma_init(); + dvma_init(); /* blank everything below the kernel, and we've got the base diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3/sbus.c linux/arch/m68k/sun3/sbus.c --- v2.4.5/linux/arch/m68k/sun3/sbus.c Wed Sep 8 11:20:42 1999 +++ linux/arch/m68k/sun3/sbus.c Mon Jun 11 19:15:27 2001 @@ -12,8 +12,12 @@ #include #include +extern void rs_init(void); + void __init sbus_init(void) { + + rs_init(); } diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3/sun3_ksyms.c linux/arch/m68k/sun3/sun3_ksyms.c --- v2.4.5/linux/arch/m68k/sun3/sun3_ksyms.c Fri Jan 28 08:04:58 2000 +++ linux/arch/m68k/sun3/sun3_ksyms.c Mon Jun 11 19:15:27 2001 @@ -6,5 +6,8 @@ /* * Add things here when you find the need for it. */ -EXPORT_SYMBOL(sun3_dvma_malloc); +EXPORT_SYMBOL(dvma_map_align); +EXPORT_SYMBOL(dvma_unmap); +EXPORT_SYMBOL(dvma_malloc_align); +EXPORT_SYMBOL(dvma_free); EXPORT_SYMBOL(idprom); diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3/sun3dvma.c linux/arch/m68k/sun3/sun3dvma.c --- v2.4.5/linux/arch/m68k/sun3/sun3dvma.c Wed Dec 31 16:00:00 1969 +++ linux/arch/m68k/sun3/sun3dvma.c Mon Jun 11 19:15:27 2001 @@ -0,0 +1,295 @@ +/* + * linux/arch/m68k/mm/sun3dvma.c + * + * Copyright (C) 2000 Sam Creasey + * + * Contains common routines for sun3/sun3x DVMA management. + */ + +#include +#include +#include + +#include +#include +#include + +#ifdef CONFIG_SUN3X +extern void dvma_unmap_iommu(unsigned long baddr, int len); +#else +static inline void dvma_unmap_iommu(unsigned long a, int b) +{ +} +#endif + +unsigned long iommu_use[IOMMU_TOTAL_ENTRIES]; + +#define dvma_index(baddr) ((baddr - DVMA_START) >> DVMA_PAGE_SHIFT) + +#define dvma_entry_use(baddr) (iommu_use[dvma_index(baddr)]) + +struct hole { + unsigned long start; + unsigned long end; + unsigned long size; + struct list_head list; +}; + +static struct list_head hole_list; +static struct list_head hole_cache; +static struct hole initholes[64]; + +static inline int refill(void) +{ + + struct hole *hole; + struct hole *prev = NULL; + struct list_head *cur; + int ret = 0; + + list_for_each(cur, &hole_list) { + hole = list_entry(cur, struct hole, list); + + if(!prev) { + prev = hole; + continue; + } + + if(hole->end == prev->start) { + hole->size += prev->size; + hole->end = prev->end; + list_del(&(prev->list)); + list_add(&(prev->list), &hole_cache); + ret++; + } + + } + + return ret; +} + +static inline struct hole *rmcache(void) +{ + struct hole *ret; + + if(list_empty(&hole_cache)) { + if(!refill()) { + printk("out of dvma hole cache!\n"); + BUG(); + } + } + + ret = list_entry(hole_cache.next, struct hole, list); + list_del(&(ret->list)); + + return ret; + +} + +static inline unsigned long get_baddr(int len, unsigned long align) +{ + + struct list_head *cur; + struct hole *hole; + + if(list_empty(&hole_list)) { + printk("out of dvma holes!\n"); + BUG(); + } + + list_for_each(cur, &hole_list) { + unsigned long newlen; + + hole = list_entry(cur, struct hole, list); + + if(align > DVMA_PAGE_SIZE) + newlen = len + ((hole->end - len) & (align-1)); + else + newlen = len; + + if(hole->size > newlen) { + hole->end -= newlen; + hole->size -= newlen; + dvma_entry_use(hole->end) = newlen; + return hole->end; + } else if(hole->size == newlen) { + list_del(&(hole->list)); + list_add(&(hole->list), &hole_cache); + dvma_entry_use(hole->start) = newlen; + return hole->start; + } + + } + + printk("unable to find dvma hole!\n"); + BUG(); + return 0; +} + +static inline int free_baddr(unsigned long baddr) +{ + + unsigned long len; + struct hole *hole; + struct list_head *cur; + unsigned long orig_baddr; + + orig_baddr = baddr; + len = dvma_entry_use(baddr); + dvma_entry_use(baddr) = 0; + baddr &= DVMA_PAGE_MASK; + dvma_unmap_iommu(baddr, len); + + list_for_each(cur, &hole_list) { + hole = list_entry(cur, struct hole, list); + + if(hole->end == baddr) { + hole->end += len; + hole->size += len; + return 0; + } else if(hole->start == (baddr + len)) { + hole->start = baddr; + hole->size += len; + return 0; + } + + } + + hole = rmcache(); + + hole->start = baddr; + hole->end = baddr + len; + hole->size = len; + +// list_add_tail(&(hole->list), cur); + list_add(&(hole->list), cur); + + return 0; + +} + +void dvma_init(void) +{ + + struct hole *hole; + int i; + + INIT_LIST_HEAD(&hole_list); + INIT_LIST_HEAD(&hole_cache); + + /* prepare the hole cache */ + for(i = 0; i < 64; i++) + list_add(&(initholes[i].list), &hole_cache); + + hole = rmcache(); + hole->start = DVMA_START; + hole->end = DVMA_END; + hole->size = DVMA_SIZE; + + list_add(&(hole->list), &hole_list); + + memset(iommu_use, 0, sizeof(iommu_use)); + + dvma_unmap_iommu(DVMA_START, DVMA_SIZE); + +#ifdef CONFIG_SUN3 + sun3_dvma_init(); +#endif + +} + +inline unsigned long dvma_map_align(unsigned long kaddr, int len, int align) +{ + + unsigned long baddr; + unsigned long off; + + if(!len) + len = 0x800; + + if(!kaddr || !len) { +// printk("error: kaddr %lx len %x\n", kaddr, len); +// *(int *)4 = 0; + return 0; + } + +#ifdef DEBUG + printk("dvma_map request %08lx bytes from %08lx\n", + len, kaddr); +#endif + off = kaddr & ~DVMA_PAGE_MASK; + kaddr &= PAGE_MASK; + len += off; + len = ((len + (DVMA_PAGE_SIZE-1)) & DVMA_PAGE_MASK); + + if(align == 0) + align = DVMA_PAGE_SIZE; + else + align = ((align + (DVMA_PAGE_SIZE-1)) & DVMA_PAGE_MASK); + + baddr = get_baddr(len, align); +// printk("using baddr %lx\n", baddr); + + if(!dvma_map_iommu(kaddr, baddr, len)) + return (baddr + off); + + printk("dvma_map failed kaddr %lx baddr %lx len %x\n", kaddr, baddr, len); + BUG(); + return 0; +} + +void dvma_unmap(void *baddr) +{ + + free_baddr((unsigned long)baddr); + + return; + +} + + +void *dvma_malloc_align(unsigned long len, unsigned long align) +{ + unsigned long kaddr; + unsigned long baddr; + unsigned long vaddr; + + if(!len) + return NULL; + +#ifdef DEBUG + printk("dvma_malloc request %lx bytes\n", len); +#endif + len = ((len + (DVMA_PAGE_SIZE-1)) & DVMA_PAGE_MASK); + + if((kaddr = __get_free_pages(GFP_ATOMIC, get_order(len))) == 0) + return NULL; + + if((baddr = (unsigned long)dvma_map_align(kaddr, len, align)) == 0) { + free_pages(kaddr, get_order(len)); + return NULL; + } + + vaddr = dvma_btov(baddr); + + if(dvma_map_cpu(kaddr, vaddr, len) < 0) { + dvma_unmap((void *)baddr); + free_pages(kaddr, get_order(len)); + return NULL; + } + +#ifdef DEBUG + printk("mapped %08lx bytes %08lx kern -> %08lx bus\n", + len, kaddr, baddr); +#endif + + return (void *)vaddr; + +} + +void dvma_free(void *vaddr) +{ + + return; + +} diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3/sun3ints.c linux/arch/m68k/sun3/sun3ints.c --- v2.4.5/linux/arch/m68k/sun3/sun3ints.c Fri Dec 29 14:07:20 2000 +++ linux/arch/m68k/sun3/sun3ints.c Mon Jun 11 19:15:27 2001 @@ -1,5 +1,5 @@ /* - * linux/arch/m68k/sun3/sun3ints.c -- Sun-3 Linux interrupt handling code + * linux/arch/m68k/sun3/sun3ints.c -- Sun-3(x) Linux interrupt handling code * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive @@ -35,7 +35,7 @@ ~(0x10), ~(0x08) }; -unsigned char* sun3_intreg; +volatile unsigned char* sun3_intreg; void sun3_insert_irq(irq_node_t **list, irq_node_t *node) { @@ -45,10 +45,6 @@ { } -void sun3_free_irq(unsigned int irq, void *dev_id) -{ -} - void sun3_enable_irq(unsigned int irq) { *sun3_intreg |= (1<= 64) && (irq <= 255)) { + int vec; + + vec = irq - 64; + if(sun3_vechandler[vec] != NULL) { + printk("sun3_request_irq: request for vec %d -- already taken!\n", irq); + return 1; + } + + sun3_vechandler[vec] = handler; + vec_ids[vec] = dev_id; + vec_names[vec] = devname; + + return 0; + } + } - /* setting devname would be nice */ - - sys_request_irq(irq, sun3_default_handler[irq], 0, devname, NULL); - + printk("sun3_request_irq: invalid irq %d\n", irq); + return 1; - return 0; } +void sun3_free_irq(unsigned int irq, void *dev_id) +{ + + if(irq < SYS_IRQS) { + if(sun3_inthandler[irq] == NULL) + panic("sun3_free_int: attempt to free unused irq %d\n", irq); + if(dev_ids[irq] != dev_id) + panic("sun3_free_int: incorrect dev_id for irq %d\n", irq); + + sun3_inthandler[irq] = NULL; + return; + } else if((irq >= 64) && (irq <= 255)) { + int vec; + + vec = irq - 64; + if(sun3_vechandler[vec] == NULL) + panic("sun3_free_int: attempt to free unused vector %d\n", irq); + if(vec_ids[irq] != dev_id) + panic("sun3_free_int: incorrect dev_id for vec %d\n", irq); + + sun3_vechandler[vec] = NULL; + return; + } else { + panic("sun3_free_irq: invalid irq %d\n", irq); + } +} + +void sun3_process_int(int irq, struct pt_regs *regs) +{ + + if((irq >= 64) && (irq <= 255)) { + int vec; + + vec = irq - 64; + if(sun3_vechandler[vec] == NULL) + panic ("bad interrupt vector %d received\n",irq); + + sun3_vechandler[vec](irq, vec_ids[vec], regs); + return; + } else { + panic("sun3_process_int: unable to handle interrupt vector %d\n", + irq); + } +} diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3x/Makefile linux/arch/m68k/sun3x/Makefile --- v2.4.5/linux/arch/m68k/sun3x/Makefile Fri Dec 29 14:07:20 2000 +++ linux/arch/m68k/sun3x/Makefile Mon Jun 11 19:15:27 2001 @@ -9,6 +9,6 @@ O_TARGET := sun3x.o -obj-y := config.o time.o dvma.o sbus.o +obj-y := config.o time.o dvma.o prom.o include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3x/config.c linux/arch/m68k/sun3x/config.c --- v2.4.5/linux/arch/m68k/sun3x/config.c Thu Aug 26 12:42:31 1999 +++ linux/arch/m68k/sun3x/config.c Mon Jun 11 19:15:27 2001 @@ -14,39 +14,24 @@ #include #include #include -#include +#include +#include +#include #include "time.h" -static volatile unsigned char *sun3x_intreg = (unsigned char *)SUN3X_INTREG; -extern int serial_console; +volatile char *clock_va; +extern volatile unsigned char *sun3_intreg; -void sun3x_halt(void) -{ - /* Disable interrupts */ - cli(); - - /* we can't drop back to PROM, so we loop here */ - for (;;); -} - -void sun3x_reboot(void) -{ - /* This never returns, don't bother saving things */ - cli(); - - /* no idea, whether this works */ - asm ("reset"); -} int __init sun3x_keyb_init(void) { - return 0; + return 0; } int sun3x_kbdrate(struct kbd_repeat *r) { - return 0; + return 0; } void sun3x_kbd_leds(unsigned int i) @@ -54,36 +39,15 @@ } -static void sun3x_badint (int irq, void *dev_id, struct pt_regs *fp) +void sun3_leds(unsigned int i) { - printk ("received spurious interrupt %d\n",irq); - num_spurious += 1; -} -void (*sun3x_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = { - sun3x_badint, sun3x_badint, sun3x_badint, sun3x_badint, - sun3x_badint, sun3x_badint, sun3x_badint, sun3x_badint -}; - -void sun3x_enable_irq(unsigned int irq) -{ - *sun3x_intreg |= (1 << irq); } -void sun3x_disable_irq(unsigned int irq) +/* should probably detect types of these eventually. */ +static void sun3x_get_model(char *model) { - *sun3x_intreg &= ~(1 << irq); -} - -void __init sun3x_init_IRQ(void) -{ - /* disable all interrupts initially */ - *sun3x_intreg = 1; /* master enable only */ -} - -int sun3x_get_irq_list(char *buf) -{ - return 0; + sprintf(model, "Sun3x"); } /* @@ -91,38 +55,51 @@ */ void __init config_sun3x(void) { - mach_get_irq_list = sun3x_get_irq_list; - mach_max_dma_address = 0xffffffff; /* we can DMA anywhere, whee */ - mach_keyb_init = sun3x_keyb_init; - mach_kbdrate = sun3x_kbdrate; - mach_kbd_leds = sun3x_kbd_leds; - - mach_sched_init = sun3x_sched_init; - mach_init_IRQ = sun3x_init_IRQ; - enable_irq = sun3x_enable_irq; - disable_irq = sun3x_disable_irq; - mach_request_irq = sys_request_irq; - mach_free_irq = sys_free_irq; - mach_default_handler = &sun3x_default_handler; - mach_gettimeoffset = sun3x_gettimeoffset; - mach_reset = sun3x_reboot; + sun3x_prom_init(); + + mach_get_irq_list = sun3_get_irq_list; + mach_max_dma_address = 0xffffffff; /* we can DMA anywhere, whee */ - mach_gettod = sun3x_gettod; + mach_keyb_init = sun3x_keyb_init; + mach_kbdrate = sun3x_kbdrate; + mach_kbd_leds = sun3x_kbd_leds; + + mach_default_handler = &sun3_default_handler; + mach_sched_init = sun3x_sched_init; + mach_init_IRQ = sun3_init_IRQ; + enable_irq = sun3_enable_irq; + disable_irq = sun3_disable_irq; + mach_request_irq = sun3_request_irq; + mach_free_irq = sun3_free_irq; + mach_process_int = sun3_process_int; - switch (*(unsigned char *)SUN3X_EEPROM_CONS) { + mach_gettimeoffset = sun3x_gettimeoffset; + mach_reset = sun3x_reboot; + + mach_gettod = sun3x_gettod; + mach_hwclk = sun3x_hwclk; + mach_get_model = sun3x_get_model; + + sun3_intreg = (unsigned char *)SUN3X_INTREG; + + /* only the serial console is known to work anyway... */ +#if 0 + switch (*(unsigned char *)SUN3X_EEPROM_CONS) { case 0x10: - serial_console = 1; - conswitchp = NULL; - break; + serial_console = 1; + conswitchp = NULL; + break; case 0x11: - serial_console = 2; - conswitchp = NULL; - break; + serial_console = 2; + conswitchp = NULL; + break; default: - serial_console = 0; - conswitchp = &dummy_con; - break; - } + serial_console = 0; + conswitchp = &dummy_con; + break; + } +#endif } + diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3x/dvma.c linux/arch/m68k/sun3x/dvma.c --- v2.4.5/linux/arch/m68k/sun3x/dvma.c Tue May 11 09:57:14 1999 +++ linux/arch/m68k/sun3x/dvma.c Mon Jun 11 19:15:27 2001 @@ -2,21 +2,31 @@ * Virtual DMA allocation * * (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de) + * + * 11/26/2000 -- disabled the existing code because it didn't work for + * me in 2.4. Replaced with a significantly more primitive version + * similar to the sun3 code. the old functionality was probably more + * desirable, but.... -- Sam Creasey (sammy@oh.verio.com) + * */ #include #include #include #include +#include +#include +#include #include #include #include #include +#include +#include /* IOMMU support */ -#define IOMMU_ENTRIES 2048 #define IOMMU_ADDR_MASK 0x03ffe000 #define IOMMU_CACHE_INHIBIT 0x00000040 #define IOMMU_FULL_BLOCK 0x00000020 @@ -28,135 +38,170 @@ #define IOMMU_DT_VALID 0x00000001 #define IOMMU_DT_BAD 0x00000002 -#define DVMA_PAGE_SHIFT 13 -#define DVMA_PAGE_SIZE (1UL << DVMA_PAGE_SHIFT) -#define DVMA_PAGE_MASK (~(DVMA_PAGE_SIZE-1)) - static volatile unsigned long *iommu_pte = (unsigned long *)SUN3X_IOMMU; -static unsigned long iommu_use[IOMMU_ENTRIES]; -static unsigned long iommu_bitmap[IOMMU_ENTRIES/32]; #define dvma_entry_paddr(index) (iommu_pte[index] & IOMMU_ADDR_MASK) #define dvma_entry_vaddr(index,paddr) ((index << DVMA_PAGE_SHIFT) | \ (paddr & (DVMA_PAGE_SIZE-1))) +#if 0 +#define dvma_entry_set(index,addr) (iommu_pte[index] = \ + (addr & IOMMU_ADDR_MASK) | \ + IOMMU_DT_VALID | IOMMU_CACHE_INHIBIT) +#else #define dvma_entry_set(index,addr) (iommu_pte[index] = \ (addr & IOMMU_ADDR_MASK) | \ IOMMU_DT_VALID) +#endif #define dvma_entry_clr(index) (iommu_pte[index] = IOMMU_DT_INVALID) -#define dvma_entry_use(index) (iommu_use[index]) -#define dvma_entry_inc(index) (iommu_use[index]++) -#define dvma_entry_dec(index) (iommu_use[index]--) #define dvma_entry_hash(addr) ((addr >> DVMA_PAGE_SHIFT) ^ \ ((addr & 0x03c00000) >> \ (DVMA_PAGE_SHIFT+4))) -#define dvma_map iommu_bitmap -#define dvma_map_size (IOMMU_ENTRIES/2) -#define dvma_slow_offset (IOMMU_ENTRIES/2) -#define dvma_is_slow(addr) ((addr) & \ - (dvma_slow_offset << DVMA_PAGE_SHIFT)) -static int fixed_dvma; +#undef DEBUG -void __init dvma_init(void) +#ifdef DEBUG +/* code to print out a dvma mapping for debugging purposes */ +void dvma_print (unsigned long dvma_addr) { - unsigned long tmp; - if ((unsigned long)high_memory < (IOMMU_ENTRIES << DVMA_PAGE_SHIFT)) { - printk ("Sun3x fixed DVMA mapping\n"); - fixed_dvma = 1; - for (tmp = 0; tmp < (unsigned long)high_memory; tmp += DVMA_PAGE_SIZE) - dvma_entry_set (tmp >> DVMA_PAGE_SHIFT, virt_to_phys((void *)tmp)); - fixed_dvma = 1; - } else { - printk ("Sun3x variable DVMA mapping\n"); - for (tmp = 0; tmp < IOMMU_ENTRIES; tmp++) - dvma_entry_clr (tmp); - fixed_dvma = 0; - } + unsigned long index; + + index = dvma_addr >> DVMA_PAGE_SHIFT; + + printk("idx %lx dvma_addr %08lx paddr %08lx\n", index, dvma_addr, + dvma_entry_paddr(index)); + + } +#endif -unsigned long dvma_slow_alloc (unsigned long paddr, int npages) + +/* create a virtual mapping for a page assigned within the IOMMU + so that the cpu can reach it easily */ +inline int dvma_map_cpu(unsigned long kaddr, + unsigned long vaddr, int len) { - int scan, base; - - scan = 0; - for (;;) { - scan = find_next_zero_bit(dvma_map, dvma_map_size, scan); - if ((base = scan) + npages > dvma_map_size) { - printk ("dvma_slow_alloc failed for %d pages\n",npages); - return 0; - } - for (;;) { - if (scan >= base + npages) goto found; - if (test_bit(scan, dvma_map)) break; - scan++; - } - } + pgd_t *pgd; + unsigned long end; + int ret = 0; + + kaddr &= PAGE_MASK; + vaddr &= PAGE_MASK; + + end = PAGE_ALIGN(vaddr + len); + +#ifdef DEBUG + printk("dvma: mapping kern %08lx to virt %08lx\n", + kaddr, vaddr); +#endif + pgd = pgd_offset_k(vaddr); + + do { + pmd_t *pmd; + unsigned long end2; + + if((pmd = pmd_alloc_kernel(pgd, vaddr)) == NULL) { + ret = -ENOMEM; + goto out; + } + + if((end & PGDIR_MASK) > (vaddr & PGDIR_MASK)) + end2 = (vaddr + (PGDIR_SIZE-1)) & PGDIR_MASK; + else + end2 = end; + + do { + pte_t *pte; + unsigned long end3; + + if((pte = pte_alloc_kernel(pmd, vaddr)) == NULL) { + ret = -ENOMEM; + goto out; + } + + if((end2 & PMD_MASK) > (vaddr & PMD_MASK)) + end3 = (vaddr + (PMD_SIZE-1)) & PMD_MASK; + else + end3 = end2; + + do { +#ifdef DEBUG + printk("mapping %08lx phys to %08lx\n", + __pa(kaddr), vaddr); +#endif + set_pte(pte, __mk_pte(kaddr, PAGE_KERNEL)); + pte++; + kaddr += PAGE_SIZE; + vaddr += PAGE_SIZE; + } while(vaddr < end3); + + } while(vaddr < end2); + + } while(vaddr < end); + + flush_tlb_all(); -found: - for (scan = base; scan < base+npages; scan++) { - dvma_entry_set(scan+dvma_slow_offset, paddr); - paddr += DVMA_PAGE_SIZE; - set_bit(scan, dvma_map); - } - return (dvma_entry_vaddr((base+dvma_slow_offset),paddr)); + out: + return ret; } -unsigned long dvma_alloc (unsigned long paddr, unsigned long size) + +inline int dvma_map_iommu(unsigned long kaddr, unsigned long baddr, + int len) { - int index; - int pages = ((paddr & ~DVMA_PAGE_MASK) + size + (DVMA_PAGE_SIZE-1)) >> - DVMA_PAGE_SHIFT; - - if (fixed_dvma) - return ((unsigned long)phys_to_virt (paddr)); - - if (pages > 1) /* multi page, allocate from slow pool */ - return dvma_slow_alloc (paddr, pages); - - index = dvma_entry_hash (paddr); - - if (dvma_entry_use(index)) { - if (dvma_entry_paddr(index) == (paddr & DVMA_PAGE_MASK)) { - dvma_entry_inc(index); - return dvma_entry_vaddr(index,paddr); + unsigned long end, index; + + index = baddr >> DVMA_PAGE_SHIFT; + end = ((baddr+len) >> DVMA_PAGE_SHIFT); + + if(len & ~DVMA_PAGE_MASK) + end++; + + for(; index < end ; index++) { +// if(dvma_entry_use(index)) +// BUG(); +// printk("mapping pa %lx to ba %lx\n", __pa(kaddr), index << DVMA_PAGE_SHIFT); + + dvma_entry_set(index, __pa(kaddr)); + + iommu_pte[index] |= IOMMU_FULL_BLOCK; +// dvma_entry_inc(index); + + kaddr += DVMA_PAGE_SIZE; } - /* collision, allocate from slow pool */ - return dvma_slow_alloc (paddr, pages); - } - - dvma_entry_set(index,paddr); - dvma_entry_inc(index); - return dvma_entry_vaddr(index,paddr); + +#ifdef DEBUG + for(index = (baddr >> DVMA_PAGE_SHIFT); index < end; index++) + dvma_print(index << DVMA_PAGE_SHIFT); +#endif + return 0; + } -void dvma_free (unsigned long dvma_addr, unsigned long size) +void dvma_unmap_iommu(unsigned long baddr, int len) { - int npages; - int index; - - if (fixed_dvma) - return; - - if (!dvma_is_slow(dvma_addr)) { - index = (dvma_addr >> DVMA_PAGE_SHIFT); - if (dvma_entry_use(index) == 0) { - printk ("dvma_free: %lx entry already free\n",dvma_addr); - return; + + int index, end; + + + index = baddr >> DVMA_PAGE_SHIFT; + end = (DVMA_PAGE_ALIGN(baddr+len) >> DVMA_PAGE_SHIFT); + + for(; index < end ; index++) { +#ifdef DEBUG + printk("freeing bus mapping %08x\n", index << DVMA_PAGE_SHIFT); +#endif +#if 0 + if(!dvma_entry_use(index)) + printk("dvma_unmap freeing unused entry %04x\n", + index); + else + dvma_entry_dec(index); +#endif + dvma_entry_clr(index); } - dvma_entry_dec(index); - if (dvma_entry_use(index) == 0) - dvma_entry_clr(index); - return; - } - - /* free in slow pool */ - npages = ((dvma_addr & ~DVMA_PAGE_MASK) + size + (DVMA_PAGE_SIZE-1)) >> - DVMA_PAGE_SHIFT; - for (index = (dvma_addr >> DVMA_PAGE_SHIFT); npages--; index++) { - dvma_entry_clr(index); - clear_bit (index,dvma_map); - } + } + diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3x/prom.c linux/arch/m68k/sun3x/prom.c --- v2.4.5/linux/arch/m68k/sun3x/prom.c Wed Dec 31 16:00:00 1969 +++ linux/arch/m68k/sun3x/prom.c Mon Jun 11 19:15:27 2001 @@ -0,0 +1,165 @@ +/* Prom access routines for the sun3x */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void (*sun3x_putchar)(int); +int (*sun3x_getchar)(void); +int (*sun3x_mayget)(void); +int (*sun3x_mayput)(int); +void (*sun3x_prom_reboot)(void); +e_vector sun3x_prom_abort; +struct idprom *idprom; +static struct idprom idprom_buffer; +struct linux_romvec *romvec; + +/* prom vector table */ +e_vector *sun3x_prom_vbr; + +extern e_vector vectors[256]; /* arch/m68k/kernel/traps.c */ + +/* Handle returning to the prom */ +void sun3x_halt(void) +{ + unsigned long flags; + + /* Disable interrupts while we mess with things */ + save_flags(flags); cli(); + + /* Restore prom vbr */ + __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr)); + + /* Restore prom NMI clock */ +// sun3x_disable_intreg(5); + sun3_enable_irq(7); + + /* Let 'er rip */ + __asm__ volatile ("trap #14" : : ); + + /* Restore everything */ + sun3_disable_irq(7); + sun3_enable_irq(5); + + __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors)); + restore_flags(flags); +} + +void sun3x_reboot(void) +{ + /* This never returns, don't bother saving things */ + cli(); + + /* Restore prom vbr */ + __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr)); + + /* Restore prom NMI clock */ + sun3_disable_irq(5); + sun3_enable_irq(7); + + /* Let 'er rip */ + (*romvec->pv_reboot)("vmlinux"); +} + +extern char m68k_debug_device[]; + +static void sun3x_prom_write(struct console *co, const char *s, + unsigned int count) +{ + while (count--) { + if (*s == '\n') + sun3x_putchar('\r'); + sun3x_putchar(*s++); + } +} + +/* debug console - write-only */ + +static struct console sun3x_debug = { + "debug", + sun3x_prom_write, /* write */ + NULL, /* read */ + NULL, /* device */ + NULL, /* wait_key */ + NULL, /* unblank */ + NULL, /* setup */ + CON_PRINTBUFFER, + -1, + 0, + NULL +}; + +void sun3x_prom_init(void) +{ + /* Read the vector table */ + int i; + + + sun3x_putchar = *(void (**)(int)) (SUN3X_P_PUTCHAR); + sun3x_getchar = *(int (**)(void)) (SUN3X_P_GETCHAR); + sun3x_mayget = *(int (**)(void)) (SUN3X_P_MAYGET); + sun3x_mayput = *(int (**)(int)) (SUN3X_P_MAYPUT); + sun3x_prom_reboot = *(void (**)(void)) (SUN3X_P_REBOOT); + sun3x_prom_abort = *(e_vector *) (SUN3X_P_ABORT); + romvec = (struct linux_romvec *)SUN3X_PROM_BASE; + + /* make a copy of the idprom structure */ + for(i = 0; i < sizeof(struct idprom); i++) + ((unsigned char *)(&idprom_buffer))[i] = ((unsigned char *)SUN3X_IDPROM)[i]; + idprom = &idprom_buffer; + + if((idprom->id_machtype & SM_ARCH_MASK) != SM_SUN3X) { + printk("Warning: machine reports strange type %02x\n"); + printk("Pretending it's a 3/80, but very afraid...\n"); + idprom->id_machtype = SM_SUN3X | SM_3_80; + } + + /* point trap #14 at abort. + * XXX this is futile since we restore the vbr first - oops + */ + vectors[VEC_TRAP14] = sun3x_prom_abort; + + /* If debug=prom was specified, start the debug console */ + + if (!strcmp(m68k_debug_device, "prom")) + register_console(&sun3x_debug); + + +} + +/* some prom functions to export */ +int prom_getintdefault(int node, char *property, int deflt) +{ + return deflt; +} + +int prom_getbool (int node, char *prop) +{ + return 1; +} + +void prom_printf(char *fmt, ...) +{ + +} + +void prom_halt (void) +{ + sun3x_halt(); +} diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3x/sbus.c linux/arch/m68k/sun3x/sbus.c --- v2.4.5/linux/arch/m68k/sun3x/sbus.c Thu Aug 26 12:42:31 1999 +++ linux/arch/m68k/sun3x/sbus.c Wed Dec 31 16:00:00 1969 @@ -1,44 +0,0 @@ -/* - * SBus helper functions - * - * Sun3x don't have a sbus, but many of the used devices are also - * used on Sparc machines with sbus. To avoid having a lot of - * duplicate code, we provide necessary glue stuff to make using - * of the sbus driver code possible. - * - * (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de) - */ - -#include -#include - -void __init sbus_init(void) -{ - -} - -void *sparc_alloc_io (u32 address, void *virtual, int len, char *name, - u32 bus_type, int rdonly) -{ - return (void *)address; -} - -int prom_getintdefault(int node, char *property, int deflt) -{ - return deflt; -} - -int prom_getbool (int node, char *prop) -{ - return 1; -} - -void prom_printf(char *fmt, ...) -{ - -} - -void prom_halt (void) -{ - -} diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3x/sun3x_ksyms.c linux/arch/m68k/sun3x/sun3x_ksyms.c --- v2.4.5/linux/arch/m68k/sun3x/sun3x_ksyms.c Wed Dec 31 16:00:00 1969 +++ linux/arch/m68k/sun3x/sun3x_ksyms.c Mon Jun 11 19:15:27 2001 @@ -0,0 +1,13 @@ +#include +#include +#include +#include + +/* + * Add things here when you find the need for it. + */ +EXPORT_SYMBOL(dvma_map_align); +EXPORT_SYMBOL(dvma_unmap); +EXPORT_SYMBOL(dvma_malloc_align); +EXPORT_SYMBOL(dvma_free); +EXPORT_SYMBOL(idprom); diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3x/time.c linux/arch/m68k/sun3x/time.c --- v2.4.5/linux/arch/m68k/sun3x/time.c Thu Aug 26 12:42:31 1999 +++ linux/arch/m68k/sun3x/time.c Mon Jun 11 19:15:27 2001 @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -15,6 +16,8 @@ #include #include #include +#include +#include #include "time.h" @@ -33,6 +36,7 @@ #define C_CALIB 0x1f #define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10) +#define BIN_TO_BCD(val) (((val/10) << 4) | (val % 10)) /* Read the Mostek */ void sun3x_gettod (int *yearp, int *monp, int *dayp, @@ -45,7 +49,7 @@ /* Read values */ *yearp = BCD_TO_BIN(*(eeprom + M_YEAR)); - *monp = BCD_TO_BIN(*(eeprom + M_MONTH)); + *monp = BCD_TO_BIN(*(eeprom + M_MONTH)) +1; *dayp = BCD_TO_BIN(*(eeprom + M_DATE)); *hourp = BCD_TO_BIN(*(eeprom + M_HOUR)); *minp = BCD_TO_BIN(*(eeprom + M_MIN)); @@ -55,6 +59,40 @@ *(eeprom + M_CONTROL) &= ~C_READ; } +int sun3x_hwclk(int set, struct hwclk_time *t) +{ + volatile struct mostek_dt *h = + (unsigned char *)(SUN3X_EEPROM+M_CONTROL); + unsigned long flags; + + save_and_cli(flags); + + if(set) { + h->csr |= C_WRITE; + h->sec = BIN_TO_BCD(t->sec); + h->min = BIN_TO_BCD(t->min); + h->hour = BIN_TO_BCD(t->hour); + h->wday = BIN_TO_BCD(t->wday); + h->mday = BIN_TO_BCD(t->day); + h->month = BIN_TO_BCD(t->mon); + h->year = BIN_TO_BCD(t->year); + h->csr &= ~C_WRITE; + } else { + h->csr |= C_READ; + t->sec = BCD_TO_BIN(h->sec); + t->min = BCD_TO_BIN(h->min); + t->hour = BCD_TO_BIN(h->hour); + t->wday = BCD_TO_BIN(h->wday); + t->day = BCD_TO_BIN(h->mday); + t->mon = BCD_TO_BIN(h->month); + t->year = BCD_TO_BIN(h->year); + h->csr &= ~C_READ; + } + + restore_flags(flags); + + return 0; +} /* Not much we can do here */ unsigned long sun3x_gettimeoffset (void) { @@ -74,9 +112,12 @@ void __init sun3x_sched_init(void (*vector)(int, void *, struct pt_regs *)) { - sys_request_irq(5, sun3x_timer_tick, IRQ_FLG_STD, "timer tick", vector); + + sun3_disable_interrupts(); + /* Pulse enable low to get the clock started */ - disable_irq(5); - enable_irq(5); + sun3_disable_irq(5); + sun3_enable_irq(5); + sun3_enable_interrupts(); } diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3x/time.h linux/arch/m68k/sun3x/time.h --- v2.4.5/linux/arch/m68k/sun3x/time.h Tue May 11 09:57:14 1999 +++ linux/arch/m68k/sun3x/time.h Mon Jun 11 19:15:27 2001 @@ -1,9 +1,21 @@ #ifndef SUN3X_TIME_H #define SUN3X_TIME_H -void sun3x_gettod (int *yearp, int *monp, int *dayp, +extern void sun3x_gettod (int *yearp, int *monp, int *dayp, int *hourp, int *minp, int *secp); +extern int sun3x_hwclk(int set, struct hwclk_time *t); unsigned long sun3x_gettimeoffset (void); void sun3x_sched_init(void (*vector)(int, void *, struct pt_regs *)); + +struct mostek_dt { + volatile unsigned char csr; + volatile unsigned char sec; + volatile unsigned char min; + volatile unsigned char hour; + volatile unsigned char wday; + volatile unsigned char mday; + volatile unsigned char month; + volatile unsigned char year; +}; #endif diff -u --recursive --new-file v2.4.5/linux/arch/m68k/vmlinux-sun3.lds linux/arch/m68k/vmlinux-sun3.lds --- v2.4.5/linux/arch/m68k/vmlinux-sun3.lds Sat Sep 4 13:06:41 1999 +++ linux/arch/m68k/vmlinux-sun3.lds Mon Jul 2 14:40:14 2001 @@ -20,6 +20,7 @@ .data : { /* Data */ *(.rodata) + *(.rodata.*) *(.data) CONSTRUCTORS . = ALIGN(16); /* Exception table */ diff -u --recursive --new-file v2.4.5/linux/arch/m68k/vmlinux.lds linux/arch/m68k/vmlinux.lds --- v2.4.5/linux/arch/m68k/vmlinux.lds Sat Sep 4 13:06:41 1999 +++ linux/arch/m68k/vmlinux.lds Mon Jul 2 14:40:14 2001 @@ -12,7 +12,7 @@ *(.text.lock) /* out-of-line lock text */ *(.gnu.warning) } = 0x4e75 - .rodata : { *(.rodata) } + .rodata : { *(.rodata) *(.rodata.*) } .kstrtab : { *(.kstrtab) } . = ALIGN(16); /* Exception table */ diff -u --recursive --new-file v2.4.5/linux/arch/mips/Makefile linux/arch/mips/Makefile --- v2.4.5/linux/arch/mips/Makefile Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/Makefile Mon Jul 2 13:56:40 2001 @@ -17,10 +17,8 @@ # ifdef CONFIG_CPU_LITTLE_ENDIAN tool-prefix = mipsel-linux- -output-format = elf32-littlemips else tool-prefix = mips-linux- -output-format = elf32-bigmips endif ifdef CONFIG_CROSSCOMPILE @@ -51,9 +49,6 @@ ifdef CONFIG_CPU_R3000 GCCFLAGS += -mcpu=r3000 -mips1 endif -ifdef CONFIG_CPU_R3912 -GCCFLAGS += -mcpu=r3000 -mips1 -endif ifdef CONFIG_CPU_R6000 GCCFLAGS += -mcpu=r6000 -mips2 -Wa,--trap endif @@ -67,22 +62,19 @@ GCCFLAGS += -mcpu=r4600 -mips2 -Wa,--trap endif ifdef CONFIG_CPU_R5000 -GCCFLAGS += -mcpu=r8000 -mips2 -Wa,--trap +GCCFLAGS += -mcpu=r5000 -mips2 -Wa,--trap endif ifdef CONFIG_CPU_R5432 -GCCFLAGS += -mcpu=r8000 -mips2 -Wa,--trap +GCCFLAGS += -mcpu=r5000 -mips2 -Wa,--trap endif ifdef CONFIG_CPU_NEVADA -GCCFLAGS += -mcpu=r8000 -mips2 -Wa,--trap -mmad +GCCFLAGS += -mcpu=r5000 -mips2 -Wa,--trap -mmad endif ifdef CONFIG_CPU_RM7000 -GCCFLAGS += -mcpu=r8000 -mips2 -Wa,--trap -endif -ifdef CONFIG_CPU_R8000 -GCCFLAGS += -mcpu=r8000 -mips2 -Wa,--trap +GCCFLAGS += -mcpu=r5000 -mips2 -Wa,--trap endif -ifdef CONFIG_CPU_R10000 -GCCFLAGS += -mcpu=r8000 -mips2 -Wa,--trap +ifdef CONFIG_CPU_SB1 +GCCFLAGS += -mcpu=sb1 -mips2 -Wa,--trap endif ifdef CONFIG_MIPS_FPU_EMULATOR @@ -90,14 +82,11 @@ SUBDIRS +=arch/mips/math-emu endif -# -# The pipe options is bad for my low-mem machine -# Uncomment this if you want this. -# GCCFLAGS += -pipe CFLAGS := -I $(TOPDIR)/include/asm/gcc $(CFLAGS) $(GCCFLAGS) AFLAGS += $(GCCFLAGS) +ASFLAGS += $(GCCFLAGS) # # Board-dependent options and extra files @@ -178,15 +167,6 @@ endif # -# Orion Board -# -ifdef CONFIG_ORION -LIBS += arch/mips/orion/orionkern.a -SUBDIRS += arch/mips/orion -LINKSCRIPT = arch/mips/orion/ld.script.orion -endif - -# # # NEC DDB Vrc-5476 # @@ -197,6 +177,17 @@ endif # +# +# NEC DDB Vrc-5477 +# +ifdef CONFIG_DDB5477 +SUBDIRS += arch/mips/ddb5xxx/common arch/mips/ddb5xxx/ddb5477 +LIBS += arch/mips/ddb5xxx/common/ddb5xxx.o \ + arch/mips/ddb5xxx/ddb5477/ddb5477.o +LOADADDR += 0x80080000 +endif + +# # Galileo EV64120 Board # ifdef CONFIG_MIPS_EV64120 @@ -218,7 +209,9 @@ # Momentum Ocelot board # ifdef CONFIG_MOMENCO_OCELOT -LIBS += arch/mips/gt64120/common/gt64120.o arch/mips/gt64120/momenco_ocelot/momenco_ocelot.o +# The Ocelot setup.o must be linked early - it does the ioremap() for the +# mips_io_port_base. +CORE_FILES += arch/mips/gt64120/common/gt64120.o arch/mips/gt64120/momenco_ocelot/momenco_ocelot.o SUBDIRS += arch/mips/gt64120/common arch/mips/gt64120/momenco_ocelot LOADADDR += 0x80100000 endif @@ -227,9 +220,8 @@ # Philips Nino # ifdef CONFIG_NINO -CORE_FILES += arch/mips/philips/nino/nino.o \ - arch/mips/philips/drivers/drivers.o -SUBDIRS += arch/mips/philips/nino arch/mips/philips/drivers +CORE_FILES += arch/mips/philips/nino/nino.o +SUBDIRS += arch/mips/philips/nino LOADADDR += 0x80000000 endif @@ -252,8 +244,7 @@ vmlinux: arch/$(ARCH)/ld.script arch/$(ARCH)/ld.script: arch/$(ARCH)/ld.script.in arch/$(ARCH)/Makefile - sed -e 's/@@OUTPUT_FORMAT@@/$(output-format)/' \ - -e 's/@@LOADADDR@@/$(LOADADDR)/' <$< >$@ + sed -e 's/@@LOADADDR@@/$(LOADADDR)/' <$< >$@ LINKFLAGS += -T arch/$(ARCH)/ld.script HEAD := arch/mips/kernel/head.o arch/mips/kernel/init_task.o @@ -269,13 +260,6 @@ balo: vmlinux $(BAGETBOOT) balo -endif - -ifdef CONFIG_ORION -ORIONBOOT = $(MAKE) -C arch/$(ARCH)/orion - -orionboot: - $(ORIONBOOT) orionboot endif ifdef CONFIG_MIPS_EV64120 diff -u --recursive --new-file v2.4.5/linux/arch/mips/arc/cmdline.c linux/arch/mips/arc/cmdline.c --- v2.4.5/linux/arch/mips/arc/cmdline.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/arc/cmdline.c Mon Jul 2 13:56:40 2001 @@ -25,10 +25,49 @@ "SystemPartition=", "OSLoader=", "OSLoadPartition=", - "OSLoadFilename=" + "OSLoadFilename=", + "OSLoadOptions=" }; #define NENTS(foo) ((sizeof((foo)) / (sizeof((foo[0]))))) +static char *used_arc[][2] = { + { "OSLoadPartition=", "root=" }, + { "OSLoadOptions=", "" } +}; + +static char * __init move_firmware_args(char* cp) +{ + char *s; + int actr, i; + + actr = 1; /* Always ignore argv[0] */ + + while (actr < prom_argc) { + for(i = 0; i < NENTS(used_arc); i++) { + int len = strlen(used_arc[i][0]); + + if(!strncmp(prom_argv[actr], used_arc[i][0], len)) { + /* Ok, we want it. First append the replacement... */ + strcat(cp, used_arc[i][1]); + cp += strlen(used_arc[i][1]); + /* ... and now the argument */ + s = strstr(prom_argv[actr], "="); + if(s) { + s++; + strcpy(cp, s); + cp += strlen(s); + } + *cp++ = ' '; + break; + } + } + actr++; + } + + return cp; +} + + void __init prom_init_cmdline(void) { char *cp; @@ -37,8 +76,14 @@ actr = 1; /* Always ignore argv[0] */ cp = &(arcs_cmdline[0]); - while(actr < prom_argc) { - for(i = 0; i < NENTS(ignored); i++) { + /* + * Move ARC variables to the beginning to make sure they can be + * overridden by later arguments. + */ + cp = move_firmware_args(cp); + + while (actr < prom_argc) { + for (i = 0; i < NENTS(ignored); i++) { int len = strlen(ignored[i]); if(!strncmp(prom_argv[actr], ignored[i], len)) diff -u --recursive --new-file v2.4.5/linux/arch/mips/arc/console.c linux/arch/mips/arc/console.c --- v2.4.5/linux/arch/mips/arc/console.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/arc/console.c Mon Jul 2 13:56:40 2001 @@ -15,10 +15,6 @@ #include #include -#ifdef CONFIG_ARC_CONSOLE -#define __init -#endif - /* * IP22 boardcache is not compatible with board caches. Thus we disable it * during romvec action. Since r4xx0.c is always compiled and linked with your @@ -29,7 +25,7 @@ * in some way. You should be careful with them. */ -void __init prom_putchar(char c) +void prom_putchar(char c) { long cnt; char it = c; @@ -53,7 +49,7 @@ static char ppbuf[1024]; -void __init prom_printf(char *fmt, ...) +void prom_printf(char *fmt, ...) { va_list args; char ch, *bptr; @@ -71,29 +67,4 @@ prom_putchar(ch); } va_end(args); -} - -static void -arc_console_write(struct console *con, const char *s, unsigned n) -{ - prom_printf("%s", s); -} - -static kdev_t -arc_console_dev(struct console *c) -{ - return MKDEV(TTY_MAJOR, 64 + c->index); -} - -static struct console arc_prom_console = { - name: "prom", - write: arc_console_write, - device: arc_console_dev, - flags: CON_PRINTBUFFER, - index: -1, -}; - -__init void arc_setup_console(void) -{ - register_console(&arc_prom_console); } diff -u --recursive --new-file v2.4.5/linux/arch/mips/arc/identify.c linux/arch/mips/arc/identify.c --- v2.4.5/linux/arch/mips/arc/identify.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/arc/identify.c Mon Jul 2 13:56:40 2001 @@ -36,7 +36,7 @@ { int i; - for (i = 0; i < sizeof(mach_table); i++) { + for (i = 0; i < (sizeof(mach_table) / sizeof (mach_table[0])); i++) { if (!strcmp(s, mach_table[i].name)) return &mach_table[i]; } diff -u --recursive --new-file v2.4.5/linux/arch/mips/arc/memory.c linux/arch/mips/arc/memory.c --- v2.4.5/linux/arch/mips/arc/memory.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/arc/memory.c Mon Jul 2 13:56:40 2001 @@ -32,7 +32,7 @@ "Free/Contig RAM", "Generic Free RAM", "Bad Memory", - "Standlong Program Pages", + "Standalone Program Pages", "ARCS Temp Storage Area", "ARCS Permanent Storage Area" }; diff -u --recursive --new-file v2.4.5/linux/arch/mips/arc/misc.c linux/arch/mips/arc/misc.c --- v2.4.5/linux/arch/mips/arc/misc.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/arc/misc.c Mon Jul 2 13:56:40 2001 @@ -56,7 +56,7 @@ romvec->reboot(); } -void prom_imode(void) +void ArcEnterInteractiveMode(void) { bc_disable(); cli(); diff -u --recursive --new-file v2.4.5/linux/arch/mips/baget/ld.script.balo linux/arch/mips/baget/ld.script.balo --- v2.4.5/linux/arch/mips/baget/ld.script.balo Fri Jun 25 17:40:12 1999 +++ linux/arch/mips/baget/ld.script.balo Mon Jul 2 14:40:14 2001 @@ -31,6 +31,7 @@ _ftext = . ; *(.text) *(.rodata) + *(.rodata.*) *(.rodata1) /* .gnu.warning sections are handled specially by elf32.em. */ *(.gnu.warning) diff -u --recursive --new-file v2.4.5/linux/arch/mips/boot/mkboot.c linux/arch/mips/boot/mkboot.c --- v2.4.5/linux/arch/mips/boot/mkboot.c Thu Jun 26 12:33:36 1997 +++ linux/arch/mips/boot/mkboot.c Mon Jul 2 13:56:40 2001 @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1996 by Ralf Baechle + * Copyright (C) 1996, 2001 by Ralf Baechle * * This file is written in plain Kernighan & Ritchie C as it has to run * on all crosscompile hosts no matter how braindead. This code might @@ -80,7 +80,6 @@ * Acceptable machine type in e_machine. */ #define EM_MIPS 8 /* MIPS R3000 big-endian */ -#define EM_MIPS_RS4_BE 10 /* MIPS R4000 big-endian */ /* * The type of ELF file we accept. @@ -462,7 +461,7 @@ fprintf(stderr, "Input file isn't a executable.\n"); exit(1); } - if(eh.e_machine != EM_MIPS && eh.e_machine != EM_MIPS_RS4_BE) { + if(eh.e_machine != EM_MIPS) { fprintf(stderr, "Input file isn't a MIPS executable.\n"); exit(1); } diff -u --recursive --new-file v2.4.5/linux/arch/mips/config.in linux/arch/mips/config.in --- v2.4.5/linux/arch/mips/config.in Tue Apr 17 17:19:25 2001 +++ linux/arch/mips/config.in Mon Jul 2 13:56:40 2001 @@ -2,6 +2,9 @@ # For a description of the syntax of this configuration file, # see Documentation/kbuild/config-language.txt. # +define_bool CONFIG_MIPS y +define_bool CONFIG_SMP n + mainmenu_name "Linux Kernel Configuration" mainmenu_option next_comment @@ -15,18 +18,55 @@ bool 'Support for Acer PICA 1 chipset' CONFIG_ACER_PICA_61 bool 'Support for Algorithmics P4032 (EXPERIMENTAL)' CONFIG_ALGOR_P4032 bool 'Support for BAGET MIPS series (EXPERIMENTAL)' CONFIG_BAGET_MIPS - bool 'Support for Cobalt Server' CONFIG_COBALT_MICRO_SERVER - if [ "$CONFIG_COBALT_MICRO_SERVER" = "y" ]; then - bool ' Support for 2800' CONFIG_COBALT_28 - fi bool 'Support for DECstations (EXPERIMENTAL)' CONFIG_DECSTATION bool 'Support for NEC DDB Vrc-5074 (EXPERIMENTAL)' CONFIG_DDB5074 - bool 'Support for Galileo Evaluation board or CoSine Orion' CONFIG_ORION + bool 'Support for Galileo EV96100 Evaluation board' CONFIG_MIPS_EV96100 + bool 'Support for Galileo EV64120 Evaluation board' CONFIG_MIPS_EV64120 + if [ "$CONFIG_MIPS_EV64120" = "y" ]; then + bool 'Enable Second PCI (PCI1)' CONFIG_EVB_PCI1 + choice 'Galileo Chip Clock' \ + "75 CONFIG_SYSCLK_75\ + 83.3 CONFIG_SYSCLK_83\ + 100 CONFIG_SYSCLK_100" CONFIG_SYSCLK_83 + fi + bool 'Support for MIPS Atlas board' CONFIG_MIPS_ATLAS + bool 'Support for MIPS Malta board' CONFIG_MIPS_MALTA + bool 'Support for Philips Nino (EXPERIMENTAL)' CONFIG_NINO + if [ "$CONFIG_NINO" = "y" ]; then + choice 'Nino Model Number' \ + "Model-300/301/302/319 CONFIG_NINO_4MB \ + Model-200/210/312/320/325/350/390 CONFIG_NINO_8MB \ + Model-500/510 CONFIG_NINO_16MB" CONFIG_NINO_8MB + fi fi bool 'Support for Mips Magnum 4000' CONFIG_MIPS_MAGNUM_4000 +bool 'Support for Momentum Ocelot board' CONFIG_MOMENCO_OCELOT +bool 'Support for NEC DDB Vrc-5476' CONFIG_DDB5476 +bool 'Support for NEC DDB Vrc-5477' CONFIG_DDB5477 bool 'Support for Olivetti M700-10' CONFIG_OLIVETTI_M700 bool 'Support for SGI IP22' CONFIG_SGI_IP22 bool 'Support for SNI RM200 PCI' CONFIG_SNI_RM200_PCI +bool 'Support for ITE 8172G board' CONFIG_MIPS_ITE8172 + if [ "$CONFIG_MIPS_ITE8172" = "y" ]; then + bool ' Support for older IT8172 (Rev C)' CONFIG_IT8172_REVC + bool ' Enable Qtronix 990P Keyboard Support' CONFIG_QTRONIX_KEYBOARD + if [ "$CONFIG_QTRONIX_KEYBOARD" = "y" ]; then + define_bool CONFIG_IT8172_CIR y + else + bool ' Enable PS2 Keyboard Support ' CONFIG_PC_KEYB + fi + bool ' Enable Smart Card Reader 0 Support ' CONFIG_IT8172_SCR0 + bool ' Enable Smart Card Reader 1 Support ' CONFIG_IT8172_SCR1 + fi + bool 'Support for Globespan IVR board' CONFIG_MIPS_IVR + if [ "$CONFIG_MIPS_IVR" = "y" ]; then + bool ' Enable Qtronix 990P Keyboard Support' CONFIG_QTRONIX_KEYBOARD + if [ "$CONFIG_QTRONIX_KEYBOARD" = "y" ]; then + define_bool CONFIG_IT8172_CIR y + fi + bool ' Enable Smart Card Reader 0 Support ' CONFIG_IT8172_SCR0 + fi +bool 'Support for Alchemy Semi PB1000 board' CONFIG_MIPS_PB1000 define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n @@ -35,54 +75,127 @@ # Select some configuration options automatically for certain systems. # unset CONFIG_ARC32 +unset CONFIG_BOARD_SCACHE +unset CONFIG_HAVE_STD_PC_SERIAL_PORT +unset CONFIG_I8259 unset CONFIG_ISA -unset CONFIG_EISA unset CONFIG_PCI unset CONFIG_MIPS_JAZZ +unset CONFIG_SWAP_IO_SPACE unset CONFIG_VIDEO_G364 unset CONFIG_PC_KEYB define_bool CONFIG_MCA n define_bool CONFIG_SBUS n +if [ "$CONFIG_MIPS_EV96100" = "y" ]; then + define_bool CONFIG_PCI y + define_bool CONFIG_MIPS_GT96100 y + define_bool CONFIG_SWAP_IO_SPACE y +fi +if [ "$CONFIG_MIPS_EV64120" = "y" ]; then + define_bool CONFIG_PCI y + define_bool CONFIG_ISA n + define_bool CONFIG_MIPS_GT64120 y + define_bool CONFIG_OLD_TIME_C y +fi + if [ "$CONFIG_ALGOR_P4032" = "y" ]; then define_bool CONFIG_PCI y + define_bool CONFIG_OLD_TIME_C y fi if [ "$CONFIG_MIPS_MAGNUM_4000" = "y" -o \ "$CONFIG_OLIVETTI_M700" = "y" ]; then define_bool CONFIG_ARC32 y + define_bool CONFIG_I8259 y define_bool CONFIG_ISA y define_bool CONFIG_FB y define_bool CONFIG_FB_G364 y define_bool CONFIG_MIPS_JAZZ y define_bool CONFIG_PC_KEYB y + define_bool CONFIG_OLD_TIME_C y fi if [ "$CONFIG_ACER_PICA_61" = "y" ]; then define_bool CONFIG_ARC32 y + define_bool CONFIG_I8259 y define_bool CONFIG_ISA y define_bool CONFIG_MIPS_JAZZ y define_bool CONFIG_PC_KEYB y + define_bool CONFIG_ROTTEN_IRQ y + define_bool CONFIG_OLD_TIME_C y fi -if [ "$CONFIG_COBALT_MICRO_SERVER" = "y" ]; then - define_bool CONFIG_COBALT_27 y - define_bool CONFIG_COBALT_LCD y - define_bool CONFIG_COBALT_SERIAL y +if [ "$CONFIG_MIPS_ATLAS" = "y" ]; then define_bool CONFIG_PCI y + define_bool CONFIG_SWAP_IO_SPACE y +fi +if [ "$CONFIG_MIPS_MALTA" = "y" ]; then + define_bool CONFIG_I8259 y + define_bool CONFIG_PCI y + define_bool CONFIG_HAVE_STD_PC_SERIAL_PORT y + define_bool CONFIG_SWAP_IO_SPACE y +fi +if [ "$CONFIG_MOMENCO_OCELOT" = "y" ]; then + define_bool CONFIG_PCI y + define_bool CONFIG_SYSCLK_100 y + define_bool CONFIG_SWAP_IO_SPACE y + define_bool CONFIG_NEW_IRQ y + define_bool CONFIG_OLD_TIME_C y fi if [ "$CONFIG_SGI_IP22" = "y" ]; then define_bool CONFIG_ARC32 y + define_bool CONFIG_BOARD_SCACHE y define_bool CONFIG_PC_KEYB y define_bool CONFIG_SGI y + define_bool CONFIG_NEW_IRQ y + define_bool CONFIG_OLD_TIME_C y fi if [ "$CONFIG_SNI_RM200_PCI" = "y" ]; then define_bool CONFIG_ARC32 y + define_bool CONFIG_I8259 y + define_bool CONFIG_ISA y + define_bool CONFIG_PC_KEYB y define_bool CONFIG_PCI y + define_bool CONFIG_ROTTEN_IRQ y + define_bool CONFIG_OLD_TIME_C y +fi +if [ "$CONFIG_DDB5074" = "y"]; then + define_bool CONFIG_I8259 y define_bool CONFIG_ISA y + define_bool CONFIG_PCI y define_bool CONFIG_PC_KEYB y + define_bool CONFIG_ROTTEN_IRQ y + define_bool CONFIG_HAVE_STD_PC_SERIAL_PORT y + define_bool CONFIG_OLD_TIME_C y fi -if [ "$CONFIG_DDB5074" = "y" ]; then +if [ "$CONFIG_DDB5476" = "y" ]; then + define_bool CONFIG_I8259 y define_bool CONFIG_ISA y define_bool CONFIG_PCI y + define_bool CONFIG_PC_KEYB y + define_bool CONFIG_ROTTEN_IRQ y + define_bool CONFIG_HAVE_STD_PC_SERIAL_PORT y + define_bool CONFIG_NEW_TIME_C y +fi +if [ "$CONFIG_DDB5477" = "y" ]; then + define_bool CONFIG_CPU_LITTLE_ENDIAN y + define_bool CONFIG_PCI y + define_bool CONFIG_NEW_TIME_C y + define_bool CONFIG_NEW_IRQ y +fi +if [ "$CONFIG_MIPS_ITE8172" = "y" ]; then + define_bool CONFIG_PCI y + define_bool CONFIG_IT8712 y + define_bool CONFIG_PC_KEYB y +fi +if [ "$CONFIG_MIPS_IVR" = "y" ]; then + define_bool CONFIG_PCI y +fi +if [ "$CONFIG_MIPS_PB1000" = "y" ]; then + define_bool CONFIG_MIPS_AU1000 y + define_bool CONFIG_NEW_IRQ y +fi +if [ "$CONFIG_NINO" = "y" ]; then + define_bool CONFIG_PC_KEYB y fi if [ "$CONFIG_ISA" != "y" ]; then @@ -95,6 +208,10 @@ if [ "$CONFIG_PCI" != "y" ]; then define_bool CONFIG_PCI n fi + +if [ "$CONFIG_I8259" != "y" ]; then + define_bool CONFIG_I8259 n +fi endmenu mainmenu_option next_comment @@ -115,9 +232,12 @@ R4300 CONFIG_CPU_R4300 \ R4x00 CONFIG_CPU_R4X00 \ R5000 CONFIG_CPU_R5000 \ - R56x0 CONFIG_CPU_NEVADA \ - R8000 CONFIG_CPU_R8000 \ - R10000 CONFIG_CPU_R10000" R4x00 + R5432 CONFIG_CPU_R5432 \ + RM7000 CONFIG_CPU_RM7000 \ + R52xx CONFIG_CPU_NEVADA \ + R10000 CONFIG_CPU_R10000 \ + SB1 CONFIG_CPU_SB1 \ + MIPS32 CONFIG_CPU_MIPS32" R4x00 bool 'Override CPU Options' CONFIG_CPU_ADVANCED @@ -134,19 +254,23 @@ define_bool CONFIG_CPU_HAS_WB n fi else - define_bool CONFIG_CPU_HAS_LLSC y - define_bool CONFIG_CPU_HAS_WB n + define_bool CONFIG_CPU_HAS_LLSC y + define_bool CONFIG_CPU_HAS_WB n fi fi endmenu mainmenu_option next_comment comment 'General setup' -if [ "$CONFIG_DECSTATION" = "y" -o "$CONFIG_DDB5074" = "y" ]; then +if [ "$CONFIG_DECSTATION" = "y" -o \ + "$CONFIG_DDB5074" = "y" -o \ + "$CONFIG_DDB5476" = "y" -o \ + "$CONFIG_NINO" = "y" ]; then define_bool CONFIG_CPU_LITTLE_ENDIAN y else bool 'Generate little endian code' CONFIG_CPU_LITTLE_ENDIAN fi +bool 'Kernel floating-point emulation' CONFIG_MIPS_FPU_EMULATOR if [ "$CONFIG_PROC_FS" = "y" ]; then define_bool CONFIG_KCORE_ELF y @@ -158,22 +282,30 @@ bool 'Include forward keyboard' CONFIG_FORWARD_KEYBOARD fi +if [ "$CONFIG_ARC32" = "y" ]; then + bool 'ARC console support' CONFIG_ARC_CONSOLE +fi + define_bool CONFIG_BINFMT_AOUT n define_bool CONFIG_BINFMT_ELF y tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC bool 'Networking support' CONFIG_NET -if [ "$CONFIG_PCI" = "y" ]; then - source drivers/pci/Config.in +source drivers/pci/Config.in + +bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG + +if [ "$CONFIG_HOTPLUG" = "y" ] ; then + source drivers/pcmcia/Config.in +else + define_bool CONFIG_PCMCIA n fi bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT bool 'Sysctl support' CONFIG_SYSCTL -source drivers/parport/Config.in - if [ "$CONFIG_DECSTATION" = "y" ]; then bool 'TURBOchannel support' CONFIG_TC # if [ "$CONFIG_TC" = "y" ]; then @@ -186,14 +318,10 @@ source drivers/pnp/Config.in fi -if [ "$CONFIG_HOTPLUG" = "y" ] ; then - source drivers/pcmcia/Config.in -else - define_bool CONFIG_PCMCIA n -fi - source drivers/mtd/Config.in +source drivers/parport/Config.in + source drivers/block/Config.in source drivers/md/Config.in @@ -202,10 +330,7 @@ source net/Config.in fi -if [ "$CONFIG_DECSTATION" != "y" -a \ - "$CONFIG_SGI_IP22" != "y" ]; then - source drivers/telephony/Config.in -fi +source drivers/telephony/Config.in if [ "$CONFIG_SGI_IP22" != "y" -a \ "$CONFIG_DECSTATION" != "y" ]; then @@ -236,7 +361,7 @@ if [ "$CONFIG_DECSTATION" != "y" -a \ "$CONFIG_SGI_IP22" != "y" ]; then - source drivers/i2o/Config.in + source drivers/message/i2o/Config.in fi if [ "$CONFIG_NET" = "y" ]; then @@ -245,69 +370,40 @@ bool 'Network device support' CONFIG_NETDEVICES if [ "$CONFIG_NETDEVICES" = "y" ]; then - - if [ "$CONFIG_SGI_IP22" != "y" -a \ - "$CONFIG_DECSTATION" != "y" -a \ - "$CONFIG_BAGET_MIPS" != "y" ]; then - - source drivers/net/Config.in - - if [ "$CONFIG_ATM" = "y" ]; then - source drivers/atm/Config.in - fi - else - tristate 'Dummy net driver support' CONFIG_DUMMY - tristate 'SLIP (serial line) support' CONFIG_SLIP - if [ "$CONFIG_SLIP" != "n" ]; then - bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED - bool ' Keepalive and linefill' CONFIG_SLIP_SMART - fi - tristate 'PPP (point-to-point) support' CONFIG_PPP - if [ ! "$CONFIG_PPP" = "n" ]; then - comment 'CCP compressors for PPP are only built as modules.' - fi - if [ "$CONFIG_SGI_IP22" = "y" ]; then - bool 'SGI Seeq ethernet controller support' CONFIG_SGISEEQ - fi - if [ "$CONFIG_DECSTATION" = "y" ]; then - bool 'DEC LANCE ethernet controller support' CONFIG_DECLANCE - fi - if [ "$CONFIG_BAGET_MIPS" = "y" ]; then - tristate 'Baget AMD LANCE support' CONFIG_BAGETLANCE - fi + source drivers/net/Config.in + if [ "$CONFIG_ATM" = "y" ]; then + source drivers/atm/Config.in fi fi endmenu fi -if [ "$CONFIG_ISA" = "y" -o "$CONFIG_PCI" = "y" ]; then - mainmenu_option next_comment - comment 'ISDN subsystem' - - if [ "$CONFIG_NET" != "n" ]; then - tristate 'ISDN support' CONFIG_ISDN - if [ "$CONFIG_ISDN" != "n" ]; then - source drivers/isdn/Config.in - fi - fi - endmenu +source net/ax25/Config.in - mainmenu_option next_comment - comment 'Old CD-ROM drivers (not SCSI, not IDE)' +source net/irda/Config.in - bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI - if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then - source drivers/cdrom/Config.in +mainmenu_option next_comment +comment 'ISDN subsystem' +if [ "$CONFIG_NET" != "n" ]; then + tristate 'ISDN support' CONFIG_ISDN + if [ "$CONFIG_ISDN" != "n" ]; then + source drivers/isdn/Config.in fi - endmenu fi +endmenu -if [ "$CONFIG_DECSTATION" != "y" -a \ - "$CONFIG_SGI_IP22" != "y" ]; then - source drivers/char/Config.in +mainmenu_option next_comment +comment 'Old CD-ROM drivers (not SCSI, not IDE)' - source drivers/media/Config.in +bool 'Support non-SCSI/IDE/ATAPI CDROM drives' CONFIG_CD_NO_IDESCSI +if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then + source drivers/cdrom/Config.in fi +endmenu + +source drivers/char/Config.in + +source drivers/media/Config.in if [ "$CONFIG_DECSTATION" = "y" ]; then mainmenu_option next_comment @@ -332,9 +428,7 @@ # if [ "$CONFIG_ACCESSBUS" = "y" ]; then # bool 'MAXINE Access.Bus mouse (VSXXX-BB/GB) support' CONFIG_DTOP_MOUSE # fi - bool 'Enhanced Real Time Clock Support' CONFIG_MIPS_RTC - - define_tristate CONFIG_RTC $CONFIG_MIPS_RTC + bool 'Enhanced Real Time Clock Support' CONFIG_RTC endmenu fi @@ -351,7 +445,10 @@ else define_bool CONFIG_FONT_8x16 y fi - bool 'SGI PROM Console Support' CONFIG_SGI_PROM_CONSOLE + fi + bool 'PS/2 mouse support' CONFIG_PSMOUSE + if [ "$CONFIG_PSMOUSE" != "n" ]; then + define_bool CONFIG_MOUSE y fi bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then @@ -364,13 +461,12 @@ if [ "$CONFIG_VT" = "y" ]; then mainmenu_option next_comment - comment 'Console drivers' - if [ "$CONFIG_DECSTATION" != "y" ]; then - bool 'VGA text console' CONFIG_VGA_CONSOLE - fi - bool 'Support for frame buffer devices' CONFIG_FB + bool 'VGA text console' CONFIG_VGA_CONSOLE + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + tristate 'MDA text console (dual-headed) (EXPERIMENTAL)' CONFIG_MDA_CONSOLE source drivers/video/Config.in + fi endmenu fi @@ -399,8 +495,15 @@ if [ "$CONFIG_MODULES" = "y" ]; then bool ' Build fp execption handler module' CONFIG_MIPS_FPE_MODULE fi -if [ "$CONFIG_SERIAL" = "y" ]; then +if [ "$CONFIG_SERIAL" = "y" -o "$CONFIG_AU1000_UART" = "y" ]; then bool 'Remote GDB kernel debugging' CONFIG_REMOTE_DEBUG + dep_bool 'Console output to GDB' CONFIG_GDB_CONSOLE $CONFIG_REMOTE_DEBUG +fi +if [ "$CONFIG_SERIAL" = "y" ]; then + bool 'Low-level debugging' CONFIG_LL_DEBUG fi bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ +if [ "$CONFIG_SMP" != "y" ]; then + bool 'Run uncached' CONFIG_MIPS_UNCACHED +fi endmenu diff -u --recursive --new-file v2.4.5/linux/arch/mips/dec/boot/ld.ecoff linux/arch/mips/dec/boot/ld.ecoff --- v2.4.5/linux/arch/mips/dec/boot/ld.ecoff Fri Jun 25 17:40:12 1999 +++ linux/arch/mips/dec/boot/ld.ecoff Mon Jul 2 14:40:14 2001 @@ -13,7 +13,7 @@ } .rdata : { - *(.rodata .rdata) + *(.rodata .rodata.* .rdata) } .data : { diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/Makefile linux/arch/mips/kernel/Makefile --- v2.4.5/linux/arch/mips/kernel/Makefile Tue Jul 11 11:14:42 2000 +++ linux/arch/mips/kernel/Makefile Mon Jul 2 13:56:40 2001 @@ -6,93 +6,58 @@ # unless it's something special (ie not a .c file). # +.S.s: + $(CPP) $(AFLAGS) $< -o $@ .S.o: - $(CC) $(CFLAGS) -c $< -o $*.o + $(CC) $(AFLAGS) -c $< -o $@ + +EXTRA_AFLAGS = -mips3 -mcpu=r4000 all: kernel.o head.o init_task.o -EXTRA_ASFLAGS = -mips3 -mcpu=r4000 + O_TARGET := kernel.o -O_OBJS := branch.o process.o signal.o entry.o traps.o ptrace.o vm86.o \ - ioport.o reset.o semaphore.o setup.o syscall.o sysmips.o ipc.o \ - scall_o32.o softfp.o unaligned.o -OX_OBJS := mips_ksyms.o + +obj-y += branch.o process.o signal.o entry.o \ + traps.o ptrace.o vm86.o ioport.o reset.o \ + semaphore.o setup.o syscall.o sysmips.o \ + ipc.o scall_o32.o unaligned.o +obj-$(CONFIG_MODULES) += mips_ksyms.o ifdef CONFIG_CPU_R3000 -O_OBJS += r2300_misc.o r2300_fpu.o r2300_switch.o +obj-y += r2300_misc.o r2300_fpu.o r2300_switch.o else -O_OBJS += r4k_misc.o r4k_switch.o +obj-y += r4k_misc.o r4k_switch.o ifdef CONFIG_CPU_R6000 -O_OBJS += r6000_fpu.o +obj-y += r6000_fpu.o else -O_OBJS += r4k_fpu.o -endif -endif - -ifdef CONFIG_MIPS_FPE_MODULE -M_OBJS += fpe.o +obj-y += r4k_fpu.o endif - -# -# SGIs have very different interrupt/timer hardware. -# -ifndef CONFIG_DECSTATION - ifndef CONFIG_BAGET_MIPS - O_OBJS += time.o - ifndef CONFIG_SGI_IP22 - ifndef CONFIG_ORION - OX_OBJS += irq.o - endif - endif - endif endif -# -# Do we want to be able to execute IRIX elf binaries? -# -ifdef CONFIG_BINFMT_IRIX -O_OBJS += irixelf.o irixioctl.o irixsig.o sysirix.o irixinv.o +obj-$(CONFIG_SMP) += smp.o +obj-$(CONFIG_MIPS_FPE_MODULE) += fpe.o +ifndef CONFIG_MIPS_FPU_EMULATOR + obj-y += softfp.o endif -# -# Kernel debugging -# -ifdef CONFIG_REMOTE_DEBUG -O_OBJS += gdb-low.o gdb-stub.o -endif +# Old style irq support, going to die in 2.5. +export-objs += old-irq.o +obj-$(CONFIG_NEW_IRQ) += irq.o +obj-$(CONFIG_ROTTEN_IRQ) += old-irq.o -# -# Depending from some other kernel option -# -ifdef CONFIG_PROC_FS -O_OBJS += proc.o -endif +# transition from old time.c to new time.c +# some boards uses old-time.c, some use time.c, and some use their own ones +export-objs += old-time.o time.o +obj-$(CONFIG_OLD_TIME_C) += old-time.o +obj-$(CONFIG_NEW_TIME_C) += time.o -# -# Since we add the same object files to O_OBJS for different configurations. -# O_OBJS might contain duplicate files. We correct this by filtering out -# duplicate files. Just to avoid users having to know about all the -# compatibility stuff between various boards and boards. -# -O_OBJS := $(sort $(O_OBJS)) +obj-$(CONFIG_BINFMT_IRIX) += irixelf.o irixioctl.o irixsig.o sysirix.o \ + irixinv.o +obj-$(CONFIG_REMOTE_DEBUG) += gdb-low.o gdb-stub.o +obj-$(CONFIG_PCI) += pci-dma.o +obj-$(CONFIG_PROC_FS) += proc.o entry.o: entry.S - head.o: head.S - -#r4k_switch.o: r4k_switch.S -# -#r4k_misc.o: r4k_misc.S -# -#r4k_fpu.o: r4k_fpu.S -# -#r2300_switch.o: r2300_switch.S -# -#r2300_misc.o: r2300_misc.S -# -#r2300_fpu.o: r2300_fpu.S -# -#r6000_fpu.o: r6000_fpu.S - -clean: include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/entry.S linux/arch/mips/kernel/entry.S --- v2.4.5/linux/arch/mips/kernel/entry.S Fri Aug 4 16:15:37 2000 +++ linux/arch/mips/kernel/entry.S Mon Jul 2 13:56:40 2001 @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -43,11 +44,16 @@ EXPORT(ret_from_sys_call) EXPORT(ret_from_irq) .type ret_from_irq,@function - lw t0, irq_stat # softirq_active - lw t1, irq_stat+4 # softirq_mask. unused delay slot + la t1, irq_stat # softirq_active +#ifdef CONFIG_SMP + lw t0, TASK_PROCESSOR($28) + sll t0, t0, 5 + addu t1, t0 +#endif + lw t0, 0(t1) # softirq_active + lw t1, 4(t1) # softirq_mask. unused delay slot and t0, t1 bnez t0, handle_softirq - 9: lw t0,PT_STATUS(sp) # returning to kernel mode? lw t2, TASK_NEED_RESCHED($28) diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/gdb-stub.c linux/arch/mips/kernel/gdb-stub.c --- v2.4.5/linux/arch/mips/kernel/gdb-stub.c Sun Oct 1 20:35:15 2000 +++ linux/arch/mips/kernel/gdb-stub.c Mon Jul 2 13:56:40 2001 @@ -64,6 +64,61 @@ * Host: Reply: * $m0,10#2a +$00010203040506070809101112131415#42 * + * + * ============== + * MORE EXAMPLES: + * ============== + * + * For reference -- the following are the steps that one + * company took (RidgeRun Inc) to get remote gdb debugging + * going. In this scenario the host machine was a PC and the + * target platform was a Galileo EVB64120A MIPS evaluation + * board. + * + * Step 1: + * First download gdb-5.0.tar.gz from the internet. + * and then build/install the package. + * + * Example: + * $ tar zxf gdb-5.0.tar.gz + * $ cd gdb-5.0 + * $ ./configure --target=mips-linux-elf + * $ make + * $ install + * $ which mips-linux-elf-gdb + * /usr/local/bin/mips-linux-elf-gdb + * + * Step 2: + * Configure linux for remote debugging and build it. + * + * Example: + * $ cd ~/linux + * $ make menuconfig + * $ make dep; make vmlinux + * + * Step 3: + * Download the kernel to the remote target and start + * the kernel running. It will promptly halt and wait + * for the host gdb session to connect. It does this + * since the "Kernel Hacking" option has defined + * CONFIG_REMOTE_DEBUG which in turn enables your calls + * to: + * set_debug_traps(); + * breakpoint(); + * + * Step 4: + * Start the gdb session on the host. + * + * Example: + * $ mips-linux-elf-gdb vmlinux + * (gdb) set remotebaud 115200 + * (gdb) target remote /dev/ttyS1 + * ...at this point you are connected to + * the remote target and can use gdb + * in the normal fasion. Setting + * breakpoints, single stepping, + * printing variables, etc. + * */ #include @@ -71,6 +126,8 @@ #include #include #include +#include +#include #include #include @@ -315,13 +372,10 @@ * signals, which are primarily what GDB understands. It also indicates * which hardware traps we need to commandeer when initializing the stub. */ -static struct hard_trap_info -{ +static struct hard_trap_info { unsigned char tt; /* Trap type code for MIPS R3xxx and R4xxx */ unsigned char signo; /* Signal that we map this trap into */ } hard_trap_info[] = { - { 4, SIGBUS }, /* address error (load) */ - { 5, SIGBUS }, /* address error (store) */ { 6, SIGBUS }, /* instruction bus error */ { 7, SIGBUS }, /* data bus error */ { 9, SIGTRAP }, /* break */ @@ -350,6 +404,7 @@ for (ht = hard_trap_info; ht->tt && ht->signo; ht++) set_except_vector(ht->tt, trap_low); + putDebugChar('+'); /* 'hello world' */ /* * In case GDB is started before us, ack any packets * (presumably "$?#xx") sitting there. @@ -373,7 +428,7 @@ */ extern void fltr_set_mem_err(void) { - /* FIXME: Needs to be written... */ + /* FIXME: Needs to be written... */ } /* @@ -401,8 +456,7 @@ *intValue = 0; - while (**ptr) - { + while (**ptr) { hexValue = hex(**ptr); if (hexValue < 0) break; @@ -904,3 +958,47 @@ lw $9,0($8) "); } + +#ifdef CONFIG_GDB_CONSOLE + +void gdb_puts(const char *str) +{ + int l = strlen(str); + char outbuf[18]; + + outbuf[0]='O'; + + while(l) { + int i = (l>8)?8:l; + mem2hex((char *)str, &outbuf[1], i, 0); + outbuf[(i*2)+1]=0; + putpacket(outbuf); + str += i; + l -= i; + } +} + +static kdev_t gdb_console_dev(struct console *con) +{ + return MKDEV(1, 3); /* /dev/null */ +} + +static void gdb_console_write(struct console *con, const char *s, unsigned n) +{ + gdb_puts(s); +} + +static struct console gdb_console = { + name: "gdb", + write: gdb_console_write, + device: gdb_console_dev, + flags: CON_PRINTBUFFER, + index: -1 +}; + +__init void register_gdb_console(void) +{ + register_console(&gdb_console); +} + +#endif diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/head.S linux/arch/mips/kernel/head.S --- v2.4.5/linux/arch/mips/kernel/head.S Sun Jul 9 22:18:15 2000 +++ linux/arch/mips/kernel/head.S Mon Jul 2 13:56:40 2001 @@ -1,5 +1,4 @@ -/* $Id: head.S,v 1.18 2000/03/03 22:17:07 kevink Exp $ - * +/* * arch/mips/kernel/head.S * * This file is subject to the terms and conditions of the GNU General Public @@ -15,6 +14,14 @@ * Copyright (C) 1999 Silicon Graphics, Inc. * * Head.S contains the MIPS exception handler and startup code. + * + ************************************************************************** + * 9 Nov, 2000. + * Added Cache Error exception handler and SBDDP EJTAG debug exception. + * + * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + ************************************************************************** */ #include #include @@ -52,9 +59,19 @@ .set noat LEAF(except_vec0_r4000) .set mips3 +#ifdef CONFIG_SMP + mfc0 k1, CP0_CONTEXT + la k0, current_pgd + srl k1, 23 + sll k1, 2 + addu k1, k0, k1 + lw k1, (k1) +#else + lw k1, current_pgd # get pgd pointer +#endif mfc0 k0, CP0_BADVADDR # Get faulting address srl k0, k0, 22 # get pgd only bits - lw k1, current_pgd # get pgd pointer + sll k0, k0, 2 addu k1, k1, k0 # add in pgd offset mfc0 k0, CP0_CONTEXT # get context reg @@ -69,8 +86,8 @@ srl k1, k1, 6 # convert to entrylo1 mtc0 k1, CP0_ENTRYLO1 # load it b 1f - tlbwr # write random tlb entry -1: + tlbwr # write random tlb entry +1: nop eret # return from trap END(except_vec0_r4000) @@ -308,12 +325,26 @@ /* Cache Error */ LEAF(except_vec2_generic) - /* Famous last words: unreached */ - mfc0 a1,CP0_ERROREPC - PRINT("Cache error exception: c0_errorepc == %08x\n") -1: - j 1b - nop + .set noat + .set mips0 + /* + * This is a very bad place to be. Our cache error + * detection has triggered. If we have write-back data + * in the cache, we may not be able to recover. As a + * first-order desperate measure, turn off KSEG0 cacheing. + */ + mfc0 k0,CP0_CONFIG + li k1,~CONF_CM_CMASK + and k0,k0,k1 + ori k0,k0,CONF_CM_UNCACHED + mtc0 k0,CP0_CONFIG + /* Give it a few cycles to sink in... */ + nop + nop + nop + + j cache_parity_error + nop END(except_vec2_generic) /* General exception vector R4000 version. */ @@ -338,6 +369,7 @@ * c0_badvaddr because after return from this exception handler the load / * store will be re-executed. */ + .set mips3 handle_vced: mfc0 k0, CP0_BADVADDR li k1, -4 @@ -393,6 +425,38 @@ nop END(except_vec4) + /* + * SBDDP EJTAG debug exception handler. + * The EJTAG debug exception entry point is 0xbfc00480, which + * normally is in the boot PROM, so the boot PROM must do a + * unconditional jump to this vector. + */ + NESTED(except_vec_ejtag_debug, 0, sp) + j ejtag_debug_handler + nop + END(except_vec_ejtag_debug) + + /* + * EJTAG debug exception handler. + */ + NESTED(ejtag_debug_handler, PT_SIZE, sp) + .set noat + .set noreorder + SAVE_ALL + PRINT("SDBBP EJTAG debug exception - not handled yet, just ignored!\n"); + mfc0 k0, $23 # Get EJTAG Debug register. + mfc0 k1, $24 # Get DEPC register. + bgez k0, 1f + addiu k1, k1, 4 # SBDDP inst. in delay slot. + addiu k1, k1, 4 +1: mtc0 k1, $24 + RESTORE_ALL + .word 0x4200001f # deret, return EJTAG debug exception. + nop + .set at + END(ejtag_debug_handler) + + /* * Kernel entry point */ @@ -407,9 +471,9 @@ */ la $28, init_task_union addiu t0, $28, KERNEL_STACK_SIZE-32 - sw t0, kernelsp subu sp, t0, 4*SZREG + sw t0, kernelsp /* The firmware/bootloader passes argc/argp/envp * to us as arguments. But clear bss first because * the romvec and other important info is stored there @@ -427,6 +491,30 @@ nop END(kernel_entry) + +#ifdef CONFIG_SMP + +/* + * SMP slave cpus entry point. Board specific code + * for bootstrap calls this function after setting up + * the stack and gp registers. + */ + LEAF(smp_bootstrap) + .set push + .set noreorder + mtc0 zero, CP0_WIRED + CLI + mfc0 t0, CP0_STATUS + li t1, ~(ST0_CU1|ST0_CU2|ST0_CU3|ST0_BEV); + and t0, t1 + or t0, (ST0_CU0|ST0_KX|ST0_SX|ST0_FR); + addiu a0, zero, 0 + jal start_secondary + mtc0 t0, CP0_STATUS + .set pop + END(smp_bootstrap) +#endif + /* * This buffer is reserved for the use of the cache error handler. */ @@ -434,12 +522,19 @@ EXPORT(cache_error_buffer) .fill 32*4,1,0 +#ifndef CONFIG_SMP EXPORT(kernelsp) PTR 0 EXPORT(current_pgd) - PTR 0 + PTR 0 +#else + /* There's almost certainly a better way to do this with the macros...*/ + .globl kernelsp + .comm kernelsp, NR_CPUS * 8, 8 + .globl current_pgd + .comm current_pgd, NR_CPUS * 8, 8 +#endif .text - .org 0x1000 EXPORT(swapper_pg_dir) diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/i8259.c linux/arch/mips/kernel/i8259.c --- v2.4.5/linux/arch/mips/kernel/i8259.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/kernel/i8259.c Mon Jul 2 13:56:40 2001 @@ -0,0 +1,308 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Code to handle x86 style IRQs plus some generic interrupt stuff. + * + * Copyright (C) 1992 Linus Torvalds + * Copyright (C) 1994 - 2000 Ralf Baechle + */ +#include +#include +#include +#include +#include +#include +#include + +#include + +void enable_8259A_irq(unsigned int irq); +void disable_8259A_irq(unsigned int irq); + +/* + * This is the 'legacy' 8259A Programmable Interrupt Controller, + * present in the majority of PC/AT boxes. + * plus some generic x86 specific things if generic specifics makes + * any sense at all. + * this file should become arch/i386/kernel/irq.c when the old irq.c + * moves to arch independent land + */ + +spinlock_t i8259A_lock = SPIN_LOCK_UNLOCKED; + +static void end_8259A_irq (unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_8259A_irq(irq); +} + +#define shutdown_8259A_irq disable_8259A_irq + +void mask_and_ack_8259A(unsigned int); + +static unsigned int startup_8259A_irq(unsigned int irq) +{ + enable_8259A_irq(irq); + + return 0; /* never anything pending */ +} + +static struct hw_interrupt_type i8259A_irq_type = { + "XT-PIC", + startup_8259A_irq, + shutdown_8259A_irq, + enable_8259A_irq, + disable_8259A_irq, + mask_and_ack_8259A, + end_8259A_irq, + NULL +}; + +/* + * 8259A PIC functions to handle ISA devices: + */ + +/* + * This contains the irq mask for both 8259A irq controllers, + */ +static unsigned int cached_irq_mask = 0xffff; + +#define __byte(x,y) (((unsigned char *)&(y))[x]) +#define cached_21 (__byte(0,cached_irq_mask)) +#define cached_A1 (__byte(1,cached_irq_mask)) + +void disable_8259A_irq(unsigned int irq) +{ + unsigned int mask = 1 << irq; + unsigned long flags; + + spin_lock_irqsave(&i8259A_lock, flags); + cached_irq_mask |= mask; + if (irq & 8) + outb(cached_A1,0xA1); + else + outb(cached_21,0x21); + spin_unlock_irqrestore(&i8259A_lock, flags); +} + +void enable_8259A_irq(unsigned int irq) +{ + unsigned int mask = ~(1 << irq); + unsigned long flags; + + spin_lock_irqsave(&i8259A_lock, flags); + cached_irq_mask &= mask; + if (irq & 8) + outb(cached_A1,0xA1); + else + outb(cached_21,0x21); + spin_unlock_irqrestore(&i8259A_lock, flags); +} + +int i8259A_irq_pending(unsigned int irq) +{ + unsigned int mask = 1 << irq; + unsigned long flags; + int ret; + + spin_lock_irqsave(&i8259A_lock, flags); + if (irq < 8) + ret = inb(0x20) & mask; + else + ret = inb(0xA0) & (mask >> 8); + spin_unlock_irqrestore(&i8259A_lock, flags); + + return ret; +} + +void make_8259A_irq(unsigned int irq) +{ + disable_irq_nosync(irq); + irq_desc[irq].handler = &i8259A_irq_type; + enable_irq(irq); +} + +/* + * This function assumes to be called rarely. Switching between + * 8259A registers is slow. + * This has to be protected by the irq controller spinlock + * before being called. + */ +static inline int i8259A_irq_real(unsigned int irq) +{ + int value; + int irqmask = 1 << irq; + + if (irq < 8) { + outb(0x0B,0x20); /* ISR register */ + value = inb(0x20) & irqmask; + outb(0x0A,0x20); /* back to the IRR register */ + return value; + } + outb(0x0B,0xA0); /* ISR register */ + value = inb(0xA0) & (irqmask >> 8); + outb(0x0A,0xA0); /* back to the IRR register */ + return value; +} + +/* + * Careful! The 8259A is a fragile beast, it pretty + * much _has_ to be done exactly like this (mask it + * first, _then_ send the EOI, and the order of EOI + * to the two 8259s is important! + */ +void mask_and_ack_8259A(unsigned int irq) +{ + unsigned int irqmask = 1 << irq; + unsigned long flags; + + spin_lock_irqsave(&i8259A_lock, flags); + /* + * Lightweight spurious IRQ detection. We do not want to overdo + * spurious IRQ handling - it's usually a sign of hardware problems, so + * we only do the checks we can do without slowing down good hardware + * nnecesserily. + * + * Note that IRQ7 and IRQ15 (the two spurious IRQs usually resulting + * rom the 8259A-1|2 PICs) occur even if the IRQ is masked in the 8259A. + * Thus we can check spurious 8259A IRQs without doing the quite slow + * i8259A_irq_real() call for every IRQ. This does not cover 100% of + * spurious interrupts, but should be enough to warn the user that + * there is something bad going on ... + */ + if (cached_irq_mask & irqmask) + goto spurious_8259A_irq; + cached_irq_mask |= irqmask; + +handle_real_irq: + if (irq & 8) { + inb(0xA1); /* DUMMY - (do we need this?) */ + outb(cached_A1,0xA1); + outb(0x60+(irq&7),0xA0);/* 'Specific EOI' to slave */ + outb(0x62,0x20); /* 'Specific EOI' to master-IRQ2 */ + } else { + inb(0x21); /* DUMMY - (do we need this?) */ + outb(cached_21,0x21); + outb(0x60+irq,0x20); /* 'Specific EOI' to master */ + } + spin_unlock_irqrestore(&i8259A_lock, flags); + return; + +spurious_8259A_irq: + /* + * this is the slow path - should happen rarely. + */ + if (i8259A_irq_real(irq)) + /* + * oops, the IRQ _is_ in service according to the + * 8259A - not spurious, go handle it. + */ + goto handle_real_irq; + + { + static int spurious_irq_mask = 0; + /* + * At this point we can be sure the IRQ is spurious, + * lets ACK and report it. [once per IRQ] + */ + if (!(spurious_irq_mask & irqmask)) { + printk("spurious 8259A interrupt: IRQ%d.\n", irq); + spurious_irq_mask |= irqmask; + } + irq_err_count++; + /* + * Theoretically we do not have to handle this IRQ, + * but in Linux this does not cause problems and is + * simpler for us. + */ + goto handle_real_irq; + } +} + +void __init init_8259A(int auto_eoi) +{ + unsigned long flags; + + spin_lock_irqsave(&i8259A_lock, flags); + + outb(0xff, 0x21); /* mask all of 8259A-1 */ + outb(0xff, 0xA1); /* mask all of 8259A-2 */ + + /* + * outb_p - this has to work on a wide range of PC hardware. + */ + outb_p(0x11, 0x20); /* ICW1: select 8259A-1 init */ + outb_p(0x20 + 0, 0x21); /* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */ + outb_p(0x04, 0x21); /* 8259A-1 (the master) has a slave on IR2 */ + if (auto_eoi) + outb_p(0x03, 0x21); /* master does Auto EOI */ + else + outb_p(0x01, 0x21); /* master expects normal EOI */ + + outb_p(0x11, 0xA0); /* ICW1: select 8259A-2 init */ + outb_p(0x20 + 8, 0xA1); /* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */ + outb_p(0x02, 0xA1); /* 8259A-2 is a slave on master's IR2 */ + outb_p(0x01, 0xA1); /* (slave's support for AEOI in flat mode + is to be investigated) */ + + if (auto_eoi) + /* + * in AEOI mode we just have to mask the interrupt + * when acking. + */ + i8259A_irq_type.ack = disable_8259A_irq; + else + i8259A_irq_type.ack = mask_and_ack_8259A; + + udelay(100); /* wait for 8259A to initialize */ + + outb(cached_21, 0x21); /* restore master IRQ mask */ + outb(cached_A1, 0xA1); /* restore slave IRQ mask */ + + spin_unlock_irqrestore(&i8259A_lock, flags); +} + +asmlinkage void i8259_do_irq(int irq, struct pt_regs regs) +{ + panic("i8259_do_irq: I want to be implemented"); +} + +/* + * IRQ2 is cascade interrupt to second interrupt controller + */ +static struct irqaction irq2 = { + no_action, 0, 0, "cascade", NULL, NULL +}; + +static struct resource pic1_io_resource = { + "pic1", 0x20, 0x3f, IORESOURCE_BUSY +}; + +static struct resource pic2_io_resource = { + "pic2", 0xa0, 0xbf, IORESOURCE_BUSY +}; + +/* + * On systems with i8259-style interrupt controllers we assume for + * driver compatibility reasons interrupts 0 - 15 to be the i8295 + * interrupts even if the hardware uses a different interrupt numbering. + */ +void __init init_i8259_irqs (void) +{ + int i; + + request_resource(&ioport_resource, &pic1_io_resource); + request_resource(&ioport_resource, &pic2_io_resource); + setup_irq(2, &irq2); + + init_8259A(0); + + for (i = 0; i < 16; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 1; + irq_desc[i].handler = &i8259A_irq_type; + } +} diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/irixsig.c linux/arch/mips/kernel/irixsig.c --- v2.4.5/linux/arch/mips/kernel/irixsig.c Wed Jan 24 15:21:10 2001 +++ linux/arch/mips/kernel/irixsig.c Mon Jul 2 13:56:40 2001 @@ -714,7 +714,7 @@ SET_LINKS(p); notify_parent(p, SIGCHLD); } else - release(p); + release_task(p); goto end_waitsys; default: continue; diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/irq.c linux/arch/mips/kernel/irq.c --- v2.4.5/linux/arch/mips/kernel/irq.c Fri Feb 9 11:29:44 2001 +++ linux/arch/mips/kernel/irq.c Mon Jul 2 13:56:40 2001 @@ -8,289 +8,367 @@ * Copyright (C) 1992 Linus Torvalds * Copyright (C) 1994 - 2000 Ralf Baechle */ -#include -#include +#include +#include #include -#include -#include -#include -#include -#include #include -#include -#include +#include #include +#include #include +#include -#include -#include -#include -#include -#include #include -#include -#include /* - * Linux has a controller-independent x86 interrupt architecture. - * every controller has a 'controller-template', that is used - * by the main code to do the right thing. Each driver-visible - * interrupt source is transparently wired to the apropriate - * controller. Thus drivers need not be aware of the - * interrupt-controller. - * - * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC, - * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC. - * (IO-APICs assumed to be messaging to Pentium local-APICs) - * - * the code is designed to be easily extended with new/different - * interrupt controllers, without having to do assembly magic. + * Controller mappings for all interrupt sources: */ +irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = + { [0 ... NR_IRQS-1] = { 0, &no_irq_type, NULL, 0, SPIN_LOCK_UNLOCKED}}; /* - * This contains the irq mask for both 8259A irq controllers, it's an - * int so we can deal with the third PIC in some systems like the RM300. - * (XXX This is broken for big endian.) + * Special irq handlers. */ -static unsigned int cached_irq_mask = 0xffff; - -#define __byte(x,y) (((unsigned char *)&(y))[x]) -#define __word(x,y) (((unsigned short *)&(y))[x]) -#define __long(x,y) (((unsigned int *)&(y))[x]) -#define cached_21 (__byte(0,cached_irq_mask)) -#define cached_A1 (__byte(1,cached_irq_mask)) - -unsigned long spurious_count = 0; +void no_action(int cpl, void *dev_id, struct pt_regs *regs) { } /* - * (un)mask_irq, disable_irq() and enable_irq() only handle (E)ISA and - * PCI devices. Other onboard hardware needs specific routines. + * Generic no controller code */ -static inline void mask_irq(unsigned int irq) -{ - cached_irq_mask |= 1 << irq; - if (irq & 8) { - outb(cached_A1, 0xa1); - } else { - outb(cached_21, 0x21); - } -} -static inline void unmask_irq(unsigned int irq) -{ - cached_irq_mask &= ~(1 << irq); - if (irq & 8) { - outb(cached_A1, 0xa1); - } else { - outb(cached_21, 0x21); - } -} - -void i8259_disable_irq(unsigned int irq_nr) -{ - unsigned long flags; - - save_and_cli(flags); - mask_irq(irq_nr); - restore_flags(flags); -} +static void enable_none(unsigned int irq) { } +static unsigned int startup_none(unsigned int irq) { return 0; } +static void disable_none(unsigned int irq) { } +static void ack_none(unsigned int irq) +{ + /* + * 'what should we do if we get a hw irq event on an illegal vector'. + * each architecture has to answer this themselves, it doesnt deserve + * a generic callback i think. + */ + printk("unexpected interrupt %d\n", irq); +} + +/* startup is the same as "enable", shutdown is same as "disable" */ +#define shutdown_none disable_none +#define end_none enable_none + +struct hw_interrupt_type no_irq_type = { + "none", + startup_none, + shutdown_none, + enable_none, + disable_none, + ack_none, + end_none +}; -void i8259_enable_irq(unsigned int irq_nr) -{ - unsigned long flags; - save_and_cli(flags); - unmask_irq(irq_nr); - restore_flags(flags); -} +volatile unsigned long irq_err_count, spurious_count; -static struct irqaction *irq_action[NR_IRQS] = { - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; +/* + * Generic, controller-independent functions: + */ int get_irq_list(char *buf) { - int i, len = 0; struct irqaction * action; + char *p = buf; + int i; + + p += sprintf(p, " "); + for (i=0; i < 1 /*smp_num_cpus*/; i++) + p += sprintf(p, "CPU%d ", i); + *p++ = '\n'; - for (i = 0 ; i < 32 ; i++) { - action = irq_action[i]; + for (i = 0 ; i < NR_IRQS ; i++) { + action = irq_desc[i].action; if (!action) continue; - len += sprintf(buf+len, "%2d: %8d %c %s", - i, kstat.irqs[0][i], - (action->flags & SA_INTERRUPT) ? '+' : ' ', - action->name); - for (action=action->next; action; action = action->next) { - len += sprintf(buf+len, ",%s %s", - (action->flags & SA_INTERRUPT) ? " +" : "", - action->name); - } - len += sprintf(buf+len, "\n"); + p += sprintf(p, "%3d: ",i); + p += sprintf(p, "%10u ", kstat_irqs(i)); + p += sprintf(p, " %14s", irq_desc[i].handler->typename); + p += sprintf(p, " %s", action->name); + + for (action=action->next; action; action = action->next) + p += sprintf(p, ", %s", action->name); + *p++ = '\n'; } - return len; -} - -static inline void i8259_mask_and_ack_irq(int irq) -{ - cached_irq_mask |= 1 << irq; - - if (irq & 8) { - inb(0xa1); - outb(cached_A1, 0xa1); - outb(0x62, 0x20); /* Specific EOI to cascade */ - outb(0x20, 0xa0); - } else { - inb(0x21); - outb(cached_21, 0x21); - outb(0x20, 0x20); - } + p += sprintf(p, "ERR: %10lu\n", irq_err_count); + return p - buf; } -asmlinkage void i8259_do_irq(int irq, struct pt_regs *regs) +/* + * This should really return information about whether + * we should do bottom half handling etc. Right now we + * end up _always_ checking the bottom half, which is a + * waste of time and is not what some drivers would + * prefer. + */ +int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action) { - struct irqaction *action; - int do_random, cpu; - - cpu = smp_processor_id(); - irq_enter(cpu); + int status; + int cpu = smp_processor_id(); - if (irq >= 16) - goto out; + irq_enter(cpu, irq); - i8259_mask_and_ack_irq(irq); - - kstat.irqs[cpu][irq]++; - - action = *(irq + irq_action); - if (!action) - goto out; + status = 1; /* Force the "do bottom halves" bit */ if (!(action->flags & SA_INTERRUPT)) __sti(); - action = *(irq + irq_action); - do_random = 0; - do { - do_random |= action->flags; + + do { + status |= action->flags; action->handler(irq, action->dev_id, regs); action = action->next; - } while (action); - if (do_random & SA_SAMPLE_RANDOM) + } while (action); + if (status & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); __cli(); - unmask_irq (irq); -out: - irq_exit(cpu); + irq_exit(cpu, irq); + + return status; } /* - * do_IRQ handles IRQ's that have been installed without the - * SA_INTERRUPT flag: it uses the full signal-handling return - * and runs with other interrupts enabled. All relatively slow - * IRQ's should use this format: notably the keyboard/timer - * routines. + * Generic enable/disable code: this just calls + * down into the PIC-specific version for the actual + * hardware disable after having gotten the irq + * controller lock. + */ + +/** + * disable_irq_nosync - disable an irq without waiting + * @irq: Interrupt to disable + * + * Disable the selected interrupt line. Disables of an interrupt + * stack. Unlike disable_irq(), this function does not ensure existing + * instances of the IRQ handler have completed before returning. + * + * This function may be called from IRQ context. */ -asmlinkage void do_IRQ(int irq, struct pt_regs * regs) + +void inline disable_irq_nosync(unsigned int irq) { - struct irqaction *action; - int do_random, cpu; - - cpu = smp_processor_id(); - irq_enter(cpu); - kstat.irqs[cpu][irq]++; + irq_desc_t *desc = irq_desc + irq; + unsigned long flags; - action = *(irq + irq_action); - if (action) { - if (!(action->flags & SA_INTERRUPT)) - __sti(); - action = *(irq + irq_action); - do_random = 0; - do { - do_random |= action->flags; - action->handler(irq, action->dev_id, regs); - action = action->next; - } while (action); - if (do_random & SA_SAMPLE_RANDOM) - add_interrupt_randomness(irq); - __cli(); + spin_lock_irqsave(&desc->lock, flags); + if (!desc->depth++) { + desc->status |= IRQ_DISABLED; + desc->handler->disable(irq); } - irq_exit(cpu); + spin_unlock_irqrestore(&desc->lock, flags); +} - if (softirq_active(cpu)&softirq_mask(cpu)) - do_softirq(); +/** + * disable_irq - disable an irq and wait for completion + * @irq: Interrupt to disable + * + * Disable the selected interrupt line. Disables of an interrupt + * stack. That is for two disables you need two enables. This + * function waits for any pending IRQ handlers for this interrupt + * to complete before returning. If you use this function while + * holding a resource the IRQ handler may need you will deadlock. + * + * This function may be called - with care - from IRQ context. + */ + +void disable_irq(unsigned int irq) +{ + disable_irq_nosync(irq); - /* unmasking and bottom half handling is done magically for us. */ + if (!local_irq_count(smp_processor_id())) { + do { + barrier(); + } while (irq_desc[irq].status & IRQ_INPROGRESS); + } } -int i8259_setup_irq(int irq, struct irqaction * new) +/** + * enable_irq - enable interrupt handling on an irq + * @irq: Interrupt to enable + * + * Re-enables the processing of interrupts on this IRQ line + * providing no disable_irq calls are now in effect. + * + * This function may be called from IRQ context. + */ + +void enable_irq(unsigned int irq) { - int shared = 0; - struct irqaction *old, **p; + irq_desc_t *desc = irq_desc + irq; unsigned long flags; - p = irq_action + irq; - if ((old = *p) != NULL) { - /* Can't share interrupts unless both agree to */ - if (!(old->flags & new->flags & SA_SHIRQ)) - return -EBUSY; + spin_lock_irqsave(&desc->lock, flags); + switch (desc->depth) { + case 1: { + unsigned int status = desc->status & ~IRQ_DISABLED; + desc->status = status; + if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { + desc->status = status | IRQ_REPLAY; + hw_resend_irq(desc->handler,irq); + } + desc->handler->enable(irq); + /* fall-through */ + } + default: + desc->depth--; + break; + case 0: + printk("enable_irq(%u) unbalanced from %p\n", irq, + __builtin_return_address(0)); + } + spin_unlock_irqrestore(&desc->lock, flags); +} - /* Can't share interrupts unless both are same type */ - if ((old->flags ^ new->flags) & SA_INTERRUPT) - return -EBUSY; +/* + * do_IRQ handles all normal device IRQ's (the special + * SMP cross-CPU interrupts have their own specific + * handlers). + */ +asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs) +{ + /* + * We ack quickly, we don't want the irq controller + * thinking we're snobs just because some other CPU has + * disabled global interrupts (we have already done the + * INT_ACK cycles, it's too late to try to pretend to the + * controller that we aren't taking the interrupt). + * + * 0 return value means that this irq is already being + * handled by some other CPU. (or is disabled) + */ + int cpu = smp_processor_id(); + irq_desc_t *desc = irq_desc + irq; + struct irqaction * action; + unsigned int status; - /* add new interrupt at end of irq queue */ - do { - p = &old->next; - old = *p; - } while (old); - shared = 1; + kstat.irqs[cpu][irq]++; + spin_lock(&desc->lock); + desc->handler->ack(irq); + /* + REPLAY is when Linux resends an IRQ that was dropped earlier + WAITING is used by probe to mark irqs that are being tested + */ + status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING); + status |= IRQ_PENDING; /* we _want_ to handle it */ + + /* + * If the IRQ is disabled for whatever reason, we cannot + * use the action we have. + */ + action = NULL; + if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) { + action = desc->action; + status &= ~IRQ_PENDING; /* we commit to handling */ + status |= IRQ_INPROGRESS; /* we are handling it */ } + desc->status = status; - if (new->flags & SA_SAMPLE_RANDOM) - rand_initialize_irq(irq); - - save_and_cli(flags); - *p = new; + /* + * If there is no IRQ handler or it was disabled, exit early. + Since we set PENDING, if another processor is handling + a different instance of this same irq, the other processor + will take care of it. + */ + if (!action) + goto out; - if (!shared) { - if (is_i8259_irq(irq)) - unmask_irq(irq); -#if CONFIG_DDB5074 /* This has no business here */ - else - nile4_enable_irq(irq_to_nile4(irq)); -#endif + /* + * Edge triggered interrupts need to remember + * pending events. + * This applies to any hw interrupts that allow a second + * instance of the same irq to arrive while we are in do_IRQ + * or in the handler. But the code here only handles the _second_ + * instance of the irq, not the third or fourth. So it is mostly + * useful for irq hardware that does not mask cleanly in an + * SMP environment. + */ + for (;;) { + spin_unlock(&desc->lock); + handle_IRQ_event(irq, regs, action); + spin_lock(&desc->lock); + + if (!(desc->status & IRQ_PENDING)) + break; + desc->status &= ~IRQ_PENDING; } - restore_flags(flags); - return 0; + desc->status &= ~IRQ_INPROGRESS; +out: + /* + * The ->end() handler has to deal with interrupts which got + * disabled while the handler was running. + */ + desc->handler->end(irq); + spin_unlock(&desc->lock); + + if (softirq_active(cpu) & softirq_mask(cpu)) + do_softirq(); + return 1; } -/* - * Request_interrupt and free_interrupt ``sort of'' handle interrupts of - * non i8259 devices. They will have to be replaced by architecture - * specific variants. For now we still use this as broken as it is because - * it used to work ... +/** + * request_irq - allocate an interrupt line + * @irq: Interrupt line to allocate + * @handler: Function to be called when the IRQ occurs + * @irqflags: Interrupt type flags + * @devname: An ascii name for the claiming device + * @dev_id: A cookie passed back to the handler function + * + * This call allocates interrupt resources and enables the + * interrupt line and IRQ handling. From the point this + * call is made your handler function may be invoked. Since + * your handler function must clear any interrupt the board + * raises, you must take care both to initialise your hardware + * and to set up the interrupt handler in the right order. + * + * Dev_id must be globally unique. Normally the address of the + * device data structure is used as the cookie. Since the handler + * receives this value it makes sense to use it. + * + * If your interrupt is shared you must pass a non NULL dev_id + * as this is required when freeing the interrupt. + * + * Flags: + * + * SA_SHIRQ Interrupt is shared + * + * SA_INTERRUPT Disable local interrupts while processing + * + * SA_SAMPLE_RANDOM The interrupt can be used for entropy + * */ + int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, const char * devname, void *dev_id) + unsigned long irqflags, + const char * devname, + void *dev_id) { int retval; struct irqaction * action; - if (irq >= 32) +#if 1 + /* + * Sanity-check: shared interrupts should REALLY pass in + * a real dev-ID, otherwise we'll have trouble later trying + * to figure out which interrupt is which (messes up the + * interrupt freeing logic etc). + */ + if (irqflags & SA_SHIRQ) { + if (!dev_id) + printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n", devname, (&irq)[-1]); + } +#endif + + if (irq >= NR_IRQS) return -EINVAL; if (!handler) return -EINVAL; - action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL); + action = (struct irqaction *) + kmalloc(sizeof(struct irqaction), GFP_KERNEL); if (!action) return -ENOMEM; @@ -301,107 +379,329 @@ action->next = NULL; action->dev_id = dev_id; - retval = i8259_setup_irq(irq, action); - + retval = setup_irq(irq, action); if (retval) kfree(action); return retval; } - + +/** + * free_irq - free an interrupt + * @irq: Interrupt line to free + * @dev_id: Device identity to free + * + * Remove an interrupt handler. The handler is removed and if the + * interrupt line is no longer in use by any driver it is disabled. + * On a shared IRQ the caller must ensure the interrupt is disabled + * on the card it drives before calling this function. The function + * does not return until any executing interrupts for this IRQ + * have completed. + * + * This function may be called from interrupt context. + * + * Bugs: Attempting to free an irq in a handler for the same irq hangs + * the machine. + */ + void free_irq(unsigned int irq, void *dev_id) { - struct irqaction * action, **p; + irq_desc_t *desc; + struct irqaction **p; unsigned long flags; - if (irq > 31) { - printk("Trying to free IRQ%d\n",irq); + if (irq >= NR_IRQS) return; - } - for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) { - if (action->dev_id != dev_id) - continue; - /* Found it - now free it */ - save_and_cli(flags); - *p = action->next; - if (!irq[irq_action]) - mask_irq(irq); - restore_flags(flags); - kfree(action); + desc = irq_desc + irq; + spin_lock_irqsave(&desc->lock,flags); + p = &desc->action; + for (;;) { + struct irqaction * action = *p; + if (action) { + struct irqaction **pp = p; + p = &action->next; + if (action->dev_id != dev_id) + continue; + + /* Found it - now remove it from the list of entries */ + *pp = action->next; + if (!desc->action) { + desc->status |= IRQ_DISABLED; + desc->handler->shutdown(irq); + } + spin_unlock_irqrestore(&desc->lock,flags); + +#ifdef CONFIG_SMP + /* Wait to make sure it's not being used on another CPU */ + while (desc->status & IRQ_INPROGRESS) + barrier(); +#endif + kfree(action); + return; + } + printk("Trying to free free IRQ%d\n",irq); + spin_unlock_irqrestore(&desc->lock,flags); return; } - printk("Trying to free free IRQ%d\n",irq); } -unsigned long probe_irq_on (void) +/* + * IRQ autodetection code.. + * + * This depends on the fact that any interrupt that + * comes in on to an unassigned handler will get stuck + * with "IRQ_WAITING" cleared and the interrupt + * disabled. + */ + +static DECLARE_MUTEX(probe_sem); + +/** + * probe_irq_on - begin an interrupt autodetect + * + * Commence probing for an interrupt. The interrupts are scanned + * and a mask of potential interrupt lines is returned. + * + */ + +unsigned long probe_irq_on(void) { - unsigned int i, irqs = 0; + unsigned int i; + irq_desc_t *desc; + unsigned long val; unsigned long delay; - /* first, enable any unassigned (E)ISA irqs */ - for (i = 15; i > 0; i--) { - if (!irq_action[i]) { - i8259_enable_irq(i); - irqs |= (1 << i); + down(&probe_sem); + /* + * something may have generated an irq long ago and we want to + * flush such a longstanding irq before considering it as spurious. + */ + for (i = NR_IRQS-1; i > 0; i--) { + desc = irq_desc + i; + + spin_lock_irq(&desc->lock); + if (!irq_desc[i].action) + irq_desc[i].handler->startup(i); + spin_unlock_irq(&desc->lock); + } + + /* Wait for longstanding interrupts to trigger. */ + for (delay = jiffies + HZ/50; time_after(delay, jiffies); ) + /* about 20ms delay */ synchronize_irq(); + + /* + * enable any unassigned irqs + * (we must startup again here because if a longstanding irq + * happened in the previous stage, it may have masked itself) + */ + for (i = NR_IRQS-1; i > 0; i--) { + desc = irq_desc + i; + + spin_lock_irq(&desc->lock); + if (!desc->action) { + desc->status |= IRQ_AUTODETECT | IRQ_WAITING; + if (desc->handler->startup(i)) + desc->status |= IRQ_PENDING; } + spin_unlock_irq(&desc->lock); } - /* wait for spurious interrupts to mask themselves out again */ - for (delay = jiffies + HZ/10; time_before(jiffies, delay); ) - /* about 100ms delay */; + /* + * Wait for spurious interrupts to trigger + */ + for (delay = jiffies + HZ/10; time_after(delay, jiffies); ) + /* about 100ms delay */ synchronize_irq(); + + /* + * Now filter out any obviously spurious interrupts + */ + val = 0; + for (i = 0; i < NR_IRQS; i++) { + irq_desc_t *desc = irq_desc + i; + unsigned int status; + + spin_lock_irq(&desc->lock); + status = desc->status; + + if (status & IRQ_AUTODETECT) { + /* It triggered already - consider it spurious. */ + if (!(status & IRQ_WAITING)) { + desc->status = status & ~IRQ_AUTODETECT; + desc->handler->shutdown(i); + } else + if (i < 32) + val |= 1 << i; + } + spin_unlock_irq(&desc->lock); + } - /* now filter out any obviously spurious interrupts */ - return irqs & ~cached_irq_mask; + return val; } -int probe_irq_off (unsigned long irqs) +/* + * Return a mask of triggered interrupts (this + * can handle only legacy ISA interrupts). + */ + +/** + * probe_irq_mask - scan a bitmap of interrupt lines + * @val: mask of interrupts to consider + * + * Scan the ISA bus interrupt lines and return a bitmap of + * active interrupts. The interrupt probe logic state is then + * returned to its previous value. + * + * Note: we need to scan all the irq's even though we will + * only return ISA irq numbers - just so that we reset them + * all to a known state. + */ +unsigned int probe_irq_mask(unsigned long val) { - unsigned int i; + int i; + unsigned int mask; -#ifdef DEBUG - printk("probe_irq_off: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask); -#endif - irqs &= cached_irq_mask; - if (!irqs) - return 0; - i = ffz(~irqs); - if (irqs != (irqs & (1 << i))) - i = -i; - return i; + mask = 0; + for (i = 0; i < NR_IRQS; i++) { + irq_desc_t *desc = irq_desc + i; + unsigned int status; + + spin_lock_irq(&desc->lock); + status = desc->status; + + if (status & IRQ_AUTODETECT) { + if (i < 16 && !(status & IRQ_WAITING)) + mask |= 1 << i; + + desc->status = status & ~IRQ_AUTODETECT; + desc->handler->shutdown(i); + } + spin_unlock_irq(&desc->lock); + } + up(&probe_sem); + + return mask & val; } -int (*irq_cannonicalize)(int irq); +/* + * Return the one interrupt that triggered (this can + * handle any interrupt source). + */ -static int i8259_irq_cannonicalize(int irq) +/** + * probe_irq_off - end an interrupt autodetect + * @val: mask of potential interrupts (unused) + * + * Scans the unused interrupt lines and returns the line which + * appears to have triggered the interrupt. If no interrupt was + * found then zero is returned. If more than one interrupt is + * found then minus the first candidate is returned to indicate + * their is doubt. + * + * The interrupt probe logic state is returned to its previous + * value. + * + * BUGS: When used in a module (which arguably shouldnt happen) + * nothing prevents two IRQ probe callers from overlapping. The + * results of this are non-optimal. + */ + +int probe_irq_off(unsigned long val) { - return ((irq == 2) ? 9 : irq); + int i, irq_found, nr_irqs; + + nr_irqs = 0; + irq_found = 0; + for (i = 0; i < NR_IRQS; i++) { + irq_desc_t *desc = irq_desc + i; + unsigned int status; + + spin_lock_irq(&desc->lock); + status = desc->status; + + if (status & IRQ_AUTODETECT) { + if (!(status & IRQ_WAITING)) { + if (!nr_irqs) + irq_found = i; + nr_irqs++; + } + desc->status = status & ~IRQ_AUTODETECT; + desc->handler->shutdown(i); + } + spin_unlock_irq(&desc->lock); + } + up(&probe_sem); + + if (nr_irqs > 1) + irq_found = -irq_found; + return irq_found; } -void __init i8259_init(void) +/* this was setup_x86_irq but it seems pretty generic */ +int setup_irq(unsigned int irq, struct irqaction * new) { - /* Init master interrupt controller */ - outb(0x11, 0x20); /* Start init sequence */ - outb(0x00, 0x21); /* Vector base */ - outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */ - outb(0x01, 0x21); /* Select 8086 mode */ - outb(0xff, 0x21); /* Mask all */ - - /* Init slave interrupt controller */ - outb(0x11, 0xa0); /* Start init sequence */ - outb(0x08, 0xa1); /* Vector base */ - outb(0x02, 0xa1); /* edge triggered, Cascade (slave) on IRQ2 */ - outb(0x01, 0xa1); /* Select 8086 mode */ - outb(0xff, 0xa1); /* Mask all */ + int shared = 0; + unsigned long flags; + struct irqaction *old, **p; + irq_desc_t *desc = irq_desc + irq; + + /* + * Some drivers like serial.c use request_irq() heavily, + * so we have to be careful not to interfere with a + * running system. + */ + if (new->flags & SA_SAMPLE_RANDOM) { + /* + * This function might sleep, we want to call it first, + * outside of the atomic block. + * Yes, this might clear the entropy pool if the wrong + * driver is attempted to be loaded, without actually + * installing a new handler, but is this really a problem, + * only the sysadmin is able to do this. + */ + rand_initialize_irq(irq); + } - outb(cached_A1, 0xa1); - outb(cached_21, 0x21); + /* + * The following block of code has to be executed atomically + */ + spin_lock_irqsave(&desc->lock,flags); + p = &desc->action; + if ((old = *p) != NULL) { + /* Can't share interrupts unless both agree to */ + if (!(old->flags & new->flags & SA_SHIRQ)) { + spin_unlock_irqrestore(&desc->lock,flags); + return -EBUSY; + } + + /* add new interrupt at end of irq queue */ + do { + p = &old->next; + old = *p; + } while (old); + shared = 1; + } + + *p = new; + + if (!shared) { + desc->depth = 0; + desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING); + desc->handler->startup(irq); + } + spin_unlock_irqrestore(&desc->lock,flags); + + /* register_irq_proc(irq); */ + return 0; } -void __init init_IRQ(void) +void __init init_generic_irq(void) { - irq_cannonicalize = i8259_irq_cannonicalize; - /* i8259_init(); */ - irq_setup(); -} + int i; -EXPORT_SYMBOL(irq_cannonicalize); + for (i = 0; i < NR_IRQS; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = NULL; + irq_desc[i].depth = 1; + irq_desc[i].handler = &no_irq_type; + } +} diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/mips_ksyms.c linux/arch/mips/kernel/mips_ksyms.c --- v2.4.5/linux/arch/mips/kernel/mips_ksyms.c Fri Mar 2 11:15:47 2001 +++ linux/arch/mips/kernel/mips_ksyms.c Mon Jul 2 13:56:40 2001 @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1996, 1997, 1998, 2000 by Ralf Baechle + * Copyright (C) 1996, 1997, 1998, 2000, 2001 by Ralf Baechle */ #include #include @@ -94,9 +94,10 @@ /* * Semaphore stuff */ -EXPORT_SYMBOL(__down_read); -EXPORT_SYMBOL(__down_write); -EXPORT_SYMBOL(__rwsem_wake); +EXPORT_SYMBOL(__down); +EXPORT_SYMBOL(__down_interruptible); +EXPORT_SYMBOL(__down_trylock); +EXPORT_SYMBOL(__up); /* * Base address of ports for Intel style I/O. diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/old-irq.c linux/arch/mips/kernel/old-irq.c --- v2.4.5/linux/arch/mips/kernel/old-irq.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/kernel/old-irq.c Mon Jul 2 13:56:40 2001 @@ -0,0 +1,405 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Code to handle x86 style IRQs plus some generic interrupt stuff. + * + * Copyright (C) 1992 Linus Torvalds + * Copyright (C) 1994 - 2001 Ralf Baechle + * + * Old rotten IRQ code. To be killed as soon as everybody had converted or + * in 2.5.0, whatever comes first. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* + * The board specific setup routine sets irq_setup to point to a board + * specific setup routine. + */ +void (*irq_setup)(void); + +/* + * Linux has a controller-independent x86 interrupt architecture. + * every controller has a 'controller-template', that is used + * by the main code to do the right thing. Each driver-visible + * interrupt source is transparently wired to the apropriate + * controller. Thus drivers need not be aware of the + * interrupt-controller. + * + * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC, + * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC. + * (IO-APICs assumed to be messaging to Pentium local-APICs) + * + * the code is designed to be easily extended with new/different + * interrupt controllers, without having to do assembly magic. + */ + +/* + * This contains the irq mask for both 8259A irq controllers, it's an + * int so we can deal with the third PIC in some systems like the RM300. + * (XXX This is broken for big endian.) + */ +static unsigned int cached_irq_mask = 0xffff; + +#define __byte(x,y) (((unsigned char *)&(y))[x]) +#define __word(x,y) (((unsigned short *)&(y))[x]) +#define __long(x,y) (((unsigned int *)&(y))[x]) + +#define cached_21 (__byte(0,cached_irq_mask)) +#define cached_A1 (__byte(1,cached_irq_mask)) + +unsigned long spurious_count = 0; + +/* + * (un)mask_irq, disable_irq() and enable_irq() only handle (E)ISA and + * PCI devices. Other onboard hardware needs specific routines. + */ +static inline void mask_irq(unsigned int irq) +{ + cached_irq_mask |= 1 << irq; + if (irq & 8) { + outb(cached_A1, 0xa1); + } else { + outb(cached_21, 0x21); + } +} + +static inline void unmask_irq(unsigned int irq) +{ + cached_irq_mask &= ~(1 << irq); + if (irq & 8) { + outb(cached_A1, 0xa1); + } else { + outb(cached_21, 0x21); + } +} + +void i8259_disable_irq(unsigned int irq_nr) +{ + unsigned long flags; + + save_and_cli(flags); + mask_irq(irq_nr); + restore_flags(flags); +} + +void i8259_enable_irq(unsigned int irq_nr) +{ + unsigned long flags; + save_and_cli(flags); + unmask_irq(irq_nr); + restore_flags(flags); +} + +static struct irqaction *irq_action[NR_IRQS] = { + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +int get_irq_list(char *buf) +{ + int i, len = 0; + struct irqaction * action; + + for (i = 0 ; i < 32 ; i++) { + action = irq_action[i]; + if (!action) + continue; + len += sprintf(buf+len, "%2d: %8d %c %s", + i, kstat.irqs[0][i], + (action->flags & SA_INTERRUPT) ? '+' : ' ', + action->name); + for (action=action->next; action; action = action->next) { + len += sprintf(buf+len, ",%s %s", + (action->flags & SA_INTERRUPT) ? " +" : "", + action->name); + } + len += sprintf(buf+len, "\n"); + } + return len; +} + +static inline void i8259_mask_and_ack_irq(int irq) +{ + cached_irq_mask |= 1 << irq; + + if (irq & 8) { + inb(0xa1); + outb(cached_A1, 0xa1); + outb(0x62, 0x20); /* Specific EOI to cascade */ + outb(0x20, 0xa0); + } else { + inb(0x21); + outb(cached_21, 0x21); + outb(0x20, 0x20); + } +} + +asmlinkage void i8259_do_irq(int irq, struct pt_regs *regs) +{ + struct irqaction *action; + int do_random, cpu; + + cpu = smp_processor_id(); + irq_enter(cpu, irq); + + if (irq >= 16) + goto out; + + i8259_mask_and_ack_irq(irq); + + kstat.irqs[cpu][irq]++; + + action = *(irq + irq_action); + if (!action) + goto out; + + if (!(action->flags & SA_INTERRUPT)) + __sti(); + action = *(irq + irq_action); + do_random = 0; + do { + do_random |= action->flags; + action->handler(irq, action->dev_id, regs); + action = action->next; + } while (action); + if (do_random & SA_SAMPLE_RANDOM) + add_interrupt_randomness(irq); + __cli(); + unmask_irq (irq); + +out: + irq_exit(cpu, irq); +} + +/* + * do_IRQ handles IRQ's that have been installed without the + * SA_INTERRUPT flag: it uses the full signal-handling return + * and runs with other interrupts enabled. All relatively slow + * IRQ's should use this format: notably the keyboard/timer + * routines. + */ +asmlinkage void do_IRQ(int irq, struct pt_regs * regs) +{ + struct irqaction *action; + int do_random, cpu; + + cpu = smp_processor_id(); + irq_enter(cpu, irq); + kstat.irqs[cpu][irq]++; + + action = *(irq + irq_action); + if (action) { + if (!(action->flags & SA_INTERRUPT)) + __sti(); + action = *(irq + irq_action); + do_random = 0; + do { + do_random |= action->flags; + action->handler(irq, action->dev_id, regs); + action = action->next; + } while (action); + if (do_random & SA_SAMPLE_RANDOM) + add_interrupt_randomness(irq); + __cli(); + } + irq_exit(cpu, irq); + + if (softirq_active(cpu)&softirq_mask(cpu)) + do_softirq(); + + /* unmasking and bottom half handling is done magically for us. */ +} + +int i8259_setup_irq(int irq, struct irqaction * new) +{ + int shared = 0; + struct irqaction *old, **p; + unsigned long flags; + + p = irq_action + irq; + if ((old = *p) != NULL) { + /* Can't share interrupts unless both agree to */ + if (!(old->flags & new->flags & SA_SHIRQ)) + return -EBUSY; + + /* Can't share interrupts unless both are same type */ + if ((old->flags ^ new->flags) & SA_INTERRUPT) + return -EBUSY; + + /* add new interrupt at end of irq queue */ + do { + p = &old->next; + old = *p; + } while (old); + shared = 1; + } + + if (new->flags & SA_SAMPLE_RANDOM) + rand_initialize_irq(irq); + + save_and_cli(flags); + *p = new; + + if (!shared) { + if (is_i8259_irq(irq)) + unmask_irq(irq); +#if (defined(CONFIG_DDB5074) || defined(CONFIG_DDB5476)) + else + nile4_enable_irq(irq_to_nile4(irq)); +#endif + } + restore_flags(flags); + return 0; +} + +/* + * Request_interrupt and free_interrupt ``sort of'' handle interrupts of + * non i8259 devices. They will have to be replaced by architecture + * specific variants. For now we still use this as broken as it is because + * it used to work ... + */ +int request_irq(unsigned int irq, + void (*handler)(int, void *, struct pt_regs *), + unsigned long irqflags, const char * devname, void *dev_id) +{ + int retval; + struct irqaction * action; + + if (irq >= 32) + return -EINVAL; + if (!handler) + return -EINVAL; + + action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL); + if (!action) + return -ENOMEM; + + action->handler = handler; + action->flags = irqflags; + action->mask = 0; + action->name = devname; + action->next = NULL; + action->dev_id = dev_id; + + retval = i8259_setup_irq(irq, action); + + if (retval) + kfree(action); + return retval; +} + +void free_irq(unsigned int irq, void *dev_id) +{ + struct irqaction * action, **p; + unsigned long flags; + + if (irq > 31) { + printk("Trying to free IRQ%d\n",irq); + return; + } + for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) { + if (action->dev_id != dev_id) + continue; + + /* Found it - now free it */ + save_and_cli(flags); + *p = action->next; + if (!irq[irq_action]) + mask_irq(irq); + restore_flags(flags); + kfree(action); + return; + } + printk("Trying to free free IRQ%d\n",irq); +} + +unsigned long probe_irq_on (void) +{ + unsigned int i, irqs = 0; + unsigned long delay; + + /* first, enable any unassigned (E)ISA irqs */ + for (i = 15; i > 0; i--) { + if (!irq_action[i]) { + i8259_enable_irq(i); + irqs |= (1 << i); + } + } + + /* wait for spurious interrupts to mask themselves out again */ + for (delay = jiffies + HZ/10; time_before(jiffies, delay); ) + /* about 100ms delay */; + + /* now filter out any obviously spurious interrupts */ + return irqs & ~cached_irq_mask; +} + +int probe_irq_off (unsigned long irqs) +{ + unsigned int i; + +#ifdef DEBUG + printk("probe_irq_off: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask); +#endif + irqs &= cached_irq_mask; + if (!irqs) + return 0; + i = ffz(~irqs); + if (irqs != (irqs & (1 << i))) + i = -i; + return i; +} + +void __init i8259_init(void) +{ + /* Init master interrupt controller */ + outb(0x11, 0x20); /* Start init sequence */ + outb(0x00, 0x21); /* Vector base */ + outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */ + outb(0x01, 0x21); /* Select 8086 mode */ + outb(0xff, 0x21); /* Mask all */ + + /* Init slave interrupt controller */ + outb(0x11, 0xa0); /* Start init sequence */ + outb(0x08, 0xa1); /* Vector base */ + outb(0x02, 0xa1); /* edge triggered, Cascade (slave) on IRQ2 */ + outb(0x01, 0xa1); /* Select 8086 mode */ + outb(0xff, 0xa1); /* Mask all */ + + outb(cached_A1, 0xa1); + outb(cached_21, 0x21); +} + +void __init init_IRQ(void) +{ + /* i8259_init(); */ + irq_setup(); +} diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/old-time.c linux/arch/mips/kernel/old-time.c --- v2.4.5/linux/arch/mips/kernel/old-time.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/kernel/old-time.c Mon Jul 2 13:56:40 2001 @@ -0,0 +1,519 @@ +/* + * Copyright (C) 1991, 1992, 1995 Linus Torvalds + * Copyright (C) 1996 - 2000 Ralf Baechle + * + * This file contains the time handling details for PC-style clocks as + * found in some MIPS systems. + */ +/************************************************************************** + * 9 Nov, 2000. + * Changed init_cycle_counter() routine, use the mips_cpu structure. + * + * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + *************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +extern volatile unsigned long wall_jiffies; +unsigned long r4k_interval; +extern rwlock_t xtime_lock; + +/* + * Change this if you have some constant time drift + */ +/* This is the value for the PC-style PICs. */ +/* #define USECS_PER_JIFFY (1000020/HZ) */ + +/* This is for machines which generate the exact clock. */ +#define USECS_PER_JIFFY (1000000/HZ) + +/* Cycle counter value at the previous timer interrupt.. */ + +static unsigned int timerhi, timerlo; + +/* + * On MIPS only R4000 and better have a cycle counter. + * + * FIXME: Does playing with the RP bit in c0_status interfere with this code? + */ +static unsigned long do_fast_gettimeoffset(void) +{ + u32 count; + unsigned long res, tmp; + + /* Last jiffy when do_fast_gettimeoffset() was called. */ + static unsigned long last_jiffies; + unsigned long quotient; + + /* + * Cached "1/(clocks per usec)*2^32" value. + * It has to be recalculated once each jiffy. + */ + static unsigned long cached_quotient; + + tmp = jiffies; + + quotient = cached_quotient; + + if (tmp && last_jiffies != tmp) { + last_jiffies = tmp; + __asm__(".set\tnoreorder\n\t" + ".set\tnoat\n\t" + ".set\tmips3\n\t" + "lwu\t%0,%2\n\t" + "dsll32\t$1,%1,0\n\t" + "or\t$1,$1,%0\n\t" + "ddivu\t$0,$1,%3\n\t" + "mflo\t$1\n\t" + "dsll32\t%0,%4,0\n\t" + "nop\n\t" + "ddivu\t$0,%0,$1\n\t" + "mflo\t%0\n\t" + ".set\tmips0\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=&r" (quotient) + :"r" (timerhi), + "m" (timerlo), + "r" (tmp), + "r" (USECS_PER_JIFFY) + :"$1"); + cached_quotient = quotient; + } + + /* Get last timer tick in absolute kernel time */ + count = read_32bit_cp0_register(CP0_COUNT); + + /* .. relative to previous jiffy (32 bits is enough) */ + count -= timerlo; + + __asm__("multu\t%1,%2\n\t" + "mfhi\t%0" + :"=r" (res) + :"r" (count), + "r" (quotient)); + + /* + * Due to possible jiffies inconsistencies, we need to check + * the result so that we'll get a timer that is monotonic. + */ + if (res >= USECS_PER_JIFFY) + res = USECS_PER_JIFFY-1; + + return res; +} + +/* This function must be called with interrupts disabled + * It was inspired by Steve McCanne's microtime-i386 for BSD. -- jrs + * + * However, the pc-audio speaker driver changes the divisor so that + * it gets interrupted rather more often - it loads 64 into the + * counter rather than 11932! This has an adverse impact on + * do_gettimeoffset() -- it stops working! What is also not + * good is that the interval that our timer function gets called + * is no longer 10.0002 ms, but 9.9767 ms. To get around this + * would require using a different timing source. Maybe someone + * could use the RTC - I know that this can interrupt at frequencies + * ranging from 8192Hz to 2Hz. If I had the energy, I'd somehow fix + * it so that at startup, the timer code in sched.c would select + * using either the RTC or the 8253 timer. The decision would be + * based on whether there was any other device around that needed + * to trample on the 8253. I'd set up the RTC to interrupt at 1024 Hz, + * and then do some jiggery to have a version of do_timer that + * advanced the clock by 1/1024 s. Every time that reached over 1/100 + * of a second, then do all the old code. If the time was kept correct + * then do_gettimeoffset could just return 0 - there is no low order + * divider that can be accessed. + * + * Ideally, you would be able to use the RTC for the speaker driver, + * but it appears that the speaker driver really needs interrupt more + * often than every 120 us or so. + * + * Anyway, this needs more thought.... pjsg (1993-08-28) + * + * If you are really that interested, you should be reading + * comp.protocols.time.ntp! + */ + +#define TICK_SIZE tick + +static unsigned long do_slow_gettimeoffset(void) +{ + int count; + + static int count_p = LATCH; /* for the first call after boot */ + static unsigned long jiffies_p; + + /* + * cache volatile jiffies temporarily; we have IRQs turned off. + */ + unsigned long jiffies_t; + + /* timer count may underflow right here */ + outb_p(0x00, 0x43); /* latch the count ASAP */ + + count = inb_p(0x40); /* read the latched count */ + + /* + * We do this guaranteed double memory access instead of a _p + * postfix in the previous port access. Wheee, hackady hack + */ + jiffies_t = jiffies; + + count |= inb_p(0x40) << 8; + + /* + * avoiding timer inconsistencies (they are rare, but they happen)... + * there are two kinds of problems that must be avoided here: + * 1. the timer counter underflows + * 2. hardware problem with the timer, not giving us continuous time, + * the counter does small "jumps" upwards on some Pentium systems, + * (see c't 95/10 page 335 for Neptun bug.) + */ + + if( jiffies_t == jiffies_p ) { + if( count > count_p ) { + /* the nutcase */ + + outb_p(0x0A, 0x20); + + /* assumption about timer being IRQ1 */ + if (inb(0x20) & 0x01) { + /* + * We cannot detect lost timer interrupts ... + * well, that's why we call them lost, don't we? :) + * [hmm, on the Pentium and Alpha we can ... sort of] + */ + count -= LATCH; + } else { + printk("do_slow_gettimeoffset(): hardware timer problem?\n"); + } + } + } else + jiffies_p = jiffies_t; + + count_p = count; + + count = ((LATCH-1) - count) * TICK_SIZE; + count = (count + LATCH/2) / LATCH; + + return count; +} + +static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset; + +/* + * This version of gettimeofday has near microsecond resolution. + */ +void do_gettimeofday(struct timeval *tv) +{ + unsigned long flags; + + read_lock_irqsave (&xtime_lock, flags); + *tv = xtime; + tv->tv_usec += do_gettimeoffset(); + + /* + * xtime is atomically updated in timer_bh. jiffies - wall_jiffies + * is nonzero if the timer bottom half hasnt executed yet. + */ + if (jiffies - wall_jiffies) + tv->tv_usec += USECS_PER_JIFFY; + + read_unlock_irqrestore (&xtime_lock, flags); + + if (tv->tv_usec >= 1000000) { + tv->tv_usec -= 1000000; + tv->tv_sec++; + } +} + +void do_settimeofday(struct timeval *tv) +{ + write_lock_irq (&xtime_lock); + + /* This is revolting. We need to set the xtime.tv_usec + * correctly. However, the value in this location is + * is value at the last tick. + * Discover what correction gettimeofday + * would have done, and then undo it! + */ + tv->tv_usec -= do_gettimeoffset(); + + if (tv->tv_usec < 0) { + tv->tv_usec += 1000000; + tv->tv_sec--; + } + + xtime = *tv; + time_adjust = 0; /* stop active adjtime() */ + time_status |= STA_UNSYNC; + time_maxerror = NTP_PHASE_LIMIT; + time_esterror = NTP_PHASE_LIMIT; + + write_unlock_irq (&xtime_lock); +} + +/* + * In order to set the CMOS clock precisely, set_rtc_mmss has to be + * called 500 ms after the second nowtime has started, because when + * nowtime is written into the registers of the CMOS clock, it will + * jump to the next second precisely 500 ms later. Check the Motorola + * MC146818A or Dallas DS12887 data sheet for details. + * + * BUG: This routine does not handle hour overflow properly; it just + * sets the minutes. Usually you won't notice until after reboot! + */ +static int set_rtc_mmss(unsigned long nowtime) +{ + int retval = 0; + int real_seconds, real_minutes, cmos_minutes; + unsigned char save_control, save_freq_select; + + save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ + CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); + + save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ + CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); + + cmos_minutes = CMOS_READ(RTC_MINUTES); + if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) + BCD_TO_BIN(cmos_minutes); + + /* + * since we're only adjusting minutes and seconds, + * don't interfere with hour overflow. This avoids + * messing with unknown time zones but requires your + * RTC not to be off by more than 15 minutes + */ + real_seconds = nowtime % 60; + real_minutes = nowtime / 60; + if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) + real_minutes += 30; /* correct for half hour time zone */ + real_minutes %= 60; + + if (abs(real_minutes - cmos_minutes) < 30) { + if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { + BIN_TO_BCD(real_seconds); + BIN_TO_BCD(real_minutes); + } + CMOS_WRITE(real_seconds,RTC_SECONDS); + CMOS_WRITE(real_minutes,RTC_MINUTES); + } else { + printk(KERN_WARNING + "set_rtc_mmss: can't update from %d to %d\n", + cmos_minutes, real_minutes); + retval = -1; + } + + /* The following flags have to be released exactly in this order, + * otherwise the DS12887 (popular MC146818A clone with integrated + * battery and quartz) will not reset the oscillator and will not + * update precisely 500 ms later. You won't find this mentioned in + * the Dallas Semiconductor data sheets, but who believes data + * sheets anyway ... -- Markus Kuhn + */ + CMOS_WRITE(save_control, RTC_CONTROL); + CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); + + return retval; +} + +/* last time the cmos clock got updated */ +static long last_rtc_update; + +/* + * timer_interrupt() needs to keep up the real-time clock, + * as well as call the "do_timer()" routine every clocktick + */ +static void inline +timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) +{ +#ifdef CONFIG_DDB5074 + static unsigned cnt, period, dist; + + if (cnt == 0 || cnt == dist) + ddb5074_led_d2(1); + else if (cnt == 7 || cnt == dist+7) + ddb5074_led_d2(0); + + if (++cnt > period) { + cnt = 0; + /* The hyperbolic function below modifies the heartbeat period + * length in dependency of the current (5min) load. It goes + * through the points f(0)=126, f(1)=86, f(5)=51, + * f(inf)->30. */ + period = ((672<pid) { + extern int _stext; + unsigned long pc = regs->cp0_epc; + + pc -= (unsigned long) &_stext; + pc >>= prof_shift; + /* + * Dont ignore out-of-bounds pc values silently, + * put them into the last histogram slot, so if + * present, they will show up as a sharp peak. + */ + if (pc > prof_len-1) + pc = prof_len-1; + atomic_inc((atomic_t *)&prof_buffer[pc]); + } + } + do_timer(regs); + + /* + * If we have an externally synchronized Linux clock, then update + * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be + * called as close as possible to 500 ms before the new second starts. + */ + read_lock (&xtime_lock); + if ((time_status & STA_UNSYNC) == 0 && + xtime.tv_sec > last_rtc_update + 660 && + xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 && + xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) { + if (set_rtc_mmss(xtime.tv_sec) == 0) + last_rtc_update = xtime.tv_sec; + else + last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ + } + /* As we return to user mode fire off the other CPU schedulers.. this is + basically because we don't yet share IRQ's around. This message is + rigged to be safe on the 386 - basically it's a hack, so don't look + closely for now.. */ + /*smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0); */ + read_unlock (&xtime_lock); +} + +static inline void +r4k_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) +{ + unsigned int count; + + /* + * The cycle counter is only 32 bit which is good for about + * a minute at current count rates of upto 150MHz or so. + */ + count = read_32bit_cp0_register(CP0_COUNT); + timerhi += (count < timerlo); /* Wrap around */ + timerlo = count; + +#ifdef CONFIG_SGI_IP22 + /* Since we don't get anything but r4k timer interrupts, we need to + * set this up so that we'll get one next time. Fortunately since we + * have timerhi/timerlo, we don't care so much if we miss one. So + * we need only ask for the next in r4k_interval counts. On other + * archs we have a real timer, so we don't want this. + */ + write_32bit_cp0_register (CP0_COMPARE, + (unsigned long) (count + r4k_interval)); + kstat.irqs[0][irq]++; +#endif + + timer_interrupt(irq, dev_id, regs); + + if (!jiffies) + { + /* + * If jiffies has overflowed in this timer_interrupt we must + * update the timer[hi]/[lo] to make do_fast_gettimeoffset() + * quotient calc still valid. -arca + */ + timerhi = timerlo = 0; + } +} + +void indy_r4k_timer_interrupt (struct pt_regs *regs) +{ + static const int INDY_R4K_TIMER_IRQ = 7; + r4k_timer_interrupt (INDY_R4K_TIMER_IRQ, NULL, regs); +} + +struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, 0, + "timer", NULL, NULL}; + + +void (*board_time_init)(struct irqaction *irq); + +void __init time_init(void) +{ + unsigned int epoch = 0, year, mon, day, hour, min, sec; + int i; + + /* The Linux interpretation of the CMOS clock register contents: + * When the Update-In-Progress (UIP) flag goes from 1 to 0, the + * RTC registers show the second which has precisely just started. + * Let's hope other operating systems interpret the RTC the same way. + */ + /* read RTC exactly on falling edge of update flag */ + for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */ + if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) + break; + for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */ + if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) + break; + do { /* Isn't this overkill ? UIP above should guarantee consistency */ + sec = CMOS_READ(RTC_SECONDS); + min = CMOS_READ(RTC_MINUTES); + hour = CMOS_READ(RTC_HOURS); + day = CMOS_READ(RTC_DAY_OF_MONTH); + mon = CMOS_READ(RTC_MONTH); + year = CMOS_READ(RTC_YEAR); + } while (sec != CMOS_READ(RTC_SECONDS)); + if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) + { + BCD_TO_BIN(sec); + BCD_TO_BIN(min); + BCD_TO_BIN(hour); + BCD_TO_BIN(day); + BCD_TO_BIN(mon); + BCD_TO_BIN(year); + } + + /* Attempt to guess the epoch. This is the same heuristic as in rtc.c so + no stupid things will happen to timekeeping. Who knows, maybe Ultrix + also uses 1952 as epoch ... */ + if (year > 10 && year < 44) { + epoch = 1980; + } else if (year < 96) { + epoch = 1952; + } + year += epoch; + + write_lock_irq (&xtime_lock); + xtime.tv_sec = mktime(year, mon, day, hour, min, sec); + xtime.tv_usec = 0; + write_unlock_irq (&xtime_lock); + + if (mips_cpu.options & MIPS_CPU_COUNTER) { + write_32bit_cp0_register(CP0_COUNT, 0); + do_gettimeoffset = do_fast_gettimeoffset; + irq0.handler = r4k_timer_interrupt; + } + + board_time_init(&irq0); +} diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/pci-dma.c linux/arch/mips/kernel/pci-dma.c --- v2.4.5/linux/arch/mips/kernel/pci-dma.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/kernel/pci-dma.c Mon Jul 2 13:56:40 2001 @@ -0,0 +1,41 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2000 Ani Joshi + * Copyright (C) 2000 Ralf Baechle + * swiped from i386, and cloned for MIPS by Geert, polished by Ralf. + */ +#include +#include +#include +#include + +#include + +void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, + dma_addr_t * dma_handle) +{ + void *ret; + int gfp = GFP_ATOMIC; + + if (hwdev == NULL || hwdev->dma_mask != 0xffffffff) + gfp |= GFP_DMA; + ret = (void *) __get_free_pages(gfp, get_order(size)); + + if (ret != NULL) { + memset(ret, 0, size); + dma_cache_wback_inv((unsigned long) ret, size); + *dma_handle = virt_to_bus(ret); + ret = KSEG1ADDR(ret); + } + + return ret; +} + +void pci_free_consistent(struct pci_dev *hwdev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + free_pages((unsigned long) KSEG0ADDR(vaddr), get_order(size)); +} diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/proc.c linux/arch/mips/kernel/proc.c --- v2.4.5/linux/arch/mips/kernel/proc.c Sat May 13 08:29:14 2000 +++ linux/arch/mips/kernel/proc.c Mon Jul 2 13:56:40 2001 @@ -7,12 +7,16 @@ #include #include #include +#include #include #include #include unsigned long unaligned_instructions; unsigned int vced_count, vcei_count; +#if !defined(CONFIG_CPU_HAS_LLSC) +unsigned long ll_ops, sc_ops; +#endif /* * BUFFER is PAGE_SIZE bytes long. @@ -35,32 +39,37 @@ const char *mach_cobalt_names[] = GROUP_COBALT_NAMES; const char *mach_nec_ddb_names[] = GROUP_NEC_DDB_NAMES; const char *mach_baget_names[] = GROUP_BAGET_NAMES; + const char *mach_cosine_names[] = GROUP_COSINE_NAMES; + const char *mach_galileo_names[] = GROUP_GALILEO_NAMES; + const char *mach_momenco_names[] = GROUP_MOMENCO_NAMES; + const char *mach_ite_names[] = GROUP_ITE_NAMES; + const char *mach_philips_names[] = GROUP_PHILIPS_NAMES; + const char *mach_globespan_names[] = GROUP_GLOBESPAN_NAMES; + const char *mach_sibyte_names[] = GROUP_SIBYTE_NAMES; + const char *mach_toshiba_names[] = GROUP_TOSHIBA_NAMES; + const char *mach_alchemy_names[] = GROUP_ALCHEMY_NAMES; const char **mach_group_to_name[] = { mach_unknown_names, - mach_jazz_names, - mach_dec_names, - mach_arc_names, - mach_sni_rm_names, - mach_acn_names, - mach_sgi_names, - mach_cobalt_names, - mach_nec_ddb_names, - mach_baget_names }; + mach_jazz_names, mach_dec_names, mach_arc_names, + mach_sni_rm_names, mach_acn_names, mach_sgi_names, + mach_cobalt_names, mach_nec_ddb_names, mach_baget_names, + mach_cosine_names, mach_galileo_names, mach_momenco_names, + mach_ite_names, mach_philips_names, mach_globespan_names, + mach_sibyte_names, mach_toshiba_names, mach_alchemy_names}; unsigned int version = read_32bit_cp0_register(CP0_PRID); int len; len = sprintf(buffer, "cpu\t\t\t: MIPS\n"); len += sprintf(buffer + len, "cpu model\t\t: %s V%d.%d\n", - cpu_name[mips_cputype <= CPU_LAST ? - mips_cputype : - CPU_UNKNOWN], - (version >> 4) & 0x0f, - version & 0x0f); + cpu_name[mips_cpu.cputype <= CPU_LAST ? + mips_cpu.cputype : CPU_UNKNOWN], + (version >> 4) & 0x0f, version & 0x0f); len += sprintf(buffer + len, "system type\t\t: %s %s\n", mach_group_names[mips_machgroup], mach_group_to_name[mips_machgroup][mips_machtype]); len += sprintf(buffer + len, "BogoMIPS\t\t: %lu.%02lu\n", - (loops_per_sec + 2500) / 500000, - ((loops_per_sec + 2500) / 5000) % 100); + loops_per_jiffy/(500000/HZ), + (loops_per_jiffy/(5000/HZ)) % 100); + #if defined (__MIPSEB__) len += sprintf(buffer + len, "byteorder\t\t: big endian\n"); #endif @@ -72,17 +81,23 @@ len += sprintf(buffer + len, "wait instruction\t: %s\n", cpu_wait ? "yes" : "no"); len += sprintf(buffer + len, "microsecond timers\t: %s\n", - cyclecounter_available ? "yes" : "no"); + (mips_cpu.options & MIPS_CPU_COUNTER) ? "yes" : "no"); len += sprintf(buffer + len, "extra interrupt vector\t: %s\n", dedicated_iv_available ? "yes" : "no"); len += sprintf(buffer + len, "hardware watchpoint\t: %s\n", watch_available ? "yes" : "no"); sprintf(fmt, "VCE%%c exceptions\t\t: %s\n", - vce_available ? "%d" : "not available"); + (mips_cpu.options & MIPS_CPU_VCE) ? "%d" : "not available"); len += sprintf(buffer + len, fmt, 'D', vced_count); len += sprintf(buffer + len, fmt, 'I', vcei_count); +#if !defined(CONFIG_CPU_HAS_LLSC) + len += sprintf(buffer + len, "ll emulations\t\t: %lu\n", + ll_ops); + len += sprintf(buffer + len, "sc emulations\t\t: %lu\n", + sc_ops); +#endif return len; } diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/process.c linux/arch/mips/kernel/process.c --- v2.4.5/linux/arch/mips/kernel/process.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/kernel/process.c Mon Jul 2 13:56:40 2001 @@ -162,21 +162,21 @@ long retval; __asm__ __volatile__( - ".set\tnoreorder\n\t" - "move\t$6,$sp\n\t" - "move\t$4,%5\n\t" - "li\t$2,%1\n\t" - "syscall\n\t" - "beq\t$6,$sp,1f\n\t" - "subu\t$sp,32\n\t" /* delay slot */ - "jalr\t%4\n\t" - "move\t$4,%3\n\t" /* delay slot */ - "move\t$4,$2\n\t" - "li\t$2,%2\n\t" - "syscall\n" - "1:\taddiu\t$sp,32\n\t" - "move\t%0,$2\n\t" - ".set\treorder" + ".set noreorder \n" + " move $6,$sp \n" + " move $4,%5 \n" + " li $2,%1 \n" + " syscall \n" + " beq $6,$sp,1f \n" + " subu $sp,32 \n" /* delay slot */ + " jalr %4 \n" + " move $4,%3 \n" /* delay slot */ + " move $4,$2 \n" + " li $2,%2 \n" + " syscall \n" + "1: addiu $sp,32 \n" + " move %0,$2 \n" + ".set reorder" :"=r" (retval) :"i" (__NR_clone), "i" (__NR_exit), "r" (arg), "r" (fn), @@ -199,27 +199,47 @@ #define first_sched ((unsigned long) scheduling_functions_start_here) #define last_sched ((unsigned long) scheduling_functions_end_here) +/* get_wchan - a maintenance nightmare ... */ unsigned long get_wchan(struct task_struct *p) { - unsigned long schedule_frame; - unsigned long pc; + unsigned long frame, pc; if (!p || p == current || p->state == TASK_RUNNING) return 0; pc = thread_saved_pc(&p->thread); - if (pc == (unsigned long) interruptible_sleep_on - || pc == (unsigned long) sleep_on) { - schedule_frame = ((unsigned long *)p->thread.reg30)[9]; - return ((unsigned long *)schedule_frame)[15]; - } - if (pc == (unsigned long) interruptible_sleep_on_timeout - || pc == (unsigned long) sleep_on_timeout) { - schedule_frame = ((unsigned long *)p->thread.reg30)[9]; - return ((unsigned long *)schedule_frame)[16]; + if (pc < first_sched || pc >= last_sched) { + return pc; } + + if (pc >= (unsigned long) sleep_on_timeout) + goto schedule_timeout_caller; + if (pc >= (unsigned long) sleep_on) + goto schedule_caller; + if (pc >= (unsigned long) interruptible_sleep_on_timeout) + goto schedule_timeout_caller; + if (pc >= (unsigned long)interruptible_sleep_on) + goto schedule_caller; + goto schedule_timeout_caller; + +schedule_caller: + frame = ((unsigned long *)p->thread.reg30)[9]; + pc = ((unsigned long *)frame)[11]; + return pc; + +schedule_timeout_caller: + /* Must be schedule_timeout ... */ + pc = ((unsigned long *)p->thread.reg30)[10]; + frame = ((unsigned long *)p->thread.reg30)[9]; + + /* The schedule_timeout frame ... */ + pc = ((unsigned long *)frame)[14]; + frame = ((unsigned long *)frame)[13]; + if (pc >= first_sched && pc < last_sched) { - printk(KERN_DEBUG "Bug in %s\n", __FUNCTION__); + /* schedule_timeout called by interruptible_sleep_on_timeout */ + pc = ((unsigned long *)frame)[11]; + frame = ((unsigned long *)frame)[10]; } return pc; diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/ptrace.c linux/arch/mips/kernel/ptrace.c --- v2.4.5/linux/arch/mips/kernel/ptrace.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/kernel/ptrace.c Mon Jul 2 13:56:40 2001 @@ -207,7 +207,7 @@ case PTRACE_POKEUSR: { struct pt_regs *regs; - int res = 0; + res = 0; regs = (struct pt_regs *) ((unsigned long) child + KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs)); @@ -289,7 +289,7 @@ */ case PTRACE_KILL: res = 0; - if (child->state != TASK_ZOMBIE) /* already dead */ + if (child->state == TASK_ZOMBIE) /* already dead */ break; child->exit_code = SIGKILL; wake_up_process(child); @@ -299,7 +299,7 @@ res = -EIO; if ((unsigned long) data > _NSIG) break; - child->ptrace &= ~(PT_PTRACED|PT_TRACESYS); + child->ptrace = 0; child->exit_code = data; write_lock_irq(&tasklist_lock); REMOVE_LINKS(child); @@ -310,6 +310,14 @@ res = 0; break; + case PTRACE_SETOPTIONS: + if (data & PTRACE_O_TRACESYSGOOD) + child->ptrace |= PT_TRACESYSGOOD; + else + child->ptrace &= ~PT_TRACESYSGOOD; + res = 0; + break; + default: res = -EIO; goto out; @@ -326,7 +334,10 @@ if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) != (PT_PTRACED|PT_TRACESYS)) return; - current->exit_code = SIGTRAP; + /* The 0x80 provides a way for the tracing parent to distinguish + between a syscall stop and SIGTRAP delivery */ + current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) + ? 0x80 : 0); current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/r2300_fpu.S linux/arch/mips/kernel/r2300_fpu.S --- v2.4.5/linux/arch/mips/kernel/r2300_fpu.S Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/kernel/r2300_fpu.S Mon Jul 2 13:56:40 2001 @@ -117,6 +117,7 @@ jr ra ctc1 t0,fcr31 END(_restore_fp_context) + .set reorder .type fault@function .ent fault diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/r2300_switch.S linux/arch/mips/kernel/r2300_switch.S --- v2.4.5/linux/arch/mips/kernel/r2300_switch.S Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/kernel/r2300_switch.S Mon Jul 2 13:56:40 2001 @@ -34,6 +34,9 @@ * task_struct *next) */ LEAF(resume) +#ifndef CONFIG_CPU_HAS_LLSC + sw zero, ll_bit +#endif mfc0 t1, CP0_STATUS sw t1, THREAD_STATUS(a0) CPU_SAVE_NONSCRATCH(a0) diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/r4k_fpu.S linux/arch/mips/kernel/r4k_fpu.S --- v2.4.5/linux/arch/mips/kernel/r4k_fpu.S Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/kernel/r4k_fpu.S Mon Jul 2 13:56:40 2001 @@ -93,6 +93,7 @@ jr ra ctc1 t0,fcr31 END(_restore_fp_context) + .set reorder .type fault@function .ent fault diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/r4k_misc.S linux/arch/mips/kernel/r4k_misc.S --- v2.4.5/linux/arch/mips/kernel/r4k_misc.S Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/kernel/r4k_misc.S Mon Jul 2 13:56:40 2001 @@ -35,10 +35,25 @@ * in register PTE, a ptr into the table in which * the pte belongs is in PTR. */ + +#ifdef CONFIG_SMP +#define GET_PGD(scratch, ptr) \ + mfc0 ptr, CP0_CONTEXT; \ + la scratch, current_pgd;\ + srl ptr, 23; \ + sll ptr, 2; \ + addu ptr, scratch, ptr; \ + lw ptr, (ptr); +#else +#define GET_PGD(scratch, ptr) \ + lw ptr, current_pgd; +#endif + + #define LOAD_PTE(pte, ptr) \ + GET_PGD(pte, ptr) \ mfc0 pte, CP0_BADVADDR; \ srl pte, pte, 22; \ - lw ptr, current_pgd; \ sll pte, pte, 2; \ addu ptr, ptr, pte; \ mfc0 pte, CP0_BADVADDR; \ diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/r4k_switch.S linux/arch/mips/kernel/r4k_switch.S --- v2.4.5/linux/arch/mips/kernel/r4k_switch.S Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/kernel/r4k_switch.S Mon Jul 2 13:56:40 2001 @@ -1,5 +1,4 @@ -/* $Id: r4k_switch.S,v 1.9 1999/08/18 23:37:44 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -38,6 +37,9 @@ .set noreorder .align 5 LEAF(resume) +#ifndef CONFIG_CPU_HAS_LLSC + sw zero, ll_bit +#endif mfc0 t1, CP0_STATUS sw t1, THREAD_STATUS(a0) CPU_SAVE_NONSCRATCH(a0) @@ -50,7 +52,16 @@ move $28, a1 CPU_RESTORE_NONSCRATCH($28) addiu t0, $28, KERNEL_STACK_SIZE-32 +#ifdef CONFIG_SMP + mfc0 a3, CP0_CONTEXT + la t1, kernelsp + srl a3, 23 + sll a3, 2 + addu t1, a3, t1 + sw t0, (t1) +#else sw t0, kernelsp +#endif mfc0 t1, CP0_STATUS /* Do we really need this? */ li a3, 0xff00 and t1, a3 diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/scall_o32.S linux/arch/mips/kernel/scall_o32.S --- v2.4.5/linux/arch/mips/kernel/scall_o32.S Fri Aug 4 16:15:37 2000 +++ linux/arch/mips/kernel/scall_o32.S Mon Jul 2 13:56:40 2001 @@ -65,8 +65,14 @@ 1: sw v0, PT_R2(sp) # result EXPORT(o32_ret_from_sys_call) - lw t0, irq_stat # softirq_active - lw t1, irq_stat+4 # softirq_mask. unused delay slot + la t1, irq_stat # softirq_active +#ifdef CONFIG_SMP + lw t0, TASK_PROCESSOR($28) + sll t0, t0, 5 + addu t1, t0 +#endif + lw t0, 0(t1) # softirq_active + lw t1, 4(t1) # softirq_mask. unused delay slot and t0, t1 bnez t0, o32_handle_softirq diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/setup.c linux/arch/mips/kernel/setup.c --- v2.4.5/linux/arch/mips/kernel/setup.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/kernel/setup.c Mon Jul 2 13:56:40 2001 @@ -26,13 +26,9 @@ #include #include #include -#ifdef CONFIG_BLK_DEV_RAM #include -#endif #include -#ifdef CONFIG_RTC #include -#endif #include #include @@ -45,7 +41,8 @@ #include #endif -struct mips_cpuinfo boot_cpu_data = { NULL, NULL, 0 }; + +struct mips_cpuinfo boot_cpu_data = { 0, NULL, NULL, 0 }; /* * Not all of the MIPS CPUs have the "wait" instruction available. Moreover, @@ -57,11 +54,6 @@ void (*cpu_wait)(void) = NULL; /* - * Do we have a cyclecounter available? - */ -char cyclecounter_available; - -/* * There are several bus types available for MIPS machines. "RISC PC" * type machines have ISA, EISA, VLB or PCI available, DECstations * have Turbochannel or Q-Bus, SGI has GIO, there are lots of VME @@ -72,16 +64,16 @@ struct screen_info screen_info; -#ifdef CONFIG_BLK_DEV_FD extern struct fd_ops no_fd_ops; struct fd_ops *fd_ops; -#endif #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) extern struct ide_ops no_ide_ops; struct ide_ops *ide_ops; #endif +extern void * __rd_start, * __rd_end; + extern struct rtc_ops no_rtc_ops; struct rtc_ops *rtc_ops; @@ -95,23 +87,17 @@ * * These are initialized so they are in the .data section */ -unsigned long mips_memory_upper = KSEG0; /* this is set by kernel_entry() */ -unsigned long mips_cputype = CPU_UNKNOWN; unsigned long mips_machtype = MACH_UNKNOWN; unsigned long mips_machgroup = MACH_GROUP_UNKNOWN; +struct boot_mem_map boot_mem_map; + unsigned char aux_device_present; -extern int _end; +extern char _ftext, _etext, _fdata, _edata, _end; -static char command_line[CL_SIZE] = { 0, }; - char saved_command_line[CL_SIZE]; -extern char arcs_cmdline[CL_SIZE]; - -/* - * The board specific setup routine sets irq_setup to point to a board - * specific setup routine. - */ -void (*irq_setup)(void); +static char command_line[COMMAND_LINE_SIZE]; + char saved_command_line[COMMAND_LINE_SIZE]; +extern char arcs_cmdline[COMMAND_LINE_SIZE]; /* * mips_io_port_base is the begin of the address space to which x86 style @@ -129,7 +115,10 @@ extern void SetUpBootInfo(void); extern void loadmmu(void); extern asmlinkage void start_kernel(void); -extern int prom_init(int, char **, char **, int *); +extern void prom_init(int, char **, char **, int *); + +static struct resource code_resource = { "Kernel code" }; +static struct resource data_resource = { "Kernel data" }; /* * Probe whether cpu has config register by trying to play with @@ -143,9 +132,9 @@ unsigned long size1, size2; unsigned long cfg = read_32bit_cp0_register(CP0_CONF); - size1 = r3k_cache_size(ST0_DE); + size1 = r3k_cache_size(ST0_ISC); write_32bit_cp0_register(CP0_CONF, cfg^CONF_AC); - size2 = r3k_cache_size(ST0_DE); + size2 = r3k_cache_size(ST0_ISC); write_32bit_cp0_register(CP0_CONF, cfg); return size1 != size2; #else @@ -165,152 +154,230 @@ static inline void cpu_probe(void) { + +#ifdef CONFIG_CPU_MIPS32 unsigned long config1; +#endif mips_cpu.processor_id = read_32bit_cp0_register(CP0_PRID); - switch (mips_cpu.processor_id & 0xff00) { - case PRID_IMP_R2000: - mips_cpu.cputype = CPU_R2000; - mips_cpu.isa_level = MIPS_CPU_ISA_I; - mips_cpu.options = MIPS_CPU_TLB; - mips_cpu.tlbsize = 64; - break; - case PRID_IMP_R3000: - if ((mips_cpu.processor_id & 0xff) == PRID_REV_R3000A) - if (cpu_has_confreg()) - mips_cpu.cputype = CPU_R3081E; + switch (mips_cpu.processor_id & 0xff0000) { + case PRID_COMP_LEGACY: + switch (mips_cpu.processor_id & 0xff00) { + case PRID_IMP_R2000: + mips_cpu.cputype = CPU_R2000; + mips_cpu.isa_level = MIPS_CPU_ISA_I; + mips_cpu.options = MIPS_CPU_TLB; + mips_cpu.tlbsize = 64; + break; + case PRID_IMP_R3000: + if ((mips_cpu.processor_id & 0xff) == PRID_REV_R3000A) + if (cpu_has_confreg()) + mips_cpu.cputype = CPU_R3081E; + else + mips_cpu.cputype = CPU_R3000A; else - mips_cpu.cputype = CPU_R3000A; - else - mips_cpu.cputype = CPU_R3000; - mips_cpu.isa_level = MIPS_CPU_ISA_I; - mips_cpu.options = MIPS_CPU_TLB; - mips_cpu.tlbsize = 64; - break; - case PRID_IMP_R4000: - if ((mips_cpu.processor_id & 0xff) == PRID_REV_R4400) - mips_cpu.cputype = CPU_R4400SC; - else - mips_cpu.cputype = CPU_R4000SC; - mips_cpu.isa_level = MIPS_CPU_ISA_III; - mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | - MIPS_CPU_WATCH | MIPS_CPU_VCE; - mips_cpu.tlbsize = 48; - break; - case PRID_IMP_R4600: - mips_cpu.cputype = CPU_R4600; - mips_cpu.isa_level = MIPS_CPU_ISA_III; - mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU; - mips_cpu.tlbsize = 48; - break; + mips_cpu.cputype = CPU_R3000; + mips_cpu.isa_level = MIPS_CPU_ISA_I; + mips_cpu.options = MIPS_CPU_TLB; + mips_cpu.tlbsize = 64; + break; + case PRID_IMP_R4000: + if ((mips_cpu.processor_id & 0xff) == PRID_REV_R4400) + mips_cpu.cputype = CPU_R4400SC; + else + mips_cpu.cputype = CPU_R4000SC; + mips_cpu.isa_level = MIPS_CPU_ISA_III; + mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_WATCH | MIPS_CPU_VCE; + mips_cpu.tlbsize = 48; + break; + case PRID_IMP_R4600: + mips_cpu.cputype = CPU_R4600; + mips_cpu.isa_level = MIPS_CPU_ISA_III; + mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU; + mips_cpu.tlbsize = 48; + break; /* * This processor doesn't have an MMU, so it's not "real easy" to * run Linux on it. It is left purely for documentation. - * - case PRID_IMP_R4650: - mips_cpu.cputype = CPU_R4650; - mips_cpu.isa_level = MIPS_CPU_ISA_III; - mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU; - mips_cpu.tlbsize = 48; - break; - */ - case PRID_IMP_R3912: - mips_cpu.cputype = CPU_R3912; - mips_cpu.isa_level = MIPS_CPU_ISA_I; - mips_cpu.options = MIPS_CPU_TLB; - mips_cpu.tlbsize = 32; - break; - case PRID_IMP_R4700: - mips_cpu.cputype = CPU_R4700; - mips_cpu.isa_level = MIPS_CPU_ISA_III; - mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR; - mips_cpu.tlbsize = 48; - break; - case PRID_IMP_R5000: - mips_cpu.cputype = CPU_R5000; - mips_cpu.isa_level = MIPS_CPU_ISA_IV; - mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR; - mips_cpu.tlbsize = 48; - break; - case PRID_IMP_R5432: - mips_cpu.cputype = CPU_R5432; - mips_cpu.isa_level = MIPS_CPU_ISA_IV; - mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR; - mips_cpu.tlbsize = 48; - break; - case PRID_IMP_NEVADA: - mips_cpu.cputype = CPU_NEVADA; - mips_cpu.isa_level = MIPS_CPU_ISA_IV; - mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | - MIPS_CPU_DIVEC; - mips_cpu.tlbsize = 48; - mips_cpu.icache.ways = 2; - mips_cpu.dcache.ways = 2; - break; - case PRID_IMP_R6000: - mips_cpu.cputype = CPU_R6000; - mips_cpu.isa_level = MIPS_CPU_ISA_II; - mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_FPU; - mips_cpu.tlbsize = 32; - break; - case PRID_IMP_R6000A: - mips_cpu.cputype = CPU_R6000A; - mips_cpu.isa_level = MIPS_CPU_ISA_II; - mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_FPU; - mips_cpu.tlbsize = 32; - break; - case PRID_IMP_RM7000: - mips_cpu.cputype = CPU_RM7000; - mips_cpu.isa_level = MIPS_CPU_ISA_IV; - mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR; - break; - case PRID_IMP_R8000: - mips_cpu.cputype = CPU_R8000; - mips_cpu.isa_level = MIPS_CPU_ISA_IV; - mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | - MIPS_CPU_FPU | MIPS_CPU_32FPR; - mips_cpu.tlbsize = 384; /* has wierd TLB: 3-way x 128 */ - break; - case PRID_IMP_R10000: - mips_cpu.cputype = CPU_R10000; - mips_cpu.isa_level = MIPS_CPU_ISA_IV; - mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | - MIPS_CPU_FPU | MIPS_CPU_32FPR | - MIPS_CPU_COUNTER | MIPS_CPU_WATCH; - mips_cpu.tlbsize = 64; + * case PRID_IMP_R4650: + mips_cpu.cputype = CPU_R4650; + mips_cpu.isa_level = MIPS_CPU_ISA_III; + mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU; + mips_cpu.tlbsize = 48; + break; +*/ + case PRID_IMP_TX39: + mips_cpu.isa_level = MIPS_CPU_ISA_I; + mips_cpu.options = MIPS_CPU_TLB; + + switch (mips_cpu.processor_id & 0xff) { + case PRID_REV_TX3912: + mips_cpu.cputype = CPU_TX3912; + mips_cpu.tlbsize = 32; + break; + case PRID_REV_TX3922: + mips_cpu.cputype = CPU_TX3922; + mips_cpu.tlbsize = 64; + break; + case PRID_REV_TX3927: + mips_cpu.cputype = CPU_TX3927; + mips_cpu.tlbsize = 64; + break; + default: + mips_cpu.cputype = CPU_UNKNOWN; + break; + } + break; + case PRID_IMP_R4700: + mips_cpu.cputype = CPU_R4700; + mips_cpu.isa_level = MIPS_CPU_ISA_III; + mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR; + mips_cpu.tlbsize = 48; + break; + case PRID_IMP_R5000: + mips_cpu.cputype = CPU_R5000; + mips_cpu.isa_level = MIPS_CPU_ISA_IV; + mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR; + mips_cpu.tlbsize = 48; + break; + case PRID_IMP_R5432: + mips_cpu.cputype = CPU_R5432; + mips_cpu.isa_level = MIPS_CPU_ISA_IV; + mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR; + mips_cpu.tlbsize = 48; + break; + case PRID_IMP_NEVADA: + mips_cpu.cputype = CPU_NEVADA; + mips_cpu.isa_level = MIPS_CPU_ISA_IV; + mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_DIVEC; + mips_cpu.tlbsize = 48; + mips_cpu.icache.ways = 2; + mips_cpu.dcache.ways = 2; + break; + case PRID_IMP_R6000: + mips_cpu.cputype = CPU_R6000; + mips_cpu.isa_level = MIPS_CPU_ISA_II; + mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_FPU; + mips_cpu.tlbsize = 32; + break; + case PRID_IMP_R6000A: + mips_cpu.cputype = CPU_R6000A; + mips_cpu.isa_level = MIPS_CPU_ISA_II; + mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_FPU; + mips_cpu.tlbsize = 32; + break; + case PRID_IMP_RM7000: + mips_cpu.cputype = CPU_RM7000; + mips_cpu.isa_level = MIPS_CPU_ISA_IV; + mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR; + break; + case PRID_IMP_R8000: + mips_cpu.cputype = CPU_R8000; + mips_cpu.isa_level = MIPS_CPU_ISA_IV; + mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_FPU | MIPS_CPU_32FPR; + mips_cpu.tlbsize = 384; /* has wierd TLB: 3-way x 128 */ + break; + case PRID_IMP_R10000: + mips_cpu.cputype = CPU_R10000; + mips_cpu.cputype = MIPS_CPU_ISA_IV; + mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_COUNTER | MIPS_CPU_WATCH; + mips_cpu.tlbsize = 64; + break; + default: + mips_cpu.cputype = CPU_UNKNOWN; + break; + } break; #ifdef CONFIG_CPU_MIPS32 - case PRID_IMP_4KC: - mips_cpu.cputype = CPU_4KC; - mips_cpu.isa_level = MIPS_CPU_ISA_M32; - mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | - MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | - MIPS_CPU_DIVEC | MIPS_CPU_WATCH; - config1 = read_mips32_cp0_config1(); - if (config1 & (1 << 3)) - mips_cpu.options |= MIPS_CPU_WATCH; - if (config1 & (1 << 2)) - mips_cpu.options |= MIPS_CPU_MIPS16; - if (config1 & 1) - mips_cpu.options |= MIPS_CPU_FPU; - mips_cpu.scache.flags = MIPS_CACHE_NOT_PRESENT; - break; - case PRID_IMP_5KC: - mips_cpu.cputype = CPU_5KC; - mips_cpu.isa_level = MIPS_CPU_ISA_M64; - mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | - MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | - MIPS_CPU_DIVEC | MIPS_CPU_WATCH; - config1 = read_mips32_cp0_config1(); - if (config1 & (1 << 3)) - mips_cpu.options |= MIPS_CPU_WATCH; - if (config1 & (1 << 2)) - mips_cpu.options |= MIPS_CPU_MIPS16; - if (config1 & 1) - mips_cpu.options |= MIPS_CPU_FPU; - mips_cpu.scache.flags = MIPS_CACHE_NOT_PRESENT; + case PRID_COMP_MIPS: + switch (mips_cpu.processor_id & 0xff00) { + case PRID_IMP_4KC: + mips_cpu.cputype = CPU_4KC; + goto cpu_4kc; + case PRID_IMP_4KEC: + mips_cpu.cputype = CPU_4KEC; + goto cpu_4kc; + case PRID_IMP_4KSC: + mips_cpu.cputype = CPU_4KSC; +cpu_4kc: + /* Why do we set all these options by default, THEN query them?? */ + mips_cpu.cputype = MIPS_CPU_ISA_M32; + mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | + MIPS_CPU_DIVEC | MIPS_CPU_WATCH; + config1 = read_mips32_cp0_config1(); + if (config1 & (1 << 3)) + mips_cpu.options |= MIPS_CPU_WATCH; + if (config1 & (1 << 2)) + mips_cpu.options |= MIPS_CPU_MIPS16; + if (config1 & 1) + mips_cpu.options |= MIPS_CPU_FPU; + mips_cpu.scache.flags = MIPS_CACHE_NOT_PRESENT; + break; + case PRID_IMP_5KC: + mips_cpu.cputype = CPU_5KC; + mips_cpu.cputype = MIPS_CPU_ISA_M64; + /* See comment above about querying options */ + mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | + MIPS_CPU_DIVEC | MIPS_CPU_WATCH; + config1 = read_mips32_cp0_config1(); + if (config1 & (1 << 3)) + mips_cpu.options |= MIPS_CPU_WATCH; + if (config1 & (1 << 2)) + mips_cpu.options |= MIPS_CPU_MIPS16; + if (config1 & 1) + mips_cpu.options |= MIPS_CPU_FPU; + break; + mips_cpu.scache.flags = MIPS_CACHE_NOT_PRESENT; + default: + mips_cpu.cputype = CPU_UNKNOWN; + break; + } break; #endif + case PRID_COMP_ALCHEMY: + switch (mips_cpu.processor_id & 0xff00) { +#ifdef CONFIG_CPU_MIPS32 + case PRID_IMP_AU1000: + mips_cpu.cputype = CPU_AU1000; + mips_cpu.isa_level = MIPS_CPU_ISA_M32; + mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | + MIPS_CPU_DIVEC | MIPS_CPU_WATCH; + config1 = read_mips32_cp0_config1(); + if (config1 & (1 << 3)) + mips_cpu.options |= MIPS_CPU_WATCH; + if (config1 & (1 << 2)) + mips_cpu.options |= MIPS_CPU_MIPS16; + if (config1 & 1) + mips_cpu.options |= MIPS_CPU_FPU; + mips_cpu.scache.flags = MIPS_CACHE_NOT_PRESENT; + break; +#endif + default: + mips_cpu.cputype = CPU_UNKNOWN; + break; + } + break; + case PRID_COMP_SIBYTE: + switch (mips_cpu.processor_id & 0xff00) { + case PRID_IMP_SB1: + mips_cpu.cputype = CPU_SB1; + mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_COUNTER | MIPS_CPU_DIVEC | MIPS_CPU_FPU | + MIPS_CPU_VCE; + break; + default: + mips_cpu.cputype = CPU_UNKNOWN; + break; + } + break; default: mips_cpu.cputype = CPU_UNKNOWN; } @@ -329,9 +396,6 @@ #ifdef CONFIG_SGI_IP22 sgi_sysinit(); #endif -#ifdef CONFIG_COBALT_MICRO_SERVER - SetUpBootInfo(); -#endif /* * Determine the mmu/cache attached to this machine, @@ -349,25 +413,116 @@ start_kernel(); } -static void __init default_irq_setup(void) +void __init add_memory_region(unsigned long start, unsigned long size, + long type) { - panic("Unknown machtype in init_IRQ"); + int x = boot_mem_map.nr_map; + + if (x == BOOT_MEM_MAP_MAX) { + printk("Ooops! Too many entries in the memory map!\n"); + return; + } + + boot_mem_map.map[x].addr = start; + boot_mem_map.map[x].size = size; + boot_mem_map.map[x].type = type; + boot_mem_map.nr_map++; +} + +static void __init print_memory_map(void) +{ + int i; + + for (i = 0; i < boot_mem_map.nr_map; i++) { + printk(" memory: %08lx @ %08lx ", + boot_mem_map.map[i].size, boot_mem_map.map[i].addr); + switch (boot_mem_map.map[i].type) { + case BOOT_MEM_RAM: + printk("(usable)\n"); + break; + case BOOT_MEM_ROM_DATA: + printk("(ROM data)\n"); + break; + case BOOT_MEM_RESERVED: + printk("(reserved)\n"); + break; + default: + printk("type %lu\n", boot_mem_map.map[i].type); + break; + } + } +} + +static inline void parse_mem_cmdline(void) +{ + char c = ' ', *to = command_line, *from = saved_command_line; + unsigned long start_at, mem_size; + int len = 0; + int usermem = 0; + + printk("Determined physical RAM map:\n"); + print_memory_map(); + + for (;;) { + /* + * "mem=XXX[kKmM]" defines a memory region from + * 0 to , overriding the determined size. + * "mem=XXX[KkmM]@YYY[KkmM]" defines a memory region from + * to +, overriding the determined size. + */ + if (c == ' ' && !memcmp(from, "mem=", 4)) { + if (to != command_line) + to--; + /* + * If a user specifies memory size, we + * blow away any automatically generated + * size. + */ + if (usermem == 0) { + boot_mem_map.nr_map = 0; + usermem = 1; + } + mem_size = memparse(from + 4, &from); + if (*from == '@') + start_at = memparse(from + 1, &from); + else + start_at = 0; + add_memory_region(start_at, mem_size, BOOT_MEM_RAM); + } + c = *(from++); + if (!c) + break; + if (COMMAND_LINE_SIZE <= ++len) + break; + *(to++) = c; + } + *to = '\0'; + + if (usermem) { + printk("User-defined physical RAM map:\n"); + print_memory_map(); + } } void __init setup_arch(char **cmdline_p) { + void atlas_setup(void); void baget_setup(void); - void cobalt_setup(void); + void ddb_setup(void); void decstation_setup(void); void deskstation_setup(void); void jazz_setup(void); void sni_rm200_pci_setup(void); void sgi_setup(void); - void ddb_setup(void); - void orion_setup(void); + void ev96100_setup(void); + void malta_setup(void); + void momenco_ocelot_setup(void); + void nino_setup(void); - /* Save defaults for configuration-dependent routines. */ - irq_setup = default_irq_setup; + unsigned long bootmap_size; + unsigned long start_pfn, max_pfn, first_usable_pfn; + + int i; #ifdef CONFIG_BLK_DEV_FD fd_ops = &no_fd_ops; @@ -390,21 +545,31 @@ baget_setup(); break; #endif -#ifdef CONFIG_COBALT_MICRO_SERVER - case MACH_GROUP_COBALT: - cobalt_setup(); - break; -#endif #ifdef CONFIG_DECSTATION case MACH_GROUP_DEC: decstation_setup(); break; #endif +#ifdef CONFIG_MIPS_ATLAS + case MACH_GROUP_UNKNOWN: + atlas_setup(); + break; +#endif #ifdef CONFIG_MIPS_JAZZ case MACH_GROUP_JAZZ: jazz_setup(); break; #endif +#ifdef CONFIG_MIPS_MALTA + case MACH_GROUP_UNKNOWN: + malta_setup(); + break; +#endif +#ifdef CONFIG_MOMENCO_OCELOT + case MACH_GROUP_MOMENCO: + momenco_ocelot_setup(); + break; +#endif #ifdef CONFIG_SGI_IP22 /* As of now this is only IP22. */ case MACH_GROUP_SGI: @@ -421,42 +586,193 @@ ddb_setup(); break; #endif -#ifdef CONFIG_ORION - case MACH_GROUP_ORION: - orion_setup(); +#ifdef CONFIG_DDB5476 + case MACH_GROUP_NEC_DDB: + ddb_setup(); + break; +#endif +#ifdef CONFIG_DDB5477 + case MACH_GROUP_NEC_DDB: + ddb_setup(); + break; +#endif +#ifdef CONFIG_MIPS_EV96100 + case MACH_GROUP_GALILEO: + ev96100_setup(); + break; +#endif +#ifdef CONFIG_MIPS_EV64120 + case MACH_GROUP_GALILEO: + ev64120_setup(); + break; +#endif +#if defined(CONFIG_MIPS_IVR) || defined(CONFIG_MIPS_ITE8172) + case MACH_GROUP_ITE: + case MACH_GROUP_GLOBESPAN: + it8172_setup(); + break; +#endif +#ifdef CONFIG_NINO + case MACH_GROUP_PHILIPS: + nino_setup(); + break; +#endif +#ifdef CONFIG_MIPS_PB1000 + case MACH_GROUP_ALCHEMY: + au1000_setup(); break; #endif default: panic("Unsupported architecture"); } - strncpy (command_line, arcs_cmdline, CL_SIZE); - memcpy(saved_command_line, command_line, CL_SIZE); - saved_command_line[CL_SIZE-1] = '\0'; - + strncpy(command_line, arcs_cmdline, sizeof command_line); + command_line[sizeof command_line - 1] = 0; + strcpy(saved_command_line, command_line); *cmdline_p = command_line; + parse_mem_cmdline(); + +#define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT) +#define PFN_DOWN(x) ((x) >> PAGE_SHIFT) +#define PFN_PHYS(x) ((x) << PAGE_SHIFT) + + /* + * Partially used pages are not usable - thus + * we are rounding upwards. + */ + start_pfn = PFN_UP(__pa(&_end)); + + /* Find the highest page frame number we have available. */ + max_pfn = 0; + first_usable_pfn = -1UL; + for (i = 0; i < boot_mem_map.nr_map; i++) { + unsigned long start, end; + + if (boot_mem_map.map[i].type != BOOT_MEM_RAM) + continue; + + start = PFN_UP(boot_mem_map.map[i].addr); + end = PFN_DOWN(boot_mem_map.map[i].addr + + boot_mem_map.map[i].size); + + if (start >= end) + continue; + if (end > max_pfn) + max_pfn = end; + if (start < first_usable_pfn) { + if (start > start_pfn) { + first_usable_pfn = start; + } else if (end > start_pfn) { + first_usable_pfn = start_pfn; + } + } + } + + /* Initialize the boot-time allocator. */ + bootmap_size = init_bootmem(first_usable_pfn, max_pfn); + + /* + * Register fully available low RAM pages with the bootmem allocator. + */ + for (i = 0; i < boot_mem_map.nr_map; i++) { + unsigned long curr_pfn, last_pfn, size; + + /* + * Reserve usable memory. + */ + if (boot_mem_map.map[i].type != BOOT_MEM_RAM) + continue; + + /* + * We are rounding up the start address of usable memory: + */ + curr_pfn = PFN_UP(boot_mem_map.map[i].addr); + if (curr_pfn >= max_pfn) + continue; + if (curr_pfn < start_pfn) + curr_pfn = start_pfn; + + /* + * ... and at the end of the usable range downwards: + */ + last_pfn = PFN_DOWN(boot_mem_map.map[i].addr + + boot_mem_map.map[i].size); + + if (last_pfn > max_pfn) + last_pfn = max_pfn; + + /* + * ... finally, did all the rounding and playing + * around just make the area go away? + */ + if (last_pfn <= curr_pfn) + continue; + + size = last_pfn - curr_pfn; + free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size)); + } + + /* Reserve the bootmap memory. */ + reserve_bootmem(PFN_PHYS(first_usable_pfn), bootmap_size); + #ifdef CONFIG_BLK_DEV_INITRD -#error "Fixme, I'm broken." - tmp = (((unsigned long)&_end + PAGE_SIZE-1) & PAGE_MASK) - 8; - if (tmp < (unsigned long)&_end) - tmp += PAGE_SIZE; - initrd_header = (unsigned long *)tmp; - if (initrd_header[0] == 0x494E5244) { - initrd_start = (unsigned long)&initrd_header[2]; - initrd_end = initrd_start + initrd_header[1]; - initrd_below_start_ok = 1; - if (initrd_end > memory_end) { + /* Board specific code should have set up initrd_start and initrd_end */ + ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); + initrd_start = (unsigned long)&__rd_start; + initrd_end = (unsigned long)&__rd_end; + initrd_below_start_ok = 1; + if (initrd_start) { + unsigned long initrd_size = ((unsigned char *)initrd_end) - ((unsigned char *)initrd_start); + printk("Initial ramdisk at: 0x%p (%lu bytes)\n", + (void *)initrd_start, + initrd_size); + if ((void *)initrd_end > phys_to_virt(PFN_PHYS(max_low_pfn))) { printk("initrd extends beyond end of memory " - "(0x%08lx > 0x%08lx)\ndisabling initrd\n", - initrd_end,memory_end); - initrd_start = 0; - } else - *memory_start_p = initrd_end; + "(0x%lx > 0x%p)\ndisabling initrd\n", + initrd_end, + phys_to_virt(PFN_PHYS(max_low_pfn))); + initrd_start = initrd_end = 0; + } } -#endif +#endif /* CONFIG_BLK_DEV_INITRD */ paging_init(); + + code_resource.start = virt_to_bus(&_ftext); + code_resource.end = virt_to_bus(&_etext) - 1; + data_resource.start = virt_to_bus(&_fdata); + data_resource.end = virt_to_bus(&_edata) - 1; + + /* + * Request address space for all standard RAM. + */ + for (i = 0; i < boot_mem_map.nr_map; i++) { + struct resource *res; + + res = alloc_bootmem(sizeof(struct resource)); + switch (boot_mem_map.map[i].type) { + case BOOT_MEM_RAM: + case BOOT_MEM_ROM_DATA: + res->name = "System RAM"; + break; + case BOOT_MEM_RESERVED: + default: + res->name = "reserved"; + } + res->start = boot_mem_map.map[i].addr; + res->end = res->start + boot_mem_map.map[i].size - 1; + res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; + request_resource(&iomem_resource, res); + + /* + * We dont't know which RAM region contains kernel data, + * so we try it repeatedly and let the resource manager + * test it. + */ + request_resource(res, &code_resource); + request_resource(res, &data_resource); + } } void r3081_wait(void) diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/smp.c linux/arch/mips/kernel/smp.c --- v2.4.5/linux/arch/mips/kernel/smp.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/kernel/smp.c Mon Jul 2 13:56:40 2001 @@ -0,0 +1,402 @@ +/* + * + * arch/mips/kernel/smp.c + * + * Copyright (C) 2000 Sibyte + * + * Written by Justin Carlson (carlson@sibyte.com) + * + * 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 +#include + +/* + * This was written with the BRCM12500 MP SOC in mind, but tries to + * be generic. It's modelled on the mips64 smp.c code, which is + * derived from Sparc, I'm guessing, which is derived from... + * + * It's probably horribly designed for very large ccNUMA systems + * as it doesn't take any node clustering into account. +*/ + + +/* Ze Big Kernel Lock! */ +spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED; +int smp_threads_ready; /* Not used */ +int smp_num_cpus; +int global_irq_holder = NO_PROC_ID; +spinlock_t global_irq_lock = SPIN_LOCK_UNLOCKED; +struct mips_cpuinfo cpu_data[NR_CPUS]; + +struct smp_fn_call_struct smp_fn_call = +{ SPIN_LOCK_UNLOCKED, ATOMIC_INIT(0), NULL, NULL}; + +static atomic_t cpus_booted = ATOMIC_INIT(0); + + +/* These are defined by the board-specific code. */ + +/* Cause the function described by smp_fn_call + to be executed on the passed cpu. When the function + has finished, increment the finished field of + smp_fn_call. */ + +void core_call_function(int cpu); + +/* + * Clear all undefined state in the cpu, set up sp and gp to the passed + * values, and kick the cpu into smp_bootstrap(); + */ +void prom_boot_secondary(int cpu, unsigned long sp, unsigned long gp); + +/* + * After we've done initial boot, this function is called to allow the + * board code to clean up state, if needed + */ + +void prom_init_secondary(void); + + +void cpu_idle(void); + +/* Do whatever setup needs to be done for SMP at the board level. Return + the number of cpus in the system, including this one */ +int prom_setup_smp(void); + +int start_secondary(void *unused) +{ + prom_init_secondary(); + write_32bit_cp0_register(CP0_CONTEXT, smp_processor_id()<<23); + current_pgd[smp_processor_id()] = init_mm.pgd; + printk("Slave cpu booted successfully\n"); + atomic_inc(&cpus_booted); + cpu_idle(); + return 0; +} + +void __init smp_boot_cpus(void) +{ + int i; + + smp_num_cpus = prom_setup_smp(); + init_new_context(current, &init_mm); + current->processor = 0; + atomic_set(&cpus_booted, 1); /* Master CPU is already booted... */ + init_idle(); + for (i = 1; i < smp_num_cpus; i++) { + struct task_struct *p; + struct pt_regs regs; + printk("Starting CPU %d... ", i); + + /* Spawn a new process normally. Grab a pointer to + its task struct so we can mess with it */ + do_fork(CLONE_VM|CLONE_PID, 0, ®s, 0); + p = init_task.prev_task; + + /* Schedule the first task manually */ + p->processor = i; + p->has_cpu = 1; + + /* Attach to the address space of init_task. */ + atomic_inc(&init_mm.mm_count); + p->active_mm = &init_mm; + init_tasks[i] = p; + + del_from_runqueue(p); + unhash_process(p); + + prom_boot_secondary(i, + (unsigned long)p + KERNEL_STACK_SIZE - 32, + (unsigned long)p); + +#if 0 + + /* This is copied from the ip-27 code in the mips64 tree */ + + struct task_struct *p; + + /* + * The following code is purely to make sure + * Linux can schedule processes on this slave. + */ + kernel_thread(0, NULL, CLONE_PID); + p = init_task.prev_task; + sprintf(p->comm, "%s%d", "Idle", i); + init_tasks[i] = p; + p->processor = i; + p->has_cpu = 1; /* we schedule the first task manually */ + del_from_runqueue(p); + unhash_process(p); + /* Attach to the address space of init_task. */ + atomic_inc(&init_mm.mm_count); + p->active_mm = &init_mm; + prom_boot_secondary(i, + (unsigned long)p + KERNEL_STACK_SIZE - 32, + (unsigned long)p); +#endif + } + + /* Wait for everyone to come up */ + while (atomic_read(&cpus_booted) != smp_num_cpus); +} + +void __init smp_commence(void) +{ + /* Not sure what to do here yet */ +} + +static void reschedule_this_cpu(void *dummy) +{ + current->need_resched = 1; +} + +void FASTCALL(smp_send_reschedule(int cpu)) +{ + smp_call_function(reschedule_this_cpu, NULL, 0, 0); +} + + +/* + * The caller of this wants the passed function to run on every cpu. If wait + * is set, wait until all cpus have finished the function before returning. + * The lock is here to protect the call structure. + */ +int smp_call_function (void (*func) (void *info), void *info, int retry, + int wait) +{ + int cpus = smp_num_cpus - 1; + int i; + + if (smp_num_cpus < 2) { + return 0; + } + + spin_lock_bh(&smp_fn_call.lock); + + atomic_set(&smp_fn_call.finished, 0); + smp_fn_call.fn = func; + smp_fn_call.data = info; + + for (i = 0; i < smp_num_cpus; i++) { + if (i != smp_processor_id()) { + /* Call the board specific routine */ + core_call_function(i); + } + } + + if (wait) { + while(atomic_read(&smp_fn_call.finished) != cpus) {} + } + + spin_unlock_bh(&smp_fn_call.lock); + return 0; +} + +void synchronize_irq(void) +{ + panic("synchronize_irq"); +} + +static void stop_this_cpu(void *dummy) +{ + printk("Cpu stopping\n"); + for (;;); +} + +void smp_send_stop(void) +{ + smp_call_function(stop_this_cpu, NULL, 1, 0); + smp_num_cpus = 1; +} + +/* Not really SMP stuff ... */ +int setup_profiling_timer(unsigned int multiplier) +{ + return 0; +} + + +/* + * Most of this code is take from the mips64 tree (ip27-irq.c). It's virtually + * identical to the i386 implentation in arh/i386/irq.c, with translations for + * the interrupt enable bit + */ + +#define MAXCOUNT 100000000 +#define SYNC_OTHER_CORES(x) udelay(x+1) + +static inline void wait_on_irq(int cpu) +{ + int count = MAXCOUNT; + + for (;;) { + + /* + * Wait until all interrupts are gone. Wait + * for bottom half handlers unless we're + * already executing in one.. + */ + if (!irqs_running()) + if (local_bh_count(cpu) || !spin_is_locked(&global_bh_lock)) + break; + + /* Duh, we have to loop. Release the lock to avoid deadlocks */ + spin_unlock(&global_irq_lock); + + for (;;) { + if (!--count) { + printk("Count spun out. Huh?\n"); + count = ~0; + } + __sti(); + SYNC_OTHER_CORES(cpu); + __cli(); + if (irqs_running()) + continue; + if (spin_is_locked(&global_irq_lock)) + continue; + if (!local_bh_count(cpu) && spin_is_locked(&global_bh_lock)) + continue; + if (spin_trylock(&global_irq_lock)) + break; + } + } +} + + +static inline void get_irqlock(int cpu) +{ + if (!spin_trylock(&global_irq_lock)) { + /* do we already hold the lock? */ + if ((unsigned char) cpu == global_irq_holder) + return; + /* Uhhuh.. Somebody else got it. Wait.. */ + spin_lock(&global_irq_lock); + } + /* + * We also to make sure that nobody else is running + * in an interrupt context. + */ + wait_on_irq(cpu); + + /* + * Ok, finally.. + */ + global_irq_holder = cpu; +} + + +/* + * A global "cli()" while in an interrupt context + * turns into just a local cli(). Interrupts + * should use spinlocks for the (very unlikely) + * case that they ever want to protect against + * each other. + * + * If we already have local interrupts disabled, + * this will not turn a local disable into a + * global one (problems with spinlocks: this makes + * save_flags+cli+sti usable inside a spinlock). + */ +void __global_cli(void) +{ + unsigned int flags; + + __save_flags(flags); + if (flags & ST0_IE) { + int cpu = smp_processor_id(); + __cli(); + if (!local_irq_count(cpu)) + get_irqlock(cpu); + } +} + +void __global_sti(void) +{ + int cpu = smp_processor_id(); + + if (!local_irq_count(cpu)) + release_irqlock(cpu); + __sti(); +} + +/* + * SMP flags value to restore to: + * 0 - global cli + * 1 - global sti + * 2 - local cli + * 3 - local sti + */ +unsigned long __global_save_flags(void) +{ + int retval; + int local_enabled; + unsigned long flags; + int cpu = smp_processor_id(); + + __save_flags(flags); + local_enabled = (flags & ST0_IE); + /* default to local */ + retval = 2 + local_enabled; + + /* check for global flags if we're not in an interrupt */ + if (!local_irq_count(cpu)) { + if (local_enabled) + retval = 1; + if (global_irq_holder == cpu) + retval = 0; + } + + return retval; +} + +void __global_restore_flags(unsigned long flags) +{ + switch (flags) { + case 0: + __global_cli(); + break; + case 1: + __global_sti(); + break; + case 2: + __cli(); + break; + case 3: + __sti(); + break; + default: + printk("global_restore_flags: %08lx\n", flags); + } +} diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/syscall.c linux/arch/mips/kernel/syscall.c --- v2.4.5/linux/arch/mips/kernel/syscall.c Mon Mar 19 12:35:09 2001 +++ linux/arch/mips/kernel/syscall.c Mon Jul 2 13:56:40 2001 @@ -92,22 +92,23 @@ return do_mmap2(addr, len, prot, flags, fd, pgoff); } -asmlinkage int sys_fork(struct pt_regs regs) +save_static_function(sys_fork); +static_unused int _sys_fork(struct pt_regs regs) { int res; - save_static(®s); res = do_fork(SIGCHLD, regs.regs[29], ®s, 0); return res; } -asmlinkage int sys_clone(struct pt_regs regs) + +save_static_function(sys_clone); +static_unused int _sys_clone(struct pt_regs regs) { unsigned long clone_flags; unsigned long newsp; int res; - save_static(®s); clone_flags = regs.regs[4]; newsp = regs.regs[5]; if (!newsp) diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/syscalls.h linux/arch/mips/kernel/syscalls.h --- v2.4.5/linux/arch/mips/kernel/syscalls.h Fri Aug 11 14:29:04 2000 +++ linux/arch/mips/kernel/syscalls.h Mon Jul 2 13:56:40 2001 @@ -1,10 +1,9 @@ -/* $Id: syscalls.h,v 1.22 2000/02/18 00:24:30 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle + * Copyright (C) 1995, 96, 97, 98, 99, 2000 by Ralf Baechle */ /* @@ -228,10 +227,11 @@ SYS(sys_mmap2, 6) /* 4210 */ SYS(sys_truncate64, 2) SYS(sys_ftruncate64, 2) -SYS(sys_stat64, 3) -SYS(sys_lstat64, 3) -SYS(sys_fstat64, 3) /* 4215 */ +SYS(sys_stat64, 2) +SYS(sys_lstat64, 2) +SYS(sys_fstat64, 2) /* 4215 */ SYS(sys_pivot_root, 2) SYS(sys_mincore, 3) SYS(sys_madvise, 3) SYS(sys_getdents64, 3) +SYS(sys_fcntl64, 3) /* 4220 */ diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/sysirix.c linux/arch/mips/kernel/sysirix.c --- v2.4.5/linux/arch/mips/kernel/sysirix.c Mon Mar 19 12:35:09 2001 +++ linux/arch/mips/kernel/sysirix.c Mon Jul 2 13:56:40 2001 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 David S. Miller * Copyright (C) 1997 Miguel de Icaza - * Copyright (C) 1997, 1998 Ralf Baechle + * Copyright (C) 1997, 1998, 1999, 2000 Ralf Baechle */ #include #include @@ -27,7 +27,6 @@ #include #include #include -#include #include /* 2,191 lines of complete and utter shit coming up... */ @@ -1249,9 +1248,9 @@ ks.st_blksize = (s32) sb->st_blksize; ks.st_blocks = (long long) sb->st_blocks; - memcpy(&ks.st_fstype[0], &sb->st_fstype[0], 16); - ks.st_pad4[0] = ks.st_pad4[1] = ks.st_pad4[2] = ks.st_pad4[3] = - ks.st_pad4[4] = ks.st_pad4[5] = ks.st_pad4[6] = ks.st_pad4[7] = 0; + memset(ks.st_fstype, 0, 16); + ks.st_pad4[0] = ks.st_pad4[1] = ks.st_pad4[2] = ks.st_pad4[3] = 0; + ks.st_pad4[4] = ks.st_pad4[5] = ks.st_pad4[6] = ks.st_pad4[7] = 0; /* Now write it all back. */ copy_to_user(sb, &ks, sizeof(struct xstat64)); diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/sysmips.c linux/arch/mips/kernel/sysmips.c --- v2.4.5/linux/arch/mips/kernel/sysmips.c Sun Jul 9 22:18:15 2000 +++ linux/arch/mips/kernel/sysmips.c Mon Jul 2 13:56:40 2001 @@ -7,6 +7,7 @@ * * Copyright (C) 1995, 1996, 1997, 2000 by Ralf Baechle */ +#include #include #include #include @@ -21,6 +22,8 @@ #include #include +extern asmlinkage void syscall_trace(void); + /* * How long a hostname can we get from user space? * -EFAULT if invalid area or too long @@ -49,7 +52,7 @@ { int *p; char *name; - int flags, tmp, len, retval, errno; + int tmp, len, retval, errno; switch(cmd) { case SETNAME: { @@ -72,8 +75,7 @@ } case MIPS_ATOMIC_SET: { - /* This is broken in case of page faults and SMP ... - Risc/OS faults after maximum 20 tries with EAGAIN. */ +#ifdef CONFIG_CPU_HAS_LLSC unsigned int tmp; p = (int *) arg1; @@ -81,16 +83,46 @@ if (errno) return errno; errno = 0; - save_and_cli(flags); - errno |= __get_user(tmp, p); - errno |= __put_user(arg2, p); - restore_flags(flags); + + __asm__(".set\tpush\t\t\t# sysmips(MIPS_ATOMIC, ...)\n\t" + ".set\tmips2\n\t" + ".set\tnoat\n\t" + "1:\tll\t%0, %4\n\t" + "move\t$1, %3\n\t" + "2:\tsc\t$1, %1\n\t" + "beqz\t$1, 1b\n\t" + ".set\tpop\n\t" + ".section\t.fixup,\"ax\"\n" + "3:\tli\t%2, 1\t\t\t# error\n\t" + ".previous\n\t" + ".section\t__ex_table,\"a\"\n\t" + ".word\t1b, 3b\n\t" + ".word\t2b, 3b\n\t" + ".previous\n\t" + : "=&r" (tmp), "=o" (* (u32 *) p), "=r" (errno) + : "r" (arg2), "o" (* (u32 *) p), "2" (errno) + : "$1"); if (errno) - return tmp; + return -EFAULT; - return tmp; /* This is broken ... */ - } + /* We're skipping error handling etc. */ + if (current->ptrace & PT_TRACESYS) + syscall_trace(); + + ((struct pt_regs *)&cmd)->regs[2] = tmp; + ((struct pt_regs *)&cmd)->regs[7] = 0; + + __asm__ __volatile__( + "move\t$29, %0\n\t" + "j\to32_ret_from_sys_call" + : /* No outputs */ + : "r" (&cmd)); + /* Unreached */ +#else + printk("sys_sysmips(MIPS_ATOMIC_SET, ...) not ready for !CONFIG_CPU_HAS_LLSC\n"); +#endif + } case MIPS_FIXADE: tmp = current->thread.mflags & ~3; diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/time.c linux/arch/mips/kernel/time.c --- v2.4.5/linux/arch/mips/kernel/time.c Mon Oct 16 12:58:51 2000 +++ linux/arch/mips/kernel/time.c Mon Jul 2 13:56:40 2001 @@ -1,551 +1,542 @@ -/* - * Copyright (C) 1991, 1992, 1995 Linus Torvalds - * Copyright (C) 1996 - 2000 Ralf Baechle +/*********************************************************************** + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * arch/mips/kernel/time.c + * Common time service routines for MIPS machines. See + * Documents/MIPS/time.txt. * - * This file contains the time handling details for PC-style clocks as - * found in some MIPS systems. + * 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 +#include +#include #include #include -#include #include -#include -#include -#include +#include +#include #include +#include +#include #include -#include -#include -#include -#include - -#include -#include - -extern volatile unsigned long wall_jiffies; -unsigned long r4k_interval; -extern rwlock_t xtime_lock; - -/* - * Change this if you have some constant time drift +#include +#include +#include + +/* + * macro for catching spurious errors. Eable to LL_DEBUG in kernel hacking + * config menu. */ -/* This is the value for the PC-style PICs. */ -/* #define USECS_PER_JIFFY (1000020/HZ) */ +#ifdef CONFIG_LL_DEBUG +#define MIPS_ASSERT(x) if (!(x)) { panic("MIPS_ASSERT failed at %s:%d\n", __FILE__, __LINE__); } +#define MIPS_DEBUG(x) do { x; } while (0) +#else +#define MIPS_ASSERT(x) +#define MIPS_DEBUG(x) +#endif /* This is for machines which generate the exact clock. */ #define USECS_PER_JIFFY (1000000/HZ) +#define USECS_PER_JIFFY_FRAC (0x100000000*1000000/HZ&0xffffffff) -/* Cycle counter value at the previous timer interrupt.. */ - -static unsigned int timerhi, timerlo; +/* + * forward reference + */ +extern rwlock_t xtime_lock; +extern volatile unsigned long wall_jiffies; /* - * On MIPS only R4000 and better have a cycle counter. - * - * FIXME: Does playing with the RP bit in c0_status interfere with this code? + * By default we provide the null RTC ops */ -static unsigned long do_fast_gettimeoffset(void) +static unsigned long null_rtc_get_time(void) { - u32 count; - unsigned long res, tmp; - - /* Last jiffy when do_fast_gettimeoffset() was called. */ - static unsigned long last_jiffies; - unsigned long quotient; + return mktime(2000, 1, 1, 0, 0, 0); +} - /* - * Cached "1/(clocks per usec)*2^32" value. - * It has to be recalculated once each jiffy. - */ - static unsigned long cached_quotient; +static int null_rtc_set_time(unsigned long sec) +{ + return 0; +} - tmp = jiffies; +unsigned long (*rtc_get_time)(void) = null_rtc_get_time; +int (*rtc_set_time)(unsigned long) = null_rtc_set_time; - quotient = cached_quotient; - if (tmp && last_jiffies != tmp) { - last_jiffies = tmp; - __asm__(".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "lwu\t%0,%2\n\t" - "dsll32\t$1,%1,0\n\t" - "or\t$1,$1,%0\n\t" - "ddivu\t$0,$1,%3\n\t" - "mflo\t$1\n\t" - "dsll32\t%0,%4,0\n\t" - "nop\n\t" - "ddivu\t$0,%0,$1\n\t" - "mflo\t%0\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=&r" (quotient) - :"r" (timerhi), - "m" (timerlo), - "r" (tmp), - "r" (USECS_PER_JIFFY) - :"$1"); - cached_quotient = quotient; - } +/* + * timeofday services, for syscalls. + */ +void do_gettimeofday(struct timeval *tv) +{ + unsigned long flags; - /* Get last timer tick in absolute kernel time */ - count = read_32bit_cp0_register(CP0_COUNT); + read_lock_irqsave (&xtime_lock, flags); + *tv = xtime; + tv->tv_usec += do_gettimeoffset(); + + /* + * xtime is atomically updated in timer_bh. jiffies - wall_jiffies + * is nonzero if the timer bottom half hasnt executed yet. + */ + if (jiffies - wall_jiffies) + tv->tv_usec += USECS_PER_JIFFY; + + read_unlock_irqrestore (&xtime_lock, flags); + + if (tv->tv_usec >= 1000000) { + tv->tv_usec -= 1000000; + tv->tv_sec++; + } +} - /* .. relative to previous jiffy (32 bits is enough) */ - count -= timerlo; -//printk("count: %08lx, %08lx:%08lx\n", count, timerhi, timerlo); - - __asm__("multu\t%1,%2\n\t" - "mfhi\t%0" - :"=r" (res) - :"r" (count), - "r" (quotient)); +void do_settimeofday(struct timeval *tv) +{ + write_lock_irq (&xtime_lock); - /* - * Due to possible jiffies inconsistencies, we need to check - * the result so that we'll get a timer that is monotonic. - */ - if (res >= USECS_PER_JIFFY) - res = USECS_PER_JIFFY-1; + /* This is revolting. We need to set the xtime.tv_usec + * correctly. However, the value in this location is + * is value at the last tick. + * Discover what correction gettimeofday + * would have done, and then undo it! + */ + tv->tv_usec -= do_gettimeoffset(); + + if (tv->tv_usec < 0) { + tv->tv_usec += 1000000; + tv->tv_sec--; + } + xtime = *tv; + time_adjust = 0; /* stop active adjtime() */ + time_status |= STA_UNSYNC; + time_maxerror = NTP_PHASE_LIMIT; + time_esterror = NTP_PHASE_LIMIT; - return res; + write_unlock_irq (&xtime_lock); } -/* This function must be called with interrupts disabled - * It was inspired by Steve McCanne's microtime-i386 for BSD. -- jrs - * - * However, the pc-audio speaker driver changes the divisor so that - * it gets interrupted rather more often - it loads 64 into the - * counter rather than 11932! This has an adverse impact on - * do_gettimeoffset() -- it stops working! What is also not - * good is that the interval that our timer function gets called - * is no longer 10.0002 ms, but 9.9767 ms. To get around this - * would require using a different timing source. Maybe someone - * could use the RTC - I know that this can interrupt at frequencies - * ranging from 8192Hz to 2Hz. If I had the energy, I'd somehow fix - * it so that at startup, the timer code in sched.c would select - * using either the RTC or the 8253 timer. The decision would be - * based on whether there was any other device around that needed - * to trample on the 8253. I'd set up the RTC to interrupt at 1024 Hz, - * and then do some jiggery to have a version of do_timer that - * advanced the clock by 1/1024 s. Every time that reached over 1/100 - * of a second, then do all the old code. If the time was kept correct - * then do_gettimeoffset could just return 0 - there is no low order - * divider that can be accessed. + +/* + * Gettimeoffset routines. These routines returns the time duration + * since last timer interrupt in usecs. * - * Ideally, you would be able to use the RTC for the speaker driver, - * but it appears that the speaker driver really needs interrupt more - * often than every 120 us or so. + * If the exact CPU counter frequency is known, use fixed_rate_gettimeoffset. + * Otherwise use calibrate_gettimeoffset() * - * Anyway, this needs more thought.... pjsg (1993-08-28) - * - * If you are really that interested, you should be reading - * comp.protocols.time.ntp! + * If the CPU does not have counter register all, you can either supply + * your own gettimeoffset() routine, or use null_gettimeoffset() routines, + * which gives the same resolution as HZ. */ -#define TICK_SIZE tick -static unsigned long do_slow_gettimeoffset(void) -{ - int count; +/* This is for machines which generate the exact clock. */ +#define USECS_PER_JIFFY (1000000/HZ) - static int count_p = LATCH; /* for the first call after boot */ - static unsigned long jiffies_p; +/* usecs per counter cycle, shifted to left by 32 bits */ +static unsigned int sll32_usecs_per_cycle=0; - /* - * cache volatile jiffies temporarily; we have IRQs turned off. - */ - unsigned long jiffies_t; +/* how many counter cycles in a jiffy */ +static unsigned long cycles_per_jiffy=0; + +/* Cycle counter value at the previous timer interrupt.. */ +static unsigned int timerhi, timerlo; - /* timer count may underflow right here */ - outb_p(0x00, 0x43); /* latch the count ASAP */ +/* last time when xtime and rtc are sync'ed up */ +static long last_rtc_update; - count = inb_p(0x40); /* read the latched count */ +/* the function pointer to one of the gettimeoffset funcs*/ +unsigned long (*do_gettimeoffset)(void) = null_gettimeoffset; - /* - * We do this guaranteed double memory access instead of a _p - * postfix in the previous port access. Wheee, hackady hack - */ - jiffies_t = jiffies; +unsigned long null_gettimeoffset(void) +{ + return 0; +} - count |= inb_p(0x40) << 8; +unsigned long fixed_rate_gettimeoffset(void) +{ + u32 count; + unsigned long res; - /* - * avoiding timer inconsistencies (they are rare, but they happen)... - * there are two kinds of problems that must be avoided here: - * 1. the timer counter underflows - * 2. hardware problem with the timer, not giving us continuous time, - * the counter does small "jumps" upwards on some Pentium systems, - * (see c't 95/10 page 335 for Neptun bug.) - */ + MIPS_ASSERT(mips_cpu.options & MIPS_CPU_COUNTER); + MIPS_ASSERT(mips_counter_frequency != 0); + MIPS_ASSERT(sll32_usecs_per_cycle != 0); - if( jiffies_t == jiffies_p ) { - if( count > count_p ) { - /* the nutcase */ - - outb_p(0x0A, 0x20); - - /* assumption about timer being IRQ1 */ - if (inb(0x20) & 0x01) { - /* - * We cannot detect lost timer interrupts ... - * well, that's why we call them lost, don't we? :) - * [hmm, on the Pentium and Alpha we can ... sort of] - */ - count -= LATCH; - } else { - printk("do_slow_gettimeoffset(): hardware timer problem?\n"); - } - } - } else - jiffies_p = jiffies_t; + /* Get last timer tick in absolute kernel time */ + count = read_32bit_cp0_register(CP0_COUNT); - count_p = count; + /* .. relative to previous jiffy (32 bits is enough) */ + count -= timerlo; - count = ((LATCH-1) - count) * TICK_SIZE; - count = (count + LATCH/2) / LATCH; + __asm__("multu\t%1,%2\n\t" + "mfhi\t%0" + :"=r" (res) + :"r" (count), + "r" (sll32_usecs_per_cycle)); + + /* + * Due to possible jiffies inconsistencies, we need to check + * the result so that we'll get a timer that is monotonic. + */ + if (res >= USECS_PER_JIFFY) + res = USECS_PER_JIFFY-1; - return count; + return res; } -static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset; - /* - * This version of gettimeofday has near microsecond resolution. + * Cached "1/(clocks per usec)*2^32" value. + * It has to be recalculated once each jiffy. */ -void do_gettimeofday(struct timeval *tv) -{ - unsigned long flags; +static unsigned long cached_quotient; - read_lock_irqsave (&xtime_lock, flags); - *tv = xtime; - tv->tv_usec += do_gettimeoffset(); +/* Last jiffy when calibrate_divXX_gettimeoffset() was called. */ +static unsigned long last_jiffies = 0; - /* - * xtime is atomically updated in timer_bh. jiffies - wall_jiffies - * is nonzero if the timer bottom half hasnt executed yet. - */ - if (jiffies - wall_jiffies) - tv->tv_usec += USECS_PER_JIFFY; +/* + * copied from include/asm/div64. + * We do the copy instead of include the header file because we don't + * want to reply on _MIPS_ISA value. + */ +#define do_div64_32(res, high, low, base) ({ \ + unsigned long __quot, __mod; \ + unsigned long __cf, __tmp, __i; \ + \ + __asm__(".set push\n\t" \ + ".set noat\n\t" \ + ".set noreorder\n\t" \ + "b 1f\n\t" \ + " li %4,0x21\n" \ + "0:\n\t" \ + "sll $1,%0,0x1\n\t" \ + "srl %3,%0,0x1f\n\t" \ + "or %0,$1,$2\n\t" \ + "sll %1,%1,0x1\n\t" \ + "sll %2,%2,0x1\n" \ + "1:\n\t" \ + "bnez %3,2f\n\t" \ + "sltu $2,%0,%z5\n\t" \ + "bnez $2,3f\n\t" \ + "2:\n\t" \ + " addiu %4,%4,-1\n\t" \ + "subu %0,%0,%z5\n\t" \ + "addiu %2,%2,1\n" \ + "3:\n\t" \ + "bnez %4,0b\n\t" \ + " srl $2,%1,0x1f\n\t" \ + ".set pop" \ + : "=&r" (__mod), "=&r" (__tmp), "=&r" (__quot), "=&r" (__cf), \ + "=&r" (__i) \ + : "Jr" (base), "0" (high), "1" (low), "2" (0), "3" (0) \ + /* Aarrgh! Ran out of gcc's limit on constraints... */ \ + : "$1", "$2"); \ + \ + (res) = __quot; \ + __mod; }) - read_unlock_irqrestore (&xtime_lock, flags); +/* + * This is copied from dec/time.c:do_ioasic_gettimeoffset() by Mercij. + */ +unsigned long calibrate_div32_gettimeoffset(void) +{ + u32 count; + unsigned long res, tmp; + unsigned long quotient; + + MIPS_ASSERT(mips_cpu.options & MIPS_CPU_COUNTER); + + tmp = jiffies; + + quotient = cached_quotient; + + if (last_jiffies != tmp) { + last_jiffies = tmp; + if (last_jiffies != 0) { + unsigned long r0; + do_div64_32(r0, timerhi, timerlo, tmp); + do_div64_32(quotient, USECS_PER_JIFFY, + USECS_PER_JIFFY_FRAC, r0); + cached_quotient = quotient; + } + } + + /* Get last timer tick in absolute kernel time */ + count = read_32bit_cp0_register(CP0_COUNT); + + /* .. relative to previous jiffy (32 bits is enough) */ + count -= timerlo; + + __asm__("multu %2,%3" + : "=l" (tmp), "=h" (res) + : "r" (count), "r" (quotient)); + + /* + * Due to possible jiffies inconsistencies, we need to check + * the result so that we'll get a timer that is monotonic. + */ + if (res >= USECS_PER_JIFFY) + res = USECS_PER_JIFFY - 1; - if (tv->tv_usec >= 1000000) { - tv->tv_usec -= 1000000; - tv->tv_sec++; - } + return res; } -void do_settimeofday(struct timeval *tv) +unsigned long calibrate_div64_gettimeoffset(void) { - write_lock_irq (&xtime_lock); - /* This is revolting. We need to set the xtime.tv_usec - * correctly. However, the value in this location is - * is value at the last tick. - * Discover what correction gettimeofday - * would have done, and then undo it! - */ - tv->tv_usec -= do_gettimeoffset(); - - if (tv->tv_usec < 0) { - tv->tv_usec += 1000000; - tv->tv_sec--; - } + u32 count; + unsigned long res, tmp; + unsigned long quotient; + + + MIPS_ASSERT(mips_cpu.options & MIPS_CPU_COUNTER); + MIPS_ASSERT((mips_cpu.isa_level != MIPS_CPU_ISA_I) && + (mips_cpu.isa_level != MIPS_CPU_ISA_II) && + (mips_cpu.isa_level != MIPS_CPU_ISA_M32)); + + + tmp = jiffies; + + quotient = cached_quotient; + + if (tmp && last_jiffies != tmp) { + last_jiffies = tmp; + __asm__(".set\tnoreorder\n\t" + ".set\tnoat\n\t" + ".set\tmips3\n\t" + "lwu\t%0,%2\n\t" + "dsll32\t$1,%1,0\n\t" + "or\t$1,$1,%0\n\t" + "ddivu\t$0,$1,%3\n\t" + "mflo\t$1\n\t" + "dsll32\t%0,%4,0\n\t" + "nop\n\t" + "ddivu\t$0,%0,$1\n\t" + "mflo\t%0\n\t" + ".set\tmips0\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=&r" (quotient) + :"r" (timerhi), + "m" (timerlo), + "r" (tmp), + "r" (USECS_PER_JIFFY) + :"$1"); + cached_quotient = quotient; + } + + /* Get last timer tick in absolute kernel time */ + count = read_32bit_cp0_register(CP0_COUNT); + + /* .. relative to previous jiffy (32 bits is enough) */ + count -= timerlo; + + __asm__("multu\t%1,%2\n\t" + "mfhi\t%0" + :"=r" (res) + :"r" (count), + "r" (quotient)); + + /* + * Due to possible jiffies inconsistencies, we need to check + * the result so that we'll get a timer that is monotonic. + */ + if (res >= USECS_PER_JIFFY) + res = USECS_PER_JIFFY-1; - xtime = *tv; - time_adjust = 0; /* stop active adjtime() */ - time_status |= STA_UNSYNC; - time_maxerror = NTP_PHASE_LIMIT; - time_esterror = NTP_PHASE_LIMIT; - write_unlock_irq (&xtime_lock); + return res; } + /* - * In order to set the CMOS clock precisely, set_rtc_mmss has to be - * called 500 ms after the second nowtime has started, because when - * nowtime is written into the registers of the CMOS clock, it will - * jump to the next second precisely 500 ms later. Check the Motorola - * MC146818A or Dallas DS12887 data sheet for details. - * - * BUG: This routine does not handle hour overflow properly; it just - * sets the minutes. Usually you won't notice until after reboot! + * high-level timer interrupt service routines. This function + * is set as irqaction->handler and is invoked through do_IRQ. */ -static int set_rtc_mmss(unsigned long nowtime) +void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - int retval = 0; - int real_seconds, real_minutes, cmos_minutes; - unsigned char save_control, save_freq_select; - - save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ - CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); + if (mips_cpu.options & MIPS_CPU_COUNTER) { + unsigned int count; - save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ - CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); + /* + * The cycle counter is only 32 bit which is good for about + * a minute at current count rates of upto 150MHz or so. + */ + count = read_32bit_cp0_register(CP0_COUNT); + timerhi += (count < timerlo); /* Wrap around */ + timerlo = count; - cmos_minutes = CMOS_READ(RTC_MINUTES); - if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - BCD_TO_BIN(cmos_minutes); + /* + * set up for next timer interrupt - no harm if the machine + * is using another timer interrupt source. + * Note that writing to COMPARE register clears the interrupt + */ + write_32bit_cp0_register (CP0_COMPARE, + count + cycles_per_jiffy); - /* - * since we're only adjusting minutes and seconds, - * don't interfere with hour overflow. This avoids - * messing with unknown time zones but requires your - * RTC not to be off by more than 15 minutes - */ - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) - real_minutes += 30; /* correct for half hour time zone */ - real_minutes %= 60; - - if (abs(real_minutes - cmos_minutes) < 30) { - if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BIN_TO_BCD(real_seconds); - BIN_TO_BCD(real_minutes); - } - CMOS_WRITE(real_seconds,RTC_SECONDS); - CMOS_WRITE(real_minutes,RTC_MINUTES); - } else { - printk(KERN_WARNING - "set_rtc_mmss: can't update from %d to %d\n", - cmos_minutes, real_minutes); - retval = -1; } - /* The following flags have to be released exactly in this order, - * otherwise the DS12887 (popular MC146818A clone with integrated - * battery and quartz) will not reset the oscillator and will not - * update precisely 500 ms later. You won't find this mentioned in - * the Dallas Semiconductor data sheets, but who believes data - * sheets anyway ... -- Markus Kuhn - */ - CMOS_WRITE(save_control, RTC_CONTROL); - CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); - - return retval; -} - -/* last time the cmos clock got updated */ -static long last_rtc_update; - -/* - * timer_interrupt() needs to keep up the real-time clock, - * as well as call the "do_timer()" routine every clocktick - */ -static void inline -timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) -{ -#ifdef CONFIG_DDB5074 - static unsigned cnt, period, dist; - - if (cnt == 0 || cnt == dist) - ddb5074_led_d2(1); - else if (cnt == 7 || cnt == dist+7) - ddb5074_led_d2(0); - - if (++cnt > period) { - cnt = 0; - /* The hyperbolic function below modifies the heartbeat period - * length in dependency of the current (5min) load. It goes - * through the points f(0)=126, f(1)=86, f(5)=51, - * f(inf)->30. */ - period = ((672<pid) { - extern int _stext; - unsigned long pc = regs->cp0_epc; + extern int _stext; + unsigned long pc = regs->cp0_epc; - pc -= (unsigned long) &_stext; - pc >>= prof_shift; - /* - * Dont ignore out-of-bounds pc values silently, - * put them into the last histogram slot, so if - * present, they will show up as a sharp peak. - */ - if (pc > prof_len-1) - pc = prof_len-1; - atomic_inc((atomic_t *)&prof_buffer[pc]); - } - } - do_timer(regs); + pc -= (unsigned long) &_stext; + pc >>= prof_shift; + /* + * Dont ignore out-of-bounds pc values silently, + * put them into the last histogram slot, so if + * present, they will show up as a sharp peak. + */ + if (pc > prof_len-1) + pc = prof_len-1; + atomic_inc((atomic_t *)&prof_buffer[pc]); + } + } /* - * If we have an externally synchronized Linux clock, then update - * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be - * called as close as possible to 500 ms before the new second starts. + * call the generic timer interrupt handling */ - read_lock (&xtime_lock); - if ((time_status & STA_UNSYNC) == 0 && - xtime.tv_sec > last_rtc_update + 660 && - xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 && - xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) { - if (set_rtc_mmss(xtime.tv_sec) == 0) - last_rtc_update = xtime.tv_sec; - else - last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ - } - /* As we return to user mode fire off the other CPU schedulers.. this is - basically because we don't yet share IRQ's around. This message is - rigged to be safe on the 386 - basically it's a hack, so don't look - closely for now.. */ - /*smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0); */ - read_unlock (&xtime_lock); -} + do_timer(regs); -static inline void -r4k_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) -{ - unsigned int count; + /* + * If we have an externally synchronized Linux clock, then update + * CMOS clock accordingly every ~11 minutes. rtc_set_time() has to be + * called as close as possible to 500 ms before the new second starts. + */ + read_lock (&xtime_lock); + if ((time_status & STA_UNSYNC) == 0 && + xtime.tv_sec > last_rtc_update + 660 && + xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 && + xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) { + + if (rtc_set_time(xtime.tv_sec) == 0) { + last_rtc_update = xtime.tv_sec; + } else { + last_rtc_update = xtime.tv_sec - 600; + /* do it again in 60 s */ + } + } + read_unlock (&xtime_lock); /* - * The cycle counter is only 32 bit which is good for about - * a minute at current count rates of upto 150MHz or so. - */ - count = read_32bit_cp0_register(CP0_COUNT); - timerhi += (count < timerlo); /* Wrap around */ - timerlo = count; - -#ifdef CONFIG_SGI_IP22 - /* Since we don't get anything but r4k timer interrupts, we need to - * set this up so that we'll get one next time. Fortunately since we - * have timerhi/timerlo, we don't care so much if we miss one. So - * we need only ask for the next in r4k_interval counts. On other - * archs we have a real timer, so we don't want this. - */ - write_32bit_cp0_register (CP0_COMPARE, - (unsigned long) (count + r4k_interval)); - kstat.irqs[0][irq]++; -#endif - - timer_interrupt(irq, dev_id, regs); - - if (!jiffies) - { - /* - * If jiffies has overflowed in this timer_interrupt we must - * update the timer[hi]/[lo] to make do_fast_gettimeoffset() - * quotient calc still valid. -arca - */ - timerhi = timerlo = 0; - } + * If jiffies has overflowed in this timer_interrupt we must + * update the timer[hi]/[lo] to make fast gettimeoffset funcs + * quotient calc still valid. -arca + */ + if (!jiffies) { + timerhi = timerlo = 0; + } } -void indy_r4k_timer_interrupt (struct pt_regs *regs) +asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs) { - static const int INDY_R4K_TIMER_IRQ = 7; - r4k_timer_interrupt (INDY_R4K_TIMER_IRQ, NULL, regs); -} + int cpu = smp_processor_id(); -char cyclecounter_available; + irq_enter(cpu, irq); + kstat.irqs[cpu][irq]++; -static inline void init_cycle_counter(void) -{ - switch(mips_cputype) { - case CPU_UNKNOWN: - case CPU_R2000: - case CPU_R3000: - case CPU_R3000A: - case CPU_R3041: - case CPU_R3051: - case CPU_R3052: - case CPU_R3081: - case CPU_R3081E: - case CPU_R6000: - case CPU_R6000A: - case CPU_R8000: /* Not shure about that one, play safe */ - cyclecounter_available = 0; - break; - case CPU_R4000PC: - case CPU_R4000SC: - case CPU_R4000MC: - case CPU_R4200: - case CPU_R4400PC: - case CPU_R4400SC: - case CPU_R4400MC: - case CPU_R4600: - case CPU_R10000: - case CPU_R4300: - case CPU_R4650: - case CPU_R4700: - case CPU_R5000: - case CPU_R5000A: - case CPU_R4640: - case CPU_NEVADA: - cyclecounter_available = 1; - break; - } -} + /* we keep interrupt disabled all the time */ + timer_interrupt(irq, NULL, regs); + + irq_exit(cpu, irq); -struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, 0, - "timer", NULL, NULL}; + /* check for bottom half */ + if (softirq_active(cpu)&softirq_mask(cpu)) + do_softirq(); +} -void (*board_time_init)(struct irqaction *irq); +/* + * time_init() - it does the following things. + * + * 1) board_time_init() - + * a) (optional) set up RTC routines, + * b) (optional) calibrate and set the mips_counter_frequency + * (only needed if you intended to use fixed_rate_gettimeoffset + * or use cpu counter as timer interrupt source) + * 2) setup xtime based on rtc_get_time(). + * 3) choose a appropriate gettimeoffset routine. + * 4) calculate a couple of cached variables for later usage + * 5) board_timer_setup() - + * a) (optional) over-write any choices made above by time_init(). + * b) machine specific code should setup the timer irqaction. + * c) enable the timer interrupt + */ + +void (*board_time_init)(void) = NULL; +void (*board_timer_setup)(struct irqaction *irq) = NULL; + +unsigned int mips_counter_frequency = 0; + +static struct irqaction timer_irqaction = { + timer_interrupt, + SA_INTERRUPT, + 0, + "timer", + NULL, + NULL}; void __init time_init(void) { - unsigned int epoch = 0, year, mon, day, hour, min, sec; - int i; + printk("New MIPS time_init() invoked.\n"); - /* The Linux interpretation of the CMOS clock register contents: - * When the Update-In-Progress (UIP) flag goes from 1 to 0, the - * RTC registers show the second which has precisely just started. - * Let's hope other operating systems interpret the RTC the same way. - */ - /* read RTC exactly on falling edge of update flag */ - for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */ - if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) - break; - for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */ - if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) - break; - do { /* Isn't this overkill ? UIP above should guarantee consistency */ - sec = CMOS_READ(RTC_SECONDS); - min = CMOS_READ(RTC_MINUTES); - hour = CMOS_READ(RTC_HOURS); - day = CMOS_READ(RTC_DAY_OF_MONTH); - mon = CMOS_READ(RTC_MONTH); - year = CMOS_READ(RTC_YEAR); - } while (sec != CMOS_READ(RTC_SECONDS)); - if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - { - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); - } - - /* Attempt to guess the epoch. This is the same heuristic as in rtc.c so - no stupid things will happen to timekeeping. Who knows, maybe Ultrix - also uses 1952 as epoch ... */ - if (year > 10 && year < 44) { - epoch = 1980; - } else if (year < 96) { - epoch = 1952; - } - year += epoch; + if (board_time_init) + board_time_init(); - write_lock_irq (&xtime_lock); - xtime.tv_sec = mktime(year, mon, day, hour, min, sec); + /* setup xtime */ + write_lock_irq(&xtime_lock); + xtime.tv_sec = rtc_get_time(); xtime.tv_usec = 0; - write_unlock_irq (&xtime_lock); - - init_cycle_counter(); + write_unlock_irq(&xtime_lock); - if (cyclecounter_available) { - write_32bit_cp0_register(CP0_COUNT, 0); - do_gettimeoffset = do_fast_gettimeoffset; - irq0.handler = r4k_timer_interrupt; - } - - board_time_init(&irq0); + /* choose appropriate gettimeoffset routine */ + if ( ! (mips_cpu.options & MIPS_CPU_COUNTER) ) { + /* no cpu counter - sorry */ + do_gettimeoffset = null_gettimeoffset; + } else if (mips_counter_frequency != 0) { + /* we have cpu counter and know counter frequency! */ + do_gettimeoffset = fixed_rate_gettimeoffset; + } else if ((mips_cpu.isa_level == MIPS_CPU_ISA_M32) || + (mips_cpu.isa_level == MIPS_CPU_ISA_I) || + (mips_cpu.isa_level == MIPS_CPU_ISA_II) ) { + /* we need to calibrate the counter but we don't have + * 64-bit division. */ + do_gettimeoffset = calibrate_div32_gettimeoffset; + } else { + /* we need to calibrate the counter but we *do* have + * 64-bit division. */ + do_gettimeoffset = calibrate_div64_gettimeoffset; + } + + /* caclulate cache parameters */ + if (mips_counter_frequency) { + cycles_per_jiffy = mips_counter_frequency / HZ; + + /* sll32_usecs_per_cycle = 10^6 * 2^32 / mips_counter_freq */ + /* any better way to do this? */ + sll32_usecs_per_cycle = mips_counter_frequency / 100000; + sll32_usecs_per_cycle = 0xffffffff / sll32_usecs_per_cycle; + sll32_usecs_per_cycle *= 10; + + MIPS_DEBUG(printk("cycles_per_jiffy = %d\n", + cycles_per_jiffy)); + MIPS_DEBUG(printk("sll32_usecs_per_cycle = %d \n", + sll32_usecs_per_cycle)); + } + + /* + * Call board specific timer interrupt setup. + * + * this pointer must be setup in machine setup routine. + * + * Even if the machine choose to use low-level timer interrupt, + * it still needs to setup the timer_irqaction. + * In that case, it might be better to set timer_irqaction.handler + * to be NULL function so that we are sure the high-level code + * is not invoked accidentally. + */ + MIPS_ASSERT(board_timer_setup != NULL); + board_timer_setup(&timer_irqaction); } diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/traps.c linux/arch/mips/kernel/traps.c --- v2.4.5/linux/arch/mips/kernel/traps.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/kernel/traps.c Mon Jul 2 13:56:40 2001 @@ -32,6 +32,9 @@ #include #include #include +#ifndef CONFIG_MIPS_FPU_EMULATOR +#include +#endif /* * Machine specific interrupt handlers @@ -90,9 +93,9 @@ #define RT 0x001f0000 #define OFFSET 0x0000ffff #define LL 0xc0000000 -#define SC 0xd0000000 +#define SC 0xe0000000 -#define DEBUG_LLSC +#undef DEBUG_LLSC #endif /* @@ -268,9 +271,6 @@ /* * Assume it would be too dangerous to continue ... */ -/* XXX */ -printk("Got Bus Error at %08x\n", (unsigned int)regs->cp0_epc); -show_regs(regs); while(1); force_sig(SIGBUS, current); } @@ -410,7 +410,7 @@ epc = (unsigned int *) (unsigned long) regs->cp0_epc; if (regs->cp0_cause & CAUSEF_BD) - epc += 4; + epc++; if (verify_area(VERIFY_READ, epc, 4)) { force_sig(SIGSEGV, current); @@ -423,6 +423,7 @@ void do_bp(struct pt_regs *regs) { + siginfo_t info; unsigned int opcode, bcode; /* @@ -491,48 +492,69 @@ #if !defined(CONFIG_CPU_HAS_LLSC) +#ifdef CONFIG_SMP +#error "ll/sc emulation is not SMP safe" +#endif + /* * userland emulation for R2300 CPUs * needed for the multithreading part of glibc + * + * this implementation can handle only sychronization between 2 or more + * user contexts and is not SMP safe. */ void do_ri(struct pt_regs *regs) { unsigned int opcode; + if (!user_mode(regs)) + BUG(); + if (!get_insn_opcode(regs, &opcode)) { - if ((opcode & OPCODE) == LL) + if ((opcode & OPCODE) == LL) { simulate_ll(regs, opcode); - if ((opcode & OPCODE) == SC) + return; + } + if ((opcode & OPCODE) == SC) { simulate_sc(regs, opcode); - } else { - printk("[%s:%d] Illegal instruction at %08lx ra=%08lx\n", - current->comm, current->pid, regs->cp0_epc, regs->regs[31]); + return; + } } + printk("[%s:%d] Illegal instruction %08lx at %08lx, ra=%08lx, CP0_STATUS=%08lx\n", + current->comm, current->pid, *((unsigned long*)regs->cp0_epc), regs->cp0_epc, + regs->regs[31], regs->cp0_status); if (compute_return_epc(regs)) return; force_sig(SIGILL, current); } /* - * the ll_bit will be cleared by r2300_switch.S + * The ll_bit is cleared by r*_switch.S */ -unsigned long ll_bit, *lladdr; - + +unsigned long ll_bit; +#ifdef CONFIG_PROC_FS +extern unsigned long ll_ops; +extern unsigned long sc_ops; +#endif + +static struct task_struct *ll_task = NULL; + void simulate_ll(struct pt_regs *regp, unsigned int opcode) { - unsigned long *addr, *vaddr; + unsigned long value, *vaddr; long offset; - + int signal = 0; + /* * analyse the ll instruction that just caused a ri exception * and put the referenced address to addr. */ + /* sign extend offset */ offset = opcode & OFFSET; - if (offset & 0x00008000) - offset = -(offset & 0x00007fff); - else - offset = (offset & 0x00007fff); + offset <<= 16; + offset >>= 16; vaddr = (unsigned long *)((long)(regp->regs[(opcode & BASE) >> 21]) + offset); @@ -540,31 +562,44 @@ printk("ll: vaddr = 0x%08x, reg = %d\n", (unsigned int)vaddr, (opcode & RT) >> 16); #endif - /* - * TODO: compute physical address from vaddr - */ - panic("ll: emulation not yet finished!"); +#ifdef CONFIG_PROC_FS + ll_ops++; +#endif - lladdr = addr; - ll_bit = 1; - regp->regs[(opcode & RT) >> 16] = *addr; + if ((unsigned long)vaddr & 3) + signal = SIGBUS; + else if (get_user(value, vaddr)) + signal = SIGSEGV; + else { + if (ll_task == NULL || ll_task == current) { + ll_bit = 1; + } else { + ll_bit = 0; + } + ll_task = current; + regp->regs[(opcode & RT) >> 16] = value; + } + if (compute_return_epc(regp)) + return; + if (signal) + send_sig(signal, current, 1); } - + void simulate_sc(struct pt_regs *regp, unsigned int opcode) { - unsigned long *addr, *vaddr, reg; + unsigned long *vaddr, reg; long offset; + int signal = 0; /* * analyse the sc instruction that just caused a ri exception * and put the referenced address to addr. */ + /* sign extend offset */ offset = opcode & OFFSET; - if (offset & 0x00008000) - offset = -(offset & 0x00007fff); - else - offset = (offset & 0x00007fff); + offset <<= 16; + offset >>= 16; vaddr = (unsigned long *)((long)(regp->regs[(opcode & BASE) >> 21]) + offset); reg = (opcode & RT) >> 16; @@ -573,28 +608,34 @@ printk("sc: vaddr = 0x%08x, reg = %d\n", (unsigned int)vaddr, (unsigned int)reg); #endif - /* - * TODO: compute physical address from vaddr - */ - panic("sc: emulation not yet finished!"); - - lladdr = addr; +#ifdef CONFIG_PROC_FS + sc_ops++; +#endif - if (ll_bit == 0) { + if ((unsigned long)vaddr & 3) + signal = SIGBUS; + else if (ll_bit == 0 || ll_task != current) regp->regs[reg] = 0; + else if (put_user(regp->regs[reg], vaddr)) + signal = SIGSEGV; + else + regp->regs[reg] = 1; + if (compute_return_epc(regp)) return; - } - - *addr = regp->regs[reg]; - regp->regs[reg] = 1; + if (signal) + send_sig(signal, current, 1); } #else /* MIPS 2 or higher */ void do_ri(struct pt_regs *regs) { - printk("[%s:%d] Illegal instruction at %08lx ra=%08lx\n", - current->comm, current->pid, regs->cp0_epc, regs->regs[31]); + unsigned int opcode; + + get_insn_opcode(regs, &opcode); + printk("[%s:%ld] Illegal instruction %08x at %08lx ra=%08lx\n", + current->comm, (unsigned long)current->pid, opcode, + regs->cp0_epc, regs->regs[31]); if (compute_return_epc(regs)) return; force_sig(SIGILL, current); @@ -662,50 +703,101 @@ panic("Caught WATCH exception - probably caused by stack overflow."); } +void do_mcheck(struct pt_regs *regs) +{ + show_regs(regs); + panic("Caught Machine Check exception - probably caused by multiple " + "matching entries in the TLB."); +} + void do_reserved(struct pt_regs *regs) { /* - * Game over - no way to handle this if it ever occurs. - * Most probably caused by a new unknown cpu type or - * after another deadly hard/software error. + * Game over - no way to handle this if it ever occurs. Most probably + * caused by a new unknown cpu type or after another deadly + * hard/software error. */ + show_regs(regs); panic("Caught reserved exception - should not happen."); } -static inline void watch_init(unsigned long cputype) +static inline void watch_init(void) { - switch(cputype) { - case CPU_R10000: - case CPU_R4000MC: - case CPU_R4400MC: - case CPU_R4000SC: - case CPU_R4400SC: - case CPU_R4000PC: - case CPU_R4400PC: - case CPU_R4200: - case CPU_R4300: - set_except_vector(23, handle_watch); - watch_available = 1; - break; - } + if(mips_cpu.options & MIPS_CPU_WATCH ) { + (void)set_except_vector(23, handle_watch); + watch_available = 1; + } } /* * Some MIPS CPUs have a dedicated interrupt vector which reduces the * interrupt processing overhead. Use it where available. - * FIXME: more CPUs than just the Nevada have this feature. */ static inline void setup_dedicated_int(void) { extern void except_vec4(void); - switch(mips_cputype) { - case CPU_NEVADA: + + if(mips_cpu.options & MIPS_CPU_DIVEC) { memcpy((void *)(KSEG0 + 0x200), except_vec4, 8); - set_cp0_cause(CAUSEF_IV, CAUSEF_IV); + set_cp0_cause(CAUSEF_IV); dedicated_iv_available = 1; } } +/* + * Some MIPS CPUs can enable/disable for cache parity detection, but does + * it different ways. + */ +static inline void parity_protection_init(void) +{ + switch(mips_cpu.cputype) { + case CPU_5KC: + /* Set the PE bit (bit 31) in the CP0_ECC register. */ + printk(KERN_INFO "Enable the cache parity protection for " + "MIPS 5KC CPUs.\n"); + write_32bit_cp0_register(CP0_ECC, + read_32bit_cp0_register(CP0_ECC) + | 0x80000000); + break; + default: + break; + } +} + +void cache_parity_error(void) +{ + unsigned int reg_val; + + /* For the moment, report the problem and hang. */ + reg_val = read_32bit_cp0_register(CP0_ERROREPC); + printk("Cache error exception:\n"); + printk("cp0_errorepc == %08x\n", reg_val); + reg_val = read_32bit_cp0_register(CP0_CACHEERR); + printk("cp0_cacheerr == %08x\n", reg_val); + + printk("Decoded CP0_CACHEERR: %s cache fault in %s reference.\n", + reg_val&(1<<30)?"secondary":"primary", + reg_val&(1<<31)?"data":"insn"); + printk("Error bits: %s%s%s%s%s%s%s\n", + reg_val&(1<<29)?"ED ":"", + reg_val&(1<<28)?"ET ":"", + reg_val&(1<<26)?"EE ":"", + reg_val&(1<<25)?"EB ":"", + reg_val&(1<<24)?"EI ":"", + reg_val&(1<<23)?"E1 ":"", + reg_val&(1<<22)?"E0 ":""); + printk("IDX: 0x%08x\n", reg_val&((1<<22)-1)); + + if (reg_val&(1<<22)) + printk("DErrAddr0: 0x%08x\n", read_32bit_cp0_set1_register(CP0_S1_DERRADDR0)); + + if (reg_val&(1<<23)) + printk("DErrAddr1: 0x%08x\n", read_32bit_cp0_set1_register(CP0_S1_DERRADDR1)); + + + panic("Can't handle the cache error - panic!"); +} + unsigned long exception_handlers[32]; /* @@ -713,23 +805,36 @@ * to interrupt handlers in the address range from * KSEG0 <= x < KSEG0 + 256mb on the Nevada. Oh well ... */ -void set_except_vector(int n, void *addr) +void *set_except_vector(int n, void *addr) { unsigned handler = (unsigned long) addr; + unsigned old_handler = exception_handlers[n]; exception_handlers[n] = handler; if (n == 0 && dedicated_iv_available) { *(volatile u32 *)(KSEG0+0x200) = 0x08000000 | (0x03ffffff & (handler >> 2)); flush_icache_range(KSEG0+0x200, KSEG0 + 0x204); } + return (void *)old_handler; } +asmlinkage int (*save_fp_context)(struct sigcontext *sc); +asmlinkage int (*restore_fp_context)(struct sigcontext *sc); +extern asmlinkage int _save_fp_context(struct sigcontext *sc); +extern asmlinkage int _restore_fp_context(struct sigcontext *sc); + +#ifdef CONFIG_MIPS_FPU_EMULATOR +extern asmlinkage int fpu_emulator_save_context(struct sigcontext *sc); +extern asmlinkage int fpu_emulator_restore_context(struct sigcontext *sc); +#endif + void __init trap_init(void) { extern char except_vec0_nevada, except_vec0_r4000; extern char except_vec0_r4600, except_vec0_r2300; extern char except_vec1_generic, except_vec2_generic; extern char except_vec3_generic, except_vec3_r4000; + extern char except_vec_ejtag_debug; unsigned long i; if(mips_machtype == MACH_MIPS_MAGNUM_4000 || @@ -737,101 +842,121 @@ EISA_bus = 1; /* Some firmware leaves the BEV flag set, clear it. */ - set_cp0_status(ST0_BEV, 0); + clear_cp0_status(ST0_BEV); /* Copy the generic exception handler code to it's final destination. */ memcpy((void *)(KSEG0 + 0x80), &except_vec1_generic, 0x80); memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, 0x80); memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x80); - + flush_icache_range(KSEG0 + 0x80, KSEG0 + 0x200); /* * Setup default vectors */ for(i = 0; i <= 31; i++) - set_except_vector(i, handle_reserved); + (void)set_except_vector(i, handle_reserved); + + /* + * Copy the EJTAG debug exception vector handler code to it's final + * destination. + */ + memcpy((void *)(KSEG0 + 0x300), &except_vec_ejtag_debug, 0x80); /* * Only some CPUs have the watch exceptions or a dedicated * interrupt vector. */ - watch_init(mips_cputype); + watch_init(); setup_dedicated_int(); - set_except_vector(1, handle_mod); - set_except_vector(2, handle_tlbl); - set_except_vector(3, handle_tlbs); - set_except_vector(4, handle_adel); - set_except_vector(5, handle_ades); + /* + * Some CPUs can enable/disable for cache parity detection, but does + * it different ways. + */ + parity_protection_init(); + + (void)set_except_vector(1, handle_mod); + (void)set_except_vector(2, handle_tlbl); + (void)set_except_vector(3, handle_tlbs); + (void)set_except_vector(4, handle_adel); + (void)set_except_vector(5, handle_ades); /* * The Data Bus Error/ Instruction Bus Errors are signaled * by external hardware. Therefore these two expection have * board specific handlers. */ - set_except_vector(6, handle_ibe); - set_except_vector(7, handle_dbe); + (void)set_except_vector(6, handle_ibe); + (void)set_except_vector(7, handle_dbe); ibe_board_handler = default_be_board_handler; dbe_board_handler = default_be_board_handler; - set_except_vector(8, handle_sys); - set_except_vector(9, handle_bp); - set_except_vector(10, handle_ri); - set_except_vector(11, handle_cpu); - set_except_vector(12, handle_ov); - set_except_vector(13, handle_tr); - set_except_vector(15, handle_fpe); - + (void)set_except_vector(8, handle_sys); + (void)set_except_vector(9, handle_bp); + (void)set_except_vector(10, handle_ri); + (void)set_except_vector(11, handle_cpu); + (void)set_except_vector(12, handle_ov); + (void)set_except_vector(13, handle_tr); + (void)set_except_vector(15, handle_fpe); + /* * Handling the following exceptions depends mostly of the cpu type */ - switch(mips_cputype) { - case CPU_R10000: - /* - * The R10000 is in most aspects similar to the R4400. It - * should get some special optimizations. - */ - write_32bit_cp0_register(CP0_FRAMEMASK, 0); - set_cp0_status(ST0_XX, ST0_XX); - /* - * The R10k might even work for Linux/MIPS - but we're paranoid - * and refuse to run until this is tested on real silicon - */ - panic("CPU too expensive - making holiday in the ANDES!"); - break; - case CPU_R4000MC: - case CPU_R4400MC: - case CPU_R4000SC: - case CPU_R4400SC: - vce_available = 1; - /* Fall through ... */ - case CPU_R4000PC: - case CPU_R4400PC: - case CPU_R4200: - case CPU_R4300: - /* case CPU_R4640: */ - case CPU_R4600: - case CPU_R5000: - case CPU_NEVADA: - if(mips_cputype == CPU_NEVADA) { + if ((mips_cpu.options & MIPS_CPU_4KEX) + && (mips_cpu.options & MIPS_CPU_4KTLB)) { + if(mips_cpu.cputype == CPU_NEVADA) { memcpy((void *)KSEG0, &except_vec0_nevada, 0x80); - } else if (mips_cputype == CPU_R4600) + } else if (mips_cpu.cputype == CPU_R4600) memcpy((void *)KSEG0, &except_vec0_r4600, 0x80); else memcpy((void *)KSEG0, &except_vec0_r4000, 0x80); /* Cache error vector already set above. */ - if (vce_available) { + if (mips_cpu.options & MIPS_CPU_VCE) { memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000, 0x80); } else { memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x80); } - break; + if(mips_cpu.options & MIPS_CPU_FPU) { + save_fp_context = _save_fp_context; + restore_fp_context = _restore_fp_context; +#ifdef CONFIG_MIPS_FPU_EMULATOR + } else { + save_fp_context = fpu_emulator_save_context; + restore_fp_context = fpu_emulator_restore_context; +#endif + } + } else switch(mips_cpu.cputype) { + case CPU_R10000: + /* + * The R10000 is in most aspects similar to the R4400. It + * should get some special optimizations. + */ + write_32bit_cp0_register(CP0_FRAMEMASK, 0); + set_cp0_status(ST0_XX); + /* + * The R10k might even work for Linux/MIPS - but we're paranoid + * and refuse to run until this is tested on real silicon + */ + panic("CPU too expensive - making holiday in the ANDES!"); + break; + case CPU_SB1: + /* XXX - This should be folded in to the "cleaner" handling, above */ + memcpy((void *)KSEG0, &except_vec0_r4000, 0x80); + memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000, 0x80); + save_fp_context = _save_fp_context; + restore_fp_context = _restore_fp_context; + /* Enable timer interrupt and scd mapped interrupt in status register */ + clear_cp0_status(0xf000); + set_cp0_status(0xc00); + break; case CPU_R6000: case CPU_R6000A: -#if 0 + save_fp_context = _save_fp_context; + restore_fp_context = _restore_fp_context; + /* * The R6000 is the only R-series CPU that features a machine * check exception (similar to the R4000 cache error) and @@ -840,9 +965,8 @@ * current list of targets for Linux/MIPS. * (Duh, crap, there is someone with a tripple R6k machine) */ - set_except_vector(14, handle_mc); - set_except_vector(15, handle_ndc); -#endif + //set_except_vector(14, handle_mc); + //set_except_vector(15, handle_ndc); case CPU_R2000: case CPU_R3000: case CPU_R3000A: @@ -851,12 +975,17 @@ case CPU_R3052: case CPU_R3081: case CPU_R3081E: + case CPU_TX3912: + case CPU_TX3922: + case CPU_TX3927: + save_fp_context = _save_fp_context; + restore_fp_context = _restore_fp_context; memcpy((void *)KSEG0, &except_vec0_r2300, 0x80); memcpy((void *)(KSEG0 + 0x80), &except_vec3_generic, 0x80); break; case CPU_R8000: printk("Detected unsupported CPU type %s.\n", - cpu_names[mips_cputype]); + cpu_names[mips_cpu.cputype]); panic("Can't handle CPU"); break; @@ -868,5 +997,6 @@ atomic_inc(&init_mm.mm_count); /* XXX UP? */ current->active_mm = &init_mm; - current_pgd = init_mm.pgd; + write_32bit_cp0_register(CP0_CONTEXT, smp_processor_id()<<23); + current_pgd[0] = init_mm.pgd; } diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/unaligned.c linux/arch/mips/kernel/unaligned.c --- v2.4.5/linux/arch/mips/kernel/unaligned.c Sat May 13 08:29:14 2000 +++ linux/arch/mips/kernel/unaligned.c Mon Jul 2 13:56:40 2001 @@ -1,5 +1,4 @@ -/* $Id: unaligned.c,v 1.7 1999/12/04 03:59:00 ralf Exp $ - * +/* * Handle unaligned accesses by emulation. * * This file is subject to the terms and conditions of the GNU General Public @@ -83,6 +82,7 @@ #include #include #include +#include #define STR(x) __STR(x) #define __STR(x) #x @@ -91,8 +91,8 @@ * User code may only access USEG; kernel code may access the * entire address space. */ -#define check_axs(p,a,s) \ - if ((long)(~(pc) & ((a) | ((a)+(s)))) < 0) \ +#define check_axs(pc,a,s) \ + if ((long)(~(pc) & ((a) | ((a)+(s)))) < 0) \ goto sigbus; static inline void @@ -365,12 +365,15 @@ return; } + die_if_kernel ("Unhandled kernel unaligned access", regs); send_sig(SIGSEGV, current, 1); return; sigbus: + die_if_kernel ("Unhandled kernel unaligned access", regs); send_sig(SIGBUS, current, 1); return; sigill: + die_if_kernel ("Unhandled kernel unaligned access or invalid instruction", regs); send_sig(SIGILL, current, 1); return; } @@ -380,6 +383,21 @@ asmlinkage void do_ade(struct pt_regs *regs) { unsigned long pc; +#ifdef CONFIG_MIPS_FPU_EMULATOR + extern int do_dsemulret(struct pt_regs *); + + /* + * Address errors may be deliberately induced + * by the FPU emulator to take retake control + * of the CPU after executing the instruction + * in the delay slot of an emulated branch. + */ + + if((unsigned long)regs->cp0_epc == current->thread.dsemul_aerpc) { + (void)do_dsemulret(regs); + return; + } +#endif /* CONFIG_MIPS_FPU_EMULATOR */ /* * Did we catch a fault trying to load an instruction? @@ -401,6 +419,7 @@ return; sigbus: + die_if_kernel ("Kernel unaligned instruction access", regs); force_sig(SIGBUS, current); return; diff -u --recursive --new-file v2.4.5/linux/arch/mips/ld.script.big linux/arch/mips/ld.script.big --- v2.4.5/linux/arch/mips/ld.script.big Wed Jul 12 15:14:41 2000 +++ linux/arch/mips/ld.script.big Wed Dec 31 16:00:00 1969 @@ -1,120 +0,0 @@ -OUTPUT_FORMAT("elf32-bigmips") -OUTPUT_ARCH(mips) -ENTRY(kernel_entry) -SECTIONS -{ - /* Read-only sections, merged into text segment: */ - . = 0x80000000; - .init : { *(.init) } =0 - .text : - { - _ftext = . ; - *(.text) - *(.rodata) - *(.rodata1) - /* .gnu.warning sections are handled specially by elf32.em. */ - *(.gnu.warning) - } =0 - _etext = .; - PROVIDE (etext = .); - - . = ALIGN(8192); - .data.init_task : { *(.data.init_task) } - - /* Startup code */ - . = ALIGN(4096); - __init_begin = .; - .text.init : { *(.text.init) } - .data.init : { *(.data.init) } - . = ALIGN(16); - __setup_start = .; - .setup.init : { *(.setup.init) } - __setup_end = .; - __initcall_start = .; - .initcall.init : { *(.initcall.init) } - __initcall_end = .; - . = ALIGN(4096); /* Align double page for init_task_union */ - __init_end = .; - - . = ALIGN(4096); - .data.page_aligned : { *(.data.idt) } - - . = ALIGN(32); - .data.cacheline_aligned : { *(.data.cacheline_aligned) } - - .fini : { *(.fini) } =0 - .reginfo : { *(.reginfo) } - /* Adjust the address for the data segment. We want to adjust up to - the same address within the page on the next page up. It would - be more correct to do this: - . = .; - The current expression does not correctly handle the case of a - text segment ending precisely at the end of a page; it causes the - data segment to skip a page. The above expression does not have - this problem, but it will currently (2/95) cause BFD to allocate - a single segment, combining both text and data, for this case. - This will prevent the text segment from being shared among - multiple executions of the program; I think that is more - important than losing a page of the virtual address space (note - that no actual memory is lost; the page which is skipped can not - be referenced). */ - . = .; - .data : - { - _fdata = . ; - *(.data) - CONSTRUCTORS - } - .data1 : { *(.data1) } - _gp = . + 0x8000; - .lit8 : { *(.lit8) } - .lit4 : { *(.lit4) } - .ctors : { *(.ctors) } - .dtors : { *(.dtors) } - .got : { *(.got.plt) *(.got) } - .dynamic : { *(.dynamic) } - /* We want the small data sections together, so single-instruction offsets - can access them all, and initialized data all before uninitialized, so - we can shorten the on-disk segment size. */ - .sdata : { *(.sdata) } - _edata = .; - PROVIDE (edata = .); - - __bss_start = .; - _fbss = .; - .sbss : { *(.sbss) *(.scommon) } - .bss : - { - *(.dynbss) - *(.bss) - *(COMMON) - _end = . ; - PROVIDE (end = .); - } - - /* Sections to be discarded */ - /DISCARD/ : - { - *(.text.exit) - *(.data.exit) - *(.exitcall.exit) - } - - /* These are needed for ELF backends which have not yet been - converted to the new style linker. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - /* DWARF debug sections. - Symbols in the .debug DWARF section are relative to the beginning of the - section so we begin .debug at 0. It's not clear yet what needs to happen - for the others. */ - .debug 0 : { *(.debug) } - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - .debug_sfnames 0 : { *(.debug_sfnames) } - .line 0 : { *(.line) } - /* These must appear regardless of . */ - .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) } - .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) } -} diff -u --recursive --new-file v2.4.5/linux/arch/mips/ld.script.in linux/arch/mips/ld.script.in --- v2.4.5/linux/arch/mips/ld.script.in Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/ld.script.in Mon Jul 2 13:56:40 2001 @@ -0,0 +1,147 @@ +OUTPUT_ARCH(mips) +ENTRY(kernel_entry) +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = @@LOADADDR@@; + .init : { *(.init) } =0 + .text : + { + _ftext = . ; + *(.text) + *(.rodata) + *(.rodata1) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + } =0 + .kstrtab : { *(.kstrtab) } + + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + __start___dbe_table = .; /* Exception table for data bus errors */ + __dbe_table : { *(__dbe_table) } + __stop___dbe_table = .; + + __start___ksymtab = .; /* Kernel symbol table */ + __ksymtab : { *(__ksymtab) } + __stop___ksymtab = .; + + _etext = .; + + . = ALIGN(8192); + .data.init_task : { *(.data.init_task) } + + /* Startup code */ + . = ALIGN(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(16); + __setup_start = .; + .setup.init : { *(.setup.init) } + __setup_end = .; + __initcall_start = .; + .initcall.init : { *(.initcall.init) } + __initcall_end = .; + . = ALIGN(4096); /* Align double page for init_task_union */ + __init_end = .; + + . = ALIGN(4096); + .data.page_aligned : { *(.data.idt) } + + . = ALIGN(32); + .data.cacheline_aligned : { *(.data.cacheline_aligned) } + + .fini : { *(.fini) } =0 + .reginfo : { *(.reginfo) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. It would + be more correct to do this: + . = .; + The current expression does not correctly handle the case of a + text segment ending precisely at the end of a page; it causes the + data segment to skip a page. The above expression does not have + this problem, but it will currently (2/95) cause BFD to allocate + a single segment, combining both text and data, for this case. + This will prevent the text segment from being shared among + multiple executions of the program; I think that is more + important than losing a page of the virtual address space (note + that no actual memory is lost; the page which is skipped can not + be referenced). */ + . = .; + .data : + { + _fdata = . ; + *(.data) + + /* Align the initial ramdisk image (INITRD) on page boundaries. */ + . = ALIGN(4096); + __rd_start = .; + *(.initrd) + __rd_end = .; + . = ALIGN(4096); + + CONSTRUCTORS + } + .data1 : { *(.data1) } + _gp = . + 0x8000; + .lit8 : { *(.lit8) } + .lit4 : { *(.lit4) } + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + .got : { *(.got.plt) *(.got) } + .dynamic : { *(.dynamic) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : { *(.sdata) } + . = ALIGN(4); + _edata = .; + PROVIDE (edata = .); + + __bss_start = .; + _fbss = .; + .sbss : { *(.sbss) *(.scommon) } + .bss : + { + *(.dynbss) + *(.bss) + *(COMMON) + . = ALIGN(4); + _end = . ; + PROVIDE (end = .); + } + + /* Sections to be discarded */ + /DISCARD/ : + { + *(.text.exit) + *(.data.exit) + *(.exitcall.exit) + } + + /* This is the MIPS specific mdebug section. */ + .mdebug : { *(.mdebug) } + /* These are needed for ELF backends which have not yet been + converted to the new style linker. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + /* DWARF debug sections. + Symbols in the .debug DWARF section are relative to the beginning of the + section so we begin .debug at 0. It's not clear yet what needs to happen + for the others. */ + .debug 0 : { *(.debug) } + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_sfnames 0 : { *(.debug_sfnames) } + .line 0 : { *(.line) } + /* These must appear regardless of . */ + .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) } + .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) } + .comment : { *(.comment) } + .note : { *(.note) } +} diff -u --recursive --new-file v2.4.5/linux/arch/mips/ld.script.little linux/arch/mips/ld.script.little --- v2.4.5/linux/arch/mips/ld.script.little Wed Jul 12 15:14:41 2000 +++ linux/arch/mips/ld.script.little Wed Dec 31 16:00:00 1969 @@ -1,120 +0,0 @@ -OUTPUT_FORMAT("elf32-littlemips") -OUTPUT_ARCH(mips) -ENTRY(kernel_entry) -SECTIONS -{ - /* Read-only sections, merged into text segment: */ - . = 0x80000000; - .init : { *(.init) } =0 - .text : - { - _ftext = . ; - *(.text) - *(.rodata) - *(.rodata1) - /* .gnu.warning sections are handled specially by elf32.em. */ - *(.gnu.warning) - } =0 - _etext = .; - PROVIDE (etext = .); - - . = ALIGN(8192); - .data.init_task : { *(.data.init_task) } - - /* Startup code */ - . = ALIGN(4096); - __init_begin = .; - .text.init : { *(.text.init) } - .data.init : { *(.data.init) } - . = ALIGN(16); - __setup_start = .; - .setup.init : { *(.setup.init) } - __setup_end = .; - __initcall_start = .; - .initcall.init : { *(.initcall.init) } - __initcall_end = .; - . = ALIGN(4096); /* Align double page for init_task_union */ - __init_end = .; - - . = ALIGN(4096); - .data.page_aligned : { *(.data.idt) } - - . = ALIGN(32); - .data.cacheline_aligned : { *(.data.cacheline_aligned) } - - .fini : { *(.fini) } =0 - .reginfo : { *(.reginfo) } - /* Adjust the address for the data segment. We want to adjust up to - the same address within the page on the next page up. It would - be more correct to do this: - . = .; - The current expression does not correctly handle the case of a - text segment ending precisely at the end of a page; it causes the - data segment to skip a page. The above expression does not have - this problem, but it will currently (2/95) cause BFD to allocate - a single segment, combining both text and data, for this case. - This will prevent the text segment from being shared among - multiple executions of the program; I think that is more - important than losing a page of the virtual address space (note - that no actual memory is lost; the page which is skipped can not - be referenced). */ - . = .; - .data : - { - _fdata = . ; - *(.data) - CONSTRUCTORS - } - .data1 : { *(.data1) } - _gp = . + 0x8000; - .lit8 : { *(.lit8) } - .lit4 : { *(.lit4) } - .ctors : { *(.ctors) } - .dtors : { *(.dtors) } - .got : { *(.got.plt) *(.got) } - .dynamic : { *(.dynamic) } - /* We want the small data sections together, so single-instruction offsets - can access them all, and initialized data all before uninitialized, so - we can shorten the on-disk segment size. */ - .sdata : { *(.sdata) } - _edata = .; - PROVIDE (edata = .); - - __bss_start = .; - _fbss = .; - .sbss : { *(.sbss) *(.scommon) } - .bss : - { - *(.dynbss) - *(.bss) - *(COMMON) - _end = . ; - PROVIDE (end = .); - } - - /* Sections to be discarded */ - /DISCARD/ : - { - *(.text.exit) - *(.data.exit) - *(.exitcall.exit) - } - - /* These are needed for ELF backends which have not yet been - converted to the new style linker. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - /* DWARF debug sections. - Symbols in the .debug DWARF section are relative to the beginning of the - section so we begin .debug at 0. It's not clear yet what needs to happen - for the others. */ - .debug 0 : { *(.debug) } - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - .debug_sfnames 0 : { *(.debug_sfnames) } - .line 0 : { *(.line) } - /* These must appear regardless of . */ - .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) } - .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) } -} diff -u --recursive --new-file v2.4.5/linux/arch/mips/lib/Makefile linux/arch/mips/lib/Makefile --- v2.4.5/linux/arch/mips/lib/Makefile Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/lib/Makefile Mon Jul 2 13:56:40 2001 @@ -17,11 +17,7 @@ ifdef CONFIG_CPU_R3000 obj-y += r3k_dump_tlb.o else - ifdef CONFIG_CPU_R3912 - obj-y += r3k_dump_tlb.o - else - obj-y += dump_tlb.o - endif + obj-y += dump_tlb.o endif obj-$(CONFIG_BLK_DEV_FD) += floppy-no.o floppy-std.o diff -u --recursive --new-file v2.4.5/linux/arch/mips/lib/kbd-std.c linux/arch/mips/lib/kbd-std.c --- v2.4.5/linux/arch/mips/lib/kbd-std.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/lib/kbd-std.c Mon Jul 2 13:56:40 2001 @@ -8,7 +8,6 @@ * * Copyright (C) 1998, 1999 by Ralf Baechle */ -#include #include #include #include @@ -21,7 +20,6 @@ static void std_kbd_request_region(void) { #ifdef CONFIG_MIPS_ITE8172 - printk("std_kbd_request_region\n"); request_region(0x14000060, 16, "keyboard"); #else request_region(0x60, 16, "keyboard"); @@ -30,7 +28,6 @@ static int std_kbd_request_irq(void (*handler)(int, void *, struct pt_regs *)) { - printk("std_kbd_request_irq\n"); return request_irq(KEYBOARD_IRQ, handler, 0, "keyboard", NULL); } diff -u --recursive --new-file v2.4.5/linux/arch/mips/lib/memset.S linux/arch/mips/lib/memset.S --- v2.4.5/linux/arch/mips/lib/memset.S Tue Dec 5 23:15:12 2000 +++ linux/arch/mips/lib/memset.S Mon Jul 2 13:56:40 2001 @@ -54,6 +54,7 @@ 1: EXPORT(__bzero) + .type __bzero, @function sltiu t0, a2, 4 /* very small region? */ bnez t0, small_memset andi t0, a0, 3 /* aligned? */ diff -u --recursive --new-file v2.4.5/linux/arch/mips/lib/rtc-no.c linux/arch/mips/lib/rtc-no.c --- v2.4.5/linux/arch/mips/lib/rtc-no.c Sat May 13 08:29:14 2000 +++ linux/arch/mips/lib/rtc-no.c Mon Jul 2 13:56:40 2001 @@ -1,5 +1,4 @@ -/* $Id: rtc-no.c,v 1.2 1998/06/25 20:19:15 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -7,28 +6,25 @@ * Stub RTC routines to keep Linux from crashing on machine which don't * have a RTC chip. * - * Copyright (C) 1998 by Ralf Baechle + * Copyright (C) 1998, 2001 by Ralf Baechle */ #include #include -static unsigned char no_rtc_read_data(unsigned long addr) +static unsigned int shouldnt_happen(void) { - panic("no_rtc_read_data called - shouldn't happen."); -} + static int called; -static void no_rtc_write_data(unsigned char data, unsigned long addr) -{ - panic("no_rtc_write_data called - shouldn't happen."); -} + if (!called) { + called = 1; + printk(KERN_DEBUG "RTC functions called - shouldn't happen\n"); + } -static int no_rtc_bcd_mode(void) -{ - panic("no_rtc_bcd_mode called - shouldn't happen."); + return 0; } struct rtc_ops no_rtc_ops = { - &no_rtc_read_data, - &no_rtc_write_data, - &no_rtc_bcd_mode + rtc_read_data: (void *) &shouldnt_happen, + rtc_write_data: (void *) &shouldnt_happen, + rtc_bcd_mode: (void *) &shouldnt_happen }; diff -u --recursive --new-file v2.4.5/linux/arch/mips/lib/rtc-std.c linux/arch/mips/lib/rtc-std.c --- v2.4.5/linux/arch/mips/lib/rtc-std.c Sat May 13 08:29:14 2000 +++ linux/arch/mips/lib/rtc-std.c Mon Jul 2 13:56:40 2001 @@ -1,12 +1,11 @@ -/* $Id: rtc-std.c,v 1.2 1998/06/25 20:19:16 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * RTC routines for PC style attached Dallas chip. * - * Copyright (C) 1998 by Ralf Baechle + * Copyright (C) 1998, 2001 by Ralf Baechle */ #include #include diff -u --recursive --new-file v2.4.5/linux/arch/mips/math-emu/cp1emu.c linux/arch/mips/math-emu/cp1emu.c --- v2.4.5/linux/arch/mips/math-emu/cp1emu.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/math-emu/cp1emu.c Mon Jul 2 13:56:40 2001 @@ -49,6 +49,7 @@ * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. *************************************************************************/ +#include #include #include #include diff -u --recursive --new-file v2.4.5/linux/arch/mips/math-emu/dp_sub.c linux/arch/mips/math-emu/dp_sub.c --- v2.4.5/linux/arch/mips/math-emu/dp_sub.c Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/math-emu/dp_sub.c Mon Jul 2 13:56:40 2001 @@ -176,11 +176,12 @@ xe = xe; xs = ys; } - if (xm == 0) + if (xm == 0) { if (ieee754_csr.rm == IEEE754_RD) return ieee754dp_zero(1); /* round negative inf. => sign = -1 */ else return ieee754dp_zero(0); /* other round modes => sign = 1 */ + } /* normalize to rounding precision */ diff -u --recursive --new-file v2.4.5/linux/arch/mips/mm/Makefile linux/arch/mips/mm/Makefile --- v2.4.5/linux/arch/mips/mm/Makefile Fri Apr 13 20:26:07 2001 +++ linux/arch/mips/mm/Makefile Mon Jul 2 13:56:40 2001 @@ -9,11 +9,10 @@ O_TARGET := mm.o -export-objs += umap.o -obj-y += extable.o init.o fault.o loadmmu.o +export-objs += ioremap.o umap.o +obj-y += extable.o init.o ioremap.o fault.o loadmmu.o obj-$(CONFIG_CPU_R3000) += r2300.o -obj-$(CONFIG_CPU_R3912) += r2300.o obj-$(CONFIG_CPU_R4300) += r4xx0.o obj-$(CONFIG_CPU_R4X00) += r4xx0.o obj-$(CONFIG_CPU_R5000) += r4xx0.o diff -u --recursive --new-file v2.4.5/linux/arch/mips/tools/offset.c linux/arch/mips/tools/offset.c --- v2.4.5/linux/arch/mips/tools/offset.c Thu Jul 27 18:36:54 2000 +++ linux/arch/mips/tools/offset.c Mon Jul 2 13:56:40 2001 @@ -1,12 +1,13 @@ -/* $Id: offset.c,v 1.11 1999/09/28 22:25:50 ralf Exp $ - * +/* * offset.c: Calculate pt_regs and task_struct offsets. * * Copyright (C) 1996 David S. Miller * Copyright (C) 1997, 1998, 1999 Ralf Baechle * Copyright (C) 1999 Silicon Graphics, Inc. + * + * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. */ - #include #include @@ -84,6 +85,7 @@ offset("#define TASK_COUNTER ", struct task_struct, counter); offset("#define TASK_NICE ", struct task_struct, nice); offset("#define TASK_MM ", struct task_struct, mm); + offset("#define TASK_PID ", struct task_struct, pid); size("#define TASK_STRUCT_SIZE ", struct task_struct); linefeed; } @@ -119,6 +121,10 @@ thread.irix_trampoline); offset("#define THREAD_OLDCTX ", struct task_struct, \ thread.irix_oldctx); + offset("#define THREAD_DSEEPC ", struct task_struct, \ + thread.dsemul_epc); + offset("#define THREAD_DSEAERPC ", struct task_struct, \ + thread.dsemul_aerpc); linefeed; } diff -u --recursive --new-file v2.4.5/linux/arch/mips64/ld.script.elf32.S linux/arch/mips64/ld.script.elf32.S --- v2.4.5/linux/arch/mips64/ld.script.elf32.S Tue Nov 28 21:42:04 2000 +++ linux/arch/mips64/ld.script.elf32.S Mon Jul 2 14:40:58 2001 @@ -8,6 +8,7 @@ { *(.text) *(.rodata) + *(.rodata.*) *(.rodata1) /* .gnu.warning sections are handled specially by elf32.em. */ *(.gnu.warning) diff -u --recursive --new-file v2.4.5/linux/arch/mips64/ld.script.elf64 linux/arch/mips64/ld.script.elf64 --- v2.4.5/linux/arch/mips64/ld.script.elf64 Tue Nov 28 21:42:04 2000 +++ linux/arch/mips64/ld.script.elf64 Mon Jul 2 14:40:58 2001 @@ -18,6 +18,7 @@ .text : { *(.text) *(.rodata) + *(.rodata.*) *(.rodata1) /* .gnu.warning sections are handled specially by elf32.em. */ *(.gnu.warning) diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/Makefile linux/arch/mips64/math-emu/Makefile --- v2.4.5/linux/arch/mips64/math-emu/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/Makefile Mon Jul 2 13:56:40 2001 @@ -0,0 +1,24 @@ +# +# Makefile for the Linux/MIPS kernel FPU emulation. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +EXTRA_ASFLAGS = -mips2 -mcpu=r4000 + +O_TARGET:= fpu_emulator.o + +obj-y := cp1emu.o ieee754m.o ieee754d.o ieee754dp.o ieee754sp.o ieee754.o \ + ieee754xcpt.o dp_frexp.o dp_modf.o dp_div.o dp_mul.o dp_sub.o \ + dp_add.o dp_fsp.o dp_cmp.o dp_logb.o dp_scalb.o dp_simple.o \ + dp_tint.o dp_fint.o dp_tlong.o dp_flong.o sp_frexp.o sp_modf.o \ + sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_logb.o \ + sp_scalb.o sp_simple.o sp_tint.o sp_fint.o sp_tlong.o sp_flong.o \ + dp_sqrt.o sp_sqrt.o kernel_linkage.o + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/cp1emu.c linux/arch/mips64/math-emu/cp1emu.c --- v2.4.5/linux/arch/mips64/math-emu/cp1emu.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/cp1emu.c Mon Jul 2 13:56:40 2001 @@ -0,0 +1,1807 @@ +/* + * MIPS floating point support + * + * This program is free software; you can distribute 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 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. + * + * cp1emu.c: a MIPS coprocessor 1 (fpu) instruction emulator + * + * A complete emulator for MIPS coprocessor 1 instructions. This is + * required for #float(switch) or #float(trap), where it catches all + * COP1 instructions via the "CoProcessor Unusable" exception. + * + * More surprisingly it is also required for #float(ieee), to help out + * the hardware fpu at the boundaries of the IEEE-754 representation + * (denormalised values, infinities, underflow, etc). It is made + * quite nasty because emulation of some non-COP1 instructions is + * required, e.g. in branch delay slots. + * + * Notes: + * 1) the IEEE754 library (-le) performs the actual arithmetic; + * 2) if you know that you won't have an fpu, then you'll get much + * better performance by compiling with -msoft-float! */ + * + * Nov 7, 2000 + * Massive changes to integrate with Linux kernel. + * + * Replace use of kernel data area with use of user stack + * for execution of instructions in branch delay slots. + * + * Replace use of static kernel variables with thread_struct elements. + * + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ieee754.h" + +/* Strap kernel emulator for full MIPS IV emulation */ + +#ifdef __mips +#undef __mips +#endif +#define __mips 4 + +typedef void *vaddr_t; + +/* Function which emulates the instruction in a branch delay slot. */ + +static int mips_dsemul(struct pt_regs *, mips_instruction, vaddr_t); + +/* Function which emulates a floating point instruction. */ + +static int fpu_emu(struct pt_regs *, struct mips_fpu_soft_struct *, + mips_instruction); + +#if __mips >= 4 && __mips != 32 +static int fpux_emu(struct pt_regs *, + struct mips_fpu_soft_struct *, mips_instruction); +#endif + +/* Further private data for which no space exists in mips_fpu_soft_struct */ + +struct mips_fpu_emulator_private fpuemuprivate; + +/* Control registers */ + +#define FPCREG_RID 0 /* $0 = revision id */ +#define FPCREG_CSR 31 /* $31 = csr */ + +/* Convert Mips rounding mode (0..3) to IEEE library modes. */ +static const unsigned char ieee_rm[4] = { + IEEE754_RN, IEEE754_RZ, IEEE754_RU, IEEE754_RD +}; + +#if __mips >= 4 +/* convert condition code register number to csr bit */ +static const unsigned int fpucondbit[8] = { + FPU_CSR_COND0, + FPU_CSR_COND1, + FPU_CSR_COND2, + FPU_CSR_COND3, + FPU_CSR_COND4, + FPU_CSR_COND5, + FPU_CSR_COND6, + FPU_CSR_COND7 +}; +#endif + + + +/* + * Redundant with logic already in kernel/branch.c, + * embedded in compute_return_epc. At some point, + * a single subroutine should be used across both + * modules. + */ +static int isBranchInstr(mips_instruction * i) +{ + switch (MIPSInst_OPCODE(*i)) { + case spec_op: + switch (MIPSInst_FUNC(*i)) { + case jalr_op: + case jr_op: + return 1; + } + break; + + case bcond_op: + switch (MIPSInst_RT(*i)) { + case bltz_op: + case bgez_op: + case bltzl_op: + case bgezl_op: + case bltzal_op: + case bgezal_op: + case bltzall_op: + case bgezall_op: + return 1; + } + break; + + case j_op: + case jal_op: + case jalx_op: + case beq_op: + case bne_op: + case blez_op: + case bgtz_op: + case beql_op: + case bnel_op: + case blezl_op: + case bgtzl_op: + return 1; + + case cop0_op: + case cop1_op: + case cop2_op: + case cop1x_op: + if (MIPSInst_RS(*i) == bc_op) + return 1; + break; + } + + return 0; +} + +#define REG_TO_VA (vaddr_t) +#define VA_TO_REG (unsigned long) + +static unsigned long +mips_get_word(struct pt_regs *xcp, void *va, int *perr) +{ + unsigned long temp; + + if (!user_mode(xcp)) { + *perr = 0; + return (*(unsigned long *) va); + } else { + /* Use kernel get_user() macro */ + *perr = (int) get_user(temp, (unsigned long *) va); + return temp; + } +} + +static unsigned long long +mips_get_dword(struct pt_regs *xcp, void *va, int *perr) +{ + unsigned long long temp; + + if (!user_mode(xcp)) { + *perr = 0; + return (*(unsigned long long *) va); + } else { + /* Use kernel get_user() macro */ + *perr = (int) get_user(temp, (unsigned long long *) va); + return temp; + } +} + +static int mips_put_word(struct pt_regs *xcp, void *va, unsigned long val) +{ + if (!user_mode(xcp)) { + *(unsigned long *) va = val; + return 0; + } else { + /* Use kernel get_user() macro */ + return (int) put_user(val, (unsigned long *) va); + } +} + +static int mips_put_dword(struct pt_regs *xcp, void *va, long long val) +{ + if (!user_mode(xcp)) { + *(unsigned long long *) va = val; + return 0; + } else { + /* Use kernel get_user() macro */ + return (int) put_user(val, (unsigned long long *) va); + } +} + + +/* + * In the Linux kernel, we support selection of FPR format on the + * basis of the Status.FR bit. This does imply that, if a full 32 + * FPRs are desired, there needs to be a flip-flop that can be written + * to one at that bit position. In any case, normal MIPS ABI uses + * only the even FPRs (Status.FR = 0). + */ + +#define CP0_STATUS_FR_SUPPORT + +/* + * Emulate the single floating point instruction pointed at by EPC. + * Two instructions if the instruction is in a branch delay slot. + */ + +static int +cop1Emulate(int xcptno, struct pt_regs *xcp, + struct mips_fpu_soft_struct *ctx) +{ + mips_instruction ir; + vaddr_t emulpc; + vaddr_t contpc; + unsigned int cond; + int err = 0; + + + ir = mips_get_word(xcp, REG_TO_VA xcp->cp0_epc, &err); + if (err) { + fpuemuprivate.stats.errors++; + return SIGBUS; + } + + /* XXX NEC Vr54xx bug workaround */ + if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir)) + xcp->cp0_cause &= ~CAUSEF_BD; + + if (xcp->cp0_cause & CAUSEF_BD) { + /* + * The instruction to be emulated is in a branch delay slot + * which means that we have to emulate the branch instruction + * BEFORE we do the cop1 instruction. + * + * This branch could be a COP1 branch, but in that case we + * would have had a trap for that instruction, and would not + * come through this route. + * + * Linux MIPS branch emulator operates on context, updating the + * cp0_epc. + */ + emulpc = REG_TO_VA(xcp->cp0_epc + 4); /* Snapshot emulation target */ + + if (__compute_return_epc(xcp)) { +#ifdef CP1DBG + printk("failed to emulate branch at %p\n", + REG_TO_VA(xcp->cp0_epc)); +#endif + return SIGILL;; + } + ir = mips_get_word(xcp, emulpc, &err); + if (err) { + fpuemuprivate.stats.errors++; + return SIGBUS; + } + contpc = REG_TO_VA xcp->cp0_epc; + } else { + emulpc = REG_TO_VA xcp->cp0_epc; + contpc = REG_TO_VA xcp->cp0_epc + 4; + } + + emul: + fpuemuprivate.stats.emulated++; + switch (MIPSInst_OPCODE(ir)) { +#ifdef CP0_STATUS_FR_SUPPORT + /* R4000+ 64-bit fpu registers */ +#ifndef SINGLE_ONLY_FPU + case ldc1_op: + { + void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)]) + + MIPSInst_SIMM(ir); + int ft = MIPSInst_RT(ir); + if (!(xcp->cp0_status & ST0_FR)) + ft &= ~1; + ctx->regs[ft] = mips_get_dword(xcp, va, &err); + fpuemuprivate.stats.loads++; + if (err) { + fpuemuprivate.stats.errors++; + return SIGBUS; + } + } + break; + + case sdc1_op: + { + void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)]) + + MIPSInst_SIMM(ir); + int ft = MIPSInst_RT(ir); + if (!(xcp->cp0_status & ST0_FR)) + ft &= ~1; + fpuemuprivate.stats.stores++; + if (mips_put_dword(xcp, va, ctx->regs[ft])) { + fpuemuprivate.stats.errors++; + return SIGBUS; + } + } + break; +#endif + + case lwc1_op: + { + void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)]) + + MIPSInst_SIMM(ir); + fpureg_t val; + int ft = MIPSInst_RT(ir); + fpuemuprivate.stats.loads++; + val = mips_get_word(xcp, va, &err); + if (err) { + fpuemuprivate.stats.errors++; + return SIGBUS; + } + if (xcp->cp0_status & ST0_FR) { + /* load whole register */ + ctx->regs[ft] = val; + } else if (ft & 1) { + /* load to m.s. 32 bits */ +#ifdef SINGLE_ONLY_FPU + /* illegal register in single-float mode */ + return SIGILL; +#else + ctx->regs[(ft & ~1)] &= 0xffffffff; + ctx->regs[(ft & ~1)] |= val << 32; +#endif + } else { + /* load to l.s. 32 bits */ + ctx->regs[ft] &= ~0xffffffffLL; + ctx->regs[ft] |= val; + } + } + break; + + case swc1_op: + { + void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)]) + + MIPSInst_SIMM(ir); + unsigned int val; + int ft = MIPSInst_RT(ir); + fpuemuprivate.stats.stores++; + if (xcp->cp0_status & ST0_FR) { + /* store whole register */ + val = ctx->regs[ft]; + } else if (ft & 1) { +#ifdef SINGLE_ONLY_FPU + /* illegal register in single-float mode */ + return SIGILL; +#else + /* store from m.s. 32 bits */ + val = ctx->regs[(ft & ~1)] >> 32; +#endif + } else { + /* store from l.s. 32 bits */ + val = ctx->regs[ft]; + } + if (mips_put_word(xcp, va, val)) { + fpuemuprivate.stats.errors++; + return SIGBUS; + } + } + break; +#else /* old 32-bit fpu registers */ + case lwc1_op: + { + void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)]) + + MIPSInst_SIMM(ir); + ctx->regs[MIPSInst_RT(ir)] = + mips_get_word(xcp, va, &err); + fpuemuprivate.stats.loads++; + if (err) { + fpuemuprivate.stats.errors++; + return SIGBUS; + } + } + break; + + case swc1_op: + { + void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)]) + + MIPSInst_SIMM(ir); + fpuemuprivate.stats.stores++; + if (mips_put_word + (xcp, va, ctx->regs[MIPSInst_RT(ir)])) { + fpuemuprivate.stats.errors++; + return SIGBUS; + } + } + break; + case ldc1_op: + { + void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)]) + + MIPSInst_SIMM(ir); + unsigned int rt = MIPSInst_RT(ir) & ~1; + int errs = 0; + fpuemuprivate.stats.loads++; +#if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__) + ctx->regs[rt + 1] = + mips_get_word(xcp, va + 0, &err); + errs += err; + ctx->regs[rt + 0] = + mips_get_word(xcp, va + 4, &err); + errs += err; +#else + ctx->regs[rt + 0] = + mips_get_word(xcp, va + 0, &err); + errs += err; + ctx->regs[rt + 1] = + mips_get_word(xcp, va + 4, &err); + errs += err; +#endif + if (err) + return SIGBUS; + } + break; + + case sdc1_op: + { + void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)]) + + MIPSInst_SIMM(ir); + unsigned int rt = MIPSInst_RT(ir) & ~1; + fpuemuprivate.stats.stores++; +#if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__) + if (mips_put_word(xcp, va + 0, ctx->regs[rt + 1])) + return SIGBUS; + if (mips_put_word(xcp, va + 4, ctx->regs[rt + 0])) + return SIGBUS; +#else + if (mips_put_word(xcp, va + 0, ctx->regs[rt + 0])) + return SIGBUS; + if (mips_put_word(xcp, va + 4, ctx->regs[rt + 1])) + return SIGBUS; +#endif + } + break; +#endif + + case cop1_op: + switch (MIPSInst_RS(ir)) { + +#ifdef CP0_STATUS_FR_SUPPORT +#if __mips64 && !defined(SINGLE_ONLY_FPU) + case dmfc_op: + /* copregister fs -> gpr[rt] */ + if (MIPSInst_RT(ir) != 0) { + int fs = MIPSInst_RD(ir); + if (!(xcp->cp0_status & ST0_FR)) + fs &= ~1; + xcp->regs[MIPSInst_RT(ir)] = ctx->regs[fs]; + } + break; + + case dmtc_op: + /* copregister fs <- rt */ + { + fpureg_t value; + int fs = MIPSInst_RD(ir); + if (!(xcp->cp0_status & ST0_FR)) + fs &= ~1; + value = + (MIPSInst_RT(ir) == + 0) ? 0 : xcp->regs[MIPSInst_RT(ir)]; + ctx->regs[fs] = value; + } + break; +#endif + + case mfc_op: + /* copregister rd -> gpr[rt] */ + if (MIPSInst_RT(ir) != 0) { + /* default value from l.s. 32 bits */ + int value = ctx->regs[MIPSInst_RD(ir)]; + if (MIPSInst_RD(ir) & 1) { +#ifdef SINGLE_ONLY_FPU + /* illegal register in single-float mode */ + return SIGILL; +#else + if (!(xcp->cp0_status & ST0_FR)) { + /* move from m.s. 32 bits */ + value = + ctx-> + regs[MIPSInst_RD(ir) & + ~1] >> 32; + } +#endif + } + xcp->regs[MIPSInst_RT(ir)] = value; + } + break; + + case mtc_op: + /* copregister rd <- rt */ + { + fpureg_t value; + if (MIPSInst_RT(ir) == 0) + value = 0; + else + value = + (unsigned int) xcp-> + regs[MIPSInst_RT(ir)]; + if (MIPSInst_RD(ir) & 1) { +#ifdef SINGLE_ONLY_FPU + /* illegal register in single-float mode */ + return SIGILL; +#else + if (!(xcp->cp0_status & ST0_FR)) { + /* move to m.s. 32 bits */ + ctx-> + regs[ + (MIPSInst_RD(ir) & + ~1)] &= + 0xffffffff; + ctx-> + regs[ + (MIPSInst_RD(ir) & + ~1)] |= + value << 32; + break; + } +#endif + } + /* move to l.s. 32 bits */ + ctx->regs[MIPSInst_RD(ir)] &= + ~0xffffffffLL; + ctx->regs[MIPSInst_RD(ir)] |= value; + } + break; +#else + + case mfc_op: + /* copregister rd -> gpr[rt] */ + if (MIPSInst_RT(ir) != 0) { + unsigned value = + ctx->regs[MIPSInst_RD(ir)]; + xcp->regs[MIPSInst_RT(ir)] = value; + } + break; + + case mtc_op: + /* copregister rd <- rt */ + { + unsigned value; + value = + (MIPSInst_RT(ir) == + 0) ? 0 : xcp->regs[MIPSInst_RT(ir)]; + ctx->regs[MIPSInst_RD(ir)] = value; + } + break; +#endif + + case cfc_op: + /* cop control register rd -> gpr[rt] */ + { + unsigned value; + + if (MIPSInst_RD(ir) == FPCREG_CSR) { + value = ctx->sr; +#ifdef CSRTRACE + printk + ("%p gpr[%d]<-csr=%08x\n", + REG_TO_VA(xcp->cp0_epc), + MIPSInst_RT(ir), value); +#endif + } else if (MIPSInst_RD(ir) == FPCREG_RID) + value = 0; + else + value = 0; + if (MIPSInst_RT(ir)) + xcp->regs[MIPSInst_RT(ir)] = value; + } + break; + + case ctc_op: + /* copregister rd <- rt */ + { + unsigned value; + + if (MIPSInst_RT(ir) == 0) + value = 0; + else + value = xcp->regs[MIPSInst_RT(ir)]; + + /* we only have one writable control reg + */ + if (MIPSInst_RD(ir) == FPCREG_CSR) { +#ifdef CSRTRACE + printk + ("%p gpr[%d]->csr=%08x\n", + REG_TO_VA(xcp->cp0_epc), + MIPSInst_RT(ir), value); +#endif + ctx->sr = value; + /* copy new rounding mode to ieee library state! */ + ieee754_csr.rm = + ieee_rm[value & 0x3]; + } + } + break; + + case bc_op: + if (xcp->cp0_cause & CAUSEF_BD) { + return SIGILL; + } + { + int likely = 0; + +#if __mips >= 4 + cond = + ctx-> + sr & fpucondbit[MIPSInst_RT(ir) >> 2]; +#else + cond = ctx->sr & FPU_CSR_COND; +#endif + switch (MIPSInst_RT(ir) & 3) { + case bcfl_op: + likely = 1; + case bcf_op: + cond = !cond; + break; + case bctl_op: + likely = 1; + case bct_op: + break; + default: + /* thats an illegal instruction */ + return SIGILL; + } + + xcp->cp0_cause |= CAUSEF_BD; + if (cond) { + /* branch taken: emulate dslot instruction */ + xcp->cp0_epc += 4; + contpc = + REG_TO_VA xcp->cp0_epc + + (MIPSInst_SIMM(ir) << 2); + + ir = + mips_get_word(xcp, + REG_TO_VA(xcp-> + cp0_epc), + &err); + if (err) { + fpuemuprivate.stats. + errors++; + return SIGBUS; + } + + switch (MIPSInst_OPCODE(ir)) { + case lwc1_op: + case swc1_op: +#if (__mips >= 2 || __mips64) && !defined(SINGLE_ONLY_FPU) + case ldc1_op: + case sdc1_op: +#endif + case cop1_op: +#if __mips >= 4 && __mips != 32 + case cop1x_op: +#endif + /* its one of ours */ + goto emul; +#if __mips >= 4 + case spec_op: + if (MIPSInst_FUNC(ir) == + movc_op) goto emul; + break; +#endif + } + + /* single step the non-cp1 instruction in the dslot */ + return mips_dsemul(xcp, ir, contpc); + } else { + /* branch not taken */ + if (likely) + /* branch likely nullifies dslot if not taken */ + xcp->cp0_epc += 4; + /* else continue & execute dslot as normal insn */ + } + } + break; + + default: + if (!(MIPSInst_RS(ir) & 0x10)) { + return SIGILL; + } + /* a real fpu computation instruction */ + { + int sig; + if ((sig = fpu_emu(xcp, ctx, ir))) + return sig; + } + } + break; + +#if __mips >= 4 && __mips != 32 + case cop1x_op: + { + int sig; + if ((sig = fpux_emu(xcp, ctx, ir))) + return sig; + } + break; +#endif + +#if __mips >= 4 + case spec_op: + if (MIPSInst_FUNC(ir) != movc_op) + return SIGILL; + cond = fpucondbit[MIPSInst_RT(ir) >> 2]; + if (((ctx->sr & cond) != 0) != + ((MIPSInst_RT(ir) & 1) != 0)) return 0; + xcp->regs[MIPSInst_RD(ir)] = xcp->regs[MIPSInst_RS(ir)]; + break; +#endif + + default: + return SIGILL; + } + + /* we did it !! */ + xcp->cp0_epc = VA_TO_REG(contpc); + xcp->cp0_cause &= ~CAUSEF_BD; + return 0; +} + +/* + * Emulate the arbritrary instruction ir at xcp->cp0_epc. Required when + * we have to emulate the instruction in a COP1 branch delay slot. Do + * not change cp0_epc due to the instruction + * + * According to the spec: + * 1) it shouldnt be a branch :-) + * 2) it can be a COP instruction :-( + * 3) if we are tring to run a protected memory space we must take + * special care on memory access instructions :-( + */ + +/* + * "Trampoline" return routine to catch exception following + * execution of delay-slot instruction execution. + */ + +int do_dsemulret(struct pt_regs *xcp) +{ +#ifdef DSEMUL_TRACE + printk("desemulret\n"); +#endif + /* Set EPC to return to post-branch instruction */ + xcp->cp0_epc = current->thread.dsemul_epc; + /* + * Clear the state that got us here. + */ + current->thread.dsemul_aerpc = (unsigned long) 0; + + return 0; +} + + +#define AdELOAD 0x8c000001 /* lw $0,1($0) */ + +static int +mips_dsemul(struct pt_regs *xcp, mips_instruction ir, vaddr_t cpc) +{ + mips_instruction *dsemul_insns; + mips_instruction forcetrap; + extern asmlinkage void handle_dsemulret(void); + + if (ir == 0) { /* a nop is easy */ + xcp->cp0_epc = VA_TO_REG(cpc); + return 0; + } +#ifdef DSEMUL_TRACE + printk("desemul %p %p\n", REG_TO_VA(xcp->cp0_epc), cpc); +#endif + + /* + * The strategy is to push the instruction onto the user stack + * and put a trap after it which we can catch and jump to + * the required address any alternative apart from full + * instruction emulation!!. + */ + dsemul_insns = (mips_instruction *) (xcp->regs[29] & ~3); + dsemul_insns -= 3; /* Two instructions, plus one for luck ;-) */ + /* Verify that the stack pointer is not competely insane */ + if (verify_area + (VERIFY_WRITE, dsemul_insns, sizeof(mips_instruction) * 2)) + return SIGBUS; + + if (mips_put_word(xcp, &dsemul_insns[0], ir)) { + fpuemuprivate.stats.errors++; + return (SIGBUS); + } + + /* + * Algorithmics used a system call instruction, and + * borrowed that vector. MIPS/Linux version is a bit + * more heavyweight in the interests of portability and + * multiprocessor support. We flag the thread for special + * handling in the unaligned access handler and force an + * address error excpetion. + */ + + /* If one is *really* paranoid, one tests for a bad stack pointer */ + if ((xcp->regs[29] & 0x3) == 0x3) + forcetrap = AdELOAD - 1; + else + forcetrap = AdELOAD; + + if (mips_put_word(xcp, &dsemul_insns[1], forcetrap)) { + fpuemuprivate.stats.errors++; + return (SIGBUS); + } + + /* Set thread state to catch and handle the exception */ + current->thread.dsemul_epc = (unsigned long) cpc; + current->thread.dsemul_aerpc = (unsigned long) &dsemul_insns[1]; + xcp->cp0_epc = VA_TO_REG & dsemul_insns[0]; + + /* What we'd really like to do is just flush the line(s) of the */ + /* icache containing the dsemulret instructions, but there's no */ + /* mechanism to do this yet... */ + flush_cache_all(); + return SIGILL; /* force out of emulation loop */ +} + +/* + * Conversion table from MIPS compare ops 48-63 + * cond = ieee754dp_cmp(x,y,IEEE754_UN); + */ +static const unsigned char cmptab[8] = { + 0, /* cmp_0 (sig) cmp_sf */ + IEEE754_CUN, /* cmp_un (sig) cmp_ngle */ + IEEE754_CEQ, /* cmp_eq (sig) cmp_seq */ + IEEE754_CEQ | IEEE754_CUN, /* cmp_ueq (sig) cmp_ngl */ + IEEE754_CLT, /* cmp_olt (sig) cmp_lt */ + IEEE754_CLT | IEEE754_CUN, /* cmp_ult (sig) cmp_nge */ + IEEE754_CLT | IEEE754_CEQ, /* cmp_ole (sig) cmp_le */ + IEEE754_CLT | IEEE754_CEQ | IEEE754_CUN, /* cmp_ule (sig) cmp_ngt */ +}; + +#define SIFROMREG(si,x) ((si) = ctx->regs[x]) +#define SITOREG(si,x) (ctx->regs[x] = (int)(si)) + +#if __mips64 && !defined(SINGLE_ONLY_FPU) +#define DIFROMREG(di,x) ((di) = ctx->regs[x]) +#define DITOREG(di,x) (ctx->regs[x] = (di)) +#endif + +#define SPFROMREG(sp,x) ((sp).bits = ctx->regs[x]) +#define SPTOREG(sp,x) (ctx->regs[x] = (sp).bits) + +#ifdef CP0_STATUS_FR_SUPPORT +#define DPFROMREG(dp,x) ((dp).bits = \ + ctx->regs[(xcp->cp0_status & ST0_FR) ? x : (x & ~1)]) +#define DPTOREG(dp,x) (ctx->regs[(xcp->cp0_status & ST0_FR) ? x : (x & ~1)]\ + = (dp).bits) +#else +/* Beware: MIPS COP1 doubles are always little_word endian in registers */ +#define DPFROMREG(dp,x) \ + ((dp).bits = ((unsigned long long)ctx->regs[(x)+1] << 32) | ctx->regs[x]) +#define DPTOREG(dp,x) \ + (ctx->regs[x] = (dp).bits, ctx->regs[(x)+1] = (dp).bits >> 32) +#endif + +#if __mips >= 4 && __mips != 32 + +/* + * Additional MIPS4 instructions + */ + +static ieee754dp fpemu_dp_recip(ieee754dp d) +{ + return ieee754dp_div(ieee754dp_one(0), d); +} + +static ieee754dp fpemu_dp_rsqrt(ieee754dp d) +{ + return ieee754dp_div(ieee754dp_one(0), ieee754dp_sqrt(d)); +} + +static ieee754sp fpemu_sp_recip(ieee754sp s) +{ + return ieee754sp_div(ieee754sp_one(0), s); +} + +static ieee754sp fpemu_sp_rsqrt(ieee754sp s) +{ + return ieee754sp_div(ieee754sp_one(0), ieee754sp_sqrt(s)); +} + + +static ieee754dp fpemu_dp_madd(ieee754dp r, ieee754dp s, ieee754dp t) +{ + return ieee754dp_add(ieee754dp_mul(s, t), r); +} + +static ieee754dp fpemu_dp_msub(ieee754dp r, ieee754dp s, ieee754dp t) +{ + return ieee754dp_sub(ieee754dp_mul(s, t), r); +} + +static ieee754dp fpemu_dp_nmadd(ieee754dp r, ieee754dp s, ieee754dp t) +{ + return ieee754dp_neg(ieee754dp_add(ieee754dp_mul(s, t), r)); +} + +static ieee754dp fpemu_dp_nmsub(ieee754dp r, ieee754dp s, ieee754dp t) +{ + return ieee754dp_neg(ieee754dp_sub(ieee754dp_mul(s, t), r)); +} + + +static ieee754sp fpemu_sp_madd(ieee754sp r, ieee754sp s, ieee754sp t) +{ + return ieee754sp_add(ieee754sp_mul(s, t), r); +} + +static ieee754sp fpemu_sp_msub(ieee754sp r, ieee754sp s, ieee754sp t) +{ + return ieee754sp_sub(ieee754sp_mul(s, t), r); +} + +static ieee754sp fpemu_sp_nmadd(ieee754sp r, ieee754sp s, ieee754sp t) +{ + return ieee754sp_neg(ieee754sp_add(ieee754sp_mul(s, t), r)); +} + +static ieee754sp fpemu_sp_nmsub(ieee754sp r, ieee754sp s, ieee754sp t) +{ + return ieee754sp_neg(ieee754sp_sub(ieee754sp_mul(s, t), r)); +} + +static int +fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx, + mips_instruction ir) +{ + unsigned rcsr = 0; /* resulting csr */ + + fpuemuprivate.stats.cp1xops++; + + switch (MIPSInst_FMA_FFMT(ir)) { + case s_fmt: /* 0 */ + { + ieee754sp(*handler) (ieee754sp, ieee754sp, + ieee754sp); + ieee754sp fd, fr, fs, ft; + + switch (MIPSInst_FUNC(ir)) { + case lwxc1_op: + { + void *va = + REG_TO_VA(xcp-> + regs[MIPSInst_FR(ir)] + + + xcp-> + regs[MIPSInst_FT + (ir)]); + fpureg_t val; + int err = 0; + val = mips_get_word(xcp, va, &err); + if (err) { + fpuemuprivate.stats. + errors++; + return SIGBUS; + } + if (xcp->cp0_status & ST0_FR) { + /* load whole register */ + ctx-> + regs[MIPSInst_FD(ir)] = + val; + } else if (MIPSInst_FD(ir) & 1) { + /* load to m.s. 32 bits */ +#if defined(SINGLE_ONLY_FPU) + /* illegal register in single-float mode */ + return SIGILL; +#else + ctx-> + regs[ + (MIPSInst_FD(ir) & + ~1)] &= + 0xffffffff; + ctx-> + regs[ + (MIPSInst_FD(ir) & + ~1)] |= + val << 32; +#endif + } else { + /* load to l.s. 32 bits */ + ctx-> + regs[MIPSInst_FD(ir)] + &= ~0xffffffffLL; + ctx-> + regs[MIPSInst_FD(ir)] + |= val; + } + } + break; + + case swxc1_op: + { + void *va = + REG_TO_VA(xcp-> + regs[MIPSInst_FR(ir)] + + + xcp-> + regs[MIPSInst_FT + (ir)]); + unsigned int val; + if (xcp->cp0_status & ST0_FR) { + /* store whole register */ + val = + ctx-> + regs[MIPSInst_FS(ir)]; + } else if (MIPSInst_FS(ir) & 1) { +#if defined(SINGLE_ONLY_FPU) + /* illegal register in single-float mode */ + return SIGILL; +#else + /* store from m.s. 32 bits */ + val = + ctx-> + regs[ + (MIPSInst_FS(ir) & + ~1)] >> 32; +#endif + } else { + /* store from l.s. 32 bits */ + val = + ctx-> + regs[MIPSInst_FS(ir)]; + } + if (mips_put_word(xcp, va, val)) { + fpuemuprivate.stats. + errors++; + return SIGBUS; + } + } + break; + + case madd_s_op: + handler = fpemu_sp_madd; + goto scoptop; + case msub_s_op: + handler = fpemu_sp_msub; + goto scoptop; + case nmadd_s_op: + handler = fpemu_sp_nmadd; + goto scoptop; + case nmsub_s_op: + handler = fpemu_sp_nmsub; + goto scoptop; + + scoptop: + SPFROMREG(fr, MIPSInst_FR(ir)); + SPFROMREG(fs, MIPSInst_FS(ir)); + SPFROMREG(ft, MIPSInst_FT(ir)); + fd = (*handler) (fr, fs, ft); + SPTOREG(fd, MIPSInst_FD(ir)); + + copcsr: + if (ieee754_cxtest(IEEE754_INEXACT)) + rcsr |= + FPU_CSR_INE_X | FPU_CSR_INE_S; + if (ieee754_cxtest(IEEE754_UNDERFLOW)) + rcsr |= + FPU_CSR_UDF_X | FPU_CSR_UDF_S; + if (ieee754_cxtest(IEEE754_OVERFLOW)) + rcsr |= + FPU_CSR_OVF_X | FPU_CSR_OVF_S; + if (ieee754_cxtest + (IEEE754_INVALID_OPERATION)) rcsr |= + FPU_CSR_INV_X | FPU_CSR_INV_S; + + ctx->sr = + (ctx->sr & ~FPU_CSR_ALL_X) | rcsr; + if ((ctx->sr >> 5) & ctx-> + sr & FPU_CSR_ALL_E) { + /*printk ("SIGFPE: fpu csr = %08x\n",ctx->sr); */ + return SIGFPE; + } + + break; + + default: + return SIGILL; + } + } + break; + +#if !defined(SINGLE_ONLY_FPU) + case d_fmt: /* 1 */ + { + ieee754dp(*handler) (ieee754dp, ieee754dp, + ieee754dp); + ieee754dp fd, fr, fs, ft; + + switch (MIPSInst_FUNC(ir)) { + case ldxc1_op: + { + void *va = + REG_TO_VA(xcp-> + regs[MIPSInst_FR(ir)] + + + xcp-> + regs[MIPSInst_FT + (ir)]); + int err = 0; + ctx->regs[MIPSInst_FD(ir)] = + mips_get_dword(xcp, va, &err); + if (err) { + fpuemuprivate.stats. + errors++; + return SIGBUS; + } + } + break; + + case sdxc1_op: + { + void *va = + REG_TO_VA(xcp-> + regs[MIPSInst_FR(ir)] + + + xcp-> + regs[MIPSInst_FT + (ir)]); + if (mips_put_dword + (xcp, va, + ctx->regs[MIPSInst_FS(ir)])) { + fpuemuprivate.stats. + errors++; + return SIGBUS; + } + } + break; + + case madd_d_op: + handler = fpemu_dp_madd; + goto dcoptop; + case msub_d_op: + handler = fpemu_dp_msub; + goto dcoptop; + case nmadd_d_op: + handler = fpemu_dp_nmadd; + goto dcoptop; + case nmsub_d_op: + handler = fpemu_dp_nmsub; + goto dcoptop; + + dcoptop: + DPFROMREG(fr, MIPSInst_FR(ir)); + DPFROMREG(fs, MIPSInst_FS(ir)); + DPFROMREG(ft, MIPSInst_FT(ir)); + fd = (*handler) (fr, fs, ft); + DPTOREG(fd, MIPSInst_FD(ir)); + goto copcsr; + + default: + return SIGILL; + } + } + break; +#endif + + case 0x7: /* 7 */ + { + if (MIPSInst_FUNC(ir) != pfetch_op) { + return SIGILL; + } + /* ignore prefx operation */ + } + break; + + default: + return SIGILL; + } + + return 0; +} +#endif + + + +/* + * Emulate a single COP1 arithmetic instruction. + */ +static int +fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx, + mips_instruction ir) +{ + int rfmt; /* resulting format */ + unsigned rcsr = 0; /* resulting csr */ + unsigned cond; + union { + ieee754dp d; + ieee754sp s; + int w; +#if __mips64 + long long l; +#endif + } rv; /* resulting value */ + + fpuemuprivate.stats.cp1ops++; + switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) { + + case s_fmt:{ /* 0 */ + ieee754sp(*handler) (); + + switch (MIPSInst_FUNC(ir)) { + /* binary ops */ + case fadd_op: + handler = ieee754sp_add; + goto scopbop; + case fsub_op: + handler = ieee754sp_sub; + goto scopbop; + case fmul_op: + handler = ieee754sp_mul; + goto scopbop; + case fdiv_op: + handler = ieee754sp_div; + goto scopbop; + + /* unary ops */ +#if __mips >= 2 || __mips64 + case fsqrt_op: + handler = ieee754sp_sqrt; + goto scopuop; +#endif +#if __mips >= 4 && __mips != 32 + case frsqrt_op: + handler = fpemu_sp_rsqrt; + goto scopuop; + case frecip_op: + handler = fpemu_sp_recip; + goto scopuop; +#endif +#if __mips >= 4 + case fmovc_op: + cond = fpucondbit[MIPSInst_FT(ir) >> 2]; + if (((ctx->sr & cond) != 0) != + ((MIPSInst_FT(ir) & 1) != 0)) + return 0; + SPFROMREG(rv.s, MIPSInst_FS(ir)); + break; + case fmovz_op: + if (xcp->regs[MIPSInst_FT(ir)] != 0) + return 0; + SPFROMREG(rv.s, MIPSInst_FS(ir)); + break; + case fmovn_op: + if (xcp->regs[MIPSInst_FT(ir)] == 0) + return 0; + SPFROMREG(rv.s, MIPSInst_FS(ir)); + break; +#endif + case fabs_op: + handler = ieee754sp_abs; + goto scopuop; + case fneg_op: + handler = ieee754sp_neg; + goto scopuop; + case fmov_op: + /* an easy one */ + SPFROMREG(rv.s, MIPSInst_FS(ir)); + break; + /* binary op on handler */ +scopbop: + { + ieee754sp fs, ft; + + SPFROMREG(fs, MIPSInst_FS(ir)); + SPFROMREG(ft, MIPSInst_FT(ir)); + + rv.s = (*handler) (fs, ft); + goto copcsr; + } +scopuop: + { + ieee754sp fs; + + SPFROMREG(fs, MIPSInst_FS(ir)); + rv.s = (*handler) (fs); + goto copcsr; + } +copcsr: + if (ieee754_cxtest(IEEE754_INEXACT)) + rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S; + if (ieee754_cxtest(IEEE754_UNDERFLOW)) + rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S; + if (ieee754_cxtest(IEEE754_OVERFLOW)) + rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S; + if (ieee754_cxtest(IEEE754_ZERO_DIVIDE)) + rcsr |= FPU_CSR_DIV_X | FPU_CSR_DIV_S; + if (ieee754_cxtest + (IEEE754_INVALID_OPERATION)) rcsr |= + FPU_CSR_INV_X | FPU_CSR_INV_S; + break; + + /* unary conv ops */ + case fcvts_op: + return SIGILL; /* not defined */ + case fcvtd_op: +#if defined(SINGLE_ONLY_FPU) + return SIGILL; /* not defined */ +#else + { + ieee754sp fs; + + SPFROMREG(fs, MIPSInst_FS(ir)); + rv.d = ieee754dp_fsp(fs); + rfmt = d_fmt; + goto copcsr; + } +#endif + case fcvtw_op: + { + ieee754sp fs; + + SPFROMREG(fs, MIPSInst_FS(ir)); + rv.w = ieee754sp_tint(fs); + rfmt = w_fmt; + goto copcsr; + } + +#if __mips >= 2 || __mips64 + case fround_op: + case ftrunc_op: + case fceil_op: + case ffloor_op: + { + unsigned int oldrm = ieee754_csr.rm; + ieee754sp fs; + + SPFROMREG(fs, MIPSInst_FS(ir)); + ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3]; + rv.w = ieee754sp_tint(fs); + ieee754_csr.rm = oldrm; + rfmt = w_fmt; + goto copcsr; + } +#endif /* __mips >= 2 */ + +#if __mips64 && !defined(SINGLE_ONLY_FPU) + case fcvtl_op: + { + ieee754sp fs; + + SPFROMREG(fs, MIPSInst_FS(ir)); + rv.l = ieee754sp_tlong(fs); + rfmt = l_fmt; + goto copcsr; + } + + case froundl_op: + case ftruncl_op: + case fceill_op: + case ffloorl_op: + { + unsigned int oldrm = ieee754_csr.rm; + ieee754sp fs; + + SPFROMREG(fs, MIPSInst_FS(ir)); + ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3]; + rv.l = ieee754sp_tlong(fs); + ieee754_csr.rm = oldrm; + rfmt = l_fmt; + goto copcsr; + } +#endif /* __mips64 && !fpu(single) */ + + default: + if (MIPSInst_FUNC(ir) >= fcmp_op) { + unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op; + ieee754sp fs, ft; + + SPFROMREG(fs, MIPSInst_FS(ir)); + SPFROMREG(ft, MIPSInst_FT(ir)); + rv.w = ieee754sp_cmp(fs, ft, cmptab[cmpop & 0x7]); + rfmt = -1; + if ((cmpop & 0x8) && ieee754_cxtest(IEEE754_INVALID_OPERATION)) + rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S; + } else { + return SIGILL; + } + break; + } + break; + } + +#if !defined(SINGLE_ONLY_FPU) + case d_fmt: { + ieee754dp(*handler) (); + + switch (MIPSInst_FUNC(ir)) { + /* binary ops */ + case fadd_op: + handler = ieee754dp_add; + goto dcopbop; + case fsub_op: + handler = ieee754dp_sub; + goto dcopbop; + case fmul_op: + handler = ieee754dp_mul; + goto dcopbop; + case fdiv_op: + handler = ieee754dp_div; + goto dcopbop; + + /* unary ops */ +#if __mips >= 2 || __mips64 + case fsqrt_op: + handler = ieee754dp_sqrt; + goto dcopuop; +#endif +#if __mips >= 4 && __mips != 32 + case frsqrt_op: + handler = fpemu_dp_rsqrt; + goto dcopuop; + case frecip_op: + handler = fpemu_dp_recip; + goto dcopuop; +#endif +#if __mips >= 4 + case fmovc_op: + cond = fpucondbit[MIPSInst_FT(ir) >> 2]; + if (((ctx->sr & cond) != 0) != ((MIPSInst_FT(ir) & 1) != 0)) + return 0; + DPFROMREG(rv.d, MIPSInst_FS(ir)); + break; + case fmovz_op: + if (xcp->regs[MIPSInst_FT(ir)] != 0) + return 0; + DPFROMREG(rv.d, MIPSInst_FS(ir)); + break; + case fmovn_op: + if (xcp->regs[MIPSInst_FT(ir)] == 0) + return 0; + DPFROMREG(rv.d, MIPSInst_FS(ir)); + break; +#endif + case fabs_op: + handler = ieee754dp_abs; + goto dcopuop; + case fneg_op: + handler = ieee754dp_neg; + goto dcopuop; + case fmov_op: + /* an easy one */ + DPFROMREG(rv.d, MIPSInst_FS(ir)); + break; + + /* binary op on handler */ +dcopbop: + { + ieee754dp fs, ft; + + DPFROMREG(fs, MIPSInst_FS(ir)); + DPFROMREG(ft, MIPSInst_FT(ir)); + + rv.d = (*handler) (fs, ft); + goto copcsr; + } +dcopuop: + { + ieee754dp fs; + + DPFROMREG(fs, MIPSInst_FS(ir)); + rv.d = (*handler) (fs); + goto copcsr; + } + + /* unary conv ops */ + case fcvts_op: + { + ieee754dp fs; + + DPFROMREG(fs, MIPSInst_FS(ir)); + rv.s = ieee754sp_fdp(fs); + rfmt = s_fmt; + goto copcsr; + } + case fcvtd_op: + return SIGILL; /* not defined */ + case fcvtw_op: + { + ieee754dp fs; + + DPFROMREG(fs, MIPSInst_FS(ir)); + rv.w = ieee754dp_tint(fs); /* wrong */ + rfmt = w_fmt; + goto copcsr; + } + +#if __mips >= 2 || __mips64 + case fround_op: + case ftrunc_op: + case fceil_op: + case ffloor_op: + { + unsigned int oldrm = ieee754_csr.rm; + ieee754dp fs; + + DPFROMREG(fs, MIPSInst_FS(ir)); + ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3]; + rv.w = ieee754dp_tint(fs); + ieee754_csr.rm = oldrm; + rfmt = w_fmt; + goto copcsr; + } +#endif + +#if __mips64 && !defined(SINGLE_ONLY_FPU) + case fcvtl_op: + { + ieee754dp fs; + + DPFROMREG(fs, MIPSInst_FS(ir)); + rv.l = ieee754dp_tlong(fs); + rfmt = l_fmt; + goto copcsr; + } + + case froundl_op: + case ftruncl_op: + case fceill_op: + case ffloorl_op: + { + unsigned int oldrm = ieee754_csr.rm; + ieee754dp fs; + + DPFROMREG(fs, MIPSInst_FS(ir)); + ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3]; + rv.l = ieee754dp_tlong(fs); + ieee754_csr.rm = oldrm; + rfmt = l_fmt; + goto copcsr; + } +#endif /* __mips >= 3 && !fpu(single) */ + + default: + if (MIPSInst_FUNC(ir) >= fcmp_op) { + unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op; + ieee754dp fs, ft; + + DPFROMREG(fs, MIPSInst_FS(ir)); + DPFROMREG(ft, MIPSInst_FT(ir)); + rv.w = ieee754dp_cmp(fs, ft, cmptab[cmpop & 0x7]); + rfmt = -1; + if ((cmpop & 0x8) && ieee754_cxtest (IEEE754_INVALID_OPERATION)) + rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S; + } else { + return SIGILL; + } + break; + } + break; + } +#endif /* !defined(SINGLE_ONLY_FPU) */ + + case w_fmt: { + switch (MIPSInst_FUNC(ir)) { + case fcvts_op: + /* convert word to single precision real */ + rv.s = ieee754sp_fint(ctx-> regs[MIPSInst_FS(ir)]); + rfmt = s_fmt; + goto copcsr; +#if !defined(SINGLE_ONLY_FPU) + case fcvtd_op: + /* convert word to double precision real */ + rv.d = ieee754dp_fint(ctx-> regs[MIPSInst_FS(ir)]); + rfmt = d_fmt; + goto copcsr; +#endif + default: + return SIGILL; + } + break; + } + +#if __mips64 && !defined(SINGLE_ONLY_FPU) + case l_fmt: { + switch (MIPSInst_FUNC(ir)) { + case fcvts_op: + /* convert long to single precision real */ + rv.s = ieee754sp_flong(ctx-> regs[MIPSInst_FS(ir)]); + rfmt = s_fmt; + goto copcsr; + case fcvtd_op: + /* convert long to double precision real */ + rv.d = ieee754dp_flong(ctx-> regs[MIPSInst_FS(ir)]); + rfmt = d_fmt; + goto copcsr; + default: + return SIGILL; + } + break; + } +#endif + + default: + return SIGILL; + } + + /* + * Update the fpu CSR register for this operation. + * If an exception is required, generate a tidy SIGFPE exception, + * without updating the result register. + * Note: cause exception bits do not accumulate, they are rewritten + * for each op; only the flag/sticky bits accumulate. + */ + ctx->sr = (ctx->sr & ~FPU_CSR_ALL_X) | rcsr; + if ((ctx->sr >> 5) & ctx->sr & FPU_CSR_ALL_E) { + /*printk ("SIGFPE: fpu csr = %08x\n",ctx->sr); */ + return SIGFPE; + } + + /* + * Now we can safely write the result back to the register file. + */ + switch (rfmt) { + case -1: { +#if __mips >= 4 + cond = fpucondbit[MIPSInst_FD(ir) >> 2]; +#else + cond = FPU_CSR_COND; +#endif + if (rv.w) + ctx->sr |= cond; + else + ctx->sr &= ~cond; + break; + } +#if !defined(SINGLE_ONLY_FPU) + case d_fmt: + DPTOREG(rv.d, MIPSInst_FD(ir)); + break; +#endif + case s_fmt: + SPTOREG(rv.s, MIPSInst_FD(ir)); + break; + case w_fmt: + SITOREG(rv.w, MIPSInst_FD(ir)); + break; +#if __mips64 && !defined(SINGLE_ONLY_FPU) + case l_fmt: + DITOREG(rv.l, MIPSInst_FD(ir)); + break; +#endif + default: + return SIGILL; + } + + return 0; +} + + +/* + * Emulate the floating point instruction at EPC, and continue + * to run until we hit a non-fp instruction, or a backward + * branch. This cuts down dramatically on the per instruction + * exception overhead. + */ +int fpu_emulator_cop1Handler(int xcptno, struct pt_regs *xcp) +{ + struct mips_fpu_soft_struct *ctx = ¤t->thread.fpu.soft; + unsigned long oldepc, prevepc; + unsigned int insn; + int sig = 0; + int err = 0; + + oldepc = xcp->cp0_epc; + do { + prevepc = xcp->cp0_epc; + insn = mips_get_word(xcp, REG_TO_VA(xcp->cp0_epc), &err); + if (err) { + fpuemuprivate.stats.errors++; + return SIGBUS; + } + if (insn != 0) + sig = cop1Emulate(xcptno, xcp, ctx); + else + xcp->cp0_epc += 4; /* skip nops */ + } while (xcp->cp0_epc > prevepc && sig == 0); + + /* SIGILL indicates a non-fpu instruction */ + if (sig == SIGILL && xcp->cp0_epc != oldepc) + /* but if epc has advanced, then ignore it */ + sig = 0; + + return sig; +} + + +#ifdef NOTDEF +/* + * Patch up the hardware fpu state when an f.p. exception occurs. + */ +static int cop1Patcher(int xcptno, struct pt_regs *xcp) +{ + struct mips_fpu_soft_struct *ctx = ¤t->thread.fpu.soft; + unsigned sr; + int sig; + + /* reenable Cp1, else fpe_save() will get nested exception */ + sr = mips_bissr(ST0_CU1); + + /* get fpu registers and status, then clear pending exceptions */ + fpe_save(ctx); + fpe_setsr(ctx->sr &= ~FPU_CSR_ALL_X); + + /* get current rounding mode for IEEE library, and emulate insn */ + ieee754_csr.rm = ieee_rm[ctx->sr & 0x3]; + sig = cop1Emulate(xcptno, xcp, ctx); + + /* don't return with f.p. exceptions pending */ + ctx->sr &= ~FPU_CSR_ALL_X; + fpe_restore(ctx); + + mips_setsr(sr); + return sig; +} + +void _cop1_init(int emulate) +{ + extern int _nofpu; + + if (emulate) { + /* + * Install cop1 emulator to handle "coprocessor unusable" exception + */ + xcption(XCPTCPU, cop1Handler); + fpuemuactive = 1; /* tell dbg.c that we are in charge */ + _nofpu = 0; /* tell setjmp() it "has" an fpu */ + } else { + /* + * Install cop1 emulator for floating point exceptions only, + * i.e. denormalised results, underflow, overflow etc, which + * must be emulated in s/w. + */ +#ifdef 1 + /* r4000 or above use dedicate exception */ + xcption(XCPTFPE, cop1Patcher); +#else + /* r3000 et al use interrupt */ + extern int _sbd_getfpuintr(void); + int intno = _sbd_getfpuintr(); + intrupt(intno, cop1Patcher, 0); + mips_bissr(SR_IM0 << intno); +#endif + +#if (#cpu(r4640) || #cpu(r4650)) && !defined(SINGLE_ONLY_FPU) + /* For R4640/R4650 compiled *without* the -msingle-float flag, + then we share responsibility: the h/w handles the single + precision operations, and the trap emulator handles the + double precision. We set fpuemuactive so that dbg.c first + fetches the s/w state before saving the h/w state. */ + fpuemuactive = 1; + { + int i; + /* initialise the unused d.p high order words to be NaN */ + for (i = 0; i < 32; i++) + current->thread.fpu.soft.regs[i] = + 0x7ff80bad00000000LL; + } +#endif /* (r4640 || r4650) && !fpu(single) */ + } +} +#endif + diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_add.c linux/arch/mips64/math-emu/dp_add.c --- v2.4.5/linux/arch/mips64/math-emu/dp_add.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/dp_add.c Mon Jul 2 13:56:40 2001 @@ -0,0 +1,186 @@ +/* IEEE754 floating point arithmetic + * double precision: common utilities + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754dp.h" + +ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y) +{ + COMPXDP; + COMPYDP; + + EXPLODEXDP; + EXPLODEYDP; + + CLEARCX; + + switch (CLPAIR(xc, yc)) { + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): + return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "add", x, + y); + + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): + return ieee754dp_nanxcpt(y, "add", x, y); + + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): + return ieee754dp_nanxcpt(x, "add", x, y); + + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): + return ieee754dp_bestnan(x, y); + + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): + return y; + + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): + return x; + + + /* Inifity handeling + */ + + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): + if (xs == ys) + return x; + SETCX(IEEE754_INVALID_OPERATION); + return ieee754dp_xcpt(ieee754dp_indef(), "add", x, y); + + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): + return y; + + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): + return x; + + /* Zero handeling + */ + + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): + if (xs == ys) + return x; + else + return ieee754dp_zero(ieee754_csr.rm == + IEEE754_RD); + + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): + return x; + + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): + return y; + + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): + DPDNORMX; + + /* FALL THROUGH */ + + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): + DPDNORMY; + break; + + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): + DPDNORMX; + break; + + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): + break; + } + assert(xm & DP_HIDDEN_BIT); + assert(ym & DP_HIDDEN_BIT); + + /* provide guard,round and stick bit space */ + xm <<= 3; + ym <<= 3; + + if (xe > ye) { + /* have to shift y fraction right to align + */ + int s = xe - ye; + ym = XDPSRS(ym, s); + ye += s; + } else if (ye > xe) { + /* have to shift x fraction right to align + */ + int s = ye - xe; + xm = XDPSRS(xm, s); + xe += s; + } + assert(xe == ye); + assert(xe <= DP_EMAX); + + if (xs == ys) { + /* generate 28 bit result of adding two 27 bit numbers + * leaving result in xm,xs,xe + */ + xm = xm + ym; + xe = xe; + xs = xs; + + if (xm >> (DP_MBITS + 1 + 3)) { /* carry out */ + xm = XDPSRS1(xm); + xe++; + } + } else { + if (xm >= ym) { + xm = xm - ym; + xe = xe; + xs = xs; + } else { + xm = ym - xm; + xe = xe; + xs = ys; + } + if (xm == 0) + return ieee754dp_zero(ieee754_csr.rm == + IEEE754_RD); + + /* normalize to rounding precision */ + while ((xm >> (DP_MBITS + 3)) == 0) { + xm <<= 1; + xe--; + } + + } + DPNORMRET2(xs, xe, xm, "add", x, y); +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_cmp.c linux/arch/mips64/math-emu/dp_cmp.c --- v2.4.5/linux/arch/mips64/math-emu/dp_cmp.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/dp_cmp.c Mon Jul 2 13:56:40 2001 @@ -0,0 +1,58 @@ +/* IEEE754 floating point arithmetic + * double precision: common utilities + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754dp.h" + +int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cmp) +{ + CLEARCX; + + if (ieee754dp_isnan(x) || ieee754dp_isnan(y)) { + if (cmp & IEEE754_CUN) + return 1; + if (cmp & (IEEE754_CLT | IEEE754_CGT)) { + if (SETCX(IEEE754_INVALID_OPERATION)) + return ieee754si_xcpt(0, "fcmpf", x); + } + return 0; + } else { + long long int vx = x.bits; + long long int vy = y.bits; + + if (vx < 0) + vx = -vx ^ DP_SIGN_BIT; + if (vy < 0) + vy = -vy ^ DP_SIGN_BIT; + + if (vx < vy) + return (cmp & IEEE754_CLT) != 0; + else if (vx == vy) + return (cmp & IEEE754_CEQ) != 0; + else + return (cmp & IEEE754_CGT) != 0; + } +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_div.c linux/arch/mips64/math-emu/dp_div.c --- v2.4.5/linux/arch/mips64/math-emu/dp_div.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/dp_div.c Mon Jul 2 13:56:40 2001 @@ -0,0 +1,160 @@ +/* IEEE754 floating point arithmetic + * double precision: common utilities + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754dp.h" + +ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y) +{ + COMPXDP; + COMPYDP; + + CLEARCX; + + EXPLODEXDP; + EXPLODEYDP; + + switch (CLPAIR(xc, yc)) { + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): + return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "div", x, + y); + + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): + return ieee754dp_nanxcpt(y, "div", x, y); + + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): + return ieee754dp_nanxcpt(x, "div", x, y); + + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): + return ieee754dp_bestnan(x, y); + + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): + return y; + + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): + return x; + + + /* Infinity handeling + */ + + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): + SETCX(IEEE754_INVALID_OPERATION); + return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y); + + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): + return ieee754dp_zero(xs ^ ys); + + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): + return ieee754dp_inf(xs ^ ys); + + /* Zero handeling + */ + + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): + SETCX(IEEE754_INVALID_OPERATION); + return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y); + + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): + SETCX(IEEE754_ZERO_DIVIDE); + return ieee754dp_xcpt(ieee754dp_inf(xs ^ ys), "div", x, y); + + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): + return ieee754dp_zero(xs == ys ? 0 : 1); + + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): + DPDNORMX; + + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): + DPDNORMY; + break; + + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): + DPDNORMX; + break; + + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): + break; + } + assert(xm & DP_HIDDEN_BIT); + assert(ym & DP_HIDDEN_BIT); + + /* provide rounding space */ + xm <<= 3; + ym <<= 3; + + { + /* now the dirty work */ + + unsigned long long rm = 0; + int re = xe - ye; + unsigned long long bm; + + for (bm = DP_MBIT(DP_MBITS + 2); bm; bm >>= 1) { + if (xm >= ym) { + xm -= ym; + rm |= bm; + if (xm == 0) + break; + } + xm <<= 1; + } + rm <<= 1; + if (xm) + rm |= 1; /* have remainder, set sticky */ + + assert(rm); + + /* normalise rm to rounding precision ? + */ + while ((rm >> (DP_MBITS + 3)) == 0) { + rm <<= 1; + re--; + } + + DPNORMRET2(xs == ys ? 0 : 1, re, rm, "div", x, y); + } +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_fint.c linux/arch/mips64/math-emu/dp_fint.c --- v2.4.5/linux/arch/mips64/math-emu/dp_fint.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/dp_fint.c Mon Jul 2 13:56:40 2001 @@ -0,0 +1,78 @@ +/* IEEE754 floating point arithmetic + * double precision: common utilities + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754dp.h" + +ieee754dp ieee754dp_fint(int x) +{ + COMPXDP; + + CLEARCX; + + if (x == 0) + return ieee754dp_zero(0); + if (x == 1 || x == -1) + return ieee754dp_one(x < 0); + if (x == 10 || x == -10) + return ieee754dp_ten(x < 0); + + xs = (x < 0); + if (xs) { + if (x == (1 << 31)) + xm = ((unsigned) 1 << 31); /* max neg can't be safely negated */ + else + xm = -x; + } else { + xm = x; + } + +#if 1 + /* normalize - result can never be inexact or overflow */ + xe = DP_MBITS; + while ((xm >> DP_MBITS) == 0) { + xm <<= 1; + xe--; + } + return builddp(xs, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT); +#else + /* normalize */ + xe = DP_MBITS + 3; + while ((xm >> (DP_MBITS + 3)) == 0) { + xm <<= 1; + xe--; + } + DPNORMRET1(xs, xe, xm, "fint", x); +#endif +} + +ieee754dp ieee754dp_funs(unsigned int u) +{ + if ((int) u < 0) + return ieee754dp_add(ieee754dp_1e31(), + ieee754dp_fint(u & ~(1 << 31))); + return ieee754dp_fint(u); +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_flong.c linux/arch/mips64/math-emu/dp_flong.c --- v2.4.5/linux/arch/mips64/math-emu/dp_flong.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/dp_flong.c Mon Jul 2 13:56:40 2001 @@ -0,0 +1,76 @@ +/* IEEE754 floating point arithmetic + * double precision: common utilities + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754dp.h" + +ieee754dp ieee754dp_flong(long long x) +{ + COMPXDP; + + CLEARCX; + + if (x == 0) + return ieee754dp_zero(0); + if (x == 1 || x == -1) + return ieee754dp_one(x < 0); + if (x == 10 || x == -10) + return ieee754dp_ten(x < 0); + + xs = (x < 0); + if (xs) { + if (x == (1ULL << 63)) + xm = (1ULL << 63); /* max neg can't be safely negated */ + else + xm = -x; + } else { + xm = x; + } + + /* normalize */ + xe = DP_MBITS + 3; + if (xm >> (DP_MBITS + 1 + 3)) { + /* shunt out overflow bits */ + while (xm >> (DP_MBITS + 1 + 3)) { + XDPSRSX1(); + } + } else { + /* normalize in grs extended double precision */ + while ((xm >> (DP_MBITS + 3)) == 0) { + xm <<= 1; + xe--; + } + } + DPNORMRET1(xs, xe, xm, "dp_flong", x); +} + +ieee754dp ieee754dp_fulong(unsigned long long u) +{ + if ((long long) u < 0) + return ieee754dp_add(ieee754dp_1e63(), + ieee754dp_flong(u & ~(1ULL << 63))); + return ieee754dp_flong(u); +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_frexp.c linux/arch/mips64/math-emu/dp_frexp.c --- v2.4.5/linux/arch/mips64/math-emu/dp_frexp.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/dp_frexp.c Mon Jul 2 13:56:40 2001 @@ -0,0 +1,53 @@ +/* IEEE754 floating point arithmetic + * double precision: common utilities + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754dp.h" + +/* close to ieeep754dp_logb +*/ +ieee754dp ieee754dp_frexp(ieee754dp x, int *eptr) +{ + COMPXDP; + CLEARCX; + EXPLODEXDP; + + switch (xc) { + case IEEE754_CLASS_SNAN: + case IEEE754_CLASS_QNAN: + case IEEE754_CLASS_INF: + case IEEE754_CLASS_ZERO: + *eptr = 0; + return x; + case IEEE754_CLASS_DNORM: + DPDNORMX; + break; + case IEEE754_CLASS_NORM: + break; + } + *eptr = xe + 1; + return builddp(xs, -1 + DP_EBIAS, xm & ~DP_HIDDEN_BIT); +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_fsp.c linux/arch/mips64/math-emu/dp_fsp.c --- v2.4.5/linux/arch/mips64/math-emu/dp_fsp.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/dp_fsp.c Mon Jul 2 13:56:40 2001 @@ -0,0 +1,70 @@ +/* IEEE754 floating point arithmetic + * double precision: common utilities + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754dp.h" + +ieee754dp ieee754dp_fsp(ieee754sp x) +{ + COMPXSP; + + CLEARCX; + + EXPLODEXSP; + + switch (xc) { + case IEEE754_CLASS_QNAN: + case IEEE754_CLASS_SNAN: + return ieee754dp_nanxcpt(builddp(xs, + DP_EMAX + 1 + DP_EBIAS, + ((unsigned long long) xm + << (DP_MBITS - + SP_MBITS))), "fsp", + x); + case IEEE754_CLASS_INF: + return ieee754dp_inf(xs); + case IEEE754_CLASS_ZERO: + return ieee754dp_zero(xs); + case IEEE754_CLASS_DNORM: + /* normalize */ + while ((xm >> SP_MBITS) == 0) { + xm <<= 1; + xe--; + } + break; + case IEEE754_CLASS_NORM: + break; + } + + /* CANT possibly overflow,underflow, or need rounding + */ + + /* drop the hidden bit */ + xm &= ~SP_HIDDEN_BIT; + + return builddp(xs, xe + DP_EBIAS, + (unsigned long long) xm << (DP_MBITS - SP_MBITS)); +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_logb.c linux/arch/mips64/math-emu/dp_logb.c --- v2.4.5/linux/arch/mips64/math-emu/dp_logb.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/dp_logb.c Mon Jul 2 13:56:40 2001 @@ -0,0 +1,54 @@ +/* IEEE754 floating point arithmetic + * double precision: common utilities + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754dp.h" + +ieee754dp ieee754dp_logb(ieee754dp x) +{ + COMPXDP; + + CLEARCX; + + EXPLODEXDP; + + switch (xc) { + case IEEE754_CLASS_SNAN: + return ieee754dp_nanxcpt(x, "logb", x); + case IEEE754_CLASS_QNAN: + return x; + case IEEE754_CLASS_INF: + return ieee754dp_inf(0); + case IEEE754_CLASS_ZERO: + return ieee754dp_inf(1); + case IEEE754_CLASS_DNORM: + DPDNORMX; + break; + case IEEE754_CLASS_NORM: + break; + } + return ieee754dp_fint(xe); +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_modf.c linux/arch/mips64/math-emu/dp_modf.c --- v2.4.5/linux/arch/mips64/math-emu/dp_modf.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/dp_modf.c Mon Jul 2 13:56:40 2001 @@ -0,0 +1,80 @@ +/* IEEE754 floating point arithmetic + * double precision: common utilities + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754dp.h" + +/* modf function is always exact for a finite number +*/ +ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip) +{ + COMPXDP; + + CLEARCX; + + EXPLODEXDP; + + switch (xc) { + case IEEE754_CLASS_SNAN: + case IEEE754_CLASS_QNAN: + case IEEE754_CLASS_INF: + case IEEE754_CLASS_ZERO: + *ip = x; + return x; + case IEEE754_CLASS_DNORM: + /* far to small */ + *ip = ieee754dp_zero(xs); + return x; + case IEEE754_CLASS_NORM: + break; + } + if (xe < 0) { + *ip = ieee754dp_zero(xs); + return x; + } + if (xe >= DP_MBITS) { + *ip = x; + return ieee754dp_zero(xs); + } + /* generate ipart mantissa by clearing bottom bits + */ + *ip = builddp(xs, xe + DP_EBIAS, + ((xm >> (DP_MBITS - xe)) << (DP_MBITS - xe)) & + ~DP_HIDDEN_BIT); + + /* generate fpart mantissa by clearing top bits + * and normalizing (must be able to normalize) + */ + xm = (xm << (64 - (DP_MBITS - xe))) >> (64 - (DP_MBITS - xe)); + if (xm == 0) + return ieee754dp_zero(xs); + + while ((xm >> DP_MBITS) == 0) { + xm <<= 1; + xe--; + } + return builddp(xs, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT); +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_mul.c linux/arch/mips64/math-emu/dp_mul.c --- v2.4.5/linux/arch/mips64/math-emu/dp_mul.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/dp_mul.c Mon Jul 2 13:56:40 2001 @@ -0,0 +1,180 @@ +/* IEEE754 floating point arithmetic + * double precision: common utilities + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754dp.h" + +ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y) +{ + COMPXDP; + COMPYDP; + + CLEARCX; + + EXPLODEXDP; + EXPLODEYDP; + + switch (CLPAIR(xc, yc)) { + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): + return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "mul", x, + y); + + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): + return ieee754dp_nanxcpt(y, "mul", x, y); + + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): + return ieee754dp_nanxcpt(x, "mul", x, y); + + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): + return ieee754dp_bestnan(x, y); + + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): + return y; + + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): + return x; + + + /* Infinity handeling */ + + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): + SETCX(IEEE754_INVALID_OPERATION); + return ieee754dp_xcpt(ieee754dp_indef(), "mul", x, y); + + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): + return ieee754dp_inf(xs ^ ys); + + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): + return ieee754dp_zero(xs ^ ys); + + + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): + DPDNORMX; + + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): + DPDNORMY; + break; + + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): + DPDNORMX; + break; + + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): + break; + } + /* rm = xm * ym, re = xe+ye basicly */ + assert(xm & DP_HIDDEN_BIT); + assert(ym & DP_HIDDEN_BIT); + { + int re = xe + ye; + int rs = xs ^ ys; + unsigned long long rm; + + /* shunt to top of word */ + xm <<= 64 - (DP_MBITS + 1); + ym <<= 64 - (DP_MBITS + 1); + + /* multiply 32bits xm,ym to give high 32bits rm with stickness + */ + + /* 32 * 32 => 64 */ +#define DPXMULT(x,y) ((unsigned long long)(x) * (unsigned long long)y) + + { + unsigned lxm = xm; + unsigned hxm = xm >> 32; + unsigned lym = ym; + unsigned hym = ym >> 32; + unsigned long long lrm; + unsigned long long hrm; + + lrm = DPXMULT(lxm, lym); + hrm = DPXMULT(hxm, hym); + + { + unsigned long long t = DPXMULT(lxm, hym); + { + unsigned long long at = + lrm + (t << 32); + hrm += at < lrm; + lrm = at; + } + hrm = hrm + (t >> 32); + } + + { + unsigned long long t = DPXMULT(hxm, lym); + { + unsigned long long at = + lrm + (t << 32); + hrm += at < lrm; + lrm = at; + } + hrm = hrm + (t >> 32); + } + rm = hrm | (lrm != 0); + } + + /* + * sticky shift down to normal rounding precision + */ + if ((signed long long) rm < 0) { + rm = + (rm >> (64 - (DP_MBITS + 1 + 3))) | + ((rm << (DP_MBITS + 1 + 3)) != 0); + re++; + } else { + rm = + (rm >> (64 - (DP_MBITS + 1 + 3 + 1))) | + ((rm << (DP_MBITS + 1 + 3 + 1)) != 0); + } + assert(rm & (DP_HIDDEN_BIT << 3)); + DPNORMRET2(rs, re, rm, "mul", x, y); + } +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_scalb.c linux/arch/mips64/math-emu/dp_scalb.c --- v2.4.5/linux/arch/mips64/math-emu/dp_scalb.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/dp_scalb.c Mon Jul 2 13:56:40 2001 @@ -0,0 +1,58 @@ +/* IEEE754 floating point arithmetic + * double precision: common utilities + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754dp.h" + +ieee754dp ieee754dp_scalb(ieee754dp x, int n) +{ + COMPXDP; + + CLEARCX; + + EXPLODEXDP; + + switch (xc) { + case IEEE754_CLASS_SNAN: + return ieee754dp_nanxcpt(x, "scalb", x, n); + case IEEE754_CLASS_QNAN: + case IEEE754_CLASS_INF: + case IEEE754_CLASS_ZERO: + return x; + case IEEE754_CLASS_DNORM: + DPDNORMX; + break; + case IEEE754_CLASS_NORM: + break; + } + DPNORMRET2(xs, xe + n, xm << 3, "scalb", x, n); +} + + +ieee754dp ieee754dp_ldexp(ieee754dp x, int n) +{ + return ieee754dp_scalb(x, n); +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_simple.c linux/arch/mips64/math-emu/dp_simple.c --- v2.4.5/linux/arch/mips64/math-emu/dp_simple.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/dp_simple.c Mon Jul 2 13:56:40 2001 @@ -0,0 +1,66 @@ +/* IEEE754 floating point arithmetic + * double precision: common utilities + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754dp.h" + +int ieee754dp_finite(ieee754dp x) +{ + return DPBEXP(x) != DP_EMAX + 1 + DP_EBIAS; +} + +ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y) +{ + CLEARCX; + DPSIGN(x) = DPSIGN(y); + return x; +} + + +ieee754dp ieee754dp_neg(ieee754dp x) +{ + CLEARCX; + + if (ieee754dp_isnan(x)) /* but not infinity */ + return ieee754dp_nanxcpt(x, "neg", x); + + /* quick fix up */ + DPSIGN(x) ^= 1; + return x; +} + + +ieee754dp ieee754dp_abs(ieee754dp x) +{ + CLEARCX; + + if (ieee754dp_isnan(x)) /* but not infinity */ + return ieee754dp_nanxcpt(x, "abs", x); + + /* quick fix up */ + DPSIGN(x) = 0; + return x; +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_sqrt.c linux/arch/mips64/math-emu/dp_sqrt.c --- v2.4.5/linux/arch/mips64/math-emu/dp_sqrt.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/dp_sqrt.c Mon Jul 2 13:56:40 2001 @@ -0,0 +1,167 @@ +/* IEEE754 floating point arithmetic + * double precision square root + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754dp.h" + +static const struct ieee754dp_konst knan = { +#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__) + 0, 0, DP_EBIAS + DP_EMAX + 1, 0 +#else + 0, DP_EBIAS + DP_EMAX + 1, 0, 0 +#endif +}; + +#define nan ((ieee754dp)knan) + +static const unsigned table[] = { + 0, 1204, 3062, 5746, 9193, 13348, 18162, 23592, + 29598, 36145, 43202, 50740, 58733, 67158, 75992, + 85215, 83599, 71378, 60428, 50647, 41945, 34246, + 27478, 21581, 16499, 12183, 8588, 5674, 3403, + 1742, 661, 130 +}; + +ieee754dp ieee754dp_sqrt(ieee754dp x) +{ + struct ieee754_csr oldcsr; + ieee754dp y, z, t; + unsigned scalx, yh; + COMPXDP; + + EXPLODEXDP; + + /* x == INF or NAN? */ + switch (xc) { + case IEEE754_CLASS_QNAN: + case IEEE754_CLASS_SNAN: + /* sqrt(Nan) = Nan */ + return ieee754dp_nanxcpt(x, "sqrt"); + case IEEE754_CLASS_ZERO: + /* sqrt(0) = 0 */ + return x; + case IEEE754_CLASS_INF: + if (xs) + /* sqrt(-Inf) = Nan */ + return ieee754dp_nanxcpt(nan, "sqrt"); + /* sqrt(+Inf) = Inf */ + return x; + case IEEE754_CLASS_DNORM: + DPDNORMX; + /* fall through */ + case IEEE754_CLASS_NORM: + if (xs) + /* sqrt(-x) = Nan */ + return ieee754dp_nanxcpt(nan, "sqrt"); + break; + } + + /* save old csr; switch off INX enable & flag; set RN rounding */ + oldcsr = ieee754_csr; + ieee754_csr.mx &= ~IEEE754_INEXACT; + ieee754_csr.sx &= ~IEEE754_INEXACT; + ieee754_csr.rm = IEEE754_RN; + + /* adjust exponent to prevent overflow */ + scalx = 0; + if (xe > 512) { /* x > 2**-512? */ + xe -= 512; /* x = x / 2**512 */ + scalx += 256; + } else if (xe < -512) { /* x < 2**-512? */ + xe += 512; /* x = x * 2**512 */ + scalx -= 256; + } + + y = x = builddp(0, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT); + + /* magic initial approximation to almost 8 sig. bits */ + yh = y.bits >> 32; + yh = (yh >> 1) + 0x1ff80000; + yh = yh - table[(yh >> 15) & 31]; + y.bits = ((unsigned long long) yh << 32) | (y.bits & 0xffffffff); + + /* Heron's rule once with correction to improve to ~18 sig. bits */ + /* t=x/y; y=y+t; py[n0]=py[n0]-0x00100006; py[n1]=0; */ + t = ieee754dp_div(x, y); + y = ieee754dp_add(y, t); + y.bits -= 0x0010000600000000LL; + y.bits &= 0xffffffff00000000LL; + + /* triple to almost 56 sig. bits: y ~= sqrt(x) to within 1 ulp */ + /* t=y*y; z=t; pt[n0]+=0x00100000; t+=z; z=(x-z)*y; */ + z = t = ieee754dp_mul(y, y); + t.parts.bexp += 0x001; + t = ieee754dp_add(t, z); + z = ieee754dp_mul(ieee754dp_sub(x, z), y); + + /* t=z/(t+x) ; pt[n0]+=0x00100000; y+=t; */ + t = ieee754dp_div(z, ieee754dp_add(t, x)); + t.parts.bexp += 0x001; + y = ieee754dp_add(y, t); + + /* twiddle last bit to force y correctly rounded */ + + /* set RZ, clear INEX flag */ + ieee754_csr.rm = IEEE754_RZ; + ieee754_csr.sx &= ~IEEE754_INEXACT; + + /* t=x/y; ...chopped quotient, possibly inexact */ + t = ieee754dp_div(x, y); + + if (ieee754_csr.sx & IEEE754_INEXACT || t.bits != y.bits) { + + if (!(ieee754_csr.sx & IEEE754_INEXACT)) + /* t = t-ulp */ + t.bits -= 1; + + /* add inexact to result status */ + oldcsr.cx |= IEEE754_INEXACT; + oldcsr.sx |= IEEE754_INEXACT; + + switch (oldcsr.rm) { + case IEEE754_RP: + y.bits += 1; + /* drop through */ + case IEEE754_RN: + t.bits += 1; + break; + } + + /* y=y+t; ...chopped sum */ + y = ieee754dp_add(y, t); + + /* adjust scalx for correctly rounded sqrt(x) */ + scalx -= 1; + } + + /* py[n0]=py[n0]+scalx; ...scale back y */ + y.parts.bexp += scalx; + + /* restore rounding mode, possibly set inexact */ + ieee754_csr = oldcsr; + + return y; +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_sub.c linux/arch/mips64/math-emu/dp_sub.c --- v2.4.5/linux/arch/mips64/math-emu/dp_sub.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/dp_sub.c Mon Jul 2 13:56:40 2001 @@ -0,0 +1,194 @@ +/* IEEE754 floating point arithmetic + * double precision: common utilities + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754dp.h" + +ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y) +{ + COMPXDP; + COMPYDP; + + CLEARCX; + + EXPLODEXDP; + EXPLODEYDP; + + switch (CLPAIR(xc, yc)) { + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): + return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "sub", x, + y); + + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): + return ieee754dp_nanxcpt(y, "sub", x, y); + + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): + return ieee754dp_nanxcpt(x, "sub", x, y); + + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): + return ieee754dp_bestnan(x, y); + + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): + return y; + + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): + return x; + + + /* Inifity handeling + */ + + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): + if (xs != ys) + return x; + SETCX(IEEE754_INVALID_OPERATION); + return ieee754dp_xcpt(ieee754dp_indef(), "sub", x, y); + + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): + return ieee754dp_inf(ys ^ 1); + + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): + return x; + + /* Zero handeling + */ + + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): + if (xs != ys) + return x; + else + return ieee754dp_zero(ieee754_csr.rm == + IEEE754_RD); + + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): + return x; + + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): + /* quick fix up */ + DPSIGN(y) ^= 1; + return y; + + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): + DPDNORMX; + /* FAAL THOROUGH */ + + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): + /* normalize ym,ye */ + DPDNORMY; + break; + + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): + /* normalize xm,xe */ + DPDNORMX; + break; + + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): + break; + } + /* flip sign of y and handle as add */ + ys ^= 1; + + assert(xm & DP_HIDDEN_BIT); + assert(ym & DP_HIDDEN_BIT); + + + /* provide guard,round and stick bit dpace */ + xm <<= 3; + ym <<= 3; + + if (xe > ye) { + /* have to shift y fraction right to align + */ + int s = xe - ye; + ym = XDPSRS(ym, s); + ye += s; + } else if (ye > xe) { + /* have to shift x fraction right to align + */ + int s = ye - xe; + xm = XDPSRS(xm, s); + xe += s; + } + assert(xe == ye); + assert(xe <= DP_EMAX); + + if (xs == ys) { + /* generate 28 bit result of adding two 27 bit numbers + */ + xm = xm + ym; + xe = xe; + xs = xs; + + if (xm >> (DP_MBITS + 1 + 3)) { /* carry out */ + xm = XDPSRS1(xm); /* shift preserving sticky */ + xe++; + } + } else { + if (xm >= ym) { + xm = xm - ym; + xe = xe; + xs = xs; + } else { + xm = ym - xm; + xe = xe; + xs = ys; + } + if (xm == 0) { + if (ieee754_csr.rm == IEEE754_RD) + return ieee754dp_zero(1); /* round negative inf. => sign = -1 */ + else + return ieee754dp_zero(0); /* other round modes => sign = 1 */ + } + + /* normalize to rounding precision + */ + while ((xm >> (DP_MBITS + 3)) == 0) { + xm <<= 1; + xe--; + } + } + DPNORMRET2(xs, xe, xm, "sub", x, y); +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_tint.c linux/arch/mips64/math-emu/dp_tint.c --- v2.4.5/linux/arch/mips64/math-emu/dp_tint.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/dp_tint.c Mon Jul 2 13:56:41 2001 @@ -0,0 +1,88 @@ +/* IEEE754 floating point arithmetic + * double precision: common utilities + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754dp.h" + +int ieee754dp_tint(ieee754dp x) +{ + COMPXDP; + + CLEARCX; + + EXPLODEXDP; + + switch (xc) { + case IEEE754_CLASS_SNAN: + case IEEE754_CLASS_QNAN: + SETCX(IEEE754_INVALID_OPERATION); + return ieee754si_xcpt(ieee754si_indef(), "fixdp", x); + case IEEE754_CLASS_INF: + SETCX(IEEE754_OVERFLOW); + return ieee754si_xcpt(ieee754si_indef(), "fixdp", x); + case IEEE754_CLASS_ZERO: + return 0; + case IEEE754_CLASS_DNORM: /* much to small */ + SETCX(IEEE754_UNDERFLOW); + return ieee754si_xcpt(0, "fixdp", x); + case IEEE754_CLASS_NORM: + break; + } + if (xe >= 31) { + SETCX(IEEE754_OVERFLOW); + return ieee754si_xcpt(ieee754si_indef(), "fix", x); + } + if (xe < 0) { + SETCX(IEEE754_UNDERFLOW); + return ieee754si_xcpt(0, "fix", x); + } + /* oh gawd */ + if (xe > DP_MBITS) { + xm <<= xe - DP_MBITS; + } else if (xe < DP_MBITS) { + /* XXX no rounding + */ + xm >>= DP_MBITS - xe; + } + if (xs) + return -xm; + else + return xm; +} + + +unsigned int ieee754dp_tuns(ieee754dp x) +{ + ieee754dp hb = ieee754dp_1e31(); + + /* what if x < 0 ?? */ + if (ieee754dp_lt(x, hb)) + return (unsigned) ieee754dp_tint(x); + + return (unsigned) ieee754dp_tint(ieee754dp_sub(x, hb)) | + ((unsigned) 1 << 31); +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_tlong.c linux/arch/mips64/math-emu/dp_tlong.c --- v2.4.5/linux/arch/mips64/math-emu/dp_tlong.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/dp_tlong.c Mon Jul 2 13:56:41 2001 @@ -0,0 +1,141 @@ +/* IEEE754 floating point arithmetic + * double precision: common utilities + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754dp.h" + +long long ieee754dp_tlong(ieee754dp x) +{ + COMPXDP; + + CLEARCX; + + EXPLODEXDP; + + switch (xc) { + case IEEE754_CLASS_SNAN: + case IEEE754_CLASS_QNAN: + SETCX(IEEE754_INVALID_OPERATION); + return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x); + case IEEE754_CLASS_INF: + SETCX(IEEE754_OVERFLOW); + return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x); + case IEEE754_CLASS_ZERO: + return 0; + case IEEE754_CLASS_DNORM: /* much too small */ + SETCX(IEEE754_UNDERFLOW); + return ieee754di_xcpt(0, "dp_tlong", x); + case IEEE754_CLASS_NORM: + break; + } + if (xe >= 63) { + SETCX(IEEE754_OVERFLOW); + return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x); + } + if (xe < 0) { + if (ieee754_csr.rm == IEEE754_RU) { + if (xs) { /* Negative */ + return 0x0000000000000000LL; + } else { /* Positive */ + return 0x0000000000000001LL; + } + } else if (ieee754_csr.rm == IEEE754_RD) { + if (xs) { /* Negative , return -1 */ + return 0xffffffffffffffffLL; + } else { /* Positive */ + return 0x0000000000000000LL; + } + } else { + SETCX(IEEE754_UNDERFLOW); + return ieee754di_xcpt(0, "dp_tlong", x); + } + } + /* oh gawd */ + if (xe > DP_MBITS) { + xm <<= xe - DP_MBITS; + } else if (xe < DP_MBITS) { + unsigned long long residue; + unsigned long long mask = 0; + int i; + int round; + int sticky; + int odd; + + /* compute mask */ + for (i = 0; i < DP_MBITS - xe; i++) { + mask = mask << 1; + mask = mask | 0x1; + } + residue = (xm & mask) << (64 - (DP_MBITS - xe)); + round = + ((0x8000000000000000LL & residue) != + 0x0000000000000000LL); + sticky = + ((0x7fffffffffffffffLL & residue) != + 0x0000000000000000LL); + + xm >>= DP_MBITS - xe; + + odd = ((xm & 0x1) != 0x0000000000000000LL); + + /* Do the rounding */ + if (!round && sticky) { + if ((ieee754_csr.rm == IEEE754_RU && !xs) + || (ieee754_csr.rm == IEEE754_RD && xs)) { + xm++; + } + } else if (round && !sticky) { + if ((ieee754_csr.rm == IEEE754_RU && !xs) + || (ieee754_csr.rm == IEEE754_RD && xs) + || (ieee754_csr.rm == IEEE754_RN && odd)) { + xm++; + } + } else if (round && sticky) { + if ((ieee754_csr.rm == IEEE754_RU && !xs) + || (ieee754_csr.rm == IEEE754_RD && xs) + || (ieee754_csr.rm == IEEE754_RN)) { + xm++; + } + } + } + if (xs) + return -xm; + else + return xm; +} + + +unsigned long long ieee754dp_tulong(ieee754dp x) +{ + ieee754dp hb = ieee754dp_1e63(); + + /* what if x < 0 ?? */ + if (ieee754dp_lt(x, hb)) + return (unsigned long long) ieee754dp_tlong(x); + + return (unsigned long long) ieee754dp_tlong(ieee754dp_sub(x, hb)) | + (1ULL << 63); +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/ieee754.c linux/arch/mips64/math-emu/ieee754.c --- v2.4.5/linux/arch/mips64/math-emu/ieee754.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/ieee754.c Mon Jul 2 13:56:41 2001 @@ -0,0 +1,138 @@ +/* ieee754 floating point arithmetic + * single and double precision + * + * BUGS + * not much dp done + * doesnt generate IEEE754_INEXACT + * + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754int.h" + +#define DP_EBIAS 1023 +#define DP_EMIN (-1022) +#define DP_EMAX 1023 + +#define SP_EBIAS 127 +#define SP_EMIN (-126) +#define SP_EMAX 127 + +/* indexed by class */ +const char *const ieee754_cname[] = { + "Normal", + "Zero", + "Denormal", + "Infinity", + "QNaN", + "SNaN", +}; + +/* the control status register +*/ +struct ieee754_csr ieee754_csr; + +/* special constants +*/ + + +#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__) +#define SPSTR(s,b,m) {m,b,s} +#define DPSTR(s,b,mh,ml) {ml,mh,b,s} +#endif + +#ifdef __MIPSEB__ +#define SPSTR(s,b,m) {s,b,m} +#define DPSTR(s,b,mh,ml) {s,b,mh,ml} +#endif + +const struct ieee754dp_konst __ieee754dp_spcvals[] = { + DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 0), /* + zero */ + DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 0), /* - zero */ + DPSTR(0, DP_EBIAS, 0, 0), /* + 1.0 */ + DPSTR(1, DP_EBIAS, 0, 0), /* - 1.0 */ + DPSTR(0, 3 + DP_EBIAS, 0x40000, 0), /* + 10.0 */ + DPSTR(1, 3 + DP_EBIAS, 0x40000, 0), /* - 10.0 */ + DPSTR(0, DP_EMAX + 1 + DP_EBIAS, 0, 0), /* + infinity */ + DPSTR(1, DP_EMAX + 1 + DP_EBIAS, 0, 0), /* - infinity */ + DPSTR(0, DP_EMAX + 1 + DP_EBIAS, 0x40000, 0), /* + indef quiet Nan */ + DPSTR(0, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF), /* + max */ + DPSTR(1, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF), /* - max */ + DPSTR(0, DP_EMIN + DP_EBIAS, 0, 0), /* + min normal */ + DPSTR(1, DP_EMIN + DP_EBIAS, 0, 0), /* - min normal */ + DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 1), /* + min denormal */ + DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 1), /* - min denormal */ + DPSTR(0, 31 + DP_EBIAS, 0, 0), /* + 1.0e31 */ + DPSTR(0, 63 + DP_EBIAS, 0, 0), /* + 1.0e63 */ +}; + +const struct ieee754sp_konst __ieee754sp_spcvals[] = { + SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 0), /* + zero */ + SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 0), /* - zero */ + SPSTR(0, SP_EBIAS, 0), /* + 1.0 */ + SPSTR(1, SP_EBIAS, 0), /* - 1.0 */ + SPSTR(0, 3 + SP_EBIAS, 0x200000), /* + 10.0 */ + SPSTR(1, 3 + SP_EBIAS, 0x200000), /* - 10.0 */ + SPSTR(0, SP_EMAX + 1 + SP_EBIAS, 0), /* + infinity */ + SPSTR(1, SP_EMAX + 1 + SP_EBIAS, 0), /* - infinity */ + SPSTR(0, SP_EMAX + 1 + SP_EBIAS, 0x200000), /* + indef quiet Nan */ + SPSTR(0, SP_EMAX + SP_EBIAS, 0x7FFFFF), /* + max normal */ + SPSTR(1, SP_EMAX + SP_EBIAS, 0x7FFFFF), /* - max normal */ + SPSTR(0, SP_EMIN + SP_EBIAS, 0), /* + min normal */ + SPSTR(1, SP_EMIN + SP_EBIAS, 0), /* - min normal */ + SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 1), /* + min denormal */ + SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 1), /* - min denormal */ + SPSTR(0, 31 + SP_EBIAS, 0), /* + 1.0e31 */ + SPSTR(0, 63 + SP_EBIAS, 0), /* + 1.0e63 */ +}; + + +int ieee754si_xcpt(int r, const char *op, ...) +{ + struct ieee754xctx ax; + + if (!TSTX()) + return r; + ax.op = op; + ax.rt = IEEE754_RT_SI; + ax.rv.si = r; + va_start(ax.ap, op); + ieee754_xcpt(&ax); + return ax.rv.si; +} + +long long ieee754di_xcpt(long long r, const char *op, ...) +{ + struct ieee754xctx ax; + + if (!TSTX()) + return r; + ax.op = op; + ax.rt = IEEE754_RT_DI; + ax.rv.di = r; + va_start(ax.ap, op); + ieee754_xcpt(&ax); + return ax.rv.di; +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/ieee754.h linux/arch/mips64/math-emu/ieee754.h --- v2.4.5/linux/arch/mips64/math-emu/ieee754.h Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/ieee754.h Mon Jul 2 13:56:41 2001 @@ -0,0 +1,490 @@ +/* single and double precision fp ops + * missing extended precision. +*/ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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. + * + * ######################################################################## + */ + +/************************************************************************** + * Nov 7, 2000 + * Modification to allow integration with Linux kernel + * + * Kevin D. Kissell, kevink@mips.com and Carsten Langgard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + *************************************************************************/ + +#ifdef __KERNEL__ +/* Going from Algorithmics to Linux native environment, add this */ +#include + +/* + * Not very pretty, but the Linux kernel's normal va_list definition + * does not allow it to be used as a structure element, as it is here. + */ +#ifndef _STDARG_H +#include +#endif + +#else + +/* Note that __KERNEL__ is taken to mean Linux kernel */ + +#if #system(OpenBSD) +#include +#endif +#include + +#endif /* __KERNEL__ */ + +#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__) +struct ieee754dp_konst { + unsigned mantlo:32; + unsigned manthi:20; + unsigned bexp:11; + unsigned sign:1; +}; +struct ieee754sp_konst { + unsigned mant:23; + unsigned bexp:8; + unsigned sign:1; +}; + +typedef union _ieee754dp { + struct ieee754dp_konst oparts; + struct { + unsigned long long mant:52; + unsigned int bexp:11; + unsigned int sign:1; + } parts; + unsigned long long bits; + double d; +} ieee754dp; + +typedef union _ieee754sp { + struct ieee754sp_konst parts; + float f; + unsigned long bits; +} ieee754sp; +#endif + +#if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__) +struct ieee754dp_konst { + unsigned sign:1; + unsigned bexp:11; + unsigned manthi:20; + unsigned mantlo:32; +}; +typedef union _ieee754dp { + struct ieee754dp_konst oparts; + struct { + unsigned int sign:1; + unsigned int bexp:11; + unsigned long long mant:52; + } parts; + double d; + unsigned long long bits; +} ieee754dp; + +struct ieee754sp_konst { + unsigned sign:1; + unsigned bexp:8; + unsigned mant:23; +}; + +typedef union _ieee754sp { + struct ieee754sp_konst parts; + float f; + unsigned long bits; +} ieee754sp; +#endif + +/* + * single precision (often aka float) +*/ +int ieee754sp_finite(ieee754sp x); +int ieee754sp_class(ieee754sp x); + +ieee754sp ieee754sp_abs(ieee754sp x); +ieee754sp ieee754sp_neg(ieee754sp x); +ieee754sp ieee754sp_scalb(ieee754sp x, int); +ieee754sp ieee754sp_logb(ieee754sp x); + +/* x with sign of y */ +ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y); + +ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y); +ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y); +ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y); +ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y); + +ieee754sp ieee754sp_fint(int x); +ieee754sp ieee754sp_funs(unsigned x); +ieee754sp ieee754sp_flong(long long x); +ieee754sp ieee754sp_fulong(unsigned long long x); +ieee754sp ieee754sp_fdp(ieee754dp x); + +int ieee754sp_tint(ieee754sp x); +unsigned int ieee754sp_tuns(ieee754sp x); +long long ieee754sp_tlong(ieee754sp x); +unsigned long long ieee754sp_tulong(ieee754sp x); + +int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cop); +/* + * basic sp math + */ +ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip); +ieee754sp ieee754sp_frexp(ieee754sp x, int *exp); +ieee754sp ieee754sp_ldexp(ieee754sp x, int exp); + +ieee754sp ieee754sp_ceil(ieee754sp x); +ieee754sp ieee754sp_floor(ieee754sp x); +ieee754sp ieee754sp_trunc(ieee754sp x); + +ieee754sp ieee754sp_sqrt(ieee754sp x); + +/* + * double precision (often aka double) +*/ +int ieee754dp_finite(ieee754dp x); +int ieee754dp_class(ieee754dp x); + +/* x with sign of y */ +ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y); + +ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y); +ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y); +ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y); +ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y); + +ieee754dp ieee754dp_abs(ieee754dp x); +ieee754dp ieee754dp_neg(ieee754dp x); +ieee754dp ieee754dp_scalb(ieee754dp x, int); + +/* return exponent as integer in floating point format + */ +ieee754dp ieee754dp_logb(ieee754dp x); + +ieee754dp ieee754dp_fint(int x); +ieee754dp ieee754dp_funs(unsigned x); +ieee754dp ieee754dp_flong(long long x); +ieee754dp ieee754dp_fulong(unsigned long long x); +ieee754dp ieee754dp_fsp(ieee754sp x); + +ieee754dp ieee754dp_ceil(ieee754dp x); +ieee754dp ieee754dp_floor(ieee754dp x); +ieee754dp ieee754dp_trunc(ieee754dp x); + +int ieee754dp_tint(ieee754dp x); +unsigned int ieee754dp_tuns(ieee754dp x); +long long ieee754dp_tlong(ieee754dp x); +unsigned long long ieee754dp_tulong(ieee754dp x); + +int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cop); +/* + * basic sp math + */ +ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip); +ieee754dp ieee754dp_frexp(ieee754dp x, int *exp); +ieee754dp ieee754dp_ldexp(ieee754dp x, int exp); + +ieee754dp ieee754dp_ceil(ieee754dp x); +ieee754dp ieee754dp_floor(ieee754dp x); +ieee754dp ieee754dp_trunc(ieee754dp x); + +ieee754dp ieee754dp_sqrt(ieee754dp x); + + + +/* 5 types of floating point number +*/ +#define IEEE754_CLASS_NORM 0x00 +#define IEEE754_CLASS_ZERO 0x01 +#define IEEE754_CLASS_DNORM 0x02 +#define IEEE754_CLASS_INF 0x03 +#define IEEE754_CLASS_SNAN 0x04 +#define IEEE754_CLASS_QNAN 0x05 +extern const char *const ieee754_cname[]; + +/* exception numbers */ +#define IEEE754_INEXACT 0x01 +#define IEEE754_UNDERFLOW 0x02 +#define IEEE754_OVERFLOW 0x04 +#define IEEE754_ZERO_DIVIDE 0x08 +#define IEEE754_INVALID_OPERATION 0x10 + +/* cmp operators +*/ +#define IEEE754_CLT 0x01 +#define IEEE754_CEQ 0x02 +#define IEEE754_CGT 0x04 +#define IEEE754_CUN 0x08 + +/* rounding mode +*/ +#define IEEE754_RN 0 /* round to nearest */ +#define IEEE754_RZ 1 /* round toward zero */ +#define IEEE754_RD 2 /* round toward -Infinity */ +#define IEEE754_RU 3 /* round toward +Infinity */ + +/* other naming */ +#define IEEE754_RM IEEE754_RD +#define IEEE754_RP IEEE754_RU + +/* "normal" comparisons +*/ +static __inline int ieee754sp_eq(ieee754sp x, ieee754sp y) +{ + return ieee754sp_cmp(x, y, IEEE754_CEQ); +} + +static __inline int ieee754sp_ne(ieee754sp x, ieee754sp y) +{ + return ieee754sp_cmp(x, y, + IEEE754_CLT | IEEE754_CGT | IEEE754_CUN); +} + +static __inline int ieee754sp_lt(ieee754sp x, ieee754sp y) +{ + return ieee754sp_cmp(x, y, IEEE754_CLT); +} + +static __inline int ieee754sp_le(ieee754sp x, ieee754sp y) +{ + return ieee754sp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ); +} + +static __inline int ieee754sp_gt(ieee754sp x, ieee754sp y) +{ + return ieee754sp_cmp(x, y, IEEE754_CGT); +} + + +static __inline int ieee754sp_ge(ieee754sp x, ieee754sp y) +{ + return ieee754sp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ); +} + +static __inline int ieee754dp_eq(ieee754dp x, ieee754dp y) +{ + return ieee754dp_cmp(x, y, IEEE754_CEQ); +} + +static __inline int ieee754dp_ne(ieee754dp x, ieee754dp y) +{ + return ieee754dp_cmp(x, y, + IEEE754_CLT | IEEE754_CGT | IEEE754_CUN); +} + +static __inline int ieee754dp_lt(ieee754dp x, ieee754dp y) +{ + return ieee754dp_cmp(x, y, IEEE754_CLT); +} + +static __inline int ieee754dp_le(ieee754dp x, ieee754dp y) +{ + return ieee754dp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ); +} + +static __inline int ieee754dp_gt(ieee754dp x, ieee754dp y) +{ + return ieee754dp_cmp(x, y, IEEE754_CGT); +} + +static __inline int ieee754dp_ge(ieee754dp x, ieee754dp y) +{ + return ieee754dp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ); +} + + +/* like strtod +*/ +ieee754dp ieee754dp_fstr(const char *s, char **endp); +char *ieee754dp_tstr(ieee754dp x, int prec, int fmt, int af); + + +/* the control status register +*/ +struct ieee754_csr { + unsigned pad:13; + unsigned noq:1; /* set 1 for no quiet NaN's */ + unsigned nod:1; /* set 1 for no denormalised numbers */ + unsigned cx:5; /* exceptions this operation */ + unsigned mx:5; /* exception enable mask */ + unsigned sx:5; /* exceptions total */ + unsigned rm:2; /* current rounding mode */ +}; +extern struct ieee754_csr ieee754_csr; + +static __inline unsigned ieee754_getrm(void) +{ + return (ieee754_csr.rm); +} +static __inline unsigned ieee754_setrm(unsigned rm) +{ + return (ieee754_csr.rm = rm); +} + +/* + * get current exceptions + */ +static __inline unsigned ieee754_getcx(void) +{ + return (ieee754_csr.cx); +} + +/* test for current exception condition + */ +static __inline int ieee754_cxtest(unsigned n) +{ + return (ieee754_csr.cx & n); +} + +/* + * get sticky exceptions + */ +static __inline unsigned ieee754_getsx(void) +{ + return (ieee754_csr.sx); +} + +/* clear sticky conditions +*/ +static __inline unsigned ieee754_clrsx(void) +{ + return (ieee754_csr.sx = 0); +} + +/* test for sticky exception condition + */ +static __inline int ieee754_sxtest(unsigned n) +{ + return (ieee754_csr.sx & n); +} + +/* debugging */ +ieee754sp ieee754sp_dump(char *s, ieee754sp x); +ieee754dp ieee754dp_dump(char *s, ieee754dp x); + +#define IEEE754_SPCVAL_PZERO 0 +#define IEEE754_SPCVAL_NZERO 1 +#define IEEE754_SPCVAL_PONE 2 +#define IEEE754_SPCVAL_NONE 3 +#define IEEE754_SPCVAL_PTEN 4 +#define IEEE754_SPCVAL_NTEN 5 +#define IEEE754_SPCVAL_PINFINITY 6 +#define IEEE754_SPCVAL_NINFINITY 7 +#define IEEE754_SPCVAL_INDEF 8 +#define IEEE754_SPCVAL_PMAX 9 /* +max norm */ +#define IEEE754_SPCVAL_NMAX 10 /* -max norm */ +#define IEEE754_SPCVAL_PMIN 11 /* +min norm */ +#define IEEE754_SPCVAL_NMIN 12 /* +min norm */ +#define IEEE754_SPCVAL_PMIND 13 /* +min denorm */ +#define IEEE754_SPCVAL_NMIND 14 /* +min denorm */ +#define IEEE754_SPCVAL_P1E31 15 /* + 1.0e31 */ +#define IEEE754_SPCVAL_P1E63 16 /* + 1.0e63 */ + +extern const struct ieee754dp_konst __ieee754dp_spcvals[]; +extern const struct ieee754sp_konst __ieee754sp_spcvals[]; +#define ieee754dp_spcvals ((const ieee754dp *)__ieee754dp_spcvals) +#define ieee754sp_spcvals ((const ieee754sp *)__ieee754sp_spcvals) + +/* return infinity with given sign +*/ +#define ieee754dp_inf(sn) \ + (ieee754dp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)]) +#define ieee754dp_zero(sn) \ + (ieee754dp_spcvals[IEEE754_SPCVAL_PZERO+(sn)]) +#define ieee754dp_one(sn) \ + (ieee754dp_spcvals[IEEE754_SPCVAL_PONE+(sn)]) +#define ieee754dp_ten(sn) \ + (ieee754dp_spcvals[IEEE754_SPCVAL_PTEN+(sn)]) +#define ieee754dp_indef() \ + (ieee754dp_spcvals[IEEE754_SPCVAL_INDEF]) +#define ieee754dp_max(sn) \ + (ieee754dp_spcvals[IEEE754_SPCVAL_PMAX+(sn)]) +#define ieee754dp_min(sn) \ + (ieee754dp_spcvals[IEEE754_SPCVAL_PMIN+(sn)]) +#define ieee754dp_mind(sn) \ + (ieee754dp_spcvals[IEEE754_SPCVAL_PMIND+(sn)]) +#define ieee754dp_1e31() \ + (ieee754dp_spcvals[IEEE754_SPCVAL_P1E31]) +#define ieee754dp_1e63() \ + (ieee754dp_spcvals[IEEE754_SPCVAL_P1E63]) + +#define ieee754sp_inf(sn) \ + (ieee754sp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)]) +#define ieee754sp_zero(sn) \ + (ieee754sp_spcvals[IEEE754_SPCVAL_PZERO+(sn)]) +#define ieee754sp_one(sn) \ + (ieee754sp_spcvals[IEEE754_SPCVAL_PONE+(sn)]) +#define ieee754sp_ten(sn) \ + (ieee754sp_spcvals[IEEE754_SPCVAL_PTEN+(sn)]) +#define ieee754sp_indef() \ + (ieee754sp_spcvals[IEEE754_SPCVAL_INDEF]) +#define ieee754sp_max(sn) \ + (ieee754sp_spcvals[IEEE754_SPCVAL_PMAX+(sn)]) +#define ieee754sp_min(sn) \ + (ieee754sp_spcvals[IEEE754_SPCVAL_PMIN+(sn)]) +#define ieee754sp_mind(sn) \ + (ieee754sp_spcvals[IEEE754_SPCVAL_PMIND+(sn)]) +#define ieee754sp_1e31() \ + (ieee754sp_spcvals[IEEE754_SPCVAL_P1E31]) +#define ieee754sp_1e63() \ + (ieee754sp_spcvals[IEEE754_SPCVAL_P1E63]) + +/* indefinite integer value +*/ +#define ieee754si_indef() INT_MIN +#ifdef LONG_LONG_MIN +#define ieee754di_indef() LONG_LONG_MIN +#else +#define ieee754di_indef() (-9223372036854775807LL-1) +#endif + +/* IEEE exception context, passed to handler */ +struct ieee754xctx { + const char *op; /* operation name */ + int rt; /* result type */ + union { + ieee754sp sp; /* single precision */ + ieee754dp dp; /* double precision */ +#ifdef IEEE854_XP + ieee754xp xp; /* extended precision */ +#endif + int si; /* standard signed integer (32bits) */ + long long di; /* extended signed integer (64bits) */ + } rv; /* default result format implied by op */ + va_list ap; +}; + +/* result types for xctx.rt */ +#define IEEE754_RT_SP 0 +#define IEEE754_RT_DP 1 +#define IEEE754_RT_XP 2 +#define IEEE754_RT_SI 3 +#define IEEE754_RT_DI 4 + +extern void ieee754_xcpt(struct ieee754xctx *xcp); + +/* compat */ +#define ieee754dp_fix(x) ieee754dp_tint(x) +#define ieee754sp_fix(x) ieee754sp_tint(x) diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/ieee754d.c linux/arch/mips64/math-emu/ieee754d.c --- v2.4.5/linux/arch/mips64/math-emu/ieee754d.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/ieee754d.c Mon Jul 2 13:56:41 2001 @@ -0,0 +1,142 @@ +/* some debug functions +*/ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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. + * + * ######################################################################## + */ + +/************************************************************************** + * Nov 7, 2000 + * Modified to build and operate in Linux kernel environment. + * + * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + *************************************************************************/ + +#include "ieee754.h" + +#define DP_EBIAS 1023 +#define DP_EMIN (-1022) +#define DP_EMAX 1023 +#define DP_FBITS 52 + +#define SP_EBIAS 127 +#define SP_EMIN (-126) +#define SP_EMAX 127 +#define SP_FBITS 23 + +#define DP_MBIT(x) ((unsigned long long)1 << (x)) +#define DP_HIDDEN_BIT DP_MBIT(DP_FBITS) +#define DP_SIGN_BIT DP_MBIT(63) + + +#define SP_MBIT(x) ((unsigned long)1 << (x)) +#define SP_HIDDEN_BIT SP_MBIT(SP_FBITS) +#define SP_SIGN_BIT SP_MBIT(31) + + +#define SPSIGN(sp) (sp.parts.sign) +#define SPBEXP(sp) (sp.parts.bexp) +#define SPMANT(sp) (sp.parts.mant) + +#define DPSIGN(dp) (dp.parts.sign) +#define DPBEXP(dp) (dp.parts.bexp) +#define DPMANT(dp) (dp.parts.mant) + +ieee754dp ieee754dp_dump(char *m, ieee754dp x) +{ + int i; + + printk("%s", m); + printk("<%08x,%08x>\n", (unsigned) (x.bits >> 32), + (unsigned) x.bits); + printk("\t="); + switch (ieee754dp_class(x)) { + case IEEE754_CLASS_QNAN: + case IEEE754_CLASS_SNAN: + printk("Nan %c", DPSIGN(x) ? '-' : '+'); + for (i = DP_FBITS - 1; i >= 0; i--) + printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0'); + break; + case IEEE754_CLASS_INF: + printk("%cInfinity", DPSIGN(x) ? '-' : '+'); + break; + case IEEE754_CLASS_ZERO: + printk("%cZero", DPSIGN(x) ? '-' : '+'); + break; + case IEEE754_CLASS_DNORM: + printk("%c0.", DPSIGN(x) ? '-' : '+'); + for (i = DP_FBITS - 1; i >= 0; i--) + printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0'); + printk("e%d", DPBEXP(x) - DP_EBIAS); + break; + case IEEE754_CLASS_NORM: + printk("%c1.", DPSIGN(x) ? '-' : '+'); + for (i = DP_FBITS - 1; i >= 0; i--) + printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0'); + printk("e%d", DPBEXP(x) - DP_EBIAS); + break; + default: + printk("Illegal/Unknown IEEE754 value class"); + } + printk("\n"); + return x; +} + +ieee754sp ieee754sp_dump(char *m, ieee754sp x) +{ + int i; + + printk("%s=", m); + printk("<%08x>\n", (unsigned) x.bits); + printk("\t="); + switch (ieee754sp_class(x)) { + case IEEE754_CLASS_QNAN: + case IEEE754_CLASS_SNAN: + printk("Nan %c", SPSIGN(x) ? '-' : '+'); + for (i = SP_FBITS - 1; i >= 0; i--) + printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0'); + break; + case IEEE754_CLASS_INF: + printk("%cInfinity", SPSIGN(x) ? '-' : '+'); + break; + case IEEE754_CLASS_ZERO: + printk("%cZero", SPSIGN(x) ? '-' : '+'); + break; + case IEEE754_CLASS_DNORM: + printk("%c0.", SPSIGN(x) ? '-' : '+'); + for (i = SP_FBITS - 1; i >= 0; i--) + printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0'); + printk("e%d", SPBEXP(x) - SP_EBIAS); + break; + case IEEE754_CLASS_NORM: + printk("%c1.", SPSIGN(x) ? '-' : '+'); + for (i = SP_FBITS - 1; i >= 0; i--) + printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0'); + printk("e%d", SPBEXP(x) - SP_EBIAS); + break; + default: + printk("Illegal/Unknown IEEE754 value class"); + } + printk("\n"); + return x; +} + diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/ieee754dp.c linux/arch/mips64/math-emu/ieee754dp.c --- v2.4.5/linux/arch/mips64/math-emu/ieee754dp.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/ieee754dp.c Mon Jul 2 13:56:41 2001 @@ -0,0 +1,197 @@ +/* IEEE754 floating point arithmetic + * double precision: common utilities + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754dp.h" + +int ieee754dp_class(ieee754dp x) +{ + COMPXDP; + EXPLODEXDP; + return xc; +} + +int ieee754dp_isnan(ieee754dp x) +{ + return ieee754dp_class(x) >= IEEE754_CLASS_SNAN; +} + +int ieee754dp_issnan(ieee754dp x) +{ + assert(ieee754dp_isnan(x)); + if (ieee754_csr.noq) + return 1; + return !(DPMANT(x) & DP_MBIT(DP_MBITS - 1)); +} + + +ieee754dp ieee754dp_xcpt(ieee754dp r, const char *op, ...) +{ + struct ieee754xctx ax; + if (!TSTX()) + return r; + + ax.op = op; + ax.rt = IEEE754_RT_DP; + ax.rv.dp = r; + va_start(ax.ap, op); + ieee754_xcpt(&ax); + return ax.rv.dp; +} + +ieee754dp ieee754dp_nanxcpt(ieee754dp r, const char *op, ...) +{ + struct ieee754xctx ax; + + assert(ieee754dp_isnan(r)); + + if (!ieee754dp_issnan(r)) /* QNAN does not cause invalid op !! */ + return r; + + if (!SETCX(IEEE754_INVALID_OPERATION)) { + /* not enabled convert to a quiet NaN */ + if (ieee754_csr.noq) + return r; + DPMANT(r) |= DP_MBIT(DP_MBITS - 1); + return r; + } + + ax.op = op; + ax.rt = 0; + ax.rv.dp = r; + va_start(ax.ap, op); + ieee754_xcpt(&ax); + return ax.rv.dp; +} + +ieee754dp ieee754dp_bestnan(ieee754dp x, ieee754dp y) +{ + assert(ieee754dp_isnan(x)); + assert(ieee754dp_isnan(y)); + + if (DPMANT(x) > DPMANT(y)) + return x; + else + return y; +} + + +/* generate a normal/denormal number with over,under handeling + * sn is sign + * xe is an unbiased exponent + * xm is 3bit extended precision value. + */ +ieee754dp ieee754dp_format(int sn, int xe, unsigned long long xm) +{ + assert(xm); /* we dont gen exact zeros (probably should) */ + + assert((xm >> (DP_MBITS + 1 + 3)) == 0); /* no execess */ + assert(xm & (DP_HIDDEN_BIT << 3)); + + if (xe < DP_EMIN) { + /* strip lower bits */ + int es = DP_EMIN - xe; + + if (ieee754_csr.nod) { + SETCX(IEEE754_UNDERFLOW); + return ieee754dp_zero(sn); + } + + /* sticky right shift es bits + */ + xm = XDPSRS(xm, es); + xe += es; + + assert((xm & (DP_HIDDEN_BIT << 3)) == 0); + assert(xe == DP_EMIN); + } + if (xm & (DP_MBIT(3) - 1)) { + SETCX(IEEE754_INEXACT); + /* inexact must round of 3 bits + */ + switch (ieee754_csr.rm) { + case IEEE754_RZ: + break; + case IEEE754_RN: + xm += 0x3 + ((xm >> 3) & 1); + /* xm += (xm&0x8)?0x4:0x3 */ + break; + case IEEE754_RU: /* toward +Infinity */ + if (!sn) /* ?? */ + xm += 0x8; + break; + case IEEE754_RD: /* toward -Infinity */ + if (sn) /* ?? */ + xm += 0x8; + break; + } + /* adjust exponent for rounding add overflowing + */ + if (xm >> (DP_MBITS + 3 + 1)) { /* add causes mantissa overflow */ + xm >>= 1; + xe++; + } + } + /* strip grs bits */ + xm >>= 3; + + assert((xm >> (DP_MBITS + 1)) == 0); /* no execess */ + assert(xe >= DP_EMIN); + + if (xe > DP_EMAX) { + SETCX(IEEE754_OVERFLOW); + /* -O can be table indexed by (rm,sn) */ + switch (ieee754_csr.rm) { + case IEEE754_RN: + return ieee754dp_inf(sn); + case IEEE754_RZ: + return ieee754dp_max(sn); + case IEEE754_RU: /* toward +Infinity */ + if (sn == 0) + return ieee754dp_inf(0); + else + return ieee754dp_max(1); + case IEEE754_RD: /* toward -Infinity */ + if (sn == 0) + return ieee754dp_max(0); + else + return ieee754dp_inf(1); + } + } + /* gen norm/denorm/zero */ + + if ((xm & DP_HIDDEN_BIT) == 0) { + /* we underflow (tiny/zero) */ + assert(xe == DP_EMIN); + SETCX(IEEE754_UNDERFLOW); + return builddp(sn, DP_EMIN - 1 + DP_EBIAS, xm); + } else { + assert((xm >> (DP_MBITS + 1)) == 0); /* no execess */ + assert(xm & DP_HIDDEN_BIT); + + return builddp(sn, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT); + } +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/ieee754dp.h linux/arch/mips64/math-emu/ieee754dp.h --- v2.4.5/linux/arch/mips64/math-emu/ieee754dp.h Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/ieee754dp.h Mon Jul 2 13:56:41 2001 @@ -0,0 +1,83 @@ +/* + * IEEE754 floating point + * double precision internal header file + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754int.h" + +#define assert(expr) ((void)0) + +/* 3bit extended double precision sticky right shift */ +#define XDPSRS(v,rs) \ + ((rs > (DP_MBITS+3))?1:((v) >> (rs)) | ((v) << (64-(rs)) != 0)) + +#define XDPSRSX1() \ + (xe++, (xm = (xm >> 1) | (xm & 1))) + +#define XDPSRS1(v) \ + (((v) >> 1) | ((v) & 1)) + +/* convert denormal to normalized with extended exponent */ +#define DPDNORMx(m,e) \ + while( (m >> DP_MBITS) == 0) { m <<= 1; e--; } +#define DPDNORMX DPDNORMx(xm,xe) +#define DPDNORMY DPDNORMx(ym,ye) + +static __inline ieee754dp builddp(int s, int bx, unsigned long long m) +{ + ieee754dp r; + + assert((s) == 0 || (s) == 1); + assert((bx) >= DP_EMIN - 1 + DP_EBIAS + && (bx) <= DP_EMAX + 1 + DP_EBIAS); + assert(((m) >> DP_MBITS) == 0); + + r.parts.sign = s; + r.parts.bexp = bx; + r.parts.mant = m; + return r; +} + +extern int ieee754dp_isnan(ieee754dp); +extern int ieee754dp_issnan(ieee754dp); +extern int ieee754si_xcpt(int, const char *, ...); +extern long long ieee754di_xcpt(long long, const char *, ...); +extern ieee754dp ieee754dp_xcpt(ieee754dp, const char *, ...); +extern ieee754dp ieee754dp_nanxcpt(ieee754dp, const char *, ...); +extern ieee754dp ieee754dp_bestnan(ieee754dp, ieee754dp); +extern ieee754dp ieee754dp_format(int, int, unsigned long long); + + +#define DPNORMRET2(s,e,m,name,a0,a1) \ +{ \ + ieee754dp V = ieee754dp_format(s,e,m); \ + if(TSTX()) \ + return ieee754dp_xcpt(V,name,a0,a1); \ + else \ + return V; \ +} + +#define DPNORMRET1(s,e,m,name,a0) DPNORMRET2(s,e,m,name,a0,a0) diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/ieee754int.h linux/arch/mips64/math-emu/ieee754int.h --- v2.4.5/linux/arch/mips64/math-emu/ieee754int.h Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/ieee754int.h Mon Jul 2 13:56:41 2001 @@ -0,0 +1,135 @@ +/* + * IEEE754 floating point + * common internal header file + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754.h" + +#define DP_EBIAS 1023 +#define DP_EMIN (-1022) +#define DP_EMAX 1023 +#define DP_MBITS 52 + +#define SP_EBIAS 127 +#define SP_EMIN (-126) +#define SP_EMAX 127 +#define SP_MBITS 23 + +#define DP_MBIT(x) ((unsigned long long)1 << (x)) +#define DP_HIDDEN_BIT DP_MBIT(DP_MBITS) +#define DP_SIGN_BIT DP_MBIT(63) + +#define SP_MBIT(x) ((unsigned long)1 << (x)) +#define SP_HIDDEN_BIT SP_MBIT(SP_MBITS) +#define SP_SIGN_BIT SP_MBIT(31) + + +#define SPSIGN(sp) (sp.parts.sign) +#define SPBEXP(sp) (sp.parts.bexp) +#define SPMANT(sp) (sp.parts.mant) + +#define DPSIGN(dp) (dp.parts.sign) +#define DPBEXP(dp) (dp.parts.bexp) +#define DPMANT(dp) (dp.parts.mant) + +#define CLPAIR(x,y) ((x)*6+(y)) + +#define CLEARCX \ + (ieee754_csr.cx = 0) + +#define SETCX(x) \ + (ieee754_csr.cx |= (x),ieee754_csr.sx |= (x),ieee754_csr.mx & (x)) + +#define TSTX() \ + (ieee754_csr.cx & ieee754_csr.mx) + + +#define COMPXSP \ + unsigned xm; int xe; int xs; int xc + +#define COMPYSP \ + unsigned ym; int ye; int ys; int yc + +#define EXPLODESP(v,vc,vs,ve,vm) \ +{\ + vs = SPSIGN(v);\ + ve = SPBEXP(v);\ + vm = SPMANT(v);\ + if(ve == SP_EMAX+1+SP_EBIAS){\ + if(vm == 0)\ + vc = IEEE754_CLASS_INF;\ + else if(vm & SP_MBIT(SP_MBITS-1)) \ + vc = IEEE754_CLASS_QNAN;\ + else \ + vc = IEEE754_CLASS_SNAN;\ + } else if(ve == SP_EMIN-1+SP_EBIAS) {\ + if(vm) {\ + ve = SP_EMIN;\ + vc = IEEE754_CLASS_DNORM;\ + } else\ + vc = IEEE754_CLASS_ZERO;\ + } else {\ + ve -= SP_EBIAS;\ + vm |= SP_HIDDEN_BIT;\ + vc = IEEE754_CLASS_NORM;\ + }\ +} +#define EXPLODEXSP EXPLODESP(x,xc,xs,xe,xm) +#define EXPLODEYSP EXPLODESP(y,yc,ys,ye,ym) + + +#define COMPXDP \ +unsigned long long xm; int xe; int xs; int xc + +#define COMPYDP \ +unsigned long long ym; int ye; int ys; int yc + +#define EXPLODEDP(v,vc,vs,ve,vm) \ +{\ + vm = DPMANT(v);\ + vs = DPSIGN(v);\ + ve = DPBEXP(v);\ + if(ve == DP_EMAX+1+DP_EBIAS){\ + if(vm == 0)\ + vc = IEEE754_CLASS_INF;\ + else if(vm & DP_MBIT(DP_MBITS-1)) \ + vc = IEEE754_CLASS_QNAN;\ + else \ + vc = IEEE754_CLASS_SNAN;\ + } else if(ve == DP_EMIN-1+DP_EBIAS) {\ + if(vm) {\ + ve = DP_EMIN;\ + vc = IEEE754_CLASS_DNORM;\ + } else\ + vc = IEEE754_CLASS_ZERO;\ + } else {\ + ve -= DP_EBIAS;\ + vm |= DP_HIDDEN_BIT;\ + vc = IEEE754_CLASS_NORM;\ + }\ +} +#define EXPLODEXDP EXPLODEDP(x,xc,xs,xe,xm) +#define EXPLODEYDP EXPLODEDP(y,yc,ys,ye,ym) diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/ieee754m.c linux/arch/mips64/math-emu/ieee754m.c --- v2.4.5/linux/arch/mips64/math-emu/ieee754m.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/ieee754m.c Mon Jul 2 13:56:41 2001 @@ -0,0 +1,56 @@ +/* + * floor, trunc, ceil + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754.h" + +ieee754dp ieee754dp_floor(ieee754dp x) +{ + ieee754dp i; + + if (ieee754dp_lt(ieee754dp_modf(x, &i), ieee754dp_zero(0))) + return ieee754dp_sub(i, ieee754dp_one(0)); + else + return i; +} + +ieee754dp ieee754dp_ceil(ieee754dp x) +{ + ieee754dp i; + + if (ieee754dp_gt(ieee754dp_modf(x, &i), ieee754dp_zero(0))) + return ieee754dp_add(i, ieee754dp_one(0)); + else + return i; +} + +ieee754dp ieee754dp_trunc(ieee754dp x) +{ + ieee754dp i; + + (void) ieee754dp_modf(x, &i); + return i; +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/ieee754sp.c linux/arch/mips64/math-emu/ieee754sp.c --- v2.4.5/linux/arch/mips64/math-emu/ieee754sp.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/ieee754sp.c Mon Jul 2 13:56:41 2001 @@ -0,0 +1,197 @@ +/* IEEE754 floating point arithmetic + * single precision + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754sp.h" + +int ieee754sp_class(ieee754sp x) +{ + COMPXSP; + EXPLODEXSP; + return xc; +} + +int ieee754sp_isnan(ieee754sp x) +{ + return ieee754sp_class(x) >= IEEE754_CLASS_SNAN; +} + +int ieee754sp_issnan(ieee754sp x) +{ + assert(ieee754sp_isnan(x)); + if (ieee754_csr.noq) + return 1; + return !(SPMANT(x) & SP_MBIT(SP_MBITS - 1)); +} + + +ieee754sp ieee754sp_xcpt(ieee754sp r, const char *op, ...) +{ + struct ieee754xctx ax; + + if (!TSTX()) + return r; + + ax.op = op; + ax.rt = IEEE754_RT_SP; + ax.rv.sp = r; + va_start(ax.ap, op); + ieee754_xcpt(&ax); + return ax.rv.sp; +} + +ieee754sp ieee754sp_nanxcpt(ieee754sp r, const char *op, ...) +{ + struct ieee754xctx ax; + + assert(ieee754sp_isnan(r)); + + if (!ieee754sp_issnan(r)) /* QNAN does not cause invalid op !! */ + return r; + + if (!SETCX(IEEE754_INVALID_OPERATION)) { + /* not enabled convert to a quiet NaN */ + if (ieee754_csr.noq) + return r; + SPMANT(r) |= SP_MBIT(SP_MBITS - 1); + return r; + } + + ax.op = op; + ax.rt = 0; + ax.rv.sp = r; + va_start(ax.ap, op); + ieee754_xcpt(&ax); + return ax.rv.sp; +} + +ieee754sp ieee754sp_bestnan(ieee754sp x, ieee754sp y) +{ + assert(ieee754sp_isnan(x)); + assert(ieee754sp_isnan(y)); + + if (SPMANT(x) > SPMANT(y)) + return x; + else + return y; +} + + +/* generate a normal/denormal number with over,under handeling + * sn is sign + * xe is an unbiased exponent + * xm is 3bit extended precision value. + */ +ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) +{ + assert(xm); /* we dont gen exact zeros (probably should) */ + + assert((xm >> (SP_MBITS + 1 + 3)) == 0); /* no execess */ + assert(xm & (SP_HIDDEN_BIT << 3)); + + if (xe < SP_EMIN) { + /* strip lower bits */ + int es = SP_EMIN - xe; + + if (ieee754_csr.nod) { + SETCX(IEEE754_UNDERFLOW); + return ieee754sp_zero(sn); + } + + /* sticky right shift es bits + */ + SPXSRSXn(es); + + assert((xm & (SP_HIDDEN_BIT << 3)) == 0); + assert(xe == SP_EMIN); + } + if (xm & (SP_MBIT(3) - 1)) { + SETCX(IEEE754_INEXACT); + /* inexact must round of 3 bits + */ + switch (ieee754_csr.rm) { + case IEEE754_RZ: + break; + case IEEE754_RN: + xm += 0x3 + ((xm >> 3) & 1); + /* xm += (xm&0x8)?0x4:0x3 */ + break; + case IEEE754_RU: /* toward +Infinity */ + if (!sn) /* ?? */ + xm += 0x8; + break; + case IEEE754_RD: /* toward -Infinity */ + if (sn) /* ?? */ + xm += 0x8; + break; + } + /* adjust exponent for rounding add overflowing + */ + if (xm >> (SP_MBITS + 1 + 3)) { /* add causes mantissa overflow */ + xm >>= 1; + xe++; + } + } + /* strip grs bits */ + xm >>= 3; + + assert((xm >> (SP_MBITS + 1)) == 0); /* no execess */ + assert(xe >= SP_EMIN); + + if (xe > SP_EMAX) { + SETCX(IEEE754_OVERFLOW); + /* -O can be table indexed by (rm,sn) */ + switch (ieee754_csr.rm) { + case IEEE754_RN: + return ieee754sp_inf(sn); + case IEEE754_RZ: + return ieee754sp_max(sn); + case IEEE754_RU: /* toward +Infinity */ + if (sn == 0) + return ieee754sp_inf(0); + else + return ieee754sp_max(1); + case IEEE754_RD: /* toward -Infinity */ + if (sn == 0) + return ieee754sp_max(0); + else + return ieee754sp_inf(1); + } + } + /* gen norm/denorm/zero */ + + if ((xm & SP_HIDDEN_BIT) == 0) { + /* we underflow (tiny/zero) */ + assert(xe == SP_EMIN); + SETCX(IEEE754_UNDERFLOW); + return buildsp(sn, SP_EMIN - 1 + SP_EBIAS, xm); + } else { + assert((xm >> (SP_MBITS + 1)) == 0); /* no execess */ + assert(xm & SP_HIDDEN_BIT); + + return buildsp(sn, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT); + } +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/ieee754sp.h linux/arch/mips64/math-emu/ieee754sp.h --- v2.4.5/linux/arch/mips64/math-emu/ieee754sp.h Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/ieee754sp.h Mon Jul 2 13:56:41 2001 @@ -0,0 +1,89 @@ +/* + * IEEE754 floating point + * double precision internal header file + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754int.h" + +#define assert(expr) ((void)0) + +/* 3bit extended single precision sticky right shift */ +#define SPXSRSXn(rs) \ + (xe += rs, \ + xm = (rs > (SP_MBITS+3))?1:((xm) >> (rs)) | ((xm) << (32-(rs)) != 0)) + +#define SPXSRSX1() \ + (xe++, (xm = (xm >> 1) | (xm & 1))) + +#define SPXSRSYn(rs) \ + (ye+=rs, \ + ym = (rs > (SP_MBITS+3))?1:((ym) >> (rs)) | ((ym) << (32-(rs)) != 0)) + +#define SPXSRSY1() \ + (ye++, (ym = (ym >> 1) | (ym & 1))) + +/* convert denormal to normalized with extended exponent */ +#define SPDNORMx(m,e) \ + while( (m >> SP_MBITS) == 0) { m <<= 1; e--; } +#define SPDNORMX SPDNORMx(xm,xe) +#define SPDNORMY SPDNORMx(ym,ye) + +static __inline ieee754sp buildsp(int s, int bx, unsigned m) +{ + ieee754sp r; + + assert((s) == 0 || (s) == 1); + assert((bx) >= SP_EMIN - 1 + SP_EBIAS + && (bx) <= SP_EMAX + 1 + SP_EBIAS); + assert(((m) >> SP_MBITS) == 0); + + r.parts.sign = s; + r.parts.bexp = bx; + r.parts.mant = m; + + return r; +} + +extern int ieee754sp_isnan(ieee754sp); +extern int ieee754sp_issnan(ieee754sp); +extern int ieee754si_xcpt(int, const char *, ...); +extern long long ieee754di_xcpt(long long, const char *, ...); +extern ieee754sp ieee754sp_xcpt(ieee754sp, const char *, ...); +extern ieee754sp ieee754sp_nanxcpt(ieee754sp, const char *, ...); +extern ieee754sp ieee754sp_bestnan(ieee754sp, ieee754sp); +extern ieee754sp ieee754sp_format(int, int, unsigned); + + +#define SPNORMRET2(s,e,m,name,a0,a1) \ +{ \ + ieee754sp V = ieee754sp_format(s,e,m); \ + if(TSTX()) \ + return ieee754sp_xcpt(V,name,a0,a1); \ + else \ + return V; \ +} + +#define SPNORMRET1(s,e,m,name,a0) SPNORMRET2(s,e,m,name,a0,a0) diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/ieee754xcpt.c linux/arch/mips64/math-emu/ieee754xcpt.c --- v2.4.5/linux/arch/mips64/math-emu/ieee754xcpt.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/ieee754xcpt.c Mon Jul 2 13:56:41 2001 @@ -0,0 +1,48 @@ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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. + * + * ######################################################################## + */ + +/************************************************************************** + * Nov 7, 2000 + * Added preprocessor hacks to map to Linux kernel diagnostics. + * + * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + *************************************************************************/ + +#include "ieee754.h" + +/* + * Very naff exception handler (you can plug in your own and + * override this). + */ + +static const char *const rtnames[] = { + "sp", "dp", "xp", "si", "di" +}; + +void ieee754_xcpt(struct ieee754xctx *xcp) +{ + printk("floating point exception in \"%s\", type=%s\n", + xcp->op, rtnames[xcp->rt]); +} + diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/kernel_linkage.c linux/arch/mips64/math-emu/kernel_linkage.c --- v2.4.5/linux/arch/mips64/math-emu/kernel_linkage.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/kernel_linkage.c Mon Jul 2 13:56:41 2001 @@ -0,0 +1,95 @@ +/************************************************************************** + * + * arch/mips/math_emu/kernel_linkage.c + * + * Kevin D. Kissell, kevink@mips and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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. + * + *************************************************************************/ +/* + * Routines corresponding to Linux kernel FP context + * manipulation primitives for the Algorithmics MIPS + * FPU Emulator + */ + +#include +#include +#include +#include + +#include + +extern struct mips_fpu_emulator_private fpuemuprivate; + +#define SIGNALLING_NAN 0x7ff800007ff80000LL + +void fpu_emulator_init_fpu(void) +{ + static int first = 1; + int i; + + if (first) { + first = 0; + printk("Algorithmics/MIPS FPU Emulator v1.4\n"); + } + + current->thread.fpu.soft.sr = 0; + for (i = 0; i < 32; i++) { + current->thread.fpu.soft.regs[i] = SIGNALLING_NAN; + } +} + + +/* + * Emulator context save/restore to/from a signal context + * presumed to be on the user stack, and therefore accessed + * with appropriate macros from uaccess.h + */ + +int fpu_emulator_save_context(struct sigcontext *sc) +{ + int i; + int err = 0; + + for (i = 0; i < 32; i++) { + err |= + __put_user(current->thread.fpu.soft.regs[i], + &sc->sc_fpregs[i]); + } + err |= __put_user(current->thread.fpu.soft.sr, &sc->sc_fpc_csr); + err |= __put_user(fpuemuprivate.eir, &sc->sc_fpc_eir); + + return err; +} + +int fpu_emulator_restore_context(struct sigcontext *sc) +{ + int i; + int err = 0; + + for (i = 0; i < 32; i++) { + err |= + __get_user(current->thread.fpu.soft.regs[i], + &sc->sc_fpregs[i]); + } + err |= __get_user(current->thread.fpu.soft.sr, &sc->sc_fpc_csr); + err |= __get_user(fpuemuprivate.eir, &sc->sc_fpc_eir); + + return err; +} + diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_add.c linux/arch/mips64/math-emu/sp_add.c --- v2.4.5/linux/arch/mips64/math-emu/sp_add.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/sp_add.c Mon Jul 2 13:56:41 2001 @@ -0,0 +1,180 @@ +/* IEEE754 floating point arithmetic + * single precision + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754sp.h" + +ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y) +{ + COMPXSP; + COMPYSP; + + EXPLODEXSP; + EXPLODEYSP; + + CLEARCX; + + switch (CLPAIR(xc, yc)) { + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): + return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "add", x, + y); + + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): + return ieee754sp_nanxcpt(y, "add", x, y); + + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): + return ieee754sp_nanxcpt(x, "add", x, y); + + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): + return ieee754sp_bestnan(x, y); + + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): + return y; + + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): + return x; + + + /* Inifity handeling + */ + + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): + if (xs == ys) + return x; + SETCX(IEEE754_INVALID_OPERATION); + return ieee754sp_xcpt(ieee754sp_indef(), "add", x, y); + + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): + return y; + + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): + return x; + + /* Zero handeling + */ + + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): + if (xs == ys) + return x; + else + return ieee754sp_zero(ieee754_csr.rm == + IEEE754_RD); + + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): + return x; + + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): + return y; + + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): + SPDNORMX; + + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): + SPDNORMY; + break; + + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): + SPDNORMX; + break; + + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): + break; + } + assert(xm & SP_HIDDEN_BIT); + assert(ym & SP_HIDDEN_BIT); + + /* provide guard,round and stick bit space */ + xm <<= 3; + ym <<= 3; + + if (xe > ye) { + /* have to shift y fraction right to align + */ + int s = xe - ye; + SPXSRSYn(s); + } else if (ye > xe) { + /* have to shift x fraction right to align + */ + int s = ye - xe; + SPXSRSXn(s); + } + assert(xe == ye); + assert(xe <= SP_EMAX); + + if (xs == ys) { + /* generate 28 bit result of adding two 27 bit numbers + * leaving result in xm,xs,xe + */ + xm = xm + ym; + xe = xe; + xs = xs; + + if (xm >> (SP_MBITS + 1 + 3)) { /* carry out */ + SPXSRSX1(); + } + } else { + if (xm >= ym) { + xm = xm - ym; + xe = xe; + xs = xs; + } else { + xm = ym - xm; + xe = xe; + xs = ys; + } + if (xm == 0) + return ieee754sp_zero(ieee754_csr.rm == + IEEE754_RD); + + /* normalize in extended single precision */ + while ((xm >> (SP_MBITS + 3)) == 0) { + xm <<= 1; + xe--; + } + + } + SPNORMRET2(xs, xe, xm, "add", x, y); +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_cmp.c linux/arch/mips64/math-emu/sp_cmp.c --- v2.4.5/linux/arch/mips64/math-emu/sp_cmp.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/sp_cmp.c Mon Jul 2 13:56:41 2001 @@ -0,0 +1,58 @@ +/* IEEE754 floating point arithmetic + * single precision + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754sp.h" + +int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cmp) +{ + CLEARCX; + + if (ieee754sp_isnan(x) || ieee754sp_isnan(y)) { + if (cmp & IEEE754_CUN) + return 1; + if (cmp & (IEEE754_CLT | IEEE754_CGT)) { + if (SETCX(IEEE754_INVALID_OPERATION)) + return ieee754si_xcpt(0, "fcmpf", x); + } + return 0; + } else { + int vx = x.bits; + int vy = y.bits; + + if (vx < 0) + vx = -vx ^ SP_SIGN_BIT; + if (vy < 0) + vy = -vy ^ SP_SIGN_BIT; + + if (vx < vy) + return (cmp & IEEE754_CLT) != 0; + else if (vx == vy) + return (cmp & IEEE754_CEQ) != 0; + else + return (cmp & IEEE754_CGT) != 0; + } +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_div.c linux/arch/mips64/math-emu/sp_div.c --- v2.4.5/linux/arch/mips64/math-emu/sp_div.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/sp_div.c Mon Jul 2 13:56:41 2001 @@ -0,0 +1,160 @@ +/* IEEE754 floating point arithmetic + * single precision + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754sp.h" + +ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y) +{ + COMPXSP; + COMPYSP; + + CLEARCX; + + EXPLODEXSP; + EXPLODEYSP; + + switch (CLPAIR(xc, yc)) { + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): + return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "div", x, + y); + + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): + return ieee754sp_nanxcpt(y, "div", x, y); + + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): + return ieee754sp_nanxcpt(x, "div", x, y); + + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): + return ieee754sp_bestnan(x, y); + + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): + return y; + + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): + return x; + + + /* Infinity handeling + */ + + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): + SETCX(IEEE754_INVALID_OPERATION); + return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y); + + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): + return ieee754sp_zero(xs ^ ys); + + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): + return ieee754sp_inf(xs ^ ys); + + /* Zero handeling + */ + + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): + SETCX(IEEE754_INVALID_OPERATION); + return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y); + + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): + SETCX(IEEE754_ZERO_DIVIDE); + return ieee754sp_xcpt(ieee754sp_inf(xs ^ ys), "div", x, y); + + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): + return ieee754sp_zero(xs == ys ? 0 : 1); + + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): + SPDNORMX; + + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): + SPDNORMY; + break; + + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): + SPDNORMX; + break; + + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): + break; + } + assert(xm & SP_HIDDEN_BIT); + assert(ym & SP_HIDDEN_BIT); + + /* provide rounding space */ + xm <<= 3; + ym <<= 3; + + { + /* now the dirty work */ + + unsigned rm = 0; + int re = xe - ye; + unsigned bm; + + for (bm = SP_MBIT(SP_MBITS + 2); bm; bm >>= 1) { + if (xm >= ym) { + xm -= ym; + rm |= bm; + if (xm == 0) + break; + } + xm <<= 1; + } + rm <<= 1; + if (xm) + rm |= 1; /* have remainder, set sticky */ + + assert(rm); + + /* normalise rm to rounding precision ? + */ + while ((rm >> (SP_MBITS + 3)) == 0) { + rm <<= 1; + re--; + } + + SPNORMRET2(xs == ys ? 0 : 1, re, rm, "div", x, y); + } +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_fdp.c linux/arch/mips64/math-emu/sp_fdp.c --- v2.4.5/linux/arch/mips64/math-emu/sp_fdp.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/sp_fdp.c Mon Jul 2 13:56:41 2001 @@ -0,0 +1,69 @@ +/* IEEE754 floating point arithmetic + * single precision + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754sp.h" + +ieee754sp ieee754sp_fdp(ieee754dp x) +{ + COMPXDP; + + CLEARCX; + + EXPLODEXDP; + + switch (xc) { + case IEEE754_CLASS_QNAN: + case IEEE754_CLASS_SNAN: + return ieee754sp_nanxcpt(buildsp(xs, + SP_EMAX + 1 + SP_EBIAS, + (unsigned long) + (xm >> + (DP_MBITS - SP_MBITS))), + "fdp", x); + case IEEE754_CLASS_INF: + return ieee754sp_inf(xs); + case IEEE754_CLASS_ZERO: + return ieee754sp_zero(xs); + case IEEE754_CLASS_DNORM: + /* cant possibly be sp representable */ + SETCX(IEEE754_UNDERFLOW); + return ieee754sp_xcpt(ieee754sp_zero(xs), "fdp", x); + case IEEE754_CLASS_NORM: + break; + } + + { + unsigned long rm; + + /* convert from DP_MBITS to SP_MBITS+3 with sticky right shift + */ + rm = (xm >> (DP_MBITS - (SP_MBITS + 3))) | + ((xm << (64 - (DP_MBITS - (SP_MBITS + 3)))) != 0); + + SPNORMRET1(xs, xe, rm, "fdp", x); + } +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_fint.c linux/arch/mips64/math-emu/sp_fint.c --- v2.4.5/linux/arch/mips64/math-emu/sp_fint.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/sp_fint.c Mon Jul 2 13:56:41 2001 @@ -0,0 +1,78 @@ +/* IEEE754 floating point arithmetic + * single precision + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754sp.h" + +ieee754sp ieee754sp_fint(int x) +{ + COMPXSP; + + CLEARCX; + + if (x == 0) + return ieee754sp_zero(0); + if (x == 1 || x == -1) + return ieee754sp_one(x < 0); + if (x == 10 || x == -10) + return ieee754sp_ten(x < 0); + + xs = (x < 0); + if (xs) { + if (x == (1 << 31)) + xm = ((unsigned) 1 << 31); /* max neg can't be safely negated */ + else + xm = -x; + } else { + xm = x; + } + xe = SP_MBITS + 3; + + if (xm >> (SP_MBITS + 1 + 3)) { + /* shunt out overflow bits + */ + while (xm >> (SP_MBITS + 1 + 3)) { + SPXSRSX1(); + } + } else { + /* normalize in grs extended single precision + */ + while ((xm >> (SP_MBITS + 3)) == 0) { + xm <<= 1; + xe--; + } + } + SPNORMRET1(xs, xe, xm, "fint", x); +} + + +ieee754sp ieee754sp_funs(unsigned int u) +{ + if ((int) u < 0) + return ieee754sp_add(ieee754sp_1e31(), + ieee754sp_fint(u & ~(1 << 31))); + return ieee754sp_fint(u); +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_flong.c linux/arch/mips64/math-emu/sp_flong.c --- v2.4.5/linux/arch/mips64/math-emu/sp_flong.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/sp_flong.c Mon Jul 2 13:56:41 2001 @@ -0,0 +1,77 @@ +/* IEEE754 floating point arithmetic + * single precision + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754sp.h" + +ieee754sp ieee754sp_flong(long long x) +{ + COMPXDP; /* <--- need 64-bit mantissa temp */ + + CLEARCX; + + if (x == 0) + return ieee754sp_zero(0); + if (x == 1 || x == -1) + return ieee754sp_one(x < 0); + if (x == 10 || x == -10) + return ieee754sp_ten(x < 0); + + xs = (x < 0); + if (xs) { + if (x == (1ULL << 63)) + xm = (1ULL << 63); /* max neg can't be safely negated */ + else + xm = -x; + } else { + xm = x; + } + xe = SP_MBITS + 3; + + if (xm >> (SP_MBITS + 1 + 3)) { + /* shunt out overflow bits + */ + while (xm >> (SP_MBITS + 1 + 3)) { + SPXSRSX1(); + } + } else { + /* normalize in grs extended single precision */ + while ((xm >> (SP_MBITS + 3)) == 0) { + xm <<= 1; + xe--; + } + } + SPNORMRET1(xs, xe, xm, "sp_flong", x); +} + + +ieee754sp ieee754sp_fulong(unsigned long long u) +{ + if ((long long) u < 0) + return ieee754sp_add(ieee754sp_1e63(), + ieee754sp_flong(u & ~(1ULL << 63))); + return ieee754sp_flong(u); +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_frexp.c linux/arch/mips64/math-emu/sp_frexp.c --- v2.4.5/linux/arch/mips64/math-emu/sp_frexp.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/sp_frexp.c Mon Jul 2 13:56:41 2001 @@ -0,0 +1,53 @@ +/* IEEE754 floating point arithmetic + * single precision + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754sp.h" + +/* close to ieeep754sp_logb +*/ +ieee754sp ieee754sp_frexp(ieee754sp x, int *eptr) +{ + COMPXSP; + CLEARCX; + EXPLODEXSP; + + switch (xc) { + case IEEE754_CLASS_SNAN: + case IEEE754_CLASS_QNAN: + case IEEE754_CLASS_INF: + case IEEE754_CLASS_ZERO: + *eptr = 0; + return x; + case IEEE754_CLASS_DNORM: + SPDNORMX; + break; + case IEEE754_CLASS_NORM: + break; + } + *eptr = xe + 1; + return buildsp(xs, -1 + SP_EBIAS, xm & ~SP_HIDDEN_BIT); +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_logb.c linux/arch/mips64/math-emu/sp_logb.c --- v2.4.5/linux/arch/mips64/math-emu/sp_logb.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/sp_logb.c Mon Jul 2 13:56:41 2001 @@ -0,0 +1,54 @@ +/* IEEE754 floating point arithmetic + * single precision + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754sp.h" + +ieee754sp ieee754sp_logb(ieee754sp x) +{ + COMPXSP; + + CLEARCX; + + EXPLODEXSP; + + switch (xc) { + case IEEE754_CLASS_SNAN: + return ieee754sp_nanxcpt(x, "logb", x); + case IEEE754_CLASS_QNAN: + return x; + case IEEE754_CLASS_INF: + return ieee754sp_inf(0); + case IEEE754_CLASS_ZERO: + return ieee754sp_inf(1); + case IEEE754_CLASS_DNORM: + SPDNORMX; + break; + case IEEE754_CLASS_NORM: + break; + } + return ieee754sp_fint(xe); +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_modf.c linux/arch/mips64/math-emu/sp_modf.c --- v2.4.5/linux/arch/mips64/math-emu/sp_modf.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/sp_modf.c Mon Jul 2 13:56:41 2001 @@ -0,0 +1,80 @@ +/* IEEE754 floating point arithmetic + * single precision + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754sp.h" + +/* modf function is always exact for a finite number +*/ +ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip) +{ + COMPXSP; + + CLEARCX; + + EXPLODEXSP; + + switch (xc) { + case IEEE754_CLASS_SNAN: + case IEEE754_CLASS_QNAN: + case IEEE754_CLASS_INF: + case IEEE754_CLASS_ZERO: + *ip = x; + return x; + case IEEE754_CLASS_DNORM: + /* far to small */ + *ip = ieee754sp_zero(xs); + return x; + case IEEE754_CLASS_NORM: + break; + } + if (xe < 0) { + *ip = ieee754sp_zero(xs); + return x; + } + if (xe >= SP_MBITS) { + *ip = x; + return ieee754sp_zero(xs); + } + /* generate ipart mantissa by clearing bottom bits + */ + *ip = buildsp(xs, xe + SP_EBIAS, + ((xm >> (SP_MBITS - xe)) << (SP_MBITS - xe)) & + ~SP_HIDDEN_BIT); + + /* generate fpart mantissa by clearing top bits + * and normalizing (must be able to normalize) + */ + xm = (xm << (32 - (SP_MBITS - xe))) >> (32 - (SP_MBITS - xe)); + if (xm == 0) + return ieee754sp_zero(xs); + + while ((xm >> SP_MBITS) == 0) { + xm <<= 1; + xe--; + } + return buildsp(xs, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT); +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_mul.c linux/arch/mips64/math-emu/sp_mul.c --- v2.4.5/linux/arch/mips64/math-emu/sp_mul.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/sp_mul.c Mon Jul 2 13:56:41 2001 @@ -0,0 +1,174 @@ +/* IEEE754 floating point arithmetic + * single precision + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754sp.h" + +ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y) +{ + COMPXSP; + COMPYSP; + + CLEARCX; + + EXPLODEXSP; + EXPLODEYSP; + + switch (CLPAIR(xc, yc)) { + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): + return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "mul", x, + y); + + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): + return ieee754sp_nanxcpt(y, "mul", x, y); + + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): + return ieee754sp_nanxcpt(x, "mul", x, y); + + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): + return ieee754sp_bestnan(x, y); + + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): + return y; + + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): + return x; + + + /* Infinity handeling */ + + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): + SETCX(IEEE754_INVALID_OPERATION); + return ieee754sp_xcpt(ieee754sp_indef(), "mul", x, y); + + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): + return ieee754sp_inf(xs ^ ys); + + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): + return ieee754sp_zero(xs ^ ys); + + + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): + SPDNORMX; + + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): + SPDNORMY; + break; + + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): + SPDNORMX; + break; + + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): + break; + } + /* rm = xm * ym, re = xe+ye basicly */ + assert(xm & SP_HIDDEN_BIT); + assert(ym & SP_HIDDEN_BIT); + + { + int re = xe + ye; + int rs = xs ^ ys; + unsigned rm; + + /* shunt to top of word */ + xm <<= 32 - (SP_MBITS + 1); + ym <<= 32 - (SP_MBITS + 1); + + /* multiply 32bits xm,ym to give high 32bits rm with stickness + */ + { + unsigned short lxm = xm & 0xffff; + unsigned short hxm = xm >> 16; + unsigned short lym = ym & 0xffff; + unsigned short hym = ym >> 16; + unsigned lrm; + unsigned hrm; + + lrm = lxm * lym; /* 16 * 16 => 32 */ + hrm = hxm * hym; /* 16 * 16 => 32 */ + + { + unsigned t = lxm * hym; /* 16 * 16 => 32 */ + { + unsigned at = lrm + (t << 16); + hrm += at < lrm; + lrm = at; + } + hrm = hrm + (t >> 16); + } + + { + unsigned t = hxm * lym; /* 16 * 16 => 32 */ + { + unsigned at = lrm + (t << 16); + hrm += at < lrm; + lrm = at; + } + hrm = hrm + (t >> 16); + } + rm = hrm | (lrm != 0); + } + + /* + * sticky shift down to normal rounding precision + */ + if ((int) rm < 0) { + rm = (rm >> (32 - (SP_MBITS + 1 + 3))) | + ((rm << (SP_MBITS + 1 + 3)) != 0); + re++; + } else { + rm = (rm >> (32 - (SP_MBITS + 1 + 3 + 1))) | + ((rm << (SP_MBITS + 1 + 3 + 1)) != 0); + } + assert(rm & (SP_HIDDEN_BIT << 3)); + + SPNORMRET2(rs, re, rm, "mul", x, y); + } +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_scalb.c linux/arch/mips64/math-emu/sp_scalb.c --- v2.4.5/linux/arch/mips64/math-emu/sp_scalb.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/sp_scalb.c Mon Jul 2 13:56:41 2001 @@ -0,0 +1,58 @@ +/* IEEE754 floating point arithmetic + * single precision + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754sp.h" + +ieee754sp ieee754sp_scalb(ieee754sp x, int n) +{ + COMPXSP; + + CLEARCX; + + EXPLODEXSP; + + switch (xc) { + case IEEE754_CLASS_SNAN: + return ieee754sp_nanxcpt(x, "scalb", x, n); + case IEEE754_CLASS_QNAN: + case IEEE754_CLASS_INF: + case IEEE754_CLASS_ZERO: + return x; + case IEEE754_CLASS_DNORM: + SPDNORMX; + break; + case IEEE754_CLASS_NORM: + break; + } + SPNORMRET2(xs, xe + n, xm << 3, "scalb", x, n); +} + + +ieee754sp ieee754sp_ldexp(ieee754sp x, int n) +{ + return ieee754sp_scalb(x, n); +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_simple.c linux/arch/mips64/math-emu/sp_simple.c --- v2.4.5/linux/arch/mips64/math-emu/sp_simple.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/sp_simple.c Mon Jul 2 13:56:41 2001 @@ -0,0 +1,66 @@ +/* IEEE754 floating point arithmetic + * single precision + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754sp.h" + +int ieee754sp_finite(ieee754sp x) +{ + return SPBEXP(x) != SP_EMAX + 1 + SP_EBIAS; +} + +ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y) +{ + CLEARCX; + SPSIGN(x) = SPSIGN(y); + return x; +} + + +ieee754sp ieee754sp_neg(ieee754sp x) +{ + CLEARCX; + + if (ieee754sp_isnan(x)) /* but not infinity */ + return ieee754sp_nanxcpt(x, "neg", x); + + /* quick fix up */ + SPSIGN(x) ^= 1; + return x; +} + + +ieee754sp ieee754sp_abs(ieee754sp x) +{ + CLEARCX; + + if (ieee754sp_isnan(x)) /* but not infinity */ + return ieee754sp_nanxcpt(x, "abs", x); + + /* quick fix up */ + SPSIGN(x) = 0; + return x; +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_sqrt.c linux/arch/mips64/math-emu/sp_sqrt.c --- v2.4.5/linux/arch/mips64/math-emu/sp_sqrt.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/sp_sqrt.c Mon Jul 2 13:56:41 2001 @@ -0,0 +1,115 @@ +/* IEEE754 floating point arithmetic + * single precision square root + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754sp.h" + +static const struct ieee754sp_konst knan = { + 0, SP_EBIAS + SP_EMAX + 1, 0 +}; + +#define nan ((ieee754sp)knan) + +ieee754sp ieee754sp_sqrt(ieee754sp x) +{ + int sign = (int) 0x80000000; + int ix, s, q, m, t, i; + unsigned int r; + COMPXDP; + + /* take care of Inf and NaN */ + + EXPLODEXDP; + + /* x == INF or NAN? */ + switch (xc) { + case IEEE754_CLASS_QNAN: + case IEEE754_CLASS_SNAN: + /* sqrt(Nan) = Nan */ + return ieee754sp_nanxcpt(x, "sqrt"); + case IEEE754_CLASS_ZERO: + /* sqrt(0) = 0 */ + return x; + case IEEE754_CLASS_INF: + if (xs) + /* sqrt(-Inf) = Nan */ + return ieee754sp_nanxcpt(nan, "sqrt"); + /* sqrt(+Inf) = Inf */ + return x; + case IEEE754_CLASS_DNORM: + case IEEE754_CLASS_NORM: + if (xs) + /* sqrt(-x) = Nan */ + return ieee754sp_nanxcpt(nan, "sqrt"); + break; + } + + ix = x.bits; + + /* normalize x */ + m = (ix >> 23); + if (m == 0) { /* subnormal x */ + for (i = 0; (ix & 0x00800000) == 0; i++) + ix <<= 1; + m -= i - 1; + } + m -= 127; /* unbias exponent */ + ix = (ix & 0x007fffff) | 0x00800000; + if (m & 1) /* odd m, double x to make it even */ + ix += ix; + m >>= 1; /* m = [m/2] */ + + /* generate sqrt(x) bit by bit */ + ix += ix; + q = s = 0; /* q = sqrt(x) */ + r = 0x01000000; /* r = moving bit from right to left */ + + while (r != 0) { + t = s + r; + if (t <= ix) { + s = t + r; + ix -= t; + q += r; + } + ix += ix; + r >>= 1; + } + + if (ix != 0) { + switch (ieee754_csr.rm) { + case IEEE754_RP: + q += 2; + break; + case IEEE754_RN: + q += (q & 1); + break; + } + } + ix = (q >> 1) + 0x3f000000; + ix += (m << 23); + x.bits = ix; + return x; +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_sub.c linux/arch/mips64/math-emu/sp_sub.c --- v2.4.5/linux/arch/mips64/math-emu/sp_sub.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/sp_sub.c Mon Jul 2 13:56:41 2001 @@ -0,0 +1,187 @@ +/* IEEE754 floating point arithmetic + * single precision + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754sp.h" + +ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y) +{ + COMPXSP; + COMPYSP; + + CLEARCX; + + EXPLODEXSP; + EXPLODEYSP; + + switch (CLPAIR(xc, yc)) { + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): + return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "sub", x, + y); + + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): + return ieee754sp_nanxcpt(y, "sub", x, y); + + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): + return ieee754sp_nanxcpt(x, "sub", x, y); + + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): + return ieee754sp_bestnan(x, y); + + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): + return y; + + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): + return x; + + + /* Inifity handeling + */ + + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): + if (xs != ys) + return x; + SETCX(IEEE754_INVALID_OPERATION); + return ieee754sp_xcpt(ieee754sp_indef(), "sub", x, y); + + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): + return ieee754sp_inf(ys ^ 1); + + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): + return x; + + /* Zero handeling + */ + + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): + if (xs != ys) + return x; + else + return ieee754sp_zero(ieee754_csr.rm == + IEEE754_RD); + + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): + return x; + + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): + case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): + /* quick fix up */ + DPSIGN(y) ^= 1; + return y; + + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): + SPDNORMX; + + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): + SPDNORMY; + break; + + case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): + SPDNORMX; + break; + + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): + break; + } + /* flip sign of y and handle as add */ + ys ^= 1; + + assert(xm & SP_HIDDEN_BIT); + assert(ym & SP_HIDDEN_BIT); + + + /* provide guard,round and stick bit space */ + xm <<= 3; + ym <<= 3; + + if (xe > ye) { + /* have to shift y fraction right to align + */ + int s = xe - ye; + SPXSRSYn(s); + } else if (ye > xe) { + /* have to shift x fraction right to align + */ + int s = ye - xe; + SPXSRSXn(s); + } + assert(xe == ye); + assert(xe <= SP_EMAX); + + if (xs == ys) { + /* generate 28 bit result of adding two 27 bit numbers + */ + xm = xm + ym; + xe = xe; + xs = xs; + + if (xm >> (SP_MBITS + 1 + 3)) { /* carry out */ + SPXSRSX1(); /* shift preserving sticky */ + } + } else { + if (xm >= ym) { + xm = xm - ym; + xe = xe; + xs = xs; + } else { + xm = ym - xm; + xe = xe; + xs = ys; + } + if (xm == 0) + if (ieee754_csr.rm == IEEE754_RD) + return ieee754sp_zero(1); /* round negative inf. => sign = -1 */ + else + return ieee754sp_zero(0); /* other round modes => sign = 1 */ + + /* normalize to rounding precision + */ + while ((xm >> (SP_MBITS + 3)) == 0) { + xm <<= 1; + xe--; + } + } + SPNORMRET2(xs, xe, xm, "sub", x, y); +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_tint.c linux/arch/mips64/math-emu/sp_tint.c --- v2.4.5/linux/arch/mips64/math-emu/sp_tint.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/sp_tint.c Mon Jul 2 13:56:41 2001 @@ -0,0 +1,88 @@ +/* IEEE754 floating point arithmetic + * single precision + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754sp.h" + +int ieee754sp_tint(ieee754sp x) +{ + COMPXSP; + + CLEARCX; + + EXPLODEXSP; + + switch (xc) { + case IEEE754_CLASS_SNAN: + case IEEE754_CLASS_QNAN: + SETCX(IEEE754_INVALID_OPERATION); + return ieee754si_xcpt(ieee754si_indef(), "fixsp", x); + case IEEE754_CLASS_INF: + SETCX(IEEE754_OVERFLOW); + return ieee754si_xcpt(ieee754si_indef(), "fixsp", x); + case IEEE754_CLASS_ZERO: + return 0; + case IEEE754_CLASS_DNORM: /* much to small */ + SETCX(IEEE754_UNDERFLOW); + return ieee754si_xcpt(0, "fixsp", x); + case IEEE754_CLASS_NORM: + break; + } + if (xe >= 31) { + SETCX(IEEE754_OVERFLOW); + return ieee754si_xcpt(ieee754si_indef(), "fix", x); + } + if (xe < 0) { + SETCX(IEEE754_UNDERFLOW); + return ieee754si_xcpt(0, "fix", x); + } + /* oh gawd */ + if (xe > SP_MBITS) { + xm <<= xe - SP_MBITS; + } else if (xe < SP_MBITS) { + /* XXX no rounding + */ + xm >>= SP_MBITS - xe; + } + if (xs) + return -xm; + else + return xm; +} + + +unsigned int ieee754sp_tuns(ieee754sp x) +{ + ieee754sp hb = ieee754sp_1e31(); + + /* what if x < 0 ?? */ + if (ieee754sp_lt(x, hb)) + return (unsigned) ieee754sp_tint(x); + + return (unsigned) ieee754sp_tint(ieee754sp_sub(x, hb)) | + ((unsigned) 1 << 31); +} diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_tlong.c linux/arch/mips64/math-emu/sp_tlong.c --- v2.4.5/linux/arch/mips64/math-emu/sp_tlong.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/math-emu/sp_tlong.c Mon Jul 2 13:56:41 2001 @@ -0,0 +1,87 @@ +/* IEEE754 floating point arithmetic + * single precision + */ +/* + * MIPS floating point support + * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. + * http://www.algor.co.uk + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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 "ieee754sp.h" + +long long ieee754sp_tlong(ieee754sp x) +{ + COMPXDP; /* <-- need 64-bit mantissa tmp */ + + CLEARCX; + + EXPLODEXSP; + + switch (xc) { + case IEEE754_CLASS_SNAN: + case IEEE754_CLASS_QNAN: + SETCX(IEEE754_INVALID_OPERATION); + return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x); + case IEEE754_CLASS_INF: + SETCX(IEEE754_OVERFLOW); + return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x); + case IEEE754_CLASS_ZERO: + return 0; + case IEEE754_CLASS_DNORM: /* much to small */ + SETCX(IEEE754_UNDERFLOW); + return ieee754di_xcpt(0, "sp_tlong", x); + case IEEE754_CLASS_NORM: + break; + } + if (xe >= 63) { + SETCX(IEEE754_OVERFLOW); + return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x); + } + if (xe < 0) { + SETCX(IEEE754_UNDERFLOW); + return ieee754di_xcpt(0, "sp_tlong", x); + } + /* oh gawd */ + if (xe > SP_MBITS) { + xm <<= xe - SP_MBITS; + } else if (xe < SP_MBITS) { + /* XXX no rounding + */ + xm >>= SP_MBITS - xe; + } + if (xs) + return -xm; + else + return xm; +} + + +unsigned long long ieee754sp_tulong(ieee754sp x) +{ + ieee754sp hb = ieee754sp_1e63(); + + /* what if x < 0 ?? */ + if (ieee754sp_lt(x, hb)) + return (unsigned long long) ieee754sp_tlong(x); + + return (unsigned long long) ieee754sp_tlong(ieee754sp_sub(x, hb)) | + (1ULL << 63); +} diff -u --recursive --new-file v2.4.5/linux/arch/parisc/vmlinux.lds linux/arch/parisc/vmlinux.lds --- v2.4.5/linux/arch/parisc/vmlinux.lds Tue Dec 5 12:29:39 2000 +++ linux/arch/parisc/vmlinux.lds Mon Jul 2 14:40:58 2001 @@ -22,7 +22,7 @@ } = 0 . = ALIGN(16); - .rodata : { *(.rodata) } + .rodata : { *(.rodata) *(.rodata.*) } .kstrtab : { *(.kstrtab) } _etext = .; /* End of text section */ diff -u --recursive --new-file v2.4.5/linux/arch/ppc/8xx_io/commproc.c linux/arch/ppc/8xx_io/commproc.c --- v2.4.5/linux/arch/ppc/8xx_io/commproc.c Mon May 21 17:04:46 2001 +++ linux/arch/ppc/8xx_io/commproc.c Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.commproc.c 1.8 05/18/01 07:54:04 patch + * BK Id: SCCS/s.commproc.c 1.11 06/15/01 13:00:20 paulus */ /* @@ -47,12 +47,12 @@ /* CPM interrupt vector functions. */ struct cpm_action { - void (*handler)(void *); + void (*handler)(void *, struct pt_regs * regs); void *dev_id; }; static struct cpm_action cpm_vecs[CPMVEC_NR]; static void cpm_interrupt(int irq, void * dev, struct pt_regs * regs); -static void cpm_error_interrupt(void *); +static void cpm_error_interrupt(void *, struct pt_regs * regs); void m8xx_cpm_reset(uint host_page_addr) @@ -129,7 +129,7 @@ vec >>= 11; if (cpm_vecs[vec].handler != 0) - (*cpm_vecs[vec].handler)(cpm_vecs[vec].dev_id); + (*cpm_vecs[vec].handler)(cpm_vecs[vec].dev_id, regs); else ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << vec); @@ -146,14 +146,15 @@ * tests in the interrupt handler. */ static void -cpm_error_interrupt(void *dev) +cpm_error_interrupt(void *dev, struct pt_regs *regs) { } /* Install a CPM interrupt handler. */ void -cpm_install_handler(int vec, void (*handler)(void *), void *dev_id) +cpm_install_handler(int vec, void (*handler)(void *, struct pt_regs *regs), + void *dev_id) { /* If null handler, assume we are trying to free the IRQ. diff -u --recursive --new-file v2.4.5/linux/arch/ppc/8xx_io/commproc.h linux/arch/ppc/8xx_io/commproc.h --- v2.4.5/linux/arch/ppc/8xx_io/commproc.h Mon May 21 17:04:46 2001 +++ linux/arch/ppc/8xx_io/commproc.h Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.commproc.h 1.8 05/17/01 18:14:20 cort + * BK Id: SCCS/s.commproc.h 1.13 06/15/01 13:00:20 paulus */ /* @@ -789,7 +789,8 @@ #define CICR_IEN ((uint)0x00000080) /* Int. enable */ #define CICR_SPS ((uint)0x00000001) /* SCC Spread */ -extern void cpm_install_handler(int vec, void (*handler)(void *), void *dev_id); +extern void cpm_install_handler(int vec, + void (*handler)(void *, struct pt_regs *regs), void *dev_id); extern void cpm_free_handler(int vec); #endif /* __CPM_8XX__ */ diff -u --recursive --new-file v2.4.5/linux/arch/ppc/8xx_io/uart.c linux/arch/ppc/8xx_io/uart.c --- v2.4.5/linux/arch/ppc/8xx_io/uart.c Mon May 21 17:04:46 2001 +++ linux/arch/ppc/8xx_io/uart.c Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.uart.c 1.10 05/17/01 18:14:20 cort + * BK Id: SCCS/s.uart.c 1.14 06/27/01 14:49:55 trini */ /* * UART driver for MPC860 CPM SCC or SMC @@ -44,6 +44,9 @@ #include #include #include "commproc.h" +#ifdef CONFIG_MAGIC_SYSRQ +#include +#endif #ifdef CONFIG_KGDB extern void breakpoint(void); @@ -91,6 +94,15 @@ static int serial_refcount; static int serial_console_setup(struct console *co, char *options); +static int serial_console_wait_key(struct console *co); +static void serial_console_write(struct console *c, const char *s, + unsigned count); +static kdev_t serial_console_device(struct console *c); + +#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +static unsigned long break_pressed; /* break, really ... */ +#endif + /* * Serial driver configuration section. Here are the various options: */ @@ -202,6 +214,16 @@ cbd_t *tx_cur; } ser_info_t; +static struct console sercons = { + name: "ttyS", + write: serial_console_write, + device: serial_console_device, + wait_key: serial_console_wait_key, + setup: serial_console_setup, + flags: CON_PRINTBUFFER, + index: CONFIG_SERIAL_CONSOLE_PORT, +}; + static void change_speed(ser_info_t *info); static void rs_8xx_wait_until_sent(struct tty_struct *tty, int timeout); @@ -325,7 +347,7 @@ mark_bh(SERIAL_BH); } -static _INLINE_ void receive_chars(ser_info_t *info) +static _INLINE_ void receive_chars(ser_info_t *info, struct pt_regs *regs) { struct tty_struct *tty = info->tty; unsigned char ch, *cp; @@ -413,7 +435,7 @@ } */ status &= info->read_status_mask; - + if (status & (BD_SC_BR)) { #ifdef SERIAL_DEBUG_INTR printk("handling break...."); @@ -440,6 +462,17 @@ } } } +#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) + if (break_pressed && info->line == sercons.index) { + if (ch != 0 && time_before(jiffies, + break_pressed + HZ*5)) { + handle_sysrq(ch, regs, NULL, NULL); + break_pressed = 0; + goto ignore_char; + } else + break_pressed = 0; + } +#endif if (tty->flip.count >= TTY_FLIPBUF_SIZE) break; @@ -448,6 +481,7 @@ tty->flip.count++; } + ignore_char: /* This BD is ready to be used again. Clear status. * Get next BD. */ @@ -459,17 +493,27 @@ else bdp++; } - info->rx_cur = (cbd_t *)bdp; queue_task(&tty->flip.tqueue, &tq_timer); } -static _INLINE_ void receive_break(ser_info_t *info) +static _INLINE_ void receive_break(ser_info_t *info, struct pt_regs *regs) { struct tty_struct *tty = info->tty; info->state->icount.brk++; + +#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) + if (info->line == sercons.index) { + if (!break_pressed) { + break_pressed = jiffies; + return; + } else + break_pressed = 0; + } +#endif + /* Check to see if there is room in the tty buffer for * the break. If not, we exit now, losing the break. FIXME */ @@ -482,7 +526,7 @@ queue_task(&tty->flip.tqueue, &tq_timer); } -static _INLINE_ void transmit_chars(ser_info_t *info) +static _INLINE_ void transmit_chars(ser_info_t *info, struct pt_regs *regs) { if ((info->flags & TX_WAKEUP) || @@ -571,7 +615,7 @@ /* * This is the serial driver's interrupt routine for a single port */ -static void rs_8xx_interrupt(void *dev_id) +static void rs_8xx_interrupt(void *dev_id, struct pt_regs *regs) { u_char events; int idx; @@ -585,21 +629,23 @@ if (info->state->smc_scc_num & NUM_IS_SCC) { sccp = &cpmp->cp_scc[idx]; events = sccp->scc_scce; + if (events & SMCM_BRKE) + receive_break(info, regs); if (events & SCCM_RX) - receive_chars(info); + receive_chars(info, regs); if (events & SCCM_TX) - transmit_chars(info); + transmit_chars(info, regs); sccp->scc_scce = events; } else { smcp = &cpmp->cp_smc[idx]; events = smcp->smc_smce; if (events & SMCM_BRKE) - receive_break(info); + receive_break(info, regs); if (events & SMCM_RX) - receive_chars(info); + receive_chars(info, regs); if (events & SMCM_TX) - transmit_chars(info); + transmit_chars(info, regs); smcp->smc_smce = events; } @@ -2428,17 +2474,6 @@ return MKDEV(TTY_MAJOR, 64 + c->index); } - -static struct console sercons = { - name: "ttyS", - write: serial_console_write, - device: serial_console_device, - wait_key: serial_console_wait_key, - setup: serial_console_setup, - flags: CON_PRINTBUFFER, - index: CONFIG_SERIAL_CONSOLE_PORT, -}; - /* * Register console. */ @@ -2771,7 +2806,7 @@ immap->im_ioport.iop_padir &= ~iobits; immap->im_ioport.iop_paodr &= ~iobits; } -#endif +#endif /* CONFIG_ALTSMC2 */ /* Connect the baud rate generator to the * SMC based upon index in rs_table. Also diff -u --recursive --new-file v2.4.5/linux/arch/ppc/boot/chrp/main.c linux/arch/ppc/boot/chrp/main.c --- v2.4.5/linux/arch/ppc/boot/chrp/main.c Thu May 24 15:02:06 2001 +++ linux/arch/ppc/boot/chrp/main.c Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.main.c 1.7 05/18/01 06:20:29 patch + * BK Id: SCCS/s.main.c 1.9 06/12/01 16:42:26 paulus */ /* * Copyright (C) Paul Mackerras 1997. @@ -100,13 +100,13 @@ rec->tag = BI_MACHTYPE; rec->data[0] = _MACH_chrp; rec->data[1] = 1; - rec->size = sizeof(struct bi_record) + sizeof(unsigned long); + rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long); rec = (struct bi_record *)((unsigned long)rec + rec->size); #if 0 rec->tag = BI_SYSMAP; rec->data[0] = (unsigned long)sysmap_data; rec->data[1] = sysmap_len; - rec->size = sizeof(struct bi_record) + sizeof(unsigned long); + rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long); rec = (struct bi_record *)((unsigned long)rec + rec->size); #endif rec->tag = BI_LAST; diff -u --recursive --new-file v2.4.5/linux/arch/ppc/boot/common/misc-common.c linux/arch/ppc/boot/common/misc-common.c --- v2.4.5/linux/arch/ppc/boot/common/misc-common.c Thu May 24 15:02:06 2001 +++ linux/arch/ppc/boot/common/misc-common.c Mon Jul 2 14:34:57 2001 @@ -38,7 +38,7 @@ /* If we're on a ALL_PPC, assume we have a keyboard controller * Also note, if we're not ALL_PPC, we assume you are a serial * console - Tom */ -#ifdef CONFIG_ALL_PPC +#if defined(CONFIG_ALL_PPC) && defined(CONFIG_VGA_CONSOLE) extern void cursor(int x, int y); extern void scroll(void); extern char *vidmem; @@ -268,7 +268,7 @@ s.zfree = zfree; r = inflateInit2(&s, -MAX_WBITS); if (r != Z_OK) { - puts("inflateInit2 returned %d\n"); + puts("inflateInit2 returned "); puthex(r); puts("\n"); exit(); } s.next_in = src + i; @@ -277,7 +277,7 @@ s.avail_out = dstlen; r = inflate(&s, Z_FINISH); if (r != Z_OK && r != Z_STREAM_END) { - puts("inflate returned %d\n"); + puts("inflate returned "); puthex(r); puts("\n"); exit(); } *lenp = s.next_out - (unsigned char *) dst; diff -u --recursive --new-file v2.4.5/linux/arch/ppc/boot/mbx/Makefile linux/arch/ppc/boot/mbx/Makefile --- v2.4.5/linux/arch/ppc/boot/mbx/Makefile Thu May 24 15:02:06 2001 +++ linux/arch/ppc/boot/mbx/Makefile Mon Jun 11 19:15:27 2001 @@ -1,4 +1,4 @@ -# BK Id: SCCS/s.Makefile 1.5 05/18/01 06:20:29 patch +# BK Id: SCCS/s.Makefile 1.7 06/05/01 20:20:05 paulus # # # arch/ppc/mbxboot/Makefile @@ -87,13 +87,21 @@ $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ --add-section=initrd=../images/ramdisk.image.gz \ --add-section=image=../images/vmlinux.gz \ - $@.tmp ../images/$@.mbx + $@.tmp ../images/$@.embedded zImage: zvmlinux - ln -sf zvmlinux.mbx ../images/zImage.mbx +ifeq ($(CONFIG_RPXCLASSIC),y) + dd if=../images/zvmlinux.embedded of=../images/zImage.embedded bs=65536 skip=1 +else + ln -sf ../images/zvmlinux.embedded ../images/zImage.embedded +endif zImage.initrd: zvmlinux.initrd - ln -sf zvmlinux.initrd.mbx ../images/zImage.initrd.mbx +ifeq ($(CONFIG_RPXCLASSIC),y) + dd if=../images/zvmlinux.initrd.embedded of=../images/zImage.initrd.embedded bs=65536 skip=1 +else + ln -sf ../images/zvmlinux.initrd.embedded ../images/zImage.initrd.embedded +endif zvmlinux: $(OBJECTS) $(LIBS) ../images/vmlinux.gz # @@ -114,14 +122,14 @@ $(LD) $(ZLINKFLAGS) -o $@.tmp $(OBJECTS) $(LIBS) $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ --add-section=image=../images/vmlinux.gz \ - $@.tmp ../images/$@.mbx -# Remove zvmlinux and zvmlinux.temp, we have ../images/zvmlinux.mbx + $@.tmp ../images/$@.embedded +# Remove zvmlinux and zvmlinux.temp, we have ../images/zvmlinux.embedded rm -f $@.tmp $@ znetboot : zImage - cp ../images/zImage.mbx $(TFTPIMAGE) + cp ../images/zImage.embedded $(TFTPIMAGE) znetboot.initrd : zImage.initrd - cp ../images/zImage.initrd.mbx $(TFTPIMAGE) + cp ../images/zImage.initrd.embedded $(TFTPIMAGE) include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.5/linux/arch/ppc/boot/pmac/Makefile linux/arch/ppc/boot/pmac/Makefile --- v2.4.5/linux/arch/ppc/boot/pmac/Makefile Thu May 24 15:02:07 2001 +++ linux/arch/ppc/boot/pmac/Makefile Mon Jun 11 19:15:27 2001 @@ -1,4 +1,4 @@ -# BK Id: SCCS/s.Makefile 1.8 05/21/01 09:10:38 trini +# BK Id: SCCS/s.Makefile 1.10 06/05/01 20:22:51 paulus # # Makefile for making XCOFF bootable images for booting on PowerMacs # using Open Firmware. @@ -7,7 +7,7 @@ # # Cleaned up, moved into arch/ppc/boot/pmac # Tom Rini January 2001 - + OBJCOPY_ARGS = -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment COFF_LD_ARGS = -e _start -T ld.script -Ttext 500000 -Tdata 510000 -Bstatic CHRP_LD_ARGS = -Ttext 0x01000000 diff -u --recursive --new-file v2.4.5/linux/arch/ppc/boot/pmac/chrpmain.c linux/arch/ppc/boot/pmac/chrpmain.c --- v2.4.5/linux/arch/ppc/boot/pmac/chrpmain.c Thu May 24 15:02:07 2001 +++ linux/arch/ppc/boot/pmac/chrpmain.c Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.chrpmain.c 1.9 05/18/01 06:20:29 patch + * BK Id: SCCS/s.chrpmain.c 1.12 06/12/01 16:42:26 paulus */ /* * Copyright (C) Paul Mackerras 1997. @@ -34,15 +34,6 @@ #define SCRATCH_SIZE (128 << 10) -#ifdef CONFIG_CMDLINE -#define CMDLINE CONFIG_CMDLINE -#else -#define CMDLINE "" -#endif -char cmd_preset[] = CMDLINE; -char cmd_buf[256]; -char *cmd_line = cmd_buf; - char *avail_ram; char *begin_avail, *end_avail; char *avail_high; @@ -98,7 +89,6 @@ } flush_cache(dst, len); - memcpy (cmd_line, cmd_preset, sizeof(cmd_preset)); make_bi_recs((unsigned long) dst + len); sa = (unsigned long)PROG_START; @@ -133,19 +123,14 @@ rec->tag = BI_MACHTYPE; rec->data[0] = _MACH_Pmac; rec->data[1] = 1; - rec->size = sizeof(struct bi_record) + sizeof(unsigned long); - rec = (struct bi_record *)((unsigned long)rec + rec->size); - - rec->tag = BI_CMD_LINE; - memcpy( (char *)rec->data, cmd_line, strlen(cmd_line)+1); - rec->size = sizeof(struct bi_record) + strlen(cmd_line) + 1; + rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long); rec = (struct bi_record *)((unsigned long)rec + rec->size); #ifdef SYSMAP_OFFSET rec->tag = BI_SYSMAP; rec->data[0] = SYSMAP_OFFSET; rec->data[1] = SYSMAP_SIZE; - rec->size = sizeof(struct bi_record) + sizeof(unsigned long); + rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long); rec = (struct bi_record *)((unsigned long)rec + rec->size); #endif /* SYSMAP_OFFSET */ diff -u --recursive --new-file v2.4.5/linux/arch/ppc/boot/pmac/coffmain.c linux/arch/ppc/boot/pmac/coffmain.c --- v2.4.5/linux/arch/ppc/boot/pmac/coffmain.c Thu May 24 15:02:07 2001 +++ linux/arch/ppc/boot/pmac/coffmain.c Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.coffmain.c 1.9 05/18/01 06:20:29 patch + * BK Id: SCCS/s.coffmain.c 1.12 06/12/01 16:42:26 paulus */ /* * Copyright (C) Paul Mackerras 1997. @@ -24,7 +24,7 @@ #define get_16be(x) (*(unsigned short *)(x)) #define get_32be(x) (*(unsigned *)(x)) -#define RAM_START 0xc0000000 +#define RAM_START 0 #define RAM_END (RAM_START + 0x800000) /* only 8M mapped with BATs */ #define PROG_START RAM_START @@ -32,15 +32,6 @@ #define SCRATCH_SIZE (128 << 10) -#ifdef CONFIG_CMDLINE -#define CMDLINE CONFIG_CMDLINE -#else -#define CMDLINE "" -#endif -char cmd_preset[] = CMDLINE; -char cmd_buf[256]; -char *cmd_line = cmd_buf; - char *avail_ram; char *begin_avail, *end_avail; char *avail_high; @@ -81,7 +72,7 @@ claim(0, PROG_SIZE, 0); dst = (void *) RAM_START; if (im[0] == 0x1f && im[1] == 0x8b) { - /* claim some memory for scratch space */ + /* set up scratch space */ begin_avail = avail_high = avail_ram = heap; end_avail = heap + sizeof(heap); printf("heap at 0x%x\n", avail_ram); @@ -95,7 +86,6 @@ } flush_cache(dst, len); - memcpy (cmd_line, cmd_preset, sizeof(cmd_preset)); make_bi_recs((unsigned long)dst + len); sa = (unsigned long)PROG_START; @@ -127,18 +117,13 @@ sprintf( (char *)rec->data, "coffboot"); rec->size = sizeof(struct bi_record) + strlen("coffboot") + 1; rec = (struct bi_record *)((unsigned long)rec + rec->size); - + rec->tag = BI_MACHTYPE; rec->data[0] = _MACH_Pmac; rec->data[1] = 1; - rec->size = sizeof(struct bi_record) + sizeof(unsigned long); + rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long); rec = (struct bi_record *)((unsigned long)rec + rec->size); - - rec->tag = BI_CMD_LINE; - memcpy( (char *)rec->data, cmd_line, strlen(cmd_line)+1); - rec->size = sizeof(struct bi_record) + strlen(cmd_line) + 1; - rec = (struct bi_record *)((unsigned long)rec + rec->size); - + rec->tag = BI_LAST; rec->size = sizeof(struct bi_record); rec = (struct bi_record *)((unsigned long)rec + rec->size); diff -u --recursive --new-file v2.4.5/linux/arch/ppc/boot/pmac/ld.script linux/arch/ppc/boot/pmac/ld.script --- v2.4.5/linux/arch/ppc/boot/pmac/ld.script Thu May 24 15:02:07 2001 +++ linux/arch/ppc/boot/pmac/ld.script Mon Jul 2 14:40:58 2001 @@ -32,6 +32,7 @@ { *(.text) *(.rodata) + *(.rodata.*) *(.rodata1) *(.got1) } diff -u --recursive --new-file v2.4.5/linux/arch/ppc/boot/prep/Makefile linux/arch/ppc/boot/prep/Makefile --- v2.4.5/linux/arch/ppc/boot/prep/Makefile Thu May 24 15:02:07 2001 +++ linux/arch/ppc/boot/prep/Makefile Mon Jul 2 14:34:57 2001 @@ -1,4 +1,4 @@ -# BK Id: SCCS/s.Makefile 1.15 05/21/01 11:51:32 trini +# BK Id: SCCS/s.Makefile 1.17 06/12/01 16:47:44 paulus # # arch/ppc/boot/Makefile # @@ -33,13 +33,17 @@ endif ZLINKFLAGS = -T $(TOPDIR)/arch/$(ARCH)/vmlinux.lds -Ttext 0x00800000 -OBJECTS := head.o misc.o vreset.o kbd.o ../common/misc-common.o \ +OBJECTS := head.o misc.o ../common/misc-common.o \ ../common/string.o of1275.o OBJCOPY_ARGS = -O elf32-powerpc LIBS = ../lib/zlib.a ifeq ($(CONFIG_SERIAL_CONSOLE),y) OBJECTS += ns16550.o +endif + +ifeq ($(CONFIG_VGA_CONSOLE),y) +OBJECTS += vreset.o kbd.o endif # Tools diff -u --recursive --new-file v2.4.5/linux/arch/ppc/boot/prep/misc.c linux/arch/ppc/boot/prep/misc.c --- v2.4.5/linux/arch/ppc/boot/prep/misc.c Thu May 24 15:02:07 2001 +++ linux/arch/ppc/boot/prep/misc.c Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.misc.c 1.8 05/18/01 06:20:29 patch + * BK Id: SCCS/s.misc.c 1.14 06/16/01 20:43:20 trini */ /* * misc.c @@ -13,8 +13,9 @@ #include #include "zlib.h" #include -#include #include +#include +#include #include #include #include @@ -102,6 +103,7 @@ return; } +#ifdef CONFIG_VGA_CONSOLE void scroll() { @@ -111,6 +113,7 @@ for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 ) vidmem[i] = ' '; } +#endif /* CONFIG_VGA_CONSOLE */ /* * This routine is used to control the second processor on the @@ -170,7 +173,9 @@ #if defined(CONFIG_SERIAL_CONSOLE) com_port = serial_init(0); #endif /* CONFIG_SERIAL_CONSOLE */ - vga_init((char)0xC0000000); +#if defined(CONFIG_VGA_CONSOLE) + vga_init((unsigned char *)0xC0000000); +#endif /* CONFIG_VGA_CONSOLE */ if (residual) { @@ -360,11 +365,18 @@ while (timer++ < 5*1000) { if (tstc()) { while ((ch = getc()) != '\n' && ch != '\r') { - if (ch == '\b') { + /* Test for backspace/delete */ + if (ch == '\b' || ch == '\177') { if (cp != cmd_line) { cp--; puts("\b \b"); } + /* Test for ^x/^u (and wipe the line) */ + } else if (ch == '\030' || ch == '\025') { + while (cp != cmd_line) { + cp--; + puts("\b \b"); + } } else { *cp++ = ch; putc(ch); @@ -393,7 +405,7 @@ { struct bi_record *rec; - rec = (struct bi_record *)PAGE_ALIGN(zimage_size); + rec = (struct bi_record *)_ALIGN((unsigned long)(zimage_size)+(1<<20)-1,(1<<20)); rec->tag = BI_FIRST; rec->size = sizeof(struct bi_record); @@ -406,8 +418,8 @@ rec->tag = BI_MACHTYPE; rec->data[0] = _MACH_prep; - rec->data[1] = 1; - rec->size = sizeof(struct bi_record) + sizeof(unsigned long); + rec->data[1] = 0; + rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long); rec = (struct bi_record *)((unsigned long)rec + rec->size); rec->tag = BI_CMD_LINE; diff -u --recursive --new-file v2.4.5/linux/arch/ppc/boot/tree/Makefile linux/arch/ppc/boot/tree/Makefile --- v2.4.5/linux/arch/ppc/boot/tree/Makefile Thu May 24 15:02:07 2001 +++ linux/arch/ppc/boot/tree/Makefile Mon Jul 2 14:34:57 2001 @@ -1,4 +1,4 @@ -# BK Id: SCCS/s.Makefile 1.5 05/18/01 06:20:29 patch +# BK Id: SCCS/s.Makefile 1.7 06/15/01 13:16:10 paulus # # # Module name: Makefile @@ -26,12 +26,13 @@ GZIP = gzip -vf9 RM = rm -f -MKEVIMG = ../utils/mkevimg -l +MKEVIMG = ../utils/mkevimg -l -c MKIRIMG = ../utils/mkirimg +CFLAGS += -I$(TOPDIR)/drivers/net LD_ARGS = -e _start -T ld.script -Ttext 0x00200000 -Bstatic OBJS = ../common/crt0.o main.o misc.o irSect.o ../common/string.o \ - ../common/misc-common.o + ../common/misc-common.o ../common/ns16550.o LIBS = ../lib/zlib.a treeboot: $(OBJS) $(LIBS) ld.script diff -u --recursive --new-file v2.4.5/linux/arch/ppc/boot/tree/ld.script linux/arch/ppc/boot/tree/ld.script --- v2.4.5/linux/arch/ppc/boot/tree/ld.script Thu May 24 15:02:07 2001 +++ linux/arch/ppc/boot/tree/ld.script Mon Jul 2 14:40:58 2001 @@ -32,6 +32,7 @@ { *(.text) *(.rodata) + *(.rodata.*) *(.rodata1) *(.got1) } diff -u --recursive --new-file v2.4.5/linux/arch/ppc/boot/tree/main.c linux/arch/ppc/boot/tree/main.c --- v2.4.5/linux/arch/ppc/boot/tree/main.c Thu May 24 15:02:07 2001 +++ linux/arch/ppc/boot/tree/main.c Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.main.c 1.7 05/18/01 06:20:29 patch + * BK Id: SCCS/s.main.c 1.9 06/15/01 13:16:10 paulus */ /* * Copyright (c) 1997 Paul Mackerras @@ -74,16 +74,6 @@ #define ALIGN_UP(x, align) (((x) + ((align) - 1)) & ~((align) - 1)) -#define stringify(s) tostring(s) -#define tostring(s) #s - -#define mtdcr(rn, v) asm volatile("mtdcr " stringify(rn) ",%0" : : "r" (v)) -#define mfdcr(rn) ({unsigned int rval; \ - asm volatile("mfdcr %0," stringify(rn) \ - : "=r" (rval)); rval;}) -#define DCRN_MALCR 0x180 /* MAL Configuration */ -#define MALCR_SR 0x80000000 /* Software Reset */ - /* Global Variables */ /* Needed by zalloc and zfree for allocating memory */ @@ -91,15 +81,11 @@ char *avail_ram; /* Indicates start of RAM available for heap */ char *end_avail; /* Indicates end of RAM available for heap */ -bd_t board_info; - -/* - * XXX - Until either the IBM boot ROM provides a way of passing arguments to - * the program it launches or until I/O is working in the boot loader, - * this is a good spot to pass in command line arguments to the kernel - * (e.g. console=tty0). - */ +/* Needed for serial I/O. +*/ +extern unsigned long *com_port; +bd_t board_info; /* ** The bootrom may change bootrom_cmdline to point to a buffer in the @@ -116,35 +102,16 @@ /* Function Prototypes */ -extern void *zalloc(void *x, unsigned items, unsigned size); - -/* serial I/O functions. - * These should have generic names, although this is similar to 16550.... - */ -static volatile unsigned char *uart0_lsr = (unsigned char *)0xef600305; -static volatile unsigned char *uart0_xcvr = (unsigned char *)0xef600300; +extern void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp); void -serial_putc(void *unused, unsigned char c) -{ - while ((*uart0_lsr & LSR_THRE) == 0); - *uart0_xcvr = c; -} - -unsigned char -serial_getc(void *unused) -{ - while ((*uart0_lsr & LSR_DR) == 0); - return (*uart0_xcvr); -} - -int -serial_tstc(void *unused) +kick_watchdog(void) { - return ((*uart0_lsr & LSR_DR) != 0); +#ifdef CONFIG_405GP + mtspr(SPRN_TSR, (TSR_ENW | TSR_WIS)); +#endif } - void start(void) { void *options; @@ -156,40 +123,34 @@ bd_t *(*get_board_info)(void) = (bd_t *(*)(void))(*(unsigned long *)BOARD_INFO_VECTOR); bd_t *bip = NULL; - volatile unsigned long *em0mr0 = (long *)0xEF600800; /* ftr fixup */ + com_port = (struct NS16550 *)serial_init(0); -#if defined(CONFIG_WALNUT) - /* turn off ethernet */ +#ifdef CONFIG_405GP + /* turn off on-chip ethernet */ /* This is to fix a problem with early walnut bootrom. */ - - mtdcr(DCRN_MALCR, MALCR_SR); /* 1st reset MAL */ - - while (mfdcr(DCRN_MALCR) & MALCR_SR) {}; /* wait for the reset */ - - *em0mr0 = 0x20000000; /* then reset EMAC */ -#endif - - -#if 0 - /* ftr revisit - remove printf()s */ - - printf("\n\nbootrom_cmdline = >%s<\n\n", bootrom_cmdline); - if (*bootrom_cmdline != '\0') { - printf("bootrom_cmdline != NULL, copying it into cmdline\n\n"); - *treeboot_bootrom_cmdline = '\0'; - strcat(treeboot_bootrom_cmdline, bootrom_cmdline); - cmdline = treeboot_bootrom_cmdline; + + { + /* Physical mapping of ethernet register space. */ + static struct ppc405_enet_regs *ppc405_enet_regp = + (struct ppc405_enet_regs *)PPC405_EM0_REG_ADDR; + + mtdcr(DCRN_MALCR, MALCR_MMSR); /* 1st reset MAL */ + + while (mfdcr(DCRN_MALCR) & MALCR_MMSR) {}; /* wait for the reset */ + + ppc405_enet_regp->em0mr0 = 0x20000000; /* then reset EMAC */ } #endif - if ((bip = get_board_info()) != NULL) memcpy(&board_info, bip, sizeof(bd_t)); /* Init RAM disk (initrd) section */ + kick_watchdog(); + if (initrdSect_start != 0 && (initrd_size = initrdSect_size) != 0) { initrd_start = (RAM_END - initrd_size) & ~0xFFF; @@ -208,6 +169,8 @@ /* Linux kernel image section */ + kick_watchdog(); + im = (unsigned char *)(imageSect_start); len = imageSect_size; dst = (void *)PROG_START; @@ -233,6 +196,7 @@ memmove(dst, im, len); } + kick_watchdog(); flush_cache(dst, len); diff -u --recursive --new-file v2.4.5/linux/arch/ppc/boot/utils/mkevimg linux/arch/ppc/boot/utils/mkevimg --- v2.4.5/linux/arch/ppc/boot/utils/mkevimg Thu May 24 15:02:07 2001 +++ linux/arch/ppc/boot/utils/mkevimg Mon Jul 2 14:34:57 2001 @@ -23,7 +23,8 @@ # unsigned long num_512blocks; Size, rounded-up, in 512 byte blocks # unsigned long debug_flag; Run the debugger or image after load # unsigned long entry_point; The image address to jump to after load -# unsigned long reserved[3]; +# unsigned long checksum; 32 bit checksum including header +# unsigned long reserved[2]; # } boot_block_t; # # @@ -61,6 +62,7 @@ } if ($status != 1) { + print(" -c Put checksum in load information block.\n"); print(" -h Print out this message and exit.\n"); print(" -l Linux mode; if present, copy 'image' and 'initrd' sections.\n"); print(" -v Verbose. Print out lots of ELF information.\n"); @@ -148,10 +150,14 @@ sub decode_options { - if (!getopts("hlvV")) { + if (!getopts("chlvV")) { usage(1); } + if ($opt_c) { + $do_checksum = 1; + } + if ($opt_h) { usage(0); } @@ -360,14 +366,20 @@ $output_size += $initrd_size; } - $num_blocks = $output_size / 512 + 1; + # + # Compute size with header + # + + $header = pack("H8N7", "0052504f", 0, 0, 0, 0, 0, 0, 0); + $num_blocks = ($output_size + length($header) + 511) / 512; # # Write IBM PowerPC evaluation board boot_block_t header # $header = pack("H8N7", "0052504f", $text_addr, $num_blocks, 0, - $text_addr, 0, 0, 0); + $text_addr, 0, 0, 0); + $bytes = length($header); @@ -412,18 +424,57 @@ # # Pad to a multiple of 512 bytes + # If the (size of the boot image mod 512) is between 509 and 511 bytes + # then the tftp to the Walnut fails. This may be fixed in more recent + # Walnut bootrom. # - $pad_size = 512 - (length($header) + $output_size) % 512; + $pad_size = 512 - ((length($header) + $output_size) % 512); + if ($pad_size == 512) { + $pad_size = 0; + } + + if ($pad_size != 0) { + + if ($verbose) { + print("Padding boot image by an additional $pad_size bytes.\n"); + } + + $pad_string = pack("H8","deadbeef") x 128; + + syswrite(BOOT, $pad_string, $pad_size) or + die "Could not pad boot image in output file.\n"; - if ($verbose) { - print("Padding boot image by an additional $pad_size bytes.\n"); } - $pad_string = pack(("H8","deadbeef") x 128); + # + # Compute 32 bit checksum over entire file. + # + + if ($do_checksum) { - syswrite(BOOT, $pad_string, $pad_size) or - die "Could not pad boot image in output file.\n"; + close(BOOT); + open(BOOT, "+<$ofile") || die "Cannot open output file"; + undef $/; + $temp = unpack("%32N*", ); + # Solaris and PPC Linux return 0x80000000 for "-$temp" when $temp + # is negative. "~($temp - 1)" negates $temp properly. + $csum = ~($temp - 1); + printf("Checksum = 0x%08x\r\n", $csum); + + # + # Rewrite IBM PowerPC evaluation board boot_block_t header, + # this time with the checksum included + # + + $header = pack("H8N7", "0052504f", $text_addr, $num_blocks, 0, + $text_addr, $csum, 0, 0); + + seek(BOOT, 0, 0); + syswrite(BOOT, $header, length($header)) or + die("Could not write boot image header to output file."); + + } # # Clean-up and leave diff -u --recursive --new-file v2.4.5/linux/arch/ppc/config.in linux/arch/ppc/config.in --- v2.4.5/linux/arch/ppc/config.in Tue May 22 10:23:16 2001 +++ linux/arch/ppc/config.in Mon Jul 2 14:34:57 2001 @@ -1,4 +1,4 @@ -# BK Id: SCCS/s.config.in 1.24 05/21/01 00:48:24 cort +# BK Id: SCCS/s.config.in 1.30 06/27/01 14:49:58 trini # # For a description of the syntax of this configuration file, # see Documentation/kbuild/config-language.txt. @@ -84,9 +84,9 @@ if [ "$CONFIG_6xx" = "y" -a "$CONFIG_8260" = "n" ]; then choice 'Machine Type' \ - "PowerMac/PReP/MTX/CHRP CONFIG_ALL_PPC \ - Gemini CONFIG_GEMINI \ - APUS CONFIG_APUS" PowerMac/PReP/MTX/CHRP + "CHRP/PowerMac/PReP CONFIG_ALL_PPC \ + Amgia-APUS CONFIG_APUS \ + Synergy-Gemini CONFIG_GEMINI" CHRP/PowerMac/PReP fi if [ "$CONFIG_PPC64BRIDGE" != "y" ]; then @@ -364,6 +364,10 @@ fi source drivers/usb/Config.in + +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + source net/bluetooth/Config.in +fi mainmenu_option next_comment comment 'Kernel hacking' diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/Makefile linux/arch/ppc/kernel/Makefile --- v2.4.5/linux/arch/ppc/kernel/Makefile Mon May 21 17:04:46 2001 +++ linux/arch/ppc/kernel/Makefile Mon Jul 2 14:34:57 2001 @@ -1,4 +1,4 @@ -# BK Id: SCCS/s.Makefile 1.17 05/21/01 00:48:24 cort +# BK Id: SCCS/s.Makefile 1.22 06/28/01 08:01:06 trini # # # Makefile for the linux kernel. @@ -32,18 +32,14 @@ export-objs := ppc_ksyms.o prep_setup.o obj-y := entry.o traps.o irq.o idle.o time.o misc.o \ - process.o signal.o bitops.o ptrace.o \ + process.o signal.o ptrace.o \ ppc_htab.o semaphore.o syscalls.o \ align.o setup.o obj-$(CONFIG_MODULES) += ppc_ksyms.o obj-$(CONFIG_POWER4) += xics.o obj-$(CONFIG_PCI) += pci.o pci-dma.o obj-$(CONFIG_KGDB) += ppc-stub.o -obj-$(CONFIG_PMAC_PBOOK) += sleep.o obj-$(CONFIG_SMP) += smp.o -obj-$(CONFIG_PPC_RTAS) += error_log.o proc_rtas.o -obj-$(CONFIG_NVRAM) += pmac_nvram.o -obj-$(CONFIG_PREP_RESIDUAL) += residual.o obj-$(CONFIG_4xx) += ppc4xx_pic.o obj-$(CONFIG_OAK) += oak_setup.o obj-$(CONFIG_WALNUT) += walnut_setup.o @@ -52,12 +48,10 @@ endif obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o ifeq ($(CONFIG_8xx),y) -obj-$(CONFIG_PCI) += qspan_pci.c +obj-$(CONFIG_PCI) += qspan_pci.o ifndef CONFIG_MATH_EMULATION obj-y += softemu8xx.o endif -else -obj-y += hashtable.o endif obj-$(CONFIG_MBX) += i8259.o obj-$(CONFIG_APUS) += apus_setup.o @@ -69,7 +63,11 @@ chrp_time.o chrp_pci.o open_pic.o \ indirect_pci.o i8259.o prep_pci.o \ prep_time.o prep_nvram.o prep_setup.o +obj-$(CONFIG_NVRAM) += pmac_nvram.o obj-$(CONFIG_PMAC_BACKLIGHT) += pmac_backlight.o +obj-$(CONFIG_PMAC_PBOOK) += sleep.o +obj-$(CONFIG_PPC_RTAS) += error_log.o proc_rtas.o +obj-$(CONFIG_PREP_RESIDUAL) += residual.o obj-$(CONFIG_GEMINI) += gemini_prom.o gemini_pci.o gemini_setup.o \ open_pic.o obj-$(CONFIG_8260) += m8260_setup.o ppc8260_pic.o diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/chrp_pci.c linux/arch/ppc/kernel/chrp_pci.c --- v2.4.5/linux/arch/ppc/kernel/chrp_pci.c Mon May 21 17:04:46 2001 +++ linux/arch/ppc/kernel/chrp_pci.c Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.chrp_pci.c 1.16 05/17/01 18:14:21 cort + * BK Id: SCCS/s.chrp_pci.c 1.17 06/28/01 16:11:56 paulus */ /* * CHRP pci routines. @@ -27,11 +27,6 @@ #include "open_pic.h" #include "pci.h" - -#ifdef CONFIG_POWER4 -extern unsigned long pci_address_offset(int, unsigned int); -#endif /* CONFIG_POWER4 */ - /* LongTrail */ #define pci_config_addr(dev, offset) \ (GG2_PCI_CONFIG_BASE | ((dev->bus->number)<<16) | ((dev->devfn)<<8) | (offset)) @@ -212,34 +207,6 @@ return 1; } -#ifdef CONFIG_POWER4 -static void -power4_fixup_dev(struct pci_dev *dev) -{ - int i; - unsigned long offset; - - for (i = 0; i < 6; ++i) { - if (dev->resource[i].start == 0) - continue; - offset = pci_address_offset(dev->bus->number, - dev->resource[i].flags); - if (offset) { - dev->resource[i].start += offset; - dev->resource[i].end += offset; - printk("device %x.%x[%d] now [%lx..%lx]\n", - dev->bus->number, dev->devfn, i, - dev->resource[i].start, - dev->resource[i].end); - } - /* zap the 2nd function of the winbond chip */ - if (dev->resource[i].flags & IORESOURCE_IO - && dev->bus->number == 0 && dev->devfn == 0x81) - dev->resource[i].flags &= ~IORESOURCE_IO; - } -} -#endif /* CONFIG_POWER4 */ - void __init chrp_pcibios_fixup(void) { @@ -261,48 +228,9 @@ pci_write_config_word(dev, PCI_VENDOR_ID, PCI_VENDOR_ID_AMD); } -#ifdef CONFIG_POWER4 - power4_fixup_dev(dev); -#endif } } -#if 0 -static struct { - /* parent is iomem */ - struct resource ram, pci_mem, isa_mem, pci_io, pci_cfg, rom_exp, flash; - /* parent is isa_mem */ - struct resource nvram; -} gg2_resources = { - ram: { "RAM", 0x00000000, 0xbfffffff, IORESOURCE_MEM }, - pci_mem: { "GG2 PCI mem", 0xc0000000, 0xf6ffffff, IORESOURCE_MEM }, - isa_mem: { "GG2 ISA mem", 0xf7000000, 0xf7ffffff }, - pci_io: { "GG2 PCI I/O", 0xf8000000, 0xf8ffffff }, - pci_cfg: { "GG2 PCI cfg", 0xfec00000, 0xfec7ffff }, - rom_exp: { "ROM exp", 0xff000000, 0xff7fffff, }, - flash: { "Flash ROM", 0xfff80000, 0xffffffff }, - nvram: { "NVRAM", 0xf70e0000, 0xf70e7fff }, -}; - -static void __init gg2_pcibios_fixup(void) -{ - int i; - extern unsigned long *end_of_DRAM; - - chrp_pcibios_fixup(); - gg2_resources.ram.end = (unsigned long)end_of_DRAM-PAGE_OFFSET; - for (i = 0; i < 7; i++) - request_resource(&iomem_resource, - &((struct resource *)&gg2_resources)[i]); - request_resource(&gg2_resources.isa_mem, &gg2_resources.nvram); -} - -static void __init gg2_pcibios_fixup_bus(struct pci_bus *bus) -{ - bus->resource[1] = &gg2_resources.pci_mem; -} -#endif /* 0 */ - /* this is largely modeled and stolen after the pmac_pci code -- tgall */ @@ -314,14 +242,16 @@ struct pci_controller *hose; volatile unsigned char *cfg; unsigned int *dma; -#ifdef CONFIG_POWER3 struct device_node *root = find_path_device("/"); +#ifdef CONFIG_POWER3 unsigned int *opprop = (unsigned int *) get_property(root, "platform-open-pic", NULL); int i; #endif for(; dev != NULL; dev = dev->next, ++index) { + if (dev->parent != root) + continue; if (dev->n_addrs < 1) { printk(KERN_WARNING "Can't use %s: no address\n", dev->full_name); @@ -374,23 +304,6 @@ } } -#ifdef CONFIG_POWER4 -void __init -power4_add_bridge(void) -{ - struct pci_controller* hose; - - hose = pcibios_alloc_controller(); - if (!hose) - return; - hose->first_busno = 0; - hose->last_busno = 0xff; - - hose->ops = &rtas_pci_ops; - pci_dram_offset = 0; -} -#endif /* CONFIG_POWER4 */ - void __init chrp_find_bridges(void) { @@ -400,9 +313,6 @@ ppc_md.pcibios_fixup = chrp_pcibios_fixup; -#ifdef CONFIG_POWER4 - power4_add_bridge(); -#else /* CONFIG_POWER4 */ model = get_property(find_path_device("/"), "model", NULL); if (!strncmp("MOT", model, 3)) { struct pci_controller *hose; @@ -452,36 +362,4 @@ hose->ops = &gg2_pci_ops; pci_dram_offset = 0; pci_process_bridge_OF_ranges(hose, find_devices("pci"), 1); -// ppc_md.pcibios_fixup = gg2_pcibios_fixup; -// ppc_md.pcibios_fixup_bus = gg2_pcibios_fixup_bus; -#endif /* CONFIG_POWER4 */ } - -#ifdef CONFIG_PPC64BRIDGE -#ifdef CONFIG_POWER4 -/* - * Hack alert!!! - * 64-bit machines like POWER3 and POWER4 have > 32 bit - * physical addresses. For now we remap particular parts - * of the 32-bit physical address space that the Linux - * page table gives us into parts of the physical address - * space above 4GB so we can access the I/O devices. - */ -unsigned long pci_address_offset(int busnr, unsigned int flags) -{ - unsigned long offset = 0; - - if (busnr >= 0x1e) { - if (flags & IORESOURCE_IO) - offset = -0x100000; - else if (flags & IORESOURCE_MEM) - offset = 0x38000000; - } else if (busnr <= 0xf) { - if (flags & IORESOURCE_MEM) - offset = -0x40000000; - else - } - return offset; -} -#endif /* CONFIG_POWER4 */ -#endif /* CONFIG_PPC64BRIDGE */ diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c --- v2.4.5/linux/arch/ppc/kernel/chrp_setup.c Mon May 21 17:04:46 2001 +++ linux/arch/ppc/kernel/chrp_setup.c Mon Jun 11 19:15:27 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.chrp_setup.c 1.17 05/17/01 18:14:21 cort + * BK Id: SCCS/s.chrp_setup.c 1.20 06/05/01 21:22:02 paulus */ /* * linux/arch/ppc/kernel/setup.c @@ -204,13 +204,10 @@ active = sio_read(0x30); level0 = sio_read(0x70); type0 = sio_read(0x71); - printk("sio: %s irq level %d, type %d, %sactive: ", name, level0, - type0, !active ? "in" : ""); - if (level0 == level && type0 == type && active) - printk("OK\n"); - else { - printk("remapping to level %d, type %d, active\n", level, - type); + if (level0 != level || type0 != type || !active) { + printk(KERN_WARNING "sio: %s irq level %d, type %d, %sactive: " + "remapping to level %d, type %d, active\n", + name, level0, type0, !active ? "in" : "", level, type); sio_write(0x01, 0x30); sio_write(level, 0x70); sio_write(type, 0x71); diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/entry.S linux/arch/ppc/kernel/entry.S --- v2.4.5/linux/arch/ppc/kernel/entry.S Mon May 21 17:04:46 2001 +++ linux/arch/ppc/kernel/entry.S Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.entry.S 1.12 05/21/01 11:49:59 paulus + * BK Id: SCCS/s.entry.S 1.17 06/19/01 22:40:51 paulus */ /* * PowerPC version @@ -283,6 +283,7 @@ */ mfmsr r0 /* Get current interrupt state */ rlwinm r0,r0,0,17,15 /* clear MSR_EE in r0 */ + SYNC /* Some chip revs have problems here... */ mtmsr r0 /* Update machine state */ lwz r0,_MSR(r1) @@ -310,25 +311,7 @@ beq restore .globl ret_from_except ret_from_except: - lwz r5,_MSR(r1) - andi. r5,r5,MSR_EE - beq 2f - lis r4,irq_stat@ha /* &softirq_active for cpu 0 */ - addi r4,r4,irq_stat@l -#ifdef CONFIG_SMP - /* get processor # */ - lwz r3,PROCESSOR(r2) - slwi r3,r3,LG_CACHE_LINE_SIZE - add r4,r4,r3 -#endif /* CONFIG_SMP */ - lwz r5,0(r4) /* softirq_active */ - lwz r4,4(r4) /* softirq_mask */ - and. r5,r5,r4 - beq+ 2f - bl do_softirq - .globl do_bottom_half_ret -do_bottom_half_ret: -2: lwz r3,_MSR(r1) /* Returning to user mode? */ + lwz r3,_MSR(r1) /* Returning to user mode? */ andi. r3,r3,MSR_PR beq+ do_signal_ret /* if so, check need_resched and signals */ lwz r3,NEED_RESCHED(r2) diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/feature.c linux/arch/ppc/kernel/feature.c --- v2.4.5/linux/arch/ppc/kernel/feature.c Fri May 25 12:41:46 2001 +++ linux/arch/ppc/kernel/feature.c Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.feature.c 1.10 05/17/01 18:14:21 cort + * BK Id: SCCS/s.feature.c 1.14 06/17/01 09:33:37 trini */ /* * arch/ppc/kernel/feature.c @@ -288,11 +288,11 @@ { "AAPL,PowerBook1998", FTR_CAN_SLEEP }, /* Wallstreet PowerBook */ { "PowerBook1,1", FTR_CAN_SLEEP }, /* 101 (Lombard) PowerBook */ { "PowerBook2,1", FTR_CAN_SLEEP }, /* iBook */ + { "PowerBook4,1", FTR_CAN_NAP|FTR_CAN_SLEEP }, /* iBook Dual USB */ { "PowerBook2,2", FTR_CAN_SLEEP /*| FTR_CAN_NAP*/ }, /* iBook FireWire */ { "PowerBook3,1", FTR_CAN_SLEEP|FTR_CAN_NAP| /* PowerBook 2000 (Pismo) */ FTR_HAS_FW_POWER }, { "PowerBook3,2", FTR_CAN_NAP|FTR_CAN_SLEEP }, /* PowerBook Titanium */ - { "PowerBook4,1", FTR_CAN_NAP|FTR_CAN_SLEEP }, /* New polycarbonate iBook */ { NULL, 0 } }; diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/hashtable.S linux/arch/ppc/kernel/hashtable.S --- v2.4.5/linux/arch/ppc/kernel/hashtable.S Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/hashtable.S Wed Dec 31 16:00:00 1969 @@ -1,724 +0,0 @@ -/* - * BK Id: SCCS/s.hashtable.S 1.11 05/17/01 18:14:21 cort - */ -/* - * arch/ppc/kernel/hashtable.S - * - * PowerPC version - * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) - * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP - * Copyright (C) 1996 Cort Dougan - * Adapted for Power Macintosh by Paul Mackerras. - * Low-level exception handlers and MMU support - * rewritten by Paul Mackerras. - * Copyright (C) 1996 Paul Mackerras. - * - * This file contains low-level assembler routines for managing - * the PowerPC MMU hash table. (PPC 8xx processors don't use a - * hash table, so this file is not used on them.) - * - * 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 "ppc_asm.h" -#include -#include -#include - -/* - * Load a PTE into the hash table, if possible. - * The address is in r3, and r4 contains access flags: - * _PAGE_USER (4) if a user-mode access, ored with - * _PAGE_RW (2) if a write. r20 contains DSISR or SRR1, - * so bit 1 (0x40000000) is set if the exception was due - * to no matching PTE being found in the hash table. - * SPRG3 contains the physical address of the current task's thread. - * - * Returns to the caller if the access is illegal or there is no - * mapping for the address. Otherwise it places an appropriate PTE - * in the hash table and returns from the exception. - * Uses r0, r2 - r6, ctr, lr. - * - * For speed, 4 of the instructions get patched once the size and - * physical address of the hash table are known. These definitions - * of Hash_base and Hash_bits below are just an example. - */ -Hash_base = 0x180000 -Hash_bits = 12 /* e.g. 256kB hash table */ -Hash_msk = (((1 << Hash_bits) - 1) * 64) - - .globl hash_page -hash_page: -#ifdef CONFIG_PPC64BRIDGE - mfmsr r0 - clrldi r0,r0,1 /* make sure it's in 32-bit mode */ - MTMSRD(r0) - isync -#endif -#ifdef CONFIG_SMP - SAVE_2GPRS(7,r21) - eieio - lis r2,hash_table_lock@h - ori r2,r2,hash_table_lock@l - tophys(r2,r2) - lis r6,0x0fff0000@h - mtctr r6 - mfspr r5,SPRG3 - lwz r0,PROCESSOR-THREAD(r5) - or r0,r0,r6 -10: lwarx r6,0,r2 - cmpi 0,r6,0 - bne- 12f - stwcx. r0,0,r2 - beq+ 11f - /* spin here a bit */ -12: mfctr r7 - li r8,1000 - mtctr r8 -13: - bdnz 13b - mtctr r7 - cmpw r6,r0 - bdnzf 2,10b - tw 31,31,31 -11: eieio - REST_2GPRS(7, r21) -#endif - /* Get PTE (linux-style) and check access */ - lis r0,KERNELBASE@h /* check if kernel address */ - cmplw 0,r3,r0 - mfspr r2,SPRG3 /* current task's THREAD (phys) */ - lwz r5,PGDIR(r2) /* virt page-table root */ - blt+ 112f /* assume user more likely */ - lis r5,swapper_pg_dir@ha /* if kernel address, use */ - addi r5,r5,swapper_pg_dir@l /* kernel page table */ -112: tophys(r5,r5) /* convert to phys addr */ - rlwimi r5,r3,12,20,29 /* insert top 10 bits of address */ - lwz r5,0(r5) /* get pmd entry */ - rlwinm. r5,r5,0,0,19 /* extract address of pte page */ -#ifdef CONFIG_SMP - beq- hash_page_out /* return if no mapping */ -#else - /* XXX it seems like the 601 will give a machine fault on the - rfi if its alignment is wrong (bottom 4 bits of address are - 8 or 0xc) and we have had a not-taken conditional branch - to the address following the rfi. */ - beqlr- -#endif - tophys(r2,r5) - rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */ - ori r4,r4,1 /* set _PAGE_PRESENT bit in access */ - rlwinm r5,r4,5,24,24 /* _PAGE_RW access -> _PAGE_DIRTY */ - rlwimi r5,r4,7,22,22 /* _PAGE_RW -> _PAGE_HWWRITE */ - ori r5,r5,0x100 /* set _PAGE_ACCESSED */ -retry: - lwz r6,0(r2) /* get linux-style pte */ - andc. r0,r4,r6 /* check access & ~permission */ -#ifdef CONFIG_SMP - bne- hash_page_out /* return if access not permitted */ -#else - bnelr- -#endif - andc. r0,r5,r6 /* any bits not yet set? */ - beq 2f - - /* Update the linux PTE atomically */ - lwarx r0,0,r2 /* refetch the pte and check */ - cmpw 0,r0,r6 /* that it hasn't been changed */ - bne- retry /* retry if it has */ - or r6,r6,r5 /* set accessed/dirty bits */ - stwcx. r6,0,r2 /* attempt to update PTE */ - bne- retry /* retry if someone got there first */ - - /* Convert linux-style PTE to low word of PPC-style PTE */ -2: rlwinm r4,r6,32-9,31,31 /* _PAGE_HWWRITE -> PP lsb */ - rlwimi r6,r6,32-1,31,31 /* _PAGE_USER -> PP (both bits now) */ - ori r4,r4,0xe04 /* clear out reserved bits */ - andc r6,r6,r4 /* PP=2 or 0, when _PAGE_HWWRITE */ - -#ifdef CONFIG_POWER4 - /* - * XXX hack hack hack - translate 32-bit "physical" addresses - * in the linux page tables to 42-bit real addresses in such - * a fashion that we can get at the I/O we need to access. - * -- paulus - */ - cmpwi 0,r6,0 - rlwinm r4,r6,16,16,30 - bge 57f - cmplwi 0,r4,0xfe00 - li r5,0x3fd - bne 56f - li r5,0x3ff -56: sldi r5,r5,32 - or r6,r6,r5 -57: -#endif - -#ifdef CONFIG_PPC64BRIDGE - /* Construct the high word of the PPC-style PTE */ - mfsrin r5,r3 /* get segment reg for segment */ - rlwinm r5,r5,0,5,31 - sldi r5,r5,12 - ori r5,r5,1 /* set V (valid) bit */ - rlwimi r5,r3,16,20,24 /* put in API (abbrev page index) */ - /* Get the address of the primary PTE group in the hash table */ - .globl hash_page_patch_A -hash_page_patch_A: - lis r4,Hash_base@h /* base address of hash table */ - rlwimi r4,r5,32-5,25-Hash_bits,24 /* (VSID & hash_mask) << 7 */ - rlwinm r0,r3,32-5,25-Hash_bits,24 /* (PI & hash_mask) << 7 */ - xor r4,r4,r0 /* make primary hash */ - li r2,8 /* PTEs/group */ - -#ifndef CONFIG_SMP - /* We don't do this for SMP - another cpu could have put in - the appropriate PTE since we took the exception. -- paulus. */ - /* See whether it was a PTE not found exception or a - protection violation. */ - andis. r0,r20,0x4000 - bne 10f /* no PTE: go look for an empty slot */ -#endif /* CONFIG_SMP */ - tlbie r3 /* invalidate TLB entry */ - - /* Search the primary PTEG for a PTE whose 1st dword matches r5 */ - mtctr r2 - addi r3,r4,-16 -1: ldu r0,16(r3) /* get next PTE */ - cmpd 0,r0,r5 - bdnzf 2,1b /* loop while ctr != 0 && !cr0.eq */ - beq+ found_slot - - /* Search the secondary PTEG for a matching PTE */ - ori r5,r5,0x2 /* set H (secondary hash) bit */ - .globl hash_page_patch_B -hash_page_patch_B: - xoris r3,r4,Hash_msk>>16 /* compute secondary hash */ - xori r3,r3,0xff80 - addi r3,r3,-16 - mtctr r2 -2: ldu r0,16(r3) - cmpd 0,r0,r5 - bdnzf 2,2b - beq+ found_slot - xori r5,r5,0x2 /* clear H bit again */ - - /* Search the primary PTEG for an empty slot */ -10: mtctr r2 - addi r3,r4,-16 /* search primary PTEG */ -1: ldu r0,16(r3) /* get next PTE */ - andi. r0,r0,1 - bdnzf 2,1b /* loop while ctr != 0 && !cr0.eq */ - beq+ found_empty - - /* Search the secondary PTEG for an empty slot */ - ori r5,r5,0x2 /* set H (secondary hash) bit */ - .globl hash_page_patch_C -hash_page_patch_C: - xoris r3,r4,Hash_msk>>16 /* compute secondary hash */ - xori r3,r3,0xff80 - addi r3,r3,-16 - mtctr r2 -2: ldu r0,16(r3) - andi. r0,r0,1 - bdnzf 2,2b - beq+ found_empty - - /* - * Choose an arbitrary slot in the primary PTEG to overwrite. - * Since both the primary and secondary PTEGs are full, and we - * have no information that the PTEs in the primary PTEG are - * more important or useful than those in the secondary PTEG, - * and we know there is a definite (although small) speed - * advantage to putting the PTE in the primary PTEG, we always - * put the PTE in the primary PTEG. - */ - xori r5,r5,0x2 /* clear H bit again */ - lis r3,next_slot@ha - tophys(r3,r3) - lwz r2,next_slot@l(r3) - addi r2,r2,16 - andi. r2,r2,0x70 -#ifdef CONFIG_POWER4 - /* - * Since we don't have BATs on POWER4, we rely on always having - * PTEs in the hash table to map the hash table and the code - * that manipulates it in virtual mode, namely flush_hash_page and - * flush_hash_segments. Otherwise we can get a DSI inside those - * routines which leads to a deadlock on the hash_table_lock on - * SMP machines. We avoid this by never overwriting the first - * PTE of each PTEG if it is already valid. - * -- paulus. - */ - bne 102f - li r2,0x10 -102: -#endif /* CONFIG_POWER4 */ - stw r2,next_slot@l(r3) - add r3,r4,r2 -11: - /* update counter of evicted pages */ - lis r2,htab_evicts@ha - tophys(r2,r2) - lwz r4,htab_evicts@l(r2) - addi r4,r4,1 - stw r4,htab_evicts@l(r2) - -#ifndef CONFIG_SMP - /* Store PTE in PTEG */ -found_empty: - std r5,0(r3) -found_slot: - std r6,8(r3) - -#else /* CONFIG_SMP */ -/* - * Between the tlbie above and updating the hash table entry below, - * another CPU could read the hash table entry and put it in its TLB. - * There are 3 cases: - * 1. using an empty slot - * 2. updating an earlier entry to change permissions (i.e. enable write) - * 3. taking over the PTE for an unrelated address - * - * In each case it doesn't really matter if the other CPUs have the old - * PTE in their TLB. So we don't need to bother with another tlbie here, - * which is convenient as we've overwritten the register that had the - * address. :-) The tlbie above is mainly to make sure that this CPU comes - * and gets the new PTE from the hash table. - * - * We do however have to make sure that the PTE is never in an invalid - * state with the V bit set. - */ -found_empty: -found_slot: - li r0,1 - andc r5,r5,r0 /* clear V (valid) bit in PTE */ - std r5,0(r3) - sync - tlbsync - sync - std r6,8(r3) /* put in correct RPN, WIMG, PP bits */ - sync - ori r5,r5,1 - std r5,0(r3) /* finally set V bit in PTE */ -#endif /* CONFIG_SMP */ - -#else /* CONFIG_PPC64BRIDGE */ - - /* Construct the high word of the PPC-style PTE */ - mfsrin r5,r3 /* get segment reg for segment */ - rlwinm r5,r5,7,1,24 /* put VSID in 0x7fffff80 bits */ - oris r5,r5,0x8000 /* set V (valid) bit */ - rlwimi r5,r3,10,26,31 /* put in API (abbrev page index) */ - /* Get the address of the primary PTE group in the hash table */ - .globl hash_page_patch_A -hash_page_patch_A: - lis r4,Hash_base@h /* base address of hash table */ - rlwimi r4,r5,32-1,26-Hash_bits,25 /* (VSID & hash_mask) << 6 */ - rlwinm r0,r3,32-6,26-Hash_bits,25 /* (PI & hash_mask) << 6 */ - xor r4,r4,r0 /* make primary hash */ - li r2,8 /* PTEs/group */ - -#ifndef CONFIG_SMP - /* We don't do this for SMP - another cpu could have put in - the appropriate PTE since we took the exception. -- paulus. */ - /* See whether it was a PTE not found exception or a - protection violation. */ - andis. r0,r20,0x4000 - bne 10f /* no PTE: go look for an empty slot */ -#endif /* CONFIG_SMP */ - tlbie r3 /* invalidate TLB entry */ - - /* Search the primary PTEG for a PTE whose 1st word matches r5 */ - mtctr r2 - addi r3,r4,-8 -1: lwzu r0,8(r3) /* get next PTE */ - cmp 0,r0,r5 - bdnzf 2,1b /* loop while ctr != 0 && !cr0.eq */ - beq+ found_slot - - /* Search the secondary PTEG for a matching PTE */ - ori r5,r5,0x40 /* set H (secondary hash) bit */ - .globl hash_page_patch_B -hash_page_patch_B: - xoris r3,r4,Hash_msk>>16 /* compute secondary hash */ - xori r3,r3,0xffc0 - addi r3,r3,-8 - mtctr r2 -2: lwzu r0,8(r3) - cmp 0,r0,r5 - bdnzf 2,2b - beq+ found_slot - xori r5,r5,0x40 /* clear H bit again */ - - /* Search the primary PTEG for an empty slot */ -10: mtctr r2 - addi r3,r4,-8 /* search primary PTEG */ -1: lwzu r0,8(r3) /* get next PTE */ - rlwinm. r0,r0,0,0,0 /* only want to check valid bit */ - bdnzf 2,1b /* loop while ctr != 0 && !cr0.eq */ - beq+ found_empty - - /* Search the secondary PTEG for an empty slot */ - ori r5,r5,0x40 /* set H (secondary hash) bit */ - .globl hash_page_patch_C -hash_page_patch_C: - xoris r3,r4,Hash_msk>>16 /* compute secondary hash */ - xori r3,r3,0xffc0 - addi r3,r3,-8 - mtctr r2 -2: - lwzu r0,8(r3) - rlwinm. r0,r0,0,0,0 /* only want to check valid bit */ - bdnzf 2,2b - beq+ found_empty - - /* - * Choose an arbitrary slot in the primary PTEG to overwrite. - * Since both the primary and secondary PTEGs are full, and we - * have no information that the PTEs in the primary PTEG are - * more important or useful than those in the secondary PTEG, - * and we know there is a definite (although small) speed - * advantage to putting the PTE in the primary PTEG, we always - * put the PTE in the primary PTEG. - */ - xori r5,r5,0x40 /* clear H bit again */ - lis r3,next_slot@ha - tophys(r3,r3) - lwz r2,next_slot@l(r3) - addi r2,r2,8 - andi. r2,r2,0x38 - stw r2,next_slot@l(r3) - add r3,r4,r2 -11: - /* update counter of evicted pages */ - lis r2,htab_evicts@ha - tophys(r2,r2) - lwz r4,htab_evicts@l(r2) - addi r4,r4,1 - stw r4,htab_evicts@l(r2) - -#ifndef CONFIG_SMP - /* Store PTE in PTEG */ -found_empty: - stw r5,0(r3) -found_slot: - stw r6,4(r3) - -#else /* CONFIG_SMP */ -/* - * Between the tlbie above and updating the hash table entry below, - * another CPU could read the hash table entry and put it in its TLB. - * There are 3 cases: - * 1. using an empty slot - * 2. updating an earlier entry to change permissions (i.e. enable write) - * 3. taking over the PTE for an unrelated address - * - * In each case it doesn't really matter if the other CPUs have the old - * PTE in their TLB. So we don't need to bother with another tlbie here, - * which is convenient as we've overwritten the register that had the - * address. :-) The tlbie above is mainly to make sure that this CPU comes - * and gets the new PTE from the hash table. - * - * We do however have to make sure that the PTE is never in an invalid - * state with the V bit set. - */ -found_empty: -found_slot: - rlwinm r5,r5,0,1,31 /* clear V (valid) bit in PTE */ - stw r5,0(r3) - sync - tlbsync - sync - stw r6,4(r3) /* put in correct RPN, WIMG, PP bits */ - sync - oris r5,r5,0x8000 - stw r5,0(r3) /* finally set V bit in PTE */ -#endif /* CONFIG_SMP */ -#endif /* CONFIG_PPC64BRIDGE */ - - sync /* make sure pte updates get to memory */ - -/* - * Update the hash table miss count. We only want misses here - * that _are_ valid addresses and have a pte otherwise we don't - * count it as a reload. do_page_fault() takes care of bad addrs - * and entries that need linux-style pte's created. - * - * safe to use r2 here since we're not using it as current yet - * update the htab misses count - * -- Cort - */ - lis r2,htab_reloads@ha - tophys(r2,r2) - lwz r3,htab_reloads@l(r2) - addi r3,r3,1 - stw r3,htab_reloads@l(r2) - -#ifdef CONFIG_SMP - lis r2,hash_table_lock@ha - tophys(r2,r2) - li r0,0 - stw r0,hash_table_lock@l(r2) - eieio -#endif - - /* Return from the exception */ - lwz r3,_CCR(r21) - lwz r4,_LINK(r21) - lwz r5,_CTR(r21) - mtcrf 0xff,r3 - mtlr r4 - mtctr r5 - lwz r0,GPR0(r21) - lwz r1,GPR1(r21) - lwz r2,GPR2(r21) - lwz r3,GPR3(r21) - lwz r4,GPR4(r21) - lwz r5,GPR5(r21) - lwz r6,GPR6(r21) - /* we haven't used xer */ - mtspr SRR1,r23 - mtspr SRR0,r22 - lwz r20,GPR20(r21) - lwz r22,GPR22(r21) - lwz r23,GPR23(r21) - lwz r21,GPR21(r21) - RFI - -#ifdef CONFIG_SMP -hash_page_out: - lis r2,hash_table_lock@ha - tophys(r2,r2) - li r0,0 - stw r0,hash_table_lock@l(r2) - eieio - blr - - .data - .globl hash_table_lock -hash_table_lock: - .long 0 -#endif /* CONFIG_SMP */ - - .data -next_slot: - .long 0 - - .text -/* - * Flush entries from the hash table with VSIDs in the range - * given. - */ -_GLOBAL(flush_hash_segments) - lis r5,Hash@ha - lwz r5,Hash@l(r5) /* base of hash table */ - cmpwi 0,r5,0 - bne+ 99f - tlbia - sync -#ifdef CONFIG_SMP - tlbsync - sync -#endif - blr -99: -#if defined(CONFIG_SMP) || defined(CONFIG_PPC64BRIDGE) - /* Note - we had better not do anything which could generate - a hash table miss while we have the hash table locked, - or we'll get a deadlock. -paulus */ - mfmsr r10 - SYNC - rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */ - mtmsr r0 - SYNC -#endif -#ifdef CONFIG_SMP - lis r9,hash_table_lock@h - ori r9,r9,hash_table_lock@l - lwz r8,PROCESSOR(r2) - oris r8,r8,8 -10: lwarx r6,0,r9 - cmpi 0,r6,0 - bne- 10b - stwcx. r8,0,r9 - bne- 10b - eieio -#endif -#ifndef CONFIG_PPC64BRIDGE - rlwinm r3,r3,7,1,24 /* put VSID lower limit in position */ - oris r3,r3,0x8000 /* set V bit */ - rlwinm r4,r4,7,1,24 /* put VSID upper limit in position */ - oris r4,r4,0x8000 - ori r4,r4,0x7f - lis r6,Hash_size@ha - lwz r6,Hash_size@l(r6) /* size in bytes */ - srwi r6,r6,3 /* # PTEs */ - mtctr r6 - addi r5,r5,-8 - li r0,0 -1: lwzu r6,8(r5) /* get next tag word */ - cmplw 0,r6,r3 - cmplw 1,r6,r4 - cror 0,0,5 /* set cr0.lt if out of range */ - blt 2f /* branch if out of range */ - stw r0,0(r5) /* invalidate entry */ -2: bdnz 1b /* continue with loop */ -#else /* CONFIG_PPC64BRIDGE */ - rldic r3,r3,12,20 /* put VSID lower limit in position */ - ori r3,r3,1 /* set V bit */ - rldic r4,r4,12,20 /* put VSID upper limit in position */ - ori r4,r4,0xfff /* set V bit, API etc. */ - lis r6,Hash_size@ha - lwz r6,Hash_size@l(r6) /* size in bytes */ - srwi r6,r6,4 /* # PTEs */ - mtctr r6 - addi r5,r5,-16 - li r0,0 -1: ldu r6,16(r5) /* get next tag word */ - cmpld 0,r6,r3 - cmpld 1,r6,r4 - cror 0,0,5 /* set cr0.lt if out of range */ - blt 2f /* branch if out of range */ - std r0,0(r5) /* invalidate entry */ -2: bdnz 1b /* continue with loop */ -#endif /* CONFIG_PPC64BRIDGE */ - - sync - tlbia - sync -#ifdef CONFIG_SMP - tlbsync - sync - lis r3,hash_table_lock@ha - stw r0,hash_table_lock@l(r3) -#endif -#if defined(CONFIG_SMP) || defined(CONFIG_PPC64BRIDGE) - mtmsr r10 - SYNC -#endif - blr - -/* - * Flush the entry for a particular page from the hash table. - * - * flush_hash_page(unsigned context, unsigned long va) - */ -_GLOBAL(flush_hash_page) - lis r6,Hash@ha - lwz r6,Hash@l(r6) /* hash table base */ - cmpwi 0,r6,0 /* hash table in use? */ - bne+ 99f - tlbie r4 /* in hw tlb too */ - sync -#ifdef CONFIG_SMP - tlbsync - sync -#endif - blr -99: -#if defined(CONFIG_SMP) || defined(CONFIG_PPC64BRIDGE) - /* Note - we had better not do anything which could generate - a hash table miss while we have the hash table locked, - or we'll get a deadlock. -paulus */ - mfmsr r10 - SYNC - rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */ - mtmsr r0 - SYNC -#endif -#ifdef CONFIG_SMP - lis r9,hash_table_lock@h - ori r9,r9,hash_table_lock@l - lwz r8,PROCESSOR(r2) - oris r8,r8,9 -10: lwarx r7,0,r9 - cmpi 0,r7,0 - bne- 11f - stwcx. r8,0,r9 - beq+ 12f -11: lwz r7,0(r9) - cmpi 0,r7,0 - beq 10b - b 11b -12: eieio -#endif -#ifndef CONFIG_PPC64BRIDGE - rlwinm r3,r3,11,1,20 /* put context into vsid */ - rlwimi r3,r4,11,21,24 /* put top 4 bits of va into vsid */ - oris r3,r3,0x8000 /* set V (valid) bit */ - rlwimi r3,r4,10,26,31 /* put in API (abbrev page index) */ - rlwinm r7,r4,32-6,10,25 /* get page index << 6 */ - rlwinm r5,r3,32-1,7,25 /* vsid << 6 */ - xor r7,r7,r5 /* primary hash << 6 */ - lis r5,Hash_mask@ha - lwz r5,Hash_mask@l(r5) /* hash mask */ - slwi r5,r5,6 /* << 6 */ - and r7,r7,r5 - add r6,r6,r7 /* address of primary PTEG */ - li r8,8 - mtctr r8 - addi r7,r6,-8 -1: lwzu r0,8(r7) /* get next PTE */ - cmpw 0,r0,r3 /* see if tag matches */ - bdnzf 2,1b /* while --ctr != 0 && !cr0.eq */ - beq 3f /* if we found it */ - ori r3,r3,0x40 /* set H (alt. hash) bit */ - xor r6,r6,r5 /* address of secondary PTEG */ - mtctr r8 - addi r7,r6,-8 -2: lwzu r0,8(r7) /* get next PTE */ - cmpw 0,r0,r3 /* see if tag matches */ - bdnzf 2,2b /* while --ctr != 0 && !cr0.eq */ - bne 4f /* if we didn't find it */ -3: li r0,0 - stw r0,0(r7) /* invalidate entry */ -#else /* CONFIG_PPC64BRIDGE */ - rldic r3,r3,16,16 /* put context into vsid (<< 12) */ - rlwimi r3,r4,16,16,24 /* top 4 bits of va and API */ - ori r3,r3,1 /* set V (valid) bit */ - rlwinm r7,r4,32-5,9,24 /* get page index << 7 */ - srdi r5,r3,5 /* vsid << 7 */ - rlwinm r5,r5,0,1,24 /* vsid << 7 (limited to 24 bits) */ - xor r7,r7,r5 /* primary hash << 7 */ - lis r5,Hash_mask@ha - lwz r5,Hash_mask@l(r5) /* hash mask */ - slwi r5,r5,7 /* << 7 */ - and r7,r7,r5 - add r6,r6,r7 /* address of primary PTEG */ - li r8,8 - mtctr r8 - addi r7,r6,-16 -1: ldu r0,16(r7) /* get next PTE */ - cmpd 0,r0,r3 /* see if tag matches */ - bdnzf 2,1b /* while --ctr != 0 && !cr0.eq */ - beq 3f /* if we found it */ - ori r3,r3,2 /* set H (alt. hash) bit */ - xor r6,r6,r5 /* address of secondary PTEG */ - mtctr r8 - addi r7,r6,-16 -2: ldu r0,16(r7) /* get next PTE */ - cmpd 0,r0,r3 /* see if tag matches */ - bdnzf 2,2b /* while --ctr != 0 && !cr0.eq */ - bne 4f /* if we didn't find it */ -3: li r0,0 - std r0,0(r7) /* invalidate entry */ -#endif /* CONFIG_PPC64BRIDGE */ -4: sync - tlbie r4 /* in hw tlb too */ - sync -#ifdef CONFIG_SMP - tlbsync - sync - li r0,0 - stw r0,0(r9) /* clear hash_table_lock */ -#endif -#if defined(CONFIG_SMP) || defined(CONFIG_PPC64BRIDGE) - mtmsr r10 - SYNC -#endif - blr diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S --- v2.4.5/linux/arch/ppc/kernel/head.S Thu May 24 15:03:05 2001 +++ linux/arch/ppc/kernel/head.S Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.head.S 1.21 05/23/01 00:38:42 cort + * BK Id: SCCS/s.head.S 1.23 06/28/01 15:50:16 paulus */ /* * PowerPC version @@ -25,11 +25,12 @@ * */ +#include #include "ppc_asm.h" #include #include -#include #include +#include #ifdef CONFIG_APUS #include @@ -177,7 +178,7 @@ mtspr SDR1,r4 slbia lis r5,0x2000 /* set pseudo-segment reg 12 */ - ori r5,r5,12 + ori r5,r5,0x0ccc mtsr 12,r5 #endif /* CONFIG_POWER4 */ @@ -312,9 +313,8 @@ mfspr r20,DSISR andis. r0,r20,0xa470 /* weird error? */ bne 1f /* if not, try to put a PTE */ - mfspr r3,DAR /* into the hash table */ - rlwinm r4,r23,32-13,30,30 /* MSR_PR -> _PAGE_USER */ - rlwimi r4,r20,32-23,29,29 /* DSISR_STORE -> _PAGE_RW */ + mfspr r4,DAR /* into the hash table */ + rlwinm r3,r20,32-15,21,21 /* DSISR_STORE -> _PAGE_RW */ bl hash_page 1: stw r20,_DSISR(r21) mr r5,r20 @@ -354,9 +354,8 @@ #endif /* CONFIG_PPC64BRIDGE */ andis. r0,r23,0x4000 /* no pte found? */ beq 1f /* if so, try to put a PTE */ - mr r3,r22 /* into the hash table */ - rlwinm r4,r23,32-13,30,30 /* MSR_PR -> _PAGE_USER */ - mr r20,r23 /* SRR1 has reason bits */ + li r3,0 /* into the hash table */ + mr r4,r22 /* SRR0 is fault address */ bl hash_page 1: addi r3,r1,STACK_FRAME_OVERHEAD mr r4,r22 @@ -505,10 +504,13 @@ lis r1,KERNELBASE@h /* check if kernel address */ cmplw 0,r3,r1 mfspr r2,SPRG3 + li r1,_PAGE_USER|_PAGE_PRESENT /* low addresses tested as user */ lwz r2,PGDIR(r2) blt+ 112f lis r2,swapper_pg_dir@ha /* if kernel address, use */ addi r2,r2,swapper_pg_dir@l /* kernel page table */ + mfspr r1,SRR1 /* and MSR_PR bit from SRR1 */ + rlwinm r1,r1,32-12,29,29 /* shift MSR_PR to _PAGE_USER posn */ 112: tophys(r2,r2) rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */ lwz r2,0(r2) /* get pmd entry */ @@ -516,21 +518,23 @@ beq- InstructionAddressInvalid /* return if no mapping */ tophys(r2,r2) rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */ - lwz r1,0(r2) /* get linux-style pte */ - /* setup access flags in r3 */ - mfmsr r3 - rlwinm r3,r3,32-13,30,30 /* MSR_PR -> _PAGE_USER */ - ori r3,r3,1 /* set _PAGE_PRESENT bit in access */ - andc. r3,r3,r1 /* check access & ~permission */ + lwz r3,0(r2) /* get linux-style pte */ + andc. r1,r1,r3 /* check access & ~permission */ bne- InstructionAddressInvalid /* return if access not permitted */ - ori r1,r1,0x100 /* set _PAGE_ACCESSED in pte */ - stw r1,0(r2) /* update PTE (accessed bit) */ + ori r3,r3,_PAGE_ACCESSED /* set _PAGE_ACCESSED in pte */ + /* + * NOTE! We are assuming this is not an SMP system, otherwise + * we would need to update the pte atomically with lwarx/stwcx. + */ + stw r3,0(r2) /* update PTE (accessed bit) */ /* Convert linux-style PTE to low word of PPC-style PTE */ - /* this computation could be done better -- Cort */ - rlwinm r3,r1,32-9,31,31 /* _PAGE_HWWRITE -> PP lsb */ - rlwimi r1,r1,32-1,31,31 /* _PAGE_USER -> PP (both bits now) */ - ori r3,r3,0xe04 /* clear out reserved bits */ - andc r1,r1,r3 /* PP=2 or 0, when _PAGE_HWWRITE */ + rlwinm r1,r3,32-10,31,31 /* _PAGE_RW -> PP lsb */ + rlwinm r2,r3,32-7,31,31 /* _PAGE_DIRTY -> PP lsb */ + and r1,r1,r2 /* writable if _RW and _DIRTY */ + rlwimi r3,r3,32-1,30,30 /* _PAGE_USER -> PP msb */ + rlwimi r3,r3,32-1,31,31 /* _PAGE_USER -> PP lsb */ + ori r1,r1,0xe14 /* clear out reserved bits and M */ + andc r1,r3,r1 /* PP = user? (rw&dirty? 2: 3): 0 */ mtspr RPA,r1 mfspr r3,IMISS tlbli r3 @@ -555,7 +559,6 @@ mfmsr r0 /* Restore "normal" registers */ xoris r0,r0,MSR_TGPR>>16 mtcrf 0x80,r3 /* Restore CR0 */ - SYNC /* Some chip revs have problems here... */ mtmsr r0 b InstructionAccess @@ -576,10 +579,13 @@ lis r1,KERNELBASE@h /* check if kernel address */ cmplw 0,r3,r1 mfspr r2,SPRG3 + li r1,_PAGE_USER|_PAGE_PRESENT /* low addresses tested as user */ lwz r2,PGDIR(r2) blt+ 112f lis r2,swapper_pg_dir@ha /* if kernel address, use */ addi r2,r2,swapper_pg_dir@l /* kernel page table */ + mfspr r1,SRR1 /* and MSR_PR bit from SRR1 */ + rlwinm r1,r1,32-12,29,29 /* shift MSR_PR to _PAGE_USER posn */ 112: tophys(r2,r2) rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */ lwz r2,0(r2) /* get pmd entry */ @@ -587,22 +593,23 @@ beq- DataAddressInvalid /* return if no mapping */ tophys(r2,r2) rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */ - lwz r1,0(r2) /* get linux-style pte */ - /* setup access flags in r3 */ - mfmsr r3 - rlwinm r3,r3,32-13,30,30 /* MSR_PR -> _PAGE_USER */ - ori r3,r3,1 /* set _PAGE_PRESENT bit in access */ - /* save r2 and use it as scratch for the andc. */ - andc. r3,r3,r1 /* check access & ~permission */ + lwz r3,0(r2) /* get linux-style pte */ + andc. r1,r1,r3 /* check access & ~permission */ bne- DataAddressInvalid /* return if access not permitted */ - ori r1,r1,0x100 /* set _PAGE_ACCESSED in pte */ - stw r1,0(r2) /* update PTE (accessed bit) */ + ori r3,r3,_PAGE_ACCESSED /* set _PAGE_ACCESSED in pte */ + /* + * NOTE! We are assuming this is not an SMP system, otherwise + * we would need to update the pte atomically with lwarx/stwcx. + */ + stw r3,0(r2) /* update PTE (accessed bit) */ /* Convert linux-style PTE to low word of PPC-style PTE */ - /* this computation could be done better -- Cort */ - rlwinm r3,r1,32-9,31,31 /* _PAGE_HWWRITE -> PP lsb */ - rlwimi r1,r1,32-1,31,31 /* _PAGE_USER -> PP (both bits now) */ - ori r3,r3,0xe04 /* clear out reserved bits */ - andc r1,r1,r3 /* PP=2 or 0, when _PAGE_HWWRITE */ + rlwinm r1,r3,32-10,31,31 /* _PAGE_RW -> PP lsb */ + rlwinm r2,r3,32-7,31,31 /* _PAGE_DIRTY -> PP lsb */ + and r1,r1,r2 /* writable if _RW and _DIRTY */ + rlwimi r3,r3,32-1,30,30 /* _PAGE_USER -> PP msb */ + rlwimi r3,r3,32-1,31,31 /* _PAGE_USER -> PP lsb */ + ori r1,r1,0xe14 /* clear out reserved bits and M */ + andc r1,r3,r1 /* PP = user? (rw&dirty? 2: 3): 0 */ mtspr RPA,r1 mfspr r3,DMISS tlbld r3 @@ -625,7 +632,6 @@ mfmsr r0 /* Restore "normal" registers */ xoris r0,r0,MSR_TGPR>>16 mtcrf 0x80,r3 /* Restore CR0 */ - SYNC /* Some chip revs have problems here... */ mtmsr r0 b DataAccess @@ -646,10 +652,13 @@ lis r1,KERNELBASE@h /* check if kernel address */ cmplw 0,r3,r1 mfspr r2,SPRG3 + li r1,_PAGE_RW|_PAGE_USER|_PAGE_PRESENT /* access flags */ lwz r2,PGDIR(r2) blt+ 112f lis r2,swapper_pg_dir@ha /* if kernel address, use */ addi r2,r2,swapper_pg_dir@l /* kernel page table */ + mfspr r1,SRR1 /* and MSR_PR bit from SRR1 */ + rlwinm r1,r1,32-12,29,29 /* shift MSR_PR to _PAGE_USER posn */ 112: tophys(r2,r2) rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */ lwz r2,0(r2) /* get pmd entry */ @@ -657,22 +666,19 @@ beq- DataAddressInvalid /* return if no mapping */ tophys(r2,r2) rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */ - lwz r1,0(r2) /* get linux-style pte */ - /* setup access flags in r3 */ - mfmsr r3 - rlwinm r3,r3,32-13,30,30 /* MSR_PR -> _PAGE_USER */ - ori r3,r3,0x5 /* _PAGE_PRESENT|_PAGE_RW */ - /* save r2 and use it as scratch for the andc. */ - andc. r3,r3,r1 /* check access & ~permission */ + lwz r3,0(r2) /* get linux-style pte */ + andc. r1,r1,r3 /* check access & ~permission */ bne- DataAddressInvalid /* return if access not permitted */ - ori r1,r1,0x384 /* set _PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_RW|_PAGE_HWWRITE in pte */ - stw r1,0(r2) /* update PTE (accessed bit) */ + ori r3,r3,_PAGE_ACCESSED|_PAGE_DIRTY + /* + * NOTE! We are assuming this is not an SMP system, otherwise + * we would need to update the pte atomically with lwarx/stwcx. + */ + stw r3,0(r2) /* update PTE (accessed/dirty bits) */ /* Convert linux-style PTE to low word of PPC-style PTE */ - /* this computation could be done better -- Cort */ - rlwinm r3,r1,32-9,31,31 /* _PAGE_HWWRITE -> PP lsb */ - rlwimi r1,r1,32-1,31,31 /* _PAGE_USER -> PP (both bits now) */ - ori r3,r3,0xe04 /* clear out reserved bits */ - andc r1,r1,r3 /* PP=2 or 0, when _PAGE_HWWRITE */ + rlwimi r3,r3,32-1,30,30 /* _PAGE_USER -> PP msb */ + li r1,0xe15 /* clear out reserved bits and M */ + andc r1,r3,r1 /* PP = user? 2: 0 */ mtspr RPA,r1 mfspr r3,DMISS tlbld r3 @@ -901,7 +907,6 @@ */ mfmsr r5 oris r5,r5,MSR_VEC@h - SYNC mtmsr r5 /* enable use of AltiVec now */ isync /* @@ -1028,6 +1033,7 @@ ori r5,r5,MSR_FP SYNC mtmsr r5 /* enable use of fpu now */ + SYNC isync cmpi 0,r3,0 beqlr- /* if no previous owner, done */ @@ -1384,7 +1390,7 @@ lis r3,0x2000 /* Ku = 1, VSID = 0 */ li r4,0 3: mtsrin r3,r4 - addi r3,r3,1 /* increment VSID */ + addi r3,r3,0x111 /* increment VSID */ addis r4,r4,0x1000 /* address of next segment */ bdnz 3b #ifndef CONFIG_POWER4 @@ -1490,7 +1496,8 @@ * Set up the segment registers for a new context. */ _GLOBAL(set_context) - rlwinm r3,r3,4,8,27 /* VSID = context << 4 */ + mulli r3,r3,897 /* multiply context by skew factor */ + rlwinm r3,r3,4,8,27 /* VSID = (context & 0xfffff) << 4 */ addis r3,r3,0x6000 /* Set Ks, Ku bits */ li r0,12 /* TASK_SIZE / SEGMENT_SIZE */ mtctr r0 @@ -1500,7 +1507,8 @@ slbie r4 #endif /* CONFIG_PPC64BRIDGE */ mtsrin r3,r4 - addi r3,r3,1 /* next VSID */ + addi r3,r3,0x111 /* next VSID */ + rlwinm r3,r3,0,8,3 /* clear out any overflow from VSID field */ addis r4,r4,0x1000 /* address of next segment */ bdnz 3b SYNC diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/head_8xx.S linux/arch/ppc/kernel/head_8xx.S --- v2.4.5/linux/arch/ppc/kernel/head_8xx.S Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/head_8xx.S Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.head_8xx.S 1.11 05/21/01 11:50:00 paulus + * BK Id: SCCS/s.head_8xx.S 1.14 06/28/01 15:50:16 paulus */ /* * arch/ppc/kernel/except_8xx.S @@ -500,6 +500,11 @@ #endif mtspr MD_TWC, r21 + /* Set PP0 to PP1 (== _PAGE_USER) & ~_PAGE_RW */ + rlwimi r20, r20, 32-1, 21, 21 + rlwinm r21, r20, 4, 21, 21 + andc r20, r20, r21 + /* Set four subpage valid bits (24, 25, 26, and 27). * Clear bit 28 (which should be in the PTE, but we do this anyway). */ @@ -602,7 +607,7 @@ /* Update 'changed', among others. */ - ori r20, r20, _PAGE_DIRTY|_PAGE_HWWRITE|_PAGE_ACCESSED + ori r20, r20, _PAGE_DIRTY|_PAGE_ACCESSED mfspr r21, MD_TWC /* Get pte address again */ stw r20, 0(r21) /* and update pte in table */ @@ -939,6 +944,12 @@ * ASID compare register with the new "context". */ _GLOBAL(set_context) + /* fetch the pgd from the context_mm array */ + lis r5, context_mm@ha + slwi r6, r3, 2 + add r5, r5, r6 + lwz r5, context_mm@l(r5) /* get the mm */ + lwz r4, MM_PGD(r5) /* get the pgd from the mm */ #ifdef CONFIG_8xx_CPU6 lis r6, cpu6_errata_word@h ori r6, r6, cpu6_errata_word@l diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c --- v2.4.5/linux/arch/ppc/kernel/irq.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/irq.c Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.irq.c 1.23 05/17/01 18:14:21 cort + * BK Id: SCCS/s.irq.c 1.28 06/28/01 16:15:56 paulus */ /* * arch/ppc/kernel/irq.c @@ -531,26 +531,25 @@ { int cpu = smp_processor_id(); int irq; - hardirq_enter( cpu ); + hardirq_enter(cpu); /* every arch is required to have a get_irq -- Cort */ - irq = ppc_md.get_irq( regs ); + irq = ppc_md.get_irq(regs); - if ( irq < 0 ) - { + if (irq >= 0) { + ppc_irq_dispatch_handler( regs, irq ); + } else if (irq != -2) { /* -2 means ignore, already handled */ - if (irq != -2) - { + if (ppc_spurious_interrupts < 10) printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n", irq, regs->nip); - /* That's not SMP safe ... but who cares ? */ - ppc_spurious_interrupts++; - } - goto out; + /* That's not SMP safe ... but who cares ? */ + ppc_spurious_interrupts++; } - ppc_irq_dispatch_handler( regs, irq ); -out: hardirq_exit( cpu ); + + if (softirq_pending(cpu)) + do_softirq(); return 1; /* lets ret_from_int know we can do checks */ } diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/m8xx_setup.c linux/arch/ppc/kernel/m8xx_setup.c --- v2.4.5/linux/arch/ppc/kernel/m8xx_setup.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/m8xx_setup.c Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.m8xx_setup.c 1.17 05/18/01 07:54:04 patch + * BK Id: SCCS/s.m8xx_setup.c 1.20 06/27/01 14:49:58 trini */ /* * linux/arch/ppc/kernel/setup.c @@ -124,12 +124,6 @@ extern unsigned long find_available_memory(void); extern void m8xx_cpm_reset(uint); -static void ide_interrupt_handler(void* dev_id); - -void __init adbdev_init(void) -{ -} - void __init m8xx_setup_arch(void) { @@ -359,6 +353,12 @@ /* * IDE stuff. */ +#ifdef CONFIG_BLK_DEV_MPC8xx_IDE +void ide_interrupt_handler (void *dev) +{ +} +#endif + void m8xx_ide_insw(ide_ioreg_t port, void *buf, int ns) { @@ -512,12 +512,7 @@ #endif /* CONFIG_BLK_DEV_MPC8xx_IDE */ } -#endif /* CONFIG_BLK_DEV_IDE || CONFIG_BLK_DEV_IDE_MODULE */ - - -/* -------------------------------------------------------------------- */ -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) #ifdef CONFIG_BLK_DEV_MPC8xx_IDE /* PCMCIA Timing */ @@ -577,13 +572,9 @@ if ((reg = pcmp->pcmc_por7 & mask) != 0) pcmp->pcmc_por7 = reg | timing; } - -void ide_interrupt_handler (void *dev) -{ -} - #endif /* CONFIG_BLK_DEV_MPC8xx_IDE */ #endif /* CONFIG_BLK_DEV_IDE || CONFIG_BLK_DEV_IDE_MODULE */ + /* -------------------------------------------------------------------- */ /* diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S --- v2.4.5/linux/arch/ppc/kernel/misc.S Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/misc.S Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.misc.S 1.16 05/17/01 18:14:21 cort + * BK Id: SCCS/s.misc.S 1.19 06/15/01 13:56:56 paulus */ /* * This file contains miscellaneous low-level functions. @@ -263,10 +263,13 @@ * This is a no-op on the 601. */ _GLOBAL(flush_instruction_cache) -#ifdef CONFIG_8xx +#if defined(CONFIG_8xx) isync lis r5, IDC_INVALL@h mtspr IC_CST, r5 +#elif defined(CONFIG_4xx) + lis r3, KERNELBASE@h + iccci 0,r3 #else mfspr r3,PVR rlwinm r3,r3,16,16,31 diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/mk_defs.c linux/arch/ppc/kernel/mk_defs.c --- v2.4.5/linux/arch/ppc/kernel/mk_defs.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/mk_defs.c Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.mk_defs.c 1.5 05/17/01 18:14:21 cort + * BK Id: SCCS/s.mk_defs.c 1.8 06/28/01 15:50:16 paulus */ /* * This program is used to generate definitions needed by @@ -117,5 +117,6 @@ DEFINE(RESULT, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, result)); DEFINE(TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap)); DEFINE(CLONE_VM, CLONE_VM); + DEFINE(MM_PGD, offsetof(struct mm_struct, pgd)); return 0; } diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c --- v2.4.5/linux/arch/ppc/kernel/pci.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/pci.c Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.pci.c 1.21 05/21/01 01:31:30 cort + * BK Id: SCCS/s.pci.c 1.26 06/28/01 08:02:41 trini */ /* * Common pmac/prep/chrp pci routines. -- Cort @@ -40,11 +40,10 @@ unsigned long isa_mem_base = 0; unsigned long pci_dram_offset = 0; -static u8* pci_to_OF_bus_map; - static void pcibios_fixup_resources(struct pci_dev* dev); #ifdef CONFIG_ALL_PPC static void pcibios_fixup_cardbus(struct pci_dev* dev); +static u8* pci_to_OF_bus_map; #endif /* By default, we don't re-assign bus numbers. We do this only on @@ -73,8 +72,13 @@ u32 new, check; int reg; struct pci_controller* hose = dev->sysdata; + unsigned long io_offset; new = res->start; + if (hose && res->flags & IORESOURCE_IO) { + io_offset = (unsigned long)hose->io_base_virt - isa_io_base; + new -= io_offset; + } if (hose && res->flags & IORESOURCE_MEM) new -= hose->pci_mem_offset; new |= (res->flags & PCI_REGION_FLAG_MASK); @@ -98,40 +102,43 @@ } static void -pcibios_fixup_resources(struct pci_dev* dev) +pcibios_fixup_resources(struct pci_dev *dev) { - struct pci_controller* hose = - (struct pci_controller *)dev->sysdata; + struct pci_controller* hose = (struct pci_controller *)dev->sysdata; int i; + unsigned long offset; + if (!hose) { - printk("No hose for PCI dev %x.%x !\n", dev->bus->number, dev->devfn >> 3); + printk(KERN_ERR "No hose for PCI dev %s!\n", dev->slot_name); return; } for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { struct resource *res = dev->resource + i; - if (!res->start) + if (!res->start || !res->flags) continue; - if ((res->flags & IORESOURCE_MEM) && hose->pci_mem_offset) { - res->start += hose->pci_mem_offset; - res->end += hose->pci_mem_offset; + if (res->end == 0xffffffff) { + DBG("PCI:%s Resource %d [%08lx-%08lx] is unassigned\n", + dev->slot_name, i, res->start, res->end); + res->end -= res->start; + res->start = 0; + continue; + } + offset = 0; + if (res->flags & IORESOURCE_MEM) { + offset = hose->pci_mem_offset; + } else if (res->flags & IORESOURCE_IO) { + offset = (unsigned long) hose->io_base_virt + - isa_io_base; + } + if (offset != 0) { + res->start += offset; + res->end += offset; #ifdef DEBUG - printk("Fixup mem res, dev: %x.%x, res_start: %lx->%lx\n", - dev->bus->number, dev->devfn>>3, res->start-hose->pci_mem_offset, - res->start); + printk("Fixup res %d (%lx) of dev %s: %lx -> %lx\n", + i, res->flags, dev->slot_name, + res->start - offset, res->start); #endif } - - if ((res->flags & IORESOURCE_IO) - && (unsigned long) hose->io_base_virt != isa_io_base) { - unsigned long offs; - - offs = (unsigned long)hose->io_base_virt - isa_io_base; - res->start += offs; - res->end += offs; - printk("Fixup IO res, dev: %x.%x, res_start: %lx->%lx\n", - dev->bus->number, dev->devfn>>3, - res->start - offs, res->start); - } } } @@ -228,22 +235,27 @@ { struct list_head *ln; struct pci_bus *bus; - struct pci_dev *dev; - int idx; - struct resource *r, *pr; + int i; + struct resource *res, *pr; /* Depth-First Search on bus tree */ - for (ln=bus_list->next; ln != bus_list; ln=ln->next) { + for (ln = bus_list->next; ln != bus_list; ln=ln->next) { bus = pci_bus_b(ln); - if ((dev = bus->self)) { - for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) { - r = &dev->resource[idx]; - if (!r->start) - continue; - pr = pci_find_parent_resource(dev, r); - if (!pr || request_resource(pr, r) < 0) - printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, dev->slot_name); - } + for (i = 0; i < 4; ++i) { + if ((res = bus->resource[i]) == NULL || !res->flags) + continue; + if (bus->parent == NULL) + pr = (res->flags & IORESOURCE_IO)? + &ioport_resource: &iomem_resource; + else + pr = pci_find_parent_resource(bus->self, res); + + if (pr && request_resource(pr, res) == 0) + continue; + printk(KERN_ERR "PCI: Cannot allocate resource region " + "%d of PCI bridge %d\n", i, bus->number); + DBG("PCI: resource is %lx..%lx (%lx), parent %p\n", + res->start, res->end, res->flags, pr); } pcibios_allocate_bus_resources(&bus->children); } @@ -253,13 +265,15 @@ { struct resource *pr, *r = &dev->resource[idx]; - DBG("PCI:%x:%x:%x: Resource %08lx-%08lx (f=%lx)\n", - dev->bus->number, dev->devfn >> 3, dev->devfn & 7, - r->start, r->end, r->flags); + DBG("PCI:%s: Resource %d: %08lx-%08lx (f=%lx)\n", + dev->slot_name, idx, r->start, r->end, r->flags); pr = pci_find_parent_resource(dev, r); if (!pr || request_resource(pr, r) < 0) { printk(KERN_ERR "PCI: Cannot allocate resource region %d" " of device %s\n", idx, dev->slot_name); + if (pr) + DBG("PCI: parent is %p: %08lx-%08lx (f=%lx)\n", + pr, pr->start, pr->end, pr->flags); /* We'll assign a new address later */ r->end -= r->start; r->start = 0; @@ -276,20 +290,12 @@ pci_for_each_dev(dev) { pci_read_config_word(dev, PCI_COMMAND, &command); - for(idx = 0; idx < 6; idx++) { + for (idx = 0; idx < 6; idx++) { r = &dev->resource[idx]; if (r->parent) /* Already allocated */ continue; if (!r->start) /* Not assigned at all */ continue; - if (r->end == 0xffffffff) { - /* LongTrail OF quirk: unassigned */ - DBG("PCI: Resource %08lx-%08lx was unassigned\n", r->start, r->end); - r->end -= r->start; - r->start = 0; - continue; - } - if (r->flags & IORESOURCE_IO) disabled = !(command & PCI_COMMAND_IO); else @@ -306,7 +312,8 @@ DBG("PCI: Switching off ROM of %s\n", dev->slot_name); r->flags &= ~PCI_ROM_ADDRESS_ENABLE; pci_read_config_dword(dev, dev->rom_base_reg, ®); - pci_write_config_dword(dev, dev->rom_base_reg, reg & ~PCI_ROM_ADDRESS_ENABLE); + pci_write_config_dword(dev, dev->rom_base_reg, + reg & ~PCI_ROM_ADDRESS_ENABLE); } } } @@ -325,21 +332,14 @@ if (!class || class == PCI_CLASS_BRIDGE_HOST) continue; - for(idx=0; idx<6; idx++) { + for (idx = 0; idx < 6; idx++) { r = &dev->resource[idx]; -#if 0 /* we don't need this PC-ism */ - /* - * Don't touch IDE controllers and I/O ports of video cards! - */ - if ((class == PCI_CLASS_STORAGE_IDE && idx < 4) || - (class == PCI_CLASS_DISPLAY_VGA && (r->flags & IORESOURCE_IO))) - continue; -#endif /* - * We shall assign a new address to this resource, either because - * the BIOS (sic) forgot to do so or because we have decided the old - * address was unusable for some reason. + * We shall assign a new address to this resource, + * either because the BIOS (sic) forgot to do so + * or because we have decided the old address was + * unusable for some reason. */ if (!r->start && r->end && (!ppc_md.pcibios_enable_device_hook || @@ -347,13 +347,13 @@ pci_assign_resource(dev, idx); } - if (0) { /* don't assign ROMs */ - r = &dev->resource[PCI_ROM_RESOURCE]; - r->end -= r->start; - r->start = 0; - if (r->end) - pci_assign_resource(dev, PCI_ROM_RESOURCE); - } +#if 0 /* don't assign ROMs */ + r = &dev->resource[PCI_ROM_RESOURCE]; + r->end -= r->start; + r->start = 0; + if (r->end) + pci_assign_resource(dev, PCI_ROM_RESOURCE); +#endif } } @@ -496,10 +496,15 @@ && ((reg[0] >> 16) & 0xff) == bus) return node; - /* For PCI<->PCI bridges or CardBus bridges, we go down */ + /* For PCI<->PCI bridges or CardBus bridges, we go down + * Note: some OFs create a parent node "multifunc-device" as + * a fake root for all functions of a multi-function device, + * we go down them as well. + */ class_code = (unsigned int *) get_property(node, "class-code", 0); - if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI && - (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) + if ((!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI && + (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) && + strcmp(node->name, "multifunc-device")) continue; sub_node = scan_OF_childs_for_device(node->child, bus, dev_fn); if (sub_node) @@ -682,9 +687,9 @@ { struct pci_controller *hose; struct pci_bus *bus; - int next_busno, i; + int next_busno; - printk("PCI: Probing PCI hardware\n"); + printk(KERN_INFO "PCI: Probing PCI hardware\n"); /* Scan all of the recorded PCI controllers. */ for (next_busno = 0, hose = hose_head; hose; hose = hose->next) { @@ -692,18 +697,6 @@ hose->first_busno = next_busno; hose->last_busno = 0xff; bus = pci_scan_bus(hose->first_busno, hose->ops, hose); - if (hose->io_resource.flags) { - unsigned long offs; - - offs = (unsigned long)hose->io_base_virt - isa_io_base; - hose->io_resource.start += offs; - hose->io_resource.end += offs; - bus->resource[0] = &hose->io_resource; - } - for (i = 0; i < 3; ++i) - if (hose->mem_resources[i].flags) - bus->resource[i+1] = &hose->mem_resources[i]; - hose->bus = bus; hose->last_busno = bus->subordinate; if (pci_assign_all_busses || next_busno <= hose->last_busno) next_busno = hose->last_busno+1; @@ -716,7 +709,7 @@ */ if (pci_assign_all_busses && have_of) pcibios_make_OF_bus_map(); - + /* Call machine dependant fixup */ if (ppc_md.pcibios_fixup) ppc_md.pcibios_fixup(); @@ -727,27 +720,7 @@ pcibios_allocate_resources(1); pcibios_assign_resources(); -#ifdef CONFIG_BLK_DEV_IDE - /* OF fails to initialize IDE controllers on macs - * (and maybe other machines) - * - * Ideally, this should be moved to the IDE layer, but we need - * to check specifically with Andre Hedrick how to do it cleanly - * since the common IDE code seem to care about the fact that the - * BIOS may have disabled a controller. - * - * -- BenH - */ - if (_machine == _MACH_Pmac) { - struct pci_dev *dev; - pci_for_each_dev(dev) - { - if ((dev->class >> 16) == PCI_BASE_CLASS_STORAGE) - pci_enable_device(dev); - } - } -#endif /* CONFIG_BLK_DEV_IDE */ - + /* Call machine dependent post-init code */ if (ppc_md.pcibios_after_init) ppc_md.pcibios_after_init(); } @@ -775,21 +748,62 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) { - struct pci_controller *hose; + struct pci_controller *hose = (struct pci_controller *) bus->sysdata; + unsigned long io_offset; + struct resource *res; + int i; + + io_offset = (unsigned long)hose->io_base_virt - isa_io_base; + if (bus->parent == NULL) { + /* This is a host bridge - fill in its resources */ + hose->bus = bus; - pci_read_bridge_bases(bus); + bus->resource[0] = res = &hose->io_resource; + if (!res->flags) { + if (io_offset) + printk(KERN_ERR "I/O resource not set for host" + " bridge %d\n", hose->index); + res->start = 0; + res->end = IO_SPACE_LIMIT; + res->flags = IORESOURCE_IO; + } + res->start += io_offset; + res->end += io_offset; - hose = pci_bus_to_hose(bus->number); + for (i = 0; i < 3; ++i) { + res = &hose->mem_resources[i]; + if (!res->flags) { + if (i > 0) + continue; + printk(KERN_ERR "Memory resource not set for " + "host bridge %d\n", hose->index); + res->start = hose->pci_mem_offset; + res->end = ~0U; + res->flags = IORESOURCE_MEM; + } + bus->resource[i+1] = res; + } + } else { + /* This is a subordinate bridge */ + pci_read_bridge_bases(bus); - /* Apply pci_mem_offset to bridge mem resource */ - if (hose->first_busno != bus->number) - if (bus->resource[1]->start && (bus->resource[1]->end != -1)) - { - bus->resource[1]->start += hose->pci_mem_offset; - bus->resource[1]->end += hose->pci_mem_offset; + for (i = 0; i < 4; ++i) { + if ((res = bus->resource[i]) == NULL) + continue; + if (!res->flags) + continue; + if (io_offset && (res->flags & IORESOURCE_IO)) { + res->start += io_offset; + res->end += io_offset; + } else if (hose->pci_mem_offset + && (res->flags & IORESOURCE_MEM)) { + res->start += hose->pci_mem_offset; + res->end += hose->pci_mem_offset; + } } + } - if ( ppc_md.pcibios_fixup_bus ) + if (ppc_md.pcibios_fixup_bus) ppc_md.pcibios_fixup_bus(bus); } @@ -881,26 +895,17 @@ return hose->pci_mem_offset; } -#ifdef CONFIG_POWER4 -extern unsigned long pci_address_offset(int, unsigned int); -#endif /* CONFIG_POWER4 */ - unsigned long pci_resource_to_bus(struct pci_dev *pdev, struct resource *res) { /* Hack alert again ! See comments in chrp_pci.c */ -#ifdef CONFIG_POWER4 - unsigned long offset = pci_address_offset(pdev->bus->number, res->flags); - return res->start - offset; -#else /* CONFIG_POWER4 */ struct pci_controller* hose = (struct pci_controller *)pdev->sysdata; if (hose && res->flags & IORESOURCE_MEM) return res->start - hose->pci_mem_offset; /* We may want to do something with IOs here... */ return res->start; -#endif } /* @@ -1072,27 +1077,19 @@ unsigned long pci_phys_to_bus(unsigned long pa, int busnr) { -#ifdef CONFIG_POWER4 - return pa - pci_address_offset(busnr, IORESOURCE_MEM); -#else /* CONFIG_POWER4 */ struct pci_controller* hose = pci_bus_to_hose(busnr); if (!hose) return pa; return pa - hose->pci_mem_offset; -#endif } unsigned long pci_bus_to_phys(unsigned int ba, int busnr) { -#ifdef CONFIG_POWER4 - return ba + pci_address_offset(dev->bus->number, IORESOURCE_MEM); -#else /* CONFIG_POWER4 */ struct pci_controller* hose = pci_bus_to_hose(busnr); if (!hose) return ba; return ba + hose->pci_mem_offset; -#endif } /* Provide information on locations of various I/O regions in physical diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/pmac_pci.c linux/arch/ppc/kernel/pmac_pci.c --- v2.4.5/linux/arch/ppc/kernel/pmac_pci.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/pmac_pci.c Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.pmac_pci.c 1.14 05/17/01 18:14:21 cort + * BK Id: SCCS/s.pmac_pci.c 1.18 07/01/01 12:23:31 trini */ /* * Support for PCI bridges found on Power Macintoshes. @@ -42,8 +42,6 @@ /* * Magic constants for enabling cache coherency in the bandit/PSX bridge. */ -#define APPLE_VENDID 0x106b -#define BANDIT_DEVID 1 #define BANDIT_DEVID_2 8 #define BANDIT_REVID 3 @@ -97,12 +95,17 @@ } /* - * Apple MacRISC (UniNorth, Bandit) PCI controllers. + * Apple MacRISC (UniNorth, Bandit, Chaos) PCI controllers. * * The "Bandit" version is present in all early PCI PowerMacs, * and up to the first ones using Grackle. Some machines may * have 2 bandit controllers (2 PCI busses). * + * "Chaos" is used in some "Bandit"-type machines as a bridge + * for the separate display bus. It is accessed the same + * way as bandit, but cannot be probed for devices. It therefore + * has its own config access functions. + * * The "UniNorth" version is present in all Core99 machines * (iBook, G4, new IMacs, and all the recent Apple machines). * It contains 3 controllers in one ASIC. @@ -124,10 +127,6 @@ { unsigned int caddr; -#ifdef DEBUG -// printk("macrisc_config_access(hose: 0x%08lx, bus: 0x%x, devfb: 0x%x, offset: 0x%x)\n", -// hose, bus, dev_fn, offset); -#endif if (bus == hose->first_busno) { if (dev_fn < (11 << 3)) return 0; @@ -189,55 +188,50 @@ macrisc_write_config_dword }; - /* - * Apple "Chaos" PCI controller. - * - * This controller is present on some first generation "PowerSurge" - * machines (8500, 8600, ...). It's a very weird beast and will die - * in flames if we try to probe the config space. - * The long-term solution is to provide a config space "emulation" - * based on what we find in OF device tree + * Verifiy that a specific (bus, dev_fn) exists on chaos */ - -static int chaos_config_read_byte(struct pci_dev *dev, int offset, u8 *val) -{ - return PCIBIOS_DEVICE_NOT_FOUND; -} - -static int chaos_config_read_word(struct pci_dev *dev, int offset, u16 *val) +static int __pmac +chaos_validate_dev(struct pci_dev *dev, int offset) { - return PCIBIOS_DEVICE_NOT_FOUND; -} - -static int chaos_config_read_dword(struct pci_dev *dev, int offset, u32 *val) -{ - return PCIBIOS_DEVICE_NOT_FOUND; -} - -static int chaos_config_write_byte(struct pci_dev *dev, int offset, u8 val) -{ - return PCIBIOS_DEVICE_NOT_FOUND; -} - -static int chaos_config_write_word(struct pci_dev *dev, int offset, u16 val) -{ - return PCIBIOS_DEVICE_NOT_FOUND; + if(pci_device_to_OF_node(dev) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + if((dev->vendor == 0x106b) && (dev->device == 3) && (offset >= 0x10) && + (offset != 0x14) && (offset != 0x18) && (offset <= 0x24)) { + return PCIBIOS_BAD_REGISTER_NUMBER; + } + return PCIBIOS_SUCCESSFUL; } -static int chaos_config_write_dword(struct pci_dev *dev, int offset, u32 val) -{ - return PCIBIOS_DEVICE_NOT_FOUND; -} +#define CHAOS_PCI_OP(rw, size, type) \ +static int __pmac \ +chaos_##rw##_config_##size(struct pci_dev *dev, int off, type val) \ +{ \ + int result = chaos_validate_dev(dev, off); \ + if(result == PCIBIOS_BAD_REGISTER_NUMBER) { \ + cfg_##rw##_bad(val, size) \ + return PCIBIOS_BAD_REGISTER_NUMBER; \ + } \ + if(result == PCIBIOS_SUCCESSFUL) \ + return macrisc_##rw##_config_##size(dev, off, val); \ + return result; \ +} + +CHAOS_PCI_OP(read, byte, u8 *) +CHAOS_PCI_OP(read, word, u16 *) +CHAOS_PCI_OP(read, dword, u32 *) +CHAOS_PCI_OP(write, byte, u8) +CHAOS_PCI_OP(write, word, u16) +CHAOS_PCI_OP(write, dword, u32) static struct pci_ops chaos_pci_ops = { - chaos_config_read_byte, - chaos_config_read_word, - chaos_config_read_dword, - chaos_config_write_byte, - chaos_config_write_word, - chaos_config_write_dword + chaos_read_config_byte, + chaos_read_config_word, + chaos_read_config_dword, + chaos_write_config_byte, + chaos_write_config_word, + chaos_write_config_dword }; @@ -245,7 +239,8 @@ * For a bandit bridge, turn on cache coherency if necessary. * N.B. we could clean this up using the hose ops directly. */ -static void __init init_bandit(struct pci_controller *bp) +static void __init +init_bandit(struct pci_controller *bp) { unsigned int vendev, magic; int rev; @@ -254,7 +249,8 @@ out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_VENDOR_ID); udelay(2); vendev = in_le32((volatile unsigned int *)bp->cfg_data); - if (vendev == (BANDIT_DEVID << 16) + APPLE_VENDID) { + if (vendev == (PCI_VENDOR_ID_APPLE_BANDIT << 16) + + PCI_VENDOR_ID_APPLE) { /* read the revision id */ out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_REVISION_ID); @@ -264,7 +260,7 @@ printk(KERN_WARNING "Unknown revision %d for bandit at %08lx\n", rev, bp->io_base_phys); - } else if (vendev != (BANDIT_DEVID_2 << 16) + APPLE_VENDID) { + } else if (vendev != (BANDIT_DEVID_2 << 16) + PCI_VENDOR_ID_APPLE) { printk(KERN_WARNING "bandit isn't? (%x)\n", vendev); return; } @@ -426,7 +422,8 @@ * "pci" (a MPC106) and no bandit or chaos bridges, and contrariwise, * if we have one or more bandit or chaos bridges, we don't have a MPC106. */ -static void __init add_bridges(struct device_node *dev) +static void __init +add_bridges(struct device_node *dev) { int len; struct pci_controller *hose; @@ -490,17 +487,11 @@ } } -static void +static void __init pcibios_fixup_OF_interrupts(void) { struct pci_dev* dev; - /* - * FIXME: This is broken: We should not assign IRQ's to IRQless - * devices (look at PCI_INTERRUPT_PIN) and we also should - * honor the existence of multi-function devices where - * different functions have different interrupt pins. [mj] - */ pci_for_each_dev(dev) { /* @@ -533,7 +524,7 @@ pcibios_fixup_OF_interrupts(); } -int +int __pmac pmac_pci_enable_device_hook(struct pci_dev *dev, int initial) { struct device_node* node; @@ -563,10 +554,29 @@ /* We power down some devices after they have been probed. They'll * be powered back on later on */ -void +void __init pmac_pcibios_after_init(void) { struct device_node* nd; + +#ifdef CONFIG_BLK_DEV_IDE + struct pci_dev *dev; + + /* OF fails to initialize IDE controllers on macs + * (and maybe other machines) + * + * Ideally, this should be moved to the IDE layer, but we need + * to check specifically with Andre Hedrick how to do it cleanly + * since the common IDE code seem to care about the fact that the + * BIOS may have disabled a controller. + * + * -- BenH + */ + pci_for_each_dev(dev) { + if ((dev->class >> 16) == PCI_BASE_CLASS_STORAGE) + pci_enable_device(dev); + } +#endif /* CONFIG_BLK_DEV_IDE */ nd = find_devices("firewire"); while (nd) { diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/ppc4xx_pic.h linux/arch/ppc/kernel/ppc4xx_pic.h --- v2.4.5/linux/arch/ppc/kernel/ppc4xx_pic.h Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/ppc4xx_pic.h Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.ppc4xx_pic.h 1.5 05/17/01 18:14:21 cort + * BK Id: SCCS/s.ppc4xx_pic.h 1.8 06/15/01 13:56:56 paulus */ /* * @@ -14,12 +14,8 @@ #ifndef __PPC4XX_PIC_H__ #define __PPC4XX_PIC_H__ -#include - - -#ifdef __cplusplus -extern "C" { -#endif +#include +#include "local_irq.h" /* External Global Variables */ @@ -30,10 +26,5 @@ extern void ppc4xx_pic_init(void); extern int ppc4xx_pic_get_irq(struct pt_regs *regs); - - -#ifdef __cplusplus -} -#endif #endif /* __PPC4XX_PIC_H__ */ diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/ppc_htab.c linux/arch/ppc/kernel/ppc_htab.c --- v2.4.5/linux/arch/ppc/kernel/ppc_htab.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/ppc_htab.c Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.ppc_htab.c 1.8 05/17/01 18:14:21 cort + * BK Id: SCCS/s.ppc_htab.c 1.11 06/28/01 15:50:16 paulus */ /* * PowerPC hash table management proc entry. Will show information @@ -41,9 +41,12 @@ extern unsigned long Hash_size, Hash_mask; extern unsigned long _SDR1; extern unsigned long htab_reloads; +extern unsigned long htab_preloads; extern unsigned long htab_evicts; extern unsigned long pte_misses; extern unsigned long pte_errors; +extern unsigned int primary_pteg_full; +extern unsigned int htab_hash_searches; /* these will go into processor.h when I'm done debugging -- Cort */ #define MMCR0 952 @@ -110,7 +113,7 @@ { unsigned long mmcr0 = 0, pmc1 = 0, pmc2 = 0; int n = 0, valid; - unsigned int kptes = 0, overflow = 0, uptes = 0, zombie_ptes = 0; + unsigned int kptes = 0, uptes = 0, zombie_ptes = 0; PTE *ptr; struct task_struct *p; char buffer[512]; @@ -150,41 +153,34 @@ n += sprintf( buffer + n, "No Hash Table used\n"); goto return_string; } - - /* - * compute user/kernel pte's table this info can be - * misleading since there can be valid (v bit set) entries - * in the table but their vsid is used by no process (mm->context) - * due to the way tlb invalidation is handled on the ppc - * -- Cort - */ + +#if !defined(CONFIG_8xx) && !defined(CONFIG_4xx) for ( ptr = Hash ; ptr < Hash_end ; ptr++) { - if (ptr->v) - { - /* make sure someone is using this context/vsid */ - valid = 0; - for_each_task(p) - { - if (p->mm && (ptr->vsid >> 4) == p->mm->context) - { - valid = 1; - break; - } - } - if ( !valid ) - { - zombie_ptes++; - continue; - } - /* user not allowed read or write */ - if (ptr->pp == PP_RWXX) - kptes++; - else + unsigned int ctx, mctx, vsid; + + if (!ptr->v) + continue; + /* make sure someone is using this context/vsid */ + /* first undo the esid skew */ + vsid = ptr->vsid; + mctx = ((vsid - (vsid & 0xf) * 0x111) >> 4) & 0xfffff; + if (mctx == 0) { + kptes++; + continue; + } + /* now undo the context skew; 801921 * 897 == 1 mod 2^20 */ + ctx = (mctx * 801921) & 0xfffff; + valid = 0; + for_each_task(p) { + if (p->mm != NULL && ctx == p->mm->context) { + valid = 1; uptes++; - if (ptr->h == 1) - overflow++; + break; + } } + if (!valid) + zombie_ptes++; } n += sprintf( buffer + n, @@ -195,29 +191,32 @@ "Entries\t\t: %lu\n" "User ptes\t: %u\n" "Kernel ptes\t: %u\n" - "Overflows\t: %u\n" "Zombies\t\t: %u\n" - "Percent full\t: %%%lu\n", + "Percent full\t: %lu%%\n", (unsigned long)(Hash_size>>10), (Hash_size/(sizeof(PTE)*8)), (unsigned long)Hash, Hash_size/sizeof(PTE), uptes, kptes, - overflow, zombie_ptes, ((kptes+uptes)*100) / (Hash_size/sizeof(PTE)) ); n += sprintf( buffer + n, - "Reloads\t\t: %08lx\n" - "Evicts\t\t: %08lx\n", - htab_reloads, htab_evicts); + "Reloads\t\t: %lu\n" + "Preloads\t: %lu\n" + "Searches\t: %u\n" + "Overflows\t: %u\n" + "Evicts\t\t: %lu\n", + htab_reloads, htab_preloads, htab_hash_searches, + primary_pteg_full, htab_evicts); +#endif /* !8xx && !4xx */ return_string: n += sprintf( buffer + n, - "Non-error misses: %08lx\n" - "Error misses\t: %08lx\n", + "Non-error misses: %lu\n" + "Error misses\t: %lu\n", pte_misses, pte_errors); if (*ppos >= strlen(buffer)) return 0; diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c --- v2.4.5/linux/arch/ppc/kernel/ppc_ksyms.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/ppc_ksyms.c Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.ppc_ksyms.c 1.31 05/18/01 08:18:10 patch + * BK Id: SCCS/s.ppc_ksyms.c 1.36 06/28/01 15:50:16 paulus */ #include #include @@ -357,14 +357,12 @@ #endif /* CONFIG_8xx */ EXPORT_SYMBOL(ret_to_user_hook); -EXPORT_SYMBOL(do_softirq); EXPORT_SYMBOL(next_mmu_context); EXPORT_SYMBOL(set_context); -EXPORT_SYMBOL(mmu_context_overflow); -EXPORT_SYMBOL(flush_hash_page); /* For MOL */ EXPORT_SYMBOL(handle_mm_fault); /* For MOL */ EXPORT_SYMBOL_NOVERS(disarm_decr); #if !defined(CONFIG_8xx) && !defined(CONFIG_4xx) +EXPORT_SYMBOL(flush_hash_page); /* For MOL */ extern long *intercept_table; EXPORT_SYMBOL(intercept_table); #endif diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/prep_pci.c linux/arch/ppc/kernel/prep_pci.c --- v2.4.5/linux/arch/ppc/kernel/prep_pci.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/prep_pci.c Wed Jun 20 11:16:01 2001 @@ -939,17 +939,6 @@ pci_write_config_byte(dev, 0x44, reg); } } - if ((dev = pci_find_device(PCI_VENDOR_ID_VIA, - PCI_DEVICE_ID_VIA_82C586_2, - dev))) - { - /* Force correct USB function interrupt */ - dev->irq = 11; - pcibios_write_config_byte(dev->bus->number, - dev->devfn, - PCI_INTERRUPT_LINE, - dev->irq); - } } if ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, dev))){ diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c --- v2.4.5/linux/arch/ppc/kernel/process.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/process.c Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.process.c 1.15 05/17/01 18:14:22 cort + * BK Id: SCCS/s.process.c 1.19 06/15/01 13:56:56 paulus */ /* * linux/arch/ppc/kernel/process.c @@ -267,6 +267,15 @@ printk("Last syscall: %ld ", current->thread.last_syscall); printk("\nlast math %p last altivec %p", last_task_used_math, last_task_used_altivec); + +#ifdef CONFIG_4xx + printk("\nPLB0: bear= 0x%8.8x acr= 0x%8.8x besr= 0x%8.8x\n", + mfdcr(DCRN_POB0_BEAR), mfdcr(DCRN_PLB0_ACR), + mfdcr(DCRN_PLB0_BESR)); + printk("PLB0 to OPB: bear= 0x%8.8x besr0= 0x%8.8x besr1= 0x%8.8x\n", + mfdcr(DCRN_PLB0_BEAR), mfdcr(DCRN_POB0_BESR0), + mfdcr(DCRN_POB0_BESR1)); +#endif #ifdef CONFIG_SMP printk(" CPU: %d", current->processor); @@ -289,7 +298,8 @@ printk("\n"); } } -out: ; +out: + print_backtrace((unsigned long *)regs->gpr[1]); } void exit_thread(void) diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/prom.c linux/arch/ppc/kernel/prom.c --- v2.4.5/linux/arch/ppc/kernel/prom.c Thu May 24 15:03:05 2001 +++ linux/arch/ppc/kernel/prom.c Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.prom.c 1.20 05/23/01 00:38:42 cort + * BK Id: SCCS/s.prom.c 1.26 06/28/01 15:50:16 paulus */ /* * Procedures for interfacing to the Open Firmware PROM on @@ -42,9 +42,11 @@ /* * Properties whose value is longer than this get excluded from our * copy of the device tree. This way we don't waste space storing - * things like "driver,AAPL,MacOS,PowerPC" properties. + * things like "driver,AAPL,MacOS,PowerPC" properties. But this value + * does need to be big enough to ensure that we don't lose things + * like the interrupt-map property on a PCI-PCI bridge. */ -#define MAX_PROPERTY_LENGTH 1024 +#define MAX_PROPERTY_LENGTH 4096 struct prom_args { const char *service; @@ -172,7 +174,6 @@ #endif extern void enter_rtas(void *); -extern unsigned long reloc_offset(void); void phys_call_rtas(int, int, int, ...); extern char cmd_line[512]; /* XXX */ @@ -190,6 +191,14 @@ #define BOOT_INFO_IS_V2_COMPATIBLE(bi) ((bi)->version >= 2) #define BOOT_INFO_IS_V4_COMPATIBLE(bi) ((bi)->version >= 4) +/* + * Note that prom_init() and anything called from prom_init() must + * use the RELOC/PTRRELOC macros to access any static data in + * memory, since the kernel may be running at an address that is + * different from the address that it was linked at. + * (Note that strings count as static variables.) + */ + __init static void prom_exit() @@ -478,13 +487,14 @@ unsigned int va, unsigned int pa, int mode) { unsigned int *pteg; - unsigned int hash, i; + unsigned int hash, i, vsid; - hash = ((va >> 5) ^ (va >> 21)) & 0x7fff80; + vsid = ((va >> 28) * 0x111) << 12; + hash = ((va ^ vsid) >> 5) & 0x7fff80; pteg = (unsigned int *)(htab + (hash & (hsize - 1))); for (i = 0; i < 8; ++i, pteg += 4) { if ((pteg[1] & 1) == 0) { - pteg[1] = ((va >> 16) & 0xff80) | 1; + pteg[1] = vsid | ((va >> 16) & 0xf80) | 1; pteg[3] = pa | mode; break; } @@ -670,16 +680,16 @@ prom_alloc_htab(); #endif -#ifdef CONFIG_SMP - prom_hold_cpus(mem); -#endif - mem = check_display(mem); prom_print(RELOC("copying OF device tree...")); mem = copy_device_tree(mem, mem + (1<<20)); prom_print(RELOC("done\n")); +#ifdef CONFIG_SMP + prom_hold_cpus(mem); +#endif + RELOC(klimit) = (char *) (mem - offset); /* If we are already running at 0xc0000000, we assume we were loaded by @@ -1190,7 +1200,7 @@ if ((_machine == _MACH_chrp) || (boot_infos == 0 && pmac_newworld)) use_of_interrupt_tree = 1; - mem = finish_node(allnodes, mem, NULL, 0, 0); + mem = finish_node(allnodes, mem, NULL, 1, 1); dev_tree_size = mem - (unsigned long) allnodes; klimit = (char *) mem; } @@ -1225,10 +1235,7 @@ np->name = get_property(np, "name", 0); np->type = get_property(np, "device_type", 0); -#if 0 - np->n_addr_cells = naddrc; - np->n_size_cells = nsizec; -#endif + /* get the device addresses and interrupts */ if (ifunc != NULL) { mem_start = ifunc(np, mem_start, naddrc, nsizec); @@ -1244,16 +1251,6 @@ ip = (int *) get_property(np, "#size-cells", 0); if (ip != NULL) nsizec = *ip; -#if 0 - if (np->parent == NULL) { - /* - * Set the n_addr/size_cells on the root to its - * own values, rather than 0. - */ - np->n_addr_cells = naddrc; - np->n_size_cells = nsizec; - } -#endif /* the f50 sets the name to 'display' and 'compatible' to what we * expect for the name -- Cort @@ -1479,7 +1476,8 @@ if (ip != NULL) return *ip; } while(np->parent); - return 0; + /* No #address-cells property for the root node, default to 1 */ + return 1; } int @@ -1493,7 +1491,8 @@ if (ip != NULL) return *ip; } while(np->parent); - return 0; + /* No #size-cells property for the root node, default to 1 */ + return 1; } __init @@ -1980,7 +1979,7 @@ struct property *pp; for (pp = np->properties; pp != 0; pp = pp->next) { - if (name && strcmp(pp->name, name) == 0) { + if (pp->name != NULL && strcmp(pp->name, name) == 0) { if (lenp != 0) *lenp = pp->length; return pp->value; diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c --- v2.4.5/linux/arch/ppc/kernel/setup.c Thu May 24 15:03:05 2001 +++ linux/arch/ppc/kernel/setup.c Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.setup.c 1.32 05/23/01 00:38:42 cort + * BK Id: SCCS/s.setup.c 1.44 06/28/01 08:01:06 trini */ /* * Common prep/pmac/chrp boot and setup code. @@ -36,16 +36,16 @@ #include #include #endif +#ifdef CONFIG_4xx +#include +#endif #include #include #include #include -#ifdef CONFIG_OAK -#include "oak_setup.h" -#endif /* CONFIG_OAK */ -extern void pmac_init(unsigned long r3, +extern void apus_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, @@ -57,7 +57,7 @@ unsigned long r6, unsigned long r7); -extern void prep_init(unsigned long r3, +extern void gemini_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, @@ -69,19 +69,24 @@ unsigned long r6, unsigned long r7); -extern void apus_init(unsigned long r3, +extern void m8260_init(unsigned long r3, + unsigned long r4, + unsigned long r5, + unsigned long r6, + unsigned long r7); + +extern void pmac_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7); -extern void gemini_init(unsigned long r3, +extern void prep_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7); - extern void bootx_init(unsigned long r4, unsigned long phys); extern unsigned long reloc_offset(void); @@ -332,7 +337,7 @@ * Assume here that all clock rates are the same in a * smp system. -- Cort */ -#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) && !defined(CONFIG_8260) +#if defined(CONFIG_ALL_PPC) if ( have_of ) { struct device_node *cpu_node; @@ -356,7 +361,7 @@ len += sprintf(len+buffer, "clock\t\t: %dMHz\n", *fp / 1000000); } -#endif /* !CONFIG_4xx && !CONFIG_8xx */ +#endif /* CONFIG_ALL_PPC */ if (ppc_md.setup_residual != NULL) { @@ -379,11 +384,12 @@ break; } - len += sprintf(len+buffer, "revision\t: %hd.%hd\n", maj, min); + len += sprintf(len+buffer, "revision\t: %hd.%hd (pvr %04x %04x)\n", + maj, min, PVR_VER(pvr), PVR_REV(pvr)); len += sprintf(buffer+len, "bogomips\t: %lu.%02lu\n", - (CD(loops_per_jiffy)+2500)/(500000/HZ), - (CD(loops_per_jiffy)+2500)/(5000/HZ) % 100); + CD(loops_per_jiffy)/(500000/HZ), + CD(loops_per_jiffy)/(5000/HZ) % 100); bogosum += CD(loops_per_jiffy); } @@ -391,8 +397,8 @@ if ( i ) len += sprintf(buffer+len, "\n"); len += sprintf(buffer+len,"total bogomips\t: %lu.%02lu\n", - (bogosum+2500)/(500000/HZ), - (bogosum+2500)/(5000/HZ) % 100); + bogosum/(500000/HZ), + bogosum/(5000/HZ) % 100); #endif /* CONFIG_SMP */ /* @@ -441,11 +447,15 @@ } #endif /* CONFIG_ALL_PPC */ -#ifdef CONFIG_6xx +#if defined(CONFIG_6xx) || defined(CONFIG_PPC64BRIDGE) /* * We're called here very early in the boot. We determine the machine * type and call the appropriate low-level setup functions. * -- Cort + * + * Note that the kernel may be running at an address which is different + * from the address that it was linked at, so we must use RELOC/PTRRELOC + * to access static data (including strings). -- paulus */ __init unsigned long @@ -454,65 +464,36 @@ extern char __bss_start, _end; unsigned long phys; unsigned long offset = reloc_offset(); - unsigned long local_have_of = 1, local_machine; - struct bi_record *rec; - + /* Default */ phys = offset + KERNELBASE; - -#if defined(CONFIG_APUS) - return phys; -#endif - + /* First zero the BSS -- use memset, some arches don't have * caches on yet */ - memset_io(PTRRELOC(&__bss_start),0 , &_end - &__bss_start); + memset_io(PTRRELOC(&__bss_start), 0, &_end - &__bss_start); -#if defined(CONFIG_ALL_PPC) || defined(CONFIG_GEMINI) +#if defined(CONFIG_ALL_PPC) /* If we came here from BootX, clear the screen, * set up some pointers and return. */ -#if defined(CONFIG_ALL_PPC) if ((r3 == 0x426f6f58) && (r5 == 0)) { bootx_init(r4, phys); return phys; } -#endif /* check if we're prep, return if we are */ if ( *(unsigned long *)(0) == 0xdeadc0de ) return phys; - - /* - * See if we have any bootloader info passed along. If we do, - * get the machine type and find out if we have OF. - * - * The strategy here is to assume that we want to call prom_init() - * unless the bootinfo data passed to us tell us that we don't - * have OF. - * -- Cort + + /* + * for now, don't use bootinfo because it breaks yaboot 0.5 + * and assume that if we didn't find a magic number, we have OF */ - rec = (struct bi_record *)_ALIGN((ulong)PTRRELOC(&__bss_start)+(1<<20)-1,(1<<20)); - if ( rec->tag == BI_FIRST ) - { - for ( ; rec->tag != BI_LAST ; - rec = (struct bi_record *)((ulong)rec + rec->size) ) - { - ulong *data = rec->data; - if ( rec->tag == BI_MACHTYPE ) - { - local_machine = data[0]; - local_have_of = data[1]; - } - } - } + phys = prom_init(r3, r4, (prom_entry)r5); +#endif - if ( local_have_of ) - phys = prom_init( r3, r4, (prom_entry)r5); -#endif - return phys; } -#endif /* CONFIG_6xx */ +#endif /* CONFIG_6xx || CONFIG_PPC64BRIDGE */ /* * Find out what kind of machine we're on and save any data we need @@ -522,6 +503,10 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { +#ifdef CONFIG_CMDLINE + strcpy(cmd_line, CONFIG_CMDLINE); +#endif /* CONFIG_CMDLINE */ + parse_bootinfo(); if ( ppc_md.progress ) ppc_md.progress("id mach(): start", 0x100); @@ -809,7 +794,7 @@ ppc_md.setup_arch(); if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab); -#ifdef CONFIG_PCI +#if defined(CONFIG_PCI) && defined(CONFIG_ALL_PPC) /* We create the "pci-OF-bus-map" property now so it appear in the * /proc device tree */ @@ -825,7 +810,7 @@ prom_add_property(find_path_device("/"), of_prop); } } -#endif /* CONFIG_PCI */ +#endif /* CONFIG_PCI && CONFIG_ALL_PPC */ paging_init(); sort_exception_table(); diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/sleep.S linux/arch/ppc/kernel/sleep.S --- v2.4.5/linux/arch/ppc/kernel/sleep.S Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/sleep.S Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.sleep.S 1.7 05/17/01 18:14:22 cort + * BK Id: SCCS/s.sleep.S 1.10 06/28/01 15:50:17 paulus */ /* * This file contains sleep low-level functions for PowerBook G3. @@ -194,7 +194,7 @@ lis r3,0x2000 /* Ku = 1, VSID = 0 */ li r4,0 3: mtsrin r3,r4 - addi r3,r3,1 /* increment VSID */ + addi r3,r3,0x111 /* increment VSID */ addis r4,r4,0x1000 /* address of next segment */ bdnz 3b diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/smp.c linux/arch/ppc/kernel/smp.c --- v2.4.5/linux/arch/ppc/kernel/smp.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/smp.c Mon Jun 11 19:15:27 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.smp.c 1.23 05/17/01 18:14:22 cort + * BK Id: SCCS/s.smp.c 1.25 05/23/01 00:38:42 cort */ /* * Smp support for ppc. @@ -670,12 +670,12 @@ static void smp_gemini_kick_cpu(int nr) { - openpic_init_processor( 1<gpr[1]); spin_unlock_irq(&oops_lock); /* do_exit() should take care of panic'ing from an interrupt * context so we don't handle it here @@ -186,7 +185,6 @@ } #endif show_regs(regs); - print_backtrace((unsigned long *)regs->gpr[1]); panic("System Management Interrupt"); } @@ -334,7 +332,6 @@ debugger(regs); #endif show_regs(regs); - print_backtrace((unsigned long *)regs->gpr[1]); panic("kernel stack overflow"); } diff -u --recursive --new-file v2.4.5/linux/arch/ppc/mm/Makefile linux/arch/ppc/mm/Makefile --- v2.4.5/linux/arch/ppc/mm/Makefile Mon May 21 17:04:47 2001 +++ linux/arch/ppc/mm/Makefile Mon Jul 2 14:34:57 2001 @@ -1,4 +1,4 @@ -# BK Id: SCCS/s.Makefile 1.3 05/17/01 18:14:23 cort +# BK Id: SCCS/s.Makefile 1.6 06/28/01 15:50:17 paulus # # # Makefile for the linux ppc-specific parts of the memory manager. @@ -9,8 +9,20 @@ # # Note 2! The CFLAGS definition is now in the main makefile... +USE_STANDARD_AS_RULE := true + +ifdef CONFIG_PPC64BRIDGE +EXTRA_AFLAGS := -Wa,-mppc64bridge +endif + O_TARGET := mm.o obj-y := fault.o init.o mem_pieces.o extable.o + +ifneq ($(CONFIG_8xx),y) +ifneq ($(CONFIG_4xx),y) +obj-y += hashtable.o +endif +endif obj-$(CONFIG_4xx) += 4xx_tlb.o diff -u --recursive --new-file v2.4.5/linux/arch/ppc/mm/fault.c linux/arch/ppc/mm/fault.c --- v2.4.5/linux/arch/ppc/mm/fault.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/mm/fault.c Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.fault.c 1.10 05/17/01 18:14:23 cort + * BK Id: SCCS/s.fault.c 1.13 06/28/01 15:50:17 paulus */ /* * arch/ppc/mm/fault.c @@ -44,11 +44,12 @@ int debugger_kernel_faults = 1; #endif -unsigned long htab_reloads = 0; /* updated by head.S:hash_page() */ -unsigned long htab_evicts = 0; /* updated by head.S:hash_page() */ -unsigned long pte_misses = 0; /* updated by do_page_fault() */ -unsigned long pte_errors = 0; /* updated by do_page_fault() */ -unsigned int probingmem = 0; +unsigned long htab_reloads; /* updated by hashtable.S:hash_page() */ +unsigned long htab_evicts; /* updated by hashtable.S:hash_page() */ +unsigned long htab_preloads; /* updated by hashtable.S:add_hash_page() */ +unsigned long pte_misses; /* updated by do_page_fault() */ +unsigned long pte_errors; /* updated by do_page_fault() */ +unsigned int probingmem; extern void die_if_kernel(char *, struct pt_regs *, long); void bad_page_fault(struct pt_regs *, unsigned long, int sig); diff -u --recursive --new-file v2.4.5/linux/arch/ppc/mm/hashtable.S linux/arch/ppc/mm/hashtable.S --- v2.4.5/linux/arch/ppc/mm/hashtable.S Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/mm/hashtable.S Mon Jul 2 14:34:57 2001 @@ -0,0 +1,627 @@ +/* + * BK Id: SCCS/s.hashtable.S 1.16 06/29/01 08:51:52 paulus + */ +/* + * arch/ppc/kernel/hashtable.S + * + * $Id: hashtable.S,v 1.6 1999/10/08 01:56:15 paulus Exp $ + * + * PowerPC version + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP + * Copyright (C) 1996 Cort Dougan + * Adapted for Power Macintosh by Paul Mackerras. + * Low-level exception handlers and MMU support + * rewritten by Paul Mackerras. + * Copyright (C) 1996 Paul Mackerras. + * + * This file contains low-level assembler routines for managing + * the PowerPC MMU hash table. (PPC 8xx processors don't use a + * hash table, so this file is not used on them.) + * + * 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" +#include +#include +#include + +#ifdef CONFIG_SMP + .comm hash_table_lock,4 +#endif /* CONFIG_SMP */ + +/* + * Load a PTE into the hash table, if possible. + * The address is in r4, and r3 contains an access flag: + * _PAGE_RW (0x400) if a write. + * r23 contains the SRR1 value, from which we use the MSR_PR bit. + * SPRG3 contains the physical address of the current task's thread. + * + * Returns to the caller if the access is illegal or there is no + * mapping for the address. Otherwise it places an appropriate PTE + * in the hash table and returns from the exception. + * Uses r0, r2 - r7, ctr, lr. + */ + .text + .globl hash_page +hash_page: +#ifdef CONFIG_PPC64BRIDGE + mfmsr r0 + clrldi r0,r0,1 /* make sure it's in 32-bit mode */ + MTMSRD(r0) + isync +#endif + tophys(r7,0) /* gets -KERNELBASE into r7 */ +#ifdef CONFIG_SMP + addis r2,r7,hash_table_lock@h + ori r2,r2,hash_table_lock@l + mfspr r5,SPRG3 + lwz r0,PROCESSOR-THREAD(r5) + oris r0,r0,0x0fff + b 10f +11: lwz r6,0(r2) + cmpwi 0,r6,0 + bne 11b +10: lwarx r6,0,r2 + cmpwi 0,r6,0 + bne- 11b + stwcx. r0,0,r2 + bne- 10b + isync +#endif + /* Get PTE (linux-style) and check access */ + lis r0,KERNELBASE@h /* check if kernel address */ + cmplw 0,r4,r0 + mfspr r2,SPRG3 /* current task's THREAD (phys) */ + ori r3,r3,_PAGE_USER|_PAGE_PRESENT /* test low addresses as user */ + lwz r5,PGDIR(r2) /* virt page-table root */ + blt+ 112f /* assume user more likely */ + lis r5,swapper_pg_dir@ha /* if kernel address, use */ + addi r5,r5,swapper_pg_dir@l /* kernel page table */ + rlwimi r3,r23,32-12,29,29 /* MSR_PR -> _PAGE_USER */ +112: add r5,r5,r7 /* convert to phys addr */ + rlwimi r5,r4,12,20,29 /* insert top 10 bits of address */ + lwz r5,0(r5) /* get pmd entry */ + rlwinm. r5,r5,0,0,19 /* extract address of pte page */ +#ifdef CONFIG_SMP + beq- hash_page_out /* return if no mapping */ +#else + /* XXX it seems like the 601 will give a machine fault on the + rfi if its alignment is wrong (bottom 4 bits of address are + 8 or 0xc) and we have had a not-taken conditional branch + to the address following the rfi. */ + beqlr- +#endif + add r2,r5,r7 /* convert to phys addr */ + rlwimi r2,r4,22,20,29 /* insert next 10 bits of address */ + rlwinm r0,r3,32-3,24,24 /* _PAGE_RW access -> _PAGE_DIRTY */ + ori r0,r0,_PAGE_ACCESSED|_PAGE_HASHPTE + + /* + * Update the linux PTE atomically. We do the lwarx up-front + * because almost always, there won't be a permission violation + * and there won't already be an HPTE, and thus we will have + * to update the PTE to set _PAGE_HASHPTE. -- paulus. + */ +retry: + lwarx r6,0,r2 /* get linux-style pte */ + andc. r5,r3,r6 /* check access & ~permission */ +#ifdef CONFIG_SMP + bne- hash_page_out /* return if access not permitted */ +#else + bnelr- +#endif + or r5,r0,r6 /* set accessed/dirty bits */ + stwcx. r5,0,r2 /* attempt to update PTE */ + bne- retry /* retry if someone got there first */ + + mfsrin r3,r4 /* get segment reg for segment */ + mr r2,r8 /* we have saved r2 but not r8 */ + bl create_hpte /* add the hash table entry */ + mr r8,r2 + +/* + * htab_reloads counts the number of times we have to fault an + * HPTE into the hash table. This should only happen after a + * fork (because fork does a flush_tlb_mm) or a vmalloc or ioremap. + * Where a page is faulted into a process's address space, + * update_mmu_cache gets called to put the HPTE into the hash table + * and those are counted as preloads rather than reloads. + */ + addis r2,r7,htab_reloads@ha + lwz r3,htab_reloads@l(r2) + addi r3,r3,1 + stw r3,htab_reloads@l(r2) + +#ifdef CONFIG_SMP + eieio + addis r2,r7,hash_table_lock@ha + li r0,0 + stw r0,hash_table_lock@l(r2) +#endif + + /* Return from the exception */ + lwz r3,_CCR(r21) + lwz r4,_LINK(r21) + lwz r5,_CTR(r21) + mtcrf 0xff,r3 + mtlr r4 + mtctr r5 + lwz r0,GPR0(r21) + lwz r1,GPR1(r21) + lwz r2,GPR2(r21) + lwz r3,GPR3(r21) + lwz r4,GPR4(r21) + lwz r5,GPR5(r21) + lwz r6,GPR6(r21) + lwz r7,GPR7(r21) + /* we haven't used xer */ + mtspr SRR1,r23 + mtspr SRR0,r22 + lwz r20,GPR20(r21) + lwz r22,GPR22(r21) + lwz r23,GPR23(r21) + lwz r21,GPR21(r21) + RFI + +#ifdef CONFIG_SMP +hash_page_out: + eieio + addis r2,r7,hash_table_lock@ha + li r0,0 + stw r0,hash_table_lock@l(r2) + blr +#endif /* CONFIG_SMP */ + +/* + * Add an entry for a particular page to the hash table. + * + * add_hash_page(unsigned context, unsigned long va, pte_t pte) + * + * We assume any necessary modifications to the pte (e.g. setting + * the accessed bit) have already been done and that there is actually + * a hash table in use (i.e. we're not on a 603). + */ +_GLOBAL(add_hash_page) + mflr r0 + stw r0,4(r1) + + /* Convert context and va to VSID */ + mulli r3,r3,897*16 /* multiply context by context skew */ + rlwinm r0,r4,4,28,31 /* get ESID (top 4 bits of va) */ + mulli r0,r0,0x111 /* multiply by ESID skew */ + add r3,r3,r0 /* note create_hpte trims to 24 bits */ + + /* + * We disable interrupts here, even on UP, because we don't + * want to race with hash_page, and because we want the + * _PAGE_HASHPTE bit to be a reliable indication of whether + * the HPTE exists (or at least whether one did once). -- paulus + */ + mfmsr r10 + SYNC + rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */ + mtmsr r0 + SYNC + +#ifdef CONFIG_SMP + lis r9,hash_table_lock@h + ori r9,r9,hash_table_lock@l + lwz r8,PROCESSOR(r2) + oris r8,r8,10 +10: lwarx r7,0,r9 + cmpi 0,r7,0 + bne- 11f + stwcx. r8,0,r9 + beq+ 12f +11: lwz r7,0(r9) + cmpi 0,r7,0 + beq 10b + b 11b +12: isync +#endif + + /* + * Fetch the linux pte and test and set _PAGE_HASHPTE atomically. + * If _PAGE_HASHPTE was already set, we don't replace the existing + * HPTE, so we just unlock and return. + */ + mr r7,r5 +1: lwarx r6,0,r7 + andi. r0,r6,_PAGE_HASHPTE + bne 9f /* if HASHPTE already set, done */ + ori r5,r6,_PAGE_ACCESSED|_PAGE_HASHPTE + stwcx. r5,0,r7 + bne- 1b + + li r7,0 /* no address offset needed */ + bl create_hpte + + lis r8,htab_preloads@ha + lwz r3,htab_preloads@l(r8) + addi r3,r3,1 + stw r3,htab_preloads@l(r8) + +9: +#ifdef CONFIG_SMP + eieio + li r0,0 + stw r0,0(r9) /* clear hash_table_lock */ +#endif + + lwz r0,4(r1) + mtlr r0 + + /* reenable interrupts */ + mtmsr r10 + SYNC + blr + +/* + * This routine adds a hardware PTE to the hash table. + * It is designed to be called with the MMU either on or off. + * r3 contains the VSID, r4 contains the virtual address, + * r5 contains the linux PTE, r6 contains the old value of the + * linux PTE (before setting _PAGE_HASHPTE) and r7 contains the + * offset to be added to addresses (0 if the MMU is on, + * -KERNELBASE if it is off). + * On SMP, the caller should have the hash_table_lock held. + * We assume that the caller has (or will) set the _PAGE_HASHPTE + * bit in the linux PTE in memory. The value passed in r6 should + * be the old linux PTE value; if it doesn't have _PAGE_HASHPTE set + * this routine will skip the search for an existing HPTE. + * This procedure modifies r0, r3 - r6, r8, cr0. + * -- paulus. + * + * For speed, 4 of the instructions get patched once the size and + * physical address of the hash table are known. These definitions + * of Hash_base and Hash_bits below are just an example. + */ +Hash_base = 0xc0180000 +Hash_bits = 12 /* e.g. 256kB hash table */ +Hash_msk = (((1 << Hash_bits) - 1) * 64) + +#ifndef CONFIG_PPC64BRIDGE +/* defines for the PTE format for 32-bit PPCs */ +#define PTE_SIZE 8 +#define PTEG_SIZE 64 +#define LG_PTEG_SIZE 6 +#define LDPTEu lwzu +#define STPTE stw +#define CMPPTE cmpw +#define PTE_H 0x40 +#define PTE_V 0x80000000 +#define TST_V(r) rlwinm. r,r,0,0,0 +#define SET_V(r) oris r,r,PTE_V@h +#define CLR_V(r,t) rlwinm r,r,0,1,31 + +#else +/* defines for the PTE format for 64-bit PPCs */ +#define PTE_SIZE 16 +#define PTEG_SIZE 128 +#define LG_PTEG_SIZE 7 +#define LDPTEu ldu +#define STPTE std +#define CMPPTE cmpd +#define PTE_H 2 +#define PTE_V 1 +#define TST_V(r) andi. r,r,PTE_V +#define SET_V(r) ori r,r,PTE_V +#define CLR_V(r,t) li t,PTE_V; andc r,r,t +#endif /* CONFIG_PPC64BRIDGE */ + +#define HASH_LEFT 31-(LG_PTEG_SIZE+Hash_bits-1) +#define HASH_RIGHT 31-LG_PTEG_SIZE + +_GLOBAL(create_hpte) + /* Convert linux-style PTE (r5) to low word of PPC-style PTE (r8) */ + rlwinm r8,r5,32-10,31,31 /* _PAGE_RW -> PP lsb */ + rlwinm r0,r5,32-7,31,31 /* _PAGE_DIRTY -> PP lsb */ + and r8,r8,r0 /* writable if _RW & _DIRTY */ + rlwimi r5,r5,32-1,30,30 /* _PAGE_USER -> PP msb */ + rlwimi r5,r5,32-2,31,31 /* _PAGE_USER -> PP lsb */ + ori r8,r8,0xe14 /* clear out reserved bits and M */ + andc r8,r5,r8 /* PP = user? (rw&dirty? 2: 3): 0 */ +#ifdef CONFIG_SMP + ori r8,r8,_PAGE_COHERENT /* set M (coherence required) */ +#endif + +#ifdef CONFIG_POWER4 + /* + * XXX hack hack hack - translate 32-bit "physical" addresses + * in the linux page tables to 42-bit real addresses in such + * a fashion that we can get at the I/O we need to access. + * -- paulus + */ + cmpwi r8,0 + rlwinm r0,r8,16,16,30 + bge 57f + cmplwi r0,0xfe00 + li r0,0x3fd + bne 56f + li r0,0x3ff +56: sldi r0,r0,32 + or r8,r8,r0 +57: +#endif + + /* Construct the high word of the PPC-style PTE (r5) */ +#ifndef CONFIG_PPC64BRIDGE + rlwinm r5,r3,7,1,24 /* put VSID in 0x7fffff80 bits */ + rlwimi r5,r4,10,26,31 /* put in API (abbrev page index) */ +#else /* CONFIG_PPC64BRIDGE */ + clrlwi r3,r3,8 /* reduce vsid to 24 bits */ + sldi r5,r3,12 /* shift vsid into position */ + rlwimi r5,r4,16,20,24 /* put in API (abbrev page index) */ +#endif /* CONFIG_PPC64BRIDGE */ + SET_V(r5) /* set V (valid) bit */ + + /* Get the address of the primary PTE group in the hash table (r3) */ + .globl hash_page_patch_A +hash_page_patch_A: + addis r0,r7,Hash_base@h /* base address of hash table */ + rlwimi r0,r3,LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* VSID -> hash */ + rlwinm r3,r4,20+LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* PI -> hash */ + xor r3,r3,r0 /* make primary hash */ + li r0,8 /* PTEs/group */ + + /* + * Test the _PAGE_HASHPTE bit in the old linux PTE, and skip the search + * if it is clear, meaning that the HPTE isn't there already... + */ + andi. r6,r6,_PAGE_HASHPTE + beq+ 10f /* no PTE: go look for an empty slot */ + tlbie r4 + + addis r4,r7,htab_hash_searches@ha + lwz r6,htab_hash_searches@l(r4) + addi r6,r6,1 /* count how many searches we do */ + stw r6,htab_hash_searches@l(r4) + + /* Search the primary PTEG for a PTE whose 1st (d)word matches r5 */ + mtctr r0 + addi r4,r3,-PTE_SIZE +1: LDPTEu r6,PTE_SIZE(r4) /* get next PTE */ + CMPPTE 0,r6,r5 + bdnzf 2,1b /* loop while ctr != 0 && !cr0.eq */ + beq+ found_slot + + /* Search the secondary PTEG for a matching PTE */ + ori r5,r5,PTE_H /* set H (secondary hash) bit */ + .globl hash_page_patch_B +hash_page_patch_B: + xoris r4,r3,Hash_msk>>16 /* compute secondary hash */ + xori r4,r4,(-PTEG_SIZE & 0xffff) + addi r4,r4,-PTE_SIZE + mtctr r0 +2: LDPTEu r6,PTE_SIZE(r4) + CMPPTE 0,r6,r5 + bdnzf 2,2b + beq+ found_slot + xori r5,r5,PTE_H /* clear H bit again */ + + /* Search the primary PTEG for an empty slot */ +10: mtctr r0 + addi r4,r3,-PTE_SIZE /* search primary PTEG */ +1: LDPTEu r6,PTE_SIZE(r4) /* get next PTE */ + TST_V(r6) /* test valid bit */ + bdnzf 2,1b /* loop while ctr != 0 && !cr0.eq */ + beq+ found_empty + + /* update counter of times that the primary PTEG is full */ + addis r4,r7,primary_pteg_full@ha + lwz r6,primary_pteg_full@l(r4) + addi r6,r6,1 + stw r6,primary_pteg_full@l(r4) + + /* Search the secondary PTEG for an empty slot */ + ori r5,r5,PTE_H /* set H (secondary hash) bit */ + .globl hash_page_patch_C +hash_page_patch_C: + xoris r4,r3,Hash_msk>>16 /* compute secondary hash */ + xori r4,r4,(-PTEG_SIZE & 0xffff) + addi r4,r4,-PTE_SIZE + mtctr r0 +2: LDPTEu r6,PTE_SIZE(r4) + TST_V(r6) + bdnzf 2,2b + beq+ found_empty + xori r5,r5,PTE_H /* clear H bit again */ + + /* + * Choose an arbitrary slot in the primary PTEG to overwrite. + * Since both the primary and secondary PTEGs are full, and we + * have no information that the PTEs in the primary PTEG are + * more important or useful than those in the secondary PTEG, + * and we know there is a definite (although small) speed + * advantage to putting the PTE in the primary PTEG, we always + * put the PTE in the primary PTEG. + */ + addis r4,r7,next_slot@ha + lwz r6,next_slot@l(r4) + addi r6,r6,PTE_SIZE + andi. r6,r6,7*PTE_SIZE +#ifdef CONFIG_POWER4 + /* + * Since we don't have BATs on POWER4, we rely on always having + * PTEs in the hash table to map the hash table and the code + * that manipulates it in virtual mode, namely flush_hash_page and + * flush_hash_segments. Otherwise we can get a DSI inside those + * routines which leads to a deadlock on the hash_table_lock on + * SMP machines. We avoid this by never overwriting the first + * PTE of each PTEG if it is already valid. + * -- paulus. + */ + bne 102f + li r6,PTE_SIZE +102: +#endif /* CONFIG_POWER4 */ + stw r6,next_slot@l(r4) + add r4,r3,r6 + + /* update counter of evicted pages */ + addis r6,r7,htab_evicts@ha + lwz r3,htab_evicts@l(r6) + addi r3,r3,1 + stw r3,htab_evicts@l(r6) + +#ifndef CONFIG_SMP + /* Store PTE in PTEG */ +found_empty: + STPTE r5,0(r4) +found_slot: + STPTE r8,PTE_SIZE/2(r4) + +#else /* CONFIG_SMP */ +/* + * Between the tlbie above and updating the hash table entry below, + * another CPU could read the hash table entry and put it in its TLB. + * There are 3 cases: + * 1. using an empty slot + * 2. updating an earlier entry to change permissions (i.e. enable write) + * 3. taking over the PTE for an unrelated address + * + * In each case it doesn't really matter if the other CPUs have the old + * PTE in their TLB. So we don't need to bother with another tlbie here, + * which is convenient as we've overwritten the register that had the + * address. :-) The tlbie above is mainly to make sure that this CPU comes + * and gets the new PTE from the hash table. + * + * We do however have to make sure that the PTE is never in an invalid + * state with the V bit set. + */ +found_empty: +found_slot: + CLR_V(r5,r0) /* clear V (valid) bit in PTE */ + STPTE r5,0(r4) + sync + TLBSYNC + STPTE r8,PTE_SIZE/2(r4) /* put in correct RPN, WIMG, PP bits */ + sync + SET_V(r5) + STPTE r5,0(r4) /* finally set V bit in PTE */ +#endif /* CONFIG_SMP */ + + sync /* make sure pte updates get to memory */ + blr + + .comm next_slot,4 + .comm primary_pteg_full,4 + .comm htab_hash_searches,4 + +/* + * Flush the entry for a particular page from the hash table. + * + * flush_hash_page(unsigned context, unsigned long va, pte_t *ptep) + * + * We assume that there is a hash table in use (Hash != 0). + */ +_GLOBAL(flush_hash_page) + /* Convert context and va to VSID */ + mulli r3,r3,897*16 /* multiply context by context skew */ + rlwinm r0,r4,4,28,31 /* get ESID (top 4 bits of va) */ + mulli r0,r0,0x111 /* multiply by ESID skew */ + add r3,r3,r0 /* note code below trims to 24 bits */ + + /* + * We disable interrupts here, even on UP, because we want + * the _PAGE_HASHPTE bit to be a reliable indication of + * whether the HPTE exists. -- paulus + */ + mfmsr r10 + rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */ + SYNC + mtmsr r0 + SYNC + +#ifdef CONFIG_SMP + lis r9,hash_table_lock@h + ori r9,r9,hash_table_lock@l + lwz r8,PROCESSOR(r2) + oris r8,r8,9 +10: lwarx r7,0,r9 + cmpi 0,r7,0 + bne- 11f + stwcx. r8,0,r9 + beq+ 12f +11: lwz r7,0(r9) + cmpi 0,r7,0 + beq 10b + b 11b +12: isync +#endif + + /* + * Check the _PAGE_HASHPTE bit in the linux PTE. If it is + * already clear, we're done. If not, clear it (atomically) + * and proceed. -- paulus. + */ +1: lwarx r6,0,r5 /* fetch the pte */ + andi. r0,r6,_PAGE_HASHPTE + beq 9f /* done if HASHPTE is already clear */ + rlwinm r6,r6,0,31,29 /* clear HASHPTE bit */ + stwcx. r6,0,r5 /* update the pte */ + bne- 1b + + /* Construct the high word of the PPC-style PTE (r5) */ +#ifndef CONFIG_PPC64BRIDGE + rlwinm r5,r3,7,1,24 /* put VSID in 0x7fffff80 bits */ + rlwimi r5,r4,10,26,31 /* put in API (abbrev page index) */ +#else /* CONFIG_PPC64BRIDGE */ + clrlwi r3,r3,8 /* reduce vsid to 24 bits */ + sldi r5,r3,12 /* shift vsid into position */ + rlwimi r5,r4,16,20,24 /* put in API (abbrev page index) */ +#endif /* CONFIG_PPC64BRIDGE */ + SET_V(r5) /* set V (valid) bit */ + + /* Get the address of the primary PTE group in the hash table (r3) */ + .globl flush_hash_patch_A +flush_hash_patch_A: + lis r8,Hash_base@h /* base address of hash table */ + rlwimi r8,r3,LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* VSID -> hash */ + rlwinm r3,r4,20+LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* PI -> hash */ + xor r3,r3,r8 /* make primary hash */ + li r8,8 /* PTEs/group */ + + /* Search the primary PTEG for a PTE whose 1st (d)word matches r5 */ + mtctr r8 + addi r7,r3,-PTE_SIZE +1: LDPTEu r0,PTE_SIZE(r7) /* get next PTE */ + CMPPTE 0,r0,r5 + bdnzf 2,1b /* loop while ctr != 0 && !cr0.eq */ + beq+ 3f + + /* Search the secondary PTEG for a matching PTE */ + ori r5,r5,PTE_H /* set H (secondary hash) bit */ + .globl flush_hash_patch_B +flush_hash_patch_B: + xoris r7,r3,Hash_msk>>16 /* compute secondary hash */ + xori r7,r7,(-PTEG_SIZE & 0xffff) + addi r7,r7,-PTE_SIZE + mtctr r8 +2: LDPTEu r0,PTE_SIZE(r7) + CMPPTE 0,r0,r5 + bdnzf 2,2b + bne- 4f /* should never fail to find it */ + +3: li r0,0 + STPTE r0,0(r7) /* invalidate entry */ +4: sync + tlbie r4 /* in hw tlb too */ + sync + +#ifdef CONFIG_SMP + TLBSYNC +9: li r0,0 + stw r0,0(r9) /* clear hash_table_lock */ +#endif + +9: mtmsr r10 + SYNC + blr diff -u --recursive --new-file v2.4.5/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c --- v2.4.5/linux/arch/ppc/mm/init.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/mm/init.c Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.init.c 1.22 05/17/01 18:14:23 cort + * BK Id: SCCS/s.init.c 1.27 06/28/01 15:50:17 paulus */ /* * PowerPC version @@ -73,9 +73,15 @@ #define PGTOKB(pages) (((pages) * PAGE_SIZE) >> 10) +mm_context_t next_mmu_context; +unsigned long context_map[(LAST_CONTEXT+1) / (8*sizeof(unsigned long))]; +#ifdef FEW_CONTEXTS +atomic_t nr_free_contexts; +struct mm_struct *context_mm[LAST_CONTEXT+1]; +void steal_context(void); +#endif /* FEW_CONTEXTS */ + int prom_trashed; -atomic_t next_mmu_context; -rwlock_t context_overflow_lock __cacheline_aligned = RW_LOCK_UNLOCKED; unsigned long *end_of_DRAM; unsigned long total_memory; unsigned long total_lowmem; @@ -187,12 +193,6 @@ /* max amount of low RAM to map in */ unsigned long __max_low_memory = MAX_LOW_MEM; -void __bad_pte(pmd_t *pmd) -{ - printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd)); - pmd_val(*pmd) = (unsigned long) BAD_PAGETABLE; -} - int do_check_pgt_cache(int low, int high) { int freed = 0; @@ -211,35 +211,6 @@ return freed; } -/* - * BAD_PAGE is the page that is used for page faults when linux - * is out-of-memory. Older versions of linux just did a - * do_exit(), but using this instead means there is less risk - * for a process dying in kernel mode, possibly leaving a inode - * unused etc.. - * - * BAD_PAGETABLE is the accompanying page-table: it is initialized - * to point to BAD_PAGE entries. - * - * ZERO_PAGE is a special page that is used for zero-initialized - * data and COW. - */ -pte_t *empty_bad_page_table; - -pte_t * __bad_pagetable(void) -{ - clear_page(empty_bad_page_table); - return empty_bad_page_table; -} - -void *empty_bad_page; - -pte_t __bad_page(void) -{ - clear_page(empty_bad_page); - return pte_mkdirty(mk_pte_phys(__pa(empty_bad_page), PAGE_SHARED)); -} - void show_mem(void) { int i,free = 0,total = 0,reserved = 0; @@ -319,21 +290,10 @@ void si_meminfo(struct sysinfo *val) { - int i; - - i = max_mapnr; - val->totalram = 0; + val->totalram = totalram_pages; val->sharedram = 0; val->freeram = nr_free_pages(); val->bufferram = atomic_read(&buffermem_pages); - while (i-- > 0) { - if (PageReserved(mem_map+i)) - continue; - val->totalram++; - if (!atomic_read(&mem_map[i].count)) - continue; - val->sharedram += atomic_read(&mem_map[i].count) - 1; - } val->totalhigh = totalhigh_pages; val->freehigh = nr_free_highpages(); val->mem_unit = PAGE_SIZE; @@ -482,14 +442,16 @@ if (pg != 0) { err = 0; set_pte(pg, mk_pte_phys(pa & PAGE_MASK, __pgprot(flags))); - if (mem_init_done) - flush_hash_page(0, va); +#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) + if (mem_init_done && Hash != 0) + flush_hash_page(0, va, pg); +#endif /* !4xx && !8xx */ } spin_unlock(&init_mm.page_table_lock); return err; } -#ifndef CONFIG_8xx +#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) /* * TLB flushing: * @@ -510,19 +472,14 @@ void local_flush_tlb_all(void) { -#ifdef CONFIG_PPC64BRIDGE - /* XXX this assumes that the vmalloc arena starts no lower than - * 0xd0000000 on 64-bit machines. */ - flush_hash_segments(0xd, 0xffffff); -#else - /* this could cause problems on SMP with nobats -- paulus */ - /* XXX no hash_table_lock? interesting -- paulus */ - __clear_user(Hash, Hash_size); - _tlbia(); + /* aargh!!! */ + /* just flush the kernel part of the address space, that's + all that the current callers of this require. -- paulus. */ + local_flush_tlb_range(&init_mm, TASK_SIZE, ~0UL); + #ifdef CONFIG_SMP smp_send_tlb_invalidate(0); #endif /* CONFIG_SMP */ -#endif /* CONFIG_PPC64BRIDGE */ } /* @@ -533,30 +490,18 @@ void local_flush_tlb_mm(struct mm_struct *mm) { - if (mm->context == 0) { - /* don't try to reassign a new context to the kernel */ - /* - * This could cause problems on SMP if we aren't using - * the BATs (e.g. on POWER4 or if the nobats option is used). - * The problem scenario is that one cpu is doing - * flush_hash_page or similar when another cpu clears - * out the HPTEs which map the flush_hash_page text - * and the hash table. hash_page will then deadlock. - * We need some way to have "protected" HPTEs or else - * do all hash-table manipulation with the MMU off. - * -- paulus. - */ -#ifdef CONFIG_PPC64BRIDGE - flush_hash_segments(0xd, 0xf); -#else - flush_hash_segments(0xc, 0xf); -#endif CONFIG_PPC64BRIDGE + if (Hash == 0) { _tlbia(); return; } - mm->context = NO_CONTEXT; - if (mm == current->mm) - activate_mm(mm, mm); + + if (mm->map_count) { + struct vm_area_struct *mp; + for (mp = mm->mmap; mp != NULL; mp = mp->vm_next) + local_flush_tlb_range(mm, mp->vm_start, mp->vm_end); + } else + local_flush_tlb_range(mm, 0, TASK_SIZE); + #ifdef CONFIG_SMP smp_send_tlb_invalidate(0); #endif @@ -565,10 +510,21 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) { - if (vmaddr < TASK_SIZE) - flush_hash_page(vma->vm_mm->context, vmaddr); - else - flush_hash_page(0, vmaddr); + struct mm_struct *mm; + pmd_t *pmd; + pte_t *pte; + + if (Hash == 0) { + _tlbie(vmaddr); + return; + } + mm = (vmaddr < TASK_SIZE)? vma->vm_mm: &init_mm; + pmd = pmd_offset(pgd_offset(mm, vmaddr), vmaddr); + if (!pmd_none(*pmd)) { + pte = pte_offset(pmd, vmaddr); + if (pte_val(*pte) & _PAGE_HASHPTE) + flush_hash_page(mm->context, vmaddr, pte); + } #ifdef CONFIG_SMP smp_send_tlb_invalidate(0); #endif @@ -576,28 +532,43 @@ /* - * for each page addr in the range, call MMU_invalidate_page() - * if the range is very large and the hash table is small it might be - * faster to do a search of the hash table and just invalidate pages - * that are in the range but that's for study later. - * -- Cort + * For each address in the range, find the pte for the address + * and check _PAGE_HASHPTE bit; if it is set, find and destroy + * the corresponding HPTE. */ void local_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) { - start &= PAGE_MASK; + pmd_t *pmd; + pte_t *pte; + unsigned long pmd_end; + unsigned int ctx = mm->context; - if (mm->context != 0) { - if (end > TASK_SIZE) - end = TASK_SIZE; - if (end - start > 20 * PAGE_SIZE) { - flush_tlb_mm(mm); - return; - } + if (Hash == 0) { + _tlbia(); + return; } - - for (; start < end; start += PAGE_SIZE) - flush_hash_page(mm->context, start); + start &= PAGE_MASK; + if (start >= end) + return; + pmd = pmd_offset(pgd_offset(mm, start), start); + do { + pmd_end = (start + PGDIR_SIZE) & PGDIR_MASK; + if (!pmd_none(*pmd)) { + if (!pmd_end || pmd_end > end) + pmd_end = end; + pte = pte_offset(pmd, start); + do { + if ((pte_val(*pte) & _PAGE_HASHPTE) != 0) + flush_hash_page(ctx, start, pte); + start += PAGE_SIZE; + ++pte; + } while (start && start < pmd_end); + } else { + start = pmd_end; + } + ++pmd; + } while (start && start < end); #ifdef CONFIG_SMP smp_send_tlb_invalidate(0); @@ -605,59 +576,6 @@ } /* - * The context counter has overflowed. - * We set mm->context to NO_CONTEXT for all mm's in the system. - * We assume we can get to all mm's by looking as tsk->mm for - * all tasks in the system. - */ -void -mmu_context_overflow(void) -{ - struct task_struct *tsk; - - printk(KERN_DEBUG "mmu_context_overflow\n"); - /* acquire the write lock for context overflow */ - write_lock (&context_overflow_lock); - /* recheck if overflow still exists */ - if (atomic_read(&next_mmu_context) == LAST_CONTEXT) { - read_lock(&tasklist_lock); - for_each_task(tsk) { - if (tsk->mm) - tsk->mm->context = NO_CONTEXT; - } - read_unlock(&tasklist_lock); - flush_hash_segments(0x10, 0xffffff); -#ifdef CONFIG_SMP - smp_send_tlb_invalidate(0); -#endif - atomic_set(&next_mmu_context, 0); - } - write_unlock (&context_overflow_lock); - /* make sure current always has a context */ - /* need to check to assure current task has an mm */ - /* - idle thread does not have an MM */ - if (current->mm) { - current->mm->context = MUNGE_CONTEXT(atomic_inc_return(&next_mmu_context)); - set_context(current->mm->context, current->mm->pgd); - } -} -#else /* CONFIG_8xx */ -void -mmu_context_overflow(void) -{ - atomic_set(&next_mmu_context, -1); -} -#endif /* CONFIG_8xx */ - -void flush_page_to_ram(struct page *page) -{ - unsigned long vaddr = (unsigned long) kmap(page); - __flush_page_to_ram(vaddr); - kunmap(page); -} - -#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) -/* * Set up one of the I/D BAT (block address translation) register pairs. * The parameters are not checked; in particular size must be a power * of 2 between 128k and 256M. @@ -717,8 +635,6 @@ /* * Map in all of physical memory starting at KERNELBASE. */ -#define PAGE_KERNEL_RO __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED) - static void __init mapin_ram(void) { unsigned long v, p, s, f; @@ -768,10 +684,10 @@ f = _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_SHARED; #if defined(CONFIG_KGDB) || defined(CONFIG_XMON) /* Allows stub to set breakpoints everywhere */ - f |= _PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE; + f |= _PAGE_RW | _PAGE_DIRTY; #else if ((char *) v < _stext || (char *) v >= etext) - f |= _PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE; + f |= _PAGE_RW | _PAGE_DIRTY; #ifndef CONFIG_8xx else /* On the powerpc (not 8xx), no user access @@ -839,16 +755,59 @@ #ifdef CONFIG_BLK_DEV_INITRD void free_initrd_mem(unsigned long start, unsigned long end) { + printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); + for (; start < end; start += PAGE_SIZE) { 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 - start) >> 10); } #endif +/* + * Initialize the context management stuff. + */ +static void mmu_context_init(void) +{ + context_map[0] = 1; /* init_mm uses context 0 */ + next_mmu_context = 1; +#ifdef FEW_CONTEXTS + atomic_set(&nr_free_contexts, LAST_CONTEXT); + context_mm[0] = &init_mm; +#endif /* FEW_CONTEXTS */ +} + +#ifdef FEW_CONTEXTS +/* + * Steal a context from a task that has one at the moment. + * This is only used on 8xx and 4xx and we presently assume that + * they don't do SMP. If they do then this will have to check + * whether the MM we steal is in use. + * We also assume that this is only used on systems that don't + * use an MMU hash table - this is true for 8xx and 4xx. + * This isn't an LRU system, it just frees up each context in + * turn (sort-of pseudo-random replacement :). This would be the + * place to implement an LRU scheme if anyone was motivated to do it. + * -- paulus + */ +void steal_context(void) +{ + struct mm_struct *mm; + + /* free up context `next_mmu_context' */ + /* if we shouldn't free context 0, don't... */ +#ifdef CONFIG_4xx + if (next_mmu_context == 0) + next_mmu_context = 1; +#endif /* CONFIG_4xx */ + mm = context_mm[next_mmu_context]; + flush_tlb_mm(mm); + destroy_context(mm); +} +#endif /* FEW_CONTEXTS */ + extern boot_infos_t *disp_bi; /* @@ -903,6 +862,8 @@ mtspr(SPRN_DCCR, 0x80000000); /* 128 MB of data space at 0x0. */ mtspr(SPRN_ICCR, 0x80000000); /* 128 MB of instr. space at 0x0. */ + + mmu_context_init(); } #else /* !CONFIG_4xx */ @@ -938,11 +899,7 @@ /* Map in all of RAM starting at KERNELBASE */ mapin_ram(); -#if defined(CONFIG_POWER4) - ioremap_base = ioremap_bot = 0xfffff000; - isa_io_base = (unsigned long) ioremap(0xffd00000, 0x200000) + 0x100000; - -#elif defined(CONFIG_8xx) +#if defined(CONFIG_8xx) /* Now map in some of the I/O space that is generically needed * or shared with multiple devices. * All of this fits into the same 4Mbyte region, so it only @@ -974,7 +931,7 @@ #ifdef CONFIG_PCI ioremap(PCI_CSR_ADDR, PCI_CSR_SIZE); #endif -#else /* !CONFIG_POWER4 && !CONFIG_8xx */ +#else /* !CONFIG_8xx */ /* * Setup the bat mappings we're going to load that cover * the io areas. RAM was mapped by mapin_ram(). @@ -1024,7 +981,7 @@ break; } ioremap_bot = ioremap_base; -#endif /* CONFIG_POWER4 || CONFIG_8xx */ +#endif /* CONFIG_8xx */ if ( ppc_md.progress ) ppc_md.progress("MMU:exit", 0x211); #ifdef CONFIG_BOOTX_TEXT @@ -1032,6 +989,8 @@ if (_machine == _MACH_Pmac || _machine == _MACH_chrp) map_bootx_text(); #endif + + mmu_context_init(); } #endif /* CONFIG_4xx */ @@ -1095,12 +1054,6 @@ #endif /* CONFIG_HIGHMEM */ /* - * Grab some memory for bad_page and bad_pagetable to use. - */ - empty_bad_page = alloc_bootmem_pages(PAGE_SIZE); - empty_bad_page_table = alloc_bootmem_pages(PAGE_SIZE); - - /* * All pages are DMA-able so we put them all in the DMA zone. */ zones_size[ZONE_DMA] = total_lowmem >> PAGE_SHIFT; @@ -1128,7 +1081,6 @@ highmem_mapnr = total_lowmem >> PAGE_SHIFT; highmem_start_page = mem_map + highmem_mapnr; max_mapnr = total_memory >> PAGE_SHIFT; - totalram_pages += max_mapnr - highmem_mapnr; #else max_mapnr = max_low_pfn; #endif /* CONFIG_HIGHMEM */ @@ -1201,15 +1153,17 @@ #if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) /* - * Initialize the hash table and patch the instructions in head.S. + * Initialize the hash table and patch the instructions in hashtable.S. */ static void __init hash_init(void) { int Hash_bits, mb, mb2; unsigned int hmask, h; - extern unsigned int hash_page_patch_A[], hash_page_patch_B[], - hash_page_patch_C[], hash_page[]; + extern unsigned int hash_page_patch_A[]; + extern unsigned int hash_page_patch_B[], hash_page_patch_C[]; + extern unsigned int hash_page[]; + extern unsigned int flush_hash_patch_A[], flush_hash_patch_B[]; #ifdef CONFIG_PPC64BRIDGE /* The hash table has already been allocated and initialized @@ -1259,6 +1213,7 @@ if ( Hash_size ) { Hash = mem_pieces_find(Hash_size, Hash_size); cacheable_memzero(Hash, Hash_size); + _SDR1 = __pa(Hash) | (Hash_mask >> 10); } else Hash = 0; #endif /* CONFIG_PPC64BRIDGE */ @@ -1271,10 +1226,10 @@ Hash_end = (PTE *) ((unsigned long)Hash + Hash_size); /* - * Patch up the instructions in head.S:hash_page + * Patch up the instructions in hashtable.S:create_hpte */ hash_page_patch_A[0] = (hash_page_patch_A[0] & ~0xffff) - | (__pa(Hash) >> 16); + | ((unsigned int)(Hash) >> 16); hash_page_patch_A[1] = (hash_page_patch_A[1] & ~0x7c0) | (mb << 6); hash_page_patch_A[2] = (hash_page_patch_A[2] & ~0x7c0) @@ -1283,10 +1238,6 @@ | hmask; hash_page_patch_C[0] = (hash_page_patch_C[0] & ~0xffff) | hmask; -#if 0 /* see hash_page in head.S, note also patch_C ref below */ - hash_page_patch_D[0] = (hash_page_patch_D[0] & ~0xffff) - | hmask; -#endif /* * Ensure that the locations we've patched have been written * out from the data cache and invalidated in the instruction @@ -1294,6 +1245,19 @@ */ flush_icache_range((unsigned long) &hash_page_patch_A[0], (unsigned long) &hash_page_patch_C[1]); + /* + * Patch up the instructions in hashtable.S:flush_hash_page + */ + flush_hash_patch_A[0] = (flush_hash_patch_A[0] & ~0xffff) + | ((unsigned int)(Hash) >> 16); + flush_hash_patch_A[1] = (flush_hash_patch_A[1] & ~0x7c0) + | (mb << 6); + flush_hash_patch_A[2] = (flush_hash_patch_A[2] & ~0x7c0) + | (mb2 << 6); + flush_hash_patch_B[0] = (flush_hash_patch_B[0] & ~0xffff) + | hmask; + flush_icache_range((unsigned long) &flush_hash_patch_A[0], + (unsigned long) &flush_hash_patch_B[1]); } else { Hash_end = 0; @@ -1306,6 +1270,7 @@ flush_icache_range((unsigned long) &hash_page[0], (unsigned long) &hash_page[1]); } + if ( ppc_md.progress ) ppc_md.progress("hash:done", 0x205); } #endif /* !CONFIG_4xx && !CONFIG_8xx */ @@ -1320,7 +1285,7 @@ unsigned long kstart, ksize; /* - * Initially, available phyiscal memory is equivalent to all + * Initially, available physical memory is equivalent to all * physical memory. */ @@ -1356,4 +1321,51 @@ if (Hash) mem_pieces_remove(&phys_avail, __pa(Hash), Hash_size, 1); #endif /* CONFIG_PPC64BRIDGE */ +} + +void flush_page_to_ram(struct page *page) +{ + unsigned long vaddr = (unsigned long) kmap(page); + __flush_page_to_ram(vaddr); + kunmap(page); +} + +#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) +/* + * This is called at the end of handling a user page fault, when the + * 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. + */ +void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, + pte_t pte) +{ + struct mm_struct *mm; + pmd_t *pmd; + pte_t *ptep; + static int nopreload; + + if (Hash == 0 || nopreload) + return; + mm = (address < TASK_SIZE)? vma->vm_mm: &init_mm; + pmd = pmd_offset(pgd_offset(mm, address), address); + if (!pmd_none(*pmd)) { + ptep = pte_offset(pmd, address); + add_hash_page(mm->context, address, ptep); + } +} +#endif /* !4xx && !8xx */ + +/* + * set_pte stores a linux PTE into the linux page table. + * On machines which use an MMU hash table we avoid changing the + * _PAGE_HASHPTE bit. + */ +void set_pte(pte_t *ptep, pte_t pte) +{ +#if _PAGE_HASHPTE != 0 + pte_update(ptep, ~_PAGE_HASHPTE, pte_val(pte) & ~_PAGE_HASHPTE); +#else + *ptep = pte; +#endif } diff -u --recursive --new-file v2.4.5/linux/arch/ppc/vmlinux.lds linux/arch/ppc/vmlinux.lds --- v2.4.5/linux/arch/ppc/vmlinux.lds Fri Aug 4 11:23:37 2000 +++ linux/arch/ppc/vmlinux.lds Mon Jul 2 14:40:58 2001 @@ -39,6 +39,7 @@ .rodata : { *(.rodata) + *(.rodata.*) *(.rodata1) } .kstrtab : { *(.kstrtab) } diff -u --recursive --new-file v2.4.5/linux/arch/ppc/xmon/Makefile linux/arch/ppc/xmon/Makefile --- v2.4.5/linux/arch/ppc/xmon/Makefile Mon May 21 17:04:47 2001 +++ linux/arch/ppc/xmon/Makefile Mon Jul 2 14:34:57 2001 @@ -1,13 +1,14 @@ -# BK Id: SCCS/s.Makefile 1.3 05/17/01 18:14:23 cort +# BK Id: SCCS/s.Makefile 1.6 06/27/01 14:49:58 trini # # Makefile for xmon O_TARGET := x.o -ifeq ($(CONFIG_8xx),y) -obj-y := start_8xx.o xmon.o ppc-dis.o ppc-opc.o subr_prf.o setjmp.o +ifdef CONFIG_8xx +obj-y := start_8xx.o else -obj-y := start.o xmon.o ppc-dis.o ppc-opc.o subr_prf.o setjmp.o +obj-y := start.o endif +obj-y += xmon.o ppc-dis.o ppc-opc.o subr_prf.o setjmp.o include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.5/linux/arch/ppc/xmon/xmon.c linux/arch/ppc/xmon/xmon.c --- v2.4.5/linux/arch/ppc/xmon/xmon.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/xmon/xmon.c Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.xmon.c 1.9 05/17/01 18:14:24 cort + * BK Id: SCCS/s.xmon.c 1.14 06/28/01 15:50:17 paulus */ /* * Routines providing a simple monitor for use on the PowerMac. @@ -661,8 +661,7 @@ unsigned stack[2]; struct pt_regs regs; extern char ret_from_intercept, ret_from_syscall_1, ret_from_syscall_2; - extern char do_bottom_half_ret, do_signal_ret; - extern char ret_from_except; + extern char do_signal_ret, ret_from_except; printf("backtrace:\n"); @@ -680,7 +679,6 @@ || stack[1] == (unsigned) &ret_from_except || stack[1] == (unsigned) &ret_from_syscall_1 || stack[1] == (unsigned) &ret_from_syscall_2 - || stack[1] == (unsigned) &do_bottom_half_ret || stack[1] == (unsigned) &do_signal_ret) { if (mread(sp+16, ®s, sizeof(regs)) != sizeof(regs)) break; @@ -1019,7 +1017,8 @@ seg_end = (seg << 28) | 0x0ffff000; if (seg_end > hash_end) seg_end = hash_end; - dump_hash_table_seg((hash_ctx << 4) + seg, seg_start, seg_end); + dump_hash_table_seg((hash_ctx << 4) + (seg * 0x111), + seg_start, seg_end); seg_start = seg_end + 0x1000; } } diff -u --recursive --new-file v2.4.5/linux/arch/s390/vmlinux.lds linux/arch/s390/vmlinux.lds --- v2.4.5/linux/arch/s390/vmlinux.lds Tue Feb 13 14:13:44 2001 +++ linux/arch/s390/vmlinux.lds Mon Jul 2 14:40:58 2001 @@ -14,7 +14,7 @@ *(.gnu.warning) } = 0x0700 .text.lock : { *(.text.lock) } /* out-of-line lock text */ - .rodata : { *(.rodata) } + .rodata : { *(.rodata) *(.rodata.*) } .kstrtab : { *(.kstrtab) } . = ALIGN(16); /* Exception table */ diff -u --recursive --new-file v2.4.5/linux/arch/s390x/vmlinux.lds linux/arch/s390x/vmlinux.lds --- v2.4.5/linux/arch/s390x/vmlinux.lds Wed Apr 11 19:02:29 2001 +++ linux/arch/s390x/vmlinux.lds Mon Jul 2 14:40:58 2001 @@ -14,7 +14,7 @@ *(.gnu.warning) } = 0x0700 .text.lock : { *(.text.lock) } /* out-of-line lock text */ - .rodata : { *(.rodata) } + .rodata : { *(.rodata) *(.rodata.*) } .kstrtab : { *(.kstrtab) } . = ALIGN(16); /* Exception table */ diff -u --recursive --new-file v2.4.5/linux/arch/sh/config.in linux/arch/sh/config.in --- v2.4.5/linux/arch/sh/config.in Tue Apr 17 17:19:25 2001 +++ linux/arch/sh/config.in Wed Jun 27 13:55:29 2001 @@ -29,7 +29,9 @@ choice 'SuperH system type' \ "Generic CONFIG_SH_GENERIC \ SolutionEngine CONFIG_SH_SOLUTION_ENGINE \ - Overdrive CONFIG_SH_OVERDRIVE \ + SolutionEngine7751 CONFIG_SH_7751_SOLUTION_ENGINE \ + STB1_Harp CONFIG_SH_STB1_HARP \ + STB1_Overdrive CONFIG_SH_STB1_OVERDRIVE \ HP620 CONFIG_SH_HP620 \ HP680 CONFIG_SH_HP680 \ HP690 CONFIG_SH_HP690 \ @@ -37,9 +39,17 @@ DMIDA CONFIG_SH_DMIDA \ EC3104 CONFIG_SH_EC3104 \ Dreamcast CONFIG_SH_DREAMCAST \ + CAT68701 CONFIG_SH_CAT68701 \ + BigSur CONFIG_SH_BIGSUR \ + SH2000 CONFIG_SH_SH2000 \ BareCPU CONFIG_SH_UNKNOWN" Generic -define_bool CONFIG_SH_RTC y +# The SH7750 RTC module is disabled in the Dreamcast +if [ "$CONFIG_SH_DREAMCAST" = "y" ]; then + define_bool CONFIG_SH_RTC n +else + define_bool CONFIG_SH_RTC y +fi if [ "$CONFIG_SH_HP620" = "y" -o "$CONFIG_SH_HP680" = "y" -o \ "$CONFIG_SH_HP690" = "y" ]; then @@ -50,7 +60,9 @@ "SH7707 CONFIG_CPU_SUBTYPE_SH7707 \ SH7708 CONFIG_CPU_SUBTYPE_SH7708 \ SH7709 CONFIG_CPU_SUBTYPE_SH7709 \ - SH7750 CONFIG_CPU_SUBTYPE_SH7750" SH7708 + SH7750 CONFIG_CPU_SUBTYPE_SH7750 \ + SH7751 CONFIG_CPU_SUBTYPE_SH7751 \ + ST40STB1 CONFIG_CPU_SUBTYPE_ST40STB1" SH7708 if [ "$CONFIG_CPU_SUBTYPE_SH7707" = "y" ]; then define_bool CONFIG_CPU_SH3 y define_bool CONFIG_CPU_SH4 n @@ -67,12 +79,30 @@ define_bool CONFIG_CPU_SH3 n define_bool CONFIG_CPU_SH4 y fi +if [ "$CONFIG_CPU_SUBTYPE_SH7751" = "y" ]; then + define_bool CONFIG_CPU_SH3 n + define_bool CONFIG_CPU_SH4 y +fi +if [ "$CONFIG_CPU_SUBTYPE_ST40STB1" = "y" ]; then + define_bool CONFIG_CPU_SH3 n + define_bool CONFIG_CPU_SH4 y +fi bool 'Little Endian' CONFIG_CPU_LITTLE_ENDIAN if [ "$CONFIG_SH_SOLUTION_ENGINE" = "y" -o "$CONFIG_SH_HP600" = "y" -o \ - "$CONFIG_SH_OVERDRIVE" = "y" ]; then + "$CONFIG_SH_BIGSUR" = "y" -o "$CONFIG_SH_7751_SOLUTION_ENGINE" = "y" -o \ + "$CONFIG_SH_DREAMCAST" = "y" -o "$CONFIG_SH_SH2000" = "y" ]; then define_hex CONFIG_MEMORY_START 0c000000 else - hex 'Physical memory start address' CONFIG_MEMORY_START 08000000 + if [ "$CONFIG_CPU_SUBTYPE_ST40STB1" = "y" ]; then + bool 'Memory on LMI' CONFIG_ST40_LMI_MEMORY + if [ "$CONFIG_ST40_LMI_MEMORY" = "y" ] ; then + define_hex CONFIG_MEMORY_START 08000000 + else + hex 'EMI physical memory start address' CONFIG_MEMORY_START 08000000 + fi + else + hex 'Physical memory start address' CONFIG_MEMORY_START 08000000 + fi fi endmenu @@ -89,7 +119,8 @@ bool 'Networking support' CONFIG_NET -if [ "$CONFIG_SH_GENERIC" = "y" -o "$CONFIG_SH_SOLUTION_ENGINE" = "y" -o "$CONFIG_SH_UNKNOWN" = "y" ]; then +if [ "$CONFIG_SH_GENERIC" = "y" -o "$CONFIG_SH_SOLUTION_ENGINE" = "y" -o \ + "$CONFIG_SH_UNKNOWN" = "y" -o "$CONFIG_SH_CAT68701" = "y" ]; then bool 'Compact Flash Enabler support' CONFIG_CF_ENABLER fi @@ -101,6 +132,7 @@ bool 'Hitachi HD64465 companion chip support' CONFIG_HD64465 if [ "$CONFIG_HD64465" = "y" ]; then + hex 'HD64465 start address' CONFIG_HD64465_IOBASE b0000000 int 'HD64465 IRQ' CONFIG_HD64465_IRQ 5 fi @@ -197,6 +229,10 @@ # source drivers/input/Config.in +if [ "$CONFIG_SH_DREAMCAST" = "y" ]; then +source drivers/maple/Config.in +fi + mainmenu_option next_comment comment 'Character devices' @@ -217,10 +253,29 @@ fi if [ "$CONFIG_SH_GENERIC" = "y" -o \ - "$CONFIG_SH_OVERDRIVE" = "y" -o "$CONFIG_SH_SOLUTION_ENGINE" = "y" ]; then + "$CONFIG_SH_CAT68701" = "y" -o \ + "$CONFIG_SH_STB1_HARP" = "y" -o \ + "$CONFIG_SH_STB1_OVERDRIVE" = "y" -o \ + "$CONFIG_SH_BIGSUR" = "y" -o \ + "$CONFIG_SH_7751_SOLUTION_ENGINE" = "y" -o \ + "$CONFIG_SH_SOLUTION_ENGINE" = "y" ]; then bool 'Heartbeat LED' CONFIG_HEARTBEAT fi +if [ "$CONFIG_SH_DREAMCAST" = "y" -a "$CONFIG_MAPLE" != "n" ]; then + mainmenu_option next_comment + comment 'Maple Bus input peripherals' + if [ "$CONFIG_INPUT" != "n" ]; then + dep_tristate ' Maple Bus keyboard support' CONFIG_MAPLE_KEYBOARD $CONFIG_INPUT + dep_tristate ' Maple Bus mouse support' CONFIG_MAPLE_MOUSE $CONFIG_INPUT + else + comment 'Input core support is required for Maple input peripherals' + fi + endmenu +fi + +source drivers/char/joystick/Config.in + if [ "$CONFIG_PARPORT" != "n" ]; then dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT if [ "$CONFIG_PRINTER" != "n" ]; then @@ -228,13 +283,16 @@ fi dep_tristate 'Support for user-space parallel port device drivers' CONFIG_PPDEV $CONFIG_PARPORT fi -endmenu - +bool 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE +tristate 'Enhanced Real Time Clock Support' CONFIG_RTC if [ "$CONFIG_HOTPLUG" = "y" -a "$CONFIG_PCMCIA" != "n" ]; then source drivers/char/pcmcia/Config.in fi +endmenu source fs/Config.in + +source drivers/media/Config.in if [ "$CONFIG_VT" = "y" ]; then mainmenu_option next_comment diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/Makefile linux/arch/sh/kernel/Makefile --- v2.4.5/linux/arch/sh/kernel/Makefile Wed Apr 11 21:24:52 2001 +++ linux/arch/sh/kernel/Makefile Wed Jun 27 13:55:29 2001 @@ -24,8 +24,15 @@ obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o ifeq ($(CONFIG_PCI),y) -obj-y += pci-sh.o +ifeq ($(CONFIG_SH_DREAMCAST),y) +obj-y += pci-dc.o +else +obj-y += pci-dma.o obj-$(CONFIG_CPU_SUBTYPE_ST40STB1)+= pci_st40.o +obj-$(CONFIG_CPU_SUBTYPE_SH7751)+= pci-sh7751.o +obj-$(CONFIG_SH_BIGSUR)+= pci-bigsur.o +obj-$(CONFIG_SH_7751_SOLUTION_ENGINE)+= pci-7751se.o +endif endif obj-$(CONFIG_SH_HP600) += mach_hp600.o @@ -33,6 +40,15 @@ obj-$(CONFIG_SH_SOLUTION_ENGINE)+= mach_se.o setup_se.o io_se.o led_se.o machine-specific-objs += mach_se.o setup_se.o io_se.o led_se.o + +obj-$(CONFIG_SH_7751_SOLUTION_ENGINE)+= mach_se.o setup_se.o io_se.o led_se.o pci-7751se.o +machine-specific-objs += mach_se.o setup_se.o io_se.o led_se.o pci-7751se.o + +obj-$(CONFIG_SH_BIGSUR) += mach_bigsur.o setup_bigsur.o io_bigsur.o led_bigsur.o +machine-specific-objs += mach_bigsur.o setup_bigsur.o io_bigsur.o led_bigsur.o + +obj-$(CONFIG_SH_SH2000) += setup_sh2000.o io_sh2000.o +machine-specific-objs += setup_sh2000.o io_sh2000.o obj-$(CONFIG_SH_CAT68701) += mach_cat68701.o io_cat68701.o machine-specific-objs += mach_cat68701.o io_cat68701.o diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/entry.S linux/arch/sh/kernel/entry.S --- v2.4.5/linux/arch/sh/kernel/entry.S Wed Apr 11 21:24:52 2001 +++ linux/arch/sh/kernel/entry.S Wed Jun 27 13:55:29 2001 @@ -489,8 +489,9 @@ __syscall_ret_trace: .long syscall_ret_trace __syscall_ret: - .long SYMBOL_NAME(syscall_ret) - + .long syscall_ret +__INV_IMASK: + .long 0xffffff0f ! ~(IMASK) .align 2 @@ -502,30 +503,16 @@ .align 2 1: .long SYMBOL_NAME(schedule) -ENTRY(ret_from_irq) - mov #OFF_SR, r0 - mov.l @(r0,r15), r0 ! get status register - shll r0 - shll r0 ! kernel space? - bt restore_all ! Yes, it's from kernel, go back soon - ! - STI() - bra ret_with_reschedule - nop - -ENTRY(ret_from_exception) +ret_from_irq: +ret_from_exception: mov #OFF_SR, r0 mov.l @(r0,r15), r0 ! get status register shll r0 shll r0 ! kernel space? bt restore_all ! Yes, it's from kernel, go back soon ! - STI() bra ret_from_syscall nop - .align 2 -__INV_IMASK: - .long 0xffffff0f ! ~(IMASK) .align 2 #ifdef COMPAT_OLD_SYSCALL_ABI @@ -538,16 +525,11 @@ /* fall through */ ENTRY(ret_from_syscall) - mov.l __irq_stat, r0 ! softirq_active - mov.l @r0, r1 - mov.l @(4,r0), r2 ! softirq_mask - tst r2, r1 - bt ret_with_reschedule -handle_softirq: - mov.l __do_softirq, r0 - jsr @r0 - nop -ret_with_reschedule: + /* CLI */ + stc sr, r0 + or #0xf0, r0 + ldc r0, sr + ! stc k_current, r1 mov.l @(need_resched,r1), r0 tst r0, r0 @@ -567,8 +549,6 @@ .long SYMBOL_NAME(do_signal) __irq_stat: .long SYMBOL_NAME(irq_stat) -__do_softirq: - .long SYMBOL_NAME(do_softirq) .align 2 restore_all: @@ -707,7 +687,7 @@ bra handle_exception mov.l @k2, k2 .align 2 -2: .long SYMBOL_NAME(ret_from_exception) +2: .long ret_from_exception 1: .long EXPEVT ! ! @@ -728,8 +708,8 @@ .align 2 1: .long EXPEVT 2: .long INTEVT -3: .long SYMBOL_NAME(ret_from_irq) -4: .long SYMBOL_NAME(ret_from_exception) +3: .long ret_from_irq +4: .long ret_from_exception ! ! @@ -941,24 +921,143 @@ .long SYMBOL_NAME(do_IRQ) ! 63 pcc1i #endif #elif defined(__SH4__) - .long SYMBOL_NAME(do_IRQ) ! Hitachi UDI - .long SYMBOL_NAME(do_IRQ) ! GPIO - .long SYMBOL_NAME(do_IRQ) ! DMAC dmte0 - .long SYMBOL_NAME(do_IRQ) ! dmte1 - .long SYMBOL_NAME(do_IRQ) ! dmte2 - .long SYMBOL_NAME(do_IRQ) ! dmte3 - .long SYMBOL_NAME(do_IRQ) ! dmae - .long SYMBOL_NAME(do_IRQ) - .long SYMBOL_NAME(do_IRQ) ! SCIF eri - .long SYMBOL_NAME(do_IRQ) ! rxi - .long SYMBOL_NAME(do_IRQ) ! bri - .long SYMBOL_NAME(do_IRQ) ! txi + .long SYMBOL_NAME(do_IRQ) ! 32 Hitachi UDI + .long SYMBOL_NAME(do_IRQ) ! 33 GPIO + .long SYMBOL_NAME(do_IRQ) ! 34 DMAC dmte0 + .long SYMBOL_NAME(do_IRQ) ! 35 dmte1 + .long SYMBOL_NAME(do_IRQ) ! 36 dmte2 + .long SYMBOL_NAME(do_IRQ) ! 37 dmte3 + .long SYMBOL_NAME(do_IRQ) ! 38 dmae + .long error ! 39 + .long SYMBOL_NAME(do_IRQ) ! 40 SCIF eri + .long SYMBOL_NAME(do_IRQ) ! 41 rxi + .long SYMBOL_NAME(do_IRQ) ! 42 bri + .long SYMBOL_NAME(do_IRQ) ! 43 txi + .long error ! 44 + .long error ! 45 + .long error ! 46 + .long error ! 47 + .long SYMBOL_NAME(do_fpu_state_restore) ! 48 + .long SYMBOL_NAME(do_fpu_state_restore) ! 49 +#endif +#if defined(CONFIG_CPU_SUBTYPE_SH7751) + .long error + .long error + .long error + .long error + .long error + .long error + .long error + .long error + .long error + .long error .long error .long error .long error .long error - .long SYMBOL_NAME(do_fpu_state_restore) - .long SYMBOL_NAME(do_fpu_state_restore) + .long SYMBOL_NAME(do_IRQ) ! PCI serr + .long SYMBOL_NAME(do_IRQ) ! dma3 + .long SYMBOL_NAME(do_IRQ) ! dma2 + .long SYMBOL_NAME(do_IRQ) ! dma1 + .long SYMBOL_NAME(do_IRQ) ! dma0 + .long SYMBOL_NAME(do_IRQ) ! pwon + .long SYMBOL_NAME(do_IRQ) ! pwdwn + .long SYMBOL_NAME(do_IRQ) ! err +#elif defined(CONFIG_CPU_SUBTYPE_ST40STB1) + .long error ! 50 0x840 + .long error ! 51 0x860 + .long error ! 52 0x880 + .long error ! 53 0x8a0 + .long error ! 54 0x8c0 + .long error ! 55 0x8e0 + .long error ! 56 0x900 + .long error ! 57 0x920 + .long error ! 58 0x940 + .long error ! 59 0x960 + .long error ! 60 0x980 + .long error ! 61 0x9a0 + .long error ! 62 0x9c0 + .long error ! 63 0x9e0 + .long SYMBOL_NAME(do_IRQ) ! 64 0xa00 PCI serr + .long SYMBOL_NAME(do_IRQ) ! 65 0xa20 err + .long SYMBOL_NAME(do_IRQ) ! 66 0xa40 ad + .long SYMBOL_NAME(do_IRQ) ! 67 0xa60 pwr_dwn + .long error ! 68 0xa80 + .long error ! 69 0xaa0 + .long error ! 70 0xac0 + .long error ! 71 0xae0 + .long SYMBOL_NAME(do_IRQ) ! 72 0xb00 DMA INT0 + .long SYMBOL_NAME(do_IRQ) ! 73 0xb20 INT1 + .long SYMBOL_NAME(do_IRQ) ! 74 0xb40 INT2 + .long SYMBOL_NAME(do_IRQ) ! 75 0xb60 INT3 + .long SYMBOL_NAME(do_IRQ) ! 76 0xb80 INT4 + .long error ! 77 0xba0 + .long SYMBOL_NAME(do_IRQ) ! 78 0xbc0 DMA ERR + .long error ! 79 0xbe0 + .long SYMBOL_NAME(do_IRQ) ! 80 0xc00 PIO0 + .long SYMBOL_NAME(do_IRQ) ! 81 0xc20 PIO1 + .long SYMBOL_NAME(do_IRQ) ! 82 0xc40 PIO2 + .long error ! 83 0xc60 + .long error ! 84 0xc80 + .long error ! 85 0xca0 + .long error ! 86 0xcc0 + .long error ! 87 0xce0 + .long error ! 88 0xd00 + .long error ! 89 0xd20 + .long error ! 90 0xd40 + .long error ! 91 0xd60 + .long error ! 92 0xd80 + .long error ! 93 0xda0 + .long error ! 94 0xdc0 + .long error ! 95 0xde0 + .long error ! 96 0xe00 + .long error ! 97 0xe20 + .long error ! 98 0xe40 + .long error ! 99 0xe60 + .long error ! 100 0xe80 + .long error ! 101 0xea0 + .long error ! 102 0xec0 + .long error ! 103 0xee0 + .long error ! 104 0xf00 + .long error ! 105 0xf20 + .long error ! 106 0xf40 + .long error ! 107 0xf60 + .long error ! 108 0xf80 + .long error ! 109 0xfa0 + .long error ! 110 0xfc0 + .long error ! 111 0xfe0 + .long SYMBOL_NAME(do_IRQ) ! 112 0x1000 Mailbox + .long error ! 113 0x1020 + .long error ! 114 0x1040 + .long error ! 115 0x1060 + .long error ! 116 0x1080 + .long error ! 117 0x10a0 + .long error ! 118 0x10c0 + .long error ! 119 0x10e0 + .long error ! 120 0x1100 + .long error ! 121 0x1120 + .long error ! 122 0x1140 + .long error ! 123 0x1160 + .long error ! 124 0x1180 + .long error ! 125 0x11a0 + .long error ! 126 0x11c0 + .long error ! 127 0x11e0 + .long error ! 128 0x1200 + .long error ! 129 0x1220 + .long error ! 130 0x1240 + .long error ! 131 0x1260 + .long error ! 132 0x1280 + .long error ! 133 0x12a0 + .long error ! 134 0x12c0 + .long error ! 135 0x12e0 + .long error ! 136 0x1300 + .long error ! 137 0x1320 + .long error ! 138 0x1340 + .long error ! 139 0x1360 + .long SYMBOL_NAME(do_IRQ) ! 140 0x1380 EMPI INV_ADDR + .long error ! 141 0x13a0 + .long error ! 142 0x13c0 + .long error ! 143 0x13e0 #endif ENTRY(sys_call_table) diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/hd64465_gpio.c linux/arch/sh/kernel/hd64465_gpio.c --- v2.4.5/linux/arch/sh/kernel/hd64465_gpio.c Sun May 20 12:11:38 2001 +++ linux/arch/sh/kernel/hd64465_gpio.c Wed Jun 27 13:55:29 2001 @@ -1,5 +1,5 @@ /* - * $Id: hd64465_gpio.c,v 1.1 2001/01/02 15:35:22 mjd Exp $ + * $Id: hd64465_gpio.c,v 1.2 2001/05/24 00:13:47 gniibe Exp $ * by Greg Banks * (c) 2000 PocketPenguins Inc * diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/io_bigsur.c linux/arch/sh/kernel/io_bigsur.c --- v2.4.5/linux/arch/sh/kernel/io_bigsur.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/io_bigsur.c Wed Jun 27 13:55:29 2001 @@ -0,0 +1,249 @@ +/* + * include/asm-sh/io_bigsur.c + * + * By Dustin McIntire (dustin@sensoria.com) (c)2001 + * Derived from io_hd64465.h, which bore the message: + * By Greg Banks + * (c) 2000 PocketPenguins Inc. + * and from io_hd64461.h, which bore the message: + * Copyright 2000 Stuart Menefy (stuart.menefy@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * IO functions for a Hitachi Big Sur Evaluation Board. + */ + +#include +#include +#include +#include +#include +#include + +//#define BIGSUR_DEBUG 2 +#undef BIGSUR_DEBUG + +#ifdef BIGSUR_DEBUG +#define DPRINTK(args...) printk(args) +#define DIPRINTK(n, args...) if (BIGSUR_DEBUG>(n)) printk(args) +#else +#define DPRINTK(args...) +#define DIPRINTK(n, args...) +#endif + + +/* Low iomap maps port 0-1K to addresses in 8byte chunks */ +#define BIGSUR_IOMAP_LO_THRESH 0x400 +#define BIGSUR_IOMAP_LO_SHIFT 3 +#define BIGSUR_IOMAP_LO_MASK ((1<>BIGSUR_IOMAP_LO_SHIFT) +static u32 bigsur_iomap_lo[BIGSUR_IOMAP_LO_NMAP]; +static u8 bigsur_iomap_lo_shift[BIGSUR_IOMAP_LO_NMAP]; + +/* High iomap maps port 1K-64K to addresses in 1K chunks */ +#define BIGSUR_IOMAP_HI_THRESH 0x10000 +#define BIGSUR_IOMAP_HI_SHIFT 10 +#define BIGSUR_IOMAP_HI_MASK ((1<>BIGSUR_IOMAP_HI_SHIFT) +static u32 bigsur_iomap_hi[BIGSUR_IOMAP_HI_NMAP]; +static u8 bigsur_iomap_hi_shift[BIGSUR_IOMAP_HI_NMAP]; + +#ifndef MAX +#define MAX(a,b) ((a)>(b)?(a):(b)) +#endif + +#define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x)) + +void bigsur_port_map(u32 baseport, u32 nports, u32 addr, u8 shift) +{ + u32 port, endport = baseport + nports; + + DPRINTK("bigsur_port_map(base=0x%0x, n=0x%0x, addr=0x%08x)\n", + baseport, nports, addr); + + for (port = baseport ; + port < endport && port < BIGSUR_IOMAP_LO_THRESH ; + port += (1<>BIGSUR_IOMAP_LO_SHIFT] = addr; + bigsur_iomap_lo_shift[port>>BIGSUR_IOMAP_LO_SHIFT] = shift; + addr += (1<<(BIGSUR_IOMAP_LO_SHIFT)); + } + + for (port = MAX(baseport, BIGSUR_IOMAP_LO_THRESH) ; + port < endport && port < BIGSUR_IOMAP_HI_THRESH ; + port += (1<>BIGSUR_IOMAP_HI_SHIFT] = addr; + bigsur_iomap_hi_shift[port>>BIGSUR_IOMAP_HI_SHIFT] = shift; + addr += (1<<(BIGSUR_IOMAP_HI_SHIFT)); + } +} +EXPORT_SYMBOL(bigsur_port_map); + +void bigsur_port_unmap(u32 baseport, u32 nports) +{ + u32 port, endport = baseport + nports; + + DPRINTK("bigsur_port_unmap(base=0x%0x, n=0x%0x)\n", baseport, nports); + + for (port = baseport ; + port < endport && port < BIGSUR_IOMAP_LO_THRESH ; + port += (1<>BIGSUR_IOMAP_LO_SHIFT] = 0; + } + + for (port = MAX(baseport, BIGSUR_IOMAP_LO_THRESH) ; + port < endport && port < BIGSUR_IOMAP_HI_THRESH ; + port += (1<>BIGSUR_IOMAP_HI_SHIFT] = 0; + } +} +EXPORT_SYMBOL(bigsur_port_unmap); + +unsigned long bigsur_isa_port2addr(unsigned long port) +{ + unsigned long addr = 0; + unsigned char shift; + + /* Physical address not in P0, do nothing */ + if (PXSEG(port)) addr = port; + /* physical address in P0, map to P2 */ + else if (port >= 0x30000) + addr = P2SEGADDR(port); + /* Big Sur I/O + HD64465 registers 0x10000-0x30000 */ + else if (port >= BIGSUR_IOMAP_HI_THRESH) + addr = BIGSUR_INTERNAL_BASE + (port - BIGSUR_IOMAP_HI_THRESH); + /* Handle remapping of high IO/PCI IO ports */ + else if (port >= BIGSUR_IOMAP_LO_THRESH) { + addr = bigsur_iomap_hi[port >> BIGSUR_IOMAP_HI_SHIFT]; + shift = bigsur_iomap_hi_shift[port >> BIGSUR_IOMAP_HI_SHIFT]; + if (addr != 0) + addr += (port & BIGSUR_IOMAP_HI_MASK) << shift; + } + /* Handle remapping of low IO ports */ + else { + addr = bigsur_iomap_lo[port >> BIGSUR_IOMAP_LO_SHIFT]; + shift = bigsur_iomap_lo_shift[port >> BIGSUR_IOMAP_LO_SHIFT]; + if (addr != 0) + addr += (port & BIGSUR_IOMAP_LO_MASK) << shift; + } + + DIPRINTK(2, "PORT2ADDR(0x%08lx) = 0x%08lx\n", port, addr); + + return addr; +} + +static inline void delay(void) +{ + ctrl_inw(0xa0000000); +} + +unsigned char bigsur_inb(unsigned long port) +{ + unsigned long addr = PORT2ADDR(port); + unsigned long b = (addr == 0 ? 0 : *(volatile unsigned char*)addr); + + DIPRINTK(0, "inb(%08lx) = %02x\n", addr, (unsigned)b); + return b; +} + +unsigned char bigsur_inb_p(unsigned long port) +{ + unsigned long v; + unsigned long addr = PORT2ADDR(port); + + v = (addr == 0 ? 0 : *(volatile unsigned char*)addr); + delay(); + DIPRINTK(0, "inb_p(%08lx) = %02x\n", addr, (unsigned)v); + return v; +} + +unsigned short bigsur_inw(unsigned long port) +{ + unsigned long addr = PORT2ADDR(port); + unsigned long b = (addr == 0 ? 0 : *(volatile unsigned short*)addr); + DIPRINTK(0, "inw(%08lx) = %04lx\n", addr, b); + return b; +} + +unsigned int bigsur_inl(unsigned long port) +{ + unsigned long addr = PORT2ADDR(port); + unsigned int b = (addr == 0 ? 0 : *(volatile unsigned long*)addr); + DIPRINTK(0, "inl(%08lx) = %08x\n", addr, b); + return b; +} + +void bigsur_insb(unsigned long port, void *buffer, unsigned long count) +{ + unsigned char *buf=buffer; + while(count--) *buf++=inb(port); +} + +void bigsur_insw(unsigned long port, void *buffer, unsigned long count) +{ + unsigned short *buf=buffer; + while(count--) *buf++=inw(port); +} + +void bigsur_insl(unsigned long port, void *buffer, unsigned long count) +{ + unsigned long *buf=buffer; + while(count--) *buf++=inl(port); +} + +void bigsur_outb(unsigned char b, unsigned long port) +{ + unsigned long addr = PORT2ADDR(port); + + DIPRINTK(0, "outb(%02x, %08lx)\n", (unsigned)b, addr); + if (addr != 0) + *(volatile unsigned char*)addr = b; +} + +void bigsur_outb_p(unsigned char b, unsigned long port) +{ + unsigned long addr = PORT2ADDR(port); + + DIPRINTK(0, "outb_p(%02x, %08lx)\n", (unsigned)b, addr); + if (addr != 0) + *(volatile unsigned char*)addr = b; + delay(); +} + +void bigsur_outw(unsigned short b, unsigned long port) +{ + unsigned long addr = PORT2ADDR(port); + DIPRINTK(0, "outw(%04x, %08lx)\n", (unsigned)b, addr); + if (addr != 0) + *(volatile unsigned short*)addr = b; +} + +void bigsur_outl(unsigned int b, unsigned long port) +{ + unsigned long addr = PORT2ADDR(port); + DIPRINTK(0, "outl(%08x, %08lx)\n", b, addr); + if (addr != 0) + *(volatile unsigned long*)addr = b; +} + +void bigsur_outsb(unsigned long port, const void *buffer, unsigned long count) +{ + const unsigned char *buf=buffer; + while(count--) outb(*buf++, port); +} + +void bigsur_outsw(unsigned long port, const void *buffer, unsigned long count) +{ + const unsigned short *buf=buffer; + while(count--) outw(*buf++, port); +} + +void bigsur_outsl(unsigned long port, const void *buffer, unsigned long count) +{ + const unsigned long *buf=buffer; + while(count--) outl(*buf++, port); +} + diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/io_dc.c linux/arch/sh/kernel/io_dc.c --- v2.4.5/linux/arch/sh/kernel/io_dc.c Sun May 20 12:11:38 2001 +++ linux/arch/sh/kernel/io_dc.c Wed Jun 27 13:55:29 2001 @@ -1,5 +1,5 @@ /* - * $Id: io_dc.c,v 1.1 2001/04/01 15:02:00 yaegashi Exp $ + * $Id: io_dc.c,v 1.2 2001/05/24 00:13:47 gniibe Exp $ * I/O routines for SEGA Dreamcast */ diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/io_hd64465.c linux/arch/sh/kernel/io_hd64465.c --- v2.4.5/linux/arch/sh/kernel/io_hd64465.c Wed Apr 11 21:24:52 2001 +++ linux/arch/sh/kernel/io_hd64465.c Wed Jun 27 13:55:29 2001 @@ -1,5 +1,5 @@ /* - * $Id: io_hd64465.c,v 1.6 2001/02/15 09:13:51 dave_mckay Exp $ + * $Id: io_hd64465.c,v 1.7 2001/05/09 07:39:36 gniibe Exp $ * by Greg Banks * (c) 2000 PocketPenguins Inc * @@ -52,6 +52,8 @@ #define MAX(a,b) ((a)>(b)?(a):(b)) #endif +#define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x)) + void hd64465_port_map(unsigned short baseport, unsigned int nports, unsigned long addr, unsigned char shift) { @@ -101,7 +103,7 @@ } EXPORT_SYMBOL(hd64465_port_unmap); -static /*__inline__*/ unsigned long PORT2ADDR(unsigned long port) +unsigned long hd64465_isa_port2addr(unsigned long port) { unsigned long addr = 0; unsigned char shift; diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/io_sh2000.c linux/arch/sh/kernel/io_sh2000.c --- v2.4.5/linux/arch/sh/kernel/io_sh2000.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/io_sh2000.c Wed Jun 27 13:55:29 2001 @@ -0,0 +1,19 @@ +/* + * I/O routine for SH-2000 + */ +#include +#include +#include + +#define IDE_OFFSET 0xb6200000 +#define NIC_OFFSET 0xb6000000 +#define EXTBUS_OFFSET 0xba000000 + +unsigned long sh2000_isa_port2addr(unsigned long offset) +{ + if((offset & ~7) == 0x1f0 || offset == 0x3f6) + return IDE_OFFSET + offset; + else if((offset & ~0x1f) == 0x300) + return NIC_OFFSET + offset; + return EXTBUS_OFFSET + offset; +} diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/irq.c linux/arch/sh/kernel/irq.c --- v2.4.5/linux/arch/sh/kernel/irq.c Fri Feb 9 11:29:44 2001 +++ linux/arch/sh/kernel/irq.c Wed Jun 27 13:55:29 2001 @@ -38,12 +38,6 @@ #include /* - * Micro-access to controllers is serialized over the whole - * system. We never hold this lock when we call the actual - * IRQ handler. - */ -spinlock_t irq_controller_lock = SPIN_LOCK_UNLOCKED; -/* * Controller mappings for all interrupt sources: */ irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = @@ -160,14 +154,15 @@ */ void disable_irq_nosync(unsigned int irq) { + irq_desc_t *desc = irq_desc + irq; unsigned long flags; - spin_lock_irqsave(&irq_controller_lock, flags); - if (!irq_desc[irq].depth++) { - irq_desc[irq].status |= IRQ_DISABLED; - irq_desc[irq].handler->disable(irq); + spin_lock_irqsave(&desc->lock, flags); + if (!desc->depth++) { + desc->status |= IRQ_DISABLED; + desc->handler->disable(irq); } - spin_unlock_irqrestore(&irq_controller_lock, flags); + spin_unlock_irqrestore(&desc->lock, flags); } /* @@ -187,28 +182,29 @@ void enable_irq(unsigned int irq) { + irq_desc_t *desc = irq_desc + irq; unsigned long flags; - spin_lock_irqsave(&irq_controller_lock, flags); - switch (irq_desc[irq].depth) { + spin_lock_irqsave(&desc->lock, flags); + switch (desc->depth) { case 1: { - unsigned int status = irq_desc[irq].status & ~IRQ_DISABLED; - irq_desc[irq].status = status; + unsigned int status = desc->status & ~IRQ_DISABLED; + desc->status = status; if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { - irq_desc[irq].status = status | IRQ_REPLAY; - hw_resend_irq(irq_desc[irq].handler,irq); + desc->status = status | IRQ_REPLAY; + hw_resend_irq(desc->handler,irq); } - irq_desc[irq].handler->enable(irq); + desc->handler->enable(irq); /* fall-through */ } default: - irq_desc[irq].depth--; + desc->depth--; break; case 0: printk("enable_irq() unbalanced from %p\n", __builtin_return_address(0)); } - spin_unlock_irqrestore(&irq_controller_lock, flags); + spin_unlock_irqrestore(&desc->lock, flags); } /* @@ -245,7 +241,7 @@ kstat.irqs[cpu][irq]++; desc = irq_desc + irq; - spin_lock(&irq_controller_lock); + spin_lock(&desc->lock); desc->handler->ack(irq); /* REPLAY is when Linux resends an IRQ that was dropped earlier @@ -265,7 +261,6 @@ status |= IRQ_INPROGRESS; /* we are handling it */ } desc->status = status; - spin_unlock(&irq_controller_lock); /* * If there is no IRQ handler or it was disabled, exit early. @@ -274,7 +269,7 @@ will take care of it. */ if (!action) - return 1; + goto out; /* * Edge triggered interrupts need to remember @@ -287,23 +282,24 @@ * SMP environment. */ for (;;) { + spin_unlock(&desc->lock); handle_IRQ_event(irq, ®s, action); - spin_lock(&irq_controller_lock); + spin_lock(&desc->lock); if (!(desc->status & IRQ_PENDING)) break; desc->status &= ~IRQ_PENDING; - spin_unlock(&irq_controller_lock); } desc->status &= ~IRQ_INPROGRESS; - if (!(desc->status & IRQ_DISABLED)) - desc->handler->end(irq); - spin_unlock(&irq_controller_lock); +out: + /* + * The ->end() handler has to deal with interrupts which got + * disabled while the handler was running. + */ + desc->handler->end(irq); + spin_unlock(&desc->lock); -#if 0 - __sti(); -#endif - if (softirq_active(cpu)&softirq_mask(cpu)) + if (softirq_pending(cpu)) do_softirq(); return 1; } @@ -342,14 +338,16 @@ void free_irq(unsigned int irq, void *dev_id) { + irq_desc_t *desc; struct irqaction **p; unsigned long flags; if (irq >= ACTUAL_NR_IRQS) return; - spin_lock_irqsave(&irq_controller_lock,flags); - p = &irq_desc[irq].action; + desc = irq_desc + irq; + spin_lock_irqsave(&desc->lock,flags); + p = &desc->action; for (;;) { struct irqaction * action = *p; if (action) { @@ -360,20 +358,22 @@ /* Found it - now remove it from the list of entries */ *pp = action->next; - if (!irq_desc[irq].action) { - irq_desc[irq].status |= IRQ_DISABLED; - irq_desc[irq].handler->shutdown(irq); + if (!desc->action) { + desc->status |= IRQ_DISABLED; + desc->handler->shutdown(irq); } - spin_unlock_irqrestore(&irq_controller_lock,flags); + spin_unlock_irqrestore(&desc->lock,flags); kfree(action); return; } printk("Trying to free free IRQ%d\n",irq); - spin_unlock_irqrestore(&irq_controller_lock,flags); + spin_unlock_irqrestore(&desc->lock,flags); return; } } +static DECLARE_MUTEX(probe_sem); + /* * IRQ autodetection code.. * @@ -385,21 +385,44 @@ unsigned long probe_irq_on(void) { unsigned int i; - unsigned long delay; + irq_desc_t *desc; unsigned long val; + unsigned long delay; + + down(&probe_sem); + /* + * something may have generated an irq long ago and we want to + * flush such a longstanding irq before considering it as spurious. + */ + for (i = NR_IRQS-1; i > 0; i--) { + desc = irq_desc + i; + + spin_lock_irq(&desc->lock); + if (!desc->action) + desc->handler->startup(i); + spin_unlock_irq(&desc->lock); + } + + /* Wait for longstanding interrupts to trigger. */ + for (delay = jiffies + HZ/50; time_after(delay, jiffies); ) + /* about 20ms delay */ synchronize_irq(); /* - * first, enable any unassigned irqs + * enable any unassigned irqs + * (we must startup again here because if a longstanding irq + * happened in the previous stage, it may have masked itself) */ - spin_lock_irq(&irq_controller_lock); for (i = NR_IRQS-1; i > 0; i--) { - if (!irq_desc[i].action) { - irq_desc[i].status |= IRQ_AUTODETECT | IRQ_WAITING; - if (irq_desc[i].handler->startup(i)) - irq_desc[i].status |= IRQ_PENDING; + desc = irq_desc + i; + + spin_lock_irq(&desc->lock); + if (!desc->action) { + desc->status |= IRQ_AUTODETECT | IRQ_WAITING; + if (desc->handler->startup(i)) + desc->status |= IRQ_PENDING; } + spin_unlock_irq(&desc->lock); } - spin_unlock_irq(&irq_controller_lock); /* * Wait for spurious interrupts to trigger @@ -411,23 +434,25 @@ * Now filter out any obviously spurious interrupts */ val = 0; - spin_lock_irq(&irq_controller_lock); for (i=0; ilock); + status = desc->status; - /* It triggered already - consider it spurious. */ - if (!(status & IRQ_WAITING)) { - irq_desc[i].status = status & ~IRQ_AUTODETECT; - irq_desc[i].handler->shutdown(i); + if (status & IRQ_AUTODETECT) { + /* It triggered already - consider it spurious. */ + if (!(status & IRQ_WAITING)) { + desc->status = status & ~IRQ_AUTODETECT; + desc->handler->shutdown(i); + } else + if (i < 32) + val |= 1 << i; } - - if (i < 32) - val |= 1 << i; + spin_unlock_irq(&desc->lock); } - spin_unlock_irq(&irq_controller_lock); + spin_unlock_irq(&desc->lock); return val; } @@ -438,22 +463,25 @@ nr_irqs = 0; irq_found = 0; - spin_lock_irq(&irq_controller_lock); for (i=0; ilock); + status = desc->status; - if (!(status & IRQ_WAITING)) { - if (!nr_irqs) - irq_found = i; - nr_irqs++; + if (status & IRQ_AUTODETECT) { + if (!(status & IRQ_WAITING)) { + if (!nr_irqs) + irq_found = i; + nr_irqs++; + } + desc->status = status & ~IRQ_AUTODETECT; + desc->handler->shutdown(i); } - irq_desc[i].status = status & ~IRQ_AUTODETECT; - irq_desc[i].handler->shutdown(i); + spin_unlock_irq(&desc->lock); } - spin_unlock_irq(&irq_controller_lock); + up(&probe_sem); if (nr_irqs > 1) irq_found = -irq_found; @@ -465,6 +493,7 @@ int shared = 0; struct irqaction *old, **p; unsigned long flags; + irq_desc_t *desc = irq_desc + irq; /* * Some drivers like serial.c use request_irq() heavily, @@ -486,12 +515,12 @@ /* * The following block of code has to be executed atomically */ - spin_lock_irqsave(&irq_controller_lock,flags); - p = &irq_desc[irq].action; + spin_lock_irqsave(&desc->lock,flags); + p = &desc->action; if ((old = *p) != NULL) { /* Can't share interrupts unless both agree to */ if (!(old->flags & new->flags & SA_SHIRQ)) { - spin_unlock_irqrestore(&irq_controller_lock,flags); + spin_unlock_irqrestore(&desc->lock,flags); return -EBUSY; } @@ -506,11 +535,11 @@ *p = new; if (!shared) { - irq_desc[irq].depth = 0; - irq_desc[irq].status &= ~IRQ_DISABLED; - irq_desc[irq].handler->startup(irq); + desc->depth = 0; + desc->status &= ~IRQ_DISABLED; + desc->handler->startup(irq); } - spin_unlock_irqrestore(&irq_controller_lock,flags); + spin_unlock_irqrestore(&desc->lock,flags); return 0; } diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/irq_intc2.c linux/arch/sh/kernel/irq_intc2.c --- v2.4.5/linux/arch/sh/kernel/irq_intc2.c Sun May 20 12:11:38 2001 +++ linux/arch/sh/kernel/irq_intc2.c Wed Jun 27 13:55:29 2001 @@ -45,7 +45,7 @@ } static struct hw_interrupt_type intc2_irq_type = { - "INTC2-based-IRQ", + "INTC2-IRQ", startup_intc2_irq, shutdown_intc2_irq, enable_intc2_irq, diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/irq_ipr.c linux/arch/sh/kernel/irq_ipr.c --- v2.4.5/linux/arch/sh/kernel/irq_ipr.c Wed Apr 11 21:24:52 2001 +++ linux/arch/sh/kernel/irq_ipr.c Wed Jun 27 13:55:29 2001 @@ -46,7 +46,7 @@ } static struct hw_interrupt_type ipr_irq_type = { - "IPR-based-IRQ", + "IPR-IRQ", startup_ipr_irq, shutdown_ipr_irq, enable_ipr_irq, @@ -189,7 +189,9 @@ void __init init_IRQ(void) { +#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) int i; +#endif make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY); make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY); @@ -226,27 +228,6 @@ * Initialize the Interrupt Controller (INTC) * registers to their power on values */ -#if 0 - /* - * XXX: I think that this is the job of boot loader. -- gniibe - * - * When Takeshi released new boot loader following setting - * will be removed shortly. - */ - ctrl_outb(0, INTC_IRR0); - ctrl_outb(0, INTC_IRR1); - ctrl_outb(0, INTC_IRR2); - - ctrl_outw(0, INTC_ICR0); - ctrl_outw(0, INTC_ICR1);/* Really? 0x4000?*/ - ctrl_outw(0, INTC_ICR2); - ctrl_outw(0, INTC_INTER); - ctrl_outw(0, INTC_IPRA); - ctrl_outw(0, INTC_IPRB); - ctrl_outw(0, INTC_IPRC); - ctrl_outw(0, INTC_IPRD); - ctrl_outw(0, INTC_IPRE); -#endif /* * Enable external irq (INTC IRQ mode). diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/led_bigsur.c linux/arch/sh/kernel/led_bigsur.c --- v2.4.5/linux/arch/sh/kernel/led_bigsur.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/led_bigsur.c Wed Jun 27 13:55:29 2001 @@ -0,0 +1,55 @@ +/* + * linux/arch/sh/kernel/led_bigsur.c + * + * By Dustin McIntire (dustin@sensoria.com) (c)2001 + * Derived from led_se.c and led.c, which bore the message: + * Copyright (C) 2000 Stuart Menefy + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * This file contains Big Sur specific LED code. + */ + +#include +#include +#include + +static void mach_led(int position, int value) +{ + int word; + + word = bigsur_inl(BIGSUR_CSLR); + if (value) { + bigsur_outl(word & ~BIGSUR_LED, BIGSUR_CSLR); + } else { + bigsur_outl(word | BIGSUR_LED, BIGSUR_CSLR); + } +} + +#ifdef CONFIG_HEARTBEAT + +#include + +/* Cycle the LED on/off */ +void heartbeat_bigsur(void) +{ + static unsigned cnt = 0, period = 0, dist = 0; + + if (cnt == 0 || cnt == dist) + mach_led( -1, 1); + else if (cnt == 7 || cnt == dist+7) + mach_led( -1, 0); + + if (++cnt > period) { + cnt = 0; + /* The hyperbolic function below modifies the heartbeat period + * length in dependency of the current (5min) load. It goes + * through the points f(0)=126, f(1)=86, f(5)=51, + * f(inf)->30. */ + period = ((672< +#include + +#include +#include +#include +#include +#include +#include + +/* + * The Machine Vector + */ +extern void heartbeat_bigsur(void); +extern void setup_bigsur(void); +extern void init_bigsur_IRQ(void); + +struct sh_machine_vector mv_bigsur __initmv = { + mv_name: "Big Sur", + mv_nr_irqs: NR_IRQS, // Defined in + mv_inb: bigsur_inb, + mv_inw: bigsur_inw, + mv_inl: bigsur_inl, + mv_outb: bigsur_outb, + mv_outw: bigsur_outw, + mv_outl: bigsur_outl, + + mv_inb_p: bigsur_inb_p, + mv_inw_p: bigsur_inw, + mv_inl_p: bigsur_inl, + mv_outb_p: bigsur_outb_p, + mv_outw_p: bigsur_outw, + mv_outl_p: bigsur_outl, + + mv_insb: bigsur_insb, + mv_insw: bigsur_insw, + mv_insl: bigsur_insl, + mv_outsb: bigsur_outsb, + mv_outsw: bigsur_outsw, + mv_outsl: bigsur_outsl, + + mv_readb: generic_readb, + mv_readw: generic_readw, + mv_readl: generic_readl, + mv_writeb: generic_writeb, + mv_writew: generic_writew, + mv_writel: generic_writel, + + mv_ioremap: generic_ioremap, + mv_iounmap: generic_iounmap, + + mv_isa_port2addr: bigsur_isa_port2addr, + mv_irq_demux: bigsur_irq_demux, + + mv_init_arch: setup_bigsur, + mv_init_irq: init_bigsur_IRQ, +#ifdef CONFIG_HEARTBEAT + mv_heartbeat: heartbeat_bigsur, +#endif + mv_rtc_gettimeofday: sh_rtc_gettimeofday, + mv_rtc_settimeofday: sh_rtc_settimeofday, + +}; +ALIAS_MV(bigsur) diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/mach_dc.c linux/arch/sh/kernel/mach_dc.c --- v2.4.5/linux/arch/sh/kernel/mach_dc.c Sun May 20 12:11:38 2001 +++ linux/arch/sh/kernel/mach_dc.c Wed Jun 27 13:55:29 2001 @@ -1,5 +1,5 @@ /* - * $Id: mach_dc.c,v 1.1 2001/04/01 15:02:00 yaegashi Exp $ + * $Id: mach_dc.c,v 1.4 2001/05/24 05:09:16 mrbrown Exp $ * SEGA Dreamcast machine vector */ @@ -23,7 +23,7 @@ struct sh_machine_vector mv_dreamcast __initmv = { mv_name: "dreamcast", - mv_nr_irqs: 48, + mv_nr_irqs: NR_IRQS, mv_inb: generic_inb, mv_inw: generic_inw, @@ -57,11 +57,9 @@ mv_iounmap: generic_iounmap, mv_init_arch: setup_dreamcast, -#ifdef CONFIG_PCI - mv_init_pci: dreamcast_pcibios_init, -#endif mv_isa_port2addr: dreamcast_isa_port2addr, + mv_irq_demux: systemasic_irq_demux, - mv_hw_dreamcast: 1, + mv_hw_dreamcast: 1, }; ALIAS_MV(dreamcast) diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/pci-7751se.c linux/arch/sh/kernel/pci-7751se.c --- v2.4.5/linux/arch/sh/kernel/pci-7751se.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/pci-7751se.c Wed Jun 27 13:55:29 2001 @@ -0,0 +1,102 @@ +/* + * linux/arch/sh/kernel/pci-7751se.c + * + * Author: Ian DaSilva (idasilva@mvista.com) + * + * Highly leveraged from pci-bigsur.c, written by Dustin McIntire. + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * PCI initialization for the Hitachi SH7751 Solution Engine board (MS7751SE01) + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#define PCIMCR_MRSET_OFF 0xBFFFFFFF +#define PCIMCR_RFSH_OFF 0xFFFFFFFB + +/* + * Only long word accesses of the PCIC's internal local registers and the + * configuration registers from the CPU is supported. + */ +#define PCIC_WRITE(x,v) writel((v), PCI_REG(x)) +#define PCIC_READ(x) readl(PCI_REG(x)) + +/* + * Description: This function sets up and initializes the pcic, sets + * up the BARS, maps the DRAM into the address space etc, etc. + */ +int __init pcibios_init_platform(void) +{ + unsigned long data; + unsigned long bcr1, wcr1, wcr2, wcr3, mcr; + unsigned short bcr2; + + // + // Initialize the slave bus controller on the pcic. The values used + // here should not be hardcoded, but they should be taken from the bsc + // on the processor, to make this function as generic as possible. + // (i.e. Another sbc may usr different SDRAM timing settings -- in order + // for the pcic to work, its settings need to be exactly the same.) + // + bcr1 = (*(volatile unsigned long*)(SH7751_BCR1)); + bcr2 = (*(volatile unsigned short*)(SH7751_BCR2)); + wcr1 = (*(volatile unsigned long*)(SH7751_WCR1)); + wcr2 = (*(volatile unsigned long*)(SH7751_WCR2)); + wcr3 = (*(volatile unsigned long*)(SH7751_WCR3)); + mcr = (*(volatile unsigned long*)(SH7751_MCR)); + + bcr1 = bcr1 | 0x00080000; /* Enable Bit 19, BREQEN */ + (*(volatile unsigned long*)(SH7751_BCR1)) = bcr1; + + bcr1 = bcr1 | 0x40080000; /* Enable Bit 19 BREQEN, set PCIC to slave */ + PCIC_WRITE(SH7751_PCIBCR1, bcr1); /* PCIC BCR1 */ + PCIC_WRITE(SH7751_PCIBCR2, bcr2); /* PCIC BCR2 */ + PCIC_WRITE(SH7751_PCIWCR1, wcr1); /* PCIC WCR1 */ + PCIC_WRITE(SH7751_PCIWCR2, wcr2); /* PCIC WCR2 */ + PCIC_WRITE(SH7751_PCIWCR3, wcr3); /* PCIC WCR3 */ + mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF; + PCIC_WRITE(SH7751_PCIMCR, mcr); /* PCIC MCR */ + + PCIC_WRITE(SH7751_PCIINTM, 0x0000c3ff); + PCIC_WRITE(SH7751_PCIAINTM, 0x0000980f); + PCIC_WRITE(SH7751_PCICONF1, 0xF39000C7); /* FB9000C7 */ + PCIC_WRITE(SH7751_PCICONF2, 0x00000000); /* PCI Class code & Revision ID */ + PCIC_WRITE(SH7751_PCICONF4, 0xab000001); /* PCI I/O */ + PCIC_WRITE(SH7751_PCICONF5, 0x0c000000); /* PCI MEM0 old val: 0xb0000000 */ + PCIC_WRITE(SH7751_PCICONF6, 0xd0000000); /* PCI MEM1 */ + PCIC_WRITE(SH7751_PCICONF11, 0x35051054); /* PCI Sub system ID & Sub system vendor ID */ + PCIC_WRITE(SH7751_PCILSR0, 0x03f00000); /* PCI MEM0 */ + PCIC_WRITE(SH7751_PCILSR1, 0x00000000); /* PCI MEM1 */ + PCIC_WRITE(SH7751_PCILAR0, 0x0c000000); /* MEM0 */ + PCIC_WRITE(SH7751_PCILAR1, 0x00000000); /* MEM1 */ + + PCIC_WRITE(SH7751_PCICR, 0xa5000001); + + printk("SH7751 PCI: Finished initialization of the PCI controller\n"); + + return 1; +} + +int __init pcibios_map_platform_irq(u8 slot, u8 pin) +{ + switch (slot) { + case 0: return 13; + case 1: return 13; /* AMD Ethernet controller */ + case 2: return -1; + case 3: return -1; + case 4: return -1; + default: + printk("PCI: Bad IRQ mapping request for slot %d\n", slot); + return -1; + } +} diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/pci-bigsur.c linux/arch/sh/kernel/pci-bigsur.c --- v2.4.5/linux/arch/sh/kernel/pci-bigsur.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/pci-bigsur.c Wed Jun 27 13:55:29 2001 @@ -0,0 +1,163 @@ +/* + * linux/arch/sh/kernel/pci-bigsur.c + * + * By Dustin McIntire (dustin@sensoria.com) (c)2001 + + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * PCI initialization for the Hitachi Big Sur Evaluation Board + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define PCI_REG(reg) (SH7751_PCIREG_BASE+reg) + +/* + * Initialize the Big Sur PCI interface + * Setup hardware to be Central Funtion + * Copy the BSR regs to the PCI interface + * Setup PCI windows into local RAM + */ +int __init pcibios_init_platform(void) { + u32 reg; + u32 word; + + PCIDBG(1,"PCI: bigsur_pci_init called\n"); + /* Set the BCR's to enable PCI access */ + reg = inl(SH7751_BCR1); + reg |= 0x80000; + outl(reg, SH7751_BCR1); + + /* Setup the host hardware */ + if(inl(PCI_REG(SH7751_PCICONF0)) != + (u32)((SH7751_DEVICE_ID <<16) | (SH7751_VENDOR_ID))) { + printk("PCI: Unkown PCI host bridge.\n"); + return 0; + } + printk("PCI: SH7751 PCI host bridge found.\n"); + + /* Turn the clocks back on (not done in reset)*/ + outl(0, PCI_REG(SH7751_PCICLKR)); + /* Clear Powerdown IRQ's (not done in reset) */ + word = SH7751_PCIPINT_D3 | SH7751_PCIPINT_D0; + outl(word, PCI_REG(SH7751_PCICLKR)); + + /* toggle PCI reset pin */ + word = SH7751_PCICR_PREFIX | SH7751_PCICR_PRST; + outl(word,PCI_REG(SH7751_PCICR)); + /* Wait for a long time... not 1 sec. but long enough */ + mdelay(100); + word = SH7751_PCICR_PREFIX; + outl(word,PCI_REG(SH7751_PCICR)); + + /* set the command/status bits to: + * Wait Cycle Control + Parity Enable + Bus Master + + * Mem space enable + */ + word = SH7751_PCICONF1_WCC | SH7751_PCICONF1_PER | + SH7751_PCICONF1_BUM | SH7751_PCICONF1_MES; + outl(word, PCI_REG(SH7751_PCICONF1)); + + /* define this host as the host bridge */ + word = SH7751_PCI_HOST_BRIDGE << 24; + outl(word, PCI_REG(SH7751_PCICONF2)); + + /* Set IO and Mem windows to local address + * Make PCI and local address the same for easy 1 to 1 mapping + * Window0 = BIGSUR_LSR0_SIZE @ non-cached CS3 base = SDRAM + * Window1 = BIGSUR_LSR1_SIZE @ cached CS3 base = SDRAM + */ + word = BIGSUR_LSR0_SIZE - 1; + outl(word, PCI_REG(SH7751_PCILSR0)); + word = BIGSUR_LSR1_SIZE - 1; + outl(word, PCI_REG(SH7751_PCILSR1)); + /* Set the values on window 0 PCI config registers */ + word = P2SEGADDR(SH7751_CS3_BASE_ADDR); + outl(word, PCI_REG(SH7751_PCILAR0)); + outl(word, PCI_REG(SH7751_PCICONF5)); + /* Set the values on window 1 PCI config registers */ + word = PHYSADDR(SH7751_CS3_BASE_ADDR); + outl(word, PCI_REG(SH7751_PCILAR1)); + outl(word, PCI_REG(SH7751_PCICONF6)); + + /* Set the local 16MB PCI memory space window to + * the lowest PCI mapped address + */ + word = PCIBIOS_MIN_MEM & SH7751_PCIMBR_MASK; + PCIDBG(2,"PCI: Setting upper bits of Memory window to 0x%x\n", word); + outl(word , PCI_REG(SH7751_PCIMBR)); + + /* Map IO space into PCI IO window + * The IO window is 64K-PCIBIOS_MIN_IO in size + * IO addresses will be translated to the + * PCI IO window base address + */ + PCIDBG(3,"PCI: Mapping IO address 0x%x - 0x%x to base 0x%x\n", PCIBIOS_MIN_IO, + (64*1024), SH7751_PCI_IO_BASE+PCIBIOS_MIN_IO); + bigsur_port_map(PCIBIOS_MIN_IO, (64*1024), SH7751_PCI_IO_BASE+PCIBIOS_MIN_IO,0); + + /* Make sure the MSB's of IO window are set to access PCI space correctly */ + word = PCIBIOS_MIN_IO & SH7751_PCIIOBR_MASK; + PCIDBG(2,"PCI: Setting upper bits of IO window to 0x%x\n", word); + outl(word, PCI_REG(SH7751_PCIIOBR)); + + /* Set PCI WCRx, BCRx's, copy from BSC locations */ + word = inl(SH7751_BCR1); + /* check BCR for SDRAM in area 3 */ + if(((word >> 3) & 1) == 0) { + printk("PCI: Area 3 is not configured for SDRAM. BCR1=0x%x\n", word); + return 0; + } + outl(word, PCI_REG(SH7751_PCIBCR1)); + word = (u16)inw(SH7751_BCR2); + /* check BCR2 for 32bit SDRAM interface*/ + if(((word >> 6) & 0x3) != 0x3) { + printk("PCI: Area 3 is not 32 bit SDRAM. BCR2=0x%x\n", word); + return 0; + } + outl(word, PCI_REG(SH7751_PCIBCR2)); + /* configure the wait control registers */ + word = inl(SH7751_WCR1); + outl(word, PCI_REG(SH7751_PCIWCR1)); + word = inl(SH7751_WCR2); + outl(word, PCI_REG(SH7751_PCIWCR2)); + word = inl(SH7751_WCR3); + outl(word, PCI_REG(SH7751_PCIWCR3)); + word = inl(SH7751_MCR); + outl(word, PCI_REG(SH7751_PCIMCR)); + + /* NOTE: I'm ignoring the PCI error IRQs for now.. + * TODO: add support for the internal error interrupts and + * DMA interrupts... + */ + + /* SH7751 init done, set central function init complete */ + word = SH7751_PCICR_PREFIX | SH7751_PCICR_CFIN; + outl(word,PCI_REG(SH7751_PCICR)); + PCIDBG(2,"PCI: bigsur_pci_init finished\n"); + + return 1; +} + +int pcibios_map_platform_irq(u8 slot, u8 pin) +{ + /* The Big Sur can be used in a CPCI chassis, but the SH7751 PCI interface is on the + * wrong end of the board so that it can also support a V320 CPI interface chip... + * Therefor the IRQ mapping is somewhat use dependent... I'l assume a linear map for + * now, i.e. INTA=slot0,pin0... INTD=slot3,pin0... + */ + int irq = (slot + pin-1)%4 + BIGSUR_SH7751_PCI_IRQ_BASE; + PCIDBG(2,"PCI: Mapping Big Sur IRQ for slot %d, pin %c to irq %d\n", slot, pin-1+'A', irq); + return irq; + +} diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/pci-dc.c linux/arch/sh/kernel/pci-dc.c --- v2.4.5/linux/arch/sh/kernel/pci-dc.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/pci-dc.c Wed Jun 27 13:55:29 2001 @@ -0,0 +1,276 @@ +/* + $ $Id: pci-dc.c,v 1.2 2001/05/24 05:09:16 mrbrown Exp $ + * Dreamcast PCI: Supports SEGA Broadband Adaptor only. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define GAPSPCI_REGS 0x01001400 +#define GAPSPCI_DMA_BASE 0x01840000 +#define GAPSPCI_DMA_SIZE 32768 +#define GAPSPCI_BBA_CONFIG 0x01001600 + +#define GAPSPCI_IRQ HW_EVENT_EXTERNAL + +static int gapspci_dma_used; + +static struct pci_bus *pci_root_bus; + +struct pci_fixup pcibios_fixups[] = { + {0, 0, 0, NULL} +}; + +#define BBA_SELECTED(dev) (dev->bus->number==0 && dev->devfn==0) + +static int gapspci_read_config_byte(struct pci_dev *dev, int where, + u8 * val) +{ + if (BBA_SELECTED(dev)) + *val = inb(GAPSPCI_BBA_CONFIG+where); + else + *val = 0xff; + + return PCIBIOS_SUCCESSFUL; +} + +static int gapspci_read_config_word(struct pci_dev *dev, int where, + u16 * val) +{ + if (BBA_SELECTED(dev)) + *val = inw(GAPSPCI_BBA_CONFIG+where); + else + *val = 0xffff; + + return PCIBIOS_SUCCESSFUL; +} + +static int gapspci_read_config_dword(struct pci_dev *dev, int where, + u32 * val) +{ + if (BBA_SELECTED(dev)) + *val = inl(GAPSPCI_BBA_CONFIG+where); + else + *val = 0xffffffff; + + return PCIBIOS_SUCCESSFUL; +} + +static int gapspci_write_config_byte(struct pci_dev *dev, int where, + u8 val) +{ + if (BBA_SELECTED(dev)) + outb(val, GAPSPCI_BBA_CONFIG+where); + + return PCIBIOS_SUCCESSFUL; +} + + +static int gapspci_write_config_word(struct pci_dev *dev, int where, + u16 val) +{ + if (BBA_SELECTED(dev)) + outw(val, GAPSPCI_BBA_CONFIG+where); + + return PCIBIOS_SUCCESSFUL; +} + +static int gapspci_write_config_dword(struct pci_dev *dev, int where, + u32 val) +{ + if (BBA_SELECTED(dev)) + outl(val, GAPSPCI_BBA_CONFIG+where); + + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops pci_config_ops = { + gapspci_read_config_byte, + gapspci_read_config_word, + gapspci_read_config_dword, + gapspci_write_config_byte, + gapspci_write_config_word, + gapspci_write_config_dword +}; + + +void pcibios_align_resource(void *data, struct resource *res, + unsigned long size) +{ +} + + +void __init pcibios_update_irq(struct pci_dev *dev, int irq) +{ +} + + +void __init pcibios_update_resource(struct pci_dev *dev, struct resource *root, + struct resource *res, int resource) +{ +} + + +void pcibios_set_master(struct pci_dev *dev) +{ + /* No special bus mastering setup handling */ +} + + +int pcibios_enable_device(struct pci_dev *dev) +{ + + u16 cmd, old_cmd; + int idx; + struct resource *r; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + old_cmd = cmd; + for (idx = 0; idx < 6; idx++) { + r = dev->resource + idx; + if (!r->start && r->end) { + printk(KERN_ERR + "PCI: Device %s not available because" + " of resource collisions\n", + dev->slot_name); + return -EINVAL; + } + if (r->flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + if (r->flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + if (cmd != old_cmd) { + printk("PCI: enabling device %s (%04x -> %04x)\n", + dev->slot_name, old_cmd, cmd); + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + return 0; + +} + + +void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, + dma_addr_t * dma_handle) +{ + unsigned long buf; + + if (gapspci_dma_used+size > GAPSPCI_DMA_SIZE) + return NULL; + + buf = GAPSPCI_DMA_BASE+gapspci_dma_used; + + gapspci_dma_used = PAGE_ALIGN(gapspci_dma_used+size); + + printk("pci_alloc_consistent: %ld bytes at 0x%p\n", size, buf); + + *dma_handle = (dma_addr_t)buf; + + return (void *)P2SEGADDR(buf); +} + + +void pci_free_consistent(struct pci_dev *hwdev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + /* XXX */ +} + + +void __init pcibios_fixup_pbus_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *ranges) +{ +} + +void __init pcibios_fixup_bus(struct pci_bus *bus) +{ + struct list_head *ln; + struct pci_dev *dev; + + for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) { + dev = pci_dev_b(ln); + if (!BBA_SELECTED(dev)) continue; + + printk("PCI: MMIO fixup to %s\n", dev->name); + dev->resource[1].start=0x01001700; + dev->resource[1].end=0x010017ff; + } +} + + +static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin) +{ + return PCI_SLOT(dev->devfn); +} + + +static int __init map_dc_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + return GAPSPCI_IRQ; +} + + +void __init pcibios_init(void) +{ + pci_root_bus = pci_scan_bus(0, &pci_config_ops, NULL); + /* pci_assign_unassigned_resources(); */ + pci_fixup_irqs(no_swizzle, map_dc_irq); +} + + +/* Haven't done anything here as yet */ +char * __init pcibios_setup(char *str) +{ + return str; +} + + +int __init gapspci_init(void) +{ + int i; + char idbuf[16]; + + for(i=0; i<16; i++) + idbuf[i]=inb(GAPSPCI_REGS+i); + + if(strncmp(idbuf, "GAPSPCI_BRIDGE_2", 16)) + return -1; + + outl(0x5a14a501, GAPSPCI_REGS+0x18); + + for(i=0; i<1000000; i++); + + if(inl(GAPSPCI_REGS+0x18)!=1) + return -1; + + outl(0x01000000, GAPSPCI_REGS+0x20); + outl(0x01000000, GAPSPCI_REGS+0x24); + + outl(GAPSPCI_DMA_BASE, GAPSPCI_REGS+0x28); + outl(GAPSPCI_DMA_BASE+GAPSPCI_DMA_SIZE, GAPSPCI_REGS+0x2c); + + outl(1, GAPSPCI_REGS+0x14); + outl(1, GAPSPCI_REGS+0x34); + + gapspci_dma_used=0; + + /* Setting Broadband Adapter */ + outw(0xf900, GAPSPCI_BBA_CONFIG+0x06); + outl(0x00000000, GAPSPCI_BBA_CONFIG+0x30); + outb(0x00, GAPSPCI_BBA_CONFIG+0x3c); + outb(0xf0, GAPSPCI_BBA_CONFIG+0x0d); + outw(0x0006, GAPSPCI_BBA_CONFIG+0x04); + outl(0x00002001, GAPSPCI_BBA_CONFIG+0x10); + outl(0x01000000, GAPSPCI_BBA_CONFIG+0x14); + + return 0; +} diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/pci-dma.c linux/arch/sh/kernel/pci-dma.c --- v2.4.5/linux/arch/sh/kernel/pci-dma.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/pci-dma.c Wed Jun 27 13:55:29 2001 @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Dynamic DMA mapping support. + */ + +#include +#include +#include +#include +#include +#include + + +void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, + dma_addr_t * dma_handle) +{ + void *ret; + int gfp = GFP_ATOMIC; + + ret = (void *) __get_free_pages(gfp, get_order(size)); + + if (ret != NULL) { + /* Is it neccessary to do the memset? */ + memset(ret, 0, size); + *dma_handle = virt_to_bus(ret); + } + /* We must flush the cache before we pass it on to the device */ + flush_cache_all(); + return P2SEGADDR(ret); +} + +void pci_free_consistent(struct pci_dev *hwdev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + unsigned long p1addr=P1SEGADDR((unsigned long)vaddr); + + free_pages(p1addr, get_order(size)); +} diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/pci-sh.c linux/arch/sh/kernel/pci-sh.c --- v2.4.5/linux/arch/sh/kernel/pci-sh.c Wed Aug 9 13:59:04 2000 +++ linux/arch/sh/kernel/pci-sh.c Wed Dec 31 16:00:00 1969 @@ -1,25 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -void __init pcibios_init(void) -{ - if (sh_mv.mv_init_pci != NULL) { - sh_mv.mv_init_pci(); - } -} - -/* Haven't done anything here as yet */ -char * __init pcibios_setup(char *str) -{ - return str; -} - -/* We don't have anything here to fixup */ -struct pci_fixup pcibios_fixups[] = { - {0, 0, 0, NULL} -}; diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/pci-sh7751.c linux/arch/sh/kernel/pci-sh7751.c --- v2.4.5/linux/arch/sh/kernel/pci-sh7751.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/pci-sh7751.c Wed Jun 27 13:55:29 2001 @@ -0,0 +1,674 @@ +/* + * Low-Level PCI Support for the SH7751 + * + * Dustin McIntire (dustin@sensoria.com) + * Derived from arch/i386/kernel/pci-*.c which bore the message: + * (c) 1999--2000 Martin Mares + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +struct pci_ops *pci_check_direct(void); +void pcibios_resource_survey(void); +static u8 pcibios_swizzle(struct pci_dev *dev, u8 *pin); +static int pcibios_lookup_irq(struct pci_dev *dev, u8 slot, u8 pin); + +unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1; +int pcibios_last_bus = -1; +struct pci_bus *pci_root_bus; +struct pci_ops *pci_root_ops; + +/* + * Direct access to PCI hardware... + */ + +#ifdef CONFIG_PCI_DIRECT + + +#define CONFIG_CMD(dev, where) (0x80000000 | (dev->bus->number << 16) | (dev->devfn << 8) | (where & ~3)) + +#define PCI_REG(reg) (SH7751_PCIREG_BASE+reg) + +/* + * Functions for accessing PCI configuration space with type 1 accesses + */ +static int pci_conf1_read_config_byte(struct pci_dev *dev, int where, u8 *value) +{ + u32 word; + unsigned long flags; + + /* PCIPDR may only be accessed as 32 bit words, + * so we must do byte alignment by hand + */ + __save_and_cli(flags); + outl(CONFIG_CMD(dev,where), PCI_REG(SH7751_PCIPAR)); + word = inl(PCI_REG(SH7751_PCIPDR)); + __restore_flags(flags); + switch (where & 0x3) { + case 3: + *value = (u8)(word >> 24); + break; + case 2: + *value = (u8)(word >> 16); + break; + case 1: + *value = (u8)(word >> 8); + break; + default: + *value = (u8)word; + break; + } + PCIDBG(4,"pci_conf1_read_config_byte@0x%08x=0x%x\n", + CONFIG_CMD(dev,where),*value); + return PCIBIOS_SUCCESSFUL; +} + +static int pci_conf1_read_config_word(struct pci_dev *dev, int where, u16 *value) +{ + u32 word; + unsigned long flags; + + /* PCIPDR may only be accessed as 32 bit words, + * so we must do word alignment by hand + */ + __save_and_cli(flags); + outl(CONFIG_CMD(dev,where), PCI_REG(SH7751_PCIPAR)); + word = inl(PCI_REG(SH7751_PCIPDR)); + __restore_flags(flags); + switch (where & 0x3) { + case 3: + // This should never happen... + printk(KERN_ERR "PCI BIOS: read_config_word: Illegal u16 alignment"); + return PCIBIOS_BAD_REGISTER_NUMBER; + case 2: + *value = (u16)(word >> 16); + break; + case 1: + *value = (u16)(word >> 8); + break; + default: + *value = (u16)word; + break; + } + PCIDBG(4,"pci_conf1_read_config_word@0x%08x=0x%x\n", + CONFIG_CMD(dev,where),*value); + return PCIBIOS_SUCCESSFUL; +} + +static int pci_conf1_read_config_dword(struct pci_dev *dev, int where, u32 *value) +{ + unsigned long flags; + + __save_and_cli(flags); + outl(CONFIG_CMD(dev,where), PCI_REG(SH7751_PCIPAR)); + *value = inl(PCI_REG(SH7751_PCIPDR)); + __restore_flags(flags); + PCIDBG(4,"pci_conf1_read_config_dword@0x%08x=0x%x\n", + CONFIG_CMD(dev,where),*value); + return PCIBIOS_SUCCESSFUL; +} + +static int pci_conf1_write_config_byte(struct pci_dev *dev, int where, u8 value) +{ + u32 word; + u32 shift = (where & 3) * 8; + u32 mask = ((1 << 8) - 1) << shift; // create the byte mask + unsigned long flags; + + /* Since SH7751 only does 32bit access we'll have to do a + * read,mask,write operation + */ + __save_and_cli(flags); + outl(CONFIG_CMD(dev,where), PCI_REG(SH7751_PCIPAR)); + word = inl(PCI_REG(SH7751_PCIPDR)) ; + word &= ~mask; + word |= value << shift; + + outl(word, PCI_REG(SH7751_PCIPDR)); + __restore_flags(flags); + PCIDBG(4,"pci_conf1_write_config_byte@0x%08x=0x%x\n", + CONFIG_CMD(dev,where),word); + return PCIBIOS_SUCCESSFUL; +} + +static int pci_conf1_write_config_word(struct pci_dev *dev, int where, u16 value) +{ + u32 word; + u32 shift = (where & 3) * 8; + u32 mask = ((1 << 16) - 1) << shift; // create the word mask + unsigned long flags; + + /* Since SH7751 only does 32bit access we'll have to do a + * read,mask,write operation. We'll allow an odd byte offset, + * though it should be illegal. + */ + if (shift == 24) + return PCIBIOS_BAD_REGISTER_NUMBER; + __save_and_cli(flags); + outl(CONFIG_CMD(dev,where), PCI_REG(SH7751_PCIPAR)); + word = inl(PCI_REG(SH7751_PCIPDR)) ; + word &= ~mask; + word |= value << shift; + + outl(value, PCI_REG(SH7751_PCIPDR)); + __restore_flags(flags); + PCIDBG(4,"pci_conf1_write_config_word@0x%08x=0x%x\n", + CONFIG_CMD(dev,where),word); + return PCIBIOS_SUCCESSFUL; +} + +static int pci_conf1_write_config_dword(struct pci_dev *dev, int where, u32 value) +{ + unsigned long flags; + + __save_and_cli(flags); + outl(CONFIG_CMD(dev,where), PCI_REG(SH7751_PCIPAR)); + outl(value, PCI_REG(SH7751_PCIPDR)); + __restore_flags(flags); + PCIDBG(4,"pci_conf1_write_config_dword@0x%08x=0x%x\n", + CONFIG_CMD(dev,where),value); + return PCIBIOS_SUCCESSFUL; +} + +#undef CONFIG_CMD + +static struct pci_ops pci_direct_conf1 = { + pci_conf1_read_config_byte, + pci_conf1_read_config_word, + pci_conf1_read_config_dword, + pci_conf1_write_config_byte, + pci_conf1_write_config_word, + pci_conf1_write_config_dword +}; + +struct pci_ops * __init pci_check_direct(void) +{ + unsigned int tmp, id; + + /* check for SH7751 hardware */ + id = (SH7751_DEVICE_ID << 16) | SH7751_VENDOR_ID; + if(inl(SH7751_PCIREG_BASE+SH7751_PCICONF0) != id) { + PCIDBG(2,"PCI: This is not an SH7751\n"); + return NULL; + } + /* + * Check if configuration works. + */ + if (pci_probe & PCI_PROBE_CONF1) { + tmp = inl (PCI_REG(SH7751_PCIPAR)); + outl (0x80000000, PCI_REG(SH7751_PCIPAR)); + if (inl (PCI_REG(SH7751_PCIPAR)) == 0x80000000) { + outl (tmp, PCI_REG(SH7751_PCIPAR)); + printk(KERN_INFO "PCI: Using configuration type 1\n"); + request_region(PCI_REG(SH7751_PCIPAR), 8, "PCI conf1"); + return &pci_direct_conf1; + } + outl (tmp, PCI_REG(SH7751_PCIPAR)); + } + + PCIDBG(2,"PCI: pci_check_direct failed\n"); + return NULL; +} + +#endif + +/* + * BIOS32 and PCI BIOS handling. + * + * The BIOS version of the pci functions is not yet implemented but it is left + * in for completeness. Currently an error will be genereated at compile time. + */ + +#ifdef CONFIG_PCI_BIOS + +#error PCI BIOS is not yet supported on SH7751 + +#endif /* CONFIG_PCI_BIOS */ + +/***************************************************************************************/ + +/* + * Handle bus scanning and fixups .... + */ + + +/* + * Discover remaining PCI buses in case there are peer host bridges. + * We use the number of last PCI bus provided by the PCI BIOS. + */ +static void __init pcibios_fixup_peer_bridges(void) +{ + int n; + struct pci_bus bus; + struct pci_dev dev; + u16 l; + + if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff) + return; + PCIDBG(2,"PCI: Peer bridge fixup\n"); + for (n=0; n <= pcibios_last_bus; n++) { + if (pci_bus_exists(&pci_root_buses, n)) + continue; + bus.number = n; + bus.ops = pci_root_ops; + dev.bus = &bus; + for(dev.devfn=0; dev.devfn<256; dev.devfn += 8) + if (!pci_read_config_word(&dev, PCI_VENDOR_ID, &l) && + l != 0x0000 && l != 0xffff) { + PCIDBG(3,"Found device at %02x:%02x [%04x]\n", n, dev.devfn, l); + printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n); + pci_scan_bus(n, pci_root_ops, NULL); + break; + } + } +} + + +static void __init pci_fixup_ide_bases(struct pci_dev *d) +{ + int i; + + /* + * PCI IDE controllers use non-standard I/O port decoding, respect it. + */ + if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE) + return; + PCIDBG(3,"PCI: IDE base address fixup for %s\n", d->slot_name); + for(i=0; i<4; i++) { + struct resource *r = &d->resource[i]; + if ((r->start & ~0x80) == 0x374) { + r->start |= 2; + r->end = r->start; + } + } +} + + +/* Add future fixups here... */ +struct pci_fixup pcibios_fixups[] = { + { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases }, + { 0 } +}; + +void __init pcibios_fixup_pbus_ranges(struct pci_bus *b, + struct pbus_set_ranges_data *range) +{ + /* No fixups needed */ +} + +/* + * Called after each bus is probed, but before its children + * are examined. + */ + +void __init pcibios_fixup_bus(struct pci_bus *b) +{ + pci_read_bridge_bases(b); +} + +/* + * Initialization. Try all known PCI access methods. Note that we support + * using both PCI BIOS and direct access: in such cases, we use I/O ports + * to access config space. + * + * Note that the platform specific initialization (BSC registers, and memory + * space mapping) will be called via the machine vectors (sh_mv.mv_pci_init()) if it + * exitst and via the platform defined function pcibios_init_platform(). + * See pci_bigsur.c for implementation; + * + * The BIOS version of the pci functions is not yet implemented but it is left + * in for completeness. Currently an error will be genereated at compile time. + */ + +void __init pcibios_init(void) +{ + struct pci_ops *bios = NULL; + struct pci_ops *dir = NULL; + + PCIDBG(1,"PCI: Starting intialization.\n"); +#ifdef CONFIG_PCI_BIOS + if ((pci_probe & PCI_PROBE_BIOS) && ((bios = pci_find_bios()))) { + pci_probe |= PCI_BIOS_SORT; + pci_bios_present = 1; + } +#endif +#ifdef CONFIG_PCI_DIRECT + if (pci_probe & PCI_PROBE_CONF1 ) + dir = pci_check_direct(); +#endif + if (dir) { + pci_root_ops = dir; + if(!pcibios_init_platform()) + PCIDBG(1,"PCI: Initialization failed\n"); + if (sh_mv.mv_init_pci != NULL) + sh_mv.mv_init_pci(); + } + else if (bios) + pci_root_ops = bios; + else { + PCIDBG(1,"PCI: No PCI bus detected\n"); + return; + } + + PCIDBG(1,"PCI: Probing PCI hardware\n"); + pci_root_bus = pci_scan_bus(0, pci_root_ops, NULL); + //pci_assign_unassigned_resources(); + pci_fixup_irqs(pcibios_swizzle, pcibios_lookup_irq); + pcibios_fixup_peer_bridges(); + pcibios_resource_survey(); + +#ifdef CONFIG_PCI_BIOS + if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT)) + pcibios_sort(); +#endif +} + +char * __init pcibios_setup(char *str) +{ + if (!strcmp(str, "off")) { + pci_probe = 0; + return NULL; + } +#ifdef CONFIG_PCI_BIOS + else if (!strcmp(str, "bios")) { + pci_probe = PCI_PROBE_BIOS; + return NULL; + } else if (!strcmp(str, "nobios")) { + pci_probe &= ~PCI_PROBE_BIOS; + return NULL; + } else if (!strcmp(str, "nosort")) { + pci_probe |= PCI_NO_SORT; + return NULL; + } else if (!strcmp(str, "biosirq")) { + pci_probe |= PCI_BIOS_IRQ_SCAN; + return NULL; + } +#endif +#ifdef CONFIG_PCI_DIRECT + else if (!strcmp(str, "conf1")) { + pci_probe = PCI_PROBE_CONF1 | PCI_NO_CHECKS; + return NULL; + } +#endif + else if (!strcmp(str, "rom")) { + pci_probe |= PCI_ASSIGN_ROMS; + return NULL; + } else if (!strncmp(str, "lastbus=", 8)) { + pcibios_last_bus = simple_strtol(str+8, NULL, 0); + return NULL; + } + return str; +} + +void +pcibios_update_resource(struct pci_dev *dev, struct resource *root, + struct resource *res, int resource) +{ + u32 new, check; + int reg; + + new = res->start | (res->flags & PCI_REGION_FLAG_MASK); + if (resource < 6) { + reg = PCI_BASE_ADDRESS_0 + 4*resource; + } else if (resource == PCI_ROM_RESOURCE) { + res->flags |= PCI_ROM_ADDRESS_ENABLE; + new |= PCI_ROM_ADDRESS_ENABLE; + reg = dev->rom_base_reg; + } else { + /* Somebody might have asked allocation of a non-standard resource */ + return; + } + + pci_write_config_dword(dev, reg, new); + pci_read_config_dword(dev, reg, &check); + if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) { + printk(KERN_ERR "PCI: Error while updating region " + "%s/%d (%08x != %08x)\n", dev->slot_name, resource, + new, check); + } +} + +/* + * We need to avoid collisions with `mirrored' VGA ports + * and other strange ISA hardware, so we always want the + * addresses to be allocated in the 0x000-0x0ff region + * modulo 0x400. + */ +void +pcibios_align_resource(void *data, struct resource *res, unsigned long size) +{ + if (res->flags & IORESOURCE_IO) { + unsigned long start = res->start; + + if (start & 0x300) { + start = (start + 0x3ff) & ~0x3ff; + res->start = start; + } + } +} + + +/* + * Allocate the bridge and device resources + */ + +static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) +{ + struct list_head *ln; + struct pci_bus *bus; + struct pci_dev *dev; + int idx; + struct resource *r, *pr; + + PCIDBG(2,"PCI: pcibios_allocate_bus_reasources called\n" ); + /* Depth-First Search on bus tree */ + for (ln=bus_list->next; ln != bus_list; ln=ln->next) { + bus = pci_bus_b(ln); + if ((dev = bus->self)) { + for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) { + r = &dev->resource[idx]; + if (!r->start) + continue; + pr = pci_find_parent_resource(dev, r); + if (!pr || request_resource(pr, r) < 0) + printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, dev->slot_name); + } + } + pcibios_allocate_bus_resources(&bus->children); + } +} + +static void __init pcibios_allocate_resources(int pass) +{ + struct pci_dev *dev; + int idx, disabled; + u16 command; + struct resource *r, *pr; + + PCIDBG(2,"PCI: pcibios_allocate_resources pass %d called\n", pass); + pci_for_each_dev(dev) { + pci_read_config_word(dev, PCI_COMMAND, &command); + for(idx = 0; idx < 6; idx++) { + r = &dev->resource[idx]; + if (r->parent) /* Already allocated */ + continue; + if (!r->start) /* Address not assigned at all */ + continue; + if (r->flags & IORESOURCE_IO) + disabled = !(command & PCI_COMMAND_IO); + else + disabled = !(command & PCI_COMMAND_MEMORY); + if (pass == disabled) { + PCIDBG(3,"PCI: Resource %08lx-%08lx (f=%lx, d=%d, p=%d)\n", + r->start, r->end, r->flags, disabled, pass); + pr = pci_find_parent_resource(dev, r); + if (!pr || request_resource(pr, r) < 0) { + printk(KERN_ERR "PCI: Cannot allocate resource region %d of device %s\n", idx, dev->slot_name); + /* We'll assign a new address later */ + r->end -= r->start; + r->start = 0; + } + } + } + if (!pass) { + r = &dev->resource[PCI_ROM_RESOURCE]; + if (r->flags & PCI_ROM_ADDRESS_ENABLE) { + /* Turn the ROM off, leave the resource region, but keep it unregistered. */ + u32 reg; + PCIDBG(3,"PCI: Switching off ROM of %s\n", dev->slot_name); + r->flags &= ~PCI_ROM_ADDRESS_ENABLE; + pci_read_config_dword(dev, dev->rom_base_reg, ®); + pci_write_config_dword(dev, dev->rom_base_reg, reg & ~PCI_ROM_ADDRESS_ENABLE); + } + } + } +} + +static void __init pcibios_assign_resources(void) +{ + struct pci_dev *dev; + int idx; + struct resource *r; + + PCIDBG(2,"PCI: pcibios_assign_resources called\n"); + pci_for_each_dev(dev) { + int class = dev->class >> 8; + + /* Don't touch classless devices and host bridges */ + if (!class || class == PCI_CLASS_BRIDGE_HOST) + continue; + + for(idx=0; idx<6; idx++) { + r = &dev->resource[idx]; + + /* + * Don't touch IDE controllers and I/O ports of video cards! + */ + if ((class == PCI_CLASS_STORAGE_IDE && idx < 4) || + (class == PCI_CLASS_DISPLAY_VGA && (r->flags & IORESOURCE_IO))) + continue; + + /* + * We shall assign a new address to this resource, either because + * the BIOS forgot to do so or because we have decided the old + * address was unusable for some reason. + */ + if (!r->start && r->end) + pci_assign_resource(dev, idx); + } + + if (pci_probe & PCI_ASSIGN_ROMS) { + r = &dev->resource[PCI_ROM_RESOURCE]; + r->end -= r->start; + r->start = 0; + if (r->end) + pci_assign_resource(dev, PCI_ROM_RESOURCE); + } + } +} + +void __init pcibios_resource_survey(void) +{ + PCIDBG(1,"PCI: Allocating resources\n"); + pcibios_allocate_bus_resources(&pci_root_buses); + pcibios_allocate_resources(0); + pcibios_allocate_resources(1); + pcibios_assign_resources(); +} + +int pcibios_enable_device(struct pci_dev *dev) +{ + u16 cmd, old_cmd; + int idx; + struct resource *r; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + old_cmd = cmd; + for(idx=0; idx<6; idx++) { + r = &dev->resource[idx]; + if (!r->start && r->end) { + printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name); + return -EINVAL; + } + if (r->flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + if (r->flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + if (dev->resource[PCI_ROM_RESOURCE].start) + cmd |= PCI_COMMAND_MEMORY; + if (cmd != old_cmd) { + printk(KERN_INFO "PCI: Enabling device %s (%04x -> %04x)\n", dev->name, old_cmd, cmd); + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + return 0; +} + +/* + * If we set up a device for bus mastering, we need to check and set + * the latency timer as it may not be properly set. + */ +unsigned int pcibios_max_latency = 255; + +void pcibios_set_master(struct pci_dev *dev) +{ + u8 lat; + pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); + if (lat < 16) + lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency; + else if (lat > pcibios_max_latency) + lat = pcibios_max_latency; + else + return; + printk(KERN_INFO "PCI: Setting latency timer of device %s to %d\n", dev->name, lat); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); +} + +/***************************************************************************************/ +/* + * IRQ functions + */ +static u8 __init pcibios_swizzle(struct pci_dev *dev, u8 *pin) +{ + /* no swizzling */ + return PCI_SLOT(dev->devfn); +} + +static int pcibios_lookup_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + int irq = -1; + + /* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */ + irq = pcibios_map_platform_irq(slot,pin); + if( irq < 0 ) { + PCIDBG(3,"PCI: Error mapping IRQ on device %s\n", dev->name); + return irq; + } + + PCIDBG(2,"Setting IRQ for slot %s to %d\n", dev->slot_name, irq); + + return irq; +} + +void __init pcibios_update_irq(struct pci_dev *dev, int irq) +{ + PCIDBG(3,"PCI: Update IRQ for %s on irq %d\n", dev->name, irq); + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); +} diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/pci_st40.c linux/arch/sh/kernel/pci_st40.c --- v2.4.5/linux/arch/sh/kernel/pci_st40.c Wed Apr 11 21:24:52 2001 +++ linux/arch/sh/kernel/pci_st40.c Wed Jun 27 13:55:29 2001 @@ -141,6 +141,31 @@ return tmp; } +static void __init pci_fixup_ide_bases(struct pci_dev *d) +{ + int i; + + /* + * PCI IDE controllers use non-standard I/O port decoding, respect it. + */ + if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE) + return; + printk("PCI: IDE base address fixup for %s\n", d->slot_name); + for(i=0; i<4; i++) { + struct resource *r = &d->resource[i]; + if ((r->start & ~0x80) == 0x374) { + r->start |= 2; + r->end = r->start; + } + } +} + + +/* Add future fixups here... */ +struct pci_fixup pcibios_fixups[] = { + { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases }, + { 0 } +}; int __init st40pci_init(unsigned memStart, unsigned memSize) { @@ -234,6 +259,11 @@ return 1; } +char * __init pcibios_setup(char *str) +{ + return str; +} + #define SET_CONFIG_BITS(bus,devfn,where)\ (((bus) << 16) | ((devfn) << 8) | ((where) & ~3) | (bus!=0)) @@ -390,10 +420,14 @@ ranges->mem_end -= bus->resource[1]->start; } -void __init st40_pcibios_init(void) +void __init pcibios_init(void) { extern unsigned long memory_start, memory_end; + if (sh_mv.mv_init_pci != NULL) { + sh_mv.mv_init_pci(); + } + /* The pci subsytem needs to know where memory is and how much * of it there is. I've simply made these globals. A better mechanism * is probably needed. @@ -491,4 +525,24 @@ { printk("PCI: Assigning IRQ %02d to %s\n", irq, dev->name); pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); +} + +/* + * If we set up a device for bus mastering, we need to check the latency + * timer as certain crappy BIOSes forget to set it properly. + */ +unsigned int pcibios_max_latency = 255; + +void pcibios_set_master(struct pci_dev *dev) +{ + u8 lat; + pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); + if (lat < 16) + lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency; + else if (lat > pcibios_max_latency) + lat = pcibios_max_latency; + else + return; + printk("PCI: Setting latency timer of device %s to %d\n", dev->slot_name, lat); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); } diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/rtc.c linux/arch/sh/kernel/rtc.c --- v2.4.5/linux/arch/sh/kernel/rtc.c Thu May 24 15:14:08 2001 +++ linux/arch/sh/kernel/rtc.c Wed Jun 27 13:55:29 2001 @@ -13,62 +13,6 @@ #include #include -/* RCR1 Bits */ -#define RCR1_CF 0x80 /* Carry Flag */ -#define RCR1_CIE 0x10 /* Carry Interrupt Enable */ -#define RCR1_AIE 0x08 /* Alarm Interrupt Enable */ -#define RCR1_AF 0x01 /* Alarm Flag */ - -/* RCR2 Bits */ -#define RCR2_PEF 0x80 /* PEriodic interrupt Flag */ -#define RCR2_PESMASK 0x70 /* Periodic interrupt Set */ -#define RCR2_RTCEN 0x08 /* ENable RTC */ -#define RCR2_ADJ 0x04 /* ADJustment (30-second) */ -#define RCR2_RESET 0x02 /* Reset bit */ -#define RCR2_START 0x01 /* Start bit */ - -#if defined(__sh3__) -/* SH-3 RTC */ -#define R64CNT 0xfffffec0 -#define RSECCNT 0xfffffec2 -#define RMINCNT 0xfffffec4 -#define RHRCNT 0xfffffec6 -#define RWKCNT 0xfffffec8 -#define RDAYCNT 0xfffffeca -#define RMONCNT 0xfffffecc -#define RYRCNT 0xfffffece -#define RSECAR 0xfffffed0 -#define RMINAR 0xfffffed2 -#define RHRAR 0xfffffed4 -#define RWKAR 0xfffffed6 -#define RDAYAR 0xfffffed8 -#define RMONAR 0xfffffeda -#define RCR1 0xfffffedc -#define RCR2 0xfffffede - -#define RTC_BIT_INVERTED 0 /* No bug on SH7708, SH7709A */ -#elif defined(__SH4__) -/* SH-4 RTC */ -#define R64CNT 0xffc80000 -#define RSECCNT 0xffc80004 -#define RMINCNT 0xffc80008 -#define RHRCNT 0xffc8000c -#define RWKCNT 0xffc80010 -#define RDAYCNT 0xffc80014 -#define RMONCNT 0xffc80018 -#define RYRCNT 0xffc8001c /* 16bit */ -#define RSECAR 0xffc80020 -#define RMINAR 0xffc80024 -#define RHRAR 0xffc80028 -#define RWKAR 0xffc8002c -#define RDAYAR 0xffc80030 -#define RMONAR 0xffc80034 -#define RCR1 0xffc80038 -#define RCR2 0xffc8003c - -#define RTC_BIT_INVERTED 0x40 /* bug on SH7750, SH7750S */ -#endif - #ifndef BCD_TO_BIN #define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10) #endif diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/setup.c linux/arch/sh/kernel/setup.c --- v2.4.5/linux/arch/sh/kernel/setup.c Fri Apr 27 14:10:32 2001 +++ linux/arch/sh/kernel/setup.c Wed Jun 27 13:55:29 2001 @@ -521,6 +521,9 @@ PRINT_CLOCK("CPU", boot_cpu_data.cpu_clock); PRINT_CLOCK("Bus", boot_cpu_data.bus_clock); +#ifdef CONFIG_CPU_SUBTYPE_ST40STB1 + PRINT_CLOCK("Memory", boot_cpu_data.memory_clock); +#endif PRINT_CLOCK("Peripheral module", boot_cpu_data.module_clock); return p - buffer; diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/setup_bigsur.c linux/arch/sh/kernel/setup_bigsur.c --- v2.4.5/linux/arch/sh/kernel/setup_bigsur.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/setup_bigsur.c Wed Jun 27 13:55:29 2001 @@ -0,0 +1,381 @@ +/* + * + * By Dustin McIntire (dustin@sensoria.com) (c)2001 + * + * Setup and IRQ handling code for the HD64465 companion chip. + * by Greg Banks + * Copyright (c) 2000 PocketPenguins Inc + * + * Derived from setup_hd64465.c which bore the message: + * Greg Banks + * Copyright (c) 2000 PocketPenguins Inc and + * Copyright (C) 2000 YAEGASHI Takeshi + * and setup_cqreek.c which bore message: + * Copyright (C) 2000 Niibe Yutaka + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Setup and IRQ functions for a Hitachi Big Sur Evaluation Board. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +//#define BIGSUR_DEBUG 3 +#undef BIGSUR_DEBUG + +#ifdef BIGSUR_DEBUG +#define DPRINTK(args...) printk(args) +#define DIPRINTK(n, args...) if (BIGSUR_DEBUG>(n)) printk(args) +#else +#define DPRINTK(args...) +#define DIPRINTK(n, args...) +#endif /* BIGSUR_DEBUG */ + +#ifdef CONFIG_HD64465 +extern int hd64465_irq_demux(int irq); +#endif /* CONFIG_HD64465 */ + + +/*===========================================================*/ +// Big Sur CPLD IRQ Routines +/*===========================================================*/ + +/* Level 1 IRQ routines */ +static void disable_bigsur_l1irq(unsigned int irq) +{ + unsigned long flags; + unsigned char mask; + unsigned int mask_port = ((irq - BIGSUR_IRQ_LOW)/8) ? BIGSUR_IRLMR1 : BIGSUR_IRLMR0; + unsigned char bit = (1 << ((irq - MGATE_IRQ_LOW)%8) ); + + if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) { + DPRINTK("Disable L1 IRQ %d\n", irq); + DIPRINTK(2,"disable_bigsur_l1irq: IMR=0x%08x mask=0x%x\n", + mask_port, bit); + save_and_cli(flags); + + /* Disable IRQ - set mask bit */ + mask = inb(mask_port) | bit; + outb(mask, mask_port); + restore_flags(flags); + return; + } + DPRINTK("disable_bigsur_l1irq: Invalid IRQ %d\n", irq); +} + +static void enable_bigsur_l1irq(unsigned int irq) +{ + unsigned long flags; + unsigned char mask; + unsigned int mask_port = ((irq - BIGSUR_IRQ_LOW)/8) ? BIGSUR_IRLMR1 : BIGSUR_IRLMR0; + unsigned char bit = (1 << ((irq - MGATE_IRQ_LOW)%8) ); + + if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) { + DPRINTK("Enable L1 IRQ %d\n", irq); + DIPRINTK(2,"enable_bigsur_l1irq: IMR=0x%08x mask=0x%x\n", + mask_port, bit); + save_and_cli(flags); + /* Enable L1 IRQ - clear mask bit */ + mask = inb(mask_port) & ~bit; + outb(mask, mask_port); + restore_flags(flags); + return; + } + DPRINTK("enable_bigsur_l1irq: Invalid IRQ %d\n", irq); +} + + +/* Level 2 irq masks and registers for L2 decoding */ +/* Level2 bitmasks for each level 1 IRQ */ +const u32 bigsur_l2irq_mask[] = + {0x40,0x80,0x08,0x01,0x01,0x3C,0x3E,0xFF,0x40,0x80,0x06,0x03}; +/* Level2 to ISR[n] map for each level 1 IRQ */ +const u32 bigsur_l2irq_reg[] = + { 2, 2, 3, 3, 1, 2, 1, 0, 1, 1, 3, 2}; +/* Level2 to Level 1 IRQ map */ +const u32 bigsur_l2_l1_map[] = + {7,7,7,7,7,7,7,7, 4,6,6,6,6,6,8,9, 11,11,5,5,5,5,0,1, 3,10,10,2,-1,-1,-1,-1}; +/* IRQ inactive level (high or low) */ +const u32 bigsur_l2_inactv_state[] = {0x00, 0xBE, 0xFC, 0xF7}; + +/* CPLD external status and mask registers base and offsets */ +static const u32 isr_base = BIGSUR_IRQ0; +static const u32 isr_offset = BIGSUR_IRQ0 - BIGSUR_IRQ1; +static const u32 imr_base = BIGSUR_IMR0; +static const u32 imr_offset = BIGSUR_IMR0 - BIGSUR_IMR1; + +#define REG_NUM(irq) ((irq-BIGSUR_2NDLVL_IRQ_LOW)/8 ) + +/* Level 2 IRQ routines */ +static void disable_bigsur_l2irq(unsigned int irq) +{ + unsigned long flags; + unsigned char mask; + unsigned char bit = 1 << ((irq-BIGSUR_2NDLVL_IRQ_LOW)%8); + unsigned int mask_port = imr_base - REG_NUM(irq)*imr_offset; + + if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) { + DPRINTK("Disable L2 IRQ %d\n", irq); + DIPRINTK(2,"disable_bigsur_l2irq: IMR=0x%08x mask=0x%x\n", + mask_port, bit); + save_and_cli(flags); + + /* Disable L2 IRQ - set mask bit */ + mask = inb(mask_port) | bit; + outb(mask, mask_port); + restore_flags(flags); + return; + } + DPRINTK("disable_bigsur_l2irq: Invalid IRQ %d\n", irq); +} + +static void enable_bigsur_l2irq(unsigned int irq) +{ + unsigned long flags; + unsigned char mask; + unsigned char bit = 1 << ((irq-BIGSUR_2NDLVL_IRQ_LOW)%8); + unsigned int mask_port = imr_base - REG_NUM(irq)*imr_offset; + + if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) { + DPRINTK("Enable L2 IRQ %d\n", irq); + DIPRINTK(2,"enable_bigsur_l2irq: IMR=0x%08x mask=0x%x\n", + mask_port, bit); + save_and_cli(flags); + + /* Enable L2 IRQ - clear mask bit */ + mask = inb(mask_port) & ~bit; + outb(mask, mask_port); + restore_flags(flags); + return; + } + DPRINTK("enable_bigsur_l2irq: Invalid IRQ %d\n", irq); +} + +static void mask_and_ack_bigsur(unsigned int irq) +{ + DPRINTK("mask_and_ack_bigsur IRQ %d\n", irq); + if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) + disable_bigsur_l1irq(irq); + else + disable_bigsur_l2irq(irq); +} + +static void end_bigsur_irq(unsigned int irq) +{ + DPRINTK("end_bigsur_irq IRQ %d\n", irq); + if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) + enable_bigsur_l1irq(irq); + else + enable_bigsur_l2irq(irq); +} + +static unsigned int startup_bigsur_irq(unsigned int irq) +{ + u8 mask; + u32 reg; + + DPRINTK("startup_bigsur_irq IRQ %d\n", irq); + + if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) { + /* Enable the L1 IRQ */ + enable_bigsur_l1irq(irq); + /* Enable all L2 IRQs in this L1 IRQ */ + mask = ~(bigsur_l2irq_mask[irq-BIGSUR_IRQ_LOW]); + reg = imr_base - bigsur_l2irq_reg[irq-BIGSUR_IRQ_LOW] * imr_offset; + mask &= inb(reg); + outb(mask,reg); + DIPRINTK(2,"startup_bigsur_irq: IMR=0x%08x mask=0x%x\n",reg,inb(reg)); + } + else { + /* Enable the L2 IRQ - clear mask bit */ + enable_bigsur_l2irq(irq); + /* Enable the L1 bit masking this L2 IRQ */ + enable_bigsur_l1irq(bigsur_l2_l1_map[irq-BIGSUR_2NDLVL_IRQ_LOW]); + DIPRINTK(2,"startup_bigsur_irq: L1=%d L2=%d\n", + bigsur_l2_l1_map[irq-BIGSUR_2NDLVL_IRQ_LOW],irq); + } + return 0; +} + +static void shutdown_bigsur_irq(unsigned int irq) +{ + DPRINTK("shutdown_bigsur_irq IRQ %d\n", irq); + if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) + disable_bigsur_l1irq(irq); + else + disable_bigsur_l2irq(irq); +} + +/* Define the IRQ structures for the L1 and L2 IRQ types */ +static struct hw_interrupt_type bigsur_l1irq_type = { + "BigSur-CPLD-Level1-IRQ", + startup_bigsur_irq, + shutdown_bigsur_irq, + enable_bigsur_l1irq, + disable_bigsur_l1irq, + mask_and_ack_bigsur, + end_bigsur_irq +}; + +static struct hw_interrupt_type bigsur_l2irq_type = { + "BigSur-CPLD-Level2-IRQ", + startup_bigsur_irq, + shutdown_bigsur_irq, + enable_bigsur_l2irq, + disable_bigsur_l2irq, + mask_and_ack_bigsur, + end_bigsur_irq +}; + + +static void make_bigsur_l1isr(unsigned int irq) { + + /* sanity check first */ + if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) { + /* save the handler in the main description table */ + irq_desc[irq].handler = &bigsur_l1irq_type; + irq_desc[irq].status = IRQ_DISABLED; + irq_desc[irq].action = 0; + irq_desc[irq].depth = 1; + + disable_bigsur_l1irq(irq); + return; + } + DPRINTK("make_bigsur_l1isr: bad irq, %d\n", irq); + return; +} + +static void make_bigsur_l2isr(unsigned int irq) { + + /* sanity check first */ + if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) { + /* save the handler in the main description table */ + irq_desc[irq].handler = &bigsur_l2irq_type; + irq_desc[irq].status = IRQ_DISABLED; + irq_desc[irq].action = 0; + irq_desc[irq].depth = 1; + + disable_bigsur_l2irq(irq); + return; + } + DPRINTK("make_bigsur_l2isr: bad irq, %d\n", irq); + return; +} + +/* The IRQ's will be decoded as follows: + * If a level 2 handler exists and there is an unmasked active + * IRQ, the 2nd level handler will be called. + * If a level 2 handler does not exist for the active IRQ + * the 1st level handler will be called. + */ + +int bigsur_irq_demux(int irq) +{ + int dmux_irq = irq; + u8 mask, actv_irqs; + u32 reg_num; + + DIPRINTK(3,"bigsur_irq_demux, irq=%d\n", irq); + /* decode the 1st level IRQ */ + if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) { + /* Get corresponding L2 ISR bitmask and ISR number */ + mask = bigsur_l2irq_mask[irq-BIGSUR_IRQ_LOW]; + reg_num = bigsur_l2irq_reg[irq-BIGSUR_IRQ_LOW]; + /* find the active IRQ's (XOR with inactive level)*/ + actv_irqs = inb(isr_base-reg_num*isr_offset) ^ + bigsur_l2_inactv_state[reg_num]; + /* decode active IRQ's */ + actv_irqs = actv_irqs & mask & ~(inb(imr_base-reg_num*imr_offset)); + /* if NEZ then we have an active L2 IRQ */ + if(actv_irqs) dmux_irq = ffz(~actv_irqs) + reg_num*8+BIGSUR_2NDLVL_IRQ_LOW; + /* if no 2nd level IRQ action, but has 1st level, use 1st level handler */ + if(!irq_desc[dmux_irq].action && irq_desc[irq].action) + dmux_irq = irq; + DIPRINTK(1,"bigsur_irq_demux: irq=%d dmux_irq=%d mask=0x%04x reg=%d\n", + irq, dmux_irq, mask, reg_num); + } +#ifdef CONFIG_HD64465 + dmux_irq = hd64465_irq_demux(dmux_irq); +#endif /* CONFIG_HD64465 */ + DIPRINTK(3,"bigsur_irq_demux, demux_irq=%d\n", dmux_irq); + + return dmux_irq; +} + +/*===========================================================*/ +// Big Sur Init Routines +/*===========================================================*/ +void __init init_bigsur_IRQ(void) +{ + int i; + + if (!MACH_BIGSUR) return; + + /* Create ISR's for Big Sur CPLD IRQ's */ + /*==============================================================*/ + for(i=BIGSUR_IRQ_LOW;i + * + * This file is part of the LinuxDC project (www.linuxdc.org) + * + * Released under the terms of the GNU GPL v2.0. + * + * This file originally bore the message: + * $Id: setup_dc.c,v 1.5 2001/05/24 05:09:16 mrbrown Exp $ * SEGA Dreamcast support */ @@ -9,105 +19,167 @@ #include #include #include -#include #include #include +#include -#define GAPSPCI_REGS 0x01001400 -#define GAPSPCI_DMA_BASE 0x01840000 -#define GAPSPCI_DMA_SIZE 32768 -#define GAPSPCI_BBA_CONFIG 0x01001600 +int __init gapspci_init(void); -#define GAPSPCI_IRQ 11 -#define GAPSPCI_INTC 0x005f6924 +#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) -static int gapspci_dma_used; +/* Dreamcast System ASIC Hardware Events - + + The Dreamcast's System ASIC (located on the PowerVR2 chip) is responsible + for receiving hardware events from system peripherals and triggering an + SH7750 IRQ. Hardware events can trigger IRQs 13, 11, or 9 depending on + which bits are set in the Event Mask Registers (EMRs). When a hardware + event is triggered, it's corresponding bit in the Event Status Registers + (ESRs) is set, and that bit should be rewritten to the ESR to acknowledge + that event. -static struct pci_bus *pci_root_bus; + There are three 32-bit ESRs located at 0xa05f8900 - 0xa05f6908. Event + types can be found in include/asm-sh/dc_sysasic.h. There are three groups + of EMRs that parallel the ESRs. Each EMR group corresponds to an IRQ, so + 0xa05f6910 - 0xa05f6918 triggers IRQ 13, 0xa05f6920 - 0xa05f6928 triggers + IRQ 11, and 0xa05f6930 - 0xa05f6938 triggers IRQ 9. -static void disable_gapspci_irq(unsigned int irq) -{ - unsigned long flags; - unsigned long intc; + In the kernel, these events are mapped to virtual IRQs so that drivers can + respond to them as they would a normal interrupt. In order to keep this + mapping simple, the events are mapped as: - save_and_cli(flags); - intc = inl(GAPSPCI_INTC); - intc &= ~(1<<3); - outl(intc, GAPSPCI_INTC); - restore_flags(flags); -} + 6900/6910 - Events 0-31, IRQ 13 + 6904/6924 - Events 32-63, IRQ 11 + 6908/6938 - Events 64-95, IRQ 9 +*/ -static void enable_gapspci_irq(unsigned int irq) -{ - unsigned long flags; - unsigned long intc; +#define ESR_BASE 0x005f6900 /* Base event status register */ +#define EMR_BASE 0x005f6910 /* Base event mask register */ - save_and_cli(flags); - intc = inl(GAPSPCI_INTC); - intc |= (1<<3); - outl(intc, GAPSPCI_INTC); - restore_flags(flags); -} +/* Helps us determine the EMR group that this event belongs to: 0 = 0x6910, + 1 = 0x6920, 2 = 0x6930; also determine the event offset */ +#define LEVEL(event) (((event) - HW_EVENT_IRQ_BASE) / 32) + +/* Return the hardware event's bit positon within the EMR/ESR */ +#define EVENT_BIT(event) (((event) - HW_EVENT_IRQ_BASE) & 31) +/* For each of these *_irq routines, the IRQ passed in is the virtual IRQ + (logically mapped to the corresponding bit for the hardware event). */ -static void mask_and_ack_gapspci_irq(unsigned int irq) +/* Disable the hardware event by masking its bit in its EMR */ +static inline void disable_systemasic_irq(unsigned int irq) { - unsigned long flags; - unsigned long intc; + __u32 emr = EMR_BASE + (LEVEL(irq) << 4) + (LEVEL(irq) << 2); + __u32 mask; + mask = inl(emr); + mask &= ~(1 << EVENT_BIT(irq)); + outl(mask, emr); +} - save_and_cli(flags); - intc = inl(GAPSPCI_INTC); - intc &= ~(1<<3); - outl(intc, GAPSPCI_INTC); - restore_flags(flags); +/* Enable the hardware event by setting its bit in its EMR */ +static inline void enable_systemasic_irq(unsigned int irq) +{ + __u32 emr = EMR_BASE + (LEVEL(irq) << 4) + (LEVEL(irq) << 2); + __u32 mask; + mask = inl(emr); + mask |= (1 << EVENT_BIT(irq)); + outl(mask, emr); } +/* Acknowledge a hardware event by writing its bit back to its ESR */ +static void ack_systemasic_irq(unsigned int irq) +{ + __u32 esr = ESR_BASE + (LEVEL(irq) << 2); + disable_systemasic_irq(irq); + outl((1 << EVENT_BIT(irq)), esr); +} -static void end_gapspci_irq(unsigned int irq) +/* After a IRQ has been ack'd and responded to, it needs to be renabled */ +static void end_systemasic_irq(unsigned int irq) { - enable_gapspci_irq(irq); + enable_systemasic_irq(irq); } +static unsigned int startup_systemasic_irq(unsigned int irq) +{ + enable_systemasic_irq(irq); -static unsigned int startup_gapspci_irq(unsigned int irq) -{ - enable_gapspci_irq(irq); return 0; } - -static void shutdown_gapspci_irq(unsigned int irq) +static void shutdown_systemasic_irq(unsigned int irq) { - disable_gapspci_irq(irq); + disable_systemasic_irq(irq); } - -static struct hw_interrupt_type gapspci_irq_type = { - "GAPSPCI-IRQ", - startup_gapspci_irq, - shutdown_gapspci_irq, - enable_gapspci_irq, - disable_gapspci_irq, - mask_and_ack_gapspci_irq, - end_gapspci_irq +static struct hw_interrupt_type systemasic_int = { + typename: "System ASIC", + startup: startup_systemasic_irq, + shutdown: shutdown_systemasic_irq, + enable: enable_systemasic_irq, + disable: disable_systemasic_irq, + ack: ack_systemasic_irq, + end: end_systemasic_irq, }; - -static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin) +/* + * Map the hardware event indicated by the processor IRQ to a virtual IRQ. + */ +int systemasic_irq_demux(int irq) { - return PCI_SLOT(dev->devfn); -} + __u32 emr, esr, status, level; + __u32 j, bit; -static int __init map_od_irq(struct pci_dev *dev, u8 slot, u8 pin) -{ - return GAPSPCI_IRQ; + switch (irq) { + case 13: + level = 0; + break; + case 11: + level = 1; + break; + case 9: + level = 2; + break; + default: + return irq; + } + emr = EMR_BASE + (level << 4) + (level << 2); + esr = ESR_BASE + (level << 2); + + /* Mask the ESR to filter any spurious, unwanted interrtupts */ + status = inl(esr); + status &= inl(emr); + + /* Now scan and find the first set bit as the event to map */ + for (bit = 1, j = 0; j < 32; bit <<= 1, j++) { + if (status & bit) { + irq = HW_EVENT_IRQ_BASE + j + (level << 5); + return irq; + } + } + + /* Not reached */ + return irq; } int __init setup_dreamcast(void) { + int i; + + /* Mask all hardware events */ + /* XXX */ + + /* Acknowledge any previous events */ + /* XXX */ + + /* Assign all virtual IRQs to the System ASIC int. handler */ + for (i = HW_EVENT_IRQ_BASE; i < HW_EVENT_IRQ_MAX; i++) + irq_desc[i].handler = &systemasic_int; + +#ifdef CONFIG_PCI gapspci_init(); +#endif printk(KERN_INFO "SEGA Dreamcast support.\n"); #if 0 @@ -128,232 +200,5 @@ * PCR: 0x0000 */ #endif - return 0; -} - - -/* - * Dreamcast PCI: Supports SEGA Broadband Adaptor only. - */ - -#define BBA_SELECTED(dev) (dev->bus->number==0 && dev->devfn==0) - -static int gapspci_read_config_byte(struct pci_dev *dev, int where, - u8 * val) -{ - if (BBA_SELECTED(dev)) - *val = inb(GAPSPCI_BBA_CONFIG+where); - else - *val = 0xff; - - return PCIBIOS_SUCCESSFUL; -} - -static int gapspci_read_config_word(struct pci_dev *dev, int where, - u16 * val) -{ - if (BBA_SELECTED(dev)) - *val = inw(GAPSPCI_BBA_CONFIG+where); - else - *val = 0xffff; - - return PCIBIOS_SUCCESSFUL; -} - -static int gapspci_read_config_dword(struct pci_dev *dev, int where, - u32 * val) -{ - if (BBA_SELECTED(dev)) - *val = inl(GAPSPCI_BBA_CONFIG+where); - else - *val = 0xffffffff; - - return PCIBIOS_SUCCESSFUL; -} - -static int gapspci_write_config_byte(struct pci_dev *dev, int where, - u8 val) -{ - if (BBA_SELECTED(dev)) - outb(val, GAPSPCI_BBA_CONFIG+where); - - return PCIBIOS_SUCCESSFUL; -} - - -static int gapspci_write_config_word(struct pci_dev *dev, int where, - u16 val) -{ - if (BBA_SELECTED(dev)) - outw(val, GAPSPCI_BBA_CONFIG+where); - - return PCIBIOS_SUCCESSFUL; -} - -static int gapspci_write_config_dword(struct pci_dev *dev, int where, - u32 val) -{ - if (BBA_SELECTED(dev)) - outl(val, GAPSPCI_BBA_CONFIG+where); - - return PCIBIOS_SUCCESSFUL; -} - -static struct pci_ops pci_config_ops = { - gapspci_read_config_byte, - gapspci_read_config_word, - gapspci_read_config_dword, - gapspci_write_config_byte, - gapspci_write_config_word, - gapspci_write_config_dword -}; - - -void pcibios_align_resource(void *data, struct resource *res, - unsigned long size) -{ -} - - -void __init pcibios_update_irq(struct pci_dev *dev, int irq) -{ -} - - -void __init pcibios_update_resource(struct pci_dev *dev, struct resource *root, - struct resource *res, int resource) -{ -} - - -int pcibios_enable_device(struct pci_dev *dev) -{ - - u16 cmd, old_cmd; - int idx; - struct resource *r; - - pci_read_config_word(dev, PCI_COMMAND, &cmd); - old_cmd = cmd; - for (idx = 0; idx < 6; idx++) { - r = dev->resource + idx; - if (!r->start && r->end) { - printk(KERN_ERR - "PCI: Device %s not available because" - " of resource collisions\n", - dev->slot_name); - return -EINVAL; - } - if (r->flags & IORESOURCE_IO) - cmd |= PCI_COMMAND_IO; - if (r->flags & IORESOURCE_MEM) - cmd |= PCI_COMMAND_MEMORY; - } - if (cmd != old_cmd) { - printk("PCI: enabling device %s (%04x -> %04x)\n", - dev->slot_name, old_cmd, cmd); - pci_write_config_word(dev, PCI_COMMAND, cmd); - } - return 0; - -} - - -void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, - dma_addr_t * dma_handle) -{ - unsigned long buf; - - if (gapspci_dma_used+size > GAPSPCI_DMA_SIZE) - return NULL; - - buf = GAPSPCI_DMA_BASE+gapspci_dma_used; - - gapspci_dma_used = PAGE_ALIGN(gapspci_dma_used+size); - - printk("pci_alloc_consistent: %d bytes at 0x%08x\n", size, buf); - - *dma_handle = (dma_addr_t)buf; - - return (void *)P2SEGADDR(buf); -} - - -void pci_free_consistent(struct pci_dev *hwdev, size_t size, - void *vaddr, dma_addr_t dma_handle) -{ -} - - -void __init -pcibios_fixup_pbus_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *ranges) -{ -} - -void __init pcibios_fixup_bus(struct pci_bus *bus) -{ - struct list_head *ln; - struct pci_dev *dev; - - for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) { - dev = pci_dev_b(ln); - if (!BBA_SELECTED(dev)) continue; - - printk("PCI: MMIO fixup to %s\n", dev->name); - dev->resource[1].start=0x01001700; - dev->resource[1].end=0x010017ff; - } -} - - -void __init dreamcast_pcibios_init(void) -{ - pci_root_bus = pci_scan_bus(0, &pci_config_ops, NULL); - /* pci_assign_unassigned_resources(); */ - pci_fixup_irqs(no_swizzle, map_od_irq); -} - - -static __init int gapspci_init(void) -{ - int i; - char idbuf[16]; - - for(i=0; i<16; i++) - idbuf[i]=inb(GAPSPCI_REGS+i); - - if(strncmp(idbuf, "GAPSPCI_BRIDGE_2", 16)) - return -1; - - outl(0x5a14a501, GAPSPCI_REGS+0x18); - - for(i=0; i<1000000; i++); - - if(inl(GAPSPCI_REGS+0x18)!=1) - return -1; - - outl(0x01000000, GAPSPCI_REGS+0x20); - outl(0x01000000, GAPSPCI_REGS+0x24); - - outl(GAPSPCI_DMA_BASE, GAPSPCI_REGS+0x28); - outl(GAPSPCI_DMA_BASE+GAPSPCI_DMA_SIZE, GAPSPCI_REGS+0x2c); - - outl(1, GAPSPCI_REGS+0x14); - outl(1, GAPSPCI_REGS+0x34); - - gapspci_dma_used=0; - - /* */ - irq_desc[GAPSPCI_IRQ].handler = &gapspci_irq_type; - - /* Setting Broadband Adapter */ - outw(0xf900, GAPSPCI_BBA_CONFIG+0x06); - outl(0x00000000, GAPSPCI_BBA_CONFIG+0x30); - outb(0x00, GAPSPCI_BBA_CONFIG+0x3c); - outb(0xf0, GAPSPCI_BBA_CONFIG+0x0d); - outw(0x0006, GAPSPCI_BBA_CONFIG+0x04); - outl(0x00002001, GAPSPCI_BBA_CONFIG+0x10); - outl(0x01000000, GAPSPCI_BBA_CONFIG+0x14); - return 0; } diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/setup_od.c linux/arch/sh/kernel/setup_od.c --- v2.4.5/linux/arch/sh/kernel/setup_od.c Mon Jun 19 17:59:37 2000 +++ linux/arch/sh/kernel/setup_od.c Wed Dec 31 16:00:00 1969 @@ -1,35 +0,0 @@ -/* $Id: setup_od.c,v 1.1 2000/06/14 09:35:59 stuart_menefy Exp $ - * - * arch/sh/kernel/setup_od.c - * - * Copyright (C) 2000 Stuart Menefy - * - * STMicroelectronics Overdrive Support. - * - */ - -#include -#include -#include - -/* - * Initialize the board - */ -int __init setup_od(void) -{ - /* Enable RS232 receive buffers */ - volatile int* p = (volatile int*)0xa3000000; - -#if defined(CONFIG_SH_ORION) - *p=1; -#elif defined(CONFIG_SH_OVERDRIVE) - *p=0x1e; -#else -#error Illegal configuration -#endif - - printk(KERN_INFO "STMicroelectronics Overdrive Setup...done\n"); - return 0; -} - -module_init(setup_od); diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/setup_sh2000.c linux/arch/sh/kernel/setup_sh2000.c --- v2.4.5/linux/arch/sh/kernel/setup_sh2000.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/setup_sh2000.c Wed Jun 27 13:55:29 2001 @@ -0,0 +1,95 @@ +/* + * linux/arch/sh/kernel/setup_sh2000.c + * + * Copyright (C) 2001 SUGIOKA Tochinobu + * + * SH-2000 Support. + * + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#define CF_CIS_BASE 0xb4200000 + +#define PORT_PECR 0xa4000108 +#define PORT_PHCR 0xa400010E +#define PORT_ICR1 0xa4000010 +#define PORT_IRR0 0xa4000004 + +/* + * Initialize the board + */ +int __init setup_sh2000(void) +{ + /* XXX: RTC setting comes here */ + + /* These should be done by BIOS/IPL ... */ + /* Enable nCE2A, nCE2B output */ + ctrl_outw(ctrl_inw(PORT_PECR) & ~0xf00, PORT_PECR); + /* Enable the Compact Flash card, and set the level interrupt */ + ctrl_outw(0x0042, CF_CIS_BASE+0x0200); + /* Enable interrupt */ + ctrl_outw(ctrl_inw(PORT_PHCR) & ~0x03f3, PORT_PHCR); + ctrl_outw(1, PORT_ICR1); + ctrl_outw(ctrl_inw(PORT_IRR0) & ~0xff3f, PORT_IRR0); + printk(KERN_INFO "SH-2000 Setup...done\n"); + return 0; +} +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_sh2000 __initmv = { + mv_name: "sh2000", + + mv_nr_irqs: 80, + + mv_inb: generic_inb, + mv_inw: generic_inw, + mv_inl: generic_inl, + mv_outb: generic_outb, + mv_outw: generic_outw, + mv_outl: generic_outl, + + mv_inb_p: generic_inb_p, + mv_inw_p: generic_inw_p, + mv_inl_p: generic_inl_p, + mv_outb_p: generic_outb_p, + mv_outw_p: generic_outw_p, + mv_outl_p: generic_outl_p, + + mv_insb: generic_insb, + mv_insw: generic_insw, + mv_insl: generic_insl, + mv_outsb: generic_outsb, + mv_outsw: generic_outsw, + mv_outsl: generic_outsl, + + mv_readb: generic_readb, + mv_readw: generic_readw, + mv_readl: generic_readl, + mv_writeb: generic_writeb, + mv_writew: generic_writew, + mv_writel: generic_writel, + + mv_init_arch: setup_sh2000, + + mv_isa_port2addr: sh2000_isa_port2addr, + + mv_ioremap: generic_ioremap, + mv_iounmap: generic_iounmap, + + mv_rtc_gettimeofday: sh_rtc_gettimeofday, + mv_rtc_settimeofday: sh_rtc_settimeofday, + + mv_hw_sh2000: 1, +}; +ALIAS_MV(sh2000) diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/sh_ksyms.c linux/arch/sh/kernel/sh_ksyms.c --- v2.4.5/linux/arch/sh/kernel/sh_ksyms.c Wed Apr 11 21:24:52 2001 +++ linux/arch/sh/kernel/sh_ksyms.c Wed Jun 27 13:55:29 2001 @@ -18,6 +18,7 @@ #include #include #include +#include #include extern void dump_thread(struct pt_regs *, struct user *); @@ -44,14 +45,25 @@ EXPORT_SYMBOL(strpbrk); EXPORT_SYMBOL(strstr); EXPORT_SYMBOL(strlen); +EXPORT_SYMBOL(strnlen); EXPORT_SYMBOL(strchr); EXPORT_SYMBOL(strcat); EXPORT_SYMBOL(strncat); +/* PCI exports */ +#ifdef CONFIG_PCI +EXPORT_SYMBOL(pci_alloc_consistent); +EXPORT_SYMBOL(pci_free_consistent); +EXPORT_SYMBOL(pcibios_penalize_isa_irq); +#endif + /* mem exports */ EXPORT_SYMBOL(memchr); EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(memcpy_fromio); +EXPORT_SYMBOL(memcpy_toio); EXPORT_SYMBOL(memset); +EXPORT_SYMBOL(memset_io); EXPORT_SYMBOL(memmove); EXPORT_SYMBOL(memcmp); @@ -63,20 +75,32 @@ EXPORT_SYMBOL(get_vm_area); +/* semaphore exports */ +EXPORT_SYMBOL(__up); +EXPORT_SYMBOL(__down); +EXPORT_SYMBOL(__down_interruptible); + +EXPORT_SYMBOL(__udelay); +EXPORT_SYMBOL(__const_udelay); + #define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL_NOVERS(name) /* These symbols are generated by the compiler itself */ DECLARE_EXPORT(__udivsi3); DECLARE_EXPORT(__sdivsi3); +DECLARE_EXPORT(__ashrdi3); +DECLARE_EXPORT(__ashldi3); +DECLARE_EXPORT(__lshrdi3); +DECLARE_EXPORT(__movstr); #ifdef __SH4__ DECLARE_EXPORT(__movstr_i4_even); DECLARE_EXPORT(__movstr_i4_odd); -DECLARE_EXPORT(__ashrdi3); -DECLARE_EXPORT(__ashldi3); /* needed by some modules */ +EXPORT_SYMBOL(flush_cache_all); +EXPORT_SYMBOL(flush_cache_range); EXPORT_SYMBOL(flush_dcache_page); #endif EXPORT_SYMBOL(flush_tlb_page); diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/time.c linux/arch/sh/kernel/time.c --- v2.4.5/linux/arch/sh/kernel/time.c Wed Apr 11 21:24:52 2001 +++ linux/arch/sh/kernel/time.c Wed Jun 27 13:55:29 2001 @@ -64,7 +64,11 @@ #define CCN_PVR_CHIP_MASK 0xff #define CCN_PVR_CHIP_ST40STB1 0x4 -#endif +#ifdef CONFIG_CPU_SUBTYPE_ST40STB1 +#define CLOCKGEN_MEMCLKCR 0xbb040038 +#define MEMCLKCR_RATIO_MASK 0x7 +#endif /* CONFIG_CPU_SUBTYPE_ST40STB1 */ +#endif /* __sh3__ or __SH4__ */ extern rwlock_t xtime_lock; extern unsigned long wall_jiffies; @@ -285,6 +289,9 @@ void __init time_init(void) { unsigned int cpu_clock, master_clock, bus_clock, module_clock; +#ifdef CONFIG_CPU_SUBTYPE_ST40STB1 + unsigned int memory_clock; +#endif unsigned int timer_freq; unsigned short frqcr, ifc, pfc, bfc; unsigned long interval; @@ -335,23 +342,35 @@ { 0x123, {{1,4}, {1,4}, {1,8}}}, { 0x16C, {{1,4}, {1,8}, {1,8}}}, }; + + struct memclk_data { + unsigned char multiplier; + unsigned char divisor; + }; + static struct memclk_data st40_memclk_table[8] = { + {1,1}, // 000 + {1,2}, // 001 + {1,3}, // 010 + {2,3}, // 011 + {1,4}, // 100 + {1,6}, // 101 + {1,8}, // 110 + {1,8} // 111 + }; #endif #endif -#if defined(CONFIG_SH_DREAMCAST) - xtime.tv_sec = 0; - xtime.tv_usec = 0; -#else - rtc_gettimeofday(&xtime); -#endif + if (MACH_DREAMCAST) + xtime.tv_sec = xtime.tv_usec = 0; + else + rtc_gettimeofday(&xtime); setup_irq(TIMER_IRQ, &irq0); -#if defined(CONFIG_SH_DREAMCAST) - timer_freq = 50*1000*1000/4; -#else - timer_freq = get_timer_frequency(); -#endif + if (MACH_DREAMCAST) + timer_freq = 50*1000*1000/4; + else + timer_freq = get_timer_frequency(); module_clock = timer_freq * 4; @@ -386,6 +405,8 @@ /* Unfortunatly the STB1 FRQCR values are different from the 7750 ones */ struct frqcr_data *d; int a; + unsigned long memclkcr; + struct memclk_data *e; for (a=0; afactor[0].multiplier, d->factor[0].divisor, d->factor[1].multiplier, d->factor[1].divisor, + e->multiplier, e->divisor, d->factor[2].multiplier, d->factor[2].divisor); master_clock = module_clock * d->factor[2].divisor / d->factor[2].multiplier; bus_clock = master_clock * d->factor[1].multiplier / d->factor[1].divisor; + memory_clock = master_clock * e->multiplier / e->divisor; cpu_clock = master_clock * d->factor[0].multiplier / d->factor[0].divisor; goto skip_calc; } else @@ -418,11 +444,17 @@ master_clock = module_clock * pfc; bus_clock = master_clock / bfc; cpu_clock = master_clock / ifc; +#ifdef CONFIG_CPU_SUBTYPE_ST40STB1 skip_calc: +#endif printk("CPU clock: %d.%02dMHz\n", (cpu_clock / 1000000), (cpu_clock % 1000000)/10000); printk("Bus clock: %d.%02dMHz\n", (bus_clock/1000000), (bus_clock % 1000000)/10000); +#ifdef CONFIG_CPU_SUBTYPE_ST40STB1 + printk("Memory clock: %d.%02dMHz\n", + (memory_clock/1000000), (memory_clock % 1000000)/10000); +#endif printk("Module clock: %d.%02dMHz\n", (module_clock/1000000), (module_clock % 1000000)/10000); interval = (module_clock/4 + HZ/2) / HZ; @@ -432,6 +464,9 @@ current_cpu_data.cpu_clock = cpu_clock; current_cpu_data.master_clock = master_clock; current_cpu_data.bus_clock = bus_clock; +#ifdef CONFIG_CPU_SUBTYPE_ST40STB1 + current_cpu_data.memory_clock = memory_clock; +#endif current_cpu_data.module_clock = module_clock; /* Start TMU0 */ diff -u --recursive --new-file v2.4.5/linux/arch/sh/mm/cache.c linux/arch/sh/mm/cache.c --- v2.4.5/linux/arch/sh/mm/cache.c Sun May 20 12:11:38 2001 +++ linux/arch/sh/mm/cache.c Wed Jun 27 13:55:29 2001 @@ -151,7 +151,8 @@ #elif defined(__SH4__) #ifdef CONFIG_CPU_SUBTYPE_ST40STB1 cpu_data->type = CPU_ST40STB1; -#elif defined(CONFIG_CPU_SUBTYPE_SH7750) +#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || \ + defined(CONFIG_CPU_SUBTYPE_SH7751) cpu_data->type = CPU_SH7750; #else #error Unknown SH4 CPU type diff -u --recursive --new-file v2.4.5/linux/arch/sh/mm/fault.c linux/arch/sh/mm/fault.c --- v2.4.5/linux/arch/sh/mm/fault.c Mon Mar 19 12:35:10 2001 +++ linux/arch/sh/mm/fault.c Wed Jun 27 13:55:29 2001 @@ -281,11 +281,12 @@ { unsigned long flags; unsigned long pteval; - unsigned long pteaddr; + unsigned long vpn; +#if defined(__SH4__) unsigned long ptea; +#endif save_and_cli(flags); - #if defined(__SH4__) if (pte_shared(pte)) { struct page *pg; @@ -305,13 +306,13 @@ } /* Set PTEH register */ - pteaddr = (address & MMU_VPN_MASK) | get_asid(); - ctrl_outl(pteaddr, MMU_PTEH); + vpn = (address & MMU_VPN_MASK) | get_asid(); + ctrl_outl(vpn, MMU_PTEH); - /* Set PTEA register */ - /* TODO: make this look less hacky */ pteval = pte_val(pte); #if defined(__SH4__) + /* Set PTEA register */ + /* TODO: make this look less hacky */ ptea = ((pteval >> 28) & 0xe) | (pteval & 0x1); ctrl_outl(ptea, MMU_PTEA); #endif @@ -341,9 +342,9 @@ data = (page & 0xfffe0000) | asid; /* VALID bit is off */ ctrl_outl(data, addr); #elif defined(__SH4__) - jump_to_P2(); addr = MMU_UTLB_ADDRESS_ARRAY | MMU_PAGE_ASSOC_BIT; data = page | asid; /* VALID bit is off */ + jump_to_P2(); ctrl_outl(data, addr); back_to_P1(); #endif @@ -352,27 +353,34 @@ #if defined(__SH4__) static void __flush_tlb_phys(unsigned long phys) { - int i; - unsigned long addr, data; + unsigned long addr, data, pte; - jump_to_P2(); - for (i = 0; i < MMU_UTLB_ENTRIES; i++) { - addr = MMU_UTLB_DATA_ARRAY | (i<bdata->node_boot_start >> PAGE_SHIFT) @@ -120,7 +120,7 @@ /* We don't need kernel mapping as hardware support that. */ pg_dir = swapper_pg_dir; - for (i=0; i < USER_PTRS_PER_PGD*2; i++) + for (i=0; i < PTRS_PER_PGD; i++) pgd_val(pg_dir[i]) = 0; /* Enable MMU */ diff -u --recursive --new-file v2.4.5/linux/arch/sh/stboards/Makefile linux/arch/sh/stboards/Makefile --- v2.4.5/linux/arch/sh/stboards/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/stboards/Makefile Wed Jun 27 13:55:29 2001 @@ -0,0 +1,15 @@ +# +# Makefile for STMicroelectronics board specific parts of the kernel +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +all: stboards.o +O_TARGET := stboards.o +obj-y := irq.o setup.o mach.o led.o + +clean: + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.5/linux/arch/sh/stboards/harp.h linux/arch/sh/stboards/harp.h --- v2.4.5/linux/arch/sh/stboards/harp.h Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/stboards/harp.h Wed Jun 27 13:55:29 2001 @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Defintions applicable to the STMicroelectronics ST40STB1 HARP and + * compatible boards. + */ + +#if defined(CONFIG_SH_STB1_HARP) + +#define EPLD_BASE 0xa0800000 + +#define EPLD_LED (EPLD_BASE+0x000c0000) +#define EPLD_INTSTAT0 (EPLD_BASE+0x00200000) +#define EPLD_INTSTAT1 (EPLD_BASE+0x00240000) +#define EPLD_INTMASK0 (EPLD_BASE+0x00280000) +#define EPLD_INTMASK1 (EPLD_BASE+0x002c0000) +#define EPLD_PAGEADDR (EPLD_BASE+0x00300000) +#define EPLD_REVID1 (EPLD_BASE+0x00380000) +#define EPLD_REVID2 (EPLD_BASE+0x003c0000) + +#define EPLD_LED_ON 1 +#define EPLD_LED_OFF 0 + +#elif defined(CONFIG_SH_STB1_OVERDRIVE) + +#define EPLD_BASE 0xa7000000 + +#define EPLD_REVID (EPLD_BASE+0x00000000) +#define EPLD_LED (EPLD_BASE+0x00040000) +#define EPLD_INTMASK0 (EPLD_BASE+0x001c0000) +#define EPLD_INTMASK1 (EPLD_BASE+0x00200000) +#define EPLD_INTSTAT0 (EPLD_BASE+0x00240000) +#define EPLD_INTSTAT1 (EPLD_BASE+0x00280000) + +#define EPLD_LED_ON 0 +#define EPLD_LED_OFF 1 + +#else +#error Unknown board +#endif diff -u --recursive --new-file v2.4.5/linux/arch/sh/stboards/irq.c linux/arch/sh/stboards/irq.c --- v2.4.5/linux/arch/sh/stboards/irq.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/stboards/irq.c Wed Jun 27 13:55:29 2001 @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2000 David J. Mckay (david.mckay@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Looks after interrupts on the HARP board. + * + * Bases on the IPR irq system + */ + +#include +#include +#include + +#include +#include + +#include "harp.h" + + +#define NUM_EXTERNAL_IRQS 16 + +// Early versions of the STB1 Overdrive required this nasty frig +//#define INVERT_INTMASK_WRITES + +static void enable_harp_irq(unsigned int irq); +static void disable_harp_irq(unsigned int irq); + +/* shutdown is same as "disable" */ +#define shutdown_harp_irq disable_harp_irq + +static void mask_and_ack_harp(unsigned int); +static void end_harp_irq(unsigned int irq); + +static unsigned int startup_harp_irq(unsigned int irq) +{ + enable_harp_irq(irq); + return 0; /* never anything pending */ +} + +static struct hw_interrupt_type harp_irq_type = { + "Harp-IRQ", + startup_harp_irq, + shutdown_harp_irq, + enable_harp_irq, + disable_harp_irq, + mask_and_ack_harp, + end_harp_irq +}; + +static void disable_harp_irq(unsigned int irq) +{ + unsigned val, flags; + unsigned maskReg; + unsigned mask; + int pri; + + if (irq < 0 || irq >= NUM_EXTERNAL_IRQS) + return; + + pri = 15 - irq; + + if (pri < 8) { + maskReg = EPLD_INTMASK0; + } else { + maskReg = EPLD_INTMASK1; + pri -= 8; + } + + save_and_cli(flags); + mask = ctrl_inl(maskReg); + mask &= (~(1 << pri)); +#if defined(INVERT_INTMASK_WRITES) + mask ^= 0xff; +#endif + ctrl_outl(mask, maskReg); + restore_flags(flags); +} + +static void enable_harp_irq(unsigned int irq) +{ + unsigned flags; + unsigned maskReg; + unsigned mask; + int pri; + + if (irq < 0 || irq >= NUM_EXTERNAL_IRQS) + return; + + pri = 15 - irq; + + if (pri < 8) { + maskReg = EPLD_INTMASK0; + } else { + maskReg = EPLD_INTMASK1; + pri -= 8; + } + + save_and_cli(flags); + mask = ctrl_inl(maskReg); + + + mask |= (1 << pri); + +#if defined(INVERT_INTMASK_WRITES) + mask ^= 0xff; +#endif + ctrl_outl(mask, maskReg); + + restore_flags(flags); +} + +/* This functions sets the desired irq handler to be an overdrive type */ +static void __init make_harp_irq(unsigned int irq) +{ + disable_irq_nosync(irq); + irq_desc[irq].handler = &harp_irq_type; + disable_harp_irq(irq); +} + +static void mask_and_ack_harp(unsigned int irq) +{ + disable_harp_irq(irq); +} + +static void end_harp_irq(unsigned int irq) +{ + enable_harp_irq(irq); +} + +void __init init_harp_irq(void) +{ + int i; + +#if !defined(INVERT_INTMASK_WRITES) + // On the harp these are set to enable an interrupt + ctrl_outl(0x00, EPLD_INTMASK0); + ctrl_outl(0x00, EPLD_INTMASK1); +#else + // On the Overdrive the data is inverted before being stored in the reg + ctrl_outl(0xff, EPLD_INTMASK0); + ctrl_outl(0xff, EPLD_INTMASK1); +#endif + + for (i = 0; i < NUM_EXTERNAL_IRQS; i++) { + make_harp_irq(i); + } +} diff -u --recursive --new-file v2.4.5/linux/arch/sh/stboards/led.c linux/arch/sh/stboards/led.c --- v2.4.5/linux/arch/sh/stboards/led.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/stboards/led.c Wed Jun 27 13:55:29 2001 @@ -0,0 +1,52 @@ +/* + * linux/arch/sh/stboards/led.c + * + * Copyright (C) 2000 Stuart Menefy + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * This file contains ST40STB1 HARP and compatible code. + */ + +#include +#include +#include "harp.h" + +/* Harp: Flash LD10 (front pannel) connected to EPLD (IC8) */ +/* Overdrive: Flash LD1 (front panel) connected to EPLD (IC4) */ +/* Works for HARP and overdrive */ +static void mach_led(int position, int value) +{ + if (value) { + ctrl_outl(EPLD_LED_ON, EPLD_LED); + } else { + ctrl_outl(EPLD_LED_OFF, EPLD_LED); + } +} + +#ifdef CONFIG_HEARTBEAT + +#include + +/* acts like an actual heart beat -- ie thump-thump-pause... */ +void heartbeat_harp(void) +{ + static unsigned cnt = 0, period = 0, dist = 0; + + if (cnt == 0 || cnt == dist) + mach_led( -1, 1); + else if (cnt == 7 || cnt == dist+7) + mach_led( -1, 0); + + if (++cnt > period) { + cnt = 0; + /* The hyperbolic function below modifies the heartbeat period + * length in dependency of the current (5min) load. It goes + * through the points f(0)=126, f(1)=86, f(5)=51, + * f(inf)->30. */ + period = ((672< + +#include +#include +#include +#include +#include + +void setup_harp(void); +void init_harp_irq(void); +void heartbeat_harp(void); + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_harp __initmv = { + mv_name: "STB1 Harp", + + mv_nr_irqs: 89 + HD64465_IRQ_NUM, + + mv_inb: hd64465_inb, + mv_inw: hd64465_inw, + mv_inl: hd64465_inl, + mv_outb: hd64465_outb, + mv_outw: hd64465_outw, + mv_outl: hd64465_outl, + + mv_inb_p: hd64465_inb_p, + mv_inw_p: hd64465_inw, + mv_inl_p: hd64465_inl, + mv_outb_p: hd64465_outb_p, + mv_outw_p: hd64465_outw, + mv_outl_p: hd64465_outl, + + mv_insb: hd64465_insb, + mv_insw: hd64465_insw, + mv_insl: hd64465_insl, + mv_outsb: hd64465_outsb, + mv_outsw: hd64465_outsw, + mv_outsl: hd64465_outsl, + + mv_readb: generic_readb, + mv_readw: generic_readw, + mv_readl: generic_readl, + mv_writeb: generic_writeb, + mv_writew: generic_writew, + mv_writel: generic_writel, + + mv_ioremap: generic_ioremap, + mv_iounmap: generic_iounmap, + + mv_isa_port2addr: hd64465_isa_port2addr, + + mv_init_arch: setup_harp, +#ifdef CONFIG_PCI + mv_init_irq: init_harp_irq, +#endif +#ifdef CONFIG_HEARTBEAT + mv_heartbeat: heartbeat_harp, +#endif + mv_rtc_gettimeofday: sh_rtc_gettimeofday, + mv_rtc_settimeofday: sh_rtc_settimeofday, +}; + +ALIAS_MV(harp) diff -u --recursive --new-file v2.4.5/linux/arch/sh/stboards/pcidma.c linux/arch/sh/stboards/pcidma.c --- v2.4.5/linux/arch/sh/stboards/pcidma.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/stboards/pcidma.c Wed Jun 27 13:55:29 2001 @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Dynamic DMA mapping support. + */ + +#include +#include +#include +#include +#include +#include + + +void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, + dma_addr_t * dma_handle) +{ + void *ret; + int gfp = GFP_ATOMIC; + + ret = (void *) __get_free_pages(gfp, get_order(size)); + + if (ret != NULL) { + /* Is it neccessary to do the memset? */ + memset(ret, 0, size); + *dma_handle = virt_to_bus(ret); + } + /* We must flush the cache before we pass it on to the device */ + flush_cache_all(); + return P2SEGADDR(ret); +} + +void pci_free_consistent(struct pci_dev *hwdev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + unsigned long p1addr=P1SEGADDR((unsigned long)vaddr); + + free_pages(p1addr, get_order(size)); +} diff -u --recursive --new-file v2.4.5/linux/arch/sh/stboards/setup.c linux/arch/sh/stboards/setup.c --- v2.4.5/linux/arch/sh/stboards/setup.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/stboards/setup.c Wed Jun 27 13:55:29 2001 @@ -0,0 +1,50 @@ +/* + * arch/sh/stboard/setup.c + * + * Copyright (C) 2001 Stuart Menefy (stuart.menefy@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * STMicroelectronics ST40STB1 HARP and compatible support. + */ + +#include +#include +#include +#include +#include "harp.h" +/* + * Initialize the board + */ +int __init setup_harp(void) +{ +#ifdef CONFIG_SH_STB1_HARP + unsigned long ic8_version, ic36_version; + + ic8_version = ctrl_inl(EPLD_REVID2); + ic36_version = ctrl_inl(EPLD_REVID1); + + printk("STMicroelectronics STB1 HARP initialisaton\n"); + printk("EPLD versions: IC8: %d.%02d, IC36: %d.%02d\n", + (ic8_version >> 4) & 0xf, ic8_version & 0xf, + (ic36_version >> 4) & 0xf, ic36_version & 0xf); +#elif defined(CONFIG_SH_STB1_OVERDRIVE) + unsigned long version; + + version = ctrl_inl(EPLD_REVID); + + printk("STMicroelectronics STB1 Overdrive initialisaton\n"); + printk("EPLD version: %d.%02d\n", + (version >> 4) & 0xf, version & 0xf); +#else +#error Undefined machine +#endif + + /* Currently all STB1 chips have problems with the sleep instruction, + * so disable it here. + */ + disable_hlt(); + + return 0; +} diff -u --recursive --new-file v2.4.5/linux/arch/sh/vmlinux.lds.S linux/arch/sh/vmlinux.lds.S --- v2.4.5/linux/arch/sh/vmlinux.lds.S Fri Dec 29 14:07:20 2000 +++ linux/arch/sh/vmlinux.lds.S Mon Jul 2 14:40:58 2001 @@ -24,7 +24,7 @@ *(.gnu.warning) } = 0x0009 .text.lock : { *(.text.lock) } /* out-of-line lock text */ - .rodata : { *(.rodata) } + .rodata : { *(.rodata) *(.rodata.*) } .kstrtab : { *(.kstrtab) } . = ALIGN(16); /* Exception table */ diff -u --recursive --new-file v2.4.5/linux/arch/sparc/config.in linux/arch/sparc/config.in --- v2.4.5/linux/arch/sparc/config.in Mon May 21 18:12:09 2001 +++ linux/arch/sparc/config.in Mon Jun 11 19:15:27 2001 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.110 2001/05/20 05:14:46 davem Exp $ +# $Id: config.in,v 1.111 2001/06/01 08:12:10 davem Exp $ # For a description of the syntax of this configuration file, # see Documentation/kbuild/config-language.txt. # @@ -250,6 +250,10 @@ endmenu source fs/Config.in + +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + source net/bluetooth/Config.in +fi mainmenu_option next_comment comment 'Watchdog' diff -u --recursive --new-file v2.4.5/linux/arch/sparc/kernel/rtrap.S linux/arch/sparc/kernel/rtrap.S --- v2.4.5/linux/arch/sparc/kernel/rtrap.S Sun Aug 6 11:43:17 2000 +++ linux/arch/sparc/kernel/rtrap.S Tue Jun 12 11:08:46 2001 @@ -1,4 +1,4 @@ -/* $Id: rtrap.S,v 1.55 2000/08/05 10:48:40 davem Exp $ +/* $Id: rtrap.S,v 1.56 2001/06/05 09:56:06 davem Exp $ * rtrap.S: Return from Sparc trap low-level code. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -52,9 +52,8 @@ sll %l3, 5, %l3 sethi %hi(C_LABEL(irq_stat)), %l4 ! &softirq_active add %l4, %l3, %l4 - ld [%l4 + %lo(C_LABEL(irq_stat))], %g5 ! softirq_active - ld [%l4 + %lo(C_LABEL(irq_stat) + 4)], %g4 ! softirq_mask - andcc %g4, %g5, %g0 + ld [%l4 + %lo(C_LABEL(irq_stat))], %g5 ! softirq_pending + cmp %g5, 0 be C_LABEL(ret_trap_lockless_ipi) nop call C_LABEL(do_softirq) diff -u --recursive --new-file v2.4.5/linux/arch/sparc/vmlinux.lds linux/arch/sparc/vmlinux.lds --- v2.4.5/linux/arch/sparc/vmlinux.lds Thu Nov 9 15:57:41 2000 +++ linux/arch/sparc/vmlinux.lds Mon Jul 2 14:40:58 2001 @@ -12,7 +12,7 @@ } =0 _etext = .; PROVIDE (etext = .); - .rodata : { *(.rodata) } + .rodata : { *(.rodata) *(.rodata.*) } .rodata1 : { *(.rodata1) } .data : { diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/config.in linux/arch/sparc64/config.in --- v2.4.5/linux/arch/sparc64/config.in Sun May 20 11:32:07 2001 +++ linux/arch/sparc64/config.in Thu Jun 21 14:27:40 2001 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.143 2001/05/20 05:14:46 davem Exp $ +# $Id: config.in,v 1.146 2001/06/16 04:15:26 davem Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -36,6 +36,7 @@ define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y define_bool CONFIG_ISA n +define_bool CONFIG_ISAPNP n define_bool CONFIG_EISA n define_bool CONFIG_MCA n define_bool CONFIG_PCMCIA n @@ -235,71 +236,7 @@ bool 'Network device support' CONFIG_NETDEVICES if [ "$CONFIG_NETDEVICES" = "y" ]; then - tristate ' Dummy net driver support' CONFIG_DUMMY - tristate ' Bonding driver support' CONFIG_BONDING - tristate ' Universal TUN/TAP device driver support' CONFIG_TUN - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - if [ "$CONFIG_NETLINK" = "y" ]; then - tristate ' Ethertap network tap (OBSOLETE)' CONFIG_ETHERTAP - fi - fi - tristate ' PPP (point-to-point) support' CONFIG_PPP - if [ ! "$CONFIG_PPP" = "n" ]; then - dep_tristate ' PPP support for async serial ports' CONFIG_PPP_ASYNC $CONFIG_PPP - dep_tristate ' PPP support for sync tty ports' CONFIG_PPP_SYNC_TTY $CONFIG_PPP - dep_tristate ' PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP - dep_tristate ' PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP m - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - dep_tristate ' PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP - fi - fi - tristate ' SLIP (serial line) support' CONFIG_SLIP - if [ "$CONFIG_SLIP" != "n" ]; then - bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED - bool ' Keepalive and linefill' CONFIG_SLIP_SMART - bool ' Six bit SLIP encapsulation' CONFIG_SLIP_MODE_SLIP6 - fi - - mainmenu_option next_comment - comment 'Ethernet (10 or 100Mbit)' - - tristate 'Sun LANCE support' CONFIG_SUNLANCE - tristate 'Sun Happy Meal 10/100baseT support' CONFIG_HAPPYMEAL - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate 'Sun BigMAC 10/100baseT support (EXPERIMENTAL)' CONFIG_SUNBMAC - fi - tristate ' Sun QuadEthernet support' CONFIG_SUNQE - if [ "$CONFIG_PCI" = "y" ]; then - tristate 'Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5 - tristate 'DECchip Tulip (dc21x4x) PCI support' CONFIG_TULIP - tristate '3c590/3c900 series (592/595/597) "Vortex/Boomerang" support' CONFIG_VORTEX - tristate 'RealTek RTL-8139 support' CONFIG_8139TOO - tristate 'PCI NE2000 support' CONFIG_NE2K_PCI - tristate 'VIA Rhine support' CONFIG_VIA_RHINE - tristate 'EtherExpressPro/100 support' CONFIG_EEPRO100 - tristate 'Adaptec Starfire support' CONFIG_ADAPTEC_STARFIRE - fi - endmenu - - mainmenu_option next_comment - comment 'Ethernet (1000 Mbit)' - - if [ "$CONFIG_PCI" = "y" ]; then - tristate 'Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support' CONFIG_ACENIC - if [ "$CONFIG_ACENIC" != "n" ]; then - bool ' Omit support for old Tigon I based AceNICs' CONFIG_ACENIC_OMIT_TIGON_I - fi - tristate 'SysKonnect SK-98xx support' CONFIG_SK98LIN - tristate 'Sun GEM support' CONFIG_SUNGEM - fi - tristate 'MyriCOM Gigabit Ethernet support' CONFIG_MYRI_SBUS - endmenu - - bool 'FDDI driver support' CONFIG_FDDI - if [ "$CONFIG_FDDI" = "y" ]; then - tristate ' SysKonnect FDDI PCI support' CONFIG_SKFP - fi - + source drivers/net/Config.in if [ "$CONFIG_ATM" = "y" ]; then source drivers/atm/Config.in fi @@ -330,6 +267,11 @@ comment 'XFree86 DRI support' bool 'Direct Rendering Manager (XFree86 DRI support)' CONFIG_DRM dep_tristate ' Creator/Creator3D' CONFIG_DRM_FFB $CONFIG_DRM +dep_tristate ' 3dfx Banshee/Voodoo3+' CONFIG_DRM_TDFX $CONFIG_DRM +dep_tristate ' ATI Rage 128' CONFIG_DRM_R128 $CONFIG_DRM +if [ "$CONFIG_DRM_R128" != "n" ]; then + define_bool CONFIG_AGP y +fi endmenu source drivers/input/Config.in @@ -346,6 +288,10 @@ endmenu source drivers/usb/Config.in + +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + source net/bluetooth/Config.in +fi mainmenu_option next_comment comment 'Watchdog' diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig --- v2.4.5/linux/arch/sparc64/defconfig Thu May 24 15:00:58 2001 +++ linux/arch/sparc64/defconfig Fri Jun 29 19:38:26 2001 @@ -26,6 +26,7 @@ # CONFIG_RWSEM_GENERIC_SPINLOCK is not set CONFIG_RWSEM_XCHGADD_ALGORITHM=y # CONFIG_ISA is not set +# CONFIG_ISAPNP is not set # CONFIG_EISA is not set # CONFIG_MCA is not set # CONFIG_PCMCIA is not set @@ -359,46 +360,119 @@ # Network device support # CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# Appletalk devices +# +# CONFIG_APPLETALK is not set CONFIG_DUMMY=m CONFIG_BONDING=m +CONFIG_EQUALIZER=m CONFIG_TUN=m -CONFIG_PPP=m -# CONFIG_PPP_ASYNC is not set -# CONFIG_PPP_SYNC_TTY is not set -# CONFIG_PPP_DEFLATE is not set -# CONFIG_PPP_BSDCOMP is not set -CONFIG_PPPOE=m -CONFIG_SLIP=m -CONFIG_SLIP_COMPRESSED=y -CONFIG_SLIP_SMART=y -# CONFIG_SLIP_MODE_SLIP6 is not set # # Ethernet (10 or 100Mbit) # +CONFIG_NET_ETHERNET=y CONFIG_SUNLANCE=y CONFIG_HAPPYMEAL=y CONFIG_SUNBMAC=m CONFIG_SUNQE=m -CONFIG_DE4X5=m -CONFIG_TULIP=m +CONFIG_SUNLANCE=y +CONFIG_SUNGEM=y +CONFIG_NET_VENDOR_3COM=y +# CONFIG_EL1 is not set +# CONFIG_EL2 is not set +# CONFIG_ELPLUS is not set +# CONFIG_EL16 is not set +# CONFIG_ELMC is not set +# CONFIG_ELMC_II is not set CONFIG_VORTEX=m -CONFIG_8139TOO=m +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_HP100 is not set +# CONFIG_NET_ISA is not set +CONFIG_NET_PCI=y +CONFIG_PCNET32=m +CONFIG_ADAPTEC_STARFIRE=m +# CONFIG_APRICOT is not set +# CONFIG_CS89x0 is not set +CONFIG_TULIP=m +# CONFIG_TULIP_MWI is not set +# CONFIG_TULIP_MMIO is not set +CONFIG_DE4X5=m +CONFIG_DGRS=m +# CONFIG_DM9102 is not set +CONFIG_EEPRO100=m +# CONFIG_LNE390 is not set +CONFIG_FEALNX=m +CONFIG_NATSEMI=m CONFIG_NE2K_PCI=m +# CONFIG_NE3210 is not set +# CONFIG_ES3210 is not set +CONFIG_8139TOO=m +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +# CONFIG_8139TOO_8129 is not set +# CONFIG_SIS900 is not set +CONFIG_EPIC100=m +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set CONFIG_VIA_RHINE=m -CONFIG_EEPRO100=m -CONFIG_ADAPTEC_STARFIRE=m +CONFIG_WINBOND_840=m +# CONFIG_NET_POCKET is not set # # Ethernet (1000 Mbit) # CONFIG_ACENIC=m # CONFIG_ACENIC_OMIT_TIGON_I is not set -CONFIG_SK98LIN=m -CONFIG_SUNGEM=y CONFIG_MYRI_SBUS=m +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +CONFIG_SK98LIN=m CONFIG_FDDI=y +# CONFIG_DEFXX is not set CONFIG_SKFP=m +CONFIG_HIPPI=y +# CONFIG_ROADRUNNER is not set +CONFIG_PLIP=m +CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +# CONFIG_PPP_ASYNC is not set +# CONFIG_PPP_SYNC_TTY is not set +# CONFIG_PPP_DEFLATE is not set +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +# CONFIG_SLIP_MODE_SLIP6 is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set # # Unix 98 PTY support @@ -417,6 +491,9 @@ # CONFIG_DRM=y CONFIG_DRM_FFB=m +CONFIG_DRM_TDFX=m +CONFIG_DRM_R128=m +CONFIG_AGP=y # # Input core support @@ -619,6 +696,7 @@ CONFIG_USB_IBMCAM=m CONFIG_USB_OV511=m CONFIG_USB_PWC=m +CONFIG_USB_SE401=m CONFIG_USB_DSBR=m CONFIG_USB_DABUSB=m @@ -627,6 +705,7 @@ # CONFIG_USB_PLUSB=m CONFIG_USB_PEGASUS=m +CONFIG_USB_CATC=m CONFIG_USB_NET1080=m # @@ -655,12 +734,27 @@ # CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set # CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_CYBERJACK=m CONFIG_USB_SERIAL_OMNINET=m # # USB misc drivers # CONFIG_USB_RIO500=m + +# +# Bluetooth support +# +CONFIG_BLUEZ=m +CONFIG_BLUEZ_L2CAP=m + +# +# Bluetooth device drivers +# +CONFIG_BLUEZ_HCIUSB=m +CONFIG_BLUEZ_HCIUART=m +CONFIG_BLUEZ_HCIEMU=m # # Watchdog diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/devices.c linux/arch/sparc64/kernel/devices.c --- v2.4.5/linux/arch/sparc64/kernel/devices.c Sun May 20 12:11:38 2001 +++ linux/arch/sparc64/kernel/devices.c Tue Jun 12 11:08:46 2001 @@ -9,6 +9,7 @@ #include #include #include +#include #include #include diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/ebus.c linux/arch/sparc64/kernel/ebus.c --- v2.4.5/linux/arch/sparc64/kernel/ebus.c Thu Apr 26 22:17:25 2001 +++ linux/arch/sparc64/kernel/ebus.c Tue Jun 12 11:08:46 2001 @@ -1,4 +1,4 @@ -/* $Id: ebus.c,v 1.61 2001/04/24 05:13:25 davem Exp $ +/* $Id: ebus.c,v 1.63 2001/06/08 02:27:16 davem Exp $ * ebus.c: PCI to EBus bridge device. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -25,7 +25,6 @@ #ifdef CONFIG_SUN_AUXIO extern void auxio_probe(void); #endif -extern void rs_init(void); static inline void *ebus_alloc(size_t size) { @@ -269,8 +268,6 @@ printk("]"); } -extern void clock_probe(void); -extern void power_init(void); void __init ebus_init(void) { @@ -395,10 +392,7 @@ ++num_ebus; } - rs_init(); #ifdef CONFIG_SUN_AUXIO auxio_probe(); #endif - clock_probe(); - power_init(); } diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c --- v2.4.5/linux/arch/sparc64/kernel/ioctl32.c Wed May 16 10:31:27 2001 +++ linux/arch/sparc64/kernel/ioctl32.c Mon Jun 11 19:15:27 2001 @@ -1,4 +1,4 @@ -/* $Id: ioctl32.c,v 1.115 2001/05/12 06:41:58 davem Exp $ +/* $Id: ioctl32.c,v 1.117 2001/06/02 21:39:55 davem Exp $ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) @@ -90,6 +90,9 @@ #include #include +#include +#include + /* Use this to get at 32-bit user passed pointers. See sys_sparc32.c for description about these. */ #define A(__x) ((unsigned long)(__x)) @@ -3469,6 +3472,10 @@ COMPATIBLE_IOCTL(CDROM_LOCKDOOR) COMPATIBLE_IOCTL(CDROM_DEBUG) COMPATIBLE_IOCTL(CDROM_GET_CAPABILITY) +/* DVD ioctls */ +COMPATIBLE_IOCTL(DVD_READ_STRUCT) +COMPATIBLE_IOCTL(DVD_WRITE_STRUCT) +COMPATIBLE_IOCTL(DVD_AUTH) /* Big L */ COMPATIBLE_IOCTL(LOOP_SET_FD) COMPATIBLE_IOCTL(LOOP_CLR_FD) @@ -3719,6 +3726,17 @@ COMPATIBLE_IOCTL(WIOCSTART) COMPATIBLE_IOCTL(WIOCSTOP) COMPATIBLE_IOCTL(WIOCGSTAT) +/* Bluetooth ioctls */ +COMPATIBLE_IOCTL(HCIDEVUP) +COMPATIBLE_IOCTL(HCIDEVDOWN) +COMPATIBLE_IOCTL(HCIDEVRESET) +COMPATIBLE_IOCTL(HCIRESETSTAT) +COMPATIBLE_IOCTL(HCIGETINFO) +COMPATIBLE_IOCTL(HCIGETDEVLIST) +COMPATIBLE_IOCTL(HCISETRAW) +COMPATIBLE_IOCTL(HCISETSCAN) +COMPATIBLE_IOCTL(HCISETAUTH) +COMPATIBLE_IOCTL(HCIINQUIRY) /* Misc. */ COMPATIBLE_IOCTL(0x41545900) /* ATYIO_CLKR */ COMPATIBLE_IOCTL(0x41545901) /* ATYIO_CLKW */ diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/irq.c linux/arch/sparc64/kernel/irq.c --- v2.4.5/linux/arch/sparc64/kernel/irq.c Thu Apr 26 22:17:25 2001 +++ linux/arch/sparc64/kernel/irq.c Mon Jun 11 19:15:27 2001 @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.100 2001/04/24 01:09:12 davem Exp $ +/* $Id: irq.c,v 1.101 2001/06/04 06:50:18 ecd Exp $ * irq.c: UltraSparc IRQ handling/init/registry. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -783,6 +783,8 @@ unsigned char flags = bp->flags; nbp = __bucket(bp->irq_chain); + bp->irq_chain = 0; + if ((flags & IBF_ACTIVE) != 0) { #ifdef CONFIG_PCI if ((flags & IBF_DMA_SYNC) != 0) { diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/pci.c linux/arch/sparc64/kernel/pci.c --- v2.4.5/linux/arch/sparc64/kernel/pci.c Wed May 16 10:31:27 2001 +++ linux/arch/sparc64/kernel/pci.c Wed Jun 20 21:00:55 2001 @@ -1,4 +1,4 @@ -/* $Id: pci.c,v 1.29 2001/05/15 08:54:30 davem Exp $ +/* $Id: pci.c,v 1.35 2001/06/13 06:34:30 davem Exp $ * pci.c: UltraSparc PCI controller support. * * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com) @@ -177,6 +177,10 @@ } } +extern void rs_init(void); +extern void clock_probe(void); +extern void power_init(void); + void __init pcibios_init(void) { pci_controller_probe(); @@ -190,6 +194,9 @@ isa_init(); ebus_init(); + rs_init(); + clock_probe(); + power_init(); } struct pci_fixup pcibios_fixups[] = { @@ -198,6 +205,66 @@ void pcibios_fixup_bus(struct pci_bus *pbus) { + struct pci_pbm_info *pbm = pbus->sysdata; + + /* Generic PCI bus probing sets these to point at + * &io{port,mem}_resouce which is wrong for us. + */ + pbus->resource[0] = &pbm->io_space; + pbus->resource[1] = &pbm->mem_space; +} + +/* NOTE: This can get called before we've fixed up pdev->sysdata. */ +int pci_claim_resource(struct pci_dev *pdev, int resource) +{ + struct pci_pbm_info *pbm = pci_bus2pbm[pdev->bus->number]; + struct resource *res = &pdev->resource[resource]; + struct resource *root; + + if (!pbm) + return -EINVAL; + + if (res->flags & IORESOURCE_IO) + root = &pbm->io_space; + else + root = &pbm->mem_space; + + pbm->parent->resource_adjust(pdev, res, root); + + return request_resource(root, res); +} + +int pci_assign_resource(struct pci_dev *pdev, int resource) +{ + struct pcidev_cookie *pcp = pdev->sysdata; + struct pci_pbm_info *pbm = pcp->pbm; + struct resource *res = &pdev->resource[resource]; + struct resource *root; + unsigned long min, max, size, align; + int err; + + if (res->flags & IORESOURCE_IO) { + root = &pbm->io_space; + min = root->start + 0x400UL; + max = root->end; + } else { + root = &pbm->mem_space; + min = root->start; + max = min + 0x80000000UL; + } + + size = res->end - res->start; + align = size + 1; + + err = allocate_resource(root, res, size + 1, min, max, align, NULL, NULL); + if (err < 0) { + printk("PCI: Failed to allocate resource %d for %s\n", + resource, pdev->name); + } else { + pbm->parent->base_address_update(pdev, resource); + } + + return err; } void pcibios_update_resource(struct pci_dev *pdev, struct resource *res1, @@ -238,6 +305,53 @@ /* Platform support for /proc/bus/pci/X/Y mmap()s. */ +/* If the user uses a host-bridge as the PCI device, he may use + * this to perform a raw mmap() of the I/O or MEM space behind + * that controller. + * + * This can be useful for execution of x86 PCI bios initialization code + * on a PCI card, like the xfree86 int10 stuff does. + */ +static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struct *vma, + enum pci_mmap_state mmap_state) +{ + struct pcidev_cookie *pcp = pdev->sysdata; + struct pci_pbm_info *pbm; + unsigned long space_size, user_offset, user_size; + + if (!pcp) + return -ENXIO; + pbm = pcp->pbm; + if (!pbm) + return -ENXIO; + + if (mmap_state == pci_mmap_io) { + space_size = (pbm->io_space.end - + pbm->io_space.start) + 1; + } else { + space_size = (pbm->mem_space.end - + pbm->mem_space.start) + 1; + } + + /* Make sure the request is in range. */ + user_offset = vma->vm_pgoff << PAGE_SHIFT; + user_size = vma->vm_end - vma->vm_start; + + if (user_offset >= space_size || + (user_offset + user_size) > space_size) + return -EINVAL; + + if (mmap_state == pci_mmap_io) { + vma->vm_pgoff = (pbm->io_space.start + + user_offset) >> PAGE_SHIFT; + } else { + vma->vm_pgoff = (pbm->mem_space.start + + user_offset) >> PAGE_SHIFT; + } + + return 0; +} + /* Adjust vm_pgoff of VMA such that it is the physical page offset corresponding * to the 32-bit pci bus offset for DEV requested by the user. * @@ -248,14 +362,17 @@ * * Returns negative error code on failure, zero on success. */ -static __inline__ int __pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state) +static int __pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma, + enum pci_mmap_state mmap_state) { unsigned long user_offset = vma->vm_pgoff << PAGE_SHIFT; unsigned long user32 = user_offset & 0xffffffffUL; unsigned long largest_base, this_base, addr32; int i; + if ((dev->class >> 8) == PCI_CLASS_BRIDGE_HOST) + return __pci_mmap_make_offset_bus(dev, vma, mmap_state); + /* Figure out which base address this is for. */ largest_base = 0UL; for (i = 0; i <= PCI_ROM_RESOURCE; i++) { @@ -303,7 +420,7 @@ /* Set vm_flags of VMA, as appropriate for this architecture, for a pci device * mapping. */ -static __inline__ void __pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma, +static void __pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state) { vma->vm_flags |= (VM_SHM | VM_LOCKED); @@ -312,7 +429,7 @@ /* Set vm_page_prot of VMA, as appropriate for this architecture, for a pci * device mapping. */ -static __inline__ void __pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma, +static void __pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state) { /* Our io_remap_page_range takes care of this, do nothing. */ diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/pci_common.c linux/arch/sparc64/kernel/pci_common.c --- v2.4.5/linux/arch/sparc64/kernel/pci_common.c Sat May 19 18:13:15 2001 +++ linux/arch/sparc64/kernel/pci_common.c Fri Jun 29 19:38:26 2001 @@ -1,4 +1,4 @@ -/* $Id: pci_common.c,v 1.18 2001/05/18 23:06:35 davem Exp $ +/* $Id: pci_common.c,v 1.26 2001/06/28 01:32:18 davem Exp $ * pci_common.c: PCI controller common support. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -93,12 +93,38 @@ } /* Older versions of OBP on PCI systems encode 64-bit MEM - * space assignments incorrectly, this fixes them up. + * space assignments incorrectly, this fixes them up. We also + * take the opportunity here to hide other kinds of bogus + * assignments. */ -static void __init fixup_obp_assignments(struct pcidev_cookie *pcp) +static void __init fixup_obp_assignments(struct pci_dev *pdev, + struct pcidev_cookie *pcp) { int i; + if (pdev->vendor == PCI_VENDOR_ID_AL && + (pdev->device == PCI_DEVICE_ID_AL_M7101 || + pdev->device == PCI_DEVICE_ID_AL_M1533)) { + int i; + + /* Zap all of the normal resources, they are + * meaningless and generate bogus resource collision + * messages. This is OpenBoot's ill-fated attempt to + * represent the implicit resources that these devices + * have. + */ + pcp->num_prom_assignments = 0; + for (i = 0; i < 6; i++) { + pdev->resource[i].start = + pdev->resource[i].end = + pdev->resource[i].flags = 0; + } + pdev->resource[PCI_ROM_RESOURCE].start = + pdev->resource[PCI_ROM_RESOURCE].end = + pdev->resource[PCI_ROM_RESOURCE].flags = 0; + return; + } + for (i = 0; i < pcp->num_prom_assignments; i++) { struct linux_prom_pci_registers *ap; int space; @@ -194,7 +220,7 @@ (err / sizeof(pcp->prom_assignments[0])); } - fixup_obp_assignments(pcp); + fixup_obp_assignments(pdev, pcp); pdev->sysdata = pcp; } @@ -231,11 +257,13 @@ } } -static void __init bad_assignment(struct linux_prom_pci_registers *ap, +static void __init bad_assignment(struct pci_dev *pdev, + struct linux_prom_pci_registers *ap, struct resource *res, int do_prom_halt) { - prom_printf("PCI: Bogus PROM assignment.\n"); + prom_printf("PCI: Bogus PROM assignment. BUS[%02x] DEVFN[%x]\n", + pdev->bus->number, pdev->devfn); if (ap) prom_printf("PCI: phys[%08x:%08x:%08x] size[%08x:%08x]\n", ap->phys_hi, ap->phys_mid, ap->phys_lo, @@ -293,7 +321,7 @@ case PCI_ROM_ADDRESS: /* It had better be MEM space. */ if (space != 2) - bad_assignment(ap, NULL, 0); + bad_assignment(pdev, ap, NULL, 0); res = &pdev->resource[PCI_ROM_RESOURCE]; break; @@ -308,7 +336,7 @@ break; default: - bad_assignment(ap, NULL, 0); + bad_assignment(pdev, ap, NULL, 0); res = NULL; break; }; @@ -316,6 +344,19 @@ return res; } +static int __init pdev_resource_collisions_expected(struct pci_dev *pdev) +{ + if (pdev->vendor != PCI_VENDOR_ID_SUN) + return 0; + + if (pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS || + pdev->device == PCI_DEVICE_ID_SUN_RIO_1394 || + pdev->device == PCI_DEVICE_ID_SUN_RIO_USB) + return 1; + + return 0; +} + static void __init pdev_record_assignments(struct pci_pbm_info *pbm, struct pci_dev *pdev) { @@ -332,14 +373,15 @@ ap = &pcp->prom_assignments[i]; root = get_root_resource(ap, pbm); res = get_device_resource(ap, pdev); - if (root == NULL || res == NULL) + if (root == NULL || res == NULL || + res->flags == 0) continue; /* Ok we know which resource this PROM assignment is * for, sanity check it. */ if ((res->start & 0xffffffffUL) != ap->phys_lo) - bad_assignment(ap, res, 1); + bad_assignment(pdev, ap, res, 1); /* If it is a 64-bit MEM space assignment, verify that * the resource is too and that the upper 32-bits match. @@ -348,9 +390,9 @@ if (((res->flags & IORESOURCE_MEM) == 0) || ((res->flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) != PCI_BASE_ADDRESS_MEM_TYPE_64)) - bad_assignment(ap, res, 1); + bad_assignment(pdev, ap, res, 1); if ((res->start >> 32) != ap->phys_mid) - bad_assignment(ap, res, 1); + bad_assignment(pdev, ap, res, 1); /* PBM cannot generate cpu initiated PIOs * to the full 64-bit space. Therefore the @@ -374,12 +416,17 @@ if (request_resource(root, res) < 0) { /* OK, there is some conflict. But this is fine * since we'll reassign it in the fixup pass. - * Nevertheless notify the user that OBP made - * an error. + * + * We notify the user that OBP made an error if it + * is a case we don't expect. */ - printk(KERN_ERR "PCI: Address space collision on region %ld " - "of device %s\n", - (res - &pdev->resource[0]), pdev->name); + if (!pdev_resource_collisions_expected(pdev)) { + printk(KERN_ERR "PCI: Address space collision on region %ld " + "[%016lx:%016lx] of device %s\n", + (res - &pdev->resource[0]), + res->start, res->end, + pdev->name); + } } } } @@ -397,6 +444,23 @@ pci_record_assignments(pbm, pci_bus_b(walk)); } +/* Return non-zero if PDEV has implicit I/O resources even + * though it may not have an I/O base address register + * active. + */ +static int __init has_implicit_io(struct pci_dev *pdev) +{ + int class = pdev->class >> 8; + + if (class == PCI_CLASS_NOT_DEFINED || + class == PCI_CLASS_NOT_DEFINED_VGA || + class == PCI_CLASS_STORAGE_IDE || + (pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) + return 1; + + return 0; +} + static void __init pdev_assign_unassigned(struct pci_pbm_info *pbm, struct pci_dev *pdev) { @@ -460,7 +524,7 @@ */ if (io_seen || mem_seen) { pci_read_config_word(pdev, PCI_COMMAND, &cmd); - if (io_seen) + if (io_seen || has_implicit_io(pdev)) cmd |= PCI_COMMAND_IO; if (mem_seen) cmd |= PCI_COMMAND_MEMORY; @@ -649,17 +713,22 @@ line = ((pci_irq_line - 1) & 3); } - /* Now figure out the slot. */ + /* Now figure out the slot. + * + * Basically, device number zero on the top-level bus is + * always the PCI host controller. Slot 0 is then device 1. + * PBM A supports two external slots (0 and 1), and PBM B + * supports 4 external slots (0, 1, 2, and 3). On-board PCI + * devices are wired to device numbers outside of these + * ranges. -DaveM + */ if (pdev->bus->number == pbm->pci_first_busno) { - if (pbm == &pbm->parent->pbm_A) - slot = (pdev->devfn >> 3) - 1; - else - slot = (pdev->devfn >> 3) - 2; + slot = (pdev->devfn >> 3) - 1; } else { - if (pbm == &pbm->parent->pbm_A) - slot = (pdev->bus->self->devfn >> 3) - 1; - else - slot = (pdev->bus->self->devfn >> 3) - 2; + /* Underneath a bridge, use slot number of parent + * bridge. + */ + slot = (pdev->bus->self->devfn >> 3) - 1; } slot = slot << 2; @@ -819,6 +888,46 @@ walk = &pbus->children; for (walk = walk->next; walk != &pbus->children; walk = walk->next) pci_setup_busmastering(pbm, pci_bus_b(walk)); +} + +void pci_register_legacy_regions(struct resource *io_res, + struct resource *mem_res) +{ + struct resource *p; + + /* VGA Video RAM. */ + p = kmalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return; + + memset(p, 0, sizeof(*p)); + p->name = "Video RAM area"; + p->start = mem_res->start + 0xa0000UL; + p->end = p->start + 0x1ffffUL; + p->flags = IORESOURCE_BUSY; + request_resource(mem_res, p); + + p = kmalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return; + + memset(p, 0, sizeof(*p)); + p->name = "System ROM"; + p->start = mem_res->start + 0xf0000UL; + p->end = p->start + 0xffffUL; + p->flags = IORESOURCE_BUSY; + request_resource(mem_res, p); + + p = kmalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return; + + memset(p, 0, sizeof(*p)); + p->name = "Video ROM"; + p->start = mem_res->start + 0xc0000UL; + p->end = p->start + 0x7fffUL; + p->flags = IORESOURCE_BUSY; + request_resource(mem_res, p); } /* Generic helper routines for PCI error reporting. */ diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/pci_impl.h linux/arch/sparc64/kernel/pci_impl.h --- v2.4.5/linux/arch/sparc64/kernel/pci_impl.h Wed May 16 10:31:27 2001 +++ linux/arch/sparc64/kernel/pci_impl.h Wed Jun 20 21:00:55 2001 @@ -1,4 +1,4 @@ -/* $Id: pci_impl.h,v 1.8 2001/05/15 08:54:30 davem Exp $ +/* $Id: pci_impl.h,v 1.9 2001/06/13 06:34:30 davem Exp $ * pci_impl.h: Helper definitions for PCI controller support. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -33,6 +33,8 @@ struct pci_bus *pbus); extern void pci_setup_busmastering(struct pci_pbm_info *pbm, struct pci_bus *pbus); +extern void pci_register_legacy_regions(struct resource *io_res, + struct resource *mem_res); /* Error reporting support. */ extern void pci_scan_for_target_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *); diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/pci_psycho.c linux/arch/sparc64/kernel/pci_psycho.c --- v2.4.5/linux/arch/sparc64/kernel/pci_psycho.c Wed May 16 10:31:27 2001 +++ linux/arch/sparc64/kernel/pci_psycho.c Wed Jun 20 21:00:55 2001 @@ -1,4 +1,4 @@ -/* $Id: pci_psycho.c,v 1.24 2001/05/15 08:54:30 davem Exp $ +/* $Id: pci_psycho.c,v 1.26 2001/06/13 06:34:30 davem Exp $ * pci_psycho.c: PSYCHO/U2P specific PCI controller support. * * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) @@ -353,23 +353,28 @@ if (ret == 0 && pdev == NULL) { ret = 1; } else if (ret == 0) { - switch ((pdev->class >> 16) & 0x0f) { + switch ((pdev->class >> 16) & 0xff) { case PCI_BASE_CLASS_STORAGE: ret = 4; + break; case PCI_BASE_CLASS_NETWORK: ret = 6; + break; case PCI_BASE_CLASS_DISPLAY: ret = 9; + break; case PCI_BASE_CLASS_MULTIMEDIA: case PCI_BASE_CLASS_MEMORY: case PCI_BASE_CLASS_BRIDGE: ret = 10; + break; default: ret = 1; + break; }; } @@ -1404,6 +1409,8 @@ request_resource(&ioport_resource, &pbm->io_space); request_resource(&iomem_resource, &pbm->mem_space); + pci_register_legacy_regions(&pbm->io_space, + &pbm->mem_space); } static void psycho_pbm_strbuf_init(struct pci_controller_info *p, diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/pci_sabre.c linux/arch/sparc64/kernel/pci_sabre.c --- v2.4.5/linux/arch/sparc64/kernel/pci_sabre.c Wed May 16 10:31:27 2001 +++ linux/arch/sparc64/kernel/pci_sabre.c Wed Jun 20 21:00:55 2001 @@ -1,4 +1,4 @@ -/* $Id: pci_sabre.c,v 1.32 2001/05/15 11:10:01 davem Exp $ +/* $Id: pci_sabre.c,v 1.37 2001/06/13 06:34:30 davem Exp $ * pci_sabre.c: Sabre specific PCI controller support. * * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) @@ -16,6 +16,7 @@ #include #include #include +#include #include "pci_impl.h" @@ -196,7 +197,7 @@ #define SABRE_CONFIGSPACE 0x001000000UL #define SABRE_IOSPACE 0x002000000UL -#define SABRE_IOSPACE_SIZE 0x00000ffffUL +#define SABRE_IOSPACE_SIZE 0x000ffffffUL #define SABRE_MEMSPACE 0x100000000UL #define SABRE_MEMSPACE_SIZE 0x07fffffffUL @@ -590,23 +591,28 @@ if (ret == 0 && pdev == NULL) { ret = 1; } else if (ret == 0) { - switch ((pdev->class >> 16) & 0x0f) { + switch ((pdev->class >> 16) & 0xff) { case PCI_BASE_CLASS_STORAGE: ret = 4; + break; case PCI_BASE_CLASS_NETWORK: ret = 6; + break; case PCI_BASE_CLASS_DISPLAY: ret = 9; + break; case PCI_BASE_CLASS_MULTIMEDIA: case PCI_BASE_CLASS_MEMORY: case PCI_BASE_CLASS_BRIDGE: ret = 10; + break; default: ret = 1; + break; }; } return ret; @@ -1025,8 +1031,8 @@ struct resource *res, struct resource *root) { - struct pcidev_cookie *pcp = pdev->sysdata; - struct pci_controller_info *p = pcp->pbm->parent; + struct pci_pbm_info *pbm = pci_bus2pbm[pdev->bus->number]; + struct pci_controller_info *p = pbm->parent; unsigned long base; if (res->flags & IORESOURCE_IO) @@ -1351,6 +1357,12 @@ (pbm == &p->pbm_A ? 'A' : 'B')); prom_halt(); } + + /* Register legacy regions if this PBM covers that area. */ + if (pbm->io_space.start == ibase && + pbm->mem_space.start == mbase) + pci_register_legacy_regions(&pbm->io_space, + &pbm->mem_space); } static void __init sabre_pbm_init(struct pci_controller_info *p, int sabre_node, u32 dma_begin) @@ -1476,7 +1488,7 @@ /* Hack up top-level resources. */ pbm->io_space.start = p->controller_regs + SABRE_IOSPACE; - pbm->io_space.end = pbm->io_space.start + (1UL << 16) - 1UL; + pbm->io_space.end = pbm->io_space.start + (1UL << 24) - 1UL; pbm->io_space.flags = IORESOURCE_IO; pbm->mem_space.start = p->controller_regs + SABRE_MEMSPACE; @@ -1491,6 +1503,9 @@ prom_printf("Cannot register Hummingbird's MEM space.\n"); prom_halt(); } + + pci_register_legacy_regions(&pbm->io_space, + &pbm->mem_space); } } @@ -1514,8 +1529,19 @@ if (prom_getproperty(pnode, "compatible", compat, sizeof(compat)) > 0 && - !strcmp(compat, "pci108e,a001")) + !strcmp(compat, "pci108e,a001")) { hummingbird_p = 1; + } else { + int cpu_node = linux_cpus[0].prom_node; + + /* Of course, Sun has to encode things a thousand + * different ways, inconsistently. + */ + if (prom_getproperty(cpu_node, "name", + compat, sizeof(compat)) > 0 && + !strcmp(compat, "SUNW,UltraSPARC-IIe")) + hummingbird_p = 1; + } } p = kmalloc(sizeof(*p), GFP_ATOMIC); diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/pci_schizo.c linux/arch/sparc64/kernel/pci_schizo.c --- v2.4.5/linux/arch/sparc64/kernel/pci_schizo.c Wed May 16 10:31:27 2001 +++ linux/arch/sparc64/kernel/pci_schizo.c Wed Jun 20 21:00:55 2001 @@ -1,4 +1,4 @@ -/* $Id: pci_schizo.c,v 1.16 2001/05/15 08:54:30 davem Exp $ +/* $Id: pci_schizo.c,v 1.19 2001/06/20 21:31:00 davem Exp $ * pci_schizo.c: SCHIZO specific PCI controller support. * * Copyright (C) 2001 David S. Miller (davem@redhat.com) @@ -339,23 +339,28 @@ if (ret == 0 && pdev == NULL) { ret = 1; } else if (ret == 0) { - switch ((pdev->class >> 16) & 0x0f) { + switch ((pdev->class >> 16) & 0xff) { case PCI_BASE_CLASS_STORAGE: ret = 4; + break; case PCI_BASE_CLASS_NETWORK: ret = 6; + break; case PCI_BASE_CLASS_DISPLAY: ret = 9; + break; case PCI_BASE_CLASS_MULTIMEDIA: case PCI_BASE_CLASS_MEMORY: case PCI_BASE_CLASS_BRIDGE: ret = 10; + break; default: ret = 1; + break; }; } @@ -1191,17 +1196,38 @@ /* Make all Safari error conditions fatal except unmapped errors * which we make generate interrupts. */ +#if 1 + /* XXX Something wrong with some Excalibur systems + * XXX Sun is shipping. The behavior on a 2-cpu + * XXX machine is that both CPU1 parity error bits + * XXX are set and are immediately set again when + * XXX their error status bits are cleared. Just + * XXX ignore them for now. -DaveM + */ + schizo_write(base + SCHIZO_SAFARI_ERRCTRL, + (SCHIZO_SAFERRCTRL_EN | + (SAFARI_ERROR_BADCMD | SAFARI_ERROR_SSMDIS | + SAFARI_ERROR_BADMA | SAFARI_ERROR_BADMB | + SAFARI_ERROR_BADMC | + SAFARI_ERROR_CIQTO | + SAFARI_ERROR_LPQTO | SAFARI_ERROR_SFPQTO | + SAFARI_ERROR_UFPQTO | SAFARI_ERROR_APERR | + SAFARI_ERROR_BUSERR | SAFARI_ERROR_TIMEOUT | + SAFARI_ERROR_ILL))); +#else schizo_write(base + SCHIZO_SAFARI_ERRCTRL, (SCHIZO_SAFERRCTRL_EN | (SAFARI_ERROR_BADCMD | SAFARI_ERROR_SSMDIS | SAFARI_ERROR_BADMA | SAFARI_ERROR_BADMB | - SAFARI_ERROR_BADMC | SAFARI_ERROR_CPU1PS | - SAFARI_ERROR_CPU1PB | SAFARI_ERROR_CPU0PS | - SAFARI_ERROR_CPU0PB | SAFARI_ERROR_CIQTO | + SAFARI_ERROR_BADMC | + SAFARI_ERROR_CPU1PS | SAFARI_ERROR_CPU1PB | + SAFARI_ERROR_CPU0PS | SAFARI_ERROR_CPU0PB | + SAFARI_ERROR_CIQTO | SAFARI_ERROR_LPQTO | SAFARI_ERROR_SFPQTO | SAFARI_ERROR_UFPQTO | SAFARI_ERROR_APERR | SAFARI_ERROR_BUSERR | SAFARI_ERROR_TIMEOUT | SAFARI_ERROR_ILL))); +#endif schizo_write(base + SCHIZO_SAFARI_IRQCTRL, (SCHIZO_SAFIRQCTRL_EN | (SAFARI_ERROR_UNMAP))); @@ -1487,6 +1513,8 @@ request_resource(&ioport_resource, &pbm->io_space); request_resource(&iomem_resource, &pbm->mem_space); + pci_register_legacy_regions(&pbm->io_space, + &pbm->mem_space); } #define SCHIZO_STRBUF_CONTROL_A (SCHIZO_PBM_A_REGS_OFF + 0x02800UL) diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/power.c linux/arch/sparc64/kernel/power.c --- v2.4.5/linux/arch/sparc64/kernel/power.c Tue Jul 11 15:46:08 2000 +++ linux/arch/sparc64/kernel/power.c Tue Jun 12 11:08:46 2001 @@ -1,4 +1,4 @@ -/* $Id: power.c,v 1.8 2000/07/11 22:41:33 davem Exp $ +/* $Id: power.c,v 1.9 2001/06/08 02:28:22 davem Exp $ * power.c: Power management driver. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -81,6 +81,11 @@ { struct linux_ebus *ebus; struct linux_ebus_device *edev; + static int invoked = 0; + + if (invoked) + return; + invoked = 1; for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c --- v2.4.5/linux/arch/sparc64/kernel/process.c Thu Apr 12 12:10:25 2001 +++ linux/arch/sparc64/kernel/process.c Mon Jun 11 19:15:27 2001 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.117 2001/03/30 07:10:41 davem Exp $ +/* $Id: process.c,v 1.118 2001/06/03 13:41:13 ecd Exp $ * arch/sparc64/kernel/process.c * * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu) @@ -111,6 +111,7 @@ extern void (*prom_palette)(int); extern int serial_console; #endif +extern void (*prom_keyboard)(void); void machine_halt(void) { @@ -121,6 +122,8 @@ if (!serial_console && prom_palette) prom_palette (1); #endif + if (prom_keyboard) + prom_keyboard(); prom_halt(); panic("Halt failed!"); } @@ -139,6 +142,8 @@ if (!serial_console && prom_palette) prom_palette (1); #endif + if (prom_keyboard) + prom_keyboard(); if (cmd) prom_reboot(cmd); if (*reboot_command) diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/rtrap.S linux/arch/sparc64/kernel/rtrap.S --- v2.4.5/linux/arch/sparc64/kernel/rtrap.S Sun Mar 25 18:14:21 2001 +++ linux/arch/sparc64/kernel/rtrap.S Tue Jun 12 11:08:46 2001 @@ -1,4 +1,4 @@ -/* $Id: rtrap.S,v 1.54 2001/03/08 22:08:51 davem Exp $ +/* $Id: rtrap.S,v 1.55 2001/06/05 09:56:06 davem Exp $ * rtrap.S: Preparing for return from trap on Sparc V9. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -88,9 +88,8 @@ sethi %hi(irq_stat), %l2 ! &softirq_active or %l2, %lo(irq_stat), %l2 ! &softirq_active sllx %l0, 6, %l0 - ldx [%l2 + %l0], %l1 ! softirq_active + softirq_mask - srlx %l1, 32, %l2 - andcc %l1, %l2, %g0 + lduw [%l2 + %l0], %l1 ! softirq_pending + cmp %l1, 0 bne,pn %icc, __handle_softirq ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/setup.c linux/arch/sparc64/kernel/setup.c --- v2.4.5/linux/arch/sparc64/kernel/setup.c Thu Apr 26 22:17:25 2001 +++ linux/arch/sparc64/kernel/setup.c Mon Jun 11 19:15:27 2001 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.64 2001/04/24 21:10:05 davem Exp $ +/* $Id: setup.c,v 1.65 2001/06/03 13:41:13 ecd Exp $ * linux/arch/sparc64/kernel/setup.c * * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu) @@ -64,6 +64,7 @@ #if CONFIG_SUN_CONSOLE void (*prom_palette)(int); #endif +void (*prom_keyboard)(void); asmlinkage void sys_sync(void); /* it's really int */ static void diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c --- v2.4.5/linux/arch/sparc64/kernel/sparc64_ksyms.c Sun May 20 11:32:07 2001 +++ linux/arch/sparc64/kernel/sparc64_ksyms.c Mon Jun 11 19:15:27 2001 @@ -1,4 +1,4 @@ -/* $Id: sparc64_ksyms.c,v 1.107 2001/05/18 08:01:35 davem Exp $ +/* $Id: sparc64_ksyms.c,v 1.108 2001/06/05 03:39:50 davem Exp $ * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -184,6 +185,9 @@ EXPORT_SYMBOL(mostek_lock); EXPORT_SYMBOL(mstk48t02_regs); EXPORT_SYMBOL(request_fast_irq); +#if CONFIG_SUN_AUXIO +EXPORT_SYMBOL(auxio_register); +#endif #if CONFIG_SBUS EXPORT_SYMBOL(sbus_root); EXPORT_SYMBOL(dma_chain); diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c --- v2.4.5/linux/arch/sparc64/kernel/sys_sparc32.c Fri Apr 13 20:15:55 2001 +++ linux/arch/sparc64/kernel/sys_sparc32.c Wed Jun 20 21:00:55 2001 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc32.c,v 1.176 2001/04/14 01:12:02 davem Exp $ +/* $Id: sys_sparc32.c,v 1.177 2001/06/10 06:48:46 davem Exp $ * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -3493,6 +3493,7 @@ #endif /* CONFIG_MODULES */ +#if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE) /* Stuff for NFS server syscalls... */ struct nfsctl_svc32 { u16 svc32_port; @@ -3815,6 +3816,13 @@ kfree(kres); return err; } +#else /* !NFSD */ +extern asmlinkage long sys_ni_syscall(void); +int asmlinkage sys32_nfsservctl(int cmd, void *notused, void *notused2) +{ + return sys_ni_syscall(); +} +#endif /* Translations due to time_t size differences. Which affects all sorts of things, like timeval and itimerval. */ diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/time.c linux/arch/sparc64/kernel/time.c --- v2.4.5/linux/arch/sparc64/kernel/time.c Thu Apr 26 22:17:25 2001 +++ linux/arch/sparc64/kernel/time.c Tue Jun 12 11:08:46 2001 @@ -1,4 +1,4 @@ -/* $Id: time.c,v 1.37 2001/04/24 01:09:12 davem Exp $ +/* $Id: time.c,v 1.39 2001/06/08 02:33:37 davem Exp $ * time.c: UltraSparc timer and TOD clock support. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -32,6 +32,7 @@ #include #include #include +#include #include extern rwlock_t xtime_lock; @@ -408,7 +409,13 @@ unsigned long flags; #ifdef CONFIG_PCI struct linux_ebus *ebus = NULL; + struct isa_bridge *isa_br = NULL; #endif + static int invoked = 0; + + if (invoked) + return; + invoked = 1; if (this_is_starfire) { @@ -433,6 +440,9 @@ else if (ebus_chain != NULL) { ebus = ebus_chain; busnd = ebus->prom_node; + } else if (isa_chain != NULL) { + isa_br = isa_chain; + busnd = isa_br->prom_node; } #endif else if (sbus_root != NULL) { @@ -465,6 +475,13 @@ node = prom_getchild(busnd); } } + while ((node == 0) && isa_br != NULL) { + isa_br = isa_br->next; + if (isa_br != NULL) { + busnd = isa_br->prom_node; + node = prom_getchild(busnd); + } + } #endif if (node == 0) { prom_printf("clock_probe: Cannot find timer chip\n"); @@ -504,6 +521,22 @@ mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; } break; + } else if (isa_chain != NULL) { + struct isa_device *isadev; + + for_each_isadev(isadev, isa_br) + if (isadev->prom_node == node) + break; + if (isadev == NULL) { + prom_printf("%s: Mostek not probed by ISA\n"); + prom_halt(); + } + if (!strcmp(model, "ds1287")) { + ds1287_regs = isadev->resource.start; + } else { + mstk48t59_regs = isadev->resource.start; + mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; + } } #endif else { diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/math-emu/sfp-util.h linux/arch/sparc64/math-emu/sfp-util.h --- v2.4.5/linux/arch/sparc64/math-emu/sfp-util.h Mon Dec 20 22:05:52 1999 +++ linux/arch/sparc64/math-emu/sfp-util.h Wed Jun 20 21:00:55 2001 @@ -1,4 +1,4 @@ -/* $Id: sfp-util.h,v 1.4 1999/09/20 12:14:19 jj Exp $ +/* $Id: sfp-util.h,v 1.5 2001/06/10 06:48:46 davem Exp $ * arch/sparc64/math-emu/sfp-util.h * * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz) @@ -12,10 +12,10 @@ #include #define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("addcc %4,%5,%1 - add %2,%3,%0 - bcs,a,pn %%xcc, 1f - add %0, 1, %0 + __asm__ ("addcc %4,%5,%1\n\ + add %2,%3,%0\n\ + bcs,a,pn %%xcc, 1f\n\ + add %0, 1, %0\n\ 1:" \ : "=r" ((UDItype)(sh)), \ "=&r" ((UDItype)(sl)) \ @@ -26,10 +26,10 @@ : "cc") #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("subcc %4,%5,%1 - sub %2,%3,%0 - bcs,a,pn %%xcc, 1f - sub %0, 1, %0 + __asm__ ("subcc %4,%5,%1\n\ + sub %2,%3,%0\n\ + bcs,a,pn %%xcc, 1f\n\ + sub %0, 1, %0\n\ 1:" \ : "=r" ((UDItype)(sh)), \ "=&r" ((UDItype)(sl)) \ @@ -43,26 +43,26 @@ do { \ UDItype tmp1, tmp2, tmp3, tmp4; \ __asm__ __volatile__ ( \ - "srl %7,0,%3 - mulx %3,%6,%1 - srlx %6,32,%2 - mulx %2,%3,%4 - sllx %4,32,%5 - srl %6,0,%3 - sub %1,%5,%5 - srlx %5,32,%5 - addcc %4,%5,%4 - srlx %7,32,%5 - mulx %3,%5,%3 - mulx %2,%5,%5 - sethi %%hi(0x80000000),%2 - addcc %4,%3,%4 - srlx %4,32,%4 - add %2,%2,%2 - movcc %%xcc,%%g0,%2 - addcc %5,%4,%5 - sllx %3,32,%3 - add %1,%3,%1 + "srl %7,0,%3\n\ + mulx %3,%6,%1\n\ + srlx %6,32,%2\n\ + mulx %2,%3,%4\n\ + sllx %4,32,%5\n\ + srl %6,0,%3\n\ + sub %1,%5,%5\n\ + srlx %5,32,%5\n\ + addcc %4,%5,%4\n\ + srlx %7,32,%5\n\ + mulx %3,%5,%3\n\ + mulx %2,%5,%5\n\ + sethi %%hi(0x80000000),%2\n\ + addcc %4,%3,%4\n\ + srlx %4,32,%4\n\ + add %2,%2,%2\n\ + movcc %%xcc,%%g0,%2\n\ + addcc %5,%4,%5\n\ + sllx %3,32,%3\n\ + add %1,%3,%1\n\ add %5,%2,%0" \ : "=r" ((UDItype)(wh)), \ "=&r" ((UDItype)(wl)), \ diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/vmlinux.lds linux/arch/sparc64/vmlinux.lds --- v2.4.5/linux/arch/sparc64/vmlinux.lds Thu Nov 9 15:57:41 2000 +++ linux/arch/sparc64/vmlinux.lds Mon Jul 2 14:40:58 2001 @@ -16,7 +16,7 @@ } =0 _etext = .; PROVIDE (etext = .); - .rodata : { *(.rodata) } + .rodata : { *(.rodata) *(.rodata.*) } .rodata1 : { *(.rodata1) } .data : { diff -u --recursive --new-file v2.4.5/linux/drivers/Makefile linux/drivers/Makefile --- v2.4.5/linux/drivers/Makefile Wed May 16 10:27:02 2001 +++ linux/drivers/Makefile Mon Jun 11 19:15:27 2001 @@ -7,7 +7,8 @@ mod-subdirs := dio mtd sbus video macintosh usb input telephony sgi i2o ide \ - scsi md ieee1394 pnp isdn atm fc4 net/hamradio i2c acpi + scsi md ieee1394 pnp isdn atm fc4 net/hamradio i2c acpi \ + bluetooth subdir-y := parport char block net sound misc media cdrom subdir-m := $(subdir-y) @@ -42,6 +43,8 @@ subdir-$(CONFIG_HAMRADIO) += net/hamradio subdir-$(CONFIG_I2C) += i2c subdir-$(CONFIG_ACPI) += acpi + +subdir-$(CONFIG_BLUEZ) += bluetooth include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.5/linux/drivers/acorn/char/keyb_arc.c linux/drivers/acorn/char/keyb_arc.c --- v2.4.5/linux/drivers/acorn/char/keyb_arc.c Fri Feb 9 11:30:22 2001 +++ linux/drivers/acorn/char/keyb_arc.c Wed Jun 27 14:12:04 2001 @@ -390,7 +390,7 @@ kbd_state, keyval); #endif mdelay(1); - inb(IOC_KARTRX); + ioc_readb(IOC_KARTRX); a5kkbd_sendbyte (HRST); kbd_state = KBD_INITRST; return 0; @@ -407,13 +407,13 @@ static void a5kkbd_rx(int irq, void *dev_id, struct pt_regs *regs) { kbd_pt_regs = regs; - if (handle_rawcode(inb(IOC_KARTRX))) + if (handle_rawcode(ioc_readb(IOC_KARTRX))) tasklet_schedule(&keyboard_tasklet); } static void a5kkbd_tx(int irq, void *dev_id, struct pt_regs *regs) { - outb (kbd_txval[kbd_txtail], IOC_KARTTX); + ioc_writeb (kbd_txval[kbd_txtail], IOC_KARTTX); KBD_INCTXPTR(kbd_txtail); if (kbd_txtail == kbd_txhead) disable_irq(irq); @@ -431,7 +431,7 @@ if (request_irq (IRQ_KEYBOARDTX, a5kkbd_tx, 0, "keyboard", NULL) != 0) panic("Could not allocate keyboard transmit IRQ!"); - (void)inb(IOC_KARTRX); + (void)ioc_readb(IOC_KARTRX); if (request_irq (IRQ_KEYBOARDRX, a5kkbd_rx, 0, "keyboard", NULL) != 0) panic("Could not allocate keyboard receive IRQ!"); diff -u --recursive --new-file v2.4.5/linux/drivers/acorn/char/keyb_ps2.c linux/drivers/acorn/char/keyb_ps2.c --- v2.4.5/linux/drivers/acorn/char/keyb_ps2.c Fri Feb 9 11:30:22 2001 +++ linux/drivers/acorn/char/keyb_ps2.c Wed Jun 27 14:12:04 2001 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -37,6 +38,12 @@ extern void kbd_reset_kdown(void); int kbd_read_mask; +#define TX_DONE 0 +#define TX_SENT 1 +#define TX_SEND 2 + +static volatile int tx_state; + #define VERSION 100 #define KBD_REPORT_ERR @@ -233,8 +240,33 @@ static inline void ps2kbd_sendbyte(unsigned char val) { - while(!(inb(IOMD_KCTRL) & (1 << 7))); - outb(val, IOMD_KARTTX); + int tries = 3, timeout = 1000; + + tx_state = TX_SEND; + + do { + switch (tx_state) { + case TX_SEND: + tx_state = TX_SENT; + timeout = 1000; + tries --; + + while(!(iomd_readb(IOMD_KCTRL) & (1 << 7))); + iomd_writeb(val, IOMD_KARTTX); + break; + + case TX_SENT: + udelay(1000); + if (--timeout == 0) { + printk(KERN_ERR "Keyboard timeout\n"); + tx_state = TX_DONE; + } + break; + + case TX_DONE: + break; + } + } while (tries > 0 && tx_state != TX_DONE); } static unsigned char status; @@ -254,18 +286,30 @@ if (keyval > 0x83) { switch (keyval) { - case KBD_ESCAPEE0: - ncodes = 2; - bi = 0; - break; - case KBD_ESCAPEE1: - ncodes = 3; - bi = 0; - break; - case KBD_BREAK: - status |= CODE_BREAK; - default: - return; + case KBD_ESCAPEE0: + ncodes = 2; + bi = 0; + break; + + case KBD_ESCAPEE1: + ncodes = 3; + bi = 0; + break; + + case KBD_ACK: + tx_state = TX_DONE; + return; + + case KBD_RESEND: + tx_state = TX_SEND; + return; + + case KBD_BREAK: + status |= CODE_BREAK; + return; + + default: + return; } } @@ -278,6 +322,13 @@ switch (buffer[0] << 8 | buffer[1]) { case ESCE0(0x11): keysym = K_RALT; break; case ESCE0(0x14): keysym = K_RCTL; break; + /* + * take care of MS extra keys (actually + * 0x7d - 0x7f, but last one is already K_NONE + */ + case ESCE0(0x1f): keysym = 124; break; + case ESCE0(0x27): keysym = 125; break; + case ESCE0(0x2f): keysym = 126; break; case ESCE0(0x4a): keysym = KP_SLH; break; case ESCE0(0x5a): keysym = KP_ENT; break; case ESCE0(0x69): keysym = K_END; break; @@ -320,8 +371,8 @@ { kbd_pt_regs = regs; - while (inb(IOMD_KCTRL) & (1 << 5)) - handle_rawcode(inb(IOMD_KARTRX)); + while (iomd_readb(IOMD_KCTRL) & (1 << 5)) + handle_rawcode(iomd_readb(IOMD_KARTRX)); tasklet_schedule(&keyboard_tasklet); } @@ -332,10 +383,10 @@ int __init ps2kbd_init_hw(void) { /* Reset the keyboard state machine. */ - outb(0, IOMD_KCTRL); - outb(8, IOMD_KCTRL); + iomd_writeb(0, IOMD_KCTRL); + iomd_writeb(8, IOMD_KCTRL); + iomd_readb(IOMD_KARTRX); - (void)IOMD_KARTRX; if (request_irq (IRQ_KEYBOARDRX, ps2kbd_rx, 0, "keyboard", NULL) != 0) panic("Could not allocate keyboard receive IRQ!"); if (request_irq (IRQ_KEYBOARDTX, ps2kbd_tx, 0, "keyboard", NULL) != 0) diff -u --recursive --new-file v2.4.5/linux/drivers/acorn/char/mouse_ps2.c linux/drivers/acorn/char/mouse_ps2.c --- v2.4.5/linux/drivers/acorn/char/mouse_ps2.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acorn/char/mouse_ps2.c Wed Jun 27 14:12:04 2001 @@ -0,0 +1,289 @@ +/* + * Driver for PS/2 mouse on IOMD interface + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* + * PS/2 Auxiliary Device + */ + +static struct aux_queue *queue; /* Mouse data buffer. */ +static int aux_count = 0; +/* used when we send commands to the mouse that expect an ACK. */ +static unsigned char mouse_reply_expected = 0; + +#define MAX_RETRIES 60 /* some aux operations take long time*/ + +/* + * Mouse Commands + */ + +#define AUX_SET_RES 0xE8 /* Set resolution */ +#define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */ +#define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */ +#define AUX_GET_SCALE 0xE9 /* Get scaling factor */ +#define AUX_SET_STREAM 0xEA /* Set stream mode */ +#define AUX_SET_SAMPLE 0xF3 /* Set sample rate */ +#define AUX_ENABLE_DEV 0xF4 /* Enable aux device */ +#define AUX_DISABLE_DEV 0xF5 /* Disable aux device */ +#define AUX_RESET 0xFF /* Reset aux device */ +#define AUX_ACK 0xFA /* Command byte ACK. */ + +#define AUX_BUF_SIZE 2048 /* This might be better divisible by + three to make overruns stay in sync + but then the read function would + need a lock etc - ick */ + +struct aux_queue { + unsigned long head; + unsigned long tail; + wait_queue_head_t proc_list; + struct fasync_struct *fasync; + unsigned char buf[AUX_BUF_SIZE]; +}; + +/* + * Send a byte to the mouse. + */ +static void aux_write_dev(int val) +{ + while (!(iomd_readb(IOMD_MSECTL) & 0x80)); + iomd_writeb(val, IOMD_MSEDAT); +} + +/* + * Send a byte to the mouse & handle returned ack + */ +static void aux_write_ack(int val) +{ + while (!(iomd_readb(IOMD_MSECTL) & 0x80)); + iomd_writeb(val, IOMD_MSEDAT); + + /* we expect an ACK in response. */ + mouse_reply_expected++; +} + +static unsigned char get_from_queue(void) +{ + unsigned char result; + + result = queue->buf[queue->tail]; + queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1); + return result; +} + +static void psaux_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + int val = iomd_readb(IOMD_MSEDAT); + + if (mouse_reply_expected) { + if (val == AUX_ACK) { + mouse_reply_expected--; + return; + } + mouse_reply_expected = 0; + } + + add_mouse_randomness(val); + if (aux_count) { + int head = queue->head; + + queue->buf[head] = val; + head = (head + 1) & (AUX_BUF_SIZE-1); + if (head != queue->tail) { + queue->head = head; + kill_fasync(&queue->fasync, SIGIO, POLL_IN); + wake_up_interruptible(&queue->proc_list); + } + } +} + +static inline int queue_empty(void) +{ + return queue->head == queue->tail; +} + +static int fasync_aux(int fd, struct file *filp, int on) +{ + int retval; + + retval = fasync_helper(fd, filp, on, &queue->fasync); + if (retval < 0) + return retval; + return 0; +} + + +/* + * Random magic cookie for the aux device + */ +#define AUX_DEV ((void *)queue) + +static int release_aux(struct inode * inode, struct file * file) +{ + fasync_aux(-1, file, 0); + if (--aux_count) + return 0; + free_irq(IRQ_MOUSERX, AUX_DEV); + return 0; +} + +/* + * Install interrupt handler. + * Enable auxiliary device. + */ + +static int open_aux(struct inode * inode, struct file * file) +{ + if (aux_count++) + return 0; + + queue->head = queue->tail = 0; /* Flush input queue */ + if (request_irq(IRQ_MOUSERX, psaux_interrupt, SA_SHIRQ, "ps/2 mouse", + AUX_DEV)) { + aux_count--; + return -EBUSY; + } + + aux_write_ack(AUX_ENABLE_DEV); /* Enable aux device */ + + return 0; +} + +/* + * Put bytes from input queue to buffer. + */ + +static ssize_t read_aux(struct file * file, char * buffer, + size_t count, loff_t *ppos) +{ + DECLARE_WAITQUEUE(wait, current); + ssize_t i = count; + unsigned char c; + + if (queue_empty()) { + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; + add_wait_queue(&queue->proc_list, &wait); +repeat: + current->state = TASK_INTERRUPTIBLE; + if (queue_empty() && !signal_pending(current)) { + schedule(); + goto repeat; + } + current->state = TASK_RUNNING; + remove_wait_queue(&queue->proc_list, &wait); + } + while (i > 0 && !queue_empty()) { + c = get_from_queue(); + put_user(c, buffer++); + i--; + } + if (count-i) { + file->f_dentry->d_inode->i_atime = CURRENT_TIME; + return count-i; + } + if (signal_pending(current)) + return -ERESTARTSYS; + return 0; +} + +/* + * Write to the aux device. + */ + +static ssize_t write_aux(struct file * file, const char * buffer, + size_t count, loff_t *ppos) +{ + ssize_t retval = 0; + + if (count) { + ssize_t written = 0; + + if (count > 32) + count = 32; /* Limit to 32 bytes. */ + do { + char c; + get_user(c, buffer++); + aux_write_dev(c); + written++; + } while (--count); + retval = -EIO; + if (written) { + retval = written; + file->f_dentry->d_inode->i_mtime = CURRENT_TIME; + } + } + + return retval; +} + +static unsigned int aux_poll(struct file *file, poll_table * wait) +{ + poll_wait(file, &queue->proc_list, wait); + if (!queue_empty()) + return POLLIN | POLLRDNORM; + return 0; +} + +struct file_operations psaux_fops = { + read: read_aux, + write: write_aux, + poll: aux_poll, + open: open_aux, + release: release_aux, + fasync: fasync_aux, +}; + +/* + * Initialize driver. + */ +static struct miscdevice psaux_mouse = { + PSMOUSE_MINOR, "psaux", &psaux_fops +}; + +int __init psaux_init(void) +{ + /* Reset the mouse state machine. */ + iomd_writeb(0, IOMD_MSECTL); + iomd_writeb(8, IOMD_MSECTL); + + misc_register(&psaux_mouse); + queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL); + memset(queue, 0, sizeof(*queue)); + queue->head = queue->tail = 0; + init_waitqueue_head(&queue->proc_list); + + aux_write_ack(AUX_SET_SAMPLE); + aux_write_ack(100); /* 100 samples/sec */ + aux_write_ack(AUX_SET_RES); + aux_write_ack(3); /* 8 counts per mm */ + aux_write_ack(AUX_SET_SCALE21); /* 2:1 scaling */ + + return 0; +} diff -u --recursive --new-file v2.4.5/linux/drivers/acorn/char/mouse_rpc.c linux/drivers/acorn/char/mouse_rpc.c --- v2.4.5/linux/drivers/acorn/char/mouse_rpc.c Mon Sep 18 15:15:21 2000 +++ linux/drivers/acorn/char/mouse_rpc.c Wed Jun 27 14:12:04 2001 @@ -34,9 +34,9 @@ short x, y, dx, dy; int buttons; - x = (short)inl(IOMD_MOUSEX); - y = (short)inl(IOMD_MOUSEY); - buttons = (inl (0x800C4000) >> 4) & 7; + x = (short)iomd_readl(IOMD_MOUSEX); + y = (short)iomd_readl(IOMD_MOUSEY); + buttons = (__raw_readl(0xe0310000) >> 4) & 7; dx = x - old_x; old_x = x; @@ -60,9 +60,9 @@ if (mousedev < 0) printk("rpcmouse: could not register mouse driver\n"); else { - old_x = (short)inl(IOMD_MOUSEX); - old_y = (short)inl(IOMD_MOUSEY); - old_b = (inl (0x800C4000) >> 4) & 7; + old_x = (short)iomd_readl(IOMD_MOUSEX); + old_y = (short)iomd_readl(IOMD_MOUSEY); + old_b = (__raw_readl(0xe0310000) >> 4) & 7; if (request_irq(IRQ_VSYNCPULSE, mouse_rpc_irq, SA_SHIRQ, "mouse", &mousedev)) { printk("rpcmouse: unable to allocate VSYNC interrupt\n"); unregister_busmouse(mousedev); diff -u --recursive --new-file v2.4.5/linux/drivers/acorn/net/ether1.c linux/drivers/acorn/net/ether1.c --- v2.4.5/linux/drivers/acorn/net/ether1.c Fri Feb 9 11:30:22 2001 +++ linux/drivers/acorn/net/ether1.c Wed Jun 27 14:12:04 2001 @@ -75,7 +75,7 @@ /* ------------------------------------------------------------------------- */ -static const char version[] __initdata = KERN_INFO "ether1 ethernet driver (c) 2000 Russell King v1.07\n"; +static char version[] __initdata = "ether1 ethernet driver (c) 2000 Russell King v1.07\n"; #define BUS_16 16 #define BUS_8 8 @@ -990,7 +990,7 @@ static unsigned int version_printed = 0; if (net_debug && version_printed++ == 0) - printk (version); + printk(KERN_INFO "%s", version); } static struct net_device * __init ether1_init_one(struct expansion_card *ec) @@ -1045,7 +1045,6 @@ release: release_region(dev->base_addr, 16); release_region(dev->base_addr + 0x800, 4096); -free: unregister_netdev(dev); kfree(dev); out: diff -u --recursive --new-file v2.4.5/linux/drivers/acorn/net/ether3.c linux/drivers/acorn/net/ether3.c --- v2.4.5/linux/drivers/acorn/net/ether3.c Fri Feb 9 11:30:22 2001 +++ linux/drivers/acorn/net/ether3.c Wed Jun 27 14:12:04 2001 @@ -70,7 +70,7 @@ #include #include -static const char version[] __initdata = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n"; +static char version[] __initdata = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n"; #include "ether3.h" @@ -777,7 +777,7 @@ static unsigned version_printed = 0; if (net_debug && version_printed++ == 0) - printk(version); + printk(KERN_INFO "%s", version); } static const char * __init diff -u --recursive --new-file v2.4.5/linux/drivers/acorn/scsi/acornscsi.c linux/drivers/acorn/scsi/acornscsi.c --- v2.4.5/linux/drivers/acorn/scsi/acornscsi.c Fri Mar 2 18:38:37 2001 +++ linux/drivers/acorn/scsi/acornscsi.c Wed Jun 27 14:12:04 2001 @@ -144,6 +144,7 @@ #include #include #include +#include #include #include @@ -157,6 +158,8 @@ #include "acornscsi.h" #include "msgqueue.h" +#include + #define VER_MAJOR 2 #define VER_MINOR 0 #define VER_PATCH 6 @@ -206,24 +209,24 @@ static inline void sbic_arm_write(unsigned int io_port, int reg, int value) { - outb_t(reg, io_port); - outb_t(value, io_port + 4); + __raw_writeb(reg, io_port); + __raw_writeb(value, io_port + 4); } #define sbic_arm_writenext(io,val) \ - outb_t((val), (io) + 4) + __raw_writeb((val), (io) + 4) static inline int sbic_arm_read(unsigned int io_port, int reg) { if(reg == ASR) - return inl_t(io_port) & 255; - outb_t(reg, io_port); - return inl_t(io_port + 4) & 255; + return __raw_readl(io_port) & 255; + __raw_writeb(reg, io_port); + return __raw_readl(io_port + 4) & 255; } #define sbic_arm_readnext(io) \ - inb_t((io) + 4) + __raw_readb((io) + 4) #ifdef USE_DMAC #define dmac_read(io_port,reg) \ @@ -2858,7 +2861,7 @@ * Params : host - host to setup */ static -void acornscsi_init(AS_Host *host) +void acornscsi_host_init(AS_Host *host) { memset(&host->stats, 0, sizeof (host->stats)); queue_initialise(&host->queues.issue); @@ -2926,7 +2929,7 @@ host->scsi.irq = NO_IRQ; } - acornscsi_init(host); + acornscsi_host_init(host); ++count; } @@ -3118,9 +3121,40 @@ return pos; } -#ifdef MODULE +static Scsi_Host_Template acornscsi_template = { + module: THIS_MODULE, + proc_info: acornscsi_proc_info, + name: "AcornSCSI", + detect: acornscsi_detect, + release: acornscsi_release, + info: acornscsi_info, + queuecommand: acornscsi_queuecmd, + abort: acornscsi_abort, + reset: acornscsi_reset, + bios_param: scsicam_bios_param, + can_queue: 16, + this_id: 7, + sg_tablesize: SG_ALL, + cmd_per_lun: 2, + unchecked_isa_dma: 0, + use_clustering: DISABLE_CLUSTERING +}; -Scsi_Host_Template driver_template = ACORNSCSI_3; +static int __init acornscsi_init(void) +{ + acornscsi_template.module = THIS_MODULE; + scsi_register_module(MODULE_SCSI_HA, &acornscsi_template); + if (acornscsi_template.present) + return 0; -#include "../../scsi/scsi_module.c" -#endif + scsi_unregister_module(MODULE_SCSI_HA, &acornscsi_template); + return -ENODEV; +} + +static void __exit acornscsi_exit(void) +{ + scsi_unregister_module(MODULE_SCSI_HA, &acornscsi_template); +} + +module_init(acornscsi_init); +module_exit(acornscsi_exit); diff -u --recursive --new-file v2.4.5/linux/drivers/acorn/scsi/acornscsi.h linux/drivers/acorn/scsi/acornscsi.h --- v2.4.5/linux/drivers/acorn/scsi/acornscsi.h Mon Sep 18 15:15:22 2000 +++ linux/drivers/acorn/scsi/acornscsi.h Wed Jun 27 14:12:04 2001 @@ -12,52 +12,6 @@ #ifndef ACORNSCSI_H #define ACORNSCSI_H -#ifndef ASM -extern int acornscsi_detect (Scsi_Host_Template *); -extern int acornscsi_release (struct Scsi_Host *); -extern const char *acornscsi_info (struct Scsi_Host *); -extern int acornscsi_queuecmd (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -extern int acornscsi_abort (Scsi_Cmnd *); -extern int acornscsi_reset (Scsi_Cmnd *, unsigned int); -extern int acornscsi_proc_info (char *, char **, off_t, int, int, int); -extern int acornscsi_biosparam (Disk *, kdev_t, int []); - -#ifndef NULL -#define NULL 0 -#endif - -#ifndef CMD_PER_LUN -#define CMD_PER_LUN 2 -#endif - -#ifndef CAN_QUEUE -#define CAN_QUEUE 16 -#endif - -#include "linux/proc_fs.h" - -#include - -#define ACORNSCSI_3 { \ -proc_info: acornscsi_proc_info, \ -name: "AcornSCSI", \ -detect: acornscsi_detect, \ -release: acornscsi_release, /* Release */ \ -info: acornscsi_info, \ -queuecommand: acornscsi_queuecmd, \ -abort: acornscsi_abort, \ -reset: acornscsi_reset, \ -bios_param: scsicam_bios_param, \ -can_queue: CAN_QUEUE, /* can_queue */ \ -this_id: 7, /* this id */ \ -sg_tablesize: SG_ALL, /* sg_tablesize */ \ -cmd_per_lun: CMD_PER_LUN, /* cmd_per_lun */ \ -unchecked_isa_dma: 0, /* unchecked isa dma */ \ -use_clustering: DISABLE_CLUSTERING \ - } - -#ifndef HOSTS_C - /* SBIC registers */ #define OWNID 0 #define OWNID_FS1 (1<<7) @@ -405,7 +359,4 @@ struct status_entry status[9][STATUS_BUFFER_SIZE]; } AS_Host; -#endif /* ndef HOSTS_C */ - -#endif /* ndef ASM */ #endif /* ACORNSCSI_H */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/Config.in linux/drivers/acpi/Config.in --- v2.4.5/linux/drivers/acpi/Config.in Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/Config.in Wed Jun 20 17:47:39 2001 @@ -0,0 +1,17 @@ +# +# ACPI configuration +# +#mainmenu_option next_comment +#comment 'ACPI Configuration' + +dep_bool ' ACPI Debug Statements' CONFIG_ACPI_DEBUG $CONFIG_ACPI +dep_tristate ' ACPI Bus Manager' CONFIG_ACPI_BUSMGR $CONFIG_ACPI + +dep_tristate ' System' CONFIG_ACPI_SYS $CONFIG_ACPI_BUSMGR $CONFIG_ACPI +dep_tristate ' Processor' CONFIG_ACPI_CPU $CONFIG_ACPI_BUSMGR $CONFIG_ACPI +dep_tristate ' Button' CONFIG_ACPI_BUTTON $CONFIG_ACPI_BUSMGR $CONFIG_ACPI +dep_tristate ' AC Adapter' CONFIG_ACPI_AC $CONFIG_ACPI_BUSMGR $CONFIG_ACPI +dep_tristate ' Embedded Controller' CONFIG_ACPI_EC $CONFIG_ACPI_BUSMGR $CONFIG_ACPI +dep_tristate ' Control Method Battery' CONFIG_ACPI_CMBATT $CONFIG_ACPI_BUSMGR $CONFIG_ACPI $CONFIG_ACPI_EC +dep_tristate ' Thermal' CONFIG_ACPI_THERMAL $CONFIG_ACPI_BUSMGR $CONFIG_ACPI $CONFIG_ACPI_EC +#endmenu diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/Makefile linux/drivers/acpi/Makefile --- v2.4.5/linux/drivers/acpi/Makefile Sat Mar 3 17:46:47 2001 +++ linux/drivers/acpi/Makefile Wed Jun 20 17:47:39 2001 @@ -1,13 +1,15 @@ # # Makefile for the Linux ACPI interpreter -# +# (It's a mess, but it's all here for a reason.) +# O_TARGET := acpi.o export-objs := acpi_ksyms.o export ACPI_CFLAGS -ACPI_CFLAGS := -D_LINUX + +ACPI_CFLAGS := -D_LINUX -I$(CURDIR)/include # # CONFIG_ACPI_KERNEL_CONFIG is currently only IA64 @@ -16,25 +18,37 @@ ACPI_CFLAGS += -DCONFIG_ACPI_KERNEL_CONFIG_ONLY endif -EXTRA_CFLAGS += -I./include +acpi-subdirs := utilities dispatcher events hardware \ + executer namespace parser resources tables -EXTRA_CFLAGS += $(ACPI_CFLAGS) +ifdef CONFIG_ACPI_DEBUG + ACPI_CFLAGS += -DACPI_DEBUG -Wno-unused #-DENABLE_DEBUGGER + + #acpi-subdirs += debugger +endif -acpi-subdirs := common dispatcher events hardware \ - interpreter namespace parser resources tables +EXTRA_CFLAGS += $(ACPI_CFLAGS) -subdir-$(CONFIG_ACPI) += $(acpi-subdirs) +mod-subdirs := ospm -obj-$(CONFIG_ACPI) := $(patsubst %,%.o,$(acpi-subdirs)) -obj-$(CONFIG_ACPI) += os.o acpi_ksyms.o +subdir-$(CONFIG_ACPI) += $(acpi-subdirs) +subdir-$(CONFIG_ACPI_BUSMGR) += ospm +obj-$(CONFIG_ACPI) += os.o acpi_ksyms.o +obj-$(CONFIG_ACPI) += $(foreach dir,$(acpi-subdirs),$(dir)/$(dir).o) ifdef CONFIG_ACPI_KERNEL_CONFIG - obj-$(CONFIG_ACPI) += acpiconf.o osconf.o + obj-$(CONFIG_ACPI) += acpiconf.o osconf.o else - obj-$(CONFIG_ACPI) += driver.o cmbatt.o cpu.o ec.o acpi_ksyms.o sys.o table.o power.o + obj-$(CONFIG_ACPI) += driver.o endif -include $(TOPDIR)/Rules.make +ifeq ($(CONFIG_ACPI_BUSMGR),y) + obj-y += ospm/ospm.o +endif -clean: - $(RM) *.o */*.o +# commented out until we distribute it -ASG +#ifeq ($(CONFIG_KDB),y) +# obj-m += kdb/kdbm_acpi.o +#endif + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/acpi_ksyms.c linux/drivers/acpi/acpi_ksyms.c --- v2.4.5/linux/drivers/acpi/acpi_ksyms.c Fri Feb 16 16:06:17 2001 +++ linux/drivers/acpi/acpi_ksyms.c Wed Jun 20 17:47:39 2001 @@ -18,6 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include #include #include @@ -27,6 +28,7 @@ #include "acdebug.h" extern int acpi_in_debugger; +extern FADT_DESCRIPTOR acpi_fadt; #define _COMPONENT OS_DEPENDENT MODULE_NAME ("symbols") @@ -55,9 +57,7 @@ EXPORT_SYMBOL(debug_print_raw); EXPORT_SYMBOL(debug_print_prefix); -EXPORT_SYMBOL(acpi_cm_strncmp); -EXPORT_SYMBOL(acpi_cm_memcpy); -EXPORT_SYMBOL(acpi_cm_memset); +EXPORT_SYMBOL(acpi_ut_format_exception); EXPORT_SYMBOL(acpi_get_handle); EXPORT_SYMBOL(acpi_get_parent); @@ -66,6 +66,7 @@ EXPORT_SYMBOL(acpi_get_object_info); EXPORT_SYMBOL(acpi_get_next_object); EXPORT_SYMBOL(acpi_evaluate_object); +EXPORT_SYMBOL(acpi_get_table); EXPORT_SYMBOL(acpi_install_notify_handler); EXPORT_SYMBOL(acpi_remove_notify_handler); @@ -73,6 +74,11 @@ EXPORT_SYMBOL(acpi_remove_gpe_handler); EXPORT_SYMBOL(acpi_install_address_space_handler); EXPORT_SYMBOL(acpi_remove_address_space_handler); +EXPORT_SYMBOL(acpi_install_fixed_event_handler); +EXPORT_SYMBOL(acpi_remove_fixed_event_handler); + +EXPORT_SYMBOL(acpi_acquire_global_lock); +EXPORT_SYMBOL(acpi_release_global_lock); EXPORT_SYMBOL(acpi_get_current_resources); EXPORT_SYMBOL(acpi_get_possible_resources); @@ -81,3 +87,20 @@ EXPORT_SYMBOL(acpi_enable_event); EXPORT_SYMBOL(acpi_disable_event); EXPORT_SYMBOL(acpi_clear_event); + +EXPORT_SYMBOL(acpi_get_timer_duration); +EXPORT_SYMBOL(acpi_get_timer); + +EXPORT_SYMBOL(acpi_os_signal_semaphore); +EXPORT_SYMBOL(acpi_os_create_semaphore); +EXPORT_SYMBOL(acpi_os_delete_semaphore); +EXPORT_SYMBOL(acpi_os_wait_semaphore); + +EXPORT_SYMBOL(acpi_os_in32); +EXPORT_SYMBOL(acpi_os_out32); +EXPORT_SYMBOL(acpi_fadt); +EXPORT_SYMBOL(acpi_hw_register_bit_access); +EXPORT_SYMBOL(acpi_hw_obtain_sleep_type_register_data); +EXPORT_SYMBOL(acpi_enter_sleep_state); +EXPORT_SYMBOL(acpi_get_system_info); + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/cmbatt.c linux/drivers/acpi/cmbatt.c --- v2.4.5/linux/drivers/acpi/cmbatt.c Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/cmbatt.c Wed Dec 31 16:00:00 1969 @@ -1,390 +0,0 @@ -/* - * cmbatt.c - Control Method Battery driver - * - * Copyright (C) 2000 Andrew Grover - * - * 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 - */ -/* - * Changes: - * Brendan Burns 2000-11-15 - * - added proc battery interface - * - parse returned data from _BST and _BIF - * Andy Grover 2000-12-8 - * - improved proc interface - * Pavel Machek 2001-1-31 - * - fixed oops on NULLs in return from _BIF - */ - -#include -#include -#include -#include "acpi.h" -#include "driver.h" - -#define _COMPONENT OS_DEPENDENT - MODULE_NAME ("cmbatt") - -/* ACPI-specific defines */ -#define ACPI_CMBATT_HID "PNP0C0A" -#define ACPI_BATT_PRESENT 0x10 -#define ACPI_BATT_UNKNOWN 0xFFFFFFFF - -/* driver-specific defines */ -#define MAX_CM_BATTERIES 0x8 -#define MAX_BATT_STRLEN 0x20 - -#define Xstrncpy(a, b, c) if (b) strncpy(a,b,c); else strncpy(a, "unknown", c) - -struct cmbatt_info -{ - u32 power_unit; - u32 design_capacity; - u32 last_full_capacity; - u32 battery_technology; - u32 design_voltage; - u32 design_capacity_warning; - u32 design_capacity_low; - u32 battery_capacity_granularity_1; - u32 battery_capacity_granularity_2; - - char model_number[MAX_BATT_STRLEN]; - char serial_number[MAX_BATT_STRLEN]; - char battery_type[MAX_BATT_STRLEN]; - char oem_info[MAX_BATT_STRLEN]; -}; - -struct cmbatt_context -{ - u32 is_present; - ACPI_HANDLE handle; - char UID[9]; - char *power_unit; - struct cmbatt_info info; -}; - -struct cmbatt_status -{ - u32 state; - u32 present_rate; - u32 remaining_capacity; - u32 present_voltage; -}; - -static u32 batt_count = 0; - -static struct cmbatt_context batt_list[MAX_CM_BATTERIES]; - -static ACPI_STATUS -acpi_get_battery_status(ACPI_HANDLE handle, struct cmbatt_status *result) -{ - ACPI_OBJECT *obj; - ACPI_OBJECT *objs; - ACPI_BUFFER buf; - - buf.length = 0; - buf.pointer = NULL; - - /* determine buffer length needed */ - if (acpi_evaluate_object(handle, "_BST", NULL, &buf) != AE_BUFFER_OVERFLOW) { - printk(KERN_ERR "Cmbatt: Could not get battery status struct length\n"); - return AE_NOT_FOUND; - } - - buf.pointer = kmalloc(buf.length, GFP_KERNEL); - if (!buf.pointer) - return AE_NO_MEMORY; - - /* get the data */ - if (!ACPI_SUCCESS(acpi_evaluate_object(handle, "_BST", NULL, &buf))) { - printk(KERN_ERR "Cmbatt: Could not get battery status\n"); - kfree (buf.pointer); - return AE_NOT_FOUND; - } - - obj = (ACPI_OBJECT *) buf.pointer; - objs = obj->package.elements; - - result->state = objs[0].integer.value; - result->present_rate = objs[1].integer.value; - result->remaining_capacity = objs[2].integer.value; - result->present_voltage = objs[3].integer.value; - - kfree(buf.pointer); - - return AE_OK; -} - -static ACPI_STATUS -acpi_get_battery_info(ACPI_HANDLE handle, struct cmbatt_info *result) -{ - ACPI_OBJECT *obj; - ACPI_OBJECT *objs; - ACPI_BUFFER buf; - - buf.length = 0; - buf.pointer = NULL; - - /* determine the length of the data */ - if (acpi_evaluate_object(handle, "_BIF", NULL, &buf) != AE_BUFFER_OVERFLOW) { - printk(KERN_ERR "Cmbatt: Could not get battery info struct length\n"); - return AE_NOT_FOUND; - } - - buf.pointer = kmalloc(buf.length, GFP_KERNEL); - if (!buf.pointer) - return AE_NO_MEMORY; - - /* get the data */ - if (!ACPI_SUCCESS(acpi_evaluate_object(handle, "_BIF", NULL, &buf))) { - printk(KERN_ERR "Cmbatt: Could not get battery info\n"); - kfree (buf.pointer); - return AE_NOT_FOUND; - } - - obj = (ACPI_OBJECT *) buf.pointer; - objs = obj->package.elements; - - result->power_unit=objs[0].integer.value; - result->design_capacity=objs[1].integer.value; - result->last_full_capacity=objs[2].integer.value; - result->battery_technology=objs[3].integer.value; - result->design_voltage=objs[4].integer.value; - result->design_capacity_warning=objs[5].integer.value; - result->design_capacity_low=objs[6].integer.value; - result->battery_capacity_granularity_1=objs[7].integer.value; - result->battery_capacity_granularity_2=objs[8].integer.value; - - /* BUG: trailing NULL issue */ - Xstrncpy(result->model_number, objs[9].string.pointer, MAX_BATT_STRLEN-1); - Xstrncpy(result->serial_number, objs[10].string.pointer, MAX_BATT_STRLEN-1); - Xstrncpy(result->battery_type, objs[11].string.pointer, MAX_BATT_STRLEN-1); - Xstrncpy(result->oem_info, objs[12].string.pointer, MAX_BATT_STRLEN-1); - - kfree(buf.pointer); - - return AE_OK; -} - -/* - * We found a device with the correct HID - */ -static ACPI_STATUS -acpi_found_cmbatt(ACPI_HANDLE handle, u32 level, void *ctx, void **value) -{ - ACPI_DEVICE_INFO info; - - if (batt_count >= MAX_CM_BATTERIES) { - printk(KERN_ERR "Cmbatt: MAX_CM_BATTERIES exceeded\n"); - return AE_OK; - } - - if (!ACPI_SUCCESS(acpi_get_object_info(handle, &info))) { - printk(KERN_ERR "Cmbatt: Could not get battery object info\n"); - return (AE_OK); - } - - if (info.valid & ACPI_VALID_UID) { - strncpy(batt_list[batt_count].UID, info.unique_id, 9); - } - else if (batt_count > 1) { - printk(KERN_WARNING "Cmbatt: No UID but more than 1 battery\n"); - } - - if (!(info.valid & ACPI_VALID_STA)) { - printk(KERN_ERR "Cmbatt: Battery _STA invalid\n"); - return AE_OK; - } - - if (!(info.current_status & ACPI_BATT_PRESENT)) { - printk(KERN_INFO "Cmbatt: Battery socket %d empty\n", batt_count); - batt_list[batt_count].is_present = FALSE; - } - else { - printk(KERN_INFO "Cmbatt: Battery socket %d occupied\n", batt_count); - batt_list[batt_count].is_present = TRUE; - if (acpi_get_battery_info(handle, &batt_list[batt_count].info) != AE_OK) { - printk(KERN_ERR "acpi_get_battery_info failed\n"); - return AE_OK; - } - - batt_list[batt_count].power_unit = (batt_list[batt_count].info.power_unit) ? "mA" : "mW"; - } - - batt_list[batt_count].handle = handle; - - batt_count++; - - return AE_OK; -} - -static int -proc_read_batt_info(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct cmbatt_info *info; - u32 batt_num = (u32) data; - char *p = page; - int len; - - info = &batt_list[batt_num].info; - - /* don't get info more than once for a single proc read */ - if (off != 0) - goto end; - - if (!batt_list[batt_num].is_present) { - p += sprintf(p, "battery %d not present\n", batt_num); - goto end; - } - - if (info->last_full_capacity != ACPI_BATT_UNKNOWN) - p += sprintf(p, "Last Full Capacity: %d %sh\n", - info->last_full_capacity, batt_list[batt_num].power_unit); - - if (info->design_capacity != ACPI_BATT_UNKNOWN) - p += sprintf(p, "Design Capacity: %d %sh\n", - info->design_capacity, batt_list[batt_num].power_unit); - - if (info->battery_technology) - p += sprintf(p, "Battery Technology: Secondary\n"); - else - p += sprintf(p, "Battery Technology: Primary\n"); - - if (info->design_voltage != ACPI_BATT_UNKNOWN) - p += sprintf(p, "Design Voltage: %d mV\n", - info->design_voltage); - - p += sprintf(p, "Design Capacity Warning: %d %sh\n", - info->design_capacity_warning, batt_list[batt_num].power_unit); - p += sprintf(p, "Design Capacity Low: %d %sh\n", - info->design_capacity_low, batt_list[batt_num].power_unit); - p += sprintf(p, "Battery Capacity Granularity 1: %d\n", - info->battery_capacity_granularity_1); - p += sprintf(p, "Battery Capacity Granularity 2: %d\n", - info->battery_capacity_granularity_2); - p += sprintf(p, "Model number; %s\nSerial number: %s\nBattery type: %s\nOEM info: %s\n", - info->model_number,info->serial_number, - info->battery_type,info->oem_info); -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 len; -} - -static int -proc_read_batt_status(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct cmbatt_status status; - u32 batt_num = (u32) data; - char *p = page; - int len; - - /* don't get status more than once for a single proc read */ - if (off != 0) - goto end; - - if (!batt_list[batt_num].is_present) { - p += sprintf(p, "battery %d not present\n", batt_num); - goto end; - } - - if (acpi_get_battery_status(batt_list[batt_num].handle, &status) != AE_OK) { - printk(KERN_ERR "Cmbatt: acpi_get_battery_status failed\n"); - goto end; - } - - p += sprintf(p, "Battery discharging: %s\n", - (status.state & 0x1)?"yes":"no"); - p += sprintf(p, "Battery charging: %s\n", - (status.state & 0x2)?"yes":"no"); - p += sprintf(p, "Battery critically low: %s\n", - (status.state & 0x4)?"yes":"no"); - - if (status.present_rate != ACPI_BATT_UNKNOWN) - p += sprintf(p, "Battery rate: %d %s\n", - status.present_rate, batt_list[batt_num].power_unit); - - if (status.remaining_capacity != ACPI_BATT_UNKNOWN) - p += sprintf(p, "Battery capacity: %d %sh\n", - status.remaining_capacity, batt_list[batt_num].power_unit); - - if (status.present_voltage != ACPI_BATT_UNKNOWN) - p += sprintf(p, "Battery voltage: %d mV\n", - status.present_voltage); - -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 len; -} - - - -int -acpi_cmbatt_init(void) -{ - int i; - - acpi_get_devices(ACPI_CMBATT_HID, - acpi_found_cmbatt, - NULL, - NULL); - - for (i = 0; i < batt_count; i++) { - - char batt_name[20]; - - sprintf(batt_name, "power/batt%d_info", i); - create_proc_read_entry(batt_name, 0, NULL, - proc_read_batt_info, (void *) i); - - sprintf(batt_name, "power/batt%d_status", i); - create_proc_read_entry(batt_name, 0, NULL, - proc_read_batt_status, (void *) i); - - } - - return 0; -} - -int -acpi_cmbatt_terminate(void) -{ - int i; - - for (i = 0; i < batt_count; i++) { - - char batt_name[20]; - - sprintf(batt_name, "power/batt%d_info", i); - remove_proc_entry(batt_name, NULL); - - sprintf(batt_name, "power/batt%d_status", i); - remove_proc_entry(batt_name, NULL); - } - - return 0; -} diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/common/Makefile linux/drivers/acpi/common/Makefile --- v2.4.5/linux/drivers/acpi/common/Makefile Fri Dec 29 14:07:21 2000 +++ linux/drivers/acpi/common/Makefile Wed Dec 31 16:00:00 1969 @@ -1,16 +0,0 @@ -# -# Makefile for all Linux ACPI interpreter subdirectories -# - -O_TARGET := ../$(shell basename `pwd`).o - -obj-$(CONFIG_ACPI) := $(patsubst %.c,%.o,$(wildcard *.c)) - -EXTRA_CFLAGS += -I../include - -EXTRA_CFLAGS += $(ACPI_CFLAGS) - -include $(TOPDIR)/Rules.make - -clean: - $(RM) *.o diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/common/cmalloc.c linux/drivers/acpi/common/cmalloc.c --- v2.4.5/linux/drivers/acpi/common/cmalloc.c Mon Jan 29 10:15:58 2001 +++ linux/drivers/acpi/common/cmalloc.c Wed Dec 31 16:00:00 1969 @@ -1,170 +0,0 @@ -/****************************************************************************** - * - * Module Name: cmalloc - local memory allocation routines - * $Revision: 84 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "acpi.h" -#include "acparser.h" -#include "acinterp.h" -#include "acnamesp.h" -#include "acglobal.h" - -#define _COMPONENT MISCELLANEOUS - MODULE_NAME ("cmalloc") - - -/***************************************************************************** - * - * FUNCTION: _Cm_allocate - * - * PARAMETERS: Size - Size of the allocation - * Component - Component type of caller - * Module - Source file name of caller - * Line - Line number of caller - * - * RETURN: Address of the allocated memory on success, NULL on failure. - * - * DESCRIPTION: The subsystem's equivalent of malloc. - * - ****************************************************************************/ - -void * -_cm_allocate ( - u32 size, - u32 component, - NATIVE_CHAR *module, - u32 line) -{ - void *address = NULL; - - - /* Check for an inadvertent size of zero bytes */ - - if (!size) { - _REPORT_ERROR (module, line, component, - ("Cm_allocate: Attempt to allocate zero bytes\n")); - size = 1; - } - - address = acpi_os_allocate (size); - if (!address) { - /* Report allocation error */ - - _REPORT_ERROR (module, line, component, - ("Cm_allocate: Could not allocate size %X\n", size)); - - return (NULL); - } - - - return (address); -} - - -/***************************************************************************** - * - * FUNCTION: _Cm_callocate - * - * PARAMETERS: Size - Size of the allocation - * Component - Component type of caller - * Module - Source file name of caller - * Line - Line number of caller - * - * RETURN: Address of the allocated memory on success, NULL on failure. - * - * DESCRIPTION: Subsystem equivalent of calloc. - * - ****************************************************************************/ - -void * -_cm_callocate ( - u32 size, - u32 component, - NATIVE_CHAR *module, - u32 line) -{ - void *address = NULL; - - - /* Check for an inadvertent size of zero bytes */ - - if (!size) { - _REPORT_ERROR (module, line, component, - ("Cm_callocate: Attempt to allocate zero bytes\n")); - return (NULL); - } - - - address = acpi_os_callocate (size); - - if (!address) { - /* Report allocation error */ - - _REPORT_ERROR (module, line, component, - ("Cm_callocate: Could not allocate size %X\n", size)); - return (NULL); - } - - - return (address); -} - - -/***************************************************************************** - * - * FUNCTION: _Cm_free - * - * PARAMETERS: Address - Address of the memory to deallocate - * Component - Component type of caller - * Module - Source file name of caller - * Line - Line number of caller - * - * RETURN: None - * - * DESCRIPTION: Frees the memory at Address - * - ****************************************************************************/ - -void -_cm_free ( - void *address, - u32 component, - NATIVE_CHAR *module, - u32 line) -{ - - if (NULL == address) { - _REPORT_ERROR (module, line, component, - ("_Cm_free: Trying to delete a NULL address\n")); - - return; - } - - - acpi_os_free (address); - - return; -} - - diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/common/cmclib.c linux/drivers/acpi/common/cmclib.c --- v2.4.5/linux/drivers/acpi/common/cmclib.c Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/common/cmclib.c Wed Dec 31 16:00:00 1969 @@ -1,818 +0,0 @@ -/****************************************************************************** - * - * Module Name: cmclib - Local implementation of C library functions - * $Revision: 32 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "acpi.h" -#include "acevents.h" -#include "achware.h" -#include "acnamesp.h" -#include "acinterp.h" -#include "amlcode.h" - -/* - * These implementations of standard C Library routines can optionally be - * used if a C library is not available. In general, they are less efficient - * than an inline or assembly implementation - */ - -#define _COMPONENT MISCELLANEOUS - MODULE_NAME ("cmclib") - - -#ifndef ACPI_USE_SYSTEM_CLIBRARY - -/******************************************************************************* - * - * FUNCTION: strlen - * - * PARAMETERS: String - Null terminated string - * - * RETURN: Length - * - * DESCRIPTION: Returns the length of the input string - * - ******************************************************************************/ - - -NATIVE_UINT -acpi_cm_strlen ( - const NATIVE_CHAR *string) -{ - NATIVE_UINT length = 0; - - - /* Count the string until a null is encountered */ - - while (*string) { - length++; - string++; - } - - return (length); -} - - -/******************************************************************************* - * - * FUNCTION: strcpy - * - * PARAMETERS: Dst_string - Target of the copy - * Src_string - The source string to copy - * - * RETURN: Dst_string - * - * DESCRIPTION: Copy a null terminated string - * - ******************************************************************************/ - -NATIVE_CHAR * -acpi_cm_strcpy ( - NATIVE_CHAR *dst_string, - const NATIVE_CHAR *src_string) -{ - NATIVE_CHAR *string = dst_string; - - - /* Move bytes brute force */ - - while (*src_string) { - *string = *src_string; - - string++; - src_string++; - } - - /* Null terminate */ - - *string = 0; - - return (dst_string); -} - - -/******************************************************************************* - * - * FUNCTION: strncpy - * - * PARAMETERS: Dst_string - Target of the copy - * Src_string - The source string to copy - * Count - Maximum # of bytes to copy - * - * RETURN: Dst_string - * - * DESCRIPTION: Copy a null terminated string, with a maximum length - * - ******************************************************************************/ - -NATIVE_CHAR * -acpi_cm_strncpy ( - NATIVE_CHAR *dst_string, - const NATIVE_CHAR *src_string, - NATIVE_UINT count) -{ - NATIVE_CHAR *string = dst_string; - - - /* Copy the string */ - - for (string = dst_string; - count && (count--, (*string++ = *src_string++)); ) - {;} - - /* Pad with nulls if necessary */ - - while (count--) { - *string = 0; - string++; - } - - /* Return original pointer */ - - return (dst_string); -} - - -/******************************************************************************* - * - * FUNCTION: strcmp - * - * PARAMETERS: String1 - First string - * String2 - Second string - * - * RETURN: Index where strings mismatched, or 0 if strings matched - * - * DESCRIPTION: Compare two null terminated strings - * - ******************************************************************************/ - -u32 -acpi_cm_strcmp ( - const NATIVE_CHAR *string1, - const NATIVE_CHAR *string2) -{ - - - for ( ; (*string1 == *string2); string2++) { - if (!*string1++) { - return (0); - } - } - - - return ((unsigned char) *string1 - (unsigned char) *string2); -} - - -/******************************************************************************* - * - * FUNCTION: strncmp - * - * PARAMETERS: String1 - First string - * String2 - Second string - * Count - Maximum # of bytes to compare - * - * RETURN: Index where strings mismatched, or 0 if strings matched - * - * DESCRIPTION: Compare two null terminated strings, with a maximum length - * - ******************************************************************************/ - -u32 -acpi_cm_strncmp ( - const NATIVE_CHAR *string1, - const NATIVE_CHAR *string2, - NATIVE_UINT count) -{ - - - for ( ; count-- && (*string1 == *string2); string2++) { - if (!*string1++) { - return (0); - } - } - - return ((count == -1) ? 0 : ((unsigned char) *string1 - - (unsigned char) *string2)); -} - - -/******************************************************************************* - * - * FUNCTION: Strcat - * - * PARAMETERS: Dst_string - Target of the copy - * Src_string - The source string to copy - * - * RETURN: Dst_string - * - * DESCRIPTION: Append a null terminated string to a null terminated string - * - ******************************************************************************/ - -NATIVE_CHAR * -acpi_cm_strcat ( - NATIVE_CHAR *dst_string, - const NATIVE_CHAR *src_string) -{ - NATIVE_CHAR *string; - - - /* Find end of the destination string */ - - for (string = dst_string; *string++; ) { ; } - - /* Concatinate the string */ - - for (--string; (*string++ = *src_string++); ) { ; } - - return (dst_string); -} - - -/******************************************************************************* - * - * FUNCTION: strncat - * - * PARAMETERS: Dst_string - Target of the copy - * Src_string - The source string to copy - * Count - Maximum # of bytes to copy - * - * RETURN: Dst_string - * - * DESCRIPTION: Append a null terminated string to a null terminated string, - * with a maximum count. - * - ******************************************************************************/ - -NATIVE_CHAR * -acpi_cm_strncat ( - NATIVE_CHAR *dst_string, - const NATIVE_CHAR *src_string, - NATIVE_UINT count) -{ - NATIVE_CHAR *string; - - - if (count) { - /* Find end of the destination string */ - - for (string = dst_string; *string++; ) { ; } - - /* Concatinate the string */ - - for (--string; (*string++ = *src_string++) && --count; ) { ; } - - /* Null terminate if necessary */ - - if (!count) { - *string = 0; - } - } - - return (dst_string); -} - - -/******************************************************************************* - * - * FUNCTION: memcpy - * - * PARAMETERS: Dest - Target of the copy - * Src - Source buffer to copy - * Count - Number of bytes to copy - * - * RETURN: Dest - * - * DESCRIPTION: Copy arbitrary bytes of memory - * - ******************************************************************************/ - -void * -acpi_cm_memcpy ( - void *dest, - const void *src, - NATIVE_UINT count) -{ - NATIVE_CHAR *new = (NATIVE_CHAR *) dest; - NATIVE_CHAR *old = (NATIVE_CHAR *) src; - - - while (count) { - *new = *old; - new++; - old++; - count--; - } - - return (dest); -} - - -/******************************************************************************* - * - * FUNCTION: memset - * - * PARAMETERS: Dest - Buffer to set - * Value - Value to set each byte of memory - * Count - Number of bytes to set - * - * RETURN: Dest - * - * DESCRIPTION: Initialize a buffer to a known value. - * - ******************************************************************************/ - -void * -acpi_cm_memset ( - void *dest, - NATIVE_UINT value, - NATIVE_UINT count) -{ - NATIVE_CHAR *new = (NATIVE_CHAR *) dest; - - - while (count) { - *new = (char) value; - new++; - count--; - } - - return (dest); -} - - -#define NEGATIVE 1 -#define POSITIVE 0 - - -#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' */ - -static const u8 _acpi_ctype[257] = { - _ACPI_CN, /* 0x0 0. */ - _ACPI_CN, /* 0x1 1. */ - _ACPI_CN, /* 0x2 2. */ - _ACPI_CN, /* 0x3 3. */ - _ACPI_CN, /* 0x4 4. */ - _ACPI_CN, /* 0x5 5. */ - _ACPI_CN, /* 0x6 6. */ - _ACPI_CN, /* 0x7 7. */ - _ACPI_CN, /* 0x8 8. */ - _ACPI_CN|_ACPI_SP, /* 0x9 9. */ - _ACPI_CN|_ACPI_SP, /* 0xA 10. */ - _ACPI_CN|_ACPI_SP, /* 0xB 11. */ - _ACPI_CN|_ACPI_SP, /* 0xC 12. */ - _ACPI_CN|_ACPI_SP, /* 0xD 13. */ - _ACPI_CN, /* 0xE 14. */ - _ACPI_CN, /* 0xF 15. */ - _ACPI_CN, /* 0x10 16. */ - _ACPI_CN, /* 0x11 17. */ - _ACPI_CN, /* 0x12 18. */ - _ACPI_CN, /* 0x13 19. */ - _ACPI_CN, /* 0x14 20. */ - _ACPI_CN, /* 0x15 21. */ - _ACPI_CN, /* 0x16 22. */ - _ACPI_CN, /* 0x17 23. */ - _ACPI_CN, /* 0x18 24. */ - _ACPI_CN, /* 0x19 25. */ - _ACPI_CN, /* 0x1A 26. */ - _ACPI_CN, /* 0x1B 27. */ - _ACPI_CN, /* 0x1C 28. */ - _ACPI_CN, /* 0x1D 29. */ - _ACPI_CN, /* 0x1E 30. */ - _ACPI_CN, /* 0x1F 31. */ - _ACPI_XS|_ACPI_SP, /* 0x20 32. ' ' */ - _ACPI_PU, /* 0x21 33. '!' */ - _ACPI_PU, /* 0x22 34. '"' */ - _ACPI_PU, /* 0x23 35. '#' */ - _ACPI_PU, /* 0x24 36. '$' */ - _ACPI_PU, /* 0x25 37. '%' */ - _ACPI_PU, /* 0x26 38. '&' */ - _ACPI_PU, /* 0x27 39. ''' */ - _ACPI_PU, /* 0x28 40. '(' */ - _ACPI_PU, /* 0x29 41. ')' */ - _ACPI_PU, /* 0x2A 42. '*' */ - _ACPI_PU, /* 0x2B 43. '+' */ - _ACPI_PU, /* 0x2C 44. ',' */ - _ACPI_PU, /* 0x2D 45. '-' */ - _ACPI_PU, /* 0x2E 46. '.' */ - _ACPI_PU, /* 0x2F 47. '/' */ - _ACPI_XD|_ACPI_DI, /* 0x30 48. '0' */ - _ACPI_XD|_ACPI_DI, /* 0x31 49. '1' */ - _ACPI_XD|_ACPI_DI, /* 0x32 50. '2' */ - _ACPI_XD|_ACPI_DI, /* 0x33 51. '3' */ - _ACPI_XD|_ACPI_DI, /* 0x34 52. '4' */ - _ACPI_XD|_ACPI_DI, /* 0x35 53. '5' */ - _ACPI_XD|_ACPI_DI, /* 0x36 54. '6' */ - _ACPI_XD|_ACPI_DI, /* 0x37 55. '7' */ - _ACPI_XD|_ACPI_DI, /* 0x38 56. '8' */ - _ACPI_XD|_ACPI_DI, /* 0x39 57. '9' */ - _ACPI_PU, /* 0x3A 58. ':' */ - _ACPI_PU, /* 0x3B 59. ';' */ - _ACPI_PU, /* 0x3C 60. '<' */ - _ACPI_PU, /* 0x3D 61. '=' */ - _ACPI_PU, /* 0x3E 62. '>' */ - _ACPI_PU, /* 0x3F 63. '?' */ - _ACPI_PU, /* 0x40 64. '@' */ - _ACPI_XD|_ACPI_UP, /* 0x41 65. 'A' */ - _ACPI_XD|_ACPI_UP, /* 0x42 66. 'B' */ - _ACPI_XD|_ACPI_UP, /* 0x43 67. 'C' */ - _ACPI_XD|_ACPI_UP, /* 0x44 68. 'D' */ - _ACPI_XD|_ACPI_UP, /* 0x45 69. 'E' */ - _ACPI_XD|_ACPI_UP, /* 0x46 70. 'F' */ - _ACPI_UP, /* 0x47 71. 'G' */ - _ACPI_UP, /* 0x48 72. 'H' */ - _ACPI_UP, /* 0x49 73. 'I' */ - _ACPI_UP, /* 0x4A 74. 'J' */ - _ACPI_UP, /* 0x4B 75. 'K' */ - _ACPI_UP, /* 0x4C 76. 'L' */ - _ACPI_UP, /* 0x4D 77. 'M' */ - _ACPI_UP, /* 0x4E 78. 'N' */ - _ACPI_UP, /* 0x4F 79. 'O' */ - _ACPI_UP, /* 0x50 80. 'P' */ - _ACPI_UP, /* 0x51 81. 'Q' */ - _ACPI_UP, /* 0x52 82. 'R' */ - _ACPI_UP, /* 0x53 83. 'S' */ - _ACPI_UP, /* 0x54 84. 'T' */ - _ACPI_UP, /* 0x55 85. 'U' */ - _ACPI_UP, /* 0x56 86. 'V' */ - _ACPI_UP, /* 0x57 87. 'W' */ - _ACPI_UP, /* 0x58 88. 'X' */ - _ACPI_UP, /* 0x59 89. 'Y' */ - _ACPI_UP, /* 0x5A 90. 'Z' */ - _ACPI_PU, /* 0x5B 91. '[' */ - _ACPI_PU, /* 0x5C 92. '\' */ - _ACPI_PU, /* 0x5D 93. ']' */ - _ACPI_PU, /* 0x5E 94. '^' */ - _ACPI_PU, /* 0x5F 95. '_' */ - _ACPI_PU, /* 0x60 96. '`' */ - _ACPI_XD|_ACPI_LO, /* 0x61 97. 'a' */ - _ACPI_XD|_ACPI_LO, /* 0x62 98. 'b' */ - _ACPI_XD|_ACPI_LO, /* 0x63 99. 'c' */ - _ACPI_XD|_ACPI_LO, /* 0x64 100. 'd' */ - _ACPI_XD|_ACPI_LO, /* 0x65 101. 'e' */ - _ACPI_XD|_ACPI_LO, /* 0x66 102. 'f' */ - _ACPI_LO, /* 0x67 103. 'g' */ - _ACPI_LO, /* 0x68 104. 'h' */ - _ACPI_LO, /* 0x69 105. 'i' */ - _ACPI_LO, /* 0x6A 106. 'j' */ - _ACPI_LO, /* 0x6B 107. 'k' */ - _ACPI_LO, /* 0x6C 108. 'l' */ - _ACPI_LO, /* 0x6D 109. 'm' */ - _ACPI_LO, /* 0x6E 110. 'n' */ - _ACPI_LO, /* 0x6F 111. 'o' */ - _ACPI_LO, /* 0x70 112. 'p' */ - _ACPI_LO, /* 0x71 113. 'q' */ - _ACPI_LO, /* 0x72 114. 'r' */ - _ACPI_LO, /* 0x73 115. 's' */ - _ACPI_LO, /* 0x74 116. 't' */ - _ACPI_LO, /* 0x75 117. 'u' */ - _ACPI_LO, /* 0x76 118. 'v' */ - _ACPI_LO, /* 0x77 119. 'w' */ - _ACPI_LO, /* 0x78 120. 'x' */ - _ACPI_LO, /* 0x79 121. 'y' */ - _ACPI_LO, /* 0x7A 122. 'z' */ - _ACPI_PU, /* 0x7B 123. '{' */ - _ACPI_PU, /* 0x7C 124. '|' */ - _ACPI_PU, /* 0x7D 125. '}' */ - _ACPI_PU, /* 0x7E 126. '~' */ - _ACPI_CN, /* 0x7F 127. */ - - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80 to 0x8F */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90 to 0x9F */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xA0 to 0xAF */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xB0 to 0xBF */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xC0 to 0xCF */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xD0 to 0xDF */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xE0 to 0xEF */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* 0xF0 to 0x100 */ -}; - -#define IS_UPPER(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_UP)) -#define IS_LOWER(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO)) -#define IS_DIGIT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_DI)) -#define IS_SPACE(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_SP)) -#define IS_XDIGIT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_XD)) - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_to_upper - * - * PARAMETERS: - * - * RETURN: - * - * DESCRIPTION: Convert character to uppercase - * - ******************************************************************************/ - -u32 -acpi_cm_to_upper ( - u32 c) -{ - - return (IS_LOWER(c) ? ((c)-0x20) : (c)); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_to_lower - * - * PARAMETERS: - * - * RETURN: - * - * DESCRIPTION: Convert character to lowercase - * - ******************************************************************************/ - -u32 -acpi_cm_to_lower ( - u32 c) -{ - - return (IS_UPPER(c) ? ((c)+0x20) : (c)); -} - - -/******************************************************************************* - * - * FUNCTION: strupr - * - * PARAMETERS: Src_string - The source string to convert to - * - * RETURN: Src_string - * - * DESCRIPTION: Convert string to uppercase - * - ******************************************************************************/ - -NATIVE_CHAR * -acpi_cm_strupr ( - NATIVE_CHAR *src_string) -{ - NATIVE_CHAR *string; - - - /* Walk entire string, uppercasing the letters */ - - for (string = src_string; *string; ) { - *string = (char) acpi_cm_to_upper (*string); - string++; - } - - - return (src_string); -} - - -/******************************************************************************* - * - * FUNCTION: strstr - * - * PARAMETERS: String1 - - * String2 - * - * RETURN: - * - * DESCRIPTION: Checks if String2 occurs in String1. This is not really a - * full implementation of strstr, only sufficient for command - * matching - * - ******************************************************************************/ - -NATIVE_CHAR * -acpi_cm_strstr ( - NATIVE_CHAR *string1, - NATIVE_CHAR *string2) -{ - NATIVE_CHAR *string; - - - if (acpi_cm_strlen (string2) > acpi_cm_strlen (string1)) { - return (NULL); - } - - /* Walk entire string, comparing the letters */ - - for (string = string1; *string2; ) { - if (*string2 != *string) { - return (NULL); - } - - string2++; - string++; - } - - - return (string1); -} - - -/******************************************************************************* - * - * FUNCTION: strtoul - * - * 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. - * - ******************************************************************************/ - -u32 -acpi_cm_strtoul ( - const NATIVE_CHAR *string, - NATIVE_CHAR **terminator, - NATIVE_UINT base) -{ - u32 converted = 0; - u32 index; - u32 sign; - const NATIVE_CHAR *string_start; - u32 return_value = 0; - ACPI_STATUS status = AE_OK; - - - /* - * Save the value of the pointer to the buffer's first - * character, save the current errno value, and then - * skip over any white space in the buffer: - */ - string_start = string; - while (IS_SPACE (*string) || *string == '\t') { - ++string; - } - - /* - * The buffer may contain an optional plus or minus sign. - * If it does, then skip over it but remember what is was: - */ - if (*string == '-') { - sign = NEGATIVE; - ++string; - } - - else if (*string == '+') { - ++string; - sign = POSITIVE; - } - - else { - sign = POSITIVE; - } - - /* - * 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_cm_to_lower (*(++string)) == 'x') { - base = 16; - ++string; - } - - else { - base = 8; - } - } - - else { - base = 10; - } - } - - else if (base < 2 || base > 36) { - /* - * The specified Base parameter is not in the domain of - * this function: - */ - goto done; - } - - /* - * 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_cm_to_lower (*(++string)) == 'x') - { - string++; - } - - - /* - * Main loop: convert the string to an unsigned long: - */ - while (*string) { - if (IS_DIGIT (*string)) { - index = *string - '0'; - } - - else { - index = acpi_cm_to_upper (*string); - if (IS_UPPER (index)) { - index = index - 'A' + 10; - } - - else { - goto done; - } - } - - if (index >= base) { - goto done; - } - - /* - * Check to see if value is out of range: - */ - - if (return_value > ((ACPI_UINT32_MAX - (u32) index) / - (u32) base)) - { - status = AE_ERROR; - return_value = 0L; /* reset */ - } - - else { - return_value *= base; - return_value += index; - converted = 1; - } - - ++string; - } - -done: - /* - * If appropriate, update the caller's pointer to the next - * unconverted character in the buffer. - */ - if (terminator) { - if (converted == 0 && return_value == 0L && string != NULL) { - *terminator = (NATIVE_CHAR *) string_start; - } - - else { - *terminator = (NATIVE_CHAR *) string; - } - } - - if (status == AE_ERROR) { - return_value = ACPI_UINT32_MAX; - } - - /* - * If a minus sign was present, then "the conversion is negated": - */ - if (sign == NEGATIVE) { - return_value = (ACPI_UINT32_MAX - return_value) + 1; - } - - return (return_value); -} - -#endif /* ACPI_USE_SYSTEM_CLIBRARY */ - diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/common/cmcopy.c linux/drivers/acpi/common/cmcopy.c --- v2.4.5/linux/drivers/acpi/common/cmcopy.c Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/common/cmcopy.c Wed Dec 31 16:00:00 1969 @@ -1,708 +0,0 @@ -/****************************************************************************** - * - * Module Name: cmcopy - Internal to external object translation utilities - * $Revision: 66 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "acpi.h" -#include "acinterp.h" -#include "acnamesp.h" -#include "amlcode.h" - - -#define _COMPONENT MISCELLANEOUS - MODULE_NAME ("cmcopy") - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_copy_isimple_to_esimple - * - * PARAMETERS: *Internal_object - Pointer to the object we are examining - * *Buffer - Where the object is returned - * *Space_used - Where the data length is returned - * - * RETURN: Status - * - * DESCRIPTION: This function is called to place a simple object in a user - * buffer. - * - * The buffer is assumed to have sufficient space for the object. - * - ******************************************************************************/ - -static ACPI_STATUS -acpi_cm_copy_isimple_to_esimple ( - ACPI_OPERAND_OBJECT *internal_object, - ACPI_OBJECT *external_object, - u8 *data_space, - u32 *buffer_space_used) -{ - u32 length = 0; - ACPI_STATUS status = AE_OK; - - - /* - * Check for NULL object case (could be an uninitialized - * package element - */ - - if (!internal_object) { - *buffer_space_used = 0; - return (AE_OK); - } - - /* Always clear the external object */ - - MEMSET (external_object, 0, sizeof (ACPI_OBJECT)); - - /* - * In general, the external object will be the same type as - * the internal object - */ - - external_object->type = internal_object->common.type; - - /* However, only a limited number of external types are supported */ - - switch (internal_object->common.type) - { - - case ACPI_TYPE_STRING: - - length = internal_object->string.length + 1; - external_object->string.length = internal_object->string.length; - external_object->string.pointer = (NATIVE_CHAR *) data_space; - MEMCPY ((void *) data_space, (void *) internal_object->string.pointer, length); - break; - - - case ACPI_TYPE_BUFFER: - - length = internal_object->buffer.length; - external_object->buffer.length = internal_object->buffer.length; - external_object->buffer.pointer = data_space; - MEMCPY ((void *) data_space, (void *) internal_object->buffer.pointer, length); - break; - - - case ACPI_TYPE_INTEGER: - - external_object->integer.value= internal_object->integer.value; - break; - - - case INTERNAL_TYPE_REFERENCE: - - /* - * This is an object reference. Attempt to dereference it. - */ - - switch (internal_object->reference.op_code) - { - case AML_ZERO_OP: - external_object->type = ACPI_TYPE_INTEGER; - external_object->integer.value = 0; - break; - - case AML_ONE_OP: - external_object->type = ACPI_TYPE_INTEGER; - external_object->integer.value = 1; - break; - - case AML_ONES_OP: - external_object->type = ACPI_TYPE_INTEGER; - external_object->integer.value = ACPI_INTEGER_MAX; - break; - - case AML_NAMEPATH_OP: - /* - * This is a named reference, get the string. We already know that - * we have room for it, use max length - */ - length = MAX_STRING_LENGTH; - external_object->type = ACPI_TYPE_STRING; - external_object->string.pointer = (NATIVE_CHAR *) data_space; - status = acpi_ns_handle_to_pathname ((ACPI_HANDLE *) internal_object->reference.node, - &length, (char *) data_space); - break; - - default: - /* - * Use the object type of "Any" to indicate a reference - * to object containing a handle to an ACPI named object. - */ - external_object->type = ACPI_TYPE_ANY; - external_object->reference.handle = internal_object->reference.node; - break; - } - break; - - - case ACPI_TYPE_PROCESSOR: - - external_object->processor.proc_id = internal_object->processor.proc_id; - external_object->processor.pblk_address = internal_object->processor.address; - external_object->processor.pblk_length = internal_object->processor.length; - break; - - - case ACPI_TYPE_POWER: - - external_object->power_resource.system_level = - internal_object->power_resource.system_level; - - external_object->power_resource.resource_order = - internal_object->power_resource.resource_order; - break; - - - default: - /* - * There is no corresponding external object type - */ - return (AE_SUPPORT); - break; - } - - - *buffer_space_used = (u32) ROUND_UP_TO_NATIVE_WORD (length); - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_copy_ielement_to_eelement - * - * PARAMETERS: ACPI_PKG_CALLBACK - * - * RETURN: Status - * - * DESCRIPTION: Copy one package element to another package element - * - ******************************************************************************/ - -ACPI_STATUS -acpi_cm_copy_ielement_to_eelement ( - u8 object_type, - ACPI_OPERAND_OBJECT *source_object, - ACPI_GENERIC_STATE *state, - void *context) -{ - ACPI_STATUS status = AE_OK; - ACPI_PKG_INFO *info = (ACPI_PKG_INFO *) context; - u32 object_space; - u32 this_index; - ACPI_OBJECT *target_object; - - - this_index = state->pkg.index; - target_object = (ACPI_OBJECT *) - &((ACPI_OBJECT *)(state->pkg.dest_object))->package.elements[this_index]; - - - switch (object_type) - { - case 0: - - /* - * This is a simple or null object -- get the size - */ - - status = acpi_cm_copy_isimple_to_esimple (source_object, - target_object, info->free_space, &object_space); - if (ACPI_FAILURE (status)) { - return (status); - } - - break; - - case 1: - - /* - * Build the package object - */ - target_object->type = ACPI_TYPE_PACKAGE; - target_object->package.count = source_object->package.count; - target_object->package.elements = (ACPI_OBJECT *) info->free_space; - - /* - * Pass the new package object back to the package walk routine - */ - state->pkg.this_target_obj = target_object; - - /* - * Save space for the array of objects (Package elements) - * update the buffer length counter - */ - object_space = (u32) ROUND_UP_TO_NATIVE_WORD ( - target_object->package.count * sizeof (ACPI_OBJECT)); - break; - - default: - return (AE_BAD_PARAMETER); - } - - - info->free_space += object_space; - info->length += object_space; - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_copy_ipackage_to_epackage - * - * PARAMETERS: *Internal_object - Pointer to the object we are returning - * *Buffer - Where the object is returned - * *Space_used - Where the object length is returned - * - * RETURN: Status - * - * DESCRIPTION: This function is called to place a package object in a user - * buffer. A package object by definition contains other objects. - * - * The buffer is assumed to have sufficient space for the object. - * The caller must have verified the buffer length needed using the - * Acpi_cm_get_object_size function before calling this function. - * - ******************************************************************************/ - -static ACPI_STATUS -acpi_cm_copy_ipackage_to_epackage ( - ACPI_OPERAND_OBJECT *internal_object, - u8 *buffer, - u32 *space_used) -{ - ACPI_OBJECT *external_object; - ACPI_STATUS status; - ACPI_PKG_INFO info; - - - /* - * First package at head of the buffer - */ - external_object = (ACPI_OBJECT *) buffer; - - /* - * Free space begins right after the first package - */ - info.length = 0; - info.object_space = 0; - info.num_packages = 1; - info.free_space = buffer + ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT)); - - - external_object->type = internal_object->common.type; - external_object->package.count = internal_object->package.count; - external_object->package.elements = (ACPI_OBJECT *) info.free_space; - - - /* - * Build an array of ACPI_OBJECTS in the buffer - * and move the free space past it - */ - - info.free_space += external_object->package.count * - ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT)); - - - status = acpi_cm_walk_package_tree (internal_object, external_object, - acpi_cm_copy_ielement_to_eelement, &info); - - *space_used = info.length; - - return (status); - -} - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_copy_iobject_to_eobject - * - * PARAMETERS: *Internal_object - The internal object to be converted - * *Buffer_ptr - Where the object is returned - * - * RETURN: Status - * - * DESCRIPTION: This function is called to build an API object to be returned to - * the caller. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_cm_copy_iobject_to_eobject ( - ACPI_OPERAND_OBJECT *internal_object, - ACPI_BUFFER *ret_buffer) -{ - ACPI_STATUS status; - - - if (IS_THIS_OBJECT_TYPE (internal_object, ACPI_TYPE_PACKAGE)) { - /* - * Package object: Copy all subobjects (including - * nested packages) - */ - status = acpi_cm_copy_ipackage_to_epackage (internal_object, - ret_buffer->pointer, &ret_buffer->length); - } - - else { - /* - * Build a simple object (no nested objects) - */ - status = acpi_cm_copy_isimple_to_esimple (internal_object, - (ACPI_OBJECT *) ret_buffer->pointer, - ((u8 *) ret_buffer->pointer + - ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT))), - &ret_buffer->length); - /* - * build simple does not include the object size in the length - * so we add it in here - */ - ret_buffer->length += sizeof (ACPI_OBJECT); - } - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_copy_esimple_to_isimple - * - * PARAMETERS: *External_object - The external object to be converted - * *Internal_object - Where the internal object is returned - * - * RETURN: Status - * - * DESCRIPTION: This function copies an external object to an internal one. - * NOTE: Pointers can be copied, we don't need to copy data. - * (The pointers have to be valid in our address space no matter - * what we do with them!) - * - ******************************************************************************/ - -ACPI_STATUS -acpi_cm_copy_esimple_to_isimple ( - ACPI_OBJECT *external_object, - ACPI_OPERAND_OBJECT *internal_object) -{ - - - internal_object->common.type = (u8) external_object->type; - - switch (external_object->type) - { - - case ACPI_TYPE_STRING: - - internal_object->string.length = external_object->string.length; - internal_object->string.pointer = external_object->string.pointer; - break; - - - case ACPI_TYPE_BUFFER: - - internal_object->buffer.length = external_object->buffer.length; - internal_object->buffer.pointer = external_object->buffer.pointer; - break; - - - case ACPI_TYPE_INTEGER: - /* - * Number is included in the object itself - */ - internal_object->integer.value = external_object->integer.value; - break; - - - default: - return (AE_CTRL_RETURN_VALUE); - break; - } - - - return (AE_OK); -} - - -#ifdef ACPI_FUTURE_IMPLEMENTATION - -/* Code to convert packages that are parameters to control methods */ - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_copy_epackage_to_ipackage - * - * PARAMETERS: *Internal_object - Pointer to the object we are returning - * *Buffer - Where the object is returned - * *Space_used - Where the length of the object is returned - * - * RETURN: Status - the status of the call - * - * DESCRIPTION: This function is called to place a package object in a user - * buffer. A package object by definition contains other objects. - * - * The buffer is assumed to have sufficient space for the object. - * The caller must have verified the buffer length needed using the - * Acpi_cm_get_object_size function before calling this function. - * - ******************************************************************************/ - -static ACPI_STATUS -acpi_cm_copy_epackage_to_ipackage ( - ACPI_OPERAND_OBJECT *internal_object, - u8 *buffer, - u32 *space_used) -{ - u8 *free_space; - ACPI_OBJECT *external_object; - u32 length = 0; - u32 this_index; - u32 object_space = 0; - ACPI_OPERAND_OBJECT *this_internal_obj; - ACPI_OBJECT *this_external_obj; - - - /* - * First package at head of the buffer - */ - external_object = (ACPI_OBJECT *)buffer; - - /* - * Free space begins right after the first package - */ - free_space = buffer + sizeof(ACPI_OBJECT); - - - external_object->type = internal_object->common.type; - external_object->package.count = internal_object->package.count; - external_object->package.elements = (ACPI_OBJECT *)free_space; - - - /* - * Build an array of ACPI_OBJECTS in the buffer - * and move the free space past it - */ - - free_space += external_object->package.count * sizeof(ACPI_OBJECT); - - - /* Call Walk_package */ - -} - -#endif /* Future implementation */ - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_copy_eobject_to_iobject - * - * PARAMETERS: *Internal_object - The external object to be converted - * *Buffer_ptr - Where the internal object is returned - * - * RETURN: Status - the status of the call - * - * DESCRIPTION: Converts an external object to an internal object. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_cm_copy_eobject_to_iobject ( - ACPI_OBJECT *external_object, - ACPI_OPERAND_OBJECT *internal_object) -{ - ACPI_STATUS status; - - - if (external_object->type == ACPI_TYPE_PACKAGE) { - /* - * Package objects contain other objects (which can be objects) - * buildpackage does it all - * - * TBD: Package conversion must be completed and tested - * NOTE: this code converts packages as input parameters to - * control methods only. This is a very, very rare case. - */ -/* - Status = Acpi_cm_copy_epackage_to_ipackage(Internal_object, - Ret_buffer->Pointer, - &Ret_buffer->Length); -*/ - return (AE_NOT_IMPLEMENTED); - } - - else { - /* - * Build a simple object (no nested objects) - */ - status = acpi_cm_copy_esimple_to_isimple (external_object, internal_object); - /* - * build simple does not include the object size in the length - * so we add it in here - */ - } - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_copy_ielement_to_ielement - * - * PARAMETERS: ACPI_PKG_CALLBACK - * - * RETURN: Status - the status of the call - * - * DESCRIPTION: Copy one package element to another package element - * - ******************************************************************************/ - -ACPI_STATUS -acpi_cm_copy_ielement_to_ielement ( - u8 object_type, - ACPI_OPERAND_OBJECT *source_object, - ACPI_GENERIC_STATE *state, - void *context) -{ - ACPI_STATUS status = AE_OK; - u32 this_index; - ACPI_OPERAND_OBJECT **this_target_ptr; - ACPI_OPERAND_OBJECT *target_object; - - - this_index = state->pkg.index; - this_target_ptr = (ACPI_OPERAND_OBJECT **) - &state->pkg.dest_object->package.elements[this_index]; - - switch (object_type) - { - case 0: - - /* - * This is a simple object, just copy it - */ - target_object = acpi_cm_create_internal_object (source_object->common.type); - if (!target_object) { - return (AE_NO_MEMORY); - } - - status = acpi_aml_store_object_to_object (source_object, target_object, - (ACPI_WALK_STATE *) context); - if (ACPI_FAILURE (status)) { - return (status); - } - - *this_target_ptr = target_object; - break; - - - case 1: - /* - * This object is a package - go down another nesting level - * Create and build the package object - */ - target_object = acpi_cm_create_internal_object (ACPI_TYPE_PACKAGE); - if (!target_object) { - /* TBD: must delete package created up to this point */ - - return (AE_NO_MEMORY); - } - - target_object->package.count = source_object->package.count; - - /* - * Pass the new package object back to the package walk routine - */ - state->pkg.this_target_obj = target_object; - - /* - * Store the object pointer in the parent package object - */ - *this_target_ptr = target_object; - break; - - default: - return (AE_BAD_PARAMETER); - } - - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_copy_ipackage_to_ipackage - * - * PARAMETERS: *Source_obj - Pointer to the source package object - * *Dest_obj - Where the internal object is returned - * - * RETURN: Status - the status of the call - * - * DESCRIPTION: This function is called to copy an internal package object - * into another internal package object. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_cm_copy_ipackage_to_ipackage ( - ACPI_OPERAND_OBJECT *source_obj, - ACPI_OPERAND_OBJECT *dest_obj, - ACPI_WALK_STATE *walk_state) -{ - ACPI_STATUS status = AE_OK; - - - dest_obj->common.type = source_obj->common.type; - dest_obj->package.count = source_obj->package.count; - - - /* - * Create the object array and walk the source package tree - */ - - dest_obj->package.elements = acpi_cm_callocate ((source_obj->package.count + 1) * - sizeof (void *)); - dest_obj->package.next_element = dest_obj->package.elements; - - if (!dest_obj->package.elements) { - REPORT_ERROR ( - ("Aml_build_copy_internal_package_object: Package allocation failure\n")); - return (AE_NO_MEMORY); - } - - - status = acpi_cm_walk_package_tree (source_obj, dest_obj, - acpi_cm_copy_ielement_to_ielement, walk_state); - - return (status); -} - diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/common/cmdebug.c linux/drivers/acpi/common/cmdebug.c --- v2.4.5/linux/drivers/acpi/common/cmdebug.c Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/common/cmdebug.c Wed Dec 31 16:00:00 1969 @@ -1,559 +0,0 @@ -/****************************************************************************** - * - * Module Name: cmdebug - Debug print routines - * $Revision: 64 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "acpi.h" - -#define _COMPONENT MISCELLANEOUS - MODULE_NAME ("cmdebug") - - -/***************************************************************************** - * - * FUNCTION: Get/Set debug level - * - * DESCRIPTION: Get or set value of the debug flag - * - * These are used to allow user's to get/set the debug level - * - ****************************************************************************/ - - -u32 -get_debug_level (void) -{ - - return (acpi_dbg_level); -} - -void -set_debug_level ( - u32 new_debug_level) -{ - - acpi_dbg_level = new_debug_level; -} - - -/***************************************************************************** - * - * FUNCTION: Function_trace - * - * PARAMETERS: Module_name - Caller's module name (for error output) - * Line_number - Caller's line number (for error output) - * Component_id - Caller's component ID (for error output) - * Function_name - Name of Caller's function - * - * RETURN: None - * - * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is - * set in Debug_level - * - ****************************************************************************/ - -void -function_trace ( - NATIVE_CHAR *module_name, - u32 line_number, - u32 component_id, - NATIVE_CHAR *function_name) -{ - - acpi_gbl_nesting_level++; - - debug_print (module_name, line_number, component_id, - TRACE_FUNCTIONS, - " %2.2ld Entered Function: %s\n", - acpi_gbl_nesting_level, function_name); -} - - -/***************************************************************************** - * - * FUNCTION: Function_trace_ptr - * - * PARAMETERS: Module_name - Caller's module name (for error output) - * Line_number - Caller's line number (for error output) - * Component_id - Caller's component ID (for error output) - * Function_name - Name of Caller's function - * Pointer - Pointer to display - * - * RETURN: None - * - * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is - * set in Debug_level - * - ****************************************************************************/ - -void -function_trace_ptr ( - NATIVE_CHAR *module_name, - u32 line_number, - u32 component_id, - NATIVE_CHAR *function_name, - void *pointer) -{ - - acpi_gbl_nesting_level++; - debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS, - " %2.2ld Entered Function: %s, %p\n", - acpi_gbl_nesting_level, function_name, pointer); -} - - -/***************************************************************************** - * - * FUNCTION: Function_trace_str - * - * PARAMETERS: Module_name - Caller's module name (for error output) - * Line_number - Caller's line number (for error output) - * Component_id - Caller's component ID (for error output) - * Function_name - Name of Caller's function - * String - Additional string to display - * - * RETURN: None - * - * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is - * set in Debug_level - * - ****************************************************************************/ - -void -function_trace_str ( - NATIVE_CHAR *module_name, - u32 line_number, - u32 component_id, - NATIVE_CHAR *function_name, - NATIVE_CHAR *string) -{ - - acpi_gbl_nesting_level++; - debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS, - " %2.2ld Entered Function: %s, %s\n", - acpi_gbl_nesting_level, function_name, string); -} - - -/***************************************************************************** - * - * FUNCTION: Function_trace_u32 - * - * PARAMETERS: Module_name - Caller's module name (for error output) - * Line_number - Caller's line number (for error output) - * Component_id - Caller's component ID (for error output) - * Function_name - Name of Caller's function - * Integer - Integer to display - * - * RETURN: None - * - * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is - * set in Debug_level - * - ****************************************************************************/ - -void -function_trace_u32 ( - NATIVE_CHAR *module_name, - u32 line_number, - u32 component_id, - NATIVE_CHAR *function_name, - u32 integer) -{ - - acpi_gbl_nesting_level++; - debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS, - " %2.2ld Entered Function: %s, %lX\n", - acpi_gbl_nesting_level, function_name, integer); -} - - -/***************************************************************************** - * - * FUNCTION: Function_exit - * - * PARAMETERS: Module_name - Caller's module name (for error output) - * Line_number - Caller's line number (for error output) - * Component_id - Caller's component ID (for error output) - * Function_name - Name of Caller's function - * - * RETURN: None - * - * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is - * set in Debug_level - * - ****************************************************************************/ - -void -function_exit ( - NATIVE_CHAR *module_name, - u32 line_number, - u32 component_id, - NATIVE_CHAR *function_name) -{ - - debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS, - " %2.2ld Exiting Function: %s\n", - acpi_gbl_nesting_level, function_name); - - acpi_gbl_nesting_level--; -} - - -/***************************************************************************** - * - * FUNCTION: Function_status_exit - * - * PARAMETERS: Module_name - Caller's module name (for error output) - * Line_number - Caller's line number (for error output) - * Component_id - Caller's component ID (for error output) - * Function_name - Name of Caller's function - * Status - Exit status code - * - * RETURN: None - * - * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is - * set in Debug_level. Prints exit status also. - * - ****************************************************************************/ - -void -function_status_exit ( - NATIVE_CHAR *module_name, - u32 line_number, - u32 component_id, - NATIVE_CHAR *function_name, - ACPI_STATUS status) -{ - - debug_print (module_name, line_number, component_id, - TRACE_FUNCTIONS, - " %2.2ld Exiting Function: %s, %s\n", - acpi_gbl_nesting_level, - function_name, - acpi_cm_format_exception (status)); - - acpi_gbl_nesting_level--; -} - - -/***************************************************************************** - * - * FUNCTION: Function_value_exit - * - * PARAMETERS: Module_name - Caller's module name (for error output) - * Line_number - Caller's line number (for error output) - * Component_id - Caller's component ID (for error output) - * Function_name - Name of Caller's function - * Value - Value to be printed with exit msg - * - * RETURN: None - * - * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is - * set in Debug_level. Prints exit value also. - * - ****************************************************************************/ - -void -function_value_exit ( - NATIVE_CHAR *module_name, - u32 line_number, - u32 component_id, - NATIVE_CHAR *function_name, - ACPI_INTEGER value) -{ - - debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS, - " %2.2ld Exiting Function: %s, %X\n", - acpi_gbl_nesting_level, function_name, value); - - acpi_gbl_nesting_level--; -} - - -/***************************************************************************** - * - * FUNCTION: Function_ptr_exit - * - * PARAMETERS: Module_name - Caller's module name (for error output) - * Line_number - Caller's line number (for error output) - * Component_id - Caller's component ID (for error output) - * Function_name - Name of Caller's function - * Value - Value to be printed with exit msg - * - * RETURN: None - * - * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is - * set in Debug_level. Prints exit value also. - * - ****************************************************************************/ - -void -function_ptr_exit ( - NATIVE_CHAR *module_name, - u32 line_number, - u32 component_id, - NATIVE_CHAR *function_name, - u8 *ptr) -{ - - debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS, - " %2.2ld Exiting Function: %s, %p\n", - acpi_gbl_nesting_level, function_name, ptr); - - acpi_gbl_nesting_level--; -} - - -/***************************************************************************** - * - * FUNCTION: Debug_print - * - * PARAMETERS: Module_name - Caller's module name (for error output) - * Line_number - Caller's line number (for error output) - * Component_id - Caller's component ID (for error output) - * Print_level - Requested debug print level - * Format - Printf format field - * ... - Optional printf arguments - * - * RETURN: None - * - * DESCRIPTION: Print error message with prefix consisting of the module name, - * line number, and component ID. - * - ****************************************************************************/ - -void -debug_print ( - NATIVE_CHAR *module_name, - u32 line_number, - u32 component_id, - u32 print_level, - NATIVE_CHAR *format, - ...) -{ - va_list args; - - - /* Both the level and the component must be enabled */ - - if ((print_level & acpi_dbg_level) && - (component_id & acpi_dbg_layer)) - { - va_start (args, format); - - acpi_os_printf ("%8s-%04d: ", module_name, line_number); - acpi_os_vprintf (format, args); - } -} - - -/***************************************************************************** - * - * FUNCTION: Debug_print_prefix - * - * PARAMETERS: Module_name - Caller's module name (for error output) - * Line_number - Caller's line number (for error output) - * Component_id - Caller's component ID (for error output) - * - * RETURN: None - * - * DESCRIPTION: Print the prefix part of an error message, consisting of the - * module name, and line number - * - ****************************************************************************/ - -void -debug_print_prefix ( - NATIVE_CHAR *module_name, - u32 line_number) -{ - - - acpi_os_printf ("%8s-%04d: ", module_name, line_number); -} - - -/***************************************************************************** - * - * FUNCTION: Debug_print_raw - * - * PARAMETERS: Format - Printf format field - * ... - Optional printf arguments - * - * RETURN: None - * - * DESCRIPTION: Print error message -- without module/line indentifiers - * - ****************************************************************************/ - -void -debug_print_raw ( - NATIVE_CHAR *format, - ...) -{ - va_list args; - - - va_start (args, format); - - acpi_os_vprintf (format, args); - - va_end (args); -} - - -/***************************************************************************** - * - * FUNCTION: Acpi_cm_dump_buffer - * - * PARAMETERS: Buffer - Buffer to dump - * Count - Amount to dump, in bytes - * Component_iD - Caller's component ID - * - * RETURN: None - * - * DESCRIPTION: Generic dump buffer in both hex and ascii. - * - ****************************************************************************/ - -void -acpi_cm_dump_buffer ( - u8 *buffer, - u32 count, - u32 display, - u32 component_id) -{ - u32 i = 0; - u32 j; - u32 temp32; - u8 buf_char; - - - /* Only dump the buffer if tracing is enabled */ - - if (!((TRACE_TABLES & acpi_dbg_level) && - (component_id & acpi_dbg_layer))) - { - return; - } - - - /* - * Nasty little dump buffer routine! - */ - while (i < count) { - /* Print current offset */ - - acpi_os_printf ("%05X ", i); - - - /* Print 16 hex chars */ - - for (j = 0; j < 16;) { - if (i + j >= count) { - acpi_os_printf ("\n"); - return; - } - - /* Make sure that the s8 doesn't get sign-extended! */ - - switch (display) - { - /* Default is BYTE display */ - - default: - - acpi_os_printf ("%02X ", - *((u8 *) &buffer[i + j])); - j += 1; - break; - - - case DB_WORD_DISPLAY: - - MOVE_UNALIGNED16_TO_32 (&temp32, - &buffer[i + j]); - acpi_os_printf ("%04X ", temp32); - j += 2; - break; - - - case DB_DWORD_DISPLAY: - - MOVE_UNALIGNED32_TO_32 (&temp32, - &buffer[i + j]); - acpi_os_printf ("%08X ", temp32); - j += 4; - break; - - - case DB_QWORD_DISPLAY: - - MOVE_UNALIGNED32_TO_32 (&temp32, - &buffer[i + j]); - acpi_os_printf ("%08X", temp32); - - MOVE_UNALIGNED32_TO_32 (&temp32, - &buffer[i + j + 4]); - acpi_os_printf ("%08X ", temp32); - j += 8; - break; - } - } - - - /* - * 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"); - return; - } - - buf_char = buffer[i + j]; - if ((buf_char > 0x1F && buf_char < 0x2E) || - (buf_char > 0x2F && buf_char < 0x61) || - (buf_char > 0x60 && buf_char < 0x7F)) - { - acpi_os_printf ("%c", buf_char); - } - else { - acpi_os_printf ("."); - } - } - - /* Done with that line. */ - - acpi_os_printf ("\n"); - i += 16; - } - - return; -} - - diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/common/cmdelete.c linux/drivers/acpi/common/cmdelete.c --- v2.4.5/linux/drivers/acpi/common/cmdelete.c Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/common/cmdelete.c Wed Dec 31 16:00:00 1969 @@ -1,591 +0,0 @@ -/******************************************************************************* - * - * Module Name: cmdelete - object deletion and reference count utilities - * $Revision: 62 $ - * - ******************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "acpi.h" -#include "acinterp.h" -#include "acnamesp.h" -#include "actables.h" -#include "acparser.h" - -#define _COMPONENT MISCELLANEOUS - MODULE_NAME ("cmdelete") - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_delete_internal_obj - * - * PARAMETERS: *Object - Pointer to the list to be deleted - * - * RETURN: None - * - * DESCRIPTION: Low level object deletion, after reference counts have been - * updated (All reference counts, including sub-objects!) - * - ******************************************************************************/ - -void -acpi_cm_delete_internal_obj ( - ACPI_OPERAND_OBJECT *object) -{ - void *obj_pointer = NULL; - ACPI_OPERAND_OBJECT *handler_desc; - - - if (!object) { - return; - } - - /* - * Must delete or free any pointers within the object that are not - * actual ACPI objects (for example, a raw buffer pointer). - */ - - switch (object->common.type) - { - - case ACPI_TYPE_STRING: - - /* Free the actual string buffer */ - - obj_pointer = object->string.pointer; - break; - - - case ACPI_TYPE_BUFFER: - - /* Free the actual buffer */ - - obj_pointer = object->buffer.pointer; - break; - - - case ACPI_TYPE_PACKAGE: - - /* - * Elements of the package are not handled here, they are deleted - * separately - */ - - /* Free the (variable length) element pointer array */ - - obj_pointer = object->package.elements; - break; - - - case ACPI_TYPE_MUTEX: - - acpi_os_delete_semaphore (object->mutex.semaphore); - break; - - - case ACPI_TYPE_EVENT: - - acpi_os_delete_semaphore (object->event.semaphore); - object->event.semaphore = NULL; - break; - - - case ACPI_TYPE_METHOD: - - /* Delete the method semaphore if it exists */ - - if (object->method.semaphore) { - acpi_os_delete_semaphore (object->method.semaphore); - object->method.semaphore = NULL; - } - - break; - - - case ACPI_TYPE_REGION: - - - if (object->region.extra) { - /* - * Free the Region_context if and only if the handler is one of the - * default handlers -- and therefore, we created the context object - * locally, it was not created by an external caller. - */ - handler_desc = object->region.addr_handler; - if ((handler_desc) && - (handler_desc->addr_handler.hflags == ADDR_HANDLER_DEFAULT_INSTALLED)) - { - obj_pointer = object->region.extra->extra.region_context; - } - - /* Now we can free the Extra object */ - - acpi_cm_delete_object_desc (object->region.extra); - } - break; - - - case ACPI_TYPE_FIELD_UNIT: - - if (object->field_unit.extra) { - acpi_cm_delete_object_desc (object->field_unit.extra); - } - break; - - default: - break; - } - - - /* - * Delete any allocated memory found above - */ - - if (obj_pointer) { - if (!acpi_tb_system_table_pointer (obj_pointer)) { - acpi_cm_free (obj_pointer); - } - } - - - /* Only delete the object if it was dynamically allocated */ - - - if (!(object->common.flags & AOPOBJ_STATIC_ALLOCATION)) { - acpi_cm_delete_object_desc (object); - - } - - return; -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_delete_internal_object_list - * - * PARAMETERS: *Obj_list - Pointer to the list to be deleted - * - * RETURN: Status - the status of the call - * - * DESCRIPTION: This function deletes an internal object list, including both - * simple objects and package objects - * - ******************************************************************************/ - -ACPI_STATUS -acpi_cm_delete_internal_object_list ( - ACPI_OPERAND_OBJECT **obj_list) -{ - ACPI_OPERAND_OBJECT **internal_obj; - - - /* Walk the null-terminated internal list */ - - for (internal_obj = obj_list; *internal_obj; internal_obj++) { - /* - * Check for a package - * Simple objects are simply stored in the array and do not - * need to be deleted separately. - */ - - if (IS_THIS_OBJECT_TYPE ((*internal_obj), ACPI_TYPE_PACKAGE)) { - /* Delete the package */ - - /* - * TBD: [Investigate] This might not be the right thing to do, - * depending on how the internal package object was allocated!!! - */ - acpi_cm_delete_internal_obj (*internal_obj); - } - - } - - /* Free the combined parameter pointer list and object array */ - - acpi_cm_free (obj_list); - - return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_update_ref_count - * - * PARAMETERS: *Object - Object whose ref count is to be updated - * Action - What to do - * - * RETURN: New ref count - * - * DESCRIPTION: Modify the ref count and return it. - * - ******************************************************************************/ - -static void -acpi_cm_update_ref_count ( - ACPI_OPERAND_OBJECT *object, - u32 action) -{ - u16 count; - u16 new_count; - - - if (!object) { - return; - } - - - count = object->common.reference_count; - new_count = count; - - /* - * Reference count action (increment, decrement, or force delete) - */ - - switch (action) - { - - case REF_INCREMENT: - - new_count++; - object->common.reference_count = new_count; - - break; - - - case REF_DECREMENT: - - if (count < 1) { - new_count = 0; - } - - else { - new_count--; - - } - - - object->common.reference_count = new_count; - if (new_count == 0) { - acpi_cm_delete_internal_obj (object); - } - - break; - - - case REF_FORCE_DELETE: - - new_count = 0; - object->common.reference_count = new_count; - acpi_cm_delete_internal_obj (object); - break; - - - default: - - break; - } - - - /* - * Sanity check the reference count, for debug purposes only. - * (A deleted object will have a huge reference count) - */ - - - return; -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_update_object_reference - * - * PARAMETERS: *Object - Increment ref count for this object - * and all sub-objects - * Action - Either REF_INCREMENT or REF_DECREMENT or - * REF_FORCE_DELETE - * - * RETURN: Status - * - * DESCRIPTION: Increment the object reference count - * - * Object references are incremented when: - * 1) An object is attached to a Node (namespace object) - * 2) An object is copied (all subobjects must be incremented) - * - * Object references are decremented when: - * 1) An object is detached from an Node - * - ******************************************************************************/ - -ACPI_STATUS -acpi_cm_update_object_reference ( - ACPI_OPERAND_OBJECT *object, - u16 action) -{ - ACPI_STATUS status; - u32 i; - ACPI_OPERAND_OBJECT *next; - ACPI_OPERAND_OBJECT *new; - ACPI_GENERIC_STATE *state_list = NULL; - ACPI_GENERIC_STATE *state; - - - /* Ignore a null object ptr */ - - if (!object) { - return (AE_OK); - } - - - /* - * Make sure that this isn't a namespace handle or an AML pointer - */ - - if (VALID_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_NAMED)) { - return (AE_OK); - } - - if (acpi_tb_system_table_pointer (object)) { - return (AE_OK); - } - - - state = acpi_cm_create_update_state (object, action); - - while (state) { - - object = state->update.object; - action = state->update.value; - acpi_cm_delete_generic_state (state); - - /* - * All sub-objects must have their reference count incremented also. - * Different object types have different subobjects. - */ - switch (object->common.type) - { - - case ACPI_TYPE_DEVICE: - - status = acpi_cm_create_update_state_and_push (object->device.addr_handler, - action, &state_list); - if (ACPI_FAILURE (status)) { - return (status); - } - - acpi_cm_update_ref_count (object->device.sys_handler, action); - acpi_cm_update_ref_count (object->device.drv_handler, action); - break; - - - case INTERNAL_TYPE_ADDRESS_HANDLER: - - /* Must walk list of address handlers */ - - next = object->addr_handler.next; - while (next) { - new = next->addr_handler.next; - acpi_cm_update_ref_count (next, action); - - next = new; - } - break; - - - case ACPI_TYPE_PACKAGE: - - /* - * We must update all the sub-objects of the package - * (Each of whom may have their own sub-objects, etc. - */ - for (i = 0; i < object->package.count; i++) { - /* - * Push each element onto the stack for later processing. - * Note: There can be null elements within the package, - * these are simply ignored - */ - - status = acpi_cm_create_update_state_and_push ( - object->package.elements[i], action, &state_list); - if (ACPI_FAILURE (status)) { - return (status); - } - } - break; - - - case ACPI_TYPE_FIELD_UNIT: - - status = acpi_cm_create_update_state_and_push ( - object->field_unit.container, action, &state_list); - - if (ACPI_FAILURE (status)) { - return (status); - } - break; - - - case INTERNAL_TYPE_DEF_FIELD: - - status = acpi_cm_create_update_state_and_push ( - object->field.container, action, &state_list); - if (ACPI_FAILURE (status)) { - return (status); - } - break; - - - case INTERNAL_TYPE_BANK_FIELD: - - status = acpi_cm_create_update_state_and_push ( - object->bank_field.bank_select, action, &state_list); - if (ACPI_FAILURE (status)) { - return (status); - } - - status = acpi_cm_create_update_state_and_push ( - object->bank_field.container, action, &state_list); - if (ACPI_FAILURE (status)) { - return (status); - } - break; - - - case ACPI_TYPE_REGION: - - /* TBD: [Investigate] - Acpi_cm_update_ref_count (Object->Region.Addr_handler, Action); - */ -/* - Status = - Acpi_cm_create_update_state_and_push (Object->Region.Addr_handler, - Action, &State_list); - if (ACPI_FAILURE (Status)) { - return (Status); - } -*/ - break; - - - case INTERNAL_TYPE_REFERENCE: - - break; - } - - - /* - * Now we can update the count in the main object. This can only - * happen after we update the sub-objects in case this causes the - * main object to be deleted. - */ - - acpi_cm_update_ref_count (object, action); - - - /* Move on to the next object to be updated */ - - state = acpi_cm_pop_generic_state (&state_list); - } - - - return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_add_reference - * - * PARAMETERS: *Object - Object whose reference count is to be - * incremented - * - * RETURN: None - * - * DESCRIPTION: Add one reference to an ACPI object - * - ******************************************************************************/ - -void -acpi_cm_add_reference ( - ACPI_OPERAND_OBJECT *object) -{ - - - /* - * Ensure that we have a valid object - */ - - if (!acpi_cm_valid_internal_object (object)) { - return; - } - - /* - * We have a valid ACPI internal object, now increment the reference count - */ - - acpi_cm_update_object_reference (object, REF_INCREMENT); - - return; -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_remove_reference - * - * PARAMETERS: *Object - Object whose ref count will be decremented - * - * RETURN: None - * - * DESCRIPTION: Decrement the reference count of an ACPI internal object - * - ******************************************************************************/ - -void -acpi_cm_remove_reference ( - ACPI_OPERAND_OBJECT *object) -{ - - - /* - * Ensure that we have a valid object - */ - - if (!acpi_cm_valid_internal_object (object)) { - return; - } - - /* - * Decrement the reference count, and only actually delete the object - * if the reference count becomes 0. (Must also decrement the ref count - * of all subobjects!) - */ - - acpi_cm_update_object_reference (object, REF_DECREMENT); - - return; -} - - diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/common/cmeval.c linux/drivers/acpi/common/cmeval.c --- v2.4.5/linux/drivers/acpi/common/cmeval.c Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/common/cmeval.c Wed Dec 31 16:00:00 1969 @@ -1,308 +0,0 @@ -/****************************************************************************** - * - * Module Name: cmeval - Object evaluation - * $Revision: 21 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "acpi.h" -#include "acnamesp.h" -#include "acinterp.h" - - -#define _COMPONENT MISCELLANEOUS - MODULE_NAME ("cmeval") - - -/**************************************************************************** - * - * FUNCTION: Acpi_cm_evaluate_numeric_object - * - * PARAMETERS: *Object_name - Object name to be evaluated - * Device_node - Node for the device - * *Address - Where the value is returned - * - * RETURN: Status - * - * DESCRIPTION: evaluates a numeric namespace object for a selected device - * and stores results in *Address. - * - * NOTE: Internal function, no parameter validation - * - ***************************************************************************/ - -ACPI_STATUS -acpi_cm_evaluate_numeric_object ( - NATIVE_CHAR *object_name, - ACPI_NAMESPACE_NODE *device_node, - ACPI_INTEGER *address) -{ - ACPI_OPERAND_OBJECT *obj_desc; - ACPI_STATUS status; - - - /* Execute the method */ - - status = acpi_ns_evaluate_relative (device_node, object_name, NULL, &obj_desc); - if (ACPI_FAILURE (status)) { - - return (status); - } - - - /* Did we get a return object? */ - - if (!obj_desc) { - return (AE_TYPE); - } - - /* Is the return object of the correct type? */ - - if (obj_desc->common.type != ACPI_TYPE_INTEGER) { - status = AE_TYPE; - } - else { - /* - * Since the structure is a union, setting any field will set all - * of the variables in the union - */ - *address = obj_desc->integer.value; - } - - /* On exit, we must delete the return object */ - - acpi_cm_remove_reference (obj_desc); - - return (status); -} - - -/**************************************************************************** - * - * FUNCTION: Acpi_cm_execute_HID - * - * PARAMETERS: Device_node - Node for the device - * *Hid - Where the HID is returned - * - * RETURN: Status - * - * DESCRIPTION: Executes the _HID control method that returns the hardware - * ID of the device. - * - * NOTE: Internal function, no parameter validation - * - ***************************************************************************/ - -ACPI_STATUS -acpi_cm_execute_HID ( - ACPI_NAMESPACE_NODE *device_node, - DEVICE_ID *hid) -{ - ACPI_OPERAND_OBJECT *obj_desc; - ACPI_STATUS status; - - - /* Execute the method */ - - status = acpi_ns_evaluate_relative (device_node, - METHOD_NAME__HID, NULL, &obj_desc); - if (ACPI_FAILURE (status)) { - - - return (status); - } - - /* Did we get a return object? */ - - if (!obj_desc) { - return (AE_TYPE); - } - - /* - * A _HID can return either a Number (32 bit compressed EISA ID) or - * a string - */ - - if ((obj_desc->common.type != ACPI_TYPE_INTEGER) && - (obj_desc->common.type != ACPI_TYPE_STRING)) - { - status = AE_TYPE; - } - - else { - if (obj_desc->common.type == ACPI_TYPE_INTEGER) { - /* Convert the Numeric HID to string */ - - acpi_aml_eisa_id_to_string ((u32) obj_desc->integer.value, hid->buffer); - } - - else { - /* Copy the String HID from the returned object */ - - STRNCPY(hid->buffer, obj_desc->string.pointer, sizeof(hid->buffer)); - } - } - - - /* On exit, we must delete the return object */ - - acpi_cm_remove_reference (obj_desc); - - return (status); -} - - -/**************************************************************************** - * - * FUNCTION: Acpi_cm_execute_UID - * - * PARAMETERS: Device_node - Node for the device - * *Uid - Where the UID is returned - * - * RETURN: Status - * - * DESCRIPTION: Executes the _UID control method that returns the hardware - * ID of the device. - * - * NOTE: Internal function, no parameter validation - * - ***************************************************************************/ - -ACPI_STATUS -acpi_cm_execute_UID ( - ACPI_NAMESPACE_NODE *device_node, - DEVICE_ID *uid) -{ - ACPI_OPERAND_OBJECT *obj_desc; - ACPI_STATUS status; - - - /* Execute the method */ - - status = acpi_ns_evaluate_relative (device_node, - METHOD_NAME__UID, NULL, &obj_desc); - if (ACPI_FAILURE (status)) { - - - return (status); - } - - /* Did we get a return object? */ - - if (!obj_desc) { - return (AE_TYPE); - } - - /* - * A _UID can return either a Number (32 bit compressed EISA ID) or - * a string - */ - - if ((obj_desc->common.type != ACPI_TYPE_INTEGER) && - (obj_desc->common.type != ACPI_TYPE_STRING)) - { - status = AE_TYPE; - } - - else { - if (obj_desc->common.type == ACPI_TYPE_INTEGER) { - /* Convert the Numeric UID to string */ - - acpi_aml_unsigned_integer_to_string (obj_desc->integer.value, uid->buffer); - } - - else { - /* Copy the String UID from the returned object */ - - STRNCPY(uid->buffer, obj_desc->string.pointer, sizeof(uid->buffer)); - } - } - - - /* On exit, we must delete the return object */ - - acpi_cm_remove_reference (obj_desc); - - return (status); -} - -/**************************************************************************** - * - * FUNCTION: Acpi_cm_execute_STA - * - * PARAMETERS: Device_node - Node for the device - * *Flags - Where the status flags are returned - * - * RETURN: Status - * - * DESCRIPTION: Executes _STA for selected device and stores results in - * *Flags. - * - * NOTE: Internal function, no parameter validation - * - ***************************************************************************/ - -ACPI_STATUS -acpi_cm_execute_STA ( - ACPI_NAMESPACE_NODE *device_node, - u32 *flags) -{ - ACPI_OPERAND_OBJECT *obj_desc; - ACPI_STATUS status; - - - /* Execute the method */ - - status = acpi_ns_evaluate_relative (device_node, - METHOD_NAME__STA, NULL, &obj_desc); - if (AE_NOT_FOUND == status) { - *flags = 0x0F; - status = AE_OK; - } - - - else /* success */ { - /* Did we get a return object? */ - - if (!obj_desc) { - return (AE_TYPE); - } - - /* Is the return object of the correct type? */ - - if (obj_desc->common.type != ACPI_TYPE_INTEGER) { - status = AE_TYPE; - } - - else { - /* Extract the status flags */ - - *flags = (u32) obj_desc->integer.value; - } - - /* On exit, we must delete the return object */ - - acpi_cm_remove_reference (obj_desc); - } - - return (status); -} diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/common/cmglobal.c linux/drivers/acpi/common/cmglobal.c --- v2.4.5/linux/drivers/acpi/common/cmglobal.c Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/common/cmglobal.c Wed Dec 31 16:00:00 1969 @@ -1,472 +0,0 @@ -/****************************************************************************** - * - * Module Name: cmglobal - Global variables for the ACPI subsystem - * $Revision: 116 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 DEFINE_ACPI_GLOBALS - -#include "acpi.h" -#include "acevents.h" -#include "acnamesp.h" -#include "acinterp.h" -#include "amlcode.h" - - -#define _COMPONENT MISCELLANEOUS - MODULE_NAME ("cmglobal") - - -/****************************************************************************** - * - * Static global variable initialization. - * - ******************************************************************************/ - -/* - * We want the debug switches statically initialized so they - * are already set when the debugger is entered. - */ - -/* Debug switch - level and trace mask */ - -u32 acpi_dbg_level = NORMAL_DEFAULT; - -/* Debug switch - layer (component) mask */ - -u32 acpi_dbg_layer = COMPONENT_DEFAULT; -u32 acpi_gbl_nesting_level = 0; - - -/* Debugger globals */ - -u8 acpi_gbl_db_terminate_threads = FALSE; -u8 acpi_gbl_method_executing = FALSE; - -/* System flags */ - -u32 acpi_gbl_system_flags = 0; -u32 acpi_gbl_startup_flags = 0; - -/* System starts unitialized! */ -u8 acpi_gbl_shutdown = TRUE; - - -u8 acpi_gbl_decode_to8bit [8] = {1,2,4,8,16,32,64,128}; - - -/****************************************************************************** - * - * Namespace globals - * - ******************************************************************************/ - - -/* - * Names built-in to the interpreter - * - * Initial values are currently supported only for types String and Number. - * To avoid type punning, both are specified as strings in this table. - */ - -PREDEFINED_NAMES acpi_gbl_pre_defined_names[] = -{ - {"_GPE", INTERNAL_TYPE_DEF_ANY}, - {"_PR_", INTERNAL_TYPE_DEF_ANY}, - {"_SB_", INTERNAL_TYPE_DEF_ANY}, - {"_SI_", INTERNAL_TYPE_DEF_ANY}, - {"_TZ_", INTERNAL_TYPE_DEF_ANY}, - {"_REV", ACPI_TYPE_INTEGER, "2"}, - {"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME}, - {"_GL_", ACPI_TYPE_MUTEX, "0"}, - - /* Table terminator */ - - {NULL, ACPI_TYPE_ANY} -}; - - -/* - * Properties of the ACPI Object Types, both internal and external. - * - * Elements of Acpi_ns_properties are bit significant - * and the table is indexed by values of ACPI_OBJECT_TYPE - */ - -u8 acpi_gbl_ns_properties[] = -{ - NSP_NORMAL, /* 00 Any */ - NSP_NORMAL, /* 01 Number */ - NSP_NORMAL, /* 02 String */ - NSP_NORMAL, /* 03 Buffer */ - NSP_LOCAL, /* 04 Package */ - NSP_NORMAL, /* 05 Field_unit */ - NSP_NEWSCOPE | NSP_LOCAL, /* 06 Device */ - NSP_LOCAL, /* 07 Acpi_event */ - NSP_NEWSCOPE | NSP_LOCAL, /* 08 Method */ - NSP_LOCAL, /* 09 Mutex */ - NSP_LOCAL, /* 10 Region */ - NSP_NEWSCOPE | NSP_LOCAL, /* 11 Power */ - NSP_NEWSCOPE | NSP_LOCAL, /* 12 Processor */ - NSP_NEWSCOPE | NSP_LOCAL, /* 13 Thermal */ - NSP_NORMAL, /* 14 Buffer_field */ - NSP_NORMAL, /* 15 Ddb_handle */ - NSP_NORMAL, /* 16 Debug Object */ - NSP_NORMAL, /* 17 Def_field */ - NSP_NORMAL, /* 18 Bank_field */ - NSP_NORMAL, /* 19 Index_field */ - NSP_NORMAL, /* 20 Reference */ - NSP_NORMAL, /* 21 Alias */ - NSP_NORMAL, /* 22 Notify */ - NSP_NORMAL, /* 23 Address Handler */ - NSP_NEWSCOPE | NSP_LOCAL, /* 24 Resource */ - NSP_NORMAL, /* 25 Def_field_defn */ - NSP_NORMAL, /* 26 Bank_field_defn */ - NSP_NORMAL, /* 27 Index_field_defn */ - NSP_NORMAL, /* 28 If */ - NSP_NORMAL, /* 29 Else */ - NSP_NORMAL, /* 30 While */ - NSP_NEWSCOPE, /* 31 Scope */ - NSP_LOCAL, /* 32 Def_any */ - NSP_NORMAL, /* 33 Extra */ - NSP_NORMAL /* 34 Invalid */ -}; - - -/* Hex to ASCII conversion table */ - -NATIVE_CHAR acpi_gbl_hex_to_ascii[] = - {'0','1','2','3','4','5','6','7', - '8','9','A','B','C','D','E','F'}; - - -/****************************************************************************** - * - * Table globals - * - * NOTE: This table includes ONLY the ACPI tables that the subsystem consumes. - * it is NOT an exhaustive list of all possible ACPI tables. All ACPI tables - * that are not used by the subsystem are simply ignored. - * - ******************************************************************************/ - - -ACPI_TABLE_DESC acpi_gbl_acpi_tables[NUM_ACPI_TABLES]; - - -ACPI_TABLE_SUPPORT acpi_gbl_acpi_table_data[NUM_ACPI_TABLES] = -{ - /*********** Name, Signature, Signature size, How many allowed?, Supported? Global typed pointer */ - - /* RSDP 0 */ {RSDP_NAME, RSDP_SIG, sizeof (RSDP_SIG)-1, ACPI_TABLE_SINGLE, AE_OK, NULL}, - /* DSDT 1 */ {DSDT_SIG, DSDT_SIG, sizeof (DSDT_SIG)-1, ACPI_TABLE_SINGLE, AE_OK, (void **) &acpi_gbl_DSDT}, - /* FADT 2 */ {FADT_SIG, FADT_SIG, sizeof (FADT_SIG)-1, ACPI_TABLE_SINGLE, AE_OK, (void **) &acpi_gbl_FADT}, - /* FACS 3 */ {FACS_SIG, FACS_SIG, sizeof (FACS_SIG)-1, ACPI_TABLE_SINGLE, AE_OK, (void **) &acpi_gbl_FACS}, - /* PSDT 4 */ {PSDT_SIG, PSDT_SIG, sizeof (PSDT_SIG)-1, ACPI_TABLE_MULTIPLE, AE_OK, NULL}, - /* SSDT 5 */ {SSDT_SIG, SSDT_SIG, sizeof (SSDT_SIG)-1, ACPI_TABLE_MULTIPLE, AE_OK, NULL}, - /* XSDT 6 */ {XSDT_SIG, XSDT_SIG, sizeof (RSDT_SIG)-1, ACPI_TABLE_SINGLE, AE_OK, NULL}, -}; - - -/***************************************************************************** - * - * FUNCTION: Acpi_cm_valid_object_type - * - * PARAMETERS: None. - * - * RETURN: TRUE if valid object type - * - * DESCRIPTION: Validate an object type - * - ****************************************************************************/ - -u8 -acpi_cm_valid_object_type ( - u32 type) -{ - - if (type > ACPI_TYPE_MAX) { - if ((type < INTERNAL_TYPE_BEGIN) || - (type > INTERNAL_TYPE_MAX)) - { - return (FALSE); - } - } - - return (TRUE); -} - - -/***************************************************************************** - * - * FUNCTION: Acpi_cm_format_exception - * - * PARAMETERS: Status - Acpi status to be formatted - * - * RETURN: Formatted status string - * - * DESCRIPTION: Convert an ACPI exception to a string - * - ****************************************************************************/ - -NATIVE_CHAR * -acpi_cm_format_exception ( - ACPI_STATUS status) -{ - NATIVE_CHAR *exception = "UNKNOWN_STATUS"; - ACPI_STATUS sub_status; - - - sub_status = (status & ~AE_CODE_MASK); - - - switch (status & AE_CODE_MASK) - { - case AE_CODE_ENVIRONMENTAL: - - if (sub_status <= AE_CODE_ENV_MAX) { - exception = acpi_gbl_exception_names_env [sub_status]; - } - break; - - case AE_CODE_PROGRAMMER: - - if (sub_status <= AE_CODE_PGM_MAX) { - exception = acpi_gbl_exception_names_pgm [sub_status -1]; - } - break; - - case AE_CODE_ACPI_TABLES: - - if (sub_status <= AE_CODE_TBL_MAX) { - exception = acpi_gbl_exception_names_tbl [sub_status -1]; - } - break; - - case AE_CODE_AML: - - if (sub_status <= AE_CODE_AML_MAX) { - exception = acpi_gbl_exception_names_aml [sub_status -1]; - } - break; - - case AE_CODE_CONTROL: - - if (sub_status <= AE_CODE_CTRL_MAX) { - exception = acpi_gbl_exception_names_ctrl [sub_status -1]; - } - break; - - default: - break; - } - - - return (exception); -} - - -/**************************************************************************** - * - * FUNCTION: Acpi_cm_allocate_owner_id - * - * PARAMETERS: Id_type - Type of ID (method or table) - * - * DESCRIPTION: Allocate a table or method owner id - * - ***************************************************************************/ - -ACPI_OWNER_ID -acpi_cm_allocate_owner_id ( - u32 id_type) -{ - ACPI_OWNER_ID owner_id = 0xFFFF; - - - acpi_cm_acquire_mutex (ACPI_MTX_CACHES); - - switch (id_type) - { - case OWNER_TYPE_TABLE: - - owner_id = acpi_gbl_next_table_owner_id; - acpi_gbl_next_table_owner_id++; - - if (acpi_gbl_next_table_owner_id == FIRST_METHOD_ID) { - acpi_gbl_next_table_owner_id = FIRST_TABLE_ID; - } - break; - - - case OWNER_TYPE_METHOD: - - owner_id = acpi_gbl_next_method_owner_id; - acpi_gbl_next_method_owner_id++; - - if (acpi_gbl_next_method_owner_id == FIRST_TABLE_ID) { - acpi_gbl_next_method_owner_id = FIRST_METHOD_ID; - } - break; - } - - - acpi_cm_release_mutex (ACPI_MTX_CACHES); - - return (owner_id); -} - - -/**************************************************************************** - * - * FUNCTION: Acpi_cm_init_globals - * - * PARAMETERS: none - * - * DESCRIPTION: Init library globals. All globals that require specific - * initialization should be initialized here! - * - ***************************************************************************/ - -void -acpi_cm_init_globals ( - void) -{ - u32 i; - - - /* ACPI table structure */ - - for (i = 0; i < NUM_ACPI_TABLES; i++) { - acpi_gbl_acpi_tables[i].prev = &acpi_gbl_acpi_tables[i]; - acpi_gbl_acpi_tables[i].next = &acpi_gbl_acpi_tables[i]; - acpi_gbl_acpi_tables[i].pointer = NULL; - acpi_gbl_acpi_tables[i].length = 0; - acpi_gbl_acpi_tables[i].allocation = ACPI_MEM_NOT_ALLOCATED; - acpi_gbl_acpi_tables[i].count = 0; - } - - - /* Address Space handler array */ - - for (i = 0; i < ACPI_NUM_ADDRESS_SPACES; i++) { - acpi_gbl_address_spaces[i].handler = NULL; - acpi_gbl_address_spaces[i].context = NULL; - } - - /* Mutex locked flags */ - - for (i = 0; i < NUM_MTX; i++) { - acpi_gbl_acpi_mutex_info[i].mutex = NULL; - acpi_gbl_acpi_mutex_info[i].locked = FALSE; - acpi_gbl_acpi_mutex_info[i].use_count = 0; - } - - /* Global notify handlers */ - - acpi_gbl_sys_notify.handler = NULL; - acpi_gbl_drv_notify.handler = NULL; - - /* Global "typed" ACPI table pointers */ - - acpi_gbl_RSDP = NULL; - acpi_gbl_XSDT = NULL; - acpi_gbl_FACS = NULL; - acpi_gbl_FADT = NULL; - acpi_gbl_DSDT = NULL; - - - /* Global Lock support */ - - acpi_gbl_global_lock_acquired = FALSE; - acpi_gbl_global_lock_thread_count = 0; - - /* Miscellaneous variables */ - - acpi_gbl_system_flags = 0; - acpi_gbl_startup_flags = 0; - acpi_gbl_global_lock_set = FALSE; - acpi_gbl_rsdp_original_location = 0; - acpi_gbl_cm_single_step = FALSE; - acpi_gbl_db_terminate_threads = FALSE; - acpi_gbl_shutdown = FALSE; - acpi_gbl_ns_lookup_count = 0; - acpi_gbl_ps_find_count = 0; - acpi_gbl_acpi_hardware_present = TRUE; - acpi_gbl_next_table_owner_id = FIRST_TABLE_ID; - acpi_gbl_next_method_owner_id = FIRST_METHOD_ID; - acpi_gbl_debugger_configuration = DEBUGGER_THREADING; - - /* Cache of small "state" objects */ - - acpi_gbl_generic_state_cache = NULL; - acpi_gbl_generic_state_cache_depth = 0; - acpi_gbl_state_cache_requests = 0; - acpi_gbl_state_cache_hits = 0; - - acpi_gbl_parse_cache = NULL; - acpi_gbl_parse_cache_depth = 0; - acpi_gbl_parse_cache_requests = 0; - acpi_gbl_parse_cache_hits = 0; - - acpi_gbl_ext_parse_cache = NULL; - acpi_gbl_ext_parse_cache_depth = 0; - acpi_gbl_ext_parse_cache_requests = 0; - acpi_gbl_ext_parse_cache_hits = 0; - - acpi_gbl_object_cache = NULL; - acpi_gbl_object_cache_depth = 0; - acpi_gbl_object_cache_requests = 0; - acpi_gbl_object_cache_hits = 0; - - acpi_gbl_walk_state_cache = NULL; - acpi_gbl_walk_state_cache_depth = 0; - acpi_gbl_walk_state_cache_requests = 0; - acpi_gbl_walk_state_cache_hits = 0; - - /* Hardware oriented */ - - acpi_gbl_gpe0enable_register_save = NULL; - acpi_gbl_gpe1_enable_register_save = NULL; - acpi_gbl_original_mode = SYS_MODE_UNKNOWN; /* original ACPI/legacy mode */ - acpi_gbl_gpe_registers = NULL; - acpi_gbl_gpe_info = NULL; - - /* Namespace */ - - acpi_gbl_root_node = NULL; - - acpi_gbl_root_node_struct.name = ACPI_ROOT_NAME; - acpi_gbl_root_node_struct.data_type = ACPI_DESC_TYPE_NAMED; - acpi_gbl_root_node_struct.type = ACPI_TYPE_ANY; - acpi_gbl_root_node_struct.child = NULL; - acpi_gbl_root_node_struct.peer = NULL; - acpi_gbl_root_node_struct.object = NULL; - acpi_gbl_root_node_struct.flags = ANOBJ_END_OF_PEER_LIST; - - /* Memory allocation metrics - compiled out in non-debug mode. */ - - INITIALIZE_ALLOCATION_METRICS(); - - return; -} - - diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/common/cminit.c linux/drivers/acpi/common/cminit.c --- v2.4.5/linux/drivers/acpi/common/cminit.c Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/common/cminit.c Wed Dec 31 16:00:00 1969 @@ -1,250 +0,0 @@ -/****************************************************************************** - * - * Module Name: cminit - Common ACPI subsystem initialization - * $Revision: 93 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "acpi.h" -#include "achware.h" -#include "acnamesp.h" -#include "acevents.h" -#include "acparser.h" -#include "acdispat.h" - -#define _COMPONENT MISCELLANEOUS - MODULE_NAME ("cminit") - - -#define ACPI_OFFSET(d,o) ((u32) &(((d *)0)->o)) -#define ACPI_FADT_OFFSET(o) ACPI_OFFSET (FADT_DESCRIPTOR, o) - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_fadt_register_error - * - * PARAMETERS: *Register_name - Pointer to string identifying register - * Value - Actual register contents value - * Acpi_test_spec_section - TDS section containing assertion - * Acpi_assertion - Assertion number being tested - * - * RETURN: AE_BAD_VALUE - * - * DESCRIPTION: Display failure message and link failure to TDS assertion - * - ******************************************************************************/ - -static ACPI_STATUS -acpi_cm_fadt_register_error ( - NATIVE_CHAR *register_name, - u32 value, - u32 offset) -{ - - REPORT_ERROR ( - ("Invalid FADT value %s=%lX at offset %lX FADT=%p\n", - register_name, value, offset, acpi_gbl_FADT)); - - - return (AE_BAD_VALUE); -} - - -/****************************************************************************** - * - * FUNCTION: Acpi_cm_validate_fadt - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Validate various ACPI registers in the FADT - * - ******************************************************************************/ - -ACPI_STATUS -acpi_cm_validate_fadt ( - void) -{ - ACPI_STATUS status = AE_OK; - - - /* - * Verify Fixed ACPI Description Table fields, - * but don't abort on any problems, just display error - */ - - if (acpi_gbl_FADT->pm1_evt_len < 4) { - status = acpi_cm_fadt_register_error ("PM1_EVT_LEN", - (u32) acpi_gbl_FADT->pm1_evt_len, - ACPI_FADT_OFFSET (pm1_evt_len)); - } - - if (!acpi_gbl_FADT->pm1_cnt_len) { - status = acpi_cm_fadt_register_error ("PM1_CNT_LEN", 0, - ACPI_FADT_OFFSET (pm1_cnt_len)); - } - - if (!ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm1a_evt_blk.address)) { - status = acpi_cm_fadt_register_error ("X_PM1a_EVT_BLK", 0, - ACPI_FADT_OFFSET (Xpm1a_evt_blk.address)); - } - - if (!ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm1a_cnt_blk.address)) { - status = acpi_cm_fadt_register_error ("X_PM1a_CNT_BLK", 0, - ACPI_FADT_OFFSET (Xpm1a_cnt_blk.address)); - } - - if (!ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm_tmr_blk.address)) { - status = acpi_cm_fadt_register_error ("X_PM_TMR_BLK", 0, - ACPI_FADT_OFFSET (Xpm_tmr_blk.address)); - } - - if ((ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm2_cnt_blk.address) && - !acpi_gbl_FADT->pm2_cnt_len)) - { - status = acpi_cm_fadt_register_error ("PM2_CNT_LEN", - (u32) acpi_gbl_FADT->pm2_cnt_len, - ACPI_FADT_OFFSET (pm2_cnt_len)); - } - - if (acpi_gbl_FADT->pm_tm_len < 4) { - status = acpi_cm_fadt_register_error ("PM_TM_LEN", - (u32) acpi_gbl_FADT->pm_tm_len, - ACPI_FADT_OFFSET (pm_tm_len)); - } - - /* length of GPE blocks must be a multiple of 2 */ - - - if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) && - (acpi_gbl_FADT->gpe0blk_len & 1)) - { - status = acpi_cm_fadt_register_error ("(x)GPE0_BLK_LEN", - (u32) acpi_gbl_FADT->gpe0blk_len, - ACPI_FADT_OFFSET (gpe0blk_len)); - } - - if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) && - (acpi_gbl_FADT->gpe1_blk_len & 1)) - { - status = acpi_cm_fadt_register_error ("(x)GPE1_BLK_LEN", - (u32) acpi_gbl_FADT->gpe1_blk_len, - ACPI_FADT_OFFSET (gpe1_blk_len)); - } - - return (status); -} - - -/****************************************************************************** - * - * FUNCTION: Acpi_cm_terminate - * - * PARAMETERS: none - * - * RETURN: none - * - * DESCRIPTION: free memory allocated for table storage. - * - ******************************************************************************/ - -void -acpi_cm_terminate (void) -{ - - - /* Free global tables, etc. */ - - if (acpi_gbl_gpe0enable_register_save) { - acpi_cm_free (acpi_gbl_gpe0enable_register_save); - } - - if (acpi_gbl_gpe1_enable_register_save) { - acpi_cm_free (acpi_gbl_gpe1_enable_register_save); - } - - - return; -} - - -/****************************************************************************** - * - * FUNCTION: Acpi_cm_subsystem_shutdown - * - * PARAMETERS: none - * - * RETURN: none - * - * DESCRIPTION: Shutdown the various subsystems. Don't delete the mutex - * objects here -- because the AML debugger may be still running. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_cm_subsystem_shutdown (void) -{ - - /* Just exit if subsystem is already shutdown */ - - if (acpi_gbl_shutdown) { - return (AE_OK); - } - - /* Subsystem appears active, go ahead and shut it down */ - - acpi_gbl_shutdown = TRUE; - - /* Close the Namespace */ - - acpi_ns_terminate (); - - /* Close the Acpi_event Handling */ - - acpi_ev_terminate (); - - /* Close the globals */ - - acpi_cm_terminate (); - - /* Flush the local cache(s) */ - - acpi_cm_delete_generic_state_cache (); - acpi_cm_delete_object_cache (); - acpi_ds_delete_walk_state_cache (); - - /* Close the Parser */ - - /* TBD: [Restructure] Acpi_ps_terminate () */ - - acpi_ps_delete_parse_cache (); - - /* Debug only - display leftover memory allocation, if any */ -#ifdef ENABLE_DEBUGGER - acpi_cm_dump_current_allocations (ACPI_UINT32_MAX, NULL); -#endif - - return (AE_OK); -} - - diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/common/cmobject.c linux/drivers/acpi/common/cmobject.c --- v2.4.5/linux/drivers/acpi/common/cmobject.c Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/common/cmobject.c Wed Dec 31 16:00:00 1969 @@ -1,618 +0,0 @@ -/****************************************************************************** - * - * Module Name: cmobject - ACPI object create/delete/size/cache routines - * $Revision: 36 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "acpi.h" -#include "acinterp.h" -#include "acnamesp.h" -#include "actables.h" -#include "amlcode.h" - - -#define _COMPONENT MISCELLANEOUS - MODULE_NAME ("cmobject") - - -/******************************************************************************* - * - * FUNCTION: _Cm_create_internal_object - * - * PARAMETERS: Address - Address of the memory to deallocate - * Component - Component type of caller - * Module - Source file name of caller - * Line - Line number of caller - * Type - ACPI Type of the new object - * - * RETURN: Object - The new object. Null on failure - * - * DESCRIPTION: Create and initialize a new internal object. - * - * NOTE: We always allocate the worst-case object descriptor because - * these objects are cached, and we want them to be - * one-size-satisifies-any-request. This in itself may not be - * the most memory efficient, but the efficiency of the object - * cache should more than make up for this! - * - ******************************************************************************/ - -ACPI_OPERAND_OBJECT * -_cm_create_internal_object ( - NATIVE_CHAR *module_name, - u32 line_number, - u32 component_id, - OBJECT_TYPE_INTERNAL type) -{ - ACPI_OPERAND_OBJECT *object; - - - /* Allocate the raw object descriptor */ - - object = _cm_allocate_object_desc (module_name, line_number, component_id); - if (!object) { - /* Allocation failure */ - - return (NULL); - } - - /* Save the object type in the object descriptor */ - - object->common.type = type; - - /* Init the reference count */ - - object->common.reference_count = 1; - - /* Any per-type initialization should go here */ - - - return (object); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_valid_internal_object - * - * PARAMETERS: Operand - Object to be validated - * - * RETURN: Validate a pointer to be an ACPI_OPERAND_OBJECT - * - ******************************************************************************/ - -u8 -acpi_cm_valid_internal_object ( - void *object) -{ - - /* Check for a null pointer */ - - if (!object) { - return (FALSE); - } - - /* Check for a pointer within one of the ACPI tables */ - - if (acpi_tb_system_table_pointer (object)) { - return (FALSE); - } - - /* Check the descriptor type field */ - - if (!VALID_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_INTERNAL)) { - /* Not an ACPI internal object, do some further checking */ - - - - - return (FALSE); - } - - - /* The object appears to be a valid ACPI_OPERAND_OBJECT */ - - return (TRUE); -} - - -/******************************************************************************* - * - * FUNCTION: _Cm_allocate_object_desc - * - * PARAMETERS: Module_name - Caller's module name (for error output) - * Line_number - Caller's line number (for error output) - * Component_id - Caller's component ID (for error output) - * Message - Error message to use on failure - * - * RETURN: Pointer to newly allocated object descriptor. Null on error - * - * DESCRIPTION: Allocate a new object descriptor. Gracefully handle - * error conditions. - * - ******************************************************************************/ - -void * -_cm_allocate_object_desc ( - NATIVE_CHAR *module_name, - u32 line_number, - u32 component_id) -{ - ACPI_OPERAND_OBJECT *object; - - - acpi_cm_acquire_mutex (ACPI_MTX_CACHES); - - acpi_gbl_object_cache_requests++; - - /* Check the cache first */ - - if (acpi_gbl_object_cache) { - /* There is an object available, use it */ - - object = acpi_gbl_object_cache; - acpi_gbl_object_cache = object->cache.next; - object->cache.next = NULL; - - acpi_gbl_object_cache_hits++; - acpi_gbl_object_cache_depth--; - - acpi_cm_release_mutex (ACPI_MTX_CACHES); - } - - else { - /* The cache is empty, create a new object */ - - acpi_cm_release_mutex (ACPI_MTX_CACHES); - - /* Attempt to allocate new descriptor */ - - object = _cm_callocate (sizeof (ACPI_OPERAND_OBJECT), component_id, - module_name, line_number); - if (!object) { - /* Allocation failed */ - - _REPORT_ERROR (module_name, line_number, component_id, - ("Could not allocate an object descriptor\n")); - - return (NULL); - } - - /* Memory allocation metrics - compiled out in non debug mode. */ - - INCREMENT_OBJECT_METRICS (sizeof (ACPI_OPERAND_OBJECT)); - } - - /* Mark the descriptor type */ - - object->common.data_type = ACPI_DESC_TYPE_INTERNAL; - - return (object); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_delete_object_desc - * - * PARAMETERS: Object - Acpi internal object to be deleted - * - * RETURN: None. - * - * DESCRIPTION: Free an ACPI object descriptor or add it to the object cache - * - ******************************************************************************/ - -void -acpi_cm_delete_object_desc ( - ACPI_OPERAND_OBJECT *object) -{ - - - /* Make sure that the object isn't already in the cache */ - - if (object->common.data_type == (ACPI_DESC_TYPE_INTERNAL | ACPI_CACHED_OBJECT)) { - return; - } - - /* Object must be an ACPI_OPERAND_OBJECT */ - - if (object->common.data_type != ACPI_DESC_TYPE_INTERNAL) { - return; - } - - - /* If cache is full, just free this object */ - - if (acpi_gbl_object_cache_depth >= MAX_OBJECT_CACHE_DEPTH) { - /* - * Memory allocation metrics. Call the macro here since we only - * care about dynamically allocated objects. - */ - DECREMENT_OBJECT_METRICS (sizeof (ACPI_OPERAND_OBJECT)); - - acpi_cm_free (object); - return; - } - - acpi_cm_acquire_mutex (ACPI_MTX_CACHES); - - /* Clear the entire object. This is important! */ - - MEMSET (object, 0, sizeof (ACPI_OPERAND_OBJECT)); - object->common.data_type = ACPI_DESC_TYPE_INTERNAL | ACPI_CACHED_OBJECT; - - /* Put the object at the head of the global cache list */ - - object->cache.next = acpi_gbl_object_cache; - acpi_gbl_object_cache = object; - acpi_gbl_object_cache_depth++; - - - acpi_cm_release_mutex (ACPI_MTX_CACHES); - return; -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_delete_object_cache - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Purge the global state object cache. Used during subsystem - * termination. - * - ******************************************************************************/ - -void -acpi_cm_delete_object_cache ( - void) -{ - ACPI_OPERAND_OBJECT *next; - - - /* Traverse the global cache list */ - - while (acpi_gbl_object_cache) { - /* Delete one cached state object */ - - next = acpi_gbl_object_cache->cache.next; - acpi_gbl_object_cache->cache.next = NULL; - - /* - * Memory allocation metrics. Call the macro here since we only - * care about dynamically allocated objects. - */ - DECREMENT_OBJECT_METRICS (sizeof (ACPI_OPERAND_OBJECT)); - - acpi_cm_free (acpi_gbl_object_cache); - acpi_gbl_object_cache = next; - acpi_gbl_object_cache_depth--; - } - - return; -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_init_static_object - * - * PARAMETERS: Obj_desc - Pointer to a "static" object - on stack - * or in the data segment. - * - * RETURN: None. - * - * DESCRIPTION: Initialize a static object. Sets flags to disallow dynamic - * deletion of the object. - * - ******************************************************************************/ - -void -acpi_cm_init_static_object ( - ACPI_OPERAND_OBJECT *obj_desc) -{ - - - if (!obj_desc) { - return; - } - - - /* - * Clear the entire descriptor - */ - MEMSET ((void *) obj_desc, 0, sizeof (ACPI_OPERAND_OBJECT)); - - - /* - * Initialize the header fields - * 1) This is an ACPI_OPERAND_OBJECT descriptor - * 2) The size is the full object (worst case) - * 3) The flags field indicates static allocation - * 4) Reference count starts at one (not really necessary since the - * object can't be deleted, but keeps everything sane) - */ - - obj_desc->common.data_type = ACPI_DESC_TYPE_INTERNAL; - obj_desc->common.flags = AOPOBJ_STATIC_ALLOCATION; - obj_desc->common.reference_count = 1; - - return; -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_get_simple_object_size - * - * PARAMETERS: *Internal_object - Pointer to the object we are examining - * *Ret_length - Where the length is returned - * - * RETURN: Status - * - * DESCRIPTION: This function is called to determine the space required to - * contain a simple object for return to an API user. - * - * The length includes the object structure plus any additional - * needed space. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_cm_get_simple_object_size ( - ACPI_OPERAND_OBJECT *internal_object, - u32 *obj_length) -{ - u32 length; - ACPI_STATUS status = AE_OK; - - - /* Handle a null object (Could be a uninitialized package element -- which is legal) */ - - if (!internal_object) { - *obj_length = 0; - return (AE_OK); - } - - - /* Start with the length of the Acpi object */ - - length = sizeof (ACPI_OBJECT); - - if (VALID_DESCRIPTOR_TYPE (internal_object, ACPI_DESC_TYPE_NAMED)) { - /* Object is a named object (reference), just return the length */ - - *obj_length = (u32) ROUND_UP_TO_NATIVE_WORD (length); - return (status); - } - - - /* - * The final length depends on the object type - * Strings and Buffers are packed right up against the parent object and - * must be accessed bytewise or there may be alignment problems. - * - * TBD:[Investigate] do strings and buffers require alignment also? - */ - - switch (internal_object->common.type) - { - - case ACPI_TYPE_STRING: - - length += internal_object->string.length + 1; - break; - - - case ACPI_TYPE_BUFFER: - - length += internal_object->buffer.length; - break; - - - case ACPI_TYPE_INTEGER: - case ACPI_TYPE_PROCESSOR: - case ACPI_TYPE_POWER: - - /* - * No extra data for these types - */ - break; - - - case INTERNAL_TYPE_REFERENCE: - - /* - * The only type that should be here is opcode AML_NAMEPATH_OP -- since - * this means an object reference - */ - if (internal_object->reference.op_code != AML_NAMEPATH_OP) { - status = AE_TYPE; - } - break; - - - default: - - status = AE_TYPE; - break; - } - - - /* - * Account for the space required by the object rounded up to the next - * multiple of the machine word size. This keeps each object aligned - * on a machine word boundary. (preventing alignment faults on some - * machines.) - */ - *obj_length = (u32) ROUND_UP_TO_NATIVE_WORD (length); - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_copy_package_to_internal - * - * PARAMETERS: ACPI_PKG_CALLBACK - * - * RETURN: Status - the status of the call - * - * DESCRIPTION: - * - ******************************************************************************/ - -ACPI_STATUS -acpi_cm_get_element_length ( - u8 object_type, - ACPI_OPERAND_OBJECT *source_object, - ACPI_GENERIC_STATE *state, - void *context) -{ - ACPI_STATUS status = AE_OK; - ACPI_PKG_INFO *info = (ACPI_PKG_INFO *) context; - u32 object_space; - - - switch (object_type) - { - case 0: - - /* - * Simple object - just get the size (Null object/entry is handled - * here also) and sum it into the running package length - */ - status = acpi_cm_get_simple_object_size (source_object, &object_space); - if (ACPI_FAILURE (status)) { - return (status); - } - - info->length += object_space; - break; - - - case 1: - /* Package - nothing much to do here, let the walk handle it */ - - info->num_packages++; - state->pkg.this_target_obj = NULL; - break; - - default: - return (AE_BAD_PARAMETER); - } - - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_get_package_object_size - * - * PARAMETERS: *Internal_object - Pointer to the object we are examining - * *Ret_length - Where the length is returned - * - * RETURN: Status - * - * DESCRIPTION: This function is called to determine the space required to - * contain a package object for return to an API user. - * - * This is moderately complex since a package contains other - * objects including packages. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_cm_get_package_object_size ( - ACPI_OPERAND_OBJECT *internal_object, - u32 *obj_length) -{ - ACPI_STATUS status; - ACPI_PKG_INFO info; - - - info.length = 0; - info.object_space = 0; - info.num_packages = 1; - - status = acpi_cm_walk_package_tree (internal_object, NULL, - acpi_cm_get_element_length, &info); - - /* - * We have handled all of the objects in all levels of the package. - * just add the length of the package objects themselves. - * Round up to the next machine word. - */ - info.length += ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT)) * - info.num_packages; - - /* Return the total package length */ - - *obj_length = info.length; - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_get_object_size - * - * PARAMETERS: *Internal_object - Pointer to the object we are examining - * *Ret_length - Where the length will be returned - * - * RETURN: Status - * - * DESCRIPTION: This function is called to determine the space required to - * contain an object for return to an API user. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_cm_get_object_size( - ACPI_OPERAND_OBJECT *internal_object, - u32 *obj_length) -{ - ACPI_STATUS status; - - - if ((VALID_DESCRIPTOR_TYPE (internal_object, ACPI_DESC_TYPE_INTERNAL)) && - (IS_THIS_OBJECT_TYPE (internal_object, ACPI_TYPE_PACKAGE))) - { - status = acpi_cm_get_package_object_size (internal_object, obj_length); - } - - else { - status = acpi_cm_get_simple_object_size (internal_object, obj_length); - } - - return (status); -} - - diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/common/cmutils.c linux/drivers/acpi/common/cmutils.c --- v2.4.5/linux/drivers/acpi/common/cmutils.c Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/common/cmutils.c Wed Dec 31 16:00:00 1969 @@ -1,952 +0,0 @@ -/******************************************************************************* - * - * Module Name: cmutils - common utility procedures - * $Revision: 27 $ - * - ******************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "acpi.h" -#include "acevents.h" -#include "achware.h" -#include "acnamesp.h" -#include "acinterp.h" -#include "amlcode.h" -#include "acdebug.h" - - -#define _COMPONENT MISCELLANEOUS - MODULE_NAME ("cmutils") - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_valid_acpi_name - * - * PARAMETERS: Character - The character to be examined - * - * RETURN: 1 if Character may appear in a name, else 0 - * - * DESCRIPTION: Check for a valid ACPI name. Each character must be one of: - * 1) Upper case alpha - * 2) numeric - * 3) underscore - * - ******************************************************************************/ - -u8 -acpi_cm_valid_acpi_name ( - u32 name) -{ - NATIVE_CHAR *name_ptr = (NATIVE_CHAR *) &name; - u32 i; - - - for (i = 0; i < ACPI_NAME_SIZE; i++) { - if (!((name_ptr[i] == '_') || - (name_ptr[i] >= 'A' && name_ptr[i] <= 'Z') || - (name_ptr[i] >= '0' && name_ptr[i] <= '9'))) - { - return (FALSE); - } - } - - - return (TRUE); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_valid_acpi_character - * - * PARAMETERS: Character - The character to be examined - * - * RETURN: 1 if Character may appear in a name, else 0 - * - * DESCRIPTION: Check for a printable character - * - ******************************************************************************/ - -u8 -acpi_cm_valid_acpi_character ( - NATIVE_CHAR character) -{ - - return ((u8) ((character == '_') || - (character >= 'A' && character <= 'Z') || - (character >= '0' && character <= '9'))); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_mutex_initialize - * - * PARAMETERS: None. - * - * RETURN: Status - * - * DESCRIPTION: Create the system mutex objects. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_cm_mutex_initialize ( - void) -{ - u32 i; - ACPI_STATUS status; - - - /* - * Create each of the predefined mutex objects - */ - for (i = 0; i < NUM_MTX; i++) { - status = acpi_cm_create_mutex (i); - if (ACPI_FAILURE (status)) { - return (status); - } - } - - return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_mutex_terminate - * - * PARAMETERS: None. - * - * RETURN: None. - * - * DESCRIPTION: Delete all of the system mutex objects. - * - ******************************************************************************/ - -void -acpi_cm_mutex_terminate ( - void) -{ - u32 i; - - - /* - * Delete each predefined mutex object - */ - for (i = 0; i < NUM_MTX; i++) { - acpi_cm_delete_mutex (i); - } - - return; -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_create_mutex - * - * PARAMETERS: Mutex_iD - ID of the mutex to be created - * - * RETURN: Status - * - * DESCRIPTION: Create a mutex object. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_cm_create_mutex ( - ACPI_MUTEX_HANDLE mutex_id) -{ - ACPI_STATUS status = AE_OK; - - - if (mutex_id > MAX_MTX) { - return (AE_BAD_PARAMETER); - } - - - if (!acpi_gbl_acpi_mutex_info[mutex_id].mutex) { - status = acpi_os_create_semaphore (1, 1, - &acpi_gbl_acpi_mutex_info[mutex_id].mutex); - acpi_gbl_acpi_mutex_info[mutex_id].locked = FALSE; - acpi_gbl_acpi_mutex_info[mutex_id].use_count = 0; - } - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_delete_mutex - * - * PARAMETERS: Mutex_iD - ID of the mutex to be deleted - * - * RETURN: Status - * - * DESCRIPTION: Delete a mutex object. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_cm_delete_mutex ( - ACPI_MUTEX_HANDLE mutex_id) -{ - ACPI_STATUS status; - - - if (mutex_id > MAX_MTX) { - return (AE_BAD_PARAMETER); - } - - - status = acpi_os_delete_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex); - - acpi_gbl_acpi_mutex_info[mutex_id].mutex = NULL; - acpi_gbl_acpi_mutex_info[mutex_id].locked = FALSE; - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_acquire_mutex - * - * PARAMETERS: Mutex_iD - ID of the mutex to be acquired - * - * RETURN: Status - * - * DESCRIPTION: Acquire a mutex object. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_cm_acquire_mutex ( - ACPI_MUTEX_HANDLE mutex_id) -{ - ACPI_STATUS status; - - - if (mutex_id > MAX_MTX) { - return (AE_BAD_PARAMETER); - } - - - status = acpi_os_wait_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex, - 1, WAIT_FOREVER); - - if (ACPI_SUCCESS (status)) { - acpi_gbl_acpi_mutex_info[mutex_id].locked = TRUE; - acpi_gbl_acpi_mutex_info[mutex_id].use_count++; - } - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_release_mutex - * - * PARAMETERS: Mutex_iD - ID of the mutex to be released - * - * RETURN: Status - * - * DESCRIPTION: Release a mutex object. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_cm_release_mutex ( - ACPI_MUTEX_HANDLE mutex_id) -{ - ACPI_STATUS status; - - - if (mutex_id > MAX_MTX) { - return (AE_BAD_PARAMETER); - } - - - acpi_gbl_acpi_mutex_info[mutex_id].locked = FALSE; /* Mark before unlocking */ - - status = acpi_os_signal_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex, 1); - - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_create_update_state_and_push - * - * PARAMETERS: *Object - Object to be added to the new state - * Action - Increment/Decrement - * State_list - List the state will be added to - * - * RETURN: None - * - * DESCRIPTION: Create a new state and push it - * - ******************************************************************************/ - -ACPI_STATUS -acpi_cm_create_update_state_and_push ( - ACPI_OPERAND_OBJECT *object, - u16 action, - ACPI_GENERIC_STATE **state_list) -{ - ACPI_GENERIC_STATE *state; - - - /* Ignore null objects; these are expected */ - - if (!object) { - return (AE_OK); - } - - state = acpi_cm_create_update_state (object, action); - if (!state) { - return (AE_NO_MEMORY); - } - - - acpi_cm_push_generic_state (state_list, state); - return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_create_pkg_state_and_push - * - * PARAMETERS: *Object - Object to be added to the new state - * Action - Increment/Decrement - * State_list - List the state will be added to - * - * RETURN: None - * - * DESCRIPTION: Create a new state and push it - * - ******************************************************************************/ - -ACPI_STATUS -acpi_cm_create_pkg_state_and_push ( - void *internal_object, - void *external_object, - u16 index, - ACPI_GENERIC_STATE **state_list) -{ - ACPI_GENERIC_STATE *state; - - - state = acpi_cm_create_pkg_state (internal_object, external_object, index); - if (!state) { - return (AE_NO_MEMORY); - } - - - acpi_cm_push_generic_state (state_list, state); - return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_push_generic_state - * - * PARAMETERS: List_head - Head of the state stack - * State - State object to push - * - * RETURN: Status - * - * DESCRIPTION: Push a state object onto a state stack - * - ******************************************************************************/ - -void -acpi_cm_push_generic_state ( - ACPI_GENERIC_STATE **list_head, - ACPI_GENERIC_STATE *state) -{ - /* Push the state object onto the front of the list (stack) */ - - state->common.next = *list_head; - *list_head = state; - - return; -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_pop_generic_state - * - * PARAMETERS: List_head - Head of the state stack - * - * RETURN: Status - * - * DESCRIPTION: Pop a state object from a state stack - * - ******************************************************************************/ - -ACPI_GENERIC_STATE * -acpi_cm_pop_generic_state ( - ACPI_GENERIC_STATE **list_head) -{ - ACPI_GENERIC_STATE *state; - - - /* Remove the state object at the head of the list (stack) */ - - state = *list_head; - if (state) { - /* Update the list head */ - - *list_head = state->common.next; - } - - return (state); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_create_generic_state - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Create a generic state object. Attempt to obtain one from - * the global state cache; If none available, create a new one. - * - ******************************************************************************/ - -ACPI_GENERIC_STATE * -acpi_cm_create_generic_state (void) -{ - ACPI_GENERIC_STATE *state; - - - acpi_cm_acquire_mutex (ACPI_MTX_CACHES); - - acpi_gbl_state_cache_requests++; - - /* Check the cache first */ - - if (acpi_gbl_generic_state_cache) { - /* There is an object available, use it */ - - state = acpi_gbl_generic_state_cache; - acpi_gbl_generic_state_cache = state->common.next; - state->common.next = NULL; - - acpi_gbl_state_cache_hits++; - acpi_gbl_generic_state_cache_depth--; - - acpi_cm_release_mutex (ACPI_MTX_CACHES); - - } - - else { - /* The cache is empty, create a new object */ - - acpi_cm_release_mutex (ACPI_MTX_CACHES); - - state = acpi_cm_callocate (sizeof (ACPI_GENERIC_STATE)); - } - - /* Initialize */ - - if (state) { - /* Always zero out the object before init */ - - MEMSET (state, 0, sizeof (ACPI_GENERIC_STATE)); - - state->common.data_type = ACPI_DESC_TYPE_STATE; - } - - return (state); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_create_update_state - * - * PARAMETERS: Object - Initial Object to be installed in the - * state - * Action - Update action to be performed - * - * RETURN: Status - * - * DESCRIPTION: Create an "Update State" - a flavor of the generic state used - * to update reference counts and delete complex objects such - * as packages. - * - ******************************************************************************/ - -ACPI_GENERIC_STATE * -acpi_cm_create_update_state ( - ACPI_OPERAND_OBJECT *object, - u16 action) -{ - ACPI_GENERIC_STATE *state; - - - /* Create the generic state object */ - - state = acpi_cm_create_generic_state (); - if (!state) { - return (NULL); - } - - /* Init fields specific to the update struct */ - - state->update.object = object; - state->update.value = action; - - return (state); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_create_pkg_state - * - * PARAMETERS: Object - Initial Object to be installed in the - * state - * Action - Update action to be performed - * - * RETURN: Status - * - * DESCRIPTION: Create an "Update State" - a flavor of the generic state used - * to update reference counts and delete complex objects such - * as packages. - * - ******************************************************************************/ - -ACPI_GENERIC_STATE * -acpi_cm_create_pkg_state ( - void *internal_object, - void *external_object, - u16 index) -{ - ACPI_GENERIC_STATE *state; - - - /* Create the generic state object */ - - state = acpi_cm_create_generic_state (); - if (!state) { - return (NULL); - } - - /* Init fields specific to the update struct */ - - state->pkg.source_object = (ACPI_OPERAND_OBJECT *) internal_object; - state->pkg.dest_object = external_object; - state->pkg.index = index; - state->pkg.num_packages = 1; - - return (state); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_create_control_state - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Create a "Control State" - a flavor of the generic state used - * to support nested IF/WHILE constructs in the AML. - * - ******************************************************************************/ - -ACPI_GENERIC_STATE * -acpi_cm_create_control_state ( - void) -{ - ACPI_GENERIC_STATE *state; - - - /* Create the generic state object */ - - state = acpi_cm_create_generic_state (); - if (!state) { - return (NULL); - } - - - /* Init fields specific to the control struct */ - - state->common.state = CONTROL_CONDITIONAL_EXECUTING; - - return (state); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_delete_generic_state - * - * PARAMETERS: State - The state object to be deleted - * - * RETURN: Status - * - * DESCRIPTION: Put a state object back into the global state cache. The object - * is not actually freed at this time. - * - ******************************************************************************/ - -void -acpi_cm_delete_generic_state ( - ACPI_GENERIC_STATE *state) -{ - - /* If cache is full, just free this state object */ - - if (acpi_gbl_generic_state_cache_depth >= MAX_STATE_CACHE_DEPTH) { - acpi_cm_free (state); - } - - /* Otherwise put this object back into the cache */ - - else { - acpi_cm_acquire_mutex (ACPI_MTX_CACHES); - - /* Clear the state */ - - MEMSET (state, 0, sizeof (ACPI_GENERIC_STATE)); - state->common.data_type = ACPI_DESC_TYPE_STATE; - - /* Put the object at the head of the global cache list */ - - state->common.next = acpi_gbl_generic_state_cache; - acpi_gbl_generic_state_cache = state; - acpi_gbl_generic_state_cache_depth++; - - - acpi_cm_release_mutex (ACPI_MTX_CACHES); - } - return; -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_delete_generic_state_cache - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Purge the global state object cache. Used during subsystem - * termination. - * - ******************************************************************************/ - -void -acpi_cm_delete_generic_state_cache ( - void) -{ - ACPI_GENERIC_STATE *next; - - - /* Traverse the global cache list */ - - while (acpi_gbl_generic_state_cache) { - /* Delete one cached state object */ - - next = acpi_gbl_generic_state_cache->common.next; - acpi_cm_free (acpi_gbl_generic_state_cache); - acpi_gbl_generic_state_cache = next; - acpi_gbl_generic_state_cache_depth--; - } - - return; -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_resolve_package_references - * - * PARAMETERS: Obj_desc - The Package object on which to resolve refs - * - * RETURN: Status - * - * DESCRIPTION: Walk through a package and turn internal references into values - * - ******************************************************************************/ - -ACPI_STATUS -acpi_cm_resolve_package_references ( - ACPI_OPERAND_OBJECT *obj_desc) -{ - u32 count; - ACPI_OPERAND_OBJECT *sub_object; - - - if (obj_desc->common.type != ACPI_TYPE_PACKAGE) { - /* The object must be a package */ - - REPORT_ERROR (("Must resolve Package Refs on a Package\n")); - return(AE_ERROR); - } - - /* - * TBD: what about nested packages? */ - - for (count = 0; count < obj_desc->package.count; count++) { - sub_object = obj_desc->package.elements[count]; - - if (sub_object->common.type == INTERNAL_TYPE_REFERENCE) { - if (sub_object->reference.op_code == AML_ZERO_OP) { - sub_object->common.type = ACPI_TYPE_INTEGER; - sub_object->integer.value = 0; - } - else if (sub_object->reference.op_code == AML_ONE_OP) { - sub_object->common.type = ACPI_TYPE_INTEGER; - sub_object->integer.value = 1; - } - else if (sub_object->reference.op_code == AML_ONES_OP) { - sub_object->common.type = ACPI_TYPE_INTEGER; - sub_object->integer.value = ACPI_INTEGER_MAX; - } - } - } - - return(AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_cm_walk_package_tree - * - * PARAMETERS: Obj_desc - The Package object on which to resolve refs - * - * RETURN: Status - * - * DESCRIPTION: Walk through a package - * - ******************************************************************************/ - -ACPI_STATUS -acpi_cm_walk_package_tree ( - ACPI_OPERAND_OBJECT *source_object, - void *target_object, - ACPI_PKG_CALLBACK walk_callback, - void *context) -{ - ACPI_STATUS status = AE_OK; - ACPI_GENERIC_STATE *state_list = NULL; - ACPI_GENERIC_STATE *state; - u32 this_index; - ACPI_OPERAND_OBJECT *this_source_obj; - - - state = acpi_cm_create_pkg_state (source_object, target_object, 0); - if (!state) { - return (AE_NO_MEMORY); - } - - while (state) { - this_index = state->pkg.index; - this_source_obj = (ACPI_OPERAND_OBJECT *) - state->pkg.source_object->package.elements[this_index]; - - /* - * Check for - * 1) An uninitialized package element. It is completely - * legal to declare a package and leave it uninitialized - * 2) Not an internal object - can be a namespace node instead - * 3) Any type other than a package. Packages are handled in else case below. - */ - if ((!this_source_obj) || - (!VALID_DESCRIPTOR_TYPE ( - this_source_obj, ACPI_DESC_TYPE_INTERNAL)) || - (!IS_THIS_OBJECT_TYPE ( - this_source_obj, ACPI_TYPE_PACKAGE))) - { - - status = walk_callback (0, this_source_obj, state, context); - if (ACPI_FAILURE (status)) { - /* TBD: must delete package created up to this point */ - - return (status); - } - - state->pkg.index++; - while (state->pkg.index >= state->pkg.source_object->package.count) { - /* - * We've handled all of the objects at this level, This means - * that we have just completed a package. That package may - * have contained one or more packages itself. - * - * Delete this state and pop the previous state (package). - */ - acpi_cm_delete_generic_state (state); - state = acpi_cm_pop_generic_state (&state_list); - - - /* Finished when there are no more states */ - - if (!state) { - /* - * We have handled all of the objects in the top level - * package just add the length of the package objects - * and exit - */ - return (AE_OK); - } - - /* - * Go back up a level and move the index past the just - * completed package object. - */ - state->pkg.index++; - } - } - - else { - /* This is a sub-object of type package */ - - status = walk_callback (1, this_source_obj, state, context); - if (ACPI_FAILURE (status)) { - /* TBD: must delete package created up to this point */ - - return (status); - } - - - /* - * The callback above returned a new target package object. - */ - - /* - * Push the current state and create a new one - */ - acpi_cm_push_generic_state (&state_list, state); - state = acpi_cm_create_pkg_state (this_source_obj, state->pkg.this_target_obj, 0); - if (!state) { - /* TBD: must delete package created up to this point */ - - return (AE_NO_MEMORY); - } - } - } - - /* We should never get here */ - - return (AE_AML_INTERNAL); - -} - - -/******************************************************************************* - * - * FUNCTION: _Report_error - * - * PARAMETERS: Module_name - Caller's module name (for error output) - * Line_number - Caller's line number (for error output) - * Component_id - Caller's component ID (for error output) - * Message - Error message to use on failure - * - * RETURN: None - * - * DESCRIPTION: Print error message - * - ******************************************************************************/ - -void -_report_error ( - NATIVE_CHAR *module_name, - u32 line_number, - u32 component_id) -{ - - - acpi_os_printf ("%8s-%04d: *** Error: ", module_name, line_number); -} - - -/******************************************************************************* - * - * FUNCTION: _Report_warning - * - * PARAMETERS: Module_name - Caller's module name (for error output) - * Line_number - Caller's line number (for error output) - * Component_id - Caller's component ID (for error output) - * Message - Error message to use on failure - * - * RETURN: None - * - * DESCRIPTION: Print warning message - * - ******************************************************************************/ - -void -_report_warning ( - NATIVE_CHAR *module_name, - u32 line_number, - u32 component_id) -{ - - acpi_os_printf ("%8s-%04d: *** Warning: ", module_name, line_number); -} - - -/******************************************************************************* - * - * FUNCTION: _Report_info - * - * PARAMETERS: Module_name - Caller's module name (for error output) - * Line_number - Caller's line number (for error output) - * Component_id - Caller's component ID (for error output) - * Message - Error message to use on failure - * - * RETURN: None - * - * DESCRIPTION: Print information message - * - ******************************************************************************/ - -void -_report_info ( - NATIVE_CHAR *module_name, - u32 line_number, - u32 component_id) -{ - - acpi_os_printf ("%8s-%04d: *** Info: ", module_name, line_number); -} - - diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/common/cmxface.c linux/drivers/acpi/common/cmxface.c --- v2.4.5/linux/drivers/acpi/common/cmxface.c Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/common/cmxface.c Wed Dec 31 16:00:00 1969 @@ -1,396 +0,0 @@ -/****************************************************************************** - * - * Module Name: cmxface - External interfaces for "global" ACPI functions - * $Revision: 64 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "acpi.h" -#include "acevents.h" -#include "achware.h" -#include "acnamesp.h" -#include "acinterp.h" -#include "amlcode.h" -#include "acdebug.h" - - -#define _COMPONENT MISCELLANEOUS - MODULE_NAME ("cmxface") - - -/******************************************************************************* - * - * FUNCTION: Acpi_initialize_subsystem - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Initializes all global variables. This is the first function - * called, so any early initialization belongs here. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_initialize_subsystem ( - void) -{ - ACPI_STATUS status; - - - /* Initialize all globals used by the subsystem */ - - acpi_cm_init_globals (); - - /* Initialize the OS-Dependent layer */ - - status = acpi_os_initialize (); - if (ACPI_FAILURE (status)) { - REPORT_ERROR (("OSD failed to initialize, %s\n", - acpi_cm_format_exception (status))); - return (status); - } - - /* Create the default mutex objects */ - - status = acpi_cm_mutex_initialize (); - if (ACPI_FAILURE (status)) { - REPORT_ERROR (("Global mutex creation failure, %s\n", - acpi_cm_format_exception (status))); - return (status); - } - - /* - * Initialize the namespace manager and - * the root of the namespace tree - */ - - status = acpi_ns_root_initialize (); - if (ACPI_FAILURE (status)) { - REPORT_ERROR (("Namespace initialization failure, %s\n", - acpi_cm_format_exception (status))); - return (status); - } - - - /* If configured, initialize the AML debugger */ - - DEBUGGER_EXEC (acpi_db_initialize ()); - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_enable_subsystem - * - * PARAMETERS: Flags - Init/enable Options - * - * RETURN: Status - * - * DESCRIPTION: Completes the subsystem initialization including hardware. - * Puts system into ACPI mode if it isn't already. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_enable_subsystem ( - u32 flags) -{ - ACPI_STATUS status = AE_OK; - - - /* Sanity check the FADT for valid values */ - - status = acpi_cm_validate_fadt (); - if (ACPI_FAILURE (status)) { - return (status); - } - - /* - * Install the default Op_region handlers. These are - * installed unless other handlers have already been - * installed via the Install_address_space_handler interface - */ - - if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) { - status = acpi_ev_install_default_address_space_handlers (); - if (ACPI_FAILURE (status)) { - return (status); - } - } - - /* - * We must initialize the hardware before we can enable ACPI. - */ - - if (!(flags & ACPI_NO_HARDWARE_INIT)) { - status = acpi_hw_initialize (); - if (ACPI_FAILURE (status)) { - return (status); - } - } - - /* - * Enable ACPI on this platform - */ - - if (!(flags & ACPI_NO_ACPI_ENABLE)) { - status = acpi_enable (); - if (ACPI_FAILURE (status)) { - return (status); - } - } - - /* - * Note: - * We must have the hardware AND events initialized before we can execute - * ANY control methods SAFELY. Any control method can require ACPI hardware - * support, so the hardware MUST be initialized before execution! - */ - - if (!(flags & ACPI_NO_EVENT_INIT)) { - status = acpi_ev_initialize (); - if (ACPI_FAILURE (status)) { - return (status); - } - } - - - /* - * Initialize all device objects in the namespace - * This runs the _STA and _INI methods. - */ - - if (!(flags & ACPI_NO_DEVICE_INIT)) { - status = acpi_ns_initialize_devices (); - if (ACPI_FAILURE (status)) { - return (status); - } - } - - - /* - * Initialize the objects that remain uninitialized. This - * runs the executable AML that is part of the declaration of Op_regions - * and Fields. - */ - - if (!(flags & ACPI_NO_OBJECT_INIT)) { - status = acpi_ns_initialize_objects (); - if (ACPI_FAILURE (status)) { - return (status); - } - } - - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_terminate - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Shutdown the ACPI subsystem. Release all resources. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_terminate (void) -{ - - /* Terminate the AML Debuger if present */ - - DEBUGGER_EXEC(acpi_gbl_db_terminate_threads = TRUE); - - /* TBD: [Investigate] This is no longer needed?*/ -/* Acpi_cm_release_mutex (ACPI_MTX_DEBUG_CMD_READY); */ - - - /* Shutdown and free all resources */ - - acpi_cm_subsystem_shutdown (); - - - /* Free the mutex objects */ - - acpi_cm_mutex_terminate (); - - - /* Now we can shutdown the OS-dependent layer */ - - acpi_os_terminate (); - - return (AE_OK); -} - - -/****************************************************************************** - * - * FUNCTION: Acpi_get_system_info - * - * PARAMETERS: Out_buffer - a pointer to a buffer to receive the - * resources for the device - * Buffer_length - the number of bytes available in the buffer - * - * RETURN: Status - the status of the call - * - * DESCRIPTION: This function is called to get information about the current - * state of the ACPI subsystem. It will return system information - * in the Out_buffer. - * - * If the function fails an appropriate status will be returned - * and the value of Out_buffer is undefined. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_get_system_info ( - ACPI_BUFFER *out_buffer) -{ - ACPI_SYSTEM_INFO *info_ptr; - u32 i; - - - /* - * Must have a valid buffer - */ - if ((!out_buffer) || - (!out_buffer->pointer)) - { - return (AE_BAD_PARAMETER); - } - - if (out_buffer->length < sizeof (ACPI_SYSTEM_INFO)) { - /* - * Caller's buffer is too small - */ - out_buffer->length = sizeof (ACPI_SYSTEM_INFO); - - return (AE_BUFFER_OVERFLOW); - } - - - /* - * Set return length and get data - */ - out_buffer->length = sizeof (ACPI_SYSTEM_INFO); - info_ptr = (ACPI_SYSTEM_INFO *) out_buffer->pointer; - - info_ptr->acpi_ca_version = ACPI_CA_VERSION; - - /* System flags (ACPI capabilities) */ - - info_ptr->flags = acpi_gbl_system_flags; - - /* Timer resolution - 24 or 32 bits */ - if (!acpi_gbl_FADT) { - info_ptr->timer_resolution = 0; - } - else if (acpi_gbl_FADT->tmr_val_ext == 0) { - info_ptr->timer_resolution = 24; - } - else { - info_ptr->timer_resolution = 32; - } - - /* Clear the reserved fields */ - - info_ptr->reserved1 = 0; - info_ptr->reserved2 = 0; - - /* Current debug levels */ - - info_ptr->debug_layer = acpi_dbg_layer; - info_ptr->debug_level = acpi_dbg_level; - - /* Current status of the ACPI tables, per table type */ - - info_ptr->num_table_types = NUM_ACPI_TABLES; - for (i = 0; i < NUM_ACPI_TABLES; i++) { - info_ptr->table_info[i].count = acpi_gbl_acpi_tables[i].count; - } - - return (AE_OK); -} - - -/****************************************************************************** - * - * FUNCTION: Acpi_format_exception - * - * PARAMETERS: Out_buffer - a pointer to a buffer to receive the - * exception name - * - * RETURN: Status - the status of the call - * - * DESCRIPTION: This function translates an ACPI exception into an ASCII string. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_format_exception ( - ACPI_STATUS exception, - ACPI_BUFFER *out_buffer) -{ - u32 length; - NATIVE_CHAR *formatted_exception; - - - /* - * Must have a valid buffer - */ - if ((!out_buffer) || - (!out_buffer->pointer)) - { - return (AE_BAD_PARAMETER); - } - - - /* Convert the exception code (Handles bad exception codes) */ - - formatted_exception = acpi_cm_format_exception (exception); - - /* - * Get length of string and check if it will fit in caller's buffer - */ - - length = STRLEN (formatted_exception); - if (out_buffer->length < length) { - out_buffer->length = length; - return (AE_BUFFER_OVERFLOW); - } - - - /* Copy the string, all done */ - - STRCPY (out_buffer->pointer, formatted_exception); - - return (AE_OK); -} - diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/cpu.c linux/drivers/acpi/cpu.c --- v2.4.5/linux/drivers/acpi/cpu.c Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/cpu.c Wed Dec 31 16:00:00 1969 @@ -1,353 +0,0 @@ -/* - * cpu.c - Processor handling - * - * Copyright (C) 2000 Andrew Henroid - * Copyright (C) 2001 Andrew Grover - * - * 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.h" -#include "driver.h" - -#define _COMPONENT OS_DEPENDENT - MODULE_NAME ("cpu") - -u32 acpi_c2_exit_latency = ACPI_INFINITE; -u32 acpi_c3_exit_latency = ACPI_INFINITE; -u32 acpi_c2_enter_latency = ACPI_INFINITE; -u32 acpi_c3_enter_latency = ACPI_INFINITE; -u32 acpi_use_idle = TRUE; - -u32 acpi_c1_count = 0; -u32 acpi_c2_count = 0; -u32 acpi_c3_count = 0; - -static u32 acpi_pblk = ACPI_INVALID; -static int acpi_c2_tested = 0; -static int acpi_c3_tested = 0; -static int acpi_max_c_state = 1; -static int acpi_pm_tmr_len = 24; - -#define CPU_POWER_STATES 3 -#define MAX_C2_LATENCY 100 -#define MAX_C3_LATENCY 1000 - -#define ACPI_STATE_C1 0 -#define ACPI_STATE_C2 1 -#define ACPI_STATE_C3 2 - -/* - * Clear busmaster activity flag - */ -static inline void -acpi_clear_bm_activity(void) -{ - acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, BM_STS, 1); -} - -/* - * Returns 1 if there has been busmaster activity - */ -static inline int -acpi_bm_activity(void) -{ - return acpi_hw_register_bit_access(ACPI_READ, ACPI_MTX_LOCK, BM_STS); -} - -/* - * Set system to sleep through busmaster requests - */ -static void -acpi_sleep_on_busmaster(void) -{ - acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, BM_RLD, 1); -} - -/* - * Set system to wake on busmaster requests - */ -static void -acpi_wake_on_busmaster(void) -{ - acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, BM_RLD, 0); -} - -u32 -acpi_read_pm_timer(void) -{ - return acpi_hw_register_read(ACPI_MTX_LOCK, PM_TIMER); -} - -/* - * Do a compare, accounting for 24/32bit rollover - */ -static u32 -acpi_compare_pm_timers(u32 first, u32 second) -{ - if (first < second) { - return (second - first); - } else { - if (acpi_pm_tmr_len == 24) - return (second + (0xFFFFFF - first)); - else - return (second + (0xFFFFFFFF - first)); - } -} - - -/* - * Idle loop (uniprocessor only) - */ -static void -acpi_idle(void) -{ - static int sleep_level = 1; - FADT_DESCRIPTOR *fadt = &acpi_fadt; - - /* - * start from the previous sleep level. - * if not initialized, we goto sleep1 - */ - if (sleep_level == 1 - || acpi_max_c_state < 2) - goto sleep1; - - if (sleep_level == 2 - || acpi_max_c_state < 3) - goto sleep2; - -sleep3: - sleep_level = 3; - if (!acpi_c3_tested) { - DEBUG_PRINT(ACPI_INFO, ("C3 works\n")); - acpi_c3_tested = 1; - } - acpi_wake_on_busmaster(); - if (fadt->Xpm2_cnt_blk.address) - goto sleep3_with_arbiter; - - for (;;) { - unsigned long time; - unsigned long diff; - - __cli(); - if (current->need_resched) - goto out; - if (acpi_bm_activity()) - goto sleep2; - - time = acpi_read_pm_timer(); - acpi_c3_count++; - inb(acpi_pblk + ACPI_P_LVL3); - /* Dummy read, force synchronization with the PMU */ - acpi_read_pm_timer(); - diff = acpi_compare_pm_timers(time, acpi_read_pm_timer()); - - __sti(); - if (diff < acpi_c3_exit_latency) - goto sleep1; - } - -sleep3_with_arbiter: - for (;;) { - unsigned long time; - unsigned long diff; - - __cli(); - if (current->need_resched) - goto out; - if (acpi_bm_activity()) - goto sleep2; - - time = acpi_read_pm_timer(); - - /* Disable arbiter, park on CPU */ - acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, ARB_DIS, 1); - acpi_c3_count++; - inb(acpi_pblk + ACPI_P_LVL3); - /* Dummy read, force synchronization with the PMU */ - acpi_read_pm_timer(); - diff = acpi_compare_pm_timers(time, acpi_read_pm_timer()); - /* Enable arbiter again.. */ - acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, ARB_DIS, 0); - - __sti(); - if (diff < acpi_c3_exit_latency) - goto sleep1; - } - -sleep2: - sleep_level = 2; - if (!acpi_c2_tested) { - DEBUG_PRINT(ACPI_INFO, ("C2 works\n")); - acpi_c2_tested = 1; - } - acpi_wake_on_busmaster(); /* Required to track BM activity.. */ - for (;;) { - unsigned long time; - unsigned long diff; - - __cli(); - if (current->need_resched) - goto out; - - time = acpi_read_pm_timer(); - acpi_c2_count++; - inb(acpi_pblk + ACPI_P_LVL2); - /* Dummy read, force synchronization with the PMU */ - acpi_read_pm_timer(); - diff = acpi_compare_pm_timers(time, acpi_read_pm_timer()); - - __sti(); - if (diff < acpi_c2_exit_latency) - goto sleep1; - if (acpi_bm_activity()) { - acpi_clear_bm_activity(); - continue; - } - if (diff > acpi_c3_enter_latency - && acpi_max_c_state >= 3) - goto sleep3; - } - -sleep1: - sleep_level = 1; - acpi_sleep_on_busmaster(); - for (;;) { - unsigned long time; - unsigned long diff; - - __cli(); - if (current->need_resched) - goto out; - time = acpi_read_pm_timer(); - acpi_c1_count++; - safe_halt(); - diff = acpi_compare_pm_timers(time, acpi_read_pm_timer()); - if (diff > acpi_c2_enter_latency - && acpi_max_c_state >= 2) - goto sleep2; - } - -out: - __sti(); -} - -/* - * Get processor information - */ -static ACPI_STATUS -acpi_found_cpu(ACPI_HANDLE handle, u32 level, void *ctx, void **value) -{ - ACPI_OBJECT obj; - ACPI_BUFFER buf; - - buf.length = sizeof(obj); - buf.pointer = &obj; - if (!ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buf))) - return AE_OK; - - DEBUG_PRINT(ACPI_INFO, ("PBLK %d @ 0x%04x:%d\n", - obj.processor.proc_id, - obj.processor.pblk_address, - obj.processor.pblk_length)); - - if (acpi_pblk != ACPI_INVALID - || !obj.processor.pblk_address - || obj.processor.pblk_length != 6) - return AE_OK; - - acpi_pblk = obj.processor.pblk_address; - - if (acpi_fadt.plvl2_lat - && acpi_fadt.plvl2_lat <= MAX_C2_LATENCY) { - acpi_c2_exit_latency - = ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl2_lat); - acpi_c2_enter_latency - = ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl2_lat * 4); - acpi_max_c_state = 2; - - printk(KERN_INFO "ACPI: System firmware supports: C2"); - - if (acpi_fadt.plvl3_lat - && acpi_fadt.plvl3_lat <= MAX_C3_LATENCY) { - acpi_c3_exit_latency - = ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl3_lat); - acpi_c3_enter_latency - = ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl3_lat * 12); - acpi_max_c_state = 3; - - printk(" C3"); - } - - printk("\n"); - } - - printk(KERN_INFO "ACPI: plvl2lat=%d plvl3lat=%d\n", acpi_fadt.plvl2_lat, acpi_fadt.plvl3_lat); - printk(KERN_INFO "ACPI: C2 enter=%d C2 exit=%d\n", acpi_c2_enter_latency, acpi_c2_exit_latency); - printk(KERN_INFO "ACPI: C3 enter=%d C3 exit=%d\n", acpi_c3_enter_latency, acpi_c3_exit_latency); - - return AE_OK; -} - -static int -acpi_pm_timer_init(void) -{ - FADT_DESCRIPTOR *fadt = &acpi_fadt; - - if (fadt->tmr_val_ext) { - acpi_pm_tmr_len = 32; - } else { - acpi_pm_tmr_len = 24; - } - - DEBUG_PRINT(ACPI_INFO, ("PM Timer width: %d bits\n", acpi_pm_tmr_len)); - - return AE_OK; -} - -int -acpi_cpu_init(void) -{ - acpi_walk_namespace(ACPI_TYPE_PROCESSOR, - ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, - acpi_found_cpu, - NULL, - NULL); - - acpi_pm_timer_init(); - - if (acpi_use_idle) { -#ifdef CONFIG_SMP - if (smp_num_cpus == 1) - pm_idle = acpi_idle; -#else - pm_idle = acpi_idle; -#endif - printk(KERN_INFO "ACPI: Using ACPI idle\n"); - printk(KERN_INFO "ACPI: If experiencing system slowness, try adding \"acpi=no-idle\" to cmdline\n"); - } - else { - printk(KERN_INFO "ACPI: Not using ACPI idle\n"); - } - - return 0; -} diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/debugger/dbcmds.c linux/drivers/acpi/debugger/dbcmds.c --- v2.4.5/linux/drivers/acpi/debugger/dbcmds.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/debugger/dbcmds.c Wed Jun 20 17:47:39 2001 @@ -0,0 +1,987 @@ +/******************************************************************************* + * + * Module Name: dbcmds - debug commands and output routines + * $Revision: 60 $ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "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 + +#define _COMPONENT ACPI_DEBUGGER + MODULE_NAME ("dbcmds") + + +/* + * Arguments for the Objects command + * These object types map directly to the ACPI_TYPES + */ + +ARGUMENT_INFO acpi_db_object_types [] = +{ {"ANY"}, + {"NUMBERS"}, + {"STRINGS"}, + {"BUFFERS"}, + {"PACKAGES"}, + {"FIELDS"}, + {"DEVICES"}, + {"EVENTS"}, + {"METHODS"}, + {"MUTEXES"}, + {"REGIONS"}, + {"POWERRESOURCES"}, + {"PROCESSORS"}, + {"THERMALZONES"}, + {"BUFFERFIELDS"}, + {"DDBHANDLES"}, + {NULL} /* Must be null terminated */ +}; + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_walk_for_references + * + * PARAMETERS: Callback from Walk_namespace + * + * RETURN: Status + * + * DESCRIPTION: Check if this namespace object refers to the target object + * that is passed in as the context value. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_db_walk_for_references ( + ACPI_HANDLE obj_handle, + u32 nesting_level, + void *context, + void **return_value) +{ + ACPI_OPERAND_OBJECT *obj_desc = (ACPI_OPERAND_OBJECT *) context; + ACPI_NAMESPACE_NODE *node = (ACPI_NAMESPACE_NODE *) obj_handle; + + + /* 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); + } + + /* Check for match against the object attached to the node */ + + if (node->object == obj_desc) { + acpi_os_printf ("Reference at Node->Object %p [%4.4s]\n", node, &node->name); + } + + /* Check first child for a match */ + /* TBD: [Investigate] probably now obsolete with new datastructure */ + + if (node->child == (void *) obj_desc) { + acpi_os_printf ("Reference at Node->Child %p [%4.4s]\n", node, &node->name); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_find_references + * + * PARAMETERS: Object_arg - String with hex value of the object + * + * RETURN: None + * + * DESCRIPTION: Search namespace for all references to the input object + * + ******************************************************************************/ + +void +acpi_db_find_references ( + NATIVE_CHAR *object_arg) +{ + ACPI_OPERAND_OBJECT *obj_desc; + + + /* Convert string to object pointer */ + + obj_desc = (ACPI_OPERAND_OBJECT *) STRTOUL (object_arg, NULL, 16); + + /* Search all nodes in namespace */ + + acpi_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + acpi_db_walk_for_references, (void *) obj_desc, NULL); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_display_locks + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Display information about internal mutexes. + * + ******************************************************************************/ + +void +acpi_db_display_locks (void) +{ + u32 i; + + + for (i = 0; i < MAX_MTX; i++) { + acpi_os_printf ("%26s : %s\n", acpi_ut_get_mutex_name (i), + acpi_gbl_acpi_mutex_info[i].owner_id == ACPI_MUTEX_NOT_ACQUIRED + ? "Locked" : "Unlocked"); + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_display_table_info + * + * PARAMETERS: Table_arg - String with name of table to be displayed + * + * RETURN: None + * + * DESCRIPTION: Display information about loaded tables. Current + * implementation displays all loaded tables. + * + ******************************************************************************/ + +void +acpi_db_display_table_info ( + NATIVE_CHAR *table_arg) +{ + u32 i; + + + for (i = 0; i < NUM_ACPI_TABLES; i++) { + if (acpi_gbl_acpi_tables[i].pointer) { + acpi_os_printf ("%s at %p length %X\n", acpi_gbl_acpi_table_data[i].name, + acpi_gbl_acpi_tables[i].pointer, acpi_gbl_acpi_tables[i].length); + } + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_unload_acpi_table + * + * PARAMETERS: Table_arg - Name of the table to be unloaded + * Instance_arg - Which instance of the table to unload (if + * there are multiple tables of the same type) + * + * RETURN: Nonde + * + * DESCRIPTION: Unload an ACPI table. + * Instance is not implemented + * + ******************************************************************************/ + +void +acpi_db_unload_acpi_table ( + NATIVE_CHAR *table_arg, + NATIVE_CHAR *instance_arg) +{ + u32 i; + ACPI_STATUS status; + + + /* Search all tables for the target type */ + + for (i = 0; i < NUM_ACPI_TABLES; i++) { + if (!STRNCMP (table_arg, acpi_gbl_acpi_table_data[i].signature, acpi_gbl_acpi_table_data[i].sig_length)) { + /* Found the table, unload it */ + + status = acpi_unload_table (i); + if (ACPI_SUCCESS (status)) { + acpi_os_printf ("[%s] unloaded and uninstalled\n", table_arg); + } + else { + acpi_os_printf ("%s, while unloading [%s]\n", acpi_ut_format_exception (status), table_arg); + } + + return; + } + } + + acpi_os_printf ("Unknown table type [%s]\n", table_arg); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_set_method_breakpoint + * + * PARAMETERS: Location - AML offset of breakpoint + * Walk_state - Current walk info + * Op - Current Op (from parse walk) + * + * RETURN: None + * + * DESCRIPTION: Set a breakpoint in a control method at the specified + * AML offset + * + ******************************************************************************/ + +void +acpi_db_set_method_breakpoint ( + NATIVE_CHAR *location, + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op) +{ + u32 address; + + + if (!op) { + acpi_os_printf ("There is no method currently executing\n"); + return; + } + + /* Get and verify the breakpoint address */ + + address = STRTOUL (location, NULL, 16); + if (address <= op->aml_offset) { + acpi_os_printf ("Breakpoint %X is beyond current address %X\n", address, op->aml_offset); + } + + /* Save breakpoint in current walk */ + + walk_state->method_breakpoint = address; + acpi_os_printf ("Breakpoint set at AML offset %X\n", address); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_set_method_call_breakpoint + * + * PARAMETERS: Op - Current Op (from parse walk) + * + * RETURN: None + * + * DESCRIPTION: Set a breakpoint in a control method at the specified + * AML offset + * + ******************************************************************************/ + +void +acpi_db_set_method_call_breakpoint ( + ACPI_PARSE_OBJECT *op) +{ + + + if (!op) { + acpi_os_printf ("There is no method currently executing\n"); + return; + } + + + acpi_gbl_step_to_next_call = TRUE; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_disassemble_aml + * + * PARAMETERS: Statements - Number of statements to disassemble + * Op - Current Op (from parse walk) + * + * RETURN: None + * + * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number + * of statements specified. + * + ******************************************************************************/ + +void +acpi_db_disassemble_aml ( + NATIVE_CHAR *statements, + ACPI_PARSE_OBJECT *op) +{ + u32 num_statements = 8; + + + if (!op) { + acpi_os_printf ("There is no method currently executing\n"); + return; + } + + if (statements) { + num_statements = STRTOUL (statements, NULL, 0); + } + + + acpi_db_display_op (NULL, op, num_statements); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_dump_namespace + * + * PARAMETERS: Start_arg - Node to begin namespace dump + * Depth_arg - Maximum tree depth to be dumped + * + * RETURN: None + * + * DESCRIPTION: Dump entire namespace or a subtree. Each node is displayed + * with type and other information. + * + ******************************************************************************/ + +void +acpi_db_dump_namespace ( + NATIVE_CHAR *start_arg, + NATIVE_CHAR *depth_arg) +{ + ACPI_HANDLE subtree_entry = acpi_gbl_root_node; + u32 max_depth = ACPI_UINT32_MAX; + + + /* No argument given, just start at the root and dump entire namespace */ + + if (start_arg) { + /* Check if numeric argument, must be a Node */ + + if ((start_arg[0] >= 0x30) && (start_arg[0] <= 0x39)) { + subtree_entry = (ACPI_HANDLE) STRTOUL (start_arg, NULL, 16); + if (!acpi_os_readable (subtree_entry, sizeof (ACPI_NAMESPACE_NODE))) { + acpi_os_printf ("Address %p is invalid in this address space\n", subtree_entry); + return; + } + + if (!VALID_DESCRIPTOR_TYPE ((subtree_entry), ACPI_DESC_TYPE_NAMED)) { + acpi_os_printf ("Address %p is not a valid Named object\n", subtree_entry); + return; + } + } + + /* Alpha argument */ + + else { + /* The parameter is a name string that must be resolved to a Named obj*/ + + subtree_entry = acpi_db_local_ns_lookup (start_arg); + if (!subtree_entry) { + subtree_entry = acpi_gbl_root_node; + } + } + + /* Now we can check for the depth argument */ + + if (depth_arg) { + max_depth = STRTOUL (depth_arg, NULL, 0); + } + } + + + acpi_db_set_output_destination (DB_DUPLICATE_OUTPUT); + acpi_os_printf ("ACPI Namespace (from %p subtree):\n", subtree_entry); + + /* Display the subtree */ + + acpi_db_set_output_destination (DB_REDIRECTABLE_OUTPUT); + acpi_ns_dump_objects (ACPI_TYPE_ANY, max_depth, ACPI_UINT32_MAX, subtree_entry); + acpi_db_set_output_destination (DB_CONSOLE_OUTPUT); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_dump_namespace_by_owner + * + * PARAMETERS: Owner_arg - Owner ID whose nodes will be displayed + * Depth_arg - Maximum tree depth to be dumped + * + * RETURN: None + * + * DESCRIPTION: Dump elements of the namespace that are owned by the Owner_id. + * + ******************************************************************************/ + +void +acpi_db_dump_namespace_by_owner ( + NATIVE_CHAR *owner_arg, + NATIVE_CHAR *depth_arg) +{ + ACPI_HANDLE subtree_entry = acpi_gbl_root_node; + u32 max_depth = ACPI_UINT32_MAX; + u16 owner_id; + + + owner_id = (u16) STRTOUL (owner_arg, NULL, 0); + + + /* Now we can check for the depth argument */ + + if (depth_arg) { + max_depth = STRTOUL (depth_arg, NULL, 0); + } + + + acpi_db_set_output_destination (DB_DUPLICATE_OUTPUT); + acpi_os_printf ("ACPI Namespace by owner %X:\n", owner_id); + + /* Display the subtree */ + + acpi_db_set_output_destination (DB_REDIRECTABLE_OUTPUT); + acpi_ns_dump_objects (ACPI_TYPE_ANY, max_depth, owner_id, subtree_entry); + acpi_db_set_output_destination (DB_CONSOLE_OUTPUT); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_send_notify + * + * PARAMETERS: Name - Name of ACPI object to send the notify to + * Value - Value of the notify to send. + * + * RETURN: None + * + * DESCRIPTION: Send an ACPI notification. The value specified is sent to the + * named object as an ACPI notify. + * + ******************************************************************************/ + +void +acpi_db_send_notify ( + NATIVE_CHAR *name, + u32 value) +{ + ACPI_NAMESPACE_NODE *node; + + + /* Translate name to an Named object */ + + node = acpi_db_local_ns_lookup (name); + if (!node) { + return; + } + + /* Decode Named object type */ + + switch (node->type) { + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_THERMAL: + + /* Send the notify */ + + acpi_ev_queue_notify_request (node, value); + break; + + default: + acpi_os_printf ("Named object is not a device or a thermal object\n"); + break; + } + +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_set_method_data + * + * PARAMETERS: Type_arg - L for local, A for argument + * Index_arg - which one + * Value_arg - Value to set. + * + * RETURN: None + * + * DESCRIPTION: Set a local or argument for the running control method. + * NOTE: only object supported is Number. + * + ******************************************************************************/ + +void +acpi_db_set_method_data ( + NATIVE_CHAR *type_arg, + NATIVE_CHAR *index_arg, + NATIVE_CHAR *value_arg) +{ + NATIVE_CHAR type; + u32 index; + u32 value; + ACPI_WALK_STATE *walk_state; + ACPI_OPERAND_OBJECT *obj_desc; + + + /* Validate Type_arg */ + + STRUPR (type_arg); + type = type_arg[0]; + if ((type != 'L') && + (type != 'A')) { + acpi_os_printf ("Invalid SET operand: %s\n", type_arg); + return; + } + + /* Get the index and value */ + + index = STRTOUL (index_arg, NULL, 16); + value = STRTOUL (value_arg, NULL, 16); + + walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list); + if (!walk_state) { + acpi_os_printf ("There is no method currently executing\n"); + return; + } + + + /* Create and initialize the new object */ + + obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); + if (!obj_desc) { + acpi_os_printf ("Could not create an internal object\n"); + return; + } + + obj_desc->integer.value = value; + + + /* Store the new object into the target */ + + switch (type) { + case 'A': + + /* Set a method argument */ + + if (index > MTH_NUM_ARGS) { + 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); + obj_desc = walk_state->arguments[index].object; + + acpi_os_printf ("Arg%d: ", index); + acpi_db_display_internal_object (obj_desc, walk_state); + break; + + case 'L': + + /* Set a method local */ + + if (index > MTH_NUM_LOCALS) { + 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); + obj_desc = walk_state->local_variables[index].object; + + acpi_os_printf ("Local%d: ", index); + acpi_db_display_internal_object (obj_desc, walk_state); + break; + + default: + break; + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_walk_for_specific_objects + * + * PARAMETERS: Callback from Walk_namespace + * + * RETURN: Status + * + * DESCRIPTION: Display short info about objects in the namespace + * + ******************************************************************************/ + +ACPI_STATUS +acpi_db_walk_for_specific_objects ( + ACPI_HANDLE obj_handle, + u32 nesting_level, + void *context, + void **return_value) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_STATUS status; + u32 buf_size; + NATIVE_CHAR buffer[64]; + + + obj_desc = ((ACPI_NAMESPACE_NODE *)obj_handle)->object; + buf_size = sizeof (buffer) / sizeof (*buffer); + + /* Get and display the full pathname to this object */ + + status = acpi_ns_handle_to_pathname (obj_handle, &buf_size, buffer); + + if (ACPI_FAILURE (status)) { + acpi_os_printf ("Could Not get pathname for object %p\n", obj_handle); + return (AE_OK); + } + + acpi_os_printf ("%32s", buffer); + + + /* Display short information about the object */ + + if (obj_desc) { + switch (obj_desc->common.type) { + case ACPI_TYPE_METHOD: + acpi_os_printf (" #Args %d Concurrency %X", obj_desc->method.param_count, obj_desc->method.concurrency); + break; + + case ACPI_TYPE_INTEGER: + acpi_os_printf (" Value %X", obj_desc->integer.value); + break; + + case ACPI_TYPE_STRING: + acpi_os_printf (" \"%s\"", obj_desc->string.pointer); + break; + + case ACPI_TYPE_REGION: + acpi_os_printf (" Space_id %X Address %X Length %X", obj_desc->region.space_id, obj_desc->region.address, obj_desc->region.length); + break; + + case ACPI_TYPE_PACKAGE: + acpi_os_printf (" #Elements %X", obj_desc->package.count); + break; + + case ACPI_TYPE_BUFFER: + acpi_os_printf (" Length %X", obj_desc->buffer.length); + break; + } + } + + acpi_os_printf ("\n"); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_display_objects + * + * PARAMETERS: Obj_type_arg - Type of object to display + * Display_count_arg - Max depth to display + * + * RETURN: None + * + * DESCRIPTION: Display objects in the namespace of the requested type + * + ******************************************************************************/ + +ACPI_STATUS +acpi_db_display_objects ( + NATIVE_CHAR *obj_type_arg, + NATIVE_CHAR *display_count_arg) +{ + ACPI_OBJECT_TYPE8 type; + + + /* Get the object type */ + + type = acpi_db_match_argument (obj_type_arg, acpi_db_object_types); + if (type == ACPI_TYPE_NOT_FOUND) { + acpi_os_printf ("Invalid or unsupported argument\n"); + return (AE_OK); + } + + acpi_db_set_output_destination (DB_DUPLICATE_OUTPUT); + acpi_os_printf ("Objects of type [%s] defined in the current ACPI Namespace: \n", acpi_ut_get_type_name (type)); + + acpi_db_set_output_destination (DB_REDIRECTABLE_OUTPUT); + + /* Walk the namespace from the root */ + + acpi_walk_namespace (type, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + acpi_db_walk_for_specific_objects, (void *) &type, NULL); + + acpi_db_set_output_destination (DB_CONSOLE_OUTPUT); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_walk_and_match_name + * + * PARAMETERS: Callback from Walk_namespace + * + * RETURN: Status + * + * DESCRIPTION: Find a particular name/names within the namespace. Wildcards + * are supported -- '?' matches any character. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_db_walk_and_match_name ( + ACPI_HANDLE obj_handle, + u32 nesting_level, + void *context, + void **return_value) +{ + ACPI_STATUS status; + NATIVE_CHAR *requested_name = (NATIVE_CHAR *) context; + u32 i; + u32 buf_size; + NATIVE_CHAR buffer[96]; + + + /* Check for a name match */ + + for (i = 0; i < 4; i++) { + /* Wildcard support */ + + if ((requested_name[i] != '?') && + (requested_name[i] != ((NATIVE_CHAR *) (&((ACPI_NAMESPACE_NODE *) obj_handle)->name))[i])) { + /* No match, just exit */ + + return (AE_OK); + } + } + + + /* Get the full pathname to this object */ + + buf_size = sizeof (buffer) / sizeof (*buffer); + + status = acpi_ns_handle_to_pathname (obj_handle, &buf_size, buffer); + if (ACPI_FAILURE (status)) { + acpi_os_printf ("Could Not get pathname for object %p\n", obj_handle); + } + + else { + acpi_os_printf ("%32s (%p) - %s\n", buffer, obj_handle, + acpi_ut_get_type_name (((ACPI_NAMESPACE_NODE *) obj_handle)->type)); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_find_name_in_namespace + * + * PARAMETERS: Name_arg - The 4-character ACPI name to find. + * wildcards are supported. + * + * RETURN: None + * + * DESCRIPTION: Search the namespace for a given name (with wildcards) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_db_find_name_in_namespace ( + NATIVE_CHAR *name_arg) +{ + + if (STRLEN (name_arg) > 4) { + acpi_os_printf ("Name must be no longer than 4 characters\n"); + return (AE_OK); + } + + /* Walk the namespace from the root */ + + 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 (DB_CONSOLE_OUTPUT); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_set_scope + * + * PARAMETERS: Name - New scope path + * + * RETURN: Status + * + * DESCRIPTION: Set the "current scope" as maintained by this utility. + * The scope is used as a prefix to ACPI paths. + * + ******************************************************************************/ + +void +acpi_db_set_scope ( + NATIVE_CHAR *name) +{ + + if (!name || name[0] == 0) { + acpi_os_printf ("Current scope: %s\n", scope_buf); + return; + } + + acpi_db_prep_namestring (name); + + /* TBD: [Future] Validate scope here */ + + if (name[0] == '\\') { + STRCPY (scope_buf, name); + STRCAT (scope_buf, "\\"); + } + + else { + STRCAT (scope_buf, name); + STRCAT (scope_buf, "\\"); + } + + acpi_os_printf ("New scope: %s\n", scope_buf); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_display_resources + * + * PARAMETERS: Object_arg - String with hex value of the object + * + * RETURN: None + * + * DESCRIPTION: + * + ******************************************************************************/ + +void +acpi_db_display_resources ( + NATIVE_CHAR *object_arg) +{ +#ifndef _IA16 + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_STATUS status; + ACPI_BUFFER return_obj; + + + acpi_db_set_output_destination (DB_REDIRECTABLE_OUTPUT); + + /* Convert string to object pointer */ + + obj_desc = (ACPI_OPERAND_OBJECT *) STRTOUL (object_arg, NULL, 16); + + /* Prepare for a return object of arbitrary size */ + + return_obj.pointer = buffer; + return_obj.length = BUFFER_SIZE; + + /* _PRT */ + + acpi_os_printf ("Evaluating _PRT\n"); + + status = acpi_evaluate_object (obj_desc, "_PRT", NULL, &return_obj); + if (ACPI_FAILURE (status)) { + acpi_os_printf ("Could not obtain _PRT: %s\n", acpi_ut_format_exception (status)); + goto go_cRS; + } + + return_obj.pointer = buffer; + return_obj.length = BUFFER_SIZE; + + status = acpi_get_irq_routing_table (obj_desc, &return_obj); + if (ACPI_FAILURE (status)) { + acpi_os_printf ("Get_irq_routing_table failed: %s\n", acpi_ut_format_exception (status)); + goto go_cRS; + } + + + acpi_rs_dump_irq_list((u8 *)buffer); + + /* _CRS */ +go_cRS: + acpi_os_printf ("Evaluating _CRS\n"); + + return_obj.pointer = buffer; + return_obj.length = BUFFER_SIZE; + + status = acpi_evaluate_object (obj_desc, "_CRS", NULL, &return_obj); + if (ACPI_FAILURE (status)) { + acpi_os_printf ("Could not obtain _CRS: %s\n", acpi_ut_format_exception (status)); + goto go_pRS; + } + + return_obj.pointer = buffer; + return_obj.length = BUFFER_SIZE; + + status = acpi_get_current_resources (obj_desc, &return_obj); + if (ACPI_FAILURE (status)) { + acpi_os_printf ("Acpi_get_current_resources failed: %s\n", acpi_ut_format_exception (status)); + goto go_pRS; + } + + acpi_rs_dump_resource_list ((ACPI_RESOURCE *) buffer); + + /* _PRS */ +go_pRS: + acpi_os_printf ("Evaluating _PRS\n"); + + return_obj.pointer = buffer; + return_obj.length = BUFFER_SIZE; + + status = acpi_evaluate_object (obj_desc, "_PRS", NULL, &return_obj); + if (ACPI_FAILURE (status)) { + acpi_os_printf ("Could not obtain _PRS: %s\n", acpi_ut_format_exception (status)); + goto cleanup; + } + + return_obj.pointer = buffer; + return_obj.length = BUFFER_SIZE; + + status = acpi_get_possible_resources (obj_desc, &return_obj); + if (ACPI_FAILURE (status)) { + acpi_os_printf ("Acpi_get_possible_resources failed: %s\n", acpi_ut_format_exception (status)); + goto cleanup; + } + + acpi_rs_dump_resource_list ((ACPI_RESOURCE *) buffer); + + +cleanup: + + acpi_db_set_output_destination (DB_CONSOLE_OUTPUT); + return; +#endif + +} + + +#endif /* ENABLE_DEBUGGER */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/debugger/dbdisasm.c linux/drivers/acpi/debugger/dbdisasm.c --- v2.4.5/linux/drivers/acpi/debugger/dbdisasm.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/debugger/dbdisasm.c Wed Jun 20 17:47:39 2001 @@ -0,0 +1,674 @@ +/******************************************************************************* + * + * Module Name: dbdisasm - parser op tree display routines + * $Revision: 40 $ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acparser.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "acdebug.h" + + +#ifdef ENABLE_DEBUGGER + +#define _COMPONENT ACPI_DEBUGGER + MODULE_NAME ("dbdisasm") + + +#define MAX_SHOW_ENTRY 128 +#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] " + + +NATIVE_CHAR *INDENT_STRING = "...."; + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_block_type + * + * PARAMETERS: Op - Object to be examined + * + * RETURN: Status + * + * DESCRIPTION: Type of block for this op (parens or braces) + * + ******************************************************************************/ + +u32 +acpi_db_block_type ( + ACPI_PARSE_OBJECT *op) +{ + + switch (op->opcode) { + case AML_METHOD_OP: + return (BLOCK_BRACE); + break; + + default: + break; + } + + return (BLOCK_PAREN); + +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_display_object_pathname + * + * PARAMETERS: Op - Object whose pathname is to be obtained + * + * RETURN: Status + * + * DESCRIPTION: Diplay the pathname associated with a named object. Two + * versions. One searches the parse tree (for parser-only + * applications suchas Acpi_dump), and the other searches the + * ACPI namespace (the parse tree is probably deleted) + * + ******************************************************************************/ + +#ifdef PARSER_ONLY + +ACPI_STATUS +acpi_ps_display_object_pathname ( + ACPI_PARSE_OBJECT *op) +{ + ACPI_PARSE_OBJECT *target_op; + + + /* Search parent tree up to the root if necessary */ + + target_op = acpi_ps_find (op, op->value.name, 0, 0); + if (!target_op) { + /* + * Didn't find the name in the parse tree. This may be + * a problem, or it may simply be one of the predefined names + * (such as _OS_). Rather than worry about looking up all + * the predefined names, just display the name as given + */ + + acpi_os_printf (" **** Path not found in parse tree"); + } + + else { + /* The target was found, print the name and complete path */ + + acpi_os_printf (" (Path "); + acpi_db_display_path (target_op); + acpi_os_printf (")"); + } + + return (AE_OK); +} + +#else + +ACPI_STATUS +acpi_ps_display_object_pathname ( + ACPI_PARSE_OBJECT *op) +{ + ACPI_STATUS status; + ACPI_NAMESPACE_NODE *node; + NATIVE_CHAR buffer[MAX_SHOW_ENTRY]; + u32 buffer_size = MAX_SHOW_ENTRY; + + + acpi_os_printf (" (Path "); + + /* Just get the Node out of the Op object */ + + node = op->node; + if (!node) { + /* + * No Named obj, so we can't get the pathname since the object + * is not in the namespace. This can happen during single + * stepping where a dynamic named object is *about* to be created. + */ + return (AE_OK); + } + + /* Convert Named_desc/handle to a full pathname */ + + status = acpi_ns_handle_to_pathname (node, &buffer_size, buffer); + if (ACPI_FAILURE (status)) { + acpi_os_printf ("****Could not get pathname****)"); + return (status); + } + + acpi_os_printf ("%s)", buffer); + return (AE_OK); +} + +#endif + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_display_op + * + * PARAMETERS: Origin - Starting object + * Num_opcodes - Max number of opcodes to be displayed + * + * RETURN: None + * + * DESCRIPTION: Display parser object and its children + * + ******************************************************************************/ + +void +acpi_db_display_op ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *origin, + u32 num_opcodes) +{ + ACPI_PARSE_OBJECT *op = origin; + ACPI_PARSE_OBJECT *arg; + ACPI_PARSE_OBJECT *depth; + u32 depth_count = 0; + u32 last_depth = 0; + u32 i; + u32 j; + + + if (op) { + while (op) { + /* indentation */ + + depth_count = 0; + if (!opt_verbose) { + depth_count++; + } + + /* Determine the nesting depth of this argument */ + + for (depth = op->parent; depth; depth = depth->parent) { + arg = acpi_ps_get_arg (depth, 0); + while (arg && arg != origin) { + arg = arg->next; + } + + if (arg) { + break; + } + + depth_count++; + } + + + /* Open a new block if we are nested further than last time */ + + if (depth_count > last_depth) { + VERBOSE_PRINT ((DB_NO_OP_INFO, last_depth)); + for (i = 0; i < last_depth; i++) { + acpi_os_printf (INDENT_STRING); + } + + if (acpi_db_block_type (op) == BLOCK_PAREN) { + acpi_os_printf ("(\n"); + } + else { + acpi_os_printf ("{\n"); + } + } + + /* 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++) { + acpi_os_printf (INDENT_STRING); + } + + if (acpi_db_block_type (op) == BLOCK_PAREN) { + acpi_os_printf (")\n"); + } + else { + acpi_os_printf ("}\n"); + } + } + } + + /* 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)); + + + /* Indent the output according to the depth count */ + + for (i = 0; i < depth_count; i++) { + acpi_os_printf (INDENT_STRING); + } + + + /* Now print the opcode */ + + acpi_db_display_opcode (walk_state, op); + + /* Resolve a name reference */ + + if ((op->opcode == AML_INT_NAMEPATH_OP && op->value.name) && + (op->parent) && + (opt_verbose)) { + acpi_ps_display_object_pathname (op); + } + + acpi_os_printf ("\n"); + + /* Get the next node in the tree */ + + op = acpi_ps_get_depth_next (origin, op); + last_depth = depth_count; + + num_opcodes--; + if (!num_opcodes) { + op = NULL; + } + } + + /* Close the last block(s) */ + + depth_count = last_depth -1; + for (i = 0; i < last_depth; i++) { + VERBOSE_PRINT ((DB_NO_OP_INFO, last_depth - i)); + for (j = 0; j < depth_count; j++) { + acpi_os_printf (INDENT_STRING); + } + acpi_os_printf ("}\n"); + depth_count--; + } + + } + + else { + acpi_db_display_opcode (walk_state, op); + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_display_namestring + * + * PARAMETERS: Name - ACPI Name string to store + * + * RETURN: None + * + * DESCRIPTION: Display namestring. Handles prefix characters + * + ******************************************************************************/ + +void +acpi_db_display_namestring ( + NATIVE_CHAR *name) +{ + u32 seg_count; + u8 do_dot = FALSE; + + + if (!name) { + acpi_os_printf (""); + return; + } + + if (acpi_ps_is_prefix_char (GET8 (name))) { + /* append prefix character */ + + acpi_os_printf ("%1c", GET8 (name)); + name++; + } + + switch (GET8 (name)) { + case AML_DUAL_NAME_PREFIX: + seg_count = 2; + name++; + break; + + case AML_MULTI_NAME_PREFIX_OP: + seg_count = (u32) GET8 (name + 1); + name += 2; + break; + + default: + seg_count = 1; + break; + } + + while (seg_count--) { + /* append Name segment */ + + if (do_dot) { + /* append dot */ + + acpi_os_printf ("."); + } + + acpi_os_printf ("%4.4s", name); + do_dot = TRUE; + + name += 4; + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_display_path + * + * PARAMETERS: Op - Named Op whose path is to be constructed + * + * RETURN: None + * + * DESCRIPTION: Walk backwards from current scope and display the name + * of each previous level of scope up to the root scope + * (like "pwd" does with file systems) + * + ******************************************************************************/ + +void +acpi_db_display_path ( + ACPI_PARSE_OBJECT *op) +{ + ACPI_PARSE_OBJECT *prev; + ACPI_PARSE_OBJECT *search; + u32 name; + u8 do_dot = FALSE; + ACPI_PARSE_OBJECT *name_path; + + + /* We are only interested in named objects */ + + if (!acpi_ps_is_node_op (op->opcode)) { + return; + } + + + if (acpi_ps_is_create_field_op (op->opcode)) { + /* Field creation - check for a fully qualified namepath */ + + if (op->opcode == AML_CREATE_FIELD_OP) { + name_path = acpi_ps_get_arg (op, 3); + } + else { + name_path = acpi_ps_get_arg (op, 2); + } + + if ((name_path) && + (name_path->value.string) && + (name_path->value.string[0] == '\\')) { + acpi_db_display_namestring (name_path->value.string); + return; + } + } + + prev = NULL; /* Start with Root Node */ + + while (prev != op) { + /* Search upwards in the tree to find scope with "prev" as its parent */ + + search = op; + for (; ;) { + if (search->parent == prev) { + break; + } + + /* Go up one level */ + + search = search->parent; + } + + if (prev && !acpi_ps_is_field_op (search->opcode)) { + /* below root scope, append scope name */ + + if (do_dot) { + /* append dot */ + + acpi_os_printf ("."); + } + + if (acpi_ps_is_create_field_op (search->opcode)) { + if (op->opcode == AML_CREATE_FIELD_OP) { + name_path = acpi_ps_get_arg (op, 3); + } + else { + name_path = acpi_ps_get_arg (op, 2); + } + + if ((name_path) && + (name_path->value.string)) { + acpi_os_printf ("%4.4s", name_path->value.string); + } + } + + else { + name = acpi_ps_get_name (search); + acpi_os_printf ("%4.4s", &name); + } + + do_dot = TRUE; + } + + prev = search; + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_display_opcode + * + * PARAMETERS: Op - Op that is to be printed + * + * RETURN: Status + * + * DESCRIPTION: Store printed op in a Buffer and return its length + * (or -1 if out of space) + * + * NOTE: Terse mode prints out ASL-like code. Verbose mode adds more info. + * + ******************************************************************************/ + +void +acpi_db_display_opcode ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op) +{ + u8 *byte_data; + u32 byte_count; + u32 i; + ACPI_OPCODE_INFO *opc = NULL; + u32 name; + + + if (!op) { + acpi_os_printf (""); + } + + + /* op and arguments */ + + switch (op->opcode) { + + case AML_BYTE_OP: + + if (opt_verbose) { + acpi_os_printf ("(u8) 0x%2.2X", op->value.integer & ACPI_UINT8_MAX); + } + + else { + acpi_os_printf ("0x%2.2X", op->value.integer & ACPI_UINT8_MAX); + } + + break; + + + case AML_WORD_OP: + + if (opt_verbose) { + acpi_os_printf ("(u16) 0x%4.4X", op->value.integer & ACPI_UINT16_MAX); + } + + else { + acpi_os_printf ("0x%4.4X", op->value.integer & ACPI_UINT16_MAX); + } + + break; + + + case AML_DWORD_OP: + + if (opt_verbose) { + acpi_os_printf ("(u32) 0x%8.8X", op->value.integer); + } + + else { + acpi_os_printf ("0x%8.8X", op->value.integer); + } + + break; + + + case AML_STRING_OP: + + if (op->value.string) { + acpi_os_printf ("\"%s\"", op->value.string); + } + + else { + acpi_os_printf ("<\"NULL STRING PTR\">"); + } + + break; + + + case AML_INT_STATICSTRING_OP: + + if (op->value.string) { + acpi_os_printf ("\"%s\"", op->value.string); + } + + else { + acpi_os_printf ("\"\""); + } + + break; + + + case AML_INT_NAMEPATH_OP: + + acpi_db_display_namestring (op->value.name); + break; + + + case AML_INT_NAMEDFIELD_OP: + + acpi_os_printf ("Named_field (Length 0x%8.8X) ", op->value.integer); + break; + + + case AML_INT_RESERVEDFIELD_OP: + + acpi_os_printf ("Reserved_field (Length 0x%8.8X) ", op->value.integer); + break; + + + case AML_INT_ACCESSFIELD_OP: + + acpi_os_printf ("Access_field (Length 0x%8.8X) ", op->value.integer); + break; + + + case AML_INT_BYTELIST_OP: + + if (opt_verbose) { + acpi_os_printf ("Byte_list (Length 0x%8.8X) ", op->value.integer); + } + + else { + acpi_os_printf ("0x%2.2X", op->value.integer); + + byte_count = op->value.integer; + byte_data = ((ACPI_PARSE2_OBJECT *) op)->data; + + for (i = 0; i < byte_count; i++) { + acpi_os_printf (", 0x%2.2X", byte_data[i]); + } + } + + break; + + + default: + + /* Just get the opcode name and print it */ + + opc = acpi_ps_get_opcode_info (op->opcode); + acpi_os_printf ("%s", opc->name); + + +#ifndef PARSER_ONLY + if ((op->opcode == AML_INT_RETURN_VALUE_OP) && + (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]); + } +#endif + + break; + } + + + if (!opc) { + /* If there is another element in the list, add a comma */ + + if (op->next) { + acpi_os_printf (","); + } + } + + + /* + * If this is a named opcode, print the associated name value + */ + + if (op && acpi_ps_is_named_op (op->opcode)) { + name = acpi_ps_get_name (op); + acpi_os_printf (" %4.4s", &name); + + if (opt_verbose) { + acpi_os_printf (" (Path \\"); + acpi_db_display_path (op); + acpi_os_printf (")"); + } + } +} + + +#endif /* ENABLE_DEBUGGER */ + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/debugger/dbdisply.c linux/drivers/acpi/debugger/dbdisply.c --- v2.4.5/linux/drivers/acpi/debugger/dbdisply.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/debugger/dbdisply.c Wed Jun 20 17:47:39 2001 @@ -0,0 +1,780 @@ +/******************************************************************************* + * + * Module Name: dbdisply - debug display commands + * $Revision: 45 $ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "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" + + +#ifdef ENABLE_DEBUGGER + + +#define _COMPONENT ACPI_DEBUGGER + MODULE_NAME ("dbdisply") + + +/****************************************************************************** + * + * FUNCTION: Acpi_db_get_pointer + * + * PARAMETERS: Target - Pointer to string to be converted + * + * RETURN: Converted pointer + * + * DESCRIPTION: Convert an ascii pointer value to a real value + * + *****************************************************************************/ + +void * +acpi_db_get_pointer ( + void *target) +{ + void *obj_ptr; + + +#ifdef _IA16 +#include + + /* Have to handle 16-bit pointers of the form segment:offset */ + + if (!sscanf (target, "%p", &obj_ptr)) { + acpi_os_printf ("Invalid pointer: %s\n", target); + return (NULL); + } + +#else + + /* Simple flat pointer */ + + obj_ptr = (void *) STRTOUL (target, NULL, 16); + +#endif + + return (obj_ptr); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_dump_parser_descriptor + * + * PARAMETERS: Op - A parser Op descriptor + * + * RETURN: None + * + * DESCRIPTION: Display a formatted parser object + * + ******************************************************************************/ + +void +acpi_db_dump_parser_descriptor ( + ACPI_PARSE_OBJECT *op) +{ + ACPI_OPCODE_INFO *info; + + + info = acpi_ps_get_opcode_info (op->opcode); + + acpi_os_printf ("Parser Op Descriptor:\n"); + acpi_os_printf ("%20.20s : %4.4X\n", "Opcode", op->opcode); + + 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); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_decode_and_display_object + * + * PARAMETERS: Target - String with object to be displayed. Names + * and hex pointers are supported. + * Output_type - Byte, Word, Dword, or Qword (B|W|D|Q) + * + * RETURN: None + * + * DESCRIPTION: Display a formatted ACPI object + * + ******************************************************************************/ + +void +acpi_db_decode_and_display_object ( + NATIVE_CHAR *target, + NATIVE_CHAR *output_type) +{ + void *obj_ptr; + ACPI_NAMESPACE_NODE *node; + u32 display = DB_BYTE_DISPLAY; + NATIVE_CHAR buffer[80]; + ACPI_BUFFER ret_buf; + ACPI_STATUS status; + u32 size; + + + if (!target) { + return; + } + + /* Decode the output type */ + + if (output_type) { + STRUPR (output_type); + if (output_type[0] == 'W') { + display = DB_WORD_DISPLAY; + } + else if (output_type[0] == 'D') { + display = DB_DWORD_DISPLAY; + } + else if (output_type[0] == 'Q') { + display = DB_QWORD_DISPLAY; + } + } + + + ret_buf.length = sizeof (buffer); + ret_buf.pointer = buffer; + + /* Differentiate between a number and a name */ + + if ((target[0] >= 0x30) && (target[0] <= 0x39)) { + obj_ptr = acpi_db_get_pointer (target); + if (!acpi_os_readable (obj_ptr, 16)) { + acpi_os_printf ("Address %p is invalid in this address space\n", obj_ptr); + return; + } + + /* Decode the object type */ + + if (VALID_DESCRIPTOR_TYPE ((obj_ptr), ACPI_DESC_TYPE_NAMED)) { + /* This is a Node */ + + if (!acpi_os_readable (obj_ptr, sizeof (ACPI_NAMESPACE_NODE))) { + acpi_os_printf ("Cannot read entire Named object at address %p\n", obj_ptr); + return; + } + + node = obj_ptr; + goto dump_nte; + } + + else if (VALID_DESCRIPTOR_TYPE ((obj_ptr), ACPI_DESC_TYPE_INTERNAL)) { + /* This is an ACPI OBJECT */ + + if (!acpi_os_readable (obj_ptr, sizeof (ACPI_OPERAND_OBJECT))) { + acpi_os_printf ("Cannot read entire ACPI object at address %p\n", obj_ptr); + return; + } + + acpi_ut_dump_buffer (obj_ptr, sizeof (ACPI_OPERAND_OBJECT), display, ACPI_UINT32_MAX); + acpi_ex_dump_object_descriptor (obj_ptr, 1); + } + + else if (VALID_DESCRIPTOR_TYPE ((obj_ptr), ACPI_DESC_TYPE_PARSER)) { + /* This is an Parser Op object */ + + if (!acpi_os_readable (obj_ptr, sizeof (ACPI_PARSE_OBJECT))) { + acpi_os_printf ("Cannot read entire Parser object at address %p\n", obj_ptr); + return; + } + + + acpi_ut_dump_buffer (obj_ptr, sizeof (ACPI_PARSE_OBJECT), display, ACPI_UINT32_MAX); + acpi_db_dump_parser_descriptor ((ACPI_PARSE_OBJECT *) obj_ptr); + } + + else { + size = 16; + if (acpi_os_readable (obj_ptr, 64)) { + size = 64; + } + + /* Just dump some memory */ + + acpi_ut_dump_buffer (obj_ptr, size, display, ACPI_UINT32_MAX); + } + + return; + } + + + /* The parameter is a name string that must be resolved to a Named obj */ + + node = acpi_db_local_ns_lookup (target); + if (!node) { + return; + } + + +dump_nte: + /* Now dump the Named obj */ + + status = acpi_get_name (node, ACPI_FULL_PATHNAME, &ret_buf); + if (ACPI_FAILURE (status)) { + acpi_os_printf ("Could not convert name to pathname\n"); + } + + else { + acpi_os_printf ("Object Pathname: %s\n", ret_buf.pointer); + } + + if (!acpi_os_readable (node, sizeof (ACPI_NAMESPACE_NODE))) { + acpi_os_printf ("Invalid Named object at address %p\n", node); + return; + } + + acpi_ut_dump_buffer ((void *) node, sizeof (ACPI_NAMESPACE_NODE), display, ACPI_UINT32_MAX); + acpi_ex_dump_node (node, 1); + + if (node->object) { + acpi_os_printf ("\n_attached Object (%p):\n", node->object); + if (!acpi_os_readable (node->object, sizeof (ACPI_OPERAND_OBJECT))) { + acpi_os_printf ("Invalid internal ACPI Object at address %p\n", node->object); + return; + } + + acpi_ut_dump_buffer (node->object, sizeof (ACPI_OPERAND_OBJECT), display, ACPI_UINT32_MAX); + acpi_ex_dump_object_descriptor (node->object, 1); + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_decode_internal_object + * + * PARAMETERS: Obj_desc - Object to be displayed + * + * RETURN: None + * + * DESCRIPTION: Short display of an internal object. Numbers and Strings. + * + ******************************************************************************/ + +void +acpi_db_decode_internal_object ( + ACPI_OPERAND_OBJECT *obj_desc) +{ + u32 i; + + + if (!obj_desc) { + return; + } + + acpi_os_printf (" %s", acpi_ut_get_type_name (obj_desc->common.type)); + + switch (obj_desc->common.type) { + case ACPI_TYPE_INTEGER: + acpi_os_printf (" %.8X", obj_desc->integer.value); + break; + + case ACPI_TYPE_STRING: + acpi_os_printf ("(%d) \"%.16s\"...", + obj_desc->string.length, obj_desc->string.pointer); + break; + + case ACPI_TYPE_BUFFER: + acpi_os_printf ("(%d)", obj_desc->buffer.length); + for (i = 0; (i < 8) && (i < obj_desc->buffer.length); i++) { + acpi_os_printf (" %2.2X", obj_desc->buffer.pointer[i]); + } + break; + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_display_internal_object + * + * PARAMETERS: Obj_desc - Object to be displayed + * Walk_state - Current walk state + * + * RETURN: None + * + * DESCRIPTION: Short display of an internal object + * + ******************************************************************************/ + +void +acpi_db_display_internal_object ( + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_WALK_STATE *walk_state) +{ + u8 type; + + + acpi_os_printf ("%p ", obj_desc); + + if (!obj_desc) { + acpi_os_printf ("\n"); + return; + } + + + /* Decode the object type */ + + else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_PARSER)) { + acpi_os_printf (" "); + } + + else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { + acpi_os_printf (" Name %4.4s Type-%s", + &((ACPI_NAMESPACE_NODE *)obj_desc)->name, + acpi_ut_get_type_name (((ACPI_NAMESPACE_NODE *) obj_desc)->type)); + if (((ACPI_NAMESPACE_NODE *) obj_desc)->flags & ANOBJ_METHOD_ARG) { + acpi_os_printf (" [Method Arg]"); + } + if (((ACPI_NAMESPACE_NODE *) obj_desc)->flags & ANOBJ_METHOD_LOCAL) { + acpi_os_printf (" [Method Local]"); + } + } + + else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_INTERNAL)) { + acpi_os_printf (" "); + type = obj_desc->common.type; + if (type > INTERNAL_TYPE_MAX) { + acpi_os_printf (" Type %x [Invalid Type]", type); + return; + } + + /* Decode the ACPI object type */ + + switch (obj_desc->common.type) { + case INTERNAL_TYPE_REFERENCE: + switch (obj_desc->reference.opcode) { + case AML_ZERO_OP: + acpi_os_printf ("[Const] Number %.8X", 0); + break; + + case AML_ONES_OP: + acpi_os_printf ("[Const] Number %.8X", ACPI_UINT32_MAX); + break; + + case AML_ONE_OP: + acpi_os_printf ("[Const] Number %.8X", 1); + break; + + case AML_LOCAL_OP: + acpi_os_printf ("[Local%d] ", obj_desc->reference.offset); + if (walk_state) { + obj_desc = walk_state->local_variables[obj_desc->reference.offset].object; + acpi_db_decode_internal_object (obj_desc); + } + break; + + case AML_ARG_OP: + acpi_os_printf ("[Arg%d] ", obj_desc->reference.offset); + if (walk_state) { + obj_desc = walk_state->arguments[obj_desc->reference.offset].object; + acpi_db_decode_internal_object (obj_desc); + } + break; + + case AML_DEBUG_OP: + acpi_os_printf ("[Debug] "); + break; + + case AML_INDEX_OP: + acpi_os_printf ("[Index] "); + acpi_db_decode_internal_object (obj_desc->reference.object); + break; + + default: + break; + + } + break; + + default: + acpi_os_printf (" "); + acpi_db_decode_internal_object (obj_desc); + break; + } + } + + else { + acpi_os_printf (" "); + } + + acpi_os_printf ("\n"); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_display_method_info + * + * PARAMETERS: Start_op - Root of the control method parse tree + * + * RETURN: None + * + * DESCRIPTION: Display information about the current method + * + ******************************************************************************/ + +void +acpi_db_display_method_info ( + ACPI_PARSE_OBJECT *start_op) +{ + ACPI_WALK_STATE *walk_state; + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_NAMESPACE_NODE *node; + ACPI_PARSE_OBJECT *root_op; + ACPI_PARSE_OBJECT *op; + ACPI_OPCODE_INFO *op_info; + u32 num_ops = 0; + u32 num_operands = 0; + u32 num_operators = 0; + u32 num_remaining_ops = 0; + u32 num_remaining_operands = 0; + u32 num_remaining_operators = 0; + u32 num_args; + u32 concurrency; + u8 count_remaining = FALSE; + + + walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list); + if (!walk_state) { + acpi_os_printf ("There is no method currently executing\n"); + return; + } + + obj_desc = walk_state->method_desc; + node = walk_state->method_node; + + 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 ("%X arguments, max concurrency = %X\n", num_args, concurrency); + + + root_op = start_op; + while (root_op->parent) { + root_op = root_op->parent; + } + + op = root_op; + + while (op) { + if (op == start_op) { + count_remaining = TRUE; + } + + num_ops++; + if (count_remaining) { + num_remaining_ops++; + } + + op_info = acpi_ps_get_opcode_info (op->opcode); + if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) { + /* Bad opcode or ASCII character */ + + continue; + } + + + /* Decode the opcode */ + + switch (ACPI_GET_OP_CLASS (op_info)) { + case OPTYPE_CONSTANT: /* argument type only */ + case OPTYPE_LITERAL: /* argument type only */ + case OPTYPE_DATA_TERM: /* argument type only */ + case OPTYPE_LOCAL_VARIABLE: /* argument type only */ + case OPTYPE_METHOD_ARGUMENT: /* argument type only */ + if (count_remaining) { + num_remaining_operands++; + } + + num_operands++; + break; + + default: + if (count_remaining) { + num_remaining_operators++; + } + + num_operators++; + break; + } + + + op = acpi_ps_get_depth_next (start_op, op); + } + + acpi_os_printf ("Method contains: %X AML Opcodes - %X Operators, %X Operands\n", + num_ops, num_operators, num_operands); + + acpi_os_printf ("Remaining to execute: %X AML Opcodes - %X Operators, %X Operands\n", + num_remaining_ops, num_remaining_operators, num_remaining_operands); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_display_locals + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Display all locals for the currently running control method + * + ******************************************************************************/ + +void +acpi_db_display_locals (void) +{ + u32 i; + ACPI_WALK_STATE *walk_state; + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_NAMESPACE_NODE *node; + + + walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list); + if (!walk_state) { + acpi_os_printf ("There is no method currently executing\n"); + return; + } + + obj_desc = walk_state->method_desc; + node = walk_state->method_node; + + + acpi_os_printf ("Local Variables for method [%4.4s]:\n", &node->name); + + for (i = 0; i < MTH_NUM_LOCALS; i++) { + obj_desc = walk_state->local_variables[i].object; + acpi_os_printf ("Local%d: ", i); + acpi_db_display_internal_object (obj_desc, walk_state); + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_display_arguments + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Display all arguments for the currently running control method + * + ******************************************************************************/ + +void +acpi_db_display_arguments (void) +{ + u32 i; + ACPI_WALK_STATE *walk_state; + ACPI_OPERAND_OBJECT *obj_desc; + u32 num_args; + u32 concurrency; + ACPI_NAMESPACE_NODE *node; + + + walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list); + if (!walk_state) { + acpi_os_printf ("There is no method currently executing\n"); + return; + } + + obj_desc = walk_state->method_desc; + node = walk_state->method_node; + + num_args = obj_desc->method.param_count; + concurrency = obj_desc->method.concurrency; + + acpi_os_printf ("Method [%4.4s] has %X arguments, max concurrency = %X\n", &node->name, num_args, concurrency); + + for (i = 0; i < num_args; i++) { + obj_desc = walk_state->arguments[i].object; + acpi_os_printf ("Arg%d: ", i); + acpi_db_display_internal_object (obj_desc, walk_state); + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_display_results + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Display current contents of a method result stack + * + ******************************************************************************/ + +void +acpi_db_display_results (void) +{ + u32 i; + ACPI_WALK_STATE *walk_state; + ACPI_OPERAND_OBJECT *obj_desc; + u32 num_results = 0; + ACPI_NAMESPACE_NODE *node; + + + walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list); + if (!walk_state) { + acpi_os_printf ("There is no method currently executing\n"); + return; + } + + obj_desc = walk_state->method_desc; + node = walk_state->method_node; + + if (walk_state->results) { + num_results = walk_state->results->results.num_results; + } + + acpi_os_printf ("Method [%4.4s] has %X stacked result objects\n", &node->name, num_results); + + for (i = 0; i < num_results; i++) { + obj_desc = walk_state->results->results.obj_desc[i]; + acpi_os_printf ("Result%d: ", i); + acpi_db_display_internal_object (obj_desc, walk_state); + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_display_calling_tree + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Display current calling tree of nested control methods + * + ******************************************************************************/ + +void +acpi_db_display_calling_tree (void) +{ + u32 i; + ACPI_WALK_STATE *walk_state; + ACPI_NAMESPACE_NODE *node; + + + walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list); + if (!walk_state) { + acpi_os_printf ("There is no method currently executing\n"); + return; + } + + node = walk_state->method_node; + + acpi_os_printf ("Current Control Method Call Tree\n"); + + for (i = 0; walk_state; i++) { + node = walk_state->method_node; + + acpi_os_printf (" [%4.4s]\n", &node->name); + + walk_state = walk_state->next; + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_display_result_object + * + * PARAMETERS: Obj_desc - Object to be displayed + * Walk_state - Current walk state + * + * RETURN: None + * + * DESCRIPTION: Display the result of an AML opcode + * + ******************************************************************************/ + +void +acpi_db_display_result_object ( + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_WALK_STATE *walk_state) +{ + + /* TBD: [Future] We don't always want to display the result. + * For now, only display if single stepping + * however, this output is very useful in other contexts also + */ + + if (!acpi_gbl_cm_single_step) { + return; + } + + acpi_os_printf ("Result_obj: "); + acpi_db_display_internal_object (obj_desc, walk_state); + acpi_os_printf ("\n"); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_display_argument_object + * + * PARAMETERS: Obj_desc - Object to be displayed + * Walk_state - Current walk state + * + * RETURN: None + * + * DESCRIPTION: Display the result of an AML opcode + * + ******************************************************************************/ + +void +acpi_db_display_argument_object ( + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_WALK_STATE *walk_state) +{ + + + if (!acpi_gbl_cm_single_step) { + return; + } + + acpi_os_printf ("Arg_obj: "); + acpi_db_display_internal_object (obj_desc, walk_state); +} + +#endif /* ENABLE_DEBUGGER */ + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/debugger/dbexec.c linux/drivers/acpi/debugger/dbexec.c --- v2.4.5/linux/drivers/acpi/debugger/dbexec.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/debugger/dbexec.c Wed Jun 20 17:47:39 2001 @@ -0,0 +1,341 @@ +/******************************************************************************* + * + * Module Name: dbexec - debugger control method execution + * $Revision: 26 $ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "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 + +#define _COMPONENT ACPI_DEBUGGER + MODULE_NAME ("dbexec") + + +DB_METHOD_INFO info; + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_execute_method + * + * PARAMETERS: Info - Valid info segment + * Return_obj - Where to put return object + * + * RETURN: Status + * + * DESCRIPTION: Execute a control method. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_db_execute_method ( + DB_METHOD_INFO *info, + ACPI_BUFFER *return_obj) +{ + ACPI_STATUS status; + ACPI_OBJECT_LIST param_objects; + ACPI_OBJECT params[MTH_NUM_ARGS]; + u32 i; + + + if (output_to_file && !acpi_dbg_level) { + acpi_os_printf ("Warning: debug output is not enabled!\n"); + } + + /* Are there arguments to the method? */ + + if (info->args && info->args[0]) { + for (i = 0; info->args[i] && i < MTH_NUM_ARGS; i++) { + params[i].type = ACPI_TYPE_INTEGER; + params[i].integer.value = STRTOUL (info->args[i], NULL, 16); + } + + param_objects.pointer = params; + param_objects.count = i; + } + + else { + /* Setup default parameters */ + + params[0].type = ACPI_TYPE_INTEGER; + params[0].integer.value = 0x01020304; + + params[1].type = ACPI_TYPE_STRING; + params[1].string.length = 12; + params[1].string.pointer = "AML Debugger"; + + param_objects.pointer = params; + param_objects.count = 2; + } + + /* Prepare for a return object of arbitrary size */ + + return_obj->pointer = buffer; + return_obj->length = BUFFER_SIZE; + + + /* Do the actual method execution */ + + status = acpi_evaluate_object (NULL, info->pathname, ¶m_objects, return_obj); + + acpi_gbl_cm_single_step = FALSE; + acpi_gbl_method_executing = FALSE; + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_execute_setup + * + * PARAMETERS: Info - Valid method info + * + * RETURN: Status + * + * DESCRIPTION: Setup info segment prior to method execution + * + ******************************************************************************/ + +void +acpi_db_execute_setup ( + DB_METHOD_INFO *info) +{ + + /* Catenate the current scope to the supplied name */ + + info->pathname[0] = 0; + if ((info->name[0] != '\\') && + (info->name[0] != '/')) { + STRCAT (info->pathname, scope_buf); + } + + STRCAT (info->pathname, info->name); + acpi_db_prep_namestring (info->pathname); + + acpi_db_set_output_destination (DB_DUPLICATE_OUTPUT); + acpi_os_printf ("Executing %s\n", info->pathname); + + if (info->flags & EX_SINGLE_STEP) { + acpi_gbl_cm_single_step = TRUE; + acpi_db_set_output_destination (DB_CONSOLE_OUTPUT); + } + + else { + /* No single step, allow redirection to a file */ + + acpi_db_set_output_destination (DB_REDIRECTABLE_OUTPUT); + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_execute + * + * PARAMETERS: Name - Name of method to execute + * Args - Parameters to the method + * Flags - single step/no single step + * + * RETURN: Status + * + * DESCRIPTION: Execute a control method. Name is relative to the current + * scope. + * + ******************************************************************************/ + +void +acpi_db_execute ( + NATIVE_CHAR *name, + NATIVE_CHAR **args, + u32 flags) +{ + ACPI_STATUS status; + ACPI_BUFFER return_obj; + + + info.name = name; + info.args = args; + info.flags = flags; + + acpi_db_execute_setup (&info); + status = acpi_db_execute_method (&info, &return_obj); + + + if (ACPI_FAILURE (status)) { + acpi_os_printf ("Execution of %s failed with status %s\n", + info.pathname, acpi_ut_format_exception (status)); + } + + else { + /* Display a return object, if any */ + + if (return_obj.length) { + acpi_os_printf ("Execution of %s returned object %p Buflen %X\n", + info.pathname, return_obj.pointer, return_obj.length); + acpi_db_dump_object (return_obj.pointer, 1); + } + } + + acpi_db_set_output_destination (DB_CONSOLE_OUTPUT); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_method_thread + * + * PARAMETERS: Context - Execution info segment + * + * RETURN: None + * + * DESCRIPTION: Debugger execute thread. Waits for a command line, then + * simply dispatches it. + * + ******************************************************************************/ + +void +acpi_db_method_thread ( + void *context) +{ + ACPI_STATUS status; + DB_METHOD_INFO *info = context; + u32 i; + ACPI_BUFFER return_obj; + + + for (i = 0; i < info->num_loops; i++) { + status = acpi_db_execute_method (info, &return_obj); + if (ACPI_SUCCESS (status)) { + if (return_obj.length) { + acpi_os_printf ("Execution of %s returned object %p Buflen %X\n", + info->pathname, return_obj.pointer, return_obj.length); + acpi_db_dump_object (return_obj.pointer, 1); + } + } + } + + + /* Signal our completion */ + + acpi_os_signal_semaphore (info->thread_gate, 1); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_create_execution_threads + * + * PARAMETERS: Num_threads_arg - Number of threads to create + * Num_loops_arg - Loop count for the thread(s) + * Method_name_arg - Control method to execute + * + * RETURN: None + * + * DESCRIPTION: Create threads to execute method(s) + * + ******************************************************************************/ + +void +acpi_db_create_execution_threads ( + NATIVE_CHAR *num_threads_arg, + NATIVE_CHAR *num_loops_arg, + NATIVE_CHAR *method_name_arg) +{ + ACPI_STATUS status; + u32 num_threads; + u32 num_loops; + u32 i; + ACPI_HANDLE thread_gate; + + + /* Get the arguments */ + + num_threads = STRTOUL (num_threads_arg, NULL, 0); + num_loops = STRTOUL (num_loops_arg, NULL, 0); + + if (!num_threads || !num_loops) { + acpi_os_printf ("Bad argument: Threads %X, Loops %X\n", num_threads, num_loops); + return; + } + + + /* Create the synchronization semaphore */ + + status = acpi_os_create_semaphore (1, 0, &thread_gate); + if (ACPI_FAILURE (status)) { + acpi_os_printf ("Could not create semaphore, %s\n", acpi_ut_format_exception (status)); + return; + } + + /* Setup the context to be passed to each thread */ + + info.name = method_name_arg; + info.args = NULL; + info.flags = 0; + info.num_loops = num_loops; + info.thread_gate = thread_gate; + + acpi_db_execute_setup (&info); + + + /* Create the threads */ + + 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, &info); + } + + + /* Wait for all threads to complete */ + + i = num_threads; + while (i) /* Brain damage for OSD implementations that only support wait of 1 unit */ { + status = acpi_os_wait_semaphore (thread_gate, 1, WAIT_FOREVER); + i--; + } + + /* Cleanup and exit */ + + acpi_os_delete_semaphore (thread_gate); + + acpi_db_set_output_destination (DB_DUPLICATE_OUTPUT); + acpi_os_printf ("All threads (%X) have completed\n", num_threads); + acpi_db_set_output_destination (DB_CONSOLE_OUTPUT); +} + + +#endif /* ENABLE_DEBUGGER */ + + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/debugger/dbfileio.c linux/drivers/acpi/debugger/dbfileio.c --- v2.4.5/linux/drivers/acpi/debugger/dbfileio.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/debugger/dbfileio.c Wed Jun 20 17:47:39 2001 @@ -0,0 +1,378 @@ +/******************************************************************************* + * + * Module Name: dbfileio - Debugger file I/O commands. These can't usually + * be used when running the debugger in Ring 0 (Kernel mode) + * $Revision: 41 $ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acdebug.h" +#include "acnamesp.h" +#include "acparser.h" +#include "acevents.h" +#include "actables.h" + +#ifdef ENABLE_DEBUGGER + +#define _COMPONENT ACPI_DEBUGGER + MODULE_NAME ("dbfileio") + + +ACPI_PARSE_OBJECT *root; + +#ifdef ACPI_APPLICATION +#include +FILE *debug_file = NULL; +#endif + + +/* + * NOTE: this is here for lack of a better place. It is used in all + * flavors of the debugger, need LCD file + */ + +/******************************************************************************* + * + * FUNCTION: Acpi_db_match_argument + * + * PARAMETERS: User_argument - User command line + * Arguments - Array of commands to match against + * + * RETURN: Index into command array or ACPI_TYPE_NOT_FOUND if not found + * + * DESCRIPTION: Search command array for a command match + * + ******************************************************************************/ + +ACPI_OBJECT_TYPE8 +acpi_db_match_argument ( + NATIVE_CHAR *user_argument, + ARGUMENT_INFO *arguments) +{ + u32 i; + + + if (!user_argument || user_argument[0] == 0) { + return (ACPI_TYPE_NOT_FOUND); + } + + for (i = 0; arguments[i].name; i++) { + if (STRSTR (arguments[i].name, user_argument) == arguments[i].name) { + return ((ACPI_OBJECT_TYPE8) i); + } + } + + /* Argument not recognized */ + + return (ACPI_TYPE_NOT_FOUND); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_close_debug_file + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: If open, close the current debug output file + * + ******************************************************************************/ + +void +acpi_db_close_debug_file ( + void) +{ + +#ifdef ACPI_APPLICATION + + if (debug_file) { + fclose (debug_file); + debug_file = NULL; + output_to_file = FALSE; + acpi_os_printf ("Debug output file %s closed\n", debug_filename); + } +#endif + +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_open_debug_file + * + * PARAMETERS: Name - Filename to open + * + * RETURN: Status + * + * DESCRIPTION: Open a file where debug output will be directed. + * + ******************************************************************************/ + +void +acpi_db_open_debug_file ( + NATIVE_CHAR *name) +{ + +#ifdef ACPI_APPLICATION + + acpi_db_close_debug_file (); + debug_file = fopen (name, "w+"); + if (debug_file) { + acpi_os_printf ("Debug output file %s opened\n", name); + STRCPY (debug_filename, name); + output_to_file = TRUE; + } + else { + acpi_os_printf ("Could not open debug file %s\n", name); + } + +#endif +} + + +#ifdef ACPI_APPLICATION +/******************************************************************************* + * + * FUNCTION: Acpi_db_load_table + * + * PARAMETERS: fp - File that contains table + * Table_ptr - Return value, buffer with table + * Table_lenght - Return value, length of table + * + * RETURN: Status + * + * DESCRIPTION: Load the DSDT from the file pointer + * + ******************************************************************************/ + +ACPI_STATUS +acpi_db_load_table( + FILE *fp, + ACPI_TABLE_HEADER **table_ptr, + u32 *table_length) +{ + ACPI_TABLE_HEADER table_header; + u8 *aml_ptr; + u32 aml_length; + u32 actual; + ACPI_STATUS status; + + + /* Read the table header */ + + if (fread (&table_header, 1, sizeof (table_header), fp) != sizeof (ACPI_TABLE_HEADER)) { + acpi_os_printf ("Couldn't read the table header\n"); + return (AE_BAD_SIGNATURE); + } + + + /* Validate the table header/length */ + + status = acpi_tb_validate_table_header (&table_header); + if ((ACPI_FAILURE (status)) || + (table_header.length > 524288)) /* 1/2 Mbyte should be enough */ { + acpi_os_printf ("Table header is invalid!\n"); + return (AE_ERROR); + } + + + /* We only support a limited number of table types */ + + if (STRNCMP ((char *) table_header.signature, DSDT_SIG, 4) && + STRNCMP ((char *) table_header.signature, PSDT_SIG, 4) && + STRNCMP ((char *) table_header.signature, SSDT_SIG, 4)) { + acpi_os_printf ("Table signature is invalid\n"); + return (AE_ERROR); + } + + /* Allocate a buffer for the table */ + + *table_length = table_header.length; + *table_ptr = (ACPI_TABLE_HEADER *) acpi_ut_allocate ((size_t) *table_length); + if (!*table_ptr) { + acpi_os_printf ("Could not allocate memory for the table (size=%X)\n", table_header.length); + return (AE_NO_MEMORY); + } + + + aml_ptr = (u8 *) *table_ptr + sizeof (table_header); + aml_length = *table_length - sizeof (table_header); + + /* Copy the header to the buffer */ + + MEMCPY (*table_ptr, &table_header, sizeof (table_header)); + + /* Get the rest of the table */ + + actual = fread (aml_ptr, 1, (size_t) aml_length, fp); + if (actual == aml_length) { + return (AE_OK); + } + + if (actual > 0) { + acpi_os_printf ("Warning - reading table, asked for %X got %X\n", aml_length, actual); + return (AE_OK); + } + + + acpi_os_printf ("Error - could not read the table file\n"); + acpi_ut_free (*table_ptr); + *table_ptr = NULL; + *table_length = 0; + + return (AE_ERROR); +} +#endif + + +/******************************************************************************* + * + * FUNCTION: Ae_local_load_table + * + * PARAMETERS: Table_ptr - pointer to a buffer containing the entire + * table to be loaded + * + * RETURN: Status + * + * DESCRIPTION: This function is called to load a table from the caller's + * buffer. The buffer must contain an entire ACPI Table including + * a valid header. The header fields will be verified, and if it + * is determined that the table is invalid, the call will fail. + * + * If the call fails an appropriate status will be returned. + * + ******************************************************************************/ + +ACPI_STATUS +ae_local_load_table ( + ACPI_TABLE_HEADER *table_ptr) +{ + ACPI_STATUS status; + ACPI_TABLE_DESC table_info; + + + if (!table_ptr) { + return (AE_BAD_PARAMETER); + } + + /* Install the new table into the local data structures */ + + table_info.pointer = table_ptr; + + status = acpi_tb_install_table (NULL, &table_info); + if (ACPI_FAILURE (status)) { + /* Free table allocated by Acpi_tb_get_table */ + + acpi_tb_delete_single_table (&table_info); + return (status); + } + + +#ifndef PARSER_ONLY + status = acpi_ns_load_table (table_info.installed_desc, acpi_gbl_root_node); + if (ACPI_FAILURE (status)) { + /* Uninstall table and free the buffer */ + + acpi_tb_uninstall_table (table_info.installed_desc); + return (status); + } +#endif + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_load_acpi_table + * + * PARAMETERS: Filname - File where table is located + * + * RETURN: Status + * + * DESCRIPTION: Load an ACPI table from a file + * + ******************************************************************************/ + +ACPI_STATUS +acpi_db_load_acpi_table ( + NATIVE_CHAR *filename) +{ +#ifdef ACPI_APPLICATION + FILE *fp; + ACPI_STATUS status; + ACPI_TABLE_HEADER *table_ptr; + u32 table_length; + + + /* Open the file */ + + fp = fopen (filename, "rb"); + if (!fp) { + acpi_os_printf ("Could not open file %s\n", filename); + return (AE_ERROR); + } + + + /* Get the entire file */ + + acpi_os_printf ("Loading Acpi table from file %s\n", filename); + status = acpi_db_load_table (fp, &table_ptr, &table_length); + fclose(fp); + + if (ACPI_FAILURE (status)) { + acpi_os_printf ("Couldn't get table from the file\n"); + return (status); + } + + + /* Attempt to recognize and install the table */ + status = ae_local_load_table (table_ptr); + + if (ACPI_FAILURE (status)) { + if (status == AE_EXIST) { + acpi_os_printf ("Table %4.4s is already installed\n", + &table_ptr->signature); + } + else { + acpi_os_printf ("Could not install table, %s\n", + acpi_ut_format_exception (status)); + } + acpi_ut_free (table_ptr); + return (status); + } + + acpi_os_printf ("%4.4s at %p successfully installed and loaded\n", + &table_ptr->signature, table_ptr); + + acpi_gbl_acpi_hardware_present = FALSE; + +#endif /* ACPI_APPLICATION */ + return (AE_OK); +} + + +#endif /* ENABLE_DEBUGGER */ + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/debugger/dbhistry.c linux/drivers/acpi/debugger/dbhistry.c --- v2.4.5/linux/drivers/acpi/debugger/dbhistry.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/debugger/dbhistry.c Wed Jun 20 17:47:39 2001 @@ -0,0 +1,199 @@ +/****************************************************************************** + * + * Module Name: dbhistry - debugger HISTORY command + * $Revision: 18 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "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 + +#define _COMPONENT ACPI_DEBUGGER + MODULE_NAME ("dbhistry") + + +#define HI_NO_HISTORY 0 +#define HI_RECORD_HISTORY 1 +#define HISTORY_SIZE 20 + + +typedef struct history_info +{ + NATIVE_CHAR command[80]; + u32 cmd_num; + +} HISTORY_INFO; + + +HISTORY_INFO history_buffer[HISTORY_SIZE]; +u16 lo_history = 0; +u16 num_history = 0; +u16 next_history_index = 0; +u32 next_cmd_num = 1; + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_add_to_history + * + * PARAMETERS: Command_line - Command to add + * + * RETURN: None + * + * DESCRIPTION: Add a command line to the history buffer. + * + ******************************************************************************/ + +void +acpi_db_add_to_history ( + NATIVE_CHAR *command_line) +{ + + + /* Put command into the next available slot */ + + STRCPY (history_buffer[next_history_index].command, command_line); + history_buffer[next_history_index].cmd_num = next_cmd_num; + + /* Adjust indexes */ + + if ((num_history == HISTORY_SIZE) && + (next_history_index == lo_history)) { + lo_history++; + if (lo_history >= HISTORY_SIZE) { + lo_history = 0; + } + } + + next_history_index++; + if (next_history_index >= HISTORY_SIZE) { + next_history_index = 0; + } + + + next_cmd_num++; + if (num_history < HISTORY_SIZE) { + num_history++; + } + +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_display_history + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Display the contents of the history buffer + * + ******************************************************************************/ + +void +acpi_db_display_history (void) +{ + NATIVE_UINT i; + u16 history_index; + + + history_index = lo_history; + + /* Dump entire history buffer */ + + for (i = 0; i < num_history; i++) { + acpi_os_printf ("%ld %s\n", history_buffer[history_index].cmd_num, history_buffer[history_index].command); + + history_index++; + if (history_index >= HISTORY_SIZE) { + history_index = 0; + } + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_get_from_history + * + * PARAMETERS: Command_num_arg - String containing the number of the + * command to be retrieved + * + * RETURN: None + * + * DESCRIPTION: Get a command from the history buffer + * + ******************************************************************************/ + +NATIVE_CHAR * +acpi_db_get_from_history ( + NATIVE_CHAR *command_num_arg) +{ + NATIVE_UINT i; + u16 history_index; + u32 cmd_num; + + + if (command_num_arg == NULL) { + cmd_num = next_cmd_num - 1; + } + + else { + cmd_num = STRTOUL (command_num_arg, NULL, 0); + } + + + /* Search history buffer */ + + history_index = lo_history; + for (i = 0; i < num_history; i++) { + if (history_buffer[history_index].cmd_num == cmd_num) { + /* Found the commnad, return it */ + + return (history_buffer[history_index].command); + } + + + history_index++; + if (history_index >= HISTORY_SIZE) { + history_index = 0; + } + } + + acpi_os_printf ("Invalid history number: %d\n", history_index); + return (NULL); +} + + +#endif /* ENABLE_DEBUGGER */ + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/debugger/dbinput.c linux/drivers/acpi/debugger/dbinput.c --- v2.4.5/linux/drivers/acpi/debugger/dbinput.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/debugger/dbinput.c Wed Jun 20 17:47:39 2001 @@ -0,0 +1,909 @@ +/******************************************************************************* + * + * Module Name: dbinput - user front-end to the AML debugger + * $Revision: 61 $ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acparser.h" +#include "actables.h" +#include "acnamesp.h" +#include "acinterp.h" +#include "acdebug.h" + + +#ifdef ENABLE_DEBUGGER + +#define _COMPONENT ACPI_DEBUGGER + MODULE_NAME ("dbinput") + + +/* + * Globals that are specific to the debugger + */ + +NATIVE_CHAR line_buf[80]; +NATIVE_CHAR parsed_buf[80]; +NATIVE_CHAR scope_buf[40]; +NATIVE_CHAR debug_filename[40]; +NATIVE_CHAR *args[DB_MAX_ARGS]; +NATIVE_CHAR *buffer; +NATIVE_CHAR *filename = NULL; +u8 output_to_file = FALSE; + + +u32 acpi_gbl_db_debug_level = 0x0FFFFFFF; +u32 acpi_gbl_db_console_debug_level = NORMAL_DEFAULT | TRACE_TABLES; +u8 acpi_gbl_db_output_flags = DB_CONSOLE_OUTPUT; + + +u8 opt_tables = FALSE; +u8 opt_disasm = FALSE; +u8 opt_stats = FALSE; +u8 opt_parse_jit = FALSE; +u8 opt_verbose = TRUE; +u8 opt_ini_methods = TRUE; + + +/* + * Top-level debugger commands. + * + * This list of commands must match the string table below it + */ + +enum acpi_ex_debugger_commands +{ + CMD_NOT_FOUND = 0, + CMD_NULL, + CMD_ALLOCATIONS, + CMD_ARGS, + CMD_ARGUMENTS, + CMD_BREAKPOINT, + CMD_CALL, + CMD_CLOSE, + CMD_DEBUG, + CMD_DUMP, + CMD_ENABLEACPI, + CMD_EVENT, + CMD_EXECUTE, + CMD_EXIT, + CMD_FIND, + CMD_GO, + CMD_HELP, + CMD_HELP2, + CMD_HISTORY, + CMD_HISTORY_EXE, + CMD_HISTORY_LAST, + CMD_INFORMATION, + CMD_INTO, + CMD_LEVEL, + CMD_LIST, + CMD_LOAD, + CMD_LOCALS, + CMD_LOCKS, + CMD_METHODS, + CMD_NAMESPACE, + CMD_NOTIFY, + CMD_OBJECT, + CMD_OPEN, + CMD_OWNER, + CMD_PREFIX, + CMD_QUIT, + CMD_REFERENCES, + CMD_RESOURCES, + CMD_RESULTS, + CMD_SET, + CMD_STATS, + CMD_STOP, + CMD_TABLES, + CMD_TERMINATE, + CMD_THREADS, + CMD_TREE, + CMD_UNLOAD +}; + +#define CMD_FIRST_VALID 2 + + +COMMAND_INFO commands[] = +{ {"", 0}, + {"", 0}, + {"ALLOCATIONS", 0}, + {"ARGS", 0}, + {"ARGUMENTS", 0}, + {"BREAKPOINT", 1}, + {"CALL", 0}, + {"CLOSE", 0}, + {"DEBUG", 1}, + {"DUMP", 1}, + {"ENABLEACPI", 0}, + {"EVENT", 1}, + {"EXECUTE", 1}, + {"EXIT", 0}, + {"FIND", 1}, + {"GO", 0}, + {"HELP", 0}, + {"?", 0}, + {"HISTORY", 0}, + {"!", 1}, + {"!!", 0}, + {"INFORMATION", 0}, + {"INTO", 0}, + {"LEVEL", 0}, + {"LIST", 0}, + {"LOAD", 1}, + {"LOCALS", 0}, + {"LOCKS", 0}, + {"METHODS", 0}, + {"NAMESPACE", 0}, + {"NOTIFY", 2}, + {"OBJECT", 1}, + {"OPEN", 1}, + {"OWNER", 1}, + {"PREFIX", 0}, + {"QUIT", 0}, + {"REFERENCES", 1}, + {"RESOURCES", 1}, + {"RESULTS", 0}, + {"SET", 3}, + {"STATS", 0}, + {"STOP", 0}, + {"TABLES", 0}, + {"TERMINATE", 0}, + {"THREADS", 3}, + {"TREE", 0}, + {"UNLOAD", 0}, + {NULL, 0} +}; + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_display_help + * + * PARAMETERS: Help_type - Subcommand (optional) + * + * RETURN: None + * + * DESCRIPTION: Print a usage message. + * + ******************************************************************************/ + +void +acpi_db_display_help ( + NATIVE_CHAR *help_type) +{ + + + /* No parameter, just give the overview */ + + if (!help_type) + { + acpi_os_printf ("ACPI CA Debugger Commands\n\n"); + acpi_os_printf ("The following classes of commands are available. Help is available for\n"); + acpi_os_printf ("each class by entering \"help \"\n\n"); + acpi_os_printf (" [GENERAL] General-Purpose Commands\n"); + acpi_os_printf (" [NAMESPACE] Namespace Access Commands\n"); + acpi_os_printf (" [METHOD] Control Method Execution Commands\n"); + acpi_os_printf (" [FILE] File I/O Commands\n"); + return; + + } + + + /* + * Parameter is the command class + * + * The idea here is to keep each class of commands smaller than a screenful + */ + + switch (help_type[0]) + { + case 'G': + acpi_os_printf ("\n_general-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"); + acpi_os_printf ("Enable_acpi Enable ACPI (hardware) mode\n"); + acpi_os_printf ("Help This help screen\n"); + acpi_os_printf ("History Display command history buffer\n"); + acpi_os_printf ("Level [] [console] Get/Set debug level for file or console\n"); + acpi_os_printf ("Locks Current status of internal mutexes\n"); + acpi_os_printf ("Quit or Exit Exit this command\n"); + acpi_os_printf ("Stats [Allocations|Memory|Misc\n"); + acpi_os_printf (" |Objects|Tables] Display namespace and memory statistics\n"); + acpi_os_printf ("Tables Display info about loaded ACPI tables\n"); + acpi_os_printf ("Unload Unload an ACPI table\n"); + acpi_os_printf ("! Execute command from history buffer\n"); + acpi_os_printf ("!! Execute last command again\n"); + return; + + case 'N': + acpi_os_printf ("\n_namespace 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"); + acpi_os_printf ("Find (? is wildcard) Find ACPI name(s) with wildcards\n"); + acpi_os_printf ("Method Display list of loaded control methods\n"); + acpi_os_printf ("Namespace [|] [Depth] Display loaded namespace tree/subtree\n"); + acpi_os_printf ("Notify Send a notification\n"); + acpi_os_printf ("Objects Display all objects of the given type\n"); + acpi_os_printf ("Owner [Depth] Display loaded namespace by object owner\n"); + acpi_os_printf ("Prefix [] Set or Get current execution prefix\n"); + acpi_os_printf ("References Find all references to object at addr\n"); + acpi_os_printf ("Resources xxx Get and display resources\n"); + acpi_os_printf ("Terminate Delete namespace and all internal objects\n"); + acpi_os_printf ("Thread Spawn threads to execute method(s)\n"); + return; + + case 'M': + acpi_os_printf ("\n_control 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"); + acpi_os_printf ("Go Allow method to run to completion\n"); + acpi_os_printf ("Information Display info about the current method\n"); + acpi_os_printf ("Into Step into (not over) a method call\n"); + acpi_os_printf ("List [# of Aml Opcodes] Display method ASL statements\n"); + acpi_os_printf ("Locals Display method local variables\n"); + acpi_os_printf ("Results Display method result stack\n"); + acpi_os_printf ("Set <#> Set method data (Arguments/Locals)\n"); + acpi_os_printf ("Stop Terminate control method\n"); + acpi_os_printf ("Tree Display control method calling tree\n"); + acpi_os_printf (" Single step next AML opcode (over calls)\n"); + return; + + case 'F': + acpi_os_printf ("\n_file 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); + return; + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_get_next_token + * + * PARAMETERS: String - Command buffer + * Next - Return value, end of next token + * + * RETURN: Pointer to the start of the next token. + * + * DESCRIPTION: Command line parsing. Get the next token on the command line + * + ******************************************************************************/ + +NATIVE_CHAR * +acpi_db_get_next_token ( + NATIVE_CHAR *string, + NATIVE_CHAR **next) +{ + NATIVE_CHAR *start; + + /* At end of buffer? */ + + if (!string || !(*string)) + { + return (NULL); + } + + + /* Get rid of any spaces at the beginning */ + + if (*string == ' ') + { + while (*string && (*string == ' ')) + { + string++; + } + + if (!(*string)) + { + return (NULL); + } + } + + start = string; + + /* Find end of token */ + + while (*string && (*string != ' ')) + { + string++; + } + + + if (!(*string)) + { + *next = NULL; + } + + else + { + *string = 0; + *next = string + 1; + } + + return (start); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_get_line + * + * PARAMETERS: Input_buffer - Command line buffer + * + * RETURN: None + * + * DESCRIPTION: Get the next command line from the user. Gets entire line + * up to the next newline + * + ******************************************************************************/ + +u32 +acpi_db_get_line ( + NATIVE_CHAR *input_buffer) +{ + u32 i; + u32 count; + NATIVE_CHAR *next; + NATIVE_CHAR *this; + + + STRCPY (parsed_buf, input_buffer); + STRUPR (parsed_buf); + + this = parsed_buf; + for (i = 0; i < DB_MAX_ARGS; i++) + { + args[i] = acpi_db_get_next_token (this, &next); + if (!args[i]) + { + break; + } + + this = next; + } + + + /* Uppercase the actual command */ + + if (args[0]) + { + STRUPR (args[0]); + } + + count = i; + if (count) + { + count--; /* Number of args only */ + } + + return (count); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_match_command + * + * PARAMETERS: User_command - User command line + * + * RETURN: Index into command array, -1 if not found + * + * DESCRIPTION: Search command array for a command match + * + ******************************************************************************/ + +u32 +acpi_db_match_command ( + NATIVE_CHAR *user_command) +{ + u32 i; + + + if (!user_command || user_command[0] == 0) + { + return (CMD_NULL); + } + + for (i = CMD_FIRST_VALID; commands[i].name; i++) + { + if (STRSTR (commands[i].name, user_command) == commands[i].name) + { + return (i); + } + } + + /* Command not recognized */ + + return (CMD_NOT_FOUND); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_command_dispatch + * + * PARAMETERS: Input_buffer - Command line buffer + * Walk_state - Current walk + * Op - Current (executing) parse op + * + * RETURN: Status + * + * DESCRIPTION: Command dispatcher. Called from two places: + * + ******************************************************************************/ + +ACPI_STATUS +acpi_db_command_dispatch ( + NATIVE_CHAR *input_buffer, + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op) +{ + u32 temp; + u32 command_index; + u32 param_count; + NATIVE_CHAR *command_line; + ACPI_STATUS status = AE_CTRL_TRUE; + + + /* If Acpi_terminate has been called, terminate this thread */ + + if (acpi_gbl_db_terminate_threads) + { + return (AE_CTRL_TERMINATE); + } + + param_count = acpi_db_get_line (input_buffer); + command_index = acpi_db_match_command (args[0]); + temp = 0; + + /* Verify that we have the minimum number of params */ + + if (param_count < commands[command_index].min_args) + { + acpi_os_printf ("%d parameters entered, [%s] requires %d parameters\n", + param_count, commands[command_index].name, commands[command_index].min_args); + return (AE_CTRL_TRUE); + } + + /* Decode and dispatch the command */ + + switch (command_index) + { + case CMD_NULL: + if (op) + { + return (AE_OK); + } + break; + + case CMD_ALLOCATIONS: + acpi_ut_dump_current_allocations ((u32) -1, NULL); + break; + + case CMD_ARGS: + case CMD_ARGUMENTS: + acpi_db_display_arguments (); + break; + + case CMD_BREAKPOINT: + acpi_db_set_method_breakpoint (args[1], walk_state, op); + break; + + case CMD_CALL: + acpi_db_set_method_call_breakpoint (op); + status = AE_OK; + break; + + case CMD_CLOSE: + acpi_db_close_debug_file (); + break; + + case CMD_DEBUG: + acpi_db_execute (args[1], &args[2], EX_SINGLE_STEP); + break; + + case CMD_DUMP: + acpi_db_decode_and_display_object (args[1], args[2]); + break; + + case CMD_ENABLEACPI: + status = acpi_enable(); + if (ACPI_FAILURE(status)) + { + acpi_os_printf("Acpi_enable failed (Status=%X)\n", status); + return (status); + } + break; + + case CMD_EVENT: + acpi_os_printf ("Event command not implemented\n"); + break; + + case CMD_EXECUTE: + acpi_db_execute (args[1], &args[2], EX_NO_SINGLE_STEP); + break; + + case CMD_FIND: + acpi_db_find_name_in_namespace (args[1]); + break; + + case CMD_GO: + acpi_gbl_cm_single_step = FALSE; + return (AE_OK); + + case CMD_HELP: + case CMD_HELP2: + acpi_db_display_help (args[1]); + break; + + case CMD_HISTORY: + acpi_db_display_history (); + break; + + case CMD_HISTORY_EXE: + command_line = acpi_db_get_from_history (args[1]); + if (!command_line) + { + return (AE_CTRL_TRUE); + } + + status = acpi_db_command_dispatch (command_line, walk_state, op); + if (ACPI_SUCCESS (status)) + { + status = AE_CTRL_TRUE; + } + return (status); + break; + + case CMD_HISTORY_LAST: + command_line = acpi_db_get_from_history (NULL); + if (!command_line) + { + return (AE_CTRL_TRUE); + } + + status = acpi_db_command_dispatch (command_line, walk_state, op); + if (ACPI_SUCCESS (status)) + { + status = AE_CTRL_TRUE; + } + return (status); + + case CMD_INFORMATION: + acpi_db_display_method_info (op); + break; + + case CMD_INTO: + if (op) + { + acpi_gbl_cm_single_step = TRUE; + +/* TBD: Must get current walk state */ + /* Acpi_gbl_Method_breakpoint = 0; */ + return (AE_OK); + } + break; + + case CMD_LEVEL: + if (param_count == 0) + { + acpi_os_printf ("Current debug level for file output is: %8.8lX\n", acpi_gbl_db_debug_level); + acpi_os_printf ("Current debug level for console output is: %8.8lX\n", acpi_gbl_db_console_debug_level); + } + else if (param_count == 2) + { + temp = acpi_gbl_db_console_debug_level; + acpi_gbl_db_console_debug_level = STRTOUL (args[1], NULL, 16); + acpi_os_printf ("Debug Level for console output was %8.8lX, now %8.8lX\n", temp, acpi_gbl_db_console_debug_level); + } + else + { + temp = acpi_gbl_db_debug_level; + acpi_gbl_db_debug_level = STRTOUL (args[1], NULL, 16); + acpi_os_printf ("Debug Level for file output was %8.8lX, now %8.8lX\n", temp, acpi_gbl_db_debug_level); + } + break; + + case CMD_LIST: + acpi_db_disassemble_aml (args[1], op); + break; + + case CMD_LOAD: + status = acpi_db_load_acpi_table (args[1]); + if (ACPI_FAILURE (status)) + { + return (status); + } + break; + + case CMD_LOCKS: + acpi_db_display_locks (); + break; + + case CMD_LOCALS: + acpi_db_display_locals (); + break; + + case CMD_METHODS: + acpi_db_display_objects ("METHOD", args[1]); + break; + + case CMD_NAMESPACE: + acpi_db_dump_namespace (args[1], args[2]); + break; + + case CMD_NOTIFY: + temp = STRTOUL (args[2], NULL, 0); + acpi_db_send_notify (args[1], temp); + break; + + case CMD_OBJECT: + acpi_db_display_objects (STRUPR (args[1]), args[2]); + break; + + case CMD_OPEN: + acpi_db_open_debug_file (args[1]); + break; + + case CMD_OWNER: + acpi_db_dump_namespace_by_owner (args[1], args[2]); + break; + + case CMD_PREFIX: + acpi_db_set_scope (args[1]); + break; + + case CMD_REFERENCES: + acpi_db_find_references (args[1]); + break; + + case CMD_RESOURCES: + acpi_db_display_resources (args[1]); + break; + + case CMD_RESULTS: + acpi_db_display_results (); + break; + + case CMD_SET: + acpi_db_set_method_data (args[1], args[2], args[3]); + break; + + case CMD_STATS: + acpi_db_display_statistics (args[1]); + break; + + case CMD_STOP: + return (AE_AML_ERROR); + break; + + case CMD_TABLES: + acpi_db_display_table_info (args[1]); + break; + + case CMD_TERMINATE: + acpi_db_set_output_destination (DB_REDIRECTABLE_OUTPUT); + acpi_ut_subsystem_shutdown (); + + /* TBD: [Restructure] Need some way to re-initialize without re-creating the semaphores! */ + + /* Acpi_initialize (NULL); */ + break; + + case CMD_THREADS: + acpi_db_create_execution_threads (args[1], args[2], args[3]); + break; + + case CMD_TREE: + acpi_db_display_calling_tree (); + break; + + case CMD_UNLOAD: + acpi_db_unload_acpi_table (args[1], args[2]); + break; + + case CMD_EXIT: + case CMD_QUIT: + if (op) + { + acpi_os_printf ("Method execution terminated\n"); + return (AE_CTRL_TERMINATE); + } + + if (!output_to_file) + { + acpi_dbg_level = DEBUG_DEFAULT; + } + + /* Shutdown */ + + /* Acpi_ut_subsystem_shutdown (); */ + acpi_db_close_debug_file (); + + acpi_gbl_db_terminate_threads = TRUE; + + return (AE_CTRL_TERMINATE); + + case CMD_NOT_FOUND: + acpi_os_printf ("Unknown Command\n"); + return (AE_CTRL_TRUE); + } + + + /* Add all commands that come here to the history buffer */ + + acpi_db_add_to_history (input_buffer); + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_execute_thread + * + * PARAMETERS: Context - Not used + * + * RETURN: None + * + * DESCRIPTION: Debugger execute thread. Waits for a command line, then + * simply dispatches it. + * + ******************************************************************************/ + +void +acpi_db_execute_thread ( + void *context) +{ + ACPI_STATUS status = AE_OK; + + + while (status != AE_CTRL_TERMINATE) + { + acpi_gbl_method_executing = FALSE; + acpi_gbl_step_to_next_call = FALSE; + + acpi_ut_acquire_mutex (ACPI_MTX_DEBUG_CMD_READY); + status = acpi_db_command_dispatch (line_buf, NULL, NULL); + acpi_ut_release_mutex (ACPI_MTX_DEBUG_CMD_COMPLETE); + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_single_thread + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Debugger execute thread. Waits for a command line, then + * simply dispatches it. + * + ******************************************************************************/ + +void +acpi_db_single_thread ( + void) +{ + ACPI_STATUS status = AE_OK; + + + acpi_gbl_method_executing = FALSE; + acpi_gbl_step_to_next_call = FALSE; + + status = acpi_db_command_dispatch (line_buf, NULL, NULL); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_user_commands + * + * PARAMETERS: Prompt - User prompt (depends on mode) + * Op - Current executing parse op + * + * RETURN: None + * + * DESCRIPTION: Command line execution for the AML debugger. Commands are + * matched and dispatched here. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_db_user_commands ( + NATIVE_CHAR prompt, + ACPI_PARSE_OBJECT *op) +{ + ACPI_STATUS status = AE_OK; + + + /* TBD: [Restructure] Need a separate command line buffer for step mode */ + + while (!acpi_gbl_db_terminate_threads) + { + /* Force output to console until a command is entered */ + + acpi_db_set_output_destination (DB_CONSOLE_OUTPUT); + + /* Different prompt if method is executing */ + + if (!acpi_gbl_method_executing) + { + acpi_os_printf ("%1c ", DB_COMMAND_PROMPT); + } + else + { + acpi_os_printf ("%1c ", DB_EXECUTE_PROMPT); + } + + /* Get the user input line */ + + acpi_os_get_line (line_buf); + + + /* Check for single or multithreaded debug */ + + if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) + { + /* + * Signal the debug thread that we have a command to execute, + * and wait for the command to complete. + */ + + acpi_ut_release_mutex (ACPI_MTX_DEBUG_CMD_READY); + acpi_ut_acquire_mutex (ACPI_MTX_DEBUG_CMD_COMPLETE); + } + + else + { + /* Just call to the command line interpreter */ + + acpi_db_single_thread (); + } + } + + + /* + * Only this thread (the original thread) should actually terminate the subsystem, + * because all the semaphores are deleted during termination + */ + acpi_terminate (); + + return (status); +} + + +#endif /* ENABLE_DEBUGGER */ + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/debugger/dbstats.c linux/drivers/acpi/debugger/dbstats.c --- v2.4.5/linux/drivers/acpi/debugger/dbstats.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/debugger/dbstats.c Wed Jun 20 17:47:39 2001 @@ -0,0 +1,456 @@ +/******************************************************************************* + * + * Module Name: dbstats - Generation and display of ACPI table statistics + * $Revision: 40 $ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 + +#ifdef ENABLE_DEBUGGER + +#define _COMPONENT ACPI_DEBUGGER + MODULE_NAME ("dbstats") + +/* + * Statistics subcommands + */ +ARGUMENT_INFO acpi_db_stat_types [] = +{ {"ALLOCATIONS"}, + {"OBJECTS"}, + {"MEMORY"}, + {"MISC"}, + {"TABLES"}, + {"SIZES"}, + {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 + + +/* + * Statistic globals + */ +u16 acpi_gbl_obj_type_count[INTERNAL_TYPE_NODE_MAX+1]; +u16 acpi_gbl_node_type_count[INTERNAL_TYPE_NODE_MAX+1]; +u16 acpi_gbl_obj_type_count_misc; +u16 acpi_gbl_node_type_count_misc; +u32 num_nodes; +u32 num_objects; + + +u32 size_of_parse_tree; +u32 size_of_method_trees; +u32 size_of_node_entries; +u32 size_of_acpi_objects; + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_enumerate_object + * + * PARAMETERS: Obj_desc - Object to be counted + * + * RETURN: None + * + * DESCRIPTION: Add this object to the global counts, by object type. + * Recursively handles subobjects and packages. + * + * [TBD] Restructure - remove recursion. + * + ******************************************************************************/ + +void +acpi_db_enumerate_object ( + ACPI_OPERAND_OBJECT *obj_desc) +{ + u32 type; + u32 i; + + + if (!obj_desc) + { + return; + } + + + /* Enumerate this object first */ + + num_objects++; + + type = obj_desc->common.type; + if (type > INTERNAL_TYPE_NODE_MAX) + { + acpi_gbl_obj_type_count_misc++; + } + else + { + acpi_gbl_obj_type_count [type]++; + } + + /* Count the sub-objects */ + + switch (type) + { + case ACPI_TYPE_PACKAGE: + for (i = 0; i< obj_desc->package.count; i++) + { + acpi_db_enumerate_object (obj_desc->package.elements[i]); + } + break; + + case ACPI_TYPE_DEVICE: + acpi_db_enumerate_object (obj_desc->device.sys_handler); + acpi_db_enumerate_object (obj_desc->device.drv_handler); + acpi_db_enumerate_object (obj_desc->device.addr_handler); + break; + + case ACPI_TYPE_REGION: + acpi_db_enumerate_object (obj_desc->region.addr_handler); + break; + + case ACPI_TYPE_POWER: + acpi_db_enumerate_object (obj_desc->power_resource.sys_handler); + acpi_db_enumerate_object (obj_desc->power_resource.drv_handler); + break; + + case ACPI_TYPE_PROCESSOR: + acpi_db_enumerate_object (obj_desc->processor.sys_handler); + acpi_db_enumerate_object (obj_desc->processor.drv_handler); + acpi_db_enumerate_object (obj_desc->processor.addr_handler); + break; + + case ACPI_TYPE_THERMAL: + acpi_db_enumerate_object (obj_desc->thermal_zone.sys_handler); + acpi_db_enumerate_object (obj_desc->thermal_zone.drv_handler); + acpi_db_enumerate_object (obj_desc->thermal_zone.addr_handler); + break; + } +} + + +#ifndef PARSER_ONLY + +/******************************************************************************* + * + * FUNCTION: Acpi_db_classify_one_object + * + * PARAMETERS: Callback for Walk_namespace + * + * RETURN: Status + * + * DESCRIPTION: Enumerate both the object descriptor (including subobjects) and + * the parent namespace node. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_db_classify_one_object ( + ACPI_HANDLE obj_handle, + u32 nesting_level, + void *context, + void **return_value) +{ + ACPI_NAMESPACE_NODE *node; + ACPI_OPERAND_OBJECT *obj_desc; + u32 type; + + + num_nodes++; + + node = (ACPI_NAMESPACE_NODE *) obj_handle; + obj_desc = ((ACPI_NAMESPACE_NODE *) obj_handle)->object; + + acpi_db_enumerate_object (obj_desc); + + type = node->type; + if (type > INTERNAL_TYPE_INVALID) + { + acpi_gbl_node_type_count_misc++; + } + + else + { + acpi_gbl_node_type_count [type]++; + } + + return AE_OK; + + + /* TBD: These need to be counted during the initial parsing phase */ + /* + if (Acpi_ps_is_named_op (Op->Opcode)) + { + Num_nodes++; + } + + if (Is_method) + { + Num_method_elements++; + } + + Num_grammar_elements++; + Op = Acpi_ps_get_depth_next (Root, Op); + + Size_of_parse_tree = (Num_grammar_elements - Num_method_elements) * (u32) sizeof (ACPI_PARSE_OBJECT); + Size_of_method_trees = Num_method_elements * (u32) sizeof (ACPI_PARSE_OBJECT); + Size_of_node_entries = Num_nodes * (u32) sizeof (ACPI_NAMESPACE_NODE); + Size_of_acpi_objects = Num_nodes * (u32) sizeof (ACPI_OPERAND_OBJECT); + + */ +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_count_namespace_objects + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Count and classify the entire namespace, including all + * namespace nodes and attached objects. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_db_count_namespace_objects ( + void) +{ + u32 i; + + + num_nodes = 0; + num_objects = 0; + + acpi_gbl_obj_type_count_misc = 0; + for (i = 0; i < INTERNAL_TYPE_INVALID; i++) + { + acpi_gbl_obj_type_count [i] = 0; + acpi_gbl_node_type_count [i] = 0; + } + + 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 + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_display_statistics + * + * PARAMETERS: Type_arg - Subcommand + * + * RETURN: Status + * + * DESCRIPTION: Display various statistics + * + ******************************************************************************/ + +ACPI_STATUS +acpi_db_display_statistics ( + NATIVE_CHAR *type_arg) +{ + u32 i; + u32 type; + + + if (!acpi_gbl_DSDT) + { + acpi_os_printf ("*** Warning: There is no DSDT loaded\n"); + } + + if (!type_arg) + { + acpi_os_printf ("The following subcommands are available:\n ALLOCATIONS, OBJECTS, MEMORY, MISC, SIZES, TABLES\n"); + return (AE_OK); + } + + STRUPR (type_arg); + type = acpi_db_match_argument (type_arg, acpi_db_stat_types); + if (type == (u32) -1) + { + acpi_os_printf ("Invalid or unsupported argument\n"); + return (AE_OK); + } + +#ifndef PARSER_ONLY + + acpi_db_count_namespace_objects (); +#endif + + + switch (type) + { +#ifndef PARSER_ONLY + case CMD_ALLOCATIONS: + acpi_ut_dump_allocation_info (); + break; +#endif + + case CMD_TABLES: + + acpi_os_printf ("ACPI Table Information:\n\n"); + if (acpi_gbl_DSDT) + { + acpi_os_printf ("DSDT Length:................% 7ld (%X)\n", acpi_gbl_DSDT->length, acpi_gbl_DSDT->length); + } + break; + + case CMD_OBJECTS: + + acpi_os_printf ("\n_objects defined in the current namespace:\n\n"); + + acpi_os_printf ("%16.16s % 10.10s % 10.10s\n", "ACPI_TYPE", "NODES", "OBJECTS"); + + for (i = 0; i < INTERNAL_TYPE_NODE_MAX; i++) + { + acpi_os_printf ("%16.16s % 10ld% 10ld\n", acpi_ut_get_type_name (i), + acpi_gbl_node_type_count [i], acpi_gbl_obj_type_count [i]); + } + acpi_os_printf ("%16.16s % 10ld% 10ld\n", "Misc/Unknown", + acpi_gbl_node_type_count_misc, acpi_gbl_obj_type_count_misc); + + acpi_os_printf ("%16.16s % 10ld% 10ld\n", "TOTALS:", + num_nodes, num_objects); + + +/* + Acpi_os_printf ("\n"); + + Acpi_os_printf ("ASL/AML Grammar Usage:\n\n"); + Acpi_os_printf ("Elements Inside Methods:....% 7ld\n", Num_method_elements); + Acpi_os_printf ("Elements Outside Methods:...% 7ld\n", Num_grammar_elements - Num_method_elements); + Acpi_os_printf ("Total Grammar Elements:.....% 7ld\n", Num_grammar_elements); +*/ + break; + + case CMD_MEMORY: + + acpi_os_printf ("\n_dynamic Memory Estimates:\n\n"); + acpi_os_printf ("Parse Tree without Methods:.% 7ld\n", size_of_parse_tree); + acpi_os_printf ("Control Method Parse Trees:.% 7ld (If parsed simultaneously)\n", size_of_method_trees); + acpi_os_printf ("Namespace Nodes:............% 7ld (%d nodes)\n", sizeof (ACPI_NAMESPACE_NODE) * num_nodes, num_nodes); + acpi_os_printf ("Named Internal Objects......% 7ld\n", size_of_acpi_objects); + acpi_os_printf ("State Cache size............% 7ld\n", acpi_gbl_generic_state_cache_depth * sizeof (ACPI_GENERIC_STATE)); + acpi_os_printf ("Parse Cache size............% 7ld\n", acpi_gbl_parse_cache_depth * sizeof (ACPI_PARSE_OBJECT)); + acpi_os_printf ("Object Cache size...........% 7ld\n", acpi_gbl_object_cache_depth * sizeof (ACPI_OPERAND_OBJECT)); + acpi_os_printf ("Walk_state Cache size........% 7ld\n", acpi_gbl_walk_state_cache_depth * sizeof (ACPI_WALK_STATE)); + + acpi_os_printf ("\n"); + + acpi_os_printf ("Cache Statistics:\n\n"); + acpi_os_printf ("State Cache requests........% 7ld\n", acpi_gbl_state_cache_requests); + acpi_os_printf ("State Cache hits............% 7ld\n", acpi_gbl_state_cache_hits); + acpi_os_printf ("State Cache depth...........% 7ld (%d remaining entries)\n", acpi_gbl_generic_state_cache_depth, + MAX_STATE_CACHE_DEPTH - acpi_gbl_generic_state_cache_depth); + acpi_os_printf ("Parse Cache requests........% 7ld\n", acpi_gbl_parse_cache_requests); + acpi_os_printf ("Parse Cache hits............% 7ld\n", acpi_gbl_parse_cache_hits); + acpi_os_printf ("Parse Cache depth...........% 7ld (%d remaining entries)\n", acpi_gbl_parse_cache_depth, + MAX_PARSE_CACHE_DEPTH - acpi_gbl_parse_cache_depth); + acpi_os_printf ("Ext Parse Cache requests....% 7ld\n", acpi_gbl_ext_parse_cache_requests); + acpi_os_printf ("Ext Parse Cache hits........% 7ld\n", acpi_gbl_ext_parse_cache_hits); + acpi_os_printf ("Ext Parse Cache depth.......% 7ld (%d remaining entries)\n", acpi_gbl_ext_parse_cache_depth, + MAX_EXTPARSE_CACHE_DEPTH - acpi_gbl_ext_parse_cache_depth); + acpi_os_printf ("Object Cache requests.......% 7ld\n", acpi_gbl_object_cache_requests); + acpi_os_printf ("Object Cache hits...........% 7ld\n", acpi_gbl_object_cache_hits); + acpi_os_printf ("Object Cache depth..........% 7ld (%d remaining entries)\n", acpi_gbl_object_cache_depth, + MAX_OBJECT_CACHE_DEPTH - acpi_gbl_object_cache_depth); + acpi_os_printf ("Walk_state Cache requests....% 7ld\n", acpi_gbl_walk_state_cache_requests); + acpi_os_printf ("Walk_state Cache hits........% 7ld\n", acpi_gbl_walk_state_cache_hits); + acpi_os_printf ("Walk_state Cache depth.......% 7ld (%d remaining entries)\n", acpi_gbl_walk_state_cache_depth, + MAX_WALK_CACHE_DEPTH - acpi_gbl_walk_state_cache_depth); + break; + + case CMD_MISC: + + acpi_os_printf ("\n_miscellaneous 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); + + acpi_os_printf ("\n"); + + acpi_os_printf ("Mutex usage:\n\n"); + for (i = 0; i < NUM_MTX; i++) + { + acpi_os_printf ("%-28s: % 7ld\n", acpi_ut_get_mutex_name (i), acpi_gbl_acpi_mutex_info[i].use_count); + } + break; + + + case CMD_SIZES: + + acpi_os_printf ("\n_internal object sizes:\n\n"); + + acpi_os_printf ("Common %3d\n", sizeof (ACPI_OBJECT_COMMON)); + acpi_os_printf ("Number %3d\n", sizeof (ACPI_OBJECT_INTEGER)); + acpi_os_printf ("String %3d\n", sizeof (ACPI_OBJECT_STRING)); + acpi_os_printf ("Buffer %3d\n", sizeof (ACPI_OBJECT_BUFFER)); + acpi_os_printf ("Package %3d\n", sizeof (ACPI_OBJECT_PACKAGE)); + acpi_os_printf ("Buffer_field %3d\n", sizeof (ACPI_OBJECT_BUFFER_FIELD)); + acpi_os_printf ("Device %3d\n", sizeof (ACPI_OBJECT_DEVICE)); + acpi_os_printf ("Event %3d\n", sizeof (ACPI_OBJECT_EVENT)); + acpi_os_printf ("Method %3d\n", sizeof (ACPI_OBJECT_METHOD)); + acpi_os_printf ("Mutex %3d\n", sizeof (ACPI_OBJECT_MUTEX)); + acpi_os_printf ("Region %3d\n", sizeof (ACPI_OBJECT_REGION)); + acpi_os_printf ("Power_resource %3d\n", sizeof (ACPI_OBJECT_POWER_RESOURCE)); + acpi_os_printf ("Processor %3d\n", sizeof (ACPI_OBJECT_PROCESSOR)); + acpi_os_printf ("Thermal_zone %3d\n", sizeof (ACPI_OBJECT_THERMAL_ZONE)); + acpi_os_printf ("Region_field %3d\n", sizeof (ACPI_OBJECT_REGION_FIELD)); + acpi_os_printf ("Bank_field %3d\n", sizeof (ACPI_OBJECT_BANK_FIELD)); + acpi_os_printf ("Index_field %3d\n", sizeof (ACPI_OBJECT_INDEX_FIELD)); + acpi_os_printf ("Reference %3d\n", sizeof (ACPI_OBJECT_REFERENCE)); + acpi_os_printf ("Notify_handler %3d\n", sizeof (ACPI_OBJECT_NOTIFY_HANDLER)); + acpi_os_printf ("Addr_handler %3d\n", sizeof (ACPI_OBJECT_ADDR_HANDLER)); + acpi_os_printf ("Extra %3d\n", sizeof (ACPI_OBJECT_EXTRA)); + + 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 ("Operand_object %3d\n", sizeof (ACPI_OPERAND_OBJECT)); + acpi_os_printf ("Namespace_node %3d\n", sizeof (ACPI_NAMESPACE_NODE)); + + break; + + } + + acpi_os_printf ("\n"); + return (AE_OK); +} + + +#endif /* ENABLE_DEBUGGER */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/debugger/dbutils.c linux/drivers/acpi/debugger/dbutils.c --- v2.4.5/linux/drivers/acpi/debugger/dbutils.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/debugger/dbutils.c Wed Jun 20 17:47:39 2001 @@ -0,0 +1,354 @@ +/******************************************************************************* + * + * Module Name: dbutils - AML debugger utilities + * $Revision: 37 $ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acparser.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "acparser.h" +#include "acevents.h" +#include "acinterp.h" +#include "acdebug.h" +#include "acdispat.h" + + +#ifdef ENABLE_DEBUGGER + +#define _COMPONENT ACPI_DEBUGGER + MODULE_NAME ("dbutils") + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_set_output_destination + * + * PARAMETERS: Output_flags - Current flags word + * + * RETURN: None + * + * DESCRIPTION: Set the current destination for debugger output. Alos sets + * the debug output level accordingly. + * + ******************************************************************************/ + +void +acpi_db_set_output_destination ( + u32 output_flags) +{ + + acpi_gbl_db_output_flags = (u8) output_flags; + + if (output_flags & DB_REDIRECTABLE_OUTPUT) { + if (output_to_file) { + acpi_dbg_level = acpi_gbl_db_debug_level; + } + } + else { + acpi_dbg_level = acpi_gbl_db_console_debug_level; + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_dump_buffer + * + * PARAMETERS: Address - Pointer to the buffer + * + * RETURN: None + * + * DESCRIPTION: Print a portion of a buffer + * + ******************************************************************************/ + +void +acpi_db_dump_buffer ( + u32 address) +{ + + acpi_os_printf ("\n_location %X:\n", address); + + acpi_dbg_level |= TRACE_TABLES; + acpi_ut_dump_buffer ((u8 *) address, 64, DB_BYTE_DISPLAY, ACPI_UINT32_MAX); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_dump_object + * + * PARAMETERS: Obj_desc - External ACPI object to dump + * Level - Nesting level. + * + * RETURN: None + * + * DESCRIPTION: Dump the contents of an ACPI external object + * + ******************************************************************************/ + +void +acpi_db_dump_object ( + ACPI_OBJECT *obj_desc, + u32 level) +{ + u32 i; + + + if (!obj_desc) { + acpi_os_printf ("[Null Object]\n"); + return; + } + + for (i = 0; i < level; i++) { + acpi_os_printf (" "); + } + + switch (obj_desc->type) { + case ACPI_TYPE_ANY: + + acpi_os_printf ("[Object Reference] Value: %p\n", obj_desc->reference.handle); + break; + + + case ACPI_TYPE_INTEGER: + acpi_os_printf ("[Number] Value: %ld (%lX)\n", obj_desc->integer.value, obj_desc->integer.value); + break; + + + case ACPI_TYPE_STRING: + + acpi_os_printf ("[String] Value: "); + for (i = 0; i < obj_desc->string.length; i++) { + acpi_os_printf ("%c", obj_desc->string.pointer[i]); + } + acpi_os_printf ("\n"); + break; + + + case ACPI_TYPE_BUFFER: + + acpi_os_printf ("[Buffer] Value: "); + acpi_ut_dump_buffer ((u8 *) obj_desc->buffer.pointer, obj_desc->buffer.length, DB_DWORD_DISPLAY, _COMPONENT); + break; + + + case ACPI_TYPE_PACKAGE: + + acpi_os_printf ("[Package] Contains %d Elements: \n", obj_desc->package.count); + + for (i = 0; i < obj_desc->package.count; i++) { + acpi_db_dump_object (&obj_desc->package.elements[i], level+1); + } + break; + + + case INTERNAL_TYPE_REFERENCE: + acpi_os_printf ("[Object Reference] Value: %p\n", obj_desc->reference.handle); + break; + + case ACPI_TYPE_PROCESSOR: + acpi_os_printf ("[Processor]\n"); + break; + + case ACPI_TYPE_POWER: + acpi_os_printf ("[Power Resource]\n"); + break; + + default: + + acpi_os_printf ("[Unknown Type] %X \n", obj_desc->type); + break; + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_prep_namestring + * + * PARAMETERS: Name - String to prepare + * + * RETURN: None + * + * DESCRIPTION: Translate all forward slashes and dots to backslashes. + * + ******************************************************************************/ + +void +acpi_db_prep_namestring ( + NATIVE_CHAR *name) +{ + + + if (!name) { + return; + } + + STRUPR (name); + + /* Convert a leading forward slash to a backslash */ + + if (*name == '/') { + *name = '\\'; + } + + /* Ignore a leading backslash, this is the root prefix */ + + if (*name == '\\') { + name++; + } + + /* Convert all slash path separators to dots */ + + while (*name) { + if ((*name == '/') || + (*name == '\\')) { + *name = '.'; + } + + name++; + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_second_pass_parse + * + * PARAMETERS: Root - Root of the parse tree + * + * RETURN: Status + * + * DESCRIPTION: Second pass parse of the ACPI tables. We need to wait until + * second pass to parse the control methods + * + ******************************************************************************/ + +ACPI_STATUS +acpi_db_second_pass_parse ( + ACPI_PARSE_OBJECT *root) +{ + ACPI_PARSE_OBJECT *op = root; + ACPI_PARSE2_OBJECT *method; + ACPI_PARSE_OBJECT *search_op; + ACPI_PARSE_OBJECT *start_op; + ACPI_STATUS status = AE_OK; + u32 base_aml_offset; + + + acpi_os_printf ("Pass two parse ....\n"); + + while (op) { + if (op->opcode == AML_METHOD_OP) { + method = (ACPI_PARSE2_OBJECT *) op; + status = acpi_ps_parse_aml (op, method->data, method->length, 0, + NULL, NULL, NULL, acpi_ds_load1_begin_op, acpi_ds_load1_end_op); + + + base_aml_offset = (method->value.arg)->aml_offset + 1; + start_op = (method->value.arg)->next; + search_op = start_op; + + while (search_op) { + search_op->aml_offset += base_aml_offset; + search_op = acpi_ps_get_depth_next (start_op, search_op); + } + + } + + if (op->opcode == AML_REGION_OP) { + /* TBD: [Investigate] this isn't quite the right thing to do! */ + /* + * + * Method = (ACPI_DEFERRED_OP *) Op; + * Status = Acpi_ps_parse_aml (Op, Method->Body, Method->Body_length); + */ + } + + if (ACPI_FAILURE (status)) { + return (status); + } + + op = acpi_ps_get_depth_next (root, op); + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_local_ns_lookup + * + * PARAMETERS: Name - Name to lookup + * + * RETURN: Pointer to a namespace node + * + * DESCRIPTION: Lookup a name in the ACPI namespace + * + ******************************************************************************/ + +ACPI_NAMESPACE_NODE * +acpi_db_local_ns_lookup ( + NATIVE_CHAR *name) +{ + NATIVE_CHAR *internal_path; + ACPI_STATUS status; + ACPI_NAMESPACE_NODE *node = NULL; + + + acpi_db_prep_namestring (name); + + /* Build an internal namestring */ + + status = acpi_ns_internalize_name (name, &internal_path); + if (ACPI_FAILURE (status)) { + acpi_os_printf ("Invalid namestring: %s\n", name); + return (NULL); + } + + /* Lookup the name */ + + /* TBD: [Investigate] what scope do we use? */ + /* Use the root scope for the start of the search */ + + status = acpi_ns_lookup (NULL, internal_path, ACPI_TYPE_ANY, IMODE_EXECUTE, + NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, NULL, &node); + + if (ACPI_FAILURE (status)) { + acpi_os_printf ("Could not locate name: %s %s\n", name, acpi_ut_format_exception (status)); + } + + + acpi_ut_free (internal_path); + + return (node); +} + + +#endif /* ENABLE_DEBUGGER */ + + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/debugger/dbxface.c linux/drivers/acpi/debugger/dbxface.c --- v2.4.5/linux/drivers/acpi/debugger/dbxface.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/debugger/dbxface.c Wed Jun 20 17:47:39 2001 @@ -0,0 +1,317 @@ +/******************************************************************************* + * + * Module Name: dbxface - AML Debugger external interfaces + * $Revision: 37 $ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acparser.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "acparser.h" +#include "acevents.h" +#include "acinterp.h" +#include "acdebug.h" + + +#ifdef ENABLE_DEBUGGER + +#define _COMPONENT ACPI_DEBUGGER + MODULE_NAME ("dbxface") + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_single_step + * + * PARAMETERS: Walk_state - Current walk + * Op - Current executing op + * Op_type - Type of the current AML Opcode + * + * RETURN: Status + * + * DESCRIPTION: Called just before execution of an AML opcode. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_db_single_step ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op, + u8 op_type) +{ + ACPI_PARSE_OBJECT *next; + ACPI_STATUS status = AE_OK; + u32 original_debug_level; + ACPI_PARSE_OBJECT *display_op; + + + /* Is there a breakpoint set? */ + + if (walk_state->method_breakpoint) { + /* Check if the breakpoint has been reached or passed */ + + if (walk_state->method_breakpoint <= op->aml_offset) { + /* Hit the breakpoint, resume single step, reset breakpoint */ + + acpi_os_printf ("***Break*** at AML offset %X\n", op->aml_offset); + acpi_gbl_cm_single_step = TRUE; + acpi_gbl_step_to_next_call = FALSE; + walk_state->method_breakpoint = 0; + } + } + + + /* + * Check if this is an opcode that we are interested in -- + * namely, opcodes that have arguments + */ + + if (op->opcode == AML_INT_NAMEDFIELD_OP) { + return (AE_OK); + } + + switch (op_type) { + case OPTYPE_UNDEFINED: + case OPTYPE_CONSTANT: /* argument type only */ + case OPTYPE_LITERAL: /* argument type only */ + case OPTYPE_DATA_TERM: /* argument type only */ + case OPTYPE_LOCAL_VARIABLE: /* argument type only */ + case OPTYPE_METHOD_ARGUMENT: /* argument type only */ + return (AE_OK); + break; + + case OPTYPE_NAMED_OBJECT: + switch (op->opcode) { + case AML_INT_NAMEPATH_OP: + return (AE_OK); + break; + } + } + + + /* + * Under certain debug conditions, display this opcode and its operands + */ + + if ((output_to_file) || + (acpi_gbl_cm_single_step) || + (acpi_dbg_level & TRACE_PARSE)) { + if ((output_to_file) || + (acpi_dbg_level & TRACE_PARSE)) { + acpi_os_printf ("\n[Aml_debug] Next AML Opcode to execute:\n"); + } + + /* + * Display this op (and only this op - zero out the NEXT field temporarily, + * and disable parser trace output for the duration of the display because + * we don't want the extraneous debug output) + */ + + original_debug_level = acpi_dbg_level; + acpi_dbg_level &= ~(TRACE_PARSE | TRACE_FUNCTIONS); + next = op->next; + op->next = NULL; + + + display_op = op; + if (op->parent) { + if ((op->parent->opcode == AML_IF_OP) || + (op->parent->opcode == AML_WHILE_OP)) { + display_op = op->parent; + } + } + + /* Now we can display it */ + + acpi_db_display_op (walk_state, display_op, ACPI_UINT32_MAX); + + if ((op->opcode == AML_IF_OP) || + (op->opcode == AML_WHILE_OP)) { + if (walk_state->control_state->common.value) { + acpi_os_printf ("Predicate was TRUE, executed block\n"); + } + else { + acpi_os_printf ("Predicate is FALSE, skipping block\n"); + } + } + + else if (op->opcode == AML_ELSE_OP) { + /* TBD */ + } + + + /* Restore everything */ + + op->next = next; + acpi_os_printf ("\n"); + acpi_dbg_level = original_debug_level; + } + + + /* If we are not single stepping, just continue executing the method */ + + if (!acpi_gbl_cm_single_step) { + return (AE_OK); + } + + + /* + * If we are executing a step-to-call command, + * Check if this is a method call. + */ + + if (acpi_gbl_step_to_next_call) { + if (op->opcode != AML_INT_METHODCALL_OP) { + /* Not a method call, just keep executing */ + + return (AE_OK); + } + + /* Found a method call, stop executing */ + + acpi_gbl_step_to_next_call = FALSE; + } + + + /* + * If the next opcode is a method call, we will "step over" it + * by default. + */ + + if (op->opcode == AML_INT_METHODCALL_OP) { + acpi_gbl_cm_single_step = FALSE; /* No more single step while executing called method */ + + /* Set the breakpoint on the call, it will stop execution as soon as we return */ + + /* TBD: [Future] don't kill the user breakpoint! */ + + walk_state->method_breakpoint = /* Op->Aml_offset + */ 1; /* Must be non-zero! */ + } + + + /* TBD: [Investigate] what are the namespace locking issues here */ + + /* Acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); */ + + /* Go into the command loop and await next user command */ + + acpi_gbl_method_executing = TRUE; + status = AE_CTRL_TRUE; + while (status == AE_CTRL_TRUE) { + if (acpi_gbl_debugger_configuration == DEBUGGER_MULTI_THREADED) { + /* Handshake with the front-end that gets user command lines */ + + acpi_ut_release_mutex (ACPI_MTX_DEBUG_CMD_COMPLETE); + acpi_ut_acquire_mutex (ACPI_MTX_DEBUG_CMD_READY); + } + + else { + /* Single threaded, we must get a command line ourselves */ + + /* Force output to console until a command is entered */ + + acpi_db_set_output_destination (DB_CONSOLE_OUTPUT); + + /* Different prompt if method is executing */ + + if (!acpi_gbl_method_executing) { + acpi_os_printf ("%1c ", DB_COMMAND_PROMPT); + } + else { + acpi_os_printf ("%1c ", DB_EXECUTE_PROMPT); + } + + /* Get the user input line */ + + acpi_os_get_line (line_buf); + } + + status = acpi_db_command_dispatch (line_buf, walk_state, op); + } + + /* Acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); */ + + + /* User commands complete, continue execution of the interrupted method */ + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_db_initialize + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Init and start debugger + * + ******************************************************************************/ + +int +acpi_db_initialize (void) +{ + + + /* Init globals */ + + buffer = acpi_os_allocate (BUFFER_SIZE); + + /* Initial scope is the root */ + + scope_buf [0] = '\\'; + scope_buf [1] = 0; + + + /* + * If configured for multi-thread support, the debug executor runs in + * a separate thread so that the front end can be in another address + * space, environment, or even another machine. + */ + + 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); + + /* Create the debug execution thread to execute commands */ + + acpi_os_queue_for_execution (0, acpi_db_execute_thread, NULL); + } + + if (!opt_verbose) { + INDENT_STRING = " "; + opt_disasm = TRUE; + opt_stats = FALSE; + } + + + return (0); +} + + +#endif /* ENABLE_DEBUGGER */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/dispatcher/Makefile linux/drivers/acpi/dispatcher/Makefile --- v2.4.5/linux/drivers/acpi/dispatcher/Makefile Fri Dec 29 14:07:21 2000 +++ linux/drivers/acpi/dispatcher/Makefile Wed Jun 20 17:47:39 2001 @@ -1,16 +1,12 @@ # # Makefile for all Linux ACPI interpreter subdirectories +# EXCEPT for the ospm directory # -O_TARGET := ../$(shell basename `pwd`).o +O_TARGET := $(notdir $(CURDIR)).o obj-$(CONFIG_ACPI) := $(patsubst %.c,%.o,$(wildcard *.c)) -EXTRA_CFLAGS += -I../include - EXTRA_CFLAGS += $(ACPI_CFLAGS) include $(TOPDIR)/Rules.make - -clean: - $(RM) *.o diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/dispatcher/dsfield.c linux/drivers/acpi/dispatcher/dsfield.c --- v2.4.5/linux/drivers/acpi/dispatcher/dsfield.c Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/dispatcher/dsfield.c Wed Jun 20 17:47:39 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: dsfield - Dispatcher field routines - * $Revision: 31 $ + * $Revision: 41 $ * *****************************************************************************/ @@ -31,7 +31,7 @@ #include "acnamesp.h" -#define _COMPONENT DISPATCHER +#define _COMPONENT ACPI_DISPATCHER MODULE_NAME ("dsfield") @@ -51,7 +51,8 @@ * FUNCTION: Acpi_ds_create_field * * PARAMETERS: Op - Op containing the Field definition and args - * Region_node - Object for the containing Operation Region + * Region_node - Object for the containing Operation Region + * ` Walk_state - Current method state * * RETURN: Status * @@ -69,7 +70,6 @@ ACPI_PARSE_OBJECT *arg; ACPI_NAMESPACE_NODE *node; u8 field_flags; - u8 access_attribute = 0; u32 field_bit_position = 0; @@ -78,10 +78,8 @@ arg = op->value.arg; if (!region_node) { status = acpi_ns_lookup (walk_state->scope_info, arg->value.name, - ACPI_TYPE_REGION, IMODE_EXECUTE, - NS_SEARCH_PARENT, walk_state, - ®ion_node); - + ACPI_TYPE_REGION, IMODE_EXECUTE, + NS_SEARCH_PARENT, walk_state, ®ion_node); if (ACPI_FAILURE (status)) { return (status); } @@ -96,37 +94,31 @@ arg = arg->next; while (arg) { - switch (arg->opcode) - { - case AML_RESERVEDFIELD_OP: + switch (arg->opcode) { + case AML_INT_RESERVEDFIELD_OP: field_bit_position += arg->value.size; break; - case AML_ACCESSFIELD_OP: + case AML_INT_ACCESSFIELD_OP: /* * Get a new Access_type and Access_attribute for all * entries (until end or another Access_as keyword) */ - - access_attribute = (u8) arg->value.integer; - field_flags = (u8) - ((field_flags & FIELD_ACCESS_TYPE_MASK) || - ((u8) (arg->value.integer >> 8))); + field_flags = (u8) ((field_flags & FIELD_ACCESS_TYPE_MASK) || + ((u8) (arg->value.integer >> 8))); break; - case AML_NAMEDFIELD_OP: + case AML_INT_NAMEDFIELD_OP: status = acpi_ns_lookup (walk_state->scope_info, (NATIVE_CHAR *) &((ACPI_PARSE2_OBJECT *)arg)->name, - INTERNAL_TYPE_DEF_FIELD, - IMODE_LOAD_PASS1, + INTERNAL_TYPE_REGION_FIELD, IMODE_LOAD_PASS1, NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, NULL, &node); - if (ACPI_FAILURE (status)) { return (status); } @@ -136,9 +128,8 @@ * the object stack */ - status = acpi_aml_prep_def_field_value (node, region_node, field_flags, - access_attribute, field_bit_position, arg->value.size); - + status = acpi_ex_prep_region_field_value (node, region_node, field_flags, + field_bit_position, arg->value.size); if (ACPI_FAILURE (status)) { return (status); } @@ -161,7 +152,8 @@ * FUNCTION: Acpi_ds_create_bank_field * * PARAMETERS: Op - Op containing the Field definition and args - * Region_node - Object for the containing Operation Region + * Region_node - Object for the containing Operation Region + * ` Walk_state - Current method state * * RETURN: Status * @@ -181,7 +173,6 @@ ACPI_NAMESPACE_NODE *node; u32 bank_value; u8 field_flags; - u8 access_attribute = 0; u32 field_bit_position = 0; @@ -190,10 +181,8 @@ arg = op->value.arg; if (!region_node) { status = acpi_ns_lookup (walk_state->scope_info, arg->value.name, - ACPI_TYPE_REGION, IMODE_EXECUTE, - NS_SEARCH_PARENT, walk_state, - ®ion_node); - + ACPI_TYPE_REGION, IMODE_EXECUTE, + NS_SEARCH_PARENT, walk_state, ®ion_node); if (ACPI_FAILURE (status)) { return (status); } @@ -204,11 +193,9 @@ arg = arg->next; status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, - INTERNAL_TYPE_BANK_FIELD_DEFN, - IMODE_LOAD_PASS1, - NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, - NULL, ®ister_node); - + INTERNAL_TYPE_BANK_FIELD_DEFN, IMODE_LOAD_PASS1, + NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, + NULL, ®ister_node); if (ACPI_FAILURE (status)) { return (status); } @@ -228,37 +215,31 @@ arg = arg->next; while (arg) { - switch (arg->opcode) - { - case AML_RESERVEDFIELD_OP: + switch (arg->opcode) { + case AML_INT_RESERVEDFIELD_OP: field_bit_position += arg->value.size; break; - case AML_ACCESSFIELD_OP: + case AML_INT_ACCESSFIELD_OP: /* * Get a new Access_type and Access_attribute for * all entries (until end or another Access_as keyword) */ - - access_attribute = (u8) arg->value.integer; - field_flags = (u8) - ((field_flags & FIELD_ACCESS_TYPE_MASK) || - ((u8) (arg->value.integer >> 8))); + field_flags = (u8) ((field_flags & FIELD_ACCESS_TYPE_MASK) || + ((u8) (arg->value.integer >> 8))); break; - case AML_NAMEDFIELD_OP: + case AML_INT_NAMEDFIELD_OP: status = acpi_ns_lookup (walk_state->scope_info, (NATIVE_CHAR *) &((ACPI_PARSE2_OBJECT *)arg)->name, - INTERNAL_TYPE_DEF_FIELD, - IMODE_LOAD_PASS1, + INTERNAL_TYPE_REGION_FIELD, IMODE_LOAD_PASS1, NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, NULL, &node); - if (ACPI_FAILURE (status)) { return (status); } @@ -268,10 +249,9 @@ * the object stack */ - status = acpi_aml_prep_bank_field_value (node, region_node, register_node, - bank_value, field_flags, access_attribute, - field_bit_position, arg->value.size); - + status = acpi_ex_prep_bank_field_value (node, region_node, register_node, + bank_value, field_flags, field_bit_position, + arg->value.size); if (ACPI_FAILURE (status)) { return (status); } @@ -295,7 +275,8 @@ * FUNCTION: Acpi_ds_create_index_field * * PARAMETERS: Op - Op containing the Field definition and args - * Region_node - Object for the containing Operation Region + * Region_node - Object for the containing Operation Region + * ` Walk_state - Current method state * * RETURN: Status * @@ -306,7 +287,7 @@ ACPI_STATUS acpi_ds_create_index_field ( ACPI_PARSE_OBJECT *op, - ACPI_HANDLE region_node, + ACPI_NAMESPACE_NODE *region_node, ACPI_WALK_STATE *walk_state) { ACPI_STATUS status; @@ -315,7 +296,6 @@ ACPI_NAMESPACE_NODE *index_register_node; ACPI_NAMESPACE_NODE *data_register_node; u8 field_flags; - u8 access_attribute = 0; u32 field_bit_position = 0; @@ -324,10 +304,9 @@ /* First arg is the name of the Index register */ status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, - ACPI_TYPE_ANY, IMODE_LOAD_PASS1, - NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, - NULL, &index_register_node); - + ACPI_TYPE_ANY, IMODE_LOAD_PASS1, + NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, + NULL, &index_register_node); if (ACPI_FAILURE (status)) { return (status); } @@ -337,11 +316,9 @@ arg = arg->next; status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, - INTERNAL_TYPE_INDEX_FIELD_DEFN, - IMODE_LOAD_PASS1, - NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, - NULL, &data_register_node); - + INTERNAL_TYPE_INDEX_FIELD_DEFN, IMODE_LOAD_PASS1, + NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, + NULL, &data_register_node); if (ACPI_FAILURE (status)) { return (status); } @@ -357,37 +334,31 @@ arg = arg->next; while (arg) { - switch (arg->opcode) - { - case AML_RESERVEDFIELD_OP: + switch (arg->opcode) { + case AML_INT_RESERVEDFIELD_OP: field_bit_position += arg->value.size; break; - case AML_ACCESSFIELD_OP: + case AML_INT_ACCESSFIELD_OP: /* * Get a new Access_type and Access_attribute for all * entries (until end or another Access_as keyword) */ - - access_attribute = (u8) arg->value.integer; - field_flags = (u8) - ((field_flags & FIELD_ACCESS_TYPE_MASK) || - ((u8) (arg->value.integer >> 8))); + field_flags = (u8) ((field_flags & FIELD_ACCESS_TYPE_MASK) || + ((u8) (arg->value.integer >> 8))); break; - case AML_NAMEDFIELD_OP: + case AML_INT_NAMEDFIELD_OP: status = acpi_ns_lookup (walk_state->scope_info, - (NATIVE_CHAR *) &((ACPI_PARSE2_OBJECT *)arg)->name, - INTERNAL_TYPE_INDEX_FIELD, - IMODE_LOAD_PASS1, - NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, - NULL, &node); - + (NATIVE_CHAR *) &((ACPI_PARSE2_OBJECT *)arg)->name, + INTERNAL_TYPE_INDEX_FIELD, IMODE_LOAD_PASS1, + NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, + NULL, &node); if (ACPI_FAILURE (status)) { return (status); } @@ -397,10 +368,9 @@ * the object stack */ - status = acpi_aml_prep_index_field_value (node, index_register_node, data_register_node, - field_flags, access_attribute, + status = acpi_ex_prep_index_field_value (node, index_register_node, + data_register_node, field_flags, field_bit_position, arg->value.size); - if (ACPI_FAILURE (status)) { return (status); } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/dispatcher/dsmethod.c linux/drivers/acpi/dispatcher/dsmethod.c --- v2.4.5/linux/drivers/acpi/dispatcher/dsmethod.c Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/dispatcher/dsmethod.c Wed Jun 20 17:47:39 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: dsmethod - Parser/Interpreter interface - control method parsing - * $Revision: 56 $ + * $Revision: 63 $ * *****************************************************************************/ @@ -34,7 +34,7 @@ #include "acdebug.h" -#define _COMPONENT DISPATCHER +#define _COMPONENT ACPI_DISPATCHER MODULE_NAME ("dsmethod") @@ -85,9 +85,9 @@ /* Create a mutex for the method if there is a concurrency limit */ if ((obj_desc->method.concurrency != INFINITE_CONCURRENCY) && - (!obj_desc->method.semaphore)) - { - status = acpi_os_create_semaphore (1,obj_desc->method.concurrency, + (!obj_desc->method.semaphore)) { + status = acpi_os_create_semaphore (obj_desc->method.concurrency, + obj_desc->method.concurrency, &obj_desc->method.semaphore); if (ACPI_FAILURE (status)) { return (status); @@ -98,7 +98,6 @@ * Allocate a new parser op to be the root of the parsed * method tree */ - op = acpi_ps_alloc_op (AML_METHOD_OP); if (!op) { return (AE_NO_MEMORY); @@ -113,15 +112,13 @@ /* * Parse the method, first pass * - * The first pass load is - * where newly declared named objects are + * The first pass load is where newly declared named objects are * added into the namespace. Actual evaluation of * the named objects (what would be called a "second * pass") happens during the actual execution of the * method so that operands to the named objects can * take on dynamic run-time values. */ - status = acpi_ps_parse_aml (op, obj_desc->method.pcode, obj_desc->method.pcode_length, ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE, @@ -134,7 +131,7 @@ /* Get a new Owner_id for objects created by this method */ - owner_id = acpi_cm_allocate_owner_id (OWNER_TYPE_METHOD); + owner_id = acpi_ut_allocate_owner_id (OWNER_TYPE_METHOD); obj_desc->method.owning_id = owner_id; /* Install the parsed tree in the method object */ @@ -142,7 +139,6 @@ acpi_ps_delete_parse_tree (op); - return (status); } @@ -151,8 +147,9 @@ * * FUNCTION: Acpi_ds_begin_method_execution * - * PARAMETERS: Method_node - Node of the method + * PARAMETERS: Method_node - Node of the method * Obj_desc - The method object + * Calling_method_node - Caller of this method (if non-null) * * RETURN: Status * @@ -167,7 +164,8 @@ ACPI_STATUS acpi_ds_begin_method_execution ( ACPI_NAMESPACE_NODE *method_node, - ACPI_OPERAND_OBJECT *obj_desc) + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_NAMESPACE_NODE *calling_method_node) { ACPI_STATUS status = AE_OK; @@ -176,34 +174,41 @@ return (AE_NULL_ENTRY); } - obj_desc = acpi_ns_get_attached_object (method_node); - if (!obj_desc) { - return (AE_NULL_OBJECT); - } - /* * If there is a concurrency limit on this method, we need to - * obtain a unit from the method semaphore. This releases the - * interpreter if we block + * obtain a unit from the method semaphore. */ - if (obj_desc->method.semaphore) { - status = acpi_aml_system_wait_semaphore (obj_desc->method.semaphore, + /* + * Allow recursive method calls, up to the reentrancy/concurrency + * limit imposed by the SERIALIZED rule and the Sync_level method + * parameter. + * + * The point of this code is to avoid permanently blocking a + * thread that is making recursive method calls. + */ + if (method_node == calling_method_node) { + if (obj_desc->method.thread_count >= obj_desc->method.concurrency) { + return (AE_AML_METHOD_LIMIT); + } + } + + /* + * Get a unit from the method semaphore. This releases the + * interpreter if we block + */ + status = acpi_ex_system_wait_semaphore (obj_desc->method.semaphore, WAIT_FOREVER); } /* - * Increment the method parse tree thread count since there - * is one additional thread executing in it. If configured - * for deletion-on-exit, the parse tree will be deleted when - * the last thread completes execution of the method + * Increment the method parse tree thread count since it has been + * reentered one more time (even if it is the same thread) */ - obj_desc->method.thread_count++; - return (status); } @@ -238,7 +243,6 @@ /* * Get the namespace entry for the control method we are about to call */ - method_node = this_walk_state->method_call_node; if (!method_node) { return (AE_NULL_ENTRY); @@ -252,12 +256,12 @@ /* Init for new method, wait on concurrency semaphore */ - status = acpi_ds_begin_method_execution (method_node, obj_desc); + status = acpi_ds_begin_method_execution (method_node, obj_desc, + this_walk_state->method_node); if (ACPI_FAILURE (status)) { return (status); } - /* Create and initialize a new parser state */ parser_state = acpi_ps_create_state (obj_desc->method.pcode, @@ -307,7 +311,6 @@ * stack. Operands on the previous walk state stack always * start at index 0. */ - status = acpi_ds_method_data_init_args (&this_walk_state->operands[0], this_walk_state->num_operands, next_walk_state); @@ -335,9 +338,8 @@ * Delete the operands on the previous walkstate operand stack * (they were copied to new objects) */ - for (i = 0; i < obj_desc->method.param_count; i++) { - acpi_cm_remove_reference (this_walk_state->operands [i]); + acpi_ut_remove_reference (this_walk_state->operands [i]); this_walk_state->operands [i] = NULL; } @@ -386,10 +388,9 @@ * Get the return value (if any) from the previous method. * NULL if no return value */ - status = acpi_ds_result_push (return_desc, walk_state); if (ACPI_FAILURE (status)) { - acpi_cm_remove_reference (return_desc); + acpi_ut_remove_reference (return_desc); return (status); } } @@ -399,7 +400,7 @@ * Delete the return value if it will not be used by the * calling method */ - acpi_cm_remove_reference (return_desc); + acpi_ut_remove_reference (return_desc); } } @@ -427,7 +428,6 @@ acpi_ds_terminate_control_method ( ACPI_WALK_STATE *walk_state) { - ACPI_STATUS status; ACPI_OPERAND_OBJECT *obj_desc; ACPI_NAMESPACE_NODE *method_node; @@ -448,15 +448,14 @@ * If this is the last thread executing the method, * we have additional cleanup to perform */ - - acpi_cm_acquire_mutex (ACPI_MTX_PARSER); + acpi_ut_acquire_mutex (ACPI_MTX_PARSER); /* Signal completion of the execution of this method if necessary */ if (walk_state->method_desc->method.semaphore) { - status = acpi_os_signal_semaphore ( - walk_state->method_desc->method.semaphore, 1); + acpi_os_signal_semaphore ( + walk_state->method_desc->method.semaphore, 1); } /* Decrement the thread count on the method parse tree */ @@ -470,11 +469,12 @@ * The method Node is stored in the walk state */ method_node = walk_state->method_node; + /* * Delete any namespace entries created immediately underneath * the method */ - acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); if (method_node->child) { acpi_ns_delete_namespace_subtree (method_node); } @@ -484,10 +484,10 @@ * the namespace */ acpi_ns_delete_namespace_by_owner (walk_state->method_desc->method.owning_id); - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); } - acpi_cm_release_mutex (ACPI_MTX_PARSER); + acpi_ut_release_mutex (ACPI_MTX_PARSER); return (AE_OK); } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/dispatcher/dsmthdat.c linux/drivers/acpi/dispatcher/dsmthdat.c --- v2.4.5/linux/drivers/acpi/dispatcher/dsmthdat.c Mon Jan 29 10:15:58 2001 +++ linux/drivers/acpi/dispatcher/dsmthdat.c Wed Jun 20 17:47:39 2001 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: dsmthdat - control method arguments and local variables - * $Revision: 39 $ + * $Revision: 46 $ * ******************************************************************************/ @@ -32,7 +32,7 @@ #include "acnamesp.h" -#define _COMPONENT DISPATCHER +#define _COMPONENT ACPI_DISPATCHER MODULE_NAME ("dsmthdat") @@ -60,7 +60,7 @@ /* * Walk_state fields are initialized to zero by the - * Acpi_cm_callocate(). + * Acpi_ut_callocate(). * * An Node is assigned to each argument and local so * that Ref_of() can return a pointer to the Node. @@ -125,7 +125,7 @@ /* Was given a ref when stored */ - acpi_cm_remove_reference (object); + acpi_ut_remove_reference (object); } } @@ -141,7 +141,7 @@ /* Was given a ref when stored */ - acpi_cm_remove_reference (object); + acpi_ut_remove_reference (object); } } @@ -182,16 +182,15 @@ for (pindex = mindex = 0; (mindex < MTH_NUM_ARGS) && (pindex < max_param_count); - mindex++) - { + mindex++) { if (params[pindex]) { /* * A valid parameter. * Set the current method argument to the * Params[Pindex++] argument object descriptor */ - status = acpi_ds_method_data_set_value (MTH_TYPE_ARG, mindex, - params[pindex], walk_state); + status = acpi_ds_store_object_to_local (AML_ARG_OP, mindex, + params[pindex], walk_state); if (ACPI_FAILURE (status)) { break; } @@ -212,7 +211,7 @@ * * FUNCTION: Acpi_ds_method_data_get_entry * - * PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG + * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP * Index - Which local_var or argument to get * Entry - Pointer to where a pointer to the stack * entry is returned. @@ -220,13 +219,13 @@ * * RETURN: Status * - * DESCRIPTION: Get the address of the stack entry given by Type:Index + * DESCRIPTION: Get the address of the object entry given by Opcode:Index * ******************************************************************************/ ACPI_STATUS acpi_ds_method_data_get_entry ( - u32 type, + u16 opcode, u32 index, ACPI_WALK_STATE *walk_state, ACPI_OPERAND_OBJECT ***entry) @@ -235,31 +234,30 @@ /* * Get the requested object. - * The stack "Type" is either a Local_variable or an Argument + * The stack "Opcode" is either a Local_variable or an Argument */ - switch (type) - { + switch (opcode) { - case MTH_TYPE_LOCAL: + case AML_LOCAL_OP: if (index > MTH_MAX_LOCAL) { return (AE_BAD_PARAMETER); } - *entry = - (ACPI_OPERAND_OBJECT **) &walk_state->local_variables[index].object; + *entry = (ACPI_OPERAND_OBJECT **) + &walk_state->local_variables[index].object; break; - case MTH_TYPE_ARG: + case AML_ARG_OP: if (index > MTH_MAX_ARG) { return (AE_BAD_PARAMETER); } - *entry = - (ACPI_OPERAND_OBJECT **) &walk_state->arguments[index].object; + *entry = (ACPI_OPERAND_OBJECT **) + &walk_state->arguments[index].object; break; @@ -276,20 +274,20 @@ * * FUNCTION: Acpi_ds_method_data_set_entry * - * PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG + * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP * Index - Which local_var or argument to get * Object - Object to be inserted into the stack entry * Walk_state - Current walk state object * * RETURN: Status * - * DESCRIPTION: Insert an object onto the method stack at entry Type:Index. + * DESCRIPTION: Insert an object onto the method stack at entry Opcode:Index. * ******************************************************************************/ ACPI_STATUS acpi_ds_method_data_set_entry ( - u32 type, + u16 opcode, u32 index, ACPI_OPERAND_OBJECT *object, ACPI_WALK_STATE *walk_state) @@ -300,14 +298,14 @@ /* Get a pointer to the stack entry to set */ - status = acpi_ds_method_data_get_entry (type, index, walk_state, &entry); + status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry); if (ACPI_FAILURE (status)) { return (status); } /* Increment ref count so object can't be deleted while installed */ - acpi_cm_add_reference (object); + acpi_ut_add_reference (object); /* Install the object into the stack entry */ @@ -321,7 +319,7 @@ * * FUNCTION: Acpi_ds_method_data_get_type * - * PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG + * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP * Index - Which local_var or argument whose type * to get * Walk_state - Current walk state object @@ -331,9 +329,9 @@ * ******************************************************************************/ -OBJECT_TYPE_INTERNAL +ACPI_OBJECT_TYPE8 acpi_ds_method_data_get_type ( - u32 type, + u16 opcode, u32 index, ACPI_WALK_STATE *walk_state) { @@ -344,7 +342,7 @@ /* Get a pointer to the requested stack entry */ - status = acpi_ds_method_data_get_entry (type, index, walk_state, &entry); + status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry); if (ACPI_FAILURE (status)) { return ((ACPI_TYPE_NOT_FOUND)); } @@ -366,9 +364,9 @@ /******************************************************************************* * - * FUNCTION: Acpi_ds_method_data_get_nte + * FUNCTION: Acpi_ds_method_data_get_node * - * PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG + * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP * Index - Which local_var or argument whose type * to get * Walk_state - Current walk state object @@ -378,18 +376,17 @@ ******************************************************************************/ ACPI_NAMESPACE_NODE * -acpi_ds_method_data_get_nte ( - u32 type, +acpi_ds_method_data_get_node ( + u16 opcode, u32 index, ACPI_WALK_STATE *walk_state) { ACPI_NAMESPACE_NODE *node = NULL; - switch (type) - { + switch (opcode) { - case MTH_TYPE_LOCAL: + case AML_LOCAL_OP: if (index > MTH_MAX_LOCAL) { return (node); @@ -399,7 +396,7 @@ break; - case MTH_TYPE_ARG: + case AML_ARG_OP: if (index > MTH_MAX_ARG) { return (node); @@ -422,7 +419,7 @@ * * FUNCTION: Acpi_ds_method_data_get_value * - * PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG + * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP * Index - Which local_var or argument to get * Walk_state - Current walk state object * *Dest_desc - Ptr to Descriptor into which selected Arg @@ -432,13 +429,13 @@ * * DESCRIPTION: Retrieve value of selected Arg or Local from the method frame * at the current top of the method stack. - * Used only in Acpi_aml_resolve_to_value(). + * Used only in Acpi_ex_resolve_to_value(). * ******************************************************************************/ ACPI_STATUS acpi_ds_method_data_get_value ( - u32 type, + u16 opcode, u32 index, ACPI_WALK_STATE *walk_state, ACPI_OPERAND_OBJECT **dest_desc) @@ -457,7 +454,7 @@ /* Get a pointer to the requested method stack entry */ - status = acpi_ds_method_data_get_entry (type, index, walk_state, &entry); + status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry); if (ACPI_FAILURE (status)) { return (status); } @@ -478,14 +475,13 @@ * before it was initialized. Either case is an error. */ - switch (type) - { - case MTH_TYPE_ARG: + switch (opcode) { + case AML_ARG_OP: return (AE_AML_UNINITIALIZED_ARG); break; - case MTH_TYPE_LOCAL: + case AML_LOCAL_OP: return (AE_AML_UNINITIALIZED_LOCAL); break; @@ -499,7 +495,7 @@ */ *dest_desc = object; - acpi_cm_add_reference (object); + acpi_ut_add_reference (object); return (AE_OK); } @@ -509,20 +505,20 @@ * * FUNCTION: Acpi_ds_method_data_delete_value * - * PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG + * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP * Index - Which local_var or argument to delete * Walk_state - Current walk state object * * RETURN: Status * - * DESCRIPTION: Delete the entry at Type:Index on the method stack. Inserts + * 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 acpi_ds_method_data_delete_value ( - u32 type, + u16 opcode, u32 index, ACPI_WALK_STATE *walk_state) { @@ -533,7 +529,7 @@ /* Get a pointer to the requested entry */ - status = acpi_ds_method_data_get_entry (type, index, walk_state, &entry); + status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry); if (ACPI_FAILURE (status)) { return (status); } @@ -551,14 +547,13 @@ if ((object) && - (VALID_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_INTERNAL))) - { + (VALID_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_INTERNAL))) { /* * There is a valid object in this slot * Decrement the reference count by one to balance the * increment when the object was stored in the slot. */ - acpi_cm_remove_reference (object); + acpi_ut_remove_reference (object); } @@ -568,9 +563,9 @@ /******************************************************************************* * - * FUNCTION: Acpi_ds_method_data_set_value + * FUNCTION: Acpi_ds_store_object_to_local * - * PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG + * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP * Index - Which local_var or argument to set * Src_desc - Value to be stored * Walk_state - Current walk state @@ -584,8 +579,8 @@ ******************************************************************************/ ACPI_STATUS -acpi_ds_method_data_set_value ( - u32 type, +acpi_ds_store_object_to_local ( + u16 opcode, u32 index, ACPI_OPERAND_OBJECT *src_desc, ACPI_WALK_STATE *walk_state) @@ -603,7 +598,7 @@ /* Get a pointer to the requested method stack entry */ - status = acpi_ds_method_data_get_entry (type, index, walk_state, &entry); + status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry); if (ACPI_FAILURE (status)) { goto cleanup; } @@ -638,9 +633,8 @@ * Weird, but true. */ - if ((type == MTH_TYPE_ARG) && - (VALID_DESCRIPTOR_TYPE (*entry, ACPI_DESC_TYPE_NAMED))) - { + if ((opcode == AML_ARG_OP) && + (VALID_DESCRIPTOR_TYPE (*entry, ACPI_DESC_TYPE_NAMED))) { /* Detach an existing object from the Node */ acpi_ns_detach_object ((ACPI_NAMESPACE_NODE *) *entry); @@ -655,20 +649,22 @@ } +#ifdef ACPI_ENABLE_IMPLICIT_CONVERSION /* * Perform "Implicit conversion" of the new object to the type of the * existing object */ - status = acpi_aml_convert_to_target_type ((*entry)->common.type, &src_desc, walk_state); + status = acpi_ex_convert_to_target_type ((*entry)->common.type, &src_desc, walk_state); if (ACPI_FAILURE (status)) { goto cleanup; } +#endif /* * Delete the existing object * before storing the new one */ - acpi_ds_method_data_delete_value (type, index, walk_state); + acpi_ds_method_data_delete_value (opcode, index, walk_state); } @@ -678,7 +674,7 @@ * Install the new object in the stack entry * (increments the object reference count by one) */ - status = acpi_ds_method_data_set_entry (type, index, src_desc, walk_state); + status = acpi_ds_method_data_set_entry (opcode, index, src_desc, walk_state); if (ACPI_FAILURE (status)) { goto cleanup; } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/dispatcher/dsobject.c linux/drivers/acpi/dispatcher/dsobject.c --- v2.4.5/linux/drivers/acpi/dispatcher/dsobject.c Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/dispatcher/dsobject.c Wed Jun 20 17:47:39 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: dsobject - Dispatcher object management routines - * $Revision: 57 $ + * $Revision: 65 $ * *****************************************************************************/ @@ -31,7 +31,7 @@ #include "acinterp.h" #include "acnamesp.h" -#define _COMPONENT DISPATCHER +#define _COMPONENT ACPI_DISPATCHER MODULE_NAME ("dsobject") @@ -62,12 +62,15 @@ void *context, void **return_value) { - OBJECT_TYPE_INTERNAL type; + ACPI_OBJECT_TYPE8 type; ACPI_STATUS status; ACPI_INIT_WALK_INFO *info = (ACPI_INIT_WALK_INFO *) context; u8 table_revision; + PROC_NAME ("Ds_init_one_object"); + + info->object_count++; table_revision = info->table_desc->pointer->revision; @@ -77,8 +80,7 @@ */ if (((ACPI_NAMESPACE_NODE *) obj_handle)->owner_id != - info->table_desc->table_id) - { + info->table_desc->table_id) { return (AE_OK); } @@ -87,8 +89,7 @@ type = acpi_ns_get_type (obj_handle); - switch (type) - { + switch (type) { case ACPI_TYPE_REGION: @@ -174,9 +175,8 @@ /* Walk entire namespace from the supplied root */ - status = acpi_walk_namespace (ACPI_TYPE_ANY, start_node, - ACPI_UINT32_MAX, acpi_ds_init_one_object, - &info, NULL); + status = acpi_walk_namespace (ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX, + acpi_ds_init_one_object, &info, NULL); return (AE_OK); } @@ -212,6 +212,9 @@ ACPI_OPCODE_INFO *op_info; + PROC_NAME ("Ds_init_object_from_op"); + + op_info = acpi_ps_get_opcode_info (opcode); if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) { /* Unknown opcode */ @@ -222,8 +225,7 @@ /* Get and prepare the first argument */ - switch ((*obj_desc)->common.type) - { + switch ((*obj_desc)->common.type) { case ACPI_TYPE_BUFFER: /* First arg is a number */ @@ -234,23 +236,23 @@ /* Resolve the object (could be an arg or local) */ - status = acpi_aml_resolve_to_value (&arg_desc, walk_state); + status = acpi_ex_resolve_to_value (&arg_desc, walk_state); if (ACPI_FAILURE (status)) { - acpi_cm_remove_reference (arg_desc); + acpi_ut_remove_reference (arg_desc); return (status); } /* We are expecting a number */ if (arg_desc->common.type != ACPI_TYPE_INTEGER) { - acpi_cm_remove_reference (arg_desc); + acpi_ut_remove_reference (arg_desc); return (AE_TYPE); } /* Get the value, delete the internal object */ (*obj_desc)->buffer.length = (u32) arg_desc->integer.value; - acpi_cm_remove_reference (arg_desc); + acpi_ut_remove_reference (arg_desc); /* Allocate the buffer */ @@ -262,7 +264,7 @@ else { (*obj_desc)->buffer.pointer = - acpi_cm_callocate ((*obj_desc)->buffer.length); + acpi_ut_callocate ((*obj_desc)->buffer.length); if (!(*obj_desc)->buffer.pointer) { return (AE_NO_MEMORY); @@ -279,7 +281,7 @@ arg = op->value.arg; byte_list = (ACPI_PARSE2_OBJECT *) arg->next; if (byte_list) { - if (byte_list->opcode != AML_BYTELIST_OP) { + if (byte_list->opcode != AML_INT_BYTELIST_OP) { return (AE_TYPE); } @@ -300,7 +302,7 @@ * so that it is deleted. Error checking is done * within the remove reference function. */ - acpi_cm_remove_reference(*obj_desc); + acpi_ut_remove_reference(*obj_desc); status = acpi_ds_build_internal_object (walk_state, op, obj_desc); break; @@ -322,13 +324,12 @@ case INTERNAL_TYPE_REFERENCE: - switch (ACPI_GET_OP_CLASS (op_info)) - { + switch (ACPI_GET_OP_CLASS (op_info)) { case OPTYPE_LOCAL_VARIABLE: /* Split the opcode into a base opcode + offset */ - (*obj_desc)->reference.op_code = AML_LOCAL_OP; + (*obj_desc)->reference.opcode = AML_LOCAL_OP; (*obj_desc)->reference.offset = opcode - AML_LOCAL_OP; break; @@ -336,19 +337,19 @@ /* Split the opcode into a base opcode + offset */ - (*obj_desc)->reference.op_code = AML_ARG_OP; + (*obj_desc)->reference.opcode = AML_ARG_OP; (*obj_desc)->reference.offset = opcode - AML_ARG_OP; break; default: /* Constants, Literals, etc.. */ - if (op->opcode == AML_NAMEPATH_OP) { + if (op->opcode == AML_INT_NAMEPATH_OP) { /* Node was saved in Op */ (*obj_desc)->reference.node = op->node; } - (*obj_desc)->reference.op_code = opcode; + (*obj_desc)->reference.opcode = opcode; break; } @@ -385,13 +386,13 @@ ACPI_OPERAND_OBJECT **obj_desc_ptr) { ACPI_OPERAND_OBJECT *obj_desc; - OBJECT_TYPE_INTERNAL type; + ACPI_OBJECT_TYPE8 type; ACPI_STATUS status; u32 length; char *name; - if (op->opcode == AML_NAMEPATH_OP) { + if (op->opcode == AML_INT_NAMEPATH_OP) { /* * This is an object reference. If The name was * previously looked up in the NS, it is stored in this op. @@ -414,7 +415,7 @@ if (name) { REPORT_WARNING (("Reference %s at AML %X not found\n", name, op->aml_offset)); - acpi_cm_free (name); + acpi_ut_free (name); } else { REPORT_WARNING (("Reference %s at AML %X not found\n", @@ -444,16 +445,14 @@ /* Create and init the internal ACPI object */ - obj_desc = acpi_cm_create_internal_object (type); + obj_desc = acpi_ut_create_internal_object (type); if (!obj_desc) { return (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->opcode, &obj_desc); if (ACPI_FAILURE (status)) { - acpi_cm_remove_reference (obj_desc); + acpi_ut_remove_reference (obj_desc); return (status); } @@ -488,7 +487,7 @@ ACPI_STATUS status = AE_OK; - obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_PACKAGE); + obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_PACKAGE); if (!obj_desc) { return (AE_NO_MEMORY); } @@ -505,15 +504,10 @@ */ obj_desc->package.elements = - acpi_cm_callocate ((obj_desc->package.count + 1) * - sizeof (void *)); + acpi_ut_callocate ((obj_desc->package.count + 1) * sizeof (void *)); if (!obj_desc->package.elements) { - /* Package vector allocation failure */ - - REPORT_ERROR (("Ds_build_internal_package_obj: Package vector allocation failure\n")); - - acpi_cm_delete_object_desc (obj_desc); + acpi_ut_delete_object_desc (obj_desc); return (AE_NO_MEMORY); } @@ -568,13 +562,11 @@ if (op->opcode == AML_PACKAGE_OP) { - status = acpi_ds_build_internal_package_obj (walk_state, op, - obj_desc_ptr); + status = acpi_ds_build_internal_package_obj (walk_state, op, obj_desc_ptr); } else { - status = acpi_ds_build_internal_simple_obj (walk_state, op, - obj_desc_ptr); + status = acpi_ds_build_internal_simple_obj (walk_state, op, obj_desc_ptr); } return (status); @@ -613,8 +605,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->value.arg, &obj_desc); if (ACPI_FAILURE (status)) { return (status); } @@ -626,8 +617,7 @@ /* Init obj */ - status = acpi_ns_attach_object ((ACPI_HANDLE) node, obj_desc, - (u8) node->type); + status = acpi_ns_attach_object (node, obj_desc, (u8) node->type); if (ACPI_FAILURE (status)) { goto cleanup; } @@ -637,7 +627,7 @@ cleanup: - acpi_cm_remove_reference (obj_desc); + acpi_ut_remove_reference (obj_desc); return (status); } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/dispatcher/dsopcode.c linux/drivers/acpi/dispatcher/dsopcode.c --- v2.4.5/linux/drivers/acpi/dispatcher/dsopcode.c Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/dispatcher/dsopcode.c Wed Jun 20 17:47:39 2001 @@ -2,7 +2,7 @@ * * Module Name: dsopcode - Dispatcher Op Region support and handling of * "control" opcodes - * $Revision: 32 $ + * $Revision: 44 $ * *****************************************************************************/ @@ -34,25 +34,25 @@ #include "acevents.h" #include "actables.h" -#define _COMPONENT DISPATCHER +#define _COMPONENT ACPI_DISPATCHER MODULE_NAME ("dsopcode") /***************************************************************************** * - * FUNCTION: Acpi_ds_get_field_unit_arguments + * FUNCTION: Acpi_ds_get_buffer_field_arguments * - * PARAMETERS: Obj_desc - A valid Field_unit object + * PARAMETERS: Obj_desc - A valid Buffer_field object * * RETURN: Status. * - * DESCRIPTION: Get Field_unit Buffer and Index. This implements the late + * DESCRIPTION: Get Buffer_field Buffer and Index. This implements the late * evaluation of these field attributes. * ****************************************************************************/ ACPI_STATUS -acpi_ds_get_field_unit_arguments ( +acpi_ds_get_buffer_field_arguments ( ACPI_OPERAND_OBJECT *obj_desc) { ACPI_OPERAND_OBJECT *extra_desc; @@ -68,10 +68,10 @@ } - /* Get the AML pointer (method object) and Field_unit node */ + /* Get the AML pointer (method object) and Buffer_field node */ - extra_desc = obj_desc->field_unit.extra; - node = obj_desc->field_unit.node; + extra_desc = obj_desc->buffer_field.extra; + node = obj_desc->buffer_field.node; /* * Allocate a new parser op to be the root of the parsed @@ -94,7 +94,7 @@ return (status); } - /* Pass1: Parse the entire Field_unit declaration */ + /* Pass1: Parse the entire Buffer_field declaration */ status = acpi_ps_parse_aml (op, extra_desc->extra.pcode, extra_desc->extra.pcode_length, 0, @@ -138,8 +138,8 @@ * The pseudo-method object is no longer needed since the region is * now initialized */ - acpi_cm_remove_reference (obj_desc->field_unit.extra); - obj_desc->field_unit.extra = NULL; + acpi_ut_remove_reference (obj_desc->buffer_field.extra); + obj_desc->buffer_field.extra = NULL; return (status); } @@ -278,29 +278,45 @@ /***************************************************************************** * - * FUNCTION: Acpi_ds_eval_field_unit_operands + * FUNCTION: Acpi_ds_eval_buffer_field_operands * - * PARAMETERS: Op - A valid Field_unit Op object + * PARAMETERS: Op - A valid Buffer_field Op object * * RETURN: Status * - * DESCRIPTION: Get Field_unit Buffer and Index - * Called from Acpi_ds_exec_end_op during Field_unit parse tree walk + * DESCRIPTION: Get Buffer_field Buffer and Index + * Called from Acpi_ds_exec_end_op during Buffer_field parse tree walk + * + * ACPI SPECIFICATION REFERENCES: + * Each of the Buffer Field opcodes is defined as specified in in-line + * comments below. For each one, use the following definitions. + * + * Def_bit_field := Bit_field_op Src_buf Bit_idx Destination + * Def_byte_field := Byte_field_op Src_buf Byte_idx Destination + * Def_create_field := Create_field_op Src_buf Bit_idx Num_bits Name_string + * Def_dWord_field := DWord_field_op Src_buf Byte_idx Destination + * Def_word_field := Word_field_op Src_buf Byte_idx Destination + * Bit_index := Term_arg=>Integer + * Byte_index := Term_arg=>Integer + * Destination := Name_string + * Num_bits := Term_arg=>Integer + * Source_buf := Term_arg=>Buffer * ****************************************************************************/ ACPI_STATUS -acpi_ds_eval_field_unit_operands ( +acpi_ds_eval_buffer_field_operands ( ACPI_WALK_STATE *walk_state, ACPI_PARSE_OBJECT *op) { ACPI_STATUS status; - ACPI_OPERAND_OBJECT *field_desc; + ACPI_OPERAND_OBJECT *obj_desc; ACPI_NAMESPACE_NODE *node; ACPI_PARSE_OBJECT *next_op; u32 offset; u32 bit_offset; - u16 bit_count; + u32 bit_count; + u8 field_flags; ACPI_OPERAND_OBJECT *res_desc = NULL; @@ -311,12 +327,14 @@ /* - * This is where we evaluate the address and length fields of the Op_field_unit declaration + * 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 */ + next_op = op->value.arg; /* Acpi_evaluate/create the address and length operands */ @@ -326,15 +344,15 @@ return (status); } - field_desc = acpi_ns_get_attached_object (node); - if (!field_desc) { + obj_desc = acpi_ns_get_attached_object (node); + if (!obj_desc) { return (AE_NOT_EXIST); } /* Resolve the operands */ - status = acpi_aml_resolve_operands (op->opcode, WALK_OPERANDS, walk_state); + status = acpi_ex_resolve_operands (op->opcode, WALK_OPERANDS, walk_state); /* Get the operands */ @@ -359,7 +377,7 @@ /* * If Res_desc is a Name, it will be a direct name pointer after - * Acpi_aml_resolve_operands() + * Acpi_ex_resolve_operands() */ if (!VALID_DESCRIPTOR_TYPE (res_desc, ACPI_DESC_TYPE_NAMED)) { @@ -372,61 +390,77 @@ * Setup the Bit offsets and counts, according to the opcode */ - switch (op->opcode) - { + switch (op->opcode) { + + /* Def_create_field */ + + case AML_CREATE_FIELD_OP: + + /* Offset is in bits, count is in bits */ + + bit_offset = offset; + bit_count = (u32) cnt_desc->integer.value; + field_flags = ACCESS_BYTE_ACC; + break; + /* Def_create_bit_field */ - case AML_BIT_FIELD_OP: + case AML_CREATE_BIT_FIELD_OP: - /* Offset is in bits, Field is a bit */ + /* Offset is in bits, Field is one bit */ - bit_offset = offset; - bit_count = 1; + bit_offset = offset; + bit_count = 1; + field_flags = ACCESS_BYTE_ACC; break; /* Def_create_byte_field */ - case AML_BYTE_FIELD_OP: + case AML_CREATE_BYTE_FIELD_OP: - /* Offset is in bytes, field is a byte */ + /* Offset is in bytes, field is one byte */ - bit_offset = 8 * offset; - bit_count = 8; + bit_offset = 8 * offset; + bit_count = 8; + field_flags = ACCESS_BYTE_ACC; break; /* Def_create_word_field */ - case AML_WORD_FIELD_OP: + case AML_CREATE_WORD_FIELD_OP: - /* Offset is in bytes, field is a word */ + /* Offset is in bytes, field is one word */ - bit_offset = 8 * offset; - bit_count = 16; + bit_offset = 8 * offset; + bit_count = 16; + field_flags = ACCESS_WORD_ACC; break; /* Def_create_dWord_field */ - case AML_DWORD_FIELD_OP: + case AML_CREATE_DWORD_FIELD_OP: - /* Offset is in bytes, field is a dword */ + /* Offset is in bytes, field is one dword */ - bit_offset = 8 * offset; - bit_count = 32; + bit_offset = 8 * offset; + bit_count = 32; + field_flags = ACCESS_DWORD_ACC; break; - /* Def_create_field */ + /* Def_create_qWord_field */ - case AML_CREATE_FIELD_OP: + case AML_CREATE_QWORD_FIELD_OP: - /* Offset is in bits, count is in bits */ + /* Offset is in bytes, field is one qword */ - bit_offset = offset; - bit_count = (u16) cnt_desc->integer.value; + bit_offset = 8 * offset; + bit_count = 64; + field_flags = ACCESS_QWORD_ACC; break; @@ -441,35 +475,35 @@ * Setup field according to the object type */ - switch (src_desc->common.type) - { + switch (src_desc->common.type) { /* Source_buff := Term_arg=>Buffer */ case ACPI_TYPE_BUFFER: - if (bit_offset + (u32) bit_count > - (8 * (u32) src_desc->buffer.length)) - { + if ((bit_offset + bit_count) > + (8 * (u32) src_desc->buffer.length)) { status = AE_AML_BUFFER_LIMIT; goto cleanup; } - /* Construct the remainder of the field object */ + /* + * 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, + bit_offset, bit_count); + if (ACPI_FAILURE (status)) { + return (status); + } - field_desc->field_unit.access = (u8) ACCESS_ANY_ACC; - field_desc->field_unit.lock_rule = (u8) GLOCK_NEVER_LOCK; - field_desc->field_unit.update_rule = (u8) UPDATE_PRESERVE; - field_desc->field_unit.length = bit_count; - field_desc->field_unit.bit_offset = (u8) (bit_offset % 8); - field_desc->field_unit.offset = DIV_8 (bit_offset); - field_desc->field_unit.container = src_desc; + obj_desc->buffer_field.buffer_obj = src_desc; - /* Reference count for Src_desc inherits Field_desc count */ + /* Reference count for Src_desc inherits Obj_desc count */ src_desc->common.reference_count = (u16) (src_desc->common.reference_count + - field_desc->common.reference_count); + obj_desc->common.reference_count); break; @@ -478,8 +512,6 @@ default: - if ((src_desc->common.type > (u8) INTERNAL_TYPE_REFERENCE) || - !acpi_cm_valid_object_type (src_desc->common.type)) status = AE_AML_OPERAND_TYPE; @@ -490,7 +522,7 @@ if (AML_CREATE_FIELD_OP == op->opcode) { /* Delete object descriptor unique to Create_field */ - acpi_cm_remove_reference (cnt_desc); + acpi_ut_remove_reference (cnt_desc); cnt_desc = NULL; } @@ -499,23 +531,23 @@ /* Always delete the operands */ - acpi_cm_remove_reference (off_desc); - acpi_cm_remove_reference (src_desc); + acpi_ut_remove_reference (off_desc); + acpi_ut_remove_reference (src_desc); if (AML_CREATE_FIELD_OP == op->opcode) { - acpi_cm_remove_reference (cnt_desc); + acpi_ut_remove_reference (cnt_desc); } /* On failure, delete the result descriptor */ if (ACPI_FAILURE (status)) { - acpi_cm_remove_reference (res_desc); /* Result descriptor */ + acpi_ut_remove_reference (res_desc); /* Result descriptor */ } else { - /* Now the address and length are valid for this op_field_unit */ + /* Now the address and length are valid for this Buffer_field */ - field_desc->field_unit.flags |= AOPOBJ_DATA_VALID; + obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID; } return (status); @@ -568,7 +600,7 @@ /* Resolve the length and address operands to numbers */ - status = acpi_aml_resolve_operands (op->opcode, WALK_OPERANDS, walk_state); + status = acpi_ex_resolve_operands (op->opcode, WALK_OPERANDS, walk_state); if (ACPI_FAILURE (status)) { return (status); } @@ -586,7 +618,7 @@ operand_desc = walk_state->operands[walk_state->num_operands - 1]; obj_desc->region.length = (u32) operand_desc->integer.value; - acpi_cm_remove_reference (operand_desc); + acpi_ut_remove_reference (operand_desc); /* * Get the address and save it @@ -595,7 +627,7 @@ operand_desc = walk_state->operands[walk_state->num_operands - 2]; obj_desc->region.address = (ACPI_PHYSICAL_ADDRESS) operand_desc->integer.value; - acpi_cm_remove_reference (operand_desc); + acpi_ut_remove_reference (operand_desc); /* Now the address and length are valid for this opregion */ @@ -629,8 +661,10 @@ ACPI_GENERIC_STATE *control_state; - switch (op->opcode) - { + PROC_NAME ("Ds_exec_begin_control_op"); + + + switch (op->opcode) { case AML_IF_OP: case AML_WHILE_OP: @@ -640,13 +674,13 @@ * to handle nesting. */ - control_state = acpi_cm_create_control_state (); + control_state = acpi_ut_create_control_state (); if (!control_state) { status = AE_NO_MEMORY; break; } - acpi_cm_push_generic_state (&walk_state->control_state, control_state); + acpi_ut_push_generic_state (&walk_state->control_state, control_state); /* * Save a pointer to the predicate for multiple executions @@ -708,8 +742,10 @@ ACPI_GENERIC_STATE *control_state; - switch (op->opcode) - { + PROC_NAME ("Ds_exec_end_control_op"); + + + switch (op->opcode) { case AML_IF_OP: /* @@ -718,18 +754,15 @@ */ walk_state->last_predicate = - (u8) walk_state->control_state->common.value; + (u8) walk_state->control_state->common.value; /* * Pop the control state that was created at the start * of the IF and free it */ - control_state = - acpi_cm_pop_generic_state (&walk_state->control_state); - - acpi_cm_delete_generic_state (control_state); - + control_state = acpi_ut_pop_generic_state (&walk_state->control_state); + acpi_ut_delete_generic_state (control_state); break; @@ -746,15 +779,12 @@ status = AE_CTRL_PENDING; } - /* Pop this control state and free it */ - control_state = - acpi_cm_pop_generic_state (&walk_state->control_state); + control_state = acpi_ut_pop_generic_state (&walk_state->control_state); walk_state->aml_last_while = control_state->control.aml_predicate_start; - acpi_cm_delete_generic_state (control_state); - + acpi_ut_delete_generic_state (control_state); break; @@ -779,8 +809,7 @@ * an arg or local), resolve it now because it may * cease to exist at the end of the method. */ - - status = acpi_aml_resolve_to_value (&walk_state->operands [0], walk_state); + status = acpi_ex_resolve_to_value (&walk_state->operands [0], walk_state); if (ACPI_FAILURE (status)) { return (status); } @@ -795,19 +824,24 @@ } else if ((walk_state->results) && - (walk_state->results->results.num_results > 0)) - { + (walk_state->results->results.num_results > 0)) { /* * The return value has come from a previous calculation. * * If value being returned is a Reference (such as * an arg or local), resolve it now because it may * cease to exist at the end of the method. + * + * Allow references created by the Index operator to return unchanged. */ - status = acpi_aml_resolve_to_value (&walk_state->results->results.obj_desc [0], walk_state); - if (ACPI_FAILURE (status)) { - return (status); + if (VALID_DESCRIPTOR_TYPE (walk_state->results->results.obj_desc [0], ACPI_DESC_TYPE_INTERNAL) && + ((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); + if (ACPI_FAILURE (status)) { + return (status); + } } walk_state->return_desc = walk_state->results->results.obj_desc [0]; @@ -817,7 +851,7 @@ /* No return operand */ if (walk_state->num_operands) { - acpi_cm_remove_reference (walk_state->operands [0]); + acpi_ut_remove_reference (walk_state->operands [0]); } walk_state->operands [0] = NULL; diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/dispatcher/dsutils.c linux/drivers/acpi/dispatcher/dsutils.c --- v2.4.5/linux/drivers/acpi/dispatcher/dsutils.c Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/dispatcher/dsutils.c Wed Jun 20 17:47:39 2001 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: dsutils - Dispatcher utilities - * $Revision: 52 $ + * $Revision: 58 $ * ******************************************************************************/ @@ -32,7 +32,7 @@ #include "acnamesp.h" #include "acdebug.h" -#define _COMPONENT PARSER +#define _COMPONENT ACPI_DISPATCHER MODULE_NAME ("dsutils") @@ -93,15 +93,13 @@ * as an operand later. */ - switch (ACPI_GET_OP_CLASS (parent_info)) - { + switch (ACPI_GET_OP_CLASS (parent_info)) { /* * In these cases, the parent will never use the return object */ case OPTYPE_CONTROL: /* IF, ELSE, WHILE only */ - switch (op->parent->opcode) - { + switch (op->parent->opcode) { case AML_RETURN_OP: /* Never delete the return value associated with a return opcode */ @@ -118,8 +116,7 @@ */ if ((walk_state->control_state->common.state == CONTROL_PREDICATE_EXECUTING) && - (walk_state->control_state->control.predicate_op == op)) - { + (walk_state->control_state->control.predicate_op == op)) { return (TRUE); } @@ -136,14 +133,13 @@ * These opcodes allow Term_arg(s) as operands and therefore * method calls. The result is used. */ - if ((op->parent->opcode == AML_REGION_OP) || - (op->parent->opcode == AML_CREATE_FIELD_OP) || - (op->parent->opcode == AML_BIT_FIELD_OP) || - (op->parent->opcode == AML_BYTE_FIELD_OP) || - (op->parent->opcode == AML_WORD_FIELD_OP) || - (op->parent->opcode == AML_DWORD_FIELD_OP) || - (op->parent->opcode == AML_QWORD_FIELD_OP)) - { + if ((op->parent->opcode == AML_REGION_OP) || + (op->parent->opcode == AML_CREATE_FIELD_OP) || + (op->parent->opcode == AML_CREATE_BIT_FIELD_OP) || + (op->parent->opcode == AML_CREATE_BYTE_FIELD_OP) || + (op->parent->opcode == AML_CREATE_WORD_FIELD_OP) || + (op->parent->opcode == AML_CREATE_DWORD_FIELD_OP) || + (op->parent->opcode == AML_CREATE_QWORD_FIELD_OP)) { return (TRUE); } @@ -206,7 +202,7 @@ status = acpi_ds_result_pop (&obj_desc, walk_state); if (ACPI_SUCCESS (status)) { - acpi_cm_remove_reference (result_obj); + acpi_ut_remove_reference (result_obj); } } @@ -239,7 +235,7 @@ ACPI_STATUS status = AE_OK; NATIVE_CHAR *name_string; u32 name_length; - OBJECT_TYPE_INTERNAL data_type; + ACPI_OBJECT_TYPE8 data_type; ACPI_OPERAND_OBJECT *obj_desc; ACPI_PARSE_OBJECT *parent_op; u16 opcode; @@ -249,15 +245,12 @@ /* A valid name must be looked up in the namespace */ - if ((arg->opcode == AML_NAMEPATH_OP) && - (arg->value.string)) - { + if ((arg->opcode == AML_INT_NAMEPATH_OP) && + (arg->value.string)) { /* Get the entire name string from the AML stream */ - status = acpi_aml_get_name_string (ACPI_TYPE_ANY, - arg->value.buffer, - &name_string, - &name_length); + status = acpi_ex_get_name_string (ACPI_TYPE_ANY, arg->value.buffer, + &name_string, &name_length); if (ACPI_FAILURE (status)) { return (status); @@ -277,10 +270,9 @@ parent_op = arg->parent; if ((acpi_ps_is_node_op (parent_op->opcode)) && - (parent_op->opcode != AML_METHODCALL_OP) && + (parent_op->opcode != AML_INT_METHODCALL_OP) && (parent_op->opcode != AML_REGION_OP) && - (parent_op->opcode != AML_NAMEPATH_OP)) - { + (parent_op->opcode != AML_INT_NAMEPATH_OP)) { /* Enter name into namespace if not found */ interpreter_mode = IMODE_LOAD_PASS2; @@ -300,7 +292,7 @@ /* Free the namestring created above */ - acpi_cm_free (name_string); + acpi_ut_free (name_string); /* * The only case where we pass through (ignore) a NOT_FOUND @@ -347,7 +339,7 @@ else { /* Check for null name case */ - if (arg->opcode == AML_NAMEPATH_OP) { + if (arg->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 +373,6 @@ * Use value that was already previously returned * by the evaluation of this argument */ - status = acpi_ds_result_pop_from_bottom (&obj_desc, walk_state); if (ACPI_FAILURE (status)) { /* @@ -396,7 +387,7 @@ else { /* Create an ACPI_INTERNAL_OBJECT for the argument */ - obj_desc = acpi_cm_create_internal_object (data_type); + obj_desc = acpi_ut_create_internal_object (data_type); if (!obj_desc) { return (AE_NO_MEMORY); } @@ -406,7 +397,7 @@ status = acpi_ds_init_object_from_op (walk_state, arg, opcode, &obj_desc); if (ACPI_FAILURE (status)) { - acpi_cm_delete_object_desc (obj_desc); + acpi_ut_delete_object_desc (obj_desc); return (status); } } @@ -509,11 +500,11 @@ /* * TBD: [Investigate] Note from previous parser: - * Ref_of problem with Acpi_aml_resolve_to_value() conversion. + * Ref_of problem with Acpi_ex_resolve_to_value() conversion. */ for (i = 0; i < walk_state->num_operands; i++) { - status = acpi_aml_resolve_to_value (&walk_state->operands[i], walk_state); + status = acpi_ex_resolve_to_value (&walk_state->operands[i], walk_state); if (ACPI_FAILURE (status)) { break; } @@ -538,16 +529,19 @@ * ******************************************************************************/ -OBJECT_TYPE_INTERNAL +ACPI_OBJECT_TYPE8 acpi_ds_map_opcode_to_data_type ( u16 opcode, u32 *out_flags) { - OBJECT_TYPE_INTERNAL data_type = INTERNAL_TYPE_INVALID; + ACPI_OBJECT_TYPE8 data_type = INTERNAL_TYPE_INVALID; ACPI_OPCODE_INFO *op_info; u32 flags = 0; + PROC_NAME ("Ds_map_opcode_to_data_type"); + + op_info = acpi_ps_get_opcode_info (opcode); if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) { /* Unknown opcode */ @@ -555,13 +549,11 @@ return (data_type); } - switch (ACPI_GET_OP_CLASS (op_info)) - { + switch (ACPI_GET_OP_CLASS (op_info)) { case OPTYPE_LITERAL: - switch (opcode) - { + switch (opcode) { case AML_BYTE_OP: case AML_WORD_OP: case AML_DWORD_OP: @@ -575,7 +567,7 @@ data_type = ACPI_TYPE_STRING; break; - case AML_NAMEPATH_OP: + case AML_INT_NAMEPATH_OP: data_type = INTERNAL_TYPE_REFERENCE; break; @@ -587,8 +579,7 @@ case OPTYPE_DATA_TERM: - switch (opcode) - { + switch (opcode) { case AML_BUFFER_OP: data_type = ACPI_TYPE_BUFFER; @@ -675,17 +666,16 @@ * ******************************************************************************/ -OBJECT_TYPE_INTERNAL +ACPI_OBJECT_TYPE8 acpi_ds_map_named_opcode_to_data_type ( u16 opcode) { - OBJECT_TYPE_INTERNAL data_type; + ACPI_OBJECT_TYPE8 data_type; /* Decode Opcode */ - switch (opcode) - { + switch (opcode) { case AML_SCOPE_OP: data_type = INTERNAL_TYPE_SCOPE; break; @@ -710,8 +700,8 @@ data_type = ACPI_TYPE_PROCESSOR; break; - case AML_DEF_FIELD_OP: /* Def_field_op */ - data_type = INTERNAL_TYPE_DEF_FIELD_DEFN; + case AML_FIELD_OP: /* Field_op */ + data_type = INTERNAL_TYPE_FIELD_DEFN; break; case AML_INDEX_FIELD_OP: /* Index_field_op */ @@ -722,12 +712,12 @@ data_type = INTERNAL_TYPE_BANK_FIELD_DEFN; break; - case AML_NAMEDFIELD_OP: /* NO CASE IN ORIGINAL */ + case AML_INT_NAMEDFIELD_OP: /* NO CASE IN ORIGINAL */ data_type = ACPI_TYPE_ANY; break; case AML_NAME_OP: /* Name_op - special code in original */ - case AML_NAMEPATH_OP: + case AML_INT_NAMEPATH_OP: data_type = ACPI_TYPE_ANY; break; diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/dispatcher/dswexec.c linux/drivers/acpi/dispatcher/dswexec.c --- v2.4.5/linux/drivers/acpi/dispatcher/dswexec.c Mon Jan 29 10:15:58 2001 +++ linux/drivers/acpi/dispatcher/dswexec.c Wed Jun 20 17:47:39 2001 @@ -2,7 +2,7 @@ * * Module Name: dswexec - Dispatcher method execution callbacks; * dispatch to interpreter. - * $Revision: 55 $ + * $Revision: 61 $ * *****************************************************************************/ @@ -34,7 +34,7 @@ #include "acdebug.h" -#define _COMPONENT DISPATCHER +#define _COMPONENT ACPI_DISPATCHER MODULE_NAME ("dswexec") @@ -75,7 +75,7 @@ return (status); } - status = acpi_aml_resolve_to_value (&walk_state->operands [0], walk_state); + status = acpi_ex_resolve_to_value (&walk_state->operands [0], walk_state); if (ACPI_FAILURE (status)) { return (status); } @@ -101,7 +101,7 @@ /* Truncate the predicate to 32-bits if necessary */ - acpi_aml_truncate_for32bit_table (obj_desc, walk_state); + acpi_ex_truncate_for32bit_table (obj_desc, walk_state); /* * Save the result of the predicate evaluation on @@ -134,7 +134,7 @@ * we don't need it anymore) */ - acpi_cm_remove_reference (obj_desc); + acpi_ut_remove_reference (obj_desc); walk_state->control_state->common.state = CONTROL_NORMAL; @@ -194,8 +194,7 @@ if ((walk_state->control_state) && (walk_state->control_state->common.state == - CONTROL_CONDITIONAL_EXECUTING)) - { + CONTROL_CONDITIONAL_EXECUTING)) { walk_state->control_state->common.state = CONTROL_PREDICATE_EXECUTING; /* Save start of predicate */ @@ -208,7 +207,7 @@ /* We want to send namepaths to the load code */ - if (op->opcode == AML_NAMEPATH_OP) { + if (op->opcode == AML_INT_NAMEPATH_OP) { op_info->flags = OPTYPE_NAMED_OBJECT; } @@ -217,8 +216,7 @@ * Handle the opcode based upon the opcode type */ - switch (ACPI_GET_OP_CLASS (op_info)) - { + switch (ACPI_GET_OP_CLASS (op_info)) { case OPTYPE_CONTROL: status = acpi_ds_result_stack_push (walk_state); @@ -308,11 +306,9 @@ u16 opcode; u8 optype; ACPI_PARSE_OBJECT *next_op; - ACPI_NAMESPACE_NODE *node; ACPI_PARSE_OBJECT *first_arg; ACPI_OPERAND_OBJECT *result_obj = NULL; ACPI_OPCODE_INFO *op_info; - u32 operand_index; opcode = (u16) op->opcode; @@ -342,8 +338,7 @@ /* Decode the opcode */ - switch (optype) - { + switch (optype) { case OPTYPE_UNDEFINED: return (AE_NOT_IMPLEMENTED); @@ -383,9 +378,6 @@ goto cleanup; } - operand_index = walk_state->num_operands - 1; - - /* Done with this result state (Now that operand stack is built) */ status = acpi_ds_result_stack_pop (walk_state); @@ -393,13 +385,12 @@ goto cleanup; } - switch (optype) - { + switch (optype) { case OPTYPE_MONADIC1: /* 1 Operand, 0 External_result, 0 Internal_result */ - status = acpi_aml_exec_monadic1 (opcode, walk_state); + status = acpi_ex_monadic1 (opcode, walk_state); break; @@ -407,7 +398,7 @@ /* 1 Operand, 0 External_result, 1 Internal_result */ - status = acpi_aml_exec_monadic2 (opcode, walk_state, &result_obj); + status = acpi_ex_monadic2 (opcode, walk_state, &result_obj); break; @@ -415,7 +406,7 @@ /* 1 Operand, 1 External_result, 1 Internal_result */ - status = acpi_aml_exec_monadic2_r (opcode, walk_state, &result_obj); + status = acpi_ex_monadic2_r (opcode, walk_state, &result_obj); break; @@ -423,7 +414,7 @@ /* 2 Operands, 0 External_result, 0 Internal_result */ - status = acpi_aml_exec_dyadic1 (opcode, walk_state); + status = acpi_ex_dyadic1 (opcode, walk_state); break; @@ -431,7 +422,7 @@ /* 2 Operands, 0 External_result, 1 Internal_result */ - status = acpi_aml_exec_dyadic2 (opcode, walk_state, &result_obj); + status = acpi_ex_dyadic2 (opcode, walk_state, &result_obj); break; @@ -439,7 +430,7 @@ /* 2 Operands, 1 or 2 External_results, 1 Internal_result */ - status = acpi_aml_exec_dyadic2_r (opcode, walk_state, &result_obj); + status = acpi_ex_dyadic2_r (opcode, walk_state, &result_obj); break; @@ -447,7 +438,7 @@ /* 2 Operands, 0 External_result, 1 Internal_result */ - status = acpi_aml_exec_dyadic2_s (opcode, walk_state, &result_obj); + status = acpi_ex_dyadic2_s (opcode, walk_state, &result_obj); break; @@ -455,7 +446,7 @@ /* 3 Operands, 1 External_result, 1 Internal_result */ - status = acpi_aml_exec_index (walk_state, &result_obj); + status = acpi_ex_index (walk_state, &result_obj); break; @@ -463,7 +454,7 @@ /* 6 Operands, 0 External_result, 1 Internal_result */ - status = acpi_aml_exec_match (walk_state, &result_obj); + status = acpi_ex_match (walk_state, &result_obj); break; @@ -471,7 +462,7 @@ /* 1 or 2 operands, 0 Internal Result */ - status = acpi_aml_exec_reconfiguration (opcode, walk_state); + status = acpi_ex_reconfiguration (opcode, walk_state); break; @@ -479,7 +470,7 @@ /* 3 Operands, 0 External_result, 0 Internal_result */ - status = acpi_aml_exec_fatal (walk_state); + status = acpi_ex_fatal (walk_state); break; } @@ -488,8 +479,7 @@ * current result stack */ if (ACPI_SUCCESS (status) && - result_obj) - { + result_obj) { status = acpi_ds_result_push (result_obj, walk_state); } @@ -515,7 +505,6 @@ /* Next_op points to the op that holds the method name */ next_op = first_arg; - node = next_op->node; /* Next_op points to first argument op */ @@ -562,7 +551,7 @@ break; } - status = acpi_ds_eval_field_unit_operands (walk_state, op); + status = acpi_ds_eval_buffer_field_operands (walk_state, op); break; @@ -573,8 +562,7 @@ break; } - switch (op->opcode) - { + switch (op->opcode) { case AML_REGION_OP: status = acpi_ds_eval_region_operands (walk_state, op); @@ -617,7 +605,7 @@ * ACPI 2.0 support for 64-bit integers: * Truncate numeric result value if we are executing from a 32-bit ACPI table */ - acpi_aml_truncate_for32bit_table (result_obj, walk_state); + acpi_ex_truncate_for32bit_table (result_obj, walk_state); /* * Check if we just completed the evaluation of a @@ -627,8 +615,7 @@ if ((walk_state->control_state) && (walk_state->control_state->common.state == CONTROL_PREDICATE_EXECUTING) && - (walk_state->control_state->control.predicate_op == op)) - { + (walk_state->control_state->control.predicate_op == op)) { status = acpi_ds_get_predicate_value (walk_state, op, (u32) result_obj); result_obj = NULL; } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/dispatcher/dswload.c linux/drivers/acpi/dispatcher/dswload.c --- v2.4.5/linux/drivers/acpi/dispatcher/dswload.c Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/dispatcher/dswload.c Wed Jun 20 17:47:39 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: dswload - Dispatcher namespace load callbacks - * $Revision: 26 $ + * $Revision: 37 $ * *****************************************************************************/ @@ -33,11 +33,11 @@ #include "acevents.h" -#define _COMPONENT DISPATCHER +#define _COMPONENT ACPI_DISPATCHER MODULE_NAME ("dswload") -/***************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ds_load1_begin_op * @@ -49,7 +49,7 @@ * * DESCRIPTION: Descending callback used during the loading of ACPI tables. * - ****************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_ds_load1_begin_op ( @@ -60,10 +60,12 @@ { ACPI_NAMESPACE_NODE *node; ACPI_STATUS status; - OBJECT_TYPE_INTERNAL data_type; + ACPI_OBJECT_TYPE8 data_type; NATIVE_CHAR *path; + PROC_NAME ("Ds_load1_begin_op"); + /* We are only interested in opcodes that have an associated name */ if (!acpi_ps_is_named_op (opcode)) { @@ -92,9 +94,8 @@ * as we go downward in the parse tree. Any necessary subobjects that involve * arguments to the opcode must be created as we go back up the parse tree later. */ - status = acpi_ns_lookup (walk_state->scope_info, path, - data_type, IMODE_LOAD_PASS1, - NS_NO_UPSEARCH, walk_state, &(node)); + status = acpi_ns_lookup (walk_state->scope_info, path, data_type, + IMODE_LOAD_PASS1, NS_NO_UPSEARCH, walk_state, &(node)); if (ACPI_FAILURE (status)) { return (status); @@ -128,7 +129,7 @@ } -/***************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ds_load1_end_op * @@ -141,16 +142,17 @@ * DESCRIPTION: Ascending callback used during the loading of the namespace, * both control methods and everything else. * - ****************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_ds_load1_end_op ( ACPI_WALK_STATE *walk_state, ACPI_PARSE_OBJECT *op) { - OBJECT_TYPE_INTERNAL data_type; + ACPI_OBJECT_TYPE8 data_type; + PROC_NAME ("Ds_load1_end_op"); /* We are only interested in opcodes that have an associated name */ if (!acpi_ps_is_named_op (op->opcode)) { @@ -177,7 +179,6 @@ /* Pop the scope stack */ if (acpi_ns_opens_scope (data_type)) { - acpi_ds_scope_stack_pop (walk_state); } @@ -186,7 +187,7 @@ } -/***************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ds_load2_begin_op * @@ -198,7 +199,7 @@ * * DESCRIPTION: Descending callback used during the loading of ACPI tables. * - ****************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_ds_load2_begin_op ( @@ -209,16 +210,17 @@ { ACPI_NAMESPACE_NODE *node; ACPI_STATUS status; - OBJECT_TYPE_INTERNAL data_type; + ACPI_OBJECT_TYPE8 data_type; NATIVE_CHAR *buffer_ptr; void *original = NULL; + PROC_NAME ("Ds_load2_begin_op"); + /* We only care about Namespace opcodes here */ if (!acpi_ps_is_namespace_op (opcode) && - opcode != AML_NAMEPATH_OP) - { + opcode != AML_INT_NAMEPATH_OP) { return (AE_OK); } @@ -233,7 +235,7 @@ /* * Get the name we are going to enter or lookup in the namespace */ - if (opcode == AML_NAMEPATH_OP) { + if (opcode == AML_INT_NAMEPATH_OP) { /* For Namepath op, get the path string */ buffer_ptr = op->value.string; @@ -261,15 +263,14 @@ data_type = acpi_ds_map_named_opcode_to_data_type (opcode); - if (opcode == AML_DEF_FIELD_OP || + if (opcode == AML_FIELD_OP || opcode == AML_BANK_FIELD_OP || - opcode == AML_INDEX_FIELD_OP) - { + opcode == AML_INDEX_FIELD_OP) { node = NULL; status = AE_OK; } - else if (opcode == AML_NAMEPATH_OP) { + else if (opcode == AML_INT_NAMEPATH_OP) { /* * The Name_path is an object reference to an existing object. Don't enter the * name into the namespace, but look it up for use later @@ -302,10 +303,8 @@ * as we go downward in the parse tree. Any necessary subobjects that involve * arguments to the opcode must be created as we go back up the parse tree later. */ - status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, - data_type, IMODE_EXECUTE, - NS_NO_UPSEARCH, walk_state, - &(node)); + status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, data_type, + IMODE_EXECUTE, NS_NO_UPSEARCH, walk_state, &(node)); } if (ACPI_SUCCESS (status)) { @@ -332,12 +331,11 @@ } - return (status); } -/***************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ds_load2_end_op * @@ -350,7 +348,7 @@ * DESCRIPTION: Ascending callback used during the loading of the namespace, * both control methods and everything else. * - ****************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_ds_load2_end_op ( @@ -358,12 +356,13 @@ ACPI_PARSE_OBJECT *op) { ACPI_STATUS status = AE_OK; - OBJECT_TYPE_INTERNAL data_type; + ACPI_OBJECT_TYPE8 data_type; ACPI_NAMESPACE_NODE *node; ACPI_PARSE_OBJECT *arg; ACPI_NAMESPACE_NODE *new_node; + PROC_NAME ("Ds_load2_end_op"); if (!acpi_ps_is_namespace_object_op (op->opcode)) { return (AE_OK); } @@ -422,6 +421,7 @@ * AML_CREATEBYTEFIELD * AML_CREATEWORDFIELD * AML_CREATEDWORDFIELD + * AML_CREATEQWORDFIELD * AML_METHODCALL */ @@ -430,14 +430,14 @@ arg = op->value.arg; - switch (op->opcode) - { + switch (op->opcode) { case AML_CREATE_FIELD_OP: - case AML_BIT_FIELD_OP: - case AML_BYTE_FIELD_OP: - case AML_WORD_FIELD_OP: - case AML_DWORD_FIELD_OP: + case AML_CREATE_BIT_FIELD_OP: + case AML_CREATE_BYTE_FIELD_OP: + case AML_CREATE_WORD_FIELD_OP: + case AML_CREATE_DWORD_FIELD_OP: + case AML_CREATE_QWORD_FIELD_OP: /* * Create the field object, but the field buffer and index must @@ -455,58 +455,59 @@ arg = acpi_ps_get_arg (op, 2); } + if (!arg) { + status = AE_AML_NO_OPERAND; + goto cleanup; + } + /* * Enter the Name_string into the namespace */ - - status = acpi_ns_lookup (walk_state->scope_info, - arg->value.string, - INTERNAL_TYPE_DEF_ANY, - IMODE_LOAD_PASS1, + status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, + INTERNAL_TYPE_DEF_ANY, IMODE_LOAD_PASS1, NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, walk_state, &(new_node)); + if (ACPI_FAILURE (status)) { + goto cleanup; + } - if (ACPI_SUCCESS (status)) { - /* We could put the returned object (Node) on the object stack for later, but - * 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; + /* We could put the returned object (Node) on the object stack for later, but + * 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; + /* + * If there is no object attached to the node, this node was just created and + * we need to create the field object. Otherwise, this was a lookup of an + * existing node and we don't want to create the field object again. + */ + if (!new_node->object) { /* - * If there is no object attached to the node, this node was just created and - * we need to create the field object. Otherwise, this was a lookup of an - * existing node and we don't want to create the field object again. + * The Field definition is not fully parsed at this time. + * (We must save the address of the AML for the buffer and index operands) */ - if (!new_node->object) { - /* - * The Field definition is not fully parsed at this time. - * (We must save the address of the AML for the buffer and index operands) - */ - status = acpi_aml_exec_create_field (((ACPI_PARSE2_OBJECT *) op)->data, - ((ACPI_PARSE2_OBJECT *) op)->length, - new_node, walk_state); - } + status = acpi_ex_create_buffer_field (((ACPI_PARSE2_OBJECT *) op)->data, + ((ACPI_PARSE2_OBJECT *) op)->length, + new_node, walk_state); } - - break; - case AML_METHODCALL_OP: + case AML_INT_METHODCALL_OP: /* * Lookup the method name and save the Node */ status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, - ACPI_TYPE_ANY, IMODE_LOAD_PASS2, - NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE, - walk_state, &(new_node)); + ACPI_TYPE_ANY, IMODE_LOAD_PASS2, + NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE, + walk_state, &(new_node)); if (ACPI_SUCCESS (status)) { -/* has name already been resolved by here ??*/ + /* TBD: has name already been resolved by here ??*/ /* TBD: [Restructure] Make sure that what we found is indeed a method! */ /* We didn't search for a method on purpose, to see if the name would resolve! */ @@ -526,7 +527,7 @@ /* Nothing to do other than enter object into namespace */ - status = acpi_aml_exec_create_processor (op, (ACPI_HANDLE) node); + status = acpi_ex_create_processor (op, node); if (ACPI_FAILURE (status)) { goto cleanup; } @@ -538,7 +539,7 @@ /* Nothing to do other than enter object into namespace */ - status = acpi_aml_exec_create_power_resource (op, (ACPI_HANDLE) node); + status = acpi_ex_create_power_resource (op, node); if (ACPI_FAILURE (status)) { goto cleanup; } @@ -553,13 +554,11 @@ break; - case AML_DEF_FIELD_OP: + case AML_FIELD_OP: arg = op->value.arg; - status = acpi_ds_create_field (op, - arg->node, - walk_state); + status = acpi_ds_create_field (op, arg->node, walk_state); break; @@ -567,8 +566,7 @@ arg = op->value.arg; - status = acpi_ds_create_index_field (op, - (ACPI_HANDLE) arg->node, + status = acpi_ds_create_index_field (op, (ACPI_HANDLE) arg->node, walk_state); break; @@ -576,9 +574,7 @@ case AML_BANK_FIELD_OP: arg = op->value.arg; - status = acpi_ds_create_bank_field (op, - arg->node, - walk_state); + status = acpi_ds_create_bank_field (op, arg->node, walk_state); break; @@ -588,11 +584,10 @@ case AML_METHOD_OP: if (!node->object) { - status = acpi_aml_exec_create_method (((ACPI_PARSE2_OBJECT *) op)->data, + status = acpi_ex_create_method (((ACPI_PARSE2_OBJECT *) op)->data, ((ACPI_PARSE2_OBJECT *) op)->length, - arg->value.integer, (ACPI_HANDLE) node); + arg->value.integer, node); } - break; @@ -603,7 +598,7 @@ goto cleanup; } - status = acpi_aml_exec_create_mutex (walk_state); + status = acpi_ex_create_mutex (walk_state); break; @@ -614,7 +609,7 @@ goto cleanup; } - status = acpi_aml_exec_create_event (walk_state); + status = acpi_ex_create_event (walk_state); break; @@ -624,16 +619,13 @@ break; } - /* * The Op_region is not fully parsed at this time. Only valid argument is the Space_id. * (We must save the address of the AML of the address and length operands) */ - - status = acpi_aml_exec_create_region (((ACPI_PARSE2_OBJECT *) op)->data, - ((ACPI_PARSE2_OBJECT *) op)->length, - (ACPI_ADDRESS_SPACE_TYPE) arg->value.integer, - walk_state); + status = acpi_ex_create_region (((ACPI_PARSE2_OBJECT *) op)->data, + ((ACPI_PARSE2_OBJECT *) op)->length, + (ACPI_ADR_SPACE_TYPE) arg->value.integer, walk_state); break; @@ -647,7 +639,7 @@ goto cleanup; } - status = acpi_aml_exec_create_alias (walk_state); + status = acpi_ex_create_alias (walk_state); break; @@ -666,7 +658,7 @@ break; - case AML_NAMEPATH_OP: + case AML_INT_NAMEPATH_OP: break; diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/dispatcher/dswscope.c linux/drivers/acpi/dispatcher/dswscope.c --- v2.4.5/linux/drivers/acpi/dispatcher/dswscope.c Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/dispatcher/dswscope.c Wed Jun 20 17:47:39 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: dswscope - Scope stack manipulation - * $Revision: 42 $ + * $Revision: 45 $ * *****************************************************************************/ @@ -29,7 +29,7 @@ #include "acdispat.h" -#define _COMPONENT NAMESPACE +#define _COMPONENT ACPI_DISPATCHER MODULE_NAME ("dswscope") @@ -60,7 +60,7 @@ scope_info = walk_state->scope_info; walk_state->scope_info = scope_info->scope.next; - acpi_cm_delete_generic_state (scope_info); + acpi_ut_delete_generic_state (scope_info); } } @@ -80,7 +80,7 @@ ACPI_STATUS acpi_ds_scope_stack_push ( ACPI_NAMESPACE_NODE *node, - OBJECT_TYPE_INTERNAL type, + ACPI_OBJECT_TYPE8 type, ACPI_WALK_STATE *walk_state) { ACPI_GENERIC_STATE *scope_info; @@ -95,14 +95,14 @@ /* Make sure object type is valid */ - if (!acpi_aml_validate_object_type (type)) { + if (!acpi_ex_validate_object_type (type)) { REPORT_WARNING (("Ds_scope_stack_push: type code out of range\n")); } /* Allocate a new scope object */ - scope_info = acpi_cm_create_generic_state (); + scope_info = acpi_ut_create_generic_state (); if (!scope_info) { return (AE_NO_MEMORY); } @@ -114,7 +114,7 @@ /* Push new scope object onto stack */ - acpi_cm_push_generic_state (&walk_state->scope_info, scope_info); + acpi_ut_push_generic_state (&walk_state->scope_info, scope_info); return (AE_OK); } @@ -148,12 +148,12 @@ * Pop scope info object off the stack. */ - scope_info = acpi_cm_pop_generic_state (&walk_state->scope_info); + scope_info = acpi_ut_pop_generic_state (&walk_state->scope_info); if (!scope_info) { return (AE_STACK_UNDERFLOW); } - acpi_cm_delete_generic_state (scope_info); + acpi_ut_delete_generic_state (scope_info); return (AE_OK); } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/dispatcher/dswstate.c linux/drivers/acpi/dispatcher/dswstate.c --- v2.4.5/linux/drivers/acpi/dispatcher/dswstate.c Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/dispatcher/dswstate.c Wed Jun 20 17:47:39 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: dswstate - Dispatcher parse tree walk management routines - * $Revision: 38 $ + * $Revision: 45 $ * *****************************************************************************/ @@ -31,7 +31,7 @@ #include "acnamesp.h" #include "acinterp.h" -#define _COMPONENT DISPATCHER +#define _COMPONENT ACPI_DISPATCHER MODULE_NAME ("dswstate") @@ -57,6 +57,9 @@ ACPI_GENERIC_STATE *state; + PROC_NAME ("Ds_result_insert"); + + state = walk_state->results; if (!state) { return (AE_NOT_EXIST); @@ -100,6 +103,9 @@ ACPI_GENERIC_STATE *state; + PROC_NAME ("Ds_result_remove"); + + state = walk_state->results; if (!state) { return (AE_NOT_EXIST); @@ -147,6 +153,9 @@ ACPI_GENERIC_STATE *state; + PROC_NAME ("Ds_result_pop"); + + state = walk_state->results; if (!state) { return (AE_OK); @@ -199,6 +208,9 @@ ACPI_GENERIC_STATE *state; + PROC_NAME ("Ds_result_pop_from_bottom"); + + state = walk_state->results; if (!state) { return (AE_NOT_EXIST); @@ -254,6 +266,9 @@ ACPI_GENERIC_STATE *state; + PROC_NAME ("Ds_result_push"); + + state = walk_state->results; if (!state) { return (AE_AML_INTERNAL); @@ -295,12 +310,12 @@ ACPI_GENERIC_STATE *state; - state = acpi_cm_create_generic_state (); + state = acpi_ut_create_generic_state (); if (!state) { return (AE_NO_MEMORY); } - acpi_cm_push_generic_state (&walk_state->results, state); + acpi_ut_push_generic_state (&walk_state->results, state); return (AE_OK); } @@ -332,9 +347,9 @@ } - state = acpi_cm_pop_generic_state (&walk_state->results); + state = acpi_ut_pop_generic_state (&walk_state->results); - acpi_cm_delete_generic_state (state); + acpi_ut_delete_generic_state (state); return (AE_OK); } @@ -364,7 +379,7 @@ for (i = 0; i < OBJ_NUM_OPERANDS; i++) { if (walk_state->operands[i]) { - acpi_cm_remove_reference (walk_state->operands[i]); + acpi_ut_remove_reference (walk_state->operands[i]); walk_state->operands[i] = NULL; } } @@ -432,10 +447,10 @@ /* Check for stack underflow */ if (walk_state->num_operands == 0) { + *object = NULL; return (AE_AML_NO_OPERAND); } - /* Pop the stack */ walk_state->num_operands--; @@ -443,6 +458,7 @@ /* Check for a valid operand */ if (!walk_state->operands [walk_state->num_operands]) { + *object = NULL; return (AE_AML_NO_OPERAND); } @@ -529,7 +545,7 @@ walk_state->num_operands--; obj_desc = walk_state->operands [walk_state->num_operands]; if (obj_desc) { - acpi_cm_remove_reference (walk_state->operands [walk_state->num_operands]); + acpi_ut_remove_reference (walk_state->operands [walk_state->num_operands]); walk_state->operands [walk_state->num_operands] = NULL; } } @@ -696,7 +712,7 @@ ACPI_STATUS status; - acpi_cm_acquire_mutex (ACPI_MTX_CACHES); + acpi_ut_acquire_mutex (ACPI_MTX_CACHES); acpi_gbl_walk_state_cache_requests++; /* Check the cache first */ @@ -710,17 +726,17 @@ acpi_gbl_walk_state_cache_hits++; acpi_gbl_walk_state_cache_depth--; - acpi_cm_release_mutex (ACPI_MTX_CACHES); + acpi_ut_release_mutex (ACPI_MTX_CACHES); } else { /* The cache is empty, create a new object */ - /* Avoid deadlock with Acpi_cm_callocate */ + /* Avoid deadlock with Acpi_ut_callocate */ - acpi_cm_release_mutex (ACPI_MTX_CACHES); + acpi_ut_release_mutex (ACPI_MTX_CACHES); - walk_state = acpi_cm_callocate (sizeof (ACPI_WALK_STATE)); + walk_state = acpi_ut_callocate (sizeof (ACPI_WALK_STATE)); if (!walk_state) { return (NULL); } @@ -730,6 +746,7 @@ walk_state->owner_id = owner_id; walk_state->origin = origin; walk_state->method_desc = mth_desc; + walk_state->walk_list = walk_list; /* Init the method args/local */ @@ -787,7 +804,7 @@ state = walk_state->control_state; walk_state->control_state = state->common.next; - acpi_cm_delete_generic_state (state); + acpi_ut_delete_generic_state (state); } /* Always must free any linked parse states */ @@ -796,7 +813,7 @@ state = walk_state->scope_info; walk_state->scope_info = state->common.next; - acpi_cm_delete_generic_state (state); + acpi_ut_delete_generic_state (state); } /* Always must free any stacked result states */ @@ -805,20 +822,20 @@ state = walk_state->results; walk_state->results = state->common.next; - acpi_cm_delete_generic_state (state); + acpi_ut_delete_generic_state (state); } /* If walk cache is full, just free this wallkstate object */ if (acpi_gbl_walk_state_cache_depth >= MAX_WALK_CACHE_DEPTH) { - acpi_cm_free (walk_state); + acpi_ut_free (walk_state); } /* Otherwise put this object back into the cache */ else { - acpi_cm_acquire_mutex (ACPI_MTX_CACHES); + acpi_ut_acquire_mutex (ACPI_MTX_CACHES); /* Clear the state */ @@ -832,7 +849,7 @@ acpi_gbl_walk_state_cache_depth++; - acpi_cm_release_mutex (ACPI_MTX_CACHES); + acpi_ut_release_mutex (ACPI_MTX_CACHES); } return; @@ -865,7 +882,7 @@ /* Delete one cached state object */ next = acpi_gbl_walk_state_cache->next; - acpi_cm_free (acpi_gbl_walk_state_cache); + acpi_ut_free (acpi_gbl_walk_state_cache); acpi_gbl_walk_state_cache = next; acpi_gbl_walk_state_cache_depth--; } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/driver.c linux/drivers/acpi/driver.c --- v2.4.5/linux/drivers/acpi/driver.c Tue May 22 09:38:51 2001 +++ linux/drivers/acpi/driver.c Wed Jun 20 17:47:39 2001 @@ -2,6 +2,7 @@ * driver.c - ACPI driver * * Copyright (C) 2000 Andrew Henroid + * Copyright (C) 2001 Andrew Grover * * 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 @@ -21,6 +22,10 @@ * Changes * David Woodhouse 2000-12-6 * - Fix interruptible_sleep_on() races + * Andrew Grover 2001-2-28 + * - Major revamping + * Peter Breuer 2001-5-20 + * - parse boot time params. */ #include @@ -39,416 +44,44 @@ #ifdef CONFIG_ACPI_KERNEL_CONFIG #include -#define ACPI_CAN_USE_EFI_STRUCT +#define ACPI_USE_EFI #endif #define _COMPONENT OS_DEPENDENT MODULE_NAME ("driver") -struct acpi_run_entry -{ - void (*callback)(void*); - void *context; - struct tq_struct task; -}; - -static spinlock_t acpi_event_lock = SPIN_LOCK_UNLOCKED; -static volatile u32 acpi_event_status = 0; -static volatile acpi_sstate_t acpi_event_state = ACPI_STATE_S0; -static DECLARE_WAIT_QUEUE_HEAD(acpi_event_wait); - -static volatile int acpi_thread_pid = -1; - -static int acpi_start = 1; - -/************************************************/ -/* DECLARE_TASK_QUEUE is defined in */ -/* /usr/src/linux/include/linux/tqueue.h */ -/* So, acpi_thread_run is a pointer to a */ -/* tq_struct structure,defined in the same file.*/ -/************************************************/ -static DECLARE_TASK_QUEUE(acpi_thread_run); - -static DECLARE_WAIT_QUEUE_HEAD(acpi_thread_wait); - -static struct ctl_table_header *acpi_sysctl = NULL; - -/* - * Examine/modify value - */ -static int -acpi_do_ulong(ctl_table * ctl, - int write, - struct file *file, - void *buffer, - size_t * len) -{ - char str[2 * sizeof(unsigned long) + 4], *strend; - unsigned long val; - int size; - - if (!write) { - if (file->f_pos) { - *len = 0; - return 0; - } - - val = *(unsigned long *) ctl->data; - size = sprintf(str, "0x%08lx\n", val); - if (*len >= size) { - copy_to_user(buffer, str, size); - *len = size; - } - else - *len = 0; - } - else { - size = sizeof(str) - 1; - if (size > *len) - size = *len; - copy_from_user(str, buffer, size); - str[size] = '\0'; - val = simple_strtoul(str, &strend, 0); - if (strend == str) - return -EINVAL; - *(unsigned long *) ctl->data = val; - } - - file->f_pos += *len; - return 0; -} - -static int -acpi_do_pm_timer(ctl_table * ctl, - int write, - struct file *file, - void *buffer, - size_t * len) -{ - int size; - u32 val = 0; - - char str[12]; - - if (file->f_pos) { - *len = 0; - return 0; - } - - val = acpi_read_pm_timer(); - - size = sprintf(str, "0x%08x\n", val); - if (*len >= size) { - copy_to_user(buffer, str, size); - *len = size; - } - else - *len = 0; - - file->f_pos += *len; - - return 0; -} - -/* - * Handle ACPI event - */ -static u32 -acpi_event(void *context) -{ - unsigned long flags; - int event = (int)(long)context; - int mask = 0; - - switch (event) { - case ACPI_EVENT_POWER_BUTTON: - mask = ACPI_PWRBTN; - break; - case ACPI_EVENT_SLEEP_BUTTON: - mask = ACPI_SLPBTN; - break; - default: - return AE_ERROR; - } - - if (mask) { - // notify process waiting on /dev/acpi - spin_lock_irqsave(&acpi_event_lock, flags); - acpi_event_status |= mask; - spin_unlock_irqrestore(&acpi_event_lock, flags); - acpi_event_state = acpi_sleep_state; - wake_up_interruptible(&acpi_event_wait); - } - - return AE_OK; -} - -/* - * Wait for next event - */ -static int -acpi_do_event(ctl_table * ctl, - int write, - struct file *file, - void *buffer, - size_t * len) -{ - u32 event_status = 0; - acpi_sstate_t event_state = 0; - char str[27]; - int size; - - if (write) - return -EPERM; - if (*len < sizeof(str)) { - *len = 0; - return 0; - } - - while (!event_status) { - unsigned long flags; - DECLARE_WAITQUEUE(wait, current); - - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&acpi_event_wait, &wait); - - // we need an atomic exchange here - spin_lock_irqsave(&acpi_event_lock, flags); - event_status = acpi_event_status; - acpi_event_status = 0; - spin_unlock_irqrestore(&acpi_event_lock, flags); - event_state = acpi_event_state; - - if (!event_status) - schedule(); - - remove_wait_queue(&acpi_event_wait, &wait); - set_current_state(TASK_RUNNING); - - if (signal_pending(current)) - return -ERESTARTSYS; - } - - size = sprintf(str, - "0x%08x 0x%08x 0x%01x\n", - event_status, - 0, - event_state); - copy_to_user(buffer, str, size); - *len = size; - file->f_pos += size; - - return 0; -} - -/* - * Enter system sleep state - */ -/*static int -acpi_do_sleep(ctl_table * ctl, - int write, - struct file *file, - void *buffer, - size_t * len) -{ - if (!write) { - if (file->f_pos) { - *len = 0; - return 0; - } - } - else { - int status = acpi_enter_sx(ACPI_STATE_S1); - if (status) - return status; - } - file->f_pos += *len; - return 0; -}*/ - - -/* - * Output important ACPI tables to proc - */ -static int -acpi_do_table(ctl_table * ctl, - int write, - struct file *file, - void *buffer, - size_t * len) -{ - u32 table_type; - size_t size; - ACPI_BUFFER buf; - u8* data; - - table_type = (u32) ctl->data; - size = 0; - buf.length = 0; - buf.pointer = NULL; - - /* determine what buffer size we will need */ - if (acpi_get_table(table_type, 1, &buf) != AE_BUFFER_OVERFLOW) { - *len = 0; - return 0; - } - - buf.pointer = kmalloc(buf.length, GFP_KERNEL); - if (!buf.pointer) { - return -ENOMEM; - } - - /* get the table for real */ - if (!ACPI_SUCCESS(acpi_get_table(table_type, 1, &buf))) { - kfree(buf.pointer); - *len = 0; - return 0; - } - - if (file->f_pos < buf.length) { - data = buf.pointer + file->f_pos; - size = buf.length - file->f_pos; - if (size > *len) - size = *len; - if (copy_to_user(buffer, data, size)) { - kfree(buf.pointer); - return -EFAULT; - } - } +FADT_DESCRIPTOR acpi_fadt; - kfree(buf.pointer); - - *len = size; - file->f_pos += size; - return 0; -} - -/********************************************************************/ -/* R U N Q U E U E D C A L L B A C K */ -/* */ -/* The "callback" function address that was tramped through via */ -/* "acpi_run" below is finally called and executed. If we trace all */ -/* this down, the function is acpi_ev_asynch_execute_gpe_method, in */ -/* evevent.c The only other function that is ever queued is */ -/* acpi_ev_global_lock_thread in evmisc.c. */ -/********************************************************************/ -static void -acpi_run_exec(void *context) -{ - struct acpi_run_entry *entry - = (struct acpi_run_entry*) context; - (*entry->callback)(entry->context); - kfree(entry); -} +static int acpi_disabled = 0; /* - * Queue for execution by the ACPI thread + * Start the interpreter */ int -acpi_run(void (*callback)(void*), void *context) -{ - struct acpi_run_entry *entry; - - entry = kmalloc(sizeof(*entry), GFP_ATOMIC); - if (!entry) - return -1; - - memset(entry, 0, sizeof(entry)); - entry->callback = callback; - entry->context = context; - entry->task.routine = acpi_run_exec; - entry->task.data = entry; - - queue_task(&entry->task, &acpi_thread_run); - - if (waitqueue_active(&acpi_thread_wait)) - wake_up(&acpi_thread_wait); - - return 0; -} - -static struct ctl_table acpi_table[] = -{ - {ACPI_P_LVL2_LAT, "c2_exit_latency", - &acpi_c2_exit_latency, sizeof(acpi_c2_exit_latency), - 0644, NULL, &acpi_do_ulong}, - - {ACPI_ENTER_LVL2_LAT, "c2_enter_latency", - &acpi_c2_enter_latency, sizeof(acpi_c2_enter_latency), - 0644, NULL, &acpi_do_ulong}, - - {ACPI_P_LVL3_LAT, "c3_exit_latency", - &acpi_c3_exit_latency, sizeof(acpi_c3_exit_latency), - 0644, NULL, &acpi_do_ulong}, - - {ACPI_ENTER_LVL3_LAT, "c3_enter_latency", - &acpi_c3_enter_latency, sizeof(acpi_c3_enter_latency), - 0644, NULL, &acpi_do_ulong}, - - {ACPI_C1_COUNT, "c1_count", - &acpi_c1_count, sizeof(acpi_c1_count), - 0644, NULL, &acpi_do_ulong}, - - {ACPI_C2_COUNT, "c2_count", - &acpi_c2_count, sizeof(acpi_c2_count), - 0644, NULL, &acpi_do_ulong}, - - {ACPI_C3_COUNT, "c3_count", - &acpi_c3_count, sizeof(acpi_c3_count), - 0644, NULL, &acpi_do_ulong}, - - -/* until it actually works */ -/* {ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &acpi_do_sleep},*/ - - {ACPI_EVENT, "event", NULL, 0, 0400, NULL, &acpi_do_event}, - - {ACPI_FADT, "fadt", (void *) ACPI_TABLE_FADT, sizeof(int), - 0444, NULL, &acpi_do_table}, - - {ACPI_DSDT, "dsdt", (void *) ACPI_TABLE_DSDT, sizeof(int), - 0444, NULL, &acpi_do_table}, - - {ACPI_FACS, "facs", (void *) ACPI_TABLE_FACS, sizeof(int), - 0444, NULL, &acpi_do_table}, - - {ACPI_XSDT, "xsdt", (void *) ACPI_TABLE_XSDT, sizeof(int), - 0444, NULL, &acpi_do_table}, - - {ACPI_PMTIMER, "pm_timer", NULL, 0, 0444, NULL, &acpi_do_pm_timer}, - - {0} -}; - -static struct ctl_table acpi_dir_table[] = -{ - {CTL_ACPI, "acpi", NULL, 0, 0555, acpi_table}, - {0} -}; - -/* - * Initialize and run interpreter within a kernel thread - */ -static int -acpi_thread(void *context) +acpi_init(void) { ACPI_PHYSICAL_ADDRESS rsdp_phys; ACPI_BUFFER buffer; ACPI_SYSTEM_INFO sys_info; - /* - * initialize - */ - daemonize(); - strcpy(current->comm, "kacpid"); + if (PM_IS_ACTIVE()) { + printk(KERN_NOTICE "ACPI: APM is already active, exiting\n"); + return -ENODEV; + } + + + if (acpi_disabled) { + printk(KERN_NOTICE "ACPI: disabled by cmdline, exiting\n"); + return -ENODEV; + } if (!ACPI_SUCCESS(acpi_initialize_subsystem())) { printk(KERN_ERR "ACPI: Driver initialization failed\n"); return -ENODEV; } -#ifndef ACPI_CAN_USE_EFI_STRUCT +#ifndef ACPI_USE_EFI if (!ACPI_SUCCESS(acpi_find_root_pointer(&rsdp_phys))) { printk(KERN_ERR "ACPI: System description tables not found\n"); return -ENODEV; @@ -456,12 +89,22 @@ #else rsdp_phys = efi.acpi; #endif - - if (!ACPI_SUCCESS(acpi_find_and_load_tables(rsdp_phys))) + + /* from this point on, on error we must call acpi_terminate() */ + + if (!ACPI_SUCCESS(acpi_load_tables(rsdp_phys))) { + printk(KERN_ERR "ACPI: System description table load failed\n"); + acpi_terminate(); return -ENODEV; + } - if (PM_IS_ACTIVE()) { - printk(KERN_NOTICE "ACPI: APM is already active, exiting\n"); + /* get a separate copy of the FADT for use by other drivers */ + memset(&acpi_fadt, 0, sizeof(acpi_fadt)); + buffer.pointer = &acpi_fadt; + buffer.length = sizeof(acpi_fadt); + + if (!ACPI_SUCCESS(acpi_get_table(ACPI_TABLE_FADT, 1, &buffer))) { + printk(KERN_ERR "ACPI: Could not get FADT\n"); acpi_terminate(); return -ENODEV; } @@ -483,129 +126,37 @@ return -ENODEV; } - printk(KERN_ERR "ACPI: Subsystem enabled\n"); + printk(KERN_INFO "ACPI: Subsystem enabled\n"); pm_active = 1; - acpi_cpu_init(); - acpi_sys_init(); - acpi_ec_init(); - acpi_power_init(); - - /* - * Non-intuitive: 0 means pwr and sleep are implemented using the fixed - * feature model, so we install handlers. 1 means a control method - * implementation, or none at all, so do nothing. See ACPI spec. - */ - if (acpi_fadt.pwr_button == 0) { - if (!ACPI_SUCCESS(acpi_install_fixed_event_handler( - ACPI_EVENT_POWER_BUTTON, - acpi_event, - (void *) ACPI_EVENT_POWER_BUTTON))) { - printk(KERN_ERR "ACPI: power button enable failed\n"); - } - } - - if (acpi_fadt.sleep_button == 0) { - if (!ACPI_SUCCESS(acpi_install_fixed_event_handler( - ACPI_EVENT_SLEEP_BUTTON, - acpi_event, - (void *) ACPI_EVENT_SLEEP_BUTTON))) { - printk(KERN_ERR "ACPI: sleep button enable failed\n"); - } - } - - acpi_sysctl = register_sysctl_table(acpi_dir_table, 1); - - /* - * run - */ - for (;;) { - DECLARE_WAITQUEUE(wait, current); - - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&acpi_thread_wait, &wait); - - if (list_empty(&acpi_thread_run)) - schedule(); - - remove_wait_queue(&acpi_thread_wait, &wait); - set_current_state(TASK_RUNNING); - - if (signal_pending(current)) - break; - - run_task_queue(&acpi_thread_run); - } - - /* - * terminate - */ - unregister_sysctl_table(acpi_sysctl); - - /* do not terminate, because we need acpi in order to shut down */ - /*acpi_terminate();*/ - - acpi_thread_pid = -1; - return 0; } /* - * Start the interpreter - */ -int __init -acpi_init(void) -{ - if (acpi_start) { - acpi_thread_pid = kernel_thread(acpi_thread, - NULL, - (CLONE_FS | CLONE_FILES - | CLONE_SIGHAND | SIGCHLD)); - } - else { - printk(KERN_INFO "ACPI: Disabled\n"); - } - - return ((acpi_thread_pid >= 0) ? 0:-ENODEV); -} - -/* * Terminate the interpreter */ -void __exit +void acpi_exit(void) { - int count; + acpi_terminate(); - if (!kill_proc(acpi_thread_pid, SIGTERM, 1)) { - // wait until thread terminates (at most 5 seconds) - count = 5 * HZ; - while (acpi_thread_pid >= 0 && --count) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); - } - } - - pm_idle = NULL; - pm_power_off = NULL; pm_active = 0; + + printk(KERN_ERR "ACPI: Subsystem disabled\n"); } module_init(acpi_init); module_exit(acpi_exit); #ifndef MODULE -static int __init acpi_setup(char *str) -{ - while ((str != NULL) && (*str != '\0')) { - if (strncmp(str, "no-idle", 7) == 0) - acpi_use_idle = 0; - if (strncmp(str, "off", 3) == 0) - acpi_start = 0; - str = strchr(str, ','); - if (str != NULL) - str += strspn(str, ", \t"); +static 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; } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/driver.h linux/drivers/acpi/driver.h --- v2.4.5/linux/drivers/acpi/driver.h Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/driver.h Wed Jun 20 17:47:39 2001 @@ -69,11 +69,4 @@ extern volatile acpi_sstate_t acpi_sleep_state; -/* - * table.c - */ -extern FADT_DESCRIPTOR acpi_fadt; - -int acpi_find_and_load_tables(u64 rsdp); - #endif /* __DRIVER_H */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ec.c linux/drivers/acpi/ec.c --- v2.4.5/linux/drivers/acpi/ec.c Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/ec.c Wed Dec 31 16:00:00 1969 @@ -1,600 +0,0 @@ -/* - * ec.c - Embedded controller support - * - * Copyright (C) 2000 Andrew Henroid - * - * 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 "acpi.h" -#include "driver.h" -#include "ec.h" - -#define _COMPONENT OS_DEPENDENT - MODULE_NAME ("ec") - -#define ACPI_EC_HID "PNP0C09" - -enum -{ - ACPI_EC_SMI = 0x40, - ACPI_EC_SCI = 0x20, - ACPI_EC_BURST = 0x10, - ACPI_EC_CMD = 0x08, - ACPI_EC_IBF = 0x02, - ACPI_EC_OBF = 0x01 -}; - -enum -{ - ACPI_EC_READ = 0x80, - ACPI_EC_WRITE = 0x81, - ACPI_EC_BURST_ENABLE = 0x82, - ACPI_EC_BURST_DISABLE = 0x83, - ACPI_EC_QUERY = 0x84, -}; - -typedef struct -{ - ACPI_HANDLE acpi_handle; - u32 gpe_bit; - ACPI_IO_ADDRESS status_port; - ACPI_IO_ADDRESS data_port; - u32 need_global_lock; -} ec_context_t; - - -typedef struct -{ - ec_context_t *ec; - u8 data; - -} EC_QUERY_DATA; - -static char object_name[] = {'_', 'Q', '0', '0', '\0'}; - -static char hex[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; - - -static ACPI_STATUS -ec_io_wait ( - ec_context_t *ec, - EC_EVENT wait_event) -{ - EC_STATUS ec_status = 0; - UINT32 i = 100; - - if (!ec || ((wait_event != EC_EVENT_OUTPUT_BUFFER_FULL) - && (wait_event != EC_EVENT_INPUT_BUFFER_EMPTY))) - return(AE_BAD_PARAMETER); - - /* - * Wait for Event: - * --------------- - * Poll the EC status register waiting for the event to occur. - * Note that we'll wait a maximum of 1ms in 10us chunks. - */ - switch (wait_event) { - case EC_EVENT_OUTPUT_BUFFER_FULL: - do { - ec_status = acpi_os_in8(ec->status_port); - if (ec_status & EC_FLAG_OUTPUT_BUFFER) - return(AE_OK); - acpi_os_sleep_usec(10); - } while (--i>0); - break; - case EC_EVENT_INPUT_BUFFER_EMPTY: - do { - ec_status = acpi_os_in8(ec->status_port); - if (!(ec_status & EC_FLAG_INPUT_BUFFER)) - return(AE_OK); - acpi_os_sleep_usec(10); - } while (--i>0); - break; - } - - return(AE_TIME); -} - -static ACPI_STATUS -ec_io_read ( - ec_context_t *ec, - ACPI_IO_ADDRESS io_port, - UINT8 *data, - EC_EVENT wait_event) -{ - ACPI_STATUS status = AE_OK; - - if (!ec || !data) - return(AE_BAD_PARAMETER); - - *data = acpi_os_in8(io_port); - - if (wait_event) - status = ec_io_wait(ec, wait_event); - - return(status); -} - -static ACPI_STATUS -ec_io_write ( - ec_context_t *ec, - ACPI_IO_ADDRESS io_port, - UINT8 data, - EC_EVENT wait_event) -{ - ACPI_STATUS status = AE_OK; - - if (!ec) - return(AE_BAD_PARAMETER); - - acpi_os_out8(io_port, data); - - if (wait_event) - status = ec_io_wait(ec, wait_event); - - return(status); -} - -static ACPI_STATUS -ec_read ( - ec_context_t *ec, - UINT8 address, - UINT8 *data) -{ - ACPI_STATUS status = AE_OK; - - FUNCTION_TRACE("ec_read"); - - if (!ec || !data) - return_ACPI_STATUS(AE_BAD_PARAMETER); - - status = ec_io_write(ec, ec->status_port, EC_COMMAND_READ, EC_EVENT_INPUT_BUFFER_EMPTY); - if (ACPI_FAILURE(status)) { - DEBUG_PRINT(ACPI_WARN, ("Unable to send 'read command' to EC.\n")); - return_ACPI_STATUS(status); - } - - status = ec_io_write(ec, ec->data_port, address, EC_EVENT_OUTPUT_BUFFER_FULL); - if (ACPI_FAILURE(status)) { - DEBUG_PRINT(ACPI_WARN, ("Unable to send 'read address' to EC.\n")); - return_ACPI_STATUS(status); - } - - status = ec_io_read(ec, ec->data_port, data, EC_EVENT_NONE); - - DEBUG_PRINT(ACPI_INFO, ("Read data[0x%02x] from address[0x%02x] on ec.\n", (*data), address)); - - return_ACPI_STATUS(status); -} - -static ACPI_STATUS -ec_write ( - ec_context_t *ec, - UINT8 address, - UINT8 data) -{ - ACPI_STATUS status = AE_OK; - - FUNCTION_TRACE("ec_write"); - - if (!ec) - return_ACPI_STATUS(AE_BAD_PARAMETER); - - status = ec_io_write(ec, ec->status_port, EC_COMMAND_WRITE, EC_EVENT_INPUT_BUFFER_EMPTY); - if (ACPI_FAILURE(status)) { - DEBUG_PRINT(ACPI_WARN, ("Unable to send 'write command' to EC.\n")); - return_ACPI_STATUS(status); - } - - status = ec_io_write(ec, ec->data_port, address, EC_EVENT_INPUT_BUFFER_EMPTY); - if (ACPI_FAILURE(status)) { - DEBUG_PRINT(ACPI_WARN, ("Unable to send 'write address' to EC.\n")); - return_ACPI_STATUS(status); - } - - status = ec_io_write(ec, ec->data_port, data, EC_EVENT_INPUT_BUFFER_EMPTY); - if (ACPI_FAILURE(status)) { - DEBUG_PRINT(ACPI_WARN, ("Unable to send 'write data' to EC.\n")); - return_ACPI_STATUS(status); - } - - DEBUG_PRINT(ACPI_INFO, ("Wrote data[0x%02x] to address[0x%02x] on ec.\n", data, address)); - - return_ACPI_STATUS(status); -} - -static ACPI_STATUS -ec_transaction ( - ec_context_t *ec, - EC_REQUEST *request) -{ - ACPI_STATUS status = AE_OK; - - FUNCTION_TRACE("ec_transaction"); - - if (!ec || !request) - return_ACPI_STATUS(AE_BAD_PARAMETER); - - /* - * Obtaining semaphore (mutex) to serialize all EC transactions. - */ - /* - DEBUG_PRINT(ACPI_INFO, ("Calling acpi_os_wait_semaphore(%p, 1, %d)\n", ec->mutex, EC_DEFAULT_TIMEOUT)); - status = acpi_os_wait_semaphore(ec->mutex, 1, EC_DEFAULT_TIMEOUT); - if (ACPI_FAILURE(status)) - return_ACPI_STATUS(status); - */ - - /* - * Perform the transaction. - */ - switch (request->command) { - - case EC_COMMAND_READ: - status = ec_read(ec, request->address, &(request->data)); - break; - - case EC_COMMAND_WRITE: - status = ec_write(ec, request->address, request->data); - break; - - default: - status = AE_SUPPORT; - break; - } - - /* - * Signal the semaphore (mutex) to indicate transaction completion. - */ - /* - DEBUG_PRINT(ACPI_INFO, ("Calling acpi_os_signal_semaphore(%p, 1)\n", ec->mutex)); - acpi_os_signal_semaphore(ec->mutex, 1); - */ - - return_ACPI_STATUS(status); -} - - -static void -ec_query_handler ( - void *context) -{ - ACPI_STATUS status = AE_OK; - EC_QUERY_DATA *ec_q = (EC_QUERY_DATA*)context; - - FUNCTION_TRACE("ec_query_handler"); - - if (!ec_q || !ec_q->ec) { - DEBUG_PRINT(ACPI_ERROR, ("Invalid (NULL) context.\n")); - return_VOID; - } - - /* - * Evaluate _Qxx: - * -------------- - * Evaluate corresponding _Qxx method. Note that a zero query - * value indicates a spurious EC_SCI (no such thing as _Q00). - */ - object_name[2] = hex[((ec_q->data >> 4) & 0x0F)]; - object_name[3] = hex[(ec_q->data & 0x0F)]; - - DEBUG_PRINT(ACPI_INFO, ("Read query data[0x%02x] from ec - evaluating [%s].\n", ec_q->data, object_name)); - - status = acpi_evaluate_object(ec_q->ec->acpi_handle, object_name, NULL, NULL); - - kfree(ec_q); - - return_VOID; -} - -/* - * handle GPE - */ -static void -ec_gpe_handler(void *context) -{ - ACPI_STATUS status = AE_OK; - ec_context_t *ec = (ec_context_t *) context; - EC_QUERY_DATA *ec_q = NULL; - EC_STATUS ec_status = 0; - - FUNCTION_TRACE("ec_gpe_handler"); - - if (!ec) { - DEBUG_PRINT(ACPI_INFO, ("Invalid (NULL) context.\n")); - return_VOID; - } - - // GET SPINLOCK! - - /* - * EC_SCI? - * ------- - * Check the EC_SCI bit to see if this is an EC_SCI event. If not (e.g. - * OBF/IBE) just return, as we already poll to detect these events. - */ - ec_status = acpi_os_in8(ec->status_port); - DEBUG_PRINT(ACPI_INFO, ("EC Status Register: [0x%02x]\n", ec_status)); - if (!(ec_status & EC_FLAG_SCI)) - return_VOID; - - DEBUG_PRINT(ACPI_INFO, ("EC_SCI detected - running QUERY.\n")); - - // TODO: Need GFP_ATOMIC 'switch' for OSL interface... - ec_q = kmalloc(sizeof(EC_QUERY_DATA), GFP_ATOMIC); - if (!ec_q) { - DEBUG_PRINT(ACPI_INFO, ("Memory allocation failure.\n")); - return_VOID; - } - - ec_q->ec = ec; - ec_q->data = 0; - - /* - * Run Query: - * ---------- - * Query the EC to find out which _Qxx method we need to evaluate. - * Note that successful completion of the query causes the EC_SCI - * bit to be cleared (and thus clearing the interrupt source). - */ - status = ec_io_write(ec, ec->status_port, EC_COMMAND_QUERY, EC_EVENT_OUTPUT_BUFFER_FULL); - if (ACPI_FAILURE(status)) { - DEBUG_PRINT(ACPI_WARN, ("Unable to send 'query command' to EC.\n")); - goto End; - } - - status = ec_io_read(ec, ec->data_port, &(ec_q->data), EC_EVENT_NONE); - if (ACPI_FAILURE(status)) { - DEBUG_PRINT(ACPI_WARN, ("Error reading query data.\n")); - goto End; - } - - // RELEASE SPINLOCK! - - if (!ec_q->data) { - DEBUG_PRINT(ACPI_WARN, ("Spurious EC SCI detected.\n")); - status = AE_ERROR; - goto End; - } - - /* - * Defer _Qxx Execution: - * --------------------- - * Can't evaluate this method now 'cause we're at interrupt-level. - */ - status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, ec_query_handler, ec_q); - if (ACPI_FAILURE(status)) { - DEBUG_PRINT(ACPI_ERROR, ("Unable to defer _Qxx method evaluation.\n")); - goto End; - } - -End: - if (ACPI_FAILURE(status)) - kfree(ec_q); - - return_VOID; -} - -static ACPI_STATUS -ec_region_setup ( - ACPI_HANDLE handle, - u32 function, - void *handler_context, - void **region_context) -{ - FUNCTION_TRACE("acpi_ec_region_setup"); - - if (function == ACPI_REGION_DEACTIVATE) - { - if (*region_context) - { - acpi_cm_free (*region_context); - *region_context = NULL; - } - - return_ACPI_STATUS (AE_OK); - } - - *region_context = NULL; - - return_ACPI_STATUS (AE_OK); -} - -/***************************************************************************** - * - * FUNCTION: ec_region_handler - * - * PARAMETERS: function - Read or Write operation - * address - Where in the space to read or write - * bit_width - Field width in bits (8, 16, or 32) - * value - Pointer to in or out value - * context - context pointer - * - * RETURN: - * - * DESCRIPTION: Handler for the Embedded Controller (EC) address space - * (Op Region) - * - ****************************************************************************/ - -static ACPI_STATUS -ec_region_handler ( - UINT32 function, - ACPI_PHYSICAL_ADDRESS address, - UINT32 bit_width, - UINT32 *value, - void *handler_context, - void *region_context) -{ - ACPI_STATUS status = AE_OK; - ec_context_t *ec = NULL; - EC_REQUEST ec_request; - - FUNCTION_TRACE("ec_space_handler"); - - if (address > 0xFF || bit_width != 8 || !value || !handler_context) - return_ACPI_STATUS(AE_BAD_PARAMETER); - - ec = (ec_context_t*)handler_context; - - switch (function) { - - case ADDRESS_SPACE_READ: - ec_request.command = EC_COMMAND_READ; - ec_request.address = address; - ec_request.data = 0; - break; - - case ADDRESS_SPACE_WRITE: - ec_request.command = EC_COMMAND_WRITE; - ec_request.address = address; - ec_request.data = (UINT8)(*value); - break; - - default: - DEBUG_PRINT(ACPI_WARN, ("Received request with invalid function [0x%08X].\n", function)); - return_ACPI_STATUS(AE_BAD_PARAMETER); - break; - } - - DEBUG_PRINT(ACPI_INFO, ("device[ec] command[0x%02X] address[0x%02X] data[0x%02X]\n", ec_request.command, ec_request.address, ec_request.data)); - - /* - * Perform the Transaction. - */ - status = ec_transaction(ec, &ec_request); - if (ACPI_SUCCESS(status)) - (*value) = (UINT32)ec_request.data; - - return_ACPI_STATUS(status); -} - -/* - * Get Embedded Controller information - */ -static ACPI_STATUS -found_ec( - ACPI_HANDLE handle, - u32 level, - void *ctx, - void **value) -{ - ACPI_STATUS status; - ACPI_OBJECT obj; - ACPI_BUFFER buf; - RESOURCE *res; - ec_context_t *ec_cxt; - - buf.length = 0; - buf.pointer = NULL; - if (acpi_get_current_resources(handle, &buf) != AE_BUFFER_OVERFLOW) - return AE_OK; - - buf.pointer = kmalloc(buf.length, GFP_KERNEL); - if (!buf.pointer) - return AE_NO_MEMORY; - - if (!ACPI_SUCCESS(acpi_get_current_resources(handle, &buf))) { - kfree(buf.pointer); - return AE_OK; - } - - ec_cxt = kmalloc(sizeof(ec_context_t), GFP_KERNEL); - if (!ec_cxt) { - kfree(buf.pointer); - return AE_NO_MEMORY; - } - - ec_cxt->acpi_handle = handle; - - res = (RESOURCE*) buf.pointer; - ec_cxt->data_port = res->data.io.min_base_address; - res = NEXT_RESOURCE(res); - ec_cxt->status_port = (int) res->data.io.min_base_address; - - kfree(buf.pointer); - - /* determine GPE bit */ - /* BUG: in acpi 2.0 this could return a package */ - buf.length = sizeof(obj); - buf.pointer = &obj; - if (!ACPI_SUCCESS(acpi_evaluate_object(handle, "_GPE", NULL, &buf)) - || obj.type != ACPI_TYPE_INTEGER) - return AE_OK; - - ec_cxt->gpe_bit = obj.integer.value; - - /* determine if we need the Global Lock when accessing */ - buf.length = sizeof(obj); - buf.pointer = &obj; - - status = acpi_evaluate_object(handle, "_GLK", NULL, &buf); - if (status == AE_NOT_FOUND) - ec_cxt->need_global_lock = 0; - else if (!ACPI_SUCCESS(status) || obj.type != ACPI_TYPE_INTEGER) { - DEBUG_PRINT(ACPI_ERROR, ("_GLK failed\n")); - return AE_OK; - } - - ec_cxt->need_global_lock = obj.integer.value; - - printk(KERN_INFO "ACPI: found EC @ (0x%02x,0x%02x,GPE %d GL %d)\n", - ec_cxt->data_port, ec_cxt->status_port, ec_cxt->gpe_bit, - ec_cxt->need_global_lock); - - if (!ACPI_SUCCESS(acpi_install_gpe_handler( - ec_cxt->gpe_bit, - ACPI_EVENT_EDGE_TRIGGERED, - ec_gpe_handler, - ec_cxt))) { - - REPORT_ERROR(("Could not install GPE handler for EC.\n")); - return AE_OK; - } - - status = acpi_install_address_space_handler (handle, ADDRESS_SPACE_EC, - ec_region_handler, ec_region_setup, ec_cxt); - - if (!ACPI_SUCCESS(status)) { - REPORT_ERROR(("Could not install EC address " - "space handler, error %s\n", acpi_cm_format_exception (status))); - } - - return AE_OK; -} - -int -acpi_ec_init(void) -{ - acpi_get_devices(ACPI_EC_HID, - found_ec, - NULL, - NULL); - - return 0; -} - -int -acpi_ec_terminate(void) -{ - /* TODO */ - /* walk list of EC's */ - /* free their context and release resources */ - return 0; -} diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ec.h linux/drivers/acpi/ec.h --- v2.4.5/linux/drivers/acpi/ec.h Fri Dec 29 14:07:21 2000 +++ linux/drivers/acpi/ec.h Wed Dec 31 16:00:00 1969 @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2000 Andrew Grover - * - * 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 - */ - - -#ifndef __EC_H__ -#define __EC_H__ - -// TODO: Linux-specific -#include -#include - -#include -#include - -/***************************************************************************** - * Types & Other Defines - *****************************************************************************/ - -#define EC_DEFAULT_TIMEOUT 1000 /* 1 second */ -#define EC_GPE_UNKNOWN 0xFFFFFFFF -#define EC_PORT_UNKNOWN 0x00000000 -#define EC_BURST_ENABLE_ACKNOWLEDGE 0x90 - -/* - * EC_COMMAND: - * ----------- - */ -typedef UINT8 EC_COMMAND; - -#define EC_COMMAND_UNKNOWN ((EC_COMMAND) 0x00) -#define EC_COMMAND_READ ((EC_COMMAND) 0x80) -#define EC_COMMAND_WRITE ((EC_COMMAND) 0x81) -#define EC_COMMAND_QUERY ((EC_COMMAND) 0x84) - -/* - * EC_STATUS: - * ---------- - * The encoding of the EC status register is illustrated below. - * Note that a set bit (1) indicates the property is TRUE - * (e.g. if bit 0 is set then the output buffer is full). - * +-+-+-+-+-+-+-+-+ - * |7|6|5|4|3|2|1|0| - * +-+-+-+-+-+-+-+-+ - * | | | | | | | | - * | | | | | | | +- Output Buffer Full (OBF)? - * | | | | | | +--- Input Buffer Full (IBF)? - * | | | | | +----- - * | | | | +------- data Register is command Byte? - * | | | +--------- Burst Mode Enabled? - * | | +----------- SCI event? - * | +------------- SMI event? - * +--------------- - * - */ -typedef UINT8 EC_STATUS; - -#define EC_FLAG_OUTPUT_BUFFER ((EC_STATUS) 0x01) -#define EC_FLAG_INPUT_BUFFER ((EC_STATUS) 0x02) -#define EC_FLAG_BURST_MODE ((EC_STATUS) 0x10) -#define EC_FLAG_SCI ((EC_STATUS) 0x20) - -/* - * EC_EVENT: - * --------- - */ -typedef UINT8 EC_EVENT; - -#define EC_EVENT_UNKNOWN ((EC_EVENT) 0x00) -#define EC_EVENT_NONE ((EC_EVENT) 0x00) -#define EC_EVENT_OUTPUT_BUFFER_FULL ((EC_EVENT) 0x01) -#define EC_EVENT_INPUT_BUFFER_EMPTY ((EC_EVENT) 0x02) -#define EC_EVENT_SCI ((EC_EVENT) 0x03) - -/* - * EC_REQUEST: - * ----------- - */ -typedef struct -{ - EC_COMMAND command; - UINT8 address; - UINT8 data; -} EC_REQUEST; - -#endif /* __EC_H__ */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/events/Makefile linux/drivers/acpi/events/Makefile --- v2.4.5/linux/drivers/acpi/events/Makefile Fri Dec 29 14:07:21 2000 +++ linux/drivers/acpi/events/Makefile Wed Jun 20 17:47:39 2001 @@ -1,16 +1,12 @@ # # Makefile for all Linux ACPI interpreter subdirectories +# EXCEPT for the ospm directory # -O_TARGET := ../$(shell basename `pwd`).o +O_TARGET := $(notdir $(CURDIR)).o obj-$(CONFIG_ACPI) := $(patsubst %.c,%.o,$(wildcard *.c)) -EXTRA_CFLAGS += -I../include - EXTRA_CFLAGS += $(ACPI_CFLAGS) include $(TOPDIR)/Rules.make - -clean: - $(RM) *.o diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/events/evevent.c linux/drivers/acpi/events/evevent.c --- v2.4.5/linux/drivers/acpi/events/evevent.c Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/events/evevent.c Wed Jun 20 17:47:39 2001 @@ -2,7 +2,7 @@ * * Module Name: evevent - Fixed and General Purpose Acpi_event * handling and dispatch - * $Revision: 34 $ + * $Revision: 43 $ * *****************************************************************************/ @@ -28,13 +28,12 @@ #include "achware.h" #include "acevents.h" #include "acnamesp.h" -#include "accommon.h" -#define _COMPONENT EVENT_HANDLING +#define _COMPONENT ACPI_EVENTS MODULE_NAME ("evevent") -/************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ev_initialize * @@ -46,7 +45,7 @@ * configured, disables SCI event sources, installs the SCI * handler * - *************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_ev_initialize ( @@ -114,7 +113,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ev_fixed_event_initialize * @@ -133,7 +132,7 @@ /* Initialize the structure that keeps track of fixed event handlers */ - for (i = 0; i < NUM_FIXED_EVENTS; i++) { + for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { acpi_gbl_fixed_event_handlers[i].handler = NULL; acpi_gbl_fixed_event_handlers[i].context = NULL; } @@ -148,7 +147,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ev_fixed_event_detect * @@ -179,32 +178,28 @@ /* power management timer roll over */ if ((status_register & ACPI_STATUS_PMTIMER) && - (enable_register & ACPI_ENABLE_PMTIMER)) - { + (enable_register & ACPI_ENABLE_PMTIMER)) { int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_PMTIMER); } - /* global event (BIOS want's the global lock) */ + /* global event (BIOS wants the global lock) */ if ((status_register & ACPI_STATUS_GLOBAL) && - (enable_register & ACPI_ENABLE_GLOBAL)) - { + (enable_register & ACPI_ENABLE_GLOBAL)) { int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_GLOBAL); } /* power button event */ if ((status_register & ACPI_STATUS_POWER_BUTTON) && - (enable_register & ACPI_ENABLE_POWER_BUTTON)) - { + (enable_register & ACPI_ENABLE_POWER_BUTTON)) { int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_POWER_BUTTON); } /* sleep button event */ if ((status_register & ACPI_STATUS_SLEEP_BUTTON) && - (enable_register & ACPI_ENABLE_SLEEP_BUTTON)) - { + (enable_register & ACPI_ENABLE_SLEEP_BUTTON)) { int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_SLEEP_BUTTON); } @@ -212,7 +207,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ev_fixed_event_dispatch * @@ -233,8 +228,7 @@ /* Clear the status bit */ - switch (event) - { + switch (event) { case ACPI_EVENT_PMTIMER: register_id = TMR_STS; break; @@ -286,7 +280,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ev_gpe_initialize * @@ -339,7 +333,7 @@ * Allocate the Gpe information block */ - acpi_gbl_gpe_registers = acpi_cm_callocate (acpi_gbl_gpe_register_count * + acpi_gbl_gpe_registers = acpi_ut_callocate (acpi_gbl_gpe_register_count * sizeof (ACPI_GPE_REGISTERS)); if (!acpi_gbl_gpe_registers) { return (AE_NO_MEMORY); @@ -351,16 +345,16 @@ * Initialization to zeros is sufficient */ - acpi_gbl_gpe_info = acpi_cm_callocate (MUL_8 (acpi_gbl_gpe_register_count) * + acpi_gbl_gpe_info = acpi_ut_callocate (MUL_8 (acpi_gbl_gpe_register_count) * sizeof (ACPI_GPE_LEVEL_INFO)); if (!acpi_gbl_gpe_info) { - acpi_cm_free (acpi_gbl_gpe_registers); + acpi_ut_free (acpi_gbl_gpe_registers); return (AE_NO_MEMORY); } /* Set the Gpe validation table to GPE_INVALID */ - MEMSET (acpi_gbl_gpe_valid, (int) ACPI_GPE_INVALID, NUM_GPE); + MEMSET (acpi_gbl_gpe_valid, (int) ACPI_GPE_INVALID, ACPI_NUM_GPE); /* * Initialize the Gpe information and validation blocks. A goal of these @@ -430,7 +424,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ev_save_method_info * @@ -464,6 +458,9 @@ u8 type; + PROC_NAME ("Ev_save_method_info"); + + /* Extract the name from the object and convert to a string */ MOVE_UNALIGNED32_TO_32 (name, &((ACPI_NAMESPACE_NODE *) obj_handle)->name); @@ -520,7 +517,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ev_init_gpe_control_methods * @@ -557,7 +554,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ev_gpe_detect * @@ -623,7 +620,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ev_asynch_execute_gpe_method * @@ -650,9 +647,9 @@ /* * Take a snapshot of the GPE info for this level */ - acpi_cm_acquire_mutex (ACPI_MTX_EVENTS); + acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); gpe_info = acpi_gbl_gpe_info [gpe_number]; - acpi_cm_release_mutex (ACPI_MTX_EVENTS); + acpi_ut_release_mutex (ACPI_MTX_EVENTS); /* * Method Handler (_Lxx, _Exx): @@ -681,7 +678,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ev_gpe_dispatch * @@ -706,7 +703,6 @@ { ACPI_GPE_LEVEL_INFO gpe_info; - /*DEBUG_INCREMENT_EVENT_COUNT (EVENT_GENERAL);*/ /* * Valid GPE number? @@ -751,8 +747,7 @@ */ else if (gpe_info.method_handle) { if (ACPI_FAILURE(acpi_os_queue_for_execution (OSD_PRIORITY_GPE, - acpi_ev_asynch_execute_gpe_method, (void*)(NATIVE_UINT)gpe_number))) - { + acpi_ev_asynch_execute_gpe_method, (void*) gpe_number))) { /* * Shoudn't occur, but if it does report an error. Note that * the GPE will remain disabled until the ACPI Core Subsystem diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/events/evmisc.c linux/drivers/acpi/events/evmisc.c --- v2.4.5/linux/drivers/acpi/events/evmisc.c Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/events/evmisc.c Wed Jun 20 17:47:40 2001 @@ -2,7 +2,7 @@ * * Module Name: evmisc - ACPI device notification handler dispatch * and ACPI Global Lock support - * $Revision: 22 $ + * $Revision: 31 $ * *****************************************************************************/ @@ -30,13 +30,13 @@ #include "acinterp.h" #include "achware.h" -#define _COMPONENT EVENT_HANDLING +#define _COMPONENT ACPI_EVENTS MODULE_NAME ("evmisc") -/************************************************************************** +/******************************************************************************* * - * FUNCTION: Acpi_ev_notify_dispatch + * FUNCTION: Acpi_ev_queue_notify_request * * PARAMETERS: * @@ -45,16 +45,20 @@ * DESCRIPTION: Dispatch a device notification event to a previously * installed handler. * - *************************************************************************/ + ******************************************************************************/ -void -acpi_ev_notify_dispatch ( - ACPI_HANDLE device, +ACPI_STATUS +acpi_ev_queue_notify_request ( + ACPI_NAMESPACE_NODE *node, u32 notify_value) { ACPI_OPERAND_OBJECT *obj_desc; - ACPI_OPERAND_OBJECT *handler_obj; - NOTIFY_HANDLER handler; + ACPI_OPERAND_OBJECT *handler_obj = NULL; + ACPI_GENERIC_STATE *notify_info; + ACPI_STATUS status = AE_OK; + + + PROC_NAME ("Ev_queue_notify_request"); /* @@ -64,9 +68,7 @@ * initiate soft-off or sleep operation? */ - - switch (notify_value) - { + switch (notify_value) { case 0: break; @@ -85,67 +87,136 @@ /* - * Invoke a global notify handler if installed. - * This is done _before_ we invoke the per-device handler attached to the device. + * Get the notify object attached to the device Node */ - if (notify_value <= MAX_SYS_NOTIFY) { - /* Global system notification handler */ + obj_desc = acpi_ns_get_attached_object (node); + if (obj_desc) { - if (acpi_gbl_sys_notify.handler) { - acpi_gbl_sys_notify.handler (device, notify_value, - acpi_gbl_sys_notify.context); + /* We have the notify object, Get the right handler */ + + switch (node->type) { + case ACPI_TYPE_DEVICE: + if (notify_value <= MAX_SYS_NOTIFY) { + handler_obj = obj_desc->device.sys_handler; + } + else { + handler_obj = obj_desc->device.drv_handler; + } + break; + + case ACPI_TYPE_THERMAL: + if (notify_value <= MAX_SYS_NOTIFY) { + handler_obj = obj_desc->thermal_zone.sys_handler; + } + else { + handler_obj = obj_desc->thermal_zone.drv_handler; + } + break; } } - else { - /* Global driver notification handler */ - if (acpi_gbl_drv_notify.handler) { - acpi_gbl_drv_notify.handler (device, notify_value, - acpi_gbl_drv_notify.context); + /* If there is any handler to run, schedule the dispatcher */ + + if ((acpi_gbl_sys_notify.handler && (notify_value <= MAX_SYS_NOTIFY)) || + (acpi_gbl_drv_notify.handler && (notify_value > MAX_SYS_NOTIFY)) || + handler_obj) { + + notify_info = acpi_ut_create_generic_state (); + if (!notify_info) { + return (AE_NO_MEMORY); + } + + notify_info->notify.node = node; + notify_info->notify.value = (u16) notify_value; + notify_info->notify.handler_obj = handler_obj; + + status = acpi_os_queue_for_execution (OSD_PRIORITY_HIGH, + acpi_ev_notify_dispatch, notify_info); + if (ACPI_FAILURE (status)) { + acpi_ut_delete_generic_state (notify_info); } } + if (!handler_obj) { + /* There is no per-device notify handler for this device */ - /* - * Get the notify object which must be attached to the device Node - */ + } - obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) device); - if (!obj_desc) { - /* There can be no notify handler for this device */ + return (status); +} - return; - } +/******************************************************************************* + * + * FUNCTION: Acpi_ev_notify_dispatch + * + * PARAMETERS: + * + * RETURN: None. + * + * DESCRIPTION: Dispatch a device notification event to a previously + * installed handler. + * + ******************************************************************************/ + +void +acpi_ev_notify_dispatch ( + void *context) +{ + ACPI_GENERIC_STATE *notify_info = (ACPI_GENERIC_STATE *) context; + ACPI_NOTIFY_HANDLER global_handler = NULL; + void *global_context = NULL; + ACPI_OPERAND_OBJECT *handler_obj; - /* We have the notify object, Get the right handler */ - if (notify_value <= MAX_SYS_NOTIFY) { - handler_obj = obj_desc->device.sys_handler; + /* + * We will invoke a global notify handler if installed. + * This is done _before_ we invoke the per-device handler attached to the device. + */ + + if (notify_info->notify.value <= MAX_SYS_NOTIFY) { + /* Global system notification handler */ + + if (acpi_gbl_sys_notify.handler) { + global_handler = acpi_gbl_sys_notify.handler; + global_context = acpi_gbl_sys_notify.context; + } } + else { - handler_obj = obj_desc->device.drv_handler; + /* Global driver notification handler */ + + if (acpi_gbl_drv_notify.handler) { + global_handler = acpi_gbl_drv_notify.handler; + global_context = acpi_gbl_drv_notify.context; + } } - /* Validate the handler */ - if (!handler_obj) { - /* There is no notify handler for this device */ + /* Invoke the system handler first, if present */ - return; + if (global_handler) { + global_handler (notify_info->notify.node, notify_info->notify.value, global_context); } - /* There is a handler, invoke it */ + /* Now invoke the per-device handler, if present */ - handler = handler_obj->notify_handler.handler; - handler (device, notify_value, handler_obj->notify_handler.context); + handler_obj = notify_info->notify.handler_obj; + if (handler_obj) { + handler_obj->notify_handler.handler (notify_info->notify.node, notify_info->notify.value, + handler_obj->notify_handler.context); + } + + /* All done with the info object */ + + acpi_ut_delete_generic_state (notify_info); } -/*************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ev_global_lock_thread * @@ -155,7 +226,7 @@ * Global Lock. Simply signal all threads that are waiting * for the lock. * - **************************************************************************/ + ******************************************************************************/ static void acpi_ev_global_lock_thread ( @@ -173,7 +244,7 @@ } -/*************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ev_global_lock_handler * @@ -183,7 +254,7 @@ * release interrupt occurs. Grab the global lock and queue * the global lock thread for execution * - **************************************************************************/ + ******************************************************************************/ static u32 acpi_ev_global_lock_handler ( @@ -216,7 +287,7 @@ } -/*************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ev_init_global_lock_handler * @@ -224,7 +295,7 @@ * * DESCRIPTION: Install a handler for the global lock release event * - **************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_ev_init_global_lock_handler (void) @@ -232,14 +303,27 @@ ACPI_STATUS status; + acpi_gbl_global_lock_present = TRUE; status = acpi_install_fixed_event_handler (ACPI_EVENT_GLOBAL, acpi_ev_global_lock_handler, NULL); + /* + * If the global lock does not exist on this platform, the attempt + * to enable GBL_STS will fail (the GBL_EN bit will not stick) + * Map to AE_OK, but mark global lock as not present. + * Any attempt to actually use the global lock will be flagged + * with an error. + */ + if (status == AE_NO_HARDWARE_RESPONSE) { + acpi_gbl_global_lock_present = FALSE; + status = AE_OK; + } + return (status); } -/*************************************************************************** +/****************************************************************************** * * FUNCTION: Acpi_ev_acquire_global_lock * @@ -247,7 +331,7 @@ * * DESCRIPTION: Attempt to gain ownership of the Global Lock. * - **************************************************************************/ + *****************************************************************************/ ACPI_STATUS acpi_ev_acquire_global_lock(void) @@ -257,6 +341,12 @@ void *global_lock; + /* Make sure that we actually have a global lock */ + + if (!acpi_gbl_global_lock_present) { + return (AE_NO_GLOBAL_LOCK); + } + /* One more thread wants the global lock */ acpi_gbl_global_lock_thread_count++; @@ -283,7 +373,6 @@ /* We got the lock */ acpi_gbl_global_lock_acquired = TRUE; - return (AE_OK); } @@ -298,20 +387,19 @@ * Since this wait will block, we must release the interpreter */ - status = acpi_aml_system_wait_semaphore (acpi_gbl_global_lock_semaphore, + status = acpi_ex_system_wait_semaphore (acpi_gbl_global_lock_semaphore, ACPI_UINT32_MAX); - return (status); } -/*************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ev_release_global_lock * * DESCRIPTION: Releases ownership of the Global Lock. * - **************************************************************************/ + ******************************************************************************/ void acpi_ev_release_global_lock (void) @@ -321,7 +409,7 @@ if (!acpi_gbl_global_lock_thread_count) { - REPORT_WARNING(("Releasing a non-acquired Global Lock\n")); + REPORT_WARNING(("Global Lock has not be acquired, cannot release\n")); return; } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/events/evregion.c linux/drivers/acpi/events/evregion.c --- v2.4.5/linux/drivers/acpi/events/evregion.c Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/events/evregion.c Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: evregion - ACPI Address_space (Op_region) handler dispatch - * $Revision: 96 $ + * $Revision: 103 $ * *****************************************************************************/ @@ -30,11 +30,11 @@ #include "acinterp.h" #include "amlcode.h" -#define _COMPONENT EVENT_HANDLING +#define _COMPONENT ACPI_EVENTS MODULE_NAME ("evregion") -/************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ev_install_default_address_space_handlers * @@ -44,7 +44,7 @@ * * DESCRIPTION: Installs the core subsystem address space handlers. * - *************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_ev_install_default_address_space_handlers ( @@ -70,29 +70,26 @@ */ status = acpi_install_address_space_handler (acpi_gbl_root_node, - ADDRESS_SPACE_SYSTEM_MEMORY, + ACPI_ADR_SPACE_SYSTEM_MEMORY, ACPI_DEFAULT_HANDLER, NULL, NULL); if ((ACPI_FAILURE (status)) && - (status != AE_EXIST)) - { + (status != AE_EXIST)) { return (status); } status = acpi_install_address_space_handler (acpi_gbl_root_node, - ADDRESS_SPACE_SYSTEM_IO, + ACPI_ADR_SPACE_SYSTEM_IO, ACPI_DEFAULT_HANDLER, NULL, NULL); if ((ACPI_FAILURE (status)) && - (status != AE_EXIST)) - { + (status != AE_EXIST)) { return (status); } status = acpi_install_address_space_handler (acpi_gbl_root_node, - ADDRESS_SPACE_PCI_CONFIG, + ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); if ((ACPI_FAILURE (status)) && - (status != AE_EXIST)) - { + (status != AE_EXIST)) { return (status); } @@ -103,7 +100,7 @@ /* TBD: [Restructure] Move elsewhere */ -/************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ev_execute_reg_method * @@ -114,7 +111,7 @@ * * DESCRIPTION: Execute _REG method for a region * - *************************************************************************/ + ******************************************************************************/ static ACPI_STATUS acpi_ev_execute_reg_method ( @@ -141,8 +138,8 @@ * Passed as a parameter */ - acpi_cm_init_static_object (&space_id_desc); - acpi_cm_init_static_object (&function_desc); + acpi_ut_init_static_object (&space_id_desc); + acpi_ut_init_static_object (&function_desc); /* * Method requires two parameters. @@ -168,7 +165,7 @@ } -/************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ev_address_space_dispatch * @@ -184,7 +181,7 @@ * DESCRIPTION: Dispatch an address space or operation region access to * a previously installed handler. * - *************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_ev_address_space_dispatch ( @@ -195,28 +192,27 @@ u32 *value) { ACPI_STATUS status; - ADDRESS_SPACE_HANDLER handler; - ADDRESS_SPACE_SETUP region_setup; + ACPI_ADR_SPACE_HANDLER handler; + ACPI_ADR_SPACE_SETUP region_setup; ACPI_OPERAND_OBJECT *handler_desc; void *region_context = NULL; /* - * Check for an installed handler + * Ensure that there is a handler associated with this region */ handler_desc = region_obj->region.addr_handler; - if (!handler_desc) { return(AE_NOT_EXIST); } /* - * It may be the case that the region has never been initialized - * Some types of regions require special init code + * It may be the case that the region has never been initialized + * Some types of regions require special init code */ if (!(region_obj->region.flags & AOPOBJ_INITIALIZED)) { /* - * This region has not been initialized yet, do it + * This region has not been initialized yet, do it */ region_setup = handler_desc->addr_handler.setup; if (!region_setup) { @@ -230,15 +226,14 @@ * We must exit the interpreter because the region setup will potentially * execute control methods */ - acpi_aml_exit_interpreter (); + acpi_ex_exit_interpreter (); status = region_setup (region_obj, ACPI_REGION_ACTIVATE, - handler_desc->addr_handler.context, - ®ion_context); + handler_desc->addr_handler.context, ®ion_context); /* Re-enter the interpreter */ - acpi_aml_enter_interpreter (); + acpi_ex_enter_interpreter (); /* * Init routine may fail @@ -267,7 +262,7 @@ * exit the interpreter because the handler *might* block -- we don't * know what it will do, so we can't hold the lock on the intepreter. */ - acpi_aml_exit_interpreter(); + acpi_ex_exit_interpreter(); } /* @@ -282,13 +277,13 @@ /* We just returned from a non-default handler, we must re-enter the interpreter */ - acpi_aml_enter_interpreter (); + acpi_ex_enter_interpreter (); } return (status); } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ev_disassociate_region_from_handler * @@ -310,7 +305,7 @@ ACPI_OPERAND_OBJECT *handler_obj; ACPI_OPERAND_OBJECT *obj_desc; ACPI_OPERAND_OBJECT **last_obj_ptr; - ADDRESS_SPACE_SETUP region_setup; + ACPI_ADR_SPACE_SETUP region_setup; void *region_context; ACPI_STATUS status; @@ -349,7 +344,7 @@ obj_desc->region.next = NULL; /* Must clear field */ if (acpi_ns_is_locked) { - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); } /* @@ -358,7 +353,7 @@ acpi_ev_execute_reg_method (region_obj, 0); if (acpi_ns_is_locked) { - acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); } /* @@ -366,8 +361,7 @@ */ region_setup = handler_obj->addr_handler.setup; status = region_setup (region_obj, ACPI_REGION_DEACTIVATE, - handler_obj->addr_handler.context, - ®ion_context); + handler_obj->addr_handler.context, ®ion_context); /* * Init routine may fail, Just ignore errors @@ -407,7 +401,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ev_associate_region_and_handler * @@ -456,20 +450,20 @@ * Last thing, tell all users that this region is usable */ if (acpi_ns_is_locked) { - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); } status = acpi_ev_execute_reg_method (region_obj, 1); if (acpi_ns_is_locked) { - acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); } return (status); } -/**************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ev_addr_handler_helper * @@ -486,7 +480,7 @@ * This is because the existing handler is closer in proximity * to any more regions than the one we are trying to install. * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_ev_addr_handler_helper ( @@ -502,6 +496,9 @@ ACPI_STATUS status; + PROC_NAME ("Ev_addr_handler_helper"); + + handler_obj = (ACPI_OPERAND_OBJECT *) context; /* Parameter validation */ @@ -524,14 +521,13 @@ if ((node->type != ACPI_TYPE_DEVICE) && (node->type != ACPI_TYPE_REGION) && - (node != acpi_gbl_root_node)) - { + (node != acpi_gbl_root_node)) { return (AE_OK); } /* Check for an existing internal object */ - obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) node); + obj_desc = acpi_ns_get_attached_object (node); if (!obj_desc) { /* * The object DNE, we don't care about it @@ -555,7 +551,6 @@ /* * It's for the same address space */ - /* * Since the object we found it on was a device, then it * means that someone has already installed a handler for diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/events/evrgnini.c linux/drivers/acpi/events/evrgnini.c --- v2.4.5/linux/drivers/acpi/events/evrgnini.c Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/events/evrgnini.c Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: evrgnini- ACPI Address_space (Op_region) init - * $Revision: 33 $ + * $Revision: 40 $ * *****************************************************************************/ @@ -30,11 +30,11 @@ #include "acinterp.h" #include "amlcode.h" -#define _COMPONENT EVENT_HANDLING +#define _COMPONENT ACPI_EVENTS MODULE_NAME ("evrgnini") -/***************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ev_system_memory_region_setup * @@ -47,7 +47,7 @@ * * DESCRIPTION: Do any prep work for region handling, a nop for now * - ****************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_ev_system_memory_region_setup ( @@ -59,7 +59,7 @@ if (function == ACPI_REGION_DEACTIVATE) { if (*region_context) { - acpi_cm_free (*region_context); + acpi_ut_free (*region_context); *region_context = NULL; } return (AE_OK); @@ -68,7 +68,7 @@ /* Activate. Create a new context */ - *region_context = acpi_cm_callocate (sizeof (MEM_HANDLER_CONTEXT)); + *region_context = acpi_ut_callocate (sizeof (ACPI_MEM_SPACE_CONTEXT)); if (!(*region_context)) { return (AE_NO_MEMORY); } @@ -77,7 +77,7 @@ } -/***************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ev_io_space_region_setup * @@ -90,7 +90,7 @@ * * DESCRIPTION: Do any prep work for region handling * - ****************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_ev_io_space_region_setup ( @@ -99,6 +99,7 @@ void *handler_context, void **region_context) { + if (function == ACPI_REGION_DEACTIVATE) { *region_context = NULL; } @@ -110,7 +111,7 @@ } -/***************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ev_pci_config_region_setup * @@ -125,7 +126,7 @@ * * MUTEX: Assumes namespace is not locked * - ****************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_ev_pci_config_region_setup ( @@ -136,25 +137,25 @@ { ACPI_STATUS status = AE_OK; ACPI_INTEGER temp; - PCI_HANDLER_CONTEXT *pci_context = *region_context; + ACPI_PCI_SPACE_CONTEXT *pci_context = *region_context; ACPI_OPERAND_OBJECT *handler_obj; ACPI_NAMESPACE_NODE *node; ACPI_OPERAND_OBJECT *region_obj = (ACPI_OPERAND_OBJECT *) handle; - DEVICE_ID object_hID; + ACPI_DEVICE_ID object_hID; - handler_obj = region_obj->region.addr_handler; + handler_obj = region_obj->region.addr_handler; if (!handler_obj) { /* * No installed handler. This shouldn't happen because the dispatch * routine checks before we get here, but we check again just in case. */ - return(AE_NOT_EXIST); + return (AE_NOT_EXIST); } if (function == ACPI_REGION_DEACTIVATE) { if (pci_context) { - acpi_cm_free (pci_context); + acpi_ut_free (pci_context); *region_context = NULL; } @@ -164,7 +165,7 @@ /* Create a new context */ - pci_context = acpi_cm_callocate (sizeof(PCI_HANDLER_CONTEXT)); + pci_context = acpi_ut_callocate (sizeof (ACPI_PCI_SPACE_CONTEXT)); if (!pci_context) { return (AE_NO_MEMORY); } @@ -178,22 +179,20 @@ * First get device and function numbers from the _ADR object * in the parent's scope. */ - ACPI_ASSERT(region_obj->region.node); + ACPI_ASSERT (region_obj->region.node); node = acpi_ns_get_parent_object (region_obj->region.node); /* Acpi_evaluate the _ADR object */ - status = acpi_cm_evaluate_numeric_object (METHOD_NAME__ADR, node, &temp); + 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. */ if (ACPI_SUCCESS (status)) { - /* - * Got it.. - */ pci_context->dev_func = (u32) temp; } @@ -215,40 +214,31 @@ * Node is currently the parent object */ while (node != acpi_gbl_root_node) { - status = acpi_cm_execute_HID(node, &object_hID); - + status = acpi_ut_execute_HID (node, &object_hID); if (ACPI_SUCCESS (status)) { - if (!(STRNCMP(object_hID.buffer, PCI_ROOT_HID_STRING, - sizeof (PCI_ROOT_HID_STRING)))) - { - acpi_install_address_space_handler(node, - ADDRESS_SPACE_PCI_CONFIG, + if (!(STRNCMP (object_hID.buffer, PCI_ROOT_HID_STRING, + sizeof (PCI_ROOT_HID_STRING)))) { + acpi_install_address_space_handler (node, + ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); - break; } } - node = acpi_ns_get_parent_object(node); + node = acpi_ns_get_parent_object (node); } } else { node = handler_obj->addr_handler.node; } - status = acpi_cm_evaluate_numeric_object (METHOD_NAME__SEG, node, &temp); + status = acpi_ut_evaluate_numeric_object (METHOD_NAME__SEG, node, &temp); if (ACPI_SUCCESS (status)) { - /* - * Got it.. - */ pci_context->seg = (u32) temp; } - status = acpi_cm_evaluate_numeric_object (METHOD_NAME__BBN, node, &temp); + status = acpi_ut_evaluate_numeric_object (METHOD_NAME__BBN, node, &temp); if (ACPI_SUCCESS (status)) { - /* - * Got it.. - */ pci_context->bus = (u32) temp; } @@ -258,7 +248,7 @@ } -/***************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ev_default_region_setup * @@ -271,7 +261,7 @@ * * DESCRIPTION: Do any prep work for region handling * - ****************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_ev_default_region_setup ( @@ -280,6 +270,7 @@ void *handler_context, void **region_context) { + if (function == ACPI_REGION_DEACTIVATE) { *region_context = NULL; } @@ -291,7 +282,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ev_initialize_region * @@ -307,7 +298,7 @@ * * This also performs address space specific intialization. For * example, PCI regions must have an _ADR object that contains - * a PCI address in the scope of the defintion. This address is + * a PCI address in the scope of the definition. This address is * required to perform an access to PCI config space. * ******************************************************************************/ @@ -317,20 +308,20 @@ ACPI_OPERAND_OBJECT *region_obj, u8 acpi_ns_locked) { - ACPI_OPERAND_OBJECT *handler_obj; - ACPI_OPERAND_OBJECT *obj_desc; - ACPI_ADDRESS_SPACE_TYPE space_id; - ACPI_NAMESPACE_NODE *node; + ACPI_OPERAND_OBJECT *handler_obj; + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_ADR_SPACE_TYPE space_id; + ACPI_NAMESPACE_NODE *node; ACPI_STATUS status; - ACPI_NAMESPACE_NODE *method_node; - ACPI_NAME *reg_name_ptr = (ACPI_NAME *) METHOD_NAME__REG; + ACPI_NAMESPACE_NODE *method_node; + ACPI_NAME *reg_name_ptr = (ACPI_NAME *) METHOD_NAME__REG; if (!region_obj) { return (AE_BAD_PARAMETER); } - ACPI_ASSERT(region_obj->region.node); + ACPI_ASSERT (region_obj->region.node); node = acpi_ns_get_parent_object (region_obj->region.node); space_id = region_obj->region.space_id; @@ -362,13 +353,12 @@ * Check to see if a handler exists */ handler_obj = NULL; - obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) node); + obj_desc = acpi_ns_get_attached_object (node); if (obj_desc) { /* * can only be a handler if the object exists */ - switch (node->type) - { + switch (node->type) { case ACPI_TYPE_DEVICE: handler_obj = obj_desc->device.addr_handler; @@ -394,7 +384,8 @@ /* * Found it! Now update the region and the handler */ - acpi_ev_associate_region_and_handler (handler_obj, region_obj, acpi_ns_locked); + acpi_ev_associate_region_and_handler (handler_obj, region_obj, + acpi_ns_locked); return (AE_OK); } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/events/evsci.c linux/drivers/acpi/events/evsci.c --- v2.4.5/linux/drivers/acpi/events/evsci.c Tue Mar 6 19:44:36 2001 +++ linux/drivers/acpi/events/evsci.c Wed Jun 20 17:47:40 2001 @@ -2,7 +2,7 @@ * * Module Name: evsci - System Control Interrupt configuration and * legacy to ACPI mode state transition functions - * $Revision: 69 $ + * $Revision: 72 $ * ******************************************************************************/ @@ -30,7 +30,7 @@ #include "acevents.h" -#define _COMPONENT EVENT_HANDLING +#define _COMPONENT ACPI_EVENTS MODULE_NAME ("evsci") @@ -172,21 +172,6 @@ /******************************************************************************* * - * FUNCTION: Acpi_ev_sci_count - * - * PARAMETERS: Event Event that generated an SCI. - * - * RETURN: Number of SCI's for requested event since last time - * Sci_occurred() was called for this event. - * - * DESCRIPTION: Checks to see if SCI has been generated from requested source - * since the last time this function was called. - * - ******************************************************************************/ - - -/******************************************************************************* - * * FUNCTION: Acpi_ev_restore_acpi_state * * PARAMETERS: none @@ -209,8 +194,7 @@ /* Restore the fixed events */ if (acpi_hw_register_read (ACPI_MTX_LOCK, PM1_EN) != - acpi_gbl_pm1_enable_register_save) - { + acpi_gbl_pm1_enable_register_save) { acpi_hw_register_write (ACPI_MTX_LOCK, PM1_EN, acpi_gbl_pm1_enable_register_save); } @@ -225,8 +209,7 @@ for (index = 0; index < DIV_2 (acpi_gbl_FADT->gpe0blk_len); index++) { if (acpi_hw_register_read (ACPI_MTX_LOCK, GPE0_EN_BLOCK | index) != - acpi_gbl_gpe0enable_register_save[index]) - { + acpi_gbl_gpe0enable_register_save[index]) { acpi_hw_register_write (ACPI_MTX_LOCK, GPE0_EN_BLOCK | index, acpi_gbl_gpe0enable_register_save[index]); } @@ -237,8 +220,7 @@ if (acpi_gbl_FADT->gpe1_blk_len) { for (index = 0; index < DIV_2 (acpi_gbl_FADT->gpe1_blk_len); index++) { if (acpi_hw_register_read (ACPI_MTX_LOCK, GPE1_EN_BLOCK | index) != - acpi_gbl_gpe1_enable_register_save[index]) - { + acpi_gbl_gpe1_enable_register_save[index]) { acpi_hw_register_write (ACPI_MTX_LOCK, GPE1_EN_BLOCK | index, acpi_gbl_gpe1_enable_register_save[index]); } @@ -276,11 +258,11 @@ */ if (acpi_gbl_gpe_registers) { - acpi_cm_free (acpi_gbl_gpe_registers); + acpi_ut_free (acpi_gbl_gpe_registers); } if (acpi_gbl_gpe_info) { - acpi_cm_free (acpi_gbl_gpe_info); + acpi_ut_free (acpi_gbl_gpe_info); } return; diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/events/evxface.c linux/drivers/acpi/events/evxface.c --- v2.4.5/linux/drivers/acpi/events/evxface.c Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/events/evxface.c Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: evxface - External interfaces for ACPI events - * $Revision: 101 $ + * $Revision: 110 $ * *****************************************************************************/ @@ -31,11 +31,11 @@ #include "amlcode.h" #include "acinterp.h" -#define _COMPONENT EVENT_HANDLING +#define _COMPONENT ACPI_EVENTS MODULE_NAME ("evxface") -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_install_fixed_event_handler * @@ -54,19 +54,26 @@ ACPI_STATUS acpi_install_fixed_event_handler ( u32 event, - FIXED_EVENT_HANDLER handler, + ACPI_EVENT_HANDLER handler, void *context) { - ACPI_STATUS status = AE_OK; + ACPI_STATUS status; - /* Sanity check the parameters. */ + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Parameter validation */ - if (event >= NUM_FIXED_EVENTS) { + if (event > ACPI_EVENT_MAX) { return (AE_BAD_PARAMETER); } - acpi_cm_acquire_mutex (ACPI_MTX_EVENTS); + acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); /* Don't allow two handlers. */ @@ -81,26 +88,23 @@ acpi_gbl_fixed_event_handlers[event].handler = handler; acpi_gbl_fixed_event_handlers[event].context = context; - status = acpi_enable_event(event, ACPI_EVENT_FIXED); - - if (!ACPI_SUCCESS(status)) { + status = acpi_enable_event (event, ACPI_EVENT_FIXED); + if (!ACPI_SUCCESS (status)) { /* Remove the handler */ acpi_gbl_fixed_event_handlers[event].handler = NULL; acpi_gbl_fixed_event_handlers[event].context = NULL; - - status = AE_ERROR; - goto cleanup; } + cleanup: - acpi_cm_release_mutex (ACPI_MTX_EVENTS); + acpi_ut_release_mutex (ACPI_MTX_EVENTS); return (status); } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_remove_fixed_event_handler * @@ -116,40 +120,44 @@ ACPI_STATUS acpi_remove_fixed_event_handler ( u32 event, - FIXED_EVENT_HANDLER handler) + ACPI_EVENT_HANDLER handler) { ACPI_STATUS status = AE_OK; - /* Sanity check the parameters. */ + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Parameter validation */ - if (event >= NUM_FIXED_EVENTS) { + if (event > ACPI_EVENT_MAX) { return (AE_BAD_PARAMETER); } - acpi_cm_acquire_mutex (ACPI_MTX_EVENTS); + acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); /* Disable the event before removing the handler - just in case... */ status = acpi_disable_event(event, ACPI_EVENT_FIXED); - if (!ACPI_SUCCESS(status)) { - status = AE_ERROR; - acpi_cm_release_mutex (ACPI_MTX_EVENTS); - return (status); - } - - /* Remove the handler */ + /* Always Remove the handler */ acpi_gbl_fixed_event_handlers[event].handler = NULL; acpi_gbl_fixed_event_handlers[event].context = NULL; - acpi_cm_release_mutex (ACPI_MTX_EVENTS); + + + + acpi_ut_release_mutex (ACPI_MTX_EVENTS); return (status); } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_install_notify_handler * @@ -170,7 +178,7 @@ acpi_install_notify_handler ( ACPI_HANDLE device, u32 handler_type, - NOTIFY_HANDLER handler, + ACPI_NOTIFY_HANDLER handler, void *context) { ACPI_OPERAND_OBJECT *obj_desc; @@ -179,15 +187,21 @@ ACPI_STATUS status = AE_OK; + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + /* Parameter validation */ if ((!handler) || - (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) - { + (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { return (AE_BAD_PARAMETER); } - acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); /* Convert and validate the device handle */ @@ -210,8 +224,7 @@ if (((handler_type == ACPI_SYSTEM_NOTIFY) && acpi_gbl_sys_notify.handler) || ((handler_type == ACPI_DEVICE_NOTIFY) && - acpi_gbl_drv_notify.handler)) - { + acpi_gbl_drv_notify.handler)) { status = AE_EXIST; goto unlock_and_exit; } @@ -243,15 +256,14 @@ if ((device_node->type != ACPI_TYPE_DEVICE) && (device_node->type != ACPI_TYPE_PROCESSOR) && (device_node->type != ACPI_TYPE_POWER) && - (device_node->type != ACPI_TYPE_THERMAL)) - { + (device_node->type != ACPI_TYPE_THERMAL)) { status = AE_BAD_PARAMETER; goto unlock_and_exit; } /* Check for an existing internal object */ - obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) device_node); + obj_desc = acpi_ns_get_attached_object (device_node); if (obj_desc) { /* Object exists - make sure there's no handler */ @@ -259,8 +271,7 @@ if (((handler_type == ACPI_SYSTEM_NOTIFY) && obj_desc->device.sys_handler) || ((handler_type == ACPI_DEVICE_NOTIFY) && - obj_desc->device.drv_handler)) - { + obj_desc->device.drv_handler)) { status = AE_EXIST; goto unlock_and_exit; } @@ -269,7 +280,7 @@ else { /* Create a new object */ - obj_desc = acpi_cm_create_internal_object (device_node->type); + obj_desc = acpi_ut_create_internal_object (device_node->type); if (!obj_desc) { status = AE_NO_MEMORY; goto unlock_and_exit; @@ -278,7 +289,6 @@ /* Attach new object to the Node */ status = acpi_ns_attach_object (device, obj_desc, (u8) device_node->type); - if (ACPI_FAILURE (status)) { goto unlock_and_exit; } @@ -286,7 +296,7 @@ /* Install the handler */ - notify_obj = acpi_cm_create_internal_object (INTERNAL_TYPE_NOTIFY); + notify_obj = acpi_ut_create_internal_object (INTERNAL_TYPE_NOTIFY); if (!notify_obj) { status = AE_NO_MEMORY; goto unlock_and_exit; @@ -300,18 +310,19 @@ if (handler_type == ACPI_SYSTEM_NOTIFY) { obj_desc->device.sys_handler = notify_obj; } + else /* ACPI_DEVICE_NOTIFY */ { obj_desc->device.drv_handler = notify_obj; } } unlock_and_exit: - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return (status); } -/***************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_remove_notify_handler * @@ -330,22 +341,29 @@ acpi_remove_notify_handler ( ACPI_HANDLE device, u32 handler_type, - NOTIFY_HANDLER handler) + ACPI_NOTIFY_HANDLER handler) { ACPI_OPERAND_OBJECT *notify_obj; ACPI_OPERAND_OBJECT *obj_desc; ACPI_NAMESPACE_NODE *device_node; ACPI_STATUS status = AE_OK; + + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + /* Parameter validation */ if ((!handler) || - (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) - { + (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { return (AE_BAD_PARAMETER); } - acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); /* Convert and validate the device handle */ @@ -364,8 +382,7 @@ if (((handler_type == ACPI_SYSTEM_NOTIFY) && !acpi_gbl_sys_notify.handler) || ((handler_type == ACPI_DEVICE_NOTIFY) && - !acpi_gbl_drv_notify.handler)) - { + !acpi_gbl_drv_notify.handler)) { status = AE_NOT_EXIST; goto unlock_and_exit; } @@ -393,15 +410,14 @@ if ((device_node->type != ACPI_TYPE_DEVICE) && (device_node->type != ACPI_TYPE_PROCESSOR) && (device_node->type != ACPI_TYPE_POWER) && - (device_node->type != ACPI_TYPE_THERMAL)) - { + (device_node->type != ACPI_TYPE_THERMAL)) { status = AE_BAD_PARAMETER; goto unlock_and_exit; } /* Check for an existing internal object */ - obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) device_node); + obj_desc = acpi_ns_get_attached_object (device_node); if (!obj_desc) { status = AE_NOT_EXIST; goto unlock_and_exit; @@ -417,8 +433,7 @@ } if ((!notify_obj) || - (notify_obj->notify_handler.handler != handler)) - { + (notify_obj->notify_handler.handler != handler)) { status = AE_BAD_PARAMETER; goto unlock_and_exit; } @@ -432,17 +447,17 @@ obj_desc->device.drv_handler = NULL; } - acpi_cm_remove_reference (notify_obj); + acpi_ut_remove_reference (notify_obj); } unlock_and_exit: - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return (status); } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_install_gpe_handler * @@ -463,14 +478,22 @@ acpi_install_gpe_handler ( u32 gpe_number, u32 type, - GPE_HANDLER handler, + ACPI_GPE_HANDLER handler, void *context) { ACPI_STATUS status = AE_OK; + + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + /* Parameter validation */ - if (!handler || (gpe_number > NUM_GPE)) { + if (!handler || (gpe_number > ACPI_GPE_MAX)) { return (AE_BAD_PARAMETER); } @@ -480,7 +503,7 @@ return (AE_BAD_PARAMETER); } - acpi_cm_acquire_mutex (ACPI_MTX_EVENTS); + acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); /* Make sure that there isn't a handler there already */ @@ -501,12 +524,12 @@ acpi_hw_enable_gpe (gpe_number); cleanup: - acpi_cm_release_mutex (ACPI_MTX_EVENTS); + acpi_ut_release_mutex (ACPI_MTX_EVENTS); return (status); } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_remove_gpe_handler * @@ -522,14 +545,21 @@ ACPI_STATUS acpi_remove_gpe_handler ( u32 gpe_number, - GPE_HANDLER handler) + ACPI_GPE_HANDLER handler) { ACPI_STATUS status = AE_OK; + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + /* Parameter validation */ - if (!handler || (gpe_number > NUM_GPE)) { + if (!handler || (gpe_number > ACPI_GPE_MAX)) { return (AE_BAD_PARAMETER); } @@ -543,7 +573,7 @@ acpi_hw_disable_gpe (gpe_number); - acpi_cm_acquire_mutex (ACPI_MTX_EVENTS); + acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); /* Make sure that the installed handler is the same */ @@ -559,12 +589,12 @@ acpi_gbl_gpe_info[gpe_number].context = NULL; cleanup: - acpi_cm_release_mutex (ACPI_MTX_EVENTS); + acpi_ut_release_mutex (ACPI_MTX_EVENTS); return (status); } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_acquire_global_lock * @@ -583,7 +613,17 @@ ACPI_STATUS status; - acpi_aml_enter_interpreter (); + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + + status = acpi_ex_enter_interpreter (); + if (ACPI_FAILURE (status)) { + return (status); + } /* * TBD: [Restructure] add timeout param to internal interface, and @@ -591,13 +631,13 @@ */ status = acpi_ev_acquire_global_lock (); - acpi_aml_exit_interpreter (); + acpi_ex_exit_interpreter (); return (status); } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_release_global_lock * @@ -613,6 +653,16 @@ acpi_release_global_lock ( void) { + ACPI_STATUS status; + + + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + acpi_ev_release_global_lock (); return (AE_OK); } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/events/evxfevnt.c linux/drivers/acpi/events/evxfevnt.c --- v2.4.5/linux/drivers/acpi/events/evxfevnt.c Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/events/evxfevnt.c Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: evxfevnt - External Interfaces, ACPI event disable/enable - * $Revision: 28 $ + * $Revision: 33 $ * *****************************************************************************/ @@ -31,11 +31,11 @@ #include "amlcode.h" #include "acinterp.h" -#define _COMPONENT EVENT_HANDLING +#define _COMPONENT ACPI_EVENTS MODULE_NAME ("evxfevnt") -/************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_enable * @@ -45,7 +45,7 @@ * * DESCRIPTION: Transfers the system into ACPI mode. * - *************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_enable (void) @@ -76,7 +76,7 @@ } -/************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_disable * @@ -87,7 +87,7 @@ * DESCRIPTION: Returns the system to original ACPI/legacy mode, and * uninstalls the SCI interrupt handler. * - *************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_disable (void) @@ -95,6 +95,13 @@ ACPI_STATUS status; + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + /* Restore original mode */ status = acpi_hw_set_mode (acpi_gbl_original_mode); @@ -111,7 +118,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_enable_event * @@ -133,17 +140,22 @@ u32 register_id; + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + /* The Type must be either Fixed Acpi_event or GPE */ - switch (type) - { + switch (type) { case ACPI_EVENT_FIXED: /* Decode the Fixed Acpi_event */ - switch (event) - { + switch (event) { case ACPI_EVENT_PMTIMER: register_id = TMR_EN; break; @@ -177,7 +189,7 @@ acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, register_id, 1); if (1 != acpi_hw_register_bit_access(ACPI_READ, ACPI_MTX_LOCK, register_id)) { - return (AE_ERROR); + return (AE_NO_HARDWARE_RESPONSE); } break; @@ -187,9 +199,8 @@ /* Ensure that we have a valid GPE number */ - if ((event >= NUM_GPE) || - (acpi_gbl_gpe_valid[event] == ACPI_GPE_INVALID)) - { + if ((event > ACPI_GPE_MAX) || + (acpi_gbl_gpe_valid[event] == ACPI_GPE_INVALID)) { return (AE_BAD_PARAMETER); } @@ -210,7 +221,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_disable_event * @@ -232,17 +243,22 @@ u32 register_id; + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + /* The Type must be either Fixed Acpi_event or GPE */ - switch (type) - { + switch (type) { case ACPI_EVENT_FIXED: /* Decode the Fixed Acpi_event */ - switch (event) - { + switch (event) { case ACPI_EVENT_PMTIMER: register_id = TMR_EN; break; @@ -276,7 +292,7 @@ acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, register_id, 0); if (0 != acpi_hw_register_bit_access(ACPI_READ, ACPI_MTX_LOCK, register_id)) { - return (AE_ERROR); + return (AE_NO_HARDWARE_RESPONSE); } break; @@ -286,9 +302,8 @@ /* Ensure that we have a valid GPE number */ - if ((event >= NUM_GPE) || - (acpi_gbl_gpe_valid[event] == ACPI_GPE_INVALID)) - { + if ((event > ACPI_GPE_MAX) || + (acpi_gbl_gpe_valid[event] == ACPI_GPE_INVALID)) { return (AE_BAD_PARAMETER); } @@ -306,7 +321,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_clear_event * @@ -328,17 +343,22 @@ u32 register_id; + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + /* The Type must be either Fixed Acpi_event or GPE */ - switch (type) - { + switch (type) { case ACPI_EVENT_FIXED: /* Decode the Fixed Acpi_event */ - switch (event) - { + switch (event) { case ACPI_EVENT_PMTIMER: register_id = TMR_STS; break; @@ -377,9 +397,8 @@ /* Ensure that we have a valid GPE number */ - if ((event >= NUM_GPE) || - (acpi_gbl_gpe_valid[event] == ACPI_GPE_INVALID)) - { + if ((event > ACPI_GPE_MAX) || + (acpi_gbl_gpe_valid[event] == ACPI_GPE_INVALID)) { return (AE_BAD_PARAMETER); } @@ -397,7 +416,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_get_event_status * @@ -423,6 +442,13 @@ u32 register_id; + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + if (!event_status) { return (AE_BAD_PARAMETER); } @@ -430,15 +456,13 @@ /* The Type must be either Fixed Acpi_event or GPE */ - switch (type) - { + switch (type) { case ACPI_EVENT_FIXED: /* Decode the Fixed Acpi_event */ - switch (event) - { + switch (event) { case ACPI_EVENT_PMTIMER: register_id = TMR_STS; break; @@ -474,9 +498,8 @@ /* Ensure that we have a valid GPE number */ - if ((event >= NUM_GPE) || - (acpi_gbl_gpe_valid[event] == ACPI_GPE_INVALID)) - { + if ((event > ACPI_GPE_MAX) || + (acpi_gbl_gpe_valid[event] == ACPI_GPE_INVALID)) { return (AE_BAD_PARAMETER); } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/events/evxfregn.c linux/drivers/acpi/events/evxfregn.c --- v2.4.5/linux/drivers/acpi/events/evxfregn.c Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/events/evxfregn.c Wed Jun 20 17:47:40 2001 @@ -2,7 +2,7 @@ * * Module Name: evxfregn - External Interfaces, ACPI Operation Regions and * Address Spaces. - * $Revision: 27 $ + * $Revision: 34 $ * *****************************************************************************/ @@ -32,11 +32,11 @@ #include "amlcode.h" #include "acinterp.h" -#define _COMPONENT EVENT_HANDLING +#define _COMPONENT ACPI_EVENTS MODULE_NAME ("evxfregn") -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_install_address_space_handler * @@ -55,29 +55,35 @@ ACPI_STATUS acpi_install_address_space_handler ( ACPI_HANDLE device, - ACPI_ADDRESS_SPACE_TYPE space_id, - ADDRESS_SPACE_HANDLER handler, - ADDRESS_SPACE_SETUP setup, + ACPI_ADR_SPACE_TYPE space_id, + ACPI_ADR_SPACE_HANDLER handler, + ACPI_ADR_SPACE_SETUP setup, void *context) { ACPI_OPERAND_OBJECT *obj_desc; ACPI_OPERAND_OBJECT *handler_obj; ACPI_NAMESPACE_NODE *node; ACPI_STATUS status = AE_OK; - OBJECT_TYPE_INTERNAL type; + ACPI_OBJECT_TYPE8 type; u16 flags = 0; + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + /* Parameter validation */ if ((!device) || ((!handler) && (handler != ACPI_DEFAULT_HANDLER)) || - (space_id > ACPI_MAX_ADDRESS_SPACE)) - { + (space_id > ACPI_MAX_ADDRESS_SPACE)) { return (AE_BAD_PARAMETER); } - acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); /* Convert and validate the device handle */ @@ -96,8 +102,7 @@ if ((node->type != ACPI_TYPE_DEVICE) && (node->type != ACPI_TYPE_PROCESSOR) && (node->type != ACPI_TYPE_THERMAL) && - (node != acpi_gbl_root_node)) - { + (node != acpi_gbl_root_node)) { status = AE_BAD_PARAMETER; goto unlock_and_exit; } @@ -105,20 +110,19 @@ if (handler == ACPI_DEFAULT_HANDLER) { flags = ADDR_HANDLER_DEFAULT_INSTALLED; - switch (space_id) - { - case ADDRESS_SPACE_SYSTEM_MEMORY: - handler = acpi_aml_system_memory_space_handler; + switch (space_id) { + case ACPI_ADR_SPACE_SYSTEM_MEMORY: + handler = acpi_ex_system_memory_space_handler; setup = acpi_ev_system_memory_region_setup; break; - case ADDRESS_SPACE_SYSTEM_IO: - handler = acpi_aml_system_io_space_handler; + case ACPI_ADR_SPACE_SYSTEM_IO: + handler = acpi_ex_system_io_space_handler; setup = acpi_ev_io_space_region_setup; break; - case ADDRESS_SPACE_PCI_CONFIG: - handler = acpi_aml_pci_config_space_handler; + case ACPI_ADR_SPACE_PCI_CONFIG: + handler = acpi_ex_pci_config_space_handler; setup = acpi_ev_pci_config_region_setup; break; @@ -140,7 +144,7 @@ * Check for an existing internal object */ - obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) node); + obj_desc = acpi_ns_get_attached_object (node); if (obj_desc) { /* * The object exists. @@ -178,7 +182,7 @@ type = node->type; } - obj_desc = acpi_cm_create_internal_object (type); + obj_desc = acpi_ut_create_internal_object (type); if (!obj_desc) { status = AE_NO_MEMORY; goto unlock_and_exit; @@ -192,7 +196,7 @@ status = acpi_ns_attach_object (node, obj_desc, (u8) type); if (ACPI_FAILURE (status)) { - acpi_cm_remove_reference (obj_desc); + acpi_ut_remove_reference (obj_desc); goto unlock_and_exit; } } @@ -204,7 +208,7 @@ * So, we just allocate the object for the handler and link it * into the list. */ - handler_obj = acpi_cm_create_internal_object (INTERNAL_TYPE_ADDRESS_HANDLER); + handler_obj = acpi_ut_create_internal_object (INTERNAL_TYPE_ADDRESS_HANDLER); if (!handler_obj) { status = AE_NO_MEMORY; goto unlock_and_exit; @@ -247,12 +251,12 @@ unlock_and_exit: - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return (status); } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_remove_address_space_handler * @@ -268,8 +272,8 @@ ACPI_STATUS acpi_remove_address_space_handler ( ACPI_HANDLE device, - ACPI_ADDRESS_SPACE_TYPE space_id, - ADDRESS_SPACE_HANDLER handler) + ACPI_ADR_SPACE_TYPE space_id, + ACPI_ADR_SPACE_HANDLER handler) { ACPI_OPERAND_OBJECT *obj_desc; ACPI_OPERAND_OBJECT *handler_obj; @@ -279,16 +283,22 @@ ACPI_STATUS status = AE_OK; + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + /* Parameter validation */ if ((!device) || ((!handler) && (handler != ACPI_DEFAULT_HANDLER)) || - (space_id > ACPI_MAX_ADDRESS_SPACE)) - { + (space_id > ACPI_MAX_ADDRESS_SPACE)) { return (AE_BAD_PARAMETER); } - acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); /* Convert and validate the device handle */ @@ -301,7 +311,7 @@ /* Make sure the internal object exists */ - obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) node); + obj_desc = acpi_ns_get_attached_object (node); if (!obj_desc) { /* * The object DNE. @@ -337,7 +347,7 @@ * The region is just inaccessible as indicated to * the _REG method */ - acpi_ev_disassociate_region_from_handler(region_obj, FALSE); + acpi_ev_disassociate_region_from_handler(region_obj, TRUE); /* * Walk the list, since we took the first region and it @@ -356,8 +366,8 @@ /* * Now we can delete the handler object */ - acpi_cm_remove_reference (handler_obj); - acpi_cm_remove_reference (handler_obj); + acpi_ut_remove_reference (handler_obj); + acpi_ut_remove_reference (handler_obj); goto unlock_and_exit; } @@ -377,7 +387,7 @@ unlock_and_exit: - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return (status); } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/executer/Makefile linux/drivers/acpi/executer/Makefile --- v2.4.5/linux/drivers/acpi/executer/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/executer/Makefile Wed Jun 20 17:47:40 2001 @@ -0,0 +1,12 @@ +# +# Makefile for all Linux ACPI interpreter subdirectories +# EXCEPT for the ospm directory +# + +O_TARGET := $(notdir $(CURDIR)).o + +obj-$(CONFIG_ACPI) := $(patsubst %.c,%.o,$(wildcard *.c)) + +EXTRA_CFLAGS += $(ACPI_CFLAGS) + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/executer/exconfig.c linux/drivers/acpi/executer/exconfig.c --- v2.4.5/linux/drivers/acpi/executer/exconfig.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/executer/exconfig.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,304 @@ +/****************************************************************************** + * + * Module Name: exconfig - Namespace reconfiguration (Load/Unload opcodes) + * $Revision: 34 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "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 + MODULE_NAME ("exconfig") + + +/***************************************************************************** + * + * FUNCTION: Acpi_ex_load_table_op + * + * PARAMETERS: Rgn_desc - Op region where the table will be obtained + * Ddb_handle - Where a handle to the table will be returned + * + * RETURN: Status + * + * DESCRIPTION: Load an ACPI table + * + ****************************************************************************/ + +static ACPI_STATUS +acpi_ex_load_table_op ( + ACPI_OPERAND_OBJECT *rgn_desc, + ACPI_HANDLE *ddb_handle) +{ + ACPI_STATUS status; + ACPI_OPERAND_OBJECT *table_desc = NULL; + u8 *table_ptr; + u8 *table_data_ptr; + ACPI_TABLE_HEADER table_header; + ACPI_TABLE_DESC table_info; + u32 i; + + + /* TBD: [Unhandled] Object can be either a field or an opregion */ + + + /* Get the table header */ + + table_header.length = 0; + for (i = 0; i < sizeof (ACPI_TABLE_HEADER); i++) { + status = acpi_ev_address_space_dispatch (rgn_desc, ACPI_READ_ADR_SPACE, + (ACPI_PHYSICAL_ADDRESS) i, 8, + (u32 *) ((u8 *) &table_header + i)); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + /* Allocate a buffer for the entire table */ + + table_ptr = acpi_ut_allocate (table_header.length); + if (!table_ptr) { + return (AE_NO_MEMORY); + } + + /* Copy the header to the buffer */ + + MEMCPY (table_ptr, &table_header, sizeof (ACPI_TABLE_HEADER)); + table_data_ptr = table_ptr + sizeof (ACPI_TABLE_HEADER); + + + /* Get the table from the op region */ + + for (i = 0; i < table_header.length; i++) { + status = acpi_ev_address_space_dispatch (rgn_desc, ACPI_READ_ADR_SPACE, + (ACPI_PHYSICAL_ADDRESS) i, 8, + (u32 *) (table_data_ptr + i)); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + } + + + /* Table must be either an SSDT or a PSDT */ + + if ((!STRNCMP (table_header.signature, + acpi_gbl_acpi_table_data[ACPI_TABLE_PSDT].signature, + acpi_gbl_acpi_table_data[ACPI_TABLE_PSDT].sig_length)) && + (!STRNCMP (table_header.signature, + acpi_gbl_acpi_table_data[ACPI_TABLE_SSDT].signature, + acpi_gbl_acpi_table_data[ACPI_TABLE_SSDT].sig_length))) { + status = AE_BAD_SIGNATURE; + goto cleanup; + } + + /* Create an object to be the table handle */ + + table_desc = acpi_ut_create_internal_object (INTERNAL_TYPE_REFERENCE); + if (!table_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + + /* Install the new table into the local data structures */ + + table_info.pointer = (ACPI_TABLE_HEADER *) table_ptr; + table_info.length = table_header.length; + table_info.allocation = ACPI_MEM_ALLOCATED; + table_info.base_pointer = table_ptr; + + status = acpi_tb_install_table (NULL, &table_info); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + /* Add the table to the namespace */ + + /* TBD: [Restructure] - change to whatever new interface is appropriate */ +/* + Status = Acpi_load_namespace (); + if (ACPI_FAILURE (Status)) + { +*/ + /* TBD: [Errors] Unload the table on failure ? */ +/* + goto Cleanup; + } +*/ + + + /* TBD: [Investigate] we need a pointer to the table desc */ + + /* Init the table handle */ + + table_desc->reference.opcode = AML_LOAD_OP; + table_desc->reference.object = table_info.installed_desc; + + *ddb_handle = table_desc; + + return (status); + + +cleanup: + + acpi_ut_free (table_desc); + acpi_ut_free (table_ptr); + return (status); + +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ex_unload_table + * + * PARAMETERS: Ddb_handle - Handle to a previously loaded table + * + * RETURN: Status + * + * DESCRIPTION: Unload an ACPI table + * + ****************************************************************************/ + +static ACPI_STATUS +acpi_ex_unload_table ( + ACPI_HANDLE ddb_handle) +{ + ACPI_STATUS status = AE_NOT_IMPLEMENTED; + ACPI_OPERAND_OBJECT *table_desc = (ACPI_OPERAND_OBJECT *) ddb_handle; + ACPI_TABLE_DESC *table_info; + + + /* Validate the handle */ + /* Although the handle is partially validated in Acpi_ex_reconfiguration(), + * when it calls Acpi_ex_resolve_operands(), the handle is more completely + * validated here. + */ + + if ((!ddb_handle) || + (!VALID_DESCRIPTOR_TYPE (ddb_handle, ACPI_DESC_TYPE_INTERNAL)) || + (((ACPI_OPERAND_OBJECT *)ddb_handle)->common.type != + INTERNAL_TYPE_REFERENCE)) { + return (AE_BAD_PARAMETER); + } + + + /* Get the actual table descriptor from the Ddb_handle */ + + table_info = (ACPI_TABLE_DESC *) table_desc->reference.object; + + /* + * 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 (status); + } + + /* Delete the table itself */ + + acpi_tb_uninstall_table (table_info->installed_desc); + + /* Delete the table descriptor (Ddb_handle) */ + + acpi_ut_remove_reference (table_desc); + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ex_reconfiguration + * + * PARAMETERS: Opcode - The opcode to be executed + * Walk_state - Current state of the parse tree walk + * + * RETURN: Status + * + * DESCRIPTION: Reconfiguration opcodes such as LOAD and UNLOAD + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ex_reconfiguration ( + u16 opcode, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status; + ACPI_OPERAND_OBJECT *region_desc = NULL; + ACPI_HANDLE *ddb_handle; + + + /* Resolve the operands */ + + status = acpi_ex_resolve_operands (opcode, WALK_OPERANDS, walk_state); + /* Get the table handle, common for both opcodes */ + + status |= acpi_ds_obj_stack_pop_object ((ACPI_OPERAND_OBJECT **) &ddb_handle, + walk_state); + + switch (opcode) { + + case AML_LOAD_OP: + + /* Get the region or field descriptor */ + + status |= acpi_ds_obj_stack_pop_object (®ion_desc, walk_state); + if (ACPI_FAILURE (status)) { + acpi_ut_remove_reference (region_desc); + return (status); + } + + status = acpi_ex_load_table_op (region_desc, ddb_handle); + break; + + + case AML_UNLOAD_OP: + + if (ACPI_FAILURE (status)) { + return (status); + } + + status = acpi_ex_unload_table (ddb_handle); + break; + + + default: + + status = AE_AML_BAD_OPCODE; + break; + } + + + return (status); +} + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/executer/exconvrt.c linux/drivers/acpi/executer/exconvrt.c --- v2.4.5/linux/drivers/acpi/executer/exconvrt.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/executer/exconvrt.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,518 @@ +/****************************************************************************** + * + * Module Name: exconvrt - Object conversion routines + * $Revision: 13 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acparser.h" +#include "acnamesp.h" +#include "acinterp.h" +#include "acevents.h" +#include "amlcode.h" +#include "acdispat.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("exconvrt") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_convert_to_integer + * + * PARAMETERS: *Obj_desc - Object to be converted. Must be an + * Integer, Buffer, or String + * Walk_state - Current method state + * + * RETURN: Status + * + * DESCRIPTION: Convert an ACPI Object to an integer. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_convert_to_integer ( + ACPI_OPERAND_OBJECT **obj_desc, + ACPI_WALK_STATE *walk_state) +{ + u32 i; + ACPI_OPERAND_OBJECT *ret_desc; + u32 count; + char *pointer; + ACPI_INTEGER result; + u32 integer_size = sizeof (ACPI_INTEGER); + + + switch ((*obj_desc)->common.type) { + case ACPI_TYPE_INTEGER: + return (AE_OK); + + case ACPI_TYPE_STRING: + pointer = (*obj_desc)->string.pointer; + count = (*obj_desc)->string.length; + break; + + case ACPI_TYPE_BUFFER: + pointer = (char *) (*obj_desc)->buffer.pointer; + count = (*obj_desc)->buffer.length; + break; + + default: + return (AE_TYPE); + } + + /* + * Create a new integer + */ + ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); + if (!ret_desc) { + return (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. + * + * There are two terminating conditions for the loop: + * 1) The size of an integer has been reached, or + * 2) The end of the buffer or string has been reached + */ + result = 0; + + /* Transfer no more than an integer's worth of data */ + + if (count > integer_size) { + count = integer_size; + } + + /* + * String conversion is different than Buffer conversion + */ + switch ((*obj_desc)->common.type) { + case ACPI_TYPE_STRING: + + /* TBD: Need to use 64-bit STRTOUL */ + + /* + * Convert string to an integer + * String must be hexadecimal as per the ACPI specification + */ + + result = STRTOUL (pointer, NULL, 16); + break; + + + case ACPI_TYPE_BUFFER: + + /* + * Buffer conversion - we simply grab enough raw data from the + * buffer to fill an integer + */ + for (i = 0; i < count; i++) { + /* + * Get next byte and shift it into the Result. + * Little endian is used, meaning that the first byte of the buffer + * is the LSB of the integer + */ + result |= (((ACPI_INTEGER) pointer[i]) << (i * 8)); + } + + break; + } + + /* Save the Result, delete original descriptor, store new descriptor */ + + ret_desc->integer.value = result; + + if (walk_state->opcode != AML_STORE_OP) { + acpi_ut_remove_reference (*obj_desc); + } + + *obj_desc = ret_desc; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_convert_to_buffer + * + * PARAMETERS: *Obj_desc - Object to be converted. Must be an + * Integer, Buffer, or String + * Walk_state - Current method state + * + * RETURN: Status + * + * DESCRIPTION: Convert an ACPI Object to an Buffer + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_convert_to_buffer ( + ACPI_OPERAND_OBJECT **obj_desc, + ACPI_WALK_STATE *walk_state) +{ + ACPI_OPERAND_OBJECT *ret_desc; + u32 i; + u32 integer_size = sizeof (ACPI_INTEGER); + u8 *new_buf; + + + switch ((*obj_desc)->common.type) { + case ACPI_TYPE_INTEGER: + + /* + * Create a new Buffer + */ + ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); + if (!ret_desc) { + return (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); + } + + /* Need enough space for one integers */ + + ret_desc->buffer.length = integer_size; + new_buf = acpi_ut_callocate (integer_size); + if (!new_buf) { + REPORT_ERROR + (("Ex_dyadic2_r/Concat_op: Buffer allocation failure\n")); + acpi_ut_remove_reference (ret_desc); + return (AE_NO_MEMORY); + } + + /* Copy the integer to the buffer */ + + for (i = 0; i < integer_size; i++) { + new_buf[i] = (u8) ((*obj_desc)->integer.value >> (i * 8)); + } + ret_desc->buffer.pointer = new_buf; + + /* Return the new buffer descriptor */ + + if (walk_state->opcode != AML_STORE_OP) { + acpi_ut_remove_reference (*obj_desc); + } + *obj_desc = ret_desc; + break; + + + case ACPI_TYPE_STRING: + break; + + + case ACPI_TYPE_BUFFER: + break; + + + default: + return (AE_TYPE); + break; + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_convert_to_string + * + * PARAMETERS: *Obj_desc - Object to be converted. Must be an + * Integer, Buffer, or String + * Walk_state - Current method state + * + * RETURN: Status + * + * DESCRIPTION: Convert an ACPI Object to a string + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_convert_to_string ( + ACPI_OPERAND_OBJECT **obj_desc, + ACPI_WALK_STATE *walk_state) +{ + ACPI_OPERAND_OBJECT *ret_desc; + u32 i; + u32 index; + u32 integer_size = sizeof (ACPI_INTEGER); + u8 *new_buf; + u8 *pointer; + + + switch ((*obj_desc)->common.type) { + case ACPI_TYPE_INTEGER: + + /* + * Create a new String + */ + ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_STRING); + if (!ret_desc) { + return (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); + } + + /* Need enough space for one ASCII integer plus null terminator */ + + ret_desc->string.length = (integer_size * 2) + 1; + new_buf = acpi_ut_callocate (ret_desc->string.length); + if (!new_buf) { + REPORT_ERROR + (("Ex_convert_to_string: Buffer allocation failure\n")); + acpi_ut_remove_reference (ret_desc); + return (AE_NO_MEMORY); + } + + /* Copy the integer to the buffer */ + + for (i = 0; i < (integer_size * 2); i++) { + new_buf[i] = acpi_gbl_hex_to_ascii [((*obj_desc)->integer.value >> (i * 4)) & 0xF]; + } + + /* Null terminate */ + + new_buf [i] = 0; + ret_desc->buffer.pointer = new_buf; + + /* Return the new buffer descriptor */ + + if (walk_state->opcode != AML_STORE_OP) { + acpi_ut_remove_reference (*obj_desc); + } + *obj_desc = ret_desc; + + return (AE_OK); + + + case ACPI_TYPE_BUFFER: + + if (((*obj_desc)->buffer.length * 3) > ACPI_MAX_STRING_CONVERSION) { + return (AE_AML_STRING_LIMIT); + } + + /* + * Create a new String + */ + ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_STRING); + if (!ret_desc) { + return (AE_NO_MEMORY); + } + + /* Need enough space for one ASCII integer plus null terminator */ + + ret_desc->string.length = (*obj_desc)->buffer.length * 3; + new_buf = acpi_ut_callocate (ret_desc->string.length + 1); + if (!new_buf) { + REPORT_ERROR + (("Ex_convert_to_string: Buffer allocation failure\n")); + acpi_ut_remove_reference (ret_desc); + return (AE_NO_MEMORY); + } + + /* + * Convert each byte of the buffer to two ASCII characters plus a space. + */ + pointer = (*obj_desc)->buffer.pointer; + index = 0; + for (i = 0; i < (*obj_desc)->buffer.length; i++) { + new_buf[index + 0] = acpi_gbl_hex_to_ascii [pointer[i] & 0x0F]; + new_buf[index + 1] = acpi_gbl_hex_to_ascii [(pointer[i] >> 4) & 0x0F]; + new_buf[index + 2] = ' '; + index += 3; + } + + /* Null terminate */ + + new_buf [index] = 0; + ret_desc->buffer.pointer = new_buf; + + /* Return the new buffer descriptor */ + + if (walk_state->opcode != AML_STORE_OP) { + acpi_ut_remove_reference (*obj_desc); + } + *obj_desc = ret_desc; + break; + + + case ACPI_TYPE_STRING: + break; + + + default: + return (AE_TYPE); + break; + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_convert_to_target_type + * + * PARAMETERS: *Obj_desc - Object to be converted. + * Walk_state - Current method state + * + * RETURN: Status + * + * DESCRIPTION: + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_convert_to_target_type ( + ACPI_OBJECT_TYPE8 destination_type, + ACPI_OPERAND_OBJECT **obj_desc, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status = AE_OK; + + + /* + * If required by the target, + * perform implicit conversion on the source before we store it. + */ + + switch (GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args)) { + case ARGI_SIMPLE_TARGET: + case ARGI_FIXED_TARGET: + case ARGI_INTEGER_REF: /* Handles Increment, Decrement cases */ + + switch (destination_type) { + case INTERNAL_TYPE_REGION_FIELD: + /* + * Named field can always handle conversions + */ + break; + + default: + /* No conversion allowed for these types */ + + if (destination_type != (*obj_desc)->common.type) { + status = AE_TYPE; + } + } + break; + + + case ARGI_TARGETREF: + + switch (destination_type) { + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_BUFFER_FIELD: + case INTERNAL_TYPE_BANK_FIELD: + case INTERNAL_TYPE_INDEX_FIELD: + /* + * These types require an Integer operand. We can convert + * a Buffer or a String to an Integer if necessary. + */ + status = acpi_ex_convert_to_integer (obj_desc, walk_state); + break; + + + case ACPI_TYPE_STRING: + + /* + * The operand must be a String. We can convert an + * Integer or Buffer if necessary + */ + status = acpi_ex_convert_to_string (obj_desc, walk_state); + break; + + + case ACPI_TYPE_BUFFER: + + /* + * The operand must be a String. We can convert an + * Integer or Buffer if necessary + */ + status = acpi_ex_convert_to_buffer (obj_desc, walk_state); + break; + } + break; + + + case ARGI_REFERENCE: + /* + * Create_xxxx_field cases - we are storing the field object into the name + */ + break; + + + default: + status = AE_AML_INTERNAL; + } + + + /* + * Source-to-Target conversion semantics: + * + * If conversion to the target type cannot be performed, then simply + * overwrite the target with the new object and type. + */ + if (status == AE_TYPE) { + status = AE_OK; + } + + return (status); +} + + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/executer/excreate.c linux/drivers/acpi/executer/excreate.c --- v2.4.5/linux/drivers/acpi/executer/excreate.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/executer/excreate.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,706 @@ +/****************************************************************************** + * + * Module Name: excreate - Named object creation + * $Revision: 63 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acparser.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "acevents.h" +#include "acdispat.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("excreate") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_create_buffer_field + * + * PARAMETERS: Opcode - The opcode to be executed + * Operands - List of operands for the opcode + * + * RETURN: Status + * + * DESCRIPTION: Execute Create_field operators: Create_bit_field_op, + * Create_byte_field_op, Create_word_field_op, Create_dWord_field_op, + * Create_field_op (which define fields in buffers) + * + * ALLOCATION: Deletes Create_field_op's count operand descriptor + * + * + * ACPI SPECIFICATION REFERENCES: + * Def_create_bit_field := Create_bit_field_op Src_buf Bit_idx Name_string + * Def_create_byte_field := Create_byte_field_op Src_buf Byte_idx Name_string + * Def_create_dWord_field := Create_dWord_field_op Src_buf Byte_idx Name_string + * Def_create_field := Create_field_op Src_buf Bit_idx Num_bits Name_string + * Def_create_word_field := Create_word_field_op Src_buf Byte_idx Name_string + * Bit_index := Term_arg=>Integer + * Byte_index := Term_arg=>Integer + * Num_bits := Term_arg=>Integer + * Source_buff := Term_arg=>Buffer + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_create_buffer_field ( + u8 *aml_ptr, + u32 aml_length, + ACPI_NAMESPACE_NODE *node, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status; + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_OPERAND_OBJECT *tmp_desc; + + + /* Create the descriptor */ + + obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER_FIELD); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + + /* + * Allocate a method object for this field unit + */ + + obj_desc->buffer_field.extra = acpi_ut_create_internal_object ( + INTERNAL_TYPE_EXTRA); + if (!obj_desc->buffer_field.extra) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* + * Remember location in AML stream of the field unit + * opcode and operands -- since the buffer and index + * operands must be evaluated. + */ + + obj_desc->buffer_field.extra->extra.pcode = aml_ptr; + obj_desc->buffer_field.extra->extra.pcode_length = aml_length; + obj_desc->buffer_field.node = node; + + + /* + * This operation is supposed to cause the destination Name to refer + * to the defined Buffer_field -- it must not store the constructed + * Buffer_field object (or its current value) in some location that the + * Name may already be pointing to. So, if the Name currently contains + * a reference which would cause Acpi_ex_store() to perform an indirect + * store rather than setting the value of the Name itself, clobber that + * reference before calling Acpi_ex_store(). + */ + + /* Type of Name's existing value */ + + switch (acpi_ns_get_type (node)) { + + case ACPI_TYPE_BUFFER_FIELD: + case INTERNAL_TYPE_ALIAS: + case INTERNAL_TYPE_REGION_FIELD: + case INTERNAL_TYPE_BANK_FIELD: + case INTERNAL_TYPE_INDEX_FIELD: + + tmp_desc = acpi_ns_get_attached_object (node); + if (tmp_desc) { + /* + * There is an existing object here; delete it and zero out the + * object field within the Node + */ + + acpi_ut_remove_reference (tmp_desc); + acpi_ns_attach_object ((ACPI_NAMESPACE_NODE *) node, NULL, + ACPI_TYPE_ANY); + } + + /* Set the type to ANY (or the store below will fail) */ + + ((ACPI_NAMESPACE_NODE *) node)->type = ACPI_TYPE_ANY; + + break; + + + default: + + break; + } + + + /* Store constructed field descriptor in result location */ + + status = acpi_ex_store (obj_desc, (ACPI_OPERAND_OBJECT *) node, + walk_state); + + /* + * If the field descriptor was not physically stored (or if a failure + * above), we must delete it + */ + if (obj_desc->common.reference_count <= 1) { + acpi_ut_remove_reference (obj_desc); + } + + + return (AE_OK); + + +cleanup: + + /* Delete region object and method subobject */ + + if (obj_desc) { + /* Remove deletes both objects! */ + + acpi_ut_remove_reference (obj_desc); + obj_desc = NULL; + } + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ex_create_alias + * + * PARAMETERS: Walk_state - Current state, contains List of + * operands for the opcode + * + * RETURN: Status + * + * DESCRIPTION: Create a new named alias + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ex_create_alias ( + ACPI_WALK_STATE *walk_state) +{ + ACPI_NAMESPACE_NODE *source_node; + ACPI_NAMESPACE_NODE *alias_node; + ACPI_STATUS status; + + + /* Get the source/alias operands (both namespace nodes) */ + + status = acpi_ds_obj_stack_pop_object ((ACPI_OPERAND_OBJECT **) &source_node, + walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * Don't pop it, it gets removed in the calling routine + */ + alias_node = acpi_ds_obj_stack_get_value (0, walk_state); + + /* Add an additional reference to the object */ + + acpi_ut_add_reference (source_node->object); + + /* + * Attach the original source Node to the new Alias Node. + */ + status = acpi_ns_attach_object (alias_node, source_node->object, + source_node->type); + + + /* + * The new alias assumes the type of the source, but it points + * to the same object. The reference count of the object has two + * additional references to prevent deletion out from under either the + * source or the alias Node + */ + + /* Since both operands are Nodes, we don't need to delete them */ + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ex_create_event + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Create a new event object + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ex_create_event ( + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status; + ACPI_OPERAND_OBJECT *obj_desc; + + + BREAKPOINT3; + + obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_EVENT); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Create the actual OS semaphore */ + + /* TBD: [Investigate] should be created with 0 or 1 units? */ + + status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT, 1, + &obj_desc->event.semaphore); + if (ACPI_FAILURE (status)) { + acpi_ut_remove_reference (obj_desc); + goto cleanup; + } + + /* Attach object to the Node */ + + status = acpi_ns_attach_object (acpi_ds_obj_stack_get_value (0, walk_state), + obj_desc, (u8) ACPI_TYPE_EVENT); + if (ACPI_FAILURE (status)) { + acpi_os_delete_semaphore (obj_desc->event.semaphore); + acpi_ut_remove_reference (obj_desc); + goto cleanup; + } + + +cleanup: + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ex_create_mutex + * + * PARAMETERS: Interpreter_mode - Current running mode (load1/Load2/Exec) + * Operands - List of operands for the opcode + * + * RETURN: Status + * + * DESCRIPTION: Create a new mutex object + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ex_create_mutex ( + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status = AE_OK; + ACPI_OPERAND_OBJECT *sync_desc; + ACPI_OPERAND_OBJECT *obj_desc; + + + /* Get the operand */ + + status = acpi_ds_obj_stack_pop_object (&sync_desc, walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Attempt to allocate a new object */ + + obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_MUTEX); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Create the actual OS semaphore */ + + status = acpi_os_create_semaphore (1, 1, &obj_desc->mutex.semaphore); + if (ACPI_FAILURE (status)) { + acpi_ut_remove_reference (obj_desc); + goto cleanup; + } + + obj_desc->mutex.sync_level = (u8) sync_desc->integer.value; + + /* Obj_desc was on the stack top, and the name is below it */ + + status = acpi_ns_attach_object (acpi_ds_obj_stack_get_value (0, walk_state), + obj_desc, (u8) ACPI_TYPE_MUTEX); + if (ACPI_FAILURE (status)) { + acpi_os_delete_semaphore (obj_desc->mutex.semaphore); + acpi_ut_remove_reference (obj_desc); + goto cleanup; + } + + +cleanup: + + /* Always delete the operand */ + + acpi_ut_remove_reference (sync_desc); + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ex_create_region + * + * PARAMETERS: Aml_ptr - Pointer to the region declaration AML + * Aml_length - Max length of the declaration AML + * Operands - List of operands for the opcode + * Interpreter_mode - Load1/Load2/Execute + * + * RETURN: Status + * + * DESCRIPTION: Create a new operation region object + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ex_create_region ( + u8 *aml_ptr, + u32 aml_length, + u8 region_space, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status; + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_NAMESPACE_NODE *node; + + + /* + * Space ID must be one of the predefined IDs, or in the user-defined + * range + */ + if ((region_space >= NUM_REGION_TYPES) && + (region_space < USER_REGION_BEGIN)) { + REPORT_ERROR (("Invalid Address_space type %X\n", region_space)); + return (AE_AML_INVALID_SPACE_ID); + } + + + /* Get the Node from the object stack */ + + node = (ACPI_NAMESPACE_NODE *) acpi_ds_obj_stack_get_value (0, walk_state); + + /* Create the region descriptor */ + + obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_REGION); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* + * Allocate a method object for this region. + */ + + obj_desc->region.extra = acpi_ut_create_internal_object ( + INTERNAL_TYPE_EXTRA); + if (!obj_desc->region.extra) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* + * Remember location in AML stream of address & length + * operands since they need to be evaluated at run time. + */ + + obj_desc->region.extra->extra.pcode = aml_ptr; + obj_desc->region.extra->extra.pcode_length = aml_length; + + /* Init the region from the operands */ + + obj_desc->region.space_id = region_space; + obj_desc->region.address = 0; + obj_desc->region.length = 0; + + + /* Install the new region object in the parent Node */ + + obj_desc->region.node = node; + + status = acpi_ns_attach_object (node, obj_desc, + (u8) ACPI_TYPE_REGION); + + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + /* + * If we have a valid region, initialize it + * Namespace is NOT locked at this point. + */ + + status = acpi_ev_initialize_region (obj_desc, FALSE); + + if (ACPI_FAILURE (status)) { + /* + * If AE_NOT_EXIST is returned, it is not fatal + * because many regions get created before a handler + * is installed for said region. + */ + if (AE_NOT_EXIST == status) { + status = AE_OK; + } + } + +cleanup: + + if (ACPI_FAILURE (status)) { + /* Delete region object and method subobject */ + + if (obj_desc) { + /* Remove deletes both objects! */ + + acpi_ut_remove_reference (obj_desc); + obj_desc = NULL; + } + } + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ex_create_processor + * + * PARAMETERS: Op - Op containing the Processor definition and + * args + * Processor_node - Parent Node for the processor object + * + * RETURN: Status + * + * DESCRIPTION: Create a new processor object and populate the fields + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ex_create_processor ( + ACPI_PARSE_OBJECT *op, + ACPI_NAMESPACE_NODE *processor_node) +{ + ACPI_STATUS status; + ACPI_PARSE_OBJECT *arg; + ACPI_OPERAND_OBJECT *obj_desc; + + + obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_PROCESSOR); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + /* Install the new processor object in the parent Node */ + + status = acpi_ns_attach_object (processor_node, obj_desc, + (u8) ACPI_TYPE_PROCESSOR); + if (ACPI_FAILURE (status)) { + acpi_ut_delete_object_desc (obj_desc); + return (status); + } + + /* Get first arg and verify existence */ + + arg = op->value.arg; + if (!arg) { + return (AE_AML_NO_OPERAND); + } + + /* First arg is the Processor ID */ + + obj_desc->processor.proc_id = (u8) arg->value.integer; + + /* Get second arg and verify existence */ + + arg = arg->next; + if (!arg) { + return (AE_AML_NO_OPERAND); + } + + /* Second arg is the PBlock Address */ + + obj_desc->processor.address = (ACPI_IO_ADDRESS) arg->value.integer; + + /* Get third arg and verify existence */ + + arg = arg->next; + if (!arg) { + return (AE_AML_NO_OPERAND); + } + + /* Third arg is the PBlock Length */ + + obj_desc->processor.length = (u8) arg->value.integer; + return (AE_OK); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ex_create_power_resource + * + * PARAMETERS: Op - Op containing the Power_resource definition + * and args + * Power_node - Parent Node for the power object + * + * RETURN: Status + * + * DESCRIPTION: Create a new Power_resource object and populate the fields + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ex_create_power_resource ( + ACPI_PARSE_OBJECT *op, + ACPI_NAMESPACE_NODE *power_node) +{ + ACPI_STATUS status; + ACPI_PARSE_OBJECT *arg; + ACPI_OPERAND_OBJECT *obj_desc; + + + obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_POWER); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + /* Install the new power resource object in the parent Node */ + + status = acpi_ns_attach_object (power_node, obj_desc, + (u8) ACPI_TYPE_POWER); + if (ACPI_FAILURE (status)) { + return(status); + } + + + /* Get first arg and verify existence */ + + arg = op->value.arg; + if (!arg) { + return (AE_AML_NO_OPERAND); + } + + /* First arg is the System_level */ + + obj_desc->power_resource.system_level = (u8) arg->value.integer; + + /* Get second arg and check existence */ + + arg = arg->next; + if (!arg) { + return (AE_AML_NO_OPERAND); + } + + /* Second arg is the PBlock Address */ + + obj_desc->power_resource.resource_order = (u16) arg->value.integer; + + return (AE_OK); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ex_create_method + * + * PARAMETERS: Aml_ptr - First byte of the method's AML + * Aml_length - AML byte count for this method + * Method_flags - AML method flag byte + * Method - Method Node + * + * RETURN: Status + * + * DESCRIPTION: Create a new method object + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ex_create_method ( + u8 *aml_ptr, + u32 aml_length, + u32 method_flags, + ACPI_NAMESPACE_NODE *method) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_STATUS status; + + + /* Create a new method object */ + + obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_METHOD); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + /* Get the method's AML pointer/length from the Op */ + + obj_desc->method.pcode = aml_ptr; + obj_desc->method.pcode_length = aml_length; + + /* + * First argument is the Method Flags (contains parameter count for the + * method) + */ + + obj_desc->method.method_flags = (u8) method_flags; + obj_desc->method.param_count = (u8) (method_flags & + METHOD_FLAGS_ARG_COUNT); + + /* + * Get the concurrency count. If required, a semaphore will be + * created for this method when it is parsed. + */ + if (method_flags & METHOD_FLAGS_SERIALIZED) { + /* + * ACPI 1.0: Concurrency = 1 + * ACPI 2.0: Concurrency = (Sync_level (in method declaration) + 1) + */ + obj_desc->method.concurrency = (u8) + (((method_flags & METHOD_FLAGS_SYNCH_LEVEL) >> 4) + 1); + } + + else { + obj_desc->method.concurrency = INFINITE_CONCURRENCY; + } + + /* Attach the new object to the method Node */ + + status = acpi_ns_attach_object (method, obj_desc, (u8) ACPI_TYPE_METHOD); + if (ACPI_FAILURE (status)) { + acpi_ut_delete_object_desc (obj_desc); + } + + return (status); +} + + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/executer/exdump.c linux/drivers/acpi/executer/exdump.c --- v2.4.5/linux/drivers/acpi/executer/exdump.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/executer/exdump.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,41 @@ +/****************************************************************************** + * + * Module Name: exdump - Interpreter debug output routines + * $Revision: 114 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "actables.h" + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("exdump") + + +/* + * The following routines are used for debug output only + */ + + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/executer/exdyadic.c linux/drivers/acpi/executer/exdyadic.c --- v2.4.5/linux/drivers/acpi/executer/exdyadic.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/executer/exdyadic.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,874 @@ +/****************************************************************************** + * + * Module Name: exdyadic - ACPI AML (p-code) execution for dyadic operators + * $Revision: 77 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acparser.h" +#include "acnamesp.h" +#include "acinterp.h" +#include "acevents.h" +#include "amlcode.h" +#include "acdispat.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("exdyadic") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_do_concatenate + * + * PARAMETERS: *Obj_desc - Object to be converted. Must be an + * Integer, Buffer, or String + * + * RETURN: Status + * + * DESCRIPTION: Concatenate two objects OF THE SAME TYPE. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_do_concatenate ( + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_OPERAND_OBJECT *obj_desc2, + ACPI_OPERAND_OBJECT **actual_ret_desc, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status; + u32 i; + ACPI_INTEGER this_integer; + ACPI_OPERAND_OBJECT *ret_desc; + NATIVE_CHAR *new_buf; + u32 integer_size = sizeof (ACPI_INTEGER); + + + /* + * There are three cases to handle: + * 1) Two Integers concatenated to produce a buffer + * 2) Two Strings concatenated to produce a string + * 3) Two Buffers concatenated to produce a buffer + */ + 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. + * 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 */ + + ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); + if (!ret_desc) { + return (AE_NO_MEMORY); + } + + /* Need enough space for two integers */ + + ret_desc->buffer.length = integer_size * 2; + new_buf = acpi_ut_callocate (ret_desc->buffer.length); + if (!new_buf) { + REPORT_ERROR + (("Ex_do_concatenate: Buffer allocation failure\n")); + status = AE_NO_MEMORY; + goto cleanup; + } + + ret_desc->buffer.pointer = (u8 *) new_buf; + + /* Convert the first integer */ + + this_integer = obj_desc->integer.value; + for (i = 0; i < integer_size; i++) { + new_buf[i] = (u8) 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; + this_integer >>= 8; + } + + break; + + + case ACPI_TYPE_STRING: + + ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_STRING); + if (!ret_desc) { + return (AE_NO_MEMORY); + } + + /* Operand1 is string */ + + new_buf = acpi_ut_allocate (obj_desc->string.length + + obj_desc2->string.length + 1); + if (!new_buf) { + REPORT_ERROR + (("Ex_do_concatenate: String allocation failure\n")); + status = AE_NO_MEMORY; + goto cleanup; + } + + STRCPY (new_buf, obj_desc->string.pointer); + STRCPY (new_buf + obj_desc->string.length, + obj_desc2->string.pointer); + + /* Point the return object to the new string */ + + ret_desc->string.pointer = new_buf; + ret_desc->string.length = obj_desc->string.length += + obj_desc2->string.length; + break; + + + case ACPI_TYPE_BUFFER: + + /* Operand1 is a buffer */ + + ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); + if (!ret_desc) { + return (AE_NO_MEMORY); + } + + new_buf = acpi_ut_allocate (obj_desc->buffer.length + + obj_desc2->buffer.length); + if (!new_buf) { + REPORT_ERROR + (("Ex_do_concatenate: Buffer allocation failure\n")); + status = AE_NO_MEMORY; + goto cleanup; + } + + MEMCPY (new_buf, obj_desc->buffer.pointer, + obj_desc->buffer.length); + MEMCPY (new_buf + obj_desc->buffer.length, obj_desc2->buffer.pointer, + obj_desc2->buffer.length); + + /* + * Point the return object to the new buffer + */ + + ret_desc->buffer.pointer = (u8 *) new_buf; + ret_desc->buffer.length = obj_desc->buffer.length + + obj_desc2->buffer.length; + break; + + default: + status = AE_AML_INTERNAL; + ret_desc = NULL; + } + + + *actual_ret_desc = ret_desc; + return (AE_OK); + + +cleanup: + + acpi_ut_remove_reference (ret_desc); + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_dyadic1 + * + * PARAMETERS: Opcode - The opcode to be executed + * + * RETURN: Status + * + * DESCRIPTION: Execute Type 1 dyadic operator with numeric operands: + * Notify_op + * + * ALLOCATION: Deletes both operands + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_dyadic1 ( + u16 opcode, + ACPI_WALK_STATE *walk_state) +{ + ACPI_OPERAND_OBJECT *obj_desc = NULL; + ACPI_OPERAND_OBJECT *val_desc = NULL; + ACPI_NAMESPACE_NODE *node; + ACPI_STATUS status = AE_OK; + + + /* Resolve all operands */ + + status = acpi_ex_resolve_operands (opcode, WALK_OPERANDS, walk_state); + /* Get the operands */ + + status |= acpi_ds_obj_stack_pop_object (&val_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + /* Invalid parameters on object stack */ + + goto cleanup; + } + + + /* Examine the opcode */ + + switch (opcode) { + + /* Def_notify := Notify_op Notify_object Notify_value */ + + case AML_NOTIFY_OP: + + /* The Obj_desc is actually an Node */ + + node = (ACPI_NAMESPACE_NODE *) obj_desc; + obj_desc = NULL; + + /* Object must be a device or thermal zone */ + + if (node && val_desc) { + switch (node->type) { + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_THERMAL: + + /* + * Dispatch the notify to the appropriate handler + * NOTE: the request is queued for execution after this method + * completes. The notify handlers are NOT invoked synchronously + * from this thread -- because handlers may in turn run other + * control methods. + */ + + status = acpi_ev_queue_notify_request (node, + (u32) val_desc->integer.value); + break; + + default: + status = AE_AML_OPERAND_TYPE; + break; + } + } + break; + + default: + + REPORT_ERROR (("Acpi_ex_dyadic1: Unknown dyadic opcode %X\n", opcode)); + status = AE_AML_BAD_OPCODE; + } + + +cleanup: + + /* Always delete both operands */ + + acpi_ut_remove_reference (val_desc); + acpi_ut_remove_reference (obj_desc); + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_dyadic2_r + * + * PARAMETERS: Opcode - The opcode to be executed + * + * RETURN: Status + * + * DESCRIPTION: Execute Type 2 dyadic operator with numeric operands and + * one or two result operands. + * + * ALLOCATION: Deletes one operand descriptor -- other remains on stack + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_dyadic2_r ( + u16 opcode, + ACPI_WALK_STATE *walk_state, + ACPI_OPERAND_OBJECT **return_desc) +{ + ACPI_OPERAND_OBJECT *obj_desc = NULL; + ACPI_OPERAND_OBJECT *obj_desc2 = NULL; + ACPI_OPERAND_OBJECT *res_desc = NULL; + ACPI_OPERAND_OBJECT *res_desc2 = NULL; + ACPI_OPERAND_OBJECT *ret_desc = NULL; + ACPI_OPERAND_OBJECT *ret_desc2 = NULL; + ACPI_STATUS status = AE_OK; + u32 num_operands = 3; + + + /* Resolve all operands */ + + status = acpi_ex_resolve_operands (opcode, WALK_OPERANDS, walk_state); + /* Get all operands */ + + if (AML_DIVIDE_OP == opcode) { + num_operands = 4; + status |= acpi_ds_obj_stack_pop_object (&res_desc2, walk_state); + } + + status |= acpi_ds_obj_stack_pop_object (&res_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&obj_desc2, walk_state); + status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + + /* Create an internal return object if necessary */ + + switch (opcode) { + case AML_ADD_OP: + case AML_BIT_AND_OP: + case AML_BIT_NAND_OP: + case AML_BIT_OR_OP: + case AML_BIT_NOR_OP: + case AML_BIT_XOR_OP: + case AML_DIVIDE_OP: + case AML_MULTIPLY_OP: + case AML_SHIFT_LEFT_OP: + case AML_SHIFT_RIGHT_OP: + case AML_SUBTRACT_OP: + + ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + break; + } + + + /* + * Execute the opcode + */ + + switch (opcode) { + + /* Def_add := Add_op Operand1 Operand2 Result */ + + case AML_ADD_OP: + + ret_desc->integer.value = obj_desc->integer.value + + obj_desc2->integer.value; + break; + + + /* Def_and := And_op Operand1 Operand2 Result */ + + case AML_BIT_AND_OP: + + ret_desc->integer.value = obj_desc->integer.value & + obj_desc2->integer.value; + break; + + + /* Def_nAnd := NAnd_op Operand1 Operand2 Result */ + + case AML_BIT_NAND_OP: + + ret_desc->integer.value = ~(obj_desc->integer.value & + obj_desc2->integer.value); + break; + + + /* Def_or := Or_op Operand1 Operand2 Result */ + + case AML_BIT_OR_OP: + + ret_desc->integer.value = obj_desc->integer.value | + obj_desc2->integer.value; + break; + + + /* Def_nOr := NOr_op Operand1 Operand2 Result */ + + case AML_BIT_NOR_OP: + + ret_desc->integer.value = ~(obj_desc->integer.value | + obj_desc2->integer.value); + break; + + + /* Def_xOr := XOr_op Operand1 Operand2 Result */ + + case AML_BIT_XOR_OP: + + ret_desc->integer.value = obj_desc->integer.value ^ + obj_desc2->integer.value; + break; + + + /* Def_divide := Divide_op Dividend Divisor Remainder Quotient */ + + case AML_DIVIDE_OP: + + if (!obj_desc2->integer.value) { + REPORT_ERROR + (("Ex_dyadic2_r/Divide_op: Divide by zero\n")); + + status = AE_AML_DIVIDE_BY_ZERO; + goto cleanup; + } + + ret_desc2 = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); + if (!ret_desc2) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Remainder (modulo) */ + + ret_desc->integer.value = ACPI_MODULO (obj_desc->integer.value, + obj_desc2->integer.value); + + /* Result (what we used to call the quotient) */ + + ret_desc2->integer.value = ACPI_DIVIDE (obj_desc->integer.value, + obj_desc2->integer.value); + break; + + + /* Def_multiply := Multiply_op Operand1 Operand2 Result */ + + case AML_MULTIPLY_OP: + + ret_desc->integer.value = obj_desc->integer.value * + obj_desc2->integer.value; + break; + + + /* Def_shift_left := Shift_left_op Operand Shift_count Result */ + + case AML_SHIFT_LEFT_OP: + + ret_desc->integer.value = obj_desc->integer.value << + obj_desc2->integer.value; + break; + + + /* Def_shift_right := Shift_right_op Operand Shift_count Result */ + + case AML_SHIFT_RIGHT_OP: + + ret_desc->integer.value = obj_desc->integer.value >> + obj_desc2->integer.value; + break; + + + /* Def_subtract := Subtract_op Operand1 Operand2 Result */ + + case AML_SUBTRACT_OP: + + ret_desc->integer.value = obj_desc->integer.value - + obj_desc2->integer.value; + break; + + + /* Def_concat := Concat_op Data1 Data2 Result */ + + case AML_CONCAT_OP: + + + /* + * Convert the second operand if necessary. The first operand + * determines the type of the second operand, (See the Data Types + * section of the ACPI specification.) Both object types are + * guaranteed to be either Integer/String/Buffer by the operand + * resolution mechanism above. + */ + + switch (obj_desc->common.type) { + case ACPI_TYPE_INTEGER: + status = acpi_ex_convert_to_integer (&obj_desc2, walk_state); + break; + + case ACPI_TYPE_STRING: + status = acpi_ex_convert_to_string (&obj_desc2, walk_state); + break; + + case ACPI_TYPE_BUFFER: + status = acpi_ex_convert_to_buffer (&obj_desc2, walk_state); + break; + + default: + status = AE_AML_INTERNAL; + } + + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + + /* + * Both operands are now known to be the same object type + * (Both are Integer, String, or Buffer), and we can now perform the + * concatenation. + */ + status = acpi_ex_do_concatenate (obj_desc, obj_desc2, &ret_desc, walk_state); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + break; + + + default: + + REPORT_ERROR (("Acpi_ex_dyadic2_r: Unknown dyadic opcode %X\n", + opcode)); + status = AE_AML_BAD_OPCODE; + goto cleanup; + } + + + /* + * Store the result of the operation (which is now in Obj_desc) into + * the result descriptor, or the location pointed to by the result + * descriptor (Res_desc). + */ + + status = acpi_ex_store (ret_desc, res_desc, walk_state); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + if (AML_DIVIDE_OP == opcode) { + status = acpi_ex_store (ret_desc2, res_desc2, walk_state); + + /* + * Since the remainder is not returned, remove a reference to + * the object we created earlier + */ + + acpi_ut_remove_reference (ret_desc2); + } + + +cleanup: + + /* Always delete the operands */ + + acpi_ut_remove_reference (obj_desc); + acpi_ut_remove_reference (obj_desc2); + + + /* Delete return object on error */ + + if (ACPI_FAILURE (status)) { + /* On failure, delete the result ops */ + + acpi_ut_remove_reference (res_desc); + acpi_ut_remove_reference (res_desc2); + + if (ret_desc) { + /* And delete the internal return object */ + + acpi_ut_remove_reference (ret_desc); + ret_desc = NULL; + } + } + + /* Set the return object and exit */ + + *return_desc = ret_desc; + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_dyadic2_s + * + * PARAMETERS: Opcode - The opcode to be executed + * + * RETURN: Status + * + * DESCRIPTION: Execute Type 2 dyadic synchronization operator + * + * ALLOCATION: Deletes one operand descriptor -- other remains on stack + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_dyadic2_s ( + u16 opcode, + ACPI_WALK_STATE *walk_state, + ACPI_OPERAND_OBJECT **return_desc) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_OPERAND_OBJECT *time_desc; + ACPI_OPERAND_OBJECT *ret_desc = NULL; + ACPI_STATUS status; + + + /* Resolve all operands */ + + status = acpi_ex_resolve_operands (opcode, WALK_OPERANDS, walk_state); + /* Get all operands */ + + status |= acpi_ds_obj_stack_pop_object (&time_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + /* Invalid parameters on object stack */ + + goto cleanup; + } + + + /* Create the internal return object */ + + ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Default return value is FALSE, operation did not time out */ + + ret_desc->integer.value = 0; + + + /* Examine the opcode */ + + switch (opcode) { + + /* Def_acquire := Acquire_op Mutex_object Timeout */ + + case AML_ACQUIRE_OP: + + status = acpi_ex_acquire_mutex (time_desc, obj_desc, walk_state); + break; + + + /* Def_wait := Wait_op Acpi_event_object Timeout */ + + case AML_WAIT_OP: + + status = acpi_ex_system_wait_event (time_desc, obj_desc); + break; + + + default: + + REPORT_ERROR (("Acpi_ex_dyadic2_s: Unknown dyadic synchronization opcode %X\n", opcode)); + status = AE_AML_BAD_OPCODE; + goto cleanup; + } + + + /* + * Return a boolean indicating if operation timed out + * (TRUE) or not (FALSE) + */ + + if (status == AE_TIME) { + ret_desc->integer.value = ACPI_INTEGER_MAX; /* TRUE, op timed out */ + status = AE_OK; + } + + +cleanup: + + /* Delete params */ + + acpi_ut_remove_reference (time_desc); + acpi_ut_remove_reference (obj_desc); + + /* Delete return object on error */ + + if (ACPI_FAILURE (status) && + (ret_desc)) { + acpi_ut_remove_reference (ret_desc); + ret_desc = NULL; + } + + + /* Set the return object and exit */ + + *return_desc = ret_desc; + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_dyadic2 + * + * PARAMETERS: Opcode - The opcode to be executed + * + * RETURN: Status + * + * DESCRIPTION: Execute Type 2 dyadic operator with numeric operands and + * no result operands + * + * ALLOCATION: Deletes one operand descriptor -- other remains on stack + * containing result value + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_dyadic2 ( + u16 opcode, + ACPI_WALK_STATE *walk_state, + ACPI_OPERAND_OBJECT **return_desc) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_OPERAND_OBJECT *obj_desc2; + ACPI_OPERAND_OBJECT *ret_desc = NULL; + ACPI_STATUS status; + u8 lboolean; + + + /* Resolve all operands */ + + status = acpi_ex_resolve_operands (opcode, WALK_OPERANDS, walk_state); + /* Get all operands */ + + status |= acpi_ds_obj_stack_pop_object (&obj_desc2, walk_state); + status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + /* Invalid parameters on object stack */ + + goto cleanup; + } + + + /* Create the internal return object */ + + ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* + * Execute the Opcode + */ + + lboolean = FALSE; + switch (opcode) { + + /* Def_lAnd := LAnd_op Operand1 Operand2 */ + + case AML_LAND_OP: + + lboolean = (u8) (obj_desc->integer.value && + obj_desc2->integer.value); + break; + + + /* Def_lEqual := LEqual_op Operand1 Operand2 */ + + case AML_LEQUAL_OP: + + lboolean = (u8) (obj_desc->integer.value == + obj_desc2->integer.value); + break; + + + /* Def_lGreater := LGreater_op Operand1 Operand2 */ + + case AML_LGREATER_OP: + + lboolean = (u8) (obj_desc->integer.value > + obj_desc2->integer.value); + break; + + + /* Def_lLess := LLess_op Operand1 Operand2 */ + + case AML_LLESS_OP: + + lboolean = (u8) (obj_desc->integer.value < + obj_desc2->integer.value); + break; + + + /* Def_lOr := LOr_op Operand1 Operand2 */ + + case AML_LOR_OP: + + lboolean = (u8) (obj_desc->integer.value || + obj_desc2->integer.value); + break; + + + default: + + REPORT_ERROR (("Acpi_ex_dyadic2: Unknown dyadic opcode %X\n", opcode)); + status = AE_AML_BAD_OPCODE; + goto cleanup; + break; + } + + + /* Set return value to logical TRUE (all ones) or FALSE (zero) */ + + if (lboolean) { + ret_desc->integer.value = ACPI_INTEGER_MAX; + } + else { + ret_desc->integer.value = 0; + } + + +cleanup: + + /* Always delete operands */ + + acpi_ut_remove_reference (obj_desc); + acpi_ut_remove_reference (obj_desc2); + + + /* Delete return object on error */ + + if (ACPI_FAILURE (status) && + (ret_desc)) { + acpi_ut_remove_reference (ret_desc); + ret_desc = NULL; + } + + + /* Set the return object and exit */ + + *return_desc = ret_desc; + return (status); +} + + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/executer/exfield.c linux/drivers/acpi/executer/exfield.c --- v2.4.5/linux/drivers/acpi/executer/exfield.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/executer/exfield.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,498 @@ +/****************************************************************************** + * + * Module Name: exfield - ACPI AML (p-code) execution - field manipulation + * $Revision: 90 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acdispat.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "achware.h" +#include "acevents.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("exfield") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_read_data_from_field + * + * PARAMETERS: Mode - ACPI_READ or ACPI_WRITE + * *Field_node - Parent node for field to be accessed + * *Buffer - Value(s) to be read or written + * Buffer_length - Number of bytes to transfer + * + * RETURN: Status3 + * + * DESCRIPTION: Read or write a named field + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_read_data_from_field ( + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_OPERAND_OBJECT **ret_buffer_desc) +{ + ACPI_STATUS status; + ACPI_OPERAND_OBJECT *buffer_desc; + u32 length; + void *buffer; + + + /* Parameter validation */ + + if (!obj_desc) { + return (AE_AML_NO_OPERAND); + } + + /* + * Allocate a buffer for the contents of the field. + * + * If the field is larger than the size of an ACPI_INTEGER, create + * a BUFFER to hold it. Otherwise, use an INTEGER. This allows + * the use of arithmetic operators on the returned value if the + * field size is equal or smaller than an Integer. + * + * Note: Field.length is in bits. + */ + + length = ROUND_BITS_UP_TO_BYTES (obj_desc->field.bit_length); + + if (length > sizeof (ACPI_INTEGER)) { + /* Field is too large for an Integer, create a Buffer instead */ + + buffer_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); + if (!buffer_desc) { + return (AE_NO_MEMORY); + } + + /* Create the actual read buffer */ + + buffer_desc->buffer.pointer = acpi_ut_callocate (length); + if (!buffer_desc->buffer.pointer) { + acpi_ut_remove_reference (buffer_desc); + return (AE_NO_MEMORY); + } + + buffer_desc->buffer.length = length; + buffer = buffer_desc->buffer.pointer; + } + + else { + /* Field will fit within an Integer (normal case) */ + + buffer_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); + if (!buffer_desc) { + return (AE_NO_MEMORY); + } + + length = sizeof (buffer_desc->integer.value); + buffer = &buffer_desc->integer.value; + } + + + /* Read from the appropriate field */ + + switch (obj_desc->common.type) { + case ACPI_TYPE_BUFFER_FIELD: + status = acpi_ex_access_buffer_field (ACPI_READ, obj_desc, buffer, length); + break; + + case INTERNAL_TYPE_REGION_FIELD: + status = acpi_ex_access_region_field (ACPI_READ, obj_desc, buffer, length); + break; + + case INTERNAL_TYPE_BANK_FIELD: + status = acpi_ex_access_bank_field (ACPI_READ, obj_desc, buffer, length); + break; + + case INTERNAL_TYPE_INDEX_FIELD: + status = acpi_ex_access_index_field (ACPI_READ, obj_desc, buffer, length); + break; + + default: + status = AE_AML_INTERNAL; + } + + + if (ACPI_FAILURE (status)) { + acpi_ut_remove_reference (buffer_desc); + } + + else if (ret_buffer_desc) { + *ret_buffer_desc = buffer_desc; + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_write_data_to_field + * + * PARAMETERS: Mode - ACPI_READ or ACPI_WRITE + * *Field_node - Parent node for field to be accessed + * *Buffer - Value(s) to be read or written + * Buffer_length - Number of bytes to transfer + * + * RETURN: Status + * + * DESCRIPTION: Read or write a named field + * + ******************************************************************************/ + + +ACPI_STATUS +acpi_ex_write_data_to_field ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OPERAND_OBJECT *obj_desc) +{ + ACPI_STATUS status; + u32 length; + void *buffer; + + + /* Parameter validation */ + + if (!source_desc || !obj_desc) { + return (AE_AML_NO_OPERAND); + } + + + /* + * Get a pointer to the data to be written + */ + switch (source_desc->common.type) { + case ACPI_TYPE_INTEGER: + buffer = &source_desc->integer.value; + length = sizeof (source_desc->integer.value); + break; + + case ACPI_TYPE_BUFFER: + buffer = source_desc->buffer.pointer; + length = source_desc->buffer.length; + break; + + case ACPI_TYPE_STRING: + buffer = source_desc->string.pointer; + length = source_desc->string.length; + break; + + default: + return (AE_AML_OPERAND_TYPE); + } + + + /* + * Decode the type of field to be written + */ + switch (obj_desc->common.type) { + case ACPI_TYPE_BUFFER_FIELD: + status = acpi_ex_access_buffer_field (ACPI_WRITE, obj_desc, buffer, length); + break; + + case INTERNAL_TYPE_REGION_FIELD: + status = acpi_ex_access_region_field (ACPI_WRITE, obj_desc, buffer, length); + break; + + case INTERNAL_TYPE_BANK_FIELD: + status = acpi_ex_access_bank_field (ACPI_WRITE, obj_desc, buffer, length); + break; + + case INTERNAL_TYPE_INDEX_FIELD: + status = acpi_ex_access_index_field (ACPI_WRITE, obj_desc, buffer, length); + break; + + default: + return (AE_AML_INTERNAL); + } + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_access_buffer_field + * + * PARAMETERS: Mode - ACPI_READ or ACPI_WRITE + * *Field_node - Parent node for field to be accessed + * *Buffer - Value(s) to be read or written + * Buffer_length - Number of bytes to transfer + * + * RETURN: Status + * + * DESCRIPTION: Read or write a named field + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_access_buffer_field ( + u32 mode, + ACPI_OPERAND_OBJECT *obj_desc, + void *buffer, + u32 buffer_length) +{ + ACPI_STATUS status; + + + /* + * If the Buffer_field arguments have not been previously evaluated, + * evaluate them now and save the results. + */ + if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { + status = acpi_ds_get_buffer_field_arguments (obj_desc); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + + status = acpi_ex_common_access_field (mode, obj_desc, buffer, buffer_length); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_access_region_field + * + * PARAMETERS: Mode - ACPI_READ or ACPI_WRITE + * *Field_node - Parent node for field to be accessed + * *Buffer - Value(s) to be read or written + * Buffer_length - Number of bytes to transfer + * + * RETURN: Status + * + * DESCRIPTION: Read or write a named field + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_access_region_field ( + u32 mode, + ACPI_OPERAND_OBJECT *obj_desc, + void *buffer, + u32 buffer_length) +{ + ACPI_STATUS status; + u8 locked; + + + /* + * Get the global lock if needed + */ + locked = acpi_ex_acquire_global_lock (obj_desc->field.lock_rule); + + status = acpi_ex_common_access_field (mode, obj_desc, buffer, buffer_length); + + + /* + * Release global lock if we acquired it earlier + */ + acpi_ex_release_global_lock (locked); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_access_bank_field + * + * PARAMETERS: Mode - ACPI_READ or ACPI_WRITE + * *Field_node - Parent node for field to be accessed + * *Buffer - Value(s) to be read or written + * Buffer_length - Number of bytes to transfer + * + * RETURN: Status + * + * DESCRIPTION: Read or write a Bank Field + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_access_bank_field ( + u32 mode, + ACPI_OPERAND_OBJECT *obj_desc, + void *buffer, + u32 buffer_length) +{ + ACPI_STATUS status; + u8 locked; + + + /* + * Get the global lock if needed + */ + locked = acpi_ex_acquire_global_lock (obj_desc->bank_field.lock_rule); + + + /* + * Write the Bank_value to the Bank_register to select the bank. + * The Bank_value for this Bank_field is specified in the + * Bank_field ASL declaration. The Bank_register is always a Field in + * an operation region. + */ + + status = acpi_ex_common_access_field (ACPI_WRITE, + obj_desc->bank_field.bank_register_obj, + &obj_desc->bank_field.value, + sizeof (obj_desc->bank_field.value)); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + /* + * The bank was successfully selected, now read or write the actual + * data. + */ + status = acpi_ex_common_access_field (mode, obj_desc, buffer, buffer_length); + + +cleanup: + /* + * Release global lock if we acquired it earlier + */ + acpi_ex_release_global_lock (locked); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_access_index_field + * + * PARAMETERS: Mode - ACPI_READ or ACPI_WRITE + * *Field_node - Parent node for field to be accessed + * *Buffer - Value(s) to be read or written + * Buffer_length - Number of bytes to transfer + * + * RETURN: Status + * + * DESCRIPTION: Read or write a Index Field + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_access_index_field ( + u32 mode, + ACPI_OPERAND_OBJECT *obj_desc, + void *buffer, + u32 buffer_length) +{ + ACPI_STATUS status; + u8 locked; + + + /* + * Get the global lock if needed + */ + locked = acpi_ex_acquire_global_lock (obj_desc->index_field.lock_rule); + + + /* + * Set Index value to select proper Data register + */ + status = acpi_ex_common_access_field (ACPI_WRITE, + obj_desc->index_field.index_obj, + &obj_desc->index_field.value, + sizeof (obj_desc->index_field.value)); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + /* Now read/write the data register */ + + status = acpi_ex_common_access_field (mode, obj_desc->index_field.data_obj, + buffer, buffer_length); + +cleanup: + /* + * Release global lock if we acquired it earlier + */ + acpi_ex_release_global_lock (locked); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_common_access_field + * + * PARAMETERS: Mode - ACPI_READ or ACPI_WRITE + * *Field_node - Parent node for field to be accessed + * *Buffer - Value(s) to be read or written + * Buffer_length - Size of buffer, in bytes. Must be large + * enough for all bits of the field. + * + * RETURN: Status + * + * DESCRIPTION: Read or write a named field + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_common_access_field ( + u32 mode, + ACPI_OPERAND_OBJECT *obj_desc, + void *buffer, + u32 buffer_length) +{ + ACPI_STATUS status; + + + /* Perform the actual read or write of the field */ + + switch (mode) { + case ACPI_READ: + + status = acpi_ex_extract_from_field (obj_desc, buffer, buffer_length); + break; + + + case ACPI_WRITE: + + status = acpi_ex_insert_into_field (obj_desc, buffer, buffer_length); + break; + + + default: + + status = AE_BAD_PARAMETER; + break; + } + + + return (status); +} + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/executer/exfldio.c linux/drivers/acpi/executer/exfldio.c --- v2.4.5/linux/drivers/acpi/executer/exfldio.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/executer/exfldio.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,827 @@ +/****************************************************************************** + * + * Module Name: exfldio - Aml Field I/O + * $Revision: 57 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "achware.h" +#include "acevents.h" +#include "acdispat.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("exfldio") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_setup_field + * + * PARAMETERS: *Obj_desc - Field to be read or written + * Field_datum_byte_offset - Current offset into the field + * + * RETURN: Status + * + * DESCRIPTION: Common processing for Acpi_ex_extract_from_field and + * Acpi_ex_insert_into_field + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_setup_field ( + ACPI_OPERAND_OBJECT *obj_desc, + u32 field_datum_byte_offset) +{ + ACPI_STATUS status = AE_OK; + ACPI_OPERAND_OBJECT *rgn_desc; + + + /* Parameter validation */ + + rgn_desc = obj_desc->common_field.region_obj; + if (!obj_desc || !rgn_desc) { + return (AE_AML_NO_OPERAND); + } + + if (ACPI_TYPE_REGION != rgn_desc->common.type) { + return (AE_AML_OPERAND_TYPE); + } + + + /* + * If the Region Address and Length have not been previously evaluated, + * evaluate them now and save the results. + */ + if (!(rgn_desc->region.flags & AOPOBJ_DATA_VALID)) { + + status = acpi_ds_get_region_arguments (rgn_desc); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + + /* + * Validate the request. The entire request from the byte offset for a + * length of one field datum (access width) must fit within the region. + * (Region length is specified in bytes) + */ + if (rgn_desc->region.length < (obj_desc->common_field.base_byte_offset + + field_datum_byte_offset + + obj_desc->common_field.access_byte_width)) { + if (rgn_desc->region.length < obj_desc->common_field.access_byte_width) { + /* + * This is the case where the Access_type (Acc_word, etc.) is wider + * than the region itself. For example, a region of length one + * byte, and a field with Dword access specified. + */ + } + + /* + * Offset rounded up to next multiple of field width + * exceeds region length, indicate an error + */ + return (AE_AML_REGION_LIMIT); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_read_field_datum + * + * PARAMETERS: *Obj_desc - Field to be read + * *Value - Where to store value (must be 32 bits) + * + * RETURN: Status + * + * DESCRIPTION: Retrieve the value of the given field + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_read_field_datum ( + ACPI_OPERAND_OBJECT *obj_desc, + u32 field_datum_byte_offset, + u32 *value) +{ + ACPI_STATUS status; + ACPI_OPERAND_OBJECT *rgn_desc; + ACPI_PHYSICAL_ADDRESS address; + u32 local_value; + + + if (!value) { + local_value = 0; + value = &local_value; /* support reads without saving value */ + } + + /* Clear the entire return buffer first, [Very Important!] */ + + *value = 0; + + + /* + * Buffer_fields - Read from a Buffer + * Other Fields - Read from a Operation Region. + */ + switch (obj_desc->common.type) { + case ACPI_TYPE_BUFFER_FIELD: + + /* + * For Buffer_fields, we only need to copy the data from the + * source buffer. Length is the field width in bytes. + */ + MEMCPY (value, (obj_desc->buffer_field.buffer_obj)->buffer.pointer + + obj_desc->buffer_field.base_byte_offset + field_datum_byte_offset, + obj_desc->common_field.access_byte_width); + status = AE_OK; + break; + + + case INTERNAL_TYPE_REGION_FIELD: + case INTERNAL_TYPE_BANK_FIELD: + + /* + * For other fields, we need to go through an Operation Region + * (Only types that will get here are Region_fields and Bank_fields) + */ + status = acpi_ex_setup_field (obj_desc, field_datum_byte_offset); + if (ACPI_FAILURE (status)) { + return (status); + } + + + /* + * The physical address of this field datum is: + * + * 1) The base of the region, plus + * 2) The base offset of the field, plus + * 3) The current offset into the field + */ + rgn_desc = obj_desc->common_field.region_obj; + address = rgn_desc->region.address + obj_desc->common_field.base_byte_offset + + field_datum_byte_offset; + + + /* Invoke the appropriate Address_space/Op_region handler */ + + status = acpi_ev_address_space_dispatch (rgn_desc, ACPI_READ_ADR_SPACE, + address, obj_desc->common_field.access_bit_width, value); + + break; + + + default: + + status = AE_AML_INTERNAL; + break; + } + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_get_buffer_datum + * + * PARAMETERS: Merged_datum - Value to store + * Buffer - Receiving buffer + * Byte_granularity - 1/2/4 Granularity of the field + * (aka Datum Size) + * Offset - Datum offset into the buffer + * + * RETURN: none + * + * DESCRIPTION: Store the merged datum to the buffer according to the + * byte granularity + * + ******************************************************************************/ + +static void +acpi_ex_get_buffer_datum( + u32 *datum, + void *buffer, + u32 byte_granularity, + u32 offset) +{ + + switch (byte_granularity) { + case ACPI_FIELD_BYTE_GRANULARITY: + *datum = ((u8 *) buffer) [offset]; + break; + + case ACPI_FIELD_WORD_GRANULARITY: + MOVE_UNALIGNED16_TO_32 (datum, &(((u16 *) buffer) [offset])); + break; + + case ACPI_FIELD_DWORD_GRANULARITY: + MOVE_UNALIGNED32_TO_32 (datum, &(((u32 *) buffer) [offset])); + break; + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_set_buffer_datum + * + * PARAMETERS: Merged_datum - Value to store + * Buffer - Receiving buffer + * Byte_granularity - 1/2/4 Granularity of the field + * (aka Datum Size) + * Offset - Datum offset into the buffer + * + * RETURN: none + * + * DESCRIPTION: Store the merged datum to the buffer according to the + * byte granularity + * + ******************************************************************************/ + +static void +acpi_ex_set_buffer_datum ( + u32 merged_datum, + void *buffer, + u32 byte_granularity, + u32 offset) +{ + + switch (byte_granularity) { + case ACPI_FIELD_BYTE_GRANULARITY: + ((u8 *) buffer) [offset] = (u8) merged_datum; + break; + + case ACPI_FIELD_WORD_GRANULARITY: + MOVE_UNALIGNED16_TO_16 (&(((u16 *) buffer)[offset]), &merged_datum); + break; + + case ACPI_FIELD_DWORD_GRANULARITY: + MOVE_UNALIGNED32_TO_32 (&(((u32 *) buffer)[offset]), &merged_datum); + break; + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_extract_from_field + * + * PARAMETERS: *Obj_desc - Field to be read + * *Value - Where to store value + * + * RETURN: Status + * + * DESCRIPTION: Retrieve the value of the given field + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_extract_from_field ( + ACPI_OPERAND_OBJECT *obj_desc, + void *buffer, + u32 buffer_length) +{ + ACPI_STATUS status; + u32 field_datum_byte_offset; + u32 datum_offset; + u32 previous_raw_datum; + u32 this_raw_datum = 0; + u32 merged_datum = 0; + u32 byte_field_length; + u32 datum_count; + + + /* + * The field must fit within the caller's buffer + */ + byte_field_length = ROUND_BITS_UP_TO_BYTES (obj_desc->common_field.bit_length); + if (byte_field_length > buffer_length) { + return (AE_BUFFER_OVERFLOW); + } + + /* Convert field byte count to datum count, round up if necessary */ + + datum_count = ROUND_UP_TO (byte_field_length, obj_desc->common_field.access_byte_width); + + + /* + * Clear the caller's buffer (the whole buffer length as given) + * This is very important, especially in the cases where a byte is read, + * but the buffer is really a u32 (4 bytes). + */ + MEMSET (buffer, 0, buffer_length); + + /* Read the first raw datum to prime the loop */ + + field_datum_byte_offset = 0; + datum_offset= 0; + + status = acpi_ex_read_field_datum (obj_desc, field_datum_byte_offset, &previous_raw_datum); + if (ACPI_FAILURE (status)) { + return (status); + } + + + /* We might actually be done if the request fits in one datum */ + + if ((datum_count == 1) && + (obj_desc->common_field.access_flags & AFIELD_SINGLE_DATUM)) { + /* 1) Shift the valid data bits down to start at bit 0 */ + + merged_datum = (previous_raw_datum >> obj_desc->common_field.start_field_bit_offset); + + /* 2) Mask off any upper unused bits (bits not part of the field) */ + + if (obj_desc->common_field.end_buffer_valid_bits) { + merged_datum &= MASK_BITS_ABOVE (obj_desc->common_field.end_buffer_valid_bits); + } + + /* Store the datum to the caller buffer */ + + acpi_ex_set_buffer_datum (merged_datum, buffer, obj_desc->common_field.access_byte_width, + datum_offset); + + return (AE_OK); + } + + + /* We need to get more raw data to complete one or more field data */ + + while (datum_offset < datum_count) { + field_datum_byte_offset += obj_desc->common_field.access_byte_width; + + /* + * If the field is aligned on a byte boundary, we don't want + * to perform a final read, since this would potentially read + * past the end of the region. + * + * TBD: [Investigate] It may make more sense to just split the aligned + * and non-aligned cases since the aligned case is so very simple, + */ + if ((obj_desc->common_field.start_field_bit_offset != 0) || + ((obj_desc->common_field.start_field_bit_offset == 0) && + (datum_offset < (datum_count -1)))) { + /* + * Get the next raw datum, it contains some or all bits + * of the current field datum + */ + status = acpi_ex_read_field_datum (obj_desc, field_datum_byte_offset, &this_raw_datum); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + /* + * Create the (possibly) merged datum to be stored to the caller buffer + */ + if (obj_desc->common_field.start_field_bit_offset == 0) { + /* Field is not skewed and we can just copy the datum */ + + merged_datum = previous_raw_datum; + } + + else { + /* + * Put together the appropriate bits of the two raw data to make a + * single complete field datum + * + * 1) Normalize the first datum down to bit 0 + */ + merged_datum = (previous_raw_datum >> obj_desc->common_field.start_field_bit_offset); + + /* 2) Insert the second datum "above" the first datum */ + + merged_datum |= (this_raw_datum << obj_desc->common_field.datum_valid_bits); + + if ((datum_offset >= (datum_count -1))) { + /* + * This is the last iteration of the loop. We need to clear + * any unused bits (bits that are not part of this field) that + * came from the last raw datum before we store the final + * merged datum into the caller buffer. + */ + if (obj_desc->common_field.end_buffer_valid_bits) { + merged_datum &= + MASK_BITS_ABOVE (obj_desc->common_field.end_buffer_valid_bits); + } + } + } + + + /* + * Store the merged field datum in the caller's buffer, according to + * the granularity of the field (size of each datum). + */ + acpi_ex_set_buffer_datum (merged_datum, buffer, obj_desc->common_field.access_byte_width, + datum_offset); + + /* + * Save the raw datum that was just acquired since it may contain bits + * of the *next* field datum. Update offsets + */ + previous_raw_datum = this_raw_datum; + datum_offset++; + } + + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_write_field_datum + * + * PARAMETERS: *Obj_desc - Field to be set + * Value - Value to store + * + * RETURN: Status + * + * DESCRIPTION: Store the value into the given field + * + ******************************************************************************/ + +static ACPI_STATUS +acpi_ex_write_field_datum ( + ACPI_OPERAND_OBJECT *obj_desc, + u32 field_datum_byte_offset, + u32 value) +{ + ACPI_STATUS status = AE_OK; + ACPI_OPERAND_OBJECT *rgn_desc = NULL; + ACPI_PHYSICAL_ADDRESS address; + + + /* + * Buffer_fields - Read from a Buffer + * Other Fields - Read from a Operation Region. + */ + switch (obj_desc->common.type) { + case ACPI_TYPE_BUFFER_FIELD: + + /* + * For Buffer_fields, we only need to copy the data to the + * target buffer. Length is the field width in bytes. + */ + MEMCPY ((obj_desc->buffer_field.buffer_obj)->buffer.pointer + + obj_desc->buffer_field.base_byte_offset + field_datum_byte_offset, + &value, obj_desc->common_field.access_byte_width); + status = AE_OK; + break; + + + case INTERNAL_TYPE_REGION_FIELD: + case INTERNAL_TYPE_BANK_FIELD: + + /* + * For other fields, we need to go through an Operation Region + * (Only types that will get here are Region_fields and Bank_fields) + */ + status = acpi_ex_setup_field (obj_desc, field_datum_byte_offset); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * The physical address of this field datum is: + * + * 1) The base of the region, plus + * 2) The base offset of the field, plus + * 3) The current offset into the field + */ + rgn_desc = obj_desc->common_field.region_obj; + address = rgn_desc->region.address + + obj_desc->common_field.base_byte_offset + + field_datum_byte_offset; + + /* Invoke the appropriate Address_space/Op_region handler */ + + status = acpi_ev_address_space_dispatch (rgn_desc, ACPI_WRITE_ADR_SPACE, + address, obj_desc->common_field.access_bit_width, &value); + + + + break; + + + default: + + status = AE_AML_INTERNAL; + break; + } + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_write_field_datum_with_update_rule + * + * PARAMETERS: *Obj_desc - Field to be set + * Value - Value to store + * + * RETURN: Status + * + * DESCRIPTION: Apply the field update rule to a field write + * + ******************************************************************************/ + +static ACPI_STATUS +acpi_ex_write_field_datum_with_update_rule ( + ACPI_OPERAND_OBJECT *obj_desc, + u32 mask, + u32 field_value, + u32 field_datum_byte_offset) +{ + ACPI_STATUS status = AE_OK; + u32 merged_value; + u32 current_value; + + + /* Start with the new bits */ + + merged_value = field_value; + + + /* If the mask is all ones, we don't need to worry about the update rule */ + + if (mask != ACPI_UINT32_MAX) { + /* Decode the update rule */ + + switch (obj_desc->common_field.update_rule) { + + case UPDATE_PRESERVE: + + /* + * Check if update rule needs to be applied (not if mask is all + * ones) The left shift drops the bits we want to ignore. + */ + if ((~mask << (sizeof (mask) * 8 - + obj_desc->common_field.access_bit_width)) != 0) { + /* + * Read the current contents of the byte/word/dword containing + * the field, and merge with the new field value. + */ + status = acpi_ex_read_field_datum (obj_desc, field_datum_byte_offset, + ¤t_value); + merged_value |= (current_value & ~mask); + } + break; + + + case UPDATE_WRITE_AS_ONES: + + /* Set positions outside the field to all ones */ + + merged_value |= ~mask; + break; + + + case UPDATE_WRITE_AS_ZEROS: + + /* Set positions outside the field to all zeros */ + + merged_value &= mask; + break; + + + default: + return (AE_AML_OPERAND_VALUE); + break; + } + } + + + /* Write the merged value */ + + status = acpi_ex_write_field_datum (obj_desc, field_datum_byte_offset, + merged_value); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_insert_into_field + * + * PARAMETERS: *Obj_desc - Field to be set + * Buffer - Value to store + * + * RETURN: Status + * + * DESCRIPTION: Store the value into the given field + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_insert_into_field ( + ACPI_OPERAND_OBJECT *obj_desc, + void *buffer, + u32 buffer_length) +{ + ACPI_STATUS status; + u32 field_datum_byte_offset; + u32 datum_offset; + u32 mask; + u32 merged_datum; + u32 previous_raw_datum; + u32 this_raw_datum; + u32 byte_field_length; + u32 datum_count; + + + /* + * Incoming buffer must be at least as long as the field, we do not + * allow "partial" field writes. We do not care if the buffer is + * larger than the field, this typically happens when an integer is + * written to a field that is actually smaller than an integer. + */ + byte_field_length = ROUND_BITS_UP_TO_BYTES (obj_desc->common_field.bit_length); + if (buffer_length < byte_field_length) { + /* TBD: Need a better error code */ + + return (AE_BUFFER_OVERFLOW); + } + + /* Convert byte count to datum count, round up if necessary */ + + datum_count = ROUND_UP_TO (byte_field_length, obj_desc->common_field.access_byte_width); + + + /* + * Break the request into up to three parts (similar to an I/O request): + * 1) non-aligned part at start + * 2) aligned part in middle + * 3) non-aligned part at the end + */ + field_datum_byte_offset = 0; + datum_offset= 0; + + /* Get a single datum from the caller's buffer */ + + acpi_ex_get_buffer_datum (&previous_raw_datum, buffer, + obj_desc->common_field.access_byte_width, datum_offset); + + /* + * Part1: + * Write a partial field datum if field does not begin on a datum boundary + * Note: The code in this section also handles the aligned case + * + * Construct Mask with 1 bits where the field is, 0 bits elsewhere + * (Only the bottom 5 bits of Bit_length are valid for a shift operation) + * + * Mask off bits that are "below" the field (if any) + */ + mask = MASK_BITS_BELOW (obj_desc->common_field.start_field_bit_offset); + + /* If the field fits in one datum, may need to mask upper bits */ + + if ((obj_desc->common_field.access_flags & AFIELD_SINGLE_DATUM) && + obj_desc->common_field.end_field_valid_bits) { + /* There are bits above the field, mask them off also */ + + mask &= MASK_BITS_ABOVE (obj_desc->common_field.end_field_valid_bits); + } + + /* Shift and mask the value into the field position */ + + merged_datum = (previous_raw_datum << obj_desc->common_field.start_field_bit_offset); + merged_datum &= mask; + + /* Apply the update rule (if necessary) and write the datum to the field */ + + status = acpi_ex_write_field_datum_with_update_rule (obj_desc, mask, merged_datum, + field_datum_byte_offset); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* If the entire field fits within one datum, we are done. */ + + if ((datum_count == 1) && + (obj_desc->common_field.access_flags & AFIELD_SINGLE_DATUM)) { + return (AE_OK); + } + + /* + * Part2: + * Write the aligned data. + * + * We don't need to worry about the update rule for these data, because + * all of the bits in each datum are part of the field. + * + * The last datum must be special cased because it might contain bits + * that are not part of the field -- therefore the "update rule" must be + * applied in Part3 below. + */ + while (datum_offset < datum_count) { + datum_offset++; + field_datum_byte_offset += obj_desc->common_field.access_byte_width; + + /* + * Get the next raw buffer datum. It may contain bits of the previous + * field datum + */ + acpi_ex_get_buffer_datum (&this_raw_datum, buffer, + obj_desc->common_field.access_byte_width, datum_offset); + + /* Create the field datum based on the field alignment */ + + if (obj_desc->common_field.start_field_bit_offset != 0) { + /* + * Put together appropriate bits of the two raw buffer data to make + * a single complete field datum + */ + merged_datum = + (previous_raw_datum >> obj_desc->common_field.datum_valid_bits) | + (this_raw_datum << obj_desc->common_field.start_field_bit_offset); + } + + else { + /* Field began aligned on datum boundary */ + + merged_datum = this_raw_datum; + } + + + /* + * Special handling for the last datum if the field does NOT end on + * a datum boundary. Update Rule must be applied to the bits outside + * the field. + */ + if ((datum_offset == datum_count) && + obj_desc->common_field.end_field_valid_bits) { + /* + * Part3: + * This is the last datum and the field does not end on a datum boundary. + * Build the partial datum and write with the update rule. + */ + + /* Mask off the unused bits above (after) the end-of-field */ + + mask = MASK_BITS_ABOVE (obj_desc->common_field.end_field_valid_bits); + merged_datum &= mask; + + /* Write the last datum with the update rule */ + + status = acpi_ex_write_field_datum_with_update_rule (obj_desc, mask, + merged_datum, field_datum_byte_offset); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + else { + /* Normal case -- write the completed datum */ + + status = acpi_ex_write_field_datum (obj_desc, + field_datum_byte_offset, merged_datum); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + /* + * Save the most recent datum since it may contain bits of the *next* + * field datum. Update current byte offset. + */ + previous_raw_datum = this_raw_datum; + } + + + return (status); +} + + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/executer/exmisc.c linux/drivers/acpi/executer/exmisc.c --- v2.4.5/linux/drivers/acpi/executer/exmisc.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/executer/exmisc.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,513 @@ + +/****************************************************************************** + * + * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes + * $Revision: 77 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acparser.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acdispat.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("exmisc") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_fatal + * + * PARAMETERS: none + * + * RETURN: Status. If the OS returns from the OSD call, we just keep + * on going. + * + * DESCRIPTION: Execute Fatal operator + * + * ACPI SPECIFICATION REFERENCES: + * Def_fatal := Fatal_op Fatal_type Fatal_code Fatal_arg + * Fatal_type := Byte_data + * Fatal_code := DWord_data + * Fatal_arg := Term_arg=>Integer + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_fatal ( + ACPI_WALK_STATE *walk_state) +{ + ACPI_OPERAND_OBJECT *type_desc; + ACPI_OPERAND_OBJECT *code_desc; + ACPI_OPERAND_OBJECT *arg_desc; + ACPI_STATUS status; + + + /* Resolve operands */ + + status = acpi_ex_resolve_operands (AML_FATAL_OP, WALK_OPERANDS, walk_state); + /* Get operands */ + + status |= acpi_ds_obj_stack_pop_object (&arg_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&code_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&type_desc, walk_state); + if (ACPI_FAILURE (status)) { + /* Invalid parameters on object stack */ + + goto cleanup; + } + + + /* Def_fatal := Fatal_op Fatal_type Fatal_code Fatal_arg */ + + + /* + * TBD: [Unhandled] call OSD interface to notify OS of fatal error + * requiring shutdown! + */ + + +cleanup: + + /* Free the operands */ + + acpi_ut_remove_reference (arg_desc); + acpi_ut_remove_reference (code_desc); + acpi_ut_remove_reference (type_desc); + + + /* If we get back from the OS call, we might as well keep going. */ + + REPORT_WARNING (("An AML \"fatal\" Opcode (Fatal_op) was executed\n")); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_index + * + * PARAMETERS: none + * + * RETURN: Status + * + * DESCRIPTION: Execute Index operator + * + * ALLOCATION: Deletes one operand descriptor -- other remains on stack + * + * ACPI SPECIFICATION REFERENCES: + * Def_index := Index_op Buff_pkg_obj Index_value Result + * Index_value := Term_arg=>Integer + * Name_string := | + * Result := Super_name + * Super_name := Name_string | Arg_obj | Local_obj | Debug_obj | Def_index + * Local4_op | Local5_op | Local6_op | Local7_op + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_index ( + ACPI_WALK_STATE *walk_state, + ACPI_OPERAND_OBJECT **return_desc) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_OPERAND_OBJECT *idx_desc; + ACPI_OPERAND_OBJECT *res_desc; + ACPI_OPERAND_OBJECT *ret_desc = NULL; + ACPI_OPERAND_OBJECT *tmp_desc; + ACPI_STATUS status; + + + /* Resolve operands */ + /* First operand can be either a package or a buffer */ + + status = acpi_ex_resolve_operands (AML_INDEX_OP, WALK_OPERANDS, walk_state); + /* Get all operands */ + + status |= acpi_ds_obj_stack_pop_object (&res_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&idx_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + /* Invalid parameters on object stack */ + + goto cleanup; + } + + + /* Create the internal return object */ + + ret_desc = acpi_ut_create_internal_object (INTERNAL_TYPE_REFERENCE); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + + /* + * At this point, the Obj_desc operand is either a Package or a Buffer + */ + + if (obj_desc->common.type == ACPI_TYPE_PACKAGE) { + /* Object to be indexed is a Package */ + + if (idx_desc->integer.value >= obj_desc->package.count) { + status = AE_AML_PACKAGE_LIMIT; + goto cleanup; + } + + if ((res_desc->common.type == INTERNAL_TYPE_REFERENCE) && + (res_desc->reference.opcode == AML_ZERO_OP)) { + /* + * There is no actual result descriptor (the Zero_op Result + * descriptor is a placeholder), so just delete the placeholder and + * return a reference to the package element + */ + + acpi_ut_remove_reference (res_desc); + } + + else { + /* + * Each element of the package is an internal object. Get the one + * we are after. + */ + + tmp_desc = obj_desc->package.elements[idx_desc->integer.value]; + ret_desc->reference.opcode = AML_INDEX_OP; + ret_desc->reference.target_type = tmp_desc->common.type; + ret_desc->reference.object = tmp_desc; + + status = acpi_ex_store (ret_desc, res_desc, walk_state); + ret_desc->reference.object = NULL; + } + + /* + * The local return object must always be a reference to the package element, + * not the element itself. + */ + ret_desc->reference.opcode = AML_INDEX_OP; + ret_desc->reference.target_type = ACPI_TYPE_PACKAGE; + ret_desc->reference.where = &obj_desc->package.elements[idx_desc->integer.value]; + } + + else { + /* Object to be indexed is a Buffer */ + + if (idx_desc->integer.value >= obj_desc->buffer.length) { + status = AE_AML_BUFFER_LIMIT; + goto cleanup; + } + + ret_desc->reference.opcode = AML_INDEX_OP; + ret_desc->reference.target_type = ACPI_TYPE_BUFFER_FIELD; + ret_desc->reference.object = obj_desc; + ret_desc->reference.offset = (u32) idx_desc->integer.value; + + status = acpi_ex_store (ret_desc, res_desc, walk_state); + } + + +cleanup: + + /* Always delete operands */ + + acpi_ut_remove_reference (obj_desc); + acpi_ut_remove_reference (idx_desc); + + /* Delete return object on error */ + + if (ACPI_FAILURE (status)) { + acpi_ut_remove_reference (res_desc); + + if (ret_desc) { + acpi_ut_remove_reference (ret_desc); + ret_desc = NULL; + } + } + + /* Set the return object and exit */ + + *return_desc = ret_desc; + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_match + * + * PARAMETERS: none + * + * RETURN: Status + * + * DESCRIPTION: Execute Match operator + * + * ACPI SPECIFICATION REFERENCES: + * Def_match := Match_op Search_pkg Opcode1 Operand1 + * Opcode2 Operand2 Start_index + * Opcode1 := Byte_data: MTR, MEQ, MLE, MLT, MGE, or MGT + * Opcode2 := Byte_data: MTR, MEQ, MLE, MLT, MGE, or MGT + * Operand1 := Term_arg=>Integer + * Operand2 := Term_arg=>Integer + * Search_pkg := Term_arg=>Package_object + * Start_index := Term_arg=>Integer + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_match ( + ACPI_WALK_STATE *walk_state, + ACPI_OPERAND_OBJECT **return_desc) +{ + ACPI_OPERAND_OBJECT *pkg_desc; + ACPI_OPERAND_OBJECT *op1_desc; + ACPI_OPERAND_OBJECT *V1_desc; + ACPI_OPERAND_OBJECT *op2_desc; + ACPI_OPERAND_OBJECT *V2_desc; + ACPI_OPERAND_OBJECT *start_desc; + ACPI_OPERAND_OBJECT *ret_desc = NULL; + ACPI_STATUS status; + u32 index; + u32 match_value = (u32) -1; + + + /* Resolve all operands */ + + status = acpi_ex_resolve_operands (AML_MATCH_OP, WALK_OPERANDS, walk_state); + /* Get all operands */ + + status |= acpi_ds_obj_stack_pop_object (&start_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&V2_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&op2_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&V1_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&op1_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&pkg_desc, walk_state); + + if (ACPI_FAILURE (status)) { + /* Invalid parameters on object stack */ + + goto cleanup; + } + + /* Validate match comparison sub-opcodes */ + + if ((op1_desc->integer.value > MAX_MATCH_OPERATOR) || + (op2_desc->integer.value > MAX_MATCH_OPERATOR)) { + status = AE_AML_OPERAND_VALUE; + goto cleanup; + } + + index = (u32) start_desc->integer.value; + if (index >= (u32) pkg_desc->package.count) { + status = AE_AML_PACKAGE_LIMIT; + goto cleanup; + } + + ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + + } + + /* + * Examine each element until a match is found. Within the loop, + * "continue" signifies that the current element does not match + * and the next should be examined. + * Upon finding a match, the loop will terminate via "break" at + * the bottom. If it terminates "normally", Match_value will be -1 + * (its initial value) indicating that no match was found. When + * returned as a Number, this will produce the Ones value as specified. + */ + + for ( ; index < pkg_desc->package.count; ++index) { + /* + * Treat any NULL or non-numeric elements as non-matching. + * TBD [Unhandled] - if an element is a Name, + * should we examine its value? + */ + if (!pkg_desc->package.elements[index] || + ACPI_TYPE_INTEGER != pkg_desc->package.elements[index]->common.type) { + continue; + } + + /* + * Within these switch statements: + * "break" (exit from the switch) signifies a match; + * "continue" (proceed to next iteration of enclosing + * "for" loop) signifies a non-match. + */ + switch (op1_desc->integer.value) { + + case MATCH_MTR: /* always true */ + + break; + + + case MATCH_MEQ: /* true if equal */ + + if (pkg_desc->package.elements[index]->integer.value + != V1_desc->integer.value) { + continue; + } + break; + + + case MATCH_MLE: /* true if less than or equal */ + + if (pkg_desc->package.elements[index]->integer.value + > V1_desc->integer.value) { + continue; + } + break; + + + case MATCH_MLT: /* true if less than */ + + if (pkg_desc->package.elements[index]->integer.value + >= V1_desc->integer.value) { + continue; + } + break; + + + case MATCH_MGE: /* true if greater than or equal */ + + if (pkg_desc->package.elements[index]->integer.value + < V1_desc->integer.value) { + continue; + } + break; + + + case MATCH_MGT: /* true if greater than */ + + if (pkg_desc->package.elements[index]->integer.value + <= V1_desc->integer.value) { + continue; + } + break; + + + default: /* undefined */ + + continue; + } + + + switch(op2_desc->integer.value) { + + case MATCH_MTR: + + break; + + + case MATCH_MEQ: + + if (pkg_desc->package.elements[index]->integer.value + != V2_desc->integer.value) { + continue; + } + break; + + + case MATCH_MLE: + + if (pkg_desc->package.elements[index]->integer.value + > V2_desc->integer.value) { + continue; + } + break; + + + case MATCH_MLT: + + if (pkg_desc->package.elements[index]->integer.value + >= V2_desc->integer.value) { + continue; + } + break; + + + case MATCH_MGE: + + if (pkg_desc->package.elements[index]->integer.value + < V2_desc->integer.value) { + continue; + } + break; + + + case MATCH_MGT: + + if (pkg_desc->package.elements[index]->integer.value + <= V2_desc->integer.value) { + continue; + } + break; + + + default: + + continue; + } + + /* Match found: exit from loop */ + + match_value = index; + break; + } + + /* Match_value is the return value */ + + ret_desc->integer.value = match_value; + + +cleanup: + + /* Free the operands */ + + acpi_ut_remove_reference (start_desc); + acpi_ut_remove_reference (V2_desc); + acpi_ut_remove_reference (op2_desc); + acpi_ut_remove_reference (V1_desc); + acpi_ut_remove_reference (op1_desc); + acpi_ut_remove_reference (pkg_desc); + + + /* Delete return object on error */ + + if (ACPI_FAILURE (status) && + (ret_desc)) { + acpi_ut_remove_reference (ret_desc); + ret_desc = NULL; + } + + + /* Set the return object and exit */ + + *return_desc = ret_desc; + return (status); +} diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/executer/exmonad.c linux/drivers/acpi/executer/exmonad.c --- v2.4.5/linux/drivers/acpi/executer/exmonad.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/executer/exmonad.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,972 @@ + +/****************************************************************************** + * + * Module Name: exmonad - ACPI AML (p-code) execution for monadic operators + * $Revision: 99 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acparser.h" +#include "acdispat.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("exmonad") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_get_object_reference + * + * PARAMETERS: Obj_desc - Create a reference to this object + * Ret_desc - Where to store the reference + * + * RETURN: Status + * + * DESCRIPTION: Obtain and return a "reference" to the target object + * Common code for the Ref_of_op and the Cond_ref_of_op. + * + ******************************************************************************/ + +static ACPI_STATUS +acpi_ex_get_object_reference ( + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_OPERAND_OBJECT **ret_desc, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status = AE_OK; + + + if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_INTERNAL)) { + if (obj_desc->common.type != INTERNAL_TYPE_REFERENCE) { + *ret_desc = NULL; + status = AE_TYPE; + goto cleanup; + } + + /* + * Not a Name -- an indirect name pointer would have + * been converted to a direct name pointer in Acpi_ex_resolve_operands + */ + switch (obj_desc->reference.opcode) { + case AML_LOCAL_OP: + case AML_ARG_OP: + + *ret_desc = (void *) acpi_ds_method_data_get_node (obj_desc->reference.opcode, + obj_desc->reference.offset, walk_state); + break; + + default: + + *ret_desc = NULL; + status = AE_AML_INTERNAL; + goto cleanup; + } + + } + + else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { + /* Must be a named object; Just return the Node */ + + *ret_desc = obj_desc; + } + + else { + *ret_desc = NULL; + status = AE_TYPE; + } + + +cleanup: + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_monadic1 + * + * PARAMETERS: Opcode - The opcode to be executed + * + * RETURN: Status + * + * DESCRIPTION: Execute Type 1 monadic operator with numeric operand on + * object stack + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_monadic1 ( + u16 opcode, + ACPI_WALK_STATE *walk_state) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_STATUS status; + + + /* Resolve all operands */ + + status = acpi_ex_resolve_operands (opcode, WALK_OPERANDS, walk_state); + /* Get all operands */ + + status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + + /* Examine the opcode */ + + switch (opcode) { + + /* Def_release := Release_op Mutex_object */ + + case AML_RELEASE_OP: + + status = acpi_ex_release_mutex (obj_desc, walk_state); + break; + + + /* Def_reset := Reset_op Acpi_event_object */ + + case AML_RESET_OP: + + status = acpi_ex_system_reset_event (obj_desc); + break; + + + /* Def_signal := Signal_op Acpi_event_object */ + + case AML_SIGNAL_OP: + + status = acpi_ex_system_signal_event (obj_desc); + break; + + + /* Def_sleep := Sleep_op Msec_time */ + + case AML_SLEEP_OP: + + acpi_ex_system_do_suspend ((u32) obj_desc->integer.value); + break; + + + /* Def_stall := Stall_op Usec_time */ + + case AML_STALL_OP: + + acpi_ex_system_do_stall ((u32) obj_desc->integer.value); + break; + + + /* Unknown opcode */ + + default: + + REPORT_ERROR (("Acpi_ex_monadic1: Unknown monadic opcode %X\n", + opcode)); + status = AE_AML_BAD_OPCODE; + break; + + } /* switch */ + + +cleanup: + + /* Always delete the operand */ + + acpi_ut_remove_reference (obj_desc); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_monadic2_r + * + * PARAMETERS: Opcode - The opcode to be executed + * + * RETURN: Status + * + * DESCRIPTION: Execute Type 2 monadic operator with numeric operand and + * result operand on operand stack + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_monadic2_r ( + u16 opcode, + ACPI_WALK_STATE *walk_state, + ACPI_OPERAND_OBJECT **return_desc) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_OPERAND_OBJECT *res_desc; + ACPI_OPERAND_OBJECT *ret_desc = NULL; + ACPI_OPERAND_OBJECT *ret_desc2 = NULL; + u32 res_val; + ACPI_STATUS status; + u32 i; + u32 j; + ACPI_INTEGER digit; + + + /* Resolve all operands */ + + status = acpi_ex_resolve_operands (opcode, WALK_OPERANDS, walk_state); + /* Get all operands */ + + status |= acpi_ds_obj_stack_pop_object (&res_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + + /* Create a return object of type NUMBER for most opcodes */ + + switch (opcode) { + case AML_BIT_NOT_OP: + case AML_FIND_SET_LEFT_BIT_OP: + case AML_FIND_SET_RIGHT_BIT_OP: + case AML_FROM_BCD_OP: + case AML_TO_BCD_OP: + case AML_COND_REF_OF_OP: + + ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + break; + } + + + switch (opcode) { + /* Def_not := Not_op Operand Result */ + + case AML_BIT_NOT_OP: + + ret_desc->integer.value = ~obj_desc->integer.value; + break; + + + /* Def_find_set_left_bit := Find_set_left_bit_op Operand Result */ + + case AML_FIND_SET_LEFT_BIT_OP: + + ret_desc->integer.value = obj_desc->integer.value; + + /* + * Acpi specification describes Integer type as a little + * endian unsigned value, so this boundary condition is valid. + */ + for (res_val = 0; ret_desc->integer.value && res_val < ACPI_INTEGER_BIT_SIZE; ++res_val) { + ret_desc->integer.value >>= 1; + } + + ret_desc->integer.value = res_val; + break; + + + /* Def_find_set_right_bit := Find_set_right_bit_op Operand Result */ + + case AML_FIND_SET_RIGHT_BIT_OP: + + ret_desc->integer.value = obj_desc->integer.value; + + /* + * Acpi specification describes Integer type as a little + * endian unsigned value, so this boundary condition is valid. + */ + for (res_val = 0; ret_desc->integer.value && res_val < ACPI_INTEGER_BIT_SIZE; ++res_val) { + ret_desc->integer.value <<= 1; + } + + /* Since returns must be 1-based, subtract from 33 (65) */ + + ret_desc->integer.value = res_val == 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - res_val; + break; + + + /* Def_from_bDC := From_bCDOp BCDValue Result */ + + case AML_FROM_BCD_OP: + + /* + * The 64-bit ACPI integer can hold 16 4-bit BCD integers + */ + ret_desc->integer.value = 0; + for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) { + /* Get one BCD digit */ + + digit = (ACPI_INTEGER) ((obj_desc->integer.value >> (i * 4)) & 0xF); + + /* Check the range of the digit */ + + if (digit > 9) { + 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; + } + + ret_desc->integer.value += digit; + } + } + break; + + + /* Def_to_bDC := To_bCDOp Operand Result */ + + case AML_TO_BCD_OP: + + + if (obj_desc->integer.value > ACPI_MAX_BCD_VALUE) { + status = AE_AML_NUMERIC_OVERFLOW; + goto cleanup; + } + + ret_desc->integer.value = 0; + for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) { + /* Divide by nth factor of 10 */ + + digit = obj_desc->integer.value; + for (j = 0; j < i; j++) { + digit /= 10; + } + + /* Create the BCD digit */ + + if (digit > 0) { + ret_desc->integer.value += (ACPI_MODULO (digit, 10) << (i * 4)); + } + } + break; + + + /* Def_cond_ref_of := Cond_ref_of_op Source_object Result */ + + case AML_COND_REF_OF_OP: + + /* + * 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 *) obj_desc == acpi_gbl_root_node) { + /* + * This means that the object does not exist in the namespace, + * return FALSE + */ + + ret_desc->integer.value = 0; + + /* + * Must delete the result descriptor since there is no reference + * being returned + */ + + acpi_ut_remove_reference (res_desc); + goto cleanup; + } + + /* Get the object reference and store it */ + + status = acpi_ex_get_object_reference (obj_desc, &ret_desc2, walk_state); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + status = acpi_ex_store (ret_desc2, res_desc, walk_state); + + /* The object exists in the namespace, return TRUE */ + + ret_desc->integer.value = ACPI_INTEGER_MAX; + goto cleanup; + break; + + + case AML_STORE_OP: + + /* + * A store operand is typically a number, string, buffer or lvalue + * TBD: [Unhandled] What about a store to a package? + */ + + /* + * Do the store, and be careful about deleting the source object, + * since the object itself may have been stored. + */ + + status = acpi_ex_store (obj_desc, res_desc, walk_state); + if (ACPI_FAILURE (status)) { + /* On failure, just delete the Obj_desc */ + + acpi_ut_remove_reference (obj_desc); + } + + else { + /* + * Normally, we would remove a reference on the Obj_desc parameter; + * But since it is being used as the internal return object + * (meaning we would normally increment it), the two cancel out, + * and we simply don't do anything. + */ + *return_desc = obj_desc; + } + + obj_desc = NULL; + return (status); + + break; + + + case AML_DEBUG_OP: + + /* Reference, returning an Reference */ + + return (AE_OK); + break; + + + /* + * These are obsolete opcodes + */ + + /* Def_shift_left_bit := Shift_left_bit_op Source Bit_num */ + /* Def_shift_right_bit := Shift_right_bit_op Source Bit_num */ + + case AML_SHIFT_LEFT_BIT_OP: + case AML_SHIFT_RIGHT_BIT_OP: + + status = AE_SUPPORT; + goto cleanup; + break; + + + default: + + REPORT_ERROR (("Acpi_ex_monadic2_r: Unknown monadic opcode %X\n", + opcode)); + status = AE_AML_BAD_OPCODE; + goto cleanup; + } + + + status = acpi_ex_store (ret_desc, res_desc, walk_state); + + +cleanup: + /* Always delete the operand object */ + + acpi_ut_remove_reference (obj_desc); + + /* Delete return object(s) on error */ + + if (ACPI_FAILURE (status)) { + acpi_ut_remove_reference (res_desc); /* Result descriptor */ + if (ret_desc) { + acpi_ut_remove_reference (ret_desc); + ret_desc = NULL; + } + } + + /* Set the return object and exit */ + + *return_desc = ret_desc; + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_monadic2 + * + * PARAMETERS: Opcode - The opcode to be executed + * + * RETURN: Status + * + * DESCRIPTION: Execute Type 2 monadic operator with numeric operand: + * Deref_of_op, Ref_of_op, Size_of_op, Type_op, Increment_op, + * Decrement_op, LNot_op, + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_monadic2 ( + u16 opcode, + ACPI_WALK_STATE *walk_state, + ACPI_OPERAND_OBJECT **return_desc) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_OPERAND_OBJECT *tmp_desc; + ACPI_OPERAND_OBJECT *ret_desc = NULL; + ACPI_STATUS resolve_status; + ACPI_STATUS status; + u32 type; + ACPI_INTEGER value; + + + /* Attempt to resolve the operands */ + + resolve_status = acpi_ex_resolve_operands (opcode, WALK_OPERANDS, walk_state); + /* Always get all operands */ + + status = acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); + + /* Now we can check the status codes */ + + if (ACPI_FAILURE (resolve_status)) { + goto cleanup; + } + + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + + /* Get the operand and decode the opcode */ + + + switch (opcode) { + + /* Def_lNot := LNot_op Operand */ + + case AML_LNOT_OP: + + ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + ret_desc->integer.value = !obj_desc->integer.value; + break; + + + /* Def_decrement := Decrement_op Target */ + /* Def_increment := Increment_op Target */ + + case AML_DECREMENT_OP: + case AML_INCREMENT_OP: + + /* + * Since we are expecting an Reference on the top of the stack, it + * can be either an Node or an internal object. + * + * TBD: [Future] This may be the prototype code for all cases where + * an Reference is expected!! 10/99 + */ + + if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { + ret_desc = obj_desc; + } + + else { + /* + * Duplicate the Reference in a new object so that we can resolve it + * without destroying the original Reference object + */ + + ret_desc = acpi_ut_create_internal_object (INTERNAL_TYPE_REFERENCE); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + ret_desc->reference.opcode = obj_desc->reference.opcode; + ret_desc->reference.offset = obj_desc->reference.offset; + ret_desc->reference.object = obj_desc->reference.object; + } + + + /* + * Convert the Ret_desc Reference to a Number + * (This deletes the original Ret_desc) + */ + + status = acpi_ex_resolve_operands (AML_LNOT_OP, &ret_desc, walk_state); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + /* Do the actual increment or decrement */ + + if (AML_INCREMENT_OP == opcode) { + ret_desc->integer.value++; + } + else { + ret_desc->integer.value--; + } + + /* Store the result back in the original descriptor */ + + status = acpi_ex_store (ret_desc, obj_desc, walk_state); + + /* Objdesc was just deleted (because it is an Reference) */ + + obj_desc = NULL; + + break; + + + /* Def_object_type := Object_type_op Source_object */ + + case AML_TYPE_OP: + + if (INTERNAL_TYPE_REFERENCE == obj_desc->common.type) { + /* + * Not a Name -- an indirect name pointer would have + * been converted to a direct name pointer in Resolve_operands + */ + switch (obj_desc->reference.opcode) { + case AML_ZERO_OP: + case AML_ONE_OP: + case AML_ONES_OP: + + /* Constants are of type Number */ + + type = ACPI_TYPE_INTEGER; + break; + + + case AML_DEBUG_OP: + + /* Per 1.0b spec, Debug object is of type Debug_object */ + + type = ACPI_TYPE_DEBUG_OBJECT; + break; + + + case AML_INDEX_OP: + + /* Get the type of this reference (index into another object) */ + + type = obj_desc->reference.target_type; + if (type == ACPI_TYPE_PACKAGE) { + /* + * The main object is a package, we want to get the type + * of the individual package element that is referenced by + * the index. + */ + type = (*(obj_desc->reference.where))->common.type; + } + + break; + + + case AML_LOCAL_OP: + case AML_ARG_OP: + + type = acpi_ds_method_data_get_type (obj_desc->reference.opcode, + obj_desc->reference.offset, walk_state); + break; + + + default: + + REPORT_ERROR (("Acpi_ex_monadic2/Type_op: Internal error - Unknown Reference subtype %X\n", + obj_desc->reference.opcode)); + status = AE_AML_INTERNAL; + goto cleanup; + } + } + + else { + /* + * It's not a Reference, so it must be a direct name pointer. + */ + type = acpi_ns_get_type ((ACPI_NAMESPACE_NODE *) obj_desc); + + /* Convert internal types to external types */ + + switch (type) { + case INTERNAL_TYPE_REGION_FIELD: + case INTERNAL_TYPE_BANK_FIELD: + case INTERNAL_TYPE_INDEX_FIELD: + + type = ACPI_TYPE_FIELD_UNIT; + } + + } + + /* Allocate a descriptor to hold the type. */ + + ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + ret_desc->integer.value = type; + break; + + + /* Def_size_of := Size_of_op Source_object */ + + case AML_SIZE_OF_OP: + + if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { + obj_desc = acpi_ns_get_attached_object ((ACPI_NAMESPACE_NODE *) obj_desc); + } + + if (!obj_desc) { + value = 0; + } + + else { + switch (obj_desc->common.type) { + + case ACPI_TYPE_BUFFER: + + value = obj_desc->buffer.length; + break; + + + case ACPI_TYPE_STRING: + + value = obj_desc->string.length; + break; + + + case ACPI_TYPE_PACKAGE: + + value = obj_desc->package.count; + break; + + case INTERNAL_TYPE_REFERENCE: + + value = 4; + break; + + default: + + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + } + + /* + * Now that we have the size of the object, create a result + * object to hold the value + */ + + ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + ret_desc->integer.value = value; + break; + + + /* Def_ref_of := Ref_of_op Source_object */ + + case AML_REF_OF_OP: + + status = acpi_ex_get_object_reference (obj_desc, &ret_desc, walk_state); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + break; + + + /* Def_deref_of := Deref_of_op Obj_reference */ + + case AML_DEREF_OF_OP: + + + /* Check for a method local or argument */ + + if (!VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { + /* + * Must resolve/dereference the local/arg reference first + */ + switch (obj_desc->reference.opcode) { + /* Set Obj_desc to the value of the local/arg */ + + case AML_LOCAL_OP: + case AML_ARG_OP: + + acpi_ds_method_data_get_value (obj_desc->reference.opcode, + obj_desc->reference.offset, walk_state, &tmp_desc); + + /* + * Delete our reference to the input object and + * point to the object just retrieved + */ + acpi_ut_remove_reference (obj_desc); + obj_desc = tmp_desc; + break; + + default: + + /* Index op - handled below */ + break; + } + } + + + /* Obj_desc may have changed from the code above */ + + if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { + /* Get the actual object from the Node (This is the dereference) */ + + ret_desc = ((ACPI_NAMESPACE_NODE *) obj_desc)->object; + + /* Returning a pointer to the object, add another reference! */ + + acpi_ut_add_reference (ret_desc); + } + + else { + /* + * This must be a reference object produced by the Index + * ASL operation -- check internal opcode + */ + + if ((obj_desc->reference.opcode != AML_INDEX_OP) && + (obj_desc->reference.opcode != AML_REF_OF_OP)) { + status = AE_TYPE; + goto cleanup; + } + + + switch (obj_desc->reference.opcode) { + case AML_INDEX_OP: + + /* + * Supported target types for the Index operator are + * 1) A Buffer + * 2) A Package + */ + + if (obj_desc->reference.target_type == ACPI_TYPE_BUFFER_FIELD) { + /* + * The target is a buffer, we must create a new object that + * contains one element of the buffer, the element pointed + * to by the index. + * + * NOTE: index into a buffer is NOT a pointer to a + * sub-buffer of the main buffer, it is only a pointer to a + * single element (byte) of the buffer! + */ + ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + tmp_desc = obj_desc->reference.object; + ret_desc->integer.value = + tmp_desc->buffer.pointer[obj_desc->reference.offset]; + + /* TBD: [Investigate] (see below) Don't add an additional + * ref! + */ + } + + else if (obj_desc->reference.target_type == ACPI_TYPE_PACKAGE) { + /* + * The target is a package, we want to return the referenced + * element of the package. We must add another reference to + * this object, however. + */ + + ret_desc = *(obj_desc->reference.where); + if (!ret_desc) { + /* + * We can't return a NULL dereferenced value. This is + * an uninitialized package element and is thus a + * severe error. + */ + + status = AE_AML_UNINITIALIZED_ELEMENT; + goto cleanup; + } + + acpi_ut_add_reference (ret_desc); + } + + else { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + + break; + + + case AML_REF_OF_OP: + + ret_desc = obj_desc->reference.object; + + /* Add another reference to the object! */ + + acpi_ut_add_reference (ret_desc); + break; + } + } + + break; + + + default: + + REPORT_ERROR (("Acpi_ex_monadic2: Unknown monadic opcode %X\n", + opcode)); + status = AE_AML_BAD_OPCODE; + goto cleanup; + } + + +cleanup: + + if (obj_desc) { + acpi_ut_remove_reference (obj_desc); + } + + /* Delete return object on error */ + + if (ACPI_FAILURE (status) && + (ret_desc)) { + acpi_ut_remove_reference (ret_desc); + ret_desc = NULL; + } + + *return_desc = ret_desc; + return (status); +} + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/executer/exmutex.c linux/drivers/acpi/executer/exmutex.c --- v2.4.5/linux/drivers/acpi/executer/exmutex.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/executer/exmutex.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,281 @@ + +/****************************************************************************** + * + * Module Name: exmutex - ASL Mutex Acquire/Release functions + * $Revision: 5 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "achware.h" +#include "acevents.h" + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("exmutex") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_unlink_mutex + * + * PARAMETERS: *Obj_desc - The mutex to be unlinked + * + * RETURN: Status + * + * DESCRIPTION: Remove a mutex from the "Acquired_mutex" list + * + ******************************************************************************/ + +void +acpi_ex_unlink_mutex ( + ACPI_OPERAND_OBJECT *obj_desc) +{ + + if (obj_desc->mutex.next) { + (obj_desc->mutex.next)->mutex.prev = obj_desc->mutex.prev; + } + if (obj_desc->mutex.prev) { + (obj_desc->mutex.prev)->mutex.next = obj_desc->mutex.next; + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_link_mutex + * + * PARAMETERS: *Obj_desc - The mutex to be linked + * *List_head - head of the "Acquired_mutex" list + * + * RETURN: Status + * + * DESCRIPTION: Add a mutex to the "Acquired_mutex" list for this walk + * + ******************************************************************************/ + +void +acpi_ex_link_mutex ( + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_OPERAND_OBJECT *list_head) +{ + + /* This object will be the first object in the list */ + + obj_desc->mutex.prev = list_head; + obj_desc->mutex.next = list_head->mutex.next; + + /* Update old first object to point back to this object */ + + if (list_head->mutex.next) { + (list_head->mutex.next)->mutex.prev = obj_desc; + } + + /* Update list head */ + + list_head->mutex.next = obj_desc; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_acquire_mutex + * + * PARAMETERS: *Time_desc - The 'time to delay' object descriptor + * *Obj_desc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Acquire an AML mutex + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_acquire_mutex ( + ACPI_OPERAND_OBJECT *time_desc, + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status; + + + if (!obj_desc) { + return (AE_BAD_PARAMETER); + } + + /* + * Current Sync must be less than or equal to the sync level of the + * mutex. This mechanism provides some deadlock prevention + */ + if (walk_state->current_sync_level > obj_desc->mutex.sync_level) { + return (AE_AML_MUTEX_ORDER); + } + + /* + * If the mutex is already owned by this thread, + * just increment the acquisition depth + */ + if (obj_desc->mutex.owner == walk_state) { + obj_desc->mutex.acquisition_depth++; + return (AE_OK); + } + + /* Acquire the mutex, wait if necessary */ + + status = acpi_ex_system_acquire_mutex (time_desc, obj_desc); + if (ACPI_FAILURE (status)) { + /* Includes failure from a timeout on Time_desc */ + + return (status); + } + + /* Have the mutex, update mutex and walk info */ + + obj_desc->mutex.owner = walk_state; + obj_desc->mutex.acquisition_depth = 1; + walk_state->current_sync_level = obj_desc->mutex.sync_level; + + /* Link the mutex to the walk state for force-unlock at method exit */ + + acpi_ex_link_mutex (obj_desc, (ACPI_OPERAND_OBJECT *) + &(walk_state->walk_list->acquired_mutex_list)); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_release_mutex + * + * PARAMETERS: *Obj_desc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Release a previously acquired Mutex. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_release_mutex ( + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status; + + + if (!obj_desc) { + return (AE_BAD_PARAMETER); + } + + /* The mutex must have been previously acquired in order to release it */ + + if (!obj_desc->mutex.owner) { + return (AE_AML_MUTEX_NOT_ACQUIRED); + } + + /* The Mutex is owned, but this thread must be the owner */ + + if (obj_desc->mutex.owner != walk_state) { + return (AE_AML_NOT_OWNER); + } + + /* + * The sync level of the mutex must be less than or + * equal to the current sync level + */ + if (obj_desc->mutex.sync_level > walk_state->current_sync_level) { + return (AE_AML_MUTEX_ORDER); + } + + /* + * Match multiple Acquires with multiple Releases + */ + obj_desc->mutex.acquisition_depth--; + if (obj_desc->mutex.acquisition_depth != 0) { + /* Just decrement the depth and return */ + + return (AE_OK); + } + + + /* Release the mutex */ + + status = acpi_ex_system_release_mutex (obj_desc); + + /* Update the mutex and walk state */ + + obj_desc->mutex.owner = NULL; + walk_state->current_sync_level = obj_desc->mutex.sync_level; + + /* Unlink the mutex from the owner's list */ + + acpi_ex_unlink_mutex (obj_desc); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_release_all_mutexes + * + * PARAMETERS: *Mutex_list - Head of the mutex list + * + * RETURN: Status + * + * DESCRIPTION: Release all mutexes in the list + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_release_all_mutexes ( + ACPI_OPERAND_OBJECT *list_head) +{ + ACPI_OPERAND_OBJECT *next = list_head->mutex.next; + ACPI_OPERAND_OBJECT *this; + + + /* + * Traverse the list of owned mutexes, releasing each one. + */ + while (next) { + this = next; + next = this->mutex.next; + + /* Mark mutex un-owned */ + + this->mutex.owner = NULL; + this->mutex.prev = NULL; + this->mutex.next = NULL; + this->mutex.acquisition_depth = 0; + + /* Release the mutex */ + + acpi_ex_system_release_mutex (this); + } + + return (AE_OK); +} + + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/executer/exnames.c linux/drivers/acpi/executer/exnames.c --- v2.4.5/linux/drivers/acpi/executer/exnames.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/executer/exnames.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,387 @@ + +/****************************************************************************** + * + * Module Name: exnames - interpreter/scanner name load/execute + * $Revision: 79 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("exnames") + + +/* AML Package Length encodings */ + +#define ACPI_AML_PACKAGE_TYPE1 0x40 +#define ACPI_AML_PACKAGE_TYPE2 0x4000 +#define ACPI_AML_PACKAGE_TYPE3 0x400000 +#define ACPI_AML_PACKAGE_TYPE4 0x40000000 + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_allocate_name_string + * + * PARAMETERS: Prefix_count - Count of parent levels. Special cases: + * (-1) = root, 0 = none + * Num_name_segs - count of 4-character name segments + * + * RETURN: A pointer to the allocated string segment. This segment must + * be deleted by the caller. + * + * DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name + * string is long enough, and set up prefix if any. + * + ******************************************************************************/ + +NATIVE_CHAR * +acpi_ex_allocate_name_string ( + u32 prefix_count, + u32 num_name_segs) +{ + NATIVE_CHAR *temp_ptr; + NATIVE_CHAR *name_string; + u32 size_needed; + + + /* + * Allow room for all \ and ^ prefixes, all segments, and a Multi_name_prefix. + * Also, one byte for the null terminator. + * This may actually be somewhat longer than needed. + */ + + if (prefix_count == (u32) -1) { + /* Special case for root */ + + size_needed = 1 + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1; + } + else { + size_needed = prefix_count + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1; + } + + /* + * Allocate a buffer for the name. + * This buffer must be deleted by the caller! + */ + + name_string = acpi_ut_allocate (size_needed); + if (!name_string) { + REPORT_ERROR (("Ex_allocate_name_string: name allocation failure\n")); + return (NULL); + } + + temp_ptr = name_string; + + /* Set up Root or Parent prefixes if needed */ + + if (prefix_count == (u32) -1) { + *temp_ptr++ = AML_ROOT_PREFIX; + } + + else { + while (prefix_count--) { + *temp_ptr++ = AML_PARENT_PREFIX; + } + } + + + /* Set up Dual or Multi prefixes if needed */ + + if (num_name_segs > 2) { + /* Set up multi prefixes */ + + *temp_ptr++ = AML_MULTI_NAME_PREFIX_OP; + *temp_ptr++ = (char) num_name_segs; + } + + else if (2 == num_name_segs) { + /* Set up dual prefixes */ + + *temp_ptr++ = AML_DUAL_NAME_PREFIX; + } + + /* + * Terminate string following prefixes. Acpi_ex_name_segment() will + * append the segment(s) + */ + + *temp_ptr = 0; + + return (name_string); +} + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_name_segment + * + * PARAMETERS: Interpreter_mode - Current running mode (load1/Load2/Exec) + * + * RETURN: Status + * + * DESCRIPTION: Execute a name segment (4 bytes) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_name_segment ( + u8 **in_aml_address, + NATIVE_CHAR *name_string) +{ + u8 *aml_address = *in_aml_address; + ACPI_STATUS status = AE_OK; + u32 index; + NATIVE_CHAR char_buf[5]; + + + /* + * If first character is a digit, then we know that we aren't looking at a + * valid name segment + */ + char_buf[0] = *aml_address; + + if ('0' <= char_buf[0] && char_buf[0] <= '9') { + return (AE_CTRL_PENDING); + } + + for (index = 4; + (index > 0) && (acpi_ut_valid_acpi_character (*aml_address)); + --index) { + char_buf[4 - index] = *aml_address++; + } + + + /* Valid name segment */ + + if (0 == index) { + /* Found 4 valid characters */ + + char_buf[4] = '\0'; + + if (name_string) { + STRCAT (name_string, char_buf); + } + + } + + else if (4 == index) { + /* + * First character was not a valid name character, + * so we are looking at something other than a name. + */ + status = AE_CTRL_PENDING; + } + + else { + /* Segment started with one or more valid characters, but fewer than 4 */ + + status = AE_AML_BAD_NAME; + } + + *in_aml_address = aml_address; + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_get_name_string + * + * PARAMETERS: Data_type - Data type to be associated with this name + * + * RETURN: Status + * + * DESCRIPTION: Get a name, including any prefixes. + * + ******************************************************************************/ + + +ACPI_STATUS +acpi_ex_get_name_string ( + ACPI_OBJECT_TYPE8 data_type, + u8 *in_aml_address, + NATIVE_CHAR **out_name_string, + u32 *out_name_length) +{ + ACPI_STATUS status = AE_OK; + u8 *aml_address = in_aml_address; + NATIVE_CHAR *name_string = NULL; + u32 num_segments; + u32 prefix_count = 0; + u8 prefix = 0; + u8 has_prefix = FALSE; + + + if (INTERNAL_TYPE_REGION_FIELD == data_type || + INTERNAL_TYPE_BANK_FIELD == data_type || + INTERNAL_TYPE_INDEX_FIELD == data_type) { + /* Disallow prefixes for types associated with Field_unit names */ + + name_string = acpi_ex_allocate_name_string (0, 1); + if (!name_string) { + status = AE_NO_MEMORY; + } + else { + status = acpi_ex_name_segment (&aml_address, name_string); + } + } + + else { + /* + * Data_type is not a field name. + * Examine first character of name for root or parent prefix operators + */ + + switch (*aml_address) { + + case AML_ROOT_PREFIX: + + prefix = *aml_address++; + /* + * Remember that we have a Root_prefix -- + * see comment in Acpi_ex_allocate_name_string() + */ + prefix_count = (u32) -1; + has_prefix = TRUE; + break; + + + case AML_PARENT_PREFIX: + + /* Increment past possibly multiple parent prefixes */ + + do { + prefix = *aml_address++; + ++prefix_count; + + } while (*aml_address == AML_PARENT_PREFIX); + has_prefix = TRUE; + break; + + + default: + + break; + } + + + /* Examine first character of name for name segment prefix operator */ + + switch (*aml_address) { + + case AML_DUAL_NAME_PREFIX: + + prefix = *aml_address++; + name_string = acpi_ex_allocate_name_string (prefix_count, 2); + if (!name_string) { + status = AE_NO_MEMORY; + break; + } + + /* Indicate that we processed a prefix */ + has_prefix = TRUE; + + status = acpi_ex_name_segment (&aml_address, name_string); + if (ACPI_SUCCESS (status)) { + status = acpi_ex_name_segment (&aml_address, name_string); + } + break; + + + case AML_MULTI_NAME_PREFIX_OP: + + prefix = *aml_address++; + /* Fetch count of segments remaining in name path */ + + num_segments = *aml_address++; + + name_string = acpi_ex_allocate_name_string (prefix_count, num_segments); + if (!name_string) { + status = AE_NO_MEMORY; + break; + } + + /* Indicate that we processed a prefix */ + has_prefix = TRUE; + + while (num_segments && + (status = acpi_ex_name_segment (&aml_address, name_string)) == AE_OK) { + --num_segments; + } + + break; + + + case 0: + + /* Null_name valid as of 8-12-98 ASL/AML Grammar Update */ + + + /* Consume the NULL byte */ + + aml_address++; + name_string = acpi_ex_allocate_name_string (prefix_count, 0); + if (!name_string) { + status = AE_NO_MEMORY; + break; + } + + break; + + + default: + + /* Name segment string */ + + name_string = acpi_ex_allocate_name_string (prefix_count, 1); + if (!name_string) { + status = AE_NO_MEMORY; + break; + } + + status = acpi_ex_name_segment (&aml_address, name_string); + break; + + } /* Switch (Peek_op ()) */ + } + + + if (AE_CTRL_PENDING == status && has_prefix) { + /* Ran out of segments after processing a prefix */ + + REPORT_ERROR ( + ("Ex_do_name: Malformed Name at %p\n", name_string)); + status = AE_AML_BAD_NAME; + } + + + *out_name_string = name_string; + *out_name_length = (u32) (aml_address - in_aml_address); + + return (status); +} + + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/executer/exprep.c linux/drivers/acpi/executer/exprep.c --- v2.4.5/linux/drivers/acpi/executer/exprep.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/executer/exprep.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,459 @@ + +/****************************************************************************** + * + * Module Name: exprep - ACPI AML (p-code) execution - field prep utilities + * $Revision: 90 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "acparser.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("exprep") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_decode_field_access_type + * + * PARAMETERS: Access - Encoded field access bits + * Length - Field length. + * + * RETURN: Field granularity (8, 16, or 32) + * + * DESCRIPTION: Decode the Access_type bits of a field definition. + * + ******************************************************************************/ + +static u32 +acpi_ex_decode_field_access_type ( + u32 access, + u16 length) +{ + + switch (access) { + case ACCESS_ANY_ACC: + + /* Use the length to set the access type */ + + if (length <= 8) { + return (8); + } + else if (length <= 16) { + return (16); + } + else if (length <= 32) { + return (32); + } + else if (length <= 64) { + return (64); + } + + /* Default is 8 (byte) */ + + return (8); + break; + + case ACCESS_BYTE_ACC: + return (8); + break; + + case ACCESS_WORD_ACC: + return (16); + break; + + case ACCESS_DWORD_ACC: + return (32); + break; + + case ACCESS_QWORD_ACC: /* ACPI 2.0 */ + return (64); + break; + + default: + /* Invalid field access type */ + + return (0); + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_prep_common_field_object + * + * PARAMETERS: Obj_desc - The field object + * Field_flags - Access, Lock_rule, and Update_rule. + * The format of a Field_flag is described + * in the ACPI specification + * Field_bit_position - Field start position + * Field_bit_length - Field length in number of bits + * + * RETURN: Status + * + * DESCRIPTION: Initialize the areas of the field object that are common + * to the various types of fields. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_prep_common_field_object ( + ACPI_OPERAND_OBJECT *obj_desc, + u8 field_flags, + u32 field_bit_position, + u32 field_bit_length) +{ + u32 access_bit_width; + u32 nearest_byte_address; + + + /* + * Note: the structure being initialized is the + * ACPI_COMMON_FIELD_INFO; No structure fields outside of the common area + * are initialized by this procedure. + */ + + /* Demultiplex the Field_flags byte */ + + obj_desc->common_field.lock_rule = (u8) ((field_flags & LOCK_RULE_MASK) + >> LOCK_RULE_SHIFT); + obj_desc->common_field.update_rule = (u8) ((field_flags & UPDATE_RULE_MASK) + >> UPDATE_RULE_SHIFT); + /* Other misc fields */ + + obj_desc->common_field.bit_length = (u16) field_bit_length; + + /* Decode the access type so we can compute offsets */ + + access_bit_width = acpi_ex_decode_field_access_type ( + ((field_flags & ACCESS_TYPE_MASK) >> ACCESS_TYPE_SHIFT), + obj_desc->field.bit_length); + if (!access_bit_width) { + return (AE_AML_OPERAND_VALUE); + } + + /* Setup width (access granularity) fields */ + + obj_desc->common_field.access_bit_width = (u8) access_bit_width; /* 8, 16, 32, 64 */ + obj_desc->common_field.access_byte_width = (u8) DIV_8 (access_bit_width); /* 1, 2, 4, 8 */ + + if (obj_desc->common.type == ACPI_TYPE_BUFFER_FIELD) { + /* + * Buffer_field access can be on any byte boundary, so the + * granularity is always 8 + */ + access_bit_width = 8; + } + + + /* + * Base_byte_offset is the address of the start of the field within the region. It is + * the byte address of the first *datum* (field-width data unit) of the field. + * (i.e., the first datum that contains at least the first *bit* of the field.) + */ + nearest_byte_address = ROUND_BITS_DOWN_TO_BYTES (field_bit_position); + obj_desc->common_field.base_byte_offset = ROUND_DOWN (nearest_byte_address, + DIV_8 (access_bit_width)); + + /* + * Start_field_bit_offset is the offset of the first bit of the field within a field datum. + * This is calculated as the number of bits from the Base_byte_offset. In other words, + * the start of the field is relative to a byte address, regardless of the access type + * of the field. + */ + obj_desc->common_field.start_field_bit_offset = (u8) (MOD_8 (field_bit_position)); + + /* + * Datum_valid_bits is the number of valid field bits in the first field datum. + */ + obj_desc->common_field.datum_valid_bits = (u8) (access_bit_width - + obj_desc->common_field.start_field_bit_offset); + + /* + * Valid bits -- the number of bits that compose a partial datum, + * 1) At the end of the field within the region (arbitrary starting bit offset) + * 2) At the end of a buffer used to contain the field (starting offset always zero) + */ + obj_desc->common_field.end_field_valid_bits = (u8) ((obj_desc->common_field.start_field_bit_offset + + field_bit_length) % access_bit_width); + obj_desc->common_field.end_buffer_valid_bits = (u8) (field_bit_length % access_bit_width); /* Start_buffer_bit_offset always = 0 */ + + + /* + * Does the entire field fit within a single field access element + * (datum)? (without crossing a datum boundary) + */ + if ((obj_desc->common_field.start_field_bit_offset + obj_desc->common_field.bit_length) <= + (u16) obj_desc->common_field.access_bit_width) { + obj_desc->common_field.access_flags |= AFIELD_SINGLE_DATUM; + } + + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_prep_region_field_value + * + * PARAMETERS: Node - Owning Node + * Region_node - Region in which field is being defined + * Field_flags - Access, Lock_rule, and Update_rule. + * Field_bit_position - Field start position + * Field_bit_length - Field length in number of bits + * + * RETURN: Status + * + * DESCRIPTION: Construct an ACPI_OPERAND_OBJECT of type Def_field and + * connect it to the parent Node. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_prep_region_field_value ( + ACPI_NAMESPACE_NODE *node, + ACPI_HANDLE region_node, + u8 field_flags, + u32 field_bit_position, + u32 field_bit_length) +{ + ACPI_OPERAND_OBJECT *obj_desc; + u32 type; + ACPI_STATUS status; + + + /* Parameter validation */ + + if (!region_node) { + return (AE_AML_NO_OPERAND); + } + + type = acpi_ns_get_type (region_node); + if (type != ACPI_TYPE_REGION) { + return (AE_AML_OPERAND_TYPE); + } + + /* Allocate a new object */ + + obj_desc = acpi_ut_create_internal_object (INTERNAL_TYPE_REGION_FIELD); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + + /* Obj_desc and Region valid */ + + /* Initialize areas of the object that are common to all fields */ + + status = acpi_ex_prep_common_field_object (obj_desc, field_flags, + field_bit_position, field_bit_length); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Initialize areas of the object that are specific to this field type */ + + obj_desc->field.region_obj = acpi_ns_get_attached_object (region_node); + + /* An additional reference for the container */ + + acpi_ut_add_reference (obj_desc->field.region_obj); + + + /* Debug info */ + + + /* + * Store the constructed descriptor (Obj_desc) into the parent Node, + * preserving the current type of that Named_obj. + */ + status = acpi_ns_attach_object (node, obj_desc, (u8) acpi_ns_get_type (node)); + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_prep_bank_field_value + * + * PARAMETERS: Node - Owning Node + * Region_node - Region in which field is being defined + * Bank_register_node - Bank selection register node + * Bank_val - Value to store in selection register + * Field_flags - Access, Lock_rule, and Update_rule + * Field_bit_position - Field start position + * Field_bit_length - Field length in number of bits + * + * RETURN: Status + * + * DESCRIPTION: Construct an object of type Bank_field and attach it to the + * parent Node. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_prep_bank_field_value ( + ACPI_NAMESPACE_NODE *node, + ACPI_NAMESPACE_NODE *region_node, + ACPI_NAMESPACE_NODE *bank_register_node, + u32 bank_val, + u8 field_flags, + u32 field_bit_position, + u32 field_bit_length) +{ + ACPI_OPERAND_OBJECT *obj_desc; + u32 type; + ACPI_STATUS status; + + + /* Parameter validation */ + + if (!region_node) { + return (AE_AML_NO_OPERAND); + } + + type = acpi_ns_get_type (region_node); + if (type != ACPI_TYPE_REGION) { + return (AE_AML_OPERAND_TYPE); + } + + /* Allocate a new object */ + + obj_desc = acpi_ut_create_internal_object (INTERNAL_TYPE_BANK_FIELD); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + /* Obj_desc and Region valid */ + + /* Initialize areas of the object that are common to all fields */ + + status = acpi_ex_prep_common_field_object (obj_desc, field_flags, + field_bit_position, field_bit_length); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Initialize areas of the object that are specific to this field type */ + + obj_desc->bank_field.value = bank_val; + obj_desc->bank_field.region_obj = acpi_ns_get_attached_object (region_node); + obj_desc->bank_field.bank_register_obj = acpi_ns_get_attached_object (bank_register_node); + + /* An additional reference for the attached objects */ + + acpi_ut_add_reference (obj_desc->bank_field.region_obj); + acpi_ut_add_reference (obj_desc->bank_field.bank_register_obj); + + /* Debug info */ + + + /* + * Store the constructed descriptor (Obj_desc) into the parent Node, + * preserving the current type of that Named_obj. + */ + status = acpi_ns_attach_object (node, obj_desc, (u8) acpi_ns_get_type (node)); + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_prep_index_field_value + * + * PARAMETERS: Node - Owning Node + * Index_reg - Index register + * Data_reg - Data register + * Field_flags - Access, Lock_rule, and Update_rule + * Field_bit_position - Field start position + * Field_bit_length - Field length in number of bits + * + * RETURN: Status + * + * DESCRIPTION: Construct an ACPI_OPERAND_OBJECT of type Index_field and + * connect it to the parent Node. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_prep_index_field_value ( + ACPI_NAMESPACE_NODE *node, + ACPI_NAMESPACE_NODE *index_reg, + ACPI_NAMESPACE_NODE *data_reg, + u8 field_flags, + u32 field_bit_position, + u32 field_bit_length) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_STATUS status; + + + /* Parameter validation */ + + if (!index_reg || !data_reg) { + return (AE_AML_NO_OPERAND); + } + + /* Allocate a new object descriptor */ + + obj_desc = acpi_ut_create_internal_object (INTERNAL_TYPE_INDEX_FIELD); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + /* Initialize areas of the object that are common to all fields */ + + status = acpi_ex_prep_common_field_object (obj_desc, field_flags, + field_bit_position, field_bit_length); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Initialize areas of the object that are specific to this field type */ + + obj_desc->index_field.data_obj = acpi_ns_get_attached_object (data_reg); + obj_desc->index_field.index_obj = acpi_ns_get_attached_object (index_reg); + obj_desc->index_field.value = (u32) (field_bit_position / + obj_desc->field.access_bit_width); + + /* An additional reference for the attached objects */ + + acpi_ut_add_reference (obj_desc->index_field.data_obj); + acpi_ut_add_reference (obj_desc->index_field.index_obj); + + /* Debug info */ + + + /* + * Store the constructed descriptor (Obj_desc) into the parent Node, + * preserving the current type of that Named_obj. + */ + status = acpi_ns_attach_object (node, obj_desc, (u8) acpi_ns_get_type (node)); + return (status); +} + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/executer/exregion.c linux/drivers/acpi/executer/exregion.c --- v2.4.5/linux/drivers/acpi/executer/exregion.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/executer/exregion.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,409 @@ + +/****************************************************************************** + * + * Module Name: exregion - ACPI default Op_region (address space) handlers + * $Revision: 48 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "achware.h" +#include "acevents.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("exregion") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_system_memory_space_handler + * + * PARAMETERS: Function - Read or Write operation + * Address - Where in the space to read or write + * Bit_width - Field width in bits (8, 16, or 32) + * Value - Pointer to in or out value + * Handler_context - Pointer to Handler's context + * Region_context - Pointer to context specific to the + * accessed region + * + * RETURN: Status + * + * DESCRIPTION: Handler for the System Memory address space (Op Region) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_system_memory_space_handler ( + u32 function, + ACPI_PHYSICAL_ADDRESS address, + u32 bit_width, + u32 *value, + void *handler_context, + void *region_context) +{ + ACPI_STATUS status = AE_OK; + void *logical_addr_ptr = NULL; + ACPI_MEM_SPACE_CONTEXT *mem_info = region_context; + u32 length; + + + /* Validate and translate the bit width */ + + switch (bit_width) { + case 8: + length = 1; + break; + + case 16: + length = 2; + break; + + case 32: + length = 4; + break; + + default: + return (AE_AML_OPERAND_VALUE); + break; + } + + + /* + * Does the request fit into the cached memory mapping? + * Is 1) Address below the current mapping? OR + * 2) Address beyond the current mapping? + */ + + if ((address < mem_info->mapped_physical_address) || + (((ACPI_INTEGER) address + length) > + ((ACPI_INTEGER) mem_info->mapped_physical_address + mem_info->mapped_length))) { + /* + * The request cannot be resolved by the current memory mapping; + * Delete the existing mapping and create a new one. + */ + + if (mem_info->mapped_length) { + /* Valid mapping, delete it */ + + acpi_os_unmap_memory (mem_info->mapped_logical_address, + mem_info->mapped_length); + } + + mem_info->mapped_length = 0; /* In case of failure below */ + + /* Create a new mapping starting at the address given */ + + status = acpi_os_map_memory (address, SYSMEM_REGION_WINDOW_SIZE, + (void **) &mem_info->mapped_logical_address); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* TBD: should these pointers go to 64-bit in all cases ? */ + + mem_info->mapped_physical_address = address; + mem_info->mapped_length = SYSMEM_REGION_WINDOW_SIZE; + } + + + /* + * Generate a logical pointer corresponding to the address we want to + * access + */ + + /* TBD: should these pointers go to 64-bit in all cases ? */ + + logical_addr_ptr = mem_info->mapped_logical_address + + ((ACPI_INTEGER) address - (ACPI_INTEGER) mem_info->mapped_physical_address); + + /* Perform the memory read or write */ + + switch (function) { + + case ACPI_READ_ADR_SPACE: + + switch (bit_width) { + case 8: + *value = (u32)* (u8 *) logical_addr_ptr; + break; + + case 16: + MOVE_UNALIGNED16_TO_32 (value, logical_addr_ptr); + break; + + case 32: + MOVE_UNALIGNED32_TO_32 (value, logical_addr_ptr); + break; + } + + break; + + + case ACPI_WRITE_ADR_SPACE: + + switch (bit_width) { + case 8: + *(u8 *) logical_addr_ptr = (u8) *value; + break; + + case 16: + MOVE_UNALIGNED16_TO_16 (logical_addr_ptr, value); + break; + + case 32: + MOVE_UNALIGNED32_TO_32 (logical_addr_ptr, value); + break; + } + + break; + + + default: + status = AE_BAD_PARAMETER; + break; + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_system_io_space_handler + * + * PARAMETERS: Function - Read or Write operation + * Address - Where in the space to read or write + * Bit_width - Field width in bits (8, 16, or 32) + * Value - Pointer to in or out value + * Handler_context - Pointer to Handler's context + * Region_context - Pointer to context specific to the + * accessed region + * + * RETURN: Status + * + * DESCRIPTION: Handler for the System IO address space (Op Region) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_system_io_space_handler ( + u32 function, + ACPI_PHYSICAL_ADDRESS address, + u32 bit_width, + u32 *value, + void *handler_context, + void *region_context) +{ + ACPI_STATUS status = AE_OK; + + + /* Decode the function parameter */ + + switch (function) { + + case ACPI_READ_ADR_SPACE: + + switch (bit_width) { + /* I/O Port width */ + + case 8: + *value = (u32) acpi_os_in8 ((ACPI_IO_ADDRESS) address); + break; + + case 16: + *value = (u32) acpi_os_in16 ((ACPI_IO_ADDRESS) address); + break; + + case 32: + *value = acpi_os_in32 ((ACPI_IO_ADDRESS) address); + break; + + default: + status = AE_AML_OPERAND_VALUE; + } + + break; + + + case ACPI_WRITE_ADR_SPACE: + + switch (bit_width) { + /* I/O Port width */ + case 8: + acpi_os_out8 ((ACPI_IO_ADDRESS) address, (u8) *value); + break; + + case 16: + acpi_os_out16 ((ACPI_IO_ADDRESS) address, (u16) *value); + break; + + case 32: + acpi_os_out32 ((ACPI_IO_ADDRESS) address, *value); + break; + + default: + status = AE_AML_OPERAND_VALUE; + } + + break; + + + default: + status = AE_BAD_PARAMETER; + break; + } + + return (status); +} + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_pci_config_space_handler + * + * PARAMETERS: Function - Read or Write operation + * Address - Where in the space to read or write + * Bit_width - Field width in bits (8, 16, or 32) + * Value - Pointer to in or out value + * Handler_context - Pointer to Handler's context + * Region_context - Pointer to context specific to the + * accessed region + * + * RETURN: Status + * + * DESCRIPTION: Handler for the PCI Config address space (Op Region) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_pci_config_space_handler ( + u32 function, + ACPI_PHYSICAL_ADDRESS address, + u32 bit_width, + u32 *value, + void *handler_context, + void *region_context) +{ + ACPI_STATUS status = AE_OK; + u32 pci_bus; + u32 dev_func; + u8 pci_reg; + ACPI_PCI_SPACE_CONTEXT *PCIcontext; + + + /* + * The arguments to Acpi_os(Read|Write)Pci_cfg(Byte|Word|Dword) are: + * + * Seg_bus - 0xSSSSBBBB - SSSS is the PCI bus segment + * BBBB is the PCI bus number + * + * Dev_func - 0xDDDDFFFF - DDDD is the PCI device number + * FFFF is the PCI device function number + * + * Reg_num - Config space register must be < 40h + * + * Value - input value for write, output for read + * + */ + + PCIcontext = (ACPI_PCI_SPACE_CONTEXT *) region_context; + + pci_bus = LOWORD (PCIcontext->seg) << 16; + pci_bus |= LOWORD (PCIcontext->bus); + + dev_func = PCIcontext->dev_func; + + pci_reg = (u8) address; + + switch (function) { + + case ACPI_READ_ADR_SPACE: + + *value = 0; + + switch (bit_width) { + /* PCI Register width */ + + case 8: + status = acpi_os_read_pci_cfg_byte (pci_bus, dev_func, pci_reg, + (u8 *) value); + break; + + case 16: + status = acpi_os_read_pci_cfg_word (pci_bus, dev_func, pci_reg, + (u16 *) value); + break; + + case 32: + status = acpi_os_read_pci_cfg_dword (pci_bus, dev_func, pci_reg, + value); + break; + + default: + status = AE_AML_OPERAND_VALUE; + + } /* Switch bit_width */ + + break; + + + case ACPI_WRITE_ADR_SPACE: + + switch (bit_width) { + /* PCI Register width */ + + case 8: + status = acpi_os_write_pci_cfg_byte (pci_bus, dev_func, pci_reg, + *(u8 *) value); + break; + + case 16: + status = acpi_os_write_pci_cfg_word (pci_bus, dev_func, pci_reg, + *(u16 *) value); + break; + + case 32: + status = acpi_os_write_pci_cfg_dword (pci_bus, dev_func, pci_reg, + *value); + break; + + default: + status = AE_AML_OPERAND_VALUE; + + } /* Switch bit_width */ + + break; + + + default: + + status = AE_BAD_PARAMETER; + break; + + } + + return (status); +} + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/executer/exresnte.c linux/drivers/acpi/executer/exresnte.c --- v2.4.5/linux/drivers/acpi/executer/exresnte.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/executer/exresnte.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,320 @@ + +/****************************************************************************** + * + * Module Name: exresnte - AML Interpreter object resolution + * $Revision: 37 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "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 + MODULE_NAME ("exresnte") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_resolve_node_to_value + * + * PARAMETERS: Stack_ptr - Pointer to a location on a stack that contains + * a pointer to a Node + * Walk_state - Current state + * + * RETURN: Status + * + * DESCRIPTION: Resolve a Namespace node (AKA a "direct name pointer") to + * a valued object + * + * Note: for some of the data types, the pointer attached to the Node + * can be either a pointer to an actual internal object or a pointer into the + * AML stream itself. These types are currently: + * + * ACPI_TYPE_INTEGER + * ACPI_TYPE_STRING + * ACPI_TYPE_BUFFER + * ACPI_TYPE_MUTEX + * ACPI_TYPE_PACKAGE + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_resolve_node_to_value ( + ACPI_NAMESPACE_NODE **stack_ptr, + ACPI_WALK_STATE *walk_state) + +{ + ACPI_STATUS status = AE_OK; + ACPI_OPERAND_OBJECT *val_desc; + ACPI_OPERAND_OBJECT *obj_desc = NULL; + ACPI_NAMESPACE_NODE *node; + u8 *aml_pointer = NULL; + ACPI_OBJECT_TYPE8 entry_type; + ACPI_INTEGER temp_val; + u8 attached_aml_pointer = FALSE; + u8 aml_opcode = 0; + + + /* + * The stack pointer points to a ACPI_NAMESPACE_NODE (Node). Get the + * object that is attached to the Node. + */ + + node = *stack_ptr; + val_desc = acpi_ns_get_attached_object (node); + entry_type = acpi_ns_get_type ((ACPI_HANDLE) node); + + /* + * The Val_desc attached to the Node can be either: + * 1) An internal ACPI object + * 2) A pointer into the AML stream (into one of the ACPI system tables) + */ + + if (acpi_tb_system_table_pointer (val_desc)) { + /* CAN THIS EVERY HAPPEN NOW? TBD!!! */ + + attached_aml_pointer = TRUE; + aml_opcode = *((u8 *) val_desc); + aml_pointer = ((u8 *) val_desc) + 1; + + } + + + /* + * Several Entry_types do not require further processing, so + * we will return immediately + */ + /* Devices rarely have an attached object, return the Node + * and Method locals and arguments have a pseudo-Node + */ + if (entry_type == ACPI_TYPE_DEVICE || + (node->flags & (ANOBJ_METHOD_ARG | ANOBJ_METHOD_LOCAL))) { + return (AE_OK); + } + + if (!val_desc) { + return (AE_AML_NO_OPERAND); + } + + /* + * Action is based on the type of the Node, which indicates the type + * of the attached object or pointer + */ + switch (entry_type) { + + case ACPI_TYPE_PACKAGE: + + if (attached_aml_pointer) { + /* + * This means that the package initialization is not parsed + * -- should not happen + */ + return (AE_NOT_IMPLEMENTED); + } + + /* Val_desc is an internal object in all cases by the time we get here */ + + if (ACPI_TYPE_PACKAGE != val_desc->common.type) { + return (AE_AML_OPERAND_TYPE); + } + + /* Return an additional reference to the object */ + + obj_desc = val_desc; + acpi_ut_add_reference (obj_desc); + break; + + + case ACPI_TYPE_BUFFER: + + if (attached_aml_pointer) { + /* + * This means that the buffer initialization is not parsed + * -- should not happen + */ + return (AE_NOT_IMPLEMENTED); + } + + /* Val_desc is an internal object in all cases by the time we get here */ + + if (ACPI_TYPE_BUFFER != val_desc->common.type) { + return (AE_AML_OPERAND_TYPE); + } + + /* Return an additional reference to the object */ + + obj_desc = val_desc; + acpi_ut_add_reference (obj_desc); + break; + + + case ACPI_TYPE_STRING: + + if (attached_aml_pointer) { + /* Allocate a new string object */ + + obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_STRING); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + /* Init the internal object */ + + obj_desc->string.pointer = (NATIVE_CHAR *) aml_pointer; + obj_desc->string.length = STRLEN (obj_desc->string.pointer); + } + + else { + if (ACPI_TYPE_STRING != val_desc->common.type) { + return (AE_AML_OPERAND_TYPE); + } + + /* Return an additional reference to the object */ + + obj_desc = val_desc; + acpi_ut_add_reference (obj_desc); + } + + break; + + + case ACPI_TYPE_INTEGER: + + /* + * The Node has an attached internal object, make sure that it's a + * number + */ + + if (ACPI_TYPE_INTEGER != val_desc->common.type) { + return (AE_AML_OPERAND_TYPE); + } + + /* Return an additional reference to the object */ + + obj_desc = val_desc; + acpi_ut_add_reference (obj_desc); + break; + + + case ACPI_TYPE_BUFFER_FIELD: + case INTERNAL_TYPE_REGION_FIELD: + case INTERNAL_TYPE_BANK_FIELD: + case INTERNAL_TYPE_INDEX_FIELD: + + status = acpi_ex_read_data_from_field (val_desc, &obj_desc); + break; + + + /* + * For these objects, just return the object attached to the Node + */ + + case ACPI_TYPE_MUTEX: + case ACPI_TYPE_METHOD: + case ACPI_TYPE_POWER: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + case ACPI_TYPE_EVENT: + case ACPI_TYPE_REGION: + + + /* Return an additional reference to the object */ + + obj_desc = val_desc; + acpi_ut_add_reference (obj_desc); + break; + + + /* TYPE_Any is untyped, and thus there is no object associated with it */ + + case ACPI_TYPE_ANY: + + return (AE_AML_OPERAND_TYPE); /* Cannot be AE_TYPE */ + break; + + + /* + * The only named references allowed are named constants + * e.g. -- Name (\OSFL, Ones) + */ + case INTERNAL_TYPE_REFERENCE: + + switch (val_desc->reference.opcode) { + + case AML_ZERO_OP: + + temp_val = 0; + break; + + case AML_ONE_OP: + + temp_val = 1; + break; + + case AML_ONES_OP: + + temp_val = ACPI_INTEGER_MAX; + break; + + default: + + return (AE_AML_BAD_OPCODE); + } + + /* Create object for result */ + + obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + obj_desc->integer.value = temp_val; + + /* Truncate value if we are executing from a 32-bit ACPI table */ + + acpi_ex_truncate_for32bit_table (obj_desc, walk_state); + break; + + + /* Default case is for unknown types */ + + default: + + return (AE_AML_OPERAND_TYPE); + + } /* switch (Entry_type) */ + + + /* Put the object descriptor on the stack */ + + *stack_ptr = (void *) obj_desc; + return (status); +} + + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/executer/exresolv.c linux/drivers/acpi/executer/exresolv.c --- v2.4.5/linux/drivers/acpi/executer/exresolv.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/executer/exresolv.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,401 @@ + +/****************************************************************************** + * + * Module Name: exresolv - AML Interpreter object resolution + * $Revision: 95 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "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 + MODULE_NAME ("exresolv") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_get_buffer_field_value + * + * PARAMETERS: *Obj_desc - Pointer to a Buffer_field + * *Result_desc - Pointer to an empty descriptor which will + * become an Integer with the field's value + * + * RETURN: Status + * + * DESCRIPTION: Retrieve the value from a Buffer_field + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_get_buffer_field_value ( + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_OPERAND_OBJECT *result_desc) +{ + ACPI_STATUS status; + u32 mask; + u8 *location; + + + /* + * Parameter validation + */ + if (!obj_desc) { + return (AE_AML_NO_OPERAND); + } + + if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { + status = acpi_ds_get_buffer_field_arguments (obj_desc); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + if (!obj_desc->buffer_field.buffer_obj) { + return (AE_AML_INTERNAL); + } + + if (ACPI_TYPE_BUFFER != obj_desc->buffer_field.buffer_obj->common.type) { + return (AE_AML_OPERAND_TYPE); + } + + if (!result_desc) { + return (AE_AML_INTERNAL); + } + + + /* Field location is (base of buffer) + (byte offset) */ + + location = obj_desc->buffer_field.buffer_obj->buffer.pointer + + obj_desc->buffer_field.base_byte_offset; + + /* + * Construct Mask with as many 1 bits as the field width + * + * NOTE: Only the bottom 5 bits are valid for a shift operation, so + * special care must be taken for any shift greater than 31 bits. + * + * TBD: [Unhandled] Fields greater than 32 bits will not work. + */ + if (obj_desc->buffer_field.bit_length < 32) { + mask = ((u32) 1 << obj_desc->buffer_field.bit_length) - (u32) 1; + } + else { + mask = ACPI_UINT32_MAX; + } + + result_desc->integer.type = (u8) ACPI_TYPE_INTEGER; + + /* Get the 32 bit value at the location */ + + MOVE_UNALIGNED32_TO_32 (&result_desc->integer.value, location); + + /* + * Shift the 32-bit word containing the field, and mask off the + * resulting value + */ + result_desc->integer.value = + (result_desc->integer.value >> obj_desc->buffer_field.start_field_bit_offset) & mask; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_resolve_to_value + * + * PARAMETERS: **Stack_ptr - Points to entry on Obj_stack, which can + * be either an (ACPI_OPERAND_OBJECT *) + * or an ACPI_HANDLE. + * Walk_state - Current method state + * + * RETURN: Status + * + * DESCRIPTION: Convert Reference objects to values + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_resolve_to_value ( + ACPI_OPERAND_OBJECT **stack_ptr, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status; + + + if (!stack_ptr || !*stack_ptr) { + return (AE_AML_NO_OPERAND); + } + + + /* + * The entity pointed to by the Stack_ptr can be either + * 1) A valid ACPI_OPERAND_OBJECT, or + * 2) A ACPI_NAMESPACE_NODE (Named_obj) + */ + if (VALID_DESCRIPTOR_TYPE (*stack_ptr, ACPI_DESC_TYPE_INTERNAL)) { + status = acpi_ex_resolve_object_to_value (stack_ptr, walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + /* + * Object on the stack may have changed if Acpi_ex_resolve_object_to_value() + * was called (i.e., we can't use an _else_ here.) + */ + if (VALID_DESCRIPTOR_TYPE (*stack_ptr, ACPI_DESC_TYPE_NAMED)) { + status = acpi_ex_resolve_node_to_value ((ACPI_NAMESPACE_NODE **) stack_ptr, + walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_resolve_object_to_value + * + * PARAMETERS: Stack_ptr - Pointer to a stack location that contains a + * ptr to an internal object. + * Walk_state - Current method state + * + * RETURN: Status + * + * DESCRIPTION: Retrieve the value from an internal object. The Reference type + * uses the associated AML opcode to determine the value. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_resolve_object_to_value ( + ACPI_OPERAND_OBJECT **stack_ptr, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status = AE_OK; + ACPI_OPERAND_OBJECT *stack_desc; + void *temp_node; + ACPI_OPERAND_OBJECT *obj_desc; + u16 opcode; + + + stack_desc = *stack_ptr; + + /* This is an ACPI_OPERAND_OBJECT */ + + switch (stack_desc->common.type) { + + case INTERNAL_TYPE_REFERENCE: + + opcode = stack_desc->reference.opcode; + + switch (opcode) { + + case AML_NAME_OP: + + /* + * Convert indirect name ptr to a direct name ptr. + * Then, Acpi_ex_resolve_node_to_value can be used to get the value + */ + temp_node = stack_desc->reference.object; + + /* Delete the Reference Object */ + + acpi_ut_remove_reference (stack_desc); + + /* Put direct name pointer onto stack and exit */ + + (*stack_ptr) = temp_node; + break; + + + case AML_LOCAL_OP: + case AML_ARG_OP: + + /* + * Get the local from the method's state info + * Note: this increments the local's object reference count + */ + status = acpi_ds_method_data_get_value (opcode, + stack_desc->reference.offset, walk_state, &obj_desc); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * Now we can delete the original Reference Object and + * replace it with the resolve value + */ + acpi_ut_remove_reference (stack_desc); + *stack_ptr = obj_desc; + + break; + + + /* + * TBD: [Restructure] These next three opcodes change the type of + * the object, which is actually a no-no. + */ + case AML_ZERO_OP: + + stack_desc->common.type = (u8) ACPI_TYPE_INTEGER; + stack_desc->integer.value = 0; + break; + + + case AML_ONE_OP: + + stack_desc->common.type = (u8) ACPI_TYPE_INTEGER; + stack_desc->integer.value = 1; + break; + + + case AML_ONES_OP: + + stack_desc->common.type = (u8) ACPI_TYPE_INTEGER; + stack_desc->integer.value = ACPI_INTEGER_MAX; + + /* Truncate value if we are executing from a 32-bit ACPI table */ + + acpi_ex_truncate_for32bit_table (stack_desc, walk_state); + break; + + + case AML_INDEX_OP: + + switch (stack_desc->reference.target_type) { + case ACPI_TYPE_BUFFER_FIELD: + + /* Just return - leave the Reference on the stack */ + break; + + + case ACPI_TYPE_PACKAGE: + obj_desc = *stack_desc->reference.where; + if (obj_desc) { + /* + * Valid obj descriptor, copy pointer to return value + * (i.e., dereference the package index) + * Delete the ref object, increment the returned object + */ + acpi_ut_remove_reference (stack_desc); + acpi_ut_add_reference (obj_desc); + *stack_ptr = obj_desc; + } + + else { + /* + * A NULL object descriptor means an unitialized element of + * the package, can't dereference it + */ + status = AE_AML_UNINITIALIZED_ELEMENT; + } + break; + + default: + /* Invalid reference object */ + + status = AE_AML_INTERNAL; + break; + } + + break; + + + case AML_DEBUG_OP: + + /* Just leave the object as-is */ + break; + + + default: + + status = AE_AML_INTERNAL; + break; + + } /* switch (Opcode) */ + + break; /* case INTERNAL_TYPE_REFERENCE */ + + + case ACPI_TYPE_BUFFER_FIELD: + + obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_ANY); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + status = acpi_ex_get_buffer_field_value (stack_desc, obj_desc); + if (ACPI_FAILURE (status)) { + acpi_ut_remove_reference (obj_desc); + obj_desc = NULL; + } + + *stack_ptr = (void *) obj_desc; + break; + + + case INTERNAL_TYPE_BANK_FIELD: + + obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_ANY); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + /* TBD: WRONG! */ + + status = acpi_ex_get_buffer_field_value (stack_desc, obj_desc); + if (ACPI_FAILURE (status)) { + acpi_ut_remove_reference (obj_desc); + obj_desc = NULL; + } + + *stack_ptr = (void *) obj_desc; + break; + + + /* TBD: [Future] - may need to handle Index_field, and Def_field someday */ + + default: + + break; + + } /* switch (Stack_desc->Common.Type) */ + + + return (status); +} + + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/executer/exresop.c linux/drivers/acpi/executer/exresop.c --- v2.4.5/linux/drivers/acpi/executer/exresop.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/executer/exresop.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,480 @@ + +/****************************************************************************** + * + * Module Name: exresop - AML Interpreter operand/object resolution + * $Revision: 29 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "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 + MODULE_NAME ("exresop") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_check_object_type + * + * PARAMETERS: Type_needed Object type needed + * This_type Actual object type + * Object Object pointer + * + * RETURN: Status + * + * DESCRIPTION: Check required type against actual type + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_check_object_type ( + ACPI_OBJECT_TYPE type_needed, + ACPI_OBJECT_TYPE this_type, + void *object) +{ + + + if (type_needed == ACPI_TYPE_ANY) { + /* All types OK, so we don't perform any typechecks */ + + return (AE_OK); + } + + if (type_needed != this_type) { + return (AE_AML_OPERAND_TYPE); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_resolve_operands + * + * PARAMETERS: Opcode Opcode being interpreted + * Stack_ptr Top of operand stack + * + * RETURN: Status + * + * DESCRIPTION: Convert stack entries to required types + * + * Each nibble in Arg_types represents one required operand + * and indicates the required Type: + * + * The corresponding stack entry will be converted to the + * required type if possible, else return an exception + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_resolve_operands ( + u16 opcode, + ACPI_OPERAND_OBJECT **stack_ptr, + ACPI_WALK_STATE *walk_state) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_STATUS status = AE_OK; + u8 object_type; + void *temp_node; + u32 arg_types; + ACPI_OPCODE_INFO *op_info; + u32 this_arg_type; + ACPI_OBJECT_TYPE type_needed; + + + op_info = acpi_ps_get_opcode_info (opcode); + if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) { + return (AE_AML_BAD_OPCODE); + } + + + arg_types = op_info->runtime_args; + if (arg_types == ARGI_INVALID_OPCODE) { + return (AE_AML_INTERNAL); + } + + + /* + * Normal exit is with (Arg_types == 0) at end of argument list. + * Function will return an exception from within the loop upon + * finding an entry which is not (or cannot be converted + * to) the required type; if stack underflows; or upon + * finding a NULL stack entry (which should not happen). + */ + + while (GET_CURRENT_ARG_TYPE (arg_types)) { + if (!stack_ptr || !*stack_ptr) { + return (AE_AML_INTERNAL); + } + + /* Extract useful items */ + + obj_desc = *stack_ptr; + + /* Decode the descriptor type */ + + if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { + /* Node */ + + object_type = ((ACPI_NAMESPACE_NODE *) obj_desc)->type; + } + + else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_INTERNAL)) { + /* ACPI internal object */ + + object_type = obj_desc->common.type; + + /* Check for bad ACPI_OBJECT_TYPE */ + + if (!acpi_ex_validate_object_type (object_type)) { + return (AE_AML_OPERAND_TYPE); + } + + if (object_type == (u8) INTERNAL_TYPE_REFERENCE) { + /* + * Decode the Reference + */ + + op_info = acpi_ps_get_opcode_info (opcode); + if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) { + return (AE_AML_BAD_OPCODE); + } + + + switch (obj_desc->reference.opcode) { + case AML_ZERO_OP: + case AML_ONE_OP: + case AML_ONES_OP: + case AML_DEBUG_OP: + case AML_NAME_OP: + case AML_INDEX_OP: + case AML_ARG_OP: + case AML_LOCAL_OP: + + break; + + default: + return (AE_AML_OPERAND_TYPE); + break; + } + } + } + + else { + /* Invalid descriptor */ + + return (AE_AML_OPERAND_TYPE); + } + + + /* + * Get one argument type, point to the next + */ + + this_arg_type = GET_CURRENT_ARG_TYPE (arg_types); + INCREMENT_ARG_LIST (arg_types); + + + /* + * Handle cases where the object does not need to be + * resolved to a value + */ + + switch (this_arg_type) { + + case ARGI_REFERENCE: /* References */ + case ARGI_INTEGER_REF: + case ARGI_OBJECT_REF: + case ARGI_DEVICE_REF: + case ARGI_TARGETREF: /* TBD: must implement implicit conversion rules before store */ + case ARGI_FIXED_TARGET: /* No implicit conversion before store to target */ + case ARGI_SIMPLE_TARGET: /* Name, Local, or Arg - no implicit conversion */ + + /* Need an operand of type INTERNAL_TYPE_REFERENCE */ + + if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) /* direct name ptr OK as-is */ { + goto next_operand; + } + + status = acpi_ex_check_object_type (INTERNAL_TYPE_REFERENCE, + object_type, obj_desc); + if (ACPI_FAILURE (status)) { + return (status); + } + + + if (AML_NAME_OP == obj_desc->reference.opcode) { + /* + * Convert an indirect name ptr to direct name ptr and put + * it on the stack + */ + + temp_node = obj_desc->reference.object; + acpi_ut_remove_reference (obj_desc); + (*stack_ptr) = temp_node; + } + + goto next_operand; + break; + + + case ARGI_ANYTYPE: + + /* + * We don't want to resolve Index_op reference objects during + * a store because this would be an implicit De_ref_of operation. + * Instead, we just want to store the reference object. + * -- All others must be resolved below. + */ + + if ((opcode == AML_STORE_OP) && + ((*stack_ptr)->common.type == INTERNAL_TYPE_REFERENCE) && + ((*stack_ptr)->reference.opcode == AML_INDEX_OP)) { + goto next_operand; + } + break; + } + + + /* + * Resolve this object to a value + */ + + status = acpi_ex_resolve_to_value (stack_ptr, walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + + /* + * Check the resulting object (value) type + */ + switch (this_arg_type) { + /* + * For the simple cases, only one type of resolved object + * is allowed + */ + case ARGI_MUTEX: + + /* Need an operand of type ACPI_TYPE_MUTEX */ + + type_needed = ACPI_TYPE_MUTEX; + break; + + case ARGI_EVENT: + + /* Need an operand of type ACPI_TYPE_EVENT */ + + type_needed = ACPI_TYPE_EVENT; + break; + + case ARGI_REGION: + + /* Need an operand of type ACPI_TYPE_REGION */ + + type_needed = ACPI_TYPE_REGION; + break; + + case ARGI_IF: /* If */ + + /* Need an operand of type INTERNAL_TYPE_IF */ + + type_needed = INTERNAL_TYPE_IF; + break; + + case ARGI_PACKAGE: /* Package */ + + /* Need an operand of type ACPI_TYPE_PACKAGE */ + + type_needed = ACPI_TYPE_PACKAGE; + break; + + case ARGI_ANYTYPE: + + /* Any operand type will do */ + + type_needed = ACPI_TYPE_ANY; + break; + + + /* + * The more complex cases allow multiple resolved object types + */ + + case ARGI_INTEGER: /* Number */ + + /* + * Need an operand of type ACPI_TYPE_INTEGER, + * But we can implicitly convert from a STRING or BUFFER + */ + status = acpi_ex_convert_to_integer (stack_ptr, walk_state); + if (ACPI_FAILURE (status)) { + if (status == AE_TYPE) { + return (AE_AML_OPERAND_TYPE); + } + + return (status); + } + + goto next_operand; + break; + + + case ARGI_BUFFER: + + /* + * Need an operand of type ACPI_TYPE_BUFFER, + * But we can implicitly convert from a STRING or INTEGER + */ + status = acpi_ex_convert_to_buffer (stack_ptr, walk_state); + if (ACPI_FAILURE (status)) { + if (status == AE_TYPE) { + return (AE_AML_OPERAND_TYPE); + } + + return (status); + } + + goto next_operand; + break; + + + case ARGI_STRING: + + /* + * Need an operand of type ACPI_TYPE_STRING, + * But we can implicitly convert from a BUFFER or INTEGER + */ + status = acpi_ex_convert_to_string (stack_ptr, walk_state); + if (ACPI_FAILURE (status)) { + if (status == AE_TYPE) { + return (AE_AML_OPERAND_TYPE); + } + + return (status); + } + + goto next_operand; + break; + + + case ARGI_COMPUTEDATA: + + /* Need an operand of type INTEGER, STRING or BUFFER */ + + if ((ACPI_TYPE_INTEGER != (*stack_ptr)->common.type) && + (ACPI_TYPE_STRING != (*stack_ptr)->common.type) && + (ACPI_TYPE_BUFFER != (*stack_ptr)->common.type)) { + return (AE_AML_OPERAND_TYPE); + } + goto next_operand; + break; + + + case ARGI_DATAOBJECT: + /* + * ARGI_DATAOBJECT is only used by the Size_of operator. + * + * The ACPI specification allows Size_of to return the size of + * a Buffer, String or Package. However, the MS ACPI.SYS AML + * Interpreter also allows an Node reference to return without + * error with a size of 4. + */ + + /* Need a buffer, string, package or Node reference */ + + if (((*stack_ptr)->common.type != ACPI_TYPE_BUFFER) && + ((*stack_ptr)->common.type != ACPI_TYPE_STRING) && + ((*stack_ptr)->common.type != ACPI_TYPE_PACKAGE) && + ((*stack_ptr)->common.type != INTERNAL_TYPE_REFERENCE)) { + return (AE_AML_OPERAND_TYPE); + } + + /* + * If this is a reference, only allow a reference to an Node. + */ + if ((*stack_ptr)->common.type == INTERNAL_TYPE_REFERENCE) { + if (!(*stack_ptr)->reference.node) { + return (AE_AML_OPERAND_TYPE); + } + } + goto next_operand; + break; + + + case ARGI_COMPLEXOBJ: + + /* Need a buffer or package or (ACPI 2.0) String */ + + if (((*stack_ptr)->common.type != ACPI_TYPE_BUFFER) && + ((*stack_ptr)->common.type != ACPI_TYPE_STRING) && + ((*stack_ptr)->common.type != ACPI_TYPE_PACKAGE)) { + return (AE_AML_OPERAND_TYPE); + } + goto next_operand; + break; + + + default: + + /* Unknown type */ + + return (AE_BAD_PARAMETER); + } + + + /* + * Make sure that the original object was resolved to the + * required object type (Simple cases only). + */ + status = acpi_ex_check_object_type (type_needed, + (*stack_ptr)->common.type, *stack_ptr); + if (ACPI_FAILURE (status)) { + return (status); + } + + +next_operand: + /* + * If more operands needed, decrement Stack_ptr to point + * to next operand on stack + */ + if (GET_CURRENT_ARG_TYPE (arg_types)) { + stack_ptr--; + } + + } /* while (*Types) */ + + + return (status); +} + + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/executer/exstore.c linux/drivers/acpi/executer/exstore.c --- v2.4.5/linux/drivers/acpi/executer/exstore.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/executer/exstore.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,600 @@ + +/****************************************************************************** + * + * Module Name: exstore - AML Interpreter object store support + * $Revision: 139 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acparser.h" +#include "acdispat.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "actables.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("exstore") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_store + * + * PARAMETERS: *Val_desc - Value to be stored + * *Dest_desc - Where to store it. Must be an NS node + * or an ACPI_OPERAND_OBJECT of type + * Reference; if the latter the descriptor + * will be either reused or deleted. + * + * RETURN: Status + * + * DESCRIPTION: Store the value described by Val_desc into the location + * described by Dest_desc. Called by various interpreter + * functions to store the result of an operation into + * the destination operand. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_store ( + ACPI_OPERAND_OBJECT *val_desc, + ACPI_OPERAND_OBJECT *dest_desc, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status = AE_OK; + ACPI_OPERAND_OBJECT *ref_desc = dest_desc; + + + /* Validate parameters */ + + if (!val_desc || !dest_desc) { + return (AE_AML_NO_OPERAND); + } + + /* Dest_desc can be either a namespace node or an ACPI object */ + + if (VALID_DESCRIPTOR_TYPE (dest_desc, ACPI_DESC_TYPE_NAMED)) { + /* + * Dest is a namespace node, + * Storing an object into a Name "container" + */ + status = acpi_ex_store_object_to_node (val_desc, + (ACPI_NAMESPACE_NODE *) dest_desc, walk_state); + + /* All done, that's it */ + + return (status); + } + + + /* Destination object must be an object of type Reference */ + + if (dest_desc->common.type != INTERNAL_TYPE_REFERENCE) { + /* Destination is not an Reference */ + + return (AE_AML_OPERAND_TYPE); + } + + + /* + * Examine the Reference opcode. These cases are handled: + * + * 1) Store to Name (Change the object associated with a name) + * 2) Store to an indexed area of a Buffer or Package + * 3) Store to a Method Local or Arg + * 4) Store to the debug object + * 5) Store to a constant -- a noop + */ + + switch (ref_desc->reference.opcode) { + + case AML_NAME_OP: + + /* Storing an object into a Name "container" */ + + status = acpi_ex_store_object_to_node (val_desc, ref_desc->reference.object, + walk_state); + break; + + + case AML_INDEX_OP: + + /* Storing to an Index (pointer into a packager or buffer) */ + + status = acpi_ex_store_object_to_index (val_desc, ref_desc, walk_state); + break; + + + case AML_LOCAL_OP: + case AML_ARG_OP: + + /* Store to a method local/arg */ + + status = acpi_ds_store_object_to_local (ref_desc->reference.opcode, + ref_desc->reference.offset, val_desc, walk_state); + break; + + + case AML_DEBUG_OP: + + /* + * Storing to the Debug object causes the value stored to be + * displayed and otherwise has no effect -- see ACPI Specification + */ + switch (val_desc->common.type) { + case ACPI_TYPE_INTEGER: + + break; + + + case ACPI_TYPE_BUFFER: + + break; + + + case ACPI_TYPE_STRING: + + break; + + + case ACPI_TYPE_PACKAGE: + + break; + + + default: + + break; + } + + break; + + + case AML_ZERO_OP: + case AML_ONE_OP: + case AML_ONES_OP: + + /* + * Storing to a constant is a no-op -- see ACPI Specification + * Delete the reference descriptor, however + */ + break; + + + default: + + /* TBD: [Restructure] use object dump routine !! */ + + status = AE_AML_INTERNAL; + break; + + } /* switch (Ref_desc->Reference.Opcode) */ + + + /* Always delete the reference descriptor object */ + + if (ref_desc) { + acpi_ut_remove_reference (ref_desc); + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_store_object_to_index + * + * PARAMETERS: *Val_desc - Value to be stored + * *Node - Named object to receive the value + * + * RETURN: Status + * + * DESCRIPTION: Store the object to the named object. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_store_object_to_index ( + ACPI_OPERAND_OBJECT *val_desc, + ACPI_OPERAND_OBJECT *dest_desc, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status = AE_OK; + ACPI_OPERAND_OBJECT *obj_desc; + u32 length; + u32 i; + u8 value = 0; + + + /* + * Destination must be a reference pointer, and + * must point to either a buffer or a package + */ + + switch (dest_desc->reference.target_type) { + case ACPI_TYPE_PACKAGE: + /* + * Storing to a package element is not simple. The source must be + * evaluated and converted to the type of the destination and then the + * source is copied into the destination - we can't just point to the + * source object. + */ + if (dest_desc->reference.target_type == ACPI_TYPE_PACKAGE) { + /* + * The object at *(Dest_desc->Reference.Where) is the + * element within the package that is to be modified. + */ + obj_desc = *(dest_desc->reference.where); + if (obj_desc) { + /* + * If the Destination element is a package, we will delete + * that object and construct a new one. + * + * TBD: [Investigate] Should both the src and dest be required + * to be packages? + * && (Val_desc->Common.Type == ACPI_TYPE_PACKAGE) + */ + if (obj_desc->common.type == ACPI_TYPE_PACKAGE) { + /* + * Take away the reference for being part of a package and + * delete + */ + acpi_ut_remove_reference (obj_desc); + acpi_ut_remove_reference (obj_desc); + + obj_desc = NULL; + } + } + + if (!obj_desc) { + /* + * If the Obj_desc is NULL, it means that an uninitialized package + * element has been used as a destination (this is OK), therefore, + * we must create the destination element to match the type of the + * source element NOTE: Val_desc can be of any type. + */ + obj_desc = acpi_ut_create_internal_object (val_desc->common.type); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + /* + * If the source is a package, copy the source to the new dest + */ + if (ACPI_TYPE_PACKAGE == obj_desc->common.type) { + status = acpi_ut_copy_ipackage_to_ipackage (val_desc, obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + acpi_ut_remove_reference (obj_desc); + return (status); + } + } + + /* + * Install the new descriptor into the package and add a + * reference to the newly created descriptor for now being + * part of the parent package + */ + + *(dest_desc->reference.where) = obj_desc; + acpi_ut_add_reference (obj_desc); + } + + if (ACPI_TYPE_PACKAGE != obj_desc->common.type) { + /* + * The destination element is not a package, so we need to + * convert the contents of the source (Val_desc) and copy into + * the destination (Obj_desc) + */ + status = acpi_ex_store_object_to_object (val_desc, obj_desc, + walk_state); + if (ACPI_FAILURE (status)) { + /* + * An error occurrered when copying the internal object + * so delete the reference. + */ + return (AE_AML_OPERAND_TYPE); + } + } + } + break; + + + case ACPI_TYPE_BUFFER_FIELD: + + + /* TBD: can probably call the generic Buffer/Field routines */ + + /* + * Storing into a buffer at a location defined by an Index. + * + * Each 8-bit element of the source object is written to the + * 8-bit Buffer Field of the Index destination object. + */ + + /* + * Set the Obj_desc to the destination object and type check. + */ + obj_desc = dest_desc->reference.object; + if (obj_desc->common.type != ACPI_TYPE_BUFFER) { + return (AE_AML_OPERAND_TYPE); + } + + /* + * The assignment of the individual elements will be slightly + * different for each source type. + */ + + switch (val_desc->common.type) { + case ACPI_TYPE_INTEGER: + /* + * Type is Integer, assign bytewise + * This loop to assign each of the elements is somewhat + * backward because of the Big Endian-ness of IA-64 + */ + length = sizeof (ACPI_INTEGER); + for (i = length; i != 0; i--) { + value = (u8)(val_desc->integer.value >> (MUL_8 (i - 1))); + obj_desc->buffer.pointer[dest_desc->reference.offset] = value; + } + break; + + + case ACPI_TYPE_BUFFER: + /* + * Type is Buffer, the Length is in the structure. + * Just loop through the elements and assign each one in turn. + */ + length = val_desc->buffer.length; + for (i = 0; i < length; i++) { + value = *(val_desc->buffer.pointer + i); + obj_desc->buffer.pointer[dest_desc->reference.offset] = value; + } + break; + + + case ACPI_TYPE_STRING: + /* + * Type is String, the Length is in the structure. + * Just loop through the elements and assign each one in turn. + */ + length = val_desc->string.length; + for (i = 0; i < length; i++) { + value = *(val_desc->string.pointer + i); + obj_desc->buffer.pointer[dest_desc->reference.offset] = value; + } + break; + + + default: + + /* Other types are invalid */ + + status = AE_AML_OPERAND_TYPE; + break; + } + break; + + + default: + status = AE_AML_OPERAND_TYPE; + break; + } + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_store_object_to_node + * + * PARAMETERS: *Source_desc - Value to be stored + * *Node - Named object to receive the value + * + * RETURN: Status + * + * DESCRIPTION: Store the object to the named object. + * + * The Assignment of an object to a named object is handled here + * The val passed in will replace the current value (if any) + * with the input value. + * + * When storing into an object the data is converted to the + * target object type then stored in the object. This means + * that the target object type (for an initialized target) will + * not be changed by a store operation. + * + * NOTE: the global lock is acquired early. This will result + * in the global lock being held a bit longer. Also, if the + * function fails during set up we may get the lock when we + * don't really need it. I don't think we care. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_store_object_to_node ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_NAMESPACE_NODE *node, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status = AE_OK; + ACPI_OPERAND_OBJECT *target_desc; + ACPI_OBJECT_TYPE8 target_type = ACPI_TYPE_ANY; + + + /* + * Assuming the parameters were already validated + */ + ACPI_ASSERT((node) && (source_desc)); + + + /* + * Get current type of the node, and object attached to Node + */ + target_type = acpi_ns_get_type (node); + target_desc = acpi_ns_get_attached_object (node); + + + /* + * Resolve the source object to an actual value + * (If it is a reference object) + */ + status = acpi_ex_resolve_object (&source_desc, target_type, walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + + /* + * Do the actual store operation + */ + switch (target_type) { + case ACPI_TYPE_BUFFER_FIELD: + case INTERNAL_TYPE_REGION_FIELD: + case INTERNAL_TYPE_BANK_FIELD: + case INTERNAL_TYPE_INDEX_FIELD: + + /* + * For fields, copy the source data to the target field. + */ + status = acpi_ex_write_data_to_field (source_desc, target_desc); + break; + + + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + + /* + * These target types are all of type Integer/String/Buffer, and + * therefore support implicit conversion before the store. + * + * Copy and/or convert the source object to a new target object + */ + status = acpi_ex_store_object (source_desc, target_type, &target_desc, walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * Store the new Target_desc as the new value of the Name, and set + * the Name's type to that of the value being stored in it. + * Source_desc reference count is incremented by Attach_object. + */ + status = acpi_ns_attach_object (node, target_desc, target_type); + break; + + + default: + + /* No conversions for all other types. Just attach the source object */ + + status = acpi_ns_attach_object (node, source_desc, source_desc->common.type); + + break; + } + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_store_object_to_object + * + * PARAMETERS: *Source_desc - Value to be stored + * *Dest_desc - Object to receive the value + * + * RETURN: Status + * + * DESCRIPTION: Store an object to another object. + * + * The Assignment of an object to another (not named) object + * is handled here. + * The val passed in will replace the current value (if any) + * with the input value. + * + * When storing into an object the data is converted to the + * target object type then stored in the object. This means + * that the target object type (for an initialized target) will + * not be changed by a store operation. + * + * This module allows destination types of Number, String, + * and Buffer. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_store_object_to_object ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OPERAND_OBJECT *dest_desc, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status = AE_OK; + ACPI_OBJECT_TYPE8 destination_type = dest_desc->common.type; + + + /* + * Assuming the parameters are valid! + */ + ACPI_ASSERT((dest_desc) && (source_desc)); + + + /* + * From this interface, we only support Integers/Strings/Buffers + */ + switch (destination_type) { + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + break; + + default: + return (AE_NOT_IMPLEMENTED); + } + + + /* + * Resolve the source object to an actual value + * (If it is a reference object) + */ + status = acpi_ex_resolve_object (&source_desc, destination_type, walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + + /* + * Copy and/or convert the source object to the destination object + */ + status = acpi_ex_store_object (source_desc, destination_type, &dest_desc, walk_state); + + + return (status); +} + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/executer/exstoren.c linux/drivers/acpi/executer/exstoren.c --- v2.4.5/linux/drivers/acpi/executer/exstoren.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/executer/exstoren.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,241 @@ + +/****************************************************************************** + * + * Module Name: exstoren - AML Interpreter object store support, + * Store to Node (namespace object) + * $Revision: 38 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acparser.h" +#include "acdispat.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "actables.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("exstoren") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_resolve_object + * + * PARAMETERS: Source_desc_ptr - Pointer to the source object + * Target_type - Current type of the target + * Walk_state - Current walk state + * + * RETURN: Status, resolved object in Source_desc_ptr. + * + * DESCRIPTION: Resolve an object. If the object is a reference, dereference + * it and return the actual object in the Source_desc_ptr. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_resolve_object ( + ACPI_OPERAND_OBJECT **source_desc_ptr, + ACPI_OBJECT_TYPE8 target_type, + ACPI_WALK_STATE *walk_state) +{ + ACPI_OPERAND_OBJECT *source_desc = *source_desc_ptr; + ACPI_STATUS status = AE_OK; + + + /* + * Ensure we have a Source that can be stored in the target + */ + switch (target_type) { + + /* This case handles the "interchangeable" types Integer, String, and Buffer. */ + + /* + * These cases all require only Integers or values that + * can be converted to Integers (Strings or Buffers) + */ + case ACPI_TYPE_BUFFER_FIELD: + case INTERNAL_TYPE_REGION_FIELD: + case INTERNAL_TYPE_BANK_FIELD: + case INTERNAL_TYPE_INDEX_FIELD: + + /* + * Stores into a Field/Region or into a Buffer/String + * are all essentially the same. + */ + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + + + /* TBD: FIX - check for source==REF, resolve, then check type */ + + /* + * If Source_desc is not a valid type, try to resolve it to one. + */ + if ((source_desc->common.type != ACPI_TYPE_INTEGER) && + (source_desc->common.type != ACPI_TYPE_BUFFER) && + (source_desc->common.type != ACPI_TYPE_STRING)) { + /* + * Initially not a valid type, convert + */ + status = acpi_ex_resolve_to_value (source_desc_ptr, walk_state); + if (ACPI_SUCCESS (status) && + (source_desc->common.type != ACPI_TYPE_INTEGER) && + (source_desc->common.type != ACPI_TYPE_BUFFER) && + (source_desc->common.type != ACPI_TYPE_STRING)) { + /* + * Conversion successful but still not a valid type + */ + status = AE_AML_OPERAND_TYPE; + } + } + break; + + + case INTERNAL_TYPE_ALIAS: + + /* + * Aliases are resolved by Acpi_ex_prep_operands + */ + status = AE_AML_INTERNAL; + break; + + + case ACPI_TYPE_PACKAGE: + default: + + /* + * All other types than Alias and the various Fields come here, + * including the untyped case - ACPI_TYPE_ANY. + */ + break; + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_store_object + * + * PARAMETERS: Source_desc - Object to store + * Target_type - Current type of the target + * Target_desc_ptr - Pointer to the target + * Walk_state - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: "Store" an object to another object. This may include + * converting the source type to the target type (implicit + * conversion), and a copy of the value of the source to + * the target. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_store_object ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OBJECT_TYPE8 target_type, + ACPI_OPERAND_OBJECT **target_desc_ptr, + ACPI_WALK_STATE *walk_state) +{ + ACPI_OPERAND_OBJECT *target_desc = *target_desc_ptr; + ACPI_STATUS status = AE_OK; + + + /* + * Perform the "implicit conversion" of the source to the current type + * of the target - As per the ACPI specification. + * + * If no conversion performed, Source_desc is left alone, otherwise it + * is updated with a new object. + */ + status = acpi_ex_convert_to_target_type (target_type, &source_desc, walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * We now have two objects of identical types, and we can perform a + * copy of the *value* of the source object. + */ + switch (target_type) { + case ACPI_TYPE_ANY: + case INTERNAL_TYPE_DEF_ANY: + + /* + * The target namespace node is uninitialized (has no target object), + * and will take on the type of the source object + */ + + *target_desc_ptr = source_desc; + break; + + + case ACPI_TYPE_INTEGER: + + target_desc->integer.value = source_desc->integer.value; + + /* Truncate value if we are executing from a 32-bit ACPI table */ + + acpi_ex_truncate_for32bit_table (target_desc, walk_state); + break; + + case ACPI_TYPE_STRING: + + status = acpi_ex_copy_string_to_string (source_desc, target_desc); + break; + + + case ACPI_TYPE_BUFFER: + + status = acpi_ex_copy_buffer_to_buffer (source_desc, target_desc); + break; + + + case ACPI_TYPE_PACKAGE: + + /* + * TBD: [Unhandled] Not real sure what to do here + */ + status = AE_NOT_IMPLEMENTED; + break; + + + default: + + /* + * All other types come here. + */ + status = AE_NOT_IMPLEMENTED; + break; + } + + + return (status); +} + + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/executer/exstorob.c linux/drivers/acpi/executer/exstorob.c --- v2.4.5/linux/drivers/acpi/executer/exstorob.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/executer/exstorob.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,169 @@ + +/****************************************************************************** + * + * Module Name: exstorob - AML Interpreter object store support, store to object + * $Revision: 32 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acparser.h" +#include "acdispat.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "actables.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("exstorob") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_copy_buffer_to_buffer + * + * PARAMETERS: Source_desc - Source object to copy + * Target_desc - Destination object of the copy + * + * RETURN: Status + * + * DESCRIPTION: Copy a buffer object to another buffer object. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_copy_buffer_to_buffer ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OPERAND_OBJECT *target_desc) +{ + u32 length; + u8 *buffer; + + + /* + * We know that Source_desc is a buffer by now + */ + buffer = (u8 *) source_desc->buffer.pointer; + length = source_desc->buffer.length; + + /* + * If target is a buffer of length zero, allocate a new + * buffer of the proper length + */ + if (target_desc->buffer.length == 0) { + target_desc->buffer.pointer = acpi_ut_allocate (length); + if (!target_desc->buffer.pointer) { + return (AE_NO_MEMORY); + } + + target_desc->buffer.length = length; + } + + /* + * Buffer is a static allocation, + * only place what will fit in the buffer. + */ + if (length <= target_desc->buffer.length) { + /* Clear existing buffer and copy in the new one */ + + MEMSET(target_desc->buffer.pointer, 0, target_desc->buffer.length); + MEMCPY(target_desc->buffer.pointer, buffer, length); + } + + else { + /* + * Truncate the source, copy only what will fit + */ + MEMCPY(target_desc->buffer.pointer, buffer, target_desc->buffer.length); + + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_copy_string_to_string + * + * PARAMETERS: Source_desc - Source object to copy + * Target_desc - Destination object of the copy + * + * RETURN: Status + * + * DESCRIPTION: Copy a String object to another String object + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_copy_string_to_string ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OPERAND_OBJECT *target_desc) +{ + u32 length; + u8 *buffer; + + + /* + * We know that Source_desc is a string by now. + */ + buffer = (u8 *) source_desc->string.pointer; + length = source_desc->string.length; + + /* + * Setting a string value replaces the old string + */ + if (length < target_desc->string.length) { + /* Clear old string and copy in the new one */ + + MEMSET(target_desc->string.pointer, 0, target_desc->string.length); + MEMCPY(target_desc->string.pointer, buffer, length); + } + + else { + /* + * Free the current buffer, then allocate a buffer + * large enough to hold the value + */ + if (target_desc->string.pointer && + !acpi_tb_system_table_pointer (target_desc->string.pointer)) { + /* + * Only free if not a pointer into the DSDT + */ + acpi_ut_free(target_desc->string.pointer); + } + + target_desc->string.pointer = acpi_ut_allocate (length + 1); + if (!target_desc->string.pointer) { + return (AE_NO_MEMORY); + } + target_desc->string.length = length; + + + MEMCPY(target_desc->string.pointer, buffer, length); + } + + return (AE_OK); +} + + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/executer/exsystem.c linux/drivers/acpi/executer/exsystem.c --- v2.4.5/linux/drivers/acpi/executer/exsystem.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/executer/exsystem.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,326 @@ + +/****************************************************************************** + * + * Module Name: exsystem - Interface to OS services + * $Revision: 62 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "achware.h" +#include "acevents.h" + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("exsystem") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_system_wait_semaphore + * + * PARAMETERS: Semaphore - OSD semaphore to wait on + * Timeout - Max time to wait + * + * RETURN: Status + * + * DESCRIPTION: Implements a semaphore wait with a check to see if the + * semaphore is available immediately. If it is not, the + * interpreter is released. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_system_wait_semaphore ( + ACPI_HANDLE semaphore, + u32 timeout) +{ + ACPI_STATUS status; + + + status = acpi_os_wait_semaphore (semaphore, 1, 0); + if (ACPI_SUCCESS (status)) { + return (status); + } + + if (status == AE_TIME) { + /* We must wait, so unlock the interpreter */ + + acpi_ex_exit_interpreter (); + + status = acpi_os_wait_semaphore (semaphore, 1, timeout); + + /* Reacquire the interpreter */ + + status = acpi_ex_enter_interpreter (); + if (ACPI_SUCCESS (status)) { + /* Restore the timeout exception */ + + status = AE_TIME; + } + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_system_do_stall + * + * PARAMETERS: How_long - The amount of time to stall + * + * RETURN: None + * + * DESCRIPTION: Suspend running thread for specified amount of time. + * + ******************************************************************************/ + +void +acpi_ex_system_do_stall ( + u32 how_long) +{ + + if (how_long > 1000) /* 1 millisecond */ { + /* Since this thread will sleep, we must release the interpreter */ + + acpi_ex_exit_interpreter (); + + acpi_os_sleep_usec (how_long); + + /* And now we must get the interpreter again */ + + acpi_ex_enter_interpreter (); + } + + else { + acpi_os_sleep_usec (how_long); + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_system_do_suspend + * + * PARAMETERS: How_long - The amount of time to suspend + * + * RETURN: None + * + * DESCRIPTION: Suspend running thread for specified amount of time. + * + ******************************************************************************/ + +void +acpi_ex_system_do_suspend ( + u32 how_long) +{ + /* Since this thread will sleep, we must release the interpreter */ + + acpi_ex_exit_interpreter (); + + acpi_os_sleep ((u16) (how_long / (u32) 1000), + (u16) (how_long % (u32) 1000)); + + /* And now we must get the interpreter again */ + + acpi_ex_enter_interpreter (); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_system_acquire_mutex + * + * PARAMETERS: *Time_desc - The 'time to delay' object descriptor + * *Obj_desc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Provides an access point to perform synchronization operations + * within the AML. This function will cause a lock to be generated + * for the Mutex pointed to by Obj_desc. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_system_acquire_mutex ( + ACPI_OPERAND_OBJECT *time_desc, + ACPI_OPERAND_OBJECT *obj_desc) +{ + ACPI_STATUS status = AE_OK; + + + if (!obj_desc) { + return (AE_BAD_PARAMETER); + } + + /* + * Support for the _GL_ Mutex object -- go get the global lock + */ + + if (obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore) { + status = acpi_ev_acquire_global_lock (); + return (status); + } + + status = acpi_ex_system_wait_semaphore (obj_desc->mutex.semaphore, + (u32) time_desc->integer.value); + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_system_release_mutex + * + * PARAMETERS: *Obj_desc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Provides an access point to perform synchronization operations + * within the AML. This operation is a request to release a + * previously acquired Mutex. If the Mutex variable is set then + * it will be decremented. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_system_release_mutex ( + ACPI_OPERAND_OBJECT *obj_desc) +{ + ACPI_STATUS status = AE_OK; + + + if (!obj_desc) { + return (AE_BAD_PARAMETER); + } + + /* + * 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 (AE_OK); + } + + status = acpi_os_signal_semaphore (obj_desc->mutex.semaphore, 1); + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_system_signal_event + * + * PARAMETERS: *Obj_desc - The object descriptor for this op + * + * RETURN: AE_OK + * + * DESCRIPTION: Provides an access point to perform synchronization operations + * within the AML. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_system_signal_event ( + ACPI_OPERAND_OBJECT *obj_desc) +{ + ACPI_STATUS status = AE_OK; + + + if (obj_desc) { + status = acpi_os_signal_semaphore (obj_desc->event.semaphore, 1); + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_system_wait_event + * + * PARAMETERS: *Time_desc - The 'time to delay' object descriptor + * *Obj_desc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Provides an access point to perform synchronization operations + * within the AML. This operation is a request to wait for an + * event. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_system_wait_event ( + ACPI_OPERAND_OBJECT *time_desc, + ACPI_OPERAND_OBJECT *obj_desc) +{ + ACPI_STATUS status = AE_OK; + + + if (obj_desc) { + status = acpi_ex_system_wait_semaphore (obj_desc->event.semaphore, + (u32) time_desc->integer.value); + } + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_system_reset_event + * + * PARAMETERS: *Obj_desc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Reset an event to a known state. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_system_reset_event ( + ACPI_OPERAND_OBJECT *obj_desc) +{ + ACPI_STATUS status = AE_OK; + void *temp_semaphore; + + + /* + * We are going to simply delete the existing semaphore and + * create a new one! + */ + + status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT, 0, &temp_semaphore); + if (ACPI_SUCCESS (status)) { + acpi_os_delete_semaphore (obj_desc->event.semaphore); + obj_desc->event.semaphore = temp_semaphore; + } + + return (status); +} + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/executer/exutils.c linux/drivers/acpi/executer/exutils.c --- v2.4.5/linux/drivers/acpi/executer/exutils.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/executer/exutils.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,366 @@ + +/****************************************************************************** + * + * Module Name: exutils - interpreter/scanner utilities + * $Revision: 79 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acparser.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "acevents.h" + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("exutils") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_enter_interpreter + * + * PARAMETERS: None + * + * DESCRIPTION: Enter the interpreter execution region + * TBD: should be a macro + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_enter_interpreter (void) +{ + ACPI_STATUS status; + + + status = acpi_ut_acquire_mutex (ACPI_MTX_EXECUTE); + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_exit_interpreter + * + * PARAMETERS: None + * + * DESCRIPTION: Exit the interpreter execution region + * + * Cases where the interpreter is unlocked: + * 1) Completion of the execution of a control method + * 2) Method blocked on a Sleep() AML opcode + * 3) Method blocked on an Acquire() AML opcode + * 4) Method blocked on a Wait() AML opcode + * 5) Method blocked to acquire the global lock + * 6) Method blocked to execute a serialized control method that is + * already executing + * 7) About to invoke a user-installed opregion handler + * + * TBD: should be a macro + * + ******************************************************************************/ + +void +acpi_ex_exit_interpreter (void) +{ + + acpi_ut_release_mutex (ACPI_MTX_EXECUTE); + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_validate_object_type + * + * PARAMETERS: Type Object type to validate + * + * DESCRIPTION: Determine if a type is a valid ACPI object type + * + ******************************************************************************/ + +u8 +acpi_ex_validate_object_type ( + ACPI_OBJECT_TYPE type) +{ + + if ((type > ACPI_TYPE_MAX && type < INTERNAL_TYPE_BEGIN) || + (type > INTERNAL_TYPE_MAX)) { + return (FALSE); + } + + return (TRUE); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_truncate_for32bit_table + * + * PARAMETERS: Obj_desc - Object to be truncated + * Walk_state - Current walk state + * (A method must be executing) + * + * RETURN: none + * + * DESCRIPTION: Truncate a number to 32-bits if the currently executing method + * belongs to a 32-bit ACPI table. + * + ******************************************************************************/ + +void +acpi_ex_truncate_for32bit_table ( + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_WALK_STATE *walk_state) +{ + + /* + * Object must be a valid number and we must be executing + * a control method + */ + + if ((!obj_desc) || + (obj_desc->common.type != ACPI_TYPE_INTEGER) || + (!walk_state->method_node)) { + return; + } + + 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 + */ + obj_desc->integer.value &= (ACPI_INTEGER) ACPI_UINT32_MAX; + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_acquire_global_lock + * + * PARAMETERS: Rule - Lock rule: Always_lock, Never_lock + * + * RETURN: TRUE/FALSE indicating whether the lock was actually acquired + * + * DESCRIPTION: Obtain the global lock and keep track of this fact via two + * methods. A global variable keeps the state of the lock, and + * the state is returned to the caller. + * + ******************************************************************************/ + +u8 +acpi_ex_acquire_global_lock ( + u32 rule) +{ + u8 locked = FALSE; + ACPI_STATUS status; + + + /* Only attempt lock if the Rule says so */ + + if (rule == (u32) GLOCK_ALWAYS_LOCK) { + /* We should attempt to get the lock */ + + status = acpi_ev_acquire_global_lock (); + if (ACPI_SUCCESS (status)) { + locked = TRUE; + } + + } + + return (locked); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_release_global_lock + * + * PARAMETERS: Locked_by_me - Return value from corresponding call to + * Acquire_global_lock. + * + * RETURN: Status + * + * DESCRIPTION: Release the global lock if it is locked. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_release_global_lock ( + u8 locked_by_me) +{ + + + /* Only attempt unlock if the caller locked it */ + + if (locked_by_me) { + /* OK, now release the lock */ + + acpi_ev_release_global_lock (); + } + + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_digits_needed + * + * PARAMETERS: val - Value to be represented + * base - Base of representation + * + * RETURN: the number of digits needed to represent val in base + * + ******************************************************************************/ + +u32 +acpi_ex_digits_needed ( + ACPI_INTEGER val, + u32 base) +{ + u32 num_digits = 0; + + + if (base < 1) { + REPORT_ERROR (("Ex_digits_needed: Internal error - Invalid base\n")); + } + + else { + /* + * ACPI_INTEGER is unsigned, which is why we don't worry about the '-' + */ + for (num_digits = 1; (val = ACPI_DIVIDE (val,base)); ++num_digits) { ; } + } + + return (num_digits); +} + + +/******************************************************************************* + * + * 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; + + + 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 + * Out_string - Where to put the converted string (8 bytes) + * + * DESCRIPTION: Convert a numeric EISA ID to string representation + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_eisa_id_to_string ( + u32 numeric_id, + NATIVE_CHAR *out_string) +{ + u32 id; + + /* swap to big-endian to get contiguous bits */ + + id = _ntohl (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_gbl_hex_to_ascii[(id >> 12) & 0xf]; + out_string[4] = acpi_gbl_hex_to_ascii[(id >> 8) & 0xf]; + out_string[5] = acpi_gbl_hex_to_ascii[(id >> 4) & 0xf]; + out_string[6] = acpi_gbl_hex_to_ascii[id & 0xf]; + out_string[7] = 0; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_unsigned_integer_to_string + * + * PARAMETERS: Value - Value to be converted + * Out_string - Where to put the converted string (8 bytes) + * + * RETURN: Convert a number to string representation + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_unsigned_integer_to_string ( + ACPI_INTEGER value, + NATIVE_CHAR *out_string) +{ + u32 count; + u32 digits_needed; + + + digits_needed = acpi_ex_digits_needed (value, 10); + + out_string[digits_needed] = '\0'; + + for (count = digits_needed; count > 0; count--) { + out_string[count-1] = (NATIVE_CHAR) ('0' + (ACPI_MODULO (value, 10))); + value = ACPI_DIVIDE (value, 10); + } + + return (AE_OK); +} + + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/executer/exxface.c linux/drivers/acpi/executer/exxface.c --- v2.4.5/linux/drivers/acpi/executer/exxface.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/executer/exxface.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,98 @@ + +/****************************************************************************** + * + * Module Name: exxface - External interpreter interfaces + * $Revision: 27 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acinterp.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("exxface") + + +/* + * DEFINE_AML_GLOBALS is tested in amlcode.h + * to determine whether certain global names should be "defined" or only + * "declared" in the current compilation. This enhances maintainability + * by enabling a single header file to embody all knowledge of the names + * in question. + * + * Exactly one module of any executable should #define DEFINE_GLOBALS + * before #including the header files which use this convention. The + * names in question will be defined and initialized in that module, + * and declared as extern in all other modules which #include those + * header files. + */ + +#define DEFINE_AML_GLOBALS +#include "amlcode.h" +#include "acparser.h" +#include "acnamesp.h" + + +/******************************************************************************* + * + * FUNCTION: Acpi_ex_execute_method + * + * PARAMETERS: Pcode - Pointer to the pcode stream + * Pcode_length - Length of pcode that comprises the method + * **Params - List of parameters to pass to method, + * terminated by NULL. Params itself may be + * NULL if no parameters are being passed. + * + * RETURN: Status + * + * DESCRIPTION: Execute a control method + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ex_execute_method ( + ACPI_NAMESPACE_NODE *method_node, + ACPI_OPERAND_OBJECT **params, + ACPI_OPERAND_OBJECT **return_obj_desc) +{ + ACPI_STATUS status; + + + /* + * The point here is to lock the interpreter and call the low + * level execute. + */ + + status = acpi_ex_enter_interpreter (); + if (ACPI_FAILURE (status)) { + return (status); + } + + status = acpi_psx_execute (method_node, params, return_obj_desc); + + acpi_ex_exit_interpreter (); + + return (status); +} + + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/hardware/Makefile linux/drivers/acpi/hardware/Makefile --- v2.4.5/linux/drivers/acpi/hardware/Makefile Fri Dec 29 14:07:21 2000 +++ linux/drivers/acpi/hardware/Makefile Wed Jun 20 17:47:40 2001 @@ -1,16 +1,12 @@ # # Makefile for all Linux ACPI interpreter subdirectories +# EXCEPT for the ospm directory # -O_TARGET := ../$(shell basename `pwd`).o +O_TARGET := $(notdir $(CURDIR)).o obj-$(CONFIG_ACPI) := $(patsubst %.c,%.o,$(wildcard *.c)) -EXTRA_CFLAGS += -I../include - EXTRA_CFLAGS += $(ACPI_CFLAGS) include $(TOPDIR)/Rules.make - -clean: - $(RM) *.o diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/hardware/hwacpi.c linux/drivers/acpi/hardware/hwacpi.c --- v2.4.5/linux/drivers/acpi/hardware/hwacpi.c Mon Jan 29 10:15:58 2001 +++ linux/drivers/acpi/hardware/hwacpi.c Wed Jun 20 17:47:40 2001 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: hwacpi - ACPI Hardware Initialization/Mode Interface - * $Revision: 36 $ + * $Revision: 40 $ * *****************************************************************************/ @@ -29,7 +29,7 @@ #include "achware.h" -#define _COMPONENT HARDWARE +#define _COMPONENT ACPI_HARDWARE MODULE_NAME ("hwacpi") @@ -63,7 +63,8 @@ /* Must support *some* mode! */ /* - if (!(System_flags & SYS_MODES_MASK)) { + if (!(System_flags & SYS_MODES_MASK)) + { Restore_acpi_chipset = FALSE; return (AE_ERROR); @@ -72,8 +73,7 @@ */ - switch (acpi_gbl_system_flags & SYS_MODES_MASK) - { + switch (acpi_gbl_system_flags & SYS_MODES_MASK) { /* Identify current ACPI/legacy mode */ case (SYS_MODE_ACPI): @@ -128,12 +128,11 @@ */ if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) && - acpi_gbl_FADT->gpe0blk_len) - { + acpi_gbl_FADT->gpe0blk_len) { /* GPE0 specified in FADT */ acpi_gbl_gpe0enable_register_save = - acpi_cm_allocate (DIV_2 (acpi_gbl_FADT->gpe0blk_len)); + acpi_ut_allocate (DIV_2 (acpi_gbl_FADT->gpe0blk_len)); if (!acpi_gbl_gpe0enable_register_save) { return (AE_NO_MEMORY); } @@ -151,12 +150,11 @@ } if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) && - acpi_gbl_FADT->gpe1_blk_len) - { + acpi_gbl_FADT->gpe1_blk_len) { /* GPE1 defined */ acpi_gbl_gpe1_enable_register_save = - acpi_cm_allocate (DIV_2 (acpi_gbl_FADT->gpe1_blk_len)); + acpi_ut_allocate (DIV_2 (acpi_gbl_FADT->gpe1_blk_len)); if (!acpi_gbl_gpe1_enable_register_save) { return (AE_NO_MEMORY); } @@ -196,7 +194,7 @@ u32 mode) { - ACPI_STATUS status = AE_ERROR; + ACPI_STATUS status = AE_NO_HARDWARE_RESPONSE; if (mode == SYS_MODE_ACPI) { diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/hardware/hwgpe.c linux/drivers/acpi/hardware/hwgpe.c --- v2.4.5/linux/drivers/acpi/hardware/hwgpe.c Mon Jan 29 10:15:58 2001 +++ linux/drivers/acpi/hardware/hwgpe.c Wed Jun 20 17:47:40 2001 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: hwgpe - Low level GPE enable/disable/clear functions - * $Revision: 28 $ + * $Revision: 29 $ * *****************************************************************************/ @@ -29,7 +29,7 @@ #include "acnamesp.h" #include "acevents.h" -#define _COMPONENT HARDWARE +#define _COMPONENT ACPI_HARDWARE MODULE_NAME ("hwgpe") diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/hardware/hwregs.c linux/drivers/acpi/hardware/hwregs.c --- v2.4.5/linux/drivers/acpi/hardware/hwregs.c Mon Jan 29 10:15:58 2001 +++ linux/drivers/acpi/hardware/hwregs.c Wed Jun 20 17:47:40 2001 @@ -3,7 +3,7 @@ * * Module Name: hwregs - Read/write access functions for the various ACPI * control and status registers. - * $Revision: 88 $ + * $Revision: 97 $ * ******************************************************************************/ @@ -30,7 +30,7 @@ #include "achware.h" #include "acnamesp.h" -#define _COMPONENT HARDWARE +#define _COMPONENT ACPI_HARDWARE MODULE_NAME ("hwregs") @@ -55,8 +55,7 @@ u32 acpi_hw_get_bit_shift ( - u32 mask) -{ + u32 mask) { u32 shift; @@ -85,14 +84,14 @@ u16 index; - acpi_cm_acquire_mutex (ACPI_MTX_HARDWARE); + acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE); acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, PM1_STS, ALL_FIXED_STS_BITS); if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm1b_evt_blk.address)) { acpi_os_out16 ((ACPI_IO_ADDRESS) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm1b_evt_blk.address), - (u16) ALL_FIXED_STS_BITS); + (u16) ALL_FIXED_STS_BITS); } /* now clear the GPE Bits */ @@ -101,8 +100,9 @@ gpe_length = (u16) DIV_2 (acpi_gbl_FADT->gpe0blk_len); for (index = 0; index < gpe_length; index++) { - acpi_os_out8 ((ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) + index), - (u8) 0xff); + acpi_os_out8 ((ACPI_IO_ADDRESS) ( + ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) + index), + (u8) 0xff); } } @@ -110,12 +110,13 @@ gpe_length = (u16) DIV_2 (acpi_gbl_FADT->gpe1_blk_len); for (index = 0; index < gpe_length; index++) { - acpi_os_out8 ((ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) + index), - (u8) 0xff); + acpi_os_out8 ((ACPI_IO_ADDRESS) ( + ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) + index), + (u8) 0xff); } } - acpi_cm_release_mutex (ACPI_MTX_HARDWARE); + acpi_ut_release_mutex (ACPI_MTX_HARDWARE); return; } @@ -150,8 +151,7 @@ */ if ((sleep_state > ACPI_S_STATES_MAX) || - !slp_typ_a || !slp_typ_b) - { + !slp_typ_a || !slp_typ_b) { return (AE_BAD_PARAMETER); } @@ -175,7 +175,10 @@ * two elements */ - status = acpi_cm_resolve_package_references(obj_desc); + /* Even though Acpi_evaluate_object resolves package references, + * Ns_evaluate dpesn't. So, we do it here. + */ + status = acpi_ut_resolve_package_references(obj_desc); if (obj_desc->package.count < 2) { /* Must have at least two elements */ @@ -187,8 +190,7 @@ else if (((obj_desc->package.elements[0])->common.type != ACPI_TYPE_INTEGER) || ((obj_desc->package.elements[1])->common.type != - ACPI_TYPE_INTEGER)) - { + ACPI_TYPE_INTEGER)) { /* Must have two */ REPORT_ERROR (("Sleep State package elements are not both of type Number\n")); @@ -206,7 +208,7 @@ - acpi_cm_remove_reference (obj_desc); + acpi_ut_remove_reference (obj_desc); return (status); } @@ -239,34 +241,31 @@ u32 register_value = 0; u32 mask = 0; u32 value = 0; + va_list marker; if (read_write == ACPI_WRITE) { - va_list marker; - va_start (marker, register_id); value = va_arg (marker, u32); va_end (marker); } if (ACPI_MTX_LOCK == use_lock) { - acpi_cm_acquire_mutex (ACPI_MTX_HARDWARE); + acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE); } /* * Decode the Register ID - * Register id = Register block id | bit id + * Register id = Register block id | bit id * * Check bit id to fine locate Register offset. - * check Mask to determine Register offset, and then read-write. + * Check Mask to determine Register offset, and then read-write. */ - switch (REGISTER_BLOCK_ID(register_id)) - { + switch (REGISTER_BLOCK_ID (register_id)) { case PM1_STS: - switch (register_id) - { + switch (register_id) { case TMR_STS: mask = TMR_STS_MASK; break; @@ -315,8 +314,8 @@ value &= mask; if (value) { - acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, PM1_STS, (u16) value); - + acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, PM1_STS, + (u16) value); register_value = 0; } } @@ -326,8 +325,7 @@ case PM1_EN: - switch (register_id) - { + switch (register_id) { case TMR_EN: mask = TMR_EN_MASK; break; @@ -369,8 +367,7 @@ case PM1_CONTROL: - switch (register_id) - { + switch (register_id) { case SCI_EN: mask = SCI_EN_MASK; break; @@ -421,16 +418,15 @@ * because we need to do different things. Yuck. */ - acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, - register_id, (u16) register_value); + acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, register_id, + (u16) register_value); } break; case PM2_CONTROL: - switch (register_id) - { + switch (register_id) { case ARB_DIS: mask = ARB_DIS_MASK; break; @@ -507,16 +503,18 @@ /* This write will put the Action state into the General Purpose */ /* Enable Register indexed by the value in Mask */ - acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, - register_id, (u8) register_value); - register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, register_id); + acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, register_id, + (u8) register_value); + register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, + register_id); } break; case SMI_CMD_BLOCK: case PROCESSOR_BLOCK: - /* not used */ + /* Not used by any callers at this time - therefore, not implemented */ + default: mask = 0; @@ -524,7 +522,7 @@ } if (ACPI_MTX_LOCK == use_lock) { - acpi_cm_release_mutex (ACPI_MTX_HARDWARE); + acpi_ut_release_mutex (ACPI_MTX_HARDWARE); } @@ -557,13 +555,13 @@ u32 value = 0; u32 bank_offset; + if (ACPI_MTX_LOCK == use_lock) { - acpi_cm_acquire_mutex (ACPI_MTX_HARDWARE); + acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE); } - switch (REGISTER_BLOCK_ID(register_id)) - { + switch (REGISTER_BLOCK_ID(register_id)) { case PM1_STS: /* 16-bit access */ value = acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_evt_blk, 0); @@ -637,7 +635,7 @@ if (ACPI_MTX_LOCK == use_lock) { - acpi_cm_release_mutex (ACPI_MTX_HARDWARE); + acpi_ut_release_mutex (ACPI_MTX_HARDWARE); } return (value); @@ -668,12 +666,11 @@ if (ACPI_MTX_LOCK == use_lock) { - acpi_cm_acquire_mutex (ACPI_MTX_HARDWARE); + acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE); } - switch (REGISTER_BLOCK_ID (register_id)) - { + switch (REGISTER_BLOCK_ID (register_id)) { case PM1_STS: /* 16-bit access */ acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_evt_blk, 0); @@ -751,7 +748,7 @@ /* For 2.0, SMI_CMD is always in IO space */ /* TBD: what about 1.0? 0.71? */ - acpi_os_out8 (acpi_gbl_FADT->smi_cmd, (u8) value); + acpi_os_out8 (acpi_gbl_FADT->smi_cmd, (u8) value); break; @@ -762,7 +759,7 @@ if (ACPI_MTX_LOCK == use_lock) { - acpi_cm_release_mutex (ACPI_MTX_HARDWARE); + acpi_ut_release_mutex (ACPI_MTX_HARDWARE); } return; @@ -786,7 +783,7 @@ u32 acpi_hw_low_level_read ( u32 width, - ACPI_GAS *reg, + ACPI_GENERIC_ADDRESS *reg, u32 offset) { u32 value = 0; @@ -801,8 +798,7 @@ * a non-zero address within */ if ((!reg) || - (!ACPI_VALID_ADDRESS (reg->address))) - { + (!ACPI_VALID_ADDRESS (reg->address))) { return 0; } @@ -812,14 +808,12 @@ * Memory, Io, or PCI config. */ - switch (reg->address_space_id) - { - case ADDRESS_SPACE_SYSTEM_MEMORY: + switch (reg->address_space_id) { + case ACPI_ADR_SPACE_SYSTEM_MEMORY: mem_address = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset); - switch (width) - { + switch (width) { case 8: value = acpi_os_mem_in8 (mem_address); break; @@ -833,12 +827,11 @@ break; - case ADDRESS_SPACE_SYSTEM_IO: + case ACPI_ADR_SPACE_SYSTEM_IO: io_address = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset); - switch (width) - { + switch (width) { case 8: value = acpi_os_in8 (io_address); break; @@ -852,13 +845,12 @@ break; - case ADDRESS_SPACE_PCI_CONFIG: + case ACPI_ADR_SPACE_PCI_CONFIG: pci_dev_func = ACPI_PCI_DEVFUN (ACPI_GET_ADDRESS (reg->address)); pci_register = ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (reg->address)) + offset; - switch (width) - { + switch (width) { case 8: acpi_os_read_pci_cfg_byte (0, pci_dev_func, pci_register, (u8 *) &value); break; @@ -896,7 +888,7 @@ acpi_hw_low_level_write ( u32 width, u32 value, - ACPI_GAS *reg, + ACPI_GENERIC_ADDRESS *reg, u32 offset) { ACPI_PHYSICAL_ADDRESS mem_address; @@ -910,8 +902,7 @@ * a non-zero address within */ if ((!reg) || - (!ACPI_VALID_ADDRESS (reg->address))) - { + (!ACPI_VALID_ADDRESS (reg->address))) { return; } @@ -921,14 +912,12 @@ * Memory, Io, or PCI config. */ - switch (reg->address_space_id) - { - case ADDRESS_SPACE_SYSTEM_MEMORY: + switch (reg->address_space_id) { + case ACPI_ADR_SPACE_SYSTEM_MEMORY: mem_address = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset); - switch (width) - { + switch (width) { case 8: acpi_os_mem_out8 (mem_address, (u8) value); break; @@ -942,12 +931,11 @@ break; - case ADDRESS_SPACE_SYSTEM_IO: + case ACPI_ADR_SPACE_SYSTEM_IO: io_address = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset); - switch (width) - { + switch (width) { case 8: acpi_os_out8 (io_address, (u8) value); break; @@ -961,13 +949,12 @@ break; - case ADDRESS_SPACE_PCI_CONFIG: + case ACPI_ADR_SPACE_PCI_CONFIG: pci_dev_func = ACPI_PCI_DEVFUN (ACPI_GET_ADDRESS (reg->address)); pci_register = ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (reg->address)) + offset; - switch (width) - { + switch (width) { case 8: acpi_os_write_pci_cfg_byte (0, pci_dev_func, pci_register, (u8) value); break; diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/hardware/hwsleep.c linux/drivers/acpi/hardware/hwsleep.c --- v2.4.5/linux/drivers/acpi/hardware/hwsleep.c Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/hardware/hwsleep.c Wed Jun 20 17:47:40 2001 @@ -2,7 +2,7 @@ /****************************************************************************** * * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface - * $Revision: 7 $ + * $Revision: 12 $ * *****************************************************************************/ @@ -28,7 +28,7 @@ #include "acnamesp.h" #include "achware.h" -#define _COMPONENT HARDWARE +#define _COMPONENT ACPI_HARDWARE MODULE_NAME ("hwsleep") @@ -126,27 +126,28 @@ ACPI_STATUS acpi_enter_sleep_state ( - u8 sleep_state) + u8 sleep_state) { - ACPI_STATUS status; - ACPI_OBJECT_LIST arg_list; - ACPI_OBJECT arg; - u8 type_a; - u8 type_b; - u16 PM1_acontrol; - u16 PM1_bcontrol; + ACPI_STATUS status; + ACPI_OBJECT_LIST arg_list; + ACPI_OBJECT arg; + u8 type_a; + u8 type_b; + u16 PM1_acontrol; + u16 PM1_bcontrol; + /* * _PSW methods could be run here to enable wake-on keyboard, LAN, etc. */ - status = acpi_hw_obtain_sleep_type_register_data(sleep_state, &type_a, &type_b); - - if (!ACPI_SUCCESS(status)) { + status = acpi_hw_obtain_sleep_type_register_data (sleep_state, &type_a, &type_b); + if (!ACPI_SUCCESS (status)) { return status; } /* run the _PTS and _GTS methods */ + MEMSET(&arg_list, 0, sizeof(arg_list)); arg_list.count = 1; arg_list.pointer = &arg; @@ -159,28 +160,32 @@ acpi_evaluate_object(NULL, "\\_GTS", &arg_list, NULL); /* clear wake status */ + acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, WAK_STS, 1); + disable(); + PM1_acontrol = (u16) acpi_hw_register_read(ACPI_MTX_LOCK, PM1_CONTROL); /* mask off SLP_EN and SLP_TYP fields */ PM1_acontrol &= 0xC3FF; - - /* mask in SLP_EN */ - PM1_acontrol |= (1 << acpi_hw_get_bit_shift (SLP_EN_MASK)); - PM1_bcontrol = PM1_acontrol; /* mask in SLP_TYP */ PM1_acontrol |= (type_a << acpi_hw_get_bit_shift (SLP_TYPE_X_MASK)); PM1_bcontrol |= (type_b << acpi_hw_get_bit_shift (SLP_TYPE_X_MASK)); - disable(); + /* write #1: fill in SLP_TYPE data */ + acpi_hw_register_write(ACPI_MTX_LOCK, PM1_a_CONTROL, PM1_acontrol); + acpi_hw_register_write(ACPI_MTX_LOCK, PM1_b_CONTROL, PM1_bcontrol); + + /* mask in SLP_EN */ + PM1_acontrol |= (1 << acpi_hw_get_bit_shift (SLP_EN_MASK)); + PM1_bcontrol |= (1 << acpi_hw_get_bit_shift (SLP_EN_MASK)); + /* write #2: the whole tamale */ acpi_hw_register_write(ACPI_MTX_LOCK, PM1_a_CONTROL, PM1_acontrol); acpi_hw_register_write(ACPI_MTX_LOCK, PM1_b_CONTROL, PM1_bcontrol); - acpi_hw_register_write(ACPI_MTX_LOCK, PM1_CONTROL, - (1 << acpi_hw_get_bit_shift (SLP_EN_MASK))); enable(); diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/hardware/hwtimer.c linux/drivers/acpi/hardware/hwtimer.c --- v2.4.5/linux/drivers/acpi/hardware/hwtimer.c Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/hardware/hwtimer.c Wed Jun 20 17:47:40 2001 @@ -2,7 +2,7 @@ /****************************************************************************** * * Name: hwtimer.c - ACPI Power Management Timer Interface - * $Revision: 5 $ + * $Revision: 10 $ * *****************************************************************************/ @@ -27,7 +27,7 @@ #include "acpi.h" #include "achware.h" -#define _COMPONENT HARDWARE +#define _COMPONENT ACPI_HARDWARE MODULE_NAME ("hwtimer") @@ -47,6 +47,16 @@ acpi_get_timer_resolution ( u32 *resolution) { + ACPI_STATUS status; + + + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + if (!resolution) { return (AE_BAD_PARAMETER); } @@ -78,6 +88,16 @@ acpi_get_timer ( u32 *ticks) { + ACPI_STATUS status; + + + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + if (!ticks) { return (AE_BAD_PARAMETER); } @@ -126,6 +146,7 @@ u32 microseconds = 0; u32 remainder = 0; + if (!time_elapsed) { return (AE_BAD_PARAMETER); } @@ -160,7 +181,7 @@ * divides in kernel-space we have to do some trickery to preserve * accuracy while using 32-bit math. * - * TODO: Change to use 64-bit math when supported. + * TBD: Change to use 64-bit math when supported. * * The process is as follows: * 1. Compute the number of seconds by dividing Delta Ticks by diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/accommon.h linux/drivers/acpi/include/accommon.h --- v2.4.5/linux/drivers/acpi/include/accommon.h Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/include/accommon.h Wed Dec 31 16:00:00 1969 @@ -1,725 +0,0 @@ -/****************************************************************************** - * - * Name: accommon.h -- prototypes for the common (subsystem-wide) procedures - * $Revision: 90 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 - */ - -#ifndef _ACCOMMON_H -#define _ACCOMMON_H - - -typedef -ACPI_STATUS (*ACPI_PKG_CALLBACK) ( - u8 object_type, - ACPI_OPERAND_OBJECT *source_object, - ACPI_GENERIC_STATE *state, - void *context); - - -ACPI_STATUS -acpi_cm_walk_package_tree ( - ACPI_OPERAND_OBJECT *source_object, - void *target_object, - ACPI_PKG_CALLBACK walk_callback, - void *context); - - -typedef struct acpi_pkg_info -{ - u8 *free_space; - u32 length; - u32 object_space; - u32 num_packages; -} ACPI_PKG_INFO; - -#define REF_INCREMENT (u16) 0 -#define REF_DECREMENT (u16) 1 -#define REF_FORCE_DELETE (u16) 2 - -/* Acpi_cm_dump_buffer */ - -#define DB_BYTE_DISPLAY 1 -#define DB_WORD_DISPLAY 2 -#define DB_DWORD_DISPLAY 4 -#define DB_QWORD_DISPLAY 8 - - -/* Global initialization interfaces */ - -void -acpi_cm_init_globals ( - void); - -void -acpi_cm_terminate ( - void); - - -/* - * Cm_init - miscellaneous initialization and shutdown - */ - -ACPI_STATUS -acpi_cm_hardware_initialize ( - void); - -ACPI_STATUS -acpi_cm_subsystem_shutdown ( - void); - -ACPI_STATUS -acpi_cm_validate_fadt ( - void); - -/* - * Cm_global - Global data structures and procedures - */ - -#ifdef ACPI_DEBUG - -NATIVE_CHAR * -acpi_cm_get_mutex_name ( - u32 mutex_id); - -NATIVE_CHAR * -acpi_cm_get_type_name ( - u32 type); - -NATIVE_CHAR * -acpi_cm_get_region_name ( - u8 space_id); - -#endif - - -u8 -acpi_cm_valid_object_type ( - u32 type); - -ACPI_OWNER_ID -acpi_cm_allocate_owner_id ( - u32 id_type); - - -/* - * Cm_clib - Local implementations of C library functions - */ - -#ifndef ACPI_USE_SYSTEM_CLIBRARY - -NATIVE_UINT -acpi_cm_strlen ( - const NATIVE_CHAR *string); - -NATIVE_CHAR * -acpi_cm_strcpy ( - NATIVE_CHAR *dst_string, - const NATIVE_CHAR *src_string); - -NATIVE_CHAR * -acpi_cm_strncpy ( - NATIVE_CHAR *dst_string, - const NATIVE_CHAR *src_string, - NATIVE_UINT count); - -u32 -acpi_cm_strncmp ( - const NATIVE_CHAR *string1, - const NATIVE_CHAR *string2, - NATIVE_UINT count); - -u32 -acpi_cm_strcmp ( - const NATIVE_CHAR *string1, - const NATIVE_CHAR *string2); - -NATIVE_CHAR * -acpi_cm_strcat ( - NATIVE_CHAR *dst_string, - const NATIVE_CHAR *src_string); - -NATIVE_CHAR * -acpi_cm_strncat ( - NATIVE_CHAR *dst_string, - const NATIVE_CHAR *src_string, - NATIVE_UINT count); - -u32 -acpi_cm_strtoul ( - const NATIVE_CHAR *string, - NATIVE_CHAR **terminator, - NATIVE_UINT base); - -NATIVE_CHAR * -acpi_cm_strstr ( - NATIVE_CHAR *string1, - NATIVE_CHAR *string2); - -NATIVE_CHAR * -acpi_cm_strupr ( - NATIVE_CHAR *src_string); - -void * -acpi_cm_memcpy ( - void *dest, - const void *src, - NATIVE_UINT count); - -void * -acpi_cm_memset ( - void *dest, - NATIVE_UINT value, - NATIVE_UINT count); - -u32 -acpi_cm_to_upper ( - u32 c); - -u32 -acpi_cm_to_lower ( - u32 c); - -#endif /* ACPI_USE_SYSTEM_CLIBRARY */ - -/* - * Cm_copy - Object construction and conversion interfaces - */ - -ACPI_STATUS -acpi_cm_build_simple_object( - ACPI_OPERAND_OBJECT *obj, - ACPI_OBJECT *user_obj, - u8 *data_space, - u32 *buffer_space_used); - -ACPI_STATUS -acpi_cm_build_package_object ( - ACPI_OPERAND_OBJECT *obj, - u8 *buffer, - u32 *space_used); - -ACPI_STATUS -acpi_cm_copy_iobject_to_eobject ( - ACPI_OPERAND_OBJECT *obj, - ACPI_BUFFER *ret_buffer); - -ACPI_STATUS -acpi_cm_copy_esimple_to_isimple( - ACPI_OBJECT *user_obj, - ACPI_OPERAND_OBJECT *obj); - -ACPI_STATUS -acpi_cm_copy_eobject_to_iobject ( - ACPI_OBJECT *obj, - ACPI_OPERAND_OBJECT *internal_obj); - -ACPI_STATUS -acpi_cm_copy_isimple_to_isimple ( - ACPI_OPERAND_OBJECT *source_obj, - ACPI_OPERAND_OBJECT *dest_obj); - -ACPI_STATUS -acpi_cm_copy_ipackage_to_ipackage ( - ACPI_OPERAND_OBJECT *source_obj, - ACPI_OPERAND_OBJECT *dest_obj, - ACPI_WALK_STATE *walk_state); - - -/* - * Cm_create - Object creation - */ - -ACPI_STATUS -acpi_cm_update_object_reference ( - ACPI_OPERAND_OBJECT *object, - u16 action); - -ACPI_OPERAND_OBJECT * -_cm_create_internal_object ( - NATIVE_CHAR *module_name, - u32 line_number, - u32 component_id, - OBJECT_TYPE_INTERNAL type); - - -/* - * Cm_debug - Debug interfaces - */ - -u32 -get_debug_level ( - void); - -void -set_debug_level ( - u32 level); - -void -function_trace ( - NATIVE_CHAR *module_name, - u32 line_number, - u32 component_id, - NATIVE_CHAR *function_name); - -void -function_trace_ptr ( - NATIVE_CHAR *module_name, - u32 line_number, - u32 component_id, - NATIVE_CHAR *function_name, - void *pointer); - -void -function_trace_u32 ( - NATIVE_CHAR *module_name, - u32 line_number, - u32 component_id, - NATIVE_CHAR *function_name, - u32 integer); - -void -function_trace_str ( - NATIVE_CHAR *module_name, - u32 line_number, - u32 component_id, - NATIVE_CHAR *function_name, - NATIVE_CHAR *string); - -void -function_exit ( - NATIVE_CHAR *module_name, - u32 line_number, - u32 component_id, - NATIVE_CHAR *function_name); - -void -function_status_exit ( - NATIVE_CHAR *module_name, - u32 line_number, - u32 component_id, - NATIVE_CHAR *function_name, - ACPI_STATUS status); - -void -function_value_exit ( - NATIVE_CHAR *module_name, - u32 line_number, - u32 component_id, - NATIVE_CHAR *function_name, - ACPI_INTEGER value); - -void -function_ptr_exit ( - NATIVE_CHAR *module_name, - u32 line_number, - u32 component_id, - NATIVE_CHAR *function_name, - u8 *ptr); - -void -debug_print_prefix ( - NATIVE_CHAR *module_name, - u32 line_number); - -void -debug_print ( - NATIVE_CHAR *module_name, - u32 line_number, - u32 component_id, - u32 print_level, - NATIVE_CHAR *format, ...); - -void -debug_print_raw ( - NATIVE_CHAR *format, ...); - -void -_report_info ( - NATIVE_CHAR *module_name, - u32 line_number, - u32 component_id); - -void -_report_error ( - NATIVE_CHAR *module_name, - u32 line_number, - u32 component_id); - -void -_report_warning ( - NATIVE_CHAR *module_name, - u32 line_number, - u32 component_id); - -void -acpi_cm_dump_buffer ( - u8 *buffer, - u32 count, - u32 display, - u32 component_id); - - -/* - * Cm_delete - Object deletion - */ - -void -acpi_cm_delete_internal_obj ( - ACPI_OPERAND_OBJECT *object); - -void -acpi_cm_delete_internal_package_object ( - ACPI_OPERAND_OBJECT *object); - -void -acpi_cm_delete_internal_simple_object ( - ACPI_OPERAND_OBJECT *object); - -ACPI_STATUS -acpi_cm_delete_internal_object_list ( - ACPI_OPERAND_OBJECT **obj_list); - - -/* - * Cm_eval - object evaluation - */ - -/* Method name strings */ - -#define METHOD_NAME__HID "_HID" -#define METHOD_NAME__UID "_UID" -#define METHOD_NAME__ADR "_ADR" -#define METHOD_NAME__STA "_STA" -#define METHOD_NAME__REG "_REG" -#define METHOD_NAME__SEG "_SEG" -#define METHOD_NAME__BBN "_BBN" - - -ACPI_STATUS -acpi_cm_evaluate_numeric_object ( - NATIVE_CHAR *object_name, - ACPI_NAMESPACE_NODE *device_node, - ACPI_INTEGER *address); - -ACPI_STATUS -acpi_cm_execute_HID ( - ACPI_NAMESPACE_NODE *device_node, - DEVICE_ID *hid); - -ACPI_STATUS -acpi_cm_execute_STA ( - ACPI_NAMESPACE_NODE *device_node, - u32 *status_flags); - -ACPI_STATUS -acpi_cm_execute_UID ( - ACPI_NAMESPACE_NODE *device_node, - DEVICE_ID *uid); - - -/* - * Cm_error - exception interfaces - */ - -NATIVE_CHAR * -acpi_cm_format_exception ( - ACPI_STATUS status); - - -/* - * Cm_mutex - mutual exclusion interfaces - */ - -ACPI_STATUS -acpi_cm_mutex_initialize ( - void); - -void -acpi_cm_mutex_terminate ( - void); - -ACPI_STATUS -acpi_cm_create_mutex ( - ACPI_MUTEX_HANDLE mutex_id); - -ACPI_STATUS -acpi_cm_delete_mutex ( - ACPI_MUTEX_HANDLE mutex_id); - -ACPI_STATUS -acpi_cm_acquire_mutex ( - ACPI_MUTEX_HANDLE mutex_id); - -ACPI_STATUS -acpi_cm_release_mutex ( - ACPI_MUTEX_HANDLE mutex_id); - - -/* - * Cm_object - internal object create/delete/cache routines - */ - -void * -_cm_allocate_object_desc ( - NATIVE_CHAR *module_name, - u32 line_number, - u32 component_id); - -#define acpi_cm_create_internal_object(t) _cm_create_internal_object(_THIS_MODULE,__LINE__,_COMPONENT,t) -#define acpi_cm_allocate_object_desc() _cm_allocate_object_desc(_THIS_MODULE,__LINE__,_COMPONENT) - -void -acpi_cm_delete_object_desc ( - ACPI_OPERAND_OBJECT *object); - -u8 -acpi_cm_valid_internal_object ( - void *object); - - -/* - * Cm_ref_cnt - Object reference count management - */ - -void -acpi_cm_add_reference ( - ACPI_OPERAND_OBJECT *object); - -void -acpi_cm_remove_reference ( - ACPI_OPERAND_OBJECT *object); - -/* - * Cm_size - Object size routines - */ - -ACPI_STATUS -acpi_cm_get_simple_object_size ( - ACPI_OPERAND_OBJECT *obj, - u32 *obj_length); - -ACPI_STATUS -acpi_cm_get_package_object_size ( - ACPI_OPERAND_OBJECT *obj, - u32 *obj_length); - -ACPI_STATUS -acpi_cm_get_object_size( - ACPI_OPERAND_OBJECT *obj, - u32 *obj_length); - - -/* - * Cm_state - Generic state creation/cache routines - */ - -void -acpi_cm_push_generic_state ( - ACPI_GENERIC_STATE **list_head, - ACPI_GENERIC_STATE *state); - -ACPI_GENERIC_STATE * -acpi_cm_pop_generic_state ( - ACPI_GENERIC_STATE **list_head); - - -ACPI_GENERIC_STATE * -acpi_cm_create_generic_state ( - void); - -ACPI_GENERIC_STATE * -acpi_cm_create_update_state ( - ACPI_OPERAND_OBJECT *object, - u16 action); - -ACPI_GENERIC_STATE * -acpi_cm_create_pkg_state ( - void *internal_object, - void *external_object, - u16 index); - -ACPI_STATUS -acpi_cm_create_update_state_and_push ( - ACPI_OPERAND_OBJECT *object, - u16 action, - ACPI_GENERIC_STATE **state_list); - -ACPI_STATUS -acpi_cm_create_pkg_state_and_push ( - void *internal_object, - void *external_object, - u16 index, - ACPI_GENERIC_STATE **state_list); - -ACPI_GENERIC_STATE * -acpi_cm_create_control_state ( - void); - -void -acpi_cm_delete_generic_state ( - ACPI_GENERIC_STATE *state); - -void -acpi_cm_delete_generic_state_cache ( - void); - -void -acpi_cm_delete_object_cache ( - void); - -/* - * Cmutils - */ - -u8 -acpi_cm_valid_acpi_name ( - u32 name); - -u8 -acpi_cm_valid_acpi_character ( - NATIVE_CHAR character); - -ACPI_STATUS -acpi_cm_resolve_package_references ( - ACPI_OPERAND_OBJECT *obj_desc); - -#ifdef ACPI_DEBUG - -void -acpi_cm_display_init_pathname ( - ACPI_HANDLE obj_handle, - char *path); - -#endif - - -/* - * Memory allocation functions and related macros. - * Macros that expand to include filename and line number - */ - -void * -_cm_allocate ( - u32 size, - u32 component, - NATIVE_CHAR *module, - u32 line); - -void * -_cm_callocate ( - u32 size, - u32 component, - NATIVE_CHAR *module, - u32 line); - -void -_cm_free ( - void *address, - u32 component, - NATIVE_CHAR *module, - u32 line); - -void -acpi_cm_init_static_object ( - ACPI_OPERAND_OBJECT *obj_desc); - -#define acpi_cm_allocate(a) _cm_allocate(a,_COMPONENT,_THIS_MODULE,__LINE__) -#define acpi_cm_callocate(a) _cm_callocate(a, _COMPONENT,_THIS_MODULE,__LINE__) -#define acpi_cm_free(a) _cm_free(a,_COMPONENT,_THIS_MODULE,__LINE__) - -#ifndef ACPI_DEBUG_TRACK_ALLOCATIONS - -#define acpi_cm_add_element_to_alloc_list(a,b,c,d,e,f) -#define acpi_cm_delete_element_from_alloc_list(a,b,c,d) -#define acpi_cm_dump_current_allocations(a,b) -#define acpi_cm_dump_allocation_info() - -#define DECREMENT_OBJECT_METRICS(a) -#define INCREMENT_OBJECT_METRICS(a) -#define INITIALIZE_ALLOCATION_METRICS() -#define DECREMENT_NAME_TABLE_METRICS(a) -#define INCREMENT_NAME_TABLE_METRICS(a) - -#else - -#define INITIALIZE_ALLOCATION_METRICS() \ - acpi_gbl_current_object_count = 0; \ - acpi_gbl_current_object_size = 0; \ - acpi_gbl_running_object_count = 0; \ - acpi_gbl_running_object_size = 0; \ - acpi_gbl_max_concurrent_object_count = 0; \ - acpi_gbl_max_concurrent_object_size = 0; \ - acpi_gbl_current_alloc_size = 0; \ - acpi_gbl_current_alloc_count = 0; \ - acpi_gbl_running_alloc_size = 0; \ - acpi_gbl_running_alloc_count = 0; \ - acpi_gbl_max_concurrent_alloc_size = 0; \ - acpi_gbl_max_concurrent_alloc_count = 0; \ - acpi_gbl_current_node_count = 0; \ - acpi_gbl_current_node_size = 0; \ - acpi_gbl_max_concurrent_node_count = 0 - - -#define DECREMENT_OBJECT_METRICS(a) \ - acpi_gbl_current_object_count--; \ - acpi_gbl_current_object_size -= a - -#define INCREMENT_OBJECT_METRICS(a) \ - acpi_gbl_current_object_count++; \ - acpi_gbl_running_object_count++; \ - if (acpi_gbl_max_concurrent_object_count < acpi_gbl_current_object_count) \ - { \ - acpi_gbl_max_concurrent_object_count = acpi_gbl_current_object_count; \ - } \ - acpi_gbl_running_object_size += a; \ - acpi_gbl_current_object_size += a; \ - if (acpi_gbl_max_concurrent_object_size < acpi_gbl_current_object_size) \ - { \ - acpi_gbl_max_concurrent_object_size = acpi_gbl_current_object_size; \ - } - -#define DECREMENT_NAME_TABLE_METRICS(a) \ - acpi_gbl_current_node_count--; \ - acpi_gbl_current_node_size -= (a) - -#define INCREMENT_NAME_TABLE_METRICS(a) \ - acpi_gbl_current_node_count++; \ - acpi_gbl_current_node_size+= (a); \ - if (acpi_gbl_max_concurrent_node_count < acpi_gbl_current_node_count) \ - { \ - acpi_gbl_max_concurrent_node_count = acpi_gbl_current_node_count; \ - } \ - - -void -acpi_cm_dump_allocation_info ( - void); - -void -acpi_cm_dump_current_allocations ( - u32 component, - NATIVE_CHAR *module); - -#endif - - -#endif /* _ACCOMMON_H */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/acconfig.h linux/drivers/acpi/include/acconfig.h --- v2.4.5/linux/drivers/acpi/include/acconfig.h Tue Mar 6 19:44:36 2001 +++ linux/drivers/acpi/include/acconfig.h Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acconfig.h - Global configuration constants - * $Revision: 55 $ + * $Revision: 65 $ * *****************************************************************************/ @@ -53,7 +53,7 @@ /* Version string */ -#define ACPI_CA_VERSION 0x20010208 +#define ACPI_CA_VERSION 0x20010615 /* Maximum objects in the various object caches */ @@ -147,6 +147,11 @@ #define LO_RSDP_WINDOW_SIZE 0x400 #define HI_RSDP_WINDOW_SIZE 0x20000 #define RSDP_SCAN_STEP 16 + +/* Maximum Space_ids for Operation Regions */ + +#define ACPI_MAX_ADDRESS_SPACE 255 +#define ACPI_NUM_ADDRESS_SPACES 256 #endif /* _ACCONFIG_H */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/acdebug.h linux/drivers/acpi/include/acdebug.h --- v2.4.5/linux/drivers/acpi/include/acdebug.h Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/include/acdebug.h Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acdebug.h - ACPI/AML debugger - * $Revision: 41 $ + * $Revision: 44 $ * *****************************************************************************/ @@ -36,7 +36,7 @@ extern int optind; extern NATIVE_CHAR *optarg; extern u8 *aml_ptr; -extern u32 acpi_aml_length; +extern u32 aml_length; extern u8 opt_tables; extern u8 opt_disasm; @@ -200,6 +200,10 @@ NATIVE_CHAR *object_arg); void +acpi_db_display_locks (void); + + +void acpi_db_display_resources ( NATIVE_CHAR *object_arg); @@ -303,7 +307,7 @@ * dbfileio - Debugger file I/O commands */ -OBJECT_TYPE_INTERNAL +ACPI_OBJECT_TYPE8 acpi_db_match_argument ( NATIVE_CHAR *user_argument, ARGUMENT_INFO *arguments); diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/acdispat.h linux/drivers/acpi/include/acdispat.h --- v2.4.5/linux/drivers/acpi/include/acdispat.h Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/include/acdispat.h Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acdispat.h - dispatcher (parser to interpreter interface) - * $Revision: 35 $ + * $Revision: 40 $ * *****************************************************************************/ @@ -32,12 +32,6 @@ #define NAMEOF_ARG_NTE "__A0" -/* For Acpi_ds_method_data_set_value */ - -#define MTH_TYPE_LOCAL 0 -#define MTH_TYPE_ARG 1 - - /* Common interfaces */ ACPI_STATUS @@ -64,7 +58,7 @@ /* dsopcode - support for late evaluation */ ACPI_STATUS -acpi_ds_get_field_unit_arguments ( +acpi_ds_get_buffer_field_arguments ( ACPI_OPERAND_OBJECT *obj_desc); ACPI_STATUS @@ -126,7 +120,7 @@ ACPI_STATUS acpi_ds_create_index_field ( ACPI_PARSE_OBJECT *op, - ACPI_HANDLE region_node, + ACPI_NAMESPACE_NODE *region_node, ACPI_WALK_STATE *walk_state); @@ -173,8 +167,15 @@ ACPI_STATUS +acpi_ds_store_object_to_local ( + u16 opcode, + u32 index, + ACPI_OPERAND_OBJECT *src_desc, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS acpi_ds_method_data_get_entry ( - u32 type, + u16 opcode, u32 index, ACPI_WALK_STATE *walk_state, ACPI_OPERAND_OBJECT ***node); @@ -187,29 +188,22 @@ acpi_ds_is_method_value ( ACPI_OPERAND_OBJECT *obj_desc); -OBJECT_TYPE_INTERNAL +ACPI_OBJECT_TYPE8 acpi_ds_method_data_get_type ( - u32 type, + u16 opcode, u32 index, ACPI_WALK_STATE *walk_state); ACPI_STATUS acpi_ds_method_data_get_value ( - u32 type, + u16 opcode, u32 index, ACPI_WALK_STATE *walk_state, ACPI_OPERAND_OBJECT **dest_desc); ACPI_STATUS -acpi_ds_method_data_set_value ( - u32 type, - u32 index, - ACPI_OPERAND_OBJECT *src_desc, - ACPI_WALK_STATE *walk_state); - -ACPI_STATUS acpi_ds_method_data_delete_value ( - u32 type, + u16 opcode, u32 index, ACPI_WALK_STATE *walk_state); @@ -220,8 +214,8 @@ ACPI_WALK_STATE *walk_state); ACPI_NAMESPACE_NODE * -acpi_ds_method_data_get_nte ( - u32 type, +acpi_ds_method_data_get_node ( + u16 opcode, u32 index, ACPI_WALK_STATE *walk_state); @@ -231,7 +225,7 @@ ACPI_STATUS acpi_ds_method_data_set_entry ( - u32 type, + u16 opcode, u32 index, ACPI_OPERAND_OBJECT *object, ACPI_WALK_STATE *walk_state); @@ -261,7 +255,8 @@ ACPI_STATUS acpi_ds_begin_method_execution ( ACPI_NAMESPACE_NODE *method_node, - ACPI_OPERAND_OBJECT *obj_desc); + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_NAMESPACE_NODE *calling_method_node); /* dsobj - Parser/Interpreter interface - object initialization and conversion */ @@ -307,7 +302,7 @@ /* dsregn - Parser/Interpreter interface - Op Region parsing */ ACPI_STATUS -acpi_ds_eval_field_unit_operands ( +acpi_ds_eval_buffer_field_operands ( ACPI_WALK_STATE *walk_state, ACPI_PARSE_OBJECT *op); @@ -349,12 +344,12 @@ acpi_ds_resolve_operands ( ACPI_WALK_STATE *walk_state); -OBJECT_TYPE_INTERNAL +ACPI_OBJECT_TYPE8 acpi_ds_map_opcode_to_data_type ( u16 opcode, u32 *out_flags); -OBJECT_TYPE_INTERNAL +ACPI_OBJECT_TYPE8 acpi_ds_map_named_opcode_to_data_type ( u16 opcode); @@ -366,7 +361,7 @@ ACPI_STATUS acpi_ds_scope_stack_push ( ACPI_NAMESPACE_NODE *node, - OBJECT_TYPE_INTERNAL type, + ACPI_OBJECT_TYPE8 type, ACPI_WALK_STATE *walk_state); diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/acenv.h linux/drivers/acpi/include/acenv.h --- v2.4.5/linux/drivers/acpi/include/acenv.h Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/include/acenv.h Wed Dec 31 16:00:00 1969 @@ -1,288 +0,0 @@ -/****************************************************************************** - * - * Name: acenv.h - Generation environment specific items - * $Revision: 70 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 - */ - -#ifndef __ACENV_H__ -#define __ACENV_H__ - - -/* - * Configuration for ACPI tools and utilities - */ - -#ifdef _ACPI_DUMP_APP -#define ACPI_DEBUG -#define ACPI_APPLICATION -#define ENABLE_DEBUGGER -#define ACPI_USE_SYSTEM_CLIBRARY -#define PARSER_ONLY -#endif - -#ifdef _ACPI_EXEC_APP -#undef DEBUGGER_THREADING -#define DEBUGGER_THREADING DEBUGGER_SINGLE_THREADED -#define ACPI_DEBUG -#define ACPI_APPLICATION -#define ENABLE_DEBUGGER -#define ACPI_USE_SYSTEM_CLIBRARY -#endif - -#ifdef _ACPI_ASL_COMPILER -#define ACPI_DEBUG -#define ACPI_APPLICATION -#define ENABLE_DEBUGGER -#define ACPI_USE_SYSTEM_CLIBRARY -#endif - -/* - * Memory allocation tracking. Used only if - * 1) This is the debug version - * 2) This is NOT a 16-bit version of the code (not enough real-mode memory) - */ -#ifdef ACPI_DEBUG -#ifndef _IA16 -#define ACPI_DEBUG_TRACK_ALLOCATIONS -#endif -#endif - -/* - * Environment configuration. The purpose of this file is to interface to the - * local generation environment. - * - * 1) ACPI_USE_SYSTEM_CLIBRARY - Define this if linking to an actual C library. - * Otherwise, local versions of string/memory functions will be used. - * 2) ACPI_USE_STANDARD_HEADERS - Define this if linking to a C library and - * the standard header files may be used. - * - * The ACPI subsystem only uses low level C library functions that do not call - * operating system services and may therefore be inlined in the code. - * - * It may be necessary to tailor these include files to the target - * generation environment. - * - * - * Functions and constants used from each header: - * - * string.h: memcpy - * memset - * strcat - * strcmp - * strcpy - * strlen - * strncmp - * strncat - * strncpy - * - * stdlib.h: strtoul - * - * stdarg.h: va_list - * va_arg - * va_start - * va_end - * - */ - -/*! [Begin] no source code translation */ - -#ifdef _LINUX -#include "aclinux.h" - -#elif _AED_EFI -#include "acefi.h" - -#elif WIN32 -#include "acwin.h" - -#elif __FreeBSD__ -#include "acfreebsd.h" - -#else - -/* All other environments */ - -#define ACPI_USE_STANDARD_HEADERS - -/* Name of host operating system (returned by the _OS_ namespace object) */ - -#define ACPI_OS_NAME "Intel ACPI/CA Core Subsystem" - -#endif - - -/*! [End] no source code translation !*/ - -/****************************************************************************** - * - * C library configuration - * - *****************************************************************************/ - -#ifdef ACPI_USE_SYSTEM_CLIBRARY -/* - * Use the standard C library headers. - * We want to keep these to a minimum. - * - */ - -#ifdef ACPI_USE_STANDARD_HEADERS -/* - * Use the standard headers from the standard locations - */ -#include -#include -#include -#include - -#endif /* ACPI_USE_STANDARD_HEADERS */ - -/* - * We will be linking to the standard Clib functions - */ - -#define STRSTR(s1,s2) strstr((s1), (s2)) -#define STRUPR(s) strupr((s)) -#define STRLEN(s) strlen((s)) -#define STRCPY(d,s) strcpy((d), (s)) -#define STRNCPY(d,s,n) strncpy((d), (s), (NATIVE_INT)(n)) -#define STRNCMP(d,s,n) strncmp((d), (s), (NATIVE_INT)(n)) -#define STRCMP(d,s) strcmp((d), (s)) -#define STRCAT(d,s) strcat((d), (s)) -#define STRNCAT(d,s,n) strncat((d), (s), (NATIVE_INT)(n)) -#define STRTOUL(d,s,n) strtoul((d), (s), (NATIVE_INT)(n)) -#define MEMCPY(d,s,n) memcpy((d), (s), (NATIVE_INT)(n)) -#define MEMSET(d,s,n) memset((d), (s), (NATIVE_INT)(n)) -#define TOUPPER toupper -#define TOLOWER tolower -#define IS_XDIGIT isxdigit - -/****************************************************************************** - * - * Not using native C library, use local implementations - * - *****************************************************************************/ -#else - -/* - * Use local definitions of C library macros and functions - * NOTE: The function implementations may not be as efficient - * as an inline or assembly code implementation provided by a - * native C library. - */ - -#ifndef va_arg - -#ifndef _VALIST -#define _VALIST -typedef char *va_list; -#endif /* _VALIST */ - -/* - * Storage alignment properties - */ - -#define _AUPBND (sizeof(int) - 1) -#define _ADNBND (sizeof(int) - 1) - -/* - * Variable argument list macro definitions - */ - -#define _bnd(X, bnd) (((sizeof(X)) + (bnd)) & (~(bnd))) -#define va_arg(ap, T) (*(T *)(((ap)+=((_bnd(T, _AUPBND)))-(_bnd(T,_ADNBND))))) -#define va_end(ap) (void)0 -#define va_start(ap, A) (void)((ap)=(((char*)&(A))+(_bnd(A,_AUPBND)))) - -#endif /* va_arg */ - - -#define STRSTR(s1,s2) acpi_cm_strstr ((s1), (s2)) -#define STRUPR(s) acpi_cm_strupr ((s)) -#define STRLEN(s) acpi_cm_strlen ((s)) -#define STRCPY(d,s) acpi_cm_strcpy ((d), (s)) -#define STRNCPY(d,s,n) acpi_cm_strncpy ((d), (s), (n)) -#define STRNCMP(d,s,n) acpi_cm_strncmp ((d), (s), (n)) -#define STRCMP(d,s) acpi_cm_strcmp ((d), (s)) -#define STRCAT(d,s) acpi_cm_strcat ((d), (s)) -#define STRNCAT(d,s,n) acpi_cm_strncat ((d), (s), (n)) -#define STRTOUL(d,s,n) acpi_cm_strtoul ((d), (s),(n)) -#define MEMCPY(d,s,n) acpi_cm_memcpy ((d), (s), (n)) -#define MEMSET(d,v,n) acpi_cm_memset ((d), (v), (n)) -#define TOUPPER acpi_cm_to_upper -#define TOLOWER acpi_cm_to_lower - -#endif /* ACPI_USE_SYSTEM_CLIBRARY */ - - -/****************************************************************************** - * - * Assembly code macros - * - *****************************************************************************/ - -/* - * Handle platform- and compiler-specific assembly language differences. - * These should already have been defined by the platform includes above. - * - * Notes: - * 1) Interrupt 3 is used to break into a debugger - * 2) Interrupts are turned off during ACPI register setup - */ - -/* Unrecognized compiler, use defaults */ -#ifndef ACPI_ASM_MACROS - -#define ACPI_ASM_MACROS -#define causeinterrupt(level) -#define BREAKPOINT3 -#define disable() -#define enable() -#define halt() -#define ACPI_ACQUIRE_GLOBAL_LOCK(Glptr, acq) -#define ACPI_RELEASE_GLOBAL_LOCK(Glptr, acq) - -#endif /* ACPI_ASM_MACROS */ - - -#ifdef ACPI_APPLICATION - -/* Don't want software interrupts within a ring3 application */ - -#undef causeinterrupt -#undef BREAKPOINT3 -#define causeinterrupt(level) -#define BREAKPOINT3 -#endif - - -/****************************************************************************** - * - * Compiler-specific - * - *****************************************************************************/ - -/* this has been moved to compiler-specific headers, which are included from the - platform header. */ - - -#endif /* __ACENV_H__ */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/acevents.h linux/drivers/acpi/include/acevents.h --- v2.4.5/linux/drivers/acpi/include/acevents.h Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/include/acevents.h Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acevents.h - Event subcomponent prototypes and defines - * $Revision: 63 $ + * $Revision: 65 $ * *****************************************************************************/ @@ -91,11 +91,14 @@ * Acpi_evnotify - Device Notify handling and dispatch */ -void -acpi_ev_notify_dispatch ( - ACPI_HANDLE device, +ACPI_STATUS +acpi_ev_queue_notify_request ( + ACPI_NAMESPACE_NODE *node, u32 notify_value); +void +acpi_ev_notify_dispatch ( + void *context); /* * Acpi_evregion - Address Space handling @@ -195,22 +198,6 @@ void acpi_ev_terminate ( void); - - -/* Debug support */ - -#ifdef ACPI_DEBUG - -u32 -acpi_ev_sci_count ( - u32 acpi_event); - -#define DEBUG_INCREMENT_EVENT_COUNT(a) acpi_gbl_event_count[a]++; - -#else - -#define DEBUG_INCREMENT_EVENT_COUNT(a) -#endif #endif /* __ACEVENTS_H__ */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/acexcep.h linux/drivers/acpi/include/acexcep.h --- v2.4.5/linux/drivers/acpi/include/acexcep.h Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/include/acexcep.h Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acexcep.h - Exception codes returned by the ACPI subsystem - * $Revision: 41 $ + * $Revision: 46 $ * *****************************************************************************/ @@ -68,8 +68,14 @@ #define AE_LIMIT (ACPI_STATUS) (0x0012 | AE_CODE_ENVIRONMENTAL) #define AE_TIME (ACPI_STATUS) (0x0013 | AE_CODE_ENVIRONMENTAL) #define AE_UNKNOWN_STATUS (ACPI_STATUS) (0x0014 | AE_CODE_ENVIRONMENTAL) +#define AE_ACQUIRE_DEADLOCK (ACPI_STATUS) (0x0015 | AE_CODE_ENVIRONMENTAL) +#define AE_RELEASE_DEADLOCK (ACPI_STATUS) (0x0016 | AE_CODE_ENVIRONMENTAL) +#define AE_NOT_ACQUIRED (ACPI_STATUS) (0x0017 | AE_CODE_ENVIRONMENTAL) +#define AE_ALREADY_ACQUIRED (ACPI_STATUS) (0x0018 | AE_CODE_ENVIRONMENTAL) +#define AE_NO_HARDWARE_RESPONSE (ACPI_STATUS) (0x0019 | AE_CODE_ENVIRONMENTAL) +#define AE_NO_GLOBAL_LOCK (ACPI_STATUS) (0x001A | AE_CODE_ENVIRONMENTAL) -#define AE_CODE_ENV_MAX 0x0014 +#define AE_CODE_ENV_MAX 0x001A /* * Programmer exceptions @@ -118,8 +124,13 @@ #define AE_AML_INVALID_SPACE_ID (ACPI_STATUS) (0x0012 | AE_CODE_AML) #define AE_AML_STRING_LIMIT (ACPI_STATUS) (0x0013 | AE_CODE_AML) #define AE_AML_NO_RETURN_VALUE (ACPI_STATUS) (0x0014 | AE_CODE_AML) +#define AE_AML_METHOD_LIMIT (ACPI_STATUS) (0x0015 | AE_CODE_AML) +#define AE_AML_NOT_OWNER (ACPI_STATUS) (0x0016 | AE_CODE_AML) +#define AE_AML_MUTEX_ORDER (ACPI_STATUS) (0x0017 | AE_CODE_AML) +#define AE_AML_MUTEX_NOT_ACQUIRED (ACPI_STATUS) (0x0018 | AE_CODE_AML) +#define AE_AML_INVALID_RESOURCE_TYPE (ACPI_STATUS) (0x0019 | AE_CODE_AML) -#define AE_CODE_AML_MAX 0x0014 +#define AE_CODE_AML_MAX 0x0019 /* * Internal exceptions used for control @@ -165,6 +176,12 @@ "AE_LIMIT", "AE_TIME", "AE_UNKNOWN_STATUS", + "AE_ACQUIRE_DEADLOCK", + "AE_RELEASE_DEADLOCK", + "AE_NOT_ACQUIRED", + "AE_ALREADY_ACQUIRED", + "AE_NO_HARDWARE_RESPONSE", + "AE_NO_GLOBAL_LOCK", }; static NATIVE_CHAR *acpi_gbl_exception_names_pgm[] = @@ -206,6 +223,11 @@ "AE_AML_INVALID_SPACE_ID", "AE_AML_STRING_LIMIT", "AE_AML_NO_RETURN_VALUE", + "AE_AML_METHOD_LIMIT", + "AE_AML_NOT_OWNER", + "AE_AML_MUTEX_ORDER", + "AE_AML_MUTEX_NOT_ACQUIRED", + "AE_AML_INVALID_RESOURCE_TYPE", }; static NATIVE_CHAR *acpi_gbl_exception_names_ctrl[] = diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/acgcc.h linux/drivers/acpi/include/acgcc.h --- v2.4.5/linux/drivers/acpi/include/acgcc.h Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/include/acgcc.h Wed Dec 31 16:00:00 1969 @@ -1,147 +0,0 @@ -/****************************************************************************** - * - * Name: acgcc.h - GCC specific defines, etc. - * $Revision: 5 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 - */ - -#ifndef __ACGCC_H__ -#define __ACGCC_H__ - - -#ifdef __ia64__ -#define _IA64 - -#define COMPILER_DEPENDENT_UINT64 unsigned long -/* Single threaded */ -#define ACPI_APPLICATION - -#define ACPI_ASM_MACROS -#define causeinterrupt(level) -#define BREAKPOINT3 -#define disable() __cli() -#define enable() __sti() -#define wbinvd() - -/*! [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_UINT64 unsigned long long -#define ACPI_ASM_MACROS -#define causeinterrupt(level) -#define BREAKPOINT3 -#define disable() __cli() -#define enable() __sti() -#define halt() __asm__ __volatile__ ("sti; hlt":::"memory") -#define wbinvd() - -/*! [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) - -/*! [End] no source code translation !*/ - -#endif /* IA 32 */ - -#endif /* __ACGCC_H__ */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/acglobal.h linux/drivers/acpi/include/acglobal.h --- v2.4.5/linux/drivers/acpi/include/acglobal.h Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/include/acglobal.h Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acglobal.h - Declarations for global variables - * $Revision: 96 $ + * $Revision: 101 $ * *****************************************************************************/ @@ -150,19 +150,19 @@ ACPI_EXTERN u8 acpi_gbl_debugger_configuration; ACPI_EXTERN u8 acpi_gbl_global_lock_acquired; -ACPI_EXTERN u8 acpi_gbl_global_lock_set; /* TBD: [Restructure] OBSOLETE?? */ ACPI_EXTERN u8 acpi_gbl_step_to_next_call; ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present; +ACPI_EXTERN u8 acpi_gbl_global_lock_present; ACPI_EXTERN ACPI_OBJECT_NOTIFY_HANDLER acpi_gbl_drv_notify; ACPI_EXTERN ACPI_OBJECT_NOTIFY_HANDLER acpi_gbl_sys_notify; -extern u8 acpi_gbl_shutdown; -extern u32 acpi_gbl_system_flags; -extern u32 acpi_gbl_startup_flags; -extern u8 acpi_gbl_decode_to8bit[8]; -extern NATIVE_CHAR acpi_gbl_hex_to_ascii[]; +extern u8 acpi_gbl_shutdown; +extern u32 acpi_gbl_system_flags; +extern u32 acpi_gbl_startup_flags; +extern u8 acpi_gbl_decode_to8bit[8]; +extern NATIVE_CHAR acpi_gbl_hex_to_ascii[16]; /***************************************************************************** @@ -178,15 +178,15 @@ ACPI_EXTERN ACPI_NAMESPACE_NODE acpi_gbl_root_node_struct; ACPI_EXTERN ACPI_NAMESPACE_NODE *acpi_gbl_root_node; -extern u8 acpi_gbl_ns_properties[NUM_NS_TYPES]; -extern PREDEFINED_NAMES acpi_gbl_pre_defined_names [NUM_PREDEFINED_NAMES]; +extern u8 acpi_gbl_ns_properties[NUM_NS_TYPES]; +extern PREDEFINED_NAMES acpi_gbl_pre_defined_names [NUM_PREDEFINED_NAMES]; /* Used to detect memory leaks (DEBUG ONLY) */ #ifdef ACPI_DEBUG -ACPI_EXTERN ALLOCATION_INFO *acpi_gbl_head_alloc_ptr; -ACPI_EXTERN ALLOCATION_INFO *acpi_gbl_tail_alloc_ptr; +ACPI_EXTERN ACPI_ALLOCATION_INFO *acpi_gbl_head_alloc_ptr; +ACPI_EXTERN ACPI_ALLOCATION_INFO *acpi_gbl_tail_alloc_ptr; #endif @@ -200,15 +200,9 @@ ACPI_EXTERN ACPI_WALK_LIST *acpi_gbl_current_walk_list; /* - * Handle to the last method found - used during pass1 of load - */ -ACPI_EXTERN ACPI_HANDLE acpi_gbl_last_method; - -/* * Table of Address Space handlers */ - -ACPI_EXTERN ACPI_ADDRESS_SPACE_INFO acpi_gbl_address_spaces[ACPI_NUM_ADDRESS_SPACES]; +ACPI_EXTERN ACPI_ADR_SPACE_INFO acpi_gbl_address_spaces[ACPI_NUM_ADDRESS_SPACES]; /* Control method single step flag */ @@ -240,7 +234,7 @@ * ****************************************************************************/ -ACPI_EXTERN ACPI_FIXED_EVENT_INFO acpi_gbl_fixed_event_handlers[NUM_FIXED_EVENTS]; +ACPI_EXTERN ACPI_FIXED_EVENT_INFO acpi_gbl_fixed_event_handlers[ACPI_NUM_FIXED_EVENTS]; ACPI_EXTERN ACPI_HANDLE acpi_gbl_gpe_obj_handle; ACPI_EXTERN u32 acpi_gbl_gpe_register_count; @@ -255,12 +249,12 @@ * This table is needed because the GPE numbers supported by block 1 do not * have to be contiguous with the GPE numbers supported by block 0. */ -ACPI_EXTERN u8 acpi_gbl_gpe_valid [NUM_GPE]; +ACPI_EXTERN u8 acpi_gbl_gpe_valid [ACPI_NUM_GPE]; /* Acpi_event counter for debug only */ #ifdef ACPI_DEBUG -ACPI_EXTERN u32 acpi_gbl_event_count[NUM_FIXED_EVENTS]; +ACPI_EXTERN u32 acpi_gbl_event_count[ACPI_NUM_FIXED_EVENTS]; #endif diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/achware.h linux/drivers/acpi/include/achware.h --- v2.4.5/linux/drivers/acpi/include/achware.h Mon Jan 29 10:15:59 2001 +++ linux/drivers/acpi/include/achware.h Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: achware.h -- hardware specific interfaces - * $Revision: 53 $ + * $Revision: 55 $ * *****************************************************************************/ @@ -82,14 +82,14 @@ u32 acpi_hw_low_level_read ( u32 width, - ACPI_GAS *reg, + ACPI_GENERIC_ADDRESS *reg, u32 offset); void acpi_hw_low_level_write ( u32 width, u32 value, - ACPI_GAS *reg, + ACPI_GENERIC_ADDRESS *reg, u32 offset); void diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/acinterp.h linux/drivers/acpi/include/acinterp.h --- v2.4.5/linux/drivers/acpi/include/acinterp.h Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/include/acinterp.h Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acinterp.h - Interpreter subcomponent prototypes and defines - * $Revision: 92 $ + * $Revision: 102 $ * *****************************************************************************/ @@ -48,7 +48,7 @@ ACPI_STATUS -acpi_aml_resolve_operands ( +acpi_ex_resolve_operands ( u16 opcode, ACPI_OPERAND_OBJECT **stack_ptr, ACPI_WALK_STATE *walk_state); @@ -59,11 +59,11 @@ */ ACPI_STATUS -acpi_aml_load_table ( +acpi_ex_load_table ( ACPI_TABLE_TYPE table_id); ACPI_STATUS -acpi_aml_execute_method ( +acpi_ex_execute_method ( ACPI_NAMESPACE_NODE *method_node, ACPI_OPERAND_OBJECT **params, ACPI_OPERAND_OBJECT **return_obj_desc); @@ -74,23 +74,23 @@ */ ACPI_STATUS -acpi_aml_convert_to_integer ( +acpi_ex_convert_to_integer ( ACPI_OPERAND_OBJECT **obj_desc, ACPI_WALK_STATE *walk_state); ACPI_STATUS -acpi_aml_convert_to_buffer ( +acpi_ex_convert_to_buffer ( ACPI_OPERAND_OBJECT **obj_desc, ACPI_WALK_STATE *walk_state); ACPI_STATUS -acpi_aml_convert_to_string ( +acpi_ex_convert_to_string ( ACPI_OPERAND_OBJECT **obj_desc, ACPI_WALK_STATE *walk_state); ACPI_STATUS -acpi_aml_convert_to_target_type ( - OBJECT_TYPE_INTERNAL destination_type, +acpi_ex_convert_to_target_type ( + ACPI_OBJECT_TYPE8 destination_type, ACPI_OPERAND_OBJECT **obj_desc, ACPI_WALK_STATE *walk_state); @@ -100,110 +100,164 @@ */ ACPI_STATUS -acpi_aml_read_field ( +acpi_ex_extract_from_field ( ACPI_OPERAND_OBJECT *obj_desc, void *buffer, - u32 buffer_length, - u32 byte_length, - u32 datum_length, - u32 bit_granularity, - u32 byte_granularity); + u32 buffer_length); ACPI_STATUS -acpi_aml_write_field ( +acpi_ex_insert_into_field ( ACPI_OPERAND_OBJECT *obj_desc, void *buffer, - u32 buffer_length, - u32 byte_length, - u32 datum_length, - u32 bit_granularity, - u32 byte_granularity); + u32 buffer_length); ACPI_STATUS -acpi_aml_setup_field ( +acpi_ex_setup_field ( ACPI_OPERAND_OBJECT *obj_desc, - ACPI_OPERAND_OBJECT *rgn_desc, - u32 field_bit_width); + u32 field_byte_offset); ACPI_STATUS -acpi_aml_read_field_data ( +acpi_ex_read_field_datum ( ACPI_OPERAND_OBJECT *obj_desc, u32 field_byte_offset, - u32 field_bit_width, u32 *value); ACPI_STATUS -acpi_aml_access_named_field ( +acpi_ex_common_access_field ( u32 mode, - ACPI_HANDLE named_field, + ACPI_OPERAND_OBJECT *obj_desc, + void *buffer, + u32 buffer_length); + + +ACPI_STATUS +acpi_ex_access_index_field ( + u32 mode, + ACPI_OPERAND_OBJECT *obj_desc, + void *buffer, + u32 buffer_length); + +ACPI_STATUS +acpi_ex_access_bank_field ( + u32 mode, + ACPI_OPERAND_OBJECT *obj_desc, + void *buffer, + u32 buffer_length); + +ACPI_STATUS +acpi_ex_access_region_field ( + u32 mode, + ACPI_OPERAND_OBJECT *obj_desc, + void *buffer, + u32 buffer_length); + + +ACPI_STATUS +acpi_ex_access_buffer_field ( + u32 mode, + ACPI_OPERAND_OBJECT *obj_desc, void *buffer, - u32 length); + u32 buffer_length); + +ACPI_STATUS +acpi_ex_read_data_from_field ( + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_OPERAND_OBJECT **ret_buffer_desc); + +ACPI_STATUS +acpi_ex_write_data_to_field ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OPERAND_OBJECT *obj_desc); /* * ammisc - ACPI AML (p-code) execution - specific opcodes */ ACPI_STATUS -acpi_aml_exec_create_field ( +acpi_ex_create_buffer_field ( u8 *aml_ptr, u32 aml_length, ACPI_NAMESPACE_NODE *node, ACPI_WALK_STATE *walk_state); ACPI_STATUS -acpi_aml_exec_reconfiguration ( +acpi_ex_reconfiguration ( u16 opcode, ACPI_WALK_STATE *walk_state); ACPI_STATUS -acpi_aml_exec_fatal ( +acpi_ex_fatal ( ACPI_WALK_STATE *walk_state); ACPI_STATUS -acpi_aml_exec_index ( +acpi_ex_index ( ACPI_WALK_STATE *walk_state, ACPI_OPERAND_OBJECT **return_desc); ACPI_STATUS -acpi_aml_exec_match ( +acpi_ex_match ( ACPI_WALK_STATE *walk_state, ACPI_OPERAND_OBJECT **return_desc); ACPI_STATUS -acpi_aml_exec_create_mutex ( +acpi_ex_create_mutex ( ACPI_WALK_STATE *walk_state); ACPI_STATUS -acpi_aml_exec_create_processor ( +acpi_ex_create_processor ( ACPI_PARSE_OBJECT *op, - ACPI_HANDLE processor_nTE); + ACPI_NAMESPACE_NODE *processor_node); ACPI_STATUS -acpi_aml_exec_create_power_resource ( +acpi_ex_create_power_resource ( ACPI_PARSE_OBJECT *op, - ACPI_HANDLE processor_nTE); + ACPI_NAMESPACE_NODE *power_node); ACPI_STATUS -acpi_aml_exec_create_region ( +acpi_ex_create_region ( u8 *aml_ptr, - u32 acpi_aml_length, + u32 aml_length, u8 region_space, ACPI_WALK_STATE *walk_state); ACPI_STATUS -acpi_aml_exec_create_event ( +acpi_ex_create_event ( ACPI_WALK_STATE *walk_state); ACPI_STATUS -acpi_aml_exec_create_alias ( +acpi_ex_create_alias ( ACPI_WALK_STATE *walk_state); ACPI_STATUS -acpi_aml_exec_create_method ( +acpi_ex_create_method ( u8 *aml_ptr, - u32 acpi_aml_length, + u32 aml_length, u32 method_flags, - ACPI_HANDLE method); + ACPI_NAMESPACE_NODE *method); + + +/* + * ammutex - mutex support + */ + +ACPI_STATUS +acpi_ex_acquire_mutex ( + ACPI_OPERAND_OBJECT *time_desc, + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ex_release_mutex ( + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ex_release_all_mutexes ( + ACPI_OPERAND_OBJECT *mutex_list); + +void +acpi_ex_unlink_mutex ( + ACPI_OPERAND_OBJECT *obj_desc); /* @@ -211,32 +265,36 @@ */ ACPI_STATUS -acpi_aml_prep_def_field_value ( +acpi_ex_prep_common_field_object ( + ACPI_OPERAND_OBJECT *obj_desc, + u8 field_flags, + u32 field_position, + u32 field_length); + +ACPI_STATUS +acpi_ex_prep_region_field_value ( ACPI_NAMESPACE_NODE *node, ACPI_HANDLE region, u8 field_flags, - u8 field_attribute, u32 field_position, u32 field_length); ACPI_STATUS -acpi_aml_prep_bank_field_value ( +acpi_ex_prep_bank_field_value ( ACPI_NAMESPACE_NODE *node, - ACPI_HANDLE region, - ACPI_HANDLE bank_reg, + ACPI_NAMESPACE_NODE *region_node, + ACPI_NAMESPACE_NODE *bank_register_node, u32 bank_val, u8 field_flags, - u8 field_attribute, u32 field_position, u32 field_length); ACPI_STATUS -acpi_aml_prep_index_field_value ( +acpi_ex_prep_index_field_value ( ACPI_NAMESPACE_NODE *node, - ACPI_HANDLE index_reg, - ACPI_HANDLE data_reg, + ACPI_NAMESPACE_NODE *index_reg, + ACPI_NAMESPACE_NODE *data_reg, u8 field_flags, - u8 field_attribute, u32 field_position, u32 field_length); @@ -245,47 +303,43 @@ * amsystem - Interface to OS services */ -u16 -acpi_aml_system_thread_id ( - void); - ACPI_STATUS -acpi_aml_system_do_notify_op ( +acpi_ex_system_do_notify_op ( ACPI_OPERAND_OBJECT *value, ACPI_OPERAND_OBJECT *obj_desc); void -acpi_aml_system_do_suspend( +acpi_ex_system_do_suspend( u32 time); void -acpi_aml_system_do_stall ( +acpi_ex_system_do_stall ( u32 time); ACPI_STATUS -acpi_aml_system_acquire_mutex( +acpi_ex_system_acquire_mutex( ACPI_OPERAND_OBJECT *time, ACPI_OPERAND_OBJECT *obj_desc); ACPI_STATUS -acpi_aml_system_release_mutex( +acpi_ex_system_release_mutex( ACPI_OPERAND_OBJECT *obj_desc); ACPI_STATUS -acpi_aml_system_signal_event( +acpi_ex_system_signal_event( ACPI_OPERAND_OBJECT *obj_desc); ACPI_STATUS -acpi_aml_system_wait_event( +acpi_ex_system_wait_event( ACPI_OPERAND_OBJECT *time, ACPI_OPERAND_OBJECT *obj_desc); ACPI_STATUS -acpi_aml_system_reset_event( +acpi_ex_system_reset_event( ACPI_OPERAND_OBJECT *obj_desc); ACPI_STATUS -acpi_aml_system_wait_semaphore ( +acpi_ex_system_wait_semaphore ( ACPI_HANDLE semaphore, u32 timeout); @@ -295,18 +349,18 @@ */ ACPI_STATUS -acpi_aml_exec_monadic1 ( +acpi_ex_monadic1 ( u16 opcode, ACPI_WALK_STATE *walk_state); ACPI_STATUS -acpi_aml_exec_monadic2 ( +acpi_ex_monadic2 ( u16 opcode, ACPI_WALK_STATE *walk_state, ACPI_OPERAND_OBJECT **return_desc); ACPI_STATUS -acpi_aml_exec_monadic2_r ( +acpi_ex_monadic2_r ( u16 opcode, ACPI_WALK_STATE *walk_state, ACPI_OPERAND_OBJECT **return_desc); @@ -317,24 +371,24 @@ */ ACPI_STATUS -acpi_aml_exec_dyadic1 ( +acpi_ex_dyadic1 ( u16 opcode, ACPI_WALK_STATE *walk_state); ACPI_STATUS -acpi_aml_exec_dyadic2 ( +acpi_ex_dyadic2 ( u16 opcode, ACPI_WALK_STATE *walk_state, ACPI_OPERAND_OBJECT **return_desc); ACPI_STATUS -acpi_aml_exec_dyadic2_r ( +acpi_ex_dyadic2_r ( u16 opcode, ACPI_WALK_STATE *walk_state, ACPI_OPERAND_OBJECT **return_desc); ACPI_STATUS -acpi_aml_exec_dyadic2_s ( +acpi_ex_dyadic2_s ( u16 opcode, ACPI_WALK_STATE *walk_state, ACPI_OPERAND_OBJECT **return_desc); @@ -345,22 +399,22 @@ */ ACPI_STATUS -acpi_aml_resolve_to_value ( +acpi_ex_resolve_to_value ( ACPI_OPERAND_OBJECT **stack_ptr, ACPI_WALK_STATE *walk_state); ACPI_STATUS -acpi_aml_resolve_node_to_value ( +acpi_ex_resolve_node_to_value ( ACPI_NAMESPACE_NODE **stack_ptr, ACPI_WALK_STATE *walk_state); ACPI_STATUS -acpi_aml_resolve_object_to_value ( +acpi_ex_resolve_object_to_value ( ACPI_OPERAND_OBJECT **stack_ptr, ACPI_WALK_STATE *walk_state); ACPI_STATUS -acpi_aml_get_field_unit_value ( +acpi_ex_get_buffer_field_value ( ACPI_OPERAND_OBJECT *field_desc, ACPI_OPERAND_OBJECT *result_desc); @@ -370,18 +424,18 @@ */ void -acpi_aml_show_hex_value ( +acpi_ex_show_hex_value ( u32 byte_count, u8 *aml_ptr, u32 lead_space); ACPI_STATUS -acpi_aml_dump_operand ( +acpi_ex_dump_operand ( ACPI_OPERAND_OBJECT *entry_desc); void -acpi_aml_dump_operands ( +acpi_ex_dump_operands ( ACPI_OPERAND_OBJECT **operands, OPERATING_MODE interpreter_mode, NATIVE_CHAR *ident, @@ -391,13 +445,13 @@ u32 line_number); void -acpi_aml_dump_object_descriptor ( +acpi_ex_dump_object_descriptor ( ACPI_OPERAND_OBJECT *object, u32 flags); void -acpi_aml_dump_node ( +acpi_ex_dump_node ( ACPI_NAMESPACE_NODE *node, u32 flags); @@ -407,28 +461,28 @@ */ NATIVE_CHAR * -acpi_aml_allocate_name_string ( +acpi_ex_allocate_name_string ( u32 prefix_count, u32 num_name_segs); u32 -acpi_aml_good_char ( +acpi_ex_good_char ( u32 character); ACPI_STATUS -acpi_aml_exec_name_segment ( +acpi_ex_name_segment ( u8 **in_aml_address, NATIVE_CHAR *name_string); ACPI_STATUS -acpi_aml_get_name_string ( - OBJECT_TYPE_INTERNAL data_type, +acpi_ex_get_name_string ( + ACPI_OBJECT_TYPE8 data_type, u8 *in_aml_address, NATIVE_CHAR **out_name_string, u32 *out_name_length); ACPI_STATUS -acpi_aml_do_name ( +acpi_ex_do_name ( ACPI_OBJECT_TYPE data_type, OPERATING_MODE load_exec_mode); @@ -438,25 +492,25 @@ */ ACPI_STATUS -acpi_aml_exec_store ( +acpi_ex_store ( ACPI_OPERAND_OBJECT *val_desc, ACPI_OPERAND_OBJECT *dest_desc, ACPI_WALK_STATE *walk_state); ACPI_STATUS -acpi_aml_store_object_to_index ( +acpi_ex_store_object_to_index ( ACPI_OPERAND_OBJECT *val_desc, ACPI_OPERAND_OBJECT *dest_desc, ACPI_WALK_STATE *walk_state); ACPI_STATUS -acpi_aml_store_object_to_node ( +acpi_ex_store_object_to_node ( ACPI_OPERAND_OBJECT *source_desc, ACPI_NAMESPACE_NODE *node, ACPI_WALK_STATE *walk_state); ACPI_STATUS -acpi_aml_store_object_to_object ( +acpi_ex_store_object_to_object ( ACPI_OPERAND_OBJECT *source_desc, ACPI_OPERAND_OBJECT *dest_desc, ACPI_WALK_STATE *walk_state); @@ -467,15 +521,15 @@ */ ACPI_STATUS -acpi_aml_resolve_object ( +acpi_ex_resolve_object ( ACPI_OPERAND_OBJECT **source_desc_ptr, - OBJECT_TYPE_INTERNAL target_type, + ACPI_OBJECT_TYPE8 target_type, ACPI_WALK_STATE *walk_state); ACPI_STATUS -acpi_aml_store_object ( +acpi_ex_store_object ( ACPI_OPERAND_OBJECT *source_desc, - OBJECT_TYPE_INTERNAL target_type, + ACPI_OBJECT_TYPE8 target_type, ACPI_OPERAND_OBJECT **target_desc_ptr, ACPI_WALK_STATE *walk_state); @@ -485,32 +539,32 @@ */ ACPI_STATUS -acpi_aml_copy_buffer_to_buffer ( +acpi_ex_copy_buffer_to_buffer ( ACPI_OPERAND_OBJECT *source_desc, ACPI_OPERAND_OBJECT *target_desc); ACPI_STATUS -acpi_aml_copy_string_to_string ( +acpi_ex_copy_string_to_string ( ACPI_OPERAND_OBJECT *source_desc, ACPI_OPERAND_OBJECT *target_desc); ACPI_STATUS -acpi_aml_copy_integer_to_index_field ( +acpi_ex_copy_integer_to_index_field ( ACPI_OPERAND_OBJECT *source_desc, ACPI_OPERAND_OBJECT *target_desc); ACPI_STATUS -acpi_aml_copy_integer_to_bank_field ( +acpi_ex_copy_integer_to_bank_field ( ACPI_OPERAND_OBJECT *source_desc, ACPI_OPERAND_OBJECT *target_desc); ACPI_STATUS -acpi_aml_copy_data_to_named_field ( +acpi_ex_copy_data_to_named_field ( ACPI_OPERAND_OBJECT *source_desc, ACPI_NAMESPACE_NODE *node); ACPI_STATUS -acpi_aml_copy_integer_to_field_unit ( +acpi_ex_copy_integer_to_buffer_field ( ACPI_OPERAND_OBJECT *source_desc, ACPI_OPERAND_OBJECT *target_desc); @@ -518,43 +572,43 @@ * amutils - interpreter/scanner utilities */ -void -acpi_aml_enter_interpreter ( +ACPI_STATUS +acpi_ex_enter_interpreter ( void); void -acpi_aml_exit_interpreter ( +acpi_ex_exit_interpreter ( void); void -acpi_aml_truncate_for32bit_table ( +acpi_ex_truncate_for32bit_table ( ACPI_OPERAND_OBJECT *obj_desc, ACPI_WALK_STATE *walk_state); u8 -acpi_aml_validate_object_type ( +acpi_ex_validate_object_type ( ACPI_OBJECT_TYPE type); u8 -acpi_aml_acquire_global_lock ( +acpi_ex_acquire_global_lock ( u32 rule); ACPI_STATUS -acpi_aml_release_global_lock ( +acpi_ex_release_global_lock ( u8 locked); u32 -acpi_aml_digits_needed ( +acpi_ex_digits_needed ( ACPI_INTEGER value, u32 base); ACPI_STATUS -acpi_aml_eisa_id_to_string ( +acpi_ex_eisa_id_to_string ( u32 numeric_id, NATIVE_CHAR *out_string); ACPI_STATUS -acpi_aml_unsigned_integer_to_string ( +acpi_ex_unsigned_integer_to_string ( ACPI_INTEGER value, NATIVE_CHAR *out_string); @@ -564,7 +618,7 @@ */ ACPI_STATUS -acpi_aml_system_memory_space_handler ( +acpi_ex_system_memory_space_handler ( u32 function, ACPI_PHYSICAL_ADDRESS address, u32 bit_width, @@ -573,7 +627,7 @@ void *region_context); ACPI_STATUS -acpi_aml_system_io_space_handler ( +acpi_ex_system_io_space_handler ( u32 function, ACPI_PHYSICAL_ADDRESS address, u32 bit_width, @@ -582,7 +636,7 @@ void *region_context); ACPI_STATUS -acpi_aml_pci_config_space_handler ( +acpi_ex_pci_config_space_handler ( u32 function, ACPI_PHYSICAL_ADDRESS address, u32 bit_width, @@ -591,7 +645,7 @@ void *region_context); ACPI_STATUS -acpi_aml_embedded_controller_space_handler ( +acpi_ex_embedded_controller_space_handler ( u32 function, ACPI_PHYSICAL_ADDRESS address, u32 bit_width, @@ -600,7 +654,7 @@ void *region_context); ACPI_STATUS -acpi_aml_sm_bus_space_handler ( +acpi_ex_sm_bus_space_handler ( u32 function, ACPI_PHYSICAL_ADDRESS address, u32 bit_width, diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/aclinux.h linux/drivers/acpi/include/aclinux.h --- v2.4.5/linux/drivers/acpi/include/aclinux.h Fri Feb 16 16:06:17 2001 +++ linux/drivers/acpi/include/aclinux.h Wed Dec 31 16:00:00 1969 @@ -1,55 +0,0 @@ -/****************************************************************************** - * - * Name: aclinux.h - OS specific defines, etc. - * $Revision: 9 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 - */ - -#ifndef __ACLINUX_H__ -#define __ACLINUX_H__ - -#define ACPI_OS_NAME "Linux" - -#include -#include -#include -#include -#include -#include - -/* Linux uses GCC */ - -#include "acgcc.h" - -#undef DEBUGGER_THREADING -#define DEBUGGER_THREADING DEBUGGER_SINGLE_THREADED - -#ifndef _IA64 -/* Linux ia32 can't do int64 well */ -#define ACPI_NO_INTEGER64_SUPPORT -/* And the ia32 kernel doesn't include 64-bit divide support */ -#define ACPI_DIV64(dividend, divisor) do_div(dividend, divisor) -#else -#define ACPI_DIV64(dividend, divisor) ACPI_DIVIDE(dividend, divisor) -#endif - - -#endif /* __ACLINUX_H__ */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/aclocal.h linux/drivers/acpi/include/aclocal.h --- v2.4.5/linux/drivers/acpi/include/aclocal.h Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/include/aclocal.h Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: aclocal.h - Internal data types used across the ACPI subsystem - * $Revision: 104 $ + * $Revision: 123 $ * *****************************************************************************/ @@ -27,20 +27,24 @@ #define __ACLOCAL_H__ -#define WAIT_FOREVER ((u32) -1) +#define WAIT_FOREVER ((u32) -1) -typedef void* ACPI_MUTEX; -typedef u32 ACPI_MUTEX_HANDLE; +typedef void* ACPI_MUTEX; +typedef u32 ACPI_MUTEX_HANDLE; +#define ACPI_MEMORY_MODE 0x01 +#define ACPI_LOGICAL_ADDRESSING 0x00 +#define ACPI_PHYSICAL_ADDRESSING 0x01 + /* Object descriptor types */ -#define ACPI_CACHED_OBJECT 0x11 /* ORed in when object is cached */ -#define ACPI_DESC_TYPE_STATE 0x22 -#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 ACPI_CACHED_OBJECT 0x11 /* ORed in when object is cached */ +#define ACPI_DESC_TYPE_STATE 0x22 +#define ACPI_DESC_TYPE_WALK 0x44 +#define ACPI_DESC_TYPE_PARSER 0x66 +#define ACPI_DESC_TYPE_INTERNAL 0x88 +#define ACPI_DESC_TYPE_NAMED 0xAA /***************************************************************************** @@ -52,26 +56,30 @@ /* * Predefined handles for the mutex objects used within the subsystem - * All mutex objects are automatically created by Acpi_cm_mutex_initialize. + * All mutex objects are automatically created by Acpi_ut_mutex_initialize. + * + * The acquire/release ordering protocol is implied via this list. Mutexes + * with a lower value must be acquired before mutexes with a higher value. + * * NOTE: any changes here must be reflected in the Acpi_gbl_Mutex_names table also! */ -#define ACPI_MTX_HARDWARE 0 -#define ACPI_MTX_MEMORY 1 -#define ACPI_MTX_CACHES 2 -#define ACPI_MTX_TABLES 3 -#define ACPI_MTX_PARSER 4 -#define ACPI_MTX_DISPATCHER 5 -#define ACPI_MTX_INTERPRETER 6 -#define ACPI_MTX_EXECUTE 7 -#define ACPI_MTX_NAMESPACE 8 -#define ACPI_MTX_EVENTS 9 -#define ACPI_MTX_OP_REGIONS 10 -#define ACPI_MTX_DEBUG_CMD_READY 11 -#define ACPI_MTX_DEBUG_CMD_COMPLETE 12 +#define ACPI_MTX_EXECUTE 0 +#define ACPI_MTX_INTERPRETER 1 +#define ACPI_MTX_PARSER 2 +#define ACPI_MTX_DISPATCHER 3 +#define ACPI_MTX_TABLES 4 +#define ACPI_MTX_OP_REGIONS 5 +#define ACPI_MTX_NAMESPACE 6 +#define ACPI_MTX_EVENTS 7 +#define ACPI_MTX_HARDWARE 8 +#define ACPI_MTX_CACHES 9 +#define ACPI_MTX_MEMORY 10 +#define ACPI_MTX_DEBUG_CMD_COMPLETE 11 +#define ACPI_MTX_DEBUG_CMD_READY 12 -#define MAX_MTX 12 -#define NUM_MTX MAX_MTX+1 +#define MAX_MTX 12 +#define NUM_MTX MAX_MTX+1 #if defined(ACPI_DEBUG) || defined(ENABLE_DEBUGGER) @@ -81,19 +89,19 @@ static NATIVE_CHAR *acpi_gbl_mutex_names[] = { - "ACPI_MTX_Hardware", - "ACPI_MTX_Memory", - "ACPI_MTX_Caches", - "ACPI_MTX_Tables", + "ACPI_MTX_Execute", + "ACPI_MTX_Interpreter", "ACPI_MTX_Parser", "ACPI_MTX_Dispatcher", - "ACPI_MTX_Interpreter", - "ACPI_MTX_Execute", + "ACPI_MTX_Tables", + "ACPI_MTX_Op_regions", "ACPI_MTX_Namespace", "ACPI_MTX_Events", - "ACPI_MTX_Op_regions", + "ACPI_MTX_Hardware", + "ACPI_MTX_Caches", + "ACPI_MTX_Memory", + "ACPI_MTX_Debug_cmd_complete", "ACPI_MTX_Debug_cmd_ready", - "ACPI_MTX_Debug_cmd_complete" }; #endif @@ -106,26 +114,38 @@ { ACPI_MUTEX mutex; u32 use_count; - u8 locked; + u32 owner_id; } ACPI_MUTEX_INFO; +/* This owner ID means that the mutex is not in use (unlocked) */ + +#define ACPI_MUTEX_NOT_ACQUIRED (u32) (-1) + /* Lock flag parameter for various interfaces */ -#define ACPI_MTX_DO_NOT_LOCK 0 -#define ACPI_MTX_LOCK 1 +#define ACPI_MTX_DO_NOT_LOCK 0 +#define ACPI_MTX_LOCK 1 -typedef u16 ACPI_OWNER_ID; -#define OWNER_TYPE_TABLE 0x0 -#define OWNER_TYPE_METHOD 0x1 -#define FIRST_METHOD_ID 0x0000 -#define FIRST_TABLE_ID 0x8000 +typedef u16 ACPI_OWNER_ID; +#define OWNER_TYPE_TABLE 0x0 +#define OWNER_TYPE_METHOD 0x1 +#define FIRST_METHOD_ID 0x0000 +#define FIRST_TABLE_ID 0x8000 /* TBD: [Restructure] get rid of the need for this! */ -#define TABLE_ID_DSDT (ACPI_OWNER_ID) 0x8000 +#define TABLE_ID_DSDT (ACPI_OWNER_ID) 0x8000 + + +/* Field access granularities */ + +#define ACPI_FIELD_BYTE_GRANULARITY 1 +#define ACPI_FIELD_WORD_GRANULARITY 2 +#define ACPI_FIELD_DWORD_GRANULARITY 4 +#define ACPI_FIELD_QWORD_GRANULARITY 8 /***************************************************************************** * @@ -175,13 +195,15 @@ /* Node flags */ -#define ANOBJ_AML_ATTACHMENT 0x01 -#define ANOBJ_END_OF_PEER_LIST 0x02 -#define ANOBJ_DATA_WIDTH_32 0x04 /* Parent table is 64-bits */ -#define ANOBJ_METHOD_ARG 0x08 -#define ANOBJ_METHOD_LOCAL 0x10 -#define ANOBJ_METHOD_NO_RETVAL 0x20 -#define ANOBJ_METHOD_SOME_NO_RETVAL 0x40 +#define ANOBJ_AML_ATTACHMENT 0x01 +#define ANOBJ_END_OF_PEER_LIST 0x02 +#define ANOBJ_DATA_WIDTH_32 0x04 /* Parent table is 64-bits */ +#define ANOBJ_METHOD_ARG 0x08 +#define ANOBJ_METHOD_LOCAL 0x10 +#define ANOBJ_METHOD_NO_RETVAL 0x20 +#define ANOBJ_METHOD_SOME_NO_RETVAL 0x40 + +#define ANOBJ_IS_BIT_OFFSET 0x80 /* @@ -225,19 +247,36 @@ /* * Predefined Namespace items */ -#define ACPI_MAX_ADDRESS_SPACE 255 -#define ACPI_NUM_ADDRESS_SPACES 256 - - typedef struct { NATIVE_CHAR *name; - ACPI_OBJECT_TYPE type; + ACPI_OBJECT_TYPE8 type; NATIVE_CHAR *val; } PREDEFINED_NAMES; +/* Object types used during package copies */ + + +#define ACPI_COPY_TYPE_SIMPLE 0 +#define ACPI_COPY_TYPE_PACKAGE 1 + +/* Info structure used to convert external<->internal namestrings */ + +typedef struct acpi_namestring_info +{ + NATIVE_CHAR *external_name; + NATIVE_CHAR *next_external_char; + NATIVE_CHAR *internal_name; + u32 length; + u32 num_segments; + u32 num_carats; + u8 fully_qualified; + +} ACPI_NAMESTRING_INFO; + + /***************************************************************************** * * Event typedefs and structs @@ -247,19 +286,19 @@ /* Status bits. */ -#define ACPI_STATUS_PMTIMER 0x0001 -#define ACPI_STATUS_GLOBAL 0x0020 -#define ACPI_STATUS_POWER_BUTTON 0x0100 -#define ACPI_STATUS_SLEEP_BUTTON 0x0200 -#define ACPI_STATUS_RTC_ALARM 0x0400 +#define ACPI_STATUS_PMTIMER 0x0001 +#define ACPI_STATUS_GLOBAL 0x0020 +#define ACPI_STATUS_POWER_BUTTON 0x0100 +#define ACPI_STATUS_SLEEP_BUTTON 0x0200 +#define ACPI_STATUS_RTC_ALARM 0x0400 /* Enable bits. */ -#define ACPI_ENABLE_PMTIMER 0x0001 -#define ACPI_ENABLE_GLOBAL 0x0020 -#define ACPI_ENABLE_POWER_BUTTON 0x0100 -#define ACPI_ENABLE_SLEEP_BUTTON 0x0200 -#define ACPI_ENABLE_RTC_ALARM 0x0400 +#define ACPI_ENABLE_PMTIMER 0x0001 +#define ACPI_ENABLE_GLOBAL 0x0020 +#define ACPI_ENABLE_POWER_BUTTON 0x0100 +#define ACPI_ENABLE_SLEEP_BUTTON 0x0200 +#define ACPI_ENABLE_RTC_ALARM 0x0400 /* @@ -268,10 +307,10 @@ typedef struct { - ADDRESS_SPACE_HANDLER handler; + ACPI_ADR_SPACE_HANDLER handler; void *context; -} ACPI_ADDRESS_SPACE_INFO; +} ACPI_ADR_SPACE_INFO; /* Values and addresses of the GPE registers (both banks) */ @@ -287,8 +326,8 @@ } ACPI_GPE_REGISTERS; -#define ACPI_GPE_LEVEL_TRIGGERED 1 -#define ACPI_GPE_EDGE_TRIGGERED 2 +#define ACPI_GPE_LEVEL_TRIGGERED 1 +#define ACPI_GPE_EDGE_TRIGGERED 2 /* Information about each particular GPE level */ @@ -298,7 +337,7 @@ u8 type; /* Level or Edge */ ACPI_HANDLE method_handle; /* Method handle for direct (fast) execution */ - GPE_HANDLER handler; /* Address of handler, if any */ + ACPI_GPE_HANDLER handler; /* Address of handler, if any */ void *context; /* Context to be passed to handler */ } ACPI_GPE_LEVEL_INFO; @@ -308,7 +347,7 @@ typedef struct { - FIXED_EVENT_HANDLER handler; /* Address of handler. */ + ACPI_EVENT_HANDLER handler; /* Address of handler. */ void *context; /* Context to be passed to handler */ } ACPI_FIXED_EVENT_INFO; @@ -332,16 +371,18 @@ ****************************************************************************/ -#define CONTROL_NORMAL 0xC0 -#define CONTROL_CONDITIONAL_EXECUTING 0xC1 -#define CONTROL_PREDICATE_EXECUTING 0xC2 -#define CONTROL_PREDICATE_FALSE 0xC3 -#define CONTROL_PREDICATE_TRUE 0xC4 +#define CONTROL_NORMAL 0xC0 +#define CONTROL_CONDITIONAL_EXECUTING 0xC1 +#define CONTROL_PREDICATE_EXECUTING 0xC2 +#define CONTROL_PREDICATE_FALSE 0xC3 +#define CONTROL_PREDICATE_TRUE 0xC4 -/* Forward declaration */ +/* Forward declarations */ struct acpi_walk_state; -struct acpi_parse_obj ; +struct acpi_walk_list; +struct acpi_parse_obj; +struct acpi_obj_mutex; #define ACPI_STATE_COMMON /* Two 32-bit fields and a pointer */\ @@ -401,7 +442,6 @@ /* * Scope state - current scope during namespace lookups */ - typedef struct acpi_scope_state { ACPI_STATE_COMMON @@ -436,6 +476,19 @@ } ACPI_RESULT_VALUES; +/* + * Notify info - used to pass info to the deferred notify + * handler/dispatcher. + */ +typedef struct acpi_notify_info +{ + ACPI_STATE_COMMON + ACPI_NAMESPACE_NODE *node; + union acpi_operand_obj *handler_obj; + +} ACPI_NOTIFY_INFO; + + /* Generic state is union of structs above */ typedef union acpi_gen_state @@ -447,6 +500,7 @@ ACPI_PSCOPE_STATE parse_scope; ACPI_PKG_STATE pkg; ACPI_RESULT_VALUES results; + ACPI_NOTIFY_INFO notify; } ACPI_GENERIC_STATE; @@ -470,19 +524,18 @@ * ****************************************************************************/ - -#define ACPI_OP_CLASS_MASK 0x1F -#define ACPI_OP_ARGS_MASK 0x20 -#define ACPI_OP_TYPE_MASK 0xC0 - -#define ACPI_OP_TYPE_OPCODE 0x00 -#define ACPI_OP_TYPE_ASCII 0x40 -#define ACPI_OP_TYPE_PREFIX 0x80 -#define ACPI_OP_TYPE_UNKNOWN 0xC0 - -#define ACPI_GET_OP_CLASS(a) ((a)->flags & ACPI_OP_CLASS_MASK) -#define ACPI_GET_OP_ARGS(a) ((a)->flags & ACPI_OP_ARGS_MASK) -#define ACPI_GET_OP_TYPE(a) ((a)->flags & ACPI_OP_TYPE_MASK) +#define ACPI_OP_CLASS_MASK 0x1F +#define ACPI_OP_ARGS_MASK 0x20 +#define ACPI_OP_TYPE_MASK 0xC0 + +#define ACPI_OP_TYPE_OPCODE 0x00 +#define ACPI_OP_TYPE_ASCII 0x40 +#define ACPI_OP_TYPE_PREFIX 0x80 +#define ACPI_OP_TYPE_UNKNOWN 0xC0 + +#define ACPI_GET_OP_CLASS(a) ((a)->flags & ACPI_OP_CLASS_MASK) +#define ACPI_GET_OP_ARGS(a) ((a)->flags & ACPI_OP_ARGS_MASK) +#define ACPI_GET_OP_TYPE(a) ((a)->flags & ACPI_OP_TYPE_MASK) /* @@ -572,130 +625,6 @@ /***************************************************************************** * - * Tree walking typedefs and structs - * - ****************************************************************************/ - - -/* - * Walk state - current state of a parse tree walk. Used for both a leisurely stroll through - * the tree (for whatever reason), and for control method execution. - */ - -#define NEXT_OP_DOWNWARD 1 -#define NEXT_OP_UPWARD 2 - -#define WALK_NON_METHOD 0 -#define WALK_METHOD 1 -#define WALK_METHOD_RESTART 2 - -typedef struct acpi_walk_state -{ - u8 data_type; /* To differentiate various internal objs */\ - ACPI_OWNER_ID owner_id; /* Owner of objects created during the walk */ - u8 last_predicate; /* Result of last predicate */ - u8 next_op_info; /* Info about Next_op */ - u8 num_operands; /* Stack pointer for Operands[] array */ - u8 current_result; /* */ - - struct acpi_walk_state *next; /* Next Walk_state in list */ - ACPI_PARSE_OBJECT *origin; /* Start of walk [Obsolete] */ - -/* TBD: Obsolete with removal of WALK procedure ? */ - ACPI_PARSE_OBJECT *prev_op; /* Last op that was processed */ - ACPI_PARSE_OBJECT *next_op; /* next op to be processed */ - - - ACPI_GENERIC_STATE *results; /* Stack of accumulated results */ - ACPI_GENERIC_STATE *control_state; /* List of control states (nested IFs) */ - ACPI_GENERIC_STATE *scope_info; /* Stack of nested scopes */ - ACPI_PARSE_STATE *parser_state; /* Current state of parser */ - u8 *aml_last_while; - ACPI_OPCODE_INFO *op_info; /* Info on current opcode */ - ACPI_PARSE_DOWNWARDS descending_callback; - ACPI_PARSE_UPWARDS ascending_callback; - - union acpi_operand_obj *return_desc; /* Return object, if any */ - union acpi_operand_obj *method_desc; /* Method descriptor if running a method */ - struct acpi_node *method_node; /* Method Node if running a method */ - ACPI_PARSE_OBJECT *method_call_op; /* Method_call Op if running a method */ - struct acpi_node *method_call_node; /* Called method Node*/ - union acpi_operand_obj *operands[OBJ_NUM_OPERANDS]; /* Operands passed to the interpreter */ - struct acpi_node arguments[MTH_NUM_ARGS]; /* Control method arguments */ - struct acpi_node local_variables[MTH_NUM_LOCALS]; /* Control method locals */ - u32 parse_flags; - u8 walk_type; - u8 return_used; - u16 opcode; /* Current AML opcode */ - u32 prev_arg_types; - - /* Debug support */ - - u32 method_breakpoint; - - -} ACPI_WALK_STATE; - - -/* - * Walk list - head of a tree of walk states. Multiple walk states are created when there - * are nested control methods executing. - */ -typedef struct acpi_walk_list -{ - - ACPI_WALK_STATE *walk_state; - -} ACPI_WALK_LIST; - - -/* Info used by Acpi_ps_init_objects */ - -typedef struct acpi_init_walk_info -{ - u16 method_count; - u16 op_region_count; - u16 field_count; - u16 op_region_init; - u16 field_init; - u16 object_count; - ACPI_TABLE_DESC *table_desc; - -} ACPI_INIT_WALK_INFO; - - -/* Info used by TBD */ - -typedef struct acpi_device_walk_info -{ - u16 device_count; - u16 num_STA; - u16 num_INI; - ACPI_TABLE_DESC *table_desc; - -} ACPI_DEVICE_WALK_INFO; - - -/* TBD: [Restructure] Merge with struct above */ - -typedef struct acpi_walk_info -{ - u32 debug_level; - u32 owner_id; - -} ACPI_WALK_INFO; - -typedef struct acpi_get_devices_info -{ - WALK_CALLBACK user_function; - void *context; - NATIVE_CHAR *hid; - -} ACPI_GET_DEVICES_INFO; - - -/***************************************************************************** - * * Hardware and PNP * ****************************************************************************/ @@ -703,20 +632,20 @@ /* PCI */ -#define PCI_ROOT_HID_STRING "PNP0A03" -#define PCI_ROOT_HID_VALUE 0x030AD041 /* EISAID("PNP0A03") */ +#define PCI_ROOT_HID_STRING "PNP0A03" +#define PCI_ROOT_HID_VALUE 0x030AD041 /* EISAID("PNP0A03") */ /* Sleep states */ -#define SLWA_DEBUG_LEVEL 4 -#define GTS_CALL 0 -#define GTS_WAKE 1 +#define SLWA_DEBUG_LEVEL 4 +#define GTS_CALL 0 +#define GTS_WAKE 1 /* Cx States */ -#define MAX_CX_STATE_LATENCY 0xFFFFFFFF -#define MAX_CX_STATES 4 +#define MAX_CX_STATE_LATENCY 0xFFFFFFFF +#define MAX_CX_STATES 4 /* @@ -725,13 +654,13 @@ * values as they are used in switch statements and offset calculations. */ -#define REGISTER_BLOCK_MASK 0xFF00 /* Register Block Id */ -#define BIT_IN_REGISTER_MASK 0x00FF /* Bit Id in the Register Block Id */ -#define BYTE_IN_REGISTER_MASK 0x00FF /* Register Offset in the Register Block */ - -#define REGISTER_BLOCK_ID(reg_id) (reg_id & REGISTER_BLOCK_MASK) -#define REGISTER_BIT_ID(reg_id) (reg_id & BIT_IN_REGISTER_MASK) -#define REGISTER_OFFSET(reg_id) (reg_id & BYTE_IN_REGISTER_MASK) +#define REGISTER_BLOCK_MASK 0xFF00 /* Register Block Id */ +#define BIT_IN_REGISTER_MASK 0x00FF /* Bit Id in the Register Block Id */ +#define BYTE_IN_REGISTER_MASK 0x00FF /* Register Offset in the Register Block */ + +#define REGISTER_BLOCK_ID(reg_id) (reg_id & REGISTER_BLOCK_MASK) +#define REGISTER_BIT_ID(reg_id) (reg_id & BIT_IN_REGISTER_MASK) +#define REGISTER_OFFSET(reg_id) (reg_id & BYTE_IN_REGISTER_MASK) /* * Access Rule @@ -746,94 +675,94 @@ /* * Register Block Id */ -#define PM1_STS 0x0100 -#define PM1_EN 0x0200 -#define PM1_CONTROL 0x0300 -#define PM1_a_CONTROL 0x0400 -#define PM1_b_CONTROL 0x0500 -#define PM2_CONTROL 0x0600 -#define PM_TIMER 0x0700 -#define PROCESSOR_BLOCK 0x0800 -#define GPE0_STS_BLOCK 0x0900 -#define GPE0_EN_BLOCK 0x0A00 -#define GPE1_STS_BLOCK 0x0B00 -#define GPE1_EN_BLOCK 0x0C00 -#define SMI_CMD_BLOCK 0x0D00 +#define PM1_STS 0x0100 +#define PM1_EN 0x0200 +#define PM1_CONTROL 0x0300 +#define PM1_a_CONTROL 0x0400 +#define PM1_b_CONTROL 0x0500 +#define PM2_CONTROL 0x0600 +#define PM_TIMER 0x0700 +#define PROCESSOR_BLOCK 0x0800 +#define GPE0_STS_BLOCK 0x0900 +#define GPE0_EN_BLOCK 0x0A00 +#define GPE1_STS_BLOCK 0x0B00 +#define GPE1_EN_BLOCK 0x0C00 +#define SMI_CMD_BLOCK 0x0D00 /* * Address space bitmasks for mmio or io spaces */ -#define SMI_CMD_ADDRESS_SPACE 0x01 -#define PM1_BLK_ADDRESS_SPACE 0x02 -#define PM2_CNT_BLK_ADDRESS_SPACE 0x04 -#define PM_TMR_BLK_ADDRESS_SPACE 0x08 -#define GPE0_BLK_ADDRESS_SPACE 0x10 -#define GPE1_BLK_ADDRESS_SPACE 0x20 +#define SMI_CMD_ADDRESS_SPACE 0x01 +#define PM1_BLK_ADDRESS_SPACE 0x02 +#define PM2_CNT_BLK_ADDRESS_SPACE 0x04 +#define PM_TMR_BLK_ADDRESS_SPACE 0x08 +#define GPE0_BLK_ADDRESS_SPACE 0x10 +#define GPE1_BLK_ADDRESS_SPACE 0x20 /* * Control bit definitions */ -#define TMR_STS (PM1_STS | 0x01) -#define BM_STS (PM1_STS | 0x02) -#define GBL_STS (PM1_STS | 0x03) -#define PWRBTN_STS (PM1_STS | 0x04) -#define SLPBTN_STS (PM1_STS | 0x05) -#define RTC_STS (PM1_STS | 0x06) -#define WAK_STS (PM1_STS | 0x07) - -#define TMR_EN (PM1_EN | 0x01) - /* no BM_EN */ -#define GBL_EN (PM1_EN | 0x03) -#define PWRBTN_EN (PM1_EN | 0x04) -#define SLPBTN_EN (PM1_EN | 0x05) -#define RTC_EN (PM1_EN | 0x06) -#define WAK_EN (PM1_EN | 0x07) - -#define SCI_EN (PM1_CONTROL | 0x01) -#define BM_RLD (PM1_CONTROL | 0x02) -#define GBL_RLS (PM1_CONTROL | 0x03) -#define SLP_TYPE_A (PM1_CONTROL | 0x04) -#define SLP_TYPE_B (PM1_CONTROL | 0x05) -#define SLP_EN (PM1_CONTROL | 0x06) - -#define ARB_DIS (PM2_CONTROL | 0x01) - -#define TMR_VAL (PM_TIMER | 0x01) - -#define GPE0_STS (GPE0_STS_BLOCK | 0x01) -#define GPE0_EN (GPE0_EN_BLOCK | 0x01) - -#define GPE1_STS (GPE1_STS_BLOCK | 0x01) -#define GPE1_EN (GPE1_EN_BLOCK | 0x01) - - -#define TMR_STS_MASK 0x0001 -#define BM_STS_MASK 0x0010 -#define GBL_STS_MASK 0x0020 -#define PWRBTN_STS_MASK 0x0100 -#define SLPBTN_STS_MASK 0x0200 -#define RTC_STS_MASK 0x0400 -#define WAK_STS_MASK 0x8000 - -#define ALL_FIXED_STS_BITS (TMR_STS_MASK | BM_STS_MASK | GBL_STS_MASK \ - | PWRBTN_STS_MASK | SLPBTN_STS_MASK \ - | RTC_STS_MASK | WAK_STS_MASK) - -#define TMR_EN_MASK 0x0001 -#define GBL_EN_MASK 0x0020 -#define PWRBTN_EN_MASK 0x0100 -#define SLPBTN_EN_MASK 0x0200 -#define RTC_EN_MASK 0x0400 - -#define SCI_EN_MASK 0x0001 -#define BM_RLD_MASK 0x0002 -#define GBL_RLS_MASK 0x0004 -#define SLP_TYPE_X_MASK 0x1C00 -#define SLP_EN_MASK 0x2000 +#define TMR_STS (PM1_STS | 0x01) +#define BM_STS (PM1_STS | 0x02) +#define GBL_STS (PM1_STS | 0x03) +#define PWRBTN_STS (PM1_STS | 0x04) +#define SLPBTN_STS (PM1_STS | 0x05) +#define RTC_STS (PM1_STS | 0x06) +#define WAK_STS (PM1_STS | 0x07) + +#define TMR_EN (PM1_EN | 0x01) + /* no BM_EN */ +#define GBL_EN (PM1_EN | 0x03) +#define PWRBTN_EN (PM1_EN | 0x04) +#define SLPBTN_EN (PM1_EN | 0x05) +#define RTC_EN (PM1_EN | 0x06) +#define WAK_EN (PM1_EN | 0x07) + +#define SCI_EN (PM1_CONTROL | 0x01) +#define BM_RLD (PM1_CONTROL | 0x02) +#define GBL_RLS (PM1_CONTROL | 0x03) +#define SLP_TYPE_A (PM1_CONTROL | 0x04) +#define SLP_TYPE_B (PM1_CONTROL | 0x05) +#define SLP_EN (PM1_CONTROL | 0x06) + +#define ARB_DIS (PM2_CONTROL | 0x01) + +#define TMR_VAL (PM_TIMER | 0x01) + +#define GPE0_STS (GPE0_STS_BLOCK | 0x01) +#define GPE0_EN (GPE0_EN_BLOCK | 0x01) + +#define GPE1_STS (GPE1_STS_BLOCK | 0x01) +#define GPE1_EN (GPE1_EN_BLOCK | 0x01) + + +#define TMR_STS_MASK 0x0001 +#define BM_STS_MASK 0x0010 +#define GBL_STS_MASK 0x0020 +#define PWRBTN_STS_MASK 0x0100 +#define SLPBTN_STS_MASK 0x0200 +#define RTC_STS_MASK 0x0400 +#define WAK_STS_MASK 0x8000 + +#define ALL_FIXED_STS_BITS (TMR_STS_MASK | BM_STS_MASK | GBL_STS_MASK \ + | PWRBTN_STS_MASK | SLPBTN_STS_MASK \ + | RTC_STS_MASK | WAK_STS_MASK) + +#define TMR_EN_MASK 0x0001 +#define GBL_EN_MASK 0x0020 +#define PWRBTN_EN_MASK 0x0100 +#define SLPBTN_EN_MASK 0x0200 +#define RTC_EN_MASK 0x0400 + +#define SCI_EN_MASK 0x0001 +#define BM_RLD_MASK 0x0002 +#define GBL_RLS_MASK 0x0004 +#define SLP_TYPE_X_MASK 0x1C00 +#define SLP_EN_MASK 0x2000 -#define ARB_DIS_MASK 0x0001 -#define TMR_VAL_MASK 0xFFFFFFFF +#define ARB_DIS_MASK 0x0001 +#define TMR_VAL_MASK 0xFFFFFFFF #define GPE0_STS_MASK #define GPE0_EN_MASK @@ -842,55 +771,87 @@ #define GPE1_EN_MASK -#define ACPI_READ 1 -#define ACPI_WRITE 2 +#define ACPI_READ 1 +#define ACPI_WRITE 2 + + +/***************************************************************************** + * + * Resource descriptors + * + ****************************************************************************/ + + +/* Resource_type values */ + +#define RESOURCE_TYPE_MEMORY_RANGE 0 +#define RESOURCE_TYPE_IO_RANGE 1 +#define RESOURCE_TYPE_BUS_NUMBER_RANGE 2 + +/* Resource descriptor types and masks */ + +#define RESOURCE_DESC_TYPE_LARGE 0x80 +#define RESOURCE_DESC_TYPE_SMALL 0x00 + +#define RESOURCE_DESC_TYPE_MASK 0x80 +#define RESOURCE_DESC_SMALL_MASK 0x78 /* Only bits 6:3 contain the type */ -/* Plug and play */ +/* + * Small resource descriptor types + * Note: The 3 length bits (2:0) must be zero + */ +#define RESOURCE_DESC_IRQ_FORMAT 0x20 +#define RESOURCE_DESC_DMA_FORMAT 0x28 +#define RESOURCE_DESC_START_DEPENDENT 0x30 +#define RESOURCE_DESC_END_DEPENDENT 0x38 +#define RESOURCE_DESC_IO_PORT 0x40 +#define RESOURCE_DESC_FIXED_IO_PORT 0x48 +#define RESOURCE_DESC_SMALL_VENDOR 0x70 +#define RESOURCE_DESC_END_TAG 0x78 + +/* + * Large resource descriptor types + */ -/* Pnp and ACPI data */ +#define RESOURCE_DESC_MEMORY_24 0x81 +#define RESOURCE_DESC_GENERAL_REGISTER 0x82 +#define RESOURCE_DESC_LARGE_VENDOR 0x84 +#define RESOURCE_DESC_MEMORY_32 0x85 +#define RESOURCE_DESC_FIXED_MEMORY_32 0x86 +#define RESOURCE_DESC_DWORD_ADDRESS_SPACE 0x87 +#define RESOURCE_DESC_WORD_ADDRESS_SPACE 0x88 +#define RESOURCE_DESC_EXTENDED_XRUPT 0x89 +#define RESOURCE_DESC_QWORD_ADDRESS_SPACE 0x8A -#define VERSION_NO 0x01 -#define LOGICAL_DEVICE_ID 0x02 -#define COMPATIBLE_DEVICE_ID 0x03 -#define IRQ_FORMAT 0x04 -#define DMA_FORMAT 0x05 -#define START_DEPENDENT_TAG 0x06 -#define END_DEPENDENT_TAG 0x07 -#define IO_PORT_DESCRIPTOR 0x08 -#define FIXED_LOCATION_IO_DESCRIPTOR 0x09 -#define RESERVED_TYPE0 0x0A -#define RESERVED_TYPE1 0x0B -#define RESERVED_TYPE2 0x0C -#define RESERVED_TYPE3 0x0D -#define SMALL_VENDOR_DEFINED 0x0E -#define END_TAG 0x0F - -/* Pnp and ACPI data */ - -#define MEMORY_RANGE_24 0x81 -#define ISA_MEMORY_RANGE 0x81 -#define LARGE_VENDOR_DEFINED 0x84 -#define EISA_MEMORY_RANGE 0x85 -#define MEMORY_RANGE_32 0x85 -#define FIXED_EISA_MEMORY_RANGE 0x86 -#define FIXED_MEMORY_RANGE_32 0x86 - -/* ACPI only data */ - -#define DWORD_ADDRESS_SPACE 0x87 -#define WORD_ADDRESS_SPACE 0x88 -#define EXTENDED_IRQ 0x89 -/* MUST HAVES */ +/* String version of device HIDs and UIDs */ -#define DEVICE_ID_LENGTH 0x09 +#define ACPI_DEVICE_ID_LENGTH 0x09 typedef struct { - NATIVE_CHAR buffer[DEVICE_ID_LENGTH]; + NATIVE_CHAR buffer[ACPI_DEVICE_ID_LENGTH]; + +} ACPI_DEVICE_ID; + + +/***************************************************************************** + * + * Debugger + * + ****************************************************************************/ + +typedef struct dbmethodinfo +{ + ACPI_HANDLE thread_gate; + NATIVE_CHAR *name; + NATIVE_CHAR **args; + u32 flags; + u32 num_loops; + NATIVE_CHAR pathname[128]; -} DEVICE_ID; +} DB_METHOD_INFO; /***************************************************************************** @@ -904,22 +865,22 @@ #ifdef ACPI_DEBUG -#define MEM_MALLOC 0 -#define MEM_CALLOC 1 -#define MAX_MODULE_NAME 16 - -typedef struct allocation_info -{ - struct allocation_info *previous; - struct allocation_info *next; - void *address; - u32 size; - u32 component; - u32 line; - NATIVE_CHAR module[MAX_MODULE_NAME]; - u8 alloc_type; +#define MEM_MALLOC 0 +#define MEM_CALLOC 1 +#define MAX_MODULE_NAME 16 + +typedef struct acpi_allocation_info +{ + struct acpi_allocation_info *previous; + struct acpi_allocation_info *next; + void *address; + u32 size; + u32 component; + u32 line; + NATIVE_CHAR module[MAX_MODULE_NAME]; + u8 alloc_type; -} ALLOCATION_INFO; +} ACPI_ALLOCATION_INFO; #endif diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/acmacros.h linux/drivers/acpi/include/acmacros.h --- v2.4.5/linux/drivers/acpi/include/acmacros.h Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/include/acmacros.h Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acmacros.h - C macros for the entire subsystem. - * $Revision: 62 $ + * $Revision: 72 $ * *****************************************************************************/ @@ -88,12 +88,18 @@ #define ACPI_STORE_ADDRESS(a,b) ((a)=(b)) #define ACPI_VALID_ADDRESS(a) (a) #endif + /* * Extract a byte of data using a pointer. Any more than a byte and we * get into potential aligment issues -- see the STORE macros below */ #define GET8(addr) (*(u8*)(addr)) +/* Pointer arithmetic */ + + +#define POINTER_ADD(t,a,b) (t *) ((NATIVE_UINT)(a) + (NATIVE_UINT)(b)) +#define POINTER_DIFF(a,b) ((u32) ((NATIVE_UINT)(a) - (NATIVE_UINT)(b))) /* * Macros for moving data around to/from buffers that are possibly unaligned. @@ -108,6 +114,7 @@ #define MOVE_UNALIGNED16_TO_16(d,s) *(u16*)(d) = *(u16*)(s) #define MOVE_UNALIGNED32_TO_32(d,s) *(u32*)(d) = *(u32*)(s) #define MOVE_UNALIGNED16_TO_32(d,s) *(u32*)(d) = *(u16*)(s) +#define MOVE_UNALIGNED64_TO_64(d,s) *(UINT64*)(d) = *(UINT64*)(s) #else /* @@ -126,6 +133,15 @@ #define MOVE_UNALIGNED16_TO_32(d,s) {(*(u32*)(d)) = 0; MOVE_UNALIGNED16_TO_16(d,s);} +#define 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];} + #endif @@ -177,8 +193,26 @@ #define ROUND_PTR_UP_TO_4(a,b) ((b *)(((NATIVE_UINT)(a) + 3) & ~3)) #define ROUND_PTR_UP_TO_8(a,b) ((b *)(((NATIVE_UINT)(a) + 7) & ~7)) +#define ROUND_BITS_UP_TO_BYTES(a) DIV_8((a) + 7) +#define ROUND_BITS_DOWN_TO_BYTES(a) DIV_8((a)) + #define ROUND_UP_TO_1_k(a) (((a) + 1023) >> 10) +/* Generic (non-power-of-two) rounding */ + +#define ROUND_UP_TO(value,boundary) (((value) + ((boundary)-1)) / (boundary)) + +/* + * Bitmask creation + * Bit positions start at zero. + * 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 MASK_BITS_ABOVE(position) (~(((u32)(-1)) << ((u32) (position)))) +#define MASK_BITS_BELOW(position) (((u32)(-1)) << ((u32) (position))) + #ifdef DEBUG_ASSERT #undef DEBUG_ASSERT #endif @@ -222,6 +256,10 @@ #define IS_SINGLE_TABLE(x) (((x) & 0x01) == ACPI_TABLE_SINGLE ? 1 : 0) +/* Check if ACPI has been initialized properly */ + +#define ACPI_IS_INITIALIZATION_COMPLETE(s) {if (acpi_gbl_root_node) s = AE_OK; else s=AE_NO_NAMESPACE;} + /* * Macro to check if a pointer is within an ACPI table. * Parameter (a) is the pointer to check. Parameter (b) must be defined @@ -231,12 +269,12 @@ #ifndef _IA16 #define IS_IN_ACPI_TABLE(a,b) (((u8 *)(a) >= (u8 *)(b + 1)) &&\ - ((u8 *)(a) < ((u8 *)b + b->length))) + ((u8 *)(a) < ((u8 *)b + b->length))) #else #define IS_IN_ACPI_TABLE(a,b) (_segment)(a) == (_segment)(b) &&\ - (((u8 *)(a) >= (u8 *)(b + 1)) &&\ - ((u8 *)(a) < ((u8 *)b + b->length))) + (((u8 *)(a) >= (u8 *)(b + 1)) &&\ + ((u8 *)(a) < ((u8 *)b + b->length))) #endif /* @@ -276,6 +314,26 @@ /* + * Build a GAS structure from earlier ACPI table entries (V1.0 and 0.71 extensions) + * + * 1) Address space + * 2) Length in bytes -- convert to length in bits + * 3) Bit offset is zero + * 4) Reserved field is zero + * 5) Expand address to 64 bits + */ +#define ASL_BUILD_GAS_FROM_ENTRY(a,b,c,d) {a.address_space_id = (u8) d;\ + a.register_bit_width = (u8) MUL_8 (b);\ + a.register_bit_offset = 0;\ + a.reserved = 0;\ + ACPI_STORE_ADDRESS (a.address,c);} + +/* ACPI V1.0 entries -- address space is always I/O */ + +#define ASL_BUILD_GAS_FROM_V1_ENTRY(a,b,c) ASL_BUILD_GAS_FROM_ENTRY(a,b,c,ACPI_ADR_SPACE_SYSTEM_IO) + + +/* * Reporting macros that are never compiled out */ @@ -290,7 +348,7 @@ #ifdef ACPI_DEBUG #define REPORT_INFO(fp) {_report_info(_THIS_MODULE,__LINE__,_COMPONENT); \ - debug_print_raw PARAM_LIST(fp);} + debug_print_raw PARAM_LIST(fp);} #define REPORT_ERROR(fp) {_report_error(_THIS_MODULE,__LINE__,_COMPONENT); \ debug_print_raw PARAM_LIST(fp);} #define REPORT_WARNING(fp) {_report_warning(_THIS_MODULE,__LINE__,_COMPONENT); \ @@ -318,7 +376,7 @@ /* Buffer dump macros */ -#define DUMP_BUFFER(a,b) acpi_cm_dump_buffer((u8 *)a,b,DB_BYTE_DISPLAY,_COMPONENT) +#define DUMP_BUFFER(a,b) acpi_ut_dump_buffer((u8 *)a,b,DB_BYTE_DISPLAY,_COMPONENT) /* * Debug macros that are conditionally compiled @@ -334,6 +392,7 @@ * as a local string ("_Proc_name) so that it can be also used by the function exit macros below. */ +#define PROC_NAME(a) char * _proc_name = a; #define FUNCTION_TRACE(a) char * _proc_name = a;\ function_trace(_THIS_MODULE,__LINE__,_COMPONENT,a) #define FUNCTION_TRACE_PTR(a,b) char * _proc_name = a;\ @@ -351,7 +410,7 @@ */ #define return_VOID {function_exit(_THIS_MODULE,__LINE__,_COMPONENT,_proc_name);return;} #define return_ACPI_STATUS(s) {function_status_exit(_THIS_MODULE,__LINE__,_COMPONENT,_proc_name,s);return(s);} -#define return_VALUE(s) {function_value_exit(_THIS_MODULE,__LINE__,_COMPONENT,_proc_name,(ACPI_INTEGER)s);return(s);} +#define return_VALUE(s) {function_value_exit(_THIS_MODULE,__LINE__,_COMPONENT,_proc_name,s);return(s);} #define return_PTR(s) {function_ptr_exit(_THIS_MODULE,__LINE__,_COMPONENT,_proc_name,(u8 *)s);return(s);} @@ -368,8 +427,8 @@ /* Stack and buffer dumping */ -#define DUMP_STACK_ENTRY(a) acpi_aml_dump_operand(a) -#define DUMP_OPERANDS(a,b,c,d,e) acpi_aml_dump_operands(a,b,c,d,e,_THIS_MODULE,__LINE__) +#define DUMP_STACK_ENTRY(a) acpi_ex_dump_operand(a) +#define DUMP_OPERANDS(a,b,c,d,e) acpi_ex_dump_operands(a,b,c,d,e,_THIS_MODULE,__LINE__) #define DUMP_ENTRY(a,b) acpi_ns_dump_entry (a,b) @@ -404,6 +463,12 @@ debug_print_raw PARAM_LIST(fp);\ BREAK_ON_ERROR(lvl);} +#define DEBUG_PRINTP(lvl,fp) TEST_DEBUG_SWITCH(lvl) {\ + debug_print_prefix (_THIS_MODULE,__LINE__);\ + debug_print_raw ("%s: ",_proc_name);\ + debug_print_raw PARAM_LIST(fp);\ + BREAK_ON_ERROR(lvl);} + #define DEBUG_PRINT_RAW(lvl,fp) TEST_DEBUG_SWITCH(lvl) {\ debug_print_raw PARAM_LIST(fp);} @@ -431,6 +496,7 @@ #define DEBUG_DEFINE(a) #define DEBUG_ONLY_MEMBERS(a) +#define PROC_NAME(a) #define FUNCTION_TRACE(a) #define FUNCTION_TRACE_PTR(a,b) #define FUNCTION_TRACE_U32(a,b) @@ -445,6 +511,7 @@ #define DUMP_PATHNAME(a,b,c,d) #define DUMP_RESOURCE_LIST(a) #define DEBUG_PRINT(l,f) +#define DEBUG_PRINTP(l,f) #define DEBUG_PRINT_RAW(l,f) #define BREAK_MSG(a) @@ -496,6 +563,75 @@ #define ADD_OBJECT_NAME(a,b) #endif + + +/* + * Memory allocation tracking (DEBUG ONLY) + */ + +#ifndef ACPI_DEBUG_TRACK_ALLOCATIONS + +#define acpi_ut_add_element_to_alloc_list(a,b,c,d,e,f) +#define acpi_ut_delete_element_from_alloc_list(a,b,c,d) +#define acpi_ut_dump_current_allocations(a,b) +#define acpi_ut_dump_allocation_info() + +#define DECREMENT_OBJECT_METRICS(a) +#define INCREMENT_OBJECT_METRICS(a) +#define INITIALIZE_ALLOCATION_METRICS() +#define DECREMENT_NAME_TABLE_METRICS(a) +#define INCREMENT_NAME_TABLE_METRICS(a) + +#else + +#define INITIALIZE_ALLOCATION_METRICS() \ + acpi_gbl_current_object_count = 0; \ + acpi_gbl_current_object_size = 0; \ + acpi_gbl_running_object_count = 0; \ + acpi_gbl_running_object_size = 0; \ + acpi_gbl_max_concurrent_object_count = 0; \ + acpi_gbl_max_concurrent_object_size = 0; \ + acpi_gbl_current_alloc_size = 0; \ + acpi_gbl_current_alloc_count = 0; \ + acpi_gbl_running_alloc_size = 0; \ + acpi_gbl_running_alloc_count = 0; \ + acpi_gbl_max_concurrent_alloc_size = 0; \ + acpi_gbl_max_concurrent_alloc_count = 0; \ + acpi_gbl_current_node_count = 0; \ + acpi_gbl_current_node_size = 0; \ + acpi_gbl_max_concurrent_node_count = 0 + + +#define DECREMENT_OBJECT_METRICS(a) \ + acpi_gbl_current_object_count--; \ + acpi_gbl_current_object_size -= a + +#define INCREMENT_OBJECT_METRICS(a) \ + acpi_gbl_current_object_count++; \ + acpi_gbl_running_object_count++; \ + if (acpi_gbl_max_concurrent_object_count < acpi_gbl_current_object_count) \ + { \ + acpi_gbl_max_concurrent_object_count = acpi_gbl_current_object_count; \ + } \ + acpi_gbl_running_object_size += a; \ + acpi_gbl_current_object_size += a; \ + if (acpi_gbl_max_concurrent_object_size < acpi_gbl_current_object_size) \ + { \ + acpi_gbl_max_concurrent_object_size = acpi_gbl_current_object_size; \ + } + +#define DECREMENT_NAME_TABLE_METRICS(a) \ + acpi_gbl_current_node_count--; \ + acpi_gbl_current_node_size -= (a) + +#define INCREMENT_NAME_TABLE_METRICS(a) \ + acpi_gbl_current_node_count++; \ + acpi_gbl_current_node_size+= (a); \ + if (acpi_gbl_max_concurrent_node_count < acpi_gbl_current_node_count) \ + { \ + acpi_gbl_max_concurrent_node_count = acpi_gbl_current_node_count; \ + } +#endif /* ACPI_DEBUG_TRACK_ALLOCATIONS */ #endif /* ACMACROS_H */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/acnamesp.h linux/drivers/acpi/include/acnamesp.h --- v2.4.5/linux/drivers/acpi/include/acnamesp.h Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/include/acnamesp.h Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acnamesp.h - Namespace subcomponent prototypes and defines - * $Revision: 103 $ + * $Revision: 106 $ * *****************************************************************************/ @@ -94,18 +94,18 @@ ACPI_STATUS acpi_ns_walk_namespace ( - OBJECT_TYPE_INTERNAL type, + ACPI_OBJECT_TYPE8 type, ACPI_HANDLE start_object, u32 max_depth, u8 unlock_before_callback, - WALK_CALLBACK user_function, + ACPI_WALK_CALLBACK user_function, void *context, void **return_value); ACPI_NAMESPACE_NODE * acpi_ns_get_next_object ( - OBJECT_TYPE_INTERNAL type, + ACPI_OBJECT_TYPE8 type, ACPI_NAMESPACE_NODE *parent, ACPI_NAMESPACE_NODE *child); @@ -150,7 +150,7 @@ acpi_ns_lookup ( ACPI_GENERIC_STATE *scope_info, NATIVE_CHAR *name, - OBJECT_TYPE_INTERNAL type, + ACPI_OBJECT_TYPE8 type, OPERATING_MODE interpreter_mode, u32 flags, ACPI_WALK_STATE *walk_state, @@ -223,7 +223,7 @@ void acpi_ns_dump_objects ( - OBJECT_TYPE_INTERNAL type, + ACPI_OBJECT_TYPE8 type, u32 max_depth, u32 ownder_id, ACPI_HANDLE start_handle); @@ -283,7 +283,7 @@ u32 acpi_ns_opens_scope ( - OBJECT_TYPE_INTERNAL type); + ACPI_OBJECT_TYPE8 type); NATIVE_CHAR * acpi_ns_get_table_pathname ( @@ -304,12 +304,6 @@ ACPI_NAMESPACE_NODE *obj_node, NATIVE_CHAR *search_for); -ACPI_STATUS -acpi_ns_name_compare ( - ACPI_HANDLE obj_handle, - u32 level, - void *context, - void **return_value); ACPI_STATUS acpi_ns_get_node ( @@ -330,14 +324,7 @@ acpi_ns_attach_object ( ACPI_NAMESPACE_NODE *node, ACPI_OPERAND_OBJECT *object, - OBJECT_TYPE_INTERNAL type); - - -void * -acpi_ns_compare_value ( - ACPI_HANDLE obj_handle, - u32 level, - void *obj_desc); + ACPI_OBJECT_TYPE8 type); /* @@ -350,7 +337,7 @@ ACPI_WALK_STATE *walk_state, ACPI_NAMESPACE_NODE *node, OPERATING_MODE interpreter_mode, - OBJECT_TYPE_INTERNAL type, + ACPI_OBJECT_TYPE8 type, u32 flags, ACPI_NAMESPACE_NODE **ret_node); @@ -358,7 +345,7 @@ acpi_ns_search_node ( u32 entry_name, ACPI_NAMESPACE_NODE *node, - OBJECT_TYPE_INTERNAL type, + ACPI_OBJECT_TYPE8 type, ACPI_NAMESPACE_NODE **ret_node); void @@ -366,7 +353,7 @@ ACPI_WALK_STATE *walk_state, ACPI_NAMESPACE_NODE *parent_node, /* Parent */ ACPI_NAMESPACE_NODE *node, /* New Child*/ - OBJECT_TYPE_INTERNAL type); + ACPI_OBJECT_TYPE8 type); /* @@ -381,17 +368,25 @@ acpi_ns_valid_path_separator ( NATIVE_CHAR sep); -OBJECT_TYPE_INTERNAL +ACPI_OBJECT_TYPE8 acpi_ns_get_type ( - ACPI_HANDLE obj_handle); + ACPI_NAMESPACE_NODE *node); void * acpi_ns_get_attached_object ( - ACPI_HANDLE obj_handle); + ACPI_NAMESPACE_NODE *node); u32 acpi_ns_local ( - OBJECT_TYPE_INTERNAL type); + ACPI_OBJECT_TYPE8 type); + +ACPI_STATUS +acpi_ns_build_internal_name ( + ACPI_NAMESTRING_INFO *info); + +ACPI_STATUS +acpi_ns_get_internal_name_length ( + ACPI_NAMESTRING_INFO *info); ACPI_STATUS acpi_ns_internalize_name ( diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/acobject.h linux/drivers/acpi/include/acobject.h --- v2.4.5/linux/drivers/acpi/include/acobject.h Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/include/acobject.h Wed Jun 20 17:47:40 2001 @@ -2,7 +2,7 @@ /****************************************************************************** * * Name: acobject.h - Definition of ACPI_OPERAND_OBJECT (Internal object only) - * $Revision: 78 $ + * $Revision: 89 $ * *****************************************************************************/ @@ -58,7 +58,7 @@ */ -#define ACPI_OBJECT_COMMON_HEADER /* 32-bits plus 8-bit flag */\ +#define ACPI_OBJECT_COMMON_HEADER /* SIZE/ALIGNMENT: 32-bits plus trailing 8-bit flag */\ u8 data_type; /* To differentiate various internal objs */\ u8 type; /* ACPI_OBJECT_TYPE */\ u16 reference_count; /* For object deletion management */\ @@ -73,16 +73,27 @@ /* * Common bitfield for the field objects + * "Field Datum" -- a datum from the actual field object + * "Buffer Datum" -- a datum from a user buffer, read from or to be written to the field */ -#define ACPI_COMMON_FIELD_INFO /* Three 32-bit values plus 8*/\ - u8 granularity;\ - u16 length; \ - u32 offset; /* Byte offset within containing object */\ - u8 bit_offset; /* Bit offset within min read/write data unit */\ - u8 access; /* Access_type */\ - u8 lock_rule;\ - u8 update_rule;\ - u8 access_attribute; +#define ACPI_COMMON_FIELD_INFO /* SIZE/ALIGNMENT: 24 bits + three 32-bit values */\ + u8 access_flags;\ + u16 bit_length; /* Length of field in bits */\ + u32 base_byte_offset; /* Byte offset within containing object */\ + u8 access_bit_width; /* Read/Write size in bits (from ASL Access_type)*/\ + u8 access_byte_width; /* Read/Write size in bytes */\ + u8 update_rule; /* How neighboring field bits are handled */\ + u8 lock_rule; /* Global Lock: 1 = "Must Lock" */\ + u8 start_field_bit_offset;/* Bit offset within first field datum (0-63) */\ + u8 datum_valid_bits; /* Valid bit in first "Field datum" */\ + u8 end_field_valid_bits; /* Valid bits in the last "field datum" */\ + u8 end_buffer_valid_bits; /* Valid bits in the last "buffer datum" */\ + u32 value; /* Value to store into the Bank or Index register */ + + +/* Access flag bits */ + +#define AFIELD_SINGLE_DATUM 0x1 /****************************************************************************** @@ -121,7 +132,7 @@ ACPI_OBJECT_COMMON_HEADER u32 length; - NATIVE_CHAR *pointer; /* String value in AML stream or in allocated space */ + NATIVE_CHAR *pointer; /* String value in AML stream or in allocated space */ } ACPI_OBJECT_STRING; @@ -131,7 +142,7 @@ ACPI_OBJECT_COMMON_HEADER u32 length; - u8 *pointer; /* points to the buffer in allocated space */ + u8 *pointer; /* points to the buffer in allocated space */ } ACPI_OBJECT_BUFFER; @@ -140,27 +151,14 @@ { ACPI_OBJECT_COMMON_HEADER - u32 count; /* # of elements in package */ + u32 count; /* # of elements in package */ - union acpi_operand_obj **elements; /* Array of pointers to Acpi_objects */ - union acpi_operand_obj **next_element; /* used only while initializing */ + union acpi_operand_obj **elements; /* Array of pointers to Acpi_objects */ + union acpi_operand_obj **next_element; /* used only while initializing */ } ACPI_OBJECT_PACKAGE; -typedef struct /* FIELD UNIT */ -{ - ACPI_OBJECT_COMMON_HEADER - - ACPI_COMMON_FIELD_INFO - - union acpi_operand_obj *extra; /* Pointer to executable AML (in field definition) */ - ACPI_NAMESPACE_NODE *node; /* containing object */ - union acpi_operand_obj *container; /* Containing object (Buffer) */ - -} ACPI_OBJECT_FIELD_UNIT; - - typedef struct /* DEVICE - has handle and notification handler/context */ { ACPI_OBJECT_COMMON_HEADER @@ -175,7 +173,6 @@ typedef struct /* EVENT */ { ACPI_OBJECT_COMMON_HEADER - void *semaphore; } ACPI_OBJECT_EVENT; @@ -201,12 +198,16 @@ } ACPI_OBJECT_METHOD; -typedef struct /* MUTEX */ +typedef struct acpi_obj_mutex /* MUTEX */ { ACPI_OBJECT_COMMON_HEADER u16 sync_level; + u16 acquisition_depth; void *semaphore; + void *owner; + union acpi_operand_obj *prev; /* Link for list of acquired mutexes */ + union acpi_operand_obj *next; /* Link for list of acquired mutexes */ } ACPI_OBJECT_MUTEX; @@ -267,57 +268,78 @@ /* - * Internal types + * Fields. All share a common header/info field. */ - -typedef struct /* FIELD */ +typedef struct /* COMMON FIELD (for BUFFER, REGION, BANK, and INDEX fields) */ { ACPI_OBJECT_COMMON_HEADER - ACPI_COMMON_FIELD_INFO + union acpi_operand_obj *region_obj; /* Containing Operation Region object */ + /* (REGION/BANK fields only) */ +} ACPI_OBJECT_FIELD_COMMON; - union acpi_operand_obj *container; /* Containing object */ -} ACPI_OBJECT_FIELD; +typedef struct /* REGION FIELD */ +{ + ACPI_OBJECT_COMMON_HEADER + ACPI_COMMON_FIELD_INFO + union acpi_operand_obj *region_obj; /* Containing Op_region object */ + +} ACPI_OBJECT_REGION_FIELD; typedef struct /* BANK FIELD */ { ACPI_OBJECT_COMMON_HEADER - ACPI_COMMON_FIELD_INFO - u32 value; /* Value to store into Bank_select */ - ACPI_HANDLE bank_select; /* Bank select register */ - union acpi_operand_obj *container; /* Containing object */ + union acpi_operand_obj *region_obj; /* Containing Op_region object */ + union acpi_operand_obj *bank_register_obj; /* Bank_select Register object */ } ACPI_OBJECT_BANK_FIELD; typedef struct /* INDEX FIELD */ { + ACPI_OBJECT_COMMON_HEADER + ACPI_COMMON_FIELD_INFO + /* - * No container pointer needed since the index and data register definitions - * will define how to access the respective registers + * No "Region_obj" pointer needed since the Index and Data registers + * are each field definitions unto themselves. */ - ACPI_OBJECT_COMMON_HEADER + union acpi_operand_obj *index_obj; /* Index register */ + union acpi_operand_obj *data_obj; /* Data register */ + + +} ACPI_OBJECT_INDEX_FIELD; + +/* The Buffer_field is different in that it is part of a Buffer, not an Op_region */ + +typedef struct /* BUFFER FIELD */ +{ + ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO - u32 value; /* Value to store into Index register */ - ACPI_HANDLE index; /* Index register */ - ACPI_HANDLE data; /* Data register */ + union acpi_operand_obj *extra; /* Pointer to executable AML (in field definition) */ + ACPI_NAMESPACE_NODE *node; /* Parent (containing) object node */ + union acpi_operand_obj *buffer_obj; /* Containing Buffer object */ + +} ACPI_OBJECT_BUFFER_FIELD; -} ACPI_OBJECT_INDEX_FIELD; +/* + * Handlers + */ typedef struct /* NOTIFY HANDLER */ { ACPI_OBJECT_COMMON_HEADER ACPI_NAMESPACE_NODE *node; /* Parent device */ - NOTIFY_HANDLER handler; + ACPI_NOTIFY_HANDLER handler; void *context; } ACPI_OBJECT_NOTIFY_HANDLER; @@ -334,11 +356,11 @@ u8 space_id; u16 hflags; - ADDRESS_SPACE_HANDLER handler; + ACPI_ADR_SPACE_HANDLER handler; ACPI_NAMESPACE_NODE *node; /* Parent device */ void *context; - ADDRESS_SPACE_SETUP setup; + ACPI_ADR_SPACE_SETUP setup; union acpi_operand_obj *region_list; /* regions using this handler */ union acpi_operand_obj *next; @@ -355,7 +377,7 @@ ACPI_OBJECT_COMMON_HEADER u8 target_type; /* Used for Index_op */ - u16 op_code; + u16 opcode; u32 offset; /* Used for Arg_op, Local_op, and Index_op */ void *object; /* Name_op=>HANDLE to obj, Index_op=>ACPI_OPERAND_OBJECT */ @@ -400,7 +422,7 @@ ACPI_OBJECT_STRING string; ACPI_OBJECT_BUFFER buffer; ACPI_OBJECT_PACKAGE package; - ACPI_OBJECT_FIELD_UNIT field_unit; + ACPI_OBJECT_BUFFER_FIELD buffer_field; ACPI_OBJECT_DEVICE device; ACPI_OBJECT_EVENT event; ACPI_OBJECT_METHOD method; @@ -409,7 +431,8 @@ ACPI_OBJECT_POWER_RESOURCE power_resource; ACPI_OBJECT_PROCESSOR processor; ACPI_OBJECT_THERMAL_ZONE thermal_zone; - ACPI_OBJECT_FIELD field; + ACPI_OBJECT_FIELD_COMMON common_field; + ACPI_OBJECT_REGION_FIELD field; ACPI_OBJECT_BANK_FIELD bank_field; ACPI_OBJECT_INDEX_FIELD index_field; ACPI_OBJECT_REFERENCE reference; diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/acoutput.h linux/drivers/acpi/include/acoutput.h --- v2.4.5/linux/drivers/acpi/include/acoutput.h Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/include/acoutput.h Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acoutput.h -- debug output - * $Revision: 70 $ + * $Revision: 78 $ * *****************************************************************************/ @@ -34,34 +34,35 @@ /* Component IDs -- used in the global "Debug_layer" */ -#define GLOBAL 0x00000001 -#define COMMON 0x00000002 -#define PARSER 0x00000004 -#define DISPATCHER 0x00000008 -#define INTERPRETER 0x00000010 -#define NAMESPACE 0x00000020 -#define RESOURCE_MANAGER 0x00000040 -#define TABLE_MANAGER 0x00000080 -#define EVENT_HANDLING 0x00000100 -#define HARDWARE 0x00000200 -#define MISCELLANEOUS 0x00000400 -#define OS_DEPENDENT 0x00000800 - -#define BUS_MANAGER 0x00001000 - -#define PROCESSOR_CONTROL 0x00002000 -#define SYSTEM_CONTROL 0x00004000 -#define THERMAL_CONTROL 0x00008000 -#define POWER_CONTROL 0x00010000 - -#define EMBEDDED_CONTROLLER 0x00020000 -#define BATTERY 0x00040000 - -#define DEBUGGER 0x00100000 -#define COMPILER 0x00200000 -#define ALL_COMPONENTS 0x001FFFFF +#define ACPI_UTILITIES 0x00000001 +#define ACPI_HARDWARE 0x00000002 +#define ACPI_EVENTS 0x00000004 +#define ACPI_TABLES 0x00000008 +#define ACPI_NAMESPACE 0x00000010 +#define ACPI_PARSER 0x00000020 +#define ACPI_DISPATCHER 0x00000040 +#define ACPI_EXECUTER 0x00000080 +#define ACPI_RESOURCES 0x00000100 +#define ACPI_DEBUGGER 0x00000200 +#define ACPI_OS_SERVICES 0x00000400 + +#define ACPI_BUS 0x00001000 +#define ACPI_SYSTEM 0x00002000 +#define ACPI_POWER 0x00004000 +#define ACPI_EC 0x00008000 +#define ACPI_AC_ADAPTER 0x00010000 +#define ACPI_BATTERY 0x00020000 +#define ACPI_BUTTON 0x00040000 +#define ACPI_PROCESSOR 0x00080000 +#define ACPI_THERMAL 0x00100000 -#define COMPONENT_DEFAULT (ALL_COMPONENTS) +#define ACPI_ALL_COMPONENTS 0x00FFFFFF + +#define ACPI_COMPONENT_DEFAULT (ACPI_ALL_COMPONENTS) + + +#define ACPI_COMPILER 0x10000000 +#define ACPI_TOOLS 0x20000000 /* Exception level -- used in the global "Debug_level" */ @@ -77,6 +78,7 @@ /* Trace level -- also used in the global "Debug_level" */ +#define TRACE_THREADS 0x00000080 #define TRACE_PARSE 0x00000100 #define TRACE_DISPATCH 0x00000200 #define TRACE_LOAD 0x00000400 @@ -98,7 +100,7 @@ #define TRACE_MUTEX 0x04000000 #define TRACE_INIT 0x08000000 -#define TRACE_ALL 0x0FFFFF00 +#define TRACE_ALL 0x0FFFFF80 /* Exceptionally verbose output -- also used in the global "Debug_level" */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/acpi.h linux/drivers/acpi/include/acpi.h --- v2.4.5/linux/drivers/acpi/include/acpi.h Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/include/acpi.h Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acpi.h - Master include file, Publics and external data. - * $Revision: 50 $ + * $Revision: 54 $ * *****************************************************************************/ @@ -31,20 +31,21 @@ * We put them here because we don't want to duplicate them * in the rest of the source code again and again. */ -#include "acconfig.h" /* Configuration constants */ -#include "acenv.h" /* Target environment specific items */ -#include "actypes.h" /* Fundamental data types */ -#include "acexcep.h" /* Local exception codes */ -#include "acmacros.h" /* C macros */ -#include "actbl.h" /* Acpi table definitions */ -#include "aclocal.h" /* Internal data types */ -#include "acoutput.h" /* Error output and Debug macros */ -#include "acpiosxf.h" /* Interfaces to the Acpi-to-OS layer*/ -#include "acpixf.h" /* Acpi core external interfaces */ -#include "acobject.h" /* Acpi internal object */ -#include "acglobal.h" /* All global variables */ -#include "achware.h" /* Hardware defines and interfaces */ -#include "accommon.h" /* Common (global) interfaces */ +#include "acconfig.h" /* Configuration constants */ +#include "platform/acenv.h" /* Target environment specific items */ +#include "actypes.h" /* Fundamental common data types */ +#include "acexcep.h" /* ACPI exception codes */ +#include "acmacros.h" /* C macros */ +#include "actbl.h" /* ACPI table definitions */ +#include "aclocal.h" /* Internal data types */ +#include "acoutput.h" /* Error output and Debug macros */ +#include "acpiosxf.h" /* Interfaces to the ACPI-to-OS layer*/ +#include "acpixf.h" /* ACPI core subsystem external interfaces */ +#include "acobject.h" /* ACPI internal object */ +#include "acstruct.h" /* Common structures */ +#include "acglobal.h" /* All global variables */ +#include "achware.h" /* Hardware defines and interfaces */ +#include "acutils.h" /* Utility interfaces */ #endif /* __ACPI_H__ */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/acpiosxf.h linux/drivers/acpi/include/acpiosxf.h --- v2.4.5/linux/drivers/acpi/include/acpiosxf.h Mon Jan 29 10:15:59 2001 +++ linux/drivers/acpi/include/acpiosxf.h Wed Jun 20 17:47:40 2001 @@ -1,9 +1,9 @@ /****************************************************************************** * - * Name: acpiosxf.h - All interfaces to the OS-dependent layer. These - * interfaces must be implemented by the OS-dependent - * front-end to the ACPI subsystem. + * Name: acpiosxf.h - All interfaces to the OS Services Layer (OSL). These + * interfaces must be implemented by OSL to interface the + * ACPI components to the host operating system. * *****************************************************************************/ @@ -26,26 +26,26 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __ACPIOSD_H__ -#define __ACPIOSD_H__ +#ifndef __ACPIOSXF_H__ +#define __ACPIOSXF_H__ -#include "acenv.h" +#include "platform/acenv.h" #include "actypes.h" /* Priorities for Acpi_os_queue_for_execution */ -#define OSD_PRIORITY_GPE 1 -#define OSD_PRIORITY_HIGH 2 -#define OSD_PRIORITY_MED 3 -#define OSD_PRIORITY_LO 4 +#define OSD_PRIORITY_GPE 1 +#define OSD_PRIORITY_HIGH 2 +#define OSD_PRIORITY_MED 3 +#define OSD_PRIORITY_LO 4 -#define ACPI_NO_UNIT_LIMIT ((u32) -1) -#define ACPI_MUTEX_SEM 1 +#define ACPI_NO_UNIT_LIMIT ((u32) -1) +#define ACPI_MUTEX_SEM 1 /* - * Types specific to the OS-dependent layer interfaces + * Types specific to the OS service interfaces */ typedef @@ -58,7 +58,7 @@ /* - * Initialization and shutdown primitives (Optional) + * OSL Initialization and shutdown primitives */ ACPI_STATUS @@ -69,6 +69,7 @@ acpi_os_terminate ( void); + /* * Synchronization primitives */ @@ -94,6 +95,7 @@ ACPI_HANDLE handle, u32 units); + /* * Memory allocation and mapping */ @@ -126,6 +128,7 @@ void *logical_address, ACPI_PHYSICAL_ADDRESS *physical_address); + /* * Interrupt handlers */ @@ -143,9 +146,13 @@ /* - * Scheduling + * Threads and Scheduling */ +u32 +acpi_os_get_thread_id ( + void); + ACPI_STATUS acpi_os_queue_for_execution ( u32 priority, @@ -161,6 +168,7 @@ acpi_os_sleep_usec ( u32 microseconds); + /* * Platform/Hardware independent I/O interfaces */ @@ -193,6 +201,7 @@ ACPI_IO_ADDRESS out_port, u32 value); + /* * Platform/Hardware independent physical memory interfaces */ @@ -292,6 +301,10 @@ void *pointer, u32 length); +u32 +acpi_os_get_timer ( + void); + /* * Debug print routines @@ -307,6 +320,7 @@ const NATIVE_CHAR *format, va_list args); + /* * Debug input */ @@ -328,4 +342,4 @@ NATIVE_CHAR *message); -#endif /* __ACPIOSD_H__ */ +#endif /* __ACPIOSXF_H__ */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/acpixf.h linux/drivers/acpi/include/acpixf.h --- v2.4.5/linux/drivers/acpi/include/acpixf.h Mon Jan 29 10:15:59 2001 +++ linux/drivers/acpi/include/acpixf.h Wed Jun 20 17:47:40 2001 @@ -30,6 +30,7 @@ #include "actypes.h" #include "actbl.h" + /* * Global interfaces */ @@ -65,6 +66,23 @@ /* + * ACPI Memory manager + */ + +void * +acpi_allocate ( + u32 size); + +void * +acpi_callocate ( + u32 size); + +void +acpi_free ( + void *address); + + +/* * ACPI table manipulation interfaces */ @@ -96,6 +114,13 @@ u32 instance, ACPI_BUFFER *ret_buffer); +ACPI_STATUS +acpi_get_firmware_table ( + ACPI_STRING signature, + u32 instance, + u32 flags, + ACPI_TABLE_HEADER **table_pointer); + /* * Namespace and name interfaces @@ -106,14 +131,14 @@ ACPI_OBJECT_TYPE type, ACPI_HANDLE start_object, u32 max_depth, - WALK_CALLBACK user_function, + ACPI_WALK_CALLBACK user_function, void *context, void * *return_value); ACPI_STATUS acpi_get_devices ( NATIVE_CHAR *HID, - WALK_CALLBACK user_function, + ACPI_WALK_CALLBACK user_function, void *context, void **return_value); @@ -165,52 +190,52 @@ /* - * Acpi_event handler interfaces + * Event handler interfaces */ ACPI_STATUS acpi_install_fixed_event_handler ( u32 acpi_event, - FIXED_EVENT_HANDLER handler, + ACPI_EVENT_HANDLER handler, void *context); ACPI_STATUS acpi_remove_fixed_event_handler ( u32 acpi_event, - FIXED_EVENT_HANDLER handler); + ACPI_EVENT_HANDLER handler); ACPI_STATUS acpi_install_notify_handler ( ACPI_HANDLE device, u32 handler_type, - NOTIFY_HANDLER handler, + ACPI_NOTIFY_HANDLER handler, void *context); ACPI_STATUS acpi_remove_notify_handler ( ACPI_HANDLE device, u32 handler_type, - NOTIFY_HANDLER handler); + ACPI_NOTIFY_HANDLER handler); ACPI_STATUS acpi_install_address_space_handler ( ACPI_HANDLE device, - ACPI_ADDRESS_SPACE_TYPE space_id, - ADDRESS_SPACE_HANDLER handler, - ADDRESS_SPACE_SETUP setup, + ACPI_ADR_SPACE_TYPE space_id, + ACPI_ADR_SPACE_HANDLER handler, + ACPI_ADR_SPACE_SETUP setup, void *context); ACPI_STATUS acpi_remove_address_space_handler ( ACPI_HANDLE device, - ACPI_ADDRESS_SPACE_TYPE space_id, - ADDRESS_SPACE_HANDLER handler); + ACPI_ADR_SPACE_TYPE space_id, + ACPI_ADR_SPACE_HANDLER handler); ACPI_STATUS acpi_install_gpe_handler ( u32 gpe_number, u32 type, - GPE_HANDLER handler, + ACPI_GPE_HANDLER handler, void *context); ACPI_STATUS @@ -224,7 +249,7 @@ ACPI_STATUS acpi_remove_gpe_handler ( u32 gpe_number, - GPE_HANDLER handler); + ACPI_GPE_HANDLER handler); ACPI_STATUS acpi_enable_event ( diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/acresrc.h linux/drivers/acpi/include/acresrc.h --- v2.4.5/linux/drivers/acpi/include/acresrc.h Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/include/acresrc.h Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acresrc.h - Resource Manager function prototypes - * $Revision: 22 $ + * $Revision: 25 $ * *****************************************************************************/ @@ -60,7 +60,7 @@ ACPI_STATUS acpi_rs_create_byte_stream ( - RESOURCE *linked_list_buffer, + ACPI_RESOURCE *linked_list_buffer, u8 *output_buffer, u32 *output_buffer_length); @@ -77,7 +77,7 @@ void acpi_rs_dump_resource_list ( - RESOURCE *resource); + ACPI_RESOURCE *resource); void acpi_rs_dump_irq_list ( @@ -97,7 +97,7 @@ ACPI_STATUS acpi_rs_calculate_byte_stream_length ( - RESOURCE *linked_list_buffer, + ACPI_RESOURCE *linked_list_buffer, u32 *size_needed); ACPI_STATUS @@ -113,7 +113,7 @@ ACPI_STATUS acpi_rs_list_to_byte_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u32 byte_stream_size_needed, u8 **output_buffer); @@ -133,13 +133,13 @@ ACPI_STATUS acpi_rs_io_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u8 **output_buffer, u32 *bytes_consumed); ACPI_STATUS acpi_rs_fixed_io_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u8 **output_buffer, u32 *bytes_consumed); @@ -152,7 +152,7 @@ ACPI_STATUS acpi_rs_irq_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u8 **output_buffer, u32 *bytes_consumed); @@ -165,7 +165,7 @@ ACPI_STATUS acpi_rs_dma_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u8 **output_buffer, u32 *bytes_consumed); @@ -178,7 +178,7 @@ ACPI_STATUS acpi_rs_address16_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u8 **output_buffer, u32 *bytes_consumed); @@ -191,7 +191,20 @@ ACPI_STATUS acpi_rs_address32_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed); + +ACPI_STATUS +acpi_rs_address64_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size); + +ACPI_STATUS +acpi_rs_address64_stream ( + ACPI_RESOURCE *linked_list, u8 **output_buffer, u32 *bytes_consumed); @@ -211,13 +224,13 @@ ACPI_STATUS acpi_rs_start_dependent_functions_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u8 **output_buffer, u32 *bytes_consumed); ACPI_STATUS acpi_rs_end_dependent_functions_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u8 **output_buffer, u32 *bytes_consumed); @@ -230,7 +243,7 @@ ACPI_STATUS acpi_rs_memory24_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u8 **output_buffer, u32 *bytes_consumed); @@ -251,13 +264,13 @@ ACPI_STATUS acpi_rs_memory32_range_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u8 **output_buffer, u32 *bytes_consumed); ACPI_STATUS acpi_rs_fixed_memory32_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u8 **output_buffer, u32 *bytes_consumed); @@ -270,7 +283,7 @@ ACPI_STATUS acpi_rs_extended_irq_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u8 **output_buffer, u32 *bytes_consumed); @@ -283,7 +296,7 @@ ACPI_STATUS acpi_rs_end_tag_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u8 **output_buffer, u32 *bytes_consumed); @@ -296,9 +309,12 @@ ACPI_STATUS acpi_rs_vendor_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u8 **output_buffer, u32 *bytes_consumed); +u8 +acpi_rs_get_resource_type ( + u8 resource_start_byte); #endif /* __ACRESRC_H__ */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/acstruct.h linux/drivers/acpi/include/acstruct.h --- v2.4.5/linux/drivers/acpi/include/acstruct.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/acstruct.h Wed Jun 20 17:47:40 2001 @@ -0,0 +1,157 @@ +/****************************************************************************** + * + * Name: acstruct.h - Internal structs + * $Revision: 3 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 + */ + +#ifndef __ACSTRUCT_H__ +#define __ACSTRUCT_H__ + + +/***************************************************************************** + * + * Tree walking typedefs and structs + * + ****************************************************************************/ + + +/* + * Walk state - current state of a parse tree walk. Used for both a leisurely stroll through + * the tree (for whatever reason), and for control method execution. + */ + +#define NEXT_OP_DOWNWARD 1 +#define NEXT_OP_UPWARD 2 + +#define WALK_NON_METHOD 0 +#define WALK_METHOD 1 +#define WALK_METHOD_RESTART 2 + +typedef struct acpi_walk_state +{ + u8 data_type; /* To differentiate various internal objs */\ + ACPI_OWNER_ID owner_id; /* Owner of objects created during the walk */ + u8 last_predicate; /* Result of last predicate */ + u8 next_op_info; /* Info about Next_op */ + u8 num_operands; /* Stack pointer for Operands[] array */ + u8 current_result; /* */ + + struct acpi_walk_state *next; /* Next Walk_state in list */ + ACPI_PARSE_OBJECT *origin; /* Start of walk [Obsolete] */ + +/* TBD: Obsolete with removal of WALK procedure ? */ + ACPI_PARSE_OBJECT *prev_op; /* Last op that was processed */ + ACPI_PARSE_OBJECT *next_op; /* next op to be processed */ + + + ACPI_GENERIC_STATE *results; /* Stack of accumulated results */ + ACPI_GENERIC_STATE *control_state; /* List of control states (nested IFs) */ + ACPI_GENERIC_STATE *scope_info; /* Stack of nested scopes */ + ACPI_PARSE_STATE *parser_state; /* Current state of parser */ + u8 *aml_last_while; + ACPI_OPCODE_INFO *op_info; /* Info on current opcode */ + ACPI_PARSE_DOWNWARDS descending_callback; + ACPI_PARSE_UPWARDS ascending_callback; + + union acpi_operand_obj *return_desc; /* Return object, if any */ + union acpi_operand_obj *method_desc; /* Method descriptor if running a method */ + struct acpi_node *method_node; /* Method Node if running a method */ + ACPI_PARSE_OBJECT *method_call_op; /* Method_call Op if running a method */ + struct acpi_node *method_call_node; /* Called method Node*/ + union acpi_operand_obj *operands[OBJ_NUM_OPERANDS]; /* Operands passed to the interpreter */ + struct acpi_node arguments[MTH_NUM_ARGS]; /* Control method arguments */ + struct acpi_node local_variables[MTH_NUM_LOCALS]; /* Control method locals */ + struct acpi_walk_list *walk_list; + u32 parse_flags; + u8 walk_type; + u8 return_used; + u16 opcode; /* Current AML opcode */ + u32 prev_arg_types; + u16 current_sync_level; /* Mutex Sync (nested acquire) level */ + + /* Debug support */ + + u32 method_breakpoint; + + +} ACPI_WALK_STATE; + + +/* + * Walk list - head of a tree of walk states. Multiple walk states are created when there + * are nested control methods executing. + */ +typedef struct acpi_walk_list +{ + + ACPI_WALK_STATE *walk_state; + ACPI_OBJECT_MUTEX acquired_mutex_list; /* List of all currently acquired mutexes */ + +} ACPI_WALK_LIST; + + +/* Info used by Acpi_ps_init_objects */ + +typedef struct acpi_init_walk_info +{ + u16 method_count; + u16 op_region_count; + u16 field_count; + u16 op_region_init; + u16 field_init; + u16 object_count; + ACPI_TABLE_DESC *table_desc; + +} ACPI_INIT_WALK_INFO; + + +/* Info used by TBD */ + +typedef struct acpi_device_walk_info +{ + u16 device_count; + u16 num_STA; + u16 num_INI; + ACPI_TABLE_DESC *table_desc; + +} ACPI_DEVICE_WALK_INFO; + + +/* TBD: [Restructure] Merge with struct above */ + +typedef struct acpi_walk_info +{ + u32 debug_level; + u32 owner_id; + +} ACPI_WALK_INFO; + +typedef struct acpi_get_devices_info +{ + ACPI_WALK_CALLBACK user_function; + void *context; + NATIVE_CHAR *hid; + +} ACPI_GET_DEVICES_INFO; + + +#endif diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/actables.h linux/drivers/acpi/include/actables.h --- v2.4.5/linux/drivers/acpi/include/actables.h Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/include/actables.h Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: actables.h - ACPI table management - * $Revision: 29 $ + * $Revision: 31 $ * *****************************************************************************/ @@ -54,6 +54,10 @@ acpi_tb_build_common_facs ( ACPI_TABLE_DESC *table_info); +u32 +acpi_tb_get_table_count ( + RSDP_DESCRIPTOR *RSDP, + ACPI_TABLE_HEADER *RSDT); /* * tbget - Table "get" routines @@ -80,6 +84,20 @@ ACPI_TABLE_HEADER *buffer_ptr, ACPI_TABLE_DESC *table_info); +ACPI_PHYSICAL_ADDRESS +acpi_tb_get_rsdt_address ( + void); + +ACPI_STATUS +acpi_tb_validate_rsdt ( + ACPI_TABLE_HEADER *table_ptr); + +ACPI_STATUS +acpi_tb_get_table_pointer ( + ACPI_PHYSICAL_ADDRESS physical_address, + u32 flags, + u32 *size, + ACPI_TABLE_HEADER **table_ptr); /* * tbgetall - Get all firmware ACPI tables @@ -151,7 +169,8 @@ ACPI_STATUS acpi_tb_find_rsdp ( - ACPI_TABLE_DESC *table_info); + ACPI_TABLE_DESC *table_info, + u32 flags); /* @@ -166,7 +185,7 @@ acpi_tb_map_acpi_table ( ACPI_PHYSICAL_ADDRESS physical_address, u32 *size, - void **logical_address); + ACPI_TABLE_HEADER **logical_address); ACPI_STATUS acpi_tb_verify_table_checksum ( diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/actbl.h linux/drivers/acpi/include/actbl.h --- v2.4.5/linux/drivers/acpi/include/actbl.h Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/include/actbl.h Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: actbl.h - Table data structures defined in ACPI specification - * $Revision: 45 $ + * $Revision: 46 $ * *****************************************************************************/ @@ -140,7 +140,7 @@ u8 processor_apic_id; /* ACPI processor id */ u8 local_apic_id; /* processor's local APIC id */ u32 processor_enabled: 1; /* Processor is usable if set */ - u32 reserved1 : 32; + u32 reserved1 : 31; } PROCESSOR_APIC; diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/actbl2.h linux/drivers/acpi/include/actbl2.h --- v2.4.5/linux/drivers/acpi/include/actbl2.h Mon Jan 29 10:15:59 2001 +++ linux/drivers/acpi/include/actbl2.h Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: actbl2.h - ACPI Specification Revision 2.0 Tables - * $Revision: 21 $ + * $Revision: 24 $ * *****************************************************************************/ @@ -26,159 +26,156 @@ #ifndef __ACTBL2_H__ #define __ACTBL2_H__ -/**************************************/ -/* Prefered Power Management Profiles */ -/**************************************/ -#define PM_UNSPECIFIED 0 -#define PM_DESKTOP 1 -#define PM_MOBILE 2 -#define PM_WORKSTATION 3 -#define PM_ENTERPRISE_SERVER 4 -#define PM_SOHO_SERVER 5 -#define PM_APPLIANCE_PC 6 - -/*********************************************/ -/* ACPI Boot Arch Flags, See spec Table 5-10 */ -/*********************************************/ -#define BAF_LEGACY_DEVICES 0x0001 -#define BAF_8042_KEYBOARD_CONTROLLER 0x0002 +/* + * Prefered Power Management Profiles + */ +#define PM_UNSPECIFIED 0 +#define PM_DESKTOP 1 +#define PM_MOBILE 2 +#define PM_WORKSTATION 3 +#define PM_ENTERPRISE_SERVER 4 +#define PM_SOHO_SERVER 5 +#define PM_APPLIANCE_PC 6 + +/* + * ACPI Boot Arch Flags + */ +#define BAF_LEGACY_DEVICES 0x0001 +#define BAF_8042_KEYBOARD_CONTROLLER 0x0002 + +#define FADT2_REVISION_ID 3 -#define FADT2_REVISION_ID 3 #pragma pack(1) -/*************************************/ -/* ACPI Specification Rev 2.0 for */ -/* the Root System Description Table */ -/*************************************/ +/* + * ACPI Specification Rev 2.0 for the Root System Description Table + */ typedef struct { - ACPI_TABLE_HEADER header; /* Table header */ - u32 table_offset_entry [1]; /* Array of pointers to */ - /* other tables' headers */ + ACPI_TABLE_HEADER header; /* Table header */ + u32 table_offset_entry [1]; /* Array of pointers to */ + /* other tables' headers */ } RSDT_DESCRIPTOR_REV2; -/********************************************/ -/* ACPI Specification Rev 2.0 for the */ -/* Extended System Description Table (XSDT) */ -/********************************************/ +/* + * ACPI Specification Rev 2.0 for the Extended System Description Table (XSDT) + */ typedef struct { - ACPI_TABLE_HEADER header; /* Table header */ - UINT64 table_offset_entry [1]; /* Array of pointers to */ - /* other tables' headers */ + ACPI_TABLE_HEADER header; /* Table header */ + UINT64 table_offset_entry [1]; /* Array of pointers to */ + /* other tables' headers */ } XSDT_DESCRIPTOR_REV2; -/***************************************/ -/* ACPI Specification Rev 2.0 for */ -/* the Firmware ACPI Control Structure */ -/***************************************/ + +/* + * ACPI Specification Rev 2.0 for the Firmware ACPI Control Structure + */ typedef struct { - NATIVE_CHAR signature[4]; /* signature "FACS" */ - u32 length; /* length of structure, in bytes */ - u32 hardware_signature; /* hardware configuration signature */ - u32 firmware_waking_vector; /* 32bit physical address of the Firmware Waking Vector. */ - u32 global_lock; /* Global Lock used to synchronize access to shared hardware resources */ - u32 S4_bios_f : 1; /* Indicates if S4_bIOS support is present */ - u32 reserved1 : 31; /* must be 0 */ - UINT64 Xfirmware_waking_vector; /* 64bit physical address of the Firmware Waking Vector. */ - u8 version; /* Version of this table */ - u8 reserved3 [31]; /* reserved - must be zero */ + NATIVE_CHAR signature[4]; /* signature "FACS" */ + u32 length; /* length of structure, in bytes */ + u32 hardware_signature; /* hardware configuration signature */ + u32 firmware_waking_vector; /* 32bit physical address of the Firmware Waking Vector. */ + u32 global_lock; /* Global Lock used to synchronize access to shared hardware resources */ + u32 S4_bios_f : 1; /* Indicates if S4_bIOS support is present */ + u32 reserved1 : 31; /* must be 0 */ + UINT64 Xfirmware_waking_vector; /* 64bit physical address of the Firmware Waking Vector. */ + u8 version; /* Version of this table */ + u8 reserved3 [31]; /* reserved - must be zero */ } FACS_DESCRIPTOR_REV2; -/***************************************/ -/* ACPI Specification Rev 2.0 for */ -/* the Generic Address Structure (GAS) */ -/***************************************/ +/* + * ACPI Specification Rev 2.0 for the Generic Address Structure (GAS) + */ typedef struct { - u8 address_space_id; /* Address space where struct or register exists. */ - u8 register_bit_width; /* Size in bits of given register */ - u8 register_bit_offset; /* Bit offset within the register */ - u8 reserved; /* Must be 0 */ - UINT64 address; /* 64-bit address of struct or register */ - -} ACPI_GAS; + u8 address_space_id; /* Address space where struct or register exists. */ + u8 register_bit_width; /* Size in bits of given register */ + u8 register_bit_offset; /* Bit offset within the register */ + u8 reserved; /* Must be 0 */ + UINT64 address; /* 64-bit address of struct or register */ + +} ACPI_GENERIC_ADDRESS; -/************************************/ -/* ACPI Specification Rev 2.0 for */ -/* the Fixed ACPI Description Table */ -/************************************/ +/* + * ACPI Specification Rev 2.0 for the Fixed ACPI Description Table + */ typedef struct { - ACPI_TABLE_HEADER header; /* table header */ - u32 V1_firmware_ctrl; /* 32-bit physical address of FACS */ - u32 V1_dsdt; /* 32-bit physical address of DSDT */ - u8 reserved1; /* System Interrupt Model isn't used in ACPI 2.0*/ - u8 prefer_PM_profile; /* Conveys preferred power management profile to OSPM. */ - u16 sci_int; /* System vector of SCI interrupt */ - u32 smi_cmd; /* Port address of SMI command port */ - u8 acpi_enable; /* value to write to smi_cmd to enable ACPI */ - u8 acpi_disable; /* value to write to smi_cmd to disable ACPI */ - u8 S4_bios_req; /* Value to write to SMI CMD to enter S4_bIOS state */ - u8 pstate_cnt; /* processor performance state control*/ - u32 V1_pm1a_evt_blk; /* Port address of Power Mgt 1a Acpi_event Reg Blk */ - u32 V1_pm1b_evt_blk; /* Port address of Power Mgt 1b Acpi_event Reg Blk */ - u32 V1_pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */ - u32 V1_pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */ - u32 V1_pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */ - u32 V1_pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ - u32 V1_gpe0blk; /* Port addr of General Purpose Acpi_event 0 Reg Blk */ - u32 V1_gpe1_blk; /* Port addr of General Purpose Acpi_event 1 Reg Blk */ - u8 pm1_evt_len; /* Byte Length of ports at pm1_x_evt_blk */ - u8 pm1_cnt_len; /* Byte Length of ports at pm1_x_cnt_blk */ - u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */ - u8 pm_tm_len; /* Byte Length of ports at pm_tm_blk */ - u8 gpe0blk_len; /* Byte Length of ports at gpe0_blk */ - u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */ - u8 gpe1_base; /* offset in gpe model where gpe1 events start */ - u8 cst_cnt; /* Support for the _CST object and C States change notification.*/ - u16 plvl2_lat; /* worst case HW latency to enter/exit C2 state */ - u16 plvl3_lat; /* worst case HW latency to enter/exit C3 state */ - u16 flush_size; /* number of flush strides that need to be read */ - u16 flush_stride; /* Processor's memory cache line width, in bytes */ - u8 duty_offset; /* Processor_’s duty cycle index in processor's P_CNT reg*/ - u8 duty_width; /* Processor_’s duty cycle value bit width in P_CNT register.*/ - u8 day_alrm; /* index to day-of-month alarm in RTC CMOS RAM */ - u8 mon_alrm; /* index to month-of-year alarm in RTC CMOS RAM */ - u8 century; /* index to century in RTC CMOS RAM */ - u16 iapc_boot_arch; /* IA-PC Boot Architecture Flags. See Table 5-10 for description*/ - u8 reserved2; /* reserved */ - u32 wb_invd : 1; /* wbinvd instruction works properly */ - u32 wb_invd_flush : 1; /* wbinvd flushes but does not invalidate */ - u32 proc_c1 : 1; /* all processors support C1 state */ - u32 plvl2_up : 1; /* C2 state works on MP system */ - u32 pwr_button : 1; /* Power button is handled as a generic feature */ - u32 sleep_button : 1; /* Sleep button is handled as a generic feature, or not present */ - u32 fixed_rTC : 1; /* RTC wakeup stat not in fixed register space */ - u32 rtcs4 : 1; /* RTC wakeup stat not possible from S4 */ - u32 tmr_val_ext : 1; /* tmr_val is 32 bits */ - u32 dock_cap : 1; /* Supports Docking */ - u32 reset_reg_sup : 1; /* Indicates system supports system reset via the FADT RESET_REG*/ - u32 sealed_case : 1; /* Indicates system has no internal expansion capabilities and case is sealed. */ - u32 headless : 1; /* Indicates system does not have local video capabilities or local input devices.*/ - u32 cpu_sw_sleep : 1; /* Indicates to OSPM that a processor native instruction */ - /* must be executed after writing the SLP_TYPx register. */ - u32 reserved6 : 18; /* reserved - must be zero */ - - ACPI_GAS reset_register; /* Reset register address in GAS format */ - u8 reset_value; /* Value to write to the Reset_register port to reset the system. */ - u8 reserved7[3]; /* These three bytes must be zero */ - UINT64 Xfirmware_ctrl; /* 64-bit physical address of FACS */ - UINT64 Xdsdt; /* 64-bit physical address of DSDT */ - ACPI_GAS Xpm1a_evt_blk; /* Extended Power Mgt 1a Acpi_event Reg Blk address */ - ACPI_GAS Xpm1b_evt_blk; /* Extended Power Mgt 1b Acpi_event Reg Blk address */ - ACPI_GAS Xpm1a_cnt_blk; /* Extended Power Mgt 1a Control Reg Blk address */ - ACPI_GAS Xpm1b_cnt_blk; /* Extended Power Mgt 1b Control Reg Blk address */ - ACPI_GAS Xpm2_cnt_blk; /* Extended Power Mgt 2 Control Reg Blk address */ - ACPI_GAS Xpm_tmr_blk; /* Extended Power Mgt Timer Ctrl Reg Blk address */ - ACPI_GAS Xgpe0blk; /* Extended General Purpose Acpi_event 0 Reg Blk address */ - ACPI_GAS Xgpe1_blk; /* Extended General Purpose Acpi_event 1 Reg Blk address */ + ACPI_TABLE_HEADER header; /* table header */ + u32 V1_firmware_ctrl; /* 32-bit physical address of FACS */ + u32 V1_dsdt; /* 32-bit physical address of DSDT */ + u8 reserved1; /* System Interrupt Model isn't used in ACPI 2.0*/ + u8 prefer_PM_profile; /* Conveys preferred power management profile to OSPM. */ + u16 sci_int; /* System vector of SCI interrupt */ + u32 smi_cmd; /* Port address of SMI command port */ + u8 acpi_enable; /* value to write to smi_cmd to enable ACPI */ + u8 acpi_disable; /* value to write to smi_cmd to disable ACPI */ + u8 S4_bios_req; /* Value to write to SMI CMD to enter S4_bIOS state */ + u8 pstate_cnt; /* processor performance state control*/ + u32 V1_pm1a_evt_blk; /* Port address of Power Mgt 1a Acpi_event Reg Blk */ + u32 V1_pm1b_evt_blk; /* Port address of Power Mgt 1b Acpi_event Reg Blk */ + u32 V1_pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */ + u32 V1_pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */ + u32 V1_pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */ + u32 V1_pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ + u32 V1_gpe0blk; /* Port addr of General Purpose Acpi_event 0 Reg Blk */ + u32 V1_gpe1_blk; /* Port addr of General Purpose Acpi_event 1 Reg Blk */ + u8 pm1_evt_len; /* Byte Length of ports at pm1_x_evt_blk */ + u8 pm1_cnt_len; /* Byte Length of ports at pm1_x_cnt_blk */ + u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */ + u8 pm_tm_len; /* Byte Length of ports at pm_tm_blk */ + u8 gpe0blk_len; /* Byte Length of ports at gpe0_blk */ + u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */ + u8 gpe1_base; /* offset in gpe model where gpe1 events start */ + u8 cst_cnt; /* Support for the _CST object and C States change notification.*/ + u16 plvl2_lat; /* worst case HW latency to enter/exit C2 state */ + u16 plvl3_lat; /* worst case HW latency to enter/exit C3 state */ + u16 flush_size; /* number of flush strides that need to be read */ + u16 flush_stride; /* Processor's memory cache line width, in bytes */ + u8 duty_offset; /* Processor’s duty cycle index in processor's P_CNT reg*/ + u8 duty_width; /* Processor’s duty cycle value bit width in P_CNT register.*/ + u8 day_alrm; /* index to day-of-month alarm in RTC CMOS RAM */ + u8 mon_alrm; /* index to month-of-year alarm in RTC CMOS RAM */ + u8 century; /* index to century in RTC CMOS RAM */ + u16 iapc_boot_arch; /* IA-PC Boot Architecture Flags. See Table 5-10 for description*/ + u8 reserved2; /* reserved */ + u32 wb_invd : 1; /* wbinvd instruction works properly */ + u32 wb_invd_flush : 1; /* wbinvd flushes but does not invalidate */ + u32 proc_c1 : 1; /* all processors support C1 state */ + u32 plvl2_up : 1; /* C2 state works on MP system */ + u32 pwr_button : 1; /* Power button is handled as a generic feature */ + u32 sleep_button : 1; /* Sleep button is handled as a generic feature, or not present */ + u32 fixed_rTC : 1; /* RTC wakeup stat not in fixed register space */ + u32 rtcs4 : 1; /* RTC wakeup stat not possible from S4 */ + u32 tmr_val_ext : 1; /* tmr_val is 32 bits */ + u32 dock_cap : 1; /* Supports Docking */ + u32 reset_reg_sup : 1; /* Indicates system supports system reset via the FADT RESET_REG*/ + u32 sealed_case : 1; /* Indicates system has no internal expansion capabilities and case is sealed. */ + u32 headless : 1; /* Indicates system does not have local video capabilities or local input devices.*/ + u32 cpu_sw_sleep : 1; /* Indicates to OSPM that a processor native instruction */ + /* must be executed after writing the SLP_TYPx register. */ + u32 reserved6 : 18; /* reserved - must be zero */ + + ACPI_GENERIC_ADDRESS reset_register; /* Reset register address in GAS format */ + u8 reset_value; /* Value to write to the Reset_register port to reset the system. */ + u8 reserved7[3]; /* These three bytes must be zero */ + UINT64 Xfirmware_ctrl; /* 64-bit physical address of FACS */ + UINT64 Xdsdt; /* 64-bit physical address of DSDT */ + ACPI_GENERIC_ADDRESS Xpm1a_evt_blk; /* Extended Power Mgt 1a Acpi_event Reg Blk address */ + ACPI_GENERIC_ADDRESS Xpm1b_evt_blk; /* Extended Power Mgt 1b Acpi_event Reg Blk address */ + ACPI_GENERIC_ADDRESS Xpm1a_cnt_blk; /* Extended Power Mgt 1a Control Reg Blk address */ + ACPI_GENERIC_ADDRESS Xpm1b_cnt_blk; /* Extended Power Mgt 1b Control Reg Blk address */ + ACPI_GENERIC_ADDRESS Xpm2_cnt_blk; /* Extended Power Mgt 2 Control Reg Blk address */ + ACPI_GENERIC_ADDRESS Xpm_tmr_blk; /* Extended Power Mgt Timer Ctrl Reg Blk address */ + ACPI_GENERIC_ADDRESS Xgpe0blk; /* Extended General Purpose Acpi_event 0 Reg Blk address */ + ACPI_GENERIC_ADDRESS Xgpe1_blk; /* Extended General Purpose Acpi_event 1 Reg Blk address */ } FADT_DESCRIPTOR_REV2; diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/actbl71.h linux/drivers/acpi/include/actbl71.h --- v2.4.5/linux/drivers/acpi/include/actbl71.h Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/include/actbl71.h Wed Jun 20 17:47:40 2001 @@ -3,7 +3,7 @@ * Name: actbl71.h - IA-64 Extensions to the ACPI Spec Rev. 0.71 * This file includes tables specific to this * specification revision. - * $Revision: 9 $ + * $Revision: 11 $ * *****************************************************************************/ @@ -28,8 +28,10 @@ #ifndef __ACTBL71_H__ #define __ACTBL71_H__ + /* 0.71 FADT Address_space data item bitmasks defines */ /* If the associated bit is zero then it is in memory space else in io space */ + #define SMI_CMD_ADDRESS_SPACE 0x01 #define PM1_BLK_ADDRESS_SPACE 0x02 #define PM2_CNT_BLK_ADDRESS_SPACE 0x04 @@ -38,10 +40,11 @@ #define GPE1_BLK_ADDRESS_SPACE 0x20 /* Only for clarity in declarations */ + typedef UINT64 IO_ADDRESS; -#pragma pack(1) +#pragma pack(1) typedef struct /* Root System Descriptor Pointer */ { NATIVE_CHAR signature [8]; /* contains "RSD PTR " */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/actypes.h linux/drivers/acpi/include/actypes.h --- v2.4.5/linux/drivers/acpi/include/actypes.h Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/include/actypes.h Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: actypes.h - Common data types for the entire ACPI subsystem - * $Revision: 165 $ + * $Revision: 180 $ * *****************************************************************************/ @@ -231,6 +231,10 @@ #define ACPI_ROOT_OBJECT (ACPI_HANDLE)(-1) + +/* + * Initialization sequence + */ #define ACPI_FULL_INITIALIZATION 0x00 #define ACPI_NO_ADDRESS_SPACE_INIT 0x01 #define ACPI_NO_HARDWARE_INIT 0x02 @@ -241,8 +245,11 @@ /* - * Sleep state constants + * Power state values */ + +#define ACPI_STATE_UNKNOWN (u8) 0xFF + #define ACPI_STATE_S0 (u8) 0 #define ACPI_STATE_S1 (u8) 1 #define ACPI_STATE_S2 (u8) 2 @@ -252,6 +259,26 @@ /* let's pretend S4_bIOS didn't exist for now. ASG */ #define ACPI_STATE_S4_bIOS (u8) 6 #define ACPI_S_STATES_MAX ACPI_STATE_S5 +#define ACPI_S_STATE_COUNT 6 + +#define ACPI_STATE_D0 (u8) 0 +#define ACPI_STATE_D1 (u8) 1 +#define ACPI_STATE_D2 (u8) 2 +#define ACPI_STATE_D3 (u8) 3 +#define ACPI_D_STATES_MAX ACPI_STATE_D3 +#define ACPI_D_STATE_COUNT 4 + +/* + * Standard notify values + */ +#define ACPI_NOTIFY_BUS_CHECK (u8) 0 +#define ACPI_NOTIFY_DEVICE_CHECK (u8) 1 +#define ACPI_NOTIFY_DEVICE_WAKE (u8) 2 +#define ACPI_NOTIFY_EJECT_REQUEST (u8) 3 +#define ACPI_NOTIFY_DEVICE_CHECK_LIGHT (u8) 4 +#define ACPI_NOTIFY_FREQUENCY_MISMATCH (u8) 5 +#define ACPI_NOTIFY_BUS_MODE_MISMATCH (u8) 6 +#define ACPI_NOTIFY_POWER_FAULT (u8) 7 /* @@ -282,35 +309,7 @@ */ typedef u32 ACPI_OBJECT_TYPE; -typedef u8 OBJECT_TYPE_INTERNAL; - -#define ACPI_BTYPE_ANY 0x00000000 -#define ACPI_BTYPE_INTEGER 0x00000001 -#define ACPI_BTYPE_STRING 0x00000002 -#define ACPI_BTYPE_BUFFER 0x00000004 -#define ACPI_BTYPE_PACKAGE 0x00000008 -#define ACPI_BTYPE_FIELD_UNIT 0x00000010 -#define ACPI_BTYPE_DEVICE 0x00000020 -#define ACPI_BTYPE_EVENT 0x00000040 -#define ACPI_BTYPE_METHOD 0x00000080 -#define ACPI_BTYPE_MUTEX 0x00000100 -#define ACPI_BTYPE_REGION 0x00000200 -#define ACPI_BTYPE_POWER 0x00000400 -#define ACPI_BTYPE_PROCESSOR 0x00000800 -#define ACPI_BTYPE_THERMAL 0x00001000 -#define ACPI_BTYPE_BUFFER_FIELD 0x00002000 -#define ACPI_BTYPE_DDB_HANDLE 0x00004000 -#define ACPI_BTYPE_DEBUG_OBJECT 0x00008000 -#define ACPI_BTYPE_REFERENCE 0x00010000 -#define ACPI_BTYPE_RESOURCE 0x00020000 - -#define ACPI_BTYPE_COMPUTE_DATA (ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_BUFFER) - -#define ACPI_BTYPE_DATA (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_PACKAGE) -#define ACPI_BTYPE_DATA_REFERENCE (ACPI_BTYPE_DATA | ACPI_BTYPE_REFERENCE | ACPI_BTYPE_DDB_HANDLE) -#define ACPI_BTYPE_DEVICE_OBJECTS (ACPI_BTYPE_DEVICE | ACPI_BTYPE_THERMAL | ACPI_BTYPE_PROCESSOR) -#define ACPI_BTYPE_OBJECTS_AND_REFS 0x00017FFF /* ARG or LOCAL */ -#define ACPI_BTYPE_ALL_OBJECTS 0x00007FFF +typedef u8 ACPI_OBJECT_TYPE8; #define ACPI_TYPE_ANY 0 /* 0x00 */ @@ -342,7 +341,7 @@ */ #define INTERNAL_TYPE_BEGIN 17 -#define INTERNAL_TYPE_DEF_FIELD 17 /* 0x11 */ +#define INTERNAL_TYPE_REGION_FIELD 17 /* 0x11 */ #define INTERNAL_TYPE_BANK_FIELD 18 /* 0x12 */ #define INTERNAL_TYPE_INDEX_FIELD 19 /* 0x13 */ #define INTERNAL_TYPE_REFERENCE 20 /* 0x14 Arg#, Local#, Name, Debug; used only in descriptors */ @@ -350,27 +349,62 @@ #define INTERNAL_TYPE_NOTIFY 22 /* 0x16 */ #define INTERNAL_TYPE_ADDRESS_HANDLER 23 /* 0x17 */ #define INTERNAL_TYPE_RESOURCE 24 /* 0x18 */ +#define INTERNAL_TYPE_RESOURCE_FIELD 25 /* 0x19 */ -#define INTERNAL_TYPE_NODE_MAX 24 +#define INTERNAL_TYPE_NODE_MAX 25 /* These are pseudo-types because there are never any namespace nodes with these types */ -#define INTERNAL_TYPE_DEF_FIELD_DEFN 25 /* 0x19 Name, Byte_const, multiple Field_element */ -#define INTERNAL_TYPE_BANK_FIELD_DEFN 26 /* 0x1A 2 Name,DWord_const,Byte_const,multi Field_element */ -#define INTERNAL_TYPE_INDEX_FIELD_DEFN 27 /* 0x1B 2 Name, Byte_const, multiple Field_element */ -#define INTERNAL_TYPE_IF 28 /* 0x1C Op_code, multiple Code */ -#define INTERNAL_TYPE_ELSE 29 /* 0x1D multiple Code */ -#define INTERNAL_TYPE_WHILE 30 /* 0x1E Op_code, multiple Code */ -#define INTERNAL_TYPE_SCOPE 31 /* 0x1F Name, multiple Node */ -#define INTERNAL_TYPE_DEF_ANY 32 /* 0x20 type is Any, suppress search of enclosing scopes */ -#define INTERNAL_TYPE_EXTRA 33 /* 0x21 */ +#define INTERNAL_TYPE_FIELD_DEFN 26 /* 0x1A Name, Byte_const, multiple Field_element */ +#define INTERNAL_TYPE_BANK_FIELD_DEFN 27 /* 0x1B 2 Name,DWord_const,Byte_const,multi Field_element */ +#define INTERNAL_TYPE_INDEX_FIELD_DEFN 28 /* 0x1C 2 Name, Byte_const, multiple Field_element */ +#define INTERNAL_TYPE_IF 29 /* 0x1D */ +#define INTERNAL_TYPE_ELSE 30 /* 0x1E */ +#define INTERNAL_TYPE_WHILE 31 /* 0x1F */ +#define INTERNAL_TYPE_SCOPE 32 /* 0x20 Name, multiple Node */ +#define INTERNAL_TYPE_DEF_ANY 33 /* 0x21 type is Any, suppress search of enclosing scopes */ +#define INTERNAL_TYPE_EXTRA 34 /* 0x22 */ -#define INTERNAL_TYPE_MAX 33 +#define INTERNAL_TYPE_MAX 34 -#define INTERNAL_TYPE_INVALID 34 +#define INTERNAL_TYPE_INVALID 35 #define ACPI_TYPE_NOT_FOUND 0xFF + +/* + * Bitmapped ACPI types + * Used internally only + */ +#define ACPI_BTYPE_ANY 0x00000000 +#define ACPI_BTYPE_INTEGER 0x00000001 +#define ACPI_BTYPE_STRING 0x00000002 +#define ACPI_BTYPE_BUFFER 0x00000004 +#define ACPI_BTYPE_PACKAGE 0x00000008 +#define ACPI_BTYPE_FIELD_UNIT 0x00000010 +#define ACPI_BTYPE_DEVICE 0x00000020 +#define ACPI_BTYPE_EVENT 0x00000040 +#define ACPI_BTYPE_METHOD 0x00000080 +#define ACPI_BTYPE_MUTEX 0x00000100 +#define ACPI_BTYPE_REGION 0x00000200 +#define ACPI_BTYPE_POWER 0x00000400 +#define ACPI_BTYPE_PROCESSOR 0x00000800 +#define ACPI_BTYPE_THERMAL 0x00001000 +#define ACPI_BTYPE_BUFFER_FIELD 0x00002000 +#define ACPI_BTYPE_DDB_HANDLE 0x00004000 +#define ACPI_BTYPE_DEBUG_OBJECT 0x00008000 +#define ACPI_BTYPE_REFERENCE 0x00010000 +#define ACPI_BTYPE_RESOURCE 0x00020000 + +#define ACPI_BTYPE_COMPUTE_DATA (ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_BUFFER) + +#define ACPI_BTYPE_DATA (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_PACKAGE) +#define ACPI_BTYPE_DATA_REFERENCE (ACPI_BTYPE_DATA | ACPI_BTYPE_REFERENCE | ACPI_BTYPE_DDB_HANDLE) +#define ACPI_BTYPE_DEVICE_OBJECTS (ACPI_BTYPE_DEVICE | ACPI_BTYPE_THERMAL | ACPI_BTYPE_PROCESSOR) +#define ACPI_BTYPE_OBJECTS_AND_REFS 0x0001FFFF /* ARG or LOCAL */ +#define ACPI_BTYPE_ALL_OBJECTS 0x0000FFFF + + /* * Acpi_event Types: * ------------ @@ -398,11 +432,11 @@ #define ACPI_EVENT_RTC (ACPI_EVENT_TYPE) 5 #define ACPI_EVENT_GENERAL (ACPI_EVENT_TYPE) 6 #define ACPI_EVENT_MAX 6 -#define NUM_FIXED_EVENTS (ACPI_EVENT_TYPE) 7 +#define ACPI_NUM_FIXED_EVENTS (ACPI_EVENT_TYPE) 7 #define ACPI_GPE_INVALID 0xFF #define ACPI_GPE_MAX 0xFF -#define NUM_GPE 256 +#define ACPI_NUM_GPE 256 #define ACPI_EVENT_LEVEL_TRIGGERED (ACPI_EVENT_TYPE) 1 #define ACPI_EVENT_EDGE_TRIGGERED (ACPI_EVENT_TYPE) 2 @@ -439,15 +473,15 @@ /* Address Space (Operation Region) Types */ -typedef u8 ACPI_ADDRESS_SPACE_TYPE; +typedef u8 ACPI_ADR_SPACE_TYPE; -#define ADDRESS_SPACE_SYSTEM_MEMORY (ACPI_ADDRESS_SPACE_TYPE) 0 -#define ADDRESS_SPACE_SYSTEM_IO (ACPI_ADDRESS_SPACE_TYPE) 1 -#define ADDRESS_SPACE_PCI_CONFIG (ACPI_ADDRESS_SPACE_TYPE) 2 -#define ADDRESS_SPACE_EC (ACPI_ADDRESS_SPACE_TYPE) 3 -#define ADDRESS_SPACE_SMBUS (ACPI_ADDRESS_SPACE_TYPE) 4 -#define ADDRESS_SPACE_CMOS (ACPI_ADDRESS_SPACE_TYPE) 5 -#define ADDRESS_SPACE_PCI_BAR_TARGET (ACPI_ADDRESS_SPACE_TYPE) 6 +#define ACPI_ADR_SPACE_SYSTEM_MEMORY (ACPI_ADR_SPACE_TYPE) 0 +#define ACPI_ADR_SPACE_SYSTEM_IO (ACPI_ADR_SPACE_TYPE) 1 +#define ACPI_ADR_SPACE_PCI_CONFIG (ACPI_ADR_SPACE_TYPE) 2 +#define ACPI_ADR_SPACE_EC (ACPI_ADR_SPACE_TYPE) 3 +#define ACPI_ADR_SPACE_SMBUS (ACPI_ADR_SPACE_TYPE) 4 +#define ACPI_ADR_SPACE_CMOS (ACPI_ADR_SPACE_TYPE) 5 +#define ACPI_ADR_SPACE_PCI_BAR_TARGET (ACPI_ADR_SPACE_TYPE) 6 /* @@ -495,7 +529,7 @@ { ACPI_OBJECT_TYPE type; u32 proc_id; - u32 pblk_address; + ACPI_IO_ADDRESS pblk_address; u32 pblk_length; } processor; @@ -616,29 +650,33 @@ /* not found in the IA32 manner */ } ACPI_INIT_DATA; + /* * Various handlers and callback procedures */ typedef -u32 (*FIXED_EVENT_HANDLER) ( +u32 (*ACPI_EVENT_HANDLER) ( void *context); typedef -void (*GPE_HANDLER) ( +void (*ACPI_GPE_HANDLER) ( void *context); typedef -void (*NOTIFY_HANDLER) ( +void (*ACPI_NOTIFY_HANDLER) ( ACPI_HANDLE device, u32 value, void *context); -#define ADDRESS_SPACE_READ 1 -#define ADDRESS_SPACE_WRITE 2 + +/* Address Spaces (Operation Regions */ + +#define ACPI_READ_ADR_SPACE 1 +#define ACPI_WRITE_ADR_SPACE 2 typedef -ACPI_STATUS (*ADDRESS_SPACE_HANDLER) ( +ACPI_STATUS (*ACPI_ADR_SPACE_HANDLER) ( u32 function, ACPI_PHYSICAL_ADDRESS address, u32 bit_width, @@ -646,11 +684,11 @@ void *handler_context, void *region_context); -#define ACPI_DEFAULT_HANDLER ((ADDRESS_SPACE_HANDLER) NULL) +#define ACPI_DEFAULT_HANDLER ((ACPI_ADR_SPACE_HANDLER) NULL) typedef -ACPI_STATUS (*ADDRESS_SPACE_SETUP) ( +ACPI_STATUS (*ACPI_ADR_SPACE_SETUP) ( ACPI_HANDLE region_handle, u32 function, void *handler_context, @@ -660,7 +698,7 @@ #define ACPI_REGION_DEACTIVATE 1 typedef -ACPI_STATUS (*WALK_CALLBACK) ( +ACPI_STATUS (*ACPI_WALK_CALLBACK) ( ACPI_HANDLE obj_handle, u32 nesting_level, void *context, @@ -697,7 +735,7 @@ ACPI_COMMON_OBJ_INFO; u32 valid; /* Are the next bits legit? */ - NATIVE_CHAR hardware_id [9]; /* _HID value if any */ + NATIVE_CHAR hardware_id[9]; /* _HID value if any */ NATIVE_CHAR unique_id[9]; /* _UID value if any */ ACPI_INTEGER address; /* _ADR value if any */ u32 current_status; /* _STA value */ @@ -711,7 +749,7 @@ u32 seg; u32 bus; u32 dev_func; -} PCI_HANDLER_CONTEXT; +} ACPI_PCI_SPACE_CONTEXT; typedef struct @@ -719,7 +757,7 @@ ACPI_PHYSICAL_ADDRESS mapped_physical_address; u8 *mapped_logical_address; u32 mapped_length; -} MEM_HANDLER_CONTEXT; +} ACPI_MEM_SPACE_CONTEXT; /* @@ -821,7 +859,7 @@ u32 number_of_interrupts; u32 interrupts[1]; -} IRQ_RESOURCE; +} ACPI_RESOURCE_IRQ; typedef struct { @@ -831,14 +869,14 @@ u32 number_of_channels; u32 channels[1]; -} DMA_RESOURCE; +} ACPI_RESOURCE_DMA; typedef struct { u32 compatibility_priority; u32 performance_robustness; -} START_DEPENDENT_FUNCTIONS_RESOURCE; +} ACPI_RESOURCE_START_DPF; /* * END_DEPENDENT_FUNCTIONS_RESOURCE struct is not @@ -853,21 +891,21 @@ u32 alignment; u32 range_length; -} IO_RESOURCE; +} ACPI_RESOURCE_IO; typedef struct { u32 base_address; u32 range_length; -} FIXED_IO_RESOURCE; +} ACPI_RESOURCE_FIXED_IO; typedef struct { u32 length; u8 reserved[1]; -} VENDOR_RESOURCE; +} ACPI_RESOURCE_VENDOR; typedef struct { @@ -877,7 +915,7 @@ u32 alignment; u32 range_length; -} MEMORY24_RESOURCE; +} ACPI_RESOURCE_MEM24; typedef struct { @@ -887,7 +925,7 @@ u32 alignment; u32 range_length; -} MEMORY32_RESOURCE; +} ACPI_RESOURCE_MEM32; typedef struct { @@ -895,36 +933,44 @@ u32 range_base_address; u32 range_length; -} FIXED_MEMORY32_RESOURCE; +} ACPI_RESOURCE_FIXED_MEM32; typedef struct { u16 cache_attribute; u16 read_write_attribute; -} MEMORY_ATTRIBUTE; +} ACPI_MEMORY_ATTRIBUTE; typedef struct { u16 range_attribute; u16 reserved; -} IO_ATTRIBUTE; +} ACPI_IO_ATTRIBUTE; typedef struct { u16 reserved1; u16 reserved2; -} BUS_ATTRIBUTE; +} ACPI_BUS_ATTRIBUTE; typedef union { - MEMORY_ATTRIBUTE memory; - IO_ATTRIBUTE io; - BUS_ATTRIBUTE bus; + ACPI_MEMORY_ATTRIBUTE memory; + ACPI_IO_ATTRIBUTE io; + ACPI_BUS_ATTRIBUTE bus; + +} ACPI_RESOURCE_ATTRIBUTE; + +typedef struct +{ + u32 index; + u32 string_length; + NATIVE_CHAR *string_ptr; -} ATTRIBUTE_DATA; +} ACPI_RESOURCE_SOURCE; typedef struct { @@ -933,17 +979,15 @@ u32 decode; u32 min_address_fixed; u32 max_address_fixed; - ATTRIBUTE_DATA attribute; + ACPI_RESOURCE_ATTRIBUTE attribute; u32 granularity; u32 min_address_range; u32 max_address_range; u32 address_translation_offset; u32 address_length; - u32 resource_source_index; - u32 resource_source_string_length; - NATIVE_CHAR resource_source[1]; + ACPI_RESOURCE_SOURCE resource_source; -} ADDRESS16_RESOURCE; +} ACPI_RESOURCE_ADDRESS16; typedef struct { @@ -952,17 +996,32 @@ u32 decode; u32 min_address_fixed; u32 max_address_fixed; - ATTRIBUTE_DATA attribute; + ACPI_RESOURCE_ATTRIBUTE attribute; u32 granularity; u32 min_address_range; u32 max_address_range; u32 address_translation_offset; u32 address_length; - u32 resource_source_index; - u32 resource_source_string_length; - NATIVE_CHAR resource_source[1]; + ACPI_RESOURCE_SOURCE resource_source; -} ADDRESS32_RESOURCE; +} ACPI_RESOURCE_ADDRESS32; + +typedef struct +{ + u32 resource_type; + u32 producer_consumer; + u32 decode; + u32 min_address_fixed; + u32 max_address_fixed; + ACPI_RESOURCE_ATTRIBUTE attribute; + UINT64 granularity; + UINT64 min_address_range; + UINT64 max_address_range; + UINT64 address_translation_offset; + UINT64 address_length; + ACPI_RESOURCE_SOURCE resource_source; + +} ACPI_RESOURCE_ADDRESS64; typedef struct { @@ -971,58 +1030,65 @@ u32 active_high_low; u32 shared_exclusive; u32 number_of_interrupts; + ACPI_RESOURCE_SOURCE resource_source; u32 interrupts[1]; - u32 resource_source_index; - u32 resource_source_string_length; - NATIVE_CHAR resource_source[1]; - -} EXTENDED_IRQ_RESOURCE; - -typedef enum -{ - irq, - dma, - start_dependent_functions, - end_dependent_functions, - io, - fixed_io, - vendor_specific, - end_tag, - memory24, - memory32, - fixed_memory32, - address16, - address32, - extended_irq -} RESOURCE_TYPE; + +} ACPI_RESOURCE_EXT_IRQ; + + +/* ACPI_RESOURCE_TYPEs */ + +#define ACPI_RSTYPE_IRQ 0 +#define ACPI_RSTYPE_DMA 1 +#define ACPI_RSTYPE_START_DPF 2 +#define ACPI_RSTYPE_END_DPF 3 +#define ACPI_RSTYPE_IO 4 +#define ACPI_RSTYPE_FIXED_IO 5 +#define ACPI_RSTYPE_VENDOR 6 +#define ACPI_RSTYPE_END_TAG 7 +#define ACPI_RSTYPE_MEM24 8 +#define ACPI_RSTYPE_MEM32 9 +#define ACPI_RSTYPE_FIXED_MEM32 10 +#define ACPI_RSTYPE_ADDRESS16 11 +#define ACPI_RSTYPE_ADDRESS32 12 +#define ACPI_RSTYPE_ADDRESS64 13 +#define ACPI_RSTYPE_EXT_IRQ 14 + +typedef u32 ACPI_RESOURCE_TYPE; typedef union { - IRQ_RESOURCE irq; - DMA_RESOURCE dma; - START_DEPENDENT_FUNCTIONS_RESOURCE start_dependent_functions; - IO_RESOURCE io; - FIXED_IO_RESOURCE fixed_io; - VENDOR_RESOURCE vendor_specific; - MEMORY24_RESOURCE memory24; - MEMORY32_RESOURCE memory32; - FIXED_MEMORY32_RESOURCE fixed_memory32; - ADDRESS16_RESOURCE address16; - ADDRESS32_RESOURCE address32; - EXTENDED_IRQ_RESOURCE extended_irq; -} RESOURCE_DATA; + ACPI_RESOURCE_IRQ irq; + ACPI_RESOURCE_DMA dma; + ACPI_RESOURCE_START_DPF start_dpf; + ACPI_RESOURCE_IO io; + ACPI_RESOURCE_FIXED_IO fixed_io; + ACPI_RESOURCE_VENDOR vendor_specific; + ACPI_RESOURCE_MEM24 memory24; + ACPI_RESOURCE_MEM32 memory32; + ACPI_RESOURCE_FIXED_MEM32 fixed_memory32; + ACPI_RESOURCE_ADDRESS16 address16; + ACPI_RESOURCE_ADDRESS32 address32; + ACPI_RESOURCE_ADDRESS64 address64; + ACPI_RESOURCE_EXT_IRQ extended_irq; + +} ACPI_RESOURCE_DATA; -typedef struct _resource_tag +typedef struct acpi_resource { - RESOURCE_TYPE id; + ACPI_RESOURCE_TYPE id; u32 length; - RESOURCE_DATA data; -} RESOURCE; + ACPI_RESOURCE_DATA data; + +} ACPI_RESOURCE; + +#define ACPI_RESOURCE_LENGTH 12 +#define ACPI_RESOURCE_LENGTH_NO_DATA 8 /* Id + Length fields */ + +#define SIZEOF_RESOURCE(type) (ACPI_RESOURCE_LENGTH_NO_DATA + sizeof (type)) -#define RESOURCE_LENGTH 12 -#define RESOURCE_LENGTH_NO_DATA 8 +#define NEXT_RESOURCE(res) (ACPI_RESOURCE *)((u8 *) res + res->length) -#define NEXT_RESOURCE(res) (RESOURCE*)((u8*) res + res->length) /* * END: Definitions for Resource Attributes diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/acutils.h linux/drivers/acpi/include/acutils.h --- v2.4.5/linux/drivers/acpi/include/acutils.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/acutils.h Wed Jun 20 17:47:40 2001 @@ -0,0 +1,663 @@ +/****************************************************************************** + * + * Name: acutils.h -- prototypes for the common (subsystem-wide) procedures + * $Revision: 100 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 + */ + +#ifndef _ACUTILS_H +#define _ACUTILS_H + + +typedef +ACPI_STATUS (*ACPI_PKG_CALLBACK) ( + u8 object_type, + ACPI_OPERAND_OBJECT *source_object, + ACPI_GENERIC_STATE *state, + void *context); + + +ACPI_STATUS +acpi_ut_walk_package_tree ( + ACPI_OPERAND_OBJECT *source_object, + void *target_object, + ACPI_PKG_CALLBACK walk_callback, + void *context); + + +typedef struct acpi_pkg_info +{ + u8 *free_space; + u32 length; + u32 object_space; + u32 num_packages; +} ACPI_PKG_INFO; + +#define REF_INCREMENT (u16) 0 +#define REF_DECREMENT (u16) 1 +#define REF_FORCE_DELETE (u16) 2 + +/* Acpi_ut_dump_buffer */ + +#define DB_BYTE_DISPLAY 1 +#define DB_WORD_DISPLAY 2 +#define DB_DWORD_DISPLAY 4 +#define DB_QWORD_DISPLAY 8 + + +/* Global initialization interfaces */ + +void +acpi_ut_init_globals ( + void); + +void +acpi_ut_terminate ( + void); + + +/* + * Ut_init - miscellaneous initialization and shutdown + */ + +ACPI_STATUS +acpi_ut_hardware_initialize ( + void); + +ACPI_STATUS +acpi_ut_subsystem_shutdown ( + void); + +ACPI_STATUS +acpi_ut_validate_fadt ( + void); + +/* + * Ut_global - Global data structures and procedures + */ + +#ifdef ACPI_DEBUG + +NATIVE_CHAR * +acpi_ut_get_mutex_name ( + u32 mutex_id); + +NATIVE_CHAR * +acpi_ut_get_type_name ( + u32 type); + +NATIVE_CHAR * +acpi_ut_get_region_name ( + u8 space_id); + +#endif + + +u8 +acpi_ut_valid_object_type ( + u32 type); + +ACPI_OWNER_ID +acpi_ut_allocate_owner_id ( + u32 id_type); + + +/* + * Ut_clib - Local implementations of C library functions + */ + +#ifndef ACPI_USE_SYSTEM_CLIBRARY + +u32 +acpi_ut_strlen ( + const NATIVE_CHAR *string); + +NATIVE_CHAR * +acpi_ut_strcpy ( + NATIVE_CHAR *dst_string, + const NATIVE_CHAR *src_string); + +NATIVE_CHAR * +acpi_ut_strncpy ( + NATIVE_CHAR *dst_string, + const NATIVE_CHAR *src_string, + NATIVE_UINT count); + +u32 +acpi_ut_strncmp ( + const NATIVE_CHAR *string1, + const NATIVE_CHAR *string2, + NATIVE_UINT count); + +u32 +acpi_ut_strcmp ( + const NATIVE_CHAR *string1, + const NATIVE_CHAR *string2); + +NATIVE_CHAR * +acpi_ut_strcat ( + NATIVE_CHAR *dst_string, + const NATIVE_CHAR *src_string); + +NATIVE_CHAR * +acpi_ut_strncat ( + NATIVE_CHAR *dst_string, + const NATIVE_CHAR *src_string, + NATIVE_UINT count); + +u32 +acpi_ut_strtoul ( + const NATIVE_CHAR *string, + NATIVE_CHAR **terminator, + u32 base); + +NATIVE_CHAR * +acpi_ut_strstr ( + NATIVE_CHAR *string1, + NATIVE_CHAR *string2); + +void * +acpi_ut_memcpy ( + void *dest, + const void *src, + NATIVE_UINT count); + +void * +acpi_ut_memset ( + void *dest, + NATIVE_UINT value, + NATIVE_UINT count); + +u32 +acpi_ut_to_upper ( + u32 c); + +u32 +acpi_ut_to_lower ( + u32 c); + +#endif /* ACPI_USE_SYSTEM_CLIBRARY */ + +/* + * Ut_copy - Object construction and conversion interfaces + */ + +ACPI_STATUS +acpi_ut_build_simple_object( + ACPI_OPERAND_OBJECT *obj, + ACPI_OBJECT *user_obj, + u8 *data_space, + u32 *buffer_space_used); + +ACPI_STATUS +acpi_ut_build_package_object ( + ACPI_OPERAND_OBJECT *obj, + u8 *buffer, + u32 *space_used); + +ACPI_STATUS +acpi_ut_copy_iobject_to_eobject ( + ACPI_OPERAND_OBJECT *obj, + ACPI_BUFFER *ret_buffer); + +ACPI_STATUS +acpi_ut_copy_esimple_to_isimple( + ACPI_OBJECT *user_obj, + ACPI_OPERAND_OBJECT *obj); + +ACPI_STATUS +acpi_ut_copy_eobject_to_iobject ( + ACPI_OBJECT *obj, + ACPI_OPERAND_OBJECT *internal_obj); + +ACPI_STATUS +acpi_ut_copy_isimple_to_isimple ( + ACPI_OPERAND_OBJECT *source_obj, + ACPI_OPERAND_OBJECT *dest_obj); + +ACPI_STATUS +acpi_ut_copy_ipackage_to_ipackage ( + ACPI_OPERAND_OBJECT *source_obj, + ACPI_OPERAND_OBJECT *dest_obj, + ACPI_WALK_STATE *walk_state); + + +/* + * Ut_create - Object creation + */ + +ACPI_STATUS +acpi_ut_update_object_reference ( + ACPI_OPERAND_OBJECT *object, + u16 action); + +ACPI_OPERAND_OBJECT * +_ut_create_internal_object ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + ACPI_OBJECT_TYPE8 type); + + +/* + * Ut_debug - Debug interfaces + */ + +u32 +get_debug_level ( + void); + +void +set_debug_level ( + u32 level); + +void +function_trace ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name); + +void +function_trace_ptr ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name, + void *pointer); + +void +function_trace_u32 ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name, + u32 integer); + +void +function_trace_str ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name, + NATIVE_CHAR *string); + +void +function_exit ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name); + +void +function_status_exit ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name, + ACPI_STATUS status); + +void +function_value_exit ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name, + ACPI_INTEGER value); + +void +function_ptr_exit ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name, + u8 *ptr); + +void +debug_print_prefix ( + NATIVE_CHAR *module_name, + u32 line_number); + +void +debug_print ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + u32 print_level, + NATIVE_CHAR *format, ...); + +void +debug_print_raw ( + NATIVE_CHAR *format, ...); + +void +_report_info ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id); + +void +_report_error ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id); + +void +_report_warning ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id); + +void +acpi_ut_dump_buffer ( + u8 *buffer, + u32 count, + u32 display, + u32 component_id); + + +/* + * Ut_delete - Object deletion + */ + +void +acpi_ut_delete_internal_obj ( + ACPI_OPERAND_OBJECT *object); + +void +acpi_ut_delete_internal_package_object ( + ACPI_OPERAND_OBJECT *object); + +void +acpi_ut_delete_internal_simple_object ( + ACPI_OPERAND_OBJECT *object); + +ACPI_STATUS +acpi_ut_delete_internal_object_list ( + ACPI_OPERAND_OBJECT **obj_list); + + +/* + * Ut_eval - object evaluation + */ + +/* Method name strings */ + +#define METHOD_NAME__HID "_HID" +#define METHOD_NAME__UID "_UID" +#define METHOD_NAME__ADR "_ADR" +#define METHOD_NAME__STA "_STA" +#define METHOD_NAME__REG "_REG" +#define METHOD_NAME__SEG "_SEG" +#define METHOD_NAME__BBN "_BBN" + + +ACPI_STATUS +acpi_ut_evaluate_numeric_object ( + NATIVE_CHAR *object_name, + ACPI_NAMESPACE_NODE *device_node, + ACPI_INTEGER *address); + +ACPI_STATUS +acpi_ut_execute_HID ( + ACPI_NAMESPACE_NODE *device_node, + ACPI_DEVICE_ID *hid); + +ACPI_STATUS +acpi_ut_execute_STA ( + ACPI_NAMESPACE_NODE *device_node, + u32 *status_flags); + +ACPI_STATUS +acpi_ut_execute_UID ( + ACPI_NAMESPACE_NODE *device_node, + ACPI_DEVICE_ID *uid); + + +/* + * Ut_error - exception interfaces + */ + +NATIVE_CHAR * +acpi_ut_format_exception ( + ACPI_STATUS status); + + +/* + * Ut_mutex - mutual exclusion interfaces + */ + +ACPI_STATUS +acpi_ut_mutex_initialize ( + void); + +void +acpi_ut_mutex_terminate ( + void); + +ACPI_STATUS +acpi_ut_create_mutex ( + ACPI_MUTEX_HANDLE mutex_id); + +ACPI_STATUS +acpi_ut_delete_mutex ( + ACPI_MUTEX_HANDLE mutex_id); + +ACPI_STATUS +acpi_ut_acquire_mutex ( + ACPI_MUTEX_HANDLE mutex_id); + +ACPI_STATUS +acpi_ut_release_mutex ( + ACPI_MUTEX_HANDLE mutex_id); + + +/* + * Ut_object - internal object create/delete/cache routines + */ + +void * +_ut_allocate_object_desc ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id); + +#define acpi_ut_create_internal_object(t) _ut_create_internal_object(_THIS_MODULE,__LINE__,_COMPONENT,t) +#define acpi_ut_allocate_object_desc() _ut_allocate_object_desc(_THIS_MODULE,__LINE__,_COMPONENT) + +void +acpi_ut_delete_object_desc ( + ACPI_OPERAND_OBJECT *object); + +u8 +acpi_ut_valid_internal_object ( + void *object); + + +/* + * Ut_ref_cnt - Object reference count management + */ + +void +acpi_ut_add_reference ( + ACPI_OPERAND_OBJECT *object); + +void +acpi_ut_remove_reference ( + ACPI_OPERAND_OBJECT *object); + +/* + * Ut_size - Object size routines + */ + +ACPI_STATUS +acpi_ut_get_simple_object_size ( + ACPI_OPERAND_OBJECT *obj, + u32 *obj_length); + +ACPI_STATUS +acpi_ut_get_package_object_size ( + ACPI_OPERAND_OBJECT *obj, + u32 *obj_length); + +ACPI_STATUS +acpi_ut_get_object_size( + ACPI_OPERAND_OBJECT *obj, + u32 *obj_length); + + +/* + * Ut_state - Generic state creation/cache routines + */ + +void +acpi_ut_push_generic_state ( + ACPI_GENERIC_STATE **list_head, + ACPI_GENERIC_STATE *state); + +ACPI_GENERIC_STATE * +acpi_ut_pop_generic_state ( + ACPI_GENERIC_STATE **list_head); + + +ACPI_GENERIC_STATE * +acpi_ut_create_generic_state ( + void); + +ACPI_GENERIC_STATE * +acpi_ut_create_update_state ( + ACPI_OPERAND_OBJECT *object, + u16 action); + +ACPI_GENERIC_STATE * +acpi_ut_create_pkg_state ( + void *internal_object, + void *external_object, + u16 index); + +ACPI_STATUS +acpi_ut_create_update_state_and_push ( + ACPI_OPERAND_OBJECT *object, + u16 action, + ACPI_GENERIC_STATE **state_list); + +ACPI_STATUS +acpi_ut_create_pkg_state_and_push ( + void *internal_object, + void *external_object, + u16 index, + ACPI_GENERIC_STATE **state_list); + +ACPI_GENERIC_STATE * +acpi_ut_create_control_state ( + void); + +void +acpi_ut_delete_generic_state ( + ACPI_GENERIC_STATE *state); + +void +acpi_ut_delete_generic_state_cache ( + void); + +void +acpi_ut_delete_object_cache ( + void); + +/* + * Ututils + */ + +u8 +acpi_ut_valid_acpi_name ( + u32 name); + +u8 +acpi_ut_valid_acpi_character ( + NATIVE_CHAR character); + +NATIVE_CHAR * +acpi_ut_strupr ( + NATIVE_CHAR *src_string); + +ACPI_STATUS +acpi_ut_resolve_package_references ( + ACPI_OPERAND_OBJECT *obj_desc); + + +#ifdef ACPI_DEBUG +void +acpi_ut_display_init_pathname ( + ACPI_HANDLE obj_handle, + char *path); + +#endif + + +/* + * Memory allocation functions and related macros. + * Macros that expand to include filename and line number + */ + +void * +_ut_allocate ( + u32 size, + u32 component, + NATIVE_CHAR *module, + u32 line); + +void * +_ut_callocate ( + u32 size, + u32 component, + NATIVE_CHAR *module, + u32 line); + +void +_ut_free ( + void *address, + u32 component, + NATIVE_CHAR *module, + u32 line); + +void +acpi_ut_init_static_object ( + ACPI_OPERAND_OBJECT *obj_desc); + + +#ifdef ACPI_DEBUG_TRACK_ALLOCATIONS +void +acpi_ut_dump_allocation_info ( + void); + +void +acpi_ut_dump_current_allocations ( + u32 component, + NATIVE_CHAR *module); +#endif + + +#define acpi_ut_allocate(a) _ut_allocate(a,_COMPONENT,_THIS_MODULE,__LINE__) +#define acpi_ut_callocate(a) _ut_callocate(a, _COMPONENT,_THIS_MODULE,__LINE__) +#define acpi_ut_free(a) _ut_free(a,_COMPONENT,_THIS_MODULE,__LINE__) + + +#endif /* _ACUTILS_H */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/amlcode.h linux/drivers/acpi/include/amlcode.h --- v2.4.5/linux/drivers/acpi/include/amlcode.h Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/include/amlcode.h Wed Jun 20 17:47:40 2001 @@ -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: 46 $ + * $Revision: 52 $ * *****************************************************************************/ @@ -98,12 +98,12 @@ #define AML_SIZE_OF_OP (u16) 0x87 #define AML_INDEX_OP (u16) 0x88 #define AML_MATCH_OP (u16) 0x89 -#define AML_DWORD_FIELD_OP (u16) 0x8a -#define AML_WORD_FIELD_OP (u16) 0x8b -#define AML_BYTE_FIELD_OP (u16) 0x8c -#define AML_BIT_FIELD_OP (u16) 0x8d +#define AML_CREATE_DWORD_FIELD_OP (u16) 0x8a +#define AML_CREATE_WORD_FIELD_OP (u16) 0x8b +#define AML_CREATE_BYTE_FIELD_OP (u16) 0x8c +#define AML_CREATE_BIT_FIELD_OP (u16) 0x8d #define AML_TYPE_OP (u16) 0x8e -#define AML_QWORD_FIELD_OP (u16) 0x8f /* ACPI 2.0 */ +#define AML_CREATE_QWORD_FIELD_OP (u16) 0x8f /* ACPI 2.0 */ #define AML_LAND_OP (u16) 0x90 #define AML_LOR_OP (u16) 0x91 #define AML_LNOT_OP (u16) 0x92 @@ -154,7 +154,7 @@ #define AML_DEBUG_OP (u16) 0x5b31 #define AML_FATAL_OP (u16) 0x5b32 #define AML_REGION_OP (u16) 0x5b80 -#define AML_DEF_FIELD_OP (u16) 0x5b81 +#define AML_FIELD_OP (u16) 0x5b81 #define AML_DEVICE_OP (u16) 0x5b82 #define AML_PROCESSOR_OP (u16) 0x5b83 #define AML_POWER_RES_OP (u16) 0x5b84 @@ -177,14 +177,14 @@ * any valid ACPI ASCII values (A-Z, 0-9, '-') */ -#define AML_NAMEPATH_OP (u16) 0x002d -#define AML_NAMEDFIELD_OP (u16) 0x0030 -#define AML_RESERVEDFIELD_OP (u16) 0x0031 -#define AML_ACCESSFIELD_OP (u16) 0x0032 -#define AML_BYTELIST_OP (u16) 0x0033 -#define AML_STATICSTRING_OP (u16) 0x0034 -#define AML_METHODCALL_OP (u16) 0x0035 -#define AML_RETURN_VALUE_OP (u16) 0x0036 +#define AML_INT_NAMEPATH_OP (u16) 0x002d +#define AML_INT_NAMEDFIELD_OP (u16) 0x0030 +#define AML_INT_RESERVEDFIELD_OP (u16) 0x0031 +#define AML_INT_ACCESSFIELD_OP (u16) 0x0032 +#define AML_INT_BYTELIST_OP (u16) 0x0033 +#define AML_INT_STATICSTRING_OP (u16) 0x0034 +#define AML_INT_METHODCALL_OP (u16) 0x0035 +#define AML_INT_RETURN_VALUE_OP (u16) 0x0036 #define ARG_NONE 0x0 @@ -222,7 +222,7 @@ /* "Standard" ACPI types are 1-15 (0x0F) */ -#define ARGI_INTEGER ACPI_TYPE_INTEGER /* 1 */ +#define ARGI_INTEGER ACPI_TYPE_INTEGER /* 1 */ #define ARGI_STRING ACPI_TYPE_STRING /* 2 */ #define ARGI_BUFFER ACPI_TYPE_BUFFER /* 3 */ #define ARGI_PACKAGE ACPI_TYPE_PACKAGE /* 4 */ @@ -237,8 +237,8 @@ #define ARGI_ANYOBJECT 0x11 #define ARGI_ANYTYPE 0x12 #define ARGI_COMPUTEDATA 0x13 /* Buffer, String, or Integer */ -#define ARGI_DATAOBJECT 0x14 /* Buffer, string, package or reference to a Node - Used only by Size_of operator*/ -#define ARGI_COMPLEXOBJ 0x15 /* Buffer or package */ +#define ARGI_DATAOBJECT 0x14 /* Buffer, String, package or reference to a Node - Used only by Size_of operator*/ +#define ARGI_COMPLEXOBJ 0x15 /* Buffer, String, or package (Used by INDEX op only) */ #define ARGI_INTEGER_REF 0x16 #define ARGI_OBJECT_REF 0x17 #define ARGI_DEVICE_REF 0x18 @@ -312,13 +312,14 @@ typedef enum { - REGION_MEMORY = 0, + REGION_MEMORY = 0, REGION_IO, REGION_PCI_CONFIG, REGION_EC, REGION_SMBUS, REGION_CMOS, - REGION_PCI_BAR + REGION_PCI_BAR, + REGION_FIXED_HW = 0x7F, } AML_REGION_TYPES; @@ -327,80 +328,82 @@ typedef enum { - MATCH_MTR = 0, - MATCH_MEQ = 1, - MATCH_MLE = 2, - MATCH_MLT = 3, - MATCH_MGE = 4, - MATCH_MGT = 5 + MATCH_MTR = 0, + MATCH_MEQ = 1, + MATCH_MLE = 2, + MATCH_MLT = 3, + MATCH_MGE = 4, + MATCH_MGT = 5 } AML_MATCH_OPERATOR; -#define MAX_MATCH_OPERATOR 5 +#define MAX_MATCH_OPERATOR 5 /* Field Access Types */ -#define ACCESS_TYPE_MASK 0x0f -#define ACCESS_TYPE_SHIFT 0 +#define ACCESS_TYPE_MASK 0x0f +#define ACCESS_TYPE_SHIFT 0 typedef enum { - ACCESS_ANY_ACC = 0, - ACCESS_BYTE_ACC = 1, - ACCESS_WORD_ACC = 2, - ACCESS_DWORD_ACC = 3, - ACCESS_BLOCK_ACC = 4, - ACCESS_SMBSEND_RECV_ACC = 5, - ACCESS_SMBQUICK_ACC = 6 + ACCESS_ANY_ACC = 0, + ACCESS_BYTE_ACC = 1, + ACCESS_WORD_ACC = 2, + ACCESS_DWORD_ACC = 3, + ACCESS_QWORD_ACC = 4, /* ACPI 2.0 */ + ACCESS_BLOCK_ACC = 4, + ACCESS_SMBSEND_RECV_ACC = 5, + ACCESS_SMBQUICK_ACC = 6 } AML_ACCESS_TYPE; /* Field Lock Rules */ -#define LOCK_RULE_MASK 0x10 -#define LOCK_RULE_SHIFT 4 +#define LOCK_RULE_MASK 0x10 +#define LOCK_RULE_SHIFT 4 typedef enum { - GLOCK_NEVER_LOCK = 0, - GLOCK_ALWAYS_LOCK = 1 + GLOCK_NEVER_LOCK = 0, + GLOCK_ALWAYS_LOCK = 1 } AML_LOCK_RULE; /* Field Update Rules */ -#define UPDATE_RULE_MASK 0x060 -#define UPDATE_RULE_SHIFT 5 +#define UPDATE_RULE_MASK 0x060 +#define UPDATE_RULE_SHIFT 5 typedef enum { - UPDATE_PRESERVE = 0, - UPDATE_WRITE_AS_ONES = 1, - UPDATE_WRITE_AS_ZEROS = 2 + UPDATE_PRESERVE = 0, + UPDATE_WRITE_AS_ONES = 1, + UPDATE_WRITE_AS_ZEROS = 2 } AML_UPDATE_RULE; /* bit fields in Method_flags byte */ -#define METHOD_FLAGS_ARG_COUNT 0x07 -#define METHOD_FLAGS_SERIALIZED 0x08 +#define METHOD_FLAGS_ARG_COUNT 0x07 +#define METHOD_FLAGS_SERIALIZED 0x08 +#define METHOD_FLAGS_SYNCH_LEVEL 0xF0 /* Array sizes. Used for range checking also */ -#define NUM_REGION_TYPES 7 -#define NUM_ACCESS_TYPES 7 -#define NUM_UPDATE_RULES 3 -#define NUM_MATCH_OPS 7 -#define NUM_OPCODES 256 -#define NUM_FIELD_NAMES 2 +#define NUM_REGION_TYPES 7 +#define NUM_ACCESS_TYPES 7 +#define NUM_UPDATE_RULES 3 +#define NUM_MATCH_OPS 7 +#define NUM_OPCODES 256 +#define NUM_FIELD_NAMES 2 -#define USER_REGION_BEGIN 0x80 +#define USER_REGION_BEGIN 0x80 /* * AML tables @@ -408,7 +411,7 @@ #ifdef DEFINE_AML_GLOBALS -/* External declarations of the AML tables */ +/* External declarations for the AML tables */ extern u8 acpi_gbl_aml [NUM_OPCODES]; extern u16 acpi_gbl_pfx [NUM_OPCODES]; diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/platform/acenv.h linux/drivers/acpi/include/platform/acenv.h --- v2.4.5/linux/drivers/acpi/include/platform/acenv.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/platform/acenv.h Wed Jun 20 17:47:40 2001 @@ -0,0 +1,288 @@ +/****************************************************************************** + * + * Name: acenv.h - Generation environment specific items + * $Revision: 75 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 + */ + +#ifndef __ACENV_H__ +#define __ACENV_H__ + + +/* + * Configuration for ACPI tools and utilities + */ + +#ifdef _ACPI_DUMP_APP +#define ACPI_DEBUG +#define ACPI_APPLICATION +#define ENABLE_DEBUGGER +#define ACPI_USE_SYSTEM_CLIBRARY +#define PARSER_ONLY +#endif + +#ifdef _ACPI_EXEC_APP +#undef DEBUGGER_THREADING +#define DEBUGGER_THREADING DEBUGGER_SINGLE_THREADED +#define ACPI_DEBUG +#define ACPI_APPLICATION +#define ENABLE_DEBUGGER +#define ACPI_USE_SYSTEM_CLIBRARY +#endif + +#ifdef _ACPI_ASL_COMPILER +#define ACPI_DEBUG +#define ACPI_APPLICATION +#define ENABLE_DEBUGGER +#define ACPI_USE_SYSTEM_CLIBRARY +#endif + +/* + * Memory allocation tracking. Used only if + * 1) This is the debug version + * 2) This is NOT a 16-bit version of the code (not enough real-mode memory) + */ +#ifdef ACPI_DEBUG +#ifndef _IA16 +#define ACPI_DEBUG_TRACK_ALLOCATIONS +#endif +#endif + +/* + * Environment configuration. The purpose of this file is to interface to the + * local generation environment. + * + * 1) ACPI_USE_SYSTEM_CLIBRARY - Define this if linking to an actual C library. + * Otherwise, local versions of string/memory functions will be used. + * 2) ACPI_USE_STANDARD_HEADERS - Define this if linking to a C library and + * the standard header files may be used. + * + * The ACPI subsystem only uses low level C library functions that do not call + * operating system services and may therefore be inlined in the code. + * + * It may be necessary to tailor these include files to the target + * generation environment. + * + * + * Functions and constants used from each header: + * + * string.h: memcpy + * memset + * strcat + * strcmp + * strcpy + * strlen + * strncmp + * strncat + * strncpy + * + * stdlib.h: strtoul + * + * stdarg.h: va_list + * va_arg + * va_start + * va_end + * + */ + +/*! [Begin] no source code translation */ + +#ifdef _LINUX +#include "aclinux.h" + +#elif _AED_EFI +#include "acefi.h" + +#elif WIN32 +#include "acwin.h" + +#elif __FreeBSD__ +#include "acfreebsd.h" + +#else + +/* All other environments */ + +#define ACPI_USE_STANDARD_HEADERS + +/* Name of host operating system (returned by the _OS_ namespace object) */ + +#define ACPI_OS_NAME "Intel ACPI/CA Core Subsystem" + +#endif + + +/*! [End] no source code translation !*/ + +/****************************************************************************** + * + * C library configuration + * + *****************************************************************************/ + +#ifdef ACPI_USE_SYSTEM_CLIBRARY +/* + * Use the standard C library headers. + * We want to keep these to a minimum. + * + */ + +#ifdef ACPI_USE_STANDARD_HEADERS +/* + * Use the standard headers from the standard locations + */ +#include +#include +#include +#include + +#endif /* ACPI_USE_STANDARD_HEADERS */ + +/* + * We will be linking to the standard Clib functions + */ + +#define STRSTR(s1,s2) strstr((s1), (s2)) +#define STRUPR(s) acpi_ut_strupr ((s)) +#define STRLEN(s) (u32) strlen((s)) +#define STRCPY(d,s) strcpy((d), (s)) +#define STRNCPY(d,s,n) strncpy((d), (s), (NATIVE_INT)(n)) +#define STRNCMP(d,s,n) strncmp((d), (s), (NATIVE_INT)(n)) +#define STRCMP(d,s) strcmp((d), (s)) +#define STRCAT(d,s) strcat((d), (s)) +#define STRNCAT(d,s,n) strncat((d), (s), (NATIVE_INT)(n)) +#define STRTOUL(d,s,n) strtoul((d), (s), (NATIVE_INT)(n)) +#define MEMCPY(d,s,n) memcpy((d), (s), (NATIVE_INT)(n)) +#define MEMSET(d,s,n) memset((d), (s), (NATIVE_INT)(n)) +#define TOUPPER toupper +#define TOLOWER tolower +#define IS_XDIGIT isxdigit + +/****************************************************************************** + * + * Not using native C library, use local implementations + * + *****************************************************************************/ +#else + +/* + * Use local definitions of C library macros and functions + * NOTE: The function implementations may not be as efficient + * as an inline or assembly code implementation provided by a + * native C library. + */ + +#ifndef va_arg + +#ifndef _VALIST +#define _VALIST +typedef char *va_list; +#endif /* _VALIST */ + +/* + * Storage alignment properties + */ + +#define _AUPBND (sizeof (NATIVE_INT) - 1) +#define _ADNBND (sizeof (NATIVE_INT) - 1) + +/* + * Variable argument list macro definitions + */ + +#define _bnd(X, bnd) (((sizeof (X)) + (bnd)) & (~(bnd))) +#define va_arg(ap, T) (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND)))) +#define va_end(ap) (void) 0 +#define va_start(ap, A) (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND)))) + +#endif /* va_arg */ + + +#define STRSTR(s1,s2) acpi_ut_strstr ((s1), (s2)) +#define STRUPR(s) acpi_ut_strupr ((s)) +#define STRLEN(s) acpi_ut_strlen ((s)) +#define STRCPY(d,s) acpi_ut_strcpy ((d), (s)) +#define STRNCPY(d,s,n) acpi_ut_strncpy ((d), (s), (n)) +#define STRNCMP(d,s,n) acpi_ut_strncmp ((d), (s), (n)) +#define STRCMP(d,s) acpi_ut_strcmp ((d), (s)) +#define STRCAT(d,s) acpi_ut_strcat ((d), (s)) +#define STRNCAT(d,s,n) acpi_ut_strncat ((d), (s), (n)) +#define STRTOUL(d,s,n) acpi_ut_strtoul ((d), (s),(n)) +#define MEMCPY(d,s,n) acpi_ut_memcpy ((d), (s), (n)) +#define MEMSET(d,v,n) acpi_ut_memset ((d), (v), (n)) +#define TOUPPER acpi_ut_to_upper +#define TOLOWER acpi_ut_to_lower + +#endif /* ACPI_USE_SYSTEM_CLIBRARY */ + + +/****************************************************************************** + * + * Assembly code macros + * + *****************************************************************************/ + +/* + * Handle platform- and compiler-specific assembly language differences. + * These should already have been defined by the platform includes above. + * + * Notes: + * 1) Interrupt 3 is used to break into a debugger + * 2) Interrupts are turned off during ACPI register setup + */ + +/* Unrecognized compiler, use defaults */ +#ifndef ACPI_ASM_MACROS + +#define ACPI_ASM_MACROS +#define causeinterrupt(level) +#define BREAKPOINT3 +#define disable() +#define enable() +#define halt() +#define ACPI_ACQUIRE_GLOBAL_LOCK(Glptr, acq) +#define ACPI_RELEASE_GLOBAL_LOCK(Glptr, acq) + +#endif /* ACPI_ASM_MACROS */ + + +#ifdef ACPI_APPLICATION + +/* Don't want software interrupts within a ring3 application */ + +#undef causeinterrupt +#undef BREAKPOINT3 +#define causeinterrupt(level) +#define BREAKPOINT3 +#endif + + +/****************************************************************************** + * + * Compiler-specific + * + *****************************************************************************/ + +/* this has been moved to compiler-specific headers, which are included from the + platform header. */ + + +#endif /* __ACENV_H__ */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/platform/acgcc.h linux/drivers/acpi/include/platform/acgcc.h --- v2.4.5/linux/drivers/acpi/include/platform/acgcc.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/platform/acgcc.h Wed Jun 20 17:47:40 2001 @@ -0,0 +1,147 @@ +/****************************************************************************** + * + * Name: acgcc.h - GCC specific defines, etc. + * $Revision: 6 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 + */ + +#ifndef __ACGCC_H__ +#define __ACGCC_H__ + + +#ifdef __ia64__ +#define _IA64 + +#define COMPILER_DEPENDENT_UINT64 unsigned long +/* Single threaded */ +#define ACPI_APPLICATION + +#define ACPI_ASM_MACROS +#define causeinterrupt(level) +#define BREAKPOINT3 +#define disable() __cli() +#define enable() __sti() +#define wbinvd() + +/*! [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_UINT64 unsigned long long +#define ACPI_ASM_MACROS +#define causeinterrupt(level) +#define BREAKPOINT3 +#define disable() __cli() +#define enable() __sti() +#define halt() __asm__ __volatile__ ("sti; hlt":::"memory") +#define wbinvd() + +/*! [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) + +/*! [End] no source code translation !*/ + +#endif /* IA 32 */ + +#endif /* __ACGCC_H__ */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/include/platform/aclinux.h linux/drivers/acpi/include/platform/aclinux.h --- v2.4.5/linux/drivers/acpi/include/platform/aclinux.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/include/platform/aclinux.h Wed Jun 20 17:47:40 2001 @@ -0,0 +1,71 @@ +/****************************************************************************** + * + * Name: aclinux.h - OS specific defines, etc. + * $Revision: 13 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 + */ + +#ifndef __ACLINUX_H__ +#define __ACLINUX_H__ + +#define ACPI_OS_NAME "Linux" + +#define ACPI_USE_SYSTEM_CLIBRARY + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include +#include +#include + +#define strtoul simple_strtoul + +#else + +#include +#include +#include +#include + +#endif + +/* Linux uses GCC */ + +#include "acgcc.h" + +#undef DEBUGGER_THREADING +#define DEBUGGER_THREADING DEBUGGER_SINGLE_THREADED + +#ifndef _IA64 +/* Linux ia32 can't do int64 well */ +#define ACPI_NO_INTEGER64_SUPPORT +/* And the ia32 kernel doesn't include 64-bit divide support */ +#define ACPI_DIV64(dividend, divisor) do_div(dividend, divisor) +#else +#define ACPI_DIV64(dividend, divisor) ACPI_DIVIDE(dividend, divisor) +#endif + + +#endif /* __ACLINUX_H__ */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/interpreter/Makefile linux/drivers/acpi/interpreter/Makefile --- v2.4.5/linux/drivers/acpi/interpreter/Makefile Fri Dec 29 14:07:21 2000 +++ linux/drivers/acpi/interpreter/Makefile Wed Dec 31 16:00:00 1969 @@ -1,16 +0,0 @@ -# -# Makefile for all Linux ACPI interpreter subdirectories -# - -O_TARGET := ../$(shell basename `pwd`).o - -obj-$(CONFIG_ACPI) := $(patsubst %.c,%.o,$(wildcard *.c)) - -EXTRA_CFLAGS += -I../include - -EXTRA_CFLAGS += $(ACPI_CFLAGS) - -include $(TOPDIR)/Rules.make - -clean: - $(RM) *.o diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/interpreter/amconfig.c linux/drivers/acpi/interpreter/amconfig.c --- v2.4.5/linux/drivers/acpi/interpreter/amconfig.c Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/interpreter/amconfig.c Wed Dec 31 16:00:00 1969 @@ -1,306 +0,0 @@ -/****************************************************************************** - * - * Module Name: amconfig - Namespace reconfiguration (Load/Unload opcodes) - * $Revision: 29 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "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 INTERPRETER - MODULE_NAME ("amconfig") - - -/***************************************************************************** - * - * FUNCTION: Acpi_aml_exec_load_table - * - * PARAMETERS: Rgn_desc - Op region where the table will be obtained - * Ddb_handle - Where a handle to the table will be returned - * - * RETURN: Status - * - * DESCRIPTION: Load an ACPI table - * - ****************************************************************************/ - -static ACPI_STATUS -acpi_aml_exec_load_table ( - ACPI_OPERAND_OBJECT *rgn_desc, - ACPI_HANDLE *ddb_handle) -{ - ACPI_STATUS status; - ACPI_OPERAND_OBJECT *table_desc = NULL; - u8 *table_ptr; - u8 *table_data_ptr; - ACPI_TABLE_HEADER table_header; - ACPI_TABLE_DESC table_info; - u32 i; - - - /* TBD: [Unhandled] Object can be either a field or an opregion */ - - - /* Get the table header */ - - table_header.length = 0; - for (i = 0; i < sizeof (ACPI_TABLE_HEADER); i++) { - status = acpi_ev_address_space_dispatch (rgn_desc, ADDRESS_SPACE_READ, - (ACPI_PHYSICAL_ADDRESS) i, 8, - (u32 *) ((u8 *) &table_header + i)); - if (ACPI_FAILURE (status)) { - return (status); - } - } - - /* Allocate a buffer for the entire table */ - - table_ptr = acpi_cm_allocate (table_header.length); - if (!table_ptr) { - return (AE_NO_MEMORY); - } - - /* Copy the header to the buffer */ - - MEMCPY (table_ptr, &table_header, sizeof (ACPI_TABLE_HEADER)); - table_data_ptr = table_ptr + sizeof (ACPI_TABLE_HEADER); - - - /* Get the table from the op region */ - - for (i = 0; i < table_header.length; i++) { - status = acpi_ev_address_space_dispatch (rgn_desc, ADDRESS_SPACE_READ, - (ACPI_PHYSICAL_ADDRESS)i, 8, - (u32 *) (table_data_ptr + i)); - if (ACPI_FAILURE (status)) { - goto cleanup; - } - } - - - /* Table must be either an SSDT or a PSDT */ - - if ((!STRNCMP (table_header.signature, - acpi_gbl_acpi_table_data[ACPI_TABLE_PSDT].signature, - acpi_gbl_acpi_table_data[ACPI_TABLE_PSDT].sig_length)) && - (!STRNCMP (table_header.signature, - acpi_gbl_acpi_table_data[ACPI_TABLE_SSDT].signature, - acpi_gbl_acpi_table_data[ACPI_TABLE_SSDT].sig_length))) - { - status = AE_BAD_SIGNATURE; - goto cleanup; - } - - /* Create an object to be the table handle */ - - table_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_REFERENCE); - if (!table_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - - /* Install the new table into the local data structures */ - - table_info.pointer = (ACPI_TABLE_HEADER *) table_ptr; - table_info.length = table_header.length; - table_info.allocation = ACPI_MEM_ALLOCATED; - table_info.base_pointer = table_ptr; - - status = acpi_tb_install_table (NULL, &table_info); - if (ACPI_FAILURE (status)) { - goto cleanup; - } - - /* Add the table to the namespace */ - - /* TBD: [Restructure] - change to whatever new interface is appropriate */ -/* - Status = Acpi_load_namespace (); - if (ACPI_FAILURE (Status)) { -*/ - /* TBD: [Errors] Unload the table on failure ? */ -/* - goto Cleanup; - } -*/ - - - /* TBD: [Investigate] we need a pointer to the table desc */ - - /* Init the table handle */ - - table_desc->reference.op_code = AML_LOAD_OP; - table_desc->reference.object = table_info.installed_desc; - - *ddb_handle = table_desc; - - return (status); - - -cleanup: - - acpi_cm_free (table_desc); - acpi_cm_free (table_ptr); - return (status); - -} - - -/***************************************************************************** - * - * FUNCTION: Acpi_aml_exec_unload_table - * - * PARAMETERS: Ddb_handle - Handle to a previously loaded table - * - * RETURN: Status - * - * DESCRIPTION: Unload an ACPI table - * - ****************************************************************************/ - -static ACPI_STATUS -acpi_aml_exec_unload_table ( - ACPI_HANDLE ddb_handle) -{ - ACPI_STATUS status = AE_NOT_IMPLEMENTED; - ACPI_OPERAND_OBJECT *table_desc = (ACPI_OPERAND_OBJECT *) ddb_handle; - ACPI_TABLE_DESC *table_info; - - - /* Validate the handle */ - /* Although the handle is partially validated in Acpi_aml_exec_reconfiguration(), - * when it calls Acpi_aml_resolve_operands(), the handle is more completely - * validated here. - */ - - if ((!ddb_handle) || - (!VALID_DESCRIPTOR_TYPE (ddb_handle, ACPI_DESC_TYPE_INTERNAL)) || - (((ACPI_OPERAND_OBJECT *)ddb_handle)->common.type != - INTERNAL_TYPE_REFERENCE)) - { - return (AE_BAD_PARAMETER); - } - - - /* Get the actual table descriptor from the Ddb_handle */ - - table_info = (ACPI_TABLE_DESC *) table_desc->reference.object; - - /* - * 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 (status); - } - - /* Delete the table itself */ - - acpi_tb_uninstall_table (table_info->installed_desc); - - /* Delete the table descriptor (Ddb_handle) */ - - acpi_cm_remove_reference (table_desc); - - return (status); -} - - -/***************************************************************************** - * - * FUNCTION: Acpi_aml_exec_reconfiguration - * - * PARAMETERS: Opcode - The opcode to be executed - * Walk_state - Current state of the parse tree walk - * - * RETURN: Status - * - * DESCRIPTION: Reconfiguration opcodes such as LOAD and UNLOAD - * - ****************************************************************************/ - -ACPI_STATUS -acpi_aml_exec_reconfiguration ( - u16 opcode, - ACPI_WALK_STATE *walk_state) -{ - ACPI_STATUS status; - ACPI_OPERAND_OBJECT *region_desc = NULL; - ACPI_HANDLE *ddb_handle; - - - /* Resolve the operands */ - - status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS, walk_state); - /* Get the table handle, common for both opcodes */ - - status |= acpi_ds_obj_stack_pop_object ((ACPI_OPERAND_OBJECT **) &ddb_handle, - walk_state); - - switch (opcode) - { - - case AML_LOAD_OP: - - /* Get the region or field descriptor */ - - status |= acpi_ds_obj_stack_pop_object (®ion_desc, walk_state); - if (ACPI_FAILURE (status)) { - acpi_cm_remove_reference (region_desc); - return (status); - } - - status = acpi_aml_exec_load_table (region_desc, ddb_handle); - break; - - - case AML_UNLOAD_OP: - - if (ACPI_FAILURE (status)) { - return (status); - } - - status = acpi_aml_exec_unload_table (ddb_handle); - break; - - - default: - - status = AE_AML_BAD_OPCODE; - break; - } - - - return (status); -} - diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/interpreter/amconvrt.c linux/drivers/acpi/interpreter/amconvrt.c --- v2.4.5/linux/drivers/acpi/interpreter/amconvrt.c Mon Jan 29 10:15:59 2001 +++ linux/drivers/acpi/interpreter/amconvrt.c Wed Dec 31 16:00:00 1969 @@ -1,525 +0,0 @@ -/****************************************************************************** - * - * Module Name: amconvrt - Object conversion routines - * $Revision: 3 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "acpi.h" -#include "acparser.h" -#include "acnamesp.h" -#include "acinterp.h" -#include "acevents.h" -#include "amlcode.h" -#include "acdispat.h" - - -#define _COMPONENT INTERPRETER - MODULE_NAME ("amconvrt") - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_convert_to_target_type - * - * PARAMETERS: *Obj_desc - Object to be converted. - * Walk_state - Current method state - * - * RETURN: Status - * - * DESCRIPTION: - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_convert_to_target_type ( - OBJECT_TYPE_INTERNAL destination_type, - ACPI_OPERAND_OBJECT **obj_desc, - ACPI_WALK_STATE *walk_state) -{ - ACPI_STATUS status = AE_OK; - - - /* - * If required by the target, - * perform implicit conversion on the source before we store it. - */ - - switch (GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args)) - { - case ARGI_SIMPLE_TARGET: - case ARGI_FIXED_TARGET: - case ARGI_INTEGER_REF: /* Handles Increment, Decrement cases */ - - switch (destination_type) - { - case INTERNAL_TYPE_DEF_FIELD: - /* - * Named field can always handle conversions - */ - break; - - default: - /* No conversion allowed for these types */ - - if (destination_type != (*obj_desc)->common.type) { - status = AE_TYPE; - } - } - break; - - - case ARGI_TARGETREF: - - switch (destination_type) - { - case ACPI_TYPE_INTEGER: - case ACPI_TYPE_FIELD_UNIT: - case INTERNAL_TYPE_BANK_FIELD: - case INTERNAL_TYPE_INDEX_FIELD: - /* - * These types require an Integer operand. We can convert - * a Buffer or a String to an Integer if necessary. - */ - status = acpi_aml_convert_to_integer (obj_desc, walk_state); - break; - - - case ACPI_TYPE_STRING: - - /* - * The operand must be a String. We can convert an - * Integer or Buffer if necessary - */ - status = acpi_aml_convert_to_string (obj_desc, walk_state); - break; - - - case ACPI_TYPE_BUFFER: - - /* - * The operand must be a String. We can convert an - * Integer or Buffer if necessary - */ - status = acpi_aml_convert_to_buffer (obj_desc, walk_state); - break; - } - break; - - - case ARGI_REFERENCE: - /* - * Create_xxxx_field cases - we are storing the field object into the name - */ - break; - - - default: - status = AE_AML_INTERNAL; - } - - - /* - * Source-to-Target conversion semantics: - * - * If conversion to the target type cannot be performed, then simply - * overwrite the target with the new object and type. - */ - if (status == AE_TYPE) { - status = AE_OK; - } - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_convert_to_integer - * - * PARAMETERS: *Obj_desc - Object to be converted. Must be an - * Integer, Buffer, or String - * Walk_state - Current method state - * - * RETURN: Status - * - * DESCRIPTION: Convert an ACPI Object to an integer. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_convert_to_integer ( - ACPI_OPERAND_OBJECT **obj_desc, - ACPI_WALK_STATE *walk_state) -{ - u32 i; - ACPI_OPERAND_OBJECT *ret_desc; - u32 count; - char *pointer; - ACPI_INTEGER result; - u32 integer_size = sizeof (ACPI_INTEGER); - - - switch ((*obj_desc)->common.type) - { - case ACPI_TYPE_INTEGER: - return (AE_OK); - - case ACPI_TYPE_STRING: - pointer = (*obj_desc)->string.pointer; - count = (*obj_desc)->string.length; - break; - - case ACPI_TYPE_BUFFER: - pointer = (char *) (*obj_desc)->buffer.pointer; - count = (*obj_desc)->buffer.length; - break; - - default: - return (AE_TYPE); - } - - /* - * Create a new integer - */ - ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER); - if (!ret_desc) { - return (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. - * - * There are two terminating conditions for the loop: - * 1) The size of an integer has been reached, or - * 2) The end of the buffer or string has been reached - */ - result = 0; - - /* Transfer no more than an integer's worth of data */ - - if (count > integer_size) { - count = integer_size; - } - - /* - * String conversion is different than Buffer conversion - */ - switch ((*obj_desc)->common.type) - { - case ACPI_TYPE_STRING: - - /* TBD: Need to use 64-bit STRTOUL */ - - /* - * Convert string to an integer - * String must be hexadecimal as per the ACPI specification - */ - - result = STRTOUL (pointer, NULL, 16); - break; - - - case ACPI_TYPE_BUFFER: - - /* - * Buffer conversion - we simply grab enough raw data from the - * buffer to fill an integer - */ - for (i = 0; i < count; i++) { - /* - * Get next byte and shift it into the Result. - * Little endian is used, meaning that the first byte of the buffer - * is the LSB of the integer - */ - result |= (((ACPI_INTEGER) pointer[i]) << (i * 8)); - } - - break; - } - - /* Save the Result, delete original descriptor, store new descriptor */ - - ret_desc->integer.value = result; - - if (walk_state->opcode != AML_STORE_OP) { - acpi_cm_remove_reference (*obj_desc); - } - - *obj_desc = ret_desc; - - return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_convert_to_buffer - * - * PARAMETERS: *Obj_desc - Object to be converted. Must be an - * Integer, Buffer, or String - * Walk_state - Current method state - * - * RETURN: Status - * - * DESCRIPTION: Convert an ACPI Object to an Buffer - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_convert_to_buffer ( - ACPI_OPERAND_OBJECT **obj_desc, - ACPI_WALK_STATE *walk_state) -{ - ACPI_OPERAND_OBJECT *ret_desc; - u32 i; - u32 integer_size = sizeof (ACPI_INTEGER); - u8 *new_buf; - - - switch ((*obj_desc)->common.type) - { - case ACPI_TYPE_INTEGER: - - /* - * Create a new Buffer - */ - ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_BUFFER); - if (!ret_desc) { - return (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); - } - - /* Need enough space for one integers */ - - ret_desc->buffer.length = integer_size; - new_buf = acpi_cm_callocate (integer_size); - if (!new_buf) { - REPORT_ERROR - (("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n")); - acpi_cm_remove_reference (ret_desc); - return (AE_NO_MEMORY); - } - - /* Copy the integer to the buffer */ - - for (i = 0; i < integer_size; i++) { - new_buf[i] = (u8) ((*obj_desc)->integer.value >> (i * 8)); - } - ret_desc->buffer.pointer = new_buf; - - /* Return the new buffer descriptor */ - - if (walk_state->opcode != AML_STORE_OP) { - acpi_cm_remove_reference (*obj_desc); - } - *obj_desc = ret_desc; - break; - - - case ACPI_TYPE_STRING: - break; - - - case ACPI_TYPE_BUFFER: - break; - - - default: - return (AE_TYPE); - break; - } - - return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_convert_to_string - * - * PARAMETERS: *Obj_desc - Object to be converted. Must be an - * Integer, Buffer, or String - * Walk_state - Current method state - * - * RETURN: Status - * - * DESCRIPTION: Convert an ACPI Object to a string - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_convert_to_string ( - ACPI_OPERAND_OBJECT **obj_desc, - ACPI_WALK_STATE *walk_state) -{ - ACPI_OPERAND_OBJECT *ret_desc; - u32 i; - u32 index; - u32 integer_size = sizeof (ACPI_INTEGER); - u8 *new_buf; - u8 *pointer; - - - switch ((*obj_desc)->common.type) - { - case ACPI_TYPE_INTEGER: - - /* - * Create a new String - */ - ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_STRING); - if (!ret_desc) { - return (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); - } - - /* Need enough space for one ASCII integer plus null terminator */ - - ret_desc->string.length = (integer_size * 2) + 1; - new_buf = acpi_cm_callocate (ret_desc->string.length); - if (!new_buf) { - REPORT_ERROR - (("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n")); - acpi_cm_remove_reference (ret_desc); - return (AE_NO_MEMORY); - } - - /* Copy the integer to the buffer */ - - for (i = 0; i < (integer_size * 2); i++) { - new_buf[i] = acpi_gbl_hex_to_ascii [((*obj_desc)->integer.value >> (i * 4)) & 0xF]; - } - - /* Null terminate */ - - new_buf [i] = 0; - ret_desc->buffer.pointer = new_buf; - - /* Return the new buffer descriptor */ - - if (walk_state->opcode != AML_STORE_OP) { - acpi_cm_remove_reference (*obj_desc); - } - *obj_desc = ret_desc; - - return (AE_OK); - - - case ACPI_TYPE_BUFFER: - - if (((*obj_desc)->buffer.length * 3) > ACPI_MAX_STRING_CONVERSION) { - return (AE_AML_STRING_LIMIT); - } - - /* - * Create a new String - */ - ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_STRING); - if (!ret_desc) { - return (AE_NO_MEMORY); - } - - /* Need enough space for one ASCII integer plus null terminator */ - - ret_desc->string.length = (*obj_desc)->buffer.length * 3; - new_buf = acpi_cm_callocate (ret_desc->string.length + 1); - if (!new_buf) { - REPORT_ERROR - (("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n")); - acpi_cm_remove_reference (ret_desc); - return (AE_NO_MEMORY); - } - - /* - * Convert each byte of the buffer to two ASCII characters plus a space. - */ - pointer = (*obj_desc)->buffer.pointer; - index = 0; - for (i = 0; i < (*obj_desc)->buffer.length; i++) { - new_buf[index + 0] = acpi_gbl_hex_to_ascii [pointer[i] & 0x0F]; - new_buf[index + 1] = acpi_gbl_hex_to_ascii [(pointer[i] >> 4) & 0x0F]; - new_buf[index + 2] = ' '; - index += 3; - } - - /* Null terminate */ - - new_buf [index] = 0; - ret_desc->buffer.pointer = new_buf; - - /* Return the new buffer descriptor */ - - if (walk_state->opcode != AML_STORE_OP) { - acpi_cm_remove_reference (*obj_desc); - } - *obj_desc = ret_desc; - break; - - - case ACPI_TYPE_STRING: - break; - - - default: - return (AE_TYPE); - break; - } - - return (AE_OK); -} - - diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/interpreter/amcreate.c linux/drivers/acpi/interpreter/amcreate.c --- v2.4.5/linux/drivers/acpi/interpreter/amcreate.c Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/interpreter/amcreate.c Wed Dec 31 16:00:00 1969 @@ -1,722 +0,0 @@ -/****************************************************************************** - * - * Module Name: amcreate - Named object creation - * $Revision: 53 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "acpi.h" -#include "acparser.h" -#include "acinterp.h" -#include "amlcode.h" -#include "acnamesp.h" -#include "acevents.h" -#include "acdispat.h" - - -#define _COMPONENT INTERPRETER - MODULE_NAME ("amcreate") - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_exec_create_field - * - * PARAMETERS: Opcode - The opcode to be executed - * Operands - List of operands for the opcode - * - * RETURN: Status - * - * DESCRIPTION: Execute Create_field operators: Create_bit_field_op, - * Create_byte_field_op, Create_word_field_op, Create_dWord_field_op, - * Create_field_op (which define fields in buffers) - * - * ALLOCATION: Deletes Create_field_op's count operand descriptor - * - * - * ACPI SPECIFICATION REFERENCES: - * Def_create_bit_field := Create_bit_field_op Src_buf Bit_idx Name_string - * Def_create_byte_field := Create_byte_field_op Src_buf Byte_idx Name_string - * Def_create_dWord_field := Create_dWord_field_op Src_buf Byte_idx Name_string - * Def_create_field := Create_field_op Src_buf Bit_idx Num_bits Name_string - * Def_create_word_field := Create_word_field_op Src_buf Byte_idx Name_string - * Bit_index := Term_arg=>Integer - * Byte_index := Term_arg=>Integer - * Num_bits := Term_arg=>Integer - * Source_buff := Term_arg=>Buffer - * - ******************************************************************************/ - - -ACPI_STATUS -acpi_aml_exec_create_field ( - u8 *aml_ptr, - u32 aml_length, - ACPI_NAMESPACE_NODE *node, - ACPI_WALK_STATE *walk_state) -{ - ACPI_STATUS status; - ACPI_OPERAND_OBJECT *obj_desc; - ACPI_OPERAND_OBJECT *tmp_desc; - - - /* Create the region descriptor */ - - obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_FIELD_UNIT); - if (!obj_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* Construct the field object */ - - obj_desc->field_unit.access = (u8) ACCESS_ANY_ACC; - obj_desc->field_unit.lock_rule = (u8) GLOCK_NEVER_LOCK; - obj_desc->field_unit.update_rule = (u8) UPDATE_PRESERVE; - - /* - * Allocate a method object for this field unit - */ - - obj_desc->field_unit.extra = acpi_cm_create_internal_object ( - INTERNAL_TYPE_EXTRA); - if (!obj_desc->field_unit.extra) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* - * Remember location in AML stream of the field unit - * opcode and operands -- since the buffer and index - * operands must be evaluated. - */ - - obj_desc->field_unit.extra->extra.pcode = aml_ptr; - obj_desc->field_unit.extra->extra.pcode_length = aml_length; - obj_desc->field_unit.node = node; - - - /* - * This operation is supposed to cause the destination Name to refer - * to the defined Field_unit -- it must not store the constructed - * Field_unit object (or its current value) in some location that the - * Name may already be pointing to. So, if the Name currently contains - * a reference which would cause Acpi_aml_exec_store() to perform an indirect - * store rather than setting the value of the Name itself, clobber that - * reference before calling Acpi_aml_exec_store(). - */ - - /* Type of Name's existing value */ - - switch (acpi_ns_get_type (node)) - { - - case ACPI_TYPE_FIELD_UNIT: - - case INTERNAL_TYPE_ALIAS: - case INTERNAL_TYPE_BANK_FIELD: - case INTERNAL_TYPE_DEF_FIELD: - case INTERNAL_TYPE_INDEX_FIELD: - - tmp_desc = acpi_ns_get_attached_object (node); - if (tmp_desc) { - /* - * There is an existing object here; delete it and zero out the - * object field within the Node - */ - - acpi_cm_remove_reference (tmp_desc); - acpi_ns_attach_object ((ACPI_NAMESPACE_NODE *) node, NULL, - ACPI_TYPE_ANY); - } - - /* Set the type to ANY (or the store below will fail) */ - - ((ACPI_NAMESPACE_NODE *) node)->type = ACPI_TYPE_ANY; - - break; - - - default: - - break; - } - - - /* Store constructed field descriptor in result location */ - - status = acpi_aml_exec_store (obj_desc, (ACPI_OPERAND_OBJECT *) node, walk_state); - - /* - * If the field descriptor was not physically stored (or if a failure - * above), we must delete it - */ - if (obj_desc->common.reference_count <= 1) { - acpi_cm_remove_reference (obj_desc); - } - - - return (AE_OK); - - -cleanup: - - /* Delete region object and method subobject */ - - if (obj_desc) { - /* Remove deletes both objects! */ - - acpi_cm_remove_reference (obj_desc); - obj_desc = NULL; - } - - return (status); -} - - -/***************************************************************************** - * - * FUNCTION: Acpi_aml_exec_create_alias - * - * PARAMETERS: Operands - List of operands for the opcode - * - * RETURN: Status - * - * DESCRIPTION: Create a new named alias - * - ****************************************************************************/ - -ACPI_STATUS -acpi_aml_exec_create_alias ( - ACPI_WALK_STATE *walk_state) -{ - ACPI_NAMESPACE_NODE *source_node; - ACPI_NAMESPACE_NODE *alias_node; - ACPI_STATUS status; - - - /* Get the source/alias operands (both NTEs) */ - - status = acpi_ds_obj_stack_pop_object ((ACPI_OPERAND_OBJECT **) &source_node, - walk_state); - if (ACPI_FAILURE (status)) { - return (status); - } - - /* - * Don't pop it, it gets removed in the calling routine - */ - - alias_node = acpi_ds_obj_stack_get_value (0, walk_state); - - /* Add an additional reference to the object */ - - acpi_cm_add_reference (source_node->object); - - /* - * Attach the original source Node to the new Alias Node. - */ - status = acpi_ns_attach_object (alias_node, source_node->object, - source_node->type); - - - /* - * The new alias assumes the type of the source, but it points - * to the same object. The reference count of the object has two - * additional references to prevent deletion out from under either the - * source or the alias Node - */ - - /* Since both operands are NTEs, we don't need to delete them */ - - return (status); -} - - -/***************************************************************************** - * - * FUNCTION: Acpi_aml_exec_create_event - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Create a new event object - * - ****************************************************************************/ - -ACPI_STATUS -acpi_aml_exec_create_event ( - ACPI_WALK_STATE *walk_state) -{ - ACPI_STATUS status; - ACPI_OPERAND_OBJECT *obj_desc; - - - BREAKPOINT3; - - obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_EVENT); - if (!obj_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* Create the actual OS semaphore */ - - /* TBD: [Investigate] should be created with 0 or 1 units? */ - - status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT, 1, - &obj_desc->event.semaphore); - if (ACPI_FAILURE (status)) { - acpi_cm_remove_reference (obj_desc); - goto cleanup; - } - - /* Attach object to the Node */ - - status = acpi_ns_attach_object (acpi_ds_obj_stack_get_value (0, walk_state), - obj_desc, (u8) ACPI_TYPE_EVENT); - if (ACPI_FAILURE (status)) { - acpi_os_delete_semaphore (obj_desc->event.semaphore); - acpi_cm_remove_reference (obj_desc); - goto cleanup; - } - - -cleanup: - - return (status); -} - - -/***************************************************************************** - * - * FUNCTION: Acpi_aml_exec_create_mutex - * - * PARAMETERS: Interpreter_mode - Current running mode (load1/Load2/Exec) - * Operands - List of operands for the opcode - * - * RETURN: Status - * - * DESCRIPTION: Create a new mutex object - * - ****************************************************************************/ - -ACPI_STATUS -acpi_aml_exec_create_mutex ( - ACPI_WALK_STATE *walk_state) -{ - ACPI_STATUS status = AE_OK; - ACPI_OPERAND_OBJECT *sync_desc; - ACPI_OPERAND_OBJECT *obj_desc; - - - /* Get the operand */ - - status = acpi_ds_obj_stack_pop_object (&sync_desc, walk_state); - if (ACPI_FAILURE (status)) { - return (status); - } - - /* Attempt to allocate a new object */ - - obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_MUTEX); - if (!obj_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* Create the actual OS semaphore */ - - status = acpi_os_create_semaphore (1, 1, &obj_desc->mutex.semaphore); - if (ACPI_FAILURE (status)) { - acpi_cm_remove_reference (obj_desc); - goto cleanup; - } - - obj_desc->mutex.sync_level = (u8) sync_desc->integer.value; - - /* Obj_desc was on the stack top, and the name is below it */ - - status = acpi_ns_attach_object (acpi_ds_obj_stack_get_value (0, walk_state), - obj_desc, (u8) ACPI_TYPE_MUTEX); - if (ACPI_FAILURE (status)) { - acpi_os_delete_semaphore (obj_desc->mutex.semaphore); - acpi_cm_remove_reference (obj_desc); - goto cleanup; - } - - -cleanup: - - /* Always delete the operand */ - - acpi_cm_remove_reference (sync_desc); - - return (status); -} - - -/***************************************************************************** - * - * FUNCTION: Acpi_aml_exec_create_region - * - * PARAMETERS: Aml_ptr - Pointer to the region declaration AML - * Aml_length - Max length of the declaration AML - * Operands - List of operands for the opcode - * Interpreter_mode - Load1/Load2/Execute - * - * RETURN: Status - * - * DESCRIPTION: Create a new operation region object - * - ****************************************************************************/ - -ACPI_STATUS -acpi_aml_exec_create_region ( - u8 *aml_ptr, - u32 aml_length, - u8 region_space, - ACPI_WALK_STATE *walk_state) -{ - ACPI_STATUS status; - ACPI_OPERAND_OBJECT *obj_desc; - ACPI_NAMESPACE_NODE *node; - - - /* - * Space ID must be one of the predefined IDs, or in the user-defined - * range - */ - if ((region_space >= NUM_REGION_TYPES) && - (region_space < USER_REGION_BEGIN)) - { - REPORT_ERROR (("Invalid Address_space type %X\n", region_space)); - return (AE_AML_INVALID_SPACE_ID); - } - - - /* Get the Node from the object stack */ - - node = (ACPI_NAMESPACE_NODE *) acpi_ds_obj_stack_get_value (0, walk_state); - - /* Create the region descriptor */ - - obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_REGION); - if (!obj_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* - * Allocate a method object for this region. - */ - - obj_desc->region.extra = acpi_cm_create_internal_object ( - INTERNAL_TYPE_EXTRA); - if (!obj_desc->region.extra) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* - * Remember location in AML stream of address & length - * operands since they need to be evaluated at run time. - */ - - obj_desc->region.extra->extra.pcode = aml_ptr; - obj_desc->region.extra->extra.pcode_length = aml_length; - - /* Init the region from the operands */ - - obj_desc->region.space_id = region_space; - obj_desc->region.address = 0; - obj_desc->region.length = 0; - - - /* Install the new region object in the parent Node */ - - obj_desc->region.node = node; - - status = acpi_ns_attach_object (node, obj_desc, - (u8) ACPI_TYPE_REGION); - - if (ACPI_FAILURE (status)) { - goto cleanup; - } - - /* - * If we have a valid region, initialize it - * Namespace is NOT locked at this point. - */ - - status = acpi_ev_initialize_region (obj_desc, FALSE); - - if (ACPI_FAILURE (status)) { - /* - * If AE_NOT_EXIST is returned, it is not fatal - * because many regions get created before a handler - * is installed for said region. - */ - if (AE_NOT_EXIST == status) { - status = AE_OK; - } - } - -cleanup: - - if (ACPI_FAILURE (status)) { - /* Delete region object and method subobject */ - - if (obj_desc) { - /* Remove deletes both objects! */ - - acpi_cm_remove_reference (obj_desc); - obj_desc = NULL; - } - } - - return (status); -} - - -/***************************************************************************** - * - * FUNCTION: Acpi_aml_exec_create_processor - * - * PARAMETERS: Op - Op containing the Processor definition and - * args - * Processor_nTE - Node for the containing Node - * - * RETURN: Status - * - * DESCRIPTION: Create a new processor object and populate the fields - * - ****************************************************************************/ - -ACPI_STATUS -acpi_aml_exec_create_processor ( - ACPI_PARSE_OBJECT *op, - ACPI_HANDLE processor_nTE) -{ - ACPI_STATUS status; - ACPI_PARSE_OBJECT *arg; - ACPI_OPERAND_OBJECT *obj_desc; - - - obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_PROCESSOR); - if (!obj_desc) { - status = AE_NO_MEMORY; - return (status); - } - - /* Install the new processor object in the parent Node */ - - status = acpi_ns_attach_object (processor_nTE, obj_desc, - (u8) ACPI_TYPE_PROCESSOR); - if (ACPI_FAILURE (status)) { - return(status); - } - - arg = op->value.arg; - - /* check existence */ - - if (!arg) { - status = AE_AML_NO_OPERAND; - return (status); - } - - /* First arg is the Processor ID */ - - obj_desc->processor.proc_id = (u8) arg->value.integer; - - /* Move to next arg and check existence */ - - arg = arg->next; - if (!arg) { - status = AE_AML_NO_OPERAND; - return (status); - } - - /* Second arg is the PBlock Address */ - - obj_desc->processor.address = (ACPI_IO_ADDRESS) arg->value.integer; - - /* Move to next arg and check existence */ - - arg = arg->next; - if (!arg) { - status = AE_AML_NO_OPERAND; - return (status); - } - - /* Third arg is the PBlock Length */ - - obj_desc->processor.length = (u8) arg->value.integer; - - return (AE_OK); -} - - -/***************************************************************************** - * - * FUNCTION: Acpi_aml_exec_create_power_resource - * - * PARAMETERS: Op - Op containing the Power_resource definition - * and args - * Power_res_nTE - Node for the containing Node - * - * RETURN: Status - * - * DESCRIPTION: Create a new Power_resource object and populate the fields - * - ****************************************************************************/ - -ACPI_STATUS -acpi_aml_exec_create_power_resource ( - ACPI_PARSE_OBJECT *op, - ACPI_HANDLE power_res_nTE) -{ - ACPI_STATUS status; - ACPI_PARSE_OBJECT *arg; - ACPI_OPERAND_OBJECT *obj_desc; - - - obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_POWER); - if (!obj_desc) { - status = AE_NO_MEMORY; - return (status); - } - - /* Install the new power resource object in the parent Node */ - - status = acpi_ns_attach_object (power_res_nTE, obj_desc, - (u8) ACPI_TYPE_POWER); - if (ACPI_FAILURE (status)) { - return(status); - } - - arg = op->value.arg; - - /* check existence */ - - if (!arg) { - status = AE_AML_NO_OPERAND; - return (status); - } - - /* First arg is the System_level */ - - obj_desc->power_resource.system_level = (u8) arg->value.integer; - - /* Move to next arg and check existence */ - - arg = arg->next; - if (!arg) { - status = AE_AML_NO_OPERAND; - return (status); - } - - /* Second arg is the PBlock Address */ - - obj_desc->power_resource.resource_order = (u16) arg->value.integer; - - return (AE_OK); -} - - -/***************************************************************************** - * - * FUNCTION: Acpi_aml_exec_create_method - * - * PARAMETERS: Aml_ptr - First byte of the method's AML - * Aml_length - AML byte count for this method - * Method_flags - AML method flag byte - * Method - Method Node - * - * RETURN: Status - * - * DESCRIPTION: Create a new method object - * - ****************************************************************************/ - -ACPI_STATUS -acpi_aml_exec_create_method ( - u8 *aml_ptr, - u32 aml_length, - u32 method_flags, - ACPI_HANDLE method) -{ - ACPI_OPERAND_OBJECT *obj_desc; - ACPI_STATUS status; - - - /* Create a new method object */ - - obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_METHOD); - if (!obj_desc) { - return (AE_NO_MEMORY); - } - - /* Get the method's AML pointer/length from the Op */ - - obj_desc->method.pcode = aml_ptr; - obj_desc->method.pcode_length = aml_length; - - /* - * First argument is the Method Flags (contains parameter count for the - * method) - */ - - obj_desc->method.method_flags = (u8) method_flags; - obj_desc->method.param_count = (u8) (method_flags & - METHOD_FLAGS_ARG_COUNT); - - /* - * Get the concurrency count. If required, a semaphore will be - * created for this method when it is parsed. - * - * TBD: [Future] for APCI 2.0, there will be a Sync_level value, not - * just a flag - * Concurrency = Sync_level + 1;. - */ - - if (method_flags & METHOD_FLAGS_SERIALIZED) { - obj_desc->method.concurrency = 1; - } - - else { - obj_desc->method.concurrency = INFINITE_CONCURRENCY; - } - - /* Attach the new object to the method Node */ - - status = acpi_ns_attach_object (method, obj_desc, (u8) ACPI_TYPE_METHOD); - if (ACPI_FAILURE (status)) { - acpi_cm_delete_object_desc (obj_desc); - } - - return (status); -} - - diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/interpreter/amdyadic.c linux/drivers/acpi/interpreter/amdyadic.c --- v2.4.5/linux/drivers/acpi/interpreter/amdyadic.c Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/interpreter/amdyadic.c Wed Dec 31 16:00:00 1969 @@ -1,882 +0,0 @@ -/****************************************************************************** - * - * Module Name: amdyadic - ACPI AML (p-code) execution for dyadic operators - * $Revision: 71 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "acpi.h" -#include "acparser.h" -#include "acnamesp.h" -#include "acinterp.h" -#include "acevents.h" -#include "amlcode.h" -#include "acdispat.h" - - -#define _COMPONENT INTERPRETER - MODULE_NAME ("amdyadic") - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_do_concatenate - * - * PARAMETERS: *Obj_desc - Object to be converted. Must be an - * Integer, Buffer, or String - * - * RETURN: Status - * - * DESCRIPTION: Concatenate two objects OF THE SAME TYPE. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_do_concatenate ( - ACPI_OPERAND_OBJECT *obj_desc, - ACPI_OPERAND_OBJECT *obj_desc2, - ACPI_OPERAND_OBJECT **actual_ret_desc, - ACPI_WALK_STATE *walk_state) -{ - ACPI_STATUS status; - u32 i; - ACPI_INTEGER this_integer; - ACPI_OPERAND_OBJECT *ret_desc; - NATIVE_CHAR *new_buf; - u32 integer_size = sizeof (ACPI_INTEGER); - - - /* - * There are three cases to handle: - * 1) Two Integers concatenated to produce a buffer - * 2) Two Strings concatenated to produce a string - * 3) Two Buffers concatenated to produce a buffer - */ - 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. - * 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 */ - - ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_BUFFER); - if (!ret_desc) { - return (AE_NO_MEMORY); - } - - /* Need enough space for two integers */ - - ret_desc->buffer.length = integer_size * 2; - new_buf = acpi_cm_callocate (ret_desc->buffer.length); - if (!new_buf) { - REPORT_ERROR - (("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n")); - status = AE_NO_MEMORY; - goto cleanup; - } - - ret_desc->buffer.pointer = (u8 *) new_buf; - - /* Convert the first integer */ - - this_integer = obj_desc->integer.value; - for (i = 0; i < integer_size; i++) { - new_buf[i] = (u8) 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; - this_integer >>= 8; - } - - break; - - - case ACPI_TYPE_STRING: - - ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_STRING); - if (!ret_desc) { - return (AE_NO_MEMORY); - } - - /* Operand1 is string */ - - new_buf = acpi_cm_allocate (obj_desc->string.length + - obj_desc2->string.length + 1); - if (!new_buf) { - REPORT_ERROR - (("Aml_exec_dyadic2_r/Concat_op: String allocation failure\n")); - status = AE_NO_MEMORY; - goto cleanup; - } - - STRCPY (new_buf, obj_desc->string.pointer); - STRCPY (new_buf + obj_desc->string.length, - obj_desc2->string.pointer); - - /* Point the return object to the new string */ - - ret_desc->string.pointer = new_buf; - ret_desc->string.length = obj_desc->string.length += - obj_desc2->string.length; - break; - - - case ACPI_TYPE_BUFFER: - - /* Operand1 is a buffer */ - - ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_BUFFER); - if (!ret_desc) { - return (AE_NO_MEMORY); - } - - new_buf = acpi_cm_allocate (obj_desc->buffer.length + - obj_desc2->buffer.length); - if (!new_buf) { - REPORT_ERROR - (("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n")); - status = AE_NO_MEMORY; - goto cleanup; - } - - MEMCPY (new_buf, obj_desc->buffer.pointer, - obj_desc->buffer.length); - MEMCPY (new_buf + obj_desc->buffer.length, obj_desc2->buffer.pointer, - obj_desc2->buffer.length); - - /* - * Point the return object to the new buffer - */ - - ret_desc->buffer.pointer = (u8 *) new_buf; - ret_desc->buffer.length = obj_desc->buffer.length + - obj_desc2->buffer.length; - break; - - default: - status = AE_AML_INTERNAL; - ret_desc = NULL; - } - - - *actual_ret_desc = ret_desc; - return (AE_OK); - - -cleanup: - - acpi_cm_remove_reference (ret_desc); - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_exec_dyadic1 - * - * PARAMETERS: Opcode - The opcode to be executed - * - * RETURN: Status - * - * DESCRIPTION: Execute Type 1 dyadic operator with numeric operands: - * Notify_op - * - * ALLOCATION: Deletes both operands - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_exec_dyadic1 ( - u16 opcode, - ACPI_WALK_STATE *walk_state) -{ - ACPI_OPERAND_OBJECT *obj_desc = NULL; - ACPI_OPERAND_OBJECT *val_desc = NULL; - ACPI_NAMESPACE_NODE *node; - ACPI_STATUS status = AE_OK; - - - /* Resolve all operands */ - - status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS, walk_state); - /* Get the operands */ - - status |= acpi_ds_obj_stack_pop_object (&val_desc, walk_state); - status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); - if (ACPI_FAILURE (status)) { - /* Invalid parameters on object stack */ - - goto cleanup; - } - - - /* Examine the opcode */ - - switch (opcode) - { - - /* Def_notify := Notify_op Notify_object Notify_value */ - - case AML_NOTIFY_OP: - - /* The Obj_desc is actually an Node */ - - node = (ACPI_NAMESPACE_NODE *) obj_desc; - obj_desc = NULL; - - /* Object must be a device or thermal zone */ - - if (node && val_desc) { - switch (node->type) - { - case ACPI_TYPE_DEVICE: - case ACPI_TYPE_THERMAL: - - /* - * Requires that Device and Thermal_zone be compatible - * mappings - */ - - /* Dispatch the notify to the appropriate handler */ - - acpi_ev_notify_dispatch (node, (u32) val_desc->integer.value); - break; - - default: - status = AE_AML_OPERAND_TYPE; - } - } - break; - - default: - - REPORT_ERROR (("Acpi_aml_exec_dyadic1: Unknown dyadic opcode %X\n", - opcode)); - status = AE_AML_BAD_OPCODE; - } - - -cleanup: - - /* Always delete both operands */ - - acpi_cm_remove_reference (val_desc); - acpi_cm_remove_reference (obj_desc); - - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_exec_dyadic2_r - * - * PARAMETERS: Opcode - The opcode to be executed - * - * RETURN: Status - * - * DESCRIPTION: Execute Type 2 dyadic operator with numeric operands and - * one or two result operands. - * - * ALLOCATION: Deletes one operand descriptor -- other remains on stack - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_exec_dyadic2_r ( - u16 opcode, - ACPI_WALK_STATE *walk_state, - ACPI_OPERAND_OBJECT **return_desc) -{ - ACPI_OPERAND_OBJECT *obj_desc = NULL; - ACPI_OPERAND_OBJECT *obj_desc2 = NULL; - ACPI_OPERAND_OBJECT *res_desc = NULL; - ACPI_OPERAND_OBJECT *res_desc2 = NULL; - ACPI_OPERAND_OBJECT *ret_desc = NULL; - ACPI_OPERAND_OBJECT *ret_desc2 = NULL; - ACPI_STATUS status = AE_OK; - u32 num_operands = 3; - - - /* Resolve all operands */ - - status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS, walk_state); - /* Get all operands */ - - if (AML_DIVIDE_OP == opcode) { - num_operands = 4; - status |= acpi_ds_obj_stack_pop_object (&res_desc2, walk_state); - } - - status |= acpi_ds_obj_stack_pop_object (&res_desc, walk_state); - status |= acpi_ds_obj_stack_pop_object (&obj_desc2, walk_state); - status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); - if (ACPI_FAILURE (status)) { - goto cleanup; - } - - - /* Create an internal return object if necessary */ - - switch (opcode) - { - case AML_ADD_OP: - case AML_BIT_AND_OP: - case AML_BIT_NAND_OP: - case AML_BIT_OR_OP: - case AML_BIT_NOR_OP: - case AML_BIT_XOR_OP: - case AML_DIVIDE_OP: - case AML_MULTIPLY_OP: - case AML_SHIFT_LEFT_OP: - case AML_SHIFT_RIGHT_OP: - case AML_SUBTRACT_OP: - - ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER); - if (!ret_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - break; - } - - - /* - * Execute the opcode - */ - - switch (opcode) - { - - /* Def_add := Add_op Operand1 Operand2 Result */ - - case AML_ADD_OP: - - ret_desc->integer.value = obj_desc->integer.value + - obj_desc2->integer.value; - break; - - - /* Def_and := And_op Operand1 Operand2 Result */ - - case AML_BIT_AND_OP: - - ret_desc->integer.value = obj_desc->integer.value & - obj_desc2->integer.value; - break; - - - /* Def_nAnd := NAnd_op Operand1 Operand2 Result */ - - case AML_BIT_NAND_OP: - - ret_desc->integer.value = ~(obj_desc->integer.value & - obj_desc2->integer.value); - break; - - - /* Def_or := Or_op Operand1 Operand2 Result */ - - case AML_BIT_OR_OP: - - ret_desc->integer.value = obj_desc->integer.value | - obj_desc2->integer.value; - break; - - - /* Def_nOr := NOr_op Operand1 Operand2 Result */ - - case AML_BIT_NOR_OP: - - ret_desc->integer.value = ~(obj_desc->integer.value | - obj_desc2->integer.value); - break; - - - /* Def_xOr := XOr_op Operand1 Operand2 Result */ - - case AML_BIT_XOR_OP: - - ret_desc->integer.value = obj_desc->integer.value ^ - obj_desc2->integer.value; - break; - - - /* Def_divide := Divide_op Dividend Divisor Remainder Quotient */ - - case AML_DIVIDE_OP: - - if (!obj_desc2->integer.value) { - REPORT_ERROR - (("Aml_exec_dyadic2_r/Divide_op: Divide by zero\n")); - - status = AE_AML_DIVIDE_BY_ZERO; - goto cleanup; - } - - ret_desc2 = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER); - if (!ret_desc2) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* Remainder (modulo) */ - - ret_desc->integer.value = ACPI_MODULO (obj_desc->integer.value, - obj_desc2->integer.value); - - /* Result (what we used to call the quotient) */ - - ret_desc2->integer.value = ACPI_DIVIDE (obj_desc->integer.value, - obj_desc2->integer.value); - break; - - - /* Def_multiply := Multiply_op Operand1 Operand2 Result */ - - case AML_MULTIPLY_OP: - - ret_desc->integer.value = obj_desc->integer.value * - obj_desc2->integer.value; - break; - - - /* Def_shift_left := Shift_left_op Operand Shift_count Result */ - - case AML_SHIFT_LEFT_OP: - - ret_desc->integer.value = obj_desc->integer.value << - obj_desc2->integer.value; - break; - - - /* Def_shift_right := Shift_right_op Operand Shift_count Result */ - - case AML_SHIFT_RIGHT_OP: - - ret_desc->integer.value = obj_desc->integer.value >> - obj_desc2->integer.value; - break; - - - /* Def_subtract := Subtract_op Operand1 Operand2 Result */ - - case AML_SUBTRACT_OP: - - ret_desc->integer.value = obj_desc->integer.value - - obj_desc2->integer.value; - break; - - - /* Def_concat := Concat_op Data1 Data2 Result */ - - case AML_CONCAT_OP: - - - /* - * Convert the second operand if necessary. The first operand - * determines the type of the second operand, (See the Data Types - * section of the ACPI specification.) Both object types are - * guaranteed to be either Integer/String/Buffer by the operand - * resolution mechanism above. - */ - - switch (obj_desc->common.type) - { - case ACPI_TYPE_INTEGER: - status = acpi_aml_convert_to_integer (&obj_desc2, walk_state); - break; - - case ACPI_TYPE_STRING: - status = acpi_aml_convert_to_string (&obj_desc2, walk_state); - break; - - case ACPI_TYPE_BUFFER: - status = acpi_aml_convert_to_buffer (&obj_desc2, walk_state); - break; - - default: - status = AE_AML_INTERNAL; - } - - if (ACPI_FAILURE (status)) { - goto cleanup; - } - - - /* - * Both operands are now known to be the same object type - * (Both are Integer, String, or Buffer), and we can now perform the - * concatenation. - */ - status = acpi_aml_do_concatenate (obj_desc, obj_desc2, &ret_desc, walk_state); - if (ACPI_FAILURE (status)) { - goto cleanup; - } - break; - - - default: - - REPORT_ERROR (("Acpi_aml_exec_dyadic2_r: Unknown dyadic opcode %X\n", - opcode)); - status = AE_AML_BAD_OPCODE; - goto cleanup; - } - - - /* - * Store the result of the operation (which is now in Obj_desc) into - * the result descriptor, or the location pointed to by the result - * descriptor (Res_desc). - */ - - status = acpi_aml_exec_store (ret_desc, res_desc, walk_state); - if (ACPI_FAILURE (status)) { - goto cleanup; - } - - if (AML_DIVIDE_OP == opcode) { - status = acpi_aml_exec_store (ret_desc2, res_desc2, walk_state); - - /* - * Since the remainder is not returned, remove a reference to - * the object we created earlier - */ - - acpi_cm_remove_reference (ret_desc2); - } - - -cleanup: - - /* Always delete the operands */ - - acpi_cm_remove_reference (obj_desc); - acpi_cm_remove_reference (obj_desc2); - - - /* Delete return object on error */ - - if (ACPI_FAILURE (status)) { - /* On failure, delete the result ops */ - - acpi_cm_remove_reference (res_desc); - acpi_cm_remove_reference (res_desc2); - - if (ret_desc) { - /* And delete the internal return object */ - - acpi_cm_remove_reference (ret_desc); - ret_desc = NULL; - } - } - - /* Set the return object and exit */ - - *return_desc = ret_desc; - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_exec_dyadic2_s - * - * PARAMETERS: Opcode - The opcode to be executed - * - * RETURN: Status - * - * DESCRIPTION: Execute Type 2 dyadic synchronization operator - * - * ALLOCATION: Deletes one operand descriptor -- other remains on stack - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_exec_dyadic2_s ( - u16 opcode, - ACPI_WALK_STATE *walk_state, - ACPI_OPERAND_OBJECT **return_desc) -{ - ACPI_OPERAND_OBJECT *obj_desc; - ACPI_OPERAND_OBJECT *time_desc; - ACPI_OPERAND_OBJECT *ret_desc = NULL; - ACPI_STATUS status; - - - /* Resolve all operands */ - - status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS, walk_state); - /* Get all operands */ - - status |= acpi_ds_obj_stack_pop_object (&time_desc, walk_state); - status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); - if (ACPI_FAILURE (status)) { - /* Invalid parameters on object stack */ - - goto cleanup; - } - - - /* Create the internal return object */ - - ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER); - if (!ret_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* Default return value is FALSE, operation did not time out */ - - ret_desc->integer.value = 0; - - - /* Examine the opcode */ - - switch (opcode) - { - - /* Def_acquire := Acquire_op Mutex_object Timeout */ - - case AML_ACQUIRE_OP: - - status = acpi_aml_system_acquire_mutex (time_desc, obj_desc); - break; - - - /* Def_wait := Wait_op Acpi_event_object Timeout */ - - case AML_WAIT_OP: - - status = acpi_aml_system_wait_event (time_desc, obj_desc); - break; - - - default: - - REPORT_ERROR (("Acpi_aml_exec_dyadic2_s: Unknown dyadic synchronization opcode %X\n", opcode)); - status = AE_AML_BAD_OPCODE; - goto cleanup; - } - - - /* - * Return a boolean indicating if operation timed out - * (TRUE) or not (FALSE) - */ - - if (status == AE_TIME) { - ret_desc->integer.value = ACPI_INTEGER_MAX; /* TRUE, op timed out */ - status = AE_OK; - } - - -cleanup: - - /* Delete params */ - - acpi_cm_remove_reference (time_desc); - acpi_cm_remove_reference (obj_desc); - - /* Delete return object on error */ - - if (ACPI_FAILURE (status) && - (ret_desc)) - { - acpi_cm_remove_reference (ret_desc); - ret_desc = NULL; - } - - - /* Set the return object and exit */ - - *return_desc = ret_desc; - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_exec_dyadic2 - * - * PARAMETERS: Opcode - The opcode to be executed - * - * RETURN: Status - * - * DESCRIPTION: Execute Type 2 dyadic operator with numeric operands and - * no result operands - * - * ALLOCATION: Deletes one operand descriptor -- other remains on stack - * containing result value - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_exec_dyadic2 ( - u16 opcode, - ACPI_WALK_STATE *walk_state, - ACPI_OPERAND_OBJECT **return_desc) -{ - ACPI_OPERAND_OBJECT *obj_desc; - ACPI_OPERAND_OBJECT *obj_desc2; - ACPI_OPERAND_OBJECT *ret_desc = NULL; - ACPI_STATUS status; - u8 lboolean; - - - /* Resolve all operands */ - - status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS, walk_state); - /* Get all operands */ - - status |= acpi_ds_obj_stack_pop_object (&obj_desc2, walk_state); - status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); - if (ACPI_FAILURE (status)) { - /* Invalid parameters on object stack */ - - goto cleanup; - } - - - /* Create the internal return object */ - - ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER); - if (!ret_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* - * Execute the Opcode - */ - - lboolean = FALSE; - switch (opcode) - { - - /* Def_lAnd := LAnd_op Operand1 Operand2 */ - - case AML_LAND_OP: - - lboolean = (u8) (obj_desc->integer.value && - obj_desc2->integer.value); - break; - - - /* Def_lEqual := LEqual_op Operand1 Operand2 */ - - case AML_LEQUAL_OP: - - lboolean = (u8) (obj_desc->integer.value == - obj_desc2->integer.value); - break; - - - /* Def_lGreater := LGreater_op Operand1 Operand2 */ - - case AML_LGREATER_OP: - - lboolean = (u8) (obj_desc->integer.value > - obj_desc2->integer.value); - break; - - - /* Def_lLess := LLess_op Operand1 Operand2 */ - - case AML_LLESS_OP: - - lboolean = (u8) (obj_desc->integer.value < - obj_desc2->integer.value); - break; - - - /* Def_lOr := LOr_op Operand1 Operand2 */ - - case AML_LOR_OP: - - lboolean = (u8) (obj_desc->integer.value || - obj_desc2->integer.value); - break; - - - default: - - REPORT_ERROR (("Acpi_aml_exec_dyadic2: Unknown dyadic opcode %X\n", opcode)); - status = AE_AML_BAD_OPCODE; - goto cleanup; - break; - } - - - /* Set return value to logical TRUE (all ones) or FALSE (zero) */ - - if (lboolean) { - ret_desc->integer.value = ACPI_INTEGER_MAX; - } - else { - ret_desc->integer.value = 0; - } - - -cleanup: - - /* Always delete operands */ - - acpi_cm_remove_reference (obj_desc); - acpi_cm_remove_reference (obj_desc2); - - - /* Delete return object on error */ - - if (ACPI_FAILURE (status) && - (ret_desc)) - { - acpi_cm_remove_reference (ret_desc); - ret_desc = NULL; - } - - - /* Set the return object and exit */ - - *return_desc = ret_desc; - return (status); -} - - diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/interpreter/amfield.c linux/drivers/acpi/interpreter/amfield.c --- v2.4.5/linux/drivers/acpi/interpreter/amfield.c Mon Jan 29 10:15:59 2001 +++ linux/drivers/acpi/interpreter/amfield.c Wed Dec 31 16:00:00 1969 @@ -1,283 +0,0 @@ -/****************************************************************************** - * - * Module Name: amfield - ACPI AML (p-code) execution - field manipulation - * $Revision: 77 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "acpi.h" -#include "acdispat.h" -#include "acinterp.h" -#include "amlcode.h" -#include "acnamesp.h" -#include "achware.h" -#include "acevents.h" - - -#define _COMPONENT INTERPRETER - MODULE_NAME ("amfield") - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_setup_field - * - * PARAMETERS: *Obj_desc - Field to be read or written - * *Rgn_desc - Region containing field - * Field_bit_width - Field Width in bits (8, 16, or 32) - * - * RETURN: Status - * - * DESCRIPTION: Common processing for Acpi_aml_read_field and Acpi_aml_write_field - * - * ACPI SPECIFICATION REFERENCES: - * Each of the Type1_opcodes is defined as specified in in-line - * comments below. For each one, use the following definitions. - * - * Def_bit_field := Bit_field_op Src_buf Bit_idx Destination - * Def_byte_field := Byte_field_op Src_buf Byte_idx Destination - * Def_create_field := Create_field_op Src_buf Bit_idx Num_bits Name_string - * Def_dWord_field := DWord_field_op Src_buf Byte_idx Destination - * Def_word_field := Word_field_op Src_buf Byte_idx Destination - * Bit_index := Term_arg=>Integer - * Byte_index := Term_arg=>Integer - * Destination := Name_string - * Num_bits := Term_arg=>Integer - * Source_buf := Term_arg=>Buffer - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_setup_field ( - ACPI_OPERAND_OBJECT *obj_desc, - ACPI_OPERAND_OBJECT *rgn_desc, - u32 field_bit_width) -{ - ACPI_STATUS status = AE_OK; - u32 field_byte_width; - - - /* Parameter validation */ - - if (!obj_desc || !rgn_desc) { - return (AE_AML_NO_OPERAND); - } - - if (ACPI_TYPE_REGION != rgn_desc->common.type) { - return (AE_AML_OPERAND_TYPE); - } - - - /* - * TBD: [Future] Acpi 2.0 supports Qword fields - * - * Init and validate Field width - * Possible values are 1, 2, 4 - */ - - field_byte_width = DIV_8 (field_bit_width); - - if ((field_bit_width != 8) && - (field_bit_width != 16) && - (field_bit_width != 32)) - { - return (AE_AML_OPERAND_VALUE); - } - - - /* - * If the Region Address and Length have not been previously evaluated, - * evaluate them and save the results. - */ - if (!(rgn_desc->region.flags & AOPOBJ_DATA_VALID)) { - - status = acpi_ds_get_region_arguments (rgn_desc); - if (ACPI_FAILURE (status)) { - return (status); - } - } - - - if ((obj_desc->common.type == ACPI_TYPE_FIELD_UNIT) && - (!(obj_desc->common.flags & AOPOBJ_DATA_VALID))) - { - /* - * Field Buffer and Index have not been previously evaluated, - */ - return (AE_AML_INTERNAL); - } - - if (rgn_desc->region.length < - (obj_desc->field.offset & ~((u32) field_byte_width - 1)) + - field_byte_width) - { - /* - * Offset rounded up to next multiple of field width - * exceeds region length, indicate an error - */ - - return (AE_AML_REGION_LIMIT); - } - - return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_access_named_field - * - * PARAMETERS: Mode - ACPI_READ or ACPI_WRITE - * Named_field - Handle for field to be accessed - * *Buffer - Value(s) to be read or written - * Buffer_length - Number of bytes to transfer - * - * RETURN: Status - * - * DESCRIPTION: Read or write a named field - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_access_named_field ( - u32 mode, - ACPI_HANDLE named_field, - void *buffer, - u32 buffer_length) -{ - ACPI_OPERAND_OBJECT *obj_desc = NULL; - ACPI_STATUS status = AE_OK; - u8 locked = FALSE; - u32 bit_granularity = 0; - u32 byte_granularity; - u32 datum_length; - u32 actual_byte_length; - u32 byte_field_length; - - - /* Parameter validation */ - - if ((!named_field) || (ACPI_READ == mode && !buffer)) { - return (AE_AML_INTERNAL); - } - - /* Get the attached field object */ - - obj_desc = acpi_ns_get_attached_object (named_field); - if (!obj_desc) { - return (AE_AML_INTERNAL); - } - - /* Check the type */ - - if (INTERNAL_TYPE_DEF_FIELD != acpi_ns_get_type (named_field)) { - return (AE_AML_OPERAND_TYPE); - } - - /* Obj_desc valid and Named_field is a defined field */ - - - /* Double-check that the attached object is also a field */ - - if (INTERNAL_TYPE_DEF_FIELD != obj_desc->common.type) { - return (AE_AML_OPERAND_TYPE); - } - - - /* - * Granularity was decoded from the field access type - * (Any_acc will be the same as Byte_acc) - */ - - bit_granularity = obj_desc->field_unit.granularity; - byte_granularity = DIV_8 (bit_granularity); - - /* - * Check if request is too large for the field, and silently truncate - * if necessary - */ - - /* TBD: [Errors] should an error be returned in this case? */ - - byte_field_length = (u32) DIV_8 (obj_desc->field_unit.length + 7); - - - actual_byte_length = buffer_length; - if (buffer_length > byte_field_length) { - actual_byte_length = byte_field_length; - } - - /* TBD: should these round down to a power of 2? */ - - if (DIV_8 (bit_granularity) > byte_field_length) { - bit_granularity = MUL_8(byte_field_length); - } - - if (byte_granularity > byte_field_length) { - byte_granularity = byte_field_length; - } - - - /* Convert byte count to datum count, round up if necessary */ - - datum_length = (actual_byte_length + (byte_granularity-1)) / byte_granularity; - - - /* Get the global lock if needed */ - - locked = acpi_aml_acquire_global_lock (obj_desc->field_unit.lock_rule); - - - /* Perform the actual read or write of the buffer */ - - switch (mode) - { - case ACPI_READ: - - status = acpi_aml_read_field (obj_desc, buffer, buffer_length, - actual_byte_length, datum_length, - bit_granularity, byte_granularity); - break; - - - case ACPI_WRITE: - - status = acpi_aml_write_field (obj_desc, buffer, buffer_length, - actual_byte_length, datum_length, - bit_granularity, byte_granularity); - break; - - - default: - - status = AE_BAD_PARAMETER; - break; - } - - - /* Release global lock if we acquired it earlier */ - - acpi_aml_release_global_lock (locked); - - return (status); -} - diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/interpreter/amfldio.c linux/drivers/acpi/interpreter/amfldio.c --- v2.4.5/linux/drivers/acpi/interpreter/amfldio.c Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/interpreter/amfldio.c Wed Dec 31 16:00:00 1969 @@ -1,685 +0,0 @@ -/****************************************************************************** - * - * Module Name: amfldio - Aml Field I/O - * $Revision: 39 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "acpi.h" -#include "acinterp.h" -#include "amlcode.h" -#include "acnamesp.h" -#include "achware.h" -#include "acevents.h" - - -#define _COMPONENT INTERPRETER - MODULE_NAME ("amfldio") - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_read_field_data - * - * PARAMETERS: *Obj_desc - Field to be read - * *Value - Where to store value - * Field_bit_width - Field Width in bits (8, 16, or 32) - * - * RETURN: Status - * - * DESCRIPTION: Retrieve the value of the given field - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_read_field_data ( - ACPI_OPERAND_OBJECT *obj_desc, - u32 field_byte_offset, - u32 field_bit_width, - u32 *value) -{ - ACPI_STATUS status; - ACPI_OPERAND_OBJECT *rgn_desc = NULL; - ACPI_PHYSICAL_ADDRESS address; - u32 local_value = 0; - u32 field_byte_width; - - - /* Obj_desc is validated by callers */ - - if (obj_desc) { - rgn_desc = obj_desc->field.container; - } - - - field_byte_width = DIV_8 (field_bit_width); - status = acpi_aml_setup_field (obj_desc, rgn_desc, field_bit_width); - if (ACPI_FAILURE (status)) { - return (status); - } - - /* Setup_field validated Rgn_desc and Field_bit_width */ - - if (!value) { - value = &local_value; /* support reads without saving value */ - } - - - /* - * Set offset to next multiple of field width, - * add region base address and offset within the field - */ - address = rgn_desc->region.address + - (obj_desc->field.offset * field_byte_width) + - field_byte_offset; - - - /* Invoke the appropriate Address_space/Op_region handler */ - - status = acpi_ev_address_space_dispatch (rgn_desc, ADDRESS_SPACE_READ, - address, field_bit_width, value); - - - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_read_field - * - * PARAMETERS: *Obj_desc - Field to be read - * *Value - Where to store value - * Field_bit_width - Field Width in bits (8, 16, or 32) - * - * RETURN: Status - * - * DESCRIPTION: Retrieve the value of the given field - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_read_field ( - ACPI_OPERAND_OBJECT *obj_desc, - void *buffer, - u32 buffer_length, - u32 byte_length, - u32 datum_length, - u32 bit_granularity, - u32 byte_granularity) -{ - ACPI_STATUS status; - u32 this_field_byte_offset; - u32 this_field_datum_offset; - u32 previous_raw_datum; - u32 this_raw_datum = 0; - u32 valid_field_bits; - u32 mask; - u32 merged_datum = 0; - - - /* - * Clear the caller's buffer (the whole buffer length as given) - * This is very important, especially in the cases where a byte is read, - * but the buffer is really a u32 (4 bytes). - */ - - MEMSET (buffer, 0, buffer_length); - - /* Read the first raw datum to prime the loop */ - - this_field_byte_offset = 0; - this_field_datum_offset= 0; - - status = acpi_aml_read_field_data (obj_desc, this_field_byte_offset, bit_granularity, - &previous_raw_datum); - if (ACPI_FAILURE (status)) { - goto cleanup; - } - - /* We might actually be done if the request fits in one datum */ - - if ((datum_length == 1) && - ((obj_desc->field.bit_offset + obj_desc->field_unit.length) <= - (u16) bit_granularity)) - { - merged_datum = previous_raw_datum; - - merged_datum = (merged_datum >> obj_desc->field.bit_offset); - - valid_field_bits = obj_desc->field_unit.length % bit_granularity; - if (valid_field_bits) { - mask = (((u32) 1 << valid_field_bits) - (u32) 1); - merged_datum &= mask; - } - - - /* - * Place the Merged_datum into the proper format and return buffer - * field - */ - - switch (byte_granularity) - { - case 1: - ((u8 *) buffer) [this_field_datum_offset] = (u8) merged_datum; - break; - - case 2: - MOVE_UNALIGNED16_TO_16 (&(((u16 *) buffer)[this_field_datum_offset]), &merged_datum); - break; - - case 4: - MOVE_UNALIGNED32_TO_32 (&(((u32 *) buffer)[this_field_datum_offset]), &merged_datum); - break; - } - - this_field_byte_offset = 1; - this_field_datum_offset = 1; - } - - else { - /* We need to get more raw data to complete one or more field data */ - - while (this_field_datum_offset < datum_length) { - /* - * If the field is aligned on a byte boundary, we don't want - * to perform a final read, since this would potentially read - * past the end of the region. - * - * TBD: [Investigate] It may make more sense to just split the aligned - * and non-aligned cases since the aligned case is so very simple, - */ - if ((obj_desc->field.bit_offset != 0) || - ((obj_desc->field.bit_offset == 0) && - (this_field_datum_offset < (datum_length -1)))) - { - /* - * Get the next raw datum, it contains some or all bits - * of the current field datum - */ - - status = acpi_aml_read_field_data (obj_desc, - this_field_byte_offset + byte_granularity, - bit_granularity, &this_raw_datum); - if (ACPI_FAILURE (status)) { - goto cleanup; - } - - /* Before merging the data, make sure the unused bits are clear */ - - switch (byte_granularity) - { - case 1: - this_raw_datum &= 0x000000FF; - previous_raw_datum &= 0x000000FF; - break; - - case 2: - this_raw_datum &= 0x0000FFFF; - previous_raw_datum &= 0x0000FFFF; - break; - } - } - - - /* - * Put together bits of the two raw data to make a complete - * field datum - */ - - - if (obj_desc->field.bit_offset != 0) { - merged_datum = - (previous_raw_datum >> obj_desc->field.bit_offset) | - (this_raw_datum << (bit_granularity - obj_desc->field.bit_offset)); - } - - else { - merged_datum = previous_raw_datum; - } - - /* - * Prepare the merged datum for storing into the caller's - * buffer. It is possible to have a 32-bit buffer - * (Byte_granularity == 4), but a Obj_desc->Field.Length - * of 8 or 16, meaning that the upper bytes of merged data - * are undesired. This section fixes that. - */ - switch (obj_desc->field.length) - { - case 8: - merged_datum &= 0x000000FF; - break; - - case 16: - merged_datum &= 0x0000FFFF; - break; - } - - /* - * Now store the datum in the caller's buffer, according to - * the data type - */ - switch (byte_granularity) - { - case 1: - ((u8 *) buffer) [this_field_datum_offset] = (u8) merged_datum; - break; - - case 2: - MOVE_UNALIGNED16_TO_16 (&(((u16 *) buffer) [this_field_datum_offset]), &merged_datum); - break; - - case 4: - MOVE_UNALIGNED32_TO_32 (&(((u32 *) buffer) [this_field_datum_offset]), &merged_datum); - break; - } - - /* - * Save the most recent datum since it contains bits of - * the *next* field datum - */ - - previous_raw_datum = this_raw_datum; - - this_field_byte_offset += byte_granularity; - this_field_datum_offset++; - - } /* while */ - } - -cleanup: - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_write_field_data - * - * PARAMETERS: *Obj_desc - Field to be set - * Value - Value to store - * Field_bit_width - Field Width in bits (8, 16, or 32) - * - * RETURN: Status - * - * DESCRIPTION: Store the value into the given field - * - ******************************************************************************/ - -static ACPI_STATUS -acpi_aml_write_field_data ( - ACPI_OPERAND_OBJECT *obj_desc, - u32 field_byte_offset, - u32 field_bit_width, - u32 value) -{ - ACPI_STATUS status = AE_OK; - ACPI_OPERAND_OBJECT *rgn_desc = NULL; - ACPI_PHYSICAL_ADDRESS address; - u32 field_byte_width; - - - /* Obj_desc is validated by callers */ - - if (obj_desc) { - rgn_desc = obj_desc->field.container; - } - - field_byte_width = DIV_8 (field_bit_width); - status = acpi_aml_setup_field (obj_desc, rgn_desc, field_bit_width); - if (ACPI_FAILURE (status)) { - return (status); - } - - - /* - * Set offset to next multiple of field width, - * add region base address and offset within the field - */ - address = rgn_desc->region.address + - (obj_desc->field.offset * field_byte_width) + - field_byte_offset; - - /* Invoke the appropriate Address_space/Op_region handler */ - - status = acpi_ev_address_space_dispatch (rgn_desc, ADDRESS_SPACE_WRITE, - address, field_bit_width, &value); - - - - return (status); -} - - -/***************************************************************************** - * - * FUNCTION: Acpi_aml_write_field_data_with_update_rule - * - * PARAMETERS: *Obj_desc - Field to be set - * Value - Value to store - * Field_bit_width - Field Width in bits (8, 16, or 32) - * - * RETURN: Status - * - * DESCRIPTION: Apply the field update rule to a field write - * - ****************************************************************************/ - -static ACPI_STATUS -acpi_aml_write_field_data_with_update_rule ( - ACPI_OPERAND_OBJECT *obj_desc, - u32 mask, - u32 field_value, - u32 this_field_byte_offset, - u32 bit_granularity) -{ - ACPI_STATUS status = AE_OK; - u32 merged_value; - u32 current_value; - - - /* Start with the new bits */ - - merged_value = field_value; - - - /* Decode the update rule */ - - switch (obj_desc->field.update_rule) - { - - case UPDATE_PRESERVE: - - /* Check if update rule needs to be applied (not if mask is all ones) */ - - /* The left shift drops the bits we want to ignore. */ - if ((~mask << (sizeof(mask)*8 - bit_granularity)) != 0) { - /* - * Read the current contents of the byte/word/dword containing - * the field, and merge with the new field value. - */ - status = acpi_aml_read_field_data (obj_desc, this_field_byte_offset, - bit_granularity, ¤t_value); - merged_value |= (current_value & ~mask); - } - break; - - - case UPDATE_WRITE_AS_ONES: - - /* Set positions outside the field to all ones */ - - merged_value |= ~mask; - break; - - - case UPDATE_WRITE_AS_ZEROS: - - /* Set positions outside the field to all zeros */ - - merged_value &= mask; - break; - - - default: - status = AE_AML_OPERAND_VALUE; - } - - - /* Write the merged value */ - - if (ACPI_SUCCESS (status)) { - status = acpi_aml_write_field_data (obj_desc, this_field_byte_offset, - bit_granularity, merged_value); - } - - return (status); -} - - -/***************************************************************************** - * - * FUNCTION: Acpi_aml_write_field - * - * PARAMETERS: *Obj_desc - Field to be set - * Value - Value to store - * Field_bit_width - Field Width in bits (8, 16, or 32) - * - * RETURN: Status - * - * DESCRIPTION: Store the value into the given field - * - ****************************************************************************/ - -ACPI_STATUS -acpi_aml_write_field ( - ACPI_OPERAND_OBJECT *obj_desc, - void *buffer, - u32 buffer_length, - u32 byte_length, - u32 datum_length, - u32 bit_granularity, - u32 byte_granularity) -{ - ACPI_STATUS status; - u32 this_field_byte_offset; - u32 this_field_datum_offset; - u32 mask; - u32 merged_datum; - u32 previous_raw_datum; - u32 this_raw_datum; - u32 field_value; - u32 valid_field_bits; - - - /* - * Break the request into up to three parts: - * non-aligned part at start, aligned part in middle, non-aligned part - * at end --- Just like an I/O request --- - */ - - this_field_byte_offset = 0; - this_field_datum_offset= 0; - - /* Get a datum */ - - switch (byte_granularity) - { - case 1: - previous_raw_datum = ((u8 *) buffer) [this_field_datum_offset]; - break; - - case 2: - MOVE_UNALIGNED16_TO_32 (&previous_raw_datum, &(((u16 *) buffer) [this_field_datum_offset])); - break; - - case 4: - MOVE_UNALIGNED32_TO_32 (&previous_raw_datum, &(((u32 *) buffer) [this_field_datum_offset])); - break; - - default: - status = AE_AML_OPERAND_VALUE; - goto cleanup; - } - - - /* - * Write a partial field datum if field does not begin on a datum boundary - * - * Construct Mask with 1 bits where the field is, 0 bits elsewhere - * - * 1) Bits above the field - */ - - mask = (((u32)(-1)) << (u32)obj_desc->field.bit_offset); - - /* 2) Only the bottom 5 bits are valid for a shift operation. */ - - if ((obj_desc->field.bit_offset + obj_desc->field_unit.length) < 32) { - /* Bits above the field */ - - mask &= (~(((u32)(-1)) << ((u32)obj_desc->field.bit_offset + - (u32)obj_desc->field_unit.length))); - } - - /* 3) Shift and mask the value into the field position */ - - field_value = (previous_raw_datum << obj_desc->field.bit_offset) & mask; - - status = acpi_aml_write_field_data_with_update_rule (obj_desc, mask, field_value, - this_field_byte_offset, - bit_granularity); - if (ACPI_FAILURE (status)) { - goto cleanup; - } - - - /* If the field fits within one datum, we are done. */ - - if ((datum_length == 1) && - ((obj_desc->field.bit_offset + obj_desc->field_unit.length) <= - (u16) bit_granularity)) - { - goto cleanup; - } - - /* - * We don't need to worry about the update rule for these data, because - * all of the bits are part of the field. - * - * Can't write the last datum, however, because it might contain bits that - * are not part of the field -- the update rule must be applied. - */ - - while (this_field_datum_offset < (datum_length - 1)) { - this_field_datum_offset++; - - /* Get the next raw datum, it contains bits of the current field datum... */ - - switch (byte_granularity) - { - case 1: - this_raw_datum = ((u8 *) buffer) [this_field_datum_offset]; - break; - - case 2: - MOVE_UNALIGNED16_TO_32 (&this_raw_datum, &(((u16 *) buffer) [this_field_datum_offset])); - break; - - case 4: - MOVE_UNALIGNED32_TO_32 (&this_raw_datum, &(((u32 *) buffer) [this_field_datum_offset])); - break; - - default: - status = AE_AML_OPERAND_VALUE; - goto cleanup; - } - - /* - * Put together bits of the two raw data to make a complete field - * datum - */ - - if (obj_desc->field.bit_offset != 0) { - merged_datum = - (previous_raw_datum >> (bit_granularity - obj_desc->field.bit_offset)) | - (this_raw_datum << obj_desc->field.bit_offset); - } - - else { - merged_datum = this_raw_datum; - } - - /* Now write the completed datum */ - - - status = acpi_aml_write_field_data (obj_desc, - this_field_byte_offset + byte_granularity, - bit_granularity, merged_datum); - if (ACPI_FAILURE (status)) { - goto cleanup; - } - - - /* - * Save the most recent datum since it contains bits of - * the *next* field datum - */ - - previous_raw_datum = this_raw_datum; - - this_field_byte_offset += byte_granularity; - - } /* while */ - - - /* Write a partial field datum if field does not end on a datum boundary */ - - if ((obj_desc->field_unit.length + obj_desc->field_unit.bit_offset) % - bit_granularity) - { - switch (byte_granularity) - { - case 1: - this_raw_datum = ((u8 *) buffer) [this_field_datum_offset]; - break; - - case 2: - MOVE_UNALIGNED16_TO_32 (&this_raw_datum, &(((u16 *) buffer) [this_field_datum_offset])); - break; - - case 4: - MOVE_UNALIGNED32_TO_32 (&this_raw_datum, &(((u32 *) buffer) [this_field_datum_offset])); - break; - } - - /* Construct Mask with 1 bits where the field is, 0 bits elsewhere */ - - valid_field_bits = ((obj_desc->field_unit.length % bit_granularity) + - obj_desc->field.bit_offset); - - mask = (((u32) 1 << valid_field_bits) - (u32) 1); - - /* Shift and mask the value into the field position */ - - field_value = (previous_raw_datum >> - (bit_granularity - obj_desc->field.bit_offset)) & mask; - - status = acpi_aml_write_field_data_with_update_rule (obj_desc, mask, field_value, - this_field_byte_offset + byte_granularity, - bit_granularity); - if (ACPI_FAILURE (status)) { - goto cleanup; - } - } - - -cleanup: - - return (status); -} - - diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/interpreter/ammisc.c linux/drivers/acpi/interpreter/ammisc.c --- v2.4.5/linux/drivers/acpi/interpreter/ammisc.c Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/interpreter/ammisc.c Wed Dec 31 16:00:00 1969 @@ -1,529 +0,0 @@ - -/****************************************************************************** - * - * Module Name: ammisc - ACPI AML (p-code) execution - specific opcodes - * $Revision: 73 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "acpi.h" -#include "acparser.h" -#include "acinterp.h" -#include "amlcode.h" -#include "acdispat.h" - - -#define _COMPONENT INTERPRETER - MODULE_NAME ("ammisc") - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_exec_fatal - * - * PARAMETERS: none - * - * RETURN: Status. If the OS returns from the OSD call, we just keep - * on going. - * - * DESCRIPTION: Execute Fatal operator - * - * ACPI SPECIFICATION REFERENCES: - * Def_fatal := Fatal_op Fatal_type Fatal_code Fatal_arg - * Fatal_type := Byte_data - * Fatal_code := DWord_data - * Fatal_arg := Term_arg=>Integer - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_exec_fatal ( - ACPI_WALK_STATE *walk_state) -{ - ACPI_OPERAND_OBJECT *type_desc; - ACPI_OPERAND_OBJECT *code_desc; - ACPI_OPERAND_OBJECT *arg_desc; - ACPI_STATUS status; - - - /* Resolve operands */ - - status = acpi_aml_resolve_operands (AML_FATAL_OP, WALK_OPERANDS, walk_state); - /* Get operands */ - - status |= acpi_ds_obj_stack_pop_object (&arg_desc, walk_state); - status |= acpi_ds_obj_stack_pop_object (&code_desc, walk_state); - status |= acpi_ds_obj_stack_pop_object (&type_desc, walk_state); - if (ACPI_FAILURE (status)) { - /* Invalid parameters on object stack */ - - goto cleanup; - } - - - /* Def_fatal := Fatal_op Fatal_type Fatal_code Fatal_arg */ - - - /* - * TBD: [Unhandled] call OSD interface to notify OS of fatal error - * requiring shutdown! - */ - - -cleanup: - - /* Free the operands */ - - acpi_cm_remove_reference (arg_desc); - acpi_cm_remove_reference (code_desc); - acpi_cm_remove_reference (type_desc); - - - /* If we get back from the OS call, we might as well keep going. */ - - REPORT_WARNING (("An AML \"fatal\" Opcode (Fatal_op) was executed\n")); - return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_exec_index - * - * PARAMETERS: none - * - * RETURN: Status - * - * DESCRIPTION: Execute Index operator - * - * ALLOCATION: Deletes one operand descriptor -- other remains on stack - * - * ACPI SPECIFICATION REFERENCES: - * Def_index := Index_op Buff_pkg_obj Index_value Result - * Index_value := Term_arg=>Integer - * Name_string := | - * Result := Super_name - * Super_name := Name_string | Arg_obj | Local_obj | Debug_obj | Def_index - * Local4_op | Local5_op | Local6_op | Local7_op - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_exec_index ( - ACPI_WALK_STATE *walk_state, - ACPI_OPERAND_OBJECT **return_desc) -{ - ACPI_OPERAND_OBJECT *obj_desc; - ACPI_OPERAND_OBJECT *idx_desc; - ACPI_OPERAND_OBJECT *res_desc; - ACPI_OPERAND_OBJECT *ret_desc = NULL; - ACPI_OPERAND_OBJECT *tmp_desc; - ACPI_STATUS status; - - - /* Resolve operands */ - /* First operand can be either a package or a buffer */ - - status = acpi_aml_resolve_operands (AML_INDEX_OP, WALK_OPERANDS, walk_state); - /* Get all operands */ - - status |= acpi_ds_obj_stack_pop_object (&res_desc, walk_state); - status |= acpi_ds_obj_stack_pop_object (&idx_desc, walk_state); - status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); - if (ACPI_FAILURE (status)) { - /* Invalid parameters on object stack */ - - goto cleanup; - } - - - /* Create the internal return object */ - - ret_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_REFERENCE); - if (!ret_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - - /* - * At this point, the Obj_desc operand is either a Package or a Buffer - */ - - if (obj_desc->common.type == ACPI_TYPE_PACKAGE) { - /* Object to be indexed is a Package */ - - if (idx_desc->integer.value >= obj_desc->package.count) { - status = AE_AML_PACKAGE_LIMIT; - goto cleanup; - } - - if ((res_desc->common.type == INTERNAL_TYPE_REFERENCE) && - (res_desc->reference.op_code == AML_ZERO_OP)) - { - /* - * There is no actual result descriptor (the Zero_op Result - * descriptor is a placeholder), so just delete the placeholder and - * return a reference to the package element - */ - - acpi_cm_remove_reference (res_desc); - } - - else { - /* - * Each element of the package is an internal object. Get the one - * we are after. - */ - - tmp_desc = obj_desc->package.elements[idx_desc->integer.value]; - ret_desc->reference.op_code = AML_INDEX_OP; - ret_desc->reference.target_type = tmp_desc->common.type; - ret_desc->reference.object = tmp_desc; - - status = acpi_aml_exec_store (ret_desc, res_desc, walk_state); - ret_desc->reference.object = NULL; - } - - /* - * The local return object must always be a reference to the package element, - * not the element itself. - */ - ret_desc->reference.op_code = AML_INDEX_OP; - ret_desc->reference.target_type = ACPI_TYPE_PACKAGE; - ret_desc->reference.where = &obj_desc->package.elements[idx_desc->integer.value]; - } - - else { - /* Object to be indexed is a Buffer */ - - if (idx_desc->integer.value >= obj_desc->buffer.length) { - status = AE_AML_BUFFER_LIMIT; - goto cleanup; - } - - ret_desc->reference.op_code = AML_INDEX_OP; - ret_desc->reference.target_type = ACPI_TYPE_BUFFER_FIELD; - ret_desc->reference.object = obj_desc; - ret_desc->reference.offset = (u32) idx_desc->integer.value; - - status = acpi_aml_exec_store (ret_desc, res_desc, walk_state); - } - - -cleanup: - - /* Always delete operands */ - - acpi_cm_remove_reference (obj_desc); - acpi_cm_remove_reference (idx_desc); - - /* Delete return object on error */ - - if (ACPI_FAILURE (status)) { - acpi_cm_remove_reference (res_desc); - - if (ret_desc) { - acpi_cm_remove_reference (ret_desc); - ret_desc = NULL; - } - } - - /* Set the return object and exit */ - - *return_desc = ret_desc; - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_exec_match - * - * PARAMETERS: none - * - * RETURN: Status - * - * DESCRIPTION: Execute Match operator - * - * ACPI SPECIFICATION REFERENCES: - * Def_match := Match_op Search_pkg Opcode1 Operand1 - * Opcode2 Operand2 Start_index - * Opcode1 := Byte_data: MTR, MEQ, MLE, MLT, MGE, or MGT - * Opcode2 := Byte_data: MTR, MEQ, MLE, MLT, MGE, or MGT - * Operand1 := Term_arg=>Integer - * Operand2 := Term_arg=>Integer - * Search_pkg := Term_arg=>Package_object - * Start_index := Term_arg=>Integer - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_exec_match ( - ACPI_WALK_STATE *walk_state, - ACPI_OPERAND_OBJECT **return_desc) -{ - ACPI_OPERAND_OBJECT *pkg_desc; - ACPI_OPERAND_OBJECT *op1_desc; - ACPI_OPERAND_OBJECT *V1_desc; - ACPI_OPERAND_OBJECT *op2_desc; - ACPI_OPERAND_OBJECT *V2_desc; - ACPI_OPERAND_OBJECT *start_desc; - ACPI_OPERAND_OBJECT *ret_desc = NULL; - ACPI_STATUS status; - u32 index; - u32 match_value = (u32) -1; - - - /* Resolve all operands */ - - status = acpi_aml_resolve_operands (AML_MATCH_OP, WALK_OPERANDS, walk_state); - /* Get all operands */ - - status |= acpi_ds_obj_stack_pop_object (&start_desc, walk_state); - status |= acpi_ds_obj_stack_pop_object (&V2_desc, walk_state); - status |= acpi_ds_obj_stack_pop_object (&op2_desc, walk_state); - status |= acpi_ds_obj_stack_pop_object (&V1_desc, walk_state); - status |= acpi_ds_obj_stack_pop_object (&op1_desc, walk_state); - status |= acpi_ds_obj_stack_pop_object (&pkg_desc, walk_state); - - if (ACPI_FAILURE (status)) { - /* Invalid parameters on object stack */ - - goto cleanup; - } - - /* Validate match comparison sub-opcodes */ - - if ((op1_desc->integer.value > MAX_MATCH_OPERATOR) || - (op2_desc->integer.value > MAX_MATCH_OPERATOR)) - { - status = AE_AML_OPERAND_VALUE; - goto cleanup; - } - - index = (u32) start_desc->integer.value; - if (index >= (u32) pkg_desc->package.count) { - status = AE_AML_PACKAGE_LIMIT; - goto cleanup; - } - - ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER); - if (!ret_desc) { - status = AE_NO_MEMORY; - goto cleanup; - - } - - /* - * Examine each element until a match is found. Within the loop, - * "continue" signifies that the current element does not match - * and the next should be examined. - * Upon finding a match, the loop will terminate via "break" at - * the bottom. If it terminates "normally", Match_value will be -1 - * (its initial value) indicating that no match was found. When - * returned as a Number, this will produce the Ones value as specified. - */ - - for ( ; index < pkg_desc->package.count; ++index) { - /* - * Treat any NULL or non-numeric elements as non-matching. - * TBD [Unhandled] - if an element is a Name, - * should we examine its value? - */ - if (!pkg_desc->package.elements[index] || - ACPI_TYPE_INTEGER != pkg_desc->package.elements[index]->common.type) - { - continue; - } - - /* - * Within these switch statements: - * "break" (exit from the switch) signifies a match; - * "continue" (proceed to next iteration of enclosing - * "for" loop) signifies a non-match. - */ - switch (op1_desc->integer.value) - { - - case MATCH_MTR: /* always true */ - - break; - - - case MATCH_MEQ: /* true if equal */ - - if (pkg_desc->package.elements[index]->integer.value - != V1_desc->integer.value) - { - continue; - } - break; - - - case MATCH_MLE: /* true if less than or equal */ - - if (pkg_desc->package.elements[index]->integer.value - > V1_desc->integer.value) - { - continue; - } - break; - - - case MATCH_MLT: /* true if less than */ - - if (pkg_desc->package.elements[index]->integer.value - >= V1_desc->integer.value) - { - continue; - } - break; - - - case MATCH_MGE: /* true if greater than or equal */ - - if (pkg_desc->package.elements[index]->integer.value - < V1_desc->integer.value) - { - continue; - } - break; - - - case MATCH_MGT: /* true if greater than */ - - if (pkg_desc->package.elements[index]->integer.value - <= V1_desc->integer.value) - { - continue; - } - break; - - - default: /* undefined */ - - continue; - } - - - switch(op2_desc->integer.value) - { - - case MATCH_MTR: - - break; - - - case MATCH_MEQ: - - if (pkg_desc->package.elements[index]->integer.value - != V2_desc->integer.value) - { - continue; - } - break; - - - case MATCH_MLE: - - if (pkg_desc->package.elements[index]->integer.value - > V2_desc->integer.value) - { - continue; - } - break; - - - case MATCH_MLT: - - if (pkg_desc->package.elements[index]->integer.value - >= V2_desc->integer.value) - { - continue; - } - break; - - - case MATCH_MGE: - - if (pkg_desc->package.elements[index]->integer.value - < V2_desc->integer.value) - { - continue; - } - break; - - - case MATCH_MGT: - - if (pkg_desc->package.elements[index]->integer.value - <= V2_desc->integer.value) - { - continue; - } - break; - - - default: - - continue; - } - - /* Match found: exit from loop */ - - match_value = index; - break; - } - - /* Match_value is the return value */ - - ret_desc->integer.value = match_value; - - -cleanup: - - /* Free the operands */ - - acpi_cm_remove_reference (start_desc); - acpi_cm_remove_reference (V2_desc); - acpi_cm_remove_reference (op2_desc); - acpi_cm_remove_reference (V1_desc); - acpi_cm_remove_reference (op1_desc); - acpi_cm_remove_reference (pkg_desc); - - - /* Delete return object on error */ - - if (ACPI_FAILURE (status) && - (ret_desc)) - { - acpi_cm_remove_reference (ret_desc); - ret_desc = NULL; - } - - - /* Set the return object and exit */ - - *return_desc = ret_desc; - return (status); -} diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/interpreter/ammonad.c linux/drivers/acpi/interpreter/ammonad.c --- v2.4.5/linux/drivers/acpi/interpreter/ammonad.c Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/interpreter/ammonad.c Wed Dec 31 16:00:00 1969 @@ -1,999 +0,0 @@ - -/****************************************************************************** - * - * Module Name: ammonad - ACPI AML (p-code) execution for monadic operators - * $Revision: 89 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "acpi.h" -#include "acparser.h" -#include "acdispat.h" -#include "acinterp.h" -#include "amlcode.h" -#include "acnamesp.h" - - -#define _COMPONENT INTERPRETER - MODULE_NAME ("ammonad") - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_get_object_reference - * - * PARAMETERS: Obj_desc - Create a reference to this object - * Ret_desc - Where to store the reference - * - * RETURN: Status - * - * DESCRIPTION: Obtain and return a "reference" to the target object - * Common code for the Ref_of_op and the Cond_ref_of_op. - * - ******************************************************************************/ - -static ACPI_STATUS -acpi_aml_get_object_reference ( - ACPI_OPERAND_OBJECT *obj_desc, - ACPI_OPERAND_OBJECT **ret_desc, - ACPI_WALK_STATE *walk_state) -{ - ACPI_STATUS status = AE_OK; - - - if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_INTERNAL)) { - if (obj_desc->common.type != INTERNAL_TYPE_REFERENCE) { - *ret_desc = NULL; - status = AE_TYPE; - goto cleanup; - } - - /* - * Not a Name -- an indirect name pointer would have - * been converted to a direct name pointer in Acpi_aml_resolve_operands - */ - switch (obj_desc->reference.op_code) - { - case AML_LOCAL_OP: - - *ret_desc = (void *) acpi_ds_method_data_get_nte (MTH_TYPE_LOCAL, - (obj_desc->reference.offset), walk_state); - break; - - - case AML_ARG_OP: - - *ret_desc = (void *) acpi_ds_method_data_get_nte (MTH_TYPE_ARG, - (obj_desc->reference.offset), walk_state); - break; - - - default: - - *ret_desc = NULL; - status = AE_AML_INTERNAL; - goto cleanup; - } - - } - - else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { - /* Must be a named object; Just return the Node */ - - *ret_desc = obj_desc; - } - - else { - *ret_desc = NULL; - status = AE_TYPE; - } - - -cleanup: - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_exec_monadic1 - * - * PARAMETERS: Opcode - The opcode to be executed - * - * RETURN: Status - * - * DESCRIPTION: Execute Type 1 monadic operator with numeric operand on - * object stack - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_exec_monadic1 ( - u16 opcode, - ACPI_WALK_STATE *walk_state) -{ - ACPI_OPERAND_OBJECT *obj_desc; - ACPI_STATUS status; - - - /* Resolve all operands */ - - status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS, walk_state); - /* Get all operands */ - - status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); - if (ACPI_FAILURE (status)) { - goto cleanup; - } - - - /* Examine the opcode */ - - switch (opcode) - { - - /* Def_release := Release_op Mutex_object */ - - case AML_RELEASE_OP: - - status = acpi_aml_system_release_mutex (obj_desc); - break; - - - /* Def_reset := Reset_op Acpi_event_object */ - - case AML_RESET_OP: - - status = acpi_aml_system_reset_event (obj_desc); - break; - - - /* Def_signal := Signal_op Acpi_event_object */ - - case AML_SIGNAL_OP: - - status = acpi_aml_system_signal_event (obj_desc); - break; - - - /* Def_sleep := Sleep_op Msec_time */ - - case AML_SLEEP_OP: - - acpi_aml_system_do_suspend ((u32) obj_desc->integer.value); - break; - - - /* Def_stall := Stall_op Usec_time */ - - case AML_STALL_OP: - - acpi_aml_system_do_stall ((u32) obj_desc->integer.value); - break; - - - /* Unknown opcode */ - - default: - - REPORT_ERROR (("Acpi_aml_exec_monadic1: Unknown monadic opcode %X\n", - opcode)); - status = AE_AML_BAD_OPCODE; - break; - - } /* switch */ - - -cleanup: - - /* Always delete the operand */ - - acpi_cm_remove_reference (obj_desc); - - return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_exec_monadic2_r - * - * PARAMETERS: Opcode - The opcode to be executed - * - * RETURN: Status - * - * DESCRIPTION: Execute Type 2 monadic operator with numeric operand and - * result operand on operand stack - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_exec_monadic2_r ( - u16 opcode, - ACPI_WALK_STATE *walk_state, - ACPI_OPERAND_OBJECT **return_desc) -{ - ACPI_OPERAND_OBJECT *obj_desc; - ACPI_OPERAND_OBJECT *res_desc; - ACPI_OPERAND_OBJECT *ret_desc = NULL; - ACPI_OPERAND_OBJECT *ret_desc2 = NULL; - u32 res_val; - ACPI_STATUS status; - u32 i; - u32 j; - ACPI_INTEGER digit; - - - /* Resolve all operands */ - - status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS, walk_state); - /* Get all operands */ - - status |= acpi_ds_obj_stack_pop_object (&res_desc, walk_state); - status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); - if (ACPI_FAILURE (status)) { - goto cleanup; - } - - - /* Create a return object of type NUMBER for most opcodes */ - - switch (opcode) - { - case AML_BIT_NOT_OP: - case AML_FIND_SET_LEFT_BIT_OP: - case AML_FIND_SET_RIGHT_BIT_OP: - case AML_FROM_BCD_OP: - case AML_TO_BCD_OP: - case AML_COND_REF_OF_OP: - - ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER); - if (!ret_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - break; - } - - - switch (opcode) - { - /* Def_not := Not_op Operand Result */ - - case AML_BIT_NOT_OP: - - ret_desc->integer.value = ~obj_desc->integer.value; - break; - - - /* Def_find_set_left_bit := Find_set_left_bit_op Operand Result */ - - case AML_FIND_SET_LEFT_BIT_OP: - - ret_desc->integer.value = obj_desc->integer.value; - - /* - * Acpi specification describes Integer type as a little - * endian unsigned value, so this boundry condition is valid. - */ - for (res_val = 0; ret_desc->integer.value && res_val < ACPI_INTEGER_BIT_SIZE; ++res_val) { - ret_desc->integer.value >>= 1; - } - - ret_desc->integer.value = res_val; - break; - - - /* Def_find_set_right_bit := Find_set_right_bit_op Operand Result */ - - case AML_FIND_SET_RIGHT_BIT_OP: - - ret_desc->integer.value = obj_desc->integer.value; - - /* - * Acpi specification describes Integer type as a little - * endian unsigned value, so this boundry condition is valid. - */ - for (res_val = 0; ret_desc->integer.value && res_val < ACPI_INTEGER_BIT_SIZE; ++res_val) { - ret_desc->integer.value <<= 1; - } - - /* Since returns must be 1-based, subtract from 33 (65) */ - - ret_desc->integer.value = res_val == 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - res_val; - break; - - - /* Def_from_bDC := From_bCDOp BCDValue Result */ - - case AML_FROM_BCD_OP: - - /* - * The 64-bit ACPI integer can hold 16 4-bit BCD integers - */ - ret_desc->integer.value = 0; - for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) { - /* Get one BCD digit */ - - digit = (ACPI_INTEGER) ((obj_desc->integer.value >> (i * 4)) & 0xF); - - /* Check the range of the digit */ - - if (digit > 9) { - 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; - } - - ret_desc->integer.value += digit; - } - } - break; - - - /* Def_to_bDC := To_bCDOp Operand Result */ - - case AML_TO_BCD_OP: - - - if (obj_desc->integer.value > ACPI_MAX_BCD_VALUE) { - status = AE_AML_NUMERIC_OVERFLOW; - goto cleanup; - } - - ret_desc->integer.value = 0; - for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) { - /* Divide by nth factor of 10 */ - - digit = obj_desc->integer.value; - for (j = 0; j < i; j++) { - digit /= 10; - } - - /* Create the BCD digit */ - - if (digit > 0) { - ret_desc->integer.value += (ACPI_MODULO (digit, 10) << (i * 4)); - } - } - break; - - - /* Def_cond_ref_of := Cond_ref_of_op Source_object Result */ - - case AML_COND_REF_OF_OP: - - /* - * 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 *) obj_desc == acpi_gbl_root_node) { - /* - * This means that the object does not exist in the namespace, - * return FALSE - */ - - ret_desc->integer.value = 0; - - /* - * Must delete the result descriptor since there is no reference - * being returned - */ - - acpi_cm_remove_reference (res_desc); - goto cleanup; - } - - /* Get the object reference and store it */ - - status = acpi_aml_get_object_reference (obj_desc, &ret_desc2, walk_state); - if (ACPI_FAILURE (status)) { - goto cleanup; - } - - status = acpi_aml_exec_store (ret_desc2, res_desc, walk_state); - - /* The object exists in the namespace, return TRUE */ - - ret_desc->integer.value = ACPI_INTEGER_MAX; - goto cleanup; - break; - - - case AML_STORE_OP: - - /* - * A store operand is typically a number, string, buffer or lvalue - * TBD: [Unhandled] What about a store to a package? - */ - - /* - * Do the store, and be careful about deleting the source object, - * since the object itself may have been stored. - */ - - status = acpi_aml_exec_store (obj_desc, res_desc, walk_state); - if (ACPI_FAILURE (status)) { - /* On failure, just delete the Obj_desc */ - - acpi_cm_remove_reference (obj_desc); - } - - else { - /* - * Normally, we would remove a reference on the Obj_desc parameter; - * But since it is being used as the internal return object - * (meaning we would normally increment it), the two cancel out, - * and we simply don't do anything. - */ - *return_desc = obj_desc; - } - - obj_desc = NULL; - return (status); - - break; - - - case AML_DEBUG_OP: - - /* Reference, returning an Reference */ - - return (AE_OK); - break; - - - /* - * These are obsolete opcodes - */ - - /* Def_shift_left_bit := Shift_left_bit_op Source Bit_num */ - /* Def_shift_right_bit := Shift_right_bit_op Source Bit_num */ - - case AML_SHIFT_LEFT_BIT_OP: - case AML_SHIFT_RIGHT_BIT_OP: - - status = AE_SUPPORT; - goto cleanup; - break; - - - default: - - REPORT_ERROR (("Acpi_aml_exec_monadic2_r: Unknown monadic opcode %X\n", - opcode)); - status = AE_AML_BAD_OPCODE; - goto cleanup; - } - - - status = acpi_aml_exec_store (ret_desc, res_desc, walk_state); - - -cleanup: - /* Always delete the operand object */ - - acpi_cm_remove_reference (obj_desc); - - /* Delete return object(s) on error */ - - if (ACPI_FAILURE (status)) { - acpi_cm_remove_reference (res_desc); /* Result descriptor */ - if (ret_desc) { - acpi_cm_remove_reference (ret_desc); - ret_desc = NULL; - } - } - - /* Set the return object and exit */ - - *return_desc = ret_desc; - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_exec_monadic2 - * - * PARAMETERS: Opcode - The opcode to be executed - * - * RETURN: Status - * - * DESCRIPTION: Execute Type 2 monadic operator with numeric operand: - * Deref_of_op, Ref_of_op, Size_of_op, Type_op, Increment_op, - * Decrement_op, LNot_op, - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_exec_monadic2 ( - u16 opcode, - ACPI_WALK_STATE *walk_state, - ACPI_OPERAND_OBJECT **return_desc) -{ - ACPI_OPERAND_OBJECT *obj_desc; - ACPI_OPERAND_OBJECT *tmp_desc; - ACPI_OPERAND_OBJECT *ret_desc = NULL; - ACPI_STATUS resolve_status; - ACPI_STATUS status; - u32 type; - ACPI_INTEGER value; - - - /* Attempt to resolve the operands */ - - resolve_status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS, walk_state); - /* Always get all operands */ - - status = acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); - - - /* Now we can check the status codes */ - - if (ACPI_FAILURE (resolve_status)) { - goto cleanup; - } - - if (ACPI_FAILURE (status)) { - goto cleanup; - } - - - /* Get the operand and decode the opcode */ - - - switch (opcode) - { - - /* Def_lNot := LNot_op Operand */ - - case AML_LNOT_OP: - - ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER); - if (!ret_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - ret_desc->integer.value = !obj_desc->integer.value; - break; - - - /* Def_decrement := Decrement_op Target */ - /* Def_increment := Increment_op Target */ - - case AML_DECREMENT_OP: - case AML_INCREMENT_OP: - - /* - * Since we are expecting an Reference on the top of the stack, it - * can be either an Node or an internal object. - * - * TBD: [Future] This may be the prototype code for all cases where - * an Reference is expected!! 10/99 - */ - - if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { - ret_desc = obj_desc; - } - - else { - /* - * Duplicate the Reference in a new object so that we can resolve it - * without destroying the original Reference object - */ - - ret_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_REFERENCE); - if (!ret_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - ret_desc->reference.op_code = obj_desc->reference.op_code; - ret_desc->reference.offset = obj_desc->reference.offset; - ret_desc->reference.object = obj_desc->reference.object; - } - - - /* - * Convert the Ret_desc Reference to a Number - * (This deletes the original Ret_desc) - */ - - status = acpi_aml_resolve_operands (AML_LNOT_OP, &ret_desc, walk_state); - if (ACPI_FAILURE (status)) { - goto cleanup; - } - - /* Do the actual increment or decrement */ - - if (AML_INCREMENT_OP == opcode) { - ret_desc->integer.value++; - } - else { - ret_desc->integer.value--; - } - - /* Store the result back in the original descriptor */ - - status = acpi_aml_exec_store (ret_desc, obj_desc, walk_state); - - /* Objdesc was just deleted (because it is an Reference) */ - - obj_desc = NULL; - - break; - - - /* Def_object_type := Object_type_op Source_object */ - - case AML_TYPE_OP: - - if (INTERNAL_TYPE_REFERENCE == obj_desc->common.type) { - /* - * Not a Name -- an indirect name pointer would have - * been converted to a direct name pointer in Resolve_operands - */ - switch (obj_desc->reference.op_code) - { - case AML_ZERO_OP: - case AML_ONE_OP: - case AML_ONES_OP: - - /* Constants are of type Number */ - - type = ACPI_TYPE_INTEGER; - break; - - - case AML_DEBUG_OP: - - /* Per 1.0b spec, Debug object is of type Debug_object */ - - type = ACPI_TYPE_DEBUG_OBJECT; - break; - - - case AML_INDEX_OP: - - /* Get the type of this reference (index into another object) */ - - type = obj_desc->reference.target_type; - if (type == ACPI_TYPE_PACKAGE) { - /* - * The main object is a package, we want to get the type - * of the individual package element that is referenced by - * the index. - */ - type = (*(obj_desc->reference.where))->common.type; - } - - break; - - - case AML_LOCAL_OP: - - type = acpi_ds_method_data_get_type (MTH_TYPE_LOCAL, - (obj_desc->reference.offset), walk_state); - break; - - - case AML_ARG_OP: - - type = acpi_ds_method_data_get_type (MTH_TYPE_ARG, - (obj_desc->reference.offset), walk_state); - break; - - - default: - - REPORT_ERROR (("Acpi_aml_exec_monadic2/Type_op: Internal error - Unknown Reference subtype %X\n", - obj_desc->reference.op_code)); - status = AE_AML_INTERNAL; - goto cleanup; - } - } - - else { - /* - * It's not a Reference, so it must be a direct name pointer. - */ - type = acpi_ns_get_type ((ACPI_HANDLE) obj_desc); - } - - /* Allocate a descriptor to hold the type. */ - - ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER); - if (!ret_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - ret_desc->integer.value = type; - break; - - - /* Def_size_of := Size_of_op Source_object */ - - case AML_SIZE_OF_OP: - - if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { - obj_desc = acpi_ns_get_attached_object (obj_desc); - } - - if (!obj_desc) { - value = 0; - } - - else { - switch (obj_desc->common.type) - { - - case ACPI_TYPE_BUFFER: - - value = obj_desc->buffer.length; - break; - - - case ACPI_TYPE_STRING: - - value = obj_desc->string.length; - break; - - - case ACPI_TYPE_PACKAGE: - - value = obj_desc->package.count; - break; - - case INTERNAL_TYPE_REFERENCE: - - value = 4; - break; - - default: - - status = AE_AML_OPERAND_TYPE; - goto cleanup; - } - } - - /* - * Now that we have the size of the object, create a result - * object to hold the value - */ - - ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER); - if (!ret_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - ret_desc->integer.value = value; - break; - - - /* Def_ref_of := Ref_of_op Source_object */ - - case AML_REF_OF_OP: - - status = acpi_aml_get_object_reference (obj_desc, &ret_desc, walk_state); - if (ACPI_FAILURE (status)) { - goto cleanup; - } - break; - - - /* Def_deref_of := Deref_of_op Obj_reference */ - - case AML_DEREF_OF_OP: - - - /* Check for a method local or argument */ - - if (!VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { - /* - * Must resolve/dereference the local/arg reference first - */ - switch (obj_desc->reference.op_code) - { - /* Set Obj_desc to the value of the local/arg */ - - case AML_LOCAL_OP: - - acpi_ds_method_data_get_value (MTH_TYPE_LOCAL, - (obj_desc->reference.offset), walk_state, &tmp_desc); - - /* - * Delete our reference to the input object and - * point to the object just retrieved - */ - acpi_cm_remove_reference (obj_desc); - obj_desc = tmp_desc; - break; - - - case AML_ARG_OP: - - acpi_ds_method_data_get_value (MTH_TYPE_ARG, - (obj_desc->reference.offset), walk_state, &tmp_desc); - - /* - * Delete our reference to the input object and - * point to the object just retrieved - */ - acpi_cm_remove_reference (obj_desc); - obj_desc = tmp_desc; - break; - - default: - - /* Index op - handled below */ - break; - } - } - - - /* Obj_desc may have changed from the code above */ - - if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { - /* Get the actual object from the Node (This is the dereference) */ - - ret_desc = ((ACPI_NAMESPACE_NODE *) obj_desc)->object; - - /* Returning a pointer to the object, add another reference! */ - - acpi_cm_add_reference (ret_desc); - } - - else { - /* - * This must be a reference object produced by the Index - * ASL operation -- check internal opcode - */ - - if ((obj_desc->reference.op_code != AML_INDEX_OP) && - (obj_desc->reference.op_code != AML_REF_OF_OP)) - { - status = AE_TYPE; - goto cleanup; - } - - - switch (obj_desc->reference.op_code) - { - case AML_INDEX_OP: - - /* - * Supported target types for the Index operator are - * 1) A Buffer - * 2) A Package - */ - - if (obj_desc->reference.target_type == ACPI_TYPE_BUFFER_FIELD) { - /* - * The target is a buffer, we must create a new object that - * contains one element of the buffer, the element pointed - * to by the index. - * - * NOTE: index into a buffer is NOT a pointer to a - * sub-buffer of the main buffer, it is only a pointer to a - * single element (byte) of the buffer! - */ - ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER); - if (!ret_desc) { - status = AE_NO_MEMORY; - goto cleanup; - } - - tmp_desc = obj_desc->reference.object; - ret_desc->integer.value = - tmp_desc->buffer.pointer[obj_desc->reference.offset]; - - /* TBD: [Investigate] (see below) Don't add an additional - * ref! - */ - } - - else if (obj_desc->reference.target_type == ACPI_TYPE_PACKAGE) { - /* - * The target is a package, we want to return the referenced - * element of the package. We must add another reference to - * this object, however. - */ - - ret_desc = *(obj_desc->reference.where); - if (!ret_desc) { - /* - * We can't return a NULL dereferenced value. This is - * an uninitialized package element and is thus a - * severe error. - */ - - status = AE_AML_UNINITIALIZED_ELEMENT; - goto cleanup; - } - - acpi_cm_add_reference (ret_desc); - } - - else { - status = AE_AML_OPERAND_TYPE; - goto cleanup; - } - - break; - - - case AML_REF_OF_OP: - - ret_desc = obj_desc->reference.object; - - /* Add another reference to the object! */ - - acpi_cm_add_reference (ret_desc); - break; - } - } - - break; - - - default: - - REPORT_ERROR (("Acpi_aml_exec_monadic2: Unknown monadic opcode %X\n", - opcode)); - status = AE_AML_BAD_OPCODE; - goto cleanup; - } - - -cleanup: - - if (obj_desc) { - acpi_cm_remove_reference (obj_desc); - } - - /* Delete return object on error */ - - if (ACPI_FAILURE (status) && - (ret_desc)) - { - acpi_cm_remove_reference (ret_desc); - ret_desc = NULL; - } - - *return_desc = ret_desc; - return (status); -} - diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/interpreter/amnames.c linux/drivers/acpi/interpreter/amnames.c --- v2.4.5/linux/drivers/acpi/interpreter/amnames.c Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/interpreter/amnames.c Wed Dec 31 16:00:00 1969 @@ -1,395 +0,0 @@ - -/****************************************************************************** - * - * Module Name: amnames - interpreter/scanner name load/execute - * $Revision: 73 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "acpi.h" -#include "acinterp.h" -#include "amlcode.h" -#include "acnamesp.h" - -#define _COMPONENT INTERPRETER - MODULE_NAME ("amnames") - - -/* AML Package Length encodings */ - -#define ACPI_AML_PACKAGE_TYPE1 0x40 -#define ACPI_AML_PACKAGE_TYPE2 0x4000 -#define ACPI_AML_PACKAGE_TYPE3 0x400000 -#define ACPI_AML_PACKAGE_TYPE4 0x40000000 - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_allocate_name_string - * - * PARAMETERS: Prefix_count - Count of parent levels. Special cases: - * (-1) = root, 0 = none - * Num_name_segs - count of 4-character name segments - * - * RETURN: A pointer to the allocated string segment. This segment must - * be deleted by the caller. - * - * DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name - * string is long enough, and set up prefix if any. - * - ******************************************************************************/ - -NATIVE_CHAR * -acpi_aml_allocate_name_string ( - u32 prefix_count, - u32 num_name_segs) -{ - NATIVE_CHAR *temp_ptr; - NATIVE_CHAR *name_string; - u32 size_needed; - - - /* - * Allow room for all \ and ^ prefixes, all segments, and a Multi_name_prefix. - * Also, one byte for the null terminator. - * This may actually be somewhat longer than needed. - */ - - if (prefix_count == (u32) -1) { - /* Special case for root */ - - size_needed = 1 + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1; - } - else { - size_needed = prefix_count + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1; - } - - /* - * Allocate a buffer for the name. - * This buffer must be deleted by the caller! - */ - - name_string = acpi_cm_allocate (size_needed); - if (!name_string) { - REPORT_ERROR (("Aml_allocate_name_string: name allocation failure\n")); - return (NULL); - } - - temp_ptr = name_string; - - /* Set up Root or Parent prefixes if needed */ - - if (prefix_count == (u32) -1) { - *temp_ptr++ = AML_ROOT_PREFIX; - } - - else { - while (prefix_count--) { - *temp_ptr++ = AML_PARENT_PREFIX; - } - } - - - /* Set up Dual or Multi prefixes if needed */ - - if (num_name_segs > 2) { - /* Set up multi prefixes */ - - *temp_ptr++ = AML_MULTI_NAME_PREFIX_OP; - *temp_ptr++ = (char) num_name_segs; - } - - else if (2 == num_name_segs) { - /* Set up dual prefixes */ - - *temp_ptr++ = AML_DUAL_NAME_PREFIX; - } - - /* - * Terminate string following prefixes. Acpi_aml_exec_name_segment() will - * append the segment(s) - */ - - *temp_ptr = 0; - - return (name_string); -} - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_exec_name_segment - * - * PARAMETERS: Interpreter_mode - Current running mode (load1/Load2/Exec) - * - * RETURN: Status - * - * DESCRIPTION: Execute a name segment (4 bytes) - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_exec_name_segment ( - u8 **in_aml_address, - NATIVE_CHAR *name_string) -{ - u8 *aml_address = *in_aml_address; - ACPI_STATUS status = AE_OK; - u32 index; - NATIVE_CHAR char_buf[5]; - - - /* - * If first character is a digit, then we know that we aren't looking at a - * valid name segment - */ - - char_buf[0] = *aml_address; - - if ('0' <= char_buf[0] && char_buf[0] <= '9') { - return (AE_CTRL_PENDING); - } - - for (index = 4; - (index > 0) && (acpi_cm_valid_acpi_character (*aml_address)); - --index) - { - char_buf[4 - index] = *aml_address++; - } - - - /* Valid name segment */ - - if (0 == index) { - /* Found 4 valid characters */ - - char_buf[4] = '\0'; - - if (name_string) { - STRCAT (name_string, char_buf); - } - - } - - else if (4 == index) { - /* - * First character was not a valid name character, - * so we are looking at something other than a name. - */ - status = AE_CTRL_PENDING; - } - - else { - /* Segment started with one or more valid characters, but fewer than 4 */ - - status = AE_AML_BAD_NAME; - } - - *in_aml_address = aml_address; - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_get_name_string - * - * PARAMETERS: Data_type - Data type to be associated with this name - * - * RETURN: Status - * - * DESCRIPTION: Get a name, including any prefixes. - * - ******************************************************************************/ - - -ACPI_STATUS -acpi_aml_get_name_string ( - OBJECT_TYPE_INTERNAL data_type, - u8 *in_aml_address, - NATIVE_CHAR **out_name_string, - u32 *out_name_length) -{ - ACPI_STATUS status = AE_OK; - u8 *aml_address = in_aml_address; - NATIVE_CHAR *name_string = NULL; - u32 num_segments; - u32 prefix_count = 0; - u8 prefix = 0; - u8 has_prefix = FALSE; - - - if (INTERNAL_TYPE_DEF_FIELD == data_type || - INTERNAL_TYPE_BANK_FIELD == data_type || - INTERNAL_TYPE_INDEX_FIELD == data_type) - { - /* Disallow prefixes for types associated with field names */ - - name_string = acpi_aml_allocate_name_string (0, 1); - if (!name_string) { - status = AE_NO_MEMORY; - } - else { - status = acpi_aml_exec_name_segment (&aml_address, name_string); - } - } - - else { - /* - * Data_type is not a field name. - * Examine first character of name for root or parent prefix operators - */ - - switch (*aml_address) - { - - case AML_ROOT_PREFIX: - - prefix = *aml_address++; - /* - * Remember that we have a Root_prefix -- - * see comment in Acpi_aml_allocate_name_string() - */ - prefix_count = (u32) -1; - has_prefix = TRUE; - break; - - - case AML_PARENT_PREFIX: - - /* Increment past possibly multiple parent prefixes */ - - do - { - prefix = *aml_address++; - ++prefix_count; - - } while (*aml_address == AML_PARENT_PREFIX); - has_prefix = TRUE; - break; - - - default: - - break; - } - - - /* Examine first character of name for name segment prefix operator */ - - switch (*aml_address) - { - - case AML_DUAL_NAME_PREFIX: - - prefix = *aml_address++; - name_string = acpi_aml_allocate_name_string (prefix_count, 2); - if (!name_string) { - status = AE_NO_MEMORY; - break; - } - - /* Indicate that we processed a prefix */ - has_prefix = TRUE; - - status = acpi_aml_exec_name_segment (&aml_address, name_string); - if (ACPI_SUCCESS (status)) { - status = acpi_aml_exec_name_segment (&aml_address, name_string); - } - break; - - - case AML_MULTI_NAME_PREFIX_OP: - - prefix = *aml_address++; - /* Fetch count of segments remaining in name path */ - - num_segments = *aml_address++; - - name_string = acpi_aml_allocate_name_string (prefix_count, num_segments); - if (!name_string) { - status = AE_NO_MEMORY; - break; - } - - /* Indicate that we processed a prefix */ - has_prefix = TRUE; - - while (num_segments && - (status = acpi_aml_exec_name_segment (&aml_address, name_string)) == AE_OK) - { - --num_segments; - } - - break; - - - case 0: - - /* Null_name valid as of 8-12-98 ASL/AML Grammar Update */ - - - /* Consume the NULL byte */ - - aml_address++; - name_string = acpi_aml_allocate_name_string (prefix_count, 0); - if (!name_string) { - status = AE_NO_MEMORY; - break; - } - - break; - - - default: - - /* Name segment string */ - - name_string = acpi_aml_allocate_name_string (prefix_count, 1); - if (!name_string) { - status = AE_NO_MEMORY; - break; - } - - status = acpi_aml_exec_name_segment (&aml_address, name_string); - break; - - } /* Switch (Peek_op ()) */ - } - - - if (AE_CTRL_PENDING == status && has_prefix) { - /* Ran out of segments after processing a prefix */ - - REPORT_ERROR ( - ("Aml_do_name: Malformed Name at %p\n", name_string)); - status = AE_AML_BAD_NAME; - } - - - *out_name_string = name_string; - *out_name_length = (u32) (aml_address - in_aml_address); - - return (status); -} - - diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/interpreter/amprep.c linux/drivers/acpi/interpreter/amprep.c --- v2.4.5/linux/drivers/acpi/interpreter/amprep.c Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/interpreter/amprep.c Wed Dec 31 16:00:00 1969 @@ -1,405 +0,0 @@ - -/****************************************************************************** - * - * Module Name: amprep - ACPI AML (p-code) execution - field prep utilities - * $Revision: 73 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "acpi.h" -#include "acinterp.h" -#include "amlcode.h" -#include "acnamesp.h" -#include "acparser.h" - - -#define _COMPONENT INTERPRETER - MODULE_NAME ("amprep") - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_decode_field_access_type - * - * PARAMETERS: Access - Encoded field access bits - * - * RETURN: Field granularity (8, 16, or 32) - * - * DESCRIPTION: Decode the Access_type bits of a field definition. - * - ******************************************************************************/ - -static u32 -acpi_aml_decode_field_access_type ( - u32 access, - u16 length) -{ - - switch (access) - { - case ACCESS_ANY_ACC: - if (length <= 8) { - return (8); - } - else if (length <= 16) { - return (16); - } - else if (length <= 32) { - return (32); - } - else { - return (8); - } - break; - - case ACCESS_BYTE_ACC: - return (8); - break; - - case ACCESS_WORD_ACC: - return (16); - break; - - case ACCESS_DWORD_ACC: - return (32); - break; - - default: - /* Invalid field access type */ - - return (0); - } -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_prep_common_field_objec - * - * PARAMETERS: Obj_desc - The field object - * Field_flags - Access, Lock_rule, or Update_rule. - * The format of a Field_flag is described - * in the ACPI specification - * Field_position - Field position - * Field_length - Field length - * - * RETURN: Status - * - * DESCRIPTION: Initialize the areas of the field object that are common - * to the various types of fields. - * - ******************************************************************************/ - -static ACPI_STATUS -acpi_aml_prep_common_field_object ( - ACPI_OPERAND_OBJECT *obj_desc, - u8 field_flags, - u8 field_attribute, - u32 field_position, - u32 field_length) -{ - u32 granularity; - - - /* - * Note: the structure being initialized is the - * ACPI_COMMON_FIELD_INFO; Therefore, we can just use the Field union to - * access this common area. No structure fields outside of the common area - * are initialized by this procedure. - */ - - /* Decode the Field_flags */ - - obj_desc->field.access = (u8) ((field_flags & ACCESS_TYPE_MASK) - >> ACCESS_TYPE_SHIFT); - obj_desc->field.lock_rule = (u8) ((field_flags & LOCK_RULE_MASK) - >> LOCK_RULE_SHIFT); - obj_desc->field.update_rule = (u8) ((field_flags & UPDATE_RULE_MASK) - >> UPDATE_RULE_SHIFT); - - /* Other misc fields */ - - obj_desc->field.length = (u16) field_length; - obj_desc->field.access_attribute = field_attribute; - - /* Decode the access type so we can compute offsets */ - - granularity = acpi_aml_decode_field_access_type (obj_desc->field.access, obj_desc->field.length); - if (!granularity) { - return (AE_AML_OPERAND_VALUE); - } - - /* Access granularity based fields */ - - obj_desc->field.granularity = (u8) granularity; - obj_desc->field.bit_offset = (u8) (field_position % granularity); - obj_desc->field.offset = (u32) field_position / granularity; - - - return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_prep_def_field_value - * - * PARAMETERS: Node - Owning Node - * Region - Region in which field is being defined - * Field_flags - Access, Lock_rule, or Update_rule. - * The format of a Field_flag is described - * in the ACPI specification - * Field_position - Field position - * Field_length - Field length - * - * RETURN: Status - * - * DESCRIPTION: Construct an ACPI_OPERAND_OBJECT of type Def_field and - * connect it to the parent Node. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_prep_def_field_value ( - ACPI_NAMESPACE_NODE *node, - ACPI_HANDLE region, - u8 field_flags, - u8 field_attribute, - u32 field_position, - u32 field_length) -{ - ACPI_OPERAND_OBJECT *obj_desc; - u32 type; - ACPI_STATUS status; - - - /* Parameter validation */ - - if (!region) { - return (AE_AML_NO_OPERAND); - } - - type = acpi_ns_get_type (region); - if (type != ACPI_TYPE_REGION) { - return (AE_AML_OPERAND_TYPE); - } - - /* Allocate a new object */ - - obj_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_DEF_FIELD); - if (!obj_desc) { - return (AE_NO_MEMORY); - } - - - /* Obj_desc and Region valid */ - - /* Initialize areas of the object that are common to all fields */ - - status = acpi_aml_prep_common_field_object (obj_desc, field_flags, field_attribute, - field_position, field_length); - if (ACPI_FAILURE (status)) { - return (status); - } - - /* Initialize areas of the object that are specific to this field type */ - - obj_desc->field.container = acpi_ns_get_attached_object (region); - - /* An additional reference for the container */ - - acpi_cm_add_reference (obj_desc->field.container); - - - /* Debug info */ - - /* - * Store the constructed descriptor (Obj_desc) into the Named_obj whose - * handle is on TOS, preserving the current type of that Named_obj. - */ - status = acpi_ns_attach_object ((ACPI_HANDLE) node, obj_desc, - (u8) acpi_ns_get_type ((ACPI_HANDLE) node)); - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_prep_bank_field_value - * - * PARAMETERS: Node - Owning Node - * Region - Region in which field is being defined - * Bank_reg - Bank selection register - * Bank_val - Value to store in selection register - * Field_flags - Access, Lock_rule, or Update_rule - * Field_position - Field position - * Field_length - Field length - * - * RETURN: Status - * - * DESCRIPTION: Construct an ACPI_OPERAND_OBJECT of type Bank_field and - * connect it to the parent Node. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_prep_bank_field_value ( - ACPI_NAMESPACE_NODE *node, - ACPI_HANDLE region, - ACPI_HANDLE bank_reg, - u32 bank_val, - u8 field_flags, - u8 field_attribute, - u32 field_position, - u32 field_length) -{ - ACPI_OPERAND_OBJECT *obj_desc; - u32 type; - ACPI_STATUS status; - - - /* Parameter validation */ - - if (!region) { - return (AE_AML_NO_OPERAND); - } - - type = acpi_ns_get_type (region); - if (type != ACPI_TYPE_REGION) { - return (AE_AML_OPERAND_TYPE); - } - - /* Allocate a new object */ - - obj_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_BANK_FIELD); - if (!obj_desc) { - return (AE_NO_MEMORY); - } - - /* Obj_desc and Region valid */ - - /* Initialize areas of the object that are common to all fields */ - - status = acpi_aml_prep_common_field_object (obj_desc, field_flags, field_attribute, - field_position, field_length); - if (ACPI_FAILURE (status)) { - return (status); - } - - /* Initialize areas of the object that are specific to this field type */ - - obj_desc->bank_field.value = bank_val; - obj_desc->bank_field.container = acpi_ns_get_attached_object (region); - obj_desc->bank_field.bank_select = acpi_ns_get_attached_object (bank_reg); - - /* An additional reference for the container and bank select */ - /* TBD: [Restructure] is "Bank_select" ever a real internal object?? */ - - acpi_cm_add_reference (obj_desc->bank_field.container); - acpi_cm_add_reference (obj_desc->bank_field.bank_select); - - /* Debug info */ - - /* - * Store the constructed descriptor (Obj_desc) into the Named_obj whose - * handle is on TOS, preserving the current type of that Named_obj. - */ - status = acpi_ns_attach_object ((ACPI_HANDLE) node, obj_desc, - (u8) acpi_ns_get_type ((ACPI_HANDLE) node)); - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_prep_index_field_value - * - * PARAMETERS: Node - Owning Node - * Index_reg - Index register - * Data_reg - Data register - * Field_flags - Access, Lock_rule, or Update_rule - * Field_position - Field position - * Field_length - Field length - * - * RETURN: Status - * - * DESCRIPTION: Construct an ACPI_OPERAND_OBJECT of type Index_field and - * connect it to the parent Node. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_prep_index_field_value ( - ACPI_NAMESPACE_NODE *node, - ACPI_HANDLE index_reg, - ACPI_HANDLE data_reg, - u8 field_flags, - u8 field_attribute, - u32 field_position, - u32 field_length) -{ - ACPI_OPERAND_OBJECT *obj_desc; - ACPI_STATUS status; - - - /* Parameter validation */ - - if (!index_reg || !data_reg) { - return (AE_AML_NO_OPERAND); - } - - /* Allocate a new object descriptor */ - - obj_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_INDEX_FIELD); - if (!obj_desc) { - return (AE_NO_MEMORY); - } - - /* Initialize areas of the object that are common to all fields */ - - status = acpi_aml_prep_common_field_object (obj_desc, field_flags, field_attribute, - field_position, field_length); - if (ACPI_FAILURE (status)) { - return (status); - } - - /* Initialize areas of the object that are specific to this field type */ - - obj_desc->index_field.value = (u32) (field_position / - obj_desc->field.granularity); - obj_desc->index_field.index = index_reg; - obj_desc->index_field.data = data_reg; - - /* Debug info */ - - /* - * Store the constructed descriptor (Obj_desc) into the Named_obj whose - * handle is on TOS, preserving the current type of that Named_obj. - */ - status = acpi_ns_attach_object ((ACPI_HANDLE) node, obj_desc, - (u8) acpi_ns_get_type ((ACPI_HANDLE) node)); - - return (status); -} - diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/interpreter/amregion.c linux/drivers/acpi/interpreter/amregion.c --- v2.4.5/linux/drivers/acpi/interpreter/amregion.c Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/interpreter/amregion.c Wed Dec 31 16:00:00 1969 @@ -1,420 +0,0 @@ - -/****************************************************************************** - * - * Module Name: amregion - ACPI default Op_region (address space) handlers - * $Revision: 44 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "acpi.h" -#include "acinterp.h" -#include "amlcode.h" -#include "acnamesp.h" -#include "achware.h" -#include "acevents.h" - - -#define _COMPONENT INTERPRETER - MODULE_NAME ("amregion") - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_system_memory_space_handler - * - * PARAMETERS: Function - Read or Write operation - * Address - Where in the space to read or write - * Bit_width - Field width in bits (8, 16, or 32) - * Value - Pointer to in or out value - * Handler_context - Pointer to Handler's context - * Region_context - Pointer to context specific to the - * accessed region - * - * RETURN: Status - * - * DESCRIPTION: Handler for the System Memory address space (Op Region) - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_system_memory_space_handler ( - u32 function, - ACPI_PHYSICAL_ADDRESS address, - u32 bit_width, - u32 *value, - void *handler_context, - void *region_context) -{ - ACPI_STATUS status = AE_OK; - void *logical_addr_ptr = NULL; - MEM_HANDLER_CONTEXT *mem_info = region_context; - u32 length; - - - /* Validate and translate the bit width */ - - switch (bit_width) - { - case 8: - length = 1; - break; - - case 16: - length = 2; - break; - - case 32: - length = 4; - break; - - default: - return (AE_AML_OPERAND_VALUE); - break; - } - - - /* - * Does the request fit into the cached memory mapping? - * Is 1) Address below the current mapping? OR - * 2) Address beyond the current mapping? - */ - - if ((address < mem_info->mapped_physical_address) || - (((ACPI_INTEGER) address + length) > - ((ACPI_INTEGER) mem_info->mapped_physical_address + mem_info->mapped_length))) - { - /* - * The request cannot be resolved by the current memory mapping; - * Delete the existing mapping and create a new one. - */ - - if (mem_info->mapped_length) { - /* Valid mapping, delete it */ - - acpi_os_unmap_memory (mem_info->mapped_logical_address, - mem_info->mapped_length); - } - - mem_info->mapped_length = 0; /* In case of failure below */ - - /* Create a new mapping starting at the address given */ - - status = acpi_os_map_memory (address, SYSMEM_REGION_WINDOW_SIZE, - (void **) &mem_info->mapped_logical_address); - if (ACPI_FAILURE (status)) { - return (status); - } - - /* TBD: should these pointers go to 64-bit in all cases ? */ - - mem_info->mapped_physical_address = address; - mem_info->mapped_length = SYSMEM_REGION_WINDOW_SIZE; - } - - - /* - * Generate a logical pointer corresponding to the address we want to - * access - */ - - /* TBD: should these pointers go to 64-bit in all cases ? */ - - logical_addr_ptr = mem_info->mapped_logical_address + - ((ACPI_INTEGER) address - (ACPI_INTEGER) mem_info->mapped_physical_address); - - /* Perform the memory read or write */ - - switch (function) - { - - case ADDRESS_SPACE_READ: - - switch (bit_width) - { - case 8: - *value = (u32)* (u8 *) logical_addr_ptr; - break; - - case 16: - MOVE_UNALIGNED16_TO_32 (value, logical_addr_ptr); - break; - - case 32: - MOVE_UNALIGNED32_TO_32 (value, logical_addr_ptr); - break; - } - - break; - - - case ADDRESS_SPACE_WRITE: - - switch (bit_width) - { - case 8: - *(u8 *) logical_addr_ptr = (u8) *value; - break; - - case 16: - MOVE_UNALIGNED16_TO_16 (logical_addr_ptr, value); - break; - - case 32: - MOVE_UNALIGNED32_TO_32 (logical_addr_ptr, value); - break; - } - - break; - - - default: - status = AE_BAD_PARAMETER; - break; - } - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_system_io_space_handler - * - * PARAMETERS: Function - Read or Write operation - * Address - Where in the space to read or write - * Bit_width - Field width in bits (8, 16, or 32) - * Value - Pointer to in or out value - * Handler_context - Pointer to Handler's context - * Region_context - Pointer to context specific to the - * accessed region - * - * RETURN: Status - * - * DESCRIPTION: Handler for the System IO address space (Op Region) - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_system_io_space_handler ( - u32 function, - ACPI_PHYSICAL_ADDRESS address, - u32 bit_width, - u32 *value, - void *handler_context, - void *region_context) -{ - ACPI_STATUS status = AE_OK; - - - /* Decode the function parameter */ - - switch (function) - { - - case ADDRESS_SPACE_READ: - - switch (bit_width) - { - /* I/O Port width */ - - case 8: - *value = (u32) acpi_os_in8 ((ACPI_IO_ADDRESS) address); - break; - - case 16: - *value = (u32) acpi_os_in16 ((ACPI_IO_ADDRESS) address); - break; - - case 32: - *value = acpi_os_in32 ((ACPI_IO_ADDRESS) address); - break; - - default: - status = AE_AML_OPERAND_VALUE; - } - - break; - - - case ADDRESS_SPACE_WRITE: - - switch (bit_width) - { - /* I/O Port width */ - case 8: - acpi_os_out8 ((ACPI_IO_ADDRESS) address, (u8) *value); - break; - - case 16: - acpi_os_out16 ((ACPI_IO_ADDRESS) address, (u16) *value); - break; - - case 32: - acpi_os_out32 ((ACPI_IO_ADDRESS) address, *value); - break; - - default: - status = AE_AML_OPERAND_VALUE; - } - - break; - - - default: - status = AE_BAD_PARAMETER; - break; - } - - return (status); -} - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_pci_config_space_handler - * - * PARAMETERS: Function - Read or Write operation - * Address - Where in the space to read or write - * Bit_width - Field width in bits (8, 16, or 32) - * Value - Pointer to in or out value - * Handler_context - Pointer to Handler's context - * Region_context - Pointer to context specific to the - * accessed region - * - * RETURN: Status - * - * DESCRIPTION: Handler for the PCI Config address space (Op Region) - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_pci_config_space_handler ( - u32 function, - ACPI_PHYSICAL_ADDRESS address, - u32 bit_width, - u32 *value, - void *handler_context, - void *region_context) -{ - ACPI_STATUS status = AE_OK; - u32 pci_bus; - u32 dev_func; - u8 pci_reg; - PCI_HANDLER_CONTEXT *PCIcontext; - - - /* - * The arguments to Acpi_os(Read|Write)Pci_cfg(Byte|Word|Dword) are: - * - * Seg_bus - 0xSSSSBBBB - SSSS is the PCI bus segment - * BBBB is the PCI bus number - * - * Dev_func - 0xDDDDFFFF - DDDD is the PCI device number - * FFFF is the PCI device function number - * - * Reg_num - Config space register must be < 40h - * - * Value - input value for write, output for read - * - */ - - PCIcontext = (PCI_HANDLER_CONTEXT *) region_context; - - pci_bus = LOWORD(PCIcontext->seg) << 16; - pci_bus |= LOWORD(PCIcontext->bus); - - dev_func = PCIcontext->dev_func; - - pci_reg = (u8) address; - - switch (function) - { - - case ADDRESS_SPACE_READ: - - *value = 0; - - switch (bit_width) - { - /* PCI Register width */ - - case 8: - status = acpi_os_read_pci_cfg_byte (pci_bus, dev_func, pci_reg, - (u8 *) value); - break; - - case 16: - status = acpi_os_read_pci_cfg_word (pci_bus, dev_func, pci_reg, - (u16 *) value); - break; - - case 32: - status = acpi_os_read_pci_cfg_dword (pci_bus, dev_func, pci_reg, - value); - break; - - default: - status = AE_AML_OPERAND_VALUE; - - } /* Switch bit_width */ - - break; - - - case ADDRESS_SPACE_WRITE: - - switch (bit_width) - { - /* PCI Register width */ - - case 8: - status = acpi_os_write_pci_cfg_byte (pci_bus, dev_func, pci_reg, - *(u8 *) value); - break; - - case 16: - status = acpi_os_write_pci_cfg_word (pci_bus, dev_func, pci_reg, - *(u16 *) value); - break; - - case 32: - status = acpi_os_write_pci_cfg_dword (pci_bus, dev_func, pci_reg, - *value); - break; - - default: - status = AE_AML_OPERAND_VALUE; - - } /* Switch bit_width */ - - break; - - - default: - - status = AE_BAD_PARAMETER; - break; - - } - - return (status); -} - diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/interpreter/amresnte.c linux/drivers/acpi/interpreter/amresnte.c --- v2.4.5/linux/drivers/acpi/interpreter/amresnte.c Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/interpreter/amresnte.c Wed Dec 31 16:00:00 1969 @@ -1,509 +0,0 @@ - -/****************************************************************************** - * - * Module Name: amresnte - AML Interpreter object resolution - * $Revision: 27 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "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 INTERPRETER - MODULE_NAME ("amresnte") - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_resolve_node_to_value - * - * PARAMETERS: Stack_ptr - Pointer to a location on a stack that contains - * a pointer to an Node - * - * RETURN: Status - * - * DESCRIPTION: Resolve a ACPI_NAMESPACE_NODE (Node, - * A.K.A. a "direct name pointer") - * - * Note: for some of the data types, the pointer attached to the Node - * can be either a pointer to an actual internal object or a pointer into the - * AML stream itself. These types are currently: - * - * ACPI_TYPE_INTEGER - * ACPI_TYPE_STRING - * ACPI_TYPE_BUFFER - * ACPI_TYPE_MUTEX - * ACPI_TYPE_PACKAGE - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_resolve_node_to_value ( - ACPI_NAMESPACE_NODE **stack_ptr, - ACPI_WALK_STATE *walk_state) - -{ - ACPI_STATUS status = AE_OK; - ACPI_OPERAND_OBJECT *val_desc = NULL; - ACPI_OPERAND_OBJECT *obj_desc = NULL; - ACPI_NAMESPACE_NODE *node; - u8 *aml_pointer = NULL; - OBJECT_TYPE_INTERNAL entry_type; - u8 locked; - u8 attached_aml_pointer = FALSE; - u8 aml_opcode = 0; - ACPI_INTEGER temp_val; - OBJECT_TYPE_INTERNAL object_type; - - - node = *stack_ptr; - - - /* - * The stack pointer is a "Direct name ptr", and points to a - * a ACPI_NAMESPACE_NODE (Node). Get the pointer that is attached to - * the Node. - */ - - val_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) node); - entry_type = acpi_ns_get_type ((ACPI_HANDLE) node); - - /* - * The Val_desc attached to the Node can be either: - * 1) An internal ACPI object - * 2) A pointer into the AML stream (into one of the ACPI system tables) - */ - - if (acpi_tb_system_table_pointer (val_desc)) { - attached_aml_pointer = TRUE; - aml_opcode = *((u8 *) val_desc); - aml_pointer = ((u8 *) val_desc) + 1; - - } - - - /* - * Several Entry_types do not require further processing, so - * we will return immediately - */ - /* Devices rarely have an attached object, return the Node - * and Method locals and arguments have a pseudo-Node - */ - if (entry_type == ACPI_TYPE_DEVICE || - (node->flags & (ANOBJ_METHOD_ARG | ANOBJ_METHOD_LOCAL))) - { - return (AE_OK); - } - - if (!val_desc) { - return (AE_AML_NO_OPERAND); - } - - /* - * Action is based on the type of the Node, which indicates the type - * of the attached object or pointer - */ - switch (entry_type) - { - - case ACPI_TYPE_PACKAGE: - - if (attached_aml_pointer) { - /* - * This means that the package initialization is not parsed - * -- should not happen - */ - return (AE_NOT_IMPLEMENTED); - } - - /* Val_desc is an internal object in all cases by the time we get here */ - - if (ACPI_TYPE_PACKAGE != val_desc->common.type) { - return (AE_AML_OPERAND_TYPE); - } - - /* Return an additional reference to the object */ - - obj_desc = val_desc; - acpi_cm_add_reference (obj_desc); - break; - - - case ACPI_TYPE_BUFFER: - - if (attached_aml_pointer) { - /* - * This means that the buffer initialization is not parsed - * -- should not happen - */ - return (AE_NOT_IMPLEMENTED); - } - - /* Val_desc is an internal object in all cases by the time we get here */ - - if (ACPI_TYPE_BUFFER != val_desc->common.type) { - return (AE_AML_OPERAND_TYPE); - } - - /* Return an additional reference to the object */ - - obj_desc = val_desc; - acpi_cm_add_reference (obj_desc); - break; - - - case ACPI_TYPE_STRING: - - if (attached_aml_pointer) { - /* Allocate a new string object */ - - obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_STRING); - if (!obj_desc) { - return (AE_NO_MEMORY); - } - - /* Init the internal object */ - - obj_desc->string.pointer = (NATIVE_CHAR *) aml_pointer; - obj_desc->string.length = STRLEN (obj_desc->string.pointer); - } - - else { - if (ACPI_TYPE_STRING != val_desc->common.type) { - return (AE_AML_OPERAND_TYPE); - } - - /* Return an additional reference to the object */ - - obj_desc = val_desc; - acpi_cm_add_reference (obj_desc); - } - - break; - - - case ACPI_TYPE_INTEGER: - - /* - * The Node has an attached internal object, make sure that it's a - * number - */ - - if (ACPI_TYPE_INTEGER != val_desc->common.type) { - return (AE_AML_OPERAND_TYPE); - } - - /* Return an additional reference to the object */ - - obj_desc = val_desc; - acpi_cm_add_reference (obj_desc); - break; - - - case INTERNAL_TYPE_DEF_FIELD: - - /* - * TBD: [Investigate] Is this the correct solution? - * - * This section was extended to convert to generic buffer if - * the return length is greater than 32 bits, but still allows - * for returning a type Number for smaller values because the - * caller can then apply arithmetic operators on those fields. - * - * XXX - Implementation limitation: Fields are implemented as type - * XXX - Number, but they really are supposed to be type Buffer. - * XXX - The two are interchangeable only for lengths <= 32 bits. - */ - if(val_desc->field.length > 32) { - object_type = ACPI_TYPE_BUFFER; - } - else { - object_type = ACPI_TYPE_INTEGER; - } - - /* - * Create the destination buffer object and the buffer space. - */ - obj_desc = acpi_cm_create_internal_object (object_type); - if (!obj_desc) { - return (AE_NO_MEMORY); - } - - /* - * Fill in the object specific details - */ - if (ACPI_TYPE_BUFFER == object_type) { - obj_desc->buffer.pointer = acpi_cm_callocate (val_desc->field.length); - if (!obj_desc->buffer.pointer) { - acpi_cm_remove_reference(obj_desc); - return (AE_NO_MEMORY); - } - - obj_desc->buffer.length = val_desc->field.length; - - status = acpi_aml_access_named_field (ACPI_READ, (ACPI_HANDLE) node, - obj_desc->buffer.pointer, obj_desc->buffer.length); - - if (ACPI_FAILURE (status)) { - return (status); - } - } - else { - status = acpi_aml_access_named_field (ACPI_READ, (ACPI_HANDLE) node, - &temp_val, sizeof (temp_val)); - - if (ACPI_FAILURE (status)) { - return (status); - } - - obj_desc->integer.value = temp_val; - } - - - break; - - - case INTERNAL_TYPE_BANK_FIELD: - - if (attached_aml_pointer) { - return (AE_AML_OPERAND_TYPE); - } - - if (INTERNAL_TYPE_BANK_FIELD != val_desc->common.type) { - return (AE_AML_OPERAND_TYPE); - } - - - /* Get the global lock if needed */ - - obj_desc = (ACPI_OPERAND_OBJECT *) *stack_ptr; - locked = acpi_aml_acquire_global_lock (obj_desc->field_unit.lock_rule); - - /* Set Index value to select proper Data register */ - /* perform the update */ - - status = acpi_aml_access_named_field (ACPI_WRITE, - val_desc->bank_field.bank_select, &val_desc->bank_field.value, - sizeof (val_desc->bank_field.value)); - - acpi_aml_release_global_lock (locked); - - - if (ACPI_FAILURE (status)) { - return (status); - } - - /* Read Data value */ - - status = acpi_aml_access_named_field (ACPI_READ, - (ACPI_HANDLE) val_desc->bank_field.container, - &temp_val, sizeof (temp_val)); - if (ACPI_FAILURE (status)) { - return (status); - } - - /* Create an object for the result */ - - obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER); - if (!obj_desc) { - return (AE_NO_MEMORY); - } - - obj_desc->integer.value = temp_val; - break; - - - case INTERNAL_TYPE_INDEX_FIELD: - - if (attached_aml_pointer) { - return (AE_AML_OPERAND_TYPE); - } - - if (INTERNAL_TYPE_INDEX_FIELD != val_desc->common.type) { - return (AE_AML_OPERAND_TYPE); - } - - - /* Set Index value to select proper Data register */ - /* Get the global lock if needed */ - - obj_desc = (ACPI_OPERAND_OBJECT *) *stack_ptr; - locked = acpi_aml_acquire_global_lock (obj_desc->field_unit.lock_rule); - - /* Perform the update */ - - status = acpi_aml_access_named_field (ACPI_WRITE, - val_desc->index_field.index, &val_desc->index_field.value, - sizeof (val_desc->index_field.value)); - - acpi_aml_release_global_lock (locked); - - if (ACPI_FAILURE (status)) { - return (status); - } - - /* Read Data value */ - - status = acpi_aml_access_named_field (ACPI_READ, val_desc->index_field.data, - &temp_val, sizeof (temp_val)); - if (ACPI_FAILURE (status)) { - return (status); - } - - /* Create an object for the result */ - - obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER); - if (!obj_desc) { - return (AE_NO_MEMORY); - } - - obj_desc->integer.value = temp_val; - break; - - - case ACPI_TYPE_FIELD_UNIT: - - if (attached_aml_pointer) { - return (AE_AML_OPERAND_TYPE); - } - - if (val_desc->common.type != (u8) entry_type) { - return (AE_AML_OPERAND_TYPE); - break; - } - - /* Create object for result */ - - obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_ANY); - if (!obj_desc) { - return (AE_NO_MEMORY); - } - - status = acpi_aml_get_field_unit_value (val_desc, obj_desc); - if (ACPI_FAILURE (status)) { - acpi_cm_remove_reference (obj_desc); - return (status); - } - - break; - - - /* - * For these objects, just return the object attached to the Node - */ - - case ACPI_TYPE_MUTEX: - case ACPI_TYPE_METHOD: - case ACPI_TYPE_POWER: - case ACPI_TYPE_PROCESSOR: - case ACPI_TYPE_THERMAL: - case ACPI_TYPE_EVENT: - case ACPI_TYPE_REGION: - - - /* Return an additional reference to the object */ - - obj_desc = val_desc; - acpi_cm_add_reference (obj_desc); - break; - - - /* TYPE_Any is untyped, and thus there is no object associated with it */ - - case ACPI_TYPE_ANY: - - return (AE_AML_OPERAND_TYPE); /* Cannot be AE_TYPE */ - break; - - - /* - * The only named references allowed are named constants - * - * e.g. Name (\OSFL, Ones) - */ - case INTERNAL_TYPE_REFERENCE: - - switch (val_desc->reference.op_code) - { - - case AML_ZERO_OP: - - temp_val = 0; - break; - - - case AML_ONE_OP: - - temp_val = 1; - break; - - - case AML_ONES_OP: - - temp_val = ACPI_INTEGER_MAX; - break; - - - default: - - return (AE_AML_BAD_OPCODE); - } - - /* Create object for result */ - - obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER); - if (!obj_desc) { - return (AE_NO_MEMORY); - } - - obj_desc->integer.value = temp_val; - - /* Truncate value if we are executing from a 32-bit ACPI table */ - - acpi_aml_truncate_for32bit_table (obj_desc, walk_state); - break; - - - /* Default case is for unknown types */ - - default: - - return (AE_AML_OPERAND_TYPE); - - } /* switch (Entry_type) */ - - - /* Put the object descriptor on the stack */ - - *stack_ptr = (void *) obj_desc; - - return (status); -} - - diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/interpreter/amresolv.c linux/drivers/acpi/interpreter/amresolv.c --- v2.4.5/linux/drivers/acpi/interpreter/amresolv.c Mon Jan 29 10:15:59 2001 +++ linux/drivers/acpi/interpreter/amresolv.c Wed Dec 31 16:00:00 1969 @@ -1,465 +0,0 @@ - -/****************************************************************************** - * - * Module Name: amresolv - AML Interpreter object resolution - * $Revision: 81 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "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 INTERPRETER - MODULE_NAME ("amresolv") - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_get_field_unit_value - * - * PARAMETERS: *Field_desc - Pointer to a Field_unit - * *Result_desc - Pointer to an empty descriptor - * which will become a Number - * containing the field's value. - * - * RETURN: Status - * - * DESCRIPTION: Retrieve the value from a Field_unit - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_get_field_unit_value ( - ACPI_OPERAND_OBJECT *field_desc, - ACPI_OPERAND_OBJECT *result_desc) -{ - ACPI_STATUS status = AE_OK; - u32 mask; - u8 *location = NULL; - u8 locked = FALSE; - - - if (!field_desc) { - status = AE_AML_NO_OPERAND; - } - - if (!(field_desc->common.flags & AOPOBJ_DATA_VALID)) { - status = acpi_ds_get_field_unit_arguments (field_desc); - if (ACPI_FAILURE (status)) { - return (status); - } - } - - if (!field_desc->field_unit.container) { - status = AE_AML_INTERNAL; - } - - else if (ACPI_TYPE_BUFFER != field_desc->field_unit.container->common.type) { - status = AE_AML_OPERAND_TYPE; - } - - else if (!result_desc) { - status = AE_AML_INTERNAL; - } - - if (ACPI_FAILURE (status)) { - return (status); - } - - - /* Get the global lock if needed */ - - locked = acpi_aml_acquire_global_lock (field_desc->field_unit.lock_rule); - - /* Field location is (base of buffer) + (byte offset) */ - - location = field_desc->field_unit.container->buffer.pointer - + field_desc->field_unit.offset; - - /* - * Construct Mask with as many 1 bits as the field width - * - * NOTE: Only the bottom 5 bits are valid for a shift operation, so - * special care must be taken for any shift greater than 31 bits. - * - * TBD: [Unhandled] Fields greater than 32-bits will not work. - */ - - if (field_desc->field_unit.length < 32) { - mask = ((u32) 1 << field_desc->field_unit.length) - (u32) 1; - } - else { - mask = ACPI_UINT32_MAX; - } - - result_desc->integer.type = (u8) ACPI_TYPE_INTEGER; - - /* Get the 32 bit value at the location */ - - MOVE_UNALIGNED32_TO_32 (&result_desc->integer.value, location); - - /* - * Shift the 32-bit word containing the field, and mask off the - * resulting value - */ - - result_desc->integer.value = - (result_desc->integer.value >> field_desc->field_unit.bit_offset) & mask; - - /* Release global lock if we acquired it earlier */ - - acpi_aml_release_global_lock (locked); - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_resolve_to_value - * - * PARAMETERS: **Stack_ptr - Points to entry on Obj_stack, which can - * be either an (ACPI_OPERAND_OBJECT *) - * or an ACPI_HANDLE. - * - * RETURN: Status - * - * DESCRIPTION: Convert Reference objects to values - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_resolve_to_value ( - ACPI_OPERAND_OBJECT **stack_ptr, - ACPI_WALK_STATE *walk_state) -{ - ACPI_STATUS status = AE_OK; - - - if (!stack_ptr || !*stack_ptr) { - return (AE_AML_NO_OPERAND); - } - - - /* - * The entity pointed to by the Stack_ptr can be either - * 1) A valid ACPI_OPERAND_OBJECT, or - * 2) A ACPI_NAMESPACE_NODE (Named_obj) - */ - - if (VALID_DESCRIPTOR_TYPE (*stack_ptr, ACPI_DESC_TYPE_INTERNAL)) { - - status = acpi_aml_resolve_object_to_value (stack_ptr, walk_state); - if (ACPI_FAILURE (status)) { - return (status); - } - } - - /* - * Object on the stack may have changed if Acpi_aml_resolve_object_to_value() - * was called (i.e., we can't use an _else_ here.) - */ - - if (VALID_DESCRIPTOR_TYPE (*stack_ptr, ACPI_DESC_TYPE_NAMED)) { - status = acpi_aml_resolve_node_to_value ((ACPI_NAMESPACE_NODE **) stack_ptr, walk_state); - } - - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_resolve_object_to_value - * - * PARAMETERS: Stack_ptr - Pointer to a stack location that contains a - * ptr to an internal object. - * - * RETURN: Status - * - * DESCRIPTION: Retrieve the value from an internal object. The Reference type - * uses the associated AML opcode to determine the value. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_resolve_object_to_value ( - ACPI_OPERAND_OBJECT **stack_ptr, - ACPI_WALK_STATE *walk_state) -{ - ACPI_OPERAND_OBJECT *stack_desc; - ACPI_STATUS status = AE_OK; - ACPI_HANDLE temp_handle = NULL; - ACPI_OPERAND_OBJECT *obj_desc = NULL; - u32 index = 0; - u16 opcode; - - - stack_desc = *stack_ptr; - - /* This is an ACPI_OPERAND_OBJECT */ - - switch (stack_desc->common.type) - { - - case INTERNAL_TYPE_REFERENCE: - - opcode = stack_desc->reference.op_code; - - switch (opcode) - { - - case AML_NAME_OP: - - /* - * Convert indirect name ptr to a direct name ptr. - * Then, Acpi_aml_resolve_node_to_value can be used to get the value - */ - - temp_handle = stack_desc->reference.object; - - /* Delete the Reference Object */ - - acpi_cm_remove_reference (stack_desc); - - /* Put direct name pointer onto stack and exit */ - - (*stack_ptr) = temp_handle; - status = AE_OK; - break; - - - case AML_LOCAL_OP: - - index = stack_desc->reference.offset; - - /* - * Get the local from the method's state info - * Note: this increments the local's object reference count - */ - - status = acpi_ds_method_data_get_value (MTH_TYPE_LOCAL, index, - walk_state, &obj_desc); - if (ACPI_FAILURE (status)) { - return (status); - } - - /* - * Now we can delete the original Reference Object and - * replace it with the resolve value - */ - - acpi_cm_remove_reference (stack_desc); - *stack_ptr = obj_desc; - - if (ACPI_TYPE_INTEGER == obj_desc->common.type) { - /* Value is a Number */ - - } - - break; - - - case AML_ARG_OP: - - index = stack_desc->reference.offset; - - - /* - * Get the argument from the method's state info - * Note: this increments the object reference count - */ - - status = acpi_ds_method_data_get_value (MTH_TYPE_ARG, index, - walk_state, &obj_desc); - if (ACPI_FAILURE (status)) { - return (status); - } - - /* - * Now we can delete the original Reference Object and - * replace it with the resolve value - */ - - acpi_cm_remove_reference (stack_desc); - *stack_ptr = obj_desc; - - if (ACPI_TYPE_INTEGER == obj_desc->common.type) { - /* Value is a Number */ - - } - - break; - - - /* - * TBD: [Restructure] These next three opcodes change the type of - * the object, which is actually a no-no. - */ - - case AML_ZERO_OP: - - stack_desc->common.type = (u8) ACPI_TYPE_INTEGER; - stack_desc->integer.value = 0; - break; - - - case AML_ONE_OP: - - stack_desc->common.type = (u8) ACPI_TYPE_INTEGER; - stack_desc->integer.value = 1; - break; - - - case AML_ONES_OP: - - stack_desc->common.type = (u8) ACPI_TYPE_INTEGER; - stack_desc->integer.value = ACPI_INTEGER_MAX; - - /* Truncate value if we are executing from a 32-bit ACPI table */ - - acpi_aml_truncate_for32bit_table (stack_desc, walk_state); - break; - - - case AML_INDEX_OP: - - switch (stack_desc->reference.target_type) - { - case ACPI_TYPE_BUFFER_FIELD: - - /* Just return - leave the Reference on the stack */ - break; - - - case ACPI_TYPE_PACKAGE: - obj_desc = *stack_desc->reference.where; - if (obj_desc) { - /* - * Valid obj descriptor, copy pointer to return value - * (i.e., dereference the package index) - * Delete the ref object, increment the returned object - */ - acpi_cm_remove_reference (stack_desc); - acpi_cm_add_reference (obj_desc); - *stack_ptr = obj_desc; - } - - else { - /* - * A NULL object descriptor means an unitialized element of - * the package, can't deref it - */ - - status = AE_AML_UNINITIALIZED_ELEMENT; - } - break; - - default: - /* Invalid reference OBJ*/ - - status = AE_AML_INTERNAL; - break; - } - - break; - - - case AML_DEBUG_OP: - - /* Just leave the object as-is */ - break; - - - default: - - status = AE_AML_INTERNAL; - - } /* switch (Opcode) */ - - - if (ACPI_FAILURE (status)) { - return (status); - } - - break; /* case INTERNAL_TYPE_REFERENCE */ - - - case ACPI_TYPE_FIELD_UNIT: - - obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_ANY); - if (!obj_desc) { - /* Descriptor allocation failure */ - - return (AE_NO_MEMORY); - } - - status = acpi_aml_get_field_unit_value (stack_desc, obj_desc); - if (ACPI_FAILURE (status)) { - acpi_cm_remove_reference (obj_desc); - obj_desc = NULL; - } - - *stack_ptr = (void *) obj_desc; - break; - - - case INTERNAL_TYPE_BANK_FIELD: - - obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_ANY); - if (!obj_desc) { - /* Descriptor allocation failure */ - - return (AE_NO_MEMORY); - } - - status = acpi_aml_get_field_unit_value (stack_desc, obj_desc); - if (ACPI_FAILURE (status)) { - acpi_cm_remove_reference (obj_desc); - obj_desc = NULL; - } - - *stack_ptr = (void *) obj_desc; - break; - - - /* TBD: [Future] - may need to handle Index_field, and Def_field someday */ - - default: - - break; - - } /* switch (Stack_desc->Common.Type) */ - - - return (status); -} - - diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/interpreter/amresop.c linux/drivers/acpi/interpreter/amresop.c --- v2.4.5/linux/drivers/acpi/interpreter/amresop.c Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/interpreter/amresop.c Wed Dec 31 16:00:00 1969 @@ -1,488 +0,0 @@ - -/****************************************************************************** - * - * Module Name: amresop - AML Interpreter operand/object resolution - * $Revision: 22 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "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 INTERPRETER - MODULE_NAME ("amresop") - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_check_object_type - * - * PARAMETERS: Type_needed Object type needed - * This_type Actual object type - * Object Object pointer - * - * RETURN: Status - * - * DESCRIPTION: Check required type against actual type - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_check_object_type ( - ACPI_OBJECT_TYPE type_needed, - ACPI_OBJECT_TYPE this_type, - void *object) -{ - - - if (type_needed == ACPI_TYPE_ANY) { - /* All types OK, so we don't perform any typechecks */ - - return (AE_OK); - } - - - if (type_needed != this_type) { - return (AE_AML_OPERAND_TYPE); - } - - - return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_resolve_operands - * - * PARAMETERS: Opcode Opcode being interpreted - * Stack_ptr Top of operand stack - * - * RETURN: Status - * - * DESCRIPTION: Convert stack entries to required types - * - * Each nibble in Arg_types represents one required operand - * and indicates the required Type: - * - * The corresponding stack entry will be converted to the - * required type if possible, else return an exception - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_resolve_operands ( - u16 opcode, - ACPI_OPERAND_OBJECT **stack_ptr, - ACPI_WALK_STATE *walk_state) -{ - ACPI_OPERAND_OBJECT *obj_desc; - ACPI_STATUS status = AE_OK; - u8 object_type; - ACPI_HANDLE temp_handle; - u32 arg_types; - ACPI_OPCODE_INFO *op_info; - u32 this_arg_type; - ACPI_OBJECT_TYPE type_needed; - - - op_info = acpi_ps_get_opcode_info (opcode); - if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) { - return (AE_AML_BAD_OPCODE); - } - - - arg_types = op_info->runtime_args; - if (arg_types == ARGI_INVALID_OPCODE) { - return (AE_AML_INTERNAL); - } - - - /* - * Normal exit is with *Types == '\0' at end of string. - * Function will return an exception from within the loop upon - * finding an entry which is not, and cannot be converted - * to, the required type; if stack underflows; or upon - * finding a NULL stack entry (which "should never happen"). - */ - - while (GET_CURRENT_ARG_TYPE (arg_types)) { - if (!stack_ptr || !*stack_ptr) { - return (AE_AML_INTERNAL); - } - - /* Extract useful items */ - - obj_desc = *stack_ptr; - - /* Decode the descriptor type */ - - if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { - /* Node */ - - object_type = ((ACPI_NAMESPACE_NODE *) obj_desc)->type; - } - - else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_INTERNAL)) { - /* ACPI internal object */ - - object_type = obj_desc->common.type; - - /* Check for bad ACPI_OBJECT_TYPE */ - - if (!acpi_aml_validate_object_type (object_type)) { - return (AE_AML_OPERAND_TYPE); - } - - if (object_type == (u8) INTERNAL_TYPE_REFERENCE) { - /* - * Decode the Reference - */ - - op_info = acpi_ps_get_opcode_info (opcode); - if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) { - return (AE_AML_BAD_OPCODE); - } - - - switch (obj_desc->reference.op_code) - { - case AML_ZERO_OP: - case AML_ONE_OP: - case AML_ONES_OP: - case AML_DEBUG_OP: - case AML_NAME_OP: - case AML_INDEX_OP: - case AML_ARG_OP: - case AML_LOCAL_OP: - - break; - - default: - return (AE_AML_OPERAND_TYPE); - break; - } - } - } - - else { - /* Invalid descriptor */ - - return (AE_AML_OPERAND_TYPE); - } - - - /* - * Get one argument type, point to the next - */ - - this_arg_type = GET_CURRENT_ARG_TYPE (arg_types); - INCREMENT_ARG_LIST (arg_types); - - - /* - * Handle cases where the object does not need to be - * resolved to a value - */ - - switch (this_arg_type) - { - - case ARGI_REFERENCE: /* References */ - case ARGI_INTEGER_REF: - case ARGI_OBJECT_REF: - case ARGI_DEVICE_REF: - case ARGI_TARGETREF: /* TBD: must implement implicit conversion rules before store */ - case ARGI_FIXED_TARGET: /* No implicit conversion before store to target */ - case ARGI_SIMPLE_TARGET: /* Name, Local, or Arg - no implicit conversion */ - - /* Need an operand of type INTERNAL_TYPE_REFERENCE */ - - if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) /* direct name ptr OK as-is */ { - goto next_operand; - } - - status = acpi_aml_check_object_type (INTERNAL_TYPE_REFERENCE, - object_type, obj_desc); - if (ACPI_FAILURE (status)) { - return (status); - } - - - if (AML_NAME_OP == obj_desc->reference.op_code) { - /* - * Convert an indirect name ptr to direct name ptr and put - * it on the stack - */ - - temp_handle = obj_desc->reference.object; - acpi_cm_remove_reference (obj_desc); - (*stack_ptr) = temp_handle; - } - - goto next_operand; - break; - - - case ARGI_ANYTYPE: - - /* - * We don't want to resolve Index_op reference objects during - * a store because this would be an implicit De_ref_of operation. - * Instead, we just want to store the reference object. - * -- All others must be resolved below. - */ - - if ((opcode == AML_STORE_OP) && - ((*stack_ptr)->common.type == INTERNAL_TYPE_REFERENCE) && - ((*stack_ptr)->reference.op_code == AML_INDEX_OP)) - { - goto next_operand; - } - break; - } - - - /* - * Resolve this object to a value - */ - - status = acpi_aml_resolve_to_value (stack_ptr, walk_state); - if (ACPI_FAILURE (status)) { - return (status); - } - - - /* - * Check the resulting object (value) type - */ - switch (this_arg_type) - { - /* - * For the simple cases, only one type of resolved object - * is allowed - */ - case ARGI_MUTEX: - - /* Need an operand of type ACPI_TYPE_MUTEX */ - - type_needed = ACPI_TYPE_MUTEX; - break; - - case ARGI_EVENT: - - /* Need an operand of type ACPI_TYPE_EVENT */ - - type_needed = ACPI_TYPE_EVENT; - break; - - case ARGI_REGION: - - /* Need an operand of type ACPI_TYPE_REGION */ - - type_needed = ACPI_TYPE_REGION; - break; - - case ARGI_IF: /* If */ - - /* Need an operand of type INTERNAL_TYPE_IF */ - - type_needed = INTERNAL_TYPE_IF; - break; - - case ARGI_PACKAGE: /* Package */ - - /* Need an operand of type ACPI_TYPE_PACKAGE */ - - type_needed = ACPI_TYPE_PACKAGE; - break; - - case ARGI_ANYTYPE: - - /* Any operand type will do */ - - type_needed = ACPI_TYPE_ANY; - break; - - - /* - * The more complex cases allow multiple resolved object types - */ - - case ARGI_INTEGER: /* Number */ - - /* - * Need an operand of type ACPI_TYPE_INTEGER, - * But we can implicitly convert from a STRING or BUFFER - */ - status = acpi_aml_convert_to_integer (stack_ptr, walk_state); - if (ACPI_FAILURE (status)) { - if (status == AE_TYPE) { - return (AE_AML_OPERAND_TYPE); - } - - return (status); - } - - goto next_operand; - break; - - - case ARGI_BUFFER: - - /* - * Need an operand of type ACPI_TYPE_BUFFER, - * But we can implicitly convert from a STRING or INTEGER - */ - status = acpi_aml_convert_to_buffer (stack_ptr, walk_state); - if (ACPI_FAILURE (status)) { - if (status == AE_TYPE) { - return (AE_AML_OPERAND_TYPE); - } - - return (status); - } - - goto next_operand; - break; - - - case ARGI_STRING: - - /* - * Need an operand of type ACPI_TYPE_STRING, - * But we can implicitly convert from a BUFFER or INTEGER - */ - status = acpi_aml_convert_to_string (stack_ptr, walk_state); - if (ACPI_FAILURE (status)) { - if (status == AE_TYPE) { - return (AE_AML_OPERAND_TYPE); - } - - return (status); - } - - goto next_operand; - break; - - - case ARGI_COMPUTEDATA: - - /* Need an operand of type INTEGER, STRING or BUFFER */ - - if ((ACPI_TYPE_INTEGER != (*stack_ptr)->common.type) && - (ACPI_TYPE_STRING != (*stack_ptr)->common.type) && - (ACPI_TYPE_BUFFER != (*stack_ptr)->common.type)) - { - return (AE_AML_OPERAND_TYPE); - } - goto next_operand; - break; - - - case ARGI_DATAOBJECT: - /* - * ARGI_DATAOBJECT is only used by the Size_of operator. - * - * The ACPI specification allows Size_of to return the size of - * a Buffer, String or Package. However, the MS ACPI.SYS AML - * Interpreter also allows an Node reference to return without - * error with a size of 4. - */ - - /* Need a buffer, string, package or Node reference */ - - if (((*stack_ptr)->common.type != ACPI_TYPE_BUFFER) && - ((*stack_ptr)->common.type != ACPI_TYPE_STRING) && - ((*stack_ptr)->common.type != ACPI_TYPE_PACKAGE) && - ((*stack_ptr)->common.type != INTERNAL_TYPE_REFERENCE)) - { - return (AE_AML_OPERAND_TYPE); - } - - /* - * If this is a reference, only allow a reference to an Node. - */ - if ((*stack_ptr)->common.type == INTERNAL_TYPE_REFERENCE) { - if (!(*stack_ptr)->reference.node) { - return (AE_AML_OPERAND_TYPE); - } - } - goto next_operand; - break; - - - case ARGI_COMPLEXOBJ: - - /* Need a buffer or package */ - - if (((*stack_ptr)->common.type != ACPI_TYPE_BUFFER) && - ((*stack_ptr)->common.type != ACPI_TYPE_PACKAGE)) - { - return (AE_AML_OPERAND_TYPE); - } - goto next_operand; - break; - - - default: - - /* Unknown type */ - - return (AE_BAD_PARAMETER); - } - - - /* - * Make sure that the original object was resolved to the - * required object type (Simple cases only). - */ - status = acpi_aml_check_object_type (type_needed, - (*stack_ptr)->common.type, *stack_ptr); - if (ACPI_FAILURE (status)) { - return (status); - } - - -next_operand: - /* - * If more operands needed, decrement Stack_ptr to point - * to next operand on stack - */ - if (GET_CURRENT_ARG_TYPE (arg_types)) { - stack_ptr--; - } - - } /* while (*Types) */ - - - return (status); -} - - diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/interpreter/amstore.c linux/drivers/acpi/interpreter/amstore.c --- v2.4.5/linux/drivers/acpi/interpreter/amstore.c Tue Mar 6 19:44:36 2001 +++ linux/drivers/acpi/interpreter/amstore.c Wed Dec 31 16:00:00 1969 @@ -1,578 +0,0 @@ - -/****************************************************************************** - * - * Module Name: amstore - AML Interpreter object store support - * $Revision: 123 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "acpi.h" -#include "acparser.h" -#include "acdispat.h" -#include "acinterp.h" -#include "amlcode.h" -#include "acnamesp.h" -#include "actables.h" - - -#define _COMPONENT INTERPRETER - MODULE_NAME ("amstore") - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_exec_store - * - * PARAMETERS: *Val_desc - Value to be stored - * *Dest_desc - Where to store it 0 Must be (ACPI_HANDLE) - * or an ACPI_OPERAND_OBJECT of type - * Reference; if the latter the descriptor - * will be either reused or deleted. - * - * RETURN: Status - * - * DESCRIPTION: Store the value described by Val_desc into the location - * described by Dest_desc. Called by various interpreter - * functions to store the result of an operation into - * the destination operand. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_exec_store ( - ACPI_OPERAND_OBJECT *val_desc, - ACPI_OPERAND_OBJECT *dest_desc, - ACPI_WALK_STATE *walk_state) -{ - ACPI_STATUS status = AE_OK; - ACPI_OPERAND_OBJECT *ref_desc = dest_desc; - - - /* Validate parameters */ - - if (!val_desc || !dest_desc) { - return (AE_AML_NO_OPERAND); - } - - /* Dest_desc can be either a namespace node or an ACPI object */ - - if (VALID_DESCRIPTOR_TYPE (dest_desc, ACPI_DESC_TYPE_NAMED)) { - /* - * Dest is a namespace node, - * Storing an object into a Name "container" - */ - status = acpi_aml_store_object_to_node (val_desc, - (ACPI_NAMESPACE_NODE *) dest_desc, walk_state); - - /* All done, that's it */ - - return (status); - } - - - /* Destination object must be an object of type Reference */ - - if (dest_desc->common.type != INTERNAL_TYPE_REFERENCE) { - /* Destination is not an Reference */ - - return (AE_AML_OPERAND_TYPE); - } - - - /* - * Examine the Reference opcode. These cases are handled: - * - * 1) Store to Name (Change the object associated with a name) - * 2) Store to an indexed area of a Buffer or Package - * 3) Store to a Method Local or Arg - * 4) Store to the debug object - * 5) Store to a constant -- a noop - */ - - switch (ref_desc->reference.op_code) - { - - case AML_NAME_OP: - - /* Storing an object into a Name "container" */ - - status = acpi_aml_store_object_to_node (val_desc, ref_desc->reference.object, - walk_state); - break; - - - case AML_INDEX_OP: - - /* Storing to an Index (pointer into a packager or buffer) */ - - status = acpi_aml_store_object_to_index (val_desc, ref_desc, walk_state); - break; - - - case AML_LOCAL_OP: - - status = acpi_ds_method_data_set_value (MTH_TYPE_LOCAL, - (ref_desc->reference.offset), val_desc, walk_state); - break; - - - case AML_ARG_OP: - - status = acpi_ds_method_data_set_value (MTH_TYPE_ARG, - (ref_desc->reference.offset), val_desc, walk_state); - break; - - - case AML_DEBUG_OP: - - /* - * Storing to the Debug object causes the value stored to be - * displayed and otherwise has no effect -- see ACPI Specification - * - * TBD: print known object types "prettier". - */ - - break; - - - case AML_ZERO_OP: - case AML_ONE_OP: - case AML_ONES_OP: - - /* - * Storing to a constant is a no-op -- see ACPI Specification - * Delete the reference descriptor, however - */ - break; - - - default: - - /* TBD: [Restructure] use object dump routine !! */ - - status = AE_AML_INTERNAL; - break; - - } /* switch (Ref_desc->Reference.Op_code) */ - - - /* Always delete the reference descriptor object */ - - if (ref_desc) { - acpi_cm_remove_reference (ref_desc); - } - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_store_object_to_index - * - * PARAMETERS: *Val_desc - Value to be stored - * *Node - Named object to receive the value - * - * RETURN: Status - * - * DESCRIPTION: Store the object to the named object. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_store_object_to_index ( - ACPI_OPERAND_OBJECT *val_desc, - ACPI_OPERAND_OBJECT *dest_desc, - ACPI_WALK_STATE *walk_state) -{ - ACPI_STATUS status = AE_OK; - ACPI_OPERAND_OBJECT *obj_desc; - u32 length; - u32 i; - u8 value = 0; - - - /* - * Destination must be a reference pointer, and - * must point to either a buffer or a package - */ - - switch (dest_desc->reference.target_type) - { - case ACPI_TYPE_PACKAGE: - /* - * Storing to a package element is not simple. The source must be - * evaluated and converted to the type of the destination and then the - * source is copied into the destination - we can't just point to the - * source object. - */ - if (dest_desc->reference.target_type == ACPI_TYPE_PACKAGE) { - /* - * The object at *(Dest_desc->Reference.Where) is the - * element within the package that is to be modified. - */ - obj_desc = *(dest_desc->reference.where); - if (obj_desc) { - /* - * If the Destination element is a package, we will delete - * that object and construct a new one. - * - * TBD: [Investigate] Should both the src and dest be required - * to be packages? - * && (Val_desc->Common.Type == ACPI_TYPE_PACKAGE) - */ - if (obj_desc->common.type == ACPI_TYPE_PACKAGE) { - /* - * Take away the reference for being part of a package and - * delete - */ - acpi_cm_remove_reference (obj_desc); - acpi_cm_remove_reference (obj_desc); - - obj_desc = NULL; - } - } - - if (!obj_desc) { - /* - * If the Obj_desc is NULL, it means that an uninitialized package - * element has been used as a destination (this is OK), therefore, - * we must create the destination element to match the type of the - * source element NOTE: Val_desc can be of any type. - */ - obj_desc = acpi_cm_create_internal_object (val_desc->common.type); - if (!obj_desc) { - return (AE_NO_MEMORY); - } - - /* - * If the source is a package, copy the source to the new dest - */ - if (ACPI_TYPE_PACKAGE == obj_desc->common.type) { - status = acpi_cm_copy_ipackage_to_ipackage (val_desc, obj_desc, walk_state); - if (ACPI_FAILURE (status)) { - acpi_cm_remove_reference (obj_desc); - return (status); - } - } - - /* - * Install the new descriptor into the package and add a - * reference to the newly created descriptor for now being - * part of the parent package - */ - - *(dest_desc->reference.where) = obj_desc; - acpi_cm_add_reference (obj_desc); - } - - if (ACPI_TYPE_PACKAGE != obj_desc->common.type) { - /* - * The destination element is not a package, so we need to - * convert the contents of the source (Val_desc) and copy into - * the destination (Obj_desc) - */ - status = acpi_aml_store_object_to_object (val_desc, obj_desc, - walk_state); - if (ACPI_FAILURE (status)) { - /* - * An error occurrered when copying the internal object - * so delete the reference. - */ - return (AE_AML_OPERAND_TYPE); - } - } - } - break; - - - case ACPI_TYPE_BUFFER_FIELD: - /* - * Storing into a buffer at a location defined by an Index. - * - * Each 8-bit element of the source object is written to the - * 8-bit Buffer Field of the Index destination object. - */ - - /* - * Set the Obj_desc to the destination object and type check. - */ - obj_desc = dest_desc->reference.object; - if (obj_desc->common.type != ACPI_TYPE_BUFFER) { - return (AE_AML_OPERAND_TYPE); - } - - /* - * The assignment of the individual elements will be slightly - * different for each source type. - */ - - switch (val_desc->common.type) - { - /* - * If the type is Integer, assign bytewise - * This loop to assign each of the elements is somewhat - * backward because of the Big Endian-ness of IA-64 - */ - case ACPI_TYPE_INTEGER: - length = sizeof (ACPI_INTEGER); - for (i = length; i != 0; i--) { - value = (u8)(val_desc->integer.value >> (MUL_8 (i - 1))); - obj_desc->buffer.pointer[dest_desc->reference.offset] = value; - } - break; - - /* - * If the type is Buffer, the Length is in the structure. - * Just loop through the elements and assign each one in turn. - */ - case ACPI_TYPE_BUFFER: - length = val_desc->buffer.length; - for (i = 0; i < length; i++) { - value = *(val_desc->buffer.pointer + i); - obj_desc->buffer.pointer[dest_desc->reference.offset] = value; - } - break; - - /* - * If the type is String, the Length is in the structure. - * Just loop through the elements and assign each one in turn. - */ - case ACPI_TYPE_STRING: - length = val_desc->string.length; - for (i = 0; i < length; i++) { - value = *(val_desc->string.pointer + i); - obj_desc->buffer.pointer[dest_desc->reference.offset] = value; - } - break; - - /* - * If source is not a valid type so return an error. - */ - default: - status = AE_AML_OPERAND_TYPE; - break; - } - break; - - - default: - status = AE_AML_OPERAND_TYPE; - break; - } - - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_store_object_to_node - * - * PARAMETERS: *Source_desc - Value to be stored - * *Node - Named object to receive the value - * - * RETURN: Status - * - * DESCRIPTION: Store the object to the named object. - * - * The Assignment of an object to a named object is handled here - * The val passed in will replace the current value (if any) - * with the input value. - * - * When storing into an object the data is converted to the - * target object type then stored in the object. This means - * that the target object type (for an initialized target) will - * not be changed by a store operation. - * - * NOTE: the global lock is acquired early. This will result - * in the global lock being held a bit longer. Also, if the - * function fails during set up we may get the lock when we - * don't really need it. I don't think we care. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_store_object_to_node ( - ACPI_OPERAND_OBJECT *source_desc, - ACPI_NAMESPACE_NODE *node, - ACPI_WALK_STATE *walk_state) -{ - ACPI_STATUS status = AE_OK; - ACPI_OPERAND_OBJECT *target_desc; - OBJECT_TYPE_INTERNAL target_type = ACPI_TYPE_ANY; - - - /* - * Assuming the parameters were already validated - */ - ACPI_ASSERT((node) && (source_desc)); - - - /* - * Get current type of the node, and object attached to Node - */ - target_type = acpi_ns_get_type (node); - target_desc = acpi_ns_get_attached_object (node); - - - /* - * Resolve the source object to an actual value - * (If it is a reference object) - */ - status = acpi_aml_resolve_object (&source_desc, target_type, walk_state); - if (ACPI_FAILURE (status)) { - return (status); - } - - - /* - * Do the actual store operation - */ - switch (target_type) - { - case INTERNAL_TYPE_DEF_FIELD: - - /* Raw data copy for target types Integer/String/Buffer */ - - status = acpi_aml_copy_data_to_named_field (source_desc, node); - break; - - - case ACPI_TYPE_INTEGER: - case ACPI_TYPE_STRING: - case ACPI_TYPE_BUFFER: - case INTERNAL_TYPE_BANK_FIELD: - case INTERNAL_TYPE_INDEX_FIELD: - case ACPI_TYPE_FIELD_UNIT: - - /* - * These target types are all of type Integer/String/Buffer, and - * therefore support implicit conversion before the store. - * - * Copy and/or convert the source object to a new target object - */ - status = acpi_aml_store_object (source_desc, target_type, &target_desc, walk_state); - if (ACPI_FAILURE (status)) { - return (status); - } - - /* - * Store the new Target_desc as the new value of the Name, and set - * the Name's type to that of the value being stored in it. - * Source_desc reference count is incremented by Attach_object. - */ - status = acpi_ns_attach_object (node, target_desc, target_type); - break; - - - default: - - /* No conversions for all other types. Just attach the source object */ - - status = acpi_ns_attach_object (node, source_desc, source_desc->common.type); - - break; - } - - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_store_object_to_object - * - * PARAMETERS: *Source_desc - Value to be stored - * *Dest_desc - Object to receive the value - * - * RETURN: Status - * - * DESCRIPTION: Store an object to another object. - * - * The Assignment of an object to another (not named) object - * is handled here. - * The val passed in will replace the current value (if any) - * with the input value. - * - * When storing into an object the data is converted to the - * target object type then stored in the object. This means - * that the target object type (for an initialized target) will - * not be changed by a store operation. - * - * This module allows destination types of Number, String, - * and Buffer. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_store_object_to_object ( - ACPI_OPERAND_OBJECT *source_desc, - ACPI_OPERAND_OBJECT *dest_desc, - ACPI_WALK_STATE *walk_state) -{ - ACPI_STATUS status = AE_OK; - OBJECT_TYPE_INTERNAL destination_type = dest_desc->common.type; - - - /* - * Assuming the parameters are valid! - */ - ACPI_ASSERT((dest_desc) && (source_desc)); - - - /* - * From this interface, we only support Integers/Strings/Buffers - */ - switch (destination_type) - { - case ACPI_TYPE_INTEGER: - case ACPI_TYPE_STRING: - case ACPI_TYPE_BUFFER: - break; - - default: - return (AE_NOT_IMPLEMENTED); - } - - - /* - * Resolve the source object to an actual value - * (If it is a reference object) - */ - status = acpi_aml_resolve_object (&source_desc, destination_type, walk_state); - if (ACPI_FAILURE (status)) { - return (status); - } - - - /* - * Copy and/or convert the source object to the destination object - */ - status = acpi_aml_store_object (source_desc, destination_type, &dest_desc, walk_state); - - - return (status); -} - diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/interpreter/amstoren.c linux/drivers/acpi/interpreter/amstoren.c --- v2.4.5/linux/drivers/acpi/interpreter/amstoren.c Mon Jan 29 10:15:59 2001 +++ linux/drivers/acpi/interpreter/amstoren.c Wed Dec 31 16:00:00 1969 @@ -1,262 +0,0 @@ - -/****************************************************************************** - * - * Module Name: amstoren - AML Interpreter object store support, - * Store to Node (namespace object) - * $Revision: 28 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "acpi.h" -#include "acparser.h" -#include "acdispat.h" -#include "acinterp.h" -#include "amlcode.h" -#include "acnamesp.h" -#include "actables.h" - - -#define _COMPONENT INTERPRETER - MODULE_NAME ("amstoren") - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_resolve_object - * - * PARAMETERS: Source_desc_ptr - Pointer to the source object - * Target_type - Current type of the target - * Walk_state - Current walk state - * - * RETURN: Status, resolved object in Source_desc_ptr. - * - * DESCRIPTION: Resolve an object. If the object is a reference, dereference - * it and return the actual object in the Source_desc_ptr. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_resolve_object ( - ACPI_OPERAND_OBJECT **source_desc_ptr, - OBJECT_TYPE_INTERNAL target_type, - ACPI_WALK_STATE *walk_state) -{ - ACPI_OPERAND_OBJECT *source_desc = *source_desc_ptr; - ACPI_STATUS status = AE_OK; - - - /* - * Ensure we have a Source that can be stored in the target - */ - switch (target_type) - { - - /* This case handles the "interchangeable" types Integer, String, and Buffer. */ - - /* - * These cases all require only Integers or values that - * can be converted to Integers (Strings or Buffers) - */ - case ACPI_TYPE_INTEGER: - case ACPI_TYPE_FIELD_UNIT: - case INTERNAL_TYPE_BANK_FIELD: - case INTERNAL_TYPE_INDEX_FIELD: - - /* - * Stores into a Field/Region or into a Buffer/String - * are all essentially the same. - */ - case ACPI_TYPE_STRING: - case ACPI_TYPE_BUFFER: - case INTERNAL_TYPE_DEF_FIELD: - - /* - * If Source_desc is not a valid type, try to resolve it to one. - */ - if ((source_desc->common.type != ACPI_TYPE_INTEGER) && - (source_desc->common.type != ACPI_TYPE_BUFFER) && - (source_desc->common.type != ACPI_TYPE_STRING)) - { - /* - * Initially not a valid type, convert - */ - status = acpi_aml_resolve_to_value (source_desc_ptr, walk_state); - if (ACPI_SUCCESS (status) && - (source_desc->common.type != ACPI_TYPE_INTEGER) && - (source_desc->common.type != ACPI_TYPE_BUFFER) && - (source_desc->common.type != ACPI_TYPE_STRING)) - { - /* - * Conversion successful but still not a valid type - */ - status = AE_AML_OPERAND_TYPE; - } - } - break; - - - case INTERNAL_TYPE_ALIAS: - - /* - * Aliases are resolved by Acpi_aml_prep_operands - */ - status = AE_AML_INTERNAL; - break; - - - case ACPI_TYPE_PACKAGE: - default: - - /* - * All other types than Alias and the various Fields come here, - * including the untyped case - ACPI_TYPE_ANY. - */ - break; - } - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_store_object - * - * PARAMETERS: Source_desc - Object to store - * Target_type - Current type of the target - * Target_desc_ptr - Pointer to the target - * Walk_state - Current walk state - * - * RETURN: Status - * - * DESCRIPTION: "Store" an object to another object. This may include - * converting the source type to the target type (implicit - * conversion), and a copy of the value of the source to - * the target. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_store_object ( - ACPI_OPERAND_OBJECT *source_desc, - OBJECT_TYPE_INTERNAL target_type, - ACPI_OPERAND_OBJECT **target_desc_ptr, - ACPI_WALK_STATE *walk_state) -{ - ACPI_OPERAND_OBJECT *target_desc = *target_desc_ptr; - ACPI_STATUS status; - - - /* - * Perform the "implicit conversion" of the source to the current type - * of the target - As per the ACPI specification. - * - * If no conversion performed, Source_desc is left alone, otherwise it - * is updated with a new object. - */ - status = acpi_aml_convert_to_target_type (target_type, &source_desc, walk_state); - if (ACPI_FAILURE (status)) { - return (status); - } - - - /* - * We now have two objects of identical types, and we can perform a - * copy of the *value* of the source object. - */ - switch (target_type) - { - case ACPI_TYPE_ANY: - case INTERNAL_TYPE_DEF_ANY: - - /* - * The target namespace node is uninitialized (has no target object), - * and will take on the type of the source object - */ - - *target_desc_ptr = source_desc; - break; - - - case ACPI_TYPE_INTEGER: - - target_desc->integer.value = source_desc->integer.value; - - /* Truncate value if we are executing from a 32-bit ACPI table */ - - acpi_aml_truncate_for32bit_table (target_desc, walk_state); - break; - - - case ACPI_TYPE_FIELD_UNIT: - - status = acpi_aml_copy_integer_to_field_unit (source_desc, target_desc); - break; - - - case INTERNAL_TYPE_BANK_FIELD: - - status = acpi_aml_copy_integer_to_bank_field (source_desc, target_desc); - break; - - - case INTERNAL_TYPE_INDEX_FIELD: - - status = acpi_aml_copy_integer_to_index_field (source_desc, target_desc); - break; - - - case ACPI_TYPE_STRING: - - status = acpi_aml_copy_string_to_string (source_desc, target_desc); - break; - - - case ACPI_TYPE_BUFFER: - - status = acpi_aml_copy_buffer_to_buffer (source_desc, target_desc); - break; - - - case ACPI_TYPE_PACKAGE: - - /* - * TBD: [Unhandled] Not real sure what to do here - */ - status = AE_NOT_IMPLEMENTED; - break; - - - default: - - /* - * All other types come here. - */ - status = AE_NOT_IMPLEMENTED; - break; - } - - - return (status); -} - - diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/interpreter/amstorob.c linux/drivers/acpi/interpreter/amstorob.c --- v2.4.5/linux/drivers/acpi/interpreter/amstorob.c Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/interpreter/amstorob.c Wed Dec 31 16:00:00 1969 @@ -1,435 +0,0 @@ - -/****************************************************************************** - * - * Module Name: amstorob - AML Interpreter object store support, store to object - * $Revision: 23 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "acpi.h" -#include "acparser.h" -#include "acdispat.h" -#include "acinterp.h" -#include "amlcode.h" -#include "acnamesp.h" -#include "actables.h" - - -#define _COMPONENT INTERPRETER - MODULE_NAME ("amstorob") - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_copy_buffer_to_buffer - * - * PARAMETERS: Source_desc - Source object to copy - * Target_desc - Destination object of the copy - * - * RETURN: Status - * - * DESCRIPTION: Copy a buffer object to another buffer object. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_copy_buffer_to_buffer ( - ACPI_OPERAND_OBJECT *source_desc, - ACPI_OPERAND_OBJECT *target_desc) -{ - u32 length; - u8 *buffer; - - /* - * We know that Source_desc is a buffer by now - */ - buffer = (u8 *) source_desc->buffer.pointer; - length = source_desc->buffer.length; - - /* - * If target is a buffer of length zero, allocate a new - * buffer of the proper length - */ - if (target_desc->buffer.length == 0) { - target_desc->buffer.pointer = acpi_cm_allocate (length); - if (!target_desc->buffer.pointer) { - return (AE_NO_MEMORY); - } - - target_desc->buffer.length = length; - } - - /* - * Buffer is a static allocation, - * only place what will fit in the buffer. - */ - if (length <= target_desc->buffer.length) { - /* Clear existing buffer and copy in the new one */ - - MEMSET(target_desc->buffer.pointer, 0, target_desc->buffer.length); - MEMCPY(target_desc->buffer.pointer, buffer, length); - } - - else { - /* - * Truncate the source, copy only what will fit - */ - MEMCPY(target_desc->buffer.pointer, buffer, target_desc->buffer.length); - - } - - return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_copy_string_to_string - * - * PARAMETERS: Source_desc - Source object to copy - * Target_desc - Destination object of the copy - * - * RETURN: Status - * - * DESCRIPTION: Copy a String object to another String object - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_copy_string_to_string ( - ACPI_OPERAND_OBJECT *source_desc, - ACPI_OPERAND_OBJECT *target_desc) -{ - u32 length; - u8 *buffer; - - - /* - * We know that Source_desc is a string by now. - */ - buffer = (u8 *) source_desc->string.pointer; - length = source_desc->string.length; - - /* - * Setting a string value replaces the old string - */ - if (length < target_desc->string.length) { - /* Clear old string and copy in the new one */ - - MEMSET(target_desc->string.pointer, 0, target_desc->string.length); - MEMCPY(target_desc->string.pointer, buffer, length); - } - - else { - /* - * Free the current buffer, then allocate a buffer - * large enough to hold the value - */ - if (target_desc->string.pointer && - !acpi_tb_system_table_pointer (target_desc->string.pointer)) - { - /* - * Only free if not a pointer into the DSDT - */ - acpi_cm_free(target_desc->string.pointer); - } - - target_desc->string.pointer = acpi_cm_allocate (length + 1); - if (!target_desc->string.pointer) { - return (AE_NO_MEMORY); - } - target_desc->string.length = length; - - - MEMCPY(target_desc->string.pointer, buffer, length); - } - - return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_copy_integer_to_index_field - * - * PARAMETERS: Source_desc - Source object to copy - * Target_desc - Destination object of the copy - * - * RETURN: Status - * - * DESCRIPTION: Write an Integer to an Index Field - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_copy_integer_to_index_field ( - ACPI_OPERAND_OBJECT *source_desc, - ACPI_OPERAND_OBJECT *target_desc) -{ - ACPI_STATUS status; - u8 locked; - - - /* - * Get the global lock if needed - */ - locked = acpi_aml_acquire_global_lock (target_desc->index_field.lock_rule); - - /* - * Set Index value to select proper Data register - * perform the update (Set index) - */ - status = acpi_aml_access_named_field (ACPI_WRITE, - target_desc->index_field.index, - &target_desc->index_field.value, - sizeof (target_desc->index_field.value)); - if (ACPI_SUCCESS (status)) { - /* Set_index was successful, next set Data value */ - - status = acpi_aml_access_named_field (ACPI_WRITE, - target_desc->index_field.data, - &source_desc->integer.value, - sizeof (source_desc->integer.value)); - - } - - - - /* - * Release global lock if we acquired it earlier - */ - acpi_aml_release_global_lock (locked); - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_copy_integer_to_bank_field - * - * PARAMETERS: Source_desc - Source object to copy - * Target_desc - Destination object of the copy - * - * RETURN: Status - * - * DESCRIPTION: Write an Integer to a Bank Field - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_copy_integer_to_bank_field ( - ACPI_OPERAND_OBJECT *source_desc, - ACPI_OPERAND_OBJECT *target_desc) -{ - ACPI_STATUS status; - u8 locked; - - - /* - * Get the global lock if needed - */ - locked = acpi_aml_acquire_global_lock (target_desc->index_field.lock_rule); - - - /* - * Set Bank value to select proper Bank - * Perform the update (Set Bank Select) - */ - - status = acpi_aml_access_named_field (ACPI_WRITE, - target_desc->bank_field.bank_select, - &target_desc->bank_field.value, - sizeof (target_desc->bank_field.value)); - if (ACPI_SUCCESS (status)) { - /* Set bank select successful, set data value */ - - status = acpi_aml_access_named_field (ACPI_WRITE, - target_desc->bank_field.bank_select, - &source_desc->bank_field.value, - sizeof (source_desc->bank_field.value)); - } - - - - /* - * Release global lock if we acquired it earlier - */ - acpi_aml_release_global_lock (locked); - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_copy_data_to_named_field - * - * PARAMETERS: Source_desc - Source object to copy - * Node - Destination Namespace node - * - * RETURN: Status - * - * DESCRIPTION: Copy raw data to a Named Field. No implicit conversion - * is performed on the source object - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_copy_data_to_named_field ( - ACPI_OPERAND_OBJECT *source_desc, - ACPI_NAMESPACE_NODE *node) -{ - ACPI_STATUS status; - u8 locked; - u32 length; - u8 *buffer; - - - /* - * Named fields (Create_xxx_field) - We don't perform any conversions on the - * source operand, just use the raw data - */ - switch (source_desc->common.type) - { - case ACPI_TYPE_INTEGER: - buffer = (u8 *) &source_desc->integer.value; - length = sizeof (source_desc->integer.value); - break; - - case ACPI_TYPE_BUFFER: - buffer = (u8 *) source_desc->buffer.pointer; - length = source_desc->buffer.length; - break; - - case ACPI_TYPE_STRING: - buffer = (u8 *) source_desc->string.pointer; - length = source_desc->string.length; - break; - - default: - return (AE_TYPE); - } - - /* - * Get the global lock if needed before the update - * TBD: not needed! - */ - locked = acpi_aml_acquire_global_lock (source_desc->field.lock_rule); - - status = acpi_aml_access_named_field (ACPI_WRITE, - node, buffer, length); - - acpi_aml_release_global_lock (locked); - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_copy_integer_to_field_unit - * - * PARAMETERS: Source_desc - Source object to copy - * Target_desc - Destination object of the copy - * - * RETURN: Status - * - * DESCRIPTION: Write an Integer to a Field Unit. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_copy_integer_to_field_unit ( - ACPI_OPERAND_OBJECT *source_desc, - ACPI_OPERAND_OBJECT *target_desc) -{ - ACPI_STATUS status = AE_OK; - u8 *location = NULL; - u32 mask; - u32 new_value; - u8 locked = FALSE; - - - /* - * If the Field Buffer and Index have not been previously evaluated, - * evaluate them and save the results. - */ - if (!(target_desc->common.flags & AOPOBJ_DATA_VALID)) { - status = acpi_ds_get_field_unit_arguments (target_desc); - if (ACPI_FAILURE (status)) { - return (status); - } - } - - if ((!target_desc->field_unit.container || - ACPI_TYPE_BUFFER != target_desc->field_unit.container->common.type)) - { - return (AE_AML_INTERNAL); - } - - /* - * Get the global lock if needed - */ - locked = acpi_aml_acquire_global_lock (target_desc->field_unit.lock_rule); - - /* - * TBD: [Unhandled] REMOVE this limitation - * Make sure the operation is within the limits of our implementation - * this is not a Spec limitation!! - */ - if (target_desc->field_unit.length + target_desc->field_unit.bit_offset > 32) { - return (AE_NOT_IMPLEMENTED); - } - - /* Field location is (base of buffer) + (byte offset) */ - - location = target_desc->field_unit.container->buffer.pointer - + target_desc->field_unit.offset; - - /* - * Construct Mask with 1 bits where the field is, - * 0 bits elsewhere - */ - mask = ((u32) 1 << target_desc->field_unit.length) - ((u32)1 - << target_desc->field_unit.bit_offset); - - /* Zero out the field in the buffer */ - - MOVE_UNALIGNED32_TO_32 (&new_value, location); - new_value &= ~mask; - - /* - * Shift and mask the new value into position, - * and or it into the buffer. - */ - new_value |= (source_desc->integer.value << target_desc->field_unit.bit_offset) & - mask; - - /* Store back the value */ - - MOVE_UNALIGNED32_TO_32 (location, &new_value); - - return (AE_OK); -} - - diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/interpreter/amsystem.c linux/drivers/acpi/interpreter/amsystem.c --- v2.4.5/linux/drivers/acpi/interpreter/amsystem.c Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/interpreter/amsystem.c Wed Dec 31 16:00:00 1969 @@ -1,344 +0,0 @@ - -/****************************************************************************** - * - * Module Name: amsystem - Interface to OS services - * $Revision: 54 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "acpi.h" -#include "acinterp.h" -#include "acnamesp.h" -#include "achware.h" -#include "acevents.h" - -#define _COMPONENT INTERPRETER - MODULE_NAME ("amsystem") - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_system_thread_id - * - * PARAMETERS: None - * - * RETURN: Current Thread ID (for this implementation a 1 is returned) - * - * DESCRIPTION: An invocation is identified by its Thread ID. In a single - * threaded OS the Thread ID is undefined so a 1 will be - * returned. - * - ******************************************************************************/ - -u16 -acpi_aml_system_thread_id (void) -{ - return (1); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_system_wait_semaphore - * - * PARAMETERS: Semaphore - OSD semaphore to wait on - * Timeout - Max time to wait - * - * RETURN: Status - * - * DESCRIPTION: Implements a semaphore wait with a check to see if the - * semaphore is available immediately. If it is not, the - * interpreter is released. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_system_wait_semaphore ( - ACPI_HANDLE semaphore, - u32 timeout) -{ - ACPI_STATUS status; - - - status = acpi_os_wait_semaphore (semaphore, 1, 0); - if (ACPI_SUCCESS (status)) { - return (status); - } - - if (status == AE_TIME) { - /* We must wait, so unlock the interpreter */ - - acpi_aml_exit_interpreter (); - - status = acpi_os_wait_semaphore (semaphore, 1, timeout); - - /* Reacquire the interpreter */ - - acpi_aml_enter_interpreter (); - - } - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_system_do_stall - * - * PARAMETERS: How_long - The amount of time to stall - * - * RETURN: None - * - * DESCRIPTION: Suspend running thread for specified amount of time. - * - ******************************************************************************/ - -void -acpi_aml_system_do_stall ( - u32 how_long) -{ - - if (how_long > 1000) /* 1 millisecond */ { - /* Since this thread will sleep, we must release the interpreter */ - - acpi_aml_exit_interpreter (); - - acpi_os_sleep_usec (how_long); - - /* And now we must get the interpreter again */ - - acpi_aml_enter_interpreter (); - } - - else { - acpi_os_sleep_usec (how_long); - } -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_system_do_suspend - * - * PARAMETERS: How_long - The amount of time to suspend - * - * RETURN: None - * - * DESCRIPTION: Suspend running thread for specified amount of time. - * - ******************************************************************************/ - -void -acpi_aml_system_do_suspend ( - u32 how_long) -{ - /* Since this thread will sleep, we must release the interpreter */ - - acpi_aml_exit_interpreter (); - - acpi_os_sleep ((u16) (how_long / (u32) 1000), - (u16) (how_long % (u32) 1000)); - - /* And now we must get the interpreter again */ - - acpi_aml_enter_interpreter (); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_system_acquire_mutex - * - * PARAMETERS: *Time_desc - The 'time to delay' object descriptor - * *Obj_desc - The object descriptor for this op - * - * RETURN: Status - * - * DESCRIPTION: Provides an access point to perform synchronization operations - * within the AML. This function will cause a lock to be generated - * for the Mutex pointed to by Obj_desc. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_system_acquire_mutex ( - ACPI_OPERAND_OBJECT *time_desc, - ACPI_OPERAND_OBJECT *obj_desc) -{ - ACPI_STATUS status = AE_OK; - - - if (!obj_desc) { - return (AE_BAD_PARAMETER); - } - - /* - * Support for the _GL_ Mutex object -- go get the global lock - */ - - if (obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore) { - status = acpi_ev_acquire_global_lock (); - return (status); - } - - status = acpi_aml_system_wait_semaphore (obj_desc->mutex.semaphore, - (u32) time_desc->integer.value); - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_system_release_mutex - * - * PARAMETERS: *Obj_desc - The object descriptor for this op - * - * RETURN: Status - * - * DESCRIPTION: Provides an access point to perform synchronization operations - * within the AML. This operation is a request to release a - * previously acquired Mutex. If the Mutex variable is set then - * it will be decremented. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_system_release_mutex ( - ACPI_OPERAND_OBJECT *obj_desc) -{ - ACPI_STATUS status = AE_OK; - - - if (!obj_desc) { - return (AE_BAD_PARAMETER); - } - - /* - * 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 (AE_OK); - } - - status = acpi_os_signal_semaphore (obj_desc->mutex.semaphore, 1); - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_system_signal_event - * - * PARAMETERS: *Obj_desc - The object descriptor for this op - * - * RETURN: AE_OK - * - * DESCRIPTION: Provides an access point to perform synchronization operations - * within the AML. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_system_signal_event ( - ACPI_OPERAND_OBJECT *obj_desc) -{ - ACPI_STATUS status = AE_OK; - - - if (obj_desc) { - status = acpi_os_signal_semaphore (obj_desc->event.semaphore, 1); - } - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_system_wait_event - * - * PARAMETERS: *Time_desc - The 'time to delay' object descriptor - * *Obj_desc - The object descriptor for this op - * - * RETURN: Status - * - * DESCRIPTION: Provides an access point to perform synchronization operations - * within the AML. This operation is a request to wait for an - * event. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_system_wait_event ( - ACPI_OPERAND_OBJECT *time_desc, - ACPI_OPERAND_OBJECT *obj_desc) -{ - ACPI_STATUS status = AE_OK; - - - if (obj_desc) { - status = acpi_aml_system_wait_semaphore (obj_desc->event.semaphore, - (u32) time_desc->integer.value); - } - - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_system_reset_event - * - * PARAMETERS: *Obj_desc - The object descriptor for this op - * - * RETURN: Status - * - * DESCRIPTION: Provides an access point to perform synchronization operations - * within the AML. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_system_reset_event ( - ACPI_OPERAND_OBJECT *obj_desc) -{ - ACPI_STATUS status = AE_OK; - void *temp_semaphore; - - - /* - * We are going to simply delete the existing semaphore and - * create a new one! - */ - - status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT, 0, &temp_semaphore); - if (ACPI_SUCCESS (status)) { - acpi_os_delete_semaphore (obj_desc->mutex.semaphore); - obj_desc->mutex.semaphore = temp_semaphore; - } - - return (status); -} - diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/interpreter/amutils.c linux/drivers/acpi/interpreter/amutils.c --- v2.4.5/linux/drivers/acpi/interpreter/amutils.c Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/interpreter/amutils.c Wed Dec 31 16:00:00 1969 @@ -1,370 +0,0 @@ - -/****************************************************************************** - * - * Module Name: amutils - interpreter/scanner utilities - * $Revision: 69 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "acpi.h" -#include "acparser.h" -#include "acinterp.h" -#include "amlcode.h" -#include "acnamesp.h" -#include "acevents.h" - -#define _COMPONENT INTERPRETER - MODULE_NAME ("amutils") - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_enter_interpreter - * - * PARAMETERS: None - * - * DESCRIPTION: Enter the interpreter execution region - * - ******************************************************************************/ - -void -acpi_aml_enter_interpreter (void) -{ - - acpi_cm_acquire_mutex (ACPI_MTX_EXECUTE); - - return; -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_exit_interpreter - * - * PARAMETERS: None - * - * DESCRIPTION: Exit the interpreter execution region - * - * Cases where the interpreter is unlocked: - * 1) Completion of the execution of a control method - * 2) Method blocked on a Sleep() AML opcode - * 3) Method blocked on an Acquire() AML opcode - * 4) Method blocked on a Wait() AML opcode - * 5) Method blocked to acquire the global lock - * 6) Method blocked to execute a serialized control method that is - * already executing - * 7) About to invoke a user-installed opregion handler - * - ******************************************************************************/ - -void -acpi_aml_exit_interpreter (void) -{ - - acpi_cm_release_mutex (ACPI_MTX_EXECUTE); - - return; -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_validate_object_type - * - * PARAMETERS: Type Object type to validate - * - * DESCRIPTION: Determine if a type is a valid ACPI object type - * - ******************************************************************************/ - -u8 -acpi_aml_validate_object_type ( - ACPI_OBJECT_TYPE type) -{ - - if ((type > ACPI_TYPE_MAX && type < INTERNAL_TYPE_BEGIN) || - (type > INTERNAL_TYPE_MAX)) - { - return (FALSE); - } - - return (TRUE); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_truncate_for32bit_table - * - * PARAMETERS: Obj_desc - Object to be truncated - * Walk_state - Current walk state - * (A method must be executing) - * - * RETURN: none - * - * DESCRIPTION: Truncate a number to 32-bits if the currently executing method - * belongs to a 32-bit ACPI table. - * - ******************************************************************************/ - -void -acpi_aml_truncate_for32bit_table ( - ACPI_OPERAND_OBJECT *obj_desc, - ACPI_WALK_STATE *walk_state) -{ - - /* - * Object must be a valid number and we must be executing - * a control method - */ - - if ((!obj_desc) || - (obj_desc->common.type != ACPI_TYPE_INTEGER) || - (!walk_state->method_node)) - { - return; - } - - 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 - */ - obj_desc->integer.value &= (ACPI_INTEGER) ACPI_UINT32_MAX; - } -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_acquire_global_lock - * - * PARAMETERS: Rule - Lock rule: Always_lock, Never_lock - * - * RETURN: TRUE/FALSE indicating whether the lock was actually acquired - * - * DESCRIPTION: Obtain the global lock and keep track of this fact via two - * methods. A global variable keeps the state of the lock, and - * the state is returned to the caller. - * - ******************************************************************************/ - -u8 -acpi_aml_acquire_global_lock ( - u32 rule) -{ - u8 locked = FALSE; - ACPI_STATUS status; - - - /* Only attempt lock if the Rule says so */ - - if (rule == (u32) GLOCK_ALWAYS_LOCK) { - /* OK to get the lock */ - - status = acpi_ev_acquire_global_lock (); - - if (ACPI_SUCCESS (status)) { - acpi_gbl_global_lock_set = TRUE; - locked = TRUE; - } - } - - return (locked); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_release_global_lock - * - * PARAMETERS: Locked_by_me - Return value from corresponding call to - * Acquire_global_lock. - * - * RETURN: Status - * - * DESCRIPTION: Release the global lock if it is locked. - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_release_global_lock ( - u8 locked_by_me) -{ - - - /* Only attempt unlock if the caller locked it */ - - if (locked_by_me) { - /* Double check against the global flag */ - - if (acpi_gbl_global_lock_set) { - /* OK, now release the lock */ - - acpi_ev_release_global_lock (); - acpi_gbl_global_lock_set = FALSE; - } - - } - - - return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_digits_needed - * - * PARAMETERS: val - Value to be represented - * base - Base of representation - * - * RETURN: the number of digits needed to represent val in base - * - ******************************************************************************/ - -u32 -acpi_aml_digits_needed ( - ACPI_INTEGER val, - u32 base) -{ - u32 num_digits = 0; - - - if (base < 1) { - REPORT_ERROR (("Aml_digits_needed: Internal error - Invalid base\n")); - } - - else { - for (num_digits = 1 + (val < 0); (val = ACPI_DIVIDE (val,base)); ++num_digits) { ; } - } - - return (num_digits); -} - - -/******************************************************************************* - * - * 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; - - - 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_aml_eisa_id_to_string - * - * PARAMETERS: Numeric_id - EISA ID to be converted - * Out_string - Where to put the converted string (8 bytes) - * - * DESCRIPTION: Convert a numeric EISA ID to string representation - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_eisa_id_to_string ( - u32 numeric_id, - NATIVE_CHAR *out_string) -{ - u32 id; - - /* swap to big-endian to get contiguous bits */ - - id = _ntohl (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_gbl_hex_to_ascii[(id >> 12) & 0xf]; - out_string[4] = acpi_gbl_hex_to_ascii[(id >> 8) & 0xf]; - out_string[5] = acpi_gbl_hex_to_ascii[(id >> 4) & 0xf]; - out_string[6] = acpi_gbl_hex_to_ascii[id & 0xf]; - out_string[7] = 0; - - return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_unsigned_integer_to_string - * - * PARAMETERS: Value - Value to be converted - * Out_string - Where to put the converted string (8 bytes) - * - * RETURN: Convert a number to string representation - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_unsigned_integer_to_string ( - ACPI_INTEGER value, - NATIVE_CHAR *out_string) -{ - u32 count; - u32 digits_needed; - - - digits_needed = acpi_aml_digits_needed (value, 10); - - out_string[digits_needed] = '\0'; - - for (count = digits_needed; count > 0; count--) { - out_string[count-1] = (NATIVE_CHAR) ('0' + (ACPI_MODULO (value, 10))); - value = ACPI_DIVIDE (value, 10); - } - - return (AE_OK); -} - - diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/interpreter/amxface.c linux/drivers/acpi/interpreter/amxface.c --- v2.4.5/linux/drivers/acpi/interpreter/amxface.c Mon Jan 22 13:23:42 2001 +++ linux/drivers/acpi/interpreter/amxface.c Wed Dec 31 16:00:00 1969 @@ -1,95 +0,0 @@ - -/****************************************************************************** - * - * Module Name: amxface - External interpreter interfaces - * $Revision: 24 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * 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 "acpi.h" -#include "acinterp.h" - - -#define _COMPONENT INTERPRETER - MODULE_NAME ("amxface") - - -/* - * DEFINE_AML_GLOBALS is tested in amlcode.h - * to determine whether certain global names should be "defined" or only - * "declared" in the current compilation. This enhances maintainability - * by enabling a single header file to embody all knowledge of the names - * in question. - * - * Exactly one module of any executable should #define DEFINE_GLOBALS - * before #including the header files which use this convention. The - * names in question will be defined and initialized in that module, - * and declared as extern in all other modules which #include those - * header files. - */ - -#define DEFINE_AML_GLOBALS -#include "amlcode.h" -#include "acparser.h" -#include "acnamesp.h" - - -/******************************************************************************* - * - * FUNCTION: Acpi_aml_execute_method - * - * PARAMETERS: Pcode - Pointer to the pcode stream - * Pcode_length - Length of pcode that comprises the method - * **Params - List of parameters to pass to method, - * terminated by NULL. Params itself may be - * NULL if no parameters are being passed. - * - * RETURN: Status - * - * DESCRIPTION: Execute a control method - * - ******************************************************************************/ - -ACPI_STATUS -acpi_aml_execute_method ( - ACPI_NAMESPACE_NODE *method_node, - ACPI_OPERAND_OBJECT **params, - ACPI_OPERAND_OBJECT **return_obj_desc) -{ - ACPI_STATUS status; - - - /* - * The point here is to lock the interpreter and call the low - * level execute. - */ - - acpi_aml_enter_interpreter (); - - status = acpi_psx_execute (method_node, params, return_obj_desc); - - acpi_aml_exit_interpreter (); - - return (status); -} - - diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/namespace/Makefile linux/drivers/acpi/namespace/Makefile --- v2.4.5/linux/drivers/acpi/namespace/Makefile Fri Dec 29 14:07:21 2000 +++ linux/drivers/acpi/namespace/Makefile Wed Jun 20 17:47:40 2001 @@ -1,16 +1,12 @@ # # Makefile for all Linux ACPI interpreter subdirectories +# EXCEPT for the ospm directory # -O_TARGET := ../$(shell basename `pwd`).o +O_TARGET := $(notdir $(CURDIR)).o obj-$(CONFIG_ACPI) := $(patsubst %.c,%.o,$(wildcard *.c)) -EXTRA_CFLAGS += -I../include - EXTRA_CFLAGS += $(ACPI_CFLAGS) include $(TOPDIR)/Rules.make - -clean: - $(RM) *.o diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/namespace/nsaccess.c linux/drivers/acpi/namespace/nsaccess.c --- v2.4.5/linux/drivers/acpi/namespace/nsaccess.c Mon Jan 22 13:23:43 2001 +++ linux/drivers/acpi/namespace/nsaccess.c Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: nsaccess - Top-level functions for accessing ACPI namespace - * $Revision: 119 $ + * $Revision: 126 $ * ******************************************************************************/ @@ -31,7 +31,7 @@ #include "acdispat.h" -#define _COMPONENT NAMESPACE +#define _COMPONENT ACPI_NAMESPACE MODULE_NAME ("nsaccess") @@ -58,7 +58,7 @@ ACPI_OPERAND_OBJECT *obj_desc; - acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); /* * The global root ptr is initially NULL, so a non-NULL value indicates @@ -82,8 +82,7 @@ /* Enter the pre-defined names in the name table */ for (init_val = acpi_gbl_pre_defined_names; init_val->name; init_val++) { - status = acpi_ns_lookup (NULL, init_val->name, - (OBJECT_TYPE_INTERNAL) init_val->type, + status = acpi_ns_lookup (NULL, init_val->name, init_val->type, IMODE_LOAD_PASS2, NS_NO_UPSEARCH, NULL, &new_node); @@ -100,9 +99,7 @@ * descriptor for it. */ - obj_desc = acpi_cm_create_internal_object ( - (OBJECT_TYPE_INTERNAL) init_val->type); - + obj_desc = acpi_ut_create_internal_object (init_val->type); if (!obj_desc) { status = AE_NO_MEMORY; goto unlock_and_exit; @@ -114,8 +111,7 @@ * used for initial values are implemented here. */ - switch (init_val->type) - { + switch (init_val->type) { case ACPI_TYPE_INTEGER: @@ -126,18 +122,17 @@ case ACPI_TYPE_STRING: - obj_desc->string.length = - (u16) STRLEN (init_val->val); + obj_desc->string.length = STRLEN (init_val->val); /* * Allocate a buffer for the string. All * String.Pointers must be allocated buffers! * (makes deletion simpler) */ - obj_desc->string.pointer = acpi_cm_allocate ( + obj_desc->string.pointer = acpi_ut_allocate ( (obj_desc->string.length + 1)); if (!obj_desc->string.pointer) { - acpi_cm_remove_reference (obj_desc); + acpi_ut_remove_reference (obj_desc); status = AE_NO_MEMORY; goto unlock_and_exit; } @@ -149,7 +144,7 @@ case ACPI_TYPE_MUTEX: obj_desc->mutex.sync_level = - (u16) STRTOUL (init_val->val, NULL, 10); + (u16) STRTOUL (init_val->val, NULL, 10); if (STRCMP (init_val->name, "_GL_") == 0) { /* @@ -186,21 +181,20 @@ default: REPORT_ERROR (("Unsupported initial type value %X\n", init_val->type)); - acpi_cm_remove_reference (obj_desc); + acpi_ut_remove_reference (obj_desc); obj_desc = NULL; continue; } /* Store pointer to value descriptor in the Node */ - acpi_ns_attach_object (new_node, obj_desc, - obj_desc->common.type); + acpi_ns_attach_object (new_node, obj_desc, obj_desc->common.type); } } unlock_and_exit: - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return (status); } @@ -232,7 +226,7 @@ acpi_ns_lookup ( ACPI_GENERIC_STATE *scope_info, NATIVE_CHAR *pathname, - OBJECT_TYPE_INTERNAL type, + ACPI_OBJECT_TYPE8 type, OPERATING_MODE interpreter_mode, u32 flags, ACPI_WALK_STATE *walk_state, @@ -246,8 +240,8 @@ u32 num_segments; ACPI_NAME simple_name; u8 null_name_path = FALSE; - OBJECT_TYPE_INTERNAL type_to_check_for; - OBJECT_TYPE_INTERNAL this_search_type; + ACPI_OBJECT_TYPE8 type_to_check_for; + ACPI_OBJECT_TYPE8 this_search_type; u32 local_flags = flags & ~NS_ERROR_IF_FOUND; @@ -271,8 +265,7 @@ */ if ((!scope_info) || - (!scope_info->scope.node)) - { + (!scope_info->scope.node)) { prefix_node = acpi_gbl_root_node; } else { @@ -281,14 +274,14 @@ /* - * This check is explicitly split provide relax the Type_to_check_for + * This check is explicitly split to relax the Type_to_check_for * conditions for Bank_field_defn. Originally, both Bank_field_defn and * Def_field_defn caused Type_to_check_for to be set to ACPI_TYPE_REGION, * but the Bank_field_defn may also check for a Field definition as well * as an Operation_region. */ - if (INTERNAL_TYPE_DEF_FIELD_DEFN == type) { + if (INTERNAL_TYPE_FIELD_DEFN == type) { /* Def_field_defn defines fields in a Region */ type_to_check_for = ACPI_TYPE_REGION; @@ -376,7 +369,8 @@ if (!this_node) { /* Current scope has no parent scope */ - REPORT_ERROR (("Too many parent prefixes (^) - reached root\n")); + REPORT_ERROR ( + ("Too many parent prefixes (^) - reached root\n")); return (AE_NOT_FOUND); } @@ -480,8 +474,7 @@ (type_to_check_for != INTERNAL_TYPE_SCOPE) && (type_to_check_for != INTERNAL_TYPE_INDEX_FIELD_DEFN) && (this_node->type != ACPI_TYPE_ANY) && - (this_node->type != type_to_check_for)) - { + (this_node->type != type_to_check_for)) { /* Complain about a type mismatch */ REPORT_WARNING ( @@ -500,8 +493,7 @@ } if ((num_segments || acpi_ns_opens_scope (type)) && - (this_node->child == NULL)) - { + (this_node->child == NULL)) { /* * More segments or the type implies enclosed scope, * and the next scope has not been allocated. diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/namespace/nsalloc.c linux/drivers/acpi/namespace/nsalloc.c --- v2.4.5/linux/drivers/acpi/namespace/nsalloc.c Mon Jan 22 13:23:43 2001 +++ linux/drivers/acpi/namespace/nsalloc.c Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: nsalloc - Namespace allocation and deletion utilities - * $Revision: 45 $ + * $Revision: 50 $ * ******************************************************************************/ @@ -29,7 +29,7 @@ #include "acinterp.h" -#define _COMPONENT NAMESPACE +#define _COMPONENT ACPI_NAMESPACE MODULE_NAME ("nsalloc") @@ -52,7 +52,7 @@ ACPI_NAMESPACE_NODE *node; - node = acpi_cm_callocate (sizeof (ACPI_NAMESPACE_NODE)); + node = acpi_ut_callocate (sizeof (ACPI_NAMESPACE_NODE)); if (!node) { return (NULL); } @@ -119,7 +119,7 @@ acpi_ns_detach_object (node); } - acpi_cm_free (node); + acpi_ut_free (node); return; @@ -146,7 +146,7 @@ ACPI_WALK_STATE *walk_state, ACPI_NAMESPACE_NODE *parent_node, /* Parent */ ACPI_NAMESPACE_NODE *node, /* New Child*/ - OBJECT_TYPE_INTERNAL type) + ACPI_OBJECT_TYPE8 type) { u16 owner_id = TABLE_ID_DSDT; ACPI_NAMESPACE_NODE *child_node; @@ -195,27 +195,22 @@ * add the region in order to define fields in it, we * have a forward reference. */ - if ((ACPI_TYPE_ANY == type) || - (INTERNAL_TYPE_DEF_FIELD_DEFN == type) || - (INTERNAL_TYPE_BANK_FIELD_DEFN == type)) - { + (INTERNAL_TYPE_FIELD_DEFN == type) || + (INTERNAL_TYPE_BANK_FIELD_DEFN == type)) { /* * We don't want to abort here, however! * We will fill in the actual type when the * real definition is found later. */ - } /* * The Def_field_defn and Bank_field_defn cases are actually * looking up the Region in which the field will be defined */ - - if ((INTERNAL_TYPE_DEF_FIELD_DEFN == type) || - (INTERNAL_TYPE_BANK_FIELD_DEFN == type)) - { + if ((INTERNAL_TYPE_FIELD_DEFN == type) || + (INTERNAL_TYPE_BANK_FIELD_DEFN == type)) { type = ACPI_TYPE_REGION; } @@ -225,11 +220,9 @@ * being looked up. Save any other value of Type as the type of * the entry. */ - if ((type != INTERNAL_TYPE_SCOPE) && (type != INTERNAL_TYPE_DEF_ANY) && - (type != INTERNAL_TYPE_INDEX_FIELD_DEFN)) - { + (type != INTERNAL_TYPE_INDEX_FIELD_DEFN)) { node->type = (u8) type; } @@ -237,7 +230,6 @@ * Increment the reference count(s) of all parents up to * the root! */ - while ((node = acpi_ns_get_parent_object (node)) != NULL) { node->reference_count++; } @@ -282,8 +274,7 @@ /* * Deallocate all children at this level */ - do - { + do { /* Get the things we need */ next_node = child_node->peer; @@ -304,7 +295,7 @@ acpi_ns_detach_object (child_node); } - acpi_cm_free (child_node); + acpi_ut_free (child_node); /* And move on to the next child in the list */ @@ -373,7 +364,7 @@ obj_desc = acpi_ns_get_attached_object (child_node); if (obj_desc) { acpi_ns_detach_object (child_node); - acpi_cm_remove_reference (obj_desc); + acpi_ut_remove_reference (obj_desc); } @@ -519,7 +510,7 @@ obj_desc = acpi_ns_get_attached_object (child_node); if (obj_desc) { acpi_ns_detach_object (child_node); - acpi_cm_remove_reference (obj_desc); + acpi_ut_remove_reference (obj_desc); } } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/namespace/nseval.c linux/drivers/acpi/namespace/nseval.c --- v2.4.5/linux/drivers/acpi/namespace/nseval.c Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/namespace/nseval.c Wed Jun 20 17:47:40 2001 @@ -2,7 +2,7 @@ * * Module Name: nseval - Object evaluation interfaces -- includes control * method lookup and execution. - * $Revision: 83 $ + * $Revision: 91 $ * ******************************************************************************/ @@ -32,7 +32,7 @@ #include "acnamesp.h" -#define _COMPONENT NAMESPACE +#define _COMPONENT ACPI_NAMESPACE MODULE_NAME ("nseval") @@ -88,11 +88,11 @@ /* Get the prefix handle and Node */ - acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); prefix_node = acpi_ns_convert_handle_to_entry (handle); if (!prefix_node) { - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); status = AE_BAD_PARAMETER; goto cleanup; } @@ -104,7 +104,7 @@ IMODE_EXECUTE, NS_NO_UPSEARCH, NULL, &node); - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (status)) { goto cleanup; @@ -119,10 +119,7 @@ cleanup: - /* Cleanup */ - - acpi_cm_free (internal_path); - + acpi_ut_free (internal_path); return (status); } @@ -165,7 +162,7 @@ return (status); } - acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); /* Lookup the name in the namespace */ @@ -173,7 +170,7 @@ IMODE_EXECUTE, NS_NO_UPSEARCH, NULL, &node); - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (status)) { goto cleanup; @@ -192,7 +189,7 @@ /* Cleanup */ if (internal_path) { - acpi_cm_free (internal_path); + acpi_ut_free (internal_path); } return (status); @@ -249,11 +246,11 @@ /* Get the prefix handle and Node */ - acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); node = acpi_ns_convert_handle_to_entry (handle); if (!node) { - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return (AE_BAD_PARAMETER); } @@ -348,6 +345,15 @@ ACPI_OPERAND_OBJECT *obj_desc; + /* Verify that there is a method associated with this object */ + + obj_desc = acpi_ns_get_attached_object (method_node); + if (!obj_desc) { + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); + return (AE_ERROR); + } + + /* * Unlock the namespace before execution. This allows namespace access * via the external Acpi* interfaces while a method is being executed. @@ -355,21 +361,12 @@ * interpreter locks to ensure that no thread is using the portion of the * namespace that is being deleted. */ - - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); - - /* Verify that there is a method associated with this object */ - - obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) method_node); - if (!obj_desc) { - return (AE_ERROR); - } - + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); /* * Execute the method via the interpreter */ - status = acpi_aml_execute_method (method_node, params, return_obj_desc); + status = acpi_ex_execute_method (method_node, params, return_obj_desc); return (status); } @@ -404,12 +401,11 @@ */ if ((node->type == ACPI_TYPE_PROCESSOR) || - (node->type == ACPI_TYPE_POWER)) - { + (node->type == ACPI_TYPE_POWER)) { /* * Create a Reference object to contain the object */ - obj_desc = acpi_cm_create_internal_object (node->type); + obj_desc = acpi_ut_create_internal_object (node->type); if (!obj_desc) { status = AE_NO_MEMORY; goto unlock_and_exit; @@ -434,6 +430,7 @@ MEMCPY (obj_desc, val_desc, sizeof (ACPI_OPERAND_OBJECT)); obj_desc->common.reference_count = 1; + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); } @@ -444,7 +441,7 @@ else { /* Create an Reference object to contain the object */ - obj_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_REFERENCE); + obj_desc = acpi_ut_create_internal_object (INTERNAL_TYPE_REFERENCE); if (!obj_desc) { status = AE_NO_MEMORY; goto unlock_and_exit; @@ -452,32 +449,37 @@ /* Construct a descriptor pointing to the name */ - obj_desc->reference.op_code = (u8) AML_NAME_OP; + obj_desc->reference.opcode = (u8) AML_NAME_OP; obj_desc->reference.object = (void *) node; /* - * Use Acpi_aml_resolve_to_value() to get the associated value. - * The call to Acpi_aml_resolve_to_value causes - * Obj_desc (allocated above) to always be deleted. + * Use Resolve_to_value() to get the associated value. This call + * always deletes Obj_desc (allocated above). * * NOTE: we can get away with passing in NULL for a walk state * because Obj_desc is guaranteed to not be a reference to either * a method local or a method argument * - * Even though we do not technically need to use the interpreter - * for this, we must enter it because we could hit an opregion. - * The opregion access code assumes it is in the interpreter. + * Even though we do not directly invoke the interpreter + * for this, we must enter it because we could access an opregion. + * The opregion access code assumes that the interpreter + * is locked. + * + * We must release the namespace lock before entering the + * intepreter. */ - acpi_aml_enter_interpreter(); - - status = acpi_aml_resolve_to_value (&obj_desc, NULL); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); + status = acpi_ex_enter_interpreter (); + if (ACPI_SUCCESS (status)) { + status = acpi_ex_resolve_to_value (&obj_desc, NULL); - acpi_aml_exit_interpreter(); + acpi_ex_exit_interpreter (); + } } /* - * If Acpi_aml_resolve_to_value() succeeded, the return value was + * If Acpi_ex_resolve_to_value() succeeded, the return value was * placed in Obj_desc. */ @@ -487,11 +489,15 @@ *return_obj_desc = obj_desc; } + /* Namespace is unlocked */ + + return (status); + unlock_and_exit: /* Unlock the namespace */ - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return (status); } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/namespace/nsinit.c linux/drivers/acpi/namespace/nsinit.c --- v2.4.5/linux/drivers/acpi/namespace/nsinit.c Tue Mar 6 19:44:36 2001 +++ linux/drivers/acpi/namespace/nsinit.c Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: nsinit - namespace initialization - * $Revision: 15 $ + * $Revision: 25 $ * *****************************************************************************/ @@ -28,7 +28,7 @@ #include "acnamesp.h" #include "acdispat.h" -#define _COMPONENT NAMESPACE +#define _COMPONENT ACPI_NAMESPACE MODULE_NAME ("nsinit") @@ -70,7 +70,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ns_initialize_devices * @@ -81,11 +81,10 @@ * DESCRIPTION: Walk the entire namespace and initialize all ACPI devices. * This means running _INI on all present devices. * - * Also: Install PCI config space handler for all PCI root bridges. - * A PCI root bridge is found by searching for devices containing - * a HID with the value EISAID("PNP0A03") + * Note: We install PCI config space handler on region access, + * not here. * - *****************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_ns_initialize_devices ( @@ -100,8 +99,8 @@ info.num_INI = 0; - status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, - FALSE, acpi_ns_init_one_device, &info, NULL); + status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, FALSE, acpi_ns_init_one_device, &info, NULL); @@ -136,7 +135,7 @@ void *context, void **return_value) { - OBJECT_TYPE_INTERNAL type; + ACPI_OBJECT_TYPE8 type; ACPI_STATUS status; ACPI_INIT_WALK_INFO *info = (ACPI_INIT_WALK_INFO *) context; ACPI_NAMESPACE_NODE *node = (ACPI_NAMESPACE_NODE *) obj_handle; @@ -154,8 +153,7 @@ return (AE_OK); } - switch (type) - { + switch (type) { case ACPI_TYPE_REGION: @@ -171,7 +169,7 @@ break; - case ACPI_TYPE_FIELD_UNIT: + case ACPI_TYPE_BUFFER_FIELD: info->field_count++; if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { @@ -179,7 +177,7 @@ } info->field_init++; - status = acpi_ds_get_field_unit_arguments (obj_desc); + status = acpi_ds_get_buffer_field_arguments (obj_desc); break; @@ -196,11 +194,11 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ns_init_one_device * - * PARAMETERS: WALK_CALLBACK + * PARAMETERS: ACPI_WALK_CALLBACK * * RETURN: ACPI_STATUS * @@ -208,7 +206,7 @@ * to initialize each device. It determines if the device is * present, and if so, calls _INI. * - *****************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_ns_init_one_device ( @@ -226,21 +224,21 @@ info->device_count++; - acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); node = acpi_ns_convert_handle_to_entry (obj_handle); if (!node) { - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return (AE_BAD_PARAMETER); } - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); /* * Run _STA to determine if we can run _INI on the device. */ - status = acpi_cm_execute_STA (node, &flags); + status = acpi_ut_execute_STA (node, &flags); if (ACPI_FAILURE (status)) { /* Ignore error and move on to next device */ @@ -251,6 +249,7 @@ if (!(flags & 0x01)) { /* don't look at children of a not present device */ + return(AE_CTRL_DEPTH); } @@ -258,10 +257,10 @@ /* * The device is present. Run _INI. */ - status = acpi_ns_evaluate_relative (obj_handle, "_INI", NULL, NULL); if (AE_NOT_FOUND == status) { /* No _INI means device requires no initialization */ + status = AE_OK; } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/namespace/nsload.c linux/drivers/acpi/namespace/nsload.c --- v2.4.5/linux/drivers/acpi/namespace/nsload.c Mon Jan 22 13:23:43 2001 +++ linux/drivers/acpi/namespace/nsload.c Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: nsload - namespace loading/expanding/contracting procedures - * $Revision: 35 $ + * $Revision: 41 $ * *****************************************************************************/ @@ -33,11 +33,11 @@ #include "acdebug.h" -#define _COMPONENT NAMESPACE +#define _COMPONENT ACPI_NAMESPACE MODULE_NAME ("nsload") -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_load_namespace * @@ -107,8 +107,7 @@ ACPI_STATUS status; - switch (pass_number) - { + switch (pass_number) { case 1: descending_callback = acpi_ds_load1_begin_op; ascending_callback = acpi_ds_load1_end_op; @@ -140,16 +139,13 @@ /* Pass 1: Parse everything except control method bodies */ - status = acpi_ps_parse_aml (parse_root, - table_desc->aml_pointer, + status = acpi_ps_parse_aml (parse_root, table_desc->aml_pointer, table_desc->aml_length, ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE, - NULL, NULL, NULL, - descending_callback, + NULL, NULL, NULL, descending_callback, ascending_callback); acpi_ps_delete_parse_tree (parse_root); - return (status); } @@ -211,7 +207,7 @@ } -/***************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ns_load_table * @@ -222,7 +218,7 @@ * * DESCRIPTION: Load one ACPI table into the namespace * - ****************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_ns_load_table ( @@ -252,9 +248,9 @@ * because we don't know how many arguments to parse next! */ - acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); status = acpi_ns_parse_table (table_desc, node->child); - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (status)) { return (status); @@ -273,7 +269,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ns_load_table_by_type * @@ -285,7 +281,7 @@ * of the given type are loaded. The mechanism allows this * routine to be called repeatedly. * - *****************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_ns_load_table_by_type ( @@ -293,11 +289,10 @@ { u32 i; ACPI_STATUS status = AE_OK; - ACPI_TABLE_HEADER *table_ptr; ACPI_TABLE_DESC *table_desc; - acpi_cm_acquire_mutex (ACPI_MTX_TABLES); + acpi_ut_acquire_mutex (ACPI_MTX_TABLES); /* @@ -305,8 +300,7 @@ * DSDT (one), SSDT/PSDT (multiple) */ - switch (table_type) - { + switch (table_type) { case ACPI_TABLE_DSDT: @@ -338,16 +332,13 @@ table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_SSDT]; for (i = 0; i < acpi_gbl_acpi_tables[ACPI_TABLE_SSDT].count; i++) { - table_ptr = table_desc->pointer; - /* * Only attempt to load table if it is not * already loaded! */ if (!table_desc->loaded_into_namespace) { - status = acpi_ns_load_table (table_desc, - acpi_gbl_root_node); + status = acpi_ns_load_table (table_desc, acpi_gbl_root_node); if (ACPI_FAILURE (status)) { break; } @@ -357,7 +348,6 @@ table_desc = table_desc->next; } - break; @@ -370,13 +360,10 @@ table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_PSDT]; for (i = 0; i < acpi_gbl_acpi_tables[ACPI_TABLE_PSDT].count; i++) { - table_ptr = table_desc->pointer; - /* Only attempt to load table if it is not already loaded! */ if (!table_desc->loaded_into_namespace) { - status = acpi_ns_load_table (table_desc, - acpi_gbl_root_node); + status = acpi_ns_load_table (table_desc, acpi_gbl_root_node); if (ACPI_FAILURE (status)) { break; } @@ -392,19 +379,20 @@ default: status = AE_SUPPORT; + break; } unlock_and_exit: - acpi_cm_release_mutex (ACPI_MTX_TABLES); + acpi_ut_release_mutex (ACPI_MTX_TABLES); return (status); } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ns_delete_subtree * @@ -432,9 +420,9 @@ u32 level; - parent_handle = start_handle; - child_handle = 0; - level = 1; + parent_handle = start_handle; + child_handle = 0; + level = 1; /* * Traverse the tree of objects until we bubble back up @@ -445,8 +433,7 @@ /* Attempt to get the next object in this scope */ status = acpi_get_next_object (ACPI_TYPE_ANY, parent_handle, - child_handle, - &next_child_handle); + child_handle, &next_child_handle); child_handle = next_child_handle; @@ -456,18 +443,16 @@ if (ACPI_SUCCESS (status)) { /* Check if this object has any children */ - if (ACPI_SUCCESS (acpi_get_next_object (ACPI_TYPE_ANY, - child_handle, 0, - &dummy))) - { + if (ACPI_SUCCESS (acpi_get_next_object (ACPI_TYPE_ANY, child_handle, + 0, &dummy))) { /* * There is at least one child of this object, * visit the object */ level++; - parent_handle = child_handle; - child_handle = 0; + parent_handle = child_handle; + child_handle = 0; } } @@ -491,12 +476,11 @@ acpi_ns_delete_node (child_handle); - return (AE_OK); } -/**************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ns_unload_name_space * @@ -508,7 +492,7 @@ * event. Deletes an entire subtree starting from (and * including) the given handle. * - ****************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_ns_unload_namespace ( diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/namespace/nsnames.c linux/drivers/acpi/namespace/nsnames.c --- v2.4.5/linux/drivers/acpi/namespace/nsnames.c Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/namespace/nsnames.c Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: nsnames - Name manipulation and search - * $Revision: 54 $ + * $Revision: 59 $ * ******************************************************************************/ @@ -30,7 +30,7 @@ #include "acnamesp.h" -#define _COMPONENT NAMESPACE +#define _COMPONENT ACPI_NAMESPACE MODULE_NAME ("nsnames") @@ -84,7 +84,7 @@ /* Allocate a buffer to be returned to caller */ - name_buffer = acpi_cm_callocate (size + 1); + name_buffer = acpi_ut_callocate (size + 1); if (!name_buffer) { REPORT_ERROR (("Ns_get_table_pathname: allocation failure\n")); return (NULL); @@ -95,8 +95,7 @@ name_buffer[size] = '\0'; while ((size > ACPI_NAME_SIZE) && - acpi_ns_get_parent_object (child_node)) - { + acpi_ns_get_parent_object (child_node)) { size -= ACPI_NAME_SIZE; name = acpi_ns_find_parent_name (child_node); @@ -138,8 +137,7 @@ */ for (size = 0, next_node = node; acpi_ns_get_parent_object (next_node); - next_node = acpi_ns_get_parent_object (next_node)) - { + next_node = acpi_ns_get_parent_object (next_node)) { size += PATH_SEGMENT_LENGTH; } @@ -184,7 +182,7 @@ u32 size; - if (!acpi_gbl_root_node || !target_handle) { + if (!acpi_gbl_root_node) { /* * If the name space has not been initialized, * this function should not have been called. diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/namespace/nsobject.c linux/drivers/acpi/namespace/nsobject.c --- v2.4.5/linux/drivers/acpi/namespace/nsobject.c Mon Jan 22 13:23:43 2001 +++ linux/drivers/acpi/namespace/nsobject.c Wed Jun 20 17:47:40 2001 @@ -2,7 +2,7 @@ * * Module Name: nsobject - Utilities for objects attached to namespace * table entries - * $Revision: 49 $ + * $Revision: 55 $ * ******************************************************************************/ @@ -32,7 +32,7 @@ #include "actables.h" -#define _COMPONENT NAMESPACE +#define _COMPONENT ACPI_NAMESPACE MODULE_NAME ("nsobject") @@ -57,11 +57,11 @@ acpi_ns_attach_object ( ACPI_NAMESPACE_NODE *node, ACPI_OPERAND_OBJECT *object, - OBJECT_TYPE_INTERNAL type) + ACPI_OBJECT_TYPE8 type) { ACPI_OPERAND_OBJECT *obj_desc; ACPI_OPERAND_OBJECT *previous_obj_desc; - OBJECT_TYPE_INTERNAL obj_type = ACPI_TYPE_ANY; + ACPI_OBJECT_TYPE8 obj_type = ACPI_TYPE_ANY; u8 flags; u16 opcode; @@ -124,8 +124,7 @@ */ else if (VALID_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_NAMED) && - ((ACPI_NAMESPACE_NODE *) object)->object) - { + ((ACPI_NAMESPACE_NODE *) object)->object) { /* * Value passed is a name handle and that name has a * non-null value. Use that name's value and type. @@ -183,10 +182,9 @@ MOVE_UNALIGNED16_TO_16 (&opcode, object); - /* Check for a recognized Op_code */ + /* Check for a recognized Opcode */ - switch ((u8) opcode) - { + switch ((u8) opcode) { case AML_OP_PREFIX: @@ -257,7 +255,7 @@ * (if it is an internal object) */ - acpi_cm_add_reference (obj_desc); + acpi_ut_add_reference (obj_desc); /* Save the existing object (if any) for deletion later */ @@ -277,11 +275,11 @@ if (previous_obj_desc) { /* One for the attach to the Node */ - acpi_cm_remove_reference (previous_obj_desc); + acpi_ut_remove_reference (previous_obj_desc); /* Now delete */ - acpi_cm_remove_reference (previous_obj_desc); + acpi_ut_remove_reference (previous_obj_desc); } return (AE_OK); @@ -321,14 +319,14 @@ /* Found a valid value */ /* - * Not every value is an object allocated via Acpi_cm_callocate, + * Not every value is an object allocated via Acpi_ut_callocate, * - must check */ if (!acpi_tb_system_table_pointer (obj_desc)) { /* Attempt to delete the object (and all subobjects) */ - acpi_cm_remove_reference (obj_desc); + acpi_ut_remove_reference (obj_desc); } return; @@ -339,7 +337,7 @@ * * FUNCTION: Acpi_ns_get_attached_object * - * PARAMETERS: Handle - Parent Node to be examined + * PARAMETERS: Node - Parent Node to be examined * * RETURN: Current value of the object field from the Node whose * handle is passed @@ -348,16 +346,16 @@ void * acpi_ns_get_attached_object ( - ACPI_HANDLE handle) + ACPI_NAMESPACE_NODE *node) { - if (!handle) { + if (!node) { /* handle invalid */ return (NULL); } - return (((ACPI_NAMESPACE_NODE *) handle)->object); + return (node->object); } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/namespace/nssearch.c linux/drivers/acpi/namespace/nssearch.c --- v2.4.5/linux/drivers/acpi/namespace/nssearch.c Mon Jan 29 10:15:59 2001 +++ linux/drivers/acpi/namespace/nssearch.c Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: nssearch - Namespace search - * $Revision: 64 $ + * $Revision: 70 $ * ******************************************************************************/ @@ -30,7 +30,7 @@ #include "acnamesp.h" -#define _COMPONENT NAMESPACE +#define _COMPONENT ACPI_NAMESPACE MODULE_NAME ("nssearch") @@ -39,9 +39,9 @@ * FUNCTION: Acpi_ns_search_node * * PARAMETERS: *Target_name - Ascii ACPI name to search for - * *Node - Starting table where search will begin + * *Node - Starting table where search will begin * Type - Object type to match - * **Return_node - Where the matched Named obj is returned + * **Return_node - Where the matched Named obj is returned * * RETURN: Status * @@ -64,7 +64,7 @@ acpi_ns_search_node ( u32 target_name, ACPI_NAMESPACE_NODE *node, - OBJECT_TYPE_INTERNAL type, + ACPI_OBJECT_TYPE8 type, ACPI_NAMESPACE_NODE **return_node) { ACPI_NAMESPACE_NODE *next_node; @@ -81,36 +81,29 @@ if (next_node->name == target_name) { /* - * Found matching entry. Capture type if - * appropriate before returning the entry. + * Found matching entry. Capture the type if appropriate, before + * returning the entry. + * + * The Def_field_defn and Bank_field_defn cases are actually looking up + * the Region in which the field will be defined */ - /* - * The Def_field_defn and Bank_field_defn cases - * are actually looking up the Region in which - * the field will be defined - */ - - if ((INTERNAL_TYPE_DEF_FIELD_DEFN == type) || - (INTERNAL_TYPE_BANK_FIELD_DEFN == type)) - { + if ((INTERNAL_TYPE_FIELD_DEFN == type) || + (INTERNAL_TYPE_BANK_FIELD_DEFN == type)) { type = ACPI_TYPE_REGION; } /* - * Scope, Def_any, and Index_field_defn are bogus - * "types" which do not actually have anything - * to do with the type of the name being looked - * up. For any other value of Type, if the type - * stored in the entry is Any (i.e. unknown), - * save the actual type. + * Scope, Def_any, and Index_field_defn are bogus "types" which do not + * actually have anything to do with the type of the name being + * looked up. For any other value of Type, if the type stored in + * the entry is Any (i.e. unknown), save the actual type. */ if (type != INTERNAL_TYPE_SCOPE && type != INTERNAL_TYPE_DEF_ANY && type != INTERNAL_TYPE_INDEX_FIELD_DEFN && - next_node->type == ACPI_TYPE_ANY) - { + next_node->type == ACPI_TYPE_ANY) { next_node->type = (u8) type; } @@ -137,7 +130,6 @@ /* Searched entire table, not found */ - return (AE_NOT_FOUND); } @@ -147,9 +139,9 @@ * FUNCTION: Acpi_ns_search_parent_tree * * PARAMETERS: *Target_name - Ascii ACPI name to search for - * *Node - Starting table where search will begin + * *Node - Starting table where search will begin * Type - Object type to match - * **Return_node - Where the matched Named Obj is returned + * **Return_node - Where the matched Named Obj is returned * * RETURN: Status * @@ -171,7 +163,7 @@ acpi_ns_search_parent_tree ( u32 target_name, ACPI_NAMESPACE_NODE *node, - OBJECT_TYPE_INTERNAL type, + ACPI_OBJECT_TYPE8 type, ACPI_NAMESPACE_NODE **return_node) { ACPI_STATUS status; @@ -184,9 +176,8 @@ * If there is no parent (at the root) or type is "local", we won't be * searching the parent tree. */ - if ((acpi_ns_local (type)) || - (!parent_node)) - { + if ((acpi_ns_local (type)) || + (!parent_node)) { return (AE_NOT_FOUND); @@ -199,7 +190,6 @@ * Search parents until found the target or we have backed up to * the root */ - while (parent_node) { /* Search parent scope */ /* TBD: [Investigate] Why ACPI_TYPE_ANY? */ @@ -232,12 +222,12 @@ * * PARAMETERS: Target_name - Ascii ACPI name to search for (4 chars) * Walk_state - Current state of the walk - * *Node - Starting table where search will begin + * *Node - Starting table where search will begin * Interpreter_mode - Add names only in MODE_Load_pass_x. * Otherwise,search only. * Type - Object type to match * Flags - Flags describing the search restrictions - * **Return_node - Where the Node is returned + * **Return_node - Where the Node is returned * * RETURN: Status * @@ -257,7 +247,7 @@ ACPI_WALK_STATE *walk_state, ACPI_NAMESPACE_NODE *node, OPERATING_MODE interpreter_mode, - OBJECT_TYPE_INTERNAL type, + ACPI_OBJECT_TYPE8 type, u32 flags, ACPI_NAMESPACE_NODE **return_node) { @@ -275,7 +265,7 @@ /* Name must consist of printable characters */ - if (!acpi_cm_valid_acpi_name (target_name)) { + if (!acpi_ut_valid_acpi_name (target_name)) { REPORT_ERROR (("Ns_search_and_enter: Bad character in ACPI Name\n")); return (AE_BAD_CHARACTER); } @@ -284,16 +274,14 @@ /* Try to find the name in the table specified by the caller */ *return_node = ENTRY_NOT_FOUND; - status = acpi_ns_search_node (target_name, node, - type, return_node); + status = acpi_ns_search_node (target_name, node, type, return_node); if (status != AE_NOT_FOUND) { /* - * If we found it AND the request specifies that a - * find is an error, return the error + * If we found it AND the request specifies that a find is an error, + * return the error */ if ((status == AE_OK) && - (flags & NS_ERROR_IF_FOUND)) - { + (flags & NS_ERROR_IF_FOUND)) { status = AE_EXIST; } @@ -316,8 +304,7 @@ */ if ((interpreter_mode != IMODE_LOAD_PASS1) && - (flags & NS_SEARCH_PARENT)) - { + (flags & NS_SEARCH_PARENT)) { /* * Not found in table - search parent tree according * to ACPI specification diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/namespace/nsutils.c linux/drivers/acpi/namespace/nsutils.c --- v2.4.5/linux/drivers/acpi/namespace/nsutils.c Mon Jan 29 10:15:59 2001 +++ linux/drivers/acpi/namespace/nsutils.c Wed Jun 20 17:47:40 2001 @@ -2,7 +2,7 @@ * * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing * parents and siblings and Scope manipulation - * $Revision: 77 $ + * $Revision: 83 $ * *****************************************************************************/ @@ -31,11 +31,11 @@ #include "amlcode.h" #include "actables.h" -#define _COMPONENT NAMESPACE +#define _COMPONENT ACPI_NAMESPACE MODULE_NAME ("nsutils") -/**************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ns_valid_root_prefix * @@ -45,7 +45,7 @@ * * DESCRIPTION: Check if a character is a valid ACPI Root prefix * - ***************************************************************************/ + ******************************************************************************/ u8 acpi_ns_valid_root_prefix ( @@ -56,7 +56,7 @@ } -/**************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ns_valid_path_separator * @@ -66,7 +66,7 @@ * * DESCRIPTION: Check if a character is a valid ACPI path separator * - ***************************************************************************/ + ******************************************************************************/ u8 acpi_ns_valid_path_separator ( @@ -77,7 +77,7 @@ } -/**************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ns_get_type * @@ -85,23 +85,23 @@ * * RETURN: Type field from Node whose handle is passed * - ***************************************************************************/ + ******************************************************************************/ -OBJECT_TYPE_INTERNAL +ACPI_OBJECT_TYPE8 acpi_ns_get_type ( - ACPI_HANDLE handle) + ACPI_NAMESPACE_NODE *node) { - if (!handle) { - REPORT_WARNING (("Ns_get_type: Null handle\n")); + if (!node) { + REPORT_WARNING (("Ns_get_type: Null Node ptr")); return (ACPI_TYPE_ANY); } - return (((ACPI_NAMESPACE_NODE *) handle)->type); + return (node->type); } -/**************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ns_local * @@ -110,14 +110,14 @@ * RETURN: LOCAL if names must be found locally in objects of the * passed type, 0 if enclosing scopes should be searched * - ***************************************************************************/ + ******************************************************************************/ u32 acpi_ns_local ( - OBJECT_TYPE_INTERNAL type) + ACPI_OBJECT_TYPE8 type) { - if (!acpi_cm_valid_object_type (type)) { + if (!acpi_ut_valid_object_type (type)) { /* Type code out of range */ REPORT_WARNING (("Ns_local: Invalid Object Type\n")); @@ -128,41 +128,32 @@ } -/**************************************************************************** +/******************************************************************************* * - * FUNCTION: Acpi_ns_internalize_name + * FUNCTION: Acpi_ns_get_internal_name_length * - * PARAMETERS: *External_name - External representation of name - * **Converted Name - Where to return the resulting - * internal represention of the name + * PARAMETERS: Info - Info struct initialized with the + * external name pointer. * * RETURN: Status * - * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0") - * to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30) + * DESCRIPTION: Calculate the length of the internal (AML) namestring + * corresponding to the external (ASL) namestring. * - ****************************************************************************/ + ******************************************************************************/ ACPI_STATUS -acpi_ns_internalize_name ( - NATIVE_CHAR *external_name, - NATIVE_CHAR **converted_name) +acpi_ns_get_internal_name_length ( + ACPI_NAMESTRING_INFO *info) { - NATIVE_CHAR *result = NULL; - NATIVE_CHAR *internal_name; - u32 num_segments = 0; - u8 fully_qualified = FALSE; + NATIVE_CHAR *next_external_char; u32 i; - u32 num_carats = 0; - if ((!external_name) || - (*external_name == 0) || - (!converted_name)) - { - return (AE_BAD_PARAMETER); - } - + next_external_char = info->external_name; + info->num_carats = 0; + info->num_segments = 0; + info->fully_qualified = FALSE; /* * For the internal name, the required length is 4 bytes @@ -173,10 +164,9 @@ * strlen() + 1 covers the first Name_seg, which has no * path separator */ - - if (acpi_ns_valid_root_prefix (external_name[0])) { - fully_qualified = TRUE; - external_name++; + if (acpi_ns_valid_root_prefix (next_external_char[0])) { + info->fully_qualified = TRUE; + next_external_char++; } else { @@ -184,9 +174,9 @@ * Handle Carat prefixes */ - while (*external_name == '^') { - num_carats++; - external_name++; + while (*next_external_char == '^') { + info->num_carats++; + next_external_char++; } } @@ -196,28 +186,51 @@ * with one segment since the segment count is (# separators) * + 1, and zero separators is ok. */ - - if (*external_name) { - num_segments = 1; - for (i = 0; external_name[i]; i++) { - if (acpi_ns_valid_path_separator (external_name[i])) { - num_segments++; + if (*next_external_char) { + info->num_segments = 1; + for (i = 0; next_external_char[i]; i++) { + if (acpi_ns_valid_path_separator (next_external_char[i])) { + info->num_segments++; } } } + info->length = (ACPI_NAME_SIZE * info->num_segments) + + 4 + info->num_carats; - /* We need a segment to store the internal version of the name */ + info->next_external_char = next_external_char; - internal_name = acpi_cm_callocate ((ACPI_NAME_SIZE * num_segments) + 4 + num_carats); - if (!internal_name) { - return (AE_NO_MEMORY); - } + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_build_internal_name + * + * PARAMETERS: Info - Info struct fully initialized + * + * RETURN: Status + * + * DESCRIPTION: Construct the internal (AML) namestring + * corresponding to the external (ASL) namestring. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_build_internal_name ( + ACPI_NAMESTRING_INFO *info) +{ + u32 num_segments = info->num_segments; + NATIVE_CHAR *internal_name = info->internal_name; + NATIVE_CHAR *external_name = info->next_external_char; + NATIVE_CHAR *result = NULL; + u32 i; /* Setup the correct prefixes, counts, and pointers */ - if (fully_qualified) { + if (info->fully_qualified) { internal_name[0] = '\\'; if (num_segments <= 1) { @@ -232,7 +245,6 @@ internal_name[2] = (char) num_segments; result = &internal_name[3]; } - } else { @@ -240,10 +252,9 @@ * Not fully qualified. * Handle Carats first, then append the name segments */ - i = 0; - if (num_carats) { - for (i = 0; i < num_carats; i++) { + if (info->num_carats) { + for (i = 0; i < info->num_carats; i++) { internal_name[i] = '^'; } } @@ -270,31 +281,24 @@ for (; num_segments; num_segments--) { for (i = 0; i < ACPI_NAME_SIZE; i++) { if (acpi_ns_valid_path_separator (*external_name) || - (*external_name == 0)) - { - /* - * Pad the segment with underscore(s) if - * segment is short - */ + (*external_name == 0)) { + /* Pad the segment with underscore(s) if segment is short */ result[i] = '_'; } else { - /* Convert s8 to uppercase and save it */ + /* Convert the character to uppercase and save it */ result[i] = (char) TOUPPER (*external_name); external_name++; } - } /* Now we must have a path separator, or the pathname is bad */ if (!acpi_ns_valid_path_separator (*external_name) && - (*external_name != 0)) - { - acpi_cm_free (internal_name); + (*external_name != 0)) { return (AE_BAD_PARAMETER); } @@ -305,32 +309,87 @@ } - /* Return the completed name */ + /* Terminate the string */ - /* Terminate the string! */ *result = 0; - *converted_name = internal_name; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_internalize_name + * + * PARAMETERS: *External_name - External representation of name + * **Converted Name - Where to return the resulting + * internal represention of the name + * + * RETURN: Status + * + * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0") + * to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30) + * + *******************************************************************************/ + +ACPI_STATUS +acpi_ns_internalize_name ( + NATIVE_CHAR *external_name, + NATIVE_CHAR **converted_name) +{ + NATIVE_CHAR *internal_name; + ACPI_NAMESTRING_INFO info; + ACPI_STATUS status; + + + if ((!external_name) || + (*external_name == 0) || + (!converted_name)) { + return (AE_BAD_PARAMETER); + } + + + /* Get the length of the new internal name */ + + info.external_name = external_name; + acpi_ns_get_internal_name_length (&info); + + /* We need a segment to store the internal name */ + + internal_name = acpi_ut_callocate (info.length); + if (!internal_name) { + return (AE_NO_MEMORY); + } + + /* Build the name */ + info.internal_name = internal_name; + status = acpi_ns_build_internal_name (&info); + if (ACPI_FAILURE (status)) { + acpi_ut_free (internal_name); + return (status); + } + + *converted_name = internal_name; return (AE_OK); } -/**************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ns_externalize_name * * PARAMETERS: *Internal_name - Internal representation of name * **Converted_name - Where to return the resulting - * external representation of name + * external representation of name * * RETURN: Status * * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30) * to its external form (e.g. "\_PR_.CPU0") * - ****************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_ns_externalize_name ( @@ -349,8 +408,7 @@ if (!internal_name_length || !internal_name || !converted_name_length || - !converted_name) - { + !converted_name) { return (AE_BAD_PARAMETER); } @@ -358,8 +416,7 @@ /* * Check for a prefix (one '\' | one or more '^'). */ - switch (internal_name[0]) - { + switch (internal_name[0]) { case '\\': prefix_length = 1; break; @@ -383,8 +440,7 @@ * 4-byte elements. */ if (prefix_length < internal_name_length) { - switch (internal_name[prefix_length]) - { + switch (internal_name[prefix_length]) { /* 4-byte names */ @@ -440,7 +496,7 @@ * Build Converted_name... */ - (*converted_name) = acpi_cm_callocate (*converted_name_length); + (*converted_name) = acpi_ut_callocate (*converted_name_length); if (!(*converted_name)) { return (AE_NO_MEMORY); } @@ -468,7 +524,7 @@ } -/**************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ns_convert_handle_to_entry * @@ -478,7 +534,7 @@ * * DESCRIPTION: Convert a namespace handle to a real Node * - ****************************************************************************/ + ******************************************************************************/ ACPI_NAMESPACE_NODE * acpi_ns_convert_handle_to_entry ( @@ -490,7 +546,6 @@ * TBD: [Future] Real integer handles allow for more verification * and keep all pointers within this subsystem! */ - if (!handle) { return (NULL); } @@ -510,7 +565,7 @@ } -/**************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ns_convert_entry_to_handle * @@ -520,7 +575,7 @@ * * DESCRIPTION: Convert a real Node to a namespace handle * - ****************************************************************************/ + ******************************************************************************/ ACPI_HANDLE acpi_ns_convert_entry_to_handle ( @@ -533,17 +588,18 @@ * TBD: [Future] Real integer handles allow for more verification * and keep all pointers within this subsystem! */ - return ((ACPI_HANDLE) node); /* --------------------------------------------------- - if (!Node) { + if (!Node) + { return (NULL); } - if (Node == Acpi_gbl_Root_node) { + if (Node == Acpi_gbl_Root_node) + { return (ACPI_ROOT_OBJECT); } @@ -553,7 +609,7 @@ } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ns_terminate * @@ -576,12 +632,10 @@ /* * 1) Free the entire namespace -- all objects, tables, and stacks - */ - /* + * * Delete all objects linked to the root * (additional table descriptors) */ - acpi_ns_delete_namespace_subtree (this_node); /* Detach any object(s) attached to the root */ @@ -589,23 +643,20 @@ obj_desc = acpi_ns_get_attached_object (this_node); if (obj_desc) { acpi_ns_detach_object (this_node); - acpi_cm_remove_reference (obj_desc); + acpi_ut_remove_reference (obj_desc); } acpi_ns_delete_children (this_node); - /* * 2) Now we can delete the ACPI tables */ - acpi_tb_delete_acpi_tables (); - return; } -/**************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ns_opens_scope * @@ -614,14 +665,14 @@ * RETURN: NEWSCOPE if the passed type "opens a name scope" according * to the ACPI specification, else 0 * - ***************************************************************************/ + ******************************************************************************/ u32 acpi_ns_opens_scope ( - OBJECT_TYPE_INTERNAL type) + ACPI_OBJECT_TYPE8 type) { - if (!acpi_cm_valid_object_type (type)) { + if (!acpi_ut_valid_object_type (type)) { /* type code out of range */ REPORT_WARNING (("Ns_opens_scope: Invalid Object Type\n")); @@ -632,7 +683,7 @@ } -/**************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ns_get_node * @@ -650,7 +701,7 @@ * * MUTEX: Locks namespace * - ***************************************************************************/ + ******************************************************************************/ ACPI_STATUS acpi_ns_get_node ( @@ -682,7 +733,7 @@ } - acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); /* Setup lookup scope (search starting point) */ @@ -697,17 +748,16 @@ - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); /* Cleanup */ - acpi_cm_free (internal_path); - + acpi_ut_free (internal_path); return (status); } -/**************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ns_find_parent_name * @@ -719,7 +769,7 @@ * name segment, or "????" if the parent name can't be found * (which "should not happen"). * - ***************************************************************************/ + ******************************************************************************/ ACPI_NAME acpi_ns_find_parent_name ( @@ -740,12 +790,11 @@ } - return (ACPI_UNKNOWN_NAME); } -/**************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ns_get_parent_object * @@ -755,7 +804,7 @@ * * DESCRIPTION: Obtain the parent entry for a given entry in the namespace. * - ***************************************************************************/ + ******************************************************************************/ ACPI_NAMESPACE_NODE * @@ -775,7 +824,6 @@ * This saves putting a parent back pointer in each and * every named object! */ - while (!(node->flags & ANOBJ_END_OF_PEER_LIST)) { node = node->peer; } @@ -785,7 +833,7 @@ } -/**************************************************************************** +/******************************************************************************* * * FUNCTION: Acpi_ns_get_next_valid_object * @@ -797,7 +845,7 @@ * DESCRIPTION: Find the next valid object within a name table. * Useful for implementing NULL-end-of-list loops. * - ***************************************************************************/ + ******************************************************************************/ ACPI_NAMESPACE_NODE * diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/namespace/nswalk.c linux/drivers/acpi/namespace/nswalk.c --- v2.4.5/linux/drivers/acpi/namespace/nswalk.c Mon Jan 22 13:23:43 2001 +++ linux/drivers/acpi/namespace/nswalk.c Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: nswalk - Functions for walking the APCI namespace - * $Revision: 19 $ + * $Revision: 22 $ * *****************************************************************************/ @@ -29,7 +29,7 @@ #include "acnamesp.h" -#define _COMPONENT NAMESPACE +#define _COMPONENT ACPI_NAMESPACE MODULE_NAME ("nswalk") @@ -54,7 +54,7 @@ ACPI_NAMESPACE_NODE * acpi_ns_get_next_object ( - OBJECT_TYPE_INTERNAL type, + ACPI_OBJECT_TYPE8 type, ACPI_NAMESPACE_NODE *parent_node, ACPI_NAMESPACE_NODE *child_node) { @@ -139,18 +139,18 @@ ACPI_STATUS acpi_ns_walk_namespace ( - OBJECT_TYPE_INTERNAL type, + ACPI_OBJECT_TYPE8 type, ACPI_HANDLE start_node, u32 max_depth, u8 unlock_before_callback, - WALK_CALLBACK user_function, + ACPI_WALK_CALLBACK user_function, void *context, void **return_value) { ACPI_STATUS status; ACPI_NAMESPACE_NODE *child_node; ACPI_NAMESPACE_NODE *parent_node; - OBJECT_TYPE_INTERNAL child_type; + ACPI_OBJECT_TYPE8 child_type; u32 level; @@ -202,18 +202,17 @@ */ if (unlock_before_callback) { - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); } status = user_function (child_node, level, context, return_value); if (unlock_before_callback) { - acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); } - switch (status) - { + switch (status) { case AE_OK: case AE_CTRL_DEPTH: /* Just keep going */ @@ -242,8 +241,7 @@ if ((level < max_depth) && (status != AE_CTRL_DEPTH)) { if (acpi_ns_get_next_object (ACPI_TYPE_ANY, - child_node, 0)) - { + child_node, 0)) { /* * There is at least one child of this * object, visit the object diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/namespace/nsxfname.c linux/drivers/acpi/namespace/nsxfname.c --- v2.4.5/linux/drivers/acpi/namespace/nsxfname.c Mon Jan 22 13:23:43 2001 +++ linux/drivers/acpi/namespace/nsxfname.c Wed Jun 20 17:47:40 2001 @@ -2,7 +2,7 @@ * * Module Name: nsxfname - Public interfaces to the ACPI subsystem * ACPI Namespace oriented interfaces - * $Revision: 75 $ + * $Revision: 79 $ * *****************************************************************************/ @@ -34,7 +34,7 @@ #include "acevents.h" -#define _COMPONENT NAMESPACE +#define _COMPONENT ACPI_NAMESPACE MODULE_NAME ("nsxfname") @@ -67,6 +67,15 @@ ACPI_NAMESPACE_NODE *prefix_node = NULL; + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Parameter Validation */ + if (!ret_handle || !pathname) { return (AE_BAD_PARAMETER); } @@ -74,15 +83,15 @@ /* Convert a parent handle to a prefix node */ if (parent) { - acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); prefix_node = acpi_ns_convert_handle_to_entry (parent); if (!prefix_node) { - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return (AE_BAD_PARAMETER); } - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); } /* Special case for root, since we can't search for it */ @@ -132,6 +141,13 @@ ACPI_NAMESPACE_NODE *node; + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + /* Buffer pointer must be valid always */ if (!ret_path_ptr || (name_type > ACPI_NAME_TYPE_MAX)) { @@ -141,8 +157,7 @@ /* Allow length to be zero and ignore the pointer */ if ((ret_path_ptr->length) && - (!ret_path_ptr->pointer)) - { + (!ret_path_ptr->pointer)) { return (AE_BAD_PARAMETER); } @@ -159,7 +174,7 @@ * Validate handle and convert to an Node */ - acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); node = acpi_ns_convert_handle_to_entry (handle); if (!node) { status = AE_BAD_PARAMETER; @@ -184,7 +199,7 @@ unlock_and_exit: - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return (status); } @@ -209,32 +224,39 @@ ACPI_HANDLE handle, ACPI_DEVICE_INFO *info) { - DEVICE_ID hid; - DEVICE_ID uid; + ACPI_DEVICE_ID hid; + ACPI_DEVICE_ID uid; ACPI_STATUS status; u32 device_status = 0; ACPI_INTEGER address = 0; ACPI_NAMESPACE_NODE *node; + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + /* Parameter validation */ if (!handle || !info) { return (AE_BAD_PARAMETER); } - acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); node = acpi_ns_convert_handle_to_entry (handle); if (!node) { - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return (AE_BAD_PARAMETER); } info->type = node->type; info->name = node->name; - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); /* * If not a device, we are all done. @@ -256,7 +278,7 @@ /* Execute the _HID method and save the result */ - status = acpi_cm_execute_HID (node, &hid); + status = acpi_ut_execute_HID (node, &hid); if (ACPI_SUCCESS (status)) { STRNCPY (info->hardware_id, hid.buffer, sizeof(info->hardware_id)); @@ -265,7 +287,7 @@ /* Execute the _UID method and save the result */ - status = acpi_cm_execute_UID (node, &uid); + status = acpi_ut_execute_UID (node, &uid); if (ACPI_SUCCESS (status)) { STRCPY (info->unique_id, uid.buffer); @@ -277,7 +299,7 @@ * _STA is not always present */ - status = acpi_cm_execute_STA (node, &device_status); + status = acpi_ut_execute_STA (node, &device_status); if (ACPI_SUCCESS (status)) { info->current_status = device_status; info->valid |= ACPI_VALID_STA; @@ -288,7 +310,7 @@ * _ADR is not always present */ - status = acpi_cm_evaluate_numeric_object (METHOD_NAME__ADR, + status = acpi_ut_evaluate_numeric_object (METHOD_NAME__ADR, node, &address); if (ACPI_SUCCESS (status)) { diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/namespace/nsxfobj.c linux/drivers/acpi/namespace/nsxfobj.c --- v2.4.5/linux/drivers/acpi/namespace/nsxfobj.c Sun Apr 8 10:02:56 2001 +++ linux/drivers/acpi/namespace/nsxfobj.c Wed Jun 20 17:47:40 2001 @@ -2,7 +2,7 @@ * * Module Name: nsxfobj - Public interfaces to the ACPI subsystem * ACPI Object oriented interfaces - * $Revision: 80 $ + * $Revision: 86 $ * ******************************************************************************/ @@ -31,7 +31,7 @@ #include "acdispat.h" -#define _COMPONENT NAMESPACE +#define _COMPONENT ACPI_NAMESPACE MODULE_NAME ("nsxfobj") @@ -76,6 +76,13 @@ u32 object_length; + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + /* * If there are parameters to be passed to the object * (which must be a control method), the external objects @@ -92,7 +99,7 @@ param_length = (count + 1) * sizeof (void *); object_length = count * sizeof (ACPI_OPERAND_OBJECT); - param_ptr = acpi_cm_callocate (param_length + /* Parameter List part */ + param_ptr = acpi_ut_callocate (param_length + /* Parameter List part */ object_length); /* Actual objects */ if (!param_ptr) { return (AE_NO_MEMORY); @@ -108,7 +115,7 @@ for (i = 0; i < count; i++) { param_ptr[i] = &object_ptr[i]; - acpi_cm_init_static_object (&object_ptr[i]); + acpi_ut_init_static_object (&object_ptr[i]); } param_ptr[count] = NULL; @@ -117,11 +124,11 @@ * internal object */ for (i = 0; i < count; i++) { - status = acpi_cm_copy_eobject_to_iobject (¶m_objects->pointer[i], + status = acpi_ut_copy_eobject_to_iobject (¶m_objects->pointer[i], param_ptr[i]); if (ACPI_FAILURE (status)) { - acpi_cm_delete_internal_object_list (param_ptr); + acpi_ut_delete_internal_object_list (param_ptr); return (status); } } @@ -136,8 +143,7 @@ */ if ((pathname) && - (acpi_ns_valid_root_prefix (pathname[0]))) - { + (acpi_ns_valid_root_prefix (pathname[0]))) { /* * The path is fully qualified, just evaluate by name */ @@ -212,7 +218,7 @@ * Find out how large a buffer is needed * to contain the returned object */ - status = acpi_cm_get_object_size (return_obj, + status = acpi_ut_get_object_size (return_obj, &buffer_space_needed); if (ACPI_SUCCESS (status)) { /* @@ -235,7 +241,7 @@ /* * We have enough space for the object, build it */ - status = acpi_cm_copy_iobject_to_eobject (return_obj, + status = acpi_ut_copy_iobject_to_eobject (return_obj, return_buffer); return_buffer->length = buffer_space_needed; } @@ -252,7 +258,7 @@ * Delete the internal return object. (Or at least * decrement the reference count by one) */ - acpi_cm_remove_reference (return_obj); + acpi_ut_remove_reference (return_obj); } /* @@ -262,7 +268,7 @@ if (param_ptr) { /* Free the allocated parameter block */ - acpi_cm_delete_internal_object_list (param_ptr); + acpi_ut_delete_internal_object_list (param_ptr); } return (status); @@ -300,13 +306,20 @@ ACPI_NAMESPACE_NODE *child_node = NULL; + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + /* Parameter validation */ if (type > ACPI_TYPE_MAX) { return (AE_BAD_PARAMETER); } - acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); /* If null handle, use the parent */ @@ -335,7 +348,7 @@ /* Internal function does the real work */ - node = acpi_ns_get_next_object ((OBJECT_TYPE_INTERNAL) type, + node = acpi_ns_get_next_object ((ACPI_OBJECT_TYPE8) type, parent_node, child_node); if (!node) { status = AE_NOT_FOUND; @@ -349,7 +362,7 @@ unlock_and_exit: - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return (status); } @@ -373,7 +386,15 @@ ACPI_OBJECT_TYPE *ret_type) { ACPI_NAMESPACE_NODE *node; + ACPI_STATUS status; + + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } /* Parameter Validation */ @@ -390,20 +411,20 @@ return (AE_OK); } - acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); /* Convert and validate the handle */ node = acpi_ns_convert_handle_to_entry (handle); if (!node) { - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return (AE_BAD_PARAMETER); } *ret_type = node->type; - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return (AE_OK); } @@ -431,8 +452,12 @@ ACPI_STATUS status = AE_OK; - /* No trace macro, too verbose */ + /* Ensure that ACPI has been initialized */ + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } if (!ret_handle) { return (AE_BAD_PARAMETER); @@ -445,7 +470,7 @@ } - acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); /* Convert and validate the handle */ @@ -470,7 +495,7 @@ unlock_and_exit: - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return (status); } @@ -510,19 +535,25 @@ ACPI_OBJECT_TYPE type, ACPI_HANDLE start_object, u32 max_depth, - WALK_CALLBACK user_function, + ACPI_WALK_CALLBACK user_function, void *context, void **return_value) { ACPI_STATUS status; + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + /* Parameter validation */ if ((type > ACPI_TYPE_MAX) || (!max_depth) || - (!user_function)) - { + (!user_function)) { return (AE_BAD_PARAMETER); } @@ -533,14 +564,14 @@ * must be allowed to make Acpi calls itself. */ - acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); - status = acpi_ns_walk_namespace ((OBJECT_TYPE_INTERNAL) type, + acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); + status = acpi_ns_walk_namespace ((ACPI_OBJECT_TYPE8) type, start_object, max_depth, NS_WALK_UNLOCK, user_function, context, return_value); - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return (status); } @@ -570,17 +601,15 @@ ACPI_STATUS status; ACPI_NAMESPACE_NODE *node; u32 flags; - DEVICE_ID device_id; + ACPI_DEVICE_ID device_id; ACPI_GET_DEVICES_INFO *info; info = context; - acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); - + acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); node = acpi_ns_convert_handle_to_entry (obj_handle); - - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); if (!node) { return (AE_BAD_PARAMETER); @@ -589,15 +618,13 @@ /* * Run _STA to determine if device is present */ - - status = acpi_cm_execute_STA (node, &flags); + status = acpi_ut_execute_STA (node, &flags); if (ACPI_FAILURE (status)) { - return AE_OK; + return (AE_CTRL_DEPTH); } if (!(flags & 0x01)) { /* don't return at the device or children of the device if not there */ - return (AE_CTRL_DEPTH); } @@ -605,14 +632,13 @@ * Filter based on device HID */ if (info->hid != NULL) { - status = acpi_cm_execute_HID (node, &device_id); - + status = acpi_ut_execute_HID (node, &device_id); if (status == AE_NOT_FOUND) { return (AE_OK); } else if (ACPI_FAILURE (status)) { - return (status); + return (AE_CTRL_DEPTH); } if (STRNCMP (device_id.buffer, info->hid, sizeof (device_id.buffer)) != 0) { @@ -621,7 +647,6 @@ } info->user_function (obj_handle, nesting_level, info->context, return_value); - return (AE_OK); } @@ -654,7 +679,7 @@ ACPI_STATUS acpi_get_devices ( NATIVE_CHAR *HID, - WALK_CALLBACK user_function, + ACPI_WALK_CALLBACK user_function, void *context, void **return_value) { @@ -662,6 +687,13 @@ ACPI_GET_DEVICES_INFO info; + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + /* Parameter validation */ if (!user_function) { @@ -683,14 +715,14 @@ * must be allowed to make Acpi calls itself. */ - acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, NS_WALK_UNLOCK, acpi_ns_get_device_callback, &info, return_value); - acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return (status); } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/os.c linux/drivers/acpi/os.c --- v2.4.5/linux/drivers/acpi/os.c Mon Jan 22 13:23:43 2001 +++ linux/drivers/acpi/os.c Sun Jun 24 20:53:07 2001 @@ -1,7 +1,15 @@ +/****************************************************************************** + * + * Module Name: os.c - Linux OSL functions + * $Revision: 28 $ + * + *****************************************************************************/ + /* * os.c - OS-dependent functions * * Copyright (C) 2000 Andrew Henroid + * Copyright (C) 2001 Andrew Grover * * 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 @@ -17,24 +25,36 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* Changes + * + * Christopher Liebman 2001-5-15 + * - Fixed improper kernel_thread parameters + */ #include -#include #include #include #include -#include +#include +#include #include #include -#include "acpi.h" +#include #include "driver.h" -#define _COMPONENT OS_DEPENDENT +#define _COMPONENT ACPI_OS_SERVICES MODULE_NAME ("os") -static int acpi_irq_irq = 0; -static OSD_HANDLER acpi_irq_handler = NULL; -static void *acpi_irq_context = NULL; +typedef struct +{ + OSD_EXECUTION_CALLBACK function; + void *context; +} ACPI_OS_DPC; + + +/***************************************************************************** + * Debugger Stuff + *****************************************************************************/ #ifdef ENABLE_DEBUGGER @@ -47,6 +67,19 @@ #endif +/***************************************************************************** + * Globals + *****************************************************************************/ + +static int acpi_irq_irq = 0; +static OSD_HANDLER acpi_irq_handler = NULL; +static void *acpi_irq_context = NULL; + + +/****************************************************************************** + * Functions + *****************************************************************************/ + ACPI_STATUS acpi_os_initialize(void) { @@ -141,6 +174,17 @@ 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) { @@ -171,6 +215,7 @@ free_irq(irq, acpi_irq); acpi_irq_handler = NULL; } + return AE_OK; } @@ -248,27 +293,27 @@ void acpi_os_mem_out8 (ACPI_PHYSICAL_ADDRESS phys_addr, UINT8 value) { - *(u8*) (u32) phys_addr = value; + *(u8*) phys_to_virt(phys_addr) = value; } void acpi_os_mem_out16 (ACPI_PHYSICAL_ADDRESS phys_addr, UINT16 value) { - *(u16*) (u32) phys_addr = value; + *(u16*) phys_to_virt(phys_addr) = value; } void acpi_os_mem_out32 (ACPI_PHYSICAL_ADDRESS phys_addr, UINT32 value) { - *(u32*) (u32) phys_addr = value; + *(u32*) phys_to_virt(phys_addr) = value; } ACPI_STATUS acpi_os_read_pci_cfg_byte( - u32 bus, - u32 func, - u32 addr, - u8 * val) + u32 bus, + u32 func, + u32 addr, + u8 * val) { int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn); @@ -279,10 +324,10 @@ ACPI_STATUS acpi_os_read_pci_cfg_word( - u32 bus, - u32 func, - u32 addr, - u16 * val) + u32 bus, + u32 func, + u32 addr, + u16 * val) { int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn); @@ -293,10 +338,10 @@ ACPI_STATUS acpi_os_read_pci_cfg_dword( - u32 bus, - u32 func, - u32 addr, - u32 * val) + u32 bus, + u32 func, + u32 addr, + u32 * val) { int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn); @@ -307,10 +352,10 @@ ACPI_STATUS acpi_os_write_pci_cfg_byte( - u32 bus, - u32 func, - u32 addr, - u8 val) + u32 bus, + u32 func, + u32 addr, + u8 val) { int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn); @@ -321,10 +366,10 @@ ACPI_STATUS acpi_os_write_pci_cfg_word( - u32 bus, - u32 func, - u32 addr, - u16 val) + u32 bus, + u32 func, + u32 addr, + u16 val) { int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn); @@ -335,10 +380,10 @@ ACPI_STATUS acpi_os_write_pci_cfg_dword( - u32 bus, - u32 func, - u32 addr, - u32 val) + u32 bus, + u32 func, + u32 addr, + u32 val) { int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff); struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn); @@ -347,49 +392,317 @@ return AE_OK; } -/* - * Queue for interpreter thread - */ +ACPI_STATUS +acpi_os_load_module ( + char *module_name) +{ + FUNCTION_TRACE("acpi_os_load_module"); + + if (!module_name) + return_ACPI_STATUS(AE_BAD_PARAMETER); + + if (0 > request_module(module_name)) { + DEBUG_PRINT(ACPI_WARN, ("Unable to load module [%s].\n", module_name)); + return_ACPI_STATUS(AE_ERROR); + } + + return_ACPI_STATUS(AE_OK); +} ACPI_STATUS -acpi_os_queue_for_execution( - u32 priority, - OSD_EXECUTION_CALLBACK callback, - void *context) +acpi_os_unload_module ( + char *module_name) { - if (acpi_run(callback, context)) - return AE_ERROR; - return AE_OK; + FUNCTION_TRACE("acpi_os_unload_module"); + + if (!module_name) + return_ACPI_STATUS(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_ACPI_STATUS(AE_OK); } + /* - * Semaphores are unused, interpreter access is single threaded + * See acpi_os_queue_for_execution(), too */ +static int +acpi_os_queue_exec ( + void *context) +{ + ACPI_OS_DPC *dpc = (ACPI_OS_DPC*)context; -ACPI_STATUS -acpi_os_create_semaphore(u32 max_units, u32 init, ACPI_HANDLE * handle) + FUNCTION_TRACE("acpi_os_queue_exec"); + + daemonize(); + strcpy(current->comm, "kacpidpc"); + + if (!dpc || !dpc->function) + return_ACPI_STATUS(AE_BAD_PARAMETER); + + DEBUG_PRINT(ACPI_INFO, ("Executing function [%p(%p)].\n", dpc->function, dpc->context)); + + dpc->function(dpc->context); + + acpi_os_free(dpc); + + return_VALUE(1); +} + +static void +acpi_os_schedule_exec ( + void *context) { - /* a hack to fake out sems until we implement them */ - *handle = (ACPI_HANDLE) handle; - return AE_OK; + ACPI_OS_DPC *dpc = NULL; + int thread_pid = -1; + + FUNCTION_TRACE("acpi_os_schedule_exec"); + + dpc = (ACPI_OS_DPC*)context; + if (!dpc) { + DEBUG_PRINT(ACPI_ERROR, ("Invalid (NULL) context.\n")); + return; + } + + DEBUG_PRINT(ACPI_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) { + DEBUG_PRINT(ACPI_ERROR, ("Call to kernel_thread() failed.\n")); + acpi_os_free(dpc); + } + + return_VOID; } ACPI_STATUS -acpi_os_delete_semaphore(ACPI_HANDLE handle) +acpi_os_queue_for_execution( + u32 priority, + OSD_EXECUTION_CALLBACK function, + void *context) +{ + ACPI_STATUS status = AE_OK; + ACPI_OS_DPC *dpc = NULL; + + FUNCTION_TRACE("acpi_os_queue_for_execution"); + + DEBUG_PRINT(ACPI_INFO, ("Scheduling function [%p(%p)] for deferred execution.\n", function, context)); + + if (!function) + return_ACPI_STATUS(AE_BAD_PARAMETER); + + /* + * Allocate/initialize DPC structure. Note that this memory will be + * freed by the callee. + */ + dpc = acpi_os_callocate(sizeof(ACPI_OS_DPC)); + if (!dpc) + return AE_NO_MEMORY; + + dpc->function = function; + dpc->context = context; + + /* + * 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; + + memset(&task, 0, sizeof(struct tq_struct)); + + task.routine = acpi_os_schedule_exec; + task.data = (void*)dpc; + + if (schedule_task(&task) < 0) { + DEBUG_PRINT(ACPI_ERROR, ("Call to schedule_task() failed.\n")); + status = AE_ERROR; + } + } + break; + + default: + 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) { - return AE_OK; + struct semaphore *sem = NULL; + + FUNCTION_TRACE("acpi_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; + + DEBUG_PRINT(ACPI_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_wait_semaphore(ACPI_HANDLE handle, u32 units, u32 timeout) +acpi_os_delete_semaphore( + ACPI_HANDLE handle) { - return AE_OK; + struct semaphore *sem = (struct semaphore*)handle; + + FUNCTION_TRACE("acpi_os_delete_semaphore"); + + if (!sem) + return AE_BAD_PARAMETER; + + DEBUG_PRINT(ACPI_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; + + FUNCTION_TRACE("acpi_os_wait_semaphore"); + + if (!sem || (units < 1)) + return_ACPI_STATUS(AE_BAD_PARAMETER); + + if (units > 1) + return_ACPI_STATUS(AE_SUPPORT); + + DEBUG_PRINT(ACPI_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: + ret = down_trylock(sem); + if (ret < 0) + 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)) { + DEBUG_PRINT(ACPI_INFO, ("Failed to acquire semaphore[%p|%d|%d]\n", handle, units, timeout)); + } + else { + DEBUG_PRINT(ACPI_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) +acpi_os_signal_semaphore( + ACPI_HANDLE handle, + u32 units) { - return AE_OK; + struct semaphore *sem = (struct semaphore *) handle; + + FUNCTION_TRACE("acpi_os_signal_semaphore"); + + if (!sem || (units < 1)) + return_ACPI_STATUS(AE_BAD_PARAMETER); + + if (units > 1) + return_ACPI_STATUS(AE_SUPPORT); + + DEBUG_PRINT(ACPI_INFO, ("Signaling semaphore[%p|%d]\n", handle, units)); + + up(sem); + + return_ACPI_STATUS(AE_OK); } ACPI_STATUS @@ -399,8 +712,10 @@ return AE_OK; } + void acpi_os_dbg_trap(char *msg) + { acpi_os_printf("trap: %s", msg); } @@ -421,7 +736,7 @@ kdb_read(buffer, sizeof(line_buf)); - /* remove the CR kdb includes */ + /* remove the CR kdb includes */ chars = strlen(buffer) - 1; buffer[chars] = '\0'; } @@ -444,4 +759,15 @@ acpi_os_writable(void *ptr, u32 len) { return 1; +} + +u32 +acpi_os_get_thread_id (void) +{ + if (!in_interrupt()) + return current->pid; + + /*acpi_os_printf("acpi_os_get_thread_id called from interrupt level!\n");*/ + + return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/Makefile linux/drivers/acpi/ospm/Makefile --- v2.4.5/linux/drivers/acpi/ospm/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/Makefile Wed Jun 20 17:47:40 2001 @@ -0,0 +1,22 @@ +# +# Makefile for the Linux OSPM code. +# + +O_TARGET := $(notdir $(CURDIR)).o + +ACPI_CFLAGS += -I$(CURDIR)/include + +EXTRA_CFLAGS += $(ACPI_CFLAGS) + +subdir-$(CONFIG_ACPI_BUSMGR) += busmgr +subdir-$(CONFIG_ACPI_EC) += ec +subdir-$(CONFIG_ACPI_SYS) += system +subdir-$(CONFIG_ACPI_CPU) += processor +subdir-$(CONFIG_ACPI_CMBATT) += battery +subdir-$(CONFIG_ACPI_AC) += ac_adapter +subdir-$(CONFIG_ACPI_BUTTON) += button +subdir-$(CONFIG_ACPI_THERMAL) += thermal + +obj-y += $(foreach dir,$(subdir-y),$(dir)/ospm_$(dir).o) + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/ac_adapter/Makefile linux/drivers/acpi/ospm/ac_adapter/Makefile --- v2.4.5/linux/drivers/acpi/ospm/ac_adapter/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/ac_adapter/Makefile Wed Jun 20 17:47:40 2001 @@ -0,0 +1,6 @@ +O_TARGET := ospm_$(notdir $(CURDIR)).o +obj-m := $(O_TARGET) +EXTRA_CFLAGS += $(ACPI_CFLAGS) +obj-y := $(patsubst %.c,%.o,$(wildcard *.c)) + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/ac_adapter/ac.c linux/drivers/acpi/ospm/ac_adapter/ac.c --- v2.4.5/linux/drivers/acpi/ospm/ac_adapter/ac.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/ac_adapter/ac.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,348 @@ +/***************************************************************************** + * + * Module Name: ac.c + * $Revision: 19 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 "ac.h" + + +#define _COMPONENT ACPI_AC_ADAPTER + MODULE_NAME ("ac") + + +/**************************************************************************** + * Internal Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: ac_print + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: Prints out information on a specific ac_adapter. + * + ****************************************************************************/ + +void +ac_print ( + AC_CONTEXT *ac_adapter) +{ + + return; +} + + +/**************************************************************************** + * + * FUNCTION: ac_add_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +ac_add_device( + BM_HANDLE device_handle, + void **context) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE *device = NULL; + AC_CONTEXT *ac_adapter = NULL; + ACPI_DEVICE_INFO info; + + if (!context || *context) { + return(AE_BAD_PARAMETER); + } + + /* + * Get information on this device. + */ + status = bm_get_device_info(device_handle, &device); + if (ACPI_FAILURE(status)) { + return(status); + } + + /* + * Allocate a new AC_CONTEXT structure. + */ + ac_adapter = acpi_os_callocate(sizeof(AC_CONTEXT)); + if (!ac_adapter) { + return(AE_NO_MEMORY); + } + + ac_adapter->device_handle = device->handle; + ac_adapter->acpi_handle = device->acpi_handle; + + /* + * Get information on this object. + */ + status = acpi_get_object_info(ac_adapter->acpi_handle, &info); + if (ACPI_FAILURE(status)) { + goto end; + } + + /* + * _UID? + * ----- + */ + if (info.valid & ACPI_VALID_UID) { + strncpy(ac_adapter->uid, info.unique_id, sizeof(info.unique_id)); + } + else { + strncpy(ac_adapter->uid, "0", sizeof("0")); + } + + /* + * _STA? + * ----- + */ + if (!(info.valid & ACPI_VALID_STA)) { + status = AE_ERROR; + goto end; + } + + status = ac_osl_add_device(ac_adapter); + if (ACPI_FAILURE(status)) { + goto end; + } + + *context = ac_adapter; + + ac_print(ac_adapter); + +end: + if (ACPI_FAILURE(status)) { + acpi_os_free(ac_adapter); + } + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: ac_remove_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +ac_remove_device ( + void **context) +{ + ACPI_STATUS status = AE_OK; + AC_CONTEXT *ac_adapter = NULL; + + if (!context || !*context) { + return(AE_BAD_PARAMETER); + } + + ac_adapter = (AC_CONTEXT*)*context; + + ac_osl_remove_device(ac_adapter); + + acpi_os_free(ac_adapter); + + *context = NULL; + + return(status); +} + + +/**************************************************************************** + * External Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: ac_initialize + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +ac_initialize (void) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE_ID criteria; + BM_DRIVER driver; + + MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID)); + MEMSET(&driver, 0, sizeof(BM_DRIVER)); + + driver.notify = &ac_notify; + driver.request = &ac_request; + + /* + * Register driver for AC Adapter devices. + */ + MEMCPY(criteria.hid, AC_HID_AC_ADAPTER, sizeof(AC_HID_AC_ADAPTER)); + + status = bm_register_driver(&criteria, &driver); + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: ac_terminate + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +ac_terminate (void) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE_ID criteria; + BM_DRIVER driver; + + MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID)); + MEMSET(&driver, 0, sizeof(BM_DRIVER)); + + /* + * Unregister driver for AC Adapter devices. + */ + MEMCPY(criteria.hid, AC_HID_AC_ADAPTER, sizeof(AC_HID_AC_ADAPTER)); + + driver.notify = &ac_notify; + driver.request = &ac_request; + + status = bm_unregister_driver(&criteria, &driver); + + return(status); +} + + +/***************************************************************************** + * + * FUNCTION: ac_notify + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ +ACPI_STATUS +ac_notify ( + BM_NOTIFY notify_type, + BM_HANDLE device_handle, + void **context) +{ + ACPI_STATUS status = AE_OK; + + if (!context) { + return(AE_BAD_PARAMETER); + } + + switch (notify_type) { + + case BM_NOTIFY_DEVICE_ADDED: + status = ac_add_device(device_handle, context); + break; + + case BM_NOTIFY_DEVICE_REMOVED: + status = ac_remove_device(context); + break; + + case AC_NOTIFY_STATUS_CHANGE: + status = ac_osl_generate_event(notify_type, + ((AC_CONTEXT*)*context)); + break; + + default: + status = AE_SUPPORT; + break; + } + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: ac_request + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +ac_request ( + BM_REQUEST *request, + void *context) +{ + ACPI_STATUS status = AE_OK; + + /* + * Must have a valid request structure and context. + */ + if (!request || !context) { + return(AE_BAD_PARAMETER); + } + + /* + * Handle Request: + * --------------- + */ + switch (request->command) { + + default: + status = AE_SUPPORT; + break; + } + + request->status = status; + + return(status); +} diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/ac_adapter/ac_osl.c linux/drivers/acpi/ospm/ac_adapter/ac_osl.c --- v2.4.5/linux/drivers/acpi/ospm/ac_adapter/ac_osl.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/ac_adapter/ac_osl.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,256 @@ +/***************************************************************************** + * + * Module Name: ac_osl.c + * $Revision: 7 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 "ac.h" + + +MODULE_AUTHOR("Andrew Grover"); +MODULE_DESCRIPTION("ACPI Component Architecture (CA) - AC Adapter Driver"); + + +#define AC_PROC_ROOT "ac_adapter" +#define AC_PROC_STATUS "status" +#define AC_ON_LINE "on-line" +#define AC_OFF_LINE "off-line" + +extern struct proc_dir_entry *bm_proc_root; +static struct proc_dir_entry *ac_proc_root = NULL; + + +/**************************************************************************** + * + * FUNCTION: ac_osl_proc_read_status + * + ****************************************************************************/ + +static int +ac_osl_proc_read_status ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *context) +{ + ACPI_STATUS status = AE_OK; + AC_CONTEXT *ac_adapter = NULL; + char *p = page; + int len; + + if (!context) { + goto end; + } + + ac_adapter = (AC_CONTEXT*)context; + + /* don't get status more than once for a single proc read */ + if (off != 0) { + goto end; + } + + status = bm_evaluate_simple_integer(ac_adapter->acpi_handle, + "_PSR", &(ac_adapter->is_online)); + if (ACPI_FAILURE(status)) { + p += sprintf(p, "Error reading AC Adapter status\n"); + goto end; + } + + if (ac_adapter->is_online) { + p += sprintf(p, "Status: %s\n", + AC_ON_LINE); + } + else { + p += sprintf(p, "Status: %s\n", + AC_OFF_LINE); + } + +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(len); +} + + +/**************************************************************************** + * + * FUNCTION: ac_osl_add_device + * + ****************************************************************************/ + +ACPI_STATUS +ac_osl_add_device( + AC_CONTEXT *ac_adapter) +{ + struct proc_dir_entry *proc_entry = NULL; + + if (!ac_adapter) { + return(AE_BAD_PARAMETER); + } + + printk(KERN_INFO "AC Adapter: found\n"); + + proc_entry = proc_mkdir(ac_adapter->uid, ac_proc_root); + if (!proc_entry) { + return(AE_ERROR); + } + + create_proc_read_entry(AC_PROC_STATUS, S_IFREG | S_IRUGO, + proc_entry, ac_osl_proc_read_status, (void*)ac_adapter); + + return(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: ac_osl_remove_device + * + ****************************************************************************/ + +ACPI_STATUS +ac_osl_remove_device ( + AC_CONTEXT *ac_adapter) +{ + char proc_entry[64]; + + if (!ac_adapter) { + return(AE_BAD_PARAMETER); + } + + sprintf(proc_entry, "%s/%s", ac_adapter->uid, AC_PROC_STATUS); + remove_proc_entry(proc_entry, ac_proc_root); + + sprintf(proc_entry, "%s", ac_adapter->uid); + remove_proc_entry(proc_entry, ac_proc_root); + + return(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: ac_osl_generate_event + * + ****************************************************************************/ + +ACPI_STATUS +ac_osl_generate_event ( + u32 event, + AC_CONTEXT *ac_adapter) +{ + ACPI_STATUS status = AE_OK; + + if (!ac_adapter) { + return(AE_BAD_PARAMETER); + } + + switch (event) { + + case AC_NOTIFY_STATUS_CHANGE: + status = bm_osl_generate_event(ac_adapter->device_handle, + AC_PROC_ROOT, ac_adapter->uid, event, 0); + break; + + default: + return(AE_BAD_PARAMETER); + break; + } + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: ac_osl_init + * + * PARAMETERS: + * + * RETURN: 0: Success + * + * DESCRIPTION: Module initialization. + * + ****************************************************************************/ + +static int __init +ac_osl_init (void) +{ + ACPI_STATUS status = AE_OK; + + ac_proc_root = proc_mkdir(AC_PROC_ROOT, bm_proc_root); + if (!ac_proc_root) { + status = AE_ERROR; + } + else { + status = ac_initialize(); + if (ACPI_FAILURE(status)) { + remove_proc_entry(AC_PROC_ROOT, bm_proc_root); + } + + } + + return (ACPI_SUCCESS(status)) ? 0 : -ENODEV; +} + + +/**************************************************************************** + * + * FUNCTION: ac_osl_cleanup + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: Module cleanup. + * + ****************************************************************************/ + +static void __exit +ac_osl_cleanup (void) +{ + ac_terminate(); + + if (ac_proc_root) { + remove_proc_entry(AC_PROC_ROOT, bm_proc_root); + } + + return; +} + + +module_init(ac_osl_init); +module_exit(ac_osl_cleanup); diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/battery/Makefile linux/drivers/acpi/ospm/battery/Makefile --- v2.4.5/linux/drivers/acpi/ospm/battery/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/battery/Makefile Wed Jun 20 17:47:40 2001 @@ -0,0 +1,6 @@ +O_TARGET := ospm_$(notdir $(CURDIR)).o +obj-m := $(O_TARGET) +EXTRA_CFLAGS += $(ACPI_CFLAGS) +obj-y := $(patsubst %.c,%.o,$(wildcard *.c)) + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/battery/bt.c linux/drivers/acpi/ospm/battery/bt.c --- v2.4.5/linux/drivers/acpi/ospm/battery/bt.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/battery/bt.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,593 @@ +/***************************************************************************** + * + * Module Name: bt.c + * $Revision: 24 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 "bt.h" + + +#define _COMPONENT ACPI_BATTERY + MODULE_NAME ("bt") + + +/**************************************************************************** + * Internal Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bt_print + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: Prints out information on a specific battery. + * + ****************************************************************************/ + +void +bt_print ( + BT_CONTEXT *battery) +{ + + return; +} + + +/**************************************************************************** + * + * FUNCTION: bt_get_info + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + * NOTES: Allocates battery_info - which must be freed by the caller. + * + ****************************************************************************/ + +ACPI_STATUS +bt_get_info ( + BT_CONTEXT *battery, + BT_BATTERY_INFO **battery_info) +{ + ACPI_STATUS status = AE_OK; + ACPI_BUFFER bif_buffer, package_format, package_data; + ACPI_OBJECT *package = NULL; + + if (!battery || !battery_info || *battery_info) { + return(AE_BAD_PARAMETER); + } + + MEMSET(&bif_buffer, 0, sizeof(ACPI_BUFFER)); + + /* + * Evalute _BIF: + * ------------- + * And be sure to deallocate bif_buffer.pointer! + */ + status = bm_evaluate_object(battery->acpi_handle, "_BIF", NULL, + &bif_buffer); + if (ACPI_FAILURE(status)) { + return(status); + } + + /* + * Extract Package Data: + * --------------------- + * Type-cast this bif_buffer to a package and use helper + * functions to convert results into BT_BATTERY_INFO structure. + * The first attempt is just to get the size of the package + * data; the second gets the data (once we know the required + * bif_buffer size). + */ + status = bm_cast_buffer(&bif_buffer, (void**)&package, + sizeof(ACPI_OBJECT)); + if (ACPI_FAILURE(status)) { + goto end; + } + + package_format.length = sizeof("NNNNNNNNNSSSS"); + package_format.pointer = "NNNNNNNNNSSSS"; + + MEMSET(&package_data, 0, sizeof(ACPI_BUFFER)); + + status = bm_extract_package_data(package, &package_format, + &package_data); + if (status != AE_BUFFER_OVERFLOW) { + if (status == AE_OK) { + status = AE_ERROR; + } + goto end; + } + + package_data.pointer = acpi_os_callocate(package_data.length); + if (!package_data.pointer) { + return(AE_NO_MEMORY); + } + + status = bm_extract_package_data(package, &package_format, + &package_data); + if (ACPI_FAILURE(status)) { + acpi_os_free(package_data.pointer); + goto end; + } + + *battery_info = package_data.pointer; + +end: + acpi_os_free(bif_buffer.pointer); + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: bt_get_status + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bt_get_status ( + BT_CONTEXT *battery, + BT_BATTERY_STATUS **battery_status) +{ + ACPI_STATUS status = AE_OK; + ACPI_BUFFER bst_buffer, package_format, package_data; + ACPI_OBJECT *package = NULL; + + if (!battery || !battery_status || *battery_status) { + return(AE_BAD_PARAMETER); + } + + MEMSET(&bst_buffer, 0, sizeof(ACPI_BUFFER)); + + /* + * Evalute _BST: + * ------------- + * And be sure to deallocate bst_buffer.pointer! + */ + status = bm_evaluate_object(battery->acpi_handle, "_BST", + NULL, &bst_buffer); + if (ACPI_FAILURE(status)) { + return(status); + } + + /* + * Extract Package Data: + * --------------------- + * Type-cast this bst_buffer to a package and use helper + * functions to convert results into BT_BATTERY_STATUS structure. + * The first attempt is just to get the size of the package data; + * the second gets the data (once we know the required bst_buffer + * size). + */ + status = bm_cast_buffer(&bst_buffer, (void**)&package, + sizeof(ACPI_OBJECT)); + if (ACPI_FAILURE(status)) { + goto end; + } + + package_format.length = sizeof("NNNN"); + package_format.pointer = "NNNN"; + + MEMSET(&package_data, 0, sizeof(ACPI_BUFFER)); + + status = bm_extract_package_data(package, &package_format, + &package_data); + if (status != AE_BUFFER_OVERFLOW) { + if (status == AE_OK) { + status = AE_ERROR; + } + goto end; + } + + package_data.pointer = acpi_os_callocate(package_data.length); + if (!package_data.pointer) { + return(AE_NO_MEMORY); + } + + status = bm_extract_package_data(package, &package_format, + &package_data); + if (ACPI_FAILURE(status)) { + acpi_os_free(package_data.pointer); + goto end; + } + + *battery_status = package_data.pointer; + +end: + acpi_os_free(bst_buffer.pointer); + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: bt_check_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bt_check_device ( + BT_CONTEXT *battery) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE_STATUS battery_status = BM_STATUS_UNKNOWN; + u32 was_present = FALSE; + BT_BATTERY_INFO *battery_info = NULL; + + if (!battery) { + return(AE_BAD_PARAMETER); + } + + was_present = battery->is_present; + + /* + * Battery Present? + * ---------------- + * Get the device status and check if battery slot is occupied. + */ + status = bm_get_device_status(battery->device_handle, &battery_status); + if (ACPI_FAILURE(status)) { + return(status); + } + + if (battery_status & BM_STATUS_BATTERY_PRESENT) { + battery->is_present = TRUE; + } + else { + battery->is_present = FALSE; + } + + /* + * Battery Appeared? + * ----------------- + */ + if (!was_present && battery->is_present) { + + /* + * Units of Power? + * --------------- + * Get the 'units of power', as we'll need this to report + * status information. + */ + status = bt_get_info(battery, &battery_info); + if (ACPI_SUCCESS(status)) { + battery->power_units = (battery_info->power_unit) + ? BT_POWER_UNITS_AMPS : BT_POWER_UNITS_WATTS; + acpi_os_free(battery_info); + } + } + + /* + * Battery Disappeared? + * -------------------- + */ + else if (was_present && !battery->is_present) { + battery->power_units = BT_POWER_UNITS_DEFAULT; + } + + return(status); +} + + +/***************************************************************************** + * + * FUNCTION: bt_add_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bt_add_device ( + BM_HANDLE device_handle, + void **context) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE *device = NULL; + BT_CONTEXT *battery = NULL; + + if (!context || *context) { + return(AE_BAD_PARAMETER); + } + + /* + * Get information on this device. + */ + status = bm_get_device_info(device_handle, &device); + if (ACPI_FAILURE(status)) { + return(status); + } + + /* + * Allocate a new BT_CONTEXT structure. + */ + battery = acpi_os_callocate(sizeof(BT_CONTEXT)); + if (!battery) { + return(AE_NO_MEMORY); + } + + battery->device_handle = device->handle; + battery->acpi_handle = device->acpi_handle; + strncpy(battery->uid, device->id.uid, sizeof(battery->uid)); + + battery->power_units = BT_POWER_UNITS_DEFAULT; + battery->is_present = FALSE; + + /* + * See if battery is really present. + */ + status = bt_check_device(battery); + if (ACPI_FAILURE(status)) { + goto end; + } + + status = bt_osl_add_device(battery); + if (ACPI_FAILURE(status)) { + goto end; + } + + *context = battery; + + bt_print(battery); + +end: + if (ACPI_FAILURE(status)) { + acpi_os_free(battery); + } + + return(status); +} + + +/***************************************************************************** + * + * FUNCTION: bt_remove_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bt_remove_device ( + void **context) +{ + ACPI_STATUS status = AE_OK; + BT_CONTEXT *battery = NULL; + + if (!context || !*context) { + return(AE_BAD_PARAMETER); + } + + battery = (BT_CONTEXT*)*context; + + bt_osl_remove_device(battery); + + acpi_os_free(battery); + + *context = NULL; + + return(status); +} + + +/***************************************************************************** + * External Functions + *****************************************************************************/ + +/***************************************************************************** + * + * FUNCTION: bt_initialize + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bt_initialize (void) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE_ID criteria; + BM_DRIVER driver; + + MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID)); + MEMSET(&driver, 0, sizeof(BM_DRIVER)); + + /* + * Register driver for driver method battery devices. + */ + MEMCPY(criteria.hid, BT_HID_CM_BATTERY, sizeof(BT_HID_CM_BATTERY)); + + driver.notify = &bt_notify; + driver.request = &bt_request; + + status = bm_register_driver(&criteria, &driver); + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: bt_terminate + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bt_terminate (void) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE_ID criteria; + BM_DRIVER driver; + + MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID)); + MEMSET(&driver, 0, sizeof(BM_DRIVER)); + + /* + * Unregister driver for driver method battery devices. + */ + MEMCPY(criteria.hid, BT_HID_CM_BATTERY, sizeof(BT_HID_CM_BATTERY)); + + driver.notify = &bt_notify; + driver.request = &bt_request; + + status = bm_unregister_driver(&criteria, &driver); + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: bt_notify + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bt_notify ( + BM_NOTIFY notify_type, + BM_HANDLE device_handle, + void **context) +{ + ACPI_STATUS status = AE_OK; + + if (!context) { + return(AE_BAD_PARAMETER); + } + + switch (notify_type) { + + case BM_NOTIFY_DEVICE_ADDED: + status = bt_add_device(device_handle, context); + break; + + case BM_NOTIFY_DEVICE_REMOVED: + status = bt_remove_device(context); + break; + + case BT_NOTIFY_STATUS_CHANGE: + status = bt_osl_generate_event(notify_type, + ((BT_CONTEXT*)*context)); + break; + + case BT_NOTIFY_INFORMATION_CHANGE: + status = bt_check_device((BT_CONTEXT*)*context); + if (ACPI_SUCCESS(status)) { + status = bt_osl_generate_event(notify_type, + ((BT_CONTEXT*)*context)); + } + break; + + default: + status = AE_SUPPORT; + break; + } + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: bt_request + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bt_request ( + BM_REQUEST *request, + void *context) +{ + ACPI_STATUS status = AE_OK; + + /* + * Must have a valid request structure and context. + */ + if (!request || !context) + return(AE_BAD_PARAMETER); + + /* + * Handle request: + * --------------- + */ + switch (request->command) { + + default: + status = AE_SUPPORT; + break; + } + + request->status = status; + + return(status); +} diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/battery/bt_osl.c linux/drivers/acpi/ospm/battery/bt_osl.c --- v2.4.5/linux/drivers/acpi/ospm/battery/bt_osl.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/battery/bt_osl.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,438 @@ +/****************************************************************************** + * + * Module Name: bt_osl.c + * $Revision: 18 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 + */ + +/* + * Changes: + * Brendan Burns 2000-11-15 + * - added proc battery interface + * - parse returned data from _BST and _BIF + * Andy Grover 2000-12-8 + * - improved proc interface + */ + + +#include +#include +#include +#include +#include +#include +#include "bt.h" + + +MODULE_AUTHOR("Andrew Grover"); +MODULE_DESCRIPTION("ACPI Component Architecture (CA) - Control Method Battery Driver"); + + +#define BT_PROC_ROOT "battery" +#define BT_PROC_STATUS "status" +#define BT_PROC_INFO "info" + +extern struct proc_dir_entry *bm_proc_root; +static struct proc_dir_entry *bt_proc_root = NULL; + + +/**************************************************************************** + * + * FUNCTION: bt_osl_proc_read_info + * + ****************************************************************************/ + +static int +bt_osl_proc_read_info ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *context) +{ + BT_CONTEXT *battery = NULL; + BT_BATTERY_INFO *battery_info = NULL; + char *p = page; + int len = 0; + + if (!context || (off != 0)) { + goto end; + } + + battery = (BT_CONTEXT*)context; + + /* + * Battery Present? + * ---------------- + */ + if (!battery->is_present) { + p += sprintf(p, "Present: no\n"); + goto end; + } + else { + p += sprintf(p, "Present: yes\n"); + } + + /* + * Get Battery Information: + * ------------------------ + */ + if (ACPI_FAILURE(bt_get_info(battery, &battery_info))) { + p += sprintf(p, "Error reading battery information (_BIF)\n"); + goto end; + } + + if (battery_info->design_capacity == BT_UNKNOWN) { + p += sprintf(p, "Design Capacity: unknown\n"); + } + else { + p += sprintf(p, "Design Capacity: %d %sh\n", + battery_info->design_capacity, + battery->power_units); + } + + if (battery_info->last_full_capacity == BT_UNKNOWN) { + p += sprintf(p, "Last Full Capacity: unknown\n"); + } + else { + p += sprintf(p, "Last Full Capacity: %d %sh\n", + battery_info->last_full_capacity, + battery->power_units); + } + + if (battery_info->battery_technology == 0) { + p += sprintf(p, "Battery Technology: primary (non-rechargeable)\n"); + } + else if (battery_info->battery_technology == 1) { + p += sprintf(p, "Battery Technology: secondary (rechargeable)\n"); + } + else { + p += sprintf(p, "Battery Technology: unknown\n"); + } + + if (battery_info->design_voltage == BT_UNKNOWN) { + p += sprintf(p, "Design Voltage: unknown\n"); + } + else { + p += sprintf(p, "Design Voltage: %d mV\n", + battery_info->design_voltage); + } + + p += sprintf(p, "Design Capacity Warning: %d %sh\n", + battery_info->design_capacity_warning, + battery->power_units); + p += sprintf(p, "Design Capacity Low: %d %sh\n", + battery_info->design_capacity_low, + battery->power_units); + p += sprintf(p, "Capacity Granularity 1: %d %sh\n", + battery_info->battery_capacity_granularity_1, + battery->power_units); + p += sprintf(p, "Capacity Granularity 2: %d %sh\n", + battery_info->battery_capacity_granularity_2, + battery->power_units); + p += sprintf(p, "Model Number: %s\n", + battery_info->model_number); + p += sprintf(p, "Serial Number: %s\n", + battery_info->serial_number); + p += sprintf(p, "Battery Type: %s\n", + battery_info->battery_type); + p += sprintf(p, "OEM Info: %s\n", + battery_info->oem_info); + +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; + + acpi_os_free(battery_info); + + return(len); +} + + +/**************************************************************************** + * + * FUNCTION: bt_osl_proc_read_status + * + ****************************************************************************/ + +static int +bt_osl_proc_read_status ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *context) +{ + BT_CONTEXT *battery = NULL; + BT_BATTERY_STATUS *battery_status = NULL; + char *p = page; + int len = 0; + + if (!context || (off != 0)) { + goto end; + } + + battery = (BT_CONTEXT*)context; + + /* + * Battery Present? + * ---------------- + */ + if (!battery->is_present) { + p += sprintf(p, "Present: no\n"); + goto end; + } + else { + p += sprintf(p, "Present: yes\n"); + } + + /* + * Get Battery Status: + * ------------------- + */ + if (ACPI_FAILURE(bt_get_status(battery, &battery_status))) { + p += sprintf(p, "Error reading battery status (_BST)\n"); + goto end; + } + + /* + * Store Data: + * ----------- + */ + + if (!battery_status->state) { + p += sprintf(p, "State: ok\n"); + } + else { + if (battery_status->state & 0x1) + p += sprintf(p, "State: discharging\n"); + if (battery_status->state & 0x2) + p += sprintf(p, "State: charging\n"); + if (battery_status->state & 0x4) + p += sprintf(p, "State: critically low\n"); + } + + if (battery_status->present_rate == BT_UNKNOWN) { + p += sprintf(p, "Present Rate: unknown\n"); + } + else { + p += sprintf(p, "Present Rate: %d %s\n", + battery_status->present_rate, + battery->power_units); + } + + if (battery_status->remaining_capacity == BT_UNKNOWN) { + p += sprintf(p, "Remaining Capacity: unknown\n"); + } + else { + p += sprintf(p, "Remaining Capacity: %d %sh\n", + battery_status->remaining_capacity, + battery->power_units); + } + + if (battery_status->present_voltage == BT_UNKNOWN) { + p += sprintf(p, "Battery Voltage: unknown\n"); + } + else { + p += sprintf(p, "Battery Voltage: %d mV\n", + battery_status->present_voltage); + } + +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; + + acpi_os_free(battery_status); + + return(len); +} + + +/**************************************************************************** + * + * FUNCTION: bt_osl_add_device + * + ****************************************************************************/ + +ACPI_STATUS +bt_osl_add_device( + BT_CONTEXT *battery) +{ + struct proc_dir_entry *proc_entry = NULL; + + if (!battery) { + return(AE_BAD_PARAMETER); + } + + if (battery->is_present) { + printk("Battery: socket found, battery present\n"); + } + else { + printk("Battery: socket found, battery absent\n"); + } + + proc_entry = proc_mkdir(battery->uid, bt_proc_root); + if (!proc_entry) { + return(AE_ERROR); + } + + create_proc_read_entry(BT_PROC_STATUS, S_IFREG | S_IRUGO, + proc_entry, bt_osl_proc_read_status, (void*)battery); + + create_proc_read_entry(BT_PROC_INFO, S_IFREG | S_IRUGO, + proc_entry, bt_osl_proc_read_info, (void*)battery); + + return(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: bt_osl_remove_device + * + ****************************************************************************/ + +ACPI_STATUS +bt_osl_remove_device ( + BT_CONTEXT *battery) +{ + char proc_entry[64]; + + if (!battery) { + return(AE_BAD_PARAMETER); + } + + sprintf(proc_entry, "%s/%s", battery->uid, BT_PROC_INFO); + remove_proc_entry(proc_entry, bt_proc_root); + + sprintf(proc_entry, "%s/%s", battery->uid, BT_PROC_STATUS); + remove_proc_entry(proc_entry, bt_proc_root); + + sprintf(proc_entry, "%s", battery->uid); + remove_proc_entry(proc_entry, bt_proc_root); + + return(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: bt_osl_generate_event + * + ****************************************************************************/ + +ACPI_STATUS +bt_osl_generate_event ( + u32 event, + BT_CONTEXT *battery) +{ + ACPI_STATUS status = AE_OK; + + if (!battery) { + return(AE_BAD_PARAMETER); + } + + switch (event) { + + case BT_NOTIFY_STATUS_CHANGE: + case BT_NOTIFY_INFORMATION_CHANGE: + status = bm_osl_generate_event(battery->device_handle, + BT_PROC_ROOT, battery->uid, event, 0); + break; + + default: + return(AE_BAD_PARAMETER); + break; + } + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: bt_osl_init + * + * PARAMETERS: + * + * RETURN: 0: Success + * + * DESCRIPTION: Module initialization. + * + ****************************************************************************/ + +static int __init +bt_osl_init (void) +{ + ACPI_STATUS status = AE_OK; + + bt_proc_root = proc_mkdir(BT_PROC_ROOT, bm_proc_root); + if (!bt_proc_root) { + status = AE_ERROR; + } + else { + status = bt_initialize(); + if (ACPI_FAILURE(status)) { + remove_proc_entry(BT_PROC_ROOT, bm_proc_root); + } + } + + return (ACPI_SUCCESS(status)) ? 0 : -ENODEV; +} + + +/**************************************************************************** + * + * FUNCTION: bt_osl_cleanup + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: Module cleanup. + * + ****************************************************************************/ + +static void __exit +bt_osl_cleanup (void) +{ + bt_terminate(); + + if (bt_proc_root) { + remove_proc_entry(BT_PROC_ROOT, bm_proc_root); + } + + return; +} + + +module_init(bt_osl_init); +module_exit(bt_osl_cleanup); diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/busmgr/Makefile linux/drivers/acpi/ospm/busmgr/Makefile --- v2.4.5/linux/drivers/acpi/ospm/busmgr/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/busmgr/Makefile Wed Jun 20 17:47:40 2001 @@ -0,0 +1,6 @@ +O_TARGET := ospm_$(notdir $(CURDIR)).o +obj-m := $(O_TARGET) +EXTRA_CFLAGS += $(ACPI_CFLAGS) +obj-y := $(patsubst %.c,%.o,$(wildcard *.c)) + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/busmgr/bm.c linux/drivers/acpi/ospm/busmgr/bm.c --- v2.4.5/linux/drivers/acpi/ospm/busmgr/bm.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/busmgr/bm.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,1144 @@ +/****************************************************************************** + * + * Module Name: bm.c + * $Revision: 42 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 "bm.h" + + +#define _COMPONENT ACPI_BUS + MODULE_NAME ("bm") + + +/**************************************************************************** + * Globals + ****************************************************************************/ + +extern FADT_DESCRIPTOR_REV2 acpi_fadt; +/* TBD: Make dynamically sizeable. */ +BM_NODE_LIST node_list; + + +/**************************************************************************** + * Internal Functions + ****************************************************************************/ + +/***************************************************************************** + * + * FUNCTION: bm_print_object + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +void +bm_print_object ( + ACPI_HANDLE acpi_handle) +{ + ACPI_BUFFER buffer; + ACPI_HANDLE parent; + ACPI_OBJECT_TYPE type; + + buffer.length = 256; + buffer.pointer = acpi_os_callocate(buffer.length); + if (!buffer.pointer) { + return; + } + + acpi_get_name(acpi_handle, ACPI_FULL_PATHNAME, &buffer); + acpi_get_parent(acpi_handle, &parent); + acpi_get_type(acpi_handle, &type); + + /* + * TBD: Hack to get around scope identification problem. + */ + if (type == ACPI_TYPE_ANY) { + if (ACPI_SUCCESS(acpi_get_next_object(ACPI_TYPE_ANY, + acpi_handle, 0, NULL))) { + type = INTERNAL_TYPE_SCOPE; + } + } + + switch (type) + { + case INTERNAL_TYPE_SCOPE: + acpi_os_printf("SCOPE: "); + break; + case ACPI_TYPE_INTEGER: + acpi_os_printf("SIMPLE (number): "); + break; + case ACPI_TYPE_STRING: + acpi_os_printf("SIMPLE (string): "); + break; + case ACPI_TYPE_BUFFER: + acpi_os_printf("SIMPLE (buffer): "); + break; + case ACPI_TYPE_PACKAGE: + acpi_os_printf("SIMPLE (package): "); + break; + case ACPI_TYPE_FIELD_UNIT: + acpi_os_printf("FIELD UNIT: "); + break; + case ACPI_TYPE_DEVICE: + acpi_os_printf("DEVICE: "); + break; + case ACPI_TYPE_EVENT: + acpi_os_printf("EVENT: "); + break; + case ACPI_TYPE_METHOD: + acpi_os_printf("CONTROL METHOD: "); + break; + case ACPI_TYPE_MUTEX: + acpi_os_printf("MUTEX: "); + break; + case ACPI_TYPE_REGION: + acpi_os_printf("OPERATION REGION: "); + break; + case ACPI_TYPE_POWER: + acpi_os_printf("POWER RESOURCE: "); + break; + case ACPI_TYPE_PROCESSOR: + acpi_os_printf("PROCESSOR: "); + break; + case ACPI_TYPE_THERMAL: + acpi_os_printf("THERMAL ZONE: "); + break; + case ACPI_TYPE_BUFFER_FIELD: + acpi_os_printf("BUFFER FIELD: "); + break; + case ACPI_TYPE_DDB_HANDLE: + acpi_os_printf("DDB HANDLE: "); + break; + default: + acpi_os_printf("OTHER (%d): ", type); + break; + } + + acpi_os_printf("Object[%p][%s] parent[%p].\n", acpi_handle, (char*)buffer.pointer, parent); + + acpi_os_free(buffer.pointer); +} + + +/**************************************************************************** + * + * FUNCTION: bm_print_node + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +void +bm_print_node ( + BM_NODE *node, + u32 flags) +{ +#ifdef ACPI_DEBUG + ACPI_BUFFER buffer; + BM_DEVICE *device = NULL; + char *type_string = NULL; + + if (!node) { + return; + } + + device = &(node->device); + + if (flags & BM_PRINT_PRESENT) { + if (!BM_DEVICE_PRESENT(device)) { + return; + } + } + + buffer.length = 256; + buffer.pointer = acpi_os_callocate(buffer.length); + if (!buffer.pointer) { + return; + } + + acpi_get_name(device->acpi_handle, ACPI_FULL_PATHNAME, &buffer); + + switch(device->id.type) { + case BM_TYPE_SYSTEM: + type_string = " System"; + break; + case BM_TYPE_SCOPE: + type_string = " Scope"; + break; + case BM_TYPE_PROCESSOR: + type_string = " Proc"; + break; + case BM_TYPE_THERMAL_ZONE: + type_string = "Thermal"; + break; + case BM_TYPE_POWER_RESOURCE: + type_string = " Power"; + break; + case BM_TYPE_FIXED_BUTTON: + type_string = " Button"; + break; + case BM_TYPE_DEVICE: + type_string = " Device"; + break; + default: + type_string = "Unknown"; + break; + } + + if (!(flags & BM_PRINT_GROUP)) { + DEBUG_PRINT_RAW(ACPI_INFO, ("+-------------------------------------------------------------------------------\n")); + } + + DEBUG_PRINT_RAW(ACPI_INFO, ("| %s[%02x]:[%p] flags[%02x] hid[%s] %s\n", type_string, device->handle, device->acpi_handle, device->flags, (device->id.hid[0] ? device->id.hid : " "), buffer.pointer)); + + if (flags & BM_PRINT_IDENTIFICATION) { + DEBUG_PRINT_RAW(ACPI_INFO, ("| identification: uid[%s] adr[%08x]\n", device->id.uid, device->id.adr)); + } + + if (flags & BM_PRINT_LINKAGE) { + DEBUG_PRINT_RAW(ACPI_INFO, ("| linkage: this[%p] parent[%p] next[%p]\n", node, node->parent, node->next)); + DEBUG_PRINT_RAW(ACPI_INFO, ("| scope.head[%p] scope.tail[%p]\n", node->scope.head, node->scope.tail)); + } + + if (flags & BM_PRINT_POWER) { + DEBUG_PRINT_RAW(ACPI_INFO, ("| power: state[D%d] flags[%08x]\n", device->power.state, device->power.flags)); + DEBUG_PRINT_RAW(ACPI_INFO, ("| S0[%02x] S1[%02x] S2[%02x] S3[%02x] S4[%02x] S5[%02x]\n", device->power.dx_supported[0], device->power.dx_supported[1], device->power.dx_supported[2], device->power.dx_supported[3], device->power.dx_supported[4], device->power.dx_supported[5])); + } + + if (!(flags & BM_PRINT_GROUP)) { + DEBUG_PRINT_RAW(ACPI_INFO, ("+-------------------------------------------------------------------------------\n")); + } + + acpi_os_free(buffer.pointer); +#endif /*ACPI_DEBUG*/ + + return; +} + + +/**************************************************************************** + * + * FUNCTION: bm_print_hierarchy + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +void +bm_print_hierarchy (void) +{ +#ifdef ACPI_DEBUG + u32 i = 0; + + FUNCTION_TRACE("bm_print_hierarchy"); + + DEBUG_PRINT_RAW(ACPI_INFO, ("+------------------------------------------------------------\n")); + + for (i = 0; i < node_list.count; i++) { + bm_print_node(node_list.nodes[i], BM_PRINT_GROUP | BM_PRINT_PRESENT); + } + + DEBUG_PRINT_RAW(ACPI_INFO, ("+------------------------------------------------------------\n")); +#endif /*ACPI_DEBUG*/ + + return_VOID; +} + + +/**************************************************************************** + * + * FUNCTION: bm_get_status + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_get_status ( + BM_DEVICE *device) +{ + ACPI_STATUS status = AE_OK; + + if (!device) { + return AE_BAD_PARAMETER; + } + + device->status = BM_STATUS_UNKNOWN; + + /* + * Dynamic Status? + * --------------- + * If _STA isn't present we just return the default status. + */ + if (!(device->flags & BM_FLAGS_DYNAMIC_STATUS)) { + device->status = BM_STATUS_DEFAULT; + return AE_OK; + } + + /* + * Evaluate _STA: + * -------------- + */ + status = bm_evaluate_simple_integer(device->acpi_handle, "_STA", + &(device->status)); + + return status; +} + + +/**************************************************************************** + * + * FUNCTION: bm_get_identification + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_get_identification ( + BM_DEVICE *device) +{ + ACPI_STATUS status = AE_OK; + ACPI_DEVICE_INFO info; + + if (!device) { + return AE_BAD_PARAMETER; + } + + if (!(device->flags & BM_FLAGS_IDENTIFIABLE)) { + return AE_OK; + } + + device->id.uid[0] = BM_UID_UNKNOWN; + device->id.hid[0] = BM_HID_UNKNOWN; + device->id.adr = BM_ADDRESS_UNKNOWN; + + /* + * Get Object Info: + * ---------------- + * Evalute _UID, _HID, and _ADR... + */ + status = acpi_get_object_info(device->acpi_handle, &info); + if (ACPI_FAILURE(status)) { + return status; + } + + if (info.valid & ACPI_VALID_UID) { + MEMCPY((void*)device->id.uid, (void*)info.unique_id, + sizeof(BM_DEVICE_UID)); + } + + if (info.valid & ACPI_VALID_HID) { + MEMCPY((void*)device->id.hid, (void*)info.hardware_id, + sizeof(BM_DEVICE_HID)); + } + + if (info.valid & ACPI_VALID_ADR) { + device->id.adr = info.address; + } + + return status; +} + + +/**************************************************************************** + * + * FUNCTION: bm_get_flags + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_get_flags ( + BM_DEVICE *device) +{ + ACPI_HANDLE acpi_handle = NULL; + + if (!device) { + return AE_BAD_PARAMETER; + } + + device->flags = BM_FLAGS_UNKNOWN; + + switch (device->id.type) { + + case BM_TYPE_DEVICE: + + /* + * Presence of _DCK indicates a docking station. + */ + if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, + "_DCK", &acpi_handle))) { + device->flags |= BM_FLAGS_DOCKING_STATION; + } + + /* + * Presence of _EJD and/or _EJx indicates 'ejectable'. + * TBD: _EJx... + */ + if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, + "_EJD", &acpi_handle))) { + device->flags |= BM_FLAGS_EJECTABLE; + } + + /* + * Presence of _PR0 or _PS0 indicates 'power manageable'. + */ + if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, + "_PR0", &acpi_handle)) || + ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, + "_PS0", &acpi_handle))) { + device->flags |= BM_FLAGS_POWER_CONTROL; + } + + /* + * Presence of _CRS indicates 'configurable'. + */ + if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, + "_CRS", &acpi_handle))) { + device->flags |= BM_FLAGS_CONFIGURABLE; + } + + /* Fall through to next case statement. */ + + case BM_TYPE_PROCESSOR: + case BM_TYPE_THERMAL_ZONE: + case BM_TYPE_POWER_RESOURCE: + /* + * Presence of _HID or _ADR indicates 'identifiable'. + */ + if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, + "_HID", &acpi_handle)) || + ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, + "_ADR", &acpi_handle))) { + device->flags |= BM_FLAGS_IDENTIFIABLE; + } + + /* + * Presence of _STA indicates 'dynamic status'. + */ + if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, + "_STA", &acpi_handle))) { + device->flags |= BM_FLAGS_DYNAMIC_STATUS; + } + + break; + } + + return AE_OK; +} + + +/**************************************************************************** + * + * FUNCTION: bm_add_namespace_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_add_namespace_device ( + ACPI_HANDLE acpi_handle, + ACPI_OBJECT_TYPE acpi_type, + BM_NODE *parent, + BM_NODE **child) +{ + ACPI_STATUS status = AE_OK; + BM_NODE *node = NULL; + BM_DEVICE *device = NULL; + + FUNCTION_TRACE("bm_add_namespace_device"); + + if (!parent || !child) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (node_list.count > BM_HANDLES_MAX) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + (*child) = NULL; + + /* + * Create Node: + * ------------ + */ + node = acpi_os_callocate(sizeof(BM_NODE)); + if (!node) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + node->parent = parent; + node->next = NULL; + + device = &(node->device); + + device->handle = node_list.count; + device->acpi_handle = acpi_handle; + + /* + * Device Type: + * ------------ + */ + switch (acpi_type) { + case INTERNAL_TYPE_SCOPE: + device->id.type = BM_TYPE_SCOPE; + break; + case ACPI_TYPE_PROCESSOR: + device->id.type = BM_TYPE_PROCESSOR; + break; + case ACPI_TYPE_THERMAL: + device->id.type = BM_TYPE_THERMAL_ZONE; + break; + case ACPI_TYPE_POWER: + device->id.type = BM_TYPE_POWER_RESOURCE; + break; + case ACPI_TYPE_DEVICE: + device->id.type = BM_TYPE_DEVICE; + break; + } + + /* + * Get Other Device Info: + * ---------------------- + * But only if this device's parent is present (which implies + * this device MAY be present). + */ + if (BM_NODE_PRESENT(node->parent)) { + /* + * Device Flags + */ + status = bm_get_flags(device); + if (ACPI_FAILURE(status)) { + goto end; + } + + /* + * Device Identification + */ + status = bm_get_identification(device); + if (ACPI_FAILURE(status)) { + goto end; + } + + /* + * Device Status + */ + status = bm_get_status(device); + if (ACPI_FAILURE(status)) { + goto end; + } + + /* + * Power Management: + * ----------------- + * If this node doesn't provide direct power control + * then we inherit PM capabilities from its parent. + * + * TBD: Inherit! + */ + if (BM_IS_POWER_CONTROL(device)) { + status = bm_get_pm_capabilities(node); + if (ACPI_FAILURE(status)) { + goto end; + } + } + } + +end: + if (ACPI_FAILURE(status)) { + acpi_os_free(node); + } + else { + /* + * Add to the node_list. + */ + node_list.nodes[node_list.count++] = node; + + /* + * Formulate Hierarchy: + * -------------------- + * Arrange within the namespace by assigning the parent and + * adding to the parent device's list of children (scope). + */ + if (!parent->scope.head) { + parent->scope.head = node; + } + else { + if (!parent->scope.tail) { + (parent->scope.head)->next = node; + } + else { + (parent->scope.tail)->next = node; + } + } + parent->scope.tail = node; + + (*child) = node; + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_enumerate_namespace + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_enumerate_namespace (void) +{ + ACPI_STATUS status = AE_OK; + ACPI_HANDLE parent_handle = ACPI_ROOT_OBJECT; + ACPI_HANDLE child_handle = NULL; + BM_NODE *parent = NULL; + BM_NODE *child = NULL; + ACPI_OBJECT_TYPE acpi_type = 0; + u32 level = 1; + + FUNCTION_TRACE("bm_enumerate_namespace"); + + parent = node_list.nodes[0]; + + /* + * Enumerate ACPI Namespace: + * ------------------------- + * Parse through the ACPI namespace, identify all 'devices', + * and create a new entry for each in our collection. + */ + while (level > 0) { + + /* + * Get the next object at this level. + */ + status = acpi_get_next_object(ACPI_TYPE_ANY, parent_handle, child_handle, &child_handle); + if (ACPI_SUCCESS(status)) { + /* + * TBD: This is a hack to get around the problem + * identifying scope objects. Scopes + * somehow need to be uniquely identified. + */ + status = acpi_get_type(child_handle, &acpi_type); + if (ACPI_SUCCESS(status) && (acpi_type == ACPI_TYPE_ANY)) { + status = acpi_get_next_object(ACPI_TYPE_ANY, child_handle, 0, NULL); + if (ACPI_SUCCESS(status)) { + acpi_type = INTERNAL_TYPE_SCOPE; + } + } + + /* + * Device? + * ------- + * If this object is a 'device', insert into the + * ACPI Bus Manager's local hierarchy and search + * the object's scope for any child devices (a + * depth-first search). + */ + switch (acpi_type) { + case INTERNAL_TYPE_SCOPE: + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + case ACPI_TYPE_POWER: + status = bm_add_namespace_device(child_handle, acpi_type, parent, &child); + if (ACPI_SUCCESS(status)) { + status = acpi_get_next_object(ACPI_TYPE_ANY, child_handle, 0, NULL); + if (ACPI_SUCCESS(status)) { + level++; + parent_handle = child_handle; + child_handle = 0; + parent = child; + } + } + break; + } + } + + /* + * Scope Exhausted: + * ---------------- + * No more children in this object's scope, Go back up + * in the namespace tree to the object's parent. + */ + else { + level--; + child_handle = parent_handle; + acpi_get_parent(parent_handle, + &parent_handle); + + if (parent) { + parent = parent->parent; + } + else { + return_ACPI_STATUS(AE_NULL_ENTRY); + } + } + } + + return_ACPI_STATUS(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: bm_add_fixed_feature_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_add_fixed_feature_device ( + BM_NODE *parent, + BM_DEVICE_TYPE device_type, + char *device_hid) +{ + ACPI_STATUS status = AE_OK; + BM_NODE *node = NULL; + + FUNCTION_TRACE("bm_add_fixed_feature_device"); + + if (!parent) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (node_list.count > BM_HANDLES_MAX) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* + * Allocate the new device and add to the device array. + */ + node = acpi_os_callocate(sizeof(BM_NODE)); + if (!node) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* + * Get device info. + */ + node->device.handle = node_list.count; + node->device.acpi_handle = ACPI_ROOT_OBJECT; + node->device.id.type = BM_TYPE_FIXED_BUTTON; + if (device_hid) { + MEMCPY((void*)node->device.id.hid, device_hid, + sizeof(node->device.id.hid)); + } + node->device.flags = BM_FLAGS_FIXED_FEATURE; + node->device.status = BM_STATUS_DEFAULT; + /* TBD: Device PM capabilities */ + + /* + * Add to the node_list. + */ + node_list.nodes[node_list.count++] = node; + + /* + * Formulate Hierarchy: + * -------------------- + * Arrange within the namespace by assigning the parent and + * adding to the parent device's list of children (scope). + */ + node->parent = parent; + node->next = NULL; + + if (parent) { + if (!parent->scope.head) { + parent->scope.head = node; + } + else { + if (!parent->scope.tail) { + (parent->scope.head)->next = node; + } + else { + (parent->scope.tail)->next = node; + } + } + parent->scope.tail = node; + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_enumerate_fixed_features + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_enumerate_fixed_features (void) +{ + FUNCTION_TRACE("bm_enumerate_fixed_features"); + + /* + * Root Object: + * ------------ + * Fabricate the root object, which happens to always get a + * device_handle of zero. + */ + node_list.nodes[0] = acpi_os_callocate(sizeof(BM_NODE)); + if (NULL == (node_list.nodes[0])) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + node_list.nodes[0]->device.handle = BM_HANDLE_ROOT; + node_list.nodes[0]->device.acpi_handle = ACPI_ROOT_OBJECT; + node_list.nodes[0]->device.flags = BM_FLAGS_UNKNOWN; + node_list.nodes[0]->device.status = BM_STATUS_DEFAULT; + node_list.nodes[0]->device.id.type = BM_TYPE_SYSTEM; + /* TBD: Get system PM capabilities (Sx states?) */ + + node_list.count++; + + /* + * Fixed Features: + * --------------- + * Enumerate fixed-feature devices (e.g. power and sleep buttons). + */ + if (acpi_fadt.pwr_button == 0) { + bm_add_fixed_feature_device(node_list.nodes[0], + BM_TYPE_FIXED_BUTTON, BM_HID_POWER_BUTTON); + } + + if (acpi_fadt.sleep_button == 0) { + bm_add_fixed_feature_device(node_list.nodes[0], + BM_TYPE_FIXED_BUTTON, BM_HID_SLEEP_BUTTON); + } + + return_ACPI_STATUS(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: bm_get_handle + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_get_handle ( + ACPI_HANDLE acpi_handle, + BM_HANDLE *device_handle) +{ + ACPI_STATUS status = AE_NOT_FOUND; + u32 i = 0; + + FUNCTION_TRACE("bm_get_handle"); + + if (!device_handle) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + *device_handle = BM_HANDLE_UNKNOWN; + + /* + * Search all devices for a match on the ACPI handle. + */ + for (i=0; idevice.acpi_handle == acpi_handle) { + *device_handle = node_list.nodes[i]->device.handle; + status = AE_OK; + break; + } + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_get_node + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_get_node ( + BM_HANDLE device_handle, + ACPI_HANDLE acpi_handle, + BM_NODE **node) +{ + ACPI_STATUS status = AE_OK; + + FUNCTION_TRACE("bm_get_node"); + + if (!node) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* busmgr failed to init, but we're being called by subordinate drivers */ + if (node_list.count < 1) { + return_ACPI_STATUS(AE_NOT_FOUND); + } + + /* + * If no device handle, resolve acpi handle to device handle. + */ + if (!device_handle && acpi_handle) { + status = bm_get_handle(acpi_handle, &device_handle); + if (ACPI_FAILURE(status)) + return_ACPI_STATUS(status); + } + + /* + * Valid device handle? + */ + if (device_handle > BM_HANDLES_MAX) { + DEBUG_PRINT(ACPI_ERROR, ("Invalid node handle [%02x] detected.\n", device_handle)); + return_ACPI_STATUS(AE_ERROR); + } + + *node = node_list.nodes[device_handle]; + + /* + * Valid node? + */ + if (!(*node)) { + DEBUG_PRINT(ACPI_ERROR, ("Invalid (NULL) node entry [%02x] detected.\n", device_handle)); + return_ACPI_STATUS(AE_NULL_ENTRY); + } + + return_ACPI_STATUS(AE_OK); +} + + +/**************************************************************************** + * External Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_initialize + * + * PARAMETERS: + * + * RETURN: Exception code. + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_initialize (void) +{ + ACPI_STATUS status = AE_OK; + u32 start = 0; + u32 stop = 0; + u32 elapsed = 0; + + FUNCTION_TRACE("bm_initialize"); + + MEMSET(&node_list, 0, sizeof(BM_NODE_LIST)); + + status = acpi_get_timer(&start); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + DEBUG_PRINT(ACPI_INFO, ("Building device hierarchy.\n")); + + /* + * Enumerate ACPI fixed-feature devices. + */ + status = bm_enumerate_fixed_features(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Enumerate the ACPI namespace. + */ + status = bm_enumerate_namespace(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + acpi_get_timer(&stop); + acpi_get_timer_duration(start, stop, &elapsed); + + DEBUG_PRINT(ACPI_INFO, ("Building device hierarchy took [%d] microseconds.\n", elapsed)); + + /* + * Display hierarchy. + */ + bm_print_hierarchy(); + + /* + * Register for all standard and device-specific notifications. + */ + DEBUG_PRINT(ACPI_INFO, ("Registering for all device notifications.\n")); + + status = acpi_install_notify_handler(ACPI_ROOT_OBJECT, + ACPI_SYSTEM_NOTIFY, &bm_notify, NULL); + if (ACPI_FAILURE(status)) { + DEBUG_PRINT(ACPI_ERROR, ("Unable to register for standard notifications.\n")); + return_ACPI_STATUS(status); + } + + status = acpi_install_notify_handler(ACPI_ROOT_OBJECT, + ACPI_DEVICE_NOTIFY, &bm_notify, NULL); + if (ACPI_FAILURE(status)) { + DEBUG_PRINT(ACPI_ERROR, ("Unable to register for device-specific notifications.\n")); + return_ACPI_STATUS(status); + } + + DEBUG_PRINT(ACPI_INFO, ("ACPI Bus Manager enabled.\n")); + + /* + * Initialize built-in power resource driver. + */ + bm_pr_initialize(); + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_terminate + * + * PARAMETERS: + * + * RETURN: Exception code. + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_terminate (void) +{ + ACPI_STATUS status = AE_OK; + u32 i = 0; + + FUNCTION_TRACE("bm_terminate"); + + /* + * Terminate built-in power resource driver. + */ + bm_pr_terminate(); + + /* + * Unregister for all notifications. + */ + DEBUG_PRINT(ACPI_INFO, ("Unregistering for device notifications.\n")); + + status = acpi_remove_notify_handler(ACPI_ROOT_OBJECT, + ACPI_SYSTEM_NOTIFY, &bm_notify); + if (ACPI_FAILURE(status)) { + DEBUG_PRINT(ACPI_ERROR, ("Unable to un-register for standard notifications.\n")); + } + + status = acpi_remove_notify_handler(ACPI_ROOT_OBJECT, + ACPI_DEVICE_NOTIFY, &bm_notify); + if (ACPI_FAILURE(status)) { + DEBUG_PRINT(ACPI_ERROR, ("Unable to un-register for device-specific notifications.\n")); + } + + /* + * Parse through the device array, freeing all entries. + */ + DEBUG_PRINT(ACPI_INFO, ("Removing device hierarchy.\n")); + for (i = 0; i < node_list.count; i++) { + if (node_list.nodes[i]) { + acpi_os_free(node_list.nodes[i]); + } + } + + DEBUG_PRINT(ACPI_INFO, ("ACPI Bus Manager disabled.\n")); + + return_ACPI_STATUS(AE_OK); +} diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/busmgr/bm_osl.c linux/drivers/acpi/ospm/busmgr/bm_osl.c --- v2.4.5/linux/drivers/acpi/ospm/busmgr/bm_osl.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/busmgr/bm_osl.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,383 @@ +/***************************************************************************** + * + * Module Name: bm_osl.c + * $Revision: 11 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 "bm.h" + + +MODULE_AUTHOR("Andrew Grover"); +MODULE_DESCRIPTION("ACPI Component Architecture (CA) - ACPI Bus Manager"); + + +#ifdef ACPI_DEBUG + +static int dbg_layer = ACPI_COMPONENT_DEFAULT; +MODULE_PARM(dbg_layer, "i"); +MODULE_PARM_DESC(dbg_layer, "Controls debug output (see acpi_dbg_layer).\n"); + +static int dbg_level = DEBUG_DEFAULT; +MODULE_PARM(dbg_level, "i"); +MODULE_PARM_DESC(dbg_level, "Controls debug output (see acpi_dbg_level).\n"); + +#endif /*ACPI_DEBUG*/ + + +/***************************************************************************** + * Types & Defines + *****************************************************************************/ + +typedef struct +{ + BM_HANDLE device_handle; + char *device_type; + char *device_instance; + u32 event_type; + u32 event_data; + struct list_head list; +} BM_OSL_EVENT; + + +#define BM_PROC_ROOT "acpi" +#define BM_PROC_EVENT "event" +#define BM_PROC_DEVICES "devices" + +#define BM_MAX_STRING_LENGTH 80 + + +/**************************************************************************** + * Globals + ****************************************************************************/ + +struct proc_dir_entry *bm_proc_root = NULL; +static struct proc_dir_entry *bm_proc_event = NULL; + +#ifdef ACPI_DEBUG +static u32 save_dbg_layer; +static u32 save_dbg_level; +#endif /*ACPI_DEBUG*/ + +extern BM_NODE_LIST node_list; + +static spinlock_t bm_osl_event_lock = SPIN_LOCK_UNLOCKED; + +static LIST_HEAD(bm_event_list); + +static DECLARE_WAIT_QUEUE_HEAD(bm_event_wait_queue); + +static int event_is_open = 0; + + +/**************************************************************************** + * Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_osl_generate_event + * + * DESCRIPTION: Generates an event for user-space consumption by writing + * the event data to the 'event' file. + * + ****************************************************************************/ + +ACPI_STATUS +bm_osl_generate_event ( + BM_HANDLE device_handle, + char *device_type, + char *device_instance, + u32 event_type, + u32 event_data) +{ + BM_OSL_EVENT *event = NULL; + u32 flags = 0; + + /* drop event on the floor if no one's listening */ + if (!event_is_open) + return (AE_OK); + + /* + * Allocate a new event structure. + */ + event = acpi_os_callocate(sizeof(BM_OSL_EVENT)); + if (!event) + goto alloc_error; + + event->device_type = acpi_os_callocate(strlen(device_type) + + sizeof(char)); + if (!event->device_type) + goto alloc_error; + + event->device_instance = acpi_os_callocate(strlen(device_instance) + + sizeof(char)); + if (!event->device_instance) + goto alloc_error; + + /* + * Set event data. + */ + event->device_handle = device_handle; + strcpy(event->device_type, device_type); + strcpy(event->device_instance, device_instance); + event->event_type = event_type; + event->event_data = event_data; + + /* + * Add to the end of our event list. + */ + spin_lock_irqsave(&bm_osl_event_lock, flags); + list_add_tail(&event->list, &bm_event_list); + spin_unlock_irqrestore(&bm_osl_event_lock, flags); + + /* + * Signal waiting threads (if any). + */ + wake_up_interruptible(&bm_event_wait_queue); + + return(AE_OK); + +alloc_error: + if (event->device_instance) + acpi_os_free(event->device_instance); + + if (event->device_type) + acpi_os_free(event->device_type); + + if (event) + acpi_os_free(event); + + return (AE_NO_MEMORY); +} + +static int bm_osl_open_event(struct inode *inode, struct file *file) +{ + spin_lock_irq (&bm_osl_event_lock); + + if(event_is_open) + goto out_busy; + + event_is_open = 1; + + spin_unlock_irq (&bm_osl_event_lock); + return 0; + +out_busy: + spin_unlock_irq (&bm_osl_event_lock); + return -EBUSY; +} + + +static int bm_osl_close_event(struct inode *inode, struct file *file) +{ + event_is_open = 0; + return 0; +} + +/**************************************************************************** + * + * FUNCTION: bm_osl_read_event + * + * DESCRIPTION: Handles reads to the 'event' file by blocking user-mode + * threads until data (an event) is generated. + * + ****************************************************************************/ +static ssize_t +bm_osl_read_event( + struct file *file, + char *buf, + size_t count, + loff_t *ppos) +{ + char str[BM_MAX_STRING_LENGTH]; + int size; + BM_OSL_EVENT *event = NULL; + unsigned long flags = 0; + + DECLARE_WAITQUEUE(wait, current); + + if (count < BM_MAX_STRING_LENGTH) { + return 0; + } + + if (list_empty(&bm_event_list)) { + + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&bm_event_wait_queue, &wait); + + if (list_empty(&bm_event_list)) { + schedule(); + } + + remove_wait_queue(&bm_event_wait_queue, &wait); + set_current_state(TASK_RUNNING); + + if (signal_pending(current)) { + return -ERESTARTSYS; + } + } + + spin_lock_irqsave(&bm_osl_event_lock, flags); + event = list_entry(bm_event_list.next, BM_OSL_EVENT, list); + list_del(&event->list); + spin_unlock_irqrestore(&bm_osl_event_lock, flags); + + /* BUG: buffer overrun? */ + size = sprintf(str, "%s %s %08x %08x\n", + event->device_type, event->device_instance, + event->event_type, event->event_data); + + acpi_os_free(event->device_type); + acpi_os_free(event->device_instance); + acpi_os_free(event); + + if (copy_to_user(buf, str, size)) + return -EFAULT; + + *ppos += size; + + return size; +} + +struct file_operations proc_event_operations = { + open: bm_osl_open_event, + read: bm_osl_read_event, + release: bm_osl_close_event, +}; + +/**************************************************************************** + * + * FUNCTION: bm_osl_init + * + ****************************************************************************/ + +int +bm_osl_init(void) +{ + ACPI_STATUS status = AE_OK; + +#ifdef ACPI_DEBUG + save_dbg_layer = acpi_dbg_layer; + acpi_dbg_layer = dbg_layer; + + save_dbg_level = acpi_dbg_level; + acpi_dbg_level = dbg_level; +#endif /*ACPI_DEBUG*/ + + bm_proc_root = proc_mkdir(BM_PROC_ROOT, NULL); + if (!bm_proc_root) { + return(AE_ERROR); + } + + bm_proc_event = create_proc_entry(BM_PROC_EVENT, S_IRUSR, bm_proc_root); + if (bm_proc_event) { + bm_proc_event->proc_fops = &proc_event_operations; + } + + status = bm_initialize(); + + return (ACPI_SUCCESS(status)) ? 0 : -ENODEV; +} + + +/**************************************************************************** + * + * FUNCTION: bm_osl_cleanup + * + ****************************************************************************/ + +void +bm_osl_cleanup(void) +{ + bm_terminate(); + + if (bm_proc_event) { + remove_proc_entry(BM_PROC_EVENT, bm_proc_root); + bm_proc_event = NULL; + } + + if (bm_proc_root) { + remove_proc_entry(BM_PROC_ROOT, NULL); + bm_proc_root = NULL; + } + +#ifdef ACPI_DEBUG + acpi_dbg_layer = save_dbg_layer; + acpi_dbg_level = save_dbg_level; +#endif /*ACPI_DEBUG*/ + + return; +} + + +module_init(bm_osl_init); +module_exit(bm_osl_cleanup); + + +/**************************************************************************** + * Symbols + ****************************************************************************/ + +/* bm.c */ + +EXPORT_SYMBOL(bm_get_node); + +/* bmdriver.c */ + +EXPORT_SYMBOL(bm_get_device_power_state); +EXPORT_SYMBOL(bm_set_device_power_state); +EXPORT_SYMBOL(bm_get_device_info); +EXPORT_SYMBOL(bm_get_device_status); +EXPORT_SYMBOL(bm_get_device_context); +EXPORT_SYMBOL(bm_register_driver); +EXPORT_SYMBOL(bm_unregister_driver); + +/* bmsearch.c */ + +EXPORT_SYMBOL(bm_search); + +/* bmrequest.c */ + +EXPORT_SYMBOL(bm_request); + +/* bmutils.c */ + +EXPORT_SYMBOL(bm_extract_package_data); +EXPORT_SYMBOL(bm_evaluate_object); +EXPORT_SYMBOL(bm_evaluate_simple_integer); +EXPORT_SYMBOL(bm_evaluate_reference_list); +EXPORT_SYMBOL(bm_copy_to_buffer); +EXPORT_SYMBOL(bm_cast_buffer); + +/* bm_proc.c */ + +EXPORT_SYMBOL(bm_osl_generate_event); +EXPORT_SYMBOL(bm_proc_root); diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/busmgr/bmdriver.c linux/drivers/acpi/ospm/busmgr/bmdriver.c --- v2.4.5/linux/drivers/acpi/ospm/busmgr/bmdriver.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/busmgr/bmdriver.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,469 @@ +/***************************************************************************** + * + * Module Name: bmdriver.c + * $Revision: 17 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 "bm.h" + +#define _COMPONENT ACPI_BUS + MODULE_NAME ("bmdriver") + + +/**************************************************************************** + * External Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_get_device_power_state + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_get_device_power_state ( + BM_HANDLE device_handle, + BM_POWER_STATE *state) +{ + ACPI_STATUS status = AE_OK; + BM_NODE *node = NULL; + + FUNCTION_TRACE("bm_get_device_power_state"); + + if (!state) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + *state = ACPI_STATE_UNKNOWN; + + /* + * Resolve device handle to node. + */ + status = bm_get_node(device_handle, 0, &node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Get the current power state. + */ + status = bm_get_power_state(node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + *state = node->device.power.state; + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_set_device_power_state + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_set_device_power_state ( + BM_HANDLE device_handle, + BM_POWER_STATE state) +{ + ACPI_STATUS status = AE_OK; + BM_NODE *node = NULL; + + FUNCTION_TRACE("bm_set_device_power_state"); + + /* + * Resolve device handle to node. + */ + status = bm_get_node(device_handle, 0, &node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Set the current power state. + */ + status = bm_set_power_state(node, state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_get_device_status + * + * PARAMETERS: + * device_handle is really an index number into the array of BM_DEVICE + * structures in info_list. This data item is passed to + * the registered program's "notify" callback. It is used + * to retrieve the specific BM_DEVICE structure instance + * associated with the callback. + * device_status is a pointer that receives the result of processing + * the device's associated ACPI _STA. + * + * RETURN: + * The ACPI_STATUS value indicates success AE_OK or failure of the function + * + * DESCRIPTION: Evaluates the device's ACPI _STA, if it is present. + * + ****************************************************************************/ + +ACPI_STATUS +bm_get_device_status ( + BM_HANDLE device_handle, + BM_DEVICE_STATUS *device_status) +{ + ACPI_STATUS status = AE_OK; + BM_NODE *node = NULL; + + FUNCTION_TRACE("bm_get_device_status"); + + if (!device_status) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + *device_status = BM_STATUS_UNKNOWN; + + /* + * Resolve device handle to node. + */ + status = bm_get_node(device_handle, 0, &node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Parent Present? + * --------------- + * If the parent isn't present we can't evalute _STA on the child. + * Return an unknown status. + */ + if (!BM_NODE_PRESENT(node->parent)) { + return_ACPI_STATUS(AE_OK); + } + + /* + * Dynamic Status? + * --------------- + * If _STA isn't present we just return the default status. + */ + if (!(node->device.flags & BM_FLAGS_DYNAMIC_STATUS)) { + *device_status = BM_STATUS_DEFAULT; + return_ACPI_STATUS(AE_OK); + } + + /* + * Evaluate _STA: + * -------------- + */ + status = bm_evaluate_simple_integer(node->device.acpi_handle, "_STA", + &(node->device.status)); + if (ACPI_SUCCESS(status)) { + *device_status = node->device.status; + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_get_device_info + * + * PARAMETERS: + * device_handle An index used to retrieve the associated BM_DEVICE info. + * device A pointer to a BM_DEVICE structure instance pointer. + * This pointed to BM_DEVICE structure will contain the + * this device's information. + * + * RETURN: + * The ACPI_STATUS value indicates success AE_OK or failure of the function + * + * DESCRIPTION: + * Using the device_handle this function retrieves this device's + * BM_DEVICE structure instance and save's it in device. + * + ****************************************************************************/ + +ACPI_STATUS +bm_get_device_info ( + BM_HANDLE device_handle, + BM_DEVICE **device) +{ + ACPI_STATUS status = AE_OK; + BM_NODE *node = NULL; + + FUNCTION_TRACE("bm_get_device_info"); + + if (!device) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* + * Resolve device handle to internal device. + */ + status = bm_get_node(device_handle, 0, &node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + *device = &(node->device); + + return_ACPI_STATUS(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: bm_get_device_context + * + * device_handle An index used to retrieve the associated BM_DEVICE info. + * context A pointer to a BM_DRIVER_CONTEXT structure instance. + * + * RETURN: + * The ACPI_STATUS value indicates success AE_OK or failure of the function + * + * DESCRIPTION: + * Using the device_handle this function retrieves this device's + * BM_DRIVER_CONTEXT structure instance and save's it in context. + * + ****************************************************************************/ + +ACPI_STATUS +bm_get_device_context ( + BM_HANDLE device_handle, + BM_DRIVER_CONTEXT *context) +{ + ACPI_STATUS status = AE_OK; + BM_NODE *node = NULL; + + FUNCTION_TRACE("bm_get_device_context"); + + if (!context) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + *context = NULL; + + /* + * Resolve device handle to internal device. + */ + status = bm_get_node(device_handle, 0, &node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + if (!node->driver.context) { + return_ACPI_STATUS(AE_NULL_ENTRY); + } + + *context = node->driver.context; + + return_ACPI_STATUS(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: bm_register_driver + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_register_driver ( + BM_DEVICE_ID *criteria, + BM_DRIVER *driver) +{ + ACPI_STATUS status = AE_NOT_FOUND; + BM_HANDLE_LIST device_list; + BM_NODE *node = NULL; + BM_DEVICE *device = NULL; + u32 i = 0; + + FUNCTION_TRACE("bm_register_driver"); + + if (!criteria || !driver || !driver->notify || !driver->request) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + MEMSET(&device_list, 0, sizeof(BM_HANDLE_LIST)); + + /* + * Find Matches: + * ------------- + * Search through the entire device hierarchy for matches against + * the given device criteria. + */ + status = bm_search(BM_HANDLE_ROOT, criteria, &device_list); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Install driver: + * ---------------- + * For each match, record the driver information and execute the + * driver's Notify() funciton (if present) to notify the driver + * of the device's presence. + */ + for (i = 0; i < device_list.count; i++) { + + /* Resolve the device handle. */ + status = bm_get_node(device_list.handles[i], 0, &node); + if (ACPI_FAILURE(status)) { + continue; + } + + device = &(node->device); + + /* + * Make sure another driver hasn't already registered for + * this device. + */ + if (BM_IS_DRIVER_CONTROL(device)) { + DEBUG_PRINT(ACPI_INFO, ("Another driver has already registered for device [%02x].\n", device->handle)); + continue; + } + + DEBUG_PRINT(ACPI_INFO, ("Registering driver for device [%02x].\n", device->handle)); + + /* Notify driver of new device. */ + status = driver->notify(BM_NOTIFY_DEVICE_ADDED, + node->device.handle, &(node->driver.context)); + if (ACPI_SUCCESS(status)) { + node->driver.notify = driver->notify; + node->driver.request = driver->request; + node->device.flags |= BM_FLAGS_DRIVER_CONTROL; + } + } + + return_ACPI_STATUS(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: bm_unregister_driver + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_unregister_driver ( + BM_DEVICE_ID *criteria, + BM_DRIVER *driver) +{ + ACPI_STATUS status = AE_NOT_FOUND; + BM_HANDLE_LIST device_list; + BM_NODE *node = NULL; + BM_DEVICE *device = NULL; + u32 i = 0; + + FUNCTION_TRACE("bm_unregister_driver"); + + if (!criteria || !driver || !driver->notify || !driver->request) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + MEMSET(&device_list, 0, sizeof(BM_HANDLE_LIST)); + + /* + * Find Matches: + * ------------- + * Search through the entire device hierarchy for matches against + * the given device criteria. + */ + status = bm_search(BM_HANDLE_ROOT, criteria, &device_list); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Remove driver: + * --------------- + * For each match, execute the driver's Notify() function to allow + * the driver to cleanup each device instance. + */ + for (i = 0; i < device_list.count; i++) { + + /* Resolve the device handle. */ + status = bm_get_node(device_list.handles[i], 0, &node); + if (ACPI_FAILURE(status)) { + continue; + } + + device = &(node->device); + + /* + * Make sure driver has really registered for this device. + */ + if (!BM_IS_DRIVER_CONTROL(device)) { + DEBUG_PRINT(ACPI_INFO, ("Driver hasn't registered for device [%02x].\n", device->handle)); + continue; + } + + DEBUG_PRINT(ACPI_INFO, ("Unregistering driver for device [%02x].\n", device->handle)); + + /* Notify driver of device removal. */ + status = node->driver.notify(BM_NOTIFY_DEVICE_REMOVED, + node->device.handle, &(node->driver.context)); + if (ACPI_SUCCESS(status)) { + node->driver.notify = NULL; + node->driver.request = NULL; + node->driver.context = NULL; + node->device.flags &= ~BM_FLAGS_DRIVER_CONTROL; + } + } + + return_ACPI_STATUS(AE_OK); +} diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/busmgr/bmnotify.c linux/drivers/acpi/ospm/busmgr/bmnotify.c --- v2.4.5/linux/drivers/acpi/ospm/busmgr/bmnotify.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/busmgr/bmnotify.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,312 @@ +/***************************************************************************** + * + * Module Name: bmnotify.c + * $Revision: 17 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 "bm.h" + + +#define _COMPONENT ACPI_BUS + MODULE_NAME ("bmnotify") + + +/**************************************************************************** + * Internal Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_generate_notify + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_generate_notify ( + BM_NODE *node, + u32 notify_type) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE *device = NULL; + + FUNCTION_TRACE("bm_generate_notify"); + + if (!node) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + device = &(node->device); + + DEBUG_PRINT(ACPI_INFO, ("Sending notify [%02x] to device [%02x].\n", notify_type, node->device.handle)); + + if (!BM_IS_DRIVER_CONTROL(device)) { + DEBUG_PRINT(ACPI_INFO, ("No driver installed for device [%02x].\n", device->handle)); + return_ACPI_STATUS(AE_NOT_EXIST); + } + + status = node->driver.notify(notify_type, node->device.handle, + &(node->driver.context)); + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_device_check + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_device_check ( + BM_NODE *node, + u32 *status_change) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE *device = NULL; + BM_DEVICE_STATUS old_status = BM_STATUS_UNKNOWN; + + FUNCTION_TRACE("bm_device_check"); + + if (!node) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + device = &(node->device); + + if (status_change) { + *status_change = FALSE; + } + + old_status = device->status; + + /* + * Parent Present? + * --------------- + * Only check this device if its parent is present (which implies + * this device MAY be present). + */ + if (!BM_NODE_PRESENT(node->parent)) { + return_ACPI_STATUS(AE_OK); + } + + /* + * Get Status: + * ----------- + * And see if the status has changed. + */ + status = bm_get_status(device); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + if (old_status == node->device.status) { + return_ACPI_STATUS(AE_OK); + } + + if (status_change) { + *status_change = TRUE; + } + + /* + * Device Insertion? + * ----------------- + */ + if ((device->status & BM_STATUS_PRESENT) && + !(old_status & BM_STATUS_PRESENT)) { + /* TBD: Make sure driver is loaded, and if not, load. */ + status = bm_generate_notify(node, BM_NOTIFY_DEVICE_ADDED); + } + + /* + * Device Removal? + * --------------- + */ + else if (!(device->status & BM_STATUS_PRESENT) && + (old_status & BM_STATUS_PRESENT)) { + /* TBD: Unload driver if last device instance. */ + status = bm_generate_notify(node, BM_NOTIFY_DEVICE_REMOVED); + } + + return_ACPI_STATUS(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: bm_bus_check + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_bus_check ( + BM_NODE *parent_node) +{ + ACPI_STATUS status = AE_OK; + u32 status_change = FALSE; + + FUNCTION_TRACE("bm_bus_check"); + + if (!parent_node) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* + * Status Change? + * -------------- + */ + status = bm_device_check(parent_node, &status_change); + if (ACPI_FAILURE(status) || !status_change) { + return_ACPI_STATUS(status); + } + + /* + * Enumerate Scope: + * ---------------- + * TBD: Enumerate child devices within this device's scope and + * run bm_device_check()'s on them... + */ + + return_ACPI_STATUS(AE_OK); +} + + +/**************************************************************************** + * External Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_notify + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +void +bm_notify ( + ACPI_HANDLE acpi_handle, + u32 notify_value, + void *context) +{ + ACPI_STATUS status = AE_OK; + BM_NODE *node = NULL; + + FUNCTION_TRACE("bm_notify"); + + /* + * Resolve the ACPI handle. + */ + status = bm_get_node(0, acpi_handle, &node); + if (ACPI_FAILURE(status)) { + DEBUG_PRINT(ACPI_INFO, ("Recieved notify [%02x] for unknown device [%p].\n", notify_value, acpi_handle)); + return_VOID; + } + + /* + * Device-Specific or Standard? + * ---------------------------- + * Device-specific notifies are forwarded to the control module's + * notify() function for processing. Standard notifies are handled + * internally. + */ + if (notify_value > 0x7F) { + status = bm_generate_notify(node, notify_value); + } + else { + switch (notify_value) { + + case BM_NOTIFY_BUS_CHECK: + DEBUG_PRINT(ACPI_INFO, ("Received BUS CHECK notification for device [%02x].\n", node->device.handle)); + status = bm_bus_check(node); + break; + + case BM_NOTIFY_DEVICE_CHECK: + DEBUG_PRINT(ACPI_INFO, ("Received DEVICE CHECK notification for device [%02x].\n", node->device.handle)); + status = bm_device_check(node, NULL); + break; + + case BM_NOTIFY_DEVICE_WAKE: + DEBUG_PRINT(ACPI_INFO, ("Received DEVICE WAKE notification for device [%02x].\n", node->device.handle)); + /* TBD */ + break; + + case BM_NOTIFY_EJECT_REQUEST: + DEBUG_PRINT(ACPI_INFO, ("Received EJECT REQUEST notification for device [%02x].\n", node->device.handle)); + /* TBD */ + break; + + case BM_NOTIFY_DEVICE_CHECK_LIGHT: + DEBUG_PRINT(ACPI_INFO, ("Received DEVICE CHECK LIGHT notification for device [%02x].\n", node->device.handle)); + /* TBD: Exactly what does the 'light' mean? */ + status = bm_device_check(node, NULL); + break; + + case BM_NOTIFY_FREQUENCY_MISMATCH: + DEBUG_PRINT(ACPI_INFO, ("Received FREQUENCY MISMATCH notification for device [%02x].\n", node->device.handle)); + /* TBD */ + break; + + case BM_NOTIFY_BUS_MODE_MISMATCH: + DEBUG_PRINT(ACPI_INFO, ("Received BUS MODE MISMATCH notification for device [%02x].\n", node->device.handle)); + /* TBD */ + break; + + case BM_NOTIFY_POWER_FAULT: + DEBUG_PRINT(ACPI_INFO, ("Received POWER FAULT notification.\n")); + /* TBD */ + break; + + default: + DEBUG_PRINT(ACPI_INFO, ("Received unknown/unsupported notification.\n")); + break; + } + } + + return_VOID; +} + + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/busmgr/bmpm.c linux/drivers/acpi/ospm/busmgr/bmpm.c --- v2.4.5/linux/drivers/acpi/ospm/busmgr/bmpm.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/busmgr/bmpm.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,442 @@ +/***************************************************************************** + * + * Module Name: bmpm.c + * $Revision: 10 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 "bm.h" +#include "bmpower.h" + + +#define _COMPONENT ACPI_BUS + MODULE_NAME ("bmpm") + + +/**************************************************************************** + * Internal Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_get_inferred_power_state + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_get_inferred_power_state ( + BM_DEVICE *device) +{ + ACPI_STATUS status = AE_OK; + BM_HANDLE_LIST pr_list; + BM_POWER_STATE list_state = ACPI_STATE_UNKNOWN; + char object_name[5] = {'_','P','R','0','\0'}; + u32 i = 0; + + FUNCTION_TRACE("bm_get_inferred_power_state"); + + if (!device) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + MEMSET(&pr_list, 0, sizeof(BM_HANDLE_LIST)); + + device->power.state = ACPI_STATE_D3; + + /* + * Calculate Power State: + * ---------------------- + * Try to infer the devices's power state by checking the state of + * the devices's power resources. We start by evaluating _PR0 + * (resource requirements at D0) and work through _PR1 and _PR2. + * We know the current devices power state when all resources (for + * a give Dx state) are ON. If no power resources are on then the + * device is assumed to be off (D3). + */ + for (i=ACPI_STATE_D0; iacpi_handle, + object_name, &pr_list); + + if (ACPI_SUCCESS(status)) { + + status = bm_pr_list_get_state(&pr_list, &list_state); + + if (ACPI_SUCCESS(status)) { + + if (list_state == ACPI_STATE_D0) { + device->power.state = i; + break; + } + } + } + } + + return_ACPI_STATUS(AE_OK); +} + + +/**************************************************************************** + * External Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_get_power_state + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_get_power_state ( + BM_NODE *node) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE *device = NULL; + + FUNCTION_TRACE("bm_get_power_state"); + + if (!node || !node->parent) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + device = &(node->device); + + device->power.state = ACPI_STATE_UNKNOWN; + + /* + * Power Control? + * -------------- + * If this device isn't directly power manageable (e.g. doesn't + * include _PR0/_PS0) then there's nothing to do (state is static). + */ + if (!BM_IS_POWER_CONTROL(device)) { + return_ACPI_STATUS(AE_OK); + } + + /* + * Parent Present? + * --------------- + * Make sure the parent is present before mucking with the child. + */ + if (!BM_NODE_PRESENT(node->parent)) { + return_ACPI_STATUS(AE_NOT_EXIST); + } + + /* + * Get Power State: + * ---------------- + * Either directly (via _PSC) or inferred (via power resource + * dependencies). + */ + if (BM_IS_POWER_STATE(device)) { + status = bm_evaluate_simple_integer(device->acpi_handle, + "_PSC", &(device->power.state)); + } + else { + status = bm_get_inferred_power_state(device); + } + + if (ACPI_SUCCESS(status)) { + DEBUG_PRINT(ACPI_INFO, ("Device [%02x] is at power state [D%d].\n", device->handle, device->power.state)); + } + else { + DEBUG_PRINT(ACPI_INFO, ("Error getting power state for device [%02x]\n", device->handle)); + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_set_power_state + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_set_power_state ( + BM_NODE *node, + BM_POWER_STATE state) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE *device = NULL; + BM_DEVICE *parent_device = NULL; + BM_HANDLE_LIST current_list; + BM_HANDLE_LIST target_list; + char object_name[5] = {'_','P','R','0','\0'}; + + FUNCTION_TRACE("bm_set_power_state"); + + if (!node || !node->parent || (state > ACPI_STATE_D3)) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + MEMSET(¤t_list, 0, sizeof(BM_HANDLE_LIST)); + MEMSET(&target_list, 0, sizeof(BM_HANDLE_LIST)); + + device = &(node->device); + parent_device = &(node->parent->device); + + /* + * Power Control? + * -------------- + * If this device isn't directly power manageable (e.g. doesn't + * include _PR0/_PS0) then return an error (can't set state). + */ + if (!BM_IS_POWER_CONTROL(device)) { + return_ACPI_STATUS(AE_ERROR); + } + + /* + * Parent Present? + * --------------- + * Make sure the parent is present before mucking with the child. + */ + if (!BM_NODE_PRESENT(node->parent)) { + return_ACPI_STATUS(AE_NOT_EXIST); + } + + /* + * Check Parent's Power State: + * --------------------------- + * Can't be in a higher power state (lower Dx value) than parent. + */ + if (state < parent_device->power.state) { + DEBUG_PRINT(ACPI_WARN, ("Cannot set device [%02x] to a higher-powered state than parent_device.\n", device->handle)); + return_ACPI_STATUS(AE_ERROR); + } + + /* + * Get Resources: + * -------------- + * Get the power resources associated with the device's current + * and target power states. + */ + if (device->power.state != ACPI_STATE_UNKNOWN) { + object_name[3] = '0' + device->power.state; + bm_evaluate_reference_list(device->acpi_handle, + object_name, ¤t_list); + } + + object_name[3] = '0' + state; + bm_evaluate_reference_list(device->acpi_handle, object_name, + &target_list); + + /* + * Transition Resources: + * --------------------- + * Transition all power resources referenced by this device to + * the correct power state (taking into consideration sequencing + * and dependencies to other devices). + */ + if (current_list.count || target_list.count) { + status = bm_pr_list_transition(¤t_list, &target_list); + } + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Execute _PSx: + * ------------- + * Execute the _PSx method corresponding to the target Dx state, + * if it exists. + */ + object_name[2] = 'S'; + object_name[3] = '0' + state; + bm_evaluate_object(device->acpi_handle, object_name, NULL, NULL); + + if (ACPI_SUCCESS(status)) { + DEBUG_PRINT(ACPI_INFO, ("Device [%02x] is now at [D%d].\n", device->handle, state)); + device->power.state = state; + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_get_pm_capabilities + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_get_pm_capabilities ( + BM_NODE *node) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE *device = NULL; + BM_DEVICE *parent_device = NULL; + ACPI_HANDLE acpi_handle = NULL; + BM_POWER_STATE dx_supported = ACPI_STATE_UNKNOWN; + char object_name[5] = {'_','S','0','D','\0'}; + u32 i = 0; + + FUNCTION_TRACE("bm_get_pm_capabilities"); + + if (!node || !node->parent) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + device = &(node->device); + parent_device = &(node->parent->device); + + /* + * Power Management Flags: + * ----------------------- + */ + if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PSC", + &acpi_handle))) { + device->power.flags |= BM_FLAGS_POWER_STATE; + } + + if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_IRC", + &acpi_handle))) { + device->power.flags |= BM_FLAGS_INRUSH_CURRENT; + } + + if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PRW", + &acpi_handle))) { + device->power.flags |= BM_FLAGS_WAKE_CAPABLE; + } + + /* + * Device Power State: + * ------------------- + * Note that we can't get the device's power state until we've + * initialized all power resources, so for now we just set to + * unknown. + */ + device->power.state = ACPI_STATE_UNKNOWN; + + /* + * Dx Supported in S0: + * ------------------- + * Figure out which Dx states are supported by this device for the + * S0 (working) state. Note that D0 and D3 are required (assumed). + */ + device->power.dx_supported[ACPI_STATE_S0] = BM_FLAGS_D0_SUPPORT | + BM_FLAGS_D3_SUPPORT; + + if ((ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PR1", + &acpi_handle))) || + (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PS1", + &acpi_handle)))) { + device->power.dx_supported[ACPI_STATE_S0] |= + BM_FLAGS_D1_SUPPORT; + } + + if ((ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PR2", + &acpi_handle))) || + (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PS2", + &acpi_handle)))) { + device->power.dx_supported[ACPI_STATE_S0] |= + BM_FLAGS_D2_SUPPORT; + } + + /* + * Dx Supported in S1-S5: + * ---------------------- + * Figure out which Dx states are supported by this device for + * all other Sx states. + */ + for (i = ACPI_STATE_S1; i <= ACPI_STATE_S5; i++) { + + /* + * D3 support is assumed (off is always possible!). + */ + device->power.dx_supported[i] = BM_FLAGS_D3_SUPPORT; + + /* + * Evalute _SxD: + * ------------- + * Which returns the highest (power) Dx state supported in + * this system (Sx) state. We convert this value to a bit + * mask of supported states (conceptually simpler). + */ + status = bm_evaluate_simple_integer(device->acpi_handle, + object_name, &dx_supported); + if (ACPI_SUCCESS(status)) { + switch (dx_supported) { + case 0: + device->power.dx_supported[i] |= + BM_FLAGS_D0_SUPPORT; + /* fall through */ + case 1: + device->power.dx_supported[i] |= + BM_FLAGS_D1_SUPPORT; + /* fall through */ + case 2: + device->power.dx_supported[i] |= + BM_FLAGS_D2_SUPPORT; + /* fall through */ + case 3: + device->power.dx_supported[i] |= + BM_FLAGS_D3_SUPPORT; + break; + } + + /* + * Validate: + * --------- + * Mask of any states that _Sx_d falsely advertises + * (e.g.claims D1 support but neither _PR2 or _PS2 + * exist). In other words, S1-S5 can't offer a Dx + * state that isn't supported by S0. + */ + device->power.dx_supported[i] &= + device->power.dx_supported[ACPI_STATE_S0]; + } + + object_name[2]++; + } + + return_ACPI_STATUS(AE_OK); +} diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/busmgr/bmpower.c linux/drivers/acpi/ospm/busmgr/bmpower.c --- v2.4.5/linux/drivers/acpi/ospm/busmgr/bmpower.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/busmgr/bmpower.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,663 @@ +/**************************************************************************** + * + * Module Name: bmpower.c - Driver for ACPI Power Resource 'devices' + * $Revision: 14 $ + * + ****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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. Sequencing of power resource list transitions. + * 2. Global serialization of power resource transtions (see ACPI + * spec section 7.1.2/7.1.3). + * 3. Better error handling. + */ + + +#include +#include "bm.h" +#include "bmpower.h" + + +#define _COMPONENT ACPI_BUS + MODULE_NAME ("bmpower") + + +/**************************************************************************** + * Function Prototypes + ****************************************************************************/ + +ACPI_STATUS +bm_pr_notify ( + BM_NOTIFY notify_type, + BM_HANDLE device_handle, + void **context); + +ACPI_STATUS +bm_pr_request ( + BM_REQUEST *request, + void *context); + + +/**************************************************************************** + * Internal Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_pr_print + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_pr_print ( + BM_POWER_RESOURCE *pr) +{ + ACPI_BUFFER buffer; + + if (!pr) { + return(AE_BAD_PARAMETER); + } + + buffer.length = 256; + buffer.pointer = acpi_os_callocate(buffer.length); + if (!buffer.pointer) { + return(AE_NO_MEMORY); + } + + acpi_get_name(pr->acpi_handle, ACPI_FULL_PATHNAME, &buffer); + + acpi_os_printf("Power Resource: found\n"); + + DEBUG_PRINT_RAW(ACPI_INFO, ("+------------------------------------------------------------\n")); + DEBUG_PRINT_RAW(ACPI_INFO, ("| PowerResource[%02x]:[%p] %s\n", pr->device_handle, pr->acpi_handle, buffer.pointer)); + DEBUG_PRINT_RAW(ACPI_INFO, ("| system_level[S%d] resource_order[%d]\n", pr->system_level, pr->resource_order)); + DEBUG_PRINT_RAW(ACPI_INFO, ("| state[D%d] reference_count[%d]\n", pr->state, pr->reference_count)); + DEBUG_PRINT_RAW(ACPI_INFO, ("+------------------------------------------------------------\n")); + + acpi_os_free(buffer.pointer); + + return(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: bm_pr_get_state + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_pr_get_state ( + BM_POWER_RESOURCE *pr) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE_STATUS device_status = BM_STATUS_UNKNOWN; + + FUNCTION_TRACE("bm_pr_get_state"); + + if (!pr) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + pr->state = ACPI_STATE_UNKNOWN; + + /* + * Evaluate _STA: + * -------------- + * Evalute _STA to determine whether the power resource is ON or OFF. + * Note that if the power resource isn't present we'll get AE_OK but + * an unknown status. + */ + status = bm_get_device_status(pr->device_handle, &device_status); + if (ACPI_FAILURE(status)) { + DEBUG_PRINT(ACPI_ERROR, ("Error reading status for power resource [%02x].\n", pr->device_handle)); + return_ACPI_STATUS(status); + } + + /* + * Mask off all bits but the first as some systems return non-standard + * values (e.g. 0x51). + */ + switch (device_status & 0x01) { + case 0: + DEBUG_PRINT(ACPI_INFO, ("Power resource [%02x] is OFF.\n", pr->device_handle)); + pr->state = ACPI_STATE_D3; + break; + case 1: + DEBUG_PRINT(ACPI_INFO, ("Power resource [%02x] is ON.\n", pr->device_handle)); + pr->state = ACPI_STATE_D0; + break; + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_pr_set_state + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_pr_set_state ( + BM_POWER_RESOURCE *pr, + BM_POWER_STATE target_state) +{ + ACPI_STATUS status = AE_OK; + + FUNCTION_TRACE("bm_pr_set_state"); + + if (!pr) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + status = bm_pr_get_state(pr); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + if (target_state == pr->state) { + DEBUG_PRINT(ACPI_INFO, ("Power resource [%02x] already at target power state [D%d].\n", pr->device_handle, pr->state)); + return_ACPI_STATUS(AE_OK); + } + + switch (target_state) { + + case ACPI_STATE_D0: + DEBUG_PRINT(ACPI_INFO, ("Turning power resource [%02x] ON.\n", pr->device_handle)); + status = bm_evaluate_object(pr->acpi_handle, "_ON", NULL, NULL); + break; + + case ACPI_STATE_D3: + DEBUG_PRINT(ACPI_INFO, ("Turning power resource [%02x] OFF.\n", pr->device_handle)); + status = bm_evaluate_object(pr->acpi_handle, "_OFF", NULL, NULL); + break; + + default: + status = AE_BAD_PARAMETER; + break; + } + + status = bm_pr_get_state(pr); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_pr_list_get_state + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_pr_list_get_state ( + BM_HANDLE_LIST *pr_list, + BM_POWER_STATE *power_state) +{ + ACPI_STATUS status = AE_OK; + BM_POWER_RESOURCE *pr = NULL; + u32 i = 0; + + FUNCTION_TRACE("bm_pr_list_get_state"); + + if (!pr_list || !power_state) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (pr_list->count < 1) { + pr->state = ACPI_STATE_UNKNOWN; + return_ACPI_STATUS(AE_ERROR); + } + + (*power_state) = ACPI_STATE_D0; + + /* + * Calculate Current power_state: + * ----------------------------- + * The current state of a list of power resources is ON if all + * power resources are currently in the ON state. In other words, + * if any power resource in the list is OFF then the collection + * isn't fully ON. + */ + for (i = 0; i < pr_list->count; i++) { + + status = bm_get_device_context(pr_list->handles[i], + (BM_DRIVER_CONTEXT*)(&pr)); + if (ACPI_FAILURE(status)) { + DEBUG_PRINT(ACPI_WARN, ("Invalid reference to power resource [%02x].\n", pr_list->handles[i])); + (*power_state) = ACPI_STATE_UNKNOWN; + break; + } + + status = bm_pr_get_state(pr); + if (ACPI_FAILURE(status)) { + (*power_state) = ACPI_STATE_UNKNOWN; + break; + } + + if (pr->state != ACPI_STATE_D0) { + (*power_state) = pr->state; + break; + } + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_pr_list_transition + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_pr_list_transition ( + BM_HANDLE_LIST *current_list, + BM_HANDLE_LIST *target_list) +{ + ACPI_STATUS status = AE_OK; + BM_POWER_RESOURCE *pr = NULL; + u32 i = 0; + + FUNCTION_TRACE("bm_pr_list_transition"); + + if (!current_list || !target_list) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* + * Reference Target: + * ----------------- + * Reference all resources for the target power state first (so + * the device doesn't get turned off while transitioning). Power + * resources that aren't on (new reference count of 1) are turned on. + */ + for (i = 0; i < target_list->count; i++) { + + status = bm_get_device_context(target_list->handles[i], + (BM_DRIVER_CONTEXT*)(&pr)); + if (ACPI_FAILURE(status)) { + DEBUG_PRINT(ACPI_WARN, ("Invalid reference to power resource [%02x].\n", target_list->handles[i])); + continue; + } + + if (++pr->reference_count == 1) { + /* TBD: Need ordering based upon resource_order */ + status = bm_pr_set_state(pr, ACPI_STATE_D0); + if (ACPI_FAILURE(status)) { + /* TBD: How do we handle this? */ + DEBUG_PRINT(ACPI_WARN, ("Unable to change power state for power resource [%02x].\n", target_list->handles[i])); + } + } + } + + /* + * Dereference Current: + * -------------------- + * Dereference all resources for the current power state. Power + * resources no longer referenced (new reference count of 0) are + * turned off. + */ + for (i = 0; i < current_list->count; i++) { + + status = bm_get_device_context(current_list->handles[i], + (BM_DRIVER_CONTEXT*)(&pr)); + if (ACPI_FAILURE(status)) { + DEBUG_PRINT(ACPI_WARN, ("Invalid reference to power resource [%02x].\n", target_list->handles[i])); + continue; + } + + if (--pr->reference_count == 0) { + /* TBD: Need ordering based upon resource_order */ + status = bm_pr_set_state(pr, ACPI_STATE_D3); + if (ACPI_FAILURE(status)) { + /* TBD: How do we handle this? */ + DEBUG_PRINT(ACPI_ERROR, ("Unable to change power state for power resource [%02x].\n", current_list->handles[i])); + } + } + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_pr_add_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_pr_add_device ( + BM_HANDLE device_handle, + void **context) +{ + ACPI_STATUS status = AE_OK; + BM_POWER_RESOURCE *pr = NULL; + BM_DEVICE *device = NULL; + ACPI_BUFFER buffer; + ACPI_OBJECT acpi_object; + + FUNCTION_TRACE("bm_pr_add_device"); + + DEBUG_PRINT(ACPI_INFO, ("Adding power resource [%02x].\n", device_handle)); + + if (!context || *context) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + buffer.length = sizeof(ACPI_OBJECT); + buffer.pointer = &acpi_object; + + /* + * Get information on this device. + */ + status = bm_get_device_info(device_handle, &device); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Allocate a new BM_POWER_RESOURCE structure. + */ + pr = acpi_os_callocate(sizeof(BM_POWER_RESOURCE)); + if (!pr) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + pr->device_handle = device->handle; + pr->acpi_handle = device->acpi_handle; + + /* + * Get information on this power resource. + */ + status = acpi_evaluate_object(pr->acpi_handle, NULL, NULL, &buffer); + if (ACPI_FAILURE(status)) { + goto end; + } + + pr->system_level = acpi_object.power_resource.system_level; + pr->resource_order = acpi_object.power_resource.resource_order; + pr->state = ACPI_STATE_UNKNOWN; + pr->reference_count = 0; + + /* + * Get the power resource's current state (ON|OFF). + */ + status = bm_pr_get_state(pr); + +end: + if (ACPI_FAILURE(status)) { + acpi_os_free(pr); + } + else { + *context = pr; + bm_pr_print(pr); + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_pr_remove_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_pr_remove_device ( + void **context) +{ + ACPI_STATUS status = AE_OK; + BM_POWER_RESOURCE *pr = NULL; + + FUNCTION_TRACE("bm_pr_remove_device"); + + if (!context || !*context) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + pr = (BM_POWER_RESOURCE*)*context; + + DEBUG_PRINT(ACPI_INFO, ("Removing power resource [%02x].\n", pr->device_handle)); + + acpi_os_free(pr); + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * External Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_pr_initialize + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_pr_initialize (void) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE_ID criteria; + BM_DRIVER driver; + + FUNCTION_TRACE("bm_pr_initialize"); + + MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID)); + MEMSET(&driver, 0, sizeof(BM_DRIVER)); + + criteria.type = BM_TYPE_POWER_RESOURCE; + + driver.notify = &bm_pr_notify; + driver.request = &bm_pr_request; + + status = bm_register_driver(&criteria, &driver); + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_pr_terminate + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_pr_terminate (void) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE_ID criteria; + BM_DRIVER driver; + + FUNCTION_TRACE("bm_pr_terminate"); + + MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID)); + MEMSET(&driver, 0, sizeof(BM_DRIVER)); + + criteria.type = BM_TYPE_POWER_RESOURCE; + + driver.notify = &bm_pr_notify; + driver.request = &bm_pr_request; + + status = bm_unregister_driver(&criteria, &driver); + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_pr_notify + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_pr_notify ( + BM_NOTIFY notify_type, + BM_HANDLE device_handle, + void **context) +{ + ACPI_STATUS status = AE_OK; + + FUNCTION_TRACE("bm_pr_notify"); + + switch (notify_type) { + + case BM_NOTIFY_DEVICE_ADDED: + status = bm_pr_add_device(device_handle, context); + break; + + case BM_NOTIFY_DEVICE_REMOVED: + status = bm_pr_remove_device(context); + break; + + default: + status = AE_SUPPORT; + break; + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_pr_request + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_pr_request ( + BM_REQUEST *request, + void *context) +{ + ACPI_STATUS status = AE_OK; + BM_POWER_RESOURCE *pr = NULL; + + FUNCTION_TRACE("bm_pr_request"); + + /* + * Must have a valid request structure and context. + */ + if (!request || !context) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* + * context contains information specific to this power resource. + */ + pr = (BM_POWER_RESOURCE*)context; + + /* + * Handle request: + * --------------- + */ + switch (request->command) { + + default: + status = AE_SUPPORT; + break; + } + + request->status = status; + + return_ACPI_STATUS(status); +} + + + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/busmgr/bmrequest.c linux/drivers/acpi/ospm/busmgr/bmrequest.c --- v2.4.5/linux/drivers/acpi/ospm/busmgr/bmrequest.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/busmgr/bmrequest.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,164 @@ +/****************************************************************************** + * + * Module Name: bmrequest.c + * $Revision: 12 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 "bm.h" + +#define _COMPONENT ACPI_BUS + MODULE_NAME ("bmrequest") + + +/**************************************************************************** + * External Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_generate_request + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_generate_request ( + BM_NODE *node, + BM_REQUEST *request) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE *device = NULL; + + FUNCTION_TRACE("bm_generate_request"); + + if (!node || !request) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + device = &(node->device); + + if (!BM_IS_DRIVER_CONTROL(device)) { + DEBUG_PRINT(ACPI_WARN, ("No driver installed for device [%02x].\n", device->handle)); + return_ACPI_STATUS(AE_NOT_EXIST); + } + + status = node->driver.request(request, node->driver.context); + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_request + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_request ( + BM_REQUEST *request) +{ + ACPI_STATUS status = AE_OK; + BM_NODE *node = NULL; + BM_DEVICE *device = NULL; + + FUNCTION_TRACE("bm_request"); + + /* + * Must have a valid request structure. + */ + if (!request) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + DEBUG_PRINT(ACPI_INFO, ("Received request for device [%02x] command [%02x].\n", request->handle, request->command)); + + /* + * Resolve the node. + */ + status = bm_get_node(request->handle, 0, &node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + device = &(node->device); + + /* + * Device-Specific Request? + * ------------------------ + * If a device-specific command (>=0x80) forward this request to + * the appropriate driver. + */ + if (request->command & BM_COMMAND_DEVICE_SPECIFIC) { + status = bm_generate_request(node, request); + return_ACPI_STATUS(status); + } + + /* + * Bus-Specific Requests: + * ---------------------- + */ + switch (request->command) { + + case BM_COMMAND_GET_POWER_STATE: + status = bm_get_power_state(node); + if (ACPI_FAILURE(status)) { + break; + } + status = bm_copy_to_buffer(&(request->buffer), + &(device->power.state), sizeof(BM_POWER_STATE)); + break; + + case BM_COMMAND_SET_POWER_STATE: + { + BM_POWER_STATE *power_state = NULL; + + status = bm_cast_buffer(&(request->buffer), + (void**)&power_state, sizeof(BM_POWER_STATE)); + if (ACPI_FAILURE(status)) { + break; + } + status = bm_set_power_state(node, *power_state); + } + break; + + default: + status = AE_SUPPORT; + request->status = AE_SUPPORT; + break; + } + + return_ACPI_STATUS(status); +} diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/busmgr/bmsearch.c linux/drivers/acpi/ospm/busmgr/bmsearch.c --- v2.4.5/linux/drivers/acpi/ospm/busmgr/bmsearch.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/busmgr/bmsearch.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,192 @@ +/****************************************************************************** + * + * Module Name: bmsearch.c + * $Revision: 13 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 "bm.h" + + +#define _COMPONENT ACPI_BUS + MODULE_NAME ("bmsearch") + + +/**************************************************************************** + * External Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_compare + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_compare ( + BM_DEVICE *device, + BM_DEVICE_ID *criteria) +{ + if (!device || !criteria) { + return AE_BAD_PARAMETER; + } + + /* + * Present? + * -------- + * We're only going to match on devices that are present. + * TBD: Optimize in bm_search (don't have to call here). + */ + if (!BM_DEVICE_PRESENT(device)) { + return AE_NOT_FOUND; + } + + /* + * Type? + */ + if (criteria->type && (criteria->type != device->id.type)) { + return AE_NOT_FOUND; + } + + /* + * HID? + */ + if ((criteria->hid[0]) && (0 != STRNCMP(criteria->hid, + device->id.hid, sizeof(BM_DEVICE_HID)))) { + return AE_NOT_FOUND; + } + + /* + * ADR? + */ + if ((criteria->adr) && (criteria->adr != device->id.adr)) { + return AE_NOT_FOUND; + } + + return AE_OK; +} + + +/**************************************************************************** + * + * FUNCTION: bm_search + * + * PARAMETERS: + * + * RETURN: AE_BAD_PARAMETER- invalid input parameter + * AE_NOT_EXIST - start_device_handle doesn't exist + * AE_NOT_FOUND - no matches to Search_info.criteria found + * AE_OK - success + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_search( + BM_HANDLE device_handle, + BM_DEVICE_ID *criteria, + BM_HANDLE_LIST *results) +{ + ACPI_STATUS status = AE_OK; + BM_NODE *node = NULL; + + FUNCTION_TRACE("bm_search"); + + if (!criteria || !results) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + results->count = 0; + + /* + * Locate Starting Point: + * ---------------------- + * Locate the node in the hierarchy where we'll begin our search. + */ + status = bm_get_node(device_handle, 0, &node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Parse Hierarchy: + * ---------------- + * Parse through the node hierarchy looking for matches. + */ + while (node && (results->count<=BM_HANDLES_MAX)) { + /* + * Depth-first: + * ------------ + * Searches are always performed depth-first. + */ + if (node->scope.head) { + status = bm_compare(&(node->device), criteria); + if (ACPI_SUCCESS(status)) { + results->handles[results->count++] = + node->device.handle; + } + node = node->scope.head; + } + + /* + * Now Breadth: + * ------------ + * Search all peers until scope is exhausted. + */ + else { + status = bm_compare(&(node->device), criteria); + if (ACPI_SUCCESS(status)) { + results->handles[results->count++] = + node->device.handle; + } + + /* + * Locate Next Device: + * ------------------- + * The next node is either a peer at this level + * (node->next is valid), or we work are way back + * up the tree until we either find a non-parsed + * peer or hit the top (node->parent is NULL). + */ + while (!node->next && node->parent) { + node = node->parent; + } + node = node->next; + } + } + + if (results->count == 0) { + return_ACPI_STATUS(AE_NOT_FOUND); + } + else { + return_ACPI_STATUS(AE_OK); + } +} + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/busmgr/bmutils.c linux/drivers/acpi/ospm/busmgr/bmutils.c --- v2.4.5/linux/drivers/acpi/ospm/busmgr/bmutils.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/busmgr/bmutils.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,608 @@ +/***************************************************************************** + * + * Module Name: bmutils.c + * $Revision: 28 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 "bm.h" + + +#define _COMPONENT ACPI_BUS + MODULE_NAME ("bmutils") + + +#ifdef ACPI_DEBUG +#define DEBUG_EVAL_ERROR(l,h,p,s) bm_print_eval_error(l,h,p,s) +#else +#define DEBUG_EVAL_ERROR(l,h,p,s) +#endif + + +/**************************************************************************** + * External Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_print_eval_error + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +void +bm_print_eval_error ( + u32 debug_level, + ACPI_HANDLE acpi_handle, + ACPI_STRING pathname, + ACPI_STATUS status) +{ + ACPI_BUFFER buffer; + ACPI_STRING status_string = NULL; + + buffer.length = 256; + buffer.pointer = acpi_os_callocate(buffer.length); + if (!buffer.pointer) { + return; + } + + status_string = acpi_ut_format_exception(status); + + status = acpi_get_name(acpi_handle, ACPI_FULL_PATHNAME, &buffer); + if (ACPI_FAILURE(status)) { + DEBUG_PRINT(debug_level, ("Evaluate object [%p], %s\n", acpi_handle, status_string)); + return; + } + + if (pathname) { + DEBUG_PRINT(ACPI_INFO, ("Evaluate object [%s.%s], %s\n", buffer.pointer, pathname, status_string)); + } + else { + DEBUG_PRINT(ACPI_INFO, ("Evaluate object [%s], %s\n", buffer.pointer, status_string)); + } + + acpi_os_free(buffer.pointer); +} + + +/**************************************************************************** + * + * FUNCTION: bm_copy_to_buffer + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_copy_to_buffer ( + ACPI_BUFFER *buffer, + void *data, + u32 length) +{ + FUNCTION_TRACE("bm_copy_to_buffer"); + + if (!buffer || (!buffer->pointer) || !data || (length == 0)) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (length > buffer->length) { + buffer->length = length; + return_ACPI_STATUS(AE_BUFFER_OVERFLOW); + } + + buffer->length = length; + MEMCPY(buffer->pointer, data, length); + + return_ACPI_STATUS(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: bm_cast_buffer + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_cast_buffer ( + ACPI_BUFFER *buffer, + void **pointer, + u32 length) +{ + FUNCTION_TRACE("bm_cast_buffer"); + + if (!buffer || !buffer->pointer || !pointer || length == 0) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (length > buffer->length) { + return_ACPI_STATUS(AE_BAD_DATA); + } + + *pointer = buffer->pointer; + + return_ACPI_STATUS(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: bm_extract_package_data + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +/* + * TBD: Don't assume numbers (in ASL) are 32-bit values!!!! (IA64) + * TBD: Issue with 'assumed' types coming out of interpreter... + * (e.g. toshiba _BIF) + */ + +ACPI_STATUS +bm_extract_package_data ( + ACPI_OBJECT *package, + ACPI_BUFFER *package_format, + ACPI_BUFFER *buffer) +{ + ACPI_STATUS status = AE_OK; + u8 *head = NULL; + u8 *tail = NULL; + u8 **pointer = NULL; + u32 tail_offset = 0; + ACPI_OBJECT *element = NULL; + u32 size_required = 0; + char* format = NULL; + u32 format_count = 0; + u32 i = 0; + + FUNCTION_TRACE("bm_extract_package_data"); + + if (!package || (package->type != ACPI_TYPE_PACKAGE) || + (package->package.count == 0) || !package_format || + (package_format->length < 1) || + (!package_format->pointer) || !buffer) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + format_count = package_format->length - 1; + + if (format_count > package->package.count) { + DEBUG_PRINT(ACPI_WARN, ("Format specifies more objects [%d] than exist in package [%d].", format_count, package->package.count)); + return_ACPI_STATUS(AE_BAD_DATA); + } + + format = (char*)package_format->pointer; + + /* + * Calculate size_required. + */ + for (i=0; ipackage.elements[i]); + + switch (element->type) { + + case ACPI_TYPE_INTEGER: + switch (format[i]) { + case 'N': + size_required += sizeof(ACPI_INTEGER); + tail_offset += sizeof(ACPI_INTEGER); + break; + case 'S': + size_required += sizeof(u8*) + + sizeof(ACPI_INTEGER) + 1; + tail_offset += sizeof(ACPI_INTEGER); + break; + default: + DEBUG_PRINT(ACPI_WARN, ("Invalid package element [%d]: got number, expecing [%c].\n", i, format[i])); + return_ACPI_STATUS(AE_BAD_DATA); + break; + } + break; + + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + switch (format[i]) { + case 'S': + size_required += sizeof(u8*) + + element->string.length + 1; + tail_offset += sizeof(u8*); + break; + case 'B': + size_required += sizeof(u8*) + + element->buffer.length; + tail_offset += sizeof(u8*); + break; + default: + DEBUG_PRINT(ACPI_WARN, ("Invalid package element [%d] got string/buffer, expecing [%c].\n", i, format[i])); + return_ACPI_STATUS(AE_BAD_DATA); + break; + } + break; + + case ACPI_TYPE_PACKAGE: + default: + /* TBD: handle nested packages... */ + return_ACPI_STATUS(AE_SUPPORT); + break; + } + } + + if (size_required > buffer->length) { + buffer->length = size_required; + return_ACPI_STATUS(AE_BUFFER_OVERFLOW); + } + + buffer->length = size_required; + + if (!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]); + + switch (element->type) { + + case ACPI_TYPE_INTEGER: + switch (format[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 = 0; + tail++; + break; + default: + /* Should never get here */ + break; + } + break; + + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + switch (format[i]) { + case 'S': + pointer = (u8**)head; + *pointer = tail; + memcpy(tail, element->string.pointer, + element->string.length); + head += sizeof(u8*); + tail += element->string.length; + /* NULL terminate string */ + *tail = 0; + tail++; + break; + case 'B': + pointer = (u8**)head; + *pointer = tail; + memcpy(tail, element->buffer.pointer, + element->buffer.length); + head += sizeof(u8*); + tail += element->buffer.length; + 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(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_evaluate_object + * + * PARAMETERS: + * + * RETURN: AE_OK + * AE_BUFFER_OVERFLOW Evaluated object returned data, but + * caller did not provide buffer. + * + * DESCRIPTION: Helper for acpi_evaluate_object that handles buffer + * allocation. Note that the caller is responsible for + * freeing buffer->pointer! + * + ****************************************************************************/ + +ACPI_STATUS +bm_evaluate_object ( + ACPI_HANDLE acpi_handle, + ACPI_STRING pathname, + ACPI_OBJECT_LIST *arguments, + ACPI_BUFFER *buffer) +{ + ACPI_STATUS status = AE_OK; + + FUNCTION_TRACE("bm_evaluate_object"); + + /* 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, e.g. _INI); the second + * gets the data. + */ + status = acpi_evaluate_object(acpi_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 = acpi_os_callocate(buffer->length); + if (!buffer->pointer) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Re-evaluate -- this time it should work */ + status = acpi_evaluate_object(acpi_handle, pathname, + arguments, buffer); + } + + if (ACPI_FAILURE(status)) { + if (status != AE_NOT_FOUND) { + DEBUG_EVAL_ERROR(ACPI_WARN, acpi_handle, pathname, + status); + } + if (buffer && buffer->pointer) { + acpi_os_free(buffer->pointer); + buffer->pointer = NULL; + buffer->length = 0; + } + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_evaluate_simple_integer + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_evaluate_simple_integer ( + ACPI_HANDLE acpi_handle, + ACPI_STRING pathname, + u32 *data) +{ + ACPI_STATUS status = AE_OK; + ACPI_OBJECT *element = NULL; + ACPI_BUFFER buffer; + + FUNCTION_TRACE("bm_evaluate_simple_integer"); + + if (!data) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + MEMSET(&buffer, 0, sizeof(ACPI_BUFFER)); + + /* + * Evaluate Object: + * ---------------- + */ + status = bm_evaluate_object(acpi_handle, pathname, NULL, &buffer); + if (ACPI_FAILURE(status)) { + goto end; + } + + /* + * Validate Data: + * -------------- + */ + status = bm_cast_buffer(&buffer, (void**)&element, + sizeof(ACPI_OBJECT)); + if (ACPI_FAILURE(status)) { + DEBUG_EVAL_ERROR(ACPI_WARN, acpi_handle, pathname, status); + goto end; + } + + if (element->type != ACPI_TYPE_INTEGER) { + status = AE_BAD_DATA; + DEBUG_EVAL_ERROR(ACPI_WARN, acpi_handle, pathname, status); + goto end; + } + + *data = element->integer.value; + +end: + acpi_os_free(buffer.pointer); + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_evaluate_reference_list + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_evaluate_reference_list ( + ACPI_HANDLE acpi_handle, + ACPI_STRING pathname, + BM_HANDLE_LIST *reference_list) +{ + ACPI_STATUS status = AE_OK; + ACPI_OBJECT *package = NULL; + ACPI_OBJECT *element = NULL; + ACPI_HANDLE reference_handle = NULL; + ACPI_BUFFER buffer; + u32 i = 0; + + FUNCTION_TRACE("bm_evaluate_reference_list"); + + if (!reference_list) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + MEMSET(&buffer, 0, sizeof(ACPI_BUFFER)); + + /* + * Evaluate Object: + * ---------------- + */ + status = bm_evaluate_object(acpi_handle, pathname, NULL, &buffer); + if (ACPI_FAILURE(status)) { + goto end; + } + + /* + * Validate Package: + * ----------------- + */ + status = bm_cast_buffer(&buffer, (void**)&package, + sizeof(ACPI_OBJECT)); + if (ACPI_FAILURE(status)) { + DEBUG_EVAL_ERROR(ACPI_WARN, acpi_handle, pathname, status); + goto end; + } + + if (package->type != ACPI_TYPE_PACKAGE) { + status = AE_BAD_DATA; + DEBUG_EVAL_ERROR(ACPI_WARN, acpi_handle, pathname, status); + goto end; + } + + if (package->package.count > BM_HANDLES_MAX) { + package->package.count = BM_HANDLES_MAX; + } + + /* + * Parse Package Data: + * ------------------- + */ + for (i = 0; i < package->package.count; i++) { + + element = &(package->package.elements[i]); + + if (!element || (element->type != ACPI_TYPE_STRING)) { + status = AE_BAD_DATA; + DEBUG_PRINT(ACPI_WARN, ("Invalid element in package (not a device reference).\n")); + DEBUG_EVAL_ERROR(ACPI_WARN, acpi_handle, pathname, status); + break; + } + + /* + * Resolve reference string (e.g. "\_PR_.CPU_") to an + * ACPI_HANDLE. + */ + status = acpi_get_handle(acpi_handle, + element->string.pointer, &reference_handle); + if (ACPI_FAILURE(status)) { + status = AE_BAD_DATA; + DEBUG_PRINT(ACPI_WARN, ("Unable to resolve device reference [%s].\n", element->string.pointer)); + DEBUG_EVAL_ERROR(ACPI_WARN, acpi_handle, pathname, status); + break; + } + + /* + * Resolve ACPI_HANDLE to BM_HANDLE. + */ + status = bm_get_handle(reference_handle, + &(reference_list->handles[i])); + if (ACPI_FAILURE(status)) { + status = AE_BAD_DATA; + DEBUG_PRINT(ACPI_WARN, ("Unable to resolve device reference for [%p].\n", reference_handle)); + DEBUG_EVAL_ERROR(ACPI_WARN, acpi_handle, pathname, status); + break; + } + + DEBUG_PRINT(ACPI_INFO, ("Resolved reference [%s]->[%p]->[%02x]\n", element->string.pointer, reference_handle, reference_list->handles[i])); + + (reference_list->count)++; + } + +end: + acpi_os_free(buffer.pointer); + + return_ACPI_STATUS(status); +} + + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/button/Makefile linux/drivers/acpi/ospm/button/Makefile --- v2.4.5/linux/drivers/acpi/ospm/button/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/button/Makefile Wed Jun 20 17:47:40 2001 @@ -0,0 +1,6 @@ +O_TARGET := ospm_$(notdir $(CURDIR)).o +obj-m := $(O_TARGET) +EXTRA_CFLAGS += $(ACPI_CFLAGS) +obj-y := $(patsubst %.c,%.o,$(wildcard *.c)) + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/button/bn.c linux/drivers/acpi/ospm/button/bn.c --- v2.4.5/linux/drivers/acpi/ospm/button/bn.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/button/bn.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,439 @@ +/***************************************************************************** + * + * Module Name: bn.c + * $Revision: 22 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 Plxxe, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include "bn.h" + + +#define _COMPONENT ACPI_BUTTON + MODULE_NAME ("bn") + + +/***************************************************************************** + * Internal Functions + *****************************************************************************/ + +/***************************************************************************** + * + * FUNCTION: bn_print + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: Prints out information on a specific button. + * + ****************************************************************************/ + +void +bn_print ( + BN_CONTEXT *button) +{ + + return; +} + + +/**************************************************************************** + * + * FUNCTION: bn_add_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bn_add_device( + BM_HANDLE device_handle, + void **context) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE *device = NULL; + BN_CONTEXT *button = NULL; + + if (!context || *context) { + return(AE_BAD_PARAMETER); + } + + /* + * Get information on this device. + */ + status = bm_get_device_info( device_handle, &device ); + if (ACPI_FAILURE(status)) { + return(status); + } + + /* + * Allocate a new BN_CONTEXT structure. + */ + button = acpi_os_callocate(sizeof(BN_CONTEXT)); + if (!button) { + return(AE_NO_MEMORY); + } + + button->device_handle = device->handle; + button->acpi_handle = device->acpi_handle; + + /* + * Power Button? + * ------------- + * Either fixed-feature or generic (namespace) types. + */ + if (strncmp(device->id.hid, BN_HID_POWER_BUTTON, + sizeof(BM_DEVICE_HID)) == 0) { + + if (device->id.type == BM_TYPE_FIXED_BUTTON) { + + button->type = BN_TYPE_POWER_BUTTON_FIXED; + + /* Register for fixed-feature events. */ + status = acpi_install_fixed_event_handler( + ACPI_EVENT_POWER_BUTTON, bn_notify_fixed, + (void*)button); + } + else { + button->type = BN_TYPE_POWER_BUTTON; + } + + } + + /* + * Sleep Button? + * ------------- + * Either fixed-feature or generic (namespace) types. + */ + else if (strncmp( device->id.hid, BN_HID_SLEEP_BUTTON, + sizeof(BM_DEVICE_HID)) == 0) { + + if (device->id.type == BM_TYPE_FIXED_BUTTON) { + + button->type = BN_TYPE_SLEEP_BUTTON_FIXED; + + /* Register for fixed-feature events. */ + status = acpi_install_fixed_event_handler( + ACPI_EVENT_SLEEP_BUTTON, bn_notify_fixed, + (void*)button); + } + else { + button->type = BN_TYPE_SLEEP_BUTTON; + } + } + + /* + * LID Switch? + * ----------- + */ + else if (strncmp( device->id.hid, BN_HID_LID_SWITCH, + sizeof(BM_DEVICE_HID)) == 0) { + button->type = BN_TYPE_LID_SWITCH; + } + + status = bn_osl_add_device(button); + if (ACPI_FAILURE(status)) { + goto end; + } + + *context = button; + + bn_print(button); + +end: + if (ACPI_FAILURE(status)) { + acpi_os_free(button); + } + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: bn_remove_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bn_remove_device( + void **context) +{ + ACPI_STATUS status = AE_OK; + BN_CONTEXT *button = NULL; + + if (!context || !*context) { + return(AE_BAD_PARAMETER); + } + + button = (BN_CONTEXT*)*context; + + /* + * Unregister for fixed-feature events. + */ + switch (button->type) { + case BN_TYPE_POWER_BUTTON_FIXED: + status = acpi_remove_fixed_event_handler( + ACPI_EVENT_POWER_BUTTON, bn_notify_fixed); + break; + case BN_TYPE_SLEEP_BUTTON_FIXED: + status = acpi_remove_fixed_event_handler( + ACPI_EVENT_SLEEP_BUTTON, bn_notify_fixed); + break; + } + + bn_osl_remove_device(button); + + acpi_os_free(button); + + *context = NULL; + + return(status); +} + + +/***************************************************************************** + * External Functions + *****************************************************************************/ + +/***************************************************************************** + * + * FUNCTION: bn_initialize + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + + ****************************************************************************/ + +ACPI_STATUS +bn_initialize (void) +{ + BM_DEVICE_ID criteria; + BM_DRIVER driver; + + MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID)); + MEMSET(&driver, 0, sizeof(BM_DRIVER)); + + driver.notify = &bn_notify; + driver.request = &bn_request; + + /* + * Register for power buttons. + */ + MEMCPY(criteria.hid, BN_HID_POWER_BUTTON, sizeof(BN_HID_POWER_BUTTON)); + bm_register_driver(&criteria, &driver); + + /* + * Register for sleep buttons. + */ + MEMCPY(criteria.hid, BN_HID_SLEEP_BUTTON, sizeof(BN_HID_SLEEP_BUTTON)); + bm_register_driver(&criteria, &driver); + + /* + * Register for LID switches. + */ + MEMCPY(criteria.hid, BN_HID_LID_SWITCH, sizeof(BN_HID_LID_SWITCH)); + bm_register_driver(&criteria, &driver); + + return(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: bn_terminate + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bn_terminate (void) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE_ID criteria; + BM_DRIVER driver; + + MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID)); + MEMSET(&driver, 0, sizeof(BM_DRIVER)); + + driver.notify = &bn_notify; + driver.request = &bn_request; + + /* + * Unregister for power buttons. + */ + MEMCPY(criteria.hid, BN_HID_POWER_BUTTON, sizeof(BN_HID_POWER_BUTTON)); + status = bm_unregister_driver(&criteria, &driver); + + /* + * Unregister for sleep buttons. + */ + MEMCPY(criteria.hid, BN_HID_SLEEP_BUTTON, sizeof(BN_HID_SLEEP_BUTTON)); + status = bm_unregister_driver(&criteria, &driver); + + /* + * Unregister for LID switches. + */ + MEMCPY(criteria.hid, BN_HID_LID_SWITCH, sizeof(BN_HID_LID_SWITCH)); + status = bm_unregister_driver(&criteria, &driver); + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: bn_notify_fixed + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bn_notify_fixed ( + void *context) +{ + ACPI_STATUS status = AE_OK; + + if (!context) { + return(AE_BAD_PARAMETER); + } + + status = bn_osl_generate_event(BN_NOTIFY_STATUS_CHANGE, + ((BN_CONTEXT*)context)); + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: bn_notify + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bn_notify ( + BM_NOTIFY notify_type, + BM_HANDLE device_handle, + void **context) +{ + ACPI_STATUS status = AE_OK; + + if (!context) { + return(AE_BAD_PARAMETER); + } + + switch (notify_type) { + case BM_NOTIFY_DEVICE_ADDED: + status = bn_add_device(device_handle, context); + break; + + case BM_NOTIFY_DEVICE_REMOVED: + status = bn_remove_device(context); + break; + + case BN_NOTIFY_STATUS_CHANGE: + status = bn_osl_generate_event(BN_NOTIFY_STATUS_CHANGE, + ((BN_CONTEXT*)*context)); + break; + + default: + status = AE_SUPPORT; + break; + } + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: bn_request + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bn_request ( + BM_REQUEST *request, + void *context) +{ + ACPI_STATUS status = AE_OK; + + /* + * Must have a valid request structure and context. + */ + if (!request || !context) { + return(AE_BAD_PARAMETER); + } + + /* + * Handle Request: + * --------------- + */ + switch (request->command) { + + default: + status = AE_SUPPORT; + break; + } + + request->status = status; + + return(status); +} diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/button/bn_osl.c linux/drivers/acpi/ospm/button/bn_osl.c --- v2.4.5/linux/drivers/acpi/ospm/button/bn_osl.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/button/bn_osl.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,244 @@ +/****************************************************************************** + * + * Module Name: bn_osl.c + * $Revision: 10 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 "bn.h" + + +MODULE_AUTHOR("Andrew Grover"); +MODULE_DESCRIPTION("ACPI Component Architecture (CA) - Button Driver"); + + +#define BN_PROC_ROOT "button" +#define BN_PROC_POWER_BUTTON "power" +#define BN_PROC_SLEEP_BUTTON "sleep" +#define BN_PROC_LID_SWITCH "lid" + +extern struct proc_dir_entry *bm_proc_root; +static struct proc_dir_entry *bn_proc_root = NULL; + + +/**************************************************************************** + * + * FUNCTION: bn_osl_add_device + * + ****************************************************************************/ + +ACPI_STATUS +bn_osl_add_device( + BN_CONTEXT *button) +{ + ACPI_STATUS status = AE_OK; + + if (!button) { + return(AE_BAD_PARAMETER); + } + + switch (button->type) { + + case BN_TYPE_POWER_BUTTON: + case BN_TYPE_POWER_BUTTON_FIXED: + printk(KERN_INFO "Power Button: found\n"); + if (!proc_mkdir(BN_PROC_POWER_BUTTON, bn_proc_root)) { + status = AE_ERROR; + } + break; + + case BN_TYPE_SLEEP_BUTTON: + case BN_TYPE_SLEEP_BUTTON_FIXED: + printk(KERN_INFO "Sleep Button: found\n"); + if (!proc_mkdir(BN_PROC_SLEEP_BUTTON, bn_proc_root)) { + status = AE_ERROR; + } + break; + + case BN_TYPE_LID_SWITCH: + printk(KERN_INFO "Lid Switch: found\n"); + if (!proc_mkdir(BN_PROC_LID_SWITCH, bn_proc_root)) { + status = AE_ERROR; + } + break; + } + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: bn_osl_remove_device + * + ****************************************************************************/ + +ACPI_STATUS +bn_osl_remove_device ( + BN_CONTEXT *button) +{ + if (!button) { + return(AE_BAD_PARAMETER); + } + + switch (button->type) { + + case BN_TYPE_POWER_BUTTON: + case BN_TYPE_POWER_BUTTON_FIXED: + remove_proc_entry(BN_PROC_POWER_BUTTON, bn_proc_root); + break; + + case BN_TYPE_SLEEP_BUTTON: + case BN_TYPE_SLEEP_BUTTON_FIXED: + remove_proc_entry(BN_PROC_SLEEP_BUTTON, bn_proc_root); + break; + + case BN_TYPE_LID_SWITCH: + remove_proc_entry(BN_PROC_LID_SWITCH, bn_proc_root); + break; + } + + return(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: bn_osl_generate_event + * + ****************************************************************************/ + +ACPI_STATUS +bn_osl_generate_event ( + u32 event, + BN_CONTEXT *button) +{ + ACPI_STATUS status = AE_OK; + + if (!button) { + return(AE_BAD_PARAMETER); + } + + switch (event) { + + case BN_NOTIFY_STATUS_CHANGE: + + switch(button->type) { + + case BN_TYPE_POWER_BUTTON: + case BN_TYPE_POWER_BUTTON_FIXED: + status = bm_osl_generate_event(button->device_handle, + BN_PROC_ROOT, BN_PROC_POWER_BUTTON, event, 0); + break; + + case BN_TYPE_SLEEP_BUTTON: + case BN_TYPE_SLEEP_BUTTON_FIXED: + status = bm_osl_generate_event(button->device_handle, + BN_PROC_ROOT, BN_PROC_SLEEP_BUTTON, event, 0); + break; + + case BN_TYPE_LID_SWITCH: + status = bm_osl_generate_event(button->device_handle, + BN_PROC_ROOT, BN_PROC_LID_SWITCH, event, 0); + break; + + default: + status = AE_SUPPORT; + break; + } + + break; + + default: + return(AE_BAD_PARAMETER); + break; + } + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: bn_osl_init + * + * PARAMETERS: + * + * RETURN: 0: Success + * + * DESCRIPTION: Module initialization. + * + ****************************************************************************/ + +static int __init +bn_osl_init (void) +{ + ACPI_STATUS status = AE_OK; + + bn_proc_root = proc_mkdir(BN_PROC_ROOT, bm_proc_root); + if (!bn_proc_root) { + status = AE_ERROR; + } + else { + status = bn_initialize(); + if (ACPI_FAILURE(status)) { + remove_proc_entry(BN_PROC_ROOT, bm_proc_root); + } + } + + return (ACPI_SUCCESS(status)) ? 0 : -ENODEV; +} + + +/**************************************************************************** + * + * FUNCTION: bn_osl_cleanup + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: Module cleanup. + * + ****************************************************************************/ + +static void __exit +bn_osl_cleanup (void) +{ + bn_terminate(); + + if (bn_proc_root) { + remove_proc_entry(BN_PROC_ROOT, bm_proc_root); + } + + return; +} + + +module_init(bn_osl_init); +module_exit(bn_osl_cleanup); diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/ec/Makefile linux/drivers/acpi/ospm/ec/Makefile --- v2.4.5/linux/drivers/acpi/ospm/ec/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/ec/Makefile Wed Jun 20 17:47:40 2001 @@ -0,0 +1,6 @@ +O_TARGET := ospm_$(notdir $(CURDIR)).o +obj-m := $(O_TARGET) +EXTRA_CFLAGS += $(ACPI_CFLAGS) +obj-y := $(patsubst %.c,%.o,$(wildcard *.c)) + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/ec/ec_osl.c linux/drivers/acpi/ospm/ec/ec_osl.c --- v2.4.5/linux/drivers/acpi/ospm/ec/ec_osl.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/ec/ec_osl.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,115 @@ +/***************************************************************************** + * + * Module Name: ec_osl.c + * $Revision: 6 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 "ec.h" + + +MODULE_AUTHOR("Andrew Grover"); +MODULE_DESCRIPTION("ACPI Component Architecture (CA) - Embedded Controller Driver"); + +#ifdef ACPI_DEBUG + +static int dbg_layer = ACPI_COMPONENT_DEFAULT; +MODULE_PARM(dbg_layer, "i"); +MODULE_PARM_DESC(dbg_layer, "Controls debug output (see acpi_dbg_layer).\n"); + +static int dbg_level = DEBUG_DEFAULT; +MODULE_PARM(dbg_level, "i"); +MODULE_PARM_DESC(dbg_level, "Controls debug output (see acpi_dbg_level).\n"); + +#endif /*ACPI_DEBUG*/ + + +#ifdef ACPI_DEBUG +static u32 save_dbg_layer; +static u32 save_dbg_level; +#endif /*ACPI_DEBUG*/ + + +/**************************************************************************** + * + * FUNCTION: ec_osl_init + * + * PARAMETERS: + * + * RETURN: 0: Success + * + * DESCRIPTION: Module initialization. + * + ****************************************************************************/ + +static int __init +ec_osl_init (void) +{ + ACPI_STATUS status = AE_OK; + +#ifdef ACPI_DEBUG + save_dbg_layer = acpi_dbg_layer; + acpi_dbg_layer = dbg_layer; + + save_dbg_level = acpi_dbg_level; + acpi_dbg_level = dbg_level; +#endif /*ACPI_DEBUG*/ + + status = ec_initialize(); + + return (ACPI_SUCCESS(status)) ? 0 : -ENODEV; +} + +/**************************************************************************** + * + * FUNCTION: ec_osl_cleanup + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: Module cleanup. + * + ****************************************************************************/ + +static void __exit +ec_osl_cleanup(void) +{ + ec_terminate(); + +#ifdef ACPI_DEBUG + acpi_dbg_layer = save_dbg_layer; + acpi_dbg_level = save_dbg_level; +#endif /*ACPI_DEBUG*/ + + return; +} + +module_init(ec_osl_init); +module_exit(ec_osl_cleanup); diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/ec/ecgpe.c linux/drivers/acpi/ospm/ec/ecgpe.c --- v2.4.5/linux/drivers/acpi/ospm/ec/ecgpe.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/ec/ecgpe.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,230 @@ +/***************************************************************************** + * + * Module Name: ecgpe.c + * $Revision: 26 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 "ec.h" + +#define _COMPONENT ACPI_EC + MODULE_NAME ("ecgpe") + + +/**************************************************************************** + * + * FUNCTION: ec_query_handler + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +void +ec_query_handler ( + void *context) +{ + EC_CONTEXT *ec = (EC_CONTEXT*)context; + 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'}; + + if (!ec) { + return; + } + + /* + * Evaluate _Qxx: + * -------------- + * Evaluate corresponding _Qxx method. Note that a zero query value + * indicates a spurious EC_SCI (no such thing as _Q00). + */ + object_name[2] = hex[((ec->query_data >> 4) & 0x0F)]; + object_name[3] = hex[(ec->query_data & 0x0F)]; + + bm_evaluate_object(ec->acpi_handle, object_name, NULL, NULL); + + return; +} + + +/**************************************************************************** + * + * FUNCTION: ec_gpe_handler + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +void +ec_gpe_handler ( + void *context) +{ + ACPI_STATUS status = AE_OK; + EC_CONTEXT *ec = (EC_CONTEXT*)context; + EC_STATUS ec_status = 0; + + if (!ec) { + return; + } + + /* TBD: synchronize w/ transaction (ectransx). */ + + /* + * EC_SCI? + * ------- + * Check the EC_SCI bit to see if this is an EC_SCI event. If not (e.g. + * OBF/IBE) just return, as we already poll to detect these events. + */ + ec_status = acpi_os_in8(ec->status_port); + if (!(ec_status & EC_FLAG_SCI)) { + return; + } + + /* + * Run Query: + * ---------- + * Query the EC to find out which _Qxx method we need to evaluate. + * Note that successful completion of the query causes the EC_SCI + * bit to be cleared (and thus clearing the interrupt source). + */ + status = ec_io_write(ec, ec->command_port, EC_COMMAND_QUERY, + EC_EVENT_OUTPUT_BUFFER_FULL); + if (ACPI_FAILURE(status)) { + return; + } + + status = ec_io_read(ec, ec->data_port, &(ec->query_data), + EC_EVENT_NONE); + if (ACPI_FAILURE(status)) { + return; + } + + /* TBD: un-synchronize w/ transaction (ectransx). */ + + /* + * Spurious EC_SCI? + * ---------------- + */ + if (!ec->query_data) { + return; + } + + /* + * Defer _Qxx Execution: + * --------------------- + * Can't evaluate this method now 'cause we're at interrupt-level. + */ + status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, + ec_query_handler, ec); + if (ACPI_FAILURE(status)) { + return; + } + + return; +} + + +/**************************************************************************** + * + * FUNCTION: ec_install_gpe_handler + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +ec_install_gpe_handler ( + EC_CONTEXT *ec) +{ + ACPI_STATUS status = AE_OK; + + if (!ec) { + return(AE_BAD_PARAMETER); + } + + /* + * Evaluate _GPE: + * -------------- + * Evaluate the "_GPE" object (required) to find out which GPE bit + * is used by this EC to signal events (SCIs). + */ + status = bm_evaluate_simple_integer(ec->acpi_handle, + "_GPE", &(ec->gpe_bit)); + if (ACPI_FAILURE(status)) { + return(status); + } + + /* + * Install GPE Handler: + * -------------------- + * Install a handler for this EC's GPE bit. + */ + status = acpi_install_gpe_handler(ec->gpe_bit, ACPI_EVENT_EDGE_TRIGGERED, + &ec_gpe_handler, ec); + if (ACPI_FAILURE(status)) { + ec->gpe_bit = EC_GPE_UNKNOWN; + return(status); + } + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: ec_remove_gpe_handler + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +ec_remove_gpe_handler ( + EC_CONTEXT *ec) +{ + ACPI_STATUS status = AE_OK; + + if (!ec) { + return(AE_BAD_PARAMETER); + } + + status = acpi_remove_gpe_handler(ec->gpe_bit, &ec_gpe_handler); + + return(status); +} diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/ec/ecmain.c linux/drivers/acpi/ospm/ec/ecmain.c --- v2.4.5/linux/drivers/acpi/ospm/ec/ecmain.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/ec/ecmain.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,452 @@ +/***************************************************************************** + * + * Module Name: ecmain.c + * $Revision: 26 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 "ec.h" + +#define _COMPONENT ACPI_EC + MODULE_NAME ("ecmain") + + +/**************************************************************************** + * Internal Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: ec_print + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: Prints out information on a specific ec. + * + ****************************************************************************/ + +void +ec_print ( + EC_CONTEXT *ec) +{ + + if (!ec) { + return; + } + + acpi_os_printf("EC: found, GPE %d\n", ec->gpe_bit); + + + return; +} + + +/**************************************************************************** + * + * FUNCTION: ec_get_port_values + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: Evaluate _CRS to get the current resources (I/O port + * addresses) for this EC. + * + ****************************************************************************/ + +ACPI_STATUS +ec_get_port_values( + EC_CONTEXT *ec) +{ + ACPI_STATUS status = AE_OK; + ACPI_BUFFER buffer; + ACPI_RESOURCE *resource = NULL; + + if (!ec) { + return(AE_BAD_PARAMETER); + } + + buffer.length = 0; + buffer.pointer = NULL; + + status = acpi_get_current_resources(ec->acpi_handle, &buffer); + if (status != AE_BUFFER_OVERFLOW) { + return(status); + } + + buffer.pointer = acpi_os_callocate(buffer.length); + if (!buffer.pointer) { + return(AE_NO_MEMORY); + } + + status = acpi_get_current_resources(ec->acpi_handle, &buffer); + if (ACPI_FAILURE(status)) { + goto end; + } + + resource = (ACPI_RESOURCE *) buffer.pointer; + ec->data_port = resource->data.io.min_base_address; + + resource = NEXT_RESOURCE(resource); + + ec->status_port = ec->command_port = + resource->data.io.min_base_address; +end: + acpi_os_free(buffer.pointer); + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: ec_add_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +ec_add_device( + BM_HANDLE device_handle, + void **context) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE *device = NULL; + EC_CONTEXT *ec = NULL; + u8 gpe_handler = FALSE; + u8 space_handler = FALSE; + + if (!context || *context) { + return(AE_BAD_PARAMETER); + } + + /* + * Get information on this device. + */ + status = bm_get_device_info(device_handle, &device); + if (ACPI_FAILURE(status)) { + return(status); + } + + /* + * Allocate a new EC_CONTEXT structure. + */ + ec = acpi_os_callocate(sizeof(EC_CONTEXT)); + if (!ec) { + return(AE_NO_MEMORY); + } + + ec->device_handle = device->handle; + ec->acpi_handle = device->acpi_handle; + + /* + * Get the I/O port addresses for the command/status and data ports. + */ + status = ec_get_port_values(ec); + if (ACPI_FAILURE(status)) { + goto end; + } + + /* + * See if we need to obtain the global lock for EC transactions. + */ + status = bm_evaluate_simple_integer(ec->acpi_handle, "_GLK", + &ec->use_global_lock); + if (status == AE_NOT_FOUND) { + ec->use_global_lock = 0; + } + else if (ACPI_FAILURE(status)) { + goto end; + } + + /* + * Install a handler for servicing this EC's GPE. + */ + status = ec_install_gpe_handler(ec); + if (ACPI_FAILURE(status)) { + goto end; + } + else { + gpe_handler = TRUE; + } + + /* + * Install a handler for servicing this EC's address space. + */ + status = ec_install_space_handler(ec); + if (ACPI_FAILURE(status)) { + goto end; + } + else { + space_handler = TRUE; + } + + /* + * Create a semaphore to serialize EC transactions. + */ + status = acpi_os_create_semaphore(1,1, &(ec->mutex)); + if (ACPI_FAILURE(status)) { + goto end; + } + + /* + * Context now contains information specific to this EC. Note + * that we'll get this pointer back on every ec_request() and + * ec_notify(). + */ + *context = ec; + + ec_print(ec); + +end: + if (ACPI_FAILURE(status)) { + + if (gpe_handler) { + ec_remove_gpe_handler(ec); + } + + if (space_handler) { + ec_remove_space_handler(ec); + } + + if (ec->mutex) { + acpi_os_delete_semaphore(ec->mutex); + } + + acpi_os_free(ec); + } + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: ec_remove_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +ec_remove_device( + void **context) +{ + ACPI_STATUS status = AE_OK; + EC_CONTEXT *ec = NULL; + + if (!context || !*context) { + return(AE_BAD_PARAMETER); + } + + ec = (EC_CONTEXT*)*context; + + ec_remove_space_handler(ec); + + ec_remove_gpe_handler(ec); + + if (ec->mutex) { + acpi_os_delete_semaphore(ec->mutex); + } + + acpi_os_free(ec); + + *context = NULL; + + return(status); +} + + +/**************************************************************************** + * External Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: ec_initialize + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +ec_initialize (void) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE_ID criteria; + BM_DRIVER driver; + + MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID)); + MEMSET(&driver, 0, sizeof(BM_DRIVER)); + + /* + * Register driver for AC Adapter devices. + */ + MEMCPY(criteria.hid, EC_HID_EC, sizeof(EC_HID_EC)); + + driver.notify = &ec_notify; + driver.request = &ec_request; + + status = bm_register_driver(&criteria, &driver); + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: ec_terminate + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +ec_terminate(void) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE_ID criteria; + BM_DRIVER driver; + + MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID)); + MEMSET(&driver, 0, sizeof(BM_DRIVER)); + + /* + * Unregister driver for AC Adapter devices. + */ + MEMCPY(criteria.hid, EC_HID_EC, sizeof(EC_HID_EC)); + + driver.notify = &ec_notify; + driver.request = &ec_request; + + status = bm_unregister_driver(&criteria, &driver); + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: ec_notify + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +ec_notify ( + BM_NOTIFY notify, + BM_HANDLE device_handle, + void **context) +{ + ACPI_STATUS status = AE_OK; + + switch (notify) { + + case BM_NOTIFY_DEVICE_ADDED: + status = ec_add_device(device_handle, context); + break; + + case BM_NOTIFY_DEVICE_REMOVED: + status = ec_remove_device(context); + break; + + default: + status = AE_SUPPORT; + break; + } + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: ec_request + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +ec_request ( + BM_REQUEST *request, + void *context) +{ + ACPI_STATUS status = AE_OK; + EC_REQUEST *ec_request = NULL; + EC_CONTEXT *ec = NULL; + + /* + * Must have a valid request structure and context. + */ + if (!request || !context) + return(AE_BAD_PARAMETER); + + /* + * buffer must contain a valid EC_REQUEST structure. + */ + status = bm_cast_buffer(&(request->buffer), (void**)&ec_request, + sizeof(EC_REQUEST)); + if (ACPI_FAILURE(status)) + return(status); + + /* + * context contains information specific to this EC. + */ + ec = (EC_CONTEXT*)context; + + /* + * Perform the Transaction. + */ + status = ec_transaction(ec, ec_request); + + return(status); +} diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/ec/ecspace.c linux/drivers/acpi/ospm/ec/ecspace.c --- v2.4.5/linux/drivers/acpi/ospm/ec/ecspace.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/ec/ecspace.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,185 @@ +/***************************************************************************** + * + * Module Name: ecspace.c + * $Revision: 20 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 "ec.h" + +#define _COMPONENT ACPI_EC + MODULE_NAME ("ecspace") + + +/**************************************************************************** + * + * FUNCTION: ec_space_setup + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +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 ec_space_handler. + */ + *return_context = handler_context; + + return AE_OK; +} + + +/**************************************************************************** + * + * FUNCTION: ec_space_handler + * + * PARAMETERS: function - Read or Write operation + * address - Where in the space to read or write + * bit_width - Field width in bits (8, 16, or 32) + * value - Pointer to in or out value + * context - context pointer + * + * RETURN: + * + * DESCRIPTION: Handler for the Embedded Controller (EC) address space + * (Op Region) + * + ****************************************************************************/ + +ACPI_STATUS +ec_space_handler ( + u32 function, + ACPI_PHYSICAL_ADDRESS address, + u32 bit_width, + u32 *value, + void *handler_context, + void *region_context) +{ + ACPI_STATUS status = AE_OK; + EC_CONTEXT *ec = NULL; + EC_REQUEST ec_request; + + if (address > 0xFF || bit_width != 8 || !value || !handler_context) { + return(AE_BAD_PARAMETER); + } + + ec = (EC_CONTEXT*)handler_context; + + switch (function) { + + case ACPI_READ_ADR_SPACE: + ec_request.command = EC_COMMAND_READ; + ec_request.address = address; + ec_request.data = 0; + break; + + case ACPI_WRITE_ADR_SPACE: + ec_request.command = EC_COMMAND_WRITE; + ec_request.address = address; + ec_request.data = (u8)(*value); + break; + + default: + return(AE_BAD_PARAMETER); + break; + } + + /* + * Perform the Transaction. + */ + status = ec_transaction(ec, &ec_request); + if (ACPI_SUCCESS(status)) { + (*value) = (u32)ec_request.data; + } + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: ec_install_space_handler + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +ec_install_space_handler ( + EC_CONTEXT *ec) +{ + ACPI_STATUS status = AE_OK; + + if (!ec) { + return(AE_BAD_PARAMETER); + } + + status = acpi_install_address_space_handler (ec->acpi_handle, + ACPI_ADR_SPACE_EC, &ec_space_handler, &ec_space_setup, ec); + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: ec_remove_space_handler + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +ec_remove_space_handler ( + EC_CONTEXT *ec) +{ + ACPI_STATUS status = AE_OK; + + if (!ec) { + return(AE_BAD_PARAMETER); + } + + status = acpi_remove_address_space_handler(ec->acpi_handle, + ACPI_ADR_SPACE_EC, &ec_space_handler); + + return(status); +} diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/ec/ectransx.c linux/drivers/acpi/ospm/ec/ectransx.c --- v2.4.5/linux/drivers/acpi/ospm/ec/ectransx.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/ec/ectransx.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,326 @@ +/***************************************************************************** + * + * Module Name: ectransx.c + * $Revision: 21 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 "ec.h" + +#define _COMPONENT ACPI_EC + MODULE_NAME ("ectransx") + + +/**************************************************************************** + * + * FUNCTION: ec_io_wait + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +ec_io_wait ( + EC_CONTEXT *ec, + EC_EVENT wait_event) +{ + EC_STATUS ec_status = 0; + u32 i = 100; + + if (!ec || ((wait_event != EC_EVENT_OUTPUT_BUFFER_FULL) + && (wait_event != EC_EVENT_INPUT_BUFFER_EMPTY))) { + return(AE_BAD_PARAMETER); + } + + /* + * Wait for Event: + * --------------- + * Poll the EC status register waiting for the event to occur. + * Note that we'll wait a maximum of 1ms in 10us chunks. + */ + switch (wait_event) { + + case EC_EVENT_OUTPUT_BUFFER_FULL: + do { + ec_status = acpi_os_in8(ec->status_port); + if (ec_status & EC_FLAG_OUTPUT_BUFFER) { + return(AE_OK); + } + acpi_os_sleep_usec(10); + } while (--i>0); + break; + + case EC_EVENT_INPUT_BUFFER_EMPTY: + do { + ec_status = acpi_os_in8(ec->status_port); + if (!(ec_status & EC_FLAG_INPUT_BUFFER)) { + return(AE_OK); + } + acpi_os_sleep_usec(10); + } while (--i>0); + break; + } + + return(AE_TIME); +} + + +/**************************************************************************** + * + * FUNCTION: ec_io_read + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +ec_io_read ( + EC_CONTEXT *ec, + ACPI_IO_ADDRESS io_port, + u8 *data, + EC_EVENT wait_event) +{ + ACPI_STATUS status = AE_OK; + + if (!ec || !data) { + return(AE_BAD_PARAMETER); + } + + *data = acpi_os_in8(io_port); + + if (wait_event) { + status = ec_io_wait(ec, wait_event); + } + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: ec_io_write + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +ec_io_write ( + EC_CONTEXT *ec, + ACPI_IO_ADDRESS io_port, + u8 data, + EC_EVENT wait_event) +{ + ACPI_STATUS status = AE_OK; + + if (!ec) { + return(AE_BAD_PARAMETER); + } + + acpi_os_out8(io_port, data); + + if (wait_event) { + status = ec_io_wait(ec, wait_event); + } + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: ec_read + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +ec_read ( + EC_CONTEXT *ec, + u8 address, + u8 *data) +{ + ACPI_STATUS status = AE_OK; + + if (!ec || !data) { + return(AE_BAD_PARAMETER); + } + + if (ec->use_global_lock) { + status = acpi_acquire_global_lock(); + if (ACPI_FAILURE(status)) { + return(status); + } + } + + status = ec_io_write(ec, ec->command_port, EC_COMMAND_READ, + EC_EVENT_INPUT_BUFFER_EMPTY); + if (ACPI_FAILURE(status)) { + return(status); + } + + status = ec_io_write(ec, ec->data_port, address, + EC_EVENT_OUTPUT_BUFFER_FULL); + if (ACPI_FAILURE(status)) { + return(status); + } + + status = ec_io_read(ec, ec->data_port, data, EC_EVENT_NONE); + + if (ec->use_global_lock) { + acpi_release_global_lock(); + } + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: ec_write + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +ec_write ( + EC_CONTEXT *ec, + u8 address, + u8 data) +{ + ACPI_STATUS status = AE_OK; + + if (!ec) + return(AE_BAD_PARAMETER); + + if (ec->use_global_lock) { + status = acpi_acquire_global_lock(); + if (ACPI_FAILURE(status)) { + return(status); + } + } + + status = ec_io_write(ec, ec->command_port, EC_COMMAND_WRITE, + EC_EVENT_INPUT_BUFFER_EMPTY); + if (ACPI_FAILURE(status)) { + return(status); + } + + status = ec_io_write(ec, ec->data_port, address, + EC_EVENT_INPUT_BUFFER_EMPTY); + if (ACPI_FAILURE(status)) { + return(status); + } + + status = ec_io_write(ec, ec->data_port, data, + EC_EVENT_INPUT_BUFFER_EMPTY); + if (ACPI_FAILURE(status)) { + return(status); + } + + if (ec->use_global_lock) { + acpi_release_global_lock(); + } + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: ec_transaction + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +ec_transaction ( + EC_CONTEXT *ec, + EC_REQUEST *request) +{ + ACPI_STATUS status = AE_OK; + + if (!ec || !request) { + return(AE_BAD_PARAMETER); + } + + /* + * Obtain mutex to serialize all EC transactions. + */ + status = acpi_os_wait_semaphore(ec->mutex, 1, EC_DEFAULT_TIMEOUT); + if (ACPI_FAILURE(status)) { + return(status); + } + + /* + * Perform the transaction. + */ + switch (request->command) { + + case EC_COMMAND_READ: + status = ec_read(ec, request->address, &(request->data)); + break; + + case EC_COMMAND_WRITE: + status = ec_write(ec, request->address, request->data); + break; + + default: + status = AE_SUPPORT; + break; + } + + /* + * Signal the mutex to indicate transaction completion. + */ + acpi_os_signal_semaphore(ec->mutex, 1); + + return(status); +} diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/include/ac.h linux/drivers/acpi/ospm/include/ac.h --- v2.4.5/linux/drivers/acpi/ospm/include/ac.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/include/ac.h Wed Jun 20 17:47:40 2001 @@ -0,0 +1,102 @@ +/***************************************************************************** + * + * Module Name: ac.h + * $Revision: 6 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 + */ + + +#ifndef __AC_H__ +#define __AC_H__ + +#include +#include +#include + + +/***************************************************************************** + * Types & Other Defines + *****************************************************************************/ + +/* + * Notifications: + * -------------- + */ +#define AC_NOTIFY_STATUS_CHANGE ((BM_NOTIFY) 0x80) + +/* + * Hardware IDs: + * ------------- + */ +#define AC_HID_AC_ADAPTER "ACPI0003" + + +/* + * Device Context: + * --------------- + */ +typedef struct +{ + BM_HANDLE device_handle; + ACPI_HANDLE acpi_handle; + char uid[9]; + u32 is_online; +} AC_CONTEXT; + + +/***************************************************************************** + * Function Prototypes + *****************************************************************************/ + +ACPI_STATUS +ac_initialize (void); + +ACPI_STATUS +ac_terminate (void); + +ACPI_STATUS +ac_notify ( + u32 notify_type, + u32 device, + void **context); + +ACPI_STATUS +ac_request( + BM_REQUEST *request_info, + void *context); + +/* AC Adapter Driver OSL */ + +ACPI_STATUS +ac_osl_add_device ( + AC_CONTEXT *ac_adapter); + +ACPI_STATUS +ac_osl_remove_device ( + AC_CONTEXT *ac_adapter); + +ACPI_STATUS +ac_osl_generate_event ( + u32 event, + AC_CONTEXT *ac_adapter); + + +#endif /* __AC_H__ */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/include/bm.h linux/drivers/acpi/ospm/include/bm.h --- v2.4.5/linux/drivers/acpi/ospm/include/bm.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/include/bm.h Wed Jun 20 17:47:40 2001 @@ -0,0 +1,584 @@ +/***************************************************************************** + * + * Module name: bm.h + * $Revision: 39 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 + */ + +#ifndef __BM_H__ +#define __BM_H__ + +#include +#include + + +/***************************************************************************** + * Types & Defines + *****************************************************************************/ + +/* + * Output Flags (Debug): + * --------------------- + */ +#define BM_PRINT_ALL (0x00000000) +#define BM_PRINT_GROUP (0x00000001) +#define BM_PRINT_LINKAGE (0x00000002) +#define BM_PRINT_IDENTIFICATION (0x00000004) +#define BM_PRINT_POWER (0x00000008) +#define BM_PRINT_PRESENT (0x00000010) + + +/* + * BM_COMMAND: + * ----------- + */ +typedef u32 BM_COMMAND; + +#define BM_COMMAND_UNKNOWN ((BM_COMMAND) 0x00) + +#define BM_COMMAND_GET_POWER_STATE ((BM_COMMAND) 0x01) +#define BM_COMMAND_SET_POWER_STATE ((BM_COMMAND) 0x02) + +#define BM_COMMAND_DEVICE_SPECIFIC ((BM_COMMAND) 0x80) + +/* + * BM_NOTIFY: + * ---------- + * Standard ACPI notification values, from section 5.6.3 of the ACPI 2.0 + * specification. Note that the Bus Manager internally handles all + * standard ACPI notifications -- driver modules are never sent these + * values (see "Bus Manager Notifications", below). + */ +typedef u32 BM_NOTIFY; + +#define BM_NOTIFY_BUS_CHECK ((BM_NOTIFY) 0x00) +#define BM_NOTIFY_DEVICE_CHECK ((BM_NOTIFY) 0x01) +#define BM_NOTIFY_DEVICE_WAKE ((BM_NOTIFY) 0x02) +#define BM_NOTIFY_EJECT_REQUEST ((BM_NOTIFY) 0x03) +#define BM_NOTIFY_DEVICE_CHECK_LIGHT ((BM_NOTIFY) 0x04) +#define BM_NOTIFY_FREQUENCY_MISMATCH ((BM_NOTIFY) 0x05) +#define BM_NOTIFY_BUS_MODE_MISMATCH ((BM_NOTIFY) 0x06) +#define BM_NOTIFY_POWER_FAULT ((BM_NOTIFY) 0x07) + +/* + * These are a higher-level abstraction of ACPI notifications, intended + * for consumption by driver modules to facilitate PnP. + */ +#define BM_NOTIFY_UNKNOWN ((BM_NOTIFY) 0x00) +#define BM_NOTIFY_DEVICE_ADDED ((BM_NOTIFY) 0x01) +#define BM_NOTIFY_DEVICE_REMOVED ((BM_NOTIFY) 0x02) + + +/* + * BM_HANDLE: + * ---------- + */ +typedef u32 BM_HANDLE; + +#define BM_HANDLE_ROOT ((BM_HANDLE) 0x00000000) +#define BM_HANDLE_UNKNOWN ((BM_HANDLE) 0xFFFFFFFF) +#define BM_HANDLES_MAX 100 + + + +/* + * BM_HANDLE_LIST: + * --------------- + */ +typedef struct +{ + u32 count; + BM_HANDLE handles[BM_HANDLES_MAX]; +} BM_HANDLE_LIST; + + +/* + * BM_DEVICE_TYPE: + * --------------- + */ +typedef u32 BM_DEVICE_TYPE; + +#define BM_TYPE_UNKNOWN ((BM_DEVICE_TYPE) 0x00000000) + +#define BM_TYPE_SYSTEM ((BM_DEVICE_TYPE) 0x00000001) +#define BM_TYPE_SCOPE ((BM_DEVICE_TYPE) 0x00000002) +#define BM_TYPE_PROCESSOR ((BM_DEVICE_TYPE) 0x00000003) +#define BM_TYPE_THERMAL_ZONE ((BM_DEVICE_TYPE) 0x00000004) +#define BM_TYPE_POWER_RESOURCE ((BM_DEVICE_TYPE) 0x00000005) +#define BM_TYPE_DEVICE ((BM_DEVICE_TYPE) 0x00000006) +#define BM_TYPE_FIXED_BUTTON ((BM_DEVICE_TYPE) 0x00000007) + + +/* + * BM_DEVICE_UID: + * -------------- + */ +typedef char BM_DEVICE_UID[9]; + +#define BM_UID_UNKNOWN '0' + + +/* + * BM_DEVICE_HID: + * -------------- + */ +typedef char BM_DEVICE_HID[9]; + +#define BM_HID_UNKNOWN '\0' +#define BM_HID_POWER_BUTTON "PNP0C0C" +#define BM_HID_SLEEP_BUTTON "PNP0C0E" + +/* + * BM_DEVICE_ADR: + * -------------- + */ +typedef u32 BM_DEVICE_ADR; + +#define BM_ADDRESS_UNKNOWN 0 + + +/* + * BM_DEVICE_FLAGS: + * ---------------- + * The encoding of BM_DEVICE_FLAGS is illustrated below. + * Note that a set bit (1) indicates the property is TRUE + * (e.g. if bit 0 is set then the device has dynamic status). + * +--+------------+-+-+-+-+-+-+-+ + * |31| Bits 30:7 |6|5|4|3|2|1|0| + * +--+------------+-+-+-+-+-+-+-+ + * | | | | | | | | | + * | | | | | | | | +- Dynamic status? + * | | | | | | | +--- Identifiable? + * | | | | | | +----- Configurable? + * | | | | | +------- Power Control? + * | | | | +--------- Ejectable? + * | | | +----------- Docking Station? + * | | +------------- Fixed-Feature? + * | +-------------------- + * +---------------------------- Driver Control? + * + * Dynamic status: Device has a _STA object. + * Identifiable: Device has a _HID and/or _ADR and possibly other + * identification objects defined. + * Configurable: Device has a _CRS and possibly other configuration + * objects defined. + * Power Control: Device has a _PR0 and/or _PS0 and possibly other + * power management objects defined. + * Ejectable: Device has an _EJD and/or _EJx and possibly other + * dynamic insertion/removal objects defined. + * Docking Station: Device has a _DCK object defined. + * Fixed-Feature: Device does not exist in the namespace; was + * enumerated as a fixed-feature (e.g. power button). + * Driver Control: A driver has been installed for this device. + */ +typedef u32 BM_DEVICE_FLAGS; + +#define BM_FLAGS_UNKNOWN ((BM_DEVICE_FLAGS) 0x00000000) + +#define BM_FLAGS_DYNAMIC_STATUS ((BM_DEVICE_FLAGS) 0x00000001) +#define BM_FLAGS_IDENTIFIABLE ((BM_DEVICE_FLAGS) 0x00000002) +#define BM_FLAGS_CONFIGURABLE ((BM_DEVICE_FLAGS) 0x00000004) +#define BM_FLAGS_POWER_CONTROL ((BM_DEVICE_FLAGS) 0x00000008) +#define BM_FLAGS_EJECTABLE ((BM_DEVICE_FLAGS) 0x00000010) +#define BM_FLAGS_DOCKING_STATION ((BM_DEVICE_FLAGS) 0x00000020) +#define BM_FLAGS_FIXED_FEATURE ((BM_DEVICE_FLAGS) 0x00000040) +#define BM_FLAGS_DRIVER_CONTROL ((BM_DEVICE_FLAGS) 0x80000000) + + +/* + * Device PM Flags: + * ---------------- + * +-----------+-+-+-+-+-+-+-+ + * | Bits 31:7 |6|5|4|3|2|1|0| + * +-----------+-+-+-+-+-+-+-+ + * | | | | | | | | + * | | | | | | | +- D0 Support? + * | | | | | | +--- D1 Support? + * | | | | | +----- D2 Support? + * | | | | +------- D3 Support? + * | | | +--------- Power State Queriable? + * | | +----------- Inrush Current? + * | +------------- Wake Capable? + * +-------------------- + * + * D0-D3 Support: Device supports corresponding Dx state. + * Power State: Device has a _PSC (current power state) object defined. + * Inrush Current: Device has an _IRC (inrush current) object defined. + * Wake Capable: Device has a _PRW (wake-capable) object defined. + */ +#define BM_FLAGS_D0_SUPPORT ((BM_DEVICE_FLAGS) 0x00000001) +#define BM_FLAGS_D1_SUPPORT ((BM_DEVICE_FLAGS) 0x00000002) +#define BM_FLAGS_D2_SUPPORT ((BM_DEVICE_FLAGS) 0x00000004) +#define BM_FLAGS_D3_SUPPORT ((BM_DEVICE_FLAGS) 0x00000008) +#define BM_FLAGS_POWER_STATE ((BM_DEVICE_FLAGS) 0x00000010) +#define BM_FLAGS_INRUSH_CURRENT ((BM_DEVICE_FLAGS) 0x00000020) +#define BM_FLAGS_WAKE_CAPABLE ((BM_DEVICE_FLAGS) 0x00000040) + + +/* + * BM_DEVICE_STATUS: + * ----------------- + * The encoding of BM_DEVICE_STATUS is illustrated below. + * Note that a set bit (1) indicates the property is TRUE + * (e.g. if bit 0 is set then the device is present). + * +-----------+-+-+-+-+-+ + * | Bits 31:4 |4|3|2|1|0| + * +-----------+-+-+-+-+-+ + * | | | | | | + * | | | | | +- Present? + * | | | | +--- Enabled? + * | | | +----- Show in UI? + * | | +------- Functioning? + * | +--------- Battery Present? + * +---------------- + */ +typedef u32 BM_DEVICE_STATUS; + +#define BM_STATUS_UNKNOWN ((BM_DEVICE_STATUS) 0x00000000) +#define BM_STATUS_PRESENT ((BM_DEVICE_STATUS) 0x00000001) +#define BM_STATUS_ENABLED ((BM_DEVICE_STATUS) 0x00000002) +#define BM_STATUS_SHOW_UI ((BM_DEVICE_STATUS) 0x00000004) +#define BM_STATUS_FUNCTIONING ((BM_DEVICE_STATUS) 0x00000008) +#define BM_STATUS_BATTERY_PRESENT ((BM_DEVICE_STATUS) 0x00000010) +#define BM_STATUS_DEFAULT ((BM_DEVICE_STATUS) 0x0000000F) + + +/* + * BM_POWER_STATE: + * --------------- + */ +typedef u32 BM_POWER_STATE; + + +/* + * BM_DEVICE_ID: + * ------------- + */ +typedef struct +{ + BM_DEVICE_TYPE type; + BM_DEVICE_UID uid; + BM_DEVICE_HID hid; + BM_DEVICE_ADR adr; +} BM_DEVICE_ID; + + +/* + * BM_DEVICE_POWER: + * ---------------- + * Structure containing basic device power management information. + */ +typedef struct +{ + BM_DEVICE_FLAGS flags; + BM_POWER_STATE state; + BM_DEVICE_FLAGS dx_supported[ACPI_S_STATE_COUNT]; +} BM_DEVICE_POWER; + + +/* + * BM_DEVICE: + * ---------- + */ +typedef struct +{ + BM_HANDLE handle; + ACPI_HANDLE acpi_handle; + BM_DEVICE_FLAGS flags; + BM_DEVICE_STATUS status; + BM_DEVICE_ID id; + BM_DEVICE_POWER power; +} BM_DEVICE; + + +/* + * BM_SEARCH: + * ---------- + * Structure used for searching the ACPI Bus Manager's device hierarchy. + */ +typedef struct +{ + BM_DEVICE_ID criteria; + BM_HANDLE_LIST results; +} BM_SEARCH; + + +/* + * BM_REQUEST: + * ----------- + * Structure used for sending requests to/through the ACPI Bus Manager. + */ +typedef struct +{ + ACPI_STATUS status; + BM_COMMAND command; + BM_HANDLE handle; + ACPI_BUFFER buffer; +} BM_REQUEST; + + +/* + * Driver Registration: + * -------------------- + */ + +/* Driver Context */ +typedef void * BM_DRIVER_CONTEXT; + +/* Notification Callback Function */ +typedef +ACPI_STATUS (*BM_DRIVER_NOTIFY) ( + BM_NOTIFY notify_type, + BM_HANDLE device_handle, + BM_DRIVER_CONTEXT *context); + +/* Request Callback Function */ +typedef +ACPI_STATUS (*BM_DRIVER_REQUEST) ( + BM_REQUEST *request, + BM_DRIVER_CONTEXT context); + +/* Driver Registration */ +typedef struct +{ + BM_DRIVER_NOTIFY notify; + BM_DRIVER_REQUEST request; + BM_DRIVER_CONTEXT context; +} BM_DRIVER; + + +/* + * BM_NODE: + * -------- + * Structure used to maintain the device hierarchy. + */ +typedef struct _BM_NODE +{ + BM_DEVICE device; + BM_DRIVER driver; + struct _BM_NODE *parent; + struct _BM_NODE *next; + struct + { + struct _BM_NODE *head; + struct _BM_NODE *tail; + } scope; +} BM_NODE; + + +/* + * BM_NODE_LIST: + * ------------- + * Structure used to maintain an array of node pointers. + */ +typedef struct +{ + u32 count; + BM_NODE *nodes[BM_HANDLES_MAX]; +} BM_NODE_LIST; + + +/***************************************************************************** + * Macros + *****************************************************************************/ + +/* + * Device Presence: + * ---------------- + * Note that status (_STA) means something different for power resources + * (they're assumed to always be present). + */ +#define BM_DEVICE_PRESENT(d) ((d->id.type!=BM_TYPE_POWER_RESOURCE)?(d->status & BM_STATUS_PRESENT):TRUE) +#define BM_NODE_PRESENT(n) ((n->device.id.type!=BM_TYPE_POWER_RESOURCE)?(n->device.status & BM_STATUS_PRESENT):TRUE) + +/* + * Device Flags: + * ------------- + */ +#define BM_IS_DRIVER_CONTROL(d) (d->flags & BM_FLAGS_DRIVER_CONTROL) +#define BM_IS_POWER_CONTROL(d) (d->flags & BM_FLAGS_POWER_CONTROL) + + /* + * Device Power Flags: + * ------------------- + */ +#define BM_IS_POWER_STATE(d) (d->power.flags & BM_FLAGS_POWER_STATE) + +/***************************************************************************** + * Function Prototypes + *****************************************************************************/ + +/* bm.c */ + +ACPI_STATUS +bm_initialize (void); + +ACPI_STATUS +bm_terminate (void); + +ACPI_STATUS +bm_get_status ( + BM_DEVICE *device); + +ACPI_STATUS +bm_get_handle ( + ACPI_HANDLE acpi_handle, + BM_HANDLE *device_handle); + +ACPI_STATUS +bm_get_node ( + BM_HANDLE device_handle, + ACPI_HANDLE acpi_handle, + BM_NODE **node); + +/* bmsearch.c */ + +ACPI_STATUS +bm_search( + BM_HANDLE device_handle, + BM_DEVICE_ID *criteria, + BM_HANDLE_LIST *results); + +/* bmnotify.c */ + +void +bm_notify ( + ACPI_HANDLE acpi_handle, + u32 notify_value, + void *context); + +/* bm_request.c */ + +ACPI_STATUS +bm_request ( + BM_REQUEST *request_info); + +/* bmdriver.c */ + +ACPI_STATUS +bm_get_device_power_state ( + BM_HANDLE device_handle, + BM_POWER_STATE *state); + +ACPI_STATUS +bm_set_device_power_state ( + BM_HANDLE device_handle, + BM_POWER_STATE state); + +ACPI_STATUS +bm_get_device_status ( + BM_HANDLE device_handle, + BM_DEVICE_STATUS *device_status); + +ACPI_STATUS +bm_get_device_info ( + BM_HANDLE device_handle, + BM_DEVICE **device_info); + +ACPI_STATUS +bm_get_device_context ( + BM_HANDLE device_handle, + BM_DRIVER_CONTEXT *context); + +ACPI_STATUS +bm_register_driver ( + BM_DEVICE_ID *criteria, + BM_DRIVER *driver); + +ACPI_STATUS +bm_unregister_driver ( + BM_DEVICE_ID *criteria, + BM_DRIVER *driver); + +/* bmpm.c */ + +ACPI_STATUS +bm_get_pm_capabilities ( + BM_NODE *node); + +ACPI_STATUS +bm_get_power_state ( + BM_NODE *node); + +ACPI_STATUS +bm_set_power_state ( + BM_NODE *node, + BM_POWER_STATE target_state); + +/* bmpower.c */ + +ACPI_STATUS +bm_pr_initialize (void); + +ACPI_STATUS +bm_pr_terminate (void); + +/* bmutils.c */ + +ACPI_STATUS +bm_cast_buffer ( + ACPI_BUFFER *buffer, + void **pointer, + u32 length); + +ACPI_STATUS +bm_copy_to_buffer ( + ACPI_BUFFER *buffer, + void *data, + u32 length); + +ACPI_STATUS +bm_extract_package_data ( + ACPI_OBJECT *package, + ACPI_BUFFER *format, + ACPI_BUFFER *buffer); + +ACPI_STATUS +bm_evaluate_object ( + ACPI_HANDLE acpi_handle, + ACPI_STRING pathname, + ACPI_OBJECT_LIST *arguments, + ACPI_BUFFER *buffer); + +ACPI_STATUS +bm_evaluate_simple_integer ( + ACPI_HANDLE acpi_handle, + ACPI_STRING pathname, + u32 *data); + +ACPI_STATUS +bm_evaluate_reference_list ( + ACPI_HANDLE acpi_handle, + ACPI_STRING pathname, + BM_HANDLE_LIST *reference_list); + +/* ACPI Bus Driver OSL */ + +ACPI_STATUS +bm_osl_generate_event ( + BM_HANDLE device_handle, + char *device_type, + char *device_instance, + u32 event_type, + u32 event_data); + + +#endif /* __BM_H__ */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/include/bmpower.h linux/drivers/acpi/ospm/include/bmpower.h --- v2.4.5/linux/drivers/acpi/ospm/include/bmpower.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/include/bmpower.h Wed Jun 20 17:47:40 2001 @@ -0,0 +1,75 @@ +/***************************************************************************** + * + * Module name: bmpower.h + * $Revision: 1 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 + */ + +#ifndef __BMPOWER_H__ +#define __BMPOWER_H__ + +#include "bm.h" + + +/***************************************************************************** + * Types & Defines + *****************************************************************************/ + + +/* + * BM_POWER_RESOURCE: + * ------------------ + */ +typedef struct +{ + BM_HANDLE device_handle; + ACPI_HANDLE acpi_handle; + BM_POWER_STATE system_level; + u32 resource_order; + BM_POWER_STATE state; + u32 reference_count; +} BM_POWER_RESOURCE; + + +/***************************************************************************** + * Function Prototypes + *****************************************************************************/ + +/* bmpower.c */ + +ACPI_STATUS +bm_pr_initialize (void); + +ACPI_STATUS +bm_pr_terminate (void); + +ACPI_STATUS +bm_pr_list_get_state ( + BM_HANDLE_LIST *resource_list, + BM_POWER_STATE *power_state); + +ACPI_STATUS +bm_pr_list_transition ( + BM_HANDLE_LIST *current_list, + BM_HANDLE_LIST *target_list); + + +#endif /* __BMPOWER_H__ */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/include/bn.h linux/drivers/acpi/ospm/include/bn.h --- v2.4.5/linux/drivers/acpi/ospm/include/bn.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/include/bn.h Wed Jun 20 17:47:40 2001 @@ -0,0 +1,122 @@ +/****************************************************************************** + * + * Module Name: bn.h + * $Revision: 10 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 + */ + + +#ifndef __BN_H__ +#define __BN_H__ + +#include +#include +#include + + +/***************************************************************************** + * Types & Other Defines + *****************************************************************************/ + +/* + * Notifications: + * --------------------- + */ +#define BN_NOTIFY_STATUS_CHANGE ((BM_NOTIFY) 0x80) + + +/* + * Types: + * ------ + */ +#define BN_TYPE_POWER_BUTTON 0x01 +#define BN_TYPE_POWER_BUTTON_FIXED 0x02 +#define BN_TYPE_SLEEP_BUTTON 0x03 +#define BN_TYPE_SLEEP_BUTTON_FIXED 0x04 +#define BN_TYPE_LID_SWITCH 0x05 + + +/* + * Hardware IDs: + * ------------- + * TBD: Power and Sleep button HIDs also exist in . Should all + * HIDs (ACPI well-known devices) exist in one place (e.g. + * acpi_hid.h)? + */ +#define BN_HID_POWER_BUTTON "PNP0C0C" +#define BN_HID_SLEEP_BUTTON "PNP0C0E" +#define BN_HID_LID_SWITCH "PNP0C0D" + + +/* + * Device Context: + * --------------- + */ +typedef struct +{ + BM_HANDLE device_handle; + ACPI_HANDLE acpi_handle; + u32 type; +} BN_CONTEXT; + + +/****************************************************************************** + * Function Prototypes + *****************************************************************************/ + +ACPI_STATUS +bn_initialize (void); + +ACPI_STATUS +bn_terminate (void); + +ACPI_STATUS +bn_notify_fixed ( + void *context); + +ACPI_STATUS +bn_notify ( + u32 notify_type, + u32 device, + void **context); + +ACPI_STATUS +bn_request( + BM_REQUEST *request_info, + void *context); + +/* Button OSL */ + +ACPI_STATUS +bn_osl_add_device ( + BN_CONTEXT *button); + +ACPI_STATUS +bn_osl_remove_device ( + BN_CONTEXT *button); + +ACPI_STATUS +bn_osl_generate_event ( + u32 event, + BN_CONTEXT *button); + + +#endif /* __BN_H__ */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/include/bt.h linux/drivers/acpi/ospm/include/bt.h --- v2.4.5/linux/drivers/acpi/ospm/include/bt.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/include/bt.h Wed Jun 20 17:47:40 2001 @@ -0,0 +1,161 @@ +/****************************************************************************** + * + * Module Name: bt.h + * $Revision: 13 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 + */ + + +#ifndef __BT_H__ +#define __BT_H__ + +#include +#include +#include + + +/***************************************************************************** + * Types & Other Defines + *****************************************************************************/ + +/*! [Begin] no source code translation */ + +#define BT_UNKNOWN 0xFFFFFFFF +#define BT_POWER_UNITS_DEFAULT "?" +#define BT_POWER_UNITS_WATTS "mW" +#define BT_POWER_UNITS_AMPS "mA" + +/*! [End] no source code translation */ + +/* + * Battery Notifications: + * ---------------------- + */ +#define BT_NOTIFY_STATUS_CHANGE ((BM_NOTIFY) 0x80) +#define BT_NOTIFY_INFORMATION_CHANGE ((BM_NOTIFY) 0x81) + + +/* + * Hardware IDs: + * ------------- + */ +#define BT_HID_CM_BATTERY "PNP0C0A" + + +/* + * BT_CM_BATTERY_INFO: + * ------------------- + */ +typedef struct +{ + u32 power_unit; + u32 design_capacity; + u32 last_full_capacity; + u32 battery_technology; + u32 design_voltage; + u32 design_capacity_warning; + u32 design_capacity_low; + u32 battery_capacity_granularity_1; + u32 battery_capacity_granularity_2; + ACPI_STRING model_number; + ACPI_STRING serial_number; + ACPI_STRING battery_type; + ACPI_STRING oem_info; +} BT_BATTERY_INFO; + + +/* + * BT_CM_BATTERY_STATUS: + * --------------------- + */ +typedef struct +{ + u32 state; + u32 present_rate; + u32 remaining_capacity; + u32 present_voltage; +} BT_BATTERY_STATUS; + + +/* + * BT_CONTEXT: + * ----------- + */ +typedef struct +{ + BM_HANDLE device_handle; + ACPI_HANDLE acpi_handle; + char uid[9]; + ACPI_STRING power_units; + BOOLEAN is_present; +} BT_CONTEXT; + + +/***************************************************************************** + * Function Prototypes + *****************************************************************************/ + +/* bt.c */ + +ACPI_STATUS +bt_initialize (void); + +ACPI_STATUS +bt_terminate (void); + +ACPI_STATUS +bt_notify ( + u32 notify_type, + u32 device, + void **context); + +ACPI_STATUS +bt_request( + BM_REQUEST *request_info, + void *context); + +ACPI_STATUS +bt_get_status ( + BT_CONTEXT *battery, + BT_BATTERY_STATUS **battery_status); + +ACPI_STATUS +bt_get_info ( + BT_CONTEXT *battery, + BT_BATTERY_INFO **battery_info); + +/* Battery OSL */ + +ACPI_STATUS +bt_osl_add_device ( + BT_CONTEXT *battery); + +ACPI_STATUS +bt_osl_remove_device ( + BT_CONTEXT *battery); + +ACPI_STATUS +bt_osl_generate_event ( + u32 event, + BT_CONTEXT *battery); + + +#endif /* __BT_H__ */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/include/ec.h linux/drivers/acpi/ospm/include/ec.h --- v2.4.5/linux/drivers/acpi/ospm/include/ec.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/include/ec.h Wed Jun 20 17:47:40 2001 @@ -0,0 +1,202 @@ +/***************************************************************************** + * + * Module Name: ec.h + * $Revision: 15 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 + */ + + +#ifndef __EC_H__ +#define __EC_H__ + +#include +#include +#include +#include +#include + + +/***************************************************************************** + * Types & Other Defines + *****************************************************************************/ + +#define EC_DEFAULT_TIMEOUT 1000 /* 1 second */ +#define EC_GPE_UNKNOWN 0xFFFFFFFF +#define EC_PORT_UNKNOWN 0x00000000 +#define EC_BURST_ENABLE_ACKNOWLEDGE 0x90 + + +/* + * Commands: + * --------- + */ +typedef u8 EC_COMMAND; + +#define EC_COMMAND_UNKNOWN ((EC_COMMAND) 0x00) +#define EC_COMMAND_READ ((EC_COMMAND) 0x80) +#define EC_COMMAND_WRITE ((EC_COMMAND) 0x81) +#define EC_COMMAND_QUERY ((EC_COMMAND) 0x84) + + +/* + * EC_STATUS: + * ---------- + * The encoding of the EC status register is illustrated below. + * Note that a set bit (1) indicates the property is TRUE + * (e.g. if bit 0 is set then the output buffer is full). + * +-+-+-+-+-+-+-+-+ + * |7|6|5|4|3|2|1|0| + * +-+-+-+-+-+-+-+-+ + * | | | | | | | | + * | | | | | | | +- Output Buffer Full (OBF)? + * | | | | | | +--- Input Buffer Full (IBF)? + * | | | | | +----- + * | | | | +------- data Register is command Byte? + * | | | +--------- Burst Mode Enabled? + * | | +----------- SCI event? + * | +------------- SMI event? + * +--------------- + * + */ +typedef u8 EC_STATUS; + +#define EC_FLAG_OUTPUT_BUFFER ((EC_STATUS) 0x01) +#define EC_FLAG_INPUT_BUFFER ((EC_STATUS) 0x02) +#define EC_FLAG_BURST_MODE ((EC_STATUS) 0x10) +#define EC_FLAG_SCI ((EC_STATUS) 0x20) + + +/* + * EC_EVENT: + * --------- + */ +typedef u8 EC_EVENT; + +#define EC_EVENT_UNKNOWN ((EC_EVENT) 0x00) +#define EC_EVENT_NONE ((EC_EVENT) 0x00) +#define EC_EVENT_OUTPUT_BUFFER_FULL ((EC_EVENT) 0x01) +#define EC_EVENT_INPUT_BUFFER_EMPTY ((EC_EVENT) 0x02) +#define EC_EVENT_SCI ((EC_EVENT) 0x03) + + +/* + * Hardware IDs: + * ------------- + */ +#define EC_HID_EC "PNP0C09" + + +/* + * EC_REQUEST: + * ----------- + */ +typedef struct +{ + EC_COMMAND command; + u8 address; + u8 data; +} EC_REQUEST; + + +/* + * Device Context: + * --------------- + */ +typedef struct +{ + BM_HANDLE device_handle; + ACPI_HANDLE acpi_handle; + u32 gpe_bit; + u32 status_port; + u32 command_port; + u32 data_port; + u32 use_global_lock; + u8 query_data; + ACPI_HANDLE mutex; +} EC_CONTEXT; + + +/***************************************************************************** + * Function Prototypes + *****************************************************************************/ + +/* ec.c */ + +ACPI_STATUS +ec_initialize(void); + +ACPI_STATUS +ec_terminate(void); + +ACPI_STATUS +ec_notify ( + u32 notify_type, + u32 device, + void **context); + +ACPI_STATUS +ec_request( + BM_REQUEST *request_info, + void *context); + +/* ectransx.c */ + +ACPI_STATUS +ec_transaction ( + EC_CONTEXT *ec, + EC_REQUEST *ec_request); + +ACPI_STATUS +ec_io_read ( + EC_CONTEXT *ec, + u32 io_port, + u8 *data, + EC_EVENT wait_event); + +ACPI_STATUS +ec_io_write ( + EC_CONTEXT *ec, + u32 io_port, + u8 data, + EC_EVENT wait_event); + +/* ecgpe.c */ + +ACPI_STATUS +ec_install_gpe_handler ( + EC_CONTEXT *ec); + +ACPI_STATUS +ec_remove_gpe_handler ( + EC_CONTEXT *ec); + +/* ecspace.c */ + +ACPI_STATUS +ec_install_space_handler ( + EC_CONTEXT *ec); + +ACPI_STATUS +ec_remove_space_handler ( + EC_CONTEXT *ec); + + +#endif /* __EC_H__ */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/include/pr.h linux/drivers/acpi/ospm/include/pr.h --- v2.4.5/linux/drivers/acpi/ospm/include/pr.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/include/pr.h Wed Jun 20 17:47:40 2001 @@ -0,0 +1,265 @@ +/****************************************************************************** + * + * Module Name: processor.h + * $Revision: 9 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 + */ + +#ifndef __PR_H__ +#define __PR_H__ + +#include + + +/***************************************************************************** + * Types & Other Defines + *****************************************************************************/ + + +#define PR_MAX_POWER_STATES 4 +#define PR_MAX_THROTTLE_STATES 8 +#define PR_MAX_PERF_STATES 32 +#define PR_MAX_C2_LATENCY 100 +#define PR_MAX_C3_LATENCY 1000 + + +/* + * Commands: + * --------- + */ +#define PR_COMMAND_GET_POWER_INFO ((BM_COMMAND) 0x80) +#define PR_COMMAND_SET_POWER_INFO ((BM_COMMAND) 0x81) +#define PR_COMMAND_GET_PERF_INFO ((BM_COMMAND) 0x82) +#define PR_COMMAND_GET_PERF_STATE ((BM_COMMAND) 0x83) +#define PR_COMMAND_SET_PERF_LIMIT ((BM_COMMAND) 0x84) + + +/* + * Notifications: + * -------------- + */ +#define PR_NOTIFY_PERF_STATES ((BM_NOTIFY) 0x80) +#define PR_NOTIFY_POWER_STATES ((BM_NOTIFY) 0x81) + + +/* + * Performance Control: + * -------------------- + */ +#define PR_PERF_DEC 0x00 +#define PR_PERF_INC 0x01 +#define PR_PERF_MAX 0xFF + + +/* + * Power States: + * ------------- + */ +#define PR_C0 0x00 +#define PR_C1 0x01 +#define PR_C2 0x02 +#define PR_C3 0x03 + +#define PR_C1_FLAG 0x01; +#define PR_C2_FLAG 0x02; +#define PR_C3_FLAG 0x04; + + +/* + * PR_CX_POLICY_VALUES: + * -------------------- + */ +typedef struct +{ + u32 time_threshold; + u32 count_threshold; + u32 bm_threshold; + u32 target_state; + u32 count; +} PR_CX_POLICY_VALUES; + + +/* + * PR_CX: + * ------ + */ +typedef struct +{ + u32 latency; + u32 utilization; + u8 is_valid; + PR_CX_POLICY_VALUES promotion; + PR_CX_POLICY_VALUES demotion; +} PR_CX; + + +/* + * PR_POWER: + * --------- + */ +typedef struct +{ + ACPI_PHYSICAL_ADDRESS p_lvl2; + ACPI_PHYSICAL_ADDRESS p_lvl3; + u32 bm_activity; + u32 active_state; + u32 default_state; + u32 busy_metric; + u32 state_count; + PR_CX state[PR_MAX_POWER_STATES]; +} PR_POWER; + + +/* + * PR_PERFORMANCE_STATE: + * --------------------- + */ +typedef struct +{ + u32 performance; + u32 power; +} PR_PERFORMANCE_STATE; + + +/* + * PR_PERFORMANCE: + * --------------- + */ +typedef struct +{ + u32 active_state; + u32 thermal_limit; + u32 power_limit; + u32 state_count; + PR_PERFORMANCE_STATE state[PR_MAX_PERF_STATES]; +} PR_PERFORMANCE; + + +/* + * PR_PBLOCK: + * ---------- + */ +typedef struct +{ + u32 length; + ACPI_PHYSICAL_ADDRESS address; +} PR_PBLOCK; + + +/* + * PR_CONTEXT: + * ----------- + */ +typedef struct +{ + BM_HANDLE device_handle; + ACPI_HANDLE acpi_handle; + u32 uid; + PR_PBLOCK pblk; + PR_POWER power; + PR_PERFORMANCE performance; +} PR_CONTEXT; + + +/****************************************************************************** + * Function Prototypes + *****************************************************************************/ + +/* processor.c */ + +ACPI_STATUS +pr_initialize(void); + +ACPI_STATUS +pr_terminate(void); + +ACPI_STATUS +pr_notify ( + BM_NOTIFY notify_type, + BM_HANDLE device_handle, + void **context); + +ACPI_STATUS +pr_request( + BM_REQUEST *request, + void *context); + +/* prpower.c */ + +void +pr_power_idle (void); + +ACPI_STATUS +pr_power_add_device ( + PR_CONTEXT *processor); + +ACPI_STATUS +pr_power_remove_device ( + PR_CONTEXT *processor); + +ACPI_STATUS +pr_power_initialize (void); + +ACPI_STATUS +pr_power_terminate (void); + +/* prperf.c */ + +ACPI_STATUS +pr_perf_get_state ( + PR_CONTEXT *processor, + u32 *state); + +ACPI_STATUS +pr_perf_set_state ( + PR_CONTEXT *processor, + u32 state); + +ACPI_STATUS +pr_perf_set_limit ( + PR_CONTEXT *processor, + u32 limit); + +ACPI_STATUS +pr_perf_add_device ( + PR_CONTEXT *processor); + +ACPI_STATUS +pr_perf_remove_device ( + PR_CONTEXT *processor); + +/* Processor Driver OSL */ + +ACPI_STATUS +pr_osl_add_device ( + PR_CONTEXT *processor); + +ACPI_STATUS +pr_osl_remove_device ( + PR_CONTEXT *processor); + +ACPI_STATUS +pr_osl_generate_event ( + u32 event, + PR_CONTEXT *processor); + + +#endif /* __PR_H__ */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/include/sm.h linux/drivers/acpi/ospm/include/sm.h --- v2.4.5/linux/drivers/acpi/ospm/include/sm.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/include/sm.h Wed Jun 20 17:47:40 2001 @@ -0,0 +1,91 @@ +/***************************************************************************** + * + * Module Name: sm.h + * $Revision: 3 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 + */ + + +#ifndef __SM_H__ +#define __SM_H__ + +#include +#include +#include + + +/***************************************************************************** + * Types & Other Defines + *****************************************************************************/ + +#define SM_MAX_SYSTEM_STATES 6 /* S0-S5 */ + + + /* + * Device Context: + * --------------- + */ +typedef struct +{ + BM_HANDLE device_handle; + ACPI_HANDLE acpi_handle; + u8 states[SM_MAX_SYSTEM_STATES]; +} SM_CONTEXT; + + +/***************************************************************************** + * Function Prototypes + *****************************************************************************/ + +ACPI_STATUS +sm_initialize (void); + +ACPI_STATUS +sm_terminate (void); + +ACPI_STATUS +sm_notify ( + u32 notify_type, + u32 device, + void **context); + +ACPI_STATUS +sm_request( + BM_REQUEST *request_info, + void *context); + +/* System Driver OSL */ + +ACPI_STATUS +sm_osl_add_device ( + SM_CONTEXT *system); + +ACPI_STATUS +sm_osl_remove_device ( + SM_CONTEXT *system); + +ACPI_STATUS +sm_osl_generate_event ( + u32 event, + SM_CONTEXT *system); + + +#endif /* __SM_H__ */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/include/tz.h linux/drivers/acpi/ospm/include/tz.h --- v2.4.5/linux/drivers/acpi/ospm/include/tz.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/include/tz.h Wed Jun 20 17:47:40 2001 @@ -0,0 +1,279 @@ +/***************************************************************************** + * + * Module Name: tz.h + * $Revision: 21 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 + */ + +#ifndef __TZ_H__ +#define __TZ_H__ + +/* TBD: Linux-specific */ +#include +#include + +#include +#include + + +/***************************************************************************** + * Types & Other Defines + *****************************************************************************/ + +#define TZ_MAX_THRESHOLDS 12 /* _AC0 through _AC9 + _CRT + _PSV */ +#define TZ_MAX_ACTIVE_THRESHOLDS 10 /* _AC0 through _AC9 */ +#define TZ_MAX_COOLING_DEVICES 10 /* TBD: Make size dynamic */ + + +/* + * Notifications: + * -------------- + */ +#define TZ_NOTIFY_TEMPERATURE_CHANGE ((BM_NOTIFY) 0x80) +#define TZ_NOTIFY_THRESHOLD_CHANGE ((BM_NOTIFY) 0x81) +#define TZ_NOTIFY_DEVICE_LISTS_CHANGE ((BM_NOTIFY) 0x82) + + +/* + * TZ_THRESHOLD_TYPE: + * ------------------ + */ +typedef u32 TZ_THRESHOLD_TYPE; + +#define TZ_THRESHOLD_UNKNOWN ((TZ_THRESHOLD_TYPE) 0x00) +#define TZ_THRESHOLD_CRITICAL ((TZ_THRESHOLD_TYPE) 0x01) + +#define TZ_THRESHOLD_PASSIVE ((TZ_THRESHOLD_TYPE) 0x02) +#define TZ_THRESHOLD_ACTIVE ((TZ_THRESHOLD_TYPE) 0x03) + + +/* + * TZ_COOLING_STATE: + * ----------------- + */ +typedef u32 TZ_COOLING_STATE; + +#define TZ_COOLING_UNKNOWN ((TZ_COOLING_STATE) 0x00) +#define TZ_COOLING_ENABLED ((TZ_COOLING_STATE) 0x01) +#define TZ_COOLING_DISABLED ((TZ_COOLING_STATE) 0x02) + + +/* + * TZ_COOLING_MODE: + * ---------------- + */ +typedef u32 TZ_COOLING_MODE; + +#define TZ_COOLING_MODE_ACTIVE ((TZ_COOLING_MODE) 0x00) +#define TZ_COOLING_MODE_PASSIVE ((TZ_COOLING_MODE) 0x01) + + +/* + * Thermal State: + * -------------- + * The encoding of TZ_STATE is illustrated below. + * Note that a set bit (1) indicates the property is TRUE + * (e.g. if bit 0 is set then the device has dynamic status). + * No bits set indicates an OK cooling state. + * +--+--+--+-----------+----------+ + * |31|30|29| Bits 27:4 | Bits 3:0 | + * +--+--+--+-----------+----------+ + * | | | | | + * | | | | +------ Active Index + * | | | +----------------- + * | | +------------------------- Active + * | +---------------------------- Passive + * +------------------------------- Critical + * + * Active Index: Value representing the level of active cooling + * presently applied (e.g. 0=_AL0, 9=_AL9). Only + * valid when 'Active' is set. + * Active: If set, indicates that the system temperature + * has crossed at least one active threshold (_ALx). + * Passive: If set, indicates that the system temperature + * has crossed the passive threshold (_PSL). + * Passive: If set, indicates that the system temperature + * has crossed the critical threshold (_CRT). + */ +typedef u32 TZ_STATE; + +#define TZ_STATE_OK ((TZ_STATE) 0x00000000) +#define TZ_STATE_ACTIVE ((TZ_STATE) 0x20000000) +#define TZ_STATE_PASSIVE ((TZ_STATE) 0x40000000) +#define TZ_STATE_CRITICAL ((TZ_STATE) 0x80000000) + + +/* + * TZ_THRESHOLD: + * ------------- + * Information on an individual threshold. + */ +typedef struct { + TZ_THRESHOLD_TYPE type; + u32 index; + u32 temperature; + TZ_COOLING_STATE cooling_state; + BM_HANDLE_LIST cooling_devices; +} TZ_THRESHOLD; + + +/* + * TZ_THRESHOLD_LIST: + * ------------------ + * Container for the thresholds of a given thermal zone. + * Note that thresholds are always ordered by increasing + * temperature value to simplify use by thermal policy. + */ +typedef struct { + u32 count; + TZ_THRESHOLD thresholds[TZ_MAX_THRESHOLDS]; +} TZ_THRESHOLD_LIST; + + +/* + * TZ_CRITICAL_POLICY: + * ------------------- + */ +typedef struct { + TZ_THRESHOLD *threshold; +} TZ_CRITICAL_POLICY; + + +/* + * TZ_PASSIVE_POLICY: + * ------------------ + */ +typedef struct { + u32 tc1; + u32 tc2; + u32 tsp; + TZ_THRESHOLD *threshold; +} TZ_PASSIVE_POLICY; + + +/* + * TZ_ACTIVE_POLICY: + * ----------------- + */ +typedef struct { + u32 threshold_count; + TZ_THRESHOLD *threshold[TZ_MAX_ACTIVE_THRESHOLDS]; +} TZ_ACTIVE_POLICY; + + +/* + * TZ_POLICY: + * --------- + */ +typedef struct { + u32 temperature; + TZ_STATE state; + TZ_COOLING_MODE cooling_mode; + u32 polling_freq; + TZ_THRESHOLD_LIST threshold_list; + TZ_CRITICAL_POLICY critical; + TZ_PASSIVE_POLICY passive; + TZ_ACTIVE_POLICY active; + /* TBD: Linux-specific */ + struct timer_list timer; +} TZ_POLICY; + + +/* + * TZ_CONTEXT: + * ----------- + */ +typedef struct { + BM_HANDLE device_handle; + ACPI_HANDLE acpi_handle; + char uid[9]; + TZ_POLICY policy; +} TZ_CONTEXT; + + +/***************************************************************************** + * Function Prototypes + *****************************************************************************/ + +/* thermal_zone.c */ + +ACPI_STATUS +tz_initialize (void); + +ACPI_STATUS +tz_terminate (void); + +ACPI_STATUS +tz_notify ( + BM_NOTIFY notify_type, + BM_HANDLE device_handle, + BM_DRIVER_CONTEXT *context); + +ACPI_STATUS +tz_request ( + BM_REQUEST *request, + BM_DRIVER_CONTEXT context); + +ACPI_STATUS +tz_get_temperature ( + TZ_CONTEXT *thermal_zone, + u32 *temperature); + +ACPI_STATUS +tz_get_thresholds ( + TZ_CONTEXT *thermal_zone, + TZ_THRESHOLD_LIST *threshold_list); + +void +tz_print ( + TZ_CONTEXT *thermal_zone); + +/* tzpolicy.c */ + +ACPI_STATUS +tz_policy_add_device ( + TZ_CONTEXT *thermal_zone); + +ACPI_STATUS +tz_policy_remove_device ( + TZ_CONTEXT *thermal_zone); + +void +tz_policy_check ( + void *context); + +/* Thermal Zone Driver OSL */ + +ACPI_STATUS +tz_osl_add_device ( + TZ_CONTEXT *thermal_zone); + +ACPI_STATUS +tz_osl_remove_device ( + TZ_CONTEXT *thermal_zone); + +ACPI_STATUS +tz_osl_generate_event ( + u32 event, + TZ_CONTEXT *thermal_zone); + + +#endif /* __TZ_H__ */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/processor/Makefile linux/drivers/acpi/ospm/processor/Makefile --- v2.4.5/linux/drivers/acpi/ospm/processor/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/processor/Makefile Wed Jun 20 17:47:40 2001 @@ -0,0 +1,6 @@ +O_TARGET := ospm_$(notdir $(CURDIR)).o +obj-m := $(O_TARGET) +EXTRA_CFLAGS += $(ACPI_CFLAGS) +obj-y := $(patsubst %.c,%.o,$(wildcard *.c)) + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/processor/pr.c linux/drivers/acpi/ospm/processor/pr.c --- v2.4.5/linux/drivers/acpi/ospm/processor/pr.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/processor/pr.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,454 @@ +/***************************************************************************** + * + * Module Name: pr.c + * $Revision: 30 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 "pr.h" + + +#define _COMPONENT ACPI_PROCESSOR + MODULE_NAME ("pr") + + +/**************************************************************************** + * Globals + ****************************************************************************/ + +extern FADT_DESCRIPTOR_REV2 acpi_fadt; + + +/**************************************************************************** + * Internal Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: pr_print + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: Prints out information on a specific thermal zone. + * + ****************************************************************************/ + +void +pr_print ( + PR_CONTEXT *processor) +{ + + return; +} + + +/**************************************************************************** + * + * FUNCTION: pr_add_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +pr_add_device( + BM_HANDLE device_handle, + void **context) +{ + ACPI_STATUS status = AE_OK; + PR_CONTEXT *processor = NULL; + BM_DEVICE *device = NULL; + ACPI_BUFFER buffer; + ACPI_OBJECT acpi_object; + static u32 processor_count = 0; + + + if (!context || *context) { + return(AE_BAD_PARAMETER); + } + + status = bm_get_device_info(device_handle, &device); + if (ACPI_FAILURE(status)) { + return(status); + } + + processor = acpi_os_callocate(sizeof(PR_CONTEXT)); + if (!processor) { + return AE_NO_MEMORY; + } + + processor->device_handle = device->handle; + processor->acpi_handle = device->acpi_handle; + + /* + * Processor Block: + * ---------------- + */ + MEMSET(&acpi_object, 0, sizeof(ACPI_OBJECT)); + + buffer.length = sizeof(ACPI_OBJECT); + buffer.pointer = &acpi_object; + + status = acpi_evaluate_object(processor->acpi_handle, NULL, NULL, &buffer); + if (ACPI_FAILURE(status)) { + goto end; + } + + /* + * Processor ID: + * ------------- + * TBD: We need to synchronize the processor ID values in ACPI + * with those of the APIC. For example, an IBM T20 has a + * proc_id value of '1', where the Linux value for the + * first CPU on this system is '0'. Since x86 CPUs are + * mapped 1:1 we can simply use a zero-based counter. Note + * that this assumes that processor objects are enumerated + * in the proper order. + */ + /* processor->uid = acpi_object.processor.proc_id; */ + processor->uid = processor_count++; + + processor->pblk.length = acpi_object.processor.pblk_length; + processor->pblk.address = acpi_object.processor.pblk_address; + + status = pr_power_add_device(processor); + if (ACPI_FAILURE(status)) { + goto end; + } + + status = pr_perf_add_device(processor); + if (ACPI_FAILURE(status)) { + goto end; + } + + status = pr_osl_add_device(processor); + if (ACPI_FAILURE(status)) { + goto end; + } + + *context = processor; + + pr_print(processor); + +end: + if (ACPI_FAILURE(status)) { + acpi_os_free(processor); + } + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: pr_remove_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +pr_remove_device ( + void **context) +{ + ACPI_STATUS status = AE_OK; + PR_CONTEXT *processor= NULL; + + if (!context || !*context) { + return(AE_BAD_PARAMETER); + } + + processor = (PR_CONTEXT*)(*context); + + pr_osl_remove_device(processor); + + pr_perf_remove_device(processor); + + pr_power_remove_device(processor); + + acpi_os_free(processor); + + return(status); +} + + +/**************************************************************************** + * External Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: pr_initialize + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +pr_initialize (void) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE_ID criteria; + BM_DRIVER driver; + + MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID)); + MEMSET(&driver, 0, sizeof(BM_DRIVER)); + + /* + * Initialize power (Cx state) policy. + */ + status = pr_power_initialize(); + if (ACPI_FAILURE(status)) { + return(status); + } + + /* + * Register driver for processor devices. + */ + criteria.type = BM_TYPE_PROCESSOR; + + driver.notify = &pr_notify; + driver.request = &pr_request; + + status = bm_register_driver(&criteria, &driver); + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: pr_terminate + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +pr_terminate (void) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE_ID criteria; + BM_DRIVER driver; + + MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID)); + MEMSET(&driver, 0, sizeof(BM_DRIVER)); + + /* + * Terminate power (Cx state) policy. + */ + status = pr_power_terminate(); + if (ACPI_FAILURE(status)) { + return(status); + } + + /* + * Unegister driver for processor devices. + */ + criteria.type = BM_TYPE_PROCESSOR; + + driver.notify = &pr_notify; + driver.request = &pr_request; + + status = bm_unregister_driver(&criteria, &driver); + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: pr_notify + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +pr_notify ( + BM_NOTIFY notify_type, + BM_HANDLE device_handle, + void **context) +{ + ACPI_STATUS status = AE_OK; + PR_CONTEXT *processor = NULL; + + processor = (PR_CONTEXT*)*context; + + switch (notify_type) { + + case BM_NOTIFY_DEVICE_ADDED: + status = pr_add_device(device_handle, context); + break; + + case BM_NOTIFY_DEVICE_REMOVED: + status = pr_remove_device(context); + break; + + case PR_NOTIFY_PERF_STATES: + /* TBD: Streamline (this is simple but overkill). */ + status = pr_perf_remove_device(processor); + if (ACPI_SUCCESS(status)) { + status = pr_perf_add_device(processor); + } + if (ACPI_SUCCESS(status)) { + status = pr_osl_generate_event(notify_type, + (processor)); + } + break; + + case PR_NOTIFY_POWER_STATES: + /* TBD: Streamline (this is simple but overkill). */ + status = pr_power_remove_device(processor); + if (ACPI_SUCCESS(status)) { + status = pr_power_add_device(processor); + } + if (ACPI_SUCCESS(status)) { + status = pr_osl_generate_event(notify_type, + (processor)); + } + break; + + default: + status = AE_SUPPORT; + break; + } + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: pr_request + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +pr_request ( + BM_REQUEST *request, + void *context) +{ + ACPI_STATUS status = AE_OK; + PR_CONTEXT *processor = NULL; + + /* + * Must have a valid request structure and context. + */ + if (!request || !context) { + return(AE_BAD_PARAMETER); + } + + processor = (PR_CONTEXT*)context; + + /* + * Handle request: + * --------------- + */ + switch (request->command) { + + case PR_COMMAND_GET_POWER_INFO: + status = bm_copy_to_buffer(&(request->buffer), + &(processor->power), sizeof(PR_POWER)); + break; + + case PR_COMMAND_SET_POWER_INFO: + { + PR_POWER *power_info = NULL; + u32 i = 0; + + status = bm_cast_buffer(&(request->buffer), + (void**)&power_info, sizeof(PR_POWER)); + if (ACPI_SUCCESS(status)) { + for (i=0; ipower.state_count; i++) { + MEMCPY(&(processor->power.state[i].promotion), + &(power_info->state[i].promotion), + sizeof(PR_CX_POLICY_VALUES)); + MEMCPY(&(processor->power.state[i].demotion), + &(power_info->state[i].demotion), + sizeof(PR_CX_POLICY_VALUES)); + } + } + } + break; + + case PR_COMMAND_GET_PERF_INFO: + status = bm_copy_to_buffer(&(request->buffer), + &(processor->performance), sizeof(PR_PERFORMANCE)); + break; + + case PR_COMMAND_GET_PERF_STATE: + status = bm_copy_to_buffer(&(request->buffer), + &(processor->performance.active_state), sizeof(u32)); + break; + + case PR_COMMAND_SET_PERF_LIMIT: + { + u32 *limit = NULL; + + status = bm_cast_buffer(&(request->buffer), + (void**)&limit, sizeof(u32)); + if (ACPI_SUCCESS(status)) { + status = pr_perf_set_limit(processor, *limit); + } + } + break; + + default: + status = AE_SUPPORT; + break; + } + + request->status = status; + + return(status); +} diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/processor/pr_osl.c linux/drivers/acpi/ospm/processor/pr_osl.c --- v2.4.5/linux/drivers/acpi/ospm/processor/pr_osl.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/processor/pr_osl.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,305 @@ +/****************************************************************************** + * + * Module Name: pr_osl.c + * $Revision: 14 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 "pr.h" + + +MODULE_AUTHOR("Andrew Grover"); +MODULE_DESCRIPTION("ACPI Component Architecture (CA) - IA32 Processor Driver"); + + +#define PR_PROC_ROOT "processor" +#define PR_PROC_STATUS "status" +#define PR_PROC_INFO "info" + +extern struct proc_dir_entry *bm_proc_root; +static struct proc_dir_entry *pr_proc_root = NULL; + + +/**************************************************************************** + * + * FUNCTION: pr_osl_proc_read_status + * + ****************************************************************************/ + +static int +pr_osl_proc_read_status ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *context) +{ + PR_CONTEXT *processor = NULL; + char *p = page; + int len = 0; + + if (!context || (off != 0)) { + goto end; + } + + processor = (PR_CONTEXT*)context; + + p += sprintf(p, "Bus Mastering Activity: %08x\n", + processor->power.bm_activity); + + p += sprintf(p, "C-State Utilization: C1[%d] C2[%d] C3[%d]\n", + processor->power.state[PR_C1].utilization, + processor->power.state[PR_C2].utilization, + processor->power.state[PR_C3].utilization); + +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(len); +} + + +/**************************************************************************** + * + * FUNCTION: pr_osl_proc_read_info + * + ****************************************************************************/ + +static int +pr_osl_proc_read_info ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *context) +{ + PR_CONTEXT *processor = NULL; + char *p = page; + int len = 0; + + if (!context || (off != 0)) { + goto end; + } + + processor = (PR_CONTEXT*)context; + + 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(len); +} + + +/**************************************************************************** + * + * FUNCTION: pr_osl_add_device + * + ****************************************************************************/ + +ACPI_STATUS +pr_osl_add_device( + PR_CONTEXT *processor) +{ + u32 i = 0; + struct proc_dir_entry *proc_entry = NULL; + char processor_uid[16]; + + if (!processor) { + return(AE_BAD_PARAMETER); + } + + printk("Processor[%x]:", processor->uid); + for (i=0; ipower.state_count; i++) { + if (processor->power.state[i].is_valid) { + printk(" C%d", i); + } + } + + if (processor->performance.state_count > 1) { + printk(", throttling states: %d", processor->performance.state_count); + } + + printk("\n"); + + sprintf(processor_uid, "%d", processor->uid); + + proc_entry = proc_mkdir(processor_uid, pr_proc_root); + if (!proc_entry) { + return(AE_ERROR); + } + + create_proc_read_entry(PR_PROC_STATUS, S_IFREG | S_IRUGO, + proc_entry, pr_osl_proc_read_status, (void*)processor); + + create_proc_read_entry(PR_PROC_INFO, S_IFREG | S_IRUGO, + proc_entry, pr_osl_proc_read_info, (void*)processor); + + return(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: pr_osl_remove_device + * + ****************************************************************************/ + +ACPI_STATUS +pr_osl_remove_device ( + PR_CONTEXT *processor) +{ + char proc_entry[64]; + + if (!processor) { + return(AE_BAD_PARAMETER); + } + + sprintf(proc_entry, "%d/%s", processor->uid, PR_PROC_INFO); + remove_proc_entry(proc_entry, pr_proc_root); + + sprintf(proc_entry, "%d/%s", processor->uid, PR_PROC_STATUS); + remove_proc_entry(proc_entry, pr_proc_root); + + sprintf(proc_entry, "%d", processor->uid); + remove_proc_entry(proc_entry, pr_proc_root); + + return(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: pr_osl_generate_event + * + ****************************************************************************/ + +ACPI_STATUS +pr_osl_generate_event ( + u32 event, + PR_CONTEXT *processor) +{ + ACPI_STATUS status = AE_OK; + char processor_uid[16]; + + if (!processor) { + return(AE_BAD_PARAMETER); + } + + switch (event) { + + case PR_NOTIFY_PERF_STATES: + case PR_NOTIFY_POWER_STATES: + sprintf(processor_uid, "%d", processor->uid); + status = bm_osl_generate_event(processor->device_handle, + PR_PROC_ROOT, processor_uid, event, 0); + break; + + default: + return(AE_BAD_PARAMETER); + break; + } + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: pr_osl_init + * + * PARAMETERS: + * + * RETURN: 0: Success + * + * DESCRIPTION: Module initialization. + * + ****************************************************************************/ + +static int __init +pr_osl_init (void) +{ + ACPI_STATUS status = AE_OK; + + pr_proc_root = proc_mkdir(PR_PROC_ROOT, bm_proc_root); + if (!pr_proc_root) { + status = AE_ERROR; + } + else { + status = pr_initialize(); + if (ACPI_FAILURE(status)) { + remove_proc_entry(PR_PROC_ROOT, bm_proc_root); + } + + } + + return (ACPI_SUCCESS(status)) ? 0 : -ENODEV; +} + + +/**************************************************************************** + * + * FUNCTION: pr_osl_cleanup + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: Module cleanup. + * + ****************************************************************************/ + +static void __exit +pr_osl_cleanup (void) +{ + pr_terminate(); + + if (pr_proc_root) { + remove_proc_entry(PR_PROC_ROOT, bm_proc_root); + } + + return; +} + + +module_init(pr_osl_init); +module_exit(pr_osl_cleanup); diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/processor/prperf.c linux/drivers/acpi/ospm/processor/prperf.c --- v2.4.5/linux/drivers/acpi/ospm/processor/prperf.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/processor/prperf.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,423 @@ +/***************************************************************************** + * + * Module Name: prperf.c + * $Revision: 16 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 ACPI 2.0 processor performance states (not just throttling). + * 2. Fully implement thermal -vs- power management limit control. + */ + + +#include +#include +#include "pr.h" + +#define _COMPONENT ACPI_PROCESSOR + MODULE_NAME ("prperf") + + +/**************************************************************************** + * Globals + ****************************************************************************/ + +extern FADT_DESCRIPTOR_REV2 acpi_fadt; +const u32 POWER_OF_2[] = {1,2,4,8,16,32,64,128,256,512}; + + +/**************************************************************************** + * + * FUNCTION: pr_perf_get_frequency + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +pr_perf_get_frequency ( + PR_CONTEXT *processor, + u32 *frequency) { + ACPI_STATUS status = AE_OK; + + if (!processor || !frequency) { + return(AE_BAD_PARAMETER); + } + + /* TBD: Generic method to calculate processor frequency. */ + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: pr_perf_get_state + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +/* TBD: Include support for _real_ performance states (not just throttling). */ + +ACPI_STATUS +pr_perf_get_state ( + PR_CONTEXT *processor, + u32 *state) +{ + u32 pblk_value = 0; + u32 duty_mask = 0; + u32 duty_cycle = 0; + + if (!processor || !state) { + return(AE_BAD_PARAMETER); + } + + if (processor->performance.state_count == 1) { + *state = 0; + return(AE_OK); + } + + pblk_value = acpi_os_in32(processor->pblk.address); + + /* + * Throttling Enabled? + * ------------------- + * If so, calculate the current throttling state, otherwise return + * '100% performance' (state 0). + */ + if (pblk_value & 0x00000010) { + + duty_mask = processor->performance.state_count - 1; + duty_mask <<= acpi_fadt.duty_offset; + + duty_cycle = pblk_value & duty_mask; + duty_cycle >>= acpi_fadt.duty_offset; + + if (duty_cycle == 0) { + *state = 0; + } + else { + *state = processor->performance.state_count - + duty_cycle; + } + } + else { + *state = 0; + } + + return(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: pr_perf_set_state + * + * PARAMETERS: + * + * RETURN: AE_OK + * AE_BAD_PARAMETER + * AE_BAD_DATA Invalid target throttling state. + * + * DESCRIPTION: + * + ****************************************************************************/ + +/* TBD: Includes support for _real_ performance states (not just throttling). */ + +ACPI_STATUS +pr_perf_set_state ( + PR_CONTEXT *processor, + u32 state) +{ + u32 pblk_value = 0; + u32 duty_mask = 0; + u32 duty_cycle = 0; + u32 i = 0; + + if (!processor) { + return(AE_BAD_PARAMETER); + } + + if (state > (processor->performance.state_count - 1)) { + return(AE_BAD_DATA); + } + + if (processor->performance.state_count == 1) { + return(AE_OK); + } + + /* + * Calculate Duty Cycle/Mask: + * -------------------------- + * Note that we don't support duty_cycle values that span bit 4. + */ + if (state) { + duty_cycle = processor->performance.state_count - state; + duty_cycle <<= acpi_fadt.duty_offset; + } + else { + duty_cycle = 0; + } + + duty_mask = ~((u32)(processor->performance.state_count - 1)); + for (i=0; ipblk.address); + if (pblk_value & 0x00000010) { + pblk_value &= 0xFFFFFFEF; + acpi_os_out32(processor->pblk.address, pblk_value); + } + + /* + * Set Duty Cycle: + * --------------- + * Mask off the old duty_cycle value, mask in the new. + */ + pblk_value &= duty_mask; + pblk_value |= duty_cycle; + acpi_os_out32(processor->pblk.address, pblk_value); + + /* + * Enable Throttling: + * ------------------ + * But only for non-zero (non-100% performance) states. + */ + if (state) { + pblk_value |= 0x00000010; + acpi_os_out32(processor->pblk.address, pblk_value); + } + + return(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: pr_perf_set_limit + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +pr_perf_set_limit ( + PR_CONTEXT *processor, + u32 limit) +{ + ACPI_STATUS status = AE_OK; + PR_PERFORMANCE *performance = NULL; + + if (!processor) { + return(AE_BAD_PARAMETER); + } + + performance = &(processor->performance); + + /* + * Set Limit: + * ---------- + * TBD: Properly manage thermal and power limits (only set + * performance state iff...). + */ + switch (limit) { + + case PR_PERF_DEC: + if (performance->active_state < + (performance->state_count-1)) { + status = pr_perf_set_state(processor, + (performance->active_state-1)); + } + break; + + case PR_PERF_INC: + if (performance->active_state > 0) { + status = pr_perf_set_state(processor, + (performance->active_state+1)); + } + break; + + case PR_PERF_MAX: + if (performance->active_state != 0) { + status = pr_perf_set_state(processor, 0); + } + break; + + default: + return(AE_BAD_DATA); + break; + } + + if (ACPI_SUCCESS(status)) { + performance->thermal_limit = limit; + } + + return(status); +} + + +/**************************************************************************** + * External Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: pr_perf_add_device + * + * PARAMETERS: processor Our processor-specific context. + * + * RETURN: AE_OK + * AE_BAD_PARAMETER + * + * DESCRIPTION: Calculates the number of throttling states and the state + * performance/power values. + * + ****************************************************************************/ + +/* TBD: Support duty_cycle values that span bit 4. */ + +ACPI_STATUS +pr_perf_add_device ( + PR_CONTEXT *processor) +{ + ACPI_STATUS status = AE_OK; + u32 i = 0; + u32 performance_step = 0; + u32 percentage = 0; + + if (!processor) { + return(AE_BAD_PARAMETER); + } + + /* + * Valid PBLK? + * ----------- + * For SMP it is common to have the first (boot) processor have a + * valid PBLK while all others do not -- which implies that + * throttling has system-wide effects (duty_cycle programmed into + * the chipset effects all processors). + */ + if ((processor->pblk.length < 6) || !processor->pblk.address) { + processor->performance.state_count = 1; + } + + /* + * Valid Duty Offset/Width? + * ------------------------ + * We currently only support duty_cycle values that fall within + * bits 0-3, as things get complicated when this value spans bit 4 + * (the throttling enable/disable bit). + */ + else if ((acpi_fadt.duty_offset + acpi_fadt.duty_width) > 4) { + processor->performance.state_count = 1; + } + + /* + * Compute State Count: + * -------------------- + * The number of throttling states is computed as 2^duty_width, + * but limited by PR_MAX_THROTTLE_STATES. Note that a duty_width + * of zero results is one throttling state (100%). + */ + else { + processor->performance.state_count = + POWER_OF_2[acpi_fadt.duty_width]; + } + + if (processor->performance.state_count > PR_MAX_THROTTLE_STATES) { + processor->performance.state_count = PR_MAX_THROTTLE_STATES; + } + + /* + * Compute State Values: + * --------------------- + * Note that clock throttling displays a linear power/performance + * relationship (at 50% performance the CPU will consume 50% power). + */ + performance_step = (1000 / processor->performance.state_count); + + for (i=0; iperformance.state_count; i++) { + percentage = (1000 - (performance_step * i))/10; + processor->performance.state[i].performance = percentage; + processor->performance.state[i].power = percentage; + } + + /* + * Get Current State: + * ------------------ + */ + status = pr_perf_get_state(processor, + &(processor->performance.active_state)); + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: pr_perf_remove_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +pr_perf_remove_device ( + PR_CONTEXT *processor) +{ + ACPI_STATUS status = AE_OK; + + if (!processor) { + return(AE_BAD_PARAMETER); + } + + MEMSET(&(processor->performance), 0, sizeof(PR_PERFORMANCE)); + + return(status); +} + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/processor/prpower.c linux/drivers/acpi/ospm/processor/prpower.c --- v2.4.5/linux/drivers/acpi/ospm/processor/prpower.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/processor/prpower.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,640 @@ +/***************************************************************************** + * + * Module Name: prpower.c + * $Revision: 25 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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: Linux specific */ +#include +#include + +#include +#include +#include "pr.h" + +#define _COMPONENT ACPI_PROCESSOR + MODULE_NAME ("prpower") + + +/**************************************************************************** + * Globals + ****************************************************************************/ + +extern FADT_DESCRIPTOR_REV2 acpi_fadt; +static u32 last_idle_jiffies = 0; +static PR_CONTEXT *processor_list[NR_CPUS]; +static void (*pr_pm_idle_save)(void) = NULL; + + +/**************************************************************************** + * External Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: pr_power_activate_state + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +void +pr_power_activate_state ( + PR_CONTEXT *processor, + u32 next_state) +{ + if (!processor) { + return; + } + + processor->power.state[processor->power.active_state].promotion.count = 0; + processor->power.state[processor->power.active_state].demotion.count = 0; + + /* + * Cleanup from old state. + */ + switch (processor->power.active_state) { + + case PR_C3: + /* Disable bus master reload */ + acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK, + BM_RLD, 0); + break; + } + + /* + * Prepare to use new state. + */ + switch (next_state) { + + case PR_C3: + /* Enable bus master reload */ + acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK, + BM_RLD, 1); + break; + } + + processor->power.active_state = next_state; + + return; +} + + +/**************************************************************************** + * + * FUNCTION: pr_power_idle + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +void +pr_power_idle (void) +{ + PR_CX *c_state = NULL; + u32 next_state = 0; + u32 start_ticks, end_ticks, time_elapsed; + PR_CONTEXT *processor = NULL; + + processor = processor_list[smp_processor_id()]; + + if (!processor || processor->power.active_state == PR_C0) { + return; + } + + next_state = processor->power.active_state; + + /* + * Log BM Activity: + * ---------------- + * Read BM_STS and record its value for later use by C3 policy. + * Note that we save the BM_STS values for the last 32 call to + * this function (cycles). Also note that we must clear BM_STS + * if set (sticky). + */ + processor->power.bm_activity <<= 1; + if (acpi_hw_register_bit_access(ACPI_READ, ACPI_MTX_DO_NOT_LOCK, BM_STS)) { + processor->power.bm_activity |= 1; + acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK, + BM_STS, 1); + } + + /* + * Check OS Idleness: + * ------------------ + * If the OS has been busy (hasn't called the idle handler in a while) + * then automatically demote to the default power state (e.g. C1). + * + * TBD: Optimize by having scheduler determine business instead + * of having us try to calculate it. + */ + if (processor->power.active_state != processor->power.default_state) { + if ((jiffies - last_idle_jiffies) >= processor->power.busy_metric) { + next_state = processor->power.default_state; + if (next_state != processor->power.active_state) { + pr_power_activate_state(processor, next_state); + } + } + } + + c_state = &(processor->power.state[processor->power.active_state]); + + c_state->utilization++; + + /* + * Sleep: + * ------ + * Invoke the current Cx state to put the processor to sleep. + */ + switch (processor->power.active_state) { + + case PR_C1: + /* See how long we're asleep for */ + acpi_get_timer(&start_ticks); + /* Invoke C1 */ + enable(); halt(); + /* Compute time elapsed */ + acpi_get_timer(&end_ticks); + break; + + case PR_C2: + /* Interrupts must be disabled during C2 transitions */ + disable(); + /* See how long we're asleep for */ + acpi_get_timer(&start_ticks); + /* Invoke C2 */ + acpi_os_in8(processor->power.p_lvl2); + /* Dummy op - must do something useless after P_LVL2 read */ + acpi_hw_register_bit_access(ACPI_READ, ACPI_MTX_DO_NOT_LOCK, + BM_STS); + /* Compute time elapsed */ + acpi_get_timer(&end_ticks); + /* Re-enable interrupts */ + enable(); + break; + + case PR_C3: + /* Interrupts must be disabled during C3 transitions */ + disable(); + /* Disable bus master arbitration */ + acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK, + ARB_DIS, 1); + /* See how long we're asleep for */ + acpi_get_timer(&start_ticks); + /* Invoke C2 */ + acpi_os_in8(processor->power.p_lvl3); + /* Dummy op - must do something useless after P_LVL3 read */ + acpi_hw_register_bit_access(ACPI_READ, ACPI_MTX_DO_NOT_LOCK, + BM_STS); + /* Compute time elapsed */ + acpi_get_timer(&end_ticks); + /* Enable bus master arbitration */ + acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK, + ARB_DIS, 0); + /* Re-enable interrupts */ + enable(); + break; + + default: + break; + } + + /* + * Compute the amount of time asleep (in the Cx state). + * + * TBD: Convert time_threshold 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); + + /* + * Promotion? + * ---------- + * Track the number of successful sleeps (time asleep is greater + * than time_threshold) and promote when count_threashold is + * reached. + */ + if ((c_state->promotion.target_state) && + (time_elapsed >= c_state->promotion.time_threshold)) { + + c_state->promotion.count++; + c_state->demotion.count = 0; + + if (c_state->promotion.count >= + c_state->promotion.count_threshold) { + + /* + * Bus Mastering Activity, if active and used + * by this state's promotion policy, prevents + * promotions from occuring. + */ + if (!(processor->power.bm_activity & + c_state->promotion.bm_threshold)) { + next_state = c_state->promotion.target_state; + } + } + } + + /* + * Demotion? + * --------- + * Track the number of shorts (time asleep is less than + * time_threshold) and demote when count_threshold is reached. + */ + if (c_state->demotion.target_state) { + + if (time_elapsed < c_state->demotion.time_threshold) { + + c_state->demotion.count++; + c_state->promotion.count = 0; + + if (c_state->demotion.count >= + c_state->demotion.count_threshold) { + next_state = c_state->demotion.target_state; + } + } + + /* + * Bus Mastering Activity, if active and used by this + * state's promotion policy, causes an immediate demotion + * to occur. + */ + if (processor->power.bm_activity & + c_state->demotion.bm_threshold) { + next_state = c_state->demotion.target_state; + } + } + + /* + * 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 != processor->power.active_state) { + pr_power_activate_state(processor, next_state); + processor->power.active_state = processor->power.active_state; + } + + /* + * Track OS Idleness: + * ------------------ + * Record a jiffies timestamp to compute time elapsed between calls + * to the idle handler. + */ + last_idle_jiffies = jiffies; + + return; +} + + +/***************************************************************************** + * + * FUNCTION: pr_power_set_default_policy + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: 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 Cx state policy is completely customizable, with + * the goal of having heuristics to alter policy dynamically. + * + ****************************************************************************/ + +ACPI_STATUS +pr_power_set_default_policy ( + PR_CONTEXT *processor) +{ + if (!processor) { + return(AE_BAD_PARAMETER); + } + + /* + * Busy Metric: + * ------------ + * Used to determine when the OS has been busy and thus when + * policy should return to using the default Cx state (e.g. C1). + * On Linux we use the number of jiffies (scheduler quantums) + * that transpire between calls to the idle handler. + * + * TBD: Linux-specific. + */ + processor->power.busy_metric = 2; + + /* + * C1: + * --- + * C1 serves as our default state. It must be valid. + */ + if (processor->power.state[PR_C1].is_valid) { + processor->power.active_state = + processor->power.default_state = PR_C1; + } + else { + processor->power.active_state = + processor->power.default_state = PR_C0; + return(AE_OK); + } + + /* + * C2: + * --- + * Set default C1 promotion and C2 demotion policies. + */ + if (processor->power.state[PR_C2].is_valid) { + /* + * Promote from C1 to C2 anytime we're asleep in C1 for + * longer than two times the C2 latency (to amortize cost + * of transition). Demote from C2 to C1 anytime we're + * asleep in C2 for less than this time. + */ + processor->power.state[PR_C1].promotion.count_threshold = 1; + processor->power.state[PR_C1].promotion.time_threshold = + 2 * processor->power.state[PR_C2].latency; + processor->power.state[PR_C1].promotion.target_state = PR_C2; + + processor->power.state[PR_C2].demotion.count_threshold = 1; + processor->power.state[PR_C2].demotion.time_threshold = + 2 * processor->power.state[PR_C2].latency; + processor->power.state[PR_C2].demotion.target_state = PR_C1; + } + + /* + * C3: + * --- + * Set default C2 promotion and C3 demotion policies. + */ + if ((processor->power.state[PR_C2].is_valid) && + (processor->power.state[PR_C3].is_valid)) { + /* + * Promote from C2 to C3 after 4 cycles of no bus + * mastering activity (while maintaining sleep time + * criteria). Demote immediately on a short or + * whenever bus mastering activity occurs. + */ + processor->power.state[PR_C2].promotion.count_threshold = 1; + processor->power.state[PR_C2].promotion.time_threshold = + 2 * processor->power.state[PR_C3].latency; + processor->power.state[PR_C2].promotion.bm_threshold = + 0x0000000F; + processor->power.state[PR_C2].promotion.target_state = + PR_C3; + + processor->power.state[PR_C3].demotion.count_threshold = 1; + processor->power.state[PR_C3].demotion.time_threshold = + 2 * processor->power.state[PR_C3].latency; + processor->power.state[PR_C3].demotion.bm_threshold = + 0x0000000F; + processor->power.state[PR_C3].demotion.target_state = + PR_C2; + } + + return(AE_OK); +} + +/***************************************************************************** + * + * FUNCTION: pr_power_add_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +/* + * TBD: 1. PROC_C1 support. + * 2. Symmetric Cx state support (different Cx states supported + * by different CPUs results in lowest common denominator). + */ + +ACPI_STATUS +pr_power_add_device ( + PR_CONTEXT *processor) +{ + if (!processor) { + return(AE_BAD_PARAMETER); + } + + /* + * State Count: + * ------------ + * Fixed at four (C0-C3). We use is_valid to determine whether or + * not a state actually gets used. + */ + processor->power.state_count = PR_MAX_POWER_STATES; + + /* + * C0: + * --- + * C0 exists only as filler in our array. (Let's assume its valid!) + */ + processor->power.state[PR_C0].is_valid = TRUE; + + /* + * C1: + * --- + * ACPI states that C1 must be supported by all processors + * with a latency so small that it can be ignored. + * + * TBD: What about PROC_C1 support? + */ + processor->power.state[PR_C1].is_valid = TRUE; + + /* + * C2: + * --- + * We're only supporting C2 on UP systems with latencies <= 100us. + * + * TBD: Support for C2 on MP (P_LVL2_UP) -- I'm taking the + * conservative approach for now. + */ + processor->power.state[PR_C2].latency = acpi_fadt.plvl2_lat; + +#ifdef CONFIG_SMP + if (smp_num_cpus == 1) { +#endif /*CONFIG_SMP*/ + if (acpi_fadt.plvl2_lat <= PR_MAX_C2_LATENCY) { + processor->power.state[PR_C2].is_valid = TRUE; + processor->power.p_lvl2 = processor->pblk.address + 4; + } +#ifdef CONFIG_SMP + } +#endif /*CONFIG_SMP*/ + + + /* + * C3: + * --- + * We're only supporting C3 on UP systems with latencies <= 1000us, + * and that include the ability to disable bus mastering while in + * C3 (ARB_DIS) but allows bus mastering requests to wake the system + * from C3 (BM_RLD). Note his method of maintaining cache coherency + * (disabling of bus mastering) cannot be used on SMP systems, and + * flushing caches (e.g. WBINVD) is simply too costly at this time. + * + * TBD: Support for C3 on MP -- I'm taking the conservative + * approach for now. + */ + processor->power.state[PR_C3].latency = acpi_fadt.plvl3_lat; + +#ifdef CONFIG_SMP + if (smp_num_cpus == 1) { +#endif /*CONFIG_SMP*/ + if ((acpi_fadt.plvl3_lat <= PR_MAX_C3_LATENCY) && + (acpi_fadt.V1_pm2_cnt_blk && acpi_fadt.pm2_cnt_len)) { + /* TBD: Resolve issue with C3 and HDD corruption. */ + processor->power.state[PR_C3].is_valid = FALSE; + /* processor->power.state[PR_C3].is_valid = TRUE;*/ + processor->power.p_lvl3 = processor->pblk.address + 5; + } +#ifdef CONFIG_SMP + } +#endif /*CONFIG_SMP*/ + + /* + * 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). + */ + pr_power_set_default_policy(processor); + + /* + * Save Processor Context: + * ----------------------- + * TBD: Enhance Linux idle handler to take processor context + * parameter. + */ + processor_list[processor->uid] = processor; + + return(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: pr_power_remove_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +pr_power_remove_device ( + PR_CONTEXT *processor) +{ + ACPI_STATUS status = AE_OK; + + if (!processor) { + return(AE_BAD_PARAMETER); + } + + MEMSET(&(processor->power), 0, sizeof(PR_POWER)); + + processor_list[processor->uid] = NULL; + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: pr_power_initialize + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +pr_power_initialize (void) +{ + u32 i = 0; + + /* TBD: Linux-specific. */ + for (i=0; i + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +pr_power_terminate (void) +{ + /* + * Remove idle handler. + * + * TBD: Linux-specific (need OSL function). + */ + pm_idle = pr_pm_idle_save; + + return(AE_OK); +} diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/system/Makefile linux/drivers/acpi/ospm/system/Makefile --- v2.4.5/linux/drivers/acpi/ospm/system/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/system/Makefile Wed Jun 20 17:47:40 2001 @@ -0,0 +1,6 @@ +O_TARGET := ospm_$(notdir $(CURDIR)).o +obj-m := $(O_TARGET) +EXTRA_CFLAGS += $(ACPI_CFLAGS) +obj-y := $(patsubst %.c,%.o,$(wildcard *.c)) + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/system/sm.c linux/drivers/acpi/ospm/system/sm.c --- v2.4.5/linux/drivers/acpi/ospm/system/sm.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/system/sm.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,330 @@ +/***************************************************************************** + * + * Module Name: sm.c + * $Revision: 16 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 "sm.h" + + +#define _COMPONENT ACPI_SYSTEM + MODULE_NAME ("sm") + + +/**************************************************************************** + * Internal Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: sm_print + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: Prints out information on a specific system. + * + ****************************************************************************/ + +void +sm_print ( + SM_CONTEXT *system) +{ + + return; +} + + +/**************************************************************************** + * + * FUNCTION: sm_add_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +sm_add_device( + BM_HANDLE device_handle, + void **context) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE *device = NULL; + SM_CONTEXT *system = NULL; + u8 i, type_a, type_b; + + + if (!context || *context) { + return(AE_BAD_PARAMETER); + } + + /* + * Allocate a new SM_CONTEXT structure. + */ + system = acpi_os_callocate(sizeof(SM_CONTEXT)); + if (!system) { + return(AE_NO_MEMORY); + } + + /* + * Get information on this device. + */ + status = bm_get_device_info(device_handle, &device); + if (ACPI_FAILURE(status)) { + goto end; + } + + system->device_handle = device->handle; + system->acpi_handle = device->acpi_handle; + + /* + * Sx States: + * ---------- + * Figure out which Sx states are supported. + */ + for (i=0; istates[i] = TRUE; + } + } + + status = sm_osl_add_device(system); + if (ACPI_FAILURE(status)) { + goto end; + } + + *context = system; + + sm_print(system); + +end: + if (ACPI_FAILURE(status)) { + acpi_os_free(system); + } + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: sm_remove_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +sm_remove_device ( + void **context) +{ + ACPI_STATUS status = AE_OK; + SM_CONTEXT *system = NULL; + + if (!context || !*context) { + return(AE_BAD_PARAMETER); + } + + system = (SM_CONTEXT*)*context; + + status = sm_osl_remove_device(system); + + acpi_os_free(system); + + *context = NULL; + + return(status); +} + + +/**************************************************************************** + * External Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: sm_initialize + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +sm_initialize (void) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE_ID criteria; + BM_DRIVER driver; + + MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID)); + MEMSET(&driver, 0, sizeof(BM_DRIVER)); + + /* + * Register driver for the System device. + */ + criteria.type = BM_TYPE_SYSTEM; + + driver.notify = &sm_notify; + driver.request = &sm_request; + + status = bm_register_driver(&criteria, &driver); + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: sm_terminate + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +sm_terminate (void) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE_ID criteria; + BM_DRIVER driver; + + MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID)); + MEMSET(&driver, 0, sizeof(BM_DRIVER)); + + /* + * Unregister driver for System devices. + */ + criteria.type = BM_TYPE_SYSTEM; + + driver.notify = &sm_notify; + driver.request = &sm_request; + + status = bm_unregister_driver(&criteria, &driver); + + return(status); +} + + +/***************************************************************************** + * + * FUNCTION: sm_notify + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ +ACPI_STATUS +sm_notify ( + BM_NOTIFY notify_type, + BM_HANDLE device_handle, + void **context) +{ + ACPI_STATUS status = AE_OK; + + if (!context) { + return(AE_BAD_PARAMETER); + } + + switch (notify_type) { + + case BM_NOTIFY_DEVICE_ADDED: + status = sm_add_device(device_handle, context); + break; + + case BM_NOTIFY_DEVICE_REMOVED: + status = sm_remove_device(context); + break; + + default: + status = AE_SUPPORT; + break; + } + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: sm_request + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +sm_request ( + BM_REQUEST *request, + void *context) +{ + ACPI_STATUS status = AE_OK; + + /* + * Must have a valid request structure and context. + */ + if (!request || !context) { + return(AE_BAD_PARAMETER); + } + + /* + * Handle Request: + * --------------- + */ + switch (request->command) { + + default: + status = AE_SUPPORT; + break; + } + + request->status = status; + + return(status); +} diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/system/sm_osl.c linux/drivers/acpi/ospm/system/sm_osl.c --- v2.4.5/linux/drivers/acpi/ospm/system/sm_osl.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/system/sm_osl.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,344 @@ +/****************************************************************************** + * + * Module Name: sm_osl.c + * $Revision: 10 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 "sm.h" + + +MODULE_AUTHOR("Andrew Grover"); +MODULE_DESCRIPTION("ACPI Component Architecture (CA) - ACPI System Driver"); + + +#define SM_PROC_INFO "info" +#define SM_PROC_DSDT "dsdt" + +extern struct proc_dir_entry *bm_proc_root; +struct proc_dir_entry *sm_proc_root = NULL; +static void (*sm_pm_power_off)(void) = NULL; + +static ssize_t sm_osl_read_dsdt(struct file *, char *, size_t, loff_t *); + +static struct file_operations proc_dsdt_operations = { + read: sm_osl_read_dsdt, +}; + + + +/**************************************************************************** + * + * FUNCTION: sm_osl_proc_read_info + * + ****************************************************************************/ + +static int +sm_osl_proc_read_info ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *context) +{ + ACPI_STATUS status = AE_OK; + SM_CONTEXT *system = NULL; + char *p = page; + int len; + ACPI_SYSTEM_INFO system_info; + ACPI_BUFFER buffer; + u32 i = 0; + + if (!context) { + goto end; + } + + system = (SM_CONTEXT*)context; + + /* don't get status more than once for a single proc read */ + if (off != 0) { + goto end; + } + + /* + * Get ACPI CA Information. + */ + buffer.length = sizeof(system_info); + buffer.pointer = &system_info; + + status = acpi_get_system_info(&buffer); + if (ACPI_FAILURE(status)) { + p += sprintf(p, "ACPI-CA Version: unknown\n"); + } + else { + p += sprintf(p, "ACPI-CA Version: %x\n", + system_info.acpi_ca_version); + } + + p += sprintf(p, "Sx States Supported: "); + for (i=0; istates[i]) { + p += sprintf(p, "S%d ", i); + } + } + 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(len); +} + +/**************************************************************************** + * + * FUNCTION: sm_osl_read_dsdt + * + ****************************************************************************/ + +static ssize_t +sm_osl_read_dsdt( + struct file *file, + char *buf, + size_t count, + loff_t *ppos) +{ + ACPI_BUFFER acpi_buf; + void *data; + size_t size = 0; + + acpi_buf.length = 0; + acpi_buf.pointer = NULL; + + + /* determine what buffer size we will need */ + if (acpi_get_table(ACPI_TABLE_DSDT, 1, &acpi_buf) != AE_BUFFER_OVERFLOW) { + return 0; + } + + acpi_buf.pointer = kmalloc(acpi_buf.length, GFP_KERNEL); + if (!acpi_buf.pointer) { + return -ENOMEM; + } + + /* get the table for real */ + if (!ACPI_SUCCESS(acpi_get_table(ACPI_TABLE_DSDT, 1, &acpi_buf))) { + kfree(acpi_buf.pointer); + return 0; + } + + if (*ppos < acpi_buf.length) { + data = acpi_buf.pointer + file->f_pos; + size = acpi_buf.length - file->f_pos; + if (size > count) + size = count; + if (copy_to_user(buf, data, size)) { + kfree(acpi_buf.pointer); + return -EFAULT; + } + } + + kfree(acpi_buf.pointer); + + *ppos += size; + + return size; +} + + +/**************************************************************************** + * + * FUNCTION: sm_osl_power_down + * + ****************************************************************************/ + +void +sm_osl_power_down (void) +{ + ACPI_STATUS status = AE_OK; + + /* Power down the system (S5 = soft off). */ + status = acpi_enter_sleep_state(ACPI_STATE_S5); +} + + +/**************************************************************************** + * + * FUNCTION: sm_osl_add_device + * + ****************************************************************************/ + +ACPI_STATUS +sm_osl_add_device( + SM_CONTEXT *system) +{ + u32 i = 0; + struct proc_dir_entry *bm_proc_dsdt; + + if (!system) { + return(AE_BAD_PARAMETER); + } + + printk("ACPI: System firmware supports"); + for (i=0; istates[i]) { + printk(" S%d", i); + } + } + printk("\n"); + + if (system->states[ACPI_STATE_S5]) { + sm_pm_power_off = pm_power_off; + pm_power_off = sm_osl_power_down; + } + + create_proc_read_entry(SM_PROC_INFO, S_IRUGO, + sm_proc_root, sm_osl_proc_read_info, (void*)system); + + /* + * This returns more than a page, so we need to use our own file ops, + * not proc's generic ones + */ + bm_proc_dsdt = create_proc_entry(SM_PROC_DSDT, S_IRUSR, sm_proc_root); + if (bm_proc_dsdt) { + bm_proc_dsdt->proc_fops = &proc_dsdt_operations; + } + + return(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: sm_osl_remove_device + * + ****************************************************************************/ + +ACPI_STATUS +sm_osl_remove_device ( + SM_CONTEXT *system) +{ + if (!system) { + return(AE_BAD_PARAMETER); + } + + remove_proc_entry(SM_PROC_INFO, sm_proc_root); + remove_proc_entry(SM_PROC_DSDT, sm_proc_root); + + return(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: sm_osl_generate_event + * + ****************************************************************************/ + +ACPI_STATUS +sm_osl_generate_event ( + u32 event, + SM_CONTEXT *system) +{ + ACPI_STATUS status = AE_OK; + + if (!system) { + return(AE_BAD_PARAMETER); + } + + switch (event) { + + default: + return(AE_BAD_PARAMETER); + break; + } + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: sm_osl_init + * + * PARAMETERS: + * + * RETURN: 0: Success + * + * DESCRIPTION: Module initialization. + * + ****************************************************************************/ + +static int __init +sm_osl_init (void) +{ + ACPI_STATUS status = AE_OK; + + sm_proc_root = bm_proc_root; + if (!sm_proc_root) { + status = AE_ERROR; + } + else { + status = sm_initialize(); + } + + return (ACPI_SUCCESS(status)) ? 0 : -ENODEV; +} + + +/**************************************************************************** + * + * FUNCTION: sm_osl_cleanup + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: Module cleanup. + * + ****************************************************************************/ + +static void __exit +sm_osl_cleanup (void) +{ + sm_terminate(); + + return; +} + + +module_init(sm_osl_init); +module_exit(sm_osl_cleanup); diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/thermal/Makefile linux/drivers/acpi/ospm/thermal/Makefile --- v2.4.5/linux/drivers/acpi/ospm/thermal/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/thermal/Makefile Wed Jun 20 17:47:40 2001 @@ -0,0 +1,6 @@ +O_TARGET := ospm_$(notdir $(CURDIR)).o +obj-m := $(O_TARGET) +EXTRA_CFLAGS += $(ACPI_CFLAGS) +obj-y := $(patsubst %.c,%.o,$(wildcard *.c)) + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/thermal/tz.c linux/drivers/acpi/ospm/thermal/tz.c --- v2.4.5/linux/drivers/acpi/ospm/thermal/tz.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/thermal/tz.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,659 @@ +/***************************************************************************** + * + * Module Name: tz.c + * $Revision: 38 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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. Finish /proc interface (threshold values, _SCP changes, etc.) + * 2. Update policy for ACPI 2.0 compliance + * 3. Check for all required methods prior to enabling a threshold + * 4. Support for multiple processors in a zone (passive cooling devices) + */ + +#include +#include +#include "tz.h" + +#define _COMPONENT ACPI_THERMAL + MODULE_NAME ("tz") + + +/**************************************************************************** + * Internal Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: tz_print + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: Prints out information on a specific thermal zone. + * + ****************************************************************************/ + +void +tz_print ( + TZ_CONTEXT *thermal_zone) +{ + + return; +} + + +/**************************************************************************** + * + * FUNCTION: tz_get_temperaturee + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +tz_get_temperature ( + TZ_CONTEXT *thermal_zone, + u32 *temperature) +{ + ACPI_STATUS status = AE_OK; + + if (!thermal_zone || !temperature) { + return(AE_BAD_PARAMETER); + } + + /* + * Evaluate the _TMP driver method to get the current temperature. + */ + status = bm_evaluate_simple_integer(thermal_zone->acpi_handle, + "_TMP", temperature); + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: tz_set_cooling_preference + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +tz_set_cooling_preference ( + TZ_CONTEXT *thermal_zone, + TZ_COOLING_MODE cooling_mode) +{ + ACPI_STATUS status = AE_OK; + ACPI_OBJECT_LIST arg_list; + ACPI_OBJECT arg0; + + if (!thermal_zone || ((cooling_mode != TZ_COOLING_MODE_ACTIVE) && + (cooling_mode != TZ_COOLING_MODE_PASSIVE))) { + return(AE_BAD_PARAMETER); + } + + /* + * Build the argument list, which simply consists of the current + * cooling preference. + */ + MEMSET(&arg_list, 0, sizeof(ACPI_OBJECT)); + arg_list.count = 1; + arg_list.pointer = &arg0; + + MEMSET(&arg0, 0, sizeof(ACPI_OBJECT)); + arg0.type = ACPI_TYPE_INTEGER; + arg0.integer.value = cooling_mode; + + /* + * Evaluate "_SCP" - setting the new cooling preference. + */ + status = acpi_evaluate_object(thermal_zone->acpi_handle, "_SCP", + &arg_list, NULL); + + return(status); +} + + +/*************************************************************************** + * + * FUNCTION: tz_get_single_threshold + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +tz_get_single_threshold ( + TZ_CONTEXT *thermal_zone, + TZ_THRESHOLD *threshold) +{ + ACPI_STATUS status = AE_OK; + + if (!thermal_zone || !threshold) { + return(AE_BAD_PARAMETER); + } + + switch (threshold->type) { + + /* + * Critical Threshold: + * ------------------- + */ + case TZ_THRESHOLD_CRITICAL: + threshold->index = 0; + threshold->cooling_devices.count = 0; + status = bm_evaluate_simple_integer( + thermal_zone->acpi_handle, "_CRT", + &(threshold->temperature)); + break; + + /* + * Passive Threshold: + * ------------------ + * Evaluate _PSV to get the threshold temperature and _PSL to get + * references to all passive cooling devices. + */ + case TZ_THRESHOLD_PASSIVE: + threshold->index = 0; + threshold->cooling_devices.count = 0; + status = bm_evaluate_simple_integer( + thermal_zone->acpi_handle, "_PSV", + &(threshold->temperature)); + if (ACPI_SUCCESS(status)) { + status = bm_evaluate_reference_list( + thermal_zone->acpi_handle, "_PSL", + &(threshold->cooling_devices)); + } + + break; + + /* + * Active Thresholds: + * ------------------ + * Evaluate _ACx to get all threshold temperatures, and _ALx to get + * references to all passive cooling devices. + */ + case TZ_THRESHOLD_ACTIVE: + { + char object_name[5] = {'_','A', 'C', + ('0'+threshold->index),'\0'}; + status = bm_evaluate_simple_integer( + thermal_zone->acpi_handle, object_name, + &(threshold->temperature)); + if (ACPI_SUCCESS(status)) { + object_name[2] = 'L'; + status = bm_evaluate_reference_list( + thermal_zone->acpi_handle, + object_name, + &(threshold->cooling_devices)); + } + } + break; + + default: + status = AE_SUPPORT; + break; + } + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: tz_get_thresholds + * + * PARAMETERS: thermal_zone - Identifies the thermal zone to parse. + * buffer - Output buffer. + * + * RETURN: ACPI_STATUS result code. + * + * DESCRIPTION: Builds a TZ_THRESHOLD_LIST structure containing information + * on all thresholds for a given thermal zone. + * + * NOTES: The current design limits the number of cooling devices + * per theshold to the value specified by BM_MAX_HANDLES. + * This simplifies parsing of thresholds by allowing a maximum + * threshold list size to be computed (and enforced) -- which + * allows all thresholds to be parsed in a single pass (since + * memory must be contiguous when returned in the ACPI_BUFFER). + * + ****************************************************************************/ + +ACPI_STATUS +tz_get_thresholds ( + TZ_CONTEXT *thermal_zone, + TZ_THRESHOLD_LIST *threshold_list) +{ + ACPI_STATUS status = AE_OK; + TZ_THRESHOLD *threshold = NULL; + u32 i = 0; + + if (!thermal_zone || !threshold_list) { + return(AE_BAD_PARAMETER); + } + + threshold_list->count = 0; + + /* + * Critical threshold: + * ------------------- + * Every thermal zone must have one! + */ + threshold = &(threshold_list->thresholds[threshold_list->count]); + threshold->type = TZ_THRESHOLD_CRITICAL; + + status = tz_get_single_threshold(thermal_zone, threshold); + if (ACPI_SUCCESS(status)) { + (threshold_list->count)++; + } + else { + return(status); + } + + + /* + * Passive threshold: + * ------------------ + */ + threshold = &(threshold_list->thresholds[threshold_list->count]); + threshold->type = TZ_THRESHOLD_PASSIVE; + + status = tz_get_single_threshold(thermal_zone, threshold); + if (ACPI_SUCCESS(status)) { + (threshold_list->count)++; + } + + /* + * Active threshold: + * ----------------- + * Note that active thresholds are sorted by index (e.g. _AC0, + * _AC1, ...), and thus from highest (_AC0) to lowest (_AC9) + * temperature. + */ + for (i = 0; i < TZ_MAX_ACTIVE_THRESHOLDS; i++) { + + threshold = &(threshold_list->thresholds[threshold_list->count]); + threshold->type = TZ_THRESHOLD_ACTIVE; + threshold->index = i; + + status = tz_get_single_threshold(thermal_zone, threshold); + if (ACPI_SUCCESS(status)) { + (threshold_list->count)++; + } + else { + threshold->type = TZ_THRESHOLD_UNKNOWN; + threshold->index = 0; + thermal_zone->policy.active.threshold_count = i; + break; + } + } + + return(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: tz_add_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +tz_add_device ( + BM_HANDLE device_handle, + void **context) +{ + ACPI_STATUS status = AE_OK; + TZ_CONTEXT *thermal_zone = NULL; + BM_DEVICE *device = NULL; + ACPI_HANDLE tmp_handle = NULL; + static u32 zone_count = 0; + + if (!context || *context) { + return(AE_BAD_PARAMETER); + } + + /* + * Get information on this device. + */ + status = bm_get_device_info(device_handle, &device); + if (ACPI_FAILURE(status)) { + return(status); + } + + /* + * Allocate a new Thermal Zone device. + */ + thermal_zone = acpi_os_callocate(sizeof(TZ_CONTEXT)); + if (!thermal_zone) { + return AE_NO_MEMORY; + } + + thermal_zone->device_handle = device->handle; + thermal_zone->acpi_handle = device->acpi_handle; + + /* TBD: How to manage 'uid' when zones are Pn_p? */ + sprintf(thermal_zone->uid, "%d", zone_count++); + + /* + * _TMP? + * ----- + */ + status = acpi_get_handle(thermal_zone->acpi_handle, "_TMP", + &tmp_handle); + if (ACPI_FAILURE(status)) { + goto end; + } + + /* + * Initialize Policy: + * ------------------ + * TBD: Move all thermal zone policy to user-mode daemon... + */ + status = tz_policy_add_device(thermal_zone); + if (ACPI_FAILURE(status)) { + goto end; + } + + status = tz_osl_add_device(thermal_zone); + if (ACPI_FAILURE(status)) { + goto end; + } + + *context = thermal_zone; + + tz_print(thermal_zone); + +end: + if (ACPI_FAILURE(status)) { + acpi_os_free(thermal_zone); + } + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: tz_remove_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +tz_remove_device ( + void **context) +{ + ACPI_STATUS status = AE_OK; + TZ_CONTEXT *thermal_zone = NULL; + + if (!context || !*context) { + return(AE_BAD_PARAMETER); + } + + thermal_zone = (TZ_CONTEXT*)(*context); + + status = tz_osl_remove_device(thermal_zone); + + /* + * Remove Policy: + * -------------- + * TBD: Move all thermal zone policy to user-mode daemon... + */ + status = tz_policy_remove_device(thermal_zone); + if (ACPI_FAILURE(status)) { + return(status); + } + + acpi_os_free(thermal_zone); + + return(status); +} + + +/**************************************************************************** + * External Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: tz_initialize + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +tz_initialize (void) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE_ID criteria; + BM_DRIVER driver; + + MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID)); + MEMSET(&driver, 0, sizeof(BM_DRIVER)); + + /* + * Register driver for thermal zone devices. + */ + criteria.type = BM_TYPE_THERMAL_ZONE; + + driver.notify = &tz_notify; + driver.request = &tz_request; + + status = bm_register_driver(&criteria, &driver); + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: tz_terminate + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +tz_terminate (void) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE_ID criteria; + BM_DRIVER driver; + + MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID)); + MEMSET(&driver, 0, sizeof(BM_DRIVER)); + + /* + * Unregister driver for thermal zone devices. + */ + criteria.type = BM_TYPE_THERMAL_ZONE; + + driver.notify = &tz_notify; + driver.request = &tz_request; + + status = bm_unregister_driver(&criteria, &driver); + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: tz_notify + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ +ACPI_STATUS +tz_notify ( + BM_NOTIFY notify_type, + BM_HANDLE device_handle, + void **context) +{ + ACPI_STATUS status = AE_OK; + TZ_CONTEXT *thermal_zone = NULL; + + if (!context) { + return(AE_BAD_PARAMETER); + } + + thermal_zone = (TZ_CONTEXT*)*context; + + switch (notify_type) { + + case BM_NOTIFY_DEVICE_ADDED: + status = tz_add_device(device_handle, context); + break; + + case BM_NOTIFY_DEVICE_REMOVED: + status = tz_remove_device(context); + break; + + case TZ_NOTIFY_TEMPERATURE_CHANGE: + /* -------------------------------------------- */ + /* TBD: Remove when policy moves to user-mode. */ + tz_policy_check(*context); + /* -------------------------------------------- */ + status = tz_get_temperature(thermal_zone, + &(thermal_zone->policy.temperature)); + if (ACPI_SUCCESS(status)) { + status = tz_osl_generate_event(notify_type, + thermal_zone); + } + break; + + case TZ_NOTIFY_THRESHOLD_CHANGE: + /* -------------------------------------------- */ + /* TBD: Remove when policy moves to user-mode. */ + status = tz_policy_remove_device(thermal_zone); + if (ACPI_SUCCESS(status)) { + status = tz_policy_add_device(thermal_zone); + } + /* -------------------------------------------- */ + status = tz_osl_generate_event(notify_type, thermal_zone); + break; + + case TZ_NOTIFY_DEVICE_LISTS_CHANGE: + /* -------------------------------------------- */ + /* TBD: Remove when policy moves to user-mode. */ + status = tz_policy_remove_device(thermal_zone); + if (ACPI_SUCCESS(status)) { + status = tz_policy_add_device(thermal_zone); + } + /* -------------------------------------------- */ + status = tz_osl_generate_event(notify_type, thermal_zone); + break; + + default: + status = AE_SUPPORT; + break; + } + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: tz_request + * + * PARAMETERS: + * + * RETURN: Exception code. + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +tz_request ( + BM_REQUEST *request, + void *context) +{ + ACPI_STATUS status = AE_OK; + TZ_CONTEXT *thermal_zone = NULL; + + /* + * Must have a valid request structure and context. + */ + if (!request || !context) { + return(AE_BAD_PARAMETER); + } + + thermal_zone = (TZ_CONTEXT*)context; + + /* + * Handle request: + * --------------- + */ + switch (request->command) { + + default: + status = AE_SUPPORT; + break; + } + + request->status = status; + + return(status); +} diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/thermal/tz_osl.c linux/drivers/acpi/ospm/thermal/tz_osl.c --- v2.4.5/linux/drivers/acpi/ospm/thermal/tz_osl.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/thermal/tz_osl.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,330 @@ +/****************************************************************************** + * + * Module Name: tz_osl.c + * $Revision: 18 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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 "tz.h" + + +MODULE_AUTHOR("Andrew Grover"); +MODULE_DESCRIPTION("ACPI Component Architecture (CA) - Thermal Zone Driver"); + +int TZP = 0; +MODULE_PARM(TZP, "i"); +MODULE_PARM_DESC(TZP, "Thermal zone polling frequency, in 1/10 seconds.\n"); + + +#define TZ_PROC_ROOT "thermal" +#define TZ_PROC_STATUS "status" +#define TZ_PROC_INFO "info" + +extern struct proc_dir_entry *bm_proc_root; +static struct proc_dir_entry *tz_proc_root = NULL; + + +/**************************************************************************** + * + * FUNCTION: tz_osl_proc_read_info + * + ****************************************************************************/ + +static int +tz_osl_proc_read_info ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *context) +{ + TZ_CONTEXT *thermal_zone = NULL; + char *p = page; + int len = 0; + + if (!context || (off != 0)) { + goto end; + } + + thermal_zone = (TZ_CONTEXT*)context; + + 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(len); +} + + +/**************************************************************************** + * + * FUNCTION: tz_osl_proc_read_status + * + ****************************************************************************/ + +static int +tz_osl_proc_read_status ( + char *page, + char **start, + off_t off, + int count, + int *eof, + void *context) +{ + TZ_CONTEXT *thermal_zone = NULL; + char *p = page; + int len = 0; + + if (!context || (off != 0)) { + goto end; + } + + thermal_zone = (TZ_CONTEXT*)context; + + p += sprintf(p, "Temperature: %d (1/10th degrees Kelvin)\n", + thermal_zone->policy.temperature); + + p += sprintf(p, "State: "); + if (thermal_zone->policy.state & TZ_STATE_ACTIVE) { + p += sprintf(p, "active[%d] ", thermal_zone->policy.state & 0x07); + } + if (thermal_zone->policy.state & TZ_STATE_PASSIVE) { + p += sprintf(p, "passive "); + } + if (thermal_zone->policy.state & TZ_STATE_CRITICAL) { + p += sprintf(p, "critical "); + } + if (thermal_zone->policy.state == 0) { + p += sprintf(p, "ok "); + } + p += sprintf(p, "\n"); + + p += sprintf(p, "Cooling Mode: "); + switch (thermal_zone->policy.cooling_mode) { + case TZ_COOLING_MODE_ACTIVE: + p += sprintf(p, "active (noisy)\n"); + break; + case TZ_COOLING_MODE_PASSIVE: + p += sprintf(p, "passive (quiet)\n"); + break; + default: + p += sprintf(p, "unknown\n"); + break; + } + + p += sprintf(p, "Polling Frequency: "); + switch (thermal_zone->policy.polling_freq) { + case 0: + p += sprintf(p, "n/a\n"); + break; + default: + p += sprintf(p, "%d (1/10th seconds)\n", thermal_zone->policy.polling_freq); + 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(len); +} + + +/**************************************************************************** + * + * FUNCTION: tz_osl_add_device + * + ****************************************************************************/ + +ACPI_STATUS +tz_osl_add_device( + TZ_CONTEXT *thermal_zone) +{ + struct proc_dir_entry *proc_entry = NULL; + + if (!thermal_zone) { + return(AE_BAD_PARAMETER); + } + + printk("Thermal Zone: found\n"); + + proc_entry = proc_mkdir(thermal_zone->uid, tz_proc_root); + if (!proc_entry) { + return(AE_ERROR); + } + + create_proc_read_entry(TZ_PROC_STATUS, S_IFREG | S_IRUGO, + proc_entry, tz_osl_proc_read_status, (void*)thermal_zone); + + create_proc_read_entry(TZ_PROC_INFO, S_IFREG | S_IRUGO, + proc_entry, tz_osl_proc_read_info, (void*)thermal_zone); + + return(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: tz_osl_remove_device + * + ****************************************************************************/ + +ACPI_STATUS +tz_osl_remove_device ( + TZ_CONTEXT *thermal_zone) +{ + char proc_entry[64]; + + if (!thermal_zone) { + return(AE_BAD_PARAMETER); + } + + sprintf(proc_entry, "%s/%s", thermal_zone->uid, TZ_PROC_INFO); + remove_proc_entry(proc_entry, tz_proc_root); + + sprintf(proc_entry, "%s/%s", thermal_zone->uid, TZ_PROC_STATUS); + remove_proc_entry(proc_entry, tz_proc_root); + + sprintf(proc_entry, "%s", thermal_zone->uid); + remove_proc_entry(proc_entry, tz_proc_root); + + return(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: tz_osl_generate_event + * + ****************************************************************************/ + +ACPI_STATUS +tz_osl_generate_event ( + u32 event, + TZ_CONTEXT *thermal_zone) +{ + ACPI_STATUS status = AE_OK; + + if (!thermal_zone) { + return(AE_BAD_PARAMETER); + } + + switch (event) { + + case TZ_NOTIFY_TEMPERATURE_CHANGE: + status = bm_osl_generate_event(thermal_zone->device_handle, + TZ_PROC_ROOT, thermal_zone->uid, event, + thermal_zone->policy.temperature); + break; + + case TZ_NOTIFY_THRESHOLD_CHANGE: + case TZ_NOTIFY_DEVICE_LISTS_CHANGE: + status = bm_osl_generate_event(thermal_zone->device_handle, + TZ_PROC_ROOT, thermal_zone->uid, event, 0); + break; + + default: + return(AE_BAD_PARAMETER); + break; + } + + return(status); +} + + +/**************************************************************************** + * + * FUNCTION: tz_osl_init + * + * PARAMETERS: + * + * RETURN: 0: Success + * + * DESCRIPTION: Module initialization. + * + ****************************************************************************/ + +static int __init +tz_osl_init (void) +{ + ACPI_STATUS status = AE_OK; + + tz_proc_root = proc_mkdir(TZ_PROC_ROOT, bm_proc_root); + if (!tz_proc_root) { + status = AE_ERROR; + } + else { + status = tz_initialize(); + if (ACPI_FAILURE(status)) { + remove_proc_entry(TZ_PROC_ROOT, bm_proc_root); + } + + } + + return (ACPI_SUCCESS(status)) ? 0 : -ENODEV; +} + + +/**************************************************************************** + * + * FUNCTION: tz_osl_cleanup + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: Module cleanup. + * + ****************************************************************************/ + +static void __exit +tz_osl_cleanup (void) +{ + tz_terminate(); + + if (tz_proc_root) { + remove_proc_entry(TZ_PROC_ROOT, bm_proc_root); + } + + return; +} + + +module_init(tz_osl_init); +module_exit(tz_osl_cleanup); diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/ospm/thermal/tzpolicy.c linux/drivers/acpi/ospm/thermal/tzpolicy.c --- v2.4.5/linux/drivers/acpi/ospm/thermal/tzpolicy.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/ospm/thermal/tzpolicy.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,640 @@ +/**************************************************************************** + * + * Module Name: tzpolicy.c - + * $Revision: 27 $ + * + ****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * 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. Move to user-space! + * 2. Support ACPI 2.0 items (e.g. _TZD, _HOT). + * 3. Support performance-limit control for non-processor devices + * (those listed in _TZD, e.g. graphics). + */ + +/* TBD: Linux specific */ +#include +#include +#include + +#include +#include +#include "tz.h" + + +#define _COMPONENT ACPI_THERMAL + MODULE_NAME ("tzpolicy") + + +/**************************************************************************** + * Globals + ****************************************************************************/ + +extern int TZP; + +void +tz_policy_run ( + unsigned long data); + + +/**************************************************************************** + * Internal Functions + ****************************************************************************/ + +ACPI_STATUS +set_performance_limit ( + BM_HANDLE device_handle, + u32 flag) +{ + ACPI_STATUS status; + BM_REQUEST request; + + request.status = AE_OK; + request.handle = device_handle; + request.command = PR_COMMAND_SET_PERF_LIMIT; + request.buffer.length = sizeof(u32); + request.buffer.pointer = &flag; + + status = bm_request(&request); + + if (ACPI_FAILURE(status)) { + return status; + } + else { + return request.status; + } +} + + +/**************************************************************************** + * + * FUNCTION: tz_policy_critical + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +tz_policy_critical( + TZ_CONTEXT *tz) +{ + if (!tz || !tz->policy.critical.threshold) { + return(AE_BAD_PARAMETER); + } + + if (tz->policy.temperature >= + tz->policy.critical.threshold->temperature) { + /* TBD: Need method for calling 'halt' - OSL function? */ + } + + return(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: tz_policy_passive + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +tz_policy_passive( + TZ_CONTEXT *tz) +{ + TZ_PASSIVE_POLICY *passive = NULL; + static u32 last_temperature = 0; + s32 trend = 0; + u32 i = 0; + + if (!tz || !tz->policy.passive.threshold) { + return(AE_BAD_PARAMETER); + } + + passive = &(tz->policy.passive); + + if (tz->policy.temperature >= passive->threshold->temperature) { + /* + * Thermal trend? + * -------------- + * Using the passive cooling equation (see the ACPI + * Specification), calculate the current thermal trend + * (a.k.a. performance delta). + */ + trend = passive->tc1 * + (tz->policy.temperature - last_temperature) + + passive->tc2 * + (tz->policy.temperature - passive->threshold->temperature); + + last_temperature = tz->policy.temperature; + + /* + * Heating Up? + * ----------- + * Decrease thermal performance limit on all passive + * cooling devices (processors). + */ + if (trend > 0) { + for (i=0; ithreshold->cooling_devices.count; i++) { + set_performance_limit( + passive->threshold->cooling_devices.handles[i], + PR_PERF_DEC); + } + } + /* + * Cooling Off? + * ------------ + * Increase thermal performance limit on all passive + * cooling devices (processors). + */ + else if (trend < 0) { + for (i=0; ithreshold->cooling_devices.count; i++) { + set_performance_limit( + passive->threshold->cooling_devices.handles[i], + PR_PERF_INC); + } + } + } + + return(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: tz_policy_active + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +tz_policy_active( + TZ_CONTEXT *tz) +{ + ACPI_STATUS status = AE_OK; + TZ_THRESHOLD *active = NULL; + u32 i,j = 0; + + if (!tz || !tz->policy.active.threshold) { + return(AE_BAD_PARAMETER); + } + + for (i = 0; i < TZ_MAX_ACTIVE_THRESHOLDS; i++) { + + active = tz->policy.active.threshold[i]; + if (!active) { + break; + } + + /* + * Above Threshold? + * ---------------- + * If not already enabled, turn ON all cooling devices + * associated with this active threshold. + */ + if ((tz->policy.temperature >= active->temperature) && + (active->cooling_state != TZ_COOLING_ENABLED)) { + + for (j = 0; j < active->cooling_devices.count; j++) { + + status = bm_set_device_power_state( + active->cooling_devices.handles[j], + ACPI_STATE_D0); + + if (ACPI_SUCCESS(status)) { + } + else { + } + } + + active->cooling_state = TZ_COOLING_ENABLED; + } + /* + * Below Threshold? + * ---------------- + * Turn OFF all cooling devices associated with this + * threshold. Note that by checking "if not disabled" we + * turn off all cooling devices for thresholds in the + * TZ_COOLING_STATE_UNKNOWN state, useful as a level-set + * during the first pass. + */ + else if (active->cooling_state != TZ_COOLING_DISABLED) { + + for (j = 0; j < active->cooling_devices.count; j++) { + + status = bm_set_device_power_state( + active->cooling_devices.handles[j], + ACPI_STATE_D3); + + if (ACPI_SUCCESS(status)) { + } + else { + } + } + + active->cooling_state = TZ_COOLING_DISABLED; + } + } + + return(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: tz_policy_check + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: Note that this function will get called whenever: + * 1. A thermal event occurs. + * 2. The polling/sampling time period expires. + * + ****************************************************************************/ + +void +tz_policy_check ( + void *context) +{ + ACPI_STATUS status = AE_OK; + TZ_CONTEXT *tz = NULL; + u32 previous_temperature = 0; + u32 previous_state = 0; + u32 active_index = 0; + u32 i = 0; + u32 sleep_time = 0; + + if (!context) { + return; + } + + tz = (TZ_CONTEXT*)context; + + /* + * Preserve Previous State: + * ------------------------ + */ + previous_temperature = tz->policy.temperature; + previous_state = tz->policy.state; + + /* + * Get Temperature: + * ---------------- + */ + status = tz_get_temperature(tz, &(tz->policy.temperature)); + if (ACPI_FAILURE(status)) { + return; + } + + /* + * Calculate State: + * ---------------- + */ + tz->policy.state = TZ_STATE_OK; + + /* Critical? */ + if ((tz->policy.critical.threshold) && + (tz->policy.temperature >= tz->policy.critical.threshold->temperature)) { + tz->policy.state |= TZ_STATE_CRITICAL; + } + + /* Passive? */ + if ((tz->policy.passive.threshold) && + (tz->policy.temperature >= tz->policy.passive.threshold->temperature)) { + tz->policy.state |= TZ_STATE_PASSIVE; + } + + /* Active? */ + if (tz->policy.active.threshold[0]) { + for (i=0; ipolicy.active.threshold_count; i++) { + if ((tz->policy.active.threshold[i]) && + (tz->policy.temperature >= tz->policy.active.threshold[i]->temperature)) { + tz->policy.state |= TZ_STATE_ACTIVE; + if (tz->policy.active.threshold[i]->index > active_index) { + active_index = tz->policy.active.threshold[i]->index; + } + } + } + tz->policy.state |= active_index; + } + + /* + * Invoke Policy: + * -------------- + * Note that policy must be invoked both when 'going into' a + * policy state (e.g. to allow fans to be turned on) and 'going + * out of' a policy state (e.g. to allow fans to be turned off); + * thus we must preserve the previous state. + */ + if (tz->policy.state & TZ_STATE_CRITICAL) { + tz_policy_critical(tz); + } + if ((tz->policy.state & TZ_STATE_PASSIVE) || + (previous_state & TZ_STATE_PASSIVE)) { + tz_policy_passive(tz); + } + if ((tz->policy.state & TZ_STATE_ACTIVE) || + (previous_state & TZ_STATE_ACTIVE)) { + tz_policy_active(tz); + } + + /* + * Calculate Sleep Time: + * --------------------- + * If we're in the passive state, use _TSP's value. Otherwise + * use _TZP or the OS's default polling frequency. If no polling + * frequency is specified then we'll wait forever (that is, until + * a thermal event occurs -- e.g. never poll). Note that _TSP + * and _TZD values are given in 1/10th seconds. + */ + if (tz->policy.state & TZ_STATE_PASSIVE) { + sleep_time = tz->policy.passive.tsp * 100; + } + else if (tz->policy.polling_freq > 0) { + sleep_time = tz->policy.polling_freq * 100; + } + else { + sleep_time = WAIT_FOREVER; + } + + + /* + * Schedule Next Poll: + * ------------------- + */ + if (sleep_time < WAIT_FOREVER) { + if (timer_pending(&(tz->policy.timer))) { + mod_timer(&(tz->policy.timer), + (HZ*sleep_time)/1000); + } + else { + tz->policy.timer.data = (u32)tz; + tz->policy.timer.function = tz_policy_run; + tz->policy.timer.expires = + jiffies + (HZ*sleep_time)/1000; + add_timer(&(tz->policy.timer)); + } + } + else { + if (timer_pending(&(tz->policy.timer))) { + del_timer(&(tz->policy.timer)); + } + } + + return; +} + + +/**************************************************************************** + * + * FUNCTION: tz_policy_run + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +void +tz_policy_run ( + unsigned long data) +{ + ACPI_STATUS status = AE_OK; + + if (!data) { + return; + } + + /* + * Defer to Non-Interrupt Level: + * ----------------------------- + * Note that all Linux kernel timers run at interrupt-level (ack!). + */ + status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, + tz_policy_check, (void*)data); + if (ACPI_FAILURE(status)) { + } + + return; +} + + +/**************************************************************************** + * + * FUNCTION: tz_policy_add_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +tz_policy_add_device ( + TZ_CONTEXT *tz) +{ + ACPI_STATUS status = AE_OK; + TZ_THRESHOLD *threshold = NULL; + u32 i,j = 0; + + if (!tz) { + return(AE_BAD_PARAMETER); + } + + /* + * Temperature: + * ------------ + * Make sure we can read the zone's current temperature (_TMP). + * If we can't, there's no use in doing any policy (abort). + */ + status = tz_get_temperature(tz, &(tz->policy.temperature)); + if (ACPI_FAILURE(status)) { + return(status); + } + + /* + * Polling Frequency: + * ------------------ + * If a _TZP object doesn't exist, use the OS default polling + * frequency. + */ + status = bm_evaluate_simple_integer(tz->acpi_handle, "_TZP", + &(tz->policy.polling_freq)); + if (ACPI_FAILURE(status)) { + tz->policy.polling_freq = TZP; + } + status = AE_OK; + + /* + * Get Thresholds: + * --------------- + * Get all of the zone's thresholds, parse, and organize for + * later use. + */ + status = tz_get_thresholds(tz, &(tz->policy.threshold_list)); + if (ACPI_FAILURE(status)) { + return(status); + } + + /* + * Initialize Policies: + * -------------------- + */ + for (i = 0; i < tz->policy.threshold_list.count; i++) { + + threshold = &(tz->policy.threshold_list.thresholds[i]); + + switch (threshold->type) { + + case TZ_THRESHOLD_CRITICAL: + tz->policy.critical.threshold = threshold; + break; + + case TZ_THRESHOLD_PASSIVE: + + /* + * Set thermal performance limit on all processors + * to max. + */ + for (j=0; jcooling_devices.count; j++) { + set_performance_limit( + threshold->cooling_devices.handles[j], + PR_PERF_MAX); + } + + /* + * Get passive cooling constants. + */ + status = bm_evaluate_simple_integer(tz->acpi_handle, + "_TC1", &(tz->policy.passive.tc1)); + if (ACPI_FAILURE(status)) { + break; + } + + status = bm_evaluate_simple_integer(tz->acpi_handle, + "_TC2", &(tz->policy.passive.tc2)); + if (ACPI_FAILURE(status)) { + break; + } + + status = bm_evaluate_simple_integer(tz->acpi_handle, + "_TSP", &(tz->policy.passive.tsp)); + if (ACPI_FAILURE(status)) { + break; + } + + tz->policy.passive.threshold = threshold; + + tz_policy_passive(tz); + + break; + + case TZ_THRESHOLD_ACTIVE: + tz->policy.active.threshold[threshold->index] = threshold; + tz_policy_active(tz); + break; + } + } + + if (ACPI_FAILURE(status)) { + return(status); + } + + /* + * Initialize Policy Timer: + * ------------------------ + * TBD: Linux-specific - remove when policy moves to user-space. + */ + init_timer(&(tz->policy.timer)); + + /* + * Start Policy: + * ------------- + * Run an initial check using this zone's policy. + */ + tz_policy_check(tz); + + return(status); +} + + +/***************************************************************************** + * + * FUNCTION: tz_policy_remove_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +tz_policy_remove_device( + TZ_CONTEXT *tz) +{ + u32 i = 0; + + if (!tz) { + return(AE_BAD_PARAMETER); + } + + /* + * Delete the thermal zone policy timer entry, if exists. + */ + if (timer_pending(&(tz->policy.timer))) { + del_timer(&(tz->policy.timer)); + } + + /* + * Reset thermal performance limit on all processors back to max. + */ + if (tz->policy.passive.threshold) { + for (i=0; ipolicy.passive.threshold->cooling_devices.count; i++) { + set_performance_limit( + tz->policy.passive.threshold->cooling_devices.handles[i], + PR_PERF_MAX); + } + } + + return(AE_OK); +} diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/parser/Makefile linux/drivers/acpi/parser/Makefile --- v2.4.5/linux/drivers/acpi/parser/Makefile Fri Dec 29 14:07:21 2000 +++ linux/drivers/acpi/parser/Makefile Wed Jun 20 17:47:40 2001 @@ -1,16 +1,12 @@ # # Makefile for all Linux ACPI interpreter subdirectories +# EXCEPT for the ospm directory # -O_TARGET := ../$(shell basename `pwd`).o +O_TARGET := $(notdir $(CURDIR)).o obj-$(CONFIG_ACPI) := $(patsubst %.c,%.o,$(wildcard *.c)) -EXTRA_CFLAGS += -I../include - EXTRA_CFLAGS += $(ACPI_CFLAGS) include $(TOPDIR)/Rules.make - -clean: - $(RM) *.o diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/parser/psargs.c linux/drivers/acpi/parser/psargs.c --- v2.4.5/linux/drivers/acpi/parser/psargs.c Mon Jan 22 13:23:43 2001 +++ linux/drivers/acpi/parser/psargs.c Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: psargs - Parse AML opcode arguments - * $Revision: 43 $ + * $Revision: 47 $ * *****************************************************************************/ @@ -29,7 +29,7 @@ #include "amlcode.h" #include "acnamesp.h" -#define _COMPONENT PARSER +#define _COMPONENT ACPI_PARSER MODULE_NAME ("psargs") @@ -58,8 +58,7 @@ parser_state->aml++; - switch (encoded_length >> 6) /* bits 6-7 contain encoding scheme */ - { + switch (encoded_length >> 6) /* bits 6-7 contain encoding scheme */ { case 0: /* 1-byte encoding (bits 0-5) */ length = (encoded_length & 0x3F); @@ -158,8 +157,7 @@ /* Decode the path */ - switch (GET8 (end)) - { + switch (GET8 (end)) { case 0: /* Null_name */ @@ -244,7 +242,7 @@ if (!path || !method_call) { /* Null name case, create a null namepath object */ - acpi_ps_init_op (arg, AML_NAMEPATH_OP); + acpi_ps_init_op (arg, AML_INT_NAMEPATH_OP); arg->value.name = path; return; } @@ -272,11 +270,11 @@ count = acpi_ps_get_arg (op, 0); if (count && count->opcode == AML_BYTE_OP) { - name_op = acpi_ps_alloc_op (AML_NAMEPATH_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_METHODCALL_OP); + acpi_ps_init_op (arg, AML_INT_METHODCALL_OP); name_op->value.name = path; @@ -308,7 +306,7 @@ * pathname */ - acpi_ps_init_op (arg, AML_NAMEPATH_OP); + acpi_ps_init_op (arg, AML_INT_NAMEPATH_OP); arg->value.name = path; @@ -338,7 +336,7 @@ if (!path || !method_call) { /* Null name case, create a null namepath object */ - acpi_ps_init_op (arg, AML_NAMEPATH_OP); + acpi_ps_init_op (arg, AML_INT_NAMEPATH_OP); arg->value.name = path; return; } @@ -367,11 +365,11 @@ if (ACPI_SUCCESS (status)) { if (node->type == ACPI_TYPE_METHOD) { method_node = node; - name_op = acpi_ps_alloc_op (AML_NAMEPATH_OP); + 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_METHODCALL_OP); + acpi_ps_init_op (arg, AML_INT_METHODCALL_OP); name_op->value.name = path; @@ -404,7 +402,7 @@ * pathname. */ - acpi_ps_init_op (arg, AML_NAMEPATH_OP); + acpi_ps_init_op (arg, AML_INT_NAMEPATH_OP); arg->value.name = path; @@ -435,8 +433,7 @@ { - switch (arg_type) - { + switch (arg_type) { case ARGP_BYTEDATA: @@ -483,7 +480,7 @@ case ARGP_NAME: case ARGP_NAMESTRING: - acpi_ps_init_op (arg, AML_NAMEPATH_OP); + acpi_ps_init_op (arg, AML_INT_NAMEPATH_OP); arg->value.name = acpi_ps_get_next_namestring (parser_state); break; } @@ -508,7 +505,7 @@ acpi_ps_get_next_field ( ACPI_PARSE_STATE *parser_state) { - ACPI_PTRDIFF aml_offset = parser_state->aml - + u32 aml_offset = parser_state->aml - parser_state->aml_start; ACPI_PARSE_OBJECT *field; u16 opcode; @@ -517,25 +514,24 @@ /* determine field type */ - switch (GET8 (parser_state->aml)) - { + switch (GET8 (parser_state->aml)) { default: - opcode = AML_NAMEDFIELD_OP; + opcode = AML_INT_NAMEDFIELD_OP; break; case 0x00: - opcode = AML_RESERVEDFIELD_OP; + opcode = AML_INT_RESERVEDFIELD_OP; parser_state->aml++; break; case 0x01: - opcode = AML_ACCESSFIELD_OP; + opcode = AML_INT_ACCESSFIELD_OP; parser_state->aml++; break; } @@ -549,9 +545,8 @@ /* Decode the field type */ - switch (opcode) - { - case AML_NAMEDFIELD_OP: + switch (opcode) { + case AML_INT_NAMEDFIELD_OP: /* Get the 4-character name */ @@ -565,7 +560,7 @@ break; - case AML_RESERVEDFIELD_OP: + case AML_INT_RESERVEDFIELD_OP: /* Get the length which is encoded as a package length */ @@ -573,7 +568,7 @@ break; - case AML_ACCESSFIELD_OP: + case AML_INT_ACCESSFIELD_OP: /* Get Access_type and Access_atrib and merge into the field Op */ @@ -616,8 +611,7 @@ u32 subop; - switch (arg_type) - { + switch (arg_type) { case ARGP_BYTEDATA: case ARGP_WORDDATA: case ARGP_DWORDDATA: @@ -676,7 +670,7 @@ if (parser_state->aml < parser_state->pkg_end) { /* non-empty list */ - arg = acpi_ps_alloc_op (AML_BYTELIST_OP); + arg = acpi_ps_alloc_op (AML_INT_BYTELIST_OP); if (arg) { /* fill in bytelist data */ @@ -692,16 +686,14 @@ case ARGP_TARGET: - case ARGP_SUPERNAME: - { + case ARGP_SUPERNAME: { subop = acpi_ps_peek_opcode (parser_state); if (subop == 0 || acpi_ps_is_leading_char (subop) || - acpi_ps_is_prefix_char (subop)) - { + acpi_ps_is_prefix_char (subop)) { /* Null_name or Name_string */ - arg = acpi_ps_alloc_op (AML_NAMEPATH_OP); + arg = acpi_ps_alloc_op (AML_INT_NAMEPATH_OP); if (arg) { acpi_ps_get_next_namepath (parser_state, arg, arg_count, 0); } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/parser/psfind.c linux/drivers/acpi/parser/psfind.c --- v2.4.5/linux/drivers/acpi/parser/psfind.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/parser/psfind.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,313 @@ + +/****************************************************************************** + * + * Module Name: psfind - Parse tree search routine + * $Revision: 24 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acparser.h" +#include "amlcode.h" + +#define _COMPONENT ACPI_PARSER + MODULE_NAME ("psfind") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_get_parent + * + * PARAMETERS: Op - Get the parent of this Op + * + * RETURN: The Parent op. + * + * DESCRIPTION: Get op's parent + * + ******************************************************************************/ + +static ACPI_PARSE_OBJECT* +acpi_ps_get_parent ( + ACPI_PARSE_OBJECT *op) +{ + ACPI_PARSE_OBJECT *parent = op; + + + /* Traverse the tree upward (to root if necessary) */ + + while (parent) { + switch (parent->opcode) { + case AML_SCOPE_OP: + case AML_PACKAGE_OP: + case AML_METHOD_OP: + case AML_DEVICE_OP: + case AML_POWER_RES_OP: + case AML_THERMAL_ZONE_OP: + + return (parent->parent); + } + + parent = parent->parent; + } + + return (parent); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_find_name + * + * PARAMETERS: Scope - Scope to search + * Name - ACPI name to search for + * Opcode - Opcode to search for + * + * RETURN: Op containing the name + * + * DESCRIPTION: Find name segment from a list of acpi_ops. Searches a single + * scope, no more. + * + ******************************************************************************/ + +static ACPI_PARSE_OBJECT * +acpi_ps_find_name ( + ACPI_PARSE_OBJECT *scope, + u32 name, + u32 opcode) +{ + ACPI_PARSE_OBJECT *op; + ACPI_PARSE_OBJECT *field; + + + /* search scope level for matching name segment */ + + op = acpi_ps_get_child (scope); + + while (op) { + + if (acpi_ps_is_field_op (op->opcode)) { + /* Field, search named fields */ + + field = acpi_ps_get_child (op); + while (field) { + if (acpi_ps_is_named_op (field->opcode) && + acpi_ps_get_name (field) == name && + (!opcode || field->opcode == opcode)) { + return (field); + } + + field = field->next; + } + } + + else if (acpi_ps_is_create_field_op (op->opcode)) { + if (op->opcode == AML_CREATE_FIELD_OP) { + field = acpi_ps_get_arg (op, 3); + } + + else { + /* Create_xXXField, check name */ + + field = acpi_ps_get_arg (op, 2); + } + + if ((field) && + (field->value.string) && + (!STRNCMP (field->value.string, (char *) &name, ACPI_NAME_SIZE))) { + return (op); + } + } + + else if ((acpi_ps_is_named_op (op->opcode)) && + (acpi_ps_get_name (op) == name) && + (!opcode || op->opcode == opcode || opcode == AML_SCOPE_OP)) { + break; + } + + op = op->next; + } + + return (op); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_find + * + * PARAMETERS: Scope - Where to begin the search + * Path - ACPI Path to the named object + * Opcode - Opcode associated with the object + * Create - if TRUE, create the object if not found. + * + * RETURN: Op if found, NULL otherwise. + * + * DESCRIPTION: Find object within scope + * + ******************************************************************************/ + +ACPI_PARSE_OBJECT* +acpi_ps_find ( + ACPI_PARSE_OBJECT *scope, + NATIVE_CHAR *path, + u16 opcode, + u32 create) +{ + u32 seg_count; + u32 name; + u32 name_op; + ACPI_PARSE_OBJECT *op = NULL; + u8 unprefixed = TRUE; + + + if (!scope || !path) { + return (NULL); + } + + + acpi_gbl_ps_find_count++; + + + /* Handle all prefixes in the name path */ + + while (acpi_ps_is_prefix_char (GET8 (path))) { + switch (GET8 (path)) { + + case '\\': + + /* Could just use a global for "root scope" here */ + + while (scope->parent) { + scope = scope->parent; + } + + /* get first object within the scope */ + /* TBD: [Investigate] OR - set next in root scope to point to the same value as arg */ + + /* Scope = Scope->Value.Arg; */ + + break; + + + case '^': + + /* Go up to the next valid scoping Op (method, scope, etc.) */ + + if (acpi_ps_get_parent (scope)) { + scope = acpi_ps_get_parent (scope); + } + + break; + } + + unprefixed = FALSE; + path++; + } + + /* get name segment count */ + + switch (GET8 (path)) { + case '\0': + seg_count = 0; + + /* Null name case */ + + if (unprefixed) { + op = NULL; + } + else { + op = scope; + } + + + return (op); + break; + + case AML_DUAL_NAME_PREFIX: + seg_count = 2; + path++; + break; + + case AML_MULTI_NAME_PREFIX_OP: + seg_count = GET8 (path + 1); + path += 2; + break; + + default: + seg_count = 1; + break; + } + + /* match each name segment */ + + while (scope && seg_count) { + MOVE_UNALIGNED32_TO_32 (&name, path); + path += 4; + seg_count --; + + if (seg_count) { + name_op = 0; + } + else { + name_op = opcode; + } + + op = acpi_ps_find_name (scope, name, name_op); + + if (!op) { + if (create) { + /* Create a new Scope level */ + + if (seg_count) { + op = acpi_ps_alloc_op (AML_SCOPE_OP); + } + else { + op = acpi_ps_alloc_op (opcode); + } + + if (op) { + acpi_ps_set_name (op, name); + acpi_ps_append_arg (scope, op); + + } + } + + else if (unprefixed) { + /* Search higher scopes for unprefixed name */ + + while (!op && scope->parent) { + scope = scope->parent; + op = acpi_ps_find_name (scope, name, opcode); + + } + } + + } + + unprefixed = FALSE; + scope = op; + } + + return (op); +} + + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/parser/psopcode.c linux/drivers/acpi/parser/psopcode.c --- v2.4.5/linux/drivers/acpi/parser/psopcode.c Mon Jan 22 13:23:43 2001 +++ linux/drivers/acpi/parser/psopcode.c Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: psopcode - Parser opcode information table - * $Revision: 27 $ + * $Revision: 32 $ * *****************************************************************************/ @@ -29,7 +29,7 @@ #include "amlcode.h" -#define _COMPONENT PARSER +#define _COMPONENT ACPI_PARSER MODULE_NAME ("psopcode") @@ -130,12 +130,12 @@ #define ARGP_SIZE_OF_OP ARGP_LIST1 (ARGP_SUPERNAME) #define ARGP_INDEX_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) #define ARGP_MATCH_OP ARGP_LIST6 (ARGP_TERMARG, ARGP_BYTEDATA, ARGP_TERMARG, ARGP_BYTEDATA, ARGP_TERMARG, ARGP_TERMARG) -#define ARGP_DWORD_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) -#define ARGP_WORD_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) -#define ARGP_BYTE_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) -#define ARGP_BIT_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) +#define ARGP_CREATE_DWORD_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) +#define ARGP_CREATE_WORD_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) +#define ARGP_CREATE_BYTE_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) +#define ARGP_CREATE_BIT_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) #define ARGP_TYPE_OP ARGP_LIST1 (ARGP_SUPERNAME) -#define ARGP_QWORD_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) +#define ARGP_CREATE_QWORD_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) #define ARGP_LAND_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG) #define ARGP_LOR_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG) #define ARGP_LNOT_OP ARGP_LIST1 (ARGP_TERMARG) @@ -178,7 +178,7 @@ #define ARGP_DEBUG_OP ARG_NONE #define ARGP_FATAL_OP ARGP_LIST3 (ARGP_BYTEDATA, ARGP_DWORDDATA, ARGP_TERMARG) #define ARGP_REGION_OP ARGP_LIST4 (ARGP_NAME, ARGP_BYTEDATA, ARGP_TERMARG, ARGP_TERMARG) -#define ARGP_DEF_FIELD_OP ARGP_LIST4 (ARGP_PKGLENGTH, ARGP_NAMESTRING, ARGP_BYTEDATA, ARGP_FIELDLIST) +#define ARGP_FIELD_OP ARGP_LIST4 (ARGP_PKGLENGTH, ARGP_NAMESTRING, ARGP_BYTEDATA, ARGP_FIELDLIST) #define ARGP_DEVICE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_OBJLIST) #define ARGP_PROCESSOR_OP ARGP_LIST6 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_BYTEDATA, ARGP_DWORDDATA, ARGP_BYTEDATA, ARGP_OBJLIST) #define ARGP_POWER_RES_OP ARGP_LIST5 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_BYTEDATA, ARGP_WORDDATA, ARGP_OBJLIST) @@ -202,7 +202,7 @@ * All AML opcodes and the runtime arguments for each. Used by the AML interpreter Each list is compressed * into a 32-bit number and stored in the master opcode table at the end of this file. * - * (Used by Acpi_aml_prep_operands procedure and the ASL Compiler) + * (Used by Prep_operands procedure and the ASL Compiler) */ #define ARGI_ZERO_OP ARG_NONE @@ -260,12 +260,12 @@ #define ARGI_SIZE_OF_OP ARGI_LIST1 (ARGI_DATAOBJECT) #define ARGI_INDEX_OP ARGI_LIST3 (ARGI_COMPLEXOBJ, ARGI_INTEGER, ARGI_TARGETREF) #define ARGI_MATCH_OP ARGI_LIST6 (ARGI_PACKAGE, ARGI_INTEGER, ARGI_INTEGER, ARGI_INTEGER, ARGI_INTEGER, ARGI_INTEGER) -#define ARGI_DWORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE) -#define ARGI_WORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE) -#define ARGI_BYTE_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE) -#define ARGI_BIT_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE) +#define ARGI_CREATE_DWORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE) +#define ARGI_CREATE_WORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE) +#define ARGI_CREATE_BYTE_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE) +#define ARGI_CREATE_BIT_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE) #define ARGI_TYPE_OP ARGI_LIST1 (ARGI_ANYTYPE) -#define ARGI_QWORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE) +#define ARGI_CREATE_QWORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE) #define ARGI_LAND_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER) #define ARGI_LOR_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER) #define ARGI_LNOT_OP ARGI_LIST1 (ARGI_INTEGER) @@ -308,7 +308,7 @@ #define ARGI_DEBUG_OP ARG_NONE #define ARGI_FATAL_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_INTEGER) #define ARGI_REGION_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER) -#define ARGI_DEF_FIELD_OP ARGI_INVALID_OPCODE +#define ARGI_FIELD_OP ARGI_INVALID_OPCODE #define ARGI_DEVICE_OP ARGI_INVALID_OPCODE #define ARGI_PROCESSOR_OP ARGI_INVALID_OPCODE #define ARGI_POWER_RES_OP ARGI_INVALID_OPCODE @@ -335,143 +335,143 @@ static ACPI_OPCODE_INFO aml_op_info[] = { -/* Index Opcode Type Class Has Arguments? Name Parser Args Interpreter Args */ +/* Index Opcode Type Class Has Arguments? Name Parser Args Interpreter Args */ -/* 00 */ /* AML_ZERO_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONSTANT| AML_NO_ARGS, "Zero", ARGP_ZERO_OP, ARGI_ZERO_OP), -/* 01 */ /* AML_ONE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONSTANT| AML_NO_ARGS, "One", ARGP_ONE_OP, ARGI_ONE_OP), -/* 02 */ /* AML_ALIAS_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Alias", ARGP_ALIAS_OP, ARGI_ALIAS_OP), -/* 03 */ /* AML_NAME_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Name", ARGP_NAME_OP, ARGI_NAME_OP), -/* 04 */ /* AML_BYTE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LITERAL| AML_NO_ARGS, "Byte_const", ARGP_BYTE_OP, ARGI_BYTE_OP), -/* 05 */ /* AML_WORD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LITERAL| AML_NO_ARGS, "Word_const", ARGP_WORD_OP, ARGI_WORD_OP), -/* 06 */ /* AML_DWORD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LITERAL| AML_NO_ARGS, "Dword_const", ARGP_DWORD_OP, ARGI_DWORD_OP), -/* 07 */ /* AML_STRING_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LITERAL| AML_NO_ARGS, "String", ARGP_STRING_OP, ARGI_STRING_OP), -/* 08 */ /* AML_SCOPE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Scope", ARGP_SCOPE_OP, ARGI_SCOPE_OP), -/* 09 */ /* AML_BUFFER_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DATA_TERM| AML_HAS_ARGS, "Buffer", ARGP_BUFFER_OP, ARGI_BUFFER_OP), -/* 0A */ /* AML_PACKAGE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DATA_TERM| AML_HAS_ARGS, "Package", ARGP_PACKAGE_OP, ARGI_PACKAGE_OP), -/* 0B */ /* AML_METHOD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Method", ARGP_METHOD_OP, ARGI_METHOD_OP), -/* 0C */ /* AML_LOCAL0 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS, "Local0", ARGP_LOCAL0, ARGI_LOCAL0), -/* 0D */ /* AML_LOCAL1 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS, "Local1", ARGP_LOCAL1, ARGI_LOCAL1), -/* 0E */ /* AML_LOCAL2 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS, "Local2", ARGP_LOCAL2, ARGI_LOCAL2), -/* 0F */ /* AML_LOCAL3 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS, "Local3", ARGP_LOCAL3, ARGI_LOCAL3), -/* 10 */ /* AML_LOCAL4 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS, "Local4", ARGP_LOCAL4, ARGI_LOCAL4), -/* 11 */ /* AML_LOCAL5 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS, "Local5", ARGP_LOCAL5, ARGI_LOCAL5), -/* 12 */ /* AML_LOCAL6 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS, "Local6", ARGP_LOCAL6, ARGI_LOCAL6), -/* 13 */ /* AML_LOCAL7 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS, "Local7", ARGP_LOCAL7, ARGI_LOCAL7), -/* 14 */ /* AML_ARG0 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_METHOD_ARGUMENT| AML_NO_ARGS, "Arg0", ARGP_ARG0, ARGI_ARG0), -/* 15 */ /* AML_ARG1 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_METHOD_ARGUMENT| AML_NO_ARGS, "Arg1", ARGP_ARG1, ARGI_ARG1), -/* 16 */ /* AML_ARG2 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_METHOD_ARGUMENT| AML_NO_ARGS, "Arg2", ARGP_ARG2, ARGI_ARG2), -/* 17 */ /* AML_ARG3 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_METHOD_ARGUMENT| AML_NO_ARGS, "Arg3", ARGP_ARG3, ARGI_ARG3), -/* 18 */ /* AML_ARG4 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_METHOD_ARGUMENT| AML_NO_ARGS, "Arg4", ARGP_ARG4, ARGI_ARG4), -/* 19 */ /* AML_ARG5 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_METHOD_ARGUMENT| AML_NO_ARGS, "Arg5", ARGP_ARG5, ARGI_ARG5), -/* 1_a */ /* AML_ARG6 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_METHOD_ARGUMENT| AML_NO_ARGS, "Arg6", ARGP_ARG6, ARGI_ARG6), -/* 1_b */ /* AML_STORE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Store", ARGP_STORE_OP, ARGI_STORE_OP), -/* 1_c */ /* AML_REF_OF_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2| AML_HAS_ARGS, "Ref_of", ARGP_REF_OF_OP, ARGI_REF_OF_OP), -/* 1_d */ /* AML_ADD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Add", ARGP_ADD_OP, ARGI_ADD_OP), -/* 1_e */ /* AML_CONCAT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Concatenate", ARGP_CONCAT_OP, ARGI_CONCAT_OP), -/* 1_f */ /* AML_SUBTRACT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Subtract", ARGP_SUBTRACT_OP, ARGI_SUBTRACT_OP), -/* 20 */ /* AML_INCREMENT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2| AML_HAS_ARGS, "Increment", ARGP_INCREMENT_OP, ARGI_INCREMENT_OP), -/* 21 */ /* AML_DECREMENT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2| AML_HAS_ARGS, "Decrement", ARGP_DECREMENT_OP, ARGI_DECREMENT_OP), -/* 22 */ /* AML_MULTIPLY_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Multiply", ARGP_MULTIPLY_OP, ARGI_MULTIPLY_OP), -/* 23 */ /* AML_DIVIDE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Divide", ARGP_DIVIDE_OP, ARGI_DIVIDE_OP), -/* 24 */ /* AML_SHIFT_LEFT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Shift_left", ARGP_SHIFT_LEFT_OP, ARGI_SHIFT_LEFT_OP), -/* 25 */ /* AML_SHIFT_RIGHT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Shift_right", ARGP_SHIFT_RIGHT_OP, ARGI_SHIFT_RIGHT_OP), -/* 26 */ /* AML_BIT_AND_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "And", ARGP_BIT_AND_OP, ARGI_BIT_AND_OP), -/* 27 */ /* AML_BIT_NAND_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "NAnd", ARGP_BIT_NAND_OP, ARGI_BIT_NAND_OP), -/* 28 */ /* AML_BIT_OR_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Or", ARGP_BIT_OR_OP, ARGI_BIT_OR_OP), -/* 29 */ /* AML_BIT_NOR_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "NOr", ARGP_BIT_NOR_OP, ARGI_BIT_NOR_OP), -/* 2_a */ /* AML_BIT_XOR_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "XOr", ARGP_BIT_XOR_OP, ARGI_BIT_XOR_OP), -/* 2_b */ /* AML_BIT_NOT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Not", ARGP_BIT_NOT_OP, ARGI_BIT_NOT_OP), +/* 00 */ /* AML_ZERO_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONSTANT| AML_NO_ARGS, "Zero", ARGP_ZERO_OP, ARGI_ZERO_OP), +/* 01 */ /* AML_ONE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONSTANT| AML_NO_ARGS, "One", ARGP_ONE_OP, ARGI_ONE_OP), +/* 02 */ /* AML_ALIAS_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Alias", ARGP_ALIAS_OP, ARGI_ALIAS_OP), +/* 03 */ /* AML_NAME_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Name", ARGP_NAME_OP, ARGI_NAME_OP), +/* 04 */ /* AML_BYTE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LITERAL| AML_NO_ARGS, "Byte_const", ARGP_BYTE_OP, ARGI_BYTE_OP), +/* 05 */ /* AML_WORD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LITERAL| AML_NO_ARGS, "Word_const", ARGP_WORD_OP, ARGI_WORD_OP), +/* 06 */ /* AML_DWORD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LITERAL| AML_NO_ARGS, "Dword_const", ARGP_DWORD_OP, ARGI_DWORD_OP), +/* 07 */ /* AML_STRING_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LITERAL| AML_NO_ARGS, "String", ARGP_STRING_OP, ARGI_STRING_OP), +/* 08 */ /* AML_SCOPE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Scope", ARGP_SCOPE_OP, ARGI_SCOPE_OP), +/* 09 */ /* AML_BUFFER_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DATA_TERM| AML_HAS_ARGS, "Buffer", ARGP_BUFFER_OP, ARGI_BUFFER_OP), +/* 0A */ /* AML_PACKAGE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DATA_TERM| AML_HAS_ARGS, "Package", ARGP_PACKAGE_OP, ARGI_PACKAGE_OP), +/* 0B */ /* AML_METHOD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Method", ARGP_METHOD_OP, ARGI_METHOD_OP), +/* 0C */ /* AML_LOCAL0 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS, "Local0", ARGP_LOCAL0, ARGI_LOCAL0), +/* 0D */ /* AML_LOCAL1 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS, "Local1", ARGP_LOCAL1, ARGI_LOCAL1), +/* 0E */ /* AML_LOCAL2 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS, "Local2", ARGP_LOCAL2, ARGI_LOCAL2), +/* 0F */ /* AML_LOCAL3 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS, "Local3", ARGP_LOCAL3, ARGI_LOCAL3), +/* 10 */ /* AML_LOCAL4 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS, "Local4", ARGP_LOCAL4, ARGI_LOCAL4), +/* 11 */ /* AML_LOCAL5 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS, "Local5", ARGP_LOCAL5, ARGI_LOCAL5), +/* 12 */ /* AML_LOCAL6 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS, "Local6", ARGP_LOCAL6, ARGI_LOCAL6), +/* 13 */ /* AML_LOCAL7 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS, "Local7", ARGP_LOCAL7, ARGI_LOCAL7), +/* 14 */ /* AML_ARG0 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_METHOD_ARGUMENT| AML_NO_ARGS, "Arg0", ARGP_ARG0, ARGI_ARG0), +/* 15 */ /* AML_ARG1 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_METHOD_ARGUMENT| AML_NO_ARGS, "Arg1", ARGP_ARG1, ARGI_ARG1), +/* 16 */ /* AML_ARG2 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_METHOD_ARGUMENT| AML_NO_ARGS, "Arg2", ARGP_ARG2, ARGI_ARG2), +/* 17 */ /* AML_ARG3 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_METHOD_ARGUMENT| AML_NO_ARGS, "Arg3", ARGP_ARG3, ARGI_ARG3), +/* 18 */ /* AML_ARG4 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_METHOD_ARGUMENT| AML_NO_ARGS, "Arg4", ARGP_ARG4, ARGI_ARG4), +/* 19 */ /* AML_ARG5 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_METHOD_ARGUMENT| AML_NO_ARGS, "Arg5", ARGP_ARG5, ARGI_ARG5), +/* 1_a */ /* AML_ARG6 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_METHOD_ARGUMENT| AML_NO_ARGS, "Arg6", ARGP_ARG6, ARGI_ARG6), +/* 1_b */ /* AML_STORE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Store", ARGP_STORE_OP, ARGI_STORE_OP), +/* 1_c */ /* AML_REF_OF_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2| AML_HAS_ARGS, "Ref_of", ARGP_REF_OF_OP, ARGI_REF_OF_OP), +/* 1_d */ /* AML_ADD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Add", ARGP_ADD_OP, ARGI_ADD_OP), +/* 1_e */ /* AML_CONCAT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Concatenate", ARGP_CONCAT_OP, ARGI_CONCAT_OP), +/* 1_f */ /* AML_SUBTRACT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Subtract", ARGP_SUBTRACT_OP, ARGI_SUBTRACT_OP), +/* 20 */ /* AML_INCREMENT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2| AML_HAS_ARGS, "Increment", ARGP_INCREMENT_OP, ARGI_INCREMENT_OP), +/* 21 */ /* AML_DECREMENT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2| AML_HAS_ARGS, "Decrement", ARGP_DECREMENT_OP, ARGI_DECREMENT_OP), +/* 22 */ /* AML_MULTIPLY_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Multiply", ARGP_MULTIPLY_OP, ARGI_MULTIPLY_OP), +/* 23 */ /* AML_DIVIDE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Divide", ARGP_DIVIDE_OP, ARGI_DIVIDE_OP), +/* 24 */ /* AML_SHIFT_LEFT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Shift_left", ARGP_SHIFT_LEFT_OP, ARGI_SHIFT_LEFT_OP), +/* 25 */ /* AML_SHIFT_RIGHT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Shift_right", ARGP_SHIFT_RIGHT_OP, ARGI_SHIFT_RIGHT_OP), +/* 26 */ /* AML_BIT_AND_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "And", ARGP_BIT_AND_OP, ARGI_BIT_AND_OP), +/* 27 */ /* AML_BIT_NAND_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "NAnd", ARGP_BIT_NAND_OP, ARGI_BIT_NAND_OP), +/* 28 */ /* AML_BIT_OR_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Or", ARGP_BIT_OR_OP, ARGI_BIT_OR_OP), +/* 29 */ /* AML_BIT_NOR_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "NOr", ARGP_BIT_NOR_OP, ARGI_BIT_NOR_OP), +/* 2_a */ /* AML_BIT_XOR_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "XOr", ARGP_BIT_XOR_OP, ARGI_BIT_XOR_OP), +/* 2_b */ /* AML_BIT_NOT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Not", ARGP_BIT_NOT_OP, ARGI_BIT_NOT_OP), /* 2_c */ /* AML_FIND_SET_LEFT_BIT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Find_set_left_bit", ARGP_FIND_SET_LEFT_BIT_OP, ARGI_FIND_SET_LEFT_BIT_OP), -/* 2_d */ /* AML_FIND_SET_RIGHT_BIT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Find_set_right_bit", ARGP_FIND_SET_RIGHT_BIT_OP, ARGI_FIND_SET_RIGHT_BIT_OP), -/* 2_e */ /* AML_DEREF_OF_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2| AML_HAS_ARGS, "Deref_of", ARGP_DEREF_OF_OP, ARGI_DEREF_OF_OP), -/* 2_f */ /* AML_NOTIFY_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC1| AML_HAS_ARGS, "Notify", ARGP_NOTIFY_OP, ARGI_NOTIFY_OP), -/* 30 */ /* AML_SIZE_OF_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2| AML_HAS_ARGS, "Size_of", ARGP_SIZE_OF_OP, ARGI_SIZE_OF_OP), -/* 31 */ /* AML_INDEX_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_INDEX| AML_HAS_ARGS, "Index", ARGP_INDEX_OP, ARGI_INDEX_OP), -/* 32 */ /* AML_MATCH_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MATCH| AML_HAS_ARGS, "Match", ARGP_MATCH_OP, ARGI_MATCH_OP), -/* 33 */ /* AML_DWORD_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CREATE_FIELD| AML_HAS_ARGS, "Create_dWord_field", ARGP_DWORD_FIELD_OP, ARGI_DWORD_FIELD_OP), -/* 34 */ /* AML_WORD_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CREATE_FIELD| AML_HAS_ARGS, "Create_word_field", ARGP_WORD_FIELD_OP, ARGI_WORD_FIELD_OP), -/* 35 */ /* AML_BYTE_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CREATE_FIELD| AML_HAS_ARGS, "Create_byte_field", ARGP_BYTE_FIELD_OP, ARGI_BYTE_FIELD_OP), -/* 36 */ /* AML_BIT_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CREATE_FIELD| AML_HAS_ARGS, "Create_bit_field", ARGP_BIT_FIELD_OP, ARGI_BIT_FIELD_OP), -/* 37 */ /* AML_TYPE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2| AML_HAS_ARGS, "Object_type", ARGP_TYPE_OP, ARGI_TYPE_OP), -/* 38 */ /* AML_LAND_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2| AML_HAS_ARGS, "LAnd", ARGP_LAND_OP, ARGI_LAND_OP), -/* 39 */ /* AML_LOR_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2| AML_HAS_ARGS, "LOr", ARGP_LOR_OP, ARGI_LOR_OP), -/* 3_a */ /* AML_LNOT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2| AML_HAS_ARGS, "LNot", ARGP_LNOT_OP, ARGI_LNOT_OP), -/* 3_b */ /* AML_LEQUAL_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2| AML_HAS_ARGS, "LEqual", ARGP_LEQUAL_OP, ARGI_LEQUAL_OP), -/* 3_c */ /* AML_LGREATER_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2| AML_HAS_ARGS, "LGreater", ARGP_LGREATER_OP, ARGI_LGREATER_OP), -/* 3_d */ /* AML_LLESS_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2| AML_HAS_ARGS, "LLess", ARGP_LLESS_OP, ARGI_LLESS_OP), -/* 3_e */ /* AML_IF_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL| AML_HAS_ARGS, "If", ARGP_IF_OP, ARGI_IF_OP), -/* 3_f */ /* AML_ELSE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL| AML_HAS_ARGS, "Else", ARGP_ELSE_OP, ARGI_ELSE_OP), -/* 40 */ /* AML_WHILE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL| AML_HAS_ARGS, "While", ARGP_WHILE_OP, ARGI_WHILE_OP), -/* 41 */ /* AML_NOOP_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL| AML_NO_ARGS, "Noop", ARGP_NOOP_OP, ARGI_NOOP_OP), -/* 42 */ /* AML_RETURN_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL| AML_HAS_ARGS, "Return", ARGP_RETURN_OP, ARGI_RETURN_OP), -/* 43 */ /* AML_BREAK_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL| AML_NO_ARGS, "Break", ARGP_BREAK_OP, ARGI_BREAK_OP), -/* 44 */ /* AML_BREAK_POINT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL| AML_NO_ARGS, "Break_point", ARGP_BREAK_POINT_OP, ARGI_BREAK_POINT_OP), -/* 45 */ /* AML_ONES_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONSTANT| AML_NO_ARGS, "Ones", ARGP_ONES_OP, ARGI_ONES_OP), +/* 2_d */ /* AML_FIND_SET_RIGHT_BIT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Find_set_right_bit", ARGP_FIND_SET_RIGHT_BIT_OP,ARGI_FIND_SET_RIGHT_BIT_OP), +/* 2_e */ /* AML_DEREF_OF_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2| AML_HAS_ARGS, "Deref_of", ARGP_DEREF_OF_OP, ARGI_DEREF_OF_OP), +/* 2_f */ /* AML_NOTIFY_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC1| AML_HAS_ARGS, "Notify", ARGP_NOTIFY_OP, ARGI_NOTIFY_OP), +/* 30 */ /* AML_SIZE_OF_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2| AML_HAS_ARGS, "Size_of", ARGP_SIZE_OF_OP, ARGI_SIZE_OF_OP), +/* 31 */ /* AML_INDEX_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_INDEX| AML_HAS_ARGS, "Index", ARGP_INDEX_OP, ARGI_INDEX_OP), +/* 32 */ /* AML_MATCH_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MATCH| AML_HAS_ARGS, "Match", ARGP_MATCH_OP, ARGI_MATCH_OP), +/* 33 */ /* AML_CREATE_DWORD_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CREATE_FIELD| AML_HAS_ARGS, "Create_dWord_field", ARGP_CREATE_DWORD_FIELD_OP,ARGI_CREATE_DWORD_FIELD_OP), +/* 34 */ /* AML_CREATE_WORD_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CREATE_FIELD| AML_HAS_ARGS, "Create_word_field", ARGP_CREATE_WORD_FIELD_OP, ARGI_CREATE_WORD_FIELD_OP), +/* 35 */ /* AML_CREATE_BYTE_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CREATE_FIELD| AML_HAS_ARGS, "Create_byte_field", ARGP_CREATE_BYTE_FIELD_OP, ARGI_CREATE_BYTE_FIELD_OP), +/* 36 */ /* AML_CREATE_BIT_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CREATE_FIELD| AML_HAS_ARGS, "Create_bit_field", ARGP_CREATE_BIT_FIELD_OP, ARGI_CREATE_BIT_FIELD_OP), +/* 37 */ /* AML_TYPE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2| AML_HAS_ARGS, "Object_type", ARGP_TYPE_OP, ARGI_TYPE_OP), +/* 38 */ /* AML_LAND_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2| AML_HAS_ARGS, "LAnd", ARGP_LAND_OP, ARGI_LAND_OP), +/* 39 */ /* AML_LOR_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2| AML_HAS_ARGS, "LOr", ARGP_LOR_OP, ARGI_LOR_OP), +/* 3_a */ /* AML_LNOT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2| AML_HAS_ARGS, "LNot", ARGP_LNOT_OP, ARGI_LNOT_OP), +/* 3_b */ /* AML_LEQUAL_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2| AML_HAS_ARGS, "LEqual", ARGP_LEQUAL_OP, ARGI_LEQUAL_OP), +/* 3_c */ /* AML_LGREATER_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2| AML_HAS_ARGS, "LGreater", ARGP_LGREATER_OP, ARGI_LGREATER_OP), +/* 3_d */ /* AML_LLESS_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2| AML_HAS_ARGS, "LLess", ARGP_LLESS_OP, ARGI_LLESS_OP), +/* 3_e */ /* AML_IF_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL| AML_HAS_ARGS, "If", ARGP_IF_OP, ARGI_IF_OP), +/* 3_f */ /* AML_ELSE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL| AML_HAS_ARGS, "Else", ARGP_ELSE_OP, ARGI_ELSE_OP), +/* 40 */ /* AML_WHILE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL| AML_HAS_ARGS, "While", ARGP_WHILE_OP, ARGI_WHILE_OP), +/* 41 */ /* AML_NOOP_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL| AML_NO_ARGS, "Noop", ARGP_NOOP_OP, ARGI_NOOP_OP), +/* 42 */ /* AML_RETURN_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL| AML_HAS_ARGS, "Return", ARGP_RETURN_OP, ARGI_RETURN_OP), +/* 43 */ /* AML_BREAK_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL| AML_NO_ARGS, "Break", ARGP_BREAK_OP, ARGI_BREAK_OP), +/* 44 */ /* AML_BREAK_POINT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL| AML_NO_ARGS, "Break_point", ARGP_BREAK_POINT_OP, ARGI_BREAK_POINT_OP), +/* 45 */ /* AML_ONES_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONSTANT| AML_NO_ARGS, "Ones", ARGP_ONES_OP, ARGI_ONES_OP), /* Prefixed opcodes (Two-byte opcodes with a prefix op) */ -/* 46 */ /* AML_MUTEX_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Mutex", ARGP_MUTEX_OP, ARGI_MUTEX_OP), -/* 47 */ /* AML_EVENT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_NO_ARGS, "Event", ARGP_EVENT_OP, ARGI_EVENT_OP), -/* 48 */ /* AML_COND_REF_OF_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Cond_ref_of", ARGP_COND_REF_OF_OP, ARGI_COND_REF_OF_OP), -/* 49 */ /* AML_CREATE_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CREATE_FIELD| AML_HAS_ARGS, "Create_field", ARGP_CREATE_FIELD_OP, ARGI_CREATE_FIELD_OP), -/* 4_a */ /* AML_LOAD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_RECONFIGURATION| AML_HAS_ARGS, "Load", ARGP_LOAD_OP, ARGI_LOAD_OP), -/* 4_b */ /* AML_STALL_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC1| AML_HAS_ARGS, "Stall", ARGP_STALL_OP, ARGI_STALL_OP), -/* 4_c */ /* AML_SLEEP_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC1| AML_HAS_ARGS, "Sleep", ARGP_SLEEP_OP, ARGI_SLEEP_OP), -/* 4_d */ /* AML_ACQUIRE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_s| AML_HAS_ARGS, "Acquire", ARGP_ACQUIRE_OP, ARGI_ACQUIRE_OP), -/* 4_e */ /* AML_SIGNAL_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC1| AML_HAS_ARGS, "Signal", ARGP_SIGNAL_OP, ARGI_SIGNAL_OP), -/* 4_f */ /* AML_WAIT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_s| AML_HAS_ARGS, "Wait", ARGP_WAIT_OP, ARGI_WAIT_OP), -/* 50 */ /* AML_RESET_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC1| AML_HAS_ARGS, "Reset", ARGP_RESET_OP, ARGI_RESET_OP), -/* 51 */ /* AML_RELEASE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC1| AML_HAS_ARGS, "Release", ARGP_RELEASE_OP, ARGI_RELEASE_OP), -/* 52 */ /* AML_FROM_BCD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "From_bCD", ARGP_FROM_BCD_OP, ARGI_FROM_BCD_OP), -/* 53 */ /* AML_TO_BCD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "To_bCD", ARGP_TO_BCD_OP, ARGI_TO_BCD_OP), -/* 54 */ /* AML_UNLOAD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_RECONFIGURATION| AML_HAS_ARGS, "Unload", ARGP_UNLOAD_OP, ARGI_UNLOAD_OP), -/* 55 */ /* AML_REVISION_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONSTANT| AML_NO_ARGS, "Revision", ARGP_REVISION_OP, ARGI_REVISION_OP), -/* 56 */ /* AML_DEBUG_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONSTANT| AML_NO_ARGS, "Debug", ARGP_DEBUG_OP, ARGI_DEBUG_OP), -/* 57 */ /* AML_FATAL_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_FATAL| AML_HAS_ARGS, "Fatal", ARGP_FATAL_OP, ARGI_FATAL_OP), -/* 58 */ /* AML_REGION_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Op_region", ARGP_REGION_OP, ARGI_REGION_OP), -/* 59 */ /* AML_DEF_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Field", ARGP_DEF_FIELD_OP, ARGI_DEF_FIELD_OP), -/* 5_a */ /* AML_DEVICE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Device", ARGP_DEVICE_OP, ARGI_DEVICE_OP), -/* 5_b */ /* AML_PROCESSOR_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Processor", ARGP_PROCESSOR_OP, ARGI_PROCESSOR_OP), -/* 5_c */ /* AML_POWER_RES_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Power_resource", ARGP_POWER_RES_OP, ARGI_POWER_RES_OP), -/* 5_d */ /* AML_THERMAL_ZONE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Thermal_zone", ARGP_THERMAL_ZONE_OP, ARGI_THERMAL_ZONE_OP), -/* 5_e */ /* AML_INDEX_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Index_field", ARGP_INDEX_FIELD_OP, ARGI_INDEX_FIELD_OP), -/* 5_f */ /* AML_BANK_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Bank_field", ARGP_BANK_FIELD_OP, ARGI_BANK_FIELD_OP), +/* 46 */ /* AML_MUTEX_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Mutex", ARGP_MUTEX_OP, ARGI_MUTEX_OP), +/* 47 */ /* AML_EVENT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_NO_ARGS, "Event", ARGP_EVENT_OP, ARGI_EVENT_OP), +/* 48 */ /* AML_COND_REF_OF_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Cond_ref_of", ARGP_COND_REF_OF_OP, ARGI_COND_REF_OF_OP), +/* 49 */ /* AML_CREATE_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CREATE_FIELD| AML_HAS_ARGS, "Create_field", ARGP_CREATE_FIELD_OP, ARGI_CREATE_FIELD_OP), +/* 4_a */ /* AML_LOAD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_RECONFIGURATION| AML_HAS_ARGS, "Load", ARGP_LOAD_OP, ARGI_LOAD_OP), +/* 4_b */ /* AML_STALL_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC1| AML_HAS_ARGS, "Stall", ARGP_STALL_OP, ARGI_STALL_OP), +/* 4_c */ /* AML_SLEEP_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC1| AML_HAS_ARGS, "Sleep", ARGP_SLEEP_OP, ARGI_SLEEP_OP), +/* 4_d */ /* AML_ACQUIRE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_s| AML_HAS_ARGS, "Acquire", ARGP_ACQUIRE_OP, ARGI_ACQUIRE_OP), +/* 4_e */ /* AML_SIGNAL_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC1| AML_HAS_ARGS, "Signal", ARGP_SIGNAL_OP, ARGI_SIGNAL_OP), +/* 4_f */ /* AML_WAIT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_s| AML_HAS_ARGS, "Wait", ARGP_WAIT_OP, ARGI_WAIT_OP), +/* 50 */ /* AML_RESET_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC1| AML_HAS_ARGS, "Reset", ARGP_RESET_OP, ARGI_RESET_OP), +/* 51 */ /* AML_RELEASE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC1| AML_HAS_ARGS, "Release", ARGP_RELEASE_OP, ARGI_RELEASE_OP), +/* 52 */ /* AML_FROM_BCD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "From_bCD", ARGP_FROM_BCD_OP, ARGI_FROM_BCD_OP), +/* 53 */ /* AML_TO_BCD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "To_bCD", ARGP_TO_BCD_OP, ARGI_TO_BCD_OP), +/* 54 */ /* AML_UNLOAD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_RECONFIGURATION| AML_HAS_ARGS, "Unload", ARGP_UNLOAD_OP, ARGI_UNLOAD_OP), +/* 55 */ /* AML_REVISION_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONSTANT| AML_NO_ARGS, "Revision", ARGP_REVISION_OP, ARGI_REVISION_OP), +/* 56 */ /* AML_DEBUG_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONSTANT| AML_NO_ARGS, "Debug", ARGP_DEBUG_OP, ARGI_DEBUG_OP), +/* 57 */ /* AML_FATAL_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_FATAL| AML_HAS_ARGS, "Fatal", ARGP_FATAL_OP, ARGI_FATAL_OP), +/* 58 */ /* AML_REGION_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Op_region", ARGP_REGION_OP, ARGI_REGION_OP), +/* 59 */ /* AML_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Field", ARGP_FIELD_OP, ARGI_FIELD_OP), +/* 5_a */ /* AML_DEVICE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Device", ARGP_DEVICE_OP, ARGI_DEVICE_OP), +/* 5_b */ /* AML_PROCESSOR_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Processor", ARGP_PROCESSOR_OP, ARGI_PROCESSOR_OP), +/* 5_c */ /* AML_POWER_RES_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Power_resource", ARGP_POWER_RES_OP, ARGI_POWER_RES_OP), +/* 5_d */ /* AML_THERMAL_ZONE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Thermal_zone", ARGP_THERMAL_ZONE_OP, ARGI_THERMAL_ZONE_OP), +/* 5_e */ /* AML_INDEX_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Index_field", ARGP_INDEX_FIELD_OP, ARGI_INDEX_FIELD_OP), +/* 5_f */ /* AML_BANK_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Bank_field", ARGP_BANK_FIELD_OP, ARGI_BANK_FIELD_OP), /* Internal opcodes that map to invalid AML opcodes */ -/* 60 */ /* AML_LNOTEQUAL_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_BOGUS| AML_HAS_ARGS, "LNot_equal", ARGP_LNOTEQUAL_OP, ARGI_LNOTEQUAL_OP), -/* 61 */ /* AML_LLESSEQUAL_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_BOGUS| AML_HAS_ARGS, "LLess_equal", ARGP_LLESSEQUAL_OP, ARGI_LLESSEQUAL_OP), -/* 62 */ /* AML_LGREATEREQUAL_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_BOGUS| AML_HAS_ARGS, "LGreater_equal", ARGP_LGREATEREQUAL_OP, ARGI_LGREATEREQUAL_OP), -/* 63 */ /* AML_NAMEPATH_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LITERAL| AML_NO_ARGS, "Name_path", ARGP_NAMEPATH_OP, ARGI_NAMEPATH_OP), -/* 64 */ /* AML_METHODCALL_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_METHOD_CALL| AML_HAS_ARGS, "Method_call", ARGP_METHODCALL_OP, ARGI_METHODCALL_OP), -/* 65 */ /* AML_BYTELIST_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LITERAL| AML_NO_ARGS, "Byte_list", ARGP_BYTELIST_OP, ARGI_BYTELIST_OP), -/* 66 */ /* AML_RESERVEDFIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_BOGUS| AML_NO_ARGS, "Reserved_field", ARGP_RESERVEDFIELD_OP, ARGI_RESERVEDFIELD_OP), -/* 67 */ /* AML_NAMEDFIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_BOGUS| AML_NO_ARGS, "Named_field", ARGP_NAMEDFIELD_OP, ARGI_NAMEDFIELD_OP), -/* 68 */ /* AML_ACCESSFIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_BOGUS| AML_NO_ARGS, "Access_field", ARGP_ACCESSFIELD_OP, ARGI_ACCESSFIELD_OP), -/* 69 */ /* AML_STATICSTRING_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_BOGUS| AML_NO_ARGS, "Static_string", ARGP_STATICSTRING_OP, ARGI_STATICSTRING_OP), -/* 6_a */ /* AML_RETURN_VALUE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_RETURN| AML_HAS_ARGS, "[Return Value]", ARG_NONE, ARG_NONE), -/* 6_b */ /* UNKNOWN OPCODES */ OP_INFO_ENTRY (ACPI_OP_TYPE_UNKNOWN | OPTYPE_BOGUS| AML_HAS_ARGS, "UNKNOWN_OP!", ARG_NONE, ARG_NONE), -/* 6_c */ /* ASCII CHARACTERS */ OP_INFO_ENTRY (ACPI_OP_TYPE_ASCII | OPTYPE_BOGUS| AML_HAS_ARGS, "ASCII_ONLY!", ARG_NONE, ARG_NONE), -/* 6_d */ /* PREFIX CHARACTERS */ OP_INFO_ENTRY (ACPI_OP_TYPE_PREFIX | OPTYPE_BOGUS| AML_HAS_ARGS, "PREFIX_ONLY!", ARG_NONE, ARG_NONE), +/* 60 */ /* AML_LNOTEQUAL_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_BOGUS| AML_HAS_ARGS, "LNot_equal", ARGP_LNOTEQUAL_OP, ARGI_LNOTEQUAL_OP), +/* 61 */ /* AML_LLESSEQUAL_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_BOGUS| AML_HAS_ARGS, "LLess_equal", ARGP_LLESSEQUAL_OP, ARGI_LLESSEQUAL_OP), +/* 62 */ /* AML_LGREATEREQUAL_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_BOGUS| AML_HAS_ARGS, "LGreater_equal", ARGP_LGREATEREQUAL_OP, ARGI_LGREATEREQUAL_OP), +/* 63 */ /* AML_INT_NAMEPATH_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LITERAL| AML_NO_ARGS, "Name_path", ARGP_NAMEPATH_OP, ARGI_NAMEPATH_OP), +/* 64 */ /* AML_INT_METHODCALL_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_METHOD_CALL| AML_HAS_ARGS, "Method_call", ARGP_METHODCALL_OP, ARGI_METHODCALL_OP), +/* 65 */ /* AML_INT_BYTELIST_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LITERAL| AML_NO_ARGS, "Byte_list", ARGP_BYTELIST_OP, ARGI_BYTELIST_OP), +/* 66 */ /* AML_INT_RESERVEDFIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_BOGUS| AML_NO_ARGS, "Reserved_field", ARGP_RESERVEDFIELD_OP, ARGI_RESERVEDFIELD_OP), +/* 67 */ /* AML_INT_NAMEDFIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_BOGUS| AML_NO_ARGS, "Named_field", ARGP_NAMEDFIELD_OP, ARGI_NAMEDFIELD_OP), +/* 68 */ /* AML_INT_ACCESSFIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_BOGUS| AML_NO_ARGS, "Access_field", ARGP_ACCESSFIELD_OP, ARGI_ACCESSFIELD_OP), +/* 69 */ /* AML_INT_STATICSTRING_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_BOGUS| AML_NO_ARGS, "Static_string", ARGP_STATICSTRING_OP, ARGI_STATICSTRING_OP), +/* 6_a */ /* AML_INT_RETURN_VALUE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_RETURN| AML_HAS_ARGS, "[Return Value]", ARG_NONE, ARG_NONE), +/* 6_b */ /* UNKNOWN OPCODES */ OP_INFO_ENTRY (ACPI_OP_TYPE_UNKNOWN | OPTYPE_BOGUS| AML_HAS_ARGS, "UNKNOWN_OP!", ARG_NONE, ARG_NONE), +/* 6_c */ /* ASCII CHARACTERS */ OP_INFO_ENTRY (ACPI_OP_TYPE_ASCII | OPTYPE_BOGUS| AML_HAS_ARGS, "ASCII_ONLY!", ARG_NONE, ARG_NONE), +/* 6_d */ /* PREFIX CHARACTERS */ OP_INFO_ENTRY (ACPI_OP_TYPE_PREFIX | OPTYPE_BOGUS| AML_HAS_ARGS, "PREFIX_ONLY!", ARG_NONE, ARG_NONE), /* ACPI 2.0 (new) opcodes */ -/* 6_e */ /* AML_QWORD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LITERAL| AML_NO_ARGS, "Qword_const", ARGP_QWORD_OP, ARGI_QWORD_OP), -/* 6_f */ /* AML_VAR_PACKAGE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DATA_TERM| AML_HAS_ARGS, "Var_package", ARGP_VAR_PACKAGE_OP, ARGI_VAR_PACKAGE_OP), -/* 70 */ /* AML_CONCAT_RES_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Concat_res", ARGP_CONCAT_RES_OP, ARGI_CONCAT_RES_OP), -/* 71 */ /* AML_MOD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Mod", ARGP_MOD_OP, ARGI_MOD_OP), -/* 72 */ /* AML_QWORD_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CREATE_FIELD| AML_HAS_ARGS, "Create_qWord_field", ARGP_QWORD_FIELD_OP, ARGI_QWORD_FIELD_OP), -/* 73 */ /* AML_TO_BUFFER_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "To_buffer", ARGP_TO_BUFFER_OP, ARGI_TO_BUFFER_OP), -/* 74 */ /* AML_TO_DEC_STR_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "To_dec_string", ARGP_TO_DEC_STR_OP, ARGI_TO_DEC_STR_OP), -/* 75 */ /* AML_TO_HEX_STR_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "To_hex_string", ARGP_TO_HEX_STR_OP, ARGI_TO_HEX_STR_OP), -/* 76 */ /* AML_TO_INTEGER_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "To_integer", ARGP_TO_INTEGER_OP, ARGI_TO_INTEGER_OP), -/* 77 */ /* AML_TO_STRING_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "To_string", ARGP_TO_STRING_OP, ARGI_TO_STRING_OP), -/* 78 */ /* AML_COPY_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Copy", ARGP_COPY_OP, ARGI_COPY_OP), -/* 79 */ /* AML_MID_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Mid", ARGP_MID_OP, ARGI_MID_OP), -/* 7_a */ /* AML_CONTINUE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL| AML_NO_ARGS, "Continue", ARGP_CONTINUE_OP, ARGI_CONTINUE_OP), -/* 7_b */ /* AML_LOAD_TABLE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Load_table", ARGP_LOAD_TABLE_OP, ARGI_LOAD_TABLE_OP), -/* 7_c */ /* AML_DATA_REGION_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Data_op_region", ARGP_DATA_REGION_OP, ARGI_DATA_REGION_OP), +/* 6_e */ /* AML_QWORD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LITERAL| AML_NO_ARGS, "Qword_const", ARGP_QWORD_OP, ARGI_QWORD_OP), +/* 6_f */ /* AML_VAR_PACKAGE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DATA_TERM| AML_HAS_ARGS, "Var_package", ARGP_VAR_PACKAGE_OP, ARGI_VAR_PACKAGE_OP), +/* 70 */ /* AML_CONCAT_RES_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Concat_res", ARGP_CONCAT_RES_OP, ARGI_CONCAT_RES_OP), +/* 71 */ /* AML_MOD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Mod", ARGP_MOD_OP, ARGI_MOD_OP), +/* 72 */ /* AML_CREATE_QWORD_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CREATE_FIELD| AML_HAS_ARGS, "Create_qWord_field", ARGP_CREATE_QWORD_FIELD_OP,ARGI_CREATE_QWORD_FIELD_OP), +/* 73 */ /* AML_TO_BUFFER_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "To_buffer", ARGP_TO_BUFFER_OP, ARGI_TO_BUFFER_OP), +/* 74 */ /* AML_TO_DEC_STR_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "To_dec_string", ARGP_TO_DEC_STR_OP, ARGI_TO_DEC_STR_OP), +/* 75 */ /* AML_TO_HEX_STR_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "To_hex_string", ARGP_TO_HEX_STR_OP, ARGI_TO_HEX_STR_OP), +/* 76 */ /* AML_TO_INTEGER_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "To_integer", ARGP_TO_INTEGER_OP, ARGI_TO_INTEGER_OP), +/* 77 */ /* AML_TO_STRING_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "To_string", ARGP_TO_STRING_OP, ARGI_TO_STRING_OP), +/* 78 */ /* AML_COPY_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Copy_object", ARGP_COPY_OP, ARGI_COPY_OP), +/* 79 */ /* AML_MID_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Mid", ARGP_MID_OP, ARGI_MID_OP), +/* 7_a */ /* AML_CONTINUE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL| AML_NO_ARGS, "Continue", ARGP_CONTINUE_OP, ARGI_CONTINUE_OP), +/* 7_b */ /* AML_LOAD_TABLE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Load_table", ARGP_LOAD_TABLE_OP, ARGI_LOAD_TABLE_OP), +/* 7_c */ /* AML_DATA_REGION_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Data_op_region", ARGP_DATA_REGION_OP, ARGI_DATA_REGION_OP), }; @@ -484,38 +484,38 @@ { /* 0 1 2 3 4 5 6 7 */ /* 8 9 A B C D E F */ -/* 0x00 */ 0x00, 0x01, _UNK, _UNK, _UNK, _UNK, 0x02, _UNK, -/* 0x08 */ 0x03, _UNK, 0x04, 0x05, 0x06, 0x07, 0x6E, _UNK, -/* 0x10 */ 0x08, 0x09, 0x0a, 0x6F, 0x0b, _UNK, _UNK, _UNK, -/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x20 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x28 */ _UNK, _UNK, _UNK, _UNK, _UNK, 0x63, _PFX, _PFX, -/* 0x30 */ 0x67, 0x66, 0x68, 0x65, 0x69, 0x64, 0x6A, _UNK, -/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x40 */ _UNK, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, -/* 0x48 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, -/* 0x50 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, -/* 0x58 */ _ASC, _ASC, _ASC, _UNK, _PFX, _UNK, _PFX, _ASC, -/* 0x60 */ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, -/* 0x68 */ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, _UNK, -/* 0x70 */ 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, -/* 0x78 */ 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, -/* 0x80 */ 0x2b, 0x2c, 0x2d, 0x2e, 0x70, 0x71, 0x2f, 0x30, -/* 0x88 */ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x72, -/* 0x90 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x73, 0x74, -/* 0x98 */ 0x75, 0x76, _UNK, _UNK, 0x77, 0x78, 0x79, 0x7A, -/* 0xA0 */ 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x60, 0x61, -/* 0xA8 */ 0x62, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xB0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xB8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xC0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xC8 */ _UNK, _UNK, _UNK, _UNK, 0x44, _UNK, _UNK, _UNK, -/* 0xD0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xD8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xE0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xE8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xF0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xF8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x45, +/* 0x00 */ 0x00, 0x01, _UNK, _UNK, _UNK, _UNK, 0x02, _UNK, +/* 0x08 */ 0x03, _UNK, 0x04, 0x05, 0x06, 0x07, 0x6E, _UNK, +/* 0x10 */ 0x08, 0x09, 0x0a, 0x6F, 0x0b, _UNK, _UNK, _UNK, +/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x20 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x28 */ _UNK, _UNK, _UNK, _UNK, _UNK, 0x63, _PFX, _PFX, +/* 0x30 */ 0x67, 0x66, 0x68, 0x65, 0x69, 0x64, 0x6A, _UNK, +/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x40 */ _UNK, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, +/* 0x48 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, +/* 0x50 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, +/* 0x58 */ _ASC, _ASC, _ASC, _UNK, _PFX, _UNK, _PFX, _ASC, +/* 0x60 */ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, +/* 0x68 */ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, _UNK, +/* 0x70 */ 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, +/* 0x78 */ 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, +/* 0x80 */ 0x2b, 0x2c, 0x2d, 0x2e, 0x70, 0x71, 0x2f, 0x30, +/* 0x88 */ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x72, +/* 0x90 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x73, 0x74, +/* 0x98 */ 0x75, 0x76, _UNK, _UNK, 0x77, 0x78, 0x79, 0x7A, +/* 0xA0 */ 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x60, 0x61, +/* 0xA8 */ 0x62, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xB0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xB8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xC0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xC8 */ _UNK, _UNK, _UNK, _UNK, 0x44, _UNK, _UNK, _UNK, +/* 0xD0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xD8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xE0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xE8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xF0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xF8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x45, }; @@ -523,24 +523,24 @@ { /* 0 1 2 3 4 5 6 7 */ /* 8 9 A B C D E F */ -/* 0x00 */ _UNK, 0x46, 0x47, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x08 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x10 */ _UNK, _UNK, 0x48, 0x49, _UNK, _UNK, _UNK, _UNK, -/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x7B, -/* 0x20 */ 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, -/* 0x28 */ 0x52, 0x53, 0x54, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x30 */ 0x55, 0x56, 0x57, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x40 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x48 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x50 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x58 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x60 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x68 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x70 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x78 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x80 */ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, -/* 0x88 */ 0x7C, +/* 0x00 */ _UNK, 0x46, 0x47, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x08 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x10 */ _UNK, _UNK, 0x48, 0x49, _UNK, _UNK, _UNK, _UNK, +/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x7B, +/* 0x20 */ 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, +/* 0x28 */ 0x52, 0x53, 0x54, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x30 */ 0x55, 0x56, 0x57, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x40 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x48 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x50 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x58 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x60 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x68 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x70 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x78 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x80 */ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, +/* 0x88 */ 0x7C, }; @@ -567,6 +567,9 @@ u8 lower_opcode; + PROC_NAME ("Ps_get_opcode_info"); + + /* Split the 16-bit opcode into separate bytes */ upper_opcode = (u8) (opcode >> 8); @@ -581,8 +584,7 @@ * Detect normal 8-bit opcode or extended 16-bit opcode */ - switch (upper_opcode) - { + switch (upper_opcode) { case 0: /* Simple (8-bit) opcode: 0-255, can't index beyond table */ diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/parser/psparse.c linux/drivers/acpi/parser/psparse.c --- v2.4.5/linux/drivers/acpi/parser/psparse.c Mon Jan 29 10:15:59 2001 +++ linux/drivers/acpi/parser/psparse.c Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: psparse - Parser top level AML parse routines - * $Revision: 74 $ + * $Revision: 85 $ * *****************************************************************************/ @@ -39,8 +39,9 @@ #include "amlcode.h" #include "acnamesp.h" #include "acdebug.h" +#include "acinterp.h" -#define _COMPONENT PARSER +#define _COMPONENT ACPI_PARSER MODULE_NAME ("psparse") @@ -111,9 +112,9 @@ * * if (Opcode == AML_EXTOP * || (Opcode == AML_LNOT - * && (GET8 (Acpi_aml) == AML_LEQUAL - * || GET8 (Acpi_aml) == AML_LGREATER - * || GET8 (Acpi_aml) == AML_LLESS))) + * && (GET8 (Aml) == AML_LEQUAL + * || GET8 (Aml) == AML_LGREATER + * || GET8 (Aml) == AML_LLESS))) * * extended Opcode, !=, <=, or >= */ @@ -135,8 +136,8 @@ * * FUNCTION: Acpi_ps_create_state * - * PARAMETERS: Acpi_aml - Acpi_aml code pointer - * Acpi_aml_size - Length of AML code + * PARAMETERS: Aml - Aml code pointer + * Aml_size - Length of AML code * * RETURN: A new parser state object * @@ -152,7 +153,7 @@ ACPI_PARSE_STATE *parser_state; - parser_state = acpi_cm_callocate (sizeof (ACPI_PARSE_STATE)); + parser_state = acpi_ut_callocate (sizeof (ACPI_PARSE_STATE)); if (!parser_state) { return (NULL); } @@ -260,8 +261,7 @@ (opcode_class != OPTYPE_LOCAL_VARIABLE) && (opcode_class != OPTYPE_METHOD_ARGUMENT) && (opcode_class != OPTYPE_DATA_TERM) && - (op->opcode != AML_NAMEPATH_OP)) - { + (op->opcode != AML_INT_NAMEPATH_OP)) { /* Make sure that we only delete this subtree */ if (op->parent) { @@ -272,8 +272,7 @@ parent_info = acpi_ps_get_opcode_info (op->parent->opcode); - switch (ACPI_GET_OP_CLASS (parent_info)) - { + switch (ACPI_GET_OP_CLASS (parent_info)) { case OPTYPE_CONTROL: /* IF, ELSE, WHILE only */ break; @@ -284,15 +283,14 @@ * op must be replace by a placeholder return op */ - if ((op->parent->opcode == AML_REGION_OP) || - (op->parent->opcode == AML_CREATE_FIELD_OP) || - (op->parent->opcode == AML_BIT_FIELD_OP) || - (op->parent->opcode == AML_BYTE_FIELD_OP) || - (op->parent->opcode == AML_WORD_FIELD_OP) || - (op->parent->opcode == AML_DWORD_FIELD_OP) || - (op->parent->opcode == AML_QWORD_FIELD_OP)) - { - replacement_op = acpi_ps_alloc_op (AML_RETURN_VALUE_OP); + if ((op->parent->opcode == AML_REGION_OP) || + (op->parent->opcode == AML_CREATE_FIELD_OP) || + (op->parent->opcode == AML_CREATE_BIT_FIELD_OP) || + (op->parent->opcode == AML_CREATE_BYTE_FIELD_OP) || + (op->parent->opcode == AML_CREATE_WORD_FIELD_OP) || + (op->parent->opcode == AML_CREATE_DWORD_FIELD_OP) || + (op->parent->opcode == AML_CREATE_QWORD_FIELD_OP)) { + replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP); if (!replacement_op) { return (FALSE); } @@ -301,7 +299,7 @@ break; default: - replacement_op = acpi_ps_alloc_op (AML_RETURN_VALUE_OP); + replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP); if (!replacement_op) { return (FALSE); } @@ -388,8 +386,7 @@ u32 package_length; - switch (callback_status) - { + switch (callback_status) { case AE_CTRL_TERMINATE: /* @@ -505,7 +502,7 @@ ACPI_PARSE2_OBJECT *deferred_op; u32 arg_count; /* push for fixed or var args */ u32 arg_types = 0; - ACPI_PTRDIFF aml_offset; + u32 aml_offset; u16 opcode; ACPI_PARSE_OBJECT pre_op; ACPI_PARSE_STATE *parser_state; @@ -528,8 +525,7 @@ (parser_state->scope->parse_scope.op->opcode == AML_WHILE_OP)) && (walk_state->control_state) && (walk_state->control_state->common.state == - CONTROL_PREDICATE_EXECUTING)) - { + CONTROL_PREDICATE_EXECUTING)) { /* * A predicate was just completed, get the value of the @@ -538,8 +534,7 @@ status = acpi_ds_get_predicate_value (walk_state, NULL, TRUE); if (ACPI_FAILURE (status) && - ((status & AE_CODE_MASK) != AE_CODE_CONTROL)) - { + ((status & AE_CODE_MASK) != AE_CODE_CONTROL)) { return (status); } @@ -577,8 +572,7 @@ */ op_info = acpi_ps_get_opcode_info (opcode); - switch (ACPI_GET_OP_TYPE (op_info)) - { + switch (ACPI_GET_OP_TYPE (op_info)) { case ACPI_OP_TYPE_OPCODE: /* Found opcode info, this is a normal opcode */ @@ -594,7 +588,7 @@ * string. Convert the bare name string to a namepath. */ - opcode = AML_NAMEPATH_OP; + opcode = AML_INT_NAMEPATH_OP; arg_types = ARGP_NAMESTRING; break; @@ -684,12 +678,12 @@ } - if ((op->opcode == AML_CREATE_FIELD_OP) || - (op->opcode == AML_BIT_FIELD_OP) || - (op->opcode == AML_BYTE_FIELD_OP) || - (op->opcode == AML_WORD_FIELD_OP) || - (op->opcode == AML_DWORD_FIELD_OP)) - { + if ((op->opcode == AML_CREATE_FIELD_OP) || + (op->opcode == AML_CREATE_BIT_FIELD_OP) || + (op->opcode == AML_CREATE_BYTE_FIELD_OP) || + (op->opcode == AML_CREATE_WORD_FIELD_OP) || + (op->opcode == AML_CREATE_DWORD_FIELD_OP) || + (op->opcode == AML_CREATE_QWORD_FIELD_OP)) { /* * Backup to beginning of Create_xXXfield declaration * Body_length is unknown until we parse the body @@ -733,8 +727,7 @@ if (arg_types) /* Are there any arguments that must be processed? */ { /* get arguments */ - switch (op->opcode) - { + switch (op->opcode) { case AML_BYTE_OP: /* AML_BYTEDATA_ARG */ case AML_WORD_OP: /* AML_WORDDATA_ARG */ case AML_DWORD_OP: /* AML_DWORDATA_ARG */ @@ -746,7 +739,7 @@ GET_CURRENT_ARG_TYPE (arg_types), op); break; - case AML_NAMEPATH_OP: /* AML_NAMESTRING_ARG */ + case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */ acpi_ps_get_next_namepath (parser_state, op, &arg_count, 1); arg_types = 0; @@ -783,8 +776,8 @@ */ deferred_op->data = parser_state->aml; - deferred_op->length = parser_state->pkg_end - - parser_state->aml; + deferred_op->length = (u32) (parser_state->pkg_end - + parser_state->aml); /* * Skip body of method. For Op_regions, we must continue @@ -824,19 +817,18 @@ * know the length. */ - deferred_op->length = parser_state->aml - - deferred_op->data; + deferred_op->length = (u32) (parser_state->aml - + deferred_op->data); } } } - if ((op->opcode == AML_CREATE_FIELD_OP) || - (op->opcode == AML_BIT_FIELD_OP) || - (op->opcode == AML_BYTE_FIELD_OP) || - (op->opcode == AML_WORD_FIELD_OP) || - (op->opcode == AML_DWORD_FIELD_OP) || - (op->opcode == AML_QWORD_FIELD_OP)) - { + if ((op->opcode == AML_CREATE_FIELD_OP) || + (op->opcode == AML_CREATE_BIT_FIELD_OP) || + (op->opcode == AML_CREATE_BYTE_FIELD_OP) || + (op->opcode == AML_CREATE_WORD_FIELD_OP) || + (op->opcode == AML_CREATE_DWORD_FIELD_OP) || + (op->opcode == AML_CREATE_QWORD_FIELD_OP)) { /* * Backup to beginning of Create_xXXfield declaration (1 for * Opcode) @@ -844,7 +836,8 @@ * Body_length is unknown until we parse the body */ deferred_op = (ACPI_PARSE2_OBJECT *) op; - deferred_op->length = parser_state->aml - deferred_op->data; + deferred_op->length = (u32) (parser_state->aml - + deferred_op->data); } /* This op complete, notify the dispatcher */ @@ -873,8 +866,7 @@ } - switch (status) - { + switch (status) { case AE_OK: break; @@ -908,8 +900,7 @@ status = AE_OK; /* Clean up */ - do - { + do { if (op) { acpi_ps_complete_this_op (walk_state, op); } @@ -970,8 +961,7 @@ * sequential closing braces). We want to terminate each one cleanly. */ - do - { + do { if (op) { if (walk_state->ascending_callback != NULL) { status = walk_state->ascending_callback (walk_state, op); @@ -985,8 +975,7 @@ status = AE_OK; /* Clean up */ - do - { + do { if (op) { acpi_ps_complete_this_op (walk_state, op); } @@ -1068,8 +1057,11 @@ /* Create and initialize a new walk list */ walk_list.walk_state = NULL; + walk_list.acquired_mutex_list.prev = NULL; + walk_list.acquired_mutex_list.next = NULL; - walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, parser_state->start_op, mth_desc, &walk_list); + walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, parser_state->start_op, + mth_desc, &walk_list); if (!walk_state) { status = AE_NO_MEMORY; goto cleanup; @@ -1180,15 +1172,14 @@ /* Delete this walk state and all linked control states */ acpi_ps_cleanup_scope (walk_state->parser_state); - acpi_cm_free (walk_state->parser_state); + acpi_ut_free (walk_state->parser_state); acpi_ds_delete_walk_state (walk_state); /* Check if we have restarted a preempted walk */ walk_state = acpi_ds_get_current_walk_state (&walk_list); if (walk_state && - ACPI_SUCCESS (status)) - { + ACPI_SUCCESS (status)) { /* There is another walk state, restart it */ /* @@ -1212,13 +1203,14 @@ else if (return_desc) { /* Caller doesn't want it, must delete it */ - acpi_cm_remove_reference (return_desc); + acpi_ut_remove_reference (return_desc); } } /* Normal exit */ + acpi_ex_release_all_mutexes ((ACPI_OPERAND_OBJECT *) &walk_list.acquired_mutex_list); acpi_gbl_current_walk_list = prev_walk_list; return (status); @@ -1229,8 +1221,9 @@ acpi_ds_delete_walk_state (walk_state); acpi_ps_cleanup_scope (parser_state); - acpi_cm_free (parser_state); + acpi_ut_free (parser_state); + acpi_ex_release_all_mutexes ((ACPI_OPERAND_OBJECT *)&walk_list.acquired_mutex_list); acpi_gbl_current_walk_list = prev_walk_list; return (status); diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/parser/psscope.c linux/drivers/acpi/parser/psscope.c --- v2.4.5/linux/drivers/acpi/parser/psscope.c Mon Jan 22 13:23:43 2001 +++ linux/drivers/acpi/parser/psscope.c Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: psscope - Parser scope stack management routines - * $Revision: 24 $ + * $Revision: 27 $ * *****************************************************************************/ @@ -27,7 +27,7 @@ #include "acpi.h" #include "acparser.h" -#define _COMPONENT PARSER +#define _COMPONENT ACPI_PARSER MODULE_NAME ("psscope") @@ -95,7 +95,7 @@ ACPI_GENERIC_STATE *scope; - scope = acpi_cm_create_generic_state (); + scope = acpi_ut_create_generic_state (); if (!scope) { return (AE_NO_MEMORY); } @@ -137,7 +137,7 @@ ACPI_GENERIC_STATE *scope; - scope = acpi_cm_create_generic_state (); + scope = acpi_ut_create_generic_state (); if (!scope) { return (AE_NO_MEMORY); } @@ -150,7 +150,7 @@ /* Push onto scope stack */ - acpi_cm_push_generic_state (&parser_state->scope, scope); + acpi_ut_push_generic_state (&parser_state->scope, scope); if (arg_count == ACPI_VAR_ARGS) { @@ -199,7 +199,7 @@ * Only pop the scope if there is in fact a next scope */ if (scope->common.next) { - scope = acpi_cm_pop_generic_state (&parser_state->scope); + scope = acpi_ut_pop_generic_state (&parser_state->scope); /* return to parsing previous op */ @@ -211,7 +211,7 @@ /* All done with this scope state structure */ - acpi_cm_delete_generic_state (scope); + acpi_ut_delete_generic_state (scope); } else { @@ -255,8 +255,8 @@ /* Delete anything on the scope stack */ while (parser_state->scope) { - scope = acpi_cm_pop_generic_state (&parser_state->scope); - acpi_cm_delete_generic_state (scope); + scope = acpi_ut_pop_generic_state (&parser_state->scope); + acpi_ut_delete_generic_state (scope); } return; diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/parser/pstree.c linux/drivers/acpi/parser/pstree.c --- v2.4.5/linux/drivers/acpi/parser/pstree.c Mon Jan 22 13:23:43 2001 +++ linux/drivers/acpi/parser/pstree.c Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: pstree - Parser op tree manipulation/traversal/search - * $Revision: 27 $ + * $Revision: 30 $ * *****************************************************************************/ @@ -28,7 +28,7 @@ #include "acparser.h" #include "amlcode.h" -#define _COMPONENT PARSER +#define _COMPONENT ACPI_PARSER MODULE_NAME ("pstree") @@ -174,13 +174,12 @@ ACPI_PARSE_OBJECT *child = NULL; - switch (op->opcode) - { + switch (op->opcode) { case AML_SCOPE_OP: case AML_ELSE_OP: case AML_DEVICE_OP: case AML_THERMAL_ZONE_OP: - case AML_METHODCALL_OP: + case AML_INT_METHODCALL_OP: child = acpi_ps_get_arg (op, 0); break; @@ -191,7 +190,7 @@ case AML_METHOD_OP: case AML_IF_OP: case AML_WHILE_OP: - case AML_DEF_FIELD_OP: + case AML_FIELD_OP: child = acpi_ps_get_arg (op, 1); break; diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/parser/psutils.c linux/drivers/acpi/parser/psutils.c --- v2.4.5/linux/drivers/acpi/parser/psutils.c Mon Jan 22 13:23:43 2001 +++ linux/drivers/acpi/parser/psutils.c Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: psutils - Parser miscellaneous utilities (Parser only) - * $Revision: 32 $ + * $Revision: 37 $ * *****************************************************************************/ @@ -28,7 +28,7 @@ #include "acparser.h" #include "amlcode.h" -#define _COMPONENT PARSER +#define _COMPONENT ACPI_PARSER MODULE_NAME ("psutils") @@ -94,6 +94,9 @@ u8 flags; + PROC_NAME ("Ps_alloc_op"); + + /* Allocate the minimum required size object */ if (acpi_ps_is_deferred_op (opcode)) { @@ -125,7 +128,7 @@ * Check if there is an Op already available in the cache */ - acpi_cm_acquire_mutex (ACPI_MTX_CACHES); + acpi_ut_acquire_mutex (ACPI_MTX_CACHES); acpi_gbl_parse_cache_requests++; if (acpi_gbl_parse_cache) { /* Extract an op from the front of the cache list */ @@ -142,7 +145,7 @@ MEMSET (op, 0, sizeof (ACPI_PARSE_OBJECT)); } - acpi_cm_release_mutex (ACPI_MTX_CACHES); + acpi_ut_release_mutex (ACPI_MTX_CACHES); } else { @@ -153,7 +156,7 @@ * Check if there is an Op already available in the cache */ - acpi_cm_acquire_mutex (ACPI_MTX_CACHES); + acpi_ut_acquire_mutex (ACPI_MTX_CACHES); acpi_gbl_ext_parse_cache_requests++; if (acpi_gbl_ext_parse_cache) { /* Extract an op from the front of the cache list */ @@ -170,14 +173,14 @@ MEMSET (op, 0, sizeof (ACPI_PARSE2_OBJECT)); } - acpi_cm_release_mutex (ACPI_MTX_CACHES); + acpi_ut_release_mutex (ACPI_MTX_CACHES); } /* Allocate a new Op if necessary */ if (!op) { - op = acpi_cm_callocate (size); + op = acpi_ut_callocate (size); } /* Initialize the Op */ @@ -207,6 +210,7 @@ acpi_ps_free_op ( ACPI_PARSE_OBJECT *op) { + PROC_NAME ("Ps_free_op"); @@ -221,13 +225,13 @@ MEMSET (op, 0, sizeof (ACPI_PARSE_OBJECT)); op->flags = PARSEOP_IN_CACHE; - acpi_cm_acquire_mutex (ACPI_MTX_CACHES); + acpi_ut_acquire_mutex (ACPI_MTX_CACHES); acpi_gbl_parse_cache_depth++; op->next = acpi_gbl_parse_cache; acpi_gbl_parse_cache = op; - acpi_cm_release_mutex (ACPI_MTX_CACHES); + acpi_ut_release_mutex (ACPI_MTX_CACHES); return; } } @@ -243,13 +247,13 @@ MEMSET (op, 0, sizeof (ACPI_PARSE2_OBJECT)); op->flags = PARSEOP_IN_CACHE; - acpi_cm_acquire_mutex (ACPI_MTX_CACHES); + acpi_ut_acquire_mutex (ACPI_MTX_CACHES); acpi_gbl_ext_parse_cache_depth++; op->next = (ACPI_PARSE_OBJECT *) acpi_gbl_ext_parse_cache; acpi_gbl_ext_parse_cache = (ACPI_PARSE2_OBJECT *) op; - acpi_cm_release_mutex (ACPI_MTX_CACHES); + acpi_ut_release_mutex (ACPI_MTX_CACHES); return; } } @@ -259,7 +263,7 @@ * Not a GENERIC OP, or the cache is full, just free the Op */ - acpi_cm_free (op); + acpi_ut_free (op); } @@ -288,7 +292,7 @@ /* Delete one cached state object */ next = acpi_gbl_parse_cache->next; - acpi_cm_free (acpi_gbl_parse_cache); + acpi_ut_free (acpi_gbl_parse_cache); acpi_gbl_parse_cache = next; acpi_gbl_parse_cache_depth--; } @@ -299,7 +303,7 @@ /* Delete one cached state object */ next = acpi_gbl_ext_parse_cache->next; - acpi_cm_free (acpi_gbl_ext_parse_cache); + acpi_ut_free (acpi_gbl_ext_parse_cache); acpi_gbl_ext_parse_cache = (ACPI_PARSE2_OBJECT *) next; acpi_gbl_ext_parse_cache_depth--; } @@ -350,28 +354,29 @@ u16 opcode) { return ((u8) - (opcode == AML_SCOPE_OP || - opcode == AML_DEVICE_OP || - opcode == AML_THERMAL_ZONE_OP || - opcode == AML_METHOD_OP || - opcode == AML_POWER_RES_OP || - opcode == AML_PROCESSOR_OP || - opcode == AML_DEF_FIELD_OP || - opcode == AML_INDEX_FIELD_OP || - opcode == AML_BANK_FIELD_OP || - opcode == AML_NAMEDFIELD_OP || - opcode == AML_NAME_OP || - opcode == AML_ALIAS_OP || - opcode == AML_MUTEX_OP || - opcode == AML_EVENT_OP || - opcode == AML_REGION_OP || - opcode == AML_CREATE_FIELD_OP || - opcode == AML_BIT_FIELD_OP || - opcode == AML_BYTE_FIELD_OP || - opcode == AML_WORD_FIELD_OP || - opcode == AML_DWORD_FIELD_OP || - opcode == AML_METHODCALL_OP || - opcode == AML_NAMEPATH_OP)); + (opcode == AML_SCOPE_OP || + opcode == AML_DEVICE_OP || + opcode == AML_THERMAL_ZONE_OP || + opcode == AML_METHOD_OP || + opcode == AML_POWER_RES_OP || + opcode == AML_PROCESSOR_OP || + opcode == AML_FIELD_OP || + opcode == AML_INDEX_FIELD_OP || + opcode == AML_BANK_FIELD_OP || + opcode == AML_INT_NAMEDFIELD_OP || + opcode == AML_NAME_OP || + opcode == AML_ALIAS_OP || + opcode == AML_MUTEX_OP || + opcode == AML_EVENT_OP || + opcode == AML_REGION_OP || + opcode == AML_CREATE_FIELD_OP || + opcode == AML_CREATE_BIT_FIELD_OP || + opcode == AML_CREATE_BYTE_FIELD_OP || + opcode == AML_CREATE_WORD_FIELD_OP || + opcode == AML_CREATE_DWORD_FIELD_OP || + opcode == AML_CREATE_QWORD_FIELD_OP || + opcode == AML_INT_METHODCALL_OP || + opcode == AML_INT_NAMEPATH_OP)); } u8 @@ -385,7 +390,7 @@ opcode == AML_METHOD_OP || opcode == AML_POWER_RES_OP || opcode == AML_PROCESSOR_OP || - opcode == AML_DEF_FIELD_OP || + opcode == AML_FIELD_OP || opcode == AML_INDEX_FIELD_OP || opcode == AML_BANK_FIELD_OP || opcode == AML_NAME_OP || @@ -393,7 +398,7 @@ opcode == AML_MUTEX_OP || opcode == AML_EVENT_OP || opcode == AML_REGION_OP || - opcode == AML_NAMEDFIELD_OP)); + opcode == AML_INT_NAMEDFIELD_OP)); } @@ -408,27 +413,28 @@ u16 opcode) { return ((u8) - (opcode == AML_SCOPE_OP || - opcode == AML_DEVICE_OP || - opcode == AML_THERMAL_ZONE_OP || - opcode == AML_METHOD_OP || - opcode == AML_POWER_RES_OP || - opcode == AML_PROCESSOR_OP || - opcode == AML_NAMEDFIELD_OP || - opcode == AML_NAME_OP || - opcode == AML_ALIAS_OP || - opcode == AML_MUTEX_OP || - opcode == AML_EVENT_OP || - opcode == AML_REGION_OP || - - - opcode == AML_CREATE_FIELD_OP || - opcode == AML_BIT_FIELD_OP || - opcode == AML_BYTE_FIELD_OP || - opcode == AML_WORD_FIELD_OP || - opcode == AML_DWORD_FIELD_OP || - opcode == AML_METHODCALL_OP || - opcode == AML_NAMEPATH_OP)); + (opcode == AML_SCOPE_OP || + opcode == AML_DEVICE_OP || + opcode == AML_THERMAL_ZONE_OP || + opcode == AML_METHOD_OP || + opcode == AML_POWER_RES_OP || + opcode == AML_PROCESSOR_OP || + opcode == AML_INT_NAMEDFIELD_OP || + opcode == AML_NAME_OP || + opcode == AML_ALIAS_OP || + opcode == AML_MUTEX_OP || + opcode == AML_EVENT_OP || + opcode == AML_REGION_OP || + + + opcode == AML_CREATE_FIELD_OP || + opcode == AML_CREATE_BIT_FIELD_OP || + opcode == AML_CREATE_BYTE_FIELD_OP || + opcode == AML_CREATE_WORD_FIELD_OP || + opcode == AML_CREATE_DWORD_FIELD_OP || + opcode == AML_CREATE_QWORD_FIELD_OP || + opcode == AML_INT_METHODCALL_OP || + opcode == AML_INT_NAMEPATH_OP)); } @@ -451,7 +457,7 @@ opcode == AML_MUTEX_OP || opcode == AML_EVENT_OP || opcode == AML_REGION_OP || - opcode == AML_NAMEDFIELD_OP)); + opcode == AML_INT_NAMEDFIELD_OP)); } @@ -460,12 +466,13 @@ u16 opcode) { return ((u8) - (opcode == AML_METHOD_OP || - opcode == AML_CREATE_FIELD_OP || - opcode == AML_BIT_FIELD_OP || - opcode == AML_BYTE_FIELD_OP || - opcode == AML_WORD_FIELD_OP || - opcode == AML_DWORD_FIELD_OP || + (opcode == AML_METHOD_OP || + opcode == AML_CREATE_FIELD_OP || + opcode == AML_CREATE_BIT_FIELD_OP || + opcode == AML_CREATE_BYTE_FIELD_OP || + opcode == AML_CREATE_WORD_FIELD_OP || + opcode == AML_CREATE_DWORD_FIELD_OP || + opcode == AML_CREATE_QWORD_FIELD_OP || opcode == AML_REGION_OP)); } @@ -477,7 +484,7 @@ acpi_ps_is_bytelist_op ( u16 opcode) { - return ((u8) (opcode == AML_BYTELIST_OP)); + return ((u8) (opcode == AML_INT_BYTELIST_OP)); } @@ -490,7 +497,7 @@ { return ((u8) (opcode == AML_CREATE_FIELD_OP - || opcode == AML_DEF_FIELD_OP + || opcode == AML_FIELD_OP || opcode == AML_INDEX_FIELD_OP || opcode == AML_BANK_FIELD_OP)); } @@ -504,11 +511,12 @@ u16 opcode) { return ((u8) - (opcode == AML_CREATE_FIELD_OP || - opcode == AML_BIT_FIELD_OP || - opcode == AML_BYTE_FIELD_OP || - opcode == AML_WORD_FIELD_OP || - opcode == AML_DWORD_FIELD_OP)); + (opcode == AML_CREATE_FIELD_OP || + opcode == AML_CREATE_BIT_FIELD_OP || + opcode == AML_CREATE_BYTE_FIELD_OP || + opcode == AML_CREATE_WORD_FIELD_OP || + opcode == AML_CREATE_DWORD_FIELD_OP || + opcode == AML_CREATE_QWORD_FIELD_OP)); } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/parser/pswalk.c linux/drivers/acpi/parser/pswalk.c --- v2.4.5/linux/drivers/acpi/parser/pswalk.c Mon Jan 22 13:23:43 2001 +++ linux/drivers/acpi/parser/pswalk.c Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: pswalk - Parser routines to walk parsed op tree(s) - * $Revision: 52 $ + * $Revision: 55 $ * *****************************************************************************/ @@ -31,7 +31,7 @@ #include "acnamesp.h" #include "acinterp.h" -#define _COMPONENT PARSER +#define _COMPONENT ACPI_PARSER MODULE_NAME ("pswalk") @@ -243,6 +243,9 @@ /* Create and initialize a new walk list */ walk_list.walk_state = NULL; + walk_list.acquired_mutex_list.prev = NULL; + walk_list.acquired_mutex_list.next = NULL; + walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, NULL, NULL, &walk_list); if (!walk_state) { return; @@ -271,6 +274,7 @@ /* We are done with this walk */ + acpi_ex_release_all_mutexes ((ACPI_OPERAND_OBJECT *) &walk_list.acquired_mutex_list); acpi_ds_delete_walk_state (walk_state); return; diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/parser/psxface.c linux/drivers/acpi/parser/psxface.c --- v2.4.5/linux/drivers/acpi/parser/psxface.c Mon Jan 29 10:15:59 2001 +++ linux/drivers/acpi/parser/psxface.c Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: psxface - Parser external interfaces - * $Revision: 40 $ + * $Revision: 44 $ * *****************************************************************************/ @@ -32,7 +32,7 @@ #include "acnamesp.h" -#define _COMPONENT PARSER +#define _COMPONENT ACPI_PARSER MODULE_NAME ("psxface") @@ -79,7 +79,7 @@ /* Init for new method, wait on concurrency semaphore */ - status = acpi_ds_begin_method_execution (method_node, obj_desc); + status = acpi_ds_begin_method_execution (method_node, obj_desc, NULL); if (ACPI_FAILURE (status)) { return (status); } @@ -91,7 +91,7 @@ */ for (i = 0; params[i]; i++) { - acpi_cm_add_reference (params[i]); + acpi_ut_add_reference (params[i]); } } @@ -141,7 +141,7 @@ /* Take away the extra reference that we gave the parameters above */ for (i = 0; params[i]; i++) { - acpi_cm_update_object_reference (params[i], REF_DECREMENT); + acpi_ut_update_object_reference (params[i], REF_DECREMENT); } } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/power.c linux/drivers/acpi/power.c --- v2.4.5/linux/drivers/acpi/power.c Mon Jan 22 13:23:43 2001 +++ linux/drivers/acpi/power.c Wed Dec 31 16:00:00 1969 @@ -1,137 +0,0 @@ -/* - * power.c - Overall power driver. Also handles AC adapter device. - * - * Copyright (C) 2000 Andrew Grover - * - * 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 "acpi.h" -#include "driver.h" - -#define _COMPONENT OS_DEPENDENT - MODULE_NAME ("power") - -int acpi_cmbatt_init(void); -int acpi_cmbatt_terminate(void); - -/* ACPI-specific defines */ -#define ACPI_AC_ADAPTER_HID "ACPI0003" - -static int ac_count = 0; -static ACPI_HANDLE ac_handle = 0; - -/* - * We found a device with the correct HID - */ -static ACPI_STATUS -acpi_found_ac_adapter(ACPI_HANDLE handle, u32 level, void *ctx, void **value) -{ - ACPI_DEVICE_INFO info; - - if (ac_count > 0) { - printk(KERN_ERR "AC Adapter: more than one!\n"); - return (AE_OK); - } - - if (!ACPI_SUCCESS(acpi_get_object_info(handle, &info))) { - printk(KERN_ERR "AC Adapter: Could not get AC Adapter object info\n"); - return (AE_OK); - } - - if (!(info.valid & ACPI_VALID_STA)) { - printk(KERN_ERR "AC Adapter: Battery _STA invalid\n"); - return AE_OK; - } - - printk(KERN_INFO "AC Adapter: found\n"); - - ac_handle = handle; - - ac_count++; - - return AE_OK; -} - -static int -proc_read_ac_adapter_status(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - ACPI_OBJECT obj; - ACPI_BUFFER buf; - - char *p = page; - int len; - - buf.length = sizeof(obj); - buf.pointer = &obj; - if (!ACPI_SUCCESS(acpi_evaluate_object(ac_handle, "_PSR", NULL, &buf)) - || obj.type != ACPI_TYPE_INTEGER) { - p += sprintf(p, "Could not read AC status\n"); - goto end; - } - - if (obj.integer.value) - p += sprintf(p, "on-line\n"); - else - p += sprintf(p, "off-line\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 len; -} - -int -acpi_power_init(void) -{ - acpi_get_devices(ACPI_AC_ADAPTER_HID, - acpi_found_ac_adapter, - NULL, - NULL); - - if (!proc_mkdir("power", NULL)) - return 0; - - if (ac_handle) { - create_proc_read_entry("power/ac", 0, NULL, - proc_read_ac_adapter_status, NULL); - } - - acpi_cmbatt_init(); - - return 0; -} - -int -acpi_power_terminate(void) -{ - acpi_cmbatt_terminate(); - - if (ac_handle) { - remove_proc_entry("power/ac", NULL); - } - - remove_proc_entry("power", NULL); - - return 0; -} diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/resources/Makefile linux/drivers/acpi/resources/Makefile --- v2.4.5/linux/drivers/acpi/resources/Makefile Fri Dec 29 14:07:21 2000 +++ linux/drivers/acpi/resources/Makefile Wed Jun 20 17:47:40 2001 @@ -1,16 +1,12 @@ # # Makefile for all Linux ACPI interpreter subdirectories +# EXCEPT for the ospm directory # -O_TARGET := ../$(shell basename `pwd`).o +O_TARGET := $(notdir $(CURDIR)).o obj-$(CONFIG_ACPI) := $(patsubst %.c,%.o,$(wildcard *.c)) -EXTRA_CFLAGS += -I../include - EXTRA_CFLAGS += $(ACPI_CFLAGS) include $(TOPDIR)/Rules.make - -clean: - $(RM) *.o diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/resources/rsaddr.c linux/drivers/acpi/resources/rsaddr.c --- v2.4.5/linux/drivers/acpi/resources/rsaddr.c Mon Jan 22 13:23:43 2001 +++ linux/drivers/acpi/resources/rsaddr.c Wed Jun 20 17:47:40 2001 @@ -1,10 +1,7 @@ /******************************************************************************* * - * Module Name: rsaddr - Acpi_rs_address16_resource - * Acpi_rs_address16_stream - * Acpi_rs_address32_resource - * Acpi_rs_address32_stream - * $Revision: 14 $ + * Module Name: rsaddr - Address resource descriptors (16/32/64) + * $Revision: 18 $ * ******************************************************************************/ @@ -30,7 +27,7 @@ #include "acpi.h" #include "acresrc.h" -#define _COMPONENT RESOURCE_MANAGER +#define _COMPONENT ACPI_RESOURCES MODULE_NAME ("rsaddr") @@ -39,20 +36,20 @@ * FUNCTION: Acpi_rs_address16_resource * * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte - * stream + * stream * Bytes_consumed - u32 pointer that is filled with - * the number of bytes consumed from - * the Byte_stream_buffer + * the number of bytes consumed from + * the Byte_stream_buffer * Output_buffer - Pointer to the user's return buffer * Structure_size - u32 pointer that is filled with - * the number of bytes in the filled - * in structure + * the number of bytes in the filled + * in structure * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Take the resource byte stream and fill out the appropriate - * structure pointed to by the Output_buffer. Return the - * number of bytes consumed from the byte stream. + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. * ******************************************************************************/ @@ -64,26 +61,22 @@ u32 *structure_size) { u8 *buffer = byte_stream_buffer; - RESOURCE *output_struct = (RESOURCE *) * output_buffer; + ACPI_RESOURCE *output_struct = (ACPI_RESOURCE *) *output_buffer; + NATIVE_CHAR *temp_ptr; + u32 struct_size = SIZEOF_RESOURCE (ACPI_RESOURCE_ADDRESS16); + u32 index; u16 temp16; u8 temp8; - u32 index; - u32 struct_size = sizeof(ADDRESS16_RESOURCE) + - RESOURCE_LENGTH_NO_DATA; /* * Point past the Descriptor to get the number of bytes consumed */ buffer += 1; - MOVE_UNALIGNED16_TO_16 (&temp16, buffer); *bytes_consumed = temp16 + 3; - - output_struct->id = address16; - - output_struct->length = struct_size; + output_struct->id = ACPI_RSTYPE_ADDRESS16; /* * Get the Resource Type (Byte3) @@ -93,7 +86,7 @@ /* Values 0-2 are valid */ if (temp8 > 2) { - return (AE_AML_ERROR); + return (AE_AML_INVALID_RESOURCE_TYPE); } output_struct->data.address16.resource_type = temp8 & 0x03; @@ -144,7 +137,7 @@ } else { - /* BUS_NUMBER_RANGE == Address32_data->Resource_type */ + /* BUS_NUMBER_RANGE == Address16.Data->Resource_type */ /* Nothing needs to be filled in */ } } @@ -167,25 +160,22 @@ * Get Max_address_range (Bytes 10-11) */ buffer += 2; - MOVE_UNALIGNED16_TO_16 - (&output_struct->data.address16.max_address_range, - buffer); + MOVE_UNALIGNED16_TO_16 (&output_struct->data.address16.max_address_range, + buffer); /* * Get Address_translation_offset (Bytes 12-13) */ buffer += 2; - MOVE_UNALIGNED16_TO_16 - (&output_struct->data.address16.address_translation_offset, - buffer); + MOVE_UNALIGNED16_TO_16 (&output_struct->data.address16.address_translation_offset, + buffer); /* * Get Address_length (Bytes 14-15) */ buffer += 2; - MOVE_UNALIGNED16_TO_16 - (&output_struct->data.address16.address_length, - buffer); + MOVE_UNALIGNED16_TO_16 (&output_struct->data.address16.address_length, + buffer); /* * Resource Source Index (if present) @@ -194,30 +184,36 @@ /* * This will leave us pointing to the Resource Source Index - * If it is present, then save it off and calculate the - * pointer to where the null terminated string goes: - * Each Interrupt takes 32-bits + the 5 bytes of the - * stream that are default. + * If it is present, then save it off and calculate the + * pointer to where the null terminated string goes: + * Each Interrupt takes 32-bits + the 5 bytes of the + * stream that are default. */ if (*bytes_consumed > 16) { /* Dereference the Index */ temp8 = *buffer; - output_struct->data.address16.resource_source_index = - (u32) temp8; + output_struct->data.address16.resource_source.index = (u32) temp8; /* Point to the String */ buffer += 1; + /* Point the String pointer to the end of this structure */ + + 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; + /* Copy the string into the buffer */ index = 0; while (0x00 != *buffer) { - output_struct->data.address16.resource_source[index] = - *buffer; + *temp_ptr = *buffer; + temp_ptr += 1; buffer += 1; index += 1; } @@ -225,31 +221,34 @@ /* * Add the terminating null */ - output_struct->data.address16.resource_source[index] = 0x00; + *temp_ptr = 0x00; - output_struct->data.address16.resource_source_string_length = - index + 1; + output_struct->data.address16.resource_source.string_length = index + 1; /* - * In order for the Struct_size to fall on a 32-bit boundry, - * calculate the length of the string and expand the - * Struct_size to the next 32-bit boundry. + * In order for the Struct_size to fall on a 32-bit boundary, + * calculate the length of the string and expand the + * Struct_size to the next 32-bit boundary. */ temp8 = (u8) (index + 1); struct_size += ROUND_UP_TO_32_bITS (temp8); - output_struct->length = struct_size; } + else { - output_struct->data.address16.resource_source_index = 0x00; - output_struct->data.address16.resource_source_string_length = 0; - output_struct->data.address16.resource_source[0] = 0x00; + output_struct->data.address16.resource_source.index = 0x00; + output_struct->data.address16.resource_source.string_length = 0; + output_struct->data.address16.resource_source.string_ptr = NULL; } /* + * Set the Length parameter + */ + output_struct->length = struct_size; + + /* * Return the final size of the structure */ *structure_size = struct_size; - return (AE_OK); } @@ -261,19 +260,19 @@ * PARAMETERS: Linked_list - Pointer to the resource linked list * Output_buffer - Pointer to the user's return buffer * Bytes_consumed - u32 pointer that is filled with - * the number of bytes of the - * Output_buffer used + * the number of bytes of the + * Output_buffer used * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Take the linked list resource structure and fills in the - * the appropriate bytes in a byte stream + * the appropriate bytes in a byte stream * ******************************************************************************/ ACPI_STATUS acpi_rs_address16_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u8 **output_buffer, u32 *bytes_consumed) { @@ -343,42 +342,42 @@ * Set the address space granularity */ MOVE_UNALIGNED16_TO_16 (buffer, - &linked_list->data.address16.granularity); + &linked_list->data.address16.granularity); buffer += 2; /* * Set the address range minimum */ MOVE_UNALIGNED16_TO_16 (buffer, - &linked_list->data.address16.min_address_range); + &linked_list->data.address16.min_address_range); buffer += 2; /* * Set the address range maximum */ MOVE_UNALIGNED16_TO_16 (buffer, - &linked_list->data.address16.max_address_range); + &linked_list->data.address16.max_address_range); buffer += 2; /* * Set the address translation offset */ MOVE_UNALIGNED16_TO_16 (buffer, - &linked_list->data.address16.address_translation_offset); + &linked_list->data.address16.address_translation_offset); buffer += 2; /* * Set the address length */ MOVE_UNALIGNED16_TO_16 (buffer, - &linked_list->data.address16.address_length); + &linked_list->data.address16.address_length); buffer += 2; /* * Resource Source Index and Resource Source are optional */ - if (0 != linked_list->data.address16.resource_source_string_length) { - temp8 = (u8) linked_list->data.address16.resource_source_index; + if (0 != linked_list->data.address16.resource_source.string_length) { + temp8 = (u8) linked_list->data.address16.resource_source.index; *buffer = temp8; buffer += 1; @@ -388,21 +387,21 @@ /* * Copy the string */ - STRCPY (temp_pointer, linked_list->data.address16.resource_source); + STRCPY (temp_pointer, + linked_list->data.address16.resource_source.string_ptr); /* * Buffer needs to be set to the length of the sting + one for the * terminating null */ - buffer += (STRLEN (linked_list->data.address16.resource_source) + 1); + buffer += (STRLEN (linked_list->data.address16.resource_source.string_ptr) + + 1); } /* * Return the number of bytes consumed in this operation */ - actual_bytes = (u32) ((NATIVE_UINT) buffer - - (NATIVE_UINT) *output_buffer); - + actual_bytes = POINTER_DIFF (buffer, *output_buffer); *bytes_consumed = actual_bytes; /* @@ -411,7 +410,6 @@ */ actual_bytes -= 3; MOVE_UNALIGNED16_TO_16 (length_field, &actual_bytes); - return (AE_OK); } @@ -421,20 +419,20 @@ * FUNCTION: Acpi_rs_address32_resource * * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte - * stream + * stream * Bytes_consumed - u32 pointer that is filled with - * the number of bytes consumed from - * the Byte_stream_buffer + * the number of bytes consumed from + * the Byte_stream_buffer * Output_buffer - Pointer to the user's return buffer * Structure_size - u32 pointer that is filled with - * the number of bytes in the filled - * in structure + * the number of bytes in the filled + * in structure * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Take the resource byte stream and fill out the appropriate - * structure pointed to by the Output_buffer. Return the - * number of bytes consumed from the byte stream. + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. * ******************************************************************************/ @@ -446,19 +444,18 @@ u32 *structure_size) { u8 *buffer; - RESOURCE *output_struct; + ACPI_RESOURCE *output_struct; u16 temp16; u8 temp8; + NATIVE_CHAR *temp_ptr; u32 struct_size; u32 index; buffer = byte_stream_buffer; + output_struct = (ACPI_RESOURCE *) *output_buffer; - output_struct = (RESOURCE *) *output_buffer; - - struct_size = sizeof (ADDRESS32_RESOURCE) + - RESOURCE_LENGTH_NO_DATA; + struct_size = SIZEOF_RESOURCE (ACPI_RESOURCE_ADDRESS32); /* * Point past the Descriptor to get the number of bytes consumed @@ -468,7 +465,7 @@ *bytes_consumed = temp16 + 3; - output_struct->id = address32; + output_struct->id = ACPI_RSTYPE_ADDRESS32; /* * Get the Resource Type (Byte3) @@ -478,7 +475,7 @@ /* Values 0-2 are valid */ if(temp8 > 2) { - return (AE_AML_ERROR); + return (AE_AML_INVALID_RESOURCE_TYPE); } output_struct->data.address32.resource_type = temp8 & 0x03; @@ -560,9 +557,8 @@ * Get Address_translation_offset (Bytes 18-21) */ buffer += 4; - MOVE_UNALIGNED32_TO_32 - (&output_struct->data.address32.address_translation_offset, - buffer); + MOVE_UNALIGNED32_TO_32 (&output_struct->data.address32.address_translation_offset, + buffer); /* * Get Address_length (Bytes 22-25) @@ -578,27 +574,35 @@ /* * This will leave us pointing to the Resource Source Index - * If it is present, then save it off and calculate the - * pointer to where the null terminated string goes: - * Each Interrupt takes 32-bits + the 5 bytes of the - * stream that are default. + * If it is present, then save it off and calculate the + * pointer to where the null terminated string goes: */ if (*bytes_consumed > 26) { /* Dereference the Index */ temp8 = *buffer; - output_struct->data.address32.resource_source_index = (u32)temp8; + output_struct->data.address32.resource_source.index = + (u32) temp8; /* Point to the String */ buffer += 1; + /* Point the String pointer to the end of this structure */ + + 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; + /* Copy the string into the buffer */ index = 0; while (0x00 != *buffer) { - output_struct->data.address32.resource_source[index] = *buffer; + *temp_ptr = *buffer; + + temp_ptr += 1; buffer += 1; index += 1; } @@ -606,23 +610,22 @@ /* * Add the terminating null */ - output_struct->data.address32.resource_source[index] = 0x00; - - output_struct->data.address32.resource_source_string_length = index + 1; + *temp_ptr = 0x00; + output_struct->data.address32.resource_source.string_length = index + 1; /* - * In order for the Struct_size to fall on a 32-bit boundry, + * In order for the Struct_size to fall on a 32-bit boundary, * calculate the length of the string and expand the - * Struct_size to the next 32-bit boundry. + * Struct_size to the next 32-bit boundary. */ temp8 = (u8) (index + 1); struct_size += ROUND_UP_TO_32_bITS (temp8); } else { - output_struct->data.address32.resource_source_index = 0x00; - output_struct->data.address32.resource_source_string_length = 0; - output_struct->data.address32.resource_source[0] = 0x00; + output_struct->data.address32.resource_source.index = 0x00; + output_struct->data.address32.resource_source.string_length = 0; + output_struct->data.address32.resource_source.string_ptr = NULL; } /* @@ -634,7 +637,6 @@ * Return the final size of the structure */ *structure_size = struct_size; - return (AE_OK); } @@ -646,19 +648,19 @@ * PARAMETERS: Linked_list - Pointer to the resource linked list * Output_buffer - Pointer to the user's return buffer * Bytes_consumed - u32 pointer that is filled with - * the number of bytes of the - * Output_buffer used + * the number of bytes of the + * Output_buffer used * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Take the linked list resource structure and fills in the - * the appropriate bytes in a byte stream + * the appropriate bytes in a byte stream * ******************************************************************************/ ACPI_STATUS acpi_rs_address32_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u8 **output_buffer, u32 *bytes_consumed) { @@ -680,7 +682,7 @@ * Set a pointer to the Length field - to be filled in later */ - length_field = (u16 *)buffer; + length_field = (u16 *) buffer; buffer += 2; /* @@ -730,21 +732,21 @@ * Set the address space granularity */ MOVE_UNALIGNED32_TO_32 (buffer, - &linked_list->data.address32.granularity); + &linked_list->data.address32.granularity); buffer += 4; /* * Set the address range minimum */ MOVE_UNALIGNED32_TO_32 (buffer, - &linked_list->data.address32.min_address_range); + &linked_list->data.address32.min_address_range); buffer += 4; /* * Set the address range maximum */ MOVE_UNALIGNED32_TO_32 (buffer, - &linked_list->data.address32.max_address_range); + &linked_list->data.address32.max_address_range); buffer += 4; /* @@ -758,14 +760,14 @@ * Set the address length */ MOVE_UNALIGNED32_TO_32 (buffer, - &linked_list->data.address32.address_length); + &linked_list->data.address32.address_length); buffer += 4; /* * Resource Source Index and Resource Source are optional */ - if (0 != linked_list->data.address32.resource_source_string_length) { - temp8 = (u8) linked_list->data.address32.resource_source_index; + if (0 != linked_list->data.address32.resource_source.string_length) { + temp8 = (u8) linked_list->data.address32.resource_source.index; *buffer = temp8; buffer += 1; @@ -775,27 +777,414 @@ /* * Copy the string */ - STRCPY (temp_pointer, linked_list->data.address32.resource_source); + STRCPY (temp_pointer, + linked_list->data.address32.resource_source.string_ptr); /* * Buffer needs to be set to the length of the sting + one for the * terminating null */ - buffer += (STRLEN (linked_list->data.address32.resource_source) + 1); + buffer += (STRLEN (linked_list->data.address32.resource_source.string_ptr) + 1); } /* * Return the number of bytes consumed in this operation */ - *bytes_consumed = (u32) ((NATIVE_UINT) buffer - - (NATIVE_UINT) *output_buffer); + *bytes_consumed = POINTER_DIFF (buffer, *output_buffer); /* * Set the length field to the number of bytes consumed * minus the header size (3 bytes) */ *length_field = (u16) (*bytes_consumed - 3); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_address64_resource + * + * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte + * stream + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes consumed from + * the Byte_stream_buffer + * Output_buffer - Pointer to the user's return buffer + * Structure_size - u32 pointer that is filled with + * the number of bytes in the filled + * in structure + * + * RETURN: Status + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_address64_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size) +{ + u8 *buffer; + ACPI_RESOURCE *output_struct; + u16 temp16; + u8 temp8; + NATIVE_CHAR *temp_ptr; + u32 struct_size; + u32 index; + + + buffer = byte_stream_buffer; + output_struct = (ACPI_RESOURCE *) *output_buffer; + + struct_size = SIZEOF_RESOURCE (ACPI_RESOURCE_ADDRESS64); + + /* + * Point past the Descriptor to get the number of bytes consumed + */ + buffer += 1; + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + + *bytes_consumed = temp16 + 3; + output_struct->id = ACPI_RSTYPE_ADDRESS64; + + /* + * Get the Resource Type (Byte3) + */ + buffer += 2; + temp8 = *buffer; + + /* Values 0-2 are valid */ + if(temp8 > 2) { + return (AE_AML_INVALID_RESOURCE_TYPE); + } + + output_struct->data.address64.resource_type = temp8 & 0x03; + + /* + * Get the General Flags (Byte4) + */ + buffer += 1; + temp8 = *buffer; + + /* + * Producer / Consumer + */ + output_struct->data.address64.producer_consumer = temp8 & 0x01; + + /* + * Decode + */ + output_struct->data.address64.decode = (temp8 >> 1) & 0x01; + + /* + * Min Address Fixed + */ + output_struct->data.address64.min_address_fixed = (temp8 >> 2) & 0x01; + + /* + * Max Address Fixed + */ + output_struct->data.address64.max_address_fixed = (temp8 >> 3) & 0x01; + + /* + * Get the Type Specific Flags (Byte5) + */ + buffer += 1; + temp8 = *buffer; + + if (MEMORY_RANGE == output_struct->data.address64.resource_type) { + output_struct->data.address64.attribute.memory.read_write_attribute = + (u16) (temp8 & 0x01); + + output_struct->data.address64.attribute.memory.cache_attribute = + (u16) ((temp8 >> 1) & 0x0F); + } + + else { + if (IO_RANGE == output_struct->data.address64.resource_type) { + output_struct->data.address64.attribute.io.range_attribute = + (u16) (temp8 & 0x03); + } + + else { + /* BUS_NUMBER_RANGE == Output_struct->Data.Address64.Resource_type */ + /* Nothing needs to be filled in */ + } + } + + /* + * Get Granularity (Bytes 6-13) + */ + buffer += 1; + MOVE_UNALIGNED64_TO_64 (&output_struct->data.address64.granularity, + buffer); + + /* + * Get Min_address_range (Bytes 14-21) + */ + buffer += 8; + MOVE_UNALIGNED64_TO_64 (&output_struct->data.address64.min_address_range, + buffer); + + /* + * Get Max_address_range (Bytes 22-29) + */ + buffer += 8; + MOVE_UNALIGNED64_TO_64 (&output_struct->data.address64.max_address_range, + buffer); + + /* + * Get Address_translation_offset (Bytes 30-37) + */ + buffer += 8; + MOVE_UNALIGNED64_TO_64 (&output_struct->data.address64.address_translation_offset, + buffer); + + /* + * Get Address_length (Bytes 38-45) + */ + buffer += 8; + MOVE_UNALIGNED64_TO_64 (&output_struct->data.address64.address_length, + buffer); + + /* + * Resource Source Index (if present) + */ + buffer += 8; + + /* + * This will leave us pointing to the Resource Source Index + * If it is present, then save it off and calculate the + * pointer to where the null terminated string goes: + * Each Interrupt takes 32-bits + the 5 bytes of the + * stream that are default. + */ + if (*bytes_consumed > 46) { + /* Dereference the Index */ + + temp8 = *buffer; + output_struct->data.address64.resource_source.index = + (u32) temp8; + + /* Point to the String */ + + buffer += 1; + + /* Point the String pointer to the end of this structure */ + + 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; + + /* Copy the string into the buffer */ + + index = 0; + + while (0x00 != *buffer) { + *temp_ptr = *buffer; + + temp_ptr += 1; + buffer += 1; + index += 1; + } + + /* + * Add the terminating null + */ + *temp_ptr = 0x00; + + output_struct->data.address64.resource_source.string_length = index + 1; + + /* + * In order for the Struct_size to fall on a 32-bit boundary, + * calculate the length of the string and expand the + * Struct_size to the next 32-bit boundary. + */ + temp8 = (u8) (index + 1); + struct_size += ROUND_UP_TO_32_bITS (temp8); + } + + else { + output_struct->data.address64.resource_source.index = 0x00; + output_struct->data.address64.resource_source.string_length = 0; + output_struct->data.address64.resource_source.string_ptr = NULL; + } + + /* + * Set the Length parameter + */ + output_struct->length = struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_address64_stream + * + * PARAMETERS: Linked_list - Pointer to the resource linked list + * Output_buffer - Pointer to the user's return buffer + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * Output_buffer used + * + * RETURN: Status + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_address64_stream ( + ACPI_RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed) +{ + u8 *buffer; + u16 *length_field; + u8 temp8; + NATIVE_CHAR *temp_pointer; + + + buffer = *output_buffer; + + /* + * The descriptor field is static + */ + *buffer = 0x8A; + buffer += 1; + + /* + * Set a pointer to the Length field - to be filled in later + */ + + length_field = (u16 *)buffer; + buffer += 2; + + /* + * Set the Resource Type (Memory, Io, Bus_number) + */ + temp8 = (u8) (linked_list->data.address64.resource_type & 0x03); + + *buffer = temp8; + buffer += 1; + + /* + * Set the general flags + */ + temp8 = (u8) (linked_list->data.address64.producer_consumer & 0x01); + temp8 |= (linked_list->data.address64.decode & 0x01) << 1; + temp8 |= (linked_list->data.address64.min_address_fixed & 0x01) << 2; + temp8 |= (linked_list->data.address64.max_address_fixed & 0x01) << 3; + + *buffer = temp8; + buffer += 1; + + /* + * Set the type specific flags + */ + temp8 = 0; + + if(MEMORY_RANGE == linked_list->data.address64.resource_type) { + temp8 = (u8) + (linked_list->data.address64.attribute.memory.read_write_attribute & + 0x01); + + temp8 |= + (linked_list->data.address64.attribute.memory.cache_attribute & + 0x0F) << 1; + } + + else if (IO_RANGE == linked_list->data.address64.resource_type) { + temp8 = (u8) + (linked_list->data.address64.attribute.io.range_attribute & + 0x03); + } + + *buffer = temp8; + buffer += 1; + + /* + * Set the address space granularity + */ + MOVE_UNALIGNED64_TO_64 (buffer, + &linked_list->data.address64.granularity); + buffer += 8; + + /* + * Set the address range minimum + */ + MOVE_UNALIGNED64_TO_64 (buffer, + &linked_list->data.address64.min_address_range); + buffer += 8; + /* + * Set the address range maximum + */ + MOVE_UNALIGNED64_TO_64 (buffer, + &linked_list->data.address64.max_address_range); + buffer += 8; + + /* + * Set the address translation offset + */ + MOVE_UNALIGNED64_TO_64 (buffer, + &linked_list->data.address64.address_translation_offset); + buffer += 8; + + /* + * Set the address length + */ + MOVE_UNALIGNED64_TO_64 (buffer, + &linked_list->data.address64.address_length); + buffer += 8; + + /* + * Resource Source Index and Resource Source are optional + */ + if (0 != linked_list->data.address64.resource_source.string_length) { + temp8 = (u8) linked_list->data.address64.resource_source.index; + + *buffer = temp8; + buffer += 1; + + temp_pointer = (NATIVE_CHAR *) buffer; + + /* + * Copy the string + */ + STRCPY (temp_pointer, linked_list->data.address64.resource_source.string_ptr); + + /* + * Buffer needs to be set to the length of the sting + one for the + * terminating null + */ + buffer += (STRLEN (linked_list->data.address64.resource_source.string_ptr) + 1); + } + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = POINTER_DIFF (buffer, *output_buffer); + + /* + * Set the length field to the number of bytes consumed + * minus the header size (3 bytes) + */ + *length_field = (u16) (*bytes_consumed - 3); return (AE_OK); } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/resources/rscalc.c linux/drivers/acpi/resources/rscalc.c --- v2.4.5/linux/drivers/acpi/resources/rscalc.c Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/resources/rscalc.c Wed Jun 20 17:47:40 2001 @@ -1,8 +1,7 @@ /******************************************************************************* * - * Module Name: rscalc - Acpi_rs_calculate_byte_stream_length - * Acpi_rs_calculate_list_length - * $Revision: 21 $ + * Module Name: rscalc - Calculate stream and list lengths + * $Revision: 30 $ * ******************************************************************************/ @@ -30,7 +29,7 @@ #include "amlcode.h" #include "acnamesp.h" -#define _COMPONENT RESOURCE_MANAGER +#define _COMPONENT ACPI_RESOURCES MODULE_NAME ("rscalc") @@ -40,9 +39,9 @@ * * PARAMETERS: Linked_list - Pointer to the resource linked list * Size_needed - u32 pointer of the size buffer needed - * to properly return the parsed data + * to properly return the parsed data * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Takes the resource byte stream and parses it once, calculating * the size buffer needed to hold the linked list that conveys @@ -52,214 +51,195 @@ ACPI_STATUS acpi_rs_calculate_byte_stream_length ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u32 *size_needed) { u32 byte_stream_size_needed = 0; u32 segment_size; - EXTENDED_IRQ_RESOURCE *ex_irq = NULL; + ACPI_RESOURCE_EXT_IRQ *ex_irq = NULL; u8 done = FALSE; while (!done) { - /* - * Init the variable that will hold the size to add to the - * total. + * Init the variable that will hold the size to add to the total. */ segment_size = 0; - switch (linked_list->id) - { - case irq: + switch (linked_list->id) { + case ACPI_RSTYPE_IRQ: /* * IRQ Resource - */ - /* * For an IRQ Resource, Byte 3, although optional, will - * always be created - it holds IRQ information. + * always be created - it holds IRQ information. */ segment_size = 4; break; - case dma: + case ACPI_RSTYPE_DMA: /* * DMA Resource - */ - /* * For this resource the size is static */ segment_size = 3; break; - case start_dependent_functions: + case ACPI_RSTYPE_START_DPF: /* * Start Dependent Functions Resource - */ - /* * For a Start_dependent_functions Resource, Byte 1, * although optional, will always be created. */ segment_size = 2; break; - case end_dependent_functions: + case ACPI_RSTYPE_END_DPF: /* * End Dependent Functions Resource - */ - /* * For this resource the size is static */ segment_size = 1; break; - case io: + case ACPI_RSTYPE_IO: /* * IO Port Resource - */ - /* * For this resource the size is static */ segment_size = 8; break; - case fixed_io: + case ACPI_RSTYPE_FIXED_IO: /* * Fixed IO Port Resource - */ - /* * For this resource the size is static */ segment_size = 4; break; - case vendor_specific: + case ACPI_RSTYPE_VENDOR: /* * Vendor Defined Resource - */ - /* * For a Vendor Specific resource, if the Length is - * between 1 and 7 it will be created as a Small - * Resource data type, otherwise it is a Large - * Resource data type. + * between 1 and 7 it will be created as a Small + * Resource data type, otherwise it is a Large + * Resource data type. */ - if(linked_list->data.vendor_specific.length > 7) { + if (linked_list->data.vendor_specific.length > 7) { segment_size = 3; } else { segment_size = 1; } - segment_size += - linked_list->data.vendor_specific.length; + segment_size += linked_list->data.vendor_specific.length; break; - case end_tag: + case ACPI_RSTYPE_END_TAG: /* * End Tag - */ - /* * For this resource the size is static */ segment_size = 2; done = TRUE; break; - case memory24: + case ACPI_RSTYPE_MEM24: /* * 24-Bit Memory Resource - */ - /* * For this resource the size is static */ segment_size = 12; break; - case memory32: + case ACPI_RSTYPE_MEM32: /* * 32-Bit Memory Range Resource - */ - /* * For this resource the size is static */ segment_size = 20; break; - case fixed_memory32: + case ACPI_RSTYPE_FIXED_MEM32: /* * 32-Bit Fixed Memory Resource - */ - /* * For this resource the size is static */ segment_size = 12; break; - case address16: + case ACPI_RSTYPE_ADDRESS16: /* * 16-Bit Address Resource - */ - /* * The base size of this byte stream is 16. If a - * Resource Source string is not NULL, add 1 for - * the Index + the length of the null terminated - * string Resource Source + 1 for the null. + * Resource Source string is not NULL, add 1 for + * the Index + the length of the null terminated + * string Resource Source + 1 for the null. */ segment_size = 16; - if(NULL != linked_list->data.address16.resource_source) { + if (NULL != linked_list->data.address16.resource_source.string_ptr) { segment_size += (1 + - linked_list->data.address16.resource_source_string_length); + linked_list->data.address16.resource_source.string_length); } break; - case address32: + case ACPI_RSTYPE_ADDRESS32: /* * 32-Bit Address Resource - */ - /* * The base size of this byte stream is 26. If a Resource - * Source string is not NULL, add 1 for the Index + the - * length of the null terminated string Resource Source + - * 1 for the null. + * Source string is not NULL, add 1 for the Index + the + * length of the null terminated string Resource Source + + * 1 for the null. */ segment_size = 26; - if(NULL != linked_list->data.address16.resource_source) { + if (NULL != linked_list->data.address32.resource_source.string_ptr) { segment_size += (1 + - linked_list->data.address16.resource_source_string_length); + linked_list->data.address32.resource_source.string_length); } break; - case extended_irq: + case ACPI_RSTYPE_ADDRESS64: /* - * Extended IRQ Resource + * 64-Bit Address Resource + * The base size of this byte stream is 46. If a Resource + * Source string is not NULL, add 1 for the Index + the + * length of the null terminated string Resource Source + + * 1 for the null. */ + segment_size = 46; + + if (NULL != linked_list->data.address64.resource_source.string_ptr) { + segment_size += (1 + + linked_list->data.address64.resource_source.string_length); + } + break; + + case ACPI_RSTYPE_EXT_IRQ: /* + * Extended IRQ Resource * The base size of this byte stream is 9. This is for an - * Interrupt table length of 1. For each additional - * interrupt, add 4. + * Interrupt table length of 1. For each additional + * interrupt, add 4. * If a Resource Source string is not NULL, add 1 for the - * Index + the length of the null terminated string - * Resource Source + 1 for the null. + * Index + the length of the null terminated string + * Resource Source + 1 for the null. */ - segment_size = 9; + segment_size = 9 + + ((linked_list->data.extended_irq.number_of_interrupts - 1) * 4); - segment_size += - (linked_list->data.extended_irq.number_of_interrupts - - 1) * 4; - - if(NULL != ex_irq->resource_source) { + if (NULL != ex_irq->resource_source.string_ptr) { segment_size += (1 + - linked_list->data.extended_irq.resource_source_string_length); + linked_list->data.extended_irq.resource_source.string_length); } break; default: /* * If we get here, everything is out of sync, - * so exit with an error + * so exit with an error */ - return (AE_AML_ERROR); + return (AE_AML_INVALID_RESOURCE_TYPE); break; } /* switch (Linked_list->Id) */ @@ -272,15 +252,14 @@ /* * Point to the next object */ - linked_list = (RESOURCE *) ((NATIVE_UINT) linked_list + - (NATIVE_UINT) linked_list->length); + linked_list = POINTER_ADD (ACPI_RESOURCE, + linked_list, linked_list->length); } /* * This is the data the caller needs */ *size_needed = byte_stream_size_needed; - return (AE_OK); } @@ -292,10 +271,10 @@ * PARAMETERS: Byte_stream_buffer - Pointer to the resource byte stream * Byte_stream_buffer_length - Size of Byte_stream_buffer * Size_needed - u32 pointer of the size buffer - * needed to properly return the - * parsed data + * needed to properly return the + * parsed data * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Takes the resource byte stream and parses it once, calculating * the size buffer needed to hold the linked list that conveys @@ -325,402 +304,383 @@ while (bytes_parsed < byte_stream_buffer_length) { /* - * Look at the next byte in the stream + * The next byte in the stream is the resource type */ - resource_type = *byte_stream_buffer; + resource_type = acpi_rs_get_resource_type (*byte_stream_buffer); - /* - * See if this is a small or large resource - */ - if(resource_type & 0x80) { + switch (resource_type) { + case RESOURCE_DESC_MEMORY_24: /* - * Large Resource Type + * 24-Bit Memory Resource */ - switch (resource_type) - { - case MEMORY_RANGE_24: - /* - * 24-Bit Memory Resource - */ - bytes_consumed = 12; + bytes_consumed = 12; - structure_size = sizeof (MEMORY24_RESOURCE) + - RESOURCE_LENGTH_NO_DATA; - break; + structure_size = SIZEOF_RESOURCE (ACPI_RESOURCE_MEM24); + break; - case LARGE_VENDOR_DEFINED: - /* - * Vendor Defined Resource - */ - buffer = byte_stream_buffer; - ++buffer; - MOVE_UNALIGNED16_TO_16 (&temp16, buffer); - bytes_consumed = temp16 + 3; + case RESOURCE_DESC_LARGE_VENDOR: + /* + * Vendor Defined Resource + */ + buffer = byte_stream_buffer; + ++buffer; - /* - * Ensure a 32-bit boundary for the structure - */ - temp16 = (u16) ROUND_UP_TO_32_bITS (temp16); + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + bytes_consumed = temp16 + 3; - structure_size = sizeof (VENDOR_RESOURCE) + - RESOURCE_LENGTH_NO_DATA + - (temp16 * sizeof (u8)); - break; + /* + * Ensure a 32-bit boundary for the structure + */ + temp16 = (u16) ROUND_UP_TO_32_bITS (temp16); - case MEMORY_RANGE_32: - /* - * 32-Bit Memory Range Resource - */ + structure_size = SIZEOF_RESOURCE (ACPI_RESOURCE_VENDOR) + + (temp16 * sizeof (u8)); + break; - bytes_consumed = 20; - structure_size = sizeof (MEMORY32_RESOURCE) + - RESOURCE_LENGTH_NO_DATA; - break; + case RESOURCE_DESC_MEMORY_32: + /* + * 32-Bit Memory Range Resource + */ - case FIXED_MEMORY_RANGE_32: - /* - * 32-Bit Fixed Memory Resource - */ - bytes_consumed = 12; + bytes_consumed = 20; - structure_size = sizeof(FIXED_MEMORY32_RESOURCE) + - RESOURCE_LENGTH_NO_DATA; - break; + structure_size = SIZEOF_RESOURCE (ACPI_RESOURCE_MEM32); + break; - case DWORD_ADDRESS_SPACE: - /* - * 32-Bit Address Resource - */ - buffer = byte_stream_buffer; - ++buffer; - MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + case RESOURCE_DESC_FIXED_MEMORY_32: + /* + * 32-Bit Fixed Memory Resource + */ + bytes_consumed = 12; - bytes_consumed = temp16 + 3; + structure_size = SIZEOF_RESOURCE (ACPI_RESOURCE_FIXED_MEM32); + break; - /* - * Resource Source Index and Resource Source are - * optional elements. Check the length of the - * Bytestream. If it is greater than 23, that - * means that an Index exists and is followed by - * a null termininated string. Therefore, set - * the temp variable to the length minus the minimum - * byte stream length plus the byte for the Index to - * determine the size of the NULL terminiated string. - */ - if (23 < temp16) { - temp8 = (u8) (temp16 - 24); - } - else { - temp8 = 0; - } - /* - * Ensure a 32-bit boundary for the structure - */ - temp8 = (u8) ROUND_UP_TO_32_bITS (temp8); + case RESOURCE_DESC_QWORD_ADDRESS_SPACE: + /* + * 64-Bit Address Resource + */ + buffer = byte_stream_buffer; - structure_size = sizeof (ADDRESS32_RESOURCE) + - RESOURCE_LENGTH_NO_DATA + - (temp8 * sizeof (u8)); - break; + ++buffer; + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); - case WORD_ADDRESS_SPACE: - /* - * 16-Bit Address Resource - */ - buffer = byte_stream_buffer; + bytes_consumed = temp16 + 3; - ++buffer; - MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + /* + * Resource Source Index and Resource Source are + * optional elements. Check the length of the + * Bytestream. If it is greater than 43, that + * means that an Index exists and is followed by + * a null termininated string. Therefore, set + * the temp variable to the length minus the minimum + * byte stream length plus the byte for the Index to + * determine the size of the NULL terminiated string. + */ + if (43 < temp16) { + temp8 = (u8) (temp16 - 44); + } + else { + temp8 = 0; + } - bytes_consumed = temp16 + 3; + /* + * Ensure a 64-bit boundary for the structure + */ + temp8 = (u8) ROUND_UP_TO_64_bITS (temp8); - /* - * Resource Source Index and Resource Source are - * optional elements. Check the length of the - * Bytestream. If it is greater than 13, that - * means that an Index exists and is followed by - * a null termininated string. Therefore, set - * the temp variable to the length minus the minimum - * byte stream length plus the byte for the Index to - * determine the size of the NULL terminiated string. - */ - if (13 < temp16) { - temp8 = (u8) (temp16 - 14); - } - else { - temp8 = 0; - } + structure_size = SIZEOF_RESOURCE (ACPI_RESOURCE_ADDRESS64) + + (temp8 * sizeof (u8)); + break; - /* - * Ensure a 32-bit boundry for the structure - */ - temp8 = (u8) ROUND_UP_TO_32_bITS (temp8); - structure_size = sizeof (ADDRESS16_RESOURCE) + - RESOURCE_LENGTH_NO_DATA + - (temp8 * sizeof (u8)); - break; + case RESOURCE_DESC_DWORD_ADDRESS_SPACE: + /* + * 32-Bit Address Resource + */ + buffer = byte_stream_buffer; - case EXTENDED_IRQ: - /* - * Extended IRQ - */ - buffer = byte_stream_buffer; + ++buffer; + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); - ++buffer; - MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + bytes_consumed = temp16 + 3; - bytes_consumed = temp16 + 3; + /* + * Resource Source Index and Resource Source are + * optional elements. Check the length of the + * Bytestream. If it is greater than 23, that + * means that an Index exists and is followed by + * a null termininated string. Therefore, set + * the temp variable to the length minus the minimum + * byte stream length plus the byte for the Index to + * determine the size of the NULL terminiated string. + */ + if (23 < temp16) { + temp8 = (u8) (temp16 - 24); + } + else { + temp8 = 0; + } - /* - * Point past the length field and the - * Interrupt vector flags to save off the - * Interrupt table length to the Temp8 variable. - */ - buffer += 3; - temp8 = *buffer; + /* + * Ensure a 32-bit boundary for the structure + */ + temp8 = (u8) ROUND_UP_TO_32_bITS (temp8); - /* - * To compensate for multiple interrupt numbers, - * Add 4 bytes for each additional interrupts - * greater than 1 - */ - additional_bytes = (u8) ((temp8 - 1) * 4); + structure_size = SIZEOF_RESOURCE (ACPI_RESOURCE_ADDRESS32) + + (temp8 * sizeof (u8)); + break; - /* - * Resource Source Index and Resource Source are - * optional elements. Check the length of the - * Bytestream. If it is greater than 9, that - * means that an Index exists and is followed by - * a null termininated string. Therefore, set - * the temp variable to the length minus the minimum - * byte stream length plus the byte for the Index to - * determine the size of the NULL terminiated string. - */ - if (9 + additional_bytes < temp16) { - temp8 = (u8) (temp16 - (9 + additional_bytes)); - } - else { - temp8 = 0; - } + case RESOURCE_DESC_WORD_ADDRESS_SPACE: + /* + * 16-Bit Address Resource + */ + buffer = byte_stream_buffer; - /* - * Ensure a 32-bit boundry for the structure - */ - temp8 = (u8) ROUND_UP_TO_32_bITS (temp8); + ++buffer; + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); - structure_size = sizeof (EXTENDED_IRQ_RESOURCE) + - RESOURCE_LENGTH_NO_DATA + - (additional_bytes * sizeof (u8)) + - (temp8 * sizeof (u8)); + bytes_consumed = temp16 + 3; - break; + /* + * Resource Source Index and Resource Source are + * optional elements. Check the length of the + * Bytestream. If it is greater than 13, that + * means that an Index exists and is followed by + * a null termininated string. Therefore, set + * the temp variable to the length minus the minimum + * byte stream length plus the byte for the Index to + * determine the size of the NULL terminiated string. + */ + if (13 < temp16) { + temp8 = (u8) (temp16 - 14); + } + else { + temp8 = 0; + } -/* TBD: [Future] 64-bit not currently supported */ -/* - case 0x8A: - break; -*/ + /* + * Ensure a 32-bit boundary for the structure + */ + temp8 = (u8) ROUND_UP_TO_32_bITS (temp8); - default: - /* - * If we get here, everything is out of sync, - * so exit with an error - */ - return (AE_AML_ERROR); - break; - } - } + structure_size = SIZEOF_RESOURCE (ACPI_RESOURCE_ADDRESS16) + + (temp8 * sizeof (u8)); + break; - else { + + case RESOURCE_DESC_EXTENDED_XRUPT: /* - * Small Resource Type - * Only bits 7:3 are valid + * Extended IRQ */ - resource_type >>= 3; + buffer = byte_stream_buffer; - switch (resource_type) - { - case IRQ_FORMAT: - /* - * IRQ Resource - */ - /* - * Determine if it there are two or three - * trailing bytes - */ - buffer = byte_stream_buffer; - temp8 = *buffer; + ++buffer; + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); - if(temp8 & 0x01) { - bytes_consumed = 4; - } + bytes_consumed = temp16 + 3; - else { - bytes_consumed = 3; - } + /* + * Point past the length field and the + * Interrupt vector flags to save off the + * Interrupt table length to the Temp8 variable. + */ + buffer += 3; + temp8 = *buffer; - /* - * Point past the descriptor - */ - ++buffer; + /* + * To compensate for multiple interrupt numbers, add 4 bytes for + * each additional interrupts greater than 1 + */ + additional_bytes = (u8) ((temp8 - 1) * 4); - /* - * Look at the number of bits set - */ - MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + /* + * Resource Source Index and Resource Source are + * optional elements. Check the length of the + * Bytestream. If it is greater than 9, that + * means that an Index exists and is followed by + * a null termininated string. Therefore, set + * the temp variable to the length minus the minimum + * byte stream length plus the byte for the Index to + * determine the size of the NULL terminiated string. + */ + if (9 + additional_bytes < temp16) { + temp8 = (u8) (temp16 - (9 + additional_bytes)); + } - for (index = 0; index < 16; index++) { - if (temp16 & 0x1) { - ++number_of_interrupts; - } + else { + temp8 = 0; + } - temp16 >>= 1; - } + /* + * Ensure a 32-bit boundary for the structure + */ + temp8 = (u8) ROUND_UP_TO_32_bITS (temp8); - structure_size = sizeof (IO_RESOURCE) + - RESOURCE_LENGTH_NO_DATA + - (number_of_interrupts * sizeof (u32)); - break; + structure_size = SIZEOF_RESOURCE (ACPI_RESOURCE_EXT_IRQ) + + (additional_bytes * sizeof (u8)) + + (temp8 * sizeof (u8)); + break; - case DMA_FORMAT: + case RESOURCE_DESC_IRQ_FORMAT: + /* + * IRQ Resource. + * Determine if it there are two or three trailing bytes + */ + buffer = byte_stream_buffer; + temp8 = *buffer; - /* - * DMA Resource - */ - buffer = byte_stream_buffer; + if(temp8 & 0x01) { + bytes_consumed = 4; + } + else { bytes_consumed = 3; + } - /* - * Point past the descriptor - */ - ++buffer; - - /* - * Look at the number of bits set - */ - temp8 = *buffer; + /* + * Point past the descriptor + */ + ++buffer; - for(index = 0; index < 8; index++) { - if(temp8 & 0x1) { - ++number_of_channels; - } + /* + * Look at the number of bits set + */ + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); - temp8 >>= 1; + for (index = 0; index < 16; index++) { + if (temp16 & 0x1) { + ++number_of_interrupts; } - structure_size = sizeof (DMA_RESOURCE) + - RESOURCE_LENGTH_NO_DATA + - (number_of_channels * sizeof (u32)); - break; + temp16 >>= 1; + } + structure_size = SIZEOF_RESOURCE (ACPI_RESOURCE_IO) + + (number_of_interrupts * sizeof (u32)); + break; - case START_DEPENDENT_TAG: - /* - * Start Dependent Functions Resource - */ - /* - * Determine if it there are two or three trailing bytes - */ - buffer = byte_stream_buffer; - temp8 = *buffer; + case RESOURCE_DESC_DMA_FORMAT: + /* + * DMA Resource + */ + buffer = byte_stream_buffer; + bytes_consumed = 3; - if(temp8 & 0x01) { - bytes_consumed = 2; - } - else { - bytes_consumed = 1; + /* + * Point past the descriptor + */ + ++buffer; + + /* + * Look at the number of bits set + */ + temp8 = *buffer; + + for(index = 0; index < 8; index++) { + if(temp8 & 0x1) { + ++number_of_channels; } + temp8 >>= 1; + } - structure_size = - sizeof (START_DEPENDENT_FUNCTIONS_RESOURCE) + - RESOURCE_LENGTH_NO_DATA; - break; + structure_size = SIZEOF_RESOURCE (ACPI_RESOURCE_DMA) + + (number_of_channels * sizeof (u32)); + break; - case END_DEPENDENT_TAG: + case RESOURCE_DESC_START_DEPENDENT: + /* + * Start Dependent Functions Resource + * Determine if it there are two or three trailing bytes + */ + buffer = byte_stream_buffer; + temp8 = *buffer; - /* - * End Dependent Functions Resource - */ + if(temp8 & 0x01) { + bytes_consumed = 2; + } + else { bytes_consumed = 1; - structure_size = RESOURCE_LENGTH; - break; - + } - case IO_PORT_DESCRIPTOR: - /* - * IO Port Resource - */ - bytes_consumed = 8; - structure_size = sizeof (IO_RESOURCE) + - RESOURCE_LENGTH_NO_DATA; - break; + structure_size = SIZEOF_RESOURCE (ACPI_RESOURCE_START_DPF); + break; - case FIXED_LOCATION_IO_DESCRIPTOR: + case RESOURCE_DESC_END_DEPENDENT: + /* + * End Dependent Functions Resource + */ + bytes_consumed = 1; + structure_size = ACPI_RESOURCE_LENGTH; + break; - /* - * Fixed IO Port Resource - */ - bytes_consumed = 4; - structure_size = sizeof (FIXED_IO_RESOURCE) + - RESOURCE_LENGTH_NO_DATA; - break; + case RESOURCE_DESC_IO_PORT: + /* + * IO Port Resource + */ + bytes_consumed = 8; + structure_size = SIZEOF_RESOURCE (ACPI_RESOURCE_IO); + break; - case SMALL_VENDOR_DEFINED: - /* - * Vendor Specific Resource - */ - buffer = byte_stream_buffer; + case RESOURCE_DESC_FIXED_IO_PORT: + /* + * Fixed IO Port Resource + */ + bytes_consumed = 4; + structure_size = SIZEOF_RESOURCE (ACPI_RESOURCE_FIXED_IO); + break; - temp8 = *buffer; - temp8 = (u8) (temp8 & 0x7); - bytes_consumed = temp8 + 1; - /* - * Ensure a 32-bit boundry for the structure - */ - temp8 = (u8) ROUND_UP_TO_32_bITS (temp8); - structure_size = sizeof (VENDOR_RESOURCE) + - RESOURCE_LENGTH_NO_DATA + - (temp8 * sizeof (u8)); - break; + case RESOURCE_DESC_SMALL_VENDOR: + /* + * Vendor Specific Resource + */ + buffer = byte_stream_buffer; + temp8 = *buffer; + temp8 = (u8) (temp8 & 0x7); + bytes_consumed = temp8 + 1; - case END_TAG: + /* + * Ensure a 32-bit boundary for the structure + */ + temp8 = (u8) ROUND_UP_TO_32_bITS (temp8); + structure_size = SIZEOF_RESOURCE (ACPI_RESOURCE_VENDOR) + + (temp8 * sizeof (u8)); + break; - /* - * End Tag - */ - bytes_consumed = 2; - structure_size = RESOURCE_LENGTH; - byte_stream_buffer_length = bytes_parsed; - break; + case RESOURCE_DESC_END_TAG: + /* + * End Tag + */ + bytes_consumed = 2; + structure_size = ACPI_RESOURCE_LENGTH; + byte_stream_buffer_length = bytes_parsed; + break; - default: - /* - * If we get here, everything is out of sync, - * so exit with an error - */ - return (AE_AML_ERROR); - break; - } /* switch */ + default: + /* + * If we get here, everything is out of sync, + * so exit with an error + */ + return (AE_AML_INVALID_RESOURCE_TYPE); + break; + } - } /* if(Resource_type & 0x80) */ /* * Update the return value and counter @@ -732,14 +692,13 @@ * Set the byte stream to point to the next resource */ byte_stream_buffer += bytes_consumed; - } + /* * This is the data the caller needs */ *size_needed = buffer_size; - return (AE_OK); } @@ -750,14 +709,14 @@ * * PARAMETERS: Package_object - Pointer to the package object * Buffer_size_needed - u32 pointer of the size buffer - * needed to properly return the - * parsed data + * needed to properly return the + * parsed data * - * RETURN: Status AE_OK + * RETURN: Status * * DESCRIPTION: Given a package representing a PCI routing table, this - * calculates the size of the corresponding linked list of - * descriptions. + * calculates the size of the corresponding linked list of + * descriptions. * ******************************************************************************/ @@ -785,11 +744,6 @@ * The minus one is to subtract the size of the u8 Source[1] * member because it is added below. * - * NOTE: The Number_of_elements is incremented by one to add an end - * table structure that is essentially a structure of zeros. - */ - - /* * But each PRT_ENTRY structure has a pointer to a string and * the size of that string must be found. */ @@ -815,8 +769,7 @@ for (table_index = 0; table_index < 4 && !name_found; table_index++) { if ((ACPI_TYPE_STRING == (*sub_object_list)->common.type) || ((INTERNAL_TYPE_REFERENCE == (*sub_object_list)->common.type) && - ((*sub_object_list)->reference.op_code == AML_NAMEPATH_OP))) - { + ((*sub_object_list)->reference.opcode == AML_INT_NAMEPATH_OP))) { name_found = TRUE; } @@ -841,20 +794,21 @@ */ temp_size_needed += (*sub_object_list)->string.length; } + else { - temp_size_needed += acpi_ns_get_pathname_length ((*sub_object_list)->reference.node); + temp_size_needed += acpi_ns_get_pathname_length ( + (*sub_object_list)->reference.node); } } else { /* * If no name was found, then this is a NULL, which is - * translated as a u32 zero. + * translated as a u32 zero. */ - temp_size_needed += sizeof(u32); + temp_size_needed += sizeof (u32); } - /* Round up the size since each element must be aligned */ temp_size_needed = ROUND_UP_TO_64_bITS (temp_size_needed); @@ -866,7 +820,9 @@ } - *buffer_size_needed = temp_size_needed; - + /* + * Adding an extra element to the end of the list, essentially a NULL terminator + */ + *buffer_size_needed = temp_size_needed + sizeof (PCI_ROUTING_TABLE); return (AE_OK); } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/resources/rscreate.c linux/drivers/acpi/resources/rscreate.c --- v2.4.5/linux/drivers/acpi/resources/rscreate.c Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/resources/rscreate.c Wed Jun 20 17:47:40 2001 @@ -1,9 +1,7 @@ /******************************************************************************* * - * Module Name: rscreate - Acpi_rs_create_resource_list - * Acpi_rs_create_pci_routing_table - * Acpi_rs_create_byte_stream - * $Revision: 25 $ + * Module Name: rscreate - Create resource lists/tables + * $Revision: 33 $ * ******************************************************************************/ @@ -31,7 +29,7 @@ #include "amlcode.h" #include "acnamesp.h" -#define _COMPONENT RESOURCE_MANAGER +#define _COMPONENT ACPI_RESOURCES MODULE_NAME ("rscreate") @@ -39,8 +37,7 @@ * * FUNCTION: Acpi_rs_create_resource_list * - * PARAMETERS: - * Byte_stream_buffer - Pointer to the resource byte stream + * PARAMETERS: Byte_stream_buffer - Pointer to the resource byte stream * Output_buffer - Pointer to the user's buffer * Output_buffer_length - Pointer to the size of Output_buffer * @@ -63,9 +60,9 @@ { ACPI_STATUS status; - u8 *byte_stream_start = NULL; + u8 *byte_stream_start; u32 list_size_needed = 0; - u32 byte_stream_buffer_length = 0; + u32 byte_stream_buffer_length; /* @@ -79,8 +76,7 @@ * 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_calculate_list_length (byte_stream_start, byte_stream_buffer_length, &list_size_needed); /* @@ -101,8 +97,7 @@ */ MEMSET (output_buffer, 0x00, *output_buffer_length); - status = acpi_rs_byte_stream_to_list (byte_stream_start, - byte_stream_buffer_length, + status = acpi_rs_byte_stream_to_list (byte_stream_start, byte_stream_buffer_length, &output_buffer); /* @@ -121,7 +116,6 @@ *output_buffer_length = list_size_needed; return (AE_OK); - } @@ -129,9 +123,8 @@ * * FUNCTION: Acpi_rs_create_pci_routing_table * - * PARAMETERS: - * Package_object - Pointer to an ACPI_OPERAND_OBJECT - * package + * PARAMETERS: Package_object - Pointer to an ACPI_OPERAND_OBJECT + * package * Output_buffer - Pointer to the user's buffer * Output_buffer_length - Size of Output_buffer * @@ -167,8 +160,12 @@ * Params already validated, so we don't re-validate here */ - status = acpi_rs_calculate_pci_routing_table_length(package_object, - &buffer_size_needed); + status = acpi_rs_calculate_pci_routing_table_length (package_object, + &buffer_size_needed); + + if (!ACPI_SUCCESS(status)) { + return (status); + } /* * If the data will fit into the available buffer @@ -240,8 +237,7 @@ sub_object_list++; if (ACPI_TYPE_INTEGER == (*sub_object_list)->common.type) { - user_prt->pin = - (u32) (*sub_object_list)->integer.value; + user_prt->pin = (u32) (*sub_object_list)->integer.value; } else { @@ -253,10 +249,10 @@ */ sub_object_list++; - switch ((*sub_object_list)->common.type) - { + switch ((*sub_object_list)->common.type) { case INTERNAL_TYPE_REFERENCE: - if ((*sub_object_list)->reference.op_code != AML_NAMEPATH_OP) { + + if ((*sub_object_list)->reference.opcode != AML_INT_NAMEPATH_OP) { return (AE_BAD_DATA); } @@ -298,6 +294,7 @@ default: + return (AE_BAD_DATA); break; } @@ -312,8 +309,7 @@ sub_object_list++; if (ACPI_TYPE_INTEGER == (*sub_object_list)->common.type) { - user_prt->source_index = - (u32) (*sub_object_list)->integer.value; + user_prt->source_index = (u32) (*sub_object_list)->integer.value; } else { @@ -338,7 +334,6 @@ * Report the amount of buffer used */ *output_buffer_length = buffer_size_needed; - return (AE_OK); } @@ -347,8 +342,7 @@ * * FUNCTION: Acpi_rs_create_byte_stream * - * PARAMETERS: - * Linked_list_buffer - Pointer to the resource linked list + * PARAMETERS: Linked_list_buffer - Pointer to the resource linked list * Output_buffer - Pointer to the user's buffer * Output_buffer_length - Size of Output_buffer * @@ -365,7 +359,7 @@ ACPI_STATUS acpi_rs_create_byte_stream ( - RESOURCE *linked_list_buffer, + ACPI_RESOURCE *linked_list_buffer, u8 *output_buffer, u32 *output_buffer_length) { @@ -400,8 +394,7 @@ */ MEMSET (output_buffer, 0x00, *output_buffer_length); - status = acpi_rs_list_to_byte_stream (linked_list_buffer, - byte_stream_size_needed, + status = acpi_rs_list_to_byte_stream (linked_list_buffer, byte_stream_size_needed, &output_buffer); /* @@ -412,6 +405,7 @@ } } + else { *output_buffer_length = byte_stream_size_needed; return (AE_BUFFER_OVERFLOW); diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/resources/rsdump.c linux/drivers/acpi/resources/rsdump.c --- v2.4.5/linux/drivers/acpi/resources/rsdump.c Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/resources/rsdump.c Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /******************************************************************************* * - * Module Name: rsdump - Functions do dump out the resource structures. - * $Revision: 16 $ + * Module Name: rsdump - Functions to display the resource structures. + * $Revision: 20 $ * ******************************************************************************/ @@ -27,7 +27,7 @@ #include "acpi.h" #include "acresrc.h" -#define _COMPONENT RESOURCE_MANAGER +#define _COMPONENT ACPI_RESOURCES MODULE_NAME ("rsdump") @@ -37,7 +37,7 @@ * * PARAMETERS: Data - pointer to the resource structure to dump. * - * RETURN: + * RETURN: None * * DESCRIPTION: Prints out the various members of the Data structure type. * @@ -45,28 +45,24 @@ void acpi_rs_dump_irq ( - RESOURCE_DATA *data) + ACPI_RESOURCE_DATA *data) { - IRQ_RESOURCE *irq_data = (IRQ_RESOURCE*) data; + ACPI_RESOURCE_IRQ *irq_data = (ACPI_RESOURCE_IRQ *) data; u8 index = 0; - acpi_os_printf ("\t_iRQ Resource\n"); + acpi_os_printf ("IRQ Resource\n"); - acpi_os_printf ("\t\t%s Triggered\n", - LEVEL_SENSITIVE == irq_data->edge_level ? - "Level" : "Edge"); + acpi_os_printf (" %s Triggered\n", + LEVEL_SENSITIVE == irq_data->edge_level ? "Level" : "Edge"); - acpi_os_printf ("\t\t_active %s\n", - ACTIVE_LOW == irq_data->active_high_low ? - "Low" : "High"); + acpi_os_printf (" Active %s\n", + ACTIVE_LOW == irq_data->active_high_low ? "Low" : "High"); - acpi_os_printf ("\t\t%s\n", - SHARED == irq_data->shared_exclusive ? - "Shared" : "Exclusive"); + acpi_os_printf (" %s\n", + SHARED == irq_data->shared_exclusive ? "Shared" : "Exclusive"); - acpi_os_printf ("\t\t%X Interrupts ( ", - irq_data->number_of_interrupts); + acpi_os_printf (" %X Interrupts ( ", irq_data->number_of_interrupts); for (index = 0; index < irq_data->number_of_interrupts; index++) { acpi_os_printf ("%X ", irq_data->interrupts[index]); @@ -83,7 +79,7 @@ * * PARAMETERS: Data - pointer to the resource structure to dump. * - * RETURN: + * RETURN: None * * DESCRIPTION: Prints out the various members of the Data structure type. * @@ -91,62 +87,59 @@ void acpi_rs_dump_dma ( - RESOURCE_DATA *data) + ACPI_RESOURCE_DATA *data) { - DMA_RESOURCE *dma_data = (DMA_RESOURCE*) data; + ACPI_RESOURCE_DMA *dma_data = (ACPI_RESOURCE_DMA *) data; u8 index = 0; - acpi_os_printf ("\t_dMA Resource\n"); + acpi_os_printf ("DMA Resource\n"); - switch (dma_data->type) - { + switch (dma_data->type) { case COMPATIBILITY: - acpi_os_printf ("\t\t_compatibility mode\n"); + acpi_os_printf (" Compatibility mode\n"); break; case TYPE_A: - acpi_os_printf ("\t\t_type A\n"); + acpi_os_printf (" Type A\n"); break; case TYPE_B: - acpi_os_printf ("\t\t_type B\n"); + acpi_os_printf (" Type B\n"); break; case TYPE_F: - acpi_os_printf ("\t\t_type F\n"); + acpi_os_printf (" Type F\n"); break; default: - acpi_os_printf ("\t\t_invalid DMA type\n"); + acpi_os_printf (" Invalid DMA type\n"); break; } - acpi_os_printf ("\t\t%sBus Master\n", - BUS_MASTER == dma_data->bus_master ? - "" : "Not a "); + acpi_os_printf (" %sBus Master\n", + BUS_MASTER == dma_data->bus_master ? "" : "Not a "); - switch (dma_data->transfer) - { + + switch (dma_data->transfer) { case TRANSFER_8: - acpi_os_printf ("\t\t8-bit only transfer\n"); + acpi_os_printf (" 8-bit only transfer\n"); break; case TRANSFER_8_16: - acpi_os_printf ("\t\t8 and 16-bit transfer\n"); + acpi_os_printf (" 8 and 16-bit transfer\n"); break; case TRANSFER_16: - acpi_os_printf ("\t\t16 bit only transfer\n"); + acpi_os_printf (" 16 bit only transfer\n"); break; default: - acpi_os_printf ("\t\t_invalid transfer preference\n"); + acpi_os_printf (" Invalid transfer preference\n"); break; } - acpi_os_printf ("\t\t_number of Channels: %X ( ", - dma_data->number_of_channels); + acpi_os_printf (" Number of Channels: %X ( ", dma_data->number_of_channels); for (index = 0; index < dma_data->number_of_channels; index++) { acpi_os_printf ("%X ", dma_data->channels[index]); @@ -163,7 +156,7 @@ * * PARAMETERS: Data - pointer to the resource structure to dump. * - * RETURN: + * RETURN: None * * DESCRIPTION: Prints out the various members of the Data structure type. * @@ -171,49 +164,47 @@ void acpi_rs_dump_start_dependent_functions ( - RESOURCE_DATA *data) + ACPI_RESOURCE_DATA *data) { - START_DEPENDENT_FUNCTIONS_RESOURCE *sdf_data = - (START_DEPENDENT_FUNCTIONS_RESOURCE*) data; + ACPI_RESOURCE_START_DPF *sdf_data = (ACPI_RESOURCE_START_DPF *) data; + + acpi_os_printf ("Start Dependent Functions Resource\n"); - acpi_os_printf ("\t_start Dependent Functions Resource\n"); - switch (sdf_data->compatibility_priority) - { + switch (sdf_data->compatibility_priority) { case GOOD_CONFIGURATION: - acpi_os_printf ("\t\t_good configuration\n"); + acpi_os_printf (" Good configuration\n"); break; case ACCEPTABLE_CONFIGURATION: - acpi_os_printf ("\t\t_acceptable configuration\n"); + acpi_os_printf (" Acceptable configuration\n"); break; case SUB_OPTIMAL_CONFIGURATION: - acpi_os_printf ("\t\t_sub-optimal configuration\n"); + acpi_os_printf (" Sub-optimal configuration\n"); break; default: - acpi_os_printf ("\t\t_invalid compatibility priority\n"); + acpi_os_printf (" Invalid compatibility priority\n"); break; } - switch(sdf_data->performance_robustness) - { + switch(sdf_data->performance_robustness) { case GOOD_CONFIGURATION: - acpi_os_printf ("\t\t_good configuration\n"); + acpi_os_printf (" Good configuration\n"); break; case ACCEPTABLE_CONFIGURATION: - acpi_os_printf ("\t\t_acceptable configuration\n"); + acpi_os_printf (" Acceptable configuration\n"); break; case SUB_OPTIMAL_CONFIGURATION: - acpi_os_printf ("\t\t_sub-optimal configuration\n"); + acpi_os_printf (" Sub-optimal configuration\n"); break; default: - acpi_os_printf ("\t\t_invalid performance " + acpi_os_printf (" Invalid performance " "robustness preference\n"); break; } @@ -228,7 +219,7 @@ * * PARAMETERS: Data - pointer to the resource structure to dump. * - * RETURN: + * RETURN: None * * DESCRIPTION: Prints out the various members of the Data structure type. * @@ -236,26 +227,26 @@ void acpi_rs_dump_io ( - RESOURCE_DATA *data) + ACPI_RESOURCE_DATA *data) { - IO_RESOURCE *io_data = (IO_RESOURCE*) data; + ACPI_RESOURCE_IO *io_data = (ACPI_RESOURCE_IO *) data; - acpi_os_printf ("\t_io Resource\n"); + acpi_os_printf ("Io Resource\n"); - acpi_os_printf ("\t\t%d bit decode\n", + acpi_os_printf (" %d bit decode\n", DECODE_16 == io_data->io_decode ? 16 : 10); - acpi_os_printf ("\t\t_range minimum base: %08X\n", + acpi_os_printf (" Range minimum base: %08X\n", io_data->min_base_address); - acpi_os_printf ("\t\t_range maximum base: %08X\n", + acpi_os_printf (" Range maximum base: %08X\n", io_data->max_base_address); - acpi_os_printf ("\t\t_alignment: %08X\n", + acpi_os_printf (" Alignment: %08X\n", io_data->alignment); - acpi_os_printf ("\t\t_range Length: %08X\n", + acpi_os_printf (" Range Length: %08X\n", io_data->range_length); return; @@ -268,7 +259,7 @@ * * PARAMETERS: Data - pointer to the resource structure to dump. * - * RETURN: + * RETURN: None * * DESCRIPTION: Prints out the various members of the Data structure type. * @@ -276,16 +267,16 @@ void acpi_rs_dump_fixed_io ( - RESOURCE_DATA *data) + ACPI_RESOURCE_DATA *data) { - FIXED_IO_RESOURCE *fixed_io_data = (FIXED_IO_RESOURCE*) data; + ACPI_RESOURCE_FIXED_IO *fixed_io_data = (ACPI_RESOURCE_FIXED_IO *) data; - acpi_os_printf ("\t_fixed Io Resource\n"); - acpi_os_printf ("\t\t_range base address: %08X", + acpi_os_printf ("Fixed Io Resource\n"); + acpi_os_printf (" Range base address: %08X", fixed_io_data->base_address); - acpi_os_printf ("\t\t_range length: %08X", + acpi_os_printf (" Range length: %08X", fixed_io_data->range_length); return; @@ -298,7 +289,7 @@ * * PARAMETERS: Data - pointer to the resource structure to dump. * - * RETURN: + * RETURN: None * * DESCRIPTION: Prints out the various members of the Data structure type. * @@ -306,18 +297,18 @@ void acpi_rs_dump_vendor_specific ( - RESOURCE_DATA *data) + ACPI_RESOURCE_DATA *data) { - VENDOR_RESOURCE *vendor_data = (VENDOR_RESOURCE*) data; + ACPI_RESOURCE_VENDOR *vendor_data = (ACPI_RESOURCE_VENDOR *) data; u16 index = 0; - acpi_os_printf ("\t_vendor Specific Resource\n"); + acpi_os_printf ("Vendor Specific Resource\n"); - acpi_os_printf ("\t\t_length: %08X\n", vendor_data->length); + acpi_os_printf (" Length: %08X\n", vendor_data->length); for (index = 0; index < vendor_data->length; index++) { - acpi_os_printf ("\t\t_byte %X: %08X\n", + acpi_os_printf (" Byte %X: %08X\n", index, vendor_data->reserved[index]); } @@ -331,7 +322,7 @@ * * PARAMETERS: Data - pointer to the resource structure to dump. * - * RETURN: + * RETURN: None * * DESCRIPTION: Prints out the various members of the Data structure type. * @@ -339,28 +330,28 @@ void acpi_rs_dump_memory24 ( - RESOURCE_DATA *data) + ACPI_RESOURCE_DATA *data) { - MEMORY24_RESOURCE *memory24_data = (MEMORY24_RESOURCE*) data; + ACPI_RESOURCE_MEM24 *memory24_data = (ACPI_RESOURCE_MEM24 *) data; - acpi_os_printf ("\t24-Bit Memory Range Resource\n"); + acpi_os_printf ("24-Bit Memory Range Resource\n"); - acpi_os_printf ("\t\t_read%s\n", + acpi_os_printf (" Read%s\n", READ_WRITE_MEMORY == memory24_data->read_write_attribute ? "/Write" : " only"); - acpi_os_printf ("\t\t_range minimum base: %08X\n", + acpi_os_printf (" Range minimum base: %08X\n", memory24_data->min_base_address); - acpi_os_printf ("\t\t_range maximum base: %08X\n", + acpi_os_printf (" Range maximum base: %08X\n", memory24_data->max_base_address); - acpi_os_printf ("\t\t_alignment: %08X\n", + acpi_os_printf (" Alignment: %08X\n", memory24_data->alignment); - acpi_os_printf ("\t\t_range length: %08X\n", + acpi_os_printf (" Range length: %08X\n", memory24_data->range_length); return; @@ -373,7 +364,7 @@ * * PARAMETERS: Data - pointer to the resource structure to dump. * - * RETURN: + * RETURN: None * * DESCRIPTION: Prints out the various members of the Data structure type. * @@ -381,28 +372,28 @@ void acpi_rs_dump_memory32 ( - RESOURCE_DATA *data) + ACPI_RESOURCE_DATA *data) { - MEMORY32_RESOURCE *memory32_data = (MEMORY32_RESOURCE*) data; + ACPI_RESOURCE_MEM32 *memory32_data = (ACPI_RESOURCE_MEM32 *) data; - acpi_os_printf ("\t32-Bit Memory Range Resource\n"); + acpi_os_printf ("32-Bit Memory Range Resource\n"); - acpi_os_printf ("\t\t_read%s\n", + acpi_os_printf (" Read%s\n", READ_WRITE_MEMORY == memory32_data->read_write_attribute ? "/Write" : " only"); - acpi_os_printf ("\t\t_range minimum base: %08X\n", + acpi_os_printf (" Range minimum base: %08X\n", memory32_data->min_base_address); - acpi_os_printf ("\t\t_range maximum base: %08X\n", + acpi_os_printf (" Range maximum base: %08X\n", memory32_data->max_base_address); - acpi_os_printf ("\t\t_alignment: %08X\n", + acpi_os_printf (" Alignment: %08X\n", memory32_data->alignment); - acpi_os_printf ("\t\t_range length: %08X\n", + acpi_os_printf (" Range length: %08X\n", memory32_data->range_length); return; @@ -423,22 +414,22 @@ void acpi_rs_dump_fixed_memory32 ( - RESOURCE_DATA *data) + ACPI_RESOURCE_DATA *data) { - FIXED_MEMORY32_RESOURCE *fixed_memory32_data = (FIXED_MEMORY32_RESOURCE*) data; + ACPI_RESOURCE_FIXED_MEM32 *fixed_memory32_data = (ACPI_RESOURCE_FIXED_MEM32 *) data; - acpi_os_printf ("\t32-Bit Fixed Location Memory Range Resource\n"); + acpi_os_printf ("32-Bit Fixed Location Memory Range Resource\n"); - acpi_os_printf ("\t\t_read%s\n", + acpi_os_printf (" Read%s\n", READ_WRITE_MEMORY == fixed_memory32_data->read_write_attribute ? "/Write" : " Only"); - acpi_os_printf ("\t\t_range base address: %08X\n", + acpi_os_printf (" Range base address: %08X\n", fixed_memory32_data->range_base_address); - acpi_os_printf ("\t\t_range length: %08X\n", + acpi_os_printf (" Range length: %08X\n", fixed_memory32_data->range_length); return; @@ -451,7 +442,7 @@ * * PARAMETERS: Data - pointer to the resource structure to dump. * - * RETURN: + * RETURN: None * * DESCRIPTION: Prints out the various members of the Data structure type. * @@ -459,49 +450,47 @@ void acpi_rs_dump_address16 ( - RESOURCE_DATA *data) + ACPI_RESOURCE_DATA *data) { - ADDRESS16_RESOURCE *address16_data = (ADDRESS16_RESOURCE*) data; + ACPI_RESOURCE_ADDRESS16 *address16_data = (ACPI_RESOURCE_ADDRESS16 *) data; - acpi_os_printf ("\t16-Bit Address Space Resource\n"); - acpi_os_printf ("\t\t_resource Type: "); + acpi_os_printf ("16-Bit Address Space Resource\n"); + acpi_os_printf (" Resource Type: "); - switch (address16_data->resource_type) - { + switch (address16_data->resource_type) { case MEMORY_RANGE: acpi_os_printf ("Memory Range\n"); - switch (address16_data->attribute.memory.cache_attribute) - { + switch (address16_data->attribute.memory.cache_attribute) { case NON_CACHEABLE_MEMORY: - acpi_os_printf ("\t\t_type Specific: " + acpi_os_printf (" Type Specific: " "Noncacheable memory\n"); break; case CACHABLE_MEMORY: - acpi_os_printf ("\t\t_type Specific: " + acpi_os_printf (" Type Specific: " "Cacheable memory\n"); break; case WRITE_COMBINING_MEMORY: - acpi_os_printf ("\t\t_type Specific: " + acpi_os_printf (" Type Specific: " "Write-combining memory\n"); break; case PREFETCHABLE_MEMORY: - acpi_os_printf ("\t\t_type Specific: " + acpi_os_printf (" Type Specific: " "Prefetchable memory\n"); break; default: - acpi_os_printf ("\t\t_type Specific: " + acpi_os_printf (" Type Specific: " "Invalid cache attribute\n"); break; } - acpi_os_printf ("\t\t_type Specific: Read%s\n", + acpi_os_printf (" Type Specific: Read%s\n", READ_WRITE_MEMORY == address16_data->attribute.memory.read_write_attribute ? "/Write" : " Only"); @@ -511,25 +500,24 @@ acpi_os_printf ("I/O Range\n"); - switch (address16_data->attribute.io.range_attribute) - { + switch (address16_data->attribute.io.range_attribute) { case NON_ISA_ONLY_RANGES: - acpi_os_printf ("\t\t_type Specific: " + acpi_os_printf (" Type Specific: " "Non-ISA Io Addresses\n"); break; case ISA_ONLY_RANGES: - acpi_os_printf ("\t\t_type Specific: " + acpi_os_printf (" Type Specific: " "ISA Io Addresses\n"); break; case ENTIRE_RANGE: - acpi_os_printf ("\t\t_type Specific: " + acpi_os_printf (" Type Specific: " "ISA and non-ISA Io Addresses\n"); break; default: - acpi_os_printf ("\t\t_type Specific: " + acpi_os_printf (" Type Specific: " "Invalid range attribute\n"); break; } @@ -546,42 +534,42 @@ return; } - acpi_os_printf ("\t\t_resource %s\n", + acpi_os_printf (" Resource %s\n", CONSUMER == address16_data->producer_consumer ? "Consumer" : "Producer"); - acpi_os_printf ("\t\t%s decode\n", + acpi_os_printf (" %s decode\n", SUB_DECODE == address16_data->decode ? "Subtractive" : "Positive"); - acpi_os_printf ("\t\t_min address is %s fixed\n", + acpi_os_printf (" Min address is %s fixed\n", ADDRESS_FIXED == address16_data->min_address_fixed ? "" : "not"); - acpi_os_printf ("\t\t_max address is %s fixed\n", + acpi_os_printf (" Max address is %s fixed\n", ADDRESS_FIXED == address16_data->max_address_fixed ? "" : "not"); - acpi_os_printf ("\t\t_granularity: %08X\n", + acpi_os_printf (" Granularity: %08X\n", address16_data->granularity); - acpi_os_printf ("\t\t_address range min: %08X\n", + acpi_os_printf (" Address range min: %08X\n", address16_data->min_address_range); - acpi_os_printf ("\t\t_address range max: %08X\n", + acpi_os_printf (" Address range max: %08X\n", address16_data->max_address_range); - acpi_os_printf ("\t\t_address translation offset: %08X\n", + acpi_os_printf (" Address translation offset: %08X\n", address16_data->address_translation_offset); - acpi_os_printf ("\t\t_address Length: %08X\n", + acpi_os_printf (" Address Length: %08X\n", address16_data->address_length); - if (0xFF != address16_data->resource_source_index) { - acpi_os_printf ("\t\t_resource Source Index: %X\n", - address16_data->resource_source_index); - acpi_os_printf ("\t\t_resource Source: %s\n", - address16_data->resource_source); + if (0xFF != address16_data->resource_source.index) { + acpi_os_printf (" Resource Source Index: %X\n", + address16_data->resource_source.index); + acpi_os_printf (" Resource Source: %s\n", + address16_data->resource_source.string_ptr); } return; @@ -594,7 +582,7 @@ * * PARAMETERS: Data - pointer to the resource structure to dump. * - * RETURN: + * RETURN: None * * DESCRIPTION: Prints out the various members of the Data structure type. * @@ -602,48 +590,46 @@ void acpi_rs_dump_address32 ( - RESOURCE_DATA *data) + ACPI_RESOURCE_DATA *data) { - ADDRESS32_RESOURCE *address32_data = (ADDRESS32_RESOURCE*) data; + ACPI_RESOURCE_ADDRESS32 *address32_data = (ACPI_RESOURCE_ADDRESS32 *) data; - acpi_os_printf ("\t32-Bit Address Space Resource\n"); + acpi_os_printf ("32-Bit Address Space Resource\n"); - switch (address32_data->resource_type) - { + switch (address32_data->resource_type) { case MEMORY_RANGE: - acpi_os_printf ("\t\t_resource Type: Memory Range\n"); + acpi_os_printf (" Resource Type: Memory Range\n"); - switch (address32_data->attribute.memory.cache_attribute) - { + switch (address32_data->attribute.memory.cache_attribute) { case NON_CACHEABLE_MEMORY: - acpi_os_printf ("\t\t_type Specific: " + acpi_os_printf (" Type Specific: " "Noncacheable memory\n"); break; case CACHABLE_MEMORY: - acpi_os_printf ("\t\t_type Specific: " + acpi_os_printf (" Type Specific: " "Cacheable memory\n"); break; case WRITE_COMBINING_MEMORY: - acpi_os_printf ("\t\t_type Specific: " + acpi_os_printf (" Type Specific: " "Write-combining memory\n"); break; case PREFETCHABLE_MEMORY: - acpi_os_printf ("\t\t_type Specific: " + acpi_os_printf (" Type Specific: " "Prefetchable memory\n"); break; default: - acpi_os_printf ("\t\t_type Specific: " + acpi_os_printf (" Type Specific: " "Invalid cache attribute\n"); break; } - acpi_os_printf ("\t\t_type Specific: Read%s\n", + acpi_os_printf (" Type Specific: Read%s\n", READ_WRITE_MEMORY == address32_data->attribute.memory.read_write_attribute ? "/Write" : " Only"); @@ -651,27 +637,26 @@ case IO_RANGE: - acpi_os_printf ("\t\t_resource Type: Io Range\n"); + acpi_os_printf (" Resource Type: Io Range\n"); - switch (address32_data->attribute.io.range_attribute) - { + switch (address32_data->attribute.io.range_attribute) { case NON_ISA_ONLY_RANGES: - acpi_os_printf ("\t\t_type Specific: " + acpi_os_printf (" Type Specific: " "Non-ISA Io Addresses\n"); break; case ISA_ONLY_RANGES: - acpi_os_printf ("\t\t_type Specific: " + acpi_os_printf (" Type Specific: " "ISA Io Addresses\n"); break; case ENTIRE_RANGE: - acpi_os_printf ("\t\t_type Specific: " + acpi_os_printf (" Type Specific: " "ISA and non-ISA Io Addresses\n"); break; default: - acpi_os_printf ("\t\t_type Specific: " + acpi_os_printf (" Type Specific: " "Invalid Range attribute"); break; } @@ -679,51 +664,190 @@ case BUS_NUMBER_RANGE: - acpi_os_printf ("\t\t_resource Type: Bus Number Range\n"); + acpi_os_printf (" Resource Type: Bus Number Range\n"); break; default: - acpi_os_printf ("\t\t_invalid Resource Type..exiting.\n"); + acpi_os_printf (" Invalid Resource Type..exiting.\n"); return; } - acpi_os_printf ("\t\t_resource %s\n", + acpi_os_printf (" Resource %s\n", CONSUMER == address32_data->producer_consumer ? "Consumer" : "Producer"); - acpi_os_printf ("\t\t%s decode\n", + acpi_os_printf (" %s decode\n", SUB_DECODE == address32_data->decode ? "Subtractive" : "Positive"); - acpi_os_printf ("\t\t_min address is %s fixed\n", + acpi_os_printf (" Min address is %s fixed\n", ADDRESS_FIXED == address32_data->min_address_fixed ? "" : "not "); - acpi_os_printf ("\t\t_max address is %s fixed\n", + acpi_os_printf (" Max address is %s fixed\n", ADDRESS_FIXED == address32_data->max_address_fixed ? "" : "not "); - acpi_os_printf ("\t\t_granularity: %08X\n", + acpi_os_printf (" Granularity: %08X\n", address32_data->granularity); - acpi_os_printf ("\t\t_address range min: %08X\n", + acpi_os_printf (" Address range min: %08X\n", address32_data->min_address_range); - acpi_os_printf ("\t\t_address range max: %08X\n", + acpi_os_printf (" Address range max: %08X\n", address32_data->max_address_range); - acpi_os_printf ("\t\t_address translation offset: %08X\n", + acpi_os_printf (" Address translation offset: %08X\n", address32_data->address_translation_offset); - acpi_os_printf ("\t\t_address Length: %08X\n", + acpi_os_printf (" Address Length: %08X\n", address32_data->address_length); - if(0xFF != address32_data->resource_source_index) { - acpi_os_printf ("\t\t_resource Source Index: %X\n", - address32_data->resource_source_index); - acpi_os_printf ("\t\t_resource Source: %s\n", - address32_data->resource_source); + if(0xFF != address32_data->resource_source.index) { + acpi_os_printf (" Resource Source Index: %X\n", + address32_data->resource_source.index); + acpi_os_printf (" Resource Source: %s\n", + address32_data->resource_source.string_ptr); + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_dump_address64 + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: None + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_address64 ( + ACPI_RESOURCE_DATA *data) +{ + ACPI_RESOURCE_ADDRESS64 *address64_data = (ACPI_RESOURCE_ADDRESS64 *) data; + + + acpi_os_printf ("64-Bit Address Space Resource\n"); + + switch (address64_data->resource_type) { + case MEMORY_RANGE: + + acpi_os_printf (" Resource Type: Memory Range\n"); + + switch (address64_data->attribute.memory.cache_attribute) { + case NON_CACHEABLE_MEMORY: + acpi_os_printf (" Type Specific: " + "Noncacheable memory\n"); + break; + + case CACHABLE_MEMORY: + acpi_os_printf (" Type Specific: " + "Cacheable memory\n"); + break; + + case WRITE_COMBINING_MEMORY: + acpi_os_printf (" Type Specific: " + "Write-combining memory\n"); + break; + + case PREFETCHABLE_MEMORY: + acpi_os_printf (" Type Specific: " + "Prefetchable memory\n"); + break; + + default: + acpi_os_printf (" Type Specific: " + "Invalid cache attribute\n"); + break; + } + + acpi_os_printf (" Type Specific: Read%s\n", + READ_WRITE_MEMORY == + address64_data->attribute.memory.read_write_attribute ? + "/Write" : " Only"); + break; + + case IO_RANGE: + + acpi_os_printf (" Resource Type: Io Range\n"); + + switch (address64_data->attribute.io.range_attribute) { + case NON_ISA_ONLY_RANGES: + acpi_os_printf (" Type Specific: " + "Non-ISA Io Addresses\n"); + break; + + case ISA_ONLY_RANGES: + acpi_os_printf (" Type Specific: " + "ISA Io Addresses\n"); + break; + + case ENTIRE_RANGE: + acpi_os_printf (" Type Specific: " + "ISA and non-ISA Io Addresses\n"); + break; + + default: + acpi_os_printf (" Type Specific: " + "Invalid Range attribute"); + break; + } + break; + + case BUS_NUMBER_RANGE: + + acpi_os_printf (" Resource Type: Bus Number Range\n"); + break; + + default: + + acpi_os_printf (" Invalid Resource Type..exiting.\n"); + return; + } + + acpi_os_printf (" Resource %s\n", + CONSUMER == address64_data->producer_consumer ? + "Consumer" : "Producer"); + + acpi_os_printf (" %s decode\n", + SUB_DECODE == address64_data->decode ? + "Subtractive" : "Positive"); + + acpi_os_printf (" Min address is %s fixed\n", + ADDRESS_FIXED == address64_data->min_address_fixed ? + "" : "not "); + + acpi_os_printf (" Max address is %s fixed\n", + ADDRESS_FIXED == address64_data->max_address_fixed ? + "" : "not "); + + acpi_os_printf (" Granularity: %16X\n", + address64_data->granularity); + + acpi_os_printf (" Address range min: %16X\n", + address64_data->min_address_range); + + acpi_os_printf (" Address range max: %16X\n", + address64_data->max_address_range); + + acpi_os_printf (" Address translation offset: %16X\n", + address64_data->address_translation_offset); + + acpi_os_printf (" Address Length: %16X\n", + address64_data->address_length); + + if(0xFF != address64_data->resource_source.index) { + acpi_os_printf (" Resource Source Index: %X\n", + address64_data->resource_source.index); + acpi_os_printf (" Resource Source: %s\n", + address64_data->resource_source.string_ptr); } return; @@ -736,7 +860,7 @@ * * PARAMETERS: Data - pointer to the resource structure to dump. * - * RETURN: + * RETURN: None * * DESCRIPTION: Prints out the various members of the Data structure type. * @@ -744,31 +868,31 @@ void acpi_rs_dump_extended_irq ( - RESOURCE_DATA *data) + ACPI_RESOURCE_DATA *data) { - EXTENDED_IRQ_RESOURCE *ext_irq_data = (EXTENDED_IRQ_RESOURCE*) data; + ACPI_RESOURCE_EXT_IRQ *ext_irq_data = (ACPI_RESOURCE_EXT_IRQ *) data; u8 index = 0; - acpi_os_printf ("\t_extended IRQ Resource\n"); + acpi_os_printf ("Extended IRQ Resource\n"); - acpi_os_printf ("\t\t_resource %s\n", + acpi_os_printf (" Resource %s\n", CONSUMER == ext_irq_data->producer_consumer ? "Consumer" : "Producer"); - acpi_os_printf ("\t\t%s\n", + acpi_os_printf (" %s\n", LEVEL_SENSITIVE == ext_irq_data->edge_level ? "Level" : "Edge"); - acpi_os_printf ("\t\t_active %s\n", + acpi_os_printf (" Active %s\n", ACTIVE_LOW == ext_irq_data->active_high_low ? "low" : "high"); - acpi_os_printf ("\t\t%s\n", + acpi_os_printf (" %s\n", SHARED == ext_irq_data->shared_exclusive ? "Shared" : "Exclusive"); - acpi_os_printf ("\t\t_interrupts : %X ( ", + acpi_os_printf (" Interrupts : %X ( ", ext_irq_data->number_of_interrupts); for (index = 0; index < ext_irq_data->number_of_interrupts; index++) { @@ -777,11 +901,11 @@ acpi_os_printf (")\n"); - if(0xFF != ext_irq_data->resource_source_index) { - acpi_os_printf ("\t\t_resource Source Index: %X", - ext_irq_data->resource_source_index); - acpi_os_printf ("\t\t_resource Source: %s", - ext_irq_data->resource_source); + if(0xFF != ext_irq_data->resource_source.index) { + acpi_os_printf (" Resource Source Index: %X", + ext_irq_data->resource_source.index); + acpi_os_printf (" Resource Source: %s", + ext_irq_data->resource_source.string_ptr); } return; @@ -794,7 +918,7 @@ * * PARAMETERS: Data - pointer to the resource structure to dump. * - * RETURN: + * RETURN: None * * DESCRIPTION: Dispatches the structure to the correct dump routine. * @@ -802,7 +926,7 @@ void acpi_rs_dump_resource_list ( - RESOURCE *resource) + ACPI_RESOURCE *resource) { u8 count = 0; u8 done = FALSE; @@ -810,66 +934,69 @@ if (acpi_dbg_level & TRACE_RESOURCES && _COMPONENT & acpi_dbg_layer) { while (!done) { - acpi_os_printf ("\t_resource structure %x.\n", count++); + acpi_os_printf ("Resource structure %x.\n", count++); - switch (resource->id) - { - case irq: + switch (resource->id) { + case ACPI_RSTYPE_IRQ: acpi_rs_dump_irq (&resource->data); break; - case dma: + case ACPI_RSTYPE_DMA: acpi_rs_dump_dma (&resource->data); break; - case start_dependent_functions: + case ACPI_RSTYPE_START_DPF: acpi_rs_dump_start_dependent_functions (&resource->data); break; - case end_dependent_functions: - acpi_os_printf ("\t_end_dependent_functions Resource\n"); + case ACPI_RSTYPE_END_DPF: + acpi_os_printf ("End_dependent_functions Resource\n"); /* Acpi_rs_dump_end_dependent_functions (Resource->Data);*/ break; - case io: + case ACPI_RSTYPE_IO: acpi_rs_dump_io (&resource->data); break; - case fixed_io: + case ACPI_RSTYPE_FIXED_IO: acpi_rs_dump_fixed_io (&resource->data); break; - case vendor_specific: + case ACPI_RSTYPE_VENDOR: acpi_rs_dump_vendor_specific (&resource->data); break; - case end_tag: + case ACPI_RSTYPE_END_TAG: /*Rs_dump_end_tag (Resource->Data);*/ - acpi_os_printf ("\t_end_tag Resource\n"); + acpi_os_printf ("End_tag Resource\n"); done = TRUE; break; - case memory24: + case ACPI_RSTYPE_MEM24: acpi_rs_dump_memory24 (&resource->data); break; - case memory32: + case ACPI_RSTYPE_MEM32: acpi_rs_dump_memory32 (&resource->data); break; - case fixed_memory32: + case ACPI_RSTYPE_FIXED_MEM32: acpi_rs_dump_fixed_memory32 (&resource->data); break; - case address16: + case ACPI_RSTYPE_ADDRESS16: acpi_rs_dump_address16 (&resource->data); break; - case address32: + case ACPI_RSTYPE_ADDRESS32: acpi_rs_dump_address32 (&resource->data); break; - case extended_irq: + case ACPI_RSTYPE_ADDRESS64: + acpi_rs_dump_address64 (&resource->data); + break; + + case ACPI_RSTYPE_EXT_IRQ: acpi_rs_dump_extended_irq (&resource->data); break; @@ -879,8 +1006,7 @@ } - resource = (RESOURCE *) ((NATIVE_UINT) resource + - (NATIVE_UINT) resource->length); + resource = POINTER_ADD (ACPI_RESOURCE, resource, resource->length); } } @@ -893,7 +1019,7 @@ * * PARAMETERS: Data - pointer to the routing table to dump. * - * RETURN: + * RETURN: None * * DESCRIPTION: Dispatches the structures to the correct dump routine. * @@ -913,16 +1039,16 @@ prt_element = (PCI_ROUTING_TABLE *) buffer; while (!done) { - acpi_os_printf ("\t_pCI IRQ Routing Table structure %X.\n", count++); + acpi_os_printf ("PCI IRQ Routing Table structure %X.\n", count++); - acpi_os_printf ("\t\t_address: %X\n", + acpi_os_printf (" Address: %X\n", prt_element->address); - acpi_os_printf ("\t\t_pin: %X\n", prt_element->pin); + acpi_os_printf (" Pin: %X\n", prt_element->pin); - acpi_os_printf ("\t\t_source: %s\n", prt_element->source); + acpi_os_printf (" Source: %s\n", prt_element->source); - acpi_os_printf ("\t\t_source_index: %X\n", + acpi_os_printf (" Source_index: %X\n", prt_element->source_index); buffer += prt_element->length; diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/resources/rsio.c linux/drivers/acpi/resources/rsio.c --- v2.4.5/linux/drivers/acpi/resources/rsio.c Mon Jan 22 13:23:43 2001 +++ linux/drivers/acpi/resources/rsio.c Wed Jun 20 17:47:40 2001 @@ -1,12 +1,7 @@ /******************************************************************************* * - * Module Name: rsio - Acpi_rs_io_resource - * Acpi_rs_fixed_io_resource - * Acpi_rs_io_stream - * Acpi_rs_fixed_io_stream - * Acpi_rs_dma_resource - * Acpi_rs_dma_stream - * $Revision: 12 $ + * Module Name: rsio - IO and DMA resource descriptors + * $Revision: 14 $ * ******************************************************************************/ @@ -32,7 +27,7 @@ #include "acpi.h" #include "acresrc.h" -#define _COMPONENT RESOURCE_MANAGER +#define _COMPONENT ACPI_RESOURCES MODULE_NAME ("rsio") @@ -41,20 +36,20 @@ * FUNCTION: Acpi_rs_io_resource * * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte - * stream + * stream * Bytes_consumed - u32 pointer that is filled with - * the number of bytes consumed from - * the Byte_stream_buffer + * the number of bytes consumed from + * the Byte_stream_buffer * Output_buffer - Pointer to the user's return buffer * Structure_size - u32 pointer that is filled with - * the number of bytes in the filled - * in structure + * the number of bytes in the filled + * in structure * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Take the resource byte stream and fill out the appropriate - * structure pointed to by the Output_buffer. Return the - * number of bytes consumed from the byte stream. + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. * ******************************************************************************/ @@ -66,11 +61,10 @@ u32 *structure_size) { u8 *buffer = byte_stream_buffer; - RESOURCE *output_struct = (RESOURCE *) * output_buffer; + ACPI_RESOURCE *output_struct = (ACPI_RESOURCE *) *output_buffer; u16 temp16 = 0; u8 temp8 = 0; - u32 struct_size = sizeof (IO_RESOURCE) + - RESOURCE_LENGTH_NO_DATA; + u32 struct_size = SIZEOF_RESOURCE (ACPI_RESOURCE_IO); /* @@ -78,7 +72,7 @@ */ *bytes_consumed = 8; - output_struct->id = io; + output_struct->id = ACPI_RSTYPE_IO; /* * Check Decode @@ -129,7 +123,6 @@ * Return the final size of the structure */ *structure_size = struct_size; - return (AE_OK); } @@ -139,20 +132,20 @@ * FUNCTION: Acpi_rs_fixed_io_resource * * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte - * stream + * stream * Bytes_consumed - u32 pointer that is filled with - * the number of bytes consumed from - * the Byte_stream_buffer + * the number of bytes consumed from + * the Byte_stream_buffer * Output_buffer - Pointer to the user's return buffer * Structure_size - u32 pointer that is filled with - * the number of bytes in the filled - * in structure + * the number of bytes in the filled + * in structure * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Take the resource byte stream and fill out the appropriate - * structure pointed to by the Output_buffer. Return the - * number of bytes consumed from the byte stream. + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. * ******************************************************************************/ @@ -164,11 +157,10 @@ u32 *structure_size) { u8 *buffer = byte_stream_buffer; - RESOURCE *output_struct = (RESOURCE *) * output_buffer; + ACPI_RESOURCE *output_struct = (ACPI_RESOURCE *) *output_buffer; u16 temp16 = 0; u8 temp8 = 0; - u32 struct_size = sizeof (FIXED_IO_RESOURCE) + - RESOURCE_LENGTH_NO_DATA; + u32 struct_size = SIZEOF_RESOURCE (ACPI_RESOURCE_FIXED_IO); /* @@ -176,7 +168,7 @@ */ *bytes_consumed = 4; - output_struct->id = fixed_io; + output_struct->id = ACPI_RSTYPE_FIXED_IO; /* * Check Range Base Address @@ -203,7 +195,6 @@ * Return the final size of the structure */ *structure_size = struct_size; - return (AE_OK); } @@ -215,19 +206,19 @@ * PARAMETERS: Linked_list - Pointer to the resource linked list * Output_buffer - Pointer to the user's return buffer * Bytes_consumed - u32 pointer that is filled with - * the number of bytes of the - * Output_buffer used + * the number of bytes of the + * Output_buffer used * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Take the linked list resource structure and fills in the - * the appropriate bytes in a byte stream + * the appropriate bytes in a byte stream * ******************************************************************************/ ACPI_STATUS acpi_rs_io_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u8 **output_buffer, u32 *bytes_consumed) { @@ -285,9 +276,7 @@ /* * Return the number of bytes consumed in this operation */ - *bytes_consumed = (u32) ((NATIVE_UINT) buffer - - (NATIVE_UINT) *output_buffer); - + *bytes_consumed = POINTER_DIFF (buffer, *output_buffer); return (AE_OK); } @@ -299,19 +288,19 @@ * PARAMETERS: Linked_list - Pointer to the resource linked list * Output_buffer - Pointer to the user's return buffer * Bytes_consumed - u32 pointer that is filled with - * the number of bytes of the - * Output_buffer used + * the number of bytes of the + * Output_buffer used * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Take the linked list resource structure and fills in the - * the appropriate bytes in a byte stream + * the appropriate bytes in a byte stream * ******************************************************************************/ ACPI_STATUS acpi_rs_fixed_io_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u8 **output_buffer, u32 *bytes_consumed) { @@ -346,9 +335,7 @@ /* * Return the number of bytes consumed in this operation */ - *bytes_consumed = (u32) ((NATIVE_UINT) buffer - - (NATIVE_UINT) *output_buffer); - + *bytes_consumed = POINTER_DIFF (buffer, *output_buffer); return (AE_OK); } @@ -358,20 +345,20 @@ * FUNCTION: Acpi_rs_dma_resource * * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte - * stream + * stream * Bytes_consumed - u32 pointer that is filled with - * the number of bytes consumed from - * the Byte_stream_buffer + * the number of bytes consumed from + * the Byte_stream_buffer * Output_buffer - Pointer to the user's return buffer * Structure_size - u32 pointer that is filled with - * the number of bytes in the filled - * in structure + * the number of bytes in the filled + * in structure * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Take the resource byte stream and fill out the appropriate - * structure pointed to by the Output_buffer. Return the - * number of bytes consumed from the byte stream. + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. * ******************************************************************************/ @@ -383,19 +370,18 @@ u32 *structure_size) { u8 *buffer = byte_stream_buffer; - RESOURCE *output_struct = (RESOURCE *) * output_buffer; + ACPI_RESOURCE *output_struct = (ACPI_RESOURCE *) *output_buffer; u8 temp8 = 0; u8 index; u8 i; - u32 struct_size = sizeof(DMA_RESOURCE) + - RESOURCE_LENGTH_NO_DATA; + u32 struct_size = SIZEOF_RESOURCE (ACPI_RESOURCE_DMA); /* * The number of bytes consumed are Constant */ *bytes_consumed = 3; - output_struct->id = dma; + output_struct->id = ACPI_RSTYPE_DMA; /* * Point to the 8-bits of Byte 1 @@ -453,7 +439,6 @@ * Return the final size of the structure */ *structure_size = struct_size; - return (AE_OK); } @@ -465,19 +450,19 @@ * PARAMETERS: Linked_list - Pointer to the resource linked list * Output_buffer - Pointer to the user's return buffer * Bytes_consumed - u32 pointer that is filled with - * the number of bytes of the - * Output_buffer used + * the number of bytes of the + * Output_buffer used * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Take the linked list resource structure and fills in the - * the appropriate bytes in a byte stream + * the appropriate bytes in a byte stream * ******************************************************************************/ ACPI_STATUS acpi_rs_dma_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u8 **output_buffer, u32 *bytes_consumed) { @@ -499,8 +484,7 @@ */ for (index = 0; index < linked_list->data.dma.number_of_channels; - index++) - { + index++) { temp16 = (u16) linked_list->data.dma.channels[index]; temp8 |= 0x1 << temp16; } @@ -521,9 +505,7 @@ /* * Return the number of bytes consumed in this operation */ - *bytes_consumed = (u32) ((NATIVE_UINT) buffer - - (NATIVE_UINT) *output_buffer); - + *bytes_consumed = POINTER_DIFF (buffer, *output_buffer); return (AE_OK); } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/resources/rsirq.c linux/drivers/acpi/resources/rsirq.c --- v2.4.5/linux/drivers/acpi/resources/rsirq.c Mon Jan 22 13:23:43 2001 +++ linux/drivers/acpi/resources/rsirq.c Wed Jun 20 17:47:40 2001 @@ -1,10 +1,7 @@ /******************************************************************************* * - * Module Name: rsirq - Acpi_rs_irq_resource, - * Acpi_rs_irq_stream - * Acpi_rs_extended_irq_resource - * Acpi_rs_extended_irq_stream - * $Revision: 13 $ + * Module Name: rsirq - IRQ resource descriptors + * $Revision: 17 $ * ******************************************************************************/ @@ -30,7 +27,7 @@ #include "acpi.h" #include "acresrc.h" -#define _COMPONENT RESOURCE_MANAGER +#define _COMPONENT ACPI_RESOURCES MODULE_NAME ("rsirq") @@ -39,20 +36,20 @@ * FUNCTION: Acpi_rs_irq_resource * * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte - * stream + * stream * Bytes_consumed - u32 pointer that is filled with - * the number of bytes consumed from - * the Byte_stream_buffer + * the number of bytes consumed from + * the Byte_stream_buffer * Output_buffer - Pointer to the user's return buffer * Structure_size - u32 pointer that is filled with - * the number of bytes in the filled - * in structure + * the number of bytes in the filled + * in structure * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Take the resource byte stream and fill out the appropriate - * structure pointed to by the Output_buffer. Return the - * number of bytes consumed from the byte stream. + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. * ******************************************************************************/ @@ -64,13 +61,12 @@ u32 *structure_size) { u8 *buffer = byte_stream_buffer; - RESOURCE *output_struct = (RESOURCE *) * output_buffer; + ACPI_RESOURCE *output_struct = (ACPI_RESOURCE *) *output_buffer; u16 temp16 = 0; u8 temp8 = 0; u8 index; u8 i; - u32 struct_size = sizeof (IRQ_RESOURCE) + - RESOURCE_LENGTH_NO_DATA; + u32 struct_size = SIZEOF_RESOURCE (ACPI_RESOURCE_IRQ); /* @@ -79,7 +75,7 @@ */ temp8 = *buffer; *bytes_consumed = (temp8 & 0x03) + 1; - output_struct->id = irq; + output_struct->id = ACPI_RSTYPE_IRQ; /* * Point to the 16-bits of Bytes 1 and 2 @@ -128,8 +124,8 @@ else { /* * Only _LL and _HE polarity/trigger interrupts - * are allowed (ACPI spec v1.0b ection 6.4.2.1), - * so an error will occur if we reach this point + * are allowed (ACPI spec v1.0b ection 6.4.2.1), + * so an error will occur if we reach this point */ return (AE_BAD_DATA); } @@ -144,7 +140,7 @@ else { /* * Assume Edge Sensitive, Active High, Non-Sharable - * per ACPI Specification + * per ACPI Specification */ output_struct->data.irq.edge_level = EDGE_SENSITIVE; output_struct->data.irq.active_high_low = ACTIVE_HIGH; @@ -160,7 +156,6 @@ * Return the final size of the structure */ *structure_size = struct_size; - return (AE_OK); } @@ -172,19 +167,19 @@ * PARAMETERS: Linked_list - Pointer to the resource linked list * Output_buffer - Pointer to the user's return buffer * Bytes_consumed - u32 pointer that is filled with - * the number of bytes of the - * Output_buffer used + * the number of bytes of the + * Output_buffer used * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Take the linked list resource structure and fills in the - * the appropriate bytes in a byte stream + * the appropriate bytes in a byte stream * ******************************************************************************/ ACPI_STATUS acpi_rs_irq_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u8 **output_buffer, u32 *bytes_consumed) { @@ -197,15 +192,15 @@ /* * The descriptor field is set based upon whether a third byte is - * needed to contain the IRQ Information. + * needed to contain the IRQ Information. */ if (EDGE_SENSITIVE == linked_list->data.irq.edge_level && ACTIVE_HIGH == linked_list->data.irq.active_high_low && - EXCLUSIVE == linked_list->data.irq.shared_exclusive) - { + EXCLUSIVE == linked_list->data.irq.shared_exclusive) { *buffer = 0x22; IRQinfo_byte_needed = FALSE; } + else { *buffer = 0x23; IRQinfo_byte_needed = TRUE; @@ -219,8 +214,7 @@ */ for(index = 0; index < linked_list->data.irq.number_of_interrupts; - index++) - { + index++) { temp8 = (u8) linked_list->data.irq.interrupts[index]; temp16 |= 0x1 << temp8; } @@ -237,8 +231,7 @@ 0x01) << 4); if (LEVEL_SENSITIVE == linked_list->data.irq.edge_level && - ACTIVE_LOW == linked_list->data.irq.active_high_low) - { + ACTIVE_LOW == linked_list->data.irq.active_high_low) { temp8 |= 0x08; } @@ -253,9 +246,7 @@ /* * Return the number of bytes consumed in this operation */ - *bytes_consumed = (u32) ((NATIVE_UINT) buffer - - (NATIVE_UINT) *output_buffer); - + *bytes_consumed = POINTER_DIFF (buffer, *output_buffer); return (AE_OK); } @@ -265,20 +256,20 @@ * FUNCTION: Acpi_rs_extended_irq_resource * * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte - * stream + * stream * Bytes_consumed - u32 pointer that is filled with - * the number of bytes consumed from - * the Byte_stream_buffer + * the number of bytes consumed from + * the Byte_stream_buffer * Output_buffer - Pointer to the user's return buffer * Structure_size - u32 pointer that is filled with - * the number of bytes in the filled - * in structure + * the number of bytes in the filled + * in structure * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Take the resource byte stream and fill out the appropriate - * structure pointed to by the Output_buffer. Return the - * number of bytes consumed from the byte stream. + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. * ******************************************************************************/ @@ -290,12 +281,12 @@ u32 *structure_size) { u8 *buffer = byte_stream_buffer; - RESOURCE *output_struct = (RESOURCE *) * output_buffer; + ACPI_RESOURCE *output_struct = (ACPI_RESOURCE *) *output_buffer; u16 temp16 = 0; u8 temp8 = 0; + NATIVE_CHAR *temp_ptr; u8 index; - u32 struct_size = sizeof (EXTENDED_IRQ_RESOURCE) + - RESOURCE_LENGTH_NO_DATA; + u32 struct_size = SIZEOF_RESOURCE (ACPI_RESOURCE_EXT_IRQ); /* @@ -305,7 +296,7 @@ MOVE_UNALIGNED16_TO_16 (&temp16, buffer); *bytes_consumed = temp16 + 3; - output_struct->id = extended_irq; + output_struct->id = ACPI_RSTYPE_EXT_IRQ; /* * Point to the Byte3 @@ -332,8 +323,8 @@ else { /* * Only _LL and _HE polarity/trigger interrupts - * are allowed (ACPI spec v1.0b ection 6.4.2.1), - * so an error will occur if we reach this point + * are allowed (ACPI spec v1.0b ection 6.4.2.1), + * so an error will occur if we reach this point */ return (AE_BAD_DATA); } @@ -342,8 +333,7 @@ /* * Check for sharable */ - output_struct->data.extended_irq.shared_exclusive = - (temp8 >> 3) & 0x01; + output_struct->data.extended_irq.shared_exclusive = (temp8 >> 3) & 0x01; /* * Point to Byte4 (IRQ Table length) @@ -355,9 +345,9 @@ /* * Add any additional structure size to properly calculate - * the next pointer at the end of this function + * the next pointer at the end of this function */ - struct_size += (temp8 - 1) * 4; + struct_size += (temp8 - 1) * 4; /* * Point to Byte5 (First IRQ Number) @@ -378,33 +368,38 @@ /* * This will leave us pointing to the Resource Source Index - * If it is present, then save it off and calculate the - * pointer to where the null terminated string goes: - * Each Interrupt takes 32-bits + the 5 bytes of the - * stream that are default. + * If it is present, then save it off and calculate the + * pointer to where the null terminated string goes: + * Each Interrupt takes 32-bits + the 5 bytes of the + * stream that are default. */ if (*bytes_consumed > - (u32)(output_struct->data.extended_irq.number_of_interrupts * - 4) + 5) - { + (u32)(output_struct->data.extended_irq.number_of_interrupts * 4) + 5) { /* Dereference the Index */ temp8 = *buffer; - output_struct->data.extended_irq.resource_source_index = - (u32)temp8; + output_struct->data.extended_irq.resource_source.index = (u32) temp8; /* Point to the String */ buffer += 1; + /* + * Point the String pointer to the end of this structure. + */ + 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; + /* Copy the string into the buffer */ index = 0; while (0x00 != *buffer) { - output_struct->data.extended_irq.resource_source[index] = - *buffer; + *temp_ptr = *buffer; + temp_ptr += 1; buffer += 1; index += 1; } @@ -412,23 +407,22 @@ /* * Add the terminating null */ - output_struct->data.extended_irq.resource_source[index] = 0x00; - output_struct->data.extended_irq.resource_source_string_length = - index + 1; + *temp_ptr = 0x00; + output_struct->data.extended_irq.resource_source.string_length = index + 1; /* - * In order for the Struct_size to fall on a 32-bit boundry, - * calculate the length of the string and expand the - * Struct_size to the next 32-bit boundry. + * In order for the Struct_size to fall on a 32-bit boundary, + * calculate the length of the string and expand the + * Struct_size to the next 32-bit boundary. */ temp8 = (u8) (index + 1); - temp8 = (u8) ROUND_UP_TO_32_bITS (temp8); + struct_size += ROUND_UP_TO_32_bITS (temp8); } else { - output_struct->data.extended_irq.resource_source_index = 0x00; - output_struct->data.extended_irq.resource_source_string_length = 0; - output_struct->data.extended_irq.resource_source[0] = 0x00; + output_struct->data.extended_irq.resource_source.index = 0x00; + output_struct->data.extended_irq.resource_source.string_length = 0; + output_struct->data.extended_irq.resource_source.string_ptr = NULL; } /* @@ -440,7 +434,6 @@ * Return the final size of the structure */ *structure_size = struct_size; - return (AE_OK); } @@ -452,10 +445,10 @@ * PARAMETERS: Linked_list - Pointer to the resource linked list * Output_buffer - Pointer to the user's return buffer * Bytes_consumed - u32 pointer that is filled with - * the number of bytes of the - * Output_buffer used + * the number of bytes of the + * Output_buffer used * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Take the linked list resource structure and fills in the * the appropriate bytes in a byte stream @@ -464,7 +457,7 @@ ACPI_STATUS acpi_rs_extended_irq_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u8 **output_buffer, u32 *bytes_consumed) { @@ -484,7 +477,6 @@ /* * Set a pointer to the Length field - to be filled in later */ - length_field = (u16 *)buffer; buffer += 2; @@ -492,12 +484,10 @@ * Set the Interrupt vector flags */ temp8 = (u8)(linked_list->data.extended_irq.producer_consumer & 0x01); - temp8 |= ((linked_list->data.extended_irq.shared_exclusive & 0x01) << 3); if (LEVEL_SENSITIVE == linked_list->data.extended_irq.edge_level && - ACTIVE_LOW == linked_list->data.extended_irq.active_high_low) - { + ACTIVE_LOW == linked_list->data.extended_irq.active_high_low) { temp8 |= 0x04; } else { @@ -515,10 +505,8 @@ *buffer = temp8; buffer += 1; - for (index = 0; - index < linked_list->data.extended_irq.number_of_interrupts; - index++) - { + for (index = 0; index < linked_list->data.extended_irq.number_of_interrupts; + index++) { MOVE_UNALIGNED32_TO_32 (buffer, &linked_list->data.extended_irq.interrupts[index]); buffer += 4; @@ -527,8 +515,8 @@ /* * Resource Source Index and Resource Source are optional */ - if (0 != linked_list->data.extended_irq.resource_source_string_length) { - *buffer = (u8) linked_list->data.extended_irq.resource_source_index; + if (0 != linked_list->data.extended_irq.resource_source.string_length) { + *buffer = (u8) linked_list->data.extended_irq.resource_source.index; buffer += 1; temp_pointer = (NATIVE_CHAR *) buffer; @@ -536,27 +524,26 @@ /* * Copy the string */ - STRCPY (temp_pointer, linked_list->data.extended_irq.resource_source); + STRCPY (temp_pointer, + linked_list->data.extended_irq.resource_source.string_ptr); /* * Buffer needs to be set to the length of the sting + one for the - * terminating null + * terminating null */ - buffer += (STRLEN (linked_list->data.extended_irq.resource_source) + 1); + buffer += (STRLEN (linked_list->data.extended_irq.resource_source.string_ptr) + 1); } /* * Return the number of bytes consumed in this operation */ - *bytes_consumed = (u32) ((NATIVE_UINT) buffer - - (NATIVE_UINT) *output_buffer); + *bytes_consumed = POINTER_DIFF (buffer, *output_buffer); /* * Set the length field to the number of bytes consumed - * minus the header size (3 bytes) + * minus the header size (3 bytes) */ *length_field = (u16) (*bytes_consumed - 3); - return (AE_OK); } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/resources/rslist.c linux/drivers/acpi/resources/rslist.c --- v2.4.5/linux/drivers/acpi/resources/rslist.c Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/resources/rslist.c Wed Jun 20 17:47:40 2001 @@ -1,8 +1,7 @@ /******************************************************************************* * - * Module Name: rslist - Acpi_rs_byte_stream_to_list - * Acpi_list_to_byte_stream - * $Revision: 11 $ + * Module Name: rslist - Linked list utilities + * $Revision: 17 $ * ******************************************************************************/ @@ -28,20 +27,64 @@ #include "acpi.h" #include "acresrc.h" -#define _COMPONENT RESOURCE_MANAGER +#define _COMPONENT ACPI_RESOURCES MODULE_NAME ("rslist") /******************************************************************************* * + * FUNCTION: Acpi_rs_get_resource_type + * + * PARAMETERS: Resource_start_byte - Byte 0 of a resource descriptor + * + * RETURN: The Resource Type (Name) with no extraneous bits + * + * DESCRIPTION: Extract the Resource Type/Name from the first byte of + * a resource descriptor. + * + ******************************************************************************/ + +u8 +acpi_rs_get_resource_type ( + u8 resource_start_byte) +{ + + /* + * Determine if this is a small or large resource + */ + switch (resource_start_byte & RESOURCE_DESC_TYPE_MASK) { + case RESOURCE_DESC_TYPE_SMALL: + + /* + * Small Resource Type -- Only bits 6:3 are valid + */ + return ((u8) (resource_start_byte & RESOURCE_DESC_SMALL_MASK)); + break; + + + case RESOURCE_DESC_TYPE_LARGE: + + /* + * Large Resource Type -- All bits are valid + */ + return (resource_start_byte); + break; + } + + return (0xFF); +} + + +/******************************************************************************* + * * FUNCTION: Acpi_rs_byte_stream_to_list * * PARAMETERS: Byte_stream_buffer - Pointer to the resource byte stream * Byte_stream_buffer_length - Length of Byte_stream_buffer * Output_buffer - Pointer to the buffer that will - * contain the output structures + * contain the output structures * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Takes the resource byte stream and parses it, creating a * linked list of resources in the caller's output buffer @@ -64,223 +107,170 @@ while (bytes_parsed < byte_stream_buffer_length && - FALSE == end_tag_processed) - { + FALSE == end_tag_processed) { /* - * Look at the next byte in the stream + * The next byte in the stream is the resource type */ - resource_type = *byte_stream_buffer; + resource_type = acpi_rs_get_resource_type (*byte_stream_buffer); - /* - * See if this is a small or large resource - */ - if(resource_type & 0x80) { + switch (resource_type) { + case RESOURCE_DESC_MEMORY_24: /* - * Large Resource Type + * 24-Bit Memory Resource */ - switch (resource_type) - { - case MEMORY_RANGE_24: - /* - * 24-Bit Memory Resource - */ - status = acpi_rs_memory24_resource(byte_stream_buffer, - &bytes_consumed, - buffer, - &structure_size); - - break; - - case LARGE_VENDOR_DEFINED: - /* - * Vendor Defined Resource - */ - status = acpi_rs_vendor_resource(byte_stream_buffer, - &bytes_consumed, - buffer, - &structure_size); - - break; - - case MEMORY_RANGE_32: - /* - * 32-Bit Memory Range Resource - */ - status = acpi_rs_memory32_range_resource(byte_stream_buffer, - &bytes_consumed, - buffer, - &structure_size); - - break; - - case FIXED_MEMORY_RANGE_32: - /* - * 32-Bit Fixed Memory Resource - */ - status = acpi_rs_fixed_memory32_resource(byte_stream_buffer, - &bytes_consumed, - buffer, - &structure_size); - - break; - - case DWORD_ADDRESS_SPACE: - /* - * 32-Bit Address Resource - */ - status = acpi_rs_address32_resource(byte_stream_buffer, - &bytes_consumed, - buffer, - &structure_size); - - break; - - case WORD_ADDRESS_SPACE: - /* - * 16-Bit Address Resource - */ - status = acpi_rs_address16_resource(byte_stream_buffer, - &bytes_consumed, - buffer, - &structure_size); - - break; - - case EXTENDED_IRQ: - /* - * Extended IRQ - */ - status = acpi_rs_extended_irq_resource(byte_stream_buffer, - &bytes_consumed, - buffer, - &structure_size); + status = acpi_rs_memory24_resource (byte_stream_buffer, + &bytes_consumed, buffer, &structure_size); + break; - break; -/* TBD: [Future] 64-bit not currently supported */ -/* - case 0x8A: - break; -*/ - - default: - /* - * If we get here, everything is out of sync, - * so exit with an error - */ - return (AE_AML_ERROR); - break; - } - } + case RESOURCE_DESC_LARGE_VENDOR: + /* + * Vendor Defined Resource + */ + status = acpi_rs_vendor_resource (byte_stream_buffer, + &bytes_consumed, buffer, &structure_size); + break; + + + case RESOURCE_DESC_MEMORY_32: + /* + * 32-Bit Memory Range Resource + */ + status = acpi_rs_memory32_range_resource (byte_stream_buffer, + &bytes_consumed, buffer, &structure_size); + break; + + + case RESOURCE_DESC_FIXED_MEMORY_32: + /* + * 32-Bit Fixed Memory Resource + */ + status = acpi_rs_fixed_memory32_resource (byte_stream_buffer, + &bytes_consumed, buffer, &structure_size); + break; + + + case RESOURCE_DESC_QWORD_ADDRESS_SPACE: + /* + * 64-Bit Address Resource + */ + status = acpi_rs_address64_resource (byte_stream_buffer, + &bytes_consumed, buffer, &structure_size); + break; + + + case RESOURCE_DESC_DWORD_ADDRESS_SPACE: + /* + * 32-Bit Address Resource + */ + status = acpi_rs_address32_resource (byte_stream_buffer, + &bytes_consumed, buffer, &structure_size); + break; + + + case RESOURCE_DESC_WORD_ADDRESS_SPACE: + /* + * 16-Bit Address Resource + */ + status = acpi_rs_address16_resource (byte_stream_buffer, + &bytes_consumed, buffer, &structure_size); + break; + + + case RESOURCE_DESC_EXTENDED_XRUPT: + /* + * Extended IRQ + */ + status = acpi_rs_extended_irq_resource (byte_stream_buffer, + &bytes_consumed, buffer, &structure_size); + break; + + + case RESOURCE_DESC_IRQ_FORMAT: + /* + * IRQ Resource + */ + status = acpi_rs_irq_resource (byte_stream_buffer, + &bytes_consumed, buffer, &structure_size); + break; + + + case RESOURCE_DESC_DMA_FORMAT: + /* + * DMA Resource + */ + status = acpi_rs_dma_resource (byte_stream_buffer, + &bytes_consumed, buffer, &structure_size); + break; + + + case RESOURCE_DESC_START_DEPENDENT: + /* + * Start Dependent Functions Resource + */ + status = acpi_rs_start_dependent_functions_resource (byte_stream_buffer, + &bytes_consumed, buffer, &structure_size); + break; + + + case RESOURCE_DESC_END_DEPENDENT: + /* + * End Dependent Functions Resource + */ + status = acpi_rs_end_dependent_functions_resource (byte_stream_buffer, + &bytes_consumed, buffer, &structure_size); + break; + + + case RESOURCE_DESC_IO_PORT: + /* + * IO Port Resource + */ + status = acpi_rs_io_resource (byte_stream_buffer, + &bytes_consumed, buffer, &structure_size); + break; + + + case RESOURCE_DESC_FIXED_IO_PORT: + /* + * Fixed IO Port Resource + */ + status = acpi_rs_fixed_io_resource (byte_stream_buffer, + &bytes_consumed, buffer, &structure_size); + break; + - else { + case RESOURCE_DESC_SMALL_VENDOR: /* - * Small Resource Type - * Only bits 7:3 are valid + * Vendor Specific Resource */ - resource_type >>= 3; + status = acpi_rs_vendor_resource (byte_stream_buffer, + &bytes_consumed, buffer, &structure_size); + break; - switch(resource_type) - { - case IRQ_FORMAT: - /* - * IRQ Resource - */ - status = acpi_rs_irq_resource(byte_stream_buffer, - &bytes_consumed, - buffer, - &structure_size); - - break; - - case DMA_FORMAT: - /* - * DMA Resource - */ - status = acpi_rs_dma_resource(byte_stream_buffer, - &bytes_consumed, - buffer, - &structure_size); - - break; - - case START_DEPENDENT_TAG: - /* - * Start Dependent Functions Resource - */ - status = acpi_rs_start_dependent_functions_resource(byte_stream_buffer, - &bytes_consumed, - buffer, - &structure_size); - - break; - - case END_DEPENDENT_TAG: - /* - * End Dependent Functions Resource - */ - status = acpi_rs_end_dependent_functions_resource(byte_stream_buffer, - &bytes_consumed, - buffer, - &structure_size); - - break; - - case IO_PORT_DESCRIPTOR: - /* - * IO Port Resource - */ - status = acpi_rs_io_resource(byte_stream_buffer, - &bytes_consumed, - buffer, - &structure_size); - - break; - - case FIXED_LOCATION_IO_DESCRIPTOR: - /* - * Fixed IO Port Resource - */ - status = acpi_rs_fixed_io_resource(byte_stream_buffer, - &bytes_consumed, - buffer, - &structure_size); - - break; - - case SMALL_VENDOR_DEFINED: - /* - * Vendor Specific Resource - */ - status = acpi_rs_vendor_resource(byte_stream_buffer, - &bytes_consumed, - buffer, - &structure_size); - - break; - - case END_TAG: - /* - * End Tag - */ - status = acpi_rs_end_tag_resource(byte_stream_buffer, - &bytes_consumed, - buffer, - &structure_size); - end_tag_processed = TRUE; - - break; - - default: - /* - * If we get here, everything is out of sync, - * so exit with an error - */ - return (AE_AML_ERROR); - break; - } /* switch */ - } /* end else */ + case RESOURCE_DESC_END_TAG: + /* + * End Tag + */ + end_tag_processed = TRUE; + status = acpi_rs_end_tag_resource (byte_stream_buffer, + &bytes_consumed, buffer, &structure_size); + break; + + + default: + /* + * Invalid/Unknowns resource type + */ + status = AE_AML_ERROR; + break; + } + + + if (!ACPI_SUCCESS(status)) { + return (status); + } /* * Update the return value and counter @@ -316,15 +306,15 @@ * * 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() - * The size of the Output_buffer is - * guaranteed to be >= - * Byte_stream_size_needed + * needed from calling + * Acpi_rs_calculate_byte_stream_length() + * The size of the Output_buffer is + * guaranteed to be >= + * Byte_stream_size_needed * Output_buffer - Pointer to the buffer that will - * contain the byte stream + * contain the byte stream * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Takes the resource linked list and parses it, creating a * byte stream of resources in the caller's output buffer @@ -333,7 +323,7 @@ ACPI_STATUS acpi_rs_list_to_byte_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u32 byte_stream_size_needed, u8 **output_buffer) { @@ -344,78 +334,63 @@ while (!done) { - switch (linked_list->id) - { - case irq: + switch (linked_list->id) { + case ACPI_RSTYPE_IRQ: /* * IRQ Resource */ - status = acpi_rs_irq_stream (linked_list, - &buffer, - &bytes_consumed); + status = acpi_rs_irq_stream (linked_list, &buffer, &bytes_consumed); break; - case dma: + case ACPI_RSTYPE_DMA: /* * DMA Resource */ - status = acpi_rs_dma_stream (linked_list, - &buffer, - &bytes_consumed); + status = acpi_rs_dma_stream (linked_list, &buffer, &bytes_consumed); break; - case start_dependent_functions: + case ACPI_RSTYPE_START_DPF: /* * Start Dependent Functions Resource */ status = acpi_rs_start_dependent_functions_stream (linked_list, - &buffer, - &bytes_consumed); + &buffer, &bytes_consumed); break; - case end_dependent_functions: + case ACPI_RSTYPE_END_DPF: /* * End Dependent Functions Resource */ status = acpi_rs_end_dependent_functions_stream (linked_list, - &buffer, - &bytes_consumed); + &buffer, &bytes_consumed); break; - case io: + case ACPI_RSTYPE_IO: /* * IO Port Resource */ - status = acpi_rs_io_stream (linked_list, - &buffer, - &bytes_consumed); + status = acpi_rs_io_stream (linked_list, &buffer, &bytes_consumed); break; - case fixed_io: + case ACPI_RSTYPE_FIXED_IO: /* * Fixed IO Port Resource */ - status = acpi_rs_fixed_io_stream (linked_list, - &buffer, - &bytes_consumed); + status = acpi_rs_fixed_io_stream (linked_list, &buffer, &bytes_consumed); break; - case vendor_specific: + case ACPI_RSTYPE_VENDOR: /* * Vendor Defined Resource */ - status = acpi_rs_vendor_stream (linked_list, - &buffer, - &bytes_consumed); + status = acpi_rs_vendor_stream (linked_list, &buffer, &bytes_consumed); break; - case end_tag: + case ACPI_RSTYPE_END_TAG: /* * End Tag */ - status = acpi_rs_end_tag_stream (linked_list, - &buffer, - &bytes_consumed); + status = acpi_rs_end_tag_stream (linked_list, &buffer, &bytes_consumed); /* * An End Tag indicates the end of the Resource Template @@ -423,58 +398,59 @@ done = TRUE; break; - case memory24: + case ACPI_RSTYPE_MEM24: /* * 24-Bit Memory Resource */ - status = acpi_rs_memory24_stream (linked_list, - &buffer, - &bytes_consumed); + status = acpi_rs_memory24_stream (linked_list, &buffer, &bytes_consumed); break; - case memory32: + case ACPI_RSTYPE_MEM32: /* * 32-Bit Memory Range Resource */ - status = acpi_rs_memory32_range_stream (linked_list, - &buffer, + status = acpi_rs_memory32_range_stream (linked_list, &buffer, &bytes_consumed); break; - case fixed_memory32: + case ACPI_RSTYPE_FIXED_MEM32: /* * 32-Bit Fixed Memory Resource */ - status = acpi_rs_fixed_memory32_stream (linked_list, - &buffer, + status = acpi_rs_fixed_memory32_stream (linked_list, &buffer, &bytes_consumed); break; - case address16: + case ACPI_RSTYPE_ADDRESS16: /* * 16-Bit Address Descriptor Resource */ - status = acpi_rs_address16_stream (linked_list, - &buffer, - &bytes_consumed); + status = acpi_rs_address16_stream (linked_list, &buffer, + &bytes_consumed); break; - case address32: + case ACPI_RSTYPE_ADDRESS32: /* * 32-Bit Address Descriptor Resource */ - status = acpi_rs_address32_stream (linked_list, - &buffer, - &bytes_consumed); + status = acpi_rs_address32_stream (linked_list, &buffer, + &bytes_consumed); + break; + + case ACPI_RSTYPE_ADDRESS64: + /* + * 64-Bit Address Descriptor Resource + */ + status = acpi_rs_address64_stream (linked_list, &buffer, + &bytes_consumed); break; - case extended_irq: + case ACPI_RSTYPE_EXT_IRQ: /* * Extended IRQ Resource */ - status = acpi_rs_extended_irq_stream (linked_list, - &buffer, - &bytes_consumed); + status = acpi_rs_extended_irq_stream (linked_list, &buffer, + &bytes_consumed); break; default: @@ -482,11 +458,16 @@ * If we get here, everything is out of sync, * so exit with an error */ - return (AE_BAD_DATA); + status = AE_BAD_DATA; break; } /* switch (Linked_list->Id) */ + + if (!ACPI_SUCCESS(status)) { + return (status); + } + /* * Set the Buffer to point to the open byte */ @@ -495,10 +476,10 @@ /* * Point to the next object */ - linked_list = (RESOURCE *) ((NATIVE_UINT) linked_list + - (NATIVE_UINT) linked_list->length); + linked_list = POINTER_ADD (ACPI_RESOURCE, + linked_list, linked_list->length); } - return (AE_OK); + return (AE_OK); } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/resources/rsmemory.c linux/drivers/acpi/resources/rsmemory.c --- v2.4.5/linux/drivers/acpi/resources/rsmemory.c Mon Jan 22 13:23:43 2001 +++ linux/drivers/acpi/resources/rsmemory.c Wed Jun 20 17:47:40 2001 @@ -1,12 +1,7 @@ /******************************************************************************* * - * Module Name: rsmem24 - Acpi_rs_memory24_resource - * Acpi_rs_memory24_stream - * Acpi_rs_memory32_range_resource - * Acpi_rs_fixed_memory32_resource - * Acpi_rs_memory32_range_stream - * Acpi_rs_fixed_memory32_stream - * $Revision: 12 $ + * Module Name: rsmem24 - Memory resource descriptors + * $Revision: 14 $ * ******************************************************************************/ @@ -32,7 +27,7 @@ #include "acpi.h" #include "acresrc.h" -#define _COMPONENT RESOURCE_MANAGER +#define _COMPONENT ACPI_RESOURCES MODULE_NAME ("rsmemory") @@ -41,20 +36,20 @@ * FUNCTION: Acpi_rs_memory24_resource * * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte - * stream + * stream * Bytes_consumed - u32 pointer that is filled with - * the number of bytes consumed from - * the Byte_stream_buffer + * the number of bytes consumed from + * the Byte_stream_buffer * Output_buffer - Pointer to the user's return buffer * Structure_size - u32 pointer that is filled with - * the number of bytes in the filled - * in structure + * the number of bytes in the filled + * in structure * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Take the resource byte stream and fill out the appropriate - * structure pointed to by the Output_buffer. Return the - * number of bytes consumed from the byte stream. + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. * ******************************************************************************/ @@ -66,11 +61,10 @@ u32 *structure_size) { u8 *buffer = byte_stream_buffer; - RESOURCE *output_struct = (RESOURCE *) * output_buffer; + ACPI_RESOURCE *output_struct = (ACPI_RESOURCE *) *output_buffer; u16 temp16 = 0; u8 temp8 = 0; - u32 struct_size = sizeof (MEMORY24_RESOURCE) + - RESOURCE_LENGTH_NO_DATA; + u32 struct_size = SIZEOF_RESOURCE (ACPI_RESOURCE_MEM24); /* @@ -81,7 +75,7 @@ MOVE_UNALIGNED16_TO_16 (&temp16, buffer); buffer += 2; *bytes_consumed = temp16 + 3; - output_struct->id = memory24; + output_struct->id = ACPI_RSTYPE_MEM24; /* * Check Byte 3 the Read/Write bit @@ -126,7 +120,6 @@ * Return the final size of the structure */ *structure_size = struct_size; - return (AE_OK); } @@ -138,19 +131,19 @@ * PARAMETERS: Linked_list - Pointer to the resource linked list * Output_buffer - Pointer to the user's return buffer * Bytes_consumed - u32 pointer that is filled with - * the number of bytes of the - * Output_buffer used + * the number of bytes of the + * Output_buffer used * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Take the linked list resource structure and fills in the - * the appropriate bytes in a byte stream + * the appropriate bytes in a byte stream * ******************************************************************************/ ACPI_STATUS acpi_rs_memory24_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u8 **output_buffer, u32 *bytes_consumed) { @@ -206,9 +199,7 @@ /* * Return the number of bytes consumed in this operation */ - *bytes_consumed = (u32) ((NATIVE_UINT) buffer - - (NATIVE_UINT) *output_buffer); - + *bytes_consumed = POINTER_DIFF (buffer, *output_buffer); return (AE_OK); } @@ -218,20 +209,20 @@ * FUNCTION: Acpi_rs_memory32_range_resource * * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte - * stream + * stream * Bytes_consumed - u32 pointer that is filled with - * the number of bytes consumed from - * the Byte_stream_buffer + * the number of bytes consumed from + * the Byte_stream_buffer * Output_buffer - Pointer to the user's return buffer * Structure_size - u32 pointer that is filled with - * the number of bytes in the filled - * in structure + * the number of bytes in the filled + * in structure * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Take the resource byte stream and fill out the appropriate - * structure pointed to by the Output_buffer. Return the - * number of bytes consumed from the byte stream. + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. * ******************************************************************************/ @@ -243,11 +234,10 @@ u32 *structure_size) { u8 *buffer = byte_stream_buffer; - RESOURCE *output_struct = (RESOURCE *) * output_buffer; + ACPI_RESOURCE *output_struct = (ACPI_RESOURCE *) *output_buffer; u16 temp16 = 0; u8 temp8 = 0; - u32 struct_size = sizeof (MEMORY32_RESOURCE) + - RESOURCE_LENGTH_NO_DATA; + u32 struct_size = SIZEOF_RESOURCE (ACPI_RESOURCE_MEM32); /* @@ -259,11 +249,11 @@ buffer += 2; *bytes_consumed = temp16 + 3; - output_struct->id = memory32; + output_struct->id = ACPI_RSTYPE_MEM32; /* * Point to the place in the output buffer where the data portion will - * begin. + * begin. * 1. Set the RESOURCE_DATA * Data to point to it's own address, then * 2. Set the pointer to the next address. * @@ -313,7 +303,6 @@ * Return the final size of the structure */ *structure_size = struct_size; - return (AE_OK); } @@ -323,20 +312,20 @@ * FUNCTION: Acpi_rs_fixed_memory32_resource * * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte - * stream + * stream * Bytes_consumed - u32 pointer that is filled with - * the number of bytes consumed from - * the Byte_stream_buffer + * the number of bytes consumed from + * the Byte_stream_buffer * Output_buffer - Pointer to the user's return buffer * Structure_size - u32 pointer that is filled with - * the number of bytes in the filled - * in structure + * the number of bytes in the filled + * in structure * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Take the resource byte stream and fill out the appropriate - * structure pointed to by the Output_buffer. Return the - * number of bytes consumed from the byte stream. + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. * ******************************************************************************/ @@ -348,11 +337,10 @@ u32 *structure_size) { u8 *buffer = byte_stream_buffer; - RESOURCE *output_struct = (RESOURCE *) * output_buffer; + ACPI_RESOURCE *output_struct = (ACPI_RESOURCE *) *output_buffer; u16 temp16 = 0; u8 temp8 = 0; - u32 struct_size = sizeof (FIXED_MEMORY32_RESOURCE) + - RESOURCE_LENGTH_NO_DATA; + u32 struct_size = SIZEOF_RESOURCE (ACPI_RESOURCE_FIXED_MEM32); /* @@ -364,7 +352,7 @@ buffer += 2; *bytes_consumed = temp16 + 3; - output_struct->id = fixed_memory32; + output_struct->id = ACPI_RSTYPE_FIXED_MEM32; /* * Check Byte 3 the Read/Write bit @@ -395,7 +383,6 @@ * Return the final size of the structure */ *structure_size = struct_size; - return (AE_OK); } @@ -407,19 +394,19 @@ * PARAMETERS: Linked_list - Pointer to the resource linked list * Output_buffer - Pointer to the user's return buffer * Bytes_consumed - u32 pointer that is filled with - * the number of bytes of the - * Output_buffer used + * the number of bytes of the + * Output_buffer used * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Take the linked list resource structure and fills in the - * the appropriate bytes in a byte stream + * the appropriate bytes in a byte stream * ******************************************************************************/ ACPI_STATUS acpi_rs_memory32_range_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u8 **output_buffer, u32 *bytes_consumed) { @@ -476,9 +463,7 @@ /* * Return the number of bytes consumed in this operation */ - *bytes_consumed = (u32) ((NATIVE_UINT) buffer - - (NATIVE_UINT) *output_buffer); - + *bytes_consumed = POINTER_DIFF (buffer, *output_buffer); return (AE_OK); } @@ -490,19 +475,19 @@ * PARAMETERS: Linked_list - Pointer to the resource linked list * Output_buffer - Pointer to the user's return buffer * Bytes_consumed - u32 pointer that is filled with - * the number of bytes of the - * Output_buffer used + * the number of bytes of the + * Output_buffer used * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Take the linked list resource structure and fills in the - * the appropriate bytes in a byte stream + * the appropriate bytes in a byte stream * ******************************************************************************/ ACPI_STATUS acpi_rs_fixed_memory32_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u8 **output_buffer, u32 *bytes_consumed) { @@ -549,9 +534,7 @@ /* * Return the number of bytes consumed in this operation */ - *bytes_consumed = (u32) ((NATIVE_UINT) buffer - - (NATIVE_UINT) *output_buffer); - + *bytes_consumed = POINTER_DIFF (buffer, *output_buffer); return (AE_OK); } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/resources/rsmisc.c linux/drivers/acpi/resources/rsmisc.c --- v2.4.5/linux/drivers/acpi/resources/rsmisc.c Mon Jan 22 13:23:43 2001 +++ linux/drivers/acpi/resources/rsmisc.c Wed Jun 20 17:47:40 2001 @@ -1,14 +1,7 @@ /******************************************************************************* * - * Module Name: rsmisc - Acpi_rs_end_tag_resource - * Acpi_rs_end_tag_stream - * Acpi_rs_vendor_resource - * Acpi_rs_vendor_stream - * Acpi_rs_start_dependent_functions_resource - * Acpi_rs_end_dependent_functions_resource - * Acpi_rs_start_dependent_functions_stream - * Acpi_rs_end_dependent_functions_stream - * $Revision: 12 $ + * Module Name: rsmisc - Miscellaneous resource descriptors + * $Revision: 15 $ * ******************************************************************************/ @@ -34,7 +27,7 @@ #include "acpi.h" #include "acresrc.h" -#define _COMPONENT RESOURCE_MANAGER +#define _COMPONENT ACPI_RESOURCES MODULE_NAME ("rsmisc") @@ -43,20 +36,20 @@ * FUNCTION: Acpi_rs_end_tag_resource * * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte - * stream + * stream * Bytes_consumed - u32 pointer that is filled with - * the number of bytes consumed from - * the Byte_stream_buffer + * the number of bytes consumed from + * the Byte_stream_buffer * Output_buffer - Pointer to the user's return buffer * Structure_size - u32 pointer that is filled with - * the number of bytes in the filled - * in structure + * the number of bytes in the filled + * in structure * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Take the resource byte stream and fill out the appropriate - * structure pointed to by the Output_buffer. Return the - * number of bytes consumed from the byte stream. + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. * ******************************************************************************/ @@ -67,8 +60,8 @@ u8 **output_buffer, u32 *structure_size) { - RESOURCE *output_struct = (RESOURCE *) * output_buffer; - u32 struct_size = RESOURCE_LENGTH; + ACPI_RESOURCE *output_struct = (ACPI_RESOURCE *) *output_buffer; + u32 struct_size = ACPI_RESOURCE_LENGTH; /* @@ -79,7 +72,7 @@ /* * Fill out the structure */ - output_struct->id = end_tag; + output_struct->id = ACPI_RSTYPE_END_TAG; /* * Set the Length parameter @@ -90,7 +83,6 @@ * Return the final size of the structure */ *structure_size = struct_size; - return (AE_OK); } @@ -102,19 +94,19 @@ * PARAMETERS: Linked_list - Pointer to the resource linked list * Output_buffer - Pointer to the user's return buffer * Bytes_consumed - u32 pointer that is filled with - * the number of bytes of the - * Output_buffer used + * the number of bytes of the + * Output_buffer used * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Take the linked list resource structure and fills in the - * the appropriate bytes in a byte stream + * the appropriate bytes in a byte stream * ******************************************************************************/ ACPI_STATUS acpi_rs_end_tag_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u8 **output_buffer, u32 *bytes_consumed) { @@ -130,7 +122,7 @@ /* * Set the Checksum - zero means that the resource data is treated as if - * the checksum operation succeeded (ACPI Spec 1.0b Section 6.4.2.8) + * the checksum operation succeeded (ACPI Spec 1.0b Section 6.4.2.8) */ temp8 = 0; @@ -140,9 +132,7 @@ /* * Return the number of bytes consumed in this operation */ - *bytes_consumed = (u32) ((NATIVE_UINT) buffer - - (NATIVE_UINT) *output_buffer); - + *bytes_consumed = POINTER_DIFF (buffer, *output_buffer); return (AE_OK); } @@ -152,20 +142,20 @@ * FUNCTION: Acpi_rs_vendor_resource * * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte - * stream + * stream * Bytes_consumed - u32 pointer that is filled with - * the number of bytes consumed from - * the Byte_stream_buffer + * the number of bytes consumed from + * the Byte_stream_buffer * Output_buffer - Pointer to the user's return buffer * Structure_size - u32 pointer that is filled with - * the number of bytes in the filled - * in structure + * the number of bytes in the filled + * in structure * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Take the resource byte stream and fill out the appropriate - * structure pointed to by the Output_buffer. Return the - * number of bytes consumed from the byte stream. + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. * ******************************************************************************/ @@ -177,12 +167,11 @@ u32 *structure_size) { u8 *buffer = byte_stream_buffer; - RESOURCE *output_struct = (RESOURCE *) * output_buffer; + ACPI_RESOURCE *output_struct = (ACPI_RESOURCE *) *output_buffer; u16 temp16 = 0; u8 temp8 = 0; u8 index; - u32 struct_size = sizeof (VENDOR_RESOURCE) + - RESOURCE_LENGTH_NO_DATA; + u32 struct_size = SIZEOF_RESOURCE (ACPI_RESOURCE_VENDOR); /* @@ -193,9 +182,8 @@ if (temp8 & 0x80) { /* * Large Item + * Point to the length field */ - /* Point to the length field */ - buffer += 1; /* Dereference */ @@ -214,10 +202,8 @@ else { /* * Small Item + * Dereference the size */ - - /* Dereference the size */ - temp16 = (u8)(*buffer & 0x07); /* Calculate bytes consumed */ @@ -229,7 +215,7 @@ buffer += 1; } - output_struct->id = vendor_specific; + output_struct->id = ACPI_RSTYPE_VENDOR; output_struct->data.vendor_specific.length = temp16; for (index = 0; index < temp16; index++) { @@ -238,9 +224,9 @@ } /* - * In order for the Struct_size to fall on a 32-bit boundry, - * calculate the length of the vendor string and expand the - * Struct_size to the next 32-bit boundry. + * In order for the Struct_size to fall on a 32-bit boundary, + * calculate the length of the vendor string and expand the + * Struct_size to the next 32-bit boundary. */ struct_size += ROUND_UP_TO_32_bITS (temp16); @@ -253,7 +239,6 @@ * Return the final size of the structure */ *structure_size = struct_size; - return (AE_OK); } @@ -265,19 +250,19 @@ * PARAMETERS: Linked_list - Pointer to the resource linked list * Output_buffer - Pointer to the user's return buffer * Bytes_consumed - u32 pointer that is filled with - * the number of bytes of the - * Output_buffer used + * the number of bytes of the + * Output_buffer used * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Take the linked list resource structure and fills in the - * the appropriate bytes in a byte stream + * the appropriate bytes in a byte stream * ******************************************************************************/ ACPI_STATUS acpi_rs_vendor_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u8 **output_buffer, u32 *bytes_consumed) { @@ -290,12 +275,9 @@ /* * Dereference the length to find if this is a large or small item. */ - if(linked_list->data.vendor_specific.length > 7) { /* * Large Item - */ - /* * Set the descriptor field and length bytes */ *buffer = 0x84; @@ -310,9 +292,6 @@ else { /* * Small Item - */ - - /* * Set the descriptor field */ temp8 = 0x70; @@ -335,9 +314,7 @@ /* * Return the number of bytes consumed in this operation */ - *bytes_consumed = (u32) ((NATIVE_UINT) buffer - - (NATIVE_UINT) *output_buffer); - + *bytes_consumed = POINTER_DIFF (buffer, *output_buffer); return (AE_OK); } @@ -347,20 +324,20 @@ * FUNCTION: Acpi_rs_start_dependent_functions_resource * * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte - * stream + * stream * Bytes_consumed - u32 pointer that is filled with - * the number of bytes consumed from - * the Byte_stream_buffer + * the number of bytes consumed from + * the Byte_stream_buffer * Output_buffer - Pointer to the user's return buffer * Structure_size - u32 pointer that is filled with - * the number of bytes in the filled - * in structure + * the number of bytes in the filled + * in structure * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Take the resource byte stream and fill out the appropriate - * structure pointed to by the Output_buffer. Return the - * number of bytes consumed from the byte stream. + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. * ******************************************************************************/ @@ -372,11 +349,9 @@ u32 *structure_size) { u8 *buffer = byte_stream_buffer; - RESOURCE *output_struct = (RESOURCE *) * output_buffer; + ACPI_RESOURCE *output_struct = (ACPI_RESOURCE *) *output_buffer; u8 temp8 = 0; - u32 struct_size = - sizeof(START_DEPENDENT_FUNCTIONS_RESOURCE) + - RESOURCE_LENGTH_NO_DATA; + u32 struct_size = SIZEOF_RESOURCE (ACPI_RESOURCE_START_DPF); /* @@ -386,7 +361,7 @@ *bytes_consumed = (temp8 & 0x01) + 1; - output_struct->id = start_dependent_functions; + output_struct->id = ACPI_RSTYPE_START_DPF; /* * Point to Byte 1 if it is used @@ -398,29 +373,27 @@ /* * Check Compatibility priority */ - output_struct->data.start_dependent_functions.compatibility_priority = - temp8 & 0x03; + output_struct->data.start_dpf.compatibility_priority = temp8 & 0x03; - if (3 == output_struct->data.start_dependent_functions.compatibility_priority) { + if (3 == output_struct->data.start_dpf.compatibility_priority) { return (AE_AML_ERROR); } /* * Check Performance/Robustness preference */ - output_struct->data.start_dependent_functions.performance_robustness = - (temp8 >> 2) & 0x03; + output_struct->data.start_dpf.performance_robustness = (temp8 >> 2) & 0x03; - if (3 == output_struct->data.start_dependent_functions.performance_robustness) { + if (3 == output_struct->data.start_dpf.performance_robustness) { return (AE_AML_ERROR); } } else { - output_struct->data.start_dependent_functions.compatibility_priority = + output_struct->data.start_dpf.compatibility_priority = ACCEPTABLE_CONFIGURATION; - output_struct->data.start_dependent_functions.performance_robustness = + output_struct->data.start_dpf.performance_robustness = ACCEPTABLE_CONFIGURATION; } @@ -433,7 +406,6 @@ * Return the final size of the structure */ *structure_size = struct_size; - return (AE_OK); } @@ -443,20 +415,20 @@ * FUNCTION: Acpi_rs_end_dependent_functions_resource * * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte - * stream + * stream * Bytes_consumed - u32 pointer that is filled with - * the number of bytes consumed from - * the Byte_stream_buffer + * the number of bytes consumed from + * the Byte_stream_buffer * Output_buffer - Pointer to the user's return buffer * Structure_size - u32 pointer that is filled with - * the number of bytes in the filled - * in structure + * the number of bytes in the filled + * in structure * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Take the resource byte stream and fill out the appropriate - * structure pointed to by the Output_buffer. Return the - * number of bytes consumed from the byte stream. + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. * ******************************************************************************/ @@ -467,8 +439,8 @@ u8 **output_buffer, u32 *structure_size) { - RESOURCE *output_struct = (RESOURCE *) * output_buffer; - u32 struct_size = RESOURCE_LENGTH; + ACPI_RESOURCE *output_struct = (ACPI_RESOURCE *) *output_buffer; + u32 struct_size = ACPI_RESOURCE_LENGTH; /* @@ -479,7 +451,7 @@ /* * Fill out the structure */ - output_struct->id = end_dependent_functions; + output_struct->id = ACPI_RSTYPE_END_DPF; /* * Set the Length parameter @@ -490,7 +462,6 @@ * Return the final size of the structure */ *structure_size = struct_size; - return (AE_OK); } @@ -502,19 +473,19 @@ * PARAMETERS: Linked_list - Pointer to the resource linked list * Output_buffer - Pointer to the user's return buffer * Bytes_consumed - u32 pointer that is filled with - * the number of bytes of the - * Output_buffer used + * the number of bytes of the + * Output_buffer used * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Take the linked list resource structure and fills in the - * the appropriate bytes in a byte stream + * the appropriate bytes in a byte stream * ******************************************************************************/ ACPI_STATUS acpi_rs_start_dependent_functions_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u8 **output_buffer, u32 *bytes_consumed) { @@ -524,13 +495,12 @@ /* * The descriptor field is set based upon whether a byte is needed - * to contain Priority data. + * to contain Priority data. */ if (ACCEPTABLE_CONFIGURATION == - linked_list->data.start_dependent_functions.compatibility_priority && + linked_list->data.start_dpf.compatibility_priority && ACCEPTABLE_CONFIGURATION == - linked_list->data.start_dependent_functions.performance_robustness) - { + linked_list->data.start_dpf.performance_robustness) { *buffer = 0x30; } else { @@ -541,13 +511,10 @@ * Set the Priority Byte Definition */ temp8 = 0; - temp8 = (u8) - ((linked_list->data.start_dependent_functions.performance_robustness & - 0x03) << 2); - temp8 |= - (linked_list->data.start_dependent_functions.compatibility_priority & - 0x03); - + temp8 = (u8) ((linked_list->data.start_dpf.performance_robustness & + 0x03) << 2); + temp8 |= (linked_list->data.start_dpf.compatibility_priority & + 0x03); *buffer = temp8; } @@ -556,9 +523,7 @@ /* * Return the number of bytes consumed in this operation */ - *bytes_consumed = (u32) ((NATIVE_UINT) buffer - - (NATIVE_UINT) *output_buffer); - + *bytes_consumed = POINTER_DIFF (buffer, *output_buffer); return (AE_OK); } @@ -570,19 +535,19 @@ * PARAMETERS: Linked_list - Pointer to the resource linked list * Output_buffer - Pointer to the user's return buffer * Bytes_consumed - u32 pointer that is filled with - * the number of bytes of the - * Output_buffer used + * the number of bytes of the + * Output_buffer used * - * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * RETURN: Status * * DESCRIPTION: Take the linked list resource structure and fills in the - * the appropriate bytes in a byte stream + * the appropriate bytes in a byte stream * ******************************************************************************/ ACPI_STATUS acpi_rs_end_dependent_functions_stream ( - RESOURCE *linked_list, + ACPI_RESOURCE *linked_list, u8 **output_buffer, u32 *bytes_consumed ) @@ -599,9 +564,7 @@ /* * Return the number of bytes consumed in this operation */ - *bytes_consumed = (u32) ((NATIVE_UINT) buffer - - (NATIVE_UINT) *output_buffer); - + *bytes_consumed = POINTER_DIFF (buffer, *output_buffer); return (AE_OK); } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/resources/rsutils.c linux/drivers/acpi/resources/rsutils.c --- v2.4.5/linux/drivers/acpi/resources/rsutils.c Mon Jan 22 13:23:43 2001 +++ linux/drivers/acpi/resources/rsutils.c Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: rsutils - Utilities for the resource manager - * $Revision: 14 $ + * $Revision: 19 $ * ******************************************************************************/ @@ -29,7 +29,7 @@ #include "acresrc.h" -#define _COMPONENT RESOURCE_MANAGER +#define _COMPONENT ACPI_RESOURCES MODULE_NAME ("rsutils") @@ -41,7 +41,7 @@ * Ret_buffer - a pointer to a buffer structure for the * results * - * RETURN: Status - the status of the call + * RETURN: Status * * DESCRIPTION: This function is called to get the _PRT value of an object * contained in an object specified by the handle passed in @@ -96,8 +96,7 @@ * byte stream buffer that comes back from the _CRS method * execution. */ - status = acpi_rs_create_pci_routing_table (ret_obj, - ret_buffer->pointer, + status = acpi_rs_create_pci_routing_table (ret_obj, ret_buffer->pointer, &buffer_space_needed); /* @@ -111,8 +110,7 @@ cleanup: - acpi_cm_remove_reference (ret_obj); - + acpi_ut_remove_reference (ret_obj); return (status); } @@ -125,7 +123,7 @@ * Ret_buffer - a pointer to a buffer structure for the * results * - * RETURN: Status - the status of the call + * RETURN: Status * * DESCRIPTION: This function is called to get the _CRS value of an object * contained in an object specified by the handle passed in @@ -177,10 +175,8 @@ * byte stream buffer that comes back from the _CRS method * execution. */ - status = acpi_rs_create_resource_list (ret_obj, - ret_buffer->pointer, - &buffer_space_needed); - + status = acpi_rs_create_resource_list (ret_obj, ret_buffer->pointer, + &buffer_space_needed); /* @@ -194,8 +190,7 @@ cleanup: - acpi_cm_remove_reference (ret_obj); - + acpi_ut_remove_reference (ret_obj); return (status); } @@ -208,7 +203,7 @@ * Ret_buffer - a pointer to a buffer structure for the * results * - * RETURN: Status - the status of the call + * RETURN: Status * * DESCRIPTION: This function is called to get the _PRS value of an object * contained in an object specified by the handle passed in @@ -260,9 +255,8 @@ * byte stream buffer that comes back from the _CRS method * execution. */ - status = acpi_rs_create_resource_list (ret_obj, - ret_buffer->pointer, - &buffer_space_needed); + status = acpi_rs_create_resource_list (ret_obj, ret_buffer->pointer, + &buffer_space_needed); /* * Tell the user how much of the buffer we have used or is needed @@ -275,8 +269,7 @@ cleanup: - acpi_cm_remove_reference (ret_obj); - + acpi_ut_remove_reference (ret_obj); return (status); } @@ -289,7 +282,7 @@ * In_buffer - a pointer to a buffer structure of the * parameter * - * RETURN: Status - the status of the call + * RETURN: Status * * DESCRIPTION: This function is called to set the _SRS of an object contained * in an object specified by the handle passed in @@ -315,20 +308,19 @@ /* * The In_buffer parameter will point to a linked list of - * resource parameters. It needs to be formatted into a - * byte stream to be sent in as an input parameter. + * resource parameters. It needs to be formatted into a + * byte stream to be sent in as an input parameter. */ buffer_size_needed = 0; /* * First call is to get the buffer size needed */ - status = acpi_rs_create_byte_stream (in_buffer->pointer, - byte_stream, - &buffer_size_needed); + status = acpi_rs_create_byte_stream (in_buffer->pointer, byte_stream, + &buffer_size_needed); /* * We expect a return of AE_BUFFER_OVERFLOW - * if not, exit with the error + * if not, exit with the error */ if (AE_BUFFER_OVERFLOW != status) { return (status); @@ -337,7 +329,7 @@ /* * Allocate the buffer needed */ - byte_stream = acpi_cm_callocate(buffer_size_needed); + byte_stream = acpi_ut_callocate(buffer_size_needed); if (NULL == byte_stream) { return (AE_NO_MEMORY); } @@ -345,20 +337,19 @@ /* * Now call to convert the linked list into a byte stream */ - status = acpi_rs_create_byte_stream (in_buffer->pointer, - byte_stream, - &buffer_size_needed); + status = acpi_rs_create_byte_stream (in_buffer->pointer, byte_stream, + &buffer_size_needed); if (ACPI_FAILURE (status)) { goto cleanup; } /* - * Init the param object + * Init the param object */ - acpi_cm_init_static_object (¶m_obj); + acpi_ut_init_static_object (¶m_obj); /* - * Method requires one parameter. Set it up + * Method requires one parameter. Set it up */ params [0] = ¶m_obj; params [1] = NULL; @@ -371,17 +362,16 @@ param_obj.buffer.pointer = byte_stream; /* - * Execute the method, no return value + * Execute the method, no return value */ status = acpi_ns_evaluate_relative (handle, "_SRS", params, NULL); /* - * Clean up and return the status from Acpi_ns_evaluate_relative + * Clean up and return the status from Acpi_ns_evaluate_relative */ - cleanup: - acpi_cm_free (byte_stream); + acpi_ut_free (byte_stream); return (status); } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/resources/rsxface.c linux/drivers/acpi/resources/rsxface.c --- v2.4.5/linux/drivers/acpi/resources/rsxface.c Mon Jan 22 13:23:43 2001 +++ linux/drivers/acpi/resources/rsxface.c Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /******************************************************************************* * - * Module Name: rsxface - Public interfaces to the ACPI subsystem - * $Revision: 10 $ + * Module Name: rsxface - Public interfaces to the resource manager + * $Revision: 13 $ * ******************************************************************************/ @@ -29,7 +29,7 @@ #include "acnamesp.h" #include "acresrc.h" -#define _COMPONENT RESOURCE_MANAGER +#define _COMPONENT ACPI_RESOURCES MODULE_NAME ("rsxface") @@ -41,7 +41,7 @@ * Ret_buffer - a pointer to a buffer to receive the * current resources for the device * - * RETURN: Status - the status of the call + * RETURN: Status * * DESCRIPTION: This function is called to get the IRQ routing table for a * specific bus. The caller must first acquire a handle for the @@ -64,21 +64,26 @@ ACPI_STATUS status; + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + /* - * Must have a valid handle and buffer, So we have to have a handle - * and a return buffer structure, and if there is a non-zero buffer length - * we also need a valid pointer in the buffer. If it's a zero buffer length, - * we'll be returning the needed buffer size, so keep going. + * Must have a valid handle and buffer, So we have to have a handle + * and a return buffer structure, and if there is a non-zero buffer length + * we also need a valid pointer in the buffer. If it's a zero buffer length, + * we'll be returning the needed buffer size, so keep going. */ if ((!device_handle) || (!ret_buffer) || - ((!ret_buffer->pointer) && (ret_buffer->length))) - { + ((!ret_buffer->pointer) && (ret_buffer->length))) { return (AE_BAD_PARAMETER); } status = acpi_rs_get_prt_method_data (device_handle, ret_buffer); - return (status); } @@ -92,7 +97,7 @@ * Ret_buffer - a pointer to a buffer to receive the * current resources for the device * - * RETURN: Status - the status of the call + * RETURN: Status * * DESCRIPTION: This function is called to get the current resources for a * specific device. The caller must first acquire a handle for @@ -115,21 +120,26 @@ ACPI_STATUS status; + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + /* - * Must have a valid handle and buffer, So we have to have a handle - * and a return buffer structure, and if there is a non-zero buffer length - * we also need a valid pointer in the buffer. If it's a zero buffer length, - * we'll be returning the needed buffer size, so keep going. + * Must have a valid handle and buffer, So we have to have a handle + * and a return buffer structure, and if there is a non-zero buffer length + * we also need a valid pointer in the buffer. If it's a zero buffer length, + * we'll be returning the needed buffer size, so keep going. */ if ((!device_handle) || (!ret_buffer) || - ((ret_buffer->length) && (!ret_buffer->pointer))) - { + ((ret_buffer->length) && (!ret_buffer->pointer))) { return (AE_BAD_PARAMETER); } status = acpi_rs_get_crs_method_data (device_handle, ret_buffer); - return (status); } @@ -143,7 +153,7 @@ * Ret_buffer - a pointer to a buffer to receive the * resources for the device * - * RETURN: Status - the status of the call + * RETURN: Status * * DESCRIPTION: This function is called to get a list of the possible resources * for a specific device. The caller must first acquire a handle @@ -163,21 +173,26 @@ ACPI_STATUS status; + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + /* - * Must have a valid handle and buffer, So we have to have a handle - * and a return buffer structure, and if there is a non-zero buffer length - * we also need a valid pointer in the buffer. If it's a zero buffer length, - * we'll be returning the needed buffer size, so keep going. + * Must have a valid handle and buffer, So we have to have a handle + * and a return buffer structure, and if there is a non-zero buffer length + * we also need a valid pointer in the buffer. If it's a zero buffer length, + * we'll be returning the needed buffer size, so keep going. */ if ((!device_handle) || (!ret_buffer) || - ((ret_buffer->length) && (!ret_buffer->pointer))) - { + ((ret_buffer->length) && (!ret_buffer->pointer))) { return (AE_BAD_PARAMETER); - } + } status = acpi_rs_get_prs_method_data (device_handle, ret_buffer); - return (status); } @@ -191,7 +206,7 @@ * In_buffer - a pointer to a buffer containing the * resources to be set for the device * - * RETURN: Status - the status of the call + * RETURN: Status * * DESCRIPTION: This function is called to set the current resources for a * specific device. The caller must first acquire a handle for @@ -208,18 +223,23 @@ ACPI_STATUS status; + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + /* - * Must have a valid handle and buffer + * Must have a valid handle and buffer */ if ((!device_handle) || (!in_buffer) || (!in_buffer->pointer) || - (!in_buffer->length)) - { + (!in_buffer->length)) { return (AE_BAD_PARAMETER); } status = acpi_rs_set_srs_method_data (device_handle, in_buffer); - return (status); } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/sys.c linux/drivers/acpi/sys.c --- v2.4.5/linux/drivers/acpi/sys.c Mon Jan 29 10:15:59 2001 +++ linux/drivers/acpi/sys.c Wed Dec 31 16:00:00 1969 @@ -1,146 +0,0 @@ -/* - * sys.c - System management (suspend, ...) - * - * Copyright (C) 2000 Andrew Henroid - * - * 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 "acpi.h" -#include "driver.h" - -#define _COMPONENT OS_DEPENDENT - MODULE_NAME ("sys") - -struct acpi_enter_sx_ctx -{ - wait_queue_head_t wait; - unsigned int state; -}; - -volatile acpi_sstate_t acpi_sleep_state = ACPI_STATE_S0; - -/* - * Enter system sleep state - */ -static void -acpi_enter_sx_async(void *context) -{ - struct acpi_enter_sx_ctx *ctx = (struct acpi_enter_sx_ctx*) context; - ACPI_OBJECT_LIST arg_list; - ACPI_OBJECT arg; - - acpi_enter_sleep_state(ctx->state); - - /* either we are in S1, or the transition failed, as the other states resume - from the waking vector */ - if (ctx->state != ACPI_STATE_S1) { - printk(KERN_ERR "Could not enter S%d\n", ctx->state); - goto out; - } - - /* wait until S1 is entered */ - while (!(acpi_hw_register_bit_access(ACPI_READ, ACPI_MTX_LOCK, WAK_STS))) - safe_halt(); - - /* run the _WAK method */ - memset(&arg_list, 0, sizeof(arg_list)); - arg_list.count = 1; - arg_list.pointer = &arg; - - memset(&arg, 0, sizeof(arg)); - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = ctx->state; - - acpi_evaluate_object(NULL, "\\_WAK", &arg_list, NULL); - - out: - acpi_sleep_state = ACPI_STATE_S0; - - if (waitqueue_active(&ctx->wait)) - wake_up_interruptible(&ctx->wait); -} - -/* - * Enter soft-off (S5) - */ -static void -acpi_power_off(void) -{ - struct acpi_enter_sx_ctx ctx; - - init_waitqueue_head(&ctx.wait); - ctx.state = ACPI_STATE_S5; - acpi_enter_sx_async(&ctx); -} - -/* - * Enter system sleep state and wait for completion - */ -int -acpi_enter_sx(acpi_sstate_t state) -{ - struct acpi_enter_sx_ctx ctx; - DECLARE_WAITQUEUE(wait, current); - int ret = 0; - - init_waitqueue_head(&ctx.wait); - ctx.state = state; - - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&ctx.wait, &wait); - - if (acpi_os_queue_for_execution(0, acpi_enter_sx_async, &ctx)) - ret = -1; - - if (!ret) - schedule(); - - set_current_state(TASK_RUNNING); - remove_wait_queue(&ctx.wait, &wait); - - if (!ret && signal_pending(current)) - ret = -ERESTARTSYS; - - return ret; -} - -int -acpi_sys_init(void) -{ - u8 sx; - u8 type_a; - u8 type_b; - - printk(KERN_INFO "ACPI: System firmware supports:"); - - for (sx = ACPI_STATE_S0; sx <= ACPI_STATE_S5; sx++) { - if (ACPI_SUCCESS( - acpi_hw_obtain_sleep_type_register_data(sx, - &type_a, - &type_b))) { - - printk(" S%d", sx); - } - } - printk("\n"); - - pm_power_off = acpi_power_off; - - return 0; -} diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/table.c linux/drivers/acpi/table.c --- v2.4.5/linux/drivers/acpi/table.c Mon Jan 29 10:15:59 2001 +++ linux/drivers/acpi/table.c Wed Dec 31 16:00:00 1969 @@ -1,71 +0,0 @@ -/* - * table.c - ACPI tables, chipset, and errata handling - * - * Copyright (C) 2000 Andrew Henroid - * - * 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 "acpi.h" -#include "driver.h" - -#define _COMPONENT OS_DEPENDENT - MODULE_NAME ("table") - -FADT_DESCRIPTOR acpi_fadt; - -/* - * Fetch the fadt information - */ -static int -acpi_fetch_fadt(void) -{ - ACPI_BUFFER buffer; - - memset(&acpi_fadt, 0, sizeof(acpi_fadt)); - buffer.pointer = &acpi_fadt; - buffer.length = sizeof(acpi_fadt); - if (!ACPI_SUCCESS(acpi_get_table(ACPI_TABLE_FADT, 1, &buffer))) { - printk(KERN_ERR "ACPI: missing fadt\n"); - return -ENODEV; - } - - return 0; -} - -/* - * Find and load ACPI tables - */ -int -acpi_find_and_load_tables(u64 rsdp) -{ - if (!ACPI_SUCCESS(acpi_load_tables(rsdp))) { - printk(KERN_INFO "ACPI: System description table load failed\n"); - acpi_terminate(); - return -1; - } - - if (acpi_fetch_fadt()) { - acpi_terminate(); - return -1; - } - - return 0; -} diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/tables/Makefile linux/drivers/acpi/tables/Makefile --- v2.4.5/linux/drivers/acpi/tables/Makefile Fri Dec 29 14:07:21 2000 +++ linux/drivers/acpi/tables/Makefile Wed Jun 20 17:47:40 2001 @@ -1,16 +1,12 @@ # # Makefile for all Linux ACPI interpreter subdirectories +# EXCEPT for the ospm directory # -O_TARGET := ../$(shell basename `pwd`).o +O_TARGET := $(notdir $(CURDIR)).o obj-$(CONFIG_ACPI) := $(patsubst %.c,%.o,$(wildcard *.c)) -EXTRA_CFLAGS += -I../include - EXTRA_CFLAGS += $(ACPI_CFLAGS) include $(TOPDIR)/Rules.make - -clean: - $(RM) *.o diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/tables/tbconvrt.c linux/drivers/acpi/tables/tbconvrt.c --- v2.4.5/linux/drivers/acpi/tables/tbconvrt.c Fri Feb 9 11:45:58 2001 +++ linux/drivers/acpi/tables/tbconvrt.c Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: tbconvrt - ACPI Table conversion utilities - * $Revision: 19 $ + * $Revision: 23 $ * *****************************************************************************/ @@ -30,34 +30,13 @@ #include "actbl.h" -#define _COMPONENT TABLE_MANAGER +#define _COMPONENT ACPI_TABLES MODULE_NAME ("tbconvrt") -/* - * Build a GAS structure from earlier ACPI table entries (V1.0 and 0.71 extensions) - * - * 1) Address space - * 2) Length in bytes -- convert to length in bits - * 3) Bit offset is zero - * 4) Reserved field is zero - * 5) Expand address to 64 bits - */ -#define ASL_BUILD_GAS_FROM_ENTRY(a,b,c,d) {a.address_space_id = (u8) d;\ - a.register_bit_width = (u8) MUL_8 (b);\ - a.register_bit_offset = 0;\ - a.reserved = 0;\ - ACPI_STORE_ADDRESS (a.address,c);} - - -/* ACPI V1.0 entries -- address space is always I/O */ - -#define ASL_BUILD_GAS_FROM_V1_ENTRY(a,b,c) ASL_BUILD_GAS_FROM_ENTRY(a,b,c,ADDRESS_SPACE_SYSTEM_IO) - - /******************************************************************************* * - * FUNCTION: Acpi_tb_convert_to_xsdt + * FUNCTION: Acpi_tb_get_table_count * * PARAMETERS: * @@ -67,20 +46,17 @@ * ******************************************************************************/ -ACPI_STATUS -acpi_tb_convert_to_xsdt ( - ACPI_TABLE_DESC *table_info, - u32 *number_of_tables) +u32 +acpi_tb_get_table_count ( + RSDP_DESCRIPTOR *RSDP, + ACPI_TABLE_HEADER *RSDT) { - u32 table_size; u32 pointer_size; - u32 i; - XSDT_DESCRIPTOR *new_table; #ifndef _IA64 - if (acpi_gbl_RSDP->revision < 2) { + if (RSDP->revision < 2) { pointer_size = sizeof (u32); } @@ -97,9 +73,34 @@ * is architecture-dependent. */ - table_size = table_info->pointer->length; - *number_of_tables = (table_size - - sizeof (ACPI_TABLE_HEADER)) / pointer_size; + return ((RSDT->length - sizeof (ACPI_TABLE_HEADER)) / pointer_size); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_convert_to_xsdt + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_convert_to_xsdt ( + ACPI_TABLE_DESC *table_info, + u32 *number_of_tables) +{ + u32 table_size; + u32 i; + XSDT_DESCRIPTOR *new_table; + + + *number_of_tables = acpi_tb_get_table_count (acpi_gbl_RSDP, table_info->pointer); + /* Compute size of the converted XSDT */ @@ -108,7 +109,7 @@ /* Allocate an XSDT */ - new_table = acpi_cm_callocate (table_size); + new_table = acpi_ut_callocate (table_size); if (!new_table) { return (AE_NO_MEMORY); } @@ -193,7 +194,7 @@ /* Acpi_gbl_FADT is valid */ /* Allocate and zero the 2.0 buffer */ - FADT2 = acpi_cm_callocate (sizeof (FADT_DESCRIPTOR_REV2)); + FADT2 = acpi_ut_callocate (sizeof (FADT_DESCRIPTOR_REV2)); if (FADT2 == NULL) { return (AE_NO_MEMORY); } @@ -501,7 +502,7 @@ /* Allocate a common FACS */ - common_facs = acpi_cm_callocate (sizeof (ACPI_COMMON_FACS)); + common_facs = acpi_ut_callocate (sizeof (ACPI_COMMON_FACS)); if (!common_facs) { return (AE_NO_MEMORY); } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/tables/tbget.c linux/drivers/acpi/tables/tbget.c --- v2.4.5/linux/drivers/acpi/tables/tbget.c Mon Jan 22 13:23:43 2001 +++ linux/drivers/acpi/tables/tbget.c Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: tbget - ACPI Table get* routines - * $Revision: 43 $ + * $Revision: 48 $ * *****************************************************************************/ @@ -29,11 +29,12 @@ #include "actables.h" -#define _COMPONENT TABLE_MANAGER +#define _COMPONENT ACPI_TABLES MODULE_NAME ("tbget") #define RSDP_CHECKSUM_LENGTH 20 + /******************************************************************************* * * FUNCTION: Acpi_tb_get_table_ptr @@ -72,13 +73,11 @@ * For all table types (Single/Multiple), the first * instance is always in the list head. */ - if (instance == 1) { /* * Just pluck the pointer out of the global table! * Will be null if no table is present */ - *table_ptr_loc = acpi_gbl_acpi_tables[table_type].pointer; return (AE_OK); } @@ -92,11 +91,11 @@ } /* Walk the list to get the desired table - * Since the if (Instance == 1) check above checked for the - * first table, setting Table_desc equal to the .Next member - * is actually pointing to the second table. Therefore, we - * need to walk from the 2nd table until we reach the Instance - * that the user is looking for and return its table pointer. + * Since the if (Instance == 1) check above checked for the + * first table, setting Table_desc equal to the .Next member + * is actually pointing to the second table. Therefore, we + * need to walk from the 2nd table until we reach the Instance + * that the user is looking for and return its table pointer. */ table_desc = acpi_gbl_acpi_tables[table_type].next; for (i = 2; i < instance; i++) { @@ -159,7 +158,7 @@ /* Allocate buffer for the entire table */ - full_table = acpi_cm_allocate (table_header->length); + full_table = acpi_ut_allocate (table_header->length); if (!full_table) { return (AE_NO_MEMORY); } @@ -182,8 +181,7 @@ else { size = SIZE_IN_HEADER; - status = acpi_tb_map_acpi_table (physical_address, &size, - (void **) &full_table); + status = acpi_tb_map_acpi_table (physical_address, &size, &full_table); if (ACPI_FAILURE (status)) { return (status); } @@ -382,8 +380,7 @@ /* * Obtain access to the RSDP structure */ - status = acpi_os_map_memory (rsdp_physical_address, - sizeof (RSDP_DESCRIPTOR), + status = acpi_os_map_memory (rsdp_physical_address, sizeof (RSDP_DESCRIPTOR), (void **) &table_ptr); if (ACPI_FAILURE (status)) { return (status); @@ -439,32 +436,24 @@ /******************************************************************************* * - * FUNCTION: Acpi_tb_get_table_rsdt + * FUNCTION: Acpi_tb_get_rsdt_address * - * PARAMETERS: Number_of_tables - Where the table count is placed + * PARAMETERS: None * - * RETURN: Status + * RETURN: RSDT physical address * - * DESCRIPTION: Load and validate the RSDP (ptr) and RSDT (table) + * DESCRIPTION: Extract the address of the RSDT or XSDT, depending on the + * version of the RSDP * ******************************************************************************/ -ACPI_STATUS -acpi_tb_get_table_rsdt ( - u32 *number_of_tables) +ACPI_PHYSICAL_ADDRESS +acpi_tb_get_rsdt_address (void) { - ACPI_TABLE_DESC table_info; - ACPI_STATUS status = AE_OK; ACPI_PHYSICAL_ADDRESS physical_address; - u32 signature_length; - char *table_signature; /* - * Get the RSDT from the RSDP - */ - - /* * For RSDP revision 0 or 1, we use the RSDT. * For RSDP revision 2 (and above), we use the XSDT */ @@ -475,17 +464,132 @@ #else physical_address = (ACPI_PHYSICAL_ADDRESS) acpi_gbl_RSDP->rsdt_physical_address; #endif - table_signature = RSDT_SIG; - signature_length = sizeof (RSDT_SIG) -1; } + else { physical_address = (ACPI_PHYSICAL_ADDRESS) ACPI_GET_ADDRESS (acpi_gbl_RSDP->xsdt_physical_address); - table_signature = XSDT_SIG; - signature_length = sizeof (XSDT_SIG) -1; } + return (physical_address); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_validate_rsdt + * + * PARAMETERS: Table_ptr - Addressable pointer to the RSDT. + * + * RETURN: Status + * + * DESCRIPTION: Validate signature for the RSDT or XSDT + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_validate_rsdt ( + ACPI_TABLE_HEADER *table_ptr) +{ + u32 no_match; + + + /* + * For RSDP revision 0 or 1, we use the RSDT. + * For RSDP revision 2 (and above), we use the XSDT + */ + if (acpi_gbl_RSDP->revision < 2) { + no_match = STRNCMP ((char *) table_ptr, RSDT_SIG, + sizeof (RSDT_SIG) -1); + } + else { + no_match = STRNCMP ((char *) table_ptr, XSDT_SIG, + sizeof (XSDT_SIG) -1); + } + + + if (no_match) { + /* Invalid RSDT or XSDT signature */ + + REPORT_ERROR (("Invalid signature where RSDP indicates RSDT/XSDT should be located\n")); + + return (AE_BAD_SIGNATURE); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_get_table_pointer + * + * PARAMETERS: Physical_address - Address from RSDT + * Flags - virtual or physical addressing + * Table_ptr - Addressable address (output) + * + * RETURN: Status + * + * DESCRIPTION: Create an addressable pointer to an ACPI table + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_get_table_pointer ( + ACPI_PHYSICAL_ADDRESS physical_address, + u32 flags, + u32 *size, + ACPI_TABLE_HEADER **table_ptr) +{ + ACPI_STATUS status; + + + if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) { + *size = SIZE_IN_HEADER; + status = acpi_tb_map_acpi_table (physical_address, size, table_ptr); + } + + else { + *size = 0; + *table_ptr = (ACPI_TABLE_HEADER *) (ACPI_TBLPTR) physical_address; + + status = AE_OK; + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_get_table_rsdt + * + * PARAMETERS: Number_of_tables - Where the table count is placed + * + * RETURN: Status + * + * DESCRIPTION: Load and validate the RSDP (ptr) and RSDT (table) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_get_table_rsdt ( + u32 *number_of_tables) +{ + ACPI_TABLE_DESC table_info; + ACPI_STATUS status; + ACPI_PHYSICAL_ADDRESS physical_address; + + + /* + * Get the RSDT from the RSDP + */ + + + physical_address = acpi_tb_get_rsdt_address (); + + /* Get the RSDT/XSDT */ status = acpi_tb_get_table (physical_address, NULL, &table_info); @@ -496,20 +600,16 @@ /* Check the RSDT or XSDT signature */ - if (STRNCMP ((char *) table_info.pointer, table_signature, - signature_length)) - { - /* Invalid RSDT or XSDT signature */ - - REPORT_ERROR (("Invalid signature where RSDP indicates %s should be located\n", - table_signature)); - + status = acpi_tb_validate_rsdt (table_info.pointer); + if (ACPI_FAILURE (status)) { return (status); } - /* Valid RSDT signature, verify the checksum */ - + /* + * Valid RSDT signature, verify the checksum. If it fails, just + * print a warning and ignore it. + */ status = acpi_tb_verify_table_checksum (table_info.pointer); @@ -538,7 +638,7 @@ * FUNCTION: Acpi_tb_get_table_facs * * PARAMETERS: *Buffer_ptr - If Buffer_ptr is valid, read data from - * buffer rather than searching memory + * buffer rather than searching memory * *Table_info - Where the table info is returned * * RETURN: Status @@ -555,7 +655,7 @@ ACPI_TABLE_HEADER *buffer_ptr, ACPI_TABLE_DESC *table_info) { - void *table_ptr = NULL; + ACPI_TABLE_HEADER *table_ptr = NULL; u32 size; u8 allocation; ACPI_STATUS status = AE_OK; @@ -573,7 +673,7 @@ * Getting table from a file -- allocate a buffer and * read the table. */ - table_ptr = acpi_cm_allocate (size); + table_ptr = acpi_ut_allocate (size); if(!table_ptr) { return (AE_NO_MEMORY); } @@ -590,7 +690,7 @@ status = acpi_tb_map_acpi_table ((ACPI_PHYSICAL_ADDRESS) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xfirmware_ctrl), &size, &table_ptr); - if (ACPI_FAILURE(status)) { + if (ACPI_FAILURE (status)) { return (status); } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/tables/tbinstal.c linux/drivers/acpi/tables/tbinstal.c --- v2.4.5/linux/drivers/acpi/tables/tbinstal.c Mon Jan 22 13:23:43 2001 +++ linux/drivers/acpi/tables/tbinstal.c Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: tbinstal - ACPI table installation and removal - * $Revision: 36 $ + * $Revision: 39 $ * *****************************************************************************/ @@ -29,7 +29,7 @@ #include "actables.h" -#define _COMPONENT TABLE_MANAGER +#define _COMPONENT ACPI_TABLES MODULE_NAME ("tbinstal") @@ -68,13 +68,13 @@ /* Lock tables while installing */ - acpi_cm_acquire_mutex (ACPI_MTX_TABLES); + acpi_ut_acquire_mutex (ACPI_MTX_TABLES); /* Install the table into the global data structure */ status = acpi_tb_init_table_descriptor (table_info->type, table_info); - acpi_cm_release_mutex (ACPI_MTX_TABLES); + acpi_ut_release_mutex (ACPI_MTX_TABLES); return (status); } @@ -127,8 +127,7 @@ for (i = 1; i < NUM_ACPI_TABLES; i++) { if (!STRNCMP (table_header->signature, acpi_gbl_acpi_table_data[i].signature, - acpi_gbl_acpi_table_data[i].sig_length)) - { + acpi_gbl_acpi_table_data[i].sig_length)) { /* * Found a signature match, get the pertinent info from the * Table_data structure @@ -226,7 +225,7 @@ */ if (list_head->pointer) { - table_desc = acpi_cm_callocate (sizeof (ACPI_TABLE_DESC)); + table_desc = acpi_ut_callocate (sizeof (ACPI_TABLE_DESC)); if (!table_desc) { return (AE_NO_MEMORY); } @@ -262,7 +261,7 @@ table_desc->aml_pointer = (u8 *) (table_desc->pointer + 1), table_desc->aml_length = (u32) (table_desc->length - (u32) sizeof (ACPI_TABLE_HEADER)); - table_desc->table_id = acpi_cm_allocate_owner_id (OWNER_TYPE_TABLE); + table_desc->table_id = acpi_ut_allocate_owner_id (OWNER_TYPE_TABLE); table_desc->loaded_into_namespace = FALSE; /* @@ -337,7 +336,7 @@ } - acpi_cm_acquire_mutex (ACPI_MTX_TABLES); + acpi_ut_acquire_mutex (ACPI_MTX_TABLES); /* Free the table */ @@ -346,8 +345,7 @@ /* Clear the appropriate "typed" global table pointer */ - switch (type) - { + switch (type) { case ACPI_TABLE_RSDP: acpi_gbl_RSDP = NULL; break; @@ -374,7 +372,7 @@ break; } - acpi_cm_release_mutex (ACPI_MTX_TABLES); + acpi_ut_release_mutex (ACPI_MTX_TABLES); return; } @@ -445,8 +443,7 @@ if (table_desc->pointer) { /* Valid table, determine type of memory allocation */ - switch (table_desc->allocation) - { + switch (table_desc->allocation) { case ACPI_MEM_NOT_ALLOCATED: break; @@ -454,7 +451,7 @@ case ACPI_MEM_ALLOCATED: - acpi_cm_free (table_desc->base_pointer); + acpi_ut_free (table_desc->base_pointer); break; @@ -527,7 +524,7 @@ /* Free the table descriptor */ next_desc = table_desc->next; - acpi_cm_free (table_desc); + acpi_ut_free (table_desc); } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/tables/tbutils.c linux/drivers/acpi/tables/tbutils.c --- v2.4.5/linux/drivers/acpi/tables/tbutils.c Mon Jan 22 13:23:43 2001 +++ linux/drivers/acpi/tables/tbutils.c Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: tbutils - Table manipulation utilities - * $Revision: 33 $ + * $Revision: 38 $ * *****************************************************************************/ @@ -29,7 +29,7 @@ #include "acinterp.h" -#define _COMPONENT TABLE_MANAGER +#define _COMPONENT ACPI_TABLES MODULE_NAME ("tbutils") @@ -57,8 +57,7 @@ for (i = 0; i < ACPI_TABLE_MAX; i++) { list_head = &acpi_gbl_acpi_tables[i]; - do - { + do { if (list_head->table_id == table_id) { *table_desc = list_head; return (AE_OK); @@ -108,8 +107,7 @@ /* Check for a pointer within the DSDT */ if ((acpi_gbl_DSDT) && - (IS_IN_ACPI_TABLE (where, acpi_gbl_DSDT))) - { + (IS_IN_ACPI_TABLE (where, acpi_gbl_DSDT))) { return (TRUE); } @@ -177,6 +175,9 @@ ACPI_NAME signature; + PROC_NAME ("Tb_validate_table_header"); + + /* Verify that this is a valid address */ if (!acpi_os_readable (table_header, sizeof (ACPI_TABLE_HEADER))) { @@ -187,8 +188,8 @@ /* Ensure that the signature is 4 ASCII characters */ MOVE_UNALIGNED32_TO_32 (&signature, &table_header->signature); - if (!acpi_cm_valid_acpi_name (signature)) { - REPORT_WARNING (("Invalid table signature found\n")); + if (!acpi_ut_valid_acpi_name (signature)) { + REPORT_WARNING (("Invalid table signature %4.4s found\n", &signature)); return (AE_BAD_SIGNATURE); } @@ -224,7 +225,7 @@ acpi_tb_map_acpi_table ( ACPI_PHYSICAL_ADDRESS physical_address, u32 *size, - void **logical_address) + ACPI_TABLE_HEADER **logical_address) { ACPI_TABLE_HEADER *table; u32 table_size = *size; diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/tables/tbxface.c linux/drivers/acpi/tables/tbxface.c --- v2.4.5/linux/drivers/acpi/tables/tbxface.c Mon Jan 22 13:23:43 2001 +++ linux/drivers/acpi/tables/tbxface.c Wed Jun 20 17:47:40 2001 @@ -2,7 +2,7 @@ * * Module Name: tbxface - Public interfaces to the ACPI subsystem * ACPI table oriented interfaces - * $Revision: 34 $ + * $Revision: 39 $ * *****************************************************************************/ @@ -31,7 +31,7 @@ #include "actables.h" -#define _COMPONENT TABLE_MANAGER +#define _COMPONENT ACPI_TABLES MODULE_NAME ("tbxface") @@ -52,16 +52,23 @@ acpi_load_tables ( ACPI_PHYSICAL_ADDRESS rsdp_physical_address) { - ACPI_STATUS status = AE_OK; + ACPI_STATUS status; u32 number_of_tables = 0; + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + /* Map and validate the RSDP */ status = acpi_tb_verify_rsdp (rsdp_physical_address); if (ACPI_FAILURE (status)) { REPORT_ERROR (("Acpi_load_tables: RSDP Failed validation: %s\n", - acpi_cm_format_exception (status))); + acpi_ut_format_exception (status))); goto error_exit; } @@ -70,7 +77,7 @@ status = acpi_tb_get_table_rsdt (&number_of_tables); if (ACPI_FAILURE (status)) { REPORT_ERROR (("Acpi_load_tables: Could not load RSDT: %s\n", - acpi_cm_format_exception (status))); + acpi_ut_format_exception (status))); goto error_exit; } @@ -79,7 +86,7 @@ status = acpi_tb_get_all_tables (number_of_tables, NULL); if (ACPI_FAILURE (status)) { REPORT_ERROR (("Acpi_load_tables: Error getting required tables (DSDT/FADT/FACS): %s\n", - acpi_cm_format_exception (status))); + acpi_ut_format_exception (status))); goto error_exit; } @@ -89,7 +96,7 @@ status = acpi_ns_load_namespace (); if (ACPI_FAILURE (status)) { REPORT_ERROR (("Acpi_load_tables: Could not load namespace: %s\n", - acpi_cm_format_exception (status))); + acpi_ut_format_exception (status))); goto error_exit; } @@ -98,7 +105,7 @@ error_exit: REPORT_ERROR (("Acpi_load_tables: Could not load tables: %s\n", - acpi_cm_format_exception (status))); + acpi_ut_format_exception (status))); return (status); } @@ -118,8 +125,6 @@ * a valid header. The header fields will be verified, and if it * is determined that the table is invalid, the call will fail. * - * If the call fails an appropriate status will be returned. - * ******************************************************************************/ ACPI_STATUS @@ -130,6 +135,13 @@ ACPI_TABLE_DESC table_info; + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + if (!table_ptr) { return (AE_BAD_PARAMETER); } @@ -182,7 +194,15 @@ ACPI_TABLE_TYPE table_type) { ACPI_TABLE_DESC *list_head; + ACPI_STATUS status; + + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } /* Parameter validation */ @@ -194,15 +214,13 @@ /* Find all tables of the requested type */ list_head = &acpi_gbl_acpi_tables[table_type]; - do - { + do { /* * Delete all namespace entries owned by this table. Note that these * entries can appear anywhere in the namespace by virtue of the AML * "Scope" operator. Thus, we need to track ownership by an ID, not * simply a position within the hierarchy */ - acpi_ns_delete_namespace_by_owner (list_head->table_id); /* Delete (or unmap) the actual table */ @@ -234,9 +252,6 @@ * function is not valid for the RSD PTR table since it does not * have a standard header and is fixed length. * - * If the operation fails for any reason an appropriate status will - * be returned and the contents of Out_table_header are undefined. - * ******************************************************************************/ ACPI_STATUS @@ -249,10 +264,16 @@ ACPI_STATUS status; + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + if ((instance == 0) || (table_type == ACPI_TABLE_RSDP) || - (!out_table_header)) - { + (!out_table_header)) { return (AE_BAD_PARAMETER); } @@ -260,8 +281,7 @@ if ((table_type > ACPI_TABLE_MAX) || (IS_SINGLE_TABLE (acpi_gbl_acpi_table_data[table_type].flags) && - instance > 1)) - { + instance > 1)) { return (AE_BAD_PARAMETER); } @@ -311,9 +331,6 @@ * copied into the Out_buffer->Buf_ptr buffer. This table will be * a complete table including the header. * - * If the operation fails an appropriate status will be returned - * and the contents of Out_buffer are undefined. - * ******************************************************************************/ ACPI_STATUS @@ -327,13 +344,19 @@ u32 ret_buf_len; + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + /* * If we have a buffer, we must have a length too */ if ((instance == 0) || (!ret_buffer) || - ((!ret_buffer->pointer) && (ret_buffer->length))) - { + ((!ret_buffer->pointer) && (ret_buffer->length))) { return (AE_BAD_PARAMETER); } @@ -341,8 +364,7 @@ if ((table_type > ACPI_TABLE_MAX) || (IS_SINGLE_TABLE (acpi_gbl_acpi_table_data[table_type].flags) && - instance > 1)) - { + instance > 1)) { return (AE_BAD_PARAMETER); } @@ -356,7 +378,7 @@ /* * Acpi_tb_get_table_ptr will return a NULL pointer if the - * table is not loaded. + * table is not loaded. */ if (tbl_ptr == NULL) { return (AE_NOT_EXIST); @@ -389,4 +411,5 @@ return (AE_OK); } + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/tables/tbxfroot.c linux/drivers/acpi/tables/tbxfroot.c --- v2.4.5/linux/drivers/acpi/tables/tbxfroot.c Mon Jan 22 13:23:43 2001 +++ linux/drivers/acpi/tables/tbxfroot.c Wed Jun 20 17:47:40 2001 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: tbxfroot - Find the root ACPI table (RSDT) - * $Revision: 35 $ + * $Revision: 39 $ * *****************************************************************************/ @@ -29,7 +29,7 @@ #include "actables.h" -#define _COMPONENT TABLE_MANAGER +#define _COMPONENT ACPI_TABLES MODULE_NAME ("tbxfroot") #define RSDP_CHECKSUM_LENGTH 20 @@ -57,7 +57,7 @@ /* Get the RSDP */ - status = acpi_tb_find_rsdp (&table_info); + status = acpi_tb_find_rsdp (&table_info, ACPI_LOGICAL_ADDRESSING); if (ACPI_FAILURE (status)) { return (AE_NO_ACPI_TABLES); } @@ -94,15 +94,13 @@ for (offset = 0, mem_rover = start_address; offset < length; - offset += RSDP_SCAN_STEP, mem_rover += RSDP_SCAN_STEP) - { + offset += RSDP_SCAN_STEP, mem_rover += RSDP_SCAN_STEP) { /* The signature and checksum must both be correct */ if (STRNCMP ((NATIVE_CHAR *) mem_rover, RSDP_SIG, sizeof (RSDP_SIG)-1) == 0 && - acpi_tb_checksum (mem_rover, RSDP_CHECKSUM_LENGTH) == 0) - { + acpi_tb_checksum (mem_rover, RSDP_CHECKSUM_LENGTH) == 0) { /* If so, we have found the RSDP */ return (mem_rover); @@ -119,9 +117,9 @@ * * FUNCTION: Acpi_tb_find_rsdp * - * PARAMETERS: *Buffer_ptr - If == NULL, read data from buffer - * rather than searching memory - * *Table_info - Where the table info is returned + * PARAMETERS: *Table_info - Where the table info is returned + * Flags - Current memory mode (logical vs. + * physical addressing) * * RETURN: Status * @@ -136,7 +134,8 @@ ACPI_STATUS acpi_tb_find_rsdp ( - ACPI_TABLE_DESC *table_info) + ACPI_TABLE_DESC *table_info, + u32 flags) { u8 *table_ptr; u8 *mem_rover; @@ -145,70 +144,231 @@ /* - * Search memory for RSDP. First map low physical memory. + * Scan supports either 1) Logical addressing or 2) Physical addressing */ + if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) { + /* + * 1) Search EBDA (low memory) paragraphs + */ + status = acpi_os_map_memory (LO_RSDP_WINDOW_BASE, LO_RSDP_WINDOW_SIZE, + (void **) &table_ptr); + if (ACPI_FAILURE (status)) { + return (status); + } - status = acpi_os_map_memory (LO_RSDP_WINDOW_BASE, LO_RSDP_WINDOW_SIZE, - (void **)&table_ptr); + mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, LO_RSDP_WINDOW_SIZE); + acpi_os_unmap_memory (table_ptr, LO_RSDP_WINDOW_SIZE); - if (ACPI_FAILURE (status)) { - return (status); + if (mem_rover) { + /* Found it, return the physical address */ + + phys_addr = LO_RSDP_WINDOW_BASE; + phys_addr += (mem_rover - table_ptr); + + table_info->physical_address = phys_addr; + + return (AE_OK); + } + + /* + * 2) Search upper memory: 16-byte boundaries in E0000h-F0000h + */ + status = acpi_os_map_memory (HI_RSDP_WINDOW_BASE, HI_RSDP_WINDOW_SIZE, + (void **) &table_ptr); + if (ACPI_FAILURE (status)) { + return (status); + } + + mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, HI_RSDP_WINDOW_SIZE); + acpi_os_unmap_memory (table_ptr, HI_RSDP_WINDOW_SIZE); + + if (mem_rover) { + /* Found it, return the physical address */ + + phys_addr = HI_RSDP_WINDOW_BASE; + phys_addr += (mem_rover - table_ptr); + + table_info->physical_address = phys_addr; + + return (AE_OK); + } } + /* - * 1) Search EBDA (low memory) paragraphs + * Physical addressing */ + else { + /* + * 1) Search EBDA (low memory) paragraphs + */ + mem_rover = acpi_tb_scan_memory_for_rsdp ((u8 *) LO_RSDP_WINDOW_BASE, + LO_RSDP_WINDOW_SIZE); + if (mem_rover) { + /* Found it, return the physical address */ - mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, LO_RSDP_WINDOW_SIZE); + table_info->physical_address = (ACPI_TBLPTR) mem_rover; + return (AE_OK); + } - /* This mapping is no longer needed */ + /* + * 2) Search upper memory: 16-byte boundaries in E0000h-F0000h + */ + mem_rover = acpi_tb_scan_memory_for_rsdp ((u8 *) HI_RSDP_WINDOW_BASE, + HI_RSDP_WINDOW_SIZE); + if (mem_rover) { + /* Found it, return the physical address */ - acpi_os_unmap_memory (table_ptr, LO_RSDP_WINDOW_SIZE); + table_info->physical_address = (ACPI_TBLPTR) mem_rover; + return (AE_OK); + } + } - if (mem_rover) { - /* Found it, return the physical address */ - phys_addr = LO_RSDP_WINDOW_BASE; - phys_addr += (mem_rover - table_ptr); + /* RSDP signature was not found */ - table_info->physical_address = phys_addr; + return (AE_NOT_FOUND); +} - return (AE_OK); - } + +/******************************************************************************* + * + * FUNCTION: Acpi_get_firmware_table + * + * PARAMETERS: Signature - Any ACPI table signature + * Instance - the non zero instance of the table, allows + * support for multiple tables of the same type + * Flags - 0: Physical/Virtual support + * Ret_buffer - pointer to a structure containing a buffer to + * receive the table + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get an ACPI table. The caller + * supplies an Out_buffer large enough to contain the entire ACPI + * table. Upon completion + * the Out_buffer->Length field will indicate the number of bytes + * copied into the Out_buffer->Buf_ptr buffer. This table will be + * a complete table including the header. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_firmware_table ( + ACPI_STRING signature, + u32 instance, + u32 flags, + ACPI_TABLE_HEADER **table_pointer) +{ + ACPI_PHYSICAL_ADDRESS physical_address; + ACPI_TABLE_DESC table_info; + ACPI_TABLE_HEADER *rsdt_ptr; + ACPI_TABLE_HEADER *table_ptr; + ACPI_STATUS status; + u32 rsdt_size; + u32 table_size; + u32 table_count; + u32 i; + u32 j; /* - * 2) Search upper memory: 16-byte boundaries in E0000h-F0000h + * Ensure that at least the table manager is initialized. We don't + * require that the entire ACPI subsystem is up for this interface */ - status = acpi_os_map_memory (HI_RSDP_WINDOW_BASE, HI_RSDP_WINDOW_SIZE, - (void **)&table_ptr); + /* + * If we have a buffer, we must have a length too + */ + if ((instance == 0) || + (!signature) || + (!table_pointer)) { + return (AE_BAD_PARAMETER); + } + + /* Get the RSDP by scanning low memory */ + + status = acpi_tb_find_rsdp (&table_info, flags); + if (ACPI_FAILURE (status)) { + return (AE_NO_ACPI_TABLES); + } + + acpi_gbl_RSDP = (RSDP_DESCRIPTOR *) table_info.pointer; + + + /* Get the RSDT and validate it */ + + physical_address = acpi_tb_get_rsdt_address (); + status = acpi_tb_get_table_pointer (physical_address, flags, &rsdt_size, &rsdt_ptr); if (ACPI_FAILURE (status)) { return (status); } - mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, HI_RSDP_WINDOW_SIZE); + status = acpi_tb_validate_rsdt (rsdt_ptr); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + - /* This mapping is no longer needed */ + /* Get the number of table pointers within the RSDT */ - acpi_os_unmap_memory (table_ptr, HI_RSDP_WINDOW_SIZE); + table_count = acpi_tb_get_table_count (acpi_gbl_RSDP, rsdt_ptr); - if (mem_rover) { - /* Found it, return the physical address */ - phys_addr = HI_RSDP_WINDOW_BASE; - phys_addr += (mem_rover - table_ptr); + /* + * Search the RSDT/XSDT for the correct instance of the + * requested table + */ + for (i = 0, j = 0; i < table_count; i++) { + /* Get the next table pointer */ + + if (acpi_gbl_RSDP->revision < 2) { + physical_address = ((RSDT_DESCRIPTOR *) rsdt_ptr)->table_offset_entry[i]; + } + else { + physical_address = (ACPI_PHYSICAL_ADDRESS) + ACPI_GET_ADDRESS (((XSDT_DESCRIPTOR *) rsdt_ptr)->table_offset_entry[i]); + } + + /* Get addressibility if necessary */ + + status = acpi_tb_get_table_pointer (physical_address, flags, &table_size, &table_ptr); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + /* Compare table signatures and table instance */ - table_info->physical_address = phys_addr; + if (!STRNCMP ((char *) table_ptr, signature, STRLEN (signature))) { + /* An instance of the table was found */ - return (AE_OK); + j++; + if (j >= instance) { + /* Found the correct instance */ + + *table_pointer = table_ptr; + goto cleanup; + } + } + + /* Delete table mapping if using virtual addressing */ + + if (table_size) { + acpi_os_unmap_memory (table_ptr, table_size); + } } + /* Did not find the table */ - /* RSDP signature was not found */ + status = AE_NOT_EXIST; - return (AE_NOT_FOUND); + +cleanup: + if (rsdt_size) { + acpi_os_unmap_memory (rsdt_ptr, rsdt_size); + } + return (status); } diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/utilities/Makefile linux/drivers/acpi/utilities/Makefile --- v2.4.5/linux/drivers/acpi/utilities/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/utilities/Makefile Wed Jun 20 17:47:40 2001 @@ -0,0 +1,12 @@ +# +# Makefile for all Linux ACPI interpreter subdirectories +# EXCEPT for the ospm directory +# + +O_TARGET := $(notdir $(CURDIR)).o + +obj-$(CONFIG_ACPI) := $(patsubst %.c,%.o,$(wildcard *.c)) + +EXTRA_CFLAGS += $(ACPI_CFLAGS) + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/utilities/utalloc.c linux/drivers/acpi/utilities/utalloc.c --- v2.4.5/linux/drivers/acpi/utilities/utalloc.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/utilities/utalloc.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,169 @@ +/****************************************************************************** + * + * Module Name: utalloc - local memory allocation routines + * $Revision: 90 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acparser.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "acglobal.h" + +#define _COMPONENT ACPI_UTILITIES + MODULE_NAME ("utalloc") + + +/******************************************************************************* + * + * FUNCTION: _Ut_allocate + * + * PARAMETERS: Size - Size of the allocation + * Component - Component type of caller + * Module - Source file name of caller + * Line - Line number of caller + * + * RETURN: Address of the allocated memory on success, NULL on failure. + * + * DESCRIPTION: The subsystem's equivalent of malloc. + * + ******************************************************************************/ + +void * +_ut_allocate ( + u32 size, + u32 component, + NATIVE_CHAR *module, + u32 line) +{ + void *address = NULL; + + + /* Check for an inadvertent size of zero bytes */ + + if (!size) { + _REPORT_ERROR (module, line, component, + ("Ut_allocate: Attempt to allocate zero bytes\n")); + size = 1; + } + + address = acpi_os_allocate (size); + if (!address) { + /* Report allocation error */ + + _REPORT_ERROR (module, line, component, + ("Ut_allocate: Could not allocate size %X\n", size)); + + return (NULL); + } + + + return (address); +} + + +/******************************************************************************* + * + * FUNCTION: _Ut_callocate + * + * PARAMETERS: Size - Size of the allocation + * Component - Component type of caller + * Module - Source file name of caller + * Line - Line number of caller + * + * RETURN: Address of the allocated memory on success, NULL on failure. + * + * DESCRIPTION: Subsystem equivalent of calloc. + * + ******************************************************************************/ + +void * +_ut_callocate ( + u32 size, + u32 component, + NATIVE_CHAR *module, + u32 line) +{ + void *address = NULL; + + + /* Check for an inadvertent size of zero bytes */ + + if (!size) { + _REPORT_ERROR (module, line, component, + ("Ut_callocate: Attempt to allocate zero bytes\n")); + return (NULL); + } + + + address = acpi_os_callocate (size); + if (!address) { + /* Report allocation error */ + + _REPORT_ERROR (module, line, component, + ("Ut_callocate: Could not allocate size %X\n", size)); + return (NULL); + } + + + return (address); +} + + +/******************************************************************************* + * + * FUNCTION: _Ut_free + * + * PARAMETERS: Address - Address of the memory to deallocate + * Component - Component type of caller + * Module - Source file name of caller + * Line - Line number of caller + * + * RETURN: None + * + * DESCRIPTION: Frees the memory at Address + * + ******************************************************************************/ + +void +_ut_free ( + void *address, + u32 component, + NATIVE_CHAR *module, + u32 line) +{ + + if (NULL == address) { + _REPORT_ERROR (module, line, component, + ("_Ut_free: Trying to delete a NULL address\n")); + + return; + } + + + acpi_os_free (address); + + return; +} + + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/utilities/utcopy.c linux/drivers/acpi/utilities/utcopy.c --- v2.4.5/linux/drivers/acpi/utilities/utcopy.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/utilities/utcopy.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,707 @@ +/****************************************************************************** + * + * Module Name: utcopy - Internal to external object translation utilities + * $Revision: 74 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "amlcode.h" + + +#define _COMPONENT ACPI_UTILITIES + MODULE_NAME ("utcopy") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_copy_isimple_to_esimple + * + * PARAMETERS: *Internal_object - Pointer to the object we are examining + * *Buffer - Where the object is returned + * *Space_used - Where the data length is returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to place a simple object in a user + * buffer. + * + * The buffer is assumed to have sufficient space for the object. + * + ******************************************************************************/ + +static ACPI_STATUS +acpi_ut_copy_isimple_to_esimple ( + ACPI_OPERAND_OBJECT *internal_object, + ACPI_OBJECT *external_object, + u8 *data_space, + u32 *buffer_space_used) +{ + u32 length = 0; + ACPI_STATUS status = AE_OK; + + + /* + * Check for NULL object case (could be an uninitialized + * package element + */ + + if (!internal_object) { + *buffer_space_used = 0; + return (AE_OK); + } + + /* Always clear the external object */ + + MEMSET (external_object, 0, sizeof (ACPI_OBJECT)); + + /* + * In general, the external object will be the same type as + * the internal object + */ + + external_object->type = internal_object->common.type; + + /* However, only a limited number of external types are supported */ + + switch (internal_object->common.type) { + + case ACPI_TYPE_STRING: + + length = internal_object->string.length + 1; + external_object->string.length = internal_object->string.length; + external_object->string.pointer = (NATIVE_CHAR *) data_space; + MEMCPY ((void *) data_space, (void *) internal_object->string.pointer, length); + break; + + + case ACPI_TYPE_BUFFER: + + length = internal_object->buffer.length; + external_object->buffer.length = internal_object->buffer.length; + external_object->buffer.pointer = data_space; + MEMCPY ((void *) data_space, (void *) internal_object->buffer.pointer, length); + break; + + + case ACPI_TYPE_INTEGER: + + external_object->integer.value= internal_object->integer.value; + break; + + + case INTERNAL_TYPE_REFERENCE: + + /* + * This is an object reference. Attempt to dereference it. + */ + + switch (internal_object->reference.opcode) { + case AML_ZERO_OP: + external_object->type = ACPI_TYPE_INTEGER; + external_object->integer.value = 0; + break; + + case AML_ONE_OP: + external_object->type = ACPI_TYPE_INTEGER; + external_object->integer.value = 1; + break; + + case AML_ONES_OP: + external_object->type = ACPI_TYPE_INTEGER; + external_object->integer.value = ACPI_INTEGER_MAX; + break; + + case AML_INT_NAMEPATH_OP: + /* + * This is a named reference, get the string. We already know that + * we have room for it, use max length + */ + length = MAX_STRING_LENGTH; + external_object->type = ACPI_TYPE_STRING; + external_object->string.pointer = (NATIVE_CHAR *) data_space; + status = acpi_ns_handle_to_pathname ((ACPI_HANDLE *) internal_object->reference.node, + &length, (char *) data_space); + + /* Converted (external) string length is returned from above */ + + external_object->string.length = length; + break; + + default: + /* + * Use the object type of "Any" to indicate a reference + * to object containing a handle to an ACPI named object. + */ + external_object->type = ACPI_TYPE_ANY; + external_object->reference.handle = internal_object->reference.node; + break; + } + break; + + + case ACPI_TYPE_PROCESSOR: + + external_object->processor.proc_id = internal_object->processor.proc_id; + external_object->processor.pblk_address = internal_object->processor.address; + external_object->processor.pblk_length = internal_object->processor.length; + break; + + + case ACPI_TYPE_POWER: + + external_object->power_resource.system_level = + internal_object->power_resource.system_level; + + external_object->power_resource.resource_order = + internal_object->power_resource.resource_order; + break; + + + default: + /* + * There is no corresponding external object type + */ + return (AE_SUPPORT); + break; + } + + + *buffer_space_used = (u32) ROUND_UP_TO_NATIVE_WORD (length); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_copy_ielement_to_eelement + * + * PARAMETERS: ACPI_PKG_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Copy one package element to another package element + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ut_copy_ielement_to_eelement ( + u8 object_type, + ACPI_OPERAND_OBJECT *source_object, + ACPI_GENERIC_STATE *state, + void *context) +{ + ACPI_STATUS status = AE_OK; + ACPI_PKG_INFO *info = (ACPI_PKG_INFO *) context; + u32 object_space; + u32 this_index; + ACPI_OBJECT *target_object; + + + this_index = state->pkg.index; + target_object = (ACPI_OBJECT *) + &((ACPI_OBJECT *)(state->pkg.dest_object))->package.elements[this_index]; + + + switch (object_type) { + case ACPI_COPY_TYPE_SIMPLE: + + /* + * This is a simple or null object -- get the size + */ + + status = acpi_ut_copy_isimple_to_esimple (source_object, + target_object, info->free_space, &object_space); + if (ACPI_FAILURE (status)) { + return (status); + } + + break; + + case ACPI_COPY_TYPE_PACKAGE: + + /* + * Build the package object + */ + target_object->type = ACPI_TYPE_PACKAGE; + target_object->package.count = source_object->package.count; + target_object->package.elements = (ACPI_OBJECT *) info->free_space; + + /* + * Pass the new package object back to the package walk routine + */ + state->pkg.this_target_obj = target_object; + + /* + * Save space for the array of objects (Package elements) + * update the buffer length counter + */ + object_space = (u32) ROUND_UP_TO_NATIVE_WORD ( + target_object->package.count * sizeof (ACPI_OBJECT)); + break; + + default: + return (AE_BAD_PARAMETER); + } + + + info->free_space += object_space; + info->length += object_space; + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_copy_ipackage_to_epackage + * + * PARAMETERS: *Internal_object - Pointer to the object we are returning + * *Buffer - Where the object is returned + * *Space_used - Where the object length is returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to place a package object in a user + * buffer. A package object by definition contains other objects. + * + * The buffer is assumed to have sufficient space for the object. + * The caller must have verified the buffer length needed using the + * Acpi_ut_get_object_size function before calling this function. + * + ******************************************************************************/ + +static ACPI_STATUS +acpi_ut_copy_ipackage_to_epackage ( + ACPI_OPERAND_OBJECT *internal_object, + u8 *buffer, + u32 *space_used) +{ + ACPI_OBJECT *external_object; + ACPI_STATUS status; + ACPI_PKG_INFO info; + + + /* + * First package at head of the buffer + */ + external_object = (ACPI_OBJECT *) buffer; + + /* + * Free space begins right after the first package + */ + info.length = 0; + info.object_space = 0; + info.num_packages = 1; + info.free_space = buffer + ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT)); + + + external_object->type = internal_object->common.type; + external_object->package.count = internal_object->package.count; + external_object->package.elements = (ACPI_OBJECT *) info.free_space; + + + /* + * Build an array of ACPI_OBJECTS in the buffer + * and move the free space past it + */ + + info.free_space += external_object->package.count * + ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT)); + + + status = acpi_ut_walk_package_tree (internal_object, external_object, + acpi_ut_copy_ielement_to_eelement, &info); + + *space_used = info.length; + + return (status); + +} + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_copy_iobject_to_eobject + * + * PARAMETERS: *Internal_object - The internal object to be converted + * *Buffer_ptr - Where the object is returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to build an API object to be returned to + * the caller. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ut_copy_iobject_to_eobject ( + ACPI_OPERAND_OBJECT *internal_object, + ACPI_BUFFER *ret_buffer) +{ + ACPI_STATUS status; + + + if (IS_THIS_OBJECT_TYPE (internal_object, ACPI_TYPE_PACKAGE)) { + /* + * Package object: Copy all subobjects (including + * nested packages) + */ + status = acpi_ut_copy_ipackage_to_epackage (internal_object, + ret_buffer->pointer, &ret_buffer->length); + } + + else { + /* + * Build a simple object (no nested objects) + */ + status = acpi_ut_copy_isimple_to_esimple (internal_object, + (ACPI_OBJECT *) ret_buffer->pointer, + ((u8 *) ret_buffer->pointer + + ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT))), + &ret_buffer->length); + /* + * build simple does not include the object size in the length + * so we add it in here + */ + ret_buffer->length += sizeof (ACPI_OBJECT); + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_copy_esimple_to_isimple + * + * PARAMETERS: *External_object - The external object to be converted + * *Internal_object - Where the internal object is returned + * + * RETURN: Status + * + * DESCRIPTION: This function copies an external object to an internal one. + * NOTE: Pointers can be copied, we don't need to copy data. + * (The pointers have to be valid in our address space no matter + * what we do with them!) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ut_copy_esimple_to_isimple ( + ACPI_OBJECT *external_object, + ACPI_OPERAND_OBJECT *internal_object) +{ + + + internal_object->common.type = (u8) external_object->type; + + switch (external_object->type) { + + case ACPI_TYPE_STRING: + + internal_object->string.length = external_object->string.length; + internal_object->string.pointer = external_object->string.pointer; + break; + + + case ACPI_TYPE_BUFFER: + + internal_object->buffer.length = external_object->buffer.length; + internal_object->buffer.pointer = external_object->buffer.pointer; + break; + + + case ACPI_TYPE_INTEGER: + /* + * Number is included in the object itself + */ + internal_object->integer.value = external_object->integer.value; + break; + + + default: + return (AE_CTRL_RETURN_VALUE); + break; + } + + + return (AE_OK); +} + + +#ifdef ACPI_FUTURE_IMPLEMENTATION + +/* Code to convert packages that are parameters to control methods */ + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_copy_epackage_to_ipackage + * + * PARAMETERS: *Internal_object - Pointer to the object we are returning + * *Buffer - Where the object is returned + * *Space_used - Where the length of the object is returned + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to place a package object in a user + * buffer. A package object by definition contains other objects. + * + * The buffer is assumed to have sufficient space for the object. + * The caller must have verified the buffer length needed using the + * Acpi_ut_get_object_size function before calling this function. + * + ******************************************************************************/ + +static ACPI_STATUS +acpi_ut_copy_epackage_to_ipackage ( + ACPI_OPERAND_OBJECT *internal_object, + u8 *buffer, + u32 *space_used) +{ + u8 *free_space; + ACPI_OBJECT *external_object; + u32 length = 0; + u32 this_index; + u32 object_space = 0; + ACPI_OPERAND_OBJECT *this_internal_obj; + ACPI_OBJECT *this_external_obj; + + + /* + * First package at head of the buffer + */ + external_object = (ACPI_OBJECT *)buffer; + + /* + * Free space begins right after the first package + */ + free_space = buffer + sizeof(ACPI_OBJECT); + + + external_object->type = internal_object->common.type; + external_object->package.count = internal_object->package.count; + external_object->package.elements = (ACPI_OBJECT *)free_space; + + + /* + * Build an array of ACPI_OBJECTS in the buffer + * and move the free space past it + */ + + free_space += external_object->package.count * sizeof(ACPI_OBJECT); + + + /* Call Walk_package */ + +} + +#endif /* Future implementation */ + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_copy_eobject_to_iobject + * + * PARAMETERS: *Internal_object - The external object to be converted + * *Buffer_ptr - Where the internal object is returned + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: Converts an external object to an internal object. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ut_copy_eobject_to_iobject ( + ACPI_OBJECT *external_object, + ACPI_OPERAND_OBJECT *internal_object) +{ + ACPI_STATUS status; + + + if (external_object->type == ACPI_TYPE_PACKAGE) { + /* + * Package objects contain other objects (which can be objects) + * buildpackage does it all + * + * TBD: Package conversion must be completed and tested + * NOTE: this code converts packages as input parameters to + * control methods only. This is a very, very rare case. + */ +/* + Status = Acpi_ut_copy_epackage_to_ipackage(Internal_object, + Ret_buffer->Pointer, + &Ret_buffer->Length); +*/ + return (AE_NOT_IMPLEMENTED); + } + + else { + /* + * Build a simple object (no nested objects) + */ + status = acpi_ut_copy_esimple_to_isimple (external_object, internal_object); + /* + * build simple does not include the object size in the length + * so we add it in here + */ + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_copy_ielement_to_ielement + * + * PARAMETERS: ACPI_PKG_CALLBACK + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: Copy one package element to another package element + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ut_copy_ielement_to_ielement ( + u8 object_type, + ACPI_OPERAND_OBJECT *source_object, + ACPI_GENERIC_STATE *state, + void *context) +{ + ACPI_STATUS status = AE_OK; + u32 this_index; + ACPI_OPERAND_OBJECT **this_target_ptr; + ACPI_OPERAND_OBJECT *target_object; + + + this_index = state->pkg.index; + this_target_ptr = (ACPI_OPERAND_OBJECT **) + &state->pkg.dest_object->package.elements[this_index]; + + switch (object_type) { + case 0: + + /* + * This is a simple object, just copy it + */ + target_object = acpi_ut_create_internal_object (source_object->common.type); + if (!target_object) { + return (AE_NO_MEMORY); + } + + status = acpi_ex_store_object_to_object (source_object, target_object, + (ACPI_WALK_STATE *) context); + if (ACPI_FAILURE (status)) { + return (status); + } + + *this_target_ptr = target_object; + break; + + + case 1: + /* + * This object is a package - go down another nesting level + * Create and build the package object + */ + target_object = acpi_ut_create_internal_object (ACPI_TYPE_PACKAGE); + if (!target_object) { + /* TBD: must delete package created up to this point */ + + return (AE_NO_MEMORY); + } + + target_object->package.count = source_object->package.count; + + /* + * Pass the new package object back to the package walk routine + */ + state->pkg.this_target_obj = target_object; + + /* + * Store the object pointer in the parent package object + */ + *this_target_ptr = target_object; + break; + + default: + return (AE_BAD_PARAMETER); + } + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_copy_ipackage_to_ipackage + * + * PARAMETERS: *Source_obj - Pointer to the source package object + * *Dest_obj - Where the internal object is returned + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to copy an internal package object + * into another internal package object. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ut_copy_ipackage_to_ipackage ( + ACPI_OPERAND_OBJECT *source_obj, + ACPI_OPERAND_OBJECT *dest_obj, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status = AE_OK; + + + dest_obj->common.type = source_obj->common.type; + dest_obj->package.count = source_obj->package.count; + + + /* + * Create the object array and walk the source package tree + */ + + dest_obj->package.elements = acpi_ut_callocate ((source_obj->package.count + 1) * + sizeof (void *)); + dest_obj->package.next_element = dest_obj->package.elements; + + if (!dest_obj->package.elements) { + REPORT_ERROR ( + ("Aml_build_copy_internal_package_object: Package allocation failure\n")); + return (AE_NO_MEMORY); + } + + + status = acpi_ut_walk_package_tree (source_obj, dest_obj, + acpi_ut_copy_ielement_to_ielement, walk_state); + + return (status); +} + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/utilities/utdebug.c linux/drivers/acpi/utilities/utdebug.c --- v2.4.5/linux/drivers/acpi/utilities/utdebug.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/utilities/utdebug.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,594 @@ +/****************************************************************************** + * + * Module Name: utdebug - Debug print routines + * $Revision: 72 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" + +#define _COMPONENT ACPI_UTILITIES + MODULE_NAME ("utdebug") + + +u32 prev_thread_id = 0xFFFFFFFF; + +/***************************************************************************** + * + * FUNCTION: Get/Set debug level + * + * DESCRIPTION: Get or set value of the debug flag + * + * These are used to allow user's to get/set the debug level + * + ****************************************************************************/ + + +u32 +get_debug_level (void) +{ + + return (acpi_dbg_level); +} + +void +set_debug_level ( + u32 new_debug_level) +{ + + acpi_dbg_level = new_debug_level; +} + + +/***************************************************************************** + * + * FUNCTION: Function_trace + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Function_name - Name of Caller's function + * + * RETURN: None + * + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * set in Debug_level + * + ****************************************************************************/ + +void +function_trace ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name) +{ + + acpi_gbl_nesting_level++; + + debug_print (module_name, line_number, component_id, + TRACE_FUNCTIONS, + " %2.2ld Entered Function: %s\n", + acpi_gbl_nesting_level, function_name); +} + + +/***************************************************************************** + * + * FUNCTION: Function_trace_ptr + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Function_name - Name of Caller's function + * Pointer - Pointer to display + * + * RETURN: None + * + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * set in Debug_level + * + ****************************************************************************/ + +void +function_trace_ptr ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name, + void *pointer) +{ + + acpi_gbl_nesting_level++; + debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS, + " %2.2ld Entered Function: %s, %p\n", + acpi_gbl_nesting_level, function_name, pointer); +} + + +/***************************************************************************** + * + * FUNCTION: Function_trace_str + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Function_name - Name of Caller's function + * String - Additional string to display + * + * RETURN: None + * + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * set in Debug_level + * + ****************************************************************************/ + +void +function_trace_str ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name, + NATIVE_CHAR *string) +{ + + acpi_gbl_nesting_level++; + debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS, + " %2.2ld Entered Function: %s, %s\n", + acpi_gbl_nesting_level, function_name, string); +} + + +/***************************************************************************** + * + * FUNCTION: Function_trace_u32 + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Function_name - Name of Caller's function + * Integer - Integer to display + * + * RETURN: None + * + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * set in Debug_level + * + ****************************************************************************/ + +void +function_trace_u32 ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name, + u32 integer) +{ + + acpi_gbl_nesting_level++; + debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS, + " %2.2ld Entered Function: %s, %lX\n", + acpi_gbl_nesting_level, function_name, integer); +} + + +/***************************************************************************** + * + * FUNCTION: Function_exit + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Function_name - Name of Caller's function + * + * RETURN: None + * + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * set in Debug_level + * + ****************************************************************************/ + +void +function_exit ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name) +{ + + debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS, + " %2.2ld Exiting Function: %s\n", + acpi_gbl_nesting_level, function_name); + + acpi_gbl_nesting_level--; +} + + +/***************************************************************************** + * + * FUNCTION: Function_status_exit + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Function_name - Name of Caller's function + * Status - Exit status code + * + * RETURN: None + * + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * set in Debug_level. Prints exit status also. + * + ****************************************************************************/ + +void +function_status_exit ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name, + ACPI_STATUS status) +{ + + debug_print (module_name, line_number, component_id, + TRACE_FUNCTIONS, + " %2.2ld Exiting Function: %s, %s\n", + acpi_gbl_nesting_level, + function_name, + acpi_ut_format_exception (status)); + + acpi_gbl_nesting_level--; +} + + +/***************************************************************************** + * + * FUNCTION: Function_value_exit + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Function_name - Name of Caller's function + * Value - Value to be printed with exit msg + * + * RETURN: None + * + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * set in Debug_level. Prints exit value also. + * + ****************************************************************************/ + +void +function_value_exit ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name, + ACPI_INTEGER value) +{ + + debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS, + " %2.2ld Exiting Function: %s, %X\n", + acpi_gbl_nesting_level, function_name, value); + + acpi_gbl_nesting_level--; +} + + +/***************************************************************************** + * + * FUNCTION: Function_ptr_exit + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Function_name - Name of Caller's function + * Value - Value to be printed with exit msg + * + * RETURN: None + * + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * set in Debug_level. Prints exit value also. + * + ****************************************************************************/ + +void +function_ptr_exit ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name, + u8 *ptr) +{ + + debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS, + " %2.2ld Exiting Function: %s, %p\n", + acpi_gbl_nesting_level, function_name, ptr); + + acpi_gbl_nesting_level--; +} + + +/***************************************************************************** + * + * FUNCTION: Debug_print + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Print_level - Requested debug print level + * Format - Printf format field + * ... - Optional printf arguments + * + * RETURN: None + * + * DESCRIPTION: Print error message with prefix consisting of the module name, + * line number, and component ID. + * + ****************************************************************************/ + +void +debug_print ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + u32 print_level, + NATIVE_CHAR *format, + ...) +{ + va_list args; + u32 thread_id; + + + thread_id = acpi_os_get_thread_id (); + + + /* Both the level and the component must be enabled */ + + if ((print_level & acpi_dbg_level) && + (component_id & acpi_dbg_layer)) { + va_start (args, format); + + if (thread_id != prev_thread_id) { + if (TRACE_THREADS & acpi_dbg_level) { + acpi_os_printf ("\n**** Context Switch from TID %X to TID %X ****\n\n", + prev_thread_id, thread_id); + } + + prev_thread_id = thread_id; + } + + if (TRACE_THREADS & acpi_dbg_level) { + acpi_os_printf ("%8s-%04d[%04X]: ", module_name, line_number, thread_id); + } + else { + acpi_os_printf ("%8s-%04d: ", module_name, line_number); + } + + acpi_os_vprintf (format, args); + } +} + + +/***************************************************************************** + * + * FUNCTION: Debug_print_prefix + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * + * RETURN: None + * + * DESCRIPTION: Print the prefix part of an error message, consisting of the + * module name, and line number + * + ****************************************************************************/ + +void +debug_print_prefix ( + NATIVE_CHAR *module_name, + u32 line_number) +{ + u32 thread_id; + + + thread_id = acpi_os_get_thread_id (); + + if (thread_id != prev_thread_id) { + if (TRACE_THREADS & acpi_dbg_level) { + acpi_os_printf ("\n**** Context Switch from TID %X to TID %X ****\n\n", + prev_thread_id, thread_id); + } + + prev_thread_id = thread_id; + } + + if (TRACE_THREADS & acpi_dbg_level) { + acpi_os_printf ("%8s-%04d[%04X]: ", module_name, line_number, thread_id); + } + else { + acpi_os_printf ("%8s-%04d: ", module_name, line_number); + } + +} + + +/***************************************************************************** + * + * FUNCTION: Debug_print_raw + * + * PARAMETERS: Format - Printf format field + * ... - Optional printf arguments + * + * RETURN: None + * + * DESCRIPTION: Print error message -- without module/line indentifiers + * + ****************************************************************************/ + +void +debug_print_raw ( + NATIVE_CHAR *format, + ...) +{ + va_list args; + + + va_start (args, format); + + acpi_os_vprintf (format, args); + + va_end (args); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ut_dump_buffer + * + * PARAMETERS: Buffer - Buffer to dump + * Count - Amount to dump, in bytes + * Component_iD - Caller's component ID + * + * RETURN: None + * + * DESCRIPTION: Generic dump buffer in both hex and ascii. + * + ****************************************************************************/ + +void +acpi_ut_dump_buffer ( + u8 *buffer, + u32 count, + u32 display, + u32 component_id) +{ + u32 i = 0; + u32 j; + u32 temp32; + u8 buf_char; + + + /* Only dump the buffer if tracing is enabled */ + + if (!((TRACE_TABLES & acpi_dbg_level) && + (component_id & acpi_dbg_layer))) { + return; + } + + + /* + * Nasty little dump buffer routine! + */ + while (i < count) { + /* Print current offset */ + + acpi_os_printf ("%05X ", i); + + + /* Print 16 hex chars */ + + for (j = 0; j < 16;) { + if (i + j >= count) { + acpi_os_printf ("\n"); + return; + } + + /* Make sure that the s8 doesn't get sign-extended! */ + + switch (display) { + /* Default is BYTE display */ + + default: + + acpi_os_printf ("%02X ", + *((u8 *) &buffer[i + j])); + j += 1; + break; + + + case DB_WORD_DISPLAY: + + MOVE_UNALIGNED16_TO_32 (&temp32, + &buffer[i + j]); + acpi_os_printf ("%04X ", temp32); + j += 2; + break; + + + case DB_DWORD_DISPLAY: + + MOVE_UNALIGNED32_TO_32 (&temp32, + &buffer[i + j]); + acpi_os_printf ("%08X ", temp32); + j += 4; + break; + + + case DB_QWORD_DISPLAY: + + MOVE_UNALIGNED32_TO_32 (&temp32, + &buffer[i + j]); + acpi_os_printf ("%08X", temp32); + + MOVE_UNALIGNED32_TO_32 (&temp32, + &buffer[i + j + 4]); + acpi_os_printf ("%08X ", temp32); + j += 8; + break; + } + } + + + /* + * 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"); + return; + } + + buf_char = buffer[i + j]; + if ((buf_char > 0x1F && buf_char < 0x2E) || + (buf_char > 0x2F && buf_char < 0x61) || + (buf_char > 0x60 && buf_char < 0x7F)) { + acpi_os_printf ("%c", buf_char); + } + else { + acpi_os_printf ("."); + } + } + + /* Done with that line. */ + + acpi_os_printf ("\n"); + i += 16; + } + + return; +} + + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/utilities/utdelete.c linux/drivers/acpi/utilities/utdelete.c --- v2.4.5/linux/drivers/acpi/utilities/utdelete.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/utilities/utdelete.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,602 @@ +/******************************************************************************* + * + * Module Name: utdelete - object deletion and reference count utilities + * $Revision: 71 $ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "actables.h" +#include "acparser.h" + +#define _COMPONENT ACPI_UTILITIES + MODULE_NAME ("utdelete") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_delete_internal_obj + * + * PARAMETERS: *Object - Pointer to the list to be deleted + * + * RETURN: None + * + * DESCRIPTION: Low level object deletion, after reference counts have been + * updated (All reference counts, including sub-objects!) + * + ******************************************************************************/ + +void +acpi_ut_delete_internal_obj ( + ACPI_OPERAND_OBJECT *object) +{ + void *obj_pointer = NULL; + ACPI_OPERAND_OBJECT *handler_desc; + + + if (!object) { + return; + } + + /* + * Must delete or free any pointers within the object that are not + * actual ACPI objects (for example, a raw buffer pointer). + */ + + switch (object->common.type) { + + case ACPI_TYPE_STRING: + + /* Free the actual string buffer */ + + obj_pointer = object->string.pointer; + break; + + + case ACPI_TYPE_BUFFER: + + /* Free the actual buffer */ + + obj_pointer = object->buffer.pointer; + break; + + + case ACPI_TYPE_PACKAGE: + + /* + * Elements of the package are not handled here, they are deleted + * separately + */ + + /* Free the (variable length) element pointer array */ + + obj_pointer = object->package.elements; + break; + + + case ACPI_TYPE_MUTEX: + + acpi_ex_unlink_mutex (object); + acpi_os_delete_semaphore (object->mutex.semaphore); + break; + + + case ACPI_TYPE_EVENT: + + acpi_os_delete_semaphore (object->event.semaphore); + object->event.semaphore = NULL; + break; + + + case ACPI_TYPE_METHOD: + + /* Delete the method semaphore if it exists */ + + if (object->method.semaphore) { + acpi_os_delete_semaphore (object->method.semaphore); + object->method.semaphore = NULL; + } + + break; + + + case ACPI_TYPE_REGION: + + if (object->region.extra) { + /* + * Free the Region_context if and only if the handler is one of the + * default handlers -- and therefore, we created the context object + * locally, it was not created by an external caller. + */ + handler_desc = object->region.addr_handler; + if ((handler_desc) && + (handler_desc->addr_handler.hflags == ADDR_HANDLER_DEFAULT_INSTALLED)) { + obj_pointer = object->region.extra->extra.region_context; + } + + /* Now we can free the Extra object */ + + acpi_ut_delete_object_desc (object->region.extra); + } + break; + + + case ACPI_TYPE_BUFFER_FIELD: + + if (object->buffer_field.extra) { + acpi_ut_delete_object_desc (object->buffer_field.extra); + } + break; + + default: + break; + } + + + /* + * Delete any allocated memory found above + */ + if (obj_pointer) { + if (!acpi_tb_system_table_pointer (obj_pointer)) { + acpi_ut_free (obj_pointer); + } + } + + + /* Only delete the object if it was dynamically allocated */ + + + if (!(object->common.flags & AOPOBJ_STATIC_ALLOCATION)) { + acpi_ut_delete_object_desc (object); + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_delete_internal_object_list + * + * PARAMETERS: *Obj_list - Pointer to the list to be deleted + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function deletes an internal object list, including both + * simple objects and package objects + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ut_delete_internal_object_list ( + ACPI_OPERAND_OBJECT **obj_list) +{ + ACPI_OPERAND_OBJECT **internal_obj; + + + /* Walk the null-terminated internal list */ + + for (internal_obj = obj_list; *internal_obj; internal_obj++) { + /* + * Check for a package + * Simple objects are simply stored in the array and do not + * need to be deleted separately. + */ + + if (IS_THIS_OBJECT_TYPE ((*internal_obj), ACPI_TYPE_PACKAGE)) { + /* Delete the package */ + + /* + * TBD: [Investigate] This might not be the right thing to do, + * depending on how the internal package object was allocated!!! + */ + acpi_ut_delete_internal_obj (*internal_obj); + } + + } + + /* Free the combined parameter pointer list and object array */ + + acpi_ut_free (obj_list); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_update_ref_count + * + * PARAMETERS: *Object - Object whose ref count is to be updated + * Action - What to do + * + * RETURN: New ref count + * + * DESCRIPTION: Modify the ref count and return it. + * + ******************************************************************************/ + +static void +acpi_ut_update_ref_count ( + ACPI_OPERAND_OBJECT *object, + u32 action) +{ + u16 count; + u16 new_count; + + + PROC_NAME ("Ut_update_ref_count"); + + if (!object) { + return; + } + + + count = object->common.reference_count; + new_count = count; + + /* + * Reference count action (increment, decrement, or force delete) + */ + + switch (action) { + + case REF_INCREMENT: + + new_count++; + object->common.reference_count = new_count; + + break; + + + case REF_DECREMENT: + + if (count < 1) { + new_count = 0; + } + + else { + new_count--; + + } + + + object->common.reference_count = new_count; + if (new_count == 0) { + acpi_ut_delete_internal_obj (object); + } + + break; + + + case REF_FORCE_DELETE: + + new_count = 0; + object->common.reference_count = new_count; + acpi_ut_delete_internal_obj (object); + break; + + + default: + + break; + } + + + /* + * Sanity check the reference count, for debug purposes only. + * (A deleted object will have a huge reference count) + */ + + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_update_object_reference + * + * PARAMETERS: *Object - Increment ref count for this object + * and all sub-objects + * Action - Either REF_INCREMENT or REF_DECREMENT or + * REF_FORCE_DELETE + * + * RETURN: Status + * + * DESCRIPTION: Increment the object reference count + * + * Object references are incremented when: + * 1) An object is attached to a Node (namespace object) + * 2) An object is copied (all subobjects must be incremented) + * + * Object references are decremented when: + * 1) An object is detached from an Node + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ut_update_object_reference ( + ACPI_OPERAND_OBJECT *object, + u16 action) +{ + ACPI_STATUS status; + u32 i; + ACPI_OPERAND_OBJECT *next; + ACPI_OPERAND_OBJECT *new; + ACPI_GENERIC_STATE *state_list = NULL; + ACPI_GENERIC_STATE *state; + + + /* Ignore a null object ptr */ + + if (!object) { + return (AE_OK); + } + + + /* + * Make sure that this isn't a namespace handle or an AML pointer + */ + + if (VALID_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_NAMED)) { + return (AE_OK); + } + + if (acpi_tb_system_table_pointer (object)) { + return (AE_OK); + } + + + state = acpi_ut_create_update_state (object, action); + + while (state) { + object = state->update.object; + action = state->update.value; + acpi_ut_delete_generic_state (state); + + /* + * All sub-objects must have their reference count incremented also. + * Different object types have different subobjects. + */ + switch (object->common.type) { + + case ACPI_TYPE_DEVICE: + + status = acpi_ut_create_update_state_and_push (object->device.addr_handler, + action, &state_list); + if (ACPI_FAILURE (status)) { + return (status); + } + + acpi_ut_update_ref_count (object->device.sys_handler, action); + acpi_ut_update_ref_count (object->device.drv_handler, action); + break; + + + case INTERNAL_TYPE_ADDRESS_HANDLER: + + /* Must walk list of address handlers */ + + next = object->addr_handler.next; + while (next) { + new = next->addr_handler.next; + acpi_ut_update_ref_count (next, action); + + next = new; + } + break; + + + case ACPI_TYPE_PACKAGE: + + /* + * We must update all the sub-objects of the package + * (Each of whom may have their own sub-objects, etc. + */ + for (i = 0; i < object->package.count; i++) { + /* + * Push each element onto the stack for later processing. + * Note: There can be null elements within the package, + * these are simply ignored + */ + + status = acpi_ut_create_update_state_and_push ( + object->package.elements[i], action, &state_list); + if (ACPI_FAILURE (status)) { + return (status); + } + } + break; + + + case ACPI_TYPE_BUFFER_FIELD: + + status = acpi_ut_create_update_state_and_push ( + object->buffer_field.buffer_obj, action, &state_list); + + if (ACPI_FAILURE (status)) { + return (status); + } + break; + + + case INTERNAL_TYPE_REGION_FIELD: + + status = acpi_ut_create_update_state_and_push ( + object->field.region_obj, action, &state_list); + if (ACPI_FAILURE (status)) { + return (status); + } + break; + + + case INTERNAL_TYPE_BANK_FIELD: + + status = acpi_ut_create_update_state_and_push ( + object->bank_field.bank_register_obj, action, &state_list); + if (ACPI_FAILURE (status)) { + return (status); + } + + status = acpi_ut_create_update_state_and_push ( + object->bank_field.region_obj, action, &state_list); + if (ACPI_FAILURE (status)) { + return (status); + } + break; + + + case INTERNAL_TYPE_INDEX_FIELD: + + status = acpi_ut_create_update_state_and_push ( + object->index_field.index_obj, action, &state_list); + if (ACPI_FAILURE (status)) { + return (status); + } + + status = acpi_ut_create_update_state_and_push ( + object->index_field.data_obj, action, &state_list); + if (ACPI_FAILURE (status)) { + return (status); + } + break; + + + case ACPI_TYPE_REGION: + + /* TBD: [Investigate] + Acpi_ut_update_ref_count (Object->Region.Addr_handler, Action); + */ +/* + Status = + Acpi_ut_create_update_state_and_push (Object->Region.Addr_handler, + Action, &State_list); + if (ACPI_FAILURE (Status)) + { + return (Status); + } +*/ + break; + + + case INTERNAL_TYPE_REFERENCE: + + break; + } + + + /* + * Now we can update the count in the main object. This can only + * happen after we update the sub-objects in case this causes the + * main object to be deleted. + */ + + acpi_ut_update_ref_count (object, action); + + + /* Move on to the next object to be updated */ + + state = acpi_ut_pop_generic_state (&state_list); + } + + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_add_reference + * + * PARAMETERS: *Object - Object whose reference count is to be + * incremented + * + * RETURN: None + * + * DESCRIPTION: Add one reference to an ACPI object + * + ******************************************************************************/ + +void +acpi_ut_add_reference ( + ACPI_OPERAND_OBJECT *object) +{ + + + /* + * Ensure that we have a valid object + */ + + if (!acpi_ut_valid_internal_object (object)) { + return; + } + + /* + * We have a valid ACPI internal object, now increment the reference count + */ + + acpi_ut_update_object_reference (object, REF_INCREMENT); + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_remove_reference + * + * PARAMETERS: *Object - Object whose ref count will be decremented + * + * RETURN: None + * + * DESCRIPTION: Decrement the reference count of an ACPI internal object + * + ******************************************************************************/ + +void +acpi_ut_remove_reference ( + ACPI_OPERAND_OBJECT *object) +{ + + + /* + * Ensure that we have a valid object + */ + + if (!acpi_ut_valid_internal_object (object)) { + return; + } + + /* + * Decrement the reference count, and only actually delete the object + * if the reference count becomes 0. (Must also decrement the ref count + * of all subobjects!) + */ + + acpi_ut_update_object_reference (object, REF_DECREMENT); + return; +} + + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/utilities/uteval.c linux/drivers/acpi/utilities/uteval.c --- v2.4.5/linux/drivers/acpi/utilities/uteval.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/utilities/uteval.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,308 @@ +/****************************************************************************** + * + * Module Name: uteval - Object evaluation + * $Revision: 27 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acnamesp.h" +#include "acinterp.h" + + +#define _COMPONENT ACPI_UTILITIES + MODULE_NAME ("uteval") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_evaluate_numeric_object + * + * PARAMETERS: *Object_name - Object name to be evaluated + * Device_node - Node for the device + * *Address - Where the value is returned + * + * RETURN: Status + * + * DESCRIPTION: evaluates a numeric namespace object for a selected device + * and stores results in *Address. + * + * NOTE: Internal function, no parameter validation + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ut_evaluate_numeric_object ( + NATIVE_CHAR *object_name, + ACPI_NAMESPACE_NODE *device_node, + ACPI_INTEGER *address) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_STATUS status; + + + /* Execute the method */ + + status = acpi_ns_evaluate_relative (device_node, object_name, NULL, &obj_desc); + if (ACPI_FAILURE (status)) { + + return (status); + } + + + /* Did we get a return object? */ + + if (!obj_desc) { + return (AE_TYPE); + } + + /* Is the return object of the correct type? */ + + if (obj_desc->common.type != ACPI_TYPE_INTEGER) { + status = AE_TYPE; + } + else { + /* + * Since the structure is a union, setting any field will set all + * of the variables in the union + */ + *address = obj_desc->integer.value; + } + + /* On exit, we must delete the return object */ + + acpi_ut_remove_reference (obj_desc); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_execute_HID + * + * PARAMETERS: Device_node - Node for the device + * *Hid - Where the HID is returned + * + * RETURN: Status + * + * DESCRIPTION: Executes the _HID control method that returns the hardware + * ID of the device. + * + * NOTE: Internal function, no parameter validation + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ut_execute_HID ( + ACPI_NAMESPACE_NODE *device_node, + ACPI_DEVICE_ID *hid) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_STATUS status; + + + /* Execute the method */ + + status = acpi_ns_evaluate_relative (device_node, + METHOD_NAME__HID, NULL, &obj_desc); + if (ACPI_FAILURE (status)) { + + + return (status); + } + + /* Did we get a return object? */ + + if (!obj_desc) { + return (AE_TYPE); + } + + /* + * A _HID can return either a Number (32 bit compressed EISA ID) or + * a string + */ + if ((obj_desc->common.type != ACPI_TYPE_INTEGER) && + (obj_desc->common.type != ACPI_TYPE_STRING)) { + status = AE_TYPE; + } + + else { + if (obj_desc->common.type == ACPI_TYPE_INTEGER) { + /* Convert the Numeric HID to string */ + + acpi_ex_eisa_id_to_string ((u32) obj_desc->integer.value, hid->buffer); + } + + else { + /* Copy the String HID from the returned object */ + + STRNCPY(hid->buffer, obj_desc->string.pointer, sizeof(hid->buffer)); + } + } + + + /* On exit, we must delete the return object */ + + acpi_ut_remove_reference (obj_desc); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_execute_UID + * + * PARAMETERS: Device_node - Node for the device + * *Uid - Where the UID is returned + * + * RETURN: Status + * + * DESCRIPTION: Executes the _UID control method that returns the hardware + * ID of the device. + * + * NOTE: Internal function, no parameter validation + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ut_execute_UID ( + ACPI_NAMESPACE_NODE *device_node, + ACPI_DEVICE_ID *uid) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_STATUS status; + + + PROC_NAME ("Ut_execute_UID"); + + + /* Execute the method */ + + status = acpi_ns_evaluate_relative (device_node, + METHOD_NAME__UID, NULL, &obj_desc); + if (ACPI_FAILURE (status)) { + + + return (status); + } + + /* Did we get a return object? */ + + if (!obj_desc) { + return (AE_TYPE); + } + + /* + * A _UID can return either a Number (32 bit compressed EISA ID) or + * a string + */ + if ((obj_desc->common.type != ACPI_TYPE_INTEGER) && + (obj_desc->common.type != ACPI_TYPE_STRING)) { + status = AE_TYPE; + } + + else { + if (obj_desc->common.type == ACPI_TYPE_INTEGER) { + /* Convert the Numeric UID to string */ + + acpi_ex_unsigned_integer_to_string (obj_desc->integer.value, uid->buffer); + } + + else { + /* Copy the String UID from the returned object */ + + STRNCPY(uid->buffer, obj_desc->string.pointer, sizeof(uid->buffer)); + } + } + + + /* On exit, we must delete the return object */ + + acpi_ut_remove_reference (obj_desc); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_execute_STA + * + * PARAMETERS: Device_node - Node for the device + * *Flags - Where the status flags are returned + * + * RETURN: Status + * + * DESCRIPTION: Executes _STA for selected device and stores results in + * *Flags. + * + * NOTE: Internal function, no parameter validation + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ut_execute_STA ( + ACPI_NAMESPACE_NODE *device_node, + u32 *flags) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_STATUS status; + + + /* Execute the method */ + + status = acpi_ns_evaluate_relative (device_node, + METHOD_NAME__STA, NULL, &obj_desc); + if (AE_NOT_FOUND == status) { + *flags = 0x0F; + status = AE_OK; + } + + + else /* success */ { + /* Did we get a return object? */ + + if (!obj_desc) { + return (AE_TYPE); + } + + /* Is the return object of the correct type? */ + + if (obj_desc->common.type != ACPI_TYPE_INTEGER) { + status = AE_TYPE; + } + + else { + /* Extract the status flags */ + + *flags = (u32) obj_desc->integer.value; + } + + /* On exit, we must delete the return object */ + + acpi_ut_remove_reference (obj_desc); + } + + return (status); +} diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/utilities/utglobal.c linux/drivers/acpi/utilities/utglobal.c --- v2.4.5/linux/drivers/acpi/utilities/utglobal.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/utilities/utglobal.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,483 @@ +/****************************************************************************** + * + * Module Name: utglobal - Global variables for the ACPI subsystem + * $Revision: 123 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 DEFINE_ACPI_GLOBALS + +#include "acpi.h" +#include "acevents.h" +#include "acnamesp.h" +#include "acinterp.h" +#include "amlcode.h" + + +#define _COMPONENT ACPI_UTILITIES + MODULE_NAME ("utglobal") + + +/****************************************************************************** + * + * Static global variable initialization. + * + ******************************************************************************/ + +/* + * We want the debug switches statically initialized so they + * are already set when the debugger is entered. + */ + +/* Debug switch - level and trace mask */ + +u32 acpi_dbg_level = NORMAL_DEFAULT; + +/* Debug switch - layer (component) mask */ + +u32 acpi_dbg_layer = ACPI_COMPONENT_DEFAULT; +u32 acpi_gbl_nesting_level = 0; + + +/* Debugger globals */ + +u8 acpi_gbl_db_terminate_threads = FALSE; +u8 acpi_gbl_method_executing = FALSE; + +/* System flags */ + +u32 acpi_gbl_system_flags = 0; +u32 acpi_gbl_startup_flags = 0; + +/* System starts unitialized! */ +u8 acpi_gbl_shutdown = TRUE; + + +u8 acpi_gbl_decode_to8bit [8] = {1,2,4,8,16,32,64,128}; + + +/****************************************************************************** + * + * Namespace globals + * + ******************************************************************************/ + + +/* + * Names built-in to the interpreter + * + * Initial values are currently supported only for types String and Number. + * To avoid type punning, both are specified as strings in this table. + * + * NOTES: + * 1) _SB_ is defined to be a device to allow _SB_/_INI to be run + * during the initialization sequence. + */ + +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}, + {"_REV", ACPI_TYPE_INTEGER, "2"}, + {"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME}, + {"_GL_", ACPI_TYPE_MUTEX, "0"}, + {NULL, ACPI_TYPE_ANY} /* Table terminator */ +}; + + +/* + * Properties of the ACPI Object Types, both internal and external. + * + * Elements of Acpi_ns_properties are bit significant + * and the table is indexed by values of ACPI_OBJECT_TYPE + */ + +u8 acpi_gbl_ns_properties[] = +{ + NSP_NORMAL, /* 00 Any */ + NSP_NORMAL, /* 01 Number */ + NSP_NORMAL, /* 02 String */ + NSP_NORMAL, /* 03 Buffer */ + NSP_LOCAL, /* 04 Package */ + NSP_NORMAL, /* 05 Field_unit */ + NSP_NEWSCOPE | NSP_LOCAL, /* 06 Device */ + NSP_LOCAL, /* 07 Acpi_event */ + NSP_NEWSCOPE | NSP_LOCAL, /* 08 Method */ + NSP_LOCAL, /* 09 Mutex */ + NSP_LOCAL, /* 10 Region */ + NSP_NEWSCOPE | NSP_LOCAL, /* 11 Power */ + NSP_NEWSCOPE | NSP_LOCAL, /* 12 Processor */ + NSP_NEWSCOPE | NSP_LOCAL, /* 13 Thermal */ + NSP_NORMAL, /* 14 Buffer_field */ + NSP_NORMAL, /* 15 Ddb_handle */ + NSP_NORMAL, /* 16 Debug Object */ + NSP_NORMAL, /* 17 Def_field */ + NSP_NORMAL, /* 18 Bank_field */ + NSP_NORMAL, /* 19 Index_field */ + NSP_NORMAL, /* 20 Reference */ + NSP_NORMAL, /* 21 Alias */ + NSP_NORMAL, /* 22 Notify */ + NSP_NORMAL, /* 23 Address Handler */ + NSP_NEWSCOPE | NSP_LOCAL, /* 24 Resource Desc */ + NSP_NEWSCOPE | NSP_LOCAL, /* 25 Resource Field */ + NSP_NORMAL, /* 26 Def_field_defn */ + NSP_NORMAL, /* 27 Bank_field_defn */ + NSP_NORMAL, /* 28 Index_field_defn */ + NSP_NORMAL, /* 29 If */ + NSP_NORMAL, /* 30 Else */ + NSP_NORMAL, /* 31 While */ + NSP_NEWSCOPE, /* 32 Scope */ + NSP_LOCAL, /* 33 Def_any */ + NSP_NORMAL, /* 34 Extra */ + NSP_NORMAL /* 35 Invalid */ +}; + + +/* Hex to ASCII conversion table */ + +NATIVE_CHAR acpi_gbl_hex_to_ascii[] = + {'0','1','2','3','4','5','6','7', + '8','9','A','B','C','D','E','F'}; + + +/****************************************************************************** + * + * Table globals + * + * NOTE: This table includes ONLY the ACPI tables that the subsystem consumes. + * it is NOT an exhaustive list of all possible ACPI tables. All ACPI tables + * that are not used by the subsystem are simply ignored. + * + ******************************************************************************/ + + +ACPI_TABLE_DESC acpi_gbl_acpi_tables[NUM_ACPI_TABLES]; + + +ACPI_TABLE_SUPPORT acpi_gbl_acpi_table_data[NUM_ACPI_TABLES] = +{ + /*********** Name, Signature, Signature size, How many allowed?, Supported? Global typed pointer */ + + /* RSDP 0 */ {RSDP_NAME, RSDP_SIG, sizeof (RSDP_SIG)-1, ACPI_TABLE_SINGLE, AE_OK, NULL}, + /* DSDT 1 */ {DSDT_SIG, DSDT_SIG, sizeof (DSDT_SIG)-1, ACPI_TABLE_SINGLE, AE_OK, (void **) &acpi_gbl_DSDT}, + /* FADT 2 */ {FADT_SIG, FADT_SIG, sizeof (FADT_SIG)-1, ACPI_TABLE_SINGLE, AE_OK, (void **) &acpi_gbl_FADT}, + /* FACS 3 */ {FACS_SIG, FACS_SIG, sizeof (FACS_SIG)-1, ACPI_TABLE_SINGLE, AE_OK, (void **) &acpi_gbl_FACS}, + /* PSDT 4 */ {PSDT_SIG, PSDT_SIG, sizeof (PSDT_SIG)-1, ACPI_TABLE_MULTIPLE, AE_OK, NULL}, + /* SSDT 5 */ {SSDT_SIG, SSDT_SIG, sizeof (SSDT_SIG)-1, ACPI_TABLE_MULTIPLE, AE_OK, NULL}, + /* XSDT 6 */ {XSDT_SIG, XSDT_SIG, sizeof (RSDT_SIG)-1, ACPI_TABLE_SINGLE, AE_OK, NULL}, +}; + + +/***************************************************************************** + * + * FUNCTION: Acpi_ut_valid_object_type + * + * PARAMETERS: None. + * + * RETURN: TRUE if valid object type + * + * DESCRIPTION: Validate an object type + * + ****************************************************************************/ + +u8 +acpi_ut_valid_object_type ( + u32 type) +{ + + if (type > ACPI_TYPE_MAX) + { + if ((type < INTERNAL_TYPE_BEGIN) || + (type > INTERNAL_TYPE_MAX)) + { + return (FALSE); + } + } + + return (TRUE); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ut_format_exception + * + * PARAMETERS: Status - Acpi status to be formatted + * + * RETURN: Formatted status string + * + * DESCRIPTION: Convert an ACPI exception to a string + * + ****************************************************************************/ + +NATIVE_CHAR * +acpi_ut_format_exception ( + ACPI_STATUS status) +{ + NATIVE_CHAR *exception = "UNKNOWN_STATUS"; + ACPI_STATUS sub_status; + + + sub_status = (status & ~AE_CODE_MASK); + + + switch (status & AE_CODE_MASK) + { + case AE_CODE_ENVIRONMENTAL: + + if (sub_status <= AE_CODE_ENV_MAX) + { + exception = acpi_gbl_exception_names_env [sub_status]; + } + break; + + case AE_CODE_PROGRAMMER: + + if (sub_status <= AE_CODE_PGM_MAX) + { + exception = acpi_gbl_exception_names_pgm [sub_status -1]; + } + break; + + case AE_CODE_ACPI_TABLES: + + if (sub_status <= AE_CODE_TBL_MAX) + { + exception = acpi_gbl_exception_names_tbl [sub_status -1]; + } + break; + + case AE_CODE_AML: + + if (sub_status <= AE_CODE_AML_MAX) + { + exception = acpi_gbl_exception_names_aml [sub_status -1]; + } + break; + + case AE_CODE_CONTROL: + + if (sub_status <= AE_CODE_CTRL_MAX) + { + exception = acpi_gbl_exception_names_ctrl [sub_status -1]; + } + break; + + default: + break; + } + + + return (exception); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ut_allocate_owner_id + * + * PARAMETERS: Id_type - Type of ID (method or table) + * + * DESCRIPTION: Allocate a table or method owner id + * + ***************************************************************************/ + +ACPI_OWNER_ID +acpi_ut_allocate_owner_id ( + u32 id_type) +{ + ACPI_OWNER_ID owner_id = 0xFFFF; + + + acpi_ut_acquire_mutex (ACPI_MTX_CACHES); + + switch (id_type) + { + case OWNER_TYPE_TABLE: + + owner_id = acpi_gbl_next_table_owner_id; + acpi_gbl_next_table_owner_id++; + + if (acpi_gbl_next_table_owner_id == FIRST_METHOD_ID) + { + acpi_gbl_next_table_owner_id = FIRST_TABLE_ID; + } + break; + + + case OWNER_TYPE_METHOD: + + owner_id = acpi_gbl_next_method_owner_id; + acpi_gbl_next_method_owner_id++; + + if (acpi_gbl_next_method_owner_id == FIRST_TABLE_ID) + { + acpi_gbl_next_method_owner_id = FIRST_METHOD_ID; + } + break; + } + + + acpi_ut_release_mutex (ACPI_MTX_CACHES); + + return (owner_id); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ut_init_globals + * + * PARAMETERS: none + * + * DESCRIPTION: Init library globals. All globals that require specific + * initialization should be initialized here! + * + ***************************************************************************/ + +void +acpi_ut_init_globals ( + void) +{ + u32 i; + + + /* ACPI table structure */ + + for (i = 0; i < NUM_ACPI_TABLES; i++) + { + acpi_gbl_acpi_tables[i].prev = &acpi_gbl_acpi_tables[i]; + acpi_gbl_acpi_tables[i].next = &acpi_gbl_acpi_tables[i]; + acpi_gbl_acpi_tables[i].pointer = NULL; + acpi_gbl_acpi_tables[i].length = 0; + acpi_gbl_acpi_tables[i].allocation = ACPI_MEM_NOT_ALLOCATED; + acpi_gbl_acpi_tables[i].count = 0; + } + + + /* Address Space handler array */ + + for (i = 0; i < ACPI_NUM_ADDRESS_SPACES; i++) + { + acpi_gbl_address_spaces[i].handler = NULL; + acpi_gbl_address_spaces[i].context = NULL; + } + + /* Mutex locked flags */ + + for (i = 0; i < NUM_MTX; i++) + { + acpi_gbl_acpi_mutex_info[i].mutex = NULL; + acpi_gbl_acpi_mutex_info[i].owner_id = ACPI_MUTEX_NOT_ACQUIRED; + acpi_gbl_acpi_mutex_info[i].use_count = 0; + } + + /* Global notify handlers */ + + acpi_gbl_sys_notify.handler = NULL; + acpi_gbl_drv_notify.handler = NULL; + + /* Global "typed" ACPI table pointers */ + + acpi_gbl_RSDP = NULL; + acpi_gbl_XSDT = NULL; + acpi_gbl_FACS = NULL; + acpi_gbl_FADT = NULL; + acpi_gbl_DSDT = NULL; + + + /* Global Lock support */ + + acpi_gbl_global_lock_acquired = FALSE; + acpi_gbl_global_lock_thread_count = 0; + + /* Miscellaneous variables */ + + acpi_gbl_system_flags = 0; + acpi_gbl_startup_flags = 0; + acpi_gbl_rsdp_original_location = 0; + acpi_gbl_cm_single_step = FALSE; + acpi_gbl_db_terminate_threads = FALSE; + acpi_gbl_shutdown = FALSE; + acpi_gbl_ns_lookup_count = 0; + acpi_gbl_ps_find_count = 0; + acpi_gbl_acpi_hardware_present = TRUE; + acpi_gbl_next_table_owner_id = FIRST_TABLE_ID; + acpi_gbl_next_method_owner_id = FIRST_METHOD_ID; + acpi_gbl_debugger_configuration = DEBUGGER_THREADING; + + /* Cache of small "state" objects */ + + acpi_gbl_generic_state_cache = NULL; + acpi_gbl_generic_state_cache_depth = 0; + acpi_gbl_state_cache_requests = 0; + acpi_gbl_state_cache_hits = 0; + + acpi_gbl_parse_cache = NULL; + acpi_gbl_parse_cache_depth = 0; + acpi_gbl_parse_cache_requests = 0; + acpi_gbl_parse_cache_hits = 0; + + acpi_gbl_ext_parse_cache = NULL; + acpi_gbl_ext_parse_cache_depth = 0; + acpi_gbl_ext_parse_cache_requests = 0; + acpi_gbl_ext_parse_cache_hits = 0; + + acpi_gbl_object_cache = NULL; + acpi_gbl_object_cache_depth = 0; + acpi_gbl_object_cache_requests = 0; + acpi_gbl_object_cache_hits = 0; + + acpi_gbl_walk_state_cache = NULL; + acpi_gbl_walk_state_cache_depth = 0; + acpi_gbl_walk_state_cache_requests = 0; + acpi_gbl_walk_state_cache_hits = 0; + + /* Hardware oriented */ + + acpi_gbl_gpe0enable_register_save = NULL; + acpi_gbl_gpe1_enable_register_save = NULL; + acpi_gbl_original_mode = SYS_MODE_UNKNOWN; /* original ACPI/legacy mode */ + acpi_gbl_gpe_registers = NULL; + acpi_gbl_gpe_info = NULL; + + /* Namespace */ + + acpi_gbl_root_node = NULL; + + acpi_gbl_root_node_struct.name = ACPI_ROOT_NAME; + acpi_gbl_root_node_struct.data_type = ACPI_DESC_TYPE_NAMED; + acpi_gbl_root_node_struct.type = ACPI_TYPE_ANY; + acpi_gbl_root_node_struct.child = NULL; + acpi_gbl_root_node_struct.peer = NULL; + acpi_gbl_root_node_struct.object = NULL; + acpi_gbl_root_node_struct.flags = ANOBJ_END_OF_PEER_LIST; + + /* Memory allocation metrics - compiled out in non-debug mode. */ + + INITIALIZE_ALLOCATION_METRICS(); + + return; +} + + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/utilities/utinit.c linux/drivers/acpi/utilities/utinit.c --- v2.4.5/linux/drivers/acpi/utilities/utinit.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/utilities/utinit.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,247 @@ +/****************************************************************************** + * + * Module Name: utinit - Common ACPI subsystem initialization + * $Revision: 96 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "achware.h" +#include "acnamesp.h" +#include "acevents.h" +#include "acparser.h" +#include "acdispat.h" + +#define _COMPONENT ACPI_UTILITIES + MODULE_NAME ("utinit") + + +#define ACPI_OFFSET(d,o) ((u32) &(((d *)0)->o)) +#define ACPI_FADT_OFFSET(o) ACPI_OFFSET (FADT_DESCRIPTOR, o) + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_fadt_register_error + * + * PARAMETERS: *Register_name - Pointer to string identifying register + * Value - Actual register contents value + * Acpi_test_spec_section - TDS section containing assertion + * Acpi_assertion - Assertion number being tested + * + * RETURN: AE_BAD_VALUE + * + * DESCRIPTION: Display failure message and link failure to TDS assertion + * + ******************************************************************************/ + +static ACPI_STATUS +acpi_ut_fadt_register_error ( + NATIVE_CHAR *register_name, + u32 value, + u32 offset) +{ + + REPORT_ERROR ( + ("Invalid FADT value %s=%lX at offset %lX FADT=%p\n", + register_name, value, offset, acpi_gbl_FADT)); + + + return (AE_BAD_VALUE); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ut_validate_fadt + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Validate various ACPI registers in the FADT + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ut_validate_fadt ( + void) +{ + ACPI_STATUS status = AE_OK; + + + /* + * Verify Fixed ACPI Description Table fields, + * but don't abort on any problems, just display error + */ + + if (acpi_gbl_FADT->pm1_evt_len < 4) { + status = acpi_ut_fadt_register_error ("PM1_EVT_LEN", + (u32) acpi_gbl_FADT->pm1_evt_len, + ACPI_FADT_OFFSET (pm1_evt_len)); + } + + if (!acpi_gbl_FADT->pm1_cnt_len) { + status = acpi_ut_fadt_register_error ("PM1_CNT_LEN", 0, + ACPI_FADT_OFFSET (pm1_cnt_len)); + } + + if (!ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm1a_evt_blk.address)) { + status = acpi_ut_fadt_register_error ("X_PM1a_EVT_BLK", 0, + ACPI_FADT_OFFSET (Xpm1a_evt_blk.address)); + } + + if (!ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm1a_cnt_blk.address)) { + status = acpi_ut_fadt_register_error ("X_PM1a_CNT_BLK", 0, + ACPI_FADT_OFFSET (Xpm1a_cnt_blk.address)); + } + + if (!ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm_tmr_blk.address)) { + status = acpi_ut_fadt_register_error ("X_PM_TMR_BLK", 0, + ACPI_FADT_OFFSET (Xpm_tmr_blk.address)); + } + + if ((ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm2_cnt_blk.address) && + !acpi_gbl_FADT->pm2_cnt_len)) { + status = acpi_ut_fadt_register_error ("PM2_CNT_LEN", + (u32) acpi_gbl_FADT->pm2_cnt_len, + ACPI_FADT_OFFSET (pm2_cnt_len)); + } + + if (acpi_gbl_FADT->pm_tm_len < 4) { + status = acpi_ut_fadt_register_error ("PM_TM_LEN", + (u32) acpi_gbl_FADT->pm_tm_len, + ACPI_FADT_OFFSET (pm_tm_len)); + } + + /* length of GPE blocks must be a multiple of 2 */ + + + if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) && + (acpi_gbl_FADT->gpe0blk_len & 1)) { + status = acpi_ut_fadt_register_error ("(x)GPE0_BLK_LEN", + (u32) acpi_gbl_FADT->gpe0blk_len, + ACPI_FADT_OFFSET (gpe0blk_len)); + } + + if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) && + (acpi_gbl_FADT->gpe1_blk_len & 1)) { + status = acpi_ut_fadt_register_error ("(x)GPE1_BLK_LEN", + (u32) acpi_gbl_FADT->gpe1_blk_len, + ACPI_FADT_OFFSET (gpe1_blk_len)); + } + + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ut_terminate + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: free memory allocated for table storage. + * + ******************************************************************************/ + +void +acpi_ut_terminate (void) +{ + + + /* Free global tables, etc. */ + + if (acpi_gbl_gpe0enable_register_save) { + acpi_ut_free (acpi_gbl_gpe0enable_register_save); + } + + if (acpi_gbl_gpe1_enable_register_save) { + acpi_ut_free (acpi_gbl_gpe1_enable_register_save); + } + + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_subsystem_shutdown + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: Shutdown the various subsystems. Don't delete the mutex + * objects here -- because the AML debugger may be still running. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ut_subsystem_shutdown (void) +{ + + /* Just exit if subsystem is already shutdown */ + + if (acpi_gbl_shutdown) { + return (AE_OK); + } + + /* Subsystem appears active, go ahead and shut it down */ + + acpi_gbl_shutdown = TRUE; + + /* Close the Namespace */ + + acpi_ns_terminate (); + + /* Close the Acpi_event Handling */ + + acpi_ev_terminate (); + + /* Close the globals */ + + acpi_ut_terminate (); + + /* Flush the local cache(s) */ + + acpi_ut_delete_generic_state_cache (); + acpi_ut_delete_object_cache (); + acpi_ds_delete_walk_state_cache (); + + /* Close the Parser */ + + /* TBD: [Restructure] Acpi_ps_terminate () */ + + acpi_ps_delete_parse_cache (); + + /* Debug only - display leftover memory allocation, if any */ +#ifdef ENABLE_DEBUGGER + acpi_ut_dump_current_allocations (ACPI_UINT32_MAX, NULL); +#endif + + return (AE_OK); +} + + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/utilities/utmisc.c linux/drivers/acpi/utilities/utmisc.c --- v2.4.5/linux/drivers/acpi/utilities/utmisc.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/utilities/utmisc.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,1043 @@ +/******************************************************************************* + * + * Module Name: utmisc - common utility procedures + * $Revision: 42 $ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acevents.h" +#include "achware.h" +#include "acnamesp.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acdebug.h" + + +#define _COMPONENT ACPI_UTILITIES + MODULE_NAME ("utmisc") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_valid_acpi_name + * + * PARAMETERS: Character - The character to be examined + * + * RETURN: 1 if Character may appear in a name, else 0 + * + * DESCRIPTION: Check for a valid ACPI name. Each character must be one of: + * 1) Upper case alpha + * 2) numeric + * 3) underscore + * + ******************************************************************************/ + +u8 +acpi_ut_valid_acpi_name ( + u32 name) +{ + NATIVE_CHAR *name_ptr = (NATIVE_CHAR *) &name; + u32 i; + + + for (i = 0; i < ACPI_NAME_SIZE; i++) { + if (!((name_ptr[i] == '_') || + (name_ptr[i] >= 'A' && name_ptr[i] <= 'Z') || + (name_ptr[i] >= '0' && name_ptr[i] <= '9'))) { + return (FALSE); + } + } + + + return (TRUE); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_valid_acpi_character + * + * PARAMETERS: Character - The character to be examined + * + * RETURN: 1 if Character may appear in a name, else 0 + * + * DESCRIPTION: Check for a printable character + * + ******************************************************************************/ + +u8 +acpi_ut_valid_acpi_character ( + NATIVE_CHAR character) +{ + + return ((u8) ((character == '_') || + (character >= 'A' && character <= 'Z') || + (character >= '0' && character <= '9'))); +} + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_strupr + * + * PARAMETERS: Src_string - The source string to convert to + * + * RETURN: Src_string + * + * DESCRIPTION: Convert string to uppercase + * + ******************************************************************************/ + +NATIVE_CHAR * +acpi_ut_strupr ( + NATIVE_CHAR *src_string) +{ + NATIVE_CHAR *string; + + + /* Walk entire string, uppercasing the letters */ + + for (string = src_string; *string; ) { + *string = (char) TOUPPER (*string); + string++; + } + + + return (src_string); +} + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_mutex_initialize + * + * PARAMETERS: None. + * + * RETURN: Status + * + * DESCRIPTION: Create the system mutex objects. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ut_mutex_initialize ( + void) +{ + u32 i; + ACPI_STATUS status; + + + /* + * Create each of the predefined mutex objects + */ + for (i = 0; i < NUM_MTX; i++) { + status = acpi_ut_create_mutex (i); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_mutex_terminate + * + * PARAMETERS: None. + * + * RETURN: None. + * + * DESCRIPTION: Delete all of the system mutex objects. + * + ******************************************************************************/ + +void +acpi_ut_mutex_terminate ( + void) +{ + u32 i; + + + /* + * Delete each predefined mutex object + */ + for (i = 0; i < NUM_MTX; i++) { + acpi_ut_delete_mutex (i); + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_create_mutex + * + * PARAMETERS: Mutex_iD - ID of the mutex to be created + * + * RETURN: Status + * + * DESCRIPTION: Create a mutex object. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ut_create_mutex ( + ACPI_MUTEX_HANDLE mutex_id) +{ + ACPI_STATUS status = AE_OK; + + + if (mutex_id > MAX_MTX) { + return (AE_BAD_PARAMETER); + } + + + if (!acpi_gbl_acpi_mutex_info[mutex_id].mutex) { + status = acpi_os_create_semaphore (1, 1, + &acpi_gbl_acpi_mutex_info[mutex_id].mutex); + acpi_gbl_acpi_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED; + acpi_gbl_acpi_mutex_info[mutex_id].use_count = 0; + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_delete_mutex + * + * PARAMETERS: Mutex_iD - ID of the mutex to be deleted + * + * RETURN: Status + * + * DESCRIPTION: Delete a mutex object. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ut_delete_mutex ( + ACPI_MUTEX_HANDLE mutex_id) +{ + ACPI_STATUS status; + + + if (mutex_id > MAX_MTX) { + return (AE_BAD_PARAMETER); + } + + + status = acpi_os_delete_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex); + + acpi_gbl_acpi_mutex_info[mutex_id].mutex = NULL; + acpi_gbl_acpi_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED; + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_acquire_mutex + * + * PARAMETERS: Mutex_iD - ID of the mutex to be acquired + * + * RETURN: Status + * + * DESCRIPTION: Acquire a mutex object. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ut_acquire_mutex ( + ACPI_MUTEX_HANDLE mutex_id) +{ + ACPI_STATUS status; + u32 i; + u32 this_thread_id; + + + PROC_NAME ("Ut_acquire_mutex"); + + + if (mutex_id > MAX_MTX) { + return (AE_BAD_PARAMETER); + } + + + this_thread_id = acpi_os_get_thread_id (); + + /* + * Deadlock prevention. Check if this thread owns any mutexes of value + * greater than or equal to this one. If so, the thread has violated + * the mutex ordering rule. This indicates a coding error somewhere in + * the ACPI subsystem code. + */ + for (i = mutex_id; i < MAX_MTX; i++) { + if (acpi_gbl_acpi_mutex_info[i].owner_id == this_thread_id) { + if (i == mutex_id) { + return (AE_ALREADY_ACQUIRED); + } + + return (AE_ACQUIRE_DEADLOCK); + } + } + + + status = acpi_os_wait_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex, + 1, WAIT_FOREVER); + + if (ACPI_SUCCESS (status)) { + acpi_gbl_acpi_mutex_info[mutex_id].use_count++; + acpi_gbl_acpi_mutex_info[mutex_id].owner_id = this_thread_id; + } + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_release_mutex + * + * PARAMETERS: Mutex_iD - ID of the mutex to be released + * + * RETURN: Status + * + * DESCRIPTION: Release a mutex object. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ut_release_mutex ( + ACPI_MUTEX_HANDLE mutex_id) +{ + ACPI_STATUS status; + u32 i; + u32 this_thread_id; + + + PROC_NAME ("Ut_release_mutex"); + + + this_thread_id = acpi_os_get_thread_id (); + if (mutex_id > MAX_MTX) { + return (AE_BAD_PARAMETER); + } + + + /* + * Mutex must be acquired in order to release it! + */ + if (acpi_gbl_acpi_mutex_info[mutex_id].owner_id == ACPI_MUTEX_NOT_ACQUIRED) { + return (AE_NOT_ACQUIRED); + } + + + /* + * Deadlock prevention. Check if this thread owns any mutexes of value + * greater than this one. If so, the thread has violated the mutex + * ordering rule. This indicates a coding error somewhere in + * the ACPI subsystem code. + */ + for (i = mutex_id; i < MAX_MTX; i++) { + if (acpi_gbl_acpi_mutex_info[i].owner_id == this_thread_id) { + if (i == mutex_id) { + continue; + } + + return (AE_RELEASE_DEADLOCK); + } + } + + + /* Mark unlocked FIRST */ + + acpi_gbl_acpi_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED; + + status = acpi_os_signal_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex, 1); + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_create_update_state_and_push + * + * PARAMETERS: *Object - Object to be added to the new state + * Action - Increment/Decrement + * State_list - List the state will be added to + * + * RETURN: None + * + * DESCRIPTION: Create a new state and push it + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ut_create_update_state_and_push ( + ACPI_OPERAND_OBJECT *object, + u16 action, + ACPI_GENERIC_STATE **state_list) +{ + ACPI_GENERIC_STATE *state; + + + /* Ignore null objects; these are expected */ + + if (!object) { + return (AE_OK); + } + + state = acpi_ut_create_update_state (object, action); + if (!state) { + return (AE_NO_MEMORY); + } + + + acpi_ut_push_generic_state (state_list, state); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_create_pkg_state_and_push + * + * PARAMETERS: *Object - Object to be added to the new state + * Action - Increment/Decrement + * State_list - List the state will be added to + * + * RETURN: None + * + * DESCRIPTION: Create a new state and push it + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ut_create_pkg_state_and_push ( + void *internal_object, + void *external_object, + u16 index, + ACPI_GENERIC_STATE **state_list) +{ + ACPI_GENERIC_STATE *state; + + + state = acpi_ut_create_pkg_state (internal_object, external_object, index); + if (!state) { + return (AE_NO_MEMORY); + } + + + acpi_ut_push_generic_state (state_list, state); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_push_generic_state + * + * PARAMETERS: List_head - Head of the state stack + * State - State object to push + * + * RETURN: Status + * + * DESCRIPTION: Push a state object onto a state stack + * + ******************************************************************************/ + +void +acpi_ut_push_generic_state ( + ACPI_GENERIC_STATE **list_head, + ACPI_GENERIC_STATE *state) +{ + /* Push the state object onto the front of the list (stack) */ + + state->common.next = *list_head; + *list_head = state; + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_pop_generic_state + * + * PARAMETERS: List_head - Head of the state stack + * + * RETURN: Status + * + * DESCRIPTION: Pop a state object from a state stack + * + ******************************************************************************/ + +ACPI_GENERIC_STATE * +acpi_ut_pop_generic_state ( + ACPI_GENERIC_STATE **list_head) +{ + ACPI_GENERIC_STATE *state; + + + /* Remove the state object at the head of the list (stack) */ + + state = *list_head; + if (state) { + /* Update the list head */ + + *list_head = state->common.next; + } + + return (state); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_create_generic_state + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Create a generic state object. Attempt to obtain one from + * the global state cache; If none available, create a new one. + * + ******************************************************************************/ + +ACPI_GENERIC_STATE * +acpi_ut_create_generic_state (void) +{ + ACPI_GENERIC_STATE *state; + + + acpi_ut_acquire_mutex (ACPI_MTX_CACHES); + + acpi_gbl_state_cache_requests++; + + /* Check the cache first */ + + if (acpi_gbl_generic_state_cache) { + /* There is an object available, use it */ + + state = acpi_gbl_generic_state_cache; + acpi_gbl_generic_state_cache = state->common.next; + state->common.next = NULL; + + acpi_gbl_state_cache_hits++; + acpi_gbl_generic_state_cache_depth--; + + acpi_ut_release_mutex (ACPI_MTX_CACHES); + + } + + else { + /* The cache is empty, create a new object */ + + acpi_ut_release_mutex (ACPI_MTX_CACHES); + + state = acpi_ut_callocate (sizeof (ACPI_GENERIC_STATE)); + } + + /* Initialize */ + + if (state) { + /* Always zero out the object before init */ + + MEMSET (state, 0, sizeof (ACPI_GENERIC_STATE)); + + state->common.data_type = ACPI_DESC_TYPE_STATE; + } + + return (state); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_create_update_state + * + * PARAMETERS: Object - Initial Object to be installed in the + * state + * Action - Update action to be performed + * + * RETURN: Status + * + * DESCRIPTION: Create an "Update State" - a flavor of the generic state used + * to update reference counts and delete complex objects such + * as packages. + * + ******************************************************************************/ + +ACPI_GENERIC_STATE * +acpi_ut_create_update_state ( + ACPI_OPERAND_OBJECT *object, + u16 action) +{ + ACPI_GENERIC_STATE *state; + + + /* Create the generic state object */ + + state = acpi_ut_create_generic_state (); + if (!state) { + return (NULL); + } + + /* Init fields specific to the update struct */ + + state->update.object = object; + state->update.value = action; + + return (state); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_create_pkg_state + * + * PARAMETERS: Object - Initial Object to be installed in the + * state + * Action - Update action to be performed + * + * RETURN: Status + * + * DESCRIPTION: Create an "Update State" - a flavor of the generic state used + * to update reference counts and delete complex objects such + * as packages. + * + ******************************************************************************/ + +ACPI_GENERIC_STATE * +acpi_ut_create_pkg_state ( + void *internal_object, + void *external_object, + u16 index) +{ + ACPI_GENERIC_STATE *state; + + + /* Create the generic state object */ + + state = acpi_ut_create_generic_state (); + if (!state) { + return (NULL); + } + + /* Init fields specific to the update struct */ + + state->pkg.source_object = (ACPI_OPERAND_OBJECT *) internal_object; + state->pkg.dest_object = external_object; + state->pkg.index = index; + state->pkg.num_packages = 1; + + return (state); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_create_control_state + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Create a "Control State" - a flavor of the generic state used + * to support nested IF/WHILE constructs in the AML. + * + ******************************************************************************/ + +ACPI_GENERIC_STATE * +acpi_ut_create_control_state ( + void) +{ + ACPI_GENERIC_STATE *state; + + + /* Create the generic state object */ + + state = acpi_ut_create_generic_state (); + if (!state) { + return (NULL); + } + + + /* Init fields specific to the control struct */ + + state->common.state = CONTROL_CONDITIONAL_EXECUTING; + + return (state); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_delete_generic_state + * + * PARAMETERS: State - The state object to be deleted + * + * RETURN: Status + * + * DESCRIPTION: Put a state object back into the global state cache. The object + * is not actually freed at this time. + * + ******************************************************************************/ + +void +acpi_ut_delete_generic_state ( + ACPI_GENERIC_STATE *state) +{ + + /* If cache is full, just free this state object */ + + if (acpi_gbl_generic_state_cache_depth >= MAX_STATE_CACHE_DEPTH) { + acpi_ut_free (state); + } + + /* Otherwise put this object back into the cache */ + + else { + acpi_ut_acquire_mutex (ACPI_MTX_CACHES); + + /* Clear the state */ + + MEMSET (state, 0, sizeof (ACPI_GENERIC_STATE)); + state->common.data_type = ACPI_DESC_TYPE_STATE; + + /* Put the object at the head of the global cache list */ + + state->common.next = acpi_gbl_generic_state_cache; + acpi_gbl_generic_state_cache = state; + acpi_gbl_generic_state_cache_depth++; + + + acpi_ut_release_mutex (ACPI_MTX_CACHES); + } + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_delete_generic_state_cache + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Purge the global state object cache. Used during subsystem + * termination. + * + ******************************************************************************/ + +void +acpi_ut_delete_generic_state_cache ( + void) +{ + ACPI_GENERIC_STATE *next; + + + /* Traverse the global cache list */ + + while (acpi_gbl_generic_state_cache) { + /* Delete one cached state object */ + + next = acpi_gbl_generic_state_cache->common.next; + acpi_ut_free (acpi_gbl_generic_state_cache); + acpi_gbl_generic_state_cache = next; + acpi_gbl_generic_state_cache_depth--; + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_resolve_package_references + * + * PARAMETERS: Obj_desc - The Package object on which to resolve refs + * + * RETURN: Status + * + * DESCRIPTION: Walk through a package and turn internal references into values + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ut_resolve_package_references ( + ACPI_OPERAND_OBJECT *obj_desc) +{ + u32 count; + ACPI_OPERAND_OBJECT *sub_object; + + + if (obj_desc->common.type != ACPI_TYPE_PACKAGE) { + /* The object must be a package */ + + REPORT_ERROR (("Must resolve Package Refs on a Package\n")); + return(AE_ERROR); + } + + /* + * TBD: what about nested packages? */ + + for (count = 0; count < obj_desc->package.count; count++) { + sub_object = obj_desc->package.elements[count]; + + if (sub_object->common.type == INTERNAL_TYPE_REFERENCE) { + if (sub_object->reference.opcode == AML_ZERO_OP) { + sub_object->common.type = ACPI_TYPE_INTEGER; + sub_object->integer.value = 0; + } + + else if (sub_object->reference.opcode == AML_ONE_OP) { + sub_object->common.type = ACPI_TYPE_INTEGER; + sub_object->integer.value = 1; + } + + else if (sub_object->reference.opcode == AML_ONES_OP) { + sub_object->common.type = ACPI_TYPE_INTEGER; + sub_object->integer.value = ACPI_INTEGER_MAX; + } + } + } + + return(AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_walk_package_tree + * + * PARAMETERS: Obj_desc - The Package object on which to resolve refs + * + * RETURN: Status + * + * DESCRIPTION: Walk through a package + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ut_walk_package_tree ( + ACPI_OPERAND_OBJECT *source_object, + void *target_object, + ACPI_PKG_CALLBACK walk_callback, + void *context) +{ + ACPI_STATUS status = AE_OK; + ACPI_GENERIC_STATE *state_list = NULL; + ACPI_GENERIC_STATE *state; + u32 this_index; + ACPI_OPERAND_OBJECT *this_source_obj; + + + state = acpi_ut_create_pkg_state (source_object, target_object, 0); + if (!state) { + return (AE_NO_MEMORY); + } + + while (state) { + this_index = state->pkg.index; + this_source_obj = (ACPI_OPERAND_OBJECT *) + state->pkg.source_object->package.elements[this_index]; + + /* + * Check for + * 1) An uninitialized package element. It is completely + * legal to declare a package and leave it uninitialized + * 2) Not an internal object - can be a namespace node instead + * 3) Any type other than a package. Packages are handled in else + * case below. + */ + if ((!this_source_obj) || + (!VALID_DESCRIPTOR_TYPE ( + this_source_obj, ACPI_DESC_TYPE_INTERNAL)) || + (!IS_THIS_OBJECT_TYPE ( + this_source_obj, ACPI_TYPE_PACKAGE))) { + + status = walk_callback (ACPI_COPY_TYPE_SIMPLE, this_source_obj, + state, context); + if (ACPI_FAILURE (status)) { + /* TBD: must delete package created up to this point */ + + return (status); + } + + state->pkg.index++; + while (state->pkg.index >= state->pkg.source_object->package.count) { + /* + * We've handled all of the objects at this level, This means + * that we have just completed a package. That package may + * have contained one or more packages itself. + * + * Delete this state and pop the previous state (package). + */ + acpi_ut_delete_generic_state (state); + state = acpi_ut_pop_generic_state (&state_list); + + + /* Finished when there are no more states */ + + if (!state) { + /* + * We have handled all of the objects in the top level + * package just add the length of the package objects + * and exit + */ + return (AE_OK); + } + + /* + * Go back up a level and move the index past the just + * completed package object. + */ + state->pkg.index++; + } + } + + else { + /* This is a sub-object of type package */ + + status = walk_callback (ACPI_COPY_TYPE_PACKAGE, this_source_obj, + state, context); + if (ACPI_FAILURE (status)) { + /* TBD: must delete package created up to this point */ + + return (status); + } + + + /* + * The callback above returned a new target package object. + */ + + /* + * Push the current state and create a new one + */ + acpi_ut_push_generic_state (&state_list, state); + state = acpi_ut_create_pkg_state (this_source_obj, + state->pkg.this_target_obj, 0); + if (!state) { + /* TBD: must delete package created up to this point */ + + return (AE_NO_MEMORY); + } + } + } + + /* We should never get here */ + + return (AE_AML_INTERNAL); + +} + + +/******************************************************************************* + * + * FUNCTION: _Report_error + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Message - Error message to use on failure + * + * RETURN: None + * + * DESCRIPTION: Print error message + * + ******************************************************************************/ + +void +_report_error ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id) +{ + + + acpi_os_printf ("%8s-%04d: *** Error: ", module_name, line_number); +} + + +/******************************************************************************* + * + * FUNCTION: _Report_warning + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Message - Error message to use on failure + * + * RETURN: None + * + * DESCRIPTION: Print warning message + * + ******************************************************************************/ + +void +_report_warning ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id) +{ + + acpi_os_printf ("%8s-%04d: *** Warning: ", module_name, line_number); +} + + +/******************************************************************************* + * + * FUNCTION: _Report_info + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Message - Error message to use on failure + * + * RETURN: None + * + * DESCRIPTION: Print information message + * + ******************************************************************************/ + +void +_report_info ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id) +{ + + acpi_os_printf ("%8s-%04d: *** Info: ", module_name, line_number); +} + + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/utilities/utobject.c linux/drivers/acpi/utilities/utobject.c --- v2.4.5/linux/drivers/acpi/utilities/utobject.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/utilities/utobject.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,625 @@ +/****************************************************************************** + * + * Module Name: utobject - ACPI object create/delete/size/cache routines + * $Revision: 46 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "actables.h" +#include "amlcode.h" + + +#define _COMPONENT ACPI_UTILITIES + MODULE_NAME ("utobject") + + +/******************************************************************************* + * + * FUNCTION: _Ut_create_internal_object + * + * PARAMETERS: Address - Address of the memory to deallocate + * Component - Component type of caller + * Module - Source file name of caller + * Line - Line number of caller + * Type - ACPI Type of the new object + * + * RETURN: Object - The new object. Null on failure + * + * DESCRIPTION: Create and initialize a new internal object. + * + * NOTE: We always allocate the worst-case object descriptor because + * these objects are cached, and we want them to be + * one-size-satisifies-any-request. This in itself may not be + * the most memory efficient, but the efficiency of the object + * cache should more than make up for this! + * + ******************************************************************************/ + +ACPI_OPERAND_OBJECT * +_ut_create_internal_object ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + ACPI_OBJECT_TYPE8 type) +{ + ACPI_OPERAND_OBJECT *object; + + + /* Allocate the raw object descriptor */ + + object = _ut_allocate_object_desc (module_name, line_number, component_id); + if (!object) { + /* Allocation failure */ + + return (NULL); + } + + /* Save the object type in the object descriptor */ + + object->common.type = type; + + /* Init the reference count */ + + object->common.reference_count = 1; + + /* Any per-type initialization should go here */ + + + return (object); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_valid_internal_object + * + * PARAMETERS: Operand - Object to be validated + * + * RETURN: Validate a pointer to be an ACPI_OPERAND_OBJECT + * + ******************************************************************************/ + +u8 +acpi_ut_valid_internal_object ( + void *object) +{ + + PROC_NAME ("Ut_valid_internal_object"); + + + /* Check for a null pointer */ + + if (!object) { + return (FALSE); + } + + /* Check for a pointer within one of the ACPI tables */ + + if (acpi_tb_system_table_pointer (object)) { + return (FALSE); + } + + /* Check the descriptor type field */ + + if (!VALID_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_INTERNAL)) { + /* Not an ACPI internal object, do some further checking */ + + + + + return (FALSE); + } + + + /* The object appears to be a valid ACPI_OPERAND_OBJECT */ + + return (TRUE); +} + + +/******************************************************************************* + * + * FUNCTION: _Ut_allocate_object_desc + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Message - Error message to use on failure + * + * RETURN: Pointer to newly allocated object descriptor. Null on error + * + * DESCRIPTION: Allocate a new object descriptor. Gracefully handle + * error conditions. + * + ******************************************************************************/ + +void * +_ut_allocate_object_desc ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id) +{ + ACPI_OPERAND_OBJECT *object; + + + acpi_ut_acquire_mutex (ACPI_MTX_CACHES); + + acpi_gbl_object_cache_requests++; + + /* Check the cache first */ + + if (acpi_gbl_object_cache) { + /* There is an object available, use it */ + + object = acpi_gbl_object_cache; + acpi_gbl_object_cache = object->cache.next; + object->cache.next = NULL; + + acpi_gbl_object_cache_hits++; + acpi_gbl_object_cache_depth--; + + acpi_ut_release_mutex (ACPI_MTX_CACHES); + } + + else { + /* The cache is empty, create a new object */ + + acpi_ut_release_mutex (ACPI_MTX_CACHES); + + /* Attempt to allocate new descriptor */ + + object = _ut_callocate (sizeof (ACPI_OPERAND_OBJECT), component_id, + module_name, line_number); + if (!object) { + /* Allocation failed */ + + _REPORT_ERROR (module_name, line_number, component_id, + ("Could not allocate an object descriptor\n")); + + return (NULL); + } + + /* Memory allocation metrics - compiled out in non debug mode. */ + + INCREMENT_OBJECT_METRICS (sizeof (ACPI_OPERAND_OBJECT)); + } + + /* Mark the descriptor type */ + + object->common.data_type = ACPI_DESC_TYPE_INTERNAL; + + return (object); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_delete_object_desc + * + * PARAMETERS: Object - Acpi internal object to be deleted + * + * RETURN: None. + * + * DESCRIPTION: Free an ACPI object descriptor or add it to the object cache + * + ******************************************************************************/ + +void +acpi_ut_delete_object_desc ( + ACPI_OPERAND_OBJECT *object) +{ + + + /* Make sure that the object isn't already in the cache */ + + if (object->common.data_type == (ACPI_DESC_TYPE_INTERNAL | ACPI_CACHED_OBJECT)) { + return; + } + + /* Object must be an ACPI_OPERAND_OBJECT */ + + if (object->common.data_type != ACPI_DESC_TYPE_INTERNAL) { + return; + } + + + /* If cache is full, just free this object */ + + if (acpi_gbl_object_cache_depth >= MAX_OBJECT_CACHE_DEPTH) { + /* + * Memory allocation metrics. Call the macro here since we only + * care about dynamically allocated objects. + */ + DECREMENT_OBJECT_METRICS (sizeof (ACPI_OPERAND_OBJECT)); + + acpi_ut_free (object); + return; + } + + acpi_ut_acquire_mutex (ACPI_MTX_CACHES); + + /* Clear the entire object. This is important! */ + + MEMSET (object, 0, sizeof (ACPI_OPERAND_OBJECT)); + object->common.data_type = ACPI_DESC_TYPE_INTERNAL | ACPI_CACHED_OBJECT; + + /* Put the object at the head of the global cache list */ + + object->cache.next = acpi_gbl_object_cache; + acpi_gbl_object_cache = object; + acpi_gbl_object_cache_depth++; + + + acpi_ut_release_mutex (ACPI_MTX_CACHES); + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_delete_object_cache + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Purge the global state object cache. Used during subsystem + * termination. + * + ******************************************************************************/ + +void +acpi_ut_delete_object_cache ( + void) +{ + ACPI_OPERAND_OBJECT *next; + + + /* Traverse the global cache list */ + + while (acpi_gbl_object_cache) { + /* Delete one cached state object */ + + next = acpi_gbl_object_cache->cache.next; + acpi_gbl_object_cache->cache.next = NULL; + + /* + * Memory allocation metrics. Call the macro here since we only + * care about dynamically allocated objects. + */ + DECREMENT_OBJECT_METRICS (sizeof (ACPI_OPERAND_OBJECT)); + + acpi_ut_free (acpi_gbl_object_cache); + acpi_gbl_object_cache = next; + acpi_gbl_object_cache_depth--; + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_init_static_object + * + * PARAMETERS: Obj_desc - Pointer to a "static" object - on stack + * or in the data segment. + * + * RETURN: None. + * + * DESCRIPTION: Initialize a static object. Sets flags to disallow dynamic + * deletion of the object. + * + ******************************************************************************/ + +void +acpi_ut_init_static_object ( + ACPI_OPERAND_OBJECT *obj_desc) +{ + + + if (!obj_desc) { + return; + } + + + /* + * Clear the entire descriptor + */ + MEMSET ((void *) obj_desc, 0, sizeof (ACPI_OPERAND_OBJECT)); + + + /* + * Initialize the header fields + * 1) This is an ACPI_OPERAND_OBJECT descriptor + * 2) The size is the full object (worst case) + * 3) The flags field indicates static allocation + * 4) Reference count starts at one (not really necessary since the + * object can't be deleted, but keeps everything sane) + */ + + obj_desc->common.data_type = ACPI_DESC_TYPE_INTERNAL; + obj_desc->common.flags = AOPOBJ_STATIC_ALLOCATION; + obj_desc->common.reference_count = 1; + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_get_simple_object_size + * + * PARAMETERS: *Internal_object - Pointer to the object we are examining + * *Ret_length - Where the length is returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to determine the space required to + * contain a simple object for return to an API user. + * + * The length includes the object structure plus any additional + * needed space. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ut_get_simple_object_size ( + ACPI_OPERAND_OBJECT *internal_object, + u32 *obj_length) +{ + u32 length; + ACPI_STATUS status = AE_OK; + + + /* Handle a null object (Could be a uninitialized package element -- which is legal) */ + + if (!internal_object) { + *obj_length = 0; + return (AE_OK); + } + + + /* Start with the length of the Acpi object */ + + length = sizeof (ACPI_OBJECT); + + if (VALID_DESCRIPTOR_TYPE (internal_object, ACPI_DESC_TYPE_NAMED)) { + /* Object is a named object (reference), just return the length */ + + *obj_length = (u32) ROUND_UP_TO_NATIVE_WORD (length); + return (status); + } + + + /* + * The final length depends on the object type + * Strings and Buffers are packed right up against the parent object and + * must be accessed bytewise or there may be alignment problems on + * certain processors + */ + + switch (internal_object->common.type) { + + case ACPI_TYPE_STRING: + + length += internal_object->string.length + 1; + break; + + + case ACPI_TYPE_BUFFER: + + length += internal_object->buffer.length; + break; + + + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_POWER: + + /* + * No extra data for these types + */ + break; + + + case INTERNAL_TYPE_REFERENCE: + + /* + * The only type that should be here is internal opcode NAMEPATH_OP -- since + * this means an object reference + */ + if (internal_object->reference.opcode != AML_INT_NAMEPATH_OP) { + status = AE_TYPE; + } + + else { + /* + * Get the actual length of the full pathname to this object. + * The reference will be converted to the pathname to the object + */ + length += ROUND_UP_TO_NATIVE_WORD (acpi_ns_get_pathname_length (internal_object->reference.node)); + } + break; + + + default: + + status = AE_TYPE; + break; + } + + + /* + * Account for the space required by the object rounded up to the next + * multiple of the machine word size. This keeps each object aligned + * on a machine word boundary. (preventing alignment faults on some + * machines.) + */ + *obj_length = (u32) ROUND_UP_TO_NATIVE_WORD (length); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_get_element_length + * + * PARAMETERS: ACPI_PKG_CALLBACK + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: Get the length of one package element. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ut_get_element_length ( + u8 object_type, + ACPI_OPERAND_OBJECT *source_object, + ACPI_GENERIC_STATE *state, + void *context) +{ + ACPI_STATUS status = AE_OK; + ACPI_PKG_INFO *info = (ACPI_PKG_INFO *) context; + u32 object_space; + + + switch (object_type) { + case 0: + + /* + * Simple object - just get the size (Null object/entry is handled + * here also) and sum it into the running package length + */ + status = acpi_ut_get_simple_object_size (source_object, &object_space); + if (ACPI_FAILURE (status)) { + return (status); + } + + info->length += object_space; + break; + + + case 1: + /* Package - nothing much to do here, let the walk handle it */ + + info->num_packages++; + state->pkg.this_target_obj = NULL; + break; + + default: + return (AE_BAD_PARAMETER); + } + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_get_package_object_size + * + * PARAMETERS: *Internal_object - Pointer to the object we are examining + * *Ret_length - Where the length is returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to determine the space required to + * contain a package object for return to an API user. + * + * This is moderately complex since a package contains other + * objects including packages. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ut_get_package_object_size ( + ACPI_OPERAND_OBJECT *internal_object, + u32 *obj_length) +{ + ACPI_STATUS status; + ACPI_PKG_INFO info; + + + info.length = 0; + info.object_space = 0; + info.num_packages = 1; + + status = acpi_ut_walk_package_tree (internal_object, NULL, + acpi_ut_get_element_length, &info); + + /* + * We have handled all of the objects in all levels of the package. + * just add the length of the package objects themselves. + * Round up to the next machine word. + */ + info.length += ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT)) * + info.num_packages; + + /* Return the total package length */ + + *obj_length = info.length; + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ut_get_object_size + * + * PARAMETERS: *Internal_object - Pointer to the object we are examining + * *Ret_length - Where the length will be returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to determine the space required to + * contain an object for return to an API user. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ut_get_object_size( + ACPI_OPERAND_OBJECT *internal_object, + u32 *obj_length) +{ + ACPI_STATUS status; + + + if ((VALID_DESCRIPTOR_TYPE (internal_object, ACPI_DESC_TYPE_INTERNAL)) && + (IS_THIS_OBJECT_TYPE (internal_object, ACPI_TYPE_PACKAGE))) { + status = acpi_ut_get_package_object_size (internal_object, obj_length); + } + + else { + status = acpi_ut_get_simple_object_size (internal_object, obj_length); + } + + return (status); +} + + diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/utilities/utxface.c linux/drivers/acpi/utilities/utxface.c --- v2.4.5/linux/drivers/acpi/utilities/utxface.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/acpi/utilities/utxface.c Wed Jun 20 17:47:40 2001 @@ -0,0 +1,476 @@ +/****************************************************************************** + * + * Module Name: utxface - External interfaces for "global" ACPI functions + * $Revision: 72 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * 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 "acpi.h" +#include "acevents.h" +#include "achware.h" +#include "acnamesp.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acdebug.h" + + +#define _COMPONENT ACPI_UTILITIES + MODULE_NAME ("utxface") + + +/******************************************************************************* + * + * FUNCTION: Acpi_initialize_subsystem + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initializes all global variables. This is the first function + * called, so any early initialization belongs here. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_initialize_subsystem ( + void) +{ + ACPI_STATUS status; + + + /* Initialize all globals used by the subsystem */ + + acpi_ut_init_globals (); + + /* Initialize the OS-Dependent layer */ + + status = acpi_os_initialize (); + if (ACPI_FAILURE (status)) { + REPORT_ERROR (("OSD failed to initialize, %s\n", + acpi_ut_format_exception (status))); + return (status); + } + + /* Create the default mutex objects */ + + status = acpi_ut_mutex_initialize (); + if (ACPI_FAILURE (status)) { + REPORT_ERROR (("Global mutex creation failure, %s\n", + acpi_ut_format_exception (status))); + return (status); + } + + /* + * Initialize the namespace manager and + * the root of the namespace tree + */ + + status = acpi_ns_root_initialize (); + if (ACPI_FAILURE (status)) { + REPORT_ERROR (("Namespace initialization failure, %s\n", + acpi_ut_format_exception (status))); + return (status); + } + + + /* If configured, initialize the AML debugger */ + + DEBUGGER_EXEC (acpi_db_initialize ()); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_enable_subsystem + * + * PARAMETERS: Flags - Init/enable Options + * + * RETURN: Status + * + * DESCRIPTION: Completes the subsystem initialization including hardware. + * Puts system into ACPI mode if it isn't already. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_enable_subsystem ( + u32 flags) +{ + ACPI_STATUS status = AE_OK; + + + /* Sanity check the FADT for valid values */ + + status = acpi_ut_validate_fadt (); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * Install the default Op_region handlers. These are + * installed unless other handlers have already been + * installed via the Install_address_space_handler interface + */ + + if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) { + status = acpi_ev_install_default_address_space_handlers (); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + /* + * We must initialize the hardware before we can enable ACPI. + */ + + if (!(flags & ACPI_NO_HARDWARE_INIT)) { + status = acpi_hw_initialize (); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + /* + * Enable ACPI on this platform + */ + + if (!(flags & ACPI_NO_ACPI_ENABLE)) { + status = acpi_enable (); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + /* + * Note: + * We must have the hardware AND events initialized before we can execute + * ANY control methods SAFELY. Any control method can require ACPI hardware + * support, so the hardware MUST be initialized before execution! + */ + + if (!(flags & ACPI_NO_EVENT_INIT)) { + status = acpi_ev_initialize (); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + + /* + * Initialize all device objects in the namespace + * This runs the _STA and _INI methods. + */ + + if (!(flags & ACPI_NO_DEVICE_INIT)) { + status = acpi_ns_initialize_devices (); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + + /* + * Initialize the objects that remain uninitialized. This + * runs the executable AML that is part of the declaration of Op_regions + * and Fields. + */ + + if (!(flags & ACPI_NO_OBJECT_INIT)) { + status = acpi_ns_initialize_objects (); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_terminate + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Shutdown the ACPI subsystem. Release all resources. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_terminate (void) +{ + ACPI_STATUS status; + + + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Terminate the AML Debugger if present */ + + DEBUGGER_EXEC(acpi_gbl_db_terminate_threads = TRUE); + + /* TBD: [Investigate] This is no longer needed?*/ +/* Acpi_ut_release_mutex (ACPI_MTX_DEBUG_CMD_READY); */ + + + /* Shutdown and free all resources */ + + acpi_ut_subsystem_shutdown (); + + + /* Free the mutex objects */ + + acpi_ut_mutex_terminate (); + + + /* Now we can shutdown the OS-dependent layer */ + + acpi_os_terminate (); + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_get_system_info + * + * PARAMETERS: Out_buffer - a pointer to a buffer to receive the + * resources for the device + * Buffer_length - the number of bytes available in the buffer + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to get information about the current + * state of the ACPI subsystem. It will return system information + * in the Out_buffer. + * + * If the function fails an appropriate status will be returned + * and the value of Out_buffer is undefined. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_system_info ( + ACPI_BUFFER *out_buffer) +{ + ACPI_SYSTEM_INFO *info_ptr; + u32 i; + ACPI_STATUS status; + + + /* Ensure that ACPI has been initialized */ + + ACPI_IS_INITIALIZATION_COMPLETE (status); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * Must have a valid buffer + */ + if ((!out_buffer) || + (!out_buffer->pointer)) { + return (AE_BAD_PARAMETER); + } + + if (out_buffer->length < sizeof (ACPI_SYSTEM_INFO)) { + /* + * Caller's buffer is too small + */ + out_buffer->length = sizeof (ACPI_SYSTEM_INFO); + + return (AE_BUFFER_OVERFLOW); + } + + + /* + * Set return length and get data + */ + out_buffer->length = sizeof (ACPI_SYSTEM_INFO); + info_ptr = (ACPI_SYSTEM_INFO *) out_buffer->pointer; + + info_ptr->acpi_ca_version = ACPI_CA_VERSION; + + /* System flags (ACPI capabilities) */ + + info_ptr->flags = acpi_gbl_system_flags; + + /* Timer resolution - 24 or 32 bits */ + if (!acpi_gbl_FADT) { + info_ptr->timer_resolution = 0; + } + else if (acpi_gbl_FADT->tmr_val_ext == 0) { + info_ptr->timer_resolution = 24; + } + else { + info_ptr->timer_resolution = 32; + } + + /* Clear the reserved fields */ + + info_ptr->reserved1 = 0; + info_ptr->reserved2 = 0; + + /* Current debug levels */ + + info_ptr->debug_layer = acpi_dbg_layer; + info_ptr->debug_level = acpi_dbg_level; + + /* Current status of the ACPI tables, per table type */ + + info_ptr->num_table_types = NUM_ACPI_TABLES; + for (i = 0; i < NUM_ACPI_TABLES; i++) { + info_ptr->table_info[i].count = acpi_gbl_acpi_tables[i].count; + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_format_exception + * + * PARAMETERS: Out_buffer - a pointer to a buffer to receive the + * exception name + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function translates an ACPI exception into an ASCII string. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_format_exception ( + ACPI_STATUS exception, + ACPI_BUFFER *out_buffer) +{ + u32 length; + NATIVE_CHAR *formatted_exception; + + + /* + * Must have a valid buffer + */ + if ((!out_buffer) || + (!out_buffer->pointer)) { + return (AE_BAD_PARAMETER); + } + + + /* Convert the exception code (Handles bad exception codes) */ + + formatted_exception = acpi_ut_format_exception (exception); + + /* + * Get length of string and check if it will fit in caller's buffer + */ + + length = STRLEN (formatted_exception); + if (out_buffer->length < length) { + out_buffer->length = length; + return (AE_BUFFER_OVERFLOW); + } + + + /* Copy the string, all done */ + + STRCPY (out_buffer->pointer, formatted_exception); + + return (AE_OK); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_allocate + * + * PARAMETERS: Size - Size of the allocation + * + * RETURN: Address of the allocated memory on success, NULL on failure. + * + * DESCRIPTION: The subsystem's equivalent of malloc. + * External front-end to the Ut* memory manager + * + ****************************************************************************/ + +void * +acpi_allocate ( + u32 size) +{ + + return (acpi_ut_allocate (size)); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_callocate + * + * PARAMETERS: Size - Size of the allocation + * + * RETURN: Address of the allocated memory on success, NULL on failure. + * + * DESCRIPTION: The subsystem's equivalent of calloc. + * External front-end to the Ut* memory manager + * + ****************************************************************************/ + +void * +acpi_callocate ( + u32 size) +{ + + return (acpi_ut_callocate (size)); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_free + * + * PARAMETERS: Address - Address of the memory to deallocate + * + * RETURN: None + * + * DESCRIPTION: Frees the memory at Address + * External front-end to the Ut* memory manager + * + ****************************************************************************/ + +void +acpi_free ( + void *address) +{ + + acpi_ut_free (address); +} diff -u --recursive --new-file v2.4.5/linux/drivers/atm/ambassador.c linux/drivers/atm/ambassador.c --- v2.4.5/linux/drivers/atm/ambassador.c Fri Dec 29 14:35:47 2000 +++ linux/drivers/atm/ambassador.c Wed Jun 27 16:18:13 2001 @@ -613,19 +613,21 @@ while (timeout) { // go to sleep // PRINTD (DBG_CMD, "wait: sleeping %lu for command", timeout); + set_current_state(TASK_UNINTERRUPTIBLE); timeout = schedule_timeout (timeout); - // woken up by timeout or signal } // wait for my slot to be reached (all waiters are here or above, until...) while (ptrs->out != my_slot) { PRINTD (DBG_CMD, "wait: command slot (now at %p)", ptrs->out); + set_current_state(TASK_UNINTERRUPTIBLE); schedule(); } // wait on my slot (... one gets to its slot, and... ) while (ptrs->out->request != cpu_to_be32 (SRB_COMPLETE)) { PRINTD (DBG_CMD, "wait: command slot completion"); + set_current_state(TASK_UNINTERRUPTIBLE); schedule(); } @@ -1986,6 +1988,7 @@ while (!lb->result || lb->result == cpu_to_be32 (COMMAND_IN_PROGRESS)) if (timeout) { + set_current_state(TASK_UNINTERRUPTIBLE); timeout = schedule_timeout (timeout); } else { PRINTD (DBG_LOAD|DBG_ERR, "command %d timed out", cmd); @@ -2110,12 +2113,15 @@ unsigned long timeout; // 4.2 second wait timeout = HZ*42/10; - while (timeout) + while (timeout) { + set_current_state(TASK_UNINTERRUPTIBLE); timeout = schedule_timeout (timeout); + } // half second time-out timeout = HZ/2; while (!rd_plain (dev, offsetof(amb_mem, mb.loader.ready))) if (timeout) { + set_current_state(TASK_UNINTERRUPTIBLE); timeout = schedule_timeout (timeout); } else { PRINTD (DBG_LOAD|DBG_ERR, "reset timed out"); @@ -2255,8 +2261,10 @@ u32 minor; command cmd; cmd.request = cpu_to_be32 (SRB_GET_VERSION); - while (command_do (dev, &cmd)) + while (command_do (dev, &cmd)) { + set_current_state(TASK_UNINTERRUPTIBLE); schedule(); + } major = be32_to_cpu (cmd.args.version.major); minor = be32_to_cpu (cmd.args.version.minor); PRINTK (KERN_INFO, "microcode version is %u.%u", major, minor); @@ -2280,8 +2288,10 @@ } cmd.request = cpu_to_be32 (SRB_GET_BIA); - while (command_do (dev, &cmd)) + while (command_do (dev, &cmd)) { + set_current_state(TASK_UNINTERRUPTIBLE); schedule(); + } lower4 = be32_to_cpu (cmd.args.bia.lower4); upper2 = be32_to_cpu (cmd.args.bia.upper2); PRINTD (DBG_LOAD, "BIA: lower4: %08x, upper2 %04x", lower4, upper2); @@ -2362,7 +2372,7 @@ struct pci_dev * pci_dev; int devs; - void do_pci_device (void) { + void __init do_pci_device (void) { amb_dev * dev; // read resources from PCI configuration space diff -u --recursive --new-file v2.4.5/linux/drivers/atm/fore200e.c linux/drivers/atm/fore200e.c --- v2.4.5/linux/drivers/atm/fore200e.c Fri Feb 9 11:30:22 2001 +++ linux/drivers/atm/fore200e.c Wed Jun 27 16:18:13 2001 @@ -439,6 +439,7 @@ case FORE200E_STATE_BLANK: /* nothing to do for that state */ + break; } } @@ -2023,8 +2024,10 @@ if (!prom) return -ENOMEM; ok = fore200e->bus->prom_read(fore200e, prom); - if (ok < 0) + if (ok < 0) { + fore200e_kfree(prom); return -EBUSY; + } printk(FORE200E "device %s, rev. %c, S/N: %d, ESI: %02x:%02x:%02x:%02x:%02x:%02x\n", fore200e->name, diff -u --recursive --new-file v2.4.5/linux/drivers/atm/fore200e_mkfirm.c linux/drivers/atm/fore200e_mkfirm.c --- v2.4.5/linux/drivers/atm/fore200e_mkfirm.c Mon Feb 21 16:32:27 2000 +++ linux/drivers/atm/fore200e_mkfirm.c Wed Jun 20 11:10:27 2001 @@ -10,8 +10,9 @@ */ #include +#include #include -#include +#include char* default_basename = "pca200e"; /* was initially written for the PCA-200E firmware */ char* default_infname = ""; diff -u --recursive --new-file v2.4.5/linux/drivers/atm/idt77105.c linux/drivers/atm/idt77105.c --- v2.4.5/linux/drivers/atm/idt77105.c Thu Jul 6 21:37:24 2000 +++ linux/drivers/atm/idt77105.c Wed Jun 27 16:18:13 2001 @@ -144,18 +144,18 @@ static int fetch_stats(struct atm_dev *dev,struct idt77105_stats *arg,int zero) { unsigned long flags; - int error; + struct idt77105_stats stats; - error = 0; save_flags(flags); cli(); - if (arg) - error = copy_to_user(arg,&PRIV(dev)->stats, - sizeof(struct idt77105_stats)); - if (zero && !error) - memset(&PRIV(dev)->stats,0,sizeof(struct idt77105_stats)); + memcpy(&stats, &PRIV(dev)->stats, sizeof(struct idt77105_stats)); + if (zero) + memset(&PRIV(dev)->stats, 0, sizeof(struct idt77105_stats)); restore_flags(flags); - return error ? -EFAULT : sizeof(struct idt77105_stats); + if (arg == NULL) + return 0; + return copy_to_user(arg, &PRIV(dev)->stats, + sizeof(struct idt77105_stats)) ? -EFAULT : 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/atm/iphase.c linux/drivers/atm/iphase.c --- v2.4.5/linux/drivers/atm/iphase.c Sun Feb 4 10:05:29 2001 +++ linux/drivers/atm/iphase.c Thu Jun 28 14:48:08 2001 @@ -63,7 +63,6 @@ #include #include #include -#include #include #include "iphase.h" #include "suni.h" @@ -95,6 +94,10 @@ MODULE_PARM(IA_RX_BUF, "i"); MODULE_PARM(IA_RX_BUF_SZ, "i"); MODULE_PARM(IADebugFlag, "i"); +#endif + +#if BITS_PER_LONG != 32 +# error FIXME: this driver only works on 32-bit platforms #endif /**************************** IA_LIB **********************************/ diff -u --recursive --new-file v2.4.5/linux/drivers/atm/nicstar.c linux/drivers/atm/nicstar.c --- v2.4.5/linux/drivers/atm/nicstar.c Sun Mar 25 18:24:31 2001 +++ linux/drivers/atm/nicstar.c Wed Jun 27 14:13:01 2001 @@ -62,6 +62,9 @@ #include "idt77105.h" #endif /* CONFIG_ATM_NICSTAR_USE_IDT77105 */ +#if BITS_PER_LONG != 32 +# error FIXME: this driver requires a 32-bit platform +#endif /* Additional code ************************************************************/ diff -u --recursive --new-file v2.4.5/linux/drivers/atm/uPD98402.c linux/drivers/atm/uPD98402.c --- v2.4.5/linux/drivers/atm/uPD98402.c Fri Apr 14 09:37:10 2000 +++ linux/drivers/atm/uPD98402.c Wed Jun 27 16:19:07 2001 @@ -86,16 +86,17 @@ static int get_sense(struct atm_dev *dev,u8 *arg) { unsigned long flags; - int error; + unsigned char s[3]; save_flags(flags); cli(); - error = put_user(GET(C11R),arg) || put_user(GET(C12R),arg+1) || - put_user(GET(C13R),arg+2); + s[0] = GET(C11R); + s[1] = GET(C12R); + s[2] = GET(C13R); restore_flags(flags); - error = error || put_user(0xff,arg+3) || put_user(0xff,arg+4) || - put_user(0xff,arg+5); - return error ? -EFAULT : 0; + return (put_user(s[0], arg) || put_user(s[1], arg+1) || + put_user(s[2], arg+2) || put_user(0xff, arg+3) || + put_user(0xff, arg+4) || put_user(0xff, arg+5)) ? -EFAULT : 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/atm/zatm.c linux/drivers/atm/zatm.c --- v2.4.5/linux/drivers/atm/zatm.c Wed Apr 11 19:02:30 2001 +++ linux/drivers/atm/zatm.c Wed Jun 27 16:19:07 2001 @@ -255,9 +255,7 @@ static void drain_free(struct atm_dev *dev,int pool) { - struct sk_buff *skb; - - while ((skb = skb_dequeue(&ZATM_DEV(dev)->pool[pool]))) kfree_skb(skb); + skb_queue_purge(&ZATM_DEV(dev)->pool[pool]); } @@ -1464,6 +1462,9 @@ DPRINTK("zatm_start\n"); zatm_dev = ZATM_DEV(dev); + zatm_dev->rx_map = zatm_dev->tx_map = NULL; + for (i = 0; i < NR_MBX; i++) + zatm_dev->mbx_start[i] = 0; if (request_irq(zatm_dev->irq,&zatm_int,SA_SHIRQ,DEV_LABEL,dev)) { printk(KERN_ERR DEV_LABEL "(itf %d): IRQ%d is already in use\n", dev->number,zatm_dev->irq); @@ -1496,25 +1497,27 @@ "%ld VCs\n",dev->number,NR_SHAPERS,pools,rx, (zatm_dev->mem-curr*4)/VC_SIZE); /* create mailboxes */ - for (i = 0; i < NR_MBX; i++) zatm_dev->mbx_start[i] = 0; for (i = 0; i < NR_MBX; i++) if (mbx_entries[i]) { unsigned long here; here = (unsigned long) kmalloc(2*MBX_SIZE(i), GFP_KERNEL); - if (!here) return -ENOMEM; + if (!here) { + error = -ENOMEM; + goto out; + } if ((here^(here+MBX_SIZE(i))) & ~0xffffUL)/* paranoia */ here = (here & ~0xffffUL)+0x10000; + zatm_dev->mbx_start[i] = here; if ((here^virt_to_bus((void *) here)) & 0xffff) { printk(KERN_ERR DEV_LABEL "(itf %d): system " "bus incompatible with driver\n", dev->number); - kfree((void *) here); - return -ENODEV; + error = -ENODEV; + goto out; } DPRINTK("mbx@0x%08lx-0x%08lx\n",here,here+MBX_SIZE(i)); - zatm_dev->mbx_start[i] = here; zatm_dev->mbx_end[i] = (here+MBX_SIZE(i)) & 0xffff; zout(virt_to_bus((void *) here) >> 16,MSH(i)); zout(virt_to_bus((void *) here),MSL(i)); @@ -1523,15 +1526,25 @@ zout(here & 0xffff,MWA(i)); } error = start_tx(dev); - if (error) return error; + if (error) goto out; error = start_rx(dev); - if (error) return error; + if (error) goto out; error = dev->phy->start(dev); - if (error) return error; + if (error) goto out; zout(0xffffffff,IMR); /* enable interrupts */ /* enable TX & RX */ zout(zin(GMR) | uPD98401_GMR_SE | uPD98401_GMR_RE,GMR); return 0; + out: + for (i = 0; i < NR_MBX; i++) + if (zatm_dev->mbx_start[i] != 0) + kfree((void *) zatm_dev->mbx_start[i]); + if (zatm_dev->rx_map != NULL) + kfree(zatm_dev->rx_map); + if (zatm_dev->tx_map != NULL) + kfree(zatm_dev->tx_map); + free_irq(zatm_dev->irq, dev); + return error; } @@ -1681,22 +1694,16 @@ case ZATM_GETTHIST: { int i; - + struct zatm_t_hist hs[ZATM_TIMER_HISTORY_SIZE]; save_flags(flags); cli(); - for (i = 0; i < ZATM_TIMER_HISTORY_SIZE; i++) { - if (!copy_to_user( - (struct zatm_t_hist *) arg+i, - &zatm_dev->timer_history[ + for (i = 0; i < ZATM_TIMER_HISTORY_SIZE; i++) + hs[i] = zatm_dev->timer_history[ (zatm_dev->th_curr+i) & - (ZATM_TIMER_HISTORY_SIZE-1)], - sizeof(struct zatm_t_hist))) - continue; - restore_flags(flags); - return -EFAULT; - } + (ZATM_TIMER_HISTORY_SIZE-1)]; restore_flags(flags); - return 0; + return copy_to_user((struct zatm_t_hist *) arg, + hs, sizeof(hs)) ? -EFAULT : 0; } #endif default: @@ -1828,11 +1835,11 @@ zatm_dev),GFP_KERNEL); if (!zatm_dev) { printk(KERN_EMERG "zatm.c: memory shortage\n"); - goto out; + return devs; } } } -out: + kfree(zatm_dev); return devs; } diff -u --recursive --new-file v2.4.5/linux/drivers/block/cciss.c linux/drivers/block/cciss.c --- v2.4.5/linux/drivers/block/cciss.c Tue May 22 10:23:16 2001 +++ linux/drivers/block/cciss.c Mon Jul 2 13:56:40 2001 @@ -63,6 +63,7 @@ 0x0E11, 0x4080, 0, 0, 0}, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSB, 0x0E11, 0x4082, 0, 0, 0}, + {0,} }; MODULE_DEVICE_TABLE(pci, cciss_pci_device_id); @@ -610,7 +611,10 @@ { /* Copy the data into the buffer we created */ if (copy_from_user(buff, iocommand.buf, iocommand.buf_size)) + { + kfree(buff); return -EFAULT; + } } if ((c = cmd_alloc(h , 0)) == NULL) { @@ -680,6 +684,7 @@ { kfree(buff); cmd_free(h, c, 0); + return -EFAULT; } } kfree(buff); diff -u --recursive --new-file v2.4.5/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c --- v2.4.5/linux/drivers/block/ll_rw_blk.c Thu Apr 12 12:15:52 2001 +++ linux/drivers/block/ll_rw_blk.c Fri Jun 29 18:58:07 2001 @@ -859,30 +859,34 @@ void generic_make_request (int rw, struct buffer_head * bh) { int major = MAJOR(bh->b_rdev); + int minorsize = 0; request_queue_t *q; if (!bh->b_end_io) BUG(); - if (blk_size[major]) { - unsigned long maxsector = (blk_size[major][MINOR(bh->b_rdev)] << 1) + 1; + /* Test device size, when known. */ + if (blk_size[major]) + minorsize = blk_size[major][MINOR(bh->b_rdev)]; + if (minorsize) { + unsigned long maxsector = (minorsize << 1) + 1; unsigned long sector = bh->b_rsector; unsigned int count = bh->b_size >> 9; if (maxsector < count || maxsector - count < sector) { + /* Yecch */ bh->b_state &= (1 << BH_Lock) | (1 << BH_Mapped); - if (blk_size[major][MINOR(bh->b_rdev)]) { - - /* This may well happen - the kernel calls bread() - without checking the size of the device, e.g., - when mounting a device. */ - printk(KERN_INFO - "attempt to access beyond end of device\n"); - printk(KERN_INFO "%s: rw=%d, want=%ld, limit=%d\n", - kdevname(bh->b_rdev), rw, - (sector + count)>>1, - blk_size[major][MINOR(bh->b_rdev)]); - } + + /* This may well happen - the kernel calls bread() + without checking the size of the device, e.g., + when mounting a device. */ + printk(KERN_INFO + "attempt to access beyond end of device\n"); + printk(KERN_INFO "%s: rw=%d, want=%ld, limit=%d\n", + kdevname(bh->b_rdev), rw, + (sector + count)>>1, minorsize); + + /* Yecch again */ bh->b_end_io(bh, 0); return; } @@ -900,7 +904,8 @@ q = blk_get_queue(bh->b_rdev); if (!q) { printk(KERN_ERR - "generic_make_request: Trying to access nonexistent block-device %s (%ld)\n", + "generic_make_request: Trying to access " + "nonexistent block-device %s (%ld)\n", kdevname(bh->b_rdev), bh->b_rsector); buffer_IO_error(bh); break; diff -u --recursive --new-file v2.4.5/linux/drivers/block/loop.c linux/drivers/block/loop.c --- v2.4.5/linux/drivers/block/loop.c Wed Apr 11 19:05:14 2001 +++ linux/drivers/block/loop.c Fri Jun 29 16:16:56 2001 @@ -386,7 +386,7 @@ struct buffer_head *bh; do { - bh = kmem_cache_alloc(bh_cachep, SLAB_BUFFER); + bh = kmem_cache_alloc(bh_cachep, SLAB_NOIO); if (bh) break; @@ -408,7 +408,7 @@ * so can we :-) */ do { - bh->b_page = alloc_page(GFP_BUFFER); + bh->b_page = alloc_page(GFP_NOIO); if (bh->b_page) break; @@ -648,11 +648,11 @@ lo->ioctl = NULL; figure_loop_size(lo); lo->old_gfp_mask = inode->i_mapping->gfp_mask; - inode->i_mapping->gfp_mask = GFP_BUFFER; + inode->i_mapping->gfp_mask = GFP_NOIO; bs = 0; - if (blksize_size[MAJOR(inode->i_rdev)]) - bs = blksize_size[MAJOR(inode->i_rdev)][MINOR(inode->i_rdev)]; + if (blksize_size[MAJOR(lo_device)]) + bs = blksize_size[MAJOR(lo_device)][MINOR(lo_device)]; if (!bs) bs = BLOCK_SIZE; diff -u --recursive --new-file v2.4.5/linux/drivers/block/nbd.c linux/drivers/block/nbd.c --- v2.4.5/linux/drivers/block/nbd.c Tue May 1 14:20:25 2001 +++ linux/drivers/block/nbd.c Fri Jun 29 16:15:41 2001 @@ -109,7 +109,7 @@ do { - sock->sk->allocation = GFP_BUFFER; + sock->sk->allocation = GFP_NOIO; iov.iov_base = buf; iov.iov_len = size; msg.msg_name = NULL; diff -u --recursive --new-file v2.4.5/linux/drivers/block/paride/pt.c linux/drivers/block/paride/pt.c --- v2.4.5/linux/drivers/block/paride/pt.c Fri Feb 9 11:30:22 2001 +++ linux/drivers/block/paride/pt.c Wed Jun 27 17:10:55 2001 @@ -753,6 +753,10 @@ pt_rewind(unit); return 0; + case MTWEOF: + pt_write_fm(unit); + return 0; + default: printk("%s: Unimplemented mt_op %d\n",PT.name, mtop.mt_op); diff -u --recursive --new-file v2.4.5/linux/drivers/block/ps2esdi.c linux/drivers/block/ps2esdi.c --- v2.4.5/linux/drivers/block/ps2esdi.c Thu May 24 15:14:08 2001 +++ linux/drivers/block/ps2esdi.c Wed Jun 27 17:10:55 2001 @@ -420,6 +420,7 @@ request_dma(dma_arb_level, "ed"); request_region(io_base, 4, "ed"); blksize_size[MAJOR_NR] = ps2esdi_blocksizes; + max_sectors[MAJOR_NR] = ps2esdi_maxsect; for (i = 0; i < ps2esdi_drives; i++) { register_disk(&ps2esdi_gendisk,MKDEV(MAJOR_NR,i<<6),1<<6, diff -u --recursive --new-file v2.4.5/linux/drivers/block/swim3.c linux/drivers/block/swim3.c --- v2.4.5/linux/drivers/block/swim3.c Tue May 22 10:23:16 2001 +++ linux/drivers/block/swim3.c Wed Jun 27 13:37:35 2001 @@ -33,6 +33,7 @@ #define MAJOR_NR FLOPPY_MAJOR #include +#include static int floppy_blocksizes[2] = {512,512}; static int floppy_sizes[2] = {2880,2880}; @@ -248,10 +249,7 @@ int swim3_init(void); #ifndef CONFIG_PMAC_PBOOK -static inline int check_media_bay(struct device_node *which_bay, int what) -{ - return 1; -} +#define check_media_bay(which, what) 1 #endif static void swim3_select(struct floppy_state *fs, int sel) @@ -1014,10 +1012,14 @@ revalidate: floppy_revalidate, }; +static devfs_handle_t floppy_devfs_handle; + int swim3_init(void) { struct device_node *swim; + floppy_devfs_handle = devfs_mk_dir(NULL, "floppy", NULL); + swim = find_devices("floppy"); while (swim && (floppy_count < MAX_FLOPPIES)) { @@ -1034,7 +1036,7 @@ if (floppy_count > 0) { - if (register_blkdev(MAJOR_NR, "fd", &floppy_fops)) { + if (devfs_register_blkdev(MAJOR_NR, "fd", &floppy_fops)) { printk(KERN_ERR "Unable to get major %d for floppy\n", MAJOR_NR); return -EBUSY; @@ -1051,7 +1053,9 @@ { struct device_node *mediabay; struct floppy_state *fs = &floppy_states[floppy_count]; - + char floppy_name[16]; + devfs_handle_t floppy_handle; + if (swim->n_addrs < 2) { printk(KERN_INFO "swim3: expecting 2 addrs (n_addrs:%d, n_intrs:%d)\n", @@ -1108,6 +1112,12 @@ printk(KERN_INFO "fd%d: SWIM3 floppy controller %s\n", floppy_count, mediabay ? "in media bay" : ""); + sprintf(floppy_name, "%s%d", floppy_devfs_handle ? "" : "floppy", + floppy_count); + floppy_handle = devfs_register(floppy_devfs_handle, floppy_name, + DEVFS_FL_DEFAULT, MAJOR_NR, floppy_count, + S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP |S_IWGRP, + &floppy_fops, NULL); floppy_count++; diff -u --recursive --new-file v2.4.5/linux/drivers/bluetooth/Config.in linux/drivers/bluetooth/Config.in --- v2.4.5/linux/drivers/bluetooth/Config.in Wed Dec 31 16:00:00 1969 +++ linux/drivers/bluetooth/Config.in Mon Jun 11 19:15:27 2001 @@ -0,0 +1,8 @@ +mainmenu_option next_comment +comment 'Bluetooth device drivers' + +dep_tristate 'HCI USB driver' CONFIG_BLUEZ_HCIUSB $CONFIG_BLUEZ $CONFIG_USB +dep_tristate 'HCI UART driver' CONFIG_BLUEZ_HCIUART $CONFIG_BLUEZ +dep_tristate 'HCI EMU (virtual device) driver' CONFIG_BLUEZ_HCIEMU $CONFIG_BLUEZ + +endmenu diff -u --recursive --new-file v2.4.5/linux/drivers/bluetooth/Makefile linux/drivers/bluetooth/Makefile --- v2.4.5/linux/drivers/bluetooth/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/bluetooth/Makefile Mon Jun 11 19:15:27 2001 @@ -0,0 +1,11 @@ +# +# Makefile for Bluetooth HCI device drivers. +# + +O_TARGET := bluetooth.o + +obj-$(CONFIG_BLUEZ_HCIUSB) += hci_usb.o +obj-$(CONFIG_BLUEZ_HCIUART) += hci_uart.o +obj-$(CONFIG_BLUEZ_HCIEMU) += hci_emu.o + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.5/linux/drivers/bluetooth/hci_emu.c linux/drivers/bluetooth/hci_emu.c --- v2.4.5/linux/drivers/bluetooth/hci_emu.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/bluetooth/hci_emu.c Mon Jun 11 19:15:27 2001 @@ -0,0 +1,335 @@ +/* + BlueZ - Bluetooth protocol stack for Linux + Copyright (C) 2000-2001 Qualcomm Incorporated + + Written 2000,2001 by Maxim Krasnyansky + + 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; + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY + CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, + COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS + SOFTWARE IS DISCLAIMED. +*/ + +/* + * BlueZ HCI virtual device driver. + * + * $Id: hci_emu.c,v 1.1 2001/06/01 08:12:10 davem Exp $ + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +/* HCI device part */ + +int hci_emu_open(struct hci_dev *hdev) +{ + hdev->flags |= HCI_RUNNING; + return 0; +} + +int hci_emu_flush(struct hci_dev *hdev) +{ + struct hci_emu_struct *hci_emu = (struct hci_emu_struct *) hdev->driver_data; + bluez_skb_queue_purge(&hci_emu->readq); + return 0; +} + +int hci_emu_close(struct hci_dev *hdev) +{ + hdev->flags &= ~HCI_RUNNING; + hci_emu_flush(hdev); + return 0; +} + +int hci_emu_send_frame(struct sk_buff *skb) +{ + struct hci_dev* hdev = (struct hci_dev *) skb->dev; + struct hci_emu_struct *hci_emu; + + if (!hdev) { + ERR("Frame for uknown device (hdev=NULL)"); + return -ENODEV; + } + + if (!(hdev->flags & HCI_RUNNING)) + return -EBUSY; + + hci_emu = (struct hci_emu_struct *) hdev->driver_data; + + memcpy(skb_push(skb, 1), &skb->pkt_type, 1); + skb_queue_tail(&hci_emu->readq, skb); + + if (hci_emu->flags & HCI_EMU_FASYNC) + kill_fasync(&hci_emu->fasync, SIGIO, POLL_IN); + wake_up_interruptible(&hci_emu->read_wait); + + return 0; +} + +/* Character device part */ + +/* Poll */ +static unsigned int hci_emu_chr_poll(struct file *file, poll_table * wait) +{ + struct hci_emu_struct *hci_emu = (struct hci_emu_struct *) file->private_data; + + poll_wait(file, &hci_emu->read_wait, wait); + + if (skb_queue_len(&hci_emu->readq)) + return POLLIN | POLLRDNORM; + + return POLLOUT | POLLWRNORM; +} + +/* Get packet from user space buffer(already verified) */ +static __inline__ ssize_t hci_emu_get_user(struct hci_emu_struct *hci_emu, const char *buf, size_t count) +{ + struct sk_buff *skb; + + if (count > HCI_EMU_MAX_FRAME) + return -EINVAL; + + if (!(skb = bluez_skb_alloc(count, GFP_KERNEL))) + return -ENOMEM; + + copy_from_user(skb_put(skb, count), buf, count); + + skb->dev = (void *) &hci_emu->hdev; + skb->pkt_type = *((__u8 *) skb->data); + skb_pull(skb, 1); + + hci_recv_frame(skb); + + return count; +} + +/* Write */ +static ssize_t hci_emu_chr_write(struct file * file, const char * buf, + size_t count, loff_t *pos) +{ + struct hci_emu_struct *hci_emu = (struct hci_emu_struct *) file->private_data; + + if (verify_area(VERIFY_READ, buf, count)) + return -EFAULT; + + return hci_emu_get_user(hci_emu, buf, count); +} + +/* Put packet to user space buffer(already verified) */ +static __inline__ ssize_t hci_emu_put_user(struct hci_emu_struct *hci_emu, + struct sk_buff *skb, char *buf, int count) +{ + int len = count, total = 0; + char *ptr = buf; + + len = MIN(skb->len, len); + copy_to_user(ptr, skb->data, len); + total += len; + + hci_emu->hdev.stat.byte_tx += len; + switch (skb->pkt_type) { + case HCI_COMMAND_PKT: + hci_emu->hdev.stat.cmd_tx++; + break; + + case HCI_ACLDATA_PKT: + hci_emu->hdev.stat.acl_tx++; + break; + + case HCI_SCODATA_PKT: + hci_emu->hdev.stat.cmd_tx++; + break; + }; + + return total; +} + +/* Read */ +static ssize_t hci_emu_chr_read(struct file * file, char * buf, size_t count, loff_t *pos) +{ + struct hci_emu_struct *hci_emu = (struct hci_emu_struct *) file->private_data; + DECLARE_WAITQUEUE(wait, current); + struct sk_buff *skb; + ssize_t ret = 0; + + add_wait_queue(&hci_emu->read_wait, &wait); + while (count) { + current->state = TASK_INTERRUPTIBLE; + + /* Read frames from device queue */ + if (!(skb = skb_dequeue(&hci_emu->readq))) { + if (file->f_flags & O_NONBLOCK) { + ret = -EAGAIN; + break; + } + if (signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + + /* Nothing to read, let's sleep */ + schedule(); + continue; + } + + if (!verify_area(VERIFY_WRITE, buf, count)) + ret = hci_emu_put_user(hci_emu, skb, buf, count); + else + ret = -EFAULT; + + bluez_skb_free(skb); + break; + } + + current->state = TASK_RUNNING; + remove_wait_queue(&hci_emu->read_wait, &wait); + + return ret; +} + +static loff_t hci_emu_chr_lseek(struct file * file, loff_t offset, int origin) +{ + return -ESPIPE; +} + +static int hci_emu_chr_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + return -EINVAL; +} + +static int hci_emu_chr_fasync(int fd, struct file *file, int on) +{ + struct hci_emu_struct *hci_emu = (struct hci_emu_struct *) file->private_data; + int ret; + + if ((ret = fasync_helper(fd, file, on, &hci_emu->fasync)) < 0) + return ret; + + if (on) + hci_emu->flags |= HCI_EMU_FASYNC; + else + hci_emu->flags &= ~HCI_EMU_FASYNC; + + return 0; +} + +static int hci_emu_chr_open(struct inode *inode, struct file * file) +{ + struct hci_emu_struct *hci_emu = NULL; + struct hci_dev *hdev; + + if (!(hci_emu = kmalloc(sizeof(struct hci_emu_struct), GFP_KERNEL))) + return -ENOMEM; + + memset(hci_emu, 0, sizeof(struct hci_emu_struct)); + + skb_queue_head_init(&hci_emu->readq); + init_waitqueue_head(&hci_emu->read_wait); + + /* Initialize and register HCI device */ + hdev = &hci_emu->hdev; + + hdev->type = HCI_EMU; + hdev->driver_data = hci_emu; + + hdev->open = hci_emu_open; + hdev->close = hci_emu_close; + hdev->flush = hci_emu_flush; + hdev->send = hci_emu_send_frame; + + if (hci_register_dev(hdev) < 0) { + kfree(hci_emu); + return -EBUSY; + } + + file->private_data = hci_emu; + return 0; +} + +static int hci_emu_chr_close(struct inode *inode, struct file *file) +{ + struct hci_emu_struct *hci_emu = (struct hci_emu_struct *) file->private_data; + + if (hci_unregister_dev(&hci_emu->hdev) < 0) { + ERR("Can't unregister HCI device %s", hci_emu->hdev.name); + } + + kfree(hci_emu); + file->private_data = NULL; + + return 0; +} + +static struct file_operations hci_emu_fops = { + owner: THIS_MODULE, + llseek: hci_emu_chr_lseek, + read: hci_emu_chr_read, + write: hci_emu_chr_write, + poll: hci_emu_chr_poll, + ioctl: hci_emu_chr_ioctl, + open: hci_emu_chr_open, + release:hci_emu_chr_close, + fasync: hci_emu_chr_fasync +}; + +static struct miscdevice hci_emu_miscdev= +{ + HCI_EMU_MINOR, + "hci_emu", + &hci_emu_fops +}; + +int __init hci_emu_init(void) +{ + INF("BlueZ HCI EMU driver ver %s Copyright (C) 2000,2001 Qualcomm Inc", + BLUEZ_VER); + INF("Written 2000,2001 by Maxim Krasnyansky "); + + if (misc_register(&hci_emu_miscdev)) { + ERR("Can't register misc device %d\n", HCI_EMU_MINOR); + return -EIO; + } + + return 0; +} + +void hci_emu_cleanup(void) +{ + misc_deregister(&hci_emu_miscdev); +} + +module_init(hci_emu_init); +module_exit(hci_emu_cleanup); diff -u --recursive --new-file v2.4.5/linux/drivers/bluetooth/hci_uart.c linux/drivers/bluetooth/hci_uart.c --- v2.4.5/linux/drivers/bluetooth/hci_uart.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/bluetooth/hci_uart.c Mon Jun 11 19:15:27 2001 @@ -0,0 +1,575 @@ +/* + BlueZ - Bluetooth protocol stack for Linux + Copyright (C) 2000-2001 Qualcomm Incorporated + + Written 2000,2001 by Maxim Krasnyansky + + 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; + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY + CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, + COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS + SOFTWARE IS DISCLAIMED. +*/ + +/* + * BlueZ HCI UART driver. + * + * $Id: hci_uart.c,v 1.1 2001/06/01 08:12:10 davem Exp $ + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifndef HCI_UART_DEBUG +#undef DBG +#define DBG( A... ) +#undef DMP +#define DMP( A... ) +#endif + +/* ------- Interface to HCI layer ------ */ +/* Initialize device */ +int n_hci_open(struct hci_dev *hdev) +{ + DBG("%s %p", hdev->name, hdev); + + /* Nothing to do for UART driver */ + + hdev->flags |= HCI_RUNNING; + + return 0; +} + +/* Reset device */ +int n_hci_flush(struct hci_dev *hdev) +{ + struct n_hci *n_hci = (struct n_hci *) hdev->driver_data; + struct tty_struct *tty = n_hci->tty; + + DBG("hdev %p tty %p", hdev, tty); + + /* Drop TX queue */ + bluez_skb_queue_purge(&n_hci->txq); + + /* Flush any pending characters in the driver and discipline. */ + if (tty->ldisc.flush_buffer) + tty->ldisc.flush_buffer(tty); + + if (tty->driver.flush_buffer) + tty->driver.flush_buffer(tty); + + return 0; +} + +/* Close device */ +int n_hci_close(struct hci_dev *hdev) +{ + DBG("hdev %p", hdev); + + hdev->flags &= ~HCI_RUNNING; + + n_hci_flush(hdev); + + return 0; +} + +int n_hci_tx_wakeup(struct n_hci *n_hci) +{ + register struct tty_struct *tty = n_hci->tty; + + if (test_and_set_bit(TRANS_SENDING, &n_hci->tx_state)) { + set_bit(TRANS_WAKEUP, &n_hci->tx_state); + return 0; + } + + DBG(""); + do { + register struct sk_buff *skb; + register int len; + + clear_bit(TRANS_WAKEUP, &n_hci->tx_state); + + if (!(skb = skb_dequeue(&n_hci->txq))) + break; + + DMP(skb->data, skb->len); + + /* Send frame to TTY driver */ + tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); + len = tty->driver.write(tty, 0, skb->data, skb->len); + + n_hci->hdev.stat.byte_tx += len; + + DBG("sent %d", len); + + if (len == skb->len) { + /* Full frame was sent */ + bluez_skb_free(skb); + } else { + /* Subtract sent part and requeue */ + skb_pull(skb, len); + skb_queue_head(&n_hci->txq, skb); + } + } while (test_bit(TRANS_WAKEUP, &n_hci->tx_state)); + clear_bit(TRANS_SENDING, &n_hci->tx_state); + + return 0; +} + +/* Send frames from HCI layer */ +int n_hci_send_frame(struct sk_buff *skb) +{ + struct hci_dev* hdev = (struct hci_dev *) skb->dev; + struct tty_struct *tty; + struct n_hci *n_hci; + + if (!hdev) { + ERR("Frame for uknown device (hdev=NULL)"); + return -ENODEV; + } + + if (!(hdev->flags & HCI_RUNNING)) + return -EBUSY; + + n_hci = (struct n_hci *) hdev->driver_data; + tty = n_hci2tty(n_hci); + + DBG("%s: type %d len %d", hdev->name, skb->pkt_type, skb->len); + + switch (skb->pkt_type) { + case HCI_COMMAND_PKT: + hdev->stat.cmd_tx++; + break; + + case HCI_ACLDATA_PKT: + hdev->stat.acl_tx++; + break; + + case HCI_SCODATA_PKT: + hdev->stat.cmd_tx++; + break; + }; + + /* Prepend skb with frame type and queue */ + memcpy(skb_push(skb, 1), &skb->pkt_type, 1); + skb_queue_tail(&n_hci->txq, skb); + + n_hci_tx_wakeup(n_hci); + + return 0; +} + +/* ------ LDISC part ------ */ + +/* n_hci_tty_open + * + * Called when line discipline changed to N_HCI. + * + * Arguments: + * tty pointer to tty info structure + * Return Value: + * 0 if success, otherwise error code + */ +static int n_hci_tty_open(struct tty_struct *tty) +{ + struct n_hci *n_hci = tty2n_hci(tty); + struct hci_dev *hdev; + + DBG("tty %p", tty); + + if (n_hci) + return -EEXIST; + + if (!(n_hci = kmalloc(sizeof(struct n_hci), GFP_KERNEL))) { + ERR("Can't allocate controll structure"); + return -ENFILE; + } + memset(n_hci, 0, sizeof(struct n_hci)); + + /* Initialize and register HCI device */ + hdev = &n_hci->hdev; + + hdev->type = HCI_UART; + hdev->driver_data = n_hci; + + hdev->open = n_hci_open; + hdev->close = n_hci_close; + hdev->flush = n_hci_flush; + hdev->send = n_hci_send_frame; + + if (hci_register_dev(hdev) < 0) { + ERR("Can't register HCI device %s", hdev->name); + kfree(n_hci); + return -ENODEV; + } + + tty->disc_data = n_hci; + n_hci->tty = tty; + + spin_lock_init(&n_hci->rx_lock); + n_hci->rx_state = WAIT_PACKET_TYPE; + + skb_queue_head_init(&n_hci->txq); + + MOD_INC_USE_COUNT; + + /* Flush any pending characters in the driver and discipline. */ + if (tty->ldisc.flush_buffer) + tty->ldisc.flush_buffer(tty); + + if (tty->driver.flush_buffer) + tty->driver.flush_buffer(tty); + + return 0; +} + +/* n_hci_tty_close() + * + * Called when the line discipline is changed to something + * else, the tty is closed, or the tty detects a hangup. + */ +static void n_hci_tty_close(struct tty_struct *tty) +{ + struct n_hci *n_hci = tty2n_hci(tty); + struct hci_dev *hdev = &n_hci->hdev; + + DBG("tty %p hdev %p", tty, hdev); + + if (n_hci != NULL) { + n_hci_close(hdev); + + if (hci_unregister_dev(hdev) < 0) { + ERR("Can't unregister HCI device %s",hdev->name); + } + + hdev->driver_data = NULL; + tty->disc_data = NULL; + kfree(n_hci); + + MOD_DEC_USE_COUNT; + } +} + +/* n_hci_tty_wakeup() + * + * Callback for transmit wakeup. Called when low level + * device driver can accept more send data. + * + * Arguments: tty pointer to associated tty instance data + * Return Value: None + */ +static void n_hci_tty_wakeup( struct tty_struct *tty ) +{ + struct n_hci *n_hci = tty2n_hci(tty); + + DBG(""); + + if (!n_hci) + return; + + tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); + + if (tty != n_hci->tty) + return; + + n_hci_tx_wakeup(n_hci); +} + +/* n_hci_tty_room() + * + * Callback function from tty driver. Return the amount of + * space left in the receiver's buffer to decide if remote + * transmitter is to be throttled. + * + * Arguments: tty pointer to associated tty instance data + * Return Value: number of bytes left in receive buffer + */ +static int n_hci_tty_room (struct tty_struct *tty) +{ + return 65536; +} + +static inline int n_hci_check_data_len(struct n_hci *n_hci, int len) +{ + register int room = skb_tailroom(n_hci->rx_skb); + + DBG("len %d room %d", len, room); + if (!len) { + DMP(n_hci->rx_skb->data, n_hci->rx_skb->len); + hci_recv_frame(n_hci->rx_skb); + } else if (len > room) { + ERR("Data length is to large"); + bluez_skb_free(n_hci->rx_skb); + n_hci->hdev.stat.err_rx++; + } else { + n_hci->rx_state = WAIT_DATA; + n_hci->rx_count = len; + return len; + } + + n_hci->rx_state = WAIT_PACKET_TYPE; + n_hci->rx_skb = NULL; + n_hci->rx_count = 0; + return 0; +} + +static inline void n_hci_rx(struct n_hci *n_hci, const __u8 * data, char *flags, int count) +{ + register const char *ptr; + hci_event_hdr *eh; + hci_acl_hdr *ah; + hci_sco_hdr *sh; + register int len, type, dlen; + + DBG("count %d state %d rx_count %d", count, n_hci->rx_state, n_hci->rx_count); + + n_hci->hdev.stat.byte_rx += count; + + ptr = data; + while (count) { + if (n_hci->rx_count) { + len = MIN(n_hci->rx_count, count); + memcpy(skb_put(n_hci->rx_skb, len), ptr, len); + n_hci->rx_count -= len; count -= len; ptr += len; + + if (n_hci->rx_count) + continue; + + switch (n_hci->rx_state) { + case WAIT_DATA: + DBG("Complete data"); + + DMP(n_hci->rx_skb->data, n_hci->rx_skb->len); + + hci_recv_frame(n_hci->rx_skb); + + n_hci->rx_state = WAIT_PACKET_TYPE; + n_hci->rx_skb = NULL; + continue; + + case WAIT_EVENT_HDR: + eh = (hci_event_hdr *) n_hci->rx_skb->data; + + DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen); + + n_hci_check_data_len(n_hci, eh->plen); + continue; + + case WAIT_ACL_HDR: + ah = (hci_acl_hdr *) n_hci->rx_skb->data; + dlen = __le16_to_cpu(ah->dlen); + + DBG("ACL header: dlen %d", dlen); + + n_hci_check_data_len(n_hci, dlen); + continue; + + case WAIT_SCO_HDR: + sh = (hci_sco_hdr *) n_hci->rx_skb->data; + + DBG("SCO header: dlen %d", sh->dlen); + + n_hci_check_data_len(n_hci, sh->dlen); + continue; + }; + } + + /* WAIT_PACKET_TYPE */ + switch (*ptr) { + case HCI_EVENT_PKT: + DBG("Event packet"); + n_hci->rx_state = WAIT_EVENT_HDR; + n_hci->rx_count = HCI_EVENT_HDR_SIZE; + type = HCI_EVENT_PKT; + break; + + case HCI_ACLDATA_PKT: + DBG("ACL packet"); + n_hci->rx_state = WAIT_ACL_HDR; + n_hci->rx_count = HCI_ACL_HDR_SIZE; + type = HCI_ACLDATA_PKT; + break; + + case HCI_SCODATA_PKT: + DBG("SCO packet"); + n_hci->rx_state = WAIT_SCO_HDR; + n_hci->rx_count = HCI_SCO_HDR_SIZE; + type = HCI_SCODATA_PKT; + break; + + default: + ERR("Unknown HCI packet type %2.2x", (__u8)*ptr); + n_hci->hdev.stat.err_rx++; + ptr++; count--; + continue; + }; + ptr++; count--; + + /* Allocate packet */ + if (!(n_hci->rx_skb = bluez_skb_alloc(HCI_MAX_READ, GFP_ATOMIC))) { + ERR("Can't allocate mem for new packet"); + + n_hci->rx_state = WAIT_PACKET_TYPE; + n_hci->rx_count = 0; + return; + } + n_hci->rx_skb->dev = (void *) &n_hci->hdev; + n_hci->rx_skb->pkt_type = type; + } +} + +/* n_hci_tty_receive() + * + * Called by tty low level driver when receive data is + * available. + * + * Arguments: tty pointer to tty isntance data + * data pointer to received data + * flags pointer to flags for data + * count count of received data in bytes + * + * Return Value: None + */ +static void n_hci_tty_receive(struct tty_struct *tty, const __u8 * data, char *flags, int count) +{ + struct n_hci *n_hci = tty2n_hci(tty); + + if (!n_hci || tty != n_hci->tty) + return; + + spin_lock(&n_hci->rx_lock); + n_hci_rx(n_hci, data, flags, count); + spin_unlock(&n_hci->rx_lock); + + if (test_and_clear_bit(TTY_THROTTLED,&tty->flags) && tty->driver.unthrottle) + tty->driver.unthrottle(tty); +} + +/* n_hci_tty_ioctl() + * + * Process IOCTL system call for the tty device. + * + * Arguments: + * + * tty pointer to tty instance data + * file pointer to open file object for device + * cmd IOCTL command code + * arg argument for IOCTL call (cmd dependent) + * + * Return Value: Command dependent + */ +static int n_hci_tty_ioctl (struct tty_struct *tty, struct file * file, + unsigned int cmd, unsigned long arg) +{ + struct n_hci *n_hci = tty2n_hci(tty); + int error = 0; + + DBG(""); + + /* Verify the status of the device */ + if (!n_hci) + return -EBADF; + + switch (cmd) { + default: + error = n_tty_ioctl(tty, file, cmd, arg); + break; + }; + + return error; +} + +/* + * We don't provide read/write/poll interface for user space. + */ +static ssize_t n_hci_tty_read(struct tty_struct *tty, struct file *file, unsigned char *buf, size_t nr) +{ + return 0; +} +static ssize_t n_hci_tty_write(struct tty_struct *tty, struct file *file, const unsigned char *data, size_t count) +{ + return 0; +} +static unsigned int n_hci_tty_poll(struct tty_struct *tty, struct file *filp, poll_table *wait) +{ + return 0; +} + +int __init n_hci_init(void) +{ + static struct tty_ldisc n_hci_ldisc; + int err; + + INF("BlueZ HCI UART driver ver %s Copyright (C) 2000,2001 Qualcomm Inc", + BLUEZ_VER); + INF("Written 2000,2001 by Maxim Krasnyansky "); + + /* Register the tty discipline */ + + memset(&n_hci_ldisc, 0, sizeof (n_hci_ldisc)); + n_hci_ldisc.magic = TTY_LDISC_MAGIC; + n_hci_ldisc.name = "n_hci"; + n_hci_ldisc.open = n_hci_tty_open; + n_hci_ldisc.close = n_hci_tty_close; + n_hci_ldisc.read = n_hci_tty_read; + n_hci_ldisc.write = n_hci_tty_write; + n_hci_ldisc.ioctl = n_hci_tty_ioctl; + n_hci_ldisc.poll = n_hci_tty_poll; + n_hci_ldisc.receive_room= n_hci_tty_room; + n_hci_ldisc.receive_buf = n_hci_tty_receive; + n_hci_ldisc.write_wakeup= n_hci_tty_wakeup; + + if ((err = tty_register_ldisc(N_HCI, &n_hci_ldisc))) { + ERR("Can't register HCI line discipline (%d)", err); + return err; + } + + return 0; +} + +void n_hci_cleanup(void) +{ + int err; + + /* Release tty registration of line discipline */ + if ((err = tty_register_ldisc(N_HCI, NULL))) + ERR("Can't unregister HCI line discipline (%d)", err); +} + +module_init(n_hci_init); +module_exit(n_hci_cleanup); diff -u --recursive --new-file v2.4.5/linux/drivers/bluetooth/hci_usb.c linux/drivers/bluetooth/hci_usb.c --- v2.4.5/linux/drivers/bluetooth/hci_usb.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/bluetooth/hci_usb.c Mon Jun 11 19:15:27 2001 @@ -0,0 +1,670 @@ +/* + BlueZ - Bluetooth protocol stack for Linux + Copyright (C) 2000-2001 Qualcomm Incorporated + + Written 2000,2001 by Maxim Krasnyansky + + 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; + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY + CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, + COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS + SOFTWARE IS DISCLAIMED. +*/ + +/* + * BlueZ HCI USB driver. + * Based on original USB Bluetooth driver for Linux kernel + * Copyright (c) 2000 Greg Kroah-Hartman + * Copyright (c) 2000 Mark Douglas Corner + * + * $Id: hci_usb.c,v 1.1 2001/06/01 08:12:10 davem Exp $ + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#ifndef HCI_USB_DEBUG +#undef DBG +#define DBG( A... ) +#undef DMP +#define DMP( A... ) +#endif + +static struct usb_device_id usb_bluetooth_ids [] = { + { USB_DEVICE_INFO(HCI_DEV_CLASS, HCI_DEV_SUBCLASS, HCI_DEV_PROTOCOL) }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, usb_bluetooth_ids); + +static int hci_usb_ctrl_msg(struct hci_usb *husb, struct sk_buff *skb); +static int hci_usb_write_msg(struct hci_usb *husb, struct sk_buff *skb); + +static void hci_usb_unlink_urbs(struct hci_usb *husb) +{ + usb_unlink_urb(husb->read_urb); + usb_unlink_urb(husb->intr_urb); + usb_unlink_urb(husb->ctrl_urb); + usb_unlink_urb(husb->write_urb); +} + +static void hci_usb_free_bufs(struct hci_usb *husb) +{ + if (husb->read_urb) { + if (husb->read_urb->transfer_buffer) + kfree(husb->read_urb->transfer_buffer); + usb_free_urb(husb->read_urb); + } + + if (husb->intr_urb) { + if (husb->intr_urb->transfer_buffer) + kfree(husb->intr_urb->transfer_buffer); + usb_free_urb(husb->intr_urb); + } + + if (husb->ctrl_urb) + usb_free_urb(husb->ctrl_urb); + + if (husb->write_urb) + usb_free_urb(husb->write_urb); + + if (husb->intr_skb) + bluez_skb_free(husb->intr_skb); +} + +/* ------- Interface to HCI layer ------ */ +/* Initialize device */ +int hci_usb_open(struct hci_dev *hdev) +{ + struct hci_usb *husb = (struct hci_usb *) hdev->driver_data; + int status; + + DBG("%s", hdev->name); + + husb->read_urb->dev = husb->udev; + if ((status = usb_submit_urb(husb->read_urb))) + DBG("read submit failed. %d", status); + + husb->intr_urb->dev = husb->udev; + if ((status = usb_submit_urb(husb->intr_urb))) + DBG("interrupt submit failed. %d", status); + + hdev->flags |= HCI_RUNNING; + + return 0; +} + +/* Reset device */ +int hci_usb_flush(struct hci_dev *hdev) +{ + struct hci_usb *husb = (struct hci_usb *) hdev->driver_data; + + DBG("%s", hdev->name); + + /* Drop TX queues */ + bluez_skb_queue_purge(&husb->tx_ctrl_q); + bluez_skb_queue_purge(&husb->tx_write_q); + + return 0; +} + +/* Close device */ +int hci_usb_close(struct hci_dev *hdev) +{ + struct hci_usb *husb = (struct hci_usb *) hdev->driver_data; + + DBG("%s", hdev->name); + + hdev->flags &= ~HCI_RUNNING; + hci_usb_unlink_urbs(husb); + + hci_usb_flush(hdev); + + return 0; +} + +void hci_usb_ctrl_wakeup(struct hci_usb *husb) +{ + struct sk_buff *skb; + + if (test_and_set_bit(HCI_TX_CTRL, &husb->tx_state)) + return; + + DBG("%s", husb->hdev.name); + + if (!(skb = skb_dequeue(&husb->tx_ctrl_q))) + goto done; + + if (hci_usb_ctrl_msg(husb, skb)){ + bluez_skb_free(skb); + goto done; + } + + DMP(skb->data, skb->len); + + husb->hdev.stat.byte_tx += skb->len; + return; + +done: + clear_bit(HCI_TX_CTRL, &husb->tx_state); + return; +} + +void hci_usb_write_wakeup(struct hci_usb *husb) +{ + struct sk_buff *skb; + + if (test_and_set_bit(HCI_TX_WRITE, &husb->tx_state)) + return; + + DBG("%s", husb->hdev.name); + + if (!(skb = skb_dequeue(&husb->tx_write_q))) + goto done; + + if (hci_usb_write_msg(husb, skb)) { + skb_queue_head(&husb->tx_write_q, skb); + goto done; + } + + DMP(skb->data, skb->len); + + husb->hdev.stat.byte_tx += skb->len; + return; + +done: + clear_bit(HCI_TX_WRITE, &husb->tx_state); + return; +} + +/* Send frames from HCI layer */ +int hci_usb_send_frame(struct sk_buff *skb) +{ + struct hci_dev *hdev = (struct hci_dev *) skb->dev; + struct hci_usb *husb; + + if (!hdev) { + ERR("frame for uknown device (hdev=NULL)"); + return -ENODEV; + } + + if (!(hdev->flags & HCI_RUNNING)) + return 0; + + husb = (struct hci_usb *) hdev->driver_data; + + DBG("%s type %d len %d", hdev->name, skb->pkt_type, skb->len); + + switch (skb->pkt_type) { + case HCI_COMMAND_PKT: + skb_queue_tail(&husb->tx_ctrl_q, skb); + hci_usb_ctrl_wakeup(husb); + hdev->stat.cmd_tx++; + return 0; + + case HCI_ACLDATA_PKT: + skb_queue_tail(&husb->tx_write_q, skb); + hci_usb_write_wakeup(husb); + hdev->stat.acl_tx++; + return 0; + + case HCI_SCODATA_PKT: + return -EOPNOTSUPP; + }; + + return 0; +} + +/* ---------- USB ------------- */ + +static void hci_usb_ctrl(struct urb *urb) +{ + struct sk_buff *skb = (struct sk_buff *) urb->context; + struct hci_dev *hdev; + struct hci_usb *husb; + + if (!skb) + return; + hdev = (struct hci_dev *) skb->dev; + husb = (struct hci_usb *) hdev->driver_data; + + DBG("%s", hdev->name); + + if (urb->status) + DBG("%s ctrl status: %d", hdev->name, urb->status); + + clear_bit(HCI_TX_CTRL, &husb->tx_state); + bluez_skb_free(skb); + + /* Wake up device */ + hci_usb_ctrl_wakeup(husb); +} + +static void hci_usb_bulk_write(struct urb *urb) +{ + struct sk_buff *skb = (struct sk_buff *) urb->context; + struct hci_dev *hdev; + struct hci_usb *husb; + + if (!skb) + return; + hdev = (struct hci_dev *) skb->dev; + husb = (struct hci_usb *) hdev->driver_data; + + DBG("%s", hdev->name); + + if (urb->status) + DBG("%s bulk write status: %d", hdev->name, urb->status); + + clear_bit(HCI_TX_WRITE, &husb->tx_state); + bluez_skb_free(skb); + + /* Wake up device */ + hci_usb_write_wakeup(husb); + + return; +} + +static void hci_usb_intr(struct urb *urb) +{ + struct hci_usb *husb = (struct hci_usb *) urb->context; + unsigned char *data = urb->transfer_buffer; + register int count = urb->actual_length; + register struct sk_buff *skb = husb->intr_skb; + hci_event_hdr *eh; + register int len; + + if (!husb) + return; + + DBG("%s count %d", husb->hdev.name, count); + + if (urb->status || !count) { + DBG("%s intr status %d, count %d", husb->hdev.name, urb->status, count); + return; + } + + /* Do we really have to handle continuations here ? */ + if (!skb) { + /* New frame */ + if (count < HCI_EVENT_HDR_SIZE) { + DBG("%s bad frame len %d", husb->hdev.name, count); + return; + } + + eh = (hci_event_hdr *) data; + len = eh->plen + HCI_EVENT_HDR_SIZE; + + if (count > len) { + DBG("%s corrupted frame, len %d", husb->hdev.name, count); + return; + } + + /* Allocate skb */ + if (!(skb = bluez_skb_alloc(len, GFP_ATOMIC))) { + ERR("Can't allocate mem for new packet"); + return; + } + skb->dev = (void *) &husb->hdev; + skb->pkt_type = HCI_EVENT_PKT; + + husb->intr_skb = skb; + husb->intr_count = len; + } else { + /* Continuation */ + if (count > husb->intr_count) { + ERR("%s bad frame len %d (expected %d)", husb->hdev.name, count, husb->intr_count); + + bluez_skb_free(skb); + husb->intr_skb = NULL; + husb->intr_count = 0; + return; + } + } + + memcpy(skb_put(skb, count), data, count); + husb->intr_count -= count; + + DMP(data, count); + + if (!husb->intr_count) { + /* Got complete frame */ + + husb->hdev.stat.byte_rx += skb->len; + hci_recv_frame(skb); + + husb->intr_skb = NULL; + } +} + +static void hci_usb_bulk_read(struct urb *urb) +{ + struct hci_usb *husb = (struct hci_usb *) urb->context; + unsigned char *data = urb->transfer_buffer; + int count = urb->actual_length, status; + struct sk_buff *skb; + hci_acl_hdr *ah; + register __u16 dlen; + + if (!husb) + return; + + DBG("%s status %d, count %d, flags %x", husb->hdev.name, urb->status, count, urb->transfer_flags); + + if (urb->status) { + /* Do not re-submit URB on critical errors */ + switch (urb->status) { + case -ENOENT: + return; + default: + goto resubmit; + }; + } + if (!count) + goto resubmit; + + DMP(data, count); + + ah = (hci_acl_hdr *) data; + dlen = le16_to_cpu(ah->dlen); + + /* Verify frame len and completeness */ + if ((count - HCI_ACL_HDR_SIZE) != dlen) { + ERR("%s corrupted ACL packet: count %d, plen %d", husb->hdev.name, count, dlen); + goto resubmit; + } + + /* Allocate packet */ + if (!(skb = bluez_skb_alloc(count, GFP_ATOMIC))) { + ERR("Can't allocate mem for new packet"); + goto resubmit; + } + + memcpy(skb_put(skb, count), data, count); + skb->dev = (void *) &husb->hdev; + skb->pkt_type = HCI_ACLDATA_PKT; + + husb->hdev.stat.byte_rx += skb->len; + + hci_recv_frame(skb); + +resubmit: + husb->read_urb->dev = husb->udev; + if ((status = usb_submit_urb(husb->read_urb))) + DBG("%s read URB submit failed %d", husb->hdev.name, status); + + DBG("%s read URB re-submited", husb->hdev.name); +} + +static int hci_usb_ctrl_msg(struct hci_usb *husb, struct sk_buff *skb) +{ + struct urb *urb = husb->ctrl_urb; + devrequest *dr = &husb->dev_req; + int pipe, status; + + DBG("%s len %d", husb->hdev.name, skb->len); + + pipe = usb_sndctrlpipe(husb->udev, 0); + + dr->requesttype = HCI_CTRL_REQ; + dr->request = 0; + dr->index = 0; + dr->value = 0; + dr->length = cpu_to_le16(skb->len); + + FILL_CONTROL_URB(urb, husb->udev, pipe, (void*)dr, skb->data, skb->len, + hci_usb_ctrl, skb); + + if ((status = usb_submit_urb(urb))) { + DBG("%s control URB submit failed %d", husb->hdev.name, status); + return status; + } + + return 0; +} + +static int hci_usb_write_msg(struct hci_usb *husb, struct sk_buff *skb) +{ + struct urb *urb = husb->write_urb; + int pipe, status; + + DBG("%s len %d", husb->hdev.name, skb->len); + + pipe = usb_sndbulkpipe(husb->udev, husb->bulk_out_ep_addr); + + FILL_BULK_URB(urb, husb->udev, pipe, skb->data, skb->len, + hci_usb_bulk_write, skb); + urb->transfer_flags |= USB_QUEUE_BULK; + + if ((status = usb_submit_urb(urb))) { + DBG("%s write URB submit failed %d", husb->hdev.name, status); + return status; + } + + return 0; +} + +static void * hci_usb_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id) +{ + struct usb_endpoint_descriptor *bulk_out_ep, *intr_in_ep, *bulk_in_ep; + struct usb_interface_descriptor *uif; + struct usb_endpoint_descriptor *ep; + struct hci_usb *husb; + struct hci_dev *hdev; + int i, size, pipe; + __u8 * buf; + + DBG("udev %p ifnum %d", udev, ifnum); + + /* Check device signature */ + if ((udev->descriptor.bDeviceClass != HCI_DEV_CLASS) || + (udev->descriptor.bDeviceSubClass != HCI_DEV_SUBCLASS)|| + (udev->descriptor.bDeviceProtocol != HCI_DEV_PROTOCOL) ) + return NULL; + + MOD_INC_USE_COUNT; + + uif = &udev->actconfig->interface[ifnum].altsetting[0]; + + if (uif->bNumEndpoints != 3) { + DBG("Wrong number of endpoints %d", uif->bNumEndpoints); + MOD_DEC_USE_COUNT; + return NULL; + } + + bulk_out_ep = intr_in_ep = bulk_in_ep = NULL; + + /* Find endpoints that we need */ + for ( i = 0; i < uif->bNumEndpoints; ++i) { + ep = &uif->endpoint[i]; + + switch (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + case USB_ENDPOINT_XFER_BULK: + if (ep->bEndpointAddress & USB_DIR_IN) + bulk_in_ep = ep; + else + bulk_out_ep = ep; + break; + + case USB_ENDPOINT_XFER_INT: + intr_in_ep = ep; + break; + }; + } + + if (!bulk_in_ep || !bulk_out_ep || !intr_in_ep) { + DBG("Endpoints not found: %p %p %p", bulk_in_ep, bulk_out_ep, intr_in_ep); + MOD_DEC_USE_COUNT; + return NULL; + } + + if (!(husb = kmalloc(sizeof(struct hci_usb), GFP_KERNEL))) { + ERR("Can't allocate: control structure"); + MOD_DEC_USE_COUNT; + return NULL; + } + + memset(husb, 0, sizeof(struct hci_usb)); + + husb->udev = udev; + husb->bulk_out_ep_addr = bulk_out_ep->bEndpointAddress; + + if (!(husb->ctrl_urb = usb_alloc_urb(0))) { + ERR("Can't allocate: control URB"); + goto probe_error; + } + + if (!(husb->write_urb = usb_alloc_urb(0))) { + ERR("Can't allocate: write URB"); + goto probe_error; + } + + if (!(husb->read_urb = usb_alloc_urb(0))) { + ERR("Can't allocate: read URB"); + goto probe_error; + } + + ep = bulk_in_ep; + pipe = usb_rcvbulkpipe(udev, ep->bEndpointAddress); + size = HCI_USB_MAX_READ; + + if (!(buf = kmalloc(size, GFP_KERNEL))) { + ERR("Can't allocate: read buffer"); + goto probe_error; + } + + FILL_BULK_URB(husb->read_urb, udev, pipe, buf, size, hci_usb_bulk_read, husb); + husb->read_urb->transfer_flags |= USB_QUEUE_BULK; + + ep = intr_in_ep; + pipe = usb_rcvintpipe(udev, ep->bEndpointAddress); + size = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); + + if (!(husb->intr_urb = usb_alloc_urb(0))) { + ERR("Can't allocate: interrupt URB"); + goto probe_error; + } + + if (!(buf = kmalloc(size, GFP_KERNEL))) { + ERR("Can't allocate: interrupt buffer"); + goto probe_error; + } + + FILL_INT_URB(husb->intr_urb, udev, pipe, buf, size, hci_usb_intr, husb, ep->bInterval); + + skb_queue_head_init(&husb->tx_ctrl_q); + skb_queue_head_init(&husb->tx_write_q); + + /* Initialize and register HCI device */ + hdev = &husb->hdev; + + hdev->type = HCI_USB; + hdev->driver_data = husb; + + hdev->open = hci_usb_open; + hdev->close = hci_usb_close; + hdev->flush = hci_usb_flush; + hdev->send = hci_usb_send_frame; + + if (hci_register_dev(hdev) < 0) { + ERR("Can't register HCI device %s", hdev->name); + goto probe_error; + } + + return husb; + +probe_error: + hci_usb_free_bufs(husb); + kfree(husb); + MOD_DEC_USE_COUNT; + return NULL; +} + +static void hci_usb_disconnect(struct usb_device *udev, void *ptr) +{ + struct hci_usb *husb = (struct hci_usb *) ptr; + struct hci_dev *hdev = &husb->hdev; + + if (!husb) + return; + + DBG("%s", hdev->name); + + hci_usb_close(hdev); + + if (hci_unregister_dev(hdev) < 0) { + ERR("Can't unregister HCI device %s", hdev->name); + } + + hci_usb_free_bufs(husb); + kfree(husb); + + MOD_DEC_USE_COUNT; +} + +static struct usb_driver hci_usb_driver = +{ + name: "hci_usb", + probe: hci_usb_probe, + disconnect: hci_usb_disconnect, + id_table: usb_bluetooth_ids, +}; + +int hci_usb_init(void) +{ + int err; + + INF("BlueZ HCI USB driver ver %s Copyright (C) 2000,2001 Qualcomm Inc", + BLUEZ_VER); + INF("Written 2000,2001 by Maxim Krasnyansky "); + + if ((err = usb_register(&hci_usb_driver)) < 0) + ERR("Failed to register HCI USB driver"); + + return err; +} + +void hci_usb_cleanup(void) +{ + usb_deregister(&hci_usb_driver); +} + +module_init(hci_usb_init); +module_exit(hci_usb_cleanup); diff -u --recursive --new-file v2.4.5/linux/drivers/cdrom/mcdx.c linux/drivers/cdrom/mcdx.c --- v2.4.5/linux/drivers/cdrom/mcdx.c Fri Feb 9 11:30:22 2001 +++ linux/drivers/cdrom/mcdx.c Wed Jun 27 14:13:01 2001 @@ -80,6 +80,10 @@ #define mcdx_drive_map mcdx #include "mcdx.h" +#if BITS_PER_LONG != 32 +# error FIXME: this driver only works on 32-bit platforms +#endif + #ifndef HZ #error HZ not defined #endif diff -u --recursive --new-file v2.4.5/linux/drivers/char/Config.in linux/drivers/char/Config.in --- v2.4.5/linux/drivers/char/Config.in Tue Mar 6 19:44:34 2001 +++ linux/drivers/char/Config.in Tue Jul 3 14:10:35 2001 @@ -186,6 +186,7 @@ bool ' AMD Irongate support' CONFIG_AGP_AMD bool ' Generic SiS support' CONFIG_AGP_SIS bool ' ALI chipset support' CONFIG_AGP_ALI + bool ' Serverworks LE/HE support' CONFIG_AGP_SWORKS fi source drivers/char/drm/Config.in diff -u --recursive --new-file v2.4.5/linux/drivers/char/agp/agp.h linux/drivers/char/agp/agp.h --- v2.4.5/linux/drivers/char/agp/agp.h Tue Feb 13 14:13:43 2001 +++ linux/drivers/char/agp/agp.h Mon Jul 2 15:27:56 2001 @@ -92,7 +92,7 @@ u32 mode; enum chipset_type type; enum aper_size_type size_type; - u32 *key_list; + unsigned long *key_list; atomic_t current_memory_agp; atomic_t agp_in_use; int max_memory_agp; /* in number of pages */ @@ -123,11 +123,11 @@ #define OUTREG32(mmap, addr, val) __raw_writel((val), (mmap)+(addr)) #define OUTREG16(mmap, addr, val) __raw_writew((val), (mmap)+(addr)) -#define OUTREG8 (mmap, addr, val) __raw_writeb((val), (mmap)+(addr)) +#define OUTREG8(mmap, addr, val) __raw_writeb((val), (mmap)+(addr)) #define INREG32(mmap, addr) __raw_readl((mmap)+(addr)) #define INREG16(mmap, addr) __raw_readw((mmap)+(addr)) -#define INREG8 (mmap, addr) __raw_readb((mmap)+(addr)) +#define INREG8(mmap, addr) __raw_readb((mmap)+(addr)) #define CACHE_FLUSH agp_bridge.cache_flush #define A_SIZE_8(x) ((aper_size_info_8 *) x) @@ -291,5 +291,24 @@ #define ALI_CACHE_FLUSH_CTRL 0xD0 #define ALI_CACHE_FLUSH_ADDR_MASK 0xFFFFF000 #define ALI_CACHE_FLUSH_EN 0x100 + +/* Serverworks Registers */ +#define SVWRKS_APSIZE 0x10 +#define SVWRKS_SIZE_MASK 0xfe000000 + +#define SVWRKS_MMBASE 0x14 +#define SVWRKS_CACHING 0x4b +#define SVWRKS_FEATURE 0x68 + +/* func 1 registers */ +#define SVWRKS_AGP_ENABLE 0x60 +#define SVWRKS_COMMAND 0x04 + +/* Memory mapped registers */ +#define SVWRKS_GART_CACHE 0x02 +#define SVWRKS_GATTBASE 0x04 +#define SVWRKS_TLBFLUSH 0x10 +#define SVWRKS_POSTFLUSH 0x14 +#define SVWRKS_DIRFLUSH 0x0c #endif /* _AGP_BACKEND_PRIV_H */ diff -u --recursive --new-file v2.4.5/linux/drivers/char/agp/agpgart_be.c linux/drivers/char/agp/agpgart_be.c --- v2.4.5/linux/drivers/char/agp/agpgart_be.c Tue Feb 13 14:13:43 2001 +++ linux/drivers/char/agp/agpgart_be.c Mon Jul 2 15:27:56 2001 @@ -67,7 +67,7 @@ { #if defined(__i386__) asm volatile ("wbinvd":::"memory"); -#elif defined(__alpha__) || defined(__ia64__) +#elif defined(__alpha__) || defined(__ia64__) || defined(__sparc__) /* ??? I wonder if we'll really need to flush caches, or if the core logic can manage to keep the system coherent. The ARM speaks only of using `cflush' to get things in memory in @@ -2189,6 +2189,621 @@ #endif /* CONFIG_AGP_ALI */ +#ifdef CONFIG_AGP_SWORKS +typedef struct _serverworks_page_map { + unsigned long *real; + unsigned long *remapped; +} serverworks_page_map; + +static struct _serverworks_private { + struct pci_dev *svrwrks_dev; /* device one */ + volatile u8 *registers; + serverworks_page_map **gatt_pages; + int num_tables; + serverworks_page_map scratch_dir; + + int gart_addr_ofs; + int mm_addr_ofs; +} serverworks_private; + +static int serverworks_create_page_map(serverworks_page_map *page_map) +{ + int i; + + page_map->real = (unsigned long *) __get_free_page(GFP_KERNEL); + if (page_map->real == NULL) { + return -ENOMEM; + } + set_bit(PG_reserved, &virt_to_page(page_map->real)->flags); + CACHE_FLUSH(); + page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real), + PAGE_SIZE); + if (page_map->remapped == NULL) { + clear_bit(PG_reserved, + &virt_to_page(page_map->real)->flags); + free_page((unsigned long) page_map->real); + page_map->real = NULL; + return -ENOMEM; + } + CACHE_FLUSH(); + + for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) { + page_map->remapped[i] = agp_bridge.scratch_page; + } + + return 0; +} + +static void serverworks_free_page_map(serverworks_page_map *page_map) +{ + iounmap(page_map->remapped); + clear_bit(PG_reserved, + &virt_to_page(page_map->real)->flags); + free_page((unsigned long) page_map->real); +} + +static void serverworks_free_gatt_pages(void) +{ + int i; + serverworks_page_map **tables; + serverworks_page_map *entry; + + tables = serverworks_private.gatt_pages; + for(i = 0; i < serverworks_private.num_tables; i++) { + entry = tables[i]; + if (entry != NULL) { + if (entry->real != NULL) { + serverworks_free_page_map(entry); + } + kfree(entry); + } + } + kfree(tables); +} + +static int serverworks_create_gatt_pages(int nr_tables) +{ + serverworks_page_map **tables; + serverworks_page_map *entry; + int retval = 0; + int i; + + tables = kmalloc((nr_tables + 1) * sizeof(serverworks_page_map *), + GFP_KERNEL); + if (tables == NULL) { + return -ENOMEM; + } + memset(tables, 0, sizeof(serverworks_page_map *) * (nr_tables + 1)); + for (i = 0; i < nr_tables; i++) { + entry = kmalloc(sizeof(serverworks_page_map), GFP_KERNEL); + if (entry == NULL) { + retval = -ENOMEM; + break; + } + memset(entry, 0, sizeof(serverworks_page_map)); + tables[i] = entry; + retval = serverworks_create_page_map(entry); + if (retval != 0) break; + } + serverworks_private.num_tables = nr_tables; + serverworks_private.gatt_pages = tables; + + if (retval != 0) serverworks_free_gatt_pages(); + + return retval; +} + +#define SVRWRKS_GET_GATT(addr) (serverworks_private.gatt_pages[\ + GET_PAGE_DIR_IDX(addr)]->remapped) + +#ifndef GET_PAGE_DIR_OFF +#define GET_PAGE_DIR_OFF(addr) (addr >> 22) +#endif + +#ifndef GET_PAGE_DIR_IDX +#define GET_PAGE_DIR_IDX(addr) (GET_PAGE_DIR_OFF(addr) - \ + GET_PAGE_DIR_OFF(agp_bridge.gart_bus_addr)) +#endif + +#ifndef GET_GATT_OFF +#define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12) +#endif + +static int serverworks_create_gatt_table(void) +{ + aper_size_info_lvl2 *value; + serverworks_page_map page_dir; + int retval; + u32 temp; + int i; + + value = A_SIZE_LVL2(agp_bridge.current_size); + retval = serverworks_create_page_map(&page_dir); + if (retval != 0) { + return retval; + } + retval = serverworks_create_page_map(&serverworks_private.scratch_dir); + if (retval != 0) { + serverworks_free_page_map(&page_dir); + return retval; + } + /* Create a fake scratch directory */ + for(i = 0; i < 1024; i++) { + serverworks_private.scratch_dir.remapped[i] = (unsigned long) agp_bridge.scratch_page; + page_dir.remapped[i] = + virt_to_bus(serverworks_private.scratch_dir.real); + page_dir.remapped[i] |= 0x00000001; + } + + retval = serverworks_create_gatt_pages(value->num_entries / 1024); + if (retval != 0) { + serverworks_free_page_map(&page_dir); + return retval; + } + + agp_bridge.gatt_table_real = page_dir.real; + agp_bridge.gatt_table = page_dir.remapped; + agp_bridge.gatt_bus_addr = virt_to_bus(page_dir.real); + + /* Get the address for the gart region. + * This is a bus address even on the alpha, b/c its + * used to program the agp master not the cpu + */ + + pci_read_config_dword(agp_bridge.dev, + serverworks_private.gart_addr_ofs, + &temp); + agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); + + /* Calculate the agp offset */ + + for(i = 0; i < value->num_entries / 1024; i++) { + page_dir.remapped[i] = + virt_to_bus(serverworks_private.gatt_pages[i]->real); + page_dir.remapped[i] |= 0x00000001; + } + + return 0; +} + +static int serverworks_free_gatt_table(void) +{ + serverworks_page_map page_dir; + + page_dir.real = agp_bridge.gatt_table_real; + page_dir.remapped = agp_bridge.gatt_table; + + serverworks_free_gatt_pages(); + serverworks_free_page_map(&page_dir); + return 0; +} + +static int serverworks_fetch_size(void) +{ + int i; + u32 temp; + u32 temp2; + aper_size_info_lvl2 *values; + + values = A_SIZE_LVL2(agp_bridge.aperture_sizes); + pci_read_config_dword(agp_bridge.dev, + serverworks_private.gart_addr_ofs, + &temp); + pci_write_config_dword(agp_bridge.dev, + serverworks_private.gart_addr_ofs, + 0xfe000000); + pci_read_config_dword(agp_bridge.dev, + serverworks_private.gart_addr_ofs, + &temp2); + pci_write_config_dword(agp_bridge.dev, + serverworks_private.gart_addr_ofs, + temp); + temp2 &= SVWRKS_SIZE_MASK; + + for (i = 0; i < agp_bridge.num_aperture_sizes; i++) { + if (temp2 == 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; +} + +static int serverworks_configure(void) +{ + aper_size_info_lvl2 *current_size; + u32 temp; + u8 enable_reg; + u8 cap_ptr; + u32 cap_id; + u16 cap_reg; + + current_size = A_SIZE_LVL2(agp_bridge.current_size); + + /* Get the memory mapped registers */ + pci_read_config_dword(agp_bridge.dev, + serverworks_private.mm_addr_ofs, + &temp); + temp = (temp & PCI_BASE_ADDRESS_MEM_MASK); + serverworks_private.registers = (volatile u8 *) ioremap(temp, 4096); + + OUTREG8(serverworks_private.registers, SVWRKS_GART_CACHE, 0x0a); + + OUTREG32(serverworks_private.registers, SVWRKS_GATTBASE, + agp_bridge.gatt_bus_addr); + + cap_reg = INREG16(serverworks_private.registers, SVWRKS_COMMAND); + cap_reg &= ~0x0007; + cap_reg |= 0x4; + OUTREG16(serverworks_private.registers, SVWRKS_COMMAND, cap_reg); + + pci_read_config_byte(serverworks_private.svrwrks_dev, + SVWRKS_AGP_ENABLE, &enable_reg); + enable_reg |= 0x1; /* Agp Enable bit */ + pci_write_config_byte(serverworks_private.svrwrks_dev, + SVWRKS_AGP_ENABLE, enable_reg); + agp_bridge.tlb_flush(NULL); + + pci_read_config_byte(serverworks_private.svrwrks_dev, 0x34, &cap_ptr); + if (cap_ptr != 0x00) { + do { + pci_read_config_dword(serverworks_private.svrwrks_dev, + cap_ptr, &cap_id); + + if ((cap_id & 0xff) != 0x02) + cap_ptr = (cap_id >> 8) & 0xff; + } + while (((cap_id & 0xff) != 0x02) && (cap_ptr != 0x00)); + } + agp_bridge.capndx = cap_ptr; + + /* Fill in the mode register */ + pci_read_config_dword(serverworks_private.svrwrks_dev, + agp_bridge.capndx + 4, + &agp_bridge.mode); + + pci_read_config_byte(agp_bridge.dev, + SVWRKS_CACHING, + &enable_reg); + enable_reg &= ~0x3; + pci_write_config_byte(agp_bridge.dev, + SVWRKS_CACHING, + enable_reg); + + pci_read_config_byte(agp_bridge.dev, + SVWRKS_FEATURE, + &enable_reg); + enable_reg |= (1<<6); + pci_write_config_byte(agp_bridge.dev, + SVWRKS_FEATURE, + enable_reg); + + return 0; +} + +static void serverworks_cleanup(void) +{ + iounmap((void *) serverworks_private.registers); +} + +/* + * This routine could be implemented by taking the addresses + * written to the GATT, and flushing them individually. However + * currently it just flushes the whole table. Which is probably + * more efficent, since agp_memory blocks can be a large number of + * entries. + */ + +static void serverworks_tlbflush(agp_memory * temp) +{ + unsigned long end; + + OUTREG8(serverworks_private.registers, SVWRKS_POSTFLUSH, 0x01); + end = jiffies + 3*HZ; + while(INREG8(serverworks_private.registers, + SVWRKS_POSTFLUSH) == 0x01) { + if((signed)(end - jiffies) <= 0) { + printk(KERN_ERR "Posted write buffer flush took more" + "then 3 seconds\n"); + } + } + OUTREG32(serverworks_private.registers, SVWRKS_DIRFLUSH, 0x00000001); + end = jiffies + 3*HZ; + while(INREG32(serverworks_private.registers, + SVWRKS_DIRFLUSH) == 0x00000001) { + if((signed)(end - jiffies) <= 0) { + printk(KERN_ERR "TLB flush took more" + "then 3 seconds\n"); + } + } +} + +static unsigned long serverworks_mask_memory(unsigned long addr, int type) +{ + /* Only type 0 is supported by the serverworks chipsets */ + + return addr | agp_bridge.masks[0].mask; +} + +static int serverworks_insert_memory(agp_memory * mem, + off_t pg_start, int type) +{ + int i, j, num_entries; + unsigned long *cur_gatt; + unsigned long addr; + + num_entries = A_SIZE_LVL2(agp_bridge.current_size)->num_entries; + + if (type != 0 || mem->type != 0) { + return -EINVAL; + } + if ((pg_start + mem->page_count) > num_entries) { + return -EINVAL; + } + + j = pg_start; + while (j < (pg_start + mem->page_count)) { + addr = (j * PAGE_SIZE) + agp_bridge.gart_bus_addr; + cur_gatt = SVRWRKS_GET_GATT(addr); + if (!PGE_EMPTY(cur_gatt[GET_GATT_OFF(addr)])) { + return -EBUSY; + } + j++; + } + + if (mem->is_flushed == FALSE) { + CACHE_FLUSH(); + mem->is_flushed = TRUE; + } + + for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { + addr = (j * PAGE_SIZE) + agp_bridge.gart_bus_addr; + cur_gatt = SVRWRKS_GET_GATT(addr); + cur_gatt[GET_GATT_OFF(addr)] = mem->memory[i]; + } + agp_bridge.tlb_flush(mem); + return 0; +} + +static int serverworks_remove_memory(agp_memory * mem, off_t pg_start, + int type) +{ + int i; + unsigned long *cur_gatt; + unsigned long addr; + + if (type != 0 || mem->type != 0) { + return -EINVAL; + } + + CACHE_FLUSH(); + agp_bridge.tlb_flush(mem); + + for (i = pg_start; i < (mem->page_count + pg_start); i++) { + addr = (i * PAGE_SIZE) + agp_bridge.gart_bus_addr; + cur_gatt = SVRWRKS_GET_GATT(addr); + cur_gatt[GET_GATT_OFF(addr)] = + (unsigned long) agp_bridge.scratch_page; + } + + agp_bridge.tlb_flush(mem); + return 0; +} + +static gatt_mask serverworks_masks[] = +{ + {0x00000001, 0} +}; + +static aper_size_info_lvl2 serverworks_sizes[7] = +{ + {2048, 524288, 0x80000000}, + {1024, 262144, 0xc0000000}, + {512, 131072, 0xe0000000}, + {256, 65536, 0xf0000000}, + {128, 32768, 0xf8000000}, + {64, 16384, 0xfc000000}, + {32, 8192, 0xfe000000} +}; + +static void serverworks_agp_enable(u32 mode) +{ + struct pci_dev *device = NULL; + u32 command, scratch, cap_id; + u8 cap_ptr; + + pci_read_config_dword(serverworks_private.svrwrks_dev, + agp_bridge.capndx + 4, + &command); + + /* + * PASS1: go throu all devices that claim to be + * AGP devices and collect their data. + */ + + while ((device = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8, + device)) != NULL) { + pci_read_config_dword(device, 0x04, &scratch); + + if (!(scratch & 0x00100000)) + continue; + + pci_read_config_byte(device, 0x34, &cap_ptr); + + if (cap_ptr != 0x00) { + do { + pci_read_config_dword(device, + cap_ptr, &cap_id); + + if ((cap_id & 0xff) != 0x02) + cap_ptr = (cap_id >> 8) & 0xff; + } + while (((cap_id & 0xff) != 0x02) && (cap_ptr != 0x00)); + } + if (cap_ptr != 0x00) { + /* + * Ok, here we have a AGP device. Disable impossible + * settings, and adjust the readqueue to the minimum. + */ + + pci_read_config_dword(device, cap_ptr + 4, &scratch); + + /* adjust RQ depth */ + command = + ((command & ~0xff000000) | + min((mode & 0xff000000), + min((command & 0xff000000), + (scratch & 0xff000000)))); + + /* disable SBA if it's not supported */ + if (!((command & 0x00000200) && + (scratch & 0x00000200) && + (mode & 0x00000200))) + command &= ~0x00000200; + + /* disable FW */ + command &= ~0x00000010; + + command &= ~0x00000008; + + if (!((command & 4) && + (scratch & 4) && + (mode & 4))) + command &= ~0x00000004; + + if (!((command & 2) && + (scratch & 2) && + (mode & 2))) + command &= ~0x00000002; + + if (!((command & 1) && + (scratch & 1) && + (mode & 1))) + command &= ~0x00000001; + } + } + /* + * PASS2: Figure out the 4X/2X/1X setting and enable the + * target (our motherboard chipset). + */ + + if (command & 4) { + command &= ~3; /* 4X */ + } + if (command & 2) { + command &= ~5; /* 2X */ + } + if (command & 1) { + command &= ~6; /* 1X */ + } + command |= 0x00000100; + + pci_write_config_dword(serverworks_private.svrwrks_dev, + agp_bridge.capndx + 8, + command); + + /* + * PASS3: Go throu all AGP devices and update the + * command registers. + */ + + while ((device = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8, + device)) != NULL) { + pci_read_config_dword(device, 0x04, &scratch); + + if (!(scratch & 0x00100000)) + continue; + + pci_read_config_byte(device, 0x34, &cap_ptr); + + if (cap_ptr != 0x00) { + do { + pci_read_config_dword(device, + cap_ptr, &cap_id); + + if ((cap_id & 0xff) != 0x02) + cap_ptr = (cap_id >> 8) & 0xff; + } + while (((cap_id & 0xff) != 0x02) && (cap_ptr != 0x00)); + } + if (cap_ptr != 0x00) + pci_write_config_dword(device, cap_ptr + 8, command); + } +} + +static int __init serverworks_setup (struct pci_dev *pdev) +{ + u32 temp; + u32 temp2; + + serverworks_private.svrwrks_dev = pdev; + + agp_bridge.masks = serverworks_masks; + agp_bridge.num_of_masks = 1; + agp_bridge.aperture_sizes = (void *) serverworks_sizes; + agp_bridge.size_type = LVL2_APER_SIZE; + agp_bridge.num_aperture_sizes = 7; + agp_bridge.dev_private_data = (void *) &serverworks_private; + agp_bridge.needs_scratch_page = TRUE; + agp_bridge.configure = serverworks_configure; + agp_bridge.fetch_size = serverworks_fetch_size; + agp_bridge.cleanup = serverworks_cleanup; + agp_bridge.tlb_flush = serverworks_tlbflush; + agp_bridge.mask_memory = serverworks_mask_memory; + agp_bridge.agp_enable = serverworks_agp_enable; + agp_bridge.cache_flush = global_cache_flush; + agp_bridge.create_gatt_table = serverworks_create_gatt_table; + agp_bridge.free_gatt_table = serverworks_free_gatt_table; + agp_bridge.insert_memory = serverworks_insert_memory; + agp_bridge.remove_memory = serverworks_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; + + pci_read_config_dword(agp_bridge.dev, + SVWRKS_APSIZE, + &temp); + + serverworks_private.gart_addr_ofs = 0x10; + + if(temp & PCI_BASE_ADDRESS_MEM_TYPE_64) { + pci_read_config_dword(agp_bridge.dev, + SVWRKS_APSIZE + 4, + &temp2); + if(temp2 != 0) { + printk("Detected 64 bit aperture address, but top " + "bits are not zero. Disabling agp\n"); + return -ENODEV; + } + serverworks_private.mm_addr_ofs = 0x18; + } else { + serverworks_private.mm_addr_ofs = 0x14; + } + + pci_read_config_dword(agp_bridge.dev, + serverworks_private.mm_addr_ofs, + &temp); + if(temp & PCI_BASE_ADDRESS_MEM_TYPE_64) { + pci_read_config_dword(agp_bridge.dev, + serverworks_private.mm_addr_ofs + 4, + &temp2); + if(temp2 != 0) { + printk("Detected 64 bit MMIO address, but top " + "bits are not zero. Disabling agp\n"); + return -ENODEV; + } + } + + return 0; +} + +#endif /* CONFIG_AGP_SWORKS */ + /* per-chipset initialization data. * note -- all chipsets for a single vendor MUST be grouped together @@ -2585,6 +3200,41 @@ } } #endif /* CONFIG_AGP_I810 */ + +#ifdef CONFIG_AGP_SWORKS + /* Everything is on func 1 here so we are hardcoding function one */ + if (dev->vendor == PCI_VENDOR_ID_SERVERWORKS) { + struct pci_dev *bridge_dev; + + bridge_dev = pci_find_slot ((unsigned int)dev->bus->number, + PCI_DEVFN(0, 1)); + if(bridge_dev == NULL) { + printk(KERN_INFO PFX "agpgart: Detected a Serverworks " + "Chipset, but could not find the secondary " + "device.\n"); + return -ENODEV; + } + + switch (dev->device) { + case PCI_DEVICE_ID_SERVERWORKS_HE: + agp_bridge.type = SVWRKS_HE; + return serverworks_setup(bridge_dev); + + case PCI_DEVICE_ID_SERVERWORKS_LE: + case 0x0007: + agp_bridge.type = SVWRKS_LE; + return serverworks_setup(bridge_dev); + + default: + if(agp_try_unsupported) { + agp_bridge.type = SVWRKS_GENERIC; + return serverworks_setup(bridge_dev); + } + break; + } + } + +#endif /* CONFIG_AGP_SWORKS */ /* find capndx */ pci_read_config_dword(dev, 0x04, &scratch); diff -u --recursive --new-file v2.4.5/linux/drivers/char/agp/agpgart_fe.c linux/drivers/char/agp/agpgart_fe.c --- v2.4.5/linux/drivers/char/agp/agpgart_fe.c Tue May 15 01:29:34 2001 +++ linux/drivers/char/agp/agpgart_fe.c Wed Jun 27 17:10:55 2001 @@ -875,6 +875,9 @@ } else { agp_segment *segment; + if (reserve.seg_count >= 16384) + return -EINVAL; + segment = kmalloc((sizeof(agp_segment) * reserve.seg_count), GFP_KERNEL); diff -u --recursive --new-file v2.4.5/linux/drivers/char/console.c linux/drivers/char/console.c --- v2.4.5/linux/drivers/char/console.c Fri Feb 9 11:30:22 2001 +++ linux/drivers/char/console.c Tue Jun 12 11:17:17 2001 @@ -103,8 +103,6 @@ #include #include -#include - #include "console_macros.h" @@ -2684,7 +2682,7 @@ void poke_blanked_console(void) { del_timer(&console_timer); /* Can't use _sync here: called from tasklet */ - if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS) + if (!vt_cons[fg_console] || vt_cons[fg_console]->vc_mode == KD_GRAPHICS) return; if (console_blanked) { console_timer.function = unblank_screen_t; diff -u --recursive --new-file v2.4.5/linux/drivers/char/cyclades.c linux/drivers/char/cyclades.c --- v2.4.5/linux/drivers/char/cyclades.c Fri Apr 6 10:42:55 2001 +++ linux/drivers/char/cyclades.c Wed Jun 27 17:10:55 2001 @@ -743,7 +743,7 @@ #define NR_ISA_ADDRS (sizeof(cy_isa_addresses)/sizeof(unsigned char*)) #ifdef MODULE -static int maddr[NR_CARDS] = { 0, }; +static long maddr[NR_CARDS] = { 0, }; static int irq[NR_CARDS] = { 0, }; MODULE_PARM(maddr, "1-" __MODULE_STRING(NR_CARDS) "l"); @@ -2983,10 +2983,11 @@ return 0; } - CY_LOCK(info, flags); if (from_user) { down(&tmp_buf_sem); while (1) { + int c1; + c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, SERIAL_XMIT_SIZE - info->xmit_head)); if (c <= 0) @@ -2999,23 +3000,30 @@ } break; } - c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + CY_LOCK(info, flags); + c1 = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, SERIAL_XMIT_SIZE - info->xmit_head)); + + if (c1 < c) + c = c1; memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); info->xmit_head = ((info->xmit_head + c) & (SERIAL_XMIT_SIZE-1)); info->xmit_cnt += c; + CY_UNLOCK(info, flags); buf += c; count -= c; ret += c; } up(&tmp_buf_sem); } else { + CY_LOCK(info, flags); while (1) { c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, SERIAL_XMIT_SIZE - info->xmit_head)); - if (c <= 0) { + + if (c <= 0) break; - } + memcpy(info->xmit_buf + info->xmit_head, buf, c); info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); info->xmit_cnt += c; @@ -3023,8 +3031,8 @@ count -= c; ret += c; } + CY_UNLOCK(info, flags); } - CY_UNLOCK(info, flags); info->idle_stats.xmit_bytes += ret; info->idle_stats.xmit_idle = jiffies; diff -u --recursive --new-file v2.4.5/linux/drivers/char/drm/agpsupport.c linux/drivers/char/drm/agpsupport.c --- v2.4.5/linux/drivers/char/drm/agpsupport.c Thu Nov 16 14:05:49 2000 +++ linux/drivers/char/drm/agpsupport.c Mon Jul 2 15:27:56 2001 @@ -284,6 +284,17 @@ case AMD_IRONGATE: head->chipset = "AMD Irongate"; break; case ALI_GENERIC: head->chipset = "ALi"; break; case ALI_M1541: head->chipset = "ALi M1541"; break; + case ALI_M1621: head->chipset = "ALi M1621"; break; + case ALI_M1631: head->chipset = "ALi M1631"; break; + case ALI_M1632: head->chipset = "ALi M1632"; break; + case ALI_M1641: head->chipset = "ALi M1641"; break; + case ALI_M1647: head->chipset = "ALi M1647"; break; + case ALI_M1651: head->chipset = "ALi M1651"; break; + case SVWRKS_GENERIC: head->chipset = "Serverworks Generic"; + break; + case SVWRKS_HE: head->chipset = "Serverworks HE"; + case SVWRKS_LE: head->chipset = "Serverworks LE"; + default: head->chipset = "Unknown"; break; } DRM_INFO("AGP %d.%d on %s @ 0x%08lx %ZuMB\n", diff -u --recursive --new-file v2.4.5/linux/drivers/char/drm/context.c linux/drivers/char/drm/context.c --- v2.4.5/linux/drivers/char/drm/context.c Tue Aug 29 14:09:15 2000 +++ linux/drivers/char/drm/context.c Wed Jun 27 17:10:55 2001 @@ -91,10 +91,13 @@ atomic_dec(&dev->queuelist[i]->use_count); } /* Allocate a new queue */ - down(&dev->struct_sem); queue = drm_alloc(sizeof(*queue), DRM_MEM_QUEUES); + if(queue == NULL) + return -ENOMEM; + memset(queue, 0, sizeof(*queue)); + down(&dev->struct_sem); atomic_set(&queue->use_count, 1); ++dev->queue_count; diff -u --recursive --new-file v2.4.5/linux/drivers/char/drm/dma.c linux/drivers/char/drm/dma.c --- v2.4.5/linux/drivers/char/drm/dma.c Wed Nov 15 00:41:03 2000 +++ linux/drivers/char/drm/dma.c Wed Jun 27 17:10:55 2001 @@ -38,7 +38,10 @@ { int i; - dev->dma = drm_alloc(sizeof(*dev->dma), DRM_MEM_DRIVER); + if (!(dev->dma = drm_alloc(sizeof(*dev->dma), DRM_MEM_DRIVER))) { + printk(KERN_ERR "drm_dma_setup: can't drm_alloc dev->dma"); + return; + } memset(dev->dma, 0, sizeof(*dev->dma)); for (i = 0; i <= DRM_MAX_ORDER; i++) memset(&dev->dma->bufs[i], 0, sizeof(dev->dma->bufs[0])); diff -u --recursive --new-file v2.4.5/linux/drivers/char/drm/ffb_drv.c linux/drivers/char/drm/ffb_drv.c --- v2.4.5/linux/drivers/char/drm/ffb_drv.c Sun May 20 12:11:38 2001 +++ linux/drivers/char/drm/ffb_drv.c Mon Jun 11 19:15:27 2001 @@ -1,4 +1,4 @@ -/* $Id: ffb_drv.c,v 1.12 2001/04/14 01:12:03 davem Exp $ +/* $Id: ffb_drv.c,v 1.14 2001/05/24 12:01:47 davem Exp $ * ffb_drv.c: Creator/Creator3D direct rendering driver. * * Copyright (C) 2000 David S. Miller (davem@redhat.com) @@ -719,9 +719,19 @@ current->state = TASK_RUNNING; remove_wait_queue(&dev->lock.lock_queue, &entry); - if (!ret && - (dev->last_context != lock.context)) - ffb_context_switch(dev, dev->last_context, lock.context); + if (!ret) { + sigemptyset(&dev->sigmask); + sigaddset(&dev->sigmask, SIGSTOP); + sigaddset(&dev->sigmask, SIGTSTP); + sigaddset(&dev->sigmask, SIGTTIN); + sigaddset(&dev->sigmask, SIGTTOU); + dev->sigdata.context = lock.context; + dev->sigdata.lock = dev->lock.hw_lock; + block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); + + if (dev->last_context != lock.context) + ffb_context_switch(dev, dev->last_context, lock.context); + } DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock"); @@ -770,6 +780,7 @@ wake_up_interruptible(&dev->lock.lock_queue); + unblock_all_signals(); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/char/drm/i810_dma.c linux/drivers/char/drm/i810_dma.c --- v2.4.5/linux/drivers/char/drm/i810_dma.c Mon Mar 19 12:35:08 2001 +++ linux/drivers/char/drm/i810_dma.c Wed Jun 27 17:10:55 2001 @@ -1286,6 +1286,8 @@ DRM_DEBUG("i810 dma vertex, idx %d used %d discard %d\n", vertex.idx, vertex.used, vertex.discard); + if(vertex.idx < 0 || vertex.idx > dma->buf_count) return -EINVAL; + i810_dma_dispatch_vertex( dev, dma->buflist[ vertex.idx ], vertex.discard, vertex.used ); @@ -1409,7 +1411,7 @@ if (copy_from_user(&d, (drm_i810_copy_t *)arg, sizeof(d))) return -EFAULT; - if(d.idx > dma->buf_count) return -EINVAL; + if(d.idx < 0 || d.idx > dma->buf_count) return -EINVAL; buf = dma->buflist[ d.idx ]; buf_priv = buf->dev_private; if (buf_priv->currently_mapped != I810_BUF_MAPPED) return -EPERM; diff -u --recursive --new-file v2.4.5/linux/drivers/char/drm/mga_state.c linux/drivers/char/drm/mga_state.c --- v2.4.5/linux/drivers/char/drm/mga_state.c Thu Jan 4 14:06:18 2001 +++ linux/drivers/char/drm/mga_state.c Wed Jun 27 17:10:55 2001 @@ -832,6 +832,7 @@ return -EINVAL; } + if(iload.idx < 0 || iload.idx > dma->buf_count) return -EINVAL; buf = dma->buflist[iload.idx]; buf_priv = buf->dev_private; bus_address = buf->bus_address; @@ -874,6 +875,8 @@ return -EINVAL; } + if(vertex.idx < 0 || vertex.idx > dma->buf_count) return -EINVAL; + buf = dma->buflist[vertex.idx]; buf_priv = buf->dev_private; @@ -920,6 +923,7 @@ return -EINVAL; } + if(indices.idx < 0 || indices.idx > dma->buf_count) return -EINVAL; buf = dma->buflist[indices.idx]; buf_priv = buf->dev_private; diff -u --recursive --new-file v2.4.5/linux/drivers/char/drm/proc.c linux/drivers/char/drm/proc.c --- v2.4.5/linux/drivers/char/drm/proc.c Thu Jul 27 15:10:22 2000 +++ linux/drivers/char/drm/proc.c Wed Jun 27 17:10:55 2001 @@ -92,6 +92,7 @@ if (!drm_dev_root) { DRM_ERROR("Cannot create /proc/%s\n", drm_slot_name); remove_proc_entry("dri", NULL); + break; } if (drm_dev_root->nlink == 2) break; drm_dev_root = NULL; diff -u --recursive --new-file v2.4.5/linux/drivers/char/drm/r128_drv.h linux/drivers/char/drm/r128_drv.h --- v2.4.5/linux/drivers/char/drm/r128_drv.h Fri Mar 2 18:38:37 2001 +++ linux/drivers/char/drm/r128_drv.h Wed Jun 20 21:00:55 2001 @@ -385,16 +385,14 @@ #define R128_MAX_VB_VERTS (0xffff) -#define R128_BASE(reg) ((u32)(dev_priv->mmio->handle)) +#define R128_BASE(reg) ((unsigned long)(dev_priv->mmio->handle)) #define R128_ADDR(reg) (R128_BASE(reg) + reg) -#define R128_DEREF(reg) *(__volatile__ int *)R128_ADDR(reg) -#define R128_READ(reg) R128_DEREF(reg) -#define R128_WRITE(reg,val) do { R128_DEREF(reg) = val; } while (0) +#define R128_READ(reg) readl(R128_ADDR(reg)) +#define R128_WRITE(reg,val) writel(val,R128_ADDR(reg)) -#define R128_DEREF8(reg) *(__volatile__ char *)R128_ADDR(reg) -#define R128_READ8(reg) R128_DEREF8(reg) -#define R128_WRITE8(reg,val) do { R128_DEREF8(reg) = val; } while (0) +#define R128_READ8(reg) readb(R128_ADDR(reg)) +#define R128_WRITE8(reg,val) writeb(val,R128_ADDR(reg)) #define R128_WRITE_PLL(addr,val) \ do { \ diff -u --recursive --new-file v2.4.5/linux/drivers/char/drm/radeon_bufs.c linux/drivers/char/drm/radeon_bufs.c --- v2.4.5/linux/drivers/char/drm/radeon_bufs.c Mon Mar 19 12:35:08 2001 +++ linux/drivers/char/drm/radeon_bufs.c Wed Jun 27 17:10:55 2001 @@ -132,6 +132,11 @@ buf->dev_priv_size = sizeof(drm_radeon_buf_priv_t); buf->dev_private = drm_alloc(sizeof(drm_radeon_buf_priv_t), DRM_MEM_BUFS); + if (!buf->dev_private) { + up(&dev->struct_sem); + atomic_dec(&dev->buf_alloc); + return -ENOMEM; + } memset(buf->dev_private, 0, buf->dev_priv_size); #if DRM_DMA_HISTOGRAM diff -u --recursive --new-file v2.4.5/linux/drivers/char/epca.c linux/drivers/char/epca.c --- v2.4.5/linux/drivers/char/epca.c Tue May 22 10:23:16 2001 +++ linux/drivers/char/epca.c Wed Jun 27 14:13:01 2001 @@ -60,6 +60,10 @@ #include "epca.h" #include "epcaconfig.h" +#if BITS_PER_LONG != 32 +# error FIXME: this driver only works on 32-bit platforms +#endif + /* ---------------------- Begin defines ------------------------ */ #define VERSION "1.3.0.1-LK" diff -u --recursive --new-file v2.4.5/linux/drivers/char/esp.c linux/drivers/char/esp.c --- v2.4.5/linux/drivers/char/esp.c Fri Apr 6 10:42:55 2001 +++ linux/drivers/char/esp.c Wed Jun 27 14:13:01 2001 @@ -957,7 +957,7 @@ if (!dma_buffer) info->stat_flags |= ESP_STAT_USE_PIO; else if (request_dma(dma, "esp serial")) { - free_pages((unsigned int)dma_buffer, + free_pages((unsigned long)dma_buffer, get_order(DMA_BUFFER_SZ)); dma_buffer = 0; info->stat_flags |= ESP_STAT_USE_PIO; @@ -1061,7 +1061,7 @@ if (!current_port) { free_dma(dma); - free_pages((unsigned int)dma_buffer, + free_pages((unsigned long)dma_buffer, get_order(DMA_BUFFER_SZ)); dma_buffer = 0; } @@ -2770,7 +2770,7 @@ } if (dma_buffer) - free_pages((unsigned int)dma_buffer, + free_pages((unsigned long)dma_buffer, get_order(DMA_BUFFER_SZ)); if (tmp_buf) diff -u --recursive --new-file v2.4.5/linux/drivers/char/i810-tco.c linux/drivers/char/i810-tco.c --- v2.4.5/linux/drivers/char/i810-tco.c Thu May 24 15:14:08 2001 +++ linux/drivers/char/i810-tco.c Mon Jul 2 13:56:41 2001 @@ -232,19 +232,40 @@ } } +/* + * Data for PCI driver interface + * + * This data only exists for exporting the supported + * PCI ids via MODULE_DEVICE_TABLE. We do not actually + * register a pci_driver, because someone else might one day + * want to register another driver on the same PCI id. + */ +static struct pci_device_id i810tco_pci_tbl[] __initdata = { + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10, PCI_ANY_ID, PCI_ANY_ID, }, + { 0, }, +}; +MODULE_DEVICE_TABLE (pci, i810tco_pci_tbl); + static struct pci_dev *i810tco_pci; static unsigned char i810tco_getdevice (void) { + struct pci_dev *dev; u8 val1, val2; u16 badr; /* - * Find the PCI device which has vendor id 0x8086 - * and device ID 0x2410 + * Find the PCI device */ - i810tco_pci = pci_find_device (PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82801AA_0, NULL); - if (i810tco_pci) { + + pci_for_each_dev(dev) { + if (pci_match_device(i810tco_pci_tbl, dev)) + break; + } + + if ((i810tco_pci = dev)) { /* * Find the ACPI base I/O address which is the base * for the TCO registers (TCOBASE=ACPIBASE + 0x60) @@ -268,7 +289,7 @@ pci_write_config_byte (i810tco_pci, 0xd4, val1); pci_read_config_byte (i810tco_pci, 0xd4, &val1); if (val1 & 0x02) { - printk (KERN_ERR "i810tco init: failed to reset NO_REBOOT flag\n"); + printk (KERN_ERR "i810tco init: failed to reset NO_REBOOT flag, reboot disabled by hardware\n"); return 0; /* Cannot reset NO_REBOOT bit */ } } diff -u --recursive --new-file v2.4.5/linux/drivers/char/n_r3964.c linux/drivers/char/n_r3964.c --- v2.4.5/linux/drivers/char/n_r3964.c Fri Apr 13 20:26:07 2001 +++ linux/drivers/char/n_r3964.c Wed Jun 27 14:13:01 2001 @@ -132,10 +132,10 @@ static int r3964_open(struct tty_struct *tty); static void r3964_close(struct tty_struct *tty); -static int r3964_read(struct tty_struct *tty, struct file *file, - unsigned char *buf, unsigned int nr); -static int r3964_write(struct tty_struct * tty, struct file * file, - const unsigned char * buf, unsigned int nr); +static ssize_t r3964_read(struct tty_struct *tty, struct file *file, + unsigned char *buf, size_t nr); +static ssize_t r3964_write(struct tty_struct * tty, struct file * file, + const unsigned char * buf, size_t nr); static int r3964_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg); static void r3964_set_termios(struct tty_struct *tty, struct termios * old); @@ -1238,8 +1238,8 @@ MOD_DEC_USE_COUNT; } -static int r3964_read(struct tty_struct *tty, struct file *file, - unsigned char *buf, unsigned int nr) +static ssize_t r3964_read(struct tty_struct *tty, struct file *file, + unsigned char *buf, size_t nr) { struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; struct r3964_client_info *pClient; @@ -1299,8 +1299,8 @@ return -EPERM; } -static int r3964_write(struct tty_struct * tty, struct file * file, - const unsigned char *data, unsigned int count) +static ssize_t r3964_write(struct tty_struct * tty, struct file * file, + const unsigned char *data, size_t count) { struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; struct r3964_block_header *pHeader; diff -u --recursive --new-file v2.4.5/linux/drivers/char/nvram.c linux/drivers/char/nvram.c --- v2.4.5/linux/drivers/char/nvram.c Fri Feb 9 11:40:02 2001 +++ linux/drivers/char/nvram.c Wed Jun 27 17:10:55 2001 @@ -113,7 +113,7 @@ #define NVRAM_EXCL 2 /* opened with O_EXCL */ #define RTC_FIRST_BYTE 14 /* RTC register number of first NVRAM byte */ -#define NVRAM_BYTES 50 /* number of NVRAM bytes */ +#define NVRAM_BYTES 128 /* number of NVRAM bytes */ static int mach_check_checksum( void ); diff -u --recursive --new-file v2.4.5/linux/drivers/char/nwflash.c linux/drivers/char/nwflash.c --- v2.4.5/linux/drivers/char/nwflash.c Mon Sep 18 15:15:22 2000 +++ linux/drivers/char/nwflash.c Wed Jun 27 14:12:04 2001 @@ -4,6 +4,14 @@ * * 20/08/2000 RMK use __ioremap to map flash into virtual memory * make a few more places use "volatile" + * 22/05/2001 RMK - Lock read against write + * - merge printk level changes (with mods) from Alan Cox. + * - use *ppos as the file position, not file->f_pos. + * - fix check for out of range pos and r/w size + * + * Please note that we are tampering with the only flash chip in the + * machine, which contains the bootup code. We therefore have the + * power to convert these machines into doorstops... */ #include @@ -16,6 +24,7 @@ #include #include #include +#include #include #include @@ -28,21 +37,12 @@ /*****************************************************************************/ #include -//#define MINIKERNEL 1 //export flash write, erase routines for MiniKernel +#define NWFLASH_VERSION "6.4" -#ifndef MINIKERNEL -#define MSTATIC static -#else -#define MSTATIC -#endif - -#define NWFLASH_VERSION "6.3" - -MSTATIC void kick_open(void); -MSTATIC int get_flash_id(void); -MSTATIC int erase_block(int nBlock); -MSTATIC int write_block(unsigned long p, const char *buf, int count); -static int open_flash(struct inode *inodep, struct file *filep); +static void kick_open(void); +static int get_flash_id(void); +static int erase_block(int nBlock); +static int write_block(unsigned long p, const char *buf, int count); static int flash_ioctl(struct inode *inodep, struct file *filep, unsigned int cmd, unsigned long arg); static ssize_t flash_read(struct file *file, char *buf, size_t count, loff_t * ppos); static ssize_t flash_write(struct file *file, const char *buf, size_t count, loff_t * ppos); @@ -58,27 +58,10 @@ static int gbWriteEnable; static int gbWriteBase64Enable; static volatile unsigned char *FLASH_BASE; -MSTATIC int gbFlashSize = KFLASH_SIZE; +static int gbFlashSize = KFLASH_SIZE; extern spinlock_t gpio_lock; -static struct file_operations flash_fops = -{ - owner: THIS_MODULE, - llseek: flash_llseek, - read: flash_read, - write: flash_write, - ioctl: flash_ioctl, - open: open_flash, -}; - -static struct miscdevice flash_miscdev = -{ - FLASH_MINOR, - "nwflash", - &flash_fops -}; - /* * the delay routine - it is often required to let the flash "breeze"... */ @@ -88,7 +71,7 @@ schedule_timeout(timeout); } -MSTATIC int get_flash_id(void) +static int get_flash_id(void) { volatile unsigned int c1, c2; @@ -123,23 +106,8 @@ return c2; } -static int open_flash(struct inode *inodep, struct file *filep) -{ - int id; - - id = get_flash_id(); - if ((id != KFLASH_ID) && (id != KFLASH_ID4)) { - printk("Flash: incorrect ID 0x%04X.\n", id); - return -ENXIO; - } - - return 0; -} - static int flash_ioctl(struct inode *inodep, struct file *filep, unsigned int cmd, unsigned long arg) { -// printk("Flash_ioctl: cmd = 0x%X.\n",cmd); - switch (cmd) { case CMD_WRITE_DISABLE: gbWriteBase64Enable = 0; @@ -159,41 +127,48 @@ gbWriteEnable = 0; return -EINVAL; } - return 0; } - - -static ssize_t flash_read(struct file *file, char *buf, size_t count, loff_t * ppos) +static ssize_t flash_read(struct file *file, char *buf, size_t size, loff_t * ppos) { - unsigned long p = file->f_pos; - int read; + struct inode *inode = file->f_dentry->d_inode; + unsigned long p = *ppos; + unsigned int count = size; + int ret = 0; if (flashdebug) - printk("Flash_dev: flash_read: offset=0x%X, buffer=0x%X, count=0x%X.\n", - (unsigned int) p, (unsigned int) buf, count); - + printk(KERN_DEBUG "flash_read: flash_read: offset=0x%lX, buffer=%p, count=0x%X.\n", + p, buf, count); - if (count < 0) - return -EINVAL; + if (count) + ret = -ENXIO; - if (count > gbFlashSize - p) - count = gbFlashSize - p; + if (p < gbFlashSize) { + if (count > gbFlashSize - p) + count = gbFlashSize - p; - read = 0; + /* + * We now lock against reads and writes. --rmk + */ + if (down_interruptible(&inode->i_sem)) + return -ERESTARTSYS; - if (copy_to_user(buf, (void *)(FLASH_BASE + p), count)) - return -EFAULT; - read += count; - file->f_pos += read; - return read; + ret = copy_to_user(buf, (void *)(FLASH_BASE + p), count); + if (ret == 0) { + ret = count; + *ppos += count; + } + up(&inode->i_sem); + } + return ret; } -static ssize_t flash_write(struct file *file, const char *buf, size_t count, loff_t * ppos) +static ssize_t flash_write(struct file *file, const char *buf, size_t size, loff_t * ppos) { struct inode *inode = file->f_dentry->d_inode; - unsigned long p = file->f_pos; + unsigned long p = *ppos; + unsigned int count = size; int written; int nBlock, temp, rc; int i, j; @@ -209,20 +184,19 @@ return -EINVAL; /* - * if byte count is -ve or to big - error! + * check for out of range pos or count */ - if (count < 0 || count > gbFlashSize - p) - return -EINVAL; + if (p >= gbFlashSize) + return count ? -ENXIO : 0; + if (count > gbFlashSize - p) + count = gbFlashSize - p; + if (verify_area(VERIFY_READ, buf, count)) return -EFAULT; - /* - * We now should lock around writes. Really, we shouldn't - * allow the flash to be opened more than once in write - * mode though (note that you can't stop two processes having - * it open even then). --rmk + * We now lock against reads and writes. --rmk */ if (down_interruptible(&inode->i_sem)) return -ERESTARTSYS; @@ -246,11 +220,12 @@ temp -= 1; if (flashdebug) - printk("FlashWrite: writing %d block(s) starting at %d.\n", temp, nBlock); + printk(KERN_DEBUG "flash_write: writing %d block(s) " + "starting at %d.\n", temp, nBlock); for (; temp; temp--, nBlock++) { if (flashdebug) - printk("FlashWrite: erasing block %d.\n", nBlock); + printk(KERN_DEBUG "flash_write: erasing block %d.\n", nBlock); /* * first we have to erase the block(s), where we will write... @@ -264,14 +239,12 @@ } while (rc && i < 10); if (rc) { - if (flashdebug) - printk("FlashWrite: erase error %X. Aborting...\n", rc); - + printk(KERN_ERR "flash_write: erase error %x\n", rc); break; } if (flashdebug) - printk("FlashWrite: writing offset %X, from buf %X, bytes left %X.\n", - (unsigned int) p, (unsigned int) buf, count - written); + printk(KERN_DEBUG "flash_write: writing offset %lX, from buf " + "%p, bytes left %X.\n", p, buf, count - written); /* * write_block will limit write to space left in this block @@ -296,17 +269,16 @@ } if (rc < 0) { - if (flashdebug) - printk("FlashWrite: write error %X. Aborting...\n", rc); + printk(KERN_ERR "flash_write: write error %X\n", rc); break; } p += rc; buf += rc; written += rc; - file->f_pos += rc; + *ppos += rc; if (flashdebug) - printk("FlashWrite: written 0x%X bytes OK.\n", written); + printk(KERN_DEBUG "flash_write: written 0x%X bytes OK.\n", written); } /* @@ -331,8 +303,8 @@ static long long flash_llseek(struct file *file, long long offset, int orig) { if (flashdebug) - printk("Flash_dev: flash_lseek, offset=0x%X, orig=0x%X.\n", - (unsigned int) offset, (unsigned int) orig); + printk(KERN_DEBUG "flash_llseek: offset=0x%X, orig=0x%X.\n", + (unsigned int) offset, orig); switch (orig) { case 0: @@ -362,7 +334,7 @@ * so just go ahead and erase, what requested! */ -MSTATIC int erase_block(int nBlock) +static int erase_block(int nBlock) { volatile unsigned int c1; volatile unsigned char *pWritePtr; @@ -440,13 +412,12 @@ * check if erase errors were reported */ if (c1 & 0x20) { - if (flashdebug) - printk("Flash_erase: err at %X.\n", (unsigned int) pWritePtr); + printk(KERN_ERR "flash_erase: err at %p\n", pWritePtr); + /* * reset error */ *(volatile unsigned char *) (FLASH_BASE + 0x8000) = 0x50; - return -2; } @@ -459,9 +430,8 @@ for (temp = 0; temp < 16 * 1024; temp++, pWritePtr += 4) { if ((temp1 = *(volatile unsigned int *) pWritePtr) != 0xFFFFFFFF) { - if (flashdebug) - printk("Flash_erase: verify err at %X = %X.\n", - (unsigned int) pWritePtr, temp1); + printk(KERN_ERR "flash_erase: verify err at %p = %X\n", + pWritePtr, temp1); return -1; } } @@ -473,7 +443,7 @@ /* * write_block will limit number of bytes written to the space in this block */ -MSTATIC int write_block(unsigned long p, const char *buf, int count) +static int write_block(unsigned long p, const char *buf, int count) { volatile unsigned int c1; volatile unsigned int c2; @@ -591,7 +561,7 @@ */ if (time_before(jiffies, timeout)) { if (flashdebug) - printk("FlashWrite: Retrying write (addr=0x%X)...\n", + printk(KERN_DEBUG "write_block: Retrying write at 0x%X)n", pWritePtr - FLASH_BASE); /* @@ -609,7 +579,7 @@ goto WriteRetry; } else { - printk("Timeout in flash write! (addr=0x%X) Aborting...\n", + printk(KERN_ERR "write_block: timeout at 0x%X\n", pWritePtr - FLASH_BASE); /* * return error -2 @@ -636,9 +606,8 @@ return -EFAULT; buf++; if ((c1 = *pWritePtr++) != c) { - if (flashdebug) - printk("flash write verify error at 0x%X! (%02X!=%02X) Retrying...\n", - (unsigned int) pWritePtr, c1, c); + printk(KERN_ERR "write_block: verify error at 0x%X (%02X!=%02X)\n", + pWritePtr - FLASH_BASE, c1, c); return 0; } } @@ -647,7 +616,7 @@ } -MSTATIC void kick_open(void) +static void kick_open(void) { unsigned long flags; @@ -665,7 +634,23 @@ udelay(25); } -MSTATIC int __init nwflash_init(void) +static struct file_operations flash_fops = +{ + owner: THIS_MODULE, + llseek: flash_llseek, + read: flash_read, + write: flash_write, + ioctl: flash_ioctl, +}; + +static struct miscdevice flash_miscdev = +{ + FLASH_MINOR, + "nwflash", + &flash_fops +}; + +static int __init nwflash_init(void) { int ret = -ENODEV; @@ -677,6 +662,13 @@ goto out; id = get_flash_id(); + if ((id != KFLASH_ID) && (id != KFLASH_ID4)) { + ret = -ENXIO; + iounmap((void *)FLASH_BASE); + printk("Flash: incorrect ID 0x%04X.\n", id); + goto out; + } + printk("Flash ROM driver v.%s, flash device ID 0x%04X, size %d Mb.\n", NWFLASH_VERSION, id, gbFlashSize / (1024 * 1024)); @@ -688,7 +680,7 @@ return ret; } -MSTATIC void __exit nwflash_exit(void) +static void __exit nwflash_exit(void) { misc_deregister(&flash_miscdev); iounmap((void *)FLASH_BASE); diff -u --recursive --new-file v2.4.5/linux/drivers/char/random.c linux/drivers/char/random.c --- v2.4.5/linux/drivers/char/random.c Tue May 1 16:05:00 2001 +++ linux/drivers/char/random.c Mon Jul 2 13:56:41 2001 @@ -712,8 +712,7 @@ #if defined (__i386__) if ( test_bit(X86_FEATURE_TSC, &boot_cpu_data.x86_capability) ) { __u32 high; - __asm__(".byte 0x0f,0x31" - :"=a" (time), "=d" (high)); + rdtsc(time, high); num ^= high; } else { time = jiffies; @@ -1793,7 +1792,7 @@ void *newval, size_t newlen, void **context) { unsigned char tmp_uuid[16], *uuid; - int len; + unsigned int len; if (!oldval || !oldlenp) return 1; @@ -1810,7 +1809,7 @@ if (len) { if (len > 16) len = 16; - if (copy_to_user(oldval, table->data, len)) + if (copy_to_user(oldval, uuid, len)) return -EFAULT; if (put_user(len, oldlenp)) return -EFAULT; diff -u --recursive --new-file v2.4.5/linux/drivers/char/raw.c linux/drivers/char/raw.c --- v2.4.5/linux/drivers/char/raw.c Sun May 20 11:34:05 2001 +++ linux/drivers/char/raw.c Wed Jun 27 17:10:55 2001 @@ -194,7 +194,7 @@ break; minor = rq.raw_minor; - if (minor == 0 || minor > MINORMASK) { + if (minor <= 0 || minor > MINORMASK) { err = -EINVAL; break; } diff -u --recursive --new-file v2.4.5/linux/drivers/char/rio/rioroute.c linux/drivers/char/rio/rioroute.c --- v2.4.5/linux/drivers/char/rio/rioroute.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/char/rio/rioroute.c Mon Jun 11 19:15:27 2001 @@ -657,6 +657,7 @@ */ if (PortP->TxStart == 0) { rio_dprintk (RIO_DEBUG_ROUTE, "Tx pkts not set up yet\n"); + rio_spin_unlock_irqrestore(&PortP->portSem, flags); break; } diff -u --recursive --new-file v2.4.5/linux/drivers/char/rocket.c linux/drivers/char/rocket.c --- v2.4.5/linux/drivers/char/rocket.c Sun Mar 25 18:24:31 2001 +++ linux/drivers/char/rocket.c Mon Jul 2 13:56:41 2001 @@ -485,14 +485,10 @@ unsigned char CtlMask, AiopMask; #ifdef TIME_STAT - unsigned long low=0, high=0, loop_time; + unsigned long loop_time; unsigned long long time_stat_tmp=0, time_stat_tmp2=0; - __asm__(".byte 0x0f,0x31" - :"=a" (low), "=d" (high)); - time_stat_tmp = high; - time_stat_tmp <<= 32; - time_stat_tmp += low; + rdtscll(time_stat_tmp); #endif /* TIME_STAT */ for (ctrl=0; ctrl < max_board; ctrl++) { @@ -532,11 +528,7 @@ mod_timer(&rocket_timer, jiffies + 1); } #ifdef TIME_STAT - __asm__(".byte 0x0f,0x31" - :"=a" (low), "=d" (high)); - time_stat_tmp2 = high; - time_stat_tmp2 <<= 32; - time_stat_tmp2 += low; + rdtscll(time_stat_tmp2); time_stat_tmp2 -= time_stat_tmp; time_stat += time_stat_tmp2; if (time_counter == 0) diff -u --recursive --new-file v2.4.5/linux/drivers/char/rtc.c linux/drivers/char/rtc.c --- v2.4.5/linux/drivers/char/rtc.c Thu Jan 4 12:50:17 2001 +++ linux/drivers/char/rtc.c Tue Jun 12 11:08:46 2001 @@ -73,6 +73,9 @@ #ifdef __sparc__ #include +#ifdef __sparc_v9__ +#include +#endif static unsigned long rtc_port; static int rtc_irq; @@ -622,22 +625,37 @@ #ifdef __sparc__ struct linux_ebus *ebus; struct linux_ebus_device *edev; +#ifdef __sparc_v9__ + struct isa_bridge *isa_br; + struct isa_device *isa_dev; +#endif #endif #ifdef __sparc__ for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { if(strcmp(edev->prom_name, "rtc") == 0) { + rtc_port = edev->resource[0].start; + rtc_irq = edev->irqs[0]; goto found; } } } +#ifdef __sparc_v9__ + for_each_isa(isa_br) { + for_each_isadev(isa_dev, isa_br) { + if (strcmp(isa_dev->prom_name, "rtc") == 0) { + rtc_port = isa_dev->resource.start; + rtc_irq = isa_dev->irq; + goto found; + } + } + } +#endif printk(KERN_ERR "rtc_init: no PC rtc found\n"); return -EIO; found: - rtc_port = edev->resource[0].start; - rtc_irq = edev->irqs[0]; /* * XXX Interrupt pin #7 in Espresso is shared between RTC and * PCI Slot 2 INTA# (and some INTx# in Slot 1). SA_INTERRUPT here diff -u --recursive --new-file v2.4.5/linux/drivers/char/sbc60xxwdt.c linux/drivers/char/sbc60xxwdt.c --- v2.4.5/linux/drivers/char/sbc60xxwdt.c Tue May 22 10:23:16 2001 +++ linux/drivers/char/sbc60xxwdt.c Wed Jun 27 17:10:55 2001 @@ -174,9 +174,13 @@ /* now scan */ for(ofs = 0; ofs != count; ofs++) + { + char c; + if(get_user(c, buf+ofs)) + return -EFAULT; if(buf[ofs] == 'V') wdt_expect_close = 1; - + } /* Well, anyhow someone wrote to us, we should return that favour */ next_heartbeat = jiffies + WDT_HEARTBEAT; return 1; diff -u --recursive --new-file v2.4.5/linux/drivers/char/sh-sci.c linux/drivers/char/sh-sci.c --- v2.4.5/linux/drivers/char/sh-sci.c Wed Apr 11 21:24:52 2001 +++ linux/drivers/char/sh-sci.c Wed Jun 27 13:55:29 2001 @@ -1035,7 +1035,11 @@ memset(&sci_driver, 0, sizeof(sci_driver)); sci_driver.magic = TTY_DRIVER_MAGIC; sci_driver.driver_name = "sci"; +#ifdef CONFIG_DEVFS_FS + sci_driver.name = "ttsc/%d"; +#else sci_driver.name = "ttySC"; +#endif sci_driver.major = SCI_MAJOR; sci_driver.minor_start = SCI_MINOR_START; sci_driver.num = SCI_NPORTS; @@ -1070,7 +1074,11 @@ #endif sci_callout_driver = sci_driver; +#ifdef CONFIG_DEVFS_FS + sci_callout_driver.name = "cusc/%d"; +#else sci_callout_driver.name = "cusc"; +#endif sci_callout_driver.major = SCI_MAJOR+1; sci_callout_driver.subtype = SERIAL_TYPE_CALLOUT; sci_callout_driver.read_proc = NULL; diff -u --recursive --new-file v2.4.5/linux/drivers/char/sh-sci.h linux/drivers/char/sh-sci.h --- v2.4.5/linux/drivers/char/sh-sci.h Wed Apr 11 21:24:52 2001 +++ linux/drivers/char/sh-sci.h Wed Jun 27 13:55:29 2001 @@ -46,7 +46,7 @@ # define SCPDR 0xA4000136 /* 8 bit SCI and SCIF */ # define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ # define SCI_AND_SCIF -#elif defined(CONFIG_CPU_SUBTYPE_SH7750) +#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751) # define SCI_NPORTS 2 # define SCI_INIT { \ { {}, PORT_SCI, 0xffe00000, SCI_IRQS, sci_init_pins_sci }, \ @@ -294,7 +294,7 @@ return ctrl_inb(SCPDR)&0x04 ? 1 : 0; /* IRDA */ return 1; } -#elif defined(CONFIG_CPU_SUBTYPE_SH7750) +#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751) static inline int sci_rxd_in(struct sci_port *port) { #ifndef SCIF_ONLY diff -u --recursive --new-file v2.4.5/linux/drivers/char/sx.c linux/drivers/char/sx.c --- v2.4.5/linux/drivers/char/sx.c Fri Apr 6 10:42:55 2001 +++ linux/drivers/char/sx.c Wed Jun 27 14:13:01 2001 @@ -467,7 +467,7 @@ int i, j, ch; for (i=0;ibase + SX_VPD_ROM); if (sx_debug & SX_DEBUG_PROBE) @@ -2123,7 +2124,7 @@ printheader (); if (!IS_CF_BOARD (board)) { - printk (KERN_DEBUG "sx: Found an SX board at %x\n", board->hw_base); + printk (KERN_DEBUG "sx: Found an SX board at %lx\n", board->hw_base); printk (KERN_DEBUG "sx: hw_rev: %d, assembly level: %d, uniq ID:%08x, ", vpdp.hwrev, vpdp.hwass, vpdp.uniqid); printk ( "Manufactured: %d/%d\n", @@ -2140,7 +2141,7 @@ if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) == SX_ISA_UNIQUEID1) { if (board->base & 0x8000) { - printk (KERN_WARNING "sx: Warning: There may be hardware problems with the card at %x.\n", board->base); + printk (KERN_WARNING "sx: Warning: There may be hardware problems with the card at %lx.\n", board->base); printk (KERN_WARNING "sx: Read sx.txt for more info.\n"); } } @@ -2172,7 +2173,7 @@ int i; func_enter(); - sx_dprintk (SX_DEBUG_PROBE, "Going to verify SI signature %x.\n", + sx_dprintk (SX_DEBUG_PROBE, "Going to verify SI signature %lx.\n", board->base + SI2_ISA_ID_BASE); if (sx_debug & SX_DEBUG_PROBE) @@ -2188,7 +2189,7 @@ printheader (); - printk (KERN_DEBUG "sx: Found an SI board at %x\n", board->hw_base); + printk (KERN_DEBUG "sx: Found an SI board at %lx\n", board->hw_base); /* Compared to the SX boards, it is a complete guess as to what this card is up to... */ @@ -2507,7 +2508,7 @@ board->irq = get_irq (pdev); - sx_dprintk (SX_DEBUG_PROBE, "Got a specialix card: %x/%x(%d) %x.\n", + sx_dprintk (SX_DEBUG_PROBE, "Got a specialix card: %x/%lx(%d) %x.\n", tint, boards[found].base, board->irq, board->flags); if (probe_sx (board)) { @@ -2569,8 +2570,8 @@ board->base2 = board->base = (ulong) ioremap(board->hw_base, SI2_EISA_WINDOW_LEN); - sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %x\n", board->hw_base); - sx_dprintk(SX_DEBUG_PROBE, "base: %x\n", board->base); + sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %lx\n", board->hw_base); + sx_dprintk(SX_DEBUG_PROBE, "base: %lx\n", board->base); board->irq = inb(board->eisa_base+0xc02)>>4; sx_dprintk(SX_DEBUG_PROBE, "IRQ: %d\n", board->irq); @@ -2602,7 +2603,7 @@ for (i = 0; i < SX_NBOARDS; i++) { board = &boards[i]; if (board->flags & SX_BOARD_INITIALIZED) { - sx_dprintk (SX_DEBUG_CLEANUP, "Cleaning up board at %x\n", board->base); + sx_dprintk (SX_DEBUG_CLEANUP, "Cleaning up board at %lx\n", board->base); /* The board should stop messing with us. (actually I mean the interrupt) */ sx_reset (board); diff -u --recursive --new-file v2.4.5/linux/drivers/char/sx.h linux/drivers/char/sx.h --- v2.4.5/linux/drivers/char/sx.h Mon Dec 11 13:38:29 2000 +++ linux/drivers/char/sx.h Wed Jun 27 14:13:01 2001 @@ -36,9 +36,9 @@ struct sx_board { int magic; - unsigned int base; - unsigned int base2; - unsigned int hw_base; + unsigned long base; + unsigned long base2; + unsigned long hw_base; int eisa_base; int port_base; /* Number of the first port */ struct sx_port *ports; diff -u --recursive --new-file v2.4.5/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c --- v2.4.5/linux/drivers/char/tty_io.c Thu Apr 26 17:35:49 2001 +++ linux/drivers/char/tty_io.c Mon Jul 2 14:16:31 2001 @@ -148,6 +148,7 @@ extern long serial167_console_init(void); extern void console_8xx_init(void); extern int rs_8xx_init(void); +extern void mac_scc_console_init(void); extern void hwc_console_init(void); extern void hwc_tty_init(void); extern void con3215_init(void); @@ -1871,6 +1872,8 @@ */ void do_SAK(struct tty_struct *tty) { + if (!tty) + return; PREPARE_TQUEUE(&tty->SAK_tq, __do_SAK, tty); schedule_task(&tty->SAK_tq); } @@ -2184,6 +2187,8 @@ #ifdef CONFIG_SERIAL_CONSOLE #if (defined(CONFIG_8xx) || defined(CONFIG_8260)) console_8xx_init(); +#elif defined(CONFIG_MAC_SERIAL) + mac_scc_console_init(); #elif defined(CONFIG_SERIAL) serial_console_init(); #endif /* CONFIG_8xx */ @@ -2306,9 +2311,6 @@ #endif #ifdef CONFIG_COMPUTONE ip2_init(); -#endif -#ifdef CONFIG_MAC_SERIAL - macserial_init(); #endif #ifdef CONFIG_ROCKETPORT rp_init(); diff -u --recursive --new-file v2.4.5/linux/drivers/i2o/i2o_lan.c linux/drivers/i2o/i2o_lan.c --- v2.4.5/linux/drivers/i2o/i2o_lan.c Sun May 20 12:11:38 2001 +++ linux/drivers/i2o/i2o_lan.c Mon Jun 11 19:15:27 2001 @@ -984,7 +984,7 @@ __raw_writel(priv->unit << 16 | lan_send_context, msg+2); // InitiatorContext __raw_writel(1 << 30 | 1 << 3, msg+3); // TransmitControlWord // bit 30: reply as soon as transmission attempt is complete - // bit 3: Supress CRC generation + // bit 3: Suppress CRC generation __raw_writel(0xD5000000 | skb->len, msg+4); // MAC hdr included __raw_writel((u32)skb, msg+5); // TransactionContext __raw_writel(virt_to_bus(skb->data), msg+6); diff -u --recursive --new-file v2.4.5/linux/drivers/ide/hpt366.c linux/drivers/ide/hpt366.c --- v2.4.5/linux/drivers/ide/hpt366.c Sat May 19 17:43:06 2001 +++ linux/drivers/ide/hpt366.c Wed Jun 27 17:10:55 2001 @@ -51,6 +51,16 @@ }; const char *bad_ata100_5[] = { + "IBM-DTLA-307075", + "IBM-DTLA-307060", + "IBM-DTLA-307045", + "IBM-DTLA-307030", + "IBM-DTLA-307020", + "IBM-DTLA-307015", + "IBM-DTLA-305040", + "IBM-DTLA-305030", + "IBM-DTLA-305020", + "WDC AC310200R", NULL }; diff -u --recursive --new-file v2.4.5/linux/drivers/ide/ide-floppy.c linux/drivers/ide/ide-floppy.c --- v2.4.5/linux/drivers/ide/ide-floppy.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/ide/ide-floppy.c Thu Jun 14 14:16:58 2001 @@ -237,7 +237,7 @@ idefloppy_flexible_disk_page_t flexible_disk_page; /* Copy of the flexible disk page */ int wp; /* Write protect */ - unsigned int flags; /* Status/Action flags */ + unsigned long flags; /* Status/Action flags */ } idefloppy_floppy_t; /* diff -u --recursive --new-file v2.4.5/linux/drivers/ide/ide-pci.c linux/drivers/ide/ide-pci.c --- v2.4.5/linux/drivers/ide/ide-pci.c Sun May 20 11:32:11 2001 +++ linux/drivers/ide/ide-pci.c Wed Jun 27 14:12:04 2001 @@ -34,7 +34,8 @@ #define DEVID_PIIX4U ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_1}) #define DEVID_PIIX4U2 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82372FB_1}) #define DEVID_PIIX4NX ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX}) -#define DEVID_PIIX4U3 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82820FW_5}) +#define DEVID_PIIX4U3 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_9}) +#define DEVID_PIIX4U4 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_8}) #define DEVID_VIA_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561}) #define DEVID_VP_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1}) #define DEVID_PDC20246 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20246}) @@ -282,13 +283,16 @@ #endif #ifdef CONFIG_BLK_DEV_SL82C105 +extern unsigned int pci_init_sl82c105(struct pci_dev *, const char *); +extern void dma_init_sl82c105(ide_hwif_t *, unsigned long); extern void ide_init_sl82c105(ide_hwif_t *); -extern void ide_dmacapable_sl82c105(ide_hwif_t *, unsigned long); +#define PCI_W82C105 &pci_init_sl82c105 +#define DMA_W82C105 &dma_init_sl82c105 #define INIT_W82C105 &ide_init_sl82c105 -#define DMA_W82C105 &ide_dmacapable_sl82c105 #else -#define INIT_W82C105 IDE_IGNORE +#define PCI_W82C105 NULL #define DMA_W82C105 NULL +#define INIT_W82C105 IDE_IGNORE #endif #ifdef CONFIG_BLK_DEV_TRM290 @@ -343,6 +347,7 @@ {DEVID_PIIX4U2, "PIIX4", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, {DEVID_PIIX4NX, "PIIX4", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, {DEVID_PIIX4U3, "PIIX4", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4U4, "PIIX4", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, {DEVID_VIA_IDE, "VIA_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, {DEVID_VP_IDE, "VP_IDE", PCI_VIA82CXXX, ATA66_VIA82CXXX,INIT_VIA82CXXX, DMA_VIA82CXXX, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, {DEVID_PDC20246,"PDC20246", PCI_PDC202XX, NULL, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 16 }, @@ -367,7 +372,7 @@ {DEVID_AEC6210, "AEC6210", PCI_AEC62XX, NULL, INIT_AEC62XX, DMA_AEC62XX, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, OFF_BOARD, 0 }, {DEVID_AEC6260, "AEC6260", PCI_AEC62XX, ATA66_AEC62XX, INIT_AEC62XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 0 }, {DEVID_AEC6260R,"AEC6260R", PCI_AEC62XX, ATA66_AEC62XX, INIT_AEC62XX, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, OFF_BOARD, 0 }, - {DEVID_W82C105, "W82C105", NULL, NULL, INIT_W82C105, DMA_W82C105, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, ON_BOARD, 0 }, + {DEVID_W82C105, "W82C105", PCI_W82C105, NULL, INIT_W82C105, DMA_W82C105, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, ON_BOARD, 0 }, {DEVID_UM8673F, "UM8673F", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, {DEVID_UM8886A, "UM8886A", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, {DEVID_UM8886BF,"UM8886BF", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, diff -u --recursive --new-file v2.4.5/linux/drivers/ide/ide-tape.c linux/drivers/ide/ide-tape.c --- v2.4.5/linux/drivers/ide/ide-tape.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/ide/ide-tape.c Tue Jun 12 11:09:03 2001 @@ -1,8 +1,10 @@ /* - * linux/drivers/ide/ide-tape.c Version 1.16f Dec 15, 1999 + * linux/drivers/ide/ide-tape.c Version 1.17a Jan, 2001 * * Copyright (C) 1995 - 1999 Gadi Oxman * + * $Header$ + * * This driver was constructed as a student project in the software laboratory * of the faculty of electrical engineering in the Technion - Israel's * Institute Of Technology, with the guide of Avner Lottem and Dr. Ilana David. @@ -274,7 +276,21 @@ * this section correctly, a hypothetical and unwanted situation * is being described) * Ver 1.16f Dec 15 99 Change place of the secondary OnStream header frames. - * + * Ver 1.17 Nov 2000 / Jan 2001 Marcel Mol, marcel@mesa.nl + * - Add idetape_onstream_mode_sense_tape_parameter_page + * function to get tape capacity in frames: tape->capacity. + * - Add support for DI-50 drives( or any DI- drive). + * - 'workaround' for read error/blank block arround block 3000. + * - Implement Early warning for end of media for Onstream. + * - Cosmetic code changes for readability. + * - Idetape_position_tape should not use SKIP bit during + * Onstream read recovery. + * - Add capacity, logical_blk_num and first/last_frame_position + * to /proc/ide/hd?/settings. + * - Module use count was gone in the Linux 2.4 driver. + * Ver 1.17a Apr 2001 Willem Riede osst@riede.org + * - Get drive's actual block size from mode sense block descriptor + * - Limit size of pipeline * * Here are some words from the first releases of hd.c, which are quoted * in ide.c and apply here as well: @@ -384,7 +400,7 @@ * sharing a (fast) ATA-2 disk with any (slow) new ATAPI device. */ -#define IDETAPE_VERSION "1.16f" +#define IDETAPE_VERSION "1.17a" #include #include @@ -421,7 +437,11 @@ #define OS_CONFIG_PARTITION (0xff) #define OS_DATA_PARTITION (0) #define OS_PARTITION_VERSION (1) +#define OS_EW 300 +#define OS_ADR_MINREV 2 +#define OS_DATA_STARTFRAME1 20 +#define OS_DATA_ENDFRAME1 2980 /* * partition */ @@ -512,12 +532,33 @@ } os_header_t; /* + * OnStream Tape Parameters Page + */ +typedef struct { + unsigned page_code :6; /* Page code - Should be 0x2b */ + unsigned reserved1_6 :1; + unsigned ps :1; + __u8 reserved2; + __u8 density; /* kbpi */ + __u8 reserved3,reserved4; + __u16 segtrk; /* segment of per track */ + __u16 trks; /* tracks per tape */ + __u8 reserved5,reserved6,reserved7,reserved8,reserved9,reserved10; +} onstream_tape_paramtr_page_t; + +/* * OnStream ADRL frame */ #define OS_FRAME_SIZE (32 * 1024 + 512) #define OS_DATA_SIZE (32 * 1024) #define OS_AUX_SIZE (512) +/* + * internal error codes for onstream + */ +#define OS_PART_ERROR 2 +#define OS_WRITE_ERROR 1 + #include /**************************** Tunable parameters *****************************/ @@ -559,7 +600,7 @@ * is verified to be stable enough. This will make it much more * esthetic. */ -#define IDETAPE_DEBUG_INFO 0 +#define IDETAPE_DEBUG_INFO 1 #define IDETAPE_DEBUG_LOG 1 #define IDETAPE_DEBUG_LOG_VERBOSE 0 #define IDETAPE_DEBUG_BUGS 1 @@ -949,6 +990,7 @@ int eod_frame_addr; unsigned long cmd_start_time; unsigned long max_cmd_time; + unsigned capacity; /* * Optimize the number of "buffer filling" @@ -1157,7 +1199,7 @@ typedef union { unsigned all :8; struct { - unsigned dma :1; /* Using DMA of PIO */ + unsigned dma :1; /* Using DMA or PIO */ unsigned reserved321 :3; /* Reserved */ unsigned reserved654 :3; /* Reserved (Tag Type) */ unsigned reserved7 :1; /* Reserved */ @@ -1286,8 +1328,11 @@ * packet commands. Those packet commands are still not supported * by ide-tape. */ +#define IDETAPE_BLOCK_DESCRIPTOR 0 #define IDETAPE_CAPABILITIES_PAGE 0x2a +#define IDETAPE_PARAMTR_PAGE 0x2b /* Onstream DI-x0 only */ #define IDETAPE_BLOCK_SIZE_PAGE 0x30 +#define IDETAPE_BUFFER_FILLING_PAGE 0x33 /* * Mode Parameter Header for the MODE SENSE packet command @@ -1428,6 +1473,14 @@ #endif /* IDETAPE_DEBUG_LOG_VERBOSE */ /* + * Function declarations + * + */ +static void idetape_onstream_mode_sense_tape_parameter_page(ide_drive_t *drive, int debug); +static int idetape_chrdev_release (struct inode *inode, struct file *filp); +static void idetape_write_release (struct inode *inode); + +/* * Too bad. The drive wants to send us data which we are not ready to accept. * Just throw it away. */ @@ -1452,7 +1505,8 @@ #endif /* IDETAPE_DEBUG_BUGS */ count = IDE_MIN (bh->b_size - atomic_read(&bh->b_count), bcount); atapi_input_bytes (drive, bh->b_data + atomic_read(&bh->b_count), count); - bcount -= count; atomic_add(count, &bh->b_count); + bcount -= count; + atomic_add(count, &bh->b_count); if (atomic_read(&bh->b_count) == bh->b_size) { bh = bh->b_reqnext; if (bh) @@ -1476,7 +1530,9 @@ #endif /* IDETAPE_DEBUG_BUGS */ count = IDE_MIN (pc->b_count, bcount); atapi_output_bytes (drive, pc->b_data, count); - bcount -= count; pc->b_data += count; pc->b_count -= count; + bcount -= count; + pc->b_data += count; + pc->b_count -= count; if (!pc->b_count) { pc->bh = bh = bh->b_reqnext; if (bh) { @@ -1577,20 +1633,23 @@ * to analyze the request sense. We currently do not utilize this * information. */ -static void idetape_analyze_error (ide_drive_t *drive,idetape_request_sense_result_t *result) +static void idetape_analyze_error (ide_drive_t *drive, idetape_request_sense_result_t *result) { idetape_tape_t *tape = drive->driver_data; idetape_pc_t *pc = tape->failed_pc; - tape->sense = *result; - tape->sense_key = result->sense_key; tape->asc = result->asc; tape->ascq = result->ascq; + tape->sense = *result; + tape->sense_key = result->sense_key; + tape->asc = result->asc; + tape->ascq = result->ascq; #if IDETAPE_DEBUG_LOG /* * Without debugging, we only log an error if we decided to * give up retrying. */ if (tape->debug_level >= 1) - printk (KERN_INFO "ide-tape: pc = %x, sense key = %x, asc = %x, ascq = %x\n",pc->c[0],result->sense_key,result->asc,result->ascq); + printk (KERN_INFO "ide-tape: pc = %x, sense key = %x, asc = %x, ascq = %x\n", + pc->c[0], result->sense_key, result->asc, result->ascq); #if IDETAPE_DEBUG_LOG_VERBOSE if (tape->debug_level >= 1) printk (KERN_INFO "ide-tape: pc = %s, sense key = %x, asc = %x, ascq = %x\n", @@ -1660,7 +1719,7 @@ static void idetape_active_next_stage (ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage=tape->next_stage; + idetape_stage_t *stage = tape->next_stage; struct request *rq = &stage->rq; #if IDETAPE_DEBUG_LOG @@ -1676,9 +1735,9 @@ rq->buffer = NULL; rq->bh = stage->bh; - tape->active_data_request=rq; - tape->active_stage=stage; - tape->next_stage=stage->next; + tape->active_data_request = rq; + tape->active_stage = stage; + tape->next_stage = stage->next; } /* @@ -1756,12 +1815,12 @@ return; } #endif /* IDETAPE_DEBUG_BUGS */ - stage=tape->first_stage; - tape->first_stage=stage->next; + stage = tape->first_stage; + tape->first_stage = stage->next; idetape_kfree_stage (tape, stage); tape->nr_stages--; if (tape->first_stage == NULL) { - tape->last_stage=NULL; + tape->last_stage = NULL; #if IDETAPE_DEBUG_BUGS if (tape->next_stage != NULL) printk (KERN_ERR "ide-tape: bug: tape->next_stage != NULL\n"); @@ -1821,12 +1880,12 @@ } #endif if (tape->onstream && !tape->raw) { - if (tape->first_frame_position == 0xba4) { + if (tape->first_frame_position == OS_DATA_ENDFRAME1) { #if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk("ide-tape: %s: skipping over config parition..\n", tape->name); + if (tape->debug_level >= 2) + printk("ide-tape: %s: skipping over config parition..\n", tape->name); #endif - tape->onstream_write_error = 2; + tape->onstream_write_error = OS_PART_ERROR; if (tape->sem) up(tape->sem); } @@ -1839,7 +1898,7 @@ if (tape->onstream && !tape->raw && error == IDETAPE_ERROR_GENERAL && tape->sense.sense_key == 3) { clear_bit (IDETAPE_PIPELINE_ERROR, &tape->flags); printk(KERN_ERR "ide-tape: %s: write error, enabling error recovery\n", tape->name); - tape->onstream_write_error = 1; + tape->onstream_write_error = OS_WRITE_ERROR; remove_stage = 0; tape->nr_pending_stages++; tape->next_stage = tape->first_stage; @@ -1883,11 +1942,11 @@ printk (KERN_INFO "ide-tape: Reached idetape_request_sense_callback\n"); #endif /* IDETAPE_DEBUG_LOG */ if (!tape->pc->error) { - idetape_analyze_error (drive,(idetape_request_sense_result_t *) tape->pc->buffer); - idetape_end_request (1,HWGROUP (drive)); + idetape_analyze_error (drive, (idetape_request_sense_result_t *) tape->pc->buffer); + idetape_end_request (1, HWGROUP (drive)); } else { printk (KERN_ERR "ide-tape: Error in REQUEST SENSE itself - Aborting request!\n"); - idetape_end_request (0,HWGROUP (drive)); + idetape_end_request (0, HWGROUP (drive)); } return ide_stopped; } @@ -1980,7 +2039,7 @@ idetape_status_reg_t status; idetape_bcount_reg_t bcount; idetape_ireason_reg_t ireason; - idetape_pc_t *pc=tape->pc; + idetape_pc_t *pc = tape->pc; unsigned int temp; unsigned long cmd_time; @@ -2011,7 +2070,7 @@ */ set_bit (PC_DMA_ERROR, &pc->flags); } else if (!status.b.check) { - pc->actually_transferred=pc->request_transfer; + pc->actually_transferred = pc->request_transfer; idetape_update_buffers (pc); } #if IDETAPE_DEBUG_LOG @@ -2064,7 +2123,7 @@ return ide_stopped; } if (tape->failed_pc == pc) - tape->failed_pc=NULL; + tape->failed_pc = NULL; return pc->callback(drive); /* Command finished - Call the callback function */ } #ifdef CONFIG_BLK_DEV_IDEDMA @@ -2075,9 +2134,9 @@ return ide_do_reset (drive); } #endif /* CONFIG_BLK_DEV_IDEDMA */ - bcount.b.high=IN_BYTE (IDE_BCOUNTH_REG); /* Get the number of bytes to transfer */ - bcount.b.low=IN_BYTE (IDE_BCOUNTL_REG); /* on this interrupt */ - ireason.all=IN_BYTE (IDE_IREASON_REG); + bcount.b.high = IN_BYTE (IDE_BCOUNTH_REG); /* Get the number of bytes to transfer */ + bcount.b.low = IN_BYTE (IDE_BCOUNTL_REG); /* on this interrupt */ + ireason.all = IN_BYTE (IDE_IREASON_REG); if (ireason.b.cod) { printk (KERN_ERR "ide-tape: CoD != 0 in idetape_pc_intr\n"); @@ -2093,8 +2152,8 @@ if ( temp > pc->request_transfer) { if (temp > pc->buffer_size) { printk (KERN_ERR "ide-tape: The tape wants to send us more data than expected - discarding data\n"); - idetape_discard_data (drive,bcount.all); - ide_set_handler (drive,&idetape_pc_intr,IDETAPE_WAIT_CMD,NULL); + idetape_discard_data (drive, bcount.all); + ide_set_handler (drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); return ide_started; } #if IDETAPE_DEBUG_LOG @@ -2114,13 +2173,13 @@ else atapi_input_bytes (drive,pc->current_position,bcount.all); /* Read the current buffer */ } - pc->actually_transferred+=bcount.all; /* Update the current position */ + pc->actually_transferred += bcount.all; /* Update the current position */ pc->current_position+=bcount.all; #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 2) printk(KERN_INFO "ide-tape: [cmd %x] transferred %d bytes on that interrupt\n", pc->c[0], bcount.all); #endif - ide_set_handler (drive,&idetape_pc_intr,IDETAPE_WAIT_CMD,NULL); /* And set the interrupt handler again */ + ide_set_handler (drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); /* And set the interrupt handler again */ return ide_started; } @@ -2178,7 +2237,7 @@ printk (KERN_ERR "ide-tape: Strange, packet command initiated yet DRQ isn't asserted\n"); return startstop; } - ireason.all=IN_BYTE (IDE_IREASON_REG); + ireason.all = IN_BYTE (IDE_IREASON_REG); while (retries-- && (!ireason.b.cod || ireason.b.io)) { printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while issuing a packet command, retrying\n"); udelay(100); @@ -2203,7 +2262,7 @@ { idetape_tape_t *tape = drive->driver_data; idetape_bcount_reg_t bcount; - int dma_ok=0; + int dma_ok = 0; #if IDETAPE_DEBUG_BUGS if (tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD && pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) { @@ -2212,8 +2271,8 @@ #endif /* IDETAPE_DEBUG_BUGS */ if (tape->failed_pc == NULL && pc->c[0] != IDETAPE_REQUEST_SENSE_CMD) - tape->failed_pc=pc; - tape->pc=pc; /* Set the current packet command */ + tape->failed_pc = pc; + tape->pc = pc; /* Set the current packet command */ if (pc->retries > IDETAPE_MAX_PC_RETRIES || test_bit (PC_ABORT, &pc->flags)) { /* @@ -2223,24 +2282,25 @@ * example). */ if (!test_bit (PC_ABORT, &pc->flags)) { - if (!(pc->c[0] == 0 && tape->sense_key == 2 && tape->asc == 4 && (tape->ascq == 1 || tape->ascq == 8))) { + if (!(pc->c[0] == IDETAPE_TEST_UNIT_READY_CMD && tape->sense_key == 2 && + tape->asc == 4 && (tape->ascq == 1 || tape->ascq == 8))) { printk (KERN_ERR "ide-tape: %s: I/O error, pc = %2x, key = %2x, asc = %2x, ascq = %2x\n", tape->name, pc->c[0], tape->sense_key, tape->asc, tape->ascq); - if (tape->onstream && pc->c[0] == 8 && tape->sense_key == 3 && tape->asc == 0x11) /* AJN-1: 11 should be 0x11 */ + if (tape->onstream && pc->c[0] == IDETAPE_READ_CMD && tape->sense_key == 3 && tape->asc == 0x11) /* AJN-1: 11 should be 0x11 */ printk(KERN_ERR "ide-tape: %s: enabling read error recovery\n", tape->name); } pc->error = IDETAPE_ERROR_GENERAL; /* Giving up */ } - tape->failed_pc=NULL; + tape->failed_pc = NULL; return pc->callback(drive); } #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 2) - printk (KERN_INFO "ide-tape: Retry number - %d\n",pc->retries); + printk (KERN_INFO "ide-tape: Retry number - %d\n", pc->retries); #endif /* IDETAPE_DEBUG_LOG */ pc->retries++; - pc->actually_transferred=0; /* We haven't transferred any data yet */ + pc->actually_transferred = 0; /* We haven't transferred any data yet */ pc->current_position=pc->buffer; bcount.all=pc->request_transfer; /* Request to transfer the entire buffer at once */ @@ -2250,15 +2310,15 @@ (void) HWIF(drive)->dmaproc(ide_dma_off, drive); } if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) - dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive); + dma_ok = !HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive); #endif /* CONFIG_BLK_DEV_IDEDMA */ 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); + 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); #ifdef CONFIG_BLK_DEV_IDEDMA if (dma_ok) { /* Begin DMA, if necessary */ set_bit (PC_DMA_IN_PROGRESS, &pc->flags); @@ -2287,7 +2347,7 @@ printk (KERN_INFO "ide-tape: Reached idetape_pc_callback\n"); #endif /* IDETAPE_DEBUG_LOG */ - idetape_end_request (tape->pc->error ? 0:1, HWGROUP(drive)); + idetape_end_request (tape->pc->error ? 0 : 1, HWGROUP(drive)); return ide_stopped; } @@ -2298,11 +2358,14 @@ { idetape_init_pc (pc); pc->c[0] = IDETAPE_MODE_SENSE_CMD; - pc->c[1] = 8; /* DBD = 1 - Don't return block descriptors for now */ + if (page_code != IDETAPE_BLOCK_DESCRIPTOR) + pc->c[1] = 8; /* DBD = 1 - Don't return block descriptors */ pc->c[2] = page_code; pc->c[3] = 255; /* Don't limit the returned information */ pc->c[4] = 255; /* (We will just discard data in that case) */ - if (page_code == IDETAPE_CAPABILITIES_PAGE) + if (page_code == IDETAPE_BLOCK_DESCRIPTOR) + pc->request_transfer = 12; + else if (page_code == IDETAPE_CAPABILITIES_PAGE) pc->request_transfer = 24; else pc->request_transfer = 50; @@ -2333,7 +2396,7 @@ if (tape->debug_level >= 1) printk(KERN_INFO "ide-tape: buffer fill callback, %d/%d\n", tape->cur_frames, tape->max_frames); #endif - idetape_end_request (tape->pc->error ? 0:1, HWGROUP(drive)); + idetape_end_request (tape->pc->error ? 0 : 1, HWGROUP(drive)); return ide_stopped; } @@ -2344,7 +2407,7 @@ pc = idetape_next_pc_storage (drive); rq = idetape_next_rq_storage (drive); - idetape_create_mode_sense_cmd (pc, 0x33); + idetape_create_mode_sense_cmd (pc, IDETAPE_BUFFER_FILLING_PAGE); pc->callback = idetape_onstream_buffer_fill_callback; idetape_queue_pc_head (drive, pc, rq); } @@ -2564,7 +2627,7 @@ * We do not support buffer cache originated requests. */ printk (KERN_NOTICE "ide-tape: %s: Unsupported command in request queue (%d)\n", drive->name, rq->cmd); - ide_end_request (0,HWGROUP (drive)); /* Let the common code handle it */ + ide_end_request (0, HWGROUP (drive)); /* Let the common code handle it */ return ide_stopped; } @@ -2578,7 +2641,7 @@ if (postponed_rq != NULL) if (rq != postponed_rq) { printk (KERN_ERR "ide-tape: ide-tape.c bug - Two DSC requests were queued\n"); - idetape_end_request (0,HWGROUP (drive)); + idetape_end_request (0, HWGROUP (drive)); return ide_stopped; } #endif /* IDETAPE_DEBUG_BUGS */ @@ -2624,8 +2687,15 @@ tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time); calculate_speeds(drive); if (tape->onstream && tape->max_frames && - ((rq->cmd == IDETAPE_WRITE_RQ && (tape->cur_frames == tape->max_frames || (tape->speed_control && tape->cur_frames > 5 && (tape->insert_speed > tape->max_insert_speed || (0 /* tape->cur_frames > 30 && tape->tape_still_time > 200 */))))) || - (rq->cmd == IDETAPE_READ_RQ && (tape->cur_frames == 0 || (tape->speed_control && (tape->cur_frames < tape->max_frames - 5) && tape->insert_speed > tape->max_insert_speed)) && rq->nr_sectors))) { + ((rq->cmd == IDETAPE_WRITE_RQ && + ( tape->cur_frames == tape->max_frames || + ( tape->speed_control && tape->cur_frames > 5 && + (tape->insert_speed > tape->max_insert_speed || + (0 /* tape->cur_frames > 30 && tape->tape_still_time > 200 */) ) ) ) ) || + (rq->cmd == IDETAPE_READ_RQ && + ( tape->cur_frames == 0 || + ( tape->speed_control && (tape->cur_frames < tape->max_frames - 5) && + tape->insert_speed > tape->max_insert_speed ) ) && rq->nr_sectors) ) ) { #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 4) printk(KERN_INFO "ide-tape: postponing request, cmd %d, cur %d, max %d\n", @@ -2672,7 +2742,7 @@ if (jiffies > tape->last_buffer_fill + 5 * HZ / 100) tape->req_buffer_fill = 1; } - pc=idetape_next_pc_storage (drive); + pc = idetape_next_pc_storage (drive); idetape_create_read_cmd (tape, pc, rq->current_nr_sectors, rq->bh); break; case IDETAPE_WRITE_RQ: @@ -2689,12 +2759,12 @@ tape->req_buffer_fill = 1; calculate_speeds(drive); } - pc=idetape_next_pc_storage (drive); + pc = idetape_next_pc_storage (drive); idetape_create_write_cmd (tape, pc, rq->current_nr_sectors, rq->bh); break; case IDETAPE_READ_BUFFER_RQ: tape->postpone_cnt = 0; - pc=idetape_next_pc_storage (drive); + pc = idetape_next_pc_storage (drive); idetape_create_read_buffer_cmd (tape, pc, rq->current_nr_sectors, rq->bh); break; case IDETAPE_ABORTED_WRITE_RQ: @@ -2710,7 +2780,7 @@ idetape_end_request (IDETAPE_ERROR_EOD, HWGROUP(drive)); return ide_stopped; case IDETAPE_PC_RQ1: - pc=(idetape_pc_t *) rq->buffer; + pc = (idetape_pc_t *) rq->buffer; rq->cmd = IDETAPE_PC_RQ2; break; case IDETAPE_PC_RQ2: @@ -2718,7 +2788,7 @@ return ide_stopped; default: printk (KERN_ERR "ide-tape: bug in IDETAPE_RQ_CMD macro\n"); - idetape_end_request (0,HWGROUP (drive)); + idetape_end_request (0, HWGROUP (drive)); return ide_stopped; } return idetape_issue_packet_command (drive, pc); @@ -2844,7 +2914,9 @@ #endif /* IDETAPE_DEBUG_BUGS */ count = IDE_MIN (bh->b_size - atomic_read(&bh->b_count), n); copy_from_user (bh->b_data + atomic_read(&bh->b_count), buf, count); - n -= count; atomic_add(count, &bh->b_count); buf += count; + n -= count; + atomic_add(count, &bh->b_count); + buf += count; if (atomic_read(&bh->b_count) == bh->b_size) { bh = bh->b_reqnext; if (bh) @@ -2868,7 +2940,10 @@ #endif /* IDETAPE_DEBUG_BUGS */ count = IDE_MIN (tape->b_count, n); copy_to_user (buf, tape->b_data, count); - n -= count; tape->b_data += count; tape->b_count -= count; buf += count; + n -= count; + tape->b_data += count; + tape->b_count -= count; + buf += count; if (!tape->b_count) { tape->bh = bh = bh->b_reqnext; if (bh) { @@ -2920,10 +2995,10 @@ if (tape->last_stage != NULL) tape->last_stage->next=stage; else - tape->first_stage=tape->next_stage=stage; - tape->last_stage=stage; + tape->first_stage = tape->next_stage=stage; + tape->last_stage = stage; if (tape->next_stage == NULL) - tape->next_stage=tape->last_stage; + tape->next_stage = tape->last_stage; tape->nr_stages++; tape->nr_pending_stages++; spin_unlock_irqrestore(&tape->spinlock, flags); @@ -2953,26 +3028,21 @@ par->par_desc_ver = OS_PARTITION_VERSION; par->wrt_pass_cntr = htons(0xffff); par->first_frame_addr = htonl(0); - par->last_frame_addr = htonl(0xbb7); + par->last_frame_addr = htonl(0xbb7); /* 2999 */ + aux->frame_seq_num = htonl(0); + aux->logical_blk_num_high = htonl(0); + aux->logical_blk_num = htonl(0); + aux->next_mark_addr = htonl(tape->first_mark_addr); } else { aux->update_frame_cntr = htonl(0); par->partition_num = OS_DATA_PARTITION; par->par_desc_ver = OS_PARTITION_VERSION; par->wrt_pass_cntr = htons(tape->wrt_pass_cntr); - par->first_frame_addr = htonl(0x14); - par->last_frame_addr = htonl(19239 * 24); - } - if (frame_type != OS_FRAME_TYPE_HEADER) { + par->first_frame_addr = htonl(OS_DATA_STARTFRAME1); + par->last_frame_addr = htonl(tape->capacity); aux->frame_seq_num = htonl(logical_blk_num); aux->logical_blk_num_high = htonl(0); aux->logical_blk_num = htonl(logical_blk_num); - } else { - aux->frame_seq_num = htonl(0); - aux->logical_blk_num_high = htonl(0); - aux->logical_blk_num = htonl(0); - } - - if (frame_type != OS_FRAME_TYPE_HEADER) { dat->dat_sz = 8; dat->reserved1 = 0; dat->entry_cnt = 1; @@ -2987,11 +3057,10 @@ else dat->dat_list[0].flags = OS_DAT_FLAGS_DATA; dat->dat_list[0].reserved = 0; - } else - aux->next_mark_addr = htonl(tape->first_mark_addr); - aux->filemark_cnt = ntohl(tape->filemark_cnt); - aux->phys_fm = ntohl(0xffffffff); - aux->last_mark_addr = ntohl(tape->last_mark_addr); + } + aux->filemark_cnt = ntohl(tape->filemark_cnt); /* shouldn't this be htonl ?? */ + aux->phys_fm = ntohl(0xffffffff); /* shouldn't this be htonl ?? */ + aux->last_mark_addr = ntohl(tape->last_mark_addr); /* shouldn't this be htonl ?? */ } /* @@ -3026,10 +3095,10 @@ idetape_tape_t *tape = drive->driver_data; idetape_read_position_result_t *result; -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) +//#if IDETAPE_DEBUG_LOG +// if (tape->debug_level >= 4) printk (KERN_INFO "ide-tape: Reached idetape_read_position_callback\n"); -#endif /* IDETAPE_DEBUG_LOG */ +//#endif /* IDETAPE_DEBUG_LOG */ if (!tape->pc->error) { result = (idetape_read_position_result_t *) tape->pc->buffer; @@ -3042,7 +3111,7 @@ if (result->bpu) { printk (KERN_INFO "ide-tape: Block location is unknown to the tape\n"); clear_bit (IDETAPE_ADDRESS_VALID, &tape->flags); - idetape_end_request (0,HWGROUP (drive)); + idetape_end_request (0, HWGROUP (drive)); } else { #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 2) @@ -3053,10 +3122,10 @@ tape->last_frame_position = ntohl (result->last_block); tape->blocks_in_buffer = result->blocks_in_buffer[2]; set_bit (IDETAPE_ADDRESS_VALID, &tape->flags); - idetape_end_request (1,HWGROUP (drive)); + idetape_end_request (1, HWGROUP (drive)); } } else { - idetape_end_request (0,HWGROUP (drive)); + idetape_end_request (0, HWGROUP (drive)); } return ide_stopped; } @@ -3076,8 +3145,8 @@ idetape_init_pc (pc); pc->c[0] = IDETAPE_WRITE_FILEMARK_CMD; if (tape->onstream) - pc->c[1] = 1; - pc->c[4] = write_filemark; + pc->c[1] = 1; /* Immed bit */ + pc->c[4] = write_filemark; /* not used for OnStream ?? */ set_bit (PC_WAIT_FOR_DSC, &pc->flags); pc->callback = &idetape_pc_callback; } @@ -3109,7 +3178,7 @@ * the request to the request list without waiting for it to be serviced ! * In that case, we usually use idetape_queue_pc_head. */ -static int __idetape_queue_pc_tail (ide_drive_t *drive,idetape_pc_t *pc) +static int __idetape_queue_pc_tail (ide_drive_t *drive, idetape_pc_t *pc) { struct request rq; @@ -3150,7 +3219,7 @@ return 0; if (tape->sense_key == 2 && tape->asc == 4 && tape->ascq == 2) { idetape_create_load_unload_cmd (drive, &pc, IDETAPE_LU_LOAD_MASK); - __idetape_queue_pc_tail(drive,&pc); + __idetape_queue_pc_tail(drive, &pc); idetape_create_test_unit_ready_cmd(&pc); if (!__idetape_queue_pc_tail(drive, &pc)) return 0; @@ -3169,7 +3238,8 @@ int rc; rc = __idetape_queue_pc_tail(drive, pc); - if (rc) return rc; + if (rc) + return rc; if (tape->onstream && test_bit(PC_WAIT_FOR_DSC, &pc->flags)) rc = idetape_wait_ready(drive, 60 * 10 * HZ); /* AJN-4: Changed from 5 to 10 minutes; because retension takes approx. 8:20 with Onstream 30GB tape */ @@ -3182,7 +3252,7 @@ int rc; idetape_create_write_filemark_cmd(drive, &pc, 0); - if ((rc = idetape_queue_pc_tail (drive,&pc))) + if ((rc = idetape_queue_pc_tail (drive, &pc))) return rc; idetape_wait_ready(drive, 60 * 5 * HZ); return 0; @@ -3202,11 +3272,16 @@ idetape_pc_t pc; int position; +//#if IDETAPE_DEBUG_LOG +// if (tape->debug_level >= 4) + printk (KERN_INFO "ide-tape: Reached idetape_read_position\n"); +//#endif /* IDETAPE_DEBUG_LOG */ + #ifdef NO_LONGER_REQUIRED idetape_flush_tape_buffers(drive); #endif idetape_create_read_position_cmd(&pc); - if (idetape_queue_pc_tail (drive,&pc)) + if (idetape_queue_pc_tail (drive, &pc)) return -1; position = tape->first_frame_position; #ifdef NO_LONGER_REQUIRED @@ -3231,12 +3306,17 @@ idetape_init_pc (pc); pc->c[0] = IDETAPE_LOCATE_CMD; if (tape->onstream) - pc->c[1] = 1; + pc->c[1] = 1; /* Immediate bit */ else pc->c[1] = 2; put_unaligned (htonl (block), (unsigned int *) &pc->c[3]); pc->c[8] = partition; if (tape->onstream) + /* + * Set SKIP bit. + * In case of write error this will write buffered + * data in the drive to this new position! + */ pc->c[9] = skip << 7; set_bit (PC_WAIT_FOR_DSC, &pc->flags); pc->callback = &idetape_pc_callback; @@ -3307,11 +3387,12 @@ __idetape_discard_read_pipeline(drive); idetape_wait_ready(drive, 60 * 5 * HZ); idetape_create_locate_cmd (drive, &pc, block, partition, skip); - retval=idetape_queue_pc_tail (drive,&pc); - if (retval) return (retval); + retval = idetape_queue_pc_tail (drive, &pc); + if (retval) + return (retval); idetape_create_read_position_cmd (&pc); - return (idetape_queue_pc_tail (drive,&pc)); + return (idetape_queue_pc_tail (drive, &pc)); } static void idetape_discard_read_pipeline (ide_drive_t *drive, int restore_position) @@ -3339,7 +3420,7 @@ { idetape_pc_t pc; - idetape_create_mode_sense_cmd (&pc, 0x33); + idetape_create_mode_sense_cmd (&pc, IDETAPE_BUFFER_FILLING_PAGE); pc.callback = idetape_onstream_buffer_fill_callback; (void) idetape_queue_pc_tail(drive, &pc); } @@ -3447,33 +3528,41 @@ idetape_tape_t *tape = drive->driver_data; unsigned int block; - if (tape->onstream_write_error == 1) { - printk(KERN_ERR "ide-tape: %s: detected physical bad block at %u\n", tape->name, ntohl(tape->sense.information)); - block = ntohl(tape->sense.information) + 80; + if (tape->onstream_write_error == OS_WRITE_ERROR) { + printk(KERN_ERR "ide-tape: %s: onstream_write_error_recovery: detected physical bad block at %u, logical %u first frame %u last_frame %u bufblocks %u stages %u skipping %u frames\n", + tape->name, ntohl(tape->sense.information), tape->logical_blk_num, + tape->first_frame_position, tape->last_frame_position, + tape->blocks_in_buffer, tape->nr_stages, + (ntohl(tape->sense.command_specific) >> 16) & 0xff ); + block = ntohl(tape->sense.information) + ((ntohl(tape->sense.command_specific) >> 16) & 0xff); idetape_update_stats(drive); printk(KERN_ERR "ide-tape: %s: relocating %d buffered logical blocks to physical block %u\n", tape->name, tape->cur_frames, block); +#if 0 /* isn't once enough ??? MM */ idetape_update_stats(drive); +#endif if (tape->firmware_revision_num >= 106) idetape_position_tape(drive, block, 0, 1); else { idetape_onstream_read_back_buffer(drive); idetape_position_tape(drive, block, 0, 0); } +#if 0 /* already done in idetape_position_tape MM */ idetape_read_position(drive); +#endif #if ONSTREAM_DEBUG if (tape->debug_level >= 1) printk(KERN_ERR "ide-tape: %s: positioning complete, cur_frames %d, pos %d, tape pos %d\n", tape->name, tape->cur_frames, tape->first_frame_position, tape->last_frame_position); #endif - } else if (tape->onstream_write_error == 2) { + } else if (tape->onstream_write_error == OS_PART_ERROR) { #if ONSTREAM_DEBUG if (tape->debug_level >= 1) printk(KERN_INFO "ide-tape: %s: skipping over config partition\n", tape->name); #endif idetape_flush_tape_buffers(drive); block = idetape_read_position(drive); - if (block != 0xba4) - printk(KERN_ERR "ide-tape: warning, current position %d, expected %d\n", block, 0xba4); - idetape_position_tape(drive, 0xbb8, 0, 0); + if (block != OS_DATA_ENDFRAME1) + printk(KERN_ERR "ide-tape: warning, current position %d, expected %d\n", block, OS_DATA_ENDFRAME1); + idetape_position_tape(drive, 0xbb8, 0, 0); /* 3000 */ } tape->onstream_write_error = 0; } @@ -3572,48 +3661,48 @@ return 1; } if (rq->errors == IDETAPE_ERROR_GENERAL) { - printk(KERN_INFO "ide-tape: %s: skipping frame, read error\n", tape->name); + printk(KERN_INFO "ide-tape: %s: skipping frame %d, read error\n", tape->name, tape->first_frame_position); return 0; } if (rq->errors == IDETAPE_ERROR_EOD) { - printk(KERN_INFO "ide-tape: %s: skipping frame, eod\n", tape->name); + printk(KERN_INFO "ide-tape: %s: skipping frame %d, eod\n", tape->name, tape->first_frame_position); return 0; } if (ntohl(aux->format_id) != 0) { - printk(KERN_INFO "ide-tape: %s: skipping frame, format_id %u\n", tape->name, ntohl(aux->format_id)); + printk(KERN_INFO "ide-tape: %s: skipping frame %d, format_id %u\n", tape->name, tape->first_frame_position, ntohl(aux->format_id)); return 0; } if (memcmp(aux->application_sig, tape->application_sig, 4) != 0) { - printk(KERN_INFO "ide-tape: %s: skipping frame, incorrect application signature\n", tape->name); + printk(KERN_INFO "ide-tape: %s: skipping frame %d, incorrect application signature\n", tape->name, tape->first_frame_position); return 0; } if (aux->frame_type != OS_FRAME_TYPE_DATA && aux->frame_type != OS_FRAME_TYPE_EOD && aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "ide-tape: %s: skipping frame, frame type %x\n", tape->name, aux->frame_type); + printk(KERN_INFO "ide-tape: %s: skipping frame %d, frame type %x\n", tape->name, tape->first_frame_position, aux->frame_type); return 0; } if (par->partition_num != OS_DATA_PARTITION) { if (!tape->linux_media || tape->linux_media_version != 2) { - printk(KERN_INFO "ide-tape: %s: skipping frame, partition num %d\n", tape->name, par->partition_num); + printk(KERN_INFO "ide-tape: %s: skipping frame %d, partition num %d\n", tape->name, tape->first_frame_position, par->partition_num); return 0; } } if (par->par_desc_ver != OS_PARTITION_VERSION) { - printk(KERN_INFO "ide-tape: %s: skipping frame, partition version %d\n", tape->name, par->par_desc_ver); + printk(KERN_INFO "ide-tape: %s: skipping frame %d, partition version %d\n", tape->name, tape->first_frame_position, par->par_desc_ver); return 0; } if (ntohs(par->wrt_pass_cntr) != tape->wrt_pass_cntr) { - printk(KERN_INFO "ide-tape: %s: skipping frame, wrt_pass_cntr %d (expected %d)(logical_blk_num %u)\n", tape->name, ntohs(par->wrt_pass_cntr), tape->wrt_pass_cntr, ntohl(aux->logical_blk_num)); + printk(KERN_INFO "ide-tape: %s: skipping frame %d, wrt_pass_cntr %d (expected %d)(logical_blk_num %u)\n", tape->name, tape->first_frame_position, ntohs(par->wrt_pass_cntr), tape->wrt_pass_cntr, ntohl(aux->logical_blk_num)); return 0; } if (aux->frame_seq_num != aux->logical_blk_num) { - printk(KERN_INFO "ide-tape: %s: skipping frame, seq != logical\n", tape->name); + printk(KERN_INFO "ide-tape: %s: skipping frame %d, seq != logical\n", tape->name, tape->first_frame_position); return 0; } if (logical_blk_num != -1 && ntohl(aux->logical_blk_num) != logical_blk_num) { if (!quiet) - printk(KERN_INFO "ide-tape: %s: skipping frame, logical_blk_num %u (expected %d)\n", tape->name, ntohl(aux->logical_blk_num), logical_blk_num); + printk(KERN_INFO "ide-tape: %s: skipping frame %d, logical_blk_num %u (expected %d)\n", tape->name, tape->first_frame_position, ntohl(aux->logical_blk_num), logical_blk_num); return 0; } if (aux->frame_type == OS_FRAME_TYPE_MARKER) { @@ -3689,7 +3778,7 @@ idetape_switch_buffers (tape, new_stage); idetape_init_stage(drive, new_stage, OS_FRAME_TYPE_DATA, tape->logical_blk_num); tape->logical_blk_num++; - idetape_add_stage_tail (drive,new_stage); + idetape_add_stage_tail (drive, new_stage); tape->pipeline_head++; #if USE_IOTRACE IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor); @@ -3766,7 +3855,7 @@ } #endif /* IDETAPE_DEBUG_BUGS */ if (tape->merge_stage_size) { - blocks=tape->merge_stage_size/tape->tape_block_size; + blocks = tape->merge_stage_size / tape->tape_block_size; if (tape->merge_stage_size % tape->tape_block_size) { blocks++; i = tape->tape_block_size - tape->merge_stage_size % tape->tape_block_size; @@ -3797,7 +3886,7 @@ tape->merge_stage = NULL; } clear_bit (IDETAPE_PIPELINE_ERROR, &tape->flags); - tape->chrdev_direction=idetape_direction_none; + tape->chrdev_direction = idetape_direction_none; /* * On the next backup, perform the feedback loop again. @@ -3874,13 +3963,13 @@ rq.sector = tape->first_frame_position; rq.nr_sectors = rq.current_nr_sectors = blocks; if (!test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags) && tape->nr_stages <= max_stages) { - new_stage=idetape_kmalloc_stage (tape); + new_stage = idetape_kmalloc_stage (tape); while (new_stage != NULL) { - new_stage->rq=rq; - idetape_add_stage_tail (drive,new_stage); + new_stage->rq = rq; + idetape_add_stage_tail (drive, new_stage); if (tape->nr_stages >= max_stages) break; - new_stage=idetape_kmalloc_stage (tape); + new_stage = idetape_kmalloc_stage (tape); } } if (!idetape_pipeline_active(tape)) { @@ -3922,16 +4011,23 @@ #endif clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags); position = idetape_read_position(drive); + printk(KERN_INFO "ide-tape: %s: blank block detected at %d\n", tape->name, position); if (position >= 3000 && position < 3080) - position += 32; - if (position >= 2980 && position < 3000) + position += 32; /* Why is this check and number ??? MM */ + if (position >= OS_DATA_ENDFRAME1 && position < 3000) position = 3000; else + /* + * compensate for write errors that generally skip 80 frames, + * expect around 20 read errors in a row... + */ position += 60; - if (position >= 2980 && position < 3000) + if (position >= OS_DATA_ENDFRAME1 && position < 3000) position = 3000; - printk(KERN_INFO "ide-tape: %s: blank block detected, positioning tape to block %d\n", tape->name, position); - idetape_position_tape(drive, position, 0, 1); + printk(KERN_INFO "ide-tape: %s: positioning tape to block %d\n", tape->name, position); + if (position == 3000) /* seems to be needed to correctly position at block 3000 MM */ + idetape_position_tape(drive, 0, 0, 0); + idetape_position_tape(drive, position, 0, 0); cnt += 40; continue; } else @@ -4089,12 +4185,14 @@ #endif /* IDETAPE_DEBUG_LOG */ idetape_create_rewind_cmd (drive, &pc); - retval=idetape_queue_pc_tail (drive,&pc); - if (retval) return retval; + retval = idetape_queue_pc_tail (drive, &pc); + if (retval) + return retval; idetape_create_read_position_cmd (&pc); - retval = idetape_queue_pc_tail (drive,&pc); - if (retval) return retval; + retval = idetape_queue_pc_tail (drive, &pc); + if (retval) + return retval; tape->logical_blk_num = 0; return 0; } @@ -4412,7 +4510,7 @@ switch (mt_op) { case MTFSF: idetape_create_space_cmd (&pc,mt_count-count,IDETAPE_SPACE_OVER_FILEMARK); - return (idetape_queue_pc_tail (drive,&pc)); + return (idetape_queue_pc_tail (drive, &pc)); case MTFSFM: if (!tape->capabilities.sprev) return (-EIO); @@ -4423,7 +4521,7 @@ if (!tape->capabilities.sprev) return (-EIO); idetape_create_space_cmd (&pc,-(mt_count+count),IDETAPE_SPACE_OVER_FILEMARK); - return (idetape_queue_pc_tail (drive,&pc)); + return (idetape_queue_pc_tail (drive, &pc)); case MTBSFM: if (!tape->capabilities.sprev) return (-EIO); @@ -4460,7 +4558,7 @@ struct inode *inode = file->f_dentry->d_inode; ide_drive_t *drive = get_drive_ptr (inode->i_rdev); idetape_tape_t *tape = drive->driver_data; - ssize_t bytes_read,temp,actually_read=0, rc; + ssize_t bytes_read,temp, actually_read = 0, rc; if (ppos != &file->f_pos) { /* "A request was outside the capabilities of the device." */ @@ -4482,28 +4580,32 @@ } if ((rc = idetape_initiate_read(drive, tape->max_stages)) < 0) return rc; - if (count==0) + if (count == 0) return (0); if (tape->merge_stage_size) { - actually_read=IDE_MIN (tape->merge_stage_size,count); + actually_read = IDE_MIN (tape->merge_stage_size, count); idetape_copy_stage_to_user (tape, buf, tape->merge_stage, actually_read); - buf += actually_read; tape->merge_stage_size -= actually_read; count-=actually_read; + buf += actually_read; + tape->merge_stage_size -= actually_read; + count -= actually_read; } while (count >= tape->stage_size) { - bytes_read=idetape_add_chrdev_read_request (drive, tape->capabilities.ctl); + bytes_read = idetape_add_chrdev_read_request (drive, tape->capabilities.ctl); if (bytes_read <= 0) goto finish; idetape_copy_stage_to_user (tape, buf, tape->merge_stage, bytes_read); - buf += bytes_read; count -= bytes_read; actually_read += bytes_read; + buf += bytes_read; + count -= bytes_read; + actually_read += bytes_read; } if (count) { bytes_read=idetape_add_chrdev_read_request (drive, tape->capabilities.ctl); if (bytes_read <= 0) goto finish; - temp=IDE_MIN (count,bytes_read); + temp = IDE_MIN (count, bytes_read); idetape_copy_stage_to_user (tape, buf, tape->merge_stage, temp); - actually_read+=temp; - tape->merge_stage_size=bytes_read-temp; + actually_read += temp; + tape->merge_stage_size = bytes_read-temp; } finish: if (!actually_read && test_bit (IDETAPE_FILEMARK, &tape->flags)) { @@ -4515,7 +4617,8 @@ return 0; } if (tape->onstream && !actually_read && test_and_clear_bit(IDETAPE_READ_ERROR, &tape->flags)) { - printk(KERN_ERR "ide-tape: %s: unrecovered read error on logical block number %d, skipping\n", tape->name, tape->logical_blk_num); + printk(KERN_ERR "ide-tape: %s: unrecovered read error on logical block number %d, skipping\n", + tape->name, tape->logical_blk_num); tape->logical_blk_num++; return -EIO; } @@ -4576,6 +4679,37 @@ return; } +static void idetape_write_filler (ide_drive_t *drive, int block, int cnt) +{ + idetape_tape_t *tape = drive->driver_data; + idetape_stage_t *stage; + int rc; + + if (!tape->onstream || tape->raw) + return; + stage = __idetape_kmalloc_stage(tape, 1, 1); + if (stage == NULL) + return; + idetape_init_stage(drive, stage, OS_FRAME_TYPE_FILL, 0); + idetape_wait_ready(drive, 60 * 5 * HZ); + rc = idetape_position_tape(drive, block, 0, 0); +#if ONSTREAM_DEBUG + printk(KERN_INFO "write_filler: positioning failed it returned %d\n", rc); +#endif + if (rc != 0) + return; /* don't write fillers if we cannot position the tape. */ + + strcpy(stage->bh->b_data, "Filler"); + while (cnt--) { + if (!idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, 1, stage->bh)) { + printk(KERN_INFO "ide-tape: %s: write_filler: couldn't write header frame\n", tape->name); + __idetape_kfree_stage (stage); + return; + } + } + __idetape_kfree_stage (stage); +} + static void __idetape_write_header (ide_drive_t *drive, int block, int cnt) { idetape_tape_t *tape = drive->driver_data; @@ -4591,12 +4725,12 @@ memset(&header, 0, sizeof(header)); strcpy(header.ident_str, "ADR_SEQ"); header.major_rev = 1; - header.minor_rev = 2; + header.minor_rev = OS_ADR_MINREV; header.par_num = 1; header.partition.partition_num = OS_DATA_PARTITION; header.partition.par_desc_ver = OS_PARTITION_VERSION; - header.partition.first_frame_addr = htonl(0x14); - header.partition.last_frame_addr = htonl(19239 * 24); + header.partition.first_frame_addr = htonl(OS_DATA_STARTFRAME1); + header.partition.last_frame_addr = htonl(tape->capacity); header.partition.wrt_pass_cntr = htons(tape->wrt_pass_cntr); header.partition.eod_frame_addr = htonl(tape->eod_frame_addr); memcpy(stage->bh->b_data, &header, sizeof(header)); @@ -4623,7 +4757,7 @@ return; tape->update_frame_cntr++; __idetape_write_header(drive, 5, 5); - __idetape_write_header(drive, 0xbae, 5); + __idetape_write_header(drive, 0xbae, 5); /* 2990 */ if (locate_eod) { #if ONSTREAM_DEBUG if (tape->debug_level >= 2) @@ -4639,22 +4773,39 @@ struct inode *inode = file->f_dentry->d_inode; ide_drive_t *drive = get_drive_ptr (inode->i_rdev); idetape_tape_t *tape = drive->driver_data; - ssize_t retval,actually_written=0; + ssize_t retval, actually_written = 0; int position; if (ppos != &file->f_pos) { /* "A request was outside the capabilities of the device." */ return -ENXIO; } - if (tape->onstream && (count != tape->tape_block_size)) { - printk(KERN_ERR "ide-tape: %s: use %d bytes as block size (%Zd used)\n", tape->name, tape->tape_block_size, count); - return -EINVAL; - } + #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 3) printk (KERN_INFO "ide-tape: Reached idetape_chrdev_write, count %Zd\n", count); #endif /* IDETAPE_DEBUG_LOG */ + if (tape->onstream) { + if (count != tape->tape_block_size) { + printk(KERN_ERR "ide-tape: %s: chrdev_write: use %d bytes as block size (%Zd used)\n", + tape->name, tape->tape_block_size, count); + return -EINVAL; + } + /* + * Check if we reach the end of the tape. Just assume the whole pipeline + * is filled with write requests! + */ + if (tape->first_frame_position + tape->nr_stages >= tape->capacity - OS_EW) { +#if ONSTREAM_DEBUG + printk(KERN_INFO, "chrdev_write: Write truncated at EOM early warning"); +#endif + if (tape->chrdev_direction == idetape_direction_write) + idetape_write_release(inode); + return -ENOSPC; + } + } + if (tape->chrdev_direction != idetape_direction_write) { /* Initialize write operation */ if (tape->chrdev_direction == idetape_direction_read) idetape_discard_read_pipeline (drive, 1); @@ -4671,17 +4822,17 @@ if (tape->onstream) { position = idetape_read_position(drive); - if (position <= 20) { + if (position <= OS_DATA_STARTFRAME1) { tape->logical_blk_num = 0; tape->wrt_pass_cntr++; #if ONSTREAM_DEBUG if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: logical block num 0, setting eod to 20\n", tape->name); + printk(KERN_INFO "ide-tape: %s: logical block num 0, setting eod to %d\n", tape->name, OS_DATA_STARTFRAME1); if (tape->debug_level >= 2) printk(KERN_INFO "ide-tape: %s: allocating new write pass counter %d\n", tape->name, tape->wrt_pass_cntr); #endif tape->filemark_cnt = 0; - tape->eod_frame_addr = 20; + tape->eod_frame_addr = OS_DATA_STARTFRAME1; tape->first_mark_addr = tape->last_mark_addr = -1; idetape_write_header(drive, 1); } @@ -4715,7 +4866,7 @@ printk("ide-tape: first_frame_position %d\n", tape->first_frame_position); #endif } - if (count==0) + if (count == 0) return (0); if (tape->restart_speed_control_req) idetape_restart_speed_control(drive); @@ -4723,32 +4874,35 @@ #if IDETAPE_DEBUG_BUGS if (tape->merge_stage_size >= tape->stage_size) { printk (KERN_ERR "ide-tape: bug: merge buffer too big\n"); - tape->merge_stage_size=0; + tape->merge_stage_size = 0; } #endif /* IDETAPE_DEBUG_BUGS */ - actually_written=IDE_MIN (tape->stage_size-tape->merge_stage_size,count); + actually_written = IDE_MIN (tape->stage_size - tape->merge_stage_size, count); idetape_copy_stage_from_user (tape, tape->merge_stage, buf, actually_written); - buf+=actually_written;tape->merge_stage_size+=actually_written;count-=actually_written; + buf += actually_written; + tape->merge_stage_size += actually_written; + count -= actually_written; if (tape->merge_stage_size == tape->stage_size) { tape->merge_stage_size = 0; - retval=idetape_add_chrdev_write_request (drive, tape->capabilities.ctl); + retval = idetape_add_chrdev_write_request (drive, tape->capabilities.ctl); if (retval <= 0) return (retval); } } while (count >= tape->stage_size) { idetape_copy_stage_from_user (tape, tape->merge_stage, buf, tape->stage_size); - buf+=tape->stage_size;count-=tape->stage_size; - retval=idetape_add_chrdev_write_request (drive, tape->capabilities.ctl); - actually_written+=tape->stage_size; + buf += tape->stage_size; + count -= tape->stage_size; + retval = idetape_add_chrdev_write_request (drive, tape->capabilities.ctl); + actually_written += tape->stage_size; if (retval <= 0) return (retval); } if (count) { actually_written+=count; idetape_copy_stage_from_user (tape, tape->merge_stage, buf, count); - tape->merge_stage_size+=count; + tape->merge_stage_size += count; } return (actually_written); } @@ -4760,8 +4914,8 @@ idetape_pc_t pc; if (!tape->onstream) { - idetape_create_write_filemark_cmd(drive, &pc,1); /* Write a filemark */ - if (idetape_queue_pc_tail (drive,&pc)) { + idetape_create_write_filemark_cmd(drive, &pc, 1); /* Write a filemark */ + if (idetape_queue_pc_tail (drive, &pc)) { printk (KERN_ERR "ide-tape: Couldn't write a filemark\n"); return -EIO; } @@ -4937,24 +5091,24 @@ if (idetape_rewind_tape(drive)) return -EIO; if (tape->onstream && !tape->raw) - return idetape_position_tape(drive, 20, 0, 0); + return idetape_position_tape(drive, OS_DATA_STARTFRAME1, 0, 0); return 0; case MTLOAD: idetape_discard_read_pipeline (drive, 0); idetape_create_load_unload_cmd (drive, &pc, IDETAPE_LU_LOAD_MASK); - return (idetape_queue_pc_tail (drive,&pc)); + return (idetape_queue_pc_tail (drive, &pc)); case MTUNLOAD: case MTOFFL: idetape_discard_read_pipeline (drive, 0); idetape_create_load_unload_cmd (drive, &pc,!IDETAPE_LU_LOAD_MASK); - return (idetape_queue_pc_tail (drive,&pc)); + return (idetape_queue_pc_tail (drive, &pc)); case MTNOP: idetape_discard_read_pipeline (drive, 0); return (idetape_flush_tape_buffers (drive)); case MTRETEN: idetape_discard_read_pipeline (drive, 0); idetape_create_load_unload_cmd (drive, &pc,IDETAPE_LU_RETENSION_MASK | IDETAPE_LU_LOAD_MASK); - return (idetape_queue_pc_tail (drive,&pc)); + return (idetape_queue_pc_tail (drive, &pc)); case MTEOM: if (tape->onstream) { #if ONSTREAM_DEBUG @@ -4968,24 +5122,30 @@ return -EIO; return 0; } - idetape_create_space_cmd (&pc,0,IDETAPE_SPACE_TO_EOD); - return (idetape_queue_pc_tail (drive,&pc)); + idetape_create_space_cmd (&pc, 0, IDETAPE_SPACE_TO_EOD); + return (idetape_queue_pc_tail (drive, &pc)); case MTERASE: if (tape->onstream) { - tape->eod_frame_addr = 20; + tape->eod_frame_addr = OS_DATA_STARTFRAME1; tape->logical_blk_num = 0; tape->first_mark_addr = tape->last_mark_addr = -1; idetape_position_tape(drive, tape->eod_frame_addr, 0, 0); idetape_write_eod(drive); idetape_flush_tape_buffers (drive); idetape_write_header(drive, 0); + /* + * write filler frames to the unused frames... + * REMOVE WHEN going to LIN4 application type... + */ + idetape_write_filler(drive, OS_DATA_STARTFRAME1 - 10, 10); + idetape_write_filler(drive, OS_DATA_ENDFRAME1, 10); idetape_flush_tape_buffers (drive); (void) idetape_rewind_tape (drive); return 0; } (void) idetape_rewind_tape (drive); idetape_create_erase_cmd (&pc); - return (idetape_queue_pc_tail (drive,&pc)); + return (idetape_queue_pc_tail (drive, &pc)); case MTSETBLK: if (tape->onstream) { if (mt_count != tape->tape_block_size) { @@ -5028,14 +5188,14 @@ case MTLOCK: if (!idetape_create_prevent_cmd(drive, &pc, 1)) return 0; - retval = idetape_queue_pc_tail (drive,&pc); + retval = idetape_queue_pc_tail (drive, &pc); if (retval) return retval; tape->door_locked = DOOR_EXPLICITLY_LOCKED; return 0; case MTUNLOCK: if (!idetape_create_prevent_cmd(drive, &pc, 0)) return 0; - retval = idetape_queue_pc_tail (drive,&pc); + retval = idetape_queue_pc_tail (drive, &pc); if (retval) return retval; tape->door_locked = DOOR_UNLOCKED; return 0; @@ -5113,7 +5273,7 @@ mtget.mt_gstat |= GMT_ONLINE(0xffffffff); if (tape->first_stage && tape->first_stage->aux->frame_type == OS_FRAME_TYPE_EOD) mtget.mt_gstat |= GMT_EOD(0xffffffff); - if (position <= 20) + if (position <= OS_DATA_STARTFRAME1) mtget.mt_gstat |= GMT_BOT(0xffffffff); } if (copy_to_user ((char *) arg,(char *) &mtget, sizeof (struct mtget))) @@ -5150,7 +5310,7 @@ tape->header_ok = tape->linux_media = 0; tape->update_frame_cntr = 0; tape->wrt_pass_cntr = 0; - tape->eod_frame_addr = 20; + tape->eod_frame_addr = OS_DATA_STARTFRAME1; tape->first_mark_addr = tape->last_mark_addr = -1; stage = __idetape_kmalloc_stage (tape, 0, 0); if (stage == NULL) @@ -5172,8 +5332,8 @@ __idetape_kfree_stage (stage); return 0; } - if (header->major_rev != 1 || (header->minor_rev != 1 && header->minor_rev != 2)) - printk(KERN_INFO "ide-tape: warning: revision %d.%d detected (1.1/1.2 supported)\n", header->major_rev, header->minor_rev); + if (header->major_rev != 1 || (header->minor_rev > OS_ADR_MINREV)) + printk(KERN_INFO "ide-tape: warning: revision %d.%d detected (up to 1.%d supported)\n", header->major_rev, header->minor_rev, OS_ADR_MINREV); if (header->par_num != 1) printk(KERN_INFO "ide-tape: warning: %d partitions defined, only one supported\n", header->par_num); tape->wrt_pass_cntr = ntohs(header->partition.wrt_pass_cntr); @@ -5182,12 +5342,14 @@ tape->first_mark_addr = ntohl(aux->next_mark_addr); tape->last_mark_addr = ntohl(aux->last_mark_addr); tape->update_frame_cntr = ntohl(aux->update_frame_cntr); - memcpy(tape->application_sig, aux->application_sig, 4); tape->application_sig[4] = 0; + memcpy(tape->application_sig, aux->application_sig, 4); + tape->application_sig[4] = 0; if (memcmp(tape->application_sig, "LIN", 3) == 0) { tape->linux_media = 1; tape->linux_media_version = tape->application_sig[3] - '0'; if (tape->linux_media_version != 3) - printk(KERN_INFO "ide-tape: %s: Linux media version %d detected (current 3)\n", tape->name, tape->linux_media_version); + printk(KERN_INFO "ide-tape: %s: Linux media version %d detected (current 3)\n", + tape->name, tape->linux_media_version); } else { printk(KERN_INFO "ide-tape: %s: non Linux media detected (%s)\n", tape->name, tape->application_sig); tape->linux_media = 0; @@ -5214,18 +5376,14 @@ for (block = 5; block < 10; block++) if (__idetape_analyze_headers(drive, block)) goto ok; -#if 0 - for (block = 0xbae; block < 0xbb8; block++) -#else - for (block = 0xbae; block < 0xbb3; block++) -#endif + for (block = 0xbae; block < 0xbb3; block++) /* 2990 - 2994 */ if (__idetape_analyze_headers(drive, block)) goto ok; printk(KERN_ERR "ide-tape: %s: failed to find valid ADRL header\n", tape->name); return 0; ok: - if (position < 20) - position = 20; + if (position < OS_DATA_STARTFRAME1) + position = OS_DATA_STARTFRAME1; idetape_position_tape(drive, position, 0, 0); tape->header_ok = 1; return 1; @@ -5251,7 +5409,8 @@ if (test_and_set_bit (IDETAPE_BUSY, &tape->flags)) return -EBUSY; - if (!tape->onstream) { + MOD_INC_USE_COUNT; + if (!tape->onstream) { idetape_read_position(drive); if (!test_bit (IDETAPE_ADDRESS_VALID, &tape->flags)) (void) idetape_rewind_tape (drive); @@ -5263,18 +5422,22 @@ tape->tape_block_size = tape->stage_size = 32768; tape->raw = 0; } + idetape_onstream_mode_sense_tape_parameter_page(drive, tape->debug_level); } if (idetape_wait_ready(drive, 60 * HZ)) { clear_bit(IDETAPE_BUSY, &tape->flags); printk(KERN_ERR "ide-tape: %s: drive not ready\n", tape->name); + MOD_DEC_USE_COUNT; return -EBUSY; } idetape_read_position(drive); + MOD_DEC_USE_COUNT; clear_bit (IDETAPE_PIPELINE_ERROR, &tape->flags); if (tape->chrdev_direction == idetape_direction_none) { + MOD_INC_USE_COUNT; if (idetape_create_prevent_cmd(drive, &pc, 1)) { - if (!idetape_queue_pc_tail (drive,&pc)) { + if (!idetape_queue_pc_tail (drive, &pc)) { if (tape->door_locked != DOOR_EXPLICITLY_LOCKED) tape->door_locked = DOOR_LOCKED; } @@ -5287,6 +5450,28 @@ return 0; } +static void idetape_write_release (struct inode *inode) +{ + ide_drive_t *drive = get_drive_ptr (inode->i_rdev); + idetape_tape_t *tape = drive->driver_data; + unsigned int minor=MINOR (inode->i_rdev); + + idetape_empty_write_pipeline (drive); + tape->merge_stage = __idetape_kmalloc_stage (tape, 1, 0); + if (tape->merge_stage != NULL) { + idetape_pad_zeros (drive, tape->tape_block_size * (tape->user_bs_factor - 1)); + __idetape_kfree_stage (tape->merge_stage); + tape->merge_stage = NULL; + } + idetape_write_filemark(drive); + idetape_write_eod(drive); + idetape_flush_tape_buffers (drive); + idetape_write_header(drive, minor >= 128); + idetape_flush_tape_buffers (drive); + + return; +} + /* * Our character device release function. */ @@ -5305,18 +5490,7 @@ #endif /* IDETAPE_DEBUG_LOG */ if (tape->chrdev_direction == idetape_direction_write) { - idetape_empty_write_pipeline (drive); - tape->merge_stage = __idetape_kmalloc_stage (tape, 1, 0); - if (tape->merge_stage != NULL) { - idetape_pad_zeros (drive, tape->tape_block_size * (tape->user_bs_factor - 1)); - __idetape_kfree_stage (tape->merge_stage); - tape->merge_stage = NULL; - } - idetape_write_filemark(drive); - idetape_write_eod(drive); - idetape_flush_tape_buffers (drive); - idetape_write_header(drive, minor >= 128); - idetape_flush_tape_buffers (drive); + idetape_write_release(inode); } if (tape->chrdev_direction == idetape_direction_read) { if (minor < 128) @@ -5333,9 +5507,10 @@ if (tape->chrdev_direction == idetape_direction_none) { if (tape->door_locked != DOOR_EXPLICITLY_LOCKED) { if (idetape_create_prevent_cmd(drive, &pc, 0)) - if (!idetape_queue_pc_tail (drive,&pc)) + if (!idetape_queue_pc_tail (drive, &pc)) tape->door_locked = DOOR_UNLOCKED; } + MOD_DEC_USE_COUNT; } clear_bit (IDETAPE_BUSY, &tape->flags); unlock_kernel(); @@ -5491,7 +5666,7 @@ pc.buffer[4 + 5] = vendor[3]; pc.buffer[4 + 6] = 0; pc.buffer[4 + 7] = 0; - if (idetape_queue_pc_tail (drive,&pc)) + if (idetape_queue_pc_tail (drive, &pc)) printk (KERN_ERR "ide-tape: Couldn't set vendor name to %s\n", vendor); } @@ -5513,7 +5688,7 @@ pc.buffer[4 + 1] = 2; pc.buffer[4 + 2] = 4; pc.buffer[4 + 3] = retries; - if (idetape_queue_pc_tail (drive,&pc)) + if (idetape_queue_pc_tail (drive, &pc)) printk (KERN_ERR "ide-tape: Couldn't set retries to %d\n", retries); } #endif @@ -5530,8 +5705,8 @@ /* * Get the current block size from the block size mode page */ - idetape_create_mode_sense_cmd (&pc,IDETAPE_BLOCK_SIZE_PAGE); - if (idetape_queue_pc_tail (drive,&pc)) + idetape_create_mode_sense_cmd (&pc, IDETAPE_BLOCK_SIZE_PAGE); + if (idetape_queue_pc_tail (drive, &pc)) printk (KERN_ERR "ide-tape: can't get tape block size mode page\n"); header = (idetape_mode_parameter_header_t *) pc.buffer; bs = (idetape_block_size_page_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t) + header->bdl); @@ -5552,7 +5727,7 @@ bs->record32 = 0; bs->record32_5 = 1; idetape_create_mode_select_cmd(&pc, sizeof(*header) + sizeof(*bs)); - if (idetape_queue_pc_tail (drive,&pc)) + if (idetape_queue_pc_tail (drive, &pc)) printk (KERN_ERR "ide-tape: Couldn't set tape block size mode page\n"); #if ONSTREAM_DEBUG @@ -5575,7 +5750,7 @@ idetape_inquiry_result_t *inquiry; idetape_create_inquiry_cmd(&pc); - if (idetape_queue_pc_tail (drive,&pc)) { + if (idetape_queue_pc_tail (drive, &pc)) { printk (KERN_ERR "ide-tape: %s: can't get INQUIRY results\n", tape->name); return; } @@ -5618,6 +5793,34 @@ } /* + * idetape_get_mode_sense_parameters asks the tape about its various + * parameters. This may work for other drives to??? + */ +static void idetape_onstream_mode_sense_tape_parameter_page(ide_drive_t *drive, int debug) +{ + idetape_tape_t *tape = drive->driver_data; + idetape_pc_t pc; + idetape_mode_parameter_header_t *header; + onstream_tape_paramtr_page_t *prm; + + idetape_create_mode_sense_cmd (&pc, IDETAPE_PARAMTR_PAGE); + if (idetape_queue_pc_tail (drive, &pc)) { + printk (KERN_ERR "ide-tape: Can't get tape parameters page - probably no tape inserted in onstream drive\n"); + return; + } + header = (idetape_mode_parameter_header_t *) pc.buffer; + prm = (onstream_tape_paramtr_page_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t) + header->bdl); + + tape->capacity = ntohs(prm->segtrk) * ntohs(prm->trks); + if (debug) { + printk (KERN_INFO "ide-tape: %s <-> %s: Tape length %dMB (%d frames/track, %d tracks = %d blocks, density: %dKbpi)\n", + drive->name, tape->name, tape->capacity/32, ntohs(prm->segtrk), ntohs(prm->trks), tape->capacity, prm->density); + } + + return; +} + +/* * idetape_get_mode_sense_results asks the tape about its various * parameters. In particular, we will adjust our data transfer buffer * size to the recommended value as returned by the tape. @@ -5629,8 +5832,8 @@ idetape_mode_parameter_header_t *header; idetape_capabilities_page_t *capabilities; - idetape_create_mode_sense_cmd (&pc,IDETAPE_CAPABILITIES_PAGE); - if (idetape_queue_pc_tail (drive,&pc)) { + idetape_create_mode_sense_cmd (&pc, IDETAPE_CAPABILITIES_PAGE); + if (idetape_queue_pc_tail (drive, &pc)) { printk (KERN_ERR "ide-tape: Can't get tape parameters - assuming some default values\n"); tape->tape_block_size = 512; tape->capabilities.ctl = 52; tape->capabilities.speed = 450; tape->capabilities.buffer_size = 6 * 52; @@ -5692,6 +5895,34 @@ #endif /* IDETAPE_DEBUG_INFO */ } +/* + * ide_get_blocksize_from_block_descriptor does a mode sense page 0 with block descriptor + * and if it succeeds sets the tape block size with the reported value + */ +static void idetape_get_blocksize_from_block_descriptor(ide_drive_t *drive) +{ + + idetape_tape_t *tape = drive->driver_data; + idetape_pc_t pc; + idetape_mode_parameter_header_t *header; + idetape_parameter_block_descriptor_t *block_descrp; + + idetape_create_mode_sense_cmd (&pc, IDETAPE_BLOCK_DESCRIPTOR); + if (idetape_queue_pc_tail (drive, &pc)) { + printk (KERN_ERR "ide-tape: Can't get block descriptor\n"); + if (tape->tape_block_size == 0) { + printk(KERN_WARNING "ide-tape: Cannot deal with zero block size, assume 32k\n"); + tape->tape_block_size = 32768; + } + return; + } + header = (idetape_mode_parameter_header_t *) pc.buffer; + block_descrp = (idetape_parameter_block_descriptor_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t)); + tape->tape_block_size =( block_descrp->length[0]<<16) + (block_descrp->length[1]<<8) + block_descrp->length[2]; +#if IDETAPE_DEBUG_INFO + printk (KERN_INFO "ide-tape: Adjusted block size - %d\n", tape->tape_block_size); +#endif /* IDETAPE_DEBUG_INFO */ +} static void idetape_add_settings (ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; @@ -5712,15 +5943,18 @@ ide_add_setting(drive, "pipeline_head_speed_c",SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->controlled_pipeline_head_speed, NULL); ide_add_setting(drive, "pipeline_head_speed_u",SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->uncontrolled_pipeline_head_speed, NULL); ide_add_setting(drive, "avg_speed", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->avg_speed, NULL); + ide_add_setting(drive, "debug_level",SETTING_RW, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->debug_level, NULL); if (tape->onstream) { ide_add_setting(drive, "cur_frames", SETTING_READ, -1, -1, TYPE_SHORT, 0, 0xffff, 1, 1, &tape->cur_frames, NULL); ide_add_setting(drive, "max_frames", SETTING_READ, -1, -1, TYPE_SHORT, 0, 0xffff, 1, 1, &tape->max_frames, NULL); ide_add_setting(drive, "insert_speed", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->insert_speed, NULL); ide_add_setting(drive, "speed_control",SETTING_RW, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->speed_control, NULL); - ide_add_setting(drive, "debug_level",SETTING_RW, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->debug_level, NULL); ide_add_setting(drive, "tape_still_time",SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->tape_still_time, NULL); ide_add_setting(drive, "max_insert_speed",SETTING_RW, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->max_insert_speed, NULL); ide_add_setting(drive, "insert_size", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->insert_size, NULL); + ide_add_setting(drive, "capacity", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->capacity, NULL); + ide_add_setting(drive, "first_frame", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->first_frame_position, NULL); + ide_add_setting(drive, "logical_blk", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->logical_blk_num, NULL); } } @@ -5742,12 +5976,13 @@ int speed; struct idetape_id_gcw gcw; int stage_size; + struct sysinfo si; memset (tape, 0, sizeof (idetape_tape_t)); spin_lock_init(&tape->spinlock); drive->driver_data = tape; drive->ready_stat = 0; /* An ATAPI device ignores DRDY */ - if (strstr(drive->id->model, "OnStream DI-30")) + if (strstr(drive->id->model, "OnStream DI-")) tape->onstream = 1; drive->dsc_overlap = 1; #ifdef CONFIG_BLK_DEV_IDEPCI @@ -5778,9 +6013,11 @@ idetape_get_inquiry_results(drive); idetape_get_mode_sense_results(drive); - if (tape->onstream) + idetape_get_blocksize_from_block_descriptor(drive); + if (tape->onstream) { + idetape_onstream_mode_sense_tape_parameter_page(drive, 1); idetape_configure_onstream(drive); - + } tape->user_bs_factor = 1; tape->stage_size = tape->capabilities.ctl * tape->tape_block_size; while (tape->stage_size > 0xffff) { @@ -5804,6 +6041,13 @@ speed = IDE_MAX (tape->capabilities.speed, tape->capabilities.max_speed); tape->max_stages = speed * 1000 * 10 / tape->stage_size; + + /* + * Limit memory use for pipeline to 10% of physical memory + */ + si_meminfo(&si); + if ( tape->max_stages * tape->stage_size > si.totalram * si.mem_unit / 10) + tape->max_stages = si.totalram * si.mem_unit / (10 * tape->stage_size); tape->min_pipeline = tape->max_stages; tape->max_pipeline = tape->max_stages * 2; @@ -5867,8 +6111,8 @@ char *out = page; int len; - len = sprintf(out,"%s\n", tape->name); - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); + len = sprintf(out, "%s\n", tape->name); + PROC_IDE_READ_RETURN(page, start, off, count, eof, len); } static ide_proc_entry_t idetape_proc[] = { @@ -5962,7 +6206,7 @@ continue; } if (drive->scsi) { - if (strstr(drive->id->model, "OnStream DI-30")) { + if (strstr(drive->id->model, "OnStream DI-")) { printk("ide-tape: ide-scsi emulation is not supported for %s.\n", drive->id->model); } else { printk("ide-tape: passing drive %s to ide-scsi emulation.\n", drive->name); diff -u --recursive --new-file v2.4.5/linux/drivers/ide/piix.c linux/drivers/ide/piix.c --- v2.4.5/linux/drivers/ide/piix.c Tue Mar 6 19:44:34 2001 +++ linux/drivers/ide/piix.c Wed Jun 20 11:16:01 2001 @@ -108,7 +108,8 @@ c1 = inb_p((unsigned short)bibma + 0x0a); switch(bmide_dev->device) { - case PCI_DEVICE_ID_INTEL_82820FW_5: + case PCI_DEVICE_ID_INTEL_82801BA_8: + case PCI_DEVICE_ID_INTEL_82801BA_9: p += sprintf(p, "\n Intel PIIX4 Ultra 100 Chipset.\n"); break; case PCI_DEVICE_ID_INTEL_82372FB_1: @@ -358,7 +359,8 @@ byte speed; byte udma_66 = eighty_ninty_three(drive); - int ultra100 = ((dev->device == PCI_DEVICE_ID_INTEL_82820FW_5)) ? 1 : 0; + int ultra100 = ((dev->device == PCI_DEVICE_ID_INTEL_82801BA_8) || + (dev->device == PCI_DEVICE_ID_INTEL_82801BA_9)) ? 1 : 0; int ultra66 = ((ultra100) || (dev->device == PCI_DEVICE_ID_INTEL_82801AA_1) || (dev->device == PCI_DEVICE_ID_INTEL_82372FB_1)) ? 1 : 0; diff -u --recursive --new-file v2.4.5/linux/drivers/ide/rapide.c linux/drivers/ide/rapide.c --- v2.4.5/linux/drivers/ide/rapide.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/ide/rapide.c Wed Jun 27 14:12:04 2001 @@ -17,7 +17,7 @@ #include -static const card_ids __init rapide_cids[] = { +static card_ids __init rapide_cids[] = { { MANU_YELLOWSTONE, PROD_YELLOWSTONE_RAPIDE32 }, { 0xffff, 0xffff } }; diff -u --recursive --new-file v2.4.5/linux/drivers/ide/sl82c105.c linux/drivers/ide/sl82c105.c --- v2.4.5/linux/drivers/ide/sl82c105.c Tue Nov 7 11:02:24 2000 +++ linux/drivers/ide/sl82c105.c Wed Jun 27 14:12:04 2001 @@ -56,10 +56,9 @@ } /* - * We only deal with PIO mode here - DMA mode 'using_dma' is not - * initialised at the point that this function is called. + * Configure the drive and chipset for PIO */ -static void tune_sl82c105(ide_drive_t *drive, byte pio) +static void config_for_pio(ide_drive_t *drive, int pio, int report) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; @@ -83,42 +82,212 @@ if (ide_config_drive_speed(drive, xfer_mode) == 0) drv_ctrl = get_timing_sl82c105(&p); + if (drive->using_dma == 0) { + /* + * If we are actually using MW DMA, then we can not + * reprogram the interface drive control register. + */ + pci_write_config_word(dev, reg, drv_ctrl); + pci_read_config_word(dev, reg, &drv_ctrl); + + if (report) { + printk("%s: selected %s (%dns) (%04X)\n", drive->name, + ide_xfer_verbose(xfer_mode), p.cycle_time, drv_ctrl); + } + } +} + +/* + * Configure the drive and the chipset for DMA + */ +static int config_for_dma(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + unsigned short drv_ctrl = 0x909; + unsigned int reg; + + reg = (hwif->channel ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0); + + if (ide_config_drive_speed(drive, XFER_MW_DMA_2) == 0) + drv_ctrl = 0x0240; + pci_write_config_word(dev, reg, drv_ctrl); - pci_read_config_word(dev, reg, &drv_ctrl); - printk("%s: selected %s (%dns) (%04X)\n", drive->name, - ide_xfer_verbose(xfer_mode), p.cycle_time, drv_ctrl); + return 0; } -#endif -void __init ide_dmacapable_sl82c105(ide_hwif_t *hwif, unsigned long dmabase) +/* + * Check to see if the drive and + * chipset is capable of DMA mode + */ +static int sl82c105_check_drive(ide_drive_t *drive) +{ + ide_dma_action_t dma_func = ide_dma_off_quietly; + + do { + struct hd_driveid *id = drive->id; + ide_hwif_t *hwif = HWIF(drive); + + if (!hwif->autodma) + break; + + if (!id || !(id->capability & 1)) + break; + + /* Consult the list of known "bad" drives */ + if (ide_dmaproc(ide_dma_bad_drive, drive)) { + dma_func = ide_dma_off; + break; + } + + if (id->field_valid & 2) { + if (id->dma_mword & 7 || id->dma_1word & 7) + dma_func = ide_dma_on; + break; + } + + if (ide_dmaproc(ide_dma_good_drive, drive)) { + dma_func = ide_dma_on; + break; + } + } while (0); + + return HWIF(drive)->dmaproc(dma_func, drive); +} + +/* + * Our own dmaproc, only to intercept ide_dma_check + */ +static int sl82c105_dmaproc(ide_dma_action_t func, ide_drive_t *drive) +{ + switch (func) { + case ide_dma_check: + return sl82c105_check_drive(drive); + case ide_dma_on: + if (config_for_dma(drive)) + func = ide_dma_off; + /* fall through */ + case ide_dma_off_quietly: + case ide_dma_off: + config_for_pio(drive, 4, 0); + break; + default: + break; + } + return ide_dmaproc(func, drive); +} + +/* + * We only deal with PIO mode here - DMA mode 'using_dma' is not + * initialised at the point that this function is called. + */ +static void tune_sl82c105(ide_drive_t *drive, byte pio) +{ + config_for_pio(drive, pio, 1); + + /* + * We support 32-bit I/O on this interface, and it + * doesn't have problems with interrupts. + */ + drive->io_32bit = 1; + drive->unmask = 1; +} + +/* + * Return the revision of the Winbond bridge + * which this function is part of. + */ +static unsigned int sl82c105_bridge_revision(struct pci_dev *dev) { + struct pci_dev *bridge; unsigned char rev; - pci_read_config_byte(hwif->pci_dev, PCI_REVISION_ID, &rev); + bridge = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553, NULL); + /* + * If we are part of a Winbond 553 + */ + if (!bridge || bridge->class >> 8 != PCI_CLASS_BRIDGE_ISA) + return -1; + + if (bridge->bus != dev->bus || + PCI_SLOT(bridge->devfn) != PCI_SLOT(dev->devfn)) + return -1; + + /* + * We need to find function 0's revision, not function 1 + */ + pci_read_config_byte(bridge, PCI_REVISION_ID, &rev); + + return rev; +} + +/* + * Enable the PCI device + */ +unsigned int __init pci_init_sl82c105(struct pci_dev *dev, const char *msg) +{ + unsigned char ctrl_stat; + + /* + * Enable the ports + */ + pci_read_config_byte(dev, 0x40, &ctrl_stat); + pci_write_config_byte(dev, 0x40, ctrl_stat | 0x33); + + return dev->irq; +} + +void __init dma_init_sl82c105(ide_hwif_t *hwif, unsigned long dma_base) +{ + unsigned int rev; + byte dma_state; + + dma_state = inb(dma_base + 2); + rev = sl82c105_bridge_revision(hwif->pci_dev); if (rev <= 5) { hwif->autodma = 0; hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; - printk(" %s: revision %d, Bus-Master DMA disabled\n", + printk(" %s: Winbond 553 bridge revision %d, BM-DMA disabled\n", hwif->name, rev); + dma_state &= ~0x60; + } else { + dma_state |= 0x60; + hwif->autodma = 1; } - ide_setup_dma(hwif, dmabase, 8); + outb(dma_state, dma_base + 2); + + hwif->dmaproc = NULL; + ide_setup_dma(hwif, dma_base, 8); + if (hwif->dmaproc) + hwif->dmaproc = sl82c105_dmaproc; } +/* + * Initialise the chip + */ void __init ide_init_sl82c105(ide_hwif_t *hwif) { - struct pci_dev *dev = hwif->pci_dev; + hwif->tuneproc = tune_sl82c105; +} -#ifdef CONFIG_ARCH_NETWINDER - unsigned char ctrl_stat; +#else - pci_read_config_byte(dev, 0x40, &ctrl_stat); - pci_write_config_byte(dev, 0x40, ctrl_stat | 0x33); +unsigned int pci_init_sl82c105(struct pci_dev *dev, const char *msg) +{ + return ide_special_settings(dev, msg); +} - hwif->tuneproc = tune_sl82c105; -#else +void dma_init_sl82c105(ide_hwif_t *hwif, unsigned long dma_base) +{ + ide_setup_dma(hwif, dma_base, 8); +} + +void __init ide_init_sl82c105(ide_hwif_t *hwif) +{ + struct pci_dev *dev = hwif->pci_dev; unsigned short t16; unsigned int t32; pci_read_config_word(dev, PCI_COMMAND, &t16); @@ -134,5 +303,6 @@ printk("IDE control/status register: %08x\n",t32); pci_write_config_dword(dev, 0x40, 0x10ff08a1); #endif /* CONFIG_MBX */ -#endif } +#endif + diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/Config.in linux/drivers/isdn/Config.in --- v2.4.5/linux/drivers/isdn/Config.in Thu Apr 19 22:30:16 2001 +++ linux/drivers/isdn/Config.in Mon Jul 2 14:07:55 2001 @@ -105,6 +105,10 @@ fi fi +if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then + dep_tristate 'Auvertech TurboPAM support' CONFIG_ISDN_DRV_TPAM $CONFIG_ISDN $CONFIG_PCI +fi + # CAPI subsystem tristate 'CAPI2.0 support' CONFIG_ISDN_CAPI diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/Makefile linux/drivers/isdn/Makefile --- v2.4.5/linux/drivers/isdn/Makefile Fri Mar 2 11:12:10 2001 +++ linux/drivers/isdn/Makefile Mon Jul 2 14:07:55 2001 @@ -43,6 +43,7 @@ subdir-$(CONFIG_ISDN_DRV_ACT2000) += act2000 subdir-$(CONFIG_ISDN_DRV_EICON) += eicon subdir-$(CONFIG_HYSDN) += hysdn +subdir-$(CONFIG_ISDN_DRV_TPAM) += tpam obj-y += $(addsuffix /vmlinux-obj.o, $(subdir-y)) diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/avmb1/b1.c linux/drivers/isdn/avmb1/b1.c --- v2.4.5/linux/drivers/isdn/avmb1/b1.c Sat May 19 17:54:14 2001 +++ linux/drivers/isdn/avmb1/b1.c Tue Jun 12 13:03:18 2001 @@ -1,114 +1,9 @@ /* - * $Id: b1.c,v 1.20.6.4 2001/04/20 02:41:59 keil Exp $ + * $Id: b1.c,v 1.20.6.6 2001/05/17 21:15:33 kai Exp $ * * Common module for AVM B1 cards. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) - * - * $Log: b1.c,v $ - * Revision 1.20.6.4 2001/04/20 02:41:59 keil - * changes from mainstream - * - * Revision 1.20.6.3 2001/03/21 08:52:20 kai - * merge from main branch: fix buffer for revision string (calle) - * - * Revision 1.20.6.2 2001/03/15 15:11:23 kai - * *** empty log message *** - * - * Revision 1.20.6.1 2001/02/13 11:43:29 kai - * more compatility changes for 2.2.19 - * - * Revision 1.20 2000/11/23 20:45:14 kai - * fixed module_init/exit stuff - * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. - * - * Revision 1.19 2000/11/19 17:02:47 kai - * compatibility cleanup - part 3 - * - * Revision 1.18 2000/11/19 17:01:53 kai - * compatibility cleanup - part 2 - * - * Revision 1.17 2000/11/01 14:05:02 calle - * - use module_init/module_exit from linux/init.h. - * - all static struct variables are initialized with "membername:" now. - * - avm_cs.c, let it work with newer pcmcia-cs. - * - * Revision 1.16 2000/08/04 15:36:31 calle - * copied wrong from file to file :-( - * - * Revision 1.15 2000/08/04 12:20:08 calle - * - Fix unsigned/signed warning in the right way ... - * - * Revision 1.14 2000/06/19 16:51:53 keil - * don't free skb in irq context - * - * Revision 1.13 2000/01/25 14:33:38 calle - * - Added Support AVM B1 PCI V4.0 (tested with prototype) - * - splitted up t1pci.c into b1dma.c for common function with b1pciv4 - * - support for revision register - * - * Revision 1.12 1999/11/05 16:38:01 calle - * Cleanups before kernel 2.4: - * - Changed all messages to use card->name or driver->name instead of - * constant string. - * - Moved some data from struct avmcard into new struct avmctrl_info. - * Changed all lowlevel capi driver to match the new structur. - * - * Revision 1.11 1999/10/11 22:04:12 keil - * COMPAT_NEED_UACCESS (no include in isdn_compat.h) - * - * Revision 1.10 1999/09/15 08:16:03 calle - * Implementation of 64Bit extention complete. - * - * Revision 1.9 1999/09/07 09:02:53 calle - * SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and - * DATA_B3_IND is always directly after the CAPI message. The "Data" member - * ist never used inside the kernel. - * - * Revision 1.8 1999/08/22 20:26:22 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.7 1999/08/04 10:10:09 calle - * Bugfix: corrected /proc functions, added structure for new AVM cards. - * - * Revision 1.6 1999/07/23 08:51:04 calle - * small fix and typo in checkin before. - * - * Revision 1.5 1999/07/23 08:41:48 calle - * prepared for new AVM cards. - * - * Revision 1.4 1999/07/09 15:05:38 keil - * compat.h is now isdn_compat.h - * - * Revision 1.3 1999/07/06 07:41:59 calle - * - changes in /proc interface - * - check and changed calls to [dev_]kfree_skb and [dev_]alloc_skb. - * - * Revision 1.2 1999/07/05 15:09:47 calle - * - renamed "appl_release" to "appl_released". - * - version und profile data now cleared on controller reset - * - extended /proc interface, to allow driver and controller specific - * informations to include by driver hackers. - * - * Revision 1.1 1999/07/01 15:26:23 calle - * complete new version (I love it): - * + new hardware independed "capi_driver" interface that will make it easy to: - * - support other controllers with CAPI-2.0 (i.e. USB Controller) - * - write a CAPI-2.0 for the passive cards - * - support serial link CAPI-2.0 boxes. - * + wrote "capi_driver" for all supported cards. - * + "capi_driver" (supported cards) now have to be configured with - * make menuconfig, in the past all supported cards where included - * at once. - * + new and better informations in /proc/capi/ - * + new ioctl to switch trace of capi messages per controller - * using "avmcapictrl trace [contr] on|off|...." - * + complete testcircle with all supported cards and also the - * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. - * * */ diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/avmb1/b1dma.c linux/drivers/isdn/avmb1/b1dma.c --- v2.4.5/linux/drivers/isdn/avmb1/b1dma.c Sat May 19 17:54:14 2001 +++ linux/drivers/isdn/avmb1/b1dma.c Tue Jun 12 13:03:18 2001 @@ -1,59 +1,10 @@ /* - * $Id: b1dma.c,v 1.11.6.4 2001/04/20 02:41:59 keil Exp $ + * $Id: b1dma.c,v 1.11.6.6 2001/05/17 21:15:33 kai Exp $ * * Common module for AVM B1 cards that support dma with AMCC * * (c) Copyright 2000 by Carsten Paeth (calle@calle.in-berlin.de) * - * $Log: b1dma.c,v $ - * Revision 1.11.6.4 2001/04/20 02:41:59 keil - * changes from mainstream - * - * Revision 1.11.6.3 2001/03/21 08:52:21 kai - * merge from main branch: fix buffer for revision string (calle) - * - * Revision 1.11.6.2 2001/03/15 15:11:23 kai - * *** empty log message *** - * - * Revision 1.11.6.1 2001/02/13 11:43:29 kai - * more compatility changes for 2.2.19 - * - * Revision 1.11 2000/11/19 17:02:47 kai - * compatibility cleanup - part 3 - * - * Revision 1.10 2000/11/19 17:01:53 kai - * compatibility cleanup - part 2 - * - * Revision 1.9 2000/11/01 14:05:02 calle - * - use module_init/module_exit from linux/init.h. - * - all static struct variables are initialized with "membername:" now. - * - avm_cs.c, let it work with newer pcmcia-cs. - * - * Revision 1.8 2000/10/10 17:44:19 kai - * changes from/for 2.2.18 - * - * Revision 1.7 2000/08/04 12:20:08 calle - * - Fix unsigned/signed warning in the right way ... - * - * Revision 1.6 2000/06/29 13:59:06 calle - * Bugfix: reinit txdma without interrupt will confuse some AMCC chips. - * - * Revision 1.5 2000/06/19 16:51:53 keil - * don't free skb in irq context - * - * Revision 1.4 2000/04/03 16:38:05 calle - * made suppress_pollack static. - * - * Revision 1.3 2000/02/26 01:00:53 keil - * changes from 2.3.47 - * - * Revision 1.2 2000/01/25 14:44:47 calle - * typo in b1pciv4_detect(). - * - * Revision 1.1 2000/01/25 14:36:43 calle - * common function for T1 PCI and B1 PCI V4. - * - * */ #include diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/avmb1/b1isa.c linux/drivers/isdn/avmb1/b1isa.c --- v2.4.5/linux/drivers/isdn/avmb1/b1isa.c Sat May 19 17:54:14 2001 +++ linux/drivers/isdn/avmb1/b1isa.c Tue Jun 12 13:03:18 2001 @@ -1,83 +1,10 @@ /* - * $Id: b1isa.c,v 1.10.6.4 2001/03/21 08:52:21 kai Exp $ + * $Id: b1isa.c,v 1.10.6.5 2001/05/17 20:41:51 kai Exp $ * * Module for AVM B1 ISA-card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * - * $Log: b1isa.c,v $ - * Revision 1.10.6.4 2001/03/21 08:52:21 kai - * merge from main branch: fix buffer for revision string (calle) - * - * Revision 1.10.6.3 2001/03/15 15:11:23 kai - * *** empty log message *** - * - * Revision 1.10.6.2 2001/02/16 16:43:23 kai - * Changes from -ac16, little bug fixes, typos and the like - * - * Revision 1.10.6.1 2001/02/13 11:43:29 kai - * more compatility changes for 2.2.19 - * - * Revision 1.10 2000/11/23 20:45:14 kai - * fixed module_init/exit stuff - * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. - * - * Revision 1.9 2000/11/01 14:05:02 calle - * - use module_init/module_exit from linux/init.h. - * - all static struct variables are initialized with "membername:" now. - * - avm_cs.c, let it work with newer pcmcia-cs. - * - * Revision 1.8 2000/04/03 13:29:24 calle - * make Tim Waugh happy (module unload races in 2.3.99-pre3). - * no real problem there, but now it is much cleaner ... - * - * Revision 1.7 2000/02/02 18:36:03 calle - * - Modules are now locked while init_module is running - * - fixed problem with memory mapping if address is not aligned - * - * Revision 1.6 2000/01/25 14:37:39 calle - * new message after successful detection including card revision and - * used resources. - * - * Revision 1.5 1999/11/05 16:38:01 calle - * Cleanups before kernel 2.4: - * - Changed all messages to use card->name or driver->name instead of - * constant string. - * - Moved some data from struct avmcard into new struct avmctrl_info. - * Changed all lowlevel capi driver to match the new structur. - * - * Revision 1.4 1999/08/22 20:26:24 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.3 1999/07/09 15:05:40 keil - * compat.h is now isdn_compat.h - * - * Revision 1.2 1999/07/05 15:09:49 calle - * - renamed "appl_release" to "appl_released". - * - version und profile data now cleared on controller reset - * - extended /proc interface, to allow driver and controller specific - * informations to include by driver hackers. - * - * Revision 1.1 1999/07/01 15:26:27 calle - * complete new version (I love it): - * + new hardware independed "capi_driver" interface that will make it easy to: - * - support other controllers with CAPI-2.0 (i.e. USB Controller) - * - write a CAPI-2.0 for the passive cards - * - support serial link CAPI-2.0 boxes. - * + wrote "capi_driver" for all supported cards. - * + "capi_driver" (supported cards) now have to be configured with - * make menuconfig, in the past all supported cards where included - * at once. - * + new and better informations in /proc/capi/ - * + new ioctl to switch trace of capi messages per controller - * using "avmcapictrl trace [contr] on|off|...." - * + complete testcircle with all supported cards and also the - * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. - * - * */ #include diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/avmb1/b1pci.c linux/drivers/isdn/avmb1/b1pci.c --- v2.4.5/linux/drivers/isdn/avmb1/b1pci.c Sat May 19 17:54:14 2001 +++ linux/drivers/isdn/avmb1/b1pci.c Tue Jun 12 13:03:18 2001 @@ -1,111 +1,10 @@ /* - * $Id: b1pci.c,v 1.29.6.3 2001/04/20 02:41:59 keil Exp $ + * $Id: b1pci.c,v 1.29.6.4 2001/05/17 20:41:51 kai Exp $ * * Module for AVM B1 PCI-card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * - * $Log: b1pci.c,v $ - * Revision 1.29.6.3 2001/04/20 02:41:59 keil - * changes from mainstream - * - * Revision 1.29.6.2 2001/03/21 08:52:21 kai - * merge from main branch: fix buffer for revision string (calle) - * - * Revision 1.29.6.1 2000/11/28 12:02:45 kai - * MODULE_DEVICE_TABLE for 2.4 - * - * Revision 1.29.2.2 2000/11/26 17:47:53 kai - * added PCI_DEV_TABLE for 2.4 - * - * Revision 1.29.2.1 2000/11/26 17:14:19 kai - * fix device ids - * also needs patches to include/linux/pci_ids.h - * - * Revision 1.29 2000/11/23 20:45:14 kai - * fixed module_init/exit stuff - * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. - * - * Revision 1.28 2000/11/01 14:05:02 calle - * - use module_init/module_exit from linux/init.h. - * - all static struct variables are initialized with "membername:" now. - * - avm_cs.c, let it work with newer pcmcia-cs. - * - * Revision 1.27 2000/08/08 09:24:19 calle - * calls to pci_enable_device surounded by #ifndef COMPAT_HAS_2_2_PCI - * - * Revision 1.26 2000/07/20 10:21:21 calle - * Bugfix: driver will not be unregistered, if not cards were detected. - * this result in an oops in kcapi.c - * - * Revision 1.25 2000/05/29 12:29:18 keil - * make pci_enable_dev compatible to 2.2 kernel versions - * - * Revision 1.24 2000/05/19 15:43:22 calle - * added calls to pci_device_start(). - * - * Revision 1.23 2000/05/06 00:52:36 kai - * merged changes from kernel tree - * fixed timer and net_device->name breakage - * - * Revision 1.22 2000/04/21 13:01:33 calle - * Revision in b1pciv4 driver was missing. - * - * Revision 1.21 2000/04/03 13:29:24 calle - * make Tim Waugh happy (module unload races in 2.3.99-pre3). - * no real problem there, but now it is much cleaner ... - * - * Revision 1.20 2000/02/02 18:36:03 calle - * - Modules are now locked while init_module is running - * - fixed problem with memory mapping if address is not aligned - * - * Revision 1.19 2000/01/25 14:33:38 calle - * - Added Support AVM B1 PCI V4.0 (tested with prototype) - * - splitted up t1pci.c into b1dma.c for common function with b1pciv4 - * - support for revision register - * - * Revision 1.18 1999/11/05 16:38:01 calle - * Cleanups before kernel 2.4: - * - Changed all messages to use card->name or driver->name instead of - * constant string. - * - Moved some data from struct avmcard into new struct avmctrl_info. - * Changed all lowlevel capi driver to match the new structur. - * - * Revision 1.17 1999/10/05 06:50:07 calle - * Forgot SA_SHIRQ as argument to request_irq. - * - * Revision 1.16 1999/08/11 21:01:07 keil - * new PCI codefix - * - * Revision 1.15 1999/08/10 16:02:27 calle - * struct pci_dev changed in 2.3.13. Made the necessary changes. - * - * Revision 1.14 1999/07/09 15:05:41 keil - * compat.h is now isdn_compat.h - * - * Revision 1.13 1999/07/05 15:09:50 calle - * - renamed "appl_release" to "appl_released". - * - version und profile data now cleared on controller reset - * - extended /proc interface, to allow driver and controller specific - * informations to include by driver hackers. - * - * Revision 1.12 1999/07/01 15:26:29 calle - * complete new version (I love it): - * + new hardware independed "capi_driver" interface that will make it easy to: - * - support other controllers with CAPI-2.0 (i.e. USB Controller) - * - write a CAPI-2.0 for the passive cards - * - support serial link CAPI-2.0 boxes. - * + wrote "capi_driver" for all supported cards. - * + "capi_driver" (supported cards) now have to be configured with - * make menuconfig, in the past all supported cards where included - * at once. - * + new and better informations in /proc/capi/ - * + new ioctl to switch trace of capi messages per controller - * using "avmcapictrl trace [contr] on|off|...." - * + complete testcircle with all supported cards and also the - * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. - * - * */ #include diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/avmb1/b1pcmcia.c linux/drivers/isdn/avmb1/b1pcmcia.c --- v2.4.5/linux/drivers/isdn/avmb1/b1pcmcia.c Sat May 19 17:54:14 2001 +++ linux/drivers/isdn/avmb1/b1pcmcia.c Tue Jun 12 13:03:18 2001 @@ -1,89 +1,10 @@ /* - * $Id: b1pcmcia.c,v 1.12.6.3 2001/03/21 08:52:21 kai Exp $ + * $Id: b1pcmcia.c,v 1.12.6.4 2001/05/17 20:41:51 kai Exp $ * * Module for AVM B1/M1/M2 PCMCIA-card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * - * $Log: b1pcmcia.c,v $ - * Revision 1.12.6.3 2001/03/21 08:52:21 kai - * merge from main branch: fix buffer for revision string (calle) - * - * Revision 1.12.6.2 2001/02/16 16:43:23 kai - * Changes from -ac16, little bug fixes, typos and the like - * - * Revision 1.12.6.1 2001/02/13 11:43:29 kai - * more compatility changes for 2.2.19 - * - * Revision 1.12 2000/11/23 20:45:14 kai - * fixed module_init/exit stuff - * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. - * - * Revision 1.11 2000/11/01 14:05:02 calle - * - use module_init/module_exit from linux/init.h. - * - all static struct variables are initialized with "membername:" now. - * - avm_cs.c, let it work with newer pcmcia-cs. - * - * Revision 1.10 2000/05/06 00:52:36 kai - * merged changes from kernel tree - * fixed timer and net_device->name breakage - * - * Revision 1.9 2000/04/03 13:29:24 calle - * make Tim Waugh happy (module unload races in 2.3.99-pre3). - * no real problem there, but now it is much cleaner ... - * - * Revision 1.8 2000/03/06 18:00:23 calle - * - Middleware extention now working with 2.3.49 (capifs). - * - Fixed typos in debug section of capi.c - * - Bugfix: Makefile corrected for b1pcmcia.c - * - * Revision 1.7 2000/02/02 18:36:03 calle - * - Modules are now locked while init_module is running - * - fixed problem with memory mapping if address is not aligned - * - * Revision 1.6 2000/01/25 14:37:39 calle - * new message after successful detection including card revision and - * used resources. - * - * Revision 1.5 1999/11/05 16:38:01 calle - * Cleanups before kernel 2.4: - * - Changed all messages to use card->name or driver->name instead of - * constant string. - * - Moved some data from struct avmcard into new struct avmctrl_info. - * Changed all lowlevel capi driver to match the new structur. - * - * Revision 1.4 1999/08/22 20:26:26 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.3 1999/07/09 15:05:41 keil - * compat.h is now isdn_compat.h - * - * Revision 1.2 1999/07/05 15:09:51 calle - * - renamed "appl_release" to "appl_released". - * - version und profile data now cleared on controller reset - * - extended /proc interface, to allow driver and controller specific - * informations to include by driver hackers. - * - * Revision 1.1 1999/07/01 15:26:30 calle - * complete new version (I love it): - * + new hardware independed "capi_driver" interface that will make it easy to: - * - support other controllers with CAPI-2.0 (i.e. USB Controller) - * - write a CAPI-2.0 for the passive cards - * - support serial link CAPI-2.0 boxes. - * + wrote "capi_driver" for all supported cards. - * + "capi_driver" (supported cards) now have to be configured with - * make menuconfig, in the past all supported cards where included - * at once. - * + new and better informations in /proc/capi/ - * + new ioctl to switch trace of capi messages per controller - * using "avmcapictrl trace [contr] on|off|...." - * + complete testcircle with all supported cards and also the - * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. - * - * */ #include diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/avmb1/c4.c linux/drivers/isdn/avmb1/c4.c --- v2.4.5/linux/drivers/isdn/avmb1/c4.c Sat May 19 17:54:14 2001 +++ linux/drivers/isdn/avmb1/c4.c Wed Jun 27 17:10:55 2001 @@ -1,104 +1,9 @@ /* - * $Id: c4.c,v 1.20.6.6 2001/04/20 02:41:59 keil Exp $ + * $Id: c4.c,v 1.20.6.10 2001/06/09 15:14:15 kai Exp $ * - * Module for AVM C4 card. + * Module for AVM C4 & C2 card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) - * - * $Log: c4.c,v $ - * Revision 1.20.6.6 2001/04/20 02:41:59 keil - * changes from mainstream - * - * Revision 1.20.6.5 2001/03/21 08:52:21 kai - * merge from main branch: fix buffer for revision string (calle) - * - * Revision 1.20.6.4 2001/03/15 15:11:23 kai - * *** empty log message *** - * - * Revision 1.20.6.3 2001/02/16 16:43:23 kai - * Changes from -ac16, little bug fixes, typos and the like - * - * Revision 1.20.6.2 2001/02/13 11:43:29 kai - * more compatility changes for 2.2.19 - * - * Revision 1.20.6.1 2000/11/28 12:02:45 kai - * MODULE_DEVICE_TABLE for 2.4 - * - * Revision 1.20.2.2 2000/11/26 17:47:53 kai - * added PCI_DEV_TABLE for 2.4 - * - * Revision 1.20.2.1 2000/11/26 17:14:19 kai - * fix device ids - * also needs patches to include/linux/pci_ids.h - * - * Revision 1.20 2000/11/23 20:45:14 kai - * fixed module_init/exit stuff - * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. - * - * Revision 1.19 2000/11/19 17:02:47 kai - * compatibility cleanup - part 3 - * - * Revision 1.18 2000/11/01 14:05:02 calle - * - use module_init/module_exit from linux/init.h. - * - all static struct variables are initialized with "membername:" now. - * - avm_cs.c, let it work with newer pcmcia-cs. - * - * Revision 1.17 2000/10/10 17:44:19 kai - * changes from/for 2.2.18 - * - * Revision 1.16 2000/08/20 07:30:13 keil - * changes for 2.4 - * - * Revision 1.15 2000/08/08 09:24:19 calle - * calls to pci_enable_device surounded by #ifndef COMPAT_HAS_2_2_PCI - * - * Revision 1.14 2000/08/04 12:20:08 calle - * - Fix unsigned/signed warning in the right way ... - * - * Revision 1.13 2000/07/20 10:21:21 calle - * Bugfix: driver will not be unregistered, if not cards were detected. - * this result in an oops in kcapi.c - * - * Revision 1.12 2000/06/19 16:51:53 keil - * don't free skb in irq context - * - * Revision 1.11 2000/06/19 15:11:24 keil - * avoid use of freed structs - * changes from 2.4.0-ac21 - * - * Revision 1.10 2000/05/29 12:29:18 keil - * make pci_enable_dev compatible to 2.2 kernel versions - * - * Revision 1.9 2000/05/19 15:43:22 calle - * added calls to pci_device_start(). - * - * Revision 1.8 2000/04/03 16:38:05 calle - * made suppress_pollack static. - * - * Revision 1.7 2000/04/03 13:29:24 calle - * make Tim Waugh happy (module unload races in 2.3.99-pre3). - * no real problem there, but now it is much cleaner ... - * - * Revision 1.6 2000/03/17 12:21:08 calle - * send patchvalues now working. - * - * Revision 1.5 2000/03/16 15:21:03 calle - * Bugfix in c4_remove: loop 5 times instead of 4 :-( - * - * Revision 1.4 2000/02/02 18:36:03 calle - * - Modules are now locked while init_module is running - * - fixed problem with memory mapping if address is not aligned - * - * Revision 1.3 2000/01/25 14:37:39 calle - * new message after successful detection including card revision and - * used resources. - * - * Revision 1.2 2000/01/21 20:52:58 keil - * pci_find_subsys as local function for 2.2.X kernel - * - * Revision 1.1 2000/01/20 10:51:37 calle - * Added driver for C4. - * * */ @@ -122,15 +27,11 @@ #include "capilli.h" #include "avmcard.h" -static char *revision = "$Revision: 1.20.6.8 $"; +static char *revision = "$Revision: 1.20.6.10 $"; #undef CONFIG_C4_DEBUG #undef CONFIG_C4_POLLDEBUG -/* ------------------------------------------------------------- */ -#ifndef PCI_DEVICE_ID_AVM_C2 -#define PCI_DEVICE_ID_AVM_C2 0x1100 -#endif /* ------------------------------------------------------------- */ static int suppress_pollack; diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/avmb1/capi.c linux/drivers/isdn/avmb1/capi.c --- v2.4.5/linux/drivers/isdn/avmb1/capi.c Sat May 19 17:54:14 2001 +++ linux/drivers/isdn/avmb1/capi.c Wed Jun 27 17:10:55 2001 @@ -1,5 +1,5 @@ /* - * $Id: capi.c,v 1.44.6.11 2001/05/17 20:41:51 kai Exp $ + * $Id: capi.c,v 1.44.6.12 2001/06/09 15:14:15 kai Exp $ * * CAPI 2.0 Interface for Linux * @@ -43,7 +43,7 @@ #include "capifs.h" #endif -static char *revision = "$Revision: 1.44.6.11 $"; +static char *revision = "$Revision: 1.44.6.12 $"; MODULE_AUTHOR("Carsten Paeth (calle@calle.in-berlin.de)"); @@ -256,7 +256,6 @@ void capiminor_free(struct capiminor *mp) { struct capiminor **pp; - struct sk_buff *skb; pp = &minors; while (*pp) { @@ -264,12 +263,9 @@ *pp = (*pp)->next; if (mp->ttyskb) kfree_skb(mp->ttyskb); mp->ttyskb = 0; - while ((skb = skb_dequeue(&mp->recvqueue)) != 0) - kfree_skb(skb); - while ((skb = skb_dequeue(&mp->inqueue)) != 0) - kfree_skb(skb); - while ((skb = skb_dequeue(&mp->outqueue)) != 0) - kfree_skb(skb); + skb_queue_purge(&mp->recvqueue); + skb_queue_purge(&mp->inqueue); + skb_queue_purge(&mp->outqueue); capiminor_del_all_ack(mp); kmem_cache_free(capiminor_cachep, mp); MOD_DEC_USE_COUNT; @@ -411,15 +407,12 @@ static void capidev_free(struct capidev *cdev) { struct capidev **pp; - struct sk_buff *skb; if (cdev->applid) (*capifuncs->capi_release) (cdev->applid); cdev->applid = 0; - while ((skb = skb_dequeue(&cdev->recvqueue)) != 0) { - kfree_skb(skb); - } + skb_queue_purge(&cdev->recvqueue); pp=&capidev_openlist; while (*pp && *pp != cdev) pp = &(*pp)->next; diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/avmb1/capicmd.h linux/drivers/isdn/avmb1/capicmd.h --- v2.4.5/linux/drivers/isdn/avmb1/capicmd.h Sat May 19 17:54:14 2001 +++ linux/drivers/isdn/avmb1/capicmd.h Tue Jun 12 13:03:18 2001 @@ -1,31 +1,9 @@ /* - * $Id: capicmd.h,v 1.2 2000/03/03 15:50:42 calle Exp $ + * $Id: capicmd.h,v 1.2.6.1 2001/05/17 20:41:51 kai Exp $ * * CAPI 2.0 Interface for Linux * * Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de) - * - * $Log: capicmd.h,v $ - * Revision 1.2 2000/03/03 15:50:42 calle - * - kernel CAPI: - * - Changed parameter "param" in capi_signal from __u32 to void *. - * - rewrote notifier handling in kcapi.c - * - new notifier NCCI_UP and NCCI_DOWN - * - User CAPI: - * - /dev/capi20 is now a cloning device. - * - middleware extentions prepared. - * - capidrv.c - * - locking of list operations and module count updates. - * - * Revision 1.1 1997/03/04 21:50:30 calle - * Frirst version in isdn4linux - * - * Revision 2.2 1997/02/12 09:31:39 calle - * new version - * - * Revision 1.1 1997/01/31 10:32:20 calle - * Initial revision - * * */ #ifndef __CAPICMD_H__ diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/avmb1/capifs.c linux/drivers/isdn/avmb1/capifs.c --- v2.4.5/linux/drivers/isdn/avmb1/capifs.c Thu May 24 15:42:58 2001 +++ linux/drivers/isdn/avmb1/capifs.c Tue Jun 12 13:03:18 2001 @@ -1,10 +1,10 @@ /* * $Id: capifs.c,v 1.14.6.7 2001/05/24 08:29:08 kai Exp $ - * + * * (c) Copyright 2000 by Carsten Paeth (calle@calle.de) * * Heavily based on devpts filesystem from H. Peter Anvin - * + * */ #include diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/avmb1/capifs.h linux/drivers/isdn/avmb1/capifs.h --- v2.4.5/linux/drivers/isdn/avmb1/capifs.h Sat May 19 17:54:14 2001 +++ linux/drivers/isdn/avmb1/capifs.h Tue Jun 12 13:03:18 2001 @@ -1,23 +1,7 @@ /* - * $Id: capifs.h,v 1.2 2000/03/08 17:06:33 calle Exp $ + * $Id: capifs.h,v 1.2.6.1 2001/05/17 20:41:51 kai Exp $ * * (c) Copyright 2000 by Carsten Paeth (calle@calle.de) - * - * $Log: capifs.h,v $ - * Revision 1.2 2000/03/08 17:06:33 calle - * - changes for devfs and 2.3.49 - * - capifs now configurable (no need with devfs) - * - New Middleware ioctl CAPI_NCCI_GETUNIT - * - Middleware again tested with 2.2.14 and 2.3.49 (with and without devfs) - * - * Revision 1.1 2000/03/03 16:48:38 calle - * - Added CAPI2.0 Middleware support (CONFIG_ISDN_CAPI) - * It is now possible to create a connection with a CAPI2.0 applikation - * and than to handle the data connection from /dev/capi/ (capifs) and also - * using async or sync PPP on this connection. - * The two major device number 190 and 191 are not confirmed yet, - * but I want to save the code in cvs, before I go on. - * * */ diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/avmb1/capiutil.h linux/drivers/isdn/avmb1/capiutil.h --- v2.4.5/linux/drivers/isdn/avmb1/capiutil.h Sat May 19 17:54:14 2001 +++ linux/drivers/isdn/avmb1/capiutil.h Tue Jun 12 13:03:18 2001 @@ -1,45 +1,10 @@ /* - * $Id: capiutil.h,v 1.5 2000/03/03 15:50:42 calle Exp $ + * $Id: capiutil.h,v 1.5.6.1 2001/05/17 20:41:51 kai Exp $ * * CAPI 2.0 defines & types * * From CAPI 2.0 Development Kit AVM 1995 (capi20.h) * Rewritten for Linux 1996 by Carsten Paeth (calle@calle.in-berlin.de) - * - * $Log: capiutil.h,v $ - * Revision 1.5 2000/03/03 15:50:42 calle - * - kernel CAPI: - * - Changed parameter "param" in capi_signal from __u32 to void *. - * - rewrote notifier handling in kcapi.c - * - new notifier NCCI_UP and NCCI_DOWN - * - User CAPI: - * - /dev/capi20 is now a cloning device. - * - middleware extentions prepared. - * - capidrv.c - * - locking of list operations and module count updates. - * - * Revision 1.4 1999/09/15 08:16:03 calle - * Implementation of 64Bit extention complete. - * - * Revision 1.3 1999/09/07 09:02:53 calle - * SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and - * DATA_B3_IND is always directly after the CAPI message. The "Data" member - * ist never used inside the kernel. - * - * Revision 1.2 1997/05/18 09:24:19 calle - * added verbose disconnect reason reporting to avmb1. - * some fixes in capi20 interface. - * changed info messages for B1-PCI - * - * Revision 1.1 1997/03/04 21:50:35 calle - * Frirst version in isdn4linux - * - * Revision 2.2 1997/02/12 09:31:39 calle - * new version - * - * Revision 1.1 1997/01/31 10:32:20 calle - * Initial revision - * * */ #ifndef __CAPIUTIL_H__ diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/avmb1/kcapi.c linux/drivers/isdn/avmb1/kcapi.c --- v2.4.5/linux/drivers/isdn/avmb1/kcapi.c Sat May 19 17:54:14 2001 +++ linux/drivers/isdn/avmb1/kcapi.c Wed Jun 27 17:10:55 2001 @@ -1,128 +1,10 @@ /* - * $Id: kcapi.c,v 1.21.6.5 2001/03/21 08:52:21 kai Exp $ + * $Id: kcapi.c,v 1.21.6.7 2001/06/09 15:14:15 kai Exp $ * * Kernel CAPI 2.0 Module * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * - * $Log: kcapi.c,v $ - * Revision 1.21.6.5 2001/03/21 08:52:21 kai - * merge from main branch: fix buffer for revision string (calle) - * - * Revision 1.21.6.4 2001/03/15 15:11:24 kai - * *** empty log message *** - * - * Revision 1.21.6.3 2001/03/13 16:17:08 kai - * spelling fixes from 2.4.3-pre - * - * Revision 1.21.6.2 2001/02/13 11:43:29 kai - * more compatility changes for 2.2.19 - * - * Revision 1.21.6.1 2000/12/10 23:39:19 kai - * in 2.4 we don't have tq_scheduler anymore. - * also add one supported card to hfc_pci.c - * (from main branch) - * - * Revision 1.21 2000/11/23 20:45:14 kai - * fixed module_init/exit stuff - * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. - * - * Revision 1.20 2000/11/19 17:01:53 kai - * compatibility cleanup - part 2 - * - * Revision 1.19 2000/11/01 14:05:02 calle - * - use module_init/module_exit from linux/init.h. - * - all static struct variables are initialized with "membername:" now. - * - avm_cs.c, let it work with newer pcmcia-cs. - * - * Revision 1.18 2000/07/20 10:22:27 calle - * - Made procfs function cleaner and removed variable "begin". - * - * Revision 1.17 2000/04/21 13:00:56 calle - * Bugfix: driver_proc_info was also wrong. - * - * Revision 1.16 2000/04/21 12:38:42 calle - * Bugfix: error in proc_ functions, begin-off => off-begin - * - * Revision 1.15 2000/04/06 15:01:25 calle - * Bugfix: crash in capidrv.c when reseting a capi controller. - * - changed code order on remove of controller. - * - using tq_schedule for notifier in kcapi.c. - * - now using spin_lock_irqsave() and spin_unlock_irqrestore(). - * strange: sometimes even MP hang on unload of isdn.o ... - * - * Revision 1.14 2000/04/03 13:29:25 calle - * make Tim Waugh happy (module unload races in 2.3.99-pre3). - * no real problem there, but now it is much cleaner ... - * - * Revision 1.13 2000/03/03 15:50:42 calle - * - kernel CAPI: - * - Changed parameter "param" in capi_signal from __u32 to void *. - * - rewrote notifier handling in kcapi.c - * - new notifier NCCI_UP and NCCI_DOWN - * - User CAPI: - * - /dev/capi20 is now a cloning device. - * - middleware extentions prepared. - * - capidrv.c - * - locking of list operations and module count updates. - * - * Revision 1.12 2000/01/28 16:45:39 calle - * new manufacturer command KCAPI_CMD_ADDCARD (generic addcard), - * will search named driver and call the add_card function if one exist. - * - * Revision 1.11 1999/11/23 13:29:29 calle - * Bugfix: incoming capi message were never traced. - * - * Revision 1.10 1999/10/26 15:30:32 calle - * Generate error message if user want to add card, but driver module is - * not loaded. - * - * Revision 1.9 1999/10/11 22:04:12 keil - * COMPAT_NEED_UACCESS (no include in isdn_compat.h) - * - * Revision 1.8 1999/09/10 17:24:18 calle - * Changes for proposed standard for CAPI2.0: - * - AK148 "Linux Exention" - * - * Revision 1.7 1999/09/04 06:20:05 keil - * Changes from kernel set_current_state() - * - * Revision 1.6 1999/07/20 06:41:49 calle - * Bugfix: After the redesign of the AVM B1 driver, the driver didn't even - * compile, if not selected as modules. - * - * Revision 1.5 1999/07/09 15:05:48 keil - * compat.h is now isdn_compat.h - * - * Revision 1.4 1999/07/08 14:15:17 calle - * Forgot to count down ncards in drivercb_detach_ctr. - * - * Revision 1.3 1999/07/06 07:42:02 calle - * - changes in /proc interface - * - check and changed calls to [dev_]kfree_skb and [dev_]alloc_skb. - * - * Revision 1.2 1999/07/05 15:09:52 calle - * - renamed "appl_release" to "appl_released". - * - version und profile data now cleared on controller reset - * - extended /proc interface, to allow driver and controller specific - * informations to include by driver hackers. - * - * Revision 1.1 1999/07/01 15:26:42 calle - * complete new version (I love it): - * + new hardware independed "capi_driver" interface that will make it easy to: - * - support other controllers with CAPI-2.0 (i.e. USB Controller) - * - write a CAPI-2.0 for the passive cards - * - support serial link CAPI-2.0 boxes. - * + wrote "capi_driver" for all supported cards. - * + "capi_driver" (supported cards) now have to be configured with - * make menuconfig, in the past all supported cards where included - * at once. - * + new and better informations in /proc/capi/ - * + new ioctl to switch trace of capi messages per controller - * using "avmcapictrl trace [contr] on|off|...." - * + complete testcircle with all supported cards and also the - * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. - * */ #define CONFIG_AVMB1_COMPAT @@ -148,7 +30,7 @@ #include #endif -static char *revision = "$Revision: 1.21.6.6 $"; +static char *revision = "$Revision: 1.21.6.7 $"; /* ------------------------------------------------------------- */ @@ -1247,14 +1129,12 @@ static __u16 capi_release(__u16 applid) { - struct sk_buff *skb; int i; if (!VALID_APPLID(applid) || APPL(applid)->releasing) return CAPI_ILLAPPNR; APPL(applid)->releasing++; - while ((skb = skb_dequeue(&APPL(applid)->recv_queue)) != 0) - kfree_skb(skb); + skb_queue_purge(&APPL(applid)->recv_queue); for (i = 0; i < CAPI_MAXCONTR; i++) { if (cards[i].cardstate != CARD_RUNNING) continue; diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/avmb1/t1isa.c linux/drivers/isdn/avmb1/t1isa.c --- v2.4.5/linux/drivers/isdn/avmb1/t1isa.c Sat May 19 17:54:14 2001 +++ linux/drivers/isdn/avmb1/t1isa.c Tue Jun 12 13:03:18 2001 @@ -1,104 +1,10 @@ /* - * $Id: t1isa.c,v 1.16.6.4 2001/03/21 08:52:21 kai Exp $ + * $Id: t1isa.c,v 1.16.6.6 2001/05/17 21:15:33 kai Exp $ * * Module for AVM T1 HEMA-card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * - * $Log: t1isa.c,v $ - * Revision 1.16.6.4 2001/03/21 08:52:21 kai - * merge from main branch: fix buffer for revision string (calle) - * - * Revision 1.16.6.3 2001/03/15 15:11:24 kai - * *** empty log message *** - * - * Revision 1.16.6.2 2001/02/16 16:43:24 kai - * Changes from -ac16, little bug fixes, typos and the like - * - * Revision 1.16.6.1 2001/02/13 11:43:29 kai - * more compatility changes for 2.2.19 - * - * Revision 1.16 2000/11/23 20:45:14 kai - * fixed module_init/exit stuff - * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. - * - * Revision 1.15 2000/11/01 14:05:02 calle - * - use module_init/module_exit from linux/init.h. - * - all static struct variables are initialized with "membername:" now. - * - avm_cs.c, let it work with newer pcmcia-cs. - * - * Revision 1.14 2000/10/10 17:44:19 kai - * changes from/for 2.2.18 - * - * Revision 1.13 2000/08/04 15:36:31 calle - * copied wrong from file to file :-( - * - * Revision 1.12 2000/08/04 12:20:08 calle - * - Fix unsigned/signed warning in the right way ... - * - * Revision 1.11 2000/04/03 13:29:25 calle - * make Tim Waugh happy (module unload races in 2.3.99-pre3). - * no real problem there, but now it is much cleaner ... - * - * Revision 1.10 2000/02/02 18:36:04 calle - * - Modules are now locked while init_module is running - * - fixed problem with memory mapping if address is not aligned - * - * Revision 1.9 2000/01/25 14:37:39 calle - * new message after successful detection including card revision and - * used resources. - * - * Revision 1.8 1999/11/05 16:38:01 calle - * Cleanups before kernel 2.4: - * - Changed all messages to use card->name or driver->name instead of - * constant string. - * - Moved some data from struct avmcard into new struct avmctrl_info. - * Changed all lowlevel capi driver to match the new structur. - * - * Revision 1.7 1999/09/15 08:16:03 calle - * Implementation of 64Bit extention complete. - * - * Revision 1.6 1999/09/07 09:02:53 calle - * SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and - * DATA_B3_IND is always directly after the CAPI message. The "Data" member - * ist never used inside the kernel. - * - * Revision 1.5 1999/08/22 20:26:28 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.4 1999/07/09 15:05:50 keil - * compat.h is now isdn_compat.h - * - * Revision 1.3 1999/07/06 07:42:04 calle - * - changes in /proc interface - * - check and changed calls to [dev_]kfree_skb and [dev_]alloc_skb. - * - * Revision 1.2 1999/07/05 15:09:54 calle - * - renamed "appl_release" to "appl_released". - * - version und profile data now cleared on controller reset - * - extended /proc interface, to allow driver and controller specific - * informations to include by driver hackers. - * - * Revision 1.1 1999/07/01 15:26:44 calle - * complete new version (I love it): - * + new hardware independed "capi_driver" interface that will make it easy to: - * - support other controllers with CAPI-2.0 (i.e. USB Controller) - * - write a CAPI-2.0 for the passive cards - * - support serial link CAPI-2.0 boxes. - * + wrote "capi_driver" for all supported cards. - * + "capi_driver" (supported cards) now have to be configured with - * make menuconfig, in the past all supported cards where included - * at once. - * + new and better informations in /proc/capi/ - * + new ioctl to switch trace of capi messages per controller - * using "avmcapictrl trace [contr] on|off|...." - * + complete testcircle with all supported cards and also the - * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. - * - * */ #include diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/avmb1/t1pci.c linux/drivers/isdn/avmb1/t1pci.c --- v2.4.5/linux/drivers/isdn/avmb1/t1pci.c Sat May 19 17:54:14 2001 +++ linux/drivers/isdn/avmb1/t1pci.c Tue Jun 12 13:03:18 2001 @@ -1,80 +1,10 @@ /* - * $Id: t1pci.c,v 1.13.6.3 2001/03/21 08:52:21 kai Exp $ + * $Id: t1pci.c,v 1.13.6.5 2001/05/17 20:41:51 kai Exp $ * * Module for AVM T1 PCI-card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * - * $Log: t1pci.c,v $ - * Revision 1.13.6.3 2001/03/21 08:52:21 kai - * merge from main branch: fix buffer for revision string (calle) - * - * Revision 1.13.6.2 2001/02/13 11:43:29 kai - * more compatility changes for 2.2.19 - * - * Revision 1.13.6.1 2000/11/28 12:02:45 kai - * MODULE_DEVICE_TABLE for 2.4 - * - * Revision 1.13.2.2 2000/11/26 17:47:53 kai - * added PCI_DEV_TABLE for 2.4 - * - * Revision 1.13.2.1 2000/11/26 17:14:19 kai - * fix device ids - * also needs patches to include/linux/pci_ids.h - * - * Revision 1.13 2000/11/23 20:45:14 kai - * fixed module_init/exit stuff - * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. - * - * Revision 1.12 2000/11/01 14:05:02 calle - * - use module_init/module_exit from linux/init.h. - * - all static struct variables are initialized with "membername:" now. - * - avm_cs.c, let it work with newer pcmcia-cs. - * - * Revision 1.11 2000/08/08 09:24:19 calle - * calls to pci_enable_device surounded by #ifndef COMPAT_HAS_2_2_PCI - * - * Revision 1.10 2000/07/20 10:21:21 calle - * Bugfix: driver will not be unregistered, if not cards were detected. - * this result in an oops in kcapi.c - * - * Revision 1.9 2000/05/19 15:43:22 calle - * added calls to pci_device_start(). - * - * Revision 1.8 2000/05/06 00:52:36 kai - * merged changes from kernel tree - * fixed timer and net_device->name breakage - * - * Revision 1.7 2000/04/07 15:26:55 calle - * better error message if cabel not connected or T1 has no power. - * - * Revision 1.6 2000/04/03 13:29:25 calle - * make Tim Waugh happy (module unload races in 2.3.99-pre3). - * no real problem there, but now it is much cleaner ... - * - * Revision 1.5 2000/02/02 18:36:04 calle - * - Modules are now locked while init_module is running - * - fixed problem with memory mapping if address is not aligned - * - * Revision 1.4 2000/01/25 14:33:38 calle - * - Added Support AVM B1 PCI V4.0 (tested with prototype) - * - splitted up t1pci.c into b1dma.c for common function with b1pciv4 - * - support for revision register - * - * Revision 1.3 1999/11/13 21:27:16 keil - * remove KERNELVERSION - * - * Revision 1.2 1999/11/05 16:38:02 calle - * Cleanups before kernel 2.4: - * - Changed all messages to use card->name or driver->name instead of - * constant string. - * - Moved some data from struct avmcard into new struct avmctrl_info. - * Changed all lowlevel capi driver to match the new structur. - * - * Revision 1.1 1999/10/26 15:31:42 calle - * Added driver for T1-PCI card. - * - * */ #include diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/eicon/common.c linux/drivers/isdn/eicon/common.c --- v2.4.5/linux/drivers/isdn/eicon/common.c Sat May 19 17:43:06 2001 +++ linux/drivers/isdn/eicon/common.c Wed Jun 27 17:10:55 2001 @@ -857,7 +857,7 @@ { int i; - bzero(card_list, sizeof(dia_card_list_t)); + memset(card_list, 0, sizeof(dia_card_list_t)); for(i = 0; i < DivasCardNext; i++) { diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/eicon/linchr.c linux/drivers/isdn/eicon/linchr.c --- v2.4.5/linux/drivers/isdn/eicon/linchr.c Fri Mar 2 11:12:08 2001 +++ linux/drivers/isdn/eicon/linchr.c Wed Jun 27 17:10:55 2001 @@ -46,161 +46,110 @@ int do_ioctl(struct inode *pDivasInode, struct file *pDivasFile, unsigned int command, unsigned long arg) { - dia_load_t *pDivaLoad; - dia_start_t *pDivaStart; - dia_config_t *pDivaConfig; - dia_log_t *pDivaLog; byte *pUserCards, card_i; word wCardNum; - mem_block_t *mem_block; switch (command) { case DIA_IOCTL_CONFIG: - pDivaConfig = (dia_config_t *) arg; - - if (!verify_area(VERIFY_READ, pDivaConfig, sizeof(dia_config_t))) - { - DivasCardConfig(pDivaConfig); - } - else - { - printk(KERN_WARNING "Divas: Unable to complete CONFIG ioctl (verify area failed)\n"); - return -1; - } - return 0; + { + dia_config_t DivaConfig; + if (copy_from_user(&DivaConfig, (void *)arg, sizeof(dia_config_t))) + return -EFAULT; + DivasCardConfig(&DivaConfig); + return 0; + } case DIA_IOCTL_DETECT: pUserCards = (byte *) arg; if (!verify_area(VERIFY_WRITE, pUserCards, 20)) { - put_user(DivasCardNext, pUserCards++); + if(__put_user(DivasCardNext, pUserCards++)) + return -EFAULT; for (card_i=1; card_i < 20; card_i++) { - put_user((byte) DivasCards[card_i - 1].cfg.card_type, pUserCards++); + if(__put_user((byte) DivasCards[card_i - 1].cfg.card_type, pUserCards++)) + return -EFAULT; } } - else - { - printk(KERN_WARNING "Divas: Unable to complete DETECT ioctl (verify area failed)\n"); - return -1; - } + else return -EFAULT; + return 0; case DIA_IOCTL_START: - pDivaStart = (dia_start_t *) arg; - - if (!verify_area(VERIFY_READ, pDivaStart, sizeof(dia_start_t))) - { - return DivasCardStart(pDivaStart->card_id); - } - else - { - printk(KERN_WARNING "Divas: Unable to complete START ioctl (verify area failed)\n"); - return -1; - } - + { + dia_start_t DivaStart; + if (copy_from_user(&DivaStart, (void *)arg, sizeof(dia_start_t))) + return -EFAULT; + return DivasCardStart(DivaStart.card_id); + } case DIA_IOCTL_FLAVOUR: return 0; case DIA_IOCTL_LOAD: - pDivaLoad = (dia_load_t *) arg; - if (!verify_area(VERIFY_READ, pDivaLoad->code,pDivaLoad->length)) + { + dia_load_t DivaLoad; + if(copy_from_user(&DivaLoad, (void *)arg, sizeof(dia_load_t))) + return -EFAULT; + if (!verify_area(VERIFY_READ, DivaLoad.code,DivaLoad.length)) { - if (DivasCardLoad(pDivaLoad)) + if (DivasCardLoad(&DivaLoad)) { printk(KERN_WARNING "Divas: Error loading DIVA Server adapter\n"); return -EINVAL; } + return 0; } - else - { - printk(KERN_WARNING "Divas: Error in LOAD parameters (verify failed)\n"); - return -EINVAL; - } - return 0; - + return -EFAULT; + } case DIA_IOCTL_LOG: - pDivaLog = (dia_log_t *) arg; - - if (!verify_area(VERIFY_READ, pDivaLog, sizeof(dia_log_t))) - { - DivasLog(pDivaLog); - } - else - { - printk(KERN_WARNING "Divas: Unable to complete LOG ioctl (verify area failed)\n"); - return -1; - } + { + dia_log_t DivaLog; + if (copy_from_user(&DivaLog, (void *) arg, sizeof(dia_log_t))) + return -EFAULT; + DivasLog(&DivaLog); return 0; + } case DIA_IOCTL_XLOG_REQ: - - if (!verify_area(VERIFY_READ, (void *)arg, sizeof(word))) - { - wCardNum = * (word *) arg; - DivasXlogReq(wCardNum); - } - else - { - printk(KERN_WARNING "Divas: Unable to complete XLOG_REQ ioctl (verify area failed)\n"); - return -1; - } + if(get_user(wCardNum, (word *) arg)) + return -EFAULT; + DivasXlogReq(wCardNum); return 0; case DIA_IOCTL_GET_NUM: - - if (!verify_area(VERIFY_WRITE, (void *)arg, sizeof(int))) - { - * (int *) arg = DivasCardNext; - } - else - { - printk(KERN_WARNING "Divas: Unable to complete GET_NUM ioctl (verify area failed)\n"); - return -1; - } + if(put_user(DivasCardNext, (int *)arg)) + return -EFAULT; return 0; case DIA_IOCTL_GET_LIST: + { + dia_card_list_t cards; DPRINTF(("divas: DIA_IOCTL_GET_LIST")); - - if (!verify_area(VERIFY_WRITE, (void *)arg, sizeof(dia_card_list_t))) - { - DivasGetList((dia_card_list_t *)arg); - } - else - { - printk(KERN_WARNING "Divas: Unable to complete GET_LIST ioctl (verify area failed)\n"); - return -1; - } + DivasGetList(&cards); + if(copy_to_user((void *)arg, &cards, sizeof(cards))) + return -EFAULT; return 0; - + } case DIA_IOCTL_GET_MEM: - mem_block = (mem_block_t *) arg; - - if (!verify_area(VERIFY_WRITE, mem_block, sizeof(mem_block_t))) - { - DivasGetMem(mem_block); - } - else - { - printk(KERN_WARNING "Divas: Unable to complete GET_MEM ioctl (verify area failed)\n"); - return -1; - } + { + mem_block_t mem_block; + if (copy_from_user(&mem_block, (void *)arg, sizeof(mem_block_t))) + return -EFAULT; + DivasGetMem(&mem_block); return 0; + } case DIA_IOCTL_UNLOCK: UnlockDivas(); return 0; default: - printk(KERN_WARNING "Divas: Unknown IOCTL Received by DIVA Server Driver(%d)\n", command); return -EINVAL; } - return -EINVAL; } diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/hisax/amd7930.c linux/drivers/isdn/hisax/amd7930.c --- v2.4.5/linux/drivers/isdn/hisax/amd7930.c Fri Mar 2 11:12:08 2001 +++ linux/drivers/isdn/hisax/amd7930.c Mon Jul 2 14:07:55 2001 @@ -1,4 +1,4 @@ -/* $Id: amd7930.c,v 1.5.6.1 2001/02/16 16:43:25 kai Exp $ +/* $Id: amd7930.c,v 1.5.6.3 2001/06/11 22:08:37 kai Exp $ * * HiSax ISDN driver - chip specific routines for AMD 7930 * @@ -94,7 +94,7 @@ #include "rawhdlc.h" #include -static const char *amd7930_revision = "$Revision: 1.5.6.1 $"; +static const char *amd7930_revision = "$Revision: 1.5.6.3 $"; #define RCV_BUFSIZE 1024 /* Size of raw receive buffer in bytes */ #define RCV_BUFBLKS 4 /* Number of blocks to divide buffer into @@ -362,12 +362,8 @@ amd7930_bclose(0, bcs->channel); if (test_bit(BC_FLG_INIT, &bcs->Flag)) { - while ((skb = skb_dequeue(&bcs->rqueue))) { - dev_kfree_skb(skb); - } - while ((skb = skb_dequeue(&bcs->squeue))) { - dev_kfree_skb(skb); - } + skb_queue_purge(&bcs->rqueue); + skb_queue_purge(&bcs->squeue); } test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); } diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/hisax/avm_pci.c linux/drivers/isdn/hisax/avm_pci.c --- v2.4.5/linux/drivers/isdn/hisax/avm_pci.c Fri Mar 2 11:12:08 2001 +++ linux/drivers/isdn/hisax/avm_pci.c Mon Jul 2 14:07:55 2001 @@ -1,4 +1,4 @@ -/* $Id: avm_pci.c,v 1.22.6.4 2001/02/16 16:43:25 kai Exp $ +/* $Id: avm_pci.c,v 1.22.6.5 2001/06/09 15:14:16 kai Exp $ * * avm_pci.c low level stuff for AVM Fritz!PCI and ISA PnP isdn cards * Thanks to AVM, Berlin for informations @@ -18,7 +18,7 @@ #include extern const char *CardType[]; -static const char *avm_pci_rev = "$Revision: 1.22.6.4 $"; +static const char *avm_pci_rev = "$Revision: 1.22.6.5 $"; #define AVM_FRITZ_PCI 1 #define AVM_FRITZ_PNP 2 @@ -591,8 +591,8 @@ kfree(bcs->blog); bcs->blog = NULL; } - discard_queue(&bcs->rqueue); - discard_queue(&bcs->squeue); + skb_queue_purge(&bcs->rqueue); + skb_queue_purge(&bcs->squeue); if (bcs->tx_skb) { dev_kfree_skb_any(bcs->tx_skb); bcs->tx_skb = NULL; diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/hisax/callc.c linux/drivers/isdn/hisax/callc.c --- v2.4.5/linux/drivers/isdn/hisax/callc.c Mon Mar 26 15:38:19 2001 +++ linux/drivers/isdn/hisax/callc.c Mon Jul 2 14:07:55 2001 @@ -1,4 +1,4 @@ -/* $Id: callc.c,v 2.51.6.2 2001/03/13 16:17:08 kai Exp $ +/* $Id: callc.c,v 2.51.6.4 2001/06/09 15:14:17 kai Exp $ * * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden @@ -20,7 +20,7 @@ #define MOD_USE_COUNT ( GET_USE_COUNT (&__this_module)) #endif /* MODULE */ -const char *lli_revision = "$Revision: 2.51.6.2 $"; +const char *lli_revision = "$Revision: 2.51.6.4 $"; extern struct IsdnCard cards[]; extern int nrcards; @@ -66,19 +66,6 @@ return (struct IsdnCardState *) 0; } -int -discard_queue(struct sk_buff_head *q) -{ - struct sk_buff *skb; - int ret=0; - - while ((skb = skb_dequeue(q))) { - dev_kfree_skb(skb); - ret++; - } - return(ret); -} - static void link_debug(struct Channel *chanp, int direction, char *fmt, ...) { @@ -850,14 +837,14 @@ #define FNCOUNT (sizeof(fnlist)/sizeof(struct FsmNode)) -void __init +int __init CallcNew(void) { callcfsm.state_count = STATE_COUNT; callcfsm.event_count = EVENT_COUNT; callcfsm.strEvent = strEvent; callcfsm.strState = strState; - FsmNew(&callcfsm, fnlist, FNCOUNT); + return FsmNew(&callcfsm, fnlist, FNCOUNT); } void diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/hisax/config.c linux/drivers/isdn/hisax/config.c --- v2.4.5/linux/drivers/isdn/hisax/config.c Wed Apr 18 11:49:13 2001 +++ linux/drivers/isdn/hisax/config.c Mon Jul 2 14:07:55 2001 @@ -1,4 +1,4 @@ -/* $Id: config.c,v 2.57.6.13 2001/04/08 19:41:28 kai Exp $ +/* $Id: config.c,v 2.57.6.15 2001/06/09 15:14:17 kai Exp $ * * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden @@ -837,8 +837,8 @@ csta->bcs->BC_Close(csta->bcs); } - discard_queue(&csta->rq); - discard_queue(&csta->sq); + skb_queue_purge(&csta->rq); + skb_queue_purge(&csta->sq); if (csta->rcvbuf) { kfree(csta->rcvbuf); csta->rcvbuf = NULL; @@ -1332,15 +1332,28 @@ static int __init HiSax_init(void) { - int i,j; + int i, retval; +#ifdef MODULE + int j; int nzproto = 0; +#endif HiSaxVersion(); - CallcNew(); - Isdnl3New(); - Isdnl2New(); - TeiNew(); - Isdnl1New(); + retval = CallcNew(); + if (retval) + goto out; + retval = Isdnl3New(); + if (retval) + goto out_callc; + retval = Isdnl2New(); + if (retval) + goto out_isdnl3; + retval = TeiNew(); + if (retval) + goto out_isdnl2; + retval = Isdnl1New(); + if (retval) + goto out_tei; #ifdef MODULE if (!type[0]) { @@ -1487,17 +1500,26 @@ printk(KERN_DEBUG "HiSax: Total %d card%s defined\n", nrcards, (nrcards > 1) ? "s" : ""); - if (HiSax_inithardware(NULL)) { - /* Install only, if at least one card found */ - return (0); - } else { - Isdnl1Free(); - TeiFree(); - Isdnl2Free(); - Isdnl3Free(); - CallcFree(); - return -EIO; + /* Install only, if at least one card found */ + if (!HiSax_inithardware(NULL)) { + retval = -EIO; + goto out_isdnl1; } + + return 0; + + out_isdnl1: + Isdnl1Free(); + out_tei: + TeiFree(); + out_isdnl2: + Isdnl2Free(); + out_isdnl3: + Isdnl3Free(); + out_callc: + CallcFree(); + out: + return retval; } static void __exit HiSax_exit(void) diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/hisax/elsa_ser.c linux/drivers/isdn/hisax/elsa_ser.c --- v2.4.5/linux/drivers/isdn/hisax/elsa_ser.c Fri Mar 2 11:12:08 2001 +++ linux/drivers/isdn/hisax/elsa_ser.c Mon Jul 2 14:07:55 2001 @@ -1,4 +1,4 @@ -/* $Id: elsa_ser.c,v 2.10.6.1 2001/02/16 16:43:26 kai Exp $ +/* $Id: elsa_ser.c,v 2.10.6.2 2001/06/09 15:14:17 kai Exp $ * * stuff for the serial modem on ELSA cards * @@ -439,8 +439,6 @@ void close_elsastate(struct BCState *bcs) { - struct sk_buff *skb; - modehscx(bcs, 0, bcs->channel); if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { if (bcs->hw.hscx.rcvbuf) { @@ -448,12 +446,8 @@ kfree(bcs->hw.hscx.rcvbuf); bcs->hw.hscx.rcvbuf = NULL; } - while ((skb = skb_dequeue(&bcs->rqueue))) { - dev_kfree_skb_any(skb); - } - while ((skb = skb_dequeue(&bcs->squeue))) { - dev_kfree_skb_any(skb); - } + skb_queue_purge(&bcs->rqueue); + skb_queue_purge(&bcs->squeue); if (bcs->tx_skb) { dev_kfree_skb_any(bcs->tx_skb); bcs->tx_skb = NULL; diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/hisax/fsm.c linux/drivers/isdn/hisax/fsm.c --- v2.4.5/linux/drivers/isdn/hisax/fsm.c Fri Mar 2 11:12:08 2001 +++ linux/drivers/isdn/hisax/fsm.c Tue Jun 12 10:34:48 2001 @@ -1,4 +1,4 @@ -/* $Id: fsm.c,v 1.14.6.1 2001/02/16 16:43:26 kai Exp $ +/* $Id: fsm.c,v 1.14.6.2 2001/05/26 15:19:57 kai Exp $ * * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden @@ -15,13 +15,16 @@ #define FSM_TIMER_DEBUG 0 -void __init +int __init FsmNew(struct Fsm *fsm, struct FsmNode *fnlist, int fncount) { int i; fsm->jumpmatrix = (FSMFNPTR *) kmalloc(sizeof (FSMFNPTR) * fsm->state_count * fsm->event_count, GFP_KERNEL); + if (!fsm->jumpmatrix) + return -ENOMEM; + memset(fsm->jumpmatrix, 0, sizeof (FSMFNPTR) * fsm->state_count * fsm->event_count); for (i = 0; i < fncount; i++) @@ -32,6 +35,7 @@ } else fsm->jumpmatrix[fsm->state_count * fnlist[i].event + fnlist[i].state] = (FSMFNPTR) fnlist[i].routine; + return 0; } void diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/hisax/gazel.c linux/drivers/isdn/hisax/gazel.c --- v2.4.5/linux/drivers/isdn/hisax/gazel.c Fri Mar 2 11:12:08 2001 +++ linux/drivers/isdn/hisax/gazel.c Tue Jun 12 10:34:48 2001 @@ -1,4 +1,4 @@ -/* $Id: gazel.c,v 2.11.6.4 2001/02/16 16:43:26 kai Exp $ +/* $Id: gazel.c,v 2.11.6.6 2001/06/08 08:48:46 kai Exp $ * * gazel.c low level stuff for Gazel isdn cards * @@ -19,7 +19,7 @@ #include extern const char *CardType[]; -const char *gazel_revision = "$Revision: 2.11.6.4 $"; +const char *gazel_revision = "$Revision: 2.11.6.6 $"; #define R647 1 #define R685 2 @@ -439,10 +439,6 @@ reserve_regions(struct IsdnCard *card, struct IsdnCardState *cs) { unsigned int i, base = 0, adr = 0, len = 0; - long flags; - - save_flags(flags); - cli(); switch (cs->subtyp) { case R647: @@ -487,17 +483,15 @@ break; } - restore_flags(flags); return 0; error: - restore_flags(flags); printk(KERN_WARNING "Gazel: %s io ports 0x%x-0x%x already in use\n", CardType[cs->typ], adr, adr + len); return 1; } -static int +static int __init setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs) { printk(KERN_INFO "Gazel: ISA PnP card automatic recognition\n"); @@ -546,7 +540,7 @@ static struct pci_dev *dev_tel __initdata = NULL; -static int +static int __init setup_gazelpci(struct IsdnCardState *cs) { u_int pci_ioaddr0 = 0, pci_ioaddr1 = 0; diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/hisax/hfc_2bds0.c linux/drivers/isdn/hisax/hfc_2bds0.c --- v2.4.5/linux/drivers/isdn/hisax/hfc_2bds0.c Fri Mar 2 11:12:08 2001 +++ linux/drivers/isdn/hisax/hfc_2bds0.c Mon Jul 2 14:07:55 2001 @@ -1,4 +1,4 @@ -/* $Id: hfc_2bds0.c,v 1.15.6.1 2001/02/16 16:43:26 kai Exp $ +/* $Id: hfc_2bds0.c,v 1.15.6.2 2001/06/09 15:14:17 kai Exp $ * * specific routines for CCD's HFC 2BDS0 * @@ -568,8 +568,8 @@ { mode_2bs0(bcs, 0, bcs->channel); if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { - discard_queue(&bcs->rqueue); - discard_queue(&bcs->squeue); + skb_queue_purge(&bcs->rqueue); + skb_queue_purge(&bcs->squeue); if (bcs->tx_skb) { dev_kfree_skb_any(bcs->tx_skb); bcs->tx_skb = NULL; diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/hisax/hfc_2bs0.c linux/drivers/isdn/hisax/hfc_2bs0.c --- v2.4.5/linux/drivers/isdn/hisax/hfc_2bs0.c Fri Mar 2 11:12:08 2001 +++ linux/drivers/isdn/hisax/hfc_2bs0.c Mon Jul 2 14:07:55 2001 @@ -1,4 +1,4 @@ -/* $Id: hfc_2bs0.c,v 1.17.6.1 2001/02/16 16:43:27 kai Exp $ +/* $Id: hfc_2bs0.c,v 1.17.6.2 2001/06/09 15:14:17 kai Exp $ * * specific routines for CCD's HFC 2BS0 * @@ -532,8 +532,8 @@ { mode_hfc(bcs, 0, bcs->channel); if (test_bit(BC_FLG_INIT, &bcs->Flag)) { - discard_queue(&bcs->rqueue); - discard_queue(&bcs->squeue); + skb_queue_purge(&bcs->rqueue); + skb_queue_purge(&bcs->squeue); if (bcs->tx_skb) { dev_kfree_skb_any(bcs->tx_skb); bcs->tx_skb = NULL; diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/hisax/hfc_pci.c linux/drivers/isdn/hisax/hfc_pci.c --- v2.4.5/linux/drivers/isdn/hisax/hfc_pci.c Wed Apr 18 11:49:13 2001 +++ linux/drivers/isdn/hisax/hfc_pci.c Mon Jul 2 14:07:55 2001 @@ -1,4 +1,4 @@ -/* $Id: hfc_pci.c,v 1.34.6.5 2001/04/08 19:32:26 kai Exp $ +/* $Id: hfc_pci.c,v 1.34.6.6 2001/06/09 15:14:17 kai Exp $ * hfc_pci.c low level driver for CCD´s hfc-pci based cards * @@ -35,7 +35,7 @@ extern const char *CardType[]; -static const char *hfcpci_revision = "$Revision: 1.34.6.5 $"; +static const char *hfcpci_revision = "$Revision: 1.34.6.6 $"; /* table entry in the PCI devices list */ typedef struct { @@ -1497,8 +1497,8 @@ { mode_hfcpci(bcs, 0, bcs->channel); if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { - discard_queue(&bcs->rqueue); - discard_queue(&bcs->squeue); + skb_queue_purge(&bcs->rqueue); + skb_queue_purge(&bcs->squeue); if (bcs->tx_skb) { dev_kfree_skb_any(bcs->tx_skb); bcs->tx_skb = NULL; diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/hisax/hfc_sx.c linux/drivers/isdn/hisax/hfc_sx.c --- v2.4.5/linux/drivers/isdn/hisax/hfc_sx.c Tue Nov 28 21:43:13 2000 +++ linux/drivers/isdn/hisax/hfc_sx.c Mon Jul 2 14:07:55 2001 @@ -1,4 +1,4 @@ -/* $Id: hfc_sx.c,v 1.9 2000/11/24 17:05:37 kai Exp $ +/* $Id: hfc_sx.c,v 1.9.6.1 2001/06/09 15:14:17 kai Exp $ * hfc_sx.c low level driver for CCD´s hfc-s+/sp based cards * @@ -32,7 +32,7 @@ extern const char *CardType[]; -static const char *hfcsx_revision = "$Revision: 1.9 $"; +static const char *hfcsx_revision = "$Revision: 1.9.6.1 $"; /***************************************/ /* IRQ-table for CCDs demo board */ @@ -1288,8 +1288,8 @@ { mode_hfcsx(bcs, 0, bcs->channel); if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { - discard_queue(&bcs->rqueue); - discard_queue(&bcs->squeue); + skb_queue_purge(&bcs->rqueue); + skb_queue_purge(&bcs->squeue); if (bcs->tx_skb) { dev_kfree_skb_any(bcs->tx_skb); bcs->tx_skb = NULL; diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/hisax/hisax.h linux/drivers/isdn/hisax/hisax.h --- v2.4.5/linux/drivers/isdn/hisax/hisax.h Wed Apr 18 11:49:14 2001 +++ linux/drivers/isdn/hisax/hisax.h Mon Jul 2 14:07:55 2001 @@ -1,4 +1,4 @@ -/* $Id: hisax.h,v 2.52.6.4 2001/04/08 19:32:26 kai Exp $ +/* $Id: hisax.h,v 2.52.6.6 2001/06/09 15:14:17 kai Exp $ * * Basic declarations, defines and prototypes * @@ -1304,7 +1304,7 @@ int getcallref(u_char * p); int newcallref(void); -void FsmNew(struct Fsm *fsm, struct FsmNode *fnlist, int fncount); +int FsmNew(struct Fsm *fsm, struct FsmNode *fnlist, int fncount); void FsmFree(struct Fsm *fsm); int FsmEvent(struct FsmInst *fi, int event, void *arg); void FsmChangeState(struct FsmInst *fi, int newstate); @@ -1325,7 +1325,6 @@ void LogFrame(struct IsdnCardState *cs, u_char * p, int size); void dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir); void iecpy(u_char * dest, u_char * iestart, int ieoffset); -int discard_queue(struct sk_buff_head *q); #ifdef ISDN_CHIP_ISAC void setstack_isac(struct PStack *st, struct IsdnCardState *cs); #endif /* ISDN_CHIP_ISAC */ @@ -1335,19 +1334,19 @@ int ll_run(struct IsdnCardState *cs, int addfeatures); void ll_stop(struct IsdnCardState *cs); -void CallcNew(void); +int CallcNew(void); void CallcFree(void); int CallcNewChan(struct IsdnCardState *cs); void CallcFreeChan(struct IsdnCardState *cs); -void Isdnl1New(void); +int Isdnl1New(void); void Isdnl1Free(void); -void Isdnl2New(void); +int Isdnl2New(void); void Isdnl2Free(void); -void Isdnl3New(void); +int Isdnl3New(void); void Isdnl3Free(void); void init_tei(struct IsdnCardState *cs, int protocol); void release_tei(struct IsdnCardState *cs); char *HiSax_getrev(const char *revision); -void TeiNew(void); +int TeiNew(void); void TeiFree(void); int certification_check(int output); diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/hisax/hscx.c linux/drivers/isdn/hisax/hscx.c --- v2.4.5/linux/drivers/isdn/hisax/hscx.c Fri Mar 2 11:12:08 2001 +++ linux/drivers/isdn/hisax/hscx.c Mon Jul 2 14:07:55 2001 @@ -1,4 +1,4 @@ -/* $Id: hscx.c,v 1.21.6.1 2001/02/16 16:43:27 kai Exp $ +/* $Id: hscx.c,v 1.21.6.2 2001/06/09 15:14:17 kai Exp $ * * hscx.c HSCX specific routines * @@ -166,8 +166,8 @@ kfree(bcs->blog); bcs->blog = NULL; } - discard_queue(&bcs->rqueue); - discard_queue(&bcs->squeue); + skb_queue_purge(&bcs->rqueue); + skb_queue_purge(&bcs->squeue); if (bcs->tx_skb) { dev_kfree_skb_any(bcs->tx_skb); bcs->tx_skb = NULL; diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/hisax/icc.c linux/drivers/isdn/hisax/icc.c --- v2.4.5/linux/drivers/isdn/hisax/icc.c Mon Mar 26 15:38:19 2001 +++ linux/drivers/isdn/hisax/icc.c Mon Jul 2 14:07:55 2001 @@ -1,4 +1,4 @@ -// $Id: icc.c,v 1.5.6.2 2001/03/13 16:17:08 kai Exp $ +// $Id: icc.c,v 1.5.6.3 2001/06/09 15:14:17 kai Exp $ //----------------------------------------------------------------------------- // // ICC specific routines @@ -551,8 +551,8 @@ } break; case (HW_DEACTIVATE | RESPONSE): - discard_queue(&cs->rq); - discard_queue(&cs->sq); + skb_queue_purge(&cs->rq); + skb_queue_purge(&cs->sq); if (cs->tx_skb) { dev_kfree_skb_any(cs->tx_skb); cs->tx_skb = NULL; diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/hisax/isac.c linux/drivers/isdn/hisax/isac.c --- v2.4.5/linux/drivers/isdn/hisax/isac.c Fri Mar 2 11:12:09 2001 +++ linux/drivers/isdn/hisax/isac.c Mon Jul 2 14:07:55 2001 @@ -1,4 +1,4 @@ -/* $Id: isac.c,v 1.28.6.1 2001/02/16 16:43:27 kai Exp $ +/* $Id: isac.c,v 1.28.6.2 2001/06/09 15:14:17 kai Exp $ * * isac.c ISAC specific routines * @@ -549,8 +549,8 @@ } break; case (HW_DEACTIVATE | RESPONSE): - discard_queue(&cs->rq); - discard_queue(&cs->sq); + skb_queue_purge(&cs->rq); + skb_queue_purge(&cs->sq); if (cs->tx_skb) { dev_kfree_skb_any(cs->tx_skb); cs->tx_skb = NULL; diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/hisax/isar.c linux/drivers/isdn/hisax/isar.c --- v2.4.5/linux/drivers/isdn/hisax/isar.c Wed Apr 18 11:49:14 2001 +++ linux/drivers/isdn/hisax/isar.c Mon Jul 2 14:07:55 2001 @@ -1,4 +1,4 @@ -/* $Id: isar.c,v 1.17.6.2 2001/04/08 17:51:42 kai Exp $ +/* $Id: isar.c,v 1.17.6.3 2001/06/09 15:14:17 kai Exp $ * * isar.c ISAR (Siemens PSB 7110) specific routines * @@ -1650,8 +1650,8 @@ kfree(bcs->hw.isar.rcvbuf); bcs->hw.isar.rcvbuf = NULL; } - discard_queue(&bcs->rqueue); - discard_queue(&bcs->squeue); + skb_queue_purge(&bcs->rqueue); + skb_queue_purge(&bcs->squeue); if (bcs->tx_skb) { dev_kfree_skb_any(bcs->tx_skb); bcs->tx_skb = NULL; diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/hisax/isdnl1.c linux/drivers/isdn/hisax/isdnl1.c --- v2.4.5/linux/drivers/isdn/hisax/isdnl1.c Fri Mar 2 11:12:09 2001 +++ linux/drivers/isdn/hisax/isdnl1.c Mon Jul 2 14:07:55 2001 @@ -1,4 +1,4 @@ -/* $Id: isdnl1.c,v 2.41.6.2 2001/02/16 16:43:27 kai Exp $ +/* $Id: isdnl1.c,v 2.41.6.3 2001/05/26 15:19:57 kai Exp $ * * isdnl1.c common low level stuff for Siemens Chipsetbased isdn cards * based on the teles driver from Jan den Ouden @@ -15,7 +15,7 @@ * */ -const char *l1_revision = "$Revision: 2.41.6.2 $"; +const char *l1_revision = "$Revision: 2.41.6.3 $"; #define __NO_VERSION__ #include @@ -736,26 +736,41 @@ #define L1B_FN_COUNT (sizeof(L1BFnList)/sizeof(struct FsmNode)) -void __init +int __init Isdnl1New(void) { -#ifdef HISAX_UINTERFACE - l1fsm_u.state_count = L1U_STATE_COUNT; - l1fsm_u.event_count = L1_EVENT_COUNT; - l1fsm_u.strEvent = strL1Event; - l1fsm_u.strState = strL1UState; - FsmNew(&l1fsm_u, L1UFnList, L1U_FN_COUNT); -#endif + int retval; + l1fsm_s.state_count = L1S_STATE_COUNT; l1fsm_s.event_count = L1_EVENT_COUNT; l1fsm_s.strEvent = strL1Event; l1fsm_s.strState = strL1SState; - FsmNew(&l1fsm_s, L1SFnList, L1S_FN_COUNT); + retval = FsmNew(&l1fsm_s, L1SFnList, L1S_FN_COUNT); + if (retval) + return retval; + l1fsm_b.state_count = L1B_STATE_COUNT; l1fsm_b.event_count = L1_EVENT_COUNT; l1fsm_b.strEvent = strL1Event; l1fsm_b.strState = strL1BState; - FsmNew(&l1fsm_b, L1BFnList, L1B_FN_COUNT); + retval = FsmNew(&l1fsm_b, L1BFnList, L1B_FN_COUNT); + if (retval) { + FsmFree(&l1fsm_s); + return retval; + } +#ifdef HISAX_UINTERFACE + l1fsm_u.state_count = L1U_STATE_COUNT; + l1fsm_u.event_count = L1_EVENT_COUNT; + l1fsm_u.strEvent = strL1Event; + l1fsm_u.strState = strL1UState; + retval = FsmNew(&l1fsm_u, L1UFnList, L1U_FN_COUNT); + if (retval) { + FsmFree(&l1fsm_s); + FsmFree(&l1fsm_b); + return retval; + } +#endif + return 0; } void Isdnl1Free(void) diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/hisax/isdnl2.c linux/drivers/isdn/hisax/isdnl2.c --- v2.4.5/linux/drivers/isdn/hisax/isdnl2.c Fri Mar 2 11:12:09 2001 +++ linux/drivers/isdn/hisax/isdnl2.c Mon Jul 2 14:07:55 2001 @@ -1,4 +1,4 @@ -/* $Id: isdnl2.c,v 2.25.6.1 2001/02/16 16:43:27 kai Exp $ +/* $Id: isdnl2.c,v 2.25.6.3 2001/06/09 15:14:17 kai Exp $ * * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden @@ -16,7 +16,7 @@ #include "hisax.h" #include "isdnl2.h" -const char *l2_revision = "$Revision: 2.25.6.1 $"; +const char *l2_revision = "$Revision: 2.25.6.3 $"; static void l2m_debug(struct FsmInst *fi, char *fmt, ...); @@ -649,7 +649,7 @@ { struct PStack *st = fi->userdata; - discard_queue(&st->l2.i_queue); + skb_queue_purge(&st->l2.i_queue); test_and_set_bit(FLG_L3_INIT, &st->l2.flag); test_and_clear_bit(FLG_PEND_REL, &st->l2.flag); } @@ -659,7 +659,7 @@ { struct PStack *st = fi->userdata; - discard_queue(&st->l2.i_queue); + skb_queue_purge(&st->l2.i_queue); establishlink(fi); test_and_set_bit(FLG_L3_INIT, &st->l2.flag); } @@ -685,7 +685,7 @@ { struct PStack *st = fi->userdata; - discard_queue(&st->l2.i_queue); + skb_queue_purge(&st->l2.i_queue); freewin(st); FsmChangeState(fi, ST_L2_6); st->l2.rc = 0; @@ -745,7 +745,7 @@ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'F'); if (st->l2.vs != st->l2.va) { - discard_queue(&st->l2.i_queue); + skb_queue_purge(&st->l2.i_queue); est = 1; } @@ -778,7 +778,7 @@ send_uframe(st, UA | get_PollFlagFree(st, skb), RSP); - discard_queue(&st->l2.i_queue); + skb_queue_purge(&st->l2.i_queue); freewin(st); lapb_dl_release_l2l3(st, INDICATION); } @@ -802,7 +802,7 @@ if (test_and_clear_bit(FLG_L3_INIT, &st->l2.flag)) { pr = DL_ESTABLISH | CONFIRM; } else if (st->l2.vs != st->l2.va) { - discard_queue(&st->l2.i_queue); + skb_queue_purge(&st->l2.i_queue); pr = DL_ESTABLISH | INDICATION; } @@ -860,7 +860,7 @@ if (get_PollFlagFree(st, skb)) { stop_t200(st, 7); if (!test_bit(FLG_L3_INIT, &st->l2.flag)) - discard_queue(&st->l2.i_queue); + skb_queue_purge(&st->l2.i_queue); if (test_bit(FLG_LAPB, &st->l2.flag)) st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL); st5_dl_release_l2l3(st); @@ -1156,7 +1156,7 @@ } else if (st->l2.rc == st->l2.N200) { FsmChangeState(fi, ST_L2_4); test_and_clear_bit(FLG_T200_RUN, &st->l2.flag); - discard_queue(&st->l2.i_queue); + skb_queue_purge(&st->l2.i_queue); st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'G'); if (test_bit(FLG_LAPB, &st->l2.flag)) st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL); @@ -1388,7 +1388,7 @@ { struct PStack *st = fi->userdata; - discard_queue(&st->l2.ui_queue); + skb_queue_purge(&st->l2.ui_queue); st->l2.tei = -1; FsmChangeState(fi, ST_L2_1); } @@ -1398,7 +1398,7 @@ { struct PStack *st = fi->userdata; - discard_queue(&st->l2.ui_queue); + skb_queue_purge(&st->l2.ui_queue); st->l2.tei = -1; st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL); FsmChangeState(fi, ST_L2_1); @@ -1409,8 +1409,8 @@ { struct PStack *st = fi->userdata; - discard_queue(&st->l2.i_queue); - discard_queue(&st->l2.ui_queue); + skb_queue_purge(&st->l2.i_queue); + skb_queue_purge(&st->l2.ui_queue); freewin(st); st->l2.tei = -1; stop_t200(st, 17); @@ -1423,7 +1423,7 @@ { struct PStack *st = fi->userdata; - discard_queue(&st->l2.ui_queue); + skb_queue_purge(&st->l2.ui_queue); st->l2.tei = -1; stop_t200(st, 18); st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL); @@ -1435,8 +1435,8 @@ { struct PStack *st = fi->userdata; - discard_queue(&st->l2.i_queue); - discard_queue(&st->l2.ui_queue); + skb_queue_purge(&st->l2.i_queue); + skb_queue_purge(&st->l2.ui_queue); freewin(st); st->l2.tei = -1; stop_t200(st, 17); @@ -1450,8 +1450,8 @@ { struct PStack *st = fi->userdata; - discard_queue(&st->l2.i_queue); - discard_queue(&st->l2.ui_queue); + skb_queue_purge(&st->l2.i_queue); + skb_queue_purge(&st->l2.ui_queue); if (test_and_clear_bit(FLG_ESTAB_PEND, &st->l2.flag)) st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL); } @@ -1461,8 +1461,8 @@ { struct PStack *st = fi->userdata; - discard_queue(&st->l2.i_queue); - discard_queue(&st->l2.ui_queue); + skb_queue_purge(&st->l2.i_queue); + skb_queue_purge(&st->l2.ui_queue); freewin(st); stop_t200(st, 19); st5_dl_release_l2l3(st); @@ -1474,7 +1474,7 @@ { struct PStack *st = fi->userdata; - discard_queue(&st->l2.ui_queue); + skb_queue_purge(&st->l2.ui_queue); stop_t200(st, 20); st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL); FsmChangeState(fi, ST_L2_4); @@ -1485,8 +1485,8 @@ { struct PStack *st = fi->userdata; - discard_queue(&st->l2.i_queue); - discard_queue(&st->l2.ui_queue); + skb_queue_purge(&st->l2.i_queue); + skb_queue_purge(&st->l2.ui_queue); freewin(st); stop_t200(st, 19); FsmDelTimer(&st->l2.t203, 19); @@ -1761,8 +1761,8 @@ { FsmDelTimer(&st->l2.t200, 21); FsmDelTimer(&st->l2.t203, 16); - discard_queue(&st->l2.i_queue); - discard_queue(&st->l2.ui_queue); + skb_queue_purge(&st->l2.i_queue); + skb_queue_purge(&st->l2.ui_queue); ReleaseWin(&st->l2); } @@ -1831,14 +1831,14 @@ { } -void __init +int __init Isdnl2New(void) { l2fsm.state_count = L2_STATE_COUNT; l2fsm.event_count = L2_EVENT_COUNT; l2fsm.strEvent = strL2Event; l2fsm.strState = strL2State; - FsmNew(&l2fsm, L2FnList, L2_FN_COUNT); + return FsmNew(&l2fsm, L2FnList, L2_FN_COUNT); } void diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/hisax/isdnl3.c linux/drivers/isdn/hisax/isdnl3.c --- v2.4.5/linux/drivers/isdn/hisax/isdnl3.c Fri Mar 2 11:12:09 2001 +++ linux/drivers/isdn/hisax/isdnl3.c Mon Jul 2 14:07:55 2001 @@ -1,4 +1,4 @@ -/* $Id: isdnl3.c,v 2.17.6.2 2001/02/16 16:43:27 kai Exp $ +/* $Id: isdnl3.c,v 2.17.6.4 2001/06/09 15:14:17 kai Exp $ * * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden @@ -18,7 +18,7 @@ #include "isdnl3.h" #include -const char *l3_revision = "$Revision: 2.17.6.2 $"; +const char *l3_revision = "$Revision: 2.17.6.4 $"; static struct Fsm l3fsm; @@ -404,7 +404,7 @@ st->l3.global = NULL; } FsmDelTimer(&st->l3.l3m_timer, 54); - discard_queue(&st->l3.squeue); + skb_queue_purge(&st->l3.squeue); } void @@ -520,7 +520,7 @@ FsmDelTimer(&st->l3.l3m_timer, 52); FsmChangeState(fi, ST_L3_LC_REL); - discard_queue(&st->l3.squeue); + skb_queue_purge(&st->l3.squeue); l3ml3p(st, DL_RELEASE | INDICATION); } @@ -530,7 +530,7 @@ struct PStack *st = fi->userdata; FsmChangeState(fi, ST_L3_LC_REL); - discard_queue(&st->l3.squeue); + skb_queue_purge(&st->l3.squeue); l3ml3p(st, DL_RELEASE | CONFIRM); } @@ -591,14 +591,14 @@ } } -void __init +int __init Isdnl3New(void) { l3fsm.state_count = L3_STATE_COUNT; l3fsm.event_count = L3_EVENT_COUNT; l3fsm.strEvent = strL3Event; l3fsm.strState = strL3State; - FsmNew(&l3fsm, L3FnList, L3_FN_COUNT); + return FsmNew(&l3fsm, L3FnList, L3_FN_COUNT); } void diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/hisax/jade.c linux/drivers/isdn/hisax/jade.c --- v2.4.5/linux/drivers/isdn/hisax/jade.c Fri Mar 2 11:12:09 2001 +++ linux/drivers/isdn/hisax/jade.c Mon Jul 2 14:07:55 2001 @@ -1,4 +1,4 @@ -/* $Id: jade.c,v 1.6.6.1 2001/02/16 16:43:27 kai Exp $ +/* $Id: jade.c,v 1.6.6.2 2001/06/09 15:14:18 kai Exp $ * * jade.c JADE stuff (derived from original hscx.c) * @@ -209,8 +209,8 @@ kfree(bcs->blog); bcs->blog = NULL; } - discard_queue(&bcs->rqueue); - discard_queue(&bcs->squeue); + skb_queue_purge(&bcs->rqueue); + skb_queue_purge(&bcs->squeue); if (bcs->tx_skb) { dev_kfree_skb_any(bcs->tx_skb); bcs->tx_skb = NULL; diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/hisax/md linux/drivers/isdn/hisax/md --- v2.4.5/linux/drivers/isdn/hisax/md Wed Dec 31 16:00:00 1969 +++ linux/drivers/isdn/hisax/md Mon Jul 2 14:07:55 2001 @@ -0,0 +1,12 @@ +6f9433a8b696076562562d090e3c420f isac.c +13c3eed869f5139f44c563e3a8fea1f5 isdnl1.c +addcff863b0ff1e366c0f2ae9fa6e81e isdnl2.c +7076deb94a363945c21ea27aca4a720a isdnl3.c +51c603829b6cc4f8421f744ad657ceff tei.c +669050ab5079f02887ed0239d86e5474 callc.c +e592db58630c1f1029cc064110108156 cert.c +fadeb3b85bb23bc1ac48470c0848d6fa l3dss1.c +cf7dec9fac6283716904d26b99188476 l3_1tr6.c +65d9e5471bc129624f858ebcf0743525 elsa.c +b4cf8a4dceed9ea6dcba65a85b4eecc7 diva.c +99e67bea8f6945fa0d4e0aded5bf0fa0 sedlbauer.c diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/hisax/md5sums.asc linux/drivers/isdn/hisax/md5sums.asc --- v2.4.5/linux/drivers/isdn/hisax/md5sums.asc Thu Apr 19 22:30:09 2001 +++ linux/drivers/isdn/hisax/md5sums.asc Mon Jul 2 14:07:55 2001 @@ -7,12 +7,12 @@ # cards in the moment. # Read ../../../Documentation/isdn/HiSax.cert for more informations. # -9663cc9f4374c361197d394f6d27c459 isac.c -9666c672c0fa0e65d5cc5b322f10a18c isdnl1.c -9250f15b932dfc36855aa120b896ed0b isdnl2.c -0cc2ef892bdb4a2be473e00eb1398950 isdnl3.c -cac9c32fff889c57ff50d59823053019 tei.c -665044a72334336533ac79da1a831b17 callc.c +6f9433a8b696076562562d090e3c420f isac.c +13c3eed869f5139f44c563e3a8fea1f5 isdnl1.c +addcff863b0ff1e366c0f2ae9fa6e81e isdnl2.c +7076deb94a363945c21ea27aca4a720a isdnl3.c +51c603829b6cc4f8421f744ad657ceff tei.c +669050ab5079f02887ed0239d86e5474 callc.c e592db58630c1f1029cc064110108156 cert.c fadeb3b85bb23bc1ac48470c0848d6fa l3dss1.c cf7dec9fac6283716904d26b99188476 l3_1tr6.c @@ -21,13 +21,3 @@ 99e67bea8f6945fa0d4e0aded5bf0fa0 sedlbauer.c # end of md5sums ------BEGIN PGP SIGNATURE----- -Version: 2.6.3i -Charset: noconv - -iQCVAwUBOt+j/jpxHvX/mS9tAQGXwAP/U4voKzXAcTfo9CqJhHN92GRxunj6mlvn -H+1pxSe0GdtC7BlrPhrokB5dNSwewk89Z5t7kTD76kx2FFuTcXBJxbgH7LZVF3ga -JX92bOWQekHMH7Hk12Qc7zpeTmPzY02pvVc37Eo614BCvJMCk02cpQyo8a5wWRKH -8vpQkQKiSyY= -=FFLG ------END PGP SIGNATURE----- diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/hisax/netjet.c linux/drivers/isdn/hisax/netjet.c --- v2.4.5/linux/drivers/isdn/hisax/netjet.c Fri Mar 2 11:12:09 2001 +++ linux/drivers/isdn/hisax/netjet.c Mon Jul 2 14:07:55 2001 @@ -1,4 +1,4 @@ -/* $Id: netjet.c,v 1.24.6.4 2001/02/16 16:43:28 kai Exp $ +/* $Id: netjet.c,v 1.24.6.5 2001/06/09 15:14:18 kai Exp $ * * netjet.c low level stuff for Traverse Technologie NETJet ISDN cards * @@ -22,7 +22,7 @@ #include #include "netjet.h" -const char *NETjet_revision = "$Revision: 1.24.6.4 $"; +const char *NETjet_revision = "$Revision: 1.24.6.5 $"; /* Interface functions */ @@ -880,8 +880,8 @@ kfree(bcs->hw.tiger.sendbuf); bcs->hw.tiger.sendbuf = NULL; } - discard_queue(&bcs->rqueue); - discard_queue(&bcs->squeue); + skb_queue_purge(&bcs->rqueue); + skb_queue_purge(&bcs->squeue); if (bcs->tx_skb) { dev_kfree_skb_any(bcs->tx_skb); bcs->tx_skb = NULL; diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/hisax/tei.c linux/drivers/isdn/hisax/tei.c --- v2.4.5/linux/drivers/isdn/hisax/tei.c Fri Mar 2 11:12:09 2001 +++ linux/drivers/isdn/hisax/tei.c Tue Jun 12 10:34:48 2001 @@ -1,4 +1,4 @@ -/* $Id: tei.c,v 2.17.6.1 2001/02/16 16:43:29 kai Exp $ +/* $Id: tei.c,v 2.17.6.2 2001/05/26 15:19:57 kai Exp $ * * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden @@ -17,7 +17,7 @@ #include #include -const char *tei_revision = "$Revision: 2.17.6.1 $"; +const char *tei_revision = "$Revision: 2.17.6.2 $"; #define ID_REQUEST 1 #define ID_ASSIGNED 2 @@ -446,14 +446,14 @@ #define TEI_FN_COUNT (sizeof(TeiFnList)/sizeof(struct FsmNode)) -void __init +int __init TeiNew(void) { teifsm.state_count = TEI_STATE_COUNT; teifsm.event_count = TEI_EVENT_COUNT; teifsm.strEvent = strTeiEvent; teifsm.strState = strTeiState; - FsmNew(&teifsm, TeiFnList, TEI_FN_COUNT); + return FsmNew(&teifsm, TeiFnList, TEI_FN_COUNT); } void diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/hisax/w6692.c linux/drivers/isdn/hisax/w6692.c --- v2.4.5/linux/drivers/isdn/hisax/w6692.c Fri Mar 2 11:12:09 2001 +++ linux/drivers/isdn/hisax/w6692.c Mon Jul 2 14:07:55 2001 @@ -1,4 +1,4 @@ -/* $Id: w6692.c,v 1.12.6.4 2001/02/16 16:43:29 kai Exp $ +/* $Id: w6692.c,v 1.12.6.5 2001/06/09 15:14:18 kai Exp $ * * w6692.c Winbond W6692 specific routines * @@ -35,7 +35,7 @@ extern const char *CardType[]; -const char *w6692_revision = "$Revision: 1.12.6.4 $"; +const char *w6692_revision = "$Revision: 1.12.6.5 $"; #define DBUSY_TIMER_VALUE 80 @@ -641,8 +641,8 @@ /* !!! not implemented yet */ break; case (HW_DEACTIVATE | RESPONSE): - discard_queue(&cs->rq); - discard_queue(&cs->sq); + skb_queue_purge(&cs->rq); + skb_queue_purge(&cs->sq); if (cs->tx_skb) { dev_kfree_skb_any(cs->tx_skb); cs->tx_skb = NULL; @@ -805,8 +805,8 @@ kfree(bcs->blog); bcs->blog = NULL; } - discard_queue(&bcs->rqueue); - discard_queue(&bcs->squeue); + skb_queue_purge(&bcs->rqueue); + skb_queue_purge(&bcs->squeue); if (bcs->tx_skb) { dev_kfree_skb_any(bcs->tx_skb); bcs->tx_skb = NULL; diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/hysdn/hycapi.c linux/drivers/isdn/hysdn/hycapi.c --- v2.4.5/linux/drivers/isdn/hysdn/hycapi.c Sat May 19 17:54:14 2001 +++ linux/drivers/isdn/hysdn/hycapi.c Tue Jun 12 10:34:48 2001 @@ -1,4 +1,4 @@ -/* $Id: hycapi.c,v 1.8.6.2 2001/04/20 02:42:00 keil Exp $ +/* $Id: hycapi.c,v 1.8.6.3 2001/05/26 15:19:58 kai Exp $ * * Linux driver for HYSDN cards, CAPI2.0-Interface. * written by Ulrich Albrecht (u.albrecht@hypercope.de) for Hypercope GmbH @@ -41,7 +41,7 @@ #include "hysdn_defs.h" #include -static char hycapi_revision[]="$Revision: 1.8.6.2 $"; +static char hycapi_revision[]="$Revision: 1.8.6.3 $"; unsigned int hycapi_enable = 0xffffffff; MODULE_PARM(hycapi_enable, "i"); @@ -734,7 +734,7 @@ struct capi_driver *driver; driver = &hycapi_driver; if (!hy_di) { - printk(KERN_ERR "HYSDN: no capi-driver to detach (???)\n"); + printk(KERN_ERR "HYSDN: no capi-driver to detach (?)\n"); return; } printk(KERN_NOTICE "HYSDN: Detaching capi-driver\n"); diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/hysdn/hysdn_net.c linux/drivers/isdn/hysdn/hysdn_net.c --- v2.4.5/linux/drivers/isdn/hysdn/hysdn_net.c Sat May 19 17:54:14 2001 +++ linux/drivers/isdn/hysdn/hysdn_net.c Tue Jun 12 10:34:48 2001 @@ -1,4 +1,4 @@ -/* $Id: hysdn_net.c,v 1.8.6.2 2001/04/20 02:42:00 keil Exp $ +/* $Id: hysdn_net.c,v 1.8.6.3 2001/06/05 19:45:37 kai Exp $ * Linux driver for HYSDN cards, net (ethernet type) handling routines. * @@ -41,7 +41,7 @@ MODULE_PARM(hynet_enable, "i"); /* store the actual version for log reporting */ -char *hysdn_net_revision = "$Revision: 1.8.6.2 $"; +char *hysdn_net_revision = "$Revision: 1.8.6.3 $"; #define MAX_SKB_BUFFERS 20 /* number of buffers for keeping TX-data */ @@ -304,8 +304,7 @@ hysdn_net_release(card); /* release an existing net device */ if ((dev = kmalloc(sizeof(struct net_local), GFP_KERNEL)) == NULL) { printk(KERN_WARNING "HYSDN: unable to allocate mem\n"); - if (card->debug_flags & LOG_NET_INIT) - return (-ENOMEM); + return (-ENOMEM); } memset(dev, 0, sizeof(struct net_local)); /* clean the structure */ diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/hysdn/hysdn_proclog.c linux/drivers/isdn/hysdn/hysdn_proclog.c --- v2.4.5/linux/drivers/isdn/hysdn/hysdn_proclog.c Mon Nov 27 16:53:43 2000 +++ linux/drivers/isdn/hysdn/hysdn_proclog.c Tue Jun 12 10:34:48 2001 @@ -1,4 +1,4 @@ -/* $Id: hysdn_proclog.c,v 1.9 2000/11/25 17:01:01 kai Exp $ +/* $Id: hysdn_proclog.c,v 1.9.6.1 2001/05/26 15:19:58 kai Exp $ * Linux driver for HYSDN cards, /proc/net filesystem log functions. * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH @@ -228,7 +228,7 @@ struct log_data *inf; int len; word ino; - struct procdata *pd; + struct procdata *pd = NULL; hysdn_card *card; if (!*((struct log_data **) file->private_data)) { @@ -271,7 +271,7 @@ hysdn_log_open(struct inode *ino, struct file *filep) { hysdn_card *card; - struct procdata *pd; + struct procdata *pd = NULL; ulong flags; lock_kernel(); @@ -381,7 +381,7 @@ unsigned int mask = 0; word ino; hysdn_card *card; - struct procdata *pd; + struct procdata *pd = NULL; if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) return (mask); /* no polling for write supported */ diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/icn/icn.c linux/drivers/isdn/icn/icn.c --- v2.4.5/linux/drivers/isdn/icn/icn.c Thu Apr 19 22:30:23 2001 +++ linux/drivers/isdn/icn/icn.c Mon Jul 2 14:07:55 2001 @@ -1,4 +1,4 @@ -/* $Id: icn.c,v 1.65.6.4 2001/04/20 02:42:01 keil Exp $ +/* $Id: icn.c,v 1.65.6.5 2001/06/09 15:14:19 kai Exp $ * ISDN low-level module for the ICN active ISDN-Card. * @@ -34,7 +34,7 @@ #undef MAP_DEBUG static char -*revision = "$Revision: 1.65.6.4 $"; +*revision = "$Revision: 1.65.6.5 $"; static int icn_addcard(int, char *, char *); @@ -51,8 +51,7 @@ struct sk_buff *skb; unsigned long flags; - while ((skb = skb_dequeue(queue))) - dev_kfree_skb(skb); + skb_queue_purge(queue); save_flags(flags); cli(); card->xlen[channel] = 0; diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c --- v2.4.5/linux/drivers/isdn/isdn_common.c Sat May 19 17:54:14 2001 +++ linux/drivers/isdn/isdn_common.c Mon Jul 2 14:07:55 2001 @@ -1,4 +1,4 @@ -/* $Id: isdn_common.c,v 1.114.6.11 2001/04/20 02:41:58 keil Exp $ +/* $Id: isdn_common.c,v 1.114.6.12 2001/06/09 15:14:15 kai Exp $ * Linux ISDN subsystem, common used functions (linklevel). * @@ -51,7 +51,7 @@ isdn_dev *dev; -static char *isdn_revision = "$Revision: 1.114.6.11 $"; +static char *isdn_revision = "$Revision: 1.114.6.12 $"; extern char *isdn_net_revision; extern char *isdn_tty_revision; @@ -233,20 +233,6 @@ return isdn_wildmat( TmpMsn1, TmpMsn2 ); } -static void -isdn_free_queue(struct sk_buff_head *queue) -{ - struct sk_buff *skb; - unsigned long flags; - - save_flags(flags); - cli(); - if (skb_queue_len(queue)) - while ((skb = skb_dequeue(queue))) - dev_kfree_skb(skb); - restore_flags(flags); -} - int isdn_dc2minor(int di, int ch) { @@ -739,7 +725,7 @@ kfree(dev->drv[di]->rcverr); kfree(dev->drv[di]->rcvcount); for (i = 0; i < dev->drv[di]->channels; i++) - isdn_free_queue(&dev->drv[di]->rpqueue[i]); + skb_queue_purge(&dev->drv[di]->rpqueue[i]); kfree(dev->drv[di]->rpqueue); kfree(dev->drv[di]->rcv_waitq); kfree(dev->drv[di]); @@ -1873,7 +1859,7 @@ dev->v110[i] = NULL; // 20.10.99 JIM, try to reinitialize v110 ! isdn_info_update(); - isdn_free_queue(&dev->drv[di]->rpqueue[ch]); + skb_queue_purge(&dev->drv[di]->rpqueue[ch]); } restore_flags(flags); } @@ -2036,7 +2022,7 @@ if ((adding) && (d->rpqueue)) { for (j = 0; j < d->channels; j++) - isdn_free_queue(&d->rpqueue[j]); + skb_queue_purge(&d->rpqueue[j]); kfree(d->rpqueue); } if (!(d->rpqueue = diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/isdn_net.c linux/drivers/isdn/isdn_net.c --- v2.4.5/linux/drivers/isdn/isdn_net.c Sat May 19 17:54:14 2001 +++ linux/drivers/isdn/isdn_net.c Mon Jul 2 14:07:55 2001 @@ -1,4 +1,4 @@ -/* $Id: isdn_net.c,v 1.140.6.4 2001/04/20 02:41:58 keil Exp $ +/* $Id: isdn_net.c,v 1.140.6.6 2001/06/11 22:08:37 kai Exp $ * Linux ISDN subsystem, network interfaces and related functions (linklevel). * @@ -190,7 +190,7 @@ static void isdn_net_ciscohdlck_connected(isdn_net_local *lp); static void isdn_net_ciscohdlck_disconnected(isdn_net_local *lp); -char *isdn_net_revision = "$Revision: 1.140.6.4 $"; +char *isdn_net_revision = "$Revision: 1.140.6.6 $"; /* * Code for raw-networking over ISDN @@ -301,13 +301,11 @@ isdn_net_unbind_channel(isdn_net_local * lp) { ulong flags; - struct sk_buff *skb; save_flags(flags); cli(); - while ((skb = skb_dequeue(&lp->super_tx_queue))) { - kfree_skb(skb); - } + skb_queue_purge(&lp->super_tx_queue); + if (!lp->master) { /* reset only master device */ /* Moral equivalent of dev_purge_queues(): BEWARE! This chunk of code cannot be called from hardware diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c --- v2.4.5/linux/drivers/isdn/isdn_ppp.c Tue May 22 10:23:16 2001 +++ linux/drivers/isdn/isdn_ppp.c Tue Jun 12 10:35:44 2001 @@ -1,4 +1,4 @@ -/* $Id: isdn_ppp.c,v 1.85.6.4 2001/04/08 18:53:07 kai Exp $ +/* $Id: isdn_ppp.c,v 1.85.6.5 2001/05/26 15:19:56 kai Exp $ * * Linux ISDN subsystem, functions for synchronous PPP (linklevel). * @@ -83,7 +83,7 @@ static int isdn_ppp_bundle(struct ippp_struct *, int unit); #endif /* CONFIG_ISDN_MPP */ -char *isdn_ppp_revision = "$Revision: 1.85.6.4 $"; +char *isdn_ppp_revision = "$Revision: 1.85.6.5 $"; static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS]; @@ -785,7 +785,10 @@ } skb_reserve(skb, hl); if (copy_from_user(skb_put(skb, count), buf, count)) + { + kfree_skb(skb); return -EFAULT; + } if (is->debug & 0x40) { printk(KERN_DEBUG "ppp xmit: len %d\n", (int) skb->len); isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,is->unit,lp->ppp_slot); diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/isdn_tty.c linux/drivers/isdn/isdn_tty.c --- v2.4.5/linux/drivers/isdn/isdn_tty.c Fri Mar 2 11:12:09 2001 +++ linux/drivers/isdn/isdn_tty.c Mon Jul 2 14:07:55 2001 @@ -1,4 +1,4 @@ -/* $Id: isdn_tty.c,v 1.94.6.1 2001/02/16 16:43:22 kai Exp $ +/* $Id: isdn_tty.c,v 1.94.6.2 2001/06/09 15:14:15 kai Exp $ * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel). * @@ -66,7 +66,7 @@ static int si2bit[8] = {4, 1, 4, 4, 4, 4, 4, 4}; -char *isdn_tty_revision = "$Revision: 1.94.6.1 $"; +char *isdn_tty_revision = "$Revision: 1.94.6.2 $"; /* isdn_tty_try_read() is called from within isdn_tty_rcv_skb() @@ -307,18 +307,13 @@ void isdn_tty_cleanup_xmit(modem_info * info) { - struct sk_buff *skb; unsigned long flags; save_flags(flags); cli(); - if (skb_queue_len(&info->xmit_queue)) - while ((skb = skb_dequeue(&info->xmit_queue))) - kfree_skb(skb); -#ifdef CONFIG_ISDN_AUDIO - if (skb_queue_len(&info->dtmf_queue)) - while ((skb = skb_dequeue(&info->dtmf_queue))) - kfree_skb(skb); + skb_queue_purge(&info->xmit_queue); +#ifdef CONFIG_ISDN_AUDIO + skb_queue_purge(&info->dtmf_queue); #endif restore_flags(flags); } diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/isdnloop/isdnloop.c linux/drivers/isdn/isdnloop/isdnloop.c --- v2.4.5/linux/drivers/isdn/isdnloop/isdnloop.c Fri Mar 2 11:12:09 2001 +++ linux/drivers/isdn/isdnloop/isdnloop.c Mon Jul 2 14:07:55 2001 @@ -1,4 +1,4 @@ -/* $Id: isdnloop.c,v 1.11.6.2 2001/02/16 16:43:32 kai Exp $ +/* $Id: isdnloop.c,v 1.11.6.3 2001/06/09 15:14:19 kai Exp $ * ISDN low-level module implementing a dummy loop driver. * @@ -26,7 +26,7 @@ #include "isdnloop.h" static char -*revision = "$Revision: 1.11.6.2 $"; +*revision = "$Revision: 1.11.6.3 $"; static int isdnloop_addcard(char *); @@ -41,10 +41,8 @@ isdnloop_free_queue(isdnloop_card * card, int channel) { struct sk_buff_head *queue = &card->bqueue[channel]; - struct sk_buff *skb; - while ((skb = skb_dequeue(queue))) - dev_kfree_skb(skb); + skb_queue_purge(queue); card->sndcount[channel] = 0; } @@ -1574,11 +1572,8 @@ } card = cards; while (card) { - struct sk_buff *skb; - last = card; - while ((skb = skb_dequeue(&card->dqueue))) - dev_kfree_skb(skb); + skb_queue_purge(&card->dqueue); card = card->next; kfree(last); } diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/tpam/Makefile linux/drivers/isdn/tpam/Makefile --- v2.4.5/linux/drivers/isdn/tpam/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/isdn/tpam/Makefile Mon Jul 2 14:07:55 2001 @@ -0,0 +1,21 @@ +# Makefile for the TurboPAM ISDN device driver + +# The target object and module list name. + +O_TARGET := vmlinux-obj.o + +# Multipart objects. + +list-multi := tpam.o +tpam-objs := tpam_main.o tpam_nco.o tpam_memory.o tpam_commands.o tpam_queues.o tpam_hdlc.o tpam_crcpc.o + +# Each configuration option enables a list of files. + +obj-$(CONFIG_ISDN_DRV_TPAM) += tpam.o + +include $(TOPDIR)/Rules.make + +# Link rules for multi-part drivers. + +tpam.o: $(tpam-objs) + $(LD) -r -o $@ $(tpam-objs) diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/tpam/tpam.h linux/drivers/isdn/tpam/tpam.h --- v2.4.5/linux/drivers/isdn/tpam/tpam.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/isdn/tpam/tpam.h Mon Jul 2 14:07:55 2001 @@ -0,0 +1,246 @@ +/* $Id: tpam.h,v 1.1.2.1 2001/06/05 19:45:37 kai Exp $ + * + * Turbo PAM ISDN driver for Linux. (Kernel Driver) + * + * Copyright 2001 Stelian Pop , Alcôve + * + * For all support questions please contact: + * + * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _TPAM_PRIV_H_ +#define _TPAM_PRIV_H_ + +#include +#include +#include + +/* Maximum number of channels for this board */ +#define TPAM_NBCHANNEL 30 +/* Maximum size of data */ +#define TPAM_MAXBUFSIZE 2032 +/* Size of a page of board memory */ +#define TPAM_PAGE_SIZE 0x003ffffc /* 4 MB */ +/* Magic number present if the board was successfully started */ +#define TPAM_MAGICNUMBER 0x2a343242 + +/* Registers in the PCI BAR0 */ +#define TPAM_PAGE_REGISTER 0x00400000 /* Select page */ +#define TPAM_DSPINT_REGISTER 0x00400004 /* Interrupt board */ +#define TPAM_RESETPAM_REGISTER 0x00400008 /* Reset board */ +#define TPAM_HINTACK_REGISTER 0x0040000c /* Ack interrupt */ +#define TPAM_HPIC_REGISTER 0x00400014 /* Board ready */ + +/* Registers in the board memory */ +#define TPAM_MAGICNUMBER_REGISTER 0x80008000 /* Magic number */ +#define TPAM_EXID_REGISTER 0x80008004 /* EXID - not used */ +#define TPAM_UPLOADPTR_REGISTER 0x80008008 /* Upload data ptr */ +#define TPAM_DOWNLOADPTR_REGISTER 0x8000800c /* Download data ptr */ +#define TPAM_ACKUPLOAD_REGISTER 0x80008010 /* Ack upload */ +#define TPAM_ACKDOWNLOAD_REGISTER 0x80008014 /* Ack download */ +#define TPAM_INTERRUPTACK_REGISTER 0x80008018 /* Ack interrupt */ + +/* Reserved areas in the board memory */ +#define TPAM_RESERVEDAREA1_START 0x00000000 +#define TPAM_RESERVEDAREA1_END 0x003FFFFF +#define TPAM_RESERVEDAREA2_START 0x01C00000 +#define TPAM_RESERVEDAREA2_END 0x01FFFFFF +#define TPAM_RESERVEDAREA3_START 0x04000000 +#define TPAM_RESERVEDAREA3_END 0x7FFFFFFF +#define TPAM_RESERVEDAREA4_START 0x80010000 +#define TPAM_RESERVEDAREA4_END 0xFFFFFFFF + +/* NCO ID invalid */ +#define TPAM_NCOID_INVALID 0xffff +/* channel number invalid */ +#define TPAM_CHANNEL_INVALID 0xffff + +/* Channel structure */ +typedef struct tpam_channel { + int num; /* channel number */ + struct tpam_card *card; /* channel's card */ + u32 ncoid; /* ncoid */ + u8 hdlc; /* hdlc mode (set by user level) */ + u8 realhdlc; /* hdlc mode (negociated with peer) */ + u32 hdlcshift; /* hdlc shift */ + u8 readytoreceive; /* channel ready to receive data */ + struct sk_buff_head sendq; /* Send queue */ +} tpam_channel; + +/* Card structure */ +typedef struct tpam_card { + struct tpam_card *next; /* next card in list */ + unsigned int irq; /* IRQ used by this board */ + unsigned long bar0; /* ioremapped bar0 */ + int id; /* id of the board */ + isdn_if interface; /* isdn link-level pointer */ + int channels_used; /* number of channels actually used */ + int channels_tested; /* number of channels being tested */ + u8 loopmode; /* board in looptest mode */ + tpam_channel channels[TPAM_NBCHANNEL];/* channels tab */ + int running; /* card is running */ + int busy; /* waiting for ack from card */ + int roundrobin; /* round robin between channels */ + struct sk_buff_head sendq; /* send queue */ + struct sk_buff_head recvq; /* receive queue */ + struct tq_struct send_tq; /* send task queue */ + struct tq_struct recv_tq; /* receive task queue */ + spinlock_t lock; /* lock for the card */ +} tpam_card; + +/* Timeout waiting for signature to become available */ +#define SIGNATURE_TIMEOUT (5*HZ) +/* Timeout waiting for receiving all the ACreateNCOCnf */ +#define NCOCREATE_TIMEOUT (30*HZ) + +/* Maximum size of the TLV block */ +#define MPB_MAXIMUMBLOCKTLVSIZE 128 +/* Maximum size of the data block */ +#define MPB_MAXIMUMDATASIZE 4904 +/* Maximum size of a phone number */ +#define PHONE_MAXIMUMSIZE 32 + +/* Header for a sk_buff structure */ +typedef struct skb_header { + u16 size; /* size of pci_mpb block + size of tlv block */ + u16 data_size; /* size of the data block */ + u16 ack; /* packet needs to send ack upon send */ + u16 ack_size; /* size of data to be acknowledged upon send */ +} skb_header; + +/* PCI message header structure */ +typedef struct pci_mpb { + u16 exID; /* exID - not used */ + u16 flags; /* flags - not used */ + u32 errorCode; /* errorCode - not used */ + u16 messageID; /* message ID - one of ID_XXX */ + u16 maximumBlockTLVSize; /* MPB_MAXIMUMBLOCKTLVSIZE */ + u16 actualBlockTLVSize; /* size of the tlv block */ + u16 maximumDataSize; /* MPB_MAXIMUMDATASIZE */ + u16 actualDataSize; /* size of the data block */ + u16 dummy; /* padding */ +} pci_mpb; + +/* Types of PCI messages */ +#define ID_ACreateNCOReq 101 +#define ID_ACreateNCOCnf 102 +#define ID_ADestroyNCOReq 103 +#define ID_ADestroyNCOCnf 104 +#define ID_CConnectReq 203 +#define ID_CConnectInd 204 +#define ID_CConnectRsp 205 +#define ID_CConnectCnf 206 +#define ID_CDisconnectReq 207 +#define ID_CDisconnectInd 208 +#define ID_CDisconnectRsp 209 +#define ID_CDisconnectCnf 210 +#define ID_U3DataReq 307 +#define ID_U3DataInd 308 +#define ID_U3ReadyToReceiveInd 318 + +/* Parameters for the PCI message TLV block */ +#define PAR_BearerCap 3 +#define PAR_CalledNumber 7 +#define PAR_CallingNumber 11 +#define PAR_CauseToPUF 15 +#define PAR_Cdirection 16 +#define PAR_CompletionStatus 19 +#define PAR_Facility 30 +#define PAR_HLC 34 +#define PAR_NCOID 49 +#define PAR_NCOType 50 +#define PAR_ReadyFlag 55 +#define PAR_U3Protocol 62 +#define PAR_Udirection 64 + +/* Delayed statcallb structure */ +typedef struct tpam_statcallb_data { + tpam_card *card; /* card issuing the statcallb */ + struct timer_list *timer; /* timer launching the statcallb */ + isdn_ctrl ctrl; /* isdn command */ +} tpam_statcallb_data; + +/* Function prototypes from tpam_main.c */ +extern tpam_card *tpam_findcard(int); +extern u32 tpam_findchannel(tpam_card *, u32); + +/* Function prototypes from tpam_memory.c */ +extern void copy_to_pam_dword(tpam_card *, const void *, u32); +extern void copy_to_pam(tpam_card *, void *, const void *, u32); +extern u32 copy_from_pam_dword(tpam_card *, const void *); +extern void copy_from_pam(tpam_card *, void *, const void *, u32); +extern int copy_from_pam_to_user(tpam_card *, void *, const void *, u32); +extern int copy_from_user_to_pam(tpam_card *, void *, const void *, u32); +extern int tpam_verify_area(u32, u32); + +/* Function prototypes from tpam_nco.c */ +extern struct sk_buff *build_ACreateNCOReq(const u8 *); +extern struct sk_buff *build_ADestroyNCOReq(u32); +extern struct sk_buff *build_CConnectReq(u32, const u8 *, u8); +extern struct sk_buff *build_CConnectRsp(u32); +extern struct sk_buff *build_CDisconnectReq(u32); +extern struct sk_buff *build_CDisconnectRsp(u32); +extern struct sk_buff *build_U3DataReq(u32, void *, u16, u16, u16); +extern int parse_ACreateNCOCnf(struct sk_buff *, u8 *, u32 *); +extern int parse_ADestroyNCOCnf(struct sk_buff *, u8 *, u32 *); +extern int parse_CConnectCnf(struct sk_buff *, u32 *); +extern int parse_CConnectInd(struct sk_buff *, u32 *, u8 *, u8 *, + u8 *, u8 *, u8 *); +extern int parse_CDisconnectCnf(struct sk_buff *, u32 *, u32 *); +extern int parse_CDisconnectInd(struct sk_buff *, u32 *, u32 *); +extern int parse_U3ReadyToReceiveInd(struct sk_buff *, u32 *, u8 *); +extern int parse_U3DataInd(struct sk_buff *, u32 *, u8 **, u16 *); + +/* Function prototypes from tpam_queues.c */ +extern void tpam_enqueue(tpam_card *, struct sk_buff *); +extern void tpam_enqueue_data(tpam_channel *, struct sk_buff *); +extern void tpam_irq(int, void *, struct pt_regs *); +extern void tpam_recv_tq(tpam_card *); +extern void tpam_send_tq(tpam_card *); + +/* Function prototypes from tpam_commands.c */ +extern int tpam_command(isdn_ctrl *); +extern int tpam_writebuf_skb(int, int, int, struct sk_buff *); +extern void tpam_recv_ACreateNCOCnf(tpam_card *, struct sk_buff *); +extern void tpam_recv_ADestroyNCOCnf(tpam_card *, struct sk_buff *); +extern void tpam_recv_CConnectCnf(tpam_card *, struct sk_buff *); +extern void tpam_recv_CConnectInd(tpam_card *, struct sk_buff *); +extern void tpam_recv_CDisconnectInd(tpam_card *, struct sk_buff *); +extern void tpam_recv_CDisconnectCnf(tpam_card *, struct sk_buff *); +extern void tpam_recv_U3DataInd(tpam_card *, struct sk_buff *); +extern void tpam_recv_U3ReadyToReceiveInd(tpam_card *, struct sk_buff *); + +/* Function prototypes from tpam_hdlc.c */ +extern u32 hdlc_encode(u8 *, u8 *, u32 *, u32); +extern u32 hdlc_decode(u8 *, u8 *, u32); + +/* Function prototypes from tpam_crcpc.c */ +extern void init_CRC(void); +extern void hdlc_encode_modem(u8 *, u32, u8 *, u32 *); +extern void hdlc_no_accm_encode(u8 *, u32, u8 *, u32 *); +extern u32 hdlc_no_accm_decode(u8 *, u32); + +/* Define this to enable debug tracing prints */ +#undef DEBUG + +#ifdef DEBUG +#define dprintk printk +#else +#define dprintk while(0) printk +#endif + +#endif /* _TPAM_H_ */ diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/tpam/tpam_commands.c linux/drivers/isdn/tpam/tpam_commands.c --- v2.4.5/linux/drivers/isdn/tpam/tpam_commands.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/isdn/tpam/tpam_commands.c Mon Jul 2 14:07:55 2001 @@ -0,0 +1,1035 @@ +/* $Id: tpam_commands.c,v 1.1.2.2 2001/06/08 08:23:46 kai Exp $ + * + * Turbo PAM ISDN driver for Linux. (Kernel Driver - ISDN commands) + * + * Copyright 2001 Stelian Pop , Alcôve + * + * For all support questions please contact: + * + * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include "tpam.h" + +/* Local functions prototypes */ +static int tpam_command_ioctl_dspload(tpam_card *, u32); +static int tpam_command_ioctl_dspsave(tpam_card *, u32); +static int tpam_command_ioctl_dsprun(tpam_card *); +static int tpam_command_ioctl_loopmode(tpam_card *, u8); +static int tpam_command_dial(tpam_card *, u32, u8 *); +static int tpam_command_setl2(tpam_card *, u32, u8); +static int tpam_command_getl2(tpam_card *, u32); +static int tpam_command_acceptd(tpam_card *, u32); +static int tpam_command_acceptb(tpam_card *, u32); +static int tpam_command_hangup(tpam_card *, u32); +static int tpam_command_proceed(tpam_card *, u32); +static void tpam_statcallb_run(unsigned long); +static void tpam_statcallb(tpam_card *, isdn_ctrl); + +/* + * Function called when the ISDN link level send a command to the driver. + * + * c: ISDN command. + * + * Return: 0 if OK, <0 on errors. + */ +int tpam_command(isdn_ctrl *c) { + tpam_card *card; + unsigned long argp; + + dprintk("TurboPAM(tpam_command) card=%d, command=%d\n", + c->driver, c->command); + + /* search for the board */ + if (!(card = tpam_findcard(c->driver))) { + printk(KERN_ERR "TurboPAM(tpam_command): invalid driverId %d\n", + c->driver); + return -ENODEV; + } + + /* dispatch the command */ + switch (c->command) { + case ISDN_CMD_IOCTL: + argp = c->parm.userdata; + switch (c->arg) { + case TPAM_CMD_DSPLOAD: + return tpam_command_ioctl_dspload(card, + argp); + case TPAM_CMD_DSPSAVE: + return tpam_command_ioctl_dspsave(card, + argp); + case TPAM_CMD_DSPRUN: + return tpam_command_ioctl_dsprun(card); + case TPAM_CMD_LOOPMODEON: + return tpam_command_ioctl_loopmode(card, + 1); + case TPAM_CMD_LOOPMODEOFF: + return tpam_command_ioctl_loopmode(card, + 0); + default: + dprintk("TurboPAM(tpam_command): " + "invalid tpam ioctl %ld\n", + c->arg); + return -EINVAL; + } + case ISDN_CMD_DIAL: + return tpam_command_dial(card, c->arg, + c->parm.setup.phone); + case ISDN_CMD_ACCEPTD: + return tpam_command_acceptd(card, c->arg); + case ISDN_CMD_ACCEPTB: + return tpam_command_acceptb(card, c->arg); + case ISDN_CMD_HANGUP: + return tpam_command_hangup(card, c->arg); + case ISDN_CMD_SETL2: + return tpam_command_setl2(card, c->arg & 0xff, + c->arg >> 8); + case ISDN_CMD_GETL2: + return tpam_command_getl2(card, c->arg); + case ISDN_CMD_LOCK: + MOD_INC_USE_COUNT; + return 0; + case ISDN_CMD_UNLOCK: + MOD_DEC_USE_COUNT; + return 0; + case ISDN_CMD_PROCEED: + return tpam_command_proceed(card, c->arg); + default: + dprintk("TurboPAM(tpam_command): " + "unknown or unused isdn ioctl %d\n", + c->command); + return -EINVAL; + } + + /* not reached */ + return -EINVAL; +} + +/* + * Load some data into the board's memory. + * + * card: the board + * arg: IOCTL argument containing the user space address of + * the tpam_dsp_ioctl structure describing the IOCTL. + * + * Return: 0 if OK, <0 on errors. + */ +static int tpam_command_ioctl_dspload(tpam_card *card, u32 arg) { + tpam_dsp_ioctl tdl; + int ret; + + dprintk("TurboPAM(tpam_command_ioctl_dspload): card=%d\n", card->id); + + /* get the IOCTL parameter from userspace */ + if (copy_from_user(&tdl, (void *)arg, sizeof(tpam_dsp_ioctl))) + return -EFAULT; + + /* if the board's firmware was started, protect against writes + * to unallowed memory areas. If the board's firmware wasn't started, + * all is allowed. */ + if (card->running && tpam_verify_area(tdl.address, tdl.data_len)) + return -EPERM; + + /* write the data in the board's memory */ + ret = copy_from_user_to_pam(card, (void *)tdl.address, + (void *)arg + sizeof(tpam_dsp_ioctl), + tdl.data_len); + return 0; +} + +/* + * Extract some data from the board's memory. + * + * card: the board + * arg: IOCTL argument containing the user space address of + * the tpam_dsp_ioctl structure describing the IOCTL. + * + * Return: 0 if OK, <0 on errors. + */ +static int tpam_command_ioctl_dspsave(tpam_card *card, u32 arg) { + tpam_dsp_ioctl tdl; + int ret; + + dprintk("TurboPAM(tpam_command_ioctl_dspsave): card=%d\n", card->id); + + /* get the IOCTL parameter from userspace */ + if (copy_from_user(&tdl, (void *)arg, sizeof(tpam_dsp_ioctl))) + return -EFAULT; + + /* protect against read from unallowed memory areas */ + if (tpam_verify_area(tdl.address, tdl.data_len)) + return -EPERM; + + /* read the data from the board's memory */ + ret = copy_from_pam_to_user(card, (void *)arg + sizeof(tpam_dsp_ioctl), + (void *)tdl.address, tdl.data_len); + return ret; +} + +/* + * Launch the board's firmware. This function must be called after the + * firmware was loaded into the board's memory using TPAM_CMD_DSPLOAD + * IOCTL commands. After launching the firmware, this function creates + * the NCOs and waits for their creation. + * + * card: the board + * + * Return: 0 if OK, <0 on errors. + */ +static int tpam_command_ioctl_dsprun(tpam_card *card) { + u32 signature = 0, timeout, i; + isdn_ctrl ctrl; + struct sk_buff *skb; + + dprintk("TurboPAM(tpam_command_ioctl_dsprun): card=%d\n", card->id); + + /* board must _not_ be running */ + if (card->running) + return -EBUSY; + + /* reset the board */ + spin_lock_irq(&card->lock); + copy_to_pam_dword(card, (void *)TPAM_MAGICNUMBER_REGISTER, 0xdeadface); + readl(card->bar0 + TPAM_DSPINT_REGISTER); + readl(card->bar0 + TPAM_HINTACK_REGISTER); + spin_unlock_irq(&card->lock); + + /* wait for the board signature */ + timeout = jiffies + SIGNATURE_TIMEOUT; + while (timeout > jiffies) { + spin_lock_irq(&card->lock); + signature = copy_from_pam_dword(card, + (void *)TPAM_MAGICNUMBER_REGISTER); + spin_unlock_irq(&card->lock); + if (signature == TPAM_MAGICNUMBER) + break; + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(2); + } + + /* signature not present -> board not started */ + if (signature != TPAM_MAGICNUMBER) { + printk(KERN_ERR "TurboPAM(tpam_command_ioctl_dsprun): " + "card=%d, signature 0x%lx, expected 0x%lx\n", + card->id, (unsigned long)signature, + (unsigned long)TPAM_MAGICNUMBER); + printk(KERN_ERR "TurboPAM(tpam_command_ioctl_dsprun): " + "card=%d, firmware not started\n", card->id); + return -EIO; + } + + /* the firmware is started */ + printk(KERN_INFO "TurboPAM: card=%d, firmware started\n", card->id); + + /* init the CRC routines */ + init_CRC(); + + /* create all the NCOs */ + for (i = 0; i < TPAM_NBCHANNEL; ++i) + if ((skb = build_ACreateNCOReq(""))) + tpam_enqueue(card, skb); + + /* wait for NCO creation confirmation */ + timeout = jiffies + NCOCREATE_TIMEOUT; + while (timeout > jiffies) { + if (card->channels_tested == TPAM_NBCHANNEL) + break; + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(2); + } + + card->running = 1; + + if (card->channels_tested != TPAM_NBCHANNEL) + printk(KERN_ERR "TurboPAM(tpam_command_ioctl_dsprun): " + "card=%d, tried to init %d channels, " + "got reply from only %d channels\n", card->id, + TPAM_NBCHANNEL, card->channels_tested); + + /* if all the channels were not initialized, signal to the ISDN + * link layer that fact that some channels are not usable */ + if (card->channels_used != TPAM_NBCHANNEL) + for (i = card->channels_used; i < TPAM_NBCHANNEL; ++i) { + ctrl.driver = card->id; + ctrl.command = ISDN_STAT_DISCH; + ctrl.arg = i; + ctrl.parm.num[0] = 0; + (* card->interface.statcallb)(&ctrl); + } + + printk(KERN_INFO "TurboPAM: card=%d, ready, %d channels available\n", + card->id, card->channels_used); + + /* let's rock ! */ + ctrl.driver = card->id; + ctrl.command = ISDN_STAT_RUN; + ctrl.arg = 0; + tpam_statcallb(card, ctrl); + + return 0; +} + +/* + * Set/reset the board's looptest mode. + * + * card: the board + * mode: if 1, sets the board's looptest mode, if 0 resets it. + * + * Return: 0 if OK, <0 if error. + */ +static int tpam_command_ioctl_loopmode(tpam_card *card, u8 mode) { + + /* board must be running */ + if (!card->running) + return -ENODEV; + + card->loopmode = mode; + return 0; +} + +/* + * Issue a dial command. This function builds and sends a CConnectReq. + * + * card: the board + * channel: the channel number + * phone: the remote phone number (EAZ) + * + * Return: 0 if OK, <0 if error. + */ +static int tpam_command_dial(tpam_card *card, u32 channel, u8 *phone) { + struct sk_buff *skb; + isdn_ctrl ctrl; + + dprintk("TurboPAM(tpam_command_dial): card=%d, channel=%lu, phone=%s\n", + card->id, (unsigned long)channel, phone); + + /* board must be running */ + if (!card->running) + return -ENODEV; + + /* initialize channel parameters */ + card->channels[channel].realhdlc = card->channels[channel].hdlc; + card->channels[channel].hdlcshift = 0; + card->channels[channel].readytoreceive = 0; + + /* build and send a CConnectReq */ + skb = build_CConnectReq(card->channels[channel].ncoid, phone, + card->channels[channel].realhdlc); + if (!skb) + return -ENOMEM; + tpam_enqueue(card, skb); + + /* making a connection in modem mode is slow and causes the ISDN + * link layer to hangup the connection before even it gets a chance + * to establish... All we can do is simulate a successful connection + * for now, and send a DHUP later if the connection fails */ + if (!card->channels[channel].realhdlc) { + ctrl.driver = card->id; + ctrl.command = ISDN_STAT_DCONN; + ctrl.arg = channel; + tpam_statcallb(card, ctrl); + } + + return 0; +} + +/* + * Set the level2 protocol (modem or HDLC). + * + * card: the board + * channel: the channel number + * proto: the level2 protocol (one of ISDN_PROTO_L2*) + * + * Return: 0 if OK, <0 if error. + */ +static int tpam_command_setl2(tpam_card *card, u32 channel, u8 proto) { + + dprintk("TurboPAM(tpam_command_setl2): card=%d, channel=%lu, proto=%d\n", + card->id, (unsigned long)channel, proto); + + /* board must be running */ + if (!card->running) + return -ENODEV; + + /* set the hdlc/modem mode */ + switch (proto) { + case ISDN_PROTO_L2_HDLC: + card->channels[channel].hdlc = 1; + break; + case ISDN_PROTO_L2_MODEM: + card->channels[channel].hdlc = 0; + break; + default: + return -EINVAL; + } + return 0; +} + +/* + * Return the level2 protocol (modem or HDLC). + * + * card: the board + * channel: the channel number + * + * Return: ISDN_PROTO_L2_HDLC/MODEM if OK, <0 if error. + */ +static int tpam_command_getl2(tpam_card *card, u32 channel) { + + dprintk("TurboPAM(tpam_command_getl2): card=%d, channel=%lu\n", + card->id, (unsigned long)channel); + + /* board must be running */ + if (!card->running) + return -ENODEV; + + /* return the current mode */ + if (card->channels[channel].realhdlc) + return ISDN_PROTO_L2_HDLC; + else + return ISDN_PROTO_L2_MODEM; +} + +/* + * Accept a D-channel connection (incoming connection). This function + * builds and sends a CConnectRsp message and signals DCONN to the ISDN + * link level. + * + * card: the board + * channel: the channel number + * + * Return: 0 if OK, <0 if error. + */ +static int tpam_command_acceptd(tpam_card *card, u32 channel) { + isdn_ctrl ctrl; + struct sk_buff *skb; + + dprintk("TurboPAM(tpam_command_acceptd): card=%d, channel=%lu\n", + card->id, (unsigned long)channel); + + /* board must be running */ + if (!card->running) + return -ENODEV; + + /* build and send a CConnectRsp */ + skb = build_CConnectRsp(card->channels[channel].ncoid); + if (!skb) + return -ENOMEM; + tpam_enqueue(card, skb); + + /* issue DCONN to the ISDN link level */ + ctrl.driver = card->id; + ctrl.command = ISDN_STAT_DCONN; + ctrl.arg = channel; + tpam_statcallb(card, ctrl); + return 0; +} + +/* + * Accepts a B-channel connection. This is not used by the driver, + * since the TurboPAM is an active card hiding its B-channels from + * us. We just signal BCONN to the ISDN link layer. + * + * card: the board + * channel: the channel number + * + * Return: 0 if OK, <0 if error. + */ +static int tpam_command_acceptb(tpam_card *card, u32 channel) { + isdn_ctrl ctrl; + + dprintk("TurboPAM(tpam_command_acceptb): card=%d, channel=%lu\n", + card->id, (unsigned long)channel); + + /* board must be running */ + if (!card->running) + return -ENODEV; + + /* issue BCONN to the ISDN link level */ + ctrl.driver = card->id; + ctrl.command = ISDN_STAT_BCONN; + ctrl.arg = channel; + ctrl.parm.num[0] = '\0'; + tpam_statcallb(card, ctrl); + return 0; +} + +/* + * Hang up a connection. This function builds and sends a CDisconnectReq. + * + * card: the board + * channel: the channel number. + * + * Return: 0 if OK, <0 if error. + */ +static int tpam_command_hangup(tpam_card *card, u32 channel) { + struct sk_buff *skb; + + dprintk("TurboPAM(tpam_command_hangup): card=%d, channel=%lu\n", + card->id, (unsigned long)channel); + + /* board must be running */ + if (!card->running) + return -ENODEV; + + /* build and send a CDisconnectReq */ + skb = build_CDisconnectReq(card->channels[channel].ncoid); + if (!skb) + return -ENOMEM; + tpam_enqueue(card, skb); + return 0; +} + +/* + * Proceed with an incoming connection. This function builds and sends a + * CConnectRsp. + * + * card: the board + * channel: the channel number. + * + * Return: 0 if OK, <0 if error. + */ +static int tpam_command_proceed(tpam_card *card, u32 channel) { + struct sk_buff *skb; + + dprintk("TurboPAM(tpam_command_proceed): card=%d, channel=%lu\n", + card->id, (unsigned long)channel); + + /* board must be running */ + if (!card->running) + return -ENODEV; + + /* build and send a CConnectRsp */ + skb = build_CConnectRsp(card->channels[channel].ncoid); + if (!skb) + return -ENOMEM; + tpam_enqueue(card, skb); + return 0; +} + +/* + * Send data through the board. This function encodes the data depending + * on the connection type (modem or HDLC), then builds and sends a U3DataReq. + * + * driverId: the driver id (really meaning here the board) + * channel: the channel number + * ack: data needs to be acknowledged upon send + * skb: sk_buff containing the data + * + * Return: size of data send if OK, <0 if error. + */ +int tpam_writebuf_skb(int driverId, int channel, int ack, struct sk_buff *skb) { + tpam_card *card; + int orig_size = skb->len; + void *finaldata; + u32 finallen; + + dprintk("TurboPAM(tpam_writebuf_skb): " + "card=%d, channel=%ld, ack=%d, data size=%d\n", + driverId, (unsigned long)channel, ack, skb->len); + + /* find the board based on its driver ID */ + if (!(card = tpam_findcard(driverId))) { + printk(KERN_ERR "TurboPAM(tpam_writebuf_skb): " + "invalid driverId %d\n", driverId); + return -ENODEV; + } + + /* board must be running */ + if (!card->running) + return -ENODEV; + + /* allocate some temporary memory */ + if (!(finaldata = (void *)__get_free_page(GFP_ATOMIC))) { + printk(KERN_ERR "TurboPAM(tpam_writebuf_skb): " + "get_free_page failed\n"); + return -ENOMEM; + } + + /* encode the data */ + if (!card->channels[channel].realhdlc) { + /* modem mode */ + hdlc_encode_modem(skb->data, skb->len, finaldata, &finallen); + } + else { + /* HDLC mode */ + void *tempdata; + u32 templen; + + if (!(tempdata = (void *)__get_free_page(GFP_ATOMIC))) { + printk(KERN_ERR "TurboPAM(tpam_writebuf_skb): " + "get_free_page failed\n"); + free_page((u32)finaldata); + return -ENOMEM; + } + hdlc_no_accm_encode(skb->data, skb->len, tempdata, &templen); + finallen = hdlc_encode(tempdata, finaldata, + &card->channels[channel].hdlcshift, + templen); + free_page((u32)tempdata); + } + + /* free the old sk_buff */ + kfree_skb(skb); + + /* build and send a U3DataReq */ + skb = build_U3DataReq(card->channels[channel].ncoid, finaldata, + finallen, ack, orig_size); + if (!skb) { + free_page((u32)finaldata); + return -ENOMEM; + } + tpam_enqueue_data(&card->channels[channel], skb); + + /* free the temporary memory */ + free_page((u32)finaldata); + return orig_size; +} + +/* + * Treat a received ACreateNCOCnf message. + * + * card: the board + * skb: the received message + */ +void tpam_recv_ACreateNCOCnf(tpam_card *card, struct sk_buff *skb) { + u32 ncoid; + u8 status; + u32 channel; + + dprintk("TurboPAM(tpam_recv_ACreateNCOCnf): card=%d\n", card->id); + + /* parse the message contents */ + if (parse_ACreateNCOCnf(skb, &status, &ncoid)) + return; + + /* if the card is alreay running, it means that this message + * arrives too late... */ + if (card->running) { + printk(KERN_ERR "TurboPAM(tpam_recv_ACreateNCOCnf): " + "ACreateNCOCnf received too late, status=%d\n", status); + return; + } + + /* the NCO creation failed, the corresponding channel will + * be unused */ + if (status) { + printk(KERN_ERR "TurboPAM(tpam_recv_ACreateNCOCnf): " + "ACreateNCO failed, status=%d\n", status); + card->channels_tested++; + return; + } + + /* find the first free channel and assign the nco ID to it */ + if ((channel = tpam_findchannel(card, TPAM_NCOID_INVALID)) == TPAM_CHANNEL_INVALID) { + printk(KERN_ERR "TurboPAM(tpam_recv_ACreateNCOCnf): " + "All channels are assigned\n"); + return; + } + card->channels[channel].ncoid = ncoid; + card->channels_tested++; + card->channels_used++; +} + +/* + * Treat a received ADestroyNCOCnf message. Not used by the driver. + * + * card: the board + * skb: the received message + */ +void tpam_recv_ADestroyNCOCnf(tpam_card *card, struct sk_buff *skb) { + u32 ncoid; + u8 status; + u32 channel; + + dprintk("TurboPAM(tpam_recv_ADestroyNCOCnf): card=%d\n", card->id); + + /* parse the message contents */ + if (parse_ADestroyNCOCnf(skb, &status, &ncoid)) + return; + + if (status) { + printk(KERN_ERR "TurboPAM(tpam_recv_ADestroyNCOCnf): " + "ADestroyNCO failed, status=%d\n", status); + return; + } + + /* clears the channel's nco ID */ + if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) { + printk(KERN_ERR "TurboPAM(tpam_recv_ADestroyNCOCnf): " + "ncoid invalid %lu\n", (unsigned long)ncoid); + return; + } + + card->channels[channel].ncoid = TPAM_NCOID_INVALID; +} + +/* + * Treat a received CConnectCnf message. + * + * card: the board + * skb: the received message + */ +void tpam_recv_CConnectCnf(tpam_card *card, struct sk_buff *skb) { + u32 ncoid; + u32 channel; + isdn_ctrl ctrl; + + dprintk("TurboPAM(tpam_recv_CConnectCnf): card=%d\n", card->id); + + /* parse the message contents */ + if (parse_CConnectCnf(skb, &ncoid)) + return; + + /* find the channel by its nco ID */ + if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) { + printk(KERN_ERR "TurboPAM(tpam_recv_CConnectCnf): " + "ncoid invalid %lu\n", (unsigned long)ncoid); + return; + } + + /* issue a DCONN command to the ISDN link layer if we are in HDLC mode. + * In modem mode, we alreay did it - the ISDN timer kludge */ + if (card->channels[channel].realhdlc) { + ctrl.driver = card->id; + ctrl.command = ISDN_STAT_DCONN; + ctrl.arg = channel; + (* card->interface.statcallb)(&ctrl); + } +} + +/* + * Treat a received CConnectInd message. This function signals a ICALL + * to the ISDN link layer. + * + * card: the board + * skb: the received message + */ +void tpam_recv_CConnectInd(tpam_card *card, struct sk_buff *skb) { + u32 ncoid; + u32 channel; + u8 hdlc, plan, screen; + u8 calling[PHONE_MAXIMUMSIZE], called[PHONE_MAXIMUMSIZE]; + isdn_ctrl ctrl; + int status; + + dprintk("TurboPAM(tpam_recv_CConnectInd): card=%d\n", card->id); + + /* parse the message contents */ + if (parse_CConnectInd(skb, &ncoid, &hdlc, calling, called, &plan, &screen)) + return; + + /* find the channel by its nco ID */ + if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) { + printk(KERN_ERR "TurboPAM(tpam_recv_CConnectInd): " + "ncoid invalid %lu\n", (unsigned long)ncoid); + return; + } + + /* initialize the channel parameters */ + card->channels[channel].realhdlc = hdlc; + card->channels[channel].hdlcshift = 0; + card->channels[channel].readytoreceive = 0; + + /* issue a ICALL command to the ISDN link layer */ + ctrl.driver = card->id; + ctrl.command = ISDN_STAT_ICALL; + ctrl.arg = channel; + memcpy(ctrl.parm.setup.phone, calling, 32); + memcpy(ctrl.parm.setup.eazmsn, called, 32); + ctrl.parm.setup.si1 = 7; /* data capability */ + ctrl.parm.setup.si2 = 0; + ctrl.parm.setup.plan = plan; + ctrl.parm.setup.screen = screen; + + status = (* card->interface.statcallb)(&ctrl); + switch (status) { + case 1: + case 4: + /* call accepted, link layer will send us a ACCEPTD + * command later */ + dprintk("TurboPAM(tpam_recv_CConnectInd): " + "card=%d, channel=%d, icall waiting, status=%d\n", + card->id, channel, status); + break; + default: + /* call denied, we build and send a CDisconnectReq */ + dprintk("TurboPAM(tpam_recv_CConnectInd): " + "card=%d, channel=%d, icall denied, status=%d\n", + card->id, channel, status); + skb = build_CDisconnectReq(ncoid); + if (!skb) + return; + tpam_enqueue(card, skb); + } +} + +/* + * Treat a received CDisconnectInd message. This function signals a DHUP and + * a BHUP to the ISDN link layer. + * + * card: the board + * skb: the received message + */ +void tpam_recv_CDisconnectInd(tpam_card *card, struct sk_buff *skb) { + u32 ncoid; + u32 channel; + u32 cause; + isdn_ctrl ctrl; + + dprintk("TurboPAM(tpam_recv_CDisconnectInd): card=%d\n", card->id); + + /* parse the message contents */ + if (parse_CDisconnectInd(skb, &ncoid, &cause)) + return; + + /* find the channel by its nco ID */ + if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) { + printk(KERN_ERR "TurboPAM(tpam_recv_CDisconnectInd): " + "ncoid invalid %lu\n", (unsigned long)ncoid); + return; + } + + /* build and send a CDisconnectRsp */ + skb = build_CDisconnectRsp(ncoid); + if (!skb) + return; + tpam_enqueue(card, skb); + + /* issue a DHUP to the ISDN link layer */ + ctrl.driver = card->id; + ctrl.command = ISDN_STAT_DHUP; + ctrl.arg = channel; + (* card->interface.statcallb)(&ctrl); + + /* issue a BHUP to the ISDN link layer */ + ctrl.driver = card->id; + ctrl.command = ISDN_STAT_BHUP; + ctrl.arg = channel; + (* card->interface.statcallb)(&ctrl); +} + +/* + * Treat a received CDisconnectCnf message. This function signals a DHUP and + * a BHUP to the ISDN link layer. + * + * card: the board + * skb: the received message + */ +void tpam_recv_CDisconnectCnf(tpam_card *card, struct sk_buff *skb) { + u32 ncoid; + u32 channel; + u32 cause; + isdn_ctrl ctrl; + + dprintk("TurboPAM(tpam_recv_CDisconnectCnf): card=%d\n", card->id); + + /* parse the message contents */ + if (parse_CDisconnectCnf(skb, &ncoid, &cause)) + return; + + /* find the channel by its nco ID */ + if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) { + printk(KERN_ERR "TurboPAM(tpam_recv_CDisconnectCnf): " + "ncoid invalid %lu\n", (unsigned long)ncoid); + return; + } + + /* issue a DHUP to the ISDN link layer */ + ctrl.driver = card->id; + ctrl.command = ISDN_STAT_DHUP; + ctrl.arg = channel; + (* card->interface.statcallb)(&ctrl); + + /* issue a BHUP to the ISDN link layer */ + ctrl.driver = card->id; + ctrl.command = ISDN_STAT_BHUP; + ctrl.arg = channel; + (* card->interface.statcallb)(&ctrl); +} + +/* + * Treat a received U3DataInd message. This function decodes the data + * depending on the connection type (modem or HDLC) and passes it to the + * ISDN link layer by using rcvcallb_skb. + * + * card: the board + * skb: the received message + data + */ +void tpam_recv_U3DataInd(tpam_card *card, struct sk_buff *skb) { + u32 ncoid; + u32 channel; + u8 *data; + u16 len; + struct sk_buff *result; + + dprintk("TurboPAM(tpam_recv_U3DataInd): card=%d, datalen=%d\n", + card->id, skb->len); + + /* parse the message contents */ + if (parse_U3DataInd(skb, &ncoid, &data, &len)) + return; + + /* find the channel by its nco ID */ + if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) { + printk(KERN_ERR "TurboPAM(tpam_recv_U3DataInd): " + "ncoid invalid %lu\n", (unsigned long)ncoid); + return; + } + + /* decode the data */ + if (card->channels[ncoid].realhdlc) { + /* HDLC mode */ + u8 *tempdata; + u32 templen; + + if (!(tempdata = (void *)__get_free_page(GFP_ATOMIC))) { + printk(KERN_ERR "TurboPAM(tpam_recv_U3DataInd): " + "get_free_page failed\n"); + return; + } + templen = hdlc_decode(data, tempdata, len); + templen = hdlc_no_accm_decode(tempdata, templen); + if (!(result = alloc_skb(templen, GFP_ATOMIC))) { + printk(KERN_ERR "TurboPAM(tpam_recv_U3DataInd): " + "alloc_skb failed\n"); + free_page((u32)tempdata); + return; + } + memcpy(skb_put(result, templen), tempdata, templen); + free_page((u32)tempdata); + } + else { + /* modem mode */ + if (!(result = alloc_skb(len, GFP_ATOMIC))) { + printk(KERN_ERR "TurboPAM(tpam_recv_U3DataInd): " + "alloc_skb failed\n"); + return; + } + memcpy(skb_put(result, len), data, len); + } + + /* In loop mode, resend the data immediatly */ + if (card->loopmode) { + struct sk_buff *loopskb; + + if (!(loopskb = alloc_skb(skb->len, GFP_ATOMIC))) { + printk(KERN_ERR "TurboPAM(tpam_recv_U3DataInd): " + "alloc_skb failed\n"); + kfree_skb(result); + return; + } + memcpy(skb_put(loopskb, result->len), result->data, + result->len); + if (tpam_writebuf_skb(card->id, channel, 0, loopskb) < 0) + kfree_skb(loopskb); + } + + /* pass the data to the ISDN link layer */ + (* card->interface.rcvcallb_skb)(card->id, channel, result); +} + +/* + * Treat a received U3ReadyToReceiveInd message. This function sets the + * channel ready flag and triggers the send of data if the channel becomed + * ready. + * + * card: the board + * skb: the received message + data + */ +void tpam_recv_U3ReadyToReceiveInd(tpam_card *card, struct sk_buff *skb) { + u32 ncoid; + u32 channel; + u8 ready; + + dprintk("TurboPAM(tpam_recv_U3ReadyToReceiveInd): card=%d\n", card->id); + + /* parse the message contents */ + if (parse_U3ReadyToReceiveInd(skb, &ncoid, &ready)) + return; + + /* find the channel by its nco ID */ + if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) { + printk(KERN_ERR "TurboPAM(tpam_recv_U3ReadyToReceiveInd): " + "ncoid invalid %lu\n", (unsigned long)ncoid); + return; + } + + /* set the readytoreceive flag */ + card->channels[channel].readytoreceive = ready; + + /* if the channel just becomed ready, trigger the send of queued data */ + if (ready) + tpam_enqueue_data(&card->channels[channel], NULL); +} + +/* + * Runs the delayed statcallb when its timer expires. + * + * parm: pointer to the tpam_statcallb_data statcallb argument. + */ +static void tpam_statcallb_run(unsigned long parm) { + tpam_statcallb_data *ds = (tpam_statcallb_data *)parm; + + dprintk("TurboPAM(tpam_statcallb_run)\n"); + + (* ds->card->interface.statcallb)(&ds->ctrl); + + kfree(ds->timer); + kfree(ds); +} + +/* + * Queues a statcallb call for delayed invocation. + * + * card: the board + * ctrl: the statcallb argument + */ +static void tpam_statcallb(tpam_card *card, isdn_ctrl ctrl) { + struct timer_list *timer; + tpam_statcallb_data *ds; + + dprintk("TurboPAM(tpam_statcallb): card=%d\n", card->id); + + if (!(timer = (struct timer_list *) kmalloc(sizeof(struct timer_list), + GFP_ATOMIC))) { + printk(KERN_ERR "TurboPAM: tpam_statcallb: kmalloc failed!\n"); + return; + } + + if (!(ds = (tpam_statcallb_data *) kmalloc(sizeof(tpam_statcallb_data), + GFP_ATOMIC))) { + printk(KERN_ERR "TurboPAM: tpam_statcallb: kmalloc failed!\n"); + kfree(timer); + return; + } + ds->card = card; + ds->timer = timer; + memcpy(&ds->ctrl, &ctrl, sizeof(isdn_ctrl)); + + init_timer(timer); + timer->function = tpam_statcallb_run; + timer->data = (unsigned long)ds; + timer->expires = jiffies + 0.1 * HZ; /* 0.1 second */ + add_timer(timer); +} diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/tpam/tpam_crcpc.c linux/drivers/isdn/tpam/tpam_crcpc.c --- v2.4.5/linux/drivers/isdn/tpam/tpam_crcpc.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/isdn/tpam/tpam_crcpc.c Mon Jul 2 14:07:55 2001 @@ -0,0 +1,207 @@ +/* $Id: tpam_crcpc.c,v 1.1.2.1 2001/06/05 19:45:37 kai Exp $ + * + * Turbo PAM ISDN driver for Linux. (Kernel Driver - CRC encoding) + * + * Copyright 1998-2000 AUVERTECH Télécom + * Copyright 2001 Stelian Pop , Alcôve + * + * For all support questions please contact: + * + * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +Module Name: + + crcpc.c + +Abstract: + + Modem HDLC coding + Software HDLC coding / decoding + +Revision History: + +---------------------------------------------------------------------------*/ + +#include "tpam.h" + +#define HDLC_CTRL_CHAR_CMPL_MASK 0x20 /* HDLC control character complement mask */ +#define HDLC_FLAG 0x7E /* HDLC flag */ +#define HDLC_CTRL_ESC 0x7D /* HDLC control escapr character */ +#define HDLC_LIKE_FCS_INIT_VAL 0xFFFF /* FCS initial value (0xFFFF for new equipment or 0) */ +#define HDLC_FCS_OK 0xF0B8 /* This value is the only valid value of FCS */ + +#define TRUE 1 +#define FALSE 0 + +static u16 t_ap_hdlc_like_fcs [256] = { + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; + +static u8 ap_t_ctrl_char_complemented[256]; /* list of characters to complement */ + +static void ap_hdlc_like_ctrl_char_list (u32 ctrl_char) { + int i; + + for (i = 0; i < 256; ++i) + ap_t_ctrl_char_complemented[i] = FALSE; + for (i = 0; i < 32; ++i) + if ((ctrl_char >> i) & 0x0001) + ap_t_ctrl_char_complemented [i] = TRUE; + ap_t_ctrl_char_complemented[HDLC_FLAG] = TRUE; + ap_t_ctrl_char_complemented[HDLC_CTRL_ESC] = TRUE; + +} + +void init_CRC() { + ap_hdlc_like_ctrl_char_list(0xffffffff); +} + +void hdlc_encode_modem(u8 *buffer_in, u32 lng_in, + u8 *buffer_out, u32 *lng_out) { + u16 fcs; + register u8 data; + register u8 *p_data_out = buffer_out; + + fcs = HDLC_LIKE_FCS_INIT_VAL; + + /* + * Insert HDLC flag at the beginning of the frame + */ + *p_data_out++ = HDLC_FLAG; + +#define ESCAPE_CHAR(data_out, data) \ + if (ap_t_ctrl_char_complemented[data]) { \ + *data_out++ = HDLC_CTRL_ESC; \ + *data_out++ = data ^ 0x20; \ + } \ + else \ + *data_out++ = data; + + while (lng_in--) { + data = *buffer_in++; + + /* + * FCS calculation + */ + fcs = (fcs>>8) ^ t_ap_hdlc_like_fcs[((u8)(fcs^data)) & 0xff]; + + ESCAPE_CHAR(p_data_out, data); + } + + /* + * Add FCS and closing flag + */ + fcs ^= 0xFFFF; // Complement + + data = (u8)(fcs & 0xff); /* LSB */ + ESCAPE_CHAR(p_data_out, data); + + data = (u8)((fcs >> 8)); /* MSB */ + ESCAPE_CHAR(p_data_out, data); +#undef ESCAPE_CHAR + + *p_data_out++ = HDLC_FLAG; + + *lng_out = (u32)(p_data_out - buffer_out); +} + +void hdlc_no_accm_encode(u8 *buffer_in, u32 lng_in, + u8 *buffer_out, u32 *lng_out) { + u16 fcs; + register u8 data; + register u8 *p_data_out = buffer_out; + + /* + * Insert HDLC flag at the beginning of the frame + */ + fcs = HDLC_LIKE_FCS_INIT_VAL; + + while (lng_in--) { + data = *buffer_in++; + /* calculate FCS */ + fcs = (fcs>>8) ^ t_ap_hdlc_like_fcs[((u8)(fcs^data)) & 0xff]; + *p_data_out++ = data; + } + + /* + * Add FCS and closing flag + */ + fcs ^= 0xFFFF; // Complement + data = (u8)(fcs); + *p_data_out++ = data; + + data =(u8)((fcs >> 8)); // revense MSB / LSB + *p_data_out++ = data; + + *lng_out = (u32)(p_data_out - buffer_out); +} + +u32 hdlc_no_accm_decode(u8 *buffer_in, u32 lng_in) { + u16 fcs; + u32 lng = lng_in; + register u8 data; + + /* + * Insert HDLC flag at the beginning of the frame + */ + fcs = HDLC_LIKE_FCS_INIT_VAL; + + while (lng_in--) { + data = *buffer_in++; + /* calculate FCS */ + fcs = (fcs>>8) ^ t_ap_hdlc_like_fcs[((u8)(fcs^data)) & 0xff]; + } + + if (fcs == HDLC_FCS_OK) + return (lng-2); + else + return 0; +} + diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/tpam/tpam_hdlc.c linux/drivers/isdn/tpam/tpam_hdlc.c --- v2.4.5/linux/drivers/isdn/tpam/tpam_hdlc.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/isdn/tpam/tpam_hdlc.c Mon Jul 2 14:07:55 2001 @@ -0,0 +1,934 @@ +/* $Id: tpam_hdlc.c,v 1.1.2.1 2001/06/05 19:45:37 kai Exp $ + * + * Turbo PAM ISDN driver for Linux. (Kernel Driver - HDLC encoding) + * + * Copyright 1998-2000 AUVERTECH Télécom + * Copyright 2001 Stelian Pop , Alcôve + * + * For all support questions please contact: + * + * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +Module Name: + + hdlc.c + +Abstract: + + stuff0 : array necessary for the bit stuffing algorithm + stuff1 : array necessary for the bit stuffing algorithm + stuff2 : array necessary for the bit stuffing algorithm + stuff3 : array necessary for the bit stuffing algorithm + stuff4 : array necessary for the bit stuffing algorithm + stuff5 : array necessary for the bit stuffing algorithm + stuffs[] : array conaining the previous 6 arrays + destuff0 : array necessary for the bit destuffing algorithm + destuff1 : array necessary for the bit destuffing algorithm + destuff2 : array necessary for the bit destuffing algorithm + destuff3 : array necessary for the bit destuffing algorithm + destuff4 : array necessary for the bit destuffing algorithm + destuff5 : array necessary for the bit destuffing algorithm + destuffs[] : array conaining the previous 6 arrays + + hdlc_encode : bit stuffing of a byte array, with the addition of a start and + end flag, using the bit shift given in parameter (which is + updated at the end of encoding). + hdlc_decode : bit de-stuffing of a byte array with detection of possible + ABORTs. + +Revision History: + +---------------------------------------------------------------------------*/ + +/* The arrays are used as follows: + + For the bit stuffing : + + stuff0 = used if the previous byte ended with '0' + stuff1 = used if the previous byte ended with '10' + stuff2 = used if the previous byte ended with '110' + stuff3 = used if the previous byte ended with '1110' + stuff4 = used if the previous byte ended with '11110' + stuff5 = used if the previous byte ended with '111110' + + those arrays are indexed by the byte to stuff. + + the data of those arrays are of the form (in binary): + "bbbbaaaa cccccccc" + with "cccccccc" : byte stuffed + "aaaa" : "0000" --> no insertion of '0' + "0100" --> 1 '0' inserted, carry = '0' + "0101" --> 1 '0' inserted, carry = '1' + "1000" --> 2 '0' inserted, carry = '00' + "1001" --> 2 '0' inserted, carry = '01' + "1010" --> 2 '0' inserted, carry = '10' + "1011" --> 2 '0' inserted, carry = '11' + "bbbb" : count of '1' at the end of "cccccccc" + + + + For the bit de-stuffing : + + destuff0 = used if the previous byte ended with '0' + destuff1 = used if the previous byte ended with '10' + destuff2 = used if the previous byte ended with '110' + destuff3 = used if the previous byte ended with '1110' + destuff4 = used if the previous byte ended with '11110' + destuff5 = used if the previous byte ended with '111110' + + those arrays are indexed by the byte to de-stuff. + + the data of those arrays are of the form (in binary): + "dbbbaaaa cccccccc" + with "cccccccc" : byte destuffed + "aaaa" : count of '1' at the end of the byte non destuffed + "bbb" : count of bits to use in the destuffed byte (8 less the count + of '0' deleted) less 1 (can be only 7, 6 or 5) + "d" : '1' if the byte non destuffed has more than 5 consecutive '1' + (flag or abort) +*/ + +#include +#include "tpam.h" + +typedef u8 BYTE; +typedef u16 WORD; +typedef u32 DWORD; +typedef u8 BOOL; + +#define TRUE 1 +#define FALSE 0 + +static WORD stuff0[] = +{ + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x041F, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x043E, 0x045F, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x149F, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007A, 0x007B, 0x047C, 0x047D, 0x14BE, 0x24DF, + 0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x1087, + 0x1088, 0x1089, 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x108F, + 0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x1097, + 0x1098, 0x1099, 0x109A, 0x109B, 0x109C, 0x109D, 0x109E, 0x051F, + 0x10A0, 0x10A1, 0x10A2, 0x10A3, 0x10A4, 0x10A5, 0x10A6, 0x10A7, + 0x10A8, 0x10A9, 0x10AA, 0x10AB, 0x10AC, 0x10AD, 0x10AE, 0x10AF, + 0x10B0, 0x10B1, 0x10B2, 0x10B3, 0x10B4, 0x10B5, 0x10B6, 0x10B7, + 0x10B8, 0x10B9, 0x10BA, 0x10BB, 0x10BC, 0x10BD, 0x053E, 0x055F, + 0x20C0, 0x20C1, 0x20C2, 0x20C3, 0x20C4, 0x20C5, 0x20C6, 0x20C7, + 0x20C8, 0x20C9, 0x20CA, 0x20CB, 0x20CC, 0x20CD, 0x20CE, 0x20CF, + 0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x20D7, + 0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x159F, + 0x30E0, 0x30E1, 0x30E2, 0x30E3, 0x30E4, 0x30E5, 0x30E6, 0x30E7, + 0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EE, 0x30EF, + 0x40F0, 0x40F1, 0x40F2, 0x40F3, 0x40F4, 0x40F5, 0x40F6, 0x40F7, + 0x50F8, 0x50F9, 0x50FA, 0x50FB, 0x057C, 0x057D, 0x15BE, 0x25DF, +}; + + +static WORD stuff1[] = +{ + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x040F, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x042F, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x044F, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x043E, 0x046F, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x148F, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x14AF, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x24CF, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007A, 0x007B, 0x047C, 0x047D, 0x14BE, 0x34EF, + 0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x1087, + 0x1088, 0x1089, 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x050F, + 0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x1097, + 0x1098, 0x1099, 0x109A, 0x109B, 0x109C, 0x109D, 0x109E, 0x052F, + 0x10A0, 0x10A1, 0x10A2, 0x10A3, 0x10A4, 0x10A5, 0x10A6, 0x10A7, + 0x10A8, 0x10A9, 0x10AA, 0x10AB, 0x10AC, 0x10AD, 0x10AE, 0x054F, + 0x10B0, 0x10B1, 0x10B2, 0x10B3, 0x10B4, 0x10B5, 0x10B6, 0x10B7, + 0x10B8, 0x10B9, 0x10BA, 0x10BB, 0x10BC, 0x10BD, 0x053E, 0x056F, + 0x20C0, 0x20C1, 0x20C2, 0x20C3, 0x20C4, 0x20C5, 0x20C6, 0x20C7, + 0x20C8, 0x20C9, 0x20CA, 0x20CB, 0x20CC, 0x20CD, 0x20CE, 0x158F, + 0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x20D7, + 0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x15AF, + 0x30E0, 0x30E1, 0x30E2, 0x30E3, 0x30E4, 0x30E5, 0x30E6, 0x30E7, + 0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EE, 0x25CF, + 0x40F0, 0x40F1, 0x40F2, 0x40F3, 0x40F4, 0x40F5, 0x40F6, 0x40F7, + 0x50F8, 0x50F9, 0x50FA, 0x50FB, 0x057C, 0x057D, 0x15BE, 0x35EF, +}; + + +static WORD stuff2[] = +{ + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0407, + 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x0417, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0427, + 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x0437, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0447, + 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x0457, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0467, + 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x043E, 0x0477, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x1487, + 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x1497, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x14A7, + 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x14B7, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x24C7, + 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x24D7, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x34E7, + 0x0078, 0x0079, 0x007A, 0x007B, 0x047C, 0x047D, 0x14BE, 0x44F7, + 0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x0507, + 0x1088, 0x1089, 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x0517, + 0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x0527, + 0x1098, 0x1099, 0x109A, 0x109B, 0x109C, 0x109D, 0x109E, 0x0537, + 0x10A0, 0x10A1, 0x10A2, 0x10A3, 0x10A4, 0x10A5, 0x10A6, 0x0547, + 0x10A8, 0x10A9, 0x10AA, 0x10AB, 0x10AC, 0x10AD, 0x10AE, 0x0557, + 0x10B0, 0x10B1, 0x10B2, 0x10B3, 0x10B4, 0x10B5, 0x10B6, 0x0567, + 0x10B8, 0x10B9, 0x10BA, 0x10BB, 0x10BC, 0x10BD, 0x053E, 0x0577, + 0x20C0, 0x20C1, 0x20C2, 0x20C3, 0x20C4, 0x20C5, 0x20C6, 0x1587, + 0x20C8, 0x20C9, 0x20CA, 0x20CB, 0x20CC, 0x20CD, 0x20CE, 0x1597, + 0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x15A7, + 0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x15B7, + 0x30E0, 0x30E1, 0x30E2, 0x30E3, 0x30E4, 0x30E5, 0x30E6, 0x25C7, + 0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EE, 0x25D7, + 0x40F0, 0x40F1, 0x40F2, 0x40F3, 0x40F4, 0x40F5, 0x40F6, 0x35E7, + 0x50F8, 0x50F9, 0x50FA, 0x50FB, 0x057C, 0x057D, 0x15BE, 0x45F7, +}; + + +static WORD stuff3[] = +{ + 0x0000, 0x0001, 0x0002, 0x0403, 0x0004, 0x0005, 0x0006, 0x040B, + 0x0008, 0x0009, 0x000A, 0x0413, 0x000C, 0x000D, 0x000E, 0x041B, + 0x0010, 0x0011, 0x0012, 0x0423, 0x0014, 0x0015, 0x0016, 0x042B, + 0x0018, 0x0019, 0x001A, 0x0433, 0x001C, 0x001D, 0x001E, 0x043B, + 0x0020, 0x0021, 0x0022, 0x0443, 0x0024, 0x0025, 0x0026, 0x044B, + 0x0028, 0x0029, 0x002A, 0x0453, 0x002C, 0x002D, 0x002E, 0x045B, + 0x0030, 0x0031, 0x0032, 0x0463, 0x0034, 0x0035, 0x0036, 0x046B, + 0x0038, 0x0039, 0x003A, 0x0473, 0x003C, 0x003D, 0x043E, 0x047B, + 0x0040, 0x0041, 0x0042, 0x1483, 0x0044, 0x0045, 0x0046, 0x148B, + 0x0048, 0x0049, 0x004A, 0x1493, 0x004C, 0x004D, 0x004E, 0x149B, + 0x0050, 0x0051, 0x0052, 0x14A3, 0x0054, 0x0055, 0x0056, 0x14AB, + 0x0058, 0x0059, 0x005A, 0x14B3, 0x005C, 0x005D, 0x005E, 0x14BB, + 0x0060, 0x0061, 0x0062, 0x24C3, 0x0064, 0x0065, 0x0066, 0x24CB, + 0x0068, 0x0069, 0x006A, 0x24D3, 0x006C, 0x006D, 0x006E, 0x24DB, + 0x0070, 0x0071, 0x0072, 0x34E3, 0x0074, 0x0075, 0x0076, 0x34EB, + 0x0078, 0x0079, 0x007A, 0x44F3, 0x047C, 0x047D, 0x14BE, 0x54FB, + 0x1080, 0x1081, 0x1082, 0x0503, 0x1084, 0x1085, 0x1086, 0x050B, + 0x1088, 0x1089, 0x108A, 0x0513, 0x108C, 0x108D, 0x108E, 0x051B, + 0x1090, 0x1091, 0x1092, 0x0523, 0x1094, 0x1095, 0x1096, 0x052B, + 0x1098, 0x1099, 0x109A, 0x0533, 0x109C, 0x109D, 0x109E, 0x053B, + 0x10A0, 0x10A1, 0x10A2, 0x0543, 0x10A4, 0x10A5, 0x10A6, 0x054B, + 0x10A8, 0x10A9, 0x10AA, 0x0553, 0x10AC, 0x10AD, 0x10AE, 0x055B, + 0x10B0, 0x10B1, 0x10B2, 0x0563, 0x10B4, 0x10B5, 0x10B6, 0x056B, + 0x10B8, 0x10B9, 0x10BA, 0x0573, 0x10BC, 0x10BD, 0x053E, 0x057B, + 0x20C0, 0x20C1, 0x20C2, 0x1583, 0x20C4, 0x20C5, 0x20C6, 0x158B, + 0x20C8, 0x20C9, 0x20CA, 0x1593, 0x20CC, 0x20CD, 0x20CE, 0x159B, + 0x20D0, 0x20D1, 0x20D2, 0x15A3, 0x20D4, 0x20D5, 0x20D6, 0x15AB, + 0x20D8, 0x20D9, 0x20DA, 0x15B3, 0x20DC, 0x20DD, 0x20DE, 0x15BB, + 0x30E0, 0x30E1, 0x30E2, 0x25C3, 0x30E4, 0x30E5, 0x30E6, 0x25CB, + 0x30E8, 0x30E9, 0x30EA, 0x25D3, 0x30EC, 0x30ED, 0x30EE, 0x25DB, + 0x40F0, 0x40F1, 0x40F2, 0x35E3, 0x40F4, 0x40F5, 0x40F6, 0x35EB, + 0x50F8, 0x50F9, 0x50FA, 0x45F3, 0x057C, 0x057D, 0x15BE, 0x55FB, +}; + + +static WORD stuff4[] = +{ + 0x0000, 0x0401, 0x0002, 0x0405, 0x0004, 0x0409, 0x0006, 0x040D, + 0x0008, 0x0411, 0x000A, 0x0415, 0x000C, 0x0419, 0x000E, 0x041D, + 0x0010, 0x0421, 0x0012, 0x0425, 0x0014, 0x0429, 0x0016, 0x042D, + 0x0018, 0x0431, 0x001A, 0x0435, 0x001C, 0x0439, 0x001E, 0x043D, + 0x0020, 0x0441, 0x0022, 0x0445, 0x0024, 0x0449, 0x0026, 0x044D, + 0x0028, 0x0451, 0x002A, 0x0455, 0x002C, 0x0459, 0x002E, 0x045D, + 0x0030, 0x0461, 0x0032, 0x0465, 0x0034, 0x0469, 0x0036, 0x046D, + 0x0038, 0x0471, 0x003A, 0x0475, 0x003C, 0x0479, 0x043E, 0x087D, + 0x0040, 0x1481, 0x0042, 0x1485, 0x0044, 0x1489, 0x0046, 0x148D, + 0x0048, 0x1491, 0x004A, 0x1495, 0x004C, 0x1499, 0x004E, 0x149D, + 0x0050, 0x14A1, 0x0052, 0x14A5, 0x0054, 0x14A9, 0x0056, 0x14AD, + 0x0058, 0x14B1, 0x005A, 0x14B5, 0x005C, 0x14B9, 0x005E, 0x14BD, + 0x0060, 0x24C1, 0x0062, 0x24C5, 0x0064, 0x24C9, 0x0066, 0x24CD, + 0x0068, 0x24D1, 0x006A, 0x24D5, 0x006C, 0x24D9, 0x006E, 0x24DD, + 0x0070, 0x34E1, 0x0072, 0x34E5, 0x0074, 0x34E9, 0x0076, 0x34ED, + 0x0078, 0x44F1, 0x007A, 0x44F5, 0x047C, 0x54F9, 0x14BE, 0x097D, + 0x1080, 0x0501, 0x1082, 0x0505, 0x1084, 0x0509, 0x1086, 0x050D, + 0x1088, 0x0511, 0x108A, 0x0515, 0x108C, 0x0519, 0x108E, 0x051D, + 0x1090, 0x0521, 0x1092, 0x0525, 0x1094, 0x0529, 0x1096, 0x052D, + 0x1098, 0x0531, 0x109A, 0x0535, 0x109C, 0x0539, 0x109E, 0x053D, + 0x10A0, 0x0541, 0x10A2, 0x0545, 0x10A4, 0x0549, 0x10A6, 0x054D, + 0x10A8, 0x0551, 0x10AA, 0x0555, 0x10AC, 0x0559, 0x10AE, 0x055D, + 0x10B0, 0x0561, 0x10B2, 0x0565, 0x10B4, 0x0569, 0x10B6, 0x056D, + 0x10B8, 0x0571, 0x10BA, 0x0575, 0x10BC, 0x0579, 0x053E, 0x0A7D, + 0x20C0, 0x1581, 0x20C2, 0x1585, 0x20C4, 0x1589, 0x20C6, 0x158D, + 0x20C8, 0x1591, 0x20CA, 0x1595, 0x20CC, 0x1599, 0x20CE, 0x159D, + 0x20D0, 0x15A1, 0x20D2, 0x15A5, 0x20D4, 0x15A9, 0x20D6, 0x15AD, + 0x20D8, 0x15B1, 0x20DA, 0x15B5, 0x20DC, 0x15B9, 0x20DE, 0x15BD, + 0x30E0, 0x25C1, 0x30E2, 0x25C5, 0x30E4, 0x25C9, 0x30E6, 0x25CD, + 0x30E8, 0x25D1, 0x30EA, 0x25D5, 0x30EC, 0x25D9, 0x30EE, 0x25DD, + 0x40F0, 0x35E1, 0x40F2, 0x35E5, 0x40F4, 0x35E9, 0x40F6, 0x35ED, + 0x50F8, 0x45F1, 0x50FA, 0x45F5, 0x057C, 0x55F9, 0x15BE, 0x0B7D, +}; + + +static WORD stuff5[] = +{ + 0x0400, 0x0402, 0x0404, 0x0406, 0x0408, 0x040A, 0x040C, 0x040E, + 0x0410, 0x0412, 0x0414, 0x0416, 0x0418, 0x041A, 0x041C, 0x041E, + 0x0420, 0x0422, 0x0424, 0x0426, 0x0428, 0x042A, 0x042C, 0x042E, + 0x0430, 0x0432, 0x0434, 0x0436, 0x0438, 0x043A, 0x043C, 0x083E, + 0x0440, 0x0442, 0x0444, 0x0446, 0x0448, 0x044A, 0x044C, 0x044E, + 0x0450, 0x0452, 0x0454, 0x0456, 0x0458, 0x045A, 0x045C, 0x045E, + 0x0460, 0x0462, 0x0464, 0x0466, 0x0468, 0x046A, 0x046C, 0x046E, + 0x0470, 0x0472, 0x0474, 0x0476, 0x0478, 0x047A, 0x087C, 0x18BE, + 0x1480, 0x1482, 0x1484, 0x1486, 0x1488, 0x148A, 0x148C, 0x148E, + 0x1490, 0x1492, 0x1494, 0x1496, 0x1498, 0x149A, 0x149C, 0x149E, + 0x14A0, 0x14A2, 0x14A4, 0x14A6, 0x14A8, 0x14AA, 0x14AC, 0x14AE, + 0x14B0, 0x14B2, 0x14B4, 0x14B6, 0x14B8, 0x14BA, 0x14BC, 0x093E, + 0x24C0, 0x24C2, 0x24C4, 0x24C6, 0x24C8, 0x24CA, 0x24CC, 0x24CE, + 0x24D0, 0x24D2, 0x24D4, 0x24D6, 0x24D8, 0x24DA, 0x24DC, 0x24DE, + 0x34E0, 0x34E2, 0x34E4, 0x34E6, 0x34E8, 0x34EA, 0x34EC, 0x34EE, + 0x44F0, 0x44F2, 0x44F4, 0x44F6, 0x54F8, 0x54FA, 0x097C, 0x19BE, + 0x0500, 0x0502, 0x0504, 0x0506, 0x0508, 0x050A, 0x050C, 0x050E, + 0x0510, 0x0512, 0x0514, 0x0516, 0x0518, 0x051A, 0x051C, 0x051E, + 0x0520, 0x0522, 0x0524, 0x0526, 0x0528, 0x052A, 0x052C, 0x052E, + 0x0530, 0x0532, 0x0534, 0x0536, 0x0538, 0x053A, 0x053C, 0x0A3E, + 0x0540, 0x0542, 0x0544, 0x0546, 0x0548, 0x054A, 0x054C, 0x054E, + 0x0550, 0x0552, 0x0554, 0x0556, 0x0558, 0x055A, 0x055C, 0x055E, + 0x0560, 0x0562, 0x0564, 0x0566, 0x0568, 0x056A, 0x056C, 0x056E, + 0x0570, 0x0572, 0x0574, 0x0576, 0x0578, 0x057A, 0x0A7C, 0x1ABE, + 0x1580, 0x1582, 0x1584, 0x1586, 0x1588, 0x158A, 0x158C, 0x158E, + 0x1590, 0x1592, 0x1594, 0x1596, 0x1598, 0x159A, 0x159C, 0x159E, + 0x15A0, 0x15A2, 0x15A4, 0x15A6, 0x15A8, 0x15AA, 0x15AC, 0x15AE, + 0x15B0, 0x15B2, 0x15B4, 0x15B6, 0x15B8, 0x15BA, 0x15BC, 0x0B3E, + 0x25C0, 0x25C2, 0x25C4, 0x25C6, 0x25C8, 0x25CA, 0x25CC, 0x25CE, + 0x25D0, 0x25D2, 0x25D4, 0x25D6, 0x25D8, 0x25DA, 0x25DC, 0x25DE, + 0x35E0, 0x35E2, 0x35E4, 0x35E6, 0x35E8, 0x35EA, 0x35EC, 0x35EE, + 0x45F0, 0x45F2, 0x45F4, 0x45F6, 0x55F8, 0x55FA, 0x0B7C, 0x1BBE, +}; + +static WORD destuff0[] = +{ + 0x7000, 0x7001, 0x7002, 0x7003, 0x7004, 0x7005, 0x7006, 0x7007, + 0x7008, 0x7009, 0x700A, 0x700B, 0x700C, 0x700D, 0x700E, 0x700F, + 0x7010, 0x7011, 0x7012, 0x7013, 0x7014, 0x7015, 0x7016, 0x7017, + 0x7018, 0x7019, 0x701A, 0x701B, 0x701C, 0x701D, 0x701E, 0x601F, + 0x7020, 0x7021, 0x7022, 0x7023, 0x7024, 0x7025, 0x7026, 0x7027, + 0x7028, 0x7029, 0x702A, 0x702B, 0x702C, 0x702D, 0x702E, 0x702F, + 0x7030, 0x7031, 0x7032, 0x7033, 0x7034, 0x7035, 0x7036, 0x7037, + 0x7038, 0x7039, 0x703A, 0x703B, 0x703C, 0x703D, 0x603E, 0xF03F, + 0x7040, 0x7041, 0x7042, 0x7043, 0x7044, 0x7045, 0x7046, 0x7047, + 0x7048, 0x7049, 0x704A, 0x704B, 0x704C, 0x704D, 0x704E, 0x704F, + 0x7050, 0x7051, 0x7052, 0x7053, 0x7054, 0x7055, 0x7056, 0x7057, + 0x7058, 0x7059, 0x705A, 0x705B, 0x705C, 0x705D, 0x705E, 0x603F, + 0x7060, 0x7061, 0x7062, 0x7063, 0x7064, 0x7065, 0x7066, 0x7067, + 0x7068, 0x7069, 0x706A, 0x706B, 0x706C, 0x706D, 0x706E, 0x706F, + 0x7070, 0x7071, 0x7072, 0x7073, 0x7074, 0x7075, 0x7076, 0x7077, + 0x7078, 0x7079, 0x707A, 0x707B, 0x607C, 0x607D, 0xF07E, 0xF07F, + 0x7180, 0x7181, 0x7182, 0x7183, 0x7184, 0x7185, 0x7186, 0x7187, + 0x7188, 0x7189, 0x718A, 0x718B, 0x718C, 0x718D, 0x718E, 0x718F, + 0x7190, 0x7191, 0x7192, 0x7193, 0x7194, 0x7195, 0x7196, 0x7197, + 0x7198, 0x7199, 0x719A, 0x719B, 0x719C, 0x719D, 0x719E, 0x615F, + 0x71A0, 0x71A1, 0x71A2, 0x71A3, 0x71A4, 0x71A5, 0x71A6, 0x71A7, + 0x71A8, 0x71A9, 0x71AA, 0x71AB, 0x71AC, 0x71AD, 0x71AE, 0x71AF, + 0x71B0, 0x71B1, 0x71B2, 0x71B3, 0x71B4, 0x71B5, 0x71B6, 0x71B7, + 0x71B8, 0x71B9, 0x71BA, 0x71BB, 0x71BC, 0x71BD, 0x617E, 0xF1BF, + 0x72C0, 0x72C1, 0x72C2, 0x72C3, 0x72C4, 0x72C5, 0x72C6, 0x72C7, + 0x72C8, 0x72C9, 0x72CA, 0x72CB, 0x72CC, 0x72CD, 0x72CE, 0x72CF, + 0x72D0, 0x72D1, 0x72D2, 0x72D3, 0x72D4, 0x72D5, 0x72D6, 0x72D7, + 0x72D8, 0x72D9, 0x72DA, 0x72DB, 0x72DC, 0x72DD, 0x72DE, 0x627F, + 0x73E0, 0x73E1, 0x73E2, 0x73E3, 0x73E4, 0x73E5, 0x73E6, 0x73E7, + 0x73E8, 0x73E9, 0x73EA, 0x73EB, 0x73EC, 0x73ED, 0x73EE, 0x73EF, + 0x74F0, 0x74F1, 0x74F2, 0x74F3, 0x74F4, 0x74F5, 0x74F6, 0x74F7, + 0x75F8, 0x75F9, 0x75FA, 0x75FB, 0xF6FC, 0xF6FD, 0xF7FE, 0xF8FF, +}; + + +static WORD destuff1[] = +{ + 0x7000, 0x7001, 0x7002, 0x7003, 0x7004, 0x7005, 0x7006, 0x7007, + 0x7008, 0x7009, 0x700A, 0x700B, 0x700C, 0x700D, 0x700E, 0x600F, + 0x7010, 0x7011, 0x7012, 0x7013, 0x7014, 0x7015, 0x7016, 0x7017, + 0x7018, 0x7019, 0x701A, 0x701B, 0x701C, 0x701D, 0x701E, 0xF01F, + 0x7020, 0x7021, 0x7022, 0x7023, 0x7024, 0x7025, 0x7026, 0x7027, + 0x7028, 0x7029, 0x702A, 0x702B, 0x702C, 0x702D, 0x702E, 0x601F, + 0x7030, 0x7031, 0x7032, 0x7033, 0x7034, 0x7035, 0x7036, 0x7037, + 0x7038, 0x7039, 0x703A, 0x703B, 0x703C, 0x703D, 0x603E, 0xF03F, + 0x7040, 0x7041, 0x7042, 0x7043, 0x7044, 0x7045, 0x7046, 0x7047, + 0x7048, 0x7049, 0x704A, 0x704B, 0x704C, 0x704D, 0x704E, 0x602F, + 0x7050, 0x7051, 0x7052, 0x7053, 0x7054, 0x7055, 0x7056, 0x7057, + 0x7058, 0x7059, 0x705A, 0x705B, 0x705C, 0x705D, 0x705E, 0xF05F, + 0x7060, 0x7061, 0x7062, 0x7063, 0x7064, 0x7065, 0x7066, 0x7067, + 0x7068, 0x7069, 0x706A, 0x706B, 0x706C, 0x706D, 0x706E, 0x603F, + 0x7070, 0x7071, 0x7072, 0x7073, 0x7074, 0x7075, 0x7076, 0x7077, + 0x7078, 0x7079, 0x707A, 0x707B, 0x607C, 0x607D, 0xF07E, 0xF07F, + 0x7180, 0x7181, 0x7182, 0x7183, 0x7184, 0x7185, 0x7186, 0x7187, + 0x7188, 0x7189, 0x718A, 0x718B, 0x718C, 0x718D, 0x718E, 0x614F, + 0x7190, 0x7191, 0x7192, 0x7193, 0x7194, 0x7195, 0x7196, 0x7197, + 0x7198, 0x7199, 0x719A, 0x719B, 0x719C, 0x719D, 0x719E, 0xF19F, + 0x71A0, 0x71A1, 0x71A2, 0x71A3, 0x71A4, 0x71A5, 0x71A6, 0x71A7, + 0x71A8, 0x71A9, 0x71AA, 0x71AB, 0x71AC, 0x71AD, 0x71AE, 0x615F, + 0x71B0, 0x71B1, 0x71B2, 0x71B3, 0x71B4, 0x71B5, 0x71B6, 0x71B7, + 0x71B8, 0x71B9, 0x71BA, 0x71BB, 0x71BC, 0x71BD, 0x617E, 0xF1BF, + 0x72C0, 0x72C1, 0x72C2, 0x72C3, 0x72C4, 0x72C5, 0x72C6, 0x72C7, + 0x72C8, 0x72C9, 0x72CA, 0x72CB, 0x72CC, 0x72CD, 0x72CE, 0x626F, + 0x72D0, 0x72D1, 0x72D2, 0x72D3, 0x72D4, 0x72D5, 0x72D6, 0x72D7, + 0x72D8, 0x72D9, 0x72DA, 0x72DB, 0x72DC, 0x72DD, 0x72DE, 0xF2DF, + 0x73E0, 0x73E1, 0x73E2, 0x73E3, 0x73E4, 0x73E5, 0x73E6, 0x73E7, + 0x73E8, 0x73E9, 0x73EA, 0x73EB, 0x73EC, 0x73ED, 0x73EE, 0x637F, + 0x74F0, 0x74F1, 0x74F2, 0x74F3, 0x74F4, 0x74F5, 0x74F6, 0x74F7, + 0x75F8, 0x75F9, 0x75FA, 0x75FB, 0xF6FC, 0xF6FD, 0xF7FE, 0xF9FF, +}; + + +static WORD destuff2[] = +{ + 0x7000, 0x7001, 0x7002, 0x7003, 0x7004, 0x7005, 0x7006, 0x6007, + 0x7008, 0x7009, 0x700A, 0x700B, 0x700C, 0x700D, 0x700E, 0xF00F, + 0x7010, 0x7011, 0x7012, 0x7013, 0x7014, 0x7015, 0x7016, 0x600F, + 0x7018, 0x7019, 0x701A, 0x701B, 0x701C, 0x701D, 0x701E, 0xF01F, + 0x7020, 0x7021, 0x7022, 0x7023, 0x7024, 0x7025, 0x7026, 0x6017, + 0x7028, 0x7029, 0x702A, 0x702B, 0x702C, 0x702D, 0x702E, 0xF02F, + 0x7030, 0x7031, 0x7032, 0x7033, 0x7034, 0x7035, 0x7036, 0x601F, + 0x7038, 0x7039, 0x703A, 0x703B, 0x703C, 0x703D, 0x603E, 0xF03F, + 0x7040, 0x7041, 0x7042, 0x7043, 0x7044, 0x7045, 0x7046, 0x6027, + 0x7048, 0x7049, 0x704A, 0x704B, 0x704C, 0x704D, 0x704E, 0xF04F, + 0x7050, 0x7051, 0x7052, 0x7053, 0x7054, 0x7055, 0x7056, 0x602F, + 0x7058, 0x7059, 0x705A, 0x705B, 0x705C, 0x705D, 0x705E, 0xF05F, + 0x7060, 0x7061, 0x7062, 0x7063, 0x7064, 0x7065, 0x7066, 0x6037, + 0x7068, 0x7069, 0x706A, 0x706B, 0x706C, 0x706D, 0x706E, 0xF06F, + 0x7070, 0x7071, 0x7072, 0x7073, 0x7074, 0x7075, 0x7076, 0x603F, + 0x7078, 0x7079, 0x707A, 0x707B, 0x607C, 0x607D, 0xF07E, 0xF07F, + 0x7180, 0x7181, 0x7182, 0x7183, 0x7184, 0x7185, 0x7186, 0x6147, + 0x7188, 0x7189, 0x718A, 0x718B, 0x718C, 0x718D, 0x718E, 0xF18F, + 0x7190, 0x7191, 0x7192, 0x7193, 0x7194, 0x7195, 0x7196, 0x614F, + 0x7198, 0x7199, 0x719A, 0x719B, 0x719C, 0x719D, 0x719E, 0xF19F, + 0x71A0, 0x71A1, 0x71A2, 0x71A3, 0x71A4, 0x71A5, 0x71A6, 0x6157, + 0x71A8, 0x71A9, 0x71AA, 0x71AB, 0x71AC, 0x71AD, 0x71AE, 0xF1AF, + 0x71B0, 0x71B1, 0x71B2, 0x71B3, 0x71B4, 0x71B5, 0x71B6, 0x615F, + 0x71B8, 0x71B9, 0x71BA, 0x71BB, 0x71BC, 0x71BD, 0x617E, 0xF1BF, + 0x72C0, 0x72C1, 0x72C2, 0x72C3, 0x72C4, 0x72C5, 0x72C6, 0x6267, + 0x72C8, 0x72C9, 0x72CA, 0x72CB, 0x72CC, 0x72CD, 0x72CE, 0xF2CF, + 0x72D0, 0x72D1, 0x72D2, 0x72D3, 0x72D4, 0x72D5, 0x72D6, 0x626F, + 0x72D8, 0x72D9, 0x72DA, 0x72DB, 0x72DC, 0x72DD, 0x72DE, 0xF2DF, + 0x73E0, 0x73E1, 0x73E2, 0x73E3, 0x73E4, 0x73E5, 0x73E6, 0x6377, + 0x73E8, 0x73E9, 0x73EA, 0x73EB, 0x73EC, 0x73ED, 0x73EE, 0xF3EF, + 0x74F0, 0x74F1, 0x74F2, 0x74F3, 0x74F4, 0x74F5, 0x74F6, 0x647F, + 0x75F8, 0x75F9, 0x75FA, 0x75FB, 0xF6FC, 0xF6FD, 0xF7FE, 0xFAFF, +}; + + +static WORD destuff3[] = +{ + 0x7000, 0x7001, 0x7002, 0x6003, 0x7004, 0x7005, 0x7006, 0xF007, + 0x7008, 0x7009, 0x700A, 0x6007, 0x700C, 0x700D, 0x700E, 0xF00F, + 0x7010, 0x7011, 0x7012, 0x600B, 0x7014, 0x7015, 0x7016, 0xF017, + 0x7018, 0x7019, 0x701A, 0x600F, 0x701C, 0x701D, 0x701E, 0xF01F, + 0x7020, 0x7021, 0x7022, 0x6013, 0x7024, 0x7025, 0x7026, 0xF027, + 0x7028, 0x7029, 0x702A, 0x6017, 0x702C, 0x702D, 0x702E, 0xF02F, + 0x7030, 0x7031, 0x7032, 0x601B, 0x7034, 0x7035, 0x7036, 0xF037, + 0x7038, 0x7039, 0x703A, 0x601F, 0x703C, 0x703D, 0x603E, 0xF03F, + 0x7040, 0x7041, 0x7042, 0x6023, 0x7044, 0x7045, 0x7046, 0xF047, + 0x7048, 0x7049, 0x704A, 0x6027, 0x704C, 0x704D, 0x704E, 0xF04F, + 0x7050, 0x7051, 0x7052, 0x602B, 0x7054, 0x7055, 0x7056, 0xF057, + 0x7058, 0x7059, 0x705A, 0x602F, 0x705C, 0x705D, 0x705E, 0xF05F, + 0x7060, 0x7061, 0x7062, 0x6033, 0x7064, 0x7065, 0x7066, 0xF067, + 0x7068, 0x7069, 0x706A, 0x6037, 0x706C, 0x706D, 0x706E, 0xF06F, + 0x7070, 0x7071, 0x7072, 0x603B, 0x7074, 0x7075, 0x7076, 0xF077, + 0x7078, 0x7079, 0x707A, 0x603F, 0x607C, 0x607D, 0xF07E, 0xF07F, + 0x7180, 0x7181, 0x7182, 0x6143, 0x7184, 0x7185, 0x7186, 0xF187, + 0x7188, 0x7189, 0x718A, 0x6147, 0x718C, 0x718D, 0x718E, 0xF18F, + 0x7190, 0x7191, 0x7192, 0x614B, 0x7194, 0x7195, 0x7196, 0xF197, + 0x7198, 0x7199, 0x719A, 0x614F, 0x719C, 0x719D, 0x719E, 0xF19F, + 0x71A0, 0x71A1, 0x71A2, 0x6153, 0x71A4, 0x71A5, 0x71A6, 0xF1A7, + 0x71A8, 0x71A9, 0x71AA, 0x6157, 0x71AC, 0x71AD, 0x71AE, 0xF1AF, + 0x71B0, 0x71B1, 0x71B2, 0x615B, 0x71B4, 0x71B5, 0x71B6, 0xF1B7, + 0x71B8, 0x71B9, 0x71BA, 0x615F, 0x71BC, 0x71BD, 0x617E, 0xF1BF, + 0x72C0, 0x72C1, 0x72C2, 0x6263, 0x72C4, 0x72C5, 0x72C6, 0xF2C7, + 0x72C8, 0x72C9, 0x72CA, 0x6267, 0x72CC, 0x72CD, 0x72CE, 0xF2CF, + 0x72D0, 0x72D1, 0x72D2, 0x626B, 0x72D4, 0x72D5, 0x72D6, 0xF2D7, + 0x72D8, 0x72D9, 0x72DA, 0x626F, 0x72DC, 0x72DD, 0x72DE, 0xF2DF, + 0x73E0, 0x73E1, 0x73E2, 0x6373, 0x73E4, 0x73E5, 0x73E6, 0xF3E7, + 0x73E8, 0x73E9, 0x73EA, 0x6377, 0x73EC, 0x73ED, 0x73EE, 0xF3EF, + 0x74F0, 0x74F1, 0x74F2, 0x647B, 0x74F4, 0x74F5, 0x74F6, 0xF4F7, + 0x75F8, 0x75F9, 0x75FA, 0x657F, 0xF6FC, 0xF6FD, 0xF7FE, 0xFBFF, +}; + + +static WORD destuff4[] = +{ + 0x7000, 0x6001, 0x7002, 0xF003, 0x7004, 0x6003, 0x7006, 0xF007, + 0x7008, 0x6005, 0x700A, 0xF00B, 0x700C, 0x6007, 0x700E, 0xF00F, + 0x7010, 0x6009, 0x7012, 0xF013, 0x7014, 0x600B, 0x7016, 0xF017, + 0x7018, 0x600D, 0x701A, 0xF01B, 0x701C, 0x600F, 0x701E, 0xF01F, + 0x7020, 0x6011, 0x7022, 0xF023, 0x7024, 0x6013, 0x7026, 0xF027, + 0x7028, 0x6015, 0x702A, 0xF02B, 0x702C, 0x6017, 0x702E, 0xF02F, + 0x7030, 0x6019, 0x7032, 0xF033, 0x7034, 0x601B, 0x7036, 0xF037, + 0x7038, 0x601D, 0x703A, 0xF03B, 0x703C, 0x601F, 0x603E, 0xF03F, + 0x7040, 0x6021, 0x7042, 0xF043, 0x7044, 0x6023, 0x7046, 0xF047, + 0x7048, 0x6025, 0x704A, 0xF04B, 0x704C, 0x6027, 0x704E, 0xF04F, + 0x7050, 0x6029, 0x7052, 0xF053, 0x7054, 0x602B, 0x7056, 0xF057, + 0x7058, 0x602D, 0x705A, 0xF05B, 0x705C, 0x602F, 0x705E, 0xF05F, + 0x7060, 0x6031, 0x7062, 0xF063, 0x7064, 0x6033, 0x7066, 0xF067, + 0x7068, 0x6035, 0x706A, 0xF06B, 0x706C, 0x6037, 0x706E, 0xF06F, + 0x7070, 0x6039, 0x7072, 0xF073, 0x7074, 0x603B, 0x7076, 0xF077, + 0x7078, 0x603D, 0x707A, 0xF07B, 0x607C, 0x503F, 0xF07E, 0xF07F, + 0x7180, 0x6141, 0x7182, 0xF183, 0x7184, 0x6143, 0x7186, 0xF187, + 0x7188, 0x6145, 0x718A, 0xF18B, 0x718C, 0x6147, 0x718E, 0xF18F, + 0x7190, 0x6149, 0x7192, 0xF193, 0x7194, 0x614B, 0x7196, 0xF197, + 0x7198, 0x614D, 0x719A, 0xF19B, 0x719C, 0x614F, 0x719E, 0xF19F, + 0x71A0, 0x6151, 0x71A2, 0xF1A3, 0x71A4, 0x6153, 0x71A6, 0xF1A7, + 0x71A8, 0x6155, 0x71AA, 0xF1AB, 0x71AC, 0x6157, 0x71AE, 0xF1AF, + 0x71B0, 0x6159, 0x71B2, 0xF1B3, 0x71B4, 0x615B, 0x71B6, 0xF1B7, + 0x71B8, 0x615D, 0x71BA, 0xF1BB, 0x71BC, 0x615F, 0x617E, 0xF1BF, + 0x72C0, 0x6261, 0x72C2, 0xF2C3, 0x72C4, 0x6263, 0x72C6, 0xF2C7, + 0x72C8, 0x6265, 0x72CA, 0xF2CB, 0x72CC, 0x6267, 0x72CE, 0xF2CF, + 0x72D0, 0x6269, 0x72D2, 0xF2D3, 0x72D4, 0x626B, 0x72D6, 0xF2D7, + 0x72D8, 0x626D, 0x72DA, 0xF2DB, 0x72DC, 0x626F, 0x72DE, 0xF2DF, + 0x73E0, 0x6371, 0x73E2, 0xF3E3, 0x73E4, 0x6373, 0x73E6, 0xF3E7, + 0x73E8, 0x6375, 0x73EA, 0xF3EB, 0x73EC, 0x6377, 0x73EE, 0xF3EF, + 0x74F0, 0x6479, 0x74F2, 0xF4F3, 0x74F4, 0x647B, 0x74F6, 0xF4F7, + 0x75F8, 0x657D, 0x75FA, 0xF5FB, 0xF6FC, 0xE67F, 0xF7FE, 0xFCFF, +}; + + +static WORD destuff5[] = +{ + 0x6000, 0xF001, 0x6001, 0xF003, 0x6002, 0xF005, 0x6003, 0xF007, + 0x6004, 0xF009, 0x6005, 0xF00B, 0x6006, 0xF00D, 0x6007, 0xF00F, + 0x6008, 0xF011, 0x6009, 0xF013, 0x600A, 0xF015, 0x600B, 0xF017, + 0x600C, 0xF019, 0x600D, 0xF01B, 0x600E, 0xF01D, 0x600F, 0xF01F, + 0x6010, 0xF021, 0x6011, 0xF023, 0x6012, 0xF025, 0x6013, 0xF027, + 0x6014, 0xF029, 0x6015, 0xF02B, 0x6016, 0xF02D, 0x6017, 0xF02F, + 0x6018, 0xF031, 0x6019, 0xF033, 0x601A, 0xF035, 0x601B, 0xF037, + 0x601C, 0xF039, 0x601D, 0xF03B, 0x601E, 0xF03D, 0x501F, 0xF03F, + 0x6020, 0xF041, 0x6021, 0xF043, 0x6022, 0xF045, 0x6023, 0xF047, + 0x6024, 0xF049, 0x6025, 0xF04B, 0x6026, 0xF04D, 0x6027, 0xF04F, + 0x6028, 0xF051, 0x6029, 0xF053, 0x602A, 0xF055, 0x602B, 0xF057, + 0x602C, 0xF059, 0x602D, 0xF05B, 0x602E, 0xF05D, 0x602F, 0xF05F, + 0x6030, 0xF061, 0x6031, 0xF063, 0x6032, 0xF065, 0x6033, 0xF067, + 0x6034, 0xF069, 0x6035, 0xF06B, 0x6036, 0xF06D, 0x6037, 0xF06F, + 0x6038, 0xF071, 0x6039, 0xF073, 0x603A, 0xF075, 0x603B, 0xF077, + 0x603C, 0xF079, 0x603D, 0xF07B, 0x503E, 0xE07D, 0xE03F, 0xF07F, + 0x6140, 0xF181, 0x6141, 0xF183, 0x6142, 0xF185, 0x6143, 0xF187, + 0x6144, 0xF189, 0x6145, 0xF18B, 0x6146, 0xF18D, 0x6147, 0xF18F, + 0x6148, 0xF191, 0x6149, 0xF193, 0x614A, 0xF195, 0x614B, 0xF197, + 0x614C, 0xF199, 0x614D, 0xF19B, 0x614E, 0xF19D, 0x614F, 0xF19F, + 0x6150, 0xF1A1, 0x6151, 0xF1A3, 0x6152, 0xF1A5, 0x6153, 0xF1A7, + 0x6154, 0xF1A9, 0x6155, 0xF1AB, 0x6156, 0xF1AD, 0x6157, 0xF1AF, + 0x6158, 0xF1B1, 0x6159, 0xF1B3, 0x615A, 0xF1B5, 0x615B, 0xF1B7, + 0x615C, 0xF1B9, 0x615D, 0xF1BB, 0x615E, 0xF1BD, 0x513F, 0xF1BF, + 0x6260, 0xF2C1, 0x6261, 0xF2C3, 0x6262, 0xF2C5, 0x6263, 0xF2C7, + 0x6264, 0xF2C9, 0x6265, 0xF2CB, 0x6266, 0xF2CD, 0x6267, 0xF2CF, + 0x6268, 0xF2D1, 0x6269, 0xF2D3, 0x626A, 0xF2D5, 0x626B, 0xF2D7, + 0x626C, 0xF2D9, 0x626D, 0xF2DB, 0x626E, 0xF2DD, 0x626F, 0xF2DF, + 0x6370, 0xF3E1, 0x6371, 0xF3E3, 0x6372, 0xF3E5, 0x6373, 0xF3E7, + 0x6374, 0xF3E9, 0x6375, 0xF3EB, 0x6376, 0xF3ED, 0x6377, 0xF3EF, + 0x6478, 0xF4F1, 0x6479, 0xF4F3, 0x647A, 0xF4F5, 0x647B, 0xF4F7, + 0x657C, 0xF5F9, 0x657D, 0xF5FB, 0xE67E, 0xF6FD, 0xE77F, 0xFDFF, +}; + + +static WORD * stuffs[] = { stuff0, stuff1, stuff2, stuff3, stuff4, stuff5 }; +WORD * destuffs[] = { destuff0, destuff1, destuff2, destuff3, destuff4, destuff5 }; + + +/*- AuverTech Telecom -------------------------------------------------------+ + | | + | @Function : hdlc_encode | + | @Author : Cyrille Boudon | + | | + +---------------------------------------------------------------------------+ + | | + | @Param : BYTE *pbyBuffIn IN, array of bytes to encode | + | @Param : BYTE *pbyBuffOut OUT, array of bytes encoded | + | @Param : DWORD *pdwInitialShift INOUT, initial shift | + | @Param : DWORD dwLength IN, count of bytes to encode | + | | + | @Return : DWORD count of bytes encoded | + | | + +------------------------------- @Abstract ---------------------------------+ + | | + | Bit stuffing of thz array pbyBuffIn with the insertion of a flag at the | + | beginning and the end, using the initial shift (due to the emission of | + | previous frames). The last byte can be used to insert flags (by outputting| + | the flag N times) before the next frame. The initial shift is updated at | + | the end of the algorithm for the next frame. Its signification is: for the| + | flags shifted like "1100111111001111" *pdwInitialShift = 3. At the | + | beginning (for the first frame), the shift must be initialized to 0. | + | | + +---------------------------------------------------------------------------*/ +DWORD hdlc_encode(BYTE *pbyBuffIn, BYTE *pbyBuffOut, + DWORD *pdwInitialShift, DWORD dwLength) +{ + DWORD dwShifter; // temporary variable + DWORD dwShiftNb; // shift due to the insertion of '0' + DWORD dwState; // count of '1' at the end of the current byte + DWORD dwNb; // length of the encoded array + BYTE byCarry; // carry due to the shift + BYTE byNewCarry; // temporary variable + BYTE byCharIn; // byte being encoded + BYTE byCarryMSB; // lost bit of the carry if dwShiftNb=7 and 2 '0' inserted + WORD woDecal; // temporary variable + WORD woInfo; // data read in the arrays + BOOL bContinue; // true until the two last bytes + BOOL bContinue2; // true until the last byte + + bContinue = TRUE; + bContinue2 = TRUE; + dwShiftNb = 0; + byCarry = 0; + dwState = 0; + woDecal = 0x7E; + byCarryMSB = 0xFF; + dwNb = 1; // length to 1 to account for the first flag + + /*----------------------------- + | insert the flag using the + | shift given by + | *pdwInitialShift) + +-----------------------------*/ + * pbyBuffOut ++ = 0x7E7E >> *pdwInitialShift; + + /*----------------------------- + | main loop + +-----------------------------*/ + while (dwLength--) + { + byCharIn = *pbyBuffIn ++; + +/*----------------------------- + | go back here to treat the + | carry when its length + | is over 7 and for the first + | byte (with flag) + +-----------------------------*/ +carry: + + dwNb ++; + + /*----------------------------- + | shift the byte to get the + | byte to encode (without + | taking into account the + | initial shift) + +-----------------------------*/ + if (dwShiftNb) + { + dwShifter = byCharIn << dwShiftNb; + byNewCarry = dwShifter >> 8; + byCharIn = dwShifter | byCarry; + byCarry = byNewCarry; + } + + /*----------------------------- + | get the data from the arrays + | and take into account the + | initial shift for the byte + | to encode + +-----------------------------*/ + woInfo = stuffs[dwState][byCharIn]; + woDecal |= (woInfo & 0x00FF) << 8; + * pbyBuffOut ++ = woDecal >> *pdwInitialShift; + woDecal = woInfo & 0x00FF; + dwState = woInfo >> 12; + + /*----------------------------- + | treat the lost bit if we had + | a carry overflow + +-----------------------------*/ + if (byCarryMSB != 0xFF) + { + if (!dwShiftNb) + { + if(byCarryMSB) + byCarry = 1; + dwShiftNb = 1; + } + byCarryMSB = 0xFF; + } + + /*----------------------------- + | if one '0' get inserted, we + | have to calculate the new + | carry and the new shift + +-----------------------------*/ + if (woInfo & 0x0F00) + { + byCarryMSB = byCarry & 0x40; + byCarry <<= (woInfo & 0x0C00) >> 10; + byCarry |= (woInfo & 0x0300) >> 8; + dwShiftNb += (woInfo & 0x0C00) >> 10; + } + + /*----------------------------- + | if the carry is a whole byte + | we use it as a byte to encode + +-----------------------------*/ + if (dwShiftNb > 7) + { + if (dwShiftNb == 8) + byCarryMSB = 0xFF; + dwShiftNb = 0; + byCharIn = byCarry; + byCarry = 0; + goto carry; + } + + /*----------------------------- + | at the end of the array + +-----------------------------*/ + if (!dwLength) + { + /*----------------------------- + | take into account the bits + | set in the carry + +-----------------------------*/ + if (bContinue) + { + bContinue = FALSE; + byCharIn = 0; + goto carry; + } + + /*----------------------------- + | treat the last byte if we + | had a carry overflow + +-----------------------------*/ + if (bContinue2 && ((8 - *pdwInitialShift) + dwShiftNb) > 7) + { + bContinue2 = FALSE; + byCharIn = 0; + goto carry; + } + + /*----------------------------- + | Calculate the new shift + +-----------------------------*/ + *pdwInitialShift = ((8 - *pdwInitialShift) + dwShiftNb)%8; + + /*----------------------------- + | Add a flag at the end of the + | carry and a full flag + +-----------------------------*/ + pbyBuffOut--; + *pbyBuffOut++ |= 0x7E << *pdwInitialShift; + byCarry = 0x7E7E >> (8 - *pdwInitialShift); + *pbyBuffOut++ = byCarry; + *pbyBuffOut++ = byCarry; + dwNb += 2; + } + } + + /*------------------------------- + | Pad the array to a multiple + | of 64 bytes. + +-------------------------------*/ + for(;dwNb%64;dwNb++) + *pbyBuffOut ++ = byCarry; + + *pdwInitialShift = (8 - *pdwInitialShift)%8; + + return dwNb; +} + + + +/*- AuverTech Telecom -------------------------------------------------------+ + | | + | @Function : hdlc_decode | + | @Author : Cyrille Boudon | + | | + +---------------------------------------------------------------------------+ + | | + | @Param : BYTE * pbyBuffIn IN, array of bytes to decode | + | @Param : BYTE * pbyBuffOut OUT, array of decoded bytes | + | @Param : DWORD dwLength IN, count of bytes to decode | + | | + | @Return : DWORD count of decoded bytes | + | | + +------------------------------- @Abstract ---------------------------------+ + | | + | Bit de-stuffing of the array pbyBuffIn. There has to be at least 1 full | + | flag at the beginning. At the end there has to be a flag or an abort (more| + | than 6 consecutive '1'). | + | If an abort is encountered, the returned count is '0'. | + | | + +---------------------------------------------------------------------------*/ +DWORD hdlc_decode(BYTE * pbyBuffIn, BYTE * pbyBuffOut, DWORD dwLength) +{ + BYTE byCharIn; // byte being decoded + BYTE byCarry; // current carry + WORD woInfo; // data read in the arrays + WORD woNb1; // count of '1' at the end of the previous byte + BYTE byShift; // shift of the first flag + DWORD dwInit; // temporary variable + DWORD dwLengthOut; // count of the decoded bytes + BYTE byLgCarry; // count of used bits in the carry + BYTE byLgByte; // count of used bits in the decoded byte + + /*----------------------------- + | Find the 1st flag. At the end + | of the loop dwShift is the count + | of bits to reach the 1st bit + | of the 1st flag. + +-----------------------------*/ + dwInit = *pbyBuffIn | (*(pbyBuffIn+1)<<8) | (*(pbyBuffIn+2)<<16); + for (byShift=0;byShift<17;byShift++) + { + if (!(((dwInit>>byShift)&0xFF)^0x7E)) + { + break; + } + } + + /*----------------------------- + | If at the end of the previous + | loop dwShift = 17, it means + | that no flag was found in the + | first 3 bytes (normally + | impossible impossible with the + | DSP algorithm) + +-----------------------------*/ + if (byShift == 17) + return 0; + + /*----------------------------- + | Plase the array pointer after + | the first flag. Update the + | shift. + +-----------------------------*/ + pbyBuffIn += byShift/8 + 1; + dwLength -= byShift/8 + 1; + byShift %= 8; + + /*----------------------------- + | Walk through the frame to + | find the first data byte + +-----------------------------*/ + dwInit = *pbyBuffIn | (*(pbyBuffIn+1)<<8); + while (!(((dwInit>>byShift)&0xFF)^0x7E)) + { + pbyBuffIn ++; + dwLength --; + dwInit = *pbyBuffIn | (*(pbyBuffIn+1)<<8); + } + + dwLengthOut = 0; + byCarry = 0; + byLgCarry = 0; + byLgByte = 0; + + /*------------------------------- + | Treat the first byte + +-------------------------------*/ + byCharIn = (*pbyBuffIn >> byShift) << byShift; + woInfo = destuffs[0][byCharIn]; + byLgByte = ((woInfo & 0x7000) >> 12) + 1; + woNb1 = (woInfo & 0x0F00) >> 8; + dwLength --; + pbyBuffIn++; + + if (woNb1 > 5) + return 0; + + if (byLgByte - byShift == 8) + { + *pbyBuffOut ++ = woInfo; + dwLengthOut ++; + } + else + { + byCarry = woInfo << (8 - byLgByte); + byLgCarry = byLgByte - byShift; + } + + /*------------------------------- + | main loop + +-------------------------------*/ + while(dwLength --) + { + byCharIn = *pbyBuffIn ++; + + woInfo = destuffs[woNb1][byCharIn]; + byLgByte = ((woInfo & 0x7000) >> 12) + 1; + + /*------------------------------- + | if the used bits in the carry + | and the current byte makes + | possible to output a full byte + +-------------------------------*/ + if (byLgByte + byLgCarry >= 8) + { + *pbyBuffOut ++ = ( (woInfo << 8) | byCarry) >> (8 - byLgCarry); + dwLengthOut ++; + byLgCarry += byLgByte - 8; + byCarry = woInfo << (8-byLgByte); + } + /*------------------------------- + | if the used bits in the carry + | and the current byte doesn't + | make possible to output a full + | byte + +-------------------------------*/ + else + { + dwInit = (woInfo << 8) | byCarry; + byLgCarry += byLgByte; + byCarry = dwInit >> byLgByte; + } + + woNb1 = (woInfo & 0x0F00) >> 8; + + /*------------------------------- + | if the current byte contains + | six or more consecutive '1' + +-------------------------------*/ + if (woInfo & 0x8000) + { + byCarry = ((byCharIn << 8) | *(pbyBuffIn-2)) >> (8 - byLgCarry); + if (byCarry == 0x7E) + return dwLengthOut-1; + else + if (woNb1 > 6) + return 0; + else + if ((!(*pbyBuffIn & 1)) && (byLgCarry == 7)) + return dwLengthOut; + else + return 0; + } + } + + return dwLengthOut; +} + diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/tpam/tpam_main.c linux/drivers/isdn/tpam/tpam_main.c --- v2.4.5/linux/drivers/isdn/tpam/tpam_main.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/isdn/tpam/tpam_main.c Mon Jul 2 14:07:55 2001 @@ -0,0 +1,289 @@ +/* $Id: tpam_main.c,v 1.1.2.1 2001/06/05 19:45:37 kai Exp $ + * + * Turbo PAM ISDN driver for Linux. (Kernel Driver - main routines) + * + * Copyright 2001 Stelian Pop , Alcôve + * + * For all support questions please contact: + * + * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tpam.h" + +/* Local functions prototypes */ +static int __devinit tpam_probe(struct pci_dev *, const struct pci_device_id *); +static void __devexit tpam_unregister_card(tpam_card *); +static void __devexit tpam_remove(struct pci_dev *); +static int __init tpam_init(void); +static void __exit tpam_exit(void); + +/* List of boards */ +static tpam_card *cards; /* = NULL; */ +/* Number of cards */ +static int cards_num; +/* Configurable id of the driver */ +static char *id = "tpam\0\0\0\0\0\0\0\0\0\0\0\0"; + +MODULE_DESCRIPTION("Driver for TurboPAM cards"); +MODULE_AUTHOR("Stelian Pop, Alcove"); +MODULE_SUPPORTED_DEVICE("ISDN subsystem"); +MODULE_PARM_DESC(id,"ID-String of the driver"); +MODULE_PARM(id,"s"); + +/* + * Finds a board by its driver ID. + * + * driverId: driver ID (as referenced by the IDSN link layer) + * + * Return: the tpam_card structure if found, NULL on error. + */ +tpam_card *tpam_findcard(int driverid) { + tpam_card *p = cards; + + while (p) { + if (p->id == driverid) + return p; + p = p->next; + } + return NULL; +} + +/* + * Finds a channel number by its ncoid. + * + * card: the board + * ncoid: the NCO id + * + * Return: the channel number if found, TPAM_CHANNEL_INVALID if not. + */ +u32 tpam_findchannel(tpam_card *card, u32 ncoid) { + int i; + + for (i = 0; i < TPAM_NBCHANNEL; ++i) + if (card->channels[i].ncoid == ncoid) + return card->channels[i].num; + return TPAM_CHANNEL_INVALID; +} + +/* + * Initializes and registers a new TurboPAM card. + * + * dev: the PCI device + * num: the board number + * + * Return: 0 if OK, <0 if error + */ +static int __devinit tpam_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) { + tpam_card *card, *c; + int i; + + /* allocate memory for the board structure */ + if (!(card = (tpam_card *)kmalloc(sizeof(tpam_card), GFP_KERNEL))) { + printk(KERN_ERR "TurboPAM: tpam_register_card: " + "kmalloc failed!\n"); + return -ENOMEM; + } + + memset((char *)card, 0, sizeof(tpam_card)); + + card->irq = dev->irq; + card->lock = SPIN_LOCK_UNLOCKED; + sprintf(card->interface.id, "%s%d", id, cards_num); + + /* request interrupt */ + if (request_irq(card->irq, &tpam_irq, SA_INTERRUPT | SA_SHIRQ, + card->interface.id, card)) { + printk(KERN_ERR "TurboPAM: tpam_register_card: " + "could not request irq %d\n", card->irq); + kfree(card); + return -EIO; + } + + /* remap board memory */ + if (!(card->bar0 = (unsigned long) ioremap(pci_resource_start(dev, 0), + 0x800000))) { + printk(KERN_ERR "TurboPAM: tpam_register_card: " + "unable to remap bar0\n"); + free_irq(card->irq, card); + kfree(card); + return -EIO; + } + + /* reset the board */ + readl(card->bar0 + TPAM_RESETPAM_REGISTER); + + /* initialisation magic :-( */ + copy_to_pam_dword(card, (void *)0x01800008, 0x00000030); + copy_to_pam_dword(card, (void *)0x01800010, 0x00000030); + copy_to_pam_dword(card, (void *)0x01800014, 0x42240822); + copy_to_pam_dword(card, (void *)0x01800018, 0x07114000); + copy_to_pam_dword(card, (void *)0x0180001c, 0x00000400); + copy_to_pam_dword(card, (void *)0x01840070, 0x00000010); + + /* fill the ISDN link layer structure */ + card->interface.channels = TPAM_NBCHANNEL; + card->interface.maxbufsize = TPAM_MAXBUFSIZE; + card->interface.features = + ISDN_FEATURE_P_EURO | + ISDN_FEATURE_L2_HDLC | + ISDN_FEATURE_L2_MODEM; + card->interface.hl_hdrlen = 0; + card->interface.command = tpam_command; + card->interface.writebuf_skb = tpam_writebuf_skb; + card->interface.writecmd = NULL; + card->interface.readstat = NULL; + + /* register wrt the ISDN link layer */ + if (!register_isdn(&card->interface)) { + printk(KERN_ERR "TurboPAM: tpam_register_card: " + "unable to register %s\n", card->interface.id); + free_irq(card->irq, card); + iounmap((void *)card->bar0); + kfree(card); + return -EIO; + } + card->id = card->interface.channels; + + /* initialize all channels */ + for (i = 0; i < TPAM_NBCHANNEL; ++i) { + card->channels[i].num = i; + card->channels[i].card = card; + card->channels[i].ncoid = TPAM_NCOID_INVALID; + card->channels[i].hdlc = 0; + card->channels[i].realhdlc = 0; + card->channels[i].hdlcshift = 0; + skb_queue_head_init(&card->channels[i].sendq); + } + + /* initialize the rest of board structure */ + card->channels_used = 0; + card->channels_tested = 0; + card->running = 0; + card->busy = 0; + card->roundrobin = 0; + card->loopmode = 0; + skb_queue_head_init(&card->sendq); + skb_queue_head_init(&card->recvq); + card->recv_tq.routine = (void *) (void *) tpam_recv_tq; + card->recv_tq.data = card; + card->send_tq.routine = (void *) (void *) tpam_send_tq; + card->send_tq.data = card; + + /* add the board at the end of the list of boards */ + card->next = NULL; + if (cards) { + c = cards; + while (c->next) + c = c->next; + c->next = card; + } + else + cards = card; + + ++cards_num; + pci_set_drvdata(dev, card); + + return 0; +} + +/* + * Unregisters a TurboPAM board by releasing all its ressources (irq, mem etc). + * + * card: the board. + */ +static void __devexit tpam_unregister_card(tpam_card *card) { + isdn_ctrl cmd; + + /* prevent the ISDN link layer that the driver will be unloaded */ + cmd.command = ISDN_STAT_UNLOAD; + cmd.driver = card->id; + (* card->interface.statcallb)(&cmd); + + /* release interrupt */ + free_irq(card->irq, card); + + /* release mapped memory */ + iounmap((void *)card->bar0); +} + +/* + * Stops the driver. + */ +static void __devexit tpam_remove(struct pci_dev *pcidev) { + tpam_card *card = pci_get_drvdata(pcidev); + tpam_card *c; + + /* remove from the list of cards */ + if (card == cards) + cards = cards->next; + else { + c = cards; + while (c->next != card) + c = c->next; + c->next = c->next->next; + } + + /* unregister each board */ + tpam_unregister_card(card); + + /* and free the board structure itself */ + kfree(card); +} + +static struct pci_device_id tpam_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_TURBOPAM, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { } +}; + +MODULE_DEVICE_TABLE(pci, tpam_pci_tbl); + +static struct pci_driver tpam_driver = { + name: "tpam", + id_table: tpam_pci_tbl, + probe: tpam_probe, + remove: tpam_remove, +}; + +static int __init tpam_init(void) { + int ret; + + ret = pci_module_init(&tpam_driver); + if (ret) + return ret; + printk(KERN_INFO "TurboPAM: %d card%s found, driver loaded.\n", + cards_num, (cards_num > 1) ? "s" : ""); + return 0; +} + +static void __exit tpam_exit(void) { + pci_unregister_driver(&tpam_driver); + printk(KERN_INFO "TurboPAM: driver unloaded\n"); +} + +/* Module entry points */ +module_init(tpam_init); +module_exit(tpam_exit); + diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/tpam/tpam_memory.c linux/drivers/isdn/tpam/tpam_memory.c --- v2.4.5/linux/drivers/isdn/tpam/tpam_memory.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/isdn/tpam/tpam_memory.c Mon Jul 2 14:07:55 2001 @@ -0,0 +1,258 @@ +/* $Id: tpam_memory.c,v 1.1.2.1 2001/06/05 19:45:37 kai Exp $ + * + * Turbo PAM ISDN driver for Linux. (Kernel Driver - Board Memory Access) + * + * Copyright 2001 Stelian Pop , Alcôve + * + * For all support questions please contact: + * + * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include +#include +#include + +#include "tpam.h" + +/* + * Write a DWORD into the board memory. + * + * card: the board + * addr: the address (in the board memory) + * val: the value to put into the memory. + */ +void copy_to_pam_dword(tpam_card *card, const void *addr, u32 val) { + + /* set the page register */ + writel(((unsigned long)addr) | TPAM_PAGE_SIZE, + card->bar0 + TPAM_PAGE_REGISTER); + + /* write the value */ + writel(val, card->bar0 + (((u32)addr) & TPAM_PAGE_SIZE)); +} + +/* + * Write n bytes into the board memory. The count of bytes will be rounded + * up to a multiple of 4. + * + * card: the board + * to: the destination address (in the board memory) + * from: the source address (in the kernel memory) + * n: number of bytes + */ +void copy_to_pam(tpam_card *card, void *to, const void *from, u32 n) { + u32 page, offset, count; + + /* need to write in dword ! */ + while (n & 3) n++; + + while (n) { + page = ((u32)to) | TPAM_PAGE_SIZE; + offset = ((u32)to) & TPAM_PAGE_SIZE; + count = n < TPAM_PAGE_SIZE - offset + ? n + : TPAM_PAGE_SIZE - offset; + + /* set the page register */ + writel(page, card->bar0 + TPAM_PAGE_REGISTER); + + /* copy the data */ + memcpy_toio((void *)(card->bar0 + offset), from, count); + + from += count; + to += count; + n -= count; + } +} + +/* + * Read a DWORD from the board memory. + * + * card: the board + * addr: the address (in the board memory) + * + * Return: the value read into the memory. + */ +u32 copy_from_pam_dword(tpam_card *card, const void *addr) { + + /* set the page register */ + writel(((u32)addr) | TPAM_PAGE_SIZE, + card->bar0 + TPAM_PAGE_REGISTER); + + /* read the data */ + return readl(card->bar0 + (((u32)addr) & TPAM_PAGE_SIZE)); +} + +/* + * Read n bytes from the board memory. + * + * card: the board + * to: the destination address (in the kernel memory) + * from: the source address (in the board memory) + * n: number of bytes + */ +void copy_from_pam(tpam_card *card, void *to, const void *from, u32 n) { + u32 page, offset, count; + + while (n) { + page = ((u32)from) | TPAM_PAGE_SIZE; + offset = ((u32)from) & TPAM_PAGE_SIZE; + count = n < TPAM_PAGE_SIZE - offset + ? n + : TPAM_PAGE_SIZE - offset; + + /* set the page register */ + writel(page, card->bar0 + TPAM_PAGE_REGISTER); + + /* read the data */ + memcpy_fromio(to, (void *)(card->bar0 + offset), count); + + from += count; + to += count; + n -= count; + } +} + +/* + * Read n bytes from the board memory and writes them into the user memory. + * + * card: the board + * to: the destination address (in the userspace memory) + * from: the source address (in the board memory) + * n: number of bytes + * + * Return: 0 if OK, <0 if error. + */ +int copy_from_pam_to_user(tpam_card *card, void *to, const void *from, u32 n) { + void *page; + u32 count; + + /* allocate a free page for the data transfer */ + if (!(page = (void *)__get_free_page(GFP_KERNEL))) { + printk(KERN_ERR "TurboPAM(copy_from_pam_to_user): " + "get_free_page failed\n"); + return -ENOMEM; + } + + while (n) { + count = n < PAGE_SIZE ? n : PAGE_SIZE; + + /* copy data from the board into the kernel memory */ + spin_lock_irq(&card->lock); + copy_from_pam(card, page, from, count); + spin_unlock_irq(&card->lock); + + /* copy it from the kernel memory into the user memory */ + if (copy_to_user(to, page, count)) { + + /* this can fail... */ + free_page((u32)page); + return -EFAULT; + } + from += count; + to += count; + n -= count; + } + + /* release allocated memory */ + free_page((u32)page); + return 0; +} + +/* + * Read n bytes from the user memory and writes them into the board memory. + * + * card: the board + * to: the destination address (in the board memory) + * from: the source address (in the userspace memory) + * n: number of bytes + * + * Return: 0 if OK, <0 if error. + */ +int copy_from_user_to_pam(tpam_card *card, void *to, const void *from, u32 n) { + void *page; + u32 count; + + /* allocate a free page for the data transfer */ + if (!(page = (void *)__get_free_page(GFP_KERNEL))) { + printk(KERN_ERR "TurboPAM(copy_from_user_to_pam): " + "get_free_page failed\n"); + return -ENOMEM; + } + + while (n) { + count = n < PAGE_SIZE ? n : PAGE_SIZE; + + /* copy data from the user memory into the kernel memory */ + if (copy_from_user(page, from, count)) { + /* this can fail... */ + free_page((u32)page); + return -EFAULT; + } + + /* copy it from the kernel memory into the board memory */ + spin_lock_irq(&card->lock); + copy_to_pam(card, to, page, count); + spin_unlock_irq(&card->lock); + + from += count; + to += count; + n -= count; + } + + /* release allocated memory */ + free_page((u32)page); + return 0; +} + +/* + * Verify if we have the permission to read or writes len bytes at the + * address address from/to the board memory. + * + * address: the start address (in the board memory) + * len: number of bytes + * + * Return: 0 if OK, <0 if error. + */ +int tpam_verify_area(u32 address, u32 len) { + + if (address < TPAM_RESERVEDAREA1_START) + return (address + len <= TPAM_RESERVEDAREA1_START) ? 0 : -1; + + if (address <= TPAM_RESERVEDAREA1_END) + return -1; + + if (address < TPAM_RESERVEDAREA2_START) + return (address + len <= TPAM_RESERVEDAREA2_START) ? 0 : -1; + + if (address <= TPAM_RESERVEDAREA2_END) + return -1; + + if (address < TPAM_RESERVEDAREA3_START) + return (address + len <= TPAM_RESERVEDAREA3_START) ? 0 : -1; + + if (address <= TPAM_RESERVEDAREA3_END) + return -1; + + if (address < TPAM_RESERVEDAREA4_START) + return (address + len <= TPAM_RESERVEDAREA4_START) ? 0 : -1; + + if (address <= TPAM_RESERVEDAREA4_END) + return -1; + + return 0; +} + diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/tpam/tpam_nco.c linux/drivers/isdn/tpam/tpam_nco.c --- v2.4.5/linux/drivers/isdn/tpam/tpam_nco.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/isdn/tpam/tpam_nco.c Mon Jul 2 14:07:55 2001 @@ -0,0 +1,662 @@ +/* $Id: tpam_nco.c,v 1.1.2.1 2001/06/05 19:45:37 kai Exp $ + * + * Turbo PAM ISDN driver for Linux. (Kernel Driver - Low Level NCO Manipulation) + * + * Copyright 2001 Stelian Pop , Alcôve + * + * For all support questions please contact: + * + * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include +#include +#include +#include +#include +#include + +#include "tpam.h" + +/* Local function prototypes */ +static struct sk_buff *build_NCOpacket(u16, u16, u16, u16, u16); +static int extract_NCOParameter(struct sk_buff *, u8, void *, u16); + +/* + * Build a NCO packet (PCI message). + * + * messageID: the message type (ID_*) + * size: size of the TLV block + * data_size: size of the data block + * ack: packet needs to send ack upon send + * ack_size: size of data to be acknowledged upon send + * + * Return: the sk_buff filled with the NCO packet, or NULL if error. + */ +static struct sk_buff *build_NCOpacket(u16 messageID, u16 size, + u16 data_size, u16 ack, + u16 ack_size) { + struct sk_buff *skb; + skb_header *h; + pci_mpb *p; + u16 finalsize; + + /* reserve enough space for the sk_buff header, the pci * header, + * size bytes for the TLV block, size bytes for the data and 4 more + * bytes in order to make sure we can write dwords to the board. */ + finalsize = sizeof(skb_header) + sizeof(pci_mpb) + size + data_size + 4; + + /* allocate the sk_buff */ + if (!(skb = alloc_skb(finalsize, GFP_ATOMIC))) { + printk(KERN_ERR "TurboPAM(make_NCOpacket): alloc_skb failed\n"); + return NULL; + } + + /* construct the skb_header */ + h = (skb_header *)skb_put(skb, sizeof(skb_header)); + h->size = sizeof(pci_mpb) + size; + h->data_size = data_size; + h->ack = ack; + h->ack_size = ack_size; + + /* construct the pci_mpb */ + p = (pci_mpb *)skb_put(skb, sizeof(pci_mpb)); + p->exID = 0; + p->flags = 0; + p->errorCode = 0; + p->messageID = messageID; + p->maximumBlockTLVSize = MPB_MAXIMUMBLOCKTLVSIZE; + p->actualBlockTLVSize = size; + p->maximumDataSize = MPB_MAXIMUMDATASIZE; + p->actualDataSize = data_size; + return skb; +} + +/* + * Build a ACreateNCOReq message. + * + * phone: the local phone number. + * + * Return: the sk_buff filled with the NCO packet, or NULL if error. + */ +struct sk_buff *build_ACreateNCOReq(const u8 *phone) { + struct sk_buff *skb; + u8 *tlv; + + dprintk("TurboPAM(build_ACreateNCOReq): phone=%s\n", phone); + + /* build the NCO packet */ + if (!(skb = build_NCOpacket(ID_ACreateNCOReq, 23 + strlen(phone), 0, 0, 0))) + return NULL; + + /* add the parameters */ + tlv = (u8 *)skb_put(skb, 3); + *tlv = PAR_NCOType; + *(tlv+1) = 1; + *(tlv+2) = 5; /* mistery value... */ + + tlv = (u8 *)skb_put(skb, 4); + *tlv = PAR_U3Protocol; + *(tlv+1) = 2; + *(tlv+2) = 4; /* no level 3 protocol */ + *(tlv+3) = 1; /* HDLC in level 2 */ + + tlv = (u8 *)skb_put(skb, 3); + *tlv = PAR_Cdirection; + *(tlv+1) = 1; + *(tlv+2) = 3; /* PCI_DIRECTION_BOTH */ + + tlv = (u8 *)skb_put(skb, 3); + *tlv = PAR_Udirection; + *(tlv+1) = 1; + *(tlv+2) = 3; /* PCI_DIRECTION_BOTH */ + + tlv = (u8 *)skb_put(skb, 4); + *tlv = PAR_BearerCap; + *(tlv+1) = 2; + *(tlv+2) = 0x88; + *(tlv+3) = 0x90; + + tlv = (u8 *)skb_put(skb, 6 + strlen(phone)); + *tlv = PAR_CallingNumber; + *(tlv+1) = strlen(phone) + 4; + *(tlv+2) = 0x01; /* international */ + *(tlv+3) = 0x01; /* isdn */ + *(tlv+4) = 0x00; + *(tlv+5) = 0x00; + memcpy(tlv + 6, phone, strlen(phone)); + + return skb; +} + +/* + * Build a ADestroyNCOReq message. + * + * ncoid: the NCO id. + * + * Return: the sk_buff filled with the NCO packet, or NULL if error. + */ +struct sk_buff *build_ADestroyNCOReq(u32 ncoid) { + struct sk_buff *skb; + u8 *tlv; + + dprintk("TurboPAM(build_ADestroyNCOReq): ncoid=%lu\n", + (unsigned long)ncoid); + + /* build the NCO packet */ + if (!(skb = build_NCOpacket(ID_ADestroyNCOReq, 6, 0, 0, 0))) + return NULL; + + /* add the parameters */ + tlv = (u8 *)skb_put(skb, 6); + *tlv = PAR_NCOID; + *(tlv+1) = 4; + *((u32 *)(tlv+2)) = ncoid; + + return skb; +} + +/* + * Build a CConnectReq message. + * + * ncoid: the NCO id. + * called: the destination phone number + * hdlc: type of connection: 1 (HDLC) or 0(modem) + * + * Return: the sk_buff filled with the NCO packet, or NULL if error. + */ +struct sk_buff *build_CConnectReq(u32 ncoid, const u8 *called, u8 hdlc) { + struct sk_buff *skb; + u8 *tlv; + + dprintk("TurboPAM(build_CConnectReq): ncoid=%lu, called=%s, hdlc=%d\n", + (unsigned long)ncoid, called, hdlc); + + /* build the NCO packet */ + if (!(skb = build_NCOpacket(ID_CConnectReq, 20 + strlen(called), 0, 0, 0))) + return NULL; + + /* add the parameters */ + tlv = (u8 *)skb_put(skb, 6); + *tlv = PAR_NCOID; + *(tlv+1) = 4; + *((u32 *)(tlv+2)) = ncoid; + + tlv = (u8 *)skb_put(skb, 4 + strlen(called)); + *tlv = PAR_CalledNumber; + *(tlv+1) = strlen(called) + 2; + *(tlv+2) = 0x01; /* international */ + *(tlv+3) = 0x01; /* isdn */ + memcpy(tlv + 4, called, strlen(called)); + + tlv = (u8 *)skb_put(skb, 3); + *tlv = PAR_BearerCap; + *(tlv+1) = 1; + *(tlv+2) = hdlc ? 0x88 /* HDLC */ : 0x80 /* MODEM */; + + tlv = (u8 *)skb_put(skb, 4); + *tlv = PAR_HLC; + *(tlv+1) = 2; + *(tlv+2) = 0x2; + *(tlv+3) = 0x7f; + + tlv = (u8 *)skb_put(skb, 3); + *tlv = PAR_Facility; + *(tlv+1) = 1; + *(tlv+2) = 2; + + return skb; +} + +/* + * Build a CConnectRsp message. + * + * ncoid: the NCO id. + * + * Return: the sk_buff filled with the NCO packet, or NULL if error. + */ +struct sk_buff *build_CConnectRsp(u32 ncoid) { + struct sk_buff *skb; + u8 *tlv; + + dprintk("TurboPAM(build_CConnectRsp): ncoid=%lu\n", + (unsigned long)ncoid); + + /* build the NCO packet */ + if (!(skb = build_NCOpacket(ID_CConnectRsp, 6, 0, 0, 0))) + return NULL; + + /* add the parameters */ + tlv = (u8 *)skb_put(skb, 6); + *tlv = PAR_NCOID; + *(tlv+1) = 4; + *((u32 *)(tlv+2)) = ncoid; + + return skb; +} + +/* + * Build a CDisconnectReq message. + * + * ncoid: the NCO id. + * + * Return: the sk_buff filled with the NCO packet, or NULL if error. + */ +struct sk_buff *build_CDisconnectReq(u32 ncoid) { + struct sk_buff *skb; + u8 *tlv; + + dprintk("TurboPAM(build_CDisconnectReq): ncoid=%lu\n", + (unsigned long)ncoid); + + /* build the NCO packet */ + if (!(skb = build_NCOpacket(ID_CDisconnectReq, 6, 0, 0, 0))) + return NULL; + + /* add the parameters */ + tlv = (u8 *)skb_put(skb, 6); + *tlv = PAR_NCOID; + *(tlv+1) = 4; + *((u32 *)(tlv+2)) = ncoid; + + return skb; +} + +/* + * Build a CDisconnectRsp message. + * + * ncoid: the NCO id. + * + * Return: the sk_buff filled with the NCO packet, or NULL if error. + */ +struct sk_buff *build_CDisconnectRsp(u32 ncoid) { + struct sk_buff *skb; + u8 *tlv; + + dprintk("TurboPAM(build_CDisconnectRsp): ncoid=%lu\n", + (unsigned long)ncoid); + + /* build the NCO packet */ + if (!(skb = build_NCOpacket(ID_CDisconnectRsp, 6, 0, 0, 0))) + return NULL; + + /* add the parameters */ + tlv = (u8 *)skb_put(skb, 6); + *tlv = PAR_NCOID; + *(tlv+1) = 4; + *((u32 *)(tlv+2)) = ncoid; + + return skb; +} + +/* + * Build a U3DataReq message. + * + * ncoid: the NCO id. + * data: the data to be send + * len: length of the data + * ack: send ack upon send + * ack_size: size of data to be acknowledged upon send + * + * Return: the sk_buff filled with the NCO packet, or NULL if error. + */ +struct sk_buff *build_U3DataReq(u32 ncoid, void *data, u16 len, + u16 ack, u16 ack_size) { + struct sk_buff *skb; + u8 *tlv; + void *p; + + dprintk("TurboPAM(build_U3DataReq): " + "ncoid=%lu, len=%d, ack=%d, ack_size=%d\n", + (unsigned long)ncoid, len, ack, ack_size); + + /* build the NCO packet */ + if (!(skb = build_NCOpacket(ID_U3DataReq, 6, len, ack, ack_size))) + return NULL; + + /* add the parameters */ + tlv = (u8 *)skb_put(skb, 6); + *tlv = PAR_NCOID; + *(tlv+1) = 4; + *((u32 *)(tlv+2)) = ncoid; + + p = skb_put(skb, len); + memcpy(p, data, len); + + return skb; +} + +/* + * Extract a parameter from a TLV block. + * + * skb: sk_buff containing the PCI message + * type: parameter to search for (PARAM_*) + * value: to be filled with the value of the parameter + * len: maximum length of the parameter value + * + * Return: 0 if OK, <0 if error. + */ +static int extract_NCOParameter(struct sk_buff *skb, u8 type, + void *value, u16 len) { + void *buffer = (void *)skb->data; + pci_mpb *p; + void * bufferend; + u8 valtype; + u16 vallen; + + /* calculate the start and end of the TLV block */ + buffer += sizeof(skb_header); + p = (pci_mpb *)buffer; + buffer += sizeof(pci_mpb); + bufferend = buffer + p->actualBlockTLVSize; + + /* walk through the parameters */ + while (buffer < bufferend) { + + /* parameter type */ + valtype = *((u8 *)buffer++); + /* parameter length */ + vallen = *((u8 *)buffer++); + if (vallen == 0xff) { + /* parameter length is on 2 bytes */ + vallen = *((u8 *)buffer++); + vallen <<= 8; + vallen |= *((u8 *)buffer++); + } + /* got the right parameter */ + if (valtype == type) { + /* not enough space for returning the value */ + if (vallen > len) + return -1; + /* OK, return it */ + memcpy(value, buffer, vallen); + return 0; + } + buffer += vallen; + } + return -1; +} + +/* + * Parse a ACreateNCOCnf message. + * + * skb: the sk_buff containing the message + * status: to be filled with the status field value + * ncoid: to be filled with the ncoid field value + * + * Return: 0 if OK, <0 if error. + */ +int parse_ACreateNCOCnf(struct sk_buff *skb, u8 *status, u32 *ncoid) { + + /* extract the status */ + if (extract_NCOParameter(skb, PAR_CompletionStatus, status, 1)) { + printk(KERN_ERR "TurboPAM(parse_ACreateNCOCnf): " + "CompletionStatus not found\n"); + return -1; + } + + if (*status) { + dprintk("TurboPAM(parse_ACreateNCOCnf): status=%d\n", *status); + return 0; + } + + /* extract the ncoid */ + if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4)) { + printk(KERN_ERR "TurboPAM(parse_ACreateNCOCnf): " + "NCOID not found\n"); + return -1; + } + + dprintk("TurboPAM(parse_ACreateNCOCnf): ncoid=%lu, status=%d\n", + (unsigned long)*ncoid, *status); + return 0; +} + +/* + * Parse a ADestroyNCOCnf message. Not used in the driver. + * + * skb: the sk_buff containing the message + * status: to be filled with the status field value + * ncoid: to be filled with the ncoid field value + * + * Return: 0 if OK, <0 if error. + */ +int parse_ADestroyNCOCnf(struct sk_buff *skb, u8 *status, u32 *ncoid) { + + /* extract the status */ + if (extract_NCOParameter(skb, PAR_CompletionStatus, status, 1)) { + printk(KERN_ERR "TurboPAM(parse_ADestroyNCOCnf): " + "CompletionStatus not found\n"); + return -1; + } + + if (*status) { + dprintk("TurboPAM(parse_ADestroyNCOCnf): status=%d\n", *status); + return 0; + } + + /* extract the ncoid */ + if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4)) { + printk(KERN_ERR "TurboPAM(parse_ADestroyNCOCnf): " + "NCOID not found\n"); + return -1; + } + + dprintk("TurboPAM(parse_ADestroyNCOCnf): ncoid=%lu, status=%d\n", + (unsigned long)*ncoid, *status); + return 0; +} + +/* + * Parse a CConnectCnf message. + * + * skb: the sk_buff containing the message + * ncoid: to be filled with the ncoid field value + * + * Return: 0 if OK, <0 if error. + */ +int parse_CConnectCnf(struct sk_buff *skb, u32 *ncoid) { + + /* extract the ncoid */ + if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4)) { + printk(KERN_ERR "TurboPAM(parse_CConnectCnf): " + "NCOID not found\n"); + return -1; + } + dprintk("TurboPAM(parse_CConnectCnf): ncoid=%lu\n", + (unsigned long)*ncoid); + return 0; +} + +/* + * Parse a CConnectInd message. + * + * skb: the sk_buff containing the message + * ncoid: to be filled with the ncoid field value + * hdlc: to be filled with 1 if the incoming connection is a HDLC one, + * with 0 if the incoming connection is a modem one + * calling: to be filled with the calling phone number value + * called: to be filled with the called phone number value + * plan: to be filled with the plan value + * screen: to be filled with the screen value + * + * Return: 0 if OK, <0 if error. + */ +int parse_CConnectInd(struct sk_buff *skb, u32 *ncoid, u8 *hdlc, + u8 *calling, u8 *called, u8 *plan, u8 *screen) { + u8 phone[PHONE_MAXIMUMSIZE + 4]; + + /* extract the ncoid */ + if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4)) { + printk(KERN_ERR "TurboPAM(parse_CConnectInd): " + "NCOID not found\n"); + return -1; + } + + /* extract the bearer capability field */ + if (extract_NCOParameter(skb, PAR_BearerCap, hdlc, 1)) { + printk(KERN_ERR "TurboPAM(parse_CConnectInd): " + "BearerCap not found\n"); + return -1; + } + *hdlc = (*hdlc == 0x88) ? 1 : 0; + + /* extract the calling number / plan / screen */ + if (extract_NCOParameter(skb, PAR_CallingNumber, phone, + PHONE_MAXIMUMSIZE + 4)) { + printk(KERN_ERR "TurboPAM(parse_CConnectInd): " + "CallingNumber not found\n"); + return -1; + } + memcpy(calling, phone + 4, PHONE_MAXIMUMSIZE); + *plan = phone[1]; + *screen = phone[3]; + + /* extract the called number */ + if (extract_NCOParameter(skb, PAR_CalledNumber, phone, + PHONE_MAXIMUMSIZE + 2)) { + printk(KERN_ERR "TurboPAM(parse_CConnectInd): " + "CalledNumber not found\n"); + return -1; + } + memcpy(called, phone + 2, PHONE_MAXIMUMSIZE); + + dprintk("TurboPAM(parse_CConnectInd): " + "ncoid=%lu, hdlc=%d, plan=%d, scr=%d, calling=%s, called=%s\n", + (unsigned long)*ncoid, *hdlc, *plan, *screen, calling, called); + return 0; +} + +/* + * Parse a CDisconnectCnf message. + * + * skb: the sk_buff containing the message + * ncoid: to be filled with the ncoid field value + * causetopuf: to be filled with the cause field value + * + * Return: 0 if OK, <0 if error. + */ +int parse_CDisconnectCnf(struct sk_buff *skb, u32 *ncoid, u32 *causetopuf) { + + /* extract the ncoid */ + if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4)) { + printk(KERN_ERR "TurboPAM(parse_CDisconnectCnf): " + "NCOID not found\n"); + return -1; + } + + /* extract the cause of disconnection */ + if (extract_NCOParameter(skb, PAR_CauseToPUF, causetopuf, 4)) { + printk(KERN_ERR "TurboPAM(parse_CDisconnectCnf): " + "CauseToPUF not found\n"); + return -1; + } + + dprintk("TurboPAM(parse_CDisconnectCnf): ncoid=%lu, causetopuf=%lu\n", + (unsigned long)*ncoid, (unsigned long)*causetopuf); + return 0; +} + +/* + * Parse a CDisconnectInd message. + * + * skb: the sk_buff containing the message + * ncoid: to be filled with the ncoid field value + * causetopuf: to be filled with the cause field value + * + * Return: 0 if OK, <0 if error. + */ +int parse_CDisconnectInd(struct sk_buff *skb, u32 *ncoid, u32 *causetopuf) { + + /* extract the ncoid */ + if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4)) { + printk(KERN_ERR "TurboPAM(parse_CDisconnectInd): " + "NCOID not found\n"); + return -1; + } + + /* extract the cause of disconnection */ + if (extract_NCOParameter(skb, PAR_CauseToPUF, causetopuf, 4)) { + printk(KERN_ERR "TurboPAM(parse_CDisconnectInd): " + "CauseToPUF not found\n"); + return -1; + } + + dprintk("TurboPAM(parse_CDisconnectInd): ncoid=%lu, causetopuf=%lu\n", + (unsigned long)*ncoid, (unsigned long)*causetopuf); + return 0; +} + +/* + * Parse a U3ReadyToReceiveInd message. + * + * skb: the sk_buff containing the message + * ncoid: to be filled with the ncoid field value + * ready: to be filled with the ready field value + * + * Return: 0 if OK, <0 if error. + */ +int parse_U3ReadyToReceiveInd(struct sk_buff *skb, u32 *ncoid, u8 *ready) { + + /* extract the ncoid */ + if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4)) { + printk(KERN_ERR "TurboPAM(parse_U3ReadyToReceiveInd): " + "NCOID not found\n"); + return -1; + } + + /* extract the ready flag */ + if (extract_NCOParameter(skb, PAR_ReadyFlag, ready, 1)) { + printk(KERN_ERR "TurboPAM(parse_U3ReadyToReceiveInd): " + "ReadyFlag not found\n"); + return -1; + } + + dprintk("TurboPAM(parse_U3ReadyToReceiveInd): ncoid=%lu, ready=%d\n", + (unsigned long)*ncoid, *ready); + return 0; +} + +/* + * Parse a U3DataInd message. + * + * skb: the sk_buff containing the message + data + * ncoid: to be filled with the ncoid field value + * data: to be filled with the data + * ready: to be filled with the data length + * + * Return: 0 if OK, <0 if error. + */ +int parse_U3DataInd(struct sk_buff *skb, u32 *ncoid, u8 **data, u16 *len) { + pci_mpb *p; + + /* extract the ncoid */ + if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4) == -1) { + printk(KERN_ERR "TurboPAM(parse_U3DataInd): NCOID not found\n"); + return -1; + } + + /* get a pointer to the beginning of the data block and its length */ + p = (pci_mpb *)(skb->data + sizeof(skb_header)); + *len = p->actualDataSize; + skb_pull(skb, + sizeof(skb_header) + sizeof(pci_mpb) + p->actualBlockTLVSize); + *data = skb->data; + + dprintk("TurboPAM(parse_U3DataInd): ncoid=%lu, datalen=%d\n", + (unsigned long)*ncoid, *len); + return 0; +} + diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/tpam/tpam_queues.c linux/drivers/isdn/tpam/tpam_queues.c --- v2.4.5/linux/drivers/isdn/tpam/tpam_queues.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/isdn/tpam/tpam_queues.c Mon Jul 2 14:07:55 2001 @@ -0,0 +1,418 @@ +/* $Id: tpam_queues.c,v 1.1.2.1 2001/06/05 19:45:37 kai Exp $ + * + * Turbo PAM ISDN driver for Linux. (Kernel Driver) + * + * Copyright 2001 Stelian Pop , Alcôve + * + * For all support questions please contact: + * + * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include +#include +#include +#include +#include +#include +#include + +#include "tpam.h" + +/* Local function prototype */ +static int tpam_sendpacket(tpam_card *card, tpam_channel *channel); + +/* + * Queue a message to be send to the card when possible. + * + * card: the board + * skb: the sk_buff containing the message. + */ +void tpam_enqueue(tpam_card *card, struct sk_buff *skb) { + + dprintk("TurboPAM(tpam_enqueue): card=%d\n", card->id); + + /* queue the sk_buff on the board's send queue */ + skb_queue_tail(&card->sendq, skb); + + /* queue the board's send task struct for immediate treatment */ + queue_task(&card->send_tq, &tq_immediate); + mark_bh(IMMEDIATE_BH); +} + +/* + * Queue a data message to be send to the card when possible. + * + * card: the board + * skb: the sk_buff containing the message and the data. This parameter + * can be NULL if we want just to trigger the send of queued + * messages. + */ +void tpam_enqueue_data(tpam_channel *channel, struct sk_buff *skb) { + + dprintk("TurboPAM(tpam_enqueue_data): card=%d, channel=%d\n", + channel->card->id, channel->num); + + /* if existant, queue the sk_buff on the channel's send queue */ + if (skb) + skb_queue_tail(&channel->sendq, skb); + + /* queue the channel's send task struct for immediate treatment */ + queue_task(&channel->card->send_tq, &tq_immediate); + mark_bh(IMMEDIATE_BH); +} + +/* + * IRQ handler. + * + * If a message comes from the board we read it, construct a sk_buff containing + * the message and we queue the sk_buff on the board's receive queue, and we + * trigger the execution of the board's receive task queue. + * + * If a message ack comes from the board we can go on and send a new message, + * so we trigger the execution of the board's send task queue. + * + * irq: the irq number + * dev_id: the registered board to the irq + * regs: not used. + */ +void tpam_irq(int irq, void *dev_id, struct pt_regs *regs) { + tpam_card *card = (tpam_card *)dev_id; + u32 ackupload, uploadptr; + u32 waiting_too_long; + u32 hpic; + struct sk_buff *skb; + pci_mpb mpb; + skb_header *skbh; + + dprintk("TurboPAM(tpam_irq): IRQ received, card=%d\n", card->id); + + /* grab the board lock */ + spin_lock(&card->lock); + + /* get the message type */ + ackupload = copy_from_pam_dword(card, (void *)TPAM_ACKUPLOAD_REGISTER); + + /* acknowledge the interrupt */ + copy_to_pam_dword(card, (void *)TPAM_INTERRUPTACK_REGISTER, 0); + readl(card->bar0 + TPAM_HINTACK_REGISTER); + + if (!ackupload) { + /* it is a new message from the board */ + + dprintk("TurboPAM(tpam_irq): message received, card=%d\n", + card->id); + + /* get the upload pointer */ + uploadptr = copy_from_pam_dword(card, + (void *)TPAM_UPLOADPTR_REGISTER); + + /* get the beginning of the message (pci_mpb part) */ + copy_from_pam(card, &mpb, (void *)uploadptr, sizeof(pci_mpb)); + + /* allocate the sk_buff */ + if (!(skb = alloc_skb(sizeof(skb_header) + sizeof(pci_mpb) + + mpb.actualBlockTLVSize + + mpb.actualDataSize, GFP_ATOMIC))) { + printk(KERN_ERR "TurboPAM(tpam_irq): " + "alloc_skb failed\n"); + spin_unlock(&card->lock); + return; + } + + /* build the skb_header */ + skbh = (skb_header *)skb_put(skb, sizeof(skb_header)); + skbh->size = sizeof(pci_mpb) + mpb.actualBlockTLVSize; + skbh->data_size = mpb.actualDataSize; + skbh->ack = 0; + skbh->ack_size = 0; + + /* copy the pci_mpb into the sk_buff */ + memcpy(skb_put(skb, sizeof(pci_mpb)), &mpb, sizeof(pci_mpb)); + + /* copy the TLV block into the sk_buff */ + copy_from_pam(card, skb_put(skb, mpb.actualBlockTLVSize), + (void *)uploadptr + sizeof(pci_mpb), + mpb.actualBlockTLVSize); + + /* if existent, copy the data block into the sk_buff */ + if (mpb.actualDataSize) + copy_from_pam(card, skb_put(skb, mpb.actualDataSize), + (void *)uploadptr + sizeof(pci_mpb) + 4096, + mpb.actualDataSize); + + /* wait for the board to become ready */ + waiting_too_long = 0; + do { + hpic = readl(card->bar0 + TPAM_HPIC_REGISTER); + if (waiting_too_long++ > 0xfffffff) { + spin_unlock(&card->lock); + printk(KERN_ERR "TurboPAM(tpam_irq): " + "waiting too long...\n"); + return; + } + } while (hpic & 0x00000002); + + /* acknowledge the message */ + copy_to_pam_dword(card, (void *)TPAM_ACKDOWNLOAD_REGISTER, + 0xffffffff); + readl(card->bar0 + TPAM_DSPINT_REGISTER); + + /* release the board lock */ + spin_unlock(&card->lock); + + if (mpb.messageID == ID_U3ReadyToReceiveInd) { + /* this message needs immediate treatment */ + tpam_recv_U3ReadyToReceiveInd(card, skb); + kfree_skb(skb); + } + else { + /* put the message in the receive queue */ + skb_queue_tail(&card->recvq, skb); + queue_task(&card->recv_tq, &tq_immediate); + mark_bh(IMMEDIATE_BH); + } + return; + } + else { + /* it is a ack from the board */ + + dprintk("TurboPAM(tpam_irq): message acknowledged, card=%d\n", + card->id); + + /* board is not busy anymore */ + card->busy = 0; + + /* release the lock */ + spin_unlock(&card->lock); + + /* schedule the send queue for execution */ + queue_task(&card->send_tq, &tq_immediate); + mark_bh(IMMEDIATE_BH); + return; + } + + /* not reached */ +} + +/* + * Run the board's receive task queue, dispatching each message on the queue, + * to its treatment function. + * + * card: the board. + */ +void tpam_recv_tq(tpam_card *card) { + pci_mpb *p; + struct sk_buff *skb; + + /* for each message on the receive queue... */ + while ((skb = skb_dequeue(&card->recvq))) { + + /* point to the pci_mpb block */ + p = (pci_mpb *)(skb->data + sizeof(skb_header)); + + /* dispatch the message */ + switch (p->messageID) { + case ID_ACreateNCOCnf: + tpam_recv_ACreateNCOCnf(card, skb); + break; + case ID_ADestroyNCOCnf: + tpam_recv_ADestroyNCOCnf(card, skb); + break; + case ID_CConnectCnf: + tpam_recv_CConnectCnf(card, skb); + break; + case ID_CConnectInd: + tpam_recv_CConnectInd(card, skb); + break; + case ID_CDisconnectInd: + tpam_recv_CDisconnectInd(card, skb); + break; + case ID_CDisconnectCnf: + tpam_recv_CDisconnectCnf(card, skb); + break; + case ID_U3DataInd: + tpam_recv_U3DataInd(card, skb); + break; + default: + dprintk("TurboPAM(tpam_recv_tq): " + "unknown messageID %d, card=%d\n", + p->messageID, card->id); + break; + } + /* free the sk_buff */ + kfree_skb(skb); + } +} + +/* + * Run the board's send task queue. If there is a message in the board's send + * queue, it gets sended. If not, it examines each channel (one at the time, + * using a round robin algorithm). For each channel, if there is a message + * in the channel's send queue, it gets sended. This function sends only one + * message, it does not consume all the queue. + */ +void tpam_send_tq(tpam_card *card) { + int i; + + /* first, try to send a packet from the board's send queue */ + if (tpam_sendpacket(card, NULL)) + return; + + /* then, try each channel, in a round-robin manner */ + for (i=card->roundrobin; iroundrobin+card->channels_used; i++) { + if (tpam_sendpacket(card, + &card->channels[i % card->channels_used])) { + card->roundrobin = (i + 1) % card->channels_used; + return; + } + } +} + +/* + * Try to send a packet from the board's send queue or from the channel's + * send queue. + * + * card: the board. + * channel: the channel (if NULL, the packet will be taken from the + * board's send queue. If not, it will be taken from the + * channel's send queue. + * + * Return: 0 if tpam_send_tq must try another card/channel combination + * (meaning that no packet has been send), 1 if no more packets + * can be send at that time (a packet has been send or the card is + * still busy from a previous send). + */ +static int tpam_sendpacket(tpam_card *card, tpam_channel *channel) { + struct sk_buff *skb; + u32 hpic; + u32 downloadptr; + skb_header *skbh; + u32 waiting_too_long; + + dprintk("TurboPAM(tpam_sendpacket), card=%d, channel=%d\n", + card->id, channel ? channel->num : -1); + + if (channel) { + /* dequeue a packet from the channel's send queue */ + if (!(skb = skb_dequeue(&channel->sendq))) { + dprintk("TurboPAM(tpam_sendpacket): " + "card=%d, channel=%d, no packet\n", + card->id, channel->num); + return 0; + } + + /* if the channel is not ready to receive, requeue the packet + * and return 0 to give a chance to another channel */ + if (!channel->readytoreceive) { + dprintk("TurboPAM(tpam_sendpacket): " + "card=%d, channel=%d, channel not ready\n", + card->id, channel->num); + skb_queue_head(&channel->sendq, skb); + return 0; + } + + /* grab the board lock */ + spin_lock_irq(&card->lock); + + /* if the board is busy, requeue the packet and return 1 since + * there is no need to try another channel */ + if (card->busy) { + dprintk("TurboPAM(tpam_sendpacket): " + "card=%d, channel=%d, card busy\n", + card->id, channel->num); + skb_queue_head(&channel->sendq, skb); + spin_unlock_irq(&card->lock); + return 1; + } + } + else { + /* dequeue a packet from the board's send queue */ + if (!(skb = skb_dequeue(&card->sendq))) { + dprintk("TurboPAM(tpam_sendpacket): " + "card=%d, no packet\n", card->id); + return 0; + } + + /* grab the board lock */ + spin_lock_irq(&card->lock); + + /* if the board is busy, requeue the packet and return 1 since + * there is no need to try another channel */ + if (card->busy) { + dprintk("TurboPAM(tpam_sendpacket): " + "card=%d, card busy\n", card->id); + skb_queue_head(&card->sendq, skb); + spin_unlock_irq(&card->lock); + return 1; + } + } + + /* wait for the board to become ready */ + waiting_too_long = 0; + do { + hpic = readl(card->bar0 + TPAM_HPIC_REGISTER); + if (waiting_too_long++ > 0xfffffff) { + spin_unlock_irq(&card->lock); + printk(KERN_ERR "TurboPAM(tpam_sendpacket): " + "waiting too long...\n"); + return 1; + } + } while (hpic & 0x00000002); + + skbh = (skb_header *)skb->data; + dprintk("TurboPAM(tpam_sendpacket): " + "card=%d, card ready, sending %d/%d bytes\n", + card->id, skbh->size, skbh->data_size); + + /* get the board's download pointer */ + downloadptr = copy_from_pam_dword(card, + (void *)TPAM_DOWNLOADPTR_REGISTER); + + /* copy the packet to the board at the downloadptr location */ + copy_to_pam(card, (void *)downloadptr, skb->data + sizeof(skb_header), + skbh->size); + if (skbh->data_size) + /* if there is some data in the packet, copy it too */ + copy_to_pam(card, (void *)downloadptr + sizeof(pci_mpb) + 4096, + skb->data + sizeof(skb_header) + skbh->size, + skbh->data_size); + + /* card will become busy right now */ + card->busy = 1; + + /* interrupt the board */ + copy_to_pam_dword(card, (void *)TPAM_ACKDOWNLOAD_REGISTER, 0); + readl(card->bar0 + TPAM_DSPINT_REGISTER); + + /* release the lock */ + spin_unlock_irq(&card->lock); + + /* if a data ack was requested by the ISDN link layer, send it now */ + if (skbh->ack) { + isdn_ctrl ctrl; + ctrl.driver = card->id; + ctrl.command = ISDN_STAT_BSENT; + ctrl.arg = channel->num; + ctrl.parm.length = skbh->ack_size; + (* card->interface.statcallb)(&ctrl); + } + + /* free the sk_buff */ + kfree_skb(skb); + + return 1; +} + diff -u --recursive --new-file v2.4.5/linux/drivers/macintosh/mac_hid.c linux/drivers/macintosh/mac_hid.c --- v2.4.5/linux/drivers/macintosh/mac_hid.c Sun Sep 17 09:48:05 2000 +++ linux/drivers/macintosh/mac_hid.c Wed Jun 27 13:37:35 2001 @@ -15,6 +15,7 @@ #include #include #include +#include #ifdef CONFIG_MAC_ADBKEYCODES #include @@ -401,6 +402,8 @@ return keyboard_sends_linux_keycodes; } +EXPORT_SYMBOL(mac_hid_keyboard_sends_linux_keycodes); + static int __init mac_hid_setup(char *str) { int ints[2]; @@ -448,6 +451,8 @@ return 0; } +EXPORT_SYMBOL(mac_hid_mouse_emulate_buttons); + static void emumousebtn_input_register(void) { emumousebtn.name = "Macintosh mouse button emulation"; @@ -473,9 +478,19 @@ #ifdef CONFIG_MAC_ADBKEYCODES memcpy(pc_key_maps_save, key_maps, sizeof(key_maps)); - if (!keyboard_sends_linux_keycodes) + if (!keyboard_sends_linux_keycodes) { +#ifdef CONFIG_MAGIC_SYSRQ + ppc_md.ppc_kbd_sysrq_xlate = mac_hid_kbd_sysrq_xlate; + SYSRQ_KEY = 0x69; +#endif memcpy(key_maps, mac_key_maps_save, sizeof(key_maps)); + } else { +#ifdef CONFIG_MAGIC_SYSRQ + ppc_md.ppc_kbd_sysrq_xlate = pckbd_sysrq_xlate; + SYSRQ_KEY = 0x54; #endif + } +#endif /* CONFIG_MAC_ADBKEYCODES */ #ifdef CONFIG_MAC_EMUMOUSEBTN emumousebtn_input_register(); diff -u --recursive --new-file v2.4.5/linux/drivers/macintosh/mac_keyb.c linux/drivers/macintosh/mac_keyb.c --- v2.4.5/linux/drivers/macintosh/mac_keyb.c Sun Dec 3 17:48:19 2000 +++ linux/drivers/macintosh/mac_keyb.c Wed Jun 27 13:37:35 2001 @@ -305,7 +305,7 @@ return 1; } -int mackbd_unexpected_up(unsigned char keycode) +char mackbd_unexpected_up(unsigned char keycode) { return 0x80; } diff -u --recursive --new-file v2.4.5/linux/drivers/macintosh/macserial.c linux/drivers/macintosh/macserial.c --- v2.4.5/linux/drivers/macintosh/macserial.c Sun Feb 4 10:21:25 2001 +++ linux/drivers/macintosh/macserial.c Wed Jun 27 13:37:35 2001 @@ -448,7 +448,7 @@ goto out; info->tx_active = 0; - if (info->x_char) { + if (info->x_char && !info->power_wait) { /* Send next char */ write_zsdata(info->zs_channel, info->x_char); info->x_char = 0; @@ -456,7 +456,8 @@ goto out; } - if ((info->xmit_cnt <= 0) || info->tty->stopped || info->tx_stopped) { + if ((info->xmit_cnt <= 0) || info->tty->stopped || info->tx_stopped + || info->power_wait) { write_zsreg(info->zs_channel, 0, RES_Tx_P); goto out; } @@ -474,6 +475,14 @@ restore_flags(flags); } +static void powerup_done(unsigned long data) +{ + struct mac_serial *info = (struct mac_serial *) data; + + info->power_wait = 0; + transmit_chars(info); +} + static _INLINE_ void status_handle(struct mac_serial *info) { unsigned char status; @@ -730,7 +739,7 @@ } } -static int startup(struct mac_serial * info, int can_sleep) +static int startup(struct mac_serial * info) { int delay; @@ -753,6 +762,18 @@ setup_scc(info); + if (delay) { + unsigned long flags; + + /* delay is in ms */ + save_flags(flags); + cli(); + info->power_wait = 1; + mod_timer(&info->powerup_timer, + jiffies + (delay * HZ + 999) / 1000); + restore_flags(flags); + } + OPNDBG("enabling IRQ on ttyS%d (irq %d)...\n", info->line, info->irq); info->flags |= ZILOG_INITIALIZED; @@ -761,15 +782,6 @@ enable_irq(info->rx_dma_irq); } - if (delay) { - if (can_sleep) { - /* we need to wait a bit before using the port */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(delay * HZ / 1000); - } else - mdelay(delay); - } - return 0; } @@ -863,7 +875,7 @@ queue_task(&tty->flip.tqueue, &tq_timer); } -static void poll_rxdma(void *private_) +static void poll_rxdma(unsigned long private_) { struct mac_serial *info = (struct mac_serial *) private_; unsigned long flags; @@ -2325,7 +2337,7 @@ * Start up serial port */ - retval = startup(info, 1); + retval = startup(info); if (retval) return retval; @@ -2426,6 +2438,10 @@ zss->rx_dma_irq = ch->intrs[2].line; spin_lock_init(&zss->rx_dma_lock); } + + init_timer(&zss->powerup_timer); + zss->powerup_timer.function = powerup_done; + zss->powerup_timer.data = (unsigned long) zss; } /* Ask the PROM how many Z8530s we have and initialize their zs_channels */ @@ -2680,14 +2696,7 @@ return 0; } -#ifdef MODULE -int init_module(void) -{ - macserial_init(); - return 0; -} - -void cleanup_module(void) +void macserial_cleanup(void) { int i; unsigned long flags; @@ -2717,7 +2726,9 @@ pmu_unregister_sleep_notifier(&serial_sleep_notifier); #endif /* CONFIG_PMAC_PBOOK */ } -#endif /* MODULE */ + +module_init(macserial_init); +module_exit(macserial_cleanup); #if 0 /* @@ -3119,7 +3130,7 @@ struct mac_serial *info = &zs_soft[i]; if (info->flags & ZILOG_SLEEPING) { info->flags &= ~ZILOG_SLEEPING; - startup(info, 0); + startup(info); } } break; diff -u --recursive --new-file v2.4.5/linux/drivers/macintosh/macserial.h linux/drivers/macintosh/macserial.h --- v2.4.5/linux/drivers/macintosh/macserial.h Sun Feb 4 10:21:25 2001 +++ linux/drivers/macintosh/macserial.h Wed Jun 27 13:37:35 2001 @@ -115,6 +115,7 @@ char is_irda; /* is connected to an IrDA codec */ unsigned char tx_active; /* character is being xmitted */ unsigned char tx_stopped; /* output is suspended */ + unsigned char power_wait; /* waiting for power-up delay to expire */ /* We need to know the current clock divisor * to read the bps rate the chip has currently @@ -186,6 +187,8 @@ void *dma_priv; struct timer_list poll_dma_timer; #define RX_DMA_TIMER (jiffies + 10*HZ/1000) + + struct timer_list powerup_timer; }; diff -u --recursive --new-file v2.4.5/linux/drivers/macintosh/via-pmu.c linux/drivers/macintosh/via-pmu.c --- v2.4.5/linux/drivers/macintosh/via-pmu.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/macintosh/via-pmu.c Mon Jul 2 14:34:57 2001 @@ -1431,7 +1431,7 @@ _set_L2CR(save_l2cr); /* Restore userland MMU context */ - set_context(current->mm->context, current->mm->pgd); + set_context(current->mm->context); /* Re-enable DEC interrupts and kick DEC */ asm volatile("mtdec %0" : : "r" (0x7fffffff)); @@ -1560,7 +1560,7 @@ feature_wake_up(); pbook_pci_restore(); - set_context(current->mm->context, current->mm->pgd); + set_context(current->mm->context); /* Restore L2 cache */ if (save_l2cr) diff -u --recursive --new-file v2.4.5/linux/drivers/md/md.c linux/drivers/md/md.c --- v2.4.5/linux/drivers/md/md.c Fri May 25 09:48:49 2001 +++ linux/drivers/md/md.c Mon Jul 2 14:16:24 2001 @@ -483,14 +483,17 @@ } } -static void mark_rdev_faulty (mdk_rdev_t * rdev) +static inline int mark_rdev_faulty (mdk_rdev_t * rdev) { if (!rdev) { MD_BUG(); - return; + return 0; } + if (rdev->faulty) + return 0; free_disk_sb(rdev); rdev->faulty = 1; + return 1; } static int read_disk_sb (mdk_rdev_t * rdev) @@ -634,7 +637,7 @@ md_list_add(&rdev->same_set, &mddev->disks); rdev->mddev = mddev; mddev->nb_dev++; - printk("bind<%s,%d>\n", partition_name(rdev->dev), mddev->nb_dev); + printk("md: bind<%s,%d>\n", partition_name(rdev->dev), mddev->nb_dev); } static void unbind_rdev_from_array (mdk_rdev_t * rdev) @@ -646,7 +649,7 @@ md_list_del(&rdev->same_set); MD_INIT_LIST_HEAD(&rdev->same_set); rdev->mddev->nb_dev--; - printk("unbind<%s,%d>\n", partition_name(rdev->dev), + printk("md: unbind<%s,%d>\n", partition_name(rdev->dev), rdev->mddev->nb_dev); rdev->mddev = NULL; } @@ -686,7 +689,7 @@ static void export_rdev (mdk_rdev_t * rdev) { - printk("export_rdev(%s)\n",partition_name(rdev->dev)); + printk("md: export_rdev(%s)\n",partition_name(rdev->dev)); if (rdev->mddev) MD_BUG(); unlock_rdev(rdev); @@ -694,7 +697,7 @@ md_list_del(&rdev->all); MD_INIT_LIST_HEAD(&rdev->all); if (rdev->pending.next != &rdev->pending) { - printk("(%s was pending)\n",partition_name(rdev->dev)); + printk("md: (%s was pending)\n",partition_name(rdev->dev)); md_list_del(&rdev->pending); MD_INIT_LIST_HEAD(&rdev->pending); } @@ -777,14 +780,14 @@ { int i; - printk(" SB: (V:%d.%d.%d) ID:<%08x.%08x.%08x.%08x> CT:%08x\n", + printk("md: SB: (V:%d.%d.%d) ID:<%08x.%08x.%08x.%08x> CT:%08x\n", sb->major_version, sb->minor_version, sb->patch_version, sb->set_uuid0, sb->set_uuid1, sb->set_uuid2, sb->set_uuid3, sb->ctime); - printk(" L%d S%08d ND:%d RD:%d md%d LO:%d CS:%d\n", sb->level, + printk("md: L%d S%08d ND:%d RD:%d md%d LO:%d CS:%d\n", sb->level, sb->size, sb->nr_disks, sb->raid_disks, sb->md_minor, sb->layout, sb->chunk_size); - printk(" UT:%08x ST:%d AD:%d WD:%d FD:%d SD:%d CSUM:%08x E:%08lx\n", + printk("md: UT:%08x ST:%d AD:%d WD:%d FD:%d SD:%d CSUM:%08x E:%08lx\n", sb->utime, sb->state, sb->active_disks, sb->working_disks, sb->failed_disks, sb->spare_disks, sb->sb_csum, (unsigned long)sb->events_lo); @@ -793,24 +796,24 @@ mdp_disk_t *desc; desc = sb->disks + i; - printk(" D %2d: ", i); + printk("md: D %2d: ", i); print_desc(desc); } - printk(" THIS: "); + printk("md: THIS: "); print_desc(&sb->this_disk); } static void print_rdev(mdk_rdev_t *rdev) { - printk(" rdev %s: O:%s, SZ:%08ld F:%d DN:%d ", + printk("md: rdev %s: O:%s, SZ:%08ld F:%d DN:%d ", partition_name(rdev->dev), partition_name(rdev->old_dev), rdev->size, rdev->faulty, rdev->desc_nr); if (rdev->sb) { - printk("rdev superblock:\n"); + printk("md: rdev superblock:\n"); print_sb(rdev->sb); } else - printk("no rdev superblock!\n"); + printk("md: no rdev superblock!\n"); } void md_print_devices (void) @@ -820,9 +823,9 @@ mddev_t *mddev; printk("\n"); - printk(" **********************************\n"); - printk(" * *\n"); - printk(" **********************************\n"); + printk("md: **********************************\n"); + printk("md: * *\n"); + printk("md: **********************************\n"); ITERATE_MDDEV(mddev,tmp) { printk("md%d: ", mdidx(mddev)); @@ -838,7 +841,7 @@ ITERATE_RDEV(mddev,rdev,tmp2) print_rdev(rdev); } - printk(" **********************************\n"); + printk("md: **********************************\n"); printk("\n"); } @@ -917,15 +920,15 @@ if (!rdev->sb) { MD_BUG(); - return -1; + return 1; } if (rdev->faulty) { MD_BUG(); - return -1; + return 1; } if (rdev->sb->md_magic != MD_SB_MAGIC) { MD_BUG(); - return -1; + return 1; } dev = rdev->dev; @@ -1014,7 +1017,7 @@ int md_update_sb(mddev_t * mddev) { - int first, err, count = 100; + int err, count = 100; struct md_list_head *tmp; mdk_rdev_t *rdev; @@ -1044,13 +1047,9 @@ printk(KERN_INFO "md: updating md%d RAID superblock on device\n", mdidx(mddev)); - first = 1; err = 0; ITERATE_RDEV(mddev,rdev,tmp) { - if (!first) { - first = 0; - printk(", "); - } + printk("md: "); if (rdev->faulty) printk("(skipping faulty "); printk("%s ", partition_name(rdev->dev)); @@ -1061,12 +1060,12 @@ } else printk(")\n"); } - printk(".\n"); if (err) { - printk("errors occurred during superblock update, repeating\n"); - if (--count) + if (--count) { + printk("md: errors occurred during superblock update, repeating\n"); goto repeat; - printk("excessive errors occurred during superblock update, exiting\n"); + } + printk("md: excessive errors occurred during superblock update, exiting\n"); } return 0; } @@ -1092,7 +1091,7 @@ rdev = (mdk_rdev_t *) kmalloc(sizeof(*rdev), GFP_KERNEL); if (!rdev) { - printk("could not alloc mem for %s!\n", partition_name(newdev)); + printk("md: could not alloc mem for %s!\n", partition_name(newdev)); return -ENOMEM; } memset(rdev, 0, sizeof(*rdev)); @@ -1244,7 +1243,7 @@ rdev->sb->events_hi--; } - printk("%s's event counter: %08lx\n", partition_name(rdev->dev), + printk("md: %s's event counter: %08lx\n", partition_name(rdev->dev), (unsigned long)rdev->sb->events_lo); if (!freshest) { freshest = rdev; @@ -1263,7 +1262,7 @@ } if (out_of_date) { printk(OUT_OF_DATE); - printk("freshest: %s\n", partition_name(freshest->dev)); + printk("md: freshest: %s\n", partition_name(freshest->dev)); } memcpy (sb, freshest->sb, sizeof(*sb)); @@ -1489,7 +1488,7 @@ rdev->size = calc_dev_size(rdev->dev, mddev, persistent); if (rdev->size < sb->chunk_size / 1024) { printk (KERN_WARNING - "Dev %s smaller than chunk_size: %ldk < %dk\n", + "md: Dev %s smaller than chunk_size: %ldk < %dk\n", partition_name(rdev->dev), rdev->size, sb->chunk_size / 1024); return -EINVAL; @@ -1649,8 +1648,7 @@ ITERATE_RDEV(mddev,rdev,tmp) { if (rdev->faulty) continue; - fsync_dev(rdev->dev); - invalidate_buffers(rdev->dev); + invalidate_device(rdev->dev, 1); if (get_hardsect_size(rdev->dev) > md_hardsect_sizes[mdidx(mddev)]) md_hardsect_sizes[mdidx(mddev)] = @@ -1663,7 +1661,7 @@ err = mddev->pers->run(mddev); if (err) { - printk("pers->run() failed ...\n"); + printk("md: pers->run() failed ...\n"); mddev->pers = NULL; return -EINVAL; } @@ -1676,7 +1674,8 @@ * twice as large as sectors. */ md_hd_struct[mdidx(mddev)].start_sect = 0; - md_hd_struct[mdidx(mddev)].nr_sects = md_size[mdidx(mddev)] << 1; + register_disk(&md_gendisk, MKDEV(MAJOR_NR,mdidx(mddev)), + 1, &md_fops, md_size[mdidx(mddev)]<<1); read_ahead[MD_MAJOR] = 1024; return (0); @@ -1705,7 +1704,7 @@ set_device_ro(mddev_to_kdev(mddev), 0); printk (KERN_INFO - "md%d switched to read-write mode.\n", mdidx(mddev)); + "md: md%d switched to read-write mode.\n", mdidx(mddev)); /* * Kick recovery or resync if necessary */ @@ -1733,12 +1732,6 @@ printk(STILL_IN_USE, mdidx(mddev)); OUT(-EBUSY); } - - /* this shouldn't be needed as above would have fired */ - if (!ro && is_mounted(dev)) { - printk (STILL_MOUNTED, mdidx(mddev)); - OUT(-EBUSY); - } if (mddev->pers) { /* @@ -1762,15 +1755,7 @@ down(&mddev->recovery_sem); up(&mddev->recovery_sem); - /* - * sync and invalidate buffers because we cannot kill the - * main thread with valid IO transfers still around. - * the kernel lock protects us from new requests being - * added after invalidate_buffers(). - */ - fsync_dev (mddev_to_kdev(mddev)); - fsync_dev (dev); - invalidate_buffers (dev); + invalidate_device(dev, 1); if (ro) { if (mddev->ro) @@ -1793,7 +1778,7 @@ * interrupted. */ if (!mddev->recovery_running && !resync_interrupted) { - printk("marking sb clean...\n"); + printk("md: marking sb clean...\n"); mddev->sb->state |= 1 << MD_SB_CLEAN; } md_update_sb(mddev); @@ -1806,12 +1791,12 @@ * Free resources if final stop */ if (!ro) { - printk (KERN_INFO "md%d stopped.\n", mdidx(mddev)); + printk (KERN_INFO "md: md%d stopped.\n", mdidx(mddev)); free_mddev(mddev); } else printk (KERN_INFO - "md%d switched to read-only mode.\n", mdidx(mddev)); + "md: md%d switched to read-only mode.\n", mdidx(mddev)); out: return err; } @@ -1843,16 +1828,16 @@ return; } - printk("running: "); + printk("md: running: "); ITERATE_RDEV(mddev,rdev,tmp) { printk("<%s>", partition_name(rdev->dev)); } - printk("\nnow!\n"); + printk("\nmd: now!\n"); err = do_md_run (mddev); if (err) { - printk("do_md_run() returned %d\n", err); + printk("md :do_md_run() returned %d\n", err); /* * prevent the writeback of an unrunnable array */ @@ -1882,20 +1867,20 @@ kdev_t md_kdev; - printk("autorun ...\n"); + printk("md: autorun ...\n"); while (pending_raid_disks.next != &pending_raid_disks) { rdev0 = md_list_entry(pending_raid_disks.next, mdk_rdev_t, pending); - printk("considering %s ...\n", partition_name(rdev0->dev)); + printk("md: considering %s ...\n", partition_name(rdev0->dev)); MD_INIT_LIST_HEAD(&candidates); ITERATE_RDEV_PENDING(rdev,tmp) { if (uuid_equal(rdev0, rdev)) { if (!sb_equal(rdev0->sb, rdev->sb)) { - printk("%s has same UUID as %s, but superblocks differ ...\n", partition_name(rdev->dev), partition_name(rdev0->dev)); + printk("md: %s has same UUID as %s, but superblocks differ ...\n", partition_name(rdev->dev), partition_name(rdev0->dev)); continue; } - printk(" adding %s ...\n", partition_name(rdev->dev)); + printk("md: adding %s ...\n", partition_name(rdev->dev)); md_list_del(&rdev->pending); md_list_add(&rdev->pending, &candidates); } @@ -1908,7 +1893,7 @@ md_kdev = MKDEV(MD_MAJOR, rdev0->sb->md_minor); mddev = kdev_to_mddev(md_kdev); if (mddev) { - printk("md%d already running, cannot run %s\n", + printk("md: md%d already running, cannot run %s\n", mdidx(mddev), partition_name(rdev0->dev)); ITERATE_RDEV_GENERIC(candidates,pending,rdev,tmp) export_rdev(rdev); @@ -1921,7 +1906,7 @@ } if (md_kdev == countdev) atomic_inc(&mddev->active); - printk("created md%d\n", mdidx(mddev)); + printk("md: created md%d\n", mdidx(mddev)); ITERATE_RDEV_GENERIC(candidates,pending,rdev,tmp) { bind_rdev_to_array(rdev, mddev); md_list_del(&rdev->pending); @@ -1929,7 +1914,7 @@ } autorun_array(mddev); } - printk("... autorun DONE.\n"); + printk("md: ... autorun DONE.\n"); } /* @@ -1971,7 +1956,7 @@ mdk_rdev_t *start_rdev = NULL, *rdev; if (md_import_device(startdev, 1)) { - printk("could not import %s!\n", partition_name(startdev)); + printk("md: could not import %s!\n", partition_name(startdev)); goto abort; } @@ -1981,7 +1966,7 @@ goto abort; } if (start_rdev->faulty) { - printk("can not autostart based on faulty %s!\n", + printk("md: can not autostart based on faulty %s!\n", partition_name(startdev)); goto abort; } @@ -1991,7 +1976,7 @@ err = detect_old_array(sb); if (err) { - printk("array version is too old to be autostarted, use raidtools 0.90 mkraid --upgrade\nto upgrade the array without data loss!\n"); + printk("md: array version is too old to be autostarted, use raidtools 0.90 mkraid --upgrade\nto upgrade the array without data loss!\n"); goto abort; } @@ -2007,7 +1992,7 @@ if (dev == startdev) continue; if (md_import_device(dev, 1)) { - printk("could not import %s, trying to run array nevertheless.\n", partition_name(dev)); + printk("md: could not import %s, trying to run array nevertheless.\n", partition_name(dev)); continue; } rdev = find_rdev_all(dev); @@ -2129,7 +2114,7 @@ dev = MKDEV(info->major,info->minor); if (find_rdev_all(dev)) { - printk("device %s already used in a RAID array!\n", + printk("md: device %s already used in a RAID array!\n", partition_name(dev)); return -EBUSY; } @@ -2137,7 +2122,7 @@ /* expecting a device which has a superblock */ err = md_import_device(dev, 1); if (err) { - printk("md error, md_import_device returned %d\n", err); + printk("md: md_import_device returned %d\n", err); return -EINVAL; } rdev = find_rdev_all(dev); @@ -2192,9 +2177,9 @@ persistent = !mddev->sb->not_persistent; if (!persistent) - printk("nonpersistent superblock ...\n"); + printk("md: nonpersistent superblock ...\n"); if (!mddev->sb->chunk_size) - printk("no chunksize?\n"); + printk("md: no chunksize?\n"); size = calc_dev_size(dev, mddev, persistent); rdev->sb_offset = calc_dev_sboffset(dev, mddev, persistent); @@ -2221,7 +2206,7 @@ if (!mddev->pers) return -ENODEV; - printk("trying to remove %s from md%d ... \n", + printk("md: trying to remove %s from md%d ... \n", partition_name(dev), mdidx(mddev)); if (!mddev->pers->diskop) { @@ -2261,7 +2246,7 @@ return 0; busy: - printk("cannot remove active disk %s from md%d ... \n", + printk("md: cannot remove active disk %s from md%d ... \n", partition_name(dev), mdidx(mddev)); return -EBUSY; } @@ -2276,7 +2261,7 @@ if (!mddev->pers) return -ENODEV; - printk("trying to hot-add %s to md%d ... \n", + printk("md: trying to hot-add %s to md%d ... \n", partition_name(dev), mdidx(mddev)); if (!mddev->pers->diskop) { @@ -2431,31 +2416,31 @@ static int set_disk_info (mddev_t * mddev, void * arg) { - printk("not yet"); + printk("md: not yet"); return -EINVAL; } static int clear_array (mddev_t * mddev) { - printk("not yet"); + printk("md: not yet"); return -EINVAL; } static int write_raid_info (mddev_t * mddev) { - printk("not yet"); + printk("md: not yet"); return -EINVAL; } static int protect_array (mddev_t * mddev) { - printk("not yet"); + printk("md: not yet"); return -EINVAL; } static int unprotect_array (mddev_t * mddev) { - printk("not yet"); + printk("md: not yet"); return -EINVAL; } @@ -2551,7 +2536,7 @@ case SET_ARRAY_INFO: case START_ARRAY: if (mddev) { - printk("array md%d already exists!\n", + printk("md: array md%d already exists!\n", mdidx(mddev)); err = -EEXIST; goto abort; @@ -2573,12 +2558,12 @@ */ err = lock_mddev(mddev); if (err) { - printk("ioctl, reason %d, cmd %d\n", err, cmd); + printk("md: ioctl, reason %d, cmd %d\n", err, cmd); goto abort; } if (mddev->sb) { - printk("array md%d already has a superblock!\n", + printk("md: array md%d already has a superblock!\n", mdidx(mddev)); err = -EBUSY; goto abort_unlock; @@ -2591,7 +2576,7 @@ } err = set_array_info(mddev, &info); if (err) { - printk("couldnt set array info. %d\n", err); + printk("md: couldnt set array info. %d\n", err); goto abort_unlock; } } @@ -2603,7 +2588,7 @@ */ err = autostart_array((kdev_t)arg, dev); if (err) { - printk("autostart %s failed!\n", + printk("md: autostart %s failed!\n", partition_name((kdev_t)arg)); goto abort; } @@ -2622,7 +2607,7 @@ } err = lock_mddev(mddev); if (err) { - printk("ioctl lock interrupted, reason %d, cmd %d\n",err, cmd); + printk("md: ioctl lock interrupted, reason %d, cmd %d\n",err, cmd); goto abort; } /* if we don't have a superblock yet, only ADD_NEW_DISK or STOP_ARRAY is allowed */ @@ -2760,7 +2745,7 @@ } default: - printk(KERN_WARNING "%s(pid %d) used obsolete MD ioctl, upgrade your software to use new ictls.\n", current->comm, current->pid); + printk(KERN_WARNING "md: %s(pid %d) used obsolete MD ioctl, upgrade your software to use new ictls.\n", current->comm, current->pid); err = -EINVAL; goto abort_unlock; } @@ -2773,7 +2758,7 @@ return err; done: if (err) - printk("huh12?\n"); + printk("md: huh12?\n"); abort: return err; } @@ -2835,7 +2820,7 @@ */ current->policy = SCHED_OTHER; current->nice = -20; -// md_unlock_kernel(); + md_unlock_kernel(); up(thread->sem); @@ -2845,9 +2830,9 @@ add_wait_queue(&thread->wqueue, &wait); set_task_state(current, TASK_INTERRUPTIBLE); if (!test_bit(THREAD_WAKEUP, &thread->flags)) { - dprintk("thread %p went to sleep.\n", thread); + dprintk("md: thread %p went to sleep.\n", thread); schedule(); - dprintk("thread %p woke up.\n", thread); + dprintk("md: thread %p woke up.\n", thread); } current->state = TASK_RUNNING; remove_wait_queue(&thread->wqueue, &wait); @@ -2859,7 +2844,7 @@ } else break; if (md_signal_pending(current)) { - printk("%8s(%d) flushing signals.\n", current->comm, + printk("md: %8s(%d) flushing signals.\n", current->comm, current->pid); md_flush_signals(); } @@ -2870,7 +2855,7 @@ void md_wakeup_thread(mdk_thread_t *thread) { - dprintk("waking up MD thread %p.\n", thread); + dprintk("md: waking up MD thread %p.\n", thread); set_bit(THREAD_WAKEUP, &thread->flags); wake_up(&thread->wqueue); } @@ -2909,7 +2894,7 @@ MD_BUG(); return; } - printk("interrupting MD-thread pid %d\n", thread->tsk->pid); + printk("md: interrupting MD-thread pid %d\n", thread->tsk->pid); send_sig(SIGKILL, thread->tsk, 1); } @@ -2950,7 +2935,8 @@ return 0; } rrdev = find_rdev(mddev, rdev); - mark_rdev_faulty(rrdev); + if (!mark_rdev_faulty(rrdev)) + return 0; /* * if recovery was running, stop it now. */ @@ -3132,7 +3118,7 @@ return -EBUSY; pers[pnum] = p; - printk(KERN_INFO "%s personality registered\n", p->name); + printk(KERN_INFO "md: %s personality registered\n", p->name); return 0; } @@ -3141,7 +3127,7 @@ if (pnum >= MAX_PERSONALITY) return -EINVAL; - printk(KERN_INFO "%s personality unregistered\n", pers[pnum]->name); + printk(KERN_INFO "md: %s personality unregistered\n", pers[pnum]->name); pers[pnum] = NULL; return 0; } @@ -3203,9 +3189,9 @@ curr_events = kstat.dk_drive_rblk[major][idx] + kstat.dk_drive_wblk[major][idx] ; curr_events -= sync_io[major][idx]; -// printk("events(major: %d, idx: %d): %ld\n", major, idx, curr_events); - if (curr_events != rdev->last_events) { -// printk("!I(%ld)", curr_events - rdev->last_events); +// printk("md: events(major: %d, idx: %d): %ld\n", major, idx, curr_events); + if ((curr_events - rdev->last_events) > 32) { +// printk("!I(%ld)%x", curr_events - rdev->last_events, rdev->dev); rdev->last_events = curr_events; idle = 0; } @@ -3232,7 +3218,6 @@ mddev_t *mddev2; unsigned int max_sectors, currspeed, j, window, err, serialize; - kdev_t read_disk = mddev_to_kdev(mddev); unsigned long mark[SYNC_MARKS]; unsigned long mark_cnt[SYNC_MARKS]; int last_mark,m; @@ -3332,7 +3317,7 @@ * got a signal, exit. */ mddev->curr_resync = 0; - printk("md_do_sync() got signal ... exiting\n"); + printk("md: md_do_sync() got signal ... exiting\n"); md_flush_signals(); err = -EINTR; goto out; @@ -3365,7 +3350,6 @@ } else current->nice = -20; } - fsync_dev(read_disk); printk(KERN_INFO "md: md%d: sync done.\n",mdidx(mddev)); err = 0; /* @@ -3481,7 +3465,7 @@ if ((code == MD_SYS_DOWN) || (code == MD_SYS_HALT) || (code == MD_SYS_POWER_OFF)) { - printk(KERN_INFO "stopping all md devices.\n"); + printk(KERN_INFO "md: stopping all md devices.\n"); ITERATE_MDDEV(mddev,tmp) do_md_stop (mddev, 1); @@ -3511,14 +3495,13 @@ md_size[i] = 0; md_hardsect_sizes[i] = 512; md_maxreadahead[i] = MD_READAHEAD; - register_disk(&md_gendisk, MKDEV(MAJOR_NR,i), 1, &md_fops, 0); } blksize_size[MAJOR_NR] = md_blocksizes; blk_size[MAJOR_NR] = md_size; max_readahead[MAJOR_NR] = md_maxreadahead; hardsect_size[MAJOR_NR] = md_hardsect_sizes; - printk("md.c: sizeof(mdp_super_t) = %d\n", (int)sizeof(mdp_super_t)); + dprintk("md: sizeof(mdp_super_t) = %d\n", (int)sizeof(mdp_super_t)); #ifdef CONFIG_PROC_FS create_proc_read_entry("mdstat", 0, NULL, md_status_read_proc, NULL); @@ -3530,13 +3513,13 @@ static char * name = "mdrecoveryd"; int minor; - printk (KERN_INFO "md driver %d.%d.%d MAX_MD_DEVS=%d, MD_SB_DISKS=%d\n", + printk (KERN_INFO "md: md driver %d.%d.%d MAX_MD_DEVS=%d, MD_SB_DISKS=%d\n", MD_MAJOR_VERSION, MD_MINOR_VERSION, MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MD_SB_DISKS); if (devfs_register_blkdev (MAJOR_NR, "md", &md_fops)) { - printk (KERN_ALERT "Unable to get major %d for md\n", MAJOR_NR); + printk (KERN_ALERT "md: Unable to get major %d for md\n", MAJOR_NR); return (-1); } devfs_handle = devfs_mk_dir (NULL, "md", NULL); @@ -3560,7 +3543,7 @@ md_recovery_thread = md_register_thread(md_do_recovery, NULL, name); if (!md_recovery_thread) - printk(KERN_ALERT "bug: couldn't allocate md_recovery_thread\n"); + printk(KERN_ALERT "md: bug: couldn't allocate md_recovery_thread\n"); md_register_reboot_notifier(&md_notifier); raid_table_header = register_sysctl_table(raid_root_table, 1); @@ -3605,13 +3588,13 @@ mdk_rdev_t *rdev; int i; - printk(KERN_INFO "autodetecting RAID arrays\n"); + printk(KERN_INFO "md: Autodetecting RAID arrays.\n"); for (i = 0; i < dev_cnt; i++) { kdev_t dev = detected_devices[i]; if (md_import_device(dev,1)) { - printk(KERN_ALERT "could not import %s!\n", + printk(KERN_ALERT "md: could not import %s!\n", partition_name(dev)); continue; } @@ -3638,7 +3621,7 @@ char device_set [MAX_MD_DEVS]; int pers[MAX_MD_DEVS]; int chunk[MAX_MD_DEVS]; - kdev_t devices[MAX_MD_DEVS][MD_SB_DISKS]; + char *device_names[MAX_MD_DEVS]; } md_setup_args md__initdata; /* @@ -3657,25 +3640,25 @@ * md=n,device-list reads a RAID superblock from the devices * elements in device-list are read by name_to_kdev_t so can be * a hex number or something like /dev/hda1 /dev/sdb + * 2001-06-03: Dave Cinege + * Shifted name_to_kdev_t() and related operations to md_set_drive() + * for later execution. Rewrote section to make devfs compatible. */ -#ifndef MODULE -extern kdev_t name_to_kdev_t(char *line) md__init; static int md__init md_setup(char *str) { - int minor, level, factor, fault, i=0; - kdev_t device; - char *devnames, *pername = ""; + int minor, level, factor, fault; + char *pername = ""; + char *str1 = str; if (get_option(&str, &minor) != 2) { /* MD Number */ printk("md: Too few arguments supplied to md=.\n"); return 0; } if (minor >= MAX_MD_DEVS) { - printk ("md: Minor device number too high.\n"); + printk ("md: md=%d, Minor device number too high.\n", minor); return 0; - } else if (md_setup_args.device_set[minor]) { - printk ("md: Warning - md=%d,... has been specified twice;\n" - " will discard the first definition.\n", minor); + } else if (md_setup_args.device_names[minor]) { + printk ("md: md=%d, Specified more then once. Replacing previous definition.\n", minor); } switch (get_option(&str, &level)) { /* RAID Personality */ case 2: /* could be 0 or -1.. */ @@ -3706,53 +3689,72 @@ } /* FALL THROUGH */ case 1: /* the first device is numeric */ - md_setup_args.devices[minor][i++] = level; + str = str1; /* FALL THROUGH */ case 0: md_setup_args.pers[minor] = 0; pername="super-block"; } - devnames = str; - for (; istrip_zone + i; - printk("zone %d\n", i); + printk("raid0: zone %d\n", i); zone->dev_offset = current_offset; smallest = NULL; c = 0; ITERATE_RDEV_ORDERED(mddev,rdev,j) { - printk(" checking %s ...", partition_name(rdev->dev)); + printk("raid0: checking %s ...", partition_name(rdev->dev)); if (rdev->size > current_offset) { printk(" contained as device %d\n", c); @@ -103,7 +103,7 @@ zone->nb_dev = c; zone->size = (smallest->size - current_offset) * c; - printk(" zone->nb_dev: %d, size: %ld\n",zone->nb_dev,zone->size); + printk("raid0: zone->nb_dev: %d, size: %ld\n",zone->nb_dev,zone->size); if (!conf->smallest || (zone->size < conf->smallest->size)) conf->smallest = zone; @@ -112,9 +112,9 @@ curr_zone_offset += zone->size; current_offset = smallest->size; - printk("current zone offset: %ld\n", current_offset); + printk("raid0: current zone offset: %ld\n", current_offset); } - printk("done.\n"); + printk("raid0: done.\n"); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/md/raid1.c linux/drivers/md/raid1.c --- v2.4.5/linux/drivers/md/raid1.c Thu May 24 15:40:59 2001 +++ linux/drivers/md/raid1.c Fri Jun 29 16:16:40 2001 @@ -75,14 +75,14 @@ md_spin_unlock_irq(&conf->device_lock); if (cnt == 0) break; - t = (struct buffer_head *)kmalloc(sizeof(struct buffer_head), GFP_BUFFER); + t = (struct buffer_head *)kmalloc(sizeof(struct buffer_head), GFP_NOIO); if (t) { memset(t, 0, sizeof(*t)); t->b_next = bh; bh = t; cnt--; } else { - PRINTK("waiting for %d bh\n", cnt); + PRINTK("raid1: waiting for %d bh\n", cnt); wait_event(conf->wait_buffer, conf->freebh_cnt >= cnt); } } @@ -165,8 +165,7 @@ md_spin_unlock_irq(&conf->device_lock); if (r1_bh) return r1_bh; - r1_bh = (struct raid1_bh *) kmalloc(sizeof(struct raid1_bh), - GFP_BUFFER); + r1_bh = (struct raid1_bh *) kmalloc(sizeof(struct raid1_bh), GFP_NOIO); if (r1_bh) { memset(r1_bh, 0, sizeof(*r1_bh)); return r1_bh; @@ -1123,7 +1122,7 @@ mddev = r1_bh->mddev; if (mddev->sb_dirty) { - printk(KERN_INFO "dirty sb detected, updating.\n"); + printk(KERN_INFO "raid1: dirty sb detected, updating.\n"); mddev->sb_dirty = 0; md_update_sb(mddev); } diff -u --recursive --new-file v2.4.5/linux/drivers/md/raid5.c linux/drivers/md/raid5.c --- v2.4.5/linux/drivers/md/raid5.c Thu May 24 15:40:59 2001 +++ linux/drivers/md/raid5.c Wed Jun 20 20:55:08 2001 @@ -31,6 +31,7 @@ */ #define NR_STRIPES 256 +#define IO_THRESHOLD 1 #define HASH_PAGES 1 #define HASH_PAGES_ORDER 0 #define NR_HASH (HASH_PAGES * PAGE_SIZE / sizeof(struct stripe_head *)) @@ -65,24 +66,33 @@ BUG(); if (atomic_read(&conf->active_stripes)==0) BUG(); - if (test_bit(STRIPE_HANDLE, &sh->state)) { + if (test_bit(STRIPE_DELAYED, &sh->state)) + list_add_tail(&sh->lru, &conf->delayed_list); + else if (test_bit(STRIPE_HANDLE, &sh->state)) { list_add_tail(&sh->lru, &conf->handle_list); md_wakeup_thread(conf->thread); - } - else { + } else { + if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) { + atomic_dec(&conf->preread_active_stripes); + if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) + md_wakeup_thread(conf->thread); + } list_add_tail(&sh->lru, &conf->inactive_list); atomic_dec(&conf->active_stripes); - wake_up(&conf->wait_for_stripe); + if (!conf->inactive_blocked || + atomic_read(&conf->active_stripes) < (NR_STRIPES*3/4)) + wake_up(&conf->wait_for_stripe); } } } static void release_stripe(struct stripe_head *sh) { raid5_conf_t *conf = sh->raid_conf; - - spin_lock_irq(&conf->device_lock); + unsigned long flags; + + spin_lock_irqsave(&conf->device_lock, flags); __release_stripe(conf, sh); - spin_unlock_irq(&conf->device_lock); + spin_unlock_irqrestore(&conf->device_lock, flags); } static void remove_hash(struct stripe_head *sh) @@ -284,13 +294,18 @@ sh = __find_stripe(conf, sector); if (!sh) { - sh = get_free_stripe(conf); + if (!conf->inactive_blocked) + sh = get_free_stripe(conf); if (noblock && sh == NULL) break; if (!sh) { + conf->inactive_blocked = 1; wait_event_lock_irq(conf->wait_for_stripe, - !list_empty(&conf->inactive_list), + !list_empty(&conf->inactive_list) && + (atomic_read(&conf->active_stripes) < (NR_STRIPES *3/4) + || !conf->inactive_blocked), conf->device_lock); + conf->inactive_blocked = 0; } else init_stripe(sh, sector); } else { @@ -359,23 +374,12 @@ } -static inline void raid5_end_buffer_read(struct buffer_head *blist, struct buffer_head *bh) -{ - while (blist) { - struct buffer_head *new = blist; - blist = new->b_reqnext; - memcpy(new->b_data, bh->b_data, bh->b_size); - new->b_end_io(new, 1); - } -} - static void raid5_end_read_request (struct buffer_head * bh, int uptodate) { struct stripe_head *sh = bh->b_private; raid5_conf_t *conf = sh->raid_conf; int disks = conf->raid_disks, i; unsigned long flags; - struct buffer_head *buffers = NULL; for (i=0 ; ibh_cache[i]) @@ -387,38 +391,45 @@ return; } - md_spin_lock_irqsave(&conf->device_lock, flags); if (uptodate) { -#ifdef CONFIG_HIGHMEM - /* cannot map highmem bufferheads from irq, - * so leave it for stripe_handle if there might - * be a problem + struct buffer_head *buffer; + spin_lock_irqsave(&conf->device_lock, flags); + /* we can return a buffer if we bypassed the cache or + * if the top buffer is not in highmem. If there are + * multiple buffers, leave the extra work to + * handle_stripe */ - if (sh->bh_read[i] && - sh->bh_read[i]->b_reqnext == NULL && - !PageHighMem(sh->bh_read[i]->b_page)) { - /* it's safe */ - buffers = sh->bh_read[i]; - sh->bh_read[i] = NULL; - } -#else - buffers = sh->bh_read[i]; - sh->bh_read[i] = NULL; -#endif - set_bit(BH_Uptodate, &bh->b_state); - if (buffers) { - spin_unlock_irqrestore(&conf->device_lock, flags); - raid5_end_buffer_read(buffers, bh); - spin_lock_irqsave(&conf->device_lock, flags); + buffer = sh->bh_read[i]; + if (buffer && + (!PageHighMem(buffer->b_page) + || buffer->b_page == bh->b_page ) + ) { + sh->bh_read[i] = buffer->b_reqnext; + buffer->b_reqnext = NULL; + } else + buffer = NULL; + spin_unlock_irqrestore(&conf->device_lock, flags); + if (sh->bh_page[i]==NULL) + set_bit(BH_Uptodate, &bh->b_state); + if (buffer) { + if (buffer->b_page != bh->b_page) + memcpy(buffer->b_data, bh->b_data, bh->b_size); + buffer->b_end_io(buffer, 1); } } else { md_error(conf->mddev, bh->b_dev); clear_bit(BH_Uptodate, &bh->b_state); } + /* must restore b_page before unlocking buffer... */ + if (sh->bh_page[i]) { + bh->b_page = sh->bh_page[i]; + bh->b_data = page_address(bh->b_page); + sh->bh_page[i] = NULL; + clear_bit(BH_Uptodate, &bh->b_state); + } clear_bit(BH_Lock, &bh->b_state); set_bit(STRIPE_HANDLE, &sh->state); - __release_stripe(conf, sh); - md_spin_unlock_irqrestore(&conf->device_lock, flags); + release_stripe(sh); } static void raid5_end_write_request (struct buffer_head *bh, int uptodate) @@ -819,6 +830,7 @@ spin_lock(&sh->lock); clear_bit(STRIPE_HANDLE, &sh->state); + clear_bit(STRIPE_DELAYED, &sh->state); syncing = test_bit(STRIPE_SYNCING, &sh->state); /* Now to look around and see what can be done */ @@ -939,6 +951,15 @@ } else if (conf->disks[i].operational) { set_bit(BH_Lock, &bh->b_state); action[i] = READ+1; + /* if I am just reading this block and we don't have + a failed drive, or any pending writes then sidestep the cache */ + if (sh->bh_page[i]) BUG(); + if (sh->bh_read[i] && !sh->bh_read[i]->b_reqnext && + ! syncing && !failed && !to_write) { + sh->bh_page[i] = sh->bh_cache[i]->b_page; + sh->bh_cache[i]->b_page = sh->bh_read[i]->b_page; + sh->bh_cache[i]->b_data = sh->bh_read[i]->b_data; + } locked++; PRINTK("Reading block %d (sync=%d)\n", i, syncing); if (syncing) @@ -956,7 +977,8 @@ /* would I have to read this buffer for read_modify_write */ bh = sh->bh_cache[i]; if ((sh->bh_write[i] || i == sh->pd_idx) && - !buffer_locked(bh) && !buffer_uptodate(bh)) { + (!buffer_locked(bh) || sh->bh_page[i]) && + !buffer_uptodate(bh)) { if (conf->disks[i].operational /* && !(conf->resync_parity && i == sh->pd_idx) */ ) @@ -965,7 +987,8 @@ } /* Would I have to read this buffer for reconstruct_write */ if (!sh->bh_write[i] && i != sh->pd_idx && - !buffer_locked(bh) && !buffer_uptodate(bh)) { + (!buffer_locked(bh) || sh->bh_page[i]) && + !buffer_uptodate(bh)) { if (conf->disks[i].operational) rcw++; else rcw += 2*disks; } @@ -979,10 +1002,16 @@ if ((sh->bh_write[i] || i == sh->pd_idx) && !buffer_locked(bh) && !buffer_uptodate(bh) && conf->disks[i].operational) { - PRINTK("Read_old block %d for r-m-w\n", i); - set_bit(BH_Lock, &bh->b_state); - action[i] = READ+1; - locked++; + if (test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) + { + PRINTK("Read_old block %d for r-m-w\n", i); + set_bit(BH_Lock, &bh->b_state); + action[i] = READ+1; + locked++; + } else { + set_bit(STRIPE_DELAYED, &sh->state); + set_bit(STRIPE_HANDLE, &sh->state); + } } } if (rcw <= rmw && rcw > 0) @@ -992,10 +1021,16 @@ if (!sh->bh_write[i] && i != sh->pd_idx && !buffer_locked(bh) && !buffer_uptodate(bh) && conf->disks[i].operational) { - PRINTK("Read_old block %d for Reconstruct\n", i); - set_bit(BH_Lock, &bh->b_state); - action[i] = READ+1; - locked++; + if (test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) + { + PRINTK("Read_old block %d for Reconstruct\n", i); + set_bit(BH_Lock, &bh->b_state); + action[i] = READ+1; + locked++; + } else { + set_bit(STRIPE_DELAYED, &sh->state); + set_bit(STRIPE_HANDLE, &sh->state); + } } } /* now if nothing is locked, and if we have enough data, we can start a write request */ @@ -1012,6 +1047,11 @@ || (i==sh->pd_idx && failed == 0)) set_bit(STRIPE_INSYNC, &sh->state); } + if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) { + atomic_dec(&conf->preread_active_stripes); + if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) + md_wakeup_thread(conf->thread); + } } } @@ -1103,6 +1143,47 @@ } } +static inline void raid5_activate_delayed(raid5_conf_t *conf) +{ + if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) { + while (!list_empty(&conf->delayed_list)) { + struct list_head *l = conf->delayed_list.next; + struct stripe_head *sh; + sh = list_entry(l, struct stripe_head, lru); + list_del_init(l); + clear_bit(STRIPE_DELAYED, &sh->state); + if (!test_and_set_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) + atomic_inc(&conf->preread_active_stripes); + list_add_tail(&sh->lru, &conf->handle_list); + } + } +} +static void raid5_unplug_device(void *data) +{ + raid5_conf_t *conf = (raid5_conf_t *)data; + unsigned long flags; + + spin_lock_irqsave(&conf->device_lock, flags); + + raid5_activate_delayed(conf); + + if (conf->plugged) { + conf->plugged = 0; + md_wakeup_thread(conf->thread); + } + spin_unlock_irqrestore(&conf->device_lock, flags); +} + +static inline void raid5_plug_device(raid5_conf_t *conf) +{ + spin_lock_irq(&conf->device_lock); + if (list_empty(&conf->delayed_list)) + if (!conf->plugged) { + conf->plugged = 1; + queue_task(&conf->plug_tq, &tq_disk); + } + spin_unlock_irq(&conf->device_lock); +} static int raid5_make_request (mddev_t *mddev, int rw, struct buffer_head * bh) { @@ -1129,6 +1210,8 @@ sh->pd_idx = pd_idx; add_stripe_bh(sh, bh, dd_idx, rw); + + raid5_plug_device(conf); handle_stripe(sh); release_stripe(sh); } else @@ -1208,8 +1291,19 @@ md_update_sb(mddev); } md_spin_lock_irq(&conf->device_lock); - while (!list_empty(&conf->handle_list)) { - struct list_head *first = conf->handle_list.next; + while (1) { + struct list_head *first; + + if (list_empty(&conf->handle_list) && + atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD && + !conf->plugged && + !list_empty(&conf->delayed_list)) + raid5_activate_delayed(conf); + + if (list_empty(&conf->handle_list)) + break; + + first = conf->handle_list.next; sh = list_entry(first, struct stripe_head, lru); list_del_init(first); @@ -1288,9 +1382,16 @@ conf->device_lock = MD_SPIN_LOCK_UNLOCKED; md_init_waitqueue_head(&conf->wait_for_stripe); INIT_LIST_HEAD(&conf->handle_list); + INIT_LIST_HEAD(&conf->delayed_list); INIT_LIST_HEAD(&conf->inactive_list); atomic_set(&conf->active_stripes, 0); + atomic_set(&conf->preread_active_stripes, 0); conf->buffer_size = PAGE_SIZE; /* good default for rebuild */ + + conf->plugged = 0; + conf->plug_tq.sync = 0; + conf->plug_tq.routine = &raid5_unplug_device; + conf->plug_tq.data = conf; PRINTK("raid5_run(md%d) called.\n", mdidx(mddev)); diff -u --recursive --new-file v2.4.5/linux/drivers/media/radio/Config.in linux/drivers/media/radio/Config.in --- v2.4.5/linux/drivers/media/radio/Config.in Fri Apr 13 20:26:07 2001 +++ linux/drivers/media/radio/Config.in Tue Jun 12 10:56:11 2001 @@ -24,6 +24,7 @@ dep_tristate ' Guillemot MAXI Radio FM 2000 radio' CONFIG_RADIO_MAXIRADIO $CONFIG_VIDEO_DEV dep_tristate ' Maestro on board radio' CONFIG_RADIO_MAESTRO $CONFIG_VIDEO_DEV dep_tristate ' miroSOUND PCM20 radio' CONFIG_RADIO_MIROPCM20 $CONFIG_VIDEO_DEV $CONFIG_SOUND_ACI_MIXER +dep_tristate ' miroSOUND PCM20 radio RDS user interface (EXPERIMENTAL)' CONFIG_RADIO_MIROPCM20_RDS $CONFIG_RADIO_MIROPCM20 $CONFIG_EXPERIMENTAL dep_tristate ' SF16FMI Radio' CONFIG_RADIO_SF16FMI $CONFIG_VIDEO_DEV if [ "$CONFIG_RADIO_SF16FMI" = "y" ]; then hex ' SF16FMI I/O port (0x284 or 0x384)' CONFIG_RADIO_SF16FMI_PORT 284 diff -u --recursive --new-file v2.4.5/linux/drivers/media/radio/Makefile linux/drivers/media/radio/Makefile --- v2.4.5/linux/drivers/media/radio/Makefile Fri Apr 13 20:26:07 2001 +++ linux/drivers/media/radio/Makefile Tue Jun 12 10:56:11 2001 @@ -21,11 +21,11 @@ # All of the (potential) objects that export symbols. # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'. -export-objs := +export-objs := miropcm20-rds-core.o list-multi := miropcm20.o -miropcm20-objs := radio-miropcm20.o rds-miropcm20.o +miropcm20-objs := miropcm20-rds-core.o miropcm20-radio.o obj-$(CONFIG_RADIO_AZTECH) += radio-aztech.o obj-$(CONFIG_RADIO_RTRACK2) += radio-rtrack2.o @@ -37,6 +37,7 @@ obj-$(CONFIG_RADIO_RTRACK) += radio-aimslab.o obj-$(CONFIG_RADIO_ZOLTRIX) += radio-zoltrix.o obj-$(CONFIG_RADIO_MIROPCM20) += miropcm20.o +obj-$(CONFIG_RADIO_MIROPCM20_RDS) += miropcm20-rds.o obj-$(CONFIG_RADIO_GEMTEK) += radio-gemtek.o obj-$(CONFIG_RADIO_TRUST) += radio-trust.o obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o diff -u --recursive --new-file v2.4.5/linux/drivers/media/radio/miropcm20-radio.c linux/drivers/media/radio/miropcm20-radio.c --- v2.4.5/linux/drivers/media/radio/miropcm20-radio.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/media/radio/miropcm20-radio.c Tue Jun 12 10:56:11 2001 @@ -0,0 +1,286 @@ +/* Miro PCM20 radio driver for Linux radio support + * (c) 1998 Ruurd Reitsma + * Thanks to Norberto Pellici for the ACI device interface specification + * The API part is based on the radiotrack driver by M. Kirkwood + * This driver relies on the aci mixer (drivers/sound/aci.c) + * Look there for further info... + */ + +/* Revision history: + * + * 1998 Ruurd Reitsma + * 2000-09-05 Robert Siemer + * removed unfinished volume control (maybe adding it later again) + * use OSS-mixer; added stereo control + */ + +/* What ever you think about the ACI, version 0x07 is not very well! + * I cant get frequency, 'tuner status', 'tuner flags' or mute/mono + * conditions... Robert + */ + +#include +#include +#include +#include "../../sound/aci.h" +#include "miropcm20-rds-core.h" + +static int users = 0; +static int radio_nr = -1; +MODULE_PARM(radio_nr, "i"); + +struct pcm20_device { + unsigned long freq; + int muted; + int stereo; +}; + + +static int pcm20_mute(struct pcm20_device *dev, unsigned char mute) +{ + dev->muted = mute; + return aci_write_cmd(ACI_SET_TUNERMUTE, mute); +} + +static int pcm20_stereo(struct pcm20_device *dev, unsigned char stereo) +{ + dev->stereo = stereo; + return aci_write_cmd(ACI_SET_TUNERMONO, !stereo); +} + +static int pcm20_setfreq(struct pcm20_device *dev, unsigned long freq) +{ + unsigned char freql; + unsigned char freqh; + + dev->freq=freq; + + freq /= 160; + if (!(aci_version==0x07 || aci_version>=0xb0)) + freq /= 10; /* I don't know exactly which version + * needs this hack */ + freql = freq & 0xff; + freqh = freq >> 8; + + aci_rds_cmd(RDS_RESET, 0, 0); + pcm20_stereo(dev, 1); + + return aci_rw_cmd(ACI_WRITE_TUNE, freql, freqh); +} + +static int pcm20_getflags(struct pcm20_device *dev, __u32 *flags, __u16 *signal) +{ + /* okay, check for signal, stereo and rds here... */ + int i; + unsigned char buf; + + if ((i=aci_rw_cmd(ACI_READ_TUNERSTATION, -1, -1))<0) + return i; +#if DEBUG + printk("check_sig: 0x%x\n", i); +#endif + if (i & 0x80) { + /* no signal from tuner */ + *flags=0; + *signal=0; + return 0; + } else + *signal=0xffff; + + if ((i=aci_rw_cmd(ACI_READ_TUNERSTEREO, -1, -1))<0) + return i; + if (i & 0x40) { + *flags=0; + } else { + /* stereo */ + *flags=VIDEO_TUNER_STEREO_ON; + /* I cant see stereo, when forced to mono */ + dev->stereo=1; + } + + if ((i=aci_rds_cmd(RDS_STATUS, &buf, 1))<0) + return i; + if (buf & 1) + /* RDS available */ + *flags|=VIDEO_TUNER_RDS_ON; + else + return 0; + + if ((i=aci_rds_cmd(RDS_RXVALUE, &buf, 1))<0) + return i; +#if DEBUG + printk("rds-signal: %d\n", buf); +#endif + if (buf > 15) { + printk("miropcm20-radio: RX strengths unexpected high...\n"); + buf=15; + } + /* refine signal */ + if ((*signal=SCALE(15, 0xffff, buf))==0) + *signal = 1; + + return 0; +} + +static int pcm20_ioctl(struct video_device *dev, unsigned int cmd, void *arg) +{ + struct pcm20_device *pcm20=dev->priv; + int i; + + switch(cmd) + { + case VIDIOCGCAP: + { + struct video_capability v; + v.type=VID_TYPE_TUNER; + strcpy(v.name, "Miro PCM20"); + v.channels=1; + v.audios=1; + /* No we don't do pictures */ + v.maxwidth=0; + v.maxheight=0; + v.minwidth=0; + v.minheight=0; + if(copy_to_user(arg,&v,sizeof(v))) + return -EFAULT; + return 0; + } + case VIDIOCGTUNER: + { + struct video_tuner v; + if(copy_from_user(&v, arg,sizeof(v))!=0) + return -EFAULT; + if(v.tuner) /* Only 1 tuner */ + return -EINVAL; + v.rangelow=87*16000; + v.rangehigh=108*16000; + pcm20_getflags(pcm20, &v.flags, &v.signal); + v.flags|=VIDEO_TUNER_LOW; + v.mode=VIDEO_MODE_AUTO; + strcpy(v.name, "FM"); + if(copy_to_user(arg,&v, sizeof(v))) + return -EFAULT; + return 0; + } + case VIDIOCSTUNER: + { + struct video_tuner v; + if(copy_from_user(&v, arg, sizeof(v))) + return -EFAULT; + if(v.tuner!=0) + return -EINVAL; + /* Only 1 tuner so no setting needed ! */ + return 0; + } + case VIDIOCGFREQ: + if(copy_to_user(arg, &pcm20->freq, sizeof(pcm20->freq))) + return -EFAULT; + return 0; + case VIDIOCSFREQ: + if(copy_from_user(&pcm20->freq, arg, sizeof(pcm20->freq))) + return -EFAULT; + i=pcm20_setfreq(pcm20, pcm20->freq); +#if DEBUG + printk("First view (setfreq): 0x%x\n", i); +#endif + return i; + case VIDIOCGAUDIO: + { + struct video_audio v; + memset(&v,0, sizeof(v)); + v.flags=VIDEO_AUDIO_MUTABLE; + if (pcm20->muted) + v.flags|=VIDEO_AUDIO_MUTE; + v.mode=VIDEO_SOUND_STEREO; + if (pcm20->stereo) + v.mode|=VIDEO_SOUND_MONO; + /* v.step=2048; */ + strcpy(v.name, "Radio"); + if(copy_to_user(arg,&v, sizeof(v))) + return -EFAULT; + return 0; + } + case VIDIOCSAUDIO: + { + struct video_audio v; + if(copy_from_user(&v, arg, sizeof(v))) + return -EFAULT; + if(v.audio) + return -EINVAL; + + pcm20_mute(pcm20, !!(v.flags&VIDEO_AUDIO_MUTE)); + if(v.flags&VIDEO_SOUND_MONO) + pcm20_stereo(pcm20, 0); + if(v.flags&VIDEO_SOUND_STEREO) + pcm20_stereo(pcm20, 1); + + return 0; + } + default: + return -ENOIOCTLCMD; + } +} + +static int pcm20_open(struct video_device *dev, int flags) +{ + if(users) + return -EBUSY; + users++; + MOD_INC_USE_COUNT; + return 0; +} + +static void pcm20_close(struct video_device *dev) +{ + users--; + MOD_DEC_USE_COUNT; +} + +static struct pcm20_device pcm20_unit = { + freq: 87*16000, + muted: 1, + stereo: 0 +}; + +static struct video_device pcm20_radio = { + owner: THIS_MODULE, + name: "Miro PCM 20 radio", + type: VID_TYPE_TUNER, + hardware: VID_HARDWARE_RTRACK, + open: pcm20_open, + close: pcm20_close, + ioctl: pcm20_ioctl, + priv: &pcm20_unit +}; + +static int __init pcm20_init(void) +{ + if(video_register_device(&pcm20_radio, VFL_TYPE_RADIO, radio_nr)==-1) + goto video_register_device; + + if(attach_aci_rds()<0) + goto attach_aci_rds; + + printk(KERN_INFO "Miro PCM20 radio card driver.\n"); + + return 0; + + attach_aci_rds: + video_unregister_device(&pcm20_radio); + video_register_device: + return -EINVAL; +} + +MODULE_AUTHOR("Ruurd Reitsma"); +MODULE_DESCRIPTION("A driver for the Miro PCM20 radio card."); + +EXPORT_NO_SYMBOLS; + +static void __exit pcm20_cleanup(void) +{ + unload_aci_rds(); + video_unregister_device(&pcm20_radio); +} + +module_init(pcm20_init); +module_exit(pcm20_cleanup); diff -u --recursive --new-file v2.4.5/linux/drivers/media/radio/miropcm20-rds-core.c linux/drivers/media/radio/miropcm20-rds-core.c --- v2.4.5/linux/drivers/media/radio/miropcm20-rds-core.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/media/radio/miropcm20-rds-core.c Tue Jun 12 10:56:11 2001 @@ -0,0 +1,210 @@ +/* + * Many thanks to Fred Seidel , the + * designer of the RDS decoder hardware. With his help + * I was able to code this driver. + * Thanks also to Norberto Pellicci, Dominic Mounteney + * and www.teleauskunft.de + * for good hints on finding Fred. It was somewhat hard + * to locate him here in Germany... [: + * + * Revision history: + * + * 2000-08-09 Robert Siemer + * RDS support for MiroSound PCM20 radio + */ + +#define _NO_VERSION_ + +/* #include */ +#include +#include +#include +#include +#include +#include "../../sound/aci.h" +#include "miropcm20-rds-core.h" + +#define DEBUG 0 + +static struct semaphore aci_rds_sem; + +#define RDS_DATASHIFT 2 /* Bit 2 */ +#define RDS_DATAMASK (1 << RDS_DATASHIFT) +#define RDS_BUSYMASK 0x10 /* Bit 4 */ +#define RDS_CLOCKMASK 0x08 /* Bit 3 */ + +#define RDS_DATA(x) (((x) >> RDS_DATASHIFT) & 1) + + +#if DEBUG +static void print_matrix(char array[], unsigned int length) +{ + int i, j; + + for (i=0; i=0; j--) { + printk("%d", (array[i] >> j) & 0x1); + } + if (i%8 == 0) + printk(" byte-border\n"); + else + printk("\n"); + } +} +#endif /* DEBUG */ + +static int byte2trans(unsigned char byte, unsigned char sendbuffer[], int size) +{ + int i; + + if (size != 8) + return -1; + for (i = 7; i >= 0; i--) + sendbuffer[7-i] = (byte & (1 << i)) ? RDS_DATAMASK : 0; + sendbuffer[0] |= RDS_CLOCKMASK; + + return 0; +} + +static int rds_waitread(void) +{ + unsigned char byte; + int i=2000; + + do { + byte=inb(RDS_REGISTER); + i--; + } + while ((byte & RDS_BUSYMASK) && i); + + if (i) { + #if DEBUG + printk(KERN_DEBUG "rds_waitread()"); + print_matrix(&byte, 1); + #endif + return (byte); + } else { + printk(KERN_WARNING "aci-rds: rds_waitread() timeout...\n"); + return -1; + } +} + +/* dont use any ..._nowait() function if you are not sure what you do... */ + +static inline void rds_rawwrite_nowait(unsigned char byte) +{ + #if DEBUG + printk(KERN_DEBUG "rds_rawwrite()"); + print_matrix(&byte, 1); + #endif + outb(byte, RDS_REGISTER); +} + +static int rds_rawwrite(unsigned char byte) +{ + if (rds_waitread() >= 0) { + rds_rawwrite_nowait(byte); + return 0; + } else + return -1; +} + +static int rds_write(unsigned char cmd) +{ + unsigned char sendbuffer[8]; + int i; + + if (byte2trans(cmd, sendbuffer, 8) != 0){ + return -1; + } else { + for (i=0; i<8; i++) { + rds_rawwrite(sendbuffer[i]); + } + } + return 0; +} + +static int rds_readcycle_nowait(void) +{ + rds_rawwrite_nowait(0); + return rds_waitread(); +} + +static int rds_readcycle(void) +{ + if (rds_rawwrite(0) < 0) + return -1; + return rds_waitread(); +} + +static int rds_read(unsigned char databuffer[], int datasize) +{ + #define READSIZE (8*datasize) + + int i,j; + + if (datasize < 1) /* nothing to read */ + return 0; + + /* to be able to use rds_readcycle_nowait() + I have to waitread() here */ + if (rds_waitread() < 0) + return -1; + + memset(databuffer, 0, datasize); + + for (i=0; i< READSIZE; i++) + if((j=rds_readcycle_nowait()) < 0) { + return -1; + } else { + databuffer[i/8]|=(RDS_DATA(j) << (7-(i%8))); + } + + return 0; +} + +static int rds_ack(void) +{ + int i=rds_readcycle(); + + if (i < 0) + return -1; + if (i & RDS_DATAMASK) { + return 0; /* ACK */ + } else { + printk(KERN_DEBUG "aci-rds: NACK\n"); + return 1; /* NACK */ + } +} + +int aci_rds_cmd(unsigned char cmd, unsigned char databuffer[], int datasize) +{ + int ret; + + if (down_interruptible(&aci_rds_sem)) + return -EINTR; + + rds_write(cmd); + + /* RDS_RESET doesn't need further processing */ + if (cmd!=RDS_RESET && (rds_ack() || rds_read(databuffer, datasize))) + ret = -1; + else + ret = 0; + + up(&aci_rds_sem); + + return ret; +} +EXPORT_SYMBOL(aci_rds_cmd); + +int __init attach_aci_rds(void) +{ + init_MUTEX(&aci_rds_sem); + return 0; +} + +void __exit unload_aci_rds(void) +{ +} diff -u --recursive --new-file v2.4.5/linux/drivers/media/radio/miropcm20-rds-core.h linux/drivers/media/radio/miropcm20-rds-core.h --- v2.4.5/linux/drivers/media/radio/miropcm20-rds-core.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/media/radio/miropcm20-rds-core.h Tue Jun 12 10:56:11 2001 @@ -0,0 +1,19 @@ +#ifndef _MIROPCM20_RDS_CORE_H_ +#define _MIROPCM20_RDS_CORE_H_ + +extern int aci_rds_cmd(unsigned char cmd, unsigned char databuffer[], int datasize); + +#define RDS_STATUS 0x01 +#define RDS_STATIONNAME 0x02 +#define RDS_TEXT 0x03 +#define RDS_ALTFREQ 0x04 +#define RDS_TIMEDATE 0x05 +#define RDS_PI_CODE 0x06 +#define RDS_PTYTATP 0x07 +#define RDS_RESET 0x08 +#define RDS_RXVALUE 0x09 + +extern void __exit unload_aci_rds(void); +extern int __init attach_aci_rds(void); + +#endif /* _MIROPCM20_RDS_CORE_H_ */ diff -u --recursive --new-file v2.4.5/linux/drivers/media/radio/miropcm20-rds.c linux/drivers/media/radio/miropcm20-rds.c --- v2.4.5/linux/drivers/media/radio/miropcm20-rds.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/media/radio/miropcm20-rds.c Tue Jun 12 10:56:11 2001 @@ -0,0 +1,140 @@ +/* MiroSOUND PCM20 radio rds interface driver + * (c) 2001 Robert Siemer + * Thanks to Fred Seidel. See miropcm20-rds-core.c for further information. + */ + +/* Revision history: + * + * 2001-04-18 Robert Siemer + * separate file for user interface driver + */ + +#include +#include +#include +#include +#include +#include "miropcm20-rds-core.h" + +devfs_handle_t dfsh; +char * text_buffer; +static int rds_users = 0; + + +static int rds_f_open(struct inode *in, struct file *fi) +{ + if(rds_users) + return -EBUSY; + + if ((text_buffer=kmalloc(66, GFP_KERNEL)) == 0) { + printk(KERN_NOTICE "aci-rds: Out of memory by open()...\n"); + return -ENOMEM; + } + + rds_users++; + MOD_INC_USE_COUNT; + return 0; +} + +static int rds_f_release(struct inode *in, struct file *fi) +{ + kfree(text_buffer); + + rds_users--; + MOD_DEC_USE_COUNT; + return 0; +} + +static void print_matrix(char *ch, char out[]) +{ + int j; + + for (j=7; j>=0; j--) { + out[7-j] = ((*ch >> j) & 0x1) + '0'; + } +} + +static ssize_t rds_f_read(struct file *file, char *buffer, size_t length, loff_t *offset) +{ +// i = sprintf(text_buffer, "length: %d, offset: %d\n", length, *offset); + + char c; + char bits[8]; + + current->state=TASK_UNINTERRUPTIBLE; + schedule_timeout(2*HZ); + aci_rds_cmd(RDS_STATUS, &c, 1); + print_matrix(&c, bits); + if (copy_to_user(buffer, bits, 8)) + return -EFAULT; + +/* if ((c >> 3) & 1) { + aci_rds_cmd(RDS_STATIONNAME, text_buffer+1, 8); + text_buffer[0] = ' ' ; + text_buffer[9] = '\n'; + return copy_to_user(buffer+8, text_buffer, 10) ? -EFAULT: 18; + } +*/ +/* if ((c >> 6) & 1) { + aci_rds_cmd(RDS_PTYTATP, &c, 1); + if ( c & 1) + sprintf(text_buffer, " M"); + else + sprintf(text_buffer, " S"); + if ((c >> 1) & 1) + sprintf(text_buffer+2, " TA"); + else + sprintf(text_buffer+2, " --"); + if ((c >> 7) & 1) + sprintf(text_buffer+5, " TP"); + else + sprintf(text_buffer+5, " --"); + sprintf(text_buffer+8, " %2d\n", (c >> 2) & 0x1f); + return copy_to_user(buffer+8, text_buffer, 12) ? -EFAULT: 20; + } +*/ + + if ((c >> 4) & 1) { + aci_rds_cmd(RDS_TEXT, text_buffer, 65); + text_buffer[0] = ' ' ; + text_buffer[65] = '\n'; + return copy_to_user(buffer+8, text_buffer,66) ? -EFAULT : 66+8; + } else { + put_user('\n', buffer+8); + return 9; + } +} + +static struct file_operations rds_f_ops = { + read: rds_f_read, + open: rds_f_open, + release: rds_f_release +}; + + +static int __init miropcm20_rds_init(void) +{ + if ((dfsh = devfs_register(NULL, "v4l/rds/radiotext", + DEVFS_FL_DEFAULT | DEVFS_FL_AUTO_DEVNUM, + 0, 0, S_IRUGO | S_IFCHR, &rds_f_ops, NULL)) + == NULL) + goto devfs_register; + + printk("miropcm20-rds: userinterface driver loaded.\n"); +#if DEBUG + printk("v4l-name: %s\n", devfs_get_name(pcm20_radio.devfs_handle, 0)); +#endif + + return 0; + + devfs_register: + return -EINVAL; +} + +static void __exit miropcm20_rds_cleanup(void) +{ + devfs_unregister(dfsh); +} + +module_init(miropcm20_rds_init); +module_exit(miropcm20_rds_cleanup); diff -u --recursive --new-file v2.4.5/linux/drivers/media/radio/radio-miropcm20.c linux/drivers/media/radio/radio-miropcm20.c --- v2.4.5/linux/drivers/media/radio/radio-miropcm20.c Sat May 19 17:43:06 2001 +++ linux/drivers/media/radio/radio-miropcm20.c Wed Dec 31 16:00:00 1969 @@ -1,290 +0,0 @@ -/* Miro PCM20 radio driver for Linux radio support - * (c) 1998 Ruurd Reitsma - * Thanks to Norberto Pellici for the ACI device interface specification - * The API part is based on the radiotrack driver by M. Kirkwood - * This driver relies on the aci mixer (drivers/sound/aci.c) - * Look there for further info... - */ - -/* Revision history: - * - * 1998 Ruurd Reitsma - * 2000-09-05 Robert Siemer - * removed unfinished volume control (maybe adding it later again) - * use OSS-mixer; added stereo control - */ - -/* What ever you think about the ACI, version 0x07 is not very well! - * I cant get frequency, 'tuner status', 'tuner flags' or mute/mono - * conditions... Robert - */ - -#include -#include -#include -#include -#include - -char * aci_radio_name; - -#include "../../sound/aci.h" - -static int users = 0; -static int radio_nr = -1; -MODULE_PARM(radio_nr, "i"); - -struct pcm20_device -{ - unsigned long freq; - int muted; - int stereo; -}; - - -static int pcm20_mute(struct pcm20_device *dev, unsigned char mute) -{ - dev->muted = mute; - return aci_write_cmd(0xa3, mute); -} - -static int pcm20_stereo(struct pcm20_device *dev, unsigned char stereo) -{ - dev->stereo = stereo; - return aci_write_cmd(0xa4, !stereo); -} - -static int pcm20_setfreq(struct pcm20_device *dev, unsigned long freq) -{ - unsigned char freql; - unsigned char freqh; - - dev->freq=freq; - - freq /= 160; - if (!(aci_version==0x07 || aci_version>=0xb0)) - freq /= 10; /* I don't know exactly which version - * needs this hack */ - freql = freq & 0xff; - freqh = freq >> 8; - - aci_rds_cmd(RDS_RESET, 0, 0); - pcm20_stereo(dev, 1); - - return aci_rw_cmd(0xa7, freql, freqh); /* Tune to frequency */ -} - -static int pcm20_getflags(struct pcm20_device *dev, __u32 *flags, __u16 *signal) -{ - /* okay, check for signal, stereo and rds here... */ - int i; - unsigned char buf; - - if ((i=aci_rw_cmd(0xa9, -1, -1))<0) - return i; -#if DEBUG - printk("check_sig: 0x%x\n", i); -#endif - if (i & 0x80) { - /* no signal from tuner */ - *flags=0; - *signal=0; - return 0; - } else - *signal=0xffff; - - if ((i=aci_rw_cmd(0xa8, -1, -1))<0) - return i; - if (i & 0x40) { - *flags=0; - } else { - /* stereo */ - *flags=VIDEO_TUNER_STEREO_ON; - /* I cant see stereo, when forced to mono */ - dev->stereo=1; - } - - if ((i=aci_rds_cmd(RDS_STATUS, &buf, 1))<0) - return i; - if (buf & 1) - /* RDS available */ - *flags|=VIDEO_TUNER_RDS_ON; - else - return 0; - - if ((i=aci_rds_cmd(RDS_RXVALUE, &buf, 1))<0) - return i; -#if DEBUG - printk("rds-signal: %d\n", buf); -#endif - if (buf > 15) { - printk("rds-miropcm20: RX strengths unexpected high...\n"); - buf=15; - } - /* refine signal */ - if ((*signal=SCALE(15, 0xffff, buf))==0) - *signal = 1; - - return 0; -} - -static int pcm20_ioctl(struct video_device *dev, unsigned int cmd, void *arg) -{ - struct pcm20_device *pcm20=dev->priv; - int i; - - switch(cmd) - { - case VIDIOCGCAP: - { - struct video_capability v; - v.type=VID_TYPE_TUNER; - strcpy(v.name, "Miro PCM20"); - v.channels=1; - v.audios=1; - /* No we don't do pictures */ - v.maxwidth=0; - v.maxheight=0; - v.minwidth=0; - v.minheight=0; - if(copy_to_user(arg,&v,sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCGTUNER: - { - struct video_tuner v; - if(copy_from_user(&v, arg,sizeof(v))!=0) - return -EFAULT; - if(v.tuner) /* Only 1 tuner */ - return -EINVAL; - v.rangelow=87*16000; - v.rangehigh=108*16000; - pcm20_getflags(pcm20, &v.flags, &v.signal); - v.flags|=VIDEO_TUNER_LOW; - v.mode=VIDEO_MODE_AUTO; - strcpy(v.name, "FM"); - if(copy_to_user(arg,&v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSTUNER: - { - struct video_tuner v; - if(copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if(v.tuner!=0) - return -EINVAL; - /* Only 1 tuner so no setting needed ! */ - return 0; - } - case VIDIOCGFREQ: - if(copy_to_user(arg, &pcm20->freq, sizeof(pcm20->freq))) - return -EFAULT; - return 0; - case VIDIOCSFREQ: - if(copy_from_user(&pcm20->freq, arg, sizeof(pcm20->freq))) - return -EFAULT; - i=pcm20_setfreq(pcm20, pcm20->freq); -#if DEBUG - printk("First view (setfreq): 0x%x\n", i); -#endif - return i; - case VIDIOCGAUDIO: - { - struct video_audio v; - memset(&v,0, sizeof(v)); - v.flags=VIDEO_AUDIO_MUTABLE; - if (pcm20->muted) - v.flags|=VIDEO_AUDIO_MUTE; - v.mode=VIDEO_SOUND_STEREO; - if (pcm20->stereo) - v.mode|=VIDEO_SOUND_MONO; - /* v.step=2048; */ - strcpy(v.name, "Radio"); - if(copy_to_user(arg,&v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSAUDIO: - { - struct video_audio v; - if(copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if(v.audio) - return -EINVAL; - - pcm20_mute(pcm20, !!(v.flags&VIDEO_AUDIO_MUTE)); - if(v.flags&VIDEO_SOUND_MONO) - pcm20_stereo(pcm20, 0); - if(v.flags&VIDEO_SOUND_STEREO) - pcm20_stereo(pcm20, 1); - - return 0; - } - default: - return -ENOIOCTLCMD; - } -} - -static int pcm20_open(struct video_device *dev, int flags) -{ - if(users) - return -EBUSY; - users++; - return 0; -} - -static void pcm20_close(struct video_device *dev) -{ - users--; -} - -static struct pcm20_device pcm20_unit= -{ - freq: 87*16000, - muted: 1, - stereo: 0 -}; - -static struct video_device pcm20_radio= -{ - owner: THIS_MODULE, - name: "Miro PCM 20 radio", - type: VID_TYPE_TUNER, - hardware: VID_HARDWARE_RTRACK, - open: pcm20_open, - close: pcm20_close, - ioctl: pcm20_ioctl, - priv: &pcm20_unit -}; - -static int __init pcm20_init(void) -{ - if(video_register_device(&pcm20_radio, VFL_TYPE_RADIO, radio_nr)==-1) - return -EINVAL; - - if(attach_aci_rds()<0) { - video_unregister_device(&pcm20_radio); - return -EINVAL; - } -#if DEBUG - printk("v4l-name: %s\n", devfs_get_name(pcm20_radio.devfs_handle, 0)); -#endif - printk(KERN_INFO "Miro PCM20 radio card driver.\n"); - - return 0; -} - -MODULE_AUTHOR("Ruurd Reitsma"); -MODULE_DESCRIPTION("A driver for the Miro PCM20 radio card."); - -EXPORT_NO_SYMBOLS; - -static void __exit pcm20_cleanup(void) -{ - unload_aci_rds(); - video_unregister_device(&pcm20_radio); -} - -module_init(pcm20_init); -module_exit(pcm20_cleanup); diff -u --recursive --new-file v2.4.5/linux/drivers/media/radio/rds-miropcm20.c linux/drivers/media/radio/rds-miropcm20.c --- v2.4.5/linux/drivers/media/radio/rds-miropcm20.c Fri Apr 13 20:26:07 2001 +++ linux/drivers/media/radio/rds-miropcm20.c Wed Dec 31 16:00:00 1969 @@ -1,249 +0,0 @@ -/* - * Many thanks to Fred Seidel , the - * designer of the RDS decoder hardware. With his help - * I was able to code this driver. - * Thanks also to Norberto Pellicci, Dominic Mounteney - * and www.teleauskunft.de - * for good hints on finding Fred. It was somewhat hard - * to locate him here in Germany... [: - * - * Revision history: - * - * 2000-08-09 Robert Siemer - * RDS support for MiroSound PCM20 radio - */ - -#define _NO_VERSION_ - -/* #include */ -#include -#include -#include -#include -#include -#include "../../sound/aci.h" - -#define WATCHMASK 0352 /* 11101010 */ - -#define DEBUG 0 - -static struct semaphore aci_rds_sem; - - -#define RDS_BUSYMASK 0x10 /* Bit 4 */ -#define RDS_CLOCKMASK 0x08 /* Bit 3 */ -#define RDS_DATAMASK 0x04 /* Bit 2 */ - - -static void print_matrix(char array[], unsigned int length) -{ - int i, j; - - for (i=0; i=0; j--) { - printk("%d", (array[i] >> j) & 0x1); - } - if (i%8 == 0) - printk(" byte-border\n"); - else - printk("\n"); - } -} - -static int byte2trans(unsigned char byte, unsigned char sendbuffer[], int size) -{ - int i; - - if (size != 8) - return -1; - for (i = 7; i >= 0; i--) - sendbuffer[7-i] = (byte & (1 << i)) ? RDS_DATAMASK : 0; - sendbuffer[0] |= RDS_CLOCKMASK; - - return 0; -} - -static int trans2byte(unsigned char buffer[], int size) -{ - int i; - unsigned char byte=0; - - if (size != 8) - return -1; - for (i = 7; i >= 0; i--) - byte |= ((buffer[7-i] & RDS_DATAMASK) ? 1 : 0) << i; - - return byte; -} - -static int trans2data(unsigned char readbuffer[], int readsize, unsigned char data[], int datasize) -{ - int i,j; - - if (readsize != datasize*8) - return -1; - for (i = 0; i < datasize; i++) - if ((j=trans2byte(&readbuffer[i*8], 8)) < 0) - return -1; - else - data[i]=j; - return 0; -} - -static int rds_waitread(void) -{ - unsigned char byte; - int i=2000; - - do { - byte=inb(RDS_REGISTER); - if ((byte & WATCHMASK) != WATCHMASK) - printk("aci-rds: Hidden information discoverd!\n"); - i--; - } - while ((byte & RDS_BUSYMASK) && i); - - if (i) { -#if DEBUG - printk("rds_waitread()"); - print_matrix(&byte, 1); -#endif - return (byte); - } else { - printk("aci-rds: rds_waitread() timeout...\n"); - return -1; - } -} - -/* dont use any ..._nowait() function if you are not sure what you do... */ - -static inline void rds_rawwrite_nowait(unsigned char byte) -{ -#if DEBUG - printk("rds_rawwrite()"); - print_matrix(&byte, 1); -#endif - outb(byte, RDS_REGISTER); -} - -static int rds_rawwrite(unsigned char byte) -{ - if (rds_waitread() >= 0) { - rds_rawwrite_nowait(byte); - return 0; - } else - return -1; -} - -static int rds_write(unsigned char cmd) -{ - unsigned char sendbuffer[8]; - int i; - - if (byte2trans(cmd, sendbuffer, 8) != 0){ - return -1; - } else { - for (i=0; i<8; i++) { - rds_rawwrite(sendbuffer[i]); - } - } - return 0; -} - -static int rds_readcycle_nowait(void) -{ - rds_rawwrite_nowait(0); - return rds_waitread(); -} - -static int rds_readcycle(void) -{ - if (rds_rawwrite(0) < 0) - return -1; - return rds_waitread(); -} - -static int rds_read(unsigned char databuffer[], int datasize) -{ - -#define READSIZE (8*datasize) - - int i,j; - unsigned char* readbuffer; - - if (!datasize) /* nothing to read */ - return 0; - - /* to be able to use rds_readcycle_nowait() - I have to readwait() here */ - if (rds_waitread() < 0) - return -1; - - if ((readbuffer=kmalloc(READSIZE, GFP_KERNEL)) == 0) { - printk("aci-rds: Out of memory...\n"); - return -ENOMEM; - } else { - if (signal_pending(current)) { - kfree(readbuffer); - return -EINTR; - } - } - - for (i=0; i< READSIZE; i++) - if((j=rds_readcycle_nowait()) < 0) { - kfree(readbuffer); - return -1; - } else - readbuffer[i]=j; - if (trans2data(readbuffer, READSIZE, databuffer, datasize) < 0) { - kfree(readbuffer); - return -1; - } - kfree(readbuffer); - return 0; -} - -static int rds_ack(void) -{ - int i=rds_readcycle(); - - if (i < 0) - return -1; - if (i & RDS_DATAMASK) { - return 0; /* ACK */ - } else { - return 1; /* NACK */ - } -} - -int aci_rds_cmd(unsigned char cmd, unsigned char databuffer[], int datasize) -{ - int ret; - - if (down_interruptible(&aci_rds_sem)) - return -EINTR; - - if (rds_write(cmd)) - ret = -2; - - /* RDS_RESET doesn't need further processing */ - if (cmd!=RDS_RESET && (rds_ack() || rds_read(databuffer, datasize))) - ret = -1; - else - ret = 0; - - up(&aci_rds_sem); - - return ret; -} - -int __init attach_aci_rds(void) -{ - init_MUTEX(&aci_rds_sem); - return 0; -} - -void __exit unload_aci_rds(void) -{ -} diff -u --recursive --new-file v2.4.5/linux/drivers/media/video/bttv-driver.c linux/drivers/media/video/bttv-driver.c --- v2.4.5/linux/drivers/media/video/bttv-driver.c Sat May 19 17:43:06 2001 +++ linux/drivers/media/video/bttv-driver.c Wed Jun 20 11:10:27 2001 @@ -2812,8 +2812,7 @@ /* disable PCI bus-mastering */ pci_read_config_byte(btv->dev, PCI_COMMAND, &command); - /* Should this be &=~ ?? */ - command&=~PCI_COMMAND_MASTER; + command &= ~PCI_COMMAND_MASTER; pci_write_config_byte(btv->dev, PCI_COMMAND, command); /* unmap and free memory */ diff -u --recursive --new-file v2.4.5/linux/drivers/media/video/i2c-parport.c linux/drivers/media/video/i2c-parport.c --- v2.4.5/linux/drivers/media/video/i2c-parport.c Wed Jul 12 16:24:33 2000 +++ linux/drivers/media/video/i2c-parport.c Wed Jun 27 17:10:55 2001 @@ -74,6 +74,10 @@ { struct parport_i2c_bus *b = kmalloc(sizeof(struct parport_i2c_bus), GFP_KERNEL); + if (!b) { + printk(KERN_ERR "i2c_parport: Memory allocation failed. Not attaching.\n"); + return; + } b->i2c = parport_i2c_bus_template; b->i2c.data = parport_get_port (port); strncpy(b->i2c.name, port->name, 32); diff -u --recursive --new-file v2.4.5/linux/drivers/media/video/planb.c linux/drivers/media/video/planb.c --- v2.4.5/linux/drivers/media/video/planb.c Sat May 19 17:43:06 2001 +++ linux/drivers/media/video/planb.c Wed Jun 27 17:10:55 2001 @@ -50,6 +50,7 @@ #include #include #include +#include #include "planb.h" #include "saa7196.h" @@ -326,41 +327,14 @@ /* misc. supporting functions */ /******************************/ -static void __planb_wait(struct planb *pb) -{ - DECLARE_WAITQUEUE(wait, current); - - add_wait_queue(&pb->lockq, &wait); -repeat: - set_current_state(TASK_UNINTERRUPTIBLE); - if (pb->lock) { - schedule(); - goto repeat; - } - remove_wait_queue(&pb->lockq, &wait); - current->state = TASK_RUNNING; -} - -static inline void planb_wait(struct planb *pb) -{ - DEBUG("PlanB: planb_wait\n"); - if(pb->lock) - __planb_wait(pb); -} - static inline void planb_lock(struct planb *pb) { - DEBUG("PlanB: planb_lock\n"); - if(pb->lock) - __planb_wait(pb); - pb->lock = 1; + down(&pb->lock); } static inline void planb_unlock(struct planb *pb) { - DEBUG("PlanB: planb_unlock\n"); - pb->lock = 0; - wake_up(&pb->lockq); + up(&pb->lock); } /***************/ @@ -2098,7 +2072,7 @@ pb->tab_size = PLANB_MAXLINES + 40; pb->suspend = 0; pb->lock = 0; - init_waitqueue_head(&pb->lockq); + init_MUTEX(&pb->lock); pb->ch1_cmd = 0; pb->ch2_cmd = 0; pb->mask = 0; diff -u --recursive --new-file v2.4.5/linux/drivers/media/video/planb.h linux/drivers/media/video/planb.h --- v2.4.5/linux/drivers/media/video/planb.h Wed Apr 12 09:38:53 2000 +++ linux/drivers/media/video/planb.h Wed Jun 27 17:10:55 2001 @@ -174,8 +174,7 @@ int user; unsigned int tab_size; int maxlines; - int lock; - wait_queue_head_t lockq; + struct semaphore lock; unsigned int irq; /* interrupt number */ volatile unsigned int intr_mask; diff -u --recursive --new-file v2.4.5/linux/drivers/media/video/tuner.c linux/drivers/media/video/tuner.c --- v2.4.5/linux/drivers/media/video/tuner.c Mon Feb 19 14:43:36 2001 +++ linux/drivers/media/video/tuner.c Tue Jun 12 11:06:54 2001 @@ -558,6 +558,7 @@ #endif default: /* nothing */ + break; } return 0; diff -u --recursive --new-file v2.4.5/linux/drivers/media/video/videodev.c linux/drivers/media/video/videodev.c --- v2.4.5/linux/drivers/media/video/videodev.c Sat May 19 18:13:15 2001 +++ linux/drivers/media/video/videodev.c Wed Jun 27 17:10:55 2001 @@ -373,6 +373,8 @@ return; p = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, video_dev_proc_entry); + if (!p) + return; p->data = vfd; p->read_proc = videodev_proc_read; diff -u --recursive --new-file v2.4.5/linux/drivers/media/video/zr36120.c linux/drivers/media/video/zr36120.c --- v2.4.5/linux/drivers/media/video/zr36120.c Mon May 21 17:06:00 2001 +++ linux/drivers/media/video/zr36120.c Wed Jun 27 17:10:55 2001 @@ -1025,7 +1025,7 @@ v.norm=VIDEO_MODE_PAL; #endif /* too many inputs? no decoder -> no channels */ - if (!ztv->have_decoder || v.channel >= ztv->card->video_inputs) + if (!ztv->have_decoder || v.channel < 0 || v.channel >= ztv->card->video_inputs) return -EINVAL; /* now determine the name of the channel */ diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/Config.in linux/drivers/mtd/Config.in --- v2.4.5/linux/drivers/mtd/Config.in Mon Dec 11 14:57:58 2000 +++ linux/drivers/mtd/Config.in Wed Jun 27 14:06:00 2001 @@ -1,5 +1,5 @@ -# $Id: No. :) $ +# $Id: Config.in,v 1.66 2001/05/07 21:00:43 dwmw2 Exp $ mainmenu_option next_comment comment 'Memory Technology Devices (MTD)' @@ -11,72 +11,30 @@ if [ "$CONFIG_MTD_DEBUG" = "y" ]; then int ' Debugging verbosity (0 = quiet, 3 = noisy)' CONFIG_MTD_DEBUG_VERBOSE 0 fi - -comment 'Disk-On-Chip Device Drivers' - dep_tristate ' M-Systems Disk-On-Chip 1000' CONFIG_MTD_DOC1000 $CONFIG_MTD - dep_tristate ' M-Systems Disk-On-Chip 2000 and Millennium' CONFIG_MTD_DOC2000 $CONFIG_MTD - dep_tristate ' M-Systems Disk-On-Chip Millennium-only alternative driver' CONFIG_MTD_DOC2001 $CONFIG_MTD - if [ "$CONFIG_MTD_DOC2001" = "y" -o "$CONFIG_MTD_DOC2000" = "y" ]; then - define_tristate CONFIG_MTD_DOCPROBE y - else - if [ "$CONFIG_MTD_DOC2001" = "m" -o "$CONFIG_MTD_DOC2000" = "m" ]; then - define_tristate CONFIG_MTD_DOCPROBE m - else - define_tristate CONFIG_MTD_DOCPROBE n - fi - fi - if [ "$CONFIG_MTD_DOCPROBE" = "y" -o "$CONFIG_MTD_DOCPROBE" = "m" ]; then - hex ' Physical address of DiskOnChip' CONFIG_MTD_DOCPROBE_ADDRESS 0x0000 - bool ' Probe high addresses' CONFIG_MTD_DOCPROBE_HIGH - bool ' Probe for 0x55 0xAA BIOS Extension Signature' CONFIG_MTD_DOCPROBE_55AA - fi - -comment 'RAM/ROM Device Drivers' - dep_tristate ' Use extra onboard system memory as MTD device' CONFIG_MTD_SLRAM $CONFIG_MTD - dep_tristate ' Ramix PMC551 PCI Mezzanine ram card support' CONFIG_MTD_PMC551 $CONFIG_MTD $CONFIG_PCI - if [ "$CONFIG_MTD_PMC551" != "n" ]; then - bool ' PMC551 256M DRAM Bugfix' CONFIG_MTD_PMC551_BUGFIX - bool ' PMC551 Debugging' CONFIG_MTD_PMC551_DEBUG - fi - dep_tristate ' Debugging RAM test driver' CONFIG_MTD_MTDRAM $CONFIG_MTD - if [ "$CONFIG_MTD_MTDRAM" != "n" ]; then - int 'Device size in kB' CONFIG_MTDRAM_TOTAL_SIZE 4096 - int 'Size of the erase sectors in kB' CONFIG_MTDRAM_ERASE_SIZE 128 - fi - -comment 'Linearly Mapped Flash Device Drivers' - dep_tristate ' Common Flash Interface (CFI) support' CONFIG_MTD_CFI $CONFIG_MTD - dep_tristate ' CFI support for Intel/Sharp Extended Command Set chips' CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_CFI - dep_tristate ' CFI support for AMD/Fujitsu Standard Command Set chips' CONFIG_MTD_CFI_AMDSTD $CONFIG_MTD_CFI - dep_tristate ' Support for RAM chips in bus mapping' CONFIG_MTD_RAM $CONFIG_MTD - dep_tristate ' Support for ROM chips in bus mapping' CONFIG_MTD_ROM $CONFIG_MTD - -# These will later become config-options -define_bool CONFIG_MTD_JEDEC n - - dep_tristate ' Flash chip mapping in physical memory' CONFIG_MTD_PHYSMAP $CONFIG_MTD_CFI - if [ "$CONFIG_MTD_PHYSMAP" = "y" -o "$CONFIG_MTD_PHYSMAP" = "m" ]; then - hex ' Physical start location of flash chip mapping' CONFIG_MTD_PHYSMAP_START 0x8000000 - hex ' Physical length of flash chip mapping' CONFIG_MTD_PHYSMAP_LEN 0x4000000 - int ' Bus width in octets' CONFIG_MTD_PHYSMAP_BUSWIDTH 2 + dep_tristate ' MTD partitioning support' CONFIG_MTD_PARTITIONS $CONFIG_MTD + dep_tristate ' RedBoot partition table parsing' CONFIG_MTD_REDBOOT_PARTS $CONFIG_MTD_PARTITIONS + dep_tristate ' Compaq bootldr partition table parsing' CONFIG_MTD_BOOTLDR_PARTS $CONFIG_MTD_PARTITIONS + +comment 'User Modules And Translation Layers' + dep_tristate ' Direct char device access to MTD devices' CONFIG_MTD_CHAR $CONFIG_MTD + dep_tristate ' Caching block device access to MTD devices' CONFIG_MTD_BLOCK $CONFIG_MTD + if [ "$CONFIG_MTD_BLOCK" = "n" -o "$CONFIG_MTD_BLOCK" = "m" ]; then + dep_tristate ' Readonly block device access to MTD devices' CONFIG_MTD_BLOCK_RO $CONFIG_MTD fi - -comment 'Drivers for chip mappings' - dep_tristate ' Flash chip mapping on Mixcom piggyback card' CONFIG_MTD_MIXMEM $CONFIG_MTD_JEDEC - dep_tristate ' Flash chip mapping on Nora' CONFIG_MTD_NORA $CONFIG_MTD_CFI - dep_tristate ' Flash chip mapping on Octagon 5066 SBC' CONFIG_MTD_OCTAGON $CONFIG_MTD_JEDEC - dep_tristate ' Flash chip mapping on Photron PNC-2000' CONFIG_MTD_PNC2000 $CONFIG_MTD_CFI - dep_tristate ' Flash chip mapping on RPXLite PPC board' CONFIG_MTD_RPXLITE $CONFIG_MTD_CFI - dep_tristate ' Flash chip mapping on Tempustech VMAX SBC301' CONFIG_MTD_VMAX $CONFIG_MTD_JEDEC - -comment 'User modules and translation layers for MTD devices' - dep_tristate ' Direct chardevice access to MTD devices' CONFIG_MTD_CHAR $CONFIG_MTD - dep_tristate ' Caching blockdevice access to MTD devices' CONFIG_MTD_BLOCK $CONFIG_MTD dep_tristate ' FTL (Flash Translation Layer) support' CONFIG_FTL $CONFIG_MTD dep_tristate ' NFTL (NAND Flash Translation Layer) support' CONFIG_NFTL $CONFIG_MTD if [ "$CONFIG_NFTL" = "y" -o "$CONFIG_NFTL" = "m" ]; then bool ' Write support for NFTL (BETA)' CONFIG_NFTL_RW fi + + source drivers/mtd/chips/Config.in + + source drivers/mtd/maps/Config.in + + source drivers/mtd/devices/Config.in + + source drivers/mtd/nand/Config.in + fi endmenu diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/Makefile linux/drivers/mtd/Makefile --- v2.4.5/linux/drivers/mtd/Makefile Fri Dec 29 14:07:22 2000 +++ linux/drivers/mtd/Makefile Tue Jun 12 10:30:27 2001 @@ -8,54 +8,57 @@ # Note 2! The CFLAGS definitions are now inherited from the # parent makes.. # -# $Id: Makefile,v 1.22 2000/07/14 08:10:52 dwmw2 Exp $ +# $Id: Makefile,v 1.60 2001/05/31 20:43:18 dwmw2 Exp $ -# Object file lists. -obj-y := +obj-y += chips/chipslink.o maps/mapslink.o \ + devices/devlink.o nand/nandlink.o obj-m := obj-n := obj- := O_TARGET := mtdlink.o -SUB_DIRS := -ALL_SUB_DIRS := -MOD_SUB_DIRS := -export-objs := mtdcore.o mtdpart.o jedec.o -list-multi := +export-objs := mtdcore.o mtdpart.o redboot.o bootldr.o +list-multi := nftl.o -# MTD devices +mod-subdirs := +subdir-y := chips maps devices nand +subdir-m := $(subdir-y) + +# *** BIG UGLY NOTE *** +# +# The shiny new inter_module_xxx has introduced yet another ugly link +# order dependency, which I'd previously taken great care to avoid. +# We now have to ensure that the chip drivers are initialised before the +# map drivers, and that the doc200[01] drivers are initialised before +# docprobe. +# +# We'll hopefully merge the doc200[01] drivers and docprobe back into +# a single driver some time soon, but the CFI drivers are going to have +# to stay like that. +# +# Urgh. +# +# dwmw2 21/11/0 + +# Core functionality. obj-$(CONFIG_MTD) += mtdcore.o -obj-$(CONFIG_MTD_DOC1000) += doc1000.o -obj-$(CONFIG_MTD_DOC2000) += doc2000.o -obj-$(CONFIG_MTD_DOC2001) += doc2001.o -obj-$(CONFIG_MTD_DOCPROBE) += docprobe.o docecc.o -obj-$(CONFIG_MTD_SLRAM) += slram.o -obj-$(CONFIG_MTD_PMC551) += pmc551.o -obj-$(CONFIG_MTD_MTDRAM) += mtdram.o - -# Chip drivers -obj-$(CONFIG_MTD_JEDEC) += jedec.o -obj-$(CONFIG_MTD_RAM) += map_ram.o -obj-$(CONFIG_MTD_ROM) += map_rom.o -obj-$(CONFIG_MTD_CFI) += cfi_probe.o -obj-$(CONFIG_MTD_CFI_INTELEXT) += cfi_cmdset_0001.o -obj-$(CONFIG_MTD_CFI_AMDSTD) += cfi_cmdset_0002.o - -# Chip mappings -obj-$(CONFIG_MTD_PHYSMAP) += physmap.o -obj-$(CONFIG_MTD_MIXMEM) += mixmem.o -obj-$(CONFIG_MTD_NORA) += nora.o -obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o -obj-$(CONFIG_MTD_PNC2000) += pnc2000.o mtdpart.o -obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o -obj-$(CONFIG_MTD_VMAX) += vmax301.o +obj-$(CONFIG_MTD_PARTITIONS) += mtdpart.o +obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o +obj-$(CONFIG_MTD_BOOTLDR_PARTS) += bootldr.o -# Users +# 'Users' - code which presents functionality to userspace. obj-$(CONFIG_MTD_CHAR) += mtdchar.o obj-$(CONFIG_MTD_BLOCK) += mtdblock.o +obj-$(CONFIG_MTD_BLOCK_RO) += mtdblock_ro.o obj-$(CONFIG_FTL) += ftl.o -obj-$(CONFIG_NFTL) += nftl.o nftlmount.o +obj-$(CONFIG_NFTL) += nftl.o + +nftl-objs := nftlcore.o nftlmount.o include $(TOPDIR)/Rules.make + +nftl.o: $(nftl-objs) + $(LD) -r -o $@ $(nftl-objs) + diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/bootldr.c linux/drivers/mtd/bootldr.c --- v2.4.5/linux/drivers/mtd/bootldr.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/bootldr.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,149 @@ +/* + * Read flash partition table from Compaq Bootloader + * + * Copyright 2001 Compaq Computer Corporation. + * + * $Id: bootldr.c,v 1.4 2001/06/02 18:24:27 nico Exp $ + * + * Use consistent with the GNU GPL is permitted, + * provided that this copyright notice is + * preserved in its entirety in all copies and derived works. + * + * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED, + * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS + * FITNESS FOR ANY PARTICULAR PURPOSE. + * + */ + +/* + * Maintainer: Jamey Hicks (jamey.hicks@compaq.com) + */ + +#include +#include + +#include +#include + +#define FLASH_PARTITION_NAMELEN 32 +enum LFR_FLAGS { + LFR_SIZE_PREFIX = 1, /* prefix data with 4-byte size */ + LFR_PATCH_BOOTLDR = 2, /* patch bootloader's 0th instruction */ + LFR_KERNEL = 4, /* add BOOTIMG_MAGIC, imgsize and VKERNEL_BASE to head of programmed region (see bootldr.c) */ + LFR_EXPAND = 8 /* expand partition size to fit rest of flash */ +}; + +typedef struct FlashRegion { + char name[FLASH_PARTITION_NAMELEN]; + unsigned long base; + unsigned long size; + enum LFR_FLAGS flags; +} FlashRegion; + +typedef struct BootldrFlashPartitionTable { + int magic; /* should be filled with 0x646c7470 (btlp) BOOTLDR_PARTITION_MAGIC */ + int npartitions; + struct FlashRegion partition[0]; +} BootldrFlashPartitionTable; + +#define BOOTLDR_MAGIC 0x646c7462 /* btld: marks a valid bootldr image */ +#define BOOTLDR_PARTITION_MAGIC 0x646c7470 /* btlp: marks a valid bootldr partition table in params sector */ + +#define BOOTLDR_MAGIC_OFFSET 0x20 /* offset 0x20 into the bootldr */ +#define BOOTCAP_OFFSET 0X30 /* offset 0x30 into the bootldr */ + +#define BOOTCAP_WAKEUP (1<<0) +#define BOOTCAP_PARTITIONS (1<<1) /* partition table stored in params sector */ +#define BOOTCAP_PARAMS_AFTER_BOOTLDR (1<<2) /* params sector right after bootldr sector(s), else in last sector */ + +int parse_bootldr_partitions(struct mtd_info *master, struct mtd_partition **pparts) +{ + struct mtd_partition *parts; + int ret, retlen, i; + int npartitions = 0; + long partition_table_offset; + long bootmagic = 0; + long bootcap = 0; + int namelen = 0; + struct BootldrFlashPartitionTable *partition_table = NULL; + char *names; + + /* verify bootldr magic */ + ret = master->read(master, BOOTLDR_MAGIC_OFFSET, sizeof(long), &retlen, (void *)&bootmagic); + if (ret) + goto out; + if (bootmagic != BOOTLDR_MAGIC) + goto out; + /* see if bootldr supports partition tables and where to find the partition table */ + ret = master->read(master, BOOTCAP_OFFSET, sizeof(long), &retlen, (void *)&bootcap); + if (ret) + goto out; + + if (!(bootcap & BOOTCAP_PARTITIONS)) + goto out; + if (bootcap & BOOTCAP_PARAMS_AFTER_BOOTLDR) + partition_table_offset = master->erasesize; + else + partition_table_offset = master->size - master->erasesize; + + printk(__FUNCTION__ ": partition_table_offset=%#lx\n", partition_table_offset); + + /* Read the partition table */ + partition_table = (struct BootldrFlashPartitionTable *)kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!partition_table) + return -ENOMEM; + ret = master->read(master, partition_table_offset, + PAGE_SIZE, &retlen, (void *)partition_table); + if (ret) + goto out; + + printk(__FUNCTION__ ": magic=%#x\n", partition_table->magic); + + /* check for partition table magic number */ + if (partition_table->magic != BOOTLDR_PARTITION_MAGIC) + goto out; + npartitions = partition_table->npartitions; + + printk(__FUNCTION__ ": npartitions=%#x\n", npartitions); + + for (i = 0; i < npartitions; i++) { + namelen += strlen(partition_table->partition[i].name) + 1; + } + + parts = kmalloc(sizeof(*parts)*npartitions + namelen, GFP_KERNEL); + if (!parts) { + ret = -ENOMEM; + goto out; + } + names = (char *)&parts[npartitions]; + memset(parts, 0, sizeof(*parts)*npartitions + namelen); + + for (i = 0; i < npartitions; i++) { + struct FlashRegion *partition = &partition_table->partition[i]; + const char *name = partition->name; + parts[i].name = names; + names += strlen(name) + 1; + strcpy(parts[i].name, name); + + if (partition->flags & LFR_EXPAND) + parts[i].size = MTDPART_SIZ_FULL; + else + parts[i].size = partition->size; + parts[i].offset = partition->base; + parts[i].mask_flags = 0; + + printk(" partition %s o=%x s=%x\n", + parts[i].name, parts[i].offset, parts[i].size); + + } + + ret = npartitions; + *pparts = parts; + + out: + if (partition_table) + kfree(partition_table); + return ret; +} + +EXPORT_SYMBOL(parse_bootldr_partitions); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/cfi_cmdset_0001.c linux/drivers/mtd/cfi_cmdset_0001.c --- v2.4.5/linux/drivers/mtd/cfi_cmdset_0001.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/mtd/cfi_cmdset_0001.c Wed Dec 31 16:00:00 1969 @@ -1,891 +0,0 @@ -/* - * Common Flash Interface support: - * Intel Extended Vendor Command Set (ID 0x0001) - * - * (C) 2000 Red Hat. GPL'd - * - * $Id: cfi_cmdset_0001.c,v 1.21 2000/07/13 10:36:14 dwmw2 Exp $ - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#if LINUX_VERSION_CODE < 0x20300 -#define set_current_state(x) current->state = (x); -#endif -static int cfi_intelext_read_1_by_16 (struct mtd_info *, loff_t, size_t, size_t *, u_char *); -static int cfi_intelext_write_1_by_16(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); -static int cfi_intelext_erase_1_by_16 (struct mtd_info *, struct erase_info *); -static void cfi_intelext_sync (struct mtd_info *); -static int cfi_intelext_suspend (struct mtd_info *); -static void cfi_intelext_resume (struct mtd_info *); - -static void cfi_intelext_destroy(struct mtd_info *); - -static void cfi_cmdset_0001(struct map_info *, int, unsigned long); - -static struct mtd_info *cfi_intelext_setup (struct map_info *); - -static const char im_name[] = "cfi_cmdset_0001"; - -/* This routine is made available to other mtd code via - * inter_module_register. It must only be accessed through - * inter_module_get which will bump the use count of this module. The - * addresses passed back in cfi are valid as long as the use count of - * this module is non-zero, i.e. between inter_module_get and - * inter_module_put. Keith Owens 29 Oct 2000. - */ -static void cfi_cmdset_0001(struct map_info *map, int primary, unsigned long base) -{ - struct cfi_private *cfi = map->fldrv_priv; - int i; - struct cfi_pri_intelext *extp; - - __u16 adr = primary?cfi->cfiq.P_ADR:cfi->cfiq.A_ADR; - - printk(" Intel/Sharp Extended Query Table at 0x%4.4X\n", adr); - - if (!adr) - return; - - /* Switch it into Query Mode */ - switch(map->buswidth) { - case 1: - map->write8(map, 0x98, 0x55); - break; - case 2: - map->write16(map, 0x9898, 0xaa); - break; - case 4: - map->write32(map, 0x98989898, 0x154); - break; - } - - extp = kmalloc(sizeof(*extp), GFP_KERNEL); - if (!extp) { - printk("Failed to allocate memory\n"); - return; - } - - /* Read in the Extended Query Table */ - for (i=0; iread8(map, (base+((adr+i)*map->buswidth))); - } - - if (extp->MajorVersion != '1' || - (extp->MinorVersion < '0' || extp->MinorVersion > '2')) { - printk(" Unknown IntelExt Extended Query version %c.%c.\n", - extp->MajorVersion, extp->MinorVersion); - kfree(extp); - return; - } - - /* Do some byteswapping if necessary */ - extp->FeatureSupport = le32_to_cpu(extp->FeatureSupport); - extp->BlkStatusRegMask = le32_to_cpu(extp->BlkStatusRegMask); - - - /* Tell the user about it in lots of lovely detail */ -#if 0 - printk(" Feature/Command Support: %4.4X\n", extp->FeatureSupport); - printk(" - Chip Erase: %s\n", extp->FeatureSupport&1?"supported":"unsupported"); - printk(" - Suspend Erase: %s\n", extp->FeatureSupport&2?"supported":"unsupported"); - printk(" - Suspend Program: %s\n", extp->FeatureSupport&4?"supported":"unsupported"); - printk(" - Legacy Lock/Unlock: %s\n", extp->FeatureSupport&8?"supported":"unsupported"); - printk(" - Queued Erase: %s\n", extp->FeatureSupport&16?"supported":"unsupported"); - printk(" - Instant block lock: %s\n", extp->FeatureSupport&32?"supported":"unsupported"); - printk(" - Protection Bits: %s\n", extp->FeatureSupport&64?"supported":"unsupported"); - printk(" - Page-mode read: %s\n", extp->FeatureSupport&128?"supported":"unsupported"); - printk(" - Synchronous read: %s\n", extp->FeatureSupport&256?"supported":"unsupported"); - for (i=9; i<32; i++) { - if (extp->FeatureSupport & (1<SuspendCmdSupport); - printk(" - Program after Erase Suspend: %s\n", extp->SuspendCmdSupport&1?"supported":"unsupported"); - for (i=1; i<8; i++) { - if (extp->SuspendCmdSupport & (1<BlkStatusRegMask); - printk(" - Lock Bit Active: %s\n", extp->BlkStatusRegMask&1?"yes":"no"); - printk(" - Valid Bit Active: %s\n", extp->BlkStatusRegMask&2?"yes":"no"); - for (i=2; i<16; i++) { - if (extp->BlkStatusRegMask & (1<VccOptimal >> 8, extp->VccOptimal & 0xf); - if (extp->VppOptimal) - printk(" Vpp Programming Supply Optimum Program/Erase Voltage: %d.%d V\n", - extp->VppOptimal >> 8, extp->VppOptimal & 0xf); -#endif - /* OK. We like it. Take over the control of it. */ - - /* Switch it into Read Mode */ - switch(map->buswidth) { - case 1: - map->write8(map, 0xff, 0x55); - break; - case 2: - map->write16(map, 0xffff, 0xaa); - break; - case 4: - map->write32(map, 0xffffffff, 0x154); - break; - } - - - /* If there was an old setup function, decrease its use count */ - if (cfi->cmdset_setup) - inter_module_put(cfi->im_name); - if (cfi->cmdset_priv) - kfree(cfi->cmdset_priv); - - for (i=0; i< cfi->numchips; i++) { - cfi->chips[i].word_write_time = 128; - cfi->chips[i].buffer_write_time = 128; - cfi->chips[i].erase_time = 1024; - } - - - cfi->cmdset_setup = cfi_intelext_setup; - cfi->im_name = im_name; - cfi->cmdset_priv = extp; - - return; -} - -static struct mtd_info *cfi_intelext_setup(struct map_info *map) -{ - struct cfi_private *cfi = map->fldrv_priv; - struct mtd_info *mtd; - - mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); - printk("number of CFI chips: %d\n", cfi->numchips); - - if (!mtd) { - printk("Failed to allocate memory for MTD device\n"); - kfree(cfi->cmdset_priv); - return NULL; - } - - memset(mtd, 0, sizeof(*mtd)); - mtd->priv = map; - mtd->type = MTD_NORFLASH; - mtd->erasesize = 0x20000; /* FIXME */ - /* Also select the correct geometry setup too */ - mtd->size = (1 << cfi->cfiq.DevSize) * cfi->numchips; - mtd->erase = cfi_intelext_erase_1_by_16; - mtd->read = cfi_intelext_read_1_by_16; - mtd->write = cfi_intelext_write_1_by_16; - mtd->sync = cfi_intelext_sync; - mtd->suspend = cfi_intelext_suspend; - mtd->resume = cfi_intelext_resume; - mtd->flags = MTD_CAP_NORFLASH; - map->fldrv_destroy = cfi_intelext_destroy; - mtd->name = map->name; - return mtd; -} - -static inline int do_read_1_by_16_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf) -{ - __u16 status; - unsigned long timeo = jiffies + HZ; - DECLARE_WAITQUEUE(wait, current); - - adr += chip->start; - - retry: - spin_lock_bh(chip->mutex); - - /* Check that the chip's ready to talk to us. - * Later, we can actually think about interrupting it - * if it's in FL_ERASING or FL_WRITING state. - * Not just yet, though. - */ - switch (chip->state) { -#if 0 - case FL_ERASING: - case FL_WRITING: - /* Suspend the operation, set state to FL_xxx_SUSPENDED */ -#endif - - case FL_CFI_QUERY: - case FL_JEDEC_QUERY: - case FL_READY: - map->write16(map, cpu_to_le16(0x0070), adr); - chip->state = FL_STATUS; - - case FL_STATUS: - status = le16_to_cpu(map->read16(map, adr)); - - if (!(status & (1<<7))) { - static int z=0; - /* Urgh. Chip not yet ready to talk to us. */ - if (time_after(jiffies, timeo)) { - spin_unlock_bh(chip->mutex); - printk("waiting for chip to be ready timed out in read"); - return -EIO; - } - - /* Latency issues. Drop the lock, wait a while and retry */ - spin_unlock_bh(chip->mutex); - - z++; - if ( 0 && !(z % 100 )) - printk("chip not ready yet before read. looping\n"); - - udelay(1); - - goto retry; - } - break; - - default: - printk("Waiting for chip, status = %d\n", chip->state); - - /* Stick ourselves on a wait queue to be woken when - someone changes the status */ - - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); - - spin_unlock_bh(chip->mutex); - - schedule(); - remove_wait_queue(&chip->wq, &wait); - - if(signal_pending(current)) - return -EINTR; - - - timeo = jiffies + HZ; - - goto retry; - } - - map->write16(map, cpu_to_le16(0x00ff), adr); - chip->state = FL_READY; - - map->copy_from(map, buf, adr, len); - - if (chip->state == FL_ERASE_SUSPENDED || - chip->state == FL_WRITE_SUSPENDED) { - printk("Who in hell suspended the pending operation? I didn't write that code yet!\n"); - /* Restart it and set the state accordingly */ - } - - wake_up(&chip->wq); - spin_unlock_bh(chip->mutex); - - return 0; -} - -static int cfi_intelext_read_1_by_16 (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) -{ - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; - unsigned long ofs; - int chipnum; - int ret = 0; - - /* ofs: offset within the first chip that the first read should start */ - chipnum = (from >> cfi->chipshift); - ofs = from - (chipnum << cfi->chipshift); - - *retlen = 0; - - while (len) { - unsigned long thislen; - - if (chipnum >= cfi->numchips) - break; - - if ((len + ofs -1) >> cfi->chipshift) - thislen = (1<chipshift) - ofs; - else - thislen = len; - - ret = do_read_1_by_16_onechip(map, &cfi->chips[chipnum], ofs, thislen, buf); - if (ret) - break; - - *retlen += thislen; - len -= thislen; - buf += thislen; - - ofs = 0; - chipnum++; - } - return ret; -} - -static inline int do_write_1_by_16_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, __u16 datum) -{ - __u16 status; - unsigned long timeo = jiffies + HZ; - DECLARE_WAITQUEUE(wait, current); - int z = 0; - adr += chip->start; - - retry: - spin_lock_bh(chip->mutex); - - /* Check that the chip's ready to talk to us. - * Later, we can actually think about interrupting it - * if it's in FL_ERASING state. - * Not just yet, though. - */ - switch (chip->state) { - case FL_CFI_QUERY: - case FL_JEDEC_QUERY: - case FL_READY: - map->write16(map, cpu_to_le16(0x0070), adr); - chip->state = FL_STATUS; - timeo = jiffies + HZ; - - case FL_STATUS: - status = le16_to_cpu(map->read16(map, adr)); - - if (!(status & (1<<7))) { - - /* Urgh. Chip not yet ready to talk to us. */ - if (time_after(jiffies, timeo)) { - spin_unlock_bh(chip->mutex); - printk("waiting for chip to be ready timed out in read"); - return -EIO; - } - - /* Latency issues. Drop the lock, wait a while and retry */ - spin_unlock_bh(chip->mutex); - - z++; - if ( 0 && !(z % 100 )) - printk("chip not ready yet before write. looping\n"); - - udelay(1); - - goto retry; - } - break; - - default: - printk("Waiting for chip, status = %d\n", chip->state); - - /* Stick ourselves on a wait queue to be woken when - someone changes the status */ - - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); - - spin_unlock_bh(chip->mutex); - - schedule(); - remove_wait_queue(&chip->wq, &wait); - - if(signal_pending(current)) - return -EINTR; - - timeo = jiffies + HZ; - - goto retry; - } - - map->write16(map, cpu_to_le16(0x0040), adr); - map->write16(map, datum, adr); - chip->state = FL_WRITING; - - timeo = jiffies + (HZ/2); - - spin_unlock_bh(chip->mutex); - udelay(chip->word_write_time); - spin_lock_bh(chip->mutex); - - z = 0; - while ( !( (status = le16_to_cpu(map->read16(map, adr))) & 0x80 ) ) { - - if (chip->state != FL_WRITING) { - /* Someone's suspended the write. Sleep */ - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); - - spin_unlock_bh(chip->mutex); - - schedule(); - remove_wait_queue(&chip->wq, &wait); - - if (signal_pending(current)) - return -EINTR; - - timeo = jiffies + (HZ / 2); /* FIXME */ - - spin_lock_bh(chip->mutex); - continue; - } - - /* OK Still waiting */ - if (time_after(jiffies, timeo)) { - chip->state = FL_STATUS; - spin_unlock_bh(chip->mutex); - printk("waiting for chip to be ready timed out in read"); - return -EIO; - } - - /* Latency issues. Drop the lock, wait a while and retry */ - spin_unlock_bh(chip->mutex); - - z++; - if ( 0 && !(z % 100 )) - printk("chip not ready yet after write. looping\n"); - - udelay(1); - - spin_lock_bh(chip->mutex); - continue; - } - if (!z) { - chip->word_write_time--; - if (!chip->word_write_time) - chip->word_write_time++; - } - if (z > 1) - chip->word_write_time++; - - /* Done and happy. */ - chip->state = FL_STATUS; - wake_up(&chip->wq); - spin_unlock_bh(chip->mutex); - // printk("write ret OK at %lx\n", adr); - return 0; -} - - -/* This version only uses the 'word write' instruction. We should update it - * to write using 'buffer write' if it's available - */ -static int cfi_intelext_write_1_by_16 (struct mtd_info *mtd, loff_t to , size_t len, size_t *retlen, const u_char *buf) -{ - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; - int ret = 0; - int chipnum; - unsigned long ofs; - - *retlen = 0; - chipnum = to >> cfi->chipshift; - ofs = to - (chipnum << cfi->chipshift); - - /* If it's not word-aligned, do the first byte write */ - if (ofs & 1) { -#if defined(__LITTLE_ENDIAN) - ret = do_write_1_by_16_oneword(map, &cfi->chips[chipnum], - ofs, 0xFF | (*buf << 8)); -#elif defined(__BIG_ENDIAN) - ret = do_write_1_by_16_oneword(map, &cfi->chips[chipnum], - ofs, 0xFF00 | (*buf)); -#else -#error define a sensible endianness -#endif - if (ret) - return ret; - - ofs++; - buf++; - (*retlen)++; - len--; - - if (ofs >> cfi->chipshift) { - chipnum ++; - ofs = 0; - if (chipnum == cfi->numchips) - return 0; - } - } - - while(len > 1) { - ret = do_write_1_by_16_oneword(map, &cfi->chips[chipnum], - ofs, *(__u16 *)buf); - if (ret) - return ret; - - ofs += 2; - buf += 2; - (*retlen) += 2; - len -= 2; - - if (ofs >> cfi->chipshift) { - chipnum ++; - ofs = 0; - if (chipnum == cfi->numchips) - return 0; - } - } - - if (len) { - /* Final byte to write */ -#if defined(__LITTLE_ENDIAN) - ret = do_write_1_by_16_oneword(map, &cfi->chips[chipnum], - ofs, 0xFF00 | (*buf)); -#elif defined(__BIG_ENDIAN) - ret = do_write_1_by_16_oneword(map, &cfi->chips[chipnum], - ofs, 0xFF | (*buf << 8)); -#else -#error define a sensible endianness -#endif - if (ret) - return ret; - - (*retlen)++; - } - - return 0; -} - - -static inline int do_erase_1_by_16_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr) -{ - __u16 status; - unsigned long timeo = jiffies + HZ; - DECLARE_WAITQUEUE(wait, current); - - adr += chip->start; - - retry: - spin_lock_bh(chip->mutex); - - /* Check that the chip's ready to talk to us. */ - switch (chip->state) { - case FL_CFI_QUERY: - case FL_JEDEC_QUERY: - case FL_READY: - map->write16(map, cpu_to_le16(0x0070), adr); - chip->state = FL_STATUS; - timeo = jiffies + HZ; - - case FL_STATUS: - status = le16_to_cpu(map->read16(map, adr)); - - if (!(status & (1<<7))) { - static int z=0; - /* Urgh. Chip not yet ready to talk to us. */ - if (time_after(jiffies, timeo)) { - spin_unlock_bh(chip->mutex); - printk("waiting for chip to be ready timed out in erase"); - return -EIO; - } - - /* Latency issues. Drop the lock, wait a while and retry */ - spin_unlock_bh(chip->mutex); - - z++; - if ( 0 && !(z % 100 )) - printk("chip not ready yet before erase. looping\n"); - - udelay(1); - - goto retry; - } - break; - - default: - printk("Waiting for chip, status = %d\n", chip->state); - - /* Stick ourselves on a wait queue to be woken when - someone changes the status */ - - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); - - spin_unlock_bh(chip->mutex); - - schedule(); - remove_wait_queue(&chip->wq, &wait); - - if(signal_pending(current)) - return -EINTR; - - timeo = jiffies + HZ; - - goto retry; - } - - map->write16(map, cpu_to_le16(0x0020), adr); - map->write16(map, cpu_to_le16(0x00D0), adr); - - chip->state = FL_ERASING; - - timeo = jiffies + (HZ*2); - spin_unlock_bh(chip->mutex); - schedule_timeout(HZ); - spin_lock_bh(chip->mutex); - - /* FIXME. Use a timer to check this, and return immediately. */ - /* Once the state machine's known to be working I'll do that */ - - while ( !( (status = le16_to_cpu(map->read16(map, adr))) & 0x80 ) ) { - static int z=0; - - if (chip->state != FL_ERASING) { - /* Someone's suspended the erase. Sleep */ - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); - - spin_unlock_bh(chip->mutex); - printk("erase suspended. Sleeping\n"); - - schedule(); - remove_wait_queue(&chip->wq, &wait); - - if (signal_pending(current)) - return -EINTR; - - timeo = jiffies + (HZ*2); /* FIXME */ - spin_lock_bh(chip->mutex); - continue; - } - - /* OK Still waiting */ - if (time_after(jiffies, timeo)) { - chip->state = FL_STATUS; - spin_unlock_bh(chip->mutex); - printk("waiting for erase to complete timed out."); - return -EIO; - } - - /* Latency issues. Drop the lock, wait a while and retry */ - spin_unlock_bh(chip->mutex); - - z++; - if ( 0 && !(z % 100 )) - printk("chip not ready yet after erase. looping\n"); - - udelay(1); - - spin_lock_bh(chip->mutex); - continue; - } - - /* Done and happy. */ - chip->state = FL_STATUS; - wake_up(&chip->wq); - spin_unlock_bh(chip->mutex); - //printk("erase ret OK\n"); - return 0; -} - -static int cfi_intelext_erase_1_by_16 (struct mtd_info *mtd, struct erase_info *instr) -{ - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; - unsigned long adr, len; - int chipnum, ret = 0; - - if (instr->addr & (mtd->erasesize - 1)) - return -EINVAL; - - if (instr->len & (mtd->erasesize -1)) - return -EINVAL; - - if ((instr->len + instr->addr) > mtd->size) - return -EINVAL; - - chipnum = instr->addr >> cfi->chipshift; - adr = instr->addr - (chipnum << cfi->chipshift); - len = instr->len; - - while(len) { - ret = do_erase_1_by_16_oneblock(map, &cfi->chips[chipnum], adr); - - if (ret) - return ret; - - adr += mtd->erasesize; - len -= mtd->erasesize; - - if (adr >> cfi->chipshift) { - adr = 0; - chipnum++; - - if (chipnum >= cfi->numchips) - break; - } - } - - if (instr->callback) - instr->callback(instr); - - return 0; -} - - - -static void cfi_intelext_sync (struct mtd_info *mtd) -{ - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; - int i; - struct flchip *chip; - int ret = 0; - DECLARE_WAITQUEUE(wait, current); - - for (i=0; !ret && inumchips; i++) { - chip = &cfi->chips[i]; - - retry: - spin_lock_bh(chip->mutex); - - switch(chip->state) { - case FL_READY: - case FL_STATUS: - case FL_CFI_QUERY: - case FL_JEDEC_QUERY: - chip->oldstate = chip->state; - chip->state = FL_SYNCING; - /* No need to wake_up() on this state change - - * as the whole point is that nobody can do anything - * with the chip now anyway. - */ - spin_unlock_bh(chip->mutex); - break; - - default: - /* Not an idle state */ - add_wait_queue(&chip->wq, &wait); - - spin_unlock_bh(chip->mutex); - schedule(); - - remove_wait_queue(&chip->wq, &wait); - - goto retry; - } - } - - /* Unlock the chips again */ - - for (i--; i >=0; i--) { - chip = &cfi->chips[i]; - - spin_lock_bh(chip->mutex); - - if (chip->state == FL_SYNCING) { - chip->state = chip->oldstate; - wake_up(&chip->wq); - } - spin_unlock_bh(chip->mutex); - } -} - - -static int cfi_intelext_suspend(struct mtd_info *mtd) -{ - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; - int i; - struct flchip *chip; - int ret = 0; - - for (i=0; !ret && inumchips; i++) { - chip = &cfi->chips[i]; - - spin_lock_bh(chip->mutex); - - switch(chip->state) { - case FL_READY: - case FL_STATUS: - case FL_CFI_QUERY: - case FL_JEDEC_QUERY: - chip->oldstate = chip->state; - chip->state = FL_PM_SUSPENDED; - /* No need to wake_up() on this state change - - * as the whole point is that nobody can do anything - * with the chip now anyway. - */ - break; - - default: - ret = -EAGAIN; - break; - } - spin_unlock_bh(chip->mutex); - } - - /* Unlock the chips again */ - - for (i--; i >=0; i--) { - chip = &cfi->chips[i]; - - spin_lock_bh(chip->mutex); - - if (chip->state == FL_PM_SUSPENDED) { - chip->state = chip->oldstate; - wake_up(&chip->wq); - } - spin_unlock_bh(chip->mutex); - } - - return ret; -} - -static void cfi_intelext_resume(struct mtd_info *mtd) -{ - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; - int i; - struct flchip *chip; - - for (i=0; inumchips; i++) { - - chip = &cfi->chips[i]; - - spin_lock_bh(chip->mutex); - - if (chip->state == FL_PM_SUSPENDED) { - chip->state = chip->oldstate; - wake_up(&chip->wq); - } - else - printk("Argh. Chip not in PM_SUSPENDED state upon resume()\n"); - - spin_unlock_bh(chip->mutex); - } -} - -static void cfi_intelext_destroy(struct mtd_info *mtd) -{ - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; - kfree(cfi->cmdset_priv); - inter_module_put(cfi->im_name); - kfree(cfi); -} - - -static int __init cfi_intelext_init(void) -{ - inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0001); - return 0; -} - -static void __exit cfi_intelext_exit(void) -{ - inter_module_unregister(im_name); -} - -module_init(cfi_intelext_init); -module_exit(cfi_intelext_exit); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/cfi_cmdset_0002.c linux/drivers/mtd/cfi_cmdset_0002.c --- v2.4.5/linux/drivers/mtd/cfi_cmdset_0002.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/mtd/cfi_cmdset_0002.c Wed Dec 31 16:00:00 1969 @@ -1,628 +0,0 @@ -/* - * Common Flash Interface support: - * AMD & Fujitsu Extended Vendor Command Set (ID 0x0002) - * - * Copyright (C) 2000 Crossnet Co. - * - * This code is GPL - * - * $Id: cfi_cmdset_0002.c,v 1.1 2000/07/11 12:32:09 dwmw2 Exp $ - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#if LINUX_VERSION_CODE < 0x20300 -#define set_current_state(x) current->state = (x); -#endif - -static int cfi_amdext_read_2_by_16 (struct mtd_info *, loff_t, size_t, size_t *, u_char *); -static int cfi_amdext_write_2_by_16(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); -static int cfi_amdext_erase_2_by_16 (struct mtd_info *, struct erase_info *); -static void cfi_amdext_sync (struct mtd_info *); -static int cfi_amdext_suspend (struct mtd_info *); -static void cfi_amdext_resume (struct mtd_info *); - -static void cfi_amdext_destroy(struct mtd_info *); - -static void cfi_cmdset_0002(struct map_info *, int, unsigned long); - -static struct mtd_info *cfi_amdext_setup (struct map_info *); - -static const char im_name[] = "cfi_cmdset_0002"; - -static void cfi_cmdset_0002(struct map_info *map, int primary, unsigned long base) -{ - struct cfi_private *cfi = map->fldrv_priv; - int i; -// struct cfi_pri_intelext *extp; - - __u16 adr = primary?cfi->cfiq.P_ADR:cfi->cfiq.A_ADR; - - printk(" Amd/Fujitsu Extended Query Table at 0x%4.4X\n", adr); - - - /* If there was an old setup function, decrease its use count */ - if (cfi->cmdset_setup) - inter_module_put(cfi->im_name); - if (cfi->cmdset_priv) - kfree(cfi->cmdset_priv); - - for (i=0; i< cfi->numchips; i++) { - cfi->chips[i].word_write_time = 128; - cfi->chips[i].buffer_write_time = 128; - cfi->chips[i].erase_time = 1024; - } - - - cfi->cmdset_setup = cfi_amdext_setup; - cfi->im_name = im_name; -// cfi->cmdset_priv = extp; - - return; -} - -static struct mtd_info *cfi_amdext_setup(struct map_info *map) -{ - struct cfi_private *cfi = map->fldrv_priv; - struct mtd_info *mtd; - - mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); - printk("number of CFI chips: %d\n", cfi->numchips); - - if (!mtd) { - printk("Failed to allocate memory for MTD device\n"); - kfree(cfi->cmdset_priv); - return NULL; - } - - memset(mtd, 0, sizeof(*mtd)); - mtd->priv = map; - mtd->type = MTD_NORFLASH; - mtd->erasesize = 0x20000; /* FIXME */ - /* Also select the correct geometry setup too */ - mtd->size = (1 << cfi->cfiq.DevSize) * cfi->numchips * cfi->interleave; - mtd->erase = cfi_amdext_erase_2_by_16; - mtd->read = cfi_amdext_read_2_by_16; - mtd->write = cfi_amdext_write_2_by_16; - mtd->sync = cfi_amdext_sync; - mtd->suspend = cfi_amdext_suspend; - mtd->resume = cfi_amdext_resume; - mtd->flags = MTD_CAP_NORFLASH; - map->fldrv_destroy = cfi_amdext_destroy; - mtd->name = map->name; - return mtd; -} - -static inline int do_read_2_by_16_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf) -{ - DECLARE_WAITQUEUE(wait, current); - unsigned long timeo = jiffies + HZ; - - retry: - spin_lock_bh(chip->mutex); - - if (chip->state != FL_READY){ -printk("Waiting for chip to read, status = %d\n", chip->state); - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); - - spin_unlock_bh(chip->mutex); - - schedule(); - remove_wait_queue(&chip->wq, &wait); - - if(signal_pending(current)) - return -EINTR; - - timeo = jiffies + HZ; - - goto retry; - } - - adr += chip->start; - -// map->write32(map, cpu_to_le32(0x00F000F0), adr); - - chip->state = FL_READY; - - map->copy_from(map, buf, adr, len); - - wake_up(&chip->wq); - spin_unlock_bh(chip->mutex); - - return 0; -} - -static int cfi_amdext_read_2_by_16 (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) -{ - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; - unsigned long ofs; - int chipnum; - int ret = 0; - - /* ofs: offset within the first chip that the first read should start */ - - chipnum = (from >> cfi->chipshift); - chipnum /= (cfi->interleave); - ofs = from - (chipnum << cfi->chipshift) * (cfi->interleave); - - *retlen = 0; - - while (len) { - unsigned long thislen; - - if (chipnum >= cfi->numchips) - break; - - if (((len + ofs -1) >> cfi->chipshift) / (cfi->interleave)) - thislen = (1<chipshift) * (cfi->interleave) - ofs; - else - thislen = len; - - ret = do_read_2_by_16_onechip(map, &cfi->chips[chipnum], ofs, thislen, buf); - if (ret) - break; - - *retlen += thislen; - len -= thislen; - buf += thislen; - - ofs = 0; - chipnum++; - } - return ret; -} - -static inline int do_write_2_by_16_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, __u32 datum) -{ - unsigned long timeo = jiffies + HZ; - unsigned int Last[4]; - unsigned long Count = 0; - DECLARE_WAITQUEUE(wait, current); - int ret = 0; - - retry: - spin_lock_bh(chip->mutex); - - if (chip->state != FL_READY){ -printk("Waiting for chip to write, status = %d\n", chip->state); - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); - - spin_unlock_bh(chip->mutex); - - schedule(); - remove_wait_queue(&chip->wq, &wait); -printk("Wake up to write:\n"); - if(signal_pending(current)) - return -EINTR; - - timeo = jiffies + HZ; - - goto retry; - } - - chip->state = FL_WRITING; - - adr += chip->start; - - map->write32(map, cpu_to_le32(0x00AA00AA), 0x555 *4); - map->write32(map, cpu_to_le32(0x00550055), 0x2AA *4); - map->write32(map, cpu_to_le32(0x00A000A0), 0x555 *4); - map->write32(map, cpu_to_le32(datum), adr); - - spin_unlock_bh(chip->mutex); - udelay(chip->word_write_time); - spin_lock_bh(chip->mutex); - - Last[0] = map->read32(map, adr); - Last[1] = map->read32(map, adr); - Last[2] = map->read32(map, adr); - - for (Count = 3; Last[(Count - 1) % 4] != Last[(Count - 2) % 4] && Count < 10000; Count++){ - udelay(10); - - Last[Count % 4] = map->read32(map, adr); - } - - if (Last[(Count - 1) % 4] != datum){ - map->write32(map, cpu_to_le32(0x00F000F0), adr); - ret = -EIO; - } - - chip->state = FL_READY; - wake_up(&chip->wq); - spin_unlock_bh(chip->mutex); - - return ret; -} - - -static int cfi_amdext_write_2_by_16 (struct mtd_info *mtd, loff_t to , size_t len, size_t *retlen, const u_char *buf) -{ - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; - int ret = 0; - int chipnum; - unsigned long ofs; - - *retlen = 0; - - chipnum = (to >> cfi->chipshift); - chipnum /= cfi->interleave; - ofs = to - (chipnum << cfi->chipshift) * cfi->interleave; - - while(len > 3) { - - ret = do_write_2_by_16_oneword(map, &cfi->chips[chipnum], - ofs, *(__u32 *)buf); - if (ret) - return ret; - - ofs += 4; - buf += 4; - (*retlen) += 4; - len -= 4; - - if ((ofs >> cfi->chipshift) / cfi->interleave) { - chipnum ++; - ofs = 0; - if (chipnum == cfi->numchips) - return 0; - } - } - - if (len) { - unsigned int tmp; - - /* Final byte to write */ -#if defined(__LITTLE_ENDIAN) - tmp = map->read32(map, ofs); - - tmp = 0xffffffff >> (len*8); - tmp = tmp << (len*8); - - tmp |= *(__u32 *)(buf); - - ret = do_write_2_by_16_oneword(map, &cfi->chips[chipnum], - ofs, tmp); - -#elif defined(__BIG_ENDIAN) -#error not support big endian yet -#else -#error define a sensible endianness -#endif - - if (ret) - return ret; - - (*retlen)+=len; - } - - return 0; -} - - -static inline int do_erase_2_by_16_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr) -{ - unsigned int status; - unsigned long timeo = jiffies + HZ; - DECLARE_WAITQUEUE(wait, current); - - retry: - spin_lock_bh(chip->mutex); - - if (chip->state != FL_READY){ - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); - - spin_unlock_bh(chip->mutex); - - schedule(); - remove_wait_queue(&chip->wq, &wait); - - if(signal_pending(current)) - return -EINTR; - - timeo = jiffies + HZ; - - goto retry; - } - - chip->state = FL_ERASING; - - adr += chip->start; - - map->write32(map, cpu_to_le32(0x00AA00AA), 0x555 *4); - map->write32(map, cpu_to_le32(0x00550055), 0x2AA *4); - map->write32(map, cpu_to_le32(0x00800080), 0x555 *4); - map->write32(map, cpu_to_le32(0x00AA00AA), 0x555 *4); - map->write32(map, cpu_to_le32(0x00550055), 0x2AA *4); - map->write32(map, cpu_to_le32(0x00300030), adr); - - - timeo = jiffies + (HZ*20); - - spin_unlock_bh(chip->mutex); - schedule_timeout(HZ); - spin_lock_bh(chip->mutex); - - /* FIXME. Use a timer to check this, and return immediately. */ - /* Once the state machine's known to be working I'll do that */ - - while ( ( (status = le32_to_cpu(map->read32(map, 0x00))) & 0x80808080 ) != 0x80808080 ) { - static int z=0; - - if (chip->state != FL_ERASING) { - /* Someone's suspended the erase. Sleep */ - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); - - spin_unlock_bh(chip->mutex); - printk("erase suspended. Sleeping\n"); - - schedule(); - remove_wait_queue(&chip->wq, &wait); - - if (signal_pending(current)) - return -EINTR; - - timeo = jiffies + (HZ*2); /* FIXME */ - spin_lock_bh(chip->mutex); - continue; - } - - /* OK Still waiting */ - if (time_after(jiffies, timeo)) { - chip->state = FL_READY; - spin_unlock_bh(chip->mutex); - printk("waiting for erase to complete timed out."); - return -EIO; - } - - /* Latency issues. Drop the lock, wait a while and retry */ - spin_unlock_bh(chip->mutex); - - z++; - if ( 0 && !(z % 100 )) - printk("chip not ready yet after erase. looping\n"); - - udelay(1); - - spin_lock_bh(chip->mutex); - continue; - } - - /* Done and happy. */ - chip->state = FL_READY; - wake_up(&chip->wq); - spin_unlock_bh(chip->mutex); - printk("erase ret OK\n"); - return 0; -} - -static int cfi_amdext_erase_2_by_16 (struct mtd_info *mtd, struct erase_info *instr) -{ - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; - unsigned long adr, len; - int chipnum, ret = 0; - -//printk("erase : 0x%x 0x%x 0x%x\n", instr->addr, instr->len, mtd->size); - - if (instr->addr & (mtd->erasesize - 1)) - return -EINVAL; - - if (instr->len & (mtd->erasesize -1)) - return -EINVAL; - - if ((instr->len + instr->addr) > mtd->size) - return -EINVAL; - - chipnum = instr->addr >> cfi->chipshift; - chipnum /= cfi->interleave; - adr = instr->addr - (chipnum << cfi->chipshift) * (cfi->interleave); - len = instr->len; - - printk("erase : 0x%lx 0x%lx 0x%x 0x%lx\n", adr, len, chipnum, mtd->size); - - while(len) { -//printk("erase : 0x%x 0x%x 0x%x 0x%x\n", chipnum, adr, len, cfi->chipshift); - ret = do_erase_2_by_16_oneblock(map, &cfi->chips[chipnum], adr); - - if (ret) - return ret; - - adr += mtd->erasesize; - len -= mtd->erasesize; - - if ((adr >> cfi->chipshift) / (cfi->interleave)) { - adr = 0; - chipnum++; - - if (chipnum >= cfi->numchips) - break; - } - } - - if (instr->callback) - instr->callback(instr); - - return 0; -} - - - -static void cfi_amdext_sync (struct mtd_info *mtd) -{ - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; - int i; - struct flchip *chip; - int ret = 0; - DECLARE_WAITQUEUE(wait, current); -printk("sync\n"); - - for (i=0; !ret && inumchips; i++) { - chip = &cfi->chips[i]; - - retry: - spin_lock_bh(chip->mutex); - - switch(chip->state) { - case FL_READY: - case FL_STATUS: - case FL_CFI_QUERY: - case FL_JEDEC_QUERY: - chip->oldstate = chip->state; - chip->state = FL_SYNCING; - /* No need to wake_up() on this state change - - * as the whole point is that nobody can do anything - * with the chip now anyway. - */ - spin_unlock_bh(chip->mutex); - break; - - default: - /* Not an idle state */ - add_wait_queue(&chip->wq, &wait); - - spin_unlock_bh(chip->mutex); - - schedule(); - - remove_wait_queue(&chip->wq, &wait); - - goto retry; - } - } - - /* Unlock the chips again */ - - for (i--; i >=0; i--) { - chip = &cfi->chips[i]; - - spin_lock_bh(chip->mutex); - - if (chip->state == FL_SYNCING) { - chip->state = chip->oldstate; - wake_up(&chip->wq); - } - spin_unlock_bh(chip->mutex); - } -printk("sync end\n"); -} - - -static int cfi_amdext_suspend(struct mtd_info *mtd) -{ - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; - int i; - struct flchip *chip; - int ret = 0; -//printk("suspend\n"); - - for (i=0; !ret && inumchips; i++) { - chip = &cfi->chips[i]; - - spin_lock_bh(chip->mutex); - - switch(chip->state) { - case FL_READY: - case FL_STATUS: - case FL_CFI_QUERY: - case FL_JEDEC_QUERY: - chip->oldstate = chip->state; - chip->state = FL_PM_SUSPENDED; - /* No need to wake_up() on this state change - - * as the whole point is that nobody can do anything - * with the chip now anyway. - */ - break; - - default: - ret = -EAGAIN; - break; - } - spin_unlock_bh(chip->mutex); - } - - /* Unlock the chips again */ - - for (i--; i >=0; i--) { - chip = &cfi->chips[i]; - - spin_lock_bh(chip->mutex); - - if (chip->state == FL_PM_SUSPENDED) { - chip->state = chip->oldstate; - wake_up(&chip->wq); - } - spin_unlock_bh(chip->mutex); - } - - return ret; -} - -static void cfi_amdext_resume(struct mtd_info *mtd) -{ - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; - int i; - struct flchip *chip; -//printk("resume\n"); - - for (i=0; inumchips; i++) { - - chip = &cfi->chips[i]; - - spin_lock_bh(chip->mutex); - - if (chip->state == FL_PM_SUSPENDED) { - chip->state = chip->oldstate; - wake_up(&chip->wq); - } - else - printk("Argh. Chip not in PM_SUSPENDED state upon resume()\n"); - - spin_unlock_bh(chip->mutex); - } -} - -static void cfi_amdext_destroy(struct mtd_info *mtd) -{ - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; - kfree(cfi->cmdset_priv); - inter_module_put(cfi->im_name); - kfree(cfi); -} - - -static int __init cfi_amdext_init(void) -{ - inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0002); - return 0; -} - -static void __exit cfi_amdext_exit(void) -{ - inter_module_unregister(im_name); -} - -module_init(cfi_amdext_init); -module_exit(cfi_amdext_exit); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/cfi_probe.c linux/drivers/mtd/cfi_probe.c --- v2.4.5/linux/drivers/mtd/cfi_probe.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/mtd/cfi_probe.c Wed Dec 31 16:00:00 1969 @@ -1,517 +0,0 @@ -/* - Common Flash Interface probe code. - (C) 2000 Red Hat. GPL'd. - $Id: cfi_probe.c,v 1.12 2000/07/03 13:29:16 dwmw2 Exp $ -*/ - - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - - -struct mtd_info *cfi_probe(struct map_info *); - -static void print_cfi_ident(struct cfi_ident *); -static void check_cmd_set(struct map_info *, int, unsigned long); -static struct cfi_private *cfi_cfi_probe(struct map_info *); - -static const char im_name[] = "cfi_probe"; - -/* This routine is made available to other mtd code via - * inter_module_register. It must only be accessed through - * inter_module_get which will bump the use count of this module. The - * addresses passed back in mtd are valid as long as the use count of - * this module is non-zero, i.e. between inter_module_get and - * inter_module_put. Keith Owens 29 Oct 2000. - */ -struct mtd_info *cfi_probe(struct map_info *map) -{ - struct mtd_info *mtd = NULL; - struct cfi_private *cfi; - /* First probe the map to see if we have CFI stuff there. */ - cfi = cfi_cfi_probe(map); - - if (!cfi) - return NULL; - - map->fldrv_priv = cfi; - map->im_name = im_name; - - /* OK we liked it. Now find a driver for the command set it talks */ - - check_cmd_set(map, 1, cfi->chips[0].start); /* First the primary cmdset */ - check_cmd_set(map, 0, cfi->chips[0].start); /* Then the secondary */ - - /* check_cmd_set() will have used inter_module_get to increase - the use count of the module which provides the command set - driver. If we're quitting, we have to decrease it again. - */ - - if(cfi->cmdset_setup) { - mtd = cfi->cmdset_setup(map); - - if (mtd) - return mtd; - inter_module_put(cfi->im_name); - } - printk("No supported Vendor Command Set found\n"); - - kfree(cfi); - map->fldrv_priv = NULL; - return NULL; - -} - -static int cfi_probe_new_chip(struct map_info *map, unsigned long base, - struct flchip *chips, struct cfi_private *cfi) -{ - switch (map->buswidth) { - - case 1: { - unsigned char tmp = map->read8(map, base + 0x55); - - /* If there's a device there, put it in Query Mode */ - map->write8(map, 0x98, base+0x55); - - if (map->read8(map,base+0x10) == 'Q' && - map->read8(map,base+0x11) == 'R' && - map->read8(map,base+0x12) == 'Y') { - printk("%s: Found a CFI device at 0x%lx in 8 bit mode\n", map->name, base); - if (chips) { - /* Check previous chips for aliases */ - printk("FIXME: Do alias check at line %d of cfi_probe.c\n", __LINE__); - /* Put it back into Read Mode */ - map->write8(map, 0x98, base+0x55); - } - return 1; - } else { - if (map->read8(map, base + 0x55) == 0x98) { - /* It looks like RAM. Put back the stuff we overwrote */ - map->write8(map, tmp, base+0x55); - } - return 0; - } - } - - case 2: { - __u16 tmp = map->read16(map, base + 0xaa); - - /* If there's a device there, put it into Query Mode */ - map->write16(map, 0x9898, base+0xAA); - - if (map->read16(map, base+0x20) == cpu_to_le16(0x0051) && - map->read16(map, base+0x22) == cpu_to_le16(0x0052) && - map->read16(map, base+0x24) == cpu_to_le16(0x0059)) { - printk("%s: Found a CFI device at 0x%lx in 16 bit mode\n", map->name, base); - if (chips) { - /* Check previous chips for aliases */ - int i; - - for (i=0; i < cfi->numchips; i++) { - /* This chip should be in read mode if it's one - we've already touched. */ - if (map->read16(map, chips[i].start+0x20) == cpu_to_le16(0x0051) && - map->read16(map, chips[i].start+0x22) == cpu_to_le16(0x0052) && - map->read16(map, chips[i].start+0x24) == cpu_to_le16(0x0059)){ - /* Either the old chip has got 'Q''R''Y' in a most - unfortunate place, or it's an alias of the new - chip. Double-check that it's in read mode, and check. */ - map->write16(map, 0xffff, chips[i].start+0x20); - if (map->read16(map, chips[i].start+0x20) == cpu_to_le16(0x0051) && - map->read16(map, chips[i].start+0x22) == cpu_to_le16(0x0052) && - map->read16(map, chips[i].start+0x24) == cpu_to_le16(0x0059)) { - /* Yes it's got QRY for data. Most unfortunate. - Stick the old one in read mode too. */ - map->write16(map, 0xffff, base); - if (map->read16(map, base+0x20) == cpu_to_le16(0x0051) && - map->read16(map, base+0x22) == cpu_to_le16(0x0052) && - map->read16(map, base+0x24) == cpu_to_le16(0x0059)) { - /* OK, so has the new one. Assume it's an alias */ - printk("T'was probably an alias for the chip at 0x%lx\n", chips[i].start); - return 1; - } /* else no, they're different, fall through. */ - } else { - /* No the old one hasn't got QRY for data. Therefore, - it's an alias of the new one. */ - map->write16(map, 0xffff, base+0xaa); - /* Just to be paranoid. */ - map->write16(map, 0xffff, chips[i].start+0xaa); - printk("T'was an alias for the chip at 0x%lx\n", chips[i].start); - return 1; - } - } - /* No, the old one didn't look like it's in query mode. Next. */ - } - - /* OK, if we got to here, then none of the previous chips appear to - be aliases for the current one. */ - if (cfi->numchips == MAX_CFI_CHIPS) { - printk("%s: Too many flash chips detected. Increase MAX_CFI_CHIPS from %d.\n", map->name, MAX_CFI_CHIPS); - /* Doesn't matter about resetting it to Read Mode - we're not going to talk to it anyway */ - return 1; - } - printk("Not an alias. Adding\n"); - chips[cfi->numchips].start = base; - chips[cfi->numchips].state = FL_READY; - chips[cfi->numchips].mutex = &chips[cfi->numchips]._spinlock; - cfi->numchips++; - - /* Put it back into Read Mode */ - map->write16(map, 0xffff, base+0xaa); - } - - return 1; - } - else if (map->read16(map, base+0x20) == 0x5151 && - map->read16(map, base+0x22) == 0x5252 && - map->read16(map, base+0x24) == 0x5959) { - printk("%s: Found a coupled pair of CFI devices at %lx in 8 bit mode\n", - map->name, base); - if (chips) { - /* Check previous chips for aliases */ - printk("FIXME: Do alias check at line %d of cfi_probe.c\n", __LINE__); - - /* Put it back into Read Mode */ - map->write16(map, 0xffff, base+0xaa); - } - - return 2; - } else { - if (map->read16(map, base+0xaa) == 0x9898) { - /* It looks like RAM. Put back the stuff we overwrote */ - map->write16(map, tmp, base+0xaa); - } - return 0; - } - } - - - case 4: { - __u32 tmp = map->read32(map, base+0x154); - - /* If there's a device there, put it into Query Mode */ - map->write32(map, 0x98989898, base+0x154); - - if (map->read32(map, base+0x40) == cpu_to_le32(0x00000051) && - map->read32(map, base+0x44) == cpu_to_le32(0x00000052) && - map->read32(map, base+0x48) == cpu_to_le32(0x00000059)) { - /* This isn't actually in the CFI spec - only x8 and x16 are. */ - printk("%s: Found a CFI device at %lx in 32 bit mode\n", map->name, base); - if (chips) { - /* Check previous chips for aliases */ - printk("FIXME: Do alias check at line %d of cfi_probe.c\n", __LINE__); - - /* Put it back into read mode */ - map->write32(map, 0xffffffff, base+0x154); - } - return 1; - } - else if (map->read32(map, base+0x40) == cpu_to_le32(0x00510051) && - map->read32(map, base+0x44) == cpu_to_le32(0x00520052) && - map->read32(map, base+0x48) == cpu_to_le32(0x00590059)) { - printk("%s: Found a coupled pair of CFI devices at location %lx in 16 bit mode\n", map->name, base); - if (chips) { - /* Check previous chips for aliases */ - printk("FIXME: Do alias check at line %d of cfi_probe.c\n", __LINE__); - - /* Put it back into read mode */ - map->write32(map, 0xffffffff, base+0x154); - } - return 2; - } - else if (map->read32(map, base+0x40) == 0x51515151 && - map->read32(map, base+0x44) == 0x52525252 && - map->read32(map, base+0x48) == 0x59595959) { - printk("%s: Found four side-by-side CFI devices at location %lx in 8 bit mode\n", map->name, base); - if (chips) { - /* Check previous chips for aliases */ - printk("FIXME: Do alias check at line %d of cfi_probe.c\n", __LINE__); - - /* Put it back into read mode */ - map->write32(map, 0xffffffff, base+0x154); - } - return 4; - } else { - if (map->read32(map, base+0x154) == 0x98989898) { - /* It looks like RAM. Put back the stuff we overwrote */ - map->write32(map, tmp, base+0x154); - } - return 0; - } - } - default: - printk(KERN_WARNING "cfi_probe called with strange buswidth %d\n", map->buswidth); - return 0; - } -} - -static struct cfi_private *cfi_cfi_probe(struct map_info *map) -{ - unsigned long base=0; - struct cfi_private cfi; - struct cfi_private *retcfi; - struct flchip chip[MAX_CFI_CHIPS]; - int i; - - memset(&cfi, 0, sizeof(cfi)); - - /* The first invocation (with chips == NULL) leaves the device in Query Mode */ - cfi.interleave = cfi_probe_new_chip(map, 0, NULL, NULL); - - if (!cfi.interleave) { - printk("%s: Found no CFI device at location zero\n", map->name); - /* Doesn't appear to be CFI-compliant at all */ - return NULL; - } - - /* Read the Basic Query Structure from the device */ - - for (i=0; iread8(map,base + ((0x10 + i)*map->buswidth)); - } - - /* Do any necessary byteswapping */ - cfi.cfiq.P_ID = le16_to_cpu(cfi.cfiq.P_ID); - cfi.cfiq.P_ADR = le16_to_cpu(cfi.cfiq.P_ADR); - cfi.cfiq.A_ID = le16_to_cpu(cfi.cfiq.A_ID); - cfi.cfiq.A_ADR = le16_to_cpu(cfi.cfiq.A_ADR); - cfi.cfiq.InterfaceDesc = le16_to_cpu(cfi.cfiq.InterfaceDesc); - cfi.cfiq.MaxBufWriteSize = le16_to_cpu(cfi.cfiq.MaxBufWriteSize); - -#if 1 - /* Dump the information therein */ - print_cfi_ident(&cfi.cfiq); - - for (i=0; iread8(map,base + ((0x2d + (4*i))*map->buswidth))) + - (((map->read8(map,(0x2e + (4*i))*map->buswidth)) << 8)); - __u16 EraseRegionInfoSize = (map->read8(map, base + ((0x2f + (4*i))*map->buswidth))) + - (map->read8(map, base + ((0x30 + (4*i))*map->buswidth)) << 8); - - printk(" Erase Region #%d: BlockSize 0x%4.4X bytes, %d blocks\n", - i, EraseRegionInfoSize * 256, EraseRegionInfoNum+1); - } - - printk("\n"); -#endif - - /* Switch the chip back into Read Mode, to make the alias detection work */ - switch(map->buswidth) { - case 1: - map->write8(map, 0xff, 0x55); - break; - case 2: - map->write16(map, 0xffff, 0xaa); - break; - case 4: - map->write32(map, 0xffffffff, 0x154); - break; - } - - /* OK. We've worked out what it is and we're happy with it. Now see if there are others */ - - chip[0].start = 0; - chip[0].state = FL_READY; - chip[0].mutex = &chip[0]._spinlock; - - cfi.chipshift = cfi.cfiq.DevSize; - cfi.numchips = 1; - - if (!cfi.chipshift) { - printk("cfi.chipsize is zero. This is bad. cfi.cfiq.DevSize is %d\n", cfi.cfiq.DevSize); - return NULL; - } - - for (base = (1<size; base += (1<chips[0], chip, sizeof(struct flchip) * cfi.numchips); - for (i=0; i< retcfi->numchips; i++) { - init_waitqueue_head(&retcfi->chips[i].wq); - spin_lock_init(&retcfi->chips[i]._spinlock); - } - return retcfi; -} - -static char *vendorname(__u16 vendor) -{ - switch (vendor) { - case P_ID_NONE: - return "None"; - - case P_ID_INTEL_EXT: - return "Intel/Sharp Extended"; - - case P_ID_AMD_STD: - return "AMD/Fujitsu Standard"; - - case P_ID_INTEL_STD: - return "Intel/Sharp Standard"; - - case P_ID_AMD_EXT: - return "AMD/Fujitsu Extended"; - - case P_ID_MITSUBISHI_STD: - return "Mitsubishi Standard"; - - case P_ID_MITSUBISHI_EXT: - return "Mitsubishi Extended"; - - case P_ID_RESERVED: - return "Not Allowed / Reserved for Future Use"; - - default: - return "Unknown"; - } -} - - -static void print_cfi_ident(struct cfi_ident *cfip) -{ - if (cfip->qry[0] != 'Q' || cfip->qry[1] != 'R' || cfip->qry[2] != 'Y') { - printk("Invalid CFI ident structure.\n"); - return; - } - - printk("Primary Vendor Command Set: %4.4X (%s)\n", cfip->P_ID, vendorname(cfip->P_ID)); - if (cfip->P_ADR) - printk("Primary Algorithm Table at %4.4X\n", cfip->P_ADR); - else - printk("No Primary Algorithm Table\n"); - - printk("Alternative Vendor Command Set: %4.4X (%s)\n", cfip->A_ID, vendorname(cfip->A_ID)); - if (cfip->A_ADR) - printk("Alternate Algorithm Table at %4.4X\n", cfip->A_ADR); - else - printk("No Alternate Algorithm Table\n"); - - - printk("Vcc Minimum: %x.%x V\n", cfip->VccMin >> 4, cfip->VccMin & 0xf); - printk("Vcc Maximum: %x.%x V\n", cfip->VccMax >> 4, cfip->VccMax & 0xf); - if (cfip->VppMin) { - printk("Vpp Minimum: %x.%x V\n", cfip->VppMin >> 4, cfip->VppMin & 0xf); - printk("Vpp Maximum: %x.%x V\n", cfip->VppMax >> 4, cfip->VppMax & 0xf); - } - else - printk("No Vpp line\n"); - - printk("Typical byte/word write timeout: %d µs\n", 1<WordWriteTimeoutTyp); - printk("Maximum byte/word write timeout: %d µs\n", (1<WordWriteTimeoutMax) * (1<WordWriteTimeoutTyp)); - - if (cfip->BufWriteTimeoutTyp || cfip->BufWriteTimeoutMax) { - printk("Typical full buffer write timeout: %d µs\n", 1<BufWriteTimeoutTyp); - printk("Maximum full buffer write timeout: %d µs\n", (1<BufWriteTimeoutMax) * (1<BufWriteTimeoutTyp)); - } - else - printk("Full buffer write not supported\n"); - - printk("Typical block erase timeout: %d µs\n", 1<BlockEraseTimeoutTyp); - printk("Maximum block erase timeout: %d µs\n", (1<BlockEraseTimeoutMax) * (1<BlockEraseTimeoutTyp)); - if (cfip->ChipEraseTimeoutTyp || cfip->ChipEraseTimeoutMax) { - printk("Typical chip erase timeout: %d µs\n", 1<ChipEraseTimeoutTyp); - printk("Maximum chip erase timeout: %d µs\n", (1<ChipEraseTimeoutMax) * (1<ChipEraseTimeoutTyp)); - } - else - printk("Chip erase not supported\n"); - - printk("Device size: 0x%X bytes (%d Mb)\n", 1 << cfip->DevSize, 1<< (cfip->DevSize - 20)); - printk("Flash Device Interface description: 0x%4.4X\n", cfip->InterfaceDesc); - switch(cfip->InterfaceDesc) { - case 0: - printk(" - x8-only asynchronous interface\n"); - break; - - case 1: - printk(" - x16-only asynchronous interface\n"); - break; - - case 2: - printk(" - supports x8 and x16 via BYTE# with asynchronous interface\n"); - break; - - case 3: - printk(" - x32-only asynchronous interface\n"); - break; - - case 65535: - printk(" - Not Allowed / Reserved\n"); - break; - - default: - printk(" - Unknown\n"); - break; - } - - printk("Max. bytes in buffer write: 0x%x\n", 1<< cfip->MaxBufWriteSize); - printk("Number of Erase Block Regions: %d\n", cfip->NumEraseRegions); - -} - -static void check_cmd_set(struct map_info *map, int primary, unsigned long base) -{ - __u16 adr; - struct cfi_private *cfi = map->fldrv_priv; - __u16 type = primary?cfi->cfiq.P_ID:cfi->cfiq.A_ID; - char probename[32]; - void (*probe_function)(struct map_info *, int, unsigned long); - - if (type == P_ID_NONE || type == P_ID_RESERVED) - return; - - sprintf(probename, "cfi_cmdset_%4.4X", type); - - probe_function = inter_module_get_request(probename, probename); - if (probe_function) { - (*probe_function)(map, primary, base); - return; - } - - /* This was a command set we don't know about. Print only the basic info */ - adr = primary?cfi->cfiq.P_ADR:cfi->cfiq.A_ADR; - - if (!adr) { - printk(" No Extended Query Table\n"); - } - else if (map->read8(map,base+(adr*map->buswidth)) != (primary?'P':'A') || - map->read8(map,base+((adr+1)*map->buswidth)) != (primary?'R':'L') || - map->read8(map,base+((adr+2)*map->buswidth)) != (primary?'I':'T')) { - printk ("Invalid Extended Query Table at %4.4X: %2.2X %2.2X %2.2X\n", - adr, - map->read8(map,base+(adr*map->buswidth)), - map->read8(map,base+((adr+1)*map->buswidth)), - map->read8(map,base+((adr+2)*map->buswidth))); - } - else { - printk(" Extended Query Table version %c.%c\n", - map->read8(map,base+((adr+3)*map->buswidth)), - map->read8(map,base+((adr+4)*map->buswidth))); - } -} - -static int __init cfi_probe_init(void) -{ - inter_module_register(im_name, THIS_MODULE, &cfi_probe); - return 0; -} - -static void __exit cfi_probe_exit(void) -{ - inter_module_unregister(im_name); -} - -module_init(cfi_probe_init); -module_exit(cfi_probe_exit); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/chips/Config.in linux/drivers/mtd/chips/Config.in --- v2.4.5/linux/drivers/mtd/chips/Config.in Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/chips/Config.in Tue Jun 12 10:30:27 2001 @@ -0,0 +1,42 @@ +# drivers/mtd/chips/Config.in + +# $Id: Config.in,v 1.4 2001/05/14 09:48:12 dwmw2 Exp $ + +mainmenu_option next_comment + +comment 'RAM/ROM/Flash chip drivers' + +dep_tristate ' Common Flash Interface (CFI) support' CONFIG_MTD_CFI $CONFIG_MTD +if [ "$CONFIG_MTD_CFI" = "y" -o "$CONFIG_MTD_CFI" = "m" ]; then + bool ' CFI Virtual erase regions (EXPERIMENTAL)' CONFIG_MTD_CFI_VIRTUAL_ER + bool ' CFI Advanced configuration options' CONFIG_MTD_CFI_ADV_OPTIONS + if [ "$CONFIG_MTD_CFI_ADV_OPTIONS" = "y" ]; then + choice 'Flash cmd/query data swapping' \ + "NO CONFIG_MTD_CFI_NOSWAP \ + BIG_ENDIAN_BYTE CONFIG_MTD_CFI_BE_BYTE_SWAP \ + LITTLE_ENDIAN_BYTE CONFIG_MTD_CFI_LE_BYTE_SWAP \ + LART_ENDIAN_BYTE CONFIG_MTD_CFI_LART_BIT_SWAP" NO + bool ' Specific CFI Flash geometry selection' CONFIG_MTD_CFI_GEOMETRY + if [ "$CONFIG_MTD_CFI_GEOMETRY" = "y" ]; then + bool ' Support 8-bit buswidth' CONFIG_MTD_CFI_B1 + bool ' Support 16-bit buswidth' CONFIG_MTD_CFI_B2 + bool ' Support 32-bit buswidth' CONFIG_MTD_CFI_B4 + if [ "$CONFIG_MTD_CFI_B1" = "y" ]; then + define_bool CONFIG_MTD_CFI_I1 y + else + bool ' Support 1-chip flash interleave' CONFIG_MTD_CFI_I1 + fi + bool ' Support 2-chip flash interleave' CONFIG_MTD_CFI_I2 + bool ' Support 4-chip flash interleave' CONFIG_MTD_CFI_I4 + fi + fi +fi +dep_tristate ' CFI support for Intel/Sharp Basic/Extended Commands' CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_CFI +dep_tristate ' CFI support for AMD/Fujitsu Standard Commands' CONFIG_MTD_CFI_AMDSTD $CONFIG_MTD_CFI +dep_tristate ' AMD compatible flash chip support (non-CFI)' CONFIG_MTD_AMDSTD $CONFIG_MTD +dep_tristate ' pre-CFI Sharp chip support' CONFIG_MTD_SHARP $CONFIG_MTD +dep_tristate ' Support for RAM chips in bus mapping' CONFIG_MTD_RAM $CONFIG_MTD +dep_tristate ' Support for ROM chips in bus mapping' CONFIG_MTD_ROM $CONFIG_MTD +dep_tristate ' JEDEC device support' CONFIG_MTD_JEDEC $CONFIG_MTD + +endmenu diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/chips/Makefile linux/drivers/mtd/chips/Makefile --- v2.4.5/linux/drivers/mtd/chips/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/chips/Makefile Tue Jun 12 10:30:27 2001 @@ -0,0 +1,27 @@ +# +# linux/drivers/chips/Makefile +# +# $Id: Makefile,v 1.4 2001/06/09 19:57:57 dwmw2 Exp $ + +O_TARGET := chipslink.o + +export-objs := chipreg.o + +# *** BIG UGLY NOTE *** +# +# The removal of get_module_symbol() and replacement with +# inter_module_register() et al has introduced a link order dependency +# here where previously there was none. We now have to ensure that +# the CFI command set drivers are linked before cfi_probe.o + +obj-$(CONFIG_MTD) += chipreg.o +obj-$(CONFIG_MTD_AMDSTD) += amd_flash.o +obj-$(CONFIG_MTD_CFI) += cfi_probe.o cfi_jedec.o +obj-$(CONFIG_MTD_CFI_AMDSTD) += cfi_cmdset_0002.o +obj-$(CONFIG_MTD_CFI_INTELEXT) += cfi_cmdset_0001.o +obj-$(CONFIG_MTD_JEDEC) += jedec.o +obj-$(CONFIG_MTD_RAM) += map_ram.o +obj-$(CONFIG_MTD_ROM) += map_rom.o +obj-$(CONFIG_MTD_SHARP) += sharp.o + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/chips/amd_flash.c linux/drivers/mtd/chips/amd_flash.c --- v2.4.5/linux/drivers/mtd/chips/amd_flash.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/chips/amd_flash.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,1251 @@ +/* + * MTD map driver for AMD compatible flash chips (non-CFI) + * + * Author: Jonas Holmberg + * + * $Id: amd_flash.c,v 1.8 2001/06/02 14:47:16 dwmw2 Exp $ + * + * Copyright (c) 2001 Axis Communications AB + * + * This file is under GPL. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* There's no limit. It exists only to avoid realloc. */ +#define MAX_AMD_CHIPS 8 + +#define DEVICE_TYPE_X8 (8 / 8) +#define DEVICE_TYPE_X16 (16 / 8) +#define DEVICE_TYPE_X32 (32 / 8) + +/* Addresses */ +#define ADDR_MANUFACTURER 0x0000 +#define ADDR_DEVICE_ID 0x0001 +#define ADDR_UNLOCK_1 0x0555 +#define ADDR_UNLOCK_2 0x02AA + +/* Commands */ +#define CMD_UNLOCK_DATA_1 0x00AA +#define CMD_UNLOCK_DATA_2 0x0055 +#define CMD_MANUFACTURER_UNLOCK_DATA 0x0090 +#define CMD_UNLOCK_BYPASS_MODE 0x0020 +#define CMD_PROGRAM_UNLOCK_DATA 0x00A0 +#define CMD_RESET_DATA 0x00F0 +#define CMD_SECTOR_ERASE_UNLOCK_DATA 0x0080 +#define CMD_SECTOR_ERASE_UNLOCK_DATA_2 0x0030 + +/* Manufacturers */ +#define MANUFACTURER_AMD 0x0001 +#define MANUFACTURER_FUJITSU 0x0004 +#define MANUFACTURER_ST 0x0020 +#define MANUFACTURER_SST 0x00BF +#define MANUFACTURER_TOSHIBA 0x0098 + +/* AMD */ +#define AM29F800BB 0x2258 +#define AM29F800BT 0x22D6 +#define AM29LV800BB 0x225B +#define AM29LV800BT 0x22DA +#define AM29LV160DT 0x22C4 +#define AM29LV160DB 0x2249 + +/* Fujitsu */ +#define MBM29LV160TE 0x22C4 +#define MBM29LV160BE 0x2249 + +/* ST - www.st.com */ +#define M29W800T 0x00D7 +#define M29W160DT 0x22C4 +#define M29W160DB 0x2249 + +/* SST */ +#define SST39LF800 0x2781 +#define SST39LF160 0x2782 + +/* Toshiba */ +#define TC58FVT160 0x00C2 +#define TC58FVB160 0x0043 + +#define D6_MASK 0x40 + +struct amd_flash_private { + int device_type; + int interleave; + int numchips; + unsigned long chipshift; +// const char *im_name; + struct flchip chips[0]; +}; + +struct amd_flash_info { + const __u16 mfr_id; + const __u16 dev_id; + const char *name; + const u_long size; + const int numeraseregions; + const struct mtd_erase_region_info regions[4]; +}; + + + +static int amd_flash_read(struct mtd_info *, loff_t, size_t, size_t *, + u_char *); +static int amd_flash_write(struct mtd_info *, loff_t, size_t, size_t *, + const u_char *); +static int amd_flash_erase(struct mtd_info *, struct erase_info *); +static void amd_flash_sync(struct mtd_info *); +static int amd_flash_suspend(struct mtd_info *); +static void amd_flash_resume(struct mtd_info *); +static void amd_flash_destroy(struct mtd_info *); +static struct mtd_info *amd_flash_probe(struct map_info *map); + + +static struct mtd_chip_driver amd_flash_chipdrv = { + probe: amd_flash_probe, + destroy: amd_flash_destroy, + name: "amd_flash", + module: THIS_MODULE +}; + + + +static const char im_name[] = "amd_flash"; + + + +static inline __u32 wide_read(struct map_info *map, __u32 addr) +{ + if (map->buswidth == 1) { + return map->read8(map, addr); + } else if (map->buswidth == 2) { + return map->read16(map, addr); + } else if (map->buswidth == 4) { + return map->read32(map, addr); + } + + return 0; +} + +static inline void wide_write(struct map_info *map, __u32 val, __u32 addr) +{ + if (map->buswidth == 1) { + map->write8(map, val, addr); + } else if (map->buswidth == 2) { + map->write16(map, val, addr); + } else if (map->buswidth == 4) { + map->write32(map, val, addr); + } +} + +static inline __u32 make_cmd(struct map_info *map, __u32 cmd) +{ + const struct amd_flash_private *private = map->fldrv_priv; + if ((private->interleave == 2) && + (private->device_type == DEVICE_TYPE_X16)) { + cmd |= (cmd << 16); + } + + return cmd; +} + +static inline void send_unlock(struct map_info *map, unsigned long base) +{ + wide_write(map, (CMD_UNLOCK_DATA_1 << 16) | CMD_UNLOCK_DATA_1, + base + (map->buswidth * ADDR_UNLOCK_1)); + wide_write(map, (CMD_UNLOCK_DATA_2 << 16) | CMD_UNLOCK_DATA_2, + base + (map->buswidth * ADDR_UNLOCK_2)); +} + +static inline void send_cmd(struct map_info *map, unsigned long base, __u32 cmd) +{ + send_unlock(map, base); + wide_write(map, make_cmd(map, cmd), + base + (map->buswidth * ADDR_UNLOCK_1)); +} + +static inline void send_cmd_to_addr(struct map_info *map, unsigned long base, + __u32 cmd, unsigned long addr) +{ + send_unlock(map, base); + wide_write(map, make_cmd(map, cmd), addr); +} + +static inline int flash_is_busy(struct map_info *map, unsigned long addr, + int interleave) +{ + + if ((interleave == 2) && (map->buswidth == 4)) { + __u32 read1, read2; + + read1 = wide_read(map, addr); + read2 = wide_read(map, addr); + + return (((read1 >> 16) & D6_MASK) != + ((read2 >> 16) & D6_MASK)) || + (((read1 & 0xffff) & D6_MASK) != + ((read2 & 0xffff) & D6_MASK)); + } + + return ((wide_read(map, addr) & D6_MASK) != + (wide_read(map, addr) & D6_MASK)); +} + + + +/* + * Reads JEDEC manufacturer ID and device ID and returns the index of the first + * matching table entry (-1 if not found or alias for already found chip). + */ +static int probe_new_chip(struct mtd_info *mtd, __u32 base, + struct flchip *chips, + struct amd_flash_private *private, + const struct amd_flash_info *table, int table_size) +{ + __u32 mfr_id, dev_id; + struct map_info *map = mtd->priv; + struct amd_flash_private temp; + int i; + + temp.device_type = DEVICE_TYPE_X16; // Assume X16 (FIXME) + temp.interleave = 2; + map->fldrv_priv = &temp; + + /* Enter autoselect mode. */ + send_cmd(map, base, CMD_RESET_DATA); + send_cmd(map, base, CMD_MANUFACTURER_UNLOCK_DATA); + + mfr_id = wide_read(map, base + (map->buswidth * ADDR_MANUFACTURER)); + dev_id = wide_read(map, base + (map->buswidth * ADDR_DEVICE_ID)); + + if ((map->buswidth == 4) && ((mfr_id >> 16) == (mfr_id & 0xffff)) && + ((dev_id >> 16) == (dev_id & 0xffff))) { + mfr_id = mfr_id & 0xffff; + dev_id = dev_id & 0xffff; + } else { + temp.interleave = 1; + } + + for (i = 0; i < table_size; i++) { + if ((mfr_id == table[i].mfr_id) && + (dev_id == table[i].dev_id)) { + if (chips) { + int j; + + /* Is this an alias for an already found chip? + * In that case that chip should be in + * autoselect mode now. + */ + for (j = 0; j < private->numchips; j++) { + if ((wide_read(map, chips[j].start + + (map->buswidth * + ADDR_MANUFACTURER)) + == mfr_id) + && + (wide_read(map, chips[j].start + + (map->buswidth * + ADDR_DEVICE_ID)) + == dev_id)) { + + /* Exit autoselect mode. */ + send_cmd(map, base, + CMD_RESET_DATA); + + return -1; + } + } + + if (private->numchips == MAX_AMD_CHIPS) { + printk(KERN_WARNING + "%s: Too many flash chips " + "detected. Increase " + "MAX_AMD_CHIPS from %d.\n", + map->name, MAX_AMD_CHIPS); + + return -1; + } + + chips[private->numchips].start = base; + chips[private->numchips].state = FL_READY; + chips[private->numchips].mutex = + &chips[private->numchips]._spinlock; + private->numchips++; + } + + printk("%s: Found %d x %ldMiB %s at 0x%x\n", map->name, + temp.interleave, (table[i].size)/(1024*1024), + table[i].name, base); + + mtd->size += table[i].size * temp.interleave; + mtd->numeraseregions += table[i].numeraseregions; + + break; + } + } + + /* Exit autoselect mode. */ + send_cmd(map, base, CMD_RESET_DATA); + + if (i == table_size) { + printk(KERN_DEBUG "%s: unknown flash device at 0x%x, " + "mfr id 0x%x, dev id 0x%x\n", map->name, + base, mfr_id, dev_id); + map->fldrv_priv = NULL; + + return -1; + } + + private->device_type = temp.device_type; + private->interleave = temp.interleave; + + return i; +} + + + +static struct mtd_info *amd_flash_probe(struct map_info *map) +{ + /* Keep this table on the stack so that it gets deallocated after the + * probe is done. + */ + const struct amd_flash_info table[] = { + { + mfr_id: MANUFACTURER_AMD, + dev_id: AM29LV160DT, + name: "AMD AM29LV160DT", + size: 0x00200000, + numeraseregions: 4, + regions: { + { offset: 0x000000, erasesize: 0x10000, numblocks: 31 }, + { offset: 0x1F0000, erasesize: 0x08000, numblocks: 1 }, + { offset: 0x1F8000, erasesize: 0x02000, numblocks: 2 }, + { offset: 0x1FC000, erasesize: 0x04000, numblocks: 1 } + } + }, { + mfr_id: MANUFACTURER_AMD, + dev_id: AM29LV160DB, + name: "AMD AM29LV160DB", + size: 0x00200000, + numeraseregions: 4, + regions: { + { offset: 0x000000, erasesize: 0x04000, numblocks: 1 }, + { offset: 0x004000, erasesize: 0x02000, numblocks: 2 }, + { offset: 0x008000, erasesize: 0x08000, numblocks: 1 }, + { offset: 0x010000, erasesize: 0x10000, numblocks: 31 } + } + }, { + mfr_id: MANUFACTURER_TOSHIBA, + dev_id: TC58FVT160, + name: "Toshiba TC58FVT160", + size: 0x00200000, + numeraseregions: 4, + regions: { + { offset: 0x000000, erasesize: 0x10000, numblocks: 31 }, + { offset: 0x1F0000, erasesize: 0x08000, numblocks: 1 }, + { offset: 0x1F8000, erasesize: 0x02000, numblocks: 2 }, + { offset: 0x1FC000, erasesize: 0x04000, numblocks: 1 } + } + }, { + mfr_id: MANUFACTURER_FUJITSU, + dev_id: MBM29LV160TE, + name: "Fujitsu MBM29LV160TE", + size: 0x00200000, + numeraseregions: 4, + regions: { + { offset: 0x000000, erasesize: 0x10000, numblocks: 31 }, + { offset: 0x1F0000, erasesize: 0x08000, numblocks: 1 }, + { offset: 0x1F8000, erasesize: 0x02000, numblocks: 2 }, + { offset: 0x1FC000, erasesize: 0x04000, numblocks: 1 } + } + }, { + mfr_id: MANUFACTURER_TOSHIBA, + dev_id: TC58FVB160, + name: "Toshiba TC58FVB160", + size: 0x00200000, + numeraseregions: 4, + regions: { + { offset: 0x000000, erasesize: 0x04000, numblocks: 1 }, + { offset: 0x004000, erasesize: 0x02000, numblocks: 2 }, + { offset: 0x008000, erasesize: 0x08000, numblocks: 1 }, + { offset: 0x010000, erasesize: 0x10000, numblocks: 31 } + } + }, { + mfr_id: MANUFACTURER_FUJITSU, + dev_id: MBM29LV160BE, + name: "Fujitsu MBM29LV160BE", + size: 0x00200000, + numeraseregions: 4, + regions: { + { offset: 0x000000, erasesize: 0x04000, numblocks: 1 }, + { offset: 0x004000, erasesize: 0x02000, numblocks: 2 }, + { offset: 0x008000, erasesize: 0x08000, numblocks: 1 }, + { offset: 0x010000, erasesize: 0x10000, numblocks: 31 } + } + }, { + mfr_id: MANUFACTURER_AMD, + dev_id: AM29LV800BB, + name: "AMD AM29LV800BB", + size: 0x00100000, + numeraseregions: 4, + regions: { + { offset: 0x000000, erasesize: 0x04000, numblocks: 1 }, + { offset: 0x004000, erasesize: 0x02000, numblocks: 2 }, + { offset: 0x008000, erasesize: 0x08000, numblocks: 1 }, + { offset: 0x010000, erasesize: 0x10000, numblocks: 15 } + } + }, { + mfr_id: MANUFACTURER_AMD, + dev_id: AM29F800BB, + name: "AMD AM29F800BB", + size: 0x00100000, + numeraseregions: 4, + regions: { + { offset: 0x000000, erasesize: 0x04000, numblocks: 1 }, + { offset: 0x004000, erasesize: 0x02000, numblocks: 2 }, + { offset: 0x008000, erasesize: 0x08000, numblocks: 1 }, + { offset: 0x010000, erasesize: 0x10000, numblocks: 15 } + } + }, { + mfr_id: MANUFACTURER_AMD, + dev_id: AM29LV800BT, + name: "AMD AM29LV800BT", + size: 0x00100000, + numeraseregions: 4, + regions: { + { offset: 0x000000, erasesize: 0x10000, numblocks: 15 }, + { offset: 0x0F0000, erasesize: 0x08000, numblocks: 1 }, + { offset: 0x0F8000, erasesize: 0x02000, numblocks: 2 }, + { offset: 0x0FC000, erasesize: 0x04000, numblocks: 1 } + } + }, { + mfr_id: MANUFACTURER_AMD, + dev_id: AM29F800BT, + name: "AMD AM29F800BT", + size: 0x00100000, + numeraseregions: 4, + regions: { + { offset: 0x000000, erasesize: 0x10000, numblocks: 15 }, + { offset: 0x0F0000, erasesize: 0x08000, numblocks: 1 }, + { offset: 0x0F8000, erasesize: 0x02000, numblocks: 2 }, + { offset: 0x0FC000, erasesize: 0x04000, numblocks: 1 } + } + }, { + mfr_id: MANUFACTURER_AMD, + dev_id: AM29LV800BB, + name: "AMD AM29LV800BB", + size: 0x00100000, + numeraseregions: 4, + regions: { + { offset: 0x000000, erasesize: 0x10000, numblocks: 15 }, + { offset: 0x0F0000, erasesize: 0x08000, numblocks: 1 }, + { offset: 0x0F8000, erasesize: 0x02000, numblocks: 2 }, + { offset: 0x0FC000, erasesize: 0x04000, numblocks: 1 } + } + }, { + mfr_id: MANUFACTURER_ST, + dev_id: M29W800T, + name: "ST M29W800T", + size: 0x00100000, + numeraseregions: 4, + regions: { + { offset: 0x000000, erasesize: 0x10000, numblocks: 15 }, + { offset: 0x0F0000, erasesize: 0x08000, numblocks: 1 }, + { offset: 0x0F8000, erasesize: 0x02000, numblocks: 2 }, + { offset: 0x0FC000, erasesize: 0x04000, numblocks: 1 } + } + }, { + mfr_id: MANUFACTURER_ST, + dev_id: M29W160DT, + name: "ST M29W160DT", + size: 0x00200000, + numeraseregions: 4, + regions: { + { offset: 0x000000, erasesize: 0x10000, numblocks: 31 }, + { offset: 0x1F0000, erasesize: 0x08000, numblocks: 1 }, + { offset: 0x1F8000, erasesize: 0x02000, numblocks: 2 }, + { offset: 0x1FC000, erasesize: 0x04000, numblocks: 1 } + } + }, { + mfr_id: MANUFACTURER_ST, + dev_id: M29W160DB, + name: "ST M29W160DB", + size: 0x00200000, + numeraseregions: 4, + regions: { + { offset: 0x000000, erasesize: 0x04000, numblocks: 1 }, + { offset: 0x004000, erasesize: 0x02000, numblocks: 2 }, + { offset: 0x008000, erasesize: 0x08000, numblocks: 1 }, + { offset: 0x010000, erasesize: 0x10000, numblocks: 31 } + } + } + }; + + struct mtd_info *mtd; + struct flchip chips[MAX_AMD_CHIPS]; + int table_pos[MAX_AMD_CHIPS]; + struct amd_flash_private temp; + struct amd_flash_private *private; + u_long size; + unsigned long base; + int i; + int reg_idx; + int offset; + + mtd = (struct mtd_info*)kmalloc(sizeof(*mtd), GFP_KERNEL); + if (!mtd) { + printk(KERN_WARNING + "%s: kmalloc failed for info structure\n", map->name); + return NULL; + } + memset(mtd, 0, sizeof(*mtd)); + mtd->priv = map; + + memset(&temp, 0, sizeof(temp)); + + printk("%s: Probing for AMD compatible flash...\n", map->name); + + if ((table_pos[0] = probe_new_chip(mtd, 0, NULL, &temp, table, + sizeof(table)/sizeof(table[0]))) + == -1) { + printk(KERN_WARNING + "%s: Found no AMD compatible device at location zero\n", + map->name); + kfree(mtd); + + return NULL; + } + + chips[0].start = 0; + chips[0].state = FL_READY; + chips[0].mutex = &chips[0]._spinlock; + temp.numchips = 1; + for (size = mtd->size; size > 1; size >>= 1) { + temp.chipshift++; + } + switch (temp.interleave) { + case 2: + temp.chipshift += 1; + break; + case 4: + temp.chipshift += 2; + break; + } + + /* Find out if there are any more chips in the map. */ + for (base = (1 << temp.chipshift); + base < map->size; + base += (1 << temp.chipshift)) { + int numchips = temp.numchips; + table_pos[numchips] = probe_new_chip(mtd, base, chips, + &temp, table, sizeof(table)/sizeof(table[0])); + } + + mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) * + mtd->numeraseregions, GFP_KERNEL); + if (!mtd->eraseregions) { + printk(KERN_WARNING "%s: Failed to allocate " + "memory for MTD erase region info\n", map->name); + kfree(mtd); + map->fldrv_priv = NULL; + return 0; + } + + reg_idx = 0; + offset = 0; + for (i = 0; i < temp.numchips; i++) { + int dev_size; + int j; + + dev_size = 0; + for (j = 0; j < table[table_pos[i]].numeraseregions; j++) { + mtd->eraseregions[reg_idx].offset = offset + + (table[table_pos[i]].regions[j].offset * + temp.interleave); + mtd->eraseregions[reg_idx].erasesize = + table[table_pos[i]].regions[j].erasesize * + temp.interleave; + mtd->eraseregions[reg_idx].numblocks = + table[table_pos[i]].regions[j].numblocks; + if (mtd->erasesize < + mtd->eraseregions[reg_idx].erasesize) { + mtd->erasesize = + mtd->eraseregions[reg_idx].erasesize; + } + dev_size += mtd->eraseregions[reg_idx].erasesize * + mtd->eraseregions[reg_idx].numblocks; + reg_idx++; + } + offset += dev_size; + } + mtd->type = MTD_NORFLASH; + mtd->flags = MTD_CAP_NORFLASH; + mtd->name = map->name; + mtd->erase = amd_flash_erase; + mtd->read = amd_flash_read; + mtd->write = amd_flash_write; + mtd->sync = amd_flash_sync; + mtd->suspend = amd_flash_suspend; + mtd->resume = amd_flash_resume; + + private = kmalloc(sizeof(*private) + (sizeof(struct flchip) * + temp.numchips), GFP_KERNEL); + if (!private) { + printk(KERN_WARNING + "%s: kmalloc failed for private structure\n", map->name); + kfree(mtd); + map->fldrv_priv = NULL; + return NULL; + } + memcpy(private, &temp, sizeof(temp)); + memcpy(private->chips, chips, + sizeof(struct flchip) * private->numchips); + for (i = 0; i < private->numchips; i++) { + init_waitqueue_head(&private->chips[i].wq); + spin_lock_init(&private->chips[i]._spinlock); + } + + map->fldrv_priv = private; + + map->fldrv = &amd_flash_chipdrv; + MOD_INC_USE_COUNT; + + return mtd; +} + + + +static inline int read_one_chip(struct map_info *map, struct flchip *chip, + loff_t adr, size_t len, u_char *buf) +{ + DECLARE_WAITQUEUE(wait, current); + unsigned long timeo = jiffies + HZ; + +retry: + spin_lock_bh(chip->mutex); + + if (chip->state != FL_READY){ + printk(KERN_INFO "%s: waiting for chip to read, state = %d\n", + map->name, chip->state); + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + spin_unlock_bh(chip->mutex); + + schedule(); + remove_wait_queue(&chip->wq, &wait); + + if(signal_pending(current)) { + return -EINTR; + } + + timeo = jiffies + HZ; + + goto retry; + } + + adr += chip->start; + + chip->state = FL_READY; + + map->copy_from(map, buf, adr, len); + + wake_up(&chip->wq); + spin_unlock_bh(chip->mutex); + + return 0; +} + + + +static int amd_flash_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct map_info *map = mtd->priv; + struct amd_flash_private *private = map->fldrv_priv; + unsigned long ofs; + int chipnum; + int ret = 0; + + if ((from + len) > mtd->size) { + printk(KERN_WARNING "%s: read request past end of device " + "(0x%lx)\n", map->name, (unsigned long)from + len); + + return -EINVAL; + } + + /* Offset within the first chip that the first read should start. */ + chipnum = (from >> private->chipshift); + ofs = from - (chipnum << private->chipshift); + + *retlen = 0; + + while (len) { + unsigned long this_len; + + if (chipnum >= private->numchips) { + break; + } + + if ((len + ofs - 1) >> private->chipshift) { + this_len = (1 << private->chipshift) - ofs; + } else { + this_len = len; + } + + ret = read_one_chip(map, &private->chips[chipnum], ofs, + this_len, buf); + if (ret) { + break; + } + + *retlen += this_len; + len -= this_len; + buf += this_len; + + ofs = 0; + chipnum++; + } + + return ret; +} + + + +static int write_one_word(struct map_info *map, struct flchip *chip, + unsigned long adr, __u32 datum) +{ + unsigned long timeo = jiffies + HZ; + struct amd_flash_private *private = map->fldrv_priv; + DECLARE_WAITQUEUE(wait, current); + int ret = 0; + int times_left; + +retry: + spin_lock_bh(chip->mutex); + + if (chip->state != FL_READY){ + printk("%s: waiting for chip to write, state = %d\n", + map->name, chip->state); + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + spin_unlock_bh(chip->mutex); + + schedule(); + remove_wait_queue(&chip->wq, &wait); + printk(KERN_INFO "%s: woke up to write\n", map->name); + if(signal_pending(current)) + return -EINTR; + + timeo = jiffies + HZ; + + goto retry; + } + + chip->state = FL_WRITING; + + adr += chip->start; + ENABLE_VPP(map); + send_cmd(map, chip->start, CMD_PROGRAM_UNLOCK_DATA); + wide_write(map, datum, adr); + + times_left = 500000; + while (times_left-- && flash_is_busy(map, chip->start, + private->interleave)) { + if (current->need_resched) { + spin_unlock_bh(chip->mutex); + schedule(); + spin_lock_bh(chip->mutex); + } + } + + if (!times_left) { + printk(KERN_WARNING "%s: write to 0x%lx timed out!\n", + map->name, adr); + ret = -EIO; + } else { + __u32 verify; + if ((verify = wide_read(map, adr)) != datum) { + printk(KERN_WARNING "%s: write to 0x%lx failed. " + "datum = %x, verify = %x\n", + map->name, adr, datum, verify); + ret = -EIO; + } + } + + DISABLE_VPP(map); + chip->state = FL_READY; + wake_up(&chip->wq); + spin_unlock_bh(chip->mutex); + + return ret; +} + + + +static int amd_flash_write(struct mtd_info *mtd, loff_t to , size_t len, + size_t *retlen, const u_char *buf) +{ + struct map_info *map = mtd->priv; + struct amd_flash_private *private = map->fldrv_priv; + int ret = 0; + int chipnum; + unsigned long ofs; + unsigned long chipstart; + + *retlen = 0; + if (!len) { + return 0; + } + + chipnum = to >> private->chipshift; + ofs = to - (chipnum << private->chipshift); + chipstart = private->chips[chipnum].start; + + /* If it's not bus-aligned, do the first byte write. */ + if (ofs & (map->buswidth - 1)) { + unsigned long bus_ofs = ofs & ~(map->buswidth - 1); + int i = ofs - bus_ofs; + int n = 0; + u_char tmp_buf[4]; + __u32 datum; + + map->copy_from(map, tmp_buf, + bus_ofs + private->chips[chipnum].start, + map->buswidth); + while (len && i < map->buswidth) + tmp_buf[i++] = buf[n++], len--; + + if (map->buswidth == 2) { + datum = *(__u16*)tmp_buf; + } else if (map->buswidth == 4) { + datum = *(__u32*)tmp_buf; + } else { + return -EINVAL; /* should never happen, but be safe */ + } + + ret = write_one_word(map, &private->chips[chipnum], bus_ofs, + datum); + if (ret) { + return ret; + } + + ofs += n; + buf += n; + (*retlen) += n; + + if (ofs >> private->chipshift) { + chipnum++; + ofs = 0; + if (chipnum == private->numchips) { + return 0; + } + } + } + + /* We are now aligned, write as much as possible. */ + while(len >= map->buswidth) { + __u32 datum; + + if (map->buswidth == 1) { + datum = *(__u8*)buf; + } else if (map->buswidth == 2) { + datum = *(__u16*)buf; + } else if (map->buswidth == 4) { + datum = *(__u32*)buf; + } else { + return -EINVAL; + } + + ret = write_one_word(map, &private->chips[chipnum], ofs, datum); + + if (ret) { + return ret; + } + + ofs += map->buswidth; + buf += map->buswidth; + (*retlen) += map->buswidth; + len -= map->buswidth; + + if (ofs >> private->chipshift) { + chipnum++; + ofs = 0; + if (chipnum == private->numchips) { + return 0; + } + chipstart = private->chips[chipnum].start; + } + } + + if (len & (map->buswidth - 1)) { + int i = 0, n = 0; + u_char tmp_buf[2]; + __u32 datum; + + map->copy_from(map, tmp_buf, + ofs + private->chips[chipnum].start, + map->buswidth); + while (len--) { + tmp_buf[i++] = buf[n++]; + } + + if (map->buswidth == 2) { + datum = *(__u16*)tmp_buf; + } else if (map->buswidth == 4) { + datum = *(__u32*)tmp_buf; + } else { + return -EINVAL; /* should never happen, but be safe */ + } + + ret = write_one_word(map, &private->chips[chipnum], ofs, datum); + + if (ret) { + return ret; + } + + (*retlen) += n; + } + + return 0; +} + + + +static inline int erase_one_block(struct map_info *map, struct flchip *chip, + unsigned long adr, u_long size) +{ + unsigned long timeo = jiffies + HZ; + struct amd_flash_private *private = map->fldrv_priv; + DECLARE_WAITQUEUE(wait, current); + +retry: + spin_lock_bh(chip->mutex); + + if (chip->state != FL_READY){ + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + spin_unlock_bh(chip->mutex); + + schedule(); + remove_wait_queue(&chip->wq, &wait); + + if (signal_pending(current)) { + return -EINTR; + } + + timeo = jiffies + HZ; + + goto retry; + } + + chip->state = FL_ERASING; + + adr += chip->start; + ENABLE_VPP(map); + send_cmd(map, chip->start, CMD_SECTOR_ERASE_UNLOCK_DATA); + send_cmd_to_addr(map, chip->start, CMD_SECTOR_ERASE_UNLOCK_DATA_2, adr); + + timeo = jiffies + (HZ * 20); + + spin_unlock_bh(chip->mutex); + schedule_timeout(HZ); + spin_lock_bh(chip->mutex); + + while (flash_is_busy(map, chip->start, private->interleave)) { + + if (chip->state != FL_ERASING) { + /* Someone's suspended the erase. Sleep */ + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + spin_unlock_bh(chip->mutex); + printk(KERN_INFO "%s: erase suspended. Sleeping\n", + map->name); + schedule(); + remove_wait_queue(&chip->wq, &wait); + + if (signal_pending(current)) { + return -EINTR; + } + + timeo = jiffies + (HZ*2); /* FIXME */ + spin_lock_bh(chip->mutex); + continue; + } + + /* OK Still waiting */ + if (time_after(jiffies, timeo)) { + chip->state = FL_READY; + spin_unlock_bh(chip->mutex); + printk(KERN_WARNING "%s: waiting for erase to complete " + "timed out.\n", map->name); + DISABLE_VPP(map); + + return -EIO; + } + + /* Latency issues. Drop the lock, wait a while and retry */ + spin_unlock_bh(chip->mutex); + + if (current->need_resched) + schedule(); + else + udelay(1); + + spin_lock_bh(chip->mutex); + } + + /* Verify every single word */ + { + int address; + int error = 0; + __u8 verify; + + for (address = adr; address < (adr + size); address++) { + if ((verify = map->read8(map, address)) != 0xFF) { + error = 1; + break; + } + } + if (error) { + chip->state = FL_READY; + spin_unlock_bh(chip->mutex); + printk(KERN_WARNING + "%s: verify error at 0x%x, size %ld.\n", + map->name, address, size); + DISABLE_VPP(map); + + return -EIO; + } + } + + DISABLE_VPP(map); + chip->state = FL_READY; + wake_up(&chip->wq); + spin_unlock_bh(chip->mutex); + + return 0; +} + + + +static int amd_flash_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + struct map_info *map = mtd->priv; + struct amd_flash_private *private = map->fldrv_priv; + unsigned long adr, len; + int chipnum; + int ret = 0; + int i; + int first; + struct mtd_erase_region_info *regions = mtd->eraseregions; + + if (instr->addr > mtd->size) { + return -EINVAL; + } + + if ((instr->len + instr->addr) > mtd->size) { + return -EINVAL; + } + + /* Check that both start and end of the requested erase are + * aligned with the erasesize at the appropriate addresses. + */ + + i = 0; + + /* Skip all erase regions which are ended before the start of + the requested erase. Actually, to save on the calculations, + we skip to the first erase region which starts after the + start of the requested erase, and then go back one. + */ + + while ((i < mtd->numeraseregions) && + (instr->addr >= regions[i].offset)) { + i++; + } + i--; + + /* OK, now i is pointing at the erase region in which this + * erase request starts. Check the start of the requested + * erase range is aligned with the erase size which is in + * effect here. + */ + + if (instr->addr & (regions[i].erasesize-1)) { + return -EINVAL; + } + + /* Remember the erase region we start on. */ + + first = i; + + /* Next, check that the end of the requested erase is aligned + * with the erase region at that address. + */ + + while ((i < mtd->numeraseregions) && + ((instr->addr + instr->len) >= regions[i].offset)) { + i++; + } + + /* As before, drop back one to point at the region in which + * the address actually falls. + */ + + i--; + + if ((instr->addr + instr->len) & (regions[i].erasesize-1)) { + return -EINVAL; + } + + chipnum = instr->addr >> private->chipshift; + adr = instr->addr - (chipnum << private->chipshift); + len = instr->len; + + i = first; + + while (len) { + ret = erase_one_block(map, &private->chips[chipnum], adr, + regions[i].erasesize); + + if (ret) { + return ret; + } + + adr += regions[i].erasesize; + len -= regions[i].erasesize; + + if ((adr % (1 << private->chipshift)) == + ((regions[i].offset + (regions[i].erasesize * + regions[i].numblocks)) + % (1 << private->chipshift))) { + i++; + } + + if (adr >> private->chipshift) { + adr = 0; + chipnum++; + if (chipnum >= private->numchips) { + break; + } + } + } + + instr->state = MTD_ERASE_DONE; + if (instr->callback) { + instr->callback(instr); + } + + return 0; +} + + + +static void amd_flash_sync(struct mtd_info *mtd) +{ + struct map_info *map = mtd->priv; + struct amd_flash_private *private = map->fldrv_priv; + int i; + struct flchip *chip; + int ret = 0; + DECLARE_WAITQUEUE(wait, current); + + for (i = 0; !ret && (i < private->numchips); i++) { + chip = &private->chips[i]; + + retry: + spin_lock_bh(chip->mutex); + + switch(chip->state) { + case FL_READY: + case FL_STATUS: + case FL_CFI_QUERY: + case FL_JEDEC_QUERY: + chip->oldstate = chip->state; + chip->state = FL_SYNCING; + /* No need to wake_up() on this state change - + * as the whole point is that nobody can do anything + * with the chip now anyway. + */ + case FL_SYNCING: + spin_unlock_bh(chip->mutex); + break; + + default: + /* Not an idle state */ + add_wait_queue(&chip->wq, &wait); + + spin_unlock_bh(chip->mutex); + + schedule(); + + remove_wait_queue(&chip->wq, &wait); + + goto retry; + } + } + + /* Unlock the chips again */ + for (i--; i >= 0; i--) { + chip = &private->chips[i]; + + spin_lock_bh(chip->mutex); + + if (chip->state == FL_SYNCING) { + chip->state = chip->oldstate; + wake_up(&chip->wq); + } + spin_unlock_bh(chip->mutex); + } +} + + + +static int amd_flash_suspend(struct mtd_info *mtd) +{ +printk("amd_flash_suspend(): not implemented!\n"); + return -EINVAL; +} + + + +static void amd_flash_resume(struct mtd_info *mtd) +{ +printk("amd_flash_resume(): not implemented!\n"); +} + + + +static void amd_flash_destroy(struct mtd_info *mtd) +{ + struct map_info *map = mtd->priv; + struct amd_flash_private *private = map->fldrv_priv; + kfree(private); +} + +int __init amd_flash_init(void) +{ + register_mtd_chip_driver(&amd_flash_chipdrv); + return 0; +} + +void __exit amd_flash_exit(void) +{ + unregister_mtd_chip_driver(&amd_flash_chipdrv); +} + +module_init(amd_flash_init); +module_exit(amd_flash_exit); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/chips/cfi_cmdset_0001.c linux/drivers/mtd/chips/cfi_cmdset_0001.c --- v2.4.5/linux/drivers/mtd/chips/cfi_cmdset_0001.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/chips/cfi_cmdset_0001.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,1636 @@ +/* + * Common Flash Interface support: + * Intel Extended Vendor Command Set (ID 0x0001) + * + * (C) 2000 Red Hat. GPL'd + * + * $Id: cfi_cmdset_0001.c,v 1.80 2001/06/03 01:32:57 nico Exp $ + * + * + * 10/10/2000 Nicolas Pitre + * - completely revamped method functions so they are aware and + * independent of the flash geometry (buswidth, interleave, etc.) + * - scalability vs code size is completely set at compile-time + * (see include/linux/mtd/cfi.h for selection) + * - optimized write buffer method + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +static int cfi_intelext_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); +static int cfi_intelext_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); +static int cfi_intelext_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); +static int cfi_intelext_erase_varsize(struct mtd_info *, struct erase_info *); +static void cfi_intelext_sync (struct mtd_info *); +static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len); +static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, size_t len); +static int cfi_intelext_suspend (struct mtd_info *); +static void cfi_intelext_resume (struct mtd_info *); + +static void cfi_intelext_destroy(struct mtd_info *); + +void cfi_cmdset_0001(struct map_info *, int, unsigned long); + +static struct mtd_info *cfi_intelext_setup (struct map_info *); + +static struct mtd_chip_driver cfi_intelext_chipdrv = { + probe: cfi_intelext_setup, + destroy: cfi_intelext_destroy, + name: "cfi_intel", + module: THIS_MODULE +}; + +/* #define DEBUG_LOCK_BITS */ + +/* This routine is made available to other mtd code via + * inter_module_register. It must only be accessed through + * inter_module_get which will bump the use count of this module. The + * addresses passed back in cfi are valid as long as the use count of + * this module is non-zero, i.e. between inter_module_get and + * inter_module_put. Keith Owens 29 Oct 2000. + */ +void cfi_cmdset_0001(struct map_info *map, int primary, unsigned long base) +{ + struct cfi_private *cfi = map->fldrv_priv; + int i; + struct cfi_pri_intelext *extp; + int ofs_factor = cfi->interleave * cfi->device_type; + + __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR; + + //printk(" Intel/Sharp Extended Query Table at 0x%4.4X\n", adr); + + if (!adr) + return; + + /* Switch it into Query Mode */ + switch(CFIDEV_BUSWIDTH) { + case 1: + map->write8(map, 0x98, 0x55); + break; + case 2: + map->write16(map, 0x9898, 0xaa); + break; + case 4: + map->write32(map, 0x98989898, 0x154); + break; + } + + extp = kmalloc(sizeof(*extp), GFP_KERNEL); + if (!extp) { + printk("Failed to allocate memory\n"); + return; + } + + /* Read in the Extended Query Table */ + for (i=0; iinterleave*cfi->device_type))); + } + + if (extp->MajorVersion != '1' || + (extp->MinorVersion < '0' || extp->MinorVersion > '2')) { + printk(" Unknown IntelExt Extended Query version %c.%c.\n", + extp->MajorVersion, extp->MinorVersion); + kfree(extp); + return; + } + + /* Do some byteswapping if necessary */ + extp->FeatureSupport = cfi32_to_cpu(extp->FeatureSupport); + extp->BlkStatusRegMask = cfi32_to_cpu(extp->BlkStatusRegMask); + + + /* Tell the user about it in lots of lovely detail */ +#if 0 + printk(" Feature/Command Support: %4.4X\n", extp->FeatureSupport); + printk(" - Chip Erase: %s\n", extp->FeatureSupport&1?"supported":"unsupported"); + printk(" - Suspend Erase: %s\n", extp->FeatureSupport&2?"supported":"unsupported"); + printk(" - Suspend Program: %s\n", extp->FeatureSupport&4?"supported":"unsupported"); + printk(" - Legacy Lock/Unlock: %s\n", extp->FeatureSupport&8?"supported":"unsupported"); + printk(" - Queued Erase: %s\n", extp->FeatureSupport&16?"supported":"unsupported"); + printk(" - Instant block lock: %s\n", extp->FeatureSupport&32?"supported":"unsupported"); + printk(" - Protection Bits: %s\n", extp->FeatureSupport&64?"supported":"unsupported"); + printk(" - Page-mode read: %s\n", extp->FeatureSupport&128?"supported":"unsupported"); + printk(" - Synchronous read: %s\n", extp->FeatureSupport&256?"supported":"unsupported"); + for (i=9; i<32; i++) { + if (extp->FeatureSupport & (1<SuspendCmdSupport); + printk(" - Program after Erase Suspend: %s\n", extp->SuspendCmdSupport&1?"supported":"unsupported"); + for (i=1; i<8; i++) { + if (extp->SuspendCmdSupport & (1<BlkStatusRegMask); + printk(" - Lock Bit Active: %s\n", extp->BlkStatusRegMask&1?"yes":"no"); + printk(" - Valid Bit Active: %s\n", extp->BlkStatusRegMask&2?"yes":"no"); + for (i=2; i<16; i++) { + if (extp->BlkStatusRegMask & (1<VccOptimal >> 8, extp->VccOptimal & 0xf); + if (extp->VppOptimal) + printk(" Vpp Programming Supply Optimum Program/Erase Voltage: %d.%d V\n", + extp->VppOptimal >> 8, extp->VppOptimal & 0xf); +#endif + /* OK. We like it. Take over the control of it. */ + + /* Switch it into Read Mode */ + switch(CFIDEV_BUSWIDTH) { + case 1: + map->write8(map, 0xff, 0x55); + break; + case 2: + map->write16(map, 0xffff, 0xaa); + break; + case 4: + map->write32(map, 0xffffffff, 0x154); + break; + } + + + /* If there was an old setup function, decrease its use count */ + if (map->fldrv) + if(map->fldrv->module) + __MOD_DEC_USE_COUNT(map->fldrv->module); + + if (cfi->cmdset_priv) + kfree(cfi->cmdset_priv); + + for (i=0; i< cfi->numchips; i++) { + cfi->chips[i].word_write_time = 128; + cfi->chips[i].buffer_write_time = 128; + cfi->chips[i].erase_time = 1024; + } + + + map->fldrv = &cfi_intelext_chipdrv; + MOD_INC_USE_COUNT; + + cfi->cmdset_priv = extp; + +#if 1 /* Does this work? */ + cfi_send_gen_cmd(0x90, 0x55, base, map, cfi, cfi->device_type, NULL); + + cfi->mfr = cfi_read_query(map, base); + cfi->id = cfi_read_query(map, base + ofs_factor); + + printk("JEDEC ID: %2.2X %2.2X\n", cfi->mfr, cfi->id); +#endif + + cfi_send_gen_cmd(0xff, 0x55, 0, map, cfi, cfi->device_type, NULL); + return; +} + +static struct mtd_info *cfi_intelext_setup(struct map_info *map) +{ + struct cfi_private *cfi = map->fldrv_priv; + struct mtd_info *mtd; + unsigned long offset = 0; + int i,j; + unsigned long devsize = (1<cfiq->DevSize) * cfi->interleave; + + mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); + //printk("number of CFI chips: %d\n", cfi->numchips); + + if (!mtd) { + printk("Failed to allocate memory for MTD device\n"); + kfree(cfi->cmdset_priv); + return NULL; + } + + memset(mtd, 0, sizeof(*mtd)); + mtd->priv = map; + mtd->type = MTD_NORFLASH; + mtd->size = devsize * cfi->numchips; + + mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips; + mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) + * mtd->numeraseregions, GFP_KERNEL); + if (!mtd->eraseregions) { + printk("Failed to allocate memory for MTD erase region info\n"); + kfree(cfi->cmdset_priv); + return NULL; + } + + for (i=0; icfiq->NumEraseRegions; i++) { + unsigned long ernum, ersize; + ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff) * cfi->interleave; + ernum = (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1; + + if (mtd->erasesize < ersize) { + mtd->erasesize = ersize; + } + for (j=0; jnumchips; j++) { + mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].offset = (j*devsize)+offset; + mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].erasesize = ersize; + mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].numblocks = ernum; + } + offset += (ersize * ernum); + } + + if (offset != devsize) { + /* Argh */ + printk("Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize); + kfree(mtd->eraseregions); + kfree(cfi->cmdset_priv); + return NULL; + } + + for (i=0; inumeraseregions;i++){ + printk("%d: offset=0x%x,size=0x%x,blocks=%d\n", + i,mtd->eraseregions[i].offset, + mtd->eraseregions[i].erasesize, + mtd->eraseregions[i].numblocks); + } + + /* Also select the correct geometry setup too */ + mtd->erase = cfi_intelext_erase_varsize; + mtd->read = cfi_intelext_read; + if ( cfi->cfiq->BufWriteTimeoutTyp ) { + //printk( KERN_INFO"Using buffer write method\n" ); + mtd->write = cfi_intelext_write_buffers; + } else { + //printk( KERN_INFO"Using word write method\n" ); + mtd->write = cfi_intelext_write_words; + } + mtd->sync = cfi_intelext_sync; + mtd->lock = cfi_intelext_lock; + mtd->unlock = cfi_intelext_unlock; + mtd->suspend = cfi_intelext_suspend; + mtd->resume = cfi_intelext_resume; + mtd->flags = MTD_CAP_NORFLASH; + map->fldrv = &cfi_intelext_chipdrv; + MOD_INC_USE_COUNT; + mtd->name = map->name; + return mtd; +} + + +static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf) +{ + __u32 status, status_OK; + unsigned long timeo; + DECLARE_WAITQUEUE(wait, current); + int suspended = 0; + unsigned long cmd_addr; + struct cfi_private *cfi = map->fldrv_priv; + + adr += chip->start; + + /* Ensure cmd read/writes are aligned. */ + cmd_addr = adr & ~(CFIDEV_BUSWIDTH-1); + + /* Let's determine this according to the interleave only once */ + status_OK = CMD(0x80); + + timeo = jiffies + HZ; + retry: + spin_lock_bh(chip->mutex); + + /* Check that the chip's ready to talk to us. + * If it's in FL_ERASING state, suspend it and make it talk now. + */ + switch (chip->state) { + case FL_ERASING: + cfi_write (map, CMD(0xb0), cmd_addr); + chip->oldstate = FL_ERASING; + chip->state = FL_ERASE_SUSPENDING; +// printk("Erase suspending at 0x%lx\n", cmd_addr); + for (;;) { + status = cfi_read(map, cmd_addr); + if ((status & status_OK) == status_OK) + break; + + if (time_after(jiffies, timeo)) { + /* Urgh */ + cfi_write(map, CMD(0xd0), cmd_addr); + chip->state = FL_ERASING; + spin_unlock_bh(chip->mutex); + printk("Chip not ready after erase suspended\n"); + return -EIO; + } + + spin_unlock_bh(chip->mutex); + cfi_udelay(1); + spin_lock_bh(chip->mutex); + } + + suspended = 1; + cfi_write(map, CMD(0xff), cmd_addr); + chip->state = FL_READY; + break; + +#if 0 + case FL_WRITING: + /* Not quite yet */ +#endif + + case FL_READY: + break; + + case FL_CFI_QUERY: + case FL_JEDEC_QUERY: + cfi_write(map, CMD(0x70), cmd_addr); + chip->state = FL_STATUS; + + case FL_STATUS: + status = cfi_read(map, cmd_addr); + if ((status & status_OK) == status_OK) { + cfi_write(map, CMD(0xff), cmd_addr); + chip->state = FL_READY; + break; + } + + /* Urgh. Chip not yet ready to talk to us. */ + if (time_after(jiffies, timeo)) { + spin_unlock_bh(chip->mutex); + printk("waiting for chip to be ready timed out in read. WSM status = %x\n", status); + return -EIO; + } + + /* Latency issues. Drop the lock, wait a while and retry */ + spin_unlock_bh(chip->mutex); + cfi_udelay(1); + goto retry; + + default: + /* Stick ourselves on a wait queue to be woken when + someone changes the status */ + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + spin_unlock_bh(chip->mutex); + schedule(); + remove_wait_queue(&chip->wq, &wait); + timeo = jiffies + HZ; + goto retry; + } + + map->copy_from(map, buf, adr, len); + + if (suspended) { + chip->state = chip->oldstate; + /* What if one interleaved chip has finished and the + other hasn't? The old code would leave the finished + one in READY mode. That's bad, and caused -EROFS + errors to be returned from do_erase_oneblock because + that's the only bit it checked for at the time. + As the state machine appears to explicitly allow + sending the 0x70 (Read Status) command to an erasing + chip and expecting it to be ignored, that's what we + do. */ + cfi_write(map, CMD(0xd0), cmd_addr); + cfi_write(map, CMD(0x70), cmd_addr); + } + + wake_up(&chip->wq); + spin_unlock_bh(chip->mutex); + return 0; +} + +static int cfi_intelext_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + unsigned long ofs; + int chipnum; + int ret = 0; + + /* ofs: offset within the first chip that the first read should start */ + chipnum = (from >> cfi->chipshift); + ofs = from - (chipnum << cfi->chipshift); + + *retlen = 0; + + while (len) { + unsigned long thislen; + + if (chipnum >= cfi->numchips) + break; + + if ((len + ofs -1) >> cfi->chipshift) + thislen = (1<chipshift) - ofs; + else + thislen = len; + + ret = do_read_onechip(map, &cfi->chips[chipnum], ofs, thislen, buf); + if (ret) + break; + + *retlen += thislen; + len -= thislen; + buf += thislen; + + ofs = 0; + chipnum++; + } + return ret; +} + +static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, __u32 datum) +{ + struct cfi_private *cfi = map->fldrv_priv; + __u32 status, status_OK; + unsigned long timeo; + DECLARE_WAITQUEUE(wait, current); + int z; + + adr += chip->start; + + /* Let's determine this according to the interleave only once */ + status_OK = CMD(0x80); + + timeo = jiffies + HZ; + retry: + spin_lock_bh(chip->mutex); + + /* Check that the chip's ready to talk to us. + * Later, we can actually think about interrupting it + * if it's in FL_ERASING state. + * Not just yet, though. + */ + switch (chip->state) { + case FL_READY: + break; + + case FL_CFI_QUERY: + case FL_JEDEC_QUERY: + cfi_write(map, CMD(0x70), adr); + chip->state = FL_STATUS; + + case FL_STATUS: + status = cfi_read(map, adr); + if ((status & status_OK) == status_OK) + break; + + /* Urgh. Chip not yet ready to talk to us. */ + if (time_after(jiffies, timeo)) { + spin_unlock_bh(chip->mutex); + printk("waiting for chip to be ready timed out in read\n"); + return -EIO; + } + + /* Latency issues. Drop the lock, wait a while and retry */ + spin_unlock_bh(chip->mutex); + cfi_udelay(1); + goto retry; + + default: + /* Stick ourselves on a wait queue to be woken when + someone changes the status */ + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + spin_unlock_bh(chip->mutex); + schedule(); + remove_wait_queue(&chip->wq, &wait); + timeo = jiffies + HZ; + goto retry; + } + + ENABLE_VPP(map); + cfi_write(map, CMD(0x40), adr); + cfi_write(map, datum, adr); + chip->state = FL_WRITING; + + spin_unlock_bh(chip->mutex); + cfi_udelay(chip->word_write_time); + spin_lock_bh(chip->mutex); + + timeo = jiffies + (HZ/2); + z = 0; + for (;;) { + if (chip->state != FL_WRITING) { + /* Someone's suspended the write. Sleep */ + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + spin_unlock_bh(chip->mutex); + schedule(); + remove_wait_queue(&chip->wq, &wait); + timeo = jiffies + (HZ / 2); /* FIXME */ + spin_lock_bh(chip->mutex); + continue; + } + + status = cfi_read(map, adr); + if ((status & status_OK) == status_OK) + break; + + /* OK Still waiting */ + if (time_after(jiffies, timeo)) { + chip->state = FL_STATUS; + DISABLE_VPP(map); + spin_unlock_bh(chip->mutex); + printk("waiting for chip to be ready timed out in word write\n"); + return -EIO; + } + + /* Latency issues. Drop the lock, wait a while and retry */ + spin_unlock_bh(chip->mutex); + z++; + cfi_udelay(1); + spin_lock_bh(chip->mutex); + } + if (!z) { + chip->word_write_time--; + if (!chip->word_write_time) + chip->word_write_time++; + } + if (z > 1) + chip->word_write_time++; + + /* Done and happy. */ + DISABLE_VPP(map); + chip->state = FL_STATUS; + /* check for lock bit */ + if (status & CMD(0x02)) { + /* clear status */ + cfi_write(map, CMD(0x50), adr); + /* put back into read status register mode */ + cfi_write(map, CMD(0x70), adr); + wake_up(&chip->wq); + spin_unlock_bh(chip->mutex); + return -EROFS; + } + wake_up(&chip->wq); + spin_unlock_bh(chip->mutex); + return 0; +} + + +static int cfi_intelext_write_words (struct mtd_info *mtd, loff_t to , size_t len, size_t *retlen, const u_char *buf) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + int ret = 0; + int chipnum; + unsigned long ofs; + + *retlen = 0; + if (!len) + return 0; + + chipnum = to >> cfi->chipshift; + ofs = to - (chipnum << cfi->chipshift); + + /* If it's not bus-aligned, do the first byte write */ + if (ofs & (CFIDEV_BUSWIDTH-1)) { + unsigned long bus_ofs = ofs & ~(CFIDEV_BUSWIDTH-1); + int gap = ofs - bus_ofs; + int i = 0, n = 0; + u_char tmp_buf[4]; + __u32 datum; + + while (gap--) + tmp_buf[i++] = 0xff; + while (len && i < CFIDEV_BUSWIDTH) + tmp_buf[i++] = buf[n++], len--; + while (i < CFIDEV_BUSWIDTH) + tmp_buf[i++] = 0xff; + + if (cfi_buswidth_is_2()) { + datum = *(__u16*)tmp_buf; + } else if (cfi_buswidth_is_4()) { + datum = *(__u32*)tmp_buf; + } else { + return -EINVAL; /* should never happen, but be safe */ + } + + ret = do_write_oneword(map, &cfi->chips[chipnum], + bus_ofs, datum); + if (ret) + return ret; + + ofs += n; + buf += n; + (*retlen) += n; + + if (ofs >> cfi->chipshift) { + chipnum ++; + ofs = 0; + if (chipnum == cfi->numchips) + return 0; + } + } + + while(len >= CFIDEV_BUSWIDTH) { + __u32 datum; + + if (cfi_buswidth_is_1()) { + datum = *(__u8*)buf; + } else if (cfi_buswidth_is_2()) { + datum = *(__u16*)buf; + } else if (cfi_buswidth_is_4()) { + datum = *(__u32*)buf; + } else { + return -EINVAL; + } + + ret = do_write_oneword(map, &cfi->chips[chipnum], + ofs, datum); + if (ret) + return ret; + + ofs += CFIDEV_BUSWIDTH; + buf += CFIDEV_BUSWIDTH; + (*retlen) += CFIDEV_BUSWIDTH; + len -= CFIDEV_BUSWIDTH; + + if (ofs >> cfi->chipshift) { + chipnum ++; + ofs = 0; + if (chipnum == cfi->numchips) + return 0; + } + } + + if (len & (CFIDEV_BUSWIDTH-1)) { + int i = 0, n = 0; + u_char tmp_buf[4]; + __u32 datum; + + while (len--) + tmp_buf[i++] = buf[n++]; + while (i < CFIDEV_BUSWIDTH) + tmp_buf[i++] = 0xff; + + if (cfi_buswidth_is_2()) { + datum = *(__u16*)tmp_buf; + } else if (cfi_buswidth_is_4()) { + datum = *(__u32*)tmp_buf; + } else { + return -EINVAL; /* should never happen, but be safe */ + } + + ret = do_write_oneword(map, &cfi->chips[chipnum], + ofs, datum); + if (ret) + return ret; + + (*retlen) += n; + } + + return 0; +} + + +static inline int do_write_buffer(struct map_info *map, struct flchip *chip, + unsigned long adr, const u_char *buf, int len) +{ + struct cfi_private *cfi = map->fldrv_priv; + __u32 status, status_OK; + unsigned long cmd_adr, timeo; + DECLARE_WAITQUEUE(wait, current); + int wbufsize, z; + + wbufsize = CFIDEV_INTERLEAVE << cfi->cfiq->MaxBufWriteSize; + adr += chip->start; + cmd_adr = adr & ~(wbufsize-1); + + /* Let's determine this according to the interleave only once */ + status_OK = CMD(0x80); + + timeo = jiffies + HZ; + retry: + spin_lock_bh(chip->mutex); + + /* Check that the chip's ready to talk to us. + * Later, we can actually think about interrupting it + * if it's in FL_ERASING state. + * Not just yet, though. + */ + switch (chip->state) { + case FL_READY: + break; + + case FL_CFI_QUERY: + case FL_JEDEC_QUERY: + cfi_write(map, CMD(0x70), cmd_adr); + chip->state = FL_STATUS; + + case FL_STATUS: + status = cfi_read(map, cmd_adr); + if ((status & status_OK) == status_OK) + break; + /* Urgh. Chip not yet ready to talk to us. */ + if (time_after(jiffies, timeo)) { + spin_unlock_bh(chip->mutex); + printk("waiting for chip to be ready timed out in buffer write\n"); + return -EIO; + } + + /* Latency issues. Drop the lock, wait a while and retry */ + spin_unlock_bh(chip->mutex); + cfi_udelay(1); + goto retry; + + default: + /* Stick ourselves on a wait queue to be woken when + someone changes the status */ + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + spin_unlock_bh(chip->mutex); + schedule(); + remove_wait_queue(&chip->wq, &wait); + timeo = jiffies + HZ; + goto retry; + } + + ENABLE_VPP(map); + cfi_write(map, CMD(0xe8), cmd_adr); + chip->state = FL_WRITING_TO_BUFFER; + + z = 0; + for (;;) { + status = cfi_read(map, cmd_adr); + if ((status & status_OK) == status_OK) + break; + + spin_unlock_bh(chip->mutex); + cfi_udelay(1); + spin_lock_bh(chip->mutex); + + if (++z > 20) { + /* Argh. Not ready for write to buffer */ + cfi_write(map, CMD(0x70), cmd_adr); + chip->state = FL_STATUS; + DISABLE_VPP(map); + spin_unlock_bh(chip->mutex); + printk("Chip not ready for buffer write. Xstatus = %x, status = %x\n", status, cfi_read(map, cmd_adr)); + return -EIO; + } + } + + /* Write length of data to come */ + cfi_write(map, CMD(len/CFIDEV_BUSWIDTH-1), cmd_adr ); + + /* Write data */ + for (z = 0; z < len; z += CFIDEV_BUSWIDTH) { + if (cfi_buswidth_is_1()) { + map->write8 (map, *((__u8*)buf)++, adr+z); + } else if (cfi_buswidth_is_2()) { + map->write16 (map, *((__u16*)buf)++, adr+z); + } else if (cfi_buswidth_is_4()) { + map->write32 (map, *((__u32*)buf)++, adr+z); + } else { + DISABLE_VPP(map); + return -EINVAL; + } + } + /* GO GO GO */ + cfi_write(map, CMD(0xd0), cmd_adr); + chip->state = FL_WRITING; + + spin_unlock_bh(chip->mutex); + cfi_udelay(chip->buffer_write_time); + spin_lock_bh(chip->mutex); + + timeo = jiffies + (HZ/2); + z = 0; + for (;;) { + if (chip->state != FL_WRITING) { + /* Someone's suspended the write. Sleep */ + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + spin_unlock_bh(chip->mutex); + schedule(); + remove_wait_queue(&chip->wq, &wait); + timeo = jiffies + (HZ / 2); /* FIXME */ + spin_lock_bh(chip->mutex); + continue; + } + + status = cfi_read(map, cmd_adr); + if ((status & status_OK) == status_OK) + break; + + /* OK Still waiting */ + if (time_after(jiffies, timeo)) { + chip->state = FL_STATUS; + DISABLE_VPP(map); + spin_unlock_bh(chip->mutex); + printk("waiting for chip to be ready timed out in bufwrite\n"); + return -EIO; + } + + /* Latency issues. Drop the lock, wait a while and retry */ + spin_unlock_bh(chip->mutex); + cfi_udelay(1); + z++; + spin_lock_bh(chip->mutex); + } + if (!z) { + chip->buffer_write_time--; + if (!chip->buffer_write_time) + chip->buffer_write_time++; + } + if (z > 1) + chip->buffer_write_time++; + + /* Done and happy. */ + DISABLE_VPP(map); + chip->state = FL_STATUS; + /* check for lock bit */ + if (status & CMD(0x02)) { + /* clear status */ + cfi_write(map, CMD(0x50), cmd_adr); + /* put back into read status register mode */ + cfi_write(map, CMD(0x70), adr); + wake_up(&chip->wq); + spin_unlock_bh(chip->mutex); + return -EROFS; + } + wake_up(&chip->wq); + spin_unlock_bh(chip->mutex); + return 0; +} + +static int cfi_intelext_write_buffers (struct mtd_info *mtd, loff_t to, + size_t len, size_t *retlen, const u_char *buf) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + int wbufsize = CFIDEV_INTERLEAVE << cfi->cfiq->MaxBufWriteSize; + int ret = 0; + int chipnum; + unsigned long ofs; + + *retlen = 0; + if (!len) + return 0; + + chipnum = to >> cfi->chipshift; + ofs = to - (chipnum << cfi->chipshift); + + /* If it's not bus-aligned, do the first word write */ + if (ofs & (CFIDEV_BUSWIDTH-1)) { + size_t local_len = (-ofs)&(CFIDEV_BUSWIDTH-1); + if (local_len > len) + local_len = len; + ret = cfi_intelext_write_words(mtd, to, local_len, + retlen, buf); + if (ret) + return ret; + ofs += local_len; + buf += local_len; + len -= local_len; + + if (ofs >> cfi->chipshift) { + chipnum ++; + ofs = 0; + if (chipnum == cfi->numchips) + return 0; + } + } + + /* Write buffer is worth it only if more than one word to write... */ + while(len > CFIDEV_BUSWIDTH) { + /* We must not cross write block boundaries */ + int size = wbufsize - (ofs & (wbufsize-1)); + + if (size > len) + size = len & ~(CFIDEV_BUSWIDTH-1); + ret = do_write_buffer(map, &cfi->chips[chipnum], + ofs, buf, size); + if (ret) + return ret; + + ofs += size; + buf += size; + (*retlen) += size; + len -= size; + + if (ofs >> cfi->chipshift) { + chipnum ++; + ofs = 0; + if (chipnum == cfi->numchips) + return 0; + } + } + + /* ... and write the remaining bytes */ + if (len > 0) { + size_t local_retlen; + ret = cfi_intelext_write_words(mtd, ofs + (chipnum << cfi->chipshift), + len, &local_retlen, buf); + if (ret) + return ret; + (*retlen) += local_retlen; + } + + return 0; +} + + +static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr) +{ + struct cfi_private *cfi = map->fldrv_priv; + __u32 status, status_OK; + unsigned long timeo; + int retries = 3; + DECLARE_WAITQUEUE(wait, current); + int ret = 0; + + adr += chip->start; + + /* Let's determine this according to the interleave only once */ + status_OK = CMD(0x80); + + timeo = jiffies + HZ; +retry: + spin_lock_bh(chip->mutex); + + /* Check that the chip's ready to talk to us. */ + switch (chip->state) { + case FL_CFI_QUERY: + case FL_JEDEC_QUERY: + case FL_READY: + cfi_write(map, CMD(0x70), adr); + chip->state = FL_STATUS; + + case FL_STATUS: + status = cfi_read(map, adr); + if ((status & status_OK) == status_OK) + break; + + /* Urgh. Chip not yet ready to talk to us. */ + if (time_after(jiffies, timeo)) { + spin_unlock_bh(chip->mutex); + printk("waiting for chip to be ready timed out in erase\n"); + return -EIO; + } + + /* Latency issues. Drop the lock, wait a while and retry */ + spin_unlock_bh(chip->mutex); + cfi_udelay(1); + goto retry; + + default: + /* Stick ourselves on a wait queue to be woken when + someone changes the status */ + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + spin_unlock_bh(chip->mutex); + schedule(); + remove_wait_queue(&chip->wq, &wait); + timeo = jiffies + HZ; + goto retry; + } + + ENABLE_VPP(map); + /* Clear the status register first */ + cfi_write(map, CMD(0x50), adr); + + /* Now erase */ + cfi_write(map, CMD(0x20), adr); + cfi_write(map, CMD(0xD0), adr); + chip->state = FL_ERASING; + + spin_unlock_bh(chip->mutex); + schedule_timeout(HZ); + spin_lock_bh(chip->mutex); + + /* FIXME. Use a timer to check this, and return immediately. */ + /* Once the state machine's known to be working I'll do that */ + + timeo = jiffies + (HZ*20); + for (;;) { + if (chip->state != FL_ERASING) { + /* Someone's suspended the erase. Sleep */ + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + spin_unlock_bh(chip->mutex); + schedule(); + remove_wait_queue(&chip->wq, &wait); + timeo = jiffies + (HZ*2); /* FIXME */ + spin_lock_bh(chip->mutex); + continue; + } + + status = cfi_read(map, adr); + if ((status & status_OK) == status_OK) + break; + + /* OK Still waiting */ + if (time_after(jiffies, timeo)) { + cfi_write(map, CMD(0x70), adr); + chip->state = FL_STATUS; + printk("waiting for erase to complete timed out. Xstatus = %x, status = %x.\n", status, cfi_read(map, adr)); + DISABLE_VPP(map); + spin_unlock_bh(chip->mutex); + return -EIO; + } + + /* Latency issues. Drop the lock, wait a while and retry */ + spin_unlock_bh(chip->mutex); + cfi_udelay(1); + spin_lock_bh(chip->mutex); + } + + DISABLE_VPP(map); + ret = 0; + + /* We've broken this before. It doesn't hurt to be safe */ + cfi_write(map, CMD(0x70), adr); + chip->state = FL_STATUS; + status = cfi_read(map, adr); + + /* check for lock bit */ + if (status & CMD(0x3a)) { + unsigned char chipstatus = status; + if (status != CMD(status & 0xff)) { + int i; + for (i = 1; i> (cfi->device_type * 8); + } + printk(KERN_WARNING "Status is not identical for all chips: 0x%x. Merging to give 0x%02x\n", status, chipstatus); + } + /* Reset the error bits */ + cfi_write(map, CMD(0x50), adr); + cfi_write(map, CMD(0x70), adr); + + if ((chipstatus & 0x30) == 0x30) { + printk(KERN_NOTICE "Chip reports improper command sequence: status 0x%x\n", status); + ret = -EIO; + } else if (chipstatus & 0x02) { + /* Protection bit set */ + ret = -EROFS; + } else if (chipstatus & 0x8) { + /* Voltage */ + printk(KERN_WARNING "Chip reports voltage low on erase: status 0x%x\n", status); + ret = -EIO; + } else if (chipstatus & 0x20) { + if (retries--) { + printk(KERN_DEBUG "Chip erase failed at 0x%08lx: status 0x%x. Retrying...\n", adr, status); + timeo = jiffies + HZ; + chip->state = FL_STATUS; + spin_unlock_bh(chip->mutex); + goto retry; + } + printk(KERN_DEBUG "Chip erase failed at 0x%08lx: status 0x%x\n", adr, status); + ret = -EIO; + } + } + + wake_up(&chip->wq); + spin_unlock_bh(chip->mutex); + return ret; +} + +int cfi_intelext_erase_varsize(struct mtd_info *mtd, struct erase_info *instr) +{ struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + unsigned long adr, len; + int chipnum, ret = 0; + int i, first; + struct mtd_erase_region_info *regions = mtd->eraseregions; + + if (instr->addr > mtd->size) + return -EINVAL; + + if ((instr->len + instr->addr) > mtd->size) + return -EINVAL; + + /* Check that both start and end of the requested erase are + * aligned with the erasesize at the appropriate addresses. + */ + + i = 0; + + /* Skip all erase regions which are ended before the start of + the requested erase. Actually, to save on the calculations, + we skip to the first erase region which starts after the + start of the requested erase, and then go back one. + */ + + while (i < mtd->numeraseregions && instr->addr >= regions[i].offset) + i++; + i--; + + /* OK, now i is pointing at the erase region in which this + erase request starts. Check the start of the requested + erase range is aligned with the erase size which is in + effect here. + */ + + if (instr->addr & (regions[i].erasesize-1)) + return -EINVAL; + + /* Remember the erase region we start on */ + first = i; + + /* Next, check that the end of the requested erase is aligned + * with the erase region at that address. + */ + + while (inumeraseregions && (instr->addr + instr->len) >= regions[i].offset) + i++; + + /* As before, drop back one to point at the region in which + the address actually falls + */ + i--; + + if ((instr->addr + instr->len) & (regions[i].erasesize-1)) + return -EINVAL; + + chipnum = instr->addr >> cfi->chipshift; + adr = instr->addr - (chipnum << cfi->chipshift); + len = instr->len; + + i=first; + + while(len) { + ret = do_erase_oneblock(map, &cfi->chips[chipnum], adr); + + if (ret) + return ret; + + adr += regions[i].erasesize; + len -= regions[i].erasesize; + + if (adr % (1<< cfi->chipshift) == ((regions[i].offset + (regions[i].erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift))) + i++; + + if (adr >> cfi->chipshift) { + adr = 0; + chipnum++; + + if (chipnum >= cfi->numchips) + break; + } + } + + instr->state = MTD_ERASE_DONE; + if (instr->callback) + instr->callback(instr); + + return 0; +} + +static void cfi_intelext_sync (struct mtd_info *mtd) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + int i; + struct flchip *chip; + int ret = 0; + DECLARE_WAITQUEUE(wait, current); + + for (i=0; !ret && inumchips; i++) { + chip = &cfi->chips[i]; + + retry: + spin_lock_bh(chip->mutex); + + switch(chip->state) { + case FL_READY: + case FL_STATUS: + case FL_CFI_QUERY: + case FL_JEDEC_QUERY: + chip->oldstate = chip->state; + chip->state = FL_SYNCING; + /* No need to wake_up() on this state change - + * as the whole point is that nobody can do anything + * with the chip now anyway. + */ + case FL_SYNCING: + spin_unlock_bh(chip->mutex); + break; + + default: + /* Not an idle state */ + add_wait_queue(&chip->wq, &wait); + + spin_unlock_bh(chip->mutex); + schedule(); + remove_wait_queue(&chip->wq, &wait); + + goto retry; + } + } + + /* Unlock the chips again */ + + for (i--; i >=0; i--) { + chip = &cfi->chips[i]; + + spin_lock_bh(chip->mutex); + + if (chip->state == FL_SYNCING) { + chip->state = chip->oldstate; + wake_up(&chip->wq); + } + spin_unlock_bh(chip->mutex); + } +} + +static inline int do_lock_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr) +{ + struct cfi_private *cfi = map->fldrv_priv; + __u32 status, status_OK; + unsigned long timeo = jiffies + HZ; + DECLARE_WAITQUEUE(wait, current); + + adr += chip->start; + + /* Let's determine this according to the interleave only once */ + status_OK = CMD(0x80); + + timeo = jiffies + HZ; +retry: + spin_lock_bh(chip->mutex); + + /* Check that the chip's ready to talk to us. */ + switch (chip->state) { + case FL_CFI_QUERY: + case FL_JEDEC_QUERY: + case FL_READY: + cfi_write(map, CMD(0x70), adr); + chip->state = FL_STATUS; + + case FL_STATUS: + status = cfi_read(map, adr); + if ((status & status_OK) == status_OK) + break; + + /* Urgh. Chip not yet ready to talk to us. */ + if (time_after(jiffies, timeo)) { + spin_unlock_bh(chip->mutex); + printk("waiting for chip to be ready timed out in lock\n"); + return -EIO; + } + + /* Latency issues. Drop the lock, wait a while and retry */ + spin_unlock_bh(chip->mutex); + cfi_udelay(1); + goto retry; + + default: + /* Stick ourselves on a wait queue to be woken when + someone changes the status */ + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + spin_unlock_bh(chip->mutex); + schedule(); + remove_wait_queue(&chip->wq, &wait); + timeo = jiffies + HZ; + goto retry; + } + + ENABLE_VPP(map); + cfi_write(map, CMD(0x60), adr); + cfi_write(map, CMD(0x01), adr); + chip->state = FL_LOCKING; + + spin_unlock_bh(chip->mutex); + schedule_timeout(HZ); + spin_lock_bh(chip->mutex); + + /* FIXME. Use a timer to check this, and return immediately. */ + /* Once the state machine's known to be working I'll do that */ + + timeo = jiffies + (HZ*2); + for (;;) { + + status = cfi_read(map, adr); + if ((status & status_OK) == status_OK) + break; + + /* OK Still waiting */ + if (time_after(jiffies, timeo)) { + cfi_write(map, CMD(0x70), adr); + chip->state = FL_STATUS; + printk("waiting for lock to complete timed out. Xstatus = %x, status = %x.\n", status, cfi_read(map, adr)); + DISABLE_VPP(map); + spin_unlock_bh(chip->mutex); + return -EIO; + } + + /* Latency issues. Drop the lock, wait a while and retry */ + spin_unlock_bh(chip->mutex); + cfi_udelay(1); + spin_lock_bh(chip->mutex); + } + + /* Done and happy. */ + chip->state = FL_STATUS; + DISABLE_VPP(map); + wake_up(&chip->wq); + spin_unlock_bh(chip->mutex); + return 0; +} +static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + unsigned long adr; + int chipnum, ret = 0; +#ifdef DEBUG_LOCK_BITS + int ofs_factor = cfi->interleave * cfi->device_type; +#endif + + if (ofs & (mtd->erasesize - 1)) + return -EINVAL; + + if (len & (mtd->erasesize -1)) + return -EINVAL; + + if ((len + ofs) > mtd->size) + return -EINVAL; + + chipnum = ofs >> cfi->chipshift; + adr = ofs - (chipnum << cfi->chipshift); + + while(len) { + +#ifdef DEBUG_LOCK_BITS + cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi, cfi->device_type, NULL); + printk("before lock: block status register is %x\n",cfi_read_query(map, adr+(2*ofs_factor))); + cfi_send_gen_cmd(0xff, 0x55, 0, map, cfi, cfi->device_type, NULL); +#endif + + ret = do_lock_oneblock(map, &cfi->chips[chipnum], adr); + +#ifdef DEBUG_LOCK_BITS + cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi, cfi->device_type, NULL); + printk("after lock: block status register is %x\n",cfi_read_query(map, adr+(2*ofs_factor))); + cfi_send_gen_cmd(0xff, 0x55, 0, map, cfi, cfi->device_type, NULL); +#endif + + if (ret) + return ret; + + adr += mtd->erasesize; + len -= mtd->erasesize; + + if (adr >> cfi->chipshift) { + adr = 0; + chipnum++; + + if (chipnum >= cfi->numchips) + break; + } + } + return 0; +} +static inline int do_unlock_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr) +{ + struct cfi_private *cfi = map->fldrv_priv; + __u32 status, status_OK; + unsigned long timeo = jiffies + HZ; + DECLARE_WAITQUEUE(wait, current); + + adr += chip->start; + + /* Let's determine this according to the interleave only once */ + status_OK = CMD(0x80); + + timeo = jiffies + HZ; +retry: + spin_lock_bh(chip->mutex); + + /* Check that the chip's ready to talk to us. */ + switch (chip->state) { + case FL_CFI_QUERY: + case FL_JEDEC_QUERY: + case FL_READY: + cfi_write(map, CMD(0x70), adr); + chip->state = FL_STATUS; + + case FL_STATUS: + status = cfi_read(map, adr); + if ((status & status_OK) == status_OK) + break; + + /* Urgh. Chip not yet ready to talk to us. */ + if (time_after(jiffies, timeo)) { + spin_unlock_bh(chip->mutex); + printk("waiting for chip to be ready timed out in unlock\n"); + return -EIO; + } + + /* Latency issues. Drop the lock, wait a while and retry */ + spin_unlock_bh(chip->mutex); + cfi_udelay(1); + goto retry; + + default: + /* Stick ourselves on a wait queue to be woken when + someone changes the status */ + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + spin_unlock_bh(chip->mutex); + schedule(); + remove_wait_queue(&chip->wq, &wait); + timeo = jiffies + HZ; + goto retry; + } + + ENABLE_VPP(map); + cfi_write(map, CMD(0x60), adr); + cfi_write(map, CMD(0xD0), adr); + chip->state = FL_UNLOCKING; + + spin_unlock_bh(chip->mutex); + schedule_timeout(HZ); + spin_lock_bh(chip->mutex); + + /* FIXME. Use a timer to check this, and return immediately. */ + /* Once the state machine's known to be working I'll do that */ + + timeo = jiffies + (HZ*2); + for (;;) { + + status = cfi_read(map, adr); + if ((status & status_OK) == status_OK) + break; + + /* OK Still waiting */ + if (time_after(jiffies, timeo)) { + cfi_write(map, CMD(0x70), adr); + chip->state = FL_STATUS; + printk("waiting for unlock to complete timed out. Xstatus = %x, status = %x.\n", status, cfi_read(map, adr)); + DISABLE_VPP(map); + spin_unlock_bh(chip->mutex); + return -EIO; + } + + /* Latency issues. Drop the unlock, wait a while and retry */ + spin_unlock_bh(chip->mutex); + cfi_udelay(1); + spin_lock_bh(chip->mutex); + } + + /* Done and happy. */ + chip->state = FL_STATUS; + DISABLE_VPP(map); + wake_up(&chip->wq); + spin_unlock_bh(chip->mutex); + return 0; +} +static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + unsigned long adr; + int chipnum, ret = 0; +#ifdef DEBUG_LOCK_BITS + int ofs_factor = cfi->interleave * cfi->device_type; +#endif + + chipnum = ofs >> cfi->chipshift; + adr = ofs - (chipnum << cfi->chipshift); + +#ifdef DEBUG_LOCK_BITS + { + unsigned long temp_adr = adr; + unsigned long temp_len = len; + + cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi, cfi->device_type, NULL); + while (temp_len) { + printk("before unlock %x: block status register is %x\n",temp_adr,cfi_read_query(map, temp_adr+(2*ofs_factor))); + temp_adr += mtd->erasesize; + temp_len -= mtd->erasesize; + } + cfi_send_gen_cmd(0xff, 0x55, 0, map, cfi, cfi->device_type, NULL); + } +#endif + + ret = do_unlock_oneblock(map, &cfi->chips[chipnum], adr); + +#ifdef DEBUG_LOCK_BITS + cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi, cfi->device_type, NULL); + printk("after unlock: block status register is %x\n",cfi_read_query(map, adr+(2*ofs_factor))); + cfi_send_gen_cmd(0xff, 0x55, 0, map, cfi, cfi->device_type, NULL); +#endif + + return ret; +} + +static int cfi_intelext_suspend(struct mtd_info *mtd) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + int i; + struct flchip *chip; + int ret = 0; + + for (i=0; !ret && inumchips; i++) { + chip = &cfi->chips[i]; + + spin_lock_bh(chip->mutex); + + switch(chip->state) { + case FL_READY: + case FL_STATUS: + case FL_CFI_QUERY: + case FL_JEDEC_QUERY: + chip->oldstate = chip->state; + chip->state = FL_PM_SUSPENDED; + /* No need to wake_up() on this state change - + * as the whole point is that nobody can do anything + * with the chip now anyway. + */ + case FL_PM_SUSPENDED: + break; + + default: + ret = -EAGAIN; + break; + } + spin_unlock_bh(chip->mutex); + } + + /* Unlock the chips again */ + + if (ret) { + for (i--; i >=0; i--) { + chip = &cfi->chips[i]; + + spin_lock_bh(chip->mutex); + + if (chip->state == FL_PM_SUSPENDED) { + chip->state = chip->oldstate; + wake_up(&chip->wq); + } + spin_unlock_bh(chip->mutex); + } + } + + return ret; +} + +static void cfi_intelext_resume(struct mtd_info *mtd) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + int i; + struct flchip *chip; + + for (i=0; inumchips; i++) { + + chip = &cfi->chips[i]; + + spin_lock_bh(chip->mutex); + + if (chip->state == FL_PM_SUSPENDED) { + /* We need to force it back to a known state. */ + cfi_write(map, CMD(0xff), 0); + chip->state = FL_READY; + wake_up(&chip->wq); + } + + spin_unlock_bh(chip->mutex); + } +} + +static void cfi_intelext_destroy(struct mtd_info *mtd) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + kfree(cfi->cmdset_priv); + kfree(cfi); +} + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define cfi_intelext_init init_module +#define cfi_intelext_exit cleanup_module +#endif + +static char im_name_1[]="cfi_cmdset_0001"; +static char im_name_3[]="cfi_cmdset_0003"; + + +mod_init_t cfi_intelext_init(void) +{ + inter_module_register(im_name_1, THIS_MODULE, &cfi_cmdset_0001); + inter_module_register(im_name_3, THIS_MODULE, &cfi_cmdset_0001); + return 0; +} + +mod_exit_t cfi_intelext_exit(void) +{ + inter_module_unregister(im_name_1); + inter_module_unregister(im_name_3); +} + +module_init(cfi_intelext_init); +module_exit(cfi_intelext_exit); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/chips/cfi_cmdset_0002.c linux/drivers/mtd/chips/cfi_cmdset_0002.c --- v2.4.5/linux/drivers/mtd/chips/cfi_cmdset_0002.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/chips/cfi_cmdset_0002.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,936 @@ +/* + * Common Flash Interface support: + * AMD & Fujitsu Standard Vendor Command Set (ID 0x0002) + * + * Copyright (C) 2000 Crossnet Co. + * + * 2_by_8 routines added by Simon Munton + * + * This code is GPL + * + * $Id: cfi_cmdset_0002.c,v 1.48 2001/06/03 01:32:57 nico Exp $ + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define AMD_BOOTLOC_BUG + +static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); +static int cfi_amdstd_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); +static int cfi_amdstd_erase_onesize(struct mtd_info *, struct erase_info *); +static int cfi_amdstd_erase_varsize(struct mtd_info *, struct erase_info *); +static void cfi_amdstd_sync (struct mtd_info *); +static int cfi_amdstd_suspend (struct mtd_info *); +static void cfi_amdstd_resume (struct mtd_info *); + +static void cfi_amdstd_destroy(struct mtd_info *); + +void cfi_cmdset_0002(struct map_info *, int, unsigned long); +static struct mtd_info *cfi_amdstd_setup (struct map_info *); + + +static struct mtd_chip_driver cfi_amdstd_chipdrv = { + probe: cfi_amdstd_setup, + destroy: cfi_amdstd_destroy, + name: "cfi_cmdset_0002", + module: THIS_MODULE +}; + +void cfi_cmdset_0002(struct map_info *map, int primary, unsigned long base) +{ + struct cfi_private *cfi = map->fldrv_priv; + unsigned char bootloc; + int ofs_factor = cfi->interleave * cfi->device_type; + int i; + __u8 major, minor; +// struct cfi_pri_intelext *extp; + + if (cfi->cfi_mode==0){ + __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR; + + cfi_send_gen_cmd(0x98, 0x55, 0, map, cfi, cfi->device_type, NULL); + + major = cfi_read_query(map, (adr+3)*ofs_factor); + minor = cfi_read_query(map, (adr+4)*ofs_factor); + + printk(" Amd/Fujitsu Extended Query Table v%c.%c at 0x%4.4X\n", + major, minor, adr); + + cfi_send_gen_cmd(0xf0, 0x55, 0, map, cfi, cfi->device_type, NULL); + + cfi_send_gen_cmd(0xaa, 0x555, base, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x55, 0x2aa, base, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x90, 0x555, base, map, cfi, cfi->device_type, NULL); + cfi->mfr = cfi_read_query(map, base); + cfi->id = cfi_read_query(map, base + ofs_factor); + + /* Wheee. Bring me the head of someone at AMD. */ +#ifdef AMD_BOOTLOC_BUG + if (((major << 8) | minor) < 0x3131) { + /* CFI version 1.0 => don't trust bootloc */ + if (cfi->id & 0x80) { + printk(KERN_WARNING "%s: JEDEC Device ID is 0x%02X. Assuming broken CFI table.\n", map->name, cfi->id); + bootloc = 3; /* top boot */ + } else { + bootloc = 2; /* bottom boot */ + } + } else +#endif + { + cfi_send_gen_cmd(0x98, 0x55, 0, map, cfi, cfi->device_type, NULL); + bootloc = cfi_read_query(map, (adr+15)*ofs_factor); + } + if (bootloc == 3 && cfi->cfiq->NumEraseRegions > 1) { + printk(KERN_WARNING "%s: Swapping erase regions for broken CFI table.\n", map->name); + + for (i=0; icfiq->NumEraseRegions / 2; i++) { + int j = (cfi->cfiq->NumEraseRegions-1)-i; + __u32 swap; + + swap = cfi->cfiq->EraseRegionInfo[i]; + cfi->cfiq->EraseRegionInfo[i] = cfi->cfiq->EraseRegionInfo[j]; + cfi->cfiq->EraseRegionInfo[j] = swap; + } + } + } + + /* If there was an old setup function, decrease its use count */ + if (map->fldrv) + if(map->fldrv->module) + __MOD_DEC_USE_COUNT(map->fldrv->module); + + if (cfi->cmdset_priv) + kfree(cfi->cmdset_priv); + + for (i=0; i< cfi->numchips; i++) { + cfi->chips[i].word_write_time = 1<cfiq->WordWriteTimeoutTyp; + cfi->chips[i].buffer_write_time = 1<cfiq->BufWriteTimeoutTyp; + cfi->chips[i].erase_time = 1<cfiq->BlockEraseTimeoutTyp; + } + + map->fldrv = &cfi_amdstd_chipdrv; + MOD_INC_USE_COUNT; + cfi_send_gen_cmd(0xf0, 0x55, 0, map, cfi, cfi->device_type, NULL); + return; +} + +static struct mtd_info *cfi_amdstd_setup(struct map_info *map) +{ + struct cfi_private *cfi = map->fldrv_priv; + struct mtd_info *mtd; + unsigned long devsize = (1<cfiq->DevSize) * cfi->interleave; + + mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); + printk("number of %s chips: %d\n", (cfi->cfi_mode)?"JEDEC":"CFI",cfi->numchips); + + if (!mtd) { + printk("Failed to allocate memory for MTD device\n"); + kfree(cfi->cmdset_priv); + return NULL; + } + + memset(mtd, 0, sizeof(*mtd)); + mtd->priv = map; + mtd->type = MTD_NORFLASH; + /* Also select the correct geometry setup too */ + mtd->size = devsize * cfi->numchips; + + if (cfi->cfiq->NumEraseRegions == 1) { + /* No need to muck about with multiple erase sizes */ + mtd->erasesize = ((cfi->cfiq->EraseRegionInfo[0] >> 8) & ~0xff) * cfi->interleave; + } else { + unsigned long offset = 0; + int i,j; + + mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips; + mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) * mtd->numeraseregions, GFP_KERNEL); + if (!mtd->eraseregions) { + printk("Failed to allocate memory for MTD erase region info\n"); + kfree(cfi->cmdset_priv); + return NULL; + } + + for (i=0; icfiq->NumEraseRegions; i++) { + unsigned long ernum, ersize; + ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff) * cfi->interleave; + ernum = (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1; + + if (mtd->erasesize < ersize) { + mtd->erasesize = ersize; + } + for (j=0; jnumchips; j++) { + mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].offset = (j*devsize)+offset; + mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].erasesize = ersize; + mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].numblocks = ernum; + } + offset += (ersize * ernum); + } + if (offset != devsize) { + /* Argh */ + printk("Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize); + kfree(mtd->eraseregions); + kfree(cfi->cmdset_priv); + return NULL; + } + // debug + for (i=0; inumeraseregions;i++){ + printk("%d: offset=0x%x,size=0x%x,blocks=%d\n", + i,mtd->eraseregions[i].offset, + mtd->eraseregions[i].erasesize, + mtd->eraseregions[i].numblocks); + } + } + + switch (CFIDEV_BUSWIDTH) + { + case 1: + case 2: + case 4: +#if 1 + if (mtd->numeraseregions > 1) + mtd->erase = cfi_amdstd_erase_varsize; + else +#endif + mtd->erase = cfi_amdstd_erase_onesize; + mtd->read = cfi_amdstd_read; + mtd->write = cfi_amdstd_write; + break; + + default: + printk("Unsupported buswidth\n"); + kfree(mtd); + kfree(cfi->cmdset_priv); + return NULL; + break; + } + mtd->sync = cfi_amdstd_sync; + mtd->suspend = cfi_amdstd_suspend; + mtd->resume = cfi_amdstd_resume; + mtd->flags = MTD_CAP_NORFLASH; + map->fldrv = &cfi_amdstd_chipdrv; + mtd->name = map->name; + MOD_INC_USE_COUNT; + return mtd; +} + +static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf) +{ + DECLARE_WAITQUEUE(wait, current); + unsigned long timeo = jiffies + HZ; + + retry: + cfi_spin_lock(chip->mutex); + + if (chip->state != FL_READY){ + printk("Waiting for chip to read, status = %d\n", chip->state); + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + cfi_spin_unlock(chip->mutex); + + schedule(); + remove_wait_queue(&chip->wq, &wait); +#if 0 + if(signal_pending(current)) + return -EINTR; +#endif + timeo = jiffies + HZ; + + goto retry; + } + + adr += chip->start; + + chip->state = FL_READY; + + map->copy_from(map, buf, adr, len); + + wake_up(&chip->wq); + cfi_spin_unlock(chip->mutex); + + return 0; +} + +static int cfi_amdstd_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + unsigned long ofs; + int chipnum; + int ret = 0; + + /* ofs: offset within the first chip that the first read should start */ + + chipnum = (from >> cfi->chipshift); + ofs = from - (chipnum << cfi->chipshift); + + + *retlen = 0; + + while (len) { + unsigned long thislen; + + if (chipnum >= cfi->numchips) + break; + + if ((len + ofs -1) >> cfi->chipshift) + thislen = (1<chipshift) - ofs; + else + thislen = len; + + ret = do_read_onechip(map, &cfi->chips[chipnum], ofs, thislen, buf); + if (ret) + break; + + *retlen += thislen; + len -= thislen; + buf += thislen; + + ofs = 0; + chipnum++; + } + return ret; +} + +static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, __u32 datum, int fast) +{ + unsigned long timeo = jiffies + HZ; + unsigned int Last[4]; + unsigned long Count = 0; + struct cfi_private *cfi = map->fldrv_priv; + DECLARE_WAITQUEUE(wait, current); + int ret = 0; + + retry: + cfi_spin_lock(chip->mutex); + + if (chip->state != FL_READY){ + printk("Waiting for chip to write, status = %d\n", chip->state); + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + cfi_spin_unlock(chip->mutex); + + schedule(); + remove_wait_queue(&chip->wq, &wait); + printk("Wake up to write:\n"); +#if 0 + if(signal_pending(current)) + return -EINTR; +#endif + timeo = jiffies + HZ; + + goto retry; + } + + chip->state = FL_WRITING; + + adr += chip->start; + ENABLE_VPP(map); + if (fast) { /* Unlock bypass */ + cfi_send_gen_cmd(0xA0, 0, chip->start, map, cfi, cfi->device_type, NULL); + } + else { + cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); + cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); + } + + cfi_write(map, datum, adr); + + cfi_spin_unlock(chip->mutex); + cfi_udelay(chip->word_write_time); + cfi_spin_lock(chip->mutex); + + Last[0] = cfi_read(map, adr); + // printk("Last[0] is %x\n", Last[0]); + Last[1] = cfi_read(map, adr); + // printk("Last[1] is %x\n", Last[1]); + Last[2] = cfi_read(map, adr); + // printk("Last[2] is %x\n", Last[2]); + + for (Count = 3; Last[(Count - 1) % 4] != Last[(Count - 2) % 4] && Count < 10000; Count++){ + cfi_spin_unlock(chip->mutex); + cfi_udelay(10); + cfi_spin_lock(chip->mutex); + + Last[Count % 4] = cfi_read(map, adr); + // printk("Last[%d%%4] is %x\n", Count, Last[Count%4]); + } + + if (Last[(Count - 1) % 4] != datum){ + printk("Last[%ld] is %x, datum is %x\n",(Count - 1) % 4,Last[(Count - 1) % 4],datum); + cfi_send_gen_cmd(0xF0, 0, chip->start, map, cfi, cfi->device_type, NULL); + DISABLE_VPP(map); + ret = -EIO; + } + DISABLE_VPP(map); + chip->state = FL_READY; + wake_up(&chip->wq); + cfi_spin_unlock(chip->mutex); + + return ret; +} + +static int cfi_amdstd_write (struct mtd_info *mtd, loff_t to , size_t len, size_t *retlen, const u_char *buf) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + int ret = 0; + int chipnum; + unsigned long ofs, chipstart; + + *retlen = 0; + if (!len) + return 0; + + chipnum = to >> cfi->chipshift; + ofs = to - (chipnum << cfi->chipshift); + chipstart = cfi->chips[chipnum].start; + + /* If it's not bus-aligned, do the first byte write */ + if (ofs & (CFIDEV_BUSWIDTH-1)) { + unsigned long bus_ofs = ofs & ~(CFIDEV_BUSWIDTH-1); + int i = ofs - bus_ofs; + int n = 0; + u_char tmp_buf[4]; + __u32 datum; + + map->copy_from(map, tmp_buf, bus_ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH); + while (len && i < CFIDEV_BUSWIDTH) + tmp_buf[i++] = buf[n++], len--; + + if (cfi_buswidth_is_2()) { + datum = *(__u16*)tmp_buf; + } else if (cfi_buswidth_is_4()) { + datum = *(__u32*)tmp_buf; + } else { + return -EINVAL; /* should never happen, but be safe */ + } + + ret = do_write_oneword(map, &cfi->chips[chipnum], + bus_ofs, datum, 0); + if (ret) + return ret; + + ofs += n; + buf += n; + (*retlen) += n; + + if (ofs >> cfi->chipshift) { + chipnum ++; + ofs = 0; + if (chipnum == cfi->numchips) + return 0; + } + } + + /* Go into unlock bypass mode */ + cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chipstart, map, cfi, CFI_DEVICETYPE_X8, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chipstart, map, cfi, CFI_DEVICETYPE_X8, NULL); + cfi_send_gen_cmd(0x20, cfi->addr_unlock1, chipstart, map, cfi, CFI_DEVICETYPE_X8, NULL); + + /* We are now aligned, write as much as possible */ + while(len >= CFIDEV_BUSWIDTH) { + __u32 datum; + + if (cfi_buswidth_is_1()) { + datum = *(__u8*)buf; + } else if (cfi_buswidth_is_2()) { + datum = *(__u16*)buf; + } else if (cfi_buswidth_is_4()) { + datum = *(__u32*)buf; + } else { + return -EINVAL; + } + ret = do_write_oneword(map, &cfi->chips[chipnum], + ofs, datum, cfi->fast_prog); + if (ret) { + if (cfi->fast_prog){ + /* Get out of unlock bypass mode */ + cfi_send_gen_cmd(0x90, 0, chipstart, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x00, 0, chipstart, map, cfi, cfi->device_type, NULL); + } + return ret; + } + + ofs += CFIDEV_BUSWIDTH; + buf += CFIDEV_BUSWIDTH; + (*retlen) += CFIDEV_BUSWIDTH; + len -= CFIDEV_BUSWIDTH; + + if (ofs >> cfi->chipshift) { + if (cfi->fast_prog){ + /* Get out of unlock bypass mode */ + cfi_send_gen_cmd(0x90, 0, chipstart, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x00, 0, chipstart, map, cfi, cfi->device_type, NULL); + } + + chipnum ++; + ofs = 0; + if (chipnum == cfi->numchips) + return 0; + chipstart = cfi->chips[chipnum].start; + if (cfi->fast_prog){ + /* Go into unlock bypass mode for next set of chips */ + cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chipstart, map, cfi, CFI_DEVICETYPE_X8, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chipstart, map, cfi, CFI_DEVICETYPE_X8, NULL); + cfi_send_gen_cmd(0x20, cfi->addr_unlock1, chipstart, map, cfi, CFI_DEVICETYPE_X8, NULL); + } + } + } + + if (cfi->fast_prog){ + /* Get out of unlock bypass mode */ + cfi_send_gen_cmd(0x90, 0, chipstart, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x00, 0, chipstart, map, cfi, cfi->device_type, NULL); + } + + if (len & (CFIDEV_BUSWIDTH-1)) { + int i = 0, n = 0; + u_char tmp_buf[4]; + __u32 datum; + + map->copy_from(map, tmp_buf, ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH); + while (len--) + tmp_buf[i++] = buf[n++]; + + if (cfi_buswidth_is_2()) { + datum = *(__u16*)tmp_buf; + } else if (cfi_buswidth_is_4()) { + datum = *(__u32*)tmp_buf; + } else { + return -EINVAL; /* should never happen, but be safe */ + } + + ret = do_write_oneword(map, &cfi->chips[chipnum], + ofs, datum, 0); + if (ret) + return ret; + + (*retlen) += n; + } + + return 0; +} + +static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr) +{ + unsigned int status; + unsigned long timeo = jiffies + HZ; + struct cfi_private *cfi = map->fldrv_priv; + unsigned int rdy_mask; + DECLARE_WAITQUEUE(wait, current); + + retry: + cfi_spin_lock(chip->mutex); + + if (chip->state != FL_READY){ + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + cfi_spin_unlock(chip->mutex); + + schedule(); + remove_wait_queue(&chip->wq, &wait); +#if 0 + if(signal_pending(current)) + return -EINTR; +#endif + timeo = jiffies + HZ; + + goto retry; + } + + chip->state = FL_ERASING; + + adr += chip->start; + ENABLE_VPP(map); + cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); + cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); + cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); + cfi_write(map, CMD(0x30), adr); + + timeo = jiffies + (HZ*20); + + cfi_spin_unlock(chip->mutex); + schedule_timeout(HZ); + cfi_spin_lock(chip->mutex); + + rdy_mask = CMD(0x80); + + /* FIXME. Use a timer to check this, and return immediately. */ + /* Once the state machine's known to be working I'll do that */ + + while ( ( (status = cfi_read(map,adr)) & rdy_mask ) != rdy_mask ) { + static int z=0; + + if (chip->state != FL_ERASING) { + /* Someone's suspended the erase. Sleep */ + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + cfi_spin_unlock(chip->mutex); + printk("erase suspended. Sleeping\n"); + + schedule(); + remove_wait_queue(&chip->wq, &wait); +#if 0 + if (signal_pending(current)) + return -EINTR; +#endif + timeo = jiffies + (HZ*2); /* FIXME */ + cfi_spin_lock(chip->mutex); + continue; + } + + /* OK Still waiting */ + if (time_after(jiffies, timeo)) { + chip->state = FL_READY; + cfi_spin_unlock(chip->mutex); + printk("waiting for erase to complete timed out."); + DISABLE_VPP(map); + return -EIO; + } + + /* Latency issues. Drop the lock, wait a while and retry */ + cfi_spin_unlock(chip->mutex); + + z++; + if ( 0 && !(z % 100 )) + printk("chip not ready yet after erase. looping\n"); + + cfi_udelay(1); + + cfi_spin_lock(chip->mutex); + continue; + } + + /* Done and happy. */ + DISABLE_VPP(map); + chip->state = FL_READY; + wake_up(&chip->wq); + cfi_spin_unlock(chip->mutex); + return 0; +} + +static int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + unsigned long adr, len; + int chipnum, ret = 0; + int i, first; + struct mtd_erase_region_info *regions = mtd->eraseregions; + + if (instr->addr > mtd->size) + return -EINVAL; + + if ((instr->len + instr->addr) > mtd->size) + return -EINVAL; + + /* Check that both start and end of the requested erase are + * aligned with the erasesize at the appropriate addresses. + */ + + i = 0; + + /* Skip all erase regions which are ended before the start of + the requested erase. Actually, to save on the calculations, + we skip to the first erase region which starts after the + start of the requested erase, and then go back one. + */ + + while (i < mtd->numeraseregions && instr->addr >= regions[i].offset) + i++; + i--; + + /* OK, now i is pointing at the erase region in which this + erase request starts. Check the start of the requested + erase range is aligned with the erase size which is in + effect here. + */ + + if (instr->addr & (regions[i].erasesize-1)) + return -EINVAL; + + /* Remember the erase region we start on */ + first = i; + + /* Next, check that the end of the requested erase is aligned + * with the erase region at that address. + */ + + while (inumeraseregions && (instr->addr + instr->len) >= regions[i].offset) + i++; + + /* As before, drop back one to point at the region in which + the address actually falls + */ + i--; + + if ((instr->addr + instr->len) & (regions[i].erasesize-1)) + return -EINVAL; + + chipnum = instr->addr >> cfi->chipshift; + adr = instr->addr - (chipnum << cfi->chipshift); + len = instr->len; + + i=first; + + while(len) { + ret = do_erase_oneblock(map, &cfi->chips[chipnum], adr); + + if (ret) + return ret; + + adr += regions[i].erasesize; + len -= regions[i].erasesize; + + if (adr % (1<< cfi->chipshift) == ((regions[i].offset + (regions[i].erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift))) + i++; + + if (adr >> cfi->chipshift) { + adr = 0; + chipnum++; + + if (chipnum >= cfi->numchips) + break; + } + } + + instr->state = MTD_ERASE_DONE; + if (instr->callback) + instr->callback(instr); + + return 0; +} + +static int cfi_amdstd_erase_onesize(struct mtd_info *mtd, struct erase_info *instr) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + unsigned long adr, len; + int chipnum, ret = 0; + + if (instr->addr & (mtd->erasesize - 1)) + return -EINVAL; + + if (instr->len & (mtd->erasesize -1)) + return -EINVAL; + + if ((instr->len + instr->addr) > mtd->size) + return -EINVAL; + + chipnum = instr->addr >> cfi->chipshift; + adr = instr->addr - (chipnum << cfi->chipshift); + len = instr->len; + + while(len) { + ret = do_erase_oneblock(map, &cfi->chips[chipnum], adr); + + if (ret) + return ret; + + adr += mtd->erasesize; + len -= mtd->erasesize; + + if (adr >> cfi->chipshift) { + adr = 0; + chipnum++; + + if (chipnum >= cfi->numchips) + break; + } + } + + instr->state = MTD_ERASE_DONE; + if (instr->callback) + instr->callback(instr); + + return 0; +} + +static void cfi_amdstd_sync (struct mtd_info *mtd) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + int i; + struct flchip *chip; + int ret = 0; + DECLARE_WAITQUEUE(wait, current); + + for (i=0; !ret && inumchips; i++) { + chip = &cfi->chips[i]; + + retry: + cfi_spin_lock(chip->mutex); + + switch(chip->state) { + case FL_READY: + case FL_STATUS: + case FL_CFI_QUERY: + case FL_JEDEC_QUERY: + chip->oldstate = chip->state; + chip->state = FL_SYNCING; + /* No need to wake_up() on this state change - + * as the whole point is that nobody can do anything + * with the chip now anyway. + */ + case FL_SYNCING: + cfi_spin_unlock(chip->mutex); + break; + + default: + /* Not an idle state */ + add_wait_queue(&chip->wq, &wait); + + cfi_spin_unlock(chip->mutex); + + schedule(); + + remove_wait_queue(&chip->wq, &wait); + + goto retry; + } + } + + /* Unlock the chips again */ + + for (i--; i >=0; i--) { + chip = &cfi->chips[i]; + + cfi_spin_lock(chip->mutex); + + if (chip->state == FL_SYNCING) { + chip->state = chip->oldstate; + wake_up(&chip->wq); + } + cfi_spin_unlock(chip->mutex); + } +} + + +static int cfi_amdstd_suspend(struct mtd_info *mtd) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + int i; + struct flchip *chip; + int ret = 0; +//printk("suspend\n"); + + for (i=0; !ret && inumchips; i++) { + chip = &cfi->chips[i]; + + cfi_spin_lock(chip->mutex); + + switch(chip->state) { + case FL_READY: + case FL_STATUS: + case FL_CFI_QUERY: + case FL_JEDEC_QUERY: + chip->oldstate = chip->state; + chip->state = FL_PM_SUSPENDED; + /* No need to wake_up() on this state change - + * as the whole point is that nobody can do anything + * with the chip now anyway. + */ + case FL_PM_SUSPENDED: + break; + + default: + ret = -EAGAIN; + break; + } + cfi_spin_unlock(chip->mutex); + } + + /* Unlock the chips again */ + + if (ret) { + for (i--; i >=0; i--) { + chip = &cfi->chips[i]; + + cfi_spin_lock(chip->mutex); + + if (chip->state == FL_PM_SUSPENDED) { + chip->state = chip->oldstate; + wake_up(&chip->wq); + } + cfi_spin_unlock(chip->mutex); + } + } + + return ret; +} + +static void cfi_amdstd_resume(struct mtd_info *mtd) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + int i; + struct flchip *chip; +//printk("resume\n"); + + for (i=0; inumchips; i++) { + + chip = &cfi->chips[i]; + + cfi_spin_lock(chip->mutex); + + if (chip->state == FL_PM_SUSPENDED) { + chip->state = FL_READY; + cfi_write(map, CMD(0xF0), chip->start); + wake_up(&chip->wq); + } + else + printk("Argh. Chip not in PM_SUSPENDED state upon resume()\n"); + + cfi_spin_unlock(chip->mutex); + } +} + +static void cfi_amdstd_destroy(struct mtd_info *mtd) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + kfree(cfi->cmdset_priv); + kfree(cfi); +} + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define cfi_amdstd_init init_module +#define cfi_amdstd_exit cleanup_module +#endif + +static char im_name[]="cfi_cmdset_0002"; + +mod_init_t cfi_amdstd_init(void) +{ + inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0002); + return 0; +} + +mod_exit_t cfi_amdstd_exit(void) +{ + inter_module_unregister(im_name); +} + +module_init(cfi_amdstd_init); +module_exit(cfi_amdstd_exit); + diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/chips/cfi_jedec.c linux/drivers/mtd/chips/cfi_jedec.c --- v2.4.5/linux/drivers/mtd/chips/cfi_jedec.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/chips/cfi_jedec.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,289 @@ +/* $Id: cfi_jedec.c,v 1.5 2001/06/02 14:52:23 dwmw2 Exp $ */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* Manufacturers */ +#define MANUFACTURER_AMD 0x0001 +#define MANUFACTURER_FUJITSU 0x0004 +#define MANUFACTURER_ATMEL 0x001f +#define MANUFACTURER_ST 0x0020 +#define MANUFACTURER_SST 0x00BF +#define MANUFACTURER_TOSHIBA 0x0098 + +/* AMD */ +#define AM29F800BB 0x2258 +#define AM29F800BT 0x22D6 +#define AM29LV800BB 0x225B +#define AM29LV800BT 0x22DA +#define AM29LV160DT 0x22C4 +#define AM29LV160DB 0x2249 + +/* Atmel */ +#define AT49BV16X4 0x00c0 +#define AT49BV16X4T 0x00c2 + +/* Fujitsu */ +#define MBM29LV160TE 0x22C4 +#define MBM29LV160BE 0x2249 + +/* ST - www.st.com */ +#define M29W800T 0x00D7 +#define M29W160DT 0x22C4 +#define M29W160DB 0x2249 + +/* SST */ +#define SST39LF800 0x2781 +#define SST39LF160 0x2782 + +/* Toshiba */ +#define TC58FVT160 0x00C2 +#define TC58FVB160 0x0043 + + +struct amd_flash_info { + const __u16 mfr_id; + const __u16 dev_id; + const char *name; + const int DevSize; + const int InterfaceDesc; + const int NumEraseRegions; + const ulong regions[4]; +}; + +#define ERASEINFO(size,blocks) (size<<8)|(blocks-1) + +#define SIZE_1MiB 20 +#define SIZE_2MiB 21 +#define SIZE_4MiB 22 + +static const struct amd_flash_info jedec_table[] = { + { + mfr_id: MANUFACTURER_AMD, + dev_id: AM29LV160DT, + name: "AMD AM29LV160DT", + DevSize: SIZE_2MiB, + NumEraseRegions: 4, + regions: {ERASEINFO(0x10000,31), + ERASEINFO(0x08000,1), + ERASEINFO(0x02000,2), + ERASEINFO(0x04000,1) + } + }, { + mfr_id: MANUFACTURER_AMD, + dev_id: AM29LV160DB, + name: "AMD AM29LV160DB", + DevSize: SIZE_2MiB, + NumEraseRegions: 4, + regions: {ERASEINFO(0x04000,1), + ERASEINFO(0x02000,2), + ERASEINFO(0x08000,1), + ERASEINFO(0x10000,31) + } + }, { + mfr_id: MANUFACTURER_TOSHIBA, + dev_id: TC58FVT160, + name: "Toshiba TC58FVT160", + DevSize: SIZE_2MiB, + NumEraseRegions: 4, + regions: {ERASEINFO(0x10000,31), + ERASEINFO(0x08000,1), + ERASEINFO(0x02000,2), + ERASEINFO(0x04000,1) + } + }, { + mfr_id: MANUFACTURER_FUJITSU, + dev_id: MBM29LV160TE, + name: "Fujitsu MBM29LV160TE", + DevSize: SIZE_2MiB, + NumEraseRegions: 4, + regions: {ERASEINFO(0x10000,31), + ERASEINFO(0x08000,1), + ERASEINFO(0x02000,2), + ERASEINFO(0x04000,1) + } + }, { + mfr_id: MANUFACTURER_TOSHIBA, + dev_id: TC58FVB160, + name: "Toshiba TC58FVB160", + DevSize: SIZE_2MiB, + NumEraseRegions: 4, + regions: {ERASEINFO(0x04000,1), + ERASEINFO(0x02000,2), + ERASEINFO(0x08000,1), + ERASEINFO(0x10000,31) + } + }, { + mfr_id: MANUFACTURER_FUJITSU, + dev_id: MBM29LV160BE, + name: "Fujitsu MBM29LV160BE", + DevSize: SIZE_2MiB, + NumEraseRegions: 4, + regions: {ERASEINFO(0x04000,1), + ERASEINFO(0x02000,2), + ERASEINFO(0x08000,1), + ERASEINFO(0x10000,31) + } + }, { + mfr_id: MANUFACTURER_AMD, + dev_id: AM29LV800BB, + name: "AMD AM29LV800BB", + DevSize: SIZE_1MiB, + NumEraseRegions: 4, + regions: {ERASEINFO(0x04000,1), + ERASEINFO(0x02000,2), + ERASEINFO(0x08000,1), + ERASEINFO(0x10000,15), + } + }, { + mfr_id: MANUFACTURER_AMD, + dev_id: AM29F800BB, + name: "AMD AM29F800BB", + DevSize: SIZE_1MiB, + NumEraseRegions: 4, + regions: {ERASEINFO(0x04000,1), + ERASEINFO(0x02000,2), + ERASEINFO(0x08000,1), + ERASEINFO(0x10000,15), + } + }, { + mfr_id: MANUFACTURER_AMD, + dev_id: AM29LV800BT, + name: "AMD AM29LV800BT", + DevSize: SIZE_1MiB, + NumEraseRegions: 4, + regions: {ERASEINFO(0x10000,15), + ERASEINFO(0x08000,1), + ERASEINFO(0x02000,2), + ERASEINFO(0x04000,1) + } + }, { + mfr_id: MANUFACTURER_AMD, + dev_id: AM29F800BT, + name: "AMD AM29F800BT", + DevSize: SIZE_1MiB, + NumEraseRegions: 4, + regions: {ERASEINFO(0x10000,15), + ERASEINFO(0x08000,1), + ERASEINFO(0x02000,2), + ERASEINFO(0x04000,1) + } + }, { + mfr_id: MANUFACTURER_AMD, + dev_id: AM29LV800BB, + name: "AMD AM29LV800BB", + DevSize: SIZE_1MiB, + NumEraseRegions: 4, + regions: {ERASEINFO(0x10000,15), + ERASEINFO(0x08000,1), + ERASEINFO(0x02000,2), + ERASEINFO(0x04000,1) + } + }, { + mfr_id: MANUFACTURER_ST, + dev_id: M29W800T, + name: "ST M29W800T", + DevSize: SIZE_1MiB, + NumEraseRegions: 4, + regions: {ERASEINFO(0x10000,15), + ERASEINFO(0x08000,1), + ERASEINFO(0x02000,2), + ERASEINFO(0x04000,1) + } + }, { + mfr_id: MANUFACTURER_ST, + dev_id: M29W160DT, + name: "ST M29W160DT", + DevSize: SIZE_2MiB, + NumEraseRegions: 4, + regions: {ERASEINFO(0x10000,31), + ERASEINFO(0x08000,1), + ERASEINFO(0x02000,2), + ERASEINFO(0x04000,1) + } + }, { + mfr_id: MANUFACTURER_ST, + dev_id: M29W160DB, + name: "ST M29W160DB", + DevSize: SIZE_2MiB, + NumEraseRegions: 4, + regions: {ERASEINFO(0x04000,1), + ERASEINFO(0x02000,2), + ERASEINFO(0x08000,1), + ERASEINFO(0x10000,31) + } + }, { + mfr_id: MANUFACTURER_ATMEL, + dev_id: AT49BV16X4, + name: "Atmel AT49BV16X4", + DevSize: SIZE_2MiB, + NumEraseRegions: 3, + regions: {ERASEINFO(0x02000,8), + ERASEINFO(0x08000,2), + ERASEINFO(0x10000,30) + } + }, { + mfr_id: MANUFACTURER_ATMEL, + dev_id: AT49BV16X4T, + name: "Atmel AT49BV16X4T", + DevSize: SIZE_2MiB, + NumEraseRegions: 3, + regions: {ERASEINFO(0x10000,30), + ERASEINFO(0x08000,2), + ERASEINFO(0x02000,8) + } + }, { + 0 + } +}; + +int cfi_jedec_lookup(int index, int mfr_id, int dev_id) +{ + if (index>=0){ + if (jedec_table[index].mfr_id == mfr_id && + jedec_table[index].dev_id == dev_id) return index; + } + else{ + for (index=0; jedec_table[index].mfr_id; index++){ + if (jedec_table[index].mfr_id == mfr_id && + jedec_table[index].dev_id == dev_id) return index; + } + } + return -1; +} + +int cfi_jedec_setup(struct cfi_private *p_cfi, int index) +{ +int i,num_erase_regions; + + printk("Found: %s\n",jedec_table[index].name); + + num_erase_regions = jedec_table[index].NumEraseRegions; + + p_cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL); + if (!p_cfi->cfiq) { + //xx printk(KERN_WARNING "%s: kmalloc failed for CFI ident structure\n", map->name); + return -1; + } + + memset(p_cfi->cfiq,0,sizeof(struct cfi_ident)); + + p_cfi->cfiq->P_ID = P_ID_AMD_STD; + p_cfi->cfiq->NumEraseRegions = jedec_table[index].NumEraseRegions; + p_cfi->cfiq->DevSize = jedec_table[index].DevSize; + + for (i=0; icfiq->EraseRegionInfo[i] = jedec_table[index].regions[i]; + } + return 0; /* ok */ +} + diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/chips/cfi_probe.c linux/drivers/mtd/chips/cfi_probe.c --- v2.4.5/linux/drivers/mtd/chips/cfi_probe.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/chips/cfi_probe.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,671 @@ +/* + Common Flash Interface probe code. + (C) 2000 Red Hat. GPL'd. + $Id: cfi_probe.c,v 1.60 2001/06/03 01:32:57 nico Exp $ +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* #define DEBUG_CFI */ + +#ifdef DEBUG_CFI +static void print_cfi_ident(struct cfi_ident *); +#endif + +int cfi_jedec_setup(struct cfi_private *p_cfi, int index); +int cfi_jedec_lookup(int index, int mfr_id, int dev_id); + +static void check_cmd_set(struct map_info *, int, unsigned long); +static struct cfi_private *cfi_cfi_probe(struct map_info *); +struct mtd_info *cfi_probe(struct map_info *map); + + +static struct mtd_chip_driver cfi_chipdrv = { + probe: cfi_probe, + name: "cfi", + module: THIS_MODULE +}; + + +struct mtd_info *cfi_probe(struct map_info *map) +{ + struct mtd_info *mtd = NULL; + struct cfi_private *cfi; + + /* First probe the map to see if we have CFI stuff there. */ + cfi = cfi_cfi_probe(map); + + if (!cfi) + return NULL; + + map->fldrv_priv = cfi; + /* OK we liked it. Now find a driver for the command set it talks */ + + check_cmd_set(map, 1, cfi->chips[0].start); /* First the primary cmdset */ + if (!map->fldrv) + check_cmd_set(map, 0, cfi->chips[0].start); /* Then the secondary */ + + /* check_cmd_set() will have used inter_module_get to increase + the use count of the module which provides the command set + driver. If we're quitting, we have to decrease it again. + */ + + if(map->fldrv) { + mtd = map->fldrv->probe(map); + /* Undo the use count we held onto from inter_module_get */ +#ifdef MODULE + if(map->fldrv->module) + __MOD_DEC_USE_COUNT(map->fldrv->module); +#endif + if (mtd) + return mtd; + } + printk(KERN_WARNING"cfi_probe: No supported Vendor Command Set found\n"); + + kfree(cfi->cfiq); + kfree(cfi); + map->fldrv_priv = NULL; + return NULL; +} + +static __u32 cfi_send_cmd(u_char cmd, __u32 base, struct map_info *map, struct cfi_private *cfi) +{ + return cfi_send_gen_cmd(cmd, 0x55, base, map, cfi, cfi->device_type, NULL); +} + +/* check for QRY, or search for jedec id. + in: interleave,type,mode + ret: table index, <0 for error + */ +static int cfi_check_qry_or_id(struct map_info *map, __u32 base, int index, + struct cfi_private *cfi) +{ + __u32 manufacturer_id, device_id; + int osf = cfi->interleave * cfi->device_type; // scale factor + + //printk("cfi_check_qry_or_id: base=0x%08lx interl=%d type=%d index=%d\n",base,cfi->interleave,cfi->device_type,index); + + switch(cfi->cfi_mode){ + case 0: + if (cfi_read(map,base+osf*0x10)==cfi_build_cmd('Q',map,cfi) && + cfi_read(map,base+osf*0x11)==cfi_build_cmd('R',map,cfi) && + cfi_read(map,base+osf*0x12)==cfi_build_cmd('Y',map,cfi)) + return 0; // ok ! + break; + + case 1: + manufacturer_id = cfi_read(map,base+0*osf); + device_id = cfi_read(map,base+1*osf); + //printk("cfi_check_qry_or_id: man=0x%lx,id=0x%lx\n",manufacturer_id, device_id); + + return cfi_jedec_lookup(index,manufacturer_id,device_id); + } + + return -1; // nothing found +} + +static void cfi_qry_mode(struct map_info *map, __u32 base, struct cfi_private *cfi) +{ + switch(cfi->cfi_mode){ + case 0: + /* Query */ + cfi_send_cmd(0x98, base, map, cfi); + break; + + case 1: + + /* Autoselect */ + cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, CFI_DEVICETYPE_X8, NULL); + cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL); + break; + } +} + +static int cfi_probe_chip_1(struct map_info *map, __u32 base, + struct flchip *chips, struct cfi_private *cfi) +{ + int index; + __u32 tmp,ofs; + + ofs = cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, &tmp); + + cfi_qry_mode(map,base,cfi); + + index=cfi_check_qry_or_id(map,base,-1,cfi); + if (index<0) return -1; + + if (chips){ + int i; + + for (i=0; inumchips; i++){ + /* This chip should be in read mode if it's one + we've already touched. */ + if (cfi_check_qry_or_id(map,chips[i].start,index,cfi) >= 0){ + cfi_send_gen_cmd(0xF0, 0, chips[i].start, map, cfi, cfi->device_type, NULL); + if (cfi_check_qry_or_id(map,chips[i].start,index,cfi) >= 0){ + /* Yes it's got QRY for data. Most unfortunate. + Stick the old one in read mode too. */ + cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); + if (cfi_check_qry_or_id(map,base,index,cfi) >= 0){ + /* OK, so has the new one. Assume it's an alias */ + printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n", + map->name, base, chips[i].start); + return -1; + } + } else { + /* + * FIXME: Is this supposed to work? + * The third argument is already + * multiplied as this within the + * function definition. (Nicolas Pitre) + */ + cfi_send_gen_cmd(0xF0, 0, base+0xaa*cfi->interleave * cfi->device_type, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0xF0, 0, chips[i].start+0xaa*cfi->interleave * cfi->device_type, map, cfi, cfi->device_type, NULL); + return -1; + } + } + } /* for i */ + + /* OK, if we got to here, then none of the previous chips appear to + be aliases for the current one. */ + if (cfi->numchips == MAX_CFI_CHIPS) { + printk(KERN_WARNING"%s: Too many flash chips detected. Increase MAX_CFI_CHIPS from %d.\n", map->name, MAX_CFI_CHIPS); + /* Doesn't matter about resetting it to Read Mode - we're not going to talk to it anyway */ + return -1; + } + chips[cfi->numchips].start = base; + chips[cfi->numchips].state = FL_READY; + chips[cfi->numchips].mutex = &chips[cfi->numchips]._spinlock; + cfi->numchips++; + + /* Put it back into Read Mode */ + cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); + } + printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit mode\n", map->name, + cfi->interleave, cfi->device_type*8, base, map->buswidth*8); + + return index; +} + +/* put dev into qry mode, and try cfi and jedec modes for the given type/interleave + */ +static int cfi_probe_chip(struct map_info *map, __u32 base, + struct flchip *chips, struct cfi_private *cfi) +{ + int index; + cfi->cfi_mode=0; /* cfi mode */ + + switch (cfi->device_type) { + case CFI_DEVICETYPE_X8: + cfi->addr_unlock1 = 0x555; + cfi->addr_unlock2 = 0x2aa; + break; + case CFI_DEVICETYPE_X16: + cfi->addr_unlock1 = 0xaaa; + if (map->buswidth == cfi->interleave) { + /* X16 chip(s) in X8 mode */ + cfi->addr_unlock2 = 0x555; + } else { + cfi->addr_unlock2 = 0x554; + } + break; + case CFI_DEVICETYPE_X32: + cfi->addr_unlock1 = 0x1555; + cfi->addr_unlock2 = 0xaaa; + break; + default: + return 0; + } + index = cfi_probe_chip_1(map,base,chips,cfi); + if (index>=0) return index; + + cfi->cfi_mode=1; /* jedec mode */ + index = cfi_probe_chip_1(map,base,chips,cfi); + if (index>=0) return index; + + cfi->addr_unlock1 = 0x5555; + cfi->addr_unlock2 = 0x2aaa; + index = cfi_probe_chip_1(map,base,chips,cfi); + + return index; +} + +/* + * Since probeing for CFI chips requires writing to the device problems may + * occur if the flash is not present and RAM is accessed instead. For now we + * assume that the flash is present so we don't check for RAM or replace + * possibly overwritten data. + */ +static int cfi_probe_new_chip(struct map_info *map, unsigned long base, + struct flchip *chips, struct cfi_private *cfi) +{ +int index; + switch (map->buswidth) { +#ifdef CFIDEV_BUSWIDTH_1 + case CFIDEV_BUSWIDTH_1: + cfi->interleave = CFIDEV_INTERLEAVE_1; + cfi->device_type = CFI_DEVICETYPE_X8; + index = cfi_probe_chip(map,base,chips,cfi); + if (index>=0) return index; + + cfi->device_type = CFI_DEVICETYPE_X16; + index = cfi_probe_chip(map,base,chips,cfi); + if (index>=0) return index; + break; +#endif + +#ifdef CFIDEV_BUSWIDTH_2 + case CFIDEV_BUSWIDTH_2: +#ifdef CFIDEV_INTERLEAVE_1 + cfi->interleave = CFIDEV_INTERLEAVE_1; + cfi->device_type = CFI_DEVICETYPE_X16; + index = cfi_probe_chip(map,base,chips,cfi); + if (index>=0) return index; +#endif +#ifdef CFIDEV_INTERLEAVE_2 + cfi->interleave = CFIDEV_INTERLEAVE_2; + cfi->device_type = CFI_DEVICETYPE_X8; + index = cfi_probe_chip(map,base,chips,cfi); + if (index>=0) return index; + + cfi->device_type = CFI_DEVICETYPE_X16; + index = cfi_probe_chip(map,base,chips,cfi); + if (index>=0) return index; + +#endif + break; +#endif + +#ifdef CFIDEV_BUSWIDTH_4 + case CFIDEV_BUSWIDTH_4: +#ifdef CFIDEV_INTERLEAVE_4 + cfi->interleave = CFIDEV_INTERLEAVE_4; + cfi->device_type = CFI_DEVICETYPE_X16; + index = cfi_probe_chip(map,base,chips,cfi); + if (index>=0) return index; + + cfi->device_type = CFI_DEVICETYPE_X32; + index = cfi_probe_chip(map,base,chips,cfi); + if (index>=0) return index; + + cfi->device_type = CFI_DEVICETYPE_X8; + index = cfi_probe_chip(map,base,chips,cfi); + if (index>=0) return index; +#endif +#ifdef CFIDEV_INTERLEAVE_2 + cfi->interleave = CFIDEV_INTERLEAVE_2; + cfi->device_type = CFI_DEVICETYPE_X16; + index = cfi_probe_chip(map,base,chips,cfi); + if (index>=0) return index; +#endif +#ifdef CFIDEV_INTERLEAVE_1 + cfi->interleave = CFIDEV_INTERLEAVE_1; + cfi->device_type = CFI_DEVICETYPE_X32; + index = cfi_probe_chip(map,base,chips,cfi); + if (index>=0) return index; +#endif + break; +#endif + default: + printk(KERN_WARNING "cfi_probe called with unsupported buswidth %d\n", map->buswidth); + return -1; + } // switch + return -1; +} + +static struct cfi_private *cfi_cfi_probe(struct map_info *map) +{ + unsigned long base=0; + struct cfi_private cfi; + struct cfi_private *retcfi; + struct flchip chip[MAX_CFI_CHIPS]; + int i,index; + char num_erase_regions; + int ofs_factor; + + memset(&cfi, 0, sizeof(cfi)); + + /* The first invocation (with chips == NULL) leaves the device in Query Mode */ + index = cfi_probe_new_chip(map, 0, NULL, &cfi); + + if (index<0) { + printk(KERN_WARNING"%s: Found no CFI device at location zero\n", map->name); + /* Doesn't appear to be CFI-compliant at all */ + return NULL; + } + + /* Read the Basic Query Structure from the device */ + + ofs_factor = cfi.interleave*cfi.device_type; + + /* First, work out the amount of space to allocate */ + if (cfi.cfi_mode==0){ + num_erase_regions = cfi_read_query(map, base + (0x10 + 28)*ofs_factor); + +#ifdef DEBUG_CFI + printk("Number of erase regions: %d\n", num_erase_regions); +#endif + + cfi.cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL); + if (!cfi.cfiq) { + printk(KERN_WARNING "%s: kmalloc failed for CFI ident structure\n", map->name); + return NULL; + } + + memset(cfi.cfiq,0,sizeof(struct cfi_ident)); + + cfi.fast_prog=1; /* CFI supports fast programming */ + + /* CFI flash */ + for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++) { + ((unsigned char *)cfi.cfiq)[i] = cfi_read_query(map,base + (0x10 + i)*ofs_factor); + } + + /* Do any necessary byteswapping */ + cfi.cfiq->P_ID = le16_to_cpu(cfi.cfiq->P_ID); + + cfi.cfiq->P_ADR = le16_to_cpu(cfi.cfiq->P_ADR); + cfi.cfiq->A_ID = le16_to_cpu(cfi.cfiq->A_ID); + cfi.cfiq->A_ADR = le16_to_cpu(cfi.cfiq->A_ADR); + cfi.cfiq->InterfaceDesc = le16_to_cpu(cfi.cfiq->InterfaceDesc); + cfi.cfiq->MaxBufWriteSize = le16_to_cpu(cfi.cfiq->MaxBufWriteSize); + + for (i=0; iNumEraseRegions; i++) { + cfi.cfiq->EraseRegionInfo[i] = le32_to_cpu(cfi.cfiq->EraseRegionInfo[i]); + +#ifdef DEBUG_CFI + printk(" Erase Region #%d: BlockSize 0x%4.4X bytes, %d blocks\n", + i, (cfi.cfiq->EraseRegionInfo[i] >> 8) & ~0xff, + (cfi.cfiq->EraseRegionInfo[i] & 0xffff) + 1); +#endif + } + } + else{ + /* JEDEC flash */ + if (cfi_jedec_setup(&cfi,index)<0){ + printk(KERN_WARNING "cfi_jedec_setup failed\n"); + return NULL; + } + } + + if (cfi.cfiq->NumEraseRegions == 0) { + printk(KERN_WARNING "Number of erase regions is zero\n"); + kfree(cfi.cfiq); + return NULL; + } + +#ifdef DEBUG_CFI + /* Dump the information therein */ + print_cfi_ident(cfi.cfiq); +#endif + + cfi_send_cmd(0xFF, base, map, &cfi); + + /* OK. We've worked out what it is and we're happy with it. Now see if there are others */ + + chip[0].start = 0; + chip[0].state = FL_READY; + chip[0].mutex = &chip[0]._spinlock; + + cfi.chipshift = cfi.cfiq->DevSize; + cfi.numchips = 1; + + if (!cfi.chipshift) { + printk(KERN_ERR"cfi.chipsize is zero. This is bad. cfi.cfiq->DevSize is %d\n", cfi.cfiq->DevSize); + kfree(cfi.cfiq); + return NULL; + } + switch (cfi.interleave) { + case 2: cfi.chipshift += 1; break; + case 4: cfi.chipshift += 2; break; + } + + for (base = (1<size; base += (1<name); + kfree(cfi.cfiq); + return NULL; + } + memcpy(retcfi, &cfi, sizeof(cfi)); + memcpy(&retcfi->chips[0], chip, sizeof(struct flchip) * cfi.numchips); + for (i=0; i< retcfi->numchips; i++) { + init_waitqueue_head(&retcfi->chips[i].wq); + spin_lock_init(&retcfi->chips[i]._spinlock); + retcfi->chips[i].mutex = &retcfi->chips[i]._spinlock; + } + return retcfi; +} + +#ifdef DEBUG_CFI +static char *vendorname(__u16 vendor) +{ + switch (vendor) { + case P_ID_NONE: + return "None"; + + case P_ID_INTEL_EXT: + return "Intel/Sharp Extended"; + + case P_ID_AMD_STD: + return "AMD/Fujitsu Standard"; + + case P_ID_INTEL_STD: + return "Intel/Sharp Standard"; + + case P_ID_AMD_EXT: + return "AMD/Fujitsu Extended"; + + case P_ID_MITSUBISHI_STD: + return "Mitsubishi Standard"; + + case P_ID_MITSUBISHI_EXT: + return "Mitsubishi Extended"; + + case P_ID_RESERVED: + return "Not Allowed / Reserved for Future Use"; + + default: + return "Unknown"; + } +} + + +static void print_cfi_ident(struct cfi_ident *cfip) +{ +#if 0 + if (cfip->qry[0] != 'Q' || cfip->qry[1] != 'R' || cfip->qry[2] != 'Y') { + printk("Invalid CFI ident structure.\n"); + return; + } +#endif + printk("Primary Vendor Command Set: %4.4X (%s)\n", cfip->P_ID, vendorname(cfip->P_ID)); + if (cfip->P_ADR) + printk("Primary Algorithm Table at %4.4X\n", cfip->P_ADR); + else + printk("No Primary Algorithm Table\n"); + + printk("Alternative Vendor Command Set: %4.4X (%s)\n", cfip->A_ID, vendorname(cfip->A_ID)); + if (cfip->A_ADR) + printk("Alternate Algorithm Table at %4.4X\n", cfip->A_ADR); + else + printk("No Alternate Algorithm Table\n"); + + + printk("Vcc Minimum: %x.%x V\n", cfip->VccMin >> 4, cfip->VccMin & 0xf); + printk("Vcc Maximum: %x.%x V\n", cfip->VccMax >> 4, cfip->VccMax & 0xf); + if (cfip->VppMin) { + printk("Vpp Minimum: %x.%x V\n", cfip->VppMin >> 4, cfip->VppMin & 0xf); + printk("Vpp Maximum: %x.%x V\n", cfip->VppMax >> 4, cfip->VppMax & 0xf); + } + else + printk("No Vpp line\n"); + + printk("Typical byte/word write timeout: %d µs\n", 1<WordWriteTimeoutTyp); + printk("Maximum byte/word write timeout: %d µs\n", (1<WordWriteTimeoutMax) * (1<WordWriteTimeoutTyp)); + + if (cfip->BufWriteTimeoutTyp || cfip->BufWriteTimeoutMax) { + printk("Typical full buffer write timeout: %d µs\n", 1<BufWriteTimeoutTyp); + printk("Maximum full buffer write timeout: %d µs\n", (1<BufWriteTimeoutMax) * (1<BufWriteTimeoutTyp)); + } + else + printk("Full buffer write not supported\n"); + + printk("Typical block erase timeout: %d µs\n", 1<BlockEraseTimeoutTyp); + printk("Maximum block erase timeout: %d µs\n", (1<BlockEraseTimeoutMax) * (1<BlockEraseTimeoutTyp)); + if (cfip->ChipEraseTimeoutTyp || cfip->ChipEraseTimeoutMax) { + printk("Typical chip erase timeout: %d µs\n", 1<ChipEraseTimeoutTyp); + printk("Maximum chip erase timeout: %d µs\n", (1<ChipEraseTimeoutMax) * (1<ChipEraseTimeoutTyp)); + } + else + printk("Chip erase not supported\n"); + + printk("Device size: 0x%X bytes (%d MiB)\n", 1 << cfip->DevSize, 1<< (cfip->DevSize - 20)); + printk("Flash Device Interface description: 0x%4.4X\n", cfip->InterfaceDesc); + switch(cfip->InterfaceDesc) { + case 0: + printk(" - x8-only asynchronous interface\n"); + break; + + case 1: + printk(" - x16-only asynchronous interface\n"); + break; + + case 2: + printk(" - supports x8 and x16 via BYTE# with asynchronous interface\n"); + break; + + case 3: + printk(" - x32-only asynchronous interface\n"); + break; + + case 65535: + printk(" - Not Allowed / Reserved\n"); + break; + + default: + printk(" - Unknown\n"); + break; + } + + printk("Max. bytes in buffer write: 0x%x\n", 1<< cfip->MaxBufWriteSize); + printk("Number of Erase Block Regions: %d\n", cfip->NumEraseRegions); + +} +#endif /* DEBUG_CFI */ + +typedef void cfi_cmdset_fn_t(struct map_info *, int, unsigned long); + +extern cfi_cmdset_fn_t cfi_cmdset_0001; +extern cfi_cmdset_fn_t cfi_cmdset_0002; + +static void cfi_cmdset_unknown(struct map_info *map, int primary, unsigned long base) +{ + __u16 adr; + struct cfi_private *cfi = map->fldrv_priv; + __u16 type = primary?cfi->cfiq->P_ID:cfi->cfiq->A_ID; +#ifdef HAVE_INTER_MODULE + char probename[32]; + cfi_cmdset_fn_t *probe_function; + + sprintf(probename, "cfi_cmdset_%4.4X", type); + + probe_function = inter_module_get_request(probename, probename); + + if (probe_function) { + (*probe_function)(map, primary, base); + return; + } +#endif + printk(KERN_NOTICE "Support for command set %04X not present\n", type); + /* This was a command set we don't know about. Print only the basic info */ + adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR; + + if (!adr) { + printk(" No Extended Query Table\n"); + } + else { + int ofs_factor = cfi->interleave * cfi->device_type; + + if (cfi_read_query(map,base + adr*ofs_factor) != (primary?'P':'A') || + cfi_read_query(map,base + (adr+1)*ofs_factor) != (primary?'R':'L') || + cfi_read_query(map,base + (adr+2)*ofs_factor) != (primary?'I':'T')) { + printk ("Invalid Extended Query Table at %4.4X: %2.2X %2.2X %2.2X\n", + adr, + cfi_read_query(map,base + adr*ofs_factor), + cfi_read_query(map,base + (adr+1)*ofs_factor), + cfi_read_query(map,base + (adr+2)*ofs_factor)); + } + else { + printk(" Extended Query Table version %c.%c\n", + cfi_read_query(map,base + (adr+3)*ofs_factor), + cfi_read_query(map,base + (adr+4)*ofs_factor)); + } + } + cfi_send_cmd(0xff, base, map, cfi); +} + +static void check_cmd_set(struct map_info *map, int primary, unsigned long base) +{ + struct cfi_private *cfi = map->fldrv_priv; + __u16 type = primary?cfi->cfiq->P_ID:cfi->cfiq->A_ID; + + if (type == P_ID_NONE || type == P_ID_RESERVED) + return; + /* Put it in query mode */ + cfi_qry_mode(map,base,cfi); + + switch(type){ + /* Urgh. Ifdefs. The version with weak symbols was + * _much_ nicer. Shame it didn't seem to work on + * anything but x86, really. + * But we can't rely in inter_module_get() because + * that'd mean we depend on link order. + */ +#ifdef CONFIG_MTD_CFI_INTELEXT + case 0x0001: + case 0x0003: + return cfi_cmdset_0001(map, primary, base); +#endif +#ifdef CONFIG_MTD_CFI_AMDSTD + case 0x0002: + return cfi_cmdset_0002(map, primary, base); +#endif + } + + return cfi_cmdset_unknown(map, primary, base); +} + + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define cfi_probe_init init_module +#define cfi_probe_exit cleanup_module +#endif + +mod_init_t cfi_probe_init(void) +{ + register_mtd_chip_driver(&cfi_chipdrv); + return 0; +} + +mod_exit_t cfi_probe_exit(void) +{ + unregister_mtd_chip_driver(&cfi_chipdrv); +} + +module_init(cfi_probe_init); +module_exit(cfi_probe_exit); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/chips/chipreg.c linux/drivers/mtd/chips/chipreg.c --- v2.4.5/linux/drivers/mtd/chips/chipreg.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/chips/chipreg.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,92 @@ +/* + * $Id: chipreg.c,v 1.8 2001/06/09 19:58:19 dwmw2 Exp $ + * + * Registration for chip drivers + * + */ + +#include +#include +#include +#include +#include +#include + +spinlock_t chip_drvs_lock = SPIN_LOCK_UNLOCKED; +static LIST_HEAD(chip_drvs_list); + +void register_mtd_chip_driver(struct mtd_chip_driver *drv) +{ + spin_lock(&chip_drvs_lock); + list_add(&drv->list, &chip_drvs_list); + spin_unlock(&chip_drvs_lock); +} + +void unregister_mtd_chip_driver(struct mtd_chip_driver *drv) +{ + spin_lock(&chip_drvs_lock); + list_del(&drv->list); + spin_unlock(&chip_drvs_lock); +} + +static struct mtd_chip_driver *get_mtd_chip_driver (char *name) +{ + struct list_head *pos; + struct mtd_chip_driver *ret = NULL, *this; + + spin_lock(&chip_drvs_lock); + + list_for_each(pos, &chip_drvs_list) { + this = list_entry(pos, typeof(*this), list); + + if (!strcmp(this->name, name)) { + ret = this; + break; + } + } + if (ret && !try_inc_mod_count(ret->module)) { + /* Eep. Failed. */ + ret = NULL; + } + + spin_unlock(&chip_drvs_lock); + + return ret; +} + + /* Hide all the horrid details, like some silly person taking + get_module_symbol() away from us, from the caller. */ + +struct mtd_info *do_map_probe(char *name, struct map_info *map) +{ + struct mtd_chip_driver *drv; + struct mtd_info *ret; + + drv = get_mtd_chip_driver(name); + + if (!drv && !request_module(name)) + drv = get_mtd_chip_driver(name); + + if (!drv) + return NULL; + + ret = drv->probe(map); +#ifdef CONFIG_MODULES + /* We decrease the use count here. It may have been a + probe-only module, which is no longer required from this + point, having given us a handle on (and increased the use + count of) the actual driver code. + */ + if(drv->module) + __MOD_DEC_USE_COUNT(drv->module); +#endif + + if (ret) + return ret; + + return NULL; +} + +EXPORT_SYMBOL(register_mtd_chip_driver); +EXPORT_SYMBOL(unregister_mtd_chip_driver); +EXPORT_SYMBOL(do_map_probe); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/chips/jedec.c linux/drivers/mtd/chips/jedec.c --- v2.4.5/linux/drivers/mtd/chips/jedec.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/chips/jedec.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,880 @@ + +/* JEDEC Flash Interface. + * This is an older type of interface for self programming flash. It is + * commonly use in older AMD chips and is obsolete compared with CFI. + * It is called JEDEC because the JEDEC association distributes the ID codes + * for the chips. + * + * See the AMD flash databook for information on how to operate the interface. + * + * This code does not support anything wider than 8 bit flash chips, I am + * not going to guess how to send commands to them, plus I expect they will + * all speak CFI.. + * + * $Id: jedec.c,v 1.8 2001/06/09 23:56:57 dwmw2 Exp $ + */ + +#include + +struct mtd_info *jedec_probe(struct map_info *); +int jedec_probe8(struct map_info *map,unsigned long base, + struct jedec_private *priv); +int jedec_probe16(struct map_info *map,unsigned long base, + struct jedec_private *priv); +int jedec_probe32(struct map_info *map,unsigned long base, + struct jedec_private *priv); +static void jedec_flash_chip_scan(struct jedec_private *priv,unsigned long start, + unsigned long len); +static int flash_erase(struct mtd_info *mtd, struct erase_info *instr); +static int flash_write(struct mtd_info *mtd, loff_t start, size_t len, + size_t *retlen, const u_char *buf); + +static unsigned long my_bank_size; + +/* Listing of parts and sizes. We need this table to learn the sector + size of the chip and the total length */ +static const struct JEDECTable JEDEC_table[] = + {{0x013D,"AMD Am29F017D",2*1024*1024,64*1024,MTD_CAP_NORFLASH}, + {0x01AD,"AMD Am29F016",2*1024*1024,64*1024,MTD_CAP_NORFLASH}, + {0x01D5,"AMD Am29F080",1*1024*1024,64*1024,MTD_CAP_NORFLASH}, + {0x01A4,"AMD Am29F040",512*1024,64*1024,MTD_CAP_NORFLASH}, + {0x20E3,"AMD Am29W040B",512*1024,64*1024,MTD_CAP_NORFLASH}, + {0xC2AD,"Macronix MX29F016",2*1024*1024,64*1024,MTD_CAP_NORFLASH}, + {}}; + +static void jedec_sync(struct mtd_info *mtd) {}; +static int jedec_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf); +static int jedec_read_banked(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf); + +struct mtd_info *jedec_probe(struct map_info *map); + + + +static struct mtd_chip_driver jedec_chipdrv = { + probe: jedec_probe, + name: "jedec", + module: THIS_MODULE +}; + +/* Probe entry point */ +struct jedec_private priv; +struct mtd_info __MTD; +struct mtd_info *jedec_probe(struct map_info *map) +{ + struct mtd_info *MTD = &__MTD; + unsigned long Base; + unsigned long SectorSize; + unsigned count; + unsigned I,Uniq; + char Part[200]; + memset(&priv,0,sizeof(priv)); + + my_bank_size = map->size; + + if (map->size/my_bank_size > MAX_JEDEC_CHIPS) + { + printk("mtd: Increase MAX_JEDEC_CHIPS, too many banks.\n"); + return 0; + } + + for (Base = 0; Base < map->size; Base += my_bank_size) + { + // Perhaps zero could designate all tests? + if (map->buswidth == 0) + map->buswidth = 1; + + if (map->buswidth == 1){ + if (jedec_probe8(map,Base,&priv) == 0) { + printk("did recognize jedec chip\n"); + return 0; + } + } + if (map->buswidth == 2) + jedec_probe16(map,Base,&priv); + if (map->buswidth == 4) + jedec_probe32(map,Base,&priv); + } + + // Get the biggest sector size + SectorSize = 0; + for (I = 0; priv.chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) + { + // printk("priv.chips[%d].jedec is %x\n",I,priv.chips[I].jedec); + // printk("priv.chips[%d].sectorsize is %lx\n",I,priv.chips[I].sectorsize); + if (priv.chips[I].sectorsize > SectorSize) + SectorSize = priv.chips[I].sectorsize; + } + + // Quickly ensure that the other sector sizes are factors of the largest + for (I = 0; priv.chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) + { + if ((SectorSize/priv.chips[I].sectorsize)*priv.chips[I].sectorsize != SectorSize) + { + printk("mtd: Failed. Device has incompatible mixed sector sizes\n"); + return 0; + } + } + + /* Generate a part name that includes the number of different chips and + other configuration information */ + count = 1; + strncpy(Part,map->name,sizeof(Part)-10); + Part[sizeof(Part)-11] = 0; + strcat(Part," "); + Uniq = 0; + for (I = 0; priv.chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) + { + const struct JEDECTable *JEDEC; + + if (priv.chips[I+1].jedec == priv.chips[I].jedec) + { + count++; + continue; + } + + // Locate the chip in the jedec table + JEDEC = jedec_idtoinf(priv.chips[I].jedec >> 8,priv.chips[I].jedec); + if (JEDEC == 0) + { + printk("mtd: Internal Error, JEDEC not set\n"); + return 0; + } + + if (Uniq != 0) + strcat(Part,","); + Uniq++; + + if (count != 1) + sprintf(Part+strlen(Part),"%x*[%s]",count,JEDEC->name); + else + sprintf(Part+strlen(Part),"%s",JEDEC->name); + if (strlen(Part) > sizeof(Part)*2/3) + break; + count = 1; + } + + /* Determine if the chips are organized in a linear fashion, or if there + are empty banks. Note, the last bank does not count here, only the + first banks are important. Holes on non-bank boundaries can not exist + due to the way the detection algorithm works. */ + if (priv.size < my_bank_size) + my_bank_size = priv.size; + priv.is_banked = 0; + //printk("priv.size is %x, my_bank_size is %x\n",priv.size,my_bank_size); + //printk("priv.bank_fill[0] is %x\n",priv.bank_fill[0]); + if (!priv.size) { + printk("priv.size is zero\n"); + return 0; + } + if (priv.size/my_bank_size) { + if (priv.size/my_bank_size == 1) { + priv.size = my_bank_size; + } + else { + for (I = 0; I != priv.size/my_bank_size - 1; I++) + { + if (priv.bank_fill[I] != my_bank_size) + priv.is_banked = 1; + + /* This even could be eliminated, but new de-optimized read/write + functions have to be written */ + printk("priv.bank_fill[%d] is %lx, priv.bank_fill[0] is %lx\n",I,priv.bank_fill[I],priv.bank_fill[0]); + if (priv.bank_fill[I] != priv.bank_fill[0]) + { + printk("mtd: Failed. Cannot handle unsymetric banking\n"); + return 0; + } + } + } + } + if (priv.is_banked == 1) + strcat(Part,", banked"); + + // printk("Part: '%s'\n",Part); + + memset(MTD,0,sizeof(*MTD)); + // strncpy(MTD->name,Part,sizeof(MTD->name)); + // MTD->name[sizeof(MTD->name)-1] = 0; + MTD->name = map->name; + MTD->type = MTD_NORFLASH; + MTD->flags = MTD_CAP_NORFLASH; + MTD->erasesize = SectorSize*(map->buswidth); + // printk("MTD->erasesize is %x\n",(unsigned int)MTD->erasesize); + MTD->size = priv.size; + // printk("MTD->size is %x\n",(unsigned int)MTD->size); + //MTD->module = THIS_MODULE; // ? Maybe this should be the low level module? + MTD->erase = flash_erase; + if (priv.is_banked == 1) + MTD->read = jedec_read_banked; + else + MTD->read = jedec_read; + MTD->write = flash_write; + MTD->sync = jedec_sync; + MTD->priv = map; + map->fldrv_priv = &priv; + map->fldrv = &jedec_chipdrv; + MOD_INC_USE_COUNT; + return MTD; +} + +/* Helper for the JEDEC function, JEDEC numbers all have odd parity */ +static int checkparity(u_char C) +{ + u_char parity = 0; + while (C != 0) + { + parity ^= C & 1; + C >>= 1; + } + + return parity == 1; +} + + +/* Take an array of JEDEC numbers that represent interleved flash chips + and process them. Check to make sure they are good JEDEC numbers, look + them up and then add them to the chip list */ +int handle_jedecs(struct map_info *map,__u8 *Mfg,__u8 *Id,unsigned Count, + unsigned long base,struct jedec_private *priv) +{ + unsigned I,J; + unsigned long Size; + unsigned long SectorSize; + const struct JEDECTable *JEDEC; + + // Test #2 JEDEC numbers exhibit odd parity + for (I = 0; I != Count; I++) + { + if (checkparity(Mfg[I]) == 0 || checkparity(Id[I]) == 0) + return 0; + } + + // Finally, just make sure all the chip sizes are the same + JEDEC = jedec_idtoinf(Mfg[0],Id[0]); + + if (JEDEC == 0) + { + printk("mtd: Found JEDEC flash chip, but do not have a table entry for %x:%x\n",Mfg[0],Mfg[1]); + return 0; + } + + Size = JEDEC->size; + SectorSize = JEDEC->sectorsize; + for (I = 0; I != Count; I++) + { + JEDEC = jedec_idtoinf(Mfg[0],Id[0]); + if (JEDEC == 0) + { + printk("mtd: Found JEDEC flash chip, but do not have a table entry for %x:%x\n",Mfg[0],Mfg[1]); + return 0; + } + + if (Size != JEDEC->size || SectorSize != JEDEC->sectorsize) + { + printk("mtd: Failed. Interleved flash does not have matching characteristics\n"); + return 0; + } + } + + // Load the Chips + for (I = 0; I != MAX_JEDEC_CHIPS; I++) + { + if (priv->chips[I].jedec == 0) + break; + } + + if (I + Count > MAX_JEDEC_CHIPS) + { + printk("mtd: Device has too many chips. Increase MAX_JEDEC_CHIPS\n"); + return 0; + } + + // Add them to the table + for (J = 0; J != Count; J++) + { + unsigned long Bank; + + JEDEC = jedec_idtoinf(Mfg[J],Id[J]); + priv->chips[I].jedec = (Mfg[J] << 8) | Id[J]; + priv->chips[I].size = JEDEC->size; + priv->chips[I].sectorsize = JEDEC->sectorsize; + priv->chips[I].base = base + J; + priv->chips[I].datashift = J*8; + priv->chips[I].capabilities = JEDEC->capabilities; + priv->chips[I].offset = priv->size + J; + + // log2 n :| + priv->chips[I].addrshift = 0; + for (Bank = Count; Bank != 1; Bank >>= 1, priv->chips[I].addrshift++); + + // Determine how filled this bank is. + Bank = base & (~(my_bank_size-1)); + if (priv->bank_fill[Bank/my_bank_size] < base + + (JEDEC->size << priv->chips[I].addrshift) - Bank) + priv->bank_fill[Bank/my_bank_size] = base + (JEDEC->size << priv->chips[I].addrshift) - Bank; + I++; + } + + priv->size += priv->chips[I-1].size*Count; + + return priv->chips[I-1].size; +} + +/* Lookup the chip information from the JEDEC ID table. */ +const struct JEDECTable *jedec_idtoinf(__u8 mfr,__u8 id) +{ + __u16 Id = (mfr << 8) | id; + unsigned long I = 0; + for (I = 0; JEDEC_table[I].jedec != 0; I++) + if (JEDEC_table[I].jedec == Id) + return JEDEC_table + I; + return 0; +} + +// Look for flash using an 8 bit bus interface +int jedec_probe8(struct map_info *map,unsigned long base, + struct jedec_private *priv) +{ + #define flread(x) map->read8(map,base+x) + #define flwrite(v,x) map->write8(map,v,base+x) + + const unsigned long AutoSel1 = 0xAA; + const unsigned long AutoSel2 = 0x55; + const unsigned long AutoSel3 = 0x90; + const unsigned long Reset = 0xF0; + __u32 OldVal; + __u8 Mfg[1]; + __u8 Id[1]; + unsigned I; + unsigned long Size; + + // Wait for any write/erase operation to settle + OldVal = flread(base); + for (I = 0; OldVal != flread(base) && I < 10000; I++) + OldVal = flread(base); + + // Reset the chip + flwrite(Reset,0x555); + + // Send the sequence + flwrite(AutoSel1,0x555); + flwrite(AutoSel2,0x2AA); + flwrite(AutoSel3,0x555); + + // Get the JEDEC numbers + Mfg[0] = flread(0); + Id[0] = flread(1); + // printk("Mfg is %x, Id is %x\n",Mfg[0],Id[0]); + + Size = handle_jedecs(map,Mfg,Id,1,base,priv); + // printk("handle_jedecs Size is %x\n",(unsigned int)Size); + if (Size == 0) + { + flwrite(Reset,0x555); + return 0; + } + + + // Reset. + flwrite(Reset,0x555); + + return 1; + + #undef flread + #undef flwrite +} + +// Look for flash using a 16 bit bus interface (ie 2 8-bit chips) +int jedec_probe16(struct map_info *map,unsigned long base, + struct jedec_private *priv) +{ + return 0; +} + +// Look for flash using a 32 bit bus interface (ie 4 8-bit chips) +int jedec_probe32(struct map_info *map,unsigned long base, + struct jedec_private *priv) +{ + #define flread(x) map->read32(map,base+((x)<<2)) + #define flwrite(v,x) map->write32(map,v,base+((x)<<2)) + + const unsigned long AutoSel1 = 0xAAAAAAAA; + const unsigned long AutoSel2 = 0x55555555; + const unsigned long AutoSel3 = 0x90909090; + const unsigned long Reset = 0xF0F0F0F0; + __u32 OldVal; + __u8 Mfg[4]; + __u8 Id[4]; + unsigned I; + unsigned long Size; + + // Wait for any write/erase operation to settle + OldVal = flread(base); + for (I = 0; OldVal != flread(base) && I < 10000; I++) + OldVal = flread(base); + + // Reset the chip + flwrite(Reset,0x555); + + // Send the sequence + flwrite(AutoSel1,0x555); + flwrite(AutoSel2,0x2AA); + flwrite(AutoSel3,0x555); + + // Test #1, JEDEC numbers are readable from 0x??00/0x??01 + if (flread(0) != flread(0x100) || + flread(1) != flread(0x101)) + { + flwrite(Reset,0x555); + return 0; + } + + // Split up the JEDEC numbers + OldVal = flread(0); + for (I = 0; I != 4; I++) + Mfg[I] = (OldVal >> (I*8)); + OldVal = flread(1); + for (I = 0; I != 4; I++) + Id[I] = (OldVal >> (I*8)); + + Size = handle_jedecs(map,Mfg,Id,4,base,priv); + if (Size == 0) + { + flwrite(Reset,0x555); + return 0; + } + + /* Check if there is address wrap around within a single bank, if this + returns JEDEC numbers then we assume that it is wrap around. Notice + we call this routine with the JEDEC return still enabled, if two or + more flashes have a truncated address space the probe test will still + work */ + if (base + Size+0x555 < map->size && + base + Size+0x555 < (base & (~(my_bank_size-1))) + my_bank_size) + { + if (flread(base+Size) != flread(base+Size + 0x100) || + flread(base+Size + 1) != flread(base+Size + 0x101)) + { + jedec_probe32(map,base+Size,priv); + } + } + + // Reset. + flwrite(0xF0F0F0F0,0x555); + + return 1; + + #undef flread + #undef flwrite +} + +/* Linear read. */ +static int jedec_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct map_info *map = (struct map_info *)mtd->priv; + + map->copy_from(map, buf, from, len); + *retlen = len; + return 0; +} + +/* Banked read. Take special care to jump past the holes in the bank + mapping. This version assumes symetry in the holes.. */ +static int jedec_read_banked(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct map_info *map = (struct map_info *)mtd->priv; + struct jedec_private *priv = (struct jedec_private *)map->fldrv_priv; + + *retlen = 0; + while (len > 0) + { + // Determine what bank and offset into that bank the first byte is + unsigned long bank = from & (~(priv->bank_fill[0]-1)); + unsigned long offset = from & (priv->bank_fill[0]-1); + unsigned long get = len; + if (priv->bank_fill[0] - offset < len) + get = priv->bank_fill[0] - offset; + + bank /= priv->bank_fill[0]; + map->copy_from(map,buf + *retlen,bank*my_bank_size + offset,get); + + len -= get; + *retlen += get; + from += get; + } + return 0; +} + +/* Pass the flags value that the flash return before it re-entered read + mode. */ +static void jedec_flash_failed(unsigned char code) +{ + /* Bit 5 being high indicates that there was an internal device + failure, erasure time limits exceeded or something */ + if ((code & (1 << 5)) != 0) + { + printk("mtd: Internal Flash failure\n"); + return; + } + printk("mtd: Programming didn't take\n"); +} + +/* This uses the erasure function described in the AMD Flash Handbook, + it will work for flashes with a fixed sector size only. Flashes with + a selection of sector sizes (ie the AMD Am29F800B) will need a different + routine. This routine tries to parallize erasing multiple chips/sectors + where possible */ +static int flash_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + // Does IO to the currently selected chip + #define flread(x) map->read8(map,chip->base+((x)<addrshift)) + #define flwrite(v,x) map->write8(map,v,chip->base+((x)<addrshift)) + + unsigned long Time = 0; + unsigned long NoTime = 0; + unsigned long start = instr->addr, len = instr->len; + unsigned int I; + struct map_info *map = (struct map_info *)mtd->priv; + struct jedec_private *priv = (struct jedec_private *)map->fldrv_priv; + + // Verify the arguments.. + if (start + len > mtd->size || + (start % mtd->erasesize) != 0 || + (len % mtd->erasesize) != 0 || + (len/mtd->erasesize) == 0) + return -EINVAL; + + jedec_flash_chip_scan(priv,start,len); + + // Start the erase sequence on each chip + for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) + { + unsigned long off; + struct jedec_flash_chip *chip = priv->chips + I; + + if (chip->length == 0) + continue; + + if (chip->start + chip->length > chip->size) + { + printk("DIE\n"); + return -EIO; + } + + flwrite(0xF0,chip->start + 0x555); + flwrite(0xAA,chip->start + 0x555); + flwrite(0x55,chip->start + 0x2AA); + flwrite(0x80,chip->start + 0x555); + flwrite(0xAA,chip->start + 0x555); + flwrite(0x55,chip->start + 0x2AA); + + /* Once we start selecting the erase sectors the delay between each + command must not exceed 50us or it will immediately start erasing + and ignore the other sectors */ + for (off = 0; off < len; off += chip->sectorsize) + { + // Check to make sure we didn't timeout + flwrite(0x30,chip->start + off); + if (off == 0) + continue; + if ((flread(chip->start + off) & (1 << 3)) != 0) + { + printk("mtd: Ack! We timed out the erase timer!\n"); + return -EIO; + } + } + } + + /* We could split this into a timer routine and return early, performing + background erasure.. Maybe later if the need warrents */ + + /* Poll the flash for erasure completion, specs say this can take as long + as 480 seconds to do all the sectors (for a 2 meg flash). + Erasure time is dependant on chip age, temp and wear.. */ + + /* This being a generic routine assumes a 32 bit bus. It does read32s + and bundles interleved chips into the same grouping. This will work + for all bus widths */ + Time = 0; + NoTime = 0; + for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) + { + struct jedec_flash_chip *chip = priv->chips + I; + unsigned long off = 0; + unsigned todo[4] = {0,0,0,0}; + unsigned todo_left = 0; + unsigned J; + + if (chip->length == 0) + continue; + + /* Find all chips in this data line, realistically this is all + or nothing up to the interleve count */ + for (J = 0; priv->chips[J].jedec != 0 && J < MAX_JEDEC_CHIPS; J++) + { + if ((priv->chips[J].base & (~((1<addrshift)-1))) == + (chip->base & (~((1<addrshift)-1)))) + { + todo_left++; + todo[priv->chips[J].base & ((1<addrshift)-1)] = 1; + } + } + + /* printk("todo: %x %x %x %x\n",(short)todo[0],(short)todo[1], + (short)todo[2],(short)todo[3]); + */ + while (1) + { + __u32 Last[4]; + unsigned long Count = 0; + + /* During erase bit 7 is held low and bit 6 toggles, we watch this, + should it stop toggling or go high then the erase is completed, + or this is not really flash ;> */ + switch (map->buswidth) { + case 1: + Last[0] = map->read8(map,(chip->base >> chip->addrshift) + chip->start + off); + Last[1] = map->read8(map,(chip->base >> chip->addrshift) + chip->start + off); + Last[2] = map->read8(map,(chip->base >> chip->addrshift) + chip->start + off); + break; + case 2: + Last[0] = map->read16(map,(chip->base >> chip->addrshift) + chip->start + off); + Last[1] = map->read16(map,(chip->base >> chip->addrshift) + chip->start + off); + Last[2] = map->read16(map,(chip->base >> chip->addrshift) + chip->start + off); + break; + case 3: + Last[0] = map->read32(map,(chip->base >> chip->addrshift) + chip->start + off); + Last[1] = map->read32(map,(chip->base >> chip->addrshift) + chip->start + off); + Last[2] = map->read32(map,(chip->base >> chip->addrshift) + chip->start + off); + break; + } + Count = 3; + while (todo_left != 0) + { + for (J = 0; J != 4; J++) + { + __u8 Byte1 = (Last[(Count-1)%4] >> (J*8)) & 0xFF; + __u8 Byte2 = (Last[(Count-2)%4] >> (J*8)) & 0xFF; + __u8 Byte3 = (Last[(Count-3)%4] >> (J*8)) & 0xFF; + if (todo[J] == 0) + continue; + + if ((Byte1 & (1 << 7)) == 0 && Byte1 != Byte2) + { +// printk("Check %x %x %x\n",(short)J,(short)Byte1,(short)Byte2); + continue; + } + + if (Byte1 == Byte2) + { + jedec_flash_failed(Byte3); + return -EIO; + } + + todo[J] = 0; + todo_left--; + } + +/* if (NoTime == 0) + Time += HZ/10 - schedule_timeout(HZ/10);*/ + NoTime = 0; + + switch (map->buswidth) { + case 1: + Last[Count % 4] = map->read8(map,(chip->base >> chip->addrshift) + chip->start + off); + break; + case 2: + Last[Count % 4] = map->read16(map,(chip->base >> chip->addrshift) + chip->start + off); + break; + case 4: + Last[Count % 4] = map->read32(map,(chip->base >> chip->addrshift) + chip->start + off); + break; + } + Count++; + +/* // Count time, max of 15s per sector (according to AMD) + if (Time > 15*len/mtd->erasesize*HZ) + { + printk("mtd: Flash Erase Timed out\n"); + return -EIO; + } */ + } + + // Skip to the next chip if we used chip erase + if (chip->length == chip->size) + off = chip->size; + else + off += chip->sectorsize; + + if (off >= chip->length) + break; + NoTime = 1; + } + + for (J = 0; priv->chips[J].jedec != 0 && J < MAX_JEDEC_CHIPS; J++) + { + if ((priv->chips[J].base & (~((1<addrshift)-1))) == + (chip->base & (~((1<addrshift)-1)))) + priv->chips[J].length = 0; + } + } + + //printk("done\n"); + if (instr->callback) + instr->callback(instr); + return 0; + + #undef flread + #undef flwrite +} + +/* This is the simple flash writing function. It writes to every byte, in + sequence. It takes care of how to properly address the flash if + the flash is interleved. It can only be used if all the chips in the + array are identical!*/ +static int flash_write(struct mtd_info *mtd, loff_t start, size_t len, + size_t *retlen, const u_char *buf) +{ + /* Does IO to the currently selected chip. It takes the bank addressing + base (which is divisable by the chip size) adds the necesary lower bits + of addrshift (interleve index) and then adds the control register index. */ + #define flread(x) map->read8(map,base+(off&((1<addrshift)-1))+((x)<addrshift)) + #define flwrite(v,x) map->write8(map,v,base+(off&((1<addrshift)-1))+((x)<addrshift)) + + struct map_info *map = (struct map_info *)mtd->priv; + struct jedec_private *priv = (struct jedec_private *)map->fldrv_priv; + unsigned long base; + unsigned long off; + size_t save_len = len; + + if (start + len > mtd->size) + return -EIO; + + //printk("Here"); + + //printk("flash_write: start is %x, len is %x\n",start,(unsigned long)len); + while (len != 0) + { + struct jedec_flash_chip *chip = priv->chips; + unsigned long bank; + unsigned long boffset; + + // Compute the base of the flash. + off = ((unsigned long)start) % (chip->size << chip->addrshift); + base = start - off; + + // Perform banked addressing translation. + bank = base & (~(priv->bank_fill[0]-1)); + boffset = base & (priv->bank_fill[0]-1); + bank = (bank/priv->bank_fill[0])*my_bank_size; + base = bank + boffset; + + // printk("Flasing %X %X %X\n",base,chip->size,len); + // printk("off is %x, compare with %x\n",off,chip->size << chip->addrshift); + + // Loop over this page + for (; off != (chip->size << chip->addrshift) && len != 0; start++, len--, off++,buf++) + { + unsigned char oldbyte = map->read8(map,base+off); + unsigned char Last[4]; + unsigned long Count = 0; + + if (oldbyte == *buf) { + // printk("oldbyte and *buf is %x,len is %x\n",oldbyte,len); + continue; + } + if (((~oldbyte) & *buf) != 0) + printk("mtd: warn: Trying to set a 0 to a 1\n"); + + // Write + flwrite(0xAA,0x555); + flwrite(0x55,0x2AA); + flwrite(0xA0,0x555); + map->write8(map,*buf,base + off); + Last[0] = map->read8(map,base + off); + Last[1] = map->read8(map,base + off); + Last[2] = map->read8(map,base + off); + + /* Wait for the flash to finish the operation. We store the last 4 + status bytes that have been retrieved so we can determine why + it failed. The toggle bits keep toggling when there is a + failure */ + for (Count = 3; Last[(Count - 1) % 4] != Last[(Count - 2) % 4] && + Count < 10000; Count++) + Last[Count % 4] = map->read8(map,base + off); + if (Last[(Count - 1) % 4] != *buf) + { + jedec_flash_failed(Last[(Count - 3) % 4]); + return -EIO; + } + } + } + *retlen = save_len; + return 0; +} + +/* This is used to enhance the speed of the erase routine, + when things are being done to multiple chips it is possible to + parallize the operations, particularly full memory erases of multi + chip memories benifit */ +static void jedec_flash_chip_scan(struct jedec_private *priv,unsigned long start, + unsigned long len) +{ + unsigned int I; + + // Zero the records + for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) + priv->chips[I].start = priv->chips[I].length = 0; + + // Intersect the region with each chip + for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) + { + struct jedec_flash_chip *chip = priv->chips + I; + unsigned long ByteStart; + unsigned long ChipEndByte = chip->offset + (chip->size << chip->addrshift); + + // End is before this chip or the start is after it + if (start+len < chip->offset || + ChipEndByte - (1 << chip->addrshift) < start) + continue; + + if (start < chip->offset) + { + ByteStart = chip->offset; + chip->start = 0; + } + else + { + chip->start = (start - chip->offset + (1 << chip->addrshift)-1) >> chip->addrshift; + ByteStart = start; + } + + if (start + len >= ChipEndByte) + chip->length = (ChipEndByte - ByteStart) >> chip->addrshift; + else + chip->length = (start + len - ByteStart + (1 << chip->addrshift)-1) >> chip->addrshift; + } +} + /*}}}*/ +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define jedec_probe_init init_module +#define jedec_probe_exit cleanup_module +#endif + +int __init jedec_probe_init(void) +{ + register_mtd_chip_driver(&jedec_chipdrv); + return 0; +} + +static void __exit jedec_probe_exit(void) +{ + unregister_mtd_chip_driver(&jedec_chipdrv); +} + +module_init(jedec_probe_init); +module_exit(jedec_probe_exit); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/chips/map_ram.c linux/drivers/mtd/chips/map_ram.c --- v2.4.5/linux/drivers/mtd/chips/map_ram.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/chips/map_ram.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,136 @@ +/* + * Common code to handle map devices which are simple RAM + * (C) 2000 Red Hat. GPL'd. + * $Id: map_ram.c,v 1.11 2001/06/08 15:34:04 dwmw2 Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + + +static int mapram_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); +static int mapram_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *); +static int mapram_erase (struct mtd_info *, struct erase_info *); +static void mapram_nop (struct mtd_info *); +static struct mtd_info *map_ram_probe(struct map_info *map); + + +static struct mtd_chip_driver mapram_chipdrv = { + probe: map_ram_probe, + name: "ram", + module: THIS_MODULE +}; + +static struct mtd_info *map_ram_probe(struct map_info *map) +{ + struct mtd_info *mtd; + + /* Check the first byte is RAM */ +#if 0 + map->write8(map, 0x55, 0); + if (map->read8(map, 0) != 0x55) + return NULL; + + map->write8(map, 0xAA, 0); + if (map->read8(map, 0) != 0xAA) + return NULL; + + /* Check the last byte is RAM */ + map->write8(map, 0x55, map->size-1); + if (map->read8(map, map->size-1) != 0x55) + return NULL; + + map->write8(map, 0xAA, map->size-1); + if (map->read8(map, map->size-1) != 0xAA) + return NULL; +#endif + /* OK. It seems to be RAM. */ + + mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); + if (!mtd) + return NULL; + + memset(mtd, 0, sizeof(*mtd)); + + map->fldrv = &mapram_chipdrv; + mtd->priv = map; + mtd->name = map->name; + mtd->type = MTD_RAM; + mtd->erasesize = 0x10000; + mtd->size = map->size; + mtd->erase = mapram_erase; + mtd->read = mapram_read; + mtd->write = mapram_write; + mtd->sync = mapram_nop; + mtd->flags = MTD_CAP_RAM | MTD_VOLATILE; + mtd->erasesize = PAGE_SIZE; + + MOD_INC_USE_COUNT; + return mtd; +} + + +static int mapram_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) +{ + struct map_info *map = (struct map_info *)mtd->priv; + + map->copy_from(map, buf, from, len); + *retlen = len; + return 0; +} + +static int mapram_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) +{ + struct map_info *map = (struct map_info *)mtd->priv; + + map->copy_to(map, to, buf, len); + *retlen = len; + return 0; +} + +static int mapram_erase (struct mtd_info *mtd, struct erase_info *instr) +{ + /* Yeah, it's inefficient. Who cares? It's faster than a _real_ + flash erase. */ + struct map_info *map = (struct map_info *)mtd->priv; + unsigned long i; + + for (i=0; ilen; i++) + map->write8(map, 0xFF, instr->addr + i); + + if (instr->callback) + instr->callback(instr); + + return 0; +} + +static void mapram_nop(struct mtd_info *mtd) +{ + /* Nothing to see here */ +} + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define map_ram_init init_module +#define map_ram_exit cleanup_module +#endif + +static int __init map_ram_init(void) +{ + register_mtd_chip_driver(&mapram_chipdrv); + return 0; +} + +static void __exit map_ram_exit(void) +{ + unregister_mtd_chip_driver(&mapram_chipdrv); +} + +module_init(map_ram_init); +module_exit(map_ram_exit); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/chips/map_rom.c linux/drivers/mtd/chips/map_rom.c --- v2.4.5/linux/drivers/mtd/chips/map_rom.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/chips/map_rom.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,91 @@ +/* + * Common code to handle map devices which are simple ROM + * (C) 2000 Red Hat. GPL'd. + * $Id: map_rom.c,v 1.14 2001/06/02 14:30:43 dwmw2 Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +static int maprom_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); +static int maprom_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *); +static void maprom_nop (struct mtd_info *); +struct mtd_info *map_rom_probe(struct map_info *map); + +static struct mtd_chip_driver maprom_chipdrv = { + probe: map_rom_probe, + name: "rom", + module: THIS_MODULE +}; + +struct mtd_info *map_rom_probe(struct map_info *map) +{ + struct mtd_info *mtd; + + mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); + if (!mtd) + return NULL; + + memset(mtd, 0, sizeof(*mtd)); + + map->fldrv = &maprom_chipdrv; + mtd->priv = map; + mtd->name = map->name; + mtd->type = MTD_ROM; + mtd->size = map->size; + mtd->read = maprom_read; + mtd->write = maprom_write; + mtd->sync = maprom_nop; + mtd->flags = MTD_CAP_ROM; + mtd->erasesize = 131072; + + MOD_INC_USE_COUNT; + return mtd; +} + + +static int maprom_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) +{ + struct map_info *map = (struct map_info *)mtd->priv; + + map->copy_from(map, buf, from, len); + *retlen = len; + return 0; +} + +static void maprom_nop(struct mtd_info *mtd) +{ + /* Nothing to see here */ +} + +static int maprom_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) +{ + printk(KERN_NOTICE "maprom_write called\n"); + return -EIO; +} + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define map_rom_init init_module +#define map_rom_exit cleanup_module +#endif + +mod_init_t map_rom_init(void) +{ + register_mtd_chip_driver(&maprom_chipdrv); + return 0; +} + +mod_exit_t map_rom_exit(void) +{ + unregister_mtd_chip_driver(&maprom_chipdrv); +} + +module_init(map_rom_init); +module_exit(map_rom_exit); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/chips/sharp.c linux/drivers/mtd/chips/sharp.c --- v2.4.5/linux/drivers/mtd/chips/sharp.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/chips/sharp.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,593 @@ +/* + * MTD chip driver for pre-CFI Sharp flash chips + * + * Copyright 2000,2001 David A. Schleef + * 2000,2001 Lineo, Inc. + * + * $Id: sharp.c,v 1.4 2001/04/29 16:21:17 dwmw2 Exp $ + * + * Devices supported: + * LH28F016SCT Symmetrical block flash memory, 2Mx8 + * LH28F008SCT Symmetrical block flash memory, 1Mx8 + * + * Documentation: + * http://www.sharpmeg.com/datasheets/memic/flashcmp/ + * http://www.sharpmeg.com/datasheets/memic/flashcmp/01symf/16m/016sctl9.pdf + * 016sctl9.pdf + * + * Limitations: + * This driver only supports 4x1 arrangement of chips. + * Not tested on anything but PowerPC. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CMD_RESET 0xffffffff +#define CMD_READ_ID 0x90909090 +#define CMD_READ_STATUS 0x70707070 +#define CMD_CLEAR_STATUS 0x50505050 +#define CMD_BLOCK_ERASE_1 0x20202020 +#define CMD_BLOCK_ERASE_2 0xd0d0d0d0 +#define CMD_BYTE_WRITE 0x40404040 +#define CMD_SUSPEND 0xb0b0b0b0 +#define CMD_RESUME 0xd0d0d0d0 +#define CMD_SET_BLOCK_LOCK_1 0x60606060 +#define CMD_SET_BLOCK_LOCK_2 0x01010101 +#define CMD_SET_MASTER_LOCK_1 0x60606060 +#define CMD_SET_MASTER_LOCK_2 0xf1f1f1f1 +#define CMD_CLEAR_BLOCK_LOCKS_1 0x60606060 +#define CMD_CLEAR_BLOCK_LOCKS_2 0xd0d0d0d0 + +#define SR_READY 0x80808080 // 1 = ready +#define SR_ERASE_SUSPEND 0x40404040 // 1 = block erase suspended +#define SR_ERROR_ERASE 0x20202020 // 1 = error in block erase or clear lock bits +#define SR_ERROR_WRITE 0x10101010 // 1 = error in byte write or set lock bit +#define SR_VPP 0x08080808 // 1 = Vpp is low +#define SR_WRITE_SUSPEND 0x04040404 // 1 = byte write suspended +#define SR_PROTECT 0x02020202 // 1 = lock bit set +#define SR_RESERVED 0x01010101 + +#define SR_ERRORS (SR_ERROR_ERASE|SR_ERROR_WRITE|SR_VPP|SR_PROTECT) + +/* Configuration options */ + +#undef AUTOUNLOCK /* automatically unlocks blocks before erasing */ + +struct mtd_info *sharp_probe(struct map_info *); + +static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd); + +static int sharp_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf); +static int sharp_write(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, const u_char *buf); +static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr); +static void sharp_sync(struct mtd_info *mtd); +static int sharp_suspend(struct mtd_info *mtd); +static void sharp_resume(struct mtd_info *mtd); +static void sharp_destroy(struct mtd_info *mtd); + +static int sharp_write_oneword(struct map_info *map, struct flchip *chip, + unsigned long adr, __u32 datum); +static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip, + unsigned long adr); +#ifdef AUTOUNLOCK +static void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip, + unsigned long adr); +#endif + + +struct sharp_info{ + struct flchip *chip; + int bogus; + int chipshift; + int numchips; + struct flchip chips[1]; +}; + +struct mtd_info *sharp_probe(struct map_info *map); +static void sharp_destroy(struct mtd_info *mtd); + +static struct mtd_chip_driver sharp_chipdrv = { + probe: sharp_probe, + destroy: sharp_destroy, + name: "sharp", + module: THIS_MODULE +}; + + +struct mtd_info *sharp_probe(struct map_info *map) +{ + struct mtd_info *mtd = NULL; + struct sharp_info *sharp = NULL; + int width; + + mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); + if(!mtd) + return NULL; + + sharp = kmalloc(sizeof(*sharp), GFP_KERNEL); + if(!sharp) + return NULL; + + memset(mtd, 0, sizeof(*mtd)); + + width = sharp_probe_map(map,mtd); + if(!width){ + kfree(mtd); + kfree(sharp); + return NULL; + } + + mtd->priv = map; + mtd->type = MTD_NORFLASH; + mtd->erase = sharp_erase; + mtd->read = sharp_read; + mtd->write = sharp_write; + mtd->sync = sharp_sync; + mtd->suspend = sharp_suspend; + mtd->resume = sharp_resume; + mtd->flags = MTD_CAP_NORFLASH; + mtd->name = map->name; + + memset(sharp, 0, sizeof(*sharp)); + sharp->chipshift = 23; + sharp->numchips = 1; + sharp->chips[0].start = 0; + sharp->chips[0].state = FL_READY; + sharp->chips[0].mutex = &sharp->chips[0]._spinlock; + sharp->chips[0].word_write_time = 0; + init_waitqueue_head(&sharp->chips[0].wq); + spin_lock_init(&sharp->chips[0]._spinlock); + + map->fldrv = &sharp_chipdrv; + map->fldrv_priv = sharp; + + MOD_INC_USE_COUNT; + return mtd; +} + +static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd) +{ + unsigned long tmp; + unsigned long base = 0; + u32 read0, read4; + int width = 4; + + tmp = map->read32(map, base+0); + + map->write32(map, CMD_READ_ID, base+0); + + read0=map->read32(map, base+0); + read4=map->read32(map, base+4); + if(read0 == 0x89898989){ + printk("Looks like sharp flash\n"); + switch(read4){ + case 0xaaaaaaaa: + case 0xa0a0a0a0: + /* aa - LH28F016SCT-L95 2Mx8, 32 64k blocks*/ + /* a0 - LH28F016SCT-Z4 2Mx8, 32 64k blocks*/ + mtd->erasesize = 0x10000 * width; + mtd->size = 0x200000 * width; + return width; + case 0xa6a6a6a6: + /* a6 - LH28F008SCT-L12 1Mx8, 16 64k blocks*/ + /* a6 - LH28F008SCR-L85 1Mx8, 16 64k blocks*/ + mtd->erasesize = 0x10000 * width; + mtd->size = 0x100000 * width; + return width; +#if 0 + case 0x00000000: /* unknown */ + /* XX - LH28F004SCT 512kx8, 8 64k blocks*/ + mtd->erasesize = 0x10000 * width; + mtd->size = 0x80000 * width; + return width; +#endif + default: + printk("Sort-of looks like sharp flash, 0x%08x 0x%08x\n", + read0,read4); + } + }else if((map->read32(map, base+0) == CMD_READ_ID)){ + /* RAM, probably */ + printk("Looks like RAM\n"); + map->write32(map, tmp, base+0); + }else{ + printk("Doesn't look like sharp flash, 0x%08x 0x%08x\n", + read0,read4); + } + + return 0; +} + +/* This function returns with the chip->mutex lock held. */ +static int sharp_wait(struct map_info *map, struct flchip *chip) +{ + __u16 status; + unsigned long timeo = jiffies + HZ; + DECLARE_WAITQUEUE(wait, current); + int adr = 0; + +retry: + spin_lock_bh(chip->mutex); + + switch(chip->state){ + case FL_READY: + map->write32(map,CMD_READ_STATUS,adr); + chip->state = FL_STATUS; + case FL_STATUS: + status = map->read32(map,adr); +//printk("status=%08x\n",status); + + udelay(100); + if((status & SR_READY)!=SR_READY){ +//printk(".status=%08x\n",status); + udelay(100); + } + break; + default: + printk("Waiting for chip\n"); + + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + spin_unlock_bh(chip->mutex); + + schedule(); + remove_wait_queue(&chip->wq, &wait); + + if(signal_pending(current)) + return -EINTR; + + timeo = jiffies + HZ; + + goto retry; + } + + map->write32(map,CMD_RESET, adr); + + chip->state = FL_READY; + + return 0; +} + +static void sharp_release(struct flchip *chip) +{ + wake_up(&chip->wq); + spin_unlock_bh(chip->mutex); +} + +static int sharp_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct map_info *map = mtd->priv; + struct sharp_info *sharp = map->fldrv_priv; + int chipnum; + int ret = 0; + int ofs = 0; + + chipnum = (from >> sharp->chipshift); + ofs = from & ((1 << sharp->chipshift)-1); + + *retlen = 0; + + while(len){ + unsigned long thislen; + + if(chipnum>=sharp->numchips) + break; + + thislen = len; + if(ofs+thislen >= (1<chipshift)) + thislen = (1<chipshift) - ofs; + + ret = sharp_wait(map,&sharp->chips[chipnum]); + if(ret<0) + break; + + map->copy_from(map,buf,ofs,thislen); + + sharp_release(&sharp->chips[chipnum]); + + *retlen += thislen; + len -= thislen; + buf += thislen; + + ofs = 0; + chipnum++; + } + return ret; +} + +static int sharp_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + struct map_info *map = mtd->priv; + struct sharp_info *sharp = map->fldrv_priv; + int ret = 0; + int i,j; + int chipnum; + unsigned long ofs; + union { u32 l; unsigned char uc[4]; } tbuf; + + *retlen = 0; + + while(len){ + tbuf.l = 0xffffffff; + chipnum = to >> sharp->chipshift; + ofs = to & ((1<chipshift)-1); + + j=0; + for(i=ofs&3;i<4 && len;i++){ + tbuf.uc[i] = *buf; + buf++; + to++; + len--; + j++; + } + sharp_write_oneword(map, &sharp->chips[chipnum], ofs&~3, tbuf.l); + if(ret<0) + return ret; + (*retlen)+=j; + } + + return 0; +} + +static int sharp_write_oneword(struct map_info *map, struct flchip *chip, + unsigned long adr, __u32 datum) +{ + int ret; + int timeo; + int try; + int i; + int status = 0; + + ret = sharp_wait(map,chip); + + for(try=0;try<10;try++){ + map->write32(map,CMD_BYTE_WRITE,adr); + /* cpu_to_le32 -> hack to fix the writel be->le conversion */ + map->write32(map,cpu_to_le32(datum),adr); + + chip->state = FL_WRITING; + + timeo = jiffies + (HZ/2); + + map->write32(map,CMD_READ_STATUS,adr); + for(i=0;i<100;i++){ + status = map->read32(map,adr); + if((status & SR_READY)==SR_READY) + break; + } + if(i==100){ + printk("sharp: timed out writing\n"); + } + + if(!(status&SR_ERRORS)) + break; + + printk("sharp: error writing byte at addr=%08lx status=%08x\n",adr,status); + + map->write32(map,CMD_CLEAR_STATUS,adr); + } + map->write32(map,CMD_RESET,adr); + chip->state = FL_READY; + + wake_up(&chip->wq); + spin_unlock_bh(chip->mutex); + + return 0; +} + +static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + struct map_info *map = mtd->priv; + struct sharp_info *sharp = map->fldrv_priv; + unsigned long adr,len; + int chipnum, ret=0; + +//printk("sharp_erase()\n"); + if(instr->addr & (mtd->erasesize - 1)) + return -EINVAL; + if(instr->len & (mtd->erasesize - 1)) + return -EINVAL; + if(instr->len + instr->addr > mtd->size) + return -EINVAL; + + chipnum = instr->addr >> sharp->chipshift; + adr = instr->addr & ((1<chipshift)-1); + len = instr->len; + + while(len){ + ret = sharp_erase_oneblock(map, &sharp->chips[chipnum], adr); + if(ret)return ret; + + adr += mtd->erasesize; + len -= mtd->erasesize; + if(adr >> sharp->chipshift){ + adr = 0; + chipnum++; + if(chipnum>=sharp->numchips) + break; + } + } + + if(instr->callback) + instr->callback(instr); + + return 0; +} + +static int sharp_do_wait_for_ready(struct map_info *map, struct flchip *chip, + unsigned long adr) +{ + int ret; + int timeo; + int status; + DECLARE_WAITQUEUE(wait, current); + + map->write32(map,CMD_READ_STATUS,adr); + status = map->read32(map,adr); + + timeo = jiffies + HZ; + + while(jiffieswrite32(map,CMD_READ_STATUS,adr); + status = map->read32(map,adr); + if((status & SR_READY)==SR_READY){ + ret = 0; + goto out; + } + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + //spin_unlock_bh(chip->mutex); + + schedule_timeout(1); + schedule(); + remove_wait_queue(&chip->wq, &wait); + + //spin_lock_bh(chip->mutex); + + if (signal_pending(current)){ + ret = -EINTR; + goto out; + } + + } + ret = -ETIME; +out: + return ret; +} + +static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip, + unsigned long adr) +{ + int ret; + //int timeo; + int status; + //int i; + +//printk("sharp_erase_oneblock()\n"); + +#ifdef AUTOUNLOCK + /* This seems like a good place to do an unlock */ + sharp_unlock_oneblock(map,chip,adr); +#endif + + map->write32(map,CMD_BLOCK_ERASE_1,adr); + map->write32(map,CMD_BLOCK_ERASE_2,adr); + + chip->state = FL_ERASING; + + ret = sharp_do_wait_for_ready(map,chip,adr); + if(ret<0)return ret; + + map->write32(map,CMD_READ_STATUS,adr); + status = map->read32(map,adr); + + if(!(status&SR_ERRORS)){ + map->write32(map,CMD_RESET,adr); + chip->state = FL_READY; + //spin_unlock_bh(chip->mutex); + return 0; + } + + printk("sharp: error erasing block at addr=%08lx status=%08x\n",adr,status); + map->write32(map,CMD_CLEAR_STATUS,adr); + + //spin_unlock_bh(chip->mutex); + + return -EIO; +} + +#ifdef AUTOUNLOCK +static void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip, + unsigned long adr) +{ + int i; + int status; + + map->write32(map,CMD_CLEAR_BLOCK_LOCKS_1,adr); + map->write32(map,CMD_CLEAR_BLOCK_LOCKS_2,adr); + + udelay(100); + + status = map->read32(map,adr); + printk("status=%08x\n",status); + + for(i=0;i<1000;i++){ + //map->write32(map,CMD_READ_STATUS,adr); + status = map->read32(map,adr); + if((status & SR_READY)==SR_READY) + break; + udelay(100); + } + if(i==1000){ + printk("sharp: timed out unlocking block\n"); + } + + if(!(status&SR_ERRORS)){ + map->write32(map,CMD_RESET,adr); + chip->state = FL_READY; + return; + } + + printk("sharp: error unlocking block at addr=%08lx status=%08x\n",adr,status); + map->write32(map,CMD_CLEAR_STATUS,adr); +} +#endif + +static void sharp_sync(struct mtd_info *mtd) +{ + //printk("sharp_sync()\n"); +} + +static int sharp_suspend(struct mtd_info *mtd) +{ + printk("sharp_suspend()\n"); + return -EINVAL; +} + +static void sharp_resume(struct mtd_info *mtd) +{ + printk("sharp_resume()\n"); + +} + +static void sharp_destroy(struct mtd_info *mtd) +{ + printk("sharp_destroy()\n"); + +} + +#if LINUX_VERSION_CODE < 0x020212 && defined(MODULE) +#define sharp_probe_init init_module +#define sharp_probe_exit cleanup_module +#endif + +int __init sharp_probe_init(void) +{ + printk("MTD Sharp chip driver \n"); + + register_mtd_chip_driver(&sharp_chipdrv); + + return 0; +} + +static void __exit sharp_probe_exit(void) +{ + unregister_mtd_chip_driver(&sharp_chipdrv); +} + +module_init(sharp_probe_init); +module_exit(sharp_probe_exit); + diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/devices/Config.in linux/drivers/mtd/devices/Config.in --- v2.4.5/linux/drivers/mtd/devices/Config.in Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/devices/Config.in Tue Jun 12 10:30:27 2001 @@ -0,0 +1,51 @@ +# drivers/mtd/maps/Config.in + +# $Id: Config.in,v 1.2 2001/04/29 16:24:34 dwmw2 Exp $ + +mainmenu_option next_comment + +comment 'Self-contained MTD device drivers' +dep_tristate ' Ramix PMC551 PCI Mezzanine RAM card support' CONFIG_MTD_PMC551 $CONFIG_MTD $CONFIG_PCI +if [ "$CONFIG_MTD_PMC551" = "y" -o "$CONFIG_MTD_PMC551" = "m" ]; then + bool ' PMC551 256M DRAM Bugfix' CONFIG_MTD_PMC551_BUGFIX + bool ' PMC551 Debugging' CONFIG_MTD_PMC551_DEBUG +fi +dep_tristate ' Uncached system RAM' CONFIG_MTD_SLRAM $CONFIG_MTD +dep_tristate ' Test driver using RAM' CONFIG_MTD_MTDRAM $CONFIG_MTD +if [ "$CONFIG_MTD_MTDRAM" = "y" -o "$CONFIG_MTD_MTDRAM" = "m" ]; then + int 'MTDRAM device size in KiB' CONFIG_MTDRAM_TOTAL_SIZE 4096 + int 'MTDRAM erase block size in KiB' CONFIG_MTDRAM_ERASE_SIZE 128 + if [ "$CONFIG_MTD_MTDRAM" = "y" ]; then #If not a module (I don't want to test it as a module) + hex 'SRAM Hexadecimal Absolute position or 0' CONFIG_MTDRAM_ABS_POS 0 + fi +fi + +comment 'Disk-On-Chip Device Drivers' + dep_tristate ' M-Systems Disk-On-Chip 1000' CONFIG_MTD_DOC1000 $CONFIG_MTD + dep_tristate ' M-Systems Disk-On-Chip 2000 and Millennium' CONFIG_MTD_DOC2000 $CONFIG_MTD + dep_tristate ' M-Systems Disk-On-Chip Millennium-only alternative driver (see help)' CONFIG_MTD_DOC2001 $CONFIG_MTD + if [ "$CONFIG_MTD_DOC2001" = "y" -o "$CONFIG_MTD_DOC2000" = "y" ]; then + define_bool CONFIG_MTD_DOCPROBE y + else + if [ "$CONFIG_MTD_DOC2001" = "m" -o "$CONFIG_MTD_DOC2000" = "m" ]; then + define_bool CONFIG_MTD_DOCPROBE m + else + define_bool CONFIG_MTD_DOCPROBE n + fi + fi + + if [ "$CONFIG_MTD_DOCPROBE" = "y" -o "$CONFIG_MTD_DOCPROBE" = "m" ]; then + bool ' Advanced detection options for DiskOnChip' CONFIG_MTD_DOCPROBE_ADVANCED + if [ "$CONFIG_MTD_DOCPROBE_ADVANCED" = "n" ]; then + define_hex CONFIG_MTD_DOCPROBE_ADDRESS 0 + define_bool CONFIG_MTD_DOCPROBE_HIGH n + define_bool CONFIG_MTD_DOCPROBE_55AA n + else + hex ' Physical address of DiskOnChip' CONFIG_MTD_DOCPROBE_ADDRESS 0x0000 + bool ' Probe high addresses' CONFIG_MTD_DOCPROBE_HIGH + bool ' Probe for 0x55 0xAA BIOS Extension Signature' CONFIG_MTD_DOCPROBE_55AA + fi + fi + + +endmenu diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/devices/Makefile linux/drivers/mtd/devices/Makefile --- v2.4.5/linux/drivers/mtd/devices/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/devices/Makefile Tue Jun 12 10:30:27 2001 @@ -0,0 +1,23 @@ +# +# linux/drivers/devices/Makefile +# +# $Id: Makefile,v 1.2 2001/04/19 22:12:36 dwmw2 Exp $ + +O_TARGET := devlink.o + +# *** BIG UGLY NOTE *** +# +# The removal of get_module_symbol() and replacement with +# inter_module_register() et al has introduced a link order dependency +# here where previously there was none. We now have to ensure that +# doc200[01].o are linked before docprobe.o + +obj-$(CONFIG_MTD_DOC1000) += doc1000.o +obj-$(CONFIG_MTD_DOC2000) += doc2000.o +obj-$(CONFIG_MTD_DOC2001) += doc2001.o +obj-$(CONFIG_MTD_DOCPROBE) += docprobe.o docecc.o +obj-$(CONFIG_MTD_SLRAM) += slram.o +obj-$(CONFIG_MTD_PMC551) += pmc551.o +obj-$(CONFIG_MTD_MTDRAM) += mtdram.o + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/devices/doc1000.c linux/drivers/mtd/devices/doc1000.c --- v2.4.5/linux/drivers/mtd/devices/doc1000.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/devices/doc1000.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,597 @@ +/*====================================================================== + + $Id: doc1000.c,v 1.11 2000/11/24 13:43:16 dwmw2 Exp $ + +======================================================================*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* Parameters that can be set with 'insmod' */ + +static u_long base = 0xe0000; +static int erase_timeout = 10*HZ; /* in ticks */ +static int retry_limit = 4; /* write retries */ +static u_long max_tries = 4096; /* status polling */ + +MODULE_PARM(base,"l"); +MODULE_PARM(erase_timeout, "i"); +MODULE_PARM(retry_limit, "i"); +MODULE_PARM(max_tries, "i"); + +#define WINDOW_SIZE 0x2000 +#define WINDOW_MASK (WINDOW_SIZE - 1) +#define PAGEREG_LO (WINDOW_SIZE) +#define PAGEREG_HI (WINDOW_SIZE + 2) + +static struct mtd_info *mymtd; +static struct timer_list flashcard_timer; + +#define MAX_CELLS 32 +#define MAX_FLASH_DEVICES 8 + +/* A flash region is composed of one or more "cells", where we allow + simultaneous erases if they are in different cells */ + + + +struct mypriv { + u_char *baseaddr; + u_short curpage; + u_char locked; + u_short numdevices; + u_char interleave; + struct erase_info *cur_erases; + wait_queue_head_t wq; + u_char devstat[MAX_FLASH_DEVICES]; + u_long devshift; +}; + + +static void flashcard_periodic(u_long data); +static int flashcard_erase (struct mtd_info *mtd, struct erase_info *instr); +static int flashcard_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); +static int flashcard_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); +static void flashcard_sync (struct mtd_info *mtd); + +static inline void resume_erase(volatile u_char *addr); +static inline int suspend_erase(volatile u_char *addr); +static inline int byte_write (volatile u_char *addr, u_char byte); +static inline int word_write (volatile u_char *addr, __u16 word); +static inline int check_write(volatile u_char *addr); +static inline void block_erase (volatile u_char *addr); +static inline int check_erase(volatile u_char *addr); + +#ifdef CONFIG_SMP +#warning This is definitely not SMP safe. Lock the paging mechanism. +#endif + +static u_char *pagein(struct mtd_info *mtd, u_long addr) +{ + struct mypriv *priv=mtd->priv; + u_short page = addr >> 13; + + priv->baseaddr[PAGEREG_LO] = page & 0xff; + priv->baseaddr[PAGEREG_HI] = page >> 8; + priv->curpage = page; + + return &priv->baseaddr[addr & WINDOW_MASK]; +} + + +void flashcard_sync (struct mtd_info *mtd) +{ + struct mypriv *priv=mtd->priv; + + flashcard_periodic((u_long) mtd); + printk("sync..."); + if (priv->cur_erases) + interruptible_sleep_on(&priv->wq); + printk("Done.\n"); +} + +int flashcard_erase (struct mtd_info *mtd, struct erase_info *instr) +{ + u_char *pageaddr; + struct mypriv *priv=mtd->priv; + struct erase_info **tmp=&priv->cur_erases; + + if (instr->len != mtd->erasesize) + return -EINVAL; + if (instr->addr + instr->len > mtd->size) + return -EINVAL; + + pageaddr=pagein(mtd,instr->addr); + instr->mtd = mtd; + instr->dev = instr->addr >> priv->devshift; + instr->cell = (instr->addr - (instr->dev << priv->devshift)) / mtd->erasesize; + instr->next = NULL; + instr->state = MTD_ERASE_PENDING; + + while (*tmp) + { + tmp = &((*tmp) -> next); + } + + *tmp = instr; + flashcard_periodic((u_long)mtd); + return 0; +} + + +int flashcard_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) +{ + u_char *pageaddr=pagein(mtd,from); + struct mypriv *priv=mtd->priv; + u_char device = from >> priv->devshift; + u_char cell = (int) (from - (device << priv->devshift)) / mtd->erasesize; + int ret = 0, timeron = 0; + + if ((from & WINDOW_MASK) + len <= WINDOW_SIZE) + *retlen = len; + else + *retlen = WINDOW_SIZE - (from & WINDOW_MASK); + + if (priv->devstat[device]) + { + + /* There is an erase in progress or pending for this device. Stop it */ + timeron = del_timer(&flashcard_timer); + + if (priv->cur_erases && priv->cur_erases->cell == cell) + + { + /* The erase is on the current cell. Just return all 0xff */ + add_timer(&flashcard_timer); + + + printk("Cell %d currently erasing. Setting to all 0xff\n",cell); + memset(buf, 0xff, *retlen); + return 0; + } + if (priv->devstat[device] == MTD_ERASING) + { + ret = suspend_erase(pageaddr); + priv->devstat[device] = MTD_ERASE_SUSPEND; + + if (ret) + { + printk("flashcard: failed to suspend erase\n"); + add_timer (&flashcard_timer); + return ret; + } + } + + } + + writew(IF_READ_ARRAY, (u_long)pageaddr & ~1); + + ret = 0; + memcpy (buf, pageaddr, *retlen); + + writew(IF_READ_CSR, (u_long)pageaddr & ~1); + + + if (priv->devstat[device] & MTD_ERASE_SUSPEND) + { + resume_erase(pageaddr); + priv->devstat[device]=MTD_ERASING; + } + + + if (timeron) add_timer (&flashcard_timer); + + return ret; +} + + +int flashcard_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) +{ + struct mypriv *priv = (struct mypriv *)mtd->priv; + u_char *endaddr, *startaddr; + register u_char *pageaddr; + u_char device = to >> priv->devshift; +/* jiffies_t oldj=jiffies;*/ + int ret; + + while (priv->devstat[device]) + { + flashcard_sync(mtd); + } + + if ((to & WINDOW_MASK) + len <= WINDOW_SIZE) + *retlen = len; + else + *retlen = WINDOW_SIZE - (to & WINDOW_MASK); + + pageaddr = pagein(mtd, to); + startaddr = (u_char *)((u_long) pageaddr & ~1); + endaddr = pageaddr+(*retlen); + + + + /* Set up to read */ + writew(IF_READ_CSR, startaddr); + + /* Make sure it's aligned by reading the first byte if necessary */ + if (to & 1) + { + /* Unaligned access */ + + u_char cbuf; + + cbuf = *buf; + + if (!((u_long)pageaddr & 0xf)) + schedule(); + + ret = byte_write(pageaddr, cbuf); + if (ret) return ret; + + pageaddr++; buf++; + } + + + for ( ; pageaddr + 1 < endaddr; buf += 2, pageaddr += 2) + { + /* if ((u_long)pageaddr & 0xf) schedule();*/ + + ret = word_write(pageaddr, *(__u16 *)buf); + if (ret) + return ret; + } + + if (pageaddr != endaddr) + { + /* One more byte to write at the end. */ + u_char cbuf; + + cbuf = *buf; + + ret = byte_write(pageaddr, cbuf); + + if (ret) return ret; + } + + return check_write(startaddr); +/* printk("Time taken in flashcard_write: %lx jiffies\n",jiffies - oldj);*/ +} + + + + +/*====================================================================*/ + +static inline int byte_write (volatile u_char *addr, u_char byte) +{ + register u_char status; + register u_short i = 0; + + do { + status = readb(addr); + if (status & CSR_WR_READY) + { + writeb(IF_WRITE & 0xff, addr); + writeb(byte, addr); + return 0; + } + i++; + } while(i < max_tries); + + + printk(KERN_NOTICE "flashcard: byte_write timed out, status 0x%x\n",status); + return -EIO; +} + +static inline int word_write (volatile u_char *addr, __u16 word) +{ + register u_short status; + register u_short i = 0; + + do { + status = readw(addr); + if ((status & CSR_WR_READY) == CSR_WR_READY) + { + writew(IF_WRITE, addr); + writew(word, addr); + return 0; + } + i++; + } while(i < max_tries); + + printk(KERN_NOTICE "flashcard: word_write timed out at %p, status 0x%x\n", addr, status); + return -EIO; +} + +static inline void block_erase (volatile u_char *addr) +{ + writew(IF_BLOCK_ERASE, addr); + writew(IF_CONFIRM, addr); +} + + +static inline int check_erase(volatile u_char *addr) +{ + __u16 status; + +/* writew(IF_READ_CSR, addr);*/ + status = readw(addr); + + + if ((status & CSR_WR_READY) != CSR_WR_READY) + return -EBUSY; + + if (status & (CSR_ERA_ERR | CSR_VPP_LOW | CSR_WR_ERR)) + { + printk(KERN_NOTICE "flashcard: erase failed, status 0x%x\n", + status); + return -EIO; + } + + return 0; +} + +static inline int suspend_erase(volatile u_char *addr) +{ + __u16 status; + u_long i = 0; + + writew(IF_ERASE_SUSPEND, addr); + writew(IF_READ_CSR, addr); + + do { + status = readw(addr); + if ((status & CSR_WR_READY) == CSR_WR_READY) + return 0; + i++; + } while(i < max_tries); + + printk(KERN_NOTICE "flashcard: suspend_erase timed out, status 0x%x\n", status); + return -EIO; + +} + +static inline void resume_erase(volatile u_char *addr) +{ + __u16 status; + + writew(IF_READ_CSR, addr); + status = readw(addr); + + /* Only give resume signal if the erase is really suspended */ + if (status & CSR_ERA_SUSPEND) + writew(IF_CONFIRM, addr); +} + +static inline void reset_block(volatile u_char *addr) +{ + u_short i; + __u16 status; + + writew(IF_CLEAR_CSR, addr); + + for (i = 0; i < 100; i++) { + writew(IF_READ_CSR, addr); + status = readw(addr); + if (status != 0xffff) break; + udelay(1000); + } + + writew(IF_READ_CSR, addr); +} + +static inline int check_write(volatile u_char *addr) +{ + u_short status, i = 0; + + writew(IF_READ_CSR, addr); + + do { + status = readw(addr); + if (status & (CSR_WR_ERR | CSR_VPP_LOW)) + { + printk(KERN_NOTICE "flashcard: write failure at %p, status 0x%x\n", addr, status); + reset_block(addr); + return -EIO; + } + if ((status & CSR_WR_READY) == CSR_WR_READY) + return 0; + i++; + } while (i < max_tries); + + printk(KERN_NOTICE "flashcard: write timed out at %p, status 0x%x\n", addr, status); + return -EIO; +} + + +/*====================================================================*/ + + + +static void flashcard_periodic(unsigned long data) +{ + register struct mtd_info *mtd = (struct mtd_info *)data; + register struct mypriv *priv = mtd->priv; + struct erase_info *erase = priv->cur_erases; + u_char *pageaddr; + + del_timer (&flashcard_timer); + + if (!erase) + return; + + pageaddr = pagein(mtd, erase->addr); + + if (erase->state == MTD_ERASE_PENDING) + { + block_erase(pageaddr); + priv->devstat[erase->dev] = erase->state = MTD_ERASING; + erase->time = jiffies; + erase->retries = 0; + } + else if (erase->state == MTD_ERASING) + { + /* It's trying to erase. Check whether it's finished */ + + int ret = check_erase(pageaddr); + + if (!ret) + { + /* It's finished OK */ + priv->devstat[erase->dev] = 0; + priv->cur_erases = erase->next; + erase->state = MTD_ERASE_DONE; + if (erase->callback) + (*(erase->callback))(erase); + else + kfree(erase); + } + else if (ret == -EIO) + { + if (++erase->retries > retry_limit) + { + printk("Failed too many times. Giving up\n"); + priv->cur_erases = erase->next; + priv->devstat[erase->dev] = 0; + erase->state = MTD_ERASE_FAILED; + if (erase->callback) + (*(erase->callback))(erase); + else + kfree(erase); + } + else + priv->devstat[erase->dev] = erase->state = MTD_ERASE_PENDING; + } + else if (erase->time + erase_timeout < jiffies) + { + printk("Flash erase timed out. The world is broken.\n"); + + /* Just ignore and hope it goes away. For a while, read ops will give the CSR + and writes won't work. */ + + priv->cur_erases = erase->next; + priv->devstat[erase->dev] = 0; + erase->state = MTD_ERASE_FAILED; + if (erase->callback) + (*(erase->callback))(erase); + else + kfree(erase); + } + } + + if (priv->cur_erases) + { + flashcard_timer.expires = jiffies + HZ; + add_timer (&flashcard_timer); + } + else + wake_up_interruptible(&priv->wq); + +} + +#if defined (MODULE) && LINUX_VERSION_CODE < 0x20211 +#define init_doc1000 init_module +#define cleanup_doc1000 cleanup_module +#endif + +int __init init_doc1000(void) +{ + struct mypriv *priv; + + if (!base) + { + printk(KERN_NOTICE "flashcard: No start address for memory device.\n"); + return -EINVAL; + } + + mymtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL); + + if (!mymtd) + { + printk(KERN_NOTICE "physmem: Cannot allocate memory for new MTD device.\n"); + return -ENOMEM; + } + + memset(mymtd,0,sizeof(struct mtd_info)); + + mymtd->priv = (void *) kmalloc (sizeof(struct mypriv), GFP_KERNEL); + if (!mymtd->priv) + { + kfree(mymtd); + printk(KERN_NOTICE "physmem: Cannot allocate memory for new MTD device's private data.\n"); + return -ENOMEM; + } + + + + + priv=mymtd->priv; + init_waitqueue_head(&priv->wq); + + memset (priv,0,sizeof(struct mypriv)); + + priv->baseaddr = phys_to_virt(base); + priv->numdevices = 4; + + mymtd->name = "M-Systems DiskOnChip 1000"; + + mymtd->size = 0x100000; + mymtd->flags = MTD_CLEAR_BITS | MTD_ERASEABLE; + mymtd->erase = flashcard_erase; + mymtd->point = NULL; + mymtd->unpoint = NULL; + mymtd->read = flashcard_read; + mymtd->write = flashcard_write; + + mymtd->sync = flashcard_sync; + mymtd->erasesize = 0x10000; + // mymtd->interleave = 2; + priv->devshift = 24; + mymtd->type = MTD_NORFLASH; + + if (add_mtd_device(mymtd)) + { + printk(KERN_NOTICE "MTD device registration failed!\n"); + kfree(mymtd->priv); + kfree(mymtd); + return -EAGAIN; + } + + init_timer(&flashcard_timer); + flashcard_timer.function = flashcard_periodic; + flashcard_timer.data = (u_long)mymtd; + return 0; +} + +static void __init cleanup_doc1000(void) +{ + kfree (mymtd->priv); + del_mtd_device(mymtd); + kfree(mymtd); +} + +#if LINUX_VERSION_CODE >= 0x20211 +module_init(init_doc1000); +module_exit(cleanup_doc1000); +#endif diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/devices/doc2000.c linux/drivers/mtd/devices/doc2000.c --- v2.4.5/linux/drivers/mtd/devices/doc2000.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/devices/doc2000.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,1121 @@ + +/* + * Linux driver for Disk-On-Chip 2000 and Millennium + * (c) 1999 Machine Vision Holdings, Inc. + * (c) 1999, 2000 David Woodhouse + * + * $Id: doc2000.c,v 1.43 2001/06/02 14:30:43 dwmw2 Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define DOC_SUPPORT_2000 +#define DOC_SUPPORT_MILLENNIUM + +#ifdef DOC_SUPPORT_2000 +#define DoC_is_2000(doc) (doc->ChipID == DOC_ChipID_Doc2k) +#else +#define DoC_is_2000(doc) (0) +#endif + +#ifdef DOC_SUPPORT_MILLENNIUM +#define DoC_is_Millennium(doc) (doc->ChipID == DOC_ChipID_DocMil) +#else +#define DoC_is_Millennium(doc) (0) +#endif + +/* #define ECC_DEBUG */ + +/* I have no idea why some DoC chips can not use memcpy_from|to_io(). + * This may be due to the different revisions of the ASIC controller built-in or + * simplily a QA/Bug issue. Who knows ?? If you have trouble, please uncomment + * this: + #undef USE_MEMCPY +*/ + +static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf); +static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf); +static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf, u_char *eccbuf); +static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf, u_char *eccbuf); +static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, + size_t *retlen, u_char *buf); +static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, + size_t *retlen, const u_char *buf); +static int doc_erase (struct mtd_info *mtd, struct erase_info *instr); + +static struct mtd_info *doc2klist = NULL; + +/* Perform the required delay cycles by reading from the appropriate register */ +static void DoC_Delay(struct DiskOnChip *doc, unsigned short cycles) +{ + volatile char dummy; + int i; + + for (i = 0; i < cycles; i++) { + if (DoC_is_Millennium(doc)) + dummy = ReadDOC(doc->virtadr, NOP); + else + dummy = ReadDOC(doc->virtadr, DOCStatus); + } + +} + +/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */ +static int _DoC_WaitReady(struct DiskOnChip *doc) +{ + unsigned long docptr = doc->virtadr; + unsigned short c = 0xffff; + + DEBUG(MTD_DEBUG_LEVEL3, + "_DoC_WaitReady called for out-of-line wait\n"); + + /* Out-of-line routine to wait for chip response */ + while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B) && --c) + ; + + if (c == 0) + DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n"); + + return (c == 0); +} + +static inline int DoC_WaitReady(struct DiskOnChip *doc) +{ + unsigned long docptr = doc->virtadr; + /* This is inline, to optimise the common case, where it's ready instantly */ + int ret = 0; + + /* 4 read form NOP register should be issued in prior to the read from CDSNControl + see Software Requirement 11.4 item 2. */ + DoC_Delay(doc, 4); + + if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) + /* Call the out-of-line routine to wait */ + ret = _DoC_WaitReady(doc); + + /* issue 2 read from NOP register after reading from CDSNControl register + see Software Requirement 11.4 item 2. */ + DoC_Delay(doc, 2); + + return ret; +} + +/* DoC_Command: Send a flash command to the flash chip through the CDSN Slow IO register to + bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is + required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */ + +static inline int DoC_Command(struct DiskOnChip *doc, unsigned char command, + unsigned char xtraflags) +{ + unsigned long docptr = doc->virtadr; + + if (DoC_is_2000(doc)) + xtraflags |= CDSN_CTRL_FLASH_IO; + + /* Assert the CLE (Command Latch Enable) line to the flash chip */ + WriteDOC(xtraflags | CDSN_CTRL_CLE | CDSN_CTRL_CE, docptr, CDSNControl); + DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */ + + if (DoC_is_Millennium(doc)) + WriteDOC(command, docptr, CDSNSlowIO); + + /* Send the command */ + WriteDOC_(command, docptr, doc->ioreg); + + /* Lower the CLE line */ + WriteDOC(xtraflags | CDSN_CTRL_CE, docptr, CDSNControl); + DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */ + + /* Wait for the chip to respond - Software requirement 11.4.1 (extended for any command) */ + return DoC_WaitReady(doc); +} + +/* DoC_Address: Set the current address for the flash chip through the CDSN Slow IO register to + bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is + required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */ + +static int DoC_Address(struct DiskOnChip *doc, int numbytes, unsigned long ofs, + unsigned char xtraflags1, unsigned char xtraflags2) +{ + unsigned long docptr; + int i; + + docptr = doc->virtadr; + + if (DoC_is_2000(doc)) + xtraflags1 |= CDSN_CTRL_FLASH_IO; + + /* Assert the ALE (Address Latch Enable) line to the flash chip */ + WriteDOC(xtraflags1 | CDSN_CTRL_ALE | CDSN_CTRL_CE, docptr, CDSNControl); + + DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */ + + /* Send the address */ + /* Devices with 256-byte page are addressed as: + Column (bits 0-7), Page (bits 8-15, 16-23, 24-31) + * there is no device on the market with page256 + and more than 24 bits. + Devices with 512-byte page are addressed as: + Column (bits 0-7), Page (bits 9-16, 17-24, 25-31) + * 25-31 is sent only if the chip support it. + * bit 8 changes the read command to be sent + (NAND_CMD_READ0 or NAND_CMD_READ1). + */ + + if (numbytes == ADDR_COLUMN || numbytes == ADDR_COLUMN_PAGE) { + if (DoC_is_Millennium(doc)) + WriteDOC(ofs & 0xff, docptr, CDSNSlowIO); + WriteDOC_(ofs & 0xff, docptr, doc->ioreg); + } + + if (doc->page256) { + ofs = ofs >> 8; + } else { + ofs = ofs >> 9; + } + + if (numbytes == ADDR_PAGE || numbytes == ADDR_COLUMN_PAGE) { + for (i = 0; i < doc->pageadrlen; i++, ofs = ofs >> 8) { + if (DoC_is_Millennium(doc)) + WriteDOC(ofs & 0xff, docptr, CDSNSlowIO); + WriteDOC_(ofs & 0xff, docptr, doc->ioreg); + } + } + + DoC_Delay(doc, 2); /* Needed for some slow flash chips. mf. */ + + /* FIXME: The SlowIO's for millennium could be replaced by + a single WritePipeTerm here. mf. */ + + /* Lower the ALE line */ + WriteDOC(xtraflags1 | xtraflags2 | CDSN_CTRL_CE, docptr, + CDSNControl); + + DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */ + + /* Wait for the chip to respond - Software requirement 11.4.1 */ + return DoC_WaitReady(doc); +} + +/* Read a buffer from DoC, taking care of Millennium odditys */ +static void DoC_ReadBuf(struct DiskOnChip *doc, u_char * buf, int len) +{ + int dummy; + int modulus = 0xffff; + unsigned long docptr; + int i; + + docptr = doc->virtadr; + + if (len <= 0) + return; + + if (DoC_is_Millennium(doc)) { + /* Read the data via the internal pipeline through CDSN IO register, + see Pipelined Read Operations 11.3 */ + dummy = ReadDOC(docptr, ReadPipeInit); + + /* Millennium should use the LastDataRead register - Pipeline Reads */ + len--; + + /* This is needed for correctly ECC calculation */ + modulus = 0xff; + } + + for (i = 0; i < len; i++) + buf[i] = ReadDOC_(docptr, doc->ioreg + (i & modulus)); + + if (DoC_is_Millennium(doc)) { + buf[i] = ReadDOC(docptr, LastDataRead); + } +} + +/* Write a buffer to DoC, taking care of Millennium odditys */ +static void DoC_WriteBuf(struct DiskOnChip *doc, const u_char * buf, int len) +{ + unsigned long docptr; + int i; + + docptr = doc->virtadr; + + if (len <= 0) + return; + + for (i = 0; i < len; i++) + WriteDOC_(buf[i], docptr, doc->ioreg + i); + + if (DoC_is_Millennium(doc)) { + WriteDOC(0x00, docptr, WritePipeTerm); + } +} + + +/* DoC_SelectChip: Select a given flash chip within the current floor */ + +static inline int DoC_SelectChip(struct DiskOnChip *doc, int chip) +{ + unsigned long docptr = doc->virtadr; + + /* Software requirement 11.4.4 before writing DeviceSelect */ + /* Deassert the CE line to eliminate glitches on the FCE# outputs */ + WriteDOC(CDSN_CTRL_WP, docptr, CDSNControl); + DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */ + + /* Select the individual flash chip requested */ + WriteDOC(chip, docptr, CDSNDeviceSelect); + DoC_Delay(doc, 4); + + /* Reassert the CE line */ + WriteDOC(CDSN_CTRL_CE | CDSN_CTRL_FLASH_IO | CDSN_CTRL_WP, docptr, + CDSNControl); + DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */ + + /* Wait for it to be ready */ + return DoC_WaitReady(doc); +} + +/* DoC_SelectFloor: Select a given floor (bank of flash chips) */ + +static inline int DoC_SelectFloor(struct DiskOnChip *doc, int floor) +{ + unsigned long docptr = doc->virtadr; + + /* Select the floor (bank) of chips required */ + WriteDOC(floor, docptr, FloorSelect); + + /* Wait for the chip to be ready */ + return DoC_WaitReady(doc); +} + +/* DoC_IdentChip: Identify a given NAND chip given {floor,chip} */ + +static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip) +{ + int mfr, id, i; + volatile char dummy; + + /* Page in the required floor/chip */ + DoC_SelectFloor(doc, floor); + DoC_SelectChip(doc, chip); + + /* Reset the chip */ + if (DoC_Command(doc, NAND_CMD_RESET, CDSN_CTRL_WP)) { + DEBUG(MTD_DEBUG_LEVEL2, + "DoC_Command (reset) for %d,%d returned true\n", + floor, chip); + return 0; + } + + + /* Read the NAND chip ID: 1. Send ReadID command */ + if (DoC_Command(doc, NAND_CMD_READID, CDSN_CTRL_WP)) { + DEBUG(MTD_DEBUG_LEVEL2, + "DoC_Command (ReadID) for %d,%d returned true\n", + floor, chip); + return 0; + } + + /* Read the NAND chip ID: 2. Send address byte zero */ + DoC_Address(doc, ADDR_COLUMN, 0, CDSN_CTRL_WP, 0); + + /* Read the manufacturer and device id codes from the device */ + + /* CDSN Slow IO register see Software Requirement 11.4 item 5. */ + dummy = ReadDOC(doc->virtadr, CDSNSlowIO); + DoC_Delay(doc, 2); + mfr = ReadDOC_(doc->virtadr, doc->ioreg); + + /* CDSN Slow IO register see Software Requirement 11.4 item 5. */ + dummy = ReadDOC(doc->virtadr, CDSNSlowIO); + DoC_Delay(doc, 2); + id = ReadDOC_(doc->virtadr, doc->ioreg); + + /* No response - return failure */ + if (mfr == 0xff || mfr == 0) + return 0; + + /* Check it's the same as the first chip we identified. + * M-Systems say that any given DiskOnChip device should only + * contain _one_ type of flash part, although that's not a + * hardware restriction. */ + if (doc->mfr) { + if (doc->mfr == mfr && doc->id == id) + return 1; /* This is another the same the first */ + else + printk(KERN_WARNING + "Flash chip at floor %d, chip %d is different:\n", + floor, chip); + } + + /* Print and store the manufacturer and ID codes. */ + for (i = 0; nand_flash_ids[i].name != NULL; i++) { + if (mfr == nand_flash_ids[i].manufacture_id && + id == nand_flash_ids[i].model_id) { + printk(KERN_INFO + "Flash chip found: Manufacturer ID: %2.2X, " + "Chip ID: %2.2X (%s)\n", mfr, id, + nand_flash_ids[i].name); + if (!doc->mfr) { + doc->mfr = mfr; + doc->id = id; + doc->chipshift = + nand_flash_ids[i].chipshift; + doc->page256 = nand_flash_ids[i].page256; + doc->pageadrlen = + nand_flash_ids[i].pageadrlen; + doc->erasesize = + nand_flash_ids[i].erasesize; + return 1; + } + return 0; + } + } + + + /* We haven't fully identified the chip. Print as much as we know. */ + printk(KERN_WARNING "Unknown flash chip found: %2.2X %2.2X\n", + id, mfr); + + printk(KERN_WARNING "Please report to dwmw2@infradead.org\n"); + return 0; +} + +/* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */ + +static void DoC_ScanChips(struct DiskOnChip *this) +{ + int floor, chip; + int numchips[MAX_FLOORS]; + int maxchips = MAX_CHIPS; + int ret = 1; + + this->numchips = 0; + this->mfr = 0; + this->id = 0; + + if (DoC_is_Millennium(this)) + maxchips = MAX_CHIPS_MIL; + + /* For each floor, find the number of valid chips it contains */ + for (floor = 0; floor < MAX_FLOORS; floor++) { + ret = 1; + numchips[floor] = 0; + for (chip = 0; chip < maxchips && ret != 0; chip++) { + + ret = DoC_IdentChip(this, floor, chip); + if (ret) { + numchips[floor]++; + this->numchips++; + } + } + } + + /* If there are none at all that we recognise, bail */ + if (!this->numchips) { + printk("No flash chips recognised.\n"); + return; + } + + /* Allocate an array to hold the information for each chip */ + this->chips = kmalloc(sizeof(struct Nand) * this->numchips, GFP_KERNEL); + if (!this->chips) { + printk("No memory for allocating chip info structures\n"); + return; + } + + ret = 0; + + /* Fill out the chip array with {floor, chipno} for each + * detected chip in the device. */ + for (floor = 0; floor < MAX_FLOORS; floor++) { + for (chip = 0; chip < numchips[floor]; chip++) { + this->chips[ret].floor = floor; + this->chips[ret].chip = chip; + this->chips[ret].curadr = 0; + this->chips[ret].curmode = 0x50; + ret++; + } + } + + /* Calculate and print the total size of the device */ + this->totlen = this->numchips * (1 << this->chipshift); + + printk(KERN_INFO "%d flash chips found. Total DiskOnChip size: %ld MiB\n", + this->numchips, this->totlen >> 20); +} + +static int DoC2k_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2) +{ + int tmp1, tmp2, retval; + if (doc1->physadr == doc2->physadr) + return 1; + + /* Use the alias resolution register which was set aside for this + * purpose. If it's value is the same on both chips, they might + * be the same chip, and we write to one and check for a change in + * the other. It's unclear if this register is usuable in the + * DoC 2000 (it's in the Millennium docs), but it seems to work. */ + tmp1 = ReadDOC(doc1->virtadr, AliasResolution); + tmp2 = ReadDOC(doc2->virtadr, AliasResolution); + if (tmp1 != tmp2) + return 0; + + WriteDOC((tmp1 + 1) % 0xff, doc1->virtadr, AliasResolution); + tmp2 = ReadDOC(doc2->virtadr, AliasResolution); + if (tmp2 == (tmp1 + 1) % 0xff) + retval = 1; + else + retval = 0; + + /* Restore register contents. May not be necessary, but do it just to + * be safe. */ + WriteDOC(tmp1, doc1->virtadr, AliasResolution); + + return retval; +} + +static const char im_name[] = "DoC2k_init"; + +/* This routine is made available to other mtd code via + * inter_module_register. It must only be accessed through + * inter_module_get which will bump the use count of this module. The + * addresses passed back in mtd are valid as long as the use count of + * this module is non-zero, i.e. between inter_module_get and + * inter_module_put. Keith Owens 29 Oct 2000. + */ +static void DoC2k_init(struct mtd_info *mtd) +{ + struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv; + struct DiskOnChip *old = NULL; + + /* We must avoid being called twice for the same device. */ + + if (doc2klist) + old = (struct DiskOnChip *) doc2klist->priv; + + while (old) { + if (DoC2k_is_alias(old, this)) { + printk(KERN_NOTICE + "Ignoring DiskOnChip 2000 at 0x%lX - already configured\n", + this->physadr); + iounmap((void *) this->virtadr); + kfree(mtd); + return; + } + if (old->nextdoc) + old = (struct DiskOnChip *) old->nextdoc->priv; + else + old = NULL; + } + + + switch (this->ChipID) { + case DOC_ChipID_Doc2k: + mtd->name = "DiskOnChip 2000"; + this->ioreg = DoC_2k_CDSN_IO; + break; + case DOC_ChipID_DocMil: + mtd->name = "DiskOnChip Millennium"; + this->ioreg = DoC_Mil_CDSN_IO; + break; + } + + printk(KERN_NOTICE "%s found at address 0x%lX\n", mtd->name, + this->physadr); + + mtd->type = MTD_NANDFLASH; + mtd->flags = MTD_CAP_NANDFLASH; + mtd->size = 0; + mtd->erasesize = 0; + mtd->oobblock = 512; + mtd->oobsize = 16; + mtd->module = THIS_MODULE; + mtd->erase = doc_erase; + mtd->point = NULL; + mtd->unpoint = NULL; + mtd->read = doc_read; + mtd->write = doc_write; + mtd->read_ecc = doc_read_ecc; + mtd->write_ecc = doc_write_ecc; + mtd->read_oob = doc_read_oob; + mtd->write_oob = doc_write_oob; + mtd->sync = NULL; + + this->totlen = 0; + this->numchips = 0; + + this->curfloor = -1; + this->curchip = -1; + + /* Ident all the chips present. */ + DoC_ScanChips(this); + + if (!this->totlen) { + kfree(mtd); + iounmap((void *) this->virtadr); + } else { + this->nextdoc = doc2klist; + doc2klist = mtd; + mtd->size = this->totlen; + mtd->erasesize = this->erasesize; + add_mtd_device(mtd); + return; + } +} + +static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t * retlen, u_char * buf) +{ + /* Just a special case of doc_read_ecc */ + return doc_read_ecc(mtd, from, len, retlen, buf, NULL); +} + +static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, + size_t * retlen, u_char * buf, u_char * eccbuf) +{ + struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv; + unsigned long docptr; + struct Nand *mychip; + unsigned char syndrome[6]; + volatile char dummy; + int i, len256 = 0, ret=0; + + docptr = this->virtadr; + + /* Don't allow read past end of device */ + if (from >= this->totlen) + return -EINVAL; + + /* Don't allow a single read to cross a 512-byte block boundary */ + if (from + len > ((from | 0x1ff) + 1)) + len = ((from | 0x1ff) + 1) - from; + + /* The ECC will not be calculated correctly if less than 512 is read */ + if (len != 0x200 && eccbuf) + printk(KERN_WARNING + "ECC needs a full sector read (adr: %lx size %lx)\n", + (long) from, (long) len); + + /* printk("DoC_Read (adr: %lx size %lx)\n", (long) from, (long) len); */ + + + /* Find the chip which is to be used and select it */ + mychip = &this->chips[from >> (this->chipshift)]; + + if (this->curfloor != mychip->floor) { + DoC_SelectFloor(this, mychip->floor); + DoC_SelectChip(this, mychip->chip); + } else if (this->curchip != mychip->chip) { + DoC_SelectChip(this, mychip->chip); + } + + this->curfloor = mychip->floor; + this->curchip = mychip->chip; + + DoC_Command(this, + (!this->page256 + && (from & 0x100)) ? NAND_CMD_READ1 : NAND_CMD_READ0, + CDSN_CTRL_WP); + DoC_Address(this, ADDR_COLUMN_PAGE, from, CDSN_CTRL_WP, + CDSN_CTRL_ECC_IO); + + if (eccbuf) { + /* Prime the ECC engine */ + WriteDOC(DOC_ECC_RESET, docptr, ECCConf); + WriteDOC(DOC_ECC_EN, docptr, ECCConf); + } else { + /* disable the ECC engine */ + WriteDOC(DOC_ECC_RESET, docptr, ECCConf); + WriteDOC(DOC_ECC_DIS, docptr, ECCConf); + } + + /* treat crossing 256-byte sector for 2M x 8bits devices */ + if (this->page256 && from + len > (from | 0xff) + 1) { + len256 = (from | 0xff) + 1 - from; + DoC_ReadBuf(this, buf, len256); + + DoC_Command(this, NAND_CMD_READ0, CDSN_CTRL_WP); + DoC_Address(this, ADDR_COLUMN_PAGE, from + len256, + CDSN_CTRL_WP, CDSN_CTRL_ECC_IO); + } + + DoC_ReadBuf(this, &buf[len256], len - len256); + + /* Let the caller know we completed it */ + *retlen = len; + + if (eccbuf) { + /* Read the ECC data through the DiskOnChip ECC logic */ + /* Note: this will work even with 2M x 8bit devices as */ + /* they have 8 bytes of OOB per 256 page. mf. */ + DoC_ReadBuf(this, eccbuf, 6); + + /* Flush the pipeline */ + if (DoC_is_Millennium(this)) { + dummy = ReadDOC(docptr, ECCConf); + dummy = ReadDOC(docptr, ECCConf); + i = ReadDOC(docptr, ECCConf); + } else { + dummy = ReadDOC(docptr, 2k_ECCStatus); + dummy = ReadDOC(docptr, 2k_ECCStatus); + i = ReadDOC(docptr, 2k_ECCStatus); + } + + /* Check the ECC Status */ + if (i & 0x80) { + int nb_errors; + /* There was an ECC error */ +#ifdef ECC_DEBUG + printk("DiskOnChip ECC Error: Read at %lx\n", (long)from); +#endif + /* Read the ECC syndrom through the DiskOnChip ECC logic. + These syndrome will be all ZERO when there is no error */ + for (i = 0; i < 6; i++) { + syndrome[i] = + ReadDOC(docptr, ECCSyndrome0 + i); + } + nb_errors = doc_decode_ecc(buf, syndrome); + +#ifdef ECC_DEBUG + printk("Errors corrected: %x\n", nb_errors); +#endif + if (nb_errors < 0) { + /* We return error, but have actually done the read. Not that + this can be told to user-space, via sys_read(), but at least + MTD-aware stuff can know about it by checking *retlen */ + ret = -EIO; + } + } + +#ifdef PSYCHO_DEBUG + printk("ECC DATA at %lxB: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", + (long)from, eccbuf[0], eccbuf[1], eccbuf[2], + eccbuf[3], eccbuf[4], eccbuf[5]); +#endif + + /* disable the ECC engine */ + WriteDOC(DOC_ECC_DIS, docptr , ECCConf); + } + + /* according to 11.4.1, we need to wait for the busy line + * drop if we read to the end of the page. */ + if(0 == ((from + *retlen) & 0x1ff)) + { + DoC_WaitReady(this); + } + + return ret; +} + +static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t * retlen, const u_char * buf) +{ + char eccbuf[6]; + return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf); +} + +static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, + size_t * retlen, const u_char * buf, + u_char * eccbuf) +{ + struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv; + int di; /* Yes, DI is a hangover from when I was disassembling the binary driver */ + unsigned long docptr; + volatile char dummy; + int len256 = 0; + struct Nand *mychip; + + docptr = this->virtadr; + + /* Don't allow write past end of device */ + if (to >= this->totlen) + return -EINVAL; + + /* Don't allow a single write to cross a 512-byte block boundary */ + if (to + len > ((to | 0x1ff) + 1)) + len = ((to | 0x1ff) + 1) - to; + + /* The ECC will not be calculated correctly if less than 512 is written */ + if (len != 0x200 && eccbuf) + printk(KERN_WARNING + "ECC needs a full sector write (adr: %lx size %lx)\n", + (long) to, (long) len); + + /* printk("DoC_Write (adr: %lx size %lx)\n", (long) to, (long) len); */ + + /* Find the chip which is to be used and select it */ + mychip = &this->chips[to >> (this->chipshift)]; + + if (this->curfloor != mychip->floor) { + DoC_SelectFloor(this, mychip->floor); + DoC_SelectChip(this, mychip->chip); + } else if (this->curchip != mychip->chip) { + DoC_SelectChip(this, mychip->chip); + } + + this->curfloor = mychip->floor; + this->curchip = mychip->chip; + + /* Set device to main plane of flash */ + DoC_Command(this, NAND_CMD_RESET, CDSN_CTRL_WP); + DoC_Command(this, + (!this->page256 + && (to & 0x100)) ? NAND_CMD_READ1 : NAND_CMD_READ0, + CDSN_CTRL_WP); + + DoC_Command(this, NAND_CMD_SEQIN, 0); + DoC_Address(this, ADDR_COLUMN_PAGE, to, 0, CDSN_CTRL_ECC_IO); + + if (eccbuf) { + /* Prime the ECC engine */ + WriteDOC(DOC_ECC_RESET, docptr, ECCConf); + WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf); + } else { + /* disable the ECC engine */ + WriteDOC(DOC_ECC_RESET, docptr, ECCConf); + WriteDOC(DOC_ECC_DIS, docptr, ECCConf); + } + + /* treat crossing 256-byte sector for 2M x 8bits devices */ + if (this->page256 && to + len > (to | 0xff) + 1) { + len256 = (to | 0xff) + 1 - to; + DoC_WriteBuf(this, buf, len256); + + DoC_Command(this, NAND_CMD_PAGEPROG, 0); + + DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP); + /* There's an implicit DoC_WaitReady() in DoC_Command */ + + dummy = ReadDOC(docptr, CDSNSlowIO); + DoC_Delay(this, 2); + + if (ReadDOC_(docptr, this->ioreg) & 1) { + printk("Error programming flash\n"); + /* Error in programming */ + *retlen = 0; + return -EIO; + } + + DoC_Command(this, NAND_CMD_SEQIN, 0); + DoC_Address(this, ADDR_COLUMN_PAGE, to + len256, 0, + CDSN_CTRL_ECC_IO); + } + + DoC_WriteBuf(this, &buf[len256], len - len256); + + if (eccbuf) { + WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_CE, docptr, + CDSNControl); + + if (DoC_is_Millennium(this)) { + WriteDOC(0, docptr, NOP); + WriteDOC(0, docptr, NOP); + WriteDOC(0, docptr, NOP); + } else { + WriteDOC_(0, docptr, this->ioreg); + WriteDOC_(0, docptr, this->ioreg); + WriteDOC_(0, docptr, this->ioreg); + } + + /* Read the ECC data through the DiskOnChip ECC logic */ + for (di = 0; di < 6; di++) { + eccbuf[di] = ReadDOC(docptr, ECCSyndrome0 + di); + } + + /* Reset the ECC engine */ + WriteDOC(DOC_ECC_DIS, docptr, ECCConf); + +#ifdef PSYCHO_DEBUG + printk + ("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", + (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], + eccbuf[4], eccbuf[5]); +#endif + } + + DoC_Command(this, NAND_CMD_PAGEPROG, 0); + + DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP); + /* There's an implicit DoC_WaitReady() in DoC_Command */ + + dummy = ReadDOC(docptr, CDSNSlowIO); + DoC_Delay(this, 2); + + if (ReadDOC_(docptr, this->ioreg) & 1) { + printk("Error programming flash\n"); + /* Error in programming */ + *retlen = 0; + return -EIO; + } + + /* Let the caller know we completed it */ + *retlen = len; + + if (eccbuf) { + unsigned char x[8]; + size_t dummy; + + /* Write the ECC data to flash */ + for (di=0; di<6; di++) + x[di] = eccbuf[di]; + + x[6]=0x55; + x[7]=0x55; + + return doc_write_oob(mtd, to, 8, &dummy, x); + } + + return 0; +} + +static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, + size_t * retlen, u_char * buf) +{ + struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv; + int len256 = 0; + unsigned long docptr; + struct Nand *mychip; + + docptr = this->virtadr; + + mychip = &this->chips[ofs >> this->chipshift]; + + if (this->curfloor != mychip->floor) { + DoC_SelectFloor(this, mychip->floor); + DoC_SelectChip(this, mychip->chip); + } else if (this->curchip != mychip->chip) { + DoC_SelectChip(this, mychip->chip); + } + this->curfloor = mychip->floor; + this->curchip = mychip->chip; + + /* update address for 2M x 8bit devices. OOB starts on the second */ + /* page to maintain compatibility with doc_read_ecc. */ + if (this->page256) { + if (!(ofs & 0x8)) + ofs += 0x100; + else + ofs -= 0x8; + } + + DoC_Command(this, NAND_CMD_READOOB, CDSN_CTRL_WP); + DoC_Address(this, ADDR_COLUMN_PAGE, ofs, CDSN_CTRL_WP, 0); + + /* treat crossing 8-byte OOB data for 2M x 8bit devices */ + /* Note: datasheet says it should automaticaly wrap to the */ + /* next OOB block, but it didn't work here. mf. */ + if (this->page256 && ofs + len > (ofs | 0x7) + 1) { + len256 = (ofs | 0x7) + 1 - ofs; + DoC_ReadBuf(this, buf, len256); + + DoC_Command(this, NAND_CMD_READOOB, CDSN_CTRL_WP); + DoC_Address(this, ADDR_COLUMN_PAGE, ofs & (~0x1ff), + CDSN_CTRL_WP, 0); + } + + DoC_ReadBuf(this, &buf[len256], len - len256); + + *retlen = len; + /* Reading the full OOB data drops us off of the end of the page, + * causing the flash device to go into busy mode, so we need + * to wait until ready 11.4.1 and Toshiba TC58256FT docs */ + return DoC_WaitReady(this); + +} + +static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, + size_t * retlen, const u_char * buf) +{ + struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv; + int len256 = 0; + unsigned long docptr = this->virtadr; + struct Nand *mychip = &this->chips[ofs >> this->chipshift]; + int dummy; + + // printk("doc_write_oob(%lx, %d): %2.2X %2.2X %2.2X %2.2X ... %2.2X %2.2X .. %2.2X %2.2X\n",(long)ofs, len, + // buf[0], buf[1], buf[2], buf[3], buf[8], buf[9], buf[14],buf[15]); + + /* Find the chip which is to be used and select it */ + if (this->curfloor != mychip->floor) { + DoC_SelectFloor(this, mychip->floor); + DoC_SelectChip(this, mychip->chip); + } else if (this->curchip != mychip->chip) { + DoC_SelectChip(this, mychip->chip); + } + this->curfloor = mychip->floor; + this->curchip = mychip->chip; + + /* disable the ECC engine */ + WriteDOC (DOC_ECC_RESET, docptr, ECCConf); + WriteDOC (DOC_ECC_DIS, docptr, ECCConf); + + /* Reset the chip, see Software Requirement 11.4 item 1. */ + DoC_Command(this, NAND_CMD_RESET, CDSN_CTRL_WP); + + /* issue the Read2 command to set the pointer to the Spare Data Area. */ + DoC_Command(this, NAND_CMD_READOOB, CDSN_CTRL_WP); + + /* update address for 2M x 8bit devices. OOB starts on the second */ + /* page to maintain compatibility with doc_read_ecc. */ + if (this->page256) { + if (!(ofs & 0x8)) + ofs += 0x100; + else + ofs -= 0x8; + } + + /* issue the Serial Data In command to initial the Page Program process */ + DoC_Command(this, NAND_CMD_SEQIN, 0); + DoC_Address(this, ADDR_COLUMN_PAGE, ofs, 0, 0); + + /* treat crossing 8-byte OOB data for 2M x 8bit devices */ + /* Note: datasheet says it should automaticaly wrap to the */ + /* next OOB block, but it didn't work here. mf. */ + if (this->page256 && ofs + len > (ofs | 0x7) + 1) { + len256 = (ofs | 0x7) + 1 - ofs; + DoC_WriteBuf(this, buf, len256); + + DoC_Command(this, NAND_CMD_PAGEPROG, 0); + DoC_Command(this, NAND_CMD_STATUS, 0); + /* DoC_WaitReady() is implicit in DoC_Command */ + + dummy = ReadDOC(docptr, CDSNSlowIO); + DoC_Delay(this, 2); + + if (ReadDOC_(docptr, this->ioreg) & 1) { + printk("Error programming oob data\n"); + /* There was an error */ + *retlen = 0; + return -EIO; + } + DoC_Command(this, NAND_CMD_SEQIN, 0); + DoC_Address(this, ADDR_COLUMN_PAGE, ofs & (~0x1ff), 0, 0); + } + + DoC_WriteBuf(this, &buf[len256], len - len256); + + DoC_Command(this, NAND_CMD_PAGEPROG, 0); + DoC_Command(this, NAND_CMD_STATUS, 0); + /* DoC_WaitReady() is implicit in DoC_Command */ + + dummy = ReadDOC(docptr, CDSNSlowIO); + DoC_Delay(this, 2); + + if (ReadDOC_(docptr, this->ioreg) & 1) { + printk("Error programming oob data\n"); + /* There was an error */ + *retlen = 0; + return -EIO; + } + + *retlen = len; + return 0; + +} + +int doc_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv; + __u32 ofs = instr->addr; + __u32 len = instr->len; + unsigned long docptr; + struct Nand *mychip; + + if (len != mtd->erasesize) + printk(KERN_WARNING "Erase not right size (%x != %x)n", + len, mtd->erasesize); + + docptr = this->virtadr; + + mychip = &this->chips[ofs >> this->chipshift]; + + if (this->curfloor != mychip->floor) { + DoC_SelectFloor(this, mychip->floor); + DoC_SelectChip(this, mychip->chip); + } else if (this->curchip != mychip->chip) { + DoC_SelectChip(this, mychip->chip); + } + this->curfloor = mychip->floor; + this->curchip = mychip->chip; + + instr->state = MTD_ERASE_PENDING; + + DoC_Command(this, NAND_CMD_ERASE1, 0); + DoC_Address(this, ADDR_PAGE, ofs, 0, 0); + DoC_Command(this, NAND_CMD_ERASE2, 0); + + instr->state = MTD_ERASING; + + DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP); + + if (ReadDOC_(docptr, this->ioreg) & 1) { + printk("Error writing\n"); + /* There was an error */ + instr->state = MTD_ERASE_FAILED; + } else + instr->state = MTD_ERASE_DONE; + + if (instr->callback) + instr->callback(instr); + + return 0; +} + + +/**************************************************************************** + * + * Module stuff + * + ****************************************************************************/ + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define cleanup_doc2000 cleanup_module +#define init_doc2000 init_module +#endif + +int __init init_doc2000(void) +{ + inter_module_register(im_name, THIS_MODULE, &DoC2k_init); + return 0; +} + +static void __exit cleanup_doc2000(void) +{ + struct mtd_info *mtd; + struct DiskOnChip *this; + + while ((mtd = doc2klist)) { + this = (struct DiskOnChip *) mtd->priv; + doc2klist = this->nextdoc; + + del_mtd_device(mtd); + + iounmap((void *) this->virtadr); + kfree(this->chips); + kfree(mtd); + } + inter_module_unregister(im_name); +} + +module_exit(cleanup_doc2000); +module_init(init_doc2000); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/devices/doc2001.c linux/drivers/mtd/devices/doc2001.c --- v2.4.5/linux/drivers/mtd/devices/doc2001.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/devices/doc2001.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,883 @@ + +/* + * Linux driver for Disk-On-Chip Millennium + * (c) 1999 Machine Vision Holdings, Inc. + * (c) 1999, 2000 David Woodhouse + * + * $Id: doc2001.c,v 1.34 2001/06/02 14:30:43 dwmw2 Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* #define ECC_DEBUG */ + +/* I have no idea why some DoC chips can not use memcop_form|to_io(). + * This may be due to the different revisions of the ASIC controller built-in or + * simplily a QA/Bug issue. Who knows ?? If you have trouble, please uncomment + * this:*/ +#undef USE_MEMCPY + +static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf); +static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf); +static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf, u_char *eccbuf); +static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf, u_char *eccbuf); +static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, + size_t *retlen, u_char *buf); +static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, + size_t *retlen, const u_char *buf); +static int doc_erase (struct mtd_info *mtd, struct erase_info *instr); + +static struct mtd_info *docmillist = NULL; + +/* Perform the required delay cycles by reading from the NOP register */ +static void DoC_Delay(unsigned long docptr, unsigned short cycles) +{ + volatile char dummy; + int i; + + for (i = 0; i < cycles; i++) + dummy = ReadDOC(docptr, NOP); +} + +/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */ +static int _DoC_WaitReady(unsigned long docptr) +{ + unsigned short c = 0xffff; + + DEBUG(MTD_DEBUG_LEVEL3, + "_DoC_WaitReady called for out-of-line wait\n"); + + /* Out-of-line routine to wait for chip response */ + while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B) && --c) + ; + + if (c == 0) + DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n"); + + return (c == 0); +} + +static inline int DoC_WaitReady(unsigned long docptr) +{ + /* This is inline, to optimise the common case, where it's ready instantly */ + int ret = 0; + + /* 4 read form NOP register should be issued in prior to the read from CDSNControl + see Software Requirement 11.4 item 2. */ + DoC_Delay(docptr, 4); + + if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) + /* Call the out-of-line routine to wait */ + ret = _DoC_WaitReady(docptr); + + /* issue 2 read from NOP register after reading from CDSNControl register + see Software Requirement 11.4 item 2. */ + DoC_Delay(docptr, 2); + + return ret; +} + +/* DoC_Command: Send a flash command to the flash chip through the CDSN IO register + with the internal pipeline. Each of 4 delay cycles (read from the NOP register) is + required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */ + +static inline void DoC_Command(unsigned long docptr, unsigned char command, + unsigned char xtraflags) +{ + /* Assert the CLE (Command Latch Enable) line to the flash chip */ + WriteDOC(xtraflags | CDSN_CTRL_CLE | CDSN_CTRL_CE, docptr, CDSNControl); + DoC_Delay(docptr, 4); + + /* Send the command */ + WriteDOC(command, docptr, Mil_CDSN_IO); + WriteDOC(0x00, docptr, WritePipeTerm); + + /* Lower the CLE line */ + WriteDOC(xtraflags | CDSN_CTRL_CE, docptr, CDSNControl); + DoC_Delay(docptr, 4); +} + +/* DoC_Address: Set the current address for the flash chip through the CDSN IO register + with the internal pipeline. Each of 4 delay cycles (read from the NOP register) is + required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */ + +static inline void DoC_Address(unsigned long docptr, int numbytes, unsigned long ofs, + unsigned char xtraflags1, unsigned char xtraflags2) +{ + /* Assert the ALE (Address Latch Enable) line to the flash chip */ + WriteDOC(xtraflags1 | CDSN_CTRL_ALE | CDSN_CTRL_CE, docptr, CDSNControl); + DoC_Delay(docptr, 4); + + /* Send the address */ + switch (numbytes) + { + case 1: + /* Send single byte, bits 0-7. */ + WriteDOC(ofs & 0xff, docptr, Mil_CDSN_IO); + WriteDOC(0x00, docptr, WritePipeTerm); + break; + case 2: + /* Send bits 9-16 followed by 17-23 */ + WriteDOC((ofs >> 9) & 0xff, docptr, Mil_CDSN_IO); + WriteDOC((ofs >> 17) & 0xff, docptr, Mil_CDSN_IO); + WriteDOC(0x00, docptr, WritePipeTerm); + break; + case 3: + /* Send 0-7, 9-16, then 17-23 */ + WriteDOC(ofs & 0xff, docptr, Mil_CDSN_IO); + WriteDOC((ofs >> 9) & 0xff, docptr, Mil_CDSN_IO); + WriteDOC((ofs >> 17) & 0xff, docptr, Mil_CDSN_IO); + WriteDOC(0x00, docptr, WritePipeTerm); + break; + default: + return; + } + + /* Lower the ALE line */ + WriteDOC(xtraflags1 | xtraflags2 | CDSN_CTRL_CE, docptr, CDSNControl); + DoC_Delay(docptr, 4); +} + +/* DoC_SelectChip: Select a given flash chip within the current floor */ +static int DoC_SelectChip(unsigned long docptr, int chip) +{ + /* Select the individual flash chip requested */ + WriteDOC(chip, docptr, CDSNDeviceSelect); + DoC_Delay(docptr, 4); + + /* Wait for it to be ready */ + return DoC_WaitReady(docptr); +} + +/* DoC_SelectFloor: Select a given floor (bank of flash chips) */ +static int DoC_SelectFloor(unsigned long docptr, int floor) +{ + /* Select the floor (bank) of chips required */ + WriteDOC(floor, docptr, FloorSelect); + + /* Wait for the chip to be ready */ + return DoC_WaitReady(docptr); +} + +/* DoC_IdentChip: Identify a given NAND chip given {floor,chip} */ +static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip) +{ + int mfr, id, i; + volatile char dummy; + + /* Page in the required floor/chip + FIXME: is this supported by Millennium ?? */ + DoC_SelectFloor(doc->virtadr, floor); + DoC_SelectChip(doc->virtadr, chip); + + /* Reset the chip, see Software Requirement 11.4 item 1. */ + DoC_Command(doc->virtadr, NAND_CMD_RESET, CDSN_CTRL_WP); + DoC_WaitReady(doc->virtadr); + + /* Read the NAND chip ID: 1. Send ReadID command */ + DoC_Command(doc->virtadr, NAND_CMD_READID, CDSN_CTRL_WP); + + /* Read the NAND chip ID: 2. Send address byte zero */ + DoC_Address(doc->virtadr, 1, 0x00, CDSN_CTRL_WP, 0x00); + + /* Read the manufacturer and device id codes of the flash device through + CDSN IO register see Software Requirement 11.4 item 5.*/ + dummy = ReadDOC(doc->virtadr, ReadPipeInit); + DoC_Delay(doc->virtadr, 2); + mfr = ReadDOC(doc->virtadr, Mil_CDSN_IO); + + DoC_Delay(doc->virtadr, 2); + id = ReadDOC(doc->virtadr, Mil_CDSN_IO); + dummy = ReadDOC(doc->virtadr, LastDataRead); + + /* No response - return failure */ + if (mfr == 0xff || mfr == 0) + return 0; + + /* FIXME: to deal with multi-flash on multi-Millennium case more carefully */ + for (i = 0; nand_flash_ids[i].name != NULL; i++) { + if (mfr == nand_flash_ids[i].manufacture_id && + id == nand_flash_ids[i].model_id) { + printk(KERN_INFO "Flash chip found: Manufacturer ID: %2.2X, " + "Chip ID: %2.2X (%s)\n", + mfr, id, nand_flash_ids[i].name); + doc->mfr = mfr; + doc->id = id; + doc->chipshift = nand_flash_ids[i].chipshift; + break; + } + } + + if (nand_flash_ids[i].name == NULL) + return 0; + else + return 1; +} + +/* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */ +static void DoC_ScanChips(struct DiskOnChip *this) +{ + int floor, chip; + int numchips[MAX_FLOORS_MIL]; + int ret; + + this->numchips = 0; + this->mfr = 0; + this->id = 0; + + /* For each floor, find the number of valid chips it contains */ + for (floor = 0,ret = 1; floor < MAX_FLOORS_MIL; floor++) { + numchips[floor] = 0; + for (chip = 0; chip < MAX_CHIPS_MIL && ret != 0; chip++) { + ret = DoC_IdentChip(this, floor, chip); + if (ret) { + numchips[floor]++; + this->numchips++; + } + } + } + /* If there are none at all that we recognise, bail */ + if (!this->numchips) { + printk("No flash chips recognised.\n"); + return; + } + + /* Allocate an array to hold the information for each chip */ + this->chips = kmalloc(sizeof(struct Nand) * this->numchips, GFP_KERNEL); + if (!this->chips){ + printk("No memory for allocating chip info structures\n"); + return; + } + + /* Fill out the chip array with {floor, chipno} for each + * detected chip in the device. */ + for (floor = 0, ret = 0; floor < MAX_FLOORS_MIL; floor++) { + for (chip = 0 ; chip < numchips[floor] ; chip++) { + this->chips[ret].floor = floor; + this->chips[ret].chip = chip; + this->chips[ret].curadr = 0; + this->chips[ret].curmode = 0x50; + ret++; + } + } + + /* Calculate and print the total size of the device */ + this->totlen = this->numchips * (1 << this->chipshift); + printk(KERN_INFO "%d flash chips found. Total DiskOnChip size: %ld MiB\n", + this->numchips ,this->totlen >> 20); +} + +static int DoCMil_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2) +{ + int tmp1, tmp2, retval; + + if (doc1->physadr == doc2->physadr) + return 1; + + /* Use the alias resolution register which was set aside for this + * purpose. If it's value is the same on both chips, they might + * be the same chip, and we write to one and check for a change in + * the other. It's unclear if this register is usuable in the + * DoC 2000 (it's in the Millenium docs), but it seems to work. */ + tmp1 = ReadDOC(doc1->virtadr, AliasResolution); + tmp2 = ReadDOC(doc2->virtadr, AliasResolution); + if (tmp1 != tmp2) + return 0; + + WriteDOC((tmp1+1) % 0xff, doc1->virtadr, AliasResolution); + tmp2 = ReadDOC(doc2->virtadr, AliasResolution); + if (tmp2 == (tmp1+1) % 0xff) + retval = 1; + else + retval = 0; + + /* Restore register contents. May not be necessary, but do it just to + * be safe. */ + WriteDOC(tmp1, doc1->virtadr, AliasResolution); + + return retval; +} + +static const char im_name[] = "DoCMil_init"; + +/* This routine is made available to other mtd code via + * inter_module_register. It must only be accessed through + * inter_module_get which will bump the use count of this module. The + * addresses passed back in mtd are valid as long as the use count of + * this module is non-zero, i.e. between inter_module_get and + * inter_module_put. Keith Owens 29 Oct 2000. + */ +static void DoCMil_init(struct mtd_info *mtd) +{ + struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; + struct DiskOnChip *old = NULL; + + /* We must avoid being called twice for the same device. */ + if (docmillist) + old = (struct DiskOnChip *)docmillist->priv; + + while (old) { + if (DoCMil_is_alias(this, old)) { + printk(KERN_NOTICE "Ignoring DiskOnChip Millennium at " + "0x%lX - already configured\n", this->physadr); + iounmap((void *)this->virtadr); + kfree(mtd); + return; + } + if (old->nextdoc) + old = (struct DiskOnChip *)old->nextdoc->priv; + else + old = NULL; + } + + mtd->name = "DiskOnChip Millennium"; + printk(KERN_NOTICE "DiskOnChip Millennium found at address 0x%lX\n", + this->physadr); + + mtd->type = MTD_NANDFLASH; + mtd->flags = MTD_CAP_NANDFLASH; + mtd->size = 0; + + /* FIXME: erase size is not always 8kB */ + mtd->erasesize = 0x2000; + + mtd->oobblock = 512; + mtd->oobsize = 16; + mtd->module = THIS_MODULE; + mtd->erase = doc_erase; + mtd->point = NULL; + mtd->unpoint = NULL; + mtd->read = doc_read; + mtd->write = doc_write; + mtd->read_ecc = doc_read_ecc; + mtd->write_ecc = doc_write_ecc; + mtd->read_oob = doc_read_oob; + mtd->write_oob = doc_write_oob; + mtd->sync = NULL; + + this->totlen = 0; + this->numchips = 0; + this->curfloor = -1; + this->curchip = -1; + + /* Ident all the chips present. */ + DoC_ScanChips(this); + + if (!this->totlen) { + kfree(mtd); + iounmap((void *)this->virtadr); + } else { + this->nextdoc = docmillist; + docmillist = mtd; + mtd->size = this->totlen; + add_mtd_device(mtd); + return; + } +} + +static int doc_read (struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + /* Just a special case of doc_read_ecc */ + return doc_read_ecc(mtd, from, len, retlen, buf, NULL); +} + +static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf, u_char *eccbuf) +{ + int i, ret; + volatile char dummy; + unsigned char syndrome[6]; + struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; + unsigned long docptr = this->virtadr; + struct Nand *mychip = &this->chips[from >> (this->chipshift)]; + + /* Don't allow read past end of device */ + if (from >= this->totlen) + return -EINVAL; + + /* Don't allow a single read to cross a 512-byte block boundary */ + if (from + len > ((from | 0x1ff) + 1)) + len = ((from | 0x1ff) + 1) - from; + + /* Find the chip which is to be used and select it */ + if (this->curfloor != mychip->floor) { + DoC_SelectFloor(docptr, mychip->floor); + DoC_SelectChip(docptr, mychip->chip); + } else if (this->curchip != mychip->chip) { + DoC_SelectChip(docptr, mychip->chip); + } + this->curfloor = mychip->floor; + this->curchip = mychip->chip; + + /* issue the Read0 or Read1 command depend on which half of the page + we are accessing. Polling the Flash Ready bit after issue 3 bytes + address in Sequence Read Mode, see Software Requirement 11.4 item 1.*/ + DoC_Command(docptr, (from >> 8) & 1, CDSN_CTRL_WP); + DoC_Address(docptr, 3, from, CDSN_CTRL_WP, 0x00); + DoC_WaitReady(docptr); + + if (eccbuf) { + /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/ + WriteDOC (DOC_ECC_RESET, docptr, ECCConf); + WriteDOC (DOC_ECC_EN, docptr, ECCConf); + } else { + /* disable the ECC engine */ + WriteDOC (DOC_ECC_RESET, docptr, ECCConf); + WriteDOC (DOC_ECC_DIS, docptr, ECCConf); + } + + /* Read the data via the internal pipeline through CDSN IO register, + see Pipelined Read Operations 11.3 */ + dummy = ReadDOC(docptr, ReadPipeInit); +#ifndef USE_MEMCPY + for (i = 0; i < len-1; i++) { + /* N.B. you have to increase the source address in this way or the + ECC logic will not work properly */ + buf[i] = ReadDOC(docptr, Mil_CDSN_IO + (i & 0xff)); + } +#else + memcpy_fromio(buf, docptr + DoC_Mil_CDSN_IO, len - 1); +#endif + buf[len - 1] = ReadDOC(docptr, LastDataRead); + + /* Let the caller know we completed it */ + *retlen = len; + ret = 0; + + if (eccbuf) { + /* Read the ECC data from Spare Data Area, + see Reed-Solomon EDC/ECC 11.1 */ + dummy = ReadDOC(docptr, ReadPipeInit); +#ifndef USE_MEMCPY + for (i = 0; i < 5; i++) { + /* N.B. you have to increase the source address in this way or the + ECC logic will not work properly */ + eccbuf[i] = ReadDOC(docptr, Mil_CDSN_IO + i); + } +#else + memcpy_fromio(eccbuf, docptr + DoC_Mil_CDSN_IO, 5); +#endif + eccbuf[5] = ReadDOC(docptr, LastDataRead); + + /* Flush the pipeline */ + dummy = ReadDOC(docptr, ECCConf); + dummy = ReadDOC(docptr, ECCConf); + + /* Check the ECC Status */ + if (ReadDOC(docptr, ECCConf) & 0x80) { + int nb_errors; + /* There was an ECC error */ +#ifdef ECC_DEBUG + printk("DiskOnChip ECC Error: Read at %lx\n", (long)from); +#endif + /* Read the ECC syndrom through the DiskOnChip ECC logic. + These syndrome will be all ZERO when there is no error */ + for (i = 0; i < 6; i++) { + syndrome[i] = ReadDOC(docptr, ECCSyndrome0 + i); + } + nb_errors = doc_decode_ecc(buf, syndrome); +#ifdef ECC_DEBUG + printk("ECC Errors corrected: %x\n", nb_errors); +#endif + if (nb_errors < 0) { + /* We return error, but have actually done the read. Not that + this can be told to user-space, via sys_read(), but at least + MTD-aware stuff can know about it by checking *retlen */ + ret = -EIO; + } + } + +#ifdef PSYCHO_DEBUG + printk("ECC DATA at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", + (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], + eccbuf[4], eccbuf[5]); +#endif + + /* disable the ECC engine */ + WriteDOC(DOC_ECC_DIS, docptr , ECCConf); + } + + return ret; +} + +static int doc_write (struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + char eccbuf[6]; + return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf); +} + +static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf, u_char *eccbuf) +{ + int i,ret = 0; + volatile char dummy; + struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; + unsigned long docptr = this->virtadr; + struct Nand *mychip = &this->chips[to >> (this->chipshift)]; + + /* Don't allow write past end of device */ + if (to >= this->totlen) + return -EINVAL; + +#if 0 + /* Don't allow a single write to cross a 512-byte block boundary */ + if (to + len > ( (to | 0x1ff) + 1)) + len = ((to | 0x1ff) + 1) - to; +#else + /* Don't allow writes which aren't exactly one block */ + if (to & 0x1ff || len != 0x200) + return -EINVAL; +#endif + + /* Find the chip which is to be used and select it */ + if (this->curfloor != mychip->floor) { + DoC_SelectFloor(docptr, mychip->floor); + DoC_SelectChip(docptr, mychip->chip); + } else if (this->curchip != mychip->chip) { + DoC_SelectChip(docptr, mychip->chip); + } + this->curfloor = mychip->floor; + this->curchip = mychip->chip; + + /* Reset the chip, see Software Requirement 11.4 item 1. */ + DoC_Command(docptr, NAND_CMD_RESET, 0x00); + DoC_WaitReady(docptr); + /* Set device to main plane of flash */ + DoC_Command(docptr, NAND_CMD_READ0, 0x00); + + /* issue the Serial Data In command to initial the Page Program process */ + DoC_Command(docptr, NAND_CMD_SEQIN, 0x00); + DoC_Address(docptr, 3, to, 0x00, 0x00); + DoC_WaitReady(docptr); + + if (eccbuf) { + /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/ + WriteDOC (DOC_ECC_RESET, docptr, ECCConf); + WriteDOC (DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf); + } else { + /* disable the ECC engine */ + WriteDOC (DOC_ECC_RESET, docptr, ECCConf); + WriteDOC (DOC_ECC_DIS, docptr, ECCConf); + } + + /* Write the data via the internal pipeline through CDSN IO register, + see Pipelined Write Operations 11.2 */ +#ifndef USE_MEMCPY + for (i = 0; i < len; i++) { + /* N.B. you have to increase the source address in this way or the + ECC logic will not work properly */ + WriteDOC(buf[i], docptr, Mil_CDSN_IO + i); + } +#else + memcpy_toio(docptr + DoC_Mil_CDSN_IO, buf, len); +#endif + WriteDOC(0x00, docptr, WritePipeTerm); + + if (eccbuf) { + /* Write ECC data to flash, the ECC info is generated by the DiskOnChip ECC logic + see Reed-Solomon EDC/ECC 11.1 */ + WriteDOC(0, docptr, NOP); + WriteDOC(0, docptr, NOP); + WriteDOC(0, docptr, NOP); + + /* Read the ECC data through the DiskOnChip ECC logic */ + for (i = 0; i < 6; i++) { + eccbuf[i] = ReadDOC(docptr, ECCSyndrome0 + i); + } + + /* ignore the ECC engine */ + WriteDOC(DOC_ECC_DIS, docptr , ECCConf); + +#ifndef USE_MEMCPY + /* Write the ECC data to flash */ + for (i = 0; i < 6; i++) { + /* N.B. you have to increase the source address in this way or the + ECC logic will not work properly */ + WriteDOC(eccbuf[i], docptr, Mil_CDSN_IO + i); + } +#else + memcpy_toio(docptr + DoC_Mil_CDSN_IO, eccbuf, 6); +#endif + + /* write the block status BLOCK_USED (0x5555) at the end of ECC data + FIXME: this is only a hack for programming the IPL area for LinuxBIOS + and should be replace with proper codes in user space utilities */ + WriteDOC(0x55, docptr, Mil_CDSN_IO); + WriteDOC(0x55, docptr, Mil_CDSN_IO + 1); + + WriteDOC(0x00, docptr, WritePipeTerm); + +#ifdef PSYCHO_DEBUG + printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", + (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], + eccbuf[4], eccbuf[5]); +#endif + } + + /* Commit the Page Program command and wait for ready + see Software Requirement 11.4 item 1.*/ + DoC_Command(docptr, NAND_CMD_PAGEPROG, 0x00); + DoC_WaitReady(docptr); + + /* Read the status of the flash device through CDSN IO register + see Software Requirement 11.4 item 5.*/ + DoC_Command(docptr, NAND_CMD_STATUS, CDSN_CTRL_WP); + dummy = ReadDOC(docptr, ReadPipeInit); + DoC_Delay(docptr, 2); + if (ReadDOC(docptr, Mil_CDSN_IO) & 1) { + printk("Error programming flash\n"); + /* Error in programming + FIXME: implement Bad Block Replacement (in nftl.c ??) */ + *retlen = 0; + ret = -EIO; + } + dummy = ReadDOC(docptr, LastDataRead); + + /* Let the caller know we completed it */ + *retlen = len; + + return ret; +} + +static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, + size_t *retlen, u_char *buf) +{ +#ifndef USE_MEMCPY + int i; +#endif + volatile char dummy; + struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; + unsigned long docptr = this->virtadr; + struct Nand *mychip = &this->chips[ofs >> this->chipshift]; + + /* Find the chip which is to be used and select it */ + if (this->curfloor != mychip->floor) { + DoC_SelectFloor(docptr, mychip->floor); + DoC_SelectChip(docptr, mychip->chip); + } else if (this->curchip != mychip->chip) { + DoC_SelectChip(docptr, mychip->chip); + } + this->curfloor = mychip->floor; + this->curchip = mychip->chip; + + /* disable the ECC engine */ + WriteDOC (DOC_ECC_RESET, docptr, ECCConf); + WriteDOC (DOC_ECC_DIS, docptr, ECCConf); + + /* issue the Read2 command to set the pointer to the Spare Data Area. + Polling the Flash Ready bit after issue 3 bytes address in + Sequence Read Mode, see Software Requirement 11.4 item 1.*/ + DoC_Command(docptr, NAND_CMD_READOOB, CDSN_CTRL_WP); + DoC_Address(docptr, 3, ofs, CDSN_CTRL_WP, 0x00); + DoC_WaitReady(docptr); + + /* Read the data out via the internal pipeline through CDSN IO register, + see Pipelined Read Operations 11.3 */ + dummy = ReadDOC(docptr, ReadPipeInit); +#ifndef USE_MEMCPY + for (i = 0; i < len-1; i++) { + /* N.B. you have to increase the source address in this way or the + ECC logic will not work properly */ + buf[i] = ReadDOC(docptr, Mil_CDSN_IO + i); + } +#else + memcpy_fromio(buf, docptr + DoC_Mil_CDSN_IO, len - 1); +#endif + buf[len - 1] = ReadDOC(docptr, LastDataRead); + + *retlen = len; + + return 0; +} + +static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, + size_t *retlen, const u_char *buf) +{ +#ifndef USE_MEMCPY + int i; +#endif + volatile char dummy; + int ret = 0; + struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; + unsigned long docptr = this->virtadr; + struct Nand *mychip = &this->chips[ofs >> this->chipshift]; + + /* Find the chip which is to be used and select it */ + if (this->curfloor != mychip->floor) { + DoC_SelectFloor(docptr, mychip->floor); + DoC_SelectChip(docptr, mychip->chip); + } else if (this->curchip != mychip->chip) { + DoC_SelectChip(docptr, mychip->chip); + } + this->curfloor = mychip->floor; + this->curchip = mychip->chip; + + /* disable the ECC engine */ + WriteDOC (DOC_ECC_RESET, docptr, ECCConf); + WriteDOC (DOC_ECC_DIS, docptr, ECCConf); + + /* Reset the chip, see Software Requirement 11.4 item 1. */ + DoC_Command(docptr, NAND_CMD_RESET, CDSN_CTRL_WP); + DoC_WaitReady(docptr); + /* issue the Read2 command to set the pointer to the Spare Data Area. */ + DoC_Command(docptr, NAND_CMD_READOOB, CDSN_CTRL_WP); + + /* issue the Serial Data In command to initial the Page Program process */ + DoC_Command(docptr, NAND_CMD_SEQIN, 0x00); + DoC_Address(docptr, 3, ofs, 0x00, 0x00); + + /* Write the data via the internal pipeline through CDSN IO register, + see Pipelined Write Operations 11.2 */ +#ifndef USE_MEMCPY + for (i = 0; i < len; i++) { + /* N.B. you have to increase the source address in this way or the + ECC logic will not work properly */ + WriteDOC(buf[i], docptr, Mil_CDSN_IO + i); + } +#else + memcpy_toio(docptr + DoC_Mil_CDSN_IO, buf, len); +#endif + WriteDOC(0x00, docptr, WritePipeTerm); + + /* Commit the Page Program command and wait for ready + see Software Requirement 11.4 item 1.*/ + DoC_Command(docptr, NAND_CMD_PAGEPROG, 0x00); + DoC_WaitReady(docptr); + + /* Read the status of the flash device through CDSN IO register + see Software Requirement 11.4 item 5.*/ + DoC_Command(docptr, NAND_CMD_STATUS, 0x00); + dummy = ReadDOC(docptr, ReadPipeInit); + DoC_Delay(docptr, 2); + if (ReadDOC(docptr, Mil_CDSN_IO) & 1) { + printk("Error programming oob data\n"); + /* FIXME: implement Bad Block Replacement (in nftl.c ??) */ + *retlen = 0; + ret = -EIO; + } + dummy = ReadDOC(docptr, LastDataRead); + + *retlen = len; + + return ret; +} + +int doc_erase (struct mtd_info *mtd, struct erase_info *instr) +{ + volatile char dummy; + struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; + __u32 ofs = instr->addr; + __u32 len = instr->len; + unsigned long docptr = this->virtadr; + struct Nand *mychip = &this->chips[ofs >> this->chipshift]; + + if (len != mtd->erasesize) + printk(KERN_WARNING "Erase not right size (%x != %x)n", + len, mtd->erasesize); + + /* Find the chip which is to be used and select it */ + if (this->curfloor != mychip->floor) { + DoC_SelectFloor(docptr, mychip->floor); + DoC_SelectChip(docptr, mychip->chip); + } else if (this->curchip != mychip->chip) { + DoC_SelectChip(docptr, mychip->chip); + } + this->curfloor = mychip->floor; + this->curchip = mychip->chip; + + instr->state = MTD_ERASE_PENDING; + + /* issue the Erase Setup command */ + DoC_Command(docptr, NAND_CMD_ERASE1, 0x00); + DoC_Address(docptr, 2, ofs, 0x00, 0x00); + + /* Commit the Erase Start command and wait for ready + see Software Requirement 11.4 item 1.*/ + DoC_Command(docptr, NAND_CMD_ERASE2, 0x00); + DoC_WaitReady(docptr); + + instr->state = MTD_ERASING; + + /* Read the status of the flash device through CDSN IO register + see Software Requirement 11.4 item 5. + FIXME: it seems that we are not wait long enough, some blocks are not + erased fully */ + DoC_Command(docptr, NAND_CMD_STATUS, CDSN_CTRL_WP); + dummy = ReadDOC(docptr, ReadPipeInit); + DoC_Delay(docptr, 2); + if (ReadDOC(docptr, Mil_CDSN_IO) & 1) { + printk("Error Erasing at 0x%x\n", ofs); + /* There was an error + FIXME: implement Bad Block Replacement (in nftl.c ??) */ + instr->state = MTD_ERASE_FAILED; + } else + instr->state = MTD_ERASE_DONE; + dummy = ReadDOC(docptr, LastDataRead); + + if (instr->callback) + instr->callback(instr); + + return 0; +} + +/**************************************************************************** + * + * Module stuff + * + ****************************************************************************/ + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define cleanup_doc2001 cleanup_module +#define init_doc2001 init_module +#endif + +int __init init_doc2001(void) +{ + inter_module_register(im_name, THIS_MODULE, &DoCMil_init); + return 0; +} + +static void __exit cleanup_doc2001(void) +{ + struct mtd_info *mtd; + struct DiskOnChip *this; + + while ((mtd=docmillist)) { + this = (struct DiskOnChip *)mtd->priv; + docmillist = this->nextdoc; + + del_mtd_device(mtd); + + iounmap((void *)this->virtadr); + kfree(this->chips); + kfree(mtd); + } + inter_module_unregister(im_name); +} + +module_exit(cleanup_doc2001); +module_init(init_doc2001); + + diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/devices/docecc.c linux/drivers/mtd/devices/docecc.c --- v2.4.5/linux/drivers/mtd/devices/docecc.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/devices/docecc.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,522 @@ +/* + * ECC algorithm for M-systems disk on chip. We use the excellent Reed + * Solmon code of Phil Karn (karn@ka9q.ampr.org) available under the + * GNU GPL License. The rest is simply to convert the disk on chip + * syndrom into a standard syndom. + * + * Author: Fabrice Bellard (fabrice.bellard@netgem.com) + * Copyright (C) 2000 Netgem S.A. + * + * $Id: docecc.c,v 1.1 2000/11/03 12:43:43 dwmw2 Exp $ + * + * 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 + +/* need to undef it (from asm/termbits.h) */ +#undef B0 + +#define MM 10 /* Symbol size in bits */ +#define KK (1023-4) /* Number of data symbols per block */ +#define B0 510 /* First root of generator polynomial, alpha form */ +#define PRIM 1 /* power of alpha used to generate roots of generator poly */ +#define NN ((1 << MM) - 1) + +typedef unsigned short dtype; + +/* 1+x^3+x^10 */ +static const int Pp[MM+1] = { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 }; + +/* This defines the type used to store an element of the Galois Field + * used by the code. Make sure this is something larger than a char if + * if anything larger than GF(256) is used. + * + * Note: unsigned char will work up to GF(256) but int seems to run + * faster on the Pentium. + */ +typedef int gf; + +/* No legal value in index form represents zero, so + * we need a special value for this purpose + */ +#define A0 (NN) + +/* Compute x % NN, where NN is 2**MM - 1, + * without a slow divide + */ +static inline gf +modnn(int x) +{ + while (x >= NN) { + x -= NN; + x = (x >> MM) + (x & NN); + } + return x; +} + +#define min(a,b) ((a) < (b) ? (a) : (b)) + +#define CLEAR(a,n) {\ +int ci;\ +for(ci=(n)-1;ci >=0;ci--)\ +(a)[ci] = 0;\ +} + +#define COPY(a,b,n) {\ +int ci;\ +for(ci=(n)-1;ci >=0;ci--)\ +(a)[ci] = (b)[ci];\ +} + +#define COPYDOWN(a,b,n) {\ +int ci;\ +for(ci=(n)-1;ci >=0;ci--)\ +(a)[ci] = (b)[ci];\ +} + +#define Ldec 1 + +/* generate GF(2**m) from the irreducible polynomial p(X) in Pp[0]..Pp[m] + lookup tables: index->polynomial form alpha_to[] contains j=alpha**i; + polynomial form -> index form index_of[j=alpha**i] = i + alpha=2 is the primitive element of GF(2**m) + HARI's COMMENT: (4/13/94) alpha_to[] can be used as follows: + Let @ represent the primitive element commonly called "alpha" that + is the root of the primitive polynomial p(x). Then in GF(2^m), for any + 0 <= i <= 2^m-2, + @^i = a(0) + a(1) @ + a(2) @^2 + ... + a(m-1) @^(m-1) + where the binary vector (a(0),a(1),a(2),...,a(m-1)) is the representation + of the integer "alpha_to[i]" with a(0) being the LSB and a(m-1) the MSB. Thus for + example the polynomial representation of @^5 would be given by the binary + representation of the integer "alpha_to[5]". + Similarily, index_of[] can be used as follows: + As above, let @ represent the primitive element of GF(2^m) that is + the root of the primitive polynomial p(x). In order to find the power + of @ (alpha) that has the polynomial representation + a(0) + a(1) @ + a(2) @^2 + ... + a(m-1) @^(m-1) + we consider the integer "i" whose binary representation with a(0) being LSB + and a(m-1) MSB is (a(0),a(1),...,a(m-1)) and locate the entry + "index_of[i]". Now, @^index_of[i] is that element whose polynomial + representation is (a(0),a(1),a(2),...,a(m-1)). + NOTE: + The element alpha_to[2^m-1] = 0 always signifying that the + representation of "@^infinity" = 0 is (0,0,0,...,0). + Similarily, the element index_of[0] = A0 always signifying + that the power of alpha which has the polynomial representation + (0,0,...,0) is "infinity". + +*/ + +static void +generate_gf(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1]) +{ + register int i, mask; + + mask = 1; + Alpha_to[MM] = 0; + for (i = 0; i < MM; i++) { + Alpha_to[i] = mask; + Index_of[Alpha_to[i]] = i; + /* If Pp[i] == 1 then, term @^i occurs in poly-repr of @^MM */ + if (Pp[i] != 0) + Alpha_to[MM] ^= mask; /* Bit-wise EXOR operation */ + mask <<= 1; /* single left-shift */ + } + Index_of[Alpha_to[MM]] = MM; + /* + * Have obtained poly-repr of @^MM. Poly-repr of @^(i+1) is given by + * poly-repr of @^i shifted left one-bit and accounting for any @^MM + * term that may occur when poly-repr of @^i is shifted. + */ + mask >>= 1; + for (i = MM + 1; i < NN; i++) { + if (Alpha_to[i - 1] >= mask) + Alpha_to[i] = Alpha_to[MM] ^ ((Alpha_to[i - 1] ^ mask) << 1); + else + Alpha_to[i] = Alpha_to[i - 1] << 1; + Index_of[Alpha_to[i]] = i; + } + Index_of[0] = A0; + Alpha_to[NN] = 0; +} + +/* + * Performs ERRORS+ERASURES decoding of RS codes. bb[] is the content + * of the feedback shift register after having processed the data and + * the ECC. + * + * Return number of symbols corrected, or -1 if codeword is illegal + * or uncorrectable. If eras_pos is non-null, the detected error locations + * are written back. NOTE! This array must be at least NN-KK elements long. + * The corrected data are written in eras_val[]. They must be xor with the data + * to retrieve the correct data : data[erase_pos[i]] ^= erase_val[i] . + * + * First "no_eras" erasures are declared by the calling program. Then, the + * maximum # of errors correctable is t_after_eras = floor((NN-KK-no_eras)/2). + * If the number of channel errors is not greater than "t_after_eras" the + * transmitted codeword will be recovered. Details of algorithm can be found + * in R. Blahut's "Theory ... of Error-Correcting Codes". + + * Warning: the eras_pos[] array must not contain duplicate entries; decoder failure + * will result. The decoder *could* check for this condition, but it would involve + * extra time on every decoding operation. + * */ +static int +eras_dec_rs(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1], + gf bb[NN - KK + 1], gf eras_val[NN-KK], int eras_pos[NN-KK], + int no_eras) +{ + int deg_lambda, el, deg_omega; + int i, j, r,k; + gf u,q,tmp,num1,num2,den,discr_r; + gf lambda[NN-KK + 1], s[NN-KK + 1]; /* Err+Eras Locator poly + * and syndrome poly */ + gf b[NN-KK + 1], t[NN-KK + 1], omega[NN-KK + 1]; + gf root[NN-KK], reg[NN-KK + 1], loc[NN-KK]; + int syn_error, count; + + syn_error = 0; + for(i=0;i 0) { + /* Init lambda to be the erasure locator polynomial */ + lambda[1] = Alpha_to[modnn(PRIM * eras_pos[0])]; + for (i = 1; i < no_eras; i++) { + u = modnn(PRIM*eras_pos[i]); + for (j = i+1; j > 0; j--) { + tmp = Index_of[lambda[j - 1]]; + if(tmp != A0) + lambda[j] ^= Alpha_to[modnn(u + tmp)]; + } + } +#if DEBUG >= 1 + /* Test code that verifies the erasure locator polynomial just constructed + Needed only for decoder debugging. */ + + /* find roots of the erasure location polynomial */ + for(i=1;i<=no_eras;i++) + reg[i] = Index_of[lambda[i]]; + count = 0; + for (i = 1,k=NN-Ldec; i <= NN; i++,k = modnn(NN+k-Ldec)) { + q = 1; + for (j = 1; j <= no_eras; j++) + if (reg[j] != A0) { + reg[j] = modnn(reg[j] + j); + q ^= Alpha_to[reg[j]]; + } + if (q != 0) + continue; + /* store root and error location number indices */ + root[count] = i; + loc[count] = k; + count++; + } + if (count != no_eras) { + printf("\n lambda(x) is WRONG\n"); + count = -1; + goto finish; + } +#if DEBUG >= 2 + printf("\n Erasure positions as determined by roots of Eras Loc Poly:\n"); + for (i = 0; i < count; i++) + printf("%d ", loc[i]); + printf("\n"); +#endif +#endif + } + for(i=0;i 0; j--){ + if (reg[j] != A0) { + reg[j] = modnn(reg[j] + j); + q ^= Alpha_to[reg[j]]; + } + } + if (q != 0) + continue; + /* store root (index-form) and error location number */ + root[count] = i; + loc[count] = k; + /* If we've already found max possible roots, + * abort the search to save time + */ + if(++count == deg_lambda) + break; + } + if (deg_lambda != count) { + /* + * deg(lambda) unequal to number of roots => uncorrectable + * error detected + */ + count = -1; + goto finish; + } + /* + * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo + * x**(NN-KK)). in index form. Also find deg(omega). + */ + deg_omega = 0; + for (i = 0; i < NN-KK;i++){ + tmp = 0; + j = (deg_lambda < i) ? deg_lambda : i; + for(;j >= 0; j--){ + if ((s[i + 1 - j] != A0) && (lambda[j] != A0)) + tmp ^= Alpha_to[modnn(s[i + 1 - j] + lambda[j])]; + } + if(tmp != 0) + deg_omega = i; + omega[i] = Index_of[tmp]; + } + omega[NN-KK] = A0; + + /* + * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 = + * inv(X(l))**(B0-1) and den = lambda_pr(inv(X(l))) all in poly-form + */ + for (j = count-1; j >=0; j--) { + num1 = 0; + for (i = deg_omega; i >= 0; i--) { + if (omega[i] != A0) + num1 ^= Alpha_to[modnn(omega[i] + i * root[j])]; + } + num2 = Alpha_to[modnn(root[j] * (B0 - 1) + NN)]; + den = 0; + + /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */ + for (i = min(deg_lambda,NN-KK-1) & ~1; i >= 0; i -=2) { + if(lambda[i+1] != A0) + den ^= Alpha_to[modnn(lambda[i+1] + i * root[j])]; + } + if (den == 0) { +#if DEBUG >= 1 + printf("\n ERROR: denominator = 0\n"); +#endif + /* Convert to dual- basis */ + count = -1; + goto finish; + } + /* Apply error to data */ + if (num1 != 0) { + eras_val[j] = Alpha_to[modnn(Index_of[num1] + Index_of[num2] + NN - Index_of[den])]; + } else { + eras_val[j] = 0; + } + } + finish: + for(i=0;i> 2) | ((ecc1[2] & 0x0f) << 6); + bb[2] = ((ecc1[2] & 0xf0) >> 4) | ((ecc1[3] & 0x3f) << 4); + bb[3] = ((ecc1[3] & 0xc0) >> 6) | ((ecc1[0] & 0xff) << 2); + + nb_errors = eras_dec_rs(Alpha_to, Index_of, bb, + error_val, error_pos, 0); + if (nb_errors <= 0) + goto the_end; + + /* correct the errors */ + for(i=0;i= NB_DATA && pos < KK) { + nb_errors = -1; + goto the_end; + } + if (pos < NB_DATA) { + /* extract bit position (MSB first) */ + pos = 10 * (NB_DATA - 1 - pos) - 6; + /* now correct the following 10 bits. At most two bytes + can be modified since pos is even */ + index = (pos >> 3) ^ 1; + bitpos = pos & 7; + if ((index >= 0 && index < SECTOR_SIZE) || + index == (SECTOR_SIZE + 1)) { + val = error_val[i] >> (2 + bitpos); + parity ^= val; + if (index < SECTOR_SIZE) + sector[index] ^= val; + } + index = ((pos >> 3) + 1) ^ 1; + bitpos = (bitpos + 10) & 7; + if (bitpos == 0) + bitpos = 8; + if ((index >= 0 && index < SECTOR_SIZE) || + index == (SECTOR_SIZE + 1)) { + val = error_val[i] << (8 - bitpos); + parity ^= val; + if (index < SECTOR_SIZE) + sector[index] ^= val; + } + } + } + + /* use parity to test extra errors */ + if ((parity & 0xff) != 0) + nb_errors = -1; + + the_end: + kfree(Alpha_to); + kfree(Index_of); + return nb_errors; +} + diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/devices/docprobe.c linux/drivers/mtd/devices/docprobe.c --- v2.4.5/linux/drivers/mtd/devices/docprobe.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/devices/docprobe.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,285 @@ + +/* Linux driver for Disk-On-Chip devices */ +/* Probe routines common to all DoC devices */ +/* (c) 1999 Machine Vision Holdings, Inc. */ +/* Author: David Woodhouse */ +/* $Id: docprobe.c,v 1.27 2001/06/03 19:06:09 dwmw2 Exp $ */ + + + +/* DOC_PASSIVE_PROBE: + In order to ensure that the BIOS checksum is correct at boot time, and + hence that the onboard BIOS extension gets executed, the DiskOnChip + goes into reset mode when it is read sequentially: all registers + return 0xff until the chip is woken up again by writing to the + DOCControl register. + + Unfortunately, this means that the probe for the DiskOnChip is unsafe, + because one of the first things it does is write to where it thinks + the DOCControl register should be - which may well be shared memory + for another device. I've had machines which lock up when this is + attempted. Hence the possibility to do a passive probe, which will fail + to detect a chip in reset mode, but is at least guaranteed not to lock + the machine. + + If you have this problem, uncomment the following line: +#define DOC_PASSIVE_PROBE +*/ + + +/* DOC_SINGLE_DRIVER: + Millennium driver has been merged into DOC2000 driver. + + The newly-merged driver doesn't appear to work for writing. It's the + same with the DiskOnChip 2000 and the Millennium. If you have a + Millennium and you want write support to work, remove the definition + of DOC_SINGLE_DRIVER below to use the old doc2001-specific driver. + + Otherwise, it's left on in the hope that it'll annoy someone with + a Millennium enough that they go through and work out what the + difference is :) +*/ +#define DOC_SINGLE_DRIVER + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* Where to look for the devices? */ +#ifndef CONFIG_MTD_DOCPROBE_ADDRESS +#define CONFIG_MTD_DOCPROBE_ADDRESS 0 +#endif + + +static unsigned long doc_config_location = CONFIG_MTD_DOCPROBE_ADDRESS; +MODULE_PARM(doc_config_location, "l"); + + +static unsigned long __initdata doc_locations[] = { +#if defined (__alpha__) || defined(__i386__) +#ifdef CONFIG_MTD_DOCPROBE_HIGH + 0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000, + 0xfffd0000, 0xfffd2000, 0xfffd4000, 0xfffd6000, + 0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000, + 0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000, + 0xfffe8000, 0xfffea000, 0xfffec000, 0xfffee000, +#else /* CONFIG_MTD_DOCPROBE_HIGH */ + 0xc8000, 0xca000, 0xcc000, 0xce000, + 0xd0000, 0xd2000, 0xd4000, 0xd6000, + 0xd8000, 0xda000, 0xdc000, 0xde000, + 0xe0000, 0xe2000, 0xe4000, 0xe6000, + 0xe8000, 0xea000, 0xec000, 0xee000, +#endif /* CONFIG_MTD_DOCPROBE_HIGH */ +#elif defined(__ppc__) + 0xe4000000, +#elif defined(CONFIG_MOMENCO_OCELOT) + 0x2f000000, +#else +#warning Unknown architecture for DiskOnChip. No default probe locations defined +#endif + 0 }; + +/* doccheck: Probe a given memory window to see if there's a DiskOnChip present */ + +static inline int __init doccheck(unsigned long potential, unsigned long physadr) +{ + unsigned long window=potential; + unsigned char tmp, ChipID; +#ifndef DOC_PASSIVE_PROBE + unsigned char tmp2; +#endif + + /* Routine copied from the Linux DOC driver */ + +#ifdef CONFIG_MTD_DOCPROBE_55AA + /* Check for 0x55 0xAA signature at beginning of window, + this is no longer true once we remove the IPL (for Millennium */ + if (ReadDOC(window, Sig1) != 0x55 || ReadDOC(window, Sig2) != 0xaa) + return 0; +#endif /* CONFIG_MTD_DOCPROBE_55AA */ + +#ifndef DOC_PASSIVE_PROBE + /* It's not possible to cleanly detect the DiskOnChip - the + * bootup procedure will put the device into reset mode, and + * it's not possible to talk to it without actually writing + * to the DOCControl register. So we store the current contents + * of the DOCControl register's location, in case we later decide + * that it's not a DiskOnChip, and want to put it back how we + * found it. + */ + tmp2 = ReadDOC(window, DOCControl); + + /* Reset the DiskOnChip ASIC */ + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, + window, DOCControl); + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, + window, DOCControl); + + /* Enable the DiskOnChip ASIC */ + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, + window, DOCControl); + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, + window, DOCControl); +#endif /* !DOC_PASSIVE_PROBE */ + + ChipID = ReadDOC(window, ChipID); + + switch (ChipID) { + case DOC_ChipID_Doc2k: + /* Check the TOGGLE bit in the ECC register */ + tmp = ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT; + if ((ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT) != tmp) + return ChipID; + break; + + case DOC_ChipID_DocMil: + /* Check the TOGGLE bit in the ECC register */ + tmp = ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT; + if ((ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT) != tmp) + return ChipID; + break; + + default: +#ifndef CONFIG_MTD_DOCPROBE_55AA + printk(KERN_WARNING "Possible DiskOnChip with unknown ChipID %2.2X found at 0x%lx\n", + ChipID, physadr); +#endif +#ifndef DOC_PASSIVE_PROBE + /* Put back the contents of the DOCControl register, in case it's not + * actually a DiskOnChip. + */ + WriteDOC(tmp2, window, DOCControl); +#endif + return 0; + } + + printk(KERN_WARNING "DiskOnChip failed TOGGLE test, dropping.\n"); + +#ifndef DOC_PASSIVE_PROBE + /* Put back the contents of the DOCControl register: it's not a DiskOnChip */ + WriteDOC(tmp2, window, DOCControl); +#endif + return 0; +} + + +static void __init DoC_Probe(unsigned long physadr) +{ + unsigned long docptr; + struct DiskOnChip *this; + struct mtd_info *mtd; + int ChipID; + char namebuf[15]; + char *name = namebuf; + char *im_funcname = NULL; + char *im_modname = NULL; + void (*initroutine)(struct mtd_info *) = NULL; + + docptr = (unsigned long)ioremap(physadr, DOC_IOREMAP_LEN); + + if (!docptr) + return; + + if ((ChipID = doccheck(docptr, physadr))) { + + mtd = kmalloc(sizeof(struct DiskOnChip) + sizeof(struct mtd_info), GFP_KERNEL); + + if (!mtd) { + printk("Cannot allocate memory for data structures. Dropping.\n"); + iounmap((void *)docptr); + return; + } + + this = (struct DiskOnChip *)(&mtd[1]); + + memset((char *)mtd,0, sizeof(struct mtd_info)); + memset((char *)this, 0, sizeof(struct DiskOnChip)); + + mtd->priv = this; + this->virtadr = docptr; + this->physadr = physadr; + this->ChipID = ChipID; + sprintf(namebuf, "with ChipID %2.2X", ChipID); + + switch(ChipID) { + case DOC_ChipID_Doc2k: + name="2000"; + im_funcname = "DoC2k_init"; + im_modname = "doc2000"; + break; + + case DOC_ChipID_DocMil: + name="Millennium"; +#ifdef DOC_SINGLE_DRIVER + im_funcname = "DoC2k_init"; + im_modname = "doc2000"; +#else + im_funcname = "DoCMil_init"; + im_modname = "doc2001"; +#endif /* DOC_SINGLE_DRIVER */ + break; + } + + if (im_funcname) + initroutine = inter_module_get_request(im_funcname, im_modname); + + if (initroutine) { + (*initroutine)(mtd); + inter_module_put(im_funcname); + return; + } + printk("Cannot find driver for DiskOnChip %s at 0x%lX\n", name, physadr); + } + iounmap((void *)docptr); +} + + +/**************************************************************************** + * + * Module stuff + * + ****************************************************************************/ + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define init_doc init_module +#endif + +int __init init_doc(void) +{ + int i; + + printk(KERN_NOTICE "M-Systems DiskOnChip driver. (C) 1999 Machine Vision Holdings, Inc.\n"); +#ifdef PRERELEASE + printk(KERN_INFO "$Id: docprobe.c,v 1.27 2001/06/03 19:06:09 dwmw2 Exp $\n"); +#endif + if (doc_config_location) { + printk("Using configured probe address 0x%lx\n", doc_config_location); + DoC_Probe(doc_config_location); + } else { + for (i=0; doc_locations[i]; i++) { + DoC_Probe(doc_locations[i]); + } + } + /* So it looks like we've been used and we get unloaded */ + MOD_INC_USE_COUNT; + MOD_DEC_USE_COUNT; + return 0; + +} + +module_init(init_doc); + diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/devices/mtdram.c linux/drivers/mtd/devices/mtdram.c --- v2.4.5/linux/drivers/mtd/devices/mtdram.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/devices/mtdram.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,178 @@ +/* + * mtdram - a test mtd device + * $Id: mtdram.c,v 1.24 2001/06/09 23:09:23 dwmw2 Exp $ + * Author: Alexander Larsson + * + * Copyright (c) 1999 Alexander Larsson + * + * This code is GPL + * + */ + +#include +#include +#include +#include +#include +#include + +#ifndef CONFIG_MTDRAM_ABS_POS + #define CONFIG_MTDRAM_ABS_POS 0 +#endif + +#if CONFIG_MTDRAM_ABS_POS > 0 + #include +#endif + +#ifdef MODULE +static unsigned long total_size = CONFIG_MTDRAM_TOTAL_SIZE; +static unsigned long erase_size = CONFIG_MTDRAM_ERASE_SIZE; +MODULE_PARM(total_size,"l"); +MODULE_PARM(erase_size,"l"); +#define MTDRAM_TOTAL_SIZE (total_size * 1024) +#define MTDRAM_ERASE_SIZE (erase_size * 1024) +#else +#define MTDRAM_TOTAL_SIZE (CONFIG_MTDRAM_TOTAL_SIZE * 1024) +#define MTDRAM_ERASE_SIZE (CONFIG_MTDRAM_ERASE_SIZE * 1024) +#endif + + +// We could store these in the mtd structure, but we only support 1 device.. +static struct mtd_info *mtd_info; + + +static int +ram_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + DEBUG(MTD_DEBUG_LEVEL2, "ram_erase(pos:%ld, len:%ld)\n", (long)instr->addr, (long)instr->len); + if (instr->addr + instr->len > mtd->size) { + DEBUG(MTD_DEBUG_LEVEL1, "ram_erase() out of bounds (%ld > %ld)\n", (long)(instr->addr + instr->len), (long)mtd->size); + return -EINVAL; + } + + memset((char *)mtd->priv + instr->addr, 0xff, instr->len); + + instr->state = MTD_ERASE_DONE; + + if (instr->callback) + (*(instr->callback))(instr); + return 0; +} + +static int ram_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf) +{ + if (from + len > mtd->size) + return -EINVAL; + + *mtdbuf = mtd->priv + from; + *retlen = len; + return 0; +} + +static void ram_unpoint (struct mtd_info *mtd, u_char *addr) +{ + DEBUG(MTD_DEBUG_LEVEL2, "ram_unpoint\n"); +} + +static int ram_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + DEBUG(MTD_DEBUG_LEVEL2, "ram_read(pos:%ld, len:%ld)\n", (long)from, (long)len); + if (from + len > mtd->size) { + DEBUG(MTD_DEBUG_LEVEL1, "ram_read() out of bounds (%ld > %ld)\n", (long)(from + len), (long)mtd->size); + return -EINVAL; + } + + memcpy(buf, mtd->priv + from, len); + + *retlen=len; + return 0; +} + +static int ram_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + DEBUG(MTD_DEBUG_LEVEL2, "ram_write(pos:%ld, len:%ld)\n", (long)to, (long)len); + if (to + len > mtd->size) { + DEBUG(MTD_DEBUG_LEVEL1, "ram_write() out of bounds (%ld > %ld)\n", (long)(to + len), (long)mtd->size); + return -EINVAL; + } + + memcpy ((char *)mtd->priv + to, buf, len); + + *retlen=len; + return 0; +} + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define init_mtdram init_module +#define cleanup_mtdram cleanup_module +#endif + +//static void __exit cleanup_mtdram(void) +mod_exit_t cleanup_mtdram(void) +{ + if (mtd_info) { + del_mtd_device(mtd_info); + if (mtd_info->priv) +#if CONFIG_MTDRAM_ABS_POS > 0 + iounmap(mtd_info->priv); +#else + vfree(mtd_info->priv); +#endif + kfree(mtd_info); + } +} + +mod_init_t init_mtdram(void) +{ + // Allocate some memory + mtd_info = (struct mtd_info *)kmalloc(sizeof(struct mtd_info), GFP_KERNEL); + if (!mtd_info) + return 0; + + memset(mtd_info, 0, sizeof(*mtd_info)); + + // Setup the MTD structure + mtd_info->name = "mtdram test device"; + mtd_info->type = MTD_RAM; + mtd_info->flags = MTD_CAP_RAM; + mtd_info->size = MTDRAM_TOTAL_SIZE; + mtd_info->erasesize = MTDRAM_ERASE_SIZE; +#if CONFIG_MTDRAM_ABS_POS > 0 + mtd_info->priv = ioremap(CONFIG_MTDRAM_ABS_POS, MTDRAM_TOTAL_SIZE); +#else + mtd_info->priv = vmalloc(MTDRAM_TOTAL_SIZE); +#endif + + if (!mtd_info->priv) { + DEBUG(MTD_DEBUG_LEVEL1, "Failed to vmalloc(/ioremap) memory region of size %ld (ABS_POS:%ld)\n", (long)MTDRAM_TOTAL_SIZE, (long)CONFIG_MTDRAM_ABS_POS); + kfree(mtd_info); + mtd_info = NULL; + return -ENOMEM; + } + memset(mtd_info->priv, 0xff, MTDRAM_TOTAL_SIZE); + + mtd_info->module = THIS_MODULE; + mtd_info->erase = ram_erase; + mtd_info->point = ram_point; + mtd_info->unpoint = ram_unpoint; + mtd_info->read = ram_read; + mtd_info->write = ram_write; + + if (add_mtd_device(mtd_info)) { +#if CONFIG_MTDRAM_ABS_POS > 0 + iounmap(mtd_info->priv); +#else + vfree(mtd_info->priv); +#endif + kfree(mtd_info); + mtd_info = NULL; + return -EIO; + } + + return 0; +} + +module_init(init_mtdram); +module_exit(cleanup_mtdram); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/devices/pmc551.c linux/drivers/mtd/devices/pmc551.c --- v2.4.5/linux/drivers/mtd/devices/pmc551.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/devices/pmc551.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,872 @@ +/* + * $Id: pmc551.c,v 1.17 2001/05/22 13:56:46 dwmw2 Exp $ + * + * PMC551 PCI Mezzanine Ram Device + * + * Author: + * Mark Ferrell + * Copyright 1999,2000 Nortel Networks + * + * License: + * As part of this driver was derived from the slram.c driver it + * falls under the same license, which is GNU General Public + * License v2 + * + * Description: + * This driver is intended to support the PMC551 PCI Ram device + * from Ramix Inc. The PMC551 is a PMC Mezzanine module for + * cPCI embedded systems. The device contains a single SROM + * that initially programs the V370PDC chipset onboard the + * device, and various banks of DRAM/SDRAM onboard. This driver + * implements this PCI Ram device as an MTD (Memory Technology + * Device) so that it can be used to hold a file system, or for + * added swap space in embedded systems. Since the memory on + * this board isn't as fast as main memory we do not try to hook + * it into main memory as that would simply reduce performance + * on the system. Using it as a block device allows us to use + * it as high speed swap or for a high speed disk device of some + * sort. Which becomes very useful on diskless systems in the + * embedded market I might add. + * + * Notes: + * Due to what I assume is more buggy SROM, the 64M PMC551 I + * have available claims that all 4 of it's DRAM banks have 64M + * of ram configured (making a grand total of 256M onboard). + * This is slightly annoying since the BAR0 size reflects the + * aperture size, not the dram size, and the V370PDC supplies no + * other method for memory size discovery. This problem is + * mostly only relevant when compiled as a module, as the + * unloading of the module with an aperture size smaller then + * the ram will cause the driver to detect the onboard memory + * size to be equal to the aperture size when the module is + * reloaded. Soooo, to help, the module supports an msize + * option to allow the specification of the onboard memory, and + * an asize option, to allow the specification of the aperture + * size. The aperture must be equal to or less then the memory + * size, the driver will correct this if you screw it up. This + * problem is not relevant for compiled in drivers as compiled + * in drivers only init once. + * + * Credits: + * Saeed Karamooz of Ramix INC. for the + * initial example code of how to initialize this device and for + * help with questions I had concerning operation of the device. + * + * Most of the MTD code for this driver was originally written + * for the slram.o module in the MTD drivers package which + * allows the mapping of system memory into an MTD device. + * Since the PMC551 memory module is accessed in the same + * fashion as system memory, the slram.c code became a very nice + * fit to the needs of this driver. All we added was PCI + * detection/initialization to the driver and automatically figure + * out the size via the PCI detection.o, later changes by Corey + * Minyard set up the card to utilize a 1M sliding apature. + * + * Corey Minyard + * * Modified driver to utilize a sliding aperture instead of + * mapping all memory into kernel space which turned out to + * be very wasteful. + * * Located a bug in the SROM's initialization sequence that + * made the memory unusable, added a fix to code to touch up + * the DRAM some. + * + * Bugs/FIXME's: + * * MUST fix the init function to not spin on a register + * waiting for it to set .. this does not safely handle busted + * devices that never reset the register correctly which will + * cause the system to hang w/ a reboot being the only chance at + * recover. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef CONFIG_PCI +#error Enable PCI in your kernel config +#endif + +#include +#include +#include + +#if LINUX_VERSION_CODE > 0x20300 +#define PCI_BASE_ADDRESS(dev) (dev->resource[0].start) +#else +#define PCI_BASE_ADDRESS(dev) (dev->base_address[0]) +#endif + +static struct mtd_info *pmc551list; + +static int pmc551_erase (struct mtd_info *mtd, struct erase_info *instr) +{ + struct mypriv *priv = mtd->priv; + u32 start_addr_highbits; + u32 end_addr_highbits; + u32 start_addr_lowbits; + u32 end_addr_lowbits; + unsigned long end; + + end = instr->addr + instr->len; + + /* Is it too much memory? The second check find if we wrap around + past the end of a u32. */ + if ((end > mtd->size) || (end < instr->addr)) { + return -EINVAL; + } + + start_addr_highbits = instr->addr & PMC551_ADDR_HIGH_MASK; + end_addr_highbits = end & PMC551_ADDR_HIGH_MASK; + start_addr_lowbits = instr->addr & PMC551_ADDR_LOW_MASK; + end_addr_lowbits = end & PMC551_ADDR_LOW_MASK; + + pci_write_config_dword ( priv->dev, + PMC551_PCI_MEM_MAP0, + (priv->mem_map0_base_val + | start_addr_highbits)); + if (start_addr_highbits == end_addr_highbits) { + /* The whole thing fits within one access, so just one shot + will do it. */ + memset(priv->start + start_addr_lowbits, + 0xff, + instr->len); + } else { + /* We have to do multiple writes to get all the data + written. */ + memset(priv->start + start_addr_lowbits, + 0xff, + priv->aperture_size - start_addr_lowbits); + start_addr_highbits += priv->aperture_size; + while (start_addr_highbits != end_addr_highbits) { + pci_write_config_dword ( priv->dev, + PMC551_PCI_MEM_MAP0, + (priv->mem_map0_base_val + | start_addr_highbits)); + memset(priv->start, + 0xff, + priv->aperture_size); + start_addr_highbits += priv->aperture_size; + } + priv->curr_mem_map0_val = (priv->mem_map0_base_val + | start_addr_highbits); + pci_write_config_dword ( priv->dev, + PMC551_PCI_MEM_MAP0, + priv->curr_mem_map0_val); + memset(priv->start, + 0xff, + end_addr_lowbits); + } + + instr->state = MTD_ERASE_DONE; + + if (instr->callback) { + (*(instr->callback))(instr); + } + + return 0; +} + + +static void pmc551_unpoint (struct mtd_info *mtd, u_char *addr) +{} + + +static int pmc551_read (struct mtd_info *mtd, + loff_t from, + size_t len, + size_t *retlen, + u_char *buf) +{ + struct mypriv *priv = (struct mypriv *)mtd->priv; + u32 start_addr_highbits; + u32 end_addr_highbits; + u32 start_addr_lowbits; + u32 end_addr_lowbits; + unsigned long end; + u_char *copyto = buf; + + + /* Is it past the end? */ + if (from > mtd->size) { + return -EINVAL; + } + + end = from + len; + start_addr_highbits = from & PMC551_ADDR_HIGH_MASK; + end_addr_highbits = end & PMC551_ADDR_HIGH_MASK; + start_addr_lowbits = from & PMC551_ADDR_LOW_MASK; + end_addr_lowbits = end & PMC551_ADDR_LOW_MASK; + + + /* Only rewrite the first value if it doesn't match our current + values. Most operations are on the same page as the previous + value, so this is a pretty good optimization. */ + if (priv->curr_mem_map0_val != + (priv->mem_map0_base_val | start_addr_highbits)) { + priv->curr_mem_map0_val = (priv->mem_map0_base_val + | start_addr_highbits); + pci_write_config_dword ( priv->dev, + PMC551_PCI_MEM_MAP0, + priv->curr_mem_map0_val); + } + + if (start_addr_highbits == end_addr_highbits) { + /* The whole thing fits within one access, so just one shot + will do it. */ + memcpy(copyto, + priv->start + start_addr_lowbits, + len); + copyto += len; + } else { + /* We have to do multiple writes to get all the data + written. */ + memcpy(copyto, + priv->start + start_addr_lowbits, + priv->aperture_size - start_addr_lowbits); + copyto += priv->aperture_size - start_addr_lowbits; + start_addr_highbits += priv->aperture_size; + while (start_addr_highbits != end_addr_highbits) { + pci_write_config_dword ( priv->dev, + PMC551_PCI_MEM_MAP0, + (priv->mem_map0_base_val + | start_addr_highbits)); + memcpy(copyto, + priv->start, + priv->aperture_size); + copyto += priv->aperture_size; + start_addr_highbits += priv->aperture_size; + if (start_addr_highbits >= mtd->size) { + /* Make sure we have the right value here. */ + priv->curr_mem_map0_val + = (priv->mem_map0_base_val + | start_addr_highbits); + goto out; + } + } + priv->curr_mem_map0_val = (priv->mem_map0_base_val + | start_addr_highbits); + pci_write_config_dword ( priv->dev, + PMC551_PCI_MEM_MAP0, + priv->curr_mem_map0_val); + memcpy(copyto, + priv->start, + end_addr_lowbits); + copyto += end_addr_lowbits; + } + +out: + *retlen = copyto - buf; + return 0; +} + +static int pmc551_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) +{ + struct mypriv *priv = (struct mypriv *)mtd->priv; + u32 start_addr_highbits; + u32 end_addr_highbits; + u32 start_addr_lowbits; + u32 end_addr_lowbits; + unsigned long end; + const u_char *copyfrom = buf; + + + /* Is it past the end? */ + if (to > mtd->size) { + return -EINVAL; + } + + end = to + len; + start_addr_highbits = to & PMC551_ADDR_HIGH_MASK; + end_addr_highbits = end & PMC551_ADDR_HIGH_MASK; + start_addr_lowbits = to & PMC551_ADDR_LOW_MASK; + end_addr_lowbits = end & PMC551_ADDR_LOW_MASK; + + + /* Only rewrite the first value if it doesn't match our current + values. Most operations are on the same page as the previous + value, so this is a pretty good optimization. */ + if (priv->curr_mem_map0_val != + (priv->mem_map0_base_val | start_addr_highbits)) { + priv->curr_mem_map0_val = (priv->mem_map0_base_val + | start_addr_highbits); + pci_write_config_dword ( priv->dev, + PMC551_PCI_MEM_MAP0, + priv->curr_mem_map0_val); + } + + if (start_addr_highbits == end_addr_highbits) { + /* The whole thing fits within one access, so just one shot + will do it. */ + memcpy(priv->start + start_addr_lowbits, + copyfrom, + len); + copyfrom += len; + } else { + /* We have to do multiple writes to get all the data + written. */ + memcpy(priv->start + start_addr_lowbits, + copyfrom, + priv->aperture_size - start_addr_lowbits); + copyfrom += priv->aperture_size - start_addr_lowbits; + start_addr_highbits += priv->aperture_size; + while (start_addr_highbits != end_addr_highbits) { + pci_write_config_dword ( priv->dev, + PMC551_PCI_MEM_MAP0, + (priv->mem_map0_base_val + | start_addr_highbits)); + memcpy(priv->start, + copyfrom, + priv->aperture_size); + copyfrom += priv->aperture_size; + start_addr_highbits += priv->aperture_size; + if (start_addr_highbits >= mtd->size) { + /* Make sure we have the right value here. */ + priv->curr_mem_map0_val + = (priv->mem_map0_base_val + | start_addr_highbits); + goto out; + } + } + priv->curr_mem_map0_val = (priv->mem_map0_base_val + | start_addr_highbits); + pci_write_config_dword ( priv->dev, + PMC551_PCI_MEM_MAP0, + priv->curr_mem_map0_val); + memcpy(priv->start, + copyfrom, + end_addr_lowbits); + copyfrom += end_addr_lowbits; + } + +out: + *retlen = copyfrom - buf; + return 0; +} + +/* + * Fixup routines for the V370PDC + * PCI device ID 0x020011b0 + * + * This function basicly kick starts the DRAM oboard the card and gets it + * ready to be used. Before this is done the device reads VERY erratic, so + * much that it can crash the Linux 2.2.x series kernels when a user cat's + * /proc/pci .. though that is mainly a kernel bug in handling the PCI DEVSEL + * register. FIXME: stop spinning on registers .. must implement a timeout + * mechanism + * returns the size of the memory region found. + */ +static u32 fixup_pmc551 (struct pci_dev *dev) +{ +#ifdef CONFIG_MTD_PMC551_BUGFIX + u32 dram_data; +#endif + u32 size, dcmd, cfg, dtmp; + u16 cmd, tmp, i; + u8 bcmd, counter; + + /* Sanity Check */ + if(!dev) { + return -ENODEV; + } + + /* + * Attempt to reset the card + * FIXME: Stop Spinning registers + */ + counter=0; + /* unlock registers */ + pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, 0xA5 ); + /* read in old data */ + pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd ); + /* bang the reset line up and down for a few */ + for(i=0;i<10;i++) { + counter=0; + bcmd &= ~0x80; + while(counter++ < 100) { + pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd); + } + counter=0; + bcmd |= 0x80; + while(counter++ < 100) { + pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd); + } + } + bcmd |= (0x40|0x20); + pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd); + + /* + * Take care and turn off the memory on the device while we + * tweak the configurations + */ + pci_read_config_word(dev, PCI_COMMAND, &cmd); + tmp = cmd & ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY); + pci_write_config_word(dev, PCI_COMMAND, tmp); + + /* + * Disable existing aperture before probing memory size + */ + pci_read_config_dword(dev, PMC551_PCI_MEM_MAP0, &dcmd); + dtmp=(dcmd|PMC551_PCI_MEM_MAP_ENABLE|PMC551_PCI_MEM_MAP_REG_EN); + pci_write_config_dword(dev, PMC551_PCI_MEM_MAP0, dtmp); + /* + * Grab old BAR0 config so that we can figure out memory size + * This is another bit of kludge going on. The reason for the + * redundancy is I am hoping to retain the original configuration + * previously assigned to the card by the BIOS or some previous + * fixup routine in the kernel. So we read the old config into cfg, + * then write all 1's to the memory space, read back the result into + * "size", and then write back all the old config. + */ + pci_read_config_dword( dev, PCI_BASE_ADDRESS_0, &cfg ); +#ifndef CONFIG_MTD_PMC551_BUGFIX + pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, ~0 ); + pci_read_config_dword( dev, PCI_BASE_ADDRESS_0, &size ); + pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg ); + size=~(size&PCI_BASE_ADDRESS_MEM_MASK)+1; +#else + /* + * Get the size of the memory by reading all the DRAM size values + * and adding them up. + * + * KLUDGE ALERT: the boards we are using have invalid column and + * row mux values. We fix them here, but this will break other + * memory configurations. + */ + pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dram_data); + size = PMC551_DRAM_BLK_GET_SIZE(dram_data); + dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); + dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); + pci_write_config_dword(dev, PMC551_DRAM_BLK0, dram_data); + + pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dram_data); + size += PMC551_DRAM_BLK_GET_SIZE(dram_data); + dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); + dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); + pci_write_config_dword(dev, PMC551_DRAM_BLK1, dram_data); + + pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dram_data); + size += PMC551_DRAM_BLK_GET_SIZE(dram_data); + dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); + dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); + pci_write_config_dword(dev, PMC551_DRAM_BLK2, dram_data); + + pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dram_data); + size += PMC551_DRAM_BLK_GET_SIZE(dram_data); + dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); + dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); + pci_write_config_dword(dev, PMC551_DRAM_BLK3, dram_data); + + /* + * Oops .. something went wrong + */ + if( (size &= PCI_BASE_ADDRESS_MEM_MASK) == 0) { + return -ENODEV; + } +#endif /* CONFIG_MTD_PMC551_BUGFIX */ + + if ((cfg&PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) { + return -ENODEV; + } + + /* + * Precharge Dram + */ + pci_write_config_word( dev, PMC551_SDRAM_MA, 0x0400 ); + pci_write_config_word( dev, PMC551_SDRAM_CMD, 0x00bf ); + + /* + * Wait until command has gone through + * FIXME: register spinning issue + */ + do { pci_read_config_word( dev, PMC551_SDRAM_CMD, &cmd ); + if(counter++ > 100)break; + } while ( (PCI_COMMAND_IO) & cmd ); + + /* + * Turn on auto refresh + * The loop is taken directly from Ramix's example code. I assume that + * this must be held high for some duration of time, but I can find no + * documentation refrencing the reasons why. + * + */ + for ( i = 1; i<=8 ; i++) { + pci_write_config_word (dev, PMC551_SDRAM_CMD, 0x0df); + + /* + * Make certain command has gone through + * FIXME: register spinning issue + */ + counter=0; + do { pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd); + if(counter++ > 100)break; + } while ( (PCI_COMMAND_IO) & cmd ); + } + + pci_write_config_word ( dev, PMC551_SDRAM_MA, 0x0020); + pci_write_config_word ( dev, PMC551_SDRAM_CMD, 0x0ff); + + /* + * Wait until command completes + * FIXME: register spinning issue + */ + counter=0; + do { pci_read_config_word ( dev, PMC551_SDRAM_CMD, &cmd); + if(counter++ > 100)break; + } while ( (PCI_COMMAND_IO) & cmd ); + + pci_read_config_dword ( dev, PMC551_DRAM_CFG, &dcmd); + dcmd |= 0x02000000; + pci_write_config_dword ( dev, PMC551_DRAM_CFG, dcmd); + + /* + * Check to make certain fast back-to-back, if not + * then set it so + */ + pci_read_config_word( dev, PCI_STATUS, &cmd); + if((cmd&PCI_COMMAND_FAST_BACK) == 0) { + cmd |= PCI_COMMAND_FAST_BACK; + pci_write_config_word( dev, PCI_STATUS, cmd); + } + + /* + * Check to make certain the DEVSEL is set correctly, this device + * has a tendancy to assert DEVSEL and TRDY when a write is performed + * to the memory when memory is read-only + */ + if((cmd&PCI_STATUS_DEVSEL_MASK) != 0x0) { + cmd &= ~PCI_STATUS_DEVSEL_MASK; + pci_write_config_word( dev, PCI_STATUS, cmd ); + } + /* + * Set to be prefetchable and put everything back based on old cfg. + * it's possible that the reset of the V370PDC nuked the original + * setup + */ + cfg |= PCI_BASE_ADDRESS_MEM_PREFETCH; + pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg ); + + /* + * Turn PCI memory and I/O bus access back on + */ + pci_write_config_word( dev, PCI_COMMAND, + PCI_COMMAND_MEMORY | PCI_COMMAND_IO ); +#ifdef CONFIG_MTD_PMC551_DEBUG + /* + * Some screen fun + */ + printk(KERN_DEBUG "pmc551: %d%c (0x%x) of %sprefetchable memory at 0x%lx\n", + (size<1024)?size:(size<1048576)?size/1024:size/1024/1024, + (size<1024)?'B':(size<1048576)?'K':'M', + size, ((dcmd&(0x1<<3)) == 0)?"non-":"", + PCI_BASE_ADDRESS(dev)&PCI_BASE_ADDRESS_MEM_MASK ); + + /* + * Check to see the state of the memory + */ + pci_read_config_dword( dev, PMC551_DRAM_BLK0, &dcmd ); + printk(KERN_DEBUG "pmc551: DRAM_BLK0 Flags: %s,%s\n" + "pmc551: DRAM_BLK0 Size: %d at %d\n" + "pmc551: DRAM_BLK0 Row MUX: %d, Col MUX: %d\n", + (((0x1<<1)&dcmd) == 0)?"RW":"RO", + (((0x1<<0)&dcmd) == 0)?"Off":"On", + PMC551_DRAM_BLK_GET_SIZE(dcmd), + ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) ); + + pci_read_config_dword( dev, PMC551_DRAM_BLK1, &dcmd ); + printk(KERN_DEBUG "pmc551: DRAM_BLK1 Flags: %s,%s\n" + "pmc551: DRAM_BLK1 Size: %d at %d\n" + "pmc551: DRAM_BLK1 Row MUX: %d, Col MUX: %d\n", + (((0x1<<1)&dcmd) == 0)?"RW":"RO", + (((0x1<<0)&dcmd) == 0)?"Off":"On", + PMC551_DRAM_BLK_GET_SIZE(dcmd), + ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) ); + + pci_read_config_dword( dev, PMC551_DRAM_BLK2, &dcmd ); + printk(KERN_DEBUG "pmc551: DRAM_BLK2 Flags: %s,%s\n" + "pmc551: DRAM_BLK2 Size: %d at %d\n" + "pmc551: DRAM_BLK2 Row MUX: %d, Col MUX: %d\n", + (((0x1<<1)&dcmd) == 0)?"RW":"RO", + (((0x1<<0)&dcmd) == 0)?"Off":"On", + PMC551_DRAM_BLK_GET_SIZE(dcmd), + ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) ); + + pci_read_config_dword( dev, PMC551_DRAM_BLK3, &dcmd ); + printk(KERN_DEBUG "pmc551: DRAM_BLK3 Flags: %s,%s\n" + "pmc551: DRAM_BLK3 Size: %d at %d\n" + "pmc551: DRAM_BLK3 Row MUX: %d, Col MUX: %d\n", + (((0x1<<1)&dcmd) == 0)?"RW":"RO", + (((0x1<<0)&dcmd) == 0)?"Off":"On", + PMC551_DRAM_BLK_GET_SIZE(dcmd), + ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) ); + + pci_read_config_word( dev, PCI_COMMAND, &cmd ); + printk( KERN_DEBUG "pmc551: Memory Access %s\n", + (((0x1<<1)&cmd) == 0)?"off":"on" ); + printk( KERN_DEBUG "pmc551: I/O Access %s\n", + (((0x1<<0)&cmd) == 0)?"off":"on" ); + + pci_read_config_word( dev, PCI_STATUS, &cmd ); + printk( KERN_DEBUG "pmc551: Devsel %s\n", + ((PCI_STATUS_DEVSEL_MASK&cmd)==0x000)?"Fast": + ((PCI_STATUS_DEVSEL_MASK&cmd)==0x200)?"Medium": + ((PCI_STATUS_DEVSEL_MASK&cmd)==0x400)?"Slow":"Invalid" ); + + printk( KERN_DEBUG "pmc551: %sFast Back-to-Back\n", + ((PCI_COMMAND_FAST_BACK&cmd) == 0)?"Not ":"" ); + + pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd ); + printk( KERN_DEBUG "pmc551: EEPROM is under %s control\n" + "pmc551: System Control Register is %slocked to PCI access\n" + "pmc551: System Control Register is %slocked to EEPROM access\n", + (bcmd&0x1)?"software":"hardware", + (bcmd&0x20)?"":"un", (bcmd&0x40)?"":"un"); +#endif + return size; +} + +/* + * Kernel version specific module stuffages + */ + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define init_pmc551 init_module +#define cleanup_pmc551 cleanup_module +#endif + +#if defined(MODULE) +MODULE_AUTHOR("Mark Ferrell "); +MODULE_DESCRIPTION(PMC551_VERSION); +MODULE_PARM(msize, "i"); +MODULE_PARM_DESC(msize, "memory size, 6=32M, 7=64M, 8=128M, etc.. [32M-1024M]"); +MODULE_PARM(asize, "i"); +MODULE_PARM_DESC(asize, "aperture size, must be <= memsize [1M-1024M]"); +#endif +/* + * Stuff these outside the ifdef so as to not bust compiled in driver support + */ +static int msize=0; +#if defined(CONFIG_MTD_PMC551_APERTURE_SIZE) +static int asize=CONFIG_MTD_PMC551_APERTURE_SIZE +#else +static int asize=0; +#endif + +/* + * PMC551 Card Initialization + */ +int __init init_pmc551(void) +{ + struct pci_dev *PCI_Device = NULL; + struct mypriv *priv; + int count, found=0; + struct mtd_info *mtd; + u32 length = 0; + + if(msize) { + if (msize < 6 || msize > 11 ) { + printk(KERN_NOTICE "pmc551: Invalid memory size\n"); + return -ENODEV; + } + msize = (512*1024)< 11 ) { + printk(KERN_NOTICE "pmc551: Invalid aperture size\n"); + return -ENODEV; + } + asize = (512*1024)<irq); + + /* + * The PMC551 device acts VERY weird if you don't init it + * first. i.e. it will not correctly report devsel. If for + * some reason the sdram is in a wrote-protected state the + * device will DEVSEL when it is written to causing problems + * with the oldproc.c driver in + * some kernels (2.2.*) + */ + if((length = fixup_pmc551(PCI_Device)) <= 0) { + printk(KERN_NOTICE "pmc551: Cannot init SDRAM\n"); + break; + } + if(msize) { + length = msize; + printk(KERN_NOTICE "pmc551: Using specified memory size 0x%x\n", length); + } + + mtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL); + if (!mtd) { + printk(KERN_NOTICE "pmc551: Cannot allocate new MTD device.\n"); + break; + } + + memset(mtd, 0, sizeof(struct mtd_info)); + + priv = kmalloc (sizeof(struct mypriv), GFP_KERNEL); + if (!priv) { + printk(KERN_NOTICE "pmc551: Cannot allocate new MTD device.\n"); + kfree(mtd); + break; + } + memset(priv, 0, sizeof(*priv)); + mtd->priv = priv; + + priv->dev = PCI_Device; + if(asize) { + if(asize > length) { + asize=length; + printk(KERN_NOTICE "pmc551: reducing aperture size to fit memory [0x%x]\n",asize); + } else { + printk(KERN_NOTICE "pmc551: Using specified aperture size 0x%x\n", asize); + } + priv->aperture_size = asize; + } else { + priv->aperture_size = length; + } + priv->start = ioremap((PCI_BASE_ADDRESS(PCI_Device) + & PCI_BASE_ADDRESS_MEM_MASK), + priv->aperture_size); + + if (!priv->start) { + kfree(mtd->priv); + kfree(mtd); + break; + } + /* + * Due to the dynamic nature of the code, we need to figure + * this out in order to stuff the register to set the proper + * aperture size. If you know of an easier way to do this then + * PLEASE help yourself. + * + * Not with bloody floating point, you don't. Consider yourself + * duly LARTed. dwmw2. + */ + { + u32 size; + u16 bits; + size = priv->aperture_size>>20; + for(bits=0;!(size&0x01)&&size>0;bits++,size=size>>1); + //size=((u32)((log10(priv->aperture_size)/.30103)-19)<<4); + priv->mem_map0_base_val = (PMC551_PCI_MEM_MAP_REG_EN + | PMC551_PCI_MEM_MAP_ENABLE + | size); +#ifdef CONFIG_MTD_PMC551_DEBUG + printk(KERN_NOTICE "pmc551: aperture set to %d[%d]\n", + size, size>>4); +#endif + } + priv->curr_mem_map0_val = priv->mem_map0_base_val; + + pci_write_config_dword ( priv->dev, + PMC551_PCI_MEM_MAP0, + priv->curr_mem_map0_val); + + mtd->size = length; + mtd->flags = (MTD_CLEAR_BITS + | MTD_SET_BITS + | MTD_WRITEB_WRITEABLE + | MTD_VOLATILE); + mtd->erase = pmc551_erase; + mtd->point = NULL; + mtd->unpoint = pmc551_unpoint; + mtd->read = pmc551_read; + mtd->write = pmc551_write; + mtd->module = THIS_MODULE; + mtd->type = MTD_RAM; + mtd->name = "PMC551 RAM board"; + mtd->erasesize = 0x10000; + + if (add_mtd_device(mtd)) { + printk(KERN_NOTICE "pmc551: Failed to register new device\n"); + iounmap(priv->start); + kfree(mtd->priv); + kfree(mtd); + break; + } + printk(KERN_NOTICE "Registered pmc551 memory device.\n"); + printk(KERN_NOTICE "Mapped %dM of memory from 0x%p to 0x%p\n", + priv->aperture_size/1024/1024, + priv->start, + priv->start + priv->aperture_size); + printk(KERN_NOTICE "Total memory is %d%c\n", + (length<1024)?length: + (length<1048576)?length/1024:length/1024/1024, + (length<1024)?'B':(length<1048576)?'K':'M'); + priv->nextpmc551 = pmc551list; + pmc551list = mtd; + found++; + } + + if( !pmc551list ) { + printk(KERN_NOTICE "pmc551: not detected,\n"); + return -ENODEV; + } else { + printk(KERN_NOTICE "pmc551: %d pmc551 devices loaded\n", found); + return 0; + } +} + +/* + * PMC551 Card Cleanup + */ +static void __exit cleanup_pmc551(void) +{ + int found=0; + struct mtd_info *mtd; + struct mypriv *priv; + + while((mtd=pmc551list)) { + priv = (struct mypriv *)mtd->priv; + pmc551list = priv->nextpmc551; + + if(priv->start) + iounmap(priv->start); + + kfree (mtd->priv); + del_mtd_device(mtd); + kfree(mtd); + found++; + } + + printk(KERN_NOTICE "pmc551: %d pmc551 devices unloaded\n", found); +} + +module_init(init_pmc551); +module_exit(cleanup_pmc551); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/devices/slram.c linux/drivers/mtd/devices/slram.c --- v2.4.5/linux/drivers/mtd/devices/slram.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/devices/slram.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,341 @@ +/*====================================================================== + + $Id: slram.c,v 1.19 2001/06/02 20:33:20 dwmw2 Exp $ + +======================================================================*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define SLRAM_MAX_DEVICES_PARAMS 6 /* 3 parameters / device */ + +#define T(fmt, args...) printk(KERN_DEBUG fmt, ## args) +#define E(fmt, args...) printk(KERN_NOTICE fmt, ## args) + +typedef struct slram_priv { + u_char *start; + u_char *end; +} slram_priv_t; + +typedef struct slram_mtd_list { + struct mtd_info *mtdinfo; + struct slram_mtd_list *next; +} slram_mtd_list_t; + +#ifdef MODULE +static char *map[SLRAM_MAX_DEVICES_PARAMS]; +#else +static char *map; +#endif + +#ifdef MODULE +#if LINUX_VERSION_CODE < 0x20212 +#define init_slram init_module +#define cleanup_slram cleanup_module +#endif + +MODULE_PARM(map, "3-" __MODULE_STRING(SLRAM_MAX_DEVICES_PARAMS) "s"); +MODULE_PARM_DESC(map, "List of memory regions to map. \"map=, , \""); +#endif + +static slram_mtd_list_t *slram_mtdlist = NULL; + +int slram_erase(struct mtd_info *, struct erase_info *); +int slram_point(struct mtd_info *, loff_t, size_t, size_t *, u_char **); +void slram_unpoint(struct mtd_info *, u_char *); +int slram_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *); +int slram_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); + +int slram_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + slram_priv_t *priv = mtd->priv; + + if (instr->addr + instr->len > mtd->size) { + return(-EINVAL); + } + + memset(priv->start + instr->addr, 0xff, instr->len); + + /* This'll catch a few races. Free the thing before returning :) + * I don't feel at all ashamed. This kind of thing is possible anyway + * with flash, but unlikely. + */ + + instr->state = MTD_ERASE_DONE; + + if (instr->callback) { + (*(instr->callback))(instr); + } + else { + kfree(instr); + } + + return(0); +} + +int slram_point(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char **mtdbuf) +{ + slram_priv_t *priv = (slram_priv_t *)mtd->priv; + + *mtdbuf = priv->start + from; + *retlen = len; + return(0); +} + +void slram_unpoint(struct mtd_info *mtd, u_char *addr) +{ +} + +int slram_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + slram_priv_t *priv = (slram_priv_t *)mtd->priv; + + memcpy(buf, priv->start + from, len); + + *retlen = len; + return(0); +} + +int slram_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + slram_priv_t *priv = (slram_priv_t *)mtd->priv; + + memcpy(priv->start + to, buf, len); + + *retlen = len; + return(0); +} + +/*====================================================================*/ + +int register_device(char *name, long start, long length) +{ + slram_mtd_list_t **curmtd; + + curmtd = &slram_mtdlist; + while (*curmtd) { + curmtd = &(*curmtd)->next; + } + + *curmtd = kmalloc(sizeof(slram_mtd_list_t), GFP_KERNEL); + if (!curmtd) { + E("slram: Cannot allocate new MTD device.\n"); + return(-ENOMEM); + } + (*curmtd)->mtdinfo = kmalloc(sizeof(struct mtd_info), GFP_KERNEL); + (*curmtd)->next = NULL; + + if ((*curmtd)->mtdinfo) { + memset((char *)(*curmtd)->mtdinfo, 0, sizeof(struct mtd_info)); + (*curmtd)->mtdinfo->priv = + (void *)kmalloc(sizeof(slram_priv_t), GFP_KERNEL); + + if (!(*curmtd)->mtdinfo->priv) { + kfree((*curmtd)->mtdinfo); + (*curmtd)->mtdinfo = NULL; + } else { + memset((*curmtd)->mtdinfo->priv,0,sizeof(slram_priv_t)); + } + } + + if (!(*curmtd)->mtdinfo) { + E("slram: Cannot allocate new MTD device.\n"); + return(-ENOMEM); + } + + if (!(((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start = + ioremap(start, length))) { + E("slram: ioremap failed\n"); + return -EIO; + } + ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->end = + ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start + length; + + + (*curmtd)->mtdinfo->name = name; + (*curmtd)->mtdinfo->size = length; + (*curmtd)->mtdinfo->flags = MTD_CLEAR_BITS | MTD_SET_BITS | + MTD_WRITEB_WRITEABLE | MTD_VOLATILE; + (*curmtd)->mtdinfo->erase = slram_erase; + (*curmtd)->mtdinfo->point = slram_point; + (*curmtd)->mtdinfo->unpoint = slram_unpoint; + (*curmtd)->mtdinfo->read = slram_read; + (*curmtd)->mtdinfo->write = slram_write; + (*curmtd)->mtdinfo->module = THIS_MODULE; + (*curmtd)->mtdinfo->type = MTD_RAM; + (*curmtd)->mtdinfo->erasesize = 0x10000; + + if (add_mtd_device((*curmtd)->mtdinfo)) { + E("slram: Failed to register new device\n"); + iounmap(((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start); + kfree((*curmtd)->mtdinfo->priv); + kfree((*curmtd)->mtdinfo); + return(-EAGAIN); + } + T("slram: Registered device %s from %dKiB to %dKiB\n", name, + (int)(start / 1024), (int)((start + length) / 1024)); + T("slram: Mapped from 0x%p to 0x%p\n", + ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start, + ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->end); + return(0); +} + +void unregister_devices(void) +{ + slram_mtd_list_t *nextitem; + + while (slram_mtdlist) { + nextitem = slram_mtdlist->next; + del_mtd_device(slram_mtdlist->mtdinfo); + iounmap(((slram_priv_t *)slram_mtdlist->mtdinfo->priv)->start); + kfree(slram_mtdlist->mtdinfo->priv); + kfree(slram_mtdlist->mtdinfo); + kfree(slram_mtdlist); + slram_mtdlist = nextitem; + } +} + +int handle_unit(long value, char *unit) +{ + if ((*unit == 'M') || (*unit == 'm')) { + return(value * 1024 * 1024); + } else if ((*unit == 'K') || (*unit == 'k')) { + return(value * 1024); + } + return(value); +} + +int parse_cmdline(char *devname, char *szstart, char *szlength) +{ + char *buffer; + long devstart; + long devlength; + + if ((!devname) || (!szstart) || (!szlength)) { + unregister_devices(); + return(-EINVAL); + } + + devstart = simple_strtoul(szstart, &buffer, 0); + devstart = handle_unit(devstart, buffer); + + if (*(szlength) != '+') { + devlength = simple_strtoul(szlength, &buffer, 0); + devlength = handle_unit(devlength, buffer) - devstart; + } else { + devlength = simple_strtoul(szlength + 1, &buffer, 0); + devlength = handle_unit(devlength, buffer); + } + T("slram: devname=%s, devstart=%li, devlength=%li\n", + devname, devstart, devlength); + if ((devstart < 0) || (devlength < 0)) { + E("slram: Illegal start / length parameter.\n"); + return(-EINVAL); + } + + if ((devstart = register_device(devname, devstart, devlength))){ + unregister_devices(); + return((int)devstart); + } + return(0); +} + +#ifndef MODULE + +static int __init mtd_slram_setup(char *str) +{ + map = str; + return(1); +} + +__setup("slram=", mtd_slram_setup); + +#endif + +int init_slram(void) +{ + char *devname; + int i; + +#ifndef MODULE + char *devstart; + char *devlength; + + i = 0; + + if (!map) { + E("slram: not enough parameters.\n"); + return(-EINVAL); + } + while (map) { + devname = devstart = devlength = NULL; + + if (!(devname = strsep(&map, ","))) { + E("slram: No devicename specified.\n"); + break; + } + T("slram: devname = %s\n", devname); + if ((!map) || (!(devstart = strsep(&map, ",")))) { + E("slram: No devicestart specified.\n"); + } + T("slram: devstart = %s\n", devstart); + if ((!map) || (!(devlength = strsep(&map, ",")))) { + E("slram: No devicelength / -end specified.\n"); + } + T("slram: devlength = %s\n", devlength); + if (parse_cmdline(devname, devstart, devlength) != 0) { + return(-EINVAL); + } + } +#else + int count; + + for (count = 0; (map[count]) && (count < SLRAM_MAX_DEVICES_PARAMS); + count++) { + } + + if ((count % 3 != 0) || (count == 0)) { + E("slram: not enough parameters.\n"); + return(-EINVAL); + } + for (i = 0; i < (count / 3); i++) { + devname = map[i * 3]; + + if (parse_cmdline(devname, map[i * 3 + 1], map[i * 3 + 2])!=0) { + return(-EINVAL); + } + + } +#endif /* !MODULE */ + + return(0); +} + +static void __exit cleanup_slram(void) +{ + unregister_devices(); +} + +module_init(init_slram); +module_exit(cleanup_slram); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/doc1000.c linux/drivers/mtd/doc1000.c --- v2.4.5/linux/drivers/mtd/doc1000.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/mtd/doc1000.c Wed Dec 31 16:00:00 1969 @@ -1,597 +0,0 @@ -/*====================================================================== - - $Id: doc1000.c,v 1.11 2000/11/24 13:43:16 dwmw2 Exp $ - -======================================================================*/ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -/* Parameters that can be set with 'insmod' */ - -static u_long base = 0xe0000; -static int erase_timeout = 10*HZ; /* in ticks */ -static int retry_limit = 4; /* write retries */ -static u_long max_tries = 4096; /* status polling */ - -MODULE_PARM(base,"l"); -MODULE_PARM(erase_timeout, "i"); -MODULE_PARM(retry_limit, "i"); -MODULE_PARM(max_tries, "i"); - -#define WINDOW_SIZE 0x2000 -#define WINDOW_MASK (WINDOW_SIZE - 1) -#define PAGEREG_LO (WINDOW_SIZE) -#define PAGEREG_HI (WINDOW_SIZE + 2) - -static struct mtd_info *mymtd; -static struct timer_list flashcard_timer; - -#define MAX_CELLS 32 -#define MAX_FLASH_DEVICES 8 - -/* A flash region is composed of one or more "cells", where we allow - simultaneous erases if they are in different cells */ - - - -struct mypriv { - u_char *baseaddr; - u_short curpage; - u_char locked; - u_short numdevices; - u_char interleave; - struct erase_info *cur_erases; - wait_queue_head_t wq; - u_char devstat[MAX_FLASH_DEVICES]; - u_long devshift; -}; - - -static void flashcard_periodic(u_long data); -static int flashcard_erase (struct mtd_info *mtd, struct erase_info *instr); -static int flashcard_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); -static int flashcard_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); -static void flashcard_sync (struct mtd_info *mtd); - -static inline void resume_erase(volatile u_char *addr); -static inline int suspend_erase(volatile u_char *addr); -static inline int byte_write (volatile u_char *addr, u_char byte); -static inline int word_write (volatile u_char *addr, __u16 word); -static inline int check_write(volatile u_char *addr); -static inline void block_erase (volatile u_char *addr); -static inline int check_erase(volatile u_char *addr); - -#ifdef CONFIG_SMP -#warning This is definitely not SMP safe. Lock the paging mechanism. -#endif - -static u_char *pagein(struct mtd_info *mtd, u_long addr) -{ - struct mypriv *priv=mtd->priv; - u_short page = addr >> 13; - - priv->baseaddr[PAGEREG_LO] = page & 0xff; - priv->baseaddr[PAGEREG_HI] = page >> 8; - priv->curpage = page; - - return &priv->baseaddr[addr & WINDOW_MASK]; -} - - -void flashcard_sync (struct mtd_info *mtd) -{ - struct mypriv *priv=mtd->priv; - - flashcard_periodic((u_long) mtd); - printk("sync..."); - if (priv->cur_erases) - interruptible_sleep_on(&priv->wq); - printk("Done.\n"); -} - -int flashcard_erase (struct mtd_info *mtd, struct erase_info *instr) -{ - u_char *pageaddr; - struct mypriv *priv=mtd->priv; - struct erase_info **tmp=&priv->cur_erases; - - if (instr->len != mtd->erasesize) - return -EINVAL; - if (instr->addr + instr->len > mtd->size) - return -EINVAL; - - pageaddr=pagein(mtd,instr->addr); - instr->mtd = mtd; - instr->dev = instr->addr >> priv->devshift; - instr->cell = (instr->addr - (instr->dev << priv->devshift)) / mtd->erasesize; - instr->next = NULL; - instr->state = MTD_ERASE_PENDING; - - while (*tmp) - { - tmp = &((*tmp) -> next); - } - - *tmp = instr; - flashcard_periodic((u_long)mtd); - return 0; -} - - -int flashcard_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) -{ - u_char *pageaddr=pagein(mtd,from); - struct mypriv *priv=mtd->priv; - u_char device = from >> priv->devshift; - u_char cell = (int) (from - (device << priv->devshift)) / mtd->erasesize; - int ret = 0, timeron = 0; - - if ((from & WINDOW_MASK) + len <= WINDOW_SIZE) - *retlen = len; - else - *retlen = WINDOW_SIZE - (from & WINDOW_MASK); - - if (priv->devstat[device]) - { - - /* There is an erase in progress or pending for this device. Stop it */ - timeron = del_timer(&flashcard_timer); - - if (priv->cur_erases && priv->cur_erases->cell == cell) - - { - /* The erase is on the current cell. Just return all 0xff */ - add_timer(&flashcard_timer); - - - printk("Cell %d currently erasing. Setting to all 0xff\n",cell); - memset(buf, 0xff, *retlen); - return 0; - } - if (priv->devstat[device] == MTD_ERASING) - { - ret = suspend_erase(pageaddr); - priv->devstat[device] = MTD_ERASE_SUSPEND; - - if (ret) - { - printk("flashcard: failed to suspend erase\n"); - add_timer (&flashcard_timer); - return ret; - } - } - - } - - writew(IF_READ_ARRAY, (u_long)pageaddr & ~1); - - ret = 0; - memcpy (buf, pageaddr, *retlen); - - writew(IF_READ_CSR, (u_long)pageaddr & ~1); - - - if (priv->devstat[device] & MTD_ERASE_SUSPEND) - { - resume_erase(pageaddr); - priv->devstat[device]=MTD_ERASING; - } - - - if (timeron) add_timer (&flashcard_timer); - - return ret; -} - - -int flashcard_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) -{ - struct mypriv *priv = (struct mypriv *)mtd->priv; - u_char *endaddr, *startaddr; - register u_char *pageaddr; - u_char device = to >> priv->devshift; -/* jiffies_t oldj=jiffies;*/ - int ret; - - while (priv->devstat[device]) - { - flashcard_sync(mtd); - } - - if ((to & WINDOW_MASK) + len <= WINDOW_SIZE) - *retlen = len; - else - *retlen = WINDOW_SIZE - (to & WINDOW_MASK); - - pageaddr = pagein(mtd, to); - startaddr = (u_char *)((u_long) pageaddr & ~1); - endaddr = pageaddr+(*retlen); - - - - /* Set up to read */ - writew(IF_READ_CSR, startaddr); - - /* Make sure it's aligned by reading the first byte if necessary */ - if (to & 1) - { - /* Unaligned access */ - - u_char cbuf; - - cbuf = *buf; - - if (!((u_long)pageaddr & 0xf)) - schedule(); - - ret = byte_write(pageaddr, cbuf); - if (ret) return ret; - - pageaddr++; buf++; - } - - - for ( ; pageaddr + 1 < endaddr; buf += 2, pageaddr += 2) - { - /* if ((u_long)pageaddr & 0xf) schedule();*/ - - ret = word_write(pageaddr, *(__u16 *)buf); - if (ret) - return ret; - } - - if (pageaddr != endaddr) - { - /* One more byte to write at the end. */ - u_char cbuf; - - cbuf = *buf; - - ret = byte_write(pageaddr, cbuf); - - if (ret) return ret; - } - - return check_write(startaddr); -/* printk("Time taken in flashcard_write: %lx jiffies\n",jiffies - oldj);*/ -} - - - - -/*====================================================================*/ - -static inline int byte_write (volatile u_char *addr, u_char byte) -{ - register u_char status; - register u_short i = 0; - - do { - status = readb(addr); - if (status & CSR_WR_READY) - { - writeb(IF_WRITE & 0xff, addr); - writeb(byte, addr); - return 0; - } - i++; - } while(i < max_tries); - - - printk(KERN_NOTICE "flashcard: byte_write timed out, status 0x%x\n",status); - return -EIO; -} - -static inline int word_write (volatile u_char *addr, __u16 word) -{ - register u_short status; - register u_short i = 0; - - do { - status = readw(addr); - if ((status & CSR_WR_READY) == CSR_WR_READY) - { - writew(IF_WRITE, addr); - writew(word, addr); - return 0; - } - i++; - } while(i < max_tries); - - printk(KERN_NOTICE "flashcard: word_write timed out at %p, status 0x%x\n", addr, status); - return -EIO; -} - -static inline void block_erase (volatile u_char *addr) -{ - writew(IF_BLOCK_ERASE, addr); - writew(IF_CONFIRM, addr); -} - - -static inline int check_erase(volatile u_char *addr) -{ - __u16 status; - -/* writew(IF_READ_CSR, addr);*/ - status = readw(addr); - - - if ((status & CSR_WR_READY) != CSR_WR_READY) - return -EBUSY; - - if (status & (CSR_ERA_ERR | CSR_VPP_LOW | CSR_WR_ERR)) - { - printk(KERN_NOTICE "flashcard: erase failed, status 0x%x\n", - status); - return -EIO; - } - - return 0; -} - -static inline int suspend_erase(volatile u_char *addr) -{ - __u16 status; - u_long i = 0; - - writew(IF_ERASE_SUSPEND, addr); - writew(IF_READ_CSR, addr); - - do { - status = readw(addr); - if ((status & CSR_WR_READY) == CSR_WR_READY) - return 0; - i++; - } while(i < max_tries); - - printk(KERN_NOTICE "flashcard: suspend_erase timed out, status 0x%x\n", status); - return -EIO; - -} - -static inline void resume_erase(volatile u_char *addr) -{ - __u16 status; - - writew(IF_READ_CSR, addr); - status = readw(addr); - - /* Only give resume signal if the erase is really suspended */ - if (status & CSR_ERA_SUSPEND) - writew(IF_CONFIRM, addr); -} - -static inline void reset_block(volatile u_char *addr) -{ - u_short i; - __u16 status; - - writew(IF_CLEAR_CSR, addr); - - for (i = 0; i < 100; i++) { - writew(IF_READ_CSR, addr); - status = readw(addr); - if (status != 0xffff) break; - udelay(1000); - } - - writew(IF_READ_CSR, addr); -} - -static inline int check_write(volatile u_char *addr) -{ - u_short status, i = 0; - - writew(IF_READ_CSR, addr); - - do { - status = readw(addr); - if (status & (CSR_WR_ERR | CSR_VPP_LOW)) - { - printk(KERN_NOTICE "flashcard: write failure at %p, status 0x%x\n", addr, status); - reset_block(addr); - return -EIO; - } - if ((status & CSR_WR_READY) == CSR_WR_READY) - return 0; - i++; - } while (i < max_tries); - - printk(KERN_NOTICE "flashcard: write timed out at %p, status 0x%x\n", addr, status); - return -EIO; -} - - -/*====================================================================*/ - - - -static void flashcard_periodic(unsigned long data) -{ - register struct mtd_info *mtd = (struct mtd_info *)data; - register struct mypriv *priv = mtd->priv; - struct erase_info *erase = priv->cur_erases; - u_char *pageaddr; - - del_timer (&flashcard_timer); - - if (!erase) - return; - - pageaddr = pagein(mtd, erase->addr); - - if (erase->state == MTD_ERASE_PENDING) - { - block_erase(pageaddr); - priv->devstat[erase->dev] = erase->state = MTD_ERASING; - erase->time = jiffies; - erase->retries = 0; - } - else if (erase->state == MTD_ERASING) - { - /* It's trying to erase. Check whether it's finished */ - - int ret = check_erase(pageaddr); - - if (!ret) - { - /* It's finished OK */ - priv->devstat[erase->dev] = 0; - priv->cur_erases = erase->next; - erase->state = MTD_ERASE_DONE; - if (erase->callback) - (*(erase->callback))(erase); - else - kfree(erase); - } - else if (ret == -EIO) - { - if (++erase->retries > retry_limit) - { - printk("Failed too many times. Giving up\n"); - priv->cur_erases = erase->next; - priv->devstat[erase->dev] = 0; - erase->state = MTD_ERASE_FAILED; - if (erase->callback) - (*(erase->callback))(erase); - else - kfree(erase); - } - else - priv->devstat[erase->dev] = erase->state = MTD_ERASE_PENDING; - } - else if (erase->time + erase_timeout < jiffies) - { - printk("Flash erase timed out. The world is broken.\n"); - - /* Just ignore and hope it goes away. For a while, read ops will give the CSR - and writes won't work. */ - - priv->cur_erases = erase->next; - priv->devstat[erase->dev] = 0; - erase->state = MTD_ERASE_FAILED; - if (erase->callback) - (*(erase->callback))(erase); - else - kfree(erase); - } - } - - if (priv->cur_erases) - { - flashcard_timer.expires = jiffies + HZ; - add_timer (&flashcard_timer); - } - else - wake_up_interruptible(&priv->wq); - -} - -#if defined (MODULE) && LINUX_VERSION_CODE < 0x20211 -#define init_doc1000 init_module -#define cleanup_doc1000 cleanup_module -#endif - -int __init init_doc1000(void) -{ - struct mypriv *priv; - - if (!base) - { - printk(KERN_NOTICE "flashcard: No start address for memory device.\n"); - return -EINVAL; - } - - mymtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL); - - if (!mymtd) - { - printk(KERN_NOTICE "physmem: Cannot allocate memory for new MTD device.\n"); - return -ENOMEM; - } - - memset(mymtd,0,sizeof(struct mtd_info)); - - mymtd->priv = (void *) kmalloc (sizeof(struct mypriv), GFP_KERNEL); - if (!mymtd->priv) - { - kfree(mymtd); - printk(KERN_NOTICE "physmem: Cannot allocate memory for new MTD device's private data.\n"); - return -ENOMEM; - } - - - - - priv=mymtd->priv; - init_waitqueue_head(&priv->wq); - - memset (priv,0,sizeof(struct mypriv)); - - priv->baseaddr = phys_to_virt(base); - priv->numdevices = 4; - - mymtd->name = "M-Systems DiskOnChip 1000"; - - mymtd->size = 0x100000; - mymtd->flags = MTD_CLEAR_BITS | MTD_ERASEABLE; - mymtd->erase = flashcard_erase; - mymtd->point = NULL; - mymtd->unpoint = NULL; - mymtd->read = flashcard_read; - mymtd->write = flashcard_write; - - mymtd->sync = flashcard_sync; - mymtd->erasesize = 0x10000; - // mymtd->interleave = 2; - priv->devshift = 24; - mymtd->type = MTD_NORFLASH; - - if (add_mtd_device(mymtd)) - { - printk(KERN_NOTICE "MTD device registration failed!\n"); - kfree(mymtd->priv); - kfree(mymtd); - return -EAGAIN; - } - - init_timer(&flashcard_timer); - flashcard_timer.function = flashcard_periodic; - flashcard_timer.data = (u_long)mymtd; - return 0; -} - -static void __init cleanup_doc1000(void) -{ - kfree (mymtd->priv); - del_mtd_device(mymtd); - kfree(mymtd); -} - -#if LINUX_VERSION_CODE >= 0x20211 -module_init(init_doc1000); -module_exit(cleanup_doc1000); -#endif diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/doc2000.c linux/drivers/mtd/doc2000.c --- v2.4.5/linux/drivers/mtd/doc2000.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/mtd/doc2000.c Wed Dec 31 16:00:00 1969 @@ -1,1113 +0,0 @@ - -/* - * Linux driver for Disk-On-Chip 2000 and Millennium - * (c) 1999 Machine Vision Holdings, Inc. - * (c) 1999, 2000 David Woodhouse - * - * $Id: doc2000.c,v 1.39 2000/12/01 17:34:29 dwmw2 Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define DOC_SUPPORT_2000 -#define DOC_SUPPORT_MILLENNIUM - -#ifdef DOC_SUPPORT_2000 -#define DoC_is_2000(doc) (doc->ChipID == DOC_ChipID_Doc2k) -#else -#define DoC_is_2000(doc) (0) -#endif - -#ifdef DOC_SUPPORT_MILLENNIUM -#define DoC_is_Millennium(doc) (doc->ChipID == DOC_ChipID_DocMil) -#else -#define DoC_is_Millennium(doc) (0) -#endif - -/* #define ECC_DEBUG */ - -/* I have no idea why some DoC chips can not use memcpy_from|to_io(). - * This may be due to the different revisions of the ASIC controller built-in or - * simplily a QA/Bug issue. Who knows ?? If you have trouble, please uncomment - * this: - #undef USE_MEMCPY -*/ - -static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf); -static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf); -static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf, u_char *eccbuf); -static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf, u_char *eccbuf); -static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, - size_t *retlen, u_char *buf); -static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, - size_t *retlen, const u_char *buf); -static int doc_erase (struct mtd_info *mtd, struct erase_info *instr); - -static struct mtd_info *doc2klist = NULL; - -/* Perform the required delay cycles by reading from the appropriate register */ -static void DoC_Delay(struct DiskOnChip *doc, unsigned short cycles) -{ - volatile char dummy; - int i; - - for (i = 0; i < cycles; i++) { - if (DoC_is_Millennium(doc)) - dummy = ReadDOC(doc->virtadr, NOP); - else - dummy = ReadDOC(doc->virtadr, DOCStatus); - } - -} - -/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */ -static int _DoC_WaitReady(struct DiskOnChip *doc) -{ - unsigned long docptr = doc->virtadr; - unsigned short c = 0xffff; - - DEBUG(MTD_DEBUG_LEVEL3, - "_DoC_WaitReady called for out-of-line wait\n"); - - /* Out-of-line routine to wait for chip response */ - while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B) && --c) - ; - - if (c == 0) - DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n"); - - return (c == 0); -} - -static inline int DoC_WaitReady(struct DiskOnChip *doc) -{ - unsigned long docptr = doc->virtadr; - /* This is inline, to optimise the common case, where it's ready instantly */ - int ret = 0; - - /* 4 read form NOP register should be issued in prior to the read from CDSNControl - see Software Requirement 11.4 item 2. */ - DoC_Delay(doc, 4); - - if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) - /* Call the out-of-line routine to wait */ - ret = _DoC_WaitReady(doc); - - /* issue 2 read from NOP register after reading from CDSNControl register - see Software Requirement 11.4 item 2. */ - DoC_Delay(doc, 2); - - return ret; -} - -/* DoC_Command: Send a flash command to the flash chip through the CDSN Slow IO register to - bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is - required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */ - -static inline int DoC_Command(struct DiskOnChip *doc, unsigned char command, - unsigned char xtraflags) -{ - unsigned long docptr = doc->virtadr; - - if (DoC_is_2000(doc)) - xtraflags |= CDSN_CTRL_FLASH_IO; - - /* Assert the CLE (Command Latch Enable) line to the flash chip */ - WriteDOC(xtraflags | CDSN_CTRL_CLE | CDSN_CTRL_CE, docptr, CDSNControl); - DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */ - - if (DoC_is_Millennium(doc)) - WriteDOC(command, docptr, CDSNSlowIO); - - /* Send the command */ - WriteDOC_(command, docptr, doc->ioreg); - - /* Lower the CLE line */ - WriteDOC(xtraflags | CDSN_CTRL_CE, docptr, CDSNControl); - DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */ - - /* Wait for the chip to respond - Software requirement 11.4.1 (extended for any command) */ - return DoC_WaitReady(doc); -} - -/* DoC_Address: Set the current address for the flash chip through the CDSN Slow IO register to - bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is - required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */ - -static int DoC_Address(struct DiskOnChip *doc, int numbytes, unsigned long ofs, - unsigned char xtraflags1, unsigned char xtraflags2) -{ - unsigned long docptr; - int i; - - docptr = doc->virtadr; - - if (DoC_is_2000(doc)) - xtraflags1 |= CDSN_CTRL_FLASH_IO; - - /* Assert the ALE (Address Latch Enable) line to the flash chip */ - WriteDOC(xtraflags1 | CDSN_CTRL_ALE | CDSN_CTRL_CE, docptr, CDSNControl); - - DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */ - - /* Send the address */ - /* Devices with 256-byte page are addressed as: - Column (bits 0-7), Page (bits 8-15, 16-23, 24-31) - * there is no device on the market with page256 - and more than 24 bits. - Devices with 512-byte page are addressed as: - Column (bits 0-7), Page (bits 9-16, 17-24, 25-31) - * 25-31 is sent only if the chip support it. - * bit 8 changes the read command to be sent - (NAND_CMD_READ0 or NAND_CMD_READ1). - */ - - if (numbytes == ADDR_COLUMN || numbytes == ADDR_COLUMN_PAGE) { - if (DoC_is_Millennium(doc)) - WriteDOC(ofs & 0xff, docptr, CDSNSlowIO); - WriteDOC_(ofs & 0xff, docptr, doc->ioreg); - } - - if (doc->page256) { - ofs = ofs >> 8; - } else { - ofs = ofs >> 9; - } - - if (numbytes == ADDR_PAGE || numbytes == ADDR_COLUMN_PAGE) { - for (i = 0; i < doc->pageadrlen; i++, ofs = ofs >> 8) { - if (DoC_is_Millennium(doc)) - WriteDOC(ofs & 0xff, docptr, CDSNSlowIO); - WriteDOC_(ofs & 0xff, docptr, doc->ioreg); - } - } - - DoC_Delay(doc, 2); /* Needed for some slow flash chips. mf. */ - - /* FIXME: The SlowIO's for millennium could be replaced by - a single WritePipeTerm here. mf. */ - - /* Lower the ALE line */ - WriteDOC(xtraflags1 | xtraflags2 | CDSN_CTRL_CE, docptr, - CDSNControl); - - DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */ - - /* Wait for the chip to respond - Software requirement 11.4.1 */ - return DoC_WaitReady(doc); -} - -/* Read a buffer from DoC, taking care of Millennium odditys */ -static void DoC_ReadBuf(struct DiskOnChip *doc, u_char * buf, int len) -{ - int dummy; - int modulus = 0xffff; - unsigned long docptr; - int i; - - docptr = doc->virtadr; - - if (len <= 0) - return; - - if (DoC_is_Millennium(doc)) { - /* Read the data via the internal pipeline through CDSN IO register, - see Pipelined Read Operations 11.3 */ - dummy = ReadDOC(docptr, ReadPipeInit); - - /* Millennium should use the LastDataRead register - Pipeline Reads */ - len--; - - /* This is needed for correctly ECC calculation */ - modulus = 0xff; - } - - for (i = 0; i < len; i++) - buf[i] = ReadDOC_(docptr, doc->ioreg + (i & modulus)); - - if (DoC_is_Millennium(doc)) { - buf[i] = ReadDOC(docptr, LastDataRead); - } -} - -/* Write a buffer to DoC, taking care of Millennium odditys */ -static void DoC_WriteBuf(struct DiskOnChip *doc, const u_char * buf, int len) -{ - unsigned long docptr; - int i; - - docptr = doc->virtadr; - - if (len <= 0) - return; - - for (i = 0; i < len; i++) - WriteDOC_(buf[i], docptr, doc->ioreg + i); - - if (DoC_is_Millennium(doc)) { - WriteDOC(0x00, docptr, WritePipeTerm); - } -} - - -/* DoC_SelectChip: Select a given flash chip within the current floor */ - -static inline int DoC_SelectChip(struct DiskOnChip *doc, int chip) -{ - unsigned long docptr = doc->virtadr; - - /* Software requirement 11.4.4 before writing DeviceSelect */ - /* Deassert the CE line to eliminate glitches on the FCE# outputs */ - WriteDOC(CDSN_CTRL_WP, docptr, CDSNControl); - DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */ - - /* Select the individual flash chip requested */ - WriteDOC(chip, docptr, CDSNDeviceSelect); - DoC_Delay(doc, 4); - - /* Reassert the CE line */ - WriteDOC(CDSN_CTRL_CE | CDSN_CTRL_FLASH_IO | CDSN_CTRL_WP, docptr, - CDSNControl); - DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */ - - /* Wait for it to be ready */ - return DoC_WaitReady(doc); -} - -/* DoC_SelectFloor: Select a given floor (bank of flash chips) */ - -static inline int DoC_SelectFloor(struct DiskOnChip *doc, int floor) -{ - unsigned long docptr = doc->virtadr; - - /* Select the floor (bank) of chips required */ - WriteDOC(floor, docptr, FloorSelect); - - /* Wait for the chip to be ready */ - return DoC_WaitReady(doc); -} - -/* DoC_IdentChip: Identify a given NAND chip given {floor,chip} */ - -static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip) -{ - int mfr, id, i; - volatile char dummy; - - /* Page in the required floor/chip */ - DoC_SelectFloor(doc, floor); - DoC_SelectChip(doc, chip); - - /* Reset the chip */ - if (DoC_Command(doc, NAND_CMD_RESET, CDSN_CTRL_WP)) { - DEBUG(MTD_DEBUG_LEVEL2, - "DoC_Command (reset) for %d,%d returned true\n", - floor, chip); - return 0; - } - - - /* Read the NAND chip ID: 1. Send ReadID command */ - if (DoC_Command(doc, NAND_CMD_READID, CDSN_CTRL_WP)) { - DEBUG(MTD_DEBUG_LEVEL2, - "DoC_Command (ReadID) for %d,%d returned true\n", - floor, chip); - return 0; - } - - /* Read the NAND chip ID: 2. Send address byte zero */ - DoC_Address(doc, ADDR_COLUMN, 0, CDSN_CTRL_WP, 0); - - /* Read the manufacturer and device id codes from the device */ - - /* CDSN Slow IO register see Software Requirement 11.4 item 5. */ - dummy = ReadDOC(doc->virtadr, CDSNSlowIO); - DoC_Delay(doc, 2); - mfr = ReadDOC_(doc->virtadr, doc->ioreg); - - /* CDSN Slow IO register see Software Requirement 11.4 item 5. */ - dummy = ReadDOC(doc->virtadr, CDSNSlowIO); - DoC_Delay(doc, 2); - id = ReadDOC_(doc->virtadr, doc->ioreg); - - /* No response - return failure */ - if (mfr == 0xff || mfr == 0) - return 0; - - /* Check it's the same as the first chip we identified. - * M-Systems say that any given DiskOnChip device should only - * contain _one_ type of flash part, although that's not a - * hardware restriction. */ - if (doc->mfr) { - if (doc->mfr == mfr && doc->id == id) - return 1; /* This is another the same the first */ - else - printk(KERN_WARNING - "Flash chip at floor %d, chip %d is different:\n", - floor, chip); - } - - /* Print and store the manufacturer and ID codes. */ - for (i = 0; nand_flash_ids[i].name != NULL; i++) { - if (mfr == nand_flash_ids[i].manufacture_id && - id == nand_flash_ids[i].model_id) { - printk(KERN_INFO - "Flash chip found: Manufacturer ID: %2.2X, " - "Chip ID: %2.2X (%s)\n", mfr, id, - nand_flash_ids[i].name); - if (!doc->mfr) { - doc->mfr = mfr; - doc->id = id; - doc->chipshift = - nand_flash_ids[i].chipshift; - doc->page256 = nand_flash_ids[i].page256; - doc->pageadrlen = - nand_flash_ids[i].pageadrlen; - doc->erasesize = - nand_flash_ids[i].erasesize; - return 1; - } - return 0; - } - } - - - /* We haven't fully identified the chip. Print as much as we know. */ - printk(KERN_WARNING "Unknown flash chip found: %2.2X %2.2X\n", - id, mfr); - - printk(KERN_WARNING "Please report to dwmw2@infradead.org\n"); - return 0; -} - -/* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */ - -static void DoC_ScanChips(struct DiskOnChip *this) -{ - int floor, chip; - int numchips[MAX_FLOORS]; - int maxchips = MAX_CHIPS; - int ret = 1; - - this->numchips = 0; - this->mfr = 0; - this->id = 0; - - if (DoC_is_Millennium(this)) - maxchips = MAX_CHIPS_MIL; - - /* For each floor, find the number of valid chips it contains */ - for (floor = 0; floor < MAX_FLOORS; floor++) { - ret = 1; - numchips[floor] = 0; - for (chip = 0; chip < maxchips && ret != 0; chip++) { - - ret = DoC_IdentChip(this, floor, chip); - if (ret) { - numchips[floor]++; - this->numchips++; - } - } - } - - /* If there are none at all that we recognise, bail */ - if (!this->numchips) { - printk("No flash chips recognised.\n"); - return; - } - - /* Allocate an array to hold the information for each chip */ - this->chips = kmalloc(sizeof(struct Nand) * this->numchips, GFP_KERNEL); - if (!this->chips) { - printk("No memory for allocating chip info structures\n"); - return; - } - - ret = 0; - - /* Fill out the chip array with {floor, chipno} for each - * detected chip in the device. */ - for (floor = 0; floor < MAX_FLOORS; floor++) { - for (chip = 0; chip < numchips[floor]; chip++) { - this->chips[ret].floor = floor; - this->chips[ret].chip = chip; - this->chips[ret].curadr = 0; - this->chips[ret].curmode = 0x50; - ret++; - } - } - - /* Calculate and print the total size of the device */ - this->totlen = this->numchips * (1 << this->chipshift); - - printk(KERN_INFO - "%d flash chips found. Total DiskOnChip size: %ld Mb\n", - this->numchips, this->totlen >> 20); -} - - -static int DoC2k_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2) -{ - int tmp1, tmp2, retval; - if (doc1->physadr == doc2->physadr) - return 1; - - /* Use the alias resolution register which was set aside for this - * purpose. If it's value is the same on both chips, they might - * be the same chip, and we write to one and check for a change in - * the other. It's unclear if this register is usuable in the - * DoC 2000 (it's in the Millennium docs), but it seems to work. */ - tmp1 = ReadDOC(doc1->virtadr, AliasResolution); - tmp2 = ReadDOC(doc2->virtadr, AliasResolution); - if (tmp1 != tmp2) - return 0; - - WriteDOC((tmp1 + 1) % 0xff, doc1->virtadr, AliasResolution); - tmp2 = ReadDOC(doc2->virtadr, AliasResolution); - if (tmp2 == (tmp1 + 1) % 0xff) - retval = 1; - else - retval = 0; - - /* Restore register contents. May not be necessary, but do it just to - * be safe. */ - WriteDOC(tmp1, doc1->virtadr, AliasResolution); - - return retval; -} - -static const char im_name[] = "DoC2k_init"; - -/* This routine is made available to other mtd code via - * inter_module_register. It must only be accessed through - * inter_module_get which will bump the use count of this module. The - * addresses passed back in mtd are valid as long as the use count of - * this module is non-zero, i.e. between inter_module_get and - * inter_module_put. Keith Owens 29 Oct 2000. - */ -static void DoC2k_init(struct mtd_info *mtd) -{ - struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv; - struct DiskOnChip *old = NULL; - - /* We must avoid being called twice for the same device. */ - - if (doc2klist) - old = (struct DiskOnChip *) doc2klist->priv; - - while (old) { - if (DoC2k_is_alias(old, this)) { - printk(KERN_NOTICE - "Ignoring DiskOnChip 2000 at 0x%lX - already configured\n", - this->physadr); - iounmap((void *) this->virtadr); - kfree(mtd); - return; - } - if (old->nextdoc) - old = (struct DiskOnChip *) old->nextdoc->priv; - else - old = NULL; - } - - - switch (this->ChipID) { - case DOC_ChipID_Doc2k: - mtd->name = "DiskOnChip 2000"; - this->ioreg = DoC_2k_CDSN_IO; - break; - case DOC_ChipID_DocMil: - mtd->name = "DiskOnChip Millennium"; - this->ioreg = DoC_Mil_CDSN_IO; - break; - } - - printk(KERN_NOTICE "%s found at address 0x%lX\n", mtd->name, - this->physadr); - - mtd->type = MTD_NANDFLASH; - mtd->flags = MTD_CAP_NANDFLASH; - mtd->size = 0; - mtd->erasesize = 0; - mtd->oobblock = 512; - mtd->oobsize = 16; - mtd->module = THIS_MODULE; - mtd->erase = doc_erase; - mtd->point = NULL; - mtd->unpoint = NULL; - mtd->read = doc_read; - mtd->write = doc_write; - mtd->read_ecc = doc_read_ecc; - mtd->write_ecc = doc_write_ecc; - mtd->read_oob = doc_read_oob; - mtd->write_oob = doc_write_oob; - mtd->sync = NULL; - - this->totlen = 0; - this->numchips = 0; - - this->curfloor = -1; - this->curchip = -1; - - /* Ident all the chips present. */ - DoC_ScanChips(this); - - if (!this->totlen) { - kfree(mtd); - iounmap((void *) this->virtadr); - } else { - this->nextdoc = doc2klist; - doc2klist = mtd; - mtd->size = this->totlen; - mtd->erasesize = this->erasesize; - add_mtd_device(mtd); - return; - } -} - -static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, - size_t * retlen, u_char * buf) -{ - /* Just a special case of doc_read_ecc */ - return doc_read_ecc(mtd, from, len, retlen, buf, NULL); -} - -static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, - size_t * retlen, u_char * buf, u_char * eccbuf) -{ - struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv; - unsigned long docptr; - struct Nand *mychip; - unsigned char syndrome[6]; - volatile char dummy; - int i, len256 = 0, ret=0; - - docptr = this->virtadr; - - /* Don't allow read past end of device */ - if (from >= this->totlen) - return -EINVAL; - - /* Don't allow a single read to cross a 512-byte block boundary */ - if (from + len > ((from | 0x1ff) + 1)) - len = ((from | 0x1ff) + 1) - from; - - /* The ECC will not be calculated correctly if less than 512 is read */ - if (len != 0x200 && eccbuf) - printk(KERN_WARNING - "ECC needs a full sector read (adr: %lx size %lx)\n", - (long) from, (long) len); - - /* printk("DoC_Read (adr: %lx size %lx)\n", (long) from, (long) len); */ - - - /* Find the chip which is to be used and select it */ - mychip = &this->chips[from >> (this->chipshift)]; - - if (this->curfloor != mychip->floor) { - DoC_SelectFloor(this, mychip->floor); - DoC_SelectChip(this, mychip->chip); - } else if (this->curchip != mychip->chip) { - DoC_SelectChip(this, mychip->chip); - } - - this->curfloor = mychip->floor; - this->curchip = mychip->chip; - - DoC_Command(this, - (!this->page256 - && (from & 0x100)) ? NAND_CMD_READ1 : NAND_CMD_READ0, - CDSN_CTRL_WP); - DoC_Address(this, ADDR_COLUMN_PAGE, from, CDSN_CTRL_WP, - CDSN_CTRL_ECC_IO); - - if (eccbuf) { - /* Prime the ECC engine */ - WriteDOC(DOC_ECC_RESET, docptr, ECCConf); - WriteDOC(DOC_ECC_EN, docptr, ECCConf); - } else { - /* disable the ECC engine */ - WriteDOC(DOC_ECC_RESET, docptr, ECCConf); - WriteDOC(DOC_ECC_DIS, docptr, ECCConf); - } - - /* treat crossing 256-byte sector for 2M x 8bits devices */ - if (this->page256 && from + len > (from | 0xff) + 1) { - len256 = (from | 0xff) + 1 - from; - DoC_ReadBuf(this, buf, len256); - - DoC_Command(this, NAND_CMD_READ0, CDSN_CTRL_WP); - DoC_Address(this, ADDR_COLUMN_PAGE, from + len256, - CDSN_CTRL_WP, CDSN_CTRL_ECC_IO); - } - - DoC_ReadBuf(this, &buf[len256], len - len256); - - /* Let the caller know we completed it */ - *retlen = len; - - if (eccbuf) { - /* Read the ECC data through the DiskOnChip ECC logic */ - /* Note: this will work even with 2M x 8bit devices as */ - /* they have 8 bytes of OOB per 256 page. mf. */ - DoC_ReadBuf(this, eccbuf, 6); - - /* Flush the pipeline */ - if (DoC_is_Millennium(this)) { - dummy = ReadDOC(docptr, ECCConf); - dummy = ReadDOC(docptr, ECCConf); - i = ReadDOC(docptr, ECCConf); - } else { - dummy = ReadDOC(docptr, 2k_ECCStatus); - dummy = ReadDOC(docptr, 2k_ECCStatus); - i = ReadDOC(docptr, 2k_ECCStatus); - } - - /* Check the ECC Status */ - if (i & 0x80) { - int nb_errors; - /* There was an ECC error */ -#ifdef ECC_DEBUG - printk("DiskOnChip ECC Error: Read at %lx\n", (long)from); -#endif - /* Read the ECC syndrom through the DiskOnChip ECC logic. - These syndrome will be all ZERO when there is no error */ - for (i = 0; i < 6; i++) { - syndrome[i] = - ReadDOC(docptr, ECCSyndrome0 + i); - } - nb_errors = doc_decode_ecc(buf, syndrome); - -#ifdef ECC_DEBUG - printk("Errors corrected: %x\n", nb_errors); -#endif - if (nb_errors < 0) { - /* We return error, but have actually done the read. Not that - this can be told to user-space, via sys_read(), but at least - MTD-aware stuff can know about it by checking *retlen */ - ret = -EIO; - } - } - -#ifdef PSYCHO_DEBUG - printk("ECC DATA at %lxB: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", - (long)from, eccbuf[0], eccbuf[1], eccbuf[2], - eccbuf[3], eccbuf[4], eccbuf[5]); -#endif - - /* disable the ECC engine */ - WriteDOC(DOC_ECC_DIS, docptr , ECCConf); - } - - return ret; -} - -static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, - size_t * retlen, const u_char * buf) -{ - char eccbuf[6]; - return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf); -} - -static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, - size_t * retlen, const u_char * buf, - u_char * eccbuf) -{ - struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv; - int di; /* Yes, DI is a hangover from when I was disassembling the binary driver */ - unsigned long docptr; - volatile char dummy; - int len256 = 0; - struct Nand *mychip; - - docptr = this->virtadr; - - /* Don't allow write past end of device */ - if (to >= this->totlen) - return -EINVAL; - - /* Don't allow a single write to cross a 512-byte block boundary */ - if (to + len > ((to | 0x1ff) + 1)) - len = ((to | 0x1ff) + 1) - to; - - /* The ECC will not be calculated correctly if less than 512 is written */ - if (len != 0x200 && eccbuf) - printk(KERN_WARNING - "ECC needs a full sector write (adr: %lx size %lx)\n", - (long) to, (long) len); - - /* printk("DoC_Write (adr: %lx size %lx)\n", (long) to, (long) len); */ - - /* Find the chip which is to be used and select it */ - mychip = &this->chips[to >> (this->chipshift)]; - - if (this->curfloor != mychip->floor) { - DoC_SelectFloor(this, mychip->floor); - DoC_SelectChip(this, mychip->chip); - } else if (this->curchip != mychip->chip) { - DoC_SelectChip(this, mychip->chip); - } - - this->curfloor = mychip->floor; - this->curchip = mychip->chip; - - /* Set device to main plane of flash */ - DoC_Command(this, NAND_CMD_RESET, CDSN_CTRL_WP); - DoC_Command(this, - (!this->page256 - && (to & 0x100)) ? NAND_CMD_READ1 : NAND_CMD_READ0, - CDSN_CTRL_WP); - - DoC_Command(this, NAND_CMD_SEQIN, 0); - DoC_Address(this, ADDR_COLUMN_PAGE, to, 0, CDSN_CTRL_ECC_IO); - - if (eccbuf) { - /* Prime the ECC engine */ - WriteDOC(DOC_ECC_RESET, docptr, ECCConf); - WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf); - } else { - /* disable the ECC engine */ - WriteDOC(DOC_ECC_RESET, docptr, ECCConf); - WriteDOC(DOC_ECC_DIS, docptr, ECCConf); - } - - /* treat crossing 256-byte sector for 2M x 8bits devices */ - if (this->page256 && to + len > (to | 0xff) + 1) { - len256 = (to | 0xff) + 1 - to; - DoC_WriteBuf(this, buf, len256); - - DoC_Command(this, NAND_CMD_PAGEPROG, 0); - - DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP); - /* There's an implicit DoC_WaitReady() in DoC_Command */ - - dummy = ReadDOC(docptr, CDSNSlowIO); - DoC_Delay(this, 2); - - if (ReadDOC_(docptr, this->ioreg) & 1) { - printk("Error programming flash\n"); - /* Error in programming */ - *retlen = 0; - return -EIO; - } - - DoC_Command(this, NAND_CMD_SEQIN, 0); - DoC_Address(this, ADDR_COLUMN_PAGE, to + len256, 0, - CDSN_CTRL_ECC_IO); - } - - DoC_WriteBuf(this, &buf[len256], len - len256); - - if (eccbuf) { - WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_CE, docptr, - CDSNControl); - - if (DoC_is_Millennium(this)) { - WriteDOC(0, docptr, NOP); - WriteDOC(0, docptr, NOP); - WriteDOC(0, docptr, NOP); - } else { - WriteDOC_(0, docptr, this->ioreg); - WriteDOC_(0, docptr, this->ioreg); - WriteDOC_(0, docptr, this->ioreg); - } - - /* Read the ECC data through the DiskOnChip ECC logic */ - for (di = 0; di < 6; di++) { - eccbuf[di] = ReadDOC(docptr, ECCSyndrome0 + di); - } - - /* Reset the ECC engine */ - WriteDOC(DOC_ECC_DIS, docptr, ECCConf); - -#ifdef PSYCHO_DEBUG - printk - ("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", - (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], - eccbuf[4], eccbuf[5]); -#endif - } - - DoC_Command(this, NAND_CMD_PAGEPROG, 0); - - DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP); - /* There's an implicit DoC_WaitReady() in DoC_Command */ - - dummy = ReadDOC(docptr, CDSNSlowIO); - DoC_Delay(this, 2); - - if (ReadDOC_(docptr, this->ioreg) & 1) { - printk("Error programming flash\n"); - /* Error in programming */ - *retlen = 0; - return -EIO; - } - - /* Let the caller know we completed it */ - *retlen = len; - - if (eccbuf) { - unsigned char x[8]; - size_t dummy; - - /* Write the ECC data to flash */ - for (di=0; di<6; di++) - x[di] = eccbuf[di]; - - x[6]=0x55; - x[7]=0x55; - - return doc_write_oob(mtd, to, 8, &dummy, x); - } - - return 0; -} - -static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, - size_t * retlen, u_char * buf) -{ - struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv; - int len256 = 0; - unsigned long docptr; - struct Nand *mychip; - - docptr = this->virtadr; - - mychip = &this->chips[ofs >> this->chipshift]; - - if (this->curfloor != mychip->floor) { - DoC_SelectFloor(this, mychip->floor); - DoC_SelectChip(this, mychip->chip); - } else if (this->curchip != mychip->chip) { - DoC_SelectChip(this, mychip->chip); - } - this->curfloor = mychip->floor; - this->curchip = mychip->chip; - - /* update address for 2M x 8bit devices. OOB starts on the second */ - /* page to maintain compatibility with doc_read_ecc. */ - if (this->page256) { - if (!(ofs & 0x8)) - ofs += 0x100; - else - ofs -= 0x8; - } - - DoC_Command(this, NAND_CMD_READOOB, CDSN_CTRL_WP); - DoC_Address(this, ADDR_COLUMN_PAGE, ofs, CDSN_CTRL_WP, 0); - - /* treat crossing 8-byte OOB data for 2M x 8bit devices */ - /* Note: datasheet says it should automaticaly wrap to the */ - /* next OOB block, but it didn't work here. mf. */ - if (this->page256 && ofs + len > (ofs | 0x7) + 1) { - len256 = (ofs | 0x7) + 1 - ofs; - DoC_ReadBuf(this, buf, len256); - - DoC_Command(this, NAND_CMD_READOOB, CDSN_CTRL_WP); - DoC_Address(this, ADDR_COLUMN_PAGE, ofs & (~0x1ff), - CDSN_CTRL_WP, 0); - } - - DoC_ReadBuf(this, &buf[len256], len - len256); - - *retlen = len; - return 0; - -} - -static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, - size_t * retlen, const u_char * buf) -{ - struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv; - int len256 = 0; - unsigned long docptr = this->virtadr; - struct Nand *mychip = &this->chips[ofs >> this->chipshift]; - int dummy; - - // printk("doc_write_oob(%lx, %d): %2.2X %2.2X %2.2X %2.2X ... %2.2X %2.2X .. %2.2X %2.2X\n",(long)ofs, len, - // buf[0], buf[1], buf[2], buf[3], buf[8], buf[9], buf[14],buf[15]); - - /* Find the chip which is to be used and select it */ - if (this->curfloor != mychip->floor) { - DoC_SelectFloor(this, mychip->floor); - DoC_SelectChip(this, mychip->chip); - } else if (this->curchip != mychip->chip) { - DoC_SelectChip(this, mychip->chip); - } - this->curfloor = mychip->floor; - this->curchip = mychip->chip; - - /* disable the ECC engine */ - WriteDOC (DOC_ECC_RESET, docptr, ECCConf); - WriteDOC (DOC_ECC_DIS, docptr, ECCConf); - - /* Reset the chip, see Software Requirement 11.4 item 1. */ - DoC_Command(this, NAND_CMD_RESET, CDSN_CTRL_WP); - - /* issue the Read2 command to set the pointer to the Spare Data Area. */ - DoC_Command(this, NAND_CMD_READOOB, CDSN_CTRL_WP); - - /* update address for 2M x 8bit devices. OOB starts on the second */ - /* page to maintain compatibility with doc_read_ecc. */ - if (this->page256) { - if (!(ofs & 0x8)) - ofs += 0x100; - else - ofs -= 0x8; - } - - /* issue the Serial Data In command to initial the Page Program process */ - DoC_Command(this, NAND_CMD_SEQIN, 0); - DoC_Address(this, ADDR_COLUMN_PAGE, ofs, 0, 0); - - /* treat crossing 8-byte OOB data for 2M x 8bit devices */ - /* Note: datasheet says it should automaticaly wrap to the */ - /* next OOB block, but it didn't work here. mf. */ - if (this->page256 && ofs + len > (ofs | 0x7) + 1) { - len256 = (ofs | 0x7) + 1 - ofs; - DoC_WriteBuf(this, buf, len256); - - DoC_Command(this, NAND_CMD_PAGEPROG, 0); - DoC_Command(this, NAND_CMD_STATUS, 0); - /* DoC_WaitReady() is implicit in DoC_Command */ - - dummy = ReadDOC(docptr, CDSNSlowIO); - DoC_Delay(this, 2); - - if (ReadDOC_(docptr, this->ioreg) & 1) { - printk("Error programming oob data\n"); - /* There was an error */ - *retlen = 0; - return -EIO; - } - DoC_Command(this, NAND_CMD_SEQIN, 0); - DoC_Address(this, ADDR_COLUMN_PAGE, ofs & (~0x1ff), 0, 0); - } - - DoC_WriteBuf(this, &buf[len256], len - len256); - - DoC_Command(this, NAND_CMD_PAGEPROG, 0); - DoC_Command(this, NAND_CMD_STATUS, 0); - /* DoC_WaitReady() is implicit in DoC_Command */ - - dummy = ReadDOC(docptr, CDSNSlowIO); - DoC_Delay(this, 2); - - if (ReadDOC_(docptr, this->ioreg) & 1) { - printk("Error programming oob data\n"); - /* There was an error */ - *retlen = 0; - return -EIO; - } - - *retlen = len; - return 0; - -} - -int doc_erase(struct mtd_info *mtd, struct erase_info *instr) -{ - struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv; - unsigned long ofs = instr->addr; - unsigned long len = instr->len; - unsigned long docptr; - struct Nand *mychip; - - if (len != mtd->erasesize) - printk(KERN_WARNING "Erase not right size (%lx != %lx)n", - len, mtd->erasesize); - - docptr = this->virtadr; - - mychip = &this->chips[ofs >> this->chipshift]; - - if (this->curfloor != mychip->floor) { - DoC_SelectFloor(this, mychip->floor); - DoC_SelectChip(this, mychip->chip); - } else if (this->curchip != mychip->chip) { - DoC_SelectChip(this, mychip->chip); - } - this->curfloor = mychip->floor; - this->curchip = mychip->chip; - - instr->state = MTD_ERASE_PENDING; - - DoC_Command(this, NAND_CMD_ERASE1, 0); - DoC_Address(this, ADDR_PAGE, ofs, 0, 0); - DoC_Command(this, NAND_CMD_ERASE2, 0); - - instr->state = MTD_ERASING; - - DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP); - - if (ReadDOC_(docptr, this->ioreg) & 1) { - printk("Error writing\n"); - /* There was an error */ - instr->state = MTD_ERASE_FAILED; - } else - instr->state = MTD_ERASE_DONE; - - if (instr->callback) - instr->callback(instr); - - return 0; -} - - -/**************************************************************************** - * - * Module stuff - * - ****************************************************************************/ - -#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) -#define cleanup_doc2000 cleanup_module -#define init_doc2000 init_module -#endif - -int __init init_doc2000(void) -{ - inter_module_register(im_name, THIS_MODULE, &DoC2k_init); - return 0; -} - -static void __exit cleanup_doc2000(void) -{ - struct mtd_info *mtd; - struct DiskOnChip *this; - - while ((mtd = doc2klist)) { - this = (struct DiskOnChip *) mtd->priv; - doc2klist = this->nextdoc; - - del_mtd_device(mtd); - - iounmap((void *) this->virtadr); - kfree(this->chips); - kfree(mtd); - } - inter_module_unregister(im_name); -} - -module_exit(cleanup_doc2000); -module_init(init_doc2000); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/doc2001.c linux/drivers/mtd/doc2001.c --- v2.4.5/linux/drivers/mtd/doc2001.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/mtd/doc2001.c Wed Dec 31 16:00:00 1969 @@ -1,883 +0,0 @@ - -/* - * Linux driver for Disk-On-Chip Millennium - * (c) 1999 Machine Vision Holdings, Inc. - * (c) 1999, 2000 David Woodhouse - * - * $Id: doc2001.c,v 1.24 2000/12/01 13:11:02 dwmw2 Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* #define ECC_DEBUG */ - -/* I have no idea why some DoC chips can not use memcop_form|to_io(). - * This may be due to the different revisions of the ASIC controller built-in or - * simplily a QA/Bug issue. Who knows ?? If you have trouble, please uncomment - * this: - #undef USE_MEMCPY -*/ - -static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf); -static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf); -static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf, u_char *eccbuf); -static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf, u_char *eccbuf); -static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, - size_t *retlen, u_char *buf); -static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, - size_t *retlen, const u_char *buf); -static int doc_erase (struct mtd_info *mtd, struct erase_info *instr); - -static struct mtd_info *docmillist = NULL; - -/* Perform the required delay cycles by reading from the NOP register */ -static void DoC_Delay(unsigned long docptr, unsigned short cycles) -{ - volatile char dummy; - int i; - - for (i = 0; i < cycles; i++) - dummy = ReadDOC(docptr, NOP); -} - -/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */ -static int _DoC_WaitReady(unsigned long docptr) -{ - unsigned short c = 0xffff; - - DEBUG(MTD_DEBUG_LEVEL3, - "_DoC_WaitReady called for out-of-line wait\n"); - - /* Out-of-line routine to wait for chip response */ - while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B) && --c) - ; - - if (c == 0) - DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n"); - - return (c == 0); -} - -static inline int DoC_WaitReady(unsigned long docptr) -{ - /* This is inline, to optimise the common case, where it's ready instantly */ - int ret = 0; - - /* 4 read form NOP register should be issued in prior to the read from CDSNControl - see Software Requirement 11.4 item 2. */ - DoC_Delay(docptr, 4); - - if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) - /* Call the out-of-line routine to wait */ - ret = _DoC_WaitReady(docptr); - - /* issue 2 read from NOP register after reading from CDSNControl register - see Software Requirement 11.4 item 2. */ - DoC_Delay(docptr, 2); - - return ret; -} - -/* DoC_Command: Send a flash command to the flash chip through the CDSN Slow IO register to - bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is - required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */ - -static inline void DoC_Command(unsigned long docptr, unsigned char command, - unsigned char xtraflags) -{ - /* Assert the CLE (Command Latch Enable) line to the flash chip */ - WriteDOC(xtraflags | CDSN_CTRL_CLE | CDSN_CTRL_CE, docptr, CDSNControl); - DoC_Delay(docptr, 4); - - /* Send the command */ - WriteDOC(command, docptr, CDSNSlowIO); - WriteDOC(command, docptr, Mil_CDSN_IO); - - /* Lower the CLE line */ - WriteDOC(xtraflags | CDSN_CTRL_CE, docptr, CDSNControl); - DoC_Delay(docptr, 4); -} - -/* DoC_Address: Set the current address for the flash chip through the CDSN Slow IO register to - bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is - required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */ - -static inline void DoC_Address(unsigned long docptr, int numbytes, unsigned long ofs, - unsigned char xtraflags1, unsigned char xtraflags2) -{ - /* Assert the ALE (Address Latch Enable) line to the flash chip */ - WriteDOC(xtraflags1 | CDSN_CTRL_ALE | CDSN_CTRL_CE, docptr, CDSNControl); - DoC_Delay(docptr, 4); - - /* Send the address */ - switch (numbytes) - { - case 1: - /* Send single byte, bits 0-7. */ - WriteDOC(ofs & 0xff, docptr, CDSNSlowIO); - WriteDOC(ofs & 0xff, docptr, Mil_CDSN_IO); - break; - case 2: - /* Send bits 9-16 followed by 17-23 */ - WriteDOC((ofs >> 9) & 0xff, docptr, CDSNSlowIO); - WriteDOC((ofs >> 9) & 0xff, docptr, Mil_CDSN_IO); - WriteDOC((ofs >> 17) & 0xff, docptr, CDSNSlowIO); - WriteDOC((ofs >> 17) & 0xff, docptr, Mil_CDSN_IO); - break; - case 3: - /* Send 0-7, 9-16, then 17-23 */ - WriteDOC(ofs & 0xff, docptr, CDSNSlowIO); - WriteDOC(ofs & 0xff, docptr, Mil_CDSN_IO); - WriteDOC((ofs >> 9) & 0xff, docptr, CDSNSlowIO); - WriteDOC((ofs >> 9) & 0xff, docptr, Mil_CDSN_IO); - WriteDOC((ofs >> 17) & 0xff, docptr, CDSNSlowIO); - WriteDOC((ofs >> 17) & 0xff, docptr, Mil_CDSN_IO); - break; - default: - return; - } - - /* Lower the ALE line */ - WriteDOC(xtraflags1 | xtraflags2 | CDSN_CTRL_CE, docptr, CDSNControl); - DoC_Delay(docptr, 4); -} - -/* DoC_SelectChip: Select a given flash chip within the current floor */ -static int DoC_SelectChip(unsigned long docptr, int chip) -{ - /* Select the individual flash chip requested */ - WriteDOC(chip, docptr, CDSNDeviceSelect); - DoC_Delay(docptr, 4); - - /* Wait for it to be ready */ - return DoC_WaitReady(docptr); -} - -/* DoC_SelectFloor: Select a given floor (bank of flash chips) */ -static int DoC_SelectFloor(unsigned long docptr, int floor) -{ - /* Select the floor (bank) of chips required */ - WriteDOC(floor, docptr, FloorSelect); - - /* Wait for the chip to be ready */ - return DoC_WaitReady(docptr); -} - -/* DoC_IdentChip: Identify a given NAND chip given {floor,chip} */ -static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip) -{ - int mfr, id, i; - volatile char dummy; - - /* Page in the required floor/chip - FIXME: is this supported by Millennium ?? */ - DoC_SelectFloor(doc->virtadr, floor); - DoC_SelectChip(doc->virtadr, chip); - - /* Reset the chip, see Software Requirement 11.4 item 1. */ - DoC_Command(doc->virtadr, NAND_CMD_RESET, CDSN_CTRL_WP); - DoC_WaitReady(doc->virtadr); - - /* Read the NAND chip ID: 1. Send ReadID command */ - DoC_Command(doc->virtadr, NAND_CMD_READID, CDSN_CTRL_WP); - - /* Read the NAND chip ID: 2. Send address byte zero */ - DoC_Address(doc->virtadr, 1, 0x00, CDSN_CTRL_WP, 0x00); - - /* Read the manufacturer and device id codes of the flash device through - CDSN Slow IO register see Software Requirement 11.4 item 5.*/ - dummy = ReadDOC(doc->virtadr, CDSNSlowIO); - DoC_Delay(doc->virtadr, 2); - mfr = ReadDOC(doc->virtadr, Mil_CDSN_IO); - - dummy = ReadDOC(doc->virtadr, CDSNSlowIO); - DoC_Delay(doc->virtadr, 2); - id = ReadDOC(doc->virtadr, Mil_CDSN_IO); - - /* No response - return failure */ - if (mfr == 0xff || mfr == 0) - return 0; - - /* FIXME: to deal with multi-flash on multi-Millennium case more carefully */ - for (i = 0; nand_flash_ids[i].name != NULL; i++) { - if (mfr == nand_flash_ids[i].manufacture_id && - id == nand_flash_ids[i].model_id) { - printk(KERN_INFO "Flash chip found: Manufacturer ID: %2.2X, " - "Chip ID: %2.2X (%s)\n", - mfr, id, nand_flash_ids[i].name); - doc->mfr = mfr; - doc->id = id; - doc->chipshift = nand_flash_ids[i].chipshift; - break; - } - } - - if (nand_flash_ids[i].name == NULL) - return 0; - else - return 1; -} - -/* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */ -static void DoC_ScanChips(struct DiskOnChip *this) -{ - int floor, chip; - int numchips[MAX_FLOORS_MIL]; - int ret; - - this->numchips = 0; - this->mfr = 0; - this->id = 0; - - /* For each floor, find the number of valid chips it contains */ - for (floor = 0,ret = 1; floor < MAX_FLOORS_MIL; floor++) { - numchips[floor] = 0; - for (chip = 0; chip < MAX_CHIPS_MIL && ret != 0; chip++) { - ret = DoC_IdentChip(this, floor, chip); - if (ret) { - numchips[floor]++; - this->numchips++; - } - } - } - /* If there are none at all that we recognise, bail */ - if (!this->numchips) { - printk("No flash chips recognised.\n"); - return; - } - - /* Allocate an array to hold the information for each chip */ - this->chips = kmalloc(sizeof(struct Nand) * this->numchips, GFP_KERNEL); - if (!this->chips){ - printk("No memory for allocating chip info structures\n"); - return; - } - - /* Fill out the chip array with {floor, chipno} for each - * detected chip in the device. */ - for (floor = 0, ret = 0; floor < MAX_FLOORS_MIL; floor++) { - for (chip = 0 ; chip < numchips[floor] ; chip++) { - this->chips[ret].floor = floor; - this->chips[ret].chip = chip; - this->chips[ret].curadr = 0; - this->chips[ret].curmode = 0x50; - ret++; - } - } - - /* Calculate and print the total size of the device */ - this->totlen = this->numchips * (1 << this->chipshift); - printk(KERN_NOTICE "%d flash chips found. Total DiskOnChip size: %ld Mbytes\n", - this->numchips ,this->totlen >> 20); -} - -static int DoCMil_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2) -{ - int tmp1, tmp2, retval; - - if (doc1->physadr == doc2->physadr) - return 1; - - /* Use the alias resolution register which was set aside for this - * purpose. If it's value is the same on both chips, they might - * be the same chip, and we write to one and check for a change in - * the other. It's unclear if this register is usuable in the - * DoC 2000 (it's in the Millenium docs), but it seems to work. */ - tmp1 = ReadDOC(doc1->virtadr, AliasResolution); - tmp2 = ReadDOC(doc2->virtadr, AliasResolution); - if (tmp1 != tmp2) - return 0; - - WriteDOC((tmp1+1) % 0xff, doc1->virtadr, AliasResolution); - tmp2 = ReadDOC(doc2->virtadr, AliasResolution); - if (tmp2 == (tmp1+1) % 0xff) - retval = 1; - else - retval = 0; - - /* Restore register contents. May not be necessary, but do it just to - * be safe. */ - WriteDOC(tmp1, doc1->virtadr, AliasResolution); - - return retval; -} - -static const char im_name[] = "DoCMil_init"; - -/* This routine is made available to other mtd code via - * inter_module_register. It must only be accessed through - * inter_module_get which will bump the use count of this module. The - * addresses passed back in mtd are valid as long as the use count of - * this module is non-zero, i.e. between inter_module_get and - * inter_module_put. Keith Owens 29 Oct 2000. - */ -static void DoCMil_init(struct mtd_info *mtd) -{ - struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; - struct DiskOnChip *old = NULL; - - /* We must avoid being called twice for the same device. */ - if (docmillist) - old = (struct DiskOnChip *)docmillist->priv; - - while (old) { - if (DoCMil_is_alias(this, old)) { - printk(KERN_NOTICE "Ignoring DiskOnChip Millennium at " - "0x%lX - already configured\n", this->physadr); - iounmap((void *)this->virtadr); - kfree(mtd); - return; - } - if (old->nextdoc) - old = (struct DiskOnChip *)old->nextdoc->priv; - else - old = NULL; - } - - mtd->name = "DiskOnChip Millennium"; - printk(KERN_NOTICE "DiskOnChip Millennium found at address 0x%lX\n", - this->physadr); - - mtd->type = MTD_NANDFLASH; - mtd->flags = MTD_CAP_NANDFLASH; - mtd->size = 0; - - /* FIXME: erase size is not always 8kB */ - mtd->erasesize = 0x2000; - - mtd->oobblock = 512; - mtd->oobsize = 16; - mtd->module = THIS_MODULE; - mtd->erase = doc_erase; - mtd->point = NULL; - mtd->unpoint = NULL; - mtd->read = doc_read; - mtd->write = doc_write; - mtd->read_ecc = doc_read_ecc; - mtd->write_ecc = doc_write_ecc; - mtd->read_oob = doc_read_oob; - mtd->write_oob = doc_write_oob; - mtd->sync = NULL; - - this->totlen = 0; - this->numchips = 0; - this->curfloor = -1; - this->curchip = -1; - - /* Ident all the chips present. */ - DoC_ScanChips(this); - - if (!this->totlen) { - kfree(mtd); - iounmap((void *)this->virtadr); - } else { - this->nextdoc = docmillist; - docmillist = mtd; - mtd->size = this->totlen; - add_mtd_device(mtd); - return; - } -} - -static int doc_read (struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf) -{ - /* Just a special case of doc_read_ecc */ - return doc_read_ecc(mtd, from, len, retlen, buf, NULL); -} - -static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf, u_char *eccbuf) -{ - int i, ret; - volatile char dummy; - unsigned char syndrome[6]; - struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; - unsigned long docptr = this->virtadr; - struct Nand *mychip = &this->chips[from >> (this->chipshift)]; - - /* Don't allow read past end of device */ - if (from >= this->totlen) - return -EINVAL; - - /* Don't allow a single read to cross a 512-byte block boundary */ - if (from + len > ((from | 0x1ff) + 1)) - len = ((from | 0x1ff) + 1) - from; - - /* Find the chip which is to be used and select it */ - if (this->curfloor != mychip->floor) { - DoC_SelectFloor(docptr, mychip->floor); - DoC_SelectChip(docptr, mychip->chip); - } else if (this->curchip != mychip->chip) { - DoC_SelectChip(docptr, mychip->chip); - } - this->curfloor = mychip->floor; - this->curchip = mychip->chip; - - /* issue the Read0 or Read1 command depend on which half of the page - we are accessing. Polling the Flash Ready bit after issue 3 bytes - address in Sequence Read Mode, see Software Requirement 11.4 item 1.*/ - DoC_Command(docptr, (from >> 8) & 1, CDSN_CTRL_WP); - DoC_Address(docptr, 3, from, CDSN_CTRL_WP, 0x00); - DoC_WaitReady(docptr); - - if (eccbuf) { - /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/ - WriteDOC (DOC_ECC_RESET, docptr, ECCConf); - WriteDOC (DOC_ECC_EN, docptr, ECCConf); - } else { - /* disable the ECC engine */ - WriteDOC (DOC_ECC_RESET, docptr, ECCConf); - WriteDOC (DOC_ECC_DIS, docptr, ECCConf); - } - - /* Read the data via the internal pipeline through CDSN IO register, - see Pipelined Read Operations 11.3 */ - dummy = ReadDOC(docptr, ReadPipeInit); -#ifndef USE_MEMCPY - for (i = 0; i < len-1; i++) { - /* N.B. you have to increase the source address in this way or the - ECC logic will not work properly */ - buf[i] = ReadDOC(docptr, Mil_CDSN_IO + (i & 0xff)); - } -#else - memcpy_fromio(buf, docptr + DoC_Mil_CDSN_IO, len - 1); -#endif - buf[len - 1] = ReadDOC(docptr, LastDataRead); - - /* Let the caller know we completed it */ - *retlen = len; - ret = 0; - - if (eccbuf) { - /* Read the ECC data from Spare Data Area, - see Reed-Solomon EDC/ECC 11.1 */ - dummy = ReadDOC(docptr, ReadPipeInit); -#ifndef USE_MEMCPY - for (i = 0; i < 5; i++) { - /* N.B. you have to increase the source address in this way or the - ECC logic will not work properly */ - eccbuf[i] = ReadDOC(docptr, Mil_CDSN_IO + i); - } -#else - memcpy_fromio(eccbuf, docptr + DoC_Mil_CDSN_IO, 5); -#endif - eccbuf[5] = ReadDOC(docptr, LastDataRead); - - /* Flush the pipeline */ - dummy = ReadDOC(docptr, ECCConf); - dummy = ReadDOC(docptr, ECCConf); - - /* Check the ECC Status */ - if (ReadDOC(docptr, ECCConf) & 0x80) { - int nb_errors; - /* There was an ECC error */ -#ifdef ECC_DEBUG - printk("DiskOnChip ECC Error: Read at %lx\n", (long)from); -#endif - /* Read the ECC syndrom through the DiskOnChip ECC logic. - These syndrome will be all ZERO when there is no error */ - for (i = 0; i < 6; i++) { - syndrome[i] = ReadDOC(docptr, ECCSyndrome0 + i); - } - nb_errors = doc_decode_ecc(buf, syndrome); -#ifdef ECC_DEBUG - printk("Errors corrected: %x\n", nb_errors); -#endif - if (nb_errors < 0) { - /* We return error, but have actually done the read. Not that - this can be told to user-space, via sys_read(), but at least - MTD-aware stuff can know about it by checking *retlen */ - ret = -EIO; - } - } - -#ifdef PSYCHO_DEBUG - printk("ECC DATA at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", - (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], - eccbuf[4], eccbuf[5]); -#endif - /* disable the ECC engine */ - WriteDOC(DOC_ECC_DIS, docptr , ECCConf); - } - - return ret; -} - -static int doc_write (struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf) -{ - char eccbuf[6]; - return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf); -} - -static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf, u_char *eccbuf) -{ - int i; - volatile char dummy; - struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; - unsigned long docptr = this->virtadr; - struct Nand *mychip = &this->chips[to >> (this->chipshift)]; - - /* Don't allow write past end of device */ - if (to >= this->totlen) - return -EINVAL; - -#if 0 - /* Don't allow a single write to cross a 512-byte block boundary */ - if (to + len > ( (to | 0x1ff) + 1)) - len = ((to | 0x1ff) + 1) - to; -#else - /* Don't allow writes which aren't exactly one block */ - if (to & 0x1ff || len != 0x200) - return -EINVAL; -#endif - - /* Find the chip which is to be used and select it */ - if (this->curfloor != mychip->floor) { - DoC_SelectFloor(docptr, mychip->floor); - DoC_SelectChip(docptr, mychip->chip); - } else if (this->curchip != mychip->chip) { - DoC_SelectChip(docptr, mychip->chip); - } - this->curfloor = mychip->floor; - this->curchip = mychip->chip; - - /* Reset the chip, see Software Requirement 11.4 item 1. */ - DoC_Command(docptr, NAND_CMD_RESET, 0x00); - DoC_WaitReady(docptr); - /* Set device to main plane of flash */ - DoC_Command(docptr, NAND_CMD_READ0, 0x00); - - /* issue the Serial Data In command to initial the Page Program process */ - DoC_Command(docptr, NAND_CMD_SEQIN, 0x00); - DoC_Address(docptr, 3, to, 0x00, 0x00); - DoC_WaitReady(docptr); - - if (eccbuf) { - /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/ - WriteDOC (DOC_ECC_RESET, docptr, ECCConf); - WriteDOC (DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf); - } else { - /* disable the ECC engine */ - WriteDOC (DOC_ECC_RESET, docptr, ECCConf); - WriteDOC (DOC_ECC_DIS, docptr, ECCConf); - } - - /* Write the data via the internal pipeline through CDSN IO register, - see Pipelined Write Operations 11.2 */ -#ifndef USE_MEMCPY - for (i = 0; i < len; i++) { - /* N.B. you have to increase the source address in this way or the - ECC logic will not work properly */ - WriteDOC(buf[i], docptr, Mil_CDSN_IO + i); - } -#else - memcpy_toio(docptr + DoC_Mil_CDSN_IO, buf, len); -#endif - WriteDOC(0x00, docptr, WritePipeTerm); - - if (eccbuf) { - /* Write ECC data to flash, the ECC info is generated by the DiskOnChip ECC logic - see Reed-Solomon EDC/ECC 11.1 */ - WriteDOC(0, docptr, NOP); - WriteDOC(0, docptr, NOP); - WriteDOC(0, docptr, NOP); - - /* Read the ECC data through the DiskOnChip ECC logic */ - for (i = 0; i < 6; i++) { - eccbuf[i] = ReadDOC(docptr, ECCSyndrome0 + i); - } - - /* ignore the ECC engine */ - WriteDOC(DOC_ECC_DIS, docptr , ECCConf); - -#ifndef USE_MEMCPY - /* Write the ECC data to flash */ - for (i = 0; i < 6; i++) { - /* N.B. you have to increase the source address in this way or the - ECC logic will not work properly */ - WriteDOC(eccbuf[i], docptr, Mil_CDSN_IO + i); - } -#else - memcpy_toio(docptr + DoC_Mil_CDSN_IO, eccbuf, 6); -#endif - - /* write the block status BLOCK_USED (0x5555) at the end of ECC data - FIXME: this is only a hack for programming the IPL area for LinuxBIOS - and should be replace with proper codes in user space utilities */ - WriteDOC(0x55, docptr, Mil_CDSN_IO); - WriteDOC(0x55, docptr, Mil_CDSN_IO + 1); - - WriteDOC(0x00, docptr, WritePipeTerm); - -#ifdef PSYCHO_DEBUG - printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", - (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], - eccbuf[4], eccbuf[5]); -#endif - } - - /* Commit the Page Program command and wait for ready - see Software Requirement 11.4 item 1.*/ - DoC_Command(docptr, NAND_CMD_PAGEPROG, 0x00); - DoC_WaitReady(docptr); - - /* Read the status of the flash device through CDSN Slow IO register - see Software Requirement 11.4 item 5.*/ - DoC_Command(docptr, NAND_CMD_STATUS, CDSN_CTRL_WP); - dummy = ReadDOC(docptr, CDSNSlowIO); - DoC_Delay(docptr, 2); - if (ReadDOC(docptr, Mil_CDSN_IO) & 1) { - printk("Error programming flash\n"); - /* Error in programming - FIXME: implement Bad Block Replacement (in nftl.c ??) */ - *retlen = 0; - return -EIO; - } - - /* Let the caller know we completed it */ - *retlen = len; - - return 0; -} - -static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, - size_t *retlen, u_char *buf) -{ -#ifndef USE_MEMCPY - int i; -#endif - volatile char dummy; - struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; - unsigned long docptr = this->virtadr; - struct Nand *mychip = &this->chips[ofs >> this->chipshift]; - - /* Find the chip which is to be used and select it */ - if (this->curfloor != mychip->floor) { - DoC_SelectFloor(docptr, mychip->floor); - DoC_SelectChip(docptr, mychip->chip); - } else if (this->curchip != mychip->chip) { - DoC_SelectChip(docptr, mychip->chip); - } - this->curfloor = mychip->floor; - this->curchip = mychip->chip; - - /* disable the ECC engine */ - WriteDOC (DOC_ECC_RESET, docptr, ECCConf); - WriteDOC (DOC_ECC_DIS, docptr, ECCConf); - - /* issue the Read2 command to set the pointer to the Spare Data Area. - Polling the Flash Ready bit after issue 3 bytes address in - Sequence Read Mode, see Software Requirement 11.4 item 1.*/ - DoC_Command(docptr, NAND_CMD_READOOB, CDSN_CTRL_WP); - DoC_Address(docptr, 3, ofs, CDSN_CTRL_WP, 0x00); - DoC_WaitReady(docptr); - - /* Read the data out via the internal pipeline through CDSN IO register, - see Pipelined Read Operations 11.3 */ - dummy = ReadDOC(docptr, ReadPipeInit); -#ifndef USE_MEMCPY - for (i = 0; i < len-1; i++) { - /* N.B. you have to increase the source address in this way or the - ECC logic will not work properly */ - buf[i] = ReadDOC(docptr, Mil_CDSN_IO + i); - } - buf[i] = ReadDOC(docptr, LastDataRead); -#else - memcpy_fromio(buf, docptr + DoC_Mil_CDSN_IO, len - 1); -#endif - buf[len - 1] = ReadDOC(docptr, LastDataRead); - - *retlen = len; - - return 0; -} - -static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, - size_t *retlen, const u_char *buf) -{ -#ifndef USE_MEMCPY - int i; -#endif - volatile char dummy; - struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; - unsigned long docptr = this->virtadr; - struct Nand *mychip = &this->chips[ofs >> this->chipshift]; - - /* Find the chip which is to be used and select it */ - if (this->curfloor != mychip->floor) { - DoC_SelectFloor(docptr, mychip->floor); - DoC_SelectChip(docptr, mychip->chip); - } else if (this->curchip != mychip->chip) { - DoC_SelectChip(docptr, mychip->chip); - } - this->curfloor = mychip->floor; - this->curchip = mychip->chip; - - /* disable the ECC engine */ - WriteDOC (DOC_ECC_RESET, docptr, ECCConf); - WriteDOC (DOC_ECC_DIS, docptr, ECCConf); - - /* Reset the chip, see Software Requirement 11.4 item 1. */ - DoC_Command(docptr, NAND_CMD_RESET, CDSN_CTRL_WP); - DoC_WaitReady(docptr); - /* issue the Read2 command to set the pointer to the Spare Data Area. */ - DoC_Command(docptr, NAND_CMD_READOOB, CDSN_CTRL_WP); - - /* issue the Serial Data In command to initial the Page Program process */ - DoC_Command(docptr, NAND_CMD_SEQIN, 0x00); - DoC_Address(docptr, 3, ofs, 0x00, 0x00); - - /* Write the data via the internal pipeline through CDSN IO register, - see Pipelined Write Operations 11.2 */ -#ifndef USE_MEMCPY - for (i = 0; i < len; i++) { - /* N.B. you have to increase the source address in this way or the - ECC logic will not work properly */ - WriteDOC(buf[i], docptr, Mil_CDSN_IO + i); - } -#else - memcpy_toio(docptr + DoC_Mil_CDSN_IO, buf, len); -#endif - WriteDOC(0x00, docptr, WritePipeTerm); - - /* Commit the Page Program command and wait for ready - see Software Requirement 11.4 item 1.*/ - DoC_Command(docptr, NAND_CMD_PAGEPROG, 0x00); - DoC_WaitReady(docptr); - - /* Read the status of the flash device through CDSN Slow IO register - see Software Requirement 11.4 item 5.*/ - DoC_Command(docptr, NAND_CMD_STATUS, 0x00); - dummy = ReadDOC(docptr, CDSNSlowIO); - DoC_Delay(docptr, 2); - if (ReadDOC(docptr, Mil_CDSN_IO) & 1) { - printk("Error programming oob data\n"); - /* FIXME: implement Bad Block Replacement (in nftl.c ??) */ - *retlen = 0; - return -EIO; - } - - *retlen = len; - - return 0; -} - -int doc_erase (struct mtd_info *mtd, struct erase_info *instr) -{ - volatile char dummy; - struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; - unsigned long ofs = instr->addr; - unsigned long len = instr->len; - unsigned long docptr = this->virtadr; - struct Nand *mychip = &this->chips[ofs >> this->chipshift]; - - if (len != mtd->erasesize) - printk(KERN_WARNING "Erase not right size (%lx != %lx)n", - len, mtd->erasesize); - - /* Find the chip which is to be used and select it */ - if (this->curfloor != mychip->floor) { - DoC_SelectFloor(docptr, mychip->floor); - DoC_SelectChip(docptr, mychip->chip); - } else if (this->curchip != mychip->chip) { - DoC_SelectChip(docptr, mychip->chip); - } - this->curfloor = mychip->floor; - this->curchip = mychip->chip; - - instr->state = MTD_ERASE_PENDING; - - /* issue the Erase Setup command */ - DoC_Command(docptr, NAND_CMD_ERASE1, 0x00); - DoC_Address(docptr, 2, ofs, 0x00, 0x00); - - /* Commit the Erase Start command and wait for ready - see Software Requirement 11.4 item 1.*/ - DoC_Command(docptr, NAND_CMD_ERASE2, 0x00); - DoC_WaitReady(docptr); - - instr->state = MTD_ERASING; - - /* Read the status of the flash device through CDSN Slow IO register - see Software Requirement 11.4 item 5. - FIXME: it seems that we are not wait long enough, some blocks are not - erased fully */ - DoC_Command(docptr, NAND_CMD_STATUS, CDSN_CTRL_WP); - dummy = ReadDOC(docptr, CDSNSlowIO); - DoC_Delay(docptr, 2); - if (ReadDOC(docptr, Mil_CDSN_IO) & 1) { - printk("Error Erasing at 0x%lx\n", ofs); - /* There was an error - FIXME: implement Bad Block Replacement (in nftl.c ??) */ - instr->state = MTD_ERASE_FAILED; - } else - instr->state = MTD_ERASE_DONE; - - if (instr->callback) - instr->callback(instr); - - return 0; -} - -/**************************************************************************** - * - * Module stuff - * - ****************************************************************************/ - -#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) -#define cleanup_doc2001 cleanup_module -#define init_doc2001 init_module -#endif - -int __init init_doc2001(void) -{ - inter_module_register(im_name, THIS_MODULE, &DoCMil_init); - return 0; -} - -static void __exit cleanup_doc2001(void) -{ - struct mtd_info *mtd; - struct DiskOnChip *this; - - while((mtd=docmillist)) { - this = (struct DiskOnChip *)mtd->priv; - docmillist = this->nextdoc; - - del_mtd_device(mtd); - - iounmap((void *)this->virtadr); - kfree(this->chips); - kfree(mtd); - } - inter_module_unregister(im_name); -} - -module_exit(cleanup_doc2001); -module_init(init_doc2001); - - diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/docecc.c linux/drivers/mtd/docecc.c --- v2.4.5/linux/drivers/mtd/docecc.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/mtd/docecc.c Wed Dec 31 16:00:00 1969 @@ -1,522 +0,0 @@ -/* - * ECC algorithm for M-systems disk on chip. We use the excellent Reed - * Solmon code of Phil Karn (karn@ka9q.ampr.org) available under the - * GNU GPL License. The rest is simply to convert the disk on chip - * syndrom into a standard syndom. - * - * Author: Fabrice Bellard (fabrice.bellard@netgem.com) - * Copyright (C) 2000 Netgem S.A. - * - * $Id: docecc.c,v 1.1 2000/11/03 12:43:43 dwmw2 Exp $ - * - * 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 - -/* need to undef it (from asm/termbits.h) */ -#undef B0 - -#define MM 10 /* Symbol size in bits */ -#define KK (1023-4) /* Number of data symbols per block */ -#define B0 510 /* First root of generator polynomial, alpha form */ -#define PRIM 1 /* power of alpha used to generate roots of generator poly */ -#define NN ((1 << MM) - 1) - -typedef unsigned short dtype; - -/* 1+x^3+x^10 */ -static const int Pp[MM+1] = { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 }; - -/* This defines the type used to store an element of the Galois Field - * used by the code. Make sure this is something larger than a char if - * if anything larger than GF(256) is used. - * - * Note: unsigned char will work up to GF(256) but int seems to run - * faster on the Pentium. - */ -typedef int gf; - -/* No legal value in index form represents zero, so - * we need a special value for this purpose - */ -#define A0 (NN) - -/* Compute x % NN, where NN is 2**MM - 1, - * without a slow divide - */ -static inline gf -modnn(int x) -{ - while (x >= NN) { - x -= NN; - x = (x >> MM) + (x & NN); - } - return x; -} - -#define min(a,b) ((a) < (b) ? (a) : (b)) - -#define CLEAR(a,n) {\ -int ci;\ -for(ci=(n)-1;ci >=0;ci--)\ -(a)[ci] = 0;\ -} - -#define COPY(a,b,n) {\ -int ci;\ -for(ci=(n)-1;ci >=0;ci--)\ -(a)[ci] = (b)[ci];\ -} - -#define COPYDOWN(a,b,n) {\ -int ci;\ -for(ci=(n)-1;ci >=0;ci--)\ -(a)[ci] = (b)[ci];\ -} - -#define Ldec 1 - -/* generate GF(2**m) from the irreducible polynomial p(X) in Pp[0]..Pp[m] - lookup tables: index->polynomial form alpha_to[] contains j=alpha**i; - polynomial form -> index form index_of[j=alpha**i] = i - alpha=2 is the primitive element of GF(2**m) - HARI's COMMENT: (4/13/94) alpha_to[] can be used as follows: - Let @ represent the primitive element commonly called "alpha" that - is the root of the primitive polynomial p(x). Then in GF(2^m), for any - 0 <= i <= 2^m-2, - @^i = a(0) + a(1) @ + a(2) @^2 + ... + a(m-1) @^(m-1) - where the binary vector (a(0),a(1),a(2),...,a(m-1)) is the representation - of the integer "alpha_to[i]" with a(0) being the LSB and a(m-1) the MSB. Thus for - example the polynomial representation of @^5 would be given by the binary - representation of the integer "alpha_to[5]". - Similarily, index_of[] can be used as follows: - As above, let @ represent the primitive element of GF(2^m) that is - the root of the primitive polynomial p(x). In order to find the power - of @ (alpha) that has the polynomial representation - a(0) + a(1) @ + a(2) @^2 + ... + a(m-1) @^(m-1) - we consider the integer "i" whose binary representation with a(0) being LSB - and a(m-1) MSB is (a(0),a(1),...,a(m-1)) and locate the entry - "index_of[i]". Now, @^index_of[i] is that element whose polynomial - representation is (a(0),a(1),a(2),...,a(m-1)). - NOTE: - The element alpha_to[2^m-1] = 0 always signifying that the - representation of "@^infinity" = 0 is (0,0,0,...,0). - Similarily, the element index_of[0] = A0 always signifying - that the power of alpha which has the polynomial representation - (0,0,...,0) is "infinity". - -*/ - -static void -generate_gf(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1]) -{ - register int i, mask; - - mask = 1; - Alpha_to[MM] = 0; - for (i = 0; i < MM; i++) { - Alpha_to[i] = mask; - Index_of[Alpha_to[i]] = i; - /* If Pp[i] == 1 then, term @^i occurs in poly-repr of @^MM */ - if (Pp[i] != 0) - Alpha_to[MM] ^= mask; /* Bit-wise EXOR operation */ - mask <<= 1; /* single left-shift */ - } - Index_of[Alpha_to[MM]] = MM; - /* - * Have obtained poly-repr of @^MM. Poly-repr of @^(i+1) is given by - * poly-repr of @^i shifted left one-bit and accounting for any @^MM - * term that may occur when poly-repr of @^i is shifted. - */ - mask >>= 1; - for (i = MM + 1; i < NN; i++) { - if (Alpha_to[i - 1] >= mask) - Alpha_to[i] = Alpha_to[MM] ^ ((Alpha_to[i - 1] ^ mask) << 1); - else - Alpha_to[i] = Alpha_to[i - 1] << 1; - Index_of[Alpha_to[i]] = i; - } - Index_of[0] = A0; - Alpha_to[NN] = 0; -} - -/* - * Performs ERRORS+ERASURES decoding of RS codes. bb[] is the content - * of the feedback shift register after having processed the data and - * the ECC. - * - * Return number of symbols corrected, or -1 if codeword is illegal - * or uncorrectable. If eras_pos is non-null, the detected error locations - * are written back. NOTE! This array must be at least NN-KK elements long. - * The corrected data are written in eras_val[]. They must be xor with the data - * to retrieve the correct data : data[erase_pos[i]] ^= erase_val[i] . - * - * First "no_eras" erasures are declared by the calling program. Then, the - * maximum # of errors correctable is t_after_eras = floor((NN-KK-no_eras)/2). - * If the number of channel errors is not greater than "t_after_eras" the - * transmitted codeword will be recovered. Details of algorithm can be found - * in R. Blahut's "Theory ... of Error-Correcting Codes". - - * Warning: the eras_pos[] array must not contain duplicate entries; decoder failure - * will result. The decoder *could* check for this condition, but it would involve - * extra time on every decoding operation. - * */ -static int -eras_dec_rs(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1], - gf bb[NN - KK + 1], gf eras_val[NN-KK], int eras_pos[NN-KK], - int no_eras) -{ - int deg_lambda, el, deg_omega; - int i, j, r,k; - gf u,q,tmp,num1,num2,den,discr_r; - gf lambda[NN-KK + 1], s[NN-KK + 1]; /* Err+Eras Locator poly - * and syndrome poly */ - gf b[NN-KK + 1], t[NN-KK + 1], omega[NN-KK + 1]; - gf root[NN-KK], reg[NN-KK + 1], loc[NN-KK]; - int syn_error, count; - - syn_error = 0; - for(i=0;i 0) { - /* Init lambda to be the erasure locator polynomial */ - lambda[1] = Alpha_to[modnn(PRIM * eras_pos[0])]; - for (i = 1; i < no_eras; i++) { - u = modnn(PRIM*eras_pos[i]); - for (j = i+1; j > 0; j--) { - tmp = Index_of[lambda[j - 1]]; - if(tmp != A0) - lambda[j] ^= Alpha_to[modnn(u + tmp)]; - } - } -#if DEBUG >= 1 - /* Test code that verifies the erasure locator polynomial just constructed - Needed only for decoder debugging. */ - - /* find roots of the erasure location polynomial */ - for(i=1;i<=no_eras;i++) - reg[i] = Index_of[lambda[i]]; - count = 0; - for (i = 1,k=NN-Ldec; i <= NN; i++,k = modnn(NN+k-Ldec)) { - q = 1; - for (j = 1; j <= no_eras; j++) - if (reg[j] != A0) { - reg[j] = modnn(reg[j] + j); - q ^= Alpha_to[reg[j]]; - } - if (q != 0) - continue; - /* store root and error location number indices */ - root[count] = i; - loc[count] = k; - count++; - } - if (count != no_eras) { - printf("\n lambda(x) is WRONG\n"); - count = -1; - goto finish; - } -#if DEBUG >= 2 - printf("\n Erasure positions as determined by roots of Eras Loc Poly:\n"); - for (i = 0; i < count; i++) - printf("%d ", loc[i]); - printf("\n"); -#endif -#endif - } - for(i=0;i 0; j--){ - if (reg[j] != A0) { - reg[j] = modnn(reg[j] + j); - q ^= Alpha_to[reg[j]]; - } - } - if (q != 0) - continue; - /* store root (index-form) and error location number */ - root[count] = i; - loc[count] = k; - /* If we've already found max possible roots, - * abort the search to save time - */ - if(++count == deg_lambda) - break; - } - if (deg_lambda != count) { - /* - * deg(lambda) unequal to number of roots => uncorrectable - * error detected - */ - count = -1; - goto finish; - } - /* - * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo - * x**(NN-KK)). in index form. Also find deg(omega). - */ - deg_omega = 0; - for (i = 0; i < NN-KK;i++){ - tmp = 0; - j = (deg_lambda < i) ? deg_lambda : i; - for(;j >= 0; j--){ - if ((s[i + 1 - j] != A0) && (lambda[j] != A0)) - tmp ^= Alpha_to[modnn(s[i + 1 - j] + lambda[j])]; - } - if(tmp != 0) - deg_omega = i; - omega[i] = Index_of[tmp]; - } - omega[NN-KK] = A0; - - /* - * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 = - * inv(X(l))**(B0-1) and den = lambda_pr(inv(X(l))) all in poly-form - */ - for (j = count-1; j >=0; j--) { - num1 = 0; - for (i = deg_omega; i >= 0; i--) { - if (omega[i] != A0) - num1 ^= Alpha_to[modnn(omega[i] + i * root[j])]; - } - num2 = Alpha_to[modnn(root[j] * (B0 - 1) + NN)]; - den = 0; - - /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */ - for (i = min(deg_lambda,NN-KK-1) & ~1; i >= 0; i -=2) { - if(lambda[i+1] != A0) - den ^= Alpha_to[modnn(lambda[i+1] + i * root[j])]; - } - if (den == 0) { -#if DEBUG >= 1 - printf("\n ERROR: denominator = 0\n"); -#endif - /* Convert to dual- basis */ - count = -1; - goto finish; - } - /* Apply error to data */ - if (num1 != 0) { - eras_val[j] = Alpha_to[modnn(Index_of[num1] + Index_of[num2] + NN - Index_of[den])]; - } else { - eras_val[j] = 0; - } - } - finish: - for(i=0;i> 2) | ((ecc1[2] & 0x0f) << 6); - bb[2] = ((ecc1[2] & 0xf0) >> 4) | ((ecc1[3] & 0x3f) << 4); - bb[3] = ((ecc1[3] & 0xc0) >> 6) | ((ecc1[0] & 0xff) << 2); - - nb_errors = eras_dec_rs(Alpha_to, Index_of, bb, - error_val, error_pos, 0); - if (nb_errors <= 0) - goto the_end; - - /* correct the errors */ - for(i=0;i= NB_DATA && pos < KK) { - nb_errors = -1; - goto the_end; - } - if (pos < NB_DATA) { - /* extract bit position (MSB first) */ - pos = 10 * (NB_DATA - 1 - pos) - 6; - /* now correct the following 10 bits. At most two bytes - can be modified since pos is even */ - index = (pos >> 3) ^ 1; - bitpos = pos & 7; - if ((index >= 0 && index < SECTOR_SIZE) || - index == (SECTOR_SIZE + 1)) { - val = error_val[i] >> (2 + bitpos); - parity ^= val; - if (index < SECTOR_SIZE) - sector[index] ^= val; - } - index = ((pos >> 3) + 1) ^ 1; - bitpos = (bitpos + 10) & 7; - if (bitpos == 0) - bitpos = 8; - if ((index >= 0 && index < SECTOR_SIZE) || - index == (SECTOR_SIZE + 1)) { - val = error_val[i] << (8 - bitpos); - parity ^= val; - if (index < SECTOR_SIZE) - sector[index] ^= val; - } - } - } - - /* use parity to test extra errors */ - if ((parity & 0xff) != 0) - nb_errors = -1; - - the_end: - kfree(Alpha_to); - kfree(Index_of); - return nb_errors; -} - diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/docprobe.c linux/drivers/mtd/docprobe.c --- v2.4.5/linux/drivers/mtd/docprobe.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/mtd/docprobe.c Wed Dec 31 16:00:00 1969 @@ -1,283 +0,0 @@ - -/* Linux driver for Disk-On-Chip devices */ -/* Probe routines common to all DoC devices */ -/* (c) 1999 Machine Vision Holdings, Inc. */ -/* Author: David Woodhouse */ -/* $Id: docprobe.c,v 1.21 2000/12/03 19:32:34 dwmw2 Exp $ */ - - - -/* DOC_PASSIVE_PROBE: - In order to ensure that the BIOS checksum is correct at boot time, and - hence that the onboard BIOS extension gets executed, the DiskOnChip - goes into reset mode when it is read sequentially: all registers - return 0xff until the chip is woken up again by writing to the - DOCControl register. - - Unfortunately, this means that the probe for the DiskOnChip is unsafe, - because one of the first things it does is write to where it thinks - the DOCControl register should be - which may well be shared memory - for another device. I've had machines which lock up when this is - attempted. Hence the possibility to do a passive probe, which will fail - to detect a chip in reset mode, but is at least guaranteed not to lock - the machine. - - If you have this problem, uncomment the following line: -#define DOC_PASSIVE_PROBE -*/ - - -/* DOC_SINGLE_DRIVER: - Millennium driver has been merged into DOC2000 driver. - - The newly-merged driver doesn't appear to work for writing. It's the - same with the DiskOnChip 2000 and the Millennium. If you have a - Millennium and you want write support to work, remove the definition - of DOC_SINGLE_DRIVER below to use the old doc2001-specific driver. - - Otherwise, it's left on in the hope that it'll annoy someone with - a Millennium enough that they go through and work out what the - difference is :) -*/ -#define DOC_SINGLE_DRIVER - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/* Where to look for the devices? */ -#ifndef CONFIG_MTD_DOCPROBE_ADDRESS -#define CONFIG_MTD_DOCPROBE_ADDRESS 0 -#endif - - -static unsigned long doc_config_location = CONFIG_MTD_DOCPROBE_ADDRESS; -MODULE_PARM(doc_config_location, "l"); - - -static unsigned long __initdata doc_locations[] = { -#if defined (__alpha__) || defined(__i386__) -#ifdef CONFIG_MTD_DOCPROBE_HIGH - 0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000, - 0xfffd0000, 0xfffd2000, 0xfffd4000, 0xfffd6000, - 0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000, - 0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000, - 0xfffe8000, 0xfffea000, 0xfffec000, 0xfffee000, -#else /* CONFIG_MTD_DOCPROBE_HIGH */ - 0xc8000, 0xca000, 0xcc000, 0xce000, - 0xd0000, 0xd2000, 0xd4000, 0xd6000, - 0xd8000, 0xda000, 0xdc000, 0xde000, - 0xe0000, 0xe2000, 0xe4000, 0xe6000, - 0xe8000, 0xea000, 0xec000, 0xee000, -#endif /* CONFIG_MTD_DOCPROBE_HIGH */ -#elif defined(__ppc__) - 0xe4000000, -#else -#warning Unknown architecture for DiskOnChip. No default probe locations defined -#endif - 0 }; - -/* doccheck: Probe a given memory window to see if there's a DiskOnChip present */ - -static inline int __init doccheck(unsigned long potential, unsigned long physadr) -{ - unsigned long window=potential; - unsigned char tmp, ChipID; -#ifndef DOC_PASSIVE_PROBE - unsigned char tmp2; -#endif - - /* Routine copied from the Linux DOC driver */ - -#ifdef CONFIG_MTD_DOCPROBE_55AA - /* Check for 0x55 0xAA signature at beginning of window, - this is no longer true once we remove the IPL (for Millennium */ - if (ReadDOC(window, Sig1) != 0x55 || ReadDOC(window, Sig2) != 0xaa) - return 0; -#endif /* CONFIG_MTD_DOCPROBE_55AA */ - -#ifndef DOC_PASSIVE_PROBE - /* It's not possible to cleanly detect the DiskOnChip - the - * bootup procedure will put the device into reset mode, and - * it's not possible to talk to it without actually writing - * to the DOCControl register. So we store the current contents - * of the DOCControl register's location, in case we later decide - * that it's not a DiskOnChip, and want to put it back how we - * found it. - */ - tmp2 = ReadDOC(window, DOCControl); - - /* Reset the DiskOnChip ASIC */ - WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, - window, DOCControl); - WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, - window, DOCControl); - - /* Enable the DiskOnChip ASIC */ - WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, - window, DOCControl); - WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, - window, DOCControl); -#endif /* !DOC_PASSIVE_PROBE */ - - ChipID = ReadDOC(window, ChipID); - - switch (ChipID) { - case DOC_ChipID_Doc2k: - /* Check the TOGGLE bit in the ECC register */ - tmp = ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT; - if ((ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT) != tmp) - return ChipID; - break; - - case DOC_ChipID_DocMil: - /* Check the TOGGLE bit in the ECC register */ - tmp = ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT; - if ((ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT) != tmp) - return ChipID; - break; - - default: -#ifndef CONFIG_MTD_DOCPROBE_55AA - printk(KERN_WARNING "Possible DiskOnChip with unknown ChipID %2.2X found at 0x%lx\n", - ChipID, physadr); -#endif -#ifndef DOC_PASSIVE_PROBE - /* Put back the contents of the DOCControl register, in case it's not - * actually a DiskOnChip. - */ - WriteDOC(tmp2, window, DOCControl); -#endif - return 0; - } - - printk(KERN_WARNING "DiskOnChip failed TOGGLE test, dropping.\n"); - -#ifndef DOC_PASSIVE_PROBE - /* Put back the contents of the DOCControl register: it's not a DiskOnChip */ - WriteDOC(tmp2, window, DOCControl); -#endif - return 0; -} - - -static void DoC_Probe(unsigned long physadr) -{ - unsigned long docptr; - struct DiskOnChip *this; - struct mtd_info *mtd; - int ChipID; - char namebuf[15]; - char *name = namebuf; - char *im_funcname = NULL; - char *im_modname = NULL; - void (*initroutine)(struct mtd_info *) = NULL; - - docptr = (unsigned long)ioremap(physadr, 0x2000); - - if (!docptr) - return; - - if ((ChipID = doccheck(docptr, physadr))) { - - mtd = kmalloc(sizeof(struct DiskOnChip) + sizeof(struct mtd_info), GFP_KERNEL); - - if (!mtd) { - printk("Cannot allocate memory for data structures. Dropping.\n"); - iounmap((void *)docptr); - return; - } - - this = (struct DiskOnChip *)(&mtd[1]); - - memset((char *)mtd,0, sizeof(struct mtd_info)); - memset((char *)this, 0, sizeof(struct DiskOnChip)); - - mtd->priv = this; - this->virtadr = docptr; - this->physadr = physadr; - this->ChipID = ChipID; - sprintf(namebuf, "with ChipID %2.2X", ChipID); - - switch(ChipID) { - case DOC_ChipID_Doc2k: - name="2000"; - im_funcname = "DoC2k_init"; - im_modname = "doc2000"; - break; - - case DOC_ChipID_DocMil: - name="Millennium"; -#ifdef DOC_SINGLE_DRIVER - im_funcname = "DoC2k_init"; - im_modname = "doc2000"; -#else - im_funcname = "DoCMil_init"; - im_modname = "doc2001"; -#endif /* DOC_SINGLE_DRIVER */ - break; - } - - if (im_funcname) - initroutine = inter_module_get_request(im_funcname, im_modname); - - if (initroutine) { - (*initroutine)(mtd); - inter_module_put(im_funcname); - return; - } - printk("Cannot find driver for DiskOnChip %s at 0x%lX\n", name, physadr); - } - iounmap((void *)docptr); -} - - -/**************************************************************************** - * - * Module stuff - * - ****************************************************************************/ - -#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) -#define init_doc init_module -#endif - -int __init init_doc(void) -{ - int i; - - printk(KERN_NOTICE "M-Systems DiskOnChip driver. (C) 1999 Machine Vision Holdings, Inc.\n"); -#ifdef PRERELEASE - printk(KERN_INFO "$Id: docprobe.c,v 1.21 2000/12/03 19:32:34 dwmw2 Exp $\n"); -#endif - if (doc_config_location) { - printk("Using configured probe address 0x%lx\n", doc_config_location); - DoC_Probe(doc_config_location); - } else { - for (i=0; doc_locations[i]; i++) { - DoC_Probe(doc_locations[i]); - } - } - /* So it looks like we've been used and we get unloaded */ - MOD_INC_USE_COUNT; - MOD_DEC_USE_COUNT; - return 0; - -} - -module_init(init_doc); - diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/ftl.c linux/drivers/mtd/ftl.c --- v2.4.5/linux/drivers/mtd/ftl.c Sat Apr 28 11:27:54 2001 +++ linux/drivers/mtd/ftl.c Tue Jun 12 10:30:27 2001 @@ -1,10 +1,10 @@ /* This version ported to the Linux-MTD system by dwmw2@infradead.org + * $Id: ftl.c,v 1.35 2001/06/09 00:40:17 dwmw2 Exp $ * - * - Based on Id: ftl.c,v 1.21 2000/08/01 13:07:49 dwmw2 Exp - * - With the Franz Galiana's set_bam_entry fix from v1.23 - * - Perhaps it's about time I made a branch for the 2.4 series. - - * Originally based on: + * Fixes: Arnaldo Carvalho de Melo + * - fixes some leaks on failure in build_maps and ftl_notify_add, cleanups + * + * Based on: */ /*====================================================================== @@ -30,8 +30,8 @@ are Copyright (C) 1999 David A. Hinds. All Rights Reserved. Alternatively, the contents of this file may be used under the - terms of the GNU General Public License version 2 (the "GPL"), in which - case the provisions of the GPL are applicable instead of the + terms of the GNU General Public License version 2 (the "GPL"), in + which case the provisions of the GPL are applicable instead of the above. If you wish to allow the use of your version of this file only under the terms of the GPL and not to allow others to use your version of this file under the MPL, indicate your decision @@ -55,11 +55,6 @@ contact M-Systems (http://www.m-sys.com) directly. ======================================================================*/ -#define FTL_DEBUG 5 -#ifdef FTL_DEBUG -#define DEBUGLVL debug -#endif - #include #include #include @@ -108,19 +103,16 @@ /*====================================================================*/ /* Parameters that can be set with 'insmod' */ - -/* Major device # for FTL device */ static int shuffle_freq = 50; - MODULE_PARM(shuffle_freq, "i"); /*====================================================================*/ +/* Major device # for FTL device */ #ifndef FTL_MAJOR #define FTL_MAJOR 44 #endif - /* Funky stuff for setting up a block device */ #define MAJOR_NR FTL_MAJOR #define DEVICE_NAME "ftl" @@ -135,17 +127,8 @@ #include -#ifdef FTL_DEBUG -static int debug = FTL_DEBUG; -MODULE_PARM(debug, "i"); -#endif - /*====================================================================*/ -#ifndef FTL_MAJOR -#define FTL_MAJOR 44 -#endif - /* Maximum number of separate memory devices we'll allow */ #define MAX_DEV 4 @@ -200,7 +183,10 @@ void ftl_freepart(partition_t *part); -static struct mtd_notifier ftl_notifier={ftl_notify_add, ftl_notify_remove, NULL}; +static struct mtd_notifier ftl_notifier = { + add: ftl_notify_add, + remove: ftl_notify_remove, +}; /* Partition state flags */ #define FTL_FORMATTED 0x01 @@ -226,7 +212,6 @@ #endif part: ftl_hd, sizes: ftl_sizes, - nr_real: 0 }; /*====================================================================*/ @@ -274,7 +259,7 @@ /* Search first megabyte for a valid FTL header */ for (offset = 0; offset < max_offset; - offset += part->mtd->erasesize?part->mtd->erasesize:0x2000) { + offset += part->mtd->erasesize ? : 0x2000) { ret = part->mtd->read(part->mtd, offset, sizeof(header), &ret, (unsigned char *)&header); @@ -296,7 +281,7 @@ return -1; } if ((1 << header.EraseUnitSize) != part->mtd->erasesize) { - printk(KERN_NOTICE "ftl: FTL EraseUnitSize %x != MTD erasesize %lx\n", + printk(KERN_NOTICE "ftl: FTL EraseUnitSize %x != MTD erasesize %x\n", 1 << header.EraseUnitSize,part->mtd->erasesize); return -1; } @@ -309,7 +294,7 @@ erase_unit_header_t header; u_int16_t xvalid, xtrans, i; u_int blocks, j; - int hdr_ok, ret; + int hdr_ok, ret = -1; ssize_t retval; loff_t offset; @@ -318,13 +303,15 @@ part->header.NumTransferUnits; part->EUNInfo = kmalloc(part->DataUnits * sizeof(struct eun_info_t), GFP_KERNEL); - if (!part->EUNInfo) return -1; + if (!part->EUNInfo) + goto out; for (i = 0; i < part->DataUnits; i++) part->EUNInfo[i].Offset = 0xffffffff; part->XferInfo = kmalloc(part->header.NumTransferUnits * sizeof(struct xfer_info_t), GFP_KERNEL); - if (!part->XferInfo) return -1; + if (!part->XferInfo) + goto out_EUNInfo; xvalid = xtrans = 0; for (i = 0; i < le16_to_cpu(part->header.NumEraseUnits); i++) { @@ -334,8 +321,9 @@ (unsigned char *)&header); if (ret) - return ret; + goto out_XferInfo; + ret = -1; /* Is this a transfer partition? */ hdr_ok = (strcmp(header.DataOrgTuple+3, "FTL100") == 0); if (hdr_ok && (le16_to_cpu(header.LogicalEUN) < part->DataUnits) && @@ -348,7 +336,7 @@ if (xtrans == part->header.NumTransferUnits) { printk(KERN_NOTICE "ftl_cs: format error: too many " "transfer units!\n"); - return -1; + goto out_XferInfo; } if (hdr_ok && (le16_to_cpu(header.LogicalEUN) == 0xffff)) { part->XferInfo[xtrans].state = XFER_PREPARED; @@ -369,18 +357,22 @@ (xvalid+xtrans != le16_to_cpu(header.NumEraseUnits))) { printk(KERN_NOTICE "ftl_cs: format error: erase units " "don't add up!\n"); - return -1; + goto out_XferInfo; } /* Set up virtual page map */ blocks = le32_to_cpu(header.FormattedSize) >> header.BlockSize; part->VirtualBlockMap = vmalloc(blocks * sizeof(u_int32_t)); + if (!part->VirtualBlockMap) + goto out_XferInfo; + memset(part->VirtualBlockMap, 0xff, blocks * sizeof(u_int32_t)); part->BlocksPerUnit = (1 << header.EraseUnitSize) >> header.BlockSize; part->bam_cache = kmalloc(part->BlocksPerUnit * sizeof(u_int32_t), GFP_KERNEL); - if (!part->bam_cache) return -1; + if (!part->bam_cache) + goto out_VirtualBlockMap; part->bam_index = 0xffff; part->FreeTotal = 0; @@ -395,7 +387,7 @@ (unsigned char *)part->bam_cache); if (ret) - return ret; + goto out_bam_cache; for (j = 0; j < part->BlocksPerUnit; j++) { if (BLOCK_FREE(le32_to_cpu(part->bam_cache[j]))) { @@ -410,8 +402,19 @@ } } - return 0; - + ret = 0; + goto out; + +out_bam_cache: + kfree(part->bam_cache); +out_VirtualBlockMap: + vfree(part->VirtualBlockMap); +out_XferInfo: + kfree(part->XferInfo); +out_EUNInfo: + kfree(part->EUNInfo); +out: + return ret; } /* build_maps */ /*====================================================================== @@ -699,7 +702,7 @@ int queued, ret; DEBUG(0, "ftl_cs: reclaiming space...\n"); - DEBUG(4, "NumTransferUnits == %x\n", part->header.NumTransferUnits); + DEBUG(3, "NumTransferUnits == %x\n", part->header.NumTransferUnits); /* Pick the least erased transfer unit */ best = 0xffffffff; xfer = 0xffff; do { @@ -707,22 +710,22 @@ for (i = 0; i < part->header.NumTransferUnits; i++) { int n=0; if (part->XferInfo[i].state == XFER_UNKNOWN) { - DEBUG(4,"XferInfo[%d].state == XFER_UNKNOWN\n",i); + DEBUG(3,"XferInfo[%d].state == XFER_UNKNOWN\n",i); n=1; erase_xfer(part, i); } if (part->XferInfo[i].state == XFER_ERASING) { - DEBUG(4,"XferInfo[%d].state == XFER_ERASING\n",i); + DEBUG(3,"XferInfo[%d].state == XFER_ERASING\n",i); n=1; queued = 1; } else if (part->XferInfo[i].state == XFER_ERASED) { - DEBUG(4,"XferInfo[%d].state == XFER_ERASED\n",i); + DEBUG(3,"XferInfo[%d].state == XFER_ERASED\n",i); n=1; prepare_xfer(part, i); } if (part->XferInfo[i].state == XFER_PREPARED) { - DEBUG(4,"XferInfo[%d].state == XFER_PREPARED\n",i); + DEBUG(3,"XferInfo[%d].state == XFER_PREPARED\n",i); n=1; if (part->XferInfo[i].EraseCount <= best) { best = part->XferInfo[i].EraseCount; @@ -730,7 +733,7 @@ } } if (!n) - DEBUG(4,"XferInfo[%d].state == %x\n",i, part->XferInfo[i].state); + DEBUG(3,"XferInfo[%d].state == %x\n",i, part->XferInfo[i].state); } if (xfer == 0xffff) { @@ -1219,11 +1222,12 @@ } whole = minor & ~(MAX_PART-1); - for (i = 0; i < MAX_PART; i++) { + i = MAX_PART - 1; + while (i-- > 0) { if (ftl_hd[whole+i].nr_sects > 0) { kdev_t rdev = MKDEV(FTL_MAJOR, whole+i); - sync_dev(rdev); - invalidate_buffers(rdev); + + invalidate_device(rdev, 1); } ftl_hd[whole+i].start_sect = 0; ftl_hd[whole+i].nr_sects = 0; @@ -1362,7 +1366,8 @@ printk(KERN_INFO "ftl_cs: opening %d kb FTL partition\n", le32_to_cpu(partition->header.FormattedSize) >> 10); #endif - } + } else + kfree(partition); } static void ftl_notify_remove(struct mtd_info *mtd) @@ -1395,13 +1400,10 @@ } } - -#if LINUX_VERSION_CODE < 0x20300 -#ifdef MODULE +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) #define init_ftl init_module #define cleanup_ftl cleanup_module #endif -#endif mod_init_t init_ftl(void) { @@ -1409,6 +1411,8 @@ memset(myparts, 0, sizeof(myparts)); + DEBUG(0, "$Id: ftl.c,v 1.35 2001/06/09 00:40:17 dwmw2 Exp $\n"); + if (register_blkdev(FTL_MAJOR, "ftl", &ftl_blk_fops)) { printk(KERN_NOTICE "ftl_cs: unable to grab major " "device number!\n"); @@ -1449,7 +1453,5 @@ } } -#if LINUX_VERSION_CODE > 0x20300 module_init(init_ftl); module_exit(cleanup_ftl); -#endif diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/jedec.c linux/drivers/mtd/jedec.c --- v2.4.5/linux/drivers/mtd/jedec.c Tue Jul 4 10:10:05 2000 +++ linux/drivers/mtd/jedec.c Wed Dec 31 16:00:00 1969 @@ -1,773 +0,0 @@ - -/* JEDEC Flash Interface. - * This is an older type of interface for self programming flash. It is - * commonly use in older AMD chips and is obsolete compared with CFI. - * It is called JEDEC because the JEDEC association distributes the ID codes - * for the chips. - * - * See the AMD flash databook for information on how to operate the interface. - * - * This code does not support anything wider than 8 bit flash chips, I am - * not going to guess how to send commands to them, plus I expect they will - * all speak CFI.. - * - * $Id: jedec.c,v 1.1 2000/07/04 07:21:57 jgg Exp $ - */ - -#include - -struct mtd_info *jedec_probe(struct map_info *); -int jedec_probe8(struct map_info *map,unsigned long base, - struct jedec_private *priv); -int jedec_probe16(struct map_info *map,unsigned long base, - struct jedec_private *priv); -int jedec_probe32(struct map_info *map,unsigned long base, - struct jedec_private *priv); -static void jedec_flash_chip_scan(struct jedec_private *priv,unsigned long start, - unsigned long len); -static int flash_erase(struct mtd_info *mtd, struct erase_info *instr); -static int flash_write(struct mtd_info *mtd, loff_t start, size_t len, - size_t *retlen, const u_char *buf); - -EXPORT_SYMBOL(jedec_probe); - -/* Listing of parts and sizes. We need this table to learn the sector - size of the chip and the total length */ -static const struct JEDECTable JEDEC_table[] = - {{0x01AD,"AMD Am29F016",2*1024*1024,64*1024,MTD_CAP_NORFLASH}, - {0x01D5,"AMD Am29F080",1*1024*1024,64*1024,MTD_CAP_NORFLASH}, - {0x01A4,"AMD Am29F040",512*1024,64*1024,MTD_CAP_NORFLASH}, - {}}; - -static void jedec_sync(struct mtd_info *mtd) {}; -static int jedec_read(struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf); -static int jedec_read_banked(struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf); - -/* Probe entry point */ - struct jedec_private priv; - struct mtd_info __MTD; -struct mtd_info *jedec_probe(struct map_info *map) -{ - struct mtd_info *MTD = &__MTD; - unsigned long Base; - unsigned long SectorSize; - unsigned count; - unsigned I,Uniq; - char Part[200]; - memset(&priv,0,sizeof(priv)); - - if (map->bank_size == 0) - map->bank_size = map->size; - - if (map->size/map->bank_size > MAX_JEDEC_CHIPS) - { - printk("mtd: Increase MAX_JEDEC_CHIPS, too many banks.\n"); - return 0; - } - - for (Base = 0; Base < map->size; Base += map->bank_size) - { - // Perhaps zero could designate all tests? - if (map->bus_width == 0) - map->bus_width = 8; - - if (map->bus_width == 8) - jedec_probe8(map,Base,&priv); - if (map->bus_width == 16) - jedec_probe16(map,Base,&priv); - if (map->bus_width == 32) - jedec_probe32(map,Base,&priv); - } - - // Get the biggest sector size - SectorSize = 0; - for (I = 0; priv.chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) - { - if (priv.chips[I].sectorsize > SectorSize) - SectorSize = priv.chips[I].sectorsize; - } - - // Quickly ensure that the other sector sizes are factors of the largest - for (I = 0; priv.chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) - { - if ((SectorSize/priv.chips[I].sectorsize)*priv.chips[I].sectorsize != SectorSize) - { - printk("mtd: Failed. Device has incompatible mixed sector sizes\n"); - return 0; - } - } - - /* Generate a part name that includes the number of different chips and - other configuration information */ - count = 1; - strncpy(Part,map->name,sizeof(Part)-10); - Part[sizeof(Part)-11] = 0; - strcat(Part," "); - Uniq = 0; - for (I = 0; priv.chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) - { - const struct JEDECTable *JEDEC; - - if (priv.chips[I+1].jedec == priv.chips[I].jedec) - { - count++; - continue; - } - - // Locate the chip in the jedec table - JEDEC = jedec_idtoinf(priv.chips[I].jedec >> 8,priv.chips[I].jedec); - if (JEDEC == 0) - { - printk("mtd: Internal Error, JEDEC not set\n"); - return 0; - } - - if (Uniq != 0) - strcat(Part,","); - Uniq++; - - if (count != 1) - sprintf(Part+strlen(Part),"%x*[%s]",count,JEDEC->name); - else - sprintf(Part+strlen(Part),"%s",JEDEC->name); - if (strlen(Part) > sizeof(Part)*2/3) - break; - count = 1; - } - - /* Determine if the chips are organized in a linear fashion, or if there - are empty banks. Note, the last bank does not count here, only the - first banks are important. Holes on non-bank boundaries can not exist - due to the way the detection algorithm works. */ - if (priv.size < map->bank_size) - map->bank_size = priv.size; - priv.is_banked = 0; - for (I = 0; I != priv.size/map->bank_size - 1; I++) - { - if (priv.bank_fill[I] != map->bank_size) - priv.is_banked = 1; - - /* This even could be eliminated, but new de-optimized read/write - functions have to be written */ - if (priv.bank_fill[I] != priv.bank_fill[0]) - { - printk("mtd: Failed. Cannot handle unsymetric banking\n"); - return 0; - } - } - if (priv.is_banked == 1) - strcat(Part,", banked"); - - xprintf("Part: '%s'\n",Part); - - memset(MTD,0,sizeof(*MTD)); - strncpy(MTD->name,Part,sizeof(MTD->name)); - MTD->name[sizeof(MTD->name)-1] = 0; - MTD->type = MTD_NORFLASH; - MTD->flags = MTD_CAP_NORFLASH; - MTD->erasesize = SectorSize*(map->bus_width/8); - MTD->size = priv.size; - //MTD->module = THIS_MODULE; // ? Maybe this should be the low level module? - MTD->erase = flash_erase; - if (priv.is_banked == 1) - MTD->read = jedec_read_banked; - else - MTD->read = jedec_read; - MTD->write = flash_write; - MTD->sync = jedec_sync; - MTD->priv = map; - map->fldrv_priv = &priv; - - return MTD; -} - -/* Helper for the JEDEC function, JEDEC numbers all have odd parity */ -static int checkparity(u_char C) -{ - u_char parity = 0; - while (C != 0) - { - parity ^= C & 1; - C >>= 1; - } - - return parity == 1; -} - - -/* Take an array of JEDEC numbers that represent interleved flash chips - and process them. Check to make sure they are good JEDEC numbers, look - them up and then add them to the chip list */ -int handle_jedecs(struct map_info *map,__u8 *Mfg,__u8 *Id,unsigned Count, - unsigned long base,struct jedec_private *priv) -{ - unsigned I,J; - unsigned long Size; - unsigned long SectorSize; - const struct JEDECTable *JEDEC; - - // Test #2 JEDEC numbers exhibit odd parity - for (I = 0; I != Count; I++) - { - if (checkparity(Mfg[I]) == 0 || checkparity(Id[I]) == 0) - return 0; - } - - // Finally, just make sure all the chip sizes are the same - JEDEC = jedec_idtoinf(Mfg[0],Id[0]); - - if (JEDEC == 0) - { - printk("mtd: Found JEDEC flash chip, but do not have a table entry for %x:%x\n",Mfg[0],Mfg[1]); - return 0; - } - - Size = JEDEC->size; - SectorSize = JEDEC->sectorsize; - for (I = 0; I != Count; I++) - { - JEDEC = jedec_idtoinf(Mfg[0],Id[0]); - if (JEDEC == 0) - { - printk("mtd: Found JEDEC flash chip, but do not have a table entry for %x:%x\n",Mfg[0],Mfg[1]); - return 0; - } - - if (Size != JEDEC->size || SectorSize != JEDEC->sectorsize) - { - printk("mtd: Failed. Interleved flash does not have matching characteristics\n"); - return 0; - } - } - - // Load the Chips - for (I = 0; I != MAX_JEDEC_CHIPS; I++) - { - if (priv->chips[I].jedec == 0) - break; - } - - if (I + Count > MAX_JEDEC_CHIPS) - { - printk("mtd: Device has too many chips. Increase MAX_JEDEC_CHIPS\n"); - return 0; - } - - // Add them to the table - for (J = 0; J != Count; J++) - { - unsigned long Bank; - - JEDEC = jedec_idtoinf(Mfg[J],Id[J]); - priv->chips[I].jedec = (Mfg[J] << 8) | Id[J]; - priv->chips[I].size = JEDEC->size; - priv->chips[I].sectorsize = JEDEC->sectorsize; - priv->chips[I].base = base + J; - priv->chips[I].datashift = J*8; - priv->chips[I].capabilities = JEDEC->capabilities; - priv->chips[I].offset = priv->size + J; - - // log2 n :| - priv->chips[I].addrshift = 0; - for (Bank = Count; Bank != 1; Bank >>= 1, priv->chips[I].addrshift++); - - // Determine how filled this bank is. - Bank = base & (~(map->bank_size-1)); - if (priv->bank_fill[Bank/map->bank_size] < base + - (JEDEC->size << priv->chips[I].addrshift) - Bank) - priv->bank_fill[Bank/map->bank_size] = base + (JEDEC->size << priv->chips[I].addrshift) - Bank; - I++; - } - - priv->size += priv->chips[I-1].size*Count; - - return priv->chips[I-1].size; -} - -/* Lookup the chip information from the JEDEC ID table. */ -const struct JEDECTable *jedec_idtoinf(__u8 mfr,__u8 id) -{ - __u16 Id = (mfr << 8) | id; - unsigned long I = 0; - for (I = 0; JEDEC_table[I].jedec != 0; I++) - if (JEDEC_table[I].jedec == Id) - return JEDEC_table + I; - return 0; -} - -// Look for flash using an 8 bit bus interface -int jedec_probe8(struct map_info *map,unsigned long base, - struct jedec_private *priv) -{ - return 0; -} - -// Look for flash using a 16 bit bus interface (ie 2 8-bit chips) -int jedec_probe16(struct map_info *map,unsigned long base, - struct jedec_private *priv) -{ - return 0; -} - -// Look for flash using a 32 bit bus interface (ie 4 8-bit chips) -int jedec_probe32(struct map_info *map,unsigned long base, - struct jedec_private *priv) -{ - #define flread(x) map->read32(map,base+((x)<<2)) - #define flwrite(v,x) map->write32(map,v,base+((x)<<2)) - - const unsigned long AutoSel1 = 0xAAAAAAAA; - const unsigned long AutoSel2 = 0x55555555; - const unsigned long AutoSel3 = 0x90909090; - const unsigned long Reset = 0x90909090; - __u32 OldVal; - __u8 Mfg[4]; - __u8 Id[4]; - unsigned I; - unsigned long Size; - - // Wait for any write/erase operation to settle - OldVal = flread(base); - for (I = 0; OldVal != flread(base) && I < 10000; I++) - OldVal = flread(base); - - // Reset the chip - flwrite(Reset,0x555); - - // Send the sequence - flwrite(AutoSel1,0x555); - flwrite(AutoSel2,0x2AA); - flwrite(AutoSel3,0x555); - - // Test #1, JEDEC numbers are readable from 0x??00/0x??01 - if (flread(0) != flread(0x100) || - flread(1) != flread(0x101)) - { - flwrite(Reset,0x555); - return 0; - } - - // Split up the JEDEC numbers - OldVal = flread(0); - for (I = 0; I != 4; I++) - Mfg[I] = (OldVal >> (I*8)); - OldVal = flread(1); - for (I = 0; I != 4; I++) - Id[I] = (OldVal >> (I*8)); - - Size = handle_jedecs(map,Mfg,Id,4,base,priv); - if (Size == 0) - { - flwrite(Reset,0x555); - return 0; - } - - /* Check if there is address wrap around within a single bank, if this - returns JEDEC numbers then we assume that it is wrap around. Notice - we call this routine with the JEDEC return still enabled, if two or - more flashes have a truncated address space the probe test will still - work */ - if (base + Size+0x555 < map->size && - base + Size+0x555 < (base & (~(map->bank_size-1))) + map->bank_size) - { - if (flread(base+Size) != flread(base+Size + 0x100) || - flread(base+Size + 1) != flread(base+Size + 0x101)) - { - jedec_probe32(map,base+Size,priv); - } - } - - // Reset. - flwrite(0xF0F0F0F0,0x555); - - return 1; - - #undef flread - #undef flwrite -} - -/* Linear read. */ -static int jedec_read(struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf) -{ - struct map_info *map = (struct map_info *)mtd->priv; - - map->copy_from(map, buf, from, len); - *retlen = len; - return 0; -} - -/* Banked read. Take special care to jump past the holes in the bank - mapping. This version assumes symetry in the holes.. */ -static int jedec_read_banked(struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf) -{ - struct map_info *map = (struct map_info *)mtd->priv; - struct jedec_private *priv = (struct jedec_private *)map->fldrv_priv; - - *retlen = 0; - while (len > 0) - { - // Determine what bank and offset into that bank the first byte is - unsigned long bank = from & (~(priv->bank_fill[0]-1)); - unsigned long offset = from & (priv->bank_fill[0]-1); - unsigned long get = len; - if (priv->bank_fill[0] - offset < len) - get = priv->bank_fill[0] - offset; - - bank /= priv->bank_fill[0]; - map->copy_from(map,buf + *retlen,bank*map->bank_size + offset,get); - - len -= get; - *retlen += get; - from += get; - } - return 0; -} - -/* Pass the flags value that the flash return before it re-entered read - mode. */ -static void jedec_flash_failed(unsigned char code) -{ - /* Bit 5 being high indicates that there was an internal device - failure, erasure time limits exceeded or something */ - if ((code & (1 << 5)) != 0) - { - printk("mtd: Internal Flash failure\n"); - return; - } - printk("mtd: Programming didn't take\n"); -} - -/* This uses the erasure function described in the AMD Flash Handbook, - it will work for flashes with a fixed sector size only. Flashes with - a selection of sector sizes (ie the AMD Am29F800B) will need a different - routine. This routine tries to parallize erasing multiple chips/sectors - where possible */ -static int flash_erase(struct mtd_info *mtd, struct erase_info *instr) -{ - // Does IO to the currently selected chip - #define flread(x) map->read8(map,chip->base+((x)<addrshift)) - #define flwrite(v,x) map->write8(map,v,chip->base+((x)<addrshift)) - - unsigned long Time = 0; - unsigned long NoTime = 0; - unsigned long start = instr->addr, len = instr->len; - unsigned int I; - struct map_info *map = (struct map_info *)mtd->priv; - struct jedec_private *priv = (struct jedec_private *)map->fldrv_priv; - - // Verify the arguments.. - if (start + len > mtd->size || - (start % mtd->erasesize) != 0 || - (len % mtd->erasesize) != 0 || - (len/mtd->erasesize) == 0) - return -EINVAL; - - jedec_flash_chip_scan(priv,start,len); - - // Start the erase sequence on each chip - for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) - { - unsigned long off; - struct jedec_flash_chip *chip = priv->chips + I; - - if (chip->length == 0) - continue; - - // Send the erase setup code - xprintf("Erase: "); - puth(chip->start); putc(' '); - puth(chip->base); putc(' '); - puth(chip->length); putc(' '); - puth(chip->sectorsize); putc('\n'); - - if (chip->start + chip->length > chip->size) - { - xprintf("DIE\n"); - return -EIO; - } - - flwrite(0xF0,chip->start + 0x555); - flwrite(0xAA,chip->start + 0x555); - flwrite(0x55,chip->start + 0x2AA); - flwrite(0x80,chip->start + 0x555); - flwrite(0xAA,chip->start + 0x555); - flwrite(0x55,chip->start + 0x2AA); - - // Use chip erase if possible - if (chip->start == 0 && chip->length == chip->size) - { - flwrite(0x10,0x555); - continue; - } - - /* Once we start selecting the erase sectors the delay between each - command must not exceed 50us or it will immediately start erasing - and ignore the other sectors */ -/* how do you portably turn off interrupts? - save_flags(flags); - cli();*/ - for (off = 0; off < chip->length; off += chip->sectorsize) - { - // Check to make sure we didn't timeout - flwrite(0x30,chip->start + off); - if (off == 0) - continue; - if ((flread(chip->start + off) & (1 << 3)) != 0) - { - printk("mtd: Ack! We timed out the erase timer!\n"); - return -EIO; - } - } -// restore_flags(flags); - } - - /* We could split this into a timer routine and return early, performing - background erasure.. Maybe later if the need warrents */ - - /* Poll the flash for erasure completion, specs say this can take as long - as 480 seconds to do all the sectors (for a 2 meg flash). - Erasure time is dependant on chip age, temp and wear.. */ - - /* This being a generic routine assumes a 32 bit bus. It does read32s - and bundles interleved chips into the same grouping. This will work - for all bus widths */ - Time = 0; - NoTime = 0; - for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) - { - struct jedec_flash_chip *chip = priv->chips + I; - unsigned long off = 0; - unsigned todo[4] = {0,0,0,0}; - unsigned todo_left = 0; - unsigned J; - - if (chip->length == 0) - continue; - - /* Find all chips in this data line, realistically this is all - or nothing up to the interleve count */ - for (J = 0; priv->chips[J].jedec != 0 && J < MAX_JEDEC_CHIPS; J++) - { - if ((priv->chips[J].base & (~((1<addrshift)-1))) == - (chip->base & (~((1<addrshift)-1)))) - { - todo_left++; - todo[priv->chips[J].base & ((1<addrshift)-1)] = 1; - } - } - - xprintf("todo: %x %x %x %x\n",(short)todo[0],(short)todo[1], - (short)todo[2],(short)todo[3]); - - while (1) - { - __u32 Last[4]; - unsigned long Count = 0; - - /* During erase bit 7 is held low and bit 6 toggles, we watch this, - should it stop toggling or go high then the erase is completed, - or this is not really flash ;> */ - Last[0] = map->read32(map,(chip->base >> chip->addrshift) + chip->start + off); - Last[1] = map->read32(map,(chip->base >> chip->addrshift) + chip->start + off); - Last[2] = map->read32(map,(chip->base >> chip->addrshift) + chip->start + off); - Count = 3; - while (todo_left != 0) - { - for (J = 0; J != 4; J++) - { - __u8 Byte1 = (Last[(Count-1)%4] >> (J*8)) & 0xFF; - __u8 Byte2 = (Last[(Count-2)%4] >> (J*8)) & 0xFF; - __u8 Byte3 = (Last[(Count-3)%4] >> (J*8)) & 0xFF; - if (todo[J] == 0) - continue; - - if ((Byte1 & (1 << 7)) == 0 && Byte1 != Byte2) - { -// printk("Check %x %x %x\n",(short)J,(short)Byte1,(short)Byte2); - continue; - } - - if (Byte1 == Byte2) - { - jedec_flash_failed(Byte3); - return -EIO; - } - - todo[J] = 0; - todo_left--; - } - -/* if (NoTime == 0) - Time += HZ/10 - schedule_timeout(HZ/10);*/ - NoTime = 0; - - Last[Count % 4] = map->read32(map,(chip->base >> chip->addrshift) + chip->start + off); - Count++; - - putc('.'); - -/* // Count time, max of 15s per sector (according to AMD) - if (Time > 15*len/mtd->erasesize*HZ) - { - printk("mtd: Flash Erase Timed out\n"); - return -EIO; - } */ - } - - puts("out\n"); - - // Skip to the next chip if we used chip erase - if (chip->length == chip->size) - off = chip->size; - else - off += chip->sectorsize; - - if (off >= chip->length) - break; - NoTime = 1; - } - - for (J = 0; priv->chips[J].jedec != 0 && J < MAX_JEDEC_CHIPS; J++) - { - if ((priv->chips[J].base & (~((1<addrshift)-1))) == - (chip->base & (~((1<addrshift)-1)))) - priv->chips[J].length = 0; - } - } - - puts("done\n"); - return 0; - - #undef flread - #undef flwrite -} - -/* This is the simple flash writing function. It writes to every byte, in - sequence. It takes care of how to properly address the flash if - the flash is interleved. It can only be used if all the chips in the - array are identical!*/ -static int flash_write(struct mtd_info *mtd, loff_t start, size_t len, - size_t *retlen, const u_char *buf) -{ - /* Does IO to the currently selected chip. It takes the bank addressing - base (which is divisable by the chip size) adds the necesary lower bits - of addrshift (interleve index) and then adds the control register index. */ - #define flread(x) map->read8(map,base+(off&((1<addrshift)-1))+((x)<addrshift)) - #define flwrite(v,x) map->write8(map,v,base+(off&((1<addrshift)-1))+((x)<addrshift)) - - struct map_info *map = (struct map_info *)mtd->priv; - struct jedec_private *priv = (struct jedec_private *)map->fldrv_priv; - unsigned long base; - unsigned long off; - - if (start + len > mtd->size) - return -EIO; - - puts("Here"); - - while (len != 0) - { - struct jedec_flash_chip *chip = priv->chips; - unsigned long bank; - unsigned long boffset; - - // Compute the base of the flash. - off = start % (chip->size << chip->addrshift); - base = start - off; - - // Perform banked addressing translation. - bank = base & (~(priv->bank_fill[0]-1)); - boffset = base & (priv->bank_fill[0]-1); - bank = (bank/priv->bank_fill[0])*map->bank_size; - base = bank + boffset; - - xprintf("Flasing %X %X %X\n",base,chip->size,len); - - // Loop over this page - for (; off != (chip->size << chip->addrshift) && len != 0; start++, len--, off++,buf++) - { - unsigned char oldbyte = map->read8(map,base+off); - unsigned char Last[4]; - unsigned long Count = 0; - -// putc('.'); - - if (oldbyte == *buf) - continue; - if (((~oldbyte) & *buf) != 0) - printk("mtd: warn: Trying to set a 0 to a 1\n"); - - // Write - flwrite(0xAA,0x555); - flwrite(0x55,0x2AA); - flwrite(0xA0,0x555); - map->write8(map,*buf,base + off); - Last[0] = map->read8(map,base + off); - Last[1] = map->read8(map,base + off); - Last[2] = map->read8(map,base + off); - - /* Wait for the flash to finish the operation. We store the last 4 - status bytes that have been retrieved so we can determine why - it failed. The toggle bits keep toggling when there is a - failure */ - for (Count = 3; Last[(Count - 1) % 4] != Last[(Count - 2) % 4] && - Count < 10000; Count++) - Last[Count % 4] = map->read8(map,base + off); - if (Last[(Count - 1) % 4] != *buf) - { - jedec_flash_failed(Last[(Count - 3) % 4]); - return -EIO; - } - } - } - *retlen = len; - return 0; -} - -/* This is used to enhance the speed of the erase routine, - when things are being done to multiple chips it is possible to - parallize the operations, particularly full memory erases of multi - chip memories benifit */ -static void jedec_flash_chip_scan(struct jedec_private *priv,unsigned long start, - unsigned long len) -{ - unsigned int I; - - // Zero the records - for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) - priv->chips[I].start = priv->chips[I].length = 0; - - // Intersect the region with each chip - for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) - { - struct jedec_flash_chip *chip = priv->chips + I; - unsigned long ByteStart; - unsigned long ChipEndByte = chip->offset + (chip->size << chip->addrshift); - - // End is before this chip or the start is after it - if (start+len < chip->offset || - ChipEndByte - (1 << chip->addrshift) < start) - continue; - - if (start < chip->offset) - { - ByteStart = chip->offset; - chip->start = 0; - } - else - { - chip->start = (start - chip->offset + (1 << chip->addrshift)-1) >> chip->addrshift; - ByteStart = start; - } - - if (start + len >= ChipEndByte) - chip->length = (ChipEndByte - ByteStart) >> chip->addrshift; - else - chip->length = (start + len - ByteStart + (1 << chip->addrshift)-1) >> chip->addrshift; - } -} - /*}}}*/ diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/map_ram.c linux/drivers/mtd/map_ram.c --- v2.4.5/linux/drivers/mtd/map_ram.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/mtd/map_ram.c Wed Dec 31 16:00:00 1969 @@ -1,137 +0,0 @@ -/* - * Common code to handle map devices which are simple RAM - * (C) 2000 Red Hat. GPL'd. - * $Id: map_ram.c,v 1.7 2000/12/10 01:39:13 dwmw2 Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include - -#include - - -static int mapram_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); -static int mapram_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *); -static int mapram_erase (struct mtd_info *, struct erase_info *); -static void mapram_nop (struct mtd_info *); - -static const char im_name[] = "map_ram_probe"; - -/* This routine is made available to other mtd code via - * inter_module_register. It must only be accessed through - * inter_module_get which will bump the use count of this module. The - * addresses passed back in mtd are valid as long as the use count of - * this module is non-zero, i.e. between inter_module_get and - * inter_module_put. Keith Owens 29 Oct 2000. - */ - -static struct mtd_info *map_ram_probe(struct map_info *map) -{ - struct mtd_info *mtd; - - /* Check the first byte is RAM */ - map->write8(map, 0x55, 0); - if (map->read8(map, 0) != 0x55) - return NULL; - - map->write8(map, 0xAA, 0); - if (map->read8(map, 0) != 0xAA) - return NULL; - - /* Check the last byte is RAM */ - map->write8(map, 0x55, map->size-1); - if (map->read8(map, map->size-1) != 0x55) - return NULL; - - map->write8(map, 0xAA, map->size-1); - if (map->read8(map, map->size-1) != 0xAA) - return NULL; - - /* OK. It seems to be RAM. */ - - mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); - if (!mtd) - return NULL; - - memset(mtd, 0, sizeof(*mtd)); - - map->im_name = im_name; - map->fldrv_destroy = mapram_nop; - mtd->priv = map; - mtd->name = map->name; - mtd->type = MTD_RAM; - mtd->erasesize = 0x10000; - mtd->size = map->size; - mtd->erase = mapram_erase; - mtd->read = mapram_read; - mtd->write = mapram_write; - mtd->sync = mapram_nop; - mtd->flags = MTD_CAP_RAM | MTD_VOLATILE; - mtd->erasesize = PAGE_SIZE; - - return mtd; -} - - -static int mapram_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) -{ - struct map_info *map = (struct map_info *)mtd->priv; - - map->copy_from(map, buf, from, len); - *retlen = len; - return 0; -} - -static int mapram_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) -{ - struct map_info *map = (struct map_info *)mtd->priv; - - map->copy_to(map, to, buf, len); - *retlen = len; - return 0; -} - -static int mapram_erase (struct mtd_info *mtd, struct erase_info *instr) -{ - /* Yeah, it's inefficient. Who cares? It's faster than a _real_ - flash erase. */ - struct map_info *map = (struct map_info *)mtd->priv; - unsigned long i; - - for (i=0; ilen; i++) - map->write8(map, 0xFF, instr->addr + i); - - if (instr->callback) - instr->callback(instr); - - return 0; -} - -static void mapram_nop(struct mtd_info *mtd) -{ - /* Nothing to see here */ -} - -#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) -#define map_ram_init init_module -#define map_ram_exit cleanup_module -#endif - -static int __init map_ram_init(void) -{ - inter_module_register(im_name, THIS_MODULE, &map_ram_probe); - return 0; -} - -static void __exit map_ram_exit(void) -{ - inter_module_unregister(im_name); -} - -module_init(map_ram_init); -module_exit(map_ram_exit); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/map_rom.c linux/drivers/mtd/map_rom.c --- v2.4.5/linux/drivers/mtd/map_rom.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/mtd/map_rom.c Wed Dec 31 16:00:00 1969 @@ -1,94 +0,0 @@ -/* - * Common code to handle map devices which are simple ROM - * (C) 2000 Red Hat. GPL'd. - * $Id: map_rom.c,v 1.10 2000/12/10 01:39:13 dwmw2 Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include - -#include - -static int maprom_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); -static int maprom_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *); -static void maprom_nop (struct mtd_info *); - -static const char im_name[] = "map_rom_probe"; - -/* This routine is made available to other mtd code via - * inter_module_register. It must only be accessed through - * inter_module_get which will bump the use count of this module. The - * addresses passed back in mtd are valid as long as the use count of - * this module is non-zero, i.e. between inter_module_get and - * inter_module_put. Keith Owens 29 Oct 2000. - */ - -struct mtd_info *map_rom_probe(struct map_info *map) -{ - struct mtd_info *mtd; - - mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); - if (!mtd) - return NULL; - - memset(mtd, 0, sizeof(*mtd)); - - map->im_name = im_name; - map->fldrv_destroy = maprom_nop; - mtd->priv = map; - mtd->name = map->name; - mtd->type = MTD_ROM; - mtd->size = map->size; - mtd->read = maprom_read; - mtd->write = maprom_write; - mtd->sync = maprom_nop; - mtd->flags = MTD_CAP_ROM; - mtd->erasesize = 131072; - - return mtd; -} - - -static int maprom_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) -{ - struct map_info *map = (struct map_info *)mtd->priv; - - map->copy_from(map, buf, from, len); - *retlen = len; - return 0; -} - -static void maprom_nop(struct mtd_info *mtd) -{ - /* Nothing to see here */ -} - -static int maprom_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) -{ - printk(KERN_NOTICE "maprom_write called\n"); - return -EIO; -} - -#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) -#define map_rom_init init_module -#define map_rom_exit cleanup_module -#endif - -static int __init map_rom_init(void) -{ - inter_module_register(im_name, THIS_MODULE, &map_rom_probe); - return 0; -} - -static void __exit map_rom_exit(void) -{ - inter_module_unregister(im_name); -} - -module_init(map_rom_init); -module_exit(map_rom_exit); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/maps/Config.in linux/drivers/mtd/maps/Config.in --- v2.4.5/linux/drivers/mtd/maps/Config.in Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/maps/Config.in Tue Jun 12 10:30:27 2001 @@ -0,0 +1,41 @@ +# drivers/mtd/maps/Config.in + +# $Id: Config.in,v 1.9.2.1 2001/06/09 19:43:49 dwmw2 Exp $ + +mainmenu_option next_comment + +comment 'Mapping drivers for chip access' + +dep_tristate ' CFI Flash device in physical memory map' CONFIG_MTD_PHYSMAP $CONFIG_MTD_CFI +if [ "$CONFIG_MTD_PHYSMAP" = "y" -o "$CONFIG_MTD_PHYSMAP" = "m" ]; then + hex ' Physical start address of flash mapping' CONFIG_MTD_PHYSMAP_START 0x8000000 + hex ' Physical length of flash mapping' CONFIG_MTD_PHYSMAP_LEN 0x4000000 + int ' Bus width in octets' CONFIG_MTD_PHYSMAP_BUSWIDTH 2 +fi + +dep_tristate ' Sun Microsystems userflash support' CONFIG_MTD_SUN_UFLASH $CONFIG_SPARC64 +dep_tristate ' CFI Flash device mapped on Nora' CONFIG_MTD_NORA $CONFIG_MTD_CFI +dep_tristate ' CFI Flash device mapped on Photron PNC-2000' CONFIG_MTD_PNC2000 $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS +dep_tristate ' CFI Flash device mapped on RPX Lite or CLLF' CONFIG_MTD_RPXLITE $CONFIG_MTD_CFI +dep_tristate ' CFI Flash device mapped on AMD SC520 CDP' CONFIG_MTD_SC520CDP $CONFIG_MTD_CFI +dep_tristate ' CFI Flash device mapped on AMD NetSc520' CONFIG_MTD_NETSC520 $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS +dep_tristate ' CFI Flash device mapped on Arcom SBC-GXx boards' CONFIG_MTD_SBC_GXX $CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_PARTITIONS +dep_tristate ' CFI Flash device mapped on Arcom ELAN-104NC' CONFIG_MTD_ELAN_104NC $CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_PARTITIONS +dep_tristate ' CFI Flash device mapped on StrongARM SA11x0' CONFIG_MTD_SA1100 $CONFIG_MTD_CFI $CONFIG_ARCH_SA1100 $CONFIG_MTD_PARTITIONS + dep_bool ' Support for RedBoot partition tables on SA11x0' CONFIG_MTD_SA1100_REDBOOT_PARTITIONS $CONFIG_MTD_SA1100 $CONFIG_MTD_REDBOOT_PARTS + dep_bool ' Support for Compaq bootldr partition tables on SA11x0' CONFIG_MTD_SA1100_BOOTLDR_PARTITIONS $CONFIG_MTD_SA1100 $CONFIG_MTD_BOOTLDR_PARTS +dep_tristate ' CFI Flash device mapped on DC21285 Footbridge' CONFIG_MTD_DC21285 $CONFIG_MTD_CFI $CONFIG_ARCH_FOOTBRIDGE $CONFIG_MTD_PARTITIONS +dep_tristate ' CFI Flash device mapped on the XScale IQ80310 board' CONFIG_MTD_IQ80310 $CONFIG_MTD_CFI $CONFIG_XSCALE_IQ80310 +dep_tristate ' CFI Flash device mapped on D-Box2' CONFIG_MTD_DBOX2 $CONFIG_MTD_CFI_INTELSTD $CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_CFI_AMDSTD +dep_tristate ' Flash chip mapping on ITE QED-4N-S01B, Globespan IVR or custom board' CONFIG_MTD_CSTM_MIPS_IXX $CONFIG_MTD_CFI $CONFIG_MTD_JEDEC $CONFIG_MTD_PARTITIONS +if [ "$CONFIG_MTD_CSTM_MIPS_IXX" = "y" -o "$CONFIG_MTD_CSTM_MIPS_IXX" = "m" ]; then + hex ' Physical start address of flash mapping' CONFIG_MTD_CSTM_MIPS_IXX_START 0x8000000 + hex ' Physical length of flash mapping' CONFIG_MTD_CSTM_MIPS_IXX_LEN 0x4000000 + int ' Bus width in octets' CONFIG_MTD_CSTM_MIPS_IXX_BUSWIDTH 2 +fi +dep_tristate ' CFI Flash device mapping on FlagaDM' CONFIG_MTD_CFI_FLAGADM $CONFIG_MTD_CFI +dep_tristate ' JEDEC Flash device mapped on Mixcom piggyback card' CONFIG_MTD_MIXMEM $CONFIG_MTD_JEDEC +dep_tristate ' JEDEC Flash device mapped on Octagon 5066 SBC' CONFIG_MTD_OCTAGON $CONFIG_MTD_JEDEC +dep_tristate ' JEDEC Flash device mapped on Tempustech VMAX SBC301' CONFIG_MTD_VMAX $CONFIG_MTD_JEDEC +dep_tristate ' Momenco Ocelot boot flash device' CONFIG_MTD_OCELOT $CONFIG_MOMENCO_OCELOT +endmenu diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/maps/Makefile linux/drivers/mtd/maps/Makefile --- v2.4.5/linux/drivers/mtd/maps/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/maps/Makefile Tue Jun 12 10:30:27 2001 @@ -0,0 +1,29 @@ +# +# linux/drivers/maps/Makefile +# +# $Id: Makefile,v 1.9.2.1 2001/06/09 19:43:49 dwmw2 Exp $ + +O_TARGET := mapslink.o + +# Chip mappings + +obj-$(CONFIG_MTD_CFI_FLAGADM) += cfi_flagadm.o +obj-$(CONFIG_MTD_CSTM_MIPS_IXX) += cstm_mips_ixx.o +obj-$(CONFIG_MTD_DC21285) += dc21285.o +obj-$(CONFIG_MTD_ELAN_104NC) += elan-104nc.o +obj-$(CONFIG_MTD_IQ80310) += iq80310.o +obj-$(CONFIG_MTD_NORA) += nora.o +obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o +obj-$(CONFIG_MTD_PHYSMAP) += physmap.o +obj-$(CONFIG_MTD_PNC2000) += pnc2000.o +obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o +obj-$(CONFIG_MTD_SA1100) += sa1100-flash.o +obj-$(CONFIG_MTD_SBC_GXX) += sbc_gxx.o +obj-$(CONFIG_MTD_SC520CDP) += sc520cdp.o +obj-$(CONFIG_MTD_NETSC520) += netsc520.o +obj-$(CONFIG_MTD_SUN_UFLASH) += sun_uflash.o +obj-$(CONFIG_MTD_VMAX) += vmax301.o +obj-$(CONFIG_MTD_DBOX2) += dbox2-flash.o +obj-$(CONFIG_MTD_OCELOT) += ocelot.o + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/maps/cfi_flagadm.c linux/drivers/mtd/maps/cfi_flagadm.c --- v2.4.5/linux/drivers/mtd/maps/cfi_flagadm.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/maps/cfi_flagadm.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,184 @@ +/* + * Copyright © 2001 Flaga hf. Medical Devices, Kári Davíđsson + * + * $Id: cfi_flagadm.c,v 1.5 2001/05/29 15:47:49 kd Exp $ + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + + +/* We split the flash chip up into four parts. + * 1: bootloader firts 128k (0x00000000 - 0x0001FFFF) size 0x020000 + * 2: kernel 640k (0x00020000 - 0x000BFFFF) size 0x0A0000 + * 3: compressed 1536k root ramdisk (0x000C0000 - 0x0023FFFF) size 0x180000 + * 4: writeable diskpartition (jffs)(0x00240000 - 0x003FFFFF) size 0x1C0000 + */ + +#define FLASH_PHYS_ADDR 0x40000000 +#define FLASH_SIZE 0x400000 + +#define FLASH_PARTITION0_ADDR 0x00000000 +#define FLASH_PARTITION0_SIZE 0x00020000 + +#define FLASH_PARTITION1_ADDR 0x00020000 +#define FLASH_PARTITION1_SIZE 0x000A0000 + +#define FLASH_PARTITION2_ADDR 0x000C0000 +#define FLASH_PARTITION2_SIZE 0x00180000 + +#define FLASH_PARTITION3_ADDR 0x00240000 +#define FLASH_PARTITION3_SIZE 0x001C0000 + +__u8 flagadm_read8(struct map_info *map, unsigned long ofs) +{ + return __raw_readb(map->map_priv_1 + ofs); +} + +__u16 flagadm_read16(struct map_info *map, unsigned long ofs) +{ + return __raw_readw(map->map_priv_1 + ofs); +} + +__u32 flagadm_read32(struct map_info *map, unsigned long ofs) +{ + return __raw_readl(map->map_priv_1 + ofs); +} + +void flagadm_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) +{ + memcpy_fromio(to, map->map_priv_1 + from, len); +} + +void flagadm_write8(struct map_info *map, __u8 d, unsigned long adr) +{ + __raw_writeb(d, map->map_priv_1 + adr); + mb(); +} + +void flagadm_write16(struct map_info *map, __u16 d, unsigned long adr) +{ + __raw_writew(d, map->map_priv_1 + adr); + mb(); +} + +void flagadm_write32(struct map_info *map, __u32 d, unsigned long adr) +{ + __raw_writel(d, map->map_priv_1 + adr); + mb(); +} + +void flagadm_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) +{ + memcpy_toio(map->map_priv_1 + to, from, len); +} + +struct map_info flagadm_map = { + name: "FlagaDM flash device", + size: FLASH_SIZE, + buswidth: 2, + read8: flagadm_read8, + read16: flagadm_read16, + read32: flagadm_read32, + copy_from: flagadm_copy_from, + write8: flagadm_write8, + write16: flagadm_write16, + write32: flagadm_write32, + copy_to: flagadm_copy_to +}; + +struct mtd_partition flagadm_parts[] = { + { + name : "Bootloader", + offset : FLASH_PARTITION0_ADDR, + size : FLASH_PARTITION0_SIZE + }, + { + name : "Kernel image", + offset : FLASH_PARTITION1_ADDR, + size : FLASH_PARTITION1_SIZE + }, + { + name : "Initial ramdisk image", + offset : FLASH_PARTITION2_ADDR, + size : FLASH_PARTITION2_SIZE + }, + { + name : "Persistant storage", + offset : FLASH_PARTITION3_ADDR, + size : FLASH_PARTITION3_SIZE + } +}; + +#define PARTITION_COUNT (sizeof(flagadm_parts)/sizeof(struct mtd_partition)) + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define init_flagadm init_module +#define cleanup_flagadm cleanup_module +#endif + +static struct mtd_info *mymtd; + +int __init init_flagadm(void) +{ + printk(KERN_NOTICE "FlagaDM flash device: %x at %x\n", + FLASH_SIZE, FLASH_PHYS_ADDR); + + flagadm_map.map_priv_1 = (unsigned long)ioremap(FLASH_PHYS_ADDR, + FLASH_SIZE); + + if (!flagadm_map.map_priv_1) { + printk("Failed to ioremap\n"); + return -EIO; + } + mymtd = do_map_probe("cfi", &flagadm_map); + if (mymtd) { + mymtd->module = THIS_MODULE; + add_mtd_partitions(mymtd, flagadm_parts, PARTITION_COUNT); + printk(KERN_NOTICE "FlagaDM flash device initialized\n"); + return 0; + } + + iounmap((void *)flagadm_map.map_priv_1); + return -ENXIO; +} + +static void __exit cleanup_flagadm(void) +{ + if (mymtd) { + del_mtd_partitions(mymtd); + map_destroy(mymtd); + } + if (flagadm_map.map_priv_1) { + iounmap((void *)flagadm_map.map_priv_1); + flagadm_map.map_priv_1 = 0; + } +} + +module_init(init_flagadm); +module_exit(cleanup_flagadm); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/maps/cstm_mips_ixx.c linux/drivers/mtd/maps/cstm_mips_ixx.c --- v2.4.5/linux/drivers/mtd/maps/cstm_mips_ixx.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/maps/cstm_mips_ixx.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,314 @@ +/* + * $Id: cstm_mips_ixx.c,v 1.3 2001/06/02 14:52:23 dwmw2 Exp $ + * + * Mapping of a custom board with both AMD CFI and JEDEC flash in partitions. + * Config with both CFI and JEDEC device support. + * + * Basically physmap.c with the addition of partitions and + * an array of mapping info to accomodate more than one flash type per board. + * + * Copyright 2000 MontaVista Software Inc. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) +#include +#endif + +__u8 cstm_mips_ixx_read8(struct map_info *map, unsigned long ofs) +{ + return *(__u8 *)(map->map_priv_1 + ofs); +} + +__u16 cstm_mips_ixx_read16(struct map_info *map, unsigned long ofs) +{ + return *(__u16 *)(map->map_priv_1 + ofs); +} + +__u32 cstm_mips_ixx_read32(struct map_info *map, unsigned long ofs) +{ + return *(__u32 *)(map->map_priv_1 + ofs); +} + +void cstm_mips_ixx_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) +{ + memcpy_fromio(to, map->map_priv_1 + from, len); +} + +void cstm_mips_ixx_write8(struct map_info *map, __u8 d, unsigned long adr) +{ + *(__u8 *)(map->map_priv_1 + adr) = d; +} + +void cstm_mips_ixx_write16(struct map_info *map, __u16 d, unsigned long adr) +{ + *(__u16 *)(map->map_priv_1 + adr) = d; +} + +void cstm_mips_ixx_write32(struct map_info *map, __u32 d, unsigned long adr) +{ + *(__u32 *)(map->map_priv_1 + adr) = d; +} + +void cstm_mips_ixx_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) +{ + memcpy_toio(map->map_priv_1 + to, from, len); +} + +#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) +#define CC_GCR 0xB4013818 +#define CC_GPBCR 0xB401380A +#define CC_GPBDR 0xB4013808 +#define CC_M68K_DEVICE 1 +#define CC_M68K_FUNCTION 6 +#define CC_CONFADDR 0xB8004000 +#define CC_CONFDATA 0xB8004004 +#define CC_FC_FCR 0xB8002004 +#define CC_FC_DCR 0xB8002008 +#define CC_GPACR 0xB4013802 +#define CC_GPAICR 0xB4013804 +#endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */ + +void cstm_mips_ixx_set_vpp(struct map_info *map,int vpp) +{ + if (vpp) { +#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) + __u16 data; + __u8 data1; + static u8 first = 1; + + // Set GPIO port B pin3 to high + data = *(__u16 *)(CC_GPBCR); + data = (data & 0xff0f) | 0x0040; + *(__u16 *)CC_GPBCR = data; + *(__u8 *)CC_GPBDR = (*(__u8*)CC_GPBDR) | 0x08; + if (first) { + first = 0; + /* need to have this delay for first + enabling vpp after powerup */ + udelay(40); + } +#endif /* CONFIG_MIPS_ITE8172 */ + } + else { +#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) + __u16 data; + + // Set GPIO port B pin3 to high + data = *(__u16 *)(CC_GPBCR); + data = (data & 0xff3f) | 0x0040; + *(__u16 *)CC_GPBCR = data; + *(__u8 *)CC_GPBDR = (*(__u8*)CC_GPBDR) & 0xf7; +#endif /* CONFIG_MIPS_ITE8172 */ + } +} + +const struct map_info basic_cstm_mips_ixx_map = { + NULL, + 0, + 0, + cstm_mips_ixx_read8, + cstm_mips_ixx_read16, + cstm_mips_ixx_read32, + cstm_mips_ixx_copy_from, + cstm_mips_ixx_write8, + cstm_mips_ixx_write16, + cstm_mips_ixx_write32, + cstm_mips_ixx_copy_to, + cstm_mips_ixx_set_vpp, + 0, + 0 +}; + +/* board and partition description */ + +#define MAX_PHYSMAP_PARTITIONS 8 +struct cstm_mips_ixx_info { + char *name; + unsigned long window_addr; + unsigned long window_size; + int buswidth; + int num_partitions; +}; + +#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) +#define PHYSMAP_NUMBER 1 // number of board desc structs needed, one per contiguous flash type +const struct cstm_mips_ixx_info cstm_mips_ixx_board_desc[PHYSMAP_NUMBER] = +{ + { // 28F128J3A in 2x16 configuration + "big flash", // name + 0x08000000, // window_addr + 0x02000000, // window_size + 4, // buswidth + 1, // num_partitions + } + +}; +static struct mtd_partition cstm_mips_ixx_partitions[PHYSMAP_NUMBER][MAX_PHYSMAP_PARTITIONS] = { +{ // 28F128J3A in 2x16 configuration + { + name: "main partition ", + size: 0x02000000, // 128 x 2 x 128k byte sectors + offset: 0, + }, +}, +}; +#else /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */ +#define PHYSMAP_NUMBER 1 // number of board desc structs needed, one per contiguous flash type +const struct cstm_mips_ixx_info cstm_mips_ixx_board_desc[PHYSMAP_NUMBER] = +{ + { + "MTD flash", // name + CONFIG_MTD_CSTM_MIPS_IXX_START, // window_addr + CONFIG_MTD_CSTM_MIPS_IXX_LEN, // window_size + CONFIG_MTD_CSTM_MIPS_IXX_BUSWIDTH, // buswidth + 1, // num_partitions + }, + +}; +static struct mtd_partition cstm_mips_ixx_partitions[PHYSMAP_NUMBER][MAX_PHYSMAP_PARTITIONS] = { +{ + { + name: "main partition", + size: CONFIG_MTD_CSTM_MIPS_IXX_LEN, + offset: 0, + }, +}, +}; +#endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */ + +struct map_info cstm_mips_ixx_map[PHYSMAP_NUMBER]; + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define init_cstm_mips_ixx init_module +#define cleanup_cstm_mips_ixx cleanup_module +#endif + +int __init init_cstm_mips_ixx(void) +{ + int i; + int jedec; + struct mtd_info *mymtd; + struct mtd_partition *parts; + + /* Initialize mapping */ + for (i=0;imodule = THIS_MODULE; + + cstm_mips_ixx_map[i].map_priv_2 = (unsigned long)mymtd; + add_mtd_partitions(mymtd, parts, cstm_mips_ixx_board_desc[i].num_partitions); + } + else + return -ENXIO; + } + return 0; +} + +static void __exit cleanup_cstm_mips_ixx(void) +{ + int i; + struct mtd_info *mymtd; + + for (i=0;i> 8 >>1; // Bug: we must shift one more bit + + /* need to set ITE flash to 32 bits instead of default 8 */ +#ifdef CONFIG_MIPS_IVR + *(__u32 *)CC_FC_FCR = 0x55; + *(__u32 *)CC_GPACR = 0xfffc; +#else + *(__u32 *)CC_FC_FCR = 0x77; +#endif + /* turn bursting off */ + *(__u32 *)CC_FC_DCR = 0x0; + + /* setup for one chip 4 byte PCI access */ + PCISetULongByOffset(CC_M68K_DEVICE, CC_M68K_FUNCTION, 0x60, size | base); + PCISetULongByOffset(CC_M68K_DEVICE, CC_M68K_FUNCTION, 0x64, 0x02); +} +#endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */ + +module_init(init_cstm_mips_ixx); +module_exit(cleanup_cstm_mips_ixx); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/maps/dbox2-flash.c linux/drivers/mtd/maps/dbox2-flash.c --- v2.4.5/linux/drivers/mtd/maps/dbox2-flash.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/maps/dbox2-flash.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,151 @@ +/* + * $Id: dbox2-flash.c,v 1.2 2001/04/26 15:42:43 dwmw2 Exp $ + * + * Nokia / Sagem D-Box 2 flash driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* partition_info gives details on the logical partitions that the split the + * single flash device into. If the size if zero we use up to the end of the + * device. */ +static struct mtd_partition partition_info[]= {{name: "BR bootloader", // raw + size: 128 * 1024, + offset: 0, + mask_flags: MTD_WRITEABLE}, + {name: "PPC bootloader", // flfs + size: 128 * 1024, + offset: MTDPART_OFS_APPEND, + mask_flags: 0}, + {name: "Kernel", // idxfs + size: 768 * 1024, + offset: MTDPART_OFS_APPEND, + mask_flags: 0}, + {name: "System", // jffs + size: MTDPART_SIZ_FULL, + offset: MTDPART_OFS_APPEND, + mask_flags: 0}}; + +#define NUM_PARTITIONS (sizeof(partition_info) / sizeof(partition_info[0])) + +#define WINDOW_ADDR 0x10000000 +#define WINDOW_SIZE 0x800000 + +static struct mtd_info *mymtd; + +__u8 dbox2_flash_read8(struct map_info *map, unsigned long ofs) +{ + return __raw_readb(map->map_priv_1 + ofs); +} + +__u16 dbox2_flash_read16(struct map_info *map, unsigned long ofs) +{ + return __raw_readw(map->map_priv_1 + ofs); +} + +__u32 dbox2_flash_read32(struct map_info *map, unsigned long ofs) +{ + return __raw_readl(map->map_priv_1 + ofs); +} + +void dbox2_flash_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) +{ + memcpy_fromio(to, map->map_priv_1 + from, len); +} + +void dbox2_flash_write8(struct map_info *map, __u8 d, unsigned long adr) +{ + __raw_writeb(d, map->map_priv_1 + adr); + mb(); +} + +void dbox2_flash_write16(struct map_info *map, __u16 d, unsigned long adr) +{ + __raw_writew(d, map->map_priv_1 + adr); + mb(); +} + +void dbox2_flash_write32(struct map_info *map, __u32 d, unsigned long adr) +{ + __raw_writel(d, map->map_priv_1 + adr); + mb(); +} + +void dbox2_flash_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) +{ + memcpy_toio(map->map_priv_1 + to, from, len); +} + +struct map_info dbox2_flash_map = { + name: "D-Box 2 flash memory", + size: WINDOW_SIZE, + buswidth: 4, + read8: dbox2_flash_read8, + read16: dbox2_flash_read16, + read32: dbox2_flash_read32, + copy_from: dbox2_flash_copy_from, + write8: dbox2_flash_write8, + write16: dbox2_flash_write16, + write32: dbox2_flash_write32, + copy_to: dbox2_flash_copy_to +}; + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define init_dbox2_flash init_module +#define cleanup_dbox2_flash cleanup_module +#endif + +mod_init_t init_dbox2_flash(void) +{ + printk(KERN_NOTICE "D-Box 2 flash driver (size->0x%X mem->0x%X)\n", WINDOW_SIZE, WINDOW_ADDR); + dbox2_flash_map.map_priv_1 = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); + + if (!dbox2_flash_map.map_priv_1) { + printk("Failed to ioremap\n"); + return -EIO; + } + + // Probe for dual Intel 28F320 or dual AMD + mymtd = do_map_probe("cfi", &dbox2_flash_map); + if (!mymtd) { + // Probe for single Intel 28F640 + dbox2_flash_map.buswidth = 2; + + mymtd = do_map_probe("cfi", &dbox2_flash_map); + } + + if (mymtd) { + mymtd->module = THIS_MODULE; + + /* Create MTD devices for each partition. */ + add_mtd_partitions(mymtd, partition_info, NUM_PARTITIONS); + + return 0; + } + + iounmap((void *)dbox2_flash_map.map_priv_1); + return -ENXIO; +} + +mod_exit_t cleanup_dbox2_flash(void) +{ + if (mymtd) { + del_mtd_partitions(mymtd); + map_destroy(mymtd); + } + if (dbox2_flash_map.map_priv_1) { + iounmap((void *)dbox2_flash_map.map_priv_1); + dbox2_flash_map.map_priv_1 = 0; + } +} + +module_init(init_dbox2_flash); +module_exit(cleanup_dbox2_flash); + diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/maps/dc21285.c linux/drivers/mtd/maps/dc21285.c --- v2.4.5/linux/drivers/mtd/maps/dc21285.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/maps/dc21285.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,193 @@ +/* + * MTD map driver for flash on the DC21285 (the StrongARM-110 companion chip) + * + * (C) 2000 Nicolas Pitre + * + * This code is GPL + * + * $Id: dc21285.c,v 1.4 2001/04/26 15:40:23 dwmw2 Exp $ + */ + +#include +#include +#include + +#include +#include +#include + +#include +#include + + +static struct mtd_info *mymtd; + +__u8 dc21285_read8(struct map_info *map, unsigned long ofs) +{ + return *(__u8*)(map->map_priv_1 + ofs); +} + +__u16 dc21285_read16(struct map_info *map, unsigned long ofs) +{ + return *(__u16*)(map->map_priv_1 + ofs); +} + +__u32 dc21285_read32(struct map_info *map, unsigned long ofs) +{ + return *(__u32*)(map->map_priv_1 + ofs); +} + +void dc21285_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) +{ + memcpy(to, (void*)(map->map_priv_1 + from), len); +} + +void dc21285_write8(struct map_info *map, __u8 d, unsigned long adr) +{ + *CSR_ROMWRITEREG = adr; + adr &= ~3; + *(__u8*)(map->map_priv_1 + adr) = d; +} + +void dc21285_write16(struct map_info *map, __u16 d, unsigned long adr) +{ + *CSR_ROMWRITEREG = adr; + adr &= ~1; + *(__u16*)(map->map_priv_1 + adr) = d; +} + +void dc21285_write32(struct map_info *map, __u32 d, unsigned long adr) +{ + *(__u32*)(map->map_priv_1 + adr) = d; +} + +void dc21285_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) +{ + switch (map->buswidth) { + case 4: + while (len > 0) { + __u32 d = *((__u32*)from)++; + dc21285_write32(map, d, to); + to += 4; + len -= 4; + } + break; + case 2: + while (len > 0) { + __u16 d = *((__u16*)from)++; + dc21285_write16(map, d, to); + to += 2; + len -= 2; + } + break; + case 1: + while (len > 0) { + __u8 d = *((__u8*)from)++; + dc21285_write8(map, d, to); + to++; + len--; + } + break; + } +} + +struct map_info dc21285_map = { + name: "DC21285 flash", + size: 16*1024*1024, + read8: dc21285_read8, + read16: dc21285_read16, + read32: dc21285_read32, + copy_from: dc21285_copy_from, + write8: dc21285_write8, + write16: dc21285_write16, + write32: dc21285_write32, + copy_to: dc21285_copy_to +}; + + +/* Partition stuff */ +static struct mtd_partition *dc21285_parts; + +extern int parse_redboot_partitions(struct mtd_info *, struct mtd_partition **); + +int __init init_dc21285(void) +{ + /* Determine buswidth */ + switch (*CSR_SA110_CNTL & (3<<14)) { + case SA110_CNTL_ROMWIDTH_8: + dc21285_map.buswidth = 1; + break; + case SA110_CNTL_ROMWIDTH_16: + dc21285_map.buswidth = 2; + break; + case SA110_CNTL_ROMWIDTH_32: + dc21285_map.buswidth = 4; + break; + default: + printk (KERN_ERR "DC21285 flash: undefined buswidth\n"); + return -ENXIO; + } + printk (KERN_NOTICE "DC21285 flash support (%d-bit buswidth)\n", + dc21285_map.buswidth*8); + + /* Let's map the flash area */ + dc21285_map.map_priv_1 = (unsigned long)__ioremap(DC21285_FLASH, 16*1024*1024, 0); + if (!dc21285_map.map_priv_1) { + printk("Failed to ioremap\n"); + return -EIO; + } + + mymtd = do_map_probe("cfi", &dc21285_map); + if (mymtd) { + int nrparts; + + mymtd->module = THIS_MODULE; + + /* partition fixup */ + + nrparts = parse_redboot_partitions(mymtd, &dc21285_parts); + if (nrparts <=0) { + printk(KERN_NOTICE "RedBoot partition table failed\n"); + iounmap((void *)dc21285_map.map_priv_1); + return -ENXIO; + } + + add_mtd_partitions(mymtd, dc21285_parts, nrparts); + + /* + * Flash timing is determined with bits 19-16 of the + * CSR_SA110_CNTL. The value is the number of wait cycles, or + * 0 for 16 cycles (the default). Cycles are 20 ns. + * Here we use 7 for 140 ns flash chips. + */ + /* access time */ + *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x000f0000) | (7 << 16)); + /* burst time */ + *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x00f00000) | (7 << 20)); + /* tristate time */ + *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x0f000000) | (7 << 24)); + + return 0; + } + + iounmap((void *)dc21285_map.map_priv_1); + return -ENXIO; +} + +static void __exit cleanup_dc21285(void) +{ + if (mymtd) { + del_mtd_device(mymtd); + map_destroy(mymtd); + mymtd = NULL; + } + if (dc21285_map.map_priv_1) { + iounmap((void *)dc21285_map.map_priv_1); + dc21285_map.map_priv_1 = 0; + } + if(dc21285_parts) + kfree(dc21285_parts); +} + +module_init(init_dc21285); +module_exit(cleanup_dc21285); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/maps/elan-104nc.c linux/drivers/mtd/maps/elan-104nc.c --- v2.4.5/linux/drivers/mtd/maps/elan-104nc.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/maps/elan-104nc.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,277 @@ +/* elan-104nc.c -- MTD map driver for Arcom Control Systems ELAN-104NC + + Copyright (C) 2000 Arcom Control System Ltd + + 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 + + $Id: elan-104nc.c,v 1.10 2001/06/02 14:30:44 dwmw2 Exp $ + +The ELAN-104NC has up to 8 Mibyte of Intel StrataFlash (28F320/28F640) in x16 +mode. This drivers uses the CFI probe and Intel Extended Command Set drivers. + +The flash is accessed as follows: + + 32 kbyte memory window at 0xb0000-0xb7fff + + 16 bit I/O port (0x22) for some sort of paging. + +The single flash device is divided into 3 partition which appear as seperate +MTD devices. + +Linux thinks that the I/O port is used by the PIC and hence check_region() will +always fail. So we don't do it. I just hope it doesn't break anything. +*/ +#include +#include +#include +#include +#include + +#include +#include + +#define WINDOW_START 0xb0000 +/* Number of bits in offset. */ +#define WINDOW_SHIFT 15 +#define WINDOW_LENGTH (1 << WINDOW_SHIFT) +/* The bits for the offset into the window. */ +#define WINDOW_MASK (WINDOW_LENGTH-1) +#define PAGE_IO 0x22 +#define PAGE_IO_SIZE 2 + +static volatile int page_in_window = -1; // Current page in window. +static unsigned long iomapadr; +static spinlock_t elan_104nc_spin = SPIN_LOCK_UNLOCKED; + +/* partition_info gives details on the logical partitions that the split the + * single flash device into. If the size if zero we use up to the end of the + * device. */ +static struct mtd_partition partition_info[]={ + { name: "ELAN-104NC flash boot partition", + offset: 0, + size: 640*1024 }, + { name: "ELAN-104NC flash partition 1", + offset: 640*1024, + size: 896*1024 }, + { name: "ELAN-104NC flash partition 2", + offset: (640+896)*1024 } +}; +#define NUM_PARTITIONS (sizeof(partition_info)/sizeof(partition_info[0])) + +/* + * If no idea what is going on here. This is taken from the FlashFX stuff. + */ +#define ROMCS 1 + +static inline void elan_104nc_setup(void) +{ + u16 t; + + outw( 0x0023 + ROMCS*2, PAGE_IO ); + t=inb( PAGE_IO+1 ); + + t=(t & 0xf9) | 0x04; + + outw( ((0x0023 + ROMCS*2) | (t << 8)), PAGE_IO ); +} + +static inline void elan_104nc_page(struct map_info *map, unsigned long ofs) +{ + unsigned long page = ofs >> WINDOW_SHIFT; + + if( page!=page_in_window ) { + int cmd1; + int cmd2; + + cmd1=(page & 0x700) + 0x0833 + ROMCS*0x4000; + cmd2=((page & 0xff) << 8) + 0x0032; + + outw( cmd1, PAGE_IO ); + outw( cmd2, PAGE_IO ); + + page_in_window = page; + } +} + + +static __u8 elan_104nc_read8(struct map_info *map, unsigned long ofs) +{ + __u8 ret; + spin_lock(&elan_104nc_spin); + elan_104nc_page(map, ofs); + ret = readb(iomapadr + (ofs & WINDOW_MASK)); + spin_unlock(&elan_104nc_spin); + return ret; +} + +static __u16 elan_104nc_read16(struct map_info *map, unsigned long ofs) +{ + __u16 ret; + spin_lock(&elan_104nc_spin); + elan_104nc_page(map, ofs); + ret = readw(iomapadr + (ofs & WINDOW_MASK)); + spin_unlock(&elan_104nc_spin); + return ret; +} + +static __u32 elan_104nc_read32(struct map_info *map, unsigned long ofs) +{ + __u32 ret; + spin_lock(&elan_104nc_spin); + elan_104nc_page(map, ofs); + ret = readl(iomapadr + (ofs & WINDOW_MASK)); + spin_unlock(&elan_104nc_spin); + return ret; +} + +static void elan_104nc_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) +{ + while(len) { + unsigned long thislen = len; + if (len > (WINDOW_LENGTH - (from & WINDOW_MASK))) + thislen = WINDOW_LENGTH-(from & WINDOW_MASK); + + spin_lock(&elan_104nc_spin); + elan_104nc_page(map, from); + memcpy_fromio(to, iomapadr + (from & WINDOW_MASK), thislen); + spin_unlock(&elan_104nc_spin); + (__u8*)to += thislen; + from += thislen; + len -= thislen; + } +} + +static void elan_104nc_write8(struct map_info *map, __u8 d, unsigned long adr) +{ + spin_lock(&elan_104nc_spin); + elan_104nc_page(map, adr); + writeb(d, iomapadr + (adr & WINDOW_MASK)); + spin_unlock(&elan_104nc_spin); +} + +static void elan_104nc_write16(struct map_info *map, __u16 d, unsigned long adr) +{ + spin_lock(&elan_104nc_spin); + elan_104nc_page(map, adr); + writew(d, iomapadr + (adr & WINDOW_MASK)); + spin_unlock(&elan_104nc_spin); +} + +static void elan_104nc_write32(struct map_info *map, __u32 d, unsigned long adr) +{ + spin_lock(&elan_104nc_spin); + elan_104nc_page(map, adr); + writel(d, iomapadr + (adr & WINDOW_MASK)); + spin_unlock(&elan_104nc_spin); +} + +static void elan_104nc_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) +{ + while(len) { + unsigned long thislen = len; + if (len > (WINDOW_LENGTH - (to & WINDOW_MASK))) + thislen = WINDOW_LENGTH-(to & WINDOW_MASK); + + spin_lock(&elan_104nc_spin); + elan_104nc_page(map, to); + memcpy_toio(iomapadr + (to & WINDOW_MASK), from, thislen); + spin_unlock(&elan_104nc_spin); + to += thislen; + from += thislen; + len -= thislen; + } +} + +static struct map_info elan_104nc_map = { + name: "ELAN-104NC flash", + size: 8*1024*1024, /* this must be set to a maximum possible amount + of flash so the cfi probe routines find all + the chips */ + buswidth: 2, + read8: elan_104nc_read8, + read16: elan_104nc_read16, + read32: elan_104nc_read32, + copy_from: elan_104nc_copy_from, + write8: elan_104nc_write8, + write16: elan_104nc_write16, + write32: elan_104nc_write32, + copy_to: elan_104nc_copy_to +}; + +/* MTD device for all of the flash. */ +static struct mtd_info *all_mtd; + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define init_elan_104nc init_module +#define cleanup_elan_104nc cleanup_module +#endif + +mod_exit_t cleanup_elan_104nc(void) +{ + if( all_mtd ) { + del_mtd_partitions( all_mtd ); + map_destroy( all_mtd ); + } + + iounmap((void *)iomapadr); + release_region(PAGE_IO,PAGE_IO_SIZE); +} + +mod_init_t init_elan_104nc(void) +{ + /* Urg! We use I/O port 0x22 without request_region()ing it */ + /* + if (check_region(PAGE_IO,PAGE_IO_SIZE) != 0) { + printk( KERN_ERR"%s: IO ports 0x%x-0x%x in use\n", + elan_104nc_map.name, + PAGE_IO, PAGE_IO+PAGE_IO_SIZE-1 ); + return -EAGAIN; + } + */ + iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH); + if (!iomapadr) { + printk( KERN_ERR"%s: failed to ioremap memory region\n", + elan_104nc_map.name ); + return -EIO; + } + + /* + request_region( PAGE_IO, PAGE_IO_SIZE, "ELAN-104NC flash" ); + */ + + printk( KERN_INFO"%s: IO:0x%x-0x%x MEM:0x%x-0x%x\n", + elan_104nc_map.name, + PAGE_IO, PAGE_IO+PAGE_IO_SIZE-1, + WINDOW_START, WINDOW_START+WINDOW_LENGTH-1 ); + + elan_104nc_setup(); + + /* Probe for chip. */ + all_mtd = do_map_probe("cfi", &elan_104nc_map ); + if( !all_mtd ) { + cleanup_elan_104nc(); + return -ENXIO; + } + + all_mtd->module=THIS_MODULE; + + /* Create MTD devices for each partition. */ + add_mtd_partitions( all_mtd, partition_info, NUM_PARTITIONS ); + + return 0; +} + +module_init(init_elan_104nc); +module_exit(cleanup_elan_104nc); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/maps/iq80310.c linux/drivers/mtd/maps/iq80310.c --- v2.4.5/linux/drivers/mtd/maps/iq80310.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/maps/iq80310.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,133 @@ +/* + * $Id: iq80310.c,v 1.3 2001/04/26 15:40:23 dwmw2 Exp $ + * + * Mapping for the Intel XScale IQ80310 evaluation board + * + * Author: Nicolas Pitre + * Copyright: (C) 2001 MontaVista Software Inc. + * + * 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 + + +#define WINDOW_ADDR 0 +#define WINDOW_SIZE 8*1024*1024 +#define BUSWIDTH 1 + +static struct mtd_info *mymtd; + +static __u8 iq80310_read8(struct map_info *map, unsigned long ofs) +{ + return *(__u8 *)(map->map_priv_1 + ofs); +} + +static __u16 iq80310_read16(struct map_info *map, unsigned long ofs) +{ + return *(__u16 *)(map->map_priv_1 + ofs); +} + +static __u32 iq80310_read32(struct map_info *map, unsigned long ofs) +{ + return *(__u32 *)(map->map_priv_1 + ofs); +} + +static void iq80310_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) +{ + memcpy(to, (void *)(map->map_priv_1 + from), len); +} + +static void iq80310_write8(struct map_info *map, __u8 d, unsigned long adr) +{ + *(__u8 *)(map->map_priv_1 + adr) = d; +} + +static void iq80310_write16(struct map_info *map, __u16 d, unsigned long adr) +{ + *(__u16 *)(map->map_priv_1 + adr) = d; +} + +static void iq80310_write32(struct map_info *map, __u32 d, unsigned long adr) +{ + *(__u32 *)(map->map_priv_1 + adr) = d; +} + +static void iq80310_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) +{ + memcpy((void *)(map->map_priv_1 + to), from, len); +} + +static struct map_info iq80310_map = { + name: "IQ80310 flash", + size: WINDOW_SIZE, + buswidth: BUSWIDTH, + read8: iq80310_read8, + read16: iq80310_read16, + read32: iq80310_read32, + copy_from: iq80310_copy_from, + write8: iq80310_write8, + write16: iq80310_write16, + write32: iq80310_write32, + copy_to: iq80310_copy_to +}; + +static struct mtd_partition iq80310_partitions[3] = { + { + name: "firmware", + size: 0x00080000, + offset: 0, + mask_flags: MTD_WRITEABLE /* force read-only */ + },{ + name: "kernel", + size: 0x00080000, + offset: 0x00080000, + },{ + name: "filesystem", + size: 0x00700000, + offset: 0x00100000 + } +}; + +static int __init init_iq80310(void) +{ + iq80310_map.map_priv_1 = (unsigned long)__ioremap(WINDOW_ADDR, WINDOW_SIZE, 0); + + if (!iq80310_map.map_priv_1) { + printk("Failed to ioremap\n"); + return -EIO; + } + mymtd = do_map_probe("cfi", &iq80310_map); + if (mymtd) { + mymtd->module = THIS_MODULE; + add_mtd_partitions(mymtd, iq80310_partitions, 3); + return 0; + } + + iounmap((void *)iq80310_map.map_priv_1); + return -ENXIO; +} + +static void __exit cleanup_iq80310(void) +{ + if (mymtd) { + del_mtd_partitions(mymtd); + map_destroy(mymtd); + } + if (iq80310_map.map_priv_1) { + iounmap((void *)iq80310_map.map_priv_1); + iq80310_map.map_priv_1 = 0; + } +} + +module_init(init_iq80310); +module_exit(cleanup_iq80310); + diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/maps/netsc520.c linux/drivers/mtd/maps/netsc520.c --- v2.4.5/linux/drivers/mtd/maps/netsc520.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/maps/netsc520.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,192 @@ +/* netsc520.c -- MTD map driver for AMD NetSc520 Demonstration Board + * + * Copyright (C) 2001 Mark Langsdorf (mark.langsdorf@amd.com) + * based on sc520cdp.c by Sysgo Real-Time Solutions GmbH + * + * $Id: netsc520.c,v 1.3 2001/06/02 14:52:23 dwmw2 Exp $ + * + * 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 + * + * The NetSc520 is a demonstration board for the Elan Sc520 processor available + * from AMD. It has a single back of 16 megs of 32-bit Flash ROM and another + * 16 megs of SDRAM. + */ + +#include +#include +#include +#include +#include +#include +#include + + +/* +** The single, 16 megabyte flash bank is divided into four virtual +** partitions. The first partition is 768 KiB and is intended to +** store the kernel image loaded by the bootstrap loader. The second +** partition is 256 KiB and holds the BIOS image. The third +** partition is 14.5 MiB and is intended for the flash file system +** image. The last partition is 512 KiB and contains another copy +** of the BIOS image and the reset vector. +** +** Only the third partition should be mounted. The first partition +** should not be mounted, but it can erased and written to using the +** MTD character routines. The second and fourth partitions should +** not be touched - it is possible to corrupt the BIOS image by +** mounting these partitions, and potentially the board will not be +** recoverable afterwards. +*/ + +static __u8 netsc520_read8(struct map_info *map, unsigned long ofs) +{ + return readb(map->map_priv_1 + ofs); +} + +static __u16 netsc520_read16(struct map_info *map, unsigned long ofs) +{ + return readw(map->map_priv_1 + ofs); +} + +static __u32 netsc520_read32(struct map_info *map, unsigned long ofs) +{ + return readl(map->map_priv_1 + ofs); +} + +static void netsc520_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) +{ + memcpy_fromio(to, (void *)(map->map_priv_1 + from), len); +} + +static void netsc520_write8(struct map_info *map, __u8 d, unsigned long adr) +{ + writeb(d, map->map_priv_1 + adr); +} + +static void netsc520_write16(struct map_info *map, __u16 d, unsigned long adr) +{ + writew(d, map->map_priv_1 + adr); +} + +static void netsc520_write32(struct map_info *map, __u32 d, unsigned long adr) +{ + writel(d, map->map_priv_1 + adr); +} + +static void netsc520_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) +{ + memcpy_toio((void *)(map->map_priv_1 + to), from, len); +} + +/* partition_info gives details on the logical partitions that the split the + * single flash device into. If the size if zero we use up to the end of the + * device. */ +static struct mtd_partition partition_info[]={ + { + name: "NetSc520 boot kernel", + offset: 0, + size: 0xc0000 + }, + { + name: "NetSc520 Low BIOS", + offset: 0xc0000, + size: 0x40000 + }, + { + name: "NetSc520 file system", + offset: 0x100000, + size: 0xe80000 + }, + { + name: "NetSc520 High BIOS", + offset: 0xf80000, + size: 0x80000 + }, +}; +#define NUM_PARTITIONS (sizeof(partition_info)/sizeof(partition_info[0])) + +/* + * If no idea what is going on here. This is taken from the FlashFX stuff. + */ +#define ROMCS 1 + + +#define WINDOW_SIZE 0x00100000 +#define WINDOW_ADDR 0x00200000 + +static struct map_info netsc520_map = { + name: "netsc520 Flash Bank", + size: WINDOW_SIZE, + buswidth: 4, + read8: netsc520_read8, + read16: netsc520_read16, + read32: netsc520_read32, + copy_from: netsc520_copy_from, + write8: netsc520_write8, + write16: netsc520_write16, + write32: netsc520_write32, + copy_to: netsc520_copy_to, + map_priv_2: WINDOW_ADDR +}; + +#define NUM_FLASH_BANKS (sizeof(netsc520_map)/sizeof(struct map_info)) + +static struct mtd_info *mymtd; + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define init_netsc520 init_module +#define cleanup_netsc520 cleanup_module +#endif + + +static int __init init_netsc520(void) +{ + printk(KERN_NOTICE "NetSc520 flash device: %lx at %lx\n", netsc520_map.size, netsc520_map.map_priv_2); + netsc520_map.map_priv_1 = (unsigned long)ioremap_nocache(netsc520_map.map_priv_2, netsc520_map.size); + + if (!netsc520_map.map_priv_1) { + printk("Failed to ioremap_nocache\n"); + return -EIO; + } + mymtd = do_map_probe("cfi", &netsc520_map); + if(!mymtd) + mymtd = do_map_probe("ram", &netsc520_map); + if(!mymtd) + mymtd = do_map_probe("rom", &netsc520_map); + + if (!mymtd) { + iounmap((void *)netsc520_map.map_priv_1); + return -ENXIO; + } + + mymtd->module = THIS_MODULE; + add_mtd_partitions( mymtd, partition_info, NUM_PARTITIONS ); + return 0; +} + +static void __exit cleanup_netsc520(void) +{ + if (mymtd) { + del_mtd_partitions(mymtd); + map_destroy(mymtd); + } + if (netsc520_map.map_priv_1) { + iounmap((void *)netsc520_map.map_priv_1); + netsc520_map.map_priv_1 = 0; + } +} + +module_init(init_netsc520); +module_exit(cleanup_netsc520); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/maps/nora.c linux/drivers/mtd/maps/nora.c --- v2.4.5/linux/drivers/mtd/maps/nora.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/maps/nora.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,206 @@ +/* + * $Id: nora.c,v 1.19 2001/04/26 15:40:23 dwmw2 Exp $ + * + * This is so simple I love it. + */ + +#include +#include +#include + +#include +#include + + +#define WINDOW_ADDR 0xd0000000 +#define WINDOW_SIZE 0x04000000 + +static struct mtd_info *mymtd; + +__u8 nora_read8(struct map_info *map, unsigned long ofs) +{ + return *(__u8 *)(WINDOW_ADDR + ofs); +} + +__u16 nora_read16(struct map_info *map, unsigned long ofs) +{ + return *(__u16 *)(WINDOW_ADDR + ofs); +} + +__u32 nora_read32(struct map_info *map, unsigned long ofs) +{ + return *(__u32 *)(WINDOW_ADDR + ofs); +} + +void nora_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) +{ + memcpy(to, (void *)(WINDOW_ADDR + from), len); +} + +void nora_write8(struct map_info *map, __u8 d, unsigned long adr) +{ + *(__u8 *)(WINDOW_ADDR + adr) = d; +} + +void nora_write16(struct map_info *map, __u16 d, unsigned long adr) +{ + *(__u16 *)(WINDOW_ADDR + adr) = d; +} + +void nora_write32(struct map_info *map, __u32 d, unsigned long adr) +{ + *(__u32 *)(WINDOW_ADDR + adr) = d; +} + +void nora_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) +{ + memcpy((void *)(WINDOW_ADDR + to), from, len); +} + +struct map_info nora_map = { + name: "NORA", + size: WINDOW_SIZE, + buswidth: 2, + read8: nora_read8, + read16: nora_read16, + read32: nora_read32, + copy_from: nora_copy_from, + write8: nora_write8, + write16: nora_write16, + write32: nora_write32, + copy_to: nora_copy_to +}; + + +static int nora_mtd_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) +{ + return mymtd->read(mymtd, from + (unsigned long)mtd->priv, len, retlen, buf); +} + +static int nora_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) +{ + return mymtd->write(mymtd, to + (unsigned long)mtd->priv, len, retlen, buf); +} + +static int nora_mtd_erase (struct mtd_info *mtd, struct erase_info *instr) +{ + instr->addr += (unsigned long)mtd->priv; + return mymtd->erase(mymtd, instr); +} + +static void nora_mtd_sync (struct mtd_info *mtd) +{ + mymtd->sync(mymtd); +} + +static int nora_mtd_suspend (struct mtd_info *mtd) +{ + return mymtd->suspend(mymtd); +} + +static void nora_mtd_resume (struct mtd_info *mtd) +{ + mymtd->resume(mymtd); +} + + +static struct mtd_info nora_mtds[4] = { /* boot, kernel, ramdisk, fs */ + { + type: MTD_NORFLASH, + flags: MTD_CAP_NORFLASH, + size: 0x60000, + erasesize: 0x20000, + name: "NORA boot firmware", + module: THIS_MODULE, + erase: nora_mtd_erase, + read: nora_mtd_read, + write: nora_mtd_write, + suspend: nora_mtd_suspend, + resume: nora_mtd_resume, + sync: nora_mtd_sync, + priv: (void *)0 + }, + { + type: MTD_NORFLASH, + flags: MTD_CAP_NORFLASH, + size: 0x0a0000, + erasesize: 0x20000, + name: "NORA kernel", + module: THIS_MODULE, + erase: nora_mtd_erase, + read: nora_mtd_read, + write: nora_mtd_write, + suspend: nora_mtd_suspend, + resume: nora_mtd_resume, + sync: nora_mtd_sync, + priv: (void *)0x60000 + }, + { + type: MTD_NORFLASH, + flags: MTD_CAP_NORFLASH, + size: 0x900000, + erasesize: 0x20000, + name: "NORA root filesystem", + module: THIS_MODULE, + erase: nora_mtd_erase, + read: nora_mtd_read, + write: nora_mtd_write, + suspend: nora_mtd_suspend, + resume: nora_mtd_resume, + sync: nora_mtd_sync, + priv: (void *)0x100000 + }, + { + type: MTD_NORFLASH, + flags: MTD_CAP_NORFLASH, + size: 0x1600000, + erasesize: 0x20000, + name: "NORA second filesystem", + module: THIS_MODULE, + erase: nora_mtd_erase, + read: nora_mtd_read, + write: nora_mtd_write, + suspend: nora_mtd_suspend, + resume: nora_mtd_resume, + sync: nora_mtd_sync, + priv: (void *)0xa00000 + } +}; + + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define init_nora init_module +#define cleanup_nora cleanup_module +#endif + +int __init init_nora(void) +{ + printk(KERN_NOTICE "nora flash device: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR); + + mymtd = do_map_probe("cfi", &nora_map); + if (mymtd) { + mymtd->module = THIS_MODULE; + + add_mtd_device(&nora_mtds[2]); + add_mtd_device(&nora_mtds[0]); + add_mtd_device(&nora_mtds[1]); + add_mtd_device(&nora_mtds[3]); + return 0; + } + + return -ENXIO; +} + +static void __exit cleanup_nora(void) +{ + if (mymtd) { + del_mtd_device(&nora_mtds[3]); + del_mtd_device(&nora_mtds[1]); + del_mtd_device(&nora_mtds[0]); + del_mtd_device(&nora_mtds[2]); + map_destroy(mymtd); + } +} + +module_init(init_nora); +module_exit(cleanup_nora); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/maps/ocelot.c linux/drivers/mtd/maps/ocelot.c --- v2.4.5/linux/drivers/mtd/maps/ocelot.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/maps/ocelot.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,199 @@ +/* + * $Id: ocelot.c,v 1.4 2001/06/08 15:36:27 dwmw2 Exp $ + * + * Flash on Momenco Ocelot + */ + +#include +#include +#include +#include +#include +#include +#include + +#define OCELOT_PLD 0x2c000000 +#define FLASH_WINDOW_ADDR 0x2fc00000 +#define FLASH_WINDOW_SIZE 0x00080000 +#define FLASH_BUSWIDTH 1 +#define NVRAM_WINDOW_ADDR 0x2c800000 +#define NVRAM_WINDOW_SIZE 0x00007FF0 +#define NVRAM_BUSWIDTH 1 + +extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts); + +static unsigned int cacheflush = 0; + +static struct mtd_info *flash_mtd; +static struct mtd_info *nvram_mtd; + +__u8 ocelot_read8(struct map_info *map, unsigned long ofs) +{ + return __raw_readb(map->map_priv_1 + ofs); +} + +void ocelot_write8(struct map_info *map, __u8 d, unsigned long adr) +{ + cacheflush = 1; + __raw_writeb(d, map->map_priv_1 + adr); + mb(); +} + +void ocelot_copy_from_cache(struct map_info *map, void *to, unsigned long from, ssize_t len) +{ + if (cacheflush) { + dma_cache_inv(map->map_priv_2, map->size); + cacheflush = 0; + } + memcpy_fromio(to, map->map_priv_1 + from, len); +} + +void ocelot_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) +{ + memcpy_fromio(to, map->map_priv_1 + from, len); +} + +void ocelot_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) +{ + /* If we use memcpy, it does word-wide writes. Even though we told the + GT64120A that it's an 8-bit wide region, word-wide writes don't work. + We end up just writing the first byte of the four to all four bytes. + So we have this loop instead */ + while(len) { + __raw_writeb(*(unsigned char *) from, map->map_priv_1 + to); + from++; + to++; + len--; + } +} + +static struct mtd_partition *parsed_parts; + +struct map_info ocelot_flash_map = { + name: "Ocelot boot flash", + size: FLASH_WINDOW_SIZE, + buswidth: FLASH_BUSWIDTH, + read8: ocelot_read8, + copy_from: ocelot_copy_from_cache, + write8: ocelot_write8, +}; + +struct map_info ocelot_nvram_map = { + name: "Ocelot NVRAM", + size: NVRAM_WINDOW_SIZE, + buswidth: NVRAM_BUSWIDTH, + read8: ocelot_read8, + copy_from: ocelot_copy_from, + write8: ocelot_write8, + copy_to: ocelot_copy_to +}; + +static int __init init_ocelot_maps(void) +{ + void *pld; + int nr_parts; + unsigned char brd_status; + + printk(KERN_INFO "Momenco Ocelot MTD mappings: Flash 0x%x at 0x%x, NVRAM 0x%x at 0x%x\n", + FLASH_WINDOW_SIZE, FLASH_WINDOW_ADDR, NVRAM_WINDOW_SIZE, NVRAM_WINDOW_ADDR); + + /* First check whether the flash jumper is present */ + pld = ioremap(OCELOT_PLD, 0x10); + if (!pld) { + printk(KERN_NOTICE "Failed to ioremap Ocelot PLD\n"); + return -EIO; + } + brd_status = readb(pld+4); + iounmap(pld); + + /* Now ioremap the NVRAM space */ + ocelot_nvram_map.map_priv_1 = (unsigned long)ioremap_nocache(NVRAM_WINDOW_ADDR, NVRAM_WINDOW_SIZE); + if (!ocelot_nvram_map.map_priv_1) { + printk(KERN_NOTICE "Failed to ioremap Ocelot NVRAM space\n"); + return -EIO; + } + // ocelot_nvram_map.map_priv_2 = ocelot_nvram_map.map_priv_1; + + /* And do the RAM probe on it to get an MTD device */ + nvram_mtd = do_map_probe("ram", &ocelot_nvram_map); + if (!nvram_mtd) { + printk("NVRAM probe failed\n"); + goto fail_1; + } + nvram_mtd->module = THIS_MODULE; + nvram_mtd->erasesize = 16; + + /* Now map the flash space */ + ocelot_flash_map.map_priv_1 = (unsigned long)ioremap_nocache(FLASH_WINDOW_ADDR, FLASH_WINDOW_SIZE); + if (!ocelot_flash_map.map_priv_1) { + printk(KERN_NOTICE "Failed to ioremap Ocelot flash space\n"); + goto fail_2; + } + /* Now the cached version */ + ocelot_flash_map.map_priv_2 = (unsigned long)__ioremap(FLASH_WINDOW_ADDR, FLASH_WINDOW_SIZE, 0); + + if (!ocelot_flash_map.map_priv_2) { + /* Doesn't matter if it failed. Just use the uncached version */ + ocelot_flash_map.map_priv_2 = ocelot_flash_map.map_priv_1; + } + + /* Only probe for flash if the write jumper is present */ + if (brd_status & 0x40) { + flash_mtd = do_map_probe("jedec", &ocelot_flash_map); + } else { + printk(KERN_NOTICE "Ocelot flash write jumper not present. Treating as ROM\n"); + } + /* If that failed or the jumper's absent, pretend it's ROM */ + if (!flash_mtd) { + flash_mtd = do_map_probe("rom", &ocelot_flash_map); + /* If we're treating it as ROM, set the erase size */ + if (flash_mtd) + flash_mtd->erasesize = 0x10000; + } + if (!flash_mtd) + goto fail3; + + add_mtd_device(nvram_mtd); + + flash_mtd->module = THIS_MODULE; + nr_parts = parse_redboot_partitions(flash_mtd, &parsed_parts); + + if (nr_parts) + add_mtd_partitions(flash_mtd, parsed_parts, nr_parts); + else + add_mtd_device(flash_mtd); + + return 0; + + fail3: + iounmap((void *)ocelot_flash_map.map_priv_1); + if (ocelot_flash_map.map_priv_2 && + ocelot_flash_map.map_priv_2 != ocelot_flash_map.map_priv_1) + iounmap((void *)ocelot_flash_map.map_priv_2); + fail_2: + map_destroy(nvram_mtd); + fail_1: + iounmap((void *)ocelot_nvram_map.map_priv_1); + + return -ENXIO; +} + +static void __exit cleanup_ocelot_maps(void) +{ + del_mtd_device(nvram_mtd); + map_destroy(nvram_mtd); + iounmap((void *)ocelot_nvram_map.map_priv_1); + + if (parsed_parts) + del_mtd_partitions(flash_mtd); + else + del_mtd_device(flash_mtd); + map_destroy(flash_mtd); + iounmap((void *)ocelot_flash_map.map_priv_1); + if (ocelot_flash_map.map_priv_2 != ocelot_flash_map.map_priv_1) + iounmap((void *)ocelot_flash_map.map_priv_2); +} + +module_init(init_ocelot_maps); +module_exit(cleanup_ocelot_maps); + diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/maps/octagon-5066.c linux/drivers/mtd/maps/octagon-5066.c --- v2.4.5/linux/drivers/mtd/maps/octagon-5066.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/maps/octagon-5066.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,285 @@ +// $Id: octagon-5066.c,v 1.17 2001/06/02 14:30:44 dwmw2 Exp $ +/* ###################################################################### + + Octagon 5066 MTD Driver. + + The Octagon 5066 is a SBC based on AMD's 586-WB running at 133 MHZ. It + comes with a builtin AMD 29F016 flash chip and a socketed EEPROM that + is replacable by flash. Both units are mapped through a multiplexer + into a 32k memory window at 0xe8000. The control register for the + multiplexing unit is located at IO 0x208 with a bit map of + 0-5 Page Selection in 32k increments + 6-7 Device selection: + 00 SSD off + 01 SSD 0 (Socket) + 10 SSD 1 (Flash chip) + 11 undefined + + On each SSD, the first 128k is reserved for use by the bios + (actually it IS the bios..) This only matters if you are booting off the + flash, you must not put a file system starting there. + + The driver tries to do a detection algorithm to guess what sort of devices + are plugged into the sockets. + + ##################################################################### */ + +#include +#include +#include +#include +#include + +#include + +#define WINDOW_START 0xe8000 +#define WINDOW_LENGTH 0x8000 +#define WINDOW_SHIFT 27 +#define WINDOW_MASK 0x7FFF +#define PAGE_IO 0x208 + +static volatile char page_n_dev = 0; +static unsigned long iomapadr; +static spinlock_t oct5066_spin = SPIN_LOCK_UNLOCKED; + +/* + * We use map_priv_1 to identify which device we are. + */ + +static void __oct5066_page(struct map_info *map, __u8 byte) +{ + outb(byte,PAGE_IO); + page_n_dev = byte; +} + +static inline void oct5066_page(struct map_info *map, unsigned long ofs) +{ + __u8 byte = map->map_priv_1 | (ofs >> WINDOW_SHIFT); + + if (page_n_dev != byte) + __oct5066_page(map, byte); +} + + +static __u8 oct5066_read8(struct map_info *map, unsigned long ofs) +{ + __u8 ret; + spin_lock(&oct5066_spin); + oct5066_page(map, ofs); + ret = readb(iomapadr + (ofs & WINDOW_MASK)); + spin_unlock(&oct5066_spin); + return ret; +} + +static __u16 oct5066_read16(struct map_info *map, unsigned long ofs) +{ + __u16 ret; + spin_lock(&oct5066_spin); + oct5066_page(map, ofs); + ret = readw(iomapadr + (ofs & WINDOW_MASK)); + spin_unlock(&oct5066_spin); + return ret; +} + +static __u32 oct5066_read32(struct map_info *map, unsigned long ofs) +{ + __u32 ret; + spin_lock(&oct5066_spin); + oct5066_page(map, ofs); + ret = readl(iomapadr + (ofs & WINDOW_MASK)); + spin_unlock(&oct5066_spin); + return ret; +} + +static void oct5066_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) +{ + while(len) { + unsigned long thislen = len; + if (len > (WINDOW_LENGTH - (from & WINDOW_MASK))) + thislen = WINDOW_LENGTH-(from & WINDOW_MASK); + + spin_lock(&oct5066_spin); + oct5066_page(map, from); + memcpy_fromio(to, iomapadr + from, thislen); + spin_unlock(&oct5066_spin); + to += thislen; + from += thislen; + len -= thislen; + } +} + +static void oct5066_write8(struct map_info *map, __u8 d, unsigned long adr) +{ + spin_lock(&oct5066_spin); + oct5066_page(map, adr); + writeb(d, iomapadr + (adr & WINDOW_MASK)); + spin_unlock(&oct5066_spin); +} + +static void oct5066_write16(struct map_info *map, __u16 d, unsigned long adr) +{ + spin_lock(&oct5066_spin); + oct5066_page(map, adr); + writew(d, iomapadr + (adr & WINDOW_MASK)); + spin_unlock(&oct5066_spin); +} + +static void oct5066_write32(struct map_info *map, __u32 d, unsigned long adr) +{ + spin_lock(&oct5066_spin); + oct5066_page(map, adr); + writel(d, iomapadr + (adr & WINDOW_MASK)); + spin_unlock(&oct5066_spin); +} + +static void oct5066_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) +{ + while(len) { + unsigned long thislen = len; + if (len > (WINDOW_LENGTH - (to & WINDOW_MASK))) + thislen = WINDOW_LENGTH-(to & WINDOW_MASK); + + spin_lock(&oct5066_spin); + oct5066_page(map, to); + memcpy_toio(iomapadr + to, from, thislen); + spin_unlock(&oct5066_spin); + to += thislen; + from += thislen; + len -= thislen; + } +} + +static struct map_info oct5066_map[2] = { + { + name: "Octagon 5066 Socket", + size: 512 * 1024, + buswidth: 1, + read8: oct5066_read8, + read16: oct5066_read16, + read32: oct5066_read32, + copy_from: oct5066_copy_from, + write8: oct5066_write8, + write16: oct5066_write16, + write32: oct5066_write32, + copy_to: oct5066_copy_to, + map_priv_1: 1<<6 + }, + { + name: "Octagon 5066 Internal Flash", + size: 2 * 1024 * 1024, + buswidth: 1, + read8: oct5066_read8, + read16: oct5066_read16, + read32: oct5066_read32, + copy_from: oct5066_copy_from, + write8: oct5066_write8, + write16: oct5066_write16, + write32: oct5066_write32, + copy_to: oct5066_copy_to, + map_priv_1: 2<<6 + } +}; + +static struct mtd_info *oct5066_mtd[2] = {NULL, NULL}; + +// OctProbe - Sense if this is an octagon card +// --------------------------------------------------------------------- +/* Perform a simple validity test, we map the window select SSD0 and + change pages while monitoring the window. A change in the window, + controlled by the PAGE_IO port is a functioning 5066 board. This will + fail if the thing in the socket is set to a uniform value. */ +static int __init OctProbe(void) +{ + unsigned int Base = (1 << 6); + unsigned long I; + unsigned long Values[10]; + for (I = 0; I != 20; I++) + { + outb(Base + (I%10),PAGE_IO); + if (I < 10) + { + // Record the value and check for uniqueness + Values[I%10] = readl(iomapadr); + if (I > 0 && Values[I%10] == Values[0]) + return -EAGAIN; + } + else + { + // Make sure we get the same values on the second pass + if (Values[I%10] != readl(iomapadr)) + return -EAGAIN; + } + } + return 0; +} + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define init_oct5066 init_module +#define cleanup_oct5066 cleanup_module +#endif + +void cleanup_oct5066(void) +{ + int i; + for (i=0; i<2; i++) { + if (oct5066_mtd[i]) { + del_mtd_device(oct5066_mtd[i]); + map_destroy(oct5066_mtd[i]); + } + } + iounmap((void *)iomapadr); + release_region(PAGE_IO,1); +} + +int __init init_oct5066(void) +{ + int i; + + // Do an autoprobe sequence + if (check_region(PAGE_IO,1) != 0) + { + printk("5066: Page Register in Use\n"); + return -EAGAIN; + } + iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH); + if (!iomapadr) { + printk("Failed to ioremap memory region\n"); + return -EIO; + } + if (OctProbe() != 0) + { + printk("5066: Octagon Probe Failed, is this an Octagon 5066 SBC?\n"); + iounmap((void *)iomapadr); + return -EAGAIN; + } + + request_region(PAGE_IO,1,"Octagon SSD"); + + // Print out our little header.. + printk("Octagon 5066 SSD IO:0x%x MEM:0x%x-0x%x\n",PAGE_IO,WINDOW_START, + WINDOW_START+WINDOW_LENGTH); + + for (i=0; i<2; i++) { + oct5066_mtd[i] = do_map_probe("cfi", &oct5066_map[i]); + if (!oct5066_mtd[i]) + oct5066_mtd[i] = do_map_probe("jedec", &oct5066_map[i]); + if (!oct5066_mtd[i]) + oct5066_mtd[i] = do_map_probe("ram", &oct5066_map[i]); + if (!oct5066_mtd[i]) + oct5066_mtd[i] = do_map_probe("rom", &oct5066_map[i]); + if (oct5066_mtd[i]) { + oct5066_mtd[i]->module = THIS_MODULE; + add_mtd_device(oct5066_mtd[i]); + } + } + + if (!oct5066_mtd[0] && !oct5066_mtd[1]) { + cleanup_oct5066(); + return -ENXIO; + } + + return 0; +} + +module_init(init_oct5066); +module_exit(cleanup_oct5066); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/maps/physmap.c linux/drivers/mtd/maps/physmap.c --- v2.4.5/linux/drivers/mtd/maps/physmap.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/maps/physmap.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,119 @@ +/* + * $Id: physmap.c,v 1.13 2001/06/10 00:14:55 dwmw2 Exp $ + * + * Normal mappings of chips in physical memory + */ + +#include +#include +#include +#include +#include +#include +#include + + +#define WINDOW_ADDR CONFIG_MTD_PHYSMAP_START +#define WINDOW_SIZE CONFIG_MTD_PHYSMAP_LEN +#define BUSWIDTH CONFIG_MTD_PHYSMAP_BUSWIDTH + +static struct mtd_info *mymtd; + +__u8 physmap_read8(struct map_info *map, unsigned long ofs) +{ + return __raw_readb(map->map_priv_1 + ofs); +} + +__u16 physmap_read16(struct map_info *map, unsigned long ofs) +{ + return __raw_readw(map->map_priv_1 + ofs); +} + +__u32 physmap_read32(struct map_info *map, unsigned long ofs) +{ + return __raw_readl(map->map_priv_1 + ofs); +} + +void physmap_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) +{ + memcpy_fromio(to, map->map_priv_1 + from, len); +} + +void physmap_write8(struct map_info *map, __u8 d, unsigned long adr) +{ + __raw_writeb(d, map->map_priv_1 + adr); + mb(); +} + +void physmap_write16(struct map_info *map, __u16 d, unsigned long adr) +{ + __raw_writew(d, map->map_priv_1 + adr); + mb(); +} + +void physmap_write32(struct map_info *map, __u32 d, unsigned long adr) +{ + __raw_writel(d, map->map_priv_1 + adr); + mb(); +} + +void physmap_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) +{ + memcpy_toio(map->map_priv_1 + to, from, len); +} + +struct map_info physmap_map = { + name: "Physically mapped flash", + size: WINDOW_SIZE, + buswidth: BUSWIDTH, + read8: physmap_read8, + read16: physmap_read16, + read32: physmap_read32, + copy_from: physmap_copy_from, + write8: physmap_write8, + write16: physmap_write16, + write32: physmap_write32, + copy_to: physmap_copy_to +}; + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define init_physmap init_module +#define cleanup_physmap cleanup_module +#endif + +int __init init_physmap(void) +{ + printk(KERN_NOTICE "physmap flash device: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR); + physmap_map.map_priv_1 = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); + + if (!physmap_map.map_priv_1) { + printk("Failed to ioremap\n"); + return -EIO; + } + mymtd = do_map_probe("cfi", &physmap_map); + if (mymtd) { + mymtd->module = THIS_MODULE; + + add_mtd_device(mymtd); + return 0; + } + + iounmap((void *)physmap_map.map_priv_1); + return -ENXIO; +} + +static void __exit cleanup_physmap(void) +{ + if (mymtd) { + del_mtd_device(mymtd); + map_destroy(mymtd); + } + if (physmap_map.map_priv_1) { + iounmap((void *)physmap_map.map_priv_1); + physmap_map.map_priv_1 = 0; + } +} + +module_init(init_physmap); +module_exit(cleanup_physmap); + diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/maps/pnc2000.c linux/drivers/mtd/maps/pnc2000.c --- v2.4.5/linux/drivers/mtd/maps/pnc2000.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/maps/pnc2000.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,136 @@ +/* + * pnc2000.c - mapper for Photron PNC-2000 board. + * + * Copyright (C) 2000 Crossnet Co. + * + * This code is GPL + * + * $Id: pnc2000.c,v 1.8 2001/06/10 00:09:45 dwmw2 Exp $ + */ + +#include +#include +#include + +#include +#include +#include + + +#define WINDOW_ADDR 0xbf000000 +#define WINDOW_SIZE 0x00400000 + +/* + * MAP DRIVER STUFF + */ + +__u8 pnc_read8(struct map_info *map, unsigned long ofs) +{ + return *(__u8 *)(WINDOW_ADDR + ofs); +} + +__u16 pnc_read16(struct map_info *map, unsigned long ofs) +{ + return *(__u16 *)(WINDOW_ADDR + ofs); +} + +__u32 pnc_read32(struct map_info *map, unsigned long ofs) +{ + return *(volatile unsigned int *)(WINDOW_ADDR + ofs); +} + +void pnc_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) +{ + memcpy(to, (void *)(WINDOW_ADDR + from), len); +} + +void pnc_write8(struct map_info *map, __u8 d, unsigned long adr) +{ + *(__u8 *)(WINDOW_ADDR + adr) = d; +} + +void pnc_write16(struct map_info *map, __u16 d, unsigned long adr) +{ + *(__u16 *)(WINDOW_ADDR + adr) = d; +} + +void pnc_write32(struct map_info *map, __u32 d, unsigned long adr) +{ + *(__u32 *)(WINDOW_ADDR + adr) = d; +} + +void pnc_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) +{ + memcpy((void *)(WINDOW_ADDR + to), from, len); +} + +struct map_info pnc_map = { + name: "PNC-2000", + size: WINDOW_SIZE, + buswidth: 4, + read8: pnc_read8, + read16: pnc_read16, + read32: pnc_read32, + copy_from: pnc_copy_from, + write8: pnc_write8, + write16: pnc_write16, + write32: pnc_write32, + copy_to: pnc_copy_to +}; + + +/* + * MTD 'PARTITIONING' STUFF + */ +static struct mtd_partition pnc_partitions[3] = { + { + name: "PNC-2000 boot firmware", + size: 0x20000, + offset: 0 + }, + { + name: "PNC-2000 kernel", + size: 0x1a0000, + offset: 0x20000 + }, + { + name: "PNC-2000 filesystem", + size: 0x240000, + offset: 0x1c0000 + } +}; + +/* + * This is the master MTD device for which all the others are just + * auto-relocating aliases. + */ +static struct mtd_info *mymtd; + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define init_pnc2000 init_module +#define cleanup_pnc2000 cleanup_module +#endif + +int __init init_pnc2000(void) +{ + printk(KERN_NOTICE "Photron PNC-2000 flash mapping: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR); + + mymtd = do_map_probe("cfi", &pnc_map); + if (mymtd) { + mymtd->module = THIS_MODULE; + return add_mtd_partitions(mymtd, pnc_partitions, 3); + } + + return -ENXIO; +} + +static void __exit cleanup_pnc2000(void) +{ + if (mymtd) { + del_mtd_partitions(mymtd); + map_destroy(mymtd); + } +} + +module_init(init_pnc2000); +module_exit(cleanup_pnc2000); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/maps/rpxlite.c linux/drivers/mtd/maps/rpxlite.c --- v2.4.5/linux/drivers/mtd/maps/rpxlite.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/maps/rpxlite.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,112 @@ +/* + * $Id: rpxlite.c,v 1.12 2001/04/26 15:40:23 dwmw2 Exp $ + * + * Handle mapping of the flash on the RPX Lite and CLLF boards + */ + +#include +#include +#include +#include +#include +#include + + +#define WINDOW_ADDR 0xfe000000 +#define WINDOW_SIZE 0x800000 + +static struct mtd_info *mymtd; + +__u8 rpxlite_read8(struct map_info *map, unsigned long ofs) +{ + return readb(map->map_priv_1 + ofs); +} + +__u16 rpxlite_read16(struct map_info *map, unsigned long ofs) +{ + return readw(map->map_priv_1 + ofs); +} + +__u32 rpxlite_read32(struct map_info *map, unsigned long ofs) +{ + return readl(map->map_priv_1 + ofs); +} + +void rpxlite_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) +{ + memcpy_fromio(to, (void *)(map->map_priv_1 + from), len); +} + +void rpxlite_write8(struct map_info *map, __u8 d, unsigned long adr) +{ + writeb(d, map->map_priv_1 + adr); +} + +void rpxlite_write16(struct map_info *map, __u16 d, unsigned long adr) +{ + writew(d, map->map_priv_1 + adr); +} + +void rpxlite_write32(struct map_info *map, __u32 d, unsigned long adr) +{ + writel(d, map->map_priv_1 + adr); +} + +void rpxlite_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) +{ + memcpy_toio((void *)(map->map_priv_1 + to), from, len); +} + +struct map_info rpxlite_map = { + name: "RPX", + size: WINDOW_SIZE, + buswidth: 4, + read8: rpxlite_read8, + read16: rpxlite_read16, + read32: rpxlite_read32, + copy_from: rpxlite_copy_from, + write8: rpxlite_write8, + write16: rpxlite_write16, + write32: rpxlite_write32, + copy_to: rpxlite_copy_to +}; + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define init_rpxlite init_module +#define cleanup_rpxlite cleanup_module +#endif + +int __init init_rpxlite(void) +{ + printk(KERN_NOTICE "RPX Lite or CLLF flash device: %x at %x\n", WINDOW_SIZE*4, WINDOW_ADDR); + rpxlite_map.map_priv_1 = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE * 4); + + if (!rpxlite_map.map_priv_1) { + printk("Failed to ioremap\n"); + return -EIO; + } + mymtd = do_map_probe("cfi", &rpxlite_map); + if (mymtd) { + mymtd->module = THIS_MODULE; + add_mtd_device(mymtd); + return 0; + } + + iounmap((void *)rpxlite_map.map_priv_1); + return -ENXIO; +} + +static void __exit cleanup_rpxlite(void) +{ + if (mymtd) { + del_mtd_device(mymtd); + map_destroy(mymtd); + } + if (rpxlite_map.map_priv_1) { + iounmap((void *)rpxlite_map.map_priv_1); + rpxlite_map.map_priv_1 = 0; + } +} + +module_init(init_rpxlite); +module_exit(cleanup_rpxlite); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/maps/sa1100-flash.c linux/drivers/mtd/maps/sa1100-flash.c --- v2.4.5/linux/drivers/mtd/maps/sa1100-flash.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/maps/sa1100-flash.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,644 @@ +/* + * Flash memory access on SA11x0 based devices + * + * (C) 2000 Nicolas Pitre + * + * $Id: sa1100-flash.c,v 1.15 2001/06/02 18:29:22 nico Exp $ + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include + + +#ifndef CONFIG_ARCH_SA1100 +#error This is for SA1100 architecture only +#endif + + +#define WINDOW_ADDR 0xe8000000 + +static __u8 sa1100_read8(struct map_info *map, unsigned long ofs) +{ + return *(__u8 *)(WINDOW_ADDR + ofs); +} + +static __u16 sa1100_read16(struct map_info *map, unsigned long ofs) +{ + return *(__u16 *)(WINDOW_ADDR + ofs); +} + +static __u32 sa1100_read32(struct map_info *map, unsigned long ofs) +{ + return *(__u32 *)(WINDOW_ADDR + ofs); +} + +static void sa1100_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) +{ + memcpy(to, (void *)(WINDOW_ADDR + from), len); +} + +static void sa1100_write8(struct map_info *map, __u8 d, unsigned long adr) +{ + *(__u8 *)(WINDOW_ADDR + adr) = d; +} + +static void sa1100_write16(struct map_info *map, __u16 d, unsigned long adr) +{ + *(__u16 *)(WINDOW_ADDR + adr) = d; +} + +static void sa1100_write32(struct map_info *map, __u32 d, unsigned long adr) +{ + *(__u32 *)(WINDOW_ADDR + adr) = d; +} + +static void sa1100_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) +{ + memcpy((void *)(WINDOW_ADDR + to), from, len); +} + + +#ifdef CONFIG_SA1100_BITSY + +static void bitsy_set_vpp(struct map_info *map, int vpp) +{ + if (vpp) + set_bitsy_egpio(EGPIO_BITSY_VPP_ON); + else + clr_bitsy_egpio(EGPIO_BITSY_VPP_ON); +} + +#endif + +#ifdef CONFIG_SA1100_JORNADA720 + +static void jornada720_set_vpp(int vpp) +{ + if (vpp) + PPSR |= 0x80; + else + PPSR &= ~0x80; + PPDR |= 0x80; +} + +#endif + +static struct map_info sa1100_map = { + name: "SA1100 flash", + read8: sa1100_read8, + read16: sa1100_read16, + read32: sa1100_read32, + copy_from: sa1100_copy_from, + write8: sa1100_write8, + write16: sa1100_write16, + write32: sa1100_write32, + copy_to: sa1100_copy_to +}; + + +/* + * Here are partition information for all known SA1100-based devices. + * See include/linux/mtd/partitions.h for definition of the mtd_partition + * structure. + * + * The *_max_flash_size is the maximum possible mapped flash size which + * is not necessarily the actual flash size. It must correspond to the + * value specified in the mapping definition defined by the + * "struct map_desc *_io_desc" for the corresponding machine. + */ + +#ifdef CONFIG_SA1100_ASSABET + +/* Phase 4 Assabet has two 28F160B3 flash parts in bank 0: */ +static unsigned long assabet4_max_flash_size = 0x00400000; +static struct mtd_partition assabet4_partitions[] = { + { + name: "bootloader", + size: 0x00020000, + offset: 0, + mask_flags: MTD_WRITEABLE + },{ + name: "bootloader params", + size: 0x00020000, + offset: MTDPART_OFS_APPEND, + mask_flags: MTD_WRITEABLE + },{ + name: "jffs", + size: MTDPART_SIZ_FULL, + offset: MTDPART_OFS_APPEND + } +}; + +/* Phase 5 Assabet has two 28F128J3A flash parts in bank 0: */ +static unsigned long assabet5_max_flash_size = 0x02000000; +static struct mtd_partition assabet5_partitions[] = { + { + name: "bootloader", + size: 0x00040000, + offset: 0, + mask_flags: MTD_WRITEABLE + },{ + name: "bootloader params", + size: 0x00040000, + offset: MTDPART_OFS_APPEND, + mask_flags: MTD_WRITEABLE + },{ + name: "jffs", + size: MTDPART_SIZ_FULL, + offset: MTDPART_OFS_APPEND + } +}; + +#define assabet_max_flash_size assabet5_max_flash_size +#define assabet_partitions assabet5_partitions + +#endif + +#ifdef CONFIG_SA1100_FLEXANET + +/* Flexanet has two 28F128J3A flash parts in bank 0: */ +static unsigned long flexanet_max_flash_size = 0x02000000; +static struct mtd_partition flexanet_partitions[] = { + { + name: "bootloader", + size: 0x00040000, + offset: 0, + mask_flags: MTD_WRITEABLE + },{ + name: "bootloader params", + size: 0x00040000, + offset: MTDPART_OFS_APPEND, + mask_flags: MTD_WRITEABLE + },{ + name: "kernel", + size: 0x000C0000, + offset: MTDPART_OFS_APPEND, + mask_flags: MTD_WRITEABLE + },{ + name: "altkernel", + size: 0x000C0000, + offset: MTDPART_OFS_APPEND, + mask_flags: MTD_WRITEABLE + },{ + name: "root", + size: 0x00400000, + offset: MTDPART_OFS_APPEND, + mask_flags: MTD_WRITEABLE + },{ + name: "free1", + size: 0x00300000, + offset: MTDPART_OFS_APPEND, + mask_flags: MTD_WRITEABLE + },{ + name: "free2", + size: 0x00300000, + offset: MTDPART_OFS_APPEND, + mask_flags: MTD_WRITEABLE + },{ + name: "free3", + size: MTDPART_SIZ_FULL, + offset: MTDPART_OFS_APPEND, + mask_flags: MTD_WRITEABLE + } +}; + +#endif + +#ifdef CONFIG_SA1100_HUW_WEBPANEL +static unsigned long huw_webpanel_max_flash_size = 0x01000000; +static struct mtd_partition huw_webpanel_partitions[] = { + { + name: "Loader", + size: 0x00040000, + offset: 0, + },{ + name: "Sector 1", + size: 0x00040000, + offset: MTDPART_OFS_APPEND, + },{ + size: MTDPART_SIZ_FULL, + offset: MTDPART_OFS_APPEND, + } +}; +#endif /* CONFIG_SA1100_HUW_WEBPANEL */ + + +#ifdef CONFIG_SA1100_BITSY + +static unsigned long bitsy_max_flash_size = 0x02000000; +static struct mtd_partition bitsy_partitions[] = { + { + name: "BITSY boot firmware", + size: 0x00040000, + offset: 0, + mask_flags: MTD_WRITEABLE /* force read-only */ + },{ + name: "BITSY kernel", + size: 0x00080000, + offset: 0x40000 + },{ + name: "BITSY params", + size: 0x00040000, + offset: 0xC0000 + },{ +#ifdef CONFIG_JFFS2_FS + name: "BITSY root jffs2", + offset: 0x00100000, + size: MTDPART_SIZ_FULL +#else + name: "BITSY initrd", + size: 0x00100000, + offset: 0x00100000 + },{ + name: "BITSY root cramfs", + size: 0x00300000, + offset: 0x00200000 + },{ + name: "BITSY usr cramfs", + size: 0x00800000, + offset: 0x00500000 + },{ + name: "BITSY usr local", + offset: 0x00d00000, + size: MTDPART_SIZ_FULL +#endif + } +}; + +#endif +#ifdef CONFIG_SA1100_FREEBIRD +static unsigned long freebird_max_flash_size = 0x02000000; +static struct mtd_partition freebird_partitions[] = { +#if CONFIG_SA1100_FREEBIRD_NEW + { + name: "firmware", + size: 0x00040000, + offset: 0, + mask_flags: MTD_WRITEABLE /* force read-only */ + },{ + name: "kernel", + size: 0x00080000, + offset: 0x40000 + },{ + name: "params", + size: 0x00040000, + offset: 0xC0000 + },{ + name: "initrd", + size: 0x00100000, + offset: 0x00100000 + },{ + name: "root cramfs", + size: 0x00300000, + offset: 0x00200000 + },{ + name: "usr cramfs", + size: 0x00C00000, + offset: 0x00500000 + },{ + name: "local", + offset: 0x01100000, + size: MTDPART_SIZ_FULL + } +#else + { offset: 0, size: 0x00040000, }, + { offset: MTDPART_OFS_APPEND, size: 0x000c0000, }, + { offset: MTDPART_OFS_APPEND, size: 0x00400000, }, + { offset: MTDPART_OFS_APPEND, size: MTDPART_SIZ_FULL } +#endif + }; +#endif + + +#ifdef CONFIG_SA1100_CERF + +static unsigned long cerf_max_flash_size = 0x01000000; +static struct mtd_partition cerf_partitions[] = { + { offset: 0, size: 0x00800000 }, + { offset: MTDPART_OFS_APPEND, size: 0x00800000 } +}; + +#endif + +#ifdef CONFIG_SA1100_GRAPHICSCLIENT + +static unsigned long graphicsclient_max_flash_size = 0x01000000; +static struct mtd_partition graphicsclient_partitions[] = { + { + name: "Bootloader + zImage", + offset: 0, + size: 0x100000 + }, + { + name: "ramdisk.gz", + offset: MTDPART_OFS_APPEND, + size: 0x300000 + }, + { + name: "User FS", + offset: MTDPART_OFS_APPEND, + size: MTDPART_SIZ_FULL + } +}; + +#endif + +#ifdef CONFIG_SA1100_LART + +static unsigned long lart_max_flash_size = 0x00400000; +static struct mtd_partition lart_partitions[] = { + { offset: 0, size: 0x020000 }, + { offset: MTDPART_OFS_APPEND, size: 0x0e0000 }, + { offset: MTDPART_OFS_APPEND, size: MTDPART_SIZ_FULL } +}; + +#endif + +#ifdef CONFIG_SA1100_PANGOLIN + +static unsigned long pangolin_max_flash_size = 0x04000000; +static struct mtd_partition pangolin_partitions[] = { + { + name: "boot firmware", + offset: 0x00000000, + size: 0x00080000, + mask_flags: MTD_WRITEABLE, /* force read-only */ + }, + { + name: "kernel", + offset: 0x00080000, + size: 0x00100000, + }, + { + name: "initrd", + offset: 0x00180000, + size: 0x00200000, + }, + { + name: "initrd-test", + offset: 0x00400000, + size: 0x03C00000, + } +}; + +#endif + +#ifdef CONFIG_SA1100_YOPY + +static unsigned long yopy_max_flash_size = 0x08000000; +static struct mtd_partition yopy_partitions[] = { + { + name: "boot firmware", + offset: 0x00000000, + size: 0x00040000, + mask_flags: MTD_WRITEABLE, /* force read-only */ + }, + { + name: "kernel", + offset: 0x00080000, + size: 0x00080000, + }, + { + name: "initrd", + offset: 0x00100000, + size: 0x00300000, + }, + { + name: "root", + offset: 0x00400000, + size: 0x01000000, + }, +}; + +#endif + +#ifdef CONFIG_SA1100_JORNADA720 + +static unsigned long jornada720_max_flash_size = 0x02000000; +static struct mtd_partition jornada720_partitions[] = { + { + name: "JORNADA720 boot firmware", + size: 0x00040000, + offset: 0, + mask_flags: MTD_WRITEABLE /* force read-only */ + },{ + name: "JORNADA720 kernel", + size: 0x000c0000, + offset: 0x40000 + },{ + name: "JORNADA720 params", + size: 0x00040000, + offset: 0x100000 + },{ + name: "JORNADA720 initrd", + size: 0x00100000, + offset: 0x00140000 + },{ + name: "JORNADA720 root cramfs", + size: 0x00300000, + offset: 0x00240000 + },{ + name: "JORNADA720 usr cramfs", + size: 0x00800000, + offset: 0x00540000 + },{ + name: "JORNADA720 usr local", + offset: 0x00d00000, + size: 0 /* will expand to the end of the flash */ + } +}; +#endif + +#ifdef CONFIG_SA1100_SHERMAN + +static unsigned long sherman_max_flash_size = 0x02000000; +static struct mtd_partition sherman_partitions[] = { + { offset: 0, size: 0x50000 }, + { offset: MTDPART_OFS_APPEND, size: 0x70000 }, + { offset: MTDPART_OFS_APPEND, size: 0x600000 }, + { offset: MTDPART_OFS_APPEND, size: 0xA0000 } +}; + +#endif + +#define NB_OF(x) (sizeof(x)/sizeof(x[0])) + + +extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts); +extern int parse_bootldr_partitions(struct mtd_info *master, struct mtd_partition **pparts); + +static struct mtd_partition *parsed_parts; +static struct mtd_info *mymtd; + +int __init sa1100_mtd_init(void) +{ + struct mtd_partition *parts; + int nb_parts = 0; + int parsed_nr_parts = 0; + char *part_type; + + sa1100_map.buswidth = (MSC0 & MSC_RBW) ? 2 : 4; + printk(KERN_NOTICE "SA1100 flash: probing %d-bit flash bus\n", sa1100_map.buswidth*8); + mymtd = do_map_probe("cfi", &sa1100_map); + if (!mymtd) + return -ENXIO; + mymtd->module = THIS_MODULE; + + /* + * Static partition definition selection + */ + part_type = "static"; +#ifdef CONFIG_SA1100_ASSABET + if (machine_is_assabet()) { + parts = assabet_partitions; + nb_parts = NB_OF(assabet_partitions); + sa1100_map.size = assabet_max_flash_size; + } +#endif + +#ifdef CONFIG_SA1100_HUW_WEBPANEL + if (machine_is_huw_webpanel()) { + parts = huw_webpanel_partitions; + nb_parts = NB_OF(huw_webpanel_partitions); + sa1100_map.size = huw_webpanel_max_flash_size; + } +#endif + +#ifdef CONFIG_SA1100_BITSY + if (machine_is_bitsy()) { + parts = bitsy_partitions; + nb_parts = NB_OF(bitsy_partitions); + sa1100_map.size = bitsy_max_flash_size; + sa1100_map.set_vpp = bitsy_set_vpp; + } +#endif +#ifdef CONFIG_SA1100_FREEBIRD + if (machine_is_freebird()) { + parts = freebird_partitions; + nb_parts = NB_OF(freebird_partitions); + sa1100_map.size = freebird_max_flash_size; + } +#endif +#ifdef CONFIG_SA1100_CERF + if (machine_is_cerf()) { + parts = cerf_partitions; + nb_parts = NB_OF(cerf_partitions); + sa1100_map.size = cerf_max_flash_size; + } +#endif +#ifdef CONFIG_SA1100_GRAPHICSCLIENT + if (machine_is_graphicsclient()) { + parts = graphicsclient_partitions; + nb_parts = NB_OF(graphicsclient_partitions); + sa1100_map.size = graphicsclient_max_flash_size; + } +#endif +#ifdef CONFIG_SA1100_LART + if (machine_is_lart()) { + parts = lart_partitions; + nb_parts = NB_OF(lart_partitions); + sa1100_map.size = lart_max_flash_size; + } +#endif +#ifdef CONFIG_SA1100_PANGOLIN + if (machine_is_pangolin()) { + parts = pangolin_partitions; + nb_parts = NB_OF(pangolin_partitions); + sa1100_map.size = pangolin_max_flash_size; + } +#endif +#ifdef CONFIG_SA1100_JORNADA720 + if (machine_is_jornada720()) { + parts = jornada720_partitions; + nb_parts = NB_OF(jornada720_partitions); + sa1100_map.size = jornada720_max_flash_size; + sa1100_map.set_vpp = jornada720_set_vpp; + } +#endif +#ifdef CONFIG_SA1100_YOPY + if (machine_is_yopy()) { + parts = yopy_partitions; + nb_parts = NB_OF(yopy_partitions); + sa1100_map.size = yopy_max_flash_size; + } +#endif +#ifdef CONFIG_SA1100_SHERMAN + if (machine_is_sherman()) { + parts = sherman_partitions; + nb_parts = NB_OF(sherman_partitions); + sa1100_map.size = sherman_max_flash_size; + } +#endif +#ifdef CONFIG_SA1100_FLEXANET + if (machine_is_flexanet()) { + parts = flexanet_partitions; + nb_parts = NB_OF(flexanet_partitions); + sa1100_map.size = flexanet_max_flash_size; + } +#endif + + + if (!nb_parts) { + printk(KERN_WARNING "MTD: no known flash definition for this SA1100 machine\n"); + return -ENXIO; + } + + + /* + * Dynamic partition selection stuff (might override the static ones) + */ +#ifdef CONFIG_MTD_SA1100_REDBOOT_PARTITIONS + if (parsed_nr_parts == 0) { + int ret = parse_redboot_partitions(mymtd, &parsed_parts); + + if (ret > 0) { + part_type = "RedBoot"; + parsed_nr_parts = ret; + } + } +#endif +#ifdef CONFIG_MTD_SA1100_BOOTLDR_PARTITIONS + if (parsed_nr_parts == 0) { + int ret = parse_bootldr_partitions(mymtd, &parsed_parts); + if (ret > 0) { + part_type = "Compaq bootldr"; + parsed_nr_parts = ret; + } + } +#endif + + if (parsed_nr_parts > 0) { + parts = parsed_parts; + nb_parts = parsed_nr_parts; + } + + if (nb_parts == 0) { + printk(KERN_NOTICE "SA1100 flash: no partition info available, registering whole flash at once\n"); + add_mtd_device(mymtd); + } else { + printk(KERN_NOTICE "Using %s partition definition\n", part_type); + add_mtd_partitions(mymtd, parts, nb_parts); + } + return 0; +} + +static void __exit sa1100_mtd_cleanup(void) +{ + if (mymtd) { + del_mtd_partitions(mymtd); + map_destroy(mymtd); + if (parsed_parts) + kfree(parsed_parts); + } +} + +module_init(sa1100_mtd_init); +module_exit(sa1100_mtd_cleanup); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/maps/sbc_gxx.c linux/drivers/mtd/maps/sbc_gxx.c --- v2.4.5/linux/drivers/mtd/maps/sbc_gxx.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/maps/sbc_gxx.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,278 @@ +/* sbc_gxx.c -- MTD map driver for Arcom Control Systems SBC-MediaGX, + SBC-GXm and SBC-GX1 series boards. + + Copyright (C) 2001 Arcom Control System Ltd + + 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 + + $Id: sbc_gxx.c,v 1.17 2001/06/02 14:52:23 dwmw2 Exp $ + +The SBC-MediaGX / SBC-GXx has up to 16 MiB of +Intel StrataFlash (28F320/28F640) in x8 mode. + +This driver uses the CFI probe and Intel Extended Command Set drivers. + +The flash is accessed as follows: + + 16 kbyte memory window at 0xdc000-0xdffff + + Two IO address locations for paging + + 0x258 + bit 0-7: address bit 14-21 + 0x259 + bit 0-1: address bit 22-23 + bit 7: 0 - reset/powered down + 1 - device enabled + +The single flash device is divided into 3 partition which appear as +separate MTD devices. + +25/04/2001 AJL (Arcom) Modified signon strings and partition sizes + (to support bzImages up to 638KiB-ish) +*/ + +// Includes + +#include +#include +#include +#include +#include + +#include +#include +#include + +// Defines + +// - Hardware specific + +#define WINDOW_START 0xdc000 + +/* Number of bits in offset. */ +#define WINDOW_SHIFT 14 +#define WINDOW_LENGTH (1 << WINDOW_SHIFT) + +/* The bits for the offset into the window. */ +#define WINDOW_MASK (WINDOW_LENGTH-1) +#define PAGE_IO 0x258 +#define PAGE_IO_SIZE 2 + +/* bit 7 of 0x259 must be 1 to enable device. */ +#define DEVICE_ENABLE 0x8000 + +// - Flash / Partition sizing + +#define MAX_SIZE_KiB 16384 +#define BOOT_PARTITION_SIZE_KiB 768 +#define DATA_PARTITION_SIZE_KiB 1280 +#define APP_PARTITION_SIZE_KiB 6144 + +// Globals + +static volatile int page_in_window = -1; // Current page in window. +static unsigned long iomapadr; +static spinlock_t sbc_gxx_spin = SPIN_LOCK_UNLOCKED; + +/* partition_info gives details on the logical partitions that the split the + * single flash device into. If the size if zero we use up to the end of the + * device. */ +static struct mtd_partition partition_info[]={ + { name: "SBC-GXx flash boot partition", + offset: 0, + size: BOOT_PARTITION_SIZE_KiB*1024 }, + { name: "SBC-GXx flash data partition", + offset: BOOT_PARTITION_SIZE_KiB*1024, + size: (DATA_PARTITION_SIZE_KiB)*1024 }, + { name: "SBC-GXx flash application partition", + offset: (BOOT_PARTITION_SIZE_KiB+DATA_PARTITION_SIZE_KiB)*1024 } +}; + +#define NUM_PARTITIONS 3 + +static inline void sbc_gxx_page(struct map_info *map, unsigned long ofs) +{ + unsigned long page = ofs >> WINDOW_SHIFT; + + if( page!=page_in_window ) { + outw( page | DEVICE_ENABLE, PAGE_IO ); + page_in_window = page; + } +} + + +static __u8 sbc_gxx_read8(struct map_info *map, unsigned long ofs) +{ + __u8 ret; + spin_lock(&sbc_gxx_spin); + sbc_gxx_page(map, ofs); + ret = readb(iomapadr + (ofs & WINDOW_MASK)); + spin_unlock(&sbc_gxx_spin); + return ret; +} + +static __u16 sbc_gxx_read16(struct map_info *map, unsigned long ofs) +{ + __u16 ret; + spin_lock(&sbc_gxx_spin); + sbc_gxx_page(map, ofs); + ret = readw(iomapadr + (ofs & WINDOW_MASK)); + spin_unlock(&sbc_gxx_spin); + return ret; +} + +static __u32 sbc_gxx_read32(struct map_info *map, unsigned long ofs) +{ + __u32 ret; + spin_lock(&sbc_gxx_spin); + sbc_gxx_page(map, ofs); + ret = readl(iomapadr + (ofs & WINDOW_MASK)); + spin_unlock(&sbc_gxx_spin); + return ret; +} + +static void sbc_gxx_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) +{ + while(len) { + unsigned long thislen = len; + if (len > (WINDOW_LENGTH - (from & WINDOW_MASK))) + thislen = WINDOW_LENGTH-(from & WINDOW_MASK); + + spin_lock(&sbc_gxx_spin); + sbc_gxx_page(map, from); + memcpy_fromio(to, iomapadr + (from & WINDOW_MASK), thislen); + spin_unlock(&sbc_gxx_spin); + (__u8*)to += thislen; + from += thislen; + len -= thislen; + } +} + +static void sbc_gxx_write8(struct map_info *map, __u8 d, unsigned long adr) +{ + spin_lock(&sbc_gxx_spin); + sbc_gxx_page(map, adr); + writeb(d, iomapadr + (adr & WINDOW_MASK)); + spin_unlock(&sbc_gxx_spin); +} + +static void sbc_gxx_write16(struct map_info *map, __u16 d, unsigned long adr) +{ + spin_lock(&sbc_gxx_spin); + sbc_gxx_page(map, adr); + writew(d, iomapadr + (adr & WINDOW_MASK)); + spin_unlock(&sbc_gxx_spin); +} + +static void sbc_gxx_write32(struct map_info *map, __u32 d, unsigned long adr) +{ + spin_lock(&sbc_gxx_spin); + sbc_gxx_page(map, adr); + writel(d, iomapadr + (adr & WINDOW_MASK)); + spin_unlock(&sbc_gxx_spin); +} + +static void sbc_gxx_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) +{ + while(len) { + unsigned long thislen = len; + if (len > (WINDOW_LENGTH - (to & WINDOW_MASK))) + thislen = WINDOW_LENGTH-(to & WINDOW_MASK); + + spin_lock(&sbc_gxx_spin); + sbc_gxx_page(map, to); + memcpy_toio(iomapadr + (to & WINDOW_MASK), from, thislen); + spin_unlock(&sbc_gxx_spin); + to += thislen; + from += thislen; + len -= thislen; + } +} + +static struct map_info sbc_gxx_map = { + name: "SBC-GXx flash", + size: MAX_SIZE_KiB*1024, /* this must be set to a maximum possible amount + of flash so the cfi probe routines find all + the chips */ + buswidth: 1, + read8: sbc_gxx_read8, + read16: sbc_gxx_read16, + read32: sbc_gxx_read32, + copy_from: sbc_gxx_copy_from, + write8: sbc_gxx_write8, + write16: sbc_gxx_write16, + write32: sbc_gxx_write32, + copy_to: sbc_gxx_copy_to +}; + +/* MTD device for all of the flash. */ +static struct mtd_info *all_mtd; + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define init_sbc_gxx init_module +#define cleanup_sbc_gxx cleanup_module +#endif + +mod_exit_t cleanup_sbc_gxx(void) +{ + if( all_mtd ) { + del_mtd_partitions( all_mtd ); + map_destroy( all_mtd ); + } + + iounmap((void *)iomapadr); + release_region(PAGE_IO,PAGE_IO_SIZE); +} + +mod_init_t init_sbc_gxx(void) +{ + if (check_region(PAGE_IO,PAGE_IO_SIZE) != 0) { + printk( KERN_ERR"%s: IO ports 0x%x-0x%x in use\n", + sbc_gxx_map.name, + PAGE_IO, PAGE_IO+PAGE_IO_SIZE-1 ); + return -EAGAIN; + } + iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH); + if (!iomapadr) { + printk( KERN_ERR"%s: failed to ioremap memory region\n", + sbc_gxx_map.name ); + return -EIO; + } + + request_region( PAGE_IO, PAGE_IO_SIZE, "SBC-GXx flash" ); + + printk( KERN_INFO"%s: IO:0x%x-0x%x MEM:0x%x-0x%x\n", + sbc_gxx_map.name, + PAGE_IO, PAGE_IO+PAGE_IO_SIZE-1, + WINDOW_START, WINDOW_START+WINDOW_LENGTH-1 ); + + /* Probe for chip. */ + all_mtd = do_map_probe( "cfi", &sbc_gxx_map ); + if( !all_mtd ) { + cleanup_sbc_gxx(); + return -ENXIO; + } + + all_mtd->module=THIS_MODULE; + + /* Create MTD devices for each partition. */ + add_mtd_partitions(all_mtd, partition_info, NUM_PARTITIONS ); + + return 0; +} + +module_init(init_sbc_gxx); +module_exit(cleanup_sbc_gxx); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/maps/sc520cdp.c linux/drivers/mtd/maps/sc520cdp.c --- v2.4.5/linux/drivers/mtd/maps/sc520cdp.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/maps/sc520cdp.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,348 @@ +/* sc520cdp.c -- MTD map driver for AMD SC520 Customer Development Platform + * + * Copyright (C) 2001 Sysgo Real-Time Solutions GmbH + * + * 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 + * + * $Id: sc520cdp.c,v 1.7 2001/06/02 14:52:23 dwmw2 Exp $ + * + * + * The SC520CDP is an evaluation board for the Elan SC520 processor available + * from AMD. It has two banks of 32-bit Flash ROM, each 8 Megabytes in size, + * and up to 512 KiB of 8-bit DIL Flash ROM. + * For details see http://www.amd.com/products/epd/desiging/evalboards/18.elansc520/520_cdp_brief/index.html + */ + +#include +#include +#include +#include +#include +#include + + +/* +** The Embedded Systems BIOS decodes the first FLASH starting at +** 0x8400000. This is a *terrible* place for it because accessing +** the flash at this location causes the A22 address line to be high +** (that's what 0x8400000 binary's ought to be). But this is the highest +** order address line on the raw flash devices themselves!! +** This causes the top HALF of the flash to be accessed first. Beyond +** the physical limits of the flash, the flash chip aliases over (to +** 0x880000 which causes the bottom half to be accessed. This splits the +** flash into two and inverts it! If you then try to access this from another +** program that does NOT do this insanity, then you *will* access the +** first half of the flash, but not find what you expect there. That +** stuff is in the *second* half! Similarly, the address used by the +** BIOS for the second FLASH bank is also quite a bad choice. +** If REPROGRAM_PAR is defined below (the default), then this driver will +** choose more useful addresses for the FLASH banks by reprogramming the +** responsible PARxx registers in the SC520's MMCR region. This will +** cause the settings to be incompatible with the BIOS's settings, which +** shouldn't be a problem since you are running Linux, (i.e. the BIOS is +** not much use anyway). However, if you need to be compatible with +** the BIOS for some reason, just undefine REPROGRAM_PAR. +*/ +#define REPROGRAM_PAR + + + +#ifdef REPROGRAM_PAR + +/* These are the addresses we want.. */ +#define WINDOW_ADDR_0 0x08800000 +#define WINDOW_ADDR_1 0x09000000 +#define WINDOW_ADDR_2 0x09800000 + +/* .. and these are the addresses the BIOS gives us */ +#define WINDOW_ADDR_0_BIOS 0x08400000 +#define WINDOW_ADDR_1_BIOS 0x08c00000 +#define WINDOW_ADDR_2_BIOS 0x09400000 + +#else + +#define WINDOW_ADDR_0 0x08400000 +#define WINDOW_ADDR_1 0x08C00000 +#define WINDOW_ADDR_2 0x09400000 + +#endif + +#define WINDOW_SIZE_0 0x00800000 +#define WINDOW_SIZE_1 0x00800000 +#define WINDOW_SIZE_2 0x00080000 + +static __u8 sc520cdp_read8(struct map_info *map, unsigned long ofs) +{ + return readb(map->map_priv_1 + ofs); +} + +static __u16 sc520cdp_read16(struct map_info *map, unsigned long ofs) +{ + return readw(map->map_priv_1 + ofs); +} + +static __u32 sc520cdp_read32(struct map_info *map, unsigned long ofs) +{ + return readl(map->map_priv_1 + ofs); +} + +static void sc520cdp_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) +{ + memcpy_fromio(to, (void *)(map->map_priv_1 + from), len); +} + +static void sc520cdp_write8(struct map_info *map, __u8 d, unsigned long adr) +{ + writeb(d, map->map_priv_1 + adr); +} + +static void sc520cdp_write16(struct map_info *map, __u16 d, unsigned long adr) +{ + writew(d, map->map_priv_1 + adr); +} + +static void sc520cdp_write32(struct map_info *map, __u32 d, unsigned long adr) +{ + writel(d, map->map_priv_1 + adr); +} + +static void sc520cdp_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) +{ + memcpy_toio((void *)(map->map_priv_1 + to), from, len); +} + +static struct map_info sc520cdp_map[] = { + { + name: "SC520CDP Flash Bank #0", + size: WINDOW_SIZE_0, + buswidth: 4, + read8: sc520cdp_read8, + read16: sc520cdp_read16, + read32: sc520cdp_read32, + copy_from: sc520cdp_copy_from, + write8: sc520cdp_write8, + write16: sc520cdp_write16, + write32: sc520cdp_write32, + copy_to: sc520cdp_copy_to, + map_priv_2: WINDOW_ADDR_0 + }, + { + name: "SC520CDP Flash Bank #1", + size: WINDOW_SIZE_1, + buswidth: 4, + read8: sc520cdp_read8, + read16: sc520cdp_read16, + read32: sc520cdp_read32, + copy_from: sc520cdp_copy_from, + write8: sc520cdp_write8, + write16: sc520cdp_write16, + write32: sc520cdp_write32, + copy_to: sc520cdp_copy_to, + map_priv_2: WINDOW_ADDR_1 + }, + { + name: "SC520CDP DIL Flash", + size: WINDOW_SIZE_2, + buswidth: 1, + read8: sc520cdp_read8, + read16: sc520cdp_read16, + read32: sc520cdp_read32, + copy_from: sc520cdp_copy_from, + write8: sc520cdp_write8, + write16: sc520cdp_write16, + write32: sc520cdp_write32, + copy_to: sc520cdp_copy_to, + map_priv_2: WINDOW_ADDR_2 + }, +}; + +#define NUM_FLASH_BANKS (sizeof(sc520cdp_map)/sizeof(struct map_info)) + +static struct mtd_info *mymtd[NUM_FLASH_BANKS]; + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define init_sc520cdp init_module +#define cleanup_sc520cdp cleanup_module +#endif + +#ifdef REPROGRAM_PAR + +/* +** The SC520 MMCR (memory mapped control register) region resides +** at 0xFFFEF000. The 16 Programmable Address Region (PAR) registers +** are at offset 0x88 in the MMCR: +*/ +#define SC520_MMCR_BASE 0xFFFEF000 +#define SC520_MMCR_EXTENT 0x1000 +#define SC520_PAR(x) ((0x88/sizeof(unsigned long)) + (x)) +#define NUM_SC520_PAR 16 /* total number of PAR registers */ + +/* +** The highest three bits in a PAR register determine what target +** device is controlled by this PAR. Here, only ROMCS? and BOOTCS +** devices are of interest. +*/ +#define SC520_PAR_BOOTCS (0x4<<29) +#define SC520_PAR_ROMCS0 (0x5<<29) +#define SC520_PAR_ROMCS1 (0x6<<29) +#define SC520_PAR_TRGDEV (0x7<<29) + +/* +** Bits 28 thru 26 determine some attributes for the +** region controlled by the PAR. (We only use non-cacheable) +*/ +#define SC520_PAR_WRPROT (1<<26) /* write protected */ +#define SC520_PAR_NOCACHE (1<<27) /* non-cacheable */ +#define SC520_PAR_NOEXEC (1<<28) /* code execution denied */ + + +/* +** Bit 25 determines the granularity: 4K or 64K +*/ +#define SC520_PAR_PG_SIZ4 (0<<25) +#define SC520_PAR_PG_SIZ64 (1<<25) + +/* +** Build a value to be written into a PAR register. +** We only need ROM entries, 64K page size: +*/ +#define SC520_PAR_ENTRY(trgdev, address, size) \ + ((trgdev) | SC520_PAR_NOCACHE | SC520_PAR_PG_SIZ64 | \ + (address) >> 16 | (((size) >> 16) - 1) << 14) + +struct sc520_par_table +{ + unsigned long trgdev; + unsigned long new_par; + unsigned long default_address; +}; + +static struct sc520_par_table par_table[NUM_FLASH_BANKS] = +{ + { /* Flash Bank #0: selected by ROMCS0 */ + SC520_PAR_ROMCS0, + SC520_PAR_ENTRY(SC520_PAR_ROMCS0, WINDOW_ADDR_0, WINDOW_SIZE_0), + WINDOW_ADDR_0_BIOS + }, + { /* Flash Bank #1: selected by ROMCS1 */ + SC520_PAR_ROMCS1, + SC520_PAR_ENTRY(SC520_PAR_ROMCS1, WINDOW_ADDR_1, WINDOW_SIZE_1), + WINDOW_ADDR_1_BIOS + }, + { /* DIL (BIOS) Flash: selected by BOOTCS */ + SC520_PAR_BOOTCS, + SC520_PAR_ENTRY(SC520_PAR_BOOTCS, WINDOW_ADDR_2, WINDOW_SIZE_2), + WINDOW_ADDR_2_BIOS + } +}; + + +static void sc520cdp_setup_par(void) +{ + volatile unsigned long *mmcr; + unsigned long mmcr_val; + int i, j; + + /* map in SC520's MMCR area */ + mmcr = (unsigned long *)ioremap_nocache(SC520_MMCR_BASE, SC520_MMCR_EXTENT); + if(!mmcr) { /* ioremap_nocache failed: skip the PAR reprogramming */ + /* force map_priv_2 fields to BIOS defaults: */ + for(i = 0; i < NUM_FLASH_BANKS; i++) + sc520cdp_map[i].map_priv_2 = par_table[i].default_address; + return; + } + + /* + ** Find the PARxx registers that are reponsible for activating + ** ROMCS0, ROMCS1 and BOOTCS. Reprogram each of these with a + ** new value from the table. + */ + for(i = 0; i < NUM_FLASH_BANKS; i++) { /* for each par_table entry */ + for(j = 0; j < NUM_SC520_PAR; j++) { /* for each PAR register */ + mmcr_val = mmcr[SC520_PAR(j)]; + /* if target device field matches, reprogram the PAR */ + if((mmcr_val & SC520_PAR_TRGDEV) == par_table[i].trgdev) + { + mmcr[SC520_PAR(j)] = par_table[i].new_par; + break; + } + } + if(j == NUM_SC520_PAR) + { /* no matching PAR found: try default BIOS address */ + printk(KERN_NOTICE "Could not find PAR responsible for %s\n", + sc520cdp_map[i].name); + printk(KERN_NOTICE "Trying default address 0x%lx\n", + par_table[i].default_address); + sc520cdp_map[i].map_priv_2 = par_table[i].default_address; + } + } + iounmap((void *)mmcr); +} +#endif + + +static int __init init_sc520cdp(void) +{ + int i, devices_found = 0; + +#ifdef REPROGRAM_PAR + /* reprogram PAR registers so flash appears at the desired addresses */ + sc520cdp_setup_par(); +#endif + + for (i = 0; i < NUM_FLASH_BANKS; i++) { + printk(KERN_NOTICE "SC520 CDP flash device: %lx at %lx\n", sc520cdp_map[i].size, sc520cdp_map[i].map_priv_2); + sc520cdp_map[i].map_priv_1 = (unsigned long)ioremap_nocache(sc520cdp_map[i].map_priv_2, sc520cdp_map[i].size); + + if (!sc520cdp_map[i].map_priv_1) { + printk("Failed to ioremap_nocache\n"); + return -EIO; + } + mymtd[i] = do_map_probe("cfi", &sc520cdp_map[i]); + if(!mymtd[i]) + mymtd[i] = do_map_probe("jedec", &sc520cdp_map[i]); + if(!mymtd[i]) + mymtd[i] = do_map_probe("rom", &sc520cdp_map[i]); + + if (mymtd[i]) { + mymtd[i]->module = THIS_MODULE; + add_mtd_device(mymtd[i]); + ++devices_found; + } + else { + iounmap((void *)sc520cdp_map[i].map_priv_1); + } + } + return(devices_found ? 0 : -ENXIO); +} + +static void __exit cleanup_sc520cdp(void) +{ + int i; + + for (i = 0; i < NUM_FLASH_BANKS; i++) { + if (mymtd[i]) { + del_mtd_device(mymtd[i]); + map_destroy(mymtd[i]); + } + if (sc520cdp_map[i].map_priv_1) { + iounmap((void *)sc520cdp_map[i].map_priv_1); + sc520cdp_map[i].map_priv_1 = 0; + } + } +} + +module_init(init_sc520cdp); +module_exit(cleanup_sc520cdp); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/maps/sun_uflash.c linux/drivers/mtd/maps/sun_uflash.c --- v2.4.5/linux/drivers/mtd/maps/sun_uflash.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/maps/sun_uflash.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,224 @@ +/* $Id: sun_uflash.c,v 1.2 2001/04/26 15:40:23 dwmw2 Exp $ + * + * sun_uflash - Driver implementation for user-programmable flash + * present on many Sun Microsystems SME boardsets. + * + * This driver does NOT provide access to the OBP-flash for + * safety reasons-- use /drivers/sbus/char/flash.c instead. + * + * Copyright (c) 2001 Eric Brower (ebrower@usa.net) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define UFLASH_OBPNAME "flashprom" +#define UFLASH_DEVNAME "userflash" + +#define UFLASH_WINDOW_SIZE 0x200000 +#define UFLASH_BUSWIDTH 1 /* EBus is 8-bit */ + +MODULE_AUTHOR + ("Eric Brower "); +MODULE_DESCRIPTION + ("User-programmable flash device on Sun Microsystems boardsets"); +MODULE_SUPPORTED_DEVICE + ("userflash"); + +static LIST_HEAD(device_list); +struct uflash_dev { + char * name; /* device name */ + struct map_info map; /* mtd map info */ + struct mtd_info * mtd; /* mtd info */ + struct list_head list; +}; + +__u8 uflash_read8(struct map_info *map, unsigned long ofs) +{ + return(__raw_readb(map->map_priv_1 + ofs)); +} + +__u16 uflash_read16(struct map_info *map, unsigned long ofs) +{ + return(__raw_readw(map->map_priv_1 + ofs)); +} + +__u32 uflash_read32(struct map_info *map, unsigned long ofs) +{ + return(__raw_readl(map->map_priv_1 + ofs)); +} + +void uflash_copy_from(struct map_info *map, void *to, unsigned long from, + ssize_t len) +{ + memcpy_fromio(to, map->map_priv_1 + from, len); +} + +void uflash_write8(struct map_info *map, __u8 d, unsigned long adr) +{ + __raw_writeb(d, map->map_priv_1 + adr); +} + +void uflash_write16(struct map_info *map, __u16 d, unsigned long adr) +{ + __raw_writew(d, map->map_priv_1 + adr); +} + +void uflash_write32(struct map_info *map, __u32 d, unsigned long adr) +{ + __raw_writel(d, map->map_priv_1 + adr); +} + +void uflash_copy_to(struct map_info *map, unsigned long to, const void *from, + ssize_t len) +{ + memcpy_toio(map->map_priv_1 + to, from, len); +} + +struct map_info uflash_map_templ = { + name: "SUNW,???-????", + size: UFLASH_WINDOW_SIZE, + buswidth: UFLASH_BUSWIDTH, + read8: uflash_read8, + read16: uflash_read16, + read32: uflash_read32, + copy_from: uflash_copy_from, + write8: uflash_write8, + write16: uflash_write16, + write32: uflash_write32, + copy_to: uflash_copy_to +}; + +int uflash_devinit(struct linux_ebus_device* edev) +{ + int iTmp, nregs; + struct linux_prom_registers regs[2]; + struct uflash_dev *pdev; + + iTmp = prom_getproperty( + edev->prom_node, "reg", (void *)regs, sizeof(regs)); + if ((iTmp % sizeof(regs[0])) != 0) { + printk("%s: Strange reg property size %d\n", + UFLASH_DEVNAME, iTmp); + return -ENODEV; + } + + nregs = iTmp / sizeof(regs[0]); + + if (nregs != 1) { + /* Non-CFI userflash device-- once I find one we + * can work on supporting it. + */ + printk("%s: unsupported device at 0x%lx (%d regs): " \ + "email ebrower@usa.net\n", + UFLASH_DEVNAME, edev->resource[0].start, nregs); + return -ENODEV; + } + + if(0 == (pdev = kmalloc(sizeof(struct uflash_dev), GFP_KERNEL))) { + printk("%s: unable to kmalloc new device\n", UFLASH_DEVNAME); + return(-ENOMEM); + } + + /* copy defaults and tweak parameters */ + memcpy(&pdev->map, &uflash_map_templ, sizeof(uflash_map_templ)); + pdev->map.size = regs[0].reg_size; + + iTmp = prom_getproplen(edev->prom_node, "model"); + pdev->name = kmalloc(iTmp, GFP_KERNEL); + prom_getstring(edev->prom_node, "model", pdev->name, iTmp); + if(0 != pdev->name && 0 < strlen(pdev->name)) { + pdev->map.name = pdev->name; + } + + pdev->map.map_priv_1 = + (unsigned long)ioremap_nocache(edev->resource[0].start, pdev->map.size); + if(0 == pdev->map.map_priv_1) { + printk("%s: failed to map device\n", __FUNCTION__); + kfree(pdev->name); + kfree(pdev); + return(-1); + } + + /* MTD registration */ + pdev->mtd = do_map_probe("cfi", &pdev->map); + if(0 == pdev->mtd) { + iounmap((void *)pdev->map.map_priv_1); + kfree(pdev->name); + kfree(pdev); + return(-ENXIO); + } + + list_add(&pdev->list, &device_list); + + pdev->mtd->module = THIS_MODULE; + + add_mtd_device(pdev->mtd); + return(0); +} + +static int __init uflash_init(void) +{ + struct linux_ebus *ebus = NULL; + struct linux_ebus_device *edev = NULL; + + for_each_ebus(ebus) { + for_each_ebusdev(edev, ebus) { + if (!strcmp(edev->prom_name, UFLASH_OBPNAME)) { + if(0 > prom_getproplen(edev->prom_node, "user")) { + DEBUG(2, "%s: ignoring device at 0x%lx\n", + UFLASH_DEVNAME, edev->resource[0].start); + } else { + uflash_devinit(edev); + } + } + } + } + + if(list_empty(&device_list)) { + printk("%s: unable to locate device\n", UFLASH_DEVNAME); + return -ENODEV; + } + return(0); +} + +static void __exit uflash_cleanup(void) +{ + struct list_head *udevlist; + struct uflash_dev *udev; + + list_for_each(udevlist, &device_list) { + udev = list_entry(udevlist, struct uflash_dev, list); + DEBUG(2, "%s: removing device %s\n", + UFLASH_DEVNAME, udev->name); + + if(0 != udev->mtd) { + del_mtd_device(udev->mtd); + map_destroy(udev->mtd); + } + if(0 != udev->map.map_priv_1) { + iounmap((void*)udev->map.map_priv_1); + udev->map.map_priv_1 = 0; + } + if(0 != udev->name) { + kfree(udev->name); + } + kfree(udev); + } +} + +module_init(uflash_init); +module_exit(uflash_cleanup); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/maps/vmax301.c linux/drivers/mtd/maps/vmax301.c --- v2.4.5/linux/drivers/mtd/maps/vmax301.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/maps/vmax301.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,240 @@ +// $Id: vmax301.c,v 1.22 2001/06/02 14:30:44 dwmw2 Exp $ +/* ###################################################################### + + Tempustech VMAX SBC301 MTD Driver. + + The VMAx 301 is a SBC based on . It + comes with three builtin AMD 29F016B flash chips and a socket for SRAM or + more flash. Each unit has it's own 8k mapping into a settable region + (0xD8000). There are two 8k mappings for each MTD, the first is always set + to the lower 8k of the device the second is paged. Writing a 16 bit page + value to anywhere in the first 8k will cause the second 8k to page around. + + To boot the device a bios extension must be installed into the first 8k + of flash that is smart enough to copy itself down, page in the rest of + itself and begin executing. + + ##################################################################### */ + +#include +#include +#include +#include +#include +#include + +#include + + +#define WINDOW_START 0xd8000 +#define WINDOW_LENGTH 0x2000 +#define WINDOW_SHIFT 25 +#define WINDOW_MASK 0x1FFF + +/* Actually we could use two spinlocks, but we'd have to have + more private space in the struct map_info. We lose a little + performance like this, but we'd probably lose more by having + the extra indirection from having one of the map->map_priv + fields pointing to yet another private struct. +*/ +static spinlock_t vmax301_spin = SPIN_LOCK_UNLOCKED; + +static void __vmax301_page(struct map_info *map, unsigned long page) +{ + writew(page, map->map_priv_2 - WINDOW_LENGTH); + map->map_priv_1 = page; +} + +static inline void vmax301_page(struct map_info *map, + unsigned long ofs) +{ + unsigned long page = (ofs >> WINDOW_SHIFT); + if (map->map_priv_1 != page) + __vmax301_page(map, page); +} + +static __u8 vmax301_read8(struct map_info *map, unsigned long ofs) +{ + __u8 ret; + spin_lock(&vmax301_spin); + vmax301_page(map, ofs); + ret = readb(map->map_priv_2 + (ofs & WINDOW_MASK)); + spin_unlock(&vmax301_spin); + return ret; +} + +static __u16 vmax301_read16(struct map_info *map, unsigned long ofs) +{ + __u16 ret; + spin_lock(&vmax301_spin); + vmax301_page(map, ofs); + ret = readw(map->map_priv_2 + (ofs & WINDOW_MASK)); + spin_unlock(&vmax301_spin); + return ret; +} + +static __u32 vmax301_read32(struct map_info *map, unsigned long ofs) +{ + __u32 ret; + spin_lock(&vmax301_spin); + vmax301_page(map, ofs); + ret = readl(map->map_priv_2 + (ofs & WINDOW_MASK)); + spin_unlock(&vmax301_spin); + return ret; +} + +static void vmax301_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) +{ + while(len) { + unsigned long thislen = len; + if (len > (WINDOW_LENGTH - (from & WINDOW_MASK))) + thislen = WINDOW_LENGTH-(from & WINDOW_MASK); + spin_lock(&vmax301_spin); + vmax301_page(map, from); + memcpy_fromio(to, map->map_priv_2 + from, thislen); + spin_unlock(&vmax301_spin); + to += thislen; + from += thislen; + len -= thislen; + } +} + +static void vmax301_write8(struct map_info *map, __u8 d, unsigned long adr) +{ + spin_lock(&vmax301_spin); + vmax301_page(map, adr); + writeb(d, map->map_priv_2 + (adr & WINDOW_MASK)); + spin_unlock(&vmax301_spin); +} + +static void vmax301_write16(struct map_info *map, __u16 d, unsigned long adr) +{ + spin_lock(&vmax301_spin); + vmax301_page(map, adr); + writew(d, map->map_priv_2 + (adr & WINDOW_MASK)); + spin_unlock(&vmax301_spin); +} + +static void vmax301_write32(struct map_info *map, __u32 d, unsigned long adr) +{ + spin_lock(&vmax301_spin); + vmax301_page(map, adr); + writel(d, map->map_priv_2 + (adr & WINDOW_MASK)); + spin_unlock(&vmax301_spin); +} + +static void vmax301_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) +{ + while(len) { + unsigned long thislen = len; + if (len > (WINDOW_LENGTH - (to & WINDOW_MASK))) + thislen = WINDOW_LENGTH-(to & WINDOW_MASK); + + spin_lock(&vmax301_spin); + vmax301_page(map, to); + memcpy_toio(map->map_priv_2 + to, from, thislen); + spin_unlock(&vmax301_spin); + to += thislen; + from += thislen; + len -= thislen; + } +} + +static struct map_info vmax_map[2] = { + { + name: "VMAX301 Internal Flash", + size: 3*2*1024*1024, + buswidth: 1, + read8: vmax301_read8, + read16: vmax301_read16, + read32: vmax301_read32, + copy_from: vmax301_copy_from, + write8: vmax301_write8, + write16: vmax301_write16, + write32: vmax301_write32, + copy_to: vmax301_copy_to, + map_priv_1: WINDOW_START + WINDOW_LENGTH, + map_priv_2: 0xFFFFFFFF + }, + { + name: "VMAX301 Socket", + size: 0, + buswidth: 1, + read8: vmax301_read8, + read16: vmax301_read16, + read32: vmax301_read32, + copy_from: vmax301_copy_from, + write8: vmax301_write8, + write16: vmax301_write16, + write32: vmax301_write32, + copy_to: vmax301_copy_to, + map_priv_1: WINDOW_START + (3*WINDOW_LENGTH), + map_priv_2: 0xFFFFFFFF + } +}; + +static struct mtd_info *vmax_mtd[2] = {NULL, NULL}; + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define init_vmax301 init_module +#define cleanup_vmax301 cleanup_module +#endif + +static void __exit cleanup_vmax301(void) +{ + int i; + + for (i=0; i<2; i++) { + if (vmax_mtd[i]) { + del_mtd_device(vmax_mtd[i]); + map_destroy(vmax_mtd[i]); + } + } + iounmap((void *)vmax_map[0].map_priv_1 - WINDOW_START); +} + +int __init init_vmax301(void) +{ + int i; + unsigned long iomapadr; + // Print out our little header.. + printk("Tempustech VMAX 301 MEM:0x%x-0x%x\n",WINDOW_START, + WINDOW_START+4*WINDOW_LENGTH); + + iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH*4); + if (!iomapadr) { + printk("Failed to ioremap memory region\n"); + return -EIO; + } + /* Put the address in the map's private data area. + We store the actual MTD IO address rather than the + address of the first half, because it's used more + often. + */ + vmax_map[0].map_priv_1 = iomapadr + WINDOW_START; + vmax_map[1].map_priv_1 = iomapadr + (3*WINDOW_START); + + for (i=0; i<2; i++) { + vmax_mtd[i] = do_map_probe("cfi", &vmax_map[i]); + if (!vmax_mtd[i]) + vmax_mtd[i] = do_map_probe("jedec", &vmax_map[i]); + if (!vmax_mtd[i]) + vmax_mtd[i] = do_map_probe("ram", &vmax_map[i]); + if (!vmax_mtd[i]) + vmax_mtd[i] = do_map_probe("rom", &vmax_map[i]); + if (vmax_mtd[i]) { + vmax_mtd[i]->module = THIS_MODULE; + add_mtd_device(vmax_mtd[i]); + } + } + + if (!vmax_mtd[1] && !vmax_mtd[2]) { + iounmap((void *)iomapadr); + return -ENXIO; + } + + return 0; +} + +module_init(init_vmax301); +module_exit(cleanup_vmax301); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/mixmem.c linux/drivers/mtd/mixmem.c --- v2.4.5/linux/drivers/mtd/mixmem.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/mtd/mixmem.c Wed Dec 31 16:00:00 1969 @@ -1,151 +0,0 @@ -/* - * mixmem - a block device driver for flash rom found on the - * piggyback board of the multi-purpose mixcom card - * - * Author: Gergely Madarasz - * - * Copyright (c) 1999 ITConsult-Pro Co. - * - * This code is GPL - * - */ - -#include -#include -#include -#include -#include -#include - -#define MIXCOM_ID_OFFSET 0xc10 -#define MIXCOM_PAGE_OFFSET 0xc11 -#define MIXCOM_ID_1 0x11 -#define MIXCOM_ID_2 0x13 -#define MIXMEM_PAGESIZE 4096 -#define FIRST_BLOCK_OFFSET 0x1000 - -#if LINUX_VERSION_CODE < 0x20300 -#define __exit -#endif - -static unsigned int mixmem_addrs[] = { 0xc8000, 0xd8000, 0 }; -static unsigned int mixcom_ports[] = { 0x180, 0x280, 0x380, 0 }; - -// We could store these in the mtd structure, but we only support 1 device.. -static unsigned long base_io = 0; -static unsigned long base_addr = 0; -static struct mapped_mtd_info *SSD; - -static unsigned long mixmem_page(struct mapped_mtd_info *map, - unsigned long page) -{ - outb((char)(page & 0xff), base_io+MIXCOM_PAGE_OFFSET); - outb((char)((page >> 8) & 0x7), base_io+MIXCOM_PAGE_OFFSET+1); - return base_addr; -} - -static int flash_probe(int base) -{ - int prev,curr; - unsigned long flags; - - writeb(0xf0, base); - save_flags(flags); cli(); - - prev=readw(base); - - writeb(0xaa, base+0x555); - writeb(0x55, base+0x2AA); - writeb(0x90, base+0x555); - - curr=readw(base); - - restore_flags(flags); - writeb(0xf0, base); - return(prev==curr?0:curr); -} - -static int mixmem_probe(void) -{ - int i; - int id; - int chip; - - /* This should really check to see if the io ports are in use before - writing to them */ - for(i=0;mixcom_ports[i]!=0;i++) { - id=inb(mixcom_ports[i]+MIXCOM_ID_OFFSET); - if(id==MIXCOM_ID_1 || id==MIXCOM_ID_2) { - printk("mixmem: mixcom board found at 0x%3x\n",mixcom_ports[i]); - break; - } - } - - if(mixcom_ports[i]==0) { - printk("mixmem: no mixcom board found\n"); - return -ENODEV; - } - - if (check_region(mixcom_ports[i]+MIXCOM_PAGE_OFFSET, 2)) return -EAGAIN; - - - - // What is the deal with first_block_offset? - for(i=0;mixmem_addrs[i]!=0;i++) { - chip=flash_probe(mixmem_addrs[i]+FIRST_BLOCK_OFFSET); - if(chip)break; - } - - if(mixmem_addrs[i]==0) { - printk("mixmem: no flash available\n"); - return -ENODEV; - } - base_io = mixcom_ports[i]; - base_addr = mixmem_addrs[i]; - request_region(mixcom_ports[i]+MIXCOM_PAGE_OFFSET, 2, "mixmem"); - return 0; -} - - -static void __exit cleanup_mixmem() -{ - mtd_mapped_remove(SSD); - kfree(SSD); - SSD = 0; - release_region(base_io+MIXCOM_PAGE_OFFSET, 2); -} - -//static int __init init_mixmem(void) -int __init init_mixmem(void) -{ - if (mixmem_probe() != 0) - return -EAGAIN; - - // Print out our little header.. - printk("mixcom MTD IO:0x%lx MEM:0x%lx-0x%lx\n",base_io,base_addr, - base_addr+MIXMEM_PAGESIZE); - - // Allocate some memory - SSD = (struct mapped_mtd_info *)kmalloc(sizeof(*SSD),GFP_KERNEL); - if (SSD == 0) - return 0; - memset(SSD,0,sizeof(*SSD)); - - // Setup the MTD structure - SSD->page = mixmem_page; - SSD->pagesize = MIXMEM_PAGESIZE; - SSD->maxsize = 0x7FF; - SSD->mtd.name = "mixcom piggyback"; - - // Setup the MTD, this will sense the flash parameters and so on.. - if (mtd_mapped_setup(SSD) != 0) - { - printk("Failed to register new device\n"); - cleanup_module(); - return -EAGAIN; - } - - return 0; -} -module_init(init_mixmem); -module_exit(cleanup_mixmem); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/mtdblock_ro.c linux/drivers/mtd/mtdblock_ro.c --- v2.4.5/linux/drivers/mtd/mtdblock_ro.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/mtdblock_ro.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,289 @@ +/* + * $Id: mtdblock_ro.c,v 1.5 2001/06/10 01:41:53 dwmw2 Exp $ + * + * Read-only version of the mtdblock device, without the + * read/erase/modify/writeback stuff + */ + +#ifdef MTDBLOCK_DEBUG +#define DEBUGLVL debug +#endif + + +#include +#include + +#include + +#define MAJOR_NR MTD_BLOCK_MAJOR +#define DEVICE_NAME "mtdblock" +#define DEVICE_REQUEST mtdblock_request +#define DEVICE_NR(device) (device) +#define DEVICE_ON(device) +#define DEVICE_OFF(device) +#define DEVICE_NO_RANDOM +#include + +#if LINUX_VERSION_CODE < 0x20300 +#define RQFUNC_ARG void +#define blkdev_dequeue_request(req) do {CURRENT = req->next;} while (0) +#else +#define RQFUNC_ARG request_queue_t *q +#endif + +#ifdef MTDBLOCK_DEBUG +static int debug = MTDBLOCK_DEBUG; +MODULE_PARM(debug, "i"); +#endif + + +static int mtd_sizes[MAX_MTD_DEVICES]; + + +static int mtdblock_open(struct inode *inode, struct file *file) +{ + struct mtd_info *mtd = NULL; + + int dev; + + DEBUG(1,"mtdblock_open\n"); + + if (inode == 0) + return -EINVAL; + + dev = MINOR(inode->i_rdev); + + MOD_INC_USE_COUNT; + + mtd = get_mtd_device(NULL, dev); + + if (!mtd) { + MOD_DEC_USE_COUNT; + return -ENODEV; + } + + mtd_sizes[dev] = mtd->size>>9; + + DEBUG(1, "ok\n"); + + return 0; +} + +static release_t mtdblock_release(struct inode *inode, struct file *file) +{ + int dev; + struct mtd_info *mtd; + + DEBUG(1, "mtdblock_release\n"); + + if (inode == NULL) + release_return(-ENODEV); + + invalidate_device(inode->i_rdev, 1); + + dev = MINOR(inode->i_rdev); + mtd = __get_mtd_device(NULL, dev); + + if (!mtd) { + printk(KERN_WARNING "MTD device is absent on mtd_release!\n"); + MOD_DEC_USE_COUNT; + release_return(-ENODEV); + } + + if (mtd->sync) + mtd->sync(mtd); + + put_mtd_device(mtd); + + DEBUG(1, "ok\n"); + + MOD_DEC_USE_COUNT; + release_return(0); +} + + +static void mtdblock_request(RQFUNC_ARG) +{ + struct request *current_request; + unsigned int res = 0; + struct mtd_info *mtd; + + while (1) + { + /* Grab the Request and unlink it from the request list, INIT_REQUEST + will execute a return if we are done. */ + INIT_REQUEST; + current_request = CURRENT; + + if (MINOR(current_request->rq_dev) >= MAX_MTD_DEVICES) + { + printk("mtd: Unsupported device!\n"); + end_request(0); + continue; + } + + // Grab our MTD structure + + mtd = __get_mtd_device(NULL, MINOR(current_request->rq_dev)); + if (!mtd) { + printk("MTD device %d doesn't appear to exist any more\n", CURRENT_DEV); + end_request(0); + } + + if (current_request->sector << 9 > mtd->size || + (current_request->sector + current_request->nr_sectors) << 9 > mtd->size) + { + printk("mtd: Attempt to read past end of device!\n"); + printk("size: %x, sector: %lx, nr_sectors %lx\n", mtd->size, current_request->sector, current_request->nr_sectors); + end_request(0); + continue; + } + + /* Remove the request we are handling from the request list so nobody messes + with it */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) + /* Now drop the lock that the ll_rw_blk functions grabbed for us + and process the request. This is necessary due to the extreme time + we spend processing it. */ + spin_unlock_irq(&io_request_lock); +#endif + + // Handle the request + switch (current_request->cmd) + { + size_t retlen; + + case READ: + if (MTD_READ(mtd,current_request->sector<<9, + current_request->nr_sectors << 9, + &retlen, current_request->buffer) == 0) + res = 1; + else + res = 0; + break; + + case WRITE: + + /* printk("mtdblock_request WRITE sector=%d(%d)\n",current_request->sector, + current_request->nr_sectors); + */ + + // Read only device + if ((mtd->flags & MTD_CAP_RAM) == 0) + { + res = 0; + break; + } + + // Do the write + if (MTD_WRITE(mtd,current_request->sector<<9, + current_request->nr_sectors << 9, + &retlen, current_request->buffer) == 0) + res = 1; + else + res = 0; + break; + + // Shouldn't happen + default: + printk("mtd: unknown request\n"); + break; + } + + // Grab the lock and re-thread the item onto the linked list +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) + spin_lock_irq(&io_request_lock); +#endif + end_request(res); + } +} + + + +static int mtdblock_ioctl(struct inode * inode, struct file * file, + unsigned int cmd, unsigned long arg) +{ + struct mtd_info *mtd; + + mtd = __get_mtd_device(NULL, MINOR(inode->i_rdev)); + + if (!mtd) return -EINVAL; + + switch (cmd) { + case BLKGETSIZE: /* Return device size */ + if (!arg) return -EFAULT; + return Put_user((mtd->size >> 9), + (long *) arg); + + case BLKFLSBUF: +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) + if(!capable(CAP_SYS_ADMIN)) return -EACCES; +#endif + fsync_dev(inode->i_rdev); + invalidate_buffers(inode->i_rdev); + if (mtd->sync) + mtd->sync(mtd); + return 0; + + default: + return -ENOTTY; + } +} + +#if LINUX_VERSION_CODE < 0x20326 +static struct file_operations mtd_fops = +{ + open: mtdblock_open, + ioctl: mtdblock_ioctl, + release: mtdblock_release, + read: block_read, + write: block_write +}; +#else +static struct block_device_operations mtd_fops = +{ + open: mtdblock_open, + release: mtdblock_release, + ioctl: mtdblock_ioctl +}; +#endif + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define init_mtdblock init_module +#define cleanup_mtdblock cleanup_module +#endif + +int __init init_mtdblock(void) +{ + int i; + + if (register_blkdev(MAJOR_NR,DEVICE_NAME,&mtd_fops)) { + printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", + MTD_BLOCK_MAJOR); + return EAGAIN; + } + + /* We fill it in at open() time. */ + for (i=0; i< MAX_MTD_DEVICES; i++) { + mtd_sizes[i] = 0; + } + + /* Allow the block size to default to BLOCK_SIZE. */ + blksize_size[MAJOR_NR] = NULL; + blk_size[MAJOR_NR] = mtd_sizes; + +#if LINUX_VERSION_CODE < 0x20320 + blk_dev[MAJOR_NR].request_fn = mtdblock_request; +#else + blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &mtdblock_request); +#endif + return 0; +} + +static void __exit cleanup_mtdblock(void) +{ + unregister_blkdev(MAJOR_NR,DEVICE_NAME); +} + +module_init(init_mtdblock); +module_exit(cleanup_mtdblock); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/mtdchar.c linux/drivers/mtd/mtdchar.c --- v2.4.5/linux/drivers/mtd/mtdchar.c Mon May 21 17:06:29 2001 +++ linux/drivers/mtd/mtdchar.c Tue Jun 12 10:30:27 2001 @@ -1,5 +1,5 @@ /* - * $Id: mtdchar.c,v 1.21.2.3 2001/01/09 00:18:31 dwmw2 Exp $ + * $Id: mtdchar.c,v 1.38.2.1 2001/06/09 17:31:16 dwmw2 Exp $ * * Character-device access to raw MTD devices. * @@ -7,7 +7,6 @@ #include - #include #include #include @@ -18,21 +17,18 @@ #include static void mtd_notify_add(struct mtd_info* mtd); static void mtd_notify_remove(struct mtd_info* mtd); + static struct mtd_notifier notifier = { - mtd_notify_add, - mtd_notify_remove, - NULL + add: mtd_notify_add, + remove: mtd_notify_remove, }; -static devfs_handle_t devfs_dir_handle = NULL; + +static devfs_handle_t devfs_dir_handle; static devfs_handle_t devfs_rw_handle[MAX_MTD_DEVICES]; static devfs_handle_t devfs_ro_handle[MAX_MTD_DEVICES]; #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) static loff_t mtd_lseek (struct file *file, loff_t offset, int orig) -#else -static int mtd_lseek (struct inode *inode, struct file *file, off_t offset, int orig) -#endif { struct mtd_info *mtd=(struct mtd_info *)file->private_data; @@ -119,15 +115,18 @@ #define FILE_POS file->f_pos #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) +/* FIXME: This _really_ needs to die. In 2.5, we should lock the + userspace buffer down and use it directly with readv/writev. +*/ +#define MAX_KMALLOC_SIZE 0x20000 + static ssize_t mtd_read(struct file *file, char *buf, size_t count,loff_t *ppos) -#else -static int mtd_read(struct inode *inode,struct file *file, char *buf, int count) -#endif { struct mtd_info *mtd = (struct mtd_info *)file->private_data; size_t retlen=0; + size_t total_retlen=0; int ret=0; + int len; char *kbuf; DEBUG(MTD_DEBUG_LEVEL0,"MTD_read\n"); @@ -138,39 +137,50 @@ if (!count) return 0; - /* FIXME: Use kiovec in 2.3 or 2.2+rawio, or at - * least split the IO into smaller chunks. - */ - - kbuf = vmalloc(count); - if (!kbuf) - return -ENOMEM; - - ret = MTD_READ(mtd, FILE_POS, count, &retlen, kbuf); - if (!ret) { - FILE_POS += retlen; - if (copy_to_user(buf, kbuf, retlen)) - ret = -EFAULT; + /* FIXME: Use kiovec in 2.5 to lock down the user's buffers + and pass them directly to the MTD functions */ + while (count) { + if (count > MAX_KMALLOC_SIZE) + len = MAX_KMALLOC_SIZE; else - ret = retlen; + len = count; + kbuf=kmalloc(len,GFP_KERNEL); + if (!kbuf) + return -ENOMEM; + + ret = MTD_READ(mtd, FILE_POS, len, &retlen, kbuf); + if (!ret) { + FILE_POS += retlen; + if (copy_to_user(buf, kbuf, retlen)) { + kfree(kbuf); + return -EFAULT; + } + else + total_retlen += retlen; + + count -= retlen; + buf += retlen; + } + else { + kfree(kbuf); + return ret; + } + + kfree(kbuf); } - vfree(kbuf); - - return ret; + return total_retlen; } /* mtd_read */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) static ssize_t mtd_write(struct file *file, const char *buf, size_t count,loff_t *ppos) -#else -static read_write_t mtd_write(struct inode *inode,struct file *file, const char *buf, count_t count) -#endif { struct mtd_info *mtd = (struct mtd_info *)file->private_data; char *kbuf; size_t retlen; + size_t total_retlen=0; int ret=0; + int len; DEBUG(MTD_DEBUG_LEVEL0,"MTD_write\n"); @@ -183,27 +193,39 @@ if (!count) return 0; - kbuf=vmalloc(count); + while (count) { + if (count > MAX_KMALLOC_SIZE) + len = MAX_KMALLOC_SIZE; + else + len = count; - if (!kbuf) - return -ENOMEM; - - if (copy_from_user(kbuf, buf, count)) { - vfree(kbuf); - return -EFAULT; - } - + kbuf=kmalloc(len,GFP_KERNEL); + if (!kbuf) { + printk("kmalloc is null\n"); + return -ENOMEM; + } - ret = (*(mtd->write))(mtd, FILE_POS, count, &retlen, buf); + if (copy_from_user(kbuf, buf, len)) { + kfree(kbuf); + return -EFAULT; + } - if (!ret) { - FILE_POS += retlen; - ret = retlen; + ret = (*(mtd->write))(mtd, FILE_POS, len, &retlen, kbuf); + if (!ret) { + FILE_POS += retlen; + total_retlen += retlen; + count -= retlen; + buf += retlen; + } + else { + kfree(kbuf); + return ret; + } + + kfree(kbuf); } - vfree(kbuf); - - return ret; + return total_retlen; } /* mtd_write */ /*====================================================================== @@ -236,6 +258,30 @@ } switch (cmd) { + case MEMGETREGIONCOUNT: + if (copy_to_user((int *) arg, &(mtd->numeraseregions), sizeof(int))) + return -EFAULT; + break; + + case MEMGETREGIONINFO: + { + struct region_info_user ur; + + if (copy_from_user( &ur, + (struct region_info_user *)arg, + sizeof(struct region_info_user))) { + return -EFAULT; + } + + if (ur.regionindex >= mtd->numeraseregions) + return -EINVAL; + if (copy_to_user((struct mtd_erase_region_info *) arg, + &(mtd->eraseregions[ur.regionindex]), + sizeof(struct mtd_erase_region_info))) + return -EFAULT; + break; + } + case MEMGETINFO: if (copy_to_user((struct mtd_info *)arg, mtd, sizeof(struct mtd_info_user))) @@ -317,7 +363,7 @@ ret = (mtd->write_oob)(mtd, buf.start, buf.length, &retlen, databuf); - if (copy_to_user((void *)arg + sizeof(loff_t), &retlen, sizeof(ssize_t))) + if (copy_to_user((void *)arg + sizeof(u_int32_t), &retlen, sizeof(u_int32_t))) ret = -EFAULT; kfree(databuf); @@ -351,7 +397,7 @@ ret = (mtd->read_oob)(mtd, buf.start, buf.length, &retlen, databuf); - if (copy_to_user((void *)arg + sizeof(loff_t), &retlen, sizeof(ssize_t))) + if (copy_to_user((void *)arg + sizeof(u_int32_t), &retlen, sizeof(u_int32_t))) ret = -EFAULT; else if (retlen && copy_to_user(buf.ptr, databuf, retlen)) ret = -EFAULT; @@ -371,6 +417,7 @@ ret = -EOPNOTSUPP; else ret = mtd->lock(mtd, adrs[0], adrs[1]); + break; } case MEMUNLOCK: @@ -384,14 +431,15 @@ ret = -EOPNOTSUPP; else ret = mtd->unlock(mtd, adrs[0], adrs[1]); + break; } default: - printk("Invalid ioctl %x (MEMGETINFO = %x)\n",cmd, MEMGETINFO); - ret = -EINVAL; + DEBUG(MTD_DEBUG_LEVEL0, "Invalid ioctl %x (MEMGETINFO = %x)\n", cmd, MEMGETINFO); + ret = -ENOTTY; } - + return ret; } /* memory_ioctl */ diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/mtdcore.c linux/drivers/mtd/mtdcore.c --- v2.4.5/linux/drivers/mtd/mtdcore.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/mtd/mtdcore.c Tue Jun 12 10:30:27 2001 @@ -1,5 +1,5 @@ /* - * $Id: mtdcore.c,v 1.27 2000/12/10 01:10:09 dwmw2 Exp $ + * $Id: mtdcore.c,v 1.30 2001/06/02 14:30:42 dwmw2 Exp $ * * Core registration and callback routines for MTD * drivers and users. @@ -258,8 +258,8 @@ if (!this) return 0; - return sprintf(buf, "mtd%d: %8.8lx \"%s\"\n", i, this->size, - this->name); + return sprintf(buf, "mtd%d: %8.8x %8.8x \"%s\"\n", i, this->size, + this->erasesize, this->name); } static int mtd_read_proc ( char *page, char **start, off_t off,int count @@ -270,11 +270,12 @@ #endif ) { - int len = 0, l, i; + int len, l, i; off_t begin = 0; down(&mtd_table_mutex); + len = sprintf(page, "dev: size erasesize name\n"); for (i=0; i< MAX_MTD_DEVICES; i++) { l = mtd_proc_info(page + len, i); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/mtdpart.c linux/drivers/mtd/mtdpart.c --- v2.4.5/linux/drivers/mtd/mtdpart.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/mtd/mtdpart.c Tue Jun 12 10:30:27 2001 @@ -5,7 +5,7 @@ * * This code is GPL * - * $Id: mtdpart.c,v 1.7 2000/12/09 23:29:47 dwmw2 Exp $ + * $Id: mtdpart.c,v 1.21 2001/06/09 16:33:32 dwmw2 Exp $ */ #include @@ -25,7 +25,7 @@ struct mtd_part { struct mtd_info mtd; struct mtd_info *master; - loff_t offset; + u_int32_t offset; int index; struct list_head list; }; @@ -100,15 +100,36 @@ static int part_lock (struct mtd_info *mtd, loff_t ofs, size_t len) { struct mtd_part *part = PART(mtd); + if ((len + ofs) > mtd->size) + return -EINVAL; return part->master->lock(part->master, ofs + part->offset, len); } static int part_unlock (struct mtd_info *mtd, loff_t ofs, size_t len) { struct mtd_part *part = PART(mtd); + if ((len + ofs) > mtd->size) + return -EINVAL; return part->master->unlock(part->master, ofs + part->offset, len); } +static void part_sync(struct mtd_info *mtd) +{ + struct mtd_part *part = PART(mtd); + part->master->sync(part->master); +} + +static int part_suspend(struct mtd_info *mtd) +{ + struct mtd_part *part = PART(mtd); + return part->master->suspend(part->master); +} + +static void part_resume(struct mtd_info *mtd) +{ + struct mtd_part *part = PART(mtd); + part->master->resume(part->master); +} /* * This function unregisters and destroy all slave MTD objects which are @@ -130,14 +151,12 @@ del_mtd_device(&slave->mtd); kfree(slave); node = prev; - MOD_DEC_USE_COUNT; } } return 0; } - /* * This function, given a master MTD object and a partition table, creates * and registers slave MTD objects which are bound to the master according to @@ -150,10 +169,13 @@ int nbparts) { struct mtd_part *slave; - u_long cur_offset = 0; + u_int32_t cur_offset = 0; int i; + printk (KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name); + for (i = 0; i < nbparts; i++) { + /* allocate the partition structure */ slave = kmalloc (sizeof(*slave), GFP_KERNEL); if (!slave) { @@ -162,63 +184,102 @@ del_mtd_partitions(master); return -ENOMEM; } + memset(slave, 0, sizeof(*slave)); list_add(&slave->list, &mtd_partitions); /* set up the MTD object for this partition */ - slave->mtd = *master; - slave->mtd.name = parts[i].name; + slave->mtd.type = master->type; + slave->mtd.flags = master->flags & ~parts[i].mask_flags; slave->mtd.size = parts[i].size; - slave->mtd.flags &= ~parts[i].mask_flags; + slave->mtd.oobblock = master->oobblock; + slave->mtd.oobsize = master->oobsize; + slave->mtd.ecctype = master->ecctype; + slave->mtd.eccsize = master->eccsize; + + slave->mtd.name = parts[i].name; + slave->mtd.bank_size = master->bank_size; + + slave->mtd.module = master->module; + slave->mtd.read = part_read; slave->mtd.write = part_write; - if (slave->mtd.writev) + slave->mtd.sync = part_sync; + if (!i && master->suspend && master->resume) { + slave->mtd.suspend = part_suspend; + slave->mtd.resume = part_resume; + } + + if (master->writev) slave->mtd.writev = part_writev; - if (slave->mtd.readv) + if (master->readv) slave->mtd.readv = part_readv; - if (slave->mtd.lock) + if (master->lock) slave->mtd.lock = part_lock; - if (slave->mtd.unlock) + if (master->unlock) slave->mtd.unlock = part_unlock; slave->mtd.erase = part_erase; slave->master = master; slave->offset = parts[i].offset; slave->index = i; - if (slave->offset == 0) + if (slave->offset == MTDPART_OFS_APPEND) slave->offset = cur_offset; - if (slave->mtd.size == 0) + if (slave->mtd.size == MTDPART_SIZ_FULL) slave->mtd.size = master->size - slave->offset; cur_offset = slave->offset + slave->mtd.size; + + printk (KERN_NOTICE "0x%08x-0x%08x : \"%s\"\n", slave->offset, + slave->offset + slave->mtd.size, slave->mtd.name); /* let's do some sanity checks */ + if (slave->offset >= master->size) { + /* let's register it anyway to preserve ordering */ + slave->offset = 0; + slave->mtd.size = 0; + printk ("mtd: partition \"%s\" is out of reach -- disabled\n", + parts[i].name); + } + if (slave->offset + slave->mtd.size > master->size) { + slave->mtd.size = master->size - slave->offset; + printk ("mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#x\n", + parts[i].name, master->name, slave->mtd.size); + } + if (master->numeraseregions>1) { + /* Deal with variable erase size stuff */ + int i; + struct mtd_erase_region_info *regions = master->eraseregions; + + /* Find the first erase regions which is part of this partition. */ + for (i=0; i < master->numeraseregions && slave->offset >= regions[i].offset; i++) + ; + + for (i--; i < master->numeraseregions && slave->offset + slave->mtd.size > regions[i].offset; i++) { + if (slave->mtd.erasesize < regions[i].erasesize) { + slave->mtd.erasesize = regions[i].erasesize; + } + } + } else { + /* Single erase size */ + slave->mtd.erasesize = master->erasesize; + } + if ((slave->mtd.flags & MTD_WRITEABLE) && - (parts[i].offset % master->erasesize)) { + (slave->offset % slave->mtd.erasesize)) { + /* Doesn't start on a boundary of major erase size */ + /* FIXME: Let it be writable if it is on a boundary of _minor_ erase size though */ slave->mtd.flags &= ~MTD_WRITEABLE; printk ("mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n", - parts[i].name); + parts[i].name); } if ((slave->mtd.flags & MTD_WRITEABLE) && - (parts[i].size % master->erasesize)) { + (slave->mtd.size % slave->mtd.erasesize)) { slave->mtd.flags &= ~MTD_WRITEABLE; printk ("mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n", - parts[i].name); - } - if (parts[i].offset >= master->size) { - /* let's register it anyway to preserve ordering */ - slave->offset = 0; - slave->mtd.size = 0; - printk ("mtd: partition \"%s\" is out of reach -- disabled\n", - parts[i].name); - } - if (parts[i].offset + parts[i].size > master->size) { - slave->mtd.size = master->size - parts[i].offset; - printk ("mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#lx\n", - parts[i].name, master->name, slave->mtd.size); + parts[i].name); } /* register our partition */ add_mtd_device(&slave->mtd); - MOD_INC_USE_COUNT; } return 0; diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/mtdram.c linux/drivers/mtd/mtdram.c --- v2.4.5/linux/drivers/mtd/mtdram.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/mtd/mtdram.c Wed Dec 31 16:00:00 1969 @@ -1,148 +0,0 @@ -/* - * mtdram - a test mtd device - * $Id: mtdram.c,v 1.15 2000/07/13 12:40:46 scote1 Exp $ - * Author: Alexander Larsson - * - * Copyright (c) 1999 Alexander Larsson - * - * This code is GPL - * - */ - -#include -#include - -#include -#include -#include -#include - - -#define MTDRAM_TOTAL_SIZE (CONFIG_MTDRAM_TOTAL_SIZE * 1024) -#define MTDRAM_ERASE_SIZE (CONFIG_MTDRAM_ERASE_SIZE * 1024) - - -// We could store these in the mtd structure, but we only support 1 device.. -static struct mtd_info *mtd_info; - - -static int -ram_erase(struct mtd_info *mtd, struct erase_info *instr) -{ - if (instr->addr + instr->len > mtd->size) - return -EINVAL; - - memset((char *)mtd->priv + instr->addr, 0xff, instr->len); - - instr->state = MTD_ERASE_DONE; - - if (instr->callback) - (*(instr->callback))(instr); - return 0; -} - -static int ram_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf) -{ - if (from + len > mtd->size) - return -EINVAL; - - *mtdbuf = mtd->priv + from; - *retlen = len; - return 0; -} - -static void ram_unpoint (struct mtd_info *mtd, u_char *addr) -{ -} - -static int ram_read(struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf) -{ - if (from + len > mtd->size) - return -EINVAL; - - memcpy(buf, mtd->priv + from, len); - - *retlen=len; - return 0; -} - -static int ram_write(struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf) -{ - if (to + len > mtd->size) - return -EINVAL; - - memcpy ((char *)mtd->priv + to, buf, len); - - *retlen=len; - return 0; -} - -#if LINUX_VERSION_CODE < 0x20300 -#ifdef MODULE -#define init_mtdram init_module -#define cleanup_mtdram cleanup_module -#endif -#endif - -//static void __exit cleanup_mtdram(void) -mod_exit_t cleanup_mtdram(void) -{ - if (mtd_info) { - del_mtd_device(mtd_info); - if (mtd_info->priv) - vfree(mtd_info->priv); - kfree(mtd_info); - } -} - -extern struct module __this_module; - -mod_init_t init_mtdram(void) -{ - // Allocate some memory - mtd_info = (struct mtd_info *)kmalloc(sizeof(struct mtd_info), GFP_KERNEL); - if (mtd_info == 0) - return 0; - - memset(mtd_info, 0, sizeof(*mtd_info)); - - // Setup the MTD structure - mtd_info->name = "mtdram test device"; - mtd_info->type = MTD_RAM; - mtd_info->flags = MTD_CAP_RAM; - mtd_info->size = MTDRAM_TOTAL_SIZE; - mtd_info->erasesize = MTDRAM_ERASE_SIZE; - mtd_info->priv = vmalloc(MTDRAM_TOTAL_SIZE); - memset(mtd_info->priv, 0xff, MTDRAM_TOTAL_SIZE); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) - mtd_info->module = THIS_MODULE; -#endif - - if (!mtd_info->priv) { - kfree(mtd_info); - mtd_info = NULL; - return -ENOMEM; - } - mtd_info->erase = ram_erase; - mtd_info->point = ram_point; - mtd_info->unpoint = ram_unpoint; - mtd_info->read = ram_read; - mtd_info->write = ram_write; - - if (add_mtd_device(mtd_info)) { - vfree(mtd_info->priv); - kfree(mtd_info); - mtd_info = NULL; - return -EIO; - } - - return 0; -} - -#if LINUX_VERSION_CODE > 0x20300 -module_init(init_mtdram); -module_exit(cleanup_mtdram); -#endif diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/nand/Config.in linux/drivers/mtd/nand/Config.in --- v2.4.5/linux/drivers/mtd/nand/Config.in Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/nand/Config.in Tue Jul 3 12:15:40 2001 @@ -0,0 +1,18 @@ +# drivers/mtd/nand/Config.in + +# $Id: Config.in,v 1.3 2001/07/03 17:50:56 sjhill Exp $ + +mainmenu_option next_comment + +comment 'NAND Flash Device Drivers' + +dep_tristate ' NAND Device Support' CONFIG_MTD_NAND $CONFIG_MTD +if [ "$CONFIG_MTD_NAND" = "y" -o "$CONFIG_MTD_NAND" = "m" ]; then + bool ' Enable ECC correction algorithm' CONFIG_MTD_NAND_ECC y + bool ' Verify NAND page writes' CONFIG_MTD_NAND_VERIFY_WRITE y +fi +if [ "$CONFIG_ARM" = "y" -a "$CONFIG_ARCH_P720T" = "y" ]; then + dep_tristate ' NAND Flash device on SPIA board' CONFIG_MTD_NAND_SPIA $CONFIG_MTD_NAND +fi + +endmenu diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/nand/Makefile linux/drivers/mtd/nand/Makefile --- v2.4.5/linux/drivers/mtd/nand/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/nand/Makefile Thu Jun 28 14:43:02 2001 @@ -0,0 +1,14 @@ +# +# linux/drivers/nand/Makefile +# +# $Id: Makefile,v 1.4 2001/06/28 10:49:45 dwmw2 Exp $ + +O_TARGET := nandlink.o + +export-objs := nand.o nand_ecc.o + +obj-$(CONFIG_MTD_NAND) += nand.o +obj-$(CONFIG_MTD_NAND_ECC) += nand_ecc.o +obj-$(CONFIG_MTD_NAND_SPIA) += spia.o + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/nand/nand.c linux/drivers/mtd/nand/nand.c --- v2.4.5/linux/drivers/mtd/nand/nand.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/nand/nand.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,1369 @@ +/* + * drivers/mtd/nand.c + * + * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com) + * + * $Id: nand.c,v 1.10 2001/03/20 07:26:01 dwmw2 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 + * published by the Free Software Foundation. + * + * Overview: + * This is the generic MTD driver for NAND flash devices. It should be + * capable of working with almost all NAND chips currently available. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_MTD_NAND_ECC +#include +#endif + +/* + * Macros for low-level register control + */ +#define NAND_CTRL (*(volatile unsigned char *) \ + ((struct nand_chip *) mtd->priv)->CTRL_ADDR) +#define nand_select() NAND_CTRL &= ~this->NCE; \ + nand_command(mtd, NAND_CMD_RESET, -1, -1); \ + udelay (10); +#define nand_deselect() NAND_CTRL |= ~this->NCE; + +/* + * NAND low-level MTD interface functions + */ +static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf); +static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf, u_char *ecc_code); +static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf); +static int nand_write (struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf); +static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf, + u_char *ecc_code); +static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf); +static int nand_writev (struct mtd_info *mtd, const struct iovec *vecs, + unsigned long count, loff_t to, size_t *retlen); +static int nand_erase (struct mtd_info *mtd, struct erase_info *instr); +static void nand_sync (struct mtd_info *mtd); + +/* + * Send command to NAND device + */ +static void nand_command (struct mtd_info *mtd, unsigned command, + int column, int page_addr) +{ + register struct nand_chip *this = mtd->priv; + register unsigned long NAND_IO_ADDR = this->IO_ADDR; + + /* Begin command latch cycle */ + NAND_CTRL |= this->CLE; + + /* + * Write out the command to the device. + */ + if (command != NAND_CMD_SEQIN) + writeb (command, NAND_IO_ADDR); + else { + if (mtd->oobblock == 256 && column >= 256) { + column -= 256; + writeb(NAND_CMD_RESET, NAND_IO_ADDR); + writeb(NAND_CMD_READOOB, NAND_IO_ADDR); + writeb(NAND_CMD_SEQIN, NAND_IO_ADDR); + } + else if (mtd->oobblock == 512 && column >= 256) { + if (column < 512) { + column -= 256; + writeb(NAND_CMD_READ1, NAND_IO_ADDR); + writeb(NAND_CMD_SEQIN, NAND_IO_ADDR); + } + else { + column -= 512; + writeb(NAND_CMD_READOOB, NAND_IO_ADDR); + writeb(NAND_CMD_SEQIN, NAND_IO_ADDR); + } + } + else { + writeb(NAND_CMD_READ0, NAND_IO_ADDR); + writeb(NAND_CMD_SEQIN, NAND_IO_ADDR); + } + } + + /* Set ALE and clear CLE to start address cycle */ + NAND_CTRL &= ~this->CLE; + NAND_CTRL |= this->ALE; + + /* Serially input address */ + if (column != -1) + writeb (column, NAND_IO_ADDR); + if (page_addr != -1) { + writeb ((unsigned char) (page_addr & 0xff), NAND_IO_ADDR); + writeb ((unsigned char) ((page_addr >> 8) & 0xff), NAND_IO_ADDR); + /* One more address cycle for higher density devices */ + if (mtd->size & 0x0c000000) { + writeb ((unsigned char) ((page_addr >> 16) & 0x0f), + NAND_IO_ADDR); + } + } + + /* Latch in address */ + NAND_CTRL &= ~this->ALE; + + /* Pause for 15us */ + udelay (15); +} + +/* + * NAND read + */ +static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ +#ifdef CONFIG_MTD_NAND_ECC + struct nand_chip *this = mtd->priv; + + return nand_read_ecc (mtd, from, len, retlen, buf, this->ecc_code_buf); +#else + return nand_read_ecc (mtd, from, len, retlen, buf, NULL); +#endif +} + +/* + * NAND read with ECC + */ +static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf, u_char *ecc_code) +{ + int j, col, page, state; + int erase_state = 0; + struct nand_chip *this = mtd->priv; + DECLARE_WAITQUEUE(wait, current); +#ifdef CONFIG_MTD_NAND_ECC + int ecc_result; + u_char ecc_calc[6]; +#endif + + DEBUG (MTD_DEBUG_LEVEL3, + "nand_read_ecc: from = 0x%08x, len = %i\n", (unsigned int) from, + (int) len); + + /* Do not allow reads past end of device */ + if ((from + len) > mtd->size) { + DEBUG (MTD_DEBUG_LEVEL0, + "nand_read_ecc: Attempt read beyond end of device\n"); + *retlen = 0; + return -EINVAL; + } + + /* Grab the lock and see if the device is available */ +retry: + spin_lock_bh (&this->chip_lock); + + switch (this->state) { + case FL_READY: + this->state = FL_READING; + spin_unlock_bh (&this->chip_lock); + break; + + case FL_ERASING: + this->state = FL_READING; + erase_state = 1; + spin_unlock_bh (&this->chip_lock); + break; + + default: + set_current_state (TASK_UNINTERRUPTIBLE); + add_wait_queue (&this->wq, &wait); + spin_unlock_bh (&this->chip_lock); + schedule(); + + remove_wait_queue (&this->wq, &wait); + goto retry; + }; + + /* First we calculate the starting page */ + page = from >> this->page_shift; + + /* Get raw starting column */ + col = from & (mtd->oobblock - 1); + + /* State machine for devices having pages larger than 256 bytes */ + state = (col < mtd->eccsize) ? 0 : 1; + + /* Calculate column address within ECC block context */ + col = (col >= mtd->eccsize) ? (col - mtd->eccsize) : col; + + /* Initialize return value */ + *retlen = 0; + + /* Select the NAND device */ + nand_select (); + + /* Loop until all data read */ + while (*retlen < len) { + +#ifdef CONFIG_MTD_NAND_ECC + /* Send the read command */ + if (!state) + nand_command (mtd, NAND_CMD_READ0, 0x00, page); + else + nand_command (mtd, NAND_CMD_READ1, 0x00, page); + + /* Read in a block big enough for ECC */ + for (j=0 ; j < mtd->eccsize ; j++) + this->data_buf[j] = readb (this->IO_ADDR); + + /* Read in the out-of-band data */ + if (!state) { + nand_command (mtd, NAND_CMD_READOOB, 0x00, page); + for (j=0 ; j<3 ; j++) + ecc_code[j] = readb(this->IO_ADDR); + nand_command (mtd, NAND_CMD_READ0, 0x00, page); + } + else { + nand_command (mtd, NAND_CMD_READOOB, 0x03, page); + for (j=3 ; j<6 ; j++) + ecc_code[j] = readb(this->IO_ADDR); + nand_command (mtd, NAND_CMD_READ0, 0x00, page); + } + + /* Calculate the ECC and verify it */ + if (!state) { + nand_calculate_ecc (&this->data_buf[0], + &ecc_calc[0]); + ecc_result = nand_correct_data (&this->data_buf[0], + &ecc_code[0], &ecc_calc[0]); + } + else { + nand_calculate_ecc (&this->data_buf[0], + &ecc_calc[3]); + ecc_result = nand_correct_data (&this->data_buf[0], + &ecc_code[3], &ecc_calc[3]); + } + if (ecc_result == -1) { + DEBUG (MTD_DEBUG_LEVEL0, + "nand_read_ecc: " \ + "Failed ECC read, page 0x%08x\n", page); + nand_deselect (); + spin_lock_bh (&this->chip_lock); + if (erase_state) + this->state = FL_ERASING; + else + this->state = FL_READY; + wake_up (&this->wq); + spin_unlock_bh (&this->chip_lock); + return -EIO; + } + + /* Read the data from ECC data buffer into return buffer */ + if ((*retlen + (mtd->eccsize - col)) >= len) { + while (*retlen < len) + buf[(*retlen)++] = this->data_buf[col++]; + /* We're done */ + continue; + } + else + for (j=col ; j < mtd->eccsize ; j++) + buf[(*retlen)++] = this->data_buf[j]; +#else + /* Send the read command */ + if (!state) + nand_command (mtd, NAND_CMD_READ0, col, page); + else + nand_command (mtd, NAND_CMD_READ1, col, page); + + /* Read the data directly into the return buffer */ + if ((*retlen + (mtd->eccsize - col)) >= len) { + while (*retlen < len) + buf[(*retlen)++] = readb (this->IO_ADDR); + /* We're done */ + continue; + } + else + for (j=col ; j < mtd->eccsize ; j++) + buf[(*retlen)++] = readb (this->IO_ADDR); +#endif + + /* + * If the amount of data to be read is greater than + * (256 - col), then all subsequent reads will take + * place on page or half-page (in the case of 512 byte + * page devices) aligned boundaries and the column + * address will be zero. Setting the column address to + * to zero after the first read allows us to simplify + * the reading of data and the if/else statements above. + */ + if (col) + col = 0x00; + + /* Increment page address */ + if ((mtd->oobblock == 256) || state) + page++; + + /* Toggle state machine */ + if (mtd->oobblock == 512) + state = state ? 0 : 1; + } + + /* De-select the NAND device */ + nand_deselect (); + + /* Wake up anyone waiting on the device */ + spin_lock_bh (&this->chip_lock); + if (erase_state) + this->state = FL_ERASING; + else + this->state = FL_READY; + wake_up (&this->wq); + spin_unlock_bh (&this->chip_lock); + + /* Return happy */ + return 0; +} + +/* + * NAND read out-of-band + */ +static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + int i, col, page; + int erase_state = 0; + struct nand_chip *this = mtd->priv; + DECLARE_WAITQUEUE(wait, current); + + DEBUG (MTD_DEBUG_LEVEL3, + "nand_read_oob: from = 0x%08x, len = %i\n", (unsigned int) from, + (int) len); + + /* Shift to get page */ + page = ((int) from) >> this->page_shift; + + /* Mask to get column */ + col = from & 0x0f; + + /* Initialize return length value */ + *retlen = 0; + + /* Do not allow read past end of page */ + if ((col + len) > mtd->oobsize) { + DEBUG (MTD_DEBUG_LEVEL0, + "nand_read_oob: Attempt read past end of page " \ + "0x%08x, column %i, length %i\n", page, col, len); + return -EINVAL; + } + +retry: + /* Grab the lock and see if the device is available */ + spin_lock_bh (&this->chip_lock); + + switch (this->state) { + case FL_READY: + this->state = FL_READING; + spin_unlock_bh (&this->chip_lock); + break; + + case FL_ERASING: + this->state = FL_READING; + erase_state = 1; + spin_unlock_bh (&this->chip_lock); + break; + + default: + set_current_state (TASK_UNINTERRUPTIBLE); + add_wait_queue (&this->wq, &wait); + spin_unlock_bh (&this->chip_lock); + schedule(); + + remove_wait_queue (&this->wq, &wait); + goto retry; + }; + + /* Select the NAND device */ + nand_select (); + + /* Send the read command */ + nand_command (mtd, NAND_CMD_READOOB, col, page); + + /* Read the data */ + for (i = 0 ; i < len ; i++) + buf[i] = readb (this->IO_ADDR); + + /* De-select the NAND device */ + nand_deselect (); + + /* Wake up anyone waiting on the device */ + spin_lock_bh (&this->chip_lock); + if (erase_state) + this->state = FL_ERASING; + else + this->state = FL_READY; + wake_up (&this->wq); + spin_unlock_bh (&this->chip_lock); + + /* Return happy */ + *retlen = len; + return 0; +} + +/* + * NAND write + */ +static int nand_write (struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ +#ifdef CONFIG_MTD_NAND_ECC + struct nand_chip *this = mtd->priv; + + return nand_write_ecc (mtd, to, len, retlen, buf, this->ecc_code_buf); +#else + return nand_write_ecc (mtd, to, len, retlen, buf, NULL); +#endif +} + +/* + * NAND write with ECC + */ +static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf, + u_char *ecc_code) +{ + int i, page, col, cnt, status; + struct nand_chip *this = mtd->priv; + DECLARE_WAITQUEUE(wait, current); +#ifdef CONFIG_MTD_NAND_ECC + int ecc_bytes = (mtd->oobblock == 512) ? 6 : 3; +#endif + + DEBUG (MTD_DEBUG_LEVEL3, + "nand_write_ecc: to = 0x%08x, len = %i\n", (unsigned int) to, + (int) len); + + /* Do not allow write past end of page */ + if ((to + len) > mtd->size) { + DEBUG (MTD_DEBUG_LEVEL0, + "nand_write_ecc: Attempted write past end of device\n"); + return -EINVAL; + } + +retry: + /* Grab the lock and see if the device is available */ + spin_lock_bh (&this->chip_lock); + + switch (this->state) { + case FL_READY: + this->state = FL_WRITING; + spin_unlock_bh (&this->chip_lock); + break; + + default: + set_current_state (TASK_UNINTERRUPTIBLE); + add_wait_queue (&this->wq, &wait); + spin_unlock_bh (&this->chip_lock); + schedule(); + + remove_wait_queue (&this->wq, &wait); + goto retry; + }; + + /* Shift to get page */ + page = ((int) to) >> this->page_shift; + + /* Get the starting column */ + col = to & (mtd->oobblock - 1); + + /* Initialize return length value */ + *retlen = 0; + + /* Select the NAND device */ + nand_select (); + + /* Check the WP bit */ + nand_command (mtd, NAND_CMD_STATUS, -1, -1); + if (!(readb (this->IO_ADDR) & 0x80)) { + DEBUG (MTD_DEBUG_LEVEL0, + "nand_write_ecc: Device is write protected!!!\n"); + nand_deselect (); + spin_lock_bh (&this->chip_lock); + this->state = FL_READY; + wake_up (&this->wq); + spin_unlock_bh (&this->chip_lock); + return -EIO; + } + + /* Loop until all data is written */ + while (*retlen < len) { + /* Write data into buffer */ + if ((col + len) >= mtd->oobblock) + for(i=col, cnt=0 ; i < mtd->oobblock ; i++, cnt++) + this->data_buf[i] = buf[(*retlen + cnt)]; + else + for(i=col, cnt=0 ; cnt < (len - *retlen) ; i++, cnt++) + this->data_buf[i] = buf[(*retlen + cnt)]; + +#ifdef CONFIG_MTD_NAND_ECC + /* Zero out the ECC array */ + for (i=0 ; i < 6 ; i++) + ecc_code[i] = 0x00; + + /* Calculate and write the ECC if we have enough data */ + if ((col < mtd->eccsize) && + ((col + (len - *retlen)) >= mtd->eccsize)) { + nand_command (mtd, NAND_CMD_READ0, col, page); + for (i=0 ; i < col ; i++) + this->data_buf[i] = readb (this->IO_ADDR); + nand_calculate_ecc (&this->data_buf[0], &ecc_code[0]); + for (i=0 ; i<3 ; i++) + this->data_buf[(mtd->oobblock + i)] = + ecc_code[i]; + } + + /* Calculate and write the second ECC if we have enough data */ + if ((mtd->oobblock == 512) && + ((col + (len - *retlen)) >= mtd->oobblock)) { + nand_calculate_ecc (&this->data_buf[256], &ecc_code[3]); + for (i=3 ; i<6 ; i++) + this->data_buf[(mtd->oobblock + i)] = + ecc_code[i]; + } + + /* Write ones for partial page programming */ + for (i=ecc_bytes ; i < mtd->oobsize ; i++) + this->data_buf[(mtd->oobblock + i)] = 0xff; +#else + /* Write ones for partial page programming */ + for (i=mtd->oobblock ; i < (mtd->oobblock + mtd->oobsize) ; i++) + this->data_buf[i] = 0xff; +#endif + + /* Write pre-padding bytes into buffer */ + for (i=0 ; i < col ; i++) + this->data_buf[i] = 0xff; + + /* Write post-padding bytes into buffer */ + if ((col + (len - *retlen)) < mtd->oobblock) { + for(i=(col + cnt) ; i < mtd->oobblock ; i++) + this->data_buf[i] = 0xff; + } + + /* Send command to begin auto page programming */ + nand_command (mtd, NAND_CMD_SEQIN, 0x00, page); + + /* Write out complete page of data */ + for (i=0 ; i < (mtd->oobblock + mtd->oobsize) ; i++) + writeb (this->data_buf[i], this->IO_ADDR); + + /* Send command to actually program the data */ + nand_command (mtd, NAND_CMD_PAGEPROG, -1, -1); + + /* + * Wait for program operation to complete. This could + * take up to 3000us (3ms) on some devices, so we try + * and exit as quickly as possible. + */ + status = 0; + for (i=0 ; i<24 ; i++) { + /* Delay for 125us */ + udelay (125); + + /* Check the status */ + nand_command (mtd, NAND_CMD_STATUS, -1, -1); + status = (int) readb (this->IO_ADDR); + if (status & 0x40) + break; + } + + /* See if device thinks it succeeded */ + if (status & 0x01) { + DEBUG (MTD_DEBUG_LEVEL0, + "nand_write_ecc: " \ + "Failed write, page 0x%08x, " \ + "%6i bytes were succesful\n", page, *retlen); + nand_deselect (); + spin_lock_bh (&this->chip_lock); + this->state = FL_READY; + wake_up (&this->wq); + spin_unlock_bh (&this->chip_lock); + return -EIO; + } + +#ifdef CONFIG_MTD_NAND_VERIFY_WRITE + /* + * The NAND device assumes that it is always writing to + * a cleanly erased page. Hence, it performs its internal + * write verification only on bits that transitioned from + * 1 to 0. The device does NOT verify the whole page on a + * byte by byte basis. It is possible that the page was + * not completely erased or the page is becoming unusable + * due to wear. The read with ECC would catch the error + * later when the ECC page check fails, but we would rather + * catch it early in the page write stage. Better to write + * no data than invalid data. + */ + + /* Send command to read back the page */ + if (col < mtd->eccsize) + nand_command (mtd, NAND_CMD_READ0, col, page); + else + nand_command (mtd, NAND_CMD_READ1, col - 256, page); + + /* Loop through and verify the data */ + for (i=col ; i < cnt ; i++) { + if (this->data_buf[i] != readb (this->IO_ADDR)) { + DEBUG (MTD_DEBUG_LEVEL0, + "nand_write_ecc: " \ + "Failed write verify, page 0x%08x, " \ + "%6i bytes were succesful\n", + page, *retlen); + nand_deselect (); + spin_lock_bh (&this->chip_lock); + this->state = FL_READY; + wake_up (&this->wq); + spin_unlock_bh (&this->chip_lock); + return -EIO; + } + } + +#ifdef CONFIG_MTD_NAND_ECC + /* + * We also want to check that the ECC bytes wrote + * correctly for the same reasons stated above. + */ + nand_command (mtd, NAND_CMD_READOOB, 0x00, page); + for (i=0 ; i < ecc_bytes ; i++) { + if ((readb (this->IO_ADDR) != ecc_code[i]) && + ecc_code[i]) { + DEBUG (MTD_DEBUG_LEVEL0, + "nand_write_ecc: Failed ECC write " \ + "verify, page 0x%08x, " \ + "%6i bytes were succesful\n", + page, i); + nand_deselect (); + spin_lock_bh (&this->chip_lock); + this->state = FL_READY; + wake_up (&this->wq); + spin_unlock_bh (&this->chip_lock); + return -EIO; + } + } +#endif + +#endif + + /* + * If we are writing a large amount of data and/or it + * crosses page or half-page boundaries, we set the + * the column to zero. It simplifies the program logic. + */ + if (col) + col = 0x00; + + /* Update written bytes count */ + *retlen += cnt; + + /* Increment page address */ + page++; + } + + /* De-select the NAND device */ + nand_deselect (); + + /* Wake up anyone waiting on the device */ + spin_lock_bh (&this->chip_lock); + this->state = FL_READY; + wake_up (&this->wq); + spin_unlock_bh (&this->chip_lock); + + /* Return happy */ + *retlen = len; + return 0; +} + +/* + * NAND write out-of-band + */ +static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + int i, column, page, status; + struct nand_chip *this = mtd->priv; + DECLARE_WAITQUEUE(wait, current); + + DEBUG (MTD_DEBUG_LEVEL3, + "nand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, + (int) len); + + /* Shift to get page */ + page = ((int) to) >> this->page_shift; + + /* Mask to get column */ + column = to & 0x1f; + + /* Initialize return length value */ + *retlen = 0; + + /* Do not allow write past end of page */ + if ((column + len) > mtd->oobsize) { + DEBUG (MTD_DEBUG_LEVEL0, + "nand_write_oob: Attempt to write past end of page\n"); + return -EINVAL; + } + +retry: + /* Grab the lock and see if the device is available */ + spin_lock_bh (&this->chip_lock); + + switch (this->state) { + case FL_READY: + this->state = FL_WRITING; + spin_unlock_bh (&this->chip_lock); + break; + + default: + set_current_state (TASK_UNINTERRUPTIBLE); + add_wait_queue (&this->wq, &wait); + spin_unlock_bh (&this->chip_lock); + schedule(); + + remove_wait_queue (&this->wq, &wait); + goto retry; + }; + + /* Select the NAND device */ + nand_select (); + + /* Check the WP bit */ + nand_command (mtd, NAND_CMD_STATUS, -1, -1); + if (!(readb (this->IO_ADDR) & 0x80)) { + DEBUG (MTD_DEBUG_LEVEL0, + "nand_write_oob: Device is write protected!!!\n"); + nand_deselect (); + spin_lock_bh (&this->chip_lock); + this->state = FL_READY; + wake_up (&this->wq); + spin_unlock_bh (&this->chip_lock); + return -EIO; + } + + /* Write out desired data */ + nand_command (mtd, NAND_CMD_SEQIN, column + 512, page); + for (i=0 ; iIO_ADDR); + + /* Send command to program the OOB data */ + nand_command (mtd, NAND_CMD_PAGEPROG, -1, -1); + + /* + * Wait for program operation to complete. This could + * take up to 3000us (3ms) on some devices, so we try + * and exit as quickly as possible. + */ + status = 0; + for (i=0 ; i<24 ; i++) { + /* Delay for 125us */ + udelay (125); + + /* Check the status */ + nand_command (mtd, NAND_CMD_STATUS, -1, -1); + status = (int) readb (this->IO_ADDR); + if (status & 0x40) + break; + } + + /* See if device thinks it succeeded */ + if (status & 0x01) { + DEBUG (MTD_DEBUG_LEVEL0, + "nand_write_oob: " \ + "Failed write, page 0x%08x\n", page); + nand_deselect (); + spin_lock_bh (&this->chip_lock); + this->state = FL_READY; + wake_up (&this->wq); + spin_unlock_bh (&this->chip_lock); + return -EIO; + } + +#ifdef CONFIG_MTD_NAND_VERIFY_WRITE + /* Send command to read back the data */ + nand_command (mtd, NAND_CMD_READOOB, column, page); + + /* Loop through and verify the data */ + for (i=0 ; iIO_ADDR)) { + DEBUG (MTD_DEBUG_LEVEL0, + "nand_write_oob: " \ + "Failed write verify, page 0x%08x\n", page); + nand_deselect (); + spin_lock_bh (&this->chip_lock); + this->state = FL_READY; + wake_up (&this->wq); + spin_unlock_bh (&this->chip_lock); + return -EIO; + } + } +#endif + + /* De-select the NAND device */ + nand_deselect (); + + /* Wake up anyone waiting on the device */ + spin_lock_bh (&this->chip_lock); + this->state = FL_READY; + wake_up (&this->wq); + spin_unlock_bh (&this->chip_lock); + + /* Return happy */ + *retlen = len; + return 0; +} + +/* + * NAND write with iovec + */ +static int nand_writev (struct mtd_info *mtd, const struct iovec *vecs, + unsigned long count, loff_t to, size_t *retlen) +{ + int i, page, col, cnt, len, total_len, status; + struct nand_chip *this = mtd->priv; + DECLARE_WAITQUEUE(wait, current); +#ifdef CONFIG_MTD_NAND_ECC + int ecc_bytes = (mtd->oobblock == 512) ? 6 : 3; +#endif + + /* Calculate total length of data */ + total_len = 0; + for (i=0 ; i < count ; i++) + total_len += (int) vecs[i].iov_len; + + DEBUG (MTD_DEBUG_LEVEL3, + "nand_writev: to = 0x%08x, len = %i\n", (unsigned int) to, + (unsigned int) total_len); + + /* Do not allow write past end of page */ + if ((to + total_len) > mtd->size) { + DEBUG (MTD_DEBUG_LEVEL0, + "nand_writev: Attempted write past end of device\n"); + return -EINVAL; + } + +retry: + /* Grab the lock and see if the device is available */ + spin_lock_bh (&this->chip_lock); + + switch (this->state) { + case FL_READY: + this->state = FL_WRITING; + spin_unlock_bh (&this->chip_lock); + break; + + default: + set_current_state (TASK_UNINTERRUPTIBLE); + add_wait_queue (&this->wq, &wait); + spin_unlock_bh (&this->chip_lock); + schedule(); + + remove_wait_queue (&this->wq, &wait); + goto retry; + }; + + /* Shift to get page */ + page = ((int) to) >> this->page_shift; + + /* Get the starting column */ + col = to & (mtd->oobblock - 1); + + /* Initialize return length value */ + *retlen = 0; + + /* Select the NAND device */ + nand_select (); + + /* Check the WP bit */ + nand_command (mtd, NAND_CMD_STATUS, -1, -1); + if (!(readb (this->IO_ADDR) & 0x80)) { + DEBUG (MTD_DEBUG_LEVEL0, + "nand_writev: Device is write protected!!!\n"); + nand_deselect (); + spin_lock_bh (&this->chip_lock); + this->state = FL_READY; + wake_up (&this->wq); + spin_unlock_bh (&this->chip_lock); + return -EIO; + } + + /* Loop until all iovecs' data has been written */ + cnt = col; + len = 0; + while (count) { + /* Do any need pre-fill for partial page programming */ + for (i=0 ; i < cnt ; i++) + this->data_buf[i] = 0xff; + + /* + * Read data out of each tuple until we have a full page + * to write or we've read all the tuples. + */ + while ((cnt < mtd->oobblock) && count) { + this->data_buf[cnt++] = + ((u_char *) vecs->iov_base)[len++]; + if (len >= (int) vecs->iov_len) { + vecs++; + len = 0; + count--; + } + } + + /* Do any need post-fill for partial page programming */ + for (i=cnt ; i < mtd->oobblock ; i++) + this->data_buf[i] = 0xff; + +#ifdef CONFIG_MTD_NAND_ECC + /* Zero out the ECC array */ + for (i=0 ; i < 6 ; i++) + this->ecc_code_buf[i] = 0x00; + + /* Calculate and write the first ECC */ + if (col >= mtd->eccsize) { + nand_command (mtd, NAND_CMD_READ0, col, page); + for (i=0 ; i < col ; i++) + this->data_buf[i] = readb (this->IO_ADDR); + nand_calculate_ecc (&this->data_buf[0], + &(this->ecc_code_buf[0])); + for (i=0 ; i<3 ; i++) + this->data_buf[(mtd->oobblock + i)] = + this->ecc_code_buf[i]; + } + + /* Calculate and write the second ECC */ + if ((mtd->oobblock == 512) && (cnt == mtd->oobblock)) { + nand_calculate_ecc (&this->data_buf[256], + &(this->ecc_code_buf[3])); + for (i=3 ; i<6 ; i++) + this->data_buf[(mtd->oobblock + i)] = + this->ecc_code_buf[i]; + } + + /* Write ones for partial page programming */ + for (i=ecc_bytes ; i < mtd->oobsize ; i++) + this->data_buf[(mtd->oobblock + i)] = 0xff; +#else + /* Write ones for partial page programming */ + for (i=mtd->oobblock ; i < (mtd->oobblock + mtd->oobsize) ; i++) + this->data_buf[i] = 0xff; +#endif + /* Send command to begin auto page programming */ + nand_command (mtd, NAND_CMD_SEQIN, 0x00, page); + + /* Write out complete page of data */ + for (i=0 ; i < (mtd->oobblock + mtd->oobsize) ; i++) + writeb (this->data_buf[i], this->IO_ADDR); + + /* Send command to actually program the data */ + nand_command (mtd, NAND_CMD_PAGEPROG, -1, -1); + + /* + * Wait for program operation to complete. This could + * take up to 3000us (3ms) on some devices, so we try + * and exit as quickly as possible. + */ + status = 0; + for (i=0 ; i<24 ; i++) { + /* Delay for 125us */ + udelay (125); + + /* Check the status */ + nand_command (mtd, NAND_CMD_STATUS, -1, -1); + status = (int) readb (this->IO_ADDR); + if (status & 0x40) + break; + } + + /* See if device thinks it succeeded */ + if (status & 0x01) { + DEBUG (MTD_DEBUG_LEVEL0, + "nand_writev: " \ + "Failed write, page 0x%08x, " \ + "%6i bytes were succesful\n", page, *retlen); + nand_deselect (); + spin_lock_bh (&this->chip_lock); + this->state = FL_READY; + wake_up (&this->wq); + spin_unlock_bh (&this->chip_lock); + return -EIO; + } + +#ifdef CONFIG_MTD_NAND_VERIFY_WRITE + /* + * The NAND device assumes that it is always writing to + * a cleanly erased page. Hence, it performs its internal + * write verification only on bits that transitioned from + * 1 to 0. The device does NOT verify the whole page on a + * byte by byte basis. It is possible that the page was + * not completely erased or the page is becoming unusable + * due to wear. The read with ECC would catch the error + * later when the ECC page check fails, but we would rather + * catch it early in the page write stage. Better to write + * no data than invalid data. + */ + + /* Send command to read back the page */ + if (col < mtd->eccsize) + nand_command (mtd, NAND_CMD_READ0, col, page); + else + nand_command (mtd, NAND_CMD_READ1, col - 256, page); + + /* Loop through and verify the data */ + for (i=col ; i < cnt ; i++) { + if (this->data_buf[i] != readb (this->IO_ADDR)) { + DEBUG (MTD_DEBUG_LEVEL0, + "nand_writev: " \ + "Failed write verify, page 0x%08x, " \ + "%6i bytes were succesful\n", + page, *retlen); + nand_deselect (); + spin_lock_bh (&this->chip_lock); + this->state = FL_READY; + wake_up (&this->wq); + spin_unlock_bh (&this->chip_lock); + return -EIO; + } + } + +#ifdef CONFIG_MTD_NAND_ECC + /* + * We also want to check that the ECC bytes wrote + * correctly for the same reasons stated above. + */ + nand_command (mtd, NAND_CMD_READOOB, 0x00, page); + for (i=0 ; i < ecc_bytes ; i++) { + if ((readb (this->IO_ADDR) != this->ecc_code_buf[i]) && + this->ecc_code_buf[i]) { + DEBUG (MTD_DEBUG_LEVEL0, + "nand_writev: Failed ECC write " \ + "verify, page 0x%08x, " \ + "%6i bytes were succesful\n", + page, i); + nand_deselect (); + spin_lock_bh (&this->chip_lock); + this->state = FL_READY; + wake_up (&this->wq); + spin_unlock_bh (&this->chip_lock); + return -EIO; + } + } +#endif + +#endif + /* Update written bytes count */ + *retlen += (cnt - col); + + /* Reset written byte counter and column */ + col = cnt = 0; + + /* Increment page address */ + page++; + } + + /* De-select the NAND device */ + nand_deselect (); + + /* Wake up anyone waiting on the device */ + spin_lock_bh (&this->chip_lock); + this->state = FL_READY; + wake_up (&this->wq); + spin_unlock_bh (&this->chip_lock); + + /* Return happy */ + return 0; +} + +/* + * NAND erase a block + */ +static int nand_erase (struct mtd_info *mtd, struct erase_info *instr) +{ + int i, page, len, status, pages_per_block; + struct nand_chip *this = mtd->priv; + DECLARE_WAITQUEUE(wait, current); + + DEBUG (MTD_DEBUG_LEVEL3, + "nand_erase: start = 0x%08x, len = %i\n", + (unsigned int) instr->addr, (unsigned int) instr->len); + + /* Start address must align on block boundary */ + if (instr->addr & (mtd->erasesize - 1)) { + DEBUG (MTD_DEBUG_LEVEL0, + "nand_erase: Unaligned address\n"); + return -EINVAL; + } + + /* Length must align on block boundary */ + if (instr->len & (mtd->erasesize - 1)) { + DEBUG (MTD_DEBUG_LEVEL0, + "nand_erase: Length not block aligned\n"); + return -EINVAL; + } + + /* Do not allow erase past end of device */ + if ((instr->len + instr->addr) > mtd->size) { + DEBUG (MTD_DEBUG_LEVEL0, + "nand_erase: Erase past end of device\n"); + return -EINVAL; + } + +retry: + /* Grab the lock and see if the device is available */ + spin_lock_bh (&this->chip_lock); + + switch (this->state) { + case FL_READY: + this->state = FL_ERASING; + break; + + default: + set_current_state (TASK_UNINTERRUPTIBLE); + add_wait_queue (&this->wq, &wait); + spin_unlock_bh (&this->chip_lock); + schedule(); + + remove_wait_queue (&this->wq, &wait); + goto retry; + }; + + /* Shift to get first page */ + page = (int) (instr->addr >> this->page_shift); + + /* Calculate pages in each block */ + pages_per_block = mtd->erasesize / mtd->oobblock; + + /* Select the NAND device */ + nand_select (); + + /* Check the WP bit */ + nand_command (mtd, NAND_CMD_STATUS, -1, -1); + if (!(readb (this->IO_ADDR) & 0x80)) { + DEBUG (MTD_DEBUG_LEVEL0, + "nand_erase: Device is write protected!!!\n"); + nand_deselect (); + this->state = FL_READY; + spin_unlock_bh (&this->chip_lock); + return -EIO; + } + + /* Loop through the pages */ + len = instr->len; + while (len) { + /* Send commands to erase a page */ + nand_command(mtd, NAND_CMD_ERASE1, -1, page); + nand_command(mtd, NAND_CMD_ERASE2, -1, -1); + + /* + * Wait for program operation to complete. This could + * take up to 4000us (4ms) on some devices, so we try + * and exit as quickly as possible. + */ + status = 0; + for (i=0 ; i<32 ; i++) { + /* Delay for 125us */ + udelay (125); + + /* Check the status */ + nand_command (mtd, NAND_CMD_STATUS, -1, -1); + status = (int) readb (this->IO_ADDR); + if (status & 0x40) + break; + } + + /* See if block erase succeeded */ + if (status & 0x01) { + DEBUG (MTD_DEBUG_LEVEL0, + "nand_erase: " \ + "Failed erase, page 0x%08x\n", page); + nand_deselect (); + this->state = FL_READY; + spin_unlock_bh (&this->chip_lock); + return -EIO; + } + + /* Increment page address and decrement length */ + len -= mtd->erasesize; + page += pages_per_block; + + /* Release the spin lock */ + spin_unlock_bh (&this->chip_lock); + +erase_retry: + /* Check the state and sleep if it changed */ + spin_lock_bh (&this->chip_lock); + if (this->state == FL_ERASING) { + continue; + } + else { + set_current_state (TASK_UNINTERRUPTIBLE); + add_wait_queue (&this->wq, &wait); + spin_unlock_bh (&this->chip_lock); + schedule(); + + remove_wait_queue (&this->wq, &wait); + goto erase_retry; + } + } + spin_unlock_bh (&this->chip_lock); + + /* De-select the NAND device */ + nand_deselect (); + + /* Do call back function */ + if (instr->callback) + instr->callback (instr); + + /* The device is ready */ + spin_lock_bh (&this->chip_lock); + this->state = FL_READY; + spin_unlock_bh (&this->chip_lock); + + /* Return happy */ + return 0; +} + +/* + * NAND sync + */ +static void nand_sync (struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + DECLARE_WAITQUEUE(wait, current); + + DEBUG (MTD_DEBUG_LEVEL3, "nand_sync: called\n"); + +retry: + /* Grab the spinlock */ + spin_lock_bh(&this->chip_lock); + + /* See what's going on */ + switch(this->state) { + case FL_READY: + case FL_SYNCING: + this->state = FL_SYNCING; + spin_unlock_bh (&this->chip_lock); + break; + + default: + /* Not an idle state */ + add_wait_queue (&this->wq, &wait); + spin_unlock_bh (&this->chip_lock); + schedule (); + + remove_wait_queue (&this->wq, &wait); + goto retry; + } + + /* Lock the device */ + spin_lock_bh (&this->chip_lock); + + /* Set the device to be ready again */ + if (this->state == FL_SYNCING) { + this->state = FL_READY; + wake_up (&this->wq); + } + + /* Unlock the device */ + spin_unlock_bh (&this->chip_lock); +} + +/* + * Scan for the NAND device + */ +int nand_scan (struct mtd_info *mtd) +{ + int i, nand_maf_id, nand_dev_id; + struct nand_chip *this = mtd->priv; + + /* Select the device */ + nand_select (); + + /* Send the command for reading device ID */ + nand_command (mtd, NAND_CMD_READID, 0x00, -1); + + /* Read manufacturer and device IDs */ + nand_maf_id = readb (this->IO_ADDR); + nand_dev_id = readb (this->IO_ADDR); + + /* Print and store flash device information */ + for (i = 0; nand_flash_ids[i].name != NULL; i++) { + if (nand_maf_id == nand_flash_ids[i].manufacture_id && + nand_dev_id == nand_flash_ids[i].model_id) { + if (!mtd->size) { + mtd->name = nand_flash_ids[i].name; + mtd->erasesize = nand_flash_ids[i].erasesize; + mtd->size = (1 << nand_flash_ids[i].chipshift); + mtd->eccsize = 256; + if (nand_flash_ids[i].page256) { + mtd->oobblock = 256; + mtd->oobsize = 8; + this->page_shift = 8; + } + else { + mtd->oobblock = 512; + mtd->oobsize = 16; + this->page_shift = 9; + } + } + printk (KERN_INFO "NAND device: Manufacture ID:" \ + " 0x%02x, Chip ID: 0x%02x (%s)\n", + nand_maf_id, nand_dev_id, mtd->name); + break; + } + } + + /* Initialize state and spinlock */ + this->state = FL_READY; + spin_lock_init(&this->chip_lock); + + /* De-select the device */ + nand_deselect (); + + /* Print warning message for no device */ + if (!mtd->size) { + printk (KERN_WARNING "No NAND device found!!!\n"); + return 1; + } + + /* Fill in remaining MTD driver data */ + mtd->type = MTD_NANDFLASH; + mtd->flags = MTD_CAP_NANDFLASH | MTD_ECC; + mtd->module = THIS_MODULE; + mtd->ecctype = MTD_ECC_SW; + mtd->erase = nand_erase; + mtd->point = NULL; + mtd->unpoint = NULL; + mtd->read = nand_read; + mtd->write = nand_write; + mtd->read_ecc = nand_read_ecc; + mtd->write_ecc = nand_write_ecc; + mtd->read_oob = nand_read_oob; + mtd->write_oob = nand_write_oob; + mtd->readv = NULL; + mtd->writev = nand_writev; + mtd->sync = nand_sync; + mtd->lock = NULL; + mtd->unlock = NULL; + mtd->suspend = NULL; + mtd->resume = NULL; + + /* Return happy */ + return 0; +} + +EXPORT_SYMBOL(nand_scan); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/nand/nand_ecc.c linux/drivers/mtd/nand/nand_ecc.c --- v2.4.5/linux/drivers/mtd/nand/nand_ecc.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/nand/nand_ecc.c Thu Jun 28 14:43:02 2001 @@ -0,0 +1,209 @@ +/* + * drivers/mtd/nand_ecc.c + * + * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com) + * Toshiba America Electronics Components, Inc. + * + * $Id: nand_ecc.c,v 1.6 2001/06/28 10:52:26 dwmw2 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 + * published by the Free Software Foundation. + * + * This file contains an ECC algorithm from Toshiba that detects and + * corrects 1 bit errors in a 256 byte block of data. + */ + +#include +#include +#include + +/* + * Pre-calculated 256-way 1 byte column parity + */ +static const u_char nand_ecc_precalc_table[] = { + 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00, + 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65, + 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66, + 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03, + 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69, + 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c, + 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f, + 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a, + 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a, + 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f, + 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c, + 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69, + 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03, + 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66, + 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65, + 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00 +}; + + +/* + * Creates non-inverted ECC code from line parity + */ +static void nand_trans_result(u_char reg2, u_char reg3, + u_char *ecc_code) +{ + u_char a, b, i, tmp1, tmp2; + + /* Initialize variables */ + a = b = 0x80; + tmp1 = tmp2 = 0; + + /* Calculate first ECC byte */ + for (i = 0; i < 4; i++) { + if (reg3 & a) /* LP15,13,11,9 --> ecc_code[0] */ + tmp1 |= b; + b >>= 1; + if (reg2 & a) /* LP14,12,10,8 --> ecc_code[0] */ + tmp1 |= b; + b >>= 1; + a >>= 1; + } + + /* Calculate second ECC byte */ + b = 0x80; + for (i = 0; i < 4; i++) { + if (reg3 & a) /* LP7,5,3,1 --> ecc_code[1] */ + tmp2 |= b; + b >>= 1; + if (reg2 & a) /* LP6,4,2,0 --> ecc_code[1] */ + tmp2 |= b; + b >>= 1; + a >>= 1; + } + + /* Store two of the ECC bytes */ + ecc_code[0] = tmp1; + ecc_code[1] = tmp2; +} + +/* + * Calculate 3 byte ECC code for 256 byte block + */ +void nand_calculate_ecc (const u_char *dat, u_char *ecc_code) +{ + u_char idx, reg1, reg2, reg3; + int j; + + /* Initialize variables */ + reg1 = reg2 = reg3 = 0; + ecc_code[0] = ecc_code[1] = ecc_code[2] = 0; + + /* Build up column parity */ + for(j = 0; j < 256; j++) { + + /* Get CP0 - CP5 from table */ + idx = nand_ecc_precalc_table[dat[j]]; + reg1 ^= (idx & 0x3f); + + /* All bit XOR = 1 ? */ + if (idx & 0x40) { + reg3 ^= (u_char) j; + reg2 ^= ~((u_char) j); + } + } + + /* Create non-inverted ECC code from line parity */ + nand_trans_result(reg2, reg3, ecc_code); + + /* Calculate final ECC code */ + ecc_code[0] = ~ecc_code[0]; + ecc_code[1] = ~ecc_code[1]; + ecc_code[2] = ((~reg1) << 2) | 0x03; +} + +/* + * Detect and correct a 1 bit error for 256 byte block + */ +int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc) +{ + u_char a, b, c, d1, d2, d3, add, bit, i; + + /* Do error detection */ + d1 = calc_ecc[0] ^ read_ecc[0]; + d2 = calc_ecc[1] ^ read_ecc[1]; + d3 = calc_ecc[2] ^ read_ecc[2]; + + if ((d1 | d2 | d3) == 0) { + /* No errors */ + return 0; + } + else { + a = (d1 ^ (d1 >> 1)) & 0x55; + b = (d2 ^ (d2 >> 1)) & 0x55; + c = (d3 ^ (d3 >> 1)) & 0x54; + + /* Found and will correct single bit error in the data */ + if ((a == 0x55) && (b == 0x55) && (c == 0x54)) { + c = 0x80; + add = 0; + a = 0x80; + for (i=0; i<4; i++) { + if (d1 & c) + add |= a; + c >>= 2; + a >>= 1; + } + c = 0x80; + for (i=0; i<4; i++) { + if (d2 & c) + add |= a; + c >>= 2; + a >>= 1; + } + bit = 0; + b = 0x04; + c = 0x80; + for (i=0; i<3; i++) { + if (d3 & c) + bit |= b; + c >>= 2; + b >>= 1; + } + b = 0x01; + a = dat[add]; + a ^= (b << bit); + dat[add] = a; + return 1; + } + else { + i = 0; + while (d1) { + if (d1 & 0x01) + ++i; + d1 >>= 1; + } + while (d2) { + if (d2 & 0x01) + ++i; + d2 >>= 1; + } + while (d3) { + if (d3 & 0x01) + ++i; + d3 >>= 1; + } + if (i == 1) { + /* ECC Code Error Correction */ + read_ecc[0] = calc_ecc[0]; + read_ecc[1] = calc_ecc[1]; + read_ecc[2] = calc_ecc[2]; + return 2; + } + else { + /* Uncorrectable Error */ + return -1; + } + } + } + + /* Should never happen */ + return -1; +} + +EXPORT_SYMBOL(nand_calculate_ecc); +EXPORT_SYMBOL(nand_correct_data); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/nand/spia.c linux/drivers/mtd/nand/spia.c --- v2.4.5/linux/drivers/mtd/nand/spia.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/nand/spia.c Tue Jul 3 12:15:40 2001 @@ -0,0 +1,160 @@ +/* + * drivers/mtd/spia.c + * + * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com) + * + * $Id: spia.c,v 1.11 2001/07/03 17:50:56 sjhill 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 + * published by the Free Software Foundation. + * + * Overview: + * This is a device driver for the NAND flash device found on the + * SPIA board which utilizes the Toshiba TC58V64AFT part. This is + * a 64Mibit (8MiB x 8 bits) NAND flash device. + */ + +#include +#include +#include +#include +#include +#include + +/* + * MTD structure for SPIA board + */ +static struct mtd_info *spia_mtd = NULL; + +/* + * Values specific to the SPIA board (used with EP7212 processor) + */ +#define SPIA_IO_ADDR = 0xd0000000 /* Start of EP7212 IO address space */ +#define SPIA_FIO_ADDR = 0xf0000000 /* Address where flash is mapped */ +#define SPIA_PEDR = 0x0080 /* + * IO offset to Port E data register + * where the CLE, ALE and NCE pins + * are wired to. + */ +#define SPIA_PEDDR = 0x00c0 /* + * IO offset to Port E data direction + * register so we can control the IO + * lines. + */ + +/* + * Module stuff + */ +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) + #define spia_init init_module + #define spia_cleanup cleanup_module +#endif + +static int spia_io_base = SPIA_IO_BASE; +static int spia_fio_base = SPIA_FIO_BASE; +static int spia_pedr = SPIA_PEDR; +static int spia_peddr = SPIA_PEDDR; + +MODULE_PARM(spia_io_base, "i"); +MODULE_PARM(spia_fio_base, "i"); +MODULE_PARM(spia_pedr, "i"); +MODULE_PARM(spia_peddr, "i"); + +__setup("spia_io_base=",spia_io_base); +__setup("spia_fio_base=",spia_fio_base); +__setup("spia_pedr=",spia_pedr); +__setup("spia_peddr=",spia_peddr); + +/* + * Define partitions for flash device + */ +const static struct mtd_partition partition_info[] = { + { name: "SPIA flash partition 1", + offset: 0, + size: 2*1024*1024 }, + { name: "SPIA flash partition 2", + offset: 2*1024*1024, + size: 6*1024*1024 } +}; +#define NUM_PARTITIONS 2 + +/* + * Main initialization routine + */ +int __init spia_init (void) +{ + struct nand_chip *this; + + /* Allocate memory for MTD device structure and private data */ + spia_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), + GFP_KERNEL); + if (!spia_mtd) { + printk ("Unable to allocate SPIA NAND MTD device structure.\n"); + return -ENOMEM; + } + + /* Get pointer to private data */ + this = (struct nand_chip *) (&spia_mtd[1]); + + /* Initialize structures */ + memset((char *) spia_mtd, 0, sizeof(struct mtd_info)); + memset((char *) this, 0, sizeof(struct nand_chip)); + + /* Link the private data with the MTD structure */ + spia_mtd->priv = this; + + /* + * Set GPIO Port E control register so that the pins are configured + * to be outputs for controlling the NAND flash. + */ + (*(volatile unsigned char *) (spia_io_base + spia_peddr)) = 0x07; + + /* Set address of NAND IO lines */ + this->IO_ADDR = spia_fio_base; + this->CTRL_ADDR = spia_io_base + spia_pedr; + this->CLE = 0x01; + this->ALE = 0x02; + this->NCE = 0x04; + + /* Scan to find existance of the device */ + if (nand_scan (spia_mtd)) { + kfree (spia_mtd); + return -ENXIO; + } + + /* Allocate memory for internal data buffer */ + this->data_buf = kmalloc (sizeof(u_char) * (spia_mtd->oobblock + spia_mtd->oobsize), GFP_KERNEL); + if (!this->data_buf) { + printk ("Unable to allocate NAND data buffer for SPIA.\n"); + kfree (spia_mtd); + return -ENOMEM; + } + + /* Register the partitions */ + add_mtd_partitions(spia_mtd, partition_info, NUM_PARTITIONS); + + /* Return happy */ + return 0; +} +module_init(spia_init); + +/* + * Clean up routine + */ +#ifdef MODULE +static void __exit spia_cleanup (void) +{ + struct nand_chip *this = (struct nand_chip *) &spia_mtd[1]; + + /* Unregister the device */ + del_mtd_device (spia_mtd); + + /* Free internal data buffer */ + kfree (this->data_buf); + + /* Free the MTD device structure */ + kfree (spia_mtd); +} +module_exit(spia_cleanup); +#endif diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/nftl.c linux/drivers/mtd/nftl.c --- v2.4.5/linux/drivers/mtd/nftl.c Sat Apr 28 11:27:54 2001 +++ linux/drivers/mtd/nftl.c Wed Dec 31 16:00:00 1969 @@ -1,1108 +0,0 @@ -/* Linux driver for NAND Flash Translation Layer */ -/* (c) 1999 Machine Vision Holdings, Inc. */ -/* Author: David Woodhouse */ -/* $Id: nftl.c,v 1.57 2000/12/01 17:51:54 dwmw2 Exp $ */ - -/* - The contents of this file are distributed under the GNU General - Public License version 2 ("GPL"). The author places no additional - restrictions of any kind on it. However, local legislation in some - countries may restrict the use of the algorithms implemented by this - code in certain circumstances. - - The legal note below refers only to the _use_ of the code in the - affected jurisdictions, and does not in any way affect the copying, - distribution and modification of this code, which are permitted, and - indeed required, under the terms of the GPL. - - Section 0 of the GPL says: - "Activities other than copying, distribution and modification are not - covered by this License; they are outside its scope." - - You may copy, distribute and modify this code to your hearts' - content - it's just that in some jurisdictions, you may only _use_ - it under the terms of the patent grant below. This puts it in a - similar situation to the ISDN code, which you may need telco - approval to use, and indeed any code which has uses that may be - restricted in law. For example, certain malicious uses of the - networking stack may be illegal, but that doesn't prevent the - networking code from being under GPL. - - In fact the ISDN case is worse than this, because modification of - the code automatically invalidates its approval. Modification, - unlike usage, _is_ one of the rights which is protected by the - GPL. Happily, the law in those places where approval is required - doesn't actually prevent you from modifying the code - it's just - that you may not be allowed to _use_ it once you've done so - and - because usage isn't addressed by the GPL, that's just fine. - - dwmw2@infradead.org - 30/10/0 - - LEGAL NOTE: The NFTL format is patented by M-Systems. They have - granted a licence for its use with their DiskOnChip products: - - "M-Systems grants a royalty-free, non-exclusive license under - any presently existing M-Systems intellectual property rights - necessary for the design and development of NFTL-compatible - drivers, file systems and utilities to use the data formats with, - and solely to support, M-Systems' DiskOnChip products" - - A signed copy of this agreement from M-Systems is kept on file by - Red Hat UK Limited. In the unlikely event that you need access to it, - please contact dwmw2@redhat.com for assistance. */ - -#define PRERELEASE - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_KMOD -#include -#endif -#include -#include -#include - -/* maximum number of loops while examining next block, to have a - chance to detect consistency problems (they should never happen - because of the checks done in the mounting */ - -#define MAX_LOOPS 10000 - -/* NFTL block device stuff */ -#define MAJOR_NR NFTL_MAJOR -#define DEVICE_REQUEST nftl_request -#define DEVICE_OFF(device) - - -#include -#include - -/* Linux-specific block device functions */ - -/* I _HATE_ the Linux block device setup more than anything else I've ever - * encountered, except ... - */ - -static int nftl_sizes[256] = {0,}; -static int nftl_blocksizes[256] = {0,}; - -/* .. for the Linux partition table handling. */ -struct hd_struct part_table[256] = {{0,0},}; - -#if LINUX_VERSION_CODE < 0x20328 -static void dummy_init (struct gendisk *crap) -{} -#endif - -static struct gendisk nftl_gendisk = { - MAJOR_NR, /* Major number */ - "nftl", /* Major name */ - 4, /* Bits to shift to get real from partition */ - 15, /* Number of partitions per real */ -#if LINUX_VERSION_CODE < 0x20328 - MAX_NFTLS, /* maximum number of real */ - dummy_init, /* init function */ -#endif - part_table, /* hd struct */ - nftl_sizes, /* block sizes */ - 0, /* number */ - NULL, /* internal use, not presently used */ - NULL /* next */ -}; - -struct NFTLrecord *NFTLs[MAX_NFTLS] = {NULL}; - -static void NFTL_setup(struct mtd_info *mtd) -{ - int i; - struct NFTLrecord *nftl; - unsigned long temp; - int firstfree = -1; - - DEBUG(MTD_DEBUG_LEVEL1,"NFTL_setup\n"); - - for (i = 0; i < MAX_NFTLS; i++) { - if (!NFTLs[i] && firstfree == -1) - firstfree = i; - else if (NFTLs[i] && NFTLs[i]->mtd == mtd) { - /* This is a Spare Media Header for an NFTL we've already found */ - DEBUG(MTD_DEBUG_LEVEL1, "MTD already mounted as NFTL\n"); - return; - } - } - if (firstfree == -1) { - printk(KERN_WARNING "No more NFTL slot available\n"); - return; - } - - nftl = kmalloc(sizeof(struct NFTLrecord), GFP_KERNEL); - if (!nftl) { - printk(KERN_WARNING "Out of memory for NFTL data structures\n"); - return; - } - - init_MUTEX(&nftl->mutex); - - /* get physical parameters */ - nftl->EraseSize = mtd->erasesize; - nftl->nb_blocks = mtd->size / mtd->erasesize; - nftl->mtd = mtd; - - if (NFTL_mount(nftl) < 0) { - printk(KERN_WARNING "Could not mount NFTL device\n"); - kfree(nftl); - return; - } - - /* OK, it's a new one. Set up all the data structures. */ -#ifdef PSYCHO_DEBUG - printk("Found new NFTL nftl%c\n", firstfree + 'a'); -#endif - - /* linux stuff */ - nftl->usecount = 0; - nftl->cylinders = 1024; - nftl->heads = 16; - - temp = nftl->cylinders * nftl->heads; - nftl->sectors = nftl->nr_sects / temp; - if (nftl->nr_sects % temp) { - nftl->sectors++; - temp = nftl->cylinders * nftl->sectors; - nftl->heads = nftl->nr_sects / temp; - - if (nftl->nr_sects % temp) { - nftl->heads++; - temp = nftl->heads * nftl->sectors; - nftl->cylinders = nftl->nr_sects / temp; - } - } - - if (nftl->nr_sects != nftl->heads * nftl->cylinders * nftl->sectors) { - printk(KERN_WARNING "Cannot calculate an NFTL geometry to " - "match size of 0x%lx.\n", nftl->nr_sects); - printk(KERN_WARNING "Using C:%d H:%d S:%d (== 0x%lx sects)\n", - nftl->cylinders, nftl->heads , nftl->sectors, - (long)nftl->cylinders * (long)nftl->heads * (long)nftl->sectors ); - - /* Oh no we don't have nftl->nr_sects = nftl->heads * nftl->cylinders * nftl->sectors; */ - } - NFTLs[firstfree] = nftl; - /* Finally, set up the block device sizes */ - nftl_sizes[firstfree * 16] = nftl->nr_sects; - //nftl_blocksizes[firstfree*16] = 512; - part_table[firstfree * 16].nr_sects = nftl->nr_sects; - - /* partition check ... */ -#if LINUX_VERSION_CODE < 0x20328 - resetup_one_dev(&nftl_gendisk, firstfree); -#else - grok_partitions(&nftl_gendisk, firstfree, 1<<4, nftl->nr_sects); -#endif -} - -static void NFTL_unsetup(int i) -{ - struct NFTLrecord *nftl = NFTLs[i]; - - DEBUG(MTD_DEBUG_LEVEL1, "NFTL_unsetup %d\n", i); - - NFTLs[i] = NULL; - - if (nftl->ReplUnitTable) - kfree(nftl->ReplUnitTable); - if (nftl->EUNtable) - kfree(nftl->EUNtable); - - kfree(nftl); -} - -/* Search the MTD device for NFTL partitions */ -static void NFTL_notify_add(struct mtd_info *mtd) -{ - DEBUG(MTD_DEBUG_LEVEL1, "NFTL_notify_add for %s\n", mtd->name); - - if (mtd) { - if (!mtd->read_oob) { - /* If this MTD doesn't have out-of-band data, - then there's no point continuing */ - DEBUG(MTD_DEBUG_LEVEL1, "No OOB data, quitting\n"); - return; - } - DEBUG(MTD_DEBUG_LEVEL3, "mtd->read = %p, size = %d, erasesize = %d\n", - mtd->read, mtd->size, mtd->erasesize); - - NFTL_setup(mtd); - } -} - -static void NFTL_notify_remove(struct mtd_info *mtd) -{ - int i; - - for (i = 0; i < MAX_NFTLS; i++) { - if (NFTLs[i] && NFTLs[i]->mtd == mtd) - NFTL_unsetup(i); - } -} - -#ifdef CONFIG_NFTL_RW - -/* Actual NFTL access routines */ -/* NFTL_findfreeblock: Find a free Erase Unit on the NFTL partition. This function is used - * when the give Virtual Unit Chain - */ -static u16 NFTL_findfreeblock(struct NFTLrecord *nftl, int desperate ) -{ - /* For a given Virtual Unit Chain: find or create a free block and - add it to the chain */ - /* We're passed the number of the last EUN in the chain, to save us from - having to look it up again */ - u16 pot = nftl->LastFreeEUN; - int silly = -1; - - /* Normally, we force a fold to happen before we run out of free blocks completely */ - if (!desperate && nftl->numfreeEUNs < 2) { - DEBUG(MTD_DEBUG_LEVEL1, "NFTL_findfreeblock: there are too few free EUNs\n"); - return 0xffff; - } - - /* Scan for a free block */ - do { - if (nftl->ReplUnitTable[pot] == BLOCK_FREE) { - nftl->LastFreeEUN = pot; - nftl->numfreeEUNs--; - return pot; - } - - /* This will probably point to the MediaHdr unit itself, - right at the beginning of the partition. But that unit - (and the backup unit too) should have the UCI set - up so that it's not selected for overwriting */ - if (++pot > nftl->lastEUN) - pot = le16_to_cpu(nftl->MediaHdr.FirstPhysicalEUN); - - if (!silly--) { - printk("Argh! No free blocks found! LastFreeEUN = %d, " - "FirstEUN = %d\n", nftl->LastFreeEUN, - le16_to_cpu(nftl->MediaHdr.FirstPhysicalEUN)); - return 0xffff; - } - } while (pot != nftl->LastFreeEUN); - - return 0xffff; -} - -static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned pendingblock ) -{ - u16 BlockMap[MAX_SECTORS_PER_UNIT]; - unsigned char BlockLastState[MAX_SECTORS_PER_UNIT]; - unsigned char BlockFreeFound[MAX_SECTORS_PER_UNIT]; - unsigned int thisEUN; - int block; - int silly; - unsigned int targetEUN; - struct nftl_oob oob; - int inplace = 1; - size_t retlen; - - memset(BlockMap, 0xff, sizeof(BlockMap)); - memset(BlockFreeFound, 0, sizeof(BlockFreeFound)); - - thisEUN = nftl->EUNtable[thisVUC]; - - if (thisEUN == BLOCK_NIL) { - printk(KERN_WARNING "Trying to fold non-existent " - "Virtual Unit Chain %d!\n", thisVUC); - return BLOCK_NIL; - } - - /* Scan to find the Erase Unit which holds the actual data for each - 512-byte block within the Chain. - */ - silly = MAX_LOOPS; - targetEUN = BLOCK_NIL; - while (thisEUN <= nftl->lastEUN ) { - unsigned int status, foldmark; - - targetEUN = thisEUN; - for (block = 0; block < nftl->EraseSize / 512; block ++) { - MTD_READOOB(nftl->mtd, - (thisEUN * nftl->EraseSize) + (block * 512), - 16 , &retlen, (char *)&oob); - if (block == 2) { - foldmark = oob.u.c.FoldMark | oob.u.c.FoldMark1; - if (foldmark == FOLD_MARK_IN_PROGRESS) { - DEBUG(MTD_DEBUG_LEVEL1, - "Write Inhibited on EUN %d\n", thisEUN); - inplace = 0; - } else { - /* There's no other reason not to do inplace, - except ones that come later. So we don't need - to preserve inplace */ - inplace = 1; - } - } - status = oob.b.Status | oob.b.Status1; - BlockLastState[block] = status; - - switch(status) { - case SECTOR_FREE: - BlockFreeFound[block] = 1; - break; - - case SECTOR_USED: - if (!BlockFreeFound[block]) - BlockMap[block] = thisEUN; - else - printk(KERN_WARNING - "SECTOR_USED found after SECTOR_FREE " - "in Virtual Unit Chain %d for block %d\n", - thisVUC, block); - break; - case SECTOR_IGNORE: - case SECTOR_DELETED: - break; - default: - printk("Unknown status for block %d in EUN %d: %x\n", - block, thisEUN, status); - } - } - - if (!silly--) { - printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%x\n", - thisVUC); - return BLOCK_NIL; - } - - thisEUN = nftl->ReplUnitTable[thisEUN]; - } - - if (inplace) { - /* We're being asked to be a fold-in-place. Check - that all blocks are either present or SECTOR_FREE - in the target block. If not, we're going to have - to fold out-of-place anyway. - */ - for (block = 0; block < nftl->EraseSize / 512 ; block++) { - if (BlockLastState[block] != SECTOR_FREE && - BlockMap[block] != targetEUN) { - DEBUG(MTD_DEBUG_LEVEL1, "Setting inplace to 0. VUC %d, " - "block %d was %x lastEUN, " - "and is in EUN %d (%s) %d\n", - thisVUC, block, BlockLastState[block], - BlockMap[block], - BlockMap[block]== targetEUN ? "==" : "!=", - targetEUN); - inplace = 0; - break; - } - } - - if (pendingblock >= (thisVUC * (nftl->EraseSize / 512)) && - pendingblock < ((thisVUC + 1)* (nftl->EraseSize / 512)) && - BlockLastState[pendingblock - (thisVUC * (nftl->EraseSize / 512))] != - SECTOR_FREE) { - DEBUG(MTD_DEBUG_LEVEL1, "Pending write not free in EUN %d. " - "Folding out of place.\n", targetEUN); - inplace = 0; - } - } - - if (!inplace) { - DEBUG(MTD_DEBUG_LEVEL1, "Cannot fold Virtual Unit Chain %d in place. " - "Trying out-of-place\n", thisVUC); - /* We need to find a targetEUN to fold into. */ - targetEUN = NFTL_findfreeblock(nftl, 1); - if (targetEUN == BLOCK_NIL) { - /* Ouch. Now we're screwed. We need to do a - fold-in-place of another chain to make room - for this one. We need a better way of selecting - which chain to fold, because makefreeblock will - only ask us to fold the same one again. - */ - printk(KERN_WARNING - "NFTL_findfreeblock(desperate) returns 0xffff.\n"); - return BLOCK_NIL; - } - } else { - /* We put a fold mark in the chain we are folding only if - we fold in place to help the mount check code. If we do - not fold in place, it is possible to find the valid - chain by selecting the longer one */ - oob.u.c.FoldMark = oob.u.c.FoldMark1 = cpu_to_le16(FOLD_MARK_IN_PROGRESS); - oob.u.c.unused = 0xffffffff; - MTD_WRITEOOB(nftl->mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8, - 8, &retlen, (char *)&oob.u); - } - - /* OK. We now know the location of every block in the Virtual Unit Chain, - and the Erase Unit into which we are supposed to be copying. - Go for it. - */ - DEBUG(MTD_DEBUG_LEVEL1,"Folding chain %d into unit %d\n", thisVUC, targetEUN); - for (block = 0; block < nftl->EraseSize / 512 ; block++) { - unsigned char movebuf[512]; - int ret; - - /* If it's in the target EUN already, or if it's pending write, do nothing */ - if (BlockMap[block] == targetEUN || - (pendingblock == (thisVUC * (nftl->EraseSize / 512) + block))) { - continue; - } - - /* copy only in non free block (free blocks can only - happen in case of media errors or deleted blocks) */ - if (BlockMap[block] == BLOCK_NIL) - continue; - - ret = MTD_READECC(nftl->mtd, (nftl->EraseSize * BlockMap[block]) - + (block * 512), 512, &retlen, movebuf, (char *)&oob); - if (ret < 0) { - ret = MTD_READECC(nftl->mtd, (nftl->EraseSize * BlockMap[block]) - + (block * 512), 512, &retlen, - movebuf, (char *)&oob); - if (ret != -EIO) - printk("Error went away on retry.\n"); - } - MTD_WRITEECC(nftl->mtd, (nftl->EraseSize * targetEUN) + (block * 512), - 512, &retlen, movebuf, (char *)&oob); - } - - /* add the header so that it is now a valid chain */ - oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum - = cpu_to_le16(thisVUC); - oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff; - - MTD_WRITEOOB(nftl->mtd, (nftl->EraseSize * targetEUN) + 8, - 8, &retlen, (char *)&oob.u); - - /* OK. We've moved the whole lot into the new block. Now we have to free the original blocks. */ - - /* At this point, we have two different chains for this Virtual Unit, and no way to tell - them apart. If we crash now, we get confused. However, both contain the same data, so we - shouldn't actually lose data in this case. It's just that when we load up on a medium which - has duplicate chains, we need to free one of the chains because it's not necessary any more. - */ - thisEUN = nftl->EUNtable[thisVUC]; - DEBUG(MTD_DEBUG_LEVEL1,"Want to erase\n"); - - /* For each block in the old chain (except the targetEUN of course), - free it and make it available for future use */ - while (thisEUN <= nftl->lastEUN && thisEUN != targetEUN) { - unsigned int EUNtmp; - - EUNtmp = nftl->ReplUnitTable[thisEUN]; - - if (NFTL_formatblock(nftl, thisEUN) < 0) { - /* could not erase : mark block as reserved - * FixMe: Update Bad Unit Table on disk - */ - nftl->ReplUnitTable[thisEUN] = BLOCK_RESERVED; - } else { - /* correctly erased : mark it as free */ - nftl->ReplUnitTable[thisEUN] = BLOCK_FREE; - nftl->numfreeEUNs++; - } - thisEUN = EUNtmp; - } - - /* Make this the new start of chain for thisVUC */ - nftl->ReplUnitTable[targetEUN] = BLOCK_NIL; - nftl->EUNtable[thisVUC] = targetEUN; - - return targetEUN; -} - -u16 NFTL_makefreeblock( struct NFTLrecord *nftl , unsigned pendingblock) -{ - /* This is the part that needs some cleverness applied. - For now, I'm doing the minimum applicable to actually - get the thing to work. - Wear-levelling and other clever stuff needs to be implemented - and we also need to do some assessment of the results when - the system loses power half-way through the routine. - */ - u16 LongestChain = 0; - u16 ChainLength = 0, thislen; - u16 chain, EUN; - - for (chain = 0; chain < nftl->MediaHdr.FormattedSize / nftl->EraseSize; chain++) { - EUN = nftl->EUNtable[chain]; - thislen = 0; - - while (EUN <= nftl->lastEUN) { - thislen++; - //printk("VUC %d reaches len %d with EUN %d\n", chain, thislen, EUN); - EUN = nftl->ReplUnitTable[EUN] & 0x7fff; - if (thislen > 0xff00) { - printk("Endless loop in Virtual Chain %d: Unit %x\n", - chain, EUN); - } - if (thislen > 0xff10) { - /* Actually, don't return failure. Just ignore this chain and - get on with it. */ - thislen = 0; - break; - } - } - - if (thislen > ChainLength) { - //printk("New longest chain is %d with length %d\n", chain, thislen); - ChainLength = thislen; - LongestChain = chain; - } - } - - if (ChainLength < 2) { - printk(KERN_WARNING "No Virtual Unit Chains available for folding. " - "Failing request\n"); - return 0xffff; - } - - return NFTL_foldchain (nftl, LongestChain, pendingblock); -} - -/* NFTL_findwriteunit: Return the unit number into which we can write - for this block. Make it available if it isn't already -*/ -static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) -{ - u16 lastEUN; - u16 thisVUC = block / (nftl->EraseSize / 512); - unsigned int writeEUN; - unsigned long blockofs = (block * 512) & (nftl->EraseSize -1); - size_t retlen; - int silly, silly2 = 3; - struct nftl_oob oob; - - do { - /* Scan the media to find a unit in the VUC which has - a free space for the block in question. - */ - - /* This condition catches the 0x[7f]fff cases, as well as - being a sanity check for past-end-of-media access - */ - lastEUN = BLOCK_NIL; - writeEUN = nftl->EUNtable[thisVUC]; - silly = MAX_LOOPS; - while (writeEUN <= nftl->lastEUN) { - struct nftl_bci bci; - size_t retlen; - unsigned int status; - - lastEUN = writeEUN; - - MTD_READOOB(nftl->mtd, (writeEUN * nftl->EraseSize) + blockofs, - 8, &retlen, (char *)&bci); - - DEBUG(MTD_DEBUG_LEVEL2, "Status of block %d in EUN %d is %x\n", - block , writeEUN, le16_to_cpu(bci.Status)); - - status = bci.Status | bci.Status1; - switch(status) { - case SECTOR_FREE: - return writeEUN; - - case SECTOR_DELETED: - case SECTOR_USED: - case SECTOR_IGNORE: - break; - default: - // Invalid block. Don't use it any more. Must implement. - break; - } - - if (!silly--) { - printk(KERN_WARNING - "Infinite loop in Virtual Unit Chain 0x%x\n", - thisVUC); - return 0xffff; - } - - /* Skip to next block in chain */ - writeEUN = nftl->ReplUnitTable[writeEUN]; - } - - /* OK. We didn't find one in the existing chain, or there - is no existing chain. */ - - /* Try to find an already-free block */ - writeEUN = NFTL_findfreeblock(nftl, 0); - - if (writeEUN == BLOCK_NIL) { - /* That didn't work - there were no free blocks just - waiting to be picked up. We're going to have to fold - a chain to make room. - */ - - /* First remember the start of this chain */ - //u16 startEUN = nftl->EUNtable[thisVUC]; - - //printk("Write to VirtualUnitChain %d, calling makefreeblock()\n", thisVUC); - writeEUN = NFTL_makefreeblock(nftl, 0xffff); - - if (writeEUN == BLOCK_NIL) { - /* Ouch. This should never happen - we should - always be able to make some room somehow. - If we get here, we've allocated more storage - space than actual media, or our makefreeblock - routine is missing something. - */ - printk(KERN_WARNING "Cannot make free space.\n"); - return BLOCK_NIL; - } - //printk("Restarting scan\n"); - lastEUN = BLOCK_NIL; - continue; - } - - /* We've found a free block. Insert it into the chain. */ - - if (lastEUN != BLOCK_NIL) { - thisVUC |= 0x8000; /* It's a replacement block */ - } else { - /* The first block in a new chain */ - nftl->EUNtable[thisVUC] = writeEUN; - } - - /* set up the actual EUN we're writing into */ - /* Both in our cache... */ - nftl->ReplUnitTable[writeEUN] = BLOCK_NIL; - - /* ... and on the flash itself */ - MTD_READOOB(nftl->mtd, writeEUN * nftl->EraseSize + 8, 8, - &retlen, (char *)&oob.u); - - oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC); - - MTD_WRITEOOB(nftl->mtd, writeEUN * nftl->EraseSize + 8, 8, - &retlen, (char *)&oob.u); - - /* we link the new block to the chain only after the - block is ready. It avoids the case where the chain - could point to a free block */ - if (lastEUN != BLOCK_NIL) { - /* Both in our cache... */ - nftl->ReplUnitTable[lastEUN] = writeEUN; - /* ... and on the flash itself */ - MTD_READOOB(nftl->mtd, (lastEUN * nftl->EraseSize) + 8, - 8, &retlen, (char *)&oob.u); - - oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum - = cpu_to_le16(writeEUN); - - MTD_WRITEOOB(nftl->mtd, (lastEUN * nftl->EraseSize) + 8, - 8, &retlen, (char *)&oob.u); - } - - return writeEUN; - - } while (silly2--); - - printk(KERN_WARNING "Error folding to make room for Virtual Unit Chain 0x%x\n", - thisVUC); - return 0xffff; -} - -static int NFTL_writeblock(struct NFTLrecord *nftl, unsigned block, char *buffer) -{ - u16 writeEUN; - unsigned long blockofs = (block * 512) & (nftl->EraseSize - 1); - size_t retlen; - u8 eccbuf[6]; - - writeEUN = NFTL_findwriteunit(nftl, block); - - if (writeEUN == BLOCK_NIL) { - printk(KERN_WARNING - "NFTL_writeblock(): Cannot find block to write to\n"); - /* If we _still_ haven't got a block to use, we're screwed */ - return 1; - } - - MTD_WRITEECC(nftl->mtd, (writeEUN * nftl->EraseSize) + blockofs, - 512, &retlen, (char *)buffer, (char *)eccbuf); - /* no need to write SECTOR_USED flags since they are written in mtd_writeecc */ - - return 0; -} -#endif /* CONFIG_NFTL_RW */ - -static int NFTL_readblock(struct NFTLrecord *nftl, unsigned block, char *buffer) -{ - u16 lastgoodEUN; - u16 thisEUN = nftl->EUNtable[block / (nftl->EraseSize / 512)]; - unsigned long blockofs = (block * 512) & (nftl->EraseSize - 1); - unsigned int status; - int silly = MAX_LOOPS; - size_t retlen; - struct nftl_bci bci; - - lastgoodEUN = BLOCK_NIL; - - if (thisEUN != BLOCK_NIL) { - while (thisEUN < nftl->nb_blocks) { - if (MTD_READOOB(nftl->mtd, (thisEUN * nftl->EraseSize) + blockofs, - 8, &retlen, (char *)&bci) < 0) - status = SECTOR_IGNORE; - else - status = bci.Status | bci.Status1; - - switch (status) { - case SECTOR_FREE: - /* no modification of a sector should follow a free sector */ - goto the_end; - case SECTOR_DELETED: - lastgoodEUN = BLOCK_NIL; - break; - case SECTOR_USED: - lastgoodEUN = thisEUN; - break; - case SECTOR_IGNORE: - break; - default: - printk("Unknown status for block %d in EUN %d: %x\n", - block, thisEUN, status); - break; - } - - if (!silly--) { - printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%x\n", - block / (nftl->EraseSize / 512)); - return 1; - } - thisEUN = nftl->ReplUnitTable[thisEUN]; - } - } - - the_end: - if (lastgoodEUN == BLOCK_NIL) { - /* the requested block is not on the media, return all 0x00 */ - memset(buffer, 0, 512); - } else { - loff_t ptr = (lastgoodEUN * nftl->EraseSize) + blockofs; - size_t retlen; - u_char eccbuf[6]; - if (MTD_READECC(nftl->mtd, ptr, 512, &retlen, buffer, eccbuf)) - return -EIO; - } - return 0; -} - -static int nftl_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) -{ - struct NFTLrecord *nftl; - - nftl = NFTLs[MINOR(inode->i_rdev) / 16]; - - if (!nftl) return -EINVAL; - - switch (cmd) { - case HDIO_GETGEO: { - struct hd_geometry g; - - g.heads = nftl->heads; - g.sectors = nftl->sectors; - g.cylinders = nftl->cylinders; - g.start = part_table[MINOR(inode->i_rdev)].start_sect; - return copy_to_user((void *)arg, &g, sizeof g) ? -EFAULT : 0; - } - case BLKGETSIZE: /* Return device size */ - if (!arg) return -EINVAL; - return put_user(part_table[MINOR(inode->i_rdev)].nr_sects, - (long *) arg); - - case BLKFLSBUF: - if (!capable(CAP_SYS_ADMIN)) return -EACCES; - fsync_dev(inode->i_rdev); - invalidate_buffers(inode->i_rdev); - if (nftl->mtd->sync) - nftl->mtd->sync(nftl->mtd); - return 0; - - case BLKRRPART: - if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (nftl->usecount > 1) return -EBUSY; -#if LINUX_VERSION_CODE < 0x20328 - resetup_one_dev(&nftl_gendisk, MINOR(inode->i_rdev) / 16); -#else - grok_partitions(&nftl_gendisk, MINOR(inode->i_rdev) / 16, - 1<<4, nftl->nr_sects); -#endif - return 0; - -#if (LINUX_VERSION_CODE < 0x20303) - RO_IOCTLS(inode->i_rdev, arg); /* ref. linux/blk.h */ -#else - case BLKROSET: - case BLKROGET: - case BLKSSZGET: - return blk_ioctl(inode->i_rdev, cmd, arg); -#endif - - default: - return -EINVAL; - } -} - -void nftl_request(RQFUNC_ARG) -{ - unsigned int dev, block, nsect; - struct NFTLrecord *nftl; - char *buffer; - struct request *req; - int res; - - while (1) { - INIT_REQUEST; /* blk.h */ - req = CURRENT; - - /* We can do this because the generic code knows not to - touch the request at the head of the queue */ - spin_unlock_irq(&io_request_lock); - - DEBUG(MTD_DEBUG_LEVEL2, "NFTL_request\n"); - DEBUG(MTD_DEBUG_LEVEL3, "NFTL %s request, from sector 0x%04lx for 0x%04lx sectors\n", - (req->cmd == READ) ? "Read " : "Write", - req->sector, req->current_nr_sectors); - - dev = MINOR(req->rq_dev); - block = req->sector; - nsect = req->current_nr_sectors; - buffer = req->buffer; - res = 1; /* succeed */ - - if (dev >= MAX_NFTLS * 16) { - /* there is no such partition */ - printk("nftl: bad minor number: device = %s\n", - kdevname(req->rq_dev)); - res = 0; /* fail */ - goto repeat; - } - - nftl = NFTLs[dev / 16]; - DEBUG(MTD_DEBUG_LEVEL3, "Waiting for mutex\n"); - down(&nftl->mutex); - DEBUG(MTD_DEBUG_LEVEL3, "Got mutex\n"); - - if (block + nsect > part_table[dev].nr_sects) { - /* access past the end of device */ - printk("nftl%c%d: bad access: block = %d, count = %d\n", - (MINOR(req->rq_dev)>>6)+'a', dev & 0xf, block, nsect); - up(&nftl->mutex); - res = 0; /* fail */ - goto repeat; - } - - block += part_table[dev].start_sect; - - if (req->cmd == READ) { - DEBUG(MTD_DEBUG_LEVEL2, "NFTL read request of 0x%x sectors @ %x " - "(req->nr_sectors == %lx)\n", nsect, block, req->nr_sectors); - - for ( ; nsect > 0; nsect-- , block++, buffer += 512) { - /* Read a single sector to req->buffer + (512 * i) */ - if (NFTL_readblock(nftl, block, buffer)) { - DEBUG(MTD_DEBUG_LEVEL2, "NFTL read request failed\n"); - up(&nftl->mutex); - res = 0; - goto repeat; - } - } - - DEBUG(MTD_DEBUG_LEVEL2,"NFTL read request completed OK\n"); - up(&nftl->mutex); - goto repeat; - } else if (req->cmd == WRITE) { - DEBUG(MTD_DEBUG_LEVEL2, "NFTL write request of 0x%x sectors @ %x " - "(req->nr_sectors == %lx)\n", nsect, block, - req->nr_sectors); -#ifdef CONFIG_NFTL_RW - for ( ; nsect > 0; nsect-- , block++, buffer += 512) { - /* Read a single sector to req->buffer + (512 * i) */ - if (NFTL_writeblock(nftl, block, buffer)) { - DEBUG(MTD_DEBUG_LEVEL1,"NFTL write request failed\n"); - up(&nftl->mutex); - res = 0; - goto repeat; - } - } - DEBUG(MTD_DEBUG_LEVEL2,"NFTL write request completed OK\n"); -#else - res = 0; /* Writes always fail */ -#endif /* CONFIG_NFTL_RW */ - up(&nftl->mutex); - goto repeat; - } else { - DEBUG(MTD_DEBUG_LEVEL0, "NFTL unknown request\n"); - up(&nftl->mutex); - res = 0; - goto repeat; - } - repeat: - DEBUG(MTD_DEBUG_LEVEL3, "end_request(%d)\n", res); - spin_lock_irq(&io_request_lock); - end_request(res); - } -} - -static int nftl_open(struct inode *ip, struct file *fp) -{ - int nftlnum = MINOR(ip->i_rdev) / 16; - struct NFTLrecord *thisNFTL; - thisNFTL = NFTLs[nftlnum]; - - DEBUG(MTD_DEBUG_LEVEL2,"NFTL_open\n"); - -#ifdef CONFIG_KMOD - if (!thisNFTL && nftlnum == 0) { - request_module("docprobe"); - thisNFTL = NFTLs[nftlnum]; - } -#endif - if (!thisNFTL) { - DEBUG(MTD_DEBUG_LEVEL2,"ENODEV: thisNFTL = %d, minor = %d, ip = %p, fp = %p\n", - nftlnum, ip->i_rdev, ip, fp); - return -ENODEV; - } - -#ifndef CONFIG_NFTL_RW - if (fp->f_mode & FMODE_WRITE) - return -EROFS; -#endif /* !CONFIG_NFTL_RW */ - - thisNFTL->usecount++; - MOD_INC_USE_COUNT; - if (!get_mtd_device(thisNFTL->mtd, -1)) { - MOD_DEC_USE_COUNT; - return /* -E'SBUGGEREDOFF */ -ENXIO; - } - - return 0; -} - -static int nftl_release(struct inode *inode, struct file *fp) -{ - struct NFTLrecord *thisNFTL; - - thisNFTL = NFTLs[MINOR(inode->i_rdev) / 16]; - - DEBUG(MTD_DEBUG_LEVEL2, "NFTL_release\n"); - - invalidate_device(inode->i_rdev, 1); - - if (thisNFTL->mtd->sync) - thisNFTL->mtd->sync(thisNFTL->mtd); - thisNFTL->usecount--; - MOD_DEC_USE_COUNT; - - put_mtd_device(thisNFTL->mtd); - - return 0; -} -#if LINUX_VERSION_CODE < 0x20326 -static struct file_operations nftl_fops = { - read: block_read, - write: block_write, - ioctl: nftl_ioctl, - open: nftl_open, - release: nftl_release, - fsync: block_fsync, -}; -#else -static struct block_device_operations nftl_fops = -{ - open: nftl_open, - release: nftl_release, - ioctl: nftl_ioctl -}; -#endif - - - -/**************************************************************************** - * - * Module stuff - * - ****************************************************************************/ - -#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) -#define init_nftl init_module -#define cleanup_nftl cleanup_module -#endif - -static struct mtd_notifier nftl_notifier = {NFTL_notify_add, NFTL_notify_remove, NULL}; - -/* static int __init init_nftl(void) */ -int __init init_nftl(void) -{ - int i; - - printk(KERN_NOTICE - "M-Systems NAND Flash Translation Layer driver. (C) 1999 MVHI\n"); -#ifdef PRERELEASE - printk(KERN_INFO"$Id: nftl.c,v 1.57 2000/12/01 17:51:54 dwmw2 Exp $\n"); -#endif - - if (register_blkdev(MAJOR_NR, "nftl", &nftl_fops)){ - printk("unable to register NFTL block device on major %d\n", MAJOR_NR); - return -EBUSY; - } else { -#if LINUX_VERSION_CODE < 0x20320 - blk_dev[MAJOR_NR].request_fn = nftl_request; -#else - blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &nftl_request); -#endif - /* set block size to 1kB each */ - for (i = 0; i < 256; i++) { - nftl_blocksizes[i] = 1024; - } - blksize_size[MAJOR_NR] = nftl_blocksizes; - - nftl_gendisk.next = gendisk_head; - gendisk_head = &nftl_gendisk; - } - - register_mtd_user(&nftl_notifier); - - return 0; -} - -static void __exit cleanup_nftl(void) -{ - struct gendisk *gd, **gdp; - - unregister_mtd_user(&nftl_notifier); - unregister_blkdev(MAJOR_NR, "nftl"); - -#if LINUX_VERSION_CODE < 0x20320 - blk_dev[MAJOR_NR].request_fn = 0; -#else - blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); -#endif - - /* remove ourself from generic harddisk list - FIXME: why can't I found this partition on /proc/partition */ - for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next)) - if (*gdp == &nftl_gendisk) { - gd = *gdp; *gdp = gd->next; - break; - } -} - -module_init(init_nftl); -module_exit(cleanup_nftl); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/nftlcore.c linux/drivers/mtd/nftlcore.c --- v2.4.5/linux/drivers/mtd/nftlcore.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/nftlcore.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,1094 @@ +/* Linux driver for NAND Flash Translation Layer */ +/* (c) 1999 Machine Vision Holdings, Inc. */ +/* Author: David Woodhouse */ +/* $Id: nftlcore.c,v 1.73 2001/06/09 01:09:43 dwmw2 Exp $ */ + +/* + The contents of this file are distributed under the GNU General + Public License version 2. The author places no additional + restrictions of any kind on it. + */ + +#define PRERELEASE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_KMOD +#include +#endif +#include +#include +#include + +/* maximum number of loops while examining next block, to have a + chance to detect consistency problems (they should never happen + because of the checks done in the mounting */ + +#define MAX_LOOPS 10000 + +/* NFTL block device stuff */ +#define MAJOR_NR NFTL_MAJOR +#define DEVICE_REQUEST nftl_request +#define DEVICE_OFF(device) + + +#include +#include + +/* Linux-specific block device functions */ + +/* I _HATE_ the Linux block device setup more than anything else I've ever + * encountered, except ... + */ + +static int nftl_sizes[256]; +static int nftl_blocksizes[256]; + +/* .. for the Linux partition table handling. */ +struct hd_struct part_table[256]; + +#if LINUX_VERSION_CODE < 0x20328 +static void dummy_init (struct gendisk *crap) +{} +#endif + +static struct gendisk nftl_gendisk = { + major: MAJOR_NR, + major_name: "nftl", + minor_shift: NFTL_PARTN_BITS, /* Bits to shift to get real from partition */ + max_p: (1<mtd == mtd) { + /* This is a Spare Media Header for an NFTL we've already found */ + DEBUG(MTD_DEBUG_LEVEL1, "MTD already mounted as NFTL\n"); + return; + } + } + if (firstfree == -1) { + printk(KERN_WARNING "No more NFTL slot available\n"); + return; + } + + nftl = kmalloc(sizeof(struct NFTLrecord), GFP_KERNEL); + if (!nftl) { + printk(KERN_WARNING "Out of memory for NFTL data structures\n"); + return; + } + + init_MUTEX(&nftl->mutex); + + /* get physical parameters */ + nftl->EraseSize = mtd->erasesize; + nftl->nb_blocks = mtd->size / mtd->erasesize; + nftl->mtd = mtd; + + if (NFTL_mount(nftl) < 0) { + printk(KERN_WARNING "Could not mount NFTL device\n"); + kfree(nftl); + return; + } + + /* OK, it's a new one. Set up all the data structures. */ +#ifdef PSYCHO_DEBUG + printk("Found new NFTL nftl%c\n", firstfree + 'a'); +#endif + + /* linux stuff */ + nftl->usecount = 0; + nftl->cylinders = 1024; + nftl->heads = 16; + + temp = nftl->cylinders * nftl->heads; + nftl->sectors = nftl->nr_sects / temp; + if (nftl->nr_sects % temp) { + nftl->sectors++; + temp = nftl->cylinders * nftl->sectors; + nftl->heads = nftl->nr_sects / temp; + + if (nftl->nr_sects % temp) { + nftl->heads++; + temp = nftl->heads * nftl->sectors; + nftl->cylinders = nftl->nr_sects / temp; + } + } + + if (nftl->nr_sects != nftl->heads * nftl->cylinders * nftl->sectors) { + printk(KERN_WARNING "Cannot calculate an NFTL geometry to " + "match size of 0x%lx.\n", nftl->nr_sects); + printk(KERN_WARNING "Using C:%d H:%d S:%d (== 0x%lx sects)\n", + nftl->cylinders, nftl->heads , nftl->sectors, + (long)nftl->cylinders * (long)nftl->heads * (long)nftl->sectors ); + + /* Oh no we don't have nftl->nr_sects = nftl->heads * nftl->cylinders * nftl->sectors; */ + } + NFTLs[firstfree] = nftl; + /* Finally, set up the block device sizes */ + nftl_sizes[firstfree * 16] = nftl->nr_sects; + //nftl_blocksizes[firstfree*16] = 512; + part_table[firstfree * 16].nr_sects = nftl->nr_sects; + + nftl_gendisk.nr_real++; + + /* partition check ... */ +#if LINUX_VERSION_CODE < 0x20328 + resetup_one_dev(&nftl_gendisk, firstfree); +#else + grok_partitions(&nftl_gendisk, firstfree, 1<nr_sects); +#endif +} + +static void NFTL_unsetup(int i) +{ + struct NFTLrecord *nftl = NFTLs[i]; + + DEBUG(MTD_DEBUG_LEVEL1, "NFTL_unsetup %d\n", i); + + NFTLs[i] = NULL; + + if (nftl->ReplUnitTable) + kfree(nftl->ReplUnitTable); + if (nftl->EUNtable) + kfree(nftl->EUNtable); + + nftl_gendisk.nr_real--; + kfree(nftl); +} + +/* Search the MTD device for NFTL partitions */ +static void NFTL_notify_add(struct mtd_info *mtd) +{ + DEBUG(MTD_DEBUG_LEVEL1, "NFTL_notify_add for %s\n", mtd->name); + + if (mtd) { + if (!mtd->read_oob) { + /* If this MTD doesn't have out-of-band data, + then there's no point continuing */ + DEBUG(MTD_DEBUG_LEVEL1, "No OOB data, quitting\n"); + return; + } + DEBUG(MTD_DEBUG_LEVEL3, "mtd->read = %p, size = %d, erasesize = %d\n", + mtd->read, mtd->size, mtd->erasesize); + + NFTL_setup(mtd); + } +} + +static void NFTL_notify_remove(struct mtd_info *mtd) +{ + int i; + + for (i = 0; i < MAX_NFTLS; i++) { + if (NFTLs[i] && NFTLs[i]->mtd == mtd) + NFTL_unsetup(i); + } +} + +#ifdef CONFIG_NFTL_RW + +/* Actual NFTL access routines */ +/* NFTL_findfreeblock: Find a free Erase Unit on the NFTL partition. This function is used + * when the give Virtual Unit Chain + */ +static u16 NFTL_findfreeblock(struct NFTLrecord *nftl, int desperate ) +{ + /* For a given Virtual Unit Chain: find or create a free block and + add it to the chain */ + /* We're passed the number of the last EUN in the chain, to save us from + having to look it up again */ + u16 pot = nftl->LastFreeEUN; + int silly = -1; + + /* Normally, we force a fold to happen before we run out of free blocks completely */ + if (!desperate && nftl->numfreeEUNs < 2) { + DEBUG(MTD_DEBUG_LEVEL1, "NFTL_findfreeblock: there are too few free EUNs\n"); + return 0xffff; + } + + /* Scan for a free block */ + do { + if (nftl->ReplUnitTable[pot] == BLOCK_FREE) { + nftl->LastFreeEUN = pot; + nftl->numfreeEUNs--; + return pot; + } + + /* This will probably point to the MediaHdr unit itself, + right at the beginning of the partition. But that unit + (and the backup unit too) should have the UCI set + up so that it's not selected for overwriting */ + if (++pot > nftl->lastEUN) + pot = le16_to_cpu(nftl->MediaHdr.FirstPhysicalEUN); + + if (!silly--) { + printk("Argh! No free blocks found! LastFreeEUN = %d, " + "FirstEUN = %d\n", nftl->LastFreeEUN, + le16_to_cpu(nftl->MediaHdr.FirstPhysicalEUN)); + return 0xffff; + } + } while (pot != nftl->LastFreeEUN); + + return 0xffff; +} + +static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned pendingblock ) +{ + u16 BlockMap[MAX_SECTORS_PER_UNIT]; + unsigned char BlockLastState[MAX_SECTORS_PER_UNIT]; + unsigned char BlockFreeFound[MAX_SECTORS_PER_UNIT]; + unsigned int thisEUN; + int block; + int silly; + unsigned int targetEUN; + struct nftl_oob oob; + int inplace = 1; + size_t retlen; + + memset(BlockMap, 0xff, sizeof(BlockMap)); + memset(BlockFreeFound, 0, sizeof(BlockFreeFound)); + + thisEUN = nftl->EUNtable[thisVUC]; + + if (thisEUN == BLOCK_NIL) { + printk(KERN_WARNING "Trying to fold non-existent " + "Virtual Unit Chain %d!\n", thisVUC); + return BLOCK_NIL; + } + + /* Scan to find the Erase Unit which holds the actual data for each + 512-byte block within the Chain. + */ + silly = MAX_LOOPS; + targetEUN = BLOCK_NIL; + while (thisEUN <= nftl->lastEUN ) { + unsigned int status, foldmark; + + targetEUN = thisEUN; + for (block = 0; block < nftl->EraseSize / 512; block ++) { + MTD_READOOB(nftl->mtd, + (thisEUN * nftl->EraseSize) + (block * 512), + 16 , &retlen, (char *)&oob); + if (block == 2) { + foldmark = oob.u.c.FoldMark | oob.u.c.FoldMark1; + if (foldmark == FOLD_MARK_IN_PROGRESS) { + DEBUG(MTD_DEBUG_LEVEL1, + "Write Inhibited on EUN %d\n", thisEUN); + inplace = 0; + } else { + /* There's no other reason not to do inplace, + except ones that come later. So we don't need + to preserve inplace */ + inplace = 1; + } + } + status = oob.b.Status | oob.b.Status1; + BlockLastState[block] = status; + + switch(status) { + case SECTOR_FREE: + BlockFreeFound[block] = 1; + break; + + case SECTOR_USED: + if (!BlockFreeFound[block]) + BlockMap[block] = thisEUN; + else + printk(KERN_WARNING + "SECTOR_USED found after SECTOR_FREE " + "in Virtual Unit Chain %d for block %d\n", + thisVUC, block); + break; + case SECTOR_IGNORE: + case SECTOR_DELETED: + break; + default: + printk("Unknown status for block %d in EUN %d: %x\n", + block, thisEUN, status); + } + } + + if (!silly--) { + printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%x\n", + thisVUC); + return BLOCK_NIL; + } + + thisEUN = nftl->ReplUnitTable[thisEUN]; + } + + if (inplace) { + /* We're being asked to be a fold-in-place. Check + that all blocks are either present or SECTOR_FREE + in the target block. If not, we're going to have + to fold out-of-place anyway. + */ + for (block = 0; block < nftl->EraseSize / 512 ; block++) { + if (BlockLastState[block] != SECTOR_FREE && + BlockMap[block] != targetEUN) { + DEBUG(MTD_DEBUG_LEVEL1, "Setting inplace to 0. VUC %d, " + "block %d was %x lastEUN, " + "and is in EUN %d (%s) %d\n", + thisVUC, block, BlockLastState[block], + BlockMap[block], + BlockMap[block]== targetEUN ? "==" : "!=", + targetEUN); + inplace = 0; + break; + } + } + + if (pendingblock >= (thisVUC * (nftl->EraseSize / 512)) && + pendingblock < ((thisVUC + 1)* (nftl->EraseSize / 512)) && + BlockLastState[pendingblock - (thisVUC * (nftl->EraseSize / 512))] != + SECTOR_FREE) { + DEBUG(MTD_DEBUG_LEVEL1, "Pending write not free in EUN %d. " + "Folding out of place.\n", targetEUN); + inplace = 0; + } + } + + if (!inplace) { + DEBUG(MTD_DEBUG_LEVEL1, "Cannot fold Virtual Unit Chain %d in place. " + "Trying out-of-place\n", thisVUC); + /* We need to find a targetEUN to fold into. */ + targetEUN = NFTL_findfreeblock(nftl, 1); + if (targetEUN == BLOCK_NIL) { + /* Ouch. Now we're screwed. We need to do a + fold-in-place of another chain to make room + for this one. We need a better way of selecting + which chain to fold, because makefreeblock will + only ask us to fold the same one again. + */ + printk(KERN_WARNING + "NFTL_findfreeblock(desperate) returns 0xffff.\n"); + return BLOCK_NIL; + } + } else { + /* We put a fold mark in the chain we are folding only if + we fold in place to help the mount check code. If we do + not fold in place, it is possible to find the valid + chain by selecting the longer one */ + oob.u.c.FoldMark = oob.u.c.FoldMark1 = cpu_to_le16(FOLD_MARK_IN_PROGRESS); + oob.u.c.unused = 0xffffffff; + MTD_WRITEOOB(nftl->mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8, + 8, &retlen, (char *)&oob.u); + } + + /* OK. We now know the location of every block in the Virtual Unit Chain, + and the Erase Unit into which we are supposed to be copying. + Go for it. + */ + DEBUG(MTD_DEBUG_LEVEL1,"Folding chain %d into unit %d\n", thisVUC, targetEUN); + for (block = 0; block < nftl->EraseSize / 512 ; block++) { + unsigned char movebuf[512]; + int ret; + + /* If it's in the target EUN already, or if it's pending write, do nothing */ + if (BlockMap[block] == targetEUN || + (pendingblock == (thisVUC * (nftl->EraseSize / 512) + block))) { + continue; + } + + /* copy only in non free block (free blocks can only + happen in case of media errors or deleted blocks) */ + if (BlockMap[block] == BLOCK_NIL) + continue; + + ret = MTD_READECC(nftl->mtd, (nftl->EraseSize * BlockMap[block]) + + (block * 512), 512, &retlen, movebuf, (char *)&oob); + if (ret < 0) { + ret = MTD_READECC(nftl->mtd, (nftl->EraseSize * BlockMap[block]) + + (block * 512), 512, &retlen, + movebuf, (char *)&oob); + if (ret != -EIO) + printk("Error went away on retry.\n"); + } + MTD_WRITEECC(nftl->mtd, (nftl->EraseSize * targetEUN) + (block * 512), + 512, &retlen, movebuf, (char *)&oob); + } + + /* add the header so that it is now a valid chain */ + oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum + = cpu_to_le16(thisVUC); + oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff; + + MTD_WRITEOOB(nftl->mtd, (nftl->EraseSize * targetEUN) + 8, + 8, &retlen, (char *)&oob.u); + + /* OK. We've moved the whole lot into the new block. Now we have to free the original blocks. */ + + /* At this point, we have two different chains for this Virtual Unit, and no way to tell + them apart. If we crash now, we get confused. However, both contain the same data, so we + shouldn't actually lose data in this case. It's just that when we load up on a medium which + has duplicate chains, we need to free one of the chains because it's not necessary any more. + */ + thisEUN = nftl->EUNtable[thisVUC]; + DEBUG(MTD_DEBUG_LEVEL1,"Want to erase\n"); + + /* For each block in the old chain (except the targetEUN of course), + free it and make it available for future use */ + while (thisEUN <= nftl->lastEUN && thisEUN != targetEUN) { + unsigned int EUNtmp; + + EUNtmp = nftl->ReplUnitTable[thisEUN]; + + if (NFTL_formatblock(nftl, thisEUN) < 0) { + /* could not erase : mark block as reserved + * FixMe: Update Bad Unit Table on disk + */ + nftl->ReplUnitTable[thisEUN] = BLOCK_RESERVED; + } else { + /* correctly erased : mark it as free */ + nftl->ReplUnitTable[thisEUN] = BLOCK_FREE; + nftl->numfreeEUNs++; + } + thisEUN = EUNtmp; + } + + /* Make this the new start of chain for thisVUC */ + nftl->ReplUnitTable[targetEUN] = BLOCK_NIL; + nftl->EUNtable[thisVUC] = targetEUN; + + return targetEUN; +} + +u16 NFTL_makefreeblock( struct NFTLrecord *nftl , unsigned pendingblock) +{ + /* This is the part that needs some cleverness applied. + For now, I'm doing the minimum applicable to actually + get the thing to work. + Wear-levelling and other clever stuff needs to be implemented + and we also need to do some assessment of the results when + the system loses power half-way through the routine. + */ + u16 LongestChain = 0; + u16 ChainLength = 0, thislen; + u16 chain, EUN; + + for (chain = 0; chain < nftl->MediaHdr.FormattedSize / nftl->EraseSize; chain++) { + EUN = nftl->EUNtable[chain]; + thislen = 0; + + while (EUN <= nftl->lastEUN) { + thislen++; + //printk("VUC %d reaches len %d with EUN %d\n", chain, thislen, EUN); + EUN = nftl->ReplUnitTable[EUN] & 0x7fff; + if (thislen > 0xff00) { + printk("Endless loop in Virtual Chain %d: Unit %x\n", + chain, EUN); + } + if (thislen > 0xff10) { + /* Actually, don't return failure. Just ignore this chain and + get on with it. */ + thislen = 0; + break; + } + } + + if (thislen > ChainLength) { + //printk("New longest chain is %d with length %d\n", chain, thislen); + ChainLength = thislen; + LongestChain = chain; + } + } + + if (ChainLength < 2) { + printk(KERN_WARNING "No Virtual Unit Chains available for folding. " + "Failing request\n"); + return 0xffff; + } + + return NFTL_foldchain (nftl, LongestChain, pendingblock); +} + +/* NFTL_findwriteunit: Return the unit number into which we can write + for this block. Make it available if it isn't already +*/ +static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) +{ + u16 lastEUN; + u16 thisVUC = block / (nftl->EraseSize / 512); + unsigned int writeEUN; + unsigned long blockofs = (block * 512) & (nftl->EraseSize -1); + size_t retlen; + int silly, silly2 = 3; + struct nftl_oob oob; + + do { + /* Scan the media to find a unit in the VUC which has + a free space for the block in question. + */ + + /* This condition catches the 0x[7f]fff cases, as well as + being a sanity check for past-end-of-media access + */ + lastEUN = BLOCK_NIL; + writeEUN = nftl->EUNtable[thisVUC]; + silly = MAX_LOOPS; + while (writeEUN <= nftl->lastEUN) { + struct nftl_bci bci; + size_t retlen; + unsigned int status; + + lastEUN = writeEUN; + + MTD_READOOB(nftl->mtd, (writeEUN * nftl->EraseSize) + blockofs, + 8, &retlen, (char *)&bci); + + DEBUG(MTD_DEBUG_LEVEL2, "Status of block %d in EUN %d is %x\n", + block , writeEUN, le16_to_cpu(bci.Status)); + + status = bci.Status | bci.Status1; + switch(status) { + case SECTOR_FREE: + return writeEUN; + + case SECTOR_DELETED: + case SECTOR_USED: + case SECTOR_IGNORE: + break; + default: + // Invalid block. Don't use it any more. Must implement. + break; + } + + if (!silly--) { + printk(KERN_WARNING + "Infinite loop in Virtual Unit Chain 0x%x\n", + thisVUC); + return 0xffff; + } + + /* Skip to next block in chain */ + writeEUN = nftl->ReplUnitTable[writeEUN]; + } + + /* OK. We didn't find one in the existing chain, or there + is no existing chain. */ + + /* Try to find an already-free block */ + writeEUN = NFTL_findfreeblock(nftl, 0); + + if (writeEUN == BLOCK_NIL) { + /* That didn't work - there were no free blocks just + waiting to be picked up. We're going to have to fold + a chain to make room. + */ + + /* First remember the start of this chain */ + //u16 startEUN = nftl->EUNtable[thisVUC]; + + //printk("Write to VirtualUnitChain %d, calling makefreeblock()\n", thisVUC); + writeEUN = NFTL_makefreeblock(nftl, 0xffff); + + if (writeEUN == BLOCK_NIL) { + /* OK, we accept that the above comment is + lying - there may have been free blocks + last time we called NFTL_findfreeblock(), + but they are reserved for when we're + desperate. Well, now we're desperate. + */ + DEBUG(MTD_DEBUG_LEVEL1, "Using desperate==1 to find free EUN to accommodate write to VUC %d\n", thisVUC); + writeEUN = NFTL_findfreeblock(nftl, 1); + } + if (writeEUN == BLOCK_NIL) { + /* Ouch. This should never happen - we should + always be able to make some room somehow. + If we get here, we've allocated more storage + space than actual media, or our makefreeblock + routine is missing something. + */ + printk(KERN_WARNING "Cannot make free space.\n"); + return BLOCK_NIL; + } + //printk("Restarting scan\n"); + lastEUN = BLOCK_NIL; + continue; + } + + /* We've found a free block. Insert it into the chain. */ + + if (lastEUN != BLOCK_NIL) { + thisVUC |= 0x8000; /* It's a replacement block */ + } else { + /* The first block in a new chain */ + nftl->EUNtable[thisVUC] = writeEUN; + } + + /* set up the actual EUN we're writing into */ + /* Both in our cache... */ + nftl->ReplUnitTable[writeEUN] = BLOCK_NIL; + + /* ... and on the flash itself */ + MTD_READOOB(nftl->mtd, writeEUN * nftl->EraseSize + 8, 8, + &retlen, (char *)&oob.u); + + oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC); + + MTD_WRITEOOB(nftl->mtd, writeEUN * nftl->EraseSize + 8, 8, + &retlen, (char *)&oob.u); + + /* we link the new block to the chain only after the + block is ready. It avoids the case where the chain + could point to a free block */ + if (lastEUN != BLOCK_NIL) { + /* Both in our cache... */ + nftl->ReplUnitTable[lastEUN] = writeEUN; + /* ... and on the flash itself */ + MTD_READOOB(nftl->mtd, (lastEUN * nftl->EraseSize) + 8, + 8, &retlen, (char *)&oob.u); + + oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum + = cpu_to_le16(writeEUN); + + MTD_WRITEOOB(nftl->mtd, (lastEUN * nftl->EraseSize) + 8, + 8, &retlen, (char *)&oob.u); + } + + return writeEUN; + + } while (silly2--); + + printk(KERN_WARNING "Error folding to make room for Virtual Unit Chain 0x%x\n", + thisVUC); + return 0xffff; +} + +static int NFTL_writeblock(struct NFTLrecord *nftl, unsigned block, char *buffer) +{ + u16 writeEUN; + unsigned long blockofs = (block * 512) & (nftl->EraseSize - 1); + size_t retlen; + u8 eccbuf[6]; + + writeEUN = NFTL_findwriteunit(nftl, block); + + if (writeEUN == BLOCK_NIL) { + printk(KERN_WARNING + "NFTL_writeblock(): Cannot find block to write to\n"); + /* If we _still_ haven't got a block to use, we're screwed */ + return 1; + } + + MTD_WRITEECC(nftl->mtd, (writeEUN * nftl->EraseSize) + blockofs, + 512, &retlen, (char *)buffer, (char *)eccbuf); + /* no need to write SECTOR_USED flags since they are written in mtd_writeecc */ + + return 0; +} +#endif /* CONFIG_NFTL_RW */ + +static int NFTL_readblock(struct NFTLrecord *nftl, unsigned block, char *buffer) +{ + u16 lastgoodEUN; + u16 thisEUN = nftl->EUNtable[block / (nftl->EraseSize / 512)]; + unsigned long blockofs = (block * 512) & (nftl->EraseSize - 1); + unsigned int status; + int silly = MAX_LOOPS; + size_t retlen; + struct nftl_bci bci; + + lastgoodEUN = BLOCK_NIL; + + if (thisEUN != BLOCK_NIL) { + while (thisEUN < nftl->nb_blocks) { + if (MTD_READOOB(nftl->mtd, (thisEUN * nftl->EraseSize) + blockofs, + 8, &retlen, (char *)&bci) < 0) + status = SECTOR_IGNORE; + else + status = bci.Status | bci.Status1; + + switch (status) { + case SECTOR_FREE: + /* no modification of a sector should follow a free sector */ + goto the_end; + case SECTOR_DELETED: + lastgoodEUN = BLOCK_NIL; + break; + case SECTOR_USED: + lastgoodEUN = thisEUN; + break; + case SECTOR_IGNORE: + break; + default: + printk("Unknown status for block %d in EUN %d: %x\n", + block, thisEUN, status); + break; + } + + if (!silly--) { + printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%x\n", + block / (nftl->EraseSize / 512)); + return 1; + } + thisEUN = nftl->ReplUnitTable[thisEUN]; + } + } + + the_end: + if (lastgoodEUN == BLOCK_NIL) { + /* the requested block is not on the media, return all 0x00 */ + memset(buffer, 0, 512); + } else { + loff_t ptr = (lastgoodEUN * nftl->EraseSize) + blockofs; + size_t retlen; + u_char eccbuf[6]; + if (MTD_READECC(nftl->mtd, ptr, 512, &retlen, buffer, eccbuf)) + return -EIO; + } + return 0; +} + +static int nftl_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) +{ + struct NFTLrecord *nftl; + int p; + + nftl = NFTLs[MINOR(inode->i_rdev) >> NFTL_PARTN_BITS]; + + if (!nftl) return -EINVAL; + + switch (cmd) { + case HDIO_GETGEO: { + struct hd_geometry g; + + g.heads = nftl->heads; + g.sectors = nftl->sectors; + g.cylinders = nftl->cylinders; + g.start = part_table[MINOR(inode->i_rdev)].start_sect; + return copy_to_user((void *)arg, &g, sizeof g) ? -EFAULT : 0; + } + case BLKGETSIZE: /* Return device size */ + if (!arg) return -EINVAL; + return put_user(part_table[MINOR(inode->i_rdev)].nr_sects, + (long *) arg); + + case BLKFLSBUF: + if (!capable(CAP_SYS_ADMIN)) return -EACCES; + fsync_dev(inode->i_rdev); + invalidate_buffers(inode->i_rdev); + if (nftl->mtd->sync) + nftl->mtd->sync(nftl->mtd); + return 0; + + case BLKRRPART: + if (!capable(CAP_SYS_ADMIN)) return -EACCES; + if (nftl->usecount > 1) return -EBUSY; + /* + * We have to flush all buffers and invalidate caches, + * or we won't be able to re-use the partitions, + * if there was a change and we don't want to reboot + */ + p = (1< 0) { + kdev_t devp = MKDEV(MAJOR(inode->i_dev), MINOR(inode->i_dev)+p); + if (part_table[p].nr_sects > 0) + invalidate_device (devp, 1); + + part_table[MINOR(inode->i_dev)+p].start_sect = 0; + part_table[MINOR(inode->i_dev)+p].nr_sects = 0; + } + +#if LINUX_VERSION_CODE < 0x20328 + resetup_one_dev(&nftl_gendisk, MINOR(inode->i_rdev) >> NFTL_PARTN_BITS); +#else + grok_partitions(&nftl_gendisk, MINOR(inode->i_rdev) >> NFTL_PARTN_BITS, + 1<nr_sects); +#endif + return 0; + +#if (LINUX_VERSION_CODE < 0x20303) + RO_IOCTLS(inode->i_rdev, arg); /* ref. linux/blk.h */ +#else + case BLKROSET: + case BLKROGET: + case BLKSSZGET: + return blk_ioctl(inode->i_rdev, cmd, arg); +#endif + + default: + return -EINVAL; + } +} + +void nftl_request(RQFUNC_ARG) +{ + unsigned int dev, block, nsect; + struct NFTLrecord *nftl; + char *buffer; + struct request *req; + int res; + + while (1) { + INIT_REQUEST; /* blk.h */ + req = CURRENT; + + /* We can do this because the generic code knows not to + touch the request at the head of the queue */ + spin_unlock_irq(&io_request_lock); + + DEBUG(MTD_DEBUG_LEVEL2, "NFTL_request\n"); + DEBUG(MTD_DEBUG_LEVEL3, "NFTL %s request, from sector 0x%04lx for 0x%04lx sectors\n", + (req->cmd == READ) ? "Read " : "Write", + req->sector, req->current_nr_sectors); + + dev = MINOR(req->rq_dev); + block = req->sector; + nsect = req->current_nr_sectors; + buffer = req->buffer; + res = 1; /* succeed */ + + if (dev >= MAX_NFTLS * (1<rq_dev)); + res = 0; /* fail */ + goto repeat; + } + + nftl = NFTLs[dev / (1<mutex); + DEBUG(MTD_DEBUG_LEVEL3, "Got mutex\n"); + + if (block + nsect > part_table[dev].nr_sects) { + /* access past the end of device */ + printk("nftl%c%d: bad access: block = %d, count = %d\n", + (MINOR(req->rq_dev)>>6)+'a', dev & 0xf, block, nsect); + up(&nftl->mutex); + res = 0; /* fail */ + goto repeat; + } + + block += part_table[dev].start_sect; + + if (req->cmd == READ) { + DEBUG(MTD_DEBUG_LEVEL2, "NFTL read request of 0x%x sectors @ %x " + "(req->nr_sectors == %lx)\n", nsect, block, req->nr_sectors); + + for ( ; nsect > 0; nsect-- , block++, buffer += 512) { + /* Read a single sector to req->buffer + (512 * i) */ + if (NFTL_readblock(nftl, block, buffer)) { + DEBUG(MTD_DEBUG_LEVEL2, "NFTL read request failed\n"); + up(&nftl->mutex); + res = 0; + goto repeat; + } + } + + DEBUG(MTD_DEBUG_LEVEL2,"NFTL read request completed OK\n"); + up(&nftl->mutex); + goto repeat; + } else if (req->cmd == WRITE) { + DEBUG(MTD_DEBUG_LEVEL2, "NFTL write request of 0x%x sectors @ %x " + "(req->nr_sectors == %lx)\n", nsect, block, + req->nr_sectors); +#ifdef CONFIG_NFTL_RW + for ( ; nsect > 0; nsect-- , block++, buffer += 512) { + /* Read a single sector to req->buffer + (512 * i) */ + if (NFTL_writeblock(nftl, block, buffer)) { + DEBUG(MTD_DEBUG_LEVEL1,"NFTL write request failed\n"); + up(&nftl->mutex); + res = 0; + goto repeat; + } + } + DEBUG(MTD_DEBUG_LEVEL2,"NFTL write request completed OK\n"); +#else + res = 0; /* Writes always fail */ +#endif /* CONFIG_NFTL_RW */ + up(&nftl->mutex); + goto repeat; + } else { + DEBUG(MTD_DEBUG_LEVEL0, "NFTL unknown request\n"); + up(&nftl->mutex); + res = 0; + goto repeat; + } + repeat: + DEBUG(MTD_DEBUG_LEVEL3, "end_request(%d)\n", res); + spin_lock_irq(&io_request_lock); + end_request(res); + } +} + +static int nftl_open(struct inode *ip, struct file *fp) +{ + int nftlnum = MINOR(ip->i_rdev) >> NFTL_PARTN_BITS; + struct NFTLrecord *thisNFTL; + thisNFTL = NFTLs[nftlnum]; + + DEBUG(MTD_DEBUG_LEVEL2,"NFTL_open\n"); + +#ifdef CONFIG_KMOD + if (!thisNFTL && nftlnum == 0) { + request_module("docprobe"); + thisNFTL = NFTLs[nftlnum]; + } +#endif + if (!thisNFTL) { + DEBUG(MTD_DEBUG_LEVEL2,"ENODEV: thisNFTL = %d, minor = %d, ip = %p, fp = %p\n", + nftlnum, ip->i_rdev, ip, fp); + return -ENODEV; + } + +#ifndef CONFIG_NFTL_RW + if (fp->f_mode & FMODE_WRITE) + return -EROFS; +#endif /* !CONFIG_NFTL_RW */ + + thisNFTL->usecount++; + MOD_INC_USE_COUNT; + if (!get_mtd_device(thisNFTL->mtd, -1)) { + MOD_DEC_USE_COUNT; + return /* -E'SBUGGEREDOFF */ -ENXIO; + } + + return 0; +} + +static int nftl_release(struct inode *inode, struct file *fp) +{ + struct NFTLrecord *thisNFTL; + + thisNFTL = NFTLs[MINOR(inode->i_rdev) / 16]; + + DEBUG(MTD_DEBUG_LEVEL2, "NFTL_release\n"); + + invalidate_device(inode->i_rdev, 1); + + if (thisNFTL->mtd->sync) + thisNFTL->mtd->sync(thisNFTL->mtd); + thisNFTL->usecount--; + MOD_DEC_USE_COUNT; + + put_mtd_device(thisNFTL->mtd); + + return 0; +} +#if LINUX_VERSION_CODE < 0x20326 +static struct file_operations nftl_fops = { + read: block_read, + write: block_write, + ioctl: nftl_ioctl, + open: nftl_open, + release: nftl_release, + fsync: block_fsync, +}; +#else +static struct block_device_operations nftl_fops = +{ + open: nftl_open, + release: nftl_release, + ioctl: nftl_ioctl +}; +#endif + + + +/**************************************************************************** + * + * Module stuff + * + ****************************************************************************/ + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define init_nftl init_module +#define cleanup_nftl cleanup_module +#endif + +static struct mtd_notifier nftl_notifier = { + add: NFTL_notify_add, + remove: NFTL_notify_remove +}; + +static int __init init_nftl(void) +{ + int i; + + printk(KERN_NOTICE + "M-Systems NAND Flash Translation Layer driver. (C) 1999 MVHI\n"); +#ifdef PRERELEASE + printk(KERN_INFO"$Id: nftlcore.c,v 1.73 2001/06/09 01:09:43 dwmw2 Exp $\n"); +#endif + + if (register_blkdev(MAJOR_NR, "nftl", &nftl_fops)){ + printk("unable to register NFTL block device on major %d\n", MAJOR_NR); + return -EBUSY; + } else { +#if LINUX_VERSION_CODE < 0x20320 + blk_dev[MAJOR_NR].request_fn = nftl_request; +#else + blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &nftl_request); +#endif + /* set block size to 1kB each */ + for (i = 0; i < 256; i++) { + nftl_blocksizes[i] = 1024; + } + blksize_size[MAJOR_NR] = nftl_blocksizes; + + nftl_gendisk.next = gendisk_head; + gendisk_head = &nftl_gendisk; + } + + register_mtd_user(&nftl_notifier); + + return 0; +} + +static void __exit cleanup_nftl(void) +{ + struct gendisk *gd, **gdp; + + unregister_mtd_user(&nftl_notifier); + unregister_blkdev(MAJOR_NR, "nftl"); + +#if LINUX_VERSION_CODE < 0x20320 + blk_dev[MAJOR_NR].request_fn = 0; +#else + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); +#endif + + /* remove ourself from generic harddisk list + FIXME: why can't I found this partition on /proc/partition */ + for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next)) + if (*gdp == &nftl_gendisk) { + gd = *gdp; *gdp = gd->next; + break; + } +} + +module_init(init_nftl); +module_exit(cleanup_nftl); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/nftlmount.c linux/drivers/mtd/nftlmount.c --- v2.4.5/linux/drivers/mtd/nftlmount.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/mtd/nftlmount.c Tue Jun 12 10:30:27 2001 @@ -4,7 +4,7 @@ * Author: Fabrice Bellard (fabrice.bellard@netgem.com) * Copyright (C) 2000 Netgem S.A. * - * $Id: nftlmount.c,v 1.11 2000/11/17 12:24:09 ollie Exp $ + * $Id: nftlmount.c,v 1.17 2001/06/02 20:33:20 dwmw2 Exp $ * * 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 @@ -20,6 +20,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#define __NO_VERSION__ #include #include #include @@ -85,13 +87,20 @@ } nftl->nb_boot_blocks = le16_to_cpu(mh->FirstPhysicalEUN); - if ((nftl->nb_boot_blocks + 2) >= nftl->nb_blocks) + if ((nftl->nb_boot_blocks + 2) >= nftl->nb_blocks) { + printk(KERN_NOTICE "Potential NFTL Media Header found, but sanity check failed:\n"); + printk(KERN_NOTICE "nb_boot_blocks (%d) + 2 > nb_blocks (%d)\n", + nftl->nb_boot_blocks, nftl->nb_blocks); goto ReplUnitTable; /* small consistency check */ + } nftl->numvunits = le32_to_cpu(mh->FormattedSize) / nftl->EraseSize; - if (nftl->numvunits > (nftl->nb_blocks - nftl->nb_boot_blocks - 2)) + if (nftl->numvunits > (nftl->nb_blocks - nftl->nb_boot_blocks - 2)) { + printk(KERN_NOTICE "Potential NFTL Media Header found, but sanity check failed:\n"); + printk(KERN_NOTICE "numvunits (%d) > nb_blocks (%d) - nb_boot_blocks(%d) - 2\n", + nftl->numvunits, nftl->nb_blocks, nftl->nb_boot_blocks); goto ReplUnitTable; /* small consistency check */ - + } /* FixMe: with bad blocks, the total size available is not FormattedSize any more !!! */ nftl->nr_sects = nftl->numvunits * (nftl->EraseSize / SECTORSIZE); @@ -359,8 +368,7 @@ { struct nftl_uci1 h1; unsigned int erase_mark; - int i, retlen; - unsigned char buf[SECTORSIZE]; + int retlen; /* check erase mark. */ if (MTD_READOOB(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/nora.c linux/drivers/mtd/nora.c --- v2.4.5/linux/drivers/mtd/nora.c Mon Dec 11 14:57:58 2000 +++ linux/drivers/mtd/nora.c Wed Dec 31 16:00:00 1969 @@ -1,208 +0,0 @@ -/* - * $Id: nora.c,v 1.17 2000/12/03 19:32:21 dwmw2 Exp $ - * - * This is so simple I love it. - */ - -#include -#include -#include - -#include -#include - - -#define WINDOW_ADDR 0xd0000000 -#define WINDOW_SIZE 0x04000000 - -static struct mtd_info *mymtd; - -__u8 nora_read8(struct map_info *map, unsigned long ofs) -{ - return *(__u8 *)(WINDOW_ADDR + ofs); -} - -__u16 nora_read16(struct map_info *map, unsigned long ofs) -{ - return *(__u16 *)(WINDOW_ADDR + ofs); -} - -__u32 nora_read32(struct map_info *map, unsigned long ofs) -{ - return *(__u32 *)(WINDOW_ADDR + ofs); -} - -void nora_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) -{ - memcpy(to, (void *)(WINDOW_ADDR + from), len); -} - -void nora_write8(struct map_info *map, __u8 d, unsigned long adr) -{ - *(__u8 *)(WINDOW_ADDR + adr) = d; -} - -void nora_write16(struct map_info *map, __u16 d, unsigned long adr) -{ - *(__u16 *)(WINDOW_ADDR + adr) = d; -} - -void nora_write32(struct map_info *map, __u32 d, unsigned long adr) -{ - *(__u32 *)(WINDOW_ADDR + adr) = d; -} - -void nora_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) -{ - memcpy((void *)(WINDOW_ADDR + to), from, len); -} - -struct map_info nora_map = { - name: "NORA", - size: WINDOW_SIZE, - buswidth: 2, - read8: nora_read8, - read16: nora_read16, - read32: nora_read32, - copy_from: nora_copy_from, - write8: nora_write8, - write16: nora_write16, - write32: nora_write32, - copy_to: nora_copy_to -}; - - -static int nora_mtd_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) -{ - return mymtd->read(mymtd, from + (unsigned long)mtd->priv, len, retlen, buf); -} - -static int nora_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) -{ - return mymtd->write(mymtd, to + (unsigned long)mtd->priv, len, retlen, buf); -} - -static int nora_mtd_erase (struct mtd_info *mtd, struct erase_info *instr) -{ - instr->addr += (unsigned long)mtd->priv; - return mymtd->erase(mymtd, instr); -} - -static void nora_mtd_sync (struct mtd_info *mtd) -{ - mymtd->sync(mymtd); -} - -static int nora_mtd_suspend (struct mtd_info *mtd) -{ - return mymtd->suspend(mymtd); -} - -static void nora_mtd_resume (struct mtd_info *mtd) -{ - mymtd->resume(mymtd); -} - - -static struct mtd_info nora_mtds[4] = { /* boot, kernel, ramdisk, fs */ - { - type: MTD_NORFLASH, - flags: MTD_CAP_NORFLASH, - size: 0x60000, - erasesize: 0x20000, - name: "NORA boot firmware", - module: THIS_MODULE, - erase: nora_mtd_erase, - read: nora_mtd_read, - write: nora_mtd_write, - suspend: nora_mtd_suspend, - resume: nora_mtd_resume, - sync: nora_mtd_sync, - priv: (void *)0 - }, - { - type: MTD_NORFLASH, - flags: MTD_CAP_NORFLASH, - size: 0x0a0000, - erasesize: 0x20000, - name: "NORA kernel", - module: THIS_MODULE, - erase: nora_mtd_erase, - read: nora_mtd_read, - write: nora_mtd_write, - suspend: nora_mtd_suspend, - resume: nora_mtd_resume, - sync: nora_mtd_sync, - priv: (void *)0x60000 - }, - { - type: MTD_NORFLASH, - flags: MTD_CAP_NORFLASH, - size: 0x900000, - erasesize: 0x20000, - name: "NORA root filesystem", - module: THIS_MODULE, - erase: nora_mtd_erase, - read: nora_mtd_read, - write: nora_mtd_write, - suspend: nora_mtd_suspend, - resume: nora_mtd_resume, - sync: nora_mtd_sync, - priv: (void *)0x100000 - }, - { - type: MTD_NORFLASH, - flags: MTD_CAP_NORFLASH, - size: 0x1600000, - erasesize: 0x20000, - name: "NORA second filesystem", - module: THIS_MODULE, - erase: nora_mtd_erase, - read: nora_mtd_read, - write: nora_mtd_write, - suspend: nora_mtd_suspend, - resume: nora_mtd_resume, - sync: nora_mtd_sync, - priv: (void *)0xa00000 - } -}; - - -#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) -#define init_nora init_module -#define cleanup_nora cleanup_module -#endif - -int __init init_nora(void) -{ - printk(KERN_NOTICE "nora flash device: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR); - - mymtd = do_cfi_probe(&nora_map); - if (mymtd) { -#ifdef MODULE - mymtd->module = &__this_module; -#endif - - add_mtd_device(&nora_mtds[2]); - add_mtd_device(&nora_mtds[0]); - add_mtd_device(&nora_mtds[1]); - add_mtd_device(&nora_mtds[3]); - return 0; - } - - return -ENXIO; -} - -static void __exit cleanup_nora(void) -{ - if (mymtd) { - del_mtd_device(&nora_mtds[3]); - del_mtd_device(&nora_mtds[1]); - del_mtd_device(&nora_mtds[0]); - del_mtd_device(&nora_mtds[2]); - map_destroy(mymtd); - } -} - -module_init(init_nora); -module_exit(cleanup_nora); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/octagon-5066.c linux/drivers/mtd/octagon-5066.c --- v2.4.5/linux/drivers/mtd/octagon-5066.c Fri Feb 16 16:02:36 2001 +++ linux/drivers/mtd/octagon-5066.c Wed Dec 31 16:00:00 1969 @@ -1,285 +0,0 @@ -// $Id: octagon-5066.c,v 1.12.2.1 2001/02/15 10:12:48 dwmw2 Exp $ -/* ###################################################################### - - Octagon 5066 MTD Driver. - - The Octagon 5066 is a SBC based on AMD's 586-WB running at 133 MHZ. It - comes with a builtin AMD 29F016 flash chip and a socketed EEPROM that - is replacable by flash. Both units are mapped through a multiplexer - into a 32k memory window at 0xe8000. The control register for the - multiplexing unit is located at IO 0x208 with a bit map of - 0-5 Page Selection in 32k increments - 6-7 Device selection: - 00 SSD off - 01 SSD 0 (Socket) - 10 SSD 1 (Flash chip) - 11 undefined - - On each SSD, the first 128k is reserved for use by the bios - (actually it IS the bios..) This only matters if you are booting off the - flash, you must not put a file system starting there. - - The driver tries to do a detection algorithm to guess what sort of devices - are plugged into the sockets. - - ##################################################################### */ - -#include -#include -#include -#include -#include - -#include - -#define WINDOW_START 0xe8000 -#define WINDOW_LENGTH 0x8000 -#define WINDOW_SHIFT 27 -#define WINDOW_MASK 0x7FFF -#define PAGE_IO 0x208 - -static volatile char page_n_dev = 0; -static unsigned long iomapadr; -static spinlock_t oct5066_spin = SPIN_LOCK_UNLOCKED; - -/* - * We use map_priv_1 to identify which device we are. - */ - -static void __oct5066_page(struct map_info *map, __u8 byte) -{ - outb(byte,PAGE_IO); - page_n_dev = byte; -} - -static inline void oct5066_page(struct map_info *map, unsigned long ofs) -{ - __u8 byte = map->map_priv_1 | (ofs >> WINDOW_SHIFT); - - if (page_n_dev != byte) - __oct5066_page(map, byte); -} - - -static __u8 oct5066_read8(struct map_info *map, unsigned long ofs) -{ - __u8 ret; - spin_lock(&oct5066_spin); - oct5066_page(map, ofs); - ret = readb(iomapadr + (ofs & WINDOW_MASK)); - spin_unlock(&oct5066_spin); - return ret; -} - -static __u16 oct5066_read16(struct map_info *map, unsigned long ofs) -{ - __u16 ret; - spin_lock(&oct5066_spin); - oct5066_page(map, ofs); - ret = readw(iomapadr + (ofs & WINDOW_MASK)); - spin_unlock(&oct5066_spin); - return ret; -} - -static __u32 oct5066_read32(struct map_info *map, unsigned long ofs) -{ - __u32 ret; - spin_lock(&oct5066_spin); - oct5066_page(map, ofs); - ret = readl(iomapadr + (ofs & WINDOW_MASK)); - spin_unlock(&oct5066_spin); - return ret; -} - -static void oct5066_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) -{ - while(len) { - unsigned long thislen = len; - if (len > (WINDOW_LENGTH - (from & WINDOW_MASK))) - thislen = WINDOW_LENGTH-(from & WINDOW_MASK); - - spin_lock(&oct5066_spin); - oct5066_page(map, from); - memcpy_fromio(to, iomapadr + from, thislen); - spin_unlock(&oct5066_spin); - to += thislen; - from += thislen; - len -= thislen; - } -} - -static void oct5066_write8(struct map_info *map, __u8 d, unsigned long adr) -{ - spin_lock(&oct5066_spin); - oct5066_page(map, adr); - writeb(d, iomapadr + (adr & WINDOW_MASK)); - spin_unlock(&oct5066_spin); -} - -static void oct5066_write16(struct map_info *map, __u16 d, unsigned long adr) -{ - spin_lock(&oct5066_spin); - oct5066_page(map, adr); - writew(d, iomapadr + (adr & WINDOW_MASK)); - spin_unlock(&oct5066_spin); -} - -static void oct5066_write32(struct map_info *map, __u32 d, unsigned long adr) -{ - spin_lock(&oct5066_spin); - oct5066_page(map, adr); - writel(d, iomapadr + (adr & WINDOW_MASK)); - spin_unlock(&oct5066_spin); -} - -static void oct5066_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) -{ - while(len) { - unsigned long thislen = len; - if (len > (WINDOW_LENGTH - (to & WINDOW_MASK))) - thislen = WINDOW_LENGTH-(to & WINDOW_MASK); - - spin_lock(&oct5066_spin); - oct5066_page(map, to); - memcpy_toio(iomapadr + to, from, thislen); - spin_unlock(&oct5066_spin); - to += thislen; - from += thislen; - len -= thislen; - } -} - -static struct map_info oct5066_map[2] = { - { - name: "Octagon 5066 Socket", - size: 512 * 1024, - buswidth: 1, - read8: oct5066_read8, - read16: oct5066_read16, - read32: oct5066_read32, - copy_from: oct5066_copy_from, - write8: oct5066_write8, - write16: oct5066_write16, - write32: oct5066_write32, - copy_to: oct5066_copy_to, - map_priv_1: 1<<6 - }, - { - name: "Octagon 5066 Internal Flash", - size: 2 * 1024 * 1024, - buswidth: 1, - read8: oct5066_read8, - read16: oct5066_read16, - read32: oct5066_read32, - copy_from: oct5066_copy_from, - write8: oct5066_write8, - write16: oct5066_write16, - write32: oct5066_write32, - copy_to: oct5066_copy_to, - map_priv_1: 2<<6 - } -}; - -static struct mtd_info *oct5066_mtd[2] = {NULL, NULL}; - -// OctProbe - Sense if this is an octagon card -// --------------------------------------------------------------------- -/* Perform a simple validity test, we map the window select SSD0 and - change pages while monitoring the window. A change in the window, - controlled by the PAGE_IO port is a functioning 5066 board. This will - fail if the thing in the socket is set to a uniform value. */ -static int __init OctProbe() -{ - unsigned int Base = (1 << 6); - unsigned long I; - unsigned long Values[10]; - for (I = 0; I != 20; I++) - { - outb(Base + (I%10),PAGE_IO); - if (I < 10) - { - // Record the value and check for uniqueness - Values[I%10] = readl(iomapadr); - if (I > 0 && Values[I%10] == Values[0]) - return -EAGAIN; - } - else - { - // Make sure we get the same values on the second pass - if (Values[I%10] != readl(iomapadr)) - return -EAGAIN; - } - } - return 0; -} - -#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) -#define init_oct5066 init_module -#define cleanup_oct5066 cleanup_module -#endif - -void cleanup_oct5066(void) -{ - int i; - for (i=0; i<2; i++) { - if (oct5066_mtd[i]) { - del_mtd_device(oct5066_mtd[i]); - map_destroy(oct5066_mtd[i]); - } - } - iounmap((void *)iomapadr); - release_region(PAGE_IO,1); -} - -int __init init_oct5066(void) -{ - int i; - - // Do an autoprobe sequence - if (check_region(PAGE_IO,1) != 0) - { - printk("5066: Page Register in Use\n"); - return -EAGAIN; - } - iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH); - if (!iomapadr) { - printk("Failed to ioremap memory region\n"); - return -EIO; - } - if (OctProbe() != 0) - { - printk("5066: Octagon Probe Failed, is this an Octagon 5066 SBC?\n"); - iounmap((void *)iomapadr); - return -EAGAIN; - } - - request_region(PAGE_IO,1,"Octagon SSD"); - - // Print out our little header.. - printk("Octagon 5066 SSD IO:0x%x MEM:0x%x-0x%x\n",PAGE_IO,WINDOW_START, - WINDOW_START+WINDOW_LENGTH); - - for (i=0; i<2; i++) { - oct5066_mtd[i] = do_cfi_probe(&oct5066_map[i]); - if (!oct5066_mtd[i]) - oct5066_mtd[i] = do_jedec_probe(&oct5066_map[i]); - if (!oct5066_mtd[i]) - oct5066_mtd[i] = do_ram_probe(&oct5066_map[i]); - if (!oct5066_mtd[i]) - oct5066_mtd[i] = do_rom_probe(&oct5066_map[i]); - if (oct5066_mtd[i]) { - oct5066_mtd[i]->module = THIS_MODULE; - add_mtd_device(oct5066_mtd[i]); - } - } - - if (!oct5066_mtd[0] && !oct5066_mtd[1]) { - cleanup_oct5066(); - return -ENXIO; - } - - return 0; -} - -module_init(init_oct5066); -module_exit(cleanup_oct5066); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/physmap.c linux/drivers/mtd/physmap.c --- v2.4.5/linux/drivers/mtd/physmap.c Mon Dec 11 14:57:58 2000 +++ linux/drivers/mtd/physmap.c Wed Dec 31 16:00:00 1969 @@ -1,117 +0,0 @@ -/* - * $Id: physmap.c,v 1.8 2000/11/27 08:50:22 dwmw2 Exp $ - * - * Normal mappings of chips in physical memory - */ - -#include -#include -#include -#include -#include -#include -#include - - -#define WINDOW_ADDR CONFIG_MTD_PHYSMAP_START -#define WINDOW_SIZE CONFIG_MTD_PHYSMAP_LEN -#define BUSWIDTH CONFIG_MTD_PHYSMAP_BUSWIDTH - -static struct mtd_info *mymtd; - -__u8 physmap_read8(struct map_info *map, unsigned long ofs) -{ - return readb(map->map_priv_1 + ofs); -} - -__u16 physmap_read16(struct map_info *map, unsigned long ofs) -{ - return readw(map->map_priv_1 + ofs); -} - -__u32 physmap_read32(struct map_info *map, unsigned long ofs) -{ - return readl(map->map_priv_1 + ofs); -} - -void physmap_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) -{ - memcpy_fromio(to, map->map_priv_1 + from, len); -} - -void physmap_write8(struct map_info *map, __u8 d, unsigned long adr) -{ - writeb(d, map->map_priv_1 + adr); -} - -void physmap_write16(struct map_info *map, __u16 d, unsigned long adr) -{ - writew(d, map->map_priv_1 + adr); -} - -void physmap_write32(struct map_info *map, __u32 d, unsigned long adr) -{ - writel(d, map->map_priv_1 + adr); -} - -void physmap_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) -{ - memcpy_toio(map->map_priv_1 + to, from, len); -} - -struct map_info physmap_map = { - name: "Physically mapped flash", - size: WINDOW_SIZE, - buswidth: BUSWIDTH, - read8: physmap_read8, - read16: physmap_read16, - read32: physmap_read32, - copy_from: physmap_copy_from, - write8: physmap_write8, - write16: physmap_write16, - write32: physmap_write32, - copy_to: physmap_copy_to -}; - -#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) -#define init_physmap init_module -#define cleanup_physmap cleanup_module -#endif - -int __init init_physmap(void) -{ - printk(KERN_NOTICE "physmap flash device: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR); - physmap_map.map_priv_1 = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); - - if (!physmap_map.map_priv_1) { - printk("Failed to ioremap\n"); - return -EIO; - } - mymtd = do_cfi_probe(&physmap_map); - if (mymtd) { -#ifdef MODULE - mymtd->module = &__this_module; -#endif - add_mtd_device(mymtd); - return 0; - } - - iounmap((void *)physmap_map.map_priv_1); - return -ENXIO; -} - -static void __exit cleanup_physmap(void) -{ - if (mymtd) { - del_mtd_device(mymtd); - map_destroy(mymtd); - } - if (physmap_map.map_priv_1) { - iounmap((void *)physmap_map.map_priv_1); - physmap_map.map_priv_1 = 0; - } -} - -module_init(init_physmap); -module_exit(cleanup_physmap); - diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/pmc551.c linux/drivers/mtd/pmc551.c --- v2.4.5/linux/drivers/mtd/pmc551.c Fri Apr 6 10:42:55 2001 +++ linux/drivers/mtd/pmc551.c Wed Dec 31 16:00:00 1969 @@ -1,863 +0,0 @@ -/* - * $Id: pmc551.c,v 1.11 2000/11/23 13:40:12 dwmw2 Exp $ - * - * PMC551 PCI Mezzanine Ram Device - * - * Author: - * Mark Ferrell - * Copyright 1999,2000 Nortel Networks - * - * License: - * As part of this driver was derrived from the slram.c driver it falls - * under the same license, which is GNU General Public License v2 - * - * Description: - * This driver is intended to support the PMC551 PCI Ram device from - * Ramix Inc. The PMC551 is a PMC Mezzanine module for cPCI embedded - * systems. The device contains a single SROM that initally programs the - * V370PDC chipset onboard the device, and various banks of DRAM/SDRAM - * onboard. This driver implements this PCI Ram device as an MTD (Memory - * Technologies Device) so that it can be used to hold a filesystem, or - * for added swap space in embedded systems. Since the memory on this - * board isn't as fast as main memory we do not try to hook it into main - * memeory as that would simply reduce performance on the system. Using - * it as a block device allows us to use it as high speed swap or for a - * high speed disk device of some sort. Which becomes very useful on - * diskless systems in the embedded market I might add. - * - * Notes: - * Due to what I assume is more buggy SROM, the 64M PMC551 I have - * available claims that all 4 of it's DRAM banks have 64M of ram - * configured (making a grand total of 256M onboard). This is slightly - * annoying since the BAR0 size reflects the aperture size, not the dram - * size, and the V370PDC supplies no other method for memory size - * discovery. This problem is mostly only relivant when compiled as a - * module, as the unloading of the module with an aperture size smaller - * then the ram will cause the driver to detect the onboard memory size - * to be equal to the aperture size when the module is reloaded. Soooo, - * to help, the module supports an msize option to allow the - * specification of the onboard memory, and an asize option, to allow the - * specification of the aperture size. The aperture must be equal to or - * less then the memory size, the driver will correct this if you screw - * it up. This problem is not relivant for compiled in drivers as - * compiled in drivers only init once. - * - * Credits: - * Saeed Karamooz of Ramix INC. for the initial - * example code of how to initialize this device and for help with - * questions I had concerning operation of the device. - * - * Most of the MTD code for this driver was originally written for the - * slram.o module in the MTD drivers package written by David Hinds - * which allows the mapping of system - * memory into an mtd device. Since the PMC551 memory module is - * accessed in the same fashion as system memory, the slram.c code - * became a very nice fit to the needs of this driver. All we added was - * PCI detection/initialization to the driver and automaticly figure out - * the size via the PCI detection.o, later changes by Corey Minyard - * settup the card to utilize a 1M sliding apature. - * - * Corey Minyard - * * Modified driver to utilize a sliding apature instead of mapping all - * memory into kernel space which turned out to be very wastefull. - * * Located a bug in the SROM's initialization sequence that made the - * memory unusable, added a fix to code to touch up the DRAM some. - * - * Bugs/FIXME's: - * * MUST fix the init function to not spin on a register - * waiting for it to set .. this does not safely handle busted devices - * that never reset the register correctly which will cause the system to - * hang w/ a reboot beeing the only chance at recover. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef CONFIG_PCI -#error Enable PCI in your kernel config -#endif - -#include -#include -#include - -#if LINUX_VERSION_CODE > 0x20300 -#define PCI_BASE_ADDRESS(dev) (dev->resource[0].start) -#else -#define PCI_BASE_ADDRESS(dev) (dev->base_address[0]) -#endif - -static struct mtd_info *pmc551list = NULL; - -static int pmc551_erase (struct mtd_info *mtd, struct erase_info *instr) -{ - struct mypriv *priv = mtd->priv; - u32 start_addr_highbits; - u32 end_addr_highbits; - u32 start_addr_lowbits; - u32 end_addr_lowbits; - unsigned long end; - - end = instr->addr + instr->len; - - /* Is it too much memory? The second check find if we wrap around - past the end of a u32. */ - if ((end > mtd->size) || (end < instr->addr)) { - return -EINVAL; - } - - start_addr_highbits = instr->addr & PMC551_ADDR_HIGH_MASK; - end_addr_highbits = end & PMC551_ADDR_HIGH_MASK; - start_addr_lowbits = instr->addr & PMC551_ADDR_LOW_MASK; - end_addr_lowbits = end & PMC551_ADDR_LOW_MASK; - - pci_write_config_dword ( priv->dev, - PMC551_PCI_MEM_MAP0, - (priv->mem_map0_base_val - | start_addr_highbits)); - if (start_addr_highbits == end_addr_highbits) { - /* The whole thing fits within one access, so just one shot - will do it. */ - memset(priv->start + start_addr_lowbits, - 0xff, - instr->len); - } else { - /* We have to do multiple writes to get all the data - written. */ - memset(priv->start + start_addr_lowbits, - 0xff, - priv->aperture_size - start_addr_lowbits); - start_addr_highbits += priv->aperture_size; - while (start_addr_highbits != end_addr_highbits) { - pci_write_config_dword ( priv->dev, - PMC551_PCI_MEM_MAP0, - (priv->mem_map0_base_val - | start_addr_highbits)); - memset(priv->start, - 0xff, - priv->aperture_size); - start_addr_highbits += priv->aperture_size; - } - priv->curr_mem_map0_val = (priv->mem_map0_base_val - | start_addr_highbits); - pci_write_config_dword ( priv->dev, - PMC551_PCI_MEM_MAP0, - priv->curr_mem_map0_val); - memset(priv->start, - 0xff, - end_addr_lowbits); - } - - instr->state = MTD_ERASE_DONE; - - if (instr->callback) { - (*(instr->callback))(instr); - } - - return 0; -} - - -static void pmc551_unpoint (struct mtd_info *mtd, u_char *addr) -{} - - -static int pmc551_read (struct mtd_info *mtd, - loff_t from, - size_t len, - size_t *retlen, - u_char *buf) -{ - struct mypriv *priv = (struct mypriv *)mtd->priv; - u32 start_addr_highbits; - u32 end_addr_highbits; - u32 start_addr_lowbits; - u32 end_addr_lowbits; - unsigned long end; - u_char *copyto = buf; - - - /* Is it past the end? */ - if (from > mtd->size) { - return -EINVAL; - } - - end = from + len; - start_addr_highbits = from & PMC551_ADDR_HIGH_MASK; - end_addr_highbits = end & PMC551_ADDR_HIGH_MASK; - start_addr_lowbits = from & PMC551_ADDR_LOW_MASK; - end_addr_lowbits = end & PMC551_ADDR_LOW_MASK; - - - /* Only rewrite the first value if it doesn't match our current - values. Most operations are on the same page as the previous - value, so this is a pretty good optimization. */ - if (priv->curr_mem_map0_val != - (priv->mem_map0_base_val | start_addr_highbits)) { - priv->curr_mem_map0_val = (priv->mem_map0_base_val - | start_addr_highbits); - pci_write_config_dword ( priv->dev, - PMC551_PCI_MEM_MAP0, - priv->curr_mem_map0_val); - } - - if (start_addr_highbits == end_addr_highbits) { - /* The whole thing fits within one access, so just one shot - will do it. */ - memcpy(copyto, - priv->start + start_addr_lowbits, - len); - copyto += len; - } else { - /* We have to do multiple writes to get all the data - written. */ - memcpy(copyto, - priv->start + start_addr_lowbits, - priv->aperture_size - start_addr_lowbits); - copyto += priv->aperture_size - start_addr_lowbits; - start_addr_highbits += priv->aperture_size; - while (start_addr_highbits != end_addr_highbits) { - pci_write_config_dword ( priv->dev, - PMC551_PCI_MEM_MAP0, - (priv->mem_map0_base_val - | start_addr_highbits)); - memcpy(copyto, - priv->start, - priv->aperture_size); - copyto += priv->aperture_size; - start_addr_highbits += priv->aperture_size; - if (start_addr_highbits >= mtd->size) { - /* Make sure we have the right value here. */ - priv->curr_mem_map0_val - = (priv->mem_map0_base_val - | start_addr_highbits); - goto out; - } - } - priv->curr_mem_map0_val = (priv->mem_map0_base_val - | start_addr_highbits); - pci_write_config_dword ( priv->dev, - PMC551_PCI_MEM_MAP0, - priv->curr_mem_map0_val); - memcpy(copyto, - priv->start, - end_addr_lowbits); - copyto += end_addr_lowbits; - } - -out: - *retlen = copyto - buf; - return 0; -} - -static int pmc551_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) -{ - struct mypriv *priv = (struct mypriv *)mtd->priv; - u32 start_addr_highbits; - u32 end_addr_highbits; - u32 start_addr_lowbits; - u32 end_addr_lowbits; - unsigned long end; - const u_char *copyfrom = buf; - - - /* Is it past the end? */ - if (to > mtd->size) { - return -EINVAL; - } - - end = to + len; - start_addr_highbits = to & PMC551_ADDR_HIGH_MASK; - end_addr_highbits = end & PMC551_ADDR_HIGH_MASK; - start_addr_lowbits = to & PMC551_ADDR_LOW_MASK; - end_addr_lowbits = end & PMC551_ADDR_LOW_MASK; - - - /* Only rewrite the first value if it doesn't match our current - values. Most operations are on the same page as the previous - value, so this is a pretty good optimization. */ - if (priv->curr_mem_map0_val != - (priv->mem_map0_base_val | start_addr_highbits)) { - priv->curr_mem_map0_val = (priv->mem_map0_base_val - | start_addr_highbits); - pci_write_config_dword ( priv->dev, - PMC551_PCI_MEM_MAP0, - priv->curr_mem_map0_val); - } - - if (start_addr_highbits == end_addr_highbits) { - /* The whole thing fits within one access, so just one shot - will do it. */ - memcpy(priv->start + start_addr_lowbits, - copyfrom, - len); - copyfrom += len; - } else { - /* We have to do multiple writes to get all the data - written. */ - memcpy(priv->start + start_addr_lowbits, - copyfrom, - priv->aperture_size - start_addr_lowbits); - copyfrom += priv->aperture_size - start_addr_lowbits; - start_addr_highbits += priv->aperture_size; - while (start_addr_highbits != end_addr_highbits) { - pci_write_config_dword ( priv->dev, - PMC551_PCI_MEM_MAP0, - (priv->mem_map0_base_val - | start_addr_highbits)); - memcpy(priv->start, - copyfrom, - priv->aperture_size); - copyfrom += priv->aperture_size; - start_addr_highbits += priv->aperture_size; - if (start_addr_highbits >= mtd->size) { - /* Make sure we have the right value here. */ - priv->curr_mem_map0_val - = (priv->mem_map0_base_val - | start_addr_highbits); - goto out; - } - } - priv->curr_mem_map0_val = (priv->mem_map0_base_val - | start_addr_highbits); - pci_write_config_dword ( priv->dev, - PMC551_PCI_MEM_MAP0, - priv->curr_mem_map0_val); - memcpy(priv->start, - copyfrom, - end_addr_lowbits); - copyfrom += end_addr_lowbits; - } - -out: - *retlen = copyfrom - buf; - return 0; -} - -/* - * Fixup routines for the V370PDC - * PCI device ID 0x020011b0 - * - * This function basicly kick starts the DRAM oboard the card and gets it - * ready to be used. Before this is done the device reads VERY erratic, so - * much that it can crash the Linux 2.2.x series kernels when a user cat's - * /proc/pci .. though that is mainly a kernel bug in handling the PCI DEVSEL - * register. FIXME: stop spinning on registers .. must implement a timeout - * mechanism - * returns the size of the memory region found. - */ -static u32 fixup_pmc551 (struct pci_dev *dev) -{ -#ifdef CONFIG_MTD_PMC551_BUGFIX - u32 dram_data; -#endif - u32 size, dcmd, cfg, dtmp; - u16 cmd, tmp, i; - u8 bcmd, counter; - - /* Sanity Check */ - if(!dev) { - return -ENODEV; - } - - /* - * Attempt to reset the card - * FIXME: Stop Spinning registers - */ - counter=0; - /* unlock registers */ - pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, 0xA5 ); - /* read in old data */ - pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd ); - /* bang the reset line up and down for a few */ - for(i=0;i<10;i++) { - counter=0; - bcmd &= ~0x80; - while(counter++ < 100) { - pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd); - } - counter=0; - bcmd |= 0x80; - while(counter++ < 100) { - pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd); - } - } - bcmd |= (0x40|0x20); - pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd); - - /* - * Take care and turn off the memory on the device while we - * tweak the configurations - */ - pci_read_config_word(dev, PCI_COMMAND, &cmd); - tmp = cmd & ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY); - pci_write_config_word(dev, PCI_COMMAND, tmp); - - /* - * Disable existing aperture before probing memory size - */ - pci_read_config_dword(dev, PMC551_PCI_MEM_MAP0, &dcmd); - dtmp=(dcmd|PMC551_PCI_MEM_MAP_ENABLE|PMC551_PCI_MEM_MAP_REG_EN); - pci_write_config_dword(dev, PMC551_PCI_MEM_MAP0, dtmp); - /* - * Grab old BAR0 config so that we can figure out memory size - * This is another bit of kludge going on. The reason for the - * redundancy is I am hoping to retain the original configuration - * previously assigned to the card by the BIOS or some previous - * fixup routine in the kernel. So we read the old config into cfg, - * then write all 1's to the memory space, read back the result into - * "size", and then write back all the old config. - */ - pci_read_config_dword( dev, PCI_BASE_ADDRESS_0, &cfg ); -#ifndef CONFIG_MTD_PMC551_BUGFIX - pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, ~0 ); - pci_read_config_dword( dev, PCI_BASE_ADDRESS_0, &size ); - pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg ); - size=~(size&PCI_BASE_ADDRESS_MEM_MASK)+1; -#else - /* - * Get the size of the memory by reading all the DRAM size values - * and adding them up. - * - * KLUDGE ALERT: the boards we are using have invalid column and - * row mux values. We fix them here, but this will break other - * memory configurations. - */ - pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dram_data); - size = PMC551_DRAM_BLK_GET_SIZE(dram_data); - dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); - dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); - pci_write_config_dword(dev, PMC551_DRAM_BLK0, dram_data); - - pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dram_data); - size += PMC551_DRAM_BLK_GET_SIZE(dram_data); - dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); - dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); - pci_write_config_dword(dev, PMC551_DRAM_BLK1, dram_data); - - pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dram_data); - size += PMC551_DRAM_BLK_GET_SIZE(dram_data); - dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); - dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); - pci_write_config_dword(dev, PMC551_DRAM_BLK2, dram_data); - - pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dram_data); - size += PMC551_DRAM_BLK_GET_SIZE(dram_data); - dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); - dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); - pci_write_config_dword(dev, PMC551_DRAM_BLK3, dram_data); - - /* - * Oops .. something went wrong - */ - if( (size &= PCI_BASE_ADDRESS_MEM_MASK) == 0) { - return -ENODEV; - } -#endif /* CONFIG_MTD_PMC551_BUGFIX */ - - if ((cfg&PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) { - return -ENODEV; - } - - /* - * Precharge Dram - */ - pci_write_config_word( dev, PMC551_SDRAM_MA, 0x0400 ); - pci_write_config_word( dev, PMC551_SDRAM_CMD, 0x00bf ); - - /* - * Wait until command has gone through - * FIXME: register spinning issue - */ - do { pci_read_config_word( dev, PMC551_SDRAM_CMD, &cmd ); - if(counter++ > 100)break; - } while ( (PCI_COMMAND_IO) & cmd ); - - /* - * Turn on auto refresh - * The loop is taken directly from Ramix's example code. I assume that - * this must be held high for some duration of time, but I can find no - * documentation refrencing the reasons why. - * - */ - for ( i = 1; i<=8 ; i++) { - pci_write_config_word (dev, PMC551_SDRAM_CMD, 0x0df); - - /* - * Make certain command has gone through - * FIXME: register spinning issue - */ - counter=0; - do { pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd); - if(counter++ > 100)break; - } while ( (PCI_COMMAND_IO) & cmd ); - } - - pci_write_config_word ( dev, PMC551_SDRAM_MA, 0x0020); - pci_write_config_word ( dev, PMC551_SDRAM_CMD, 0x0ff); - - /* - * Wait until command completes - * FIXME: register spinning issue - */ - counter=0; - do { pci_read_config_word ( dev, PMC551_SDRAM_CMD, &cmd); - if(counter++ > 100)break; - } while ( (PCI_COMMAND_IO) & cmd ); - - pci_read_config_dword ( dev, PMC551_DRAM_CFG, &dcmd); - dcmd |= 0x02000000; - pci_write_config_dword ( dev, PMC551_DRAM_CFG, dcmd); - - /* - * Check to make certain fast back-to-back, if not - * then set it so - */ - pci_read_config_word( dev, PCI_STATUS, &cmd); - if((cmd&PCI_COMMAND_FAST_BACK) == 0) { - cmd |= PCI_COMMAND_FAST_BACK; - pci_write_config_word( dev, PCI_STATUS, cmd); - } - - /* - * Check to make certain the DEVSEL is set correctly, this device - * has a tendancy to assert DEVSEL and TRDY when a write is performed - * to the memory when memory is read-only - */ - if((cmd&PCI_STATUS_DEVSEL_MASK) != 0x0) { - cmd &= ~PCI_STATUS_DEVSEL_MASK; - pci_write_config_word( dev, PCI_STATUS, cmd ); - } - /* - * Set to be prefetchable and put everything back based on old cfg. - * it's possible that the reset of the V370PDC nuked the original - * settup - */ - cfg |= PCI_BASE_ADDRESS_MEM_PREFETCH; - pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg ); - - /* - * Turn PCI memory and I/O bus access back on - */ - pci_write_config_word( dev, PCI_COMMAND, - PCI_COMMAND_MEMORY | PCI_COMMAND_IO ); -#ifdef CONFIG_MTD_PMC551_DEBUG - /* - * Some screen fun - */ - printk(KERN_DEBUG "pmc551: %d%c (0x%x) of %sprefetchable memory at 0x%lx\n", - (size<1024)?size:(size<1048576)?size/1024:size/1024/1024, - (size<1024)?'B':(size<1048576)?'K':'M', - size, ((dcmd&(0x1<<3)) == 0)?"non-":"", - PCI_BASE_ADDRESS(dev)&PCI_BASE_ADDRESS_MEM_MASK ); - - /* - * Check to see the state of the memory - */ - pci_read_config_dword( dev, PMC551_DRAM_BLK0, &dcmd ); - printk(KERN_DEBUG "pmc551: DRAM_BLK0 Flags: %s,%s\n" - "pmc551: DRAM_BLK0 Size: %d at %d\n" - "pmc551: DRAM_BLK0 Row MUX: %d, Col MUX: %d\n", - (((0x1<<1)&dcmd) == 0)?"RW":"RO", - (((0x1<<0)&dcmd) == 0)?"Off":"On", - PMC551_DRAM_BLK_GET_SIZE(dcmd), - ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) ); - - pci_read_config_dword( dev, PMC551_DRAM_BLK1, &dcmd ); - printk(KERN_DEBUG "pmc551: DRAM_BLK1 Flags: %s,%s\n" - "pmc551: DRAM_BLK1 Size: %d at %d\n" - "pmc551: DRAM_BLK1 Row MUX: %d, Col MUX: %d\n", - (((0x1<<1)&dcmd) == 0)?"RW":"RO", - (((0x1<<0)&dcmd) == 0)?"Off":"On", - PMC551_DRAM_BLK_GET_SIZE(dcmd), - ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) ); - - pci_read_config_dword( dev, PMC551_DRAM_BLK2, &dcmd ); - printk(KERN_DEBUG "pmc551: DRAM_BLK2 Flags: %s,%s\n" - "pmc551: DRAM_BLK2 Size: %d at %d\n" - "pmc551: DRAM_BLK2 Row MUX: %d, Col MUX: %d\n", - (((0x1<<1)&dcmd) == 0)?"RW":"RO", - (((0x1<<0)&dcmd) == 0)?"Off":"On", - PMC551_DRAM_BLK_GET_SIZE(dcmd), - ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) ); - - pci_read_config_dword( dev, PMC551_DRAM_BLK3, &dcmd ); - printk(KERN_DEBUG "pmc551: DRAM_BLK3 Flags: %s,%s\n" - "pmc551: DRAM_BLK3 Size: %d at %d\n" - "pmc551: DRAM_BLK3 Row MUX: %d, Col MUX: %d\n", - (((0x1<<1)&dcmd) == 0)?"RW":"RO", - (((0x1<<0)&dcmd) == 0)?"Off":"On", - PMC551_DRAM_BLK_GET_SIZE(dcmd), - ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) ); - - pci_read_config_word( dev, PCI_COMMAND, &cmd ); - printk( KERN_DEBUG "pmc551: Memory Access %s\n", - (((0x1<<1)&cmd) == 0)?"off":"on" ); - printk( KERN_DEBUG "pmc551: I/O Access %s\n", - (((0x1<<0)&cmd) == 0)?"off":"on" ); - - pci_read_config_word( dev, PCI_STATUS, &cmd ); - printk( KERN_DEBUG "pmc551: Devsel %s\n", - ((PCI_STATUS_DEVSEL_MASK&cmd)==0x000)?"Fast": - ((PCI_STATUS_DEVSEL_MASK&cmd)==0x200)?"Medium": - ((PCI_STATUS_DEVSEL_MASK&cmd)==0x400)?"Slow":"Invalid" ); - - printk( KERN_DEBUG "pmc551: %sFast Back-to-Back\n", - ((PCI_COMMAND_FAST_BACK&cmd) == 0)?"Not ":"" ); - - pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd ); - printk( KERN_DEBUG "pmc551: EEPROM is under %s control\n" - "pmc551: System Control Register is %slocked to PCI access\n" - "pmc551: System Control Register is %slocked to EEPROM access\n", - (bcmd&0x1)?"software":"hardware", - (bcmd&0x20)?"":"un", (bcmd&0x40)?"":"un"); -#endif - return size; -} - -/* - * Kernel version specific module stuffages - */ -#if LINUX_VERSION_CODE < 0x20211 -#ifdef MODULE -#define init_pmc551 init_module -#define cleanup_pmc551 cleanup_module -#endif -#define __exit -#endif - -#if defined(MODULE) -MODULE_AUTHOR("Mark Ferrell "); -MODULE_DESCRIPTION(PMC551_VERSION); -MODULE_PARM(msize, "i"); -MODULE_PARM_DESC(msize, "memory size, 6=32M, 7=64M, 8=128M, ect.. [32M-1024M]"); -MODULE_PARM(asize, "i"); -MODULE_PARM_DESC(asize, "aperture size, must be <= memsize [1M-1024M]"); -#endif -/* - * Stuff these outside the ifdef so as to not bust compiled in driver support - */ -static int msize=0; -#if defined(CONFIG_MTD_PMC551_APERTURE_SIZE) -static int asize=CONFIG_MTD_PMC551_APERTURE_SIZE -#else -static int asize=0; -#endif - -/* - * PMC551 Card Initialization - */ -int __init init_pmc551(void) -{ - struct pci_dev *PCI_Device = NULL; - struct mypriv *priv; - int count, found=0; - struct mtd_info *mtd; - u32 length = 0; - - if(msize) { - if (msize < 6 || msize > 11 ) { - printk(KERN_NOTICE "pmc551: Invalid memory size\n"); - return -ENODEV; - } - msize = (512*1024)< 11 ) { - printk(KERN_NOTICE "pmc551: Invalid aperture size\n"); - return -ENODEV; - } - asize = (512*1024)<irq); - - /* - * The PMC551 device acts VERY weird if you don't init it - * first. i.e. it will not correctly report devsel. If for - * some reason the sdram is in a wrote-protected state the - * device will DEVSEL when it is written to causing problems - * with the oldproc.c driver in - * some kernels (2.2.*) - */ - if((length = fixup_pmc551(PCI_Device)) <= 0) { - printk(KERN_NOTICE "pmc551: Cannot init SDRAM\n"); - break; - } - if(msize) { - length = msize; - printk(KERN_NOTICE "pmc551: Using specified memory size 0x%x\n", length); - } - - mtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL); - if (!mtd) { - printk(KERN_NOTICE "pmc551: Cannot allocate new MTD device.\n"); - break; - } - - memset(mtd, 0, sizeof(struct mtd_info)); - - priv = kmalloc (sizeof(struct mypriv), GFP_KERNEL); - if (!priv) { - printk(KERN_NOTICE "pmc551: Cannot allocate new MTD device.\n"); - kfree(mtd); - break; - } - memset(priv, 0, sizeof(*priv)); - mtd->priv = priv; - - priv->dev = PCI_Device; - if(asize) { - if(asize > length) { - asize=length; - printk(KERN_NOTICE "pmc551: reducing aperture size to fit memory [0x%x]\n",asize); - } else { - printk(KERN_NOTICE "pmc551: Using specified aperture size 0x%x\n", asize); - } - priv->aperture_size = asize; - } else { - priv->aperture_size = length; - } - priv->start = ioremap((PCI_BASE_ADDRESS(PCI_Device) - & PCI_BASE_ADDRESS_MEM_MASK), - priv->aperture_size); - - /* - * Due to the dynamic nature of the code, we need to figure - * this out in order to stuff the register to set the proper - * aperture size. If you know of an easier way to do this then - * PLEASE help yourself. - * - * Not with bloody floating point, you don't. Consider yourself - * duly LARTed. dwmw2. - */ - { - u32 size; - u16 bits; - size = priv->aperture_size>>20; - for(bits=0;!(size&0x01)&&size>0;bits++,size=size>>1); - //size=((u32)((log10(priv->aperture_size)/.30103)-19)<<4); - priv->mem_map0_base_val = (PMC551_PCI_MEM_MAP_REG_EN - | PMC551_PCI_MEM_MAP_ENABLE - | size); -#ifdef CONFIG_MTD_PMC551_DEBUG - printk(KERN_NOTICE "pmc551: aperture set to %d[%d]\n", - size, size>>4); -#endif - } - priv->curr_mem_map0_val = priv->mem_map0_base_val; - - pci_write_config_dword ( priv->dev, - PMC551_PCI_MEM_MAP0, - priv->curr_mem_map0_val); - - mtd->size = length; - mtd->flags = (MTD_CLEAR_BITS - | MTD_SET_BITS - | MTD_WRITEB_WRITEABLE - | MTD_VOLATILE); - mtd->erase = pmc551_erase; - mtd->point = NULL; - mtd->unpoint = pmc551_unpoint; - mtd->read = pmc551_read; - mtd->write = pmc551_write; - mtd->module = THIS_MODULE; - mtd->type = MTD_RAM; - mtd->name = "PMC551 RAM board"; - mtd->erasesize = 0x10000; - - if (add_mtd_device(mtd)) { - printk(KERN_NOTICE "pmc551: Failed to register new device\n"); - iounmap(priv->start); - kfree(mtd->priv); - kfree(mtd); - break; - } - printk(KERN_NOTICE "Registered pmc551 memory device.\n"); - printk(KERN_NOTICE "Mapped %dM of memory from 0x%p to 0x%p\n", - priv->aperture_size/1024/1024, - priv->start, - priv->start + priv->aperture_size); - printk(KERN_NOTICE "Total memory is %d%c\n", - (length<1024)?length: - (length<1048576)?length/1024:length/1024/1024, - (length<1024)?'B':(length<1048576)?'K':'M'); - priv->nextpmc551 = pmc551list; - pmc551list = mtd; - found++; - } - - if( !pmc551list ) { - printk(KERN_NOTICE "pmc551: not detected,\n"); - return -ENODEV; - } else { - printk(KERN_NOTICE "pmc551: %d pmc551 devices loaded\n", found); - return 0; - } -} - -/* - * PMC551 Card Cleanup - */ -static void __exit cleanup_pmc551(void) -{ - int found=0; - struct mtd_info *mtd; - struct mypriv *priv; - - while((mtd=pmc551list)) { - priv = (struct mypriv *)mtd->priv; - pmc551list = priv->nextpmc551; - - if(priv->start) - iounmap(((struct mypriv *)mtd->priv)->start); - - kfree (mtd->priv); - del_mtd_device(mtd); - kfree(mtd); - found++; - } - - printk(KERN_NOTICE "pmc551: %d pmc551 devices unloaded\n", found); -} - -#if LINUX_VERSION_CODE >= 0x20211 -module_init(init_pmc551); -module_exit(cleanup_pmc551); -#endif diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/pnc2000.c linux/drivers/mtd/pnc2000.c --- v2.4.5/linux/drivers/mtd/pnc2000.c Mon Dec 11 14:57:58 2000 +++ linux/drivers/mtd/pnc2000.c Wed Dec 31 16:00:00 1969 @@ -1,136 +0,0 @@ -/* - * pnc2000.c - mapper for Photron PNC-2000 board. - * - * Copyright (C) 2000 Crossnet Co. - * - * This code is GPL - * - * $Id: pnc2000.c,v 1.4 2000/11/27 08:50:22 dwmw2 Exp $ - */ - -#include -#include -#include - -#include -#include -#include - - -#define WINDOW_ADDR 0xbf000000 -#define WINDOW_SIZE 0x00400000 - -/* - * MAP DRIVER STUFF - */ - -__u8 pnc_read8(struct map_info *map, unsigned long ofs) -{ - return *(__u8 *)(WINDOW_ADDR + ofs); -} - -__u16 pnc_read16(struct map_info *map, unsigned long ofs) -{ - return *(__u16 *)(WINDOW_ADDR + ofs); -} - -__u32 pnc_read32(struct map_info *map, unsigned long ofs) -{ - return *(volatile unsigned int *)(WINDOW_ADDR + ofs); -} - -void pnc_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) -{ - memcpy(to, (void *)(WINDOW_ADDR + from), len); -} - -void pnc_write8(struct map_info *map, __u8 d, unsigned long adr) -{ - *(__u8 *)(WINDOW_ADDR + adr) = d; -} - -void pnc_write16(struct map_info *map, __u16 d, unsigned long adr) -{ - *(__u16 *)(WINDOW_ADDR + adr) = d; -} - -void pnc_write32(struct map_info *map, __u32 d, unsigned long adr) -{ - *(__u32 *)(WINDOW_ADDR + adr) = d; -} - -void pnc_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) -{ - memcpy((void *)(WINDOW_ADDR + to), from, len); -} - -struct map_info pnc_map = { - name: "PNC-2000", - size: WINDOW_SIZE, - buswidth: 4, - read8: pnc_read8, - read16: pnc_read16, - read32: pnc_read32, - copy_from: pnc_copy_from, - write8: pnc_write8, - write16: pnc_write16, - write32: pnc_write32, - copy_to: pnc_copy_to -}; - - -/* - * MTD 'PARTITIONING' STUFF - */ -static struct mtd_partition pnc_partitions[3] = { - { - name: "PNC-2000 boot firmware", - size: 0x20000, - offset: 0 - }, - { - name: "PNC-2000 kernel", - size: 0x1a0000, - offset: 0x20000 - }, - { - name: "PNC-2000 filesystem", - size: 0x240000, - offset: 0x1c0000 - } -}; - -/* - * This is the master MTD device for which all the others are just - * auto-relocating aliases. - */ -static struct mtd_info *mymtd; - -#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) -#define init_pnc init_module -#define cleanup_pnc cleanup_module -#endif - -int __init init_pnc(void) -{ - printk(KERN_NOTICE "Photron PNC-2000 flash mapping: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR); - - mymtd = do_cfi_probe(&pnc_map); - if (mymtd) { - mymtd->module = THIS_MODULE; - return add_mtd_partitions(mymtd, pnc_partitions, 3); - } - - return -ENXIO; -} - -static void __exit cleanup_pnc(void) -{ - if (mymtd) { - del_mtd_partitions(mymtd); - map_destroy(mymtd); - } -} - -module_init(init_pnc); -module_exit(cleanup_pnc); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/redboot.c linux/drivers/mtd/redboot.c --- v2.4.5/linux/drivers/mtd/redboot.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/redboot.c Tue Jun 12 10:30:27 2001 @@ -0,0 +1,150 @@ +/* + * $Id: redboot.c,v 1.4 2001/05/31 20:43:18 dwmw2 Exp $ + * + * Parse RedBoot-style Flash Image System (FIS) tables and + * produce a Linux partition array to match. + */ + +#include +#include + +#include +#include + +struct fis_image_desc { + unsigned char name[16]; // Null terminated name + unsigned long flash_base; // Address within FLASH of image + unsigned long mem_base; // Address in memory where it executes + unsigned long size; // Length of image + unsigned long entry_point; // Execution entry point + unsigned long data_length; // Length of actual data + unsigned char _pad[256-(16+7*sizeof(unsigned long))]; + unsigned long desc_cksum; // Checksum over image descriptor + unsigned long file_cksum; // Checksum over image data +}; + +struct fis_list { + struct fis_image_desc *img; + struct fis_list *next; +}; + +static inline int redboot_checksum(struct fis_image_desc *img) +{ + /* RedBoot doesn't actually write the desc_cksum field yet AFAICT */ + return 1; +} + +int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts) +{ + int nrparts = 0; + struct fis_image_desc *buf; + struct mtd_partition *parts; + struct fis_list *fl = NULL, *tmp_fl; + int ret, i; + size_t retlen; + char *names; + int namelen = 0; + + buf = kmalloc(PAGE_SIZE, GFP_KERNEL); + + if (!buf) + return -ENOMEM; + + /* Read the start of the last erase block */ + ret = master->read(master, master->size - master->erasesize, + PAGE_SIZE, &retlen, (void *)buf); + + if (ret) + goto out; + + if (retlen != PAGE_SIZE) { + ret = -EIO; + goto out; + } + + if (memcmp(buf, "RedBoot", 8)) { + ret = 0; + goto out; + } + + for (i = 0; i < PAGE_SIZE / sizeof(struct fis_image_desc); i++) { + struct fis_list *new_fl, **prev; + + if (buf[i].name[0] == 0xff) + break; + if (!redboot_checksum(&buf[i])) + break; + + new_fl = kmalloc(sizeof(struct fis_list), GFP_KERNEL); + namelen += strlen(buf[i].name)+1; + if (!new_fl) { + ret = -ENOMEM; + goto out; + } + new_fl->img = &buf[i]; + buf[i].flash_base &= master->size-1; + + /* I'm sure the JFFS2 code has done me permanent damage. + * I now think the following is _normal_ + */ + prev = &fl; + while(*prev && (*prev)->img->flash_base < new_fl->img->flash_base) + prev = &(*prev)->next; + new_fl->next = *prev; + *prev = new_fl; + + nrparts++; + } + if (fl->img->flash_base) + nrparts++; + + for (tmp_fl = fl; tmp_fl->next; tmp_fl = tmp_fl->next) { + if (tmp_fl->img->flash_base + tmp_fl->img->size + master->erasesize < tmp_fl->next->img->flash_base) + nrparts++; + } + parts = kmalloc(sizeof(*parts)*nrparts + namelen, GFP_KERNEL); + + if (!parts) { + ret = -ENOMEM; + goto out; + } + names = (char *)&parts[nrparts]; + memset(parts, 0, sizeof(*parts)*nrparts + namelen); + i=0; + + if (fl->img->flash_base) { + parts[0].name = "unallocated space"; + parts[0].size = fl->img->flash_base; + parts[0].offset = 0; + } + for ( ; iimg->size; + parts[i].offset = fl->img->flash_base; + parts[i].name = names; + + strcpy(names, fl->img->name); + names += strlen(names)+1; + + if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize < fl->next->img->flash_base) { + i++; + parts[i].offset = parts[i-1].size + parts[i-1].offset; + parts[i].size = fl->next->img->flash_base - parts[i].offset; + parts[i].name = "unallocated space"; + } + tmp_fl = fl; + fl = fl->next; + kfree(tmp_fl); + } + ret = nrparts; + *pparts = parts; + out: + while (fl) { + struct fis_list *old = fl; + fl = fl->next; + kfree(old); + } + kfree(buf); + return ret; +} + +EXPORT_SYMBOL(parse_redboot_partitions); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/rpxlite.c linux/drivers/mtd/rpxlite.c --- v2.4.5/linux/drivers/mtd/rpxlite.c Sun Feb 4 10:05:30 2001 +++ linux/drivers/mtd/rpxlite.c Wed Dec 31 16:00:00 1969 @@ -1,114 +0,0 @@ -/* - * $Id: rpxlite.c,v 1.8 2000/12/09 22:00:31 dwmw2 Exp $ - * - * Handle mapping of the flash on the RPX Lite and CLLF boards - */ - -#include -#include -#include -#include -#include -#include - - -#define WINDOW_ADDR 0xfe000000 -#define WINDOW_SIZE 0x800000 - -static struct mtd_info *mymtd; - -__u8 rpxlite_read8(struct map_info *map, unsigned long ofs) -{ - return readb(map->map_priv_1 * ofs); -} - -__u16 rpxlite_read16(struct map_info *map, unsigned long ofs) -{ - return readw(map->map_priv_1 + ofs); -} - -__u32 rpxlite_read32(struct map_info *map, unsigned long ofs) -{ - return readl(map->map_priv_1 + ofs); -} - -void rpxlite_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) -{ - memcpy_fromio(to, (void *)(map->map_priv_1 + from), len); -} - -void rpxlite_write8(struct map_info *map, __u8 d, unsigned long adr) -{ - writeb(d, map->map_priv_1 + adr); -} - -void rpxlite_write16(struct map_info *map, __u16 d, unsigned long adr) -{ - writew(d, map->map_priv_1 + adr); -} - -void rpxlite_write32(struct map_info *map, __u32 d, unsigned long adr) -{ - writel(d, map->map_priv_1 + adr); -} - -void rpxlite_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) -{ - memcpy_toio((void *)(map->map_priv_1 + to), from, len); -} - -struct map_info rpxlite_map = { - name: "RPX", - size: WINDOW_SIZE, - buswidth: 4, - read8: rpxlite_read8, - read16: rpxlite_read16, - read32: rpxlite_read32, - copy_from: rpxlite_copy_from, - write8: rpxlite_write8, - write16: rpxlite_write16, - write32: rpxlite_write32, - copy_to: rpxlite_copy_to -}; - -#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) -#define init_rpxlite init_module -#define cleanup_rpxlite cleanup_module -#endif - -int __init init_rpxlite(void) -{ - printk(KERN_NOTICE "RPX Lite or CLLF flash device: %x at %x\n", WINDOW_SIZE*4, WINDOW_ADDR); - rpxlite_map.map_priv_1 = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE * 4); - - if (!rpxlite_map.map_priv_1) { - printk("Failed to ioremap\n"); - return -EIO; - } - mymtd = do_cfi_probe(&rpxlite_map); - if (mymtd) { -#ifdef MODULE - mymtd->module = &__this_module; -#endif - add_mtd_device(mymtd); - return 0; - } - - iounmap((void *)rpxlite_map.map_priv_1); - return -ENXIO; -} - -static void __exit cleanup_rpxlite(void) -{ - if (mymtd) { - del_mtd_device(mymtd); - map_destroy(mymtd); - } - if (rpxlite_map.map_priv_1) { - iounmap((void *)rpxlite_map.map_priv_1); - rpxlite_map.map_priv_1 = 0; - } -} - -module_init(init_rpxlite); -module_exit(cleanup_rpxlite); diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/slram.c linux/drivers/mtd/slram.c --- v2.4.5/linux/drivers/mtd/slram.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/mtd/slram.c Wed Dec 31 16:00:00 1969 @@ -1,227 +0,0 @@ -/*====================================================================== - - $Id: slram.c,v 1.10 2000/07/03 10:01:38 dwmw2 Exp $ - -======================================================================*/ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -struct mypriv { - u_char *start; - u_char *end; -}; - -int physmem_erase (struct mtd_info *mtd, struct erase_info *instr); -int physmem_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf); -void physmem_unpoint (struct mtd_info *mtd, u_char *addr); -int physmem_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); -int physmem_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); - - -int physmem_erase (struct mtd_info *mtd, struct erase_info *instr) -{ - struct mypriv *priv = mtd->priv; - - if (instr->addr + instr->len > mtd->size) - return -EINVAL; - - memset(priv->start + instr->addr, 0xff, instr->len); - - /* This'll catch a few races. Free the thing before returning :) - * I don't feel at all ashamed. This kind of thing is possible anyway - * with flash, but unlikely. - */ - - instr->state = MTD_ERASE_DONE; - - if (instr->callback) - (*(instr->callback))(instr); - else - kfree(instr); - - return 0; -} - - -int physmem_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf) -{ - struct mypriv *priv = (struct mypriv *)mtd->priv; - - *mtdbuf = priv->start + from; - *retlen = len; - return 0; -} - -void physmem_unpoint (struct mtd_info *mtd, u_char *addr) -{ -} - -int physmem_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) -{ - struct mypriv *priv = (struct mypriv *)mtd->priv; - - memcpy (buf, priv->start + from, len); - - *retlen=len; - return 0; -} - -int physmem_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) -{ - struct mypriv *priv = (struct mypriv *)mtd->priv; - - memcpy (priv->start + to, buf, len); - - *retlen=len; - return 0; -} - - - - -/*====================================================================*/ - -/* Place your defaults here */ - -static u_long start = 100663296; -static u_long length = 33554432; -static u_long end = 0; - -#if LINUX_VERSION_CODE < 0x20300 -#ifdef MODULE -#define init_slram init_module -#define cleanup_slram cleanup_module -#endif -#define __exit -#endif - -#ifdef MODULE -MODULE_PARM(start,"l"); -MODULE_PARM(length,"l"); -MODULE_PARM(end,"l"); -#endif - -struct mtd_info *mymtd; - -void __init mtd_slram_setup(char *str, int *ints) -{ - if (ints[0] > 0) - start=ints[1]; - if (ints[0] > 1) - length=ints[2]; -} - -int init_slram(void) -{ - if (!start) - { - printk(KERN_NOTICE "physmem: No start address for memory device.\n"); - return -EINVAL; - } - - if (!length && !end) - { - printk(KERN_NOTICE "physmem: No length or endpointer given.\n"); - return -EINVAL; - } - - if (!end) - end = start + length; - - if (!length) - length = end - start; - - if (start + length != end) - { - printk(KERN_NOTICE "physmem: start(%lx) + length(%lx) != end(%lx) !\n", - start, length, end); - return -EINVAL; - } - - mymtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL); - - memset(mymtd, 0, sizeof(*mymtd)); - - if (mymtd) - { - memset((char *)mymtd, 0, sizeof(struct mtd_info)); - mymtd->priv = (void *) kmalloc (sizeof(struct mypriv), GFP_KERNEL); - if (!mymtd->priv) - { - kfree(mymtd); - mymtd = NULL; - } - memset(mymtd->priv, 0, sizeof(struct mypriv)); - } - - if (!mymtd) - { - printk(KERN_NOTICE "physmem: Cannot allocate new MTD device.\n"); - return -ENOMEM; - } - - - ((struct mypriv *)mymtd->priv)->start = ioremap(start, length); - ((struct mypriv *)mymtd->priv)->end = ((struct mypriv *)mymtd->priv)->start + length; - - - mymtd->name = "Raw memory"; - - mymtd->size = length; - mymtd->flags = MTD_CLEAR_BITS | MTD_SET_BITS | MTD_WRITEB_WRITEABLE | MTD_VOLATILE; - mymtd->erase = physmem_erase; - mymtd->point = physmem_point; - mymtd->unpoint = physmem_unpoint; - mymtd->read = physmem_read; - mymtd->write = physmem_write; - mymtd->module = THIS_MODULE; - mymtd->type = MTD_RAM; - mymtd->erasesize = 0x10000; - - if (add_mtd_device(mymtd)) - { - printk("Failed to register new device\n"); - iounmap(((struct mypriv *)mymtd->priv)->start); - kfree(mymtd->priv); - kfree(mymtd); - return -EAGAIN; - } - printk("Registered physmem device from %dKb to %dKb\n", - (int)(start / 1024), (int)(end / 1024)); - printk("Mapped from 0x%p to 0x%p\n",((struct mypriv *)mymtd->priv)->start, -((struct mypriv *)mymtd->priv)->end); - - return 0; -} - -static void __exit cleanup_slram(void) -{ - iounmap(((struct mypriv *)mymtd->priv)->start); - kfree (mymtd->priv); - del_mtd_device(mymtd); - kfree(mymtd); -} - -#if LINUX_VERSION_CODE > 0x20300 -module_init(init_slram); -module_exit(cleanup_slram); -#endif diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/vmax301.c linux/drivers/mtd/vmax301.c --- v2.4.5/linux/drivers/mtd/vmax301.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/mtd/vmax301.c Wed Dec 31 16:00:00 1969 @@ -1,240 +0,0 @@ -// $Id: vmax301.c,v 1.15 2000/11/27 08:50:22 dwmw2 Exp $ -/* ###################################################################### - - Tempustech VMAX SBC301 MTD Driver. - - The VMAx 301 is a SBC based on . It - comes with three builtin AMD 29F016B flash chips and a socket for SRAM or - more flash. Each unit has it's own 8k mapping into a settable region - (0xD8000). There are two 8k mappings for each MTD, the first is always set - to the lower 8k of the device the second is paged. Writing a 16 bit page - value to anywhere in the first 8k will cause the second 8k to page around. - - To boot the device a bios extension must be installed into the first 8k - of flash that is smart enough to copy itself down, page in the rest of - itself and begin executing. - - ##################################################################### */ - -#include -#include -#include -#include -#include -#include - -#include - - -#define WINDOW_START 0xd8000 -#define WINDOW_LENGTH 0x2000 -#define WINDOW_SHIFT 25 -#define WINDOW_MASK 0x1FFF - -/* Actually we could use two spinlocks, but we'd have to have - more private space in the struct map_info. We lose a little - performance like this, but we'd probably lose more by having - the extra indirection from having one of the map->map_priv - fields pointing to yet another private struct. -*/ -static spinlock_t vmax301_spin = SPIN_LOCK_UNLOCKED; - -static void __vmax301_page(struct map_info *map, unsigned long page) -{ - writew(page, map->map_priv_2 - WINDOW_LENGTH); - map->map_priv_1 = page; -} - -static inline void vmax301_page(struct map_info *map, - unsigned long ofs) -{ - unsigned long page = (ofs >> WINDOW_SHIFT); - if (map->map_priv_1 != page) - __vmax301_page(map, page); -} - -static __u8 vmax301_read8(struct map_info *map, unsigned long ofs) -{ - __u8 ret; - spin_lock(&vmax301_spin); - vmax301_page(map, ofs); - ret = readb(map->map_priv_2 + (ofs & WINDOW_MASK)); - spin_unlock(&vmax301_spin); - return ret; -} - -static __u16 vmax301_read16(struct map_info *map, unsigned long ofs) -{ - __u16 ret; - spin_lock(&vmax301_spin); - vmax301_page(map, ofs); - ret = readw(map->map_priv_2 + (ofs & WINDOW_MASK)); - spin_unlock(&vmax301_spin); - return ret; -} - -static __u32 vmax301_read32(struct map_info *map, unsigned long ofs) -{ - __u32 ret; - spin_lock(&vmax301_spin); - vmax301_page(map, ofs); - ret = readl(map->map_priv_2 + (ofs & WINDOW_MASK)); - spin_unlock(&vmax301_spin); - return ret; -} - -static void vmax301_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) -{ - while(len) { - unsigned long thislen = len; - if (len > (WINDOW_LENGTH - (from & WINDOW_MASK))) - thislen = WINDOW_LENGTH-(from & WINDOW_MASK); - spin_lock(&vmax301_spin); - vmax301_page(map, from); - memcpy_fromio(to, map->map_priv_2 + from, thislen); - spin_unlock(&vmax301_spin); - to += thislen; - from += thislen; - len -= thislen; - } -} - -static void vmax301_write8(struct map_info *map, __u8 d, unsigned long adr) -{ - spin_lock(&vmax301_spin); - vmax301_page(map, adr); - writeb(d, map->map_priv_2 + (adr & WINDOW_MASK)); - spin_unlock(&vmax301_spin); -} - -static void vmax301_write16(struct map_info *map, __u16 d, unsigned long adr) -{ - spin_lock(&vmax301_spin); - vmax301_page(map, adr); - writew(d, map->map_priv_2 + (adr & WINDOW_MASK)); - spin_unlock(&vmax301_spin); -} - -static void vmax301_write32(struct map_info *map, __u32 d, unsigned long adr) -{ - spin_lock(&vmax301_spin); - vmax301_page(map, adr); - writel(d, map->map_priv_2 + (adr & WINDOW_MASK)); - spin_unlock(&vmax301_spin); -} - -static void vmax301_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) -{ - while(len) { - unsigned long thislen = len; - if (len > (WINDOW_LENGTH - (to & WINDOW_MASK))) - thislen = WINDOW_LENGTH-(to & WINDOW_MASK); - - spin_lock(&vmax301_spin); - vmax301_page(map, to); - memcpy_toio(map->map_priv_2 + to, from, thislen); - spin_unlock(&vmax301_spin); - to += thislen; - from += thislen; - len -= thislen; - } -} - -static struct map_info vmax_map[2] = { - { - name: "VMAX301 Internal Flash", - size: 3*2*1024*1024, - buswidth: 1, - read8: vmax301_read8, - read16: vmax301_read16, - read32: vmax301_read32, - copy_from: vmax301_copy_from, - write8: vmax301_write8, - write16: vmax301_write16, - write32: vmax301_write32, - copy_to: vmax301_copy_to, - map_priv_1: WINDOW_START + WINDOW_LENGTH, - map_priv_2: 0xFFFFFFFF - }, - { - name: "VMAX301 Socket", - size: 0, - buswidth: 1, - read8: vmax301_read8, - read16: vmax301_read16, - read32: vmax301_read32, - copy_from: vmax301_copy_from, - write8: vmax301_write8, - write16: vmax301_write16, - write32: vmax301_write32, - copy_to: vmax301_copy_to, - map_priv_1: WINDOW_START + (3*WINDOW_LENGTH), - map_priv_2: 0xFFFFFFFF - } -}; - -static struct mtd_info *vmax_mtd[2] = {NULL, NULL}; - -#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) -#define init_vmax301 init_module -#define cleanup_vmax301 cleanup_module -#endif - -static void __exit cleanup_vmax301(void) -{ - int i; - - for (i=0; i<2; i++) { - if (vmax_mtd[i]) { - del_mtd_device(vmax_mtd[i]); - map_destroy(vmax_mtd[i]); - } - } - iounmap((void *)vmax_map[0].map_priv_1 - WINDOW_START); -} - -int __init init_vmax301(void) -{ - int i; - unsigned long iomapadr; - // Print out our little header.. - printk("Tempustech VMAX 301 MEM:0x%x-0x%x\n",WINDOW_START, - WINDOW_START+4*WINDOW_LENGTH); - - iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH*4); - if (!iomapadr) { - printk("Failed to ioremap memory region\n"); - return -EIO; - } - /* Put the address in the map's private data area. - We store the actual MTD IO address rather than the - address of the first half, because it's used more - often. - */ - vmax_map[0].map_priv_1 = iomapadr + WINDOW_START; - vmax_map[1].map_priv_1 = iomapadr + (3*WINDOW_START); - - for (i=0; i<2; i++) { - vmax_mtd[i] = do_cfi_probe(&vmax_map[i]); - if (!vmax_mtd[i]) - vmax_mtd[i] = do_jedec_probe(&vmax_map[i]); - if (!vmax_mtd[i]) - vmax_mtd[i] = do_ram_probe(&vmax_map[i]); - if (!vmax_mtd[i]) - vmax_mtd[i] = do_rom_probe(&vmax_map[i]); - if (vmax_mtd[i]) { - vmax_mtd[i]->module = THIS_MODULE; - add_mtd_device(vmax_mtd[i]); - } - } - - if (!vmax_mtd[1] && !vmax_mtd[2]) { - iounmap(iomapadr); - return -ENXIO; - } - - return 0; -} - -module_init(init_vmax301); -module_exit(cleanup_vmax301); diff -u --recursive --new-file v2.4.5/linux/drivers/net/3c501.c linux/drivers/net/3c501.c --- v2.4.5/linux/drivers/net/3c501.c Thu Apr 19 09:34:52 2001 +++ linux/drivers/net/3c501.c Wed Jun 20 11:10:53 2001 @@ -251,7 +251,7 @@ } /** - * el1_probe: + * el1_probe1: * @dev: The device structure to use * @ioaddr: An I/O address to probe at. * @@ -925,6 +925,8 @@ static int irq=5; MODULE_PARM(io, "i"); MODULE_PARM(irq, "i"); +MODULE_PARM_DESC(io, "EtherLink I/O base address"); +MODULE_PARM_DESC(irq, "EtherLink IRQ number"); /** * init_module: diff -u --recursive --new-file v2.4.5/linux/drivers/net/3c503.c linux/drivers/net/3c503.c --- v2.4.5/linux/drivers/net/3c503.c Thu Apr 19 09:34:52 2001 +++ linux/drivers/net/3c503.c Wed Jun 20 11:10:53 2001 @@ -615,6 +615,9 @@ MODULE_PARM(io, "1-" __MODULE_STRING(MAX_EL2_CARDS) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_EL2_CARDS) "i"); MODULE_PARM(xcvr, "1-" __MODULE_STRING(MAX_EL2_CARDS) "i"); +MODULE_PARM_DESC(io, "EtherLink II I/O base address(es)"); +MODULE_PARM_DESC(irq, "EtherLink II IRQ number(s) (assigned)"); +MODULE_PARM_DESC(xcvr, "EtherLink II tranceiver(s) (0=internal, 1=external)"); /* This is set up so that only a single autoprobe takes place per call. ISA device autoprobes on a running machine are not recommended. */ diff -u --recursive --new-file v2.4.5/linux/drivers/net/3c505.c linux/drivers/net/3c505.c --- v2.4.5/linux/drivers/net/3c505.c Thu Apr 19 09:34:52 2001 +++ linux/drivers/net/3c505.c Wed Jun 20 11:10:53 2001 @@ -1621,6 +1621,9 @@ MODULE_PARM(io, "1-" __MODULE_STRING(ELP_MAX_CARDS) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(ELP_MAX_CARDS) "i"); MODULE_PARM(dma, "1-" __MODULE_STRING(ELP_MAX_CARDS) "i"); +MODULE_PARM_DESC(io, "EtherLink Plus I/O base address(es)"); +MODULE_PARM_DESC(irq, "EtherLink Plus IRQ number(s) (assigned)"); +MODULE_PARM_DESC(dma, "EtherLink Plus DMA channel(s)"); int init_module(void) { diff -u --recursive --new-file v2.4.5/linux/drivers/net/3c507.c linux/drivers/net/3c507.c --- v2.4.5/linux/drivers/net/3c507.c Thu Apr 19 09:34:52 2001 +++ linux/drivers/net/3c507.c Wed Jun 20 11:10:53 2001 @@ -861,6 +861,8 @@ static int irq; MODULE_PARM(io, "i"); MODULE_PARM(irq, "i"); +MODULE_PARM_DESC(io, "EtherLink16 I/O base address"); +MODULE_PARM_DESC(irq, "(ignored)"); int init_module(void) { diff -u --recursive --new-file v2.4.5/linux/drivers/net/3c509.c linux/drivers/net/3c509.c --- v2.4.5/linux/drivers/net/3c509.c Thu Apr 12 12:15:25 2001 +++ linux/drivers/net/3c509.c Wed Jun 27 17:10:55 2001 @@ -192,6 +192,9 @@ ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5098), (long) "3Com Etherlink III (TPC)" }, { ISAPNP_ANY_ID, ISAPNP_ANY_ID, + ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_FUNCTION(0x80f7), + (long) "3Com Etherlink III compatible" }, + { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_FUNCTION(0x80f8), (long) "3Com Etherlink III compatible" }, { } /* terminate list */ @@ -1007,9 +1010,14 @@ MODULE_PARM(irq,"1-8i"); MODULE_PARM(xcvr,"1-8i"); MODULE_PARM(max_interrupt_work, "i"); +MODULE_PARM_DESC(debug, "EtherLink III debug level (0-6)"); +MODULE_PARM_DESC(irq, "EtherLink III IRQ number(s) (assigned)"); +MODULE_PARM_DESC(xcvr,"EtherLink III tranceiver(s) (0=internal, 1=external)"); +MODULE_PARM_DESC(max_interrupt_work, "EtherLink III maximum events handled per interrupt"); #ifdef CONFIG_ISAPNP MODULE_PARM(nopnp, "i"); -#endif +MODULE_PARM_DESC(nopnp, "EtherLink III disable ISA PnP support (0-1)"); +#endif /* CONFIG_ISAPNP */ int init_module(void) diff -u --recursive --new-file v2.4.5/linux/drivers/net/3c515.c linux/drivers/net/3c515.c --- v2.4.5/linux/drivers/net/3c515.c Thu Apr 12 12:15:25 2001 +++ linux/drivers/net/3c515.c Wed Jun 20 11:10:53 2001 @@ -85,6 +85,11 @@ MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i"); MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(max_interrupt_work, "i"); +MODULE_PARM_DESC(debug, "3c515 debug level (0-6)"); +MODULE_PARM_DESC(options, "3c515: Bits 0-2: media type, bit 3: full duplex, bit 4: bus mastering"); +MODULE_PARM_DESC(full_duplex, "(ignored)"); +MODULE_PARM_DESC(rx_copybreak, "3c515 copy breakpoint for copy-only-tiny-frames"); +MODULE_PARM_DESC(max_interrupt_work, "3c515 maximum events handled per interrupt"); /* "Knobs" for adjusting internal parameters. */ /* Put out somewhat more debugging messages. (0 - no msg, 1 minimal msgs). */ diff -u --recursive --new-file v2.4.5/linux/drivers/net/3c523.c linux/drivers/net/3c523.c --- v2.4.5/linux/drivers/net/3c523.c Thu Apr 12 12:15:25 2001 +++ linux/drivers/net/3c523.c Wed Jun 20 11:10:53 2001 @@ -1226,6 +1226,8 @@ static int io[MAX_3C523_CARDS]; MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_3C523_CARDS) "i"); MODULE_PARM(io, "1-" __MODULE_STRING(MAX_3C523_CARDS) "i"); +MODULE_PARM_DESC(io, "EtherLink/MC I/O base address(es)"); +MODULE_PARM_DESC(irq, "EtherLink/MC IRQ number(s)"); int init_module(void) { diff -u --recursive --new-file v2.4.5/linux/drivers/net/3c59x.c linux/drivers/net/3c59x.c --- v2.4.5/linux/drivers/net/3c59x.c Thu Apr 12 12:16:35 2001 +++ linux/drivers/net/3c59x.c Mon Jul 2 14:03:04 2001 @@ -142,6 +142,13 @@ - If a device's internalconfig register reports it has NWAY, use it, even if autoselect is enabled. + LK1.1.15 6 June 2001 akpm + - Prevent double counting of received bytes (Lars Christensen) + - Add ethtool support (jgarzik) + - Add module parm descriptions (Andrzej M. Krzysztofowicz) + - Implemented alloc_etherdev() API + - Special-case the 'Tx error 82' message. + - See http://www.uow.edu.au/~andrewm/linux/#3c59x-2.3 for more details. - Also see Documentation/networking/vortex.txt */ @@ -155,6 +162,13 @@ * elimination of all the tests and reduced cache footprint. */ + +#define DRV_NAME "3c59x" +#define DRV_VERSION "LK1.1.15" +#define DRV_RELDATE "6 June 2001" + + + /* A few values that may be tweaked. */ /* Keep the ring sizes a power of two for efficiency. */ #define TX_RING_SIZE 16 @@ -164,7 +178,13 @@ /* "Knobs" that adjust features and parameters. */ /* Set the copy breakpoint for the copy-only-tiny-frames scheme. Setting to > 1512 effectively disables this feature. */ +#ifndef __arm__ static const int rx_copybreak = 200; +#else +/* ARM systems perform better by disregarding the bus-master + transfer capability of these cards. -- rmk */ +static const int rx_copybreak = 1513; +#endif /* Allow setting MTU to a larger size, bypassing the normal ethernet setup. */ static const int mtu = 1500; /* Maximum events (Rx packets, etc.) to handle at each interrupt. */ @@ -204,13 +224,16 @@ #include #include #include +#include #include #include #include #include +#include #include /* For NR_IRQS only. */ #include #include +#include /* Kernel compatibility defines, some common to David Hinds' PCMCIA package. This is only in the support-all-kernels source code. */ @@ -219,8 +242,9 @@ #include + static char version[] __devinitdata = -"3c59x.c:LK1.1.13 27 Jan 2001 Donald Becker and others. http://www.scyld.com/network/vortex.html\n"; +DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " Donald Becker and others. http://www.scyld.com/network/vortex.html\n"; MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("3Com 3c59x/3c90x/3c575 series Vortex/Boomerang/Cyclone driver"); @@ -236,6 +260,18 @@ MODULE_PARM(compaq_irq, "i"); MODULE_PARM(compaq_device_id, "i"); MODULE_PARM(watchdog, "i"); +MODULE_PARM_DESC(debug, "3c59x debug level (0-6)"); +MODULE_PARM_DESC(options, "3c59x: Bits 0-3: media type, bit 4: bus mastering, bit 9: full duplex"); +MODULE_PARM_DESC(full_duplex, "3c59x full duplex setting(s) (1)"); +MODULE_PARM_DESC(hw_checksums, "3c59x Hardware checksum checking by adapter(s) (0-1)"); +MODULE_PARM_DESC(flow_ctrl, "3c59x 802.3x flow control usage (PAUSE only) (0-1)"); +MODULE_PARM_DESC(enable_wol, "3c59x: Turn on Wake-on-LAN for adapter(s) (0-1)"); +MODULE_PARM_DESC(rx_copybreak, "3c59x copy breakpoint for copy-only-tiny-frames"); +MODULE_PARM_DESC(max_interrupt_work, "3c59x maximum events handled per interrupt"); +MODULE_PARM_DESC(compaq_ioaddr, "3c59x PCI I/O base address (Compaq BIOS problem workaround)"); +MODULE_PARM_DESC(compaq_irq, "3c59x PCI IRQ number (Compaq BIOS problem workaround)"); +MODULE_PARM_DESC(compaq_device_id, "3c59x PCI device ID (Compaq BIOS problem workaround)"); +MODULE_PARM_DESC(watchdog, "3c59x transmit timeout in milliseconds"); /* Operational parameter that usually are not changed. */ @@ -251,7 +287,7 @@ code size of a per-interface flag is not worthwhile. */ static char mii_preamble_required; -#define PFX "3c59x: " +#define PFX DRV_NAME ": " @@ -805,7 +841,9 @@ static int vortex_cards_found; -static void vortex_suspend (struct pci_dev *pdev) +#ifdef CONFIG_PM + +static int vortex_suspend (struct pci_dev *pdev, u32 state) { struct net_device *dev = pdev->driver_data; @@ -818,9 +856,10 @@ vortex_down(dev); } } + return 0; } -static void vortex_resume (struct pci_dev *pdev) +static int vortex_resume (struct pci_dev *pdev) { struct net_device *dev = pdev->driver_data; @@ -833,8 +872,11 @@ netif_device_attach(dev); } } + return 0; } +#endif /* CONFIG_PM */ + /* returns count found (>= 0), or negative on error */ static int __init vortex_eisa_init (void) { @@ -849,7 +891,7 @@ for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) { int device_id; - if (request_region(ioaddr, VORTEX_TOTAL_SIZE, "3c59x") == NULL) + if (request_region(ioaddr, VORTEX_TOTAL_SIZE, DRV_NAME) == NULL) continue; /* Check the standard EISA ID register for an encoded '3Com'. */ @@ -918,6 +960,7 @@ static int printed_version; int retval; struct vortex_chip_info * const vci = &vortex_info_tbl[chip_idx]; + char *print_name; if (!printed_version) { printk (KERN_INFO "%s", version); @@ -925,7 +968,9 @@ printed_version = 1; } - dev = init_etherdev(NULL, sizeof(*vp)); + print_name = pdev ? pdev->slot_name : "3c59x"; + + dev = alloc_etherdev(sizeof(*vp)); retval = -ENOMEM; if (!dev) { printk (KERN_ERR PFX "unable to allocate etherdev, aborting\n"); @@ -934,7 +979,7 @@ SET_MODULE_OWNER(dev); printk(KERN_INFO "%s: 3Com %s %s at 0x%lx, ", - dev->name, + print_name, pdev ? "PCI" : "EISA", vci->name, ioaddr); @@ -958,7 +1003,7 @@ if (pdev) { /* EISA resources already marked, so only PCI needs to do this here */ /* Ignore return value, because Cardbus drivers already allocate for us */ - if (request_region(ioaddr, vci->io_size, dev->name) != NULL) + if (request_region(ioaddr, vci->io_size, print_name) != NULL) vp->must_free_region = 1; /* enable bus-mastering if necessary */ @@ -977,7 +1022,7 @@ if (pci_latency < new_latency) { printk(KERN_INFO "%s: Overriding PCI latency" " timer (CFLT) setting of %d, new value is %d.\n", - dev->name, pci_latency, new_latency); + print_name, pci_latency, new_latency); pci_write_config_byte(pdev, PCI_LATENCY_TIMER, new_latency); } } @@ -1107,7 +1152,7 @@ goto free_ring; } printk(KERN_INFO "%s: CardBus functions mapped %8.8lx->%p\n", - dev->name, fn_st_addr, vp->cb_fn_base); + print_name, fn_st_addr, vp->cb_fn_base); EL3WINDOW(2); n = inw(ioaddr + Wn2_ResetOptions) & ~0x4010; @@ -1230,7 +1275,7 @@ if (vortex_debug > 0) { printk(KERN_INFO "%s: scatter/gather %sabled. h/w checksums %sabled\n", - dev->name, + print_name, (dev->features & NETIF_F_SG) ? "en":"dis", (dev->features & NETIF_F_IP_CSUM) ? "en":"dis"); } @@ -1241,7 +1286,9 @@ dev->set_multicast_list = set_rx_mode; dev->tx_timeout = vortex_tx_timeout; dev->watchdog_timeo = (watchdog * HZ) / 1000; - return 0; + retval = register_netdev(dev); + if (retval == 0) + return 0; free_ring: pci_free_consistent(pdev, @@ -1252,7 +1299,6 @@ free_region: if (vp->must_free_region) release_region(ioaddr, vci->io_size); - unregister_netdev(dev); kfree (dev); printk(KERN_ERR PFX "vortex_probe1 fails. Returns %d\n", retval); out: @@ -1725,7 +1771,7 @@ unsigned char tx_status = 0; if (vortex_debug > 2) { - printk(KERN_DEBUG "%s: vortex_error(), status=0x%x\n", dev->name, status); + printk(KERN_ERR "%s: vortex_error(), status=0x%x\n", dev->name, status); } if (status & TxComplete) { /* Really "TxError" for us. */ @@ -1733,8 +1779,12 @@ /* Presumably a tx-timeout. We must merely re-enable. */ if (vortex_debug > 2 || (tx_status != 0x88 && vortex_debug > 0)) { - printk(KERN_DEBUG"%s: Transmit error, Tx status register %2.2x.\n", + printk(KERN_ERR "%s: Transmit error, Tx status register %2.2x.\n", dev->name, tx_status); + if (tx_status == 0x82) { + printk(KERN_ERR "Probably a duplex mismatch. See " + "Documentation/networking/vortex.txt\n"); + } dump_tx_ring(dev); } if (tx_status & 0x14) vp->stats.tx_fifo_errors++; @@ -2293,7 +2343,6 @@ struct sk_buff *skb; dma_addr_t dma = le32_to_cpu(vp->rx_ring[entry].addr); - vp->stats.rx_bytes += pkt_len; if (vortex_debug > 4) printk(KERN_DEBUG "Receiving packet size %d status %4.4x.\n", pkt_len, rx_status); @@ -2571,28 +2620,65 @@ return; } + +static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr) +{ + struct vortex_private *vp = dev->priv; + u32 ethcmd; + + if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) + return -EFAULT; + + switch (ethcmd) { + case ETHTOOL_GDRVINFO: { + struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; + strcpy(info.driver, DRV_NAME); + strcpy(info.version, DRV_VERSION); + if (vp->pdev) + strcpy(info.bus_info, vp->pdev->slot_name); + else + sprintf(info.bus_info, "EISA 0x%lx %d", + dev->base_addr, dev->irq); + if (copy_to_user(useraddr, &info, sizeof(info))) + return -EFAULT; + return 0; + } + + } + + return -EOPNOTSUPP; +} + static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct vortex_private *vp = (struct vortex_private *)dev->priv; long ioaddr = dev->base_addr; - u16 *data = (u16 *)&rq->ifr_data; + struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data; int phy = vp->phys[0] & 0x1f; int retval; switch(cmd) { - case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ - data[0] = phy; - case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ + case SIOCETHTOOL: + return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); + + case SIOCGMIIPHY: /* Get address of MII PHY in use. */ + case SIOCDEVPRIVATE: /* for binary compat, remove in 2.5 */ + data->phy_id = phy; + + case SIOCGMIIREG: /* Read MII PHY register. */ + case SIOCDEVPRIVATE+1: /* for binary compat, remove in 2.5 */ EL3WINDOW(4); - data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f); + data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f); retval = 0; break; - case SIOCDEVPRIVATE+2: /* Write the specified MII register */ + + case SIOCSMIIREG: /* Write MII PHY register. */ + case SIOCDEVPRIVATE+2: /* for binary compat, remove in 2.5 */ if (!capable(CAP_NET_ADMIN)) { retval = -EPERM; } else { EL3WINDOW(4); - mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]); + mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in); retval = 0; } break; @@ -2774,9 +2860,11 @@ name: "3c59x", probe: vortex_init_one, remove: vortex_remove_one, + id_table: vortex_pci_tbl, +#ifdef CONFIG_PM suspend: vortex_suspend, resume: vortex_resume, - id_table: vortex_pci_tbl, +#endif }; diff -u --recursive --new-file v2.4.5/linux/drivers/net/8139too.c linux/drivers/net/8139too.c --- v2.4.5/linux/drivers/net/8139too.c Mon May 7 14:13:19 2001 +++ linux/drivers/net/8139too.c Mon Jul 2 14:02:53 2001 @@ -136,6 +136,10 @@ */ +#define DRV_NAME "8139too" +#define DRV_VERSION "0.9.18-pre4" + + #include #include #include @@ -146,13 +150,14 @@ #include #include #include +#include +#include #include +#include -#define RTL8139_VERSION "0.9.17" -#define MODNAME "8139too" -#define RTL8139_DRIVER_NAME MODNAME " Fast Ethernet driver " RTL8139_VERSION -#define PFX MODNAME ": " +#define RTL8139_DRIVER_NAME DRV_NAME " Fast Ethernet driver " DRV_VERSION +#define PFX DRV_NAME ": " /* enable PIO instead of MMIO, if CONFIG_8139TOO_PIO is selected */ @@ -363,7 +368,10 @@ TxOK = 0x04, RxErr = 0x02, RxOK = 0x01, + + RxAckBits = RxFIFOOver | RxOverflow | RxOK, }; + enum TxStatusBits { TxHostOwns = 0x2000, TxUnderrun = 0x4000, @@ -542,6 +550,11 @@ }; +struct rtl_extra_stats { + unsigned long early_rx; + unsigned long tx_buf_mapped; + unsigned long tx_timeouts; +}; struct rtl8139_private { void *mmio_addr; @@ -560,7 +573,6 @@ dma_addr_t rx_ring_dma; dma_addr_t tx_bufs_dma; signed char phys[4]; /* MII device addresses. */ - u16 advertising; /* NWay media advertisement */ char twistie, twist_row, twist_col; /* Twister tune state. */ unsigned int full_duplex:1; /* Full-duplex operation requested. */ unsigned int duplex_lock:1; @@ -574,6 +586,7 @@ wait_queue_head_t thr_wait; struct semaphore thr_exited; u32 rx_config; + struct rtl_extra_stats xstats; }; MODULE_AUTHOR ("Jeff Garzik "); @@ -582,6 +595,10 @@ MODULE_PARM (max_interrupt_work, "i"); MODULE_PARM (media, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM (full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); +MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); +MODULE_PARM_DESC (max_interrupt_work, "8139too maximum events handled per interrupt"); +MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); +MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); static int read_eeprom (void *ioaddr, int location, int addr_len); static int rtl8139_open (struct net_device *dev); @@ -596,7 +613,7 @@ static void rtl8139_interrupt (int irq, void *dev_instance, struct pt_regs *regs); static int rtl8139_close (struct net_device *dev); -static int mii_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); +static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); static inline u32 ether_crc (int length, unsigned char *data); static void rtl8139_set_rx_mode (struct net_device *dev); @@ -938,7 +955,7 @@ dev->stop = rtl8139_close; dev->get_stats = rtl8139_get_stats; dev->set_multicast_list = rtl8139_set_rx_mode; - dev->do_ioctl = mii_ioctl; + dev->do_ioctl = netdev_ioctl; dev->tx_timeout = rtl8139_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; @@ -984,11 +1001,11 @@ for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { int mii_status = mdio_read(dev, phy, 1); if (mii_status != 0xffff && mii_status != 0x0000) { + u16 advertising = mdio_read(dev, phy, 4); tp->phys[phy_idx++] = phy; - tp->advertising = mdio_read(dev, phy, 4); printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x " "advertising %4.4x.\n", - dev->name, phy, mii_status, tp->advertising); + dev->name, phy, mii_status, advertising); } } if (phy_idx == 0) { @@ -1314,6 +1331,28 @@ } +static void rtl_check_media (struct net_device *dev) +{ + struct rtl8139_private *tp = dev->priv; + + DPRINTK("ENTER\n"); + + if (tp->phys[0] >= 0) { + u16 mii_reg5 = mdio_read(dev, tp->phys[0], 5); + if (mii_reg5 == 0xffff) + ; /* Not there */ + else if ((mii_reg5 & 0x0100) == 0x0100 + || (mii_reg5 & 0x00C0) == 0x0040) + tp->full_duplex = 1; + + printk (KERN_INFO"%s: Setting %s%s-duplex based on" + " auto-negotiated partner ability %4.4x.\n", + dev->name, mii_reg5 == 0 ? "" : + (mii_reg5 & 0x0180) ? "100mbps " : "10mbps ", + tp->full_duplex ? "full" : "half", mii_reg5); + } +} + /* Start the hardware at open or resume. */ static void rtl8139_hw_start (struct net_device *dev) { @@ -1331,50 +1370,25 @@ rtl8139_chip_reset (ioaddr); /* unlock Config[01234] and BMCR register writes */ - RTL_W8 (Cfg9346, Cfg9346_Unlock); + RTL_W8_F (Cfg9346, Cfg9346_Unlock); /* Restore our idea of the MAC address. */ RTL_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - RTL_W32 (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); + RTL_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); /* Must enable Tx/Rx before setting transfer thresholds! */ RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; - RTL_W32 (RxConfig, rtl8139_rx_config); + RTL_W32 (RxConfig, tp->rx_config); /* Check this value: the documentation for IFG contradicts ifself. */ RTL_W32 (TxConfig, (TX_DMA_BURST << TxDMAShift)); tp->cur_rx = 0; - DPRINTK("check_duplex"); - - /* This is check_duplex() */ - if (tp->phys[0] >= 0 || (tp->drv_flags & HAS_MII_XCVR)) { - u16 mii_reg5 = mdio_read(dev, tp->phys[0], 5); - if (mii_reg5 == 0xffff) - ; /* Not there */ - else if ((mii_reg5 & 0x0100) == 0x0100 - || (mii_reg5 & 0x00C0) == 0x0040) - tp->full_duplex = 1; - if (mii_reg5) { - printk(KERN_INFO"%s: Setting %s%s-duplex based on" - " auto-negotiated partner ability %4.4x.\n", dev->name, - mii_reg5 == 0 ? "" : - (mii_reg5 & 0x0180) ? "100mbps " : "10mbps ", - tp->full_duplex ? "full" : "half", mii_reg5); - } else { - printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n", - dev->name); - } - } + rtl_check_media (dev); if (tp->chipset >= CH_8139B) { - tmp = RTL_R8 (Config4) & ~(1<<2); - /* chip will clear Rx FIFO overflow automatically */ - tmp |= (1<<7); - RTL_W8 (Config4, tmp); - /* disable magic packet scanning, which is enabled * when PM is enabled in Config1 */ RTL_W8 (Config3, RTL_R8 (Config3) & ~(1<<5)); @@ -1654,6 +1668,8 @@ RTL_R16 (IntrStatus), RTL_R8 (MediaStatus)); + tp->xstats.tx_timeouts++; + /* disable Tx ASAP, if not already */ tmp8 = RTL_R8 (ChipCmd); if (tmp8 & CmdTxEnb) @@ -1683,13 +1699,14 @@ } - static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) { struct rtl8139_private *tp = dev->priv; void *ioaddr = tp->mmio_addr; unsigned int entry; - unsigned long flags; + u32 dma_addr; + + mb(); /* Calculate the next Tx descriptor entry. */ entry = tp->cur_tx % NUM_TX_DESC; @@ -1701,29 +1718,29 @@ if ((long) skb->data & 3) { /* Must use alignment buffer. */ /* tp->tx_info[entry].mapping = 0; */ memcpy (tp->tx_buf[entry], skb->data, skb->len); - RTL_W32 (TxAddr0 + (entry * 4), - tp->tx_bufs_dma + (tp->tx_buf[entry] - tp->tx_bufs)); + dma_addr = tp->tx_bufs_dma + (tp->tx_buf[entry] - tp->tx_bufs); } else { + tp->xstats.tx_buf_mapped++; tp->tx_info[entry].mapping = pci_map_single (tp->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE); - RTL_W32 (TxAddr0 + (entry * 4), tp->tx_info[entry].mapping); + dma_addr = tp->tx_info[entry].mapping; } /* Note: the chip doesn't have auto-pad! */ - RTL_W32 (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN)); + spin_lock_irq(&tp->lock); + RTL_W32_F (TxAddr0 + (entry * 4), dma_addr); + RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), + tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN)); + spin_unlock_irq(&tp->lock); dev->trans_start = jiffies; - spin_lock_irqsave (&tp->lock, flags); - tp->cur_tx++; + mb(); if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) netif_stop_queue (dev); - spin_unlock_irqrestore (&tp->lock, flags); - DPRINTK ("%s: Queued Tx packet at %p size %u to slot %d.\n", dev->name, skb->data, skb->len, entry); @@ -1760,7 +1777,7 @@ tp->stats.tx_errors++; if (txstatus & TxAborted) { tp->stats.tx_aborted_errors++; - RTL_W32 (TxConfig, TxClearAbt | (TX_DMA_BURST << TxDMAShift)); + RTL_W32_F (TxConfig, TxClearAbt | (TX_DMA_BURST << TxDMAShift)); } if (txstatus & TxCarrierLost) tp->stats.tx_carrier_errors++; @@ -1795,7 +1812,6 @@ dirty_tx++; tx_left--; - barrier(); } #ifndef RTL8139_NDEBUG @@ -1809,6 +1825,7 @@ /* only wake the queue if we did work, and the queue is stopped */ if (tp->dirty_tx != dirty_tx) { tp->dirty_tx = dirty_tx; + mb(); if (netif_queue_stopped (dev)) netif_wake_queue (dev); } @@ -1865,11 +1882,10 @@ static void rtl8139_rx_interrupt (struct net_device *dev, - struct rtl8139_private *tp, void *ioaddr, - u16 status) + struct rtl8139_private *tp, void *ioaddr) { unsigned char *rx_ring; - u16 cur_rx, ackstat; + u16 cur_rx; assert (dev != NULL); assert (tp != NULL); @@ -1883,11 +1899,6 @@ RTL_R16 (RxBufAddr), RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - if (status & RxFIFOOver) - status = RxOverflow | RxOK; - else - status = RxOK; - while ((RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { int ring_offset = cur_rx % RX_BUF_LEN; u32 rx_status; @@ -1895,8 +1906,8 @@ unsigned int pkt_size; struct sk_buff *skb; - mb(); - + rmb(); + /* read size+status of next frame from DMA ring buffer */ rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset)); rx_size = rx_status >> 16; @@ -1916,8 +1927,10 @@ } #endif - if (rx_size == 0xfff0) /* Early Rx in progress */ + if (rx_size == 0xfff0) { /* Early Rx in progress */ + tp->xstats.early_rx++; break; + } /* If Rx err or invalid rx_size/rx_status received * (which happens if we get lost in the ring), @@ -1963,9 +1976,8 @@ cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; RTL_W16 (RxBufPtr, cur_rx - 16); - ackstat = RTL_R16 (IntrStatus) & status; - if (ackstat) - RTL_W16 (IntrStatus, ackstat); + if (RTL_R16 (IntrStatus) & RxAckBits) + RTL_W16_F (IntrStatus, RxAckBits); } DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," @@ -1975,11 +1987,9 @@ tp->cur_rx = cur_rx; - if (RTL_R8 (ChipCmd) & RxBufEmpty) { - ackstat = RTL_R16 (IntrStatus) & status; - if (ackstat) - RTL_W16_F (IntrStatus, ackstat); - } + if ((RTL_R8 (ChipCmd) & RxBufEmpty) && + (RTL_R16 (IntrStatus) & RxAckBits)) + RTL_W16_F (IntrStatus, RxAckBits); } @@ -2047,6 +2057,8 @@ int ackstat, status; int link_changed = 0; /* avoid bogus "uninit" warning */ + spin_lock (&tp->lock); + do { status = RTL_R16 (IntrStatus); @@ -2059,26 +2071,10 @@ if (status & RxUnderrun) link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; - /* E. Gill */ - /* In case of an RxFIFOOver we must also clear the RxOverflow - bit to avoid dropping frames for ever. Believe me, I got a - lot of troubles copying huge data (approximately 2 RxFIFOOver - errors per 1GB data transfer). - The following is written in the 'p-guide.pdf' file (RTL8139(A/B) - Programming guide V0.1, from 1999/1/15) on page 9 from REALTEC. - ----------------------------------------------------------- - 2. RxFIFOOvw handling: - When RxFIFOOvw occurs, all incoming packets are discarded. - Clear ISR(RxFIFOOvw) doesn't dismiss RxFIFOOvw event. To - dismiss RxFIFOOvw event, the ISR(RxBufOvw) must be written - with a '1'. - ----------------------------------------------------------- - Unfortunately I was not able to find any reason for the - RxFIFOOver error (I got the feeling this depends on the - CPU speed, lower CPU speed --> more errors). - After clearing the RxOverflow bit the transfer of the - packet was repeated and all data are error free transferred */ - ackstat = status & ~(RxFIFOOver | RxOverflow | RxOK); + /* The chip takes special action when we clear RxAckBits, + * so we clear them later in rtl8139_rx_interrupt + */ + ackstat = status & ~RxAckBits; RTL_W16 (IntrStatus, ackstat); DPRINTK ("%s: interrupt status=%#4.4x ackstat=%#4.4x new intstat=%#4.4x.\n", @@ -2089,9 +2085,8 @@ RxFIFOOver | TxErr | TxOK | RxErr | RxOK)) == 0) break; - if (netif_running (dev) && - status & (RxOK | RxUnderrun | RxOverflow | RxFIFOOver)) /* Rx interrupt */ - rtl8139_rx_interrupt (dev, tp, ioaddr, status); + if (netif_running (dev) && (status & RxAckBits)) + rtl8139_rx_interrupt (dev, tp, ioaddr); /* Check uncommon events with one test. */ if (status & (PCIErr | PCSTimeout | RxUnderrun | RxOverflow | @@ -2099,26 +2094,22 @@ rtl8139_weird_interrupt (dev, tp, ioaddr, status, link_changed); - if (netif_running (dev) && - status & (TxOK | TxErr)) { - spin_lock (&tp->lock); + if (netif_running (dev) && (status & (TxOK | TxErr))) rtl8139_tx_interrupt (dev, tp, ioaddr); - spin_unlock (&tp->lock); - } boguscnt--; } while (boguscnt > 0); if (boguscnt <= 0) { - printk (KERN_WARNING - "%s: Too much work at interrupt, " - "IntrStatus=0x%4.4x.\n", dev->name, - status); + printk (KERN_WARNING "%s: Too much work at interrupt, " + "IntrStatus=0x%4.4x.\n", dev->name, status); /* Clear all interrupt sources. */ RTL_W16 (IntrStatus, 0xffff); } + spin_unlock (&tp->lock); + DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", dev->name, RTL_R16 (IntrStatus)); } @@ -2184,42 +2175,79 @@ } -static int mii_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) +static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr) +{ + struct rtl8139_private *np = dev->priv; + u32 ethcmd; + + if (copy_from_user (ðcmd, useraddr, sizeof (ethcmd))) + return -EFAULT; + + switch (ethcmd) { + case ETHTOOL_GDRVINFO: + { + struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; + strcpy (info.driver, DRV_NAME); + strcpy (info.version, DRV_VERSION); + strcpy (info.bus_info, np->pci_dev->slot_name); + if (copy_to_user (useraddr, &info, sizeof (info))) + return -EFAULT; + return 0; + } + + default: + break; + } + + return -EOPNOTSUPP; +} + +static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) { struct rtl8139_private *tp = dev->priv; - u16 *data = (u16 *) & rq->ifr_data; + struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data; int rc = 0; + int phy = tp->phys[0] & 0x3f; DPRINTK ("ENTER\n"); + data->phy_id &= 0x1f; + data->reg_num &= 0x1f; + switch (cmd) { - case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ - data[0] = tp->phys[0] & 0x3f; + case SIOCETHTOOL: + return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); + + case SIOCGMIIPHY: /* Get the address of the PHY in use. */ + case SIOCDEVPRIVATE: /* binary compat, remove in 2.5 */ + data->phy_id = phy; /* Fall Through */ - case SIOCDEVPRIVATE + 1: /* Read the specified MII register. */ - data[3] = mdio_read (dev, data[0], data[1] & 0x1f); + case SIOCGMIIREG: /* Read the specified MII register. */ + case SIOCDEVPRIVATE+1: /* binary compat, remove in 2.5 */ + data->val_out = mdio_read (dev, data->phy_id, data->reg_num); break; - case SIOCDEVPRIVATE + 2: /* Write the specified MII register */ + case SIOCSMIIREG: /* Write the specified MII register */ + case SIOCDEVPRIVATE+2: /* binary compat, remove in 2.5 */ if (!capable (CAP_NET_ADMIN)) { rc = -EPERM; break; } - if (data[0] == tp->phys[0]) { - u16 value = data[2]; - switch (data[1]) { + if (data->phy_id == phy) { + u16 value = data->val_in; + switch (data->reg_num) { case 0: /* Check for autonegotiation on or reset. */ tp->medialock = (value & 0x9000) ? 0 : 1; if (tp->medialock) tp->full_duplex = (value & 0x0100) ? 1 : 0; break; - case 4: tp->advertising = value; break; + case 4: /* tp->advertising = value; */ break; } } - mdio_write(dev, data[0], data[1] & 0x1f, data[2]); + mdio_write(dev, data->phy_id, data->reg_num, data->val_in); break; default: @@ -2308,8 +2336,9 @@ mc_filter[1] = mc_filter[0] = 0; for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; i++, mclist = mclist->next) { - set_bit (ether_crc (ETH_ALEN, mclist->dmi_addr) >> 26, - mc_filter); + int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; + + mc_filter[bit_nr >> 5] |= cpu_to_le32(1 << (bit_nr & 31)); rx_mode |= AcceptMulticast; } } @@ -2323,7 +2352,7 @@ tp->rx_config = tmp; } RTL_W32_F (MAR0 + 0, mc_filter[0]); - RTL_W32 (MAR0 + 4, mc_filter[1]); + RTL_W32_F (MAR0 + 4, mc_filter[1]); spin_unlock_irqrestore (&tp->lock, flags); @@ -2331,7 +2360,9 @@ } -static void rtl8139_suspend (struct pci_dev *pdev) +#ifdef CONFIG_PM + +static int rtl8139_suspend (struct pci_dev *pdev, u32 state) { struct net_device *dev = pci_get_drvdata (pdev); struct rtl8139_private *tp = dev->priv; @@ -2339,7 +2370,7 @@ unsigned long flags; if (!netif_running (dev)) - return; + return 0; netif_device_detach (dev); @@ -2354,27 +2385,33 @@ RTL_W32 (RxMissed, 0); spin_unlock_irqrestore (&tp->lock, flags); + return 0; } -static void rtl8139_resume (struct pci_dev *pdev) +static int rtl8139_resume (struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata (pdev); if (!netif_running (dev)) - return; + return 0; netif_device_attach (dev); rtl8139_hw_start (dev); + return 0; } +#endif /* CONFIG_PM */ + static struct pci_driver rtl8139_pci_driver = { - name: MODNAME, + name: DRV_NAME, id_table: rtl8139_pci_tbl, probe: rtl8139_init_one, remove: rtl8139_remove_one, +#ifdef CONFIG_PM suspend: rtl8139_suspend, resume: rtl8139_resume, +#endif /* CONFIG_PM */ }; diff -u --recursive --new-file v2.4.5/linux/drivers/net/82596.c linux/drivers/net/82596.c --- v2.4.5/linux/drivers/net/82596.c Thu Apr 12 12:15:25 2001 +++ linux/drivers/net/82596.c Wed Jun 20 11:10:53 2001 @@ -151,6 +151,7 @@ MODULE_AUTHOR("Richard Hirst"); MODULE_DESCRIPTION("i82596 driver"); MODULE_PARM(i596_debug, "i"); +MODULE_PARM_DESC(i596_debug, "i82596 debug mask"); /* Copy frames shorter than rx_copybreak, otherwise pass on up in @@ -1493,9 +1494,11 @@ static int io = 0x300; static int irq = 10; MODULE_PARM(irq, "i"); +MODULE_PARM_DESC(irq, "Apricot IRQ number"); #endif MODULE_PARM(debug, "i"); +MODULE_PARM_DESC(debug, "i82596 debug mask"); static int debug = -1; int init_module(void) diff -u --recursive --new-file v2.4.5/linux/drivers/net/Config.in linux/drivers/net/Config.in --- v2.4.5/linux/drivers/net/Config.in Sat May 19 17:55:11 2001 +++ linux/drivers/net/Config.in Mon Jul 2 14:03:04 2001 @@ -15,7 +15,9 @@ fi fi -tristate 'General Instruments Surfboard 1000' CONFIG_NET_SB1000 +if [ "$CONFIG_ISAPNP" = "y" -o "$CONFIG_ISAPNP" = "m" ]; then + tristate 'General Instruments Surfboard 1000' CONFIG_NET_SB1000 $CONFIG_ISAPNP +fi # # Ethernet @@ -26,12 +28,9 @@ bool 'Ethernet (10 or 100Mbit)' CONFIG_NET_ETHERNET if [ "$CONFIG_NET_ETHERNET" = "y" ]; then - if [ "$CONFIG_ARM" = "y" ]; then - if [ "$CONFIG_ARCH_ACORN" != "y" ]; then - tristate ' AM79C961A support' CONFIG_ARM_AM79C961A - else - source drivers/acorn/net/Config.in - fi + dep_bool ' ARM EBSA110 AM79C961A support' CONFIG_ARM_AM79C961A $CONFIG_ARCH_EBSA110 + if [ "$CONFIG_ARCH_ACORN" = "y" ]; then + source drivers/acorn/net/Config.in fi if [ "$CONFIG_PPC" = "y" ]; then tristate ' MACE (Power Mac ethernet) support' CONFIG_MACE @@ -64,6 +63,14 @@ if [ "$CONFIG_SUPERH" = "y" ]; then tristate ' National DP83902AV support' CONFIG_STNIC fi + dep_tristate ' Sun LANCE support' CONFIG_SUNLANCE $CONFIG_SBUS + if [ "$CONFIG_SBUS" = "y" -o "$CONFIG_PCI" = "y" ]; then + tristate ' Sun Happy Meal 10/100baseT support' CONFIG_HAPPYMEAL + fi + dep_tristate ' Sun BigMAC 10/100baseT support (EXPERIMENTAL)' CONFIG_SUNBMAC $CONFIG_SBUS $CONFIG_EXPERIMENTAL + dep_tristate ' Sun QuadEthernet support' CONFIG_SUNQE $CONFIG_SBUS + dep_tristate ' Sun LANCE support' CONFIG_SUNLANCE $CONFIG_SBUS + dep_tristate ' Sun GEM support' CONFIG_SUNGEM $CONFIG_PCI bool ' 3COM cards' CONFIG_NET_VENDOR_3COM if [ "$CONFIG_NET_VENDOR_3COM" = "y" ]; then dep_tristate ' 3c501 "EtherLink" support' CONFIG_EL1 $CONFIG_ISA @@ -85,24 +92,24 @@ dep_tristate ' AMD LANCE and PCnet (AT1500 and NE2100) support' CONFIG_LANCE $CONFIG_ISA bool ' Western Digital/SMC cards' CONFIG_NET_VENDOR_SMC if [ "$CONFIG_NET_VENDOR_SMC" = "y" ]; then - tristate ' WD80*3 support' CONFIG_WD80x3 - if [ "$CONFIG_MCA" = "y" ]; then - tristate ' SMC Ultra MCA support' CONFIG_ULTRAMCA - fi - tristate ' SMC Ultra support' CONFIG_ULTRA + dep_tristate ' WD80*3 support' CONFIG_WD80x3 $CONFIG_ISA + dep_tristate ' SMC Ultra MCA support' CONFIG_ULTRAMCA $CONFIG_MCA + dep_tristate ' SMC Ultra support' CONFIG_ULTRA $CONFIG_ISA dep_tristate ' SMC Ultra32 EISA support' CONFIG_ULTRA32 $CONFIG_EISA - tristate ' SMC 9194 support' CONFIG_SMC9194 + dep_tristate ' SMC 9194 support' CONFIG_SMC9194 $CONFIG_ISA fi bool ' Racal-Interlan (Micom) NI cards' CONFIG_NET_VENDOR_RACAL if [ "$CONFIG_NET_VENDOR_RACAL" = "y" ]; then - dep_tristate ' NI5010 support (EXPERIMENTAL)' CONFIG_NI5010 $CONFIG_EXPERIMENTAL - tristate ' NI5210 support' CONFIG_NI52 - tristate ' NI6510 support' CONFIG_NI65 + dep_tristate ' NI5010 support (EXPERIMENTAL)' CONFIG_NI5010 $CONFIG_ISA $CONFIG_EXPERIMENTAL + dep_tristate ' NI5210 support' CONFIG_NI52 $CONFIG_ISA + dep_tristate ' NI6510 support' CONFIG_NI65 $CONFIG_ISA fi - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate ' AT1700/1720 support (EXPERIMENTAL)' CONFIG_AT1700 + if [ "$CONFIG_ISA" = "y" -o "$CONFIG_MCA" = "y" ]; then + dep_tristate ' AT1700/1720 support (EXPERIMENTAL)' CONFIG_AT1700 $CONFIG_EXPERIMENTAL + fi + if [ "$CONFIG_ISA" = "y" -o "$CONFIG_EISA" = "y" -o "$CONFIG_MCA" = "y" ]; then + tristate ' DEPCA, DE10x, DE200, DE201, DE202, DE422 support' CONFIG_DEPCA fi - tristate ' DEPCA, DE10x, DE200, DE201, DE202, DE422 support' CONFIG_DEPCA if [ "$CONFIG_ISA" = "y" -o "$CONFIG_EISA" = "y" -o "$CONFIG_PCI" = "y" ]; then tristate ' HP 10/100VG PCLAN (ISA, EISA, PCI) support' CONFIG_HP100 fi @@ -131,7 +138,11 @@ tristate ' NE/2 (ne2000 MCA version) support' CONFIG_NE2_MCA tristate ' IBM LAN Adapter/A support' CONFIG_IBMLANA fi - bool ' EISA, VLB, PCI and on board controllers' CONFIG_NET_PCI + if [ "$CONFIG_ISA" = "y" -o "$CONFIG_PCI" = "y" ]; then + bool ' EISA, VLB, PCI and on board controllers' CONFIG_NET_PCI + else + define_bool CONFIG_NET_PCI n + fi if [ "$CONFIG_NET_PCI" = "y" ]; then dep_tristate ' AMD PCnet32 PCI support' CONFIG_PCNET32 $CONFIG_PCI dep_tristate ' Adaptec Starfire support (EXPERIMENTAL)' CONFIG_ADAPTEC_STARFIRE $CONFIG_PCI $CONFIG_EXPERIMENTAL @@ -139,16 +150,17 @@ dep_tristate ' Ansel Communications EISA 3200 support (EXPERIMENTAL)' CONFIG_AC3200 $CONFIG_EXPERIMENTAL fi - tristate ' Apricot Xen-II on board Ethernet' CONFIG_APRICOT + dep_tristate ' Apricot Xen-II on board Ethernet' CONFIG_APRICOT $CONFIG_ISA dep_tristate ' CS89x0 support' CONFIG_CS89x0 $CONFIG_ISA dep_tristate ' DECchip Tulip (dc21x4x) PCI support' CONFIG_TULIP $CONFIG_PCI + dep_mbool ' New bus configuration (EXPERIMENTAL)' CONFIG_TULIP_MWI $CONFIG_EXPERIMENTAL $CONFIG_TULIP + dep_mbool ' Use PCI shared mem for NIC registers' CONFIG_TULIP_MMIO $CONFIG_TULIP if [ "$CONFIG_PCI" = "y" -o "$CONFIG_EISA" = "y" ]; then tristate ' Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5 tristate ' Digi Intl. RightSwitch SE-X support' CONFIG_DGRS fi dep_tristate ' Davicom DM910x/DM980x support' CONFIG_DM9102 $CONFIG_PCI dep_tristate ' EtherExpressPro/100 support' CONFIG_EEPRO100 $CONFIG_PCI - dep_mbool ' Enable Power Management (EXPERIMENTAL)' CONFIG_EEPRO100_PM $CONFIG_EEPRO100 $CONFIG_EXPERIMENTAL dep_tristate ' Mylex EISA LNE390A/B support (EXPERIMENTAL)' CONFIG_LNE390 $CONFIG_EISA $CONFIG_EXPERIMENTAL dep_tristate ' Myson MTD-8xx PCI Ethernet support' CONFIG_FEALNX $CONFIG_PCI dep_tristate ' National Semiconductor DP8381x series PCI Ethernet support' CONFIG_NATSEMI $CONFIG_PCI @@ -167,9 +179,8 @@ fi dep_tristate ' VIA Rhine support' CONFIG_VIA_RHINE $CONFIG_PCI dep_tristate ' Winbond W89c840 Ethernet support' CONFIG_WINBOND_840 $CONFIG_PCI - dep_tristate ' Sun Happy Meal 10/100baseT PCI support' CONFIG_HAPPYMEAL $CONFIG_PCI if [ "$CONFIG_OBSOLETE" = "y" ]; then - bool ' Zenith Z-Note support (EXPERIMENTAL)' CONFIG_ZNET + dep_bool ' Zenith Z-Note support (EXPERIMENTAL)' CONFIG_ZNET $CONFIG_ISA fi if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_ORION" = "y" ]; then bool ' Philips SAA9730 Ethernet support (EXPERIMENTAL)' CONFIG_LAN_SAA9730 @@ -177,9 +188,11 @@ fi bool ' Pocket and portable adapters' CONFIG_NET_POCKET if [ "$CONFIG_NET_POCKET" = "y" ]; then - dep_tristate ' AT-LAN-TEC/RealTek pocket adapter support' CONFIG_ATP $CONFIG_ISA - tristate ' D-Link DE600 pocket adapter support' CONFIG_DE600 - tristate ' D-Link DE620 pocket adapter support' CONFIG_DE620 + if [ "$CONFIG_ISA" = "y" -a "$CONFIG_X86" = "y" ]; then + tristate ' AT-LAN-TEC/RealTek pocket adapter support' CONFIG_ATP + fi + dep_tristate ' D-Link DE600 pocket adapter support' CONFIG_DE600 $CONFIG_ISA + dep_tristate ' D-Link DE620 pocket adapter support' CONFIG_DE620 $CONFIG_ISA fi fi @@ -193,13 +206,10 @@ comment 'Ethernet (1000 Mbit)' dep_tristate 'Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support' CONFIG_ACENIC $CONFIG_PCI -if [ "$CONFIG_ACENIC" != "n" ]; then - bool ' Omit support for old Tigon I based AceNICs' CONFIG_ACENIC_OMIT_TIGON_I -fi +dep_mbool ' Omit support for old Tigon I based AceNICs' CONFIG_ACENIC_OMIT_TIGON_I $CONFIG_ACENIC +dep_tristate 'MyriCOM Gigabit Ethernet support' CONFIG_MYRI_SBUS $CONFIG_SBUS dep_tristate 'Packet Engines Hamachi GNIC-II support' CONFIG_HAMACHI $CONFIG_PCI -if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - dep_tristate 'Packet Engines Yellowfin Gigabit-NIC support (EXPERIMENTAL)' CONFIG_YELLOWFIN $CONFIG_PCI -fi +dep_tristate 'Packet Engines Yellowfin Gigabit-NIC support (EXPERIMENTAL)' CONFIG_YELLOWFIN $CONFIG_PCI $CONFIG_EXPERIMENTAL dep_tristate 'SysKonnect SK-98xx support' CONFIG_SK98LIN $CONFIG_PCI endmenu @@ -209,14 +219,14 @@ if [ "$CONFIG_PCI" = "y" -o "$CONFIG_EISA" = "y" ]; then tristate ' Digital DEFEA and DEFPA adapter support' CONFIG_DEFXX fi - tristate ' SysKonnect FDDI PCI support' CONFIG_SKFP + dep_tristate ' SysKonnect FDDI PCI support' CONFIG_SKFP $CONFIG_PCI fi if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then if [ "$CONFIG_INET" = "y" ]; then bool 'HIPPI driver support (EXPERIMENTAL)' CONFIG_HIPPI if [ "$CONFIG_HIPPI" = "y" -a "$CONFIG_PCI" = "y" ]; then - tristate ' Essential RoadRunner HIPPI PCI adapter support' CONFIG_ROADRUNNER + dep_tristate ' Essential RoadRunner HIPPI PCI adapter support' CONFIG_ROADRUNNER $CONFIG_PCI if [ "$CONFIG_ROADRUNNER" != "n" ]; then bool ' Use large TX/RX rings' CONFIG_ROADRUNNER_LARGE_RINGS fi @@ -224,9 +234,7 @@ fi fi -if [ ! "$CONFIG_PARPORT" = "n" ]; then - dep_tristate 'PLIP (parallel port) support' CONFIG_PLIP $CONFIG_PARPORT -fi +dep_tristate 'PLIP (parallel port) support' CONFIG_PLIP $CONFIG_PARPORT tristate 'PPP (point-to-point protocol) support' CONFIG_PPP if [ ! "$CONFIG_PPP" = "n" ]; then @@ -236,9 +244,7 @@ dep_tristate ' PPP support for sync tty ports' CONFIG_PPP_SYNC_TTY $CONFIG_PPP dep_tristate ' PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP dep_tristate ' PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP $CONFIG_PPP - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - dep_tristate ' PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP - fi + dep_tristate ' PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP $CONFIG_EXPERIMENTAL fi tristate 'SLIP (serial line) support' CONFIG_SLIP diff -u --recursive --new-file v2.4.5/linux/drivers/net/Makefile linux/drivers/net/Makefile --- v2.4.5/linux/drivers/net/Makefile Wed May 16 10:25:38 2001 +++ linux/drivers/net/Makefile Wed Jun 20 11:13:18 2001 @@ -30,7 +30,7 @@ endif subdir-$(CONFIG_NET_PCMCIA) += pcmcia -subdir-$(CONFIG_NET_RADIO) += wireless +subdir-$(CONFIG_NET_WIRELESS) += wireless subdir-$(CONFIG_TULIP) += tulip subdir-$(CONFIG_IRDA) += irda subdir-$(CONFIG_TR) += tokenring diff -u --recursive --new-file v2.4.5/linux/drivers/net/ac3200.c linux/drivers/net/ac3200.c --- v2.4.5/linux/drivers/net/ac3200.c Thu Apr 19 09:34:52 2001 +++ linux/drivers/net/ac3200.c Wed Jun 20 11:10:53 2001 @@ -344,6 +344,9 @@ MODULE_PARM(io, "1-" __MODULE_STRING(MAX_AC32_CARDS) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_AC32_CARDS) "i"); MODULE_PARM(mem, "1-" __MODULE_STRING(MAX_AC32_CARDS) "i"); +MODULE_PARM_DESC(io, "ac3200 I/O base adress(es)"); +MODULE_PARM_DESC(irq, "ac3200 IRQ number(s)"); +MODULE_PARM_DESC(mem, "ac3200 Memory base address(es)"); int init_module(void) diff -u --recursive --new-file v2.4.5/linux/drivers/net/acenic.c linux/drivers/net/acenic.c --- v2.4.5/linux/drivers/net/acenic.c Fri Apr 13 20:26:07 2001 +++ linux/drivers/net/acenic.c Thu Jun 28 14:47:10 2001 @@ -157,6 +157,9 @@ #define __devinit __init #endif +#ifndef min +#define min(a,b) (((a)<(b))?(a):(b)) +#endif #ifndef SMP_CACHE_BYTES #define SMP_CACHE_BYTES L1_CACHE_BYTES @@ -260,6 +263,11 @@ #define ace_if_down(dev) {do{} while(0);} #endif +#ifndef pci_set_dma_mask +#define pci_set_dma_mask(dev, mask) dev->dma_mask = mask; +#endif + + #if (LINUX_VERSION_CODE >= 0x02031b) #define NEW_NETINIT #define ACE_PROBE_ARG void @@ -510,7 +518,7 @@ static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1}; static char version[] __initdata = - "acenic.c: v0.80 03/08/2001 Jes Sorensen, linux-acenic@SunSITE.dk\n" + "acenic.c: v0.81 04/20/2001 Jes Sorensen, linux-acenic@SunSITE.dk\n" " http://home.cern.ch/~jes/gige/acenic.html\n"; static struct net_device *root_dev; @@ -741,7 +749,7 @@ #ifdef MODULE -MODULE_AUTHOR("Jes Sorensen "); +MODULE_AUTHOR("Jes Sorensen "); MODULE_DESCRIPTION("AceNIC/3C985/GA620 Gigabit Ethernet driver"); MODULE_PARM(link, "1-" __MODULE_STRING(8) "i"); MODULE_PARM(trace, "1-" __MODULE_STRING(8) "i"); @@ -1036,7 +1044,7 @@ u32 tig_ver, mac1, mac2, tmp, pci_state; int board_idx, ecode = 0; short i; - unsigned char cache; + unsigned char cache_size; ap = dev->priv; regs = ap->regs; @@ -1169,13 +1177,18 @@ * Ie. having two NICs in the machine, one will have the cache * line set at boot time, the other will not. */ - pci_read_config_byte(ap->pdev, PCI_CACHE_LINE_SIZE, &cache); - if ((cache << 2) != SMP_CACHE_BYTES) { + pci_read_config_byte(ap->pdev, PCI_CACHE_LINE_SIZE, &cache_size); + cache_size <<= 2; + if (cache_size != SMP_CACHE_BYTES) { printk(KERN_INFO " PCI cache line size set incorrectly " - "(%i bytes) by BIOS/FW, correcting to %i\n", - (cache << 2), SMP_CACHE_BYTES); - pci_write_config_byte(ap->pdev, PCI_CACHE_LINE_SIZE, - SMP_CACHE_BYTES >> 2); + "(%i bytes) by BIOS/FW, ", cache_size); + if (cache_size > SMP_CACHE_BYTES) + printk("expecting %i\n", SMP_CACHE_BYTES); + else { + printk("correcting to %i\n", SMP_CACHE_BYTES); + pci_write_config_byte(ap->pdev, PCI_CACHE_LINE_SIZE, + SMP_CACHE_BYTES >> 2); + } } pci_state = readl(®s->PciState); @@ -1186,6 +1199,12 @@ ap->pci_latency); /* + * Make sure to enable the 64 bit DMA mask if we're in a 64bit slot + */ + if (!(pci_state & PCI_32BIT)) + pci_set_dma_mask(ap->pdev, (dma_addr_t)~0ULL); + + /* * Set the max DMA transfer size. Seems that for most systems * the performance is better when no MAX parameter is * set. However for systems enabling PCI write and invalidate, @@ -1210,21 +1229,10 @@ printk(KERN_INFO " Disabling PCI memory " "write and invalidate\n"); } -#ifdef __alpha__ - /* This maximizes throughput on my alpha. */ - tmp |= DMA_WRITE_MAX_128; -#endif } else if (ap->pci_command & PCI_COMMAND_INVALIDATE) { printk(KERN_INFO " PCI memory write & invalidate " "enabled by BIOS, enabling counter measures\n"); -#ifdef __alpha__ - /* All the docs sy MUST NOT. Well, I did. - * Nothing terrible happens, if we load wrong size. - * Bit w&i still works better! - */ - tmp |= DMA_WRITE_MAX_128; -#else switch(SMP_CACHE_BYTES) { case 16: tmp |= DMA_WRITE_MAX_16; @@ -1235,6 +1243,9 @@ case 64: tmp |= DMA_WRITE_MAX_64; break; + case 128: + tmp |= DMA_WRITE_MAX_128; + break; default: printk(KERN_INFO " Cache line size %i not " "supported, PCI write and invalidate " @@ -1243,7 +1254,6 @@ pci_write_config_word(ap->pdev, PCI_COMMAND, ap->pci_command); } -#endif } } @@ -1259,12 +1269,19 @@ * set will give the PCI controller proper hints about * prefetching. */ - tmp = tmp & ~DMA_READ_WRITE_MASK; + tmp &= ~DMA_READ_WRITE_MASK; tmp |= DMA_READ_MAX_64; tmp |= DMA_WRITE_MAX_64; #endif #ifdef __alpha__ + tmp &= ~DMA_READ_WRITE_MASK; tmp |= DMA_READ_MAX_128; + /* + * All the docs sy MUST NOT. Well, I did. + * Nothing terrible happens, if we load wrong size. + * Bit w&i still works better! + */ + tmp |= DMA_WRITE_MAX_128; #endif writel(tmp, ®s->PciState); @@ -3318,6 +3335,6 @@ /* * Local variables: - * compile-command: "gcc -D__KERNEL__ -DMODULE -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -DMODVERSIONS -include ../../include/linux/modversions.h -c -o acenic.o acenic.c" + * compile-command: "gcc -D__SMP__ -D__KERNEL__ -DMODULE -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -DMODVERSIONS -include ../../include/linux/modversions.h -c -o acenic.o acenic.c" * End: */ diff -u --recursive --new-file v2.4.5/linux/drivers/net/acenic.h linux/drivers/net/acenic.h --- v2.4.5/linux/drivers/net/acenic.h Sun May 20 12:11:38 2001 +++ linux/drivers/net/acenic.h Thu Jun 28 14:47:10 2001 @@ -207,8 +207,8 @@ /* * udelay() values for when clocking the eeprom */ -#define ACE_SHORT_DELAY 1 -#define ACE_LONG_DELAY 2 +#define ACE_SHORT_DELAY 2 +#define ACE_LONG_DELAY 4 /* diff -u --recursive --new-file v2.4.5/linux/drivers/net/aironet4500_card.c linux/drivers/net/aironet4500_card.c --- v2.4.5/linux/drivers/net/aironet4500_card.c Thu Apr 19 09:34:52 2001 +++ linux/drivers/net/aironet4500_card.c Wed Jun 20 11:10:53 2001 @@ -707,14 +707,14 @@ awc_i365_card_release(s); - udelay(100000); + mdelay(100); i365_out(s, 0x2, 0x10 ); // power enable - udelay(200000); + mdelay(200); i365_out(s, 0x2, 0x10 | 0x01 | 0x04 | 0x80); //power enable - udelay(250000); + mdelay(250); if (!s->irq) s->irq = 11; @@ -740,7 +740,7 @@ i365_out(s,0x15,0x3f | 0x40); // enab mem reg bit i365_out(s,0x06,0x01); // enab mem - udelay(10000); + mdelay(10); cis[0] = 0x45; @@ -751,7 +751,7 @@ mem[0x3e0] = 0x45; - udelay(10000); + mdelay(10); memcpy_fromio(cis,0xD000, 0x3e0); @@ -779,7 +779,7 @@ s->socket, s->manufacturer,s->product); i365_out(s,0x07, 0x1 | 0x2); // enable io 16bit - udelay(1000); + mdelay(1); port = s->io; i365_out(s,0x08, port & 0xff); i365_out(s,0x09, (port & 0xff00)/ 0x100); @@ -788,7 +788,7 @@ i365_out(s,0x06, 0x40); // enable io window - udelay(1000); + mdelay(1); i365_out(s,0x3e0,0x45); @@ -806,13 +806,10 @@ outw(0x10, s->io + 0x34); - udelay(10000); + mdelay(10); return 0; - - - }; diff -u --recursive --new-file v2.4.5/linux/drivers/net/aironet4500_core.c linux/drivers/net/aironet4500_core.c --- v2.4.5/linux/drivers/net/aironet4500_core.c Tue Feb 13 13:15:05 2001 +++ linux/drivers/net/aironet4500_core.c Wed Jun 20 11:10:53 2001 @@ -2567,7 +2567,7 @@ MODULE_PARM(rx_queue_len,"i"); MODULE_PARM(tx_rate,"i"); MODULE_PARM(channel,"i"); -MODULE_PARM(tx_full_rate,"i"); +//MODULE_PARM(tx_full_rate,"i"); MODULE_PARM(adhoc,"i"); MODULE_PARM(master,"i"); MODULE_PARM(slave,"i"); @@ -2576,6 +2576,12 @@ MODULE_PARM(large_buff_mem,"i"); MODULE_PARM(small_buff_no,"i"); MODULE_PARM(SSID,"c33"); +MODULE_PARM_DESC(awc_debug,"Aironet debug mask"); +MODULE_PARM_DESC(channel,"Aironet "); +MODULE_PARM_DESC(adhoc,"Aironet Access Points not available (0-1)"); +MODULE_PARM_DESC(master,"Aironet is Adhoc master (creates network sync) (0-1)"); +MODULE_PARM_DESC(slave,"Aironet is Adhoc slave (0-1)"); +MODULE_PARM_DESC(max_mtu,"Aironet MTU limit (256-2312)"); #endif /*EXPORT_SYMBOL(tx_queue_len); diff -u --recursive --new-file v2.4.5/linux/drivers/net/aironet4500_proc.c linux/drivers/net/aironet4500_proc.c --- v2.4.5/linux/drivers/net/aironet4500_proc.c Tue Feb 13 13:15:04 2001 +++ linux/drivers/net/aironet4500_proc.c Mon Jul 2 14:03:04 2001 @@ -1,5 +1,5 @@ /* - * Aironet 4500 Pcmcia driver + * Aironet 4500 /proc interface * * Elmer Joandi, Januar 1999 * Copyright GPL diff -u --recursive --new-file v2.4.5/linux/drivers/net/am79c961a.c linux/drivers/net/am79c961a.c --- v2.4.5/linux/drivers/net/am79c961a.c Thu Apr 12 12:15:25 2001 +++ linux/drivers/net/am79c961a.c Wed Jun 27 14:12:04 2001 @@ -1,7 +1,7 @@ /* * linux/drivers/net/am79c961.c * - * by Russell King 1995-2000. + * by Russell King 1995-2001. * * 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 @@ -10,9 +10,9 @@ * Derived from various things including skeleton.c * * This is a special driver for the am79c961A Lance chip used in the - * Intel (formally Digital Equipment Corp) EBSA110 platform. + * Intel (formally Digital Equipment Corp) EBSA110 platform. Please + * note that this can not be built as a module (it doesn't make sense). */ -#include #include #include #include @@ -35,7 +35,6 @@ #include #include #include -#include #define TX_BUFFERS 15 #define RX_BUFFERS 25 @@ -46,45 +45,42 @@ static unsigned int net_debug = NET_DEBUG; -static char *version = "am79c961 ethernet driver (c) 1995 R.M.King v0.02\n"; +static const char version[] = + "am79c961 ethernet driver (C) 1995-2001 Russell King v0.04\n"; /* --------------------------------------------------------------------------- */ #ifdef __arm__ -static void -write_rreg (unsigned long base, unsigned int reg, unsigned short val) +static void write_rreg(u_long base, u_int reg, u_int val) { __asm__("str%?h %1, [%2] @ NET_RAP str%?h %0, [%2, #-4] @ NET_RDP - " : : "r" (val), "r" (reg), "r" (0xf0000464)); + " : : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464)); } -static inline unsigned short -read_rreg (unsigned int base_addr, unsigned int reg) +static inline unsigned short read_rreg(u_long base_addr, u_int reg) { unsigned short v; __asm__("str%?h %1, [%2] @ NET_RAP ldr%?h %0, [%2, #-4] @ NET_RDP - " : "=r" (v): "r" (reg), "r" (0xf0000464)); + " : "=r" (v): "r" (reg), "r" (ISAIO_BASE + 0x0464)); return v; } -static inline void -write_ireg (unsigned long base, unsigned int reg, unsigned short val) +static inline void write_ireg(u_long base, u_int reg, u_int val) { __asm__("str%?h %1, [%2] @ NET_RAP str%?h %0, [%2, #8] @ NET_IDP - " : : "r" (val), "r" (reg), "r" (0xf0000464)); + " : : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464)); } -#define am_writeword(dev,off,val)\ - __asm__("str%?h %0, [%1]" : : \ - "r" ((val) & 0xffff), "r" (0xe0000000 + ((off) << 1))); +#define am_writeword(dev,off,val) __raw_writew(val, ISAMEM_BASE + ((off) << 1)) +#define am_readword(dev,off) __raw_readw(ISAMEM_BASE + ((off) << 1)) static inline void am_writebuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned int length) { - offset = 0xe0000000 + (offset << 1); + offset = ISAMEM_BASE + (offset << 1); length = (length + 1) & ~1; if ((int)buf & 2) { __asm__ __volatile__("str%?h %2, [%0], #4" @@ -114,23 +110,10 @@ } } -/* - * This reads a 16-bit quantity in little-endian - * mode from the am79c961 buffer. - */ -static inline unsigned short am_readword(struct net_device *dev, u_int off) -{ - unsigned long address = 0xe0000000 + (off << 1); - unsigned short val; - - __asm__("ldr%?h %0, [%1]" : "=r" (val): "r" (address)); - return val; -} - static inline void am_readbuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned int length) { - offset = 0xe0000000 + (offset << 1); + offset = ISAMEM_BASE + (offset << 1); length = (length + 1) & ~1; if ((int)buf & 2) { unsigned int tmp; @@ -274,12 +257,7 @@ } /* - * Open/initialize the board. This is called (in the current kernel) - * sometime after booting when the 'ifconfig' program is run. - * - * This routine should set everything up anew at each open, even - * registers that "should" only need to be set once at boot, so that - * there is non-reboot way to recover if something goes wrong. + * Open/initialize the board. */ static int am79c961_open(struct net_device *dev) @@ -322,8 +300,7 @@ } /* - * Get the current statistics. This may be called with the card open or - * closed. + * Get the current statistics. */ static struct net_device_stats *am79c961_getstats (struct net_device *dev) { @@ -367,7 +344,7 @@ } /* - * Set or clear promiscuous/multicast mode filter for this adaptor. + * Set or clear promiscuous/multicast mode filter for this adapter. */ static void am79c961_setmulticastlist (struct net_device *dev) { @@ -478,10 +455,8 @@ * then the tx ring is full and we can't add another * packet. */ - if (am_readword(dev, priv->txhdr + (priv->txhead << 3) + 2) & TMD_OWN) { - printk(KERN_DEBUG"tx ring full, stopping queue\n"); + if (am_readword(dev, priv->txhdr + (priv->txhead << 3) + 2) & TMD_OWN) netif_stop_queue(dev); - } dev_kfree_skb(skb); @@ -557,9 +532,7 @@ do { u_int hdraddr; u_int status; -int bufnum; -bufnum = priv->txtail; hdraddr = priv->txhdr + (priv->txtail << 3); status = am_readword (dev, hdraddr + 2); if (status & TMD_OWN) @@ -654,7 +627,6 @@ if (!dev) goto out; - SET_MODULE_OWNER(dev); priv = dev->priv; /* @@ -668,7 +640,7 @@ /* * Reset the device. */ - inb((dev->base_addr + NET_RESET) >> 1); + inb(dev->base_addr + NET_RESET); udelay(5); /* @@ -676,21 +648,20 @@ * ether address. */ ret = -ENODEV; - if (inb(dev->base_addr >> 1) != 0x08 || - inb((dev->base_addr >> 1) + 1) != 00 || - inb((dev->base_addr >> 1) + 2) != 0x2b) + if (inb(dev->base_addr) != 0x08 || + inb(dev->base_addr + 2) != 0x00 || + inb(dev->base_addr + 4) != 0x2b) goto nodev; if (!request_region(dev->base_addr, 0x18, dev->name)) goto nodev; am79c961_banner(); - printk(KERN_INFO "%s: am79c961 found at %08lx, IRQ%d, ether address ", - dev->name, dev->base_addr, dev->irq); + printk(KERN_INFO "%s: ether address ", dev->name); /* Retrive and print the ethernet address. */ for (i = 0; i < 6; i++) { - dev->dev_addr[i] = inb((dev->base_addr >> 1) + i) & 0xff; + dev->dev_addr[i] = inb(dev->base_addr + i * 2) & 0xff; printk (i == 5 ? "%02x\n" : "%02x:", dev->dev_addr[i]); } @@ -715,4 +686,4 @@ return ret; } -module_init(am79c961_init); +__initcall(am79c961_init); diff -u --recursive --new-file v2.4.5/linux/drivers/net/appletalk/ipddp.c linux/drivers/net/appletalk/ipddp.c --- v2.4.5/linux/drivers/net/appletalk/ipddp.c Wed May 16 10:31:27 2001 +++ linux/drivers/net/appletalk/ipddp.c Wed Jun 27 17:10:55 2001 @@ -255,22 +255,26 @@ static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct ipddp_route *rt = (struct ipddp_route *)ifr->ifr_data; + struct ipddp_route rcp; if(!capable(CAP_NET_ADMIN)) return -EPERM; + if(copy_from_user(&rcp, rt, sizeof(rcp))) + return -EFAULT; + switch(cmd) { case SIOCADDIPDDPRT: - return (ipddp_create(rt)); + return (ipddp_create(&rcp)); case SIOCFINDIPDDPRT: - if(copy_to_user(rt, ipddp_find_route(rt), sizeof(struct ipddp_route))) + if(copy_to_user(rt, ipddp_find_route(&rcp), sizeof(struct ipddp_route))) return -EFAULT; return 0; case SIOCDELIPDDPRT: - return (ipddp_delete(rt)); + return (ipddp_delete(&rcp)); default: return -EINVAL; diff -u --recursive --new-file v2.4.5/linux/drivers/net/arlan.c linux/drivers/net/arlan.c --- v2.4.5/linux/drivers/net/arlan.c Tue Mar 6 19:28:33 2001 +++ linux/drivers/net/arlan.c Wed Jun 20 11:10:53 2001 @@ -68,6 +68,23 @@ MODULE_PARM(arlan_exit_debug, "i"); MODULE_PARM(arlan_entry_and_exit_debug, "i"); MODULE_PARM(arlan_EEPROM_bad, "i"); +MODULE_PARM_DESC(irq, "(unused)"); +MODULE_PARM_DESC(mem, "Arlan memory address for single device probing"); +MODULE_PARM_DESC(probe, "Arlan probe at initialization (0-1)"); +MODULE_PARM_DESC(arlan_debug, "Arlan debug enable (0-1)"); +MODULE_PARM_DESC(numDevices, "Number of Arlan devices; ignored if >1"); +MODULE_PARM_DESC(testMemory, "(unused)"); +MODULE_PARM_DESC(mdebug, "Arlan multicast debugging (0-1)"); +MODULE_PARM_DESC(retries, "Arlan maximum packet retransmisions"); +#ifdef ARLAN_ENTRY_EXIT_DEBUGGING +MODULE_PARM_DESC(arlan_entry_debug, "Arlan driver function entry debugging"); +MODULE_PARM_DESC(arlan_exit_debug, "Arlan driver function exit debugging"); +MODULE_PARM_DESC(arlan_entry_and_exit_debug, "Arlan driver function entry and exit debugging"); +#else +MODULE_PARM_DESC(arlan_entry_debug, "(ignored)"); +MODULE_PARM_DESC(arlan_exit_debug, "(ignored)"); +MODULE_PARM_DESC(arlan_entry_and_exit_debug, "(ignored)"); +#endif EXPORT_SYMBOL(arlan_device); EXPORT_SYMBOL(arlan_conf); diff -u --recursive --new-file v2.4.5/linux/drivers/net/at1700.c linux/drivers/net/at1700.c --- v2.4.5/linux/drivers/net/at1700.c Tue Feb 13 13:15:05 2001 +++ linux/drivers/net/at1700.c Wed Jun 20 11:13:18 2001 @@ -70,7 +70,7 @@ /* These unusual address orders are used to verify the CONFIG register. */ -static int fmv18x_probe_list[] = { +static int fmv18x_probe_list[] __initdata = { 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0 }; @@ -78,7 +78,7 @@ * ISA */ -static int at1700_probe_list[] = { +static int at1700_probe_list[] __initdata = { 0x260, 0x280, 0x2a0, 0x240, 0x340, 0x320, 0x380, 0x300, 0 }; @@ -86,15 +86,15 @@ * MCA */ #ifdef CONFIG_MCA -static int at1700_ioaddr_pattern[] = { +static int at1700_ioaddr_pattern[] __initdata = { 0x00, 0x04, 0x01, 0x05, 0x02, 0x06, 0x03, 0x07 }; -static int at1700_mca_probe_list[] = { +static int at1700_mca_probe_list[] __initdata = { 0x400, 0x1400, 0x2400, 0x3400, 0x4400, 0x5400, 0x6400, 0x7400, 0 }; -static int at1700_irq_pattern[] = { +static int at1700_irq_pattern[] __initdata = { 0x00, 0x00, 0x00, 0x30, 0x70, 0xb0, 0x00, 0x00, 0x00, 0xf0, 0x34, 0x74, 0xb4, 0x00, 0x00, 0xf4, 0x00 }; @@ -175,10 +175,10 @@ }; /* rEnE : maybe there are others I don't know off... */ -static struct at1720_mca_adapters_struct at1720_mca_adapters[] = { +static struct at1720_mca_adapters_struct at1720_mca_adapters[] __initdata = { { "Allied Telesys AT1720AT", 0x6410 }, { "Allied Telesys AT1720BT", 0x6413 }, - { "Allied Telesys AT1720T", 0x6416 }, + { "Allied Telesys AT1720T", 0x6416 }, { NULL, 0 }, }; #endif @@ -470,7 +470,7 @@ #define EE_READ_CMD (6 << 6) #define EE_ERASE_CMD (7 << 6) -static int read_eeprom(int ioaddr, int location) +static int __init read_eeprom(int ioaddr, int location) { int i; unsigned short retval = 0; @@ -880,6 +880,9 @@ MODULE_PARM(io, "i"); MODULE_PARM(irq, "i"); MODULE_PARM(net_debug, "i"); +MODULE_PARM_DESC(io, "AT1700/FMV18X I/O base address"); +MODULE_PARM_DESC(irq, "AT1700/FMV18X IRQ number"); +MODULE_PARM_DESC(net_debug, "AT1700/FMV18X debug level (0-6)"); int init_module(void) { diff -u --recursive --new-file v2.4.5/linux/drivers/net/atari_bionet.c linux/drivers/net/atari_bionet.c --- v2.4.5/linux/drivers/net/atari_bionet.c Thu Apr 19 09:34:52 2001 +++ linux/drivers/net/atari_bionet.c Wed Jun 20 11:10:53 2001 @@ -127,6 +127,7 @@ */ unsigned int bionet_debug = NET_DEBUG; MODULE_PARM(bionet_debug, "i"); +MODULE_PARM_DESC(bionet_debug, "bionet debug level (0-2)"); static unsigned int bionet_min_poll_time = 2; diff -u --recursive --new-file v2.4.5/linux/drivers/net/atari_pamsnet.c linux/drivers/net/atari_pamsnet.c --- v2.4.5/linux/drivers/net/atari_pamsnet.c Thu Apr 12 12:15:25 2001 +++ linux/drivers/net/atari_pamsnet.c Wed Jun 20 11:10:53 2001 @@ -123,6 +123,7 @@ */ unsigned int pamsnet_debug = NET_DEBUG; MODULE_PARM(pamsnet_debug, "i"); +MODULE_PARM_DESC(pamsnet_debug, "pamsnet debug enable (0-1)"); static unsigned int pamsnet_min_poll_time = 2; diff -u --recursive --new-file v2.4.5/linux/drivers/net/atarilance.c linux/drivers/net/atarilance.c --- v2.4.5/linux/drivers/net/atarilance.c Fri Apr 20 11:54:22 2001 +++ linux/drivers/net/atarilance.c Wed Jun 20 11:10:53 2001 @@ -83,6 +83,7 @@ static int lance_debug = 1; #endif MODULE_PARM(lance_debug, "i"); +MODULE_PARM_DESC(lance_debug, "atarilance debug level (0-3)"); /* Print debug messages on probing? */ #undef LANCE_DEBUG_PROBE diff -u --recursive --new-file v2.4.5/linux/drivers/net/atp.c linux/drivers/net/atp.c --- v2.4.5/linux/drivers/net/atp.c Thu Apr 12 12:15:25 2001 +++ linux/drivers/net/atp.c Wed Jun 20 11:10:53 2001 @@ -153,9 +153,14 @@ MODULE_DESCRIPTION("RealTek RTL8002/8012 parallel port Ethernet driver"); MODULE_PARM(max_interrupt_work, "i"); MODULE_PARM(debug, "i"); -MODULE_PARM(io, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM(xcvr, "1-" __MODULE_STRING(MAX_UNITS) "i"); +MODULE_PARM(io, "1-" __MODULE_STRING(NUM_UNITS) "i"); +MODULE_PARM(irq, "1-" __MODULE_STRING(NUM_UNITS) "i"); +MODULE_PARM(xcvr, "1-" __MODULE_STRING(NUM_UNITS) "i"); +MODULE_PARM_DESC(max_interrupt_work, "ATP maximum events handled per interrupt"); +MODULE_PARM_DESC(debug, "ATP debug level (0-7)"); +MODULE_PARM_DESC(io, "ATP I/O base address(es)"); +MODULE_PARM_DESC(irq, "ATP IRQ number(s)"); +MODULE_PARM_DESC(xcvr, "ATP tranceiver(s) (0=internal, 1=external)"); #define RUN_AT(x) (jiffies + (x)) diff -u --recursive --new-file v2.4.5/linux/drivers/net/bagetlance.c linux/drivers/net/bagetlance.c --- v2.4.5/linux/drivers/net/bagetlance.c Thu Apr 12 12:15:25 2001 +++ linux/drivers/net/bagetlance.c Wed Jun 20 11:10:53 2001 @@ -1,5 +1,5 @@ /* $Id$ - * vmelance.c: Ethernet driver for VME Lance cards on Baget/MIPS + * bagetlance.c: Ethernet driver for VME Lance cards on Baget/MIPS * This code stealed and adopted from linux/drivers/net/atarilance.c * See that for author info * @@ -59,6 +59,7 @@ static int lance_debug = 1; #endif MODULE_PARM(lance_debug, "i"); +MODULE_PARM_DESC(lance_debug, "Lance debug level (0-3)"); /* Print debug messages on probing? */ #undef LANCE_DEBUG_PROBE diff -u --recursive --new-file v2.4.5/linux/drivers/net/cs89x0.c linux/drivers/net/cs89x0.c --- v2.4.5/linux/drivers/net/cs89x0.c Thu Apr 12 12:16:35 2001 +++ linux/drivers/net/cs89x0.c Wed Jun 20 11:10:53 2001 @@ -1607,6 +1607,25 @@ MODULE_PARM(dma , "i"); MODULE_PARM(dmasize , "i"); MODULE_PARM(use_dma , "i"); +MODULE_PARM_DESC(io, "cs89x0 I/O base address"); +MODULE_PARM_DESC(irq, "cs89x0 IRQ number"); +#if DEBUGGING +MODULE_PARM_DESC(debug, "cs89x0 debug level (0-6)"); +#else +MODULE_PARM_DESC(debug, "(ignored)"); +#endif +MODULE_PARM_DESC(media, "Set cs89x0 adapter(s) media type(s) (rj45,bnc,aui)"); +/* No other value than -1 for duplex seems to be currently interpreted */ +MODULE_PARM_DESC(duplex, "(ignored)"); +#if ALLOW_DMA +MODULE_PARM_DESC(dma , "cs89x0 ISA DMA channel; ignored if use_dma=0"); +MODULE_PARM_DESC(dmasize , "cs89x0 DMA size in kB (16,64); ignored if use_dma=0"); +MODULE_PARM_DESC(use_dma , "cs89x0 using DMA (0-1)"); +#else +MODULE_PARM_DESC(dma , "(ignored)"); +MODULE_PARM_DESC(dmasize , "(ignored)"); +MODULE_PARM_DESC(use_dma , "(ignored)"); +#endif MODULE_AUTHOR("Mike Cruse, Russwll Nelson , Andrew Morton "); diff -u --recursive --new-file v2.4.5/linux/drivers/net/de4x5.c linux/drivers/net/de4x5.c --- v2.4.5/linux/drivers/net/de4x5.c Fri Apr 13 20:26:07 2001 +++ linux/drivers/net/de4x5.c Wed Jun 20 11:10:53 2001 @@ -1044,6 +1044,9 @@ MODULE_PARM(de4x5_debug, "i"); MODULE_PARM(dec_only, "i"); MODULE_PARM(args, "s"); +MODULE_PARM_DESC(de4x5_debug, "de4x5 debug mask"); +MODULE_PARM_DESC(dec_only, "de4x5 probe only for Digital boards (0-1)"); +MODULE_PARM_DESC(args, "de4x5 full duplex and media type settings; see de4x5.c for details"); # else static int loading_module; #endif /* MODULE */ @@ -5784,6 +5787,7 @@ static struct net_device *mdev = NULL; static int io=0x0;/* EDIT THIS LINE FOR YOUR CONFIGURATION IF NEEDED */ MODULE_PARM(io, "i"); +MODULE_PARM_DESC(io, "de4x5 I/O base address"); int init_module(void) diff -u --recursive --new-file v2.4.5/linux/drivers/net/de600.c linux/drivers/net/de600.c --- v2.4.5/linux/drivers/net/de600.c Thu Apr 19 09:34:52 2001 +++ linux/drivers/net/de600.c Wed Jun 20 11:10:53 2001 @@ -113,9 +113,11 @@ static unsigned int de600_debug = DE600_DEBUG; MODULE_PARM(de600_debug, "i"); +MODULE_PARM_DESC(de600_debug, "DE-600 debug level (0-2)"); static unsigned int delay_time = 10; MODULE_PARM(delay_time, "i"); +MODULE_PARM_DESC(delay_time, "DE-600 deley on I/O in microseconds"); #ifdef FAKE_SMALL_MAX static unsigned long de600_rspace(struct sock *sk); diff -u --recursive --new-file v2.4.5/linux/drivers/net/de620.c linux/drivers/net/de620.c --- v2.4.5/linux/drivers/net/de620.c Thu Apr 19 09:34:52 2001 +++ linux/drivers/net/de620.c Wed Jun 20 11:10:53 2001 @@ -197,6 +197,12 @@ MODULE_PARM(irq, "i"); MODULE_PARM(clone, "i"); MODULE_PARM(de620_debug, "i"); +MODULE_PARM_DESC(bnc, "DE-620 set BNC medium (0-1)"); +MODULE_PARM_DESC(utp, "DE-620 set UTP medium (0-1)"); +MODULE_PARM_DESC(io, "DE-620 I/O base address,required"); +MODULE_PARM_DESC(irq, "DE-620 IRQ number,required"); +MODULE_PARM_DESC(clone, "Check also for non-D-Link DE-620 clones (0-1)"); +MODULE_PARM_DESC(de620_debug, "DE-620 debug level (0-2)"); /*********************************************** * * diff -u --recursive --new-file v2.4.5/linux/drivers/net/declance.c linux/drivers/net/declance.c --- v2.4.5/linux/drivers/net/declance.c Thu Apr 12 12:15:25 2001 +++ linux/drivers/net/declance.c Mon Jul 2 14:03:04 2001 @@ -83,7 +83,7 @@ #include #ifndef CONFIG_TC -unsigned long system_base = 0; +unsigned long system_base; unsigned long dmaptr; #endif static int type; diff -u --recursive --new-file v2.4.5/linux/drivers/net/defxx.c linux/drivers/net/defxx.c --- v2.4.5/linux/drivers/net/defxx.c Fri Apr 20 11:54:23 2001 +++ linux/drivers/net/defxx.c Sat Jun 30 10:36:37 2001 @@ -2732,7 +2732,7 @@ for (i = 0; i < (int)(bp->rcv_bufs_to_post); i++) for (j = 0; (i + j) < (int)PI_RCV_DATA_K_NUM_ENTRIES; j += bp->rcv_bufs_to_post) { - struct sk_buff *newskb = __dev_alloc_skb(NEW_SKB_SIZE, GFP_BUFFER); + struct sk_buff *newskb = __dev_alloc_skb(NEW_SKB_SIZE, GFP_NOIO); if (!newskb) return -ENOMEM; bp->descr_block_virt->rcv_data[i+j].long_0 = (u32) (PI_RCV_DESCR_M_SOP | diff -u --recursive --new-file v2.4.5/linux/drivers/net/depca.c linux/drivers/net/depca.c --- v2.4.5/linux/drivers/net/depca.c Fri Apr 13 20:26:07 2001 +++ linux/drivers/net/depca.c Wed Jun 20 11:10:53 2001 @@ -2039,6 +2039,8 @@ static int io=0x200; /* Or use the irq= io= options to insmod */ MODULE_PARM(irq, "i"); MODULE_PARM(io, "i"); +MODULE_PARM_DESC(irq, "DEPCA IRQ number"); +MODULE_PARM_DESC(io, "DEPCA I/O base address"); /* See depca_probe() for autoprobe messages when a module */ int diff -u --recursive --new-file v2.4.5/linux/drivers/net/dgrs.c linux/drivers/net/dgrs.c --- v2.4.5/linux/drivers/net/dgrs.c Thu Apr 12 12:15:25 2001 +++ linux/drivers/net/dgrs.c Wed Jun 20 21:00:55 2001 @@ -538,7 +538,7 @@ break; /* For safety */ if ( (p-putp) >= len) { - printk("%s: cbp = %x\n", devN->name, H2S(cbp)); + printk("%s: cbp = %lx\n", devN->name, (long) H2S(cbp)); proc_reset(dev0, 1); /* Freeze IDT */ break; /* For Safety */ } @@ -607,7 +607,7 @@ break; /* For safety */ if ( (p-putp) >= len) { - printk("%s: cbp = %x\n", devN->name, H2S(cbp)); + printk("%s: cbp = %lx\n", devN->name, (long) H2S(cbp)); proc_reset(dev0, 1); /* Freeze IDT */ break; /* For Safety */ } @@ -642,7 +642,7 @@ break; /* For safety */ if ( (p-putp) >= len) { - printk("%s: cbp = %x\n", devN->name, H2S(cbp)); + printk("%s: cbp = %lx\n", devN->name, (long) H2S(cbp)); proc_reset(dev0, 1); /* Freeze IDT */ break; /* For Safety */ } @@ -1441,6 +1441,9 @@ MODULE_PARM(iptrap, "1-4i"); MODULE_PARM(ipxnet, "i"); MODULE_PARM(nicmode, "i"); +MODULE_PARM_DESC(debug, "Digi RightSwitch enable debugging (0-1)"); +MODULE_PARM_DESC(dma, "Digi RightSwitch enable BM DMA (0-1)"); +MODULE_PARM_DESC(nicmode, "Digi RightSwitch operating mode (1: switch, 2: multi-NIC)"); static int __init dgrs_init_module (void) { diff -u --recursive --new-file v2.4.5/linux/drivers/net/dmfe.c linux/drivers/net/dmfe.c --- v2.4.5/linux/drivers/net/dmfe.c Sat May 19 18:05:23 2001 +++ linux/drivers/net/dmfe.c Mon Jul 2 14:03:04 2001 @@ -77,6 +77,10 @@ #include #include +#if BITS_PER_LONG == 64 +#error FIXME: driver does not support 64-bit platforms +#endif + /* Board/System/Debug information/definition ---------------- */ #define PCI_DM9132_ID 0x91321282 /* Davicom DM9132 ID */ @@ -126,7 +130,7 @@ #define DMFE_TX_TIMEOUT (HZ * 1.5) /* tx packet time-out time 1.5 s" */ #define DMFE_TX_KICK (HZ * 0.5) /* tx packet Kick-out time 0.5 s" */ -#define DMFE_DBUG(dbug_now, msg, vaule) if (dmfe_debug || dbug_now) printk(KERN_ERR ": %s %x\n", msg, vaule) +#define DMFE_DBUG(dbug_now, msg, value) if (dmfe_debug || (dbug_now)) printk(KERN_ERR ": %s %lx\n", (msg), (long) (value)) #define SHOW_MEDIA_TYPE(mode) printk(KERN_ERR ": Change Speed to %sMhz %s duplex\n",mode & 1 ?"100":"10", mode & 4 ? "full":"half"); @@ -178,7 +182,7 @@ struct pci_dev * net_dev; /* PCI device */ spinlock_t lock; - u32 ioaddr; /* I/O base address */ + long ioaddr; /* I/O base address */ u32 cr0_data; u32 cr5_data; u32 cr6_data; @@ -202,10 +206,10 @@ struct rx_desc *first_rx_desc; struct rx_desc *rx_insert_ptr; struct rx_desc *rx_ready_ptr; /* packet come pointer */ - u32 tx_packet_cnt; /* transmitted packet count */ - u32 tx_queue_cnt; /* wait to send packet count */ - u32 rx_avail_cnt; /* available rx descriptor count */ - u32 interval_rx_cnt; /* rx packet count a callback time */ + unsigned long tx_packet_cnt; /* transmitted packet count */ + unsigned long tx_queue_cnt; /* wait to send packet count */ + unsigned long rx_avail_cnt; /* available rx descriptor count */ + unsigned long interval_rx_cnt; /* rx packet count a callback time */ u16 HPNA_command; /* For HPNA register 16 */ u16 HPNA_timer; /* For HPNA remote device check */ @@ -261,20 +265,20 @@ static char version[] __devinitdata = KERN_INFO "Davicom DM9xxx net driver, version " DMFE_VERSION "\n"; -static int dmfe_debug = 0; +static int dmfe_debug; static unsigned char dmfe_media_mode = DMFE_AUTO; -static u32 dmfe_cr6_user_set = 0; +static u32 dmfe_cr6_user_set; /* For module input parameter */ -static int debug = 0; -static u32 cr6set = 0; +static int debug; +static u32 cr6set; static unsigned char mode = 8; static u8 chkmode = 1; -static u8 HPNA_mode = 0; /* Default: Low Power/High Speed */ -static u8 HPNA_rx_cmd = 0; /* Default: Disable Rx remote command */ -static u8 HPNA_tx_cmd = 0; /* Default: Don't issue remote command */ -static u8 HPNA_NoiseFloor = 0; /* Default: HPNA NoiseFloor */ -static u8 SF_mode = 0; /* Special Function: 1:VLAN, 2:RX Flow Control +static u8 HPNA_mode; /* Default: Low Power/High Speed */ +static u8 HPNA_rx_cmd; /* Default: Disable Rx remote command */ +static u8 HPNA_tx_cmd; /* Default: Don't issue remote command */ +static u8 HPNA_NoiseFloor; /* Default: HPNA NoiseFloor */ +static u8 SF_mode; /* Special Function: 1:VLAN, 2:RX Flow Control 4: TX pause packet */ unsigned long CrcTable[256] = { @@ -353,15 +357,15 @@ static int dmfe_do_ioctl(struct DEVICE *, struct ifreq *, int); static u16 read_srom_word(long ,int); static void dmfe_interrupt(int , void *, struct pt_regs *); -static void dmfe_descriptor_init(struct dmfe_board_info *, u32); +static void dmfe_descriptor_init(struct dmfe_board_info *, unsigned long); static void allocated_rx_buffer(struct dmfe_board_info *); -static void update_cr6(u32, u32); +static void update_cr6(u32, unsigned long); static void send_filter_frame(struct DEVICE * ,int); static void dm9132_id_table(struct DEVICE * ,int); -static u16 phy_read(u32, u8, u8, u32); -static void phy_write(u32, u8, u8, u16, u32); -static void phy_write_1bit(u32, u32); -static u16 phy_read_1bit(u32); +static u16 phy_read(unsigned long, u8, u8, u32); +static void phy_write(unsigned long, u8, u8, u16, u32); +static void phy_write_1bit(unsigned long, u32); +static u16 phy_read_1bit(unsigned long); static u8 dmfe_sense_speed(struct dmfe_board_info *); static void dmfe_process_mode(struct dmfe_board_info *); static void dmfe_timer(unsigned long); @@ -603,7 +607,7 @@ static void dmfe_init_dm910x(struct DEVICE *dev) { struct dmfe_board_info *db = dev->priv; - u32 ioaddr = db->ioaddr; + unsigned long ioaddr = db->ioaddr; DMFE_DBUG(0, "dmfe_init_dm910x()", 0); @@ -689,7 +693,7 @@ /* No Tx resource check, it never happen nromally */ if (db->tx_queue_cnt >= TX_FREE_DESC_CNT) { spin_unlock_irqrestore(&db->lock, flags); - printk(KERN_ERR ": No Tx resource %d\n", db->tx_queue_cnt); + printk(KERN_ERR ": No Tx resource %ld\n", db->tx_queue_cnt); return 1; } @@ -738,7 +742,7 @@ static int dmfe_stop(struct DEVICE *dev) { struct dmfe_board_info *db = dev->priv; - u32 ioaddr = dev->base_addr; + unsigned long ioaddr = dev->base_addr; DMFE_DBUG(0, "dmfe_stop", 0); @@ -781,7 +785,7 @@ { struct DEVICE *dev = dev_id; struct dmfe_board_info *db = (struct dmfe_board_info *) dev->priv; - u32 ioaddr = dev->base_addr; + unsigned long ioaddr = dev->base_addr; unsigned long flags; DMFE_DBUG(0, "dmfe_interrupt()", 0); @@ -847,7 +851,7 @@ static void dmfe_free_tx_pkt(struct DEVICE *dev, struct dmfe_board_info * db) { struct tx_desc *txptr; - u32 ioaddr = dev->base_addr; + unsigned long ioaddr = dev->base_addr; txptr = db->tx_remove_ptr; while(db->tx_packet_cnt) { @@ -1271,7 +1275,7 @@ * Using Chain structure, and allocated Tx/Rx buffer */ -static void dmfe_descriptor_init(struct dmfe_board_info *db, u32 ioaddr) +static void dmfe_descriptor_init(struct dmfe_board_info *db, unsigned long ioaddr) { struct tx_desc *tmp_tx; struct rx_desc *tmp_rx; @@ -1330,11 +1334,11 @@ /* - * Update CR6 vaule + * Update CR6 value * Firstly stop DM910X , then written value and start */ -static void update_cr6(u32 cr6_data, u32 ioaddr) +static void update_cr6(u32 cr6_data, unsigned long ioaddr) { u32 cr6_tmp; @@ -1355,7 +1359,7 @@ { struct dev_mc_list *mcptr; u16 * addrptr; - u32 ioaddr = dev->base_addr+0xc0; /* ID Table */ + unsigned long ioaddr = dev->base_addr+0xc0; /* ID Table */ u32 hash_val; u16 i, hash_table[4]; @@ -1466,7 +1470,7 @@ while(db->rx_avail_cnt < RX_DESC_CNT) { if ( ( skb = dev_alloc_skb(RX_ALLOC_SIZE) ) == NULL ) break; - rxptr->rx_skb_ptr = (u32) skb; + rxptr->rx_skb_ptr = (u32) skb; /* FIXME */ rxptr->rdes2 = cpu_to_le32( pci_map_single(db->net_dev, skb->tail, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) ); rxptr->rdes0 = cpu_to_le32(0x80000000); rxptr = (struct rx_desc *) rxptr->next_rx_desc; @@ -1659,10 +1663,10 @@ * Write a word to Phy register */ -static void phy_write(u32 iobase, u8 phy_addr, u8 offset, u16 phy_data, u32 chip_id) +static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset, u16 phy_data, u32 chip_id) { u16 i; - u32 ioaddr; + unsigned long ioaddr; if (chip_id == PCI_DM9132_ID) { ioaddr = iobase + 0x80 + offset * 4; @@ -1706,11 +1710,11 @@ * Read a word data from phy register */ -static u16 phy_read(u32 iobase, u8 phy_addr, u8 offset, u32 chip_id) +static u16 phy_read(unsigned long iobase, u8 phy_addr, u8 offset, u32 chip_id) { int i; u16 phy_data; - u32 ioaddr; + unsigned long ioaddr; if (chip_id == PCI_DM9132_ID) { /* DM9132 Chip */ @@ -1758,7 +1762,7 @@ * Write one bit data to Phy Controller */ -static void phy_write_1bit(u32 ioaddr, u32 phy_data) +static void phy_write_1bit(unsigned long ioaddr, u32 phy_data) { outl(phy_data, ioaddr); /* MII Clock Low */ udelay(1); @@ -1773,7 +1777,7 @@ * Read one bit phy data from PHY controller */ -static u16 phy_read_1bit(u32 ioaddr) +static u16 phy_read_1bit(unsigned long ioaddr) { u16 phy_data; @@ -2014,7 +2018,10 @@ MODULE_PARM(HPNA_tx_cmd, "i"); MODULE_PARM(HPNA_NoiseFloor, "i"); MODULE_PARM(SF_mode, "i"); - +MODULE_PARM_DESC(debug, "Davicom DM9xxx enable debugging (0-1)"); +MODULE_PARM_DESC(mode, "Davicom DM9xxx: Bit 0: 10/100Mbps, bit 2: duplex, bit 8: HomePNA"); +MODULE_PARM_DESC(SF_mode, "Davicom DM9xxx special function (bit 0: VLAN, bit 1 Flow Control, bit 2: TX pause packet)"); + /* Description: * when user used insmod to add module, system invoked init_module() * to initilize and register. diff -u --recursive --new-file v2.4.5/linux/drivers/net/dummy.c linux/drivers/net/dummy.c --- v2.4.5/linux/drivers/net/dummy.c Sun Dec 3 17:45:22 2000 +++ linux/drivers/net/dummy.c Mon Jul 2 14:02:53 2001 @@ -54,33 +54,32 @@ static int __init dummy_init(struct net_device *dev) { /* Initialize the device structure. */ - dev->hard_start_xmit = dummy_xmit; dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL); if (dev->priv == NULL) return -ENOMEM; memset(dev->priv, 0, sizeof(struct net_device_stats)); - dev->get_stats = dummy_get_stats; + dev->get_stats = dummy_get_stats; + dev->hard_start_xmit = dummy_xmit; dev->set_multicast_list = set_multicast_list; +#ifdef CONFIG_NET_FASTROUTE + dev->accept_fastpath = dummy_accept_fastpath; +#endif - /* Fill in the fields of the device structure with ethernet-generic values. */ + /* Fill in device structure with ethernet-generic values. */ ether_setup(dev); dev->tx_queue_len = 0; dev->flags |= IFF_NOARP; dev->flags &= ~IFF_MULTICAST; -#ifdef CONFIG_NET_FASTROUTE - dev->accept_fastpath = dummy_accept_fastpath; -#endif return 0; } static int dummy_xmit(struct sk_buff *skb, struct net_device *dev) { - struct net_device_stats *stats; + struct net_device_stats *stats = dev->priv; - stats = (struct net_device_stats *)dev->priv; stats->tx_packets++; stats->tx_bytes+=skb->len; @@ -106,8 +105,9 @@ err=dev_alloc_name(&dev_dummy,"dummy%d"); if(err<0) return err; - if (register_netdev(&dev_dummy) != 0) - return -EIO; + err = register_netdev(&dev_dummy); + if (err<0) + return err; return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/net/e2100.c linux/drivers/net/e2100.c --- v2.4.5/linux/drivers/net/e2100.c Thu Apr 19 09:34:52 2001 +++ linux/drivers/net/e2100.c Wed Jun 20 11:10:53 2001 @@ -386,6 +386,10 @@ MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_E21_CARDS) "i"); MODULE_PARM(mem, "1-" __MODULE_STRING(MAX_E21_CARDS) "i"); MODULE_PARM(xcvr, "1-" __MODULE_STRING(MAX_E21_CARDS) "i"); +MODULE_PARM_DESC(io, "E2100 I/O base address(es)"); +MODULE_PARM_DESC(irq, "E2100 IRQ number(s)"); +MODULE_PARM_DESC(mem, " E2100 memory base address(es)"); +MODULE_PARM_DESC(xcvr, "E2100 tranceiver(s) (0=internal, 1=external)"); /* This is set up so that only a single autoprobe takes place per call. ISA device autoprobes on a running machine are not recommended. */ diff -u --recursive --new-file v2.4.5/linux/drivers/net/eepro.c linux/drivers/net/eepro.c --- v2.4.5/linux/drivers/net/eepro.c Thu Apr 19 09:34:52 2001 +++ linux/drivers/net/eepro.c Wed Jun 20 11:10:53 2001 @@ -1771,6 +1771,10 @@ MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_EEPRO) "i"); MODULE_PARM(mem, "1-" __MODULE_STRING(MAX_EEPRO) "i"); MODULE_PARM(autodetect, "1-" __MODULE_STRING(1) "i"); +MODULE_PARM_DESC(io, "EtherExpress Pro/10 I/O base addres(es)"); +MODULE_PARM_DESC(irq, "EtherExpress Pro/10 IRQ number(s)"); +MODULE_PARM_DESC(mem, "EtherExpress Pro/10 Rx buffer size(es) in kB (3-29)"); +MODULE_PARM_DESC(autodetect, "EtherExpress Pro/10 force board(s) detection (0-1)"); int init_module(void) diff -u --recursive --new-file v2.4.5/linux/drivers/net/eepro100.c linux/drivers/net/eepro100.c --- v2.4.5/linux/drivers/net/eepro100.c Tue Feb 13 13:15:05 2001 +++ linux/drivers/net/eepro100.c Mon Jul 2 14:03:04 2001 @@ -43,7 +43,7 @@ /* Set the copy breakpoint for the copy-only-tiny-buffer Rx method. Lower values use more memory, but are faster. */ -#if defined(__alpha__) || defined(__sparc__) +#if defined(__alpha__) || defined(__sparc__) || defined(__arm__) static int rx_copybreak = 1518; #else static int rx_copybreak = 200; @@ -102,6 +102,7 @@ #include #include #include +#include #include #include @@ -124,18 +125,29 @@ MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(max_interrupt_work, "i"); MODULE_PARM(multicast_filter_limit, "i"); +MODULE_PARM_DESC(debug, "eepro100 debug level (0-6)"); +MODULE_PARM_DESC(options, "eepro100: Bits 0-3: tranceiver type, bit 4: full duplex, bit 5: 100Mbps"); +MODULE_PARM_DESC(full_duplex, "eepro100 full duplex setting(s) (1)"); +MODULE_PARM_DESC(congenb, "eepro100 Enable congestion control (1)"); +MODULE_PARM_DESC(txfifo, "eepro100 Tx FIFO threshold in 4 byte units, (0-15)"); +MODULE_PARM_DESC(rxfifo, "eepro100 Rx FIFO threshold in 4 byte units, (0-15)"); +MODULE_PARM_DESC(txdmaccount, "eepro100 Tx DMA burst length; 128 - disable (0-128)"); +MODULE_PARM_DESC(rxdmaccount, "eepro100 Rx DMA burst length; 128 - disable (0-128)"); +MODULE_PARM_DESC(rx_copybreak, "eepro100 copy breakpoint for copy-only-tiny-frames"); +MODULE_PARM_DESC(max_interrupt_work, "eepro100 maximum events handled per interrupt"); +MODULE_PARM_DESC(multicast_filter_limit, "eepro100 maximum number of filtered multicast addresses"); #define RUN_AT(x) (jiffies + (x)) /* ACPI power states don't universally work (yet) */ -#ifndef CONFIG_EEPRO100_PM +#ifndef CONFIG_PM #undef pci_set_power_state #define pci_set_power_state null_set_power_state static inline int null_set_power_state(struct pci_dev *dev, int state) { return 0; } -#endif /* CONFIG_EEPRO100_PM */ +#endif /* CONFIG_PM */ #define netdevice_start(dev) #define netdevice_stop(dev) @@ -144,8 +156,6 @@ (dev)->tx_timeout = (tf); \ (dev)->watchdog_timeo = (tm); \ } while(0) -#define netif_device_attach(dev) netif_start_queue(dev) -#define netif_device_detach(dev) netif_stop_queue(dev) #ifndef PCI_DEVICE_ID_INTEL_ID1029 #define PCI_DEVICE_ID_INTEL_ID1029 0x1029 @@ -461,7 +471,6 @@ dma_addr_t last_rxf_dma; unsigned int cur_rx, dirty_rx; /* The next free ring entry */ long last_rx_time; /* Last Rx, in jiffies, to handle Rx hang. */ - const char *product_name; struct net_device_stats stats; struct speedo_stats *lstats; dma_addr_t lstats_dma; @@ -470,7 +479,7 @@ struct timer_list timer; /* Media selection timer. */ struct speedo_mc_block *mc_setup_head;/* Multicast setup frame list head. */ struct speedo_mc_block *mc_setup_tail;/* Multicast setup frame list tail. */ - int in_interrupt; /* Word-aligned dev->interrupt */ + long in_interrupt; /* Word-aligned dev->interrupt */ unsigned char acpi_pwr; signed char rx_mode; /* Current PROMISC/ALLMULTI setting. */ unsigned int tx_full:1; /* The Tx queue is full. */ @@ -512,9 +521,9 @@ 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_EEPRO100_PM -static void eepro100_suspend (struct pci_dev *pdev); -static void eepro100_resume (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); @@ -789,7 +798,7 @@ /* Return the chip to its original power state. */ pci_set_power_state(pdev, acpi_idle_state); - pdev->driver_data = dev; + pci_set_drvdata (pdev, dev); dev->base_addr = ioaddr; dev->irq = pdev->irq; @@ -1895,32 +1904,37 @@ { struct speedo_private *sp = (struct speedo_private *)dev->priv; long ioaddr = dev->base_addr; - u16 *data = (u16 *)&rq->ifr_data; + struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data; int phy = sp->phy[0] & 0x1f; int saved_acpi; int t; switch(cmd) { - case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ - data[0] = phy; - case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ + case SIOCGMIIPHY: /* Get address of MII PHY in use. */ + case SIOCDEVPRIVATE: /* for binary compat, remove in 2.5 */ + data->phy_id = phy; + + case SIOCGMIIREG: /* Read MII PHY register. */ + case SIOCDEVPRIVATE+1: /* for binary compat, remove in 2.5 */ /* FIXME: these operations need to be serialized with MDIO access from the timeout handler. They are currently serialized only with MDIO access from the timer routine. 2000/05/09 SAW */ saved_acpi = pci_set_power_state(sp->pdev, 0); t = del_timer_sync(&sp->timer); - data[3] = mdio_read(ioaddr, data[0], data[1]); + data->val_out = mdio_read(ioaddr, data->phy_id & 0x1f, data->reg_num & 0x1f); if (t) add_timer(&sp->timer); /* may be set to the past --SAW */ pci_set_power_state(sp->pdev, saved_acpi); return 0; - case SIOCDEVPRIVATE+2: /* Write the specified MII register */ + + case SIOCSMIIREG: /* Write MII PHY register. */ + case SIOCDEVPRIVATE+2: /* for binary compat, remove in 2.5 */ if (!capable(CAP_NET_ADMIN)) return -EPERM; saved_acpi = pci_set_power_state(sp->pdev, 0); t = del_timer_sync(&sp->timer); - mdio_write(ioaddr, data[0], data[1], data[2]); + mdio_write(ioaddr, data->phy_id, data->reg_num, data->val_in); if (t) add_timer(&sp->timer); /* may be set to the past --SAW */ pci_set_power_state(sp->pdev, saved_acpi); @@ -2129,24 +2143,31 @@ sp->rx_mode = new_rx_mode; } -#ifdef CONFIG_EEPRO100_PM -static void eepro100_suspend(struct pci_dev *pdev) +#ifdef CONFIG_PM +static int eepro100_suspend(struct pci_dev *pdev, u32 state) { - struct net_device *dev = pdev->driver_data; + struct net_device *dev = pci_get_drvdata (pdev); long ioaddr = dev->base_addr; + if (!netif_running(dev)) + return 0; + netif_device_detach(dev); outl(PortPartialReset, ioaddr + SCBPort); /* XXX call pci_set_power_state ()? */ + return 0; } -static void eepro100_resume(struct pci_dev *pdev) +static int eepro100_resume(struct pci_dev *pdev) { - struct net_device *dev = pdev->driver_data; + struct net_device *dev = pci_get_drvdata (pdev); struct speedo_private *sp = (struct speedo_private *)dev->priv; long ioaddr = dev->base_addr; + if (!netif_running(dev)) + return 0; + /* I'm absolutely uncertain if this part of code may work. The problems are: - correct hardware reinitialization; @@ -2160,12 +2181,13 @@ sp->rx_mode = -1; sp->flow_ctrl = sp->partner = 0; set_rx_mode(dev); + return 0; } -#endif /* CONFIG_EEPRO100_PM */ +#endif /* CONFIG_PM */ static void __devexit eepro100_remove_one (struct pci_dev *pdev) { - struct net_device *dev = pdev->driver_data; + struct net_device *dev = pci_get_drvdata (pdev); struct speedo_private *sp = (struct speedo_private *)dev->priv; unregister_netdev(dev); @@ -2192,7 +2214,7 @@ PCI_ANY_ID, PCI_ANY_ID, }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ID1030, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82820FW_4, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_7, PCI_ANY_ID, PCI_ANY_ID, }, { 0,} }; @@ -2203,10 +2225,10 @@ id_table: eepro100_pci_tbl, probe: eepro100_init_one, remove: eepro100_remove_one, -#ifdef CONFIG_EEPRO100_PM +#ifdef CONFIG_PM suspend: eepro100_suspend, resume: eepro100_resume, -#endif +#endif /* CONFIG_PM */ }; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,48) diff -u --recursive --new-file v2.4.5/linux/drivers/net/eexpress.c linux/drivers/net/eexpress.c --- v2.4.5/linux/drivers/net/eexpress.c Tue Mar 20 12:05:01 2001 +++ linux/drivers/net/eexpress.c Wed Jun 20 11:10:53 2001 @@ -1632,6 +1632,8 @@ MODULE_PARM(io, "1-" __MODULE_STRING(EEXP_MAX_CARDS) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(EEXP_MAX_CARDS) "i"); +MODULE_PARM_DESC(io, "EtherExpress 16 I/O base address(es)"); +MODULE_PARM_DESC(irq, "EtherExpress 16 IRQ number(s)"); /* Ideally the user would give us io=, irq= for every card. If any parameters * are specified, we verify and then use them. If no parameters are given, we diff -u --recursive --new-file v2.4.5/linux/drivers/net/epic100.c linux/drivers/net/epic100.c --- v2.4.5/linux/drivers/net/epic100.c Sat May 19 18:02:45 2001 +++ linux/drivers/net/epic100.c Mon Jul 2 14:03:04 2001 @@ -45,13 +45,16 @@ * { fill me in } LK1.1.8: - * ethtool support (jgarzik) + * ethtool driver info support (jgarzik) + + LK1.1.9: + * MII ioctl support (jgarzik) */ #define DRV_NAME "epic100" -#define DRV_VERSION "1.11+LK1.1.8" -#define DRV_RELDATE "May 18, 2001" +#define DRV_VERSION "1.11+LK1.1.9" +#define DRV_RELDATE "July 2, 2001" /* The user-configurable values. @@ -100,6 +103,7 @@ #error You must compile this driver with "-O". #endif +#include #include #include #include @@ -116,6 +120,7 @@ #include #include #include +#include #include #include #include @@ -135,6 +140,11 @@ MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); +MODULE_PARM_DESC(debug, "EPIC/100 debug level (0-5)"); +MODULE_PARM_DESC(max_interrupt_work, "EPIC/100 maximum events handled per interrupt"); +MODULE_PARM_DESC(options, "EPIC/100: Bits 0-3: media type, bit 4: full duplex"); +MODULE_PARM_DESC(rx_copybreak, "EPIC/100 copy breakpoint for copy-only-tiny-frames"); +MODULE_PARM_DESC(full_duplex, "EPIC/100 full duplex setting(s) (1)"); /* Theory of Operation @@ -1169,7 +1179,7 @@ if (pkt_len > PKT_BUF_SZ - 4) { printk(KERN_ERR "%s: Oversized Ethernet frame, status %x " "%d bytes.\n", - dev->name, pkt_len, status); + dev->name, status, pkt_len); pkt_len = 1514; } /* Check if the packet is long enough to accept without copying @@ -1344,27 +1354,30 @@ return; } -static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr) +static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr) { struct epic_private *np = dev->priv; u32 ethcmd; - - if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) + + if (copy_from_user (ðcmd, useraddr, sizeof (ethcmd))) return -EFAULT; - switch (ethcmd) { - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; - strcpy(info.driver, DRV_NAME); - strcpy(info.version, DRV_VERSION); - strcpy(info.bus_info, np->pci_dev->slot_name); - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; + switch (ethcmd) { + case ETHTOOL_GDRVINFO: + { + struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; + strcpy (info.driver, DRV_NAME); + strcpy (info.version, DRV_VERSION); + strcpy (info.bus_info, np->pci_dev->slot_name); + if (copy_to_user (useraddr, &info, sizeof (info))) + return -EFAULT; + return 0; + } + + default: + break; } - } - return -EOPNOTSUPP; } @@ -1372,20 +1385,24 @@ { struct epic_private *ep = dev->priv; long ioaddr = dev->base_addr; - u16 *data = (u16 *)&rq->ifr_data; + struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data; switch(cmd) { case SIOCETHTOOL: return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); - case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ - data[0] = ep->phys[0] & 0x1f; + + case SIOCGMIIPHY: /* Get address of MII PHY in use. */ + case SIOCDEVPRIVATE: /* for binary compat, remove in 2.5 */ + data->phy_id = ep->phys[0] & 0x1f; /* Fall Through */ - case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ + + case SIOCGMIIREG: /* Read MII PHY register. */ + case SIOCDEVPRIVATE+1: /* for binary compat, remove in 2.5 */ if (! netif_running(dev)) { outl(0x0200, ioaddr + GENCTL); outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL); } - data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f); + data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f); #if 0 /* Just leave on if the ioctl() is ever used. */ if (! netif_running(dev)) { outl(0x0008, ioaddr + GENCTL); @@ -1393,16 +1410,18 @@ } #endif return 0; - case SIOCDEVPRIVATE+2: /* Write the specified MII register */ + + case SIOCSMIIREG: /* Write MII PHY register. */ + case SIOCDEVPRIVATE+2: /* for binary compat, remove in 2.5 */ if (!capable(CAP_NET_ADMIN)) return -EPERM; if (! netif_running(dev)) { outl(0x0200, ioaddr + GENCTL); outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL); } - if (data[0] == ep->phys[0]) { - u16 value = data[2]; - switch (data[1]) { + if (data->phy_id == ep->phys[0]) { + u16 value = data->val_in; + switch (data->reg_num) { case 0: /* Check for autonegotiation on or reset. */ ep->duplex_lock = (value & 0x9000) ? 0 : 1; @@ -1413,7 +1432,7 @@ } /* Perhaps check_duplex(dev), depending on chip semantics. */ } - mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]); + mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in); #if 0 /* Leave on if the ioctl() is used. */ if (! netif_running(dev)) { outl(0x0008, ioaddr + GENCTL); @@ -1445,38 +1464,46 @@ } -static void epic_suspend (struct pci_dev *pdev) +#ifdef CONFIG_PM + +static int epic_suspend (struct pci_dev *pdev, u32 state) { struct net_device *dev = pci_get_drvdata(pdev); long ioaddr = dev->base_addr; if (!netif_running(dev)) - return; + return 0; epic_pause(dev); /* Put the chip into low-power mode. */ outl(0x0008, ioaddr + GENCTL); /* pci_power_off(pdev, -1); */ + return 0; } -static void epic_resume (struct pci_dev *pdev) +static int epic_resume (struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); if (!netif_running(dev)) - return; + return 0; epic_restart(dev); /* pci_power_on(pdev); */ + return 0; } +#endif /* CONFIG_PM */ + static struct pci_driver epic_driver = { name: DRV_NAME, id_table: epic_pci_tbl, probe: epic_init_one, remove: epic_remove_one, +#ifdef CONFIG_PM suspend: epic_suspend, resume: epic_resume, +#endif /* CONFIG_PM */ }; diff -u --recursive --new-file v2.4.5/linux/drivers/net/es3210.c linux/drivers/net/es3210.c --- v2.4.5/linux/drivers/net/es3210.c Thu Apr 19 09:34:52 2001 +++ linux/drivers/net/es3210.c Wed Jun 20 11:10:53 2001 @@ -383,6 +383,9 @@ MODULE_PARM(io, "1-" __MODULE_STRING(MAX_ES_CARDS) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_ES_CARDS) "i"); MODULE_PARM(mem, "1-" __MODULE_STRING(MAX_ES_CARDS) "i"); +MODULE_PARM_DESC(io, "ES3210 I/O base address(es)"); +MODULE_PARM_DESC(irq, "ES3210 IRQ number(s)"); +MODULE_PARM_DESC(mem, "ES3210 memory base address(es)"); int init_module(void) diff -u --recursive --new-file v2.4.5/linux/drivers/net/eth16i.c linux/drivers/net/eth16i.c --- v2.4.5/linux/drivers/net/eth16i.c Thu Apr 19 09:34:52 2001 +++ linux/drivers/net/eth16i.c Wed Jun 20 11:10:53 2001 @@ -1407,7 +1407,7 @@ MODULE_DESCRIPTION("ICL EtherTeam 16i/32 driver"); MODULE_PARM(io, "1-" __MODULE_STRING(MAX_ETH16I_CARDS) "i"); -MODULE_PARM_DESC(io, "eth16i io base address"); +MODULE_PARM_DESC(io, "eth16i I/O base address(es)"); #if 0 MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_ETH16I_CARDS) "i"); @@ -1415,10 +1415,10 @@ #endif MODULE_PARM(mediatype, "1-" __MODULE_STRING(MAX_ETH16I_CARDS) "s"); -MODULE_PARM_DESC(mediatype, "eth16i interfaceport mediatype"); +MODULE_PARM_DESC(mediatype, "eth16i media type of interface(s) (bnc,tp,dix,auto,eprom)"); MODULE_PARM(debug, "i"); -MODULE_PARM_DESC(debug, "eth16i debug level (0-4)"); +MODULE_PARM_DESC(debug, "eth16i debug level (0-6)"); #endif int init_module(void) diff -u --recursive --new-file v2.4.5/linux/drivers/net/ethertap.c linux/drivers/net/ethertap.c --- v2.4.5/linux/drivers/net/ethertap.c Thu Apr 12 12:15:25 2001 +++ linux/drivers/net/ethertap.c Wed Jun 20 11:10:53 2001 @@ -336,6 +336,7 @@ static int unit; MODULE_PARM(unit,"i"); +MODULE_PARM_DESC(unit,"Ethertap device number"); static struct net_device dev_ethertap = { diff -u --recursive --new-file v2.4.5/linux/drivers/net/ewrk3.c linux/drivers/net/ewrk3.c --- v2.4.5/linux/drivers/net/ewrk3.c Thu Apr 12 12:15:25 2001 +++ linux/drivers/net/ewrk3.c Wed Jun 27 17:10:55 2001 @@ -1633,38 +1633,44 @@ u_long iobase = dev->base_addr; int i, j, status = 0; u_char csr; - union { + union ewrk3_addr { u_char addr[HASH_TABLE_LEN * ETH_ALEN]; u_short val[(HASH_TABLE_LEN * ETH_ALEN) >> 1]; - } tmp; + }; + + union ewrk3_addr *tmp; + + tmp = kmalloc(sizeof(union ewrk3_addr), GFP_KERNEL); + if(tmp==NULL) + return -ENOMEM; switch (ioc->cmd) { case EWRK3_GET_HWADDR: /* Get the hardware address */ for (i = 0; i < ETH_ALEN; i++) { - tmp.addr[i] = dev->dev_addr[i]; + tmp->addr[i] = dev->dev_addr[i]; } ioc->len = ETH_ALEN; - if (copy_to_user(ioc->data, tmp.addr, ioc->len)) { + if (copy_to_user(ioc->data, tmp->addr, ioc->len)) status = -EFAULT; - break; - } + break; + case EWRK3_SET_HWADDR: /* Set the hardware address */ if (capable(CAP_NET_ADMIN)) { - csr = inb(EWRK3_CSR); - csr |= (CSR_TXD | CSR_RXD); - outb(csr, EWRK3_CSR); /* Disable the TX and RX */ - - if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN)) { - status = -EFAULT; - break; - } - for (i = 0; i < ETH_ALEN; i++) { - dev->dev_addr[i] = tmp.addr[i]; - outb(tmp.addr[i], EWRK3_PAR0 + i); - } + csr = inb(EWRK3_CSR); + csr |= (CSR_TXD | CSR_RXD); + outb(csr, EWRK3_CSR); /* Disable the TX and RX */ + + if (copy_from_user(tmp->addr, ioc->data, ETH_ALEN)) { + status = -EFAULT; + break; + } + for (i = 0; i < ETH_ALEN; i++) { + dev->dev_addr[i] = tmp->addr[i]; + outb(tmp->addr[i], EWRK3_PAR0 + i); + } - csr &= ~(CSR_TXD | CSR_RXD); /* Enable the TX and RX */ - outb(csr, EWRK3_CSR); + csr &= ~(CSR_TXD | CSR_RXD); /* Enable the TX and RX */ + outb(csr, EWRK3_CSR); } else { status = -EPERM; } @@ -1691,32 +1697,28 @@ } break; - case EWRK3_SAY_BOO: /* Say "Boo!" to the kernel log file */ - printk("%s: Boo!\n", dev->name); - - break; case EWRK3_GET_MCA: /* Get the multicast address table */ spin_lock_irq(&lp->hw_lock); if (lp->shmem_length == IO_ONLY) { outb(0, EWRK3_IOPR); outw(PAGE0_HTE, EWRK3_PIR1); for (i = 0; i < (HASH_TABLE_LEN >> 3); i++) { - tmp.addr[i] = inb(EWRK3_DATA); + tmp->addr[i] = inb(EWRK3_DATA); } } else { outb(0, EWRK3_MPR); - isa_memcpy_fromio(tmp.addr, lp->shmem_base + PAGE0_HTE, (HASH_TABLE_LEN >> 3)); + isa_memcpy_fromio(tmp->addr, lp->shmem_base + PAGE0_HTE, (HASH_TABLE_LEN >> 3)); } spin_unlock_irq(&lp->hw_lock); ioc->len = (HASH_TABLE_LEN >> 3); - if (copy_to_user(ioc->data, tmp.addr, ioc->len)) + if (copy_to_user(ioc->data, tmp->addr, ioc->len)) status = -EFAULT; break; case EWRK3_SET_MCA: /* Set a multicast address */ if (capable(CAP_NET_ADMIN)) { - if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len)) { + if (copy_from_user(tmp->addr, ioc->data, ETH_ALEN * ioc->len)) { status = -EFAULT; break; } @@ -1764,18 +1766,18 @@ break; case EWRK3_GET_CSR: /* Get the CSR Register contents */ - tmp.addr[0] = inb(EWRK3_CSR); + tmp->addr[0] = inb(EWRK3_CSR); ioc->len = 1; - if (copy_to_user(ioc->data, tmp.addr, ioc->len)) + if (copy_to_user(ioc->data, tmp->addr, ioc->len)) status = -EFAULT; break; case EWRK3_SET_CSR: /* Set the CSR Register contents */ if (capable(CAP_NET_ADMIN)) { - if (copy_from_user(tmp.addr, ioc->data, 1)) { + if (copy_from_user(tmp->addr, ioc->data, 1)) { status = -EFAULT; break; } - outb(tmp.addr[0], EWRK3_CSR); + outb(tmp->addr[0], EWRK3_CSR); } else { status = -EPERM; } @@ -1784,15 +1786,15 @@ case EWRK3_GET_EEPROM: /* Get the EEPROM contents */ if (capable(CAP_NET_ADMIN)) { for (i = 0; i < (EEPROM_MAX >> 1); i++) { - tmp.val[i] = (short) Read_EEPROM(iobase, i); + tmp->val[i] = (short) Read_EEPROM(iobase, i); } i = EEPROM_MAX; - tmp.addr[i++] = inb(EWRK3_CMR); /* Config/Management Reg. */ + tmp->addr[i++] = inb(EWRK3_CMR); /* Config/Management Reg. */ for (j = 0; j < ETH_ALEN; j++) { - tmp.addr[i++] = inb(EWRK3_PAR0 + j); + tmp->addr[i++] = inb(EWRK3_PAR0 + j); } ioc->len = EEPROM_MAX + 1 + ETH_ALEN; - if (copy_to_user(ioc->data, tmp.addr, ioc->len)) + if (copy_to_user(ioc->data, tmp->addr, ioc->len)) status = -EFAULT; } else { status = -EPERM; @@ -1801,12 +1803,12 @@ break; case EWRK3_SET_EEPROM: /* Set the EEPROM contents */ if (capable(CAP_NET_ADMIN)) { - if (copy_from_user(tmp.addr, ioc->data, EEPROM_MAX)) { + if (copy_from_user(tmp->addr, ioc->data, EEPROM_MAX)) { status = -EFAULT; break; } for (i = 0; i < (EEPROM_MAX >> 1); i++) { - Write_EEPROM(tmp.val[i], iobase, i); + Write_EEPROM(tmp->val[i], iobase, i); } } else { status = -EPERM; @@ -1814,9 +1816,9 @@ break; case EWRK3_GET_CMR: /* Get the CMR Register contents */ - tmp.addr[0] = inb(EWRK3_CMR); + tmp->addr[0] = inb(EWRK3_CMR); ioc->len = 1; - if (copy_to_user(ioc->data, tmp.addr, ioc->len)) + if (copy_to_user(ioc->data, tmp->addr, ioc->len)) status = -EFAULT; break; case EWRK3_SET_TX_CUT_THRU: /* Set TX cut through mode */ @@ -1838,7 +1840,7 @@ default: status = -EOPNOTSUPP; } - + kfree(tmp); return status; } @@ -1849,6 +1851,8 @@ MODULE_PARM(io, "i"); MODULE_PARM(irq, "i"); +MODULE_PARM_DESC(io, "EtherWORKS 3 I/O base address"); +MODULE_PARM_DESC(irq, "EtherWORKS 3 IRQ number"); int init_module(void) { diff -u --recursive --new-file v2.4.5/linux/drivers/net/fc/iph5526.c linux/drivers/net/fc/iph5526.c --- v2.4.5/linux/drivers/net/fc/iph5526.c Wed Apr 18 14:40:05 2001 +++ linux/drivers/net/fc/iph5526.c Wed Jun 20 11:19:02 2001 @@ -222,7 +222,7 @@ static int get_scsi_oxid(struct fc_info *fi); static void update_scsi_oxid(struct fc_info *fi); -Scsi_Host_Template driver_template = IPH5526_SCSI_FC; +static Scsi_Host_Template driver_template = IPH5526_SCSI_FC; static void iph5526_timeout(struct net_device *dev); diff -u --recursive --new-file v2.4.5/linux/drivers/net/fealnx.c linux/drivers/net/fealnx.c --- v2.4.5/linux/drivers/net/fealnx.c Thu May 24 15:37:37 2001 +++ linux/drivers/net/fealnx.c Mon Jul 2 14:03:04 2001 @@ -17,7 +17,7 @@ http://www.scyld.com/network/pci-skeleton.html */ -static int debug = 0; /* 1-> print debug message */ +static int debug; /* 1-> print debug message */ static int max_interrupt_work = 20; /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). */ @@ -25,7 +25,7 @@ /* Set the copy breakpoint for the copy-only-tiny-frames scheme. */ /* Setting to > 1518 effectively disables this feature. */ -static int rx_copybreak = 0; +static int rx_copybreak; /* Used to pass the media type, etc. */ /* Both 'options[]' and 'full_duplex[]' should exist for driver */ @@ -46,6 +46,8 @@ // #define RX_RING_SIZE 32 #define TX_RING_SIZE 6 #define RX_RING_SIZE 12 +#define TX_TOTAL_SIZE TX_RING_SIZE*sizeof(struct fealnx_desc) +#define RX_TOTAL_SIZE RX_RING_SIZE*sizeof(struct fealnx_desc) /* Operational parameters that usually are not changed. */ /* Time in jiffies before concluding the transmitter is hung. */ @@ -69,6 +71,7 @@ #include #include #include +#include #include /* Processor type for cache alignment. */ #include #include @@ -107,12 +110,18 @@ MODULE_AUTHOR("Myson or whoever"); MODULE_DESCRIPTION("Myson MTD-8xx 100/10M Ethernet PCI Adapter Driver"); MODULE_PARM(max_interrupt_work, "i"); -MODULE_PARM(min_pci_latency, "i"); +//MODULE_PARM(min_pci_latency, "i"); MODULE_PARM(debug, "i"); MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(multicast_filter_limit, "i"); MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); +MODULE_PARM_DESC(max_interrupt_work, "fealnx maximum events handled per interrupt"); +MODULE_PARM_DESC(debug, "fealnx enable debugging (0-1)"); +MODULE_PARM_DESC(rx_copybreak, "fealnx copy breakpoint for copy-only-tiny-frames"); +MODULE_PARM_DESC(multicast_filter_limit, "fealnx maximum number of filtered multicast addresses"); +MODULE_PARM_DESC(options, "fealnx: Bits 0-3: media type, bit 17: full duplex"); +MODULE_PARM_DESC(full_duplex, "fealnx full duplex setting(s) (1)"); #define MIN_REGION_SIZE 136 @@ -363,8 +372,11 @@ struct netdev_private { /* Descriptor rings first for alignment. */ - struct fealnx_desc rx_ring[RX_RING_SIZE]; - struct fealnx_desc tx_ring[TX_RING_SIZE]; + struct fealnx_desc *rx_ring; + struct fealnx_desc *tx_ring; + + dma_addr_t rx_ring_dma; + dma_addr_t tx_ring_dma; struct net_device_stats stats; @@ -461,6 +473,8 @@ long ioaddr; unsigned int chip_id = ent->driver_data; struct net_device *dev; + void *ring_space; + dma_addr_t ring_dma; /* when built into the kernel, we only print version if device is found */ #ifndef MODULE @@ -528,6 +542,22 @@ np->flags = skel_netdrv_tbl[chip_id].flags; pci_set_drvdata(pdev, dev); + ring_space = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma); + if (!ring_space) { + err = -ENOMEM; + goto err_out_free_dev; + } + np->rx_ring = (struct fealnx_desc *)ring_space; + np->rx_ring_dma = ring_dma; + + ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma); + if (!ring_space) { + err = -ENOMEM; + goto err_out_free_rx; + } + np->tx_ring = (struct fealnx_desc *)ring_space; + np->tx_ring_dma = ring_dma; + /* find the connected MII xcvrs */ if (np->flags == HAS_MII_XCVR) { int phy, phy_idx = 0; @@ -623,7 +653,7 @@ err = register_netdev(dev); if (err) - goto err_out_free; + goto err_out_free_tx; printk(KERN_INFO "%s: %s at 0x%lx, ", dev->name, skel_netdrv_tbl[chip_id].chip_name, ioaddr); @@ -633,7 +663,11 @@ return 0; -err_out_free: +err_out_free_tx: + pci_free_consistent(pdev, TX_TOTAL_SIZE, np->tx_ring, np->tx_ring_dma); +err_out_free_rx: + pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring, np->rx_ring_dma); +err_out_free_dev: kfree(dev); err_out_unmap: #ifndef USE_IO_OPS @@ -647,7 +681,14 @@ static void __devexit fealnx_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); + if (dev) { + struct netdev_private *np = dev->priv; + + pci_free_consistent(pdev, TX_TOTAL_SIZE, np->tx_ring, + np->tx_ring_dma); + pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring, + np->rx_ring_dma); unregister_netdev(dev); #ifndef USE_IO_OPS iounmap((void *)dev->base_addr); @@ -828,8 +869,8 @@ init_ring(dev); - writel(virt_to_bus(np->rx_ring), ioaddr + RXLBA); - writel(virt_to_bus(np->tx_ring), ioaddr + TXLBA); + writel(np->rx_ring_dma, ioaddr + RXLBA); + writel(np->tx_ring_dma, ioaddr + TXLBA); /* Initialize other registers. */ /* Configure the PCI bus bursts and FIFO thresholds. @@ -846,7 +887,7 @@ 1 1 1 256 Wait the specified 50 PCI cycles after a reset by initializing Tx and Rx queues and the address filter list. */ -#if defined(__powerpc__) +#if defined(__powerpc__) || defined(__sparc__) // 89/9/1 modify, // np->bcrvalue=0x04 | 0x0x38; /* big-endian, 256 burst length */ np->bcrvalue = 0x04 | 0x10; /* big-endian, tx 8 burst length */ @@ -1077,7 +1118,8 @@ break; /* Better luck next round. */ skb->dev = dev; /* Mark as being used by this device. */ - np->lack_rxbuf->buffer = virt_to_bus(skb->tail); + np->lack_rxbuf->buffer = pci_map_single(np->pci_dev, skb->tail, + np->rx_buf_sz, PCI_DMA_FROMDEVICE); np->lack_rxbuf = np->lack_rxbuf->next_desc_logical; ++np->really_rx_count; } @@ -1125,19 +1167,17 @@ printk(KERN_WARNING "%s: Transmit timed out, status %8.8x," " resetting...\n", dev->name, readl(ioaddr + ISR)); -#ifndef __alpha__ { int i; - printk(KERN_DEBUG " Rx ring %8.8x: ", (int) np->rx_ring); + printk(KERN_DEBUG " Rx ring %p: ", np->rx_ring); for (i = 0; i < RX_RING_SIZE; i++) printk(" %8.8x", (unsigned int) np->rx_ring[i].status); - printk("\n" KERN_DEBUG " Tx ring %8.8x: ", (int) np->tx_ring); + printk("\n" KERN_DEBUG " Tx ring %p: ", np->tx_ring); for (i = 0; i < TX_RING_SIZE; i++) printk(" %4.4x", np->tx_ring[i].status); printk("\n"); } -#endif /* Perhaps we should reinitialize the hardware here. Just trigger a Tx demand for now. */ @@ -1168,14 +1208,15 @@ for (i = 0; i < RX_RING_SIZE; i++) { np->rx_ring[i].status = 0; np->rx_ring[i].control = np->rx_buf_sz << RBSShift; - np->rx_ring[i].next_desc = virt_to_bus(&np->rx_ring[i + 1]); + np->rx_ring[i].next_desc = np->rx_ring_dma + + (i + 1)*sizeof(struct fealnx_desc); np->rx_ring[i].next_desc_logical = &np->rx_ring[i + 1]; np->rx_ring[i].skbuff = NULL; } /* for the last rx descriptor */ - np->rx_ring[i - 1].next_desc = virt_to_bus(&np->rx_ring[0]); - np->rx_ring[i - 1].next_desc_logical = &np->rx_ring[0]; + np->rx_ring[i - 1].next_desc = np->rx_ring_dma; + np->rx_ring[i - 1].next_desc_logical = np->rx_ring; /* allocate skb for rx buffers */ for (i = 0; i < RX_RING_SIZE; i++) { @@ -1189,7 +1230,8 @@ ++np->really_rx_count; np->rx_ring[i].skbuff = skb; skb->dev = dev; /* Mark as being used by this device. */ - np->rx_ring[i].buffer = virt_to_bus(skb->tail); + np->rx_ring[i].buffer = pci_map_single(np->pci_dev, skb->tail, + np->rx_buf_sz, PCI_DMA_FROMDEVICE); np->rx_ring[i].status = RXOWN; np->rx_ring[i].control |= RXIC; } @@ -1202,13 +1244,14 @@ for (i = 0; i < TX_RING_SIZE; i++) { np->tx_ring[i].status = 0; - np->tx_ring[i].next_desc = virt_to_bus(&np->tx_ring[i + 1]); + np->tx_ring[i].next_desc = np->tx_ring_dma + + (i + 1)*sizeof(struct fealnx_desc); np->tx_ring[i].next_desc_logical = &np->tx_ring[i + 1]; np->tx_ring[i].skbuff = NULL; } /* for the last tx descriptor */ - np->tx_ring[i - 1].next_desc = virt_to_bus(&np->tx_ring[0]); + np->tx_ring[i - 1].next_desc = np->tx_ring_dma; np->tx_ring[i - 1].next_desc_logical = &np->tx_ring[0]; return; @@ -1220,11 +1263,12 @@ struct netdev_private *np = dev->priv; np->cur_tx_copy->skbuff = skb; - np->cur_tx_copy->buffer = virt_to_bus(skb->data); #define one_buffer #define BPT 1022 #if defined(one_buffer) + np->cur_tx_copy->buffer = pci_map_single(np->pci_dev, skb->data, + skb->len, PCI_DMA_TODEVICE); np->cur_tx_copy->control = TXIC | TXLD | TXFD | CRCEnable | PADEnable; np->cur_tx_copy->control |= (skb->len << PKTSShift); /* pkt size */ np->cur_tx_copy->control |= (skb->len << TBSShift); /* buffer size */ @@ -1239,6 +1283,8 @@ struct fealnx_desc *next; /* for the first descriptor */ + np->cur_tx_copy->buffer = pci_map_single(np->pci_dev, skb->data, + BPT, PCI_DMA_TODEVICE); np->cur_tx_copy->control = TXIC | TXFD | CRCEnable | PADEnable; np->cur_tx_copy->control |= (skb->len << PKTSShift); /* pkt size */ np->cur_tx_copy->control |= (BPT << TBSShift); /* buffer size */ @@ -1252,7 +1298,8 @@ // 89/12/29 add, if (np->pci_dev->device == 0x891) np->cur_tx_copy->control |= ETIControl | RetryTxLC; - next->buffer = virt_to_bus(skb->data) + BPT; + next->buffer = pci_map_single(ep->pci_dev, skb->data + BPT, + skb->len - BPT, PCI_DMA_TODEVICE); next->status = TXOWN; np->cur_tx_copy->status = TXOWN; @@ -1260,6 +1307,8 @@ np->cur_tx_copy = next->next_desc_logical; np->free_tx_count -= 2; } else { + np->cur_tx_copy->buffer = pci_map_single(np->pci_dev, skb->data, + skb->len, PCI_DMA_TODEVICE); np->cur_tx_copy->control = TXIC | TXLD | TXFD | CRCEnable | PADEnable; np->cur_tx_copy->control |= (skb->len << PKTSShift); /* pkt size */ np->cur_tx_copy->control |= (skb->len << TBSShift); /* buffer size */ @@ -1308,7 +1357,8 @@ allocate_rx_buffers(dev); - writel(virt_to_bus(np->cur_rx), dev->base_addr + RXLBA); + writel(np->rx_ring_dma + (np->cur_rx - np->rx_ring), + dev->base_addr + RXLBA); writel(np->crvalue, dev->base_addr + TCRRCR); } @@ -1421,6 +1471,8 @@ } /* Free the original skb. */ + pci_unmap_single(np->pci_dev, np->cur_tx->buffer, + np->cur_tx->skbuff->len, PCI_DMA_TODEVICE); dev_kfree_skb_irq(np->cur_tx->skbuff); np->cur_tx->skbuff = NULL; --np->really_tx_count; @@ -1554,6 +1606,10 @@ printk(KERN_DEBUG " netdev_rx() normal Rx pkt length %d" " status %x.\n", pkt_len, rx_status); #endif + pci_dma_sync_single(np->pci_dev, np->cur_rx->buffer, + np->rx_buf_sz, PCI_DMA_FROMDEVICE); + pci_unmap_single(np->pci_dev, np->cur_rx->buffer, + np->rx_buf_sz, PCI_DMA_FROMDEVICE); /* Check if the packet is long enough to accept without copying to a minimally-sized skbuff. */ @@ -1564,12 +1620,12 @@ /* Call copy + cksum if available. */ #if ! defined(__alpha__) - eth_copy_and_sum(skb, bus_to_virt(np->cur_rx->buffer), - pkt_len, 0); + eth_copy_and_sum(skb, + np->cur_rx->skbuff->tail, pkt_len, 0); skb_put(skb, pkt_len); #else memcpy(skb_put(skb, pkt_len), - bus_to_virt(np->cur_rx->buffer), pkt_len); + np->cur_rx->skbuff->tail, pkt_len); #endif } else { skb_put(skb = np->cur_rx->skbuff, pkt_len); @@ -1592,7 +1648,8 @@ if (skb != NULL) { skb->dev = dev; /* Mark as being used by this device. */ - np->cur_rx->buffer = virt_to_bus(skb->tail); + np->cur_rx->buffer = pci_map_single(np->pci_dev, skb->tail, + np->rx_buf_sz, PCI_DMA_FROMDEVICE); np->cur_rx->skbuff = skb; ++np->really_rx_count; } @@ -1686,19 +1743,24 @@ static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - u16 *data = (u16 *) & rq->ifr_data; + struct mii_ioctl_data *data = (struct mii_ioctl_data *) & rq->ifr_data; switch (cmd) { - case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ - data[0] = ((struct netdev_private *) dev->priv)->phys[0] & 0x1f; + case SIOCGMIIPHY: /* Get address of MII PHY in use. */ + case SIOCDEVPRIVATE: /* for binary compat, remove in 2.5 */ + data->phy_id = ((struct netdev_private *) dev->priv)->phys[0] & 0x1f; /* Fall Through */ - case SIOCDEVPRIVATE + 1: /* Read the specified MII register. */ - data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f); + + case SIOCGMIIREG: /* Read MII PHY register. */ + case SIOCDEVPRIVATE+1: /* for binary compat, remove in 2.5 */ + data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f); return 0; - case SIOCDEVPRIVATE + 2: /* Write the specified MII register */ + + case SIOCSMIIREG: /* Write MII PHY register. */ + case SIOCDEVPRIVATE+2: /* for binary compat, remove in 2.5 */ if (!suser()) return -EPERM; - mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]); + mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in); return 0; default: return -EOPNOTSUPP; @@ -1727,16 +1789,26 @@ /* Free all the skbuffs in the Rx queue. */ for (i = 0; i < RX_RING_SIZE; i++) { + struct sk_buff *skb = np->rx_ring[i].skbuff; + np->rx_ring[i].status = 0; - if (np->rx_ring[i].skbuff) - dev_kfree_skb(np->rx_ring[i].skbuff); - np->rx_ring[i].skbuff = NULL; + if (skb) { + pci_unmap_single(np->pci_dev, np->rx_ring[i].buffer, + np->rx_buf_sz, PCI_DMA_FROMDEVICE); + dev_kfree_skb(skb); + np->rx_ring[i].skbuff = NULL; + } } for (i = 0; i < TX_RING_SIZE; i++) { - if (np->tx_ring[i].skbuff) - dev_kfree_skb(np->tx_ring[i].skbuff); - np->tx_ring[i].skbuff = NULL; + struct sk_buff *skb = np->tx_ring[i].skbuff; + + if (skb) { + pci_unmap_single(np->pci_dev, np->tx_ring[i].buffer, + skb->len, PCI_DMA_TODEVICE); + dev_kfree_skb(skb); + np->tx_ring[i].skbuff = NULL; + } } return 0; diff -u --recursive --new-file v2.4.5/linux/drivers/net/fmv18x.c linux/drivers/net/fmv18x.c --- v2.4.5/linux/drivers/net/fmv18x.c Thu Apr 19 09:34:52 2001 +++ linux/drivers/net/fmv18x.c Wed Jun 20 11:10:53 2001 @@ -628,6 +628,9 @@ MODULE_PARM(io, "i"); MODULE_PARM(irq, "i"); MODULE_PARM(net_debug, "i"); +MODULE_PARM_DESC(io, "FMV-18X I/O address"); +MODULE_PARM_DESC(irq, "FMV-18X IRQ number"); +MODULE_PARM_DESC(net_debug, "FMV-18X debug level (0-1,5-6)"); int init_module(void) { diff -u --recursive --new-file v2.4.5/linux/drivers/net/hamachi.c linux/drivers/net/hamachi.c --- v2.4.5/linux/drivers/net/hamachi.c Sat May 19 18:02:45 2001 +++ linux/drivers/net/hamachi.c Mon Jul 2 14:03:04 2001 @@ -164,6 +164,7 @@ #include #include #include +#include #include #include /* Processor type for cache alignment. */ @@ -535,7 +536,22 @@ MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(force32, "i"); - +MODULE_PARM_DESC(max_interrupt_work, "GNIC-II maximum events handled per interrupt"); +MODULE_PARM_DESC(mtu, "GNIC-II MTU (all boards)"); +MODULE_PARM_DESC(debug, "GNIC-II debug level (0-7)"); +MODULE_PARM_DESC(min_rx_pkt, "GNIC-II minimum Rx packets processed between interrupts"); +MODULE_PARM_DESC(max_rx_gap, "GNIC-II maximum Rx inter-packet gap in 8.192 microsecond units"); +MODULE_PARM_DESC(max_rx_latency, "GNIC-II time between Rx interrupts in 8.192 microsecond units"); +MODULE_PARM_DESC(min_tx_pkt, "GNIC-II minimum Tx packets processed between interrupts"); +MODULE_PARM_DESC(max_tx_gap, "GNIC-II maximum Tx inter-packet gap in 8.192 microsecond units"); +MODULE_PARM_DESC(max_tx_latency, "GNIC-II time between Tx interrupts in 8.192 microsecond units"); +MODULE_PARM_DESC(rx_copybreak, "GNIC-II copy breakpoint for copy-only-tiny-frames"); +MODULE_PARM_DESC(rx_params, "GNIC-II min_rx_pkt+max_rx_gap+max_rx_latency"); +MODULE_PARM_DESC(tx_params, "GNIC-II min_tx_pkt+max_tx_gap+max_tx_latency"); +MODULE_PARM_DESC(options, "GNIC-II Bits 0-3: media type, bits 4-6: as force32, bit 7: half duplex, bit 9 full duplex"); +MODULE_PARM_DESC(full_duplex, "GNIC-II full duplex setting(s) (1)"); +MODULE_PARM_DESC(force32, "GNIC-II: Bit 0: 32 bit PCI, bit 1: disable parity, bit 2: 64 bit PCI (all boards)"); + static int read_eeprom(long ioaddr, int location); static int mdio_read(long ioaddr, int phy_id, int location); static void mdio_write(long ioaddr, int phy_id, int location, int value); @@ -1858,24 +1874,29 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { long ioaddr = dev->base_addr; - u16 *data = (u16 *)&rq->ifr_data; + struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data; switch(cmd) { case SIOCETHTOOL: return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); - case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ - data[0] = ((struct hamachi_private *)dev->priv)->phys[0] & 0x1f; + case SIOCGMIIPHY: /* Get address of MII PHY in use. */ + case SIOCDEVPRIVATE: /* for binary compat, remove in 2.5 */ + data->phy_id = ((struct hamachi_private *)dev->priv)->phys[0] & 0x1f; /* Fall Through */ - case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ - data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f); + + case SIOCGMIIREG: /* Read MII PHY register. */ + case SIOCDEVPRIVATE+1: /* for binary compat, remove in 2.5 */ + data->val_out = mdio_read(ioaddr, data->phy_id & 0x1f, data->reg_num & 0x1f); return 0; - case SIOCDEVPRIVATE+2: /* Write the specified MII register */ + + case SIOCSMIIREG: /* Write MII PHY register. */ + case SIOCDEVPRIVATE+2: /* for binary compat, remove in 2.5 */ /* TODO: Check the sequencing of this. Might need to stop and * restart Rx and Tx engines. -KDU */ if (!capable(CAP_NET_ADMIN)) return -EPERM; - mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]); + mdio_write(ioaddr, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in); return 0; case SIOCDEVPRIVATE+3: { /* set rx,tx intr params */ u32 *d = (u32 *)&rq->ifr_data; diff -u --recursive --new-file v2.4.5/linux/drivers/net/hamradio/bpqether.c linux/drivers/net/hamradio/bpqether.c --- v2.4.5/linux/drivers/net/hamradio/bpqether.c Wed Apr 18 14:40:06 2001 +++ linux/drivers/net/hamradio/bpqether.c Wed Jun 27 17:10:55 2001 @@ -166,7 +166,7 @@ */ static int bpq_check_devices(struct net_device *dev) { - struct bpqdev *bpq, *bpq_prev; + struct bpqdev *bpq, *bpq_prev, *bpq_next; int result = 0; unsigned long flags; @@ -175,7 +175,8 @@ bpq_prev = NULL; - for (bpq = bpq_devices; bpq != NULL; bpq = bpq->next) { + for (bpq = bpq_devices; bpq != NULL; bpq = bpq_next) { + bpq_next = bpq->next; if (!dev_get(bpq->ethname)) { if (bpq_prev) bpq_prev->next = bpq->next; @@ -192,8 +193,8 @@ unregister_netdevice(&bpq->axdev); kfree(bpq); } - - bpq_prev = bpq; + else + bpq_prev = bpq; } restore_flags(flags); diff -u --recursive --new-file v2.4.5/linux/drivers/net/hamradio/scc.c linux/drivers/net/hamradio/scc.c --- v2.4.5/linux/drivers/net/hamradio/scc.c Thu Apr 19 09:34:52 2001 +++ linux/drivers/net/hamradio/scc.c Wed Jun 27 17:10:55 2001 @@ -216,7 +216,7 @@ static unsigned char SCC_DriverName[] = "scc"; -static struct irqflags { unsigned char used : 1; } Ivec[16]; +static struct irqflags { unsigned char used : 1; } Ivec[NR_IRQS]; static struct scc_channel SCC_Info[2 * SCC_MAXCHIPS]; /* information per channel */ @@ -1484,7 +1484,7 @@ printk(KERN_INFO "Init Z8530 driver: %u channels, IRQ", Nchips*2); flag=" "; - for (k = 0; k < 16; k++) + for (k = 0; k < NR_IRQS; k++) if (Ivec[k].used) { printk("%s%d", flag, k); @@ -1764,6 +1764,9 @@ if (hwcfg.irq == 2) hwcfg.irq = 9; + if (hwcfg.irq <0 || hwcfg.irq > NR_IRQS) + return -EINVAL; + if (!Ivec[hwcfg.irq].used && hwcfg.irq) { if (request_irq(hwcfg.irq, scc_isr, SA_INTERRUPT, "AX.25 SCC", NULL)) @@ -2162,7 +2165,7 @@ } } - for (k=0; k < 16 ; k++) + for (k=0; k < NR_IRQS ; k++) if (Ivec[k].used) free_irq(k, NULL); if (Vector_Latch) diff -u --recursive --new-file v2.4.5/linux/drivers/net/hamradio/soundmodem/sm.h linux/drivers/net/hamradio/soundmodem/sm.h --- v2.4.5/linux/drivers/net/hamradio/soundmodem/sm.h Mon Dec 11 13:22:15 2000 +++ linux/drivers/net/hamradio/soundmodem/sm.h Wed Jun 27 17:10:55 2001 @@ -299,6 +299,8 @@ #ifdef __i386__ +#include + /* * only do 32bit cycle counter arithmetic; we hope we won't overflow. * in fact, overflowing modems would require over 2THz CPU clock speeds :-) @@ -307,10 +309,10 @@ #define time_exec(var,cmd) \ ({ \ if (cpu_has_tsc) { \ - unsigned int cnt1, cnt2, cnt3; \ - __asm__(".byte 0x0f,0x31" : "=a" (cnt1), "=d" (cnt3)); \ + unsigned int cnt1, cnt2; \ + rdtscl(cnt1); \ cmd; \ - __asm__(".byte 0x0f,0x31" : "=a" (cnt2), "=d" (cnt3)); \ + rdtscl(cnt2); \ var = cnt2-cnt1; \ } else { \ cmd; \ diff -u --recursive --new-file v2.4.5/linux/drivers/net/hamradio/soundmodem/sm_wss.c linux/drivers/net/hamradio/soundmodem/sm_wss.c --- v2.4.5/linux/drivers/net/hamradio/soundmodem/sm_wss.c Tue Jul 18 16:55:19 2000 +++ linux/drivers/net/hamradio/soundmodem/sm_wss.c Wed Jun 27 17:10:55 2001 @@ -172,8 +172,10 @@ /* MCE and interface config reg */ write_codec(dev, 0x49, fdx ? 0x8 : 0xc); outb(0xb, WSS_CODEC_IA(dev->base_addr)); /* leave MCE */ - if (SCSTATE->crystal && !fullcalib) + if (SCSTATE->crystal && !fullcalib) { + restore_flags(flags); return 0; + } /* * wait for ACI start */ diff -u --recursive --new-file v2.4.5/linux/drivers/net/hp-plus.c linux/drivers/net/hp-plus.c --- v2.4.5/linux/drivers/net/hp-plus.c Thu Apr 19 09:34:52 2001 +++ linux/drivers/net/hp-plus.c Wed Jun 20 11:10:53 2001 @@ -408,6 +408,8 @@ MODULE_PARM(io, "1-" __MODULE_STRING(MAX_HPP_CARDS) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_HPP_CARDS) "i"); +MODULE_PARM_DESC(io, "HP PC-LAN+ I/O port address(es)"); +MODULE_PARM_DESC(irq, "HP PC-LAN+ IRQ number(s); ignored if properly detected"); /* This is set up so that only a single autoprobe takes place per call. ISA device autoprobes on a running machine are not recommended. */ diff -u --recursive --new-file v2.4.5/linux/drivers/net/hp.c linux/drivers/net/hp.c --- v2.4.5/linux/drivers/net/hp.c Thu Apr 19 09:34:52 2001 +++ linux/drivers/net/hp.c Wed Jun 20 11:10:53 2001 @@ -379,6 +379,8 @@ MODULE_PARM(io, "1-" __MODULE_STRING(MAX_HP_CARDS) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_HP_CARDS) "i"); +MODULE_PARM_DESC(io, "HP PC-LAN I/O base address(es)"); +MODULE_PARM_DESC(irq, "HP PC-LAN IRQ number(s) (assigned)"); /* This is set up so that only a single autoprobe takes place per call. ISA device autoprobes on a running machine are not recommended. */ diff -u --recursive --new-file v2.4.5/linux/drivers/net/ibmlana.c linux/drivers/net/ibmlana.c --- v2.4.5/linux/drivers/net/ibmlana.c Tue Feb 13 13:15:05 2001 +++ linux/drivers/net/ibmlana.c Wed Jun 20 11:10:53 2001 @@ -1197,6 +1197,8 @@ static int io; MODULE_PARM(irq, "i"); MODULE_PARM(io, "i"); +MODULE_PARM_DESC(irq, "IBM LAN/A IRQ number"); +MODULE_PARM_DESC(io, "IBM LAN/A I/O base address"); int init_module(void) { diff -u --recursive --new-file v2.4.5/linux/drivers/net/lance.c linux/drivers/net/lance.c --- v2.4.5/linux/drivers/net/lance.c Thu Apr 19 09:34:52 2001 +++ linux/drivers/net/lance.c Wed Jun 20 11:10:53 2001 @@ -299,6 +299,10 @@ MODULE_PARM(dma, "1-" __MODULE_STRING(MAX_CARDS) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_CARDS) "i"); MODULE_PARM(lance_debug, "i"); +MODULE_PARM_DESC(io, "LANCE/PCnet I/O base address(es),required"); +MODULE_PARM_DESC(dma, "LANCE/PCnet ISA DMA channel (ignored for some devices)"); +MODULE_PARM_DESC(irq, "LANCE/PCnet IRQ number (ignored for some devices)"); +MODULE_PARM_DESC(lance_debug, "LANCE/PCnet debug level (0-7)"); int init_module(void) { diff -u --recursive --new-file v2.4.5/linux/drivers/net/lasi_82596.c linux/drivers/net/lasi_82596.c --- v2.4.5/linux/drivers/net/lasi_82596.c Tue Feb 13 13:15:05 2001 +++ linux/drivers/net/lasi_82596.c Mon Jul 2 14:03:04 2001 @@ -181,7 +181,7 @@ MODULE_AUTHOR("Richard Hirst"); MODULE_DESCRIPTION("i82596 driver"); MODULE_PARM(i596_debug, "i"); - +MODULE_PARM_DESC(i596_debug, "lasi_82596 debug mask"); /* Copy frames shorter than rx_copybreak, otherwise pass on up in * a full sized sk_buff. Value of 100 stolen from tulip.c (!alpha). @@ -1515,13 +1515,13 @@ {0,}; static struct net_device dev_82596 = { - devicename, /* device name inserted by drivers/net/net_init.c */ - 0, 0, 0, 0, - 0, 0, /* base, irq */ - 0, 0, 0, NULL, lasi_i82596_probe}; + name: devicename, /* device name inserted by drivers/net/net_init.c */ + init: lasi_i82596_probe, +}; MODULE_PARM(debug, "i"); +MODULE_PARM_DESC(debug, "lasi_82596 debug mask"); static int debug = -1; int init_module(void) diff -u --recursive --new-file v2.4.5/linux/drivers/net/lne390.c linux/drivers/net/lne390.c --- v2.4.5/linux/drivers/net/lne390.c Tue Feb 13 13:15:05 2001 +++ linux/drivers/net/lne390.c Wed Jun 20 11:10:53 2001 @@ -381,6 +381,9 @@ MODULE_PARM(io, "1-" __MODULE_STRING(MAX_LNE_CARDS) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_LNE_CARDS) "i"); MODULE_PARM(mem, "1-" __MODULE_STRING(MAX_LNE_CARDS) "i"); +MODULE_PARM_DESC(io, "LNE390 I/O base address(es)"); +MODULE_PARM_DESC(irq, "LNE390 IRQ number(s)"); +MODULE_PARM_DESC(mem, "LNE390 memory base address(es)"); int init_module(void) { diff -u --recursive --new-file v2.4.5/linux/drivers/net/mac89x0.c linux/drivers/net/mac89x0.c --- v2.4.5/linux/drivers/net/mac89x0.c Tue Mar 6 19:28:35 2001 +++ linux/drivers/net/mac89x0.c Wed Jun 20 11:10:53 2001 @@ -626,6 +626,7 @@ static int debug; MODULE_PARM(debug, "i"); +MODULE_PARM_DESC(debug, "CS89[02]0 debug level (0-5)"); EXPORT_NO_SYMBOLS; diff -u --recursive --new-file v2.4.5/linux/drivers/net/mace.c linux/drivers/net/mace.c --- v2.4.5/linux/drivers/net/mace.c Sun May 20 12:11:38 2001 +++ linux/drivers/net/mace.c Wed Jun 20 11:10:53 2001 @@ -25,6 +25,7 @@ static int port_aaui = -1; MODULE_PARM(port_aaui, "i"); +MODULE_PARM_DESC(port_aaui, "MACE uses AAUI port (0-1)"); #define N_RX_RING 8 #define N_TX_RING 6 diff -u --recursive --new-file v2.4.5/linux/drivers/net/macsonic.c linux/drivers/net/macsonic.c --- v2.4.5/linux/drivers/net/macsonic.c Sun Mar 25 18:24:31 2001 +++ linux/drivers/net/macsonic.c Wed Jun 20 11:10:53 2001 @@ -575,6 +575,7 @@ static struct net_device dev_macsonic; MODULE_PARM(sonic_debug, "i"); +MODULE_PARM_DESC(sonic_debug, "macsonic debug level (1-4)"); EXPORT_NO_SYMBOLS; diff -u --recursive --new-file v2.4.5/linux/drivers/net/natsemi.c linux/drivers/net/natsemi.c --- v2.4.5/linux/drivers/net/natsemi.c Sat May 19 18:02:45 2001 +++ linux/drivers/net/natsemi.c Thu Jun 21 14:28:39 2001 @@ -51,10 +51,24 @@ * One-liner removal of a duplicate declaration of netdev_error(). (uzi) + Version 1.0.7: (Manfred Spraul) + * pci dma + * SMP locking update + * full reset added into tx_timeout + * correct multicast hash generation (both big and little endian) + [copied from a natsemi driver version + from Myrio Corporation, Greg Smith] + * suspend/resume + + TODO: + * big endian support with CFG:BEM instead of cpu_to_le32 + * support for an external PHY + * flow control + * Wake-On-LAN */ #define DRV_NAME "natsemi" -#define DRV_VERSION "1.07+LK1.0.6" +#define DRV_VERSION "1.07+LK1.0.7" #define DRV_RELDATE "May 18, 2001" @@ -111,6 +125,8 @@ /* Time in jiffies before concluding the transmitter is hung. */ #define TX_TIMEOUT (2*HZ) +#define NATSEMI_HW_TIMEOUT 200 + #define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/ #if !defined(__OPTIMIZE__) @@ -119,6 +135,7 @@ #error You must compile this driver with "-O". #endif +#include #include #include #include @@ -134,6 +151,8 @@ #include #include #include +#include +#include #include /* Processor type for cache alignment. */ #include #include @@ -145,10 +164,6 @@ KERN_INFO " http://www.scyld.com/network/natsemi.html\n" KERN_INFO " (unofficial 2.4.x kernel port, version " DRV_VERSION ", " DRV_RELDATE " Jeff Garzik, Tjeerd Mulder)\n"; -/* Condensed operations for readability. */ -#define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr)) -#define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr)) - MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("National Semiconductor DP8381x series PCI Ethernet driver"); MODULE_PARM(max_interrupt_work, "i"); @@ -157,6 +172,12 @@ MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); +MODULE_PARM_DESC(max_interrupt_work, "DP8381x maximum events handled per interrupt"); +MODULE_PARM_DESC(mtu, "DP8381x MTU (all boards)"); +MODULE_PARM_DESC(debug, "DP8381x debug level (0-5)"); +MODULE_PARM_DESC(rx_copybreak, "DP8381x copy breakpoint for copy-only-tiny-frames"); +MODULE_PARM_DESC(options, "DP8381x: Bits 0-3: media type, bit 17: full duplex"); +MODULE_PARM_DESC(full_duplex, "DP8381x full duplex setting(s) (1)"); /* Theory of Operation @@ -330,15 +351,17 @@ DescPktOK=0x08000000, RxTooLong=0x00400000, }; -#define PRIV_ALIGN 15 /* Required alignment mask */ struct netdev_private { /* Descriptor rings first for alignment. */ - struct netdev_desc rx_ring[RX_RING_SIZE]; - struct netdev_desc tx_ring[TX_RING_SIZE]; + dma_addr_t ring_dma; + struct netdev_desc* rx_ring; + struct netdev_desc* tx_ring; /* The addresses of receive-in-place skbuffs. */ struct sk_buff* rx_skbuff[RX_RING_SIZE]; + dma_addr_t rx_dma[RX_RING_SIZE]; /* The saved address of a sent-in-place packet/buffer, for later free(). */ struct sk_buff* tx_skbuff[TX_RING_SIZE]; + dma_addr_t tx_dma[TX_RING_SIZE]; struct net_device_stats stats; struct timer_list timer; /* Media monitoring timer. */ /* Frequently used values: keep some adjacent for cache effect. */ @@ -348,10 +371,7 @@ unsigned int cur_tx, dirty_tx; unsigned int rx_buf_sz; /* Based on MTU+slack. */ /* These values are keep track of the transceiver/media in use. */ - unsigned int full_duplex:1; /* Full-duplex operation requested. */ - unsigned int duplex_lock:1; - unsigned int medialock:1; /* Do not sense media. */ - unsigned int default_port:4; /* Last dev->if_port value. */ + unsigned int full_duplex; /* Rx filter. */ u32 cur_rx_mode; u32 rx_filter[16]; @@ -360,24 +380,31 @@ /* original contents of ClkRun register */ u32 SavedClkRun; /* MII transceiver section. */ - u16 advertising; /* NWay media advertisement */ - + u16 advertising; /* NWay media advertisement */ unsigned int iosize; spinlock_t lock; }; static int eeprom_read(long ioaddr, int location); static int mdio_read(struct net_device *dev, int phy_id, int location); +static void natsemi_reset(struct net_device *dev); static int netdev_open(struct net_device *dev); -static void check_duplex(struct net_device *dev); +static void check_link(struct net_device *dev); static void netdev_timer(unsigned long data); static void tx_timeout(struct net_device *dev); +static int alloc_ring(struct net_device *dev); static void init_ring(struct net_device *dev); +static void drain_ring(struct net_device *dev); +static void free_ring(struct net_device *dev); +static void init_registers(struct net_device *dev); static int start_tx(struct sk_buff *skb, struct net_device *dev); static void intr_handler(int irq, void *dev_instance, struct pt_regs *regs); static void netdev_error(struct net_device *dev, int intr_status); -static int netdev_rx(struct net_device *dev); +static void netdev_rx(struct net_device *dev); +static void netdev_tx_done(struct net_device *dev); +static void __set_rx_mode(struct net_device *dev); static void set_rx_mode(struct net_device *dev); +static void __get_stats(struct net_device *dev); static struct net_device_stats *get_stats(struct net_device *dev); static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static int netdev_close(struct net_device *dev); @@ -417,7 +444,6 @@ } find_cnt++; - option = find_cnt < MAX_UNITS ? options[find_cnt] : 0; ioaddr = pci_resource_start(pdev, pcibar); iosize = pci_resource_len(pdev, pcibar); irq = pdev->irq; @@ -455,9 +481,6 @@ prev_eedata = eedata; } - /* Reset the chip to erase previous misconfiguration. */ - writel(ChipReset, ioaddr + ChipCmd); - dev->base_addr = ioaddr; dev->irq = irq; @@ -468,6 +491,9 @@ np->iosize = iosize; spin_lock_init(&np->lock); + /* Reset the chip to erase previous misconfiguration. */ + natsemi_reset(dev); + option = find_cnt < MAX_UNITS ? options[find_cnt] : 0; if (dev->mem_start) option = dev->mem_start; @@ -475,16 +501,13 @@ if (option > 0) { if (option & 0x200) np->full_duplex = 1; - np->default_port = option & 15; - if (np->default_port) - np->medialock = 1; + if (option & 15) + printk(KERN_INFO "%s: ignoring user supplied media type %d", + dev->name, option & 15); } if (find_cnt < MAX_UNITS && full_duplex[find_cnt] > 0) np->full_duplex = 1; - if (np->full_duplex) - np->duplex_lock = 1; - /* The chip-specific entries in the device structure. */ dev->open = &netdev_open; dev->hard_start_xmit = &start_tx; @@ -598,6 +621,25 @@ return 0xffff; } +static void natsemi_reset(struct net_device *dev) +{ + int i; + + writel(ChipReset, dev->base_addr + ChipCmd); + for (i=0;ibase_addr + ChipCmd) & ChipReset)) + break; + udelay(5); + } + if (i==NATSEMI_HW_TIMEOUT && debug) { + printk(KERN_INFO "%s: reset did not complete in %d usec.\n", + dev->name, i*5); + } else if (debug > 2) { + printk(KERN_DEBUG "%s: reset completed in %d usec.\n", + dev->name, i*5); + } +} + static int netdev_open(struct net_device *dev) { @@ -606,25 +648,7 @@ int i; /* Reset the chip, just in case. */ - writel(ChipReset, ioaddr + ChipCmd); - - /* On page 78 of the spec, they recommend some settings for "optimum - performance" to be done in sequence. These settings optimize some - of the 100Mbit autodetection circuitry. Also, we only want to do - this for rev C of the chip. - */ - if (readl(ioaddr + SiliconRev) == 0x302) { - writew(0x0001, ioaddr + PGSEL); - writew(0x189C, ioaddr + PMDCSR); - writew(0x0000, ioaddr + TSTDAT); - writew(0x5040, ioaddr + DSPCFG); - writew(0x008C, ioaddr + SDCFG); - } - - /* Enable PHY Specific event based interrupts. Link state change - and Auto-Negotiation Completion are among the affected. - */ - writew(0x0002, ioaddr + MIntrCtrl); + natsemi_reset(dev); i = request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev); if (i) return i; @@ -632,56 +656,16 @@ if (debug > 1) printk(KERN_DEBUG "%s: netdev_open() irq %d.\n", dev->name, dev->irq); - - init_ring(dev); - - writel(virt_to_bus(np->rx_ring), ioaddr + RxRingPtr); - writel(virt_to_bus(np->tx_ring), ioaddr + TxRingPtr); - - for (i = 0; i < ETH_ALEN; i += 2) { - writel(i, ioaddr + RxFilterAddr); - writew(dev->dev_addr[i] + (dev->dev_addr[i+1] << 8), - ioaddr + RxFilterData); - } - - /* Initialize other registers. */ - /* Configure the PCI bus bursts and FIFO thresholds. */ - /* Configure for standard, in-spec Ethernet. */ - - if (readl(ioaddr + ChipConfig) & 0x20000000) { /* Full duplex */ - np->tx_config = 0xD0801002; - np->rx_config = 0x10000020; - } else { - np->tx_config = 0x10801002; - np->rx_config = 0x0020; + i = alloc_ring(dev); + if (i < 0) { + free_irq(dev->irq, dev); + return i; } - writel(np->tx_config, ioaddr + TxConfig); - writel(np->rx_config, ioaddr + RxConfig); - - if (dev->if_port == 0) - dev->if_port = np->default_port; - - /* Disable PME: - * The PME bit is initialized from the EEPROM contents. - * PCI cards probably have PME disabled, but motherboard - * implementations may have PME set to enable WakeOnLan. - * With PME set the chip will scan incoming packets but - * nothing will be written to memory. */ - np->SavedClkRun = readl(ioaddr + ClkRun); - writel(np->SavedClkRun & ~0x100, ioaddr + ClkRun); + init_ring(dev); + init_registers(dev); netif_start_queue(dev); - check_duplex(dev); - set_rx_mode(dev); - - /* Enable interrupts by setting the interrupt mask. */ - writel(IntrNormalSummary | IntrAbnormalSummary | 0x1f, ioaddr + IntrMask); - writel(1, ioaddr + IntrEnable); - - writel(RxOn | TxOn, ioaddr + ChipCmd); - writel(4, ioaddr + StatsCtrl); /* Clear Stats */ - if (debug > 2) printk(KERN_DEBUG "%s: Done netdev_open(), status: %x.\n", dev->name, (int)readl(ioaddr + ChipCmd)); @@ -696,17 +680,33 @@ return 0; } -static void check_duplex(struct net_device *dev) +static void check_link(struct net_device *dev) { struct netdev_private *np = dev->priv; long ioaddr = dev->base_addr; int duplex; + int chipcfg = readl(ioaddr + ChipConfig); - if (np->duplex_lock) + if(!(chipcfg & 0x80000000)) { + if (netif_carrier_ok(dev)) { + if (debug) + printk(KERN_INFO "%s: no link. Disabling watchdog.\n", + dev->name); + netif_carrier_off(dev); + } return; - duplex = readl(ioaddr + ChipConfig) & 0x20000000 ? 1 : 0; - if (np->full_duplex != duplex) { - np->full_duplex = duplex; + } + if (!netif_carrier_ok(dev)) { + if (debug) + printk(KERN_INFO "%s: link is back. Enabling watchdog.\n", + dev->name); + netif_carrier_on(dev); + } + + duplex = np->full_duplex || (chipcfg & 0x20000000 ? 1 : 0); + + /* if duplex is set then bit 28 must be set, too */ + if (duplex ^ !!(np->rx_config & 0x10000000)) { if (debug) printk(KERN_INFO "%s: Setting %s-duplex based on negotiated link" " capability.\n", dev->name, @@ -723,17 +723,104 @@ } } +static void init_registers(struct net_device *dev) +{ + struct netdev_private *np = dev->priv; + long ioaddr = dev->base_addr; + int i; + + if (debug > 4) + printk(KERN_DEBUG "%s: found silicon revision %xh.\n", + dev->name, readl(ioaddr + SiliconRev)); + /* On page 78 of the spec, they recommend some settings for "optimum + performance" to be done in sequence. These settings optimize some + of the 100Mbit autodetection circuitry. Also, we only want to do + this for rev C of the chip. + + There seems to be a typo on page 78: the fixup should be performed + for "DP83815CVNG (SRR = 203h)", but the description of the + SiliconRev regsiters says "DP83815CVNG: 00000302h" + */ + if (readl(ioaddr + SiliconRev) == 0x302) { + writew(0x0001, ioaddr + PGSEL); + writew(0x189C, ioaddr + PMDCSR); + writew(0x0000, ioaddr + TSTDAT); + writew(0x5040, ioaddr + DSPCFG); + writew(0x008C, ioaddr + SDCFG); + } + + /* Enable PHY Specific event based interrupts. Link state change + and Auto-Negotiation Completion are among the affected. + */ + writew(0x0002, ioaddr + MIntrCtrl); + + writel(np->ring_dma, ioaddr + RxRingPtr); + writel(np->ring_dma + RX_RING_SIZE * sizeof(struct netdev_desc), ioaddr + TxRingPtr); + + for (i = 0; i < ETH_ALEN; i += 2) { + writel(i, ioaddr + RxFilterAddr); + writew(dev->dev_addr[i] + (dev->dev_addr[i+1] << 8), + ioaddr + RxFilterData); + } + + /* Initialize other registers. + * Configure the PCI bus bursts and FIFO thresholds. + * Configure for standard, in-spec Ethernet. + * Start with half-duplex. check_link will update + * to the correct settings. + */ + + /* DRTH: 2: start tx if 64 bytes are in the fifo + * FLTH: 0x10: refill with next packet if 512 bytes are free + * MXDMA: 0: up to 512 byte bursts. + * MXDMA must be <= FLTH + * ECRETRY=1 + * ATP=1 + */ + np->tx_config = 0x10801002; + /* DRTH 0x10: start copying to memory if 128 bytes are in the fifo + * MXDMA 0: up to 512 byte bursts + */ + np->rx_config = 0x0020; + writel(np->tx_config, ioaddr + TxConfig); + writel(np->rx_config, ioaddr + RxConfig); + + /* Disable PME: + * The PME bit is initialized from the EEPROM contents. + * PCI cards probably have PME disabled, but motherboard + * implementations may have PME set to enable WakeOnLan. + * With PME set the chip will scan incoming packets but + * nothing will be written to memory. */ + np->SavedClkRun = readl(ioaddr + ClkRun); + writel(np->SavedClkRun & ~0x100, ioaddr + ClkRun); + + check_link(dev); + __set_rx_mode(dev); + + /* Enable interrupts by setting the interrupt mask. */ + writel(IntrNormalSummary | IntrAbnormalSummary | 0x1f, ioaddr + IntrMask); + writel(1, ioaddr + IntrEnable); + + writel(RxOn | TxOn, ioaddr + ChipCmd); + writel(4, ioaddr + StatsCtrl); /* Clear Stats */ +} + static void netdev_timer(unsigned long data) { struct net_device *dev = (struct net_device *)data; struct netdev_private *np = dev->priv; - long ioaddr = dev->base_addr; int next_tick = 60*HZ; - if (debug > 3) - printk(KERN_DEBUG "%s: Media selection timer tick, status %8.8x.\n", - dev->name, (int)readl(ioaddr + IntrStatus)); - check_duplex(dev); + if (debug > 3) { + /* DO NOT read the IntrStatus register, + * a read clears any pending interrupts. + */ + printk(KERN_DEBUG "%s: Media selection timer tick.\n", + dev->name); + } + spin_lock_irq(&np->lock); + check_link(dev); + spin_unlock_irq(&np->lock); np->timer.expires = jiffies + next_tick; add_timer(&np->timer); } @@ -746,30 +833,39 @@ printk(KERN_WARNING "%s: Transmit timed out, status %8.8x," " resetting...\n", dev->name, (int)readl(ioaddr + TxRingPtr)); -#ifndef __alpha__ { int i; - printk(KERN_DEBUG " Rx ring %8.8x: ", (int)np->rx_ring); + printk(KERN_DEBUG " Rx ring %p: ", np->rx_ring); for (i = 0; i < RX_RING_SIZE; i++) printk(" %8.8x", (unsigned int)np->rx_ring[i].cmd_status); - printk("\n"KERN_DEBUG" Tx ring %8.8x: ", (int)np->tx_ring); + printk("\n"KERN_DEBUG" Tx ring %p: ", np->tx_ring); for (i = 0; i < TX_RING_SIZE; i++) printk(" %4.4x", np->tx_ring[i].cmd_status); printk("\n"); } -#endif - - /* Perhaps we should reinitialize the hardware here. */ - dev->if_port = 0; - /* Stop and restart the chip's Tx processes . */ - - /* Trigger an immediate transmit demand. */ + spin_lock_irq(&np->lock); + natsemi_reset(dev); + drain_ring(dev); + init_ring(dev); + init_registers(dev); + spin_unlock_irq(&np->lock); dev->trans_start = jiffies; np->stats.tx_errors++; netif_wake_queue(dev); } +static int alloc_ring(struct net_device *dev) +{ + struct netdev_private *np = dev->priv; + np->rx_ring = pci_alloc_consistent(np->pci_dev, + sizeof(struct netdev_desc) * (RX_RING_SIZE+TX_RING_SIZE), + &np->ring_dma); + if (!np->rx_ring) + return -ENOMEM; + np->tx_ring = &np->rx_ring[RX_RING_SIZE]; + return 0; +} /* Initialize the Rx and Tx rings, along with various 'dev' bits. */ static void init_ring(struct net_device *dev) @@ -785,12 +881,12 @@ /* Initialize all Rx descriptors. */ for (i = 0; i < RX_RING_SIZE; i++) { - np->rx_ring[i].next_desc = virt_to_le32desc(&np->rx_ring[i+1]); - np->rx_ring[i].cmd_status = DescOwn; - np->rx_skbuff[i] = 0; + np->rx_ring[i].next_desc = cpu_to_le32(np->ring_dma+sizeof(struct netdev_desc)*(i+1)); + np->rx_ring[i].cmd_status = cpu_to_le32(DescOwn); + np->rx_skbuff[i] = NULL; } /* Mark the last entry as wrapping the ring. */ - np->rx_ring[i-1].next_desc = virt_to_le32desc(&np->rx_ring[0]); + np->rx_ring[i-1].next_desc = cpu_to_le32(np->ring_dma); /* Fill in the Rx buffers. Handle allocation failure gracefully. */ for (i = 0; i < RX_RING_SIZE; i++) { @@ -799,19 +895,59 @@ if (skb == NULL) break; skb->dev = dev; /* Mark as being used by this device. */ - np->rx_ring[i].addr = virt_to_le32desc(skb->tail); - np->rx_ring[i].cmd_status = - cpu_to_le32(DescIntr | np->rx_buf_sz); + np->rx_dma[i] = pci_map_single(np->pci_dev, + skb->data, skb->len, PCI_DMA_FROMDEVICE); + np->rx_ring[i].addr = cpu_to_le32(np->rx_dma[i]); + np->rx_ring[i].cmd_status = cpu_to_le32(DescIntr | np->rx_buf_sz); } np->dirty_rx = (unsigned int)(i - RX_RING_SIZE); for (i = 0; i < TX_RING_SIZE; i++) { - np->tx_skbuff[i] = 0; - np->tx_ring[i].next_desc = virt_to_le32desc(&np->tx_ring[i+1]); + np->tx_skbuff[i] = NULL; + np->tx_ring[i].next_desc = cpu_to_le32(np->ring_dma + +sizeof(struct netdev_desc)*(i+1+RX_RING_SIZE)); np->tx_ring[i].cmd_status = 0; } - np->tx_ring[i-1].next_desc = virt_to_le32desc(&np->tx_ring[0]); - return; + np->tx_ring[i-1].next_desc = cpu_to_le32(np->ring_dma + +sizeof(struct netdev_desc)*(RX_RING_SIZE)); +} + +static void drain_ring(struct net_device *dev) +{ + struct netdev_private *np = dev->priv; + int i; + + /* Free all the skbuffs in the Rx queue. */ + for (i = 0; i < RX_RING_SIZE; i++) { + np->rx_ring[i].cmd_status = 0; + np->rx_ring[i].addr = 0xBADF00D0; /* An invalid address. */ + if (np->rx_skbuff[i]) { + pci_unmap_single(np->pci_dev, + np->rx_dma[i], + np->rx_skbuff[i]->len, + PCI_DMA_FROMDEVICE); + dev_kfree_skb(np->rx_skbuff[i]); + } + np->rx_skbuff[i] = NULL; + } + for (i = 0; i < TX_RING_SIZE; i++) { + if (np->tx_skbuff[i]) { + pci_unmap_single(np->pci_dev, + np->rx_dma[i], + np->rx_skbuff[i]->len, + PCI_DMA_TODEVICE); + dev_kfree_skb(np->tx_skbuff[i]); + } + np->tx_skbuff[i] = NULL; + } +} + +static void free_ring(struct net_device *dev) +{ + struct netdev_private *np = dev->priv; + pci_free_consistent(np->pci_dev, + sizeof(struct netdev_desc) * (RX_RING_SIZE+TX_RING_SIZE), + np->rx_ring, np->ring_dma); } static int start_tx(struct sk_buff *skb, struct net_device *dev) @@ -826,17 +962,26 @@ entry = np->cur_tx % TX_RING_SIZE; np->tx_skbuff[entry] = skb; + np->tx_dma[entry] = pci_map_single(np->pci_dev, + skb->data,skb->len, PCI_DMA_TODEVICE); - np->tx_ring[entry].addr = virt_to_le32desc(skb->data); - np->tx_ring[entry].cmd_status = cpu_to_le32(DescOwn|DescIntr | skb->len); - np->cur_tx++; + np->tx_ring[entry].addr = cpu_to_le32(np->tx_dma[entry]); + + spin_lock_irq(&np->lock); +#if 0 + np->tx_ring[entry].cmd_status = cpu_to_le32(DescOwn | DescIntr | skb->len); +#else + np->tx_ring[entry].cmd_status = cpu_to_le32(DescOwn | skb->len); +#endif /* StrongARM: Explicitly cache flush np->tx_ring and skb->data,skb->len. */ wmb(); - - spin_lock_irq(&np->lock); - if (np->cur_tx - np->dirty_tx >= TX_QUEUE_LEN - 1) - netif_stop_queue(dev); + np->cur_tx++; + if (np->cur_tx - np->dirty_tx >= TX_QUEUE_LEN - 1) { + netdev_tx_done(dev); + if (np->cur_tx - np->dirty_tx >= TX_QUEUE_LEN - 1) + netif_stop_queue(dev); + } spin_unlock_irq(&np->lock); /* Wake the potentially-idle transmit channel. */ @@ -851,6 +996,48 @@ return 0; } +static void netdev_tx_done(struct net_device *dev) +{ + struct netdev_private *np = dev->priv; + + for (; np->cur_tx - np->dirty_tx > 0; np->dirty_tx++) { + int entry = np->dirty_tx % TX_RING_SIZE; + if (np->tx_ring[entry].cmd_status & cpu_to_le32(DescOwn)) { + if (debug > 4) + printk(KERN_DEBUG "%s: tx frame #%d is busy.\n", + dev->name, np->dirty_tx); + break; + } + if (debug > 4) + printk(KERN_DEBUG "%s: tx frame #%d finished with status %8.8xh.\n", + dev->name, np->dirty_tx, + le32_to_cpu(np->tx_ring[entry].cmd_status)); + if (np->tx_ring[entry].cmd_status & cpu_to_le32(0x08000000)) { + np->stats.tx_packets++; + np->stats.tx_bytes += np->tx_skbuff[entry]->len; + } else { /* Various Tx errors */ + int tx_status = le32_to_cpu(np->tx_ring[entry].cmd_status); + if (tx_status & 0x04010000) np->stats.tx_aborted_errors++; + if (tx_status & 0x02000000) np->stats.tx_fifo_errors++; + if (tx_status & 0x01000000) np->stats.tx_carrier_errors++; + if (tx_status & 0x00200000) np->stats.tx_window_errors++; + np->stats.tx_errors++; + } + pci_unmap_single(np->pci_dev,np->tx_dma[entry], + np->tx_skbuff[entry]->len, + PCI_DMA_TODEVICE); + /* Free the original skb. */ + dev_kfree_skb_irq(np->tx_skbuff[entry]); + np->tx_skbuff[entry] = NULL; + } + if (netif_queue_stopped(dev) + && np->cur_tx - np->dirty_tx < TX_QUEUE_LEN - 4) { + /* The ring is no longer full, wake queue. */ + netif_wake_queue(dev); + } + spin_unlock(&np->lock); + +} /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs) @@ -864,11 +1051,9 @@ np = dev->priv; do { + /* Reading automatically acknowledges all int sources. */ u32 intr_status = readl(ioaddr + IntrStatus); - /* Acknowledge all of the current interrupt sources ASAP. */ - writel(intr_status & 0x000ffff, ioaddr + IntrStatus); - if (debug > 4) printk(KERN_DEBUG "%s: Interrupt, status %4.4x.\n", dev->name, intr_status); @@ -879,35 +1064,12 @@ if (intr_status & (IntrRxDone | IntrRxIntr)) netdev_rx(dev); - spin_lock(&np->lock); - - for (; np->cur_tx - np->dirty_tx > 0; np->dirty_tx++) { - int entry = np->dirty_tx % TX_RING_SIZE; - if (np->tx_ring[entry].cmd_status & cpu_to_le32(DescOwn)) - break; - if (np->tx_ring[entry].cmd_status & cpu_to_le32(0x08000000)) { - np->stats.tx_packets++; - np->stats.tx_bytes += np->tx_skbuff[entry]->len; - } else { /* Various Tx errors */ - int tx_status = le32_to_cpu(np->tx_ring[entry].cmd_status); - if (tx_status & 0x04010000) np->stats.tx_aborted_errors++; - if (tx_status & 0x02000000) np->stats.tx_fifo_errors++; - if (tx_status & 0x01000000) np->stats.tx_carrier_errors++; - if (tx_status & 0x00200000) np->stats.tx_window_errors++; - np->stats.tx_errors++; - } - /* Free the original skb. */ - dev_kfree_skb_irq(np->tx_skbuff[entry]); - np->tx_skbuff[entry] = 0; - } - if (netif_queue_stopped(dev) - && np->cur_tx - np->dirty_tx < TX_QUEUE_LEN - 4) { - /* The ring is no longer full, wake queue. */ - netif_wake_queue(dev); + if (intr_status & (IntrTxDone | IntrTxIntr | IntrTxIdle | IntrTxErr) ) { + spin_lock(&np->lock); + netdev_tx_done(dev); + spin_unlock(&np->lock); } - spin_unlock(&np->lock); - /* Abnormal error summary/uncommon events handlers. */ if (intr_status & IntrAbnormalSummary) netdev_error(dev, intr_status); @@ -921,13 +1083,13 @@ } while (1); if (debug > 3) - printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n", - dev->name, (int)readl(ioaddr + IntrStatus)); + printk(KERN_DEBUG "%s: exiting interrupt.\n", + dev->name); } /* This routine is logically part of the interrupt handler, but separated for clarity and better register allocation. */ -static int netdev_rx(struct net_device *dev) +static void netdev_rx(struct net_device *dev) { struct netdev_private *np = dev->priv; int entry = np->cur_rx % RX_RING_SIZE; @@ -967,6 +1129,9 @@ && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) { skb->dev = dev; skb_reserve(skb, 2); /* 16 byte align the IP header */ + pci_dma_sync_single(np->pci_dev, np->rx_dma[entry], + np->rx_skbuff[entry]->len, + PCI_DMA_FROMDEVICE); #if HAS_IP_COPYSUM eth_copy_and_sum(skb, np->rx_skbuff[entry]->tail, pkt_len, 0); skb_put(skb, pkt_len); @@ -975,16 +1140,11 @@ pkt_len); #endif } else { - char *temp = skb_put(skb = np->rx_skbuff[entry], pkt_len); + pci_unmap_single(np->pci_dev, np->rx_dma[entry], + np->rx_skbuff[entry]->len, + PCI_DMA_FROMDEVICE); + skb_put(skb = np->rx_skbuff[entry], pkt_len); np->rx_skbuff[entry] = NULL; -#ifndef final_version /* Remove after testing. */ - if (le32desc_to_virt(np->rx_ring[entry].addr) != temp) - printk(KERN_ERR "%s: Internal fault: The skbuff addresses " - "do not match in netdev_rx: %p vs. %p / %p.\n", - dev->name, - le32desc_to_virt(np->rx_ring[entry].addr), - skb->head, temp); -#endif } skb->protocol = eth_type_trans(skb, dev); /* W/ hardware checksum: skb->ip_summed = CHECKSUM_UNNECESSARY; */ @@ -1008,7 +1168,9 @@ if (skb == NULL) break; /* Better luck next round. */ skb->dev = dev; /* Mark as being used by this device. */ - np->rx_ring[entry].addr = virt_to_le32desc(skb->tail); + np->rx_dma[entry] = pci_map_single(np->pci_dev, + skb->data, skb->len, PCI_DMA_FROMDEVICE); + np->rx_ring[entry].addr = cpu_to_le32(np->rx_dma[entry]); } np->rx_ring[entry].cmd_status = cpu_to_le32(DescIntr | np->rx_buf_sz); @@ -1016,7 +1178,6 @@ /* Restart Rx engine if stopped. */ writel(RxOn, dev->base_addr + ChipCmd); - return 0; } static void netdev_error(struct net_device *dev, int intr_status) @@ -1024,20 +1185,24 @@ struct netdev_private *np = dev->priv; long ioaddr = dev->base_addr; + spin_lock(&np->lock); if (intr_status & LinkChange) { printk(KERN_NOTICE "%s: Link changed: Autonegotiation advertising" " %4.4x partner %4.4x.\n", dev->name, (int)readl(ioaddr + 0x90), (int)readl(ioaddr + 0x94)); /* read MII int status to clear the flag */ readw(ioaddr + MIntrStatus); - check_duplex(dev); + check_link(dev); } if (intr_status & StatsMax) { - get_stats(dev); + __get_stats(dev); } if (intr_status & IntrTxUnderrun) { if ((np->tx_config & 0x3f) < 62) np->tx_config += 2; + if (debug > 2) + printk(KERN_NOTICE "%s: increasing Tx theshold, new tx cfg %8.8xh.\n", + dev->name, np->tx_config); writel(np->tx_config, ioaddr + TxConfig); } if (intr_status & WOLPkt) { @@ -1054,23 +1219,30 @@ np->stats.tx_fifo_errors++; np->stats.rx_fifo_errors++; } + spin_unlock(&np->lock); } -static struct net_device_stats *get_stats(struct net_device *dev) +static void __get_stats(struct net_device *dev) { long ioaddr = dev->base_addr; struct netdev_private *np = dev->priv; - /* We should lock this segment of code for SMP eventually, although - the vulnerability window is very small and statistics are - non-critical. */ /* The chip only need report frame silently dropped. */ np->stats.rx_crc_errors += readl(ioaddr + RxCRCErrs); np->stats.rx_missed_errors += readl(ioaddr + RxMissed); +} + +static struct net_device_stats *get_stats(struct net_device *dev) +{ + struct netdev_private *np = dev->priv; + + /* The chip only need report frame silently dropped. */ + spin_lock_irq(&np->lock); + __get_stats(dev); + spin_unlock_irq(&np->lock); return &np->stats; } - /* The little-endian AUTODIN II ethernet CRC calculations. A big-endian version is also available. This is slow but compact code. Do not use this routine for bulk data, @@ -1079,6 +1251,7 @@ Chips may use the upper or lower CRC bits, and may reverse and/or invert them. Select the endian-ness that results in minimal calculations. */ +#if 0 static unsigned const ethernet_polynomial_le = 0xedb88320U; static inline unsigned ether_crc_le(int length, unsigned char *data) { @@ -1096,8 +1269,41 @@ } return crc; } +#else +#define DP_POLYNOMIAL 0x04C11DB7 +/* dp83815_crc - computer CRC for hash table entries */ +static unsigned ether_crc_le(int length, unsigned char *data) +{ + u32 crc; + u8 cur_byte; + u8 msb; + u8 byte, bit; + + crc = ~0; + for (byte=0; byte> 31; + crc <<= 1; + if (msb ^ (cur_byte & 1)) { + crc ^= DP_POLYNOMIAL; + crc |= 1; + } + cur_byte >>= 1; + } + } + crc >>= 23; -static void set_rx_mode(struct net_device *dev) + return (crc); +} +#endif + +void set_bit_le(int offset, unsigned char * data) +{ + data[offset >> 3] |= (1 << (offset & 0x07)); +} +#define HASH_TABLE 0x200 +static void __set_rx_mode(struct net_device *dev) { long ioaddr = dev->base_addr; struct netdev_private *np = dev->priv; @@ -1118,17 +1324,25 @@ memset(mc_filter, 0, sizeof(mc_filter)); for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; i++, mclist = mclist->next) { - set_bit(ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x1ff, + set_bit_le(ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x1ff, mc_filter); } rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; for (i = 0; i < 64; i += 2) { - writew(0x200 + i, ioaddr + RxFilterAddr); + writew(HASH_TABLE + i, ioaddr + RxFilterAddr); writew((mc_filter[i+1]<<8) + mc_filter[i], ioaddr + RxFilterData); } } writel(rx_mode, ioaddr + RxFilterAddr); np->cur_rx_mode = rx_mode; + spin_unlock_irq(&np->lock); +} +static void set_rx_mode(struct net_device *dev) +{ + struct netdev_private *np = dev->priv; + spin_lock_irq(&np->lock); + __set_rx_mode(dev); + spin_unlock_irq(&np->lock); } static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr) @@ -1177,12 +1391,6 @@ u16 value = data[2]; writew(value, dev->base_addr + 0x80 + (miireg << 2)); switch (miireg) { - case 0: - /* Check for autonegotiation on or reset. */ - np->duplex_lock = (value & 0x9000) ? 0 : 1; - if (np->duplex_lock) - np->full_duplex = (value & 0x0100) ? 1 : 0; - break; case 4: np->advertising = value; break; } } @@ -1196,15 +1404,12 @@ { long ioaddr = dev->base_addr; struct netdev_private *np = dev->priv; - int i; netif_stop_queue(dev); if (debug > 1) { - printk(KERN_DEBUG "%s: Shutting down ethercard, status was %4.4x " - "Int %2.2x.\n", - dev->name, (int)readl(ioaddr + ChipCmd), - (int)readl(ioaddr + IntrStatus)); + printk(KERN_DEBUG "%s: Shutting down ethercard, status was %4.4x.", + dev->name, (int)readl(ioaddr + ChipCmd)); printk(KERN_DEBUG "%s: Queue pointers were Tx %d / %d, Rx %d / %d.\n", dev->name, np->cur_tx, np->dirty_tx, np->cur_rx, np->dirty_rx); } @@ -1221,13 +1426,14 @@ #ifdef __i386__ if (debug > 2) { + int i; printk("\n"KERN_DEBUG" Tx ring at %8.8x:\n", - (int)virt_to_bus(np->tx_ring)); + (int)np->tx_ring); for (i = 0; i < TX_RING_SIZE; i++) printk(" #%d desc. %8.8x %8.8x.\n", i, np->tx_ring[i].cmd_status, np->tx_ring[i].addr); printk("\n"KERN_DEBUG " Rx ring %8.8x:\n", - (int)virt_to_bus(np->rx_ring)); + (int)np->rx_ring); for (i = 0; i < RX_RING_SIZE; i++) { printk(KERN_DEBUG " #%d desc. %8.8x %8.8x\n", i, np->rx_ring[i].cmd_status, np->rx_ring[i].addr); @@ -1236,21 +1442,9 @@ #endif /* __i386__ debugging only */ free_irq(dev->irq, dev); + drain_ring(dev); + free_ring(dev); - /* Free all the skbuffs in the Rx queue. */ - for (i = 0; i < RX_RING_SIZE; i++) { - np->rx_ring[i].cmd_status = 0; - np->rx_ring[i].addr = 0xBADF00D0; /* An invalid address. */ - if (np->rx_skbuff[i]) { - dev_kfree_skb(np->rx_skbuff[i]); - } - np->rx_skbuff[i] = 0; - } - for (i = 0; i < TX_RING_SIZE; i++) { - if (np->tx_skbuff[i]) - dev_kfree_skb(np->tx_skbuff[i]); - np->tx_skbuff[i] = 0; - } /* Restore PME enable bit */ writel(np->SavedClkRun, ioaddr + ClkRun); #if 0 @@ -1272,11 +1466,86 @@ pci_set_drvdata(pdev, NULL); } +#ifdef CONFIG_PM + +static int natsemi_suspend (struct pci_dev *pdev, u32 state) +{ + struct net_device *dev = pci_get_drvdata (pdev); + struct netdev_private *np = dev->priv; + long ioaddr = dev->base_addr; + + netif_device_detach(dev); + /* no more calls to tx_timeout, hard_start_xmit, set_rx_mode */ + rtnl_lock(); + rtnl_unlock(); + /* noone within ->open */ + if (netif_running (dev)) { + int i; + del_timer_sync(&np->timer); + /* no more link beat timer calls */ + spin_lock_irq(&np->lock); + writel(RxOff | TxOff, ioaddr + ChipCmd); + for(i=0;i< NATSEMI_HW_TIMEOUT;i++) { + if ((readl(ioaddr + ChipCmd) & (TxOn|RxOn)) == 0) + break; + udelay(5); + } + if (i==NATSEMI_HW_TIMEOUT && debug) { + printk(KERN_INFO "%s: Tx/Rx process did not stop in %d usec.\n", + dev->name, i*5); + } else if (debug > 2) { + printk(KERN_DEBUG "%s: Tx/Rx process stopped in %d usec.\n", + dev->name, i*5); + } + /* Tx and Rx processes stopped */ + + writel(0, ioaddr + IntrEnable); + /* all irq events disabled. */ + spin_unlock_irq(&np->lock); + + synchronize_irq(); + + /* Update the error counts. */ + __get_stats(dev); + + /* pci_power_off(pdev, -1); */ + drain_ring(dev); + } + return 0; +} + + +static int natsemi_resume (struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata (pdev); + struct netdev_private *np = dev->priv; + + if (netif_running (dev)) { + pci_enable_device(pdev); + /* pci_power_on(pdev); */ + + natsemi_reset(dev); + init_ring(dev); + init_registers(dev); + + np->timer.expires = jiffies + 1*HZ; + add_timer(&np->timer); + } + netif_device_attach(dev); + return 0; +} + +#endif /* CONFIG_PM */ + static struct pci_driver natsemi_driver = { name: DRV_NAME, id_table: natsemi_pci_tbl, probe: natsemi_probe1, remove: natsemi_remove1, +#ifdef CONFIG_PM + suspend: natsemi_suspend, + resume: natsemi_resume, +#endif }; static int __init natsemi_init_mod (void) diff -u --recursive --new-file v2.4.5/linux/drivers/net/ncr885e.c linux/drivers/net/ncr885e.c --- v2.4.5/linux/drivers/net/ncr885e.c Sat Dec 30 18:16:13 2000 +++ linux/drivers/net/ncr885e.c Mon Jul 2 14:03:04 2001 @@ -60,7 +60,7 @@ #define EOP (1<<7) /* rx: end of packet written to buffer */ int ncr885e_debug = NCR885E_DEBUG; -static int print_version = 0; +static int print_version; struct ncr885e_private { @@ -94,7 +94,7 @@ spinlock_t lock; }; -static struct net_device *root_dev = NULL; +static struct net_device *root_dev; static int ncr885e_open( struct net_device *dev ); static int ncr885e_close( struct net_device *dev ); diff -u --recursive --new-file v2.4.5/linux/drivers/net/ne.c linux/drivers/net/ne.c --- v2.4.5/linux/drivers/net/ne.c Thu Apr 12 12:15:25 2001 +++ linux/drivers/net/ne.c Wed Jun 20 11:10:53 2001 @@ -735,6 +735,9 @@ MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); MODULE_PARM(bad, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); +MODULE_PARM_DESC(io, "NEx000 I/O base address(es),required"); +MODULE_PARM_DESC(irq, "NEx000 IRQ number(s)"); +MODULE_PARM_DESC(bad, "NEx000 accept bad clone(s)"); /* This is set up so that no ISA autoprobe takes place. We can't guarantee that the ne2k probe is the last 8390 based probe to take place (as it diff -u --recursive --new-file v2.4.5/linux/drivers/net/ne2.c linux/drivers/net/ne2.c --- v2.4.5/linux/drivers/net/ne2.c Fri Feb 9 11:40:02 2001 +++ linux/drivers/net/ne2.c Wed Jun 20 11:10:53 2001 @@ -749,6 +749,9 @@ MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); MODULE_PARM(bad, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); +MODULE_PARM_DESC(io, "(ignored)"); +MODULE_PARM_DESC(irq, "(ignored)"); +MODULE_PARM_DESC(bad, "(ignored)"); #endif /* Module code fixed by David Weinehall */ diff -u --recursive --new-file v2.4.5/linux/drivers/net/ne2k-pci.c linux/drivers/net/ne2k-pci.c --- v2.4.5/linux/drivers/net/ne2k-pci.c Fri Apr 20 11:54:23 2001 +++ linux/drivers/net/ne2k-pci.c Wed Jun 20 11:13:18 2001 @@ -25,6 +25,11 @@ Limited full-duplex support. */ +#define DRV_NAME "ne2k-pci" +#define DRV_VERSION "1.02" +#define DRV_RELDATE "10/19/2000" + + /* The user-configurable values. These may be modified when a driver module is loaded.*/ @@ -45,10 +50,12 @@ #include #include #include +#include #include #include #include +#include #include #include @@ -56,7 +63,7 @@ /* These identify the driver base version and may not be removed. */ static char version[] __devinitdata = -KERN_INFO "ne2k-pci.c:v1.02 10/19/2000 D. Becker/P. Gortmaker\n" +KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " D. Becker/P. Gortmaker\n" KERN_INFO " http://www.scyld.com/network/ne2k-pci.html\n"; #if defined(__powerpc__) @@ -66,11 +73,16 @@ #define outsl outsl_ns #endif +#define PFX DRV_NAME ": " + MODULE_AUTHOR("Donald Becker / Paul Gortmaker"); MODULE_DESCRIPTION("PCI NE2000 clone driver"); MODULE_PARM(debug, "i"); MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); +MODULE_PARM_DESC(debug, "PCI NE2000 debug level (1-2)"); +MODULE_PARM_DESC(options, "PCI NE2000: Bit 5: full duplex"); +MODULE_PARM_DESC(full_duplex, "PCI NE2000 full duplex setting(s) (1)"); /* Some defines that people can play with if so inclined. */ @@ -160,6 +172,7 @@ struct sk_buff *skb, int ring_offset); static void ne2k_pci_block_output(struct net_device *dev, const int count, const unsigned char *buf, const int start_page); +static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); @@ -215,12 +228,12 @@ irq = pdev->irq; if (!ioaddr || ((pci_resource_flags (pdev, 0) & IORESOURCE_IO) == 0)) { - printk (KERN_ERR "ne2k-pci: no I/O resource at PCI BAR #0\n"); + printk (KERN_ERR PFX "no I/O resource at PCI BAR #0\n"); return -ENODEV; } - if (request_region (ioaddr, NE_IO_EXTENT, "ne2k-pci") == NULL) { - printk (KERN_ERR "ne2k-pci: I/O resource 0x%x @ 0x%lx busy\n", + if (request_region (ioaddr, NE_IO_EXTENT, DRV_NAME) == NULL) { + printk (KERN_ERR PFX "I/O resource 0x%x @ 0x%lx busy\n", NE_IO_EXTENT, ioaddr); return -EBUSY; } @@ -246,7 +259,7 @@ dev = alloc_etherdev(0); if (!dev) { - printk (KERN_ERR "ne2k-pci: cannot allocate ethernet device\n"); + printk (KERN_ERR PFX "cannot allocate ethernet device\n"); goto err_out_free_res; } SET_MODULE_OWNER(dev); @@ -263,7 +276,7 @@ while ((inb(ioaddr + EN0_ISR) & ENISR_RESET) == 0) /* Limit wait: '2' avoids jiffy roll-over. */ if (jiffies - reset_start_time > 2) { - printk("ne2k-pci: Card failure (no reset ack).\n"); + printk(KERN_ERR PFX "Card failure (no reset ack).\n"); goto err_out_free_netdev; } @@ -342,8 +355,10 @@ ei_status.block_input = &ne2k_pci_block_input; ei_status.block_output = &ne2k_pci_block_output; ei_status.get_8390_hdr = &ne2k_pci_get_8390_hdr; + ei_status.priv = (unsigned long) pdev; dev->open = &ne2k_pci_open; dev->stop = &ne2k_pci_close; + dev->do_ioctl = &netdev_ioctl; NS8390_init(dev, 0); i = register_netdev(dev); @@ -573,6 +588,40 @@ return; } +static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr) +{ + struct ei_device *ei = dev->priv; + struct pci_dev *pci_dev = (struct pci_dev *) ei->priv; + u32 ethcmd; + + if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) + return -EFAULT; + + switch (ethcmd) { + case ETHTOOL_GDRVINFO: { + struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; + strcpy(info.driver, DRV_NAME); + strcpy(info.version, DRV_VERSION); + strcpy(info.bus_info, pci_dev->slot_name); + if (copy_to_user(useraddr, &info, sizeof(info))) + return -EFAULT; + return 0; + } + + } + + return -EOPNOTSUPP; +} + +static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + switch(cmd) { + case SIOCETHTOOL: + return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); + default: + return -EOPNOTSUPP; + } +} static void __devexit ne2k_pci_remove_one (struct pci_dev *pdev) { @@ -589,7 +638,7 @@ static struct pci_driver ne2k_driver = { - name: "ne2k-pci", + name: DRV_NAME, probe: ne2k_pci_init_one, remove: ne2k_pci_remove_one, id_table: ne2k_pci_tbl, diff -u --recursive --new-file v2.4.5/linux/drivers/net/ne3210.c linux/drivers/net/ne3210.c --- v2.4.5/linux/drivers/net/ne3210.c Tue Feb 13 13:15:05 2001 +++ linux/drivers/net/ne3210.c Wed Jun 20 11:10:53 2001 @@ -370,6 +370,9 @@ MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NE3210_CARDS) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_NE3210_CARDS) "i"); MODULE_PARM(mem, "1-" __MODULE_STRING(MAX_NE3210_CARDS) "i"); +MODULE_PARM_DESC(io, "NE3210 I/O base address(es)"); +MODULE_PARM_DESC(irq, "NE3210 IRQ number(s)"); +MODULE_PARM_DESC(mem, "NE3210 memory base address(es)"); int init_module(void) { diff -u --recursive --new-file v2.4.5/linux/drivers/net/ni5010.c linux/drivers/net/ni5010.c --- v2.4.5/linux/drivers/net/ni5010.c Thu Apr 12 12:15:25 2001 +++ linux/drivers/net/ni5010.c Wed Jun 20 11:10:53 2001 @@ -739,6 +739,8 @@ MODULE_PARM(io, "i"); MODULE_PARM(irq, "i"); +MODULE_PARM_DESC(io, "ni5010 I/O base address"); +MODULE_PARM_DESC(irq, "ni5010 IRQ number"); int init_module(void) { diff -u --recursive --new-file v2.4.5/linux/drivers/net/ni52.c linux/drivers/net/ni52.c --- v2.4.5/linux/drivers/net/ni52.c Thu Apr 12 12:15:25 2001 +++ linux/drivers/net/ni52.c Wed Jun 20 11:10:53 2001 @@ -1296,6 +1296,10 @@ MODULE_PARM(irq, "i"); MODULE_PARM(memstart, "l"); MODULE_PARM(memend, "l"); +MODULE_PARM_DESC(io, "NI5210 I/O base address,required"); +MODULE_PARM_DESC(irq, "NI5210 IRQ number,required"); +MODULE_PARM_DESC(memstart, "NI5210 memory base address,required"); +MODULE_PARM_DESC(memend, "NI5210 memory end address,required"); int init_module(void) { diff -u --recursive --new-file v2.4.5/linux/drivers/net/ni65.c linux/drivers/net/ni65.c --- v2.4.5/linux/drivers/net/ni65.c Wed Apr 18 14:40:04 2001 +++ linux/drivers/net/ni65.c Wed Jun 20 11:10:53 2001 @@ -1184,6 +1184,9 @@ MODULE_PARM(irq, "i"); MODULE_PARM(io, "i"); MODULE_PARM(dma, "i"); +MODULE_PARM_DESC(irq, "ni6510 IRQ number (ignored for some cards)"); +MODULE_PARM_DESC(io, "ni6510 I/O base address"); +MODULE_PARM_DESC(dma, "ni6510 ISA DMA channel (ignored for some cards)"); int init_module(void) { diff -u --recursive --new-file v2.4.5/linux/drivers/net/pci-skeleton.c linux/drivers/net/pci-skeleton.c --- v2.4.5/linux/drivers/net/pci-skeleton.c Fri Apr 20 11:54:23 2001 +++ linux/drivers/net/pci-skeleton.c Mon Jul 2 14:03:04 2001 @@ -85,6 +85,7 @@ */ +#include #include #include #include @@ -93,6 +94,7 @@ #include #include #include +#include #include #define NETDRV_VERSION "1.0.0" @@ -480,11 +482,15 @@ }; MODULE_AUTHOR ("Jeff Garzik "); -MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver"); +MODULE_DESCRIPTION ("Skeleton for a PCI Fast Ethernet driver"); MODULE_PARM (multicast_filter_limit, "i"); MODULE_PARM (max_interrupt_work, "i"); MODULE_PARM (debug, "i"); MODULE_PARM (media, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM_DESC (multicast_filter_limit, "pci-skeleton maximum number of filtered multicast addresses"); +MODULE_PARM_DESC (max_interrupt_work, "pci-skeleton maximum events handled per interrupt"); +MODULE_PARM_DESC (media, "pci-skeleton: Bits 0-3: media type, bit 17: full duplex"); +MODULE_PARM_DESC (debug, "(unused)"); static int read_eeprom (void *ioaddr, int location, int addr_len); static int netdrv_open (struct net_device *dev); @@ -1777,31 +1783,34 @@ static int netdrv_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) { struct netdrv_private *tp = dev->priv; - u16 *data = (u16 *) & rq->ifr_data; + struct mii_ioctl_data *data = (struct mii_ioctl_data *) & rq->ifr_data; unsigned long flags; int rc = 0; DPRINTK ("ENTER\n"); switch (cmd) { - case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ - data[0] = tp->phys[0] & 0x3f; + case SIOCGMIIPHY: /* Get address of MII PHY in use. */ + case SIOCDEVPRIVATE: /* for binary compat, remove in 2.5 */ + data->phy_id = tp->phys[0] & 0x3f; /* Fall Through */ - case SIOCDEVPRIVATE + 1: /* Read the specified MII register. */ + case SIOCGMIIREG: /* Read MII PHY register. */ + case SIOCDEVPRIVATE+1: /* for binary compat, remove in 2.5 */ spin_lock_irqsave (&tp->lock, flags); - data[3] = mdio_read (dev, data[0], data[1] & 0x1f); + data->val_out = mdio_read (dev, data->phy_id & 0x1f, data->reg_num & 0x1f); spin_unlock_irqrestore (&tp->lock, flags); break; - case SIOCDEVPRIVATE + 2: /* Write the specified MII register */ + case SIOCSMIIREG: /* Write MII PHY register. */ + case SIOCDEVPRIVATE+2: /* for binary compat, remove in 2.5 */ if (!capable (CAP_NET_ADMIN)) { rc = -EPERM; break; } spin_lock_irqsave (&tp->lock, flags); - mdio_write (dev, data[0], data[1] & 0x1f, data[2]); + mdio_write (dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in); spin_unlock_irqrestore (&tp->lock, flags); break; @@ -1918,7 +1927,9 @@ } -static void netdrv_suspend (struct pci_dev *pdev) +#ifdef CONFIG_PM + +static int netdrv_suspend (struct pci_dev *pdev, u32 state) { struct net_device *dev = pci_get_drvdata (pdev); struct netdrv_private *tp = dev->priv; @@ -1942,10 +1953,12 @@ spin_unlock_irqrestore (&tp->lock, flags); pci_power_off (pdev, -1); + + return 0; } -static void netdrv_resume (struct pci_dev *pdev) +static int netdrv_resume (struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata (pdev); @@ -1954,16 +1967,22 @@ pci_power_on (pdev); netif_device_attach (dev); netdrv_hw_start (dev); + + return 0; } +#endif /* CONFIG_PM */ + static struct pci_driver netdrv_pci_driver = { name: MODNAME, id_table: netdrv_pci_tbl, probe: netdrv_init_one, remove: netdrv_remove_one, +#ifdef CONFIG_PM suspend: netdrv_suspend, resume: netdrv_resume, +#endif /* CONFIG_PM */ }; diff -u --recursive --new-file v2.4.5/linux/drivers/net/pcmcia/Config.in linux/drivers/net/pcmcia/Config.in --- v2.4.5/linux/drivers/net/pcmcia/Config.in Mon May 7 19:42:14 2001 +++ linux/drivers/net/pcmcia/Config.in Wed Jun 20 11:13:18 2001 @@ -32,13 +32,4 @@ fi fi -if [ "$CONFIG_PCMCIA_3C589" = "y" -o "$CONFIG_PCMCIA_3C574" = "y" -o \ - "$CONFIG_PCMCIA_FMVJ18X" = "y" -o "$CONFIG_PCMCIA_PCNET" = "y" -o \ - "$CONFIG_PCMCIA_NMCLAN" = "y" -o "$CONFIG_PCMCIA_SMC91C92" = "y" -o \ - "$CONFIG_PCMCIA_XIRC2PS" = "y" -o "$CONFIG_PCMCIA_RAYCS" = "y" -o \ - "$CONFIG_PCMCIA_NETWAVE" = "y" -o "$CONFIG_PCMCIA_WAVELAN" = "y" -o \ - "$CONFIG_PCMCIA_XIRTULIP" = "y" ]; then - define_bool CONFIG_PCMCIA_NETCARD y -fi - endmenu diff -u --recursive --new-file v2.4.5/linux/drivers/net/pcmcia/Makefile linux/drivers/net/pcmcia/Makefile --- v2.4.5/linux/drivers/net/pcmcia/Makefile Mon May 7 19:42:14 2001 +++ linux/drivers/net/pcmcia/Makefile Wed Jun 20 11:13:18 2001 @@ -36,10 +36,3 @@ obj-$(CONFIG_PCMCIA_IBMTR) += ibmtr_cs.o include $(TOPDIR)/Rules.make - -tmp-ibmtr.o: ../tokenring/ibmtr.c - $(CC) $(CFLAGS) -D__NO_VERSION__ -DPCMCIA -c -o $@ ../tokenring/ibmtr.c - -ibmtr_cs.o: tmp-ibmtr.o ibmtr_cs.c - $(CC) $(CFLAGS) -DPCMCIA -c -o tmp-$@ ibmtr_cs.c - $(LD) -r -o $@ tmp-$@ tmp-ibmtr.o diff -u --recursive --new-file v2.4.5/linux/drivers/net/pcmcia/ibmtr_cs.c linux/drivers/net/pcmcia/ibmtr_cs.c --- v2.4.5/linux/drivers/net/pcmcia/ibmtr_cs.c Wed Apr 18 14:40:05 2001 +++ linux/drivers/net/pcmcia/ibmtr_cs.c Wed Jun 20 11:13:18 2001 @@ -73,6 +73,9 @@ #include #include +#define PCMCIA +#include "../tokenring/ibmtr.c" + #ifdef PCMCIA_DEBUG static int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i"); @@ -130,7 +133,7 @@ unsigned char pcmcia_reality_check(unsigned char gss); extern int trdev_init(struct net_device *dev); -extern void tok_interrupt(int irq, struct pt_regs *regs); +extern void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs); extern int tok_init_card(struct net_device *dev); extern unsigned char get_sram_size(struct tok_info *ti); diff -u --recursive --new-file v2.4.5/linux/drivers/net/pcmcia/xircom_tulip_cb.c linux/drivers/net/pcmcia/xircom_tulip_cb.c --- v2.4.5/linux/drivers/net/pcmcia/xircom_tulip_cb.c Sun Mar 25 18:24:31 2001 +++ linux/drivers/net/pcmcia/xircom_tulip_cb.c Wed Jun 20 11:16:01 2001 @@ -245,10 +245,6 @@ /* This table use during operation for capabilities and media timer. */ static void tulip_timer(unsigned long data); -static void t21142_timer(unsigned long data); -static void mxic_timer(unsigned long data); -static void pnic_timer(unsigned long data); -static void comet_timer(unsigned long data); enum tbl_flag { HAS_MII=1, HAS_MEDIA_TABLE=2, CSR12_IN_SROM=4, ALWAYS_CHECK_MII=8, @@ -262,37 +258,15 @@ int flags; void (*media_timer)(unsigned long data); } tulip_tbl[] = { - { "Digital DC21040 Tulip", 128, 0x0001ebef, 0, tulip_timer }, - { "Digital DC21041 Tulip", 128, 0x0001ebef, HAS_MEDIA_TABLE, tulip_timer }, - { "Digital DS21140 Tulip", 128, 0x0001ebef, - HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, tulip_timer }, - { "Digital DS21143 Tulip", 128, 0x0801fbff, - HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_ACPI | HAS_NWAY143, t21142_timer }, - { "Lite-On 82c168 PNIC", 256, 0x0001ebef, - HAS_MII, pnic_timer }, - { "Macronix 98713 PMAC", 128, 0x0001ebef, - HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer }, - { "Macronix 98715 PMAC", 256, 0x0001ebef, - HAS_MEDIA_TABLE, mxic_timer }, - { "Macronix 98725 PMAC", 256, 0x0001ebef, - HAS_MEDIA_TABLE, mxic_timer }, - { "ASIX AX88140", 128, 0x0001fbff, - HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | MC_HASH_ONLY, tulip_timer }, - { "Lite-On PNIC-II", 256, 0x0001ebef, - HAS_MII | HAS_NWAY143, pnic_timer }, - { "ADMtek Comet", 256, 0x0001abef, - MC_HASH_ONLY, comet_timer }, - { "Compex 9881 PMAC", 128, 0x0001ebef, - HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer }, { "Xircom Cardbus Adapter (DEC 21143 compatible mode)", 128, 0x0801fbff, HAS_MII | HAS_ACPI, tulip_timer }, {0}, }; /* This matches the table above. Note 21142 == 21143. */ enum chips { - DC21040=0, DC21041=1, DC21140=2, DC21142=3, DC21143=3, - LC82C168, MX98713, MX98715, MX98725, AX88140, PNIC2, COMET, COMPEX9881, X3201_3, + DC21040, DC21041, DC21140, DC21142=4, DC21143=4, + LC82C168, MX98713, MX98715, MX98725, AX88140, PNIC2, COMET, COMPEX9881, }; /* A full-duplex map for media types. */ @@ -307,9 +281,7 @@ static u16 t21041_csr14[] = { 0x7F3F, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, }; static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, }; -static u16 t21142_csr13[] = { 0x0001, 0x0009, 0x0009, 0x0000, 0x0001, }; static u16 t21142_csr14[] = { 0xFFFF, 0x0705, 0x0705, 0x0000, 0x7F3D, }; -static u16 t21142_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, }; /* Offsets to the Command and Status Registers, "CSRs". All accesses must be longword instructions and quadword aligned. */ @@ -1272,7 +1244,7 @@ *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2]; /* Put the setup frame on the Tx list. */ - tp->tx_ring[0].length = 0x08000000 | 192; + tp->tx_ring[0].length = 0x68000000 | 192; tp->tx_ring[0].buffer1 = virt_to_bus(tp->setup_frame); tp->tx_ring[0].status = DescOwned; @@ -1291,7 +1263,7 @@ } /* Put the setup frame on the Tx list. */ - tp->tx_ring[tp->cur_tx].length = 0x08000000 | 192; + tp->tx_ring[tp->cur_tx].length = 0x68000000 | 192; /* Lie about the address of our setup frame to make the */ /* chip happy */ tp->tx_ring[tp->cur_tx].buffer1 = virt_to_bus(tp->setup_frame); @@ -1862,83 +1834,6 @@ add_timer(&tp->timer); } -/* Handle the 21143 uniquely: do autoselect with NWay, not the EEPROM list - of available transceivers. */ -static void t21142_timer(unsigned long data) -{ - struct net_device *dev = (struct net_device *)data; - struct tulip_private *tp = (struct tulip_private *)dev->priv; - long ioaddr = dev->base_addr; - int csr12 = inl(ioaddr + CSR12); - int next_tick = 60*HZ; - int new_csr6 = 0; - - if ((tulip_debug > 2) && !(media_cap[dev->if_port] & MediaIsMII)) - printk(KERN_INFO"%s: 21143 negotiation status %8.8x, %s.\n", - dev->name, csr12, medianame[dev->if_port]); - if (media_cap[dev->if_port] & MediaIsMII) { - check_duplex(dev); - next_tick = 60*HZ; - } else if (tp->nwayset) { - /* Don't screw up a negotiated session! */ - if (tulip_debug > 1) - printk(KERN_INFO"%s: Using NWay-set %s media, csr12 %8.8x.\n", - dev->name, medianame[dev->if_port], csr12); - } else if (tp->medialock) { - ; - } else if (dev->if_port == 3) { - if (csr12 & 2) { /* No 100mbps link beat, revert to 10mbps. */ - if (tulip_debug > 1) - printk(KERN_INFO"%s: No 21143 100baseTx link beat, %8.8x, " - "trying NWay.\n", dev->name, csr12); - t21142_start_nway(dev); - next_tick = 3*HZ; - } - } else if (((csr12 & 0x7000) != 0x5000) - && tp->chip_id != X3201_3) { - /* Negotiation failed. Search media types. */ - if (tulip_debug > 1) - printk(KERN_INFO"%s: 21143 negotiation failed, status %8.8x.\n", - dev->name, csr12); - if (!(csr12 & 4)) { /* 10mbps link beat good. */ - new_csr6 = 0x82420000; - dev->if_port = 0; - outl(0, ioaddr + CSR13); - outl(0x0003FFFF, ioaddr + CSR14); - outw(t21142_csr15[dev->if_port], ioaddr + CSR15); - outl(t21142_csr13[dev->if_port], ioaddr + CSR13); - } else { - /* Select 100mbps port to check for link beat. */ - new_csr6 = 0x83860000; - dev->if_port = 3; - outl(0, ioaddr + CSR13); - outl(0x0003FF7F, ioaddr + CSR14); - outw(8, ioaddr + CSR15); - outl(1, ioaddr + CSR13); - } - if (tulip_debug > 1) - printk(KERN_INFO"%s: Testing new 21143 media %s.\n", - dev->name, medianame[dev->if_port]); - if (new_csr6 != (tp->csr6 & ~0x00D5)) { - tp->csr6 &= 0x00D5; - tp->csr6 |= new_csr6; - outl(0x0301, ioaddr + CSR12); - outl_CSR6(tp->csr6 | 0x0002, ioaddr, tp->chip_id); - outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id); - } - next_tick = 3*HZ; - } - if (tp->cur_tx - tp->dirty_tx > 0 && - jiffies - dev->trans_start > TX_TIMEOUT) { - printk(KERN_WARNING "%s: Tx hung, %d vs. %d.\n", - dev->name, tp->cur_tx, tp->dirty_tx); - tulip_tx_timeout(dev); - } - - tp->timer.expires = RUN_AT(next_tick); - add_timer(&tp->timer); -} - static void t21142_start_nway(struct net_device *dev) { struct tulip_private *tp = (struct tulip_private *)dev->priv; @@ -2069,123 +1964,6 @@ } } -static void mxic_timer(unsigned long data) -{ - struct net_device *dev = (struct net_device *)data; - struct tulip_private *tp = (struct tulip_private *)dev->priv; - long ioaddr = dev->base_addr; - int next_tick = 60*HZ; - - if (tulip_debug > 3) { - printk(KERN_INFO"%s: MXIC negotiation status %8.8x.\n", dev->name, - inl(ioaddr + CSR12)); - } - if (next_tick) { - tp->timer.expires = RUN_AT(next_tick); - add_timer(&tp->timer); - } -} - -static void pnic_timer(unsigned long data) -{ - struct net_device *dev = (struct net_device *)data; - struct tulip_private *tp = (struct tulip_private *)dev->priv; - long ioaddr = dev->base_addr; - int csr12 = inl(ioaddr + CSR12); - int next_tick = 60*HZ; - int new_csr6 = tp->csr6 & ~0x40C40200; - - if (media_cap[dev->if_port] & MediaIsMII) { - int negotiated = mdio_read(dev, tp->phys[0], 5) & tp->advertising[0]; - - if (tulip_debug > 1) - printk(KERN_DEBUG "%s: PNIC negotiated capability %8.8x, " - "CSR5 %8.8x.\n", - dev->name, negotiated, inl(ioaddr + CSR5)); - - if (negotiated & 0x0380) /* 10 vs 100mbps */ - new_csr6 |= 0x810E0000; - else - new_csr6 |= 0x814E0000; - if (((negotiated & 0x0300) == 0x0100) /* Duplex */ - || (negotiated & 0x00C0) == 0x0040 - || tp->full_duplex_lock) { - tp->full_duplex = 1; - new_csr6 |= 0x0200; - } - if (tulip_debug > 1) - printk(KERN_DEBUG "%s: PNIC MII PHY status %4.4x, Link " - "partner report %4.4x, csr6 %8.8x/%8.8x.\n", - dev->name, mdio_read(dev, tp->phys[0], 1), negotiated, - tp->csr6, inl(ioaddr + CSR6)); - } else { - int phy_reg = inl(ioaddr + 0xB8); - int csr5 = inl(ioaddr + CSR5); - - if (tulip_debug > 1) - printk(KERN_DEBUG "%s: PNIC PHY status %8.8x, CSR5 %8.8x.\n", - dev->name, phy_reg, csr5); - - if (phy_reg & 0x04000000) { /* Remote link fault */ - /*outl(0x0201F078, ioaddr + 0xB8);*/ - next_tick = 3*HZ; - } - if (inl(ioaddr + CSR5) & TPLnkFail) { /* 100baseTx link beat */ - if (tulip_debug > 1) - printk(KERN_DEBUG "%s: %s link beat failed, CSR12 %4.4x, " - "CSR5 %8.8x, PHY %3.3x.\n", - dev->name, medianame[dev->if_port], csr12, - inl(ioaddr + CSR5), inl(ioaddr + 0xB8)); - if (tp->medialock) { - } else if (dev->if_port == 0) { - dev->if_port = 3; - outl(0x33, ioaddr + CSR12); - new_csr6 = 0x01860000; - outl(0x1F868, ioaddr + 0xB8); - } else { - dev->if_port = 0; - outl(0x32, ioaddr + CSR12); - new_csr6 = 0x00420000; - outl(0x1F078, ioaddr + 0xB8); - } - new_csr6 |= (tp->csr6 & 0xfdff); - next_tick = 3*HZ; - } else - new_csr6 = tp->csr6; - if (tp->full_duplex_lock || (phy_reg & 0x30000000) != 0) { - tp->full_duplex = 1; - new_csr6 |= 0x00000200; - } - } - if (tp->csr6 != new_csr6) { - tp->csr6 = new_csr6; - outl_CSR6(tp->csr6 | 0x0002, ioaddr, tp->chip_id); /* Restart Tx */ - outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id); - dev->trans_start = jiffies; - if (tulip_debug > 1) - printk(KERN_INFO "%s: Changing PNIC configuration to %s-duplex, " - "CSR6 %8.8x.\n", - dev->name, tp->full_duplex ? "full" : "half", new_csr6); - } - tp->timer.expires = RUN_AT(next_tick); - add_timer(&tp->timer); -} - -static void comet_timer(unsigned long data) -{ - struct net_device *dev = (struct net_device *)data; - struct tulip_private *tp = (struct tulip_private *)dev->priv; - long ioaddr = dev->base_addr; - int next_tick = 60*HZ; - - if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Comet link status %4.4x partner capability " - "%4.4x.\n", - dev->name, inl(ioaddr + 0xB8), inl(ioaddr + 0xC8)); - tp->timer.expires = RUN_AT(next_tick); - add_timer(&tp->timer); -} - static void tulip_tx_timeout(struct net_device *dev) { struct tulip_private *tp = (struct tulip_private *)dev->priv; @@ -2741,12 +2519,6 @@ case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ if (tp->mii_cnt) data[0] = phy; - else if (tp->chip_id == DC21142) /* 21142 pseudo-MII */ - data[0] = 32; - else if (tp->chip_id == PNIC2) - data[0] = 32; - else if (tp->chip_id == COMET) - data[0] = 1; else return -ENODEV; return 0; @@ -2874,27 +2646,18 @@ for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; i++, mclist = mclist->next) set_bit(ether_crc(ETH_ALEN, mclist->dmi_addr)>>26, mc_filter); - if (tp->chip_id == AX88140) { - outl(2, ioaddr + CSR13); - outl(mc_filter[0], ioaddr + CSR14); - outl(3, ioaddr + CSR13); - outl(mc_filter[1], ioaddr + CSR14); - } else if (tp->chip_id == COMET) { /* Has a simple hash filter. */ - outl(mc_filter[0], ioaddr + 0xAC); - outl(mc_filter[1], ioaddr + 0xB0); - } } } else { u16 *eaddrs, *setup_frm = tp->setup_frame; struct dev_mc_list *mclist; - u32 tx_flags = 0x08000000 | 192; + u32 tx_flags = 0x68000000 | 192; int i; /* Note that only the low-address shortword of setup_frame is valid! The values are doubled for big-endian architectures. */ - if ((dev->mc_count > 14) || ((dev->mc_count > 6) && (tp->chip_id == X3201_3))) { /* Must use a multicast hash table. */ + if (dev->mc_count > 14) { /* Must use a multicast hash table. */ u16 hash_table[32]; - tx_flags = 0x08400000 | 192; /* Use hash filter. */ + tx_flags = 0x68400000 | 192; /* Use hash filter. */ memset(hash_table, 0, sizeof(hash_table)); set_bit(255, hash_table); /* Broadcast entry */ /* This should work on big-endian machines as well. */ @@ -2907,7 +2670,7 @@ *setup_frm++ = hash_table[i]; } setup_frm = &tp->setup_frame[13*6]; - } else if(tp->chip_id != X3201_3) { + } else { /* We have <= 14 addresses so we can use the wonderful 16 address perfect filtering of the Tulip. */ for (i = 0, mclist = dev->mc_list; i < dev->mc_count; @@ -2920,30 +2683,6 @@ /* Fill the unused entries with the broadcast address. */ memset(setup_frm, 0xff, (15-i)*12); setup_frm = &tp->setup_frame[15*6]; - } else { - /* fill the first two table entries with our address */ - eaddrs = (u16 *)dev->dev_addr; - for(i=0; i<2; i++) { - *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0]; - *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1]; - *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2]; - } - /* Double fill each entry to accomodate chips that */ - /* don't like to parse these correctly */ - for (i=0, mclist=dev->mc_list; imc_count; - i++, mclist=mclist->next) { - eaddrs = (u16 *)mclist->dmi_addr; - *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0]; - *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1]; - *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2]; - *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0]; - *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1]; - *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2]; - } - i=((i+1)*2); - /* Fill the unused entries with the broadcast address. */ - memset(setup_frm, 0xff, (15-i)*12); - setup_frm = &tp->setup_frame[15*6]; } /* Fill the final entry with our physical address. */ @@ -2995,20 +2734,6 @@ } static struct pci_device_id tulip_pci_table[] __devinitdata = { -#if 0 /* these entries conflict with regular tulip driver */ - { 0x1011, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21040 }, - { 0x1011, 0x0014, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21041 }, - { 0x1011, 0x0009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21140 }, - { 0x1011, 0x0019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21142 }, - { 0x11AD, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, LC82C168 }, - { 0x10d9, 0x0512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98713 }, - { 0x10d9, 0x0531, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98715 }, - { 0x10d9, 0x0531, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98725 }, - { 0x125B, 0x1400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AX88140 }, - { 0x11AD, 0xc115, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PNIC2 }, - { 0x1317, 0x0981, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, - { 0x11F6, 0x9881, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMPEX9881 }, -#endif { 0x115D, 0x0003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, X3201_3 }, {0}, }; @@ -3034,20 +2759,22 @@ return -ENODEV; } -static void tulip_suspend(struct pci_dev *pdev) +static int tulip_suspend(struct pci_dev *pdev, u32 state) { struct net_device *dev = pdev->driver_data; struct tulip_private *tp = (struct tulip_private *)dev->priv; printk(KERN_INFO "tulip_suspend(%s)\n", dev->name); if (tp->open) tulip_down(dev); + return 0; } -static void tulip_resume(struct pci_dev *pdev) +static int tulip_resume(struct pci_dev *pdev) { struct net_device *dev = pdev->driver_data; struct tulip_private *tp = (struct tulip_private *)dev->priv; printk(KERN_INFO "tulip_resume(%s)\n", dev->name); if (tp->open) tulip_up(dev); + return 0; } static void __devexit tulip_remove(struct pci_dev *pdev) diff -u --recursive --new-file v2.4.5/linux/drivers/net/pcnet32.c linux/drivers/net/pcnet32.c --- v2.4.5/linux/drivers/net/pcnet32.c Thu Apr 19 22:57:06 2001 +++ linux/drivers/net/pcnet32.c Mon Jul 2 14:03:04 2001 @@ -47,6 +47,16 @@ static unsigned int pcnet32_portlist[] __initdata = {0x300, 0x320, 0x340, 0x360, 0}; +/* + * PCI device identifiers for "new style" Linux PCI Device Drivers + */ +static struct pci_device_id pcnet32_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE_HOME, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, 0x1014, 0x2000, 0, 0, 0 }, + { 0, } +}; + static int pcnet32_debug = 1; static int tx_start = 1; /* Mapping -- 0:20, 1:64, 2:128, 3:~220 (depends on chip vers) */ @@ -205,16 +215,6 @@ #define PCNET32_TOTAL_SIZE 0x20 -/* some PCI ids */ -#ifndef PCI_DEVICE_ID_AMD_LANCE -#define PCI_VENDOR_ID_AMD 0x1022 -#define PCI_DEVICE_ID_AMD_LANCE 0x2000 -#endif -#ifndef PCI_DEVICE_ID_AMD_PCNETHOME -#define PCI_DEVICE_ID_AMD_PCNETHOME 0x2001 -#endif - - #define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ /* The PCNET32 Rx and Tx ring descriptors. */ @@ -319,16 +319,6 @@ int (*probe1) (unsigned long, unsigned char, int, int, struct pci_dev *); }; - -/* - * PCI device identifiers for "new style" Linux PCI Device Drivers - */ -static struct pci_device_id pcnet32_pci_tbl[] __devinitdata = { - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_PCNETHOME, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, 0x1014, 0x2000, 0, 0, 0 }, - { 0, } -}; MODULE_DEVICE_TABLE (pci, pcnet32_pci_tbl); diff -u --recursive --new-file v2.4.5/linux/drivers/net/plip.c linux/drivers/net/plip.c --- v2.4.5/linux/drivers/net/plip.c Thu Apr 19 09:34:52 2001 +++ linux/drivers/net/plip.c Wed Jun 20 11:10:53 2001 @@ -1297,6 +1297,7 @@ MODULE_PARM(parport, "1-" __MODULE_STRING(PLIP_MAX) "i"); MODULE_PARM(timid, "1i"); +MODULE_PARM_DESC(parport, "List of parport device numbers to use by plip"); static struct net_device *dev_plip[PLIP_MAX] = { NULL, }; diff -u --recursive --new-file v2.4.5/linux/drivers/net/ppp_async.c linux/drivers/net/ppp_async.c --- v2.4.5/linux/drivers/net/ppp_async.c Fri Apr 20 11:54:24 2001 +++ linux/drivers/net/ppp_async.c Wed Jun 20 11:10:53 2001 @@ -80,6 +80,7 @@ static int flag_time = HZ; MODULE_PARM(flag_time, "i"); +MODULE_PARM_DESC(flag_time, "ppp_async: interval between flagged packets (in clock ticks)"); /* * Prototypes. diff -u --recursive --new-file v2.4.5/linux/drivers/net/rcif.h linux/drivers/net/rcif.h --- v2.4.5/linux/drivers/net/rcif.h Thu Jan 14 22:58:47 1999 +++ linux/drivers/net/rcif.h Mon Jul 2 14:03:04 2001 @@ -38,39 +38,35 @@ /* The following protocol revision # should be incremented every time a new protocol or new structures are used in this file. */ -int USER_PROTOCOL_REV = 2; /* used to track different protocol revisions */ +int USER_PROTOCOL_REV = 2; /* used to track different protocol revisions */ /* define a single TCB & buffer */ -typedef struct /* a single buffer */ -{ - U32 context; /* context */ - U32 scount; /* segment count */ - U32 size; /* segment size */ - U32 addr; /* segment physical address */ -} -__attribute__((packed)) -singleB, *psingleB ; -typedef struct /* a single TCB */ -{ - /* - ** +-----------------------+ - ** | 1 | one buffer in the TCB - ** +-----------------------+ - ** | | user's buffer reference - ** +-----------------------+ - ** | 1 | one segment buffer - ** +-----------------------+ _ - ** | | size \ - ** +-----------------------+ \ segment descriptor - ** | | physical address of buffer / - ** +-----------------------+ _/ - */ - U32 bcount; /* buffer count */ - singleB b; /* buffer */ - -} -__attribute__((packed)) -singleTCB, *psingleTCB; +typedef struct { /* a single buffer */ + U32 context; /* context */ + U32 scount; /* segment count */ + U32 size; /* segment size */ + U32 addr; /* segment physical address */ +} __attribute__ ((packed)) + singleB, *psingleB; +typedef struct { /* a single TCB */ + /* + ** +-----------------------+ + ** | 1 | one buffer in the TCB + ** +-----------------------+ + ** | | user's buffer reference + ** +-----------------------+ + ** | 1 | one segment buffer + ** +-----------------------+ _ + ** | | size \ + ** +-----------------------+ \ segment descriptor + ** | | physical address of buffer / + ** +-----------------------+ _/ + */ + U32 bcount; /* buffer count */ + singleB b; /* buffer */ + +} __attribute__ ((packed)) + singleTCB, *psingleTCB; /* When adding new entries, please add all 5 related changes, since @@ -104,121 +100,119 @@ typedef struct RC_user_tag RCuser_struct; /* 1) User structure entry */ -struct RC_user_tag -{ - int cmd; - union - { - /* GETINFO structure */ - struct RCgetinfo_tag { - unsigned long int mem_start; - unsigned long int mem_end; - unsigned long int base_addr; - unsigned char irq; - unsigned char dma; - unsigned char port; - } RCgetinfo; /* <---- RCgetinfo */ - - /* GETSPEED structure */ - struct RCgetspeed_tag { - U32 LinkSpeedCode; - } RCgetspeed; /* <---- RCgetspeed */ - - /* SETSPEED structure */ - struct RCsetspeed_tag { - U16 LinkSpeedCode; - } RCsetspeed; /* <---- RCsetspeed */ - - /* GETPROM structure */ - struct RCgetprom_tag { - U32 PromMode; - } RCgetprom; /* <---- RCgetprom */ - - /* SETPROM structure */ - struct RCsetprom_tag { - U16 PromMode; - } RCsetprom; /* <---- RCsetprom */ - - /* GETBROADCAST structure */ - struct RCgetbroadcast_tag { - U32 BroadcastMode; - } RCgetbroadcast; /* <---- RCgetbroadcast */ - - /* SETBROADCAST structure */ - struct RCsetbroadcast_tag { - U16 BroadcastMode; - } RCsetbroadcast; /* <---- RCsetbroadcast */ - - /* GETFIRMWAREVER structure */ - #define FirmStringLen 80 - struct RCgetfwver_tag { - U8 FirmString[FirmStringLen]; - } RCgetfwver; /* <---- RCgetfwver */ - - /* GETIPANDMASK structure */ - struct RCgetipnmask_tag { - U32 IpAddr; - U32 NetMask; - } RCgetipandmask; /* <---- RCgetipandmask */ - - /* SETIPANDMASK structure */ - struct RCsetipnmask_tag { - U32 IpAddr; - U32 NetMask; - } RCsetipandmask; /* <---- RCsetipandmask */ - - /* GETMAC structure */ - #define MAC_SIZE 10 - struct RCgetmac_tag { - U8 mac[MAC_SIZE]; - } RCgetmac; /* <---- RCgetmac */ - - /* SETMAC structure */ - struct RCsetmac_tag { - U8 mac[MAC_SIZE]; - } RCsetmac; /* <---- RCsetmac */ - - /* GETLINKSTATUS structure */ - struct RCgetlnkstatus_tag { - U32 ReturnStatus; - } RCgetlnkstatus; /* <---- RCgetlnkstatus */ - - /* GETLINKSTATISTICS structure */ - struct RCgetlinkstats_tag { - RCLINKSTATS StatsReturn; - } RCgetlinkstats; /* <---- RCgetlinkstats */ - - /* DEFAULT structure (when no command was recognized) */ - struct RCdefault_tag { - int rc; - } RCdefault; /* <---- RCdefault */ +struct RC_user_tag { + int cmd; + union { + /* GETINFO structure */ + struct RCgetinfo_tag { + unsigned long int mem_start; + unsigned long int mem_end; + unsigned long int base_addr; + unsigned char irq; + unsigned char dma; + unsigned char port; + } RCgetinfo; /* <---- RCgetinfo */ + + /* GETSPEED structure */ + struct RCgetspeed_tag { + U32 LinkSpeedCode; + } RCgetspeed; /* <---- RCgetspeed */ + + /* SETSPEED structure */ + struct RCsetspeed_tag { + U16 LinkSpeedCode; + } RCsetspeed; /* <---- RCsetspeed */ + + /* GETPROM structure */ + struct RCgetprom_tag { + U32 PromMode; + } RCgetprom; /* <---- RCgetprom */ + + /* SETPROM structure */ + struct RCsetprom_tag { + U16 PromMode; + } RCsetprom; /* <---- RCsetprom */ + + /* GETBROADCAST structure */ + struct RCgetbroadcast_tag { + U32 BroadcastMode; + } RCgetbroadcast; /* <---- RCgetbroadcast */ + + /* SETBROADCAST structure */ + struct RCsetbroadcast_tag { + U16 BroadcastMode; + } RCsetbroadcast; /* <---- RCsetbroadcast */ + + /* GETFIRMWAREVER structure */ +#define FirmStringLen 80 + struct RCgetfwver_tag { + U8 FirmString[FirmStringLen]; + } RCgetfwver; /* <---- RCgetfwver */ + + /* GETIPANDMASK structure */ + struct RCgetipnmask_tag { + U32 IpAddr; + U32 NetMask; + } RCgetipandmask; /* <---- RCgetipandmask */ + + /* SETIPANDMASK structure */ + struct RCsetipnmask_tag { + U32 IpAddr; + U32 NetMask; + } RCsetipandmask; /* <---- RCsetipandmask */ + + /* GETMAC structure */ +#define MAC_SIZE 10 + struct RCgetmac_tag { + U8 mac[MAC_SIZE]; + } RCgetmac; /* <---- RCgetmac */ + + /* SETMAC structure */ + struct RCsetmac_tag { + U8 mac[MAC_SIZE]; + } RCsetmac; /* <---- RCsetmac */ + + /* GETLINKSTATUS structure */ + struct RCgetlnkstatus_tag { + U32 ReturnStatus; + } RCgetlnkstatus; /* <---- RCgetlnkstatus */ + + /* GETLINKSTATISTICS structure */ + struct RCgetlinkstats_tag { + RCLINKSTATS StatsReturn; + } RCgetlinkstats; /* <---- RCgetlinkstats */ + + /* DEFAULT structure (when no command was recognized) */ + struct RCdefault_tag { + int rc; + } RCdefault; /* <---- RCdefault */ - } data; + } data; -}; /* struct RC_user_tag { ... } */ +}; /* struct RC_user_tag { ... } */ /* 2) User data entry */ /* RCUD = RedCreek User Data */ -union RC_user_data_tag { /* structure tags used are taken from RC_user_tag structure above */ - struct RCgetinfo_tag *getinfo; - struct RCgetspeed_tag *getspeed; - struct RCgetprom_tag *getprom; - struct RCgetbroadcast_tag *getbroadcast; - struct RCgetfwver_tag *getfwver; - struct RCgetipnmask_tag *getipandmask; - struct RCgetmac_tag *getmac; - struct RCgetlnkstatus_tag *getlinkstatus; - struct RCgetlinkstats_tag *getlinkstatistics; - struct RCdefault_tag *rcdefault; - struct RCsetspeed_tag *setspeed; - struct RCsetprom_tag *setprom; - struct RCsetbroadcast_tag *setbroadcast; - struct RCsetipnmask_tag *setipandmask; - struct RCsetmac_tag *setmac; -} _RC_user_data; /* declare as a global, so the defines below will work */ +union RC_user_data_tag { /* structure tags used are taken from RC_user_tag structure above */ + struct RCgetinfo_tag *getinfo; + struct RCgetspeed_tag *getspeed; + struct RCgetprom_tag *getprom; + struct RCgetbroadcast_tag *getbroadcast; + struct RCgetfwver_tag *getfwver; + struct RCgetipnmask_tag *getipandmask; + struct RCgetmac_tag *getmac; + struct RCgetlnkstatus_tag *getlinkstatus; + struct RCgetlinkstats_tag *getlinkstatistics; + struct RCdefault_tag *rcdefault; + struct RCsetspeed_tag *setspeed; + struct RCsetprom_tag *setprom; + struct RCsetbroadcast_tag *setbroadcast; + struct RCsetipnmask_tag *setipandmask; + struct RCsetmac_tag *setmac; +} _RC_user_data; /* declare as a global, so the defines below will work */ /* 3) Structure short-cut entry */ -/* define structure short-cuts */ /* structure names are taken from RC_user_tag structure above */ +/* define structure short-cuts *//* structure names are taken from RC_user_tag structure above */ #define RCUS_GETINFO data.RCgetinfo; #define RCUS_GETSPEED data.RCgetspeed; #define RCUS_GETPROM data.RCgetprom; @@ -236,7 +230,7 @@ #define RCUS_SETMAC data.RCsetmac; /* 4) Data short-cut entry */ -/* define data short-cuts */ /* pointer names are from RC_user_data_tag union (just below RC_user_tag) */ +/* define data short-cuts *//* pointer names are from RC_user_data_tag union (just below RC_user_tag) */ #define RCUD_GETINFO _RC_user_data.getinfo #define RCUD_GETSPEED _RC_user_data.getspeed #define RCUD_GETPROM _RC_user_data.getprom @@ -295,5 +289,4 @@ RCUD_GETINFO->base_addr, RCUD_GETINFO->irq); */ -#endif /* RCIF_H */ - +#endif /* RCIF_H */ diff -u --recursive --new-file v2.4.5/linux/drivers/net/rclanmtl.c linux/drivers/net/rclanmtl.c --- v2.4.5/linux/drivers/net/rclanmtl.c Sun Feb 4 10:05:30 2001 +++ linux/drivers/net/rclanmtl.c Mon Jul 2 14:03:04 2001 @@ -42,10 +42,9 @@ #include "rclanmtl.h" /* RedCreek LAN device Target ID */ -#define RC_LAN_TARGET_ID 0x10 +#define RC_LAN_TARGET_ID 0x10 /* RedCreek's OSM default LAN receive Initiator */ -#define DEFAULT_RECV_INIT_CONTEXT 0xA17 - +#define DEFAULT_RECV_INIT_CONTEXT 0xA17 /* ** I2O message structures @@ -102,17 +101,14 @@ #define I2O_EXEC_SYS_QUIESCE 0xC3 #define I2O_EXEC_SYS_TAB_SET 0xA3 - /* Init Outbound Q status */ #define I2O_EXEC_OUTBOUND_INIT_IN_PROGRESS 0x01 #define I2O_EXEC_OUTBOUND_INIT_REJECTED 0x02 #define I2O_EXEC_OUTBOUND_INIT_FAILED 0x03 #define I2O_EXEC_OUTBOUND_INIT_COMPLETE 0x04 - #define I2O_UTIL_NOP 0x00 - /* I2O Get Status State values */ #define I2O_IOP_STATE_INITIALIZING 0x01 @@ -123,7 +119,6 @@ #define I2O_IOP_STATE_FAILED 0x10 #define I2O_IOP_STATE_FAULTED 0x11 - /* Defines for Request Status Codes: Table 3-1 Reply Status Codes. */ #define I2O_REPLY_STATUS_SUCCESS 0x00 @@ -139,7 +134,6 @@ #define I2O_REPLY_STATUS_TRANSACTION_ERROR 0x0A #define I2O_REPLY_STATUS_PROGRESS_REPORT 0x80 - /* DetailedStatusCode defines for ALL messages: Table 3-2 Detailed Status Codes.*/ #define I2O_DETAIL_STATUS_SUCCESS 0x0000 @@ -203,17 +197,17 @@ #define I2O_HOST_TID 0xB91 /* RedCreek I2O private message codes */ -#define RC_PRIVATE_GET_MAC_ADDR 0x0001/**/ /* OBSOLETE */ +#define RC_PRIVATE_GET_MAC_ADDR 0x0001/**/ /* OBSOLETE */ #define RC_PRIVATE_SET_MAC_ADDR 0x0002 #define RC_PRIVATE_GET_NIC_STATS 0x0003 #define RC_PRIVATE_GET_LINK_STATUS 0x0004 #define RC_PRIVATE_SET_LINK_SPEED 0x0005 #define RC_PRIVATE_SET_IP_AND_MASK 0x0006 -/* #define RC_PRIVATE_GET_IP_AND_MASK 0x0007 */ /* OBSOLETE */ +/* #define RC_PRIVATE_GET_IP_AND_MASK 0x0007 *//* OBSOLETE */ #define RC_PRIVATE_GET_LINK_SPEED 0x0008 #define RC_PRIVATE_GET_FIRMWARE_REV 0x0009 /* #define RC_PRIVATE_GET_MAC_ADDR 0x000A */ -#define RC_PRIVATE_GET_IP_AND_MASK 0x000B +#define RC_PRIVATE_GET_IP_AND_MASK 0x000B #define RC_PRIVATE_DEBUG_MSG 0x000C #define RC_PRIVATE_REPORT_DRIVER_CAPABILITY 0x000D #define RC_PRIVATE_SET_PROMISCUOUS_MODE 0x000e @@ -223,30 +217,26 @@ #define RC_PRIVATE_REBOOT 0x00FF - /* I2O message header */ -typedef struct _I2O_MESSAGE_FRAME -{ - U8 VersionOffset; - U8 MsgFlags; - U16 MessageSize; - BF TargetAddress:I2O_TID_SZ; - BF InitiatorAddress:I2O_TID_SZ; - BF Function:I2O_FUNCTION_SZ; - U32 InitiatorContext; - /* SGL[] */ -} -I2O_MESSAGE_FRAME, *PI2O_MESSAGE_FRAME; - +typedef struct _I2O_MESSAGE_FRAME { + U8 VersionOffset; + U8 MsgFlags; + U16 MessageSize; + BF TargetAddress:I2O_TID_SZ; + BF InitiatorAddress:I2O_TID_SZ; + BF Function:I2O_FUNCTION_SZ; + U32 InitiatorContext; + /* SGL[] */ +} I2O_MESSAGE_FRAME, *PI2O_MESSAGE_FRAME; /* assumed a 16K minus 256 byte space for outbound queue message frames */ #define MSG_FRAME_SIZE 512 #define NMBR_MSG_FRAMES 30 /* - ** in reserved space right after PAB in host memory is area for returning - ** values from card - */ + ** in reserved space right after PAB in host memory is area for returning + ** values from card + */ /* ** typedef NICSTAT @@ -254,43 +244,37 @@ ** Data structure for NIC statistics retruned from PCI card. Data copied from ** here to user allocated RCLINKSTATS (see rclanmtl.h) structure. */ -typedef struct tag_NicStat -{ - unsigned long TX_good; - unsigned long TX_maxcol; - unsigned long TX_latecol; - unsigned long TX_urun; - unsigned long TX_crs; /* lost carrier sense */ - unsigned long TX_def; /* transmit deferred */ - unsigned long TX_singlecol; /* single collisions */ - unsigned long TX_multcol; - unsigned long TX_totcol; - unsigned long Rcv_good; - unsigned long Rcv_CRCerr; - unsigned long Rcv_alignerr; - unsigned long Rcv_reserr; /* rnr'd pkts */ - unsigned long Rcv_orun; - unsigned long Rcv_cdt; - unsigned long Rcv_runt; - unsigned long dump_status; /* last field directly from the chip */ -} -NICSTAT, *P_NICSTAT; - - -#define DUMP_DONE 0x0000A005 /* completed statistical dump */ -#define DUMP_CLEAR 0x0000A007 /* completed stat dump and clear counters */ +typedef struct tag_NicStat { + unsigned long TX_good; + unsigned long TX_maxcol; + unsigned long TX_latecol; + unsigned long TX_urun; + unsigned long TX_crs; /* lost carrier sense */ + unsigned long TX_def; /* transmit deferred */ + unsigned long TX_singlecol; /* single collisions */ + unsigned long TX_multcol; + unsigned long TX_totcol; + unsigned long Rcv_good; + unsigned long Rcv_CRCerr; + unsigned long Rcv_alignerr; + unsigned long Rcv_reserr; /* rnr'd pkts */ + unsigned long Rcv_orun; + unsigned long Rcv_cdt; + unsigned long Rcv_runt; + unsigned long dump_status; /* last field directly from the chip */ +} NICSTAT, *P_NICSTAT; +#define DUMP_DONE 0x0000A005 /* completed statistical dump */ +#define DUMP_CLEAR 0x0000A007 /* completed stat dump and clear counters */ static volatile int msgFlag; - /* local function prototypes */ -static void ProcessOutboundI2OMsg(PPAB pPab, U32 phyMsgAddr); -static int FillI2OMsgSGLFromTCB(PU32 pMsg, PRCTCB pXmitCntrlBlock); -static int GetI2OStatus(PPAB pPab); -static int SendI2OOutboundQInitMsg(PPAB pPab); -static int SendEnableSysMsg(PPAB pPab); - +static void ProcessOutboundI2OMsg (PPAB pPab, U32 phyMsgAddr); +static int FillI2OMsgSGLFromTCB (PU32 pMsg, PRCTCB pXmitCntrlBlock); +static int GetI2OStatus (PPAB pPab); +static int SendI2OOutboundQInitMsg (PPAB pPab); +static int SendEnableSysMsg (PPAB pPab); /* ** ========================================================================= @@ -308,85 +292,89 @@ ** ========================================================================= */ RC_RETURN -RCInitI2OMsgLayer(struct net_device *dev, - PFNTXCALLBACK TransmitCallbackFunction, - PFNRXCALLBACK ReceiveCallbackFunction, - PFNCALLBACK RebootCallbackFunction) -{ - int result; - PPAB pPab; - U32 pciBaseAddr = dev->base_addr; - PDPA pDpa = dev->priv; - PU8 p_msgbuf = pDpa->PLanApiPA; - PU8 p_phymsgbuf = (PU8)virt_to_bus((void *) p_msgbuf); - - dprintk("InitI2O: Adapter:0x%04ux ATU:0x%08ulx msgbuf:0x%08ulx phymsgbuf:0x%08ulx\n" - "TransmitCallbackFunction:0x%08ulx ReceiveCallbackFunction:0x%08ulx\n", - pDpa->id, pciBaseAddr, (u32)p_msgbuf, (u32)p_phymsgbuf, - (u32)TransmitCallbackFunction, (u32)ReceiveCallbackFunction); - - - /* Check if this interface already initialized - if so, shut it down */ - if (pDpa->pPab != NULL) { - printk(KERN_WARNING "(rcpci45 driver:) pDpa->pPab [%d] != NULL\n", pDpa->id); +RCInitI2OMsgLayer (struct net_device *dev, + PFNTXCALLBACK TransmitCallbackFunction, + PFNRXCALLBACK ReceiveCallbackFunction, + PFNCALLBACK RebootCallbackFunction) +{ + int result; + PPAB pPab; + U32 pciBaseAddr = dev->base_addr; + PDPA pDpa = dev->priv; + PU8 p_msgbuf = pDpa->PLanApiPA; + PU8 p_phymsgbuf = (PU8) virt_to_bus ((void *) p_msgbuf); + + dprintk + ("InitI2O: Adapter:0x%04ux ATU:0x%08ulx msgbuf:0x%08ulx phymsgbuf:0x%08ulx\n" + "TransmitCallbackFunction:0x%08ulx ReceiveCallbackFunction:0x%08ulx\n", + pDpa->id, pciBaseAddr, (u32) p_msgbuf, (u32) p_phymsgbuf, + (u32) TransmitCallbackFunction, (u32) ReceiveCallbackFunction); + + /* Check if this interface already initialized - if so, shut it down */ + if (pDpa->pPab != NULL) { + printk (KERN_WARNING + "(rcpci45 driver:) pDpa->pPab [%d] != NULL\n", + pDpa->id); /* RCResetLANCard(pDpa->id, 0, (PU32)NULL, (PFNCALLBACK)NULL); */ - pDpa->pPab = NULL; - } + pDpa->pPab = NULL; + } + + /* store adapter instance values in adapter block. + * Adapter block is at beginning of message buffer */ - /* store adapter instance values in adapter block. - * Adapter block is at beginning of message buffer */ - - pPab = kmalloc(sizeof(*pPab), GFP_KERNEL); - if (!pPab) { - printk(KERN_ERR "(rcpci45 driver:) RCInitI2OMsgLayer: Could not allocate memory for PAB struct!\n"); - result = RC_RTN_MALLOC_ERROR; - goto err_out; - } - - memset(pPab, 0, sizeof(*pPab)); - pDpa->pPab = pPab; - pPab->p_atu = (PATU)pciBaseAddr; - pPab->pPci45LinBaseAddr = (PU8)pciBaseAddr; - - /* Set outbound message frame addr */ - pPab->outMsgBlockPhyAddr = (U32)p_phymsgbuf; - pPab->pLinOutMsgBlock = (PU8)p_msgbuf; - - /* store callback function addresses */ - pPab->pTransCallbackFunc = TransmitCallbackFunction; - pPab->pRecvCallbackFunc = ReceiveCallbackFunction; - pPab->pRebootCallbackFunc = RebootCallbackFunction; - pPab->pCallbackFunc = (PFNCALLBACK)NULL; - - /* - ** Initialize I2O IOP - */ - result = GetI2OStatus(pPab); - - if (result != RC_RTN_NO_ERROR) - goto err_out_dealloc; - - if (pPab->IOPState == I2O_IOP_STATE_OPERATIONAL) { - printk(KERN_INFO "(rcpci45 driver:) pPab->IOPState == op: resetting adapter\n"); - RCResetLANCard(dev, 0, (PU32)NULL, (PFNCALLBACK)NULL); - } - - result = SendI2OOutboundQInitMsg(pPab); - - if (result != RC_RTN_NO_ERROR) - goto err_out_dealloc; - - result = SendEnableSysMsg(pPab); - - if (result != RC_RTN_NO_ERROR) - goto err_out_dealloc; - - return RC_RTN_NO_ERROR; - - err_out_dealloc: - kfree(pPab); - err_out: - return result; + pPab = kmalloc (sizeof (*pPab), GFP_KERNEL); + if (!pPab) { + printk (KERN_ERR + "(rcpci45 driver:) RCInitI2OMsgLayer: Could not allocate memory for PAB struct!\n"); + result = RC_RTN_MALLOC_ERROR; + goto err_out; + } + + memset (pPab, 0, sizeof (*pPab)); + pDpa->pPab = pPab; + pPab->p_atu = (PATU) pciBaseAddr; + pPab->pPci45LinBaseAddr = (PU8) pciBaseAddr; + + /* Set outbound message frame addr */ + pPab->outMsgBlockPhyAddr = (U32) p_phymsgbuf; + pPab->pLinOutMsgBlock = (PU8) p_msgbuf; + + /* store callback function addresses */ + pPab->pTransCallbackFunc = TransmitCallbackFunction; + pPab->pRecvCallbackFunc = ReceiveCallbackFunction; + pPab->pRebootCallbackFunc = RebootCallbackFunction; + pPab->pCallbackFunc = (PFNCALLBACK) NULL; + + /* + ** Initialize I2O IOP + */ + result = GetI2OStatus (pPab); + + if (result != RC_RTN_NO_ERROR) + goto err_out_dealloc; + + if (pPab->IOPState == I2O_IOP_STATE_OPERATIONAL) { + printk (KERN_INFO + "(rcpci45 driver:) pPab->IOPState == op: resetting adapter\n"); + RCResetLANCard (dev, 0, (PU32) NULL, (PFNCALLBACK) NULL); + } + + result = SendI2OOutboundQInitMsg (pPab); + + if (result != RC_RTN_NO_ERROR) + goto err_out_dealloc; + + result = SendEnableSysMsg (pPab); + + if (result != RC_RTN_NO_ERROR) + goto err_out_dealloc; + + return RC_RTN_NO_ERROR; + + err_out_dealloc: + kfree (pPab); + err_out: + return result; } /* @@ -399,35 +387,34 @@ ** queue is not emtpy. ** ========================================================================= */ -#define i960_OUT_POST_Q_INT_BIT 0x0008 /* bit set masks interrupts */ +#define i960_OUT_POST_Q_INT_BIT 0x0008 /* bit set masks interrupts */ -RC_RETURN RCDisableI2OInterrupts(struct net_device *dev) +RC_RETURN +RCDisableI2OInterrupts (struct net_device * dev) { - PPAB pPab = ((PDPA)dev->priv)->pPab; + PPAB pPab = ((PDPA) dev->priv)->pPab; + if (pPab == NULL) + return RC_RTN_ADPTR_NOT_REGISTERED; - if (pPab == NULL) - return RC_RTN_ADPTR_NOT_REGISTERED; - - pPab->p_atu->OutIntMask |= i960_OUT_POST_Q_INT_BIT; + pPab->p_atu->OutIntMask |= i960_OUT_POST_Q_INT_BIT; - return RC_RTN_NO_ERROR; + return RC_RTN_NO_ERROR; } -RC_RETURN RCEnableI2OInterrupts(struct net_device *dev) +RC_RETURN +RCEnableI2OInterrupts (struct net_device * dev) { - PPAB pPab = ((PDPA)dev->priv)->pPab; + PPAB pPab = ((PDPA) dev->priv)->pPab; + if (pPab == NULL) + return RC_RTN_ADPTR_NOT_REGISTERED; - if (pPab == NULL) - return RC_RTN_ADPTR_NOT_REGISTERED; - - pPab->p_atu->OutIntMask &= ~i960_OUT_POST_Q_INT_BIT; - - return RC_RTN_NO_ERROR; + pPab->p_atu->OutIntMask &= ~i960_OUT_POST_Q_INT_BIT; -} + return RC_RTN_NO_ERROR; +} /* ** ========================================================================= @@ -435,55 +422,53 @@ ** ========================================================================= */ RC_RETURN -RCI2OSendPacket(struct net_device *dev, U32 InitiatorContext, - PRCTCB pTransCtrlBlock) +RCI2OSendPacket (struct net_device * dev, U32 InitiatorContext, + PRCTCB pTransCtrlBlock) { - U32 msgOffset; - PU32 pMsg; - int size; - PPAB pPab = ((PDPA)dev->priv)->pPab; - - - dprintk("RCI2OSendPacket()...\n"); - - if (pPab == NULL) - return RC_RTN_ADPTR_NOT_REGISTERED; - - /* get Inbound free Q entry - reading from In Q gets free Q entry */ - /* offset to Msg Frame in PCI msg block */ - - msgOffset = pPab->p_atu->InQueue; - - if (msgOffset == 0xFFFFFFFF) - { - dprintk("RCI2OSendPacket(): Inbound Free Q empty!\n"); - return RC_RTN_FREE_Q_EMPTY; - } - - /* calc virual address of msg - virual already mapped to physical */ - pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset); - - size = FillI2OMsgSGLFromTCB(pMsg + 4, pTransCtrlBlock); - - if (size == -1) /* error processing TCB - send NOP msg */ - { - dprintk("RCI2OSendPacket(): Error Rrocess TCB!\n"); - pMsg[0] = THREE_WORD_MSG_SIZE | SGL_OFFSET_0; - pMsg[1] = I2O_UTIL_NOP << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; - return RC_RTN_TCB_ERROR; - } - else /* send over msg header */ - { - pMsg[0] = (size + 4) << 16 | LAN_MSG_REQST; /* send over message size and flags */ - pMsg[1] = I2O_LAN_PACKET_SEND << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; - pMsg[2] = InitiatorContext; - pMsg[3] = 0; /* batch reply */ - /* post to Inbound Post Q */ - pPab->p_atu->InQueue = msgOffset; - return RC_RTN_NO_ERROR; - } + U32 msgOffset; + PU32 pMsg; + int size; + PPAB pPab = ((PDPA) dev->priv)->pPab; + + dprintk ("RCI2OSendPacket()...\n"); + + if (pPab == NULL) + return RC_RTN_ADPTR_NOT_REGISTERED; + + /* get Inbound free Q entry - reading from In Q gets free Q entry */ + /* offset to Msg Frame in PCI msg block */ + + msgOffset = pPab->p_atu->InQueue; + + if (msgOffset == 0xFFFFFFFF) { + dprintk ("RCI2OSendPacket(): Inbound Free Q empty!\n"); + return RC_RTN_FREE_Q_EMPTY; + } + + /* calc virual address of msg - virual already mapped to physical */ + pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset); + + size = FillI2OMsgSGLFromTCB (pMsg + 4, pTransCtrlBlock); + + if (size == -1) { /* error processing TCB - send NOP msg */ + dprintk ("RCI2OSendPacket(): Error Rrocess TCB!\n"); + pMsg[0] = THREE_WORD_MSG_SIZE | SGL_OFFSET_0; + pMsg[1] = + I2O_UTIL_NOP << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; + return RC_RTN_TCB_ERROR; + } else { /* send over msg header */ + + pMsg[0] = (size + 4) << 16 | LAN_MSG_REQST; /* send over message size and flags */ + pMsg[1] = + I2O_LAN_PACKET_SEND << 24 | I2O_HOST_TID << 12 | + RC_LAN_TARGET_ID; + pMsg[2] = InitiatorContext; + pMsg[3] = 0; /* batch reply */ + /* post to Inbound Post Q */ + pPab->p_atu->InQueue = msgOffset; + return RC_RTN_NO_ERROR; + } } - /* ** ========================================================================= @@ -495,56 +480,57 @@ ** ========================================================================= */ RC_RETURN -RCPostRecvBuffers(struct net_device *dev, PRCTCB pTransCtrlBlock) +RCPostRecvBuffers (struct net_device * dev, PRCTCB pTransCtrlBlock) { - U32 msgOffset; - PU32 pMsg; - int size; - PPAB pPab = ((PDPA)dev->priv)->pPab; - - dprintk("RCPostRecvBuffers()...\n"); - - /* search for DeviceHandle */ - - if (pPab == NULL) - return RC_RTN_ADPTR_NOT_REGISTERED; - - /* get Inbound free Q entry - reading from In Q gets free Q entry */ - /* offset to Msg Frame in PCI msg block */ - msgOffset = pPab->p_atu->InQueue; - - if (msgOffset == 0xFFFFFFFF) - { - dprintk("RCPostRecvBuffers(): Inbound Free Q empty!\n"); - return RC_RTN_FREE_Q_EMPTY; - } - /* calc virual address of msg - virual already mapped to physical */ - pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset); - - size = FillI2OMsgSGLFromTCB(pMsg + 4, pTransCtrlBlock); - - if (size == -1) /* error prcessing TCB - send 3 DWORD private msg == NOP */ - { - dprintk("RCPostRecvBuffers(): Error Processing TCB! size = %d\n", size); - pMsg[0] = THREE_WORD_MSG_SIZE | SGL_OFFSET_0; - pMsg[1] = I2O_UTIL_NOP << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; - /* post to Post Q */ - pPab->p_atu->InQueue = msgOffset; - return RC_RTN_TCB_ERROR; - } - else /* send over size msg header */ - { - pMsg[0] = (size + 4) << 16 | LAN_MSG_REQST; /* send over message size and flags */ - pMsg[1] = I2O_LAN_RECEIVE_POST << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; - pMsg[2] = DEFAULT_RECV_INIT_CONTEXT; - pMsg[3] = *(PU32)pTransCtrlBlock; /* number of packet buffers */ - /* post to Post Q */ - pPab->p_atu->InQueue = msgOffset; - return RC_RTN_NO_ERROR; - } + U32 msgOffset; + PU32 pMsg; + int size; + PPAB pPab = ((PDPA) dev->priv)->pPab; + + dprintk ("RCPostRecvBuffers()...\n"); + + /* search for DeviceHandle */ + + if (pPab == NULL) + return RC_RTN_ADPTR_NOT_REGISTERED; + + /* get Inbound free Q entry - reading from In Q gets free Q entry */ + /* offset to Msg Frame in PCI msg block */ + msgOffset = pPab->p_atu->InQueue; + + if (msgOffset == 0xFFFFFFFF) { + dprintk ("RCPostRecvBuffers(): Inbound Free Q empty!\n"); + return RC_RTN_FREE_Q_EMPTY; + } + /* calc virual address of msg - virual already mapped to physical */ + pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset); + + size = FillI2OMsgSGLFromTCB (pMsg + 4, pTransCtrlBlock); + + if (size == -1) { /* error prcessing TCB - send 3 DWORD private msg == NOP */ + dprintk + ("RCPostRecvBuffers(): Error Processing TCB! size = %d\n", + size); + pMsg[0] = THREE_WORD_MSG_SIZE | SGL_OFFSET_0; + pMsg[1] = + I2O_UTIL_NOP << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; + /* post to Post Q */ + pPab->p_atu->InQueue = msgOffset; + return RC_RTN_TCB_ERROR; + } else { /* send over size msg header */ + + pMsg[0] = (size + 4) << 16 | LAN_MSG_REQST; /* send over message size and flags */ + pMsg[1] = + I2O_LAN_RECEIVE_POST << 24 | I2O_HOST_TID << 12 | + RC_LAN_TARGET_ID; + pMsg[2] = DEFAULT_RECV_INIT_CONTEXT; + pMsg[3] = *(PU32) pTransCtrlBlock; /* number of packet buffers */ + /* post to Post Q */ + pPab->p_atu->InQueue = msgOffset; + return RC_RTN_NO_ERROR; + } } - /* ** ========================================================================= ** RCProcI2OMsgQ() @@ -552,106 +538,112 @@ ** Process I2O outbound message queue until empty. ** ========================================================================= */ -void -RCProcI2OMsgQ(struct net_device *dev) +void +RCProcI2OMsgQ (struct net_device *dev) { - U32 phyAddrMsg; - PU8 p8Msg; - PU32 p32; - U16 count; - PPAB pPab = ((PDPA)dev->priv)->pPab; - unsigned char debug_msg[20]; - - - if (pPab == NULL) - return; - - phyAddrMsg = pPab->p_atu->OutQueue; - - while (phyAddrMsg != 0xFFFFFFFF) - { - p8Msg = pPab->pLinOutMsgBlock + (phyAddrMsg - pPab->outMsgBlockPhyAddr); - p32 = (PU32)p8Msg; - - dprintk("msg: 0x%x 0x%x \n", p8Msg[7], p32[5]); - - /* Send Packet Reply Msg */ - if (I2O_LAN_PACKET_SEND == p8Msg[7]) { /* function code byte */ - count = *(PU16)(p8Msg+2); - count -= p8Msg[0] >> 4; - /* status, count, context[], adapter */ - (*pPab->pTransCallbackFunc)(p8Msg[19], count, p32+5, dev); - } else if (I2O_LAN_RECEIVE_POST == p8Msg[7]) { /* Receive Packet Reply Msg */ - dprintk("I2O_RECV_REPLY pPab:0x%08ulx p8Msg:0x%08ulx p32:0x%08ulx\n", (u32)pPab, (u32)p8Msg, (u32)p32); - dprintk("msg: 0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", - p32[0], p32[1], p32[2], p32[3]); - dprintk(" 0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", - p32[4], p32[5], p32[6], p32[7]); - dprintk(" 0x%08ulx:0X%08ulx:0x%08ulx:0x%08ulx\n", - p32[8], p32[9], p32[10], p32[11]); - /* status, count, buckets remaining, packetParmBlock, adapter */ - (*pPab->pRecvCallbackFunc)(p8Msg[19], p8Msg[12], p32[5], p32+6, dev); - } else if (I2O_LAN_RESET == p8Msg[7] || I2O_LAN_SHUTDOWN == p8Msg[7]) - if (pPab->pCallbackFunc) - (*pPab->pCallbackFunc)(p8Msg[19],0,0,dev); - else - pPab->pCallbackFunc = (PFNCALLBACK) 1; - else if (I2O_PRIVATE == p8Msg[7]) { - dprintk("i2o private 0x%x, 0x%x \n", p8Msg[7], p32[5]); - switch (p32[5]) - { - case RC_PRIVATE_DEBUG_MSG: - msgFlag = 1; - dprintk("Received I2O_PRIVATE msg\n"); - debug_msg[15] = (p32[6]&0xff000000) >> 24; - debug_msg[14] = (p32[6]&0x00ff0000) >> 16; - debug_msg[13] = (p32[6]&0x0000ff00) >> 8; - debug_msg[12] = (p32[6]&0x000000ff); - - debug_msg[11] = (p32[7]&0xff000000) >> 24; - debug_msg[10] = (p32[7]&0x00ff0000) >> 16; - debug_msg[ 9] = (p32[7]&0x0000ff00) >> 8; - debug_msg[ 8] = (p32[7]&0x000000ff); - - debug_msg[ 7] = (p32[8]&0xff000000) >> 24; - debug_msg[ 6] = (p32[8]&0x00ff0000) >> 16; - debug_msg[ 5] = (p32[8]&0x0000ff00) >> 8; - debug_msg[ 4] = (p32[8]&0x000000ff); - - debug_msg[ 3] = (p32[9]&0xff000000) >> 24; - debug_msg[ 2] = (p32[9]&0x00ff0000) >> 16; - debug_msg[ 1] = (p32[9]&0x0000ff00) >> 8; - debug_msg[ 0] = (p32[9]&0x000000ff); - - debug_msg[16] = '\0'; - dprintk("%s", debug_msg); - break; - case RC_PRIVATE_REBOOT: - dprintk("Adapter reboot initiated...\n"); - if (pPab->pRebootCallbackFunc) - (*pPab->pRebootCallbackFunc)(0,0,0,dev); - break; - default: - printk(KERN_WARNING "(rcpci45 driver:) Unknown private I2O msg received: 0x%x\n", p32[5]); - break; - } - } - - /* - ** Process other Msg's - */ - else - ProcessOutboundI2OMsg(pPab, phyAddrMsg); - - /* return MFA to outbound free Q*/ - pPab->p_atu->OutQueue = phyAddrMsg; - - /* any more msgs? */ - phyAddrMsg = pPab->p_atu->OutQueue; - } + U32 phyAddrMsg; + PU8 p8Msg; + PU32 p32; + U16 count; + PPAB pPab = ((PDPA) dev->priv)->pPab; + unsigned char debug_msg[20]; + + if (pPab == NULL) + return; + + phyAddrMsg = pPab->p_atu->OutQueue; + + while (phyAddrMsg != 0xFFFFFFFF) { + p8Msg = + pPab->pLinOutMsgBlock + (phyAddrMsg - + pPab->outMsgBlockPhyAddr); + p32 = (PU32) p8Msg; + + dprintk ("msg: 0x%x 0x%x \n", p8Msg[7], p32[5]); + + /* Send Packet Reply Msg */ + if (I2O_LAN_PACKET_SEND == p8Msg[7]) { /* function code byte */ + count = *(PU16) (p8Msg + 2); + count -= p8Msg[0] >> 4; + /* status, count, context[], adapter */ + (*pPab->pTransCallbackFunc) (p8Msg[19], count, p32 + 5, + dev); + } else if (I2O_LAN_RECEIVE_POST == p8Msg[7]) { /* Receive Packet Reply Msg */ + dprintk + ("I2O_RECV_REPLY pPab:0x%08ulx p8Msg:0x%08ulx p32:0x%08ulx\n", + (u32) pPab, (u32) p8Msg, (u32) p32); + dprintk ("msg: 0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", + p32[0], p32[1], p32[2], p32[3]); + dprintk (" 0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", + p32[4], p32[5], p32[6], p32[7]); + dprintk (" 0x%08ulx:0X%08ulx:0x%08ulx:0x%08ulx\n", + p32[8], p32[9], p32[10], p32[11]); + /* status, count, buckets remaining, packetParmBlock, adapter */ + (*pPab->pRecvCallbackFunc) (p8Msg[19], p8Msg[12], + p32[5], p32 + 6, dev); + } else if (I2O_LAN_RESET == p8Msg[7] + || I2O_LAN_SHUTDOWN == p8Msg[7]) + if (pPab->pCallbackFunc) + (*pPab->pCallbackFunc) (p8Msg[19], 0, 0, dev); + else + pPab->pCallbackFunc = (PFNCALLBACK) 1; + else if (I2O_PRIVATE == p8Msg[7]) { + dprintk ("i2o private 0x%x, 0x%x \n", p8Msg[7], p32[5]); + switch (p32[5]) { + case RC_PRIVATE_DEBUG_MSG: + msgFlag = 1; + dprintk ("Received I2O_PRIVATE msg\n"); + debug_msg[15] = (p32[6] & 0xff000000) >> 24; + debug_msg[14] = (p32[6] & 0x00ff0000) >> 16; + debug_msg[13] = (p32[6] & 0x0000ff00) >> 8; + debug_msg[12] = (p32[6] & 0x000000ff); + + debug_msg[11] = (p32[7] & 0xff000000) >> 24; + debug_msg[10] = (p32[7] & 0x00ff0000) >> 16; + debug_msg[9] = (p32[7] & 0x0000ff00) >> 8; + debug_msg[8] = (p32[7] & 0x000000ff); + + debug_msg[7] = (p32[8] & 0xff000000) >> 24; + debug_msg[6] = (p32[8] & 0x00ff0000) >> 16; + debug_msg[5] = (p32[8] & 0x0000ff00) >> 8; + debug_msg[4] = (p32[8] & 0x000000ff); + + debug_msg[3] = (p32[9] & 0xff000000) >> 24; + debug_msg[2] = (p32[9] & 0x00ff0000) >> 16; + debug_msg[1] = (p32[9] & 0x0000ff00) >> 8; + debug_msg[0] = (p32[9] & 0x000000ff); + + debug_msg[16] = '\0'; + dprintk ("%s", debug_msg); + break; + case RC_PRIVATE_REBOOT: + dprintk ("Adapter reboot initiated...\n"); + if (pPab->pRebootCallbackFunc) + (*pPab->pRebootCallbackFunc) (0, 0, 0, + dev); + break; + default: + printk (KERN_WARNING + "(rcpci45 driver:) Unknown private I2O msg received: 0x%x\n", + p32[5]); + break; + } + } + + /* + ** Process other Msg's + */ + else + ProcessOutboundI2OMsg (pPab, phyAddrMsg); + + /* return MFA to outbound free Q */ + pPab->p_atu->OutQueue = phyAddrMsg; + + /* any more msgs? */ + phyAddrMsg = pPab->p_atu->OutQueue; + } } - /* ** ========================================================================= ** Returns LAN interface statistical counters to space provided by caller at @@ -661,79 +653,75 @@ ** ========================================================================= */ RC_RETURN -RCGetLinkStatistics(struct net_device *dev, - P_RCLINKSTATS StatsReturnAddr, - PFNWAITCALLBACK WaitCallback) -{ - U32 msgOffset; - volatile U32 timeout; - volatile PU32 pMsg; - volatile PU32 p32, pReturnAddr; - P_NICSTAT pStats; - int i; - PPAB pPab = ((PDPA)dev->priv)->pPab; - +RCGetLinkStatistics (struct net_device *dev, + P_RCLINKSTATS StatsReturnAddr, + PFNWAITCALLBACK WaitCallback) +{ + U32 msgOffset; + volatile U32 timeout; + volatile PU32 pMsg; + volatile PU32 p32, pReturnAddr; + P_NICSTAT pStats; + int i; + PPAB pPab = ((PDPA) dev->priv)->pPab; /*dprintk("Get82558Stats() StatsReturnAddr:0x%08ulx\n", StatsReturnAddr); */ - if (pPab == NULL) - return RC_RTN_ADPTR_NOT_REGISTERED; - - msgOffset = pPab->p_atu->InQueue; - - if (msgOffset == 0xFFFFFFFF) - { - dprintk("Get8255XStats(): Inbound Free Q empty!\n"); - return RC_RTN_FREE_Q_EMPTY; - } + if (pPab == NULL) + return RC_RTN_ADPTR_NOT_REGISTERED; + + msgOffset = pPab->p_atu->InQueue; + + if (msgOffset == 0xFFFFFFFF) { + dprintk ("Get8255XStats(): Inbound Free Q empty!\n"); + return RC_RTN_FREE_Q_EMPTY; + } - /* calc virual address of msg - virual already mapped to physical */ - pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset); + /* calc virual address of msg - virual already mapped to physical */ + pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset); /*dprintk("Get82558Stats - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", pMsg, msgOffset);*/ /*dprintk("Get82558Stats - pMsg = 0x%08X, InQ msgOffset = 0x%08X\n", pMsg, msgOffset);*/ - pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0; - pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; - pMsg[2] = DEFAULT_RECV_INIT_CONTEXT; - pMsg[3] = 0x112; /* transaction context */ - pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_NIC_STATS; - pMsg[5] = pPab->outMsgBlockPhyAddr; - - p32 = (PU32) pPab->outMsgBlockPhyAddr; - pStats = (P_NICSTAT)pPab->pLinOutMsgBlock; - pStats->dump_status = 0xFFFFFFFF; - - /* post to Inbound Post Q */ - pPab->p_atu->InQueue = msgOffset; - - timeout = 100000; - while (1) - { - if (WaitCallback) - (*WaitCallback)(); - - udelay(10); - - if (pStats->dump_status != 0xFFFFFFFF) - break; - - if (!timeout--) - { - dprintk("RCGet82558Stats() Timeout waiting for NIC statistics\n"); - return RC_RTN_MSG_REPLY_TIMEOUT; - } - } - - pReturnAddr = (PU32)StatsReturnAddr; - - /* copy Nic stats to user's structure */ - for (i = 0; i < (int) sizeof(RCLINKSTATS) / 4; i++) - pReturnAddr[i] = p32[i]; - - return RC_RTN_NO_ERROR; -} + pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0; + pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; + pMsg[2] = DEFAULT_RECV_INIT_CONTEXT; + pMsg[3] = 0x112; /* transaction context */ + pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_NIC_STATS; + pMsg[5] = pPab->outMsgBlockPhyAddr; + + p32 = (PU32) pPab->outMsgBlockPhyAddr; + pStats = (P_NICSTAT) pPab->pLinOutMsgBlock; + pStats->dump_status = 0xFFFFFFFF; + + /* post to Inbound Post Q */ + pPab->p_atu->InQueue = msgOffset; + + timeout = 100000; + while (1) { + if (WaitCallback) + (*WaitCallback) (); + + udelay (10); + + if (pStats->dump_status != 0xFFFFFFFF) + break; + + if (!timeout--) { + dprintk + ("RCGet82558Stats() Timeout waiting for NIC statistics\n"); + return RC_RTN_MSG_REPLY_TIMEOUT; + } + } + + pReturnAddr = (PU32) StatsReturnAddr; + + /* copy Nic stats to user's structure */ + for (i = 0; i < (int) sizeof (RCLINKSTATS) / 4; i++) + pReturnAddr[i] = p32[i]; + return RC_RTN_NO_ERROR; +} /* ** ========================================================================= @@ -741,67 +729,66 @@ ** ========================================================================= */ RC_RETURN -RCGetLinkStatus(struct net_device *dev, PU32 ReturnAddr, - PFNWAITCALLBACK WaitCallback) +RCGetLinkStatus (struct net_device * dev, PU32 ReturnAddr, + PFNWAITCALLBACK WaitCallback) { - U32 msgOffset; - volatile U32 timeout; - volatile PU32 pMsg; - volatile PU32 p32; - PPAB pPab = ((PDPA)dev->priv)->pPab; - - - dprintk("Get82558LinkStatus() ReturnPhysAddr:0x%08ulx\n", (u32)ReturnAddr); - - if (pPab == NULL) - return RC_RTN_ADPTR_NOT_REGISTERED; - - msgOffset = pPab->p_atu->InQueue; - - if (msgOffset == 0xFFFFFFFF) - { - dprintk("Get82558LinkStatus(): Inbound Free Q empty!\n"); - return RC_RTN_FREE_Q_EMPTY; - } + U32 msgOffset; + volatile U32 timeout; + volatile PU32 pMsg; + volatile PU32 p32; + PPAB pPab = ((PDPA) dev->priv)->pPab; + + dprintk ("Get82558LinkStatus() ReturnPhysAddr:0x%08ulx\n", + (u32) ReturnAddr); + + if (pPab == NULL) + return RC_RTN_ADPTR_NOT_REGISTERED; + + msgOffset = pPab->p_atu->InQueue; + + if (msgOffset == 0xFFFFFFFF) { + dprintk ("Get82558LinkStatus(): Inbound Free Q empty!\n"); + return RC_RTN_FREE_Q_EMPTY; + } - /* calc virual address of msg - virual already mapped to physical */ - pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset); + /* calc virual address of msg - virual already mapped to physical */ + pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset); /*dprintk("Get82558LinkStatus - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", pMsg, msgOffset);*/ /*dprintk("Get82558LinkStatus - pMsg = 0x%08X, InQ msgOffset = 0x%08X\n", pMsg, msgOffset);*/ - pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0; - pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; - pMsg[2] = DEFAULT_RECV_INIT_CONTEXT; - pMsg[3] = 0x112; /* transaction context */ - pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_LINK_STATUS; - pMsg[5] = pPab->outMsgBlockPhyAddr; - - p32 = (PU32)pPab->pLinOutMsgBlock; - *p32 = 0xFFFFFFFF; - - /* post to Inbound Post Q */ - pPab->p_atu->InQueue = msgOffset; - - timeout = 100000; - while (1) { - if (WaitCallback) - (*WaitCallback)(); - - udelay(10); - - if (*p32 != 0xFFFFFFFF) - break; - - if (!timeout--) { - dprintk("Timeout waiting for link status\n"); - return RC_RTN_MSG_REPLY_TIMEOUT; - } - } - - *ReturnAddr = *p32; /* 1 = up 0 = down */ - - return RC_RTN_NO_ERROR; - + pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0; + pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; + pMsg[2] = DEFAULT_RECV_INIT_CONTEXT; + pMsg[3] = 0x112; /* transaction context */ + pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_LINK_STATUS; + pMsg[5] = pPab->outMsgBlockPhyAddr; + + p32 = (PU32) pPab->pLinOutMsgBlock; + *p32 = 0xFFFFFFFF; + + /* post to Inbound Post Q */ + pPab->p_atu->InQueue = msgOffset; + + timeout = 100000; + while (1) { + if (WaitCallback) + (*WaitCallback) (); + + udelay (10); + + if (*p32 != 0xFFFFFFFF) + break; + + if (!timeout--) { + dprintk ("Timeout waiting for link status\n"); + return RC_RTN_MSG_REPLY_TIMEOUT; + } + } + + *ReturnAddr = *p32; /* 1 = up 0 = down */ + + return RC_RTN_NO_ERROR; + } /* @@ -813,73 +800,68 @@ ** ========================================================================= */ RC_RETURN -RCGetMAC(struct net_device *dev, PFNWAITCALLBACK WaitCallback) +RCGetMAC (struct net_device * dev, PFNWAITCALLBACK WaitCallback) { - unsigned timeout; - U32 off; - PU8 mac = dev->dev_addr; - PU32 p; - U32 temp[2]; - PPAB pPab = ((PDPA)dev->priv)->pPab; - PATU p_atu; - - if (pPab == NULL) - return RC_RTN_ADPTR_NOT_REGISTERED; - - p_atu = pPab->p_atu; - - p_atu->EtherMacLow = 0; /* first zero return data */ - p_atu->EtherMacHi = 0; - - off = p_atu->InQueue; /* get addresss of message */ - - if (0xFFFFFFFF == off) - return RC_RTN_FREE_Q_EMPTY; - - p = (PU32)(pPab->pPci45LinBaseAddr + off); - - dprintk("RCGetMAC: p_atu 0x%08x, off 0x%08x, p 0x%08x\n", - (uint)p_atu, (uint)off, (uint)p); - /* setup private message */ - p[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0; - p[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; - p[2] = 0; /* initiator context */ - p[3] = 0x218; /* transaction context */ - p[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_MAC_ADDR; - - - p_atu->InQueue = off; /* send it to the I2O device */ - dprintk("RCGetMAC: p_atu 0x%08x, off 0x%08x, p 0x%08x\n", - (uint)p_atu, (uint)off, (uint)p); - - /* wait for the rcpci45 board to update the info */ - timeout = 1000000; - while (0 == p_atu->EtherMacLow) - { - if (WaitCallback) - (*WaitCallback)(); - - udelay(10); - - if (!timeout--) - { - printk("rc_getmac: Timeout\n"); - return RC_RTN_MSG_REPLY_TIMEOUT; - } - } - - /* read the mac address */ - temp[0] = p_atu->EtherMacLow; - temp[1] = p_atu->EtherMacHi; - memcpy((char *)mac, (char *)temp, 6); + unsigned timeout; + U32 off; + PU8 mac = dev->dev_addr; + PU32 p; + U32 temp[2]; + PPAB pPab = ((PDPA) dev->priv)->pPab; + PATU p_atu; + + if (pPab == NULL) + return RC_RTN_ADPTR_NOT_REGISTERED; + + p_atu = pPab->p_atu; + + p_atu->EtherMacLow = 0; /* first zero return data */ + p_atu->EtherMacHi = 0; + + off = p_atu->InQueue; /* get addresss of message */ + + if (0xFFFFFFFF == off) + return RC_RTN_FREE_Q_EMPTY; + + p = (PU32) (pPab->pPci45LinBaseAddr + off); + + dprintk ("RCGetMAC: p_atu 0x%08x, off 0x%08x, p 0x%08x\n", + (uint) p_atu, (uint) off, (uint) p); + /* setup private message */ + p[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0; + p[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; + p[2] = 0; /* initiator context */ + p[3] = 0x218; /* transaction context */ + p[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_MAC_ADDR; + + p_atu->InQueue = off; /* send it to the I2O device */ + dprintk ("RCGetMAC: p_atu 0x%08x, off 0x%08x, p 0x%08x\n", + (uint) p_atu, (uint) off, (uint) p); + + /* wait for the rcpci45 board to update the info */ + timeout = 1000000; + while (0 == p_atu->EtherMacLow) { + if (WaitCallback) + (*WaitCallback) (); + + udelay (10); + + if (!timeout--) { + printk ("rc_getmac: Timeout\n"); + return RC_RTN_MSG_REPLY_TIMEOUT; + } + } + + /* read the mac address */ + temp[0] = p_atu->EtherMacLow; + temp[1] = p_atu->EtherMacHi; + memcpy ((char *) mac, (char *) temp, 6); + dprintk ("rc_getmac: 0x%x\n", (u32) mac); - dprintk("rc_getmac: 0x%x\n", (u32)mac); - - return RC_RTN_NO_ERROR; + return RC_RTN_NO_ERROR; } - /* ** ========================================================================= ** RCSetMAC() @@ -889,37 +871,35 @@ ** ========================================================================= */ RC_RETURN -RCSetMAC(struct net_device *dev, PU8 mac) +RCSetMAC (struct net_device * dev, PU8 mac) { - U32 off; - PU32 pMsg; - PPAB pPab = ((PDPA)dev->priv)->pPab; - - - if (pPab == NULL) - return RC_RTN_ADPTR_NOT_REGISTERED; - - off = pPab->p_atu->InQueue; /* get addresss of message */ - - if (0xFFFFFFFF == off) - return RC_RTN_FREE_Q_EMPTY; - - pMsg = (PU32)(pPab->pPci45LinBaseAddr + off); - - /* setup private message */ - pMsg[0] = SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0; - pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; - pMsg[2] = 0; /* initiator context */ - pMsg[3] = 0x219; /* transaction context */ - pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_MAC_ADDR; - pMsg[5] = *(unsigned *)mac; /* first four bytes */ - pMsg[6] = *(unsigned *)(mac + 4); /* last two bytes */ - - pPab->p_atu->InQueue = off; /* send it to the I2O device */ + U32 off; + PU32 pMsg; + PPAB pPab = ((PDPA) dev->priv)->pPab; - return RC_RTN_NO_ERROR ; -} + if (pPab == NULL) + return RC_RTN_ADPTR_NOT_REGISTERED; + + off = pPab->p_atu->InQueue; /* get addresss of message */ + + if (0xFFFFFFFF == off) + return RC_RTN_FREE_Q_EMPTY; + + pMsg = (PU32) (pPab->pPci45LinBaseAddr + off); + + /* setup private message */ + pMsg[0] = SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0; + pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; + pMsg[2] = 0; /* initiator context */ + pMsg[3] = 0x219; /* transaction context */ + pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_MAC_ADDR; + pMsg[5] = *(unsigned *) mac; /* first four bytes */ + pMsg[6] = *(unsigned *) (mac + 4); /* last two bytes */ + pPab->p_atu->InQueue = off; /* send it to the I2O device */ + + return RC_RTN_NO_ERROR; +} /* ** ========================================================================= @@ -936,35 +916,35 @@ ** ========================================================================= */ RC_RETURN -RCSetLinkSpeed(struct net_device *dev, U16 LinkSpeedCode) +RCSetLinkSpeed (struct net_device * dev, U16 LinkSpeedCode) { - U32 off; - PU32 pMsg; - PPAB pPab = ((PDPA)dev->priv)->pPab; - - - if (pPab == NULL) - return RC_RTN_ADPTR_NOT_REGISTERED; - - off = pPab->p_atu->InQueue; /* get addresss of message */ - - if (0xFFFFFFFF == off) - return RC_RTN_FREE_Q_EMPTY; - - pMsg = (PU32)(pPab->pPci45LinBaseAddr + off); - - /* setup private message */ - pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0; - pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; - pMsg[2] = 0; /* initiator context */ - pMsg[3] = 0x219; /* transaction context */ - pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_LINK_SPEED; - pMsg[5] = LinkSpeedCode; /* link speed code */ + U32 off; + PU32 pMsg; + PPAB pPab = ((PDPA) dev->priv)->pPab; + + if (pPab == NULL) + return RC_RTN_ADPTR_NOT_REGISTERED; + + off = pPab->p_atu->InQueue; /* get addresss of message */ + + if (0xFFFFFFFF == off) + return RC_RTN_FREE_Q_EMPTY; + + pMsg = (PU32) (pPab->pPci45LinBaseAddr + off); + + /* setup private message */ + pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0; + pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; + pMsg[2] = 0; /* initiator context */ + pMsg[3] = 0x219; /* transaction context */ + pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_LINK_SPEED; + pMsg[5] = LinkSpeedCode; /* link speed code */ - pPab->p_atu->InQueue = off; /* send it to the I2O device */ + pPab->p_atu->InQueue = off; /* send it to the I2O device */ - return RC_RTN_NO_ERROR ; + return RC_RTN_NO_ERROR; } + /* ** ========================================================================= ** RCSetPromiscuousMode() @@ -976,34 +956,35 @@ ** ========================================================================= */ RC_RETURN -RCSetPromiscuousMode(struct net_device *dev, U16 Mode) +RCSetPromiscuousMode (struct net_device * dev, U16 Mode) { - U32 off; - PU32 pMsg; - PPAB pPab = ((PDPA)dev->priv)->pPab; - - if (pPab == NULL) - return RC_RTN_ADPTR_NOT_REGISTERED; - - off = pPab->p_atu->InQueue; /* get addresss of message */ - - if (0xFFFFFFFF == off) - return RC_RTN_FREE_Q_EMPTY; - - pMsg = (PU32)(pPab->pPci45LinBaseAddr + off); - - /* setup private message */ - pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0; - pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; - pMsg[2] = 0; /* initiator context */ - pMsg[3] = 0x219; /* transaction context */ - pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_PROMISCUOUS_MODE; - pMsg[5] = Mode; /* promiscuous mode setting */ + U32 off; + PU32 pMsg; + PPAB pPab = ((PDPA) dev->priv)->pPab; + + if (pPab == NULL) + return RC_RTN_ADPTR_NOT_REGISTERED; + + off = pPab->p_atu->InQueue; /* get addresss of message */ + + if (0xFFFFFFFF == off) + return RC_RTN_FREE_Q_EMPTY; + + pMsg = (PU32) (pPab->pPci45LinBaseAddr + off); + + /* setup private message */ + pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0; + pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; + pMsg[2] = 0; /* initiator context */ + pMsg[3] = 0x219; /* transaction context */ + pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_PROMISCUOUS_MODE; + pMsg[5] = Mode; /* promiscuous mode setting */ - pPab->p_atu->InQueue = off; /* send it to the device */ + pPab->p_atu->InQueue = off; /* send it to the device */ - return RC_RTN_NO_ERROR ; + return RC_RTN_NO_ERROR; } + /* ** ========================================================================= ** RCGetPromiscuousMode() @@ -1017,67 +998,67 @@ ** ========================================================================= */ RC_RETURN -RCGetPromiscuousMode(struct net_device *dev, PU32 pMode, - PFNWAITCALLBACK WaitCallback) +RCGetPromiscuousMode (struct net_device * dev, PU32 pMode, + PFNWAITCALLBACK WaitCallback) { - U32 msgOffset, timeout; - PU32 pMsg; - volatile PU32 p32; - PPAB pPab = ((PDPA)dev->priv)->pPab; - - - msgOffset = pPab->p_atu->InQueue; - - if (msgOffset == 0xFFFFFFFF) - { - printk(KERN_WARNING "(rcpci45 driver:) RCGetLinkSpeed(): Inbound Free Q empty!\n"); - return RC_RTN_FREE_Q_EMPTY; - } - - /* calc virtual address of msg - virtual already mapped to physical */ - pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset); - - /* virtual pointer to return buffer - clear first two dwords */ - p32 = (volatile PU32)pPab->pLinOutMsgBlock; - p32[0] = 0xff; - - /* setup private message */ - pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0; - pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; - pMsg[2] = 0; /* initiator context */ - pMsg[3] = 0x219; /* transaction context */ - pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_PROMISCUOUS_MODE; - /* phys address to return status - area right after PAB */ - pMsg[5] = pPab->outMsgBlockPhyAddr; - - /* post to Inbound Post Q */ - - pPab->p_atu->InQueue = msgOffset; - - /* wait for response */ - timeout = 1000000; - while(1) { - if (WaitCallback) - (*WaitCallback)(); - - udelay(10); /* please don't hog the bus!!! */ - - if (p32[0] != 0xff) - break; - - if (!timeout--) - { - dprintk("Timeout waiting for promiscuous mode from adapter\n"); - dprintk("0x%8x\n", p32[0]); - return RC_RTN_NO_LINK_SPEED; - } - } + U32 msgOffset, timeout; + PU32 pMsg; + volatile PU32 p32; + PPAB pPab = ((PDPA) dev->priv)->pPab; + + msgOffset = pPab->p_atu->InQueue; + + if (msgOffset == 0xFFFFFFFF) { + printk (KERN_WARNING + "(rcpci45 driver:) RCGetLinkSpeed(): Inbound Free Q empty!\n"); + return RC_RTN_FREE_Q_EMPTY; + } + + /* calc virtual address of msg - virtual already mapped to physical */ + pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset); + + /* virtual pointer to return buffer - clear first two dwords */ + p32 = (volatile PU32) pPab->pLinOutMsgBlock; + p32[0] = 0xff; + + /* setup private message */ + pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0; + pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; + pMsg[2] = 0; /* initiator context */ + pMsg[3] = 0x219; /* transaction context */ + pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_PROMISCUOUS_MODE; + /* phys address to return status - area right after PAB */ + pMsg[5] = pPab->outMsgBlockPhyAddr; + + /* post to Inbound Post Q */ + + pPab->p_atu->InQueue = msgOffset; + + /* wait for response */ + timeout = 1000000; + while (1) { + if (WaitCallback) + (*WaitCallback) (); + + udelay (10); /* please don't hog the bus!!! */ + + if (p32[0] != 0xff) + break; + + if (!timeout--) { + dprintk + ("Timeout waiting for promiscuous mode from adapter\n"); + dprintk ("0x%8x\n", p32[0]); + return RC_RTN_NO_LINK_SPEED; + } + } - /* get mode */ - *pMode = (U8)((volatile PU8)p32)[0] & 0x0f; + /* get mode */ + *pMode = (U8) ((volatile PU8) p32)[0] & 0x0f; - return RC_RTN_NO_ERROR; + return RC_RTN_NO_ERROR; } + /* ** ========================================================================= ** RCSetBroadcastMode() @@ -1089,35 +1070,35 @@ ** ========================================================================= */ RC_RETURN -RCSetBroadcastMode(struct net_device *dev, U16 Mode) +RCSetBroadcastMode (struct net_device * dev, U16 Mode) { - U32 off; - PU32 pMsg; - PPAB pPab = ((PDPA)dev->priv)->pPab; - - - if (pPab == NULL) - return RC_RTN_ADPTR_NOT_REGISTERED; - - off = pPab->p_atu->InQueue; /* get addresss of message */ - - if (0xFFFFFFFF == off) - return RC_RTN_FREE_Q_EMPTY; - - pMsg = (PU32)(pPab->pPci45LinBaseAddr + off); - - /* setup private message */ - pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0; - pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; - pMsg[2] = 0; /* initiator context */ - pMsg[3] = 0x219; /* transaction context */ - pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_BROADCAST_MODE; - pMsg[5] = Mode; /* promiscuous mode setting */ + U32 off; + PU32 pMsg; + PPAB pPab = ((PDPA) dev->priv)->pPab; + + if (pPab == NULL) + return RC_RTN_ADPTR_NOT_REGISTERED; + + off = pPab->p_atu->InQueue; /* get addresss of message */ + + if (0xFFFFFFFF == off) + return RC_RTN_FREE_Q_EMPTY; + + pMsg = (PU32) (pPab->pPci45LinBaseAddr + off); - pPab->p_atu->InQueue = off; /* send it to the device */ + /* setup private message */ + pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0; + pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; + pMsg[2] = 0; /* initiator context */ + pMsg[3] = 0x219; /* transaction context */ + pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_BROADCAST_MODE; + pMsg[5] = Mode; /* promiscuous mode setting */ - return RC_RTN_NO_ERROR ; + pPab->p_atu->InQueue = off; /* send it to the device */ + + return RC_RTN_NO_ERROR; } + /* ** ========================================================================= ** RCGetBroadcastMode() @@ -1131,66 +1112,66 @@ ** ========================================================================= */ RC_RETURN -RCGetBroadcastMode(struct net_device *dev, PU32 pMode, - PFNWAITCALLBACK WaitCallback) +RCGetBroadcastMode (struct net_device * dev, PU32 pMode, + PFNWAITCALLBACK WaitCallback) { - U32 msgOffset, timeout; - PU32 pMsg; - volatile PU32 p32; - PPAB pPab = ((PDPA)dev->priv)->pPab; - - - msgOffset = pPab->p_atu->InQueue; - - if (msgOffset == 0xFFFFFFFF) - { - printk(KERN_WARNING "(rcpci45 driver:) RCGetLinkSpeed(): Inbound Free Q empty!\n"); - return RC_RTN_FREE_Q_EMPTY; - } - - /* calc virtual address of msg - virtual already mapped to physical */ - pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset); - - /* virtual pointer to return buffer - clear first two dwords */ - p32 = (volatile PU32)pPab->pLinOutMsgBlock; - p32[0] = 0xff; - - /* setup private message */ - pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0; - pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; - pMsg[2] = 0; /* initiator context */ - pMsg[3] = 0x219; /* transaction context */ - pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_BROADCAST_MODE; - /* phys address to return status - area right after PAB */ - pMsg[5] = pPab->outMsgBlockPhyAddr; - - /* post to Inbound Post Q */ - - pPab->p_atu->InQueue = msgOffset; - - /* wait for response */ - timeout = 1000000; - while(1) { - if (WaitCallback) - (*WaitCallback)(); - - udelay(10); /* please don't hog the bus!!! */ - - if (p32[0] != 0xff) - break; - - if (!timeout--) - { - printk(KERN_WARNING "(rcpci45 driver:) Timeout waiting for promiscuous mode from adapter\n"); - printk(KERN_WARNING "(rcpci45 driver:) 0x%8x\n", p32[0]); - return RC_RTN_NO_LINK_SPEED; - } - } + U32 msgOffset, timeout; + PU32 pMsg; + volatile PU32 p32; + PPAB pPab = ((PDPA) dev->priv)->pPab; + + msgOffset = pPab->p_atu->InQueue; + + if (msgOffset == 0xFFFFFFFF) { + printk (KERN_WARNING + "(rcpci45 driver:) RCGetLinkSpeed(): Inbound Free Q empty!\n"); + return RC_RTN_FREE_Q_EMPTY; + } + + /* calc virtual address of msg - virtual already mapped to physical */ + pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset); + + /* virtual pointer to return buffer - clear first two dwords */ + p32 = (volatile PU32) pPab->pLinOutMsgBlock; + p32[0] = 0xff; + + /* setup private message */ + pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0; + pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; + pMsg[2] = 0; /* initiator context */ + pMsg[3] = 0x219; /* transaction context */ + pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_BROADCAST_MODE; + /* phys address to return status - area right after PAB */ + pMsg[5] = pPab->outMsgBlockPhyAddr; + + /* post to Inbound Post Q */ + + pPab->p_atu->InQueue = msgOffset; + + /* wait for response */ + timeout = 1000000; + while (1) { + if (WaitCallback) + (*WaitCallback) (); + + udelay (10); /* please don't hog the bus!!! */ + + if (p32[0] != 0xff) + break; + + if (!timeout--) { + printk (KERN_WARNING + "(rcpci45 driver:) Timeout waiting for promiscuous mode from adapter\n"); + printk (KERN_WARNING "(rcpci45 driver:) 0x%8x\n", + p32[0]); + return RC_RTN_NO_LINK_SPEED; + } + } - /* get mode */ - *pMode = (U8)((volatile PU8)p32)[0] & 0x0f; + /* get mode */ + *pMode = (U8) ((volatile PU8) p32)[0] & 0x0f; - return RC_RTN_NO_ERROR; + return RC_RTN_NO_ERROR; } /* @@ -1208,69 +1189,67 @@ ** ========================================================================= */ RC_RETURN -RCGetLinkSpeed(struct net_device *dev, PU32 pLinkSpeedCode, - PFNWAITCALLBACK WaitCallback) +RCGetLinkSpeed (struct net_device * dev, PU32 pLinkSpeedCode, + PFNWAITCALLBACK WaitCallback) { - U32 msgOffset, timeout; - PU32 pMsg; - volatile PU32 p32; - U8 IOPLinkSpeed; - PPAB pPab = ((PDPA)dev->priv)->pPab; - - - msgOffset = pPab->p_atu->InQueue; - - if (msgOffset == 0xFFFFFFFF) - { - printk(KERN_WARNING "(rcpci45 driver:) RCGetLinkSpeed(): Inbound Free Q empty!\n"); - return RC_RTN_FREE_Q_EMPTY; - } - - /* calc virtual address of msg - virtual already mapped to physical */ - pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset); - - /* virtual pointer to return buffer - clear first two dwords */ - p32 = (volatile PU32)pPab->pLinOutMsgBlock; - p32[0] = 0xff; - - /* setup private message */ - pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0; - pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; - pMsg[2] = 0; /* initiator context */ - pMsg[3] = 0x219; /* transaction context */ - pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_LINK_SPEED; - /* phys address to return status - area right after PAB */ - pMsg[5] = pPab->outMsgBlockPhyAddr; - - /* post to Inbound Post Q */ - - pPab->p_atu->InQueue = msgOffset; - - /* wait for response */ - timeout = 1000000; - while(1) { - if (WaitCallback) - (*WaitCallback)(); - - udelay(10); /* please don't hog the bus!!! */ - - if (p32[0] != 0xff) - break; - - if (!timeout--) - { - dprintk("Timeout waiting for link speed from IOP\n"); - dprintk("0x%8x\n", p32[0]); - return RC_RTN_NO_LINK_SPEED; - } - } + U32 msgOffset, timeout; + PU32 pMsg; + volatile PU32 p32; + U8 IOPLinkSpeed; + PPAB pPab = ((PDPA) dev->priv)->pPab; + + msgOffset = pPab->p_atu->InQueue; + + if (msgOffset == 0xFFFFFFFF) { + printk (KERN_WARNING + "(rcpci45 driver:) RCGetLinkSpeed(): Inbound Free Q empty!\n"); + return RC_RTN_FREE_Q_EMPTY; + } + + /* calc virtual address of msg - virtual already mapped to physical */ + pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset); + + /* virtual pointer to return buffer - clear first two dwords */ + p32 = (volatile PU32) pPab->pLinOutMsgBlock; + p32[0] = 0xff; + + /* setup private message */ + pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0; + pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; + pMsg[2] = 0; /* initiator context */ + pMsg[3] = 0x219; /* transaction context */ + pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_LINK_SPEED; + /* phys address to return status - area right after PAB */ + pMsg[5] = pPab->outMsgBlockPhyAddr; + + /* post to Inbound Post Q */ + + pPab->p_atu->InQueue = msgOffset; + + /* wait for response */ + timeout = 1000000; + while (1) { + if (WaitCallback) + (*WaitCallback) (); + + udelay (10); /* please don't hog the bus!!! */ + + if (p32[0] != 0xff) + break; + + if (!timeout--) { + dprintk ("Timeout waiting for link speed from IOP\n"); + dprintk ("0x%8x\n", p32[0]); + return RC_RTN_NO_LINK_SPEED; + } + } - /* get Link speed */ - IOPLinkSpeed = (U8)((volatile PU8)p32)[0] & 0x0f; + /* get Link speed */ + IOPLinkSpeed = (U8) ((volatile PU8) p32)[0] & 0x0f; - *pLinkSpeedCode= IOPLinkSpeed; + *pLinkSpeedCode = IOPLinkSpeed; - return RC_RTN_NO_ERROR; + return RC_RTN_NO_ERROR; } /* @@ -1283,33 +1262,34 @@ ** ========================================================================= */ RC_RETURN -RCReportDriverCapability(struct net_device *dev, U32 capability) +RCReportDriverCapability (struct net_device * dev, U32 capability) { - U32 off; - PU32 pMsg; - PPAB pPab = ((PDPA)dev->priv)->pPab; - - if (pPab == NULL) - return RC_RTN_ADPTR_NOT_REGISTERED; - - off = pPab->p_atu->InQueue; /* get addresss of message */ - - if (0xFFFFFFFF == off) - return RC_RTN_FREE_Q_EMPTY; - - pMsg = (PU32)(pPab->pPci45LinBaseAddr + off); - - /* setup private message */ - pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0; - pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; - pMsg[2] = 0; /* initiator context */ - pMsg[3] = 0x219; /* transaction context */ - pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_REPORT_DRIVER_CAPABILITY; - pMsg[5] = capability; + U32 off; + PU32 pMsg; + PPAB pPab = ((PDPA) dev->priv)->pPab; + + if (pPab == NULL) + return RC_RTN_ADPTR_NOT_REGISTERED; + + off = pPab->p_atu->InQueue; /* get addresss of message */ + + if (0xFFFFFFFF == off) + return RC_RTN_FREE_Q_EMPTY; - pPab->p_atu->InQueue = off; /* send it to the I2O device */ + pMsg = (PU32) (pPab->pPci45LinBaseAddr + off); - return RC_RTN_NO_ERROR ; + /* setup private message */ + pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0; + pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; + pMsg[2] = 0; /* initiator context */ + pMsg[3] = 0x219; /* transaction context */ + pMsg[4] = + RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_REPORT_DRIVER_CAPABILITY; + pMsg[5] = capability; + + pPab->p_atu->InQueue = off; /* send it to the I2O device */ + + return RC_RTN_NO_ERROR; } /* @@ -1321,65 +1301,59 @@ ** ========================================================================= */ RC_RETURN -RCGetFirmwareVer(struct net_device *dev, PU8 pFirmString, - PFNWAITCALLBACK WaitCallback) +RCGetFirmwareVer (struct net_device * dev, PU8 pFirmString, + PFNWAITCALLBACK WaitCallback) { - U32 msgOffset, timeout; - PU32 pMsg; - volatile PU32 p32; - PPAB pPab = ((PDPA)dev->priv)->pPab; - - - msgOffset = pPab->p_atu->InQueue; - if (msgOffset == 0xFFFFFFFF) - { - dprintk("RCGetFirmwareVer(): Inbound Free Q empty!\n"); - return RC_RTN_FREE_Q_EMPTY; - } - - /* calc virtual address of msg - virtual already mapped to physical */ - pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset); - - /* virtual pointer to return buffer - clear first two dwords */ - p32 = (volatile PU32)pPab->pLinOutMsgBlock; - p32[0] = 0xff; - - /* setup private message */ - pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0; - pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; - pMsg[2] = 0; /* initiator context */ - pMsg[3] = 0x219; /* transaction context */ - pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_FIRMWARE_REV; - /* phys address to return status - area right after PAB */ - pMsg[5] = pPab->outMsgBlockPhyAddr; - - - - /* post to Inbound Post Q */ - - pPab->p_atu->InQueue = msgOffset; - - - /* wait for response */ - timeout = 1000000; - while(1) { - if (WaitCallback) - (*WaitCallback)(); - - udelay(10); /* please don't hog the bus!!! */ - - if (p32[0] != 0xff) - break; - - if (!timeout--) - { - dprintk("Timeout waiting for link speed from IOP\n"); - return RC_RTN_NO_FIRM_VER; - } - } + U32 msgOffset, timeout; + PU32 pMsg; + volatile PU32 p32; + PPAB pPab = ((PDPA) dev->priv)->pPab; + + msgOffset = pPab->p_atu->InQueue; + if (msgOffset == 0xFFFFFFFF) { + dprintk ("RCGetFirmwareVer(): Inbound Free Q empty!\n"); + return RC_RTN_FREE_Q_EMPTY; + } + + /* calc virtual address of msg - virtual already mapped to physical */ + pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset); + + /* virtual pointer to return buffer - clear first two dwords */ + p32 = (volatile PU32) pPab->pLinOutMsgBlock; + p32[0] = 0xff; + + /* setup private message */ + pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0; + pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; + pMsg[2] = 0; /* initiator context */ + pMsg[3] = 0x219; /* transaction context */ + pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_FIRMWARE_REV; + /* phys address to return status - area right after PAB */ + pMsg[5] = pPab->outMsgBlockPhyAddr; + + /* post to Inbound Post Q */ + + pPab->p_atu->InQueue = msgOffset; + + /* wait for response */ + timeout = 1000000; + while (1) { + if (WaitCallback) + (*WaitCallback) (); + + udelay (10); /* please don't hog the bus!!! */ + + if (p32[0] != 0xff) + break; + + if (!timeout--) { + dprintk ("Timeout waiting for link speed from IOP\n"); + return RC_RTN_NO_FIRM_VER; + } + } - strcpy(pFirmString, (PU8)p32); - return RC_RTN_NO_ERROR; + strcpy (pFirmString, (PU8) p32); + return RC_RTN_NO_ERROR; } /* @@ -1395,56 +1369,53 @@ ** ** ========================================================================= */ -RC_RETURN -RCResetLANCard(struct net_device *dev, U16 ResourceFlags, PU32 ReturnAddr, - PFNCALLBACK CallbackFunction) -{ - unsigned long off; - PU32 pMsg; - PPAB pPab = ((PDPA)dev->priv)->pPab; - long timeout = 0; - - - if (pPab == NULL) - return RC_RTN_ADPTR_NOT_REGISTERED; - - off = pPab->p_atu->InQueue; /* get addresss of message */ - - if (0xFFFFFFFF == off) - return RC_RTN_FREE_Q_EMPTY; - - pPab->pCallbackFunc = CallbackFunction; - - pMsg = (PU32)(pPab->pPci45LinBaseAddr + off); - - /* setup message */ - pMsg[0] = FOUR_WORD_MSG_SIZE | SGL_OFFSET_0; - pMsg[1] = I2O_LAN_RESET << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; - pMsg[2] = DEFAULT_RECV_INIT_CONTEXT; - pMsg[3] = ResourceFlags << 16; /* resource flags */ - - pPab->p_atu->InQueue = off; /* send it to the I2O device */ - - if (CallbackFunction == (PFNCALLBACK)NULL) - { - /* call RCProcI2OMsgQ() until something in pPab->pCallbackFunc - or until timer goes off */ - while (pPab->pCallbackFunc == (PFNCALLBACK)NULL) - { - RCProcI2OMsgQ(dev); - udelay(1000); /* please don't hog the bus!!! */ - timeout++; - if (timeout > 10000) - { - break; - } - } - if (ReturnAddr != (PU32)NULL) - *ReturnAddr = (U32)pPab->pCallbackFunc; - } +RC_RETURN +RCResetLANCard (struct net_device * dev, U16 ResourceFlags, PU32 ReturnAddr, + PFNCALLBACK CallbackFunction) +{ + unsigned long off; + PU32 pMsg; + PPAB pPab = ((PDPA) dev->priv)->pPab; + long timeout = 0; + + if (pPab == NULL) + return RC_RTN_ADPTR_NOT_REGISTERED; + + off = pPab->p_atu->InQueue; /* get addresss of message */ + + if (0xFFFFFFFF == off) + return RC_RTN_FREE_Q_EMPTY; + + pPab->pCallbackFunc = CallbackFunction; + + pMsg = (PU32) (pPab->pPci45LinBaseAddr + off); + + /* setup message */ + pMsg[0] = FOUR_WORD_MSG_SIZE | SGL_OFFSET_0; + pMsg[1] = I2O_LAN_RESET << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; + pMsg[2] = DEFAULT_RECV_INIT_CONTEXT; + pMsg[3] = ResourceFlags << 16; /* resource flags */ + + pPab->p_atu->InQueue = off; /* send it to the I2O device */ + + if (CallbackFunction == (PFNCALLBACK) NULL) { + /* call RCProcI2OMsgQ() until something in pPab->pCallbackFunc + or until timer goes off */ + while (pPab->pCallbackFunc == (PFNCALLBACK) NULL) { + RCProcI2OMsgQ (dev); + udelay (1000); /* please don't hog the bus!!! */ + timeout++; + if (timeout > 10000) { + break; + } + } + if (ReturnAddr != (PU32) NULL) + *ReturnAddr = (U32) pPab->pCallbackFunc; + } - return RC_RTN_NO_ERROR ; + return RC_RTN_NO_ERROR; } + /* ** ========================================================================= ** RCResetIOP() @@ -1453,59 +1424,57 @@ ** ** ========================================================================= */ -RC_RETURN -RCResetIOP(struct net_device *dev) +RC_RETURN +RCResetIOP (struct net_device * dev) { - U32 msgOffset, timeout; - PU32 pMsg; - PPAB pPab = ((PDPA)dev->priv)->pPab; - volatile PU32 p32; - - msgOffset = pPab->p_atu->InQueue; - - if (msgOffset == 0xFFFFFFFF) - { - return RC_RTN_FREE_Q_EMPTY; - } - - /* calc virtual address of msg - virtual already mapped to physical */ - pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset); - - pMsg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_0; - pMsg[1] = I2O_EXEC_IOP_RESET << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID; - pMsg[2] = 0; /* universal context */ - pMsg[3] = 0; /* universal context */ - pMsg[4] = 0; /* universal context */ - pMsg[5] = 0; /* universal context */ - /* phys address to return status - area right after PAB */ - pMsg[6] = pPab->outMsgBlockPhyAddr; - pMsg[7] = 0; - pMsg[8] = 1; /* return 1 byte */ - - /* virual pointer to return buffer - clear first two dwords */ - p32 = (volatile PU32)pPab->pLinOutMsgBlock; - p32[0] = 0; - p32[1] = 0; - - /* post to Inbound Post Q */ - - pPab->p_atu->InQueue = msgOffset; - - /* wait for response */ - timeout = 1000000; - while(1) { - udelay(10); /* please don't hog the bus!!! */ - - if (p32[0] || p32[1]) - break; - - if (!timeout--) - { - dprintk("RCResetIOP timeout\n"); - return RC_RTN_MSG_REPLY_TIMEOUT; - } - } - return RC_RTN_NO_ERROR; + U32 msgOffset, timeout; + PU32 pMsg; + PPAB pPab = ((PDPA) dev->priv)->pPab; + volatile PU32 p32; + + msgOffset = pPab->p_atu->InQueue; + + if (msgOffset == 0xFFFFFFFF) { + return RC_RTN_FREE_Q_EMPTY; + } + + /* calc virtual address of msg - virtual already mapped to physical */ + pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset); + + pMsg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_0; + pMsg[1] = I2O_EXEC_IOP_RESET << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID; + pMsg[2] = 0; /* universal context */ + pMsg[3] = 0; /* universal context */ + pMsg[4] = 0; /* universal context */ + pMsg[5] = 0; /* universal context */ + /* phys address to return status - area right after PAB */ + pMsg[6] = pPab->outMsgBlockPhyAddr; + pMsg[7] = 0; + pMsg[8] = 1; /* return 1 byte */ + + /* virual pointer to return buffer - clear first two dwords */ + p32 = (volatile PU32) pPab->pLinOutMsgBlock; + p32[0] = 0; + p32[1] = 0; + + /* post to Inbound Post Q */ + + pPab->p_atu->InQueue = msgOffset; + + /* wait for response */ + timeout = 1000000; + while (1) { + udelay (10); /* please don't hog the bus!!! */ + + if (p32[0] || p32[1]) + break; + + if (!timeout--) { + dprintk ("RCResetIOP timeout\n"); + return RC_RTN_MSG_REPLY_TIMEOUT; + } + } + return RC_RTN_NO_ERROR; } /* @@ -1521,57 +1490,55 @@ ** ** ========================================================================= */ -RC_RETURN -RCShutdownLANCard(struct net_device *dev, U16 ResourceFlags, - PU32 ReturnAddr, PFNCALLBACK CallbackFunction) -{ - volatile PU32 pMsg; - U32 off; - PPAB pPab = ((PDPA)dev->priv)->pPab; - long timeout = 0; - - if (pPab == NULL) - return RC_RTN_ADPTR_NOT_REGISTERED; - - off = pPab->p_atu->InQueue; /* get addresss of message */ - - if (0xFFFFFFFF == off) - return RC_RTN_FREE_Q_EMPTY; - - pPab->pCallbackFunc = CallbackFunction; - - pMsg = (PU32)(pPab->pPci45LinBaseAddr + off); - - /* setup message */ - pMsg[0] = FOUR_WORD_MSG_SIZE | SGL_OFFSET_0; - pMsg[1] = I2O_LAN_SHUTDOWN << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; - pMsg[2] = DEFAULT_RECV_INIT_CONTEXT; - pMsg[3] = ResourceFlags << 16; /* resource flags */ - - pPab->p_atu->InQueue = off; /* send it to the I2O device */ - - if (CallbackFunction == (PFNCALLBACK)NULL) - { - /* call RCProcI2OMsgQ() until something in pPab->pCallbackFunc - or until timer goes off */ - while (pPab->pCallbackFunc == (PFNCALLBACK)NULL) - { - RCProcI2OMsgQ(dev); - udelay(1000); /* please don't hog the bus!!! */ - timeout++; - if (timeout > 10000) - { - printk(KERN_WARNING "(rcpci45 driver:) RCShutdownLANCard(): timeout\n"); - break; - } - } - if (ReturnAddr != (PU32)NULL) - *ReturnAddr = (U32)pPab->pCallbackFunc; - } - return RC_RTN_NO_ERROR ; +RC_RETURN +RCShutdownLANCard (struct net_device * dev, U16 ResourceFlags, + PU32 ReturnAddr, PFNCALLBACK CallbackFunction) +{ + volatile PU32 pMsg; + U32 off; + PPAB pPab = ((PDPA) dev->priv)->pPab; + long timeout = 0; + + if (pPab == NULL) + return RC_RTN_ADPTR_NOT_REGISTERED; + + off = pPab->p_atu->InQueue; /* get addresss of message */ + + if (0xFFFFFFFF == off) + return RC_RTN_FREE_Q_EMPTY; + + pPab->pCallbackFunc = CallbackFunction; + + pMsg = (PU32) (pPab->pPci45LinBaseAddr + off); + + /* setup message */ + pMsg[0] = FOUR_WORD_MSG_SIZE | SGL_OFFSET_0; + pMsg[1] = + I2O_LAN_SHUTDOWN << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; + pMsg[2] = DEFAULT_RECV_INIT_CONTEXT; + pMsg[3] = ResourceFlags << 16; /* resource flags */ + + pPab->p_atu->InQueue = off; /* send it to the I2O device */ + + if (CallbackFunction == (PFNCALLBACK) NULL) { + /* call RCProcI2OMsgQ() until something in pPab->pCallbackFunc + or until timer goes off */ + while (pPab->pCallbackFunc == (PFNCALLBACK) NULL) { + RCProcI2OMsgQ (dev); + udelay (1000); /* please don't hog the bus!!! */ + timeout++; + if (timeout > 10000) { + printk (KERN_WARNING + "(rcpci45 driver:) RCShutdownLANCard(): timeout\n"); + break; + } + } + if (ReturnAddr != (PU32) NULL) + *ReturnAddr = (U32) pPab->pCallbackFunc; + } + return RC_RTN_NO_ERROR; } - /* ** ========================================================================= ** RCSetRavlinIPandMask() @@ -1585,34 +1552,33 @@ ** ========================================================================= */ RC_RETURN -RCSetRavlinIPandMask(struct net_device *dev, U32 ipAddr, U32 netMask) +RCSetRavlinIPandMask (struct net_device * dev, U32 ipAddr, U32 netMask) { - volatile PU32 pMsg; - U32 off; - PPAB pPab = ((PDPA)dev->priv)->pPab; - - if (pPab == NULL) - return RC_RTN_ADPTR_NOT_REGISTERED; - - off = pPab->p_atu->InQueue; /* get addresss of message */ - - if (0xFFFFFFFF == off) - return RC_RTN_FREE_Q_EMPTY; - - pMsg = (PU32)(pPab->pPci45LinBaseAddr + off); - - /* setup private message */ - pMsg[0] = SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0; - pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; - pMsg[2] = 0; /* initiator context */ - pMsg[3] = 0x219; /* transaction context */ - pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_IP_AND_MASK; - pMsg[5] = ipAddr; - pMsg[6] = netMask; + volatile PU32 pMsg; + U32 off; + PPAB pPab = ((PDPA) dev->priv)->pPab; + + if (pPab == NULL) + return RC_RTN_ADPTR_NOT_REGISTERED; + + off = pPab->p_atu->InQueue; /* get addresss of message */ + + if (0xFFFFFFFF == off) + return RC_RTN_FREE_Q_EMPTY; + pMsg = (PU32) (pPab->pPci45LinBaseAddr + off); - pPab->p_atu->InQueue = off; /* send it to the I2O device */ - return RC_RTN_NO_ERROR ; + /* setup private message */ + pMsg[0] = SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0; + pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; + pMsg[2] = 0; /* initiator context */ + pMsg[3] = 0x219; /* transaction context */ + pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_IP_AND_MASK; + pMsg[5] = ipAddr; + pMsg[6] = netMask; + + pPab->p_atu->InQueue = off; /* send it to the I2O device */ + return RC_RTN_NO_ERROR; } @@ -1625,69 +1591,76 @@ ** ========================================================================= */ RC_RETURN -RCGetRavlinIPandMask(struct net_device *dev, PU32 pIpAddr, PU32 pNetMask, - PFNWAITCALLBACK WaitCallback) +RCGetRavlinIPandMask (struct net_device * dev, PU32 pIpAddr, PU32 pNetMask, + PFNWAITCALLBACK WaitCallback) { - unsigned timeout; - U32 off; - PU32 pMsg, p32; - PPAB pPab = ((PDPA)dev->priv)->pPab; - PATU p_atu; - - dprintk("RCGetRavlinIPandMask: pIpAddr is 0x%08ulx, *IpAddr is 0x%08ulx\n", (u32)pIpAddr, *pIpAddr); - - if (pPab == NULL) - return RC_RTN_ADPTR_NOT_REGISTERED; - - p_atu = pPab->p_atu; - off = p_atu->InQueue; /* get addresss of message */ - - if (0xFFFFFFFF == off) - return RC_RTN_FREE_Q_EMPTY; - - p32 = (volatile PU32)pPab->pLinOutMsgBlock; - *p32 = 0xFFFFFFFF; - - pMsg = (PU32)(pPab->pPci45LinBaseAddr + off); - - dprintk("RCGetRavlinIPandMask: p_atu 0x%08ulx, off 0x%08ulx, p32 0x%08ulx\n", (u32)p_atu, off, (u32)p32); - /* setup private message */ - pMsg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0; - pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; - pMsg[2] = 0; /* initiator context */ - pMsg[3] = 0x218; /* transaction context */ - pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_IP_AND_MASK; - pMsg[5] = pPab->outMsgBlockPhyAddr; - - p_atu->InQueue = off; /* send it to the I2O device */ - dprintk("RCGetRavlinIPandMask: p_atu 0x%08ulx, off 0x%08ulx, p32 0x%08ulx\n", (u32)p_atu, off, (u32)p32); - - /* wait for the rcpci45 board to update the info */ - timeout = 100000; - while (0xffffffff == *p32) - { - if (WaitCallback) - (*WaitCallback)(); - - udelay(10); - - if (!timeout--) - { - dprintk("RCGetRavlinIPandMask: Timeout\n"); - return RC_RTN_MSG_REPLY_TIMEOUT; - } - } - - dprintk("RCGetRavlinIPandMask: after time out\np32[0] (IpAddr) 0x%08ulx, p32[1] (IPmask) 0x%08ulx\n", p32[0], p32[1]); - - /* send IP and mask to user's space */ - *pIpAddr = p32[0]; - *pNetMask = p32[1]; - + unsigned timeout; + U32 off; + PU32 pMsg, p32; + PPAB pPab = ((PDPA) dev->priv)->pPab; + PATU p_atu; + + dprintk + ("RCGetRavlinIPandMask: pIpAddr is 0x%08ulx, *IpAddr is 0x%08ulx\n", + (u32) pIpAddr, *pIpAddr); + + if (pPab == NULL) + return RC_RTN_ADPTR_NOT_REGISTERED; + + p_atu = pPab->p_atu; + off = p_atu->InQueue; /* get addresss of message */ + + if (0xFFFFFFFF == off) + return RC_RTN_FREE_Q_EMPTY; + + p32 = (volatile PU32) pPab->pLinOutMsgBlock; + *p32 = 0xFFFFFFFF; + + pMsg = (PU32) (pPab->pPci45LinBaseAddr + off); + + dprintk + ("RCGetRavlinIPandMask: p_atu 0x%08ulx, off 0x%08ulx, p32 0x%08ulx\n", + (u32) p_atu, off, (u32) p32); + /* setup private message */ + pMsg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0; + pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; + pMsg[2] = 0; /* initiator context */ + pMsg[3] = 0x218; /* transaction context */ + pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_IP_AND_MASK; + pMsg[5] = pPab->outMsgBlockPhyAddr; + + p_atu->InQueue = off; /* send it to the I2O device */ + dprintk + ("RCGetRavlinIPandMask: p_atu 0x%08ulx, off 0x%08ulx, p32 0x%08ulx\n", + (u32) p_atu, off, (u32) p32); + + /* wait for the rcpci45 board to update the info */ + timeout = 100000; + while (0xffffffff == *p32) { + if (WaitCallback) + (*WaitCallback) (); + + udelay (10); + + if (!timeout--) { + dprintk ("RCGetRavlinIPandMask: Timeout\n"); + return RC_RTN_MSG_REPLY_TIMEOUT; + } + } + + dprintk + ("RCGetRavlinIPandMask: after time out\np32[0] (IpAddr) 0x%08ulx, p32[1] (IPmask) 0x%08ulx\n", + p32[0], p32[1]); + + /* send IP and mask to user's space */ + *pIpAddr = p32[0]; + *pNetMask = p32[1]; + + dprintk + ("RCGetRavlinIPandMask: pIpAddr is 0x%08ulx, *IpAddr is 0x%08ulx\n", + (u32) pIpAddr, *pIpAddr); - dprintk("RCGetRavlinIPandMask: pIpAddr is 0x%08ulx, *IpAddr is 0x%08ulx\n", (u32)pIpAddr, *pIpAddr); - - return RC_RTN_NO_ERROR; + return RC_RTN_NO_ERROR; } /* @@ -1706,90 +1679,84 @@ ** ** ========================================================================= */ -static int -SendI2OOutboundQInitMsg(PPAB pPab) +static int +SendI2OOutboundQInitMsg (PPAB pPab) { - U32 msgOffset, timeout, phyOutQFrames, i; - volatile PU32 pMsg; - volatile PU32 p32; - - - - msgOffset = pPab->p_atu->InQueue; - - - if (msgOffset == 0xFFFFFFFF) - { - dprintk("SendI2OOutboundQInitMsg(): Inbound Free Q empty!\n"); - return RC_RTN_FREE_Q_EMPTY; - } - - - /* calc virual address of msg - virual already mapped to physical */ - pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset); - - dprintk("SendI2OOutboundQInitMsg - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", (u32)pMsg, msgOffset); - - pMsg[0] = EIGHT_WORD_MSG_SIZE | TRL_OFFSET_6; - pMsg[1] = I2O_EXEC_OUTBOUND_INIT << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID; - pMsg[2] = DEFAULT_RECV_INIT_CONTEXT; - pMsg[3] = 0x106; /* transaction context */ - pMsg[4] = 4096; /* Host page frame size */ - pMsg[5] = MSG_FRAME_SIZE << 16 | 0x80; /* outbound msg frame size and Initcode */ - pMsg[6] = 0xD0000004; /* simple sgl element LE, EOB */ - /* phys address to return status - area right after PAB */ - pMsg[7] = pPab->outMsgBlockPhyAddr; - - /* virual pointer to return buffer - clear first two dwords */ - p32 = (PU32)pPab->pLinOutMsgBlock; - p32[0] = 0; - - /* post to Inbound Post Q */ - pPab->p_atu->InQueue = msgOffset; - - /* wait for response */ - timeout = 100000; - while(1) - { - udelay(10); /* please don't hog the bus!!! */ - - if (p32[0]) - break; - - if (!timeout--) - { - dprintk("Timeout wait for InitOutQ InPrgress status from IOP\n"); - return RC_RTN_NO_I2O_STATUS; - } - } - - timeout = 100000; - while(1) - { - udelay(10); /* please don't hog the bus!!! */ - - if (p32[0] == I2O_EXEC_OUTBOUND_INIT_COMPLETE) - break; - - if (!timeout--) - { - dprintk("Timeout wait for InitOutQ Complete status from IOP\n"); - return RC_RTN_NO_I2O_STATUS; - } - } - - /* load PCI outbound free Q with MF physical addresses */ - phyOutQFrames = pPab->outMsgBlockPhyAddr; - - for (i = 0; i < NMBR_MSG_FRAMES; i++) - { - pPab->p_atu->OutQueue = phyOutQFrames; - phyOutQFrames += MSG_FRAME_SIZE; - } - return RC_RTN_NO_ERROR; + U32 msgOffset, timeout, phyOutQFrames, i; + volatile PU32 pMsg; + volatile PU32 p32; + + msgOffset = pPab->p_atu->InQueue; + + if (msgOffset == 0xFFFFFFFF) { + dprintk ("SendI2OOutboundQInitMsg(): Inbound Free Q empty!\n"); + return RC_RTN_FREE_Q_EMPTY; + } + + /* calc virual address of msg - virual already mapped to physical */ + pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset); + + dprintk + ("SendI2OOutboundQInitMsg - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", + (u32) pMsg, msgOffset); + + pMsg[0] = EIGHT_WORD_MSG_SIZE | TRL_OFFSET_6; + pMsg[1] = + I2O_EXEC_OUTBOUND_INIT << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID; + pMsg[2] = DEFAULT_RECV_INIT_CONTEXT; + pMsg[3] = 0x106; /* transaction context */ + pMsg[4] = 4096; /* Host page frame size */ + pMsg[5] = MSG_FRAME_SIZE << 16 | 0x80; /* outbound msg frame size and Initcode */ + pMsg[6] = 0xD0000004; /* simple sgl element LE, EOB */ + /* phys address to return status - area right after PAB */ + pMsg[7] = pPab->outMsgBlockPhyAddr; + + /* virual pointer to return buffer - clear first two dwords */ + p32 = (PU32) pPab->pLinOutMsgBlock; + p32[0] = 0; + + /* post to Inbound Post Q */ + pPab->p_atu->InQueue = msgOffset; + + /* wait for response */ + timeout = 100000; + while (1) { + udelay (10); /* please don't hog the bus!!! */ + + if (p32[0]) + break; + + if (!timeout--) { + dprintk + ("Timeout wait for InitOutQ InPrgress status from IOP\n"); + return RC_RTN_NO_I2O_STATUS; + } + } + + timeout = 100000; + while (1) { + udelay (10); /* please don't hog the bus!!! */ + + if (p32[0] == I2O_EXEC_OUTBOUND_INIT_COMPLETE) + break; + + if (!timeout--) { + dprintk + ("Timeout wait for InitOutQ Complete status from IOP\n"); + return RC_RTN_NO_I2O_STATUS; + } + } + + /* load PCI outbound free Q with MF physical addresses */ + phyOutQFrames = pPab->outMsgBlockPhyAddr; + + for (i = 0; i < NMBR_MSG_FRAMES; i++) { + pPab->p_atu->OutQueue = phyOutQFrames; + phyOutQFrames += MSG_FRAME_SIZE; + } + return RC_RTN_NO_ERROR; } - /* ** ========================================================================= ** GetI2OStatus() @@ -1798,80 +1765,83 @@ ** ** ========================================================================= */ -static int -GetI2OStatus(PPAB pPab) +static int +GetI2OStatus (PPAB pPab) { - U32 msgOffset, timeout; - PU32 pMsg; - volatile PU32 p32; - - - msgOffset = pPab->p_atu->InQueue; - dprintk("GetI2OStatus: msg offset = 0x%x\n", msgOffset); - if (msgOffset == 0xFFFFFFFF) - { - dprintk("GetI2OStatus(): Inbound Free Q empty!\n"); - return RC_RTN_FREE_Q_EMPTY; - } - - /* calc virual address of msg - virual already mapped to physical */ - pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset); - - pMsg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_0; - pMsg[1] = I2O_EXEC_STATUS_GET << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID; - pMsg[2] = 0; /* universal context */ - pMsg[3] = 0; /* universal context */ - pMsg[4] = 0; /* universal context */ - pMsg[5] = 0; /* universal context */ - /* phys address to return status - area right after PAB */ - pMsg[6] = pPab->outMsgBlockPhyAddr; - pMsg[7] = 0; - pMsg[8] = 88; /* return 88 bytes */ - - /* virual pointer to return buffer - clear first two dwords */ - p32 = (volatile PU32)pPab->pLinOutMsgBlock; - p32[0] = 0; - p32[1] = 0; - - dprintk("GetI2OStatus - pMsg:0x%08ulx, msgOffset:0x%08ulx, [1]:0x%08ulx, [6]:0x%08ulx\n", - (u32)pMsg, msgOffset, pMsg[1], pMsg[6]); - - /* post to Inbound Post Q */ - pPab->p_atu->InQueue = msgOffset; - - dprintk("Return status to p32 = 0x%08ulx\n", (u32)p32); - - /* wait for response */ - timeout = 1000000; - while(1) { - udelay(10); /* please don't hog the bus!!! */ - - if (p32[0] && p32[1]) - break; - - if (!timeout--) - { - dprintk("Timeout waiting for status from IOP\n"); - dprintk("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[0], p32[1], p32[2], p32[3]); - dprintk("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[4], p32[5], p32[6], p32[7]); - dprintk("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[8], p32[9], p32[10], p32[11]); - return RC_RTN_NO_I2O_STATUS; - } - } - - dprintk("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[0], p32[1], p32[2], p32[3]); - dprintk("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[4], p32[5], p32[6], p32[7]); - dprintk("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[8], p32[9], p32[10], p32[11]); - /* get IOP state */ - pPab->IOPState = ((volatile PU8)p32)[10]; - pPab->InboundMFrameSize = ((volatile PU16)p32)[6]; - - dprintk("IOP state 0x%02x InFrameSize = 0x%04x\n", - pPab->IOPState, pPab->InboundMFrameSize); - return RC_RTN_NO_ERROR; + U32 msgOffset, timeout; + PU32 pMsg; + volatile PU32 p32; + + msgOffset = pPab->p_atu->InQueue; + dprintk ("GetI2OStatus: msg offset = 0x%x\n", msgOffset); + if (msgOffset == 0xFFFFFFFF) { + dprintk ("GetI2OStatus(): Inbound Free Q empty!\n"); + return RC_RTN_FREE_Q_EMPTY; + } + + /* calc virual address of msg - virual already mapped to physical */ + pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset); + + pMsg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_0; + pMsg[1] = I2O_EXEC_STATUS_GET << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID; + pMsg[2] = 0; /* universal context */ + pMsg[3] = 0; /* universal context */ + pMsg[4] = 0; /* universal context */ + pMsg[5] = 0; /* universal context */ + /* phys address to return status - area right after PAB */ + pMsg[6] = pPab->outMsgBlockPhyAddr; + pMsg[7] = 0; + pMsg[8] = 88; /* return 88 bytes */ + + /* virual pointer to return buffer - clear first two dwords */ + p32 = (volatile PU32) pPab->pLinOutMsgBlock; + p32[0] = 0; + p32[1] = 0; + + dprintk + ("GetI2OStatus - pMsg:0x%08ulx, msgOffset:0x%08ulx, [1]:0x%08ulx, [6]:0x%08ulx\n", + (u32) pMsg, msgOffset, pMsg[1], pMsg[6]); + + /* post to Inbound Post Q */ + pPab->p_atu->InQueue = msgOffset; + + dprintk ("Return status to p32 = 0x%08ulx\n", (u32) p32); + + /* wait for response */ + timeout = 1000000; + while (1) { + udelay (10); /* please don't hog the bus!!! */ + + if (p32[0] && p32[1]) + break; + + if (!timeout--) { + dprintk ("Timeout waiting for status from IOP\n"); + dprintk ("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", + p32[0], p32[1], p32[2], p32[3]); + dprintk ("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", + p32[4], p32[5], p32[6], p32[7]); + dprintk ("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", + p32[8], p32[9], p32[10], p32[11]); + return RC_RTN_NO_I2O_STATUS; + } + } + + dprintk ("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[0], p32[1], + p32[2], p32[3]); + dprintk ("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[4], p32[5], + p32[6], p32[7]); + dprintk ("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[8], p32[9], + p32[10], p32[11]); + /* get IOP state */ + pPab->IOPState = ((volatile PU8) p32)[10]; + pPab->InboundMFrameSize = ((volatile PU16) p32)[6]; + + dprintk ("IOP state 0x%02x InFrameSize = 0x%04x\n", + pPab->IOPState, pPab->InboundMFrameSize); + return RC_RTN_NO_ERROR; } - /* ** ========================================================================= ** SendEnableSysMsg() @@ -1879,38 +1849,38 @@ ** ** ========================================================================= */ -static int -SendEnableSysMsg(PPAB pPab) +static int +SendEnableSysMsg (PPAB pPab) { - U32 msgOffset; - volatile PU32 pMsg; + U32 msgOffset; + volatile PU32 pMsg; - msgOffset = pPab->p_atu->InQueue; + msgOffset = pPab->p_atu->InQueue; - if (msgOffset == 0xFFFFFFFF) - { - dprintk("SendEnableSysMsg(): Inbound Free Q empty!\n"); - return RC_RTN_FREE_Q_EMPTY; - } + if (msgOffset == 0xFFFFFFFF) { + dprintk ("SendEnableSysMsg(): Inbound Free Q empty!\n"); + return RC_RTN_FREE_Q_EMPTY; + } - /* calc virual address of msg - virual already mapped to physical */ - pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset); + /* calc virual address of msg - virual already mapped to physical */ + pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset); - dprintk("SendEnableSysMsg - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", (u32)pMsg, msgOffset); + dprintk + ("SendEnableSysMsg - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", + (u32) pMsg, msgOffset); - pMsg[0] = FOUR_WORD_MSG_SIZE | SGL_OFFSET_0; - pMsg[1] = I2O_EXEC_SYS_ENABLE << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID; - pMsg[2] = DEFAULT_RECV_INIT_CONTEXT; - pMsg[3] = 0x110; /* transaction context */ - pMsg[4] = 0x50657465; /* RedCreek Private */ + pMsg[0] = FOUR_WORD_MSG_SIZE | SGL_OFFSET_0; + pMsg[1] = I2O_EXEC_SYS_ENABLE << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID; + pMsg[2] = DEFAULT_RECV_INIT_CONTEXT; + pMsg[3] = 0x110; /* transaction context */ + pMsg[4] = 0x50657465; /* RedCreek Private */ - /* post to Inbound Post Q */ - pPab->p_atu->InQueue = msgOffset; + /* post to Inbound Post Q */ + pPab->p_atu->InQueue = msgOffset; - return RC_RTN_NO_ERROR; + return RC_RTN_NO_ERROR; } - /* ** ========================================================================= ** FillI2OMsgFromTCB() @@ -1921,91 +1891,82 @@ ** fills in LAN SGL after Transaction Control Word or Bucket Count. ** ========================================================================= */ -static int -FillI2OMsgSGLFromTCB(PU32 pMsgFrame, PRCTCB pTransCtrlBlock) +static int +FillI2OMsgSGLFromTCB (PU32 pMsgFrame, PRCTCB pTransCtrlBlock) { - unsigned int nmbrBuffers, nmbrSeg, nmbrDwords, context, flags; - PU32 pTCB, pMsg; + unsigned int nmbrBuffers, nmbrSeg, nmbrDwords, context, flags; + PU32 pTCB, pMsg; - /* SGL element flags */ + /* SGL element flags */ #define EOB 0x40000000 #define LE 0x80000000 #define SIMPLE_SGL 0x10000000 #define BC_PRESENT 0x01000000 - pTCB = (PU32)pTransCtrlBlock; - pMsg = pMsgFrame; - nmbrDwords = 0; - - dprintk("FillI2OMsgSGLFromTCBX\n"); - dprintk("TCB 0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", - pTCB[0], pTCB[1], pTCB[2], pTCB[3], pTCB[4]); - dprintk("pTCB 0x%08ulx, pMsg 0x%08ulx\n", (u32)pTCB, (u32)pMsg); - - nmbrBuffers = *pTCB++; - - if (!nmbrBuffers) - { - return -1; - } - - do - { - context = *pTCB++; /* buffer tag (context) */ - nmbrSeg = *pTCB++; /* number of segments */ - - if (!nmbrSeg) - { - return -1; - } - - flags = SIMPLE_SGL | BC_PRESENT; - - if (1 == nmbrSeg) - { - flags |= EOB; - - if (1 == nmbrBuffers) - flags |= LE; - } - - /* 1st SGL buffer element has context */ - pMsg[0] = pTCB[0] | flags ; /* send over count (segment size) */ - pMsg[1] = context; - pMsg[2] = pTCB[1]; /* send buffer segment physical address */ - nmbrDwords += 3; - pMsg += 3; - pTCB += 2; - - - if (--nmbrSeg) - { - do - { - flags = SIMPLE_SGL; - - if (1 == nmbrSeg) - { - flags |= EOB; - - if (1 == nmbrBuffers) - flags |= LE; - } - - pMsg[0] = pTCB[0] | flags; /* send over count */ - pMsg[1] = pTCB[1]; /* send buffer segment physical address */ - nmbrDwords += 2; - pTCB += 2; - pMsg += 2; - - } while (--nmbrSeg); - } - - } while (--nmbrBuffers); - - return nmbrDwords; -} + pTCB = (PU32) pTransCtrlBlock; + pMsg = pMsgFrame; + nmbrDwords = 0; + + dprintk ("FillI2OMsgSGLFromTCBX\n"); + dprintk ("TCB 0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", + pTCB[0], pTCB[1], pTCB[2], pTCB[3], pTCB[4]); + dprintk ("pTCB 0x%08ulx, pMsg 0x%08ulx\n", (u32) pTCB, (u32) pMsg); + + nmbrBuffers = *pTCB++; + + if (!nmbrBuffers) { + return -1; + } + + do { + context = *pTCB++; /* buffer tag (context) */ + nmbrSeg = *pTCB++; /* number of segments */ + + if (!nmbrSeg) { + return -1; + } + + flags = SIMPLE_SGL | BC_PRESENT; + if (1 == nmbrSeg) { + flags |= EOB; + + if (1 == nmbrBuffers) + flags |= LE; + } + + /* 1st SGL buffer element has context */ + pMsg[0] = pTCB[0] | flags; /* send over count (segment size) */ + pMsg[1] = context; + pMsg[2] = pTCB[1]; /* send buffer segment physical address */ + nmbrDwords += 3; + pMsg += 3; + pTCB += 2; + + if (--nmbrSeg) { + do { + flags = SIMPLE_SGL; + + if (1 == nmbrSeg) { + flags |= EOB; + + if (1 == nmbrBuffers) + flags |= LE; + } + + pMsg[0] = pTCB[0] | flags; /* send over count */ + pMsg[1] = pTCB[1]; /* send buffer segment physical address */ + nmbrDwords += 2; + pTCB += 2; + pMsg += 2; + + } while (--nmbrSeg); + } + + } while (--nmbrBuffers); + + return nmbrDwords; +} /* ** ========================================================================= @@ -2015,51 +1976,52 @@ ** * change to msg structure * ** ========================================================================= */ -static void -ProcessOutboundI2OMsg(PPAB pPab, U32 phyAddrMsg) +static void +ProcessOutboundI2OMsg (PPAB pPab, U32 phyAddrMsg) { - PU8 p8Msg; - PU32 p32; + PU8 p8Msg; + PU32 p32; /* U16 count; */ - - - p8Msg = pPab->pLinOutMsgBlock + (phyAddrMsg - pPab->outMsgBlockPhyAddr); - p32 = (PU32)p8Msg; - - dprintk("VXD: ProcessOutboundI2OMsg - pPab 0x%08ulx, phyAdr 0x%08ulx, linAdr 0x%08ulx\n", (u32)pPab, phyAddrMsg, (u32)p8Msg); - dprintk("msg :0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[0], p32[1], p32[2], p32[3]); - dprintk("msg :0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[4], p32[5], p32[6], p32[7]); - - if (p32[4] >> 24 != I2O_REPLY_STATUS_SUCCESS) - { - dprintk("Message reply status not success\n"); - return; - } - - switch (p8Msg[7] ) /* function code byte */ - { - case I2O_EXEC_SYS_TAB_SET: - msgFlag = 1; - dprintk("Received I2O_EXEC_SYS_TAB_SET reply\n"); - break; - - case I2O_EXEC_HRT_GET: - msgFlag = 1; - dprintk("Received I2O_EXEC_HRT_GET reply\n"); - break; - - case I2O_EXEC_LCT_NOTIFY: - msgFlag = 1; - dprintk("Received I2O_EXEC_LCT_NOTIFY reply\n"); - break; - - case I2O_EXEC_SYS_ENABLE: - msgFlag = 1; - dprintk("Received I2O_EXEC_SYS_ENABLE reply\n"); - break; - - default: - dprintk("Received UNKNOWN reply\n"); - break; - } + + p8Msg = pPab->pLinOutMsgBlock + (phyAddrMsg - pPab->outMsgBlockPhyAddr); + p32 = (PU32) p8Msg; + + dprintk + ("VXD: ProcessOutboundI2OMsg - pPab 0x%08ulx, phyAdr 0x%08ulx, linAdr 0x%08ulx\n", + (u32) pPab, phyAddrMsg, (u32) p8Msg); + dprintk ("msg :0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[0], p32[1], + p32[2], p32[3]); + dprintk ("msg :0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[4], p32[5], + p32[6], p32[7]); + + if (p32[4] >> 24 != I2O_REPLY_STATUS_SUCCESS) { + dprintk ("Message reply status not success\n"); + return; + } + + switch (p8Msg[7]) { /* function code byte */ + case I2O_EXEC_SYS_TAB_SET: + msgFlag = 1; + dprintk ("Received I2O_EXEC_SYS_TAB_SET reply\n"); + break; + + case I2O_EXEC_HRT_GET: + msgFlag = 1; + dprintk ("Received I2O_EXEC_HRT_GET reply\n"); + break; + + case I2O_EXEC_LCT_NOTIFY: + msgFlag = 1; + dprintk ("Received I2O_EXEC_LCT_NOTIFY reply\n"); + break; + + case I2O_EXEC_SYS_ENABLE: + msgFlag = 1; + dprintk ("Received I2O_EXEC_SYS_ENABLE reply\n"); + break; + + default: + dprintk ("Received UNKNOWN reply\n"); + break; + } } diff -u --recursive --new-file v2.4.5/linux/drivers/net/rclanmtl.h linux/drivers/net/rclanmtl.h --- v2.4.5/linux/drivers/net/rclanmtl.h Tue Mar 6 19:28:34 2001 +++ linux/drivers/net/rclanmtl.h Mon Jul 2 14:03:04 2001 @@ -39,12 +39,12 @@ /* Linux specific includes */ #include -#ifdef RC_LINUX_MODULE /* linux modules need non-library version of string functions */ +#ifdef RC_LINUX_MODULE /* linux modules need non-library version of string functions */ #include #else #include #endif -#include /* for udelay() */ +#include /* for udelay() */ #include #include @@ -62,152 +62,141 @@ #define dprintk(args...) { } #endif - /* Typedefs */ /* scalar data types */ -typedef __u8 U8; -typedef __u16 U16; -typedef __u32 U32; -typedef __u8* PU8; -typedef __u16* PU16; -typedef __u32* PU32; -typedef unsigned long BF; -typedef int RC_RETURN; +typedef __u8 U8; +typedef __u16 U16; +typedef __u32 U32; +typedef __u8 *PU8; +typedef __u16 *PU16; +typedef __u32 *PU32; +typedef unsigned long BF; +typedef int RC_RETURN; /* - ** type PFNWAITCALLBACK - ** - ** pointer to void function - type used for WaitCallback in some functions - */ -typedef void (*PFNWAITCALLBACK)(void); /* void argument avoids compiler complaint */ - - /* - ** type PFNTXCALLBACK - ** - ** Pointer to user's transmit callback function. This user function is - ** called from RCProcI2OMsgQ() when packet have been transmitted from buffers - ** given in the RCI2OSendPacket() function. BufferContext is a pointer to - ** an array of 32 bit context values. These are the values the user assigned - ** and passed in the TCB to the RCI2OSendPacket() function. PcktCount - ** indicates the number of buffer context values in the BufferContext[] array. - ** The User's TransmitCallbackFunction should recover (put back in free queue) - ** the packet buffers associated with the buffer context values. - */ -typedef void (*PFNTXCALLBACK)(U32 Status, - U16 PcktCount, - PU32 BufferContext, - struct net_device *); + ** type PFNWAITCALLBACK + ** + ** pointer to void function - type used for WaitCallback in some functions + */ +typedef void (*PFNWAITCALLBACK) (void); /* void argument avoids compiler complaint */ + + /* + ** type PFNTXCALLBACK + ** + ** Pointer to user's transmit callback function. This user function is + ** called from RCProcI2OMsgQ() when packet have been transmitted from buffers + ** given in the RCI2OSendPacket() function. BufferContext is a pointer to + ** an array of 32 bit context values. These are the values the user assigned + ** and passed in the TCB to the RCI2OSendPacket() function. PcktCount + ** indicates the number of buffer context values in the BufferContext[] array. + ** The User's TransmitCallbackFunction should recover (put back in free queue) + ** the packet buffers associated with the buffer context values. + */ +typedef void (*PFNTXCALLBACK) (U32 Status, + U16 PcktCount, + PU32 BufferContext, struct net_device *); /* - ** type PFNRXCALLBACK - ** - ** Pointer to user's receive callback function. This user function - ** is called from RCProcI2OMsgQ() when packets have been received into - ** previously posted packet buffers throught the RCPostRecvBuffers() function. - ** The received callback function should process the Packet Descriptor Block - ** pointed to by PacketDescBlock. See Packet Decription Block below. - */ -typedef void (*PFNRXCALLBACK)(U32 Status, - U8 PktCount, - U32 BucketsRemain, - PU32 PacketDescBlock, - struct net_device *); + ** type PFNRXCALLBACK + ** + ** Pointer to user's receive callback function. This user function + ** is called from RCProcI2OMsgQ() when packets have been received into + ** previously posted packet buffers throught the RCPostRecvBuffers() function. + ** The received callback function should process the Packet Descriptor Block + ** pointed to by PacketDescBlock. See Packet Decription Block below. + */ +typedef void (*PFNRXCALLBACK) (U32 Status, + U8 PktCount, + U32 BucketsRemain, + PU32 PacketDescBlock, struct net_device *); /* - ** type PFNCALLBACK - ** - ** Pointer to user's generic callback function. This user function - ** can be passed to LANReset or LANShutdown and is called when the - ** the reset or shutdown is complete. - ** Param1 and Param2 are invalid for LANReset and LANShutdown. - */ -typedef void (*PFNCALLBACK)(U32 Status, - U32 Param1, - U32 Param2, - struct net_device *dev); + ** type PFNCALLBACK + ** + ** Pointer to user's generic callback function. This user function + ** can be passed to LANReset or LANShutdown and is called when the + ** the reset or shutdown is complete. + ** Param1 and Param2 are invalid for LANReset and LANShutdown. + */ +typedef void (*PFNCALLBACK) (U32 Status, + U32 Param1, U32 Param2, struct net_device * dev); /* ** Message Unit CSR definitions for RedCreek PCI45 board */ -typedef struct tag_rcatu -{ - volatile unsigned long APICRegSel; /* APIC Register Select */ - volatile unsigned long reserved0; - volatile unsigned long APICWinReg; /* APIC Window Register */ - volatile unsigned long reserved1; - volatile unsigned long InMsgReg0; /* inbound message register 0 */ - volatile unsigned long InMsgReg1; /* inbound message register 1 */ - volatile unsigned long OutMsgReg0; /* outbound message register 0 */ - volatile unsigned long OutMsgReg1; /* outbound message register 1 */ - volatile unsigned long InDoorReg; /* inbound doorbell register */ - volatile unsigned long InIntStat; /* inbound interrupt status register */ - volatile unsigned long InIntMask; /* inbound interrupt mask register */ - volatile unsigned long OutDoorReg; /* outbound doorbell register */ - volatile unsigned long OutIntStat; /* outbound interrupt status register */ - volatile unsigned long OutIntMask; /* outbound interrupt mask register */ - volatile unsigned long reserved2; - volatile unsigned long reserved3; - volatile unsigned long InQueue; /* inbound queue port */ - volatile unsigned long OutQueue; /* outbound queue port */ - volatile unsigned long reserved4; - volatile unsigned long reserver5; - /* RedCreek extension */ - volatile unsigned long EtherMacLow; - volatile unsigned long EtherMacHi; - volatile unsigned long IPaddr; - volatile unsigned long IPmask; +typedef struct tag_rcatu { + volatile unsigned long APICRegSel; /* APIC Register Select */ + volatile unsigned long reserved0; + volatile unsigned long APICWinReg; /* APIC Window Register */ + volatile unsigned long reserved1; + volatile unsigned long InMsgReg0; /* inbound message register 0 */ + volatile unsigned long InMsgReg1; /* inbound message register 1 */ + volatile unsigned long OutMsgReg0; /* outbound message register 0 */ + volatile unsigned long OutMsgReg1; /* outbound message register 1 */ + volatile unsigned long InDoorReg; /* inbound doorbell register */ + volatile unsigned long InIntStat; /* inbound interrupt status register */ + volatile unsigned long InIntMask; /* inbound interrupt mask register */ + volatile unsigned long OutDoorReg; /* outbound doorbell register */ + volatile unsigned long OutIntStat; /* outbound interrupt status register */ + volatile unsigned long OutIntMask; /* outbound interrupt mask register */ + volatile unsigned long reserved2; + volatile unsigned long reserved3; + volatile unsigned long InQueue; /* inbound queue port */ + volatile unsigned long OutQueue; /* outbound queue port */ + volatile unsigned long reserved4; + volatile unsigned long reserver5; + /* RedCreek extension */ + volatile unsigned long EtherMacLow; + volatile unsigned long EtherMacHi; + volatile unsigned long IPaddr; + volatile unsigned long IPmask; } *PATU; /* - ** typedef PAB - ** - ** PCI Adapter Block - holds instance specific information. - */ -typedef struct -{ - PATU p_atu; /* ptr to ATU register block */ - PU8 pPci45LinBaseAddr; - PU8 pLinOutMsgBlock; - U32 outMsgBlockPhyAddr; - PFNTXCALLBACK pTransCallbackFunc; - PFNRXCALLBACK pRecvCallbackFunc; - PFNCALLBACK pRebootCallbackFunc; - PFNCALLBACK pCallbackFunc; - U16 IOPState; - U16 InboundMFrameSize; + ** typedef PAB + ** + ** PCI Adapter Block - holds instance specific information. + */ +typedef struct { + PATU p_atu; /* ptr to ATU register block */ + PU8 pPci45LinBaseAddr; + PU8 pLinOutMsgBlock; + U32 outMsgBlockPhyAddr; + PFNTXCALLBACK pTransCallbackFunc; + PFNRXCALLBACK pRecvCallbackFunc; + PFNCALLBACK pRebootCallbackFunc; + PFNCALLBACK pCallbackFunc; + U16 IOPState; + U16 InboundMFrameSize; } *PPAB; /* * Driver Private Area, DPA. */ -typedef struct -{ - U8 id; /* the AdapterID */ - - /* These two field are basically for the RCioctl function. - * I could not determine if they could be avoided. (RAA)*/ - U32 pci_addr; /* the pci address of the adapter */ - U32 pci_addr_len; - - struct timer_list timer; /* timer */ - struct net_device_stats stats; /* the statistics structure */ - unsigned long numOutRcvBuffers;/* number of outstanding receive buffers*/ - unsigned char shutdown; - unsigned char reboot; - unsigned char nexus; - PU8 msgbuf; /* Pointer to Lan Api Private Area */ - PU8 PLanApiPA; /* Pointer to Lan Api Private Area (aligned) */ - PPAB pPab; /* Pointer to the PCI Adapter Block */ -} *PDPA; - +typedef struct { + U8 id; /* the AdapterID */ + /* These two field are basically for the RCioctl function. + * I could not determine if they could be avoided. (RAA)*/ + U32 pci_addr; /* the pci address of the adapter */ + U32 pci_addr_len; + + struct timer_list timer; /* timer */ + struct net_device_stats stats; /* the statistics structure */ + unsigned long numOutRcvBuffers; /* number of outstanding receive buffers */ + unsigned char shutdown; + unsigned char reboot; + unsigned char nexus; + PU8 msgbuf; /* Pointer to Lan Api Private Area */ + PU8 PLanApiPA; /* Pointer to Lan Api Private Area (aligned) */ + PPAB pPab; /* Pointer to the PCI Adapter Block */ +} *PDPA; /* PCI/45 Configuration space values */ #define RC_PCI45_VENDOR_ID 0x4916 #define RC_PCI45_DEVICE_ID 0x1960 - /* RedCreek API function return values */ #define RC_RTN_NO_ERROR 0 #define RC_RTN_I2O_NOT_INIT 1 @@ -244,7 +233,6 @@ #define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02 #define I2O_REPLY_STATUS_TRANSACTION_ERROR 0x0A - /* DetailedStatusCode defines */ #define I2O_LAN_DSC_SUCCESS 0x0000 #define I2O_LAN_DSC_DEVICE_FAILURE 0x0001 @@ -264,7 +252,6 @@ #define I2O_LAN_DSC_DESTINATION_ADDRESS_OMITTED 0x000F #define I2O_LAN_DSC_PARTIAL_PACKET_RETURNED 0x0010 - /* ** Packet Description Block (Received packets) ** @@ -301,8 +288,6 @@ ** */ - - /* ** Transaction Control Block (TCB) structure ** @@ -368,13 +353,11 @@ */ /* Buffer Segment Descriptor */ -typedef struct -{ - U32 size; - U32 phyAddress; -} - BSD, *PBSD; - +typedef struct { + U32 size; + U32 phyAddress; +} BSD, *PBSD; + typedef PU32 PRCTCB; /* ** ------------------------------------------------------------------------- @@ -382,41 +365,40 @@ ** ------------------------------------------------------------------------- */ - /* - ** InitRCI2OMsgLayer() - ** - ** Called once prior to using the I2O LAN message transport layer. User - ** provides both the physical and virual address of a locked page buffer - ** that is used as a private buffer for the RedCreek I2O message - ** transport layer. This buffer must be a contigous memory block of a - ** minimum of 16K bytes and long word aligned. The user also must provide - ** the base address of the RedCreek PCI adapter assigned by BIOS or operating - ** system. - ** - ** Inputs: dev - the net_device struct for the device. - ** TransmitCallbackFunction - address of user's TX callback function - ** ReceiveCallbackFunction - address of user's RX callback function - ** RebootCallbackFunction - address of user's reboot callback function - ** - */ -RC_RETURN RCInitI2OMsgLayer(struct net_device *dev, - PFNTXCALLBACK TransmitCallbackFunction, - PFNRXCALLBACK ReceiveCallbackFunction, - PFNCALLBACK RebootCallbackFunction); - - /* - ** RCSetRavlinIPandMask() - ** - ** Set the Ravlin 45/PCI cards IP address and network mask. - ** - ** IP address and mask must be in network byte order. - ** For example, IP address 1.2.3.4 and mask 255.255.255.0 would be - ** 0x04030201 and 0x00FFFFFF on a little endian machine. - ** - */ -RC_RETURN RCSetRavlinIPandMask(struct net_device *dev, U32 ipAddr, U32 netMask); - + ** InitRCI2OMsgLayer() + ** + ** Called once prior to using the I2O LAN message transport layer. User + ** provides both the physical and virual address of a locked page buffer + ** that is used as a private buffer for the RedCreek I2O message + ** transport layer. This buffer must be a contigous memory block of a + ** minimum of 16K bytes and long word aligned. The user also must provide + ** the base address of the RedCreek PCI adapter assigned by BIOS or operating + ** system. + ** + ** Inputs: dev - the net_device struct for the device. + ** TransmitCallbackFunction - address of user's TX callback function + ** ReceiveCallbackFunction - address of user's RX callback function + ** RebootCallbackFunction - address of user's reboot callback function + ** + */ +RC_RETURN RCInitI2OMsgLayer (struct net_device *dev, + PFNTXCALLBACK TransmitCallbackFunction, + PFNRXCALLBACK ReceiveCallbackFunction, + PFNCALLBACK RebootCallbackFunction); + + /* + ** RCSetRavlinIPandMask() + ** + ** Set the Ravlin 45/PCI cards IP address and network mask. + ** + ** IP address and mask must be in network byte order. + ** For example, IP address 1.2.3.4 and mask 255.255.255.0 would be + ** 0x04030201 and 0x00FFFFFF on a little endian machine. + ** + */ +RC_RETURN RCSetRavlinIPandMask (struct net_device *dev, U32 ipAddr, + U32 netMask); /* ** ========================================================================= @@ -427,136 +409,130 @@ ** ========================================================================= */ RC_RETURN -RCGetRavlinIPandMask(struct net_device *dev, PU32 pIpAddr, PU32 pNetMask, - PFNWAITCALLBACK WaitCallback); +RCGetRavlinIPandMask (struct net_device *dev, PU32 pIpAddr, PU32 pNetMask, + PFNWAITCALLBACK WaitCallback); /* - ** RCProcI2OMsgQ() - ** - ** Called from user's polling loop or Interrupt Service Routine for a PCI - ** interrupt from the RedCreek PCI adapter. User responsible for determining - ** and hooking the PCI interrupt. This function will call the registered - ** callback functions, TransmitCallbackFunction or ReceiveCallbackFunction, - ** if a TX or RX transaction has completed. - */ -void RCProcI2OMsgQ(struct net_device *dev); - - - /* - ** Disable and Enable I2O interrupts. I2O interrupts are enabled at Init time - ** but can be disabled and re-enabled through these two function calls. - ** Packets will still be put into any posted received buffers and packets will - ** be sent through RCI2OSendPacket() functions. Disabling I2O interrupts - ** will prevent hardware interrupt to host even though the outbound I2O msg - ** queue is not emtpy. - */ -RC_RETURN RCEnableI2OInterrupts(struct net_device *dev); -RC_RETURN RCDisableI2OInterrupts(struct net_device *dev); - + ** RCProcI2OMsgQ() + ** + ** Called from user's polling loop or Interrupt Service Routine for a PCI + ** interrupt from the RedCreek PCI adapter. User responsible for determining + ** and hooking the PCI interrupt. This function will call the registered + ** callback functions, TransmitCallbackFunction or ReceiveCallbackFunction, + ** if a TX or RX transaction has completed. + */ +void RCProcI2OMsgQ (struct net_device *dev); + + /* + ** Disable and Enable I2O interrupts. I2O interrupts are enabled at Init time + ** but can be disabled and re-enabled through these two function calls. + ** Packets will still be put into any posted received buffers and packets will + ** be sent through RCI2OSendPacket() functions. Disabling I2O interrupts + ** will prevent hardware interrupt to host even though the outbound I2O msg + ** queue is not emtpy. + */ +RC_RETURN RCEnableI2OInterrupts (struct net_device *dev); +RC_RETURN RCDisableI2OInterrupts (struct net_device *dev); /* - ** RCPostRecvBuffers() - ** - ** Post user's page locked buffers for use by the PCI adapter to - ** return ethernet packets received from the LAN. Transaction Control Block, - ** provided by user, contains buffer descriptor(s) which includes a buffer - ** context number along with buffer size and physical address. See TCB above. - ** The buffer context and actual packet length are returned to the - ** ReceiveCallbackFunction when packets have been received. Buffers posted - ** to the RedCreek adapter are considered owned by the adapter until the - ** context is return to user through the ReceiveCallbackFunction. - */ -RC_RETURN RCPostRecvBuffers(struct net_device *dev, PRCTCB pTransactionCtrlBlock); + ** RCPostRecvBuffers() + ** + ** Post user's page locked buffers for use by the PCI adapter to + ** return ethernet packets received from the LAN. Transaction Control Block, + ** provided by user, contains buffer descriptor(s) which includes a buffer + ** context number along with buffer size and physical address. See TCB above. + ** The buffer context and actual packet length are returned to the + ** ReceiveCallbackFunction when packets have been received. Buffers posted + ** to the RedCreek adapter are considered owned by the adapter until the + ** context is return to user through the ReceiveCallbackFunction. + */ +RC_RETURN RCPostRecvBuffers (struct net_device *dev, + PRCTCB pTransactionCtrlBlock); #define MAX_NMBR_POST_BUFFERS_PER_MSG 32 /* - ** RCI2OSendPacket() - ** - ** Send user's ethernet packet from a locked page buffer. - ** Packet must have full MAC header, however without a CRC. - ** Initiator context is a user provided value that is returned - ** to the TransmitCallbackFunction when packet buffer is free. - ** Transmit buffer are considered owned by the adapter until context's - ** returned to user through the TransmitCallbackFunction. - */ -RC_RETURN RCI2OSendPacket(struct net_device *dev, - U32 context, - PRCTCB pTransactionCtrlBlock); - + ** RCI2OSendPacket() + ** + ** Send user's ethernet packet from a locked page buffer. + ** Packet must have full MAC header, however without a CRC. + ** Initiator context is a user provided value that is returned + ** to the TransmitCallbackFunction when packet buffer is free. + ** Transmit buffer are considered owned by the adapter until context's + ** returned to user through the TransmitCallbackFunction. + */ +RC_RETURN RCI2OSendPacket (struct net_device *dev, + U32 context, PRCTCB pTransactionCtrlBlock); /* Ethernet Link Statistics structure */ -typedef struct tag_RC_link_stats -{ - U32 TX_good; /* good transmit frames */ - U32 TX_maxcol; /* frames not TX due to MAX collisions */ - U32 TX_latecol; /* frames not TX due to late collisions */ - U32 TX_urun; /* frames not TX due to DMA underrun */ - U32 TX_crs; /* frames TX with lost carrier sense */ - U32 TX_def; /* frames deferred due to activity on link */ - U32 TX_singlecol; /* frames TX with one and only on collision */ - U32 TX_multcol; /* frames TX with more than one collision */ - U32 TX_totcol; /* total collisions detected during TX */ - U32 Rcv_good; /* good frames received */ - U32 Rcv_CRCerr; /* frames RX and discarded with CRC errors */ - U32 Rcv_alignerr; /* frames RX with alignment and CRC errors */ - U32 Rcv_reserr; /* good frames discarded due to no RX buffer */ - U32 Rcv_orun; /* RX frames lost due to FIFO overrun */ - U32 Rcv_cdt; /* RX frames with collision during RX */ - U32 Rcv_runt; /* RX frames shorter than 64 bytes */ -} - RCLINKSTATS, *P_RCLINKSTATS; - - /* - ** RCGetLinkStatistics() - ** - ** Returns link statistics in user's structure at address StatsReturnAddr - ** If given, not NULL, the function WaitCallback is called during the wait - ** loop while waiting for the adapter to respond. - */ -RC_RETURN RCGetLinkStatistics(struct net_device *dev, - P_RCLINKSTATS StatsReturnAddr, - PFNWAITCALLBACK WaitCallback); +typedef struct tag_RC_link_stats { + U32 TX_good; /* good transmit frames */ + U32 TX_maxcol; /* frames not TX due to MAX collisions */ + U32 TX_latecol; /* frames not TX due to late collisions */ + U32 TX_urun; /* frames not TX due to DMA underrun */ + U32 TX_crs; /* frames TX with lost carrier sense */ + U32 TX_def; /* frames deferred due to activity on link */ + U32 TX_singlecol; /* frames TX with one and only on collision */ + U32 TX_multcol; /* frames TX with more than one collision */ + U32 TX_totcol; /* total collisions detected during TX */ + U32 Rcv_good; /* good frames received */ + U32 Rcv_CRCerr; /* frames RX and discarded with CRC errors */ + U32 Rcv_alignerr; /* frames RX with alignment and CRC errors */ + U32 Rcv_reserr; /* good frames discarded due to no RX buffer */ + U32 Rcv_orun; /* RX frames lost due to FIFO overrun */ + U32 Rcv_cdt; /* RX frames with collision during RX */ + U32 Rcv_runt; /* RX frames shorter than 64 bytes */ +} RCLINKSTATS, *P_RCLINKSTATS; + + /* + ** RCGetLinkStatistics() + ** + ** Returns link statistics in user's structure at address StatsReturnAddr + ** If given, not NULL, the function WaitCallback is called during the wait + ** loop while waiting for the adapter to respond. + */ +RC_RETURN RCGetLinkStatistics (struct net_device *dev, + P_RCLINKSTATS StatsReturnAddr, + PFNWAITCALLBACK WaitCallback); + + /* + ** RCGetLinkStatus() + ** + ** Return link status, up or down, to user's location addressed by ReturnAddr. + ** If given, not NULL, the function WaitCallback is called during the wait + ** loop while waiting for the adapter to respond. + */ +RC_RETURN RCGetLinkStatus (struct net_device *dev, + PU32 pReturnStatus, PFNWAITCALLBACK WaitCallback); - /* - ** RCGetLinkStatus() - ** - ** Return link status, up or down, to user's location addressed by ReturnAddr. - ** If given, not NULL, the function WaitCallback is called during the wait - ** loop while waiting for the adapter to respond. - */ -RC_RETURN RCGetLinkStatus(struct net_device *dev, - PU32 pReturnStatus, - PFNWAITCALLBACK WaitCallback); - /* Link Status defines - value returned in pReturnStatus */ #define RC_LAN_LINK_STATUS_DOWN 0 #define RC_LAN_LINK_STATUS_UP 1 /* - ** RCGetMAC() - ** - ** Get the current MAC address assigned to user. RedCreek Ravlin 45/PCI - ** has two MAC addresses. One which is private to the PCI Card, and - ** another MAC which is given to the user as its link layer MAC address. The - ** adapter runs in promiscous mode because of the dual address requirement. - ** The MAC address is returned to the unsigned char array pointer to by mac. - */ -RC_RETURN RCGetMAC(struct net_device *dev, PFNWAITCALLBACK WaitCallback); - - /* - ** RCSetMAC() - ** - ** Set a new user port MAC address. This address will be returned on - ** subsequent RCGetMAC() calls. - */ -RC_RETURN RCSetMAC(struct net_device *dev, PU8 mac); - - /* - ** RCSetLinkSpeed() - ** - ** set adapter's link speed based on given input code. - */ -RC_RETURN RCSetLinkSpeed(struct net_device *dev, U16 LinkSpeedCode); + ** RCGetMAC() + ** + ** Get the current MAC address assigned to user. RedCreek Ravlin 45/PCI + ** has two MAC addresses. One which is private to the PCI Card, and + ** another MAC which is given to the user as its link layer MAC address. The + ** adapter runs in promiscous mode because of the dual address requirement. + ** The MAC address is returned to the unsigned char array pointer to by mac. + */ +RC_RETURN RCGetMAC (struct net_device *dev, PFNWAITCALLBACK WaitCallback); + + /* + ** RCSetMAC() + ** + ** Set a new user port MAC address. This address will be returned on + ** subsequent RCGetMAC() calls. + */ +RC_RETURN RCSetMAC (struct net_device *dev, PU8 mac); + + /* + ** RCSetLinkSpeed() + ** + ** set adapter's link speed based on given input code. + */ +RC_RETURN RCSetLinkSpeed (struct net_device *dev, U16 LinkSpeedCode); /* Set link speed codes */ #define LNK_SPD_AUTO_NEG_NWAY 0 #define LNK_SPD_100MB_FULL 1 @@ -564,14 +540,11 @@ #define LNK_SPD_10MB_FULL 3 #define LNK_SPD_10MB_HALF 4 - - - /* - ** RCGetLinkSpeed() - ** - ** Return link speed code. - */ + ** RCGetLinkSpeed() + ** + ** Return link speed code. + */ /* Return link speed codes */ #define LNK_SPD_UNKNOWN 0 #define LNK_SPD_100MB_FULL 1 @@ -580,7 +553,8 @@ #define LNK_SPD_10MB_HALF 4 RC_RETURN -RCGetLinkSpeed(struct net_device *dev, PU32 pLinkSpeedCode, PFNWAITCALLBACK WaitCallback); +RCGetLinkSpeed (struct net_device *dev, PU32 pLinkSpeedCode, + PFNWAITCALLBACK WaitCallback); /* ** ========================================================================= ** RCSetPromiscuousMode(struct net_device *dev, U16 Mode) @@ -593,8 +567,7 @@ */ #define PROMISCUOUS_MODE_OFF 0 #define PROMISCUOUS_MODE_ON 1 -RC_RETURN -RCSetPromiscuousMode(struct net_device *dev, U16 Mode); +RC_RETURN RCSetPromiscuousMode (struct net_device *dev, U16 Mode); /* ** ========================================================================= ** RCGetPromiscuousMode(struct net_device *dev, PU32 pMode, PFNWAITCALLBACK WaitCallback) @@ -608,7 +581,8 @@ ** ========================================================================= */ RC_RETURN -RCGetPromiscuousMode(struct net_device *dev, PU32 pMode, PFNWAITCALLBACK WaitCallback); +RCGetPromiscuousMode (struct net_device *dev, PU32 pMode, + PFNWAITCALLBACK WaitCallback); /* ** ========================================================================= @@ -622,8 +596,7 @@ */ #define BROADCAST_MODE_OFF 0 #define BROADCAST_MODE_ON 1 -RC_RETURN -RCSetBroadcastMode(struct net_device *dev, U16 Mode); +RC_RETURN RCSetBroadcastMode (struct net_device *dev, U16 Mode); /* ** ========================================================================= ** RCGetBroadcastMode(struct net_device *dev, PU32 pMode, PFNWAITCALLBACK WaitCallback) @@ -637,7 +610,8 @@ ** ========================================================================= */ RC_RETURN -RCGetBroadcastMode(struct net_device *dev, PU32 pMode, PFNWAITCALLBACK WaitCallback); +RCGetBroadcastMode (struct net_device *dev, PU32 pMode, + PFNWAITCALLBACK WaitCallback); /* ** ========================================================================= ** RCReportDriverCapability(struct net_device *dev, U32 capability) @@ -647,8 +621,7 @@ ** ** ========================================================================= */ -RC_RETURN -RCReportDriverCapability(struct net_device *dev, U32 capability); +RC_RETURN RCReportDriverCapability (struct net_device *dev, U32 capability); /* ** RCGetFirmwareVer() @@ -658,7 +631,8 @@ ** WARNING: user's space pointed to by pFirmString should be at least 60 bytes. */ RC_RETURN -RCGetFirmwareVer(struct net_device *dev, PU8 pFirmString, PFNWAITCALLBACK WaitCallback); +RCGetFirmwareVer (struct net_device *dev, PU8 pFirmString, + PFNWAITCALLBACK WaitCallback); /* ** ---------------------------------------------- @@ -666,61 +640,61 @@ ** ---------------------------------------------- */ /* resource flag bit assignments for RCResetLANCard() & RCShutdownLANCard() */ -#define RC_RESOURCE_RETURN_POSTED_RX_BUCKETS 0x0001 +#define RC_RESOURCE_RETURN_POSTED_RX_BUCKETS 0x0001 #define RC_RESOURCE_RETURN_PEND_TX_BUFFERS 0x0002 /* - ** RCResetLANCard() - ** - ** Reset LAN card operation. Causes a software reset of the ethernet - ** controller and restarts the command and receive units. Depending on - ** the ResourceFlags given, the buffers are either returned to the - ** host with reply status of I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER and - ** detailed status of I2O_LAN_DSC_CANCELED (new receive buffers must be - ** posted after issuing this) OR the buffers are kept and reused by - ** the ethernet controller. If CallbackFunction is not NULL, the function - ** will be called when the reset is complete. If the CallbackFunction is - ** NULL,a 1 will be put into the ReturnAddr after waiting for the reset - ** to complete (please disable I2O interrupts during this method). - ** Any outstanding transmit or receive buffers that are complete will be - ** returned via the normal reply messages before the requested resource - ** buffers are returned. - ** A call to RCPostRecvBuffers() is needed to return the ethernet to full - ** operation if the receive buffers were returned during LANReset. - ** Note: The IOP status is not affected by a LAN reset. - */ -RC_RETURN RCResetLANCard(struct net_device *dev, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction); - + ** RCResetLANCard() + ** + ** Reset LAN card operation. Causes a software reset of the ethernet + ** controller and restarts the command and receive units. Depending on + ** the ResourceFlags given, the buffers are either returned to the + ** host with reply status of I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER and + ** detailed status of I2O_LAN_DSC_CANCELED (new receive buffers must be + ** posted after issuing this) OR the buffers are kept and reused by + ** the ethernet controller. If CallbackFunction is not NULL, the function + ** will be called when the reset is complete. If the CallbackFunction is + ** NULL,a 1 will be put into the ReturnAddr after waiting for the reset + ** to complete (please disable I2O interrupts during this method). + ** Any outstanding transmit or receive buffers that are complete will be + ** returned via the normal reply messages before the requested resource + ** buffers are returned. + ** A call to RCPostRecvBuffers() is needed to return the ethernet to full + ** operation if the receive buffers were returned during LANReset. + ** Note: The IOP status is not affected by a LAN reset. + */ +RC_RETURN RCResetLANCard (struct net_device *dev, U16 ResourceFlags, + PU32 ReturnAddr, PFNCALLBACK CallbackFunction); + + /* + ** RCShutdownLANCard() + ** + ** Shutdown LAN card operation and put into an idle (suspended) state. + ** The LAN card is restarted with RCResetLANCard() function. + ** Depending on the ResourceFlags given, the buffers are either returned + ** to the host with reply status of I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER + ** and detailed status of I2O_LAN_DSC_CANCELED (new receive buffers must be + ** posted after issuing this) OR the buffers are kept and reused by + ** the ethernet controller. If CallbackFunction is not NULL, the function + ** will be called when the reset is complete. If the CallbackFunction is + ** NULL,a 1 will be put into the ReturnAddr after waiting for the reset + ** to complete (please disable I2O interrupts during this method). + ** Any outstanding transmit or receive buffers that are complete will be + ** returned via the normal reply messages before the requested resource + ** buffers are returned. + ** Note: The IOP status is not affected by a LAN shutdown. + */ +RC_RETURN +RCShutdownLANCard (struct net_device *dev, U16 ResourceFlags, PU32 ReturnAddr, + PFNCALLBACK CallbackFunction); /* - ** RCShutdownLANCard() - ** - ** Shutdown LAN card operation and put into an idle (suspended) state. - ** The LAN card is restarted with RCResetLANCard() function. - ** Depending on the ResourceFlags given, the buffers are either returned - ** to the host with reply status of I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER - ** and detailed status of I2O_LAN_DSC_CANCELED (new receive buffers must be - ** posted after issuing this) OR the buffers are kept and reused by - ** the ethernet controller. If CallbackFunction is not NULL, the function - ** will be called when the reset is complete. If the CallbackFunction is - ** NULL,a 1 will be put into the ReturnAddr after waiting for the reset - ** to complete (please disable I2O interrupts during this method). - ** Any outstanding transmit or receive buffers that are complete will be - ** returned via the normal reply messages before the requested resource - ** buffers are returned. - ** Note: The IOP status is not affected by a LAN shutdown. - */ -RC_RETURN -RCShutdownLANCard(struct net_device *dev, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction); - - /* - ** RCResetIOP(); - ** Initializes IOPState to I2O_IOP_STATE_RESET. - ** Stops access to outbound message Q. - ** Discards any outstanding transmit or posted receive buffers. - ** Clears outbound message Q. - */ -RC_RETURN -RCResetIOP(struct net_device *dev); + ** RCResetIOP(); + ** Initializes IOPState to I2O_IOP_STATE_RESET. + ** Stops access to outbound message Q. + ** Discards any outstanding transmit or posted receive buffers. + ** Clears outbound message Q. + */ +RC_RETURN RCResetIOP (struct net_device *dev); -#endif /* RCLANMTL_H */ +#endif /* RCLANMTL_H */ diff -u --recursive --new-file v2.4.5/linux/drivers/net/rcpci45.c linux/drivers/net/rcpci45.c --- v2.4.5/linux/drivers/net/rcpci45.c Thu Apr 12 12:15:25 2001 +++ linux/drivers/net/rcpci45.c Mon Jul 2 14:03:04 2001 @@ -57,14 +57,12 @@ #include #include #include -#include /* For NR_IRQS only. */ +#include /* For NR_IRQS only. */ #include #include - - static char version[] __initdata = -"RedCreek Communications PCI linux driver version 2.03\n"; + "RedCreek Communications PCI linux driver version 2.03\n"; #define RC_LINUX_MODULE #include "rclanmtl.h" @@ -78,339 +76,349 @@ #define RC_PCI45_VENDOR_ID 0x4916 #define RC_PCI45_DEVICE_ID 0x1960 -#define MAX_ETHER_SIZE 1520 +#define MAX_ETHER_SIZE 1520 #define MAX_NMBR_RCV_BUFFERS 96 #define RC_POSTED_BUFFERS_LOW_MARK MAX_NMBR_RCV_BUFFERS-16 -#define BD_SIZE 3 /* Bucket Descriptor size */ -#define BD_LEN_OFFSET 2 /* Bucket Descriptor offset to length field */ - +#define BD_SIZE 3 /* Bucket Descriptor size */ +#define BD_LEN_OFFSET 2 /* Bucket Descriptor offset to length field */ /* RedCreek LAN device Target ID */ -#define RC_LAN_TARGET_ID 0x10 +#define RC_LAN_TARGET_ID 0x10 /* RedCreek's OSM default LAN receive Initiator */ -#define DEFAULT_RECV_INIT_CONTEXT 0xA17 - +#define DEFAULT_RECV_INIT_CONTEXT 0xA17 static U32 DriverControlWord; -static void rc_timer(unsigned long); - -static int RCinit(struct net_device *); +static void rc_timer (unsigned long); -static int RCopen(struct net_device *); -static int RC_xmit_packet(struct sk_buff *, struct net_device *); -static void RCinterrupt(int, void *, struct pt_regs *); -static int RCclose(struct net_device *dev); -static struct net_device_stats *RCget_stats(struct net_device *); -static int RCioctl(struct net_device *, struct ifreq *, int); -static int RCconfig(struct net_device *, struct ifmap *); -static void RCxmit_callback(U32, U16, PU32, struct net_device *); -static void RCrecv_callback(U32, U8, U32, PU32, struct net_device *); -static void RCreset_callback(U32, U32, U32, struct net_device *); -static void RCreboot_callback(U32, U32, U32, struct net_device *); -static int RC_allocate_and_post_buffers(struct net_device *, int); +static int RCinit (struct net_device *); +static int RCopen (struct net_device *); +static int RC_xmit_packet (struct sk_buff *, struct net_device *); +static void RCinterrupt (int, void *, struct pt_regs *); +static int RCclose (struct net_device *dev); +static struct net_device_stats *RCget_stats (struct net_device *); +static int RCioctl (struct net_device *, struct ifreq *, int); +static int RCconfig (struct net_device *, struct ifmap *); +static void RCxmit_callback (U32, U16, PU32, struct net_device *); +static void RCrecv_callback (U32, U8, U32, PU32, struct net_device *); +static void RCreset_callback (U32, U32, U32, struct net_device *); +static void RCreboot_callback (U32, U32, U32, struct net_device *); +static int RC_allocate_and_post_buffers (struct net_device *, int); static struct pci_device_id rcpci45_pci_table[] __devinitdata = { - { RC_PCI45_VENDOR_ID, RC_PCI45_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, }, - { } + {RC_PCI45_VENDOR_ID, RC_PCI45_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, + {} }; -MODULE_DEVICE_TABLE(pci, rcpci45_pci_table); +MODULE_DEVICE_TABLE (pci, rcpci45_pci_table); -static void __exit rcpci45_remove_one(struct pci_dev *pdev) +static void __exit +rcpci45_remove_one (struct pci_dev *pdev) { - struct net_device *dev = pci_get_drvdata(pdev); + struct net_device *dev = pci_get_drvdata (pdev); PDPA pDpa = dev->priv; - if (!dev) { - printk (KERN_ERR "(rcpci45 driver:) remove non-existent device\n"); - return; - } + if (!dev) { + printk (KERN_ERR + "(rcpci45 driver:) remove non-existent device\n"); + return; + } - dprintk("remove_one: IOP reset: 0x%x\n", RCResetIOP(dev)); + dprintk ("remove_one: IOP reset: 0x%x\n", RCResetIOP (dev)); /* RAA Inspired by starfire.c and yellowfin.c we keep these * here. */ - unregister_netdev(dev); - free_irq(dev->irq, dev); - iounmap((void *)dev->base_addr); - pci_release_regions(pdev); - kfree(pDpa->PLanApiPA); - kfree(pDpa->pPab); - kfree(pDpa); - kfree(dev); - pci_set_drvdata(pdev, NULL); + unregister_netdev (dev); + free_irq (dev->irq, dev); + iounmap ((void *) dev->base_addr); + pci_release_regions (pdev); + kfree (pDpa->PLanApiPA); + kfree (pDpa->pPab); + kfree (pDpa); + kfree (dev); + pci_set_drvdata (pdev, NULL); } -static int RCinit(struct net_device *dev) +static int +RCinit (struct net_device *dev) { - dev->open = &RCopen; - dev->hard_start_xmit = &RC_xmit_packet; - dev->stop = &RCclose; - dev->get_stats = &RCget_stats; - dev->do_ioctl = &RCioctl; - dev->set_config = &RCconfig; - return 0; + dev->open = &RCopen; + dev->hard_start_xmit = &RC_xmit_packet; + dev->stop = &RCclose; + dev->get_stats = &RCget_stats; + dev->do_ioctl = &RCioctl; + dev->set_config = &RCconfig; + return 0; } -static int rcpci45_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int +rcpci45_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { - unsigned long *vaddr; - PDPA pDpa; - int error; - static int card_idx = -1; - struct net_device *dev; - unsigned long pci_start, pci_len; - - card_idx++; - - /* - * Allocate and fill new device structure. - * We need enough for struct net_device plus DPA plus the LAN API private - * area, which requires a minimum of 16KB. The top of the allocated - * area will be assigned to struct net_device; the next chunk will be - * assigned to DPA; and finally, the rest will be assigned to the - * the LAN API layer. - */ - - dev = init_etherdev(NULL, sizeof(*pDpa)); - if (!dev) { - printk(KERN_ERR "(rcpci45 driver:) unable to allocate in init_etherdev\n"); - error = -ENOMEM; - goto err_out; - } - - error = pci_enable_device(pdev); - if (error) { - printk(KERN_ERR "(rcpci45 driver:) %d: unable to enable pci device, aborting\n",card_idx); - goto err_out; - } - error = -ENOMEM; - pci_start = pci_resource_start(pdev,0); - pci_len = pci_resource_len(pdev,0); - - pci_set_drvdata(pdev, dev); - - pDpa = dev->priv; - pDpa->id = card_idx; - pDpa->pci_addr = pci_start; - - if (!pci_start || !(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - printk(KERN_ERR "(rcpci45 driver:) No PCI memory resources! Aborting.\n"); - error = -EBUSY; - goto err_out_free_dev; - } - - /* - * Save the starting address of the LAN API private area. We'll - * pass that to RCInitI2OMsgLayer(). - */ - /* RAA FIXME: This size should be a #define somewhere after I - * clear up some questions: What flags are neeeded in the alloc below - * and what needs to be done before the memarea is long word aligned? - * (Look in old code for an approach.) (Also note that the 16K below - * is substantially less than the 32K allocated before (even though - * some of the spacce was used for data structures.) */ - pDpa->msgbuf = kmalloc(16384, GFP_KERNEL); - if (!pDpa->msgbuf) { - printk(KERN_ERR "(rcpci45 driver:) Could not allocate %d byte memory for the private msgbuf!\n", 16384); /* RAA FIXME not hardcoded! */ - goto err_out_free_dev; - } - pDpa->PLanApiPA = (void *)(((long)pDpa->msgbuf + 0xff) & ~0xff); - - dprintk("pDpa->PLanApiPA = 0x%x\n", (uint)pDpa->PLanApiPA); - - /* The adapter is accessible through memory-access read/write, not - * I/O read/write. Thus, we need to map it to some virtual address - * area in order to access the registers as normal memory. - */ - error = pci_request_regions(pdev, dev->name); - if (error) - goto err_out_free_msgbuf; - - vaddr = (ulong *) ioremap (pci_start, pci_len); - if (!vaddr) { - printk(KERN_ERR "(rcpci45 driver:) Unable to remap address range from %lu to %lu\n", pci_start, pci_start+pci_len); - goto err_out_free_region; - } - - dprintk("rcpci45_init_one: 0x%x, priv = 0x%x, vaddr = 0x%x\n", - (uint)dev, (uint)dev->priv, (uint)vaddr); - dev->base_addr = (unsigned long)vaddr; - dev->irq = pdev->irq; - - dev->init = &RCinit; - - return 0; /* success */ - - err_out_free_region: - pci_release_regions(pdev); - err_out_free_msgbuf: - kfree(pDpa->msgbuf); - err_out_free_dev: - unregister_netdev(dev); - kfree(dev); - err_out: - card_idx--; - return error; + unsigned long *vaddr; + PDPA pDpa; + int error; + static int card_idx = -1; + struct net_device *dev; + unsigned long pci_start, pci_len; + + card_idx++; + + /* + * Allocate and fill new device structure. + * We need enough for struct net_device plus DPA plus the LAN API private + * area, which requires a minimum of 16KB. The top of the allocated + * area will be assigned to struct net_device; the next chunk will be + * assigned to DPA; and finally, the rest will be assigned to the + * the LAN API layer. + */ + + dev = init_etherdev (NULL, sizeof (*pDpa)); + if (!dev) { + printk (KERN_ERR + "(rcpci45 driver:) unable to allocate in init_etherdev\n"); + error = -ENOMEM; + goto err_out; + } + + error = pci_enable_device (pdev); + if (error) { + printk (KERN_ERR + "(rcpci45 driver:) %d: unable to enable pci device, aborting\n", + card_idx); + goto err_out; + } + error = -ENOMEM; + pci_start = pci_resource_start (pdev, 0); + pci_len = pci_resource_len (pdev, 0); + + pci_set_drvdata (pdev, dev); + + pDpa = dev->priv; + pDpa->id = card_idx; + pDpa->pci_addr = pci_start; + + if (!pci_start || !(pci_resource_flags (pdev, 0) & IORESOURCE_MEM)) { + printk (KERN_ERR + "(rcpci45 driver:) No PCI memory resources! Aborting.\n"); + error = -EBUSY; + goto err_out_free_dev; + } + + /* + * Save the starting address of the LAN API private area. We'll + * pass that to RCInitI2OMsgLayer(). + */ + /* RAA FIXME: This size should be a #define somewhere after I + * clear up some questions: What flags are neeeded in the alloc below + * and what needs to be done before the memarea is long word aligned? + * (Look in old code for an approach.) (Also note that the 16K below + * is substantially less than the 32K allocated before (even though + * some of the spacce was used for data structures.) */ + pDpa->msgbuf = kmalloc (16384, GFP_KERNEL); + if (!pDpa->msgbuf) { + printk (KERN_ERR "(rcpci45 driver:) Could not allocate %d byte memory for the private msgbuf!\n", 16384); /* RAA FIXME not hardcoded! */ + goto err_out_free_dev; + } + pDpa->PLanApiPA = (void *) (((long) pDpa->msgbuf + 0xff) & ~0xff); + + dprintk ("pDpa->PLanApiPA = 0x%x\n", (uint) pDpa->PLanApiPA); + + /* The adapter is accessible through memory-access read/write, not + * I/O read/write. Thus, we need to map it to some virtual address + * area in order to access the registers as normal memory. + */ + error = pci_request_regions (pdev, dev->name); + if (error) + goto err_out_free_msgbuf; + + vaddr = (ulong *) ioremap (pci_start, pci_len); + if (!vaddr) { + printk (KERN_ERR + "(rcpci45 driver:) Unable to remap address range from %lu to %lu\n", + pci_start, pci_start + pci_len); + goto err_out_free_region; + } + + dprintk ("rcpci45_init_one: 0x%x, priv = 0x%x, vaddr = 0x%x\n", + (uint) dev, (uint) dev->priv, (uint) vaddr); + dev->base_addr = (unsigned long) vaddr; + dev->irq = pdev->irq; + + dev->init = &RCinit; + + return 0; /* success */ + +err_out_free_region: + pci_release_regions (pdev); +err_out_free_msgbuf: + kfree (pDpa->msgbuf); +err_out_free_dev: + unregister_netdev (dev); + kfree (dev); +err_out: + card_idx--; + return error; } static struct pci_driver rcpci45_driver = { - name: "rcpci45", - id_table: rcpci45_pci_table, - probe: rcpci45_init_one, - remove: rcpci45_remove_one, + name: "rcpci45", + id_table: rcpci45_pci_table, + probe: rcpci45_init_one, + remove: rcpci45_remove_one, }; -static int __init rcpci_init_module(void) +static int __init +rcpci_init_module (void) { - int rc = pci_module_init(&rcpci45_driver); + int rc = pci_module_init (&rcpci45_driver); if (!rc) - printk(KERN_INFO "%s",version); + printk (KERN_INFO "%s", version); return rc; } static int -RCopen(struct net_device *dev) +RCopen (struct net_device *dev) { - int post_buffers = MAX_NMBR_RCV_BUFFERS; - PDPA pDpa = dev->priv; - int count = 0; - int requested = 0; - int error; - - dprintk("(rcpci45 driver:) RCopen\n"); - - /* Request a shared interrupt line. */ - error=request_irq(dev->irq, RCinterrupt, SA_SHIRQ, dev->name, dev); - if (error) { - printk(KERN_ERR "(rcpci45 driver:) %s: unable to get IRQ %d\n", dev->name, dev->irq ); - goto err_out; - } - - error = RCInitI2OMsgLayer(dev, (PFNTXCALLBACK)RCxmit_callback, - (PFNRXCALLBACK)RCrecv_callback, - (PFNCALLBACK)RCreboot_callback); - if (error) { - printk(KERN_ERR "(rcpci45 driver:) Unable to initialize msg layer\n"); - goto err_out_free_irq; - } - if ( (error=RCGetMAC(dev, NULL)) ) { - printk(KERN_ERR "(rcpci45 driver:) Unable to get adapter MAC\n"); - goto err_out_free_irq; - } - - DriverControlWord |= WARM_REBOOT_CAPABLE; - RCReportDriverCapability(dev, DriverControlWord); - - printk(KERN_INFO "%s: RedCreek Communications IPSEC VPN adapter\n", - dev->name); - - - /* RAA: Old RCopen starts here */ - RCEnableI2OInterrupts(dev); - - /* RAA Hmm, how does the comment below jibe with the newly imported - * code above? A FIXME!!*/ - if (pDpa->nexus) { - /* This is not the first time RCopen is called. Thus, - * the interface was previously opened and later closed - * by RCclose(). RCclose() does a Shutdown; to wake up - * the adapter, a reset is mandatory before we can post - * receive buffers. However, if the adapter initiated - * a reboot while the interface was closed -- and interrupts - * were turned off -- we need will need to reinitialize - * the adapter, rather than simply waking it up. - */ - dprintk(KERN_INFO "Waking up adapter...\n"); - RCResetLANCard(dev,0,0,0); - } else - pDpa->nexus = 1; - - while(post_buffers) { - if (post_buffers > MAX_NMBR_POST_BUFFERS_PER_MSG) - requested = MAX_NMBR_POST_BUFFERS_PER_MSG; - else - requested = post_buffers; - count = RC_allocate_and_post_buffers(dev, requested); - - if ( count < requested ) - { - /* - * Check to see if we were able to post any buffers at all. - */ - if (post_buffers == MAX_NMBR_RCV_BUFFERS) { - printk(KERN_ERR "(rcpci45 driver:) Error RCopen: not able to allocate any buffers\r\n"); - return(-ENOMEM); - } - printk(KERN_WARNING "(rcpci45 driver:) Warning RCopen: not able to allocate all requested buffers\r\n"); - break; /* we'll try to post more buffers later */ - } else - post_buffers -= count; - } - pDpa->numOutRcvBuffers = MAX_NMBR_RCV_BUFFERS - post_buffers; - pDpa->shutdown = 0; /* just in case */ - dprintk("RCopen: posted %d buffers\n", (uint)pDpa->numOutRcvBuffers); - MOD_INC_USE_COUNT; - netif_start_queue(dev); - return 0; - - err_out_free_irq: - free_irq(dev->irq, dev); - err_out: - return error; + int post_buffers = MAX_NMBR_RCV_BUFFERS; + PDPA pDpa = dev->priv; + int count = 0; + int requested = 0; + int error; + + dprintk ("(rcpci45 driver:) RCopen\n"); + + /* Request a shared interrupt line. */ + error = request_irq (dev->irq, RCinterrupt, SA_SHIRQ, dev->name, dev); + if (error) { + printk (KERN_ERR "(rcpci45 driver:) %s: unable to get IRQ %d\n", + dev->name, dev->irq); + goto err_out; + } + + error = RCInitI2OMsgLayer (dev, (PFNTXCALLBACK) RCxmit_callback, + (PFNRXCALLBACK) RCrecv_callback, + (PFNCALLBACK) RCreboot_callback); + if (error) { + printk (KERN_ERR + "(rcpci45 driver:) Unable to initialize msg layer\n"); + goto err_out_free_irq; + } + if ((error = RCGetMAC (dev, NULL))) { + printk (KERN_ERR + "(rcpci45 driver:) Unable to get adapter MAC\n"); + goto err_out_free_irq; + } + + DriverControlWord |= WARM_REBOOT_CAPABLE; + RCReportDriverCapability (dev, DriverControlWord); + + printk (KERN_INFO "%s: RedCreek Communications IPSEC VPN adapter\n", + dev->name); + + /* RAA: Old RCopen starts here */ + RCEnableI2OInterrupts (dev); + + /* RAA Hmm, how does the comment below jibe with the newly imported + * code above? A FIXME!!*/ + if (pDpa->nexus) { + /* This is not the first time RCopen is called. Thus, + * the interface was previously opened and later closed + * by RCclose(). RCclose() does a Shutdown; to wake up + * the adapter, a reset is mandatory before we can post + * receive buffers. However, if the adapter initiated + * a reboot while the interface was closed -- and interrupts + * were turned off -- we need will need to reinitialize + * the adapter, rather than simply waking it up. + */ + dprintk (KERN_INFO "Waking up adapter...\n"); + RCResetLANCard (dev, 0, 0, 0); + } else + pDpa->nexus = 1; + + while (post_buffers) { + if (post_buffers > MAX_NMBR_POST_BUFFERS_PER_MSG) + requested = MAX_NMBR_POST_BUFFERS_PER_MSG; + else + requested = post_buffers; + count = RC_allocate_and_post_buffers (dev, requested); + + if (count < requested) { + /* + * Check to see if we were able to post any buffers at all. + */ + if (post_buffers == MAX_NMBR_RCV_BUFFERS) { + printk (KERN_ERR + "(rcpci45 driver:) Error RCopen: not able to allocate any buffers\r\n"); + return (-ENOMEM); + } + printk (KERN_WARNING + "(rcpci45 driver:) Warning RCopen: not able to allocate all requested buffers\r\n"); + break; /* we'll try to post more buffers later */ + } else + post_buffers -= count; + } + pDpa->numOutRcvBuffers = MAX_NMBR_RCV_BUFFERS - post_buffers; + pDpa->shutdown = 0; /* just in case */ + dprintk ("RCopen: posted %d buffers\n", (uint) pDpa->numOutRcvBuffers); + MOD_INC_USE_COUNT; + netif_start_queue (dev); + return 0; + +err_out_free_irq: + free_irq (dev->irq, dev); +err_out: + return error; } static int -RC_xmit_packet(struct sk_buff *skb, struct net_device *dev) +RC_xmit_packet (struct sk_buff *skb, struct net_device *dev) { - PDPA pDpa = dev->priv; - singleTCB tcb; - psingleTCB ptcb = &tcb; - RC_RETURN status = 0; - - netif_stop_queue(dev); - - if (pDpa->shutdown || pDpa->reboot) { - dprintk("RC_xmit_packet: tbusy!\n"); - return 1; - } - - /* - * The user is free to reuse the TCB after RCI2OSendPacket() returns, since - * the function copies the necessary info into its own private space. Thus, - * our TCB can be a local structure. The skb, on the other hand, will be - * freed up in our interrupt handler. - */ - - ptcb->bcount = 1; - - /* - * we'll get the context when the adapter interrupts us to tell us that - * the transmission is done. At that time, we can free skb. - */ - ptcb->b.context = (U32)skb; - ptcb->b.scount = 1; - ptcb->b.size = skb->len; - ptcb->b.addr = virt_to_bus((void *)skb->data); - - dprintk("RC xmit: skb = 0x%x, pDpa = 0x%x, id = %d, ptcb = 0x%x\n", - (uint)skb, (uint)pDpa, (uint)pDpa->id, (uint)ptcb); - if ( (status = RCI2OSendPacket(dev, (U32)NULL, (PRCTCB)ptcb)) - != RC_RTN_NO_ERROR) { - dprintk("RC send error 0x%x\n", (uint)status); - return 1; - } else { - dev->trans_start = jiffies; - netif_wake_queue(dev); - } - /* - * That's it! - */ - return 0; + PDPA pDpa = dev->priv; + singleTCB tcb; + psingleTCB ptcb = &tcb; + RC_RETURN status = 0; + + netif_stop_queue (dev); + + if (pDpa->shutdown || pDpa->reboot) { + dprintk ("RC_xmit_packet: tbusy!\n"); + return 1; + } + + /* + * The user is free to reuse the TCB after RCI2OSendPacket() returns, since + * the function copies the necessary info into its own private space. Thus, + * our TCB can be a local structure. The skb, on the other hand, will be + * freed up in our interrupt handler. + */ + + ptcb->bcount = 1; + + /* + * we'll get the context when the adapter interrupts us to tell us that + * the transmission is done. At that time, we can free skb. + */ + ptcb->b.context = (U32) skb; + ptcb->b.scount = 1; + ptcb->b.size = skb->len; + ptcb->b.addr = virt_to_bus ((void *) skb->data); + + dprintk ("RC xmit: skb = 0x%x, pDpa = 0x%x, id = %d, ptcb = 0x%x\n", + (uint) skb, (uint) pDpa, (uint) pDpa->id, (uint) ptcb); + if ((status = RCI2OSendPacket (dev, (U32) NULL, (PRCTCB) ptcb)) + != RC_RTN_NO_ERROR) { + dprintk ("RC send error 0x%x\n", (uint) status); + return 1; + } else { + dev->trans_start = jiffies; + netif_wake_queue (dev); + } + /* + * That's it! + */ + return 0; } /* @@ -423,107 +431,110 @@ * RC_RESOURCE_RETURN_PEND_TX_BUFFERS flag. * All we need to do is free the buffers. */ -static void -RCxmit_callback(U32 Status, - U16 PcktCount, - PU32 BufferContext, - struct net_device *dev) +static void +RCxmit_callback (U32 Status, + U16 PcktCount, PU32 BufferContext, struct net_device *dev) { - struct sk_buff *skb; - PDPA pDpa = dev->priv; + struct sk_buff *skb; + PDPA pDpa = dev->priv; - if (!pDpa) { - printk(KERN_ERR "(rcpci45 driver:) Fatal error: xmit callback, !pDpa\n"); - return; - } + if (!pDpa) { + printk (KERN_ERR + "(rcpci45 driver:) Fatal error: xmit callback, !pDpa\n"); + return; + } /* dprintk("xmit_callback: Status = 0x%x\n", (uint)Status); */ - if (Status != I2O_REPLY_STATUS_SUCCESS) - dprintk("xmit_callback: Status = 0x%x\n", (uint)Status); - if (pDpa->shutdown || pDpa->reboot) - dprintk("xmit callback: shutdown||reboot\n"); - - dprintk("xmit_callback: PcktCount = %d, BC = 0x%x\n", - (uint)PcktCount, (uint)BufferContext); - - while (PcktCount--) { - skb = (struct sk_buff *)(BufferContext[0]); - dprintk("skb = 0x%x\n", (uint)skb); - BufferContext++; - dev_kfree_skb_irq(skb); - } - netif_wake_queue(dev); + if (Status != I2O_REPLY_STATUS_SUCCESS) + dprintk ("xmit_callback: Status = 0x%x\n", (uint) Status); + if (pDpa->shutdown || pDpa->reboot) + dprintk ("xmit callback: shutdown||reboot\n"); + + dprintk ("xmit_callback: PcktCount = %d, BC = 0x%x\n", + (uint) PcktCount, (uint) BufferContext); + + while (PcktCount--) { + skb = (struct sk_buff *) (BufferContext[0]); + dprintk ("skb = 0x%x\n", (uint) skb); + BufferContext++; + dev_kfree_skb_irq (skb); + } + netif_wake_queue (dev); } static void -RCreset_callback(U32 Status, U32 p1, U32 p2, struct net_device *dev) +RCreset_callback (U32 Status, U32 p1, U32 p2, struct net_device *dev) { - PDPA pDpa = dev->priv; - - dprintk("RCreset_callback Status 0x%x\n", (uint)Status); - /* - * Check to see why we were called. - */ - if (pDpa->shutdown) { - printk(KERN_INFO "(rcpci45 driver:) Shutting down interface\n"); - pDpa->shutdown = 0; - pDpa->reboot = 0; - MOD_DEC_USE_COUNT; - } else if (pDpa->reboot) { - printk(KERN_INFO "(rcpci45 driver:) reboot, shutdown adapter\n"); - /* - * We don't set any of the flags in RCShutdownLANCard() - * and we don't pass a callback routine to it. - * The adapter will have already initiated the reboot by - * the time the function returns. - */ - RCDisableI2OInterrupts(dev); - RCShutdownLANCard(dev,0,0,0); - printk(KERN_INFO "(rcpci45 driver:) scheduling timer...\n"); - init_timer(&pDpa->timer); - pDpa->timer.expires = RUN_AT((40*HZ)/10); /* 4 sec. */ - pDpa->timer.data = (unsigned long)dev; - pDpa->timer.function = &rc_timer; /* timer handler */ - add_timer(&pDpa->timer); - } + PDPA pDpa = dev->priv; + + dprintk ("RCreset_callback Status 0x%x\n", (uint) Status); + /* + * Check to see why we were called. + */ + if (pDpa->shutdown) { + printk (KERN_INFO + "(rcpci45 driver:) Shutting down interface\n"); + pDpa->shutdown = 0; + pDpa->reboot = 0; + MOD_DEC_USE_COUNT; + } else if (pDpa->reboot) { + printk (KERN_INFO + "(rcpci45 driver:) reboot, shutdown adapter\n"); + /* + * We don't set any of the flags in RCShutdownLANCard() + * and we don't pass a callback routine to it. + * The adapter will have already initiated the reboot by + * the time the function returns. + */ + RCDisableI2OInterrupts (dev); + RCShutdownLANCard (dev, 0, 0, 0); + printk (KERN_INFO "(rcpci45 driver:) scheduling timer...\n"); + init_timer (&pDpa->timer); + pDpa->timer.expires = RUN_AT ((40 * HZ) / 10); /* 4 sec. */ + pDpa->timer.data = (unsigned long) dev; + pDpa->timer.function = &rc_timer; /* timer handler */ + add_timer (&pDpa->timer); + } } static void -RCreboot_callback(U32 Status, U32 p1, U32 p2, struct net_device *dev) +RCreboot_callback (U32 Status, U32 p1, U32 p2, struct net_device *dev) { - PDPA pDpa = dev->priv; - - dprintk("RCreboot: rcv buffers outstanding = %d\n", - (uint)pDpa->numOutRcvBuffers); - - if (pDpa->shutdown) { - printk(KERN_INFO "(rcpci45 driver:) skipping reboot sequence -- shutdown already initiated\n"); - return; - } - pDpa->reboot = 1; - /* - * OK, we reset the adapter and ask it to return all - * outstanding transmit buffers as well as the posted - * receive buffers. When the adapter is done returning - * those buffers, it will call our RCreset_callback() - * routine. In that routine, we'll call RCShutdownLANCard() - * to tell the adapter that it's OK to start the reboot and - * schedule a timer callback routine to execute 3 seconds - * later; this routine will reinitialize the adapter at that time. - */ - RCResetLANCard(dev, RC_RESOURCE_RETURN_POSTED_RX_BUCKETS | - RC_RESOURCE_RETURN_PEND_TX_BUFFERS,0, - (PFNCALLBACK)RCreset_callback); -} + PDPA pDpa = dev->priv; + dprintk ("RCreboot: rcv buffers outstanding = %d\n", + (uint) pDpa->numOutRcvBuffers); -int broadcast_packet(unsigned char * address) + if (pDpa->shutdown) { + printk (KERN_INFO + "(rcpci45 driver:) skipping reboot sequence -- shutdown already initiated\n"); + return; + } + pDpa->reboot = 1; + /* + * OK, we reset the adapter and ask it to return all + * outstanding transmit buffers as well as the posted + * receive buffers. When the adapter is done returning + * those buffers, it will call our RCreset_callback() + * routine. In that routine, we'll call RCShutdownLANCard() + * to tell the adapter that it's OK to start the reboot and + * schedule a timer callback routine to execute 3 seconds + * later; this routine will reinitialize the adapter at that time. + */ + RCResetLANCard (dev, RC_RESOURCE_RETURN_POSTED_RX_BUCKETS | + RC_RESOURCE_RETURN_PEND_TX_BUFFERS, 0, + (PFNCALLBACK) RCreset_callback); +} + +int +broadcast_packet (unsigned char *address) { - int i; - for (i=0; i<6; i++) - if (address[i] != 0xff) return 0; + int i; + for (i = 0; i < 6; i++) + if (address[i] != 0xff) + return 0; - return 1; + return 1; } /* @@ -534,124 +545,119 @@ * filled (one ethernet packet per buffer). */ static void -RCrecv_callback(U32 Status, - U8 PktCount, - U32 BucketsRemain, - PU32 PacketDescBlock, - struct net_device *dev) +RCrecv_callback (U32 Status, + U8 PktCount, + U32 BucketsRemain, + PU32 PacketDescBlock, struct net_device *dev) { - U32 len, count; - PDPA pDpa = dev->priv; - struct sk_buff *skb; - singleTCB tcb; - psingleTCB ptcb = &tcb; - - - ptcb->bcount = 1; - - dprintk("RCrecv_callback: 0x%x, 0x%x, 0x%x\n", - (uint)PktCount, (uint)BucketsRemain, (uint)PacketDescBlock); - - if ((pDpa->shutdown || pDpa->reboot) && !Status) - dprintk("shutdown||reboot && !Status: PktCount = %d\n",PktCount); - - if ( (Status != I2O_REPLY_STATUS_SUCCESS) || pDpa->shutdown) - { - /* - * Free whatever buffers the adapter returned, but don't - * pass them to the kernel. - */ - - if (!pDpa->shutdown && !pDpa->reboot) - printk(KERN_INFO "(rcpci45 driver:) RCrecv error: status = 0x%x\n", (uint)Status); - else - dprintk("Returning %d buffers, status = 0x%x\n", - PktCount, (uint)Status); - /* - * TO DO: check the nature of the failure and put the adapter in - * failed mode if it's a hard failure. Send a reset to the adapter - * and free all outstanding memory. - */ - if (Status == I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER) - dprintk("RCrecv status ABORT NO DATA TRANSFER\n"); - - /* check for reset status: I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER */ - if (PacketDescBlock) - { - while(PktCount--) - { - skb = (struct sk_buff *)PacketDescBlock[0]; - dprintk("free skb 0x%p\n", skb); - dev_kfree_skb (skb); - pDpa->numOutRcvBuffers--; - PacketDescBlock += BD_SIZE; /* point to next context field */ - } - } - return; - } - else - { - while(PktCount--) - { - skb = (struct sk_buff *)PacketDescBlock[0]; - if (pDpa->shutdown) - dprintk("shutdown: skb=0x%x\n", (uint)skb); - - dprintk("skb = 0x%x: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", (uint)skb, - (uint)skb->data[0], (uint)skb->data[1], (uint)skb->data[2], - (uint)skb->data[3], (uint)skb->data[4], (uint)skb->data[5]); - -#ifdef PROMISCUOUS_BY_DEFAULT /* early 2.x firmware */ - if ( (memcmp(dev->dev_addr, skb->data, 6)) && - (!broadcast_packet(skb->data))) - { - /* - * Re-post the buffer to the adapter. Since the adapter usually - * return 1 to 2 receive buffers at a time, it's not too inefficient - * post one buffer at a time but ... may be that should be - * optimized at some point. - */ - ptcb->b.context = (U32)skb; - ptcb->b.scount = 1; - ptcb->b.size = MAX_ETHER_SIZE; - ptcb->b.addr = virt_to_bus((void *)skb->data); - - if ( RCPostRecvBuffers(dev, (PRCTCB)ptcb ) != RC_RTN_NO_ERROR) - { - printk(KERN_WARNING "(rcpci45 driver:) RCrecv_callback: post buffer failed!\n"); - dev_kfree_skb (skb); - } - else - pDpa->numOutRcvBuffers++; - } - else -#endif /* PROMISCUOUS_BY_DEFAULT */ - { - len = PacketDescBlock[2]; - skb->dev = dev; - skb_put( skb, len ); /* adjust length and tail */ - skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); /* send the packet to the kernel */ - dev->last_rx = jiffies; - } - pDpa->numOutRcvBuffers--; - PacketDescBlock += BD_SIZE; /* point to next context field */ - } - } - - /* - * Replenish the posted receive buffers. - * DO NOT replenish buffers if the driver has already - * initiated a reboot or shutdown! - */ - - if (!pDpa->shutdown && !pDpa->reboot) - { - count = RC_allocate_and_post_buffers(dev, - MAX_NMBR_RCV_BUFFERS-pDpa->numOutRcvBuffers); - pDpa->numOutRcvBuffers += count; - } + U32 len, count; + PDPA pDpa = dev->priv; + struct sk_buff *skb; + singleTCB tcb; + psingleTCB ptcb = &tcb; + + ptcb->bcount = 1; + + dprintk ("RCrecv_callback: 0x%x, 0x%x, 0x%x\n", + (uint) PktCount, (uint) BucketsRemain, (uint) PacketDescBlock); + + if ((pDpa->shutdown || pDpa->reboot) && !Status) + dprintk ("shutdown||reboot && !Status: PktCount = %d\n", + PktCount); + + if ((Status != I2O_REPLY_STATUS_SUCCESS) || pDpa->shutdown) { + /* + * Free whatever buffers the adapter returned, but don't + * pass them to the kernel. + */ + + if (!pDpa->shutdown && !pDpa->reboot) + printk (KERN_INFO + "(rcpci45 driver:) RCrecv error: status = 0x%x\n", + (uint) Status); + else + dprintk ("Returning %d buffers, status = 0x%x\n", + PktCount, (uint) Status); + /* + * TO DO: check the nature of the failure and put the adapter in + * failed mode if it's a hard failure. Send a reset to the adapter + * and free all outstanding memory. + */ + if (Status == I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER) + dprintk ("RCrecv status ABORT NO DATA TRANSFER\n"); + + /* check for reset status: I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER */ + if (PacketDescBlock) { + while (PktCount--) { + skb = (struct sk_buff *) PacketDescBlock[0]; + dprintk ("free skb 0x%p\n", skb); + dev_kfree_skb (skb); + pDpa->numOutRcvBuffers--; + PacketDescBlock += BD_SIZE; /* point to next context field */ + } + } + return; + } else { + while (PktCount--) { + skb = (struct sk_buff *) PacketDescBlock[0]; + if (pDpa->shutdown) + dprintk ("shutdown: skb=0x%x\n", (uint) skb); + + dprintk ("skb = 0x%x: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + (uint) skb, (uint) skb->data[0], + (uint) skb->data[1], (uint) skb->data[2], + (uint) skb->data[3], (uint) skb->data[4], + (uint) skb->data[5]); + +#ifdef PROMISCUOUS_BY_DEFAULT /* early 2.x firmware */ + if ((memcmp (dev->dev_addr, skb->data, 6)) && + (!broadcast_packet (skb->data))) { + /* + * Re-post the buffer to the adapter. Since the adapter usually + * return 1 to 2 receive buffers at a time, it's not too inefficient + * post one buffer at a time but ... may be that should be + * optimized at some point. + */ + ptcb->b.context = (U32) skb; + ptcb->b.scount = 1; + ptcb->b.size = MAX_ETHER_SIZE; + ptcb->b.addr = virt_to_bus ((void *) skb->data); + + if (RCPostRecvBuffers (dev, (PRCTCB) ptcb) != + RC_RTN_NO_ERROR) { + printk (KERN_WARNING + "(rcpci45 driver:) RCrecv_callback: post buffer failed!\n"); + dev_kfree_skb (skb); + } else + pDpa->numOutRcvBuffers++; + } else +#endif /* PROMISCUOUS_BY_DEFAULT */ + { + len = PacketDescBlock[2]; + skb->dev = dev; + skb_put (skb, len); /* adjust length and tail */ + skb->protocol = eth_type_trans (skb, dev); + netif_rx (skb); /* send the packet to the kernel */ + dev->last_rx = jiffies; + } + pDpa->numOutRcvBuffers--; + PacketDescBlock += BD_SIZE; /* point to next context field */ + } + } + + /* + * Replenish the posted receive buffers. + * DO NOT replenish buffers if the driver has already + * initiated a reboot or shutdown! + */ + + if (!pDpa->shutdown && !pDpa->reboot) { + count = RC_allocate_and_post_buffers (dev, + MAX_NMBR_RCV_BUFFERS - + pDpa->numOutRcvBuffers); + pDpa->numOutRcvBuffers += count; + } } @@ -663,474 +669,533 @@ * RCProcI2OMsgQ(), which in turn process the message and * calls one of our callback functions. */ -static void -RCinterrupt(int irq, void *dev_id, struct pt_regs *regs) +static void +RCinterrupt (int irq, void *dev_id, struct pt_regs *regs) { - PDPA pDpa; - struct net_device *dev = dev_id; + PDPA pDpa; + struct net_device *dev = dev_id; - pDpa = dev->priv; - - if (pDpa->shutdown) - dprintk("shutdown: service irq\n"); - - dprintk("RC irq: pDpa = 0x%x, dev = 0x%x, id = %d\n", - (uint)pDpa, (uint)dev, (uint)pDpa->id); - dprintk("dev = 0x%x\n", (uint)dev); + pDpa = dev->priv; - RCProcI2OMsgQ(dev); -} + if (pDpa->shutdown) + dprintk ("shutdown: service irq\n"); + + dprintk ("RC irq: pDpa = 0x%x, dev = 0x%x, id = %d\n", + (uint) pDpa, (uint) dev, (uint) pDpa->id); + dprintk ("dev = 0x%x\n", (uint) dev); + RCProcI2OMsgQ (dev); +} #define REBOOT_REINIT_RETRY_LIMIT 4 -static void rc_timer(unsigned long data) +static void +rc_timer (unsigned long data) { - struct net_device *dev = (struct net_device *)data; - PDPA pDpa = dev->priv; - int init_status; - static int retry; - int post_buffers = MAX_NMBR_RCV_BUFFERS; - int count = 0; - int requested = 0; - - if (pDpa->reboot) - { - init_status = RCInitI2OMsgLayer(dev, (PFNTXCALLBACK)RCxmit_callback, - (PFNRXCALLBACK)RCrecv_callback, - (PFNCALLBACK)RCreboot_callback); - - switch(init_status) - { - case RC_RTN_NO_ERROR: - - pDpa->reboot = 0; - pDpa->shutdown = 0; /* just in case */ - RCReportDriverCapability(dev, DriverControlWord); - RCEnableI2OInterrupts(dev); - - if (dev->flags & IFF_UP) - { - while(post_buffers) - { - if (post_buffers > MAX_NMBR_POST_BUFFERS_PER_MSG) - requested = MAX_NMBR_POST_BUFFERS_PER_MSG; - else - requested = post_buffers; - count = RC_allocate_and_post_buffers(dev, requested); - post_buffers -= count; - if ( count < requested ) - break; - } - pDpa->numOutRcvBuffers = - MAX_NMBR_RCV_BUFFERS - post_buffers; - dprintk("rc: posted %d buffers \r\n", - (uint)pDpa->numOutRcvBuffers); - } - dprintk("Initialization done.\n"); - netif_wake_queue(dev); - retry=0; - return; - case RC_RTN_FREE_Q_EMPTY: - retry++; - printk(KERN_WARNING "(rcpci45 driver:) inbound free q empty\n"); - break; - default: - retry++; - printk(KERN_WARNING "(rcpci45 driver:) bad status after reboot: %d\n", init_status); - break; - } - - if (retry > REBOOT_REINIT_RETRY_LIMIT) - { - printk(KERN_WARNING "(rcpci45 driver:) unable to reinitialize adapter after reboot\n"); - printk(KERN_WARNING "(rcpci45 driver:) decrementing driver and closing interface\n"); - RCDisableI2OInterrupts(dev); - dev->flags &= ~IFF_UP; - MOD_DEC_USE_COUNT; - } - else - { - printk(KERN_INFO "(rcpci45 driver:) rescheduling timer...\n"); - init_timer(&pDpa->timer); - pDpa->timer.expires = RUN_AT((40*HZ)/10); /* 3 sec. */ - pDpa->timer.data = (unsigned long)dev; - pDpa->timer.function = &rc_timer; /* timer handler */ - add_timer(&pDpa->timer); - } - } - else - printk(KERN_WARNING "(rcpci45 driver:) timer??\n"); + struct net_device *dev = (struct net_device *) data; + PDPA pDpa = dev->priv; + int init_status; + static int retry; + int post_buffers = MAX_NMBR_RCV_BUFFERS; + int count = 0; + int requested = 0; + + if (pDpa->reboot) { + init_status = + RCInitI2OMsgLayer (dev, (PFNTXCALLBACK) RCxmit_callback, + (PFNRXCALLBACK) RCrecv_callback, + (PFNCALLBACK) RCreboot_callback); + + switch (init_status) { + case RC_RTN_NO_ERROR: + + pDpa->reboot = 0; + pDpa->shutdown = 0; /* just in case */ + RCReportDriverCapability (dev, DriverControlWord); + RCEnableI2OInterrupts (dev); + + if (dev->flags & IFF_UP) { + while (post_buffers) { + if (post_buffers > + MAX_NMBR_POST_BUFFERS_PER_MSG) + requested = + MAX_NMBR_POST_BUFFERS_PER_MSG; + else + requested = post_buffers; + count = + RC_allocate_and_post_buffers (dev, + requested); + post_buffers -= count; + if (count < requested) + break; + } + pDpa->numOutRcvBuffers = + MAX_NMBR_RCV_BUFFERS - post_buffers; + dprintk ("rc: posted %d buffers \r\n", + (uint) pDpa->numOutRcvBuffers); + } + dprintk ("Initialization done.\n"); + netif_wake_queue (dev); + retry = 0; + return; + case RC_RTN_FREE_Q_EMPTY: + retry++; + printk (KERN_WARNING + "(rcpci45 driver:) inbound free q empty\n"); + break; + default: + retry++; + printk (KERN_WARNING + "(rcpci45 driver:) bad status after reboot: %d\n", + init_status); + break; + } + + if (retry > REBOOT_REINIT_RETRY_LIMIT) { + printk (KERN_WARNING + "(rcpci45 driver:) unable to reinitialize adapter after reboot\n"); + printk (KERN_WARNING + "(rcpci45 driver:) decrementing driver and closing interface\n"); + RCDisableI2OInterrupts (dev); + dev->flags &= ~IFF_UP; + MOD_DEC_USE_COUNT; + } else { + printk (KERN_INFO + "(rcpci45 driver:) rescheduling timer...\n"); + init_timer (&pDpa->timer); + pDpa->timer.expires = RUN_AT ((40 * HZ) / 10); /* 3 sec. */ + pDpa->timer.data = (unsigned long) dev; + pDpa->timer.function = &rc_timer; /* timer handler */ + add_timer (&pDpa->timer); + } + } else + printk (KERN_WARNING "(rcpci45 driver:) timer??\n"); } static int -RCclose(struct net_device *dev) +RCclose (struct net_device *dev) { - PDPA pDpa = dev->priv; + PDPA pDpa = dev->priv; + + netif_stop_queue (dev); + + dprintk ("RCclose\r\n"); - netif_stop_queue(dev); - - dprintk("RCclose\r\n"); - - if (pDpa->reboot) - { - printk(KERN_INFO "(rcpci45 driver:) skipping reset -- adapter already in reboot mode\n"); - dev->flags &= ~IFF_UP; - pDpa->shutdown = 1; - return 0; - } - dprintk("receive buffers outstanding: %d\n", (uint)pDpa->numOutRcvBuffers); - - pDpa->shutdown = 1; - - /* - * We can't allow the driver to be unloaded until the adapter returns - * all posted receive buffers. It doesn't hurt to tell the adapter - * to return all posted receive buffers and outstanding xmit buffers, - * even if there are none. - */ - - RCShutdownLANCard(dev, RC_RESOURCE_RETURN_POSTED_RX_BUCKETS | - RC_RESOURCE_RETURN_PEND_TX_BUFFERS,0, - (PFNCALLBACK)RCreset_callback); + if (pDpa->reboot) { + printk (KERN_INFO + "(rcpci45 driver:) skipping reset -- adapter already in reboot mode\n"); + dev->flags &= ~IFF_UP; + pDpa->shutdown = 1; + return 0; + } + dprintk ("receive buffers outstanding: %d\n", + (uint) pDpa->numOutRcvBuffers); + + pDpa->shutdown = 1; + + /* + * We can't allow the driver to be unloaded until the adapter returns + * all posted receive buffers. It doesn't hurt to tell the adapter + * to return all posted receive buffers and outstanding xmit buffers, + * even if there are none. + */ + + RCShutdownLANCard (dev, RC_RESOURCE_RETURN_POSTED_RX_BUCKETS | + RC_RESOURCE_RETURN_PEND_TX_BUFFERS, 0, + (PFNCALLBACK) RCreset_callback); - dev->flags &= ~IFF_UP; - return 0; + dev->flags &= ~IFF_UP; + return 0; } static struct net_device_stats * -RCget_stats(struct net_device *dev) +RCget_stats (struct net_device *dev) { - RCLINKSTATS RCstats; - - PDPA pDpa = dev->priv; - - if (!pDpa) - { - dprintk("RCget_stats: !pDpa\n"); - return 0; - } - else if (!(dev->flags & IFF_UP)) - { - dprintk("RCget_stats: device down\n"); - return 0; - } - - memset(&RCstats, 0, sizeof(RCLINKSTATS)); - if ( (RCGetLinkStatistics(dev, &RCstats, (void *)0)) == RC_RTN_NO_ERROR ) - { - dprintk("TX_good 0x%x\n", (uint)RCstats.TX_good); - dprintk("TX_maxcol 0x%x\n", (uint)RCstats.TX_maxcol); - dprintk("TX_latecol 0x%x\n", (uint)RCstats.TX_latecol); - dprintk("TX_urun 0x%x\n", (uint)RCstats.TX_urun); - dprintk("TX_crs 0x%x\n", (uint)RCstats.TX_crs); - dprintk("TX_def 0x%x\n", (uint)RCstats.TX_def); - dprintk("TX_singlecol 0x%x\n", (uint)RCstats.TX_singlecol); - dprintk("TX_multcol 0x%x\n", (uint)RCstats.TX_multcol); - dprintk("TX_totcol 0x%x\n", (uint)RCstats.TX_totcol); - - dprintk("Rcv_good 0x%x\n", (uint)RCstats.Rcv_good); - dprintk("Rcv_CRCerr 0x%x\n", (uint)RCstats.Rcv_CRCerr); - dprintk("Rcv_alignerr 0x%x\n", (uint)RCstats.Rcv_alignerr); - dprintk("Rcv_reserr 0x%x\n", (uint)RCstats.Rcv_reserr); - dprintk("Rcv_orun 0x%x\n", (uint)RCstats.Rcv_orun); - dprintk("Rcv_cdt 0x%x\n", (uint)RCstats.Rcv_cdt); - dprintk("Rcv_runt 0x%x\n", (uint)RCstats.Rcv_runt); - - pDpa->stats.rx_packets = RCstats.Rcv_good; /* total packets received */ - pDpa->stats.tx_packets = RCstats.TX_good; /* total packets transmitted */ - - pDpa->stats.rx_errors = - RCstats.Rcv_CRCerr + - RCstats.Rcv_alignerr + - RCstats.Rcv_reserr + - RCstats.Rcv_orun + - RCstats.Rcv_cdt + - RCstats.Rcv_runt; /* bad packets received */ - - pDpa->stats.tx_errors = - RCstats.TX_urun + - RCstats.TX_crs + - RCstats.TX_def + - RCstats.TX_totcol; /* packet transmit problems */ - - /* - * This needs improvement. - */ - pDpa->stats.rx_dropped = 0; /* no space in linux buffers */ - pDpa->stats.tx_dropped = 0; /* no space available in linux */ - pDpa->stats.multicast = 0; /* multicast packets received */ - pDpa->stats.collisions = RCstats.TX_totcol; - - /* detailed rx_errors: */ - pDpa->stats.rx_length_errors = 0; - pDpa->stats.rx_over_errors = RCstats.Rcv_orun; /* receiver ring buff overflow */ - pDpa->stats.rx_crc_errors = RCstats.Rcv_CRCerr; /* recved pkt with crc error */ - pDpa->stats.rx_frame_errors = 0; /* recv'd frame alignment error */ - pDpa->stats.rx_fifo_errors = 0; /* recv'r fifo overrun */ - pDpa->stats.rx_missed_errors = 0; /* receiver missed packet */ - - /* detailed tx_errors */ - pDpa->stats.tx_aborted_errors = 0; - pDpa->stats.tx_carrier_errors = 0; - pDpa->stats.tx_fifo_errors = 0; - pDpa->stats.tx_heartbeat_errors = 0; - pDpa->stats.tx_window_errors = 0; - - return ((struct net_device_stats *)&(pDpa->stats)); - } - return 0; + RCLINKSTATS RCstats; + + PDPA pDpa = dev->priv; + + if (!pDpa) { + dprintk ("RCget_stats: !pDpa\n"); + return 0; + } else if (!(dev->flags & IFF_UP)) { + dprintk ("RCget_stats: device down\n"); + return 0; + } + + memset (&RCstats, 0, sizeof (RCLINKSTATS)); + if ((RCGetLinkStatistics (dev, &RCstats, (void *) 0)) == + RC_RTN_NO_ERROR) { + dprintk ("TX_good 0x%x\n", (uint) RCstats.TX_good); + dprintk ("TX_maxcol 0x%x\n", (uint) RCstats.TX_maxcol); + dprintk ("TX_latecol 0x%x\n", (uint) RCstats.TX_latecol); + dprintk ("TX_urun 0x%x\n", (uint) RCstats.TX_urun); + dprintk ("TX_crs 0x%x\n", (uint) RCstats.TX_crs); + dprintk ("TX_def 0x%x\n", (uint) RCstats.TX_def); + dprintk ("TX_singlecol 0x%x\n", (uint) RCstats.TX_singlecol); + dprintk ("TX_multcol 0x%x\n", (uint) RCstats.TX_multcol); + dprintk ("TX_totcol 0x%x\n", (uint) RCstats.TX_totcol); + + dprintk ("Rcv_good 0x%x\n", (uint) RCstats.Rcv_good); + dprintk ("Rcv_CRCerr 0x%x\n", (uint) RCstats.Rcv_CRCerr); + dprintk ("Rcv_alignerr 0x%x\n", (uint) RCstats.Rcv_alignerr); + dprintk ("Rcv_reserr 0x%x\n", (uint) RCstats.Rcv_reserr); + dprintk ("Rcv_orun 0x%x\n", (uint) RCstats.Rcv_orun); + dprintk ("Rcv_cdt 0x%x\n", (uint) RCstats.Rcv_cdt); + dprintk ("Rcv_runt 0x%x\n", (uint) RCstats.Rcv_runt); + + pDpa->stats.rx_packets = RCstats.Rcv_good; /* total packets received */ + pDpa->stats.tx_packets = RCstats.TX_good; /* total packets transmitted */ + + pDpa->stats.rx_errors = RCstats.Rcv_CRCerr + RCstats.Rcv_alignerr + RCstats.Rcv_reserr + RCstats.Rcv_orun + RCstats.Rcv_cdt + RCstats.Rcv_runt; /* bad packets received */ + + pDpa->stats.tx_errors = RCstats.TX_urun + RCstats.TX_crs + RCstats.TX_def + RCstats.TX_totcol; /* packet transmit problems */ + + /* + * This needs improvement. + */ + pDpa->stats.rx_dropped = 0; /* no space in linux buffers */ + pDpa->stats.tx_dropped = 0; /* no space available in linux */ + pDpa->stats.multicast = 0; /* multicast packets received */ + pDpa->stats.collisions = RCstats.TX_totcol; + + /* detailed rx_errors: */ + pDpa->stats.rx_length_errors = 0; + pDpa->stats.rx_over_errors = RCstats.Rcv_orun; /* receiver ring buff overflow */ + pDpa->stats.rx_crc_errors = RCstats.Rcv_CRCerr; /* recved pkt with crc error */ + pDpa->stats.rx_frame_errors = 0; /* recv'd frame alignment error */ + pDpa->stats.rx_fifo_errors = 0; /* recv'r fifo overrun */ + pDpa->stats.rx_missed_errors = 0; /* receiver missed packet */ + + /* detailed tx_errors */ + pDpa->stats.tx_aborted_errors = 0; + pDpa->stats.tx_carrier_errors = 0; + pDpa->stats.tx_fifo_errors = 0; + pDpa->stats.tx_heartbeat_errors = 0; + pDpa->stats.tx_window_errors = 0; + + return ((struct net_device_stats *) &(pDpa->stats)); + } + return 0; } -static int RCioctl(struct net_device *dev, struct ifreq *rq, int cmd) +static int +RCioctl (struct net_device *dev, struct ifreq *rq, int cmd) { - RCuser_struct RCuser; - PDPA pDpa = dev->priv; + RCuser_struct RCuser; + PDPA pDpa = dev->priv; + + dprintk ("RCioctl: cmd = 0x%x\n", cmd); + + if (!capable (CAP_NET_ADMIN)) + return -EPERM; - dprintk("RCioctl: cmd = 0x%x\n", cmd); - - if(!capable(CAP_NET_ADMIN)) - return -EPERM; - - switch (cmd) { - - case RCU_PROTOCOL_REV: - /* - * Assign user protocol revision, to tell user-level - * controller program whether or not it's in sync. - */ - rq->ifr_ifru.ifru_data = (caddr_t) USER_PROTOCOL_REV; - break; - - - case RCU_COMMAND: - { - if(copy_from_user(&RCuser, rq->ifr_data, sizeof(RCuser))) - return -EFAULT; - - dprintk("RCioctl: RCuser_cmd = 0x%x\n", RCuser.cmd); - - switch(RCuser.cmd) - { - case RCUC_GETFWVER: - printk(KERN_INFO "(rcpci45 driver:) RC GETFWVER\n"); - RCUD_GETFWVER = &RCuser.RCUS_GETFWVER; - RCGetFirmwareVer(dev, (PU8) &RCUD_GETFWVER->FirmString, NULL); - break; - case RCUC_GETINFO: - printk(KERN_INFO "(rcpci45 driver:) RC GETINFO\n"); - RCUD_GETINFO = &RCuser.RCUS_GETINFO; - RCUD_GETINFO -> mem_start = dev->base_addr; - RCUD_GETINFO -> mem_end = dev->base_addr + pDpa->pci_addr_len; - RCUD_GETINFO -> base_addr = pDpa->pci_addr; - RCUD_GETINFO -> irq = dev->irq; - break; - case RCUC_GETIPANDMASK: - printk(KERN_INFO "(rcpci45 driver:) RC GETIPANDMASK\n"); - RCUD_GETIPANDMASK = &RCuser.RCUS_GETIPANDMASK; - RCGetRavlinIPandMask(dev, (PU32) &RCUD_GETIPANDMASK->IpAddr, - (PU32) &RCUD_GETIPANDMASK->NetMask, NULL); - break; - case RCUC_GETLINKSTATISTICS: - printk(KERN_INFO "(rcpci45 driver:) RC GETLINKSTATISTICS\n"); - RCUD_GETLINKSTATISTICS = &RCuser.RCUS_GETLINKSTATISTICS; - RCGetLinkStatistics(dev, (P_RCLINKSTATS) &RCUD_GETLINKSTATISTICS->StatsReturn, NULL); - break; - case RCUC_GETLINKSTATUS: - printk(KERN_INFO "(rcpci45 driver:) RC GETLINKSTATUS\n"); - RCUD_GETLINKSTATUS = &RCuser.RCUS_GETLINKSTATUS; - RCGetLinkStatus(dev, (PU32) &RCUD_GETLINKSTATUS->ReturnStatus, NULL); - break; - case RCUC_GETMAC: - printk(KERN_INFO "(rcpci45 driver:) RC GETMAC\n"); - RCUD_GETMAC = &RCuser.RCUS_GETMAC; - RCGetMAC(dev, NULL); - break; - case RCUC_GETPROM: - printk(KERN_INFO "(rcpci45 driver:) RC GETPROM\n"); - RCUD_GETPROM = &RCuser.RCUS_GETPROM; - RCGetPromiscuousMode(dev, (PU32) &RCUD_GETPROM->PromMode, NULL); - break; - case RCUC_GETBROADCAST: - printk(KERN_INFO "(rcpci45 driver:) RC GETBROADCAST\n"); - RCUD_GETBROADCAST = &RCuser.RCUS_GETBROADCAST; - RCGetBroadcastMode(dev, (PU32) &RCUD_GETBROADCAST->BroadcastMode, NULL); - break; - case RCUC_GETSPEED: - printk(KERN_INFO "(rcpci45 driver:) RC GETSPEED\n"); - if (!(dev->flags & IFF_UP)) - { - printk(KERN_ERR "(rcpci45 driver:) RCioctl, GETSPEED error: interface down\n"); - return -ENODATA; - } - RCUD_GETSPEED = &RCuser.RCUS_GETSPEED; - RCGetLinkSpeed(dev, (PU32) &RCUD_GETSPEED->LinkSpeedCode, NULL); - printk(KERN_INFO "(rcpci45 driver:) RC speed = 0x%u\n", RCUD_GETSPEED->LinkSpeedCode); - break; - case RCUC_SETIPANDMASK: - printk(KERN_INFO "(rcpci45 driver:) RC SETIPANDMASK\n"); - RCUD_SETIPANDMASK = &RCuser.RCUS_SETIPANDMASK; - printk (KERN_INFO "(rcpci45 driver:) RC New IP Addr = %d.%d.%d.%d, ", (U8) ((RCUD_SETIPANDMASK->IpAddr) & 0xff), - (U8) ((RCUD_SETIPANDMASK->IpAddr >> 8) & 0xff), - (U8) ((RCUD_SETIPANDMASK->IpAddr >> 16) & 0xff), - (U8) ((RCUD_SETIPANDMASK->IpAddr >> 24) & 0xff)); - printk (KERN_INFO "(rcpci45 driver:) RC New Mask = %d.%d.%d.%d\n", (U8) ((RCUD_SETIPANDMASK->NetMask) & 0xff), - (U8) ((RCUD_SETIPANDMASK->NetMask >> 8) & 0xff), - (U8) ((RCUD_SETIPANDMASK->NetMask >> 16) & 0xff), - (U8) ((RCUD_SETIPANDMASK->NetMask >> 24) & 0xff)); - RCSetRavlinIPandMask(dev, (U32) RCUD_SETIPANDMASK->IpAddr, - (U32) RCUD_SETIPANDMASK->NetMask); - break; - case RCUC_SETMAC: - printk(KERN_INFO "(rcpci45 driver:) RC SETMAC\n"); - RCUD_SETMAC = &RCuser.RCUS_SETMAC; - printk (KERN_INFO "(rcpci45 driver:) RC New MAC addr = %02X:%02X:%02X:%02X:%02X:%02X\n", - (U8) (RCUD_SETMAC->mac[0]), (U8) (RCUD_SETMAC->mac[1]), (U8) (RCUD_SETMAC->mac[2]), - (U8) (RCUD_SETMAC->mac[3]), (U8) (RCUD_SETMAC->mac[4]), (U8) (RCUD_SETMAC->mac[5])); - RCSetMAC(dev, (PU8) &RCUD_SETMAC->mac); - break; - case RCUC_SETSPEED: - printk(KERN_INFO "(rcpci45 driver:) RC SETSPEED\n"); - RCUD_SETSPEED = &RCuser.RCUS_SETSPEED; - RCSetLinkSpeed(dev, (U16) RCUD_SETSPEED->LinkSpeedCode); - printk(KERN_INFO "(rcpci45 driver:) RC New speed = 0x%x\n", RCUD_SETSPEED->LinkSpeedCode); - break; - case RCUC_SETPROM: - printk(KERN_INFO "(rcpci45 driver:) RC SETPROM\n"); - RCUD_SETPROM = &RCuser.RCUS_SETPROM; - RCSetPromiscuousMode(dev,(U16)RCUD_SETPROM->PromMode); - printk(KERN_INFO "(rcpci45 driver:) RC New prom mode = 0x%x\n", RCUD_SETPROM->PromMode); - break; - case RCUC_SETBROADCAST: - printk(KERN_INFO "(rcpci45 driver:) RC SETBROADCAST\n"); - RCUD_SETBROADCAST = &RCuser.RCUS_SETBROADCAST; - RCSetBroadcastMode(dev,(U16)RCUD_SETBROADCAST->BroadcastMode); - printk(KERN_INFO "(rcpci45 driver:) RC New broadcast mode = 0x%x\n", RCUD_SETBROADCAST->BroadcastMode); - break; - default: - printk(KERN_INFO "(rcpci45 driver:) RC command default\n"); - RCUD_DEFAULT = &RCuser.RCUS_DEFAULT; - RCUD_DEFAULT -> rc = 0x11223344; - break; - } - if(copy_to_user(rq->ifr_data, &RCuser, sizeof(RCuser))) - return -EFAULT; - break; - } /* RCU_COMMAND */ + switch (cmd) { + + case RCU_PROTOCOL_REV: + /* + * Assign user protocol revision, to tell user-level + * controller program whether or not it's in sync. + */ + rq->ifr_ifru.ifru_data = (caddr_t) USER_PROTOCOL_REV; + break; + + case RCU_COMMAND: + { + if (copy_from_user + (&RCuser, rq->ifr_data, sizeof (RCuser))) + return -EFAULT; + + dprintk ("RCioctl: RCuser_cmd = 0x%x\n", RCuser.cmd); + + switch (RCuser.cmd) { + case RCUC_GETFWVER: + printk (KERN_INFO + "(rcpci45 driver:) RC GETFWVER\n"); + RCUD_GETFWVER = &RCuser.RCUS_GETFWVER; + RCGetFirmwareVer (dev, + (PU8) & RCUD_GETFWVER-> + FirmString, NULL); + break; + case RCUC_GETINFO: + printk (KERN_INFO + "(rcpci45 driver:) RC GETINFO\n"); + RCUD_GETINFO = &RCuser.RCUS_GETINFO; + RCUD_GETINFO->mem_start = dev->base_addr; + RCUD_GETINFO->mem_end = + dev->base_addr + pDpa->pci_addr_len; + RCUD_GETINFO->base_addr = pDpa->pci_addr; + RCUD_GETINFO->irq = dev->irq; + break; + case RCUC_GETIPANDMASK: + printk (KERN_INFO + "(rcpci45 driver:) RC GETIPANDMASK\n"); + RCUD_GETIPANDMASK = &RCuser.RCUS_GETIPANDMASK; + RCGetRavlinIPandMask (dev, + (PU32) & + RCUD_GETIPANDMASK->IpAddr, + (PU32) & + RCUD_GETIPANDMASK-> + NetMask, NULL); + break; + case RCUC_GETLINKSTATISTICS: + printk (KERN_INFO + "(rcpci45 driver:) RC GETLINKSTATISTICS\n"); + RCUD_GETLINKSTATISTICS = + &RCuser.RCUS_GETLINKSTATISTICS; + RCGetLinkStatistics (dev, + (P_RCLINKSTATS) & + RCUD_GETLINKSTATISTICS-> + StatsReturn, NULL); + break; + case RCUC_GETLINKSTATUS: + printk (KERN_INFO + "(rcpci45 driver:) RC GETLINKSTATUS\n"); + RCUD_GETLINKSTATUS = &RCuser.RCUS_GETLINKSTATUS; + RCGetLinkStatus (dev, + (PU32) & RCUD_GETLINKSTATUS-> + ReturnStatus, NULL); + break; + case RCUC_GETMAC: + printk (KERN_INFO + "(rcpci45 driver:) RC GETMAC\n"); + RCUD_GETMAC = &RCuser.RCUS_GETMAC; + RCGetMAC (dev, NULL); + break; + case RCUC_GETPROM: + printk (KERN_INFO + "(rcpci45 driver:) RC GETPROM\n"); + RCUD_GETPROM = &RCuser.RCUS_GETPROM; + RCGetPromiscuousMode (dev, + (PU32) & RCUD_GETPROM-> + PromMode, NULL); + break; + case RCUC_GETBROADCAST: + printk (KERN_INFO + "(rcpci45 driver:) RC GETBROADCAST\n"); + RCUD_GETBROADCAST = &RCuser.RCUS_GETBROADCAST; + RCGetBroadcastMode (dev, + (PU32) & RCUD_GETBROADCAST-> + BroadcastMode, NULL); + break; + case RCUC_GETSPEED: + printk (KERN_INFO + "(rcpci45 driver:) RC GETSPEED\n"); + if (!(dev->flags & IFF_UP)) { + printk (KERN_ERR + "(rcpci45 driver:) RCioctl, GETSPEED error: interface down\n"); + return -ENODATA; + } + RCUD_GETSPEED = &RCuser.RCUS_GETSPEED; + RCGetLinkSpeed (dev, + (PU32) & RCUD_GETSPEED-> + LinkSpeedCode, NULL); + printk (KERN_INFO + "(rcpci45 driver:) RC speed = 0x%u\n", + RCUD_GETSPEED->LinkSpeedCode); + break; + case RCUC_SETIPANDMASK: + printk (KERN_INFO + "(rcpci45 driver:) RC SETIPANDMASK\n"); + RCUD_SETIPANDMASK = &RCuser.RCUS_SETIPANDMASK; + printk (KERN_INFO + "(rcpci45 driver:) RC New IP Addr = %d.%d.%d.%d, ", + (U8) ((RCUD_SETIPANDMASK-> + IpAddr) & 0xff), + (U8) ((RCUD_SETIPANDMASK-> + IpAddr >> 8) & 0xff), + (U8) ((RCUD_SETIPANDMASK-> + IpAddr >> 16) & 0xff), + (U8) ((RCUD_SETIPANDMASK-> + IpAddr >> 24) & 0xff)); + printk (KERN_INFO + "(rcpci45 driver:) RC New Mask = %d.%d.%d.%d\n", + (U8) ((RCUD_SETIPANDMASK-> + NetMask) & 0xff), + (U8) ((RCUD_SETIPANDMASK-> + NetMask >> 8) & 0xff), + (U8) ((RCUD_SETIPANDMASK-> + NetMask >> 16) & 0xff), + (U8) ((RCUD_SETIPANDMASK-> + NetMask >> 24) & 0xff)); + RCSetRavlinIPandMask (dev, + (U32) RCUD_SETIPANDMASK-> + IpAddr, + (U32) RCUD_SETIPANDMASK-> + NetMask); + break; + case RCUC_SETMAC: + printk (KERN_INFO + "(rcpci45 driver:) RC SETMAC\n"); + RCUD_SETMAC = &RCuser.RCUS_SETMAC; + printk (KERN_INFO + "(rcpci45 driver:) RC New MAC addr = %02X:%02X:%02X:%02X:%02X:%02X\n", + (U8) (RCUD_SETMAC->mac[0]), + (U8) (RCUD_SETMAC->mac[1]), + (U8) (RCUD_SETMAC->mac[2]), + (U8) (RCUD_SETMAC->mac[3]), + (U8) (RCUD_SETMAC->mac[4]), + (U8) (RCUD_SETMAC->mac[5])); + RCSetMAC (dev, (PU8) & RCUD_SETMAC->mac); + break; + case RCUC_SETSPEED: + printk (KERN_INFO + "(rcpci45 driver:) RC SETSPEED\n"); + RCUD_SETSPEED = &RCuser.RCUS_SETSPEED; + RCSetLinkSpeed (dev, + (U16) RCUD_SETSPEED-> + LinkSpeedCode); + printk (KERN_INFO + "(rcpci45 driver:) RC New speed = 0x%x\n", + RCUD_SETSPEED->LinkSpeedCode); + break; + case RCUC_SETPROM: + printk (KERN_INFO + "(rcpci45 driver:) RC SETPROM\n"); + RCUD_SETPROM = &RCuser.RCUS_SETPROM; + RCSetPromiscuousMode (dev, + (U16) RCUD_SETPROM-> + PromMode); + printk (KERN_INFO + "(rcpci45 driver:) RC New prom mode = 0x%x\n", + RCUD_SETPROM->PromMode); + break; + case RCUC_SETBROADCAST: + printk (KERN_INFO + "(rcpci45 driver:) RC SETBROADCAST\n"); + RCUD_SETBROADCAST = &RCuser.RCUS_SETBROADCAST; + RCSetBroadcastMode (dev, + (U16) RCUD_SETBROADCAST-> + BroadcastMode); + printk (KERN_INFO + "(rcpci45 driver:) RC New broadcast mode = 0x%x\n", + RCUD_SETBROADCAST->BroadcastMode); + break; + default: + printk (KERN_INFO + "(rcpci45 driver:) RC command default\n"); + RCUD_DEFAULT = &RCuser.RCUS_DEFAULT; + RCUD_DEFAULT->rc = 0x11223344; + break; + } + if (copy_to_user + (rq->ifr_data, &RCuser, sizeof (RCuser))) + return -EFAULT; + break; + } /* RCU_COMMAND */ default: - rq->ifr_ifru.ifru_data = (caddr_t) 0x12345678; - return -EINVAL; - } - return 0; + rq->ifr_ifru.ifru_data = (caddr_t) 0x12345678; + return -EINVAL; + } + return 0; } -static int RCconfig(struct net_device *dev, struct ifmap *map) +static int +RCconfig (struct net_device *dev, struct ifmap *map) { - /* - * To be completed ... - */ - dprintk("RCconfig\n"); - return 0; - if (dev->flags & IFF_UP) /* can't act on a running interface */ - return -EBUSY; - - /* Don't allow changing the I/O address */ - if (map->base_addr != dev->base_addr) { - printk(KERN_WARNING "(rcpci45 driver:) Change I/O address not implemented\n"); - return -EOPNOTSUPP; - } - return 0; + /* + * To be completed ... + */ + dprintk ("RCconfig\n"); + return 0; + if (dev->flags & IFF_UP) /* can't act on a running interface */ + return -EBUSY; + + /* Don't allow changing the I/O address */ + if (map->base_addr != dev->base_addr) { + printk (KERN_WARNING + "(rcpci45 driver:) Change I/O address not implemented\n"); + return -EOPNOTSUPP; + } + return 0; } - -static void __exit rcpci_cleanup_module (void) +static void __exit +rcpci_cleanup_module (void) { - pci_unregister_driver(&rcpci45_driver); + pci_unregister_driver (&rcpci45_driver); } -module_init(rcpci_init_module); -module_exit(rcpci_cleanup_module); - +module_init (rcpci_init_module); +module_exit (rcpci_cleanup_module); static int -RC_allocate_and_post_buffers(struct net_device *dev, int numBuffers) +RC_allocate_and_post_buffers (struct net_device *dev, int numBuffers) { - int i; - PU32 p; - psingleB pB; - struct sk_buff *skb; - RC_RETURN status; - U32 res; - - if (!numBuffers) - return 0; - else if (numBuffers > MAX_NMBR_POST_BUFFERS_PER_MSG) - { - dprintk("Too many buffers requested!\n"); - dprintk("attempting to allocate only 32 buffers\n"); - numBuffers = 32; - } - - p = (PU32) kmalloc(sizeof(U32) + numBuffers*sizeof(singleB), GFP_KERNEL); - - dprintk("TCB = 0x%x\n", (uint)p); - - if (!p) - { - printk(KERN_WARNING "(rcpci45 driver:) RCopen: unable to allocate TCB\n"); - return 0; - } - - p[0] = 0; /* Buffer Count */ - pB = (psingleB)((U32)p + sizeof(U32)); /* point to the first buffer */ - - dprintk("p[0] = 0x%x, p = 0x%x, pB = 0x%x\n", (uint)p[0], (uint)p, (uint)pB); - dprintk("pB = 0x%x\n", (uint)pB); - - for (i=0; icontext = (U32)skb; - pB->scount = 1; /* segment count */ - pB->size = MAX_ETHER_SIZE; - pB->addr = virt_to_bus((void *)skb->data); - p[0]++; - pB++; - } - - if ( (status = RCPostRecvBuffers(dev, (PRCTCB)p )) != RC_RTN_NO_ERROR) - { - printk(KERN_WARNING "(rcpci45 driver:) Post buffer failed with error code 0x%x!\n", status); - pB = (psingleB)((U32)p + sizeof(U32)); /* point to the first buffer */ - while(p[0]) - { - skb = (struct sk_buff *)pB->context; - dprintk("freeing 0x%x\n", (uint)skb); - dev_kfree_skb (skb); - p[0]--; - pB++; - } - dprintk("freed all buffers, p[0] = %d\n", (uint)p[0]); - } - res = p[0]; - kfree(p); - return(res); /* return the number of posted buffers */ + int i; + PU32 p; + psingleB pB; + struct sk_buff *skb; + RC_RETURN status; + U32 res; + + if (!numBuffers) + return 0; + else if (numBuffers > MAX_NMBR_POST_BUFFERS_PER_MSG) { + dprintk ("Too many buffers requested!\n"); + dprintk ("attempting to allocate only 32 buffers\n"); + numBuffers = 32; + } + + p = (PU32) kmalloc (sizeof (U32) + numBuffers * sizeof (singleB), + GFP_KERNEL); + + dprintk ("TCB = 0x%x\n", (uint) p); + + if (!p) { + printk (KERN_WARNING + "(rcpci45 driver:) RCopen: unable to allocate TCB\n"); + return 0; + } + + p[0] = 0; /* Buffer Count */ + pB = (psingleB) ((U32) p + sizeof (U32)); /* point to the first buffer */ + + dprintk ("p[0] = 0x%x, p = 0x%x, pB = 0x%x\n", (uint) p[0], (uint) p, + (uint) pB); + dprintk ("pB = 0x%x\n", (uint) pB); + + for (i = 0; i < numBuffers; i++) { + skb = dev_alloc_skb (MAX_ETHER_SIZE + 2); + if (!skb) { + dprintk + ("Doh! RCopen: unable to allocate enough skbs!\n"); + if (*p != 0) { /* did we allocate any buffers at all? */ + dprintk ("will post only %d buffers \n", + (uint) (*p)); + break; + } else { + kfree (p); /* Free the TCB */ + return 0; + } + } + dprintk ("post 0x%x\n", (uint) skb); + skb_reserve (skb, 2); /* Align IP on 16 byte boundaries */ + pB->context = (U32) skb; + pB->scount = 1; /* segment count */ + pB->size = MAX_ETHER_SIZE; + pB->addr = virt_to_bus ((void *) skb->data); + p[0]++; + pB++; + } + + if ((status = RCPostRecvBuffers (dev, (PRCTCB) p)) != RC_RTN_NO_ERROR) { + printk (KERN_WARNING + "(rcpci45 driver:) Post buffer failed with error code 0x%x!\n", + status); + pB = (psingleB) ((U32) p + sizeof (U32)); /* point to the first buffer */ + while (p[0]) { + skb = (struct sk_buff *) pB->context; + dprintk ("freeing 0x%x\n", (uint) skb); + dev_kfree_skb (skb); + p[0]--; + pB++; + } + dprintk ("freed all buffers, p[0] = %d\n", (uint) p[0]); + } + res = p[0]; + kfree (p); + return (res); /* return the number of posted buffers */ } diff -u --recursive --new-file v2.4.5/linux/drivers/net/saa9730.c linux/drivers/net/saa9730.c --- v2.4.5/linux/drivers/net/saa9730.c Fri Apr 13 20:26:07 2001 +++ linux/drivers/net/saa9730.c Mon Jul 2 14:03:04 2001 @@ -44,7 +44,7 @@ /* Non-zero only if the current card is a PCI with BIOS-set IRQ. */ -static unsigned int pci_irq_line = 0; +static unsigned int pci_irq_line; #define INL(a) inl((unsigned long)a) #define OUTL(x,a) outl(x,(unsigned long)a) @@ -335,7 +335,7 @@ printk("Error: lan_saa9730_mii_init: timeout\n"); return -1; } - udelay(1000); /* wait 1 ms. */ + mdelay(1); /* wait 1 ms. */ } /* Now set the control and address register. */ @@ -350,11 +350,11 @@ printk("Error: lan_saa9730_mii_init: timeout\n"); return -1; } - udelay(1000); /* wait 1 ms. */ + mdelay(1); /* wait 1 ms. */ } /* Wait for 1 ms. */ - udelay(1000); + mdelay(1); /* Check the link status. */ if (INL(&lp->lan_saa9730_regs->StationMgmtData) & @@ -369,7 +369,7 @@ &lp->lan_saa9730_regs->StationMgmtCtl); /* Wait for 1 ms. */ - udelay(1000); + mdelay(1); /* set 'CONTROL' = force reset and renegotiate */ OUTL(PHY_CONTROL_RESET | PHY_CONTROL_AUTO_NEG | @@ -377,7 +377,7 @@ &lp->lan_saa9730_regs->StationMgmtData); /* Wait for 50 ms. */ - udelay(50 * 1000); + mdelay(50); /* set 'BUSY' to start operation */ OUTL(MD_CA_BUSY | PHY_ADDRESS << MD_CA_PHY_SHF | MD_CA_WR | @@ -393,11 +393,11 @@ ("Error: lan_saa9730_mii_init: timeout\n"); return -1; } - udelay(1000); /* wait 1 ms. */ + mdelay(1); /* wait 1 ms. */ } /* Wait for 1 ms. */ - udelay(1000); + mdelay(1); for (l = 0; l < 2; l++) { /* set PHY address = 'STATUS' */ @@ -415,11 +415,11 @@ ("Error: lan_saa9730_mii_init: timeout\n"); return -1; } - udelay(1000); /* wait 1 ms. */ + mdelay(1); /* wait 1 ms. */ } /* wait for 3 sec. */ - udelay(3000 * 1000); + mdelay(3000); /* check the link status */ if (INL(&lp->lan_saa9730_regs->StationMgmtData) & @@ -495,7 +495,7 @@ ("Error: lan_sa9730_stop: MAC reset timeout\n"); return -1; } - udelay(1000); /* wait 1 ms. */ + mdelay(1); /* wait 1 ms. */ } return 0; diff -u --recursive --new-file v2.4.5/linux/drivers/net/sb1000.c linux/drivers/net/sb1000.c --- v2.4.5/linux/drivers/net/sb1000.c Wed Apr 18 11:49:14 2001 +++ linux/drivers/net/sb1000.c Wed Jun 20 11:10:53 2001 @@ -1211,6 +1211,8 @@ MODULE_DESCRIPTION("General Instruments SB1000 driver"); MODULE_PARM(io, "1-2i"); MODULE_PARM(irq, "i"); +MODULE_PARM_DESC(io, "SB1000 I/O base addresses"); +MODULE_PARM_DESC(irq, "SB1000 IRQ number"); static struct net_device dev_sb1000; static int io[2]; diff -u --recursive --new-file v2.4.5/linux/drivers/net/seeq8005.c linux/drivers/net/seeq8005.c --- v2.4.5/linux/drivers/net/seeq8005.c Thu Apr 19 09:34:52 2001 +++ linux/drivers/net/seeq8005.c Wed Jun 20 11:10:53 2001 @@ -101,8 +101,6 @@ /* Check for a network adaptor of this type, and return '0' iff one exists. If dev->base_addr == 0, probe all likely locations. If dev->base_addr == 1, always return failure. - If dev->base_addr == 2, allocate space for the device and return success - (detachable devices only). */ int __init @@ -715,6 +713,8 @@ static int irq = 10; MODULE_PARM(io, "i"); MODULE_PARM(irq, "i"); +MODULE_PARM_DESC(io, "SEEQ 8005 I/O base address"); +MODULE_PARM_DESC(irq, "SEEQ 8005 IRQ number"); int init_module(void) { diff -u --recursive --new-file v2.4.5/linux/drivers/net/shaper.c linux/drivers/net/shaper.c --- v2.4.5/linux/drivers/net/shaper.c Wed Apr 18 14:40:06 2001 +++ linux/drivers/net/shaper.c Wed Jun 27 17:10:55 2001 @@ -283,7 +283,7 @@ shaper->dev->name,newskb->priority); dev_queue_xmit(newskb); - shaper->stats.tx_bytes+=newskb->len; + shaper->stats.tx_bytes += skb->len; shaper->stats.tx_packets++; if(sh_debug) @@ -682,6 +682,7 @@ #ifdef MODULE MODULE_PARM(shapers, "i"); +MODULE_PARM_DESC(shapers, "Traffic shaper: maximum nuber of shapers"); #else /* MODULE */ diff -u --recursive --new-file v2.4.5/linux/drivers/net/sis900.c linux/drivers/net/sis900.c --- v2.4.5/linux/drivers/net/sis900.c Fri Apr 20 11:54:23 2001 +++ linux/drivers/net/sis900.c Mon Jul 2 14:03:04 2001 @@ -1,6 +1,6 @@ /* sis900.c: A SiS 900/7016 PCI Fast Ethernet driver for Linux. Copyright 1999 Silicon Integrated System Corporation - Revision: 1.07.11 Apr. 10 2001 + Revision: 1.08.00 Jun. 11 2001 Modified from the driver which is originally written by Donald Becker. @@ -18,6 +18,7 @@ preliminary Rev. 1.0 Jan. 18, 1998 http://www.sis.com.tw/support/databook.htm + Rev 1.08.00 Jun. 11 2001 Hui-Fen Hsu workaround for RTL8201 PHY and some bug fix Rev 1.07.11 Apr. 2 2001 Hui-Fen Hsu updates PCI drivers to use the new pci_set_dma_mask for kernel 2.4.3 Rev 1.07.10 Mar. 1 2001 Hui-Fen Hsu some bug fix & 635M/B support Rev 1.07.09 Feb. 9 2001 Dave Jones PCI enable cleanup @@ -52,6 +53,7 @@ #include #include #include +#include #include #include @@ -63,7 +65,7 @@ #include "sis900.h" static char version[] __devinitdata = -KERN_INFO "sis900.c: v1.07.11 4/10/2001\n"; +KERN_INFO "sis900.c: v1.08.00 6/11/2001\n"; static int max_interrupt_work = 40; static int multicast_filter_limit = 128; @@ -110,6 +112,7 @@ { "AMD 79C901 HomePNA PHY", 0x0000, 0x6B90, HOME}, { "ICS LAN PHY", 0x0015, 0xF440, LAN }, { "NS 83851 PHY", 0x2000, 0x5C20, MIX }, + { "Realtek RTL8201 PHY", 0x0000, 0x8200, LAN }, {0,}, }; @@ -158,6 +161,9 @@ MODULE_PARM(multicast_filter_limit, "i"); MODULE_PARM(max_interrupt_work, "i"); MODULE_PARM(debug, "i"); +MODULE_PARM_DESC(multicast_filter_limit, "SiS 900/7016 maximum number of filtered multicast addresses"); +MODULE_PARM_DESC(max_interrupt_work, "SiS 900/7016 maximum events handled per interrupt"); +MODULE_PARM_DESC(debug, "SiS 900/7016 debug level (2-4)"); static int sis900_open(struct net_device *net_dev); static int sis900_mii_probe (struct net_device * net_dev); @@ -375,13 +381,13 @@ if (ret == 0) { ret = -ENODEV; - goto err_out_region; + goto err_out_unregister; } /* probe for mii transciver */ if (sis900_mii_probe(net_dev) == 0) { ret = -ENODEV; - goto err_out_region; + goto err_out_unregister; } /* print some information about our NIC */ @@ -393,9 +399,10 @@ return 0; + err_out_unregister: + unregister_netdev(net_dev); err_out_cleardev: pci_set_drvdata(pci_dev, NULL); - err_out_region: pci_release_regions(pci_dev); err_out: kfree(net_dev); @@ -996,7 +1003,7 @@ static void sis630_set_eq(struct net_device *net_dev, u8 revision) { struct sis900_private *sis_priv = net_dev->priv; - u16 reg14h, eq_value, max_value=0, min_value=0; + u16 reg14h, eq_value=0, max_value=0, min_value=0; u8 host_bridge_rev; int i, maxcount=10; struct pci_dev *dev=NULL; @@ -1243,6 +1250,7 @@ static void sis900_read_mode(struct net_device *net_dev, int *speed, int *duplex) { struct sis900_private *sis_priv = net_dev->priv; + struct mii_phy *phy = sis_priv->mii; int phy_addr = sis_priv->cur_phy; u32 status; u16 autoadv, autorec; @@ -1258,18 +1266,25 @@ autoadv = mdio_read(net_dev, phy_addr, MII_ANADV); autorec = mdio_read(net_dev, phy_addr, MII_ANLPAR); status = autoadv & autorec; + + *speed = HW_SPEED_10_MBPS; + *duplex = FDX_CAPABLE_HALF_SELECTED; if (status & (MII_NWAY_TX | MII_NWAY_TX_FDX)) *speed = HW_SPEED_100_MBPS; - else - *speed = HW_SPEED_10_MBPS; if (status & ( MII_NWAY_TX_FDX | MII_NWAY_T_FDX)) *duplex = FDX_CAPABLE_FULL_SELECTED; - else - *duplex = FDX_CAPABLE_HALF_SELECTED; - - sis_priv->autong_complete = 1; + sis_priv->autong_complete = 1; + + /* Workaround for Realtek RTL8201 PHY issue */ + if((phy->phy_id0 == 0x0000) && ((phy->phy_id1 & 0xFFF0) == 0x8200)){ + if(mdio_read(net_dev, phy_addr, MII_CONTROL) & MII_CNTL_FDX) + *duplex = FDX_CAPABLE_FULL_SELECTED; + if(mdio_read(net_dev, phy_addr, 0x0019) & 0x01) + *speed = HW_SPEED_100_MBPS; + } + printk(KERN_INFO "%s: Media Link On %s %s-duplex \n", net_dev->name, *speed == HW_SPEED_100_MBPS ? @@ -1688,19 +1703,24 @@ static int mii_ioctl(struct net_device *net_dev, struct ifreq *rq, int cmd) { struct sis900_private *sis_priv = net_dev->priv; - u16 *data = (u16 *)&rq->ifr_data; + struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data; switch(cmd) { - case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ - data[0] = sis_priv->mii->phy_addr; + case SIOCGMIIPHY: /* Get address of MII PHY in use. */ + case SIOCDEVPRIVATE: /* for binary compat, remove in 2.5 */ + data->phy_id = sis_priv->mii->phy_addr; /* Fall Through */ - case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ - data[3] = mdio_read(net_dev, data[0] & 0x1f, data[1] & 0x1f); + + case SIOCGMIIREG: /* Read MII PHY register. */ + case SIOCDEVPRIVATE+1: /* for binary compat, remove in 2.5 */ + data->val_out = mdio_read(net_dev, data->phy_id & 0x1f, data->reg_num & 0x1f); return 0; - case SIOCDEVPRIVATE+2: /* Write the specified MII register */ + + case SIOCSMIIREG: /* Write MII PHY register. */ + case SIOCDEVPRIVATE+2: /* for binary compat, remove in 2.5 */ if (!capable(CAP_NET_ADMIN)) return -EPERM; - mdio_write(net_dev, data[0] & 0x1f, data[1] & 0x1f, data[2]); + mdio_write(net_dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in); return 0; default: return -EOPNOTSUPP; diff -u --recursive --new-file v2.4.5/linux/drivers/net/sis900.h linux/drivers/net/sis900.h --- v2.4.5/linux/drivers/net/sis900.h Wed Apr 11 21:17:59 2001 +++ linux/drivers/net/sis900.h Mon Jul 2 14:03:04 2001 @@ -266,13 +266,5 @@ #define NUM_TX_DESC 16 /* Number of Tx descriptor registers. */ #define NUM_RX_DESC 16 /* Number of Rx descriptor registers. */ -/* PCI stuff, should be move to pic.h */ -#define PCI_DEVICE_ID_SI_900 0x900 -#define PCI_DEVICE_ID_SI_7016 0x7016 #define SIS630_VENDOR_ID 0x1039 #define SIS630_DEVICE_ID 0x0630 - -/* ioctl for accessing MII transceiver */ -#define SIOCGMIIPHY (SIOCDEVPRIVATE) /* Get the PHY in use. */ -#define SIOCGMIIREG (SIOCDEVPRIVATE+1) /* Read a PHY register. */ -#define SIOCSMIIREG (SIOCDEVPRIVATE+2) /* Write a PHY register */ diff -u --recursive --new-file v2.4.5/linux/drivers/net/sk_g16.c linux/drivers/net/sk_g16.c --- v2.4.5/linux/drivers/net/sk_g16.c Thu Apr 19 09:34:52 2001 +++ linux/drivers/net/sk_g16.c Mon Jul 2 14:03:04 2001 @@ -536,8 +536,6 @@ * Check for a network adaptor of this type, and return '0' if one exists. * If dev->base_addr == 0, probe all likely locations. * If dev->base_addr == 1, always return failure. - * If dev->base_addr == 2, allocate space for the device and return success - * (detachable devices only). */ int __init SK_init(struct net_device *dev) diff -u --recursive --new-file v2.4.5/linux/drivers/net/slip.c linux/drivers/net/slip.c --- v2.4.5/linux/drivers/net/slip.c Wed Apr 18 14:40:06 2001 +++ linux/drivers/net/slip.c Wed Jun 20 11:10:53 2001 @@ -96,6 +96,7 @@ int slip_maxdev = SL_NRUNIT; /* Can be overridden with insmod! */ MODULE_PARM(slip_maxdev, "i"); +MODULE_PARM_DESC(slip_maxdev, "Maximum number of slip devices"); static struct tty_ldisc sl_ldisc; diff -u --recursive --new-file v2.4.5/linux/drivers/net/smc-mca.c linux/drivers/net/smc-mca.c --- v2.4.5/linux/drivers/net/smc-mca.c Sun Mar 4 14:05:04 2001 +++ linux/drivers/net/smc-mca.c Wed Jun 20 11:10:53 2001 @@ -440,6 +440,8 @@ MODULE_PARM(io, "1-" __MODULE_STRING(MAX_ULTRAMCA_CARDS) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_ULTRAMCA_CARDS) "i"); +MODULE_PARM_DESC(io, "SMC Ultra/EtherEZ MCA I/O base address(es)"); +MODULE_PARM_DESC(irq, "SMC Ultra/EtherEZ MCA IRQ number(s)"); int init_module(void) { diff -u --recursive --new-file v2.4.5/linux/drivers/net/smc-ultra.c linux/drivers/net/smc-ultra.c --- v2.4.5/linux/drivers/net/smc-ultra.c Thu Apr 19 09:34:52 2001 +++ linux/drivers/net/smc-ultra.c Wed Jun 20 11:10:53 2001 @@ -500,6 +500,8 @@ MODULE_PARM(io, "1-" __MODULE_STRING(MAX_ULTRA_CARDS) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_ULTRA_CARDS) "i"); +MODULE_PARM_DESC(io, "SMC Ultra I/O base address(es)"); +MODULE_PARM_DESC(irq, "SMC Ultra IRQ number(s) (assigned)"); EXPORT_NO_SYMBOLS; diff -u --recursive --new-file v2.4.5/linux/drivers/net/smc9194.c linux/drivers/net/smc9194.c --- v2.4.5/linux/drivers/net/smc9194.c Thu Apr 19 09:34:52 2001 +++ linux/drivers/net/smc9194.c Wed Jun 20 11:10:53 2001 @@ -1566,6 +1566,9 @@ MODULE_PARM(io, "i"); MODULE_PARM(irq, "i"); MODULE_PARM(ifport, "i"); +MODULE_PARM_DESC(io, "SMC 99194 I/O base address"); +MODULE_PARM_DESC(irq, "SMC 99194 IRQ number"); +MODULE_PARM_DESC(ifport, "SMC 99194 interface port (0-default, 1-TP, 2-AUI)"); int init_module(void) { diff -u --recursive --new-file v2.4.5/linux/drivers/net/starfire.c linux/drivers/net/starfire.c --- v2.4.5/linux/drivers/net/starfire.c Fri Apr 20 11:54:23 2001 +++ linux/drivers/net/starfire.c Mon Jul 2 14:03:04 2001 @@ -2,6 +2,10 @@ /* Written 1998-2000 by Donald Becker. + Current maintainer is Ion Badulescu . Please + send all bug reports to me, and not to Donald Becker, as this code + has been modified quite a bit from Donald's original version. + This software may be used and distributed according to the terms of the GNU General Public License (GPL), incorporated herein by reference. Drivers based on or derived from this code fall under the GPL and must @@ -20,7 +24,7 @@ ----------------------------------------------------------- Linux kernel-specific changes: - + LK1.1.1 (jgarzik): - Use PCI driver interface - Fix MOD_xxx races @@ -31,35 +35,130 @@ LK1.1.3 (Andrew Morton) - Timer cleanups - + LK1.1.4 (jgarzik): - Merge Becker version 1.03 + + LK1.2.1 (Ion Badulescu ) + - Support hardware Rx/Tx checksumming + - Use the GFP firmware taken from Adaptec's Netware driver + + LK1.2.2 (Ion Badulescu) + - Backported to 2.2.x + + LK1.2.3 (Ion Badulescu) + - Fix the flaky mdio interface + - More compat clean-ups + + LK1.2.4 (Ion Badulescu) + - More 2.2.x initialization fixes + + LK1.2.5 (Ion Badulescu) + - Several fixes from Manfred Spraul + + LK1.2.6 (Ion Badulescu) + - Fixed ifup/ifdown/ifup problem in 2.4.x + + LK1.2.7 (Ion Badulescu) + - Removed unused code + - Made more functions static and __init + + LK1.2.8 (Ion Badulescu) + - Quell bogus error messages, inform about the Tx threshold + - Removed #ifdef CONFIG_PCI, this driver is PCI only + + LK1.2.9 (Ion Badulescu) + - Merged Jeff Garzik's changes from 2.4.4-pre5 + - Added 2.2.x compatibility stuff required by the above changes + + LK1.2.9a (Ion Badulescu) + - More updates from Jeff Garzik + + LK1.3.0 (Ion Badulescu) + - Merged zerocopy support + + LK1.3.1 (Ion Badulescu) + - Added ethtool support + - Added GPIO (media change) interrupt support + + LK1.3.2 (Ion Badulescu) + - Fixed 2.2.x compatibility issues introduced in 1.3.1 + - Fixed ethtool ioctl returning uninitialized memory + +TODO: + - implement tx_timeout() properly */ +#define DRV_NAME "starfire" +#define DRV_VERSION "1.03+LK1.3.2" +#define DRV_RELDATE "June 04, 2001" + +/* + * Adaptec's license for their Novell drivers (which is where I got the + * firmware files) does not allow one to redistribute them. Thus, we can't + * include the firmware with this driver. + * + * However, an end-user is allowed to download and use it, after + * converting it to C header files using starfire_firmware.pl. + * Once that's done, the #undef below must be changed into a #define + * for this driver to really use the firmware. Note that Rx/Tx + * hardware TCP checksumming is not possible without the firmware. + * + * I'm currently [Feb 2001] talking to Adaptec about this redistribution + * issue. Stay tuned... + */ +#undef HAS_FIRMWARE +/* + * The current frame processor firmware fails to checksum a fragment + * of length 1. If and when this is fixed, the #define below can be removed. + */ +#define HAS_BROKEN_FIRMWARE +/* + * Define this if using the driver with the zero-copy patch + */ +#if defined(HAS_FIRMWARE) && defined(MAX_SKB_FRAGS) +#define ZEROCOPY +#endif + /* The user-configurable values. These may be modified when a driver module is loaded.*/ /* Used for tuning interrupt latency vs. overhead. */ -static int interrupt_mitigation = 0x0; +static int interrupt_mitigation; static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */ static int max_interrupt_work = 20; static int mtu; /* Maximum number of multicast addresses to filter (vs. rx-all-multicast). - The Starfire has a 512 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; + The Starfire has a 512 element hash table based on the Ethernet CRC. */ +static int multicast_filter_limit = 512; -/* Set the copy breakpoint for the copy-only-tiny-frames scheme. - Setting to > 1518 effectively disables this feature. */ -static int rx_copybreak = 0; +#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/ +/* + * Set the copy breakpoint for the copy-only-tiny-frames scheme. + * Setting to > 1518 effectively disables this feature. + * + * NOTE: + * The ia64 doesn't allow for unaligned loads even of integers being + * misaligned on a 2 byte boundary. Thus always force copying of + * packets as the starfire doesn't allow for misaligned DMAs ;-( + * 23/10/2000 - Jes + * + * The Alpha and the Sparc don't allow unaligned loads, either. -Ion + */ +#if defined(__ia64__) || defined(__alpha__) || defined(__sparc__) +static int rx_copybreak = PKT_BUF_SZ; +#else +static int rx_copybreak /* = 0 */; +#endif /* Used to pass the media type, etc. Both 'options[]' and 'full_duplex[]' exist for driver interoperability. The media type is usually passed in 'options[]'. */ #define MAX_UNITS 8 /* More are supported, limit only on options */ -static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; +static int options[MAX_UNITS] = {0, }; +static int full_duplex[MAX_UNITS] = {0, }; /* Operational parameters that are set at compile time. */ @@ -75,21 +174,23 @@ /* Operational parameters that usually are not changed. */ /* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (2*HZ) +#define TX_TIMEOUT (2 * HZ) -#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/ - -/* - * The ia64 doesn't allow for unaligned loads even of integers being - * misaligned on a 2 byte boundary. Thus always force copying of - * packets as the starfire doesn't allow for misaligned DMAs ;-( - * 23/10/2000 - Jes - */ -#ifdef __ia64__ -#define PKT_SHOULD_COPY(pkt_len) 1 -#else -#define PKT_SHOULD_COPY(pkt_len) (pkt_len < rx_copybreak) -#endif +#ifdef ZEROCOPY +#if MAX_SKB_FRAGS <= 6 +#define MAX_STARFIRE_FRAGS 6 +#else /* MAX_STARFIRE_FRAGS > 6 */ +#warning This driver will not work with more than 6 skb fragments. +#warning Turning off zerocopy support. +#undef ZEROCOPY +#endif /* MAX_STARFIRE_FRAGS > 6 */ +#endif /* ZEROCOPY */ + +#ifdef ZEROCOPY +#define skb_first_frag_len(skb) skb_headlen(skb) +#else /* not ZEROCOPY */ +#define skb_first_frag_len(skb) (skb->len) +#endif /* not ZEROCOPY */ #if !defined(__OPTIMIZE__) #warning You must compile this file with the correct options! @@ -97,28 +198,54 @@ #error You must compile this driver with "-O". #endif +#include #include #include -#include -#include -#include -#include -#include -#include #include #include #include -#include #include +#include #include /* Processor type for cache alignment. */ -#include +#include #include +#ifdef HAS_FIRMWARE +#include "starfire_firmware.h" +#endif /* HAS_FIRMWARE */ + +/* 2.2.x compatibility code */ +#if LINUX_VERSION_CODE < 0x20300 + +#include "starfire-kcomp22.h" + +#else /* LINUX_VERSION_CODE > 0x20300 */ + +#include +#include + +#define COMPAT_MOD_INC_USE_COUNT +#define COMPAT_MOD_DEC_USE_COUNT + +#define init_tx_timer(dev, func, timeout) \ + dev->tx_timeout = func; \ + dev->watchdog_timeo = timeout; +#define kick_tx_timer(dev, func, timeout) + +#define netif_start_if(dev) +#define netif_stop_if(dev) + +#define PCI_SLOT_NAME(pci_dev) (pci_dev)->slot_name + +#endif /* LINUX_VERSION_CODE > 0x20300 */ +/* end of compatibility code */ + + /* These identify the driver base version and may not be removed. */ static char version[] __devinitdata = KERN_INFO "starfire.c:v1.03 7/26/2000 Written by Donald Becker \n" KERN_INFO " Updates and info at http://www.scyld.com/network/starfire.html\n" -KERN_INFO " (unofficial 2.4.x kernel port, version 1.1.4a, April 17, 2001)\n"; +KERN_INFO " (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n"; MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver"); @@ -126,8 +253,15 @@ MODULE_PARM(mtu, "i"); MODULE_PARM(debug, "i"); MODULE_PARM(rx_copybreak, "i"); +MODULE_PARM(interrupt_mitigation, "i"); MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); +MODULE_PARM_DESC(max_interrupt_work, "Starfire maximum events handled per interrupt"); +MODULE_PARM_DESC(mtu, "Starfire MTU (all boards)"); +MODULE_PARM_DESC(debug, "Starfire debug level (0-6)"); +MODULE_PARM_DESC(rx_copybreak, "Starfire copy breakpoint for copy-only-tiny-frames"); +MODULE_PARM_DESC(options, "Starfire: Bits 0-3: media type, bit 17: full duplex"); +MODULE_PARM_DESC(full_duplex, "Starfire full duplex setting(s) (1)"); /* Theory of Operation @@ -158,8 +292,9 @@ See the Adaptec manual for the many possible structures, and options for each structure. There are far too many to document here. -For transmit this driver uses type 1 transmit descriptors, and relies on -automatic minimum-length padding. It does not use the completion queue +For transmit this driver uses type 0/1 transmit descriptors (depending +on the presence of the zerocopy infrastructure), and relies on automatic +minimum-length padding. It does not use the completion queue consumer index, but instead checks for non-zero status entries. For receive this driver uses type 0 receive descriptors. The driver @@ -174,10 +309,11 @@ phase of receive. A notable aspect of operation is that unaligned buffers are not permitted by -the Starfire hardware. The IP header at offset 14 in an ethernet frame thus +the Starfire hardware. Thus the IP header at offset 14 in an ethernet frame isn't longword aligned, which may cause problems on some machine -e.g. Alphas. Copied frames are put into the skbuff at an offset of "+2", -16-byte aligning the IP header. +e.g. Alphas and IA64. For these architectures, the driver is forced to copy +the frame into a new skbuff unconditionally. Copied frames are put into the +skbuff at an offset of "+2", thus 16-byte aligning the IP header. IIId. Synchronization @@ -212,7 +348,6 @@ enum chip_capability_flags {CanHaveMII=1, }; #define PCI_IOTYPE (PCI_USES_MASTER | PCI_USES_MEM | PCI_ADDR0) -#define MEM_ADDR_SZ 0x80000 /* And maps in 0.5MB(!). */ #if 0 #define ADDR_64BITS 1 /* This chip uses 64 bit addresses. */ @@ -233,10 +368,9 @@ /* A chip capabilities table, matching the CH_xxx entries in xxx_pci_tbl[] above. */ static struct chip_info { const char *name; - int io_size; int drv_flags; } netdrv_tbl[] __devinitdata = { - { "Adaptec Starfire 6915", MEM_ADDR_SZ, CanHaveMII }, + { "Adaptec Starfire 6915", CanHaveMII }, }; @@ -252,26 +386,40 @@ PCIDeviceConfig=0x50040, GenCtrl=0x50070, IntrTimerCtrl=0x50074, IntrClear=0x50080, IntrStatus=0x50084, IntrEnable=0x50088, MIICtrl=0x52000, StationAddr=0x50120, EEPROMCtrl=0x51000, - TxDescCtrl=0x50090, + GPIOCtrl=0x5008C, TxDescCtrl=0x50090, TxRingPtr=0x50098, HiPriTxRingPtr=0x50094, /* Low and High priority. */ TxRingHiAddr=0x5009C, /* 64 bit address extension. */ TxProducerIdx=0x500A0, TxConsumerIdx=0x500A4, TxThreshold=0x500B0, CompletionHiAddr=0x500B4, TxCompletionAddr=0x500B8, RxCompletionAddr=0x500BC, RxCompletionQ2Addr=0x500C0, - CompletionQConsumerIdx=0x500C4, + CompletionQConsumerIdx=0x500C4, RxDMACtrl=0x500D0, RxDescQCtrl=0x500D4, RxDescQHiAddr=0x500DC, RxDescQAddr=0x500E0, RxDescQIdx=0x500E8, RxDMAStatus=0x500F0, RxFilterMode=0x500F4, - TxMode=0x55000, + TxMode=0x55000, PerfFilterTable=0x56000, HashTable=0x56100, + TxGfpMem=0x58000, RxGfpMem=0x5a000, }; /* Bits in the interrupt status/mask registers. */ enum intr_status_bits { - IntrNormalSummary=0x8000, IntrAbnormalSummary=0x02000000, - IntrRxDone=0x0300, IntrRxEmpty=0x10040, IntrRxPCIErr=0x80000, - IntrTxDone=0x4000, IntrTxEmpty=0x1000, IntrTxPCIErr=0x80000, - StatsMax=0x08000000, LinkChange=0xf0000000, - IntrTxDataLow=0x00040000, + IntrLinkChange=0xf0000000, IntrStatsMax=0x08000000, + IntrAbnormalSummary=0x02000000, IntrGeneralTimer=0x01000000, + IntrSoftware=0x800000, IntrRxComplQ1Low=0x400000, + IntrTxComplQLow=0x200000, IntrPCI=0x100000, + IntrDMAErr=0x080000, IntrTxDataLow=0x040000, + IntrRxComplQ2Low=0x020000, IntrRxDescQ1Low=0x010000, + IntrNormalSummary=0x8000, IntrTxDone=0x4000, + IntrTxDMADone=0x2000, IntrTxEmpty=0x1000, + IntrEarlyRxQ2=0x0800, IntrEarlyRxQ1=0x0400, + IntrRxQ2Done=0x0200, IntrRxQ1Done=0x0100, + IntrRxGFPDead=0x80, IntrRxDescQ2Low=0x40, + IntrNoTxCsum=0x20, IntrTxBadID=0x10, + IntrHiPriTxBadID=0x08, IntrRxGfp=0x04, + IntrTxGfp=0x02, IntrPCIPad=0x01, + /* not quite bits */ + IntrRxDone=IntrRxQ2Done | IntrRxQ1Done, + IntrRxEmpty=IntrRxDescQ1Low | IntrRxDescQ2Low, + IntrNormalMask=0xf0, IntrAbnormalMask=0x3f0e, }; /* Bits in the RxFilterMode register. */ @@ -280,9 +428,40 @@ AcceptMulticast=0x10, AcceptMyPhys=0xE040, }; +/* Bits in the TxDescCtrl register. */ +enum tx_ctrl_bits { + TxDescSpaceUnlim=0x00, TxDescSpace32=0x10, TxDescSpace64=0x20, + TxDescSpace128=0x30, TxDescSpace256=0x40, + TxDescType0=0x00, TxDescType1=0x01, TxDescType2=0x02, + TxDescType3=0x03, TxDescType4=0x04, + TxNoDMACompletion=0x08, TxDescQ64bit=0x80, + TxHiPriFIFOThreshShift=24, TxPadLenShift=16, + TxDMABurstSizeShift=8, +}; + +/* Bits in the RxDescQCtrl register. */ +enum rx_ctrl_bits { + RxBufferLenShift=16, RxMinDescrThreshShift=0, + RxPrefetchMode=0x8000, Rx2048QEntries=0x4000, + RxVariableQ=0x2000, RxDesc64bit=0x1000, + RxDescQAddr64bit=0x0100, + RxDescSpace4=0x000, RxDescSpace8=0x100, + RxDescSpace16=0x200, RxDescSpace32=0x300, + RxDescSpace64=0x400, RxDescSpace128=0x500, + RxConsumerWrEn=0x80, +}; + +/* Bits in the RxCompletionAddr register */ +enum rx_compl_bits { + RxComplQAddr64bit=0x80, TxComplProducerWrEn=0x40, + RxComplType0=0x00, RxComplType1=0x10, + RxComplType2=0x20, RxComplType3=0x30, + RxComplThreshShift=0, +}; + /* The Rx and Tx buffer descriptors. */ struct starfire_rx_desc { - u32 rxaddr; /* Optionally 64 bits. */ + u32 rxaddr; /* Optionally 64 bits. */ }; enum rx_desc_bits { RxDescValid=1, RxDescEndRing=2, @@ -291,42 +470,72 @@ /* Completion queue entry. You must update the page allocation, init_ring and the shift count in rx() if using a larger format. */ +#ifdef HAS_FIRMWARE +#define csum_rx_status +#endif /* HAS_FIRMWARE */ struct rx_done_desc { - u32 status; /* Low 16 bits is length. */ + u32 status; /* Low 16 bits is length. */ +#ifdef csum_rx_status + u32 status2; /* Low 16 bits is csum */ +#endif /* csum_rx_status */ #ifdef full_rx_status u32 status2; u16 vlanid; - u16 csum; /* partial checksum */ + u16 csum; /* partial checksum */ u32 timestamp; -#endif +#endif /* full_rx_status */ }; enum rx_done_bits { RxOK=0x20000000, RxFIFOErr=0x10000000, RxBufQ2=0x08000000, }; +#ifdef ZEROCOPY +/* Type 0 Tx descriptor. */ +/* If more fragments are needed, don't forget to change the + descriptor spacing as well! */ +struct starfire_tx_desc { + u32 status; + u32 nbufs; + u32 first_addr; + u16 first_len; + u16 total_len; + struct { + u32 addr; + u32 len; + } frag[MAX_STARFIRE_FRAGS]; +}; +#else /* not ZEROCOPY */ /* Type 1 Tx descriptor. */ struct starfire_tx_desc { - u32 status; /* Upper bits are status, lower 16 length. */ - u32 addr; + u32 status; /* Upper bits are status, lower 16 length. */ + u32 first_addr; }; +#endif /* not ZEROCOPY */ enum tx_desc_bits { - TxDescID=0xB1010000, /* Also marks single fragment, add CRC. */ - TxDescIntr=0x08000000, TxRingWrap=0x04000000, + TxDescID=0xB0000000, + TxCRCEn=0x01000000, TxDescIntr=0x08000000, + TxRingWrap=0x04000000, TxCalTCP=0x02000000, }; struct tx_done_report { - u32 status; /* timestamp, index. */ + u32 status; /* timestamp, index. */ #if 0 - u32 intrstatus; /* interrupt status */ + u32 intrstatus; /* interrupt status */ #endif }; -#define PRIV_ALIGN 15 /* Required alignment mask */ -struct ring_info { +struct rx_ring_info { struct sk_buff *skb; dma_addr_t mapping; }; +struct tx_ring_info { + struct sk_buff *skb; + dma_addr_t first_mapping; +#ifdef ZEROCOPY + dma_addr_t frag_mapping[MAX_STARFIRE_FRAGS]; +#endif /* ZEROCOPY */ +}; -#define MII_CNT 4 +#define PHY_CNT 2 struct netdev_private { /* Descriptor rings first for alignment. */ struct starfire_rx_desc *rx_ring; @@ -334,66 +543,65 @@ dma_addr_t rx_ring_dma; dma_addr_t tx_ring_dma; /* The addresses of rx/tx-in-place skbuffs. */ - struct ring_info rx_info[RX_RING_SIZE]; - struct ring_info tx_info[TX_RING_SIZE]; - /* Pointers to completion queues (full pages). I should cache line pad..*/ - u8 pad0[100]; + struct rx_ring_info rx_info[RX_RING_SIZE]; + struct tx_ring_info tx_info[TX_RING_SIZE]; + /* Pointers to completion queues (full pages). */ struct rx_done_desc *rx_done_q; dma_addr_t rx_done_q_dma; unsigned int rx_done; struct tx_done_report *tx_done_q; - unsigned int tx_done; dma_addr_t tx_done_q_dma; + unsigned int tx_done; struct net_device_stats stats; - struct timer_list timer; /* Media monitoring timer. */ struct pci_dev *pci_dev; /* Frequently used values: keep some adjacent for cache effect. */ - unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */ + unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */ unsigned int cur_tx, dirty_tx; - unsigned int rx_buf_sz; /* Based on MTU+slack. */ - unsigned int tx_full:1; /* The Tx queue is full. */ + unsigned int rx_buf_sz; /* Based on MTU+slack. */ + unsigned int tx_full:1, /* The Tx queue is full. */ /* These values are keep track of the transceiver/media in use. */ - unsigned int full_duplex:1, /* Full-duplex operation requested. */ - medialock:1, /* Xcvr set to fixed speed/duplex. */ - rx_flowctrl:1, - tx_flowctrl:1; /* Use 802.3x flow control. */ - unsigned int default_port:4; /* Last dev->if_port value. */ + autoneg:1, /* Autonegotiation allowed. */ + full_duplex:1, /* Full-duplex operation. */ + speed100:1; /* Set if speed == 100MBit. */ + unsigned int intr_mitigation; u32 tx_mode; u8 tx_threshold; /* MII transceiver section. */ - int mii_cnt; /* MII device addresses. */ - u16 advertising; /* NWay media advertisement */ - unsigned char phys[MII_CNT]; /* MII device addresses, only first one used. */ -}; - -static int mdio_read(struct net_device *dev, int phy_id, int location); -static void mdio_write(struct net_device *dev, int phy_id, int location, int value); -static int netdev_open(struct net_device *dev); -static void check_duplex(struct net_device *dev, int startup); -static void netdev_timer(unsigned long data); -static void tx_timeout(struct net_device *dev); -static void init_ring(struct net_device *dev); -static int start_tx(struct sk_buff *skb, struct net_device *dev); -static void intr_handler(int irq, void *dev_instance, struct pt_regs *regs); -static void netdev_error(struct net_device *dev, int intr_status); -static int netdev_rx(struct net_device *dev); -static void netdev_error(struct net_device *dev, int intr_status); -static void set_rx_mode(struct net_device *dev); + u16 advertising; /* NWay media advertisement */ + int phy_cnt; /* MII device addresses. */ + unsigned char phys[PHY_CNT]; /* MII device addresses. */ +}; + +static int mdio_read(struct net_device *dev, int phy_id, int location); +static void mdio_write(struct net_device *dev, int phy_id, int location, int value); +static int netdev_open(struct net_device *dev); +static void check_duplex(struct net_device *dev); +static void tx_timeout(struct net_device *dev); +static void init_ring(struct net_device *dev); +static int start_tx(struct sk_buff *skb, struct net_device *dev); +static void intr_handler(int irq, void *dev_instance, struct pt_regs *regs); +static void netdev_error(struct net_device *dev, int intr_status); +static int netdev_rx(struct net_device *dev); +static void netdev_error(struct net_device *dev, int intr_status); +static void set_rx_mode(struct net_device *dev); static struct net_device_stats *get_stats(struct net_device *dev); -static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -static int netdev_close(struct net_device *dev); +static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); +static int netdev_close(struct net_device *dev); +static void netdev_media_change(struct net_device *dev); -static int __devinit starfire_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) +static int __devinit starfire_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct netdev_private *np; int i, irq, option, chip_idx = ent->driver_data; struct net_device *dev; static int card_idx = -1; long ioaddr; - int drv_flags, io_size = netdrv_tbl[chip_idx].io_size; + int drv_flags, io_size; + int boguscnt; + u8 cache; /* when built into the kernel, we only print version if device is found */ #ifndef MODULE @@ -403,38 +611,58 @@ #endif card_idx++; - option = card_idx < MAX_UNITS ? options[card_idx] : 0; if (pci_enable_device (pdev)) return -EIO; ioaddr = pci_resource_start (pdev, 0); + io_size = pci_resource_len (pdev, 0); if (!ioaddr || ((pci_resource_flags (pdev, 0) & IORESOURCE_MEM) == 0)) { - printk (KERN_ERR "starfire %d: no PCI MEM resources, aborting\n", card_idx); + printk (KERN_ERR DRV_NAME " %d: no PCI MEM resources, aborting\n", card_idx); return -ENODEV; } - + dev = alloc_etherdev(sizeof(*np)); if (!dev) { - printk (KERN_ERR "starfire %d: cannot alloc etherdev, aborting\n", card_idx); + printk (KERN_ERR DRV_NAME " %d: cannot alloc etherdev, aborting\n", card_idx); return -ENOMEM; } SET_MODULE_OWNER(dev); - - irq = pdev->irq; - if (pci_request_regions (pdev, "starfire")) + irq = pdev->irq; + + if (pci_request_regions (pdev, dev->name)) { + printk (KERN_ERR DRV_NAME " %d: cannot reserve PCI resources, aborting\n", card_idx); goto err_out_free_netdev; + } ioaddr = (long) ioremap (ioaddr, io_size); if (!ioaddr) { - printk (KERN_ERR "starfire %d: cannot remap 0x%x @ 0x%lx, aborting\n", + printk (KERN_ERR DRV_NAME " %d: cannot remap 0x%x @ 0x%lx, aborting\n", card_idx, io_size, ioaddr); goto err_out_free_res; } pci_set_master (pdev); - + + /* set PCI cache size */ + pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache); + if ((cache << 2) != SMP_CACHE_BYTES) { + printk(KERN_INFO " PCI cache line size set incorrectly " + "(%i bytes) by BIOS/FW, correcting to %i\n", + (cache << 2), SMP_CACHE_BYTES); + pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, + SMP_CACHE_BYTES >> 2); + } + +#ifdef ZEROCOPY + /* Starfire can do SG and TCP/UDP checksumming */ + dev->features |= NETIF_F_SG; +#ifdef HAS_FIRMWARE + dev->features |= NETIF_F_IP_CSUM; +#endif /* HAS_FIRMWARE */ +#endif /* ZEROCOPY */ + /* Serial EEPROM reads are hidden by the hardware. */ for (i = 0; i < 6; i++) dev->dev_addr[i] = readb(ioaddr + EEPROMCtrl + 20-i); @@ -442,12 +670,28 @@ #if ! defined(final_version) /* Dump the EEPROM contents during development. */ if (debug > 4) for (i = 0; i < 0x20; i++) - printk("%2.2x%s", (unsigned int)readb(ioaddr + EEPROMCtrl + i), - i % 16 != 15 ? " " : "\n"); + printk("%2.2x%s", + (unsigned int)readb(ioaddr + EEPROMCtrl + i), + i % 16 != 15 ? " " : "\n"); #endif + /* Issue soft reset */ + writel(0x8000, ioaddr + TxMode); + udelay(1000); + writel(0, ioaddr + TxMode); + /* Reset the chip to erase previous misconfiguration. */ writel(1, ioaddr + PCIDeviceConfig); + boguscnt = 1000; + while (--boguscnt > 0) { + udelay(10); + if ((readl(ioaddr + PCIDeviceConfig) & 1) == 0) + break; + } + if (boguscnt == 0) + printk("%s: chipset reset never completed!\n", dev->name); + /* wait a little longer */ + udelay(1000); dev->base_addr = ioaddr; dev->irq = irq; @@ -458,32 +702,31 @@ np->pci_dev = pdev; drv_flags = netdrv_tbl[chip_idx].drv_flags; + option = card_idx < MAX_UNITS ? options[card_idx] : 0; if (dev->mem_start) option = dev->mem_start; /* The lower four bits are the media type. */ - if (option > 0) { - if (option & 0x200) - np->full_duplex = 1; - np->default_port = option & 15; - if (np->default_port) - np->medialock = 1; - } - if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0) + if (option & 0x200) + np->full_duplex = 1; + + if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0) np->full_duplex = 1; if (np->full_duplex) - np->medialock = 1; + np->autoneg = 0; + else + np->autoneg = 1; + np->speed100 = 1; /* The chip-specific entries in the device structure. */ dev->open = &netdev_open; dev->hard_start_xmit = &start_tx; - dev->tx_timeout = &tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; + init_tx_timer(dev, tx_timeout, TX_TIMEOUT); dev->stop = &netdev_close; dev->get_stats = &get_stats; dev->set_multicast_list = &set_rx_mode; - dev->do_ioctl = &mii_ioctl; + dev->do_ioctl = &netdev_ioctl; if (mtu) dev->mtu = mtu; @@ -495,22 +738,35 @@ printk(KERN_INFO "%s: %s at 0x%lx, ", dev->name, netdrv_tbl[chip_idx].name, ioaddr); for (i = 0; i < 5; i++) - printk("%2.2x:", dev->dev_addr[i]); + printk("%2.2x:", dev->dev_addr[i]); printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq); if (drv_flags & CanHaveMII) { int phy, phy_idx = 0; - for (phy = 0; phy < 32 && phy_idx < MII_CNT; phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { + int mii_status; + for (phy = 0; phy < 32 && phy_idx < PHY_CNT; phy++) { + mdio_write(dev, phy, MII_BMCR, BMCR_RESET); + udelay(500); + boguscnt = 1000; + while (--boguscnt > 0) + if ((mdio_read(dev, phy, MII_BMCR) & BMCR_RESET) == 0) + break; + if (boguscnt == 0) { + printk("%s: PHY reset never completed!\n", dev->name); + continue; + } + mii_status = mdio_read(dev, phy, MII_BMSR); + if (mii_status != 0) { np->phys[phy_idx++] = phy; - np->advertising = mdio_read(dev, phy, 4); + np->advertising = mdio_read(dev, phy, MII_ADVERTISE); printk(KERN_INFO "%s: MII PHY found at address %d, status " "0x%4.4x advertising %4.4x.\n", dev->name, phy, mii_status, np->advertising); + /* there can be only one PHY on-board */ + break; } } - np->mii_cnt = phy_idx; + np->phy_cnt = phy_idx; } return 0; @@ -536,7 +792,11 @@ /* ??? Should we add a busy-wait here? */ do result = readl(mdio_addr); - while ((result & 0xC0000000) != 0x80000000 && --boguscnt >= 0); + while ((result & 0xC0000000) != 0x80000000 && --boguscnt > 0); + if (boguscnt == 0) + return 0; + if ((result & 0xffff) == 0xffff) + return 0; return result & 0xffff; } @@ -557,48 +817,70 @@ /* Do we ever need to reset the chip??? */ + COMPAT_MOD_INC_USE_COUNT; + retval = request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev); - if (retval) + if (retval) { + COMPAT_MOD_DEC_USE_COUNT; return retval; + } /* Disable the Rx and Tx, and reset the chip. */ writel(0, ioaddr + GenCtrl); writel(1, ioaddr + PCIDeviceConfig); if (debug > 1) printk(KERN_DEBUG "%s: netdev_open() irq %d.\n", - dev->name, dev->irq); + dev->name, dev->irq); /* Allocate the various queues, failing gracefully. */ if (np->tx_done_q == 0) np->tx_done_q = pci_alloc_consistent(np->pci_dev, PAGE_SIZE, &np->tx_done_q_dma); if (np->rx_done_q == 0) - np->rx_done_q = pci_alloc_consistent(np->pci_dev, PAGE_SIZE, &np->rx_done_q_dma); + np->rx_done_q = pci_alloc_consistent(np->pci_dev, sizeof(struct rx_done_desc) * DONE_Q_SIZE, &np->rx_done_q_dma); if (np->tx_ring == 0) np->tx_ring = pci_alloc_consistent(np->pci_dev, PAGE_SIZE, &np->tx_ring_dma); if (np->rx_ring == 0) np->rx_ring = pci_alloc_consistent(np->pci_dev, PAGE_SIZE, &np->rx_ring_dma); - if (np->tx_done_q == 0 || np->rx_done_q == 0 - || np->rx_ring == 0 || np->tx_ring == 0) { + if (np->tx_done_q == 0 || np->rx_done_q == 0 + || np->rx_ring == 0 || np->tx_ring == 0) { if (np->tx_done_q) pci_free_consistent(np->pci_dev, PAGE_SIZE, - np->tx_done_q, np->tx_done_q_dma); + np->tx_done_q, np->tx_done_q_dma); if (np->rx_done_q) - pci_free_consistent(np->pci_dev, PAGE_SIZE, - np->rx_done_q, np->rx_done_q_dma); + pci_free_consistent(np->pci_dev, sizeof(struct rx_done_desc) * DONE_Q_SIZE, + np->rx_done_q, np->rx_done_q_dma); if (np->tx_ring) pci_free_consistent(np->pci_dev, PAGE_SIZE, - np->tx_ring, np->tx_ring_dma); + np->tx_ring, np->tx_ring_dma); if (np->rx_ring) pci_free_consistent(np->pci_dev, PAGE_SIZE, - np->rx_ring, np->rx_ring_dma); + np->rx_ring, np->rx_ring_dma); + COMPAT_MOD_DEC_USE_COUNT; return -ENOMEM; } init_ring(dev); /* Set the size of the Rx buffers. */ - writel((np->rx_buf_sz<<16) | 0xA000, ioaddr + RxDescQCtrl); - + writel((np->rx_buf_sz << RxBufferLenShift) | + (0 << RxMinDescrThreshShift) | + RxPrefetchMode | RxVariableQ | + RxDescSpace4, + ioaddr + RxDescQCtrl); + +#ifdef ZEROCOPY + /* Set Tx descriptor to type 0 and spacing to 64 bytes. */ + writel((2 << TxHiPriFIFOThreshShift) | + (0 << TxPadLenShift) | + (4 << TxDMABurstSizeShift) | + TxDescSpace64 | TxDescType0, + ioaddr + TxDescCtrl); +#else /* not ZEROCOPY */ /* Set Tx descriptor to type 1 and padding to 0 bytes. */ - writel(0x02000401, ioaddr + TxDescCtrl); + writel((2 << TxHiPriFIFOThreshShift) | + (0 << TxPadLenShift) | + (4 << TxDMABurstSizeShift) | + TxDescSpaceUnlim | TxDescType1, + ioaddr + TxDescCtrl); +#endif /* not ZEROCOPY */ #if defined(ADDR_64BITS) && defined(__alpha__) /* XXX We really need a 64-bit PCI dma interfaces too... -DaveM */ @@ -613,17 +895,34 @@ writel(np->tx_ring_dma, ioaddr + TxRingPtr); writel(np->tx_done_q_dma, ioaddr + TxCompletionAddr); - writel(np->rx_done_q_dma, ioaddr + RxCompletionAddr); +#ifdef full_rx_status + writel(np->rx_done_q_dma | + RxComplType3 | + (0 << RxComplThreshShift), + ioaddr + RxCompletionAddr); +#else /* not full_rx_status */ +#ifdef csum_rx_status + writel(np->rx_done_q_dma | + RxComplType2 | + (0 << RxComplThreshShift), + ioaddr + RxCompletionAddr); +#else /* not csum_rx_status */ + writel(np->rx_done_q_dma | + RxComplType0 | + (0 << RxComplThreshShift), + ioaddr + RxCompletionAddr); +#endif /* not csum_rx_status */ +#endif /* not full_rx_status */ if (debug > 1) - printk(KERN_DEBUG "%s: Filling in the station address.\n", dev->name); + printk(KERN_DEBUG "%s: Filling in the station address.\n", dev->name); /* Fill both the unused Tx SA register and the Rx perfect filter. */ for (i = 0; i < 6; i++) writeb(dev->dev_addr[i], ioaddr + StationAddr + 5-i); for (i = 0; i < 16; i++) { u16 *eaddrs = (u16 *)dev->dev_addr; - long setup_frm = ioaddr + 0x56000 + i*16; + long setup_frm = ioaddr + PerfFilterTable + i * 16; writew(cpu_to_be16(eaddrs[2]), setup_frm); setup_frm += 4; writew(cpu_to_be16(eaddrs[1]), setup_frm); setup_frm += 4; writew(cpu_to_be16(eaddrs[0]), setup_frm); setup_frm += 8; @@ -631,116 +930,93 @@ /* Initialize other registers. */ /* Configure the PCI bus bursts and FIFO thresholds. */ - np->tx_mode = 0; /* Initialized when TxMode set. */ + np->tx_mode = 0x0C04; /* modified when link is up. */ np->tx_threshold = 4; writel(np->tx_threshold, ioaddr + TxThreshold); - writel(interrupt_mitigation, ioaddr + IntrTimerCtrl); - if (dev->if_port == 0) - dev->if_port = np->default_port; + interrupt_mitigation &= 0x1f; + np->intr_mitigation = interrupt_mitigation; + writel(np->intr_mitigation, ioaddr + IntrTimerCtrl); + netif_start_if(dev); netif_start_queue(dev); if (debug > 1) - printk(KERN_DEBUG "%s: Setting the Rx and Tx modes.\n", dev->name); + printk(KERN_DEBUG "%s: Setting the Rx and Tx modes.\n", dev->name); set_rx_mode(dev); - np->advertising = mdio_read(dev, np->phys[0], 4); - check_duplex(dev, 1); + np->advertising = mdio_read(dev, np->phys[0], MII_ADVERTISE); + check_duplex(dev); + + /* Enable GPIO interrupts on link change */ + writel(0x0f00ff00, ioaddr + GPIOCtrl); /* Set the interrupt mask and enable PCI interrupts. */ - writel(IntrRxDone | IntrRxEmpty | IntrRxPCIErr | - IntrTxDone | IntrTxEmpty | IntrTxPCIErr | - StatsMax | LinkChange | IntrNormalSummary | IntrAbnormalSummary - | 0x0010 , ioaddr + IntrEnable); + writel(IntrRxDone | IntrRxEmpty | IntrDMAErr | + IntrTxDone | IntrStatsMax | IntrLinkChange | + IntrNormalSummary | IntrAbnormalSummary | + IntrRxGFPDead | IntrNoTxCsum | IntrTxBadID, + ioaddr + IntrEnable); writel(0x00800000 | readl(ioaddr + PCIDeviceConfig), - ioaddr + PCIDeviceConfig); + ioaddr + PCIDeviceConfig); - /* Enable the Rx and Tx units. */ +#ifdef HAS_FIRMWARE + /* Load Rx/Tx firmware into the frame processors */ + for (i = 0; i < FIRMWARE_RX_SIZE * 2; i++) + writel(cpu_to_le32(firmware_rx[i]), ioaddr + RxGfpMem + i * 4); + for (i = 0; i < FIRMWARE_TX_SIZE * 2; i++) + writel(cpu_to_le32(firmware_tx[i]), ioaddr + TxGfpMem + i * 4); + /* Enable the Rx and Tx units, and the Rx/Tx frame processors. */ + writel(0x003F, ioaddr + GenCtrl); +#else /* not HAS_FIRMWARE */ + /* Enable the Rx and Tx units only. */ writel(0x000F, ioaddr + GenCtrl); +#endif /* not HAS_FIRMWARE */ if (debug > 2) printk(KERN_DEBUG "%s: Done netdev_open().\n", - dev->name); - - /* Set the timer to check for link beat. */ - init_timer(&np->timer); - np->timer.expires = jiffies + 3*HZ; - np->timer.data = (unsigned long)dev; - np->timer.function = &netdev_timer; /* timer handler */ - add_timer(&np->timer); + dev->name); return 0; } -static void check_duplex(struct net_device *dev, int startup) + +static void check_duplex(struct net_device *dev) { struct netdev_private *np = dev->priv; - long ioaddr = dev->base_addr; - int new_tx_mode ; + u16 reg0; - new_tx_mode = 0x0C04 | (np->tx_flowctrl ? 0x0800:0) - | (np->rx_flowctrl ? 0x0400:0); - if (np->medialock) { - if (np->full_duplex) - new_tx_mode |= 2; - } else { - int mii_reg5 = mdio_read(dev, np->phys[0], 5); - int negotiated = mii_reg5 & np->advertising; - int duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040; - if (duplex) - new_tx_mode |= 2; - if (np->full_duplex != duplex) { - np->full_duplex = duplex; - if (debug > 1) - printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d" - " negotiated capability %4.4x.\n", dev->name, - duplex ? "full" : "half", np->phys[0], negotiated); - } - } - if (new_tx_mode != np->tx_mode) { - np->tx_mode = new_tx_mode; - writel(np->tx_mode | 0x8000, ioaddr + TxMode); - writel(np->tx_mode, ioaddr + TxMode); - } -} + mdio_write(dev, np->phys[0], MII_ADVERTISE, np->advertising); + mdio_write(dev, np->phys[0], MII_BMCR, BMCR_RESET); + udelay(500); + while (mdio_read(dev, np->phys[0], MII_BMCR) & BMCR_RESET); -static void netdev_timer(unsigned long data) -{ - struct net_device *dev = (struct net_device *)data; - struct netdev_private *np = dev->priv; - long ioaddr = dev->base_addr; - int next_tick = 60*HZ; /* Check before driver release. */ + reg0 = mdio_read(dev, np->phys[0], MII_BMCR); - if (debug > 3) { - printk(KERN_DEBUG "%s: Media selection timer tick, status %8.8x.\n", - dev->name, (int)readl(ioaddr + IntrStatus)); - } - check_duplex(dev, 0); -#if ! defined(final_version) - /* This is often falsely triggered. */ - if (readl(ioaddr + IntrStatus) & 1) { - int new_status = readl(ioaddr + IntrStatus); - /* Bogus hardware IRQ: Fake an interrupt handler call. */ - if (new_status & 1) { - printk(KERN_ERR "%s: Interrupt blocked, status %8.8x/%8.8x.\n", - dev->name, new_status, (int)readl(ioaddr + IntrStatus)); - intr_handler(dev->irq, dev, 0); - } + if (np->autoneg) { + reg0 |= BMCR_ANENABLE | BMCR_ANRESTART; + } else { + reg0 &= ~(BMCR_ANENABLE | BMCR_ANRESTART); + if (np->speed100) + reg0 |= BMCR_SPEED100; + if (np->full_duplex) + reg0 |= BMCR_FULLDPLX; + printk(KERN_DEBUG "%s: Link forced to %sMbit %s-duplex\n", + dev->name, + np->speed100 ? "100" : "10", + np->full_duplex ? "full" : "half"); } -#endif - - np->timer.expires = jiffies + next_tick; - add_timer(&np->timer); + mdio_write(dev, np->phys[0], MII_BMCR, reg0); } + static void tx_timeout(struct net_device *dev) { struct netdev_private *np = dev->priv; long ioaddr = dev->base_addr; printk(KERN_WARNING "%s: Transmit timed out, status %8.8x," - " resetting...\n", dev->name, (int)readl(ioaddr + IntrStatus)); + " resetting...\n", dev->name, (int)readl(ioaddr + IntrStatus)); #ifndef __alpha__ { @@ -756,21 +1032,20 @@ #endif /* Perhaps we should reinitialize the hardware here. */ - dev->if_port = 0; /* Stop and restart the chip's Tx processes . */ /* Trigger an immediate transmit demand. */ dev->trans_start = jiffies; np->stats.tx_errors++; - return; + netif_wake_queue(dev); } /* Initialize the Rx and Tx rings, along with various 'dev' bits. */ static void init_ring(struct net_device *dev) { - struct netdev_private *np = (struct netdev_private *)dev->priv; + struct netdev_private *np = dev->priv; int i; np->tx_full = 0; @@ -810,7 +1085,14 @@ for (i = 0; i < TX_RING_SIZE; i++) { np->tx_info[i].skb = NULL; - np->tx_info[i].mapping = 0; + np->tx_info[i].first_mapping = 0; +#ifdef ZEROCOPY + { + int j; + for (j = 0; j < MAX_STARFIRE_FRAGS; j++) + np->tx_info[i].frag_mapping[j] = 0; + } +#endif /* ZEROCOPY */ np->tx_ring[i].status = 0; } return; @@ -820,6 +1102,11 @@ { struct netdev_private *np = dev->priv; unsigned int entry; +#ifdef ZEROCOPY + int i; +#endif + + kick_tx_timer(dev, tx_timeout, TX_TIMEOUT); /* Caution: the write order is important here, set the field with the "ownership" bits last. */ @@ -827,26 +1114,87 @@ /* Calculate the next Tx descriptor entry. */ entry = np->cur_tx % TX_RING_SIZE; +#if defined(ZEROCOPY) && defined(HAS_FIRMWARE) && defined(HAS_BROKEN_FIRMWARE) + { + int has_bad_length = 0; + + if (skb_first_frag_len(skb) == 1) + has_bad_length = 1; + else { + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) + if (skb_shinfo(skb)->frags[i].size == 1) { + has_bad_length = 1; + break; + } + } + + if (has_bad_length) + skb_checksum_help(skb); + } +#endif /* ZEROCOPY && HAS_FIRMWARE && HAS_BROKEN_FIRMWARE */ + np->tx_info[entry].skb = skb; - np->tx_info[entry].mapping = - pci_map_single(np->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE); + np->tx_info[entry].first_mapping = + pci_map_single(np->pci_dev, skb->data, skb_first_frag_len(skb), PCI_DMA_TODEVICE); + + np->tx_ring[entry].first_addr = cpu_to_le32(np->tx_info[entry].first_mapping); +#ifdef ZEROCOPY + np->tx_ring[entry].first_len = cpu_to_le32(skb_first_frag_len(skb)); + np->tx_ring[entry].total_len = cpu_to_le32(skb->len); + /* Add "| TxDescIntr" to generate Tx-done interrupts. */ + np->tx_ring[entry].status = cpu_to_le32(TxDescID | TxCRCEn); + np->tx_ring[entry].nbufs = cpu_to_le32(skb_shinfo(skb)->nr_frags + 1); +#else /* not ZEROCOPY */ + /* Add "| TxDescIntr" to generate Tx-done interrupts. */ + np->tx_ring[entry].status = cpu_to_le32(skb->len | TxDescID | TxCRCEn | 1 << 16); +#endif /* not ZEROCOPY */ + + if (entry >= TX_RING_SIZE-1) /* Wrap ring */ + np->tx_ring[entry].status |= cpu_to_le32(TxRingWrap | TxDescIntr); + +#ifdef ZEROCOPY + if (skb->ip_summed == CHECKSUM_HW) + np->tx_ring[entry].status |= cpu_to_le32(TxCalTCP); +#endif /* ZEROCOPY */ - np->tx_ring[entry].addr = cpu_to_le32(np->tx_info[entry].mapping); - /* Add "| TxDescIntr" to generate Tx-done interrupts. */ - np->tx_ring[entry].status = cpu_to_le32(skb->len | TxDescID); if (debug > 5) { - printk(KERN_DEBUG "%s: Tx #%d slot %d %8.8x %8.8x.\n", - dev->name, np->cur_tx, entry, - le32_to_cpu(np->tx_ring[entry].status), - le32_to_cpu(np->tx_ring[entry].addr)); +#ifdef ZEROCOPY + printk(KERN_DEBUG "%s: Tx #%d slot %d status %8.8x nbufs %d len %4.4x/%4.4x.\n", + dev->name, np->cur_tx, entry, + le32_to_cpu(np->tx_ring[entry].status), + le32_to_cpu(np->tx_ring[entry].nbufs), + le32_to_cpu(np->tx_ring[entry].first_len), + le32_to_cpu(np->tx_ring[entry].total_len)); +#else /* not ZEROCOPY */ + printk(KERN_DEBUG "%s: Tx #%d slot %d status %8.8x.\n", + dev->name, np->cur_tx, entry, + le32_to_cpu(np->tx_ring[entry].status)); +#endif /* not ZEROCOPY */ + } + +#ifdef ZEROCOPY + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + skb_frag_t *this_frag = &skb_shinfo(skb)->frags[i]; + + /* we already have the proper value in entry */ + np->tx_info[entry].frag_mapping[i] = + pci_map_single(np->pci_dev, page_address(this_frag->page) + this_frag->page_offset, this_frag->size, PCI_DMA_TODEVICE); + + np->tx_ring[entry].frag[i].addr = cpu_to_le32(np->tx_info[entry].frag_mapping[i]); + np->tx_ring[entry].frag[i].len = cpu_to_le32(this_frag->size); + if (debug > 5) { + printk(KERN_DEBUG "%s: Tx #%d frag %d len %4.4x.\n", + dev->name, np->cur_tx, i, + le32_to_cpu(np->tx_ring[entry].frag[i].len)); + } } +#endif /* ZEROCOPY */ + np->cur_tx++; -#if 1 - if (entry >= TX_RING_SIZE-1) { /* Wrap ring */ - np->tx_ring[entry].status |= cpu_to_le32(TxRingWrap | TxDescIntr); + + if (entry >= TX_RING_SIZE-1) /* Wrap ring */ entry = -1; - } -#endif + entry++; /* Non-x86: explicitly flush descriptor cache lines here. */ /* Ensure everything is written back above before the transmit is @@ -854,18 +1202,15 @@ wmb(); /* Update the producer index. */ - writel(++entry, dev->base_addr + TxProducerIdx); + writel(entry * (sizeof(struct starfire_tx_desc) / 8), dev->base_addr + TxProducerIdx); if (np->cur_tx - np->dirty_tx >= TX_RING_SIZE - 1) { np->tx_full = 1; netif_stop_queue(dev); } + dev->trans_start = jiffies; - if (debug > 4) { - printk(KERN_DEBUG "%s: Transmit frame #%d queued in slot %d.\n", - dev->name, np->cur_tx, entry); - } return 0; } @@ -877,24 +1222,25 @@ struct netdev_private *np; long ioaddr; int boguscnt = max_interrupt_work; + int consumer; + int tx_status; #ifndef final_version /* Can never occur. */ if (dev == NULL) { - printk (KERN_ERR "Netdev interrupt handler(): IRQ %d for unknown " - "device.\n", irq); + printk (KERN_ERR "Netdev interrupt handler(): IRQ %d for unknown device.\n", irq); return; } #endif ioaddr = dev->base_addr; - np = (struct netdev_private *)dev->priv; + np = dev->priv; do { u32 intr_status = readl(ioaddr + IntrClear); if (debug > 4) printk(KERN_DEBUG "%s: Interrupt status %4.4x.\n", - dev->name, intr_status); + dev->name, intr_status); if (intr_status == 0) break; @@ -905,77 +1251,99 @@ /* Scavenge the skbuff list based on the Tx-done queue. There are redundant checks here that may be cleaned up after the driver has proven to be reliable. */ - { - int consumer = readl(ioaddr + TxConsumerIdx); - int tx_status; - if (debug > 4) - printk(KERN_DEBUG "%s: Tx Consumer index is %d.\n", - dev->name, consumer); + consumer = readl(ioaddr + TxConsumerIdx); + if (debug > 4) + printk(KERN_DEBUG "%s: Tx Consumer index is %d.\n", + dev->name, consumer); #if 0 - if (np->tx_done >= 250 || np->tx_done == 0) - printk(KERN_DEBUG "%s: Tx completion entry %d is %8.8x, " - "%d is %8.8x.\n", dev->name, - np->tx_done, le32_to_cpu(np->tx_done_q[np->tx_done].status), - (np->tx_done+1) & (DONE_Q_SIZE-1), - le32_to_cpu(np->tx_done_q[(np->tx_done+1)&(DONE_Q_SIZE-1)].status)); + if (np->tx_done >= 250 || np->tx_done == 0) + printk(KERN_DEBUG "%s: Tx completion entry %d is %8.8x, %d is %8.8x.\n", + dev->name, np->tx_done, + le32_to_cpu(np->tx_done_q[np->tx_done].status), + (np->tx_done+1) & (DONE_Q_SIZE-1), + le32_to_cpu(np->tx_done_q[(np->tx_done+1)&(DONE_Q_SIZE-1)].status)); #endif - while ((tx_status = le32_to_cpu(np->tx_done_q[np->tx_done].status)) - != 0) { - if (debug > 4) - printk(KERN_DEBUG "%s: Tx completion entry %d is %8.8x.\n", - dev->name, np->tx_done, tx_status); - if ((tx_status & 0xe0000000) == 0xa0000000) { - np->stats.tx_packets++; - } else if ((tx_status & 0xe0000000) == 0x80000000) { - struct sk_buff *skb; - u16 entry = tx_status; /* Implicit truncate */ - entry >>= 3; - skb = np->tx_info[entry].skb; - pci_unmap_single(np->pci_dev, - np->tx_info[entry].mapping, - skb->len, PCI_DMA_TODEVICE); + while ((tx_status = le32_to_cpu(np->tx_done_q[np->tx_done].status)) != 0) { + if (debug > 4) + printk(KERN_DEBUG "%s: Tx completion entry %d is %8.8x.\n", + dev->name, np->tx_done, tx_status); + if ((tx_status & 0xe0000000) == 0xa0000000) { + np->stats.tx_packets++; + } else if ((tx_status & 0xe0000000) == 0x80000000) { + struct sk_buff *skb; +#ifdef ZEROCOPY + int i; +#endif /* ZEROCOPY */ + u16 entry = tx_status; /* Implicit truncate */ + entry /= sizeof(struct starfire_tx_desc); + + skb = np->tx_info[entry].skb; + np->tx_info[entry].skb = NULL; + pci_unmap_single(np->pci_dev, + np->tx_info[entry].first_mapping, + skb_first_frag_len(skb), + PCI_DMA_TODEVICE); + np->tx_info[entry].first_mapping = 0; - /* Scavenge the descriptor. */ - dev_kfree_skb_irq(skb); - np->tx_info[entry].skb = NULL; - np->tx_info[entry].mapping = 0; - np->dirty_tx++; +#ifdef ZEROCOPY + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + pci_unmap_single(np->pci_dev, + np->tx_info[entry].frag_mapping[i], + skb_shinfo(skb)->frags[i].size, + PCI_DMA_TODEVICE); + np->tx_info[entry].frag_mapping[i] = 0; } - np->tx_done_q[np->tx_done].status = 0; - np->tx_done = (np->tx_done+1) & (DONE_Q_SIZE-1); +#endif /* ZEROCOPY */ + + /* Scavenge the descriptor. */ + dev_kfree_skb_irq(skb); + + np->dirty_tx++; } - writew(np->tx_done, ioaddr + CompletionQConsumerIdx + 2); + np->tx_done_q[np->tx_done].status = 0; + np->tx_done = (np->tx_done+1) & (DONE_Q_SIZE-1); } + writew(np->tx_done, ioaddr + CompletionQConsumerIdx + 2); + if (np->tx_full && np->cur_tx - np->dirty_tx < TX_RING_SIZE - 4) { /* The ring is no longer full, wake the queue. */ np->tx_full = 0; netif_wake_queue(dev); } + /* Stats overflow */ + if (intr_status & IntrStatsMax) { + get_stats(dev); + } + + /* Media change interrupt. */ + if (intr_status & IntrLinkChange) + netdev_media_change(dev); + /* Abnormal error summary/uncommon events handlers. */ if (intr_status & IntrAbnormalSummary) netdev_error(dev, intr_status); if (--boguscnt < 0) { printk(KERN_WARNING "%s: Too much work at interrupt, " - "status=0x%4.4x.\n", - dev->name, intr_status); + "status=0x%4.4x.\n", + dev->name, intr_status); break; } } while (1); if (debug > 4) printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n", - dev->name, (int)readl(ioaddr + IntrStatus)); + dev->name, (int)readl(ioaddr + IntrStatus)); #ifndef final_version /* Code that should never be run! Remove after testing.. */ { static int stopit = 10; - if (!netif_running(dev) && --stopit < 0) { + if (!netif_running(dev) && --stopit < 0) { printk(KERN_ERR "%s: Emergency stop, looping startup interrupt.\n", - dev->name); + dev->name); free_irq(irq, dev); } } @@ -992,83 +1360,99 @@ if (np->rx_done_q == 0) { printk(KERN_ERR "%s: rx_done_q is NULL! rx_done is %d. %p.\n", - dev->name, np->rx_done, np->tx_done_q); + dev->name, np->rx_done, np->tx_done_q); return 0; } /* If EOP is set on the next entry, it's a new packet. Send it up. */ while ((desc_status = le32_to_cpu(np->rx_done_q[np->rx_done].status)) != 0) { + struct sk_buff *skb; + u16 pkt_len; + int entry; + if (debug > 4) - printk(KERN_DEBUG " netdev_rx() status of %d was %8.8x.\n", - np->rx_done, desc_status); + printk(KERN_DEBUG " netdev_rx() status of %d was %8.8x.\n", np->rx_done, desc_status); if (--boguscnt < 0) break; if ( ! (desc_status & RxOK)) { /* There was a error. */ if (debug > 2) - printk(KERN_DEBUG " netdev_rx() Rx error was %8.8x.\n", - desc_status); + printk(KERN_DEBUG " netdev_rx() Rx error was %8.8x.\n", desc_status); np->stats.rx_errors++; if (desc_status & RxFIFOErr) np->stats.rx_fifo_errors++; - } else { - struct sk_buff *skb; - u16 pkt_len = desc_status; /* Implicitly Truncate */ - int entry = (desc_status >> 16) & 0x7ff; + goto next_rx; + } + + pkt_len = desc_status; /* Implicitly Truncate */ + entry = (desc_status >> 16) & 0x7ff; #ifndef final_version - if (debug > 4) - printk(KERN_DEBUG " netdev_rx() normal Rx pkt length %d" - ", bogus_cnt %d.\n", - pkt_len, boguscnt); + if (debug > 4) + printk(KERN_DEBUG " netdev_rx() normal Rx pkt length %d, bogus_cnt %d.\n", pkt_len, boguscnt); #endif - /* Check if the packet is long enough to accept without copying - to a minimally-sized skbuff. */ - if (PKT_SHOULD_COPY(pkt_len) - && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) { - skb->dev = dev; - skb_reserve(skb, 2); /* 16 byte align the IP header */ - pci_dma_sync_single(np->pci_dev, - np->rx_info[entry].mapping, - pkt_len, PCI_DMA_FROMDEVICE); + /* Check if the packet is long enough to accept without copying + to a minimally-sized skbuff. */ + if (pkt_len < rx_copybreak + && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) { + skb->dev = dev; + skb_reserve(skb, 2); /* 16 byte align the IP header */ + pci_dma_sync_single(np->pci_dev, + np->rx_info[entry].mapping, + pkt_len, PCI_DMA_FROMDEVICE); #if HAS_IP_COPYSUM /* Call copy + cksum if available. */ - eth_copy_and_sum(skb, np->rx_info[entry].skb->tail, pkt_len, 0); - skb_put(skb, pkt_len); + eth_copy_and_sum(skb, np->rx_info[entry].skb->tail, pkt_len, 0); + skb_put(skb, pkt_len); #else - memcpy(skb_put(skb, pkt_len), np->rx_info[entry].skb->tail, - pkt_len); + memcpy(skb_put(skb, pkt_len), np->rx_info[entry].skb->tail, pkt_len); #endif - } else { - char *temp; + } else { + char *temp; - pci_unmap_single(np->pci_dev, np->rx_info[entry].mapping, np->rx_buf_sz, PCI_DMA_FROMDEVICE); - skb = np->rx_info[entry].skb; - temp = skb_put(skb, pkt_len); - np->rx_info[entry].skb = NULL; - np->rx_info[entry].mapping = 0; - } -#ifndef final_version /* Remove after testing. */ - /* You will want this info for the initial debug. */ - if (debug > 5) - printk(KERN_DEBUG " Rx data %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:" - "%2.2x %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x %2.2x%2.2x " - "%d.%d.%d.%d.\n", - skb->data[0], skb->data[1], skb->data[2], skb->data[3], - skb->data[4], skb->data[5], skb->data[6], skb->data[7], - skb->data[8], skb->data[9], skb->data[10], - skb->data[11], skb->data[12], skb->data[13], - skb->data[14], skb->data[15], skb->data[16], - skb->data[17]); -#endif - skb->protocol = eth_type_trans(skb, dev); -#ifdef full_rx_status - if (le32_to_cpu(np->rx_done_q[np->rx_done].status2) & 0x01000000) - skb->ip_summed = CHECKSUM_UNNECESSARY; + pci_unmap_single(np->pci_dev, np->rx_info[entry].mapping, np->rx_buf_sz, PCI_DMA_FROMDEVICE); + skb = np->rx_info[entry].skb; + temp = skb_put(skb, pkt_len); + np->rx_info[entry].skb = NULL; + np->rx_info[entry].mapping = 0; + } +#ifndef final_version /* Remove after testing. */ + /* You will want this info for the initial debug. */ + if (debug > 5) + printk(KERN_DEBUG " Rx data %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:" + "%2.2x %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x %2.2x%2.2x " + "%d.%d.%d.%d.\n", + skb->data[0], skb->data[1], skb->data[2], skb->data[3], + skb->data[4], skb->data[5], skb->data[6], skb->data[7], + skb->data[8], skb->data[9], skb->data[10], + skb->data[11], skb->data[12], skb->data[13], + skb->data[14], skb->data[15], skb->data[16], + skb->data[17]); #endif - netif_rx(skb); - dev->last_rx = jiffies; - np->stats.rx_packets++; + skb->protocol = eth_type_trans(skb, dev); +#if defined(full_rx_status) || defined(csum_rx_status) + if (le32_to_cpu(np->rx_done_q[np->rx_done].status2) & 0x01000000) { + skb->ip_summed = CHECKSUM_UNNECESSARY; } + /* + * This feature doesn't seem to be working, at least + * with the two firmware versions I have. If the GFP sees + * a fragment, it either ignores it completely, or reports + * "bad checksum" on it. + * + * Maybe I missed something -- corrections are welcome. + * Until then, the printk stays. :-) -Ion + */ + else if (le32_to_cpu(np->rx_done_q[np->rx_done].status2) & 0x00400000) { + skb->ip_summed = CHECKSUM_HW; + skb->csum = le32_to_cpu(np->rx_done_q[np->rx_done].status2) & 0xffff; + printk(KERN_DEBUG "%s: checksum_hw, status2 = %x\n", dev->name, np->rx_done_q[np->rx_done].status2); + } +#endif + netif_rx(skb); + dev->last_rx = jiffies; + np->stats.rx_packets++; + +next_rx: np->cur_rx++; np->rx_done_q[np->rx_done].status = 0; np->rx_done = (np->rx_done + 1) & (DONE_Q_SIZE-1); @@ -1083,10 +1467,10 @@ skb = dev_alloc_skb(np->rx_buf_sz); np->rx_info[entry].skb = skb; if (skb == NULL) - break; /* Better luck next round. */ + break; /* Better luck next round. */ np->rx_info[entry].mapping = pci_map_single(np->pci_dev, skb->tail, np->rx_buf_sz, PCI_DMA_FROMDEVICE); - skb->dev = dev; /* Mark as being used by this device. */ + skb->dev = dev; /* Mark as being used by this device. */ np->rx_ring[entry].rxaddr = cpu_to_le32(np->rx_info[entry].mapping | RxDescValid); } @@ -1096,42 +1480,94 @@ writew(entry, dev->base_addr + RxDescQIdx); } - if (debug > 5 - || memcmp(np->pad0, np->pad0 + 1, sizeof(np->pad0) -1)) - printk(KERN_DEBUG " exiting netdev_rx() status of %d was %8.8x %d.\n", - np->rx_done, desc_status, - memcmp(np->pad0, np->pad0 + 1, sizeof(np->pad0) -1)); + if (debug > 5) + printk(KERN_DEBUG " exiting netdev_rx() status of %d was %8.8x.\n", + np->rx_done, desc_status); /* Restart Rx engine if stopped. */ return 0; } -static void netdev_error(struct net_device *dev, int intr_status) + +static void netdev_media_change(struct net_device *dev) { struct netdev_private *np = dev->priv; + long ioaddr = dev->base_addr; + u16 reg0, reg1, reg4, reg5; + u32 new_tx_mode; - if (intr_status & LinkChange) { - printk(KERN_NOTICE "%s: Link changed: Autonegotiation advertising" - " %4.4x partner %4.4x.\n", dev->name, - mdio_read(dev, np->phys[0], 4), - mdio_read(dev, np->phys[0], 5)); - check_duplex(dev, 0); - } - if (intr_status & StatsMax) { - get_stats(dev); + /* reset status first */ + mdio_read(dev, np->phys[0], MII_BMCR); + mdio_read(dev, np->phys[0], MII_BMSR); + + reg0 = mdio_read(dev, np->phys[0], MII_BMCR); + reg1 = mdio_read(dev, np->phys[0], MII_BMSR); + + if (reg1 & BMSR_LSTATUS) { + /* link is up */ + if (reg0 & BMCR_ANENABLE) { + /* autonegotiation is enabled */ + reg4 = mdio_read(dev, np->phys[0], MII_ADVERTISE); + reg5 = mdio_read(dev, np->phys[0], MII_LPA); + if (reg4 & ADVERTISE_100FULL && reg5 & LPA_100FULL) { + np->speed100 = 1; + np->full_duplex = 1; + } else if (reg4 & ADVERTISE_100HALF && reg5 & LPA_100HALF) { + np->speed100 = 1; + np->full_duplex = 0; + } else if (reg4 & ADVERTISE_10FULL && reg5 & LPA_10FULL) { + np->speed100 = 0; + np->full_duplex = 1; + } else { + np->speed100 = 0; + np->full_duplex = 0; + } + } else { + /* autonegotiation is disabled */ + if (reg0 & BMCR_SPEED100) + np->speed100 = 1; + else + np->speed100 = 0; + if (reg0 & BMCR_FULLDPLX) + np->full_duplex = 1; + else + np->full_duplex = 0; + } + printk(KERN_DEBUG "%s: Link is up, running at %sMbit %s-duplex\n", + dev->name, + np->speed100 ? "100" : "10", + np->full_duplex ? "full" : "half"); + + new_tx_mode = np->tx_mode & ~0x2; /* duplex setting */ + if (np->full_duplex) + new_tx_mode |= 2; + if (np->tx_mode != new_tx_mode) { + np->tx_mode = new_tx_mode; + writel(np->tx_mode | 0x8000, ioaddr + TxMode); + writel(np->tx_mode, ioaddr + TxMode); + } + } else { + printk(KERN_DEBUG "%s: Link is down\n", dev->name); } +} + + +static void netdev_error(struct net_device *dev, int intr_status) +{ + struct netdev_private *np = dev->priv; + /* Came close to underrunning the Tx FIFO, increase threshold. */ - if (intr_status & IntrTxDataLow) + if (intr_status & IntrTxDataLow) { writel(++np->tx_threshold, dev->base_addr + TxThreshold); - if ((intr_status & - ~(IntrAbnormalSummary|LinkChange|StatsMax|IntrTxDataLow|1)) && debug) + printk(KERN_NOTICE "%s: Increasing Tx FIFO threshold to %d bytes\n", + dev->name, np->tx_threshold * 16); + } + if ((intr_status & ~(IntrNormalMask | IntrAbnormalSummary | IntrLinkChange | IntrStatsMax | IntrTxDataLow | IntrPCIPad)) && debug) printk(KERN_ERR "%s: Something Wicked happened! %4.4x.\n", - dev->name, intr_status); - /* Hmmmmm, it's not clear how to recover from PCI faults. */ - if (intr_status & IntrTxPCIErr) + dev->name, intr_status); + /* Hmmmmm, it's not clear how to recover from DMA faults. */ + if (intr_status & IntrDMAErr) np->stats.tx_fifo_errors++; - if (intr_status & IntrRxPCIErr) - np->stats.rx_fifo_errors++; } static struct net_device_stats *get_stats(struct net_device *dev) @@ -1146,12 +1582,13 @@ np->stats.tx_aborted_errors = readl(ioaddr + 0x57024) + readl(ioaddr + 0x57028); np->stats.tx_window_errors = readl(ioaddr + 0x57018); - np->stats.collisions = readl(ioaddr + 0x57004) + readl(ioaddr + 0x57008); + np->stats.collisions = + readl(ioaddr + 0x57004) + readl(ioaddr + 0x57008); /* The chip only need report frame silently dropped. */ - np->stats.rx_dropped += readw(ioaddr + RxDMAStatus); + np->stats.rx_dropped += readw(ioaddr + RxDMAStatus); writew(0, ioaddr + RxDMAStatus); - np->stats.rx_crc_errors = readl(ioaddr + 0x5703C); + np->stats.rx_crc_errors = readl(ioaddr + 0x5703C); np->stats.rx_frame_errors = readl(ioaddr + 0x57040); np->stats.rx_length_errors = readl(ioaddr + 0x57058); np->stats.rx_missed_errors = readl(ioaddr + 0x5707C); @@ -1192,19 +1629,17 @@ struct dev_mc_list *mclist; int i; - if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ - /* Unconditionally log net taps. */ - printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name); + if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ rx_mode = AcceptBroadcast|AcceptAllMulticast|AcceptAll|AcceptMyPhys; } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { + || (dev->flags & IFF_ALLMULTI)) { /* Too many to match, or accept all multicasts. */ rx_mode = AcceptBroadcast|AcceptAllMulticast|AcceptMyPhys; } else if (dev->mc_count <= 15) { - /* Use the 16 element perfect filter. */ - long filter_addr = ioaddr + 0x56000 + 1*16; - for (i = 1, mclist = dev->mc_list; mclist && i <= dev->mc_count; - i++, mclist = mclist->next) { + /* Use the 16 element perfect filter, skip first entry. */ + long filter_addr = ioaddr + PerfFilterTable + 1 * 16; + for (i = 1, mclist = dev->mc_list; mclist && i <= dev->mc_count; + i++, mclist = mclist->next) { u16 *eaddrs = (u16 *)mclist->dmi_addr; writew(cpu_to_be16(eaddrs[2]), filter_addr); filter_addr += 4; writew(cpu_to_be16(eaddrs[1]), filter_addr); filter_addr += 4; @@ -1224,53 +1659,169 @@ memset(mc_filter, 0, sizeof(mc_filter)); for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; i++, mclist = mclist->next) { - set_bit(ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 23, mc_filter); + int bit_nr = ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 23; + __u32 *fptr = (__u32 *) &mc_filter[(bit_nr >> 4) & ~1]; + + *fptr |= cpu_to_le32(1 << (bit_nr & 31)); } - /* Clear the perfect filter list. */ - filter_addr = ioaddr + 0x56000 + 1*16; + /* Clear the perfect filter list, skip first entry. */ + filter_addr = ioaddr + PerfFilterTable + 1 * 16; for (i = 1; i < 16; i++) { writew(0xffff, filter_addr); filter_addr += 4; writew(0xffff, filter_addr); filter_addr += 4; writew(0xffff, filter_addr); filter_addr += 8; } - for (filter_addr=ioaddr + 0x56100, i=0; i < 32; filter_addr+= 16, i++) + for (filter_addr = ioaddr + HashTable, i=0; i < 32; filter_addr+= 16, i++) writew(mc_filter[i], filter_addr); rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; } writel(rx_mode, ioaddr + RxFilterMode); } -static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) + + +static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr) +{ + struct ethtool_cmd ecmd; + struct netdev_private *np = dev->priv; + + if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) + return -EFAULT; + + switch (ecmd.cmd) { + case ETHTOOL_GSET: + ecmd.supported = + SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_Autoneg | + SUPPORTED_MII; + + ecmd.advertising = ADVERTISED_MII; + if (np->advertising & ADVERTISE_10HALF) + ecmd.advertising |= ADVERTISED_10baseT_Half; + if (np->advertising & ADVERTISE_10FULL) + ecmd.advertising |= ADVERTISED_10baseT_Full; + if (np->advertising & ADVERTISE_100HALF) + ecmd.advertising |= ADVERTISED_100baseT_Half; + if (np->advertising & ADVERTISE_100FULL) + ecmd.advertising |= ADVERTISED_100baseT_Full; + if (np->autoneg) { + ecmd.advertising |= ADVERTISED_Autoneg; + ecmd.autoneg = AUTONEG_ENABLE; + } else + ecmd.autoneg = AUTONEG_DISABLE; + + ecmd.port = PORT_MII; + ecmd.transceiver = XCVR_INTERNAL; + ecmd.phy_address = np->phys[0]; + ecmd.speed = np->speed100 ? SPEED_100 : SPEED_10; + ecmd.duplex = np->full_duplex ? DUPLEX_FULL : DUPLEX_HALF; + ecmd.maxtxpkt = TX_RING_SIZE; + ecmd.maxrxpkt = np->intr_mitigation; /* not 100% accurate */ + + + if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) + return -EFAULT; + return 0; + + case ETHTOOL_SSET: { + u16 autoneg, speed100, full_duplex; + + autoneg = (ecmd.autoneg == AUTONEG_ENABLE); + speed100 = (ecmd.speed == SPEED_100); + full_duplex = (ecmd.duplex == DUPLEX_FULL); + + np->autoneg = autoneg; + if (speed100 != np->speed100 || + full_duplex != np->full_duplex) { + np->speed100 = speed100; + np->full_duplex = full_duplex; + /* change advertising bits */ + np->advertising &= ~(ADVERTISE_10HALF | + ADVERTISE_10FULL | + ADVERTISE_100HALF | + ADVERTISE_100FULL | + ADVERTISE_100BASE4); + if (speed100) { + if (full_duplex) + np->advertising |= ADVERTISE_100FULL; + else + np->advertising |= ADVERTISE_100HALF; + } else { + if (full_duplex) + np->advertising |= ADVERTISE_10FULL; + else + np->advertising |= ADVERTISE_10HALF; + } + } + check_duplex(dev); + return 0; + } + + case ETHTOOL_GDRVINFO: { + struct ethtool_drvinfo info; + memset(&info, 0, sizeof(info)); + info.cmd = ecmd.cmd; + strcpy(info.driver, DRV_NAME); + strcpy(info.version, DRV_VERSION); + *info.fw_version = 0; + strcpy(info.bus_info, PCI_SLOT_NAME(np->pci_dev)); + if (copy_to_user(useraddr, &info, sizeof(info))) + return -EFAULT; + return 0; + } + + default: + return -EOPNOTSUPP; + } +} + + + +static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct netdev_private *np = dev->priv; - u16 *data = (u16 *)&rq->ifr_data; + struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data; switch(cmd) { - case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ - data[0] = np->phys[0] & 0x1f; + case SIOCETHTOOL: + return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); + + /* Legacy mii-diag interface */ + case SIOCGMIIPHY: /* Get address of MII PHY in use. */ + case SIOCDEVPRIVATE: /* for binary compat, remove in 2.5 */ + data->phy_id = np->phys[0] & 0x1f; /* Fall Through */ - case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ - data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f); + + case SIOCGMIIREG: /* Read MII PHY register. */ + case SIOCDEVPRIVATE+1: /* for binary compat, remove in 2.5 */ + data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f); return 0; - case SIOCDEVPRIVATE+2: /* Write the specified MII register */ + + case SIOCSMIIREG: /* Write MII PHY register. */ + case SIOCDEVPRIVATE+2: /* for binary compat, remove in 2.5 */ if (!capable(CAP_NET_ADMIN)) return -EPERM; - if (data[0] == np->phys[0]) { - u16 value = data[2]; - switch (data[1]) { + if (data->phy_id == np->phys[0]) { + u16 value = data->val_in; + switch (data->reg_num) { case 0: if (value & 0x9000) /* Autonegotiation. */ - np->medialock = 0; + np->autoneg = 1; else { np->full_duplex = (value & 0x0100) ? 1 : 0; - np->medialock = 1; + np->autoneg = 0; } break; - case 4: np->advertising = value; break; + case 4: + np->advertising = value; + break; } - check_duplex(dev, 0); + check_duplex(dev); } - mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]); + mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in); return 0; default: return -EOPNOTSUPP; @@ -1284,8 +1835,7 @@ int i; netif_stop_queue(dev); - - del_timer_sync(&np->timer); + netif_stop_if(dev); if (debug > 1) { printk(KERN_DEBUG "%s: Shutting down ethercard, Intr status %4.4x.\n", @@ -1305,15 +1855,15 @@ np->tx_ring_dma); for (i = 0; i < 8 /* TX_RING_SIZE is huge! */; i++) printk(KERN_DEBUG " #%d desc. %8.8x %8.8x -> %8.8x.\n", - i, le32_to_cpu(np->tx_ring[i].status), - le32_to_cpu(np->tx_ring[i].addr), - le32_to_cpu(np->tx_done_q[i].status)); + i, le32_to_cpu(np->tx_ring[i].status), + le32_to_cpu(np->tx_ring[i].first_addr), + le32_to_cpu(np->tx_done_q[i].status)); printk(KERN_DEBUG " Rx ring at %8.8x -> %p:\n", - np->rx_ring_dma, np->rx_done_q); + np->rx_ring_dma, np->rx_done_q); if (np->rx_done_q) for (i = 0; i < 8 /* RX_RING_SIZE */; i++) { printk(KERN_DEBUG " #%d desc. %8.8x -> %8.8x\n", - i, le32_to_cpu(np->rx_ring[i].rxaddr), le32_to_cpu(np->rx_done_q[i].status)); + i, le32_to_cpu(np->rx_ring[i].rxaddr), le32_to_cpu(np->rx_done_q[i].status)); } } #endif /* __i386__ debugging only */ @@ -1332,16 +1882,32 @@ } for (i = 0; i < TX_RING_SIZE; i++) { struct sk_buff *skb = np->tx_info[i].skb; - if (skb != NULL) { - pci_unmap_single(np->pci_dev, - np->tx_info[i].mapping, - skb->len, PCI_DMA_TODEVICE); - dev_kfree_skb(skb); - } +#ifdef ZEROCOPY + int j; +#endif /* ZEROCOPY */ + if (skb == NULL) + continue; + pci_unmap_single(np->pci_dev, + np->tx_info[i].first_mapping, + skb_first_frag_len(skb), PCI_DMA_TODEVICE); + np->tx_info[i].first_mapping = 0; + dev_kfree_skb(skb); np->tx_info[i].skb = NULL; - np->tx_info[i].mapping = 0; +#ifdef ZEROCOPY + for (j = 0; j < MAX_STARFIRE_FRAGS; j++) + if (np->tx_info[i].frag_mapping[j]) { + pci_unmap_single(np->pci_dev, + np->tx_info[i].frag_mapping[j], + skb_shinfo(skb)->frags[j].size, + PCI_DMA_TODEVICE); + np->tx_info[i].frag_mapping[j] = 0; + } else + break; +#endif /* ZEROCOPY */ } + COMPAT_MOD_DEC_USE_COUNT; + return 0; } @@ -1350,7 +1916,7 @@ { struct net_device *dev = pci_get_drvdata(pdev); struct netdev_private *np; - + if (!dev) BUG(); @@ -1358,7 +1924,7 @@ unregister_netdev(dev); iounmap((char *)dev->base_addr); - pci_release_regions (pdev); + pci_release_regions(pdev); if (np->tx_done_q) pci_free_consistent(np->pci_dev, PAGE_SIZE, @@ -1380,7 +1946,7 @@ static struct pci_driver starfire_driver = { - name: "starfire", + name: DRV_NAME, probe: starfire_init_one, remove: starfire_remove_one, id_table: starfire_pci_tbl, @@ -1409,10 +1975,9 @@ /* * Local variables: - * compile-command: "gcc -DMODULE -Wall -Wstrict-prototypes -O6 -c starfire.c" - * simple-compile-command: "gcc -DMODULE -O6 -c starfire.c" - * c-indent-level: 4 - * c-basic-offset: 4 - * tab-width: 4 + * compile-command: "gcc -DMODULE -Wall -Wstrict-prototypes -O2 -c starfire.c" + * simple-compile-command: "gcc -DMODULE -O2 -c starfire.c" + * c-basic-offset: 8 + * tab-width: 8 * End: */ diff -u --recursive --new-file v2.4.5/linux/drivers/net/sun3lance.c linux/drivers/net/sun3lance.c --- v2.4.5/linux/drivers/net/sun3lance.c Wed Apr 18 14:40:04 2001 +++ linux/drivers/net/sun3lance.c Wed Jun 20 11:10:53 2001 @@ -70,6 +70,7 @@ static int lance_debug = 1; #endif MODULE_PARM(lance_debug, "i"); +MODULE_PARM_DESC(lance_debug, "SUN3 Lance debug level (0-3)"); #define DPRINTK(n,a) \ do { \ diff -u --recursive --new-file v2.4.5/linux/drivers/net/sundance.c linux/drivers/net/sundance.c --- v2.4.5/linux/drivers/net/sundance.c Fri Apr 20 11:54:22 2001 +++ linux/drivers/net/sundance.c Mon Jul 2 14:03:04 2001 @@ -18,6 +18,11 @@ http://www.scyld.com/network/sundance.html */ +#define DRV_NAME "sundance" +#define DRV_VERSION "1.01" +#define DRV_RELDATE "4/09/00" + + /* The user-configurable values. These may be modified when a driver module is loaded.*/ @@ -85,6 +90,9 @@ #include #include #include +#include +#include +#include #include /* Processor type for cache alignment. */ #include #include @@ -93,7 +101,7 @@ /* These identify the driver base version and may not be removed. */ static char version[] __devinitdata = -KERN_INFO "sundance.c:v1.01 4/09/00 Written by Donald Becker\n" +KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker\n" KERN_INFO " http://www.scyld.com/network/sundance.html\n"; /* Condensed operations for readability. */ @@ -109,6 +117,12 @@ MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); +MODULE_PARM_DESC(max_interrupt_work, "Sundance Alta maximum events handled per interrupt"); +MODULE_PARM_DESC(mtu, "Sundance Alta MTU (all boards)"); +MODULE_PARM_DESC(debug, "Sundance Alta debug level (0-5)"); +MODULE_PARM_DESC(rx_copybreak, "Sundance Alta copy breakpoint for copy-only-tiny-frames"); +MODULE_PARM_DESC(options, "Sundance Alta: Bits 0-3: media type, bit 17: full duplex"); +MODULE_PARM_DESC(full_duplex, "Sundance Alta full duplex setting(s) (1)"); /* Theory of Operation @@ -346,6 +360,7 @@ int mii_cnt; /* MII device addresses. */ u16 advertising; /* NWay media advertisement */ unsigned char phys[MII_CNT]; /* MII device addresses, only first one used. */ + struct pci_dev *pci_dev; }; /* The station address location in the EEPROM. */ @@ -366,7 +381,7 @@ static void netdev_error(struct net_device *dev, int intr_status); static void set_rx_mode(struct net_device *dev); static struct net_device_stats *get_stats(struct net_device *dev); -static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); +static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static int netdev_close(struct net_device *dev); @@ -400,7 +415,7 @@ return -ENOMEM; SET_MODULE_OWNER(dev); - if (pci_request_regions(pdev, "sundance")) + if (pci_request_regions(pdev, DRV_NAME)) goto err_out_netdev; #ifdef USE_IO_OPS @@ -422,6 +437,7 @@ np = dev->priv; np->chip_id = chip_idx; np->drv_flags = pci_id_tbl[chip_idx].drv_flags; + np->pci_dev = pdev; spin_lock_init(&np->lock); if (dev->mem_start) @@ -447,7 +463,7 @@ dev->stop = &netdev_close; dev->get_stats = &get_stats; dev->set_multicast_list = &set_rx_mode; - dev->do_ioctl = &mii_ioctl; + dev->do_ioctl = &netdev_ioctl; dev->tx_timeout = &tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; pci_set_drvdata(pdev, dev); @@ -725,18 +741,16 @@ printk(KERN_WARNING "%s: Transmit timed out, status %2.2x," " resetting...\n", dev->name, readb(ioaddr + TxStatus)); -#ifndef __alpha__ { int i; - printk(KERN_DEBUG " Rx ring %8.8x: ", (int)np->rx_ring); + printk(KERN_DEBUG " Rx ring %p: ", np->rx_ring); for (i = 0; i < RX_RING_SIZE; i++) printk(" %8.8x", (unsigned int)np->rx_ring[i].status); - printk("\n"KERN_DEBUG" Tx ring %8.8x: ", (int)np->tx_ring); + printk("\n"KERN_DEBUG" Tx ring %p: ", np->tx_ring); for (i = 0; i < TX_RING_SIZE; i++) printk(" %4.4x", np->tx_ring[i].status); printk("\n"); } -#endif /* Perhaps we should reinitialize the hardware here. */ dev->if_port = 0; @@ -1156,21 +1170,52 @@ writeb(rx_mode, ioaddr + RxMode); } -static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr) { - u16 *data = (u16 *)&rq->ifr_data; + struct netdev_private *np = dev->priv; + u32 ethcmd; + + if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) + return -EFAULT; + + switch (ethcmd) { + case ETHTOOL_GDRVINFO: { + struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; + strcpy(info.driver, DRV_NAME); + strcpy(info.version, DRV_VERSION); + strcpy(info.bus_info, np->pci_dev->slot_name); + if (copy_to_user(useraddr, &info, sizeof(info))) + return -EFAULT; + return 0; + } + + } + + return -EOPNOTSUPP; +} + +static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data; switch(cmd) { - case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ - data[0] = ((struct netdev_private *)dev->priv)->phys[0] & 0x1f; + case SIOCETHTOOL: + return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); + case SIOCGMIIPHY: /* Get address of MII PHY in use. */ + case SIOCDEVPRIVATE: /* for binary compat, remove in 2.5 */ + data->phy_id = ((struct netdev_private *)dev->priv)->phys[0] & 0x1f; /* Fall Through */ - case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ - data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f); + + case SIOCGMIIREG: /* Read MII PHY register. */ + case SIOCDEVPRIVATE+1: /* for binary compat, remove in 2.5 */ + data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f); return 0; - case SIOCDEVPRIVATE+2: /* Write the specified MII register */ + + case SIOCSMIIREG: /* Write MII PHY register. */ + case SIOCDEVPRIVATE+2: /* for binary compat, remove in 2.5 */ if (!capable(CAP_NET_ADMIN)) return -EPERM; - mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]); + mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in); return 0; default: return -EOPNOTSUPP; @@ -1258,7 +1303,7 @@ } static struct pci_driver sundance_driver = { - name: "sundance", + name: DRV_NAME, id_table: sundance_pci_tbl, probe: sundance_probe1, remove: sundance_remove1, diff -u --recursive --new-file v2.4.5/linux/drivers/net/sungem.c linux/drivers/net/sungem.c --- v2.4.5/linux/drivers/net/sungem.c Thu Apr 26 22:17:25 2001 +++ linux/drivers/net/sungem.c Wed Jun 20 21:00:55 2001 @@ -1,4 +1,4 @@ -/* $Id: sungem.c,v 1.13 2001/04/20 08:16:28 davem Exp $ +/* $Id: sungem.c,v 1.17 2001/06/17 09:22:46 jgarzik Exp $ * sungem.c: Sun GEM ethernet driver. * * Copyright (C) 2000, 2001 David S. Miller (davem@redhat.com) @@ -49,6 +49,7 @@ MODULE_AUTHOR("David S. Miller (davem@redhat.com)"); MODULE_DESCRIPTION("Sun GEM Gbit ethernet driver"); MODULE_PARM(gem_debug, "i"); +MODULE_PARM_DESC(gem_debug, "(ignored)"); #define GEM_MODULE_NAME "gem" #define PFX GEM_MODULE_NAME ": " @@ -564,6 +565,7 @@ gp->net_stats.rx_packets++; gp->net_stats.rx_bytes += len; + gp->dev->last_rx = jiffies; next: entry = NEXT_RX(entry); @@ -1615,12 +1617,17 @@ unsigned long gemreg_base, gemreg_len; struct net_device *dev; struct gem *gp; - int i; + int i, err; if (gem_version_printed++ == 0) printk(KERN_INFO "%s", version); - pci_enable_device(pdev); + err = pci_enable_device(pdev); + if (err) { + printk(KERN_ERR PFX "Cannot enable MMIO operation, " + "aborting.\n"); + return err; + } pci_set_master(pdev); gemreg_base = pci_resource_start(pdev, 0); @@ -1645,16 +1652,7 @@ goto err_out_free_netdev; } - if (pci_enable_device(pdev)) { - printk(KERN_ERR PFX "Cannot enable MMIO operation, " - "aborting.\n"); - goto err_out_free_mmio_res; - } - - pci_set_master(pdev); - gp = dev->priv; - memset(gp, 0, sizeof(*gp)); gp->pdev = pdev; dev->base_addr = (long) pdev; @@ -1732,14 +1730,6 @@ } -static void gem_suspend(struct pci_dev *pdev) -{ -} - -static void gem_resume(struct pci_dev *pdev) -{ -} - static void __devexit gem_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); @@ -1767,8 +1757,6 @@ id_table: gem_pci_tbl, probe: gem_init_one, remove: gem_remove_one, - suspend: gem_suspend, - resume: gem_resume, }; static int __init gem_init(void) diff -u --recursive --new-file v2.4.5/linux/drivers/net/sunhme.c linux/drivers/net/sunhme.c --- v2.4.5/linux/drivers/net/sunhme.c Sun May 20 11:32:07 2001 +++ linux/drivers/net/sunhme.c Fri Jun 29 19:38:26 2001 @@ -1,4 +1,4 @@ -/* $Id: sunhme.c,v 1.119 2001/05/17 04:12:16 davem Exp $ +/* $Id: sunhme.c,v 1.120 2001/06/14 17:37:23 jgarzik Exp $ * sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching, * auto carrier detecting ethernet driver. Also known as the * "Happy Meal Ethernet" found on SunSwift SBUS cards. @@ -72,6 +72,7 @@ /* accept MAC address of the form macaddr=0x08,0x00,0x20,0x30,0x40,0x50 */ MODULE_PARM(macaddr, "6i"); +MODULE_PARM_DESC(macaddr, "Happy Meal MAC address to set"); static struct happy_meal *root_happy_dev; diff -u --recursive --new-file v2.4.5/linux/drivers/net/tlan.c linux/drivers/net/tlan.c --- v2.4.5/linux/drivers/net/tlan.c Thu Apr 19 09:34:52 2001 +++ linux/drivers/net/tlan.c Mon Jul 2 14:03:04 2001 @@ -171,6 +171,7 @@ #include #include #include +#include typedef u32 (TLanIntVectorFunc)( struct net_device *, u16 ); @@ -194,6 +195,11 @@ MODULE_PARM(speed, "1-" __MODULE_STRING(MAX_TLAN_BOARDS) "i"); MODULE_PARM(debug, "i"); MODULE_PARM(bbuf, "i"); +MODULE_PARM_DESC(aui, "ThunderLAN use AUI port(s) (0-1)"); +MODULE_PARM_DESC(duplex, "ThunderLAN duplex setting(s) (0-default, 1-half, 2-full)"); +MODULE_PARM_DESC(speed, "ThunderLAN port speen setting(s) (0,10,100)"); +MODULE_PARM_DESC(debug, "ThunderLAN debug mask"); +MODULE_PARM_DESC(bbuf, "ThunderLAN use big buffer (0-1)"); EXPORT_NO_SYMBOLS; /* Define this to enable Link beat monitoring */ @@ -240,21 +246,21 @@ }; static struct pci_device_id tlan_pci_tbl[] __devinitdata = { - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETELLIGENT_10, + { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL10, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETELLIGENT_10_100, + { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETFLEX_3P_INTEGRATED, + { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETFLEX3I, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 }, - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETFLEX_3P, + { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_THUNDER, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 }, - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETFLEX_3P_BNC, + { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETFLEX3B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 }, - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETELLIGENT_10_100_PROLIANT, + { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100PI, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 }, - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETELLIGENT_10_100_DUAL, + { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6 }, - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_DESKPRO_4000_5233MMX, + { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100I, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7 }, { PCI_VENDOR_ID_OLICOM, PCI_DEVICE_ID_OLICOM_OC2183, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 }, @@ -906,24 +912,29 @@ static int TLan_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { TLanPrivateInfo *priv = dev->priv; - u16 *data = (u16 *)&rq->ifr_data; + struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data; u32 phy = priv->phy[priv->phyNum]; if (!priv->phyOnline) return -EAGAIN; switch(cmd) { - case SIOCDEVPRIVATE: - data[0] = phy; + case SIOCGMIIPHY: /* Get address of MII PHY in use. */ + case SIOCDEVPRIVATE: /* for binary compat, remove in 2.5 */ + data->phy_id = phy; - case SIOCDEVPRIVATE+1: /* Read MII register */ - TLan_MiiReadReg(dev, data[0], data[1], &data[3]); + + case SIOCGMIIREG: /* Read MII PHY register. */ + case SIOCDEVPRIVATE+1: /* for binary compat, remove in 2.5 */ + TLan_MiiReadReg(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, &data->val_out); return 0; - case SIOCDEVPRIVATE+2: /* Write MII register */ + + case SIOCSMIIREG: /* Write MII PHY register. */ + case SIOCDEVPRIVATE+2: /* for binary compat, remove in 2.5 */ if (!capable(CAP_NET_ADMIN)) return -EPERM; - TLan_MiiWriteReg(dev, data[0], data[1], data[2]); + TLan_MiiWriteReg(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in); return 0; default: return -EOPNOTSUPP; diff -u --recursive --new-file v2.4.5/linux/drivers/net/tlan.h linux/drivers/net/tlan.h --- v2.4.5/linux/drivers/net/tlan.h Tue Mar 20 12:05:00 2001 +++ linux/drivers/net/tlan.h Mon Jul 2 14:03:04 2001 @@ -61,14 +61,6 @@ * ****************************************************************/ -#define PCI_DEVICE_ID_NETELLIGENT_10 0xAE34 -#define PCI_DEVICE_ID_NETELLIGENT_10_100 0xAE32 -#define PCI_DEVICE_ID_NETFLEX_3P_INTEGRATED 0xAE35 -#define PCI_DEVICE_ID_NETFLEX_3P 0xF130 -#define PCI_DEVICE_ID_NETFLEX_3P_BNC 0xF150 -#define PCI_DEVICE_ID_NETELLIGENT_10_100_PROLIANT 0xAE43 -#define PCI_DEVICE_ID_NETELLIGENT_10_100_DUAL 0xAE40 -#define PCI_DEVICE_ID_DESKPRO_4000_5233MMX 0xB011 #define PCI_DEVICE_ID_NETELLIGENT_10_T2 0xB012 #define PCI_DEVICE_ID_NETELLIGENT_10_100_WS_5100 0xB030 #ifndef PCI_DEVICE_ID_OLICOM_OC2183 diff -u --recursive --new-file v2.4.5/linux/drivers/net/tokenring/ibmtr.c linux/drivers/net/tokenring/ibmtr.c --- v2.4.5/linux/drivers/net/tokenring/ibmtr.c Tue Mar 20 12:05:00 2001 +++ linux/drivers/net/tokenring/ibmtr.c Tue Jun 12 11:06:54 2001 @@ -1185,7 +1185,7 @@ isa_writeb(~CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_RESET + ISRA_ODD); isa_writeb(~SRB_RESP_INT, ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD); - skip_reset: + skip_reset:; } /* SRB response */ if (status & ASB_FREE_INT) { /* ASB response */ diff -u --recursive --new-file v2.4.5/linux/drivers/net/tokenring/lanstreamer.c linux/drivers/net/tokenring/lanstreamer.c --- v2.4.5/linux/drivers/net/tokenring/lanstreamer.c Thu Apr 19 09:34:52 2001 +++ linux/drivers/net/tokenring/lanstreamer.c Wed Jun 20 11:13:18 2001 @@ -1808,25 +1808,11 @@ #endif #endif -static void streamer_suspend(struct pci_dev *pdev) { -#if STREAMER_DEBUG - printk("lanstreamer::streamer_suspend entry pdev %p\n",pdev); -#endif -} - -static void streamer_resume(struct pci_dev *pdev) { -#if STREAMER_DEBUG - printk("lanstreamer::streamer_resume entry pdev %p\n",pdev); -#endif -} - static struct pci_driver streamer_pci_driver = { name: "lanstreamer", id_table: streamer_pci_tbl, probe: streamer_init_one, remove: streamer_remove_one, - suspend: streamer_suspend, - resume: streamer_resume, }; static int __init streamer_init_module(void) { diff -u --recursive --new-file v2.4.5/linux/drivers/net/tokenring/olympic.c linux/drivers/net/tokenring/olympic.c --- v2.4.5/linux/drivers/net/tokenring/olympic.c Sun May 20 12:11:38 2001 +++ linux/drivers/net/tokenring/olympic.c Wed Jun 20 11:13:18 2001 @@ -49,6 +49,8 @@ * 04/09/01 - Couple of bug fixes to the dma unmaps and ejecting the * adapter when live does not take the system down with it. * + * 06/02/01 - Clean up, copy skb for small packets + * * To Do: * * Complete full Cardbus / hot-swap support. @@ -64,7 +66,10 @@ #define OLYMPIC_DEBUG 0 + +#include #include + #include #include #include @@ -99,8 +104,8 @@ * Official releases will only have an a.b.c version number format. */ -static char *version = -"Olympic.c v0.9.C 4/18/01 - Peter De Schrijver & Mike Phillips" ; +static char version[] __devinitdata = +"Olympic.c v0.9.7 6/02/01 - Peter De Schrijver & Mike Phillips" ; static char *open_maj_error[] = {"No error", "Lobe Media Test", "Physical Insertion", "Address Verification", "Neighbor Notification (Ring Poll)", @@ -116,6 +121,9 @@ /* Module paramters */ +MODULE_AUTHOR("Mike Phillips ") ; +MODULE_DESCRIPTION("Olympic PCI/Cardbus Chipset Driver \n") ; + /* Ring Speed 0,4,16,100 * 0 = Autosense * 4,16 = Selected speed only, no autosense @@ -157,7 +165,8 @@ }; MODULE_DEVICE_TABLE(pci,olympic_pci_tbl) ; -static int __init olympic_probe(struct pci_dev *pdev, const struct pci_device_id *ent); + +static int olympic_probe(struct pci_dev *pdev, const struct pci_device_id *ent); static int olympic_init(struct net_device *dev); static int olympic_open(struct net_device *dev); static int olympic_xmit(struct sk_buff *skb, struct net_device *dev); @@ -172,7 +181,7 @@ static void olympic_asb_bh(struct net_device *dev) ; static int olympic_proc_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data) ; -static int __init olympic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +static int __devinit olympic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *dev ; struct olympic_private *olympic_priv; @@ -239,6 +248,7 @@ dev->set_multicast_list=&olympic_set_rx_mode; dev->get_stats=&olympic_get_stats ; dev->set_mac_address=&olympic_set_mac_address ; + SET_MODULE_OWNER(dev) ; pci_set_drvdata(pdev,dev) ; register_netdev(dev) ; @@ -253,10 +263,10 @@ return 0 ; } -static int __init olympic_init(struct net_device *dev) +static int __devinit olympic_init(struct net_device *dev) { struct olympic_private *olympic_priv; - __u8 *olympic_mmio, *init_srb,*adapter_addr; + u8 *olympic_mmio, *init_srb,*adapter_addr; unsigned long t; unsigned int uaa_addr; @@ -268,7 +278,7 @@ writel(readl(olympic_mmio+BCTL) | BCTL_SOFTRESET,olympic_mmio+BCTL); t=jiffies; - while((readl(olympic_priv->olympic_mmio+BCTL)) & BCTL_SOFTRESET) { + while((readl(olympic_mmio+BCTL)) & BCTL_SOFTRESET) { schedule(); if(jiffies-t > 40*HZ) { printk(KERN_ERR "IBM PCI tokenring card not responding.\n"); @@ -381,7 +391,7 @@ static int olympic_open(struct net_device *dev) { struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv; - __u8 *olympic_mmio=olympic_priv->olympic_mmio,*init_srb; + u8 *olympic_mmio=olympic_priv->olympic_mmio,*init_srb; unsigned long flags, t; char open_error[255] ; int i, open_finished = 1 ; @@ -632,10 +642,10 @@ #endif if (olympic_priv->olympic_network_monitor) { - __u8 *oat ; - __u8 *opt ; - oat = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ; - opt = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ; + u8 *oat ; + u8 *opt ; + oat = (u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ; + opt = (u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ; printk("%s: Node Address: %02x:%02x:%02x:%02x:%02x:%02x\n",dev->name, readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)), @@ -659,7 +669,6 @@ } netif_start_queue(dev); - MOD_INC_USE_COUNT ; return 0; } @@ -673,12 +682,16 @@ * This means that we may process the frame before we receive the end * of frame interrupt. This is why we always test the status instead * of blindly processing the next frame. + * + * We also remove the last 4 bytes from the packet as well, these are + * just token ring trailer info and upset protocols that don't check + * their own length, i.e. SNA. * */ static void olympic_rx(struct net_device *dev) { struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv; - __u8 *olympic_mmio=olympic_priv->olympic_mmio; + u8 *olympic_mmio=olympic_priv->olympic_mmio; struct olympic_rx_status *rx_status; struct olympic_rx_desc *rx_desc ; int rx_ring_last_received,length, buffer_cnt, cpy_length, frag_len; @@ -688,7 +701,7 @@ rx_status=&(olympic_priv->olympic_rx_status_ring[(olympic_priv->rx_status_last_received + 1) & (OLYMPIC_RX_RING_SIZE - 1)]) ; while (rx_status->status_buffercnt) { - __u32 l_status_buffercnt; + u32 l_status_buffercnt; olympic_priv->rx_status_last_received++ ; olympic_priv->rx_status_last_received &= (OLYMPIC_RX_RING_SIZE -1); @@ -742,36 +755,50 @@ If only one buffer is used we can simply swap the buffers around. If more than one then we must use the new buffer and copy the information first. Ideally all frames would be in a single buffer, this can be tuned by - altering the buffer size. */ + altering the buffer size. If the length of the packet is less than + 1500 bytes we're going to copy it over anyway to stop packets getting + dropped from sockets with buffers small than our pkt_buf_sz. */ if (buffer_cnt==1) { olympic_priv->rx_ring_last_received++ ; olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE -1); rx_ring_last_received = olympic_priv->rx_ring_last_received ; - skb2=olympic_priv->rx_ring_skb[rx_ring_last_received] ; - /* unmap buffer */ - pci_unmap_single(olympic_priv->pdev, - le32_to_cpu(olympic_priv->olympic_rx_ring[rx_ring_last_received].buffer), - olympic_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE) ; - skb_put(skb2,length); - skb2->protocol = tr_type_trans(skb2,dev); - olympic_priv->olympic_rx_ring[rx_ring_last_received].buffer = - cpu_to_le32(pci_map_single(olympic_priv->pdev, skb->data, - olympic_priv->pkt_buf_sz, PCI_DMA_FROMDEVICE)); - olympic_priv->olympic_rx_ring[rx_ring_last_received].res_length = - cpu_to_le32(olympic_priv->pkt_buf_sz); - olympic_priv->rx_ring_skb[rx_ring_last_received] = skb ; - netif_rx(skb2) ; + if (length > 1500) { + skb2=olympic_priv->rx_ring_skb[rx_ring_last_received] ; + /* unmap buffer */ + pci_unmap_single(olympic_priv->pdev, + le32_to_cpu(olympic_priv->olympic_rx_ring[rx_ring_last_received].buffer), + olympic_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE) ; + skb_put(skb2,length-4); + skb2->protocol = tr_type_trans(skb2,dev); + olympic_priv->olympic_rx_ring[rx_ring_last_received].buffer = + cpu_to_le32(pci_map_single(olympic_priv->pdev, skb->data, + olympic_priv->pkt_buf_sz, PCI_DMA_FROMDEVICE)); + olympic_priv->olympic_rx_ring[rx_ring_last_received].res_length = + cpu_to_le32(olympic_priv->pkt_buf_sz); + olympic_priv->rx_ring_skb[rx_ring_last_received] = skb ; + netif_rx(skb2) ; + } else { + pci_dma_sync_single(olympic_priv->pdev, + le32_to_cpu(olympic_priv->olympic_rx_ring[rx_ring_last_received].buffer), + olympic_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE) ; + memcpy(skb_put(skb,length-4),olympic_priv->rx_ring_skb[rx_ring_last_received]->data,length-4) ; + skb->protocol = tr_type_trans(skb,dev) ; + netif_rx(skb) ; + } } else { do { /* Walk the buffers */ olympic_priv->rx_ring_last_received++ ; olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE -1); rx_ring_last_received = olympic_priv->rx_ring_last_received ; + pci_dma_sync_single(olympic_priv->pdev, + le32_to_cpu(olympic_priv->olympic_rx_ring[rx_ring_last_received].buffer), + olympic_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE) ; rx_desc = &(olympic_priv->olympic_rx_ring[rx_ring_last_received]); cpy_length = (i == 1 ? frag_len : le32_to_cpu(rx_desc->res_length)); memcpy(skb_put(skb, cpy_length), olympic_priv->rx_ring_skb[rx_ring_last_received]->data, cpy_length) ; } while (--i) ; - + skb_trim(skb,skb->len-4) ; skb->protocol = tr_type_trans(skb,dev); netif_rx(skb) ; } @@ -799,9 +826,9 @@ { struct net_device *dev= (struct net_device *)dev_id; struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv; - __u8 *olympic_mmio=olympic_priv->olympic_mmio; - __u32 sisr; - __u8 *adapter_check_area ; + u8 *olympic_mmio=olympic_priv->olympic_mmio; + u32 sisr; + u8 *adapter_check_area ; /* * Read sisr but don't reset it yet. @@ -855,7 +882,7 @@ netif_stop_queue(dev); printk(KERN_WARNING "%s: Adapter Check Interrupt Raised, 8 bytes of information follow:\n", dev->name); writel(readl(olympic_mmio+LAPWWO),olympic_mmio+LAPA); - adapter_check_area = (__u8 *)(olympic_mmio+LAPWWO) ; + adapter_check_area = (u8 *)(olympic_mmio+LAPWWO) ; printk(KERN_WARNING "%s: Bytes %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",dev->name, readb(adapter_check_area+0), readb(adapter_check_area+1), readb(adapter_check_area+2), readb(adapter_check_area+3), readb(adapter_check_area+4), readb(adapter_check_area+5), readb(adapter_check_area+6), readb(adapter_check_area+7)) ; /* The adapter is effectively dead, clean up and exit */ for(i=0;iirq, dev) ; - MOD_DEC_USE_COUNT ; dev->stop = NULL ; spin_unlock(&olympic_priv->olympic_lock) ; return ; @@ -921,7 +947,7 @@ static int olympic_xmit(struct sk_buff *skb, struct net_device *dev) { struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv; - __u8 *olympic_mmio=olympic_priv->olympic_mmio; + u8 *olympic_mmio=olympic_priv->olympic_mmio; unsigned long flags ; spin_lock_irqsave(&olympic_priv->olympic_lock, flags); @@ -952,7 +978,7 @@ static int olympic_close(struct net_device *dev) { struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv; - __u8 *olympic_mmio=olympic_priv->olympic_mmio,*srb; + u8 *olympic_mmio=olympic_priv->olympic_mmio,*srb; unsigned long t,flags; int i; @@ -1027,7 +1053,6 @@ #endif free_irq(dev->irq,dev); - MOD_DEC_USE_COUNT ; return 0; } @@ -1035,9 +1060,9 @@ static void olympic_set_rx_mode(struct net_device *dev) { struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ; - __u8 *olympic_mmio = olympic_priv->olympic_mmio ; - __u8 options = 0; - __u8 *srb; + u8 *olympic_mmio = olympic_priv->olympic_mmio ; + u8 options = 0; + u8 *srb; struct dev_mc_list *dmi ; unsigned char dev_mc_address[4] ; int i ; @@ -1103,8 +1128,8 @@ static void olympic_srb_bh(struct net_device *dev) { struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ; - __u8 *olympic_mmio = olympic_priv->olympic_mmio ; - __u8 *srb; + u8 *olympic_mmio = olympic_priv->olympic_mmio ; + u8 *srb; writel(olympic_priv->srb,olympic_mmio+LAPA); srb=olympic_priv->olympic_lap + (olympic_priv->srb & (~0xf800)); @@ -1277,22 +1302,22 @@ static void olympic_arb_cmd(struct net_device *dev) { struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv; - __u8 *olympic_mmio=olympic_priv->olympic_mmio; - __u8 *arb_block, *asb_block, *srb ; - __u8 header_len ; - __u16 frame_len, buffer_len ; + u8 *olympic_mmio=olympic_priv->olympic_mmio; + u8 *arb_block, *asb_block, *srb ; + u8 header_len ; + u16 frame_len, buffer_len ; struct sk_buff *mac_frame ; - __u8 *buf_ptr ; - __u8 *frame_data ; - __u16 buff_off ; - __u16 lan_status = 0, lan_status_diff ; /* Initialize to stop compiler warning */ - __u8 fdx_prot_error ; - __u16 next_ptr; + u8 *buf_ptr ; + u8 *frame_data ; + u16 buff_off ; + u16 lan_status = 0, lan_status_diff ; /* Initialize to stop compiler warning */ + u8 fdx_prot_error ; + u16 next_ptr; int i ; - arb_block = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->arb) ; - asb_block = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->asb) ; - srb = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->srb) ; + arb_block = (u8 *)(olympic_priv->olympic_lap + olympic_priv->arb) ; + asb_block = (u8 *)(olympic_priv->olympic_lap + olympic_priv->asb) ; + srb = (u8 *)(olympic_priv->olympic_lap + olympic_priv->srb) ; writel(readl(olympic_mmio+LAPA),olympic_mmio+LAPWWO); if (readb(arb_block+0) == ARB_RECEIVE_DATA) { /* Receive.data, MAC frames */ @@ -1421,7 +1446,6 @@ free_irq(dev->irq,dev); dev->stop=NULL; printk(KERN_WARNING "%s: Adapter has been closed \n", dev->name) ; - MOD_DEC_USE_COUNT ; } /* If serious error */ if (olympic_priv->olympic_message_level) { @@ -1489,10 +1513,10 @@ static void olympic_asb_bh(struct net_device *dev) { struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ; - __u8 *arb_block, *asb_block ; + u8 *arb_block, *asb_block ; - arb_block = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->arb) ; - asb_block = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->asb) ; + arb_block = (u8 *)(olympic_priv->olympic_lap + olympic_priv->arb) ; + asb_block = (u8 *)(olympic_priv->olympic_lap + olympic_priv->asb) ; if (olympic_priv->asb_queued == 1) { /* Dropped through the first time */ @@ -1529,7 +1553,7 @@ static int olympic_change_mtu(struct net_device *dev, int mtu) { struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv; - __u16 max_mtu ; + u16 max_mtu ; if (olympic_priv->olympic_ring_speed == 4) max_mtu = 4500 ; @@ -1551,8 +1575,8 @@ { struct net_device *dev = (struct net_device *)data ; struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv; - __u8 *oat = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ; - __u8 *opt = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ; + u8 *oat = (u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ; + u8 *opt = (u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ; int size = 0 ; int len=0; off_t begin=0; @@ -1672,7 +1696,8 @@ unregister_trdev(dev) ; iounmap(olympic_priv->olympic_mmio) ; iounmap(olympic_priv->olympic_lap) ; - pci_release_regions(pdev) ; + pci_release_regions(pdev) ; + pci_set_drvdata(pdev,NULL) ; kfree(dev) ; } diff -u --recursive --new-file v2.4.5/linux/drivers/net/tokenring/olympic.h linux/drivers/net/tokenring/olympic.h --- v2.4.5/linux/drivers/net/tokenring/olympic.h Wed Apr 18 11:39:21 2001 +++ linux/drivers/net/tokenring/olympic.h Wed Jun 20 11:13:18 2001 @@ -214,43 +214,43 @@ /* xxxx These structures are all little endian in hardware. */ struct olympic_tx_desc { - __u32 buffer; - __u32 status_length; + u32 buffer; + u32 status_length; }; struct olympic_tx_status { - __u32 status; + u32 status; }; struct olympic_rx_desc { - __u32 buffer; - __u32 res_length; + u32 buffer; + u32 res_length; }; struct olympic_rx_status { - __u32 fragmentcnt_framelen; - __u32 status_buffercnt; + u32 fragmentcnt_framelen; + u32 status_buffercnt; }; /* xxxx END These structures are all little endian in hardware. */ /* xxxx There may be more, but I'm pretty sure about these */ struct mac_receive_buffer { - __u16 next ; - __u8 padding ; - __u8 frame_status ; - __u16 buffer_length ; - __u8 frame_data ; + u16 next ; + u8 padding ; + u8 frame_status ; + u16 buffer_length ; + u8 frame_data ; }; struct olympic_private { - __u16 srb; /* be16 */ - __u16 trb; /* be16 */ - __u16 arb; /* be16 */ - __u16 asb; /* be16 */ + u16 srb; /* be16 */ + u16 trb; /* be16 */ + u16 arb; /* be16 */ + u16 asb; /* be16 */ - __u8 *olympic_mmio; - __u8 *olympic_lap; + u8 *olympic_mmio; + u8 *olympic_lap; struct pci_dev *pdev ; char *olympic_card_name ; @@ -274,47 +274,47 @@ int tx_ring_free, tx_ring_last_status, rx_ring_last_received,rx_status_last_received, free_tx_ring_entries; struct net_device_stats olympic_stats ; - __u16 olympic_lan_status ; - __u8 olympic_ring_speed ; - __u16 pkt_buf_sz ; - __u8 olympic_receive_options, olympic_copy_all_options,olympic_message_level, olympic_network_monitor; - __u16 olympic_addr_table_addr, olympic_parms_addr ; - __u8 olympic_laa[6] ; - __u32 rx_ring_dma_addr; - __u32 rx_status_ring_dma_addr; - __u32 tx_ring_dma_addr; - __u32 tx_status_ring_dma_addr; + u16 olympic_lan_status ; + u8 olympic_ring_speed ; + u16 pkt_buf_sz ; + u8 olympic_receive_options, olympic_copy_all_options,olympic_message_level, olympic_network_monitor; + u16 olympic_addr_table_addr, olympic_parms_addr ; + u8 olympic_laa[6] ; + u32 rx_ring_dma_addr; + u32 rx_status_ring_dma_addr; + u32 tx_ring_dma_addr; + u32 tx_status_ring_dma_addr; }; struct olympic_adapter_addr_table { - __u8 node_addr[6] ; - __u8 reserved[4] ; - __u8 func_addr[4] ; + u8 node_addr[6] ; + u8 reserved[4] ; + u8 func_addr[4] ; } ; struct olympic_parameters_table { - __u8 phys_addr[4] ; - __u8 up_node_addr[6] ; - __u8 up_phys_addr[4] ; - __u8 poll_addr[6] ; - __u16 reserved ; - __u16 acc_priority ; - __u16 auth_source_class ; - __u16 att_code ; - __u8 source_addr[6] ; - __u16 beacon_type ; - __u16 major_vector ; - __u16 lan_status ; - __u16 soft_error_time ; - __u16 reserved1 ; - __u16 local_ring ; - __u16 mon_error ; - __u16 beacon_transmit ; - __u16 beacon_receive ; - __u16 frame_correl ; - __u8 beacon_naun[6] ; - __u32 reserved2 ; - __u8 beacon_phys[4] ; + u8 phys_addr[4] ; + u8 up_node_addr[6] ; + u8 up_phys_addr[4] ; + u8 poll_addr[6] ; + u16 reserved ; + u16 acc_priority ; + u16 auth_source_class ; + u16 att_code ; + u8 source_addr[6] ; + u16 beacon_type ; + u16 major_vector ; + u16 lan_status ; + u16 soft_error_time ; + u16 reserved1 ; + u16 local_ring ; + u16 mon_error ; + u16 beacon_transmit ; + u16 beacon_receive ; + u16 frame_correl ; + u8 beacon_naun[6] ; + u32 reserved2 ; + u8 beacon_phys[4] ; }; diff -u --recursive --new-file v2.4.5/linux/drivers/net/tokenring/smctr.c linux/drivers/net/tokenring/smctr.c --- v2.4.5/linux/drivers/net/tokenring/smctr.c Wed May 16 10:31:27 2001 +++ linux/drivers/net/tokenring/smctr.c Thu Jun 21 14:28:39 2001 @@ -59,6 +59,10 @@ #include #include +#if BITS_PER_LONG == 64 +#error FIXME: driver does not support 64-bit platforms +#endif + #include "smctr.h" /* Our Stuff */ #include "smctr_firmware.h" /* SMC adapter firmware */ diff -u --recursive --new-file v2.4.5/linux/drivers/net/tulip/21142.c linux/drivers/net/tulip/21142.c --- v2.4.5/linux/drivers/net/tulip/21142.c Wed May 16 10:25:39 2001 +++ linux/drivers/net/tulip/21142.c Wed Jun 20 11:15:44 2001 @@ -84,7 +84,7 @@ tp->csr6 &= 0x00D5; tp->csr6 |= new_csr6; outl(0x0301, ioaddr + CSR12); - tulip_restart_rxtx(tp, tp->csr6); + tulip_restart_rxtx(tp); } next_tick = 3*HZ; } @@ -117,7 +117,7 @@ udelay(100); outl(csr14, ioaddr + CSR14); tp->csr6 = 0x82420000 | (tp->sym_advertise & 0x0040 ? FullDuplex : 0); - tulip_outl_csr(tp, tp->csr6, CSR6); + outl(tp->csr6, ioaddr + CSR6); if (tp->mtable && tp->mtable->csr15dir) { outl(tp->mtable->csr15dir, ioaddr + CSR15); outl(tp->mtable->csr15val, ioaddr + CSR15); @@ -201,12 +201,12 @@ outl(1, ioaddr + CSR13); } #if 0 /* Restart shouldn't be needed. */ - tulip_outl_csr(tp, tp->csr6 | csr6_sr, CSR6); + outl(tp->csr6 | RxOn, ioaddr + CSR6); if (tulip_debug > 2) printk(KERN_DEBUG "%s: Restarting Tx and Rx, CSR5 is %8.8x.\n", dev->name, inl(ioaddr + CSR5)); #endif - tulip_outl_csr(tp, tp->csr6 | csr6_st | csr6_sr, CSR6); + tulip_start_rxtx(tp); if (tulip_debug > 2) printk(KERN_DEBUG "%s: Setting CSR6 %8.8x/%x CSR12 %8.8x.\n", dev->name, tp->csr6, inl(ioaddr + CSR6), @@ -252,7 +252,7 @@ tp->csr6 = 0x83860000; outl(0x0003FF7F, ioaddr + CSR14); outl(0x0301, ioaddr + CSR12); - tulip_restart_rxtx(tp, tp->csr6); + tulip_restart_rxtx(tp); } } diff -u --recursive --new-file v2.4.5/linux/drivers/net/tulip/ChangeLog linux/drivers/net/tulip/ChangeLog --- v2.4.5/linux/drivers/net/tulip/ChangeLog Sat May 19 18:02:45 2001 +++ linux/drivers/net/tulip/ChangeLog Wed Jun 20 11:19:02 2001 @@ -1,3 +1,70 @@ +2001-06-16 Jeff Garzik + + * tulip.h, tulip_core.c: + Integrate MMIO support from devel branch, but default + it to off for stable kernel and driver series. + +2001-06-16 Jeff Garzik + + * tulip_core.c (tulip_init_one): + Free descriptor rings on error. + +2001-06-16 Jeff Garzik + + * tulip_core.c (tulip_mwi_config, tulip_init_one): + Large update to csr0 bus configuration code. This is not stable + yet, so it is only conditionally enabled, via CONFIG_TULIP_MWI. + +2001-06-16 Jeff Garzik + + * tulip_core.c: + Initialize timer in tulip_init_one and tulip_down, + not in tulip_up. + +2001-06-14 Jeff Garzik + + * tulip_core.c: + - Update tulip_suspend, tulip_resume for new PCI PM API. + - Surround suspend/resume code with CONFIG_PM. + +2001-06-12 Jeff Golds + + * tulip_core.c: + - Reset sw ring ptrs in tulip_up. Fixes PM resume case. + - Clean rx and tx rings on device down. + +2001-06-05 David Miller + + * tulip_core (set_rx_mode): Do not use set_bit + on an integer variable. Also fix endianness issue. + +2001-06-04 Jeff Garzik + + * interrupt.c: + Simplify rx processing when CONFIG_NET_HW_FLOWCONTROL is + active, and in the process fix a bug where flow control + and low load caused rx not to be acknowledged properly. + +2001-06-01 Jeff Garzik + + * tulip.h: + - Remove tulip_outl_csr helper, redundant. + - Add tulip_start_rxtx inline helper. + - tulip_stop_rxtx helper: Add synchronization. Always use current + csr6 value, instead of tp->csr6 value or value passed as arg. + - tulip_restart_rxtx helper: Add synchronization. Always + use tp->csr6 for desired mode, not value passed as arg. + - New RxOn, TxOn, RxTx constants for csr6 modes. + - Remove now-redundant constants csr6_st, csr6_sr. + + * 21142.c, interrupt.c, media.c, pnic.c, tulip_core.c: + Update for above rxtx helper changes. + + * interrupt.c: + - whitespace cleanup around #ifdef CONFIG_NET_HW_FLOWCONTROL, + convert tabs to spaces. + - Move tp->stats.rx_missed_errors update outside the ifdef. + 2001-05-18 Jeff Garzik * tulip_core.c: Added ethtool support. diff -u --recursive --new-file v2.4.5/linux/drivers/net/tulip/interrupt.c linux/drivers/net/tulip/interrupt.c --- v2.4.5/linux/drivers/net/tulip/interrupt.c Sun May 20 12:11:38 2001 +++ linux/drivers/net/tulip/interrupt.c Wed Jun 20 11:15:44 2001 @@ -328,21 +328,11 @@ if (csr5 & (RxIntr | RxNoBuf)) { #ifdef CONFIG_NET_HW_FLOWCONTROL - if (tp->fc_bit) { - if (test_bit(tp->fc_bit, &netdev_fc_xoff)) { - tulip_refill_rx(dev); - } else { - tulip_refill_rx(dev); - rx += tulip_rx(dev); - } - } else { /* not in fc mode */ - rx += tulip_rx(dev); - tulip_refill_rx(dev); - } -#else - rx += tulip_rx(dev); - tulip_refill_rx(dev); + if ((!tp->fc_bit) || + (!test_bit(tp->fc_bit, &netdev_fc_xoff))) #endif + rx += tulip_rx(dev); + tulip_refill_rx(dev); } if (csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) { @@ -418,7 +408,7 @@ printk(KERN_WARNING "%s: The transmitter stopped." " CSR5 is %x, CSR6 %x, new CSR6 %x.\n", dev->name, csr5, inl(ioaddr + CSR6), tp->csr6); - tulip_restart_rxtx(tp, tp->csr6); + tulip_restart_rxtx(tp); } spin_unlock(&tp->lock); } @@ -434,7 +424,7 @@ else tp->csr6 |= 0x00200000; /* Store-n-forward. */ /* Restart the transmit process. */ - tulip_restart_rxtx(tp, tp->csr6); + tulip_restart_rxtx(tp); outl(0, ioaddr + CSR1); } if (csr5 & (RxDied | RxNoBuf)) { @@ -444,16 +434,15 @@ } } if (csr5 & RxDied) { /* Missed a Rx frame. */ -#ifdef CONFIG_NET_HW_FLOWCONTROL - if (tp->fc_bit && !test_bit(tp->fc_bit, &netdev_fc_xoff)) { - tp->stats.rx_errors++; - tulip_outl_csr(tp, tp->csr6 | csr6_st | csr6_sr, CSR6); - } tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; +#ifdef CONFIG_NET_HW_FLOWCONTROL + if (tp->fc_bit && !test_bit(tp->fc_bit, &netdev_fc_xoff)) { + tp->stats.rx_errors++; + tulip_start_rxtx(tp); + } #else tp->stats.rx_errors++; - tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; - tulip_outl_csr(tp, tp->csr6 | csr6_st | csr6_sr, CSR6); + tulip_start_rxtx(tp); #endif } /* diff -u --recursive --new-file v2.4.5/linux/drivers/net/tulip/media.c linux/drivers/net/tulip/media.c --- v2.4.5/linux/drivers/net/tulip/media.c Wed May 16 10:25:39 2001 +++ linux/drivers/net/tulip/media.c Wed Jun 20 11:15:44 2001 @@ -411,7 +411,6 @@ */ int tulip_check_duplex(struct net_device *dev) { - long ioaddr = dev->base_addr; struct tulip_private *tp = dev->priv; unsigned int bmsr, lpa, negotiated, new_csr6; @@ -442,11 +441,8 @@ else new_csr6 &= ~FullDuplex; if (new_csr6 != tp->csr6) { - if (inl(ioaddr + CSR6) & (csr6_st | csr6_sr)) - tulip_restart_rxtx(tp, new_csr6); - else - outl(new_csr6, ioaddr + CSR6); tp->csr6 = new_csr6; + tulip_restart_rxtx(tp); if (tulip_debug > 0) printk(KERN_INFO "%s: Setting %s-duplex based on MII" diff -u --recursive --new-file v2.4.5/linux/drivers/net/tulip/pnic.c linux/drivers/net/tulip/pnic.c --- v2.4.5/linux/drivers/net/tulip/pnic.c Sat May 19 18:02:45 2001 +++ linux/drivers/net/tulip/pnic.c Wed Jun 20 11:15:44 2001 @@ -45,7 +45,7 @@ if (tp->csr6 != new_csr6) { tp->csr6 = new_csr6; /* Restart Tx */ - tulip_restart_rxtx(tp, tp->csr6); + tulip_restart_rxtx(tp); dev->trans_start = jiffies; } } @@ -69,7 +69,7 @@ return; if (! tp->nwayset || jiffies - dev->trans_start > 1*HZ) { tp->csr6 = 0x00420000 | (tp->csr6 & 0x0000fdff); - tulip_outl_csr(tp, tp->csr6, CSR6); + outl(tp->csr6, ioaddr + CSR6); outl(0x30, ioaddr + CSR12); outl(0x0201F078, ioaddr + 0xB8); /* Turn on autonegotiation. */ dev->trans_start = jiffies; @@ -148,7 +148,7 @@ if (tp->csr6 != new_csr6) { tp->csr6 = new_csr6; /* Restart Tx */ - tulip_restart_rxtx(tp, tp->csr6); + tulip_restart_rxtx(tp); dev->trans_start = jiffies; if (tulip_debug > 1) printk(KERN_INFO "%s: Changing PNIC configuration to %s " diff -u --recursive --new-file v2.4.5/linux/drivers/net/tulip/timer.c linux/drivers/net/tulip/timer.c --- v2.4.5/linux/drivers/net/tulip/timer.c Tue Apr 3 10:19:43 2001 +++ linux/drivers/net/tulip/timer.c Wed Jun 20 11:15:44 2001 @@ -158,7 +158,7 @@ medianame[tp->mtable->mleaf[tp->cur_index].media]); tulip_select_media(dev, 0); /* Restart the transmit process. */ - tulip_restart_rxtx(tp, tp->csr6); + tulip_restart_rxtx(tp); next_tick = (24*HZ)/10; break; } diff -u --recursive --new-file v2.4.5/linux/drivers/net/tulip/tulip.h linux/drivers/net/tulip/tulip.h --- v2.4.5/linux/drivers/net/tulip/tulip.h Sun May 20 12:11:38 2001 +++ linux/drivers/net/tulip/tulip.h Wed Jun 20 11:19:02 2001 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -30,6 +31,14 @@ /* undefine, or define to various debugging levels (>4 == obscene levels) */ #define TULIP_DEBUG 1 +/* undefine USE_IO_OPS for MMIO, define for PIO */ +#ifdef CONFIG_TULIP_MMIO +# undef USE_IO_OPS +#else +# define USE_IO_OPS 1 +#endif + + struct tulip_chip_table { char *chip_name; @@ -139,10 +148,13 @@ enum tulip_mode_bits { TxThreshold = (1 << 22), FullDuplex = (1 << 9), + TxOn = 0x2000, AcceptBroadcast = 0x0100, AcceptAllMulticast = 0x0080, AcceptAllPhys = 0x0040, AcceptRunt = 0x0008, + RxOn = 0x0002, + RxTx = (TxOn | RxOn), }; @@ -219,7 +231,6 @@ * (1,1) * 1024 * 160 * ***********************************/ - csr6_st = (1<<13), /* Transmit conrol: 1 = transmit, 0 = stop */ csr6_fc = (1<<12), /* Forces a collision in next transmission (for testing in loopback mode) */ csr6_om_int_loop = (1<<10), /* internal (FIFO) loopback flag */ csr6_om_ext_loop = (1<<11), /* external (PMD) loopback flag */ @@ -231,7 +242,6 @@ csr6_if = (1<<4), /* Inverse Filtering, rejects only addresses in address table: can't be set */ csr6_pb = (1<<3), /* Pass Bad Frames, (1) causes even bad frames to be passed on */ csr6_ho = (1<<2), /* Hash-only filtering mode: can't be set */ - csr6_sr = (1<<1), /* Start(1)/Stop(0) Receive */ csr6_hp = (1<<0), /* Hash/Perfect Receive Filtering Mode: can't be set */ csr6_mask_capture = (csr6_sc | csr6_ca), @@ -434,21 +444,48 @@ extern u16 t21041_csr14[]; extern u16 t21041_csr15[]; +#ifndef USE_IO_OPS +#undef inb +#undef inw +#undef inl +#undef outb +#undef outw +#undef outl +#define inb(addr) readb((void*)(addr)) +#define inw(addr) readw((void*)(addr)) +#define inl(addr) readl((void*)(addr)) +#define outb(val,addr) writeb((val), (void*)(addr)) +#define outw(val,addr) writew((val), (void*)(addr)) +#define outl(val,addr) writel((val), (void*)(addr)) +#endif /* !USE_IO_OPS */ -static inline void tulip_outl_csr (struct tulip_private *tp, u32 newValue, enum tulip_offsets offset) + + +static inline void tulip_start_rxtx(struct tulip_private *tp) { - outl (newValue, tp->base_addr + offset); + long ioaddr = tp->base_addr; + outl(tp->csr6 | RxTx, ioaddr + CSR6); + barrier(); + (void) inl(ioaddr + CSR6); /* mmio sync */ } -static inline void tulip_stop_rxtx(struct tulip_private *tp, u32 csr6mask) +static inline void tulip_stop_rxtx(struct tulip_private *tp) { - tulip_outl_csr(tp, csr6mask & ~(csr6_st | csr6_sr), CSR6); + long ioaddr = tp->base_addr; + u32 csr6 = inl(ioaddr + CSR6); + + if (csr6 & RxTx) { + outl(csr6 & ~RxTx, ioaddr + CSR6); + barrier(); + (void) inl(ioaddr + CSR6); /* mmio sync */ + } } -static inline void tulip_restart_rxtx(struct tulip_private *tp, u32 csr6mask) +static inline void tulip_restart_rxtx(struct tulip_private *tp) { - tulip_outl_csr(tp, csr6mask | csr6_sr, CSR6); - tulip_outl_csr(tp, csr6mask | csr6_st | csr6_sr, CSR6); + tulip_stop_rxtx(tp); + udelay(5); + tulip_start_rxtx(tp); } #endif /* __NET_TULIP_H__ */ diff -u --recursive --new-file v2.4.5/linux/drivers/net/tulip/tulip_core.c linux/drivers/net/tulip/tulip_core.c --- v2.4.5/linux/drivers/net/tulip/tulip_core.c Sun May 20 12:11:38 2001 +++ linux/drivers/net/tulip/tulip_core.c Mon Jul 2 14:03:04 2001 @@ -1,4 +1,4 @@ -/* tulip_core.c: A DEC 21040-family ethernet driver for Linux. */ +/* tulip_core.c: A DEC 21x4x-family ethernet driver for Linux. */ /* Maintained by Jeff Garzik @@ -15,8 +15,8 @@ */ #define DRV_NAME "tulip" -#define DRV_VERSION "0.9.15-pre2" -#define DRV_RELDATE "May 16, 2001" +#define DRV_VERSION "0.9.15-pre6" +#define DRV_RELDATE "July 2, 2001" #include #include @@ -276,7 +276,7 @@ /* On some chip revs we must set the MII/SYM port before the reset!? */ if (tp->mii_cnt || (tp->mtable && tp->mtable->has_mii)) - tulip_outl_csr (tp, 0x00040000, CSR6); + outl(0x00040000, ioaddr + CSR6); /* Reset the chip, holding bit 0 set at least 50 PCI cycles. */ outl(0x00000001, ioaddr + CSR0); @@ -291,6 +291,11 @@ if (tulip_debug > 1) printk(KERN_DEBUG "%s: tulip_up(), irq==%d.\n", dev->name, dev->irq); + outl(tp->rx_ring_dma, ioaddr + CSR3); + outl(tp->tx_ring_dma, ioaddr + CSR4); + tp->cur_rx = tp->cur_tx = 0; + tp->dirty_rx = tp->dirty_tx = 0; + if (tp->chip_id == PNIC2) { u32 addr_high = (dev->dev_addr[1]<<8) + (dev->dev_addr[0]<<0); /* This address setting does not appear to impact chip operation?? */ @@ -340,9 +345,6 @@ tp->cur_tx++; } - outl(tp->rx_ring_dma, ioaddr + CSR3); - outl(tp->tx_ring_dma, ioaddr + CSR4); - tp->saved_if_port = dev->if_port; if (dev->if_port == 0) dev->if_port = tp->default_port; @@ -409,7 +411,7 @@ printk(KERN_INFO "%s: Using MII transceiver %d, status " "%4.4x.\n", dev->name, tp->phys[0], tulip_mdio_read(dev, tp->phys[0], 1)); - tulip_outl_csr(tp, csr6_mask_defstate, CSR6); + outl(csr6_mask_defstate, ioaddr + CSR6); tp->csr6 = csr6_mask_hdcap; dev->if_port = 11; outl(0x0000, ioaddr + CSR13); @@ -455,26 +457,26 @@ tulip_select_media(dev, 1); /* Start the chip's Tx to process setup frame. */ - tulip_outl_csr(tp, tp->csr6, CSR6); - tulip_outl_csr(tp, tp->csr6 | csr6_st, CSR6); + tulip_stop_rxtx(tp); + barrier(); + udelay(5); + outl(tp->csr6 | TxOn, ioaddr + CSR6); /* Enable interrupts by setting the interrupt mask. */ outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR5); outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7); - tulip_outl_csr(tp, tp->csr6 | csr6_st | csr6_sr, CSR6); + tulip_start_rxtx(tp); outl(0, ioaddr + CSR2); /* Rx poll demand */ if (tulip_debug > 2) { - printk(KERN_DEBUG "%s: Done tulip_open(), CSR0 %8.8x, CSR5 %8.8x CSR6 %8.8x.\n", + printk(KERN_DEBUG "%s: Done tulip_up(), CSR0 %8.8x, CSR5 %8.8x CSR6 %8.8x.\n", dev->name, inl(ioaddr + CSR0), inl(ioaddr + CSR5), inl(ioaddr + CSR6)); } + /* Set the timer to switch to check for link beat and perhaps switch to an alternate media type. */ - init_timer(&tp->timer); tp->timer.expires = RUN_AT(next_tick); - tp->timer.data = (unsigned long)dev; - tp->timer.function = tulip_tbl[tp->chip_id].media_timer; add_timer(&tp->timer); } @@ -626,7 +628,7 @@ if (tp->fc_bit && test_bit(tp->fc_bit,&netdev_fc_xoff)) printk("BUG tx_timeout restarting rx when fc on\n"); #endif - tulip_restart_rxtx(tp, tp->csr6); + tulip_restart_rxtx(tp); /* Trigger an immediate transmit demand. */ outl(0, ioaddr + CSR1); @@ -645,8 +647,6 @@ struct tulip_private *tp = (struct tulip_private *)dev->priv; int i; - tp->cur_rx = tp->cur_tx = 0; - tp->dirty_rx = tp->dirty_tx = 0; tp->susp_rx = 0; tp->ttimer = 0; tp->nir = 0; @@ -742,6 +742,41 @@ return 0; } +static void tulip_release_unconsumed_tx_buffers(struct tulip_private *tp) +{ + unsigned int dirty_tx; + + for (dirty_tx = tp->dirty_tx ; tp->cur_tx - dirty_tx > 0; + dirty_tx++) { + int entry = dirty_tx % TX_RING_SIZE; + int status = le32_to_cpu(tp->tx_ring[entry].status); + + if (status > 0) + break; /* It has been Txed */ + + /* Check for Rx filter setup frames. */ + if (tp->tx_buffers[entry].skb == NULL) { + /* test because dummy frames not mapped */ + if (tp->tx_buffers[entry].mapping) + pci_unmap_single(tp->pdev, + tp->tx_buffers[entry].mapping, + sizeof(tp->setup_frame), + PCI_DMA_TODEVICE); + continue; + } + tp->stats.tx_errors++; + + pci_unmap_single(tp->pdev, tp->tx_buffers[entry].mapping, + tp->tx_buffers[entry].skb->len, + PCI_DMA_TODEVICE); + + /* Free the original skb. */ + dev_kfree_skb_irq(tp->tx_buffers[entry].skb); + tp->tx_buffers[entry].skb = NULL; + tp->tx_buffers[entry].mapping = 0; + } +} + static void tulip_down (struct net_device *dev) { long ioaddr = dev->base_addr; @@ -756,7 +791,13 @@ outl (0x00000000, ioaddr + CSR7); /* Stop the Tx and Rx processes. */ - tulip_stop_rxtx(tp, inl(ioaddr + CSR6)); + tulip_stop_rxtx(tp); + + /* prepare receive buffers */ + tulip_refill_rx(dev); + + /* release any unconsumed transmit buffers */ + tulip_release_unconsumed_tx_buffers(tp); /* 21040 -- Leave the card in 10baseT state. */ if (tp->chip_id == DC21040) @@ -767,6 +808,10 @@ spin_unlock_irqrestore (&tp->lock, flags); + init_timer(&tp->timer); + tp->timer.data = (unsigned long)dev; + tp->timer.function = tulip_tbl[tp->chip_id].media_timer; + dev->if_port = tp->saved_if_port; /* Leave the driver in snooze, not sleep, mode. */ @@ -879,66 +924,72 @@ { struct tulip_private *tp = dev->priv; long ioaddr = dev->base_addr; - u16 *data = (u16 *) & rq->ifr_data; + struct mii_ioctl_data *data = (struct mii_ioctl_data *) & rq->ifr_data; const unsigned int phy_idx = 0; int phy = tp->phys[phy_idx] & 0x1f; - unsigned int regnum = data[1]; + unsigned int regnum = data->reg_num; switch (cmd) { case SIOCETHTOOL: return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); - case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ + + case SIOCGMIIPHY: /* Get address of MII PHY in use. */ + case SIOCDEVPRIVATE: /* for binary compat, remove in 2.5 */ if (tp->mii_cnt) - data[0] = phy; + data->phy_id = phy; else if (tp->flags & HAS_NWAY) - data[0] = 32; + data->phy_id = 32; else if (tp->chip_id == COMET) - data[0] = 1; + data->phy_id = 1; else return -ENODEV; - case SIOCDEVPRIVATE + 1: /* Read the specified MII register. */ - if (data[0] == 32 && (tp->flags & HAS_NWAY)) { + + case SIOCGMIIREG: /* Read MII PHY register. */ + case SIOCDEVPRIVATE+1: /* for binary compat, remove in 2.5 */ + if (data->phy_id == 32 && (tp->flags & HAS_NWAY)) { int csr12 = inl (ioaddr + CSR12); int csr14 = inl (ioaddr + CSR14); switch (regnum) { case 0: if (((csr14<<5) & 0x1000) || (dev->if_port == 5 && tp->nwayset)) - data[3] = 0x1000; + data->val_out = 0x1000; else - data[3] = (tulip_media_cap[dev->if_port]&MediaIs100 ? 0x2000 : 0) + data->val_out = (tulip_media_cap[dev->if_port]&MediaIs100 ? 0x2000 : 0) | (tulip_media_cap[dev->if_port]&MediaIsFD ? 0x0100 : 0); break; case 1: - data[3] = + data->val_out = 0x1848 + ((csr12&0x7000) == 0x5000 ? 0x20 : 0) + ((csr12&0x06) == 6 ? 0 : 4); if (tp->chip_id != DC21041) - data[3] |= 0x6048; + data->val_out |= 0x6048; break; case 4: /* Advertised value, bogus 10baseTx-FD value from CSR6. */ - data[3] = + data->val_out = ((inl(ioaddr + CSR6) >> 3) & 0x0040) + ((csr14 >> 1) & 0x20) + 1; if (tp->chip_id != DC21041) - data[3] |= ((csr14 >> 9) & 0x03C0); + data->val_out |= ((csr14 >> 9) & 0x03C0); break; - case 5: data[3] = tp->lpar; break; - default: data[3] = 0; break; + case 5: data->val_out = tp->lpar; break; + default: data->val_out = 0; break; } } else { - data[3] = tulip_mdio_read (dev, data[0] & 0x1f, regnum); + data->val_out = tulip_mdio_read (dev, data->phy_id & 0x1f, regnum); } return 0; - case SIOCDEVPRIVATE + 2: /* Write the specified MII register */ + + case SIOCSMIIREG: /* Write MII PHY register. */ + case SIOCDEVPRIVATE+2: /* for binary compat, remove in 2.5 */ if (!capable (CAP_NET_ADMIN)) return -EPERM; if (regnum & ~0x1f) return -EINVAL; - if (data[0] == phy) { - u16 value = data[2]; + if (data->phy_id == phy) { + u16 value = data->val_in; switch (regnum) { case 0: /* Check for autonegotiation on or reset. */ tp->full_duplex_lock = (value & 0x9000) ? 0 : 1; @@ -947,19 +998,19 @@ break; case 4: tp->advertising[phy_idx] = - tp->mii_advertise = data[2]; + tp->mii_advertise = data->val_in; break; } } - if (data[0] == 32 && (tp->flags & HAS_NWAY)) { - u16 value = data[2]; + if (data->phy_id == 32 && (tp->flags & HAS_NWAY)) { + u16 value = data->val_in; if (regnum == 0) { if ((value & 0x1200) == 0x1200) t21142_start_nway (dev); } else if (regnum == 4) tp->sym_advertise = value; } else { - tulip_mdio_write (dev, data[0] & 0x1f, regnum, data[2]); + tulip_mdio_write (dev, data->phy_id & 0x1f, regnum, data->val_in); } return 0; default: @@ -1108,7 +1159,7 @@ else filterbit = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; filterbit &= 0x3f; - set_bit(filterbit, mc_filter); + mc_filter[filterbit >> 5] |= cpu_to_le32(1 << (filterbit & 31)); if (tulip_debug > 2) { printk(KERN_INFO "%s: Added filter for %2.2x:%2.2x:%2.2x:" "%2.2x:%2.2x:%2.2x %8.8x bit %d.\n", dev->name, @@ -1193,95 +1244,96 @@ spin_unlock_irqrestore(&tp->lock, flags); } - /* Can someone explain to me what the OR here is supposed to accomplish???? */ - tulip_outl_csr(tp, csr6 | 0x0000, CSR6); + outl(csr6, ioaddr + CSR6); } +#ifdef CONFIG_TULIP_MWI static void __devinit tulip_mwi_config (struct pci_dev *pdev, struct net_device *dev) { struct tulip_private *tp = dev->priv; - u8 pci_cacheline; + u8 cache; u16 pci_command, new_command; - unsigned mwi = 1; + u32 csr0; if (tulip_debug > 3) printk(KERN_DEBUG "%s: tulip_mwi_config()\n", pdev->slot_name); - /* get a sane cache line size, if possible */ - pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &pci_cacheline); - if (pci_cacheline < (SMP_CACHE_BYTES / 4)) - pci_cacheline = SMP_CACHE_BYTES / 4; - if (pci_cacheline > TULIP_MAX_CACHE_LINE) - pci_cacheline = TULIP_MAX_CACHE_LINE; - switch (pci_cacheline) { - case 8: - case 16: - case 32: break; - default: pci_cacheline = TULIP_MIN_CACHE_LINE; break; + tp->csr0 = 0; + + /* check for sane cache line size. from acenic.c. */ + pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache); + if ((cache << 2) != SMP_CACHE_BYTES) { + printk(KERN_WARNING "%s: PCI cache line size set incorrectly " + "(%i bytes) by BIOS/FW, correcting to %i\n", + pdev->slot_name, (cache << 2), SMP_CACHE_BYTES); + pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, + SMP_CACHE_BYTES >> 2); + udelay(5); } - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, pci_cacheline); - /* read back the result. if zero, or if a buggy chip rev, - * disable MWI - */ - pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &pci_cacheline); - if (!pci_cacheline || (tp->chip_id == DC21143 && tp->revision == 65)) - mwi = 0; - - /* re-clamp cache line values to ones supported by tulip */ - /* From this point forward, 'pci_cacheline' is really - * the value used for csr0 cache alignment and - * csr0 programmable burst length + /* read cache line size again, hardware may not have accepted + * our cache line size change */ - switch (pci_cacheline) { - case 0: - case 8: - case 16: - case 32: break; - default: pci_cacheline = TULIP_MIN_CACHE_LINE; break; - } + pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache); + if (!cache) + goto out; + + /* if we have any cache line size at all, we can do MRM */ + csr0 |= MRM; + + /* ...and barring hardware bugs, MWI */ + if (!(tp->chip_id == DC21143 && tp->revision == 65)) + csr0 |= MWI; /* set or disable MWI in the standard PCI command bit. * Check for the case where mwi is desired but not available */ pci_read_config_word(pdev, PCI_COMMAND, &pci_command); - if (mwi) new_command = pci_command | PCI_COMMAND_INVALIDATE; + if (csr0 & MWI) new_command = pci_command | PCI_COMMAND_INVALIDATE; else new_command = pci_command & ~PCI_COMMAND_INVALIDATE; if (new_command != pci_command) { pci_write_config_word(pdev, PCI_COMMAND, new_command); + udelay(5); pci_read_config_word(pdev, PCI_COMMAND, &pci_command); - if ((new_command != pci_command) && mwi && - ((pci_command & PCI_COMMAND_INVALIDATE) == 0)) - mwi = 0; + if ((csr0 & MWI) && (!(pci_command & PCI_COMMAND_INVALIDATE))) + csr0 &= ~MWI; } - tp->csr0 = MRL | MRM; - - /* if no PCI cache line size, bail out with minimal - * burst size and cache alignment of 8 dwords. - * We always want to have some sort of limit. + /* assign per-cacheline-size cache alignment and + * burst length values */ - if (!pci_cacheline) { - tp->csr0 |= (8 << BurstLenShift) | (1 << CALShift); + switch (cache) { + case 8: + csr0 |= MRL | (1 << CALShift) | (16 << BurstLenShift); + break; + case 16: + csr0 |= MRL | (2 << CALShift) | (16 << BurstLenShift); + break; + case 32: + csr0 |= MRL | (3 << CALShift) | (32 << BurstLenShift); + break; + default: goto out; } + + tp->csr0 = csr0; + goto out; - /* finally, build the csr0 value */ - if (mwi) - tp->csr0 |= MWI; - tp->csr0 |= (pci_cacheline << BurstLenShift); - switch (pci_cacheline) { - case 8: tp->csr0 |= (1 << CALShift); - case 16: tp->csr0 |= (2 << CALShift); - case 32: tp->csr0 |= (3 << CALShift); +early_out: + if (csr0 & MWI) { + pci_command &= ~PCI_COMMAND_INVALIDATE; + pci_write_config_word(pdev, PCI_COMMAND, pci_command); + csr0 &= ~MWI; } + tp->csr0 = csr0 | (8 << BurstLenShift) | (1 << CALShift); out: if (tulip_debug > 2) - printk(KERN_DEBUG "%s: MWI config mwi=%d, cacheline=%d, csr0=%08x\n", - pdev->slot_name, mwi, pci_cacheline, tp->csr0); + printk(KERN_DEBUG "%s: MWI config cacheline=%d, csr0=%08x\n", + pdev->slot_name, cache, csr0); } +#endif static int __devinit tulip_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) @@ -1402,6 +1454,13 @@ if (pci_request_regions (pdev, "tulip")) goto err_out_free_netdev; +#ifndef USE_IO_OPS + ioaddr = (unsigned long) ioremap (pci_resource_start (pdev, 1), + tulip_tbl[chip_idx].io_size); + if (!ioaddr) + goto err_out_free_res; +#endif + pci_set_master(pdev); pci_read_config_byte (pdev, PCI_REVISION_ID, &chip_rev); @@ -1417,7 +1476,7 @@ sizeof(struct tulip_tx_desc) * TX_RING_SIZE, &tp->rx_ring_dma); if (!tp->rx_ring) - goto err_out_free_res; + goto err_out_mtable; tp->tx_ring = (struct tulip_tx_desc *)(tp->rx_ring + RX_RING_SIZE); tp->tx_ring_dma = tp->rx_ring_dma + sizeof(struct tulip_rx_desc) * RX_RING_SIZE; @@ -1429,15 +1488,20 @@ tp->csr0 = csr0; spin_lock_init(&tp->lock); spin_lock_init(&tp->mii_lock); + init_timer(&tp->timer); + tp->timer.data = (unsigned long)dev; + tp->timer.function = tulip_tbl[tp->chip_id].media_timer; dev->base_addr = ioaddr; dev->irq = irq; +#ifdef CONFIG_TULIP_MWI if (!force_csr0 && (tp->flags & HAS_PCI_MWI)) tulip_mwi_config (pdev, dev); +#endif /* Stop the chip's Tx and Rx processes. */ - tulip_stop_rxtx(tp, inl(ioaddr + CSR6)); + tulip_stop_rxtx(tp); /* Clear the missed-packet counter. */ inl(ioaddr + CSR8); @@ -1600,7 +1664,7 @@ dev->set_multicast_list = set_rx_mode; if (register_netdev(dev)) - goto err_out_mtable; + goto err_out_free_ring; printk(KERN_INFO "%s: %s rev %d at %#3lx,", dev->name, tulip_tbl[chip_idx].chip_name, chip_rev, ioaddr); @@ -1631,7 +1695,7 @@ outl(0x00000000, ioaddr + CSR13); outl(0xFFFFFFFF, ioaddr + CSR14); outl(0x00000008, ioaddr + CSR15); /* Listen on AUI also. */ - tulip_outl_csr(tp, inl(ioaddr + CSR6) | csr6_fd, CSR6); + outl(inl(ioaddr + CSR6) | csr6_fd, ioaddr + CSR6); outl(0x0000EF01, ioaddr + CSR13); break; case DC21040: @@ -1647,10 +1711,10 @@ case DC21142: case PNIC2: if (tp->mii_cnt || tulip_media_cap[dev->if_port] & MediaIsMII) { - tulip_outl_csr(tp, csr6_mask_defstate, CSR6); + outl(csr6_mask_defstate, ioaddr + CSR6); outl(0x0000, ioaddr + CSR13); outl(0x0000, ioaddr + CSR14); - tulip_outl_csr(tp, csr6_mask_hdcap, CSR6); + outl(csr6_mask_hdcap, ioaddr + CSR6); } else t21142_start_nway(dev); break; @@ -1658,21 +1722,21 @@ if ( ! tp->mii_cnt) { tp->nway = 1; tp->nwayset = 0; - tulip_outl_csr(tp, csr6_ttm | csr6_ca, CSR6); + outl(csr6_ttm | csr6_ca, ioaddr + CSR6); outl(0x30, ioaddr + CSR12); - tulip_outl_csr(tp, 0x0001F078, CSR6); - tulip_outl_csr(tp, 0x0201F078, CSR6); /* Turn on autonegotiation. */ + outl(0x0001F078, ioaddr + CSR6); + outl(0x0201F078, ioaddr + CSR6); /* Turn on autonegotiation. */ } break; case MX98713: case COMPEX9881: - tulip_outl_csr(tp, 0x00000000, CSR6); + outl(0x00000000, ioaddr + CSR6); outl(0x000711C0, ioaddr + CSR14); /* Turn on NWay. */ outl(0x00000001, ioaddr + CSR13); break; case MX98715: case MX98725: - tulip_outl_csr(tp, 0x01a80000, CSR6); + outl(0x01a80000, ioaddr + CSR6); outl(0xFFFFFFFF, ioaddr + CSR14); outl(0x00001000, ioaddr + CSR12); break; @@ -1686,18 +1750,31 @@ return 0; +err_out_free_ring: + pci_free_consistent (pdev, + sizeof (struct tulip_rx_desc) * RX_RING_SIZE + + sizeof (struct tulip_tx_desc) * TX_RING_SIZE, + tp->rx_ring, tp->rx_ring_dma); + err_out_mtable: if (tp->mtable) kfree (tp->mtable); +#ifndef USE_IO_OPS + iounmap((void *)ioaddr); +#endif + err_out_free_res: pci_release_regions (pdev); + err_out_free_netdev: kfree (dev); return -ENODEV; } -static void tulip_suspend (struct pci_dev *pdev) +#ifdef CONFIG_PM + +static int tulip_suspend (struct pci_dev *pdev, u32 state) { struct net_device *dev = pci_get_drvdata(pdev); @@ -1706,10 +1783,11 @@ tulip_down (dev); /* pci_power_off(pdev, -1); */ } + return 0; } -static void tulip_resume(struct pci_dev *pdev) +static int tulip_resume(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); @@ -1721,8 +1799,11 @@ tulip_up (dev); netif_device_attach (dev); } + return 0; } +#endif /* CONFIG_PM */ + static void __devexit tulip_remove_one (struct pci_dev *pdev) { @@ -1740,6 +1821,9 @@ unregister_netdev (dev); if (tp->mtable) kfree (tp->mtable); +#ifndef USE_IO_OPS + iounmap((void *)dev->base_addr); +#endif kfree (dev); pci_release_regions (pdev); pci_set_drvdata (pdev, NULL); @@ -1753,8 +1837,10 @@ id_table: tulip_pci_tbl, probe: tulip_init_one, remove: tulip_remove_one, +#ifdef CONFIG_PM suspend: tulip_suspend, resume: tulip_resume, +#endif /* CONFIG_PM */ }; diff -u --recursive --new-file v2.4.5/linux/drivers/net/tun.c linux/drivers/net/tun.c --- v2.4.5/linux/drivers/net/tun.c Wed Apr 18 14:40:06 2001 +++ linux/drivers/net/tun.c Mon Jun 11 19:15:27 2001 @@ -12,7 +12,7 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * $Id: tun.c,v 1.3 2000/10/23 10:01:25 maxk Exp $ + * $Id: tun.c,v 1.12 2001/03/08 03:29:27 maxk Exp $ */ /* @@ -20,15 +20,16 @@ * Modifications for 2.3.99-pre5 kernel. */ -#define TUN_VER "1.3" +#define TUN_VER "1.4" +#include #include #include #include #include #include -#include +#include #include #include #include @@ -56,28 +57,14 @@ /* Net device open. */ static int tun_net_open(struct net_device *dev) { -#ifdef TUN_DEBUG - struct tun_struct *tun = (struct tun_struct *)dev->priv; - - DBG(KERN_INFO "%s: tun_net_open\n", tun->name); -#endif - netif_start_queue(dev); - return 0; } /* Net device close. */ static int tun_net_close(struct net_device *dev) { -#ifdef TUN_DEBUG - struct tun_struct *tun = (struct tun_struct *)dev->priv; - - DBG(KERN_INFO "%s: tun_net_close\n", tun->name); -#endif - netif_stop_queue(dev); - return 0; } @@ -88,38 +75,46 @@ DBG(KERN_INFO "%s: tun_net_xmit %d\n", tun->name, skb->len); - /* Queue frame */ - skb_queue_tail(&tun->txq, skb); - if (skb_queue_len(&tun->txq) >= TUN_TXQ_SIZE) - netif_stop_queue(dev); + /* Drop packet if interface is not attached */ + if (!tun->attached) + goto drop; + + /* Queue packet */ + if (!(tun->flags & TUN_ONE_QUEUE)) { + /* Normal queueing mode. + * Packet scheduler handles dropping. */ + if (skb_queue_len(&tun->readq) >= TUN_READQ_SIZE) + netif_stop_queue(dev); + } else { + /* Single queue mode. + * Driver handles dropping itself. */ + if (skb_queue_len(&tun->readq) >= dev->tx_queue_len) + goto drop; + } + skb_queue_tail(&tun->readq, skb); + /* Notify and wake up reader process */ if (tun->flags & TUN_FASYNC) kill_fasync(&tun->fasync, SIGIO, POLL_IN); - - /* Wake up process */ wake_up_interruptible(&tun->read_wait); + return 0; +drop: + tun->stats.tx_dropped++; + kfree_skb(skb); return 0; } static void tun_net_mclist(struct net_device *dev) { -#ifdef TUN_DEBUG - struct tun_struct *tun = (struct tun_struct *)dev->priv; - - DBG(KERN_INFO "%s: tun_net_mclist\n", tun->name); -#endif - /* Nothing to do for multicast filters. - * We always accept all frames. - */ + * We always accept all frames. */ return; } static struct net_device_stats *tun_net_stats(struct net_device *dev) { struct tun_struct *tun = (struct tun_struct *)dev->priv; - return &tun->stats; } @@ -170,15 +165,19 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait) { struct tun_struct *tun = (struct tun_struct *)file->private_data; + unsigned int mask = POLLOUT | POLLWRNORM; + + if (!tun) + return -EBADFD; DBG(KERN_INFO "%s: tun_chr_poll\n", tun->name); poll_wait(file, &tun->read_wait, wait); - if (skb_queue_len(&tun->txq)) - return POLLIN | POLLRDNORM; + if (skb_queue_len(&tun->readq)) + mask |= POLLIN | POLLRDNORM; - return POLLOUT | POLLWRNORM; + return mask; } /* Get packet from user space buffer(already verified) */ @@ -189,9 +188,6 @@ register int len = count; struct sk_buff *skb; - if (len > TUN_MAX_FRAME) - return -EINVAL; - if (!(tun->flags & TUN_NO_PI)) { if ((len -= sizeof(pi)) < 0) return -EINVAL; @@ -222,7 +218,6 @@ if (tun->flags & TUN_NOCHECKSUM) skb->ip_summed = CHECKSUM_UNNECESSARY; - skb->dev->last_rx = jiffies; netif_rx(skb); tun->stats.rx_packets++; @@ -237,10 +232,10 @@ { struct tun_struct *tun = (struct tun_struct *)file->private_data; - DBG(KERN_INFO "%s: tun_chr_write %d\n", tun->name, count); + if (!tun) + return -EBADFD; - if (!(tun->flags & TUN_IFF_SET)) - return -EBUSY; + DBG(KERN_INFO "%s: tun_chr_write %d\n", tun->name, count); if (verify_area(VERIFY_READ, buf, count)) return -EFAULT; @@ -291,14 +286,17 @@ struct sk_buff *skb; ssize_t ret = 0; + if (!tun) + return -EBADFD; + DBG(KERN_INFO "%s: tun_chr_read\n", tun->name); add_wait_queue(&tun->read_wait, &wait); while (count) { current->state = TASK_INTERRUPTIBLE; - /* Read frames from device queue */ - if (!(skb=skb_dequeue(&tun->txq))) { + /* Read frames from the queue */ + if (!(skb=skb_dequeue(&tun->readq))) { if (file->f_flags & O_NONBLOCK) { ret = -EAGAIN; break; @@ -334,50 +332,83 @@ return -ESPIPE; } -static int tun_set_iff(struct tun_struct *tun, unsigned long arg) +static int tun_set_iff(struct file *file, struct ifreq *ifr) { - struct ifreq ifr; - char *mask; + struct tun_struct *tun; + struct net_device *dev; + int err; + + dev = __dev_get_by_name(ifr->ifr_name); + if (dev) { + /* Device exist */ + tun = dev->priv; + + if (dev->init != tun_net_init || tun->attached) + return -EBUSY; + + /* Check permissions */ + if (tun->owner != -1) + if (current->euid != tun->owner && !capable(CAP_NET_ADMIN)) + return -EPERM; + } else { + char *name; + + /* Allocate new device */ + if (!(tun = kmalloc(sizeof(struct tun_struct), GFP_KERNEL)) ) + return -ENOMEM; + memset(tun, 0, sizeof(struct tun_struct)); + + skb_queue_head_init(&tun->readq); + init_waitqueue_head(&tun->read_wait); + + tun->owner = -1; + tun->dev.init = tun_net_init; + tun->dev.priv = tun; + + err = -EINVAL; + + /* Set dev type */ + if (ifr->ifr_flags & IFF_TUN) { + /* TUN device */ + tun->flags |= TUN_TUN_DEV; + name = "tun%d"; + } else if (ifr->ifr_flags & IFF_TAP) { + /* TAP device */ + tun->flags |= TUN_TAP_DEV; + name = "tap%d"; + } else + goto failed; + + if (*ifr->ifr_name) + name = ifr->ifr_name; - if (copy_from_user(&ifr, (void *)arg, sizeof(ifr))) - return -EFAULT; - ifr.ifr_name[IFNAMSIZ-1] = '\0'; + if ((err = dev_alloc_name(&tun->dev, name)) < 0) + goto failed; + if ((err = register_netdevice(&tun->dev))) + goto failed; + + MOD_INC_USE_COUNT; - if (tun->flags & TUN_IFF_SET) - return -EEXIST; + tun->name = tun->dev.name; + } - /* Set dev type */ - if (ifr.ifr_flags & IFF_TUN) { - /* TUN device */ - tun->flags |= TUN_TUN_DEV; - mask = "tun%d"; - } else if (ifr.ifr_flags & IFF_TAP) { - /* TAP device */ - tun->flags |= TUN_TAP_DEV; - mask = "tap%d"; - } else - return -EINVAL; - - if (ifr.ifr_flags & IFF_NO_PI) + DBG(KERN_INFO "%s: tun_set_iff\n", tun->name); + + if (ifr->ifr_flags & IFF_NO_PI) tun->flags |= TUN_NO_PI; - if (*ifr.ifr_name) - strcpy(tun->dev.name, ifr.ifr_name); - else - strcpy(tun->dev.name, mask); - - /* Register net device */ - if (register_netdev(&tun->dev)) - return -EBUSY; - - tun->flags |= TUN_IFF_SET; - strcpy(tun->name, tun->dev.name); - - /* Return iface info to the user space */ - strcpy(ifr.ifr_name, tun->dev.name); - copy_to_user((void *)arg, &ifr, sizeof(ifr)); + if (ifr->ifr_flags & IFF_ONE_QUEUE) + tun->flags |= TUN_ONE_QUEUE; + + file->private_data = tun; + tun->attached = 1; + + strcpy(ifr->ifr_name, tun->name); + return 0; - return 0; +failed: + kfree(tun); + return err; } static int tun_chr_ioctl(struct inode *inode, struct file *file, @@ -385,14 +416,33 @@ { struct tun_struct *tun = (struct tun_struct *)file->private_data; - DBG(KERN_INFO "%s: tun_chr_ioctl\n", tun->name); + if (cmd == TUNSETIFF && !tun) { + struct ifreq ifr; + int err; + + if (copy_from_user(&ifr, (void *)arg, sizeof(ifr))) + return -EFAULT; + ifr.ifr_name[IFNAMSIZ-1] = '\0'; - switch (cmd) { - case TUNSETIFF: - return tun_set_iff(tun, arg); + rtnl_lock(); + err = tun_set_iff(file, &ifr); + rtnl_unlock(); + if (err) + return err; + + copy_to_user((void *)arg, &ifr, sizeof(ifr)); + return 0; + } + + if (!tun) + return -EBADFD; + + DBG(KERN_INFO "%s: tun_chr_ioctl cmd %d\n", tun->name, cmd); + + switch (cmd) { case TUNSETNOCSUM: - /* Disable/Enable checksum on net iface */ + /* Disable/Enable checksum */ if (arg) tun->flags |= TUN_NOCHECKSUM; else @@ -402,6 +452,24 @@ tun->name, arg ? "disabled" : "enabled"); break; + case TUNSETPERSIST: + /* Disable/Enable persist mode */ + if (arg) + tun->flags |= TUN_PERSIST; + else + tun->flags &= ~TUN_PERSIST; + + DBG(KERN_INFO "%s: persist %s\n", + tun->name, arg ? "disabled" : "enabled"); + break; + + case TUNSETOWNER: + /* Set owner of the device */ + tun->owner = (uid_t) arg; + + DBG(KERN_INFO "%s: owner set to %d\n", tun->owner); + break; + #ifdef TUN_DEBUG case TUNSETDEBUG: tun->debug = arg; @@ -420,14 +488,22 @@ struct tun_struct *tun = (struct tun_struct *)file->private_data; int ret; + if (!tun) + return -EBADFD; + DBG(KERN_INFO "%s: tun_chr_fasync %d\n", tun->name, on); if ((ret = fasync_helper(fd, file, on, &tun->fasync)) < 0) return ret; - if (on) + if (on) { tun->flags |= TUN_FASYNC; - else + if (!file->f_owner.pid) { + file->f_owner.pid = current->pid; + file->f_owner.uid = current->uid; + file->f_owner.euid = current->euid; + } + } else tun->flags &= ~TUN_FASYNC; return 0; @@ -435,25 +511,8 @@ static int tun_chr_open(struct inode *inode, struct file * file) { - struct tun_struct *tun = NULL; - DBG1(KERN_INFO "tunX: tun_chr_open\n"); - - tun = kmalloc(sizeof(struct tun_struct), GFP_KERNEL); - if (tun == NULL) - return -ENOMEM; - - memset(tun, 0, sizeof(struct tun_struct)); - file->private_data = tun; - - skb_queue_head_init(&tun->txq); - init_waitqueue_head(&tun->read_wait); - - sprintf(tun->name, "tunX"); - - tun->dev.init = tun_net_init; - tun->dev.priv = tun; - + file->private_data = NULL; return 0; } @@ -461,22 +520,30 @@ { struct tun_struct *tun = (struct tun_struct *)file->private_data; - DBG(KERN_INFO "%s: tun_chr_close\n", tun->name); + if (!tun) + return 0; - if (tun->flags & TUN_IFF_SET) { - rtnl_lock(); - dev_close(&tun->dev); - rtnl_unlock(); + DBG(KERN_INFO "%s: tun_chr_close\n", tun->name); - /* Drop TX queue */ - skb_queue_purge(&tun->txq); + tun_chr_fasync(-1, file, 0); - unregister_netdev(&tun->dev); - } + rtnl_lock(); - kfree(tun); + /* Detach from net device */ file->private_data = NULL; + tun->attached = 0; + + /* Drop read queue */ + skb_queue_purge(&tun->readq); + + if (!(tun->flags & TUN_PERSIST)) { + dev_close(&tun->dev); + unregister_netdevice(&tun->dev); + kfree(tun); + MOD_DEC_USE_COUNT; + } + rtnl_unlock(); return 0; } @@ -494,15 +561,15 @@ static struct miscdevice tun_miscdev= { - TUN_MINOR, - "net/tun", - &tun_fops + TUN_MINOR, + "net/tun", + &tun_fops }; int __init tun_init(void) { printk(KERN_INFO "Universal TUN/TAP device driver %s " - "(C)1999-2000 Maxim Krasnyansky\n", TUN_VER); + "(C)1999-2001 Maxim Krasnyansky\n", TUN_VER); if (misc_register(&tun_miscdev)) { printk(KERN_ERR "tun: Can't register misc device %d\n", TUN_MINOR); diff -u --recursive --new-file v2.4.5/linux/drivers/net/via-rhine.c linux/drivers/net/via-rhine.c --- v2.4.5/linux/drivers/net/via-rhine.c Fri Apr 20 11:54:23 2001 +++ linux/drivers/net/via-rhine.c Mon Jul 2 14:03:04 2001 @@ -1,6 +1,6 @@ /* via-rhine.c: A Linux Ethernet device driver for VIA Rhine family chips. */ /* - Written 1998-2000 by Donald Becker. + Written 1998-2001 by Donald Becker. This software may be used and distributed according to the terms of the GNU General Public License (GPL), incorporated herein by reference. @@ -58,6 +58,12 @@ LK1.1.7: - Manfred Spraul: added reset into tx_timeout + + LK1.1.9: + - Urban Widmark: merges from Beckers 1.10 version + (media selection + eeprom reload) + - David Vrabel: merges from D-Link "1.11" version + (disable WOL and PME on startup) */ @@ -75,6 +81,11 @@ Both 'options[]' and 'full_duplex[]' should exist for driver interoperability. The media type is usually passed in 'options[]'. + The default is autonegotation for speed and duplex. + This should rarely be overridden. + Use option values 0x10/0x20 for 10Mbps, 0x100,0x200 for 100Mbps. + Use option values 0x10 and 0x100 for forcing half duplex fixed speed. + Use option values 0x20 and 0x200 for forcing full duplex operation. */ #define MAX_UNITS 8 /* More are supported, limit only on options */ static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; @@ -104,6 +115,9 @@ #define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/ +/* max time out delay time */ +#define W_MAX_TIMEOUT 0x0FFFU + #if !defined(__OPTIMIZE__) || !defined(__KERNEL__) #warning You must compile this file with the correct options! @@ -125,6 +139,7 @@ #include #include #include +#include #include /* Processor type for cache alignment. */ #include #include @@ -132,9 +147,10 @@ /* These identify the driver base version and may not be removed. */ static char version[] __devinitdata = -KERN_INFO "via-rhine.c:v1.08b-LK1.1.8 4/17/2000 Written by Donald Becker\n" +KERN_INFO "via-rhine.c:v1.10-LK1.1.9 05/31/2001 Written by Donald Becker\n" KERN_INFO " http://www.scyld.com/network/via-rhine.html\n"; +static char shortname[] __devinitdata = "via-rhine"; /* This driver was written to use PCI memory space, however most versions @@ -165,7 +181,11 @@ MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); - +MODULE_PARM_DESC(max_interrupt_work, "VIA Rhine maximum events handled per interrupt"); +MODULE_PARM_DESC(debug, "VIA Rhine debug level (0-7)"); +MODULE_PARM_DESC(rx_copybreak, "VIA Rhine copy breakpoint for copy-only-tiny-frames"); +MODULE_PARM_DESC(options, "VIA Rhine: Bits 0-3: media type, bit 17: full duplex"); +MODULE_PARM_DESC(full_duplex, "VIA Rhine full duplex setting(s) (1)"); /* Theory of Operation @@ -244,6 +264,9 @@ Preliminary VT86C100A manual from http://www.via.com.tw/ http://www.scyld.com/expert/100mbps.html http://www.scyld.com/expert/NWay.html +ftp://ftp.via.com.tw/public/lan/Products/NIC/VT86C100A/Datasheet/VT86C100A03.pdf +ftp://ftp.via.com.tw/public/lan/Products/NIC/VT6102/Datasheet/VT6102_021.PDF + IVc. Errata @@ -256,7 +279,6 @@ */ - /* This table drives the PCI probe routines. It's mostly boilerplate in all of the drivers, and will likely be provided by some future kernel. Note the matching code -- the first table entry matchs all 56** cards but @@ -320,9 +342,9 @@ StationAddr=0x00, RxConfig=0x06, TxConfig=0x07, ChipCmd=0x08, IntrStatus=0x0C, IntrEnable=0x0E, MulticastFilter0=0x10, MulticastFilter1=0x14, - RxRingPtr=0x18, TxRingPtr=0x1C, + RxRingPtr=0x18, TxRingPtr=0x1C, GFIFOTest=0x54, MIIPhyAddr=0x6C, MIIStatus=0x6D, PCIBusConfig=0x6E, - MIICmd=0x70, MIIRegAddr=0x71, MIIData=0x72, + MIICmd=0x70, MIIRegAddr=0x71, MIIData=0x72, MACRegEEcsr=0x74, Config=0x78, ConfigA=0x7A, RxMissed=0x7C, RxCRCErrs=0x7E, StickyHW=0x83, WOLcrClr=0xA4, WOLcgClr=0xA7, PwrcsrClr=0xAC, }; @@ -448,24 +470,29 @@ static int via_rhine_close(struct net_device *dev); static inline void clear_tally_counters(long ioaddr); -static void wait_for_reset(struct net_device *dev) +static void wait_for_reset(struct net_device *dev, char *name) { + struct netdev_private *np = dev->priv; long ioaddr = dev->base_addr; + int chip_id = np->chip_id; int i; + /* 3043 may need long delay after reset (dlink) */ + if (chip_id == VT3043 || chip_id == VT86C100A) + udelay(100); + i = 0; do { udelay(5); i++; if(i > 2000) { - printk(KERN_ERR "%s: reset did not complete in 10 ms.\n", - dev->name); + printk(KERN_ERR "%s: reset did not complete in 10 ms.\n", name); break; } } while(readw(ioaddr + ChipCmd) & CmdReset); if (debug > 1) printk(KERN_INFO "%s: reset finished after %d microseconds.\n", - dev->name, 5*i); + name, 5*i); } static int __devinit via_rhine_init_one (struct pci_dev *pdev, @@ -515,13 +542,12 @@ dev = alloc_etherdev(sizeof(*np)); if (dev == NULL) { - printk (KERN_ERR "init_ethernet failed for card #%d\n", - card_idx); + printk (KERN_ERR "init_ethernet failed for card #%d\n", card_idx); goto err_out; } SET_MODULE_OWNER(dev); - if (pci_request_regions(pdev, "via-rhine")) + if (pci_request_regions(pdev, shortname)) goto err_out_free_netdev; #ifndef USE_IO @@ -534,13 +560,50 @@ } #endif - /* Ideally we would read the EEPROM but access may be locked. */ - for (i = 0; i < 6; i++) - dev->dev_addr[i] = readb(ioaddr + StationAddr + i); + /* D-Link provided reset code (with comment additions) */ + if (via_rhine_chip_info[chip_id].drv_flags & HasWOL) { + unsigned char byOrgValue; + + /* clear sticky bit before reset & read ethernet address */ + byOrgValue = readb(ioaddr + StickyHW); + byOrgValue = byOrgValue & 0xFC; + writeb(byOrgValue, ioaddr + StickyHW); + + /* (bits written are cleared?) */ + /* disable force PME-enable */ + writeb(0x80, ioaddr + WOLcgClr); + /* disable power-event config bit */ + writeb(0xFF, ioaddr + WOLcrClr); + /* clear power status (undocumented in vt6102 docs?) */ + writeb(0xFF, ioaddr + PwrcsrClr); + } /* Reset the chip to erase previous misconfiguration. */ writew(CmdReset, ioaddr + ChipCmd); - wait_for_reset(dev); + wait_for_reset(dev, shortname); + + /* Reload the station address from the EEPROM. */ + writeb(0x20, ioaddr + MACRegEEcsr); + /* Typically 2 cycles to reload. */ + for (i = 0; i < 150; i++) + if (! (readb(ioaddr + MACRegEEcsr) & 0x20)) + break; + for (i = 0; i < 6; i++) + dev->dev_addr[i] = readb(ioaddr + StationAddr + i); + + if (!is_valid_ether_addr(dev->dev_addr)) { + printk(KERN_ERR "Invalid MAC address for card #%d\n", card_idx); + goto err_out_unmap; + } + + if (chip_id == VT6102) { + /* + * for 3065D, EEPROM reloaded will cause bit 0 in MAC_REG_CFGA + * turned on. it makes MAC receive magic packet + * automatically. So, we turn it off. (D-Link) + */ + writeb(readb(ioaddr + ConfigA) & 0xFE, ioaddr + ConfigA); + } dev->base_addr = ioaddr; dev->irq = pdev->irq; @@ -563,8 +626,11 @@ if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0) np->full_duplex = 1; - if (np->full_duplex) + if (np->full_duplex) { + printk(KERN_INFO "%s: Set to forced full duplex, autonegotiation" + " disabled.\n", dev->name); np->duplex_lock = 1; + } /* The chip-specific entries in the device structure. */ dev->open = via_rhine_open; @@ -611,6 +677,24 @@ np->mii_cnt = phy_idx; } + /* Allow forcing the media type. */ + if (option > 0) { + if (option & 0x220) + np->full_duplex = 1; + np->default_port = option & 0x3ff; + if (np->default_port & 0x330) { + /* FIXME: shouldn't someone check this variable? */ + /* np->medialock = 1; */ + printk(KERN_INFO " Forcing %dMbs %s-duplex operation.\n", + (option & 0x300 ? 100 : 10), + (option & 0x220 ? "full" : "half")); + if (np->mii_cnt) + mdio_write(dev, np->phys[0], 0, + ((option & 0x300) ? 0x2000 : 0) | /* 100mbps? */ + ((option & 0x220) ? 0x0100 : 0)); /* Full duplex? */ + } + } + return 0; err_out_unmap: @@ -890,7 +974,7 @@ return i; alloc_rbufs(dev); alloc_tbufs(dev); - wait_for_reset(dev); + wait_for_reset(dev, dev->name); init_registers(dev); if (debug > 2) printk(KERN_DEBUG "%s: Done via_rhine_open(), status %4.4x " @@ -997,7 +1081,7 @@ alloc_rbufs(dev); /* Reinitialize the hardware. */ - wait_for_reset(dev); + wait_for_reset(dev, dev->name); init_registers(dev); spin_unlock(&np->lock); @@ -1388,7 +1472,9 @@ memset(mc_filter, 0, sizeof(mc_filter)); for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; i++, mclist = mclist->next) { - set_bit(ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26, mc_filter); + int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; + + mc_filter[bit_nr >> 5] |= cpu_to_le32(1 << (bit_nr & 31)); } writel(mc_filter[0], ioaddr + MulticastFilter0); writel(mc_filter[1], ioaddr + MulticastFilter1); @@ -1400,7 +1486,7 @@ static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct netdev_private *np = dev->priv; - u16 *data = (u16 *)&rq->ifr_data; + struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data; unsigned long flags; int retval; @@ -1408,18 +1494,23 @@ retval = 0; switch(cmd) { - case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ - data[0] = np->phys[0] & 0x1f; + case SIOCGMIIPHY: /* Get address of MII PHY in use. */ + case SIOCDEVPRIVATE: /* for binary compat, remove in 2.5 */ + data->phy_id = np->phys[0] & 0x1f; /* Fall Through */ - case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ - data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f); + + case SIOCGMIIREG: /* Read MII PHY register. */ + case SIOCDEVPRIVATE+1: /* for binary compat, remove in 2.5 */ + data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f); break; - case SIOCDEVPRIVATE+2: /* Write the specified MII register */ + + case SIOCSMIIREG: /* Write MII PHY register. */ + case SIOCDEVPRIVATE+2: /* for binary compat, remove in 2.5 */ if (!capable(CAP_NET_ADMIN)) { retval = -EPERM; break; } - mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]); + mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in); break; default: retval = -EOPNOTSUPP; @@ -1445,7 +1536,7 @@ dev->name, readw(ioaddr + ChipCmd)); /* Switch to loopback mode to avoid hardware races. */ - writeb(np->tx_thresh | 0x01, ioaddr + TxConfig); + writeb(np->tx_thresh | 0x02, ioaddr + TxConfig); /* Disable interrupts by clearing the interrupt mask. */ writew(0x0000, ioaddr + IntrEnable); diff -u --recursive --new-file v2.4.5/linux/drivers/net/wan/comx-hw-mixcom.c linux/drivers/net/wan/comx-hw-mixcom.c --- v2.4.5/linux/drivers/net/wan/comx-hw-mixcom.c Mon Dec 11 13:38:29 2000 +++ linux/drivers/net/wan/comx-hw-mixcom.c Wed Jun 27 17:10:55 2001 @@ -487,15 +487,18 @@ struct mixcom_privdata *hw = ch->HW_privdata; struct proc_dir_entry *procfile = ch->procdir->subdir; unsigned long flags; + int ret = -ENODEV; - if (!dev->base_addr || !dev->irq) return -ENODEV; + if (!dev->base_addr || !dev->irq) + goto err_ret; if(hw->channel==1) { if(!TWIN(dev) || !(COMX_CHANNEL(TWIN(dev))->init_status & IRQ_ALLOCATED)) { printk(KERN_ERR "%s: channel 0 not yet initialized\n",dev->name); - return -EAGAIN; + ret = -EAGAIN; + goto err_ret; } } @@ -503,28 +506,29 @@ /* Is our hw present at all ? Not checking for channel 0 if it is already open */ if(hw->channel!=0 || !(ch->init_status & IRQ_ALLOCATED)) { - if (check_region(dev->base_addr, MIXCOM_IO_EXTENT)) { - return -EAGAIN; + if (!request_region(dev->base_addr, MIXCOM_IO_EXTENT, dev->name)) { + ret = -EAGAIN; + goto err_ret; } if (mixcom_probe(dev)) { - return -ENODEV; + ret = -ENODEV; + goto err_release_region; } } - save_flags(flags); cli(); - - if(hw->channel==1) { - request_region(dev->base_addr, MIXCOM_IO_EXTENT, dev->name); - } - if(hw->channel==0 && !(ch->init_status & IRQ_ALLOCATED)) { if (request_irq(dev->irq, MIXCOM_interrupt, 0, dev->name, (void *)dev)) { printk(KERN_ERR "MIXCOM: unable to obtain irq %d\n", dev->irq); - return -EAGAIN; + ret = -EAGAIN; + goto err_release_region; } + } + + save_flags(flags); cli(); + + if(hw->channel==0 && !(ch->init_status & IRQ_ALLOCATED)) { ch->init_status|=IRQ_ALLOCATED; - request_region(dev->base_addr, MIXCOM_IO_EXTENT, dev->name); mixcom_board_on(dev); } @@ -560,6 +564,13 @@ } return 0; + +err_restore_flags: + restore_flags(flags); +err_release_region: + release_region(dev->base_addr, MIXCOM_IO_EXTENT); +err_ret: + return ret; } static int MIXCOM_close(struct net_device *dev) diff -u --recursive --new-file v2.4.5/linux/drivers/net/wan/comx-proto-fr.c linux/drivers/net/wan/comx-proto-fr.c --- v2.4.5/linux/drivers/net/wan/comx-proto-fr.c Sat Mar 3 10:55:48 2001 +++ linux/drivers/net/wan/comx-proto-fr.c Wed Jun 27 17:10:55 2001 @@ -503,6 +503,8 @@ if (dev != fr->master) { struct sk_buff *newskb=skb_clone(skb, GFP_ATOMIC); + if (!newskb) + return -ENOMEM; newskb->dev=fr->master; dev_queue_xmit(newskb); ch->stats.tx_bytes += skb->len; @@ -701,7 +703,7 @@ } else { printk(KERN_ERR "comxfr_write_proc: internal error, filename %s\n", entry->name); - return -EBADF; + count = -EBADF; } free_page((unsigned long)page); @@ -960,30 +962,27 @@ } static struct comx_protocol fr_master_protocol = { - "frad", - VERSION, - ARPHRD_FRAD, - fr_master_init, - fr_exit, - NULL + name: "frad", + version: VERSION, + encap_type: ARPHRD_FRAD, + line_init: fr_master_init, + line_exit: fr_exit, }; static struct comx_protocol fr_slave_protocol = { - "ietf-ip", - VERSION, - ARPHRD_DLCI, - fr_slave_init, - fr_exit, - NULL + name: "ietf-ip", + version: VERSION, + encap_type: ARPHRD_DLCI, + line_init: fr_slave_init, + line_exit: fr_exit, }; static struct comx_hardware fr_dlci = { - "dlci", - VERSION, - dlci_init, - dlci_exit, - dlci_dump, - NULL + name: "dlci", + version: VERSION, + hw_init: dlci_init, + hw_exit: dlci_exit, + hw_dump: dlci_dump, }; #ifdef MODULE diff -u --recursive --new-file v2.4.5/linux/drivers/net/wan/cosa.c linux/drivers/net/wan/cosa.c --- v2.4.5/linux/drivers/net/wan/cosa.c Tue Mar 6 19:44:36 2001 +++ linux/drivers/net/wan/cosa.c Wed Jun 27 17:10:55 2001 @@ -1046,15 +1046,15 @@ __get_user(code, &(d->code))) return -EFAULT; - if (d->addr < 0 || d->addr > COSA_MAX_FIRMWARE_SIZE) + if (addr < 0 || addr > COSA_MAX_FIRMWARE_SIZE) return -EINVAL; - if (d->len < 0 || d->len > COSA_MAX_FIRMWARE_SIZE) + if (len < 0 || len > COSA_MAX_FIRMWARE_SIZE) return -EINVAL; /* If something fails, force the user to reset the card */ cosa->firmware_status &= ~(COSA_FW_RESET|COSA_FW_DOWNLOAD); - if ((i=download(cosa, d->code, len, addr)) < 0) { + if ((i=download(cosa, code, len, addr)) < 0) { printk(KERN_NOTICE "cosa%d: microcode download failed: %d\n", cosa->num, i); return -EIO; diff -u --recursive --new-file v2.4.5/linux/drivers/net/wan/hdlc.c linux/drivers/net/wan/hdlc.c --- v2.4.5/linux/drivers/net/wan/hdlc.c Wed Apr 18 14:40:07 2001 +++ linux/drivers/net/wan/hdlc.c Tue Jun 12 11:06:54 2001 @@ -1082,7 +1082,9 @@ } break; - default: /* to be defined */ + default: + /* to be defined */ + break; } dev_kfree_skb(skb); diff -u --recursive --new-file v2.4.5/linux/drivers/net/wan/lapbether.c linux/drivers/net/wan/lapbether.c --- v2.4.5/linux/drivers/net/wan/lapbether.c Wed Apr 18 14:40:07 2001 +++ linux/drivers/net/wan/lapbether.c Wed Jun 27 17:10:55 2001 @@ -89,7 +89,7 @@ */ static int lapbeth_check_devices(struct net_device *dev) { - struct lapbethdev *lapbeth, *lapbeth_prev; + struct lapbethdev *lapbeth, *lapbeth_prev, *lapbeth_next; int result = 0; unsigned long flags; @@ -98,7 +98,8 @@ lapbeth_prev = NULL; - for (lapbeth = lapbeth_devices; lapbeth != NULL; lapbeth = lapbeth->next) { + for (lapbeth = lapbeth_devices; lapbeth != NULL; lapbeth = lapbeth_next) { + lapbeth_next = lapbeth->next; if (!dev_get(lapbeth->ethname)) { if (lapbeth_prev) lapbeth_prev->next = lapbeth->next; @@ -112,8 +113,8 @@ dev_put(lapbeth->ethdev); kfree(lapbeth); } - - lapbeth_prev = lapbeth; + else + lapbeth_prev = lapbeth; } restore_flags(flags); diff -u --recursive --new-file v2.4.5/linux/drivers/net/wan/lmc/lmc_main.c linux/drivers/net/wan/lmc/lmc_main.c --- v2.4.5/linux/drivers/net/wan/lmc/lmc_main.c Sun Mar 25 18:24:31 2001 +++ linux/drivers/net/wan/lmc/lmc_main.c Wed Jun 27 17:10:55 2001 @@ -507,7 +507,12 @@ break; } - LMC_COPY_FROM_USER(data, xc.data, xc.len); + if(copy_from_user(data, xc.data, xc.len)) + { + kfree(data); + ret = -ENOMEM; + break; + } printk("%s: Starting load of data Len: %d at 0x%p == 0x%p\n", dev->name, xc.len, xc.data, data); diff -u --recursive --new-file v2.4.5/linux/drivers/net/wan/sdla_fr.c linux/drivers/net/wan/sdla_fr.c --- v2.4.5/linux/drivers/net/wan/sdla_fr.c Fri Apr 20 11:54:22 2001 +++ linux/drivers/net/wan/sdla_fr.c Tue Jun 12 11:06:54 2001 @@ -4435,7 +4435,8 @@ trigger_fr_poll(dev); break; - default: // ARP's and RARP's -- Shouldn't happen. + default: + break; // ARP's and RARP's -- Shouldn't happen. } return 0; diff -u --recursive --new-file v2.4.5/linux/drivers/net/wan/sdla_x25.c linux/drivers/net/wan/sdla_x25.c --- v2.4.5/linux/drivers/net/wan/sdla_x25.c Fri Apr 20 11:54:22 2001 +++ linux/drivers/net/wan/sdla_x25.c Tue Jun 12 11:06:54 2001 @@ -3108,7 +3108,7 @@ case 0x08: /* modem failure */ #ifndef MODEM_NOT_LOG printk(KERN_INFO "%s: modem failure!\n", card->devname); -#endif MODEM_NOT_LOG +#endif /* MODEM_NOT_LOG */ api_oob_event(card,mb); break; diff -u --recursive --new-file v2.4.5/linux/drivers/net/wan/syncppp.c linux/drivers/net/wan/syncppp.c --- v2.4.5/linux/drivers/net/wan/syncppp.c Tue May 22 10:23:16 2001 +++ linux/drivers/net/wan/syncppp.c Wed Jun 27 17:10:55 2001 @@ -147,7 +147,7 @@ static char *sppp_ipcp_type_name (u8 type); static void sppp_print_bytes (u8 *p, u16 len); -static int debug = 0; +static int debug; /* @@ -518,8 +518,10 @@ } /* Send Configure-Ack packet. */ sp->pp_loopcnt = 0; - sppp_cp_send (sp, PPP_LCP, LCP_CONF_ACK, - h->ident, len-4, h+1); + if (sp->lcp.state != LCP_STATE_OPENED) { + sppp_cp_send (sp, PPP_LCP, LCP_CONF_ACK, + h->ident, len-4, h+1); + } /* Change the state. */ switch (sp->lcp.state) { case LCP_STATE_CLOSED: @@ -535,7 +537,9 @@ sp->ipcp.state = IPCP_STATE_CLOSED; /* Initiate renegotiation. */ sppp_lcp_open (sp); - /* An ACK has already been sent. */ + /* Send ACK after our REQ in attempt to break loop */ + sppp_cp_send (sp, PPP_LCP, LCP_CONF_ACK, + h->ident, len-4, h+1); sp->lcp.state = LCP_STATE_ACK_SENT; break; } @@ -1388,25 +1392,21 @@ return 0; } - -struct packet_type sppp_packet_type= -{ - 0, - NULL, - sppp_rcv, - NULL, - NULL +struct packet_type sppp_packet_type = { + type: __constant_htons(ETH_P_WAN_PPP), + func: sppp_rcv, }; - +static const char banner[] __initdata = + KERN_INFO "Cronyx Ltd, Synchronous PPP and CISCO HDLC (c) 1994\n" + KERN_INFO "Linux port (c) 1998 Building Number Three Ltd & " + "Jan \"Yenya\" Kasprzak.\n"; static int __init sync_ppp_init(void) { if(debug) debug=PP_DEBUG; - printk(KERN_INFO "Cronyx Ltd, Synchronous PPP and CISCO HDLC (c) 1994\n"); - printk(KERN_INFO "Linux port (c) 1998 Building Number Three Ltd & Jan \"Yenya\" Kasprzak.\n"); - sppp_packet_type.type=htons(ETH_P_WAN_PPP); + printk(banner); dev_add_pack(&sppp_packet_type); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/net/wavelan.p.h linux/drivers/net/wavelan.p.h --- v2.4.5/linux/drivers/net/wavelan.p.h Tue Mar 6 19:28:34 2001 +++ linux/drivers/net/wavelan.p.h Mon Jul 2 14:03:04 2001 @@ -699,12 +699,15 @@ #ifdef MODULE /* Parameters set by insmod */ -static int io[4] = { 0, 0, 0, 0 }; -static int irq[4] = { 0, 0, 0, 0 }; -static char name[4][IFNAMSIZ] = { "", "", "", "" }; +static int io[4]; +static int irq[4]; +static char name[4][IFNAMSIZ]; MODULE_PARM(io, "1-4i"); MODULE_PARM(irq, "1-4i"); MODULE_PARM(name, "1-4c" __MODULE_STRING(IFNAMSIZ)); +MODULE_PARM_DESC(io, "WaveLAN I/O base address(es),required"); +MODULE_PARM_DESC(irq, "WaveLAN IRQ number(s)"); +MODULE_PARM_DESC(name, "WaveLAN interface neme(s)"); #endif /* MODULE */ #endif /* WAVELAN_P_H */ diff -u --recursive --new-file v2.4.5/linux/drivers/net/wd.c linux/drivers/net/wd.c --- v2.4.5/linux/drivers/net/wd.c Thu Apr 19 09:34:52 2001 +++ linux/drivers/net/wd.c Wed Jun 20 11:10:53 2001 @@ -449,6 +449,10 @@ MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_WD_CARDS) "i"); MODULE_PARM(mem, "1-" __MODULE_STRING(MAX_WD_CARDS) "i"); MODULE_PARM(mem_end, "1-" __MODULE_STRING(MAX_WD_CARDS) "i"); +MODULE_PARM_DESC(io, "WD80x3 I/O base address(es)"); +MODULE_PARM_DESC(irq, "WD80x3 IRQ number(s) (ignored for PureData boards)"); +MODULE_PARM_DESC(mem, "WD80x3 memory base address(es)(ignored for PureData boards)"); +MODULE_PARM_DESC(mem_end, "WD80x3 memory end address(es)"); /* This is set up so that only a single autoprobe takes place per call. ISA device autoprobes on a running machine are not recommended. */ diff -u --recursive --new-file v2.4.5/linux/drivers/net/winbond-840.c linux/drivers/net/winbond-840.c --- v2.4.5/linux/drivers/net/winbond-840.c Fri Apr 20 11:54:23 2001 +++ linux/drivers/net/winbond-840.c Mon Jul 2 14:03:04 2001 @@ -1,4 +1,4 @@ -/* winbond-840.c: A Linux PCI network adapter skeleton device driver. */ +/* winbond-840.c: A Linux PCI network adapter device driver. */ /* Written 1998-2001 by Donald Becker. @@ -38,6 +38,11 @@ descriptors. Remove cpu_to_le32, enable BE descriptors. */ +#define DRV_NAME "winbond-840" +#define DRV_VERSION "1.01" +#define DRV_RELDATE "5/15/2000" + + /* Automatically extracted configuration info: probe-func: winbond840_probe config-in: tristate 'Winbond W89c840 Ethernet support' CONFIG_WINBOND_840 @@ -122,13 +127,16 @@ #include #include #include +#include +#include +#include #include /* Processor type for cache alignment. */ #include #include /* These identify the driver base version and may not be removed. */ static char version[] __devinitdata = -KERN_INFO "winbond-840.c:v1.01 (2.4 port) 5/15/2000 Donald Becker \n" +KERN_INFO DRV_NAME ".c:v" DRV_VERSION " (2.4 port) " DRV_RELDATE " Donald Becker \n" KERN_INFO " http://www.scyld.com/network/drivers.html\n"; MODULE_AUTHOR("Donald Becker "); @@ -139,6 +147,12 @@ MODULE_PARM(multicast_filter_limit, "i"); MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); +MODULE_PARM_DESC(max_interrupt_work, "winbond-840 maximum events handled per interrupt"); +MODULE_PARM_DESC(debug, "winbond-840 debug level (0-6)"); +MODULE_PARM_DESC(rx_copybreak, "winbond-840 copy breakpoint for copy-only-tiny-frames"); +MODULE_PARM_DESC(multicast_filter_limit, "winbond-840 maximum number of filtered multicast addresses"); +MODULE_PARM_DESC(options, "winbond-840: Bits 0-3: media type, bit 17: full duplex"); +MODULE_PARM_DESC(full_duplex, "winbond-840 full duplex setting(s) (1)"); /* Theory of Operation @@ -366,7 +380,7 @@ static inline unsigned ether_crc(int length, unsigned char *data); static void set_rx_mode(struct net_device *dev); static struct net_device_stats *get_stats(struct net_device *dev); -static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); +static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static int netdev_close(struct net_device *dev); @@ -399,7 +413,7 @@ return -ENOMEM; SET_MODULE_OWNER(dev); - if (pci_request_regions(pdev, "winbond-840")) + if (pci_request_regions(pdev, DRV_NAME)) goto err_out_netdev; #ifdef USE_IO_OPS @@ -453,7 +467,7 @@ dev->stop = &netdev_close; dev->get_stats = &get_stats; dev->set_multicast_list = &set_rx_mode; - dev->do_ioctl = &mii_ioctl; + dev->do_ioctl = &netdev_ioctl; dev->tx_timeout = &tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; @@ -826,7 +840,7 @@ C000 32 longwords 0400 4 longwords Wait the specified 50 PCI cycles after a reset by initializing Tx and Rx queues and the address filter list. */ -#if defined(__powerpc__) /* Big-endian */ +#if defined(__powerpc__) || defined(__sparc__) /* Big-endian */ writel(0x00100080 | 0xE010, ioaddr + PCIBusCfg); #elif defined(__alpha__) writel(0xE010, ioaddr + PCIBusCfg); @@ -871,13 +885,12 @@ printk(KERN_WARNING "%s: Transmit timed out, status %8.8x," " resetting...\n", dev->name, (int)readl(ioaddr + IntrStatus)); -#ifndef __alpha__ { int i; - printk(KERN_DEBUG " Rx ring %8.8x: ", (int)np->rx_ring); + printk(KERN_DEBUG " Rx ring %p: ", np->rx_ring); for (i = 0; i < RX_RING_SIZE; i++) printk(" %8.8x", (unsigned int)np->rx_ring[i].status); - printk("\n"KERN_DEBUG" Tx ring %8.8x: ", (int)np->tx_ring); + printk("\n"KERN_DEBUG" Tx ring %p: ", np->tx_ring); for (i = 0; i < TX_RING_SIZE; i++) printk(" %8.8x", np->tx_ring[i].status); printk("\n"); @@ -886,7 +899,6 @@ np->cur_tx, np->dirty_tx, np->tx_full,np->tx_q_bytes); printk(KERN_DEBUG "Tx Descriptor addr %xh.\n",readl(ioaddr+0x4C)); -#endif spin_lock_irq(&np->lock); /* * Under high load dirty_tx and the internal tx descriptor pointer @@ -1312,21 +1324,52 @@ writel(np->csr6, ioaddr + NetworkConfig); } -static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr) +{ + struct netdev_private *np = dev->priv; + u32 ethcmd; + + if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) + return -EFAULT; + + switch (ethcmd) { + case ETHTOOL_GDRVINFO: { + struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; + strcpy(info.driver, DRV_NAME); + strcpy(info.version, DRV_VERSION); + strcpy(info.bus_info, np->pci_dev->slot_name); + if (copy_to_user(useraddr, &info, sizeof(info))) + return -EFAULT; + return 0; + } + + } + + return -EOPNOTSUPP; +} + +static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - u16 *data = (u16 *)&rq->ifr_data; + struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data; switch(cmd) { - case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ - data[0] = ((struct netdev_private *)dev->priv)->phys[0] & 0x1f; + case SIOCETHTOOL: + return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); + case SIOCGMIIPHY: /* Get address of MII PHY in use. */ + case SIOCDEVPRIVATE: /* for binary compat, remove in 2.5 */ + data->phy_id = ((struct netdev_private *)dev->priv)->phys[0] & 0x1f; /* Fall Through */ - case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ - data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f); + + case SIOCGMIIREG: /* Read MII PHY register. */ + case SIOCDEVPRIVATE+1: /* for binary compat, remove in 2.5 */ + data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f); return 0; - case SIOCDEVPRIVATE+2: /* Write the specified MII register */ + + case SIOCSMIIREG: /* Write MII PHY register. */ + case SIOCDEVPRIVATE+2: /* for binary compat, remove in 2.5 */ if (!capable(CAP_NET_ADMIN)) return -EPERM; - mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]); + mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in); return 0; default: return -EOPNOTSUPP; @@ -1337,7 +1380,6 @@ { long ioaddr = dev->base_addr; struct netdev_private *np = dev->priv; - int i; netif_stop_queue(dev); @@ -1360,6 +1402,8 @@ #ifdef __i386__ if (debug > 2) { + int i; + printk("\n"KERN_DEBUG" Tx ring at %8.8x:\n", (int)np->tx_ring); for (i = 0; i < TX_RING_SIZE; i++) @@ -1403,7 +1447,7 @@ } static struct pci_driver w840_driver = { - name: "winbond-840", + name: DRV_NAME, id_table: w840_pci_tbl, probe: w840_probe1, remove: w840_remove1, diff -u --recursive --new-file v2.4.5/linux/drivers/net/wireless/Config.in linux/drivers/net/wireless/Config.in --- v2.4.5/linux/drivers/net/wireless/Config.in Mon May 7 19:42:14 2001 +++ linux/drivers/net/wireless/Config.in Wed Jun 20 11:13:18 2001 @@ -2,21 +2,26 @@ # Wireless LAN device configuration # -###tristate ' Hermes chipset support' CONFIG_NET_ORINOCO -###dep_tristate ' PCMCIA Hermes support (Orinoco/WavelanIEEE/PrismII/Symbol 802.11b cards)' CONFIG_PCMCIA_HERMES $CONFIG_NET_ORINOCO $CONFIG_PCMCIA +if [ "$CONFIG_ISA" = "y" -o "$CONFIG_PCI" = "y" ]; then + tristate ' Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards' CONFIG_AIRO +fi if [ "$CONFIG_ALL_PPC" = "y" ]; then tristate ' Apple Airport support (built-in)' CONFIG_APPLE_AIRPORT fi # If Pcmcia is compiled in, offer Pcmcia cards... -if [ "$CONFIG_HOTPLUG" = "y" -a "$CONFIG_PCMCIA" != "n" ]; then +if [ "$CONFIG_PCMCIA" != "n" ]; then comment 'Wireless Pcmcia cards support' - dep_tristate ' Hermes support (Orinoco/WavelanIEEE/PrismII/Symbol 802.11b cards)' CONFIG_PCMCIA_HERMES $CONFIG_PCMCIA + tristate ' Hermes support (Orinoco/WavelanIEEE/PrismII/Symbol 802.11b cards)' CONFIG_PCMCIA_HERMES + tristate ' Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards' CONFIG_AIRO_CS +fi -# If one of the Pcmcia cards above is enabled, activate Pcmcia network support - if [ "$CONFIG_PCMCIA_HERMES" = "y" ]; then - define_bool CONFIG_PCMCIA_NETCARD y - fi +# yes, this works even when no drivers are selected +if [ "$CONFIG_ISA" = "y" -o "$CONFIG_PCI" = "y" -o \ + "$CONFIG_ALL_PPC" = "y" -o "$CONFIG_PCMCIA" != "n" ]; then + define_bool CONFIG_NET_WIRELESS y +else + define_bool CONFIG_NET_WIRELESS n fi diff -u --recursive --new-file v2.4.5/linux/drivers/net/wireless/Makefile linux/drivers/net/wireless/Makefile --- v2.4.5/linux/drivers/net/wireless/Makefile Mon May 7 19:42:14 2001 +++ linux/drivers/net/wireless/Makefile Wed Jun 20 11:13:18 2001 @@ -4,7 +4,7 @@ # Makefile for the Linux Wireless network device drivers. # -O_TARGET := orinoco_drvs.o +O_TARGET := wireless_net.o obj-y := obj-m := @@ -12,16 +12,12 @@ obj- := # Things that need to export symbols -export-objs := orinoco.o hermes.o +export-objs := airo.o orinoco.o hermes.o -# ISA Bus cards - -# PCI bus cards - -# Other cards +obj-$(CONFIG_PCMCIA_HERMES) += orinoco_cs.o orinoco.o hermes.o obj-$(CONFIG_APPLE_AIRPORT) += airport.o orinoco.o hermes.o -# 16-bit Pcmcia wireless client drivers -obj-$(CONFIG_PCMCIA_HERMES) += orinoco_cs.o orinoco.o hermes.o +obj-$(CONFIG_AIRO) += airo.o +obj-$(CONFIG_AIRO_CS) += airo_cs.o airo.o include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.5/linux/drivers/net/wireless/airo.c linux/drivers/net/wireless/airo.c --- v2.4.5/linux/drivers/net/wireless/airo.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/wireless/airo.c Mon Jul 2 14:03:04 2001 @@ -0,0 +1,4316 @@ +/*====================================================================== + + Aironet driver for 4500 and 4800 series cards + + This code is released under both the GPL version 2 and BSD licenses. + Either license may be used. The respective licenses are found at + the end of this file. + + This code was developed by Benjamin Reed + including portions of which come from the Aironet PC4500 + Developer's Reference Manual and used with permission. Copyright + (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. + +======================================================================*/ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_PCI +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, }, + { 0x14b9, 0x0340, PCI_ANY_ID, PCI_ANY_ID, }, + { 0x14b9, 0x0350, PCI_ANY_ID, PCI_ANY_ID, }, + { 0, } +}; +MODULE_DEVICE_TABLE(pci, card_ids); + +static int airo_pci_probe(struct pci_dev *, const struct pci_device_id *); +static void airo_pci_remove(struct pci_dev *); + +static struct pci_driver airo_driver = { + name: "airo", + id_table: card_ids, + probe: airo_pci_probe, + remove: airo_pci_remove, +}; +#endif /* CONFIG_PCI */ + +/* Include Wireless Extension definition and check version - Jean II */ +#include +#if WIRELESS_EXT < 9 +#warning "Wireless extension v9 or newer required - please upgrade your kernel" +#undef WIRELESS_EXT +#endif +#define WIRELESS_SPY // enable iwspy support +#define CISCO_EXT // enable Cisco extensions + +#ifdef CISCO_EXT +#include +#endif + +/* As you can see this list is HUGH! + I really don't know what a lot of these counts are about, but they + are all here for completeness. If the IGNLABEL macro is put in + infront of the label, that statistic will not be included in the list + of statistics in the /proc filesystem */ + +#define IGNLABEL 0&(int) +static char *statsLabels[] = { + "RxOverrun", + IGNLABEL "RxPlcpCrcErr", + IGNLABEL "RxPlcpFormatErr", + IGNLABEL "RxPlcpLengthErr", + "RxMacCrcErr", + "RxMacCrcOk", + "RxWepErr", + "RxWepOk", + "RetryLong", + "RetryShort", + "MaxRetries", + "NoAck", + "NoCts", + "RxAck", + "RxCts", + "TxAck", + "TxRts", + "TxCts", + "TxMc", + "TxBc", + "TxUcFrags", + "TxUcPackets", + "TxBeacon", + "RxBeacon", + "TxSinColl", + "TxMulColl", + "DefersNo", + "DefersProt", + "DefersEngy", + "DupFram", + "RxFragDisc", + "TxAged", + "RxAged", + "LostSync-MaxRetry", + "LostSync-MissedBeacons", + "LostSync-ArlExceeded", + "LostSync-Deauth", + "LostSync-Disassoced", + "LostSync-TsfTiming", + "HostTxMc", + "HostTxBc", + "HostTxUc", + "HostTxFail", + "HostRxMc", + "HostRxBc", + "HostRxUc", + "HostRxDiscard", + IGNLABEL "HmacTxMc", + IGNLABEL "HmacTxBc", + IGNLABEL "HmacTxUc", + IGNLABEL "HmacTxFail", + IGNLABEL "HmacRxMc", + IGNLABEL "HmacRxBc", + IGNLABEL "HmacRxUc", + IGNLABEL "HmacRxDiscard", + IGNLABEL "HmacRxAccepted", + "SsidMismatch", + "ApMismatch", + "RatesMismatch", + "AuthReject", + "AuthTimeout", + "AssocReject", + "AssocTimeout", + IGNLABEL "ReasonOutsideTable", + IGNLABEL "ReasonStatus1", + IGNLABEL "ReasonStatus2", + IGNLABEL "ReasonStatus3", + IGNLABEL "ReasonStatus4", + IGNLABEL "ReasonStatus5", + IGNLABEL "ReasonStatus6", + IGNLABEL "ReasonStatus7", + IGNLABEL "ReasonStatus8", + IGNLABEL "ReasonStatus9", + IGNLABEL "ReasonStatus10", + IGNLABEL "ReasonStatus11", + IGNLABEL "ReasonStatus12", + IGNLABEL "ReasonStatus13", + IGNLABEL "ReasonStatus14", + IGNLABEL "ReasonStatus15", + IGNLABEL "ReasonStatus16", + IGNLABEL "ReasonStatus17", + IGNLABEL "ReasonStatus18", + IGNLABEL "ReasonStatus19", + "RxMan", + "TxMan", + "RxRefresh", + "TxRefresh", + "RxPoll", + "TxPoll", + "HostRetries", + "LostSync-HostReq", + "HostTxBytes", + "HostRxBytes", + "ElapsedUsec", + "ElapsedSec", + "LostSyncBetterAP", + "PrivacyMismatch", + "Jammed", + "DiscRxNotWepped", + "PhyEleMismatch", + (char*)-1 }; +#ifndef RUN_AT +#define RUN_AT(x) (jiffies+(x)) +#endif + + +/* These variables are for insmod, since it seems that the rates + can only be set in setup_card. Rates should be a comma separated + (no spaces) list of rates (up to 8). */ + +static int rates[8]; +static int basic_rate; +static char *ssids[3]; + +static int io[4]; +static int irq[4]; + +static +int maxencrypt /* = 0 */; /* The highest rate that the card can encrypt at. + 0 means no limit. For old cards this was 4 */ + +static int auto_wep /* = 0 */; /* If set, it tries to figure out the wep mode */ +static int aux_bap /* = 0 */; /* Checks to see if the aux ports are needed to read + the bap, needed on some older cards and buses. */ +static int adhoc; + +static int proc_uid /* = 0 */; + +static int proc_gid /* = 0 */; + +static int airo_perm = 0555; + +static int proc_perm = 0644; + +MODULE_AUTHOR("Benjamin Reed"); +MODULE_DESCRIPTION("Support for Cisco/Aironet 802.11 wireless ethernet \ + cards. Direct support for ISA/PCI cards and support \ + for PCMCIA when used with airo_cs."); +MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340"); +MODULE_PARM(io,"1-4i"); +MODULE_PARM(irq,"1-4i"); +MODULE_PARM(basic_rate,"i"); +MODULE_PARM(rates,"1-8i"); +MODULE_PARM(ssids,"1-3s"); +MODULE_PARM(auto_wep,"i"); +MODULE_PARM_DESC(auto_wep, "If non-zero, the driver will keep looping through \ +the authentication options until an association is made. The value of \ +auto_wep is number of the wep keys to check. A value of 2 will try using \ +the key at index 0 and index 1."); +MODULE_PARM(aux_bap,"i"); +MODULE_PARM_DESC(aux_bap, "If non-zero, the driver will switch into a mode \ +than seems to work better for older cards with some older buses. Before \ +switching it checks that the switch is needed."); +MODULE_PARM(maxencrypt, "i"); +MODULE_PARM_DESC(maxencrypt, "The maximum speed that the card can do \ +encryption. Units are in 512kbs. Zero (default) means there is no limit. \ +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(proc_uid, "i"); +MODULE_PARM_DESC(proc_uid, "The uid that the /proc files will belong to."); +MODULE_PARM(proc_gid, "i"); +MODULE_PARM_DESC(proc_gid, "The gid that the /proc files will belong to."); +MODULE_PARM(airo_perm, "i"); +MODULE_PARM_DESC(airo_perm, "The permission bits of /proc/[driver/]aironet."); +MODULE_PARM(proc_perm, "i"); +MODULE_PARM_DESC(proc_perm, "The permission bits of the files in /proc"); + +#include + +#define min(x,y) ((xbap_read(ai, pu16Dst, bytelen, whichbap); +} + +static int setup_proc_entry( struct net_device *dev, + struct airo_info *apriv ); +static int takedown_proc_entry( struct net_device *dev, + struct airo_info *apriv ); + +static int readWepKeyRid(struct airo_info*ai, WepKeyRid *wkr, int temp) { + int rc = PC4500_readrid(ai, temp ? RID_WEP_TEMP : RID_WEP_PERM, + wkr, sizeof(*wkr)); + + wkr->len = le16_to_cpu(wkr->len); + wkr->kindex = le16_to_cpu(wkr->kindex); + wkr->klen = le16_to_cpu(wkr->klen); + return rc; +} +/* In the writeXXXRid routines we copy the rids so that we don't screwup + * the originals when we endian them... */ +static int writeWepKeyRid(struct airo_info*ai, WepKeyRid *pwkr, int perm) { + int rc; + WepKeyRid wkr = *pwkr; + + 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)); + 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)); + if (rc!=SUCCESS) { + printk(KERN_ERR "airo: WEP_PERM set %x\n", rc); + } + } + return rc; +} + +static int readSsidRid(struct airo_info*ai, SsidRid *ssidr) { + int i; + int rc = PC4500_readrid(ai, RID_SSID, ssidr, sizeof(*ssidr)); + + ssidr->len = le16_to_cpu(ssidr->len); + for(i = 0; i < 3; i++) { + ssidr->ssids[i].len = le16_to_cpu(ssidr->ssids[i].len); + } + return rc; +} +static int writeSsidRid(struct airo_info*ai, SsidRid *pssidr) { + int rc; + int i; + SsidRid ssidr = *pssidr; + + ssidr.len = cpu_to_le16(ssidr.len); + 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)); + return rc; +} +static int readConfigRid(struct airo_info*ai, ConfigRid *cfgr) { + int rc = PC4500_readrid(ai, RID_ACTUALCONFIG, cfgr, sizeof(*cfgr)); + u16 *s; + + for(s = &cfgr->len; s <= &cfgr->rtsThres; s++) *s = le16_to_cpu(*s); + + for(s = &cfgr->shortRetryLimit; s <= &cfgr->radioType; s++) + *s = le16_to_cpu(*s); + + for(s = &cfgr->txPower; s <= &cfgr->radioSpecific; s++) + *s = le16_to_cpu(*s); + + for(s = &cfgr->arlThreshold; s <= &cfgr->autoWake; s++) + *s = le16_to_cpu(*s); + + return rc; +} +static int writeConfigRid(struct airo_info*ai, ConfigRid *pcfgr) { + u16 *s; + ConfigRid cfgr = *pcfgr; + + for(s = &cfgr.len; s <= &cfgr.rtsThres; s++) *s = cpu_to_le16(*s); + + for(s = &cfgr.shortRetryLimit; s <= &cfgr.radioType; s++) + *s = cpu_to_le16(*s); + + for(s = &cfgr.txPower; s <= &cfgr.radioSpecific; s++) + *s = cpu_to_le16(*s); + + for(s = &cfgr.arlThreshold; s <= &cfgr.autoWake; s++) + *s = cpu_to_le16(*s); + + return do_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)); + u16 *s; + + statr->len = le16_to_cpu(statr->len); + for(s = &statr->mode; s <= &statr->SSIDlen; s++) *s = le16_to_cpu(*s); + + for(s = &statr->beaconPeriod; s <= &statr->_reserved[9]; s++) + *s = le16_to_cpu(*s); + + return rc; +} +static int readAPListRid(struct airo_info*ai, APListRid *aplr) { + int rc = PC4500_readrid(ai, RID_APLIST, aplr, sizeof(*aplr)); + aplr->len = le16_to_cpu(aplr->len); + return rc; +} +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)); + return rc; +} +static int readCapabilityRid(struct airo_info*ai, CapabilityRid *capr) { + int rc = PC4500_readrid(ai, RID_CAPABILITIES, capr, sizeof(*capr)); + u16 *s; + + capr->len = le16_to_cpu(capr->len); + capr->prodNum = le16_to_cpu(capr->prodNum); + capr->radioType = le16_to_cpu(capr->radioType); + capr->country = le16_to_cpu(capr->country); + for(s = &capr->txPowerLevels[0]; s <= &capr->requiredHard; s++) + *s = le16_to_cpu(*s); + return rc; +} +static int readStatsRid(struct airo_info*ai, StatsRid *sr, int rid) { + int rc = PC4500_readrid(ai, rid, sr, sizeof(*sr)); + u32 *i; + + sr->len = le16_to_cpu(sr->len); + for(i = &sr->vals[0]; i <= &sr->vals[99]; i++) *i = le32_to_cpu(*i); + return rc; +} + +static int airo_open(struct net_device *dev) { + struct airo_info *info = dev->priv; + + enable_interrupts(info); + + netif_start_queue(dev); + return 0; +} + +static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) { + s16 len; + s16 retval = 0; + u16 status; + u32 flags; + s8 *buffer; + int i,j; + struct airo_info *priv = (struct airo_info*)dev->priv; + u32 *fids = priv->fids; + + if ( skb == NULL ) { + printk( KERN_ERR "airo: skb == NULL!!!\n" ); + return 0; + } + + /* Find a vacant FID */ + spin_lock_irqsave(&priv->bap1_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 ) { + retval = -EBUSY; + goto tx_done; + } + + len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; /* check min length*/ + buffer = skb->data; + + status = transmit_802_3_packet( priv, + fids[i], + skb->data, len ); + + if ( status == SUCCESS ) { + /* Mark fid as used & save length for later */ + fids[i] |= (len << 16); + dev->trans_start = jiffies; + } else { + priv->stats.tx_errors++; + } + tx_done: + spin_unlock_irqrestore(&priv->bap1_lock, flags); + dev_kfree_skb(skb); + return 0; +} + +static struct net_device_stats *airo_get_stats(struct net_device *dev) { + return &(((struct airo_info*)dev->priv)->stats); +} + +static int enable_MAC( struct airo_info *ai, Resp *rsp ); +static void disable_MAC(struct airo_info *ai); + +static void airo_set_multicast_list(struct net_device *dev) { + struct airo_info *ai = (struct airo_info*)dev->priv; + Cmd cmd; + Resp rsp; + + memset(&cmd, 0, sizeof(cmd)); + cmd.cmd=CMD_SETMODE; + cmd.parm0=(dev->flags&IFF_PROMISC) ? PROMISC : NOPROMISC; + issuecommand(ai, &cmd, &rsp); + + if ((dev->flags&IFF_ALLMULTI)||dev->mc_count>0) { + /* Turn on multicast. (Should be already setup...) */ + } +} + +static int airo_set_mac_address(struct net_device *dev, void *p) +{ + struct airo_info *ai = (struct airo_info*)dev->priv; + struct sockaddr *addr = p; + ConfigRid cfg; + + 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); + return 0; +} + +static int airo_change_mtu(struct net_device *dev, int new_mtu) +{ + if ((new_mtu < 68) || (new_mtu > 2400)) + return -EINVAL; + dev->mtu = new_mtu; + return 0; +} + + +static int airo_close(struct net_device *dev) { + struct airo_info *ai = (struct airo_info*)dev->priv; + + netif_stop_queue(dev); + disable_interrupts( ai ); + return 0; +} + +static void del_airo_dev( struct net_device *dev ); + +void stop_airo_card( struct net_device *dev, int freeres ) +{ + struct airo_info *ai = (struct airo_info*)dev->priv; + takedown_proc_entry( dev, ai ); + if (ai->registered) { + unregister_netdev( dev ); + ai->registered = 0; + } + disable_interrupts(ai); + free_irq( dev->irq, dev ); + if (auto_wep) del_timer_sync(&ai->timer); + if (freeres) { + /* PCMCIA frees this stuff, so only for PCI and ISA */ + release_region( dev->base_addr, 64 ); + } + del_airo_dev( dev ); + kfree( dev ); +} + +static int add_airo_dev( struct net_device *dev ); + +struct net_device *init_airo_card( unsigned short irq, int port, int is_pcmcia ) +{ + struct net_device *dev; + struct airo_info *ai; + int i, rc; + + /* Create the network device object. */ + dev = alloc_etherdev(sizeof(*ai)); + if (!dev) { + printk(KERN_ERR "airo: Couldn't alloc_etherdev\n"); + return NULL; + } + ai = dev->priv; + ai->registered = 1; + ai->dev = dev; + ai->bap0_lock = SPIN_LOCK_UNLOCKED; + ai->bap1_lock = SPIN_LOCK_UNLOCKED; + ai->aux_lock = SPIN_LOCK_UNLOCKED; + ai->cmd_lock = SPIN_LOCK_UNLOCKED; + ai->header_parse = dev->hard_header_parse; + rc = add_airo_dev( dev ); + if (rc) + goto err_out_free; + + /* The Airo-specific entries in the device structure. */ + dev->hard_start_xmit = &airo_start_xmit; + dev->get_stats = &airo_get_stats; + dev->set_multicast_list = &airo_set_multicast_list; + dev->set_mac_address = &airo_set_mac_address; + dev->do_ioctl = &airo_ioctl; +#ifdef WIRELESS_EXT + dev->get_wireless_stats = airo_get_wireless_stats; +#endif /* WIRELESS_EXT */ + dev->change_mtu = &airo_change_mtu; + dev->open = &airo_open; + dev->stop = &airo_close; + dev->irq = irq; + dev->base_addr = port; + + rc = register_netdev(dev); + if (rc) + goto err_out_unlink; + + rc = request_irq( dev->irq, airo_interrupt, + SA_SHIRQ | SA_INTERRUPT, dev->name, dev ); + if (rc) { + printk(KERN_ERR "airo: register interrupt %d failed, rc %d\n", irq, rc ); + goto err_out_unregister; + } + if (!is_pcmcia) { + if (!request_region( dev->base_addr, 64, dev->name )) { + rc = -EBUSY; + goto err_out_irq; + } + } + + if ( setup_card( ai, dev->dev_addr, &ai->config) != SUCCESS ) { + printk( KERN_ERR "airo: MAC could not be enabled\n" ); + rc = -EIO; + goto err_out_res; + } + + printk( KERN_INFO "airo: MAC enabled %s %x:%x:%x:%x:%x:%x\n", + dev->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] ); + + /* Allocate the transmit buffers */ + for( i = 0; i < MAX_FIDS; i++ ) + ai->fids[i] = transmit_allocate( ai, 2312 ); + + setup_proc_entry( dev, dev->priv ); /* XXX check for failure */ + netif_start_queue(dev); + SET_MODULE_OWNER(dev); + return dev; + +err_out_res: + if (!is_pcmcia) + release_region( dev->base_addr, 64 ); +err_out_irq: + free_irq(dev->irq, dev); +err_out_unregister: + unregister_netdev(dev); +err_out_unlink: + del_airo_dev(dev); +err_out_free: + kfree(dev); + return NULL; +} + +int waitbusy (struct airo_info *ai) { + int delay = 0; + while ((IN4500 (ai, COMMAND) & COMMAND_BUSY) & (delay < 10000)) { + udelay (10); + if (++delay % 20) + OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY); + } + return delay < 10000; +} + +int reset_airo_card( struct net_device *dev ) { + int i, flags; + struct airo_info *ai = (struct airo_info*)dev->priv; + + disable_MAC(ai); + spin_lock_irqsave(&ai->cmd_lock, flags); + waitbusy (ai); + OUT4500(ai,COMMAND,CMD_SOFTRESET); + set_current_state (TASK_UNINTERRUPTIBLE); + schedule_timeout (HZ/5); + waitbusy (ai); + set_current_state (TASK_UNINTERRUPTIBLE); + schedule_timeout (HZ/5); + spin_unlock_irqrestore(&ai->cmd_lock, flags); + if ( setup_card(ai, dev->dev_addr, &(ai)->config) != SUCCESS ) { + printk( KERN_ERR "airo: MAC could not be enabled\n" ); + return -1; + } else { + printk( KERN_INFO "airo: MAC enabled %s %x:%x:%x:%x:%x:%x\n", + dev->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] + ); + /* Allocate the transmit buffers */ + for( i = 0; i < MAX_FIDS; i++ ) + ai->fids[i] = transmit_allocate( ai, 2312 ); + } + enable_interrupts( ai ); + netif_wake_queue(dev); + return 0; +} + +int wll_header_parse(struct sk_buff *skb, unsigned char *haddr) +{ + memcpy(haddr, skb->mac.raw + 10, ETH_ALEN); + return ETH_ALEN; +} + +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; + u16 savedInterrupts; + + + if (!netif_device_present(dev)) + return; + + status = IN4500( apriv, EVSTAT ); + if ( !status || status == 0xffff ) return; + + if ( status & EV_AWAKE ) { + OUT4500( apriv, EVACK, EV_AWAKE ); + OUT4500( apriv, EVACK, EV_AWAKE ); + } + + savedInterrupts = IN4500( apriv, EVINTEN ); + OUT4500( apriv, EVINTEN, 0 ); + + if ( status & EV_LINK ) { + /* The link status has changed, if you want to put a + monitor hook in, do it here. (Remember that + interrupts are still disabled!) + */ + u16 newStatus = IN4500(apriv, LINKSTAT); + /* Here is what newStatus means: */ +#define NOBEACON 0x8000 /* Loss of sync - missed beacons */ +#define MAXRETRIES 0x8001 /* Loss of sync - max retries */ +#define MAXARL 0x8002 /* Loss of sync - average retry level exceeded*/ +#define FORCELOSS 0x8003 /* Loss of sync - host request */ +#define TSFSYNC 0x8004 /* Loss of sync - TSF synchronization */ +#define DEAUTH 0x8100 /* Deauthentication (low byte is reason code) */ +#define DISASS 0x8200 /* Disassociation (low byte is reason code) */ +#define ASSFAIL 0x8400 /* Association failure (low byte is reason + code) */ +#define AUTHFAIL 0x0300 /* Authentication failure (low byte is reason + code) */ +#define ASSOCIATED 0x0400 /* Assocatied */ +#define RC_RESERVED 0 /* Reserved return code */ +#define RC_NOREASON 1 /* Unspecified reason */ +#define RC_AUTHINV 2 /* Previous authentication invalid */ +#define RC_DEAUTH 3 /* Deauthenticated because sending station is + leaving */ +#define RC_NOACT 4 /* Disassociated due to inactivity */ +#define RC_MAXLOAD 5 /* Disassociated because AP is unable to handle + all currently associated stations */ +#define RC_BADCLASS2 6 /* Class 2 frame received from + non-Authenticated station */ +#define RC_BADCLASS3 7 /* Class 3 frame received from + non-Associated station */ +#define RC_STATLEAVE 8 /* Disassociated because sending station is + leaving BSS */ +#define RC_NOAUTH 9 /* Station requesting (Re)Association is not + Authenticated with the responding station */ + if (newStatus != ASSOCIATED) { + if (auto_wep && !timer_pending(&apriv->timer)) { + apriv->timer.expires = RUN_AT(HZ*3); + add_timer(&apriv->timer); + } + } + } + + /* Check to see if there is something to receive */ + if ( status & EV_RX ) { + struct sk_buff *skb = NULL; + int flags; + u16 fc, len, hdrlen = 0; + struct { + u16 status, len; + u8 rssi[2]; + } hdr; + + fid = IN4500( apriv, RXFID ); + + /* Get the packet length */ + spin_lock_irqsave(&apriv->bap0_lock, flags); + if (dev->type == ARPHRD_IEEE80211) { + 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) { + apriv->stats.rx_crc_errors++; + apriv->stats.rx_errors++; + hdr.len = 0; + } + } else { + bap_setup (apriv, fid, 6, BAP0); + bap_read (apriv, (u16*)&hdr.len, 4, BAP0); + } + len = le16_to_cpu(hdr.len); + + if (len > 2312) { + apriv->stats.rx_length_errors++; + apriv->stats.rx_errors++; + printk( KERN_ERR + "airo: Bad size %d\n", len ); + len = 0; + } + if (len) { + if (dev->type == ARPHRD_IEEE80211) { + bap_setup (apriv, fid, 0x14, BAP0); + bap_read (apriv, (u16*)&fc, sizeof(fc), BAP0); + if ((le16_to_cpu(fc) & 0x300) == 0x300) + hdrlen = 30; + else + hdrlen = 24; + } else + hdrlen = 12; + + skb = dev_alloc_skb( len + hdrlen + 2 ); + if ( !skb ) { + apriv->stats.rx_dropped++; + len = 0; + } + } + if (len) { + u16 *buffer; + buffer = (u16*)skb_put (skb, len + hdrlen); + if (dev->type == ARPHRD_IEEE80211) { + u16 gap, tmpbuf[4]; + buffer[0] = fc; + bap_read (apriv, buffer + 1, hdrlen - 2, BAP0); + if (hdrlen == 24) + bap_read (apriv, tmpbuf, 6, BAP0); + + bap_read (apriv, &gap, sizeof(gap), BAP0); + gap = le16_to_cpu(gap); + if (gap && gap <= 8) + bap_read (apriv, tmpbuf, gap, BAP0); + + bap_read (apriv, buffer + hdrlen/2, len, BAP0); + } else { + bap_setup (apriv, fid, 0x38, BAP0); + bap_read (apriv, buffer,len + hdrlen,BAP0); + } +#ifdef WIRELESS_SPY + if (apriv->spy_number > 0) { + int i; + char *sa; + + sa = (char*)buffer + ((dev->type == ARPHRD_IEEE80211) ? 10 : 6); + + for (i=0; ispy_number; i++) + if (!memcmp(sa,apriv->spy_address[i],6)) + { + apriv->spy_stat[i].qual = hdr.rssi[0]; + apriv->spy_stat[i].level = hdr.rssi[1]; + apriv->spy_stat[i].noise = 0; + apriv->spy_stat[i].updated = 3; + break; + } + } +#endif /* WIRELESS_SPY */ + apriv->stats.rx_packets++; + apriv->stats.rx_bytes += len + hdrlen; + dev->last_rx = jiffies; + skb->dev = dev; + skb->ip_summed = CHECKSUM_NONE; + if (dev->type == ARPHRD_IEEE80211) { + skb->mac.raw = skb->data; + skb_pull (skb, hdrlen); + skb->pkt_type = PACKET_OTHERHOST; + skb->protocol = htons(ETH_P_802_2); + } else + skb->protocol = eth_type_trans( skb, dev ); + + netif_rx( skb ); + } + spin_unlock_irqrestore(&apriv->bap0_lock, flags); + } + + /* Check to see if a packet has been transmitted */ + if ( status & ( EV_TX|EV_TXEXC ) ) { + int i; + int len = 0; + int full = 1; + int index = -1; + + fid = IN4500(apriv, TXCOMPLFID); + + for( i = 0; i < MAX_FIDS; i++ ) { + if (!(apriv->fids[i] & 0xffff0000)) full = 0; + if ( ( apriv->fids[i] & 0xffff ) == fid ) { + len = apriv->fids[i] >> 16; + index = i; + /* Set up to be used again */ + apriv->fids[i] &= 0xffff; + } + } + if (full) netif_wake_queue(dev); + if (index==-1) { + printk( KERN_ERR + "airo: Unallocated FID was used to xmit\n" ); + } + if ( status & EV_TX ) { + apriv->stats.tx_packets++; + if(index!=-1) + apriv->stats.tx_bytes += len; + } else { + apriv->stats.tx_errors++; + } + } + if ( status & ~STATUS_INTS ) + printk( KERN_WARNING + "airo: Got weird status %x\n", + status & ~STATUS_INTS ); + OUT4500( apriv, EVACK, status & STATUS_INTS ); + OUT4500( apriv, EVINTEN, savedInterrupts ); + + /* done.. */ + return; +} + +/* + * Routines to talk to the card + */ + +/* + * This was originally written for the 4500, hence the name + * NOTE: If use with 8bit mode and SMP bad things will happen! + * Why would some one do 8 bit IO in an SMP machine?!? + */ +static void OUT4500( struct airo_info *ai, u16 reg, u16 val ) { + if ( !do8bitIO ) + outw( val, ai->dev->base_addr + reg ); + else { + outb( val & 0xff, ai->dev->base_addr + reg ); + outb( val >> 8, ai->dev->base_addr + reg + 1 ); + } +} + +static u16 IN4500( struct airo_info *ai, u16 reg ) { + unsigned short rc; + + if ( !do8bitIO ) + rc = inw( ai->dev->base_addr + reg ); + else { + rc = inb( ai->dev->base_addr + reg ); + rc += ((int)inb( ai->dev->base_addr + reg + 1 )) << 8; + } + return rc; +} + +static int enable_MAC( struct airo_info *ai, Resp *rsp ) { + Cmd cmd; + + if (ai->flags&FLAG_RADIO_OFF) return SUCCESS; + memset(&cmd, 0, sizeof(cmd)); + cmd.cmd = MAC_ENABLE; + return issuecommand(ai, &cmd, rsp); +} + +static void disable_MAC( struct airo_info *ai ) { + Cmd cmd; + Resp rsp; + + memset(&cmd, 0, sizeof(cmd)); + cmd.cmd = MAC_DISABLE; // disable in case already enabled + issuecommand(ai, &cmd, &rsp); +} + +static void enable_interrupts( struct airo_info *ai ) { + /* Reset the status register */ + u16 status = IN4500( ai, EVSTAT ); + OUT4500( ai, EVACK, status ); + /* Enable the interrupts */ + OUT4500( ai, EVINTEN, STATUS_INTS ); + /* Note there is a race condition between the last two lines that + I dont know how to get rid of right now... */ +} + +static void disable_interrupts( struct airo_info *ai ) { + OUT4500( ai, EVINTEN, 0 ); +} + +static u16 setup_card(struct airo_info *ai, u8 *mac, + ConfigRid *config) +{ + Cmd cmd; + Resp rsp; + ConfigRid cfg; + int status; + int i; + SsidRid mySsid; + u16 lastindex; + WepKeyRid wkr; + int rc; + + memset( &mySsid, 0, sizeof( mySsid ) ); + + /* The NOP is the first step in getting the card going */ + cmd.cmd = NOP; + cmd.parm0 = cmd.parm1 = cmd.parm2 = 0; + if ( issuecommand( ai, &cmd, &rsp ) != SUCCESS ) { + return ERROR; + } + memset(&cmd, 0, sizeof(cmd)); + cmd.cmd = MAC_DISABLE; // disable in case already enabled + if ( issuecommand( ai, &cmd, &rsp ) != SUCCESS ) { + return ERROR; + } + + // Let's figure out if we need to use the AUX port + cmd.cmd = CMD_ENABLEAUX; + if (issuecommand(ai, &cmd, &rsp) != SUCCESS) { + printk(KERN_ERR "airo: Error checking for AUX port\n"); + return ERROR; + } + if (!aux_bap || rsp.status & 0xff00) { + ai->bap_read = fast_bap_read; + printk(KERN_DEBUG "airo: Doing fast bap_reads\n"); + } else { + ai->bap_read = aux_bap_read; + printk(KERN_DEBUG "airo: Doing AUX bap_reads\n"); + } + if ( config->len ) { + cfg = *config; + } else { + // general configuration (read/modify/write) + status = readConfigRid(ai, &cfg); + if ( status != SUCCESS ) return ERROR; + cfg.opmode = adhoc ? MODE_STA_IBSS : MODE_STA_ESS; + + /* Save off the MAC */ + for( i = 0; i < 6; i++ ) { + mac[i] = cfg.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)); + for( i = 0; i < 8 && rates[i]; i++ ) { + cfg.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; + break; + } + } + } + cfg.authType = ai->authtype; + *config = cfg; + } + + /* Setup the SSIDs if present */ + if ( ssids[0] ) { + int i = 0; + 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); + if ( status != SUCCESS ) return ERROR; + + /* Set up the SSID list */ + status = writeSsidRid(ai, &mySsid); + 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 { + lastindex = wkr.kindex; + if (wkr.kindex == 0xffff) { + ai->defindex = wkr.mac[0]; + } + rc = readWepKeyRid(ai, &wkr, 0); + } while(lastindex != wkr.kindex); + + if (auto_wep && !timer_pending(&ai->timer)) { + ai->timer.expires = RUN_AT(HZ*3); + add_timer(&ai->timer); + } + return SUCCESS; +} + +static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) { + // Im really paranoid about letting it run forever! + int max_tries = 600000; + int rc = SUCCESS; + int flags; + + spin_lock_irqsave(&ai->cmd_lock, flags); + 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); + } + } + if ( max_tries == -1 ) { + printk( KERN_ERR + "airo: Max tries exceeded when issueing command\n" ); + rc = ERROR; + goto done; + } + // command completed + pRsp->status = IN4500(ai, STATUS); + pRsp->rsp0 = IN4500(ai, RESP0); + pRsp->rsp1 = IN4500(ai, RESP1); + pRsp->rsp2 = IN4500(ai, RESP2); + + // clear stuck command busy if necessary + if (IN4500(ai, COMMAND) & COMMAND_BUSY) { + OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY); + } + // acknowledge processing the status/response + OUT4500(ai, EVACK, EV_CMD); + done: + spin_unlock_irqrestore(&ai->cmd_lock, flags); + return rc; +} + +/* Sets up the bap to start exchange data. whichbap should + * be one of the BAP0 or BAP1 defines. Locks should be held before + * calling! */ +static int bap_setup(struct airo_info *ai, u16 rid, u16 offset, int whichbap ) +{ + int timeout = 50; + int max_tries = 3; + + OUT4500(ai, SELECT0+whichbap, rid); + OUT4500(ai, OFFSET0+whichbap, offset); + while (1) { + int status = IN4500(ai, OFFSET0+whichbap); + if (status & BAP_BUSY) { + /* This isn't really a timeout, but its kinda + close */ + if (timeout--) { + continue; + } + } else if ( status & BAP_ERR ) { + /* invalid rid or offset */ + printk( KERN_ERR "airo: BAP error %x %d\n", + status, whichbap ); + return ERROR; + } else if (status & BAP_DONE) { // success + return SUCCESS; + } + if ( !(max_tries--) ) { + printk( KERN_ERR + "airo: BAP setup error too many retries\n" ); + return ERROR; + } + // -- PC4500 missed it, try again + OUT4500(ai, SELECT0+whichbap, rid); + OUT4500(ai, OFFSET0+whichbap, offset); + timeout = 50; + } +} + +/* should only be called by aux_bap_read. This aux function and the + following use concepts not documented in the developers guide. I + got them from a patch given to my by Aironet */ +static u16 aux_setup(struct airo_info *ai, u16 page, + u16 offset, u16 *len) +{ + u16 next; + + OUT4500(ai, AUXPAGE, page); + OUT4500(ai, AUXOFF, 0); + next = IN4500(ai, AUXDATA); + *len = IN4500(ai, AUXDATA)&0xff; + if (offset != 4) OUT4500(ai, AUXOFF, offset); + return next; +} + +/* requires call to bap_setup() first */ +static int aux_bap_read(struct airo_info *ai, u16 *pu16Dst, + int bytelen, int whichbap) +{ + u16 len; + u16 page; + u16 offset; + u16 next; + int words; + int i; + int flags; + + spin_lock_irqsave(&ai->aux_lock, flags); + page = IN4500(ai, SWS0+whichbap); + offset = IN4500(ai, SWS2+whichbap); + next = aux_setup(ai, page, offset, &len); + words = (bytelen+1)>>1; + + for (i=0; i>1) < (words-i) ? (len>>1) : (words-i); + if ( !do8bitIO ) + insw( ai->dev->base_addr+DATA0+whichbap, + pu16Dst+i,count ); + else + insb( ai->dev->base_addr+DATA0+whichbap, + pu16Dst+i, count << 1 ); + i += count; + if (iaux_lock, flags); + return SUCCESS; +} + + +/* requires call to bap_setup() first */ +static int fast_bap_read(struct airo_info *ai, u16 *pu16Dst, + int bytelen, int whichbap) +{ + bytelen = (bytelen + 1) & (~1); // round up to even value + if ( !do8bitIO ) + insw( ai->dev->base_addr+DATA0+whichbap, pu16Dst, bytelen>>1 ); + else + insb( ai->dev->base_addr+DATA0+whichbap, pu16Dst, bytelen ); + return SUCCESS; +} + +/* requires call to bap_setup() first */ +static int bap_write(struct airo_info *ai, const u16 *pu16Src, + int bytelen, int whichbap) +{ + bytelen = (bytelen + 1) & (~1); // round up to even value + if ( !do8bitIO ) + outsw( ai->dev->base_addr+DATA0+whichbap, + pu16Src, bytelen>>1 ); + else + outsb( ai->dev->base_addr+DATA0+whichbap, pu16Src, bytelen ); + return SUCCESS; +} + +static int PC4500_accessrid(struct airo_info *ai, u16 rid, u16 accmd) +{ + Cmd cmd; /* for issuing commands */ + Resp rsp; /* response from commands */ + u16 status; + + memset(&cmd, 0, sizeof(cmd)); + cmd.cmd = accmd; + cmd.parm0 = rid; + status = issuecommand(ai, &cmd, &rsp); + if (status != 0) return status; + if ( (rsp.status & 0x7F00) != 0) { + return (accmd << 8) + (rsp.rsp0 & 0xFF); + } + return 0; +} + +/* Note, that we are using BAP1 which is also used by transmit, so + * we must get a lock. */ +static int PC4500_readrid(struct airo_info *ai, u16 rid, void *pBuf, int len) +{ + u16 status; + int flags; + int rc = SUCCESS; + + spin_lock_irqsave(&ai->bap1_lock, flags); + if ( (status = PC4500_accessrid(ai, rid, CMD_ACCESS)) != SUCCESS) { + rc = status; + goto done; + } + if (bap_setup(ai, rid, 0, BAP1) != SUCCESS) { + rc = ERROR; + goto done; + } + // read the rid length field + bap_read(ai, pBuf, 2, BAP1); + // length for remaining part of rid + len = min(len, le16_to_cpu(*(u16*)pBuf)) - 2; + + if ( len <= 2 ) { + printk( KERN_ERR + "airo: Rid %x has a length of %d which is too short\n", + (int)rid, + (int)len ); + rc = ERROR; + goto done; + } + // read remainder of the rid + if (bap_setup(ai, rid, 2, BAP1) != SUCCESS) { + rc = ERROR; + goto done; + } + rc = bap_read(ai, ((u16*)pBuf)+1, len, BAP1); + done: + spin_unlock_irqrestore(&ai->bap1_lock, flags); + return rc; +} + +/* Note, that we are using BAP1 which is also used by transmit, so + * make sure this isnt called when a transmit is happening */ +static int PC4500_writerid(struct airo_info *ai, u16 rid, + const void *pBuf, int len) +{ + u16 status; + int flags; + int rc = SUCCESS; + + spin_lock_irqsave(&ai->bap1_lock, flags); + // --- first access so that we can write the rid data + if ( (status = PC4500_accessrid(ai, rid, CMD_ACCESS)) != 0) { + rc = status; + goto done; + } + // --- now write the rid data + if (bap_setup(ai, rid, 0, BAP1) != SUCCESS) { + rc = ERROR; + goto done; + } + bap_write(ai, pBuf, len, BAP1); + // ---now commit the rid data + rc = PC4500_accessrid(ai, rid, 0x100|CMD_ACCESS); + done: + spin_unlock_irqrestore(&ai->bap1_lock, flags); + 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) +{ + Cmd cmd; + Resp rsp; + u16 txFid; + u16 txControl; + int flags; + + cmd.cmd = CMD_ALLOCATETX; + cmd.parm0 = lenPayload; + if (issuecommand(ai, &cmd, &rsp) != SUCCESS) return 0; + if ( (rsp.status & 0xFF00) != 0) return 0; + /* 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. */ + while ( (IN4500(ai, EVSTAT) & EV_ALLOC) == 0) ; + // get the allocated fid and acknowledge + txFid = IN4500(ai, TXALLOCFID); + OUT4500(ai, EVACK, EV_ALLOC); + + /* The CARD is pretty cool since it converts the ethernet packet + * into 802.11. Also note that we don't release the FID since we + * 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->bap1_lock, flags); + if (bap_setup(ai, txFid, 0x0008, BAP1) != SUCCESS) { + spin_unlock_irqrestore(&ai->bap1_lock, flags); + return ERROR; + } + bap_write(ai, &txControl, sizeof(txControl), BAP1); + spin_unlock_irqrestore(&ai->bap1_lock, flags); + + return txFid; +} + +/* 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) +{ + u16 payloadLen; + Cmd cmd; + Resp rsp; + + if (len < 12) { + printk( KERN_WARNING "Short packet %d\n", len ); + return ERROR; + } + + // packet is destination[6], source[6], payload[len-12] + // write the payload length and dst/src/payload + if (bap_setup(ai, txFid, 0x0036, BAP1) != SUCCESS) return ERROR; + /* The hardware addresses aren't counted as part of the payload, so + * we have to subtract the 12 bytes for the addresses off */ + payloadLen = cpu_to_le16(len-12); + bap_write(ai, &payloadLen, sizeof(payloadLen),BAP1); + bap_write(ai, (const u16*)pPacket, len, 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! + */ + +/* + * Unfortunately sometime between 2.0 and 2.2 the proc interface changed... + * Unfortunately I dont know when it was... + * Im guessing it is sometime around 0x20155... Anybody know? + */ + +static ssize_t proc_read( struct file *file, + char *buffer, + size_t len, + loff_t *offset); + +static ssize_t proc_write( struct file *file, + const char *buffer, + size_t len, + loff_t *offset ); +static int proc_close( struct inode *inode, struct file *file ); + +static int proc_stats_open( struct inode *inode, struct file *file ); +static int proc_statsdelta_open( struct inode *inode, struct file *file ); +static int proc_status_open( struct inode *inode, struct file *file ); +static int proc_SSID_open( struct inode *inode, struct file *file ); +static int proc_APList_open( struct inode *inode, struct file *file ); +static int proc_config_open( struct inode *inode, struct file *file ); +static int proc_wepkey_open( struct inode *inode, struct file *file ); + +static struct file_operations proc_statsdelta_ops = { + read: proc_read, + open: proc_statsdelta_open, + release: proc_close +}; + +static struct file_operations proc_stats_ops = { + read: proc_read, + open: proc_stats_open, + release: proc_close +}; + +static struct file_operations proc_status_ops = { + read: proc_read, + open: proc_status_open, + release: proc_close +}; + +static struct file_operations proc_SSID_ops = { + read: proc_read, + write: proc_write, + open: proc_SSID_open, + release: proc_close +}; + +static struct file_operations proc_APList_ops = { + read: proc_read, + write: proc_write, + open: proc_APList_open, + release: proc_close +}; + +static struct file_operations proc_config_ops = { + read: proc_read, + write: proc_write, + open: proc_config_open, + release: proc_close +}; + +static struct file_operations proc_wepkey_ops = { + read: proc_read, + write: proc_write, + open: proc_wepkey_open, + release: proc_close +}; + +static struct proc_dir_entry *airo_entry = 0; + +struct proc_data { + int release_buffer; + int readlen; + char *rbuffer; + int writelen; + int maxwritelen; + char *wbuffer; + void (*on_close) (struct inode *, struct file *); +}; + +static int setup_proc_entry( struct net_device *dev, + struct airo_info *apriv ) { + struct proc_dir_entry *entry; + /* First setup the device directory */ + apriv->proc_entry = create_proc_entry(dev->name, + S_IFDIR|airo_perm, + airo_entry); + apriv->proc_entry->uid = proc_uid; + apriv->proc_entry->gid = proc_gid; + + /* Setup the StatsDelta */ + entry = create_proc_entry("StatsDelta", + S_IFREG | (S_IRUGO&proc_perm), + apriv->proc_entry); + entry->uid = proc_uid; + entry->gid = proc_gid; + entry->data = dev; +/* This is what was needed right up to the last few versions + of 2.3: + entry->ops = &proc_inode_statsdelta_ops; +*/ + entry->proc_fops = &proc_statsdelta_ops; + + /* Setup the Stats */ + entry = create_proc_entry("Stats", + S_IFREG | (S_IRUGO&proc_perm), + apriv->proc_entry); + entry->uid = proc_uid; + entry->gid = proc_gid; + entry->data = dev; + entry->proc_fops = &proc_stats_ops; + + /* Setup the Status */ + entry = create_proc_entry("Status", + S_IFREG | (S_IRUGO&proc_perm), + apriv->proc_entry); + entry->uid = proc_uid; + entry->gid = proc_gid; + entry->data = dev; + entry->proc_fops = &proc_status_ops; + + /* Setup the Config */ + entry = create_proc_entry("Config", + S_IFREG | proc_perm, + apriv->proc_entry); + entry->uid = proc_uid; + entry->gid = proc_gid; + entry->data = dev; + entry->proc_fops = &proc_config_ops; + + /* Setup the SSID */ + entry = create_proc_entry("SSID", + S_IFREG | proc_perm, + apriv->proc_entry); + entry->uid = proc_uid; + entry->gid = proc_gid; + entry->data = dev; + entry->proc_fops = &proc_SSID_ops; + + /* Setup the APList */ + entry = create_proc_entry("APList", + S_IFREG | proc_perm, + apriv->proc_entry); + entry->uid = proc_uid; + entry->gid = proc_gid; + entry->data = dev; + entry->proc_fops = &proc_APList_ops; + + /* Setup the WepKey */ + entry = create_proc_entry("WepKey", + S_IFREG | proc_perm, + apriv->proc_entry); + entry->uid = proc_uid; + entry->gid = proc_gid; + entry->data = dev; + entry->proc_fops = &proc_wepkey_ops; + + return 0; +} + +static int takedown_proc_entry( struct net_device *dev, + struct airo_info *apriv ) { + if ( !apriv->proc_entry->namelen ) return 0; + remove_proc_entry("Stats",apriv->proc_entry); + remove_proc_entry("StatsDelta",apriv->proc_entry); + remove_proc_entry("Status",apriv->proc_entry); + remove_proc_entry("Config",apriv->proc_entry); + remove_proc_entry("SSID",apriv->proc_entry); + remove_proc_entry("APList",apriv->proc_entry); + remove_proc_entry("WepKey",apriv->proc_entry); + remove_proc_entry(dev->name,airo_entry); + return 0; +} + +/* + * What we want from the proc_fs is to be able to efficiently read + * and write the configuration. To do this, we want to read the + * configuration when the file is opened and write it when the file is + * closed. So basically we allocate a read buffer at open and fill it + * with data, and allocate a write buffer and read it at close. + */ + +/* + * The read routine is generic, it relies on the preallocated rbuffer + * to supply the data. + */ +static ssize_t proc_read( struct file *file, + char *buffer, + size_t len, + loff_t *offset ) +{ + int i; + int pos; + struct proc_data *priv = (struct proc_data*)file->private_data; + + if( !priv->rbuffer ) return -EINVAL; + + pos = *offset; + for( i = 0; i+pos < priv->readlen && i < len; i++ ) { + if (put_user( priv->rbuffer[i+pos], buffer+i )) + return -EFAULT; + } + *offset += i; + return i; +} + +/* + * The write routine is generic, it fills in a preallocated rbuffer + * to supply the data. + */ +static ssize_t proc_write( struct file *file, + const char *buffer, + size_t len, + loff_t *offset ) +{ + int i; + int pos; + struct proc_data *priv = (struct proc_data*)file->private_data; + + if ( !priv->wbuffer ) { + return -EINVAL; + } + + pos = *offset; + + for( i = 0; i + pos < priv->maxwritelen && + i < len; i++ ) { + if (get_user( priv->wbuffer[i+pos], buffer + i )) + return -EFAULT; + } + if ( i+pos > priv->writelen ) priv->writelen = i+file->f_pos; + *offset += i; + return i; +} + +static int proc_status_open( struct inode *inode, struct file *file ) { + struct proc_data *data; + struct proc_dir_entry *dp = inode->u.generic_ip; + struct net_device *dev = dp->data; + struct airo_info *apriv = (struct airo_info *)dev->priv; + CapabilityRid cap_rid; + StatusRid status_rid; + + MOD_INC_USE_COUNT; + + dp = inode->u.generic_ip; + + if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) + return -ENOMEM; + memset(file->private_data, 0, sizeof(struct proc_data)); + data = (struct proc_data *)file->private_data; + if ((data->rbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) { + kfree (file->private_data); + return -ENOMEM; + } + + readStatusRid(apriv, &status_rid); + readCapabilityRid(apriv, &cap_rid); + + sprintf( data->rbuffer, "Mode: %x\n" + "Signal Strength: %d\n" + "Signal Quality: %d\n" + "SSID: %-.*s\n" + "AP: %-.16s\n" + "Freq: %d\n" + "BitRate: %dmbs\n" + "Driver Version: %s\n" + "Device: %s\nManufacturer: %s\nFirmware Version: %s\n" + "Radio type: %x\nCountry: %x\nHardware Version: %x\n" + "Software Version: %x\nSoftware Subversion: %x\n" + "Boot block version: %x\n", + (int)status_rid.mode, + (int)status_rid.normalizedSignalStrength, + (int)status_rid.signalQuality, + (int)status_rid.SSIDlen, + status_rid.SSID, + status_rid.apName, + (int)status_rid.channel, + (int)status_rid.currentXmitRate/2, + version, + cap_rid.prodName, + cap_rid.manName, + cap_rid.prodVer, + cap_rid.radioType, + cap_rid.country, + cap_rid.hardVer, + (int)cap_rid.softVer, + (int)cap_rid.softSubVer, + (int)cap_rid.bootBlockVer ); + data->readlen = strlen( data->rbuffer ); + return 0; +} + +static int proc_stats_rid_open(struct inode*, struct file*, u16); +static int proc_statsdelta_open( struct inode *inode, + struct file *file ) { + if (file->f_mode&FMODE_WRITE) { + return proc_stats_rid_open(inode, file, RID_STATSDELTACLEAR); + } + return proc_stats_rid_open(inode, file, RID_STATSDELTA); +} + +static int proc_stats_open( struct inode *inode, struct file *file ) { + return proc_stats_rid_open(inode, file, RID_STATS); +} + +static int proc_stats_rid_open( struct inode *inode, + struct file *file, + u16 rid ) { + struct proc_data *data; + struct proc_dir_entry *dp = inode->u.generic_ip; + struct net_device *dev = dp->data; + struct airo_info *apriv = (struct airo_info *)dev->priv; + StatsRid stats; + int i, j; + int *vals = stats.vals; + MOD_INC_USE_COUNT; + + + dp = inode->u.generic_ip; + + if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) + return -ENOMEM; + memset(file->private_data, 0, sizeof(struct proc_data)); + data = (struct proc_data *)file->private_data; + if ((data->rbuffer = kmalloc( 4096, GFP_KERNEL )) == NULL) { + kfree (file->private_data); + return -ENOMEM; + } + + readStatsRid(apriv, &stats, rid); + + j = 0; + for(i=0; (int)statsLabels[i]!=-1 && + i*44096) { + printk(KERN_WARNING + "airo: Potentially disasterous buffer overflow averted!\n"); + break; + } + j+=sprintf(data->rbuffer+j, "%s: %d\n", statsLabels[i], vals[i]); + } + if (i*4>=stats.len){ + printk(KERN_WARNING + "airo: Got a short rid\n"); + } + data->readlen = j; + return 0; +} + +static int get_dec_u16( char *buffer, int *start, int limit ) { + u16 value; + int valid = 0; + for( value = 0; buffer[*start] >= '0' && + buffer[*start] <= '9' && + *start < limit; (*start)++ ) { + valid = 1; + value *= 10; + value += buffer[*start] - '0'; + } + if ( !valid ) return -1; + 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 = inode->u.generic_ip; + struct net_device *dev = dp->data; + struct airo_info *ai = (struct airo_info*)dev->priv; + ConfigRid config; + Resp rsp; + char *line; + int need_reset = 0; + + if ( !data->writelen ) return; + dp = (struct proc_dir_entry *) inode->u.generic_ip; + + disable_MAC(ai); + readConfigRid(ai, &config); + + line = data->wbuffer; + while( line[0] ) { +/*** Mode processing */ + if ( !strncmp( line, "Mode: ", 6 ) ) { + line += 6; + config.rmode &= 0xfe00; + if ( line[0] == 'a' ) { + 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; + } + } + +/*** Radio status */ + else if (!strncmp(line,"Radio: ", 7)) { + line += 7; + if (!strncmp(line,"off",3)) { + ai->flags |= FLAG_RADIO_OFF; + } else { + ai->flags &= ~FLAG_RADIO_OFF; + } + } +/*** NodeName processing */ + else if ( !strncmp( line, "NodeName: ", 10 ) ) { + int j; + + line += 10; + memset( 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]; + } + } + +/*** PowerMode processing */ + else if ( !strncmp( line, "PowerMode: ", 11 ) ) { + line += 11; + if ( !strncmp( line, "PSPCAM", 6 ) ) { + config.powerSaveMode = POWERSAVE_PSPCAM; + } else if ( !strncmp( line, "PSP", 3 ) ) { + config.powerSaveMode = POWERSAVE_PSP; + } else { + config.powerSaveMode = POWERSAVE_CAM; + } + } else if ( !strncmp( line, "DataRates: ", 11 ) ) { + int v, i = 0, k = 0; /* i is index into line, + k is index to rates */ + + line += 11; + while((v = get_dec_u16(line, &i, 3))!=-1) { + config.rates[k++] = (u8)v; + line += i + 1; + i = 0; + } + } 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; + } 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; + } else if ( !strncmp( line, "WEP: ", 5 ) ) { + line += 5; + switch( line[0] ) { + case 's': + config.authType = (u16)AUTH_SHAREDKEY; + break; + case 'e': + config.authType = (u16)AUTH_ENCRYPT; + break; + default: + config.authType = (u16)AUTH_OPEN; + break; + } + } 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; + } 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; + } 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; + } 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; + } 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; + } else if ( !strncmp( line, "TXDiversity: ", 13 ) ) { + config.txDiversity = + (line[13]=='l') ? 1 : + ((line[13]=='r')? 2: 3); + } else if ( !strncmp( line, "RXDiversity: ", 13 ) ) { + config.rxDiversity = + (line[13]=='l') ? 1 : + ((line[13]=='r')? 2: 3); + } else if ( !strncmp( line, "FragThreshold: ", 15 ) ) { + int v, i = 0; + + line += 15; + 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; + } 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; + default: + printk( KERN_WARNING "airo: Unknown modulation\n" ); + } + } else { + printk( KERN_WARNING "Couldn't figure out %s\n", line ); + } + while( line[0] && line[0] != '\n' ) line++; + if ( line[0] ) line++; + } + checkThrottle(&config); + ai->config = config; + if (need_reset) { + APListRid APList_rid; + SsidRid SSID_rid; + + readAPListRid(ai, &APList_rid); + readSsidRid(ai, &SSID_rid); + reset_airo_card(dev); + writeSsidRid(ai, &SSID_rid); + writeAPListRid(ai, &APList_rid); + } + writeConfigRid(ai, &config); + enable_MAC(ai, &rsp); +} + +static int proc_config_open( struct inode *inode, struct file *file ) { + struct proc_data *data; + struct proc_dir_entry *dp = inode->u.generic_ip; + struct net_device *dev = dp->data; + struct airo_info *ai = (struct airo_info*)dev->priv; + ConfigRid config; + int i; + + MOD_INC_USE_COUNT; + + dp = (struct proc_dir_entry *) inode->u.generic_ip; + + if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) + return -ENOMEM; + memset(file->private_data, 0, sizeof(struct proc_data)); + data = (struct proc_data *)file->private_data; + if ((data->rbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) { + kfree (file->private_data); + return -ENOMEM; + } + if ((data->wbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) { + kfree (data->rbuffer); + kfree (file->private_data); + return -ENOMEM; + } + memset( data->wbuffer, 0, 2048 ); + data->maxwritelen = 2048; + data->on_close = proc_config_on_close; + + readConfigRid(ai, &config); + + i = sprintf( data->rbuffer, + "Mode: %s\n" + "Radio: %s\n" + "NodeName: %-16s\n" + "PowerMode: %s\n" + "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->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 + ); + sprintf( data->rbuffer + i, + "LongRetryLimit: %d\n" + "ShortRetryLimit: %d\n" + "RTSThreshold: %d\n" + "TXMSDULifetime: %d\n" + "RXMSDULifetime: %d\n" + "TXDiversity: %s\n" + "RXDiversity: %s\n" + "FragThreshold: %d\n" + "WEP: %s\n" + "Modulation: %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" + ); + data->readlen = strlen( data->rbuffer ); + return 0; +} + +static void proc_SSID_on_close( struct inode *inode, struct file *file ) { + struct proc_data *data = (struct proc_data *)file->private_data; + struct proc_dir_entry *dp = inode->u.generic_ip; + struct net_device *dev = dp->data; + struct airo_info *ai = (struct airo_info*)dev->priv; + SsidRid SSID_rid; + int i; + int offset = 0; + + if ( !data->writelen ) return; + + memset( &SSID_rid, 0, sizeof( SSID_rid ) ); + + for( i = 0; i < 3; i++ ) { + int j; + for( j = 0; j+offset < data->writelen && j < 32 && + data->wbuffer[offset+j] != '\n'; j++ ) { + SSID_rid.ssids[i].ssid[j] = data->wbuffer[offset+j]; + } + if ( j == 0 ) break; + SSID_rid.ssids[i].len = j; + offset += j; + while( data->wbuffer[offset] != '\n' && + offset < data->writelen ) offset++; + offset++; + } + writeSsidRid(ai, &SSID_rid); +} + +inline static u8 hexVal(char c) { + if (c>='0' && c<='9') return c -= '0'; + if (c>='a' && c<='f') return c -= 'a'-10; + if (c>='A' && c<='F') return c -= 'A'-10; + return 0; +} + +static void proc_APList_on_close( struct inode *inode, struct file *file ) { + struct proc_data *data = (struct proc_data *)file->private_data; + struct proc_dir_entry *dp = inode->u.generic_ip; + struct net_device *dev = dp->data; + struct airo_info *ai = (struct airo_info*)dev->priv; + APListRid APList_rid; + int i; + + if ( !data->writelen ) return; + + memset( &APList_rid, 0, sizeof(APList_rid) ); + APList_rid.len = sizeof(APList_rid); + + for( i = 0; i < 4 && data->writelen >= (i+1)*6*3; i++ ) { + int j; + for( j = 0; j < 6*3 && data->wbuffer[j+i*6*3]; j++ ) { + switch(j%3) { + case 0: + APList_rid.ap[i][j/3]= + hexVal(data->wbuffer[j+i*6*3])<<4; + break; + case 1: + APList_rid.ap[i][j/3]|= + hexVal(data->wbuffer[j+i*6*3]); + break; + } + } + } + writeAPListRid(ai, &APList_rid); +} + +/* This function wraps PC4500_writerid with a MAC disable */ +static int do_writerid( struct airo_info *ai, u16 rid, const void *rid_data, + int len ) { + int rc; + Resp rsp; + + disable_MAC(ai); + rc = PC4500_writerid(ai, rid, rid_data, len); + enable_MAC(ai, &rsp); + return rc; +} + +/* Returns the length of the key at the index. If index == 0xffff + * the index of the transmit key is returned. If the key doesn't exist, + * -1 will be returned. + */ +static int get_wep_key(struct airo_info *ai, u16 index) { + WepKeyRid wkr; + int rc; + u16 lastindex; + + rc = readWepKeyRid(ai, &wkr, 1); + if (rc == SUCCESS) do { + lastindex = wkr.kindex; + if (wkr.kindex == index) { + if (index == 0xffff) { + return wkr.mac[0]; + } + return wkr.klen; + } + readWepKeyRid(ai, &wkr, 0); + } while(lastindex != wkr.kindex); + return -1; +} + +static int set_wep_key(struct airo_info *ai, u16 index, + const char *key, u16 keylen, int perm ) { + static const unsigned char macaddr[6] = { 0x01, 0, 0, 0, 0, 0 }; + WepKeyRid wkr; + + memset(&wkr, 0, sizeof(wkr)); + if (keylen == 0) { +// We are selecting which key to use + wkr.len = sizeof(wkr); + wkr.kindex = 0xffff; + wkr.mac[0] = (char)index; + if (perm) printk(KERN_INFO "Setting transmit key to %d\n", index); + if (perm) ai->defindex = (char)index; + } else { +// We are actually setting the key + wkr.len = sizeof(wkr); + wkr.kindex = index; + wkr.klen = keylen; + memcpy( wkr.key, key, keylen ); + memcpy( wkr.mac, macaddr, 6 ); + printk(KERN_INFO "Setting key %d\n", index); + } + + writeWepKeyRid(ai, &wkr, perm); + return 0; +} + +static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { + struct proc_data *data; + struct proc_dir_entry *dp = inode->u.generic_ip; + struct net_device *dev = dp->data; + struct airo_info *ai = (struct airo_info*)dev->priv; + int i; + char key[16]; + u16 index = 0; + int j = 0; + + memset(key, 0, sizeof(key)); + + dp = (struct proc_dir_entry *) inode->u.generic_ip; + data = (struct proc_data *)file->private_data; + if ( !data->writelen ) return; + + if (data->wbuffer[0] >= '0' && data->wbuffer[0] <= '3' && + (data->wbuffer[1] == ' ' || data->wbuffer[1] == '\n')) { + index = data->wbuffer[0] - '0'; + if (data->wbuffer[1] == '\n') { + set_wep_key(ai, index, 0, 0, 1); + return; + } + j = 2; + } else { + printk(KERN_ERR "airo: WepKey passed invalid key index\n"); + return; + } + + for( i = 0; i < 16*3 && data->wbuffer[i+j]; i++ ) { + switch(i%3) { + case 0: + key[i/3] = hexVal(data->wbuffer[i+j])<<4; + break; + case 1: + key[i/3] |= hexVal(data->wbuffer[i+j]); + break; + } + } + set_wep_key(ai, index, key, i/3, 1); +} + +static int proc_wepkey_open( struct inode *inode, struct file *file ) { + struct proc_data *data; + struct proc_dir_entry *dp = inode->u.generic_ip; + struct net_device *dev = dp->data; + struct airo_info *ai = (struct airo_info*)dev->priv; + char *ptr; + WepKeyRid wkr; + u16 lastindex; + int j=0; + int rc; + + MOD_INC_USE_COUNT; + + dp = (struct proc_dir_entry *) inode->u.generic_ip; + + if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) + return -ENOMEM; + memset(file->private_data, 0, sizeof(struct proc_data)); + memset(&wkr, 0, sizeof(wkr)); + data = (struct proc_data *)file->private_data; + if ((data->rbuffer = kmalloc( 180, GFP_KERNEL )) == NULL) { + kfree (file->private_data); + return -ENOMEM; + } + memset(data->rbuffer, 0, 180); + data->writelen = 0; + data->maxwritelen = 80; + if ((data->wbuffer = kmalloc( 80, GFP_KERNEL )) == NULL) { + kfree (data->rbuffer); + kfree (file->private_data); + return -ENOMEM; + } + memset( data->wbuffer, 0, 80 ); + data->on_close = proc_wepkey_on_close; + + ptr = data->rbuffer; + strcpy(ptr, "No wep keys\n"); + rc = readWepKeyRid(ai, &wkr, 1); + if (rc == SUCCESS) do { + lastindex = wkr.kindex; + if (wkr.kindex == 0xffff) { + j += sprintf(ptr+j, "Tx key = %d\n", + (int)wkr.mac[0]); + } else { + j += sprintf(ptr+j, "Key %d set with length = %d\n", + (int)wkr.kindex, (int)wkr.klen); + } + readWepKeyRid(ai, &wkr, 0); + } while((lastindex != wkr.kindex) && (j < 180-30)); + + data->readlen = strlen( data->rbuffer ); + return 0; +} + +static int proc_SSID_open( struct inode *inode, struct file *file ) { + struct proc_data *data; + struct proc_dir_entry *dp = inode->u.generic_ip; + struct net_device *dev = dp->data; + struct airo_info *ai = (struct airo_info*)dev->priv; + int i; + char *ptr; + SsidRid SSID_rid; + + MOD_INC_USE_COUNT; + + dp = (struct proc_dir_entry *) inode->u.generic_ip; + + if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) + return -ENOMEM; + memset(file->private_data, 0, sizeof(struct proc_data)); + data = (struct proc_data *)file->private_data; + if ((data->rbuffer = kmalloc( 104, GFP_KERNEL )) == NULL) { + kfree (file->private_data); + return -ENOMEM; + } + data->writelen = 0; + data->maxwritelen = 33*3; + if ((data->wbuffer = kmalloc( 33*3, GFP_KERNEL )) == NULL) { + kfree (data->rbuffer); + kfree (file->private_data); + return -ENOMEM; + } + memset( data->wbuffer, 0, 33*3 ); + data->on_close = proc_SSID_on_close; + + readSsidRid(ai, &SSID_rid); + ptr = data->rbuffer; + for( i = 0; i < 3; i++ ) { + int j; + if ( !SSID_rid.ssids[i].len ) break; + for( j = 0; j < 32 && + j < SSID_rid.ssids[i].len && + SSID_rid.ssids[i].ssid[j]; j++ ) { + *ptr++ = SSID_rid.ssids[i].ssid[j]; + } + *ptr++ = '\n'; + } + *ptr = '\0'; + data->readlen = strlen( data->rbuffer ); + return 0; +} + +static int proc_APList_open( struct inode *inode, struct file *file ) { + struct proc_data *data; + struct proc_dir_entry *dp = inode->u.generic_ip; + struct net_device *dev = dp->data; + struct airo_info *ai = (struct airo_info*)dev->priv; + int i; + char *ptr; + APListRid APList_rid; + + MOD_INC_USE_COUNT; + + dp = (struct proc_dir_entry *) inode->u.generic_ip; + + if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) + return -ENOMEM; + memset(file->private_data, 0, sizeof(struct proc_data)); + data = (struct proc_data *)file->private_data; + if ((data->rbuffer = kmalloc( 104, GFP_KERNEL )) == NULL) { + kfree (file->private_data); + return -ENOMEM; + } + data->writelen = 0; + data->maxwritelen = 4*6*3; + if ((data->wbuffer = kmalloc( data->maxwritelen, GFP_KERNEL )) == NULL) { + kfree (data->rbuffer); + kfree (file->private_data); + return -ENOMEM; + } + memset( data->wbuffer, 0, data->maxwritelen ); + data->on_close = proc_APList_on_close; + + readAPListRid(ai, &APList_rid); + ptr = data->rbuffer; + for( i = 0; i < 4; i++ ) { +// We end when we find a zero MAC + if ( !*(int*)APList_rid.ap[i] && + !*(int*)&APList_rid.ap[i][2]) break; + ptr += sprintf(ptr, "%02x:%02x:%02x:%02x:%02x:%02x\n", + (int)APList_rid.ap[i][0], + (int)APList_rid.ap[i][1], + (int)APList_rid.ap[i][2], + (int)APList_rid.ap[i][3], + (int)APList_rid.ap[i][4], + (int)APList_rid.ap[i][5]); + } + if (i==0) ptr += sprintf(ptr, "Not using specific APs\n"); + + *ptr = '\0'; + data->readlen = strlen( data->rbuffer ); + return 0; +} + +static int proc_close( struct inode *inode, struct file *file ) +{ + struct proc_data *data = (struct proc_data *)file->private_data; + if ( data->on_close != NULL ) data->on_close( inode, file ); + MOD_DEC_USE_COUNT; + if ( data->rbuffer ) kfree( data->rbuffer ); + if ( data->wbuffer ) kfree( data->wbuffer ); + kfree( data ); + return 0; +} + +static struct net_device_list { + struct net_device *dev; + struct net_device_list *next; +} *airo_devices = 0; + +/* Since the card doesnt automatically switch to the right WEP mode, + we will make it do it. If the card isn't associated, every secs we + will switch WEP modes to see if that will help. If the card is + associated we will check every minute to see if anything has + 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; + u16 linkstat = IN4500(apriv, LINKSTAT); + + if (linkstat != 0x400 ) { +/* We don't have a link so try changing the authtype */ + ConfigRid config = apriv->config; + + switch(apriv->authtype) { + case AUTH_ENCRYPT: +/* So drop to OPEN */ + config.authType = AUTH_OPEN; + apriv->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->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; + } + break; + default: /* We'll escalate to SHAREDKEY */ + config.authType = AUTH_SHAREDKEY; + apriv->authtype = AUTH_SHAREDKEY; + } + checkThrottle(&config); + writeConfigRid(apriv, &config); + +/* Schedule check to see if the change worked */ + apriv->timer.expires = RUN_AT(HZ*3); + add_timer(&apriv->timer); + } +} + +static int add_airo_dev( struct net_device *dev ) { + struct net_device_list *node = kmalloc( sizeof( *node ), GFP_KERNEL ); + if ( !node ) + return -ENOMEM; + + if ( auto_wep ) { + struct airo_info *apriv=dev->priv; + struct timer_list *timer = &apriv->timer; + + timer->function = timer_func; + timer->data = (u_long)dev; + init_timer(timer); + apriv->authtype = AUTH_SHAREDKEY; + } + + node->dev = dev; + node->next = airo_devices; + airo_devices = node; + + return 0; +} + +static void del_airo_dev( struct net_device *dev ) { + struct net_device_list **p = &airo_devices; + while( *p && ( (*p)->dev != dev ) ) + p = &(*p)->next; + if ( *p && (*p)->dev == dev ) + *p = (*p)->next; +} + +#ifdef CONFIG_PCI +static int __devinit airo_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *pent) +{ + pdev->driver_data = init_airo_card(pdev->irq, + pdev->resource[2].start, 0); + if (!pdev->driver_data) { + return -ENODEV; + } + return 0; +} + +static void __devexit airo_pci_remove(struct pci_dev *pdev) +{ + stop_airo_card(pdev->driver_data, 1); +} + +#endif + +static int __init airo_init_module( void ) +{ + int i, rc = 0, have_isa_dev = 0; + + airo_entry = create_proc_entry("aironet", + S_IFDIR | airo_perm, + proc_root_driver); + airo_entry->uid = proc_uid; + airo_entry->gid = proc_gid; + + for( i = 0; i < 4 && io[i] && irq[i]; i++ ) { + printk( KERN_INFO + "airo: Trying to configure ISA adapter at irq=%d io=0x%x\n", + irq[i], io[i] ); + if (init_airo_card( irq[i], io[i], 0 )) + have_isa_dev = 1; + } + +#ifdef CONFIG_PCI + printk( KERN_INFO "airo: Probing for PCI adapters\n" ); + rc = pci_module_init(&airo_driver); + printk( KERN_INFO "airo: Finished probing for PCI adapters\n" ); +#endif + + /* Always exit with success, as we are a library module + * as well as a driver module + */ + return 0; +} + +static void __exit airo_cleanup_module( void ) +{ + while( airo_devices ) { + printk( KERN_INFO "airo: Unregistering %s\n", airo_devices->dev->name ); + stop_airo_card( airo_devices->dev, 1 ); + } + remove_proc_entry("aironet", proc_root_driver); +} + +#ifdef WIRELESS_EXT +/* + * Initial Wireless Extension code for Aironet driver by : + * Jean Tourrilhes - HPL - 17 November 00 + */ +#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. + */ +static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + int 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 */ + int i; + +#ifdef CISCO_EXT + if (cmd != SIOCGIWPRIV && cmd != AIROIOCTL && cmd != AIROIDIFC) +#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); + } +#endif /* WIRELESS_EXT */ + + switch (cmd) { +#ifdef WIRELESS_EXT + // Get name + case SIOCGIWNAME: + strcpy(wrq->u.name, "IEEE 802.11-DS"); + break; + + // 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; + + // Get frequency/channel + case SIOCGIWFREQ: +#ifdef WEXT_USECHANNELS + wrq->u.freq.m = ((int)status_rid.channel) + 1; + wrq->u.freq.e = 0; +#else + { + int f = (int)status_rid.channel; + wrq->u.freq.m = frequency_list[f] * 100000; + wrq->u.freq.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; + + /* 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; + } + + /* Set the SSID */ + memset(essid, 0, sizeof(essid)); + copy_from_user(essid, + wrq->u.data.pointer, + wrq->u.data.length); + 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; + + // 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; + } + break; + + case SIOCSIWAP: + if (wrq->u.ap_addr.sa_family != ARPHRD_ETHER) + rc = -EINVAL; + else { + APListRid APList_rid; + + 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; + + // 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; + + // Set desired station name + case SIOCSIWNICKN: + if (wrq->u.data.pointer) { + char name[16 + 1]; + + /* Check the size of the string */ + if(wrq->u.data.length > 16 + 1) { + rc = -E2BIG; + break; + } + memset(name, 0, sizeof(name)); + copy_from_user(name, wrq->u.data.pointer, wrq->u.data.length); + memcpy(config.nodeName, name, 16); + local->need_commit = 1; + } + break; + + // 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; + + // 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); + + /* 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; + } + if(i != 0) + brate = cap_rid.supportedRates[i - 1]; + } + /* Check that it is valid */ + if(brate == 0) { + rc = -EINVAL; + break; + } + + /* 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; + } + break; + } + + // 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; + + // 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; + } + } + break; + + // 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; + + // 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; + } + } + break; + + // 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; + + // Set mode of operation + case SIOCSIWMODE: + switch(wrq->u.mode) { + case IW_MODE_ADHOC: + config.opmode = MODE_STA_IBSS; + local->need_commit = 1; + break; + case IW_MODE_INFRA: + config.opmode = MODE_STA_ESS; + local->need_commit = 1; + break; + case IW_MODE_MASTER: + config.opmode = MODE_AP; + local->need_commit = 1; + break; + case IW_MODE_REPEAT: + config.opmode = MODE_AP_RPTR; + local->need_commit = 1; + break; + default: + rc = -EINVAL; + } + break; + + // Get mode of operation + case SIOCGIWMODE: + /* If not managed, assume it's ad-hoc */ + switch (config.opmode & 0xFF) { + case MODE_STA_ESS: + wrq->u.mode = IW_MODE_INFRA; + break; + case MODE_AP: + wrq->u.mode = IW_MODE_MASTER; + break; + case MODE_AP_RPTR: + wrq->u.mode = IW_MODE_REPEAT; + break; + default: + wrq->u.mode = IW_MODE_ADHOC; + } + break; + + // 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 >= MAX_KEYS)) + 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 < MAX_KEYS)) { + 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; + } + } + /* 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) + local->need_commit = 1; + break; + + // Get the WEP keys and mode + case SIOCGIWENCODE: + /* Is it supported ? */ + if(!(cap_rid.softCap & 2)) { + rc = -EOPNOTSUPP; + break; + } + // Only super-user can see WEP key + if (!capable(CAP_NET_ADMIN)) { + rc = -EPERM; + 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; + } + + /* Which key do we want ? -1 -> tx index */ + if((index < 0) || (index >= MAX_KEYS)) + 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; + } + + if(copy_to_user(wrq->u.encoding.pointer, zeros, + wrq->u.encoding.length)) + rc = -EFAULT; + } + break; + +#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; + local->need_commit = 1; + break; + } + if (wrq->u.txpower.flags != IW_TXPOW_MWATT) { + rc = -EINVAL; + break; + } + 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 */ + +#if WIRELESS_EXT > 10 + case SIOCGIWRETRY: + wrq->u.retry.disabled = 0; + if ((wrq->u.retry.flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) + wrq->u.retry.value = (int)config.txLifetime * 1024; + else { + wrq->u.retry.value = (int)config.shortRetryLimit; + wrq->u.retry.flags = IW_RETRY_LIMIT; + } + break; + + case SIOCSIWRETRY: + if (wrq->u.retry.disabled) { + config.shortRetryLimit = 0; + config.longRetryLimit = 0; + config.txLifetime = 0; + local->need_commit = 1; + break; + } + if ((wrq->u.retry.flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { + config.txLifetime = (wrq->u.retry.value + 500) / 1024; + local->need_commit = 1; + } else if ((wrq->u.retry.flags & IW_RETRY_TYPE) == IW_RETRY_LIMIT) { + config.shortRetryLimit = config.longRetryLimit = wrq->u.retry.value; + local->need_commit = 1; + } + break; +#endif /* WIRELESS_EXT > 10 */ + + // Get range of parameters + case SIOCGIWRANGE: + if (wrq->u.data.pointer) { + struct iw_range range; + int i; + int k; + + wrq->u.data.length = sizeof(range); + /* Should adapt depending on max rate */ + range.throughput = 1.6 * 1024 * 1024; + 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 = 100; + 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; + + 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 = 4; // 4 keys + } 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 = 11; + 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 (copy_to_user(wrq->u.data.pointer, &range, sizeof(struct iw_range))) + rc = -EFAULT; + } + break; + + case SIOCGIWPOWER: + { + int mode = config.powerSaveMode; + if ((wrq->u.power.disabled = (mode == POWERSAVE_CAM))) + 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; + } + if ((config.rmode & 0xFF) == RXMODE_ADDR) + wrq->u.power.flags |= IW_POWER_UNICAST_R; + else + wrq->u.power.flags |= IW_POWER_ALL_R; + } + break; + + case SIOCSIWPOWER: + if (wrq->u.power.disabled) { + if ((config.rmode & 0xFF) >= RXMODE_RFMON) { + rc = -EINVAL; + break; + } + config.powerSaveMode = POWERSAVE_CAM; + config.rmode &= 0xFF00; + config.rmode |= RXMODE_BC_MC_ADDR; + local->need_commit = 1; + break; + } + 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; + } + switch (wrq->u.power.flags & IW_POWER_MODE) { + case IW_POWER_UNICAST_R: + if ((config.rmode & 0xFF) >= RXMODE_RFMON) { + rc = -EINVAL; + 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; + break; + } + config.rmode &= 0xFF00; + config.rmode |= RXMODE_BC_MC_ADDR; + local->need_commit = 1; + case IW_POWER_ON: + break; + default: + rc = -EINVAL; + } + break; + + case SIOCGIWSENS: + wrq->u.sens.value = config.rssiThreshold; + wrq->u.sens.disabled = (wrq->u.sens.value == 0); + wrq->u.sens.fixed = 1; + break; + + case SIOCSIWSENS: + config.rssiThreshold = wrq->u.sens.disabled ? RSSI_DEFAULT : wrq->u.sens.value; + local->need_commit = 1; + break; + + case SIOCGIWAPLIST: + if (wrq->u.data.pointer) { + int i; + struct sockaddr s[4]; + + for (i = 0; i < 4; i++) { + memcpy(s[i].sa_data, status_rid.bssid[i], 6); + s[i].sa_family = ARPHRD_ETHER; + } + wrq->u.data.length = 4; + if (copy_to_user(wrq->u.data.pointer, &s, sizeof(s))) + rc = -EFAULT; + } + break; + +#ifdef WIRELESS_SPY + // Set the spy list + case SIOCSIWSPY: + if (wrq->u.data.length > IW_MAX_SPY) + { + rc = -E2BIG; + break; + } + local->spy_number = wrq->u.data.length; + if (local->spy_number > 0) + { + struct sockaddr address[IW_MAX_SPY]; + int i; + + if (copy_from_user(address, wrq->u.data.pointer, + sizeof(struct sockaddr) * local->spy_number)) { + rc = -EFAULT; + break; + } + 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)) + { + 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) + break; + for (i=0; ispy_number; i++) + { + memcpy(address[i].sa_data, local->spy_address[i], 6); + address[i].sa_family = AF_UNIX; + } + copy_to_user(wrq->u.data.pointer, address, sizeof(struct sockaddr) * local->spy_number); + copy_to_user(wrq->u.data.pointer + (sizeof(struct sockaddr)*local->spy_number), local->spy_stat, sizeof(struct iw_quality) * local->spy_number); + for (i=0; ispy_number; i++) + local->spy_stat[i].updated = 0; + } + 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" }, + }; + + /* Set the number of ioctl available */ + wrq->u.data.length = 2; + + /* Copy structure to the user buffer */ + if(copy_to_user(wrq->u.data.pointer, (u_char *) priv, + sizeof(priv))) + rc = -EFAULT; + } + break; +#endif /* CISCO_EXT */ +#endif /* WIRELESS_EXT */ + +#ifdef CISCO_EXT + case AIROIDIFC: + { + int val = AIROMAGIC; + aironet_ioctl com; + if (copy_from_user(&com,rq->ifr_data,sizeof(com))) + rc = -EFAULT; + else if (copy_to_user(com.data,(char *)&val,sizeof(val))) + rc = -EFAULT; + } + break; + + case AIROIOCTL: + /* Get the command struct and hand it off for evaluation by + * the proper subfunction + */ + { + aironet_ioctl com; + copy_from_user(&com,rq->ifr_data,sizeof(com)); + + /* Seperate R/W functions bracket legality here + */ + if ( com.command <= AIROGSTATSD32 ) + rc = readrids(dev,&com); + else if ( com.command >= AIROPCAP && com.command <= AIROPLEAPUSR ) + rc = writerids(dev,&com); + else if ( com.command >= AIROFLSHRST && com.command <= AIRORESTART ) + rc = flashcard(dev,&com); + else + rc = -EINVAL; /* Bad command in ioctl */ + } + break; +#endif /* CISCO_EXT */ + + // All other calls are currently unsupported + default: + rc = -EOPNOTSUPP; + } + +#ifdef WIRELESS_EXT + /* 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 */ + + return(rc); +} + +#ifdef WIRELESS_EXT +/* + * Get the Wireless stats out of the driver + * Note : irq and spinlock protection will occur in the subroutines + * + * TODO : + * o Check if work in Ad-Hoc mode (otherwise, use SPY, as in wvlan_cs) + * o Find the noise level + * o Convert values to dBm + * o Fill out discard.misc with something interesting + * + * Jean + */ +struct iw_statistics *airo_get_wireless_stats(struct net_device *dev) +{ + struct airo_info *local = (struct airo_info*) dev->priv; + StatusRid status_rid; + StatsRid stats_rid; + int *vals = stats_rid.vals; + + /* Get stats out of the card */ + readStatusRid(local, &status_rid); + readStatsRid(local, &stats_rid, RID_STATS); + + /* The status */ + local->wstats.status = status_rid.mode; + + /* Signal quality and co. But where is the noise level ??? */ + local->wstats.qual.qual = status_rid.signalQuality; + local->wstats.qual.level = status_rid.normalizedSignalStrength; + local->wstats.qual.noise = 0; + local->wstats.qual.updated = 3; + + /* Packets discarded in the wireless adapter due to wireless + * specific problems */ + local->wstats.discard.nwid = vals[56] + vals[57] + vals[58];/* SSID Mismatch */ + local->wstats.discard.code = vals[6];/* RxWepErr */ + local->wstats.discard.misc = vals[1] + vals[2] + vals[3] + vals[4] + vals[30] + vals[32]; + return (&local->wstats); +} +#endif /* WIRELESS_EXT */ + +#ifdef CISCO_EXT +/* + * This just translates from driver IOCTL codes to the command codes to + * feed to the radio's host interface. Things can be added/deleted + * as needed. This represents the READ side of control I/O to + * the card + */ +static int readrids(struct net_device *dev, aironet_ioctl *comp) { + unsigned short ridcode; + unsigned char iobuf[2048]; + + switch(comp->command) + { + case AIROGCAP: ridcode = RID_CAPABILITIES; break; + case AIROGCFG: ridcode = RID_CONFIG; break; + case AIROGSLIST: ridcode = RID_SSID; break; + case AIROGVLIST: ridcode = RID_APLIST; break; + case AIROGDRVNAM: ridcode = RID_DRVNAME; break; + case AIROGEHTENC: ridcode = RID_ETHERENCAP; break; + case AIROGWEPKTMP: ridcode = RID_WEP_TEMP; + /* Only super-user can read WEP keys */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + break; + case AIROGWEPKNV: ridcode = RID_WEP_PERM; + /* Only super-user can read WEP keys */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + break; + case AIROGSTAT: ridcode = RID_STATUS; break; + case AIROGSTATSD32: ridcode = RID_STATSDELTA; break; + case AIROGSTATSC32: ridcode = RID_STATS; break; + default: + return -EINVAL; + break; + } + + PC4500_readrid((struct airo_info *)dev->priv,ridcode,iobuf,sizeof(iobuf)); + /* get the count of bytes in the rid docs say 1st 2 bytes is it. + * then return it to the user + * 9/22/2000 Honor user given length + */ + + if (copy_to_user(comp->data, iobuf, min (comp->len, sizeof(iobuf)))) + return -EFAULT; + return 0; +} + +/* + * Danger Will Robinson write the rids here + */ + +static int writerids(struct net_device *dev, aironet_ioctl *comp) { + int ridcode; + Resp rsp; + static int (* writer)(struct airo_info *, u16 rid, const void *, int); + unsigned char iobuf[2048]; + + /* Only super-user can write RIDs */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + ridcode = 0; + writer = do_writerid; + + switch(comp->command) + { + 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 AIROPWEPKEYNV: ridcode = RID_WEP_PERM; break; + case AIROPLEAPUSR: ridcode = RID_LEAPUSERNAME; break; + case AIROPLEAPPWD: ridcode = RID_LEAPPASSWORD; break; + case AIROPWEPKEY: ridcode = RID_WEP_TEMP; writer = PC4500_writerid; + break; + + /* this is not really a rid but a command given to the card + * same with MAC off + */ + case AIROPMACON: + if (enable_MAC(dev->priv, &rsp) != 0) + return -EIO; + return 0; + + /* + * Evidently this code in the airo driver does not get a symbol + * as disable_MAC. it's probably so short the compiler does not gen one. + */ + case AIROPMACOFF: + disable_MAC(dev->priv); + return 0; + + /* This command merely clears the counts does not actually store any data + * only reads rid. But as it changes the cards state, I put it in the + * writerid routines. + */ + case AIROPSTCLR: + ridcode = RID_STATSDELTACLEAR; + + PC4500_readrid(dev->priv,ridcode,iobuf,sizeof(iobuf)); + + if (copy_to_user(comp->data,iobuf,min(comp->len,sizeof(iobuf)))) + return -EFAULT; + return 0; + + default: + return -EOPNOTSUPP; /* Blarg! */ + } + if(comp->len > sizeof(iobuf)) + return -EINVAL; + + copy_from_user(iobuf,comp->data,comp->len); + if((*writer)((struct airo_info *)dev->priv, ridcode, iobuf,comp->len)) + return -EIO; + return 0; +} + +/***************************************************************************** + * Ancillary flash / mod functions much black magic lurkes here * + ***************************************************************************** + */ + +/* + * Flash command switch table + */ + +int flashcard(struct net_device *dev, aironet_ioctl *comp) { + int z; + int cmdreset(struct airo_info *); + int setflashmode(struct airo_info *); + int flashgchar(struct airo_info *,int,int); + int flashpchar(struct airo_info *,int,int); + int flashputbuf(struct airo_info *, unsigned short *); + int flashrestart(struct airo_info *,struct net_device *); + unsigned short * flashbuffer; + + /* Only super-user can modify flash */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + switch(comp->command) + { + case AIROFLSHRST: + return cmdreset((struct airo_info *)dev->priv); + + case AIROFLSHSTFL: + return setflashmode((struct airo_info *)dev->priv); + + case AIROFLSHGCHR: /* Get char from aux */ + if(comp->len != sizeof(int)) + return -EINVAL; + copy_from_user(&z,comp->data,comp->len); + return flashgchar((struct airo_info *)dev->priv,z,8000); + + case AIROFLSHPCHR: /* Send char to card. */ + if(comp->len != sizeof(int)) + return -EINVAL; + copy_from_user(&z,comp->data,comp->len); + return flashpchar((struct airo_info *)dev->priv,z,8000); + + case AIROFLPUTBUF: /* Send 32k to card */ + if(comp->len > FLASHSIZE) + return -EINVAL; + if ((flashbuffer = kmalloc (FLASHSIZE, GFP_KERNEL)) == NULL) + return -ENOMEM; + if(copy_from_user(flashbuffer,comp->data,comp->len)) { + kfree (flashbuffer); + return -EINVAL; + } + + flashputbuf((struct airo_info *)dev->priv,flashbuffer); + kfree (flashbuffer); + return 0; + + case AIRORESTART: + if(flashrestart((struct airo_info *)dev->priv,dev)) + return -EIO; + return 0; + } + return -EINVAL; +} + +#define FLASH_COMMAND 0x7e7e + +/* + * STEP 1) + * Disable MAC and do soft reset on + * card. + */ + +int cmdreset(struct airo_info *ai) { + int flags; + + disable_MAC(ai); + + spin_lock_irqsave(&ai->cmd_lock, flags); + if(!waitbusy (ai)){ + printk(KERN_INFO "Waitbusy hang before RESET\n"); + return -EBUSY; + } + + OUT4500(ai,COMMAND,CMD_SOFTRESET); + + set_current_state (TASK_UNINTERRUPTIBLE); + schedule_timeout (HZ); /* WAS 600 12/7/00 */ + + if(!waitbusy (ai)){ + printk(KERN_INFO "Waitbusy hang AFTER RESET\n"); + return -EBUSY; + } + spin_unlock_irqrestore(&ai->cmd_lock, flags); + return 0; +} + +/* STEP 2) + * Put the card in legendary flash + * mode + */ + +int setflashmode (struct airo_info *ai) { + int flags; + + spin_lock_irqsave(&ai->cmd_lock, flags); + OUT4500(ai, SWS0, FLASH_COMMAND); + OUT4500(ai, SWS1, FLASH_COMMAND); + OUT4500(ai, SWS0, FLASH_COMMAND); + OUT4500(ai, COMMAND,0x10); + set_current_state (TASK_UNINTERRUPTIBLE); + schedule_timeout (HZ/2); /* 500ms delay */ + spin_unlock_irqrestore(&ai->cmd_lock, flags); + + if(!waitbusy(ai)) { + printk(KERN_INFO "Waitbusy hang after setflash mode\n"); + return -EIO; + } + return 0; +} + +/* Put character to SWS0 wait for dwelltime + * x 50us for echo . + */ + +int flashpchar(struct airo_info *ai,int byte,int dwelltime) { + int echo; + int waittime; + + byte |= 0x8000; + + if(dwelltime == 0 ) + dwelltime = 200; + + waittime=dwelltime; + + /* Wait for busy bit d15 to go false indicating buffer empty */ + while ((IN4500 (ai, SWS0) & 0x8000) && waittime > 0) { + udelay (50); + waittime -= 50; + } + + /* timeout for busy clear wait */ + if(waittime <= 0 ){ + printk(KERN_INFO "flash putchar busywait timeout! \n"); + return -EBUSY; + } + + /* Port is clear now write byte and wait for it to echo back */ + do { + OUT4500(ai,SWS0,byte); + udelay(50); + dwelltime -= 50; + echo = IN4500(ai,SWS1); + } while (dwelltime >= 0 && echo != byte); + + OUT4500(ai,SWS1,0); + + return (echo == byte) ? 0 : -EIO; +} + +/* + * Get a character from the card matching matchbyte + * Step 3) + */ +int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime){ + int rchar; + unsigned char rbyte=0; + + do { + rchar = IN4500(ai,SWS1); + + if(dwelltime && !(0x8000 & rchar)){ + dwelltime -= 10; + mdelay(10); + continue; + } + rbyte = 0xff & rchar; + + if( (rbyte == matchbyte) && (0x8000 & rchar) ){ + OUT4500(ai,SWS1,0); + return 0; + } + if( rbyte == 0x81 || rbyte == 0x82 || rbyte == 0x83 || rbyte == 0x1a || 0xffff == rchar) + break; + OUT4500(ai,SWS1,0); + + }while(dwelltime > 0); + return -EIO; +} + +/* + * Transfer 32k of firmware data from user buffer to our buffer and + * send to the card + */ + +int flashputbuf(struct airo_info *ai, unsigned short *bufp){ + int nwords; + + /* Write stuff */ + OUT4500(ai,AUXPAGE,0x100); + OUT4500(ai,AUXOFF,0); + + for(nwords=0;nwords != FLASHSIZE / 2;nwords++){ + OUT4500(ai,AUXDATA,bufp[nwords] & 0xffff); + } + + OUT4500(ai,SWS0,0x8000); + + return 0; +} + +/* + * + */ +int flashrestart(struct airo_info *ai,struct net_device *dev){ + int i,status; + + 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); + + for( i = 0; i < MAX_FIDS; i++ ) { + ai->fids[i] = transmit_allocate( ai, 2312 ); + } + + set_current_state (TASK_UNINTERRUPTIBLE); + schedule_timeout (HZ); /* Added 12/7/00 */ + return status; +} +#endif /* CISCO_EXT */ + +/* + 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. + + In addition: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +module_init(airo_init_module); +module_exit(airo_cleanup_module); diff -u --recursive --new-file v2.4.5/linux/drivers/net/wireless/airo_cs.c linux/drivers/net/wireless/airo_cs.c --- v2.4.5/linux/drivers/net/wireless/airo_cs.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/wireless/airo_cs.c Wed Jun 20 11:10:53 2001 @@ -0,0 +1,691 @@ +/*====================================================================== + + Aironet driver for 4500 and 4800 series cards + + This code is released under both the GPL version 2 and BSD licenses. + Either license may be used. The respective licenses are found at + the end of this file. + + This code was developed by Benjamin Reed + including portions of which come from the Aironet PC4500 + Developer's Reference Manual and used with permission. Copyright + (C) 1999 Benjamin Reed. All Rights Reserved. Permission to use + code in the Developer's manual was granted for this driver by + Aironet. + + In addition this module was derived from dummy_cs. + The initial developer of dummy_cs is David A. Hinds + . Portions created by David A. Hinds + are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + +======================================================================*/ + +#include +#ifdef __IN_PCMCIA_PACKAGE__ +#include +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* + All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If + you do not define PCMCIA_DEBUG at all, all the debug code will be + left out. If you compile with PCMCIA_DEBUG=0, the debug code will + be present but disabled -- but it can then be enabled for specific + modules at load time with a 'pc_debug=#' option to insmod. +*/ +#ifdef PCMCIA_DEBUG +static int pc_debug = PCMCIA_DEBUG; +MODULE_PARM(pc_debug, "i"); +static char *version = "$Revision: 1.1.18.1 $"; +#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args); +#else +#define DEBUG(n, args...) +#endif + +/*====================================================================*/ + +/* Parameters that can be set with 'insmod' */ + +/* The old way: bit map of interrupts to choose from */ +/* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */ +static u_int irq_mask = 0xdeb8; +/* Newer, simpler way of listing specific interrupts */ +static int irq_list[4] = { -1 }; + +MODULE_AUTHOR("Benjamin Reed"); +MODULE_DESCRIPTION("Support for Cisco/Aironet 802.11 wireless ethernet \ + cards. This is the module that links the PCMCIA card \ + with the airo module."); +MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340 PCMCIA cards"); +MODULE_PARM(irq_mask, "i"); +MODULE_PARM(irq_list, "1-4i"); + +/*====================================================================*/ + +/* + The event() function is this driver's Card Services event handler. + It will be called by Card Services when an appropriate card status + event is received. The config() and release() entry points are + used to configure or release a socket, in response to card + insertion and ejection events. They are invoked from the airo_cs + event handler. +*/ + +struct net_device *init_airo_card( int, int, int ); +void stop_airo_card( struct net_device *, int ); +int reset_airo_card( struct net_device * ); + +static void airo_config(dev_link_t *link); +static void airo_release(u_long arg); +static int airo_event(event_t event, int priority, + event_callback_args_t *args); + +/* + The attach() and detach() entry points are used to create and destroy + "instances" of the driver, where each instance represents everything + needed to manage one actual PCMCIA card. +*/ + +static dev_link_t *airo_attach(void); +static void airo_detach(dev_link_t *); + +/* + You'll also need to prototype all the functions that will actually + be used to talk to your device. See 'pcmem_cs' for a good example + of a fully self-sufficient driver; the other drivers rely more or + less on other parts of the kernel. +*/ + +/* + The dev_info variable is the "key" that is used to match up this + device driver with appropriate cards, through the card configuration + database. +*/ + +static dev_info_t dev_info = "airo_cs"; + +/* + A linked list of "instances" of the aironet device. Each actual + PCMCIA card corresponds to one device instance, and is described + by one dev_link_t structure (defined in ds.h). + + You may not want to use a linked list for this -- for example, the + memory card driver uses an array of dev_link_t pointers, where minor + device numbers are used to derive the corresponding array index. +*/ + +static dev_link_t *dev_list = NULL; + +/* + A dev_link_t structure has fields for most things that are needed + to keep track of a socket, but there will usually be some device + specific information that also needs to be kept track of. The + 'priv' pointer in a dev_link_t structure can be used to point to + a device-specific private data structure, like this. + + A driver needs to provide a dev_node_t structure for each device + on a card. In some cases, there is only one device per card (for + example, ethernet cards, modems). In other cases, there may be + many actual or logical devices (SCSI adapters, memory cards with + multiple partitions). The dev_node_t structures need to be kept + in a linked list starting at the 'dev' field of a dev_link_t + structure. We allocate them in the card's private data structure, + because they generally shouldn't be allocated dynamically. + + In this case, we also provide a flag to indicate if a device is + "stopped" due to a power management event, or card ejection. The + device IO routines can use a flag like this to throttle IO to a + card that is not ready to accept it. +*/ + +typedef struct local_info_t { + dev_node_t node; + struct net_device *eth_dev; +} local_info_t; + +/*====================================================================*/ + +static void cs_error(client_handle_t handle, int func, int ret) +{ + error_info_t err = { func, ret }; + CardServices(ReportError, handle, &err); +} + +/*====================================================================== + + This bit of code is used to avoid unregistering network devices + at inappropriate times. 2.2 and later kernels are fairly picky + about when this can happen. + + ======================================================================*/ + +static void flush_stale_links(void) +{ + dev_link_t *link, *next; + for (link = dev_list; link; link = next) { + next = link->next; + if (link->state & DEV_STALE_LINK) + airo_detach(link); + } +} + +/*====================================================================== + + airo_attach() creates an "instance" of the driver, allocating + local data structures for one device. The device is registered + with Card Services. + + The dev_link structure is initialized, but we don't actually + configure the card at this point -- we wait until we receive a + card insertion event. + + ======================================================================*/ + +static dev_link_t *airo_attach(void) +{ + client_reg_t client_reg; + dev_link_t *link; + local_info_t *local; + int ret, i; + + DEBUG(0, "airo_attach()\n"); + flush_stale_links(); + + /* Initialize the dev_link_t structure */ + link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); + if (!link) { + printk(KERN_ERR "airo_cs: no memory for new device\n"); + return NULL; + } + memset(link, 0, sizeof(struct dev_link_t)); + link->release.function = &airo_release; + link->release.data = (u_long)link; + + /* Interrupt setup */ + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID; + if (irq_list[0] == -1) + link->irq.IRQInfo2 = irq_mask; + else + for (i = 0; i < 4; i++) + link->irq.IRQInfo2 |= 1 << irq_list[i]; + link->irq.Handler = NULL; + + /* + General socket configuration defaults can go here. In this + client, we assume very little, and rely on the CIS for almost + everything. In most clients, many details (i.e., number, sizes, + and attributes of IO windows) are fixed by the nature of the + device, and can be hard-wired here. + */ + link->conf.Attributes = 0; + link->conf.Vcc = 50; + link->conf.IntType = INT_MEMORY_AND_IO; + + /* Allocate space for private device-specific data */ + local = kmalloc(sizeof(local_info_t), GFP_KERNEL); + memset(local, 0, sizeof(local_info_t)); + link->priv = local; + + /* Register with Card Services */ + link->next = dev_list; + dev_list = link; + client_reg.dev_info = &dev_info; + client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; + client_reg.EventMask = + CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | + CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | + CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; + client_reg.event_handler = &airo_event; + client_reg.Version = 0x0210; + client_reg.event_callback_args.client_data = link; + ret = CardServices(RegisterClient, &link->handle, &client_reg); + if (ret != 0) { + cs_error(link->handle, RegisterClient, ret); + airo_detach(link); + return NULL; + } + + return link; +} /* airo_attach */ + +/*====================================================================== + + This deletes a driver "instance". The device is de-registered + with Card Services. If it has been released, all local data + structures are freed. Otherwise, the structures will be freed + when the device is released. + + ======================================================================*/ + +static void airo_detach(dev_link_t *link) +{ + dev_link_t **linkp; + + DEBUG(0, "airo_detach(0x%p)\n", link); + + /* Locate device structure */ + for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) + if (*linkp == link) break; + if (*linkp == NULL) + return; + + del_timer(&link->release); + if ( link->state & DEV_CONFIG ) { + airo_release( (int)link ); + if ( link->state & DEV_STALE_CONFIG ) { + link->state |= DEV_STALE_LINK; + return; + } + } + + if ( ((local_info_t*)link->priv)->eth_dev ) { + stop_airo_card( ((local_info_t*)link->priv)->eth_dev, 0 ); + } + ((local_info_t*)link->priv)->eth_dev = 0; + + /* Break the link with Card Services */ + if (link->handle) + CardServices(DeregisterClient, link->handle); + + + + /* Unlink device structure, free pieces */ + *linkp = link->next; + if (link->priv) { + kfree(link->priv); + } + kfree(link); + +} /* airo_detach */ + +/*====================================================================== + + airo_config() is scheduled to run after a CARD_INSERTION event + is received, to configure the PCMCIA socket, and to make the + device available to the system. + + ======================================================================*/ + +#define CS_CHECK(fn, args...) \ +while ((last_ret=CardServices(last_fn=(fn),args))!=0) goto cs_failed + +#define CFG_CHECK(fn, args...) \ +if (CardServices(fn, args) != 0) goto next_entry + +static void airo_config(dev_link_t *link) +{ + client_handle_t handle; + tuple_t tuple; + cisparse_t parse; + local_info_t *dev; + int last_fn, last_ret; + u_char buf[64]; + win_req_t req; + memreq_t map; + + handle = link->handle; + dev = link->priv; + + DEBUG(0, "airo_config(0x%p)\n", link); + + /* + This reads the card's CONFIG tuple to find its configuration + registers. + */ + tuple.DesiredTuple = CISTPL_CONFIG; + tuple.Attributes = 0; + tuple.TupleData = buf; + tuple.TupleDataMax = sizeof(buf); + tuple.TupleOffset = 0; + CS_CHECK(GetFirstTuple, handle, &tuple); + CS_CHECK(GetTupleData, handle, &tuple); + CS_CHECK(ParseTuple, handle, &tuple, &parse); + link->conf.ConfigBase = parse.config.base; + link->conf.Present = parse.config.rmask[0]; + + /* Configure card */ + link->state |= DEV_CONFIG; + + /* + In this loop, we scan the CIS for configuration table entries, + each of which describes a valid card configuration, including + voltage, IO window, memory window, and interrupt settings. + + We make no assumptions about the card to be configured: we use + just the information available in the CIS. In an ideal world, + this would work for any PCMCIA card, but it requires a complete + and accurate CIS. In practice, a driver usually "knows" most of + these things without consulting the CIS, and most client drivers + will only use the CIS to fill in implementation-defined details. + */ + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + CS_CHECK(GetFirstTuple, handle, &tuple); + while (1) { + cistpl_cftable_entry_t dflt = { 0 }; + cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); + CFG_CHECK(GetTupleData, handle, &tuple); + CFG_CHECK(ParseTuple, handle, &tuple, &parse); + + if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; + if (cfg->index == 0) goto next_entry; + link->conf.ConfigIndex = cfg->index; + + /* Does this card need audio output? */ + if (cfg->flags & CISTPL_CFTABLE_AUDIO) { + link->conf.Attributes |= CONF_ENABLE_SPKR; + link->conf.Status = CCSR_AUDIO_ENA; + } + + /* Use power settings for Vcc and Vpp if present */ + /* Note that the CIS values need to be rescaled */ + if (cfg->vcc.present & (1<conf.Vcc = cfg->vcc.param[CISTPL_POWER_VNOM]/10000; + else if (dflt.vcc.present & (1<conf.Vcc = dflt.vcc.param[CISTPL_POWER_VNOM]/10000; + + if (cfg->vpp1.present & (1<conf.Vpp1 = link->conf.Vpp2 = + cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; + else if (dflt.vpp1.present & (1<conf.Vpp1 = link->conf.Vpp2 = + dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; + + /* Do we need to allocate an interrupt? */ + if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) + link->conf.Attributes |= CONF_ENABLE_IRQ; + + /* IO window settings */ + link->io.NumPorts1 = link->io.NumPorts2 = 0; + if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { + cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; + if (!(io->flags & CISTPL_IO_8BIT)) + link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; + if (!(io->flags & CISTPL_IO_16BIT)) + link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + link->io.BasePort1 = io->win[0].base; + link->io.NumPorts1 = io->win[0].len; + if (io->nwin > 1) { + link->io.Attributes2 = link->io.Attributes1; + link->io.BasePort2 = io->win[1].base; + link->io.NumPorts2 = io->win[1].len; + } + } + + /* This reserves IO space but doesn't actually enable it */ + CFG_CHECK(RequestIO, link->handle, &link->io); + + /* + Now set up a common memory window, if needed. There is room + in the dev_link_t structure for one memory window handle, + but if the base addresses need to be saved, or if multiple + windows are needed, the info should go in the private data + structure for this device. + + Note that the memory window base is a physical address, and + needs to be mapped to virtual space with ioremap() before it + is used. + */ + if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) { + cistpl_mem_t *mem = + (cfg->mem.nwin) ? &cfg->mem : &dflt.mem; + req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM; + req.Base = mem->win[0].host_addr; + req.Size = mem->win[0].len; + req.AccessSpeed = 0; + link->win = (window_handle_t)link->handle; + CFG_CHECK(RequestWindow, &link->win, &req); + map.Page = 0; map.CardOffset = mem->win[0].card_addr; + CFG_CHECK(MapMemPage, link->win, &map); + } + /* If we got this far, we're cool! */ + break; + + next_entry: + CS_CHECK(GetNextTuple, handle, &tuple); + } + + /* + Allocate an interrupt line. Note that this does not assign a + handler to the interrupt, unless the 'Handler' member of the + irq structure is initialized. + */ + if (link->conf.Attributes & CONF_ENABLE_IRQ) + CS_CHECK(RequestIRQ, link->handle, &link->irq); + + /* + This actually configures the PCMCIA socket -- setting up + the I/O windows and the interrupt mapping, and putting the + card and host interface into "Memory and IO" mode. + */ + CS_CHECK(RequestConfiguration, link->handle, &link->conf); + ((local_info_t*)link->priv)->eth_dev = + init_airo_card( link->irq.AssignedIRQ, + link->io.BasePort1, 1 ); + if (!((local_info_t*)link->priv)->eth_dev) goto cs_failed; + + /* + At this point, the dev_node_t structure(s) need to be + initialized and arranged in a linked list at link->dev. + */ + strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name ); + dev->node.major = dev->node.minor = 0; + link->dev = &dev->node; + + /* Finally, report what we've done */ + printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d", + dev->node.dev_name, link->conf.ConfigIndex, + link->conf.Vcc/10, link->conf.Vcc%10); + if (link->conf.Vpp1) + printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10); + if (link->conf.Attributes & CONF_ENABLE_IRQ) + printk(", irq %d", link->irq.AssignedIRQ); + if (link->io.NumPorts1) + printk(", io 0x%04x-0x%04x", link->io.BasePort1, + link->io.BasePort1+link->io.NumPorts1-1); + if (link->io.NumPorts2) + printk(" & 0x%04x-0x%04x", link->io.BasePort2, + link->io.BasePort2+link->io.NumPorts2-1); + if (link->win) + printk(", mem 0x%06lx-0x%06lx", req.Base, + req.Base+req.Size-1); + printk("\n"); + + link->state &= ~DEV_CONFIG_PENDING; + return; + + cs_failed: + cs_error(link->handle, last_fn, last_ret); + airo_release((u_long)link); + +} /* airo_config */ + +/*====================================================================== + + After a card is removed, airo_release() will unregister the + device, and release the PCMCIA configuration. If the device is + still open, this will be postponed until it is closed. + + ======================================================================*/ + +static void airo_release(u_long arg) +{ + dev_link_t *link = (dev_link_t *)arg; + + DEBUG(0, "airo_release(0x%p)\n", link); + + /* + If the device is currently in use, we won't release until it + is actually closed, because until then, we can't be sure that + no one will try to access the device or its data structures. + */ + if (link->open) { + DEBUG(1, "airo_cs: release postponed, '%s' still open\n", + link->dev->dev_name); + link->state |= DEV_STALE_CONFIG; + return; + } + + /* Unlink the device chain */ + link->dev = NULL; + + /* + In a normal driver, additional code may be needed to release + other kernel data structures associated with this device. + */ + + /* Don't bother checking to see if these succeed or not */ + if (link->win) + CardServices(ReleaseWindow, link->win); + CardServices(ReleaseConfiguration, link->handle); + if (link->io.NumPorts1) + CardServices(ReleaseIO, link->handle, &link->io); + if (link->irq.AssignedIRQ) + CardServices(ReleaseIRQ, link->handle, &link->irq); + link->state &= ~DEV_CONFIG; + +} /* airo_release */ + +/*====================================================================== + + The card status event handler. Mostly, this schedules other + stuff to run after an event is received. + + When a CARD_REMOVAL event is received, we immediately set a + private flag to block future accesses to this device. All the + functions that actually access the device should check this flag + to make sure the card is still present. + + ======================================================================*/ + +static int airo_event(event_t event, int priority, + event_callback_args_t *args) +{ + dev_link_t *link = args->client_data; + local_info_t *local = link->priv; + + DEBUG(1, "airo_event(0x%06x)\n", event); + + switch (event) { + case CS_EVENT_CARD_REMOVAL: + link->state &= ~DEV_PRESENT; + if (link->state & DEV_CONFIG) { + netif_device_detach(local->eth_dev); + mod_timer(&link->release, jiffies + HZ/20); + } + break; + case CS_EVENT_CARD_INSERTION: + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + airo_config(link); + break; + case CS_EVENT_PM_SUSPEND: + link->state |= DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_RESET_PHYSICAL: + if (link->state & DEV_CONFIG) { + netif_device_detach(local->eth_dev); + CardServices(ReleaseConfiguration, link->handle); + } + break; + case CS_EVENT_PM_RESUME: + link->state &= ~DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_CARD_RESET: + if (link->state & DEV_CONFIG) { + CardServices(RequestConfiguration, link->handle, &link->conf); + reset_airo_card(local->eth_dev); + netif_device_attach(local->eth_dev); + } + break; + } + return 0; +} /* airo_event */ + +/*====================================================================*/ + +static int airo_cs_init(void) +{ + servinfo_t serv; + DEBUG(0, "%s\n", version); + CardServices(GetCardServicesInfo, &serv); + if (serv.Revision != CS_RELEASE_CODE) { + printk(KERN_NOTICE "airo_cs: Card Services release " + "does not match!\n"); + return -1; + } + register_pcmcia_driver(&dev_info, &airo_attach, &airo_detach); + return 0; +} + +static void airo_cs_cleanup(void) +{ + DEBUG(0, "airo_cs: unloading\n"); + unregister_pcmcia_driver(&dev_info); + while (dev_list != NULL) { + if (dev_list->state & DEV_CONFIG) + airo_release((u_long)dev_list); + airo_detach(dev_list); + } +} + +/* + 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. + + In addition: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +module_init(airo_cs_init); +module_exit(airo_cs_cleanup); diff -u --recursive --new-file v2.4.5/linux/drivers/net/wireless/hermes.c linux/drivers/net/wireless/hermes.c --- v2.4.5/linux/drivers/net/wireless/hermes.c Mon May 7 19:42:14 2001 +++ linux/drivers/net/wireless/hermes.c Mon Jun 11 19:15:27 2001 @@ -32,9 +32,10 @@ #include "hermes.h" +/* These are maximum timeouts. Most often, card wil react much faster */ #define CMD_BUSY_TIMEOUT (100) /* In iterations of ~1us */ #define CMD_INIT_TIMEOUT (50000) /* in iterations of ~10us */ -#define CMD_COMPL_TIMEOUT (10000) /* in iterations of ~10us */ +#define CMD_COMPL_TIMEOUT (20000) /* in iterations of ~10us */ #define ALLOC_COMPL_TIMEOUT (1000) /* in iterations of ~10us */ #define BAP_BUSY_TIMEOUT (500) /* In iterations of ~1us */ #define BAP_ERROR_RETRY (10) /* How many times to retry a BAP seek when there is an error */ @@ -141,6 +142,12 @@ /* No need to explicitly handle the timeout - hermes_issue_cmd() will probably return -EBUSY */ + /* According to the documentation, EVSTAT may contain + obsolete event occurrence information. We have to acknowledge + it by writing EVACK. */ + reg = hermes_read_regn(hw, EVSTAT); + hermes_write_regn(hw, EVACK, reg); + /* We don't use hermes_docmd_wait here, because the reset wipes the magic constant in SWSUPPORT0 away, and it gets confused */ err = hermes_issue_cmd(hw, HERMES_CMD_INIT, 0); @@ -323,8 +330,10 @@ reg = hermes_read_reg(hw, oreg); } - if (reg & HERMES_OFFSET_BUSY) + if (reg & HERMES_OFFSET_BUSY) { + DEBUG(0,"hermes_bap_seek: returning ETIMEDOUT...\n"); return -ETIMEDOUT; + } /* For some reason, seeking the BAP seems to randomly fail somewhere (firmware bug?). We retry a few times before giving up. */ diff -u --recursive --new-file v2.4.5/linux/drivers/net/wireless/hermes.h linux/drivers/net/wireless/hermes.h --- v2.4.5/linux/drivers/net/wireless/hermes.h Mon May 7 19:42:14 2001 +++ linux/drivers/net/wireless/hermes.h Mon Jun 11 19:15:27 2001 @@ -166,7 +166,6 @@ #define HERMES_RID_CNF_NICKNAME (0xfc0e) #define HERMES_RID_CNF_WEP_ON (0xfc20) #define HERMES_RID_CNF_MWO_ROBUST (0xfc25) -#define HERMES_RID_CNF_PRISM2_WEP_ON (0xfc28) #define HERMES_RID_CNF_MULTICAST_LIST (0xfc80) #define HERMES_RID_CNF_CREATEIBSS (0xfc81) #define HERMES_RID_CNF_FRAG_THRESH (0xfc82) @@ -177,6 +176,7 @@ #define HERMES_RID_CNF_TX_KEY (0xfcb1) #define HERMES_RID_CNF_TICKTIME (0xfce0) +#define HERMES_RID_CNF_PRISM2_WEP_ON (0xfc28) #define HERMES_RID_CNF_PRISM2_TX_KEY (0xfc23) #define HERMES_RID_CNF_PRISM2_KEY0 (0xfc24) #define HERMES_RID_CNF_PRISM2_KEY1 (0xfc25) diff -u --recursive --new-file v2.4.5/linux/drivers/net/wireless/orinoco.c linux/drivers/net/wireless/orinoco.c --- v2.4.5/linux/drivers/net/wireless/orinoco.c Mon May 7 19:42:14 2001 +++ linux/drivers/net/wireless/orinoco.c Mon Jun 11 19:15:27 2001 @@ -1,4 +1,4 @@ -/* orinoco.c 0.05 - (formerly known as dldwd_cs.c and orinoco_cs.c) +/* orinoco.c 0.06 - (formerly known as dldwd_cs.c and orinoco_cs.c) * * A driver for "Hermes" chipset based PCMCIA wireless adaptors, such * as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/ @@ -144,10 +144,32 @@ * (note : the memcmp bug was mine - fixed) * o Remove set_retry stuff, no firmware support it (bloat--). * + * v0.05d -> v0.06 - 25/5/2001 - Jean II + * Original patch from "Hong Lin" , + * "Ian Kinner" + * and "David Smith" + * o Init of priv->tx_rate_ctrl in firmware specific section. + * o Prism2/Symbol rate, upto should be 0xF and not 0x15. Doh ! + * o Spectrum card always need cor_reset (for every reset) + * o Fix cor_reset to not loose bit 7 in the register + * o flush_stale_links to remove zombie Pcmcia instances + * o Ack previous hermes event before reset + * Me (with my little hands) + * o Allow orinoco.c to call cor_reset via priv->card_reset_handler + * o Add priv->need_card_reset to toggle this feature + * o Fix various buglets when setting WEP in Symbol firmware + * Now, encryption is fully functional on Symbol cards. Youpi ! + * + * v0.06 -> v0.06b - 25/5/2001 - Jean II + * o IBSS on Symbol use port_mode = 4. Please don't ask... + * + * v0.06b -> v0.06c - 29/5/2001 - Jean II + * o Show first spy address in /proc/net/wireless for IBSS mode as well + * * TODO - Jean II * o inline functions (lot's of candidate, need to reorder code) * o Test PrismII/Symbol cards & firmware versions - * o Mini-PCI support + * o Mini-PCI support (some people have reported success - JII) */ #include @@ -180,7 +202,7 @@ #include "hermes.h" #include "orinoco.h" -static char *version = "orinoco.c 0.05d (David Gibson and others)"; +static char *version = "orinoco.c 0.06c (David Gibson and others)"; /* Level of debugging. Used in the macros in orinoco.h */ #ifdef ORINOCO_DEBUG @@ -369,7 +391,11 @@ priv->port_type = 3; priv->allow_ibss = 0; } else { - priv->port_type = 1; + /* Symbol is different here */ + if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL) + priv->port_type = 4; + else + priv->port_type = 1; priv->allow_ibss = 1; } break; @@ -441,10 +467,15 @@ TRACE_ENTER(priv->ndev.name); + /* Stop other people bothering us */ dldwd_lock(priv); - __dldwd_stop_irqs(priv); + /* Check if we need a card reset */ + if((priv->need_card_reset) && (priv->card_reset_handler != NULL)) + priv->card_reset_handler(priv); + + /* Do standard firmware reset if we can */ err = __dldwd_hw_reset(priv); if (err) goto out; @@ -594,7 +625,8 @@ { hermes_t *hw = &priv->hw; int err = 0; - int extra_wep_flag = 0; + int master_wep_flag; + int auth_flag; switch (priv->firmware_type) { case FIRMWARE_TYPE_LUCENT: /* Lucent style WEP */ @@ -614,24 +646,29 @@ case FIRMWARE_TYPE_PRISM2: /* Prism II style WEP */ case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */ + master_wep_flag = 0; /* Off */ if (priv->wep_on) { char keybuf[LARGE_KEY_SIZE+1]; int keylen; int i; - + + /* Fudge around firmware weirdness */ + keylen = priv->keys[priv->tx_key].len; + /* Write all 4 keys */ for(i = 0; i < MAX_KEYS; i++) { - keylen = priv->keys[i].len; - keybuf[keylen] = '\0'; - memcpy(keybuf, priv->keys[i].data, keylen); + memset(keybuf, 0, sizeof(keybuf)); + memcpy(keybuf, priv->keys[i].data, + priv->keys[i].len); err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNF_PRISM2_KEY0 + i, - HERMES_BYTES_TO_RECLEN(keylen + 1), - &keybuf); + HERMES_BYTES_TO_RECLEN(keylen), + keybuf); if (err) return err; } + /* Write the index of the key used in transmission */ err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PRISM2_TX_KEY, priv->tx_key); if (err) @@ -642,30 +679,29 @@ if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL) { /* Symbol cards : set the authentication : * 0 -> no encryption, 1 -> open, - * 2 -> shared key, 3 -> shared key 128bit */ - if(priv->wep_restrict) { - if(priv->keys[priv->tx_key].len > - SMALL_KEY_SIZE) - extra_wep_flag = 3; - else - extra_wep_flag = 2; - } else - extra_wep_flag = 1; - err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_SYMBOL_AUTH_TYPE, priv->wep_restrict); + * 2 -> shared key + * 3 -> shared key 128 -> AP only */ + if(priv->wep_restrict) + auth_flag = 2; + else + auth_flag = 1; + err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_SYMBOL_AUTH_TYPE, auth_flag); if (err) return err; + /* Master WEP setting is always 3 */ + master_wep_flag = 3; } else { /* Prism2 card : we need to modify master * WEP setting */ if(priv->wep_restrict) - extra_wep_flag = 2; + master_wep_flag = 3; else - extra_wep_flag = 0; + master_wep_flag = 1; } } /* Master WEP setting : on/off */ - err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PRISM2_WEP_ON, (priv->wep_on | extra_wep_flag)); + err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PRISM2_WEP_ON, master_wep_flag); if (err) return err; break; @@ -1182,9 +1218,11 @@ dldwd_lock(priv); + /* Do standard firmware reset */ err = hermes_reset(hw); if (err != 0) { - printk(KERN_ERR "%s: failed to reset hardware\n", dev->name); + printk(KERN_ERR "%s: failed to reset hardware (err = %d)\n", + dev->name, err); goto out; } @@ -1209,6 +1247,8 @@ /* Lucent MAC : 00:60:1D:* & 00:02:2D:* */ priv->firmware_type = FIRMWARE_TYPE_LUCENT; + priv->tx_rate_ctrl = 0x3; /* 11 Mb/s auto */ + priv->need_card_reset = 0; priv->broken_reset = 0; priv->broken_allocate = 0; priv->has_port3 = 1; /* Still works in 7.28 */ @@ -1229,6 +1269,8 @@ /* Some D-Link cards report vendor 0x02... */ priv->firmware_type = FIRMWARE_TYPE_PRISM2; + priv->tx_rate_ctrl = 0xF; /* 11 Mb/s auto */ + priv->need_card_reset = 0; priv->broken_reset = 0; priv->broken_allocate = 0; priv->has_port3 = 1; @@ -1248,9 +1290,12 @@ /* Intel MAC : 00:02:B3:* */ /* 3Com MAC : 00:50:DA:* */ - /* FIXME : probably need to use SYMBOL_***ARY_VER - * to get proper firmware version */ + /* FIXME : we need to get Symbol firmware revision. + * I tried to use SYMBOL_***ARY_VER, but it didn't + * returned anything proper... */ priv->firmware_type = FIRMWARE_TYPE_SYMBOL; + priv->tx_rate_ctrl = 0xF; /* 11 Mb/s auto */ + priv->need_card_reset = 1; priv->broken_reset = 0; priv->broken_allocate = 1; priv->has_port3 = 1; @@ -1268,6 +1313,8 @@ /* To check - Should cover Samsung & Compaq */ priv->firmware_type = FIRMWARE_TYPE_PRISM2; + priv->tx_rate_ctrl = 0xF; /* 11 Mb/s auto */ + priv->need_card_reset = 0; priv->broken_reset = 0; priv->broken_allocate = 0; priv->has_port3 = 1; @@ -1284,6 +1331,8 @@ /* D-Link MAC : 00:40:05:* */ priv->firmware_type = FIRMWARE_TYPE_PRISM2; + priv->tx_rate_ctrl = 0xF; /* 11 Mb/s auto */ + priv->need_card_reset = 0; priv->broken_reset = 0; priv->broken_allocate = 0; priv->has_port3 = 1; @@ -1300,6 +1349,8 @@ vendor_str = "UNKNOWN"; priv->firmware_type = 0; + priv->tx_rate_ctrl = 0x3; /* Hum... */ + priv->need_card_reset = 0; priv->broken_reset = 0; priv->broken_allocate = 0; priv->has_port3 = 0; @@ -1314,7 +1365,7 @@ printk(KERN_INFO "%s: Firmware ID %02X vendor 0x%x (%s) version %d.%02d\n", dev->name, priv->firmware_info.id, priv->firmware_info.vendor, vendor_str, priv->firmware_info.major, priv->firmware_info.minor); - + if (priv->has_port3) printk(KERN_INFO "%s: Ad-hoc demo mode supported.\n", dev->name); if (priv->has_ibss) @@ -1393,9 +1444,6 @@ goto out; } - /* Set initial bitrate control*/ - priv->tx_rate_ctrl = 3; - /* Power management setup */ if (priv->has_pm) { priv->pm_on = 0; @@ -1466,7 +1514,7 @@ dldwd_lock(priv); - if (priv->port_type == 3) { + if (priv->iw_mode == IW_MODE_ADHOC) { memset(&wstats->qual, 0, sizeof(wstats->qual)); #ifdef WIRELESS_SPY /* If a spy address is defined, we report stats of the @@ -1709,7 +1757,7 @@ { dldwd_priv_t *priv = dev->priv; int err = 0; - int ptype; + int mode; struct iw_range range; int numrates; int i, k; @@ -1723,7 +1771,7 @@ rrq->length = sizeof(range); dldwd_lock(priv); - ptype = priv->port_type; + mode = priv->iw_mode; dldwd_unlock(priv); memset(&range, 0, sizeof(range)); @@ -1755,7 +1803,7 @@ range.sensitivity = 3; - if ((ptype == 3) && (priv->spy_number == 0)){ + if ((mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){ /* Quality stats meaningless in ad-hoc mode */ range.max_qual.qual = 0; range.max_qual.level = 0; @@ -2253,7 +2301,7 @@ switch(brate) { case 0: fixed = 0x0; - upto = 0x15; + upto = 0xF; break; case 2: fixed = 0x1; @@ -2269,7 +2317,7 @@ break; case 22: fixed = 0x8; - upto = 0x15; + upto = 0xF; break; default: fixed = 0x0; @@ -2881,6 +2929,7 @@ if (wrq->u.data.pointer) { struct iw_priv_args privtab[] = { { SIOCDEVPRIVATE + 0x0, 0, 0, "force_reset" }, + { SIOCDEVPRIVATE + 0x1, 0, 0, "card_reset" }, { SIOCDEVPRIVATE + 0x2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_port3" }, @@ -2917,6 +2966,20 @@ dldwd_reset(priv); break; + case SIOCDEVPRIVATE + 0x1: /* card_reset */ + DEBUG(1, "%s: SIOCDEVPRIVATE + 0x1 (card_reset)\n", + dev->name); + if (! capable(CAP_NET_ADMIN)) { + err = -EPERM; + break; + } + + printk(KERN_DEBUG "%s: Forcing card reset!\n", dev->name); + if(priv->card_reset_handler != NULL) + priv->card_reset_handler(priv); + dldwd_reset(priv); + break; + case SIOCDEVPRIVATE + 0x2: /* set_port3 */ DEBUG(1, "%s: SIOCDEVPRIVATE + 0x2 (set_port3)\n", dev->name); @@ -3495,6 +3558,7 @@ ndev->priv = priv; /* Setup up default routines */ + priv->card_reset_handler = NULL; /* Caller may override */ ndev->init = dldwd_init; ndev->open = NULL; /* Caller *must* override */ ndev->stop = NULL; diff -u --recursive --new-file v2.4.5/linux/drivers/net/wireless/orinoco.h linux/drivers/net/wireless/orinoco.h --- v2.4.5/linux/drivers/net/wireless/orinoco.h Mon May 7 19:42:14 2001 +++ linux/drivers/net/wireless/orinoco.h Mon Jun 11 19:15:27 2001 @@ -44,6 +44,8 @@ typedef struct dldwd_priv { void* card; /* Pointer to card dependant structure */ + /* card dependant extra reset code (i.e. bus/interface specific */ + int (*card_reset_handler)(struct dldwd_priv *); spinlock_t lock; long state; @@ -72,7 +74,7 @@ int has_mwo; int has_pm; int has_preamble; - int broken_reset, broken_allocate; + int need_card_reset, broken_reset, broken_allocate; uint16_t channel_mask; /* Current configuration */ diff -u --recursive --new-file v2.4.5/linux/drivers/net/wireless/orinoco_cs.c linux/drivers/net/wireless/orinoco_cs.c --- v2.4.5/linux/drivers/net/wireless/orinoco_cs.c Mon May 7 19:42:14 2001 +++ linux/drivers/net/wireless/orinoco_cs.c Mon Jul 2 14:03:04 2001 @@ -1,4 +1,4 @@ -/* orinoco_cs.c 0.05 - (formerly known as dldwd_cs.c) +/* orinoco_cs.c 0.06 - (formerly known as dldwd_cs.c) * * A driver for "Hermes" chipset based PCMCIA wireless adaptors, such * as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/ @@ -50,7 +50,8 @@ struct dldwd_priv priv; } dldwd_card_t; -static char *version = "orinoco_cs.c 0.05 (David Gibson and others)"; +static char version[] __initdata = +"orinoco_cs.c 0.06 (David Gibson and others)"; /*====================================================================*/ @@ -107,8 +108,8 @@ device numbers are used to derive the corresponding array index. */ -static dev_link_t *dev_list = NULL; -static int num_instances = 0; +static dev_link_t *dev_list; +static int num_instances; /*====================================================================*/ @@ -166,6 +167,70 @@ return 0; } +/* + * Do a soft reset of the Pcmcia card using the Configuration Option Register + * Can't do any harm, and actually may do some good on some cards... + * In fact, this seem necessary for Spectrum cards... + */ +static int +dldwd_cs_cor_reset(dldwd_priv_t *priv) +{ + dldwd_card_t* card = (dldwd_card_t *)priv->card; + dev_link_t *link = &card->link; + conf_reg_t reg; + u_long default_cor; + + TRACE_ENTER(priv->ndev.name); + + /* Doing it if hardware is gone is guaranteed crash */ + if(!priv->hw_ready) + return(0); + + /* Save original COR value */ + reg.Function = 0; + reg.Action = CS_READ; + reg.Offset = CISREG_COR; + reg.Value = 0; + CardServices(AccessConfigurationRegister, link->handle, ®); + default_cor = reg.Value; + + DEBUG(2, "dldwd : dldwd_cs_cor_reset() : cor=0x%lX\n", default_cor); + + /* Soft-Reset card */ + reg.Action = CS_WRITE; + reg.Offset = CISREG_COR; + reg.Value = (default_cor | COR_SOFT_RESET); + CardServices(AccessConfigurationRegister, link->handle, ®); + + /* Wait until the card has acknowledged our reset */ + mdelay(1); + + /* Restore original COR configuration index */ + reg.Value = (default_cor & ~COR_SOFT_RESET); + CardServices(AccessConfigurationRegister, link->handle, ®); + + /* Wait until the card has finished restarting */ + mdelay(1); + + TRACE_EXIT(priv->ndev.name); + + return(0); +} + +/* Remove zombie instances (card removed, detach pending) */ +static void +flush_stale_links(void) +{ + dev_link_t *link, *next; + TRACE_ENTER("dldwd"); + for (link = dev_list; link; link = next) { + next = link->next; + if (link->state & DEV_STALE_LINK) + dldwd_cs_detach(link); + } + TRACE_EXIT("dldwd"); +} + /*====================================================================== dldwd_cs_attach() creates an "instance" of the driver, allocating local data structures for one device. The device is registered @@ -187,6 +252,8 @@ int ret, i; TRACE_ENTER("dldwd"); + /* A bit of cleanup */ + flush_stale_links(); /* Allocate space for private device-specific data */ card = kmalloc(sizeof(*card), GFP_KERNEL); @@ -237,6 +304,7 @@ /* Overrides */ ndev->open = dldwd_cs_open; ndev->stop = dldwd_cs_stop; + priv->card_reset_handler = dldwd_cs_cor_reset; /* Register with Card Services */ link->next = dev_list; @@ -320,45 +388,6 @@ TRACE_EXIT("dldwd"); } /* dldwd_cs_detach */ -/* - * Do a soft reset of the Pcmcia card using the Configuration Option Register - * Can't do any harm, and actually may do some good on some cards... - */ -static int -dldwd_cs_cor_reset(dev_link_t *link) -{ - conf_reg_t reg; - u_long default_cor; - - /* Save original COR value */ - reg.Function = 0; - reg.Action = CS_READ; - reg.Offset = CISREG_COR; - reg.Value = 0; - CardServices(AccessConfigurationRegister, link->handle, ®); - default_cor = reg.Value; - - DEBUG(2, "dldwd : dldwd_cs_cor_reset() : cor=0x%lX\n", default_cor); - - /* Soft-Reset card */ - reg.Action = CS_WRITE; - reg.Offset = CISREG_COR; - reg.Value = (default_cor | COR_SOFT_RESET); - CardServices(AccessConfigurationRegister, link->handle, ®); - - /* Wait until the card has acknowledged our reset */ - mdelay(1); - - /* Restore original COR configuration index */ - reg.Value = (default_cor & COR_CONFIG_MASK); - CardServices(AccessConfigurationRegister, link->handle, ®); - - /* Wait until the card has finished restarting */ - mdelay(1); - - return(0); -} - /*====================================================================== dldwd_cs_config() is scheduled to run after a CARD_INSERTION event is received, to configure the PCMCIA socket, and to make the @@ -556,10 +585,6 @@ ndev->base_addr = link->io.BasePort1; ndev->irq = link->irq.AssignedIRQ; - /* Do a Pcmcia soft reset of the card (optional) */ - if(reset_cor) - dldwd_cs_cor_reset(link); - /* register_netdev will give us an ethX name */ ndev->name[0] = '\0'; /* Tell the stack we exist */ @@ -586,9 +611,6 @@ link->io.BasePort2 + link->io.NumPorts2 - 1); printk("\n"); - /* Allow /proc & ioctls to act */ - priv->hw_ready = 1; - /* And give us the proc nodes for debugging */ if (dldwd_proc_dev_init(priv) != 0) { printk(KERN_ERR "orinoco_cs: Failed to create /proc node for %s\n", @@ -599,6 +621,13 @@ /* Note to myself : this replace MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT */ SET_MODULE_OWNER(ndev); + /* Allow cor_reset, /proc & ioctls to act */ + priv->hw_ready = 1; + + /* Do a Pcmcia soft reset of the card (optional) */ + if(reset_cor) + dldwd_cs_cor_reset(priv); + /* At this point, the dev_node_t structure(s) need to be initialized and arranged in a linked list at link->dev. @@ -748,9 +777,8 @@ TRACE_ENTER("dldwd"); - printk(KERN_INFO "dldwd: David's Less Dodgy WaveLAN/IEEE Driver\n"); - - DEBUG(0, "%s\n", version); + printk(KERN_INFO "dldwd: David's Less Dodgy WaveLAN/IEEE Driver\n" + KERN_INFO "%s\n", version); CardServices(GetCardServicesInfo, &serv); if (serv.Revision != CS_RELEASE_CODE) { diff -u --recursive --new-file v2.4.5/linux/drivers/net/yellowfin.c linux/drivers/net/yellowfin.c --- v2.4.5/linux/drivers/net/yellowfin.c Wed May 16 10:25:39 2001 +++ linux/drivers/net/yellowfin.c Mon Jul 2 14:03:04 2001 @@ -36,6 +36,12 @@ */ +#define DRV_NAME "yellowfin" +#define DRV_VERSION "1.05+LK1.1.3" +#define DRV_RELDATE "May 10, 2001" + +#define PFX DRV_NAME ": " + /* The user-configurable values. These may be modified when a driver module is loaded.*/ @@ -108,6 +114,8 @@ #include #include #include +#include +#include #include /* Processor type for cache alignment. */ #include #include @@ -115,9 +123,9 @@ /* These identify the driver base version and may not be removed. */ static char version[] __devinitdata = -KERN_INFO "yellowfin.c:v1.05 1/09/2001 Written by Donald Becker \n" +KERN_INFO DRV_NAME ".c:v1.05 1/09/2001 Written by Donald Becker \n" KERN_INFO " http://www.scyld.com/network/yellowfin.html\n" -KERN_INFO " (unofficial 2.4.x port, LK1.1.3, May 10, 2001)\n"; +KERN_INFO " (unofficial 2.4.x port, " DRV_VERSION ", " DRV_RELDATE ")\n"; /* Condensed operations for readability. */ #define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr)) @@ -146,6 +154,13 @@ MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(gx_fix, "i"); +MODULE_PARM_DESC(max_interrupt_work, "G-NIC maximum events handled per interrupt"); +MODULE_PARM_DESC(mtu, "G-NIC MTU (all boards)"); +MODULE_PARM_DESC(debug, "G-NIC debug level (0-7)"); +MODULE_PARM_DESC(rx_copybreak, "G-NIC copy breakpoint for copy-only-tiny-frames"); +MODULE_PARM_DESC(options, "G-NIC: Bits 0-3: media type, bit 17: full duplex"); +MODULE_PARM_DESC(full_duplex, "G-NIC full duplex setting(s) (1)"); +MODULE_PARM_DESC(gx_fix, "G-NIC: enable GX server chipset bug workaround (0-1)"); /* Theory of Operation @@ -369,7 +384,7 @@ static int read_eeprom(long ioaddr, int location); static int mdio_read(long ioaddr, int phy_id, int location); static void mdio_write(long ioaddr, int phy_id, int location, int value); -static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); +static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static int yellowfin_open(struct net_device *dev); static void yellowfin_timer(unsigned long data); static void yellowfin_tx_timeout(struct net_device *dev); @@ -407,7 +422,7 @@ dev = alloc_etherdev(sizeof(*np)); if (!dev) { - printk (KERN_ERR "yellowfin: cannot allocate ethernet device\n"); + printk (KERN_ERR PFX "cannot allocate ethernet device\n"); return -ENOMEM; } SET_MODULE_OWNER(dev); @@ -474,7 +489,7 @@ dev->stop = &yellowfin_close; dev->get_stats = &yellowfin_get_stats; dev->set_multicast_list = &set_rx_mode; - dev->do_ioctl = &mii_ioctl; + dev->do_ioctl = &netdev_ioctl; dev->tx_timeout = yellowfin_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; @@ -1330,25 +1345,56 @@ outw(cfg_value | 0x1000, ioaddr + Cnfg); } -static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr) +{ + struct yellowfin_private *np = dev->priv; + u32 ethcmd; + + if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) + return -EFAULT; + + switch (ethcmd) { + case ETHTOOL_GDRVINFO: { + struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; + strcpy(info.driver, DRV_NAME); + strcpy(info.version, DRV_VERSION); + strcpy(info.bus_info, np->pci_dev->slot_name); + if (copy_to_user(useraddr, &info, sizeof(info))) + return -EFAULT; + return 0; + } + + } + + return -EOPNOTSUPP; +} + +static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct yellowfin_private *np = dev->priv; long ioaddr = dev->base_addr; - u16 *data = (u16 *)&rq->ifr_data; + struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data; switch(cmd) { - case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ - data[0] = np->phys[0] & 0x1f; + case SIOCETHTOOL: + return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); + case SIOCGMIIPHY: /* Get address of MII PHY in use. */ + case SIOCDEVPRIVATE: /* for binary compat, remove in 2.5 */ + data->phy_id = np->phys[0] & 0x1f; /* Fall Through */ - case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ - data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f); + + case SIOCGMIIREG: /* Read MII PHY register. */ + case SIOCDEVPRIVATE+1: /* for binary compat, remove in 2.5 */ + data->val_out = mdio_read(ioaddr, data->phy_id & 0x1f, data->reg_num & 0x1f); return 0; - case SIOCDEVPRIVATE+2: /* Write the specified MII register */ + + case SIOCSMIIREG: /* Write MII PHY register. */ + case SIOCDEVPRIVATE+2: /* for binary compat, remove in 2.5 */ if (!capable(CAP_NET_ADMIN)) return -EPERM; - if (data[0] == np->phys[0]) { - u16 value = data[2]; - switch (data[1]) { + if (data->phy_id == np->phys[0]) { + u16 value = data->val_in; + switch (data->reg_num) { case 0: /* Check for autonegotiation on or reset. */ np->medialock = (value & 0x9000) ? 0 : 1; @@ -1359,7 +1405,7 @@ } /* Perhaps check_duplex(dev), depending on chip semantics. */ } - mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]); + mdio_write(ioaddr, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in); return 0; default: return -EOPNOTSUPP; @@ -1390,7 +1436,7 @@ static struct pci_driver yellowfin_driver = { - name: "yellowfin", + name: DRV_NAME, id_table: yellowfin_pci_tbl, probe: yellowfin_init_one, remove: yellowfin_remove_one, diff -u --recursive --new-file v2.4.5/linux/drivers/nubus/nubus.c linux/drivers/nubus/nubus.c --- v2.4.5/linux/drivers/nubus/nubus.c Sun Dec 3 17:48:19 2000 +++ linux/drivers/nubus/nubus.c Wed Jun 27 17:10:55 2001 @@ -574,7 +574,7 @@ /* Now clobber the whole thing */ if (size > sizeof(mode) - 1) size = sizeof(mode) - 1; - memset(&mode, sizeof(mode), 0); + memset(&mode, 0, sizeof(mode)); nubus_get_rsrc_mem(&mode, &ent, size); printk (KERN_INFO " %02X: (%02X) %s\n", ent.type, mode.id, mode.name); diff -u --recursive --new-file v2.4.5/linux/drivers/parport/ChangeLog linux/drivers/parport/ChangeLog --- v2.4.5/linux/drivers/parport/ChangeLog Tue May 22 19:54:04 2001 +++ linux/drivers/parport/ChangeLog Mon Jun 11 19:15:27 2001 @@ -1,3 +1,9 @@ +2001-06-05 Tim Waugh + + * parport_pc.c (parport_pc_unregister_port): New exported function. + Do the opposite of parport_pc_probe_port. + (cleanup_module): Use it. + 2001-05-22 Juan Quintela * parport_amiga.c: Set printk levels. diff -u --recursive --new-file v2.4.5/linux/drivers/parport/parport_pc.c linux/drivers/parport/parport_pc.c --- v2.4.5/linux/drivers/parport/parport_pc.c Tue May 22 19:54:04 2001 +++ linux/drivers/parport/parport_pc.c Mon Jun 11 19:15:27 2001 @@ -2349,6 +2349,28 @@ return p; } +void parport_pc_unregister_port (struct parport *p) +{ + struct parport_pc_private *priv = p->private_data; + struct parport_operations *ops = p->ops; + if (p->dma != PARPORT_DMA_NONE) + free_dma(p->dma); + if (p->irq != PARPORT_IRQ_NONE) + free_irq(p->irq, p); + release_region(p->base, 3); + if (p->size > 3) + release_region(p->base + 3, p->size - 3); + if (p->modes & PARPORT_MODE_ECP) + release_region(p->base_hi, 3); + parport_proc_unregister(p); + if (priv->dma_buf) + pci_free_consistent(priv->dev, PAGE_SIZE, + priv->dma_buf, + priv->dma_handle); + kfree (p->private_data); + parport_unregister_port(p); + kfree (ops); /* hope no-one cached it */ +} #ifdef CONFIG_PCI /* Via support maintained by Jeff Garzik */ @@ -2816,6 +2838,7 @@ /* Exported symbols. */ EXPORT_SYMBOL (parport_pc_probe_port); +EXPORT_SYMBOL (parport_pc_unregister_port); #ifdef MODULE static int io[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 }; @@ -2883,27 +2906,9 @@ while (p) { tmp = p->next; - if (p->modes & PARPORT_MODE_PCSPP) { - struct parport_pc_private *priv = p->private_data; - struct parport_operations *ops = p->ops; - if (p->dma != PARPORT_DMA_NONE) - free_dma(p->dma); - if (p->irq != PARPORT_IRQ_NONE) - free_irq(p->irq, p); - release_region(p->base, 3); - if (p->size > 3) - release_region(p->base + 3, p->size - 3); - if (p->modes & PARPORT_MODE_ECP) - release_region(p->base_hi, 3); - parport_proc_unregister(p); - if (priv->dma_buf) - pci_free_consistent(priv->dev, PAGE_SIZE, - priv->dma_buf, - priv->dma_handle); - kfree (p->private_data); - parport_unregister_port(p); - kfree (ops); /* hope no-one cached it */ - } + if (p->modes & PARPORT_MODE_PCSPP) + parport_pc_unregister_port (p); + p = tmp; } } diff -u --recursive --new-file v2.4.5/linux/drivers/parport/parport_sunbpp.c linux/drivers/parport/parport_sunbpp.c --- v2.4.5/linux/drivers/parport/parport_sunbpp.c Tue May 22 19:54:04 2001 +++ linux/drivers/parport/parport_sunbpp.c Mon Jun 11 19:15:27 2001 @@ -1,4 +1,4 @@ -/* $Id: parport_sunbpp.c,v 1.11 2001/02/13 01:16:58 davem Exp $ +/* $Id: parport_sunbpp.c,v 1.12 2001/05/26 03:01:42 davem Exp $ * Parallel-port routines for Sun architecture * * Author: Derrick J. Brashear diff -u --recursive --new-file v2.4.5/linux/drivers/pci/Makefile linux/drivers/pci/Makefile --- v2.4.5/linux/drivers/pci/Makefile Sat May 19 17:49:14 2001 +++ linux/drivers/pci/Makefile Tue Jun 12 11:08:46 2001 @@ -13,8 +13,12 @@ export-objs := pci.o -obj-$(CONFIG_PCI) += pci.o quirks.o compat.o names.o setup-res.o +obj-$(CONFIG_PCI) += pci.o quirks.o compat.o names.o obj-$(CONFIG_PROC_FS) += proc.o + +ifndef CONFIG_SPARC64 +obj-$(CONFIG_PCI) += setup-res.o +endif # # Some architectures use the generic PCI setup functions diff -u --recursive --new-file v2.4.5/linux/drivers/pci/pci.c linux/drivers/pci/pci.c --- v2.4.5/linux/drivers/pci/pci.c Sat May 19 17:43:06 2001 +++ linux/drivers/pci/pci.c Mon Jul 2 14:42:53 2001 @@ -229,49 +229,121 @@ } /** - * pci_set_power_state - Set power management state of a device. - * @dev: PCI device for which PM is set - * @new_state: new power management statement (0 == D0, 3 == D3, etc.) - * - * Set power management state of a device. For transitions from state D3 - * it isn't as straightforward as one could assume since many devices forget - * their configuration space during wakeup. Returns old power state. + * pci_set_power_state - Set the power state of a PCI device + * @dev: PCI device to be suspended + * @state: Power state we're entering + * + * Transition a device to a new power state, using the Power Management + * Capabilities in the device's config space. + * + * RETURN VALUE: + * -EINVAL if trying to enter a lower state than we're already in. + * 0 if we're already in the requested state. + * -EIO if device does not support PCI PM. + * 0 if we can successfully change the power state. */ + int -pci_set_power_state(struct pci_dev *dev, int new_state) +pci_set_power_state(struct pci_dev *dev, int state) { - u32 base[5], romaddr; - u16 pci_command, pwr_command; - u8 pci_latency, pci_cacheline; - int i, old_state; - int pm = pci_find_capability(dev, PCI_CAP_ID_PM); + int pm; + u16 pmcsr; - if (!pm) - return 0; - pci_read_config_word(dev, pm + PCI_PM_CTRL, &pwr_command); - old_state = pwr_command & PCI_PM_CTRL_STATE_MASK; - if (old_state == new_state) - return old_state; - DBG("PCI: %s goes from D%d to D%d\n", dev->slot_name, old_state, new_state); - if (old_state == 3) { - pci_read_config_word(dev, PCI_COMMAND, &pci_command); - pci_write_config_word(dev, PCI_COMMAND, pci_command & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY)); - for (i = 0; i < 5; i++) - pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + i*4, &base[i]); - pci_read_config_dword(dev, PCI_ROM_ADDRESS, &romaddr); - pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency); - pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &pci_cacheline); - pci_write_config_word(dev, pm + PCI_PM_CTRL, new_state); - for (i = 0; i < 5; i++) - pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + i*4, base[i]); - pci_write_config_dword(dev, PCI_ROM_ADDRESS, romaddr); + /* bound the state we're entering */ + if (state > 3) state = 3; + + /* Validate current state: + * Can enter D0 from any state, but if we can only go deeper + * to sleep if we're already in a low power state + */ + if (state > 0 && dev->current_state > state) + return -EINVAL; + else if (dev->current_state == state) + return 0; /* we're already there */ + + /* find PCI PM capability in list */ + pm = pci_find_capability(dev, PCI_CAP_ID_PM); + + /* abort if the device doesn't support PM capabilities */ + if (!pm) return -EIO; + + /* check if this device supports the desired state */ + if (state == 1 || state == 2) { + u16 pmc; + pci_read_config_word(dev,pm + PCI_PM_PMC,&pmc); + if (state == 1 && !(pmc & PCI_PM_CAP_D1)) return -EIO; + else if (state == 2 && !(pmc & PCI_PM_CAP_D2)) return -EIO; + } + + /* If we're in D3, force entire word to 0. + * This doesn't affect PME_Status, disables PME_En, and + * sets PowerState to 0. + */ + if (dev->current_state == 3) + pmcsr = 0; + else { + pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr); + pmcsr &= ~PCI_PM_CTRL_STATE_MASK; + pmcsr |= state; + } + + /* enter specified state */ + pci_write_config_word(dev, pm + PCI_PM_CTRL, pmcsr); + + dev->current_state = state; + + return 0; +} + +/** + * pci_save_state - save the PCI configuration space of a device before suspending + * @dev - PCI device that we're dealing with + * @buffer - buffer to hold config space context + * + * @buffer must be large enough to hold the entire PCI 2.2 config space + * (>= 64 bytes). + */ +int +pci_save_state(struct pci_dev *dev, u32 *buffer) +{ + int i; + if (buffer) { + /* XXX: 100% dword access ok here? */ + for (i = 0; i < 16; i++) + pci_read_config_dword(dev, i * 4,&buffer[i]); + } + return 0; +} + +/** + * pci_restore_state - Restore the saved state of a PCI device + * @dev - PCI device that we're dealing with + * @buffer - saved PCI config space + * + */ +int +pci_restore_state(struct pci_dev *dev, u32 *buffer) +{ + int i; + + if (buffer) { + for (i = 0; i < 16; i++) + pci_write_config_dword(dev,i * 4, buffer[i]); + } + /* + * otherwise, write the context information we know from bootup. + * This works around a problem where warm-booting from Windows + * combined with a D3(hot)->D0 transition causes PCI config + * header data to be forgotten. + */ + else { + for (i = 0; i < 6; i ++) + pci_write_config_dword(dev, + PCI_BASE_ADDRESS_0 + (i * 4), + dev->resource[i].start); pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, pci_cacheline); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, pci_latency); - pci_write_config_word(dev, PCI_COMMAND, pci_command); - } else - pci_write_config_word(dev, pm + PCI_PM_CTRL, (pwr_command & ~PCI_PM_CTRL_STATE_MASK) | new_state); - return old_state; + } + return 0; } /** @@ -298,10 +370,8 @@ * @dev: PCI device to be disabled * * Signal to the system that the PCI device is not in use by the system - * anymore. Currently this only involves disabling PCI busmastering, - * if active. + * anymore. This only involves disabling PCI bus-mastering, if active. */ - void pci_disable_device(struct pci_dev *dev) { @@ -314,6 +384,55 @@ } } +/** + * pci_enable_wake - enable device to generate PME# when suspended + * @dev - PCI device to operate on + * @enable - Flag to enable or disable generation + * + * Set the bits in the device's PM Capabilities to generate PME# when + * the system is suspended. + * + * -EIO is returned if device doesn't have PM Capabilities. + * -EINVAL is returned if device supports it, but can't generate wake events. + * 0 if operation is successful. + * + */ +int pci_enable_wake(struct pci_dev *dev, u32 state, int enable) +{ + int pm; + u16 value; + + /* find PCI PM capability in list */ + pm = pci_find_capability(dev, PCI_CAP_ID_PM); + + /* If device doesn't support PM Capabilities, but request is to disable + * wake events, it's a nop; otherwise fail */ + if (!pm) + return enable ? -EIO : 0; + + /* Check device's ability to generate PME# */ + pci_read_config_word(dev,pm+PCI_PM_PMC,&value); + + value &= PCI_PM_CAP_PME_MASK; + value >>= ffs(value); /* First bit of mask */ + + /* Check if it can generate PME# from requested state. */ + if (!value || !(value & (1 << state))) + return enable ? -EINVAL : 0; + + pci_read_config_word(dev, pm + PCI_PM_CTRL, &value); + + /* Clear PME_Status by writing 1 to it and enable PME# */ + value |= PCI_PM_CTRL_PME_STATUS | PCI_PM_CTRL_PME_ENABLE; + + if (!enable) + value &= ~PCI_PM_CTRL_PME_ENABLE; + + pci_write_config_word(dev, pm + PCI_PM_CTRL, value); + + return 0; +} + int pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge) { @@ -1272,40 +1391,67 @@ * easily implement them (ie just have a suspend function that calls * the pci_set_power_state() function). */ -static int pci_pm_suspend_device(struct pci_dev *dev) + +static int pci_pm_save_state_device(struct pci_dev *dev, u32 state) +{ + int error = 0; + if (dev) { + struct pci_driver *driver = dev->driver; + if (driver && driver->save_state) + error = driver->save_state(dev,state); + } + return error; +} + +static int pci_pm_suspend_device(struct pci_dev *dev, u32 state) { + int error = 0; if (dev) { struct pci_driver *driver = dev->driver; if (driver && driver->suspend) - driver->suspend(dev); + error = driver->suspend(dev,state); } - return 0; + return error; } static int pci_pm_resume_device(struct pci_dev *dev) { + int error = 0; if (dev) { struct pci_driver *driver = dev->driver; if (driver && driver->resume) - driver->resume(dev); + error = driver->resume(dev); } - return 0; + return error; } +static int pci_pm_save_state_bus(struct pci_bus *bus, u32 state) +{ + struct list_head *list; + int error = 0; -/* take care to suspend/resume bridges only once */ + list_for_each(list, &bus->children) { + error = pci_pm_save_state_bus(pci_bus_b(list),state); + if (error) return error; + } + list_for_each(list, &bus->devices) { + error = pci_pm_save_state_device(pci_dev_b(list),state); + if (error) return error; + } + return 0; +} -static int pci_pm_suspend_bus(struct pci_bus *bus) +static int pci_pm_suspend_bus(struct pci_bus *bus, u32 state) { struct list_head *list; /* Walk the bus children list */ list_for_each(list, &bus->children) - pci_pm_suspend_bus(pci_bus_b(list)); + pci_pm_suspend_bus(pci_bus_b(list),state); /* Walk the device children list */ list_for_each(list, &bus->devices) - pci_pm_suspend_device(pci_dev_b(list)); + pci_pm_suspend_device(pci_dev_b(list),state); return 0; } @@ -1323,15 +1469,30 @@ return 0; } -static int pci_pm_suspend(void) +static int pci_pm_save_state(u32 state) +{ + struct list_head *list; + struct pci_bus *bus; + int error = 0; + + list_for_each(list, &pci_root_buses) { + bus = pci_bus_b(list); + error = pci_pm_save_state_bus(bus,state); + if (!error) + error = pci_pm_save_state_device(bus->self,state); + } + return error; +} + +static int pci_pm_suspend(u32 state) { struct list_head *list; struct pci_bus *bus; list_for_each(list, &pci_root_buses) { bus = pci_bus_b(list); - pci_pm_suspend_bus(bus); - pci_pm_suspend_device(bus->self); + pci_pm_suspend_bus(bus,state); + pci_pm_suspend_device(bus->self,state); } return 0; } @@ -1349,16 +1510,26 @@ return 0; } -static int pci_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) +static int +pci_pm_callback(struct pm_dev *pm_device, pm_request_t rqst, void *data) { + int error = 0; + switch (rqst) { + case PM_SAVE_STATE: + error = pci_pm_save_state((u32)data); + break; case PM_SUSPEND: - return pci_pm_suspend(); + error = pci_pm_suspend((u32)data); + break; case PM_RESUME: - return pci_pm_resume(); - } - return 0; + error = pci_pm_resume(); + break; + default: break; + } + return error; } + #endif /* @@ -1741,7 +1912,6 @@ __setup("pci=", pci_setup); - EXPORT_SYMBOL(pci_read_config_byte); EXPORT_SYMBOL(pci_read_config_word); EXPORT_SYMBOL(pci_read_config_dword); @@ -1761,7 +1931,6 @@ EXPORT_SYMBOL(pci_find_subsys); EXPORT_SYMBOL(pci_set_master); EXPORT_SYMBOL(pci_set_dma_mask); -EXPORT_SYMBOL(pci_set_power_state); EXPORT_SYMBOL(pci_assign_resource); EXPORT_SYMBOL(pci_register_driver); EXPORT_SYMBOL(pci_unregister_driver); @@ -1774,6 +1943,11 @@ EXPORT_SYMBOL(pci_insert_device); EXPORT_SYMBOL(pci_remove_device); #endif + +EXPORT_SYMBOL(pci_set_power_state); +EXPORT_SYMBOL(pci_save_state); +EXPORT_SYMBOL(pci_restore_state); +EXPORT_SYMBOL(pci_enable_wake); /* Obsolete functions */ diff -u --recursive --new-file v2.4.5/linux/drivers/pci/pci.ids linux/drivers/pci/pci.ids --- v2.4.5/linux/drivers/pci/pci.ids Sat May 19 17:49:14 2001 +++ linux/drivers/pci/pci.ids Mon Jul 2 14:03:04 2001 @@ -244,6 +244,7 @@ 000f OHCI Compliant FireWire Controller 0011 National PCI System I/O 0012 USB Controller + 0020 DP83815 (MacPhyter) Ethernet Controller d001 87410 IDE 100c Tseng Labs Inc 3202 ET4000/W32p rev A @@ -383,10 +384,12 @@ 1014 00cf 16/4 Token-Ring Adapter Special 1014 00e4 High-Speed 100/16/4 Token-Ring Adapter 1014 00e5 16/4 Token-Ring Adapter 2 + Wake-On-LAN + 1014 016d iSeries 2744 Card 0045 SSA Adapter 0046 MPIC interrupt controller 0047 PCI to PCI Bridge 0048 PCI to PCI Bridge + 0049 Warhead SCSI Controller 004e ATM Controller (14104e00) 004f ATM Controller (14104f00) 0050 ATM Controller (14105000) @@ -398,6 +401,10 @@ 0090 GXT 3000P 1014 008E GXT-3000P 0095 20H2999 PCI Docking Bridge + 0096 Chukar chipset SCSI controller + 1014 0099 iSeries 2748 DASD IOA + 1014 0098 iSeries 2763 DASD IOA + 1014 0097 iSeries 2778 DASD IOA 00a5 ATM Controller (1410a500) 00a6 ATM 155MBPS MM Controller (1410a600) 00b7 256-bit Graphics Rasterizer [Fire GL1] @@ -458,6 +465,8 @@ 2040 79c974 7006 AMD-751 [Irongate] System Controller 7007 AMD-751 [Irongate] AGP Bridge + 700E AMD-760 [Irongate] System Controller + 700F AMD-760 [Irongate] AGP Bridge 7400 AMD-755 [Cobra] ISA 7401 AMD-755 [Cobra] IDE 7403 AMD-755 [Cobra] ACPI @@ -466,6 +475,10 @@ 7409 AMD-756 [Viper] IDE 740b AMD-756 [Viper] ACPI 740c AMD-756 [Viper] USB + 7410 AMD-765 [Viper] ISA + 7411 AMD-765 [Viper] IDE + 7413 AMD-765 [Viper] ACPI + 7414 AMD-765 [Viper] USB 1023 Trident Microsystems 0194 82C194 2000 4DWave DX @@ -993,6 +1006,7 @@ 4d30 20267 4d33 20246 4d38 20262 + 4d68 20268 5300 DC5300 105b Foxconn International, Inc. 105c Wipro Infotech Limited @@ -1925,9 +1939,9 @@ 1102 8051 CT4850 SBLive! Value 7002 SB Live! 1102 0020 Gameport Joystick -1103 Triones Technologies, Inc. - 0003 HPT343 - 0004 HPT366 +1103 HighPoint Technologies, Inc. + 0003 HPT343 UltraDMA 33 IDE Controller + 0004 HPT366/370 UltraDMA 66/100 IDE Controller 1104 RasterOps Corp. 1105 Sigma Designs, Inc. 8300 REALmagic Hollywood Plus DVD Decoder @@ -2217,7 +2231,7 @@ 1145 Workbit Corporation 1146 Force Computers 1147 Interface Corp -1148 Syskonnect (Schneider & Koch) +1148 SysKonnect GmbH 4000 FDDI Adapter 0e11 b03b Netelligent 100 FDDI DAS Fibre SC 0e11 b03c Netelligent 100 FDDI SAS Fibre SC @@ -2234,7 +2248,7 @@ 1148 5841 FDDI SK-5841 (SK-NET FDDI-FP64) 1148 5843 FDDI SK-5843 (SK-NET FDDI-LP64) 1148 5844 FDDI SK-5844 (SK-NET FDDI-LP64 DAS) - 4200 Token ring adaptor + 4200 Token Ring adapter 4300 Gigabit Ethernet 1148 9821 SK-9821 (1000Base-T single link) 1148 9822 SK-9822 (1000Base-T dual link) @@ -2242,6 +2256,8 @@ 1148 9842 SK-9842 (1000Base-LX dual link) 1148 9843 SK-9843 (1000Base-SX single link) 1148 9844 SK-9844 (1000Base-SX dual link) + 1148 9861 SK-9861 (1000Base-SX VF45 single link) + 1148 9862 SK-9862 (1000Base-SX VF45 dual link) 1149 Win System Corporation 114a VMIC 7587 VMIVME-7587 @@ -2335,13 +2351,16 @@ 1165 Imagraph Corporation 0001 Motion TPEG Recorder/Player with audio 1166 ServerWorks - 0007 CNB20-LE CPU to PCI Bridge - 0008 CNB20HE - 0009 CNB20LE + 0007 CNB20-LE Host Bridge + 0008 CNB20HE Host Bridge + 0009 CNB20LE Host Bridge 0010 CIOB30 0011 CMIC-HE - 0200 OSB4 - 0201 CSB5 + 0200 OSB4 South Bridge + 0201 CSB5 South Bridge + 0211 OSB4 IDE Controller + 0212 CSB5 IDE Controller + 0220 OSB4/CSB5 OHCI USB Controller 1167 Mutoh Industries Inc 1168 Thine Electronics Inc 1169 Centre for Development of Advanced Computing @@ -2455,7 +2474,9 @@ 1221 82C092G 119c Information Technology Inst. 119d Bug, Inc. Sapporo Japan -119e Fujitsu Microelectronics Ltd. +119e Fujitsu Microelectronics Europe GMBH + 0001 FireStream 155 + 0003 FireStream 50 119f Bull HN Information Systems 11a0 Convex Computer Corporation 11a1 Hamamatsu Photonics K.K. @@ -3002,13 +3023,14 @@ 8086 5643 ES1371, ES1373 AudioPCI On Motherboard Vancouver 8086 5753 ES1371, ES1373 AudioPCI On Motherboard WS440BX 5000 ES1370 [AudioPCI] - 5880 5880 AudioPCI + 4942 4c4c Creative Sound Blaster AudioPCI128 + 5880 CT5880 [AudioPCI] 1274 2000 Creative Sound Blaster AudioPCI128 1274 5880 Creative Sound Blaster AudioPCI128 - 1462 6880 5880 AudioPCI On Motherboard MS-6188 1.00 - 270f 2001 5880 AudioPCI On Motherboard 6CTR - 270f 2200 5880 AudioPCI On Motherboard 6WTX - 270f 7040 5880 AudioPCI On Motherboard 6ATA4 + 1462 6880 CT5880 AudioPCI On Motherboard MS-6188 1.00 + 270f 2001 CT5880 AudioPCI On Motherboard 6CTR + 270f 2200 CT5880 AudioPCI On Motherboard 6WTX + 270f 7040 CT5880 AudioPCI On Motherboard 6ATA4 1275 Network Appliance Corporation 1276 Switched Network Technologies, Inc. 1277 Comstream @@ -3893,6 +3915,7 @@ 14e2 INFOLIBRIA 14e3 AMTELCO 14e4 BROADCOM Corporation + 1644 Tigon3 14e5 Pixelfusion Ltd 14e6 SHINING Technology Inc 14e7 3CX @@ -4599,13 +4622,18 @@ 11d4 0048 SoundMAX Integrated Digital Audio 2426 82801AB AC'97 Modem 2428 82801AB PCI Bridge - 2440 82820 820 (Camino 2) Chipset ISA Bridge (ICH2) - 2442 82820 820 (Camino 2) Chipset USB (Hub A) - 2443 82820 820 (Camino 2) Chipset SMBus - 2444 82820 820 (Camino 2) Chipset USB (Hub B) - 2449 82820 820 (Camino 2) Chipset Ethernet - 244b 82820 820 (Camino 2) Chipset IDE U100 - 244e 82820 820 (Camino 2) Chipset PCI + 2440 82801BA ISA Bridge (ICH2) + 2442 82801BA(M) USB (Hub A) + 2443 82801BA(M) SMBus + 2444 82801BA(M) USB (Hub B) + 2445 82801BA(M) AC'97 Audio + 2446 82801BA(M) AC'97 Modem + 2448 82801BA PCI + 2449 82801BA(M) Ethernet + 244a 82801BAM IDE U100 + 244b 82801BA IDE U100 + 244c 82801BAM ISA Bridge (ICH2) + 244e 82801BAM PCI 2500 82820 820 (Camino) Chipset Host Bridge (MCH) 1043 801c P3C-2000 system chipset 2501 82820 820 (Camino) Chipset Host Bridge (MCH) diff -u --recursive --new-file v2.4.5/linux/drivers/pci/quirks.c linux/drivers/pci/quirks.c --- v2.4.5/linux/drivers/pci/quirks.c Sat May 19 17:43:06 2001 +++ linux/drivers/pci/quirks.c Wed Jun 20 11:16:01 2001 @@ -17,6 +17,7 @@ #include #include #include +#include #undef DEBUG @@ -267,6 +268,9 @@ /* * VIA 686A/B: If an IO-APIC is active, we need to route all on-chip * devices to the external APIC. + * + * TODO: When we have device-specific interrupt routers, + * this code will go away from quirks. */ static void __init quirk_via_ioapic(struct pci_dev *dev) { @@ -277,6 +281,9 @@ else tmp = 0x1f; /* all known bits (4-0) routed to external APIC */ + printk(KERN_INFO "PCI: %sbling Via external APIC routing\n", + tmp == 0 ? "Disa" : "Ena"); + /* Offset 0x58: External APIC IRQ output control */ pci_write_config_byte (dev, 0x58, tmp); } @@ -285,6 +292,56 @@ /* + * Via 686A/B: The PCI_INTERRUPT_LINE register for the on-chip + * devices, USB0/1, AC97, MC97, and ACPI, has an unusual feature: + * when written, it makes an internal connection to the PIC. + * For these devices, this register is defined to be 4 bits wide. + * Normally this is fine. However for IO-APIC motherboards, or + * non-x86 architectures (yes Via exists on PPC among other places), + * we must mask the PCI_INTERRUPT_LINE value versus 0xf to get + * interrupts delivered properly. + * + * TODO: When we have device-specific interrupt routers, + * quirk_via_irqpic will go away from quirks. + */ + +/* + * FIXME: it is questionable that quirk_via_acpi + * is needed. It shows up as an ISA bridge, and does not + * support the PCI_INTERRUPT_LINE register at all. Therefore + * it seems like setting the pci_dev's 'irq' to the + * value of the ACPI SCI interrupt is only done for convenience. + * -jgarzik + */ +static void __init quirk_via_acpi(struct pci_dev *d) +{ + /* + * VIA ACPI device: SCI IRQ line in PCI config byte 0x42 + */ + u8 irq; + pci_read_config_byte(d, 0x42, &irq); + irq &= 0xf; + if (irq && (irq != 2)) + d->irq = irq; +} + +static void __init quirk_via_irqpic(struct pci_dev *dev) +{ + u8 irq, new_irq = dev->irq & 0xf; + + pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); + + if (new_irq != irq) { + printk(KERN_INFO "PCI: Via IRQ fixup for %s, from %d to %d\n", + dev->slot_name, irq, new_irq); + + udelay(15); + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq); + } +} + + +/* * PIIX3 USB: We have to disable USB interrupts that are * hardwired to PIRQD# and may be shared with an * external device. @@ -372,6 +429,11 @@ #ifdef CONFIG_X86_IO_APIC { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_ioapic }, #endif + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_acpi }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_acpi }, + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, quirk_via_irqpic }, + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, quirk_via_irqpic }, + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_6, quirk_via_irqpic }, { 0 } }; diff -u --recursive --new-file v2.4.5/linux/drivers/pcmcia/cs.c linux/drivers/pcmcia/cs.c --- v2.4.5/linux/drivers/pcmcia/cs.c Fri Feb 16 16:02:36 2001 +++ linux/drivers/pcmcia/cs.c Wed Jun 20 11:19:02 2001 @@ -1,6 +1,6 @@ /*====================================================================== - PCMCIA Card Services -- core services + Kernel Card Services -- core services cs.c 1.271 2000/10/02 20:27:49 @@ -90,11 +90,11 @@ #define OPTIONS PCI_OPT CB_OPT PM_OPT #endif -static const char *release = "Linux PCMCIA Card Services " CS_RELEASE; +static const char *release = "Linux Kernel Card Services " CS_RELEASE; static const char *options = "options: " OPTIONS; MODULE_AUTHOR("David Hinds "); -MODULE_DESCRIPTION("Linux PCMCIA Card Services " CS_RELEASE +MODULE_DESCRIPTION("Linux Kernel Card Services " CS_RELEASE "\n options:" OPTIONS); /*====================================================================*/ @@ -2416,7 +2416,7 @@ static void __exit exit_pcmcia_cs(void) { - printk(KERN_INFO "unloading PCMCIA Card Services\n"); + printk(KERN_INFO "unloading Kernel Card Services\n"); #ifdef CONFIG_PROC_FS if (proc_pccard) { remove_proc_entry("pccard", proc_bus); diff -u --recursive --new-file v2.4.5/linux/drivers/pcmcia/pci_socket.c linux/drivers/pcmcia/pci_socket.c --- v2.4.5/linux/drivers/pcmcia/pci_socket.c Fri Apr 6 10:51:19 2001 +++ linux/drivers/pcmcia/pci_socket.c Tue Jun 12 16:52:14 2001 @@ -218,16 +218,18 @@ dev->driver_data = 0; } -static void cardbus_suspend (struct pci_dev *dev) +static int cardbus_suspend (struct pci_dev *dev, u32 state) { pci_socket_t *socket = (pci_socket_t *) dev->driver_data; pcmcia_suspend_socket (socket->pcmcia_socket); + return 0; } -static void cardbus_resume (struct pci_dev *dev) +static int cardbus_resume (struct pci_dev *dev) { pci_socket_t *socket = (pci_socket_t *) dev->driver_data; pcmcia_resume_socket (socket->pcmcia_socket); + return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/pcmcia/yenta.c linux/drivers/pcmcia/yenta.c --- v2.4.5/linux/drivers/pcmcia/yenta.c Fri Apr 6 10:51:19 2001 +++ linux/drivers/pcmcia/yenta.c Tue Jul 3 07:55:20 2001 @@ -642,10 +642,11 @@ /* MAGIC NUMBERS! Fixme */ config_writeb(socket, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES / 4); config_writeb(socket, PCI_LATENCY_TIMER, 168); - config_writeb(socket, PCI_SEC_LATENCY_TIMER, 176); - config_writeb(socket, PCI_PRIMARY_BUS, dev->bus->number); - config_writeb(socket, PCI_SECONDARY_BUS, dev->subordinate->number); - config_writeb(socket, PCI_SUBORDINATE_BUS, dev->subordinate->number); + config_writel(socket, PCI_PRIMARY_BUS, + (176 << 24) | /* sec. latency timer */ + (dev->subordinate->subordinate << 16) | /* subordinate bus */ + (dev->subordinate->secondary << 8) | /* secondary bus */ + dev->subordinate->primary); /* primary bus */ /* * Set up the bridging state: @@ -792,6 +793,7 @@ { PD(TI,1251A), &ti_ops }, { PD(TI,1211), &ti_ops }, { PD(TI,1251B), &ti_ops }, + { PD(TI,1410), &ti_ops }, { PD(TI,1420), &ti_ops }, { PD(RICOH,RL5C465), &ricoh_ops }, diff -u --recursive --new-file v2.4.5/linux/drivers/sbus/audio/Makefile linux/drivers/sbus/audio/Makefile --- v2.4.5/linux/drivers/sbus/audio/Makefile Fri Dec 29 14:07:22 2000 +++ linux/drivers/sbus/audio/Makefile Mon Jun 11 19:15:27 2001 @@ -11,8 +11,8 @@ obj-$(CONFIG_SPARCAUDIO) += audio.o obj-$(CONFIG_SPARCAUDIO_AMD7930) += amd7930.o -obj-$(CONFIG_SPARCAUDIO_CS4231) += cs4231.o obj-$(CONFIG_SPARCAUDIO_DBRI) += dbri.o +obj-$(CONFIG_SPARCAUDIO_CS4231) += cs4231.o obj-$(CONFIG_SPARCAUDIO_DUMMY) += dmy.o include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.5/linux/drivers/sbus/audio/amd7930.c linux/drivers/sbus/audio/amd7930.c --- v2.4.5/linux/drivers/sbus/audio/amd7930.c Sun Feb 18 19:49:54 2001 +++ linux/drivers/sbus/audio/amd7930.c Mon Jun 11 19:15:27 2001 @@ -1,4 +1,4 @@ -/* $Id: amd7930.c,v 1.26 2001/02/13 01:16:59 davem Exp $ +/* $Id: amd7930.c,v 1.27 2001/05/21 01:25:22 davem Exp $ * drivers/sbus/audio/amd7930.c * * Copyright (C) 1996,1997 Thomas K. Dyas (tdyas@eden.rutgers.edu) @@ -107,7 +107,7 @@ static __u8 linear2mulaw(__u16 data); static __u16 mulaw2linear(__u8 data); -#if defined (AMD79C30_ISDN) && defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff +#if defined (AMD79C30_ISDN) #include "../../isdn/hisax/hisax.h" #include "../../isdn/hisax/isdnl1.h" #include "../../isdn/hisax/foreign.h" @@ -1131,7 +1131,7 @@ * */ -#if defined (AMD79C30_ISDN) && defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff +#if defined (AMD79C30_ISDN) static int amd7930_get_irqnum(int dev) { struct amd7930_info *info; @@ -1659,9 +1659,8 @@ return 0; } -#ifdef MODULE /* Detach from an amd7930 chip given the device structure. */ -static void amd7930_detach(struct sparcaudio_driver *drv) +static void __exit amd7930_detach(struct sparcaudio_driver *drv) { struct amd7930_info *info = (struct amd7930_info *)drv->private; @@ -1672,14 +1671,9 @@ sbus_iounmap(info->regs, info->regs_size); kfree(drv->private); } -#endif /* Probe for the amd7930 chip and then attach the driver. */ -#ifdef MODULE -int init_module(void) -#else -int __init amd7930_init(void) -#endif +static int __init amd7930_init(void) { struct sbus_bus *sbus; struct sbus_dev *sdev; @@ -1710,8 +1704,7 @@ return (num_drivers > 0) ? 0 : -EIO; } -#ifdef MODULE -void cleanup_module(void) +static void __exit amd7930_exit(void) { register int i; @@ -1720,8 +1713,9 @@ num_drivers--; } } -#endif +module_init(amd7930_init); +module_exit(amd7930_exit); /*************************************************************/ /* Audio format conversion */ diff -u --recursive --new-file v2.4.5/linux/drivers/sbus/audio/audio.c linux/drivers/sbus/audio/audio.c --- v2.4.5/linux/drivers/sbus/audio/audio.c Sun Feb 18 19:49:54 2001 +++ linux/drivers/sbus/audio/audio.c Mon Jun 11 19:15:27 2001 @@ -1,4 +1,4 @@ -/* $Id: audio.c,v 1.58 2001/02/13 01:16:59 davem Exp $ +/* $Id: audio.c,v 1.60 2001/05/21 09:05:05 davem Exp $ * drivers/sbus/audio/audio.c * * Copyright 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu) @@ -32,10 +32,11 @@ #include #include #include -#include #include #include +#include #include +#include #include @@ -73,24 +74,6 @@ static struct sparcaudio_driver *drivers[SPARCAUDIO_MAX_DEVICES]; static devfs_handle_t devfs_handle; -/* This crap to be pulled off into a local include file */ -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20100 - -#define COPY_IN(arg, get) verify_area(VERIFY_READ, (void *)arg, sizeof(long)); memcpy_fromfs(&get, (long *)arg, sizeof(get)); -#define COPY_OUT(arg, ret) verify_area(VERIFY_WRITE, (void *)arg, sizeof(long)); memcpy_tofs((long *)arg, &ret, sizeof(ret)); -#define copy_to_user memcpy_tofs -#define copy_from_user memcpy_fromfs -#define signal_pending(x) (((x)->signal) & ~((x)->blocked)) - -#else - -#include -#include -#define COPY_IN(arg, get) get_user(get, (int *)arg) -#define COPY_OUT(arg, ret) put_user(ret, (int *)arg) -#define sparcaudio_select sparcaudio_poll - -#endif void sparcaudio_output_done(struct sparcaudio_driver * drv, int status) { @@ -215,37 +198,6 @@ * VFS layer interface */ -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20100 -static int sparcaudio_select(struct inode * inode, struct file * file, - int sel_type, select_table * wait) -{ - struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >> - SPARCAUDIO_DEVICE_SHIFT)]; - - switch (sel_type) { - case SEL_IN: - if (((!file->f_flags & O_NONBLOCK) && drv->input_count) || - (drv->input_size > drv->buffer_size)) { - dprintk(("read ready: c%d o%d\n", - drv->input_count, drv->input_offset)); - return 1; - } - select_wait(&drv->input_read_wait, wait); - break; - case SEL_OUT: - dprintk(("sel out: c%d o%d p%d\n", - drv->output_count, drv->output_offset, drv->playing_count)); - if ((drv->output_count + drv->playing_count) < (drv->num_output_buffers)) - return 1; - select_wait(&drv->output_write_wait, wait); - break; - case SEL_EX: - break; - }; - - return 0; -} -#else static unsigned int sparcaudio_poll(struct file *file, poll_table * wait) { unsigned int mask = 0; @@ -264,29 +216,16 @@ } return mask; } -#endif -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20100 -static int sparcaudio_lseek(struct inode * inode, struct file * file, - off_t offset, int origin) -#else -static loff_t sparcaudio_lseek(struct file * file, loff_t offset, int origin) -#endif +static loff_t sparcaudio_llseek(struct file * file, loff_t offset, int origin) { return -ESPIPE; } -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20100 -static int sparcaudio_read(struct inode * inode, struct file * file, - char *buf, int count) -#else static ssize_t sparcaudio_read(struct file * file, char *buf, size_t count, loff_t *ppos) -#endif { -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff struct inode *inode = file->f_dentry->d_inode; -#endif struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >> SPARCAUDIO_DEVICE_SHIFT)]; int bytes_to_copy, bytes_read = 0, err; @@ -358,17 +297,10 @@ restore_flags(flags); } -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20100 -static int sparcaudio_write(struct inode * inode, struct file * file, - const char *buf, int count) -#else static ssize_t sparcaudio_write(struct file * file, const char *buf, size_t count, loff_t *ppos) -#endif { -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff struct inode *inode = file->f_dentry->d_inode; -#endif struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >> SPARCAUDIO_DEVICE_SHIFT)]; int bytes_written = 0, bytes_to_copy, err; @@ -499,7 +431,7 @@ switch (cmd) { case SOUND_MIXER_WRITE_RECLEV: - if(COPY_IN(arg, k)) + if (get_user(k, (int *)arg)) return -EFAULT; iretry: oprintk(("setting input volume (0x%x)", k)); @@ -531,9 +463,9 @@ oprintk((" try 0x%x\n", k)); goto iretry; } - return COPY_OUT(arg, i); + return put_user(i, (int *)arg); case SOUND_MIXER_WRITE_VOLUME: - if(COPY_IN(arg, k)) + if (get_user(k, (int *)arg)) return -EFAULT; if (drv->ops->get_output_muted && drv->ops->set_output_muted) { i = drv->ops->get_output_muted(drv); @@ -546,9 +478,9 @@ if (drv->ops->get_output_muted) i = drv->ops->get_output_muted(drv); k = 0x6464 * (1 - i); - return COPY_OUT(arg, k); + return put_user(k, (int *)arg); case SOUND_MIXER_WRITE_PCM: - if(COPY_IN(arg, k)) + if (get_user(k, (int *)arg)) return -EFAULT; oretry: oprintk(("setting output volume (0x%x)\n", k)); @@ -582,25 +514,25 @@ oprintk((" try 0x%x\n", k)); goto oretry; } - return COPY_OUT(arg, i); + return put_user(i, (int *)arg); case SOUND_MIXER_READ_SPEAKER: k = OSS_PORT_AUDIO(drv, AUDIO_SPEAKER); - return COPY_OUT(arg, k); + return put_user(k, (int *)arg); case SOUND_MIXER_READ_MIC: k = OSS_IPORT_AUDIO(drv, AUDIO_MICROPHONE); - return COPY_OUT(arg, k); + return put_user(k, (int *)arg); case SOUND_MIXER_READ_CD: k = OSS_IPORT_AUDIO(drv, AUDIO_CD); - return COPY_OUT(arg, k); + return put_user(k, (int *)arg); case SOUND_MIXER_READ_LINE: k = OSS_IPORT_AUDIO(drv, AUDIO_LINE_IN); - return COPY_OUT(arg, k); + return put_user(k, (int *)arg); case SOUND_MIXER_READ_LINE1: k = OSS_PORT_AUDIO(drv, AUDIO_HEADPHONE); - return COPY_OUT(arg, k); + return put_user(k, (int *)arg); case SOUND_MIXER_READ_LINE2: k = OSS_PORT_AUDIO(drv, AUDIO_LINE_OUT); - return COPY_OUT(arg, k); + return put_user(k, (int *)arg); case SOUND_MIXER_WRITE_MIC: case SOUND_MIXER_WRITE_CD: @@ -608,7 +540,7 @@ case SOUND_MIXER_WRITE_LINE1: case SOUND_MIXER_WRITE_LINE2: case SOUND_MIXER_WRITE_SPEAKER: - if(COPY_IN(arg, k)) + if (get_user(k, (int *)arg)) return -EFAULT; OSS_TWIDDLE_IPORT(drv, cmd, SOUND_MIXER_WRITE_LINE, AUDIO_LINE_IN, k); OSS_TWIDDLE_IPORT(drv, cmd, SOUND_MIXER_WRITE_MIC, AUDIO_MICROPHONE, k); @@ -617,7 +549,7 @@ OSS_TWIDDLE_PORT(drv, cmd, SOUND_MIXER_WRITE_SPEAKER, AUDIO_SPEAKER, k); OSS_TWIDDLE_PORT(drv, cmd, SOUND_MIXER_WRITE_LINE1, AUDIO_HEADPHONE, k); OSS_TWIDDLE_PORT(drv, cmd, SOUND_MIXER_WRITE_LINE2, AUDIO_LINE_OUT, k); - return COPY_OUT(arg, k); + return put_user(k, (int *)arg); case SOUND_MIXER_READ_RECSRC: if (drv->ops->get_input_port) i = drv->ops->get_input_port(drv); @@ -627,11 +559,11 @@ if (i & AUDIO_LINE_IN) j = SOUND_MASK_LINE; if (i & AUDIO_MICROPHONE) j = SOUND_MASK_MIC; - return COPY_OUT(arg, j); + return put_user(j, (int *)arg); case SOUND_MIXER_WRITE_RECSRC: if (!drv->ops->set_input_port) return -EINVAL; - if(COPY_IN(arg, k)) + if (get_user(k, (int *)arg)) return -EFAULT; /* only one should ever be selected */ @@ -641,7 +573,7 @@ oprintk(("setting inport to %d\n", j)); i = drv->ops->set_input_port(drv, j); - return COPY_OUT(arg, i); + return put_user(i, (int *)arg); case SOUND_MIXER_READ_RECMASK: if (drv->ops->get_input_ports) i = drv->ops->get_input_ports(drv); @@ -650,10 +582,10 @@ if (i & AUDIO_LINE_IN) j |= SOUND_MASK_LINE; if (i & AUDIO_CD) j |= SOUND_MASK_CD; - return COPY_OUT(arg, j); + return put_user(j, (int *)arg); case SOUND_MIXER_READ_CAPS: /* mixer capabilities */ i = SOUND_CAP_EXCL_INPUT; - return COPY_OUT(arg, i); + return put_user(i, (int *)arg); case SOUND_MIXER_READ_DEVMASK: /* all supported devices */ if (drv->ops->get_input_ports) @@ -676,7 +608,7 @@ if (cmd == SOUND_MIXER_READ_STEREODEVS) j &= ~(MONO_DEVICES); - return COPY_OUT(arg, j); + return put_user(j, (int *)arg); default: return -EINVAL; }; @@ -742,7 +674,7 @@ case I_GETSIG: case I_GETSIG_SOLARIS: j = (int) lis_get_elist_ent(drv->sd_siglist,current->pid); - COPY_OUT(arg, j); + put_user(j, (int *)arg); retval = drv->input_count; break; @@ -773,7 +705,7 @@ * as its retval. (streamio(7I)) This should work. */ j = (drv->input_count > 0) ? drv->input_buffer_size : 0; - COPY_OUT(arg, j); + put_user(j, (int *)arg); retval = drv->input_count; break; @@ -859,11 +791,11 @@ if (drv->ops->get_output_pause(drv)) j |= PCM_ENABLE_OUTPUT; } - COPY_OUT(arg, j); + put_user(j, (int *)arg); break; case SNDCTL_DSP_GETBLKSIZE: j = drv->input_buffer_size; - COPY_OUT(arg, j); + put_user(j, (int *)arg); break; case SNDCTL_DSP_SPEED: if ((!drv->ops->set_output_rate) && @@ -871,12 +803,12 @@ retval = -EINVAL; break; } - COPY_IN(arg, i); + get_user(i, (int *)arg) tprintk(("setting speed to %d\n", i)); drv->ops->set_input_rate(drv, i); drv->ops->set_output_rate(drv, i); j = drv->ops->get_output_rate(drv); - COPY_OUT(arg, j); + put_user(j, (int *)arg); break; case SNDCTL_DSP_GETCAPS: /* All Sparc audio hardware is full duplex. @@ -884,19 +816,19 @@ * Pause functionality emulates trigger */ j = DSP_CAP_DUPLEX | DSP_CAP_TRIGGER | DSP_CAP_REALTIME; - COPY_OUT(arg, j); + put_user(j, (int *)arg); break; case SNDCTL_DSP_GETFMTS: if (drv->ops->get_formats) { j = drv->ops->get_formats(drv); - COPY_OUT(arg, j); + put_user(j, (int *)arg); } else { retval = -EINVAL; } break; case SNDCTL_DSP_SETFMT: /* need to decode into encoding, precision */ - COPY_IN(arg, i); + get_user(i, (int *)arg); /* handle special case here */ if (i == AFMT_QUERY) { @@ -926,7 +858,7 @@ break; }; } - COPY_OUT(arg, i); + put_user(i, (int *)arg); break; } @@ -991,7 +923,7 @@ dprintk(("setting format: failed\n")); return -EINVAL; } - COPY_OUT(arg, i); + put_user(i, (int *)arg); break; case SNDCTL_DSP_CHANNELS: if ((!drv->ops->set_output_channels) && @@ -999,11 +931,11 @@ retval = -EINVAL; break; } - COPY_IN(arg, i); + get_user(i, (int *)arg); drv->ops->set_input_channels(drv, i); drv->ops->set_output_channels(drv, i); i = drv->ops->get_output_channels(drv); - COPY_OUT(arg, i); + put_user(i, (int *)arg); break; case SNDCTL_DSP_STEREO: if ((!drv->ops->set_output_channels) && @@ -1011,11 +943,11 @@ retval = -EINVAL; break; } - COPY_IN(arg, i); + get_user(i, (int *)arg); drv->ops->set_input_channels(drv, (i + 1)); drv->ops->set_output_channels(drv, (i + 1)); i = ((drv->ops->get_output_channels(drv)) - 1); - COPY_OUT(arg, i); + put_user(i, (int *)arg); break; case SNDCTL_DSP_POST: case SNDCTL_DSP_SYNC: @@ -1761,14 +1693,14 @@ default: eprintk(("unknown minor device number\n")); retval = -EINVAL; - }; + } return retval; } static struct file_operations sparcaudioctl_fops = { owner: THIS_MODULE, - poll: sparcaudio_select, + poll: sparcaudio_poll, ioctl: sparcaudio_ioctl, }; @@ -1960,10 +1892,10 @@ static struct file_operations sparcaudio_fops = { owner: THIS_MODULE, - llseek: sparcaudio_lseek, + llseek: sparcaudio_llseek, read: sparcaudio_read, write: sparcaudio_write, - poll: sparcaudio_select, + poll: sparcaudio_poll, ioctl: sparcaudio_ioctl, open: sparcaudio_open, release: sparcaudio_release, @@ -2032,12 +1964,10 @@ * TODO: Make number of input/output buffers tunable parameters */ -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x202ff init_waitqueue_head(&drv->open_wait); init_waitqueue_head(&drv->output_write_wait); init_waitqueue_head(&drv->output_drain_wait); init_waitqueue_head(&drv->input_read_wait); -#endif drv->num_output_buffers = 8; drv->output_buffer_size = (4096 * 2); @@ -2204,20 +2134,6 @@ return -EIO; devfs_handle = devfs_mk_dir (NULL, "sound", NULL); - -#ifdef CONFIG_SPARCAUDIO_AMD7930 - amd7930_init(); -#endif -#ifdef CONFIG_SPARCAUDIO_DBRI - dbri_init(); -#endif -#ifdef CONFIG_SPARCAUDIO_CS4231 - cs4231_init(); -#endif -#ifdef CONFIG_SPARCAUDIO_DUMMY - dummy_init(); -#endif - return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/sbus/audio/cs4231.c linux/drivers/sbus/audio/cs4231.c --- v2.4.5/linux/drivers/sbus/audio/cs4231.c Sun Mar 25 18:14:20 2001 +++ linux/drivers/sbus/audio/cs4231.c Mon Jun 11 19:15:27 2001 @@ -1,4 +1,4 @@ -/* $Id: cs4231.c,v 1.45 2001/03/23 08:16:13 davem Exp $ +/* $Id: cs4231.c,v 1.46 2001/05/21 01:25:22 davem Exp $ * drivers/sbus/audio/cs4231.c * * Copyright 1996, 1997, 1998, 1999 Derrick J Brashear (shadow@andrew.cmu.edu) @@ -35,7 +35,7 @@ #include #include #include -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff && defined(CONFIG_PCI) +#ifdef CONFIG_PCI #define EB4231_SUPPORT #include #include @@ -2178,9 +2178,6 @@ static int cs4231_attach(struct sparcaudio_driver *drv, struct sbus_dev *sdev) { -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20100 - struct linux_prom_irqs irq; -#endif struct cs4231_chip *cs4231_chip; int err; @@ -2367,12 +2364,32 @@ } #endif -/* Probe for the cs4231 chip and then attach the driver. */ -#ifdef MODULE -int init_module(void) -#else -int __init cs4231_init(void) +/* Detach from an cs4231 chip given the device structure. */ +static void __exit cs4231_detach(struct sparcaudio_driver *drv) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + + cs4231_disable_interrupts(drv); + unregister_sparcaudio_driver(drv, 1); + disable_irq(cs4231_chip->irq); + free_irq(cs4231_chip->irq, drv); + if (!(cs4231_chip->status & CS_STATUS_IS_EBUS)) { + sbus_iounmap(cs4231_chip->regs, cs4231_chip->regs_size); + } else { +#ifdef EB4231_SUPPORT + iounmap(cs4231_chip->regs); + iounmap(cs4231_chip->eb2p); + iounmap(cs4231_chip->eb2c); + disable_irq(cs4231_chip->irq2); + free_irq(cs4231_chip->irq2, drv); #endif + } + kfree(drv->private); +} + + +/* Probe for the cs4231 chip and then attach the driver. */ +static int __init cs4231_init(void) { struct sbus_bus *sbus; struct sbus_dev *sdev; @@ -2414,31 +2431,7 @@ return (num_drivers > 0) ? 0 : -EIO; } -#ifdef MODULE -/* Detach from an cs4231 chip given the device structure. */ -static void cs4231_detach(struct sparcaudio_driver *drv) -{ - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; - - cs4231_disable_interrupts(drv); - unregister_sparcaudio_driver(drv, 1); - disable_irq(cs4231_chip->irq); - free_irq(cs4231_chip->irq, drv); - if (!(cs4231_chip->status & CS_STATUS_IS_EBUS)) { - sbus_iounmap(cs4231_chip->regs, cs4231_chip->regs_size); - } else { -#ifdef EB4231_SUPPORT - iounmap(cs4231_chip->regs); - iounmap(cs4231_chip->eb2p); - iounmap(cs4231_chip->eb2c); - disable_irq(cs4231_chip->irq2); - free_irq(cs4231_chip->irq2, drv); -#endif - } - kfree(drv->private); -} - -void cleanup_module(void) +static void __exit cs4231_exit(void) { register int i; @@ -2447,8 +2440,9 @@ num_drivers--; } } -#endif +module_init(cs4231_init); +module_exit(cs4231_exit); /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff -u --recursive --new-file v2.4.5/linux/drivers/sbus/audio/dbri.c linux/drivers/sbus/audio/dbri.c --- v2.4.5/linux/drivers/sbus/audio/dbri.c Sun Feb 18 19:49:55 2001 +++ linux/drivers/sbus/audio/dbri.c Mon Jun 11 19:15:27 2001 @@ -1,4 +1,4 @@ -/* $Id: dbri.c,v 1.25 2001/02/13 01:16:59 davem Exp $ +/* $Id: dbri.c,v 1.26 2001/05/21 01:25:22 davem Exp $ * drivers/sbus/audio/dbri.c * * Copyright (C) 1997 Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de) @@ -61,7 +61,7 @@ #include #include "dbri.h" -#if defined(DBRI_ISDN) && defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff +#if defined(DBRI_ISDN) #include "../../isdn/hisax/hisax.h" #include "../../isdn/hisax/isdnl1.h" #include "../../isdn/hisax/foreign.h" @@ -2227,7 +2227,7 @@ recv_on_pipe(dbri, 8+chan, buffer, size, callback, callback_arg); } -#if defined(DBRI_ISDN) && defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff +#if defined(DBRI_ISDN) struct foreign_interface dbri_foreign_interface = { dbri_get_irqnum, dbri_get_liu_state, @@ -2336,11 +2336,7 @@ } /* Probe for the dbri chip and then attach the driver. */ -#ifdef MODULE -int init_module(void) -#else -int __init dbri_init(void) -#endif +static int __init dbri_init(void) { struct sbus_bus *sbus; struct sbus_dev *sdev; @@ -2368,8 +2364,7 @@ return (num_drivers > 0) ? 0 : -EIO; } -#ifdef MODULE -void cleanup_module(void) +static void __exit dbri_exit(void) { register int i; @@ -2379,8 +2374,9 @@ num_drivers--; } } -#endif +module_init(dbri_init); +module_exit(dbri_exit); /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff -u --recursive --new-file v2.4.5/linux/drivers/sbus/audio/dmy.c linux/drivers/sbus/audio/dmy.c --- v2.4.5/linux/drivers/sbus/audio/dmy.c Sun Feb 18 19:49:55 2001 +++ linux/drivers/sbus/audio/dmy.c Mon Jun 11 19:15:27 2001 @@ -1,4 +1,4 @@ -/* $Id: dmy.c,v 1.7 2001/02/13 01:16:59 davem Exp $ +/* $Id: dmy.c,v 1.9 2001/05/22 23:16:10 davem Exp $ * drivers/sbus/audio/dummy.c * * Copyright 1998 Derrick J Brashear (shadow@andrew.cmu.edu) @@ -36,7 +36,7 @@ static int dummy_record_gain(struct sparcaudio_driver *drv, int value, unsigned char balance); static int dummy_output_muted(struct sparcaudio_driver *drv, int value); -static int dummy_attach(struct sparcaudio_driver *drv); +static int dummy_attach(struct sparcaudio_driver *drv) __init; static int dummy_set_output_encoding(struct sparcaudio_driver *drv, int value) @@ -710,25 +710,8 @@ dummy_get_formats, }; -/* Probe for the dummy chip and then attach the driver. */ -#ifdef MODULE -int init_module(void) -#else -int __init dummy_init(void) -#endif -{ - num_drivers = 0; - - /* Add support here for specifying multiple dummies to attach at once. */ - if (dummy_attach(&drivers[num_drivers]) == 0) - num_drivers++; - - /* Only return success if we found some dummy chips. */ - return (num_drivers > 0) ? 0 : -EIO; -} - /* Attach to an dummy chip given its PROM node. */ -static int dummy_attach(struct sparcaudio_driver *drv) +static int __init dummy_attach(struct sparcaudio_driver *drv) { struct dummy_chip *dummy_chip; int err; @@ -768,15 +751,27 @@ return 0; } -#ifdef MODULE /* Detach from an dummy chip given the device structure. */ -static void dummy_detach(struct sparcaudio_driver *drv) +static void __exit dummy_detach(struct sparcaudio_driver *drv) { unregister_sparcaudio_driver(drv, 2); kfree(drv->private); } -void cleanup_module(void) +/* Probe for the dummy chip and then attach the driver. */ +static int __init dummy_init(void) +{ + num_drivers = 0; + + /* Add support here for specifying multiple dummies to attach at once. */ + if (dummy_attach(&drivers[num_drivers]) == 0) + num_drivers++; + + /* Only return success if we found some dummy chips. */ + return (num_drivers > 0) ? 0 : -EIO; +} + +static void __exit dummy_exit(void) { int i; @@ -785,8 +780,9 @@ num_drivers--; } } -#endif +module_init(dummy_init); +module_exit(dummy_exit); /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff -u --recursive --new-file v2.4.5/linux/drivers/sbus/char/aurora.h linux/drivers/sbus/char/aurora.h --- v2.4.5/linux/drivers/sbus/char/aurora.h Mon Dec 20 22:06:42 1999 +++ linux/drivers/sbus/char/aurora.h Thu Jun 14 14:16:58 2001 @@ -1,4 +1,4 @@ -/* $Id: aurora.h,v 1.5 1999/12/02 09:55:16 davem Exp $ +/* $Id: aurora.h,v 1.6 2001/06/05 12:23:38 davem Exp $ * linux/drivers/sbus/char/aurora.h -- Aurora multiport driver * * Copyright (c) 1999 by Oliver Aldulea (oli@bv.ro) @@ -244,7 +244,7 @@ struct tty_struct * tty; int count; int blocked_open; - int event; + long event; int timeout; int close_delay; long session; diff -u --recursive --new-file v2.4.5/linux/drivers/sbus/char/pcikbd.c linux/drivers/sbus/char/pcikbd.c --- v2.4.5/linux/drivers/sbus/char/pcikbd.c Wed May 16 10:31:27 2001 +++ linux/drivers/sbus/char/pcikbd.c Wed Jun 20 21:00:55 2001 @@ -1,4 +1,4 @@ -/* $Id: pcikbd.c,v 1.54 2001/05/11 07:46:28 davem Exp $ +/* $Id: pcikbd.c,v 1.58 2001/06/10 06:51:03 davem Exp $ * pcikbd.c: Ultra/AX PC keyboard support. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -54,6 +54,7 @@ static int pcikbd_mrcoffee = 0; #else #define pcikbd_mrcoffee 0 +extern void (*prom_keyboard)(void); #endif static unsigned long pcikbd_iobase = 0; @@ -66,6 +67,9 @@ static spinlock_t pcikbd_lock = SPIN_LOCK_UNLOCKED; +static void pcikbd_write(int address, int data); +static int pcikbd_wait_for_input(void); + unsigned char pckbd_read_mask = KBD_STAT_OBF; extern int pcikbd_init(void); @@ -239,7 +243,7 @@ e0_keys[scancode - 128]; } -int do_acknowledge(unsigned char scancode) +static int do_acknowledge(unsigned char scancode) { if(reply_expected) { if(scancode == KBD_REPLY_ACK) { @@ -255,10 +259,95 @@ return 1; } +#ifdef __sparc_v9__ +static void pcikbd_enter_prom(void) +{ + pcikbd_write(KBD_DATA_REG, KBD_CMD_DISABLE); + if(pcikbd_wait_for_input() != KBD_REPLY_ACK) + printk("Prom Enter: Disable keyboard: no ACK\n"); + + /* Disable PC scancode translation */ + pcikbd_write(KBD_CNTL_REG, KBD_CCMD_WRITE_MODE); + pcikbd_write(KBD_DATA_REG, KBD_MODE_SYS); + pcikbd_write(KBD_DATA_REG, KBD_CMD_ENABLE); + if (pcikbd_wait_for_input() != KBD_REPLY_ACK) + printk("Prom Enter: Enable Keyboard: no ACK\n"); +} +#endif + +static void ctrl_break(void) +{ + extern int stop_a_enabled; + unsigned long timeout; + int status, data; + int mode; + + if (!stop_a_enabled) + return; + + pcikbd_write(KBD_DATA_REG, KBD_CMD_DISABLE); + if(pcikbd_wait_for_input() != KBD_REPLY_ACK) + printk("Prom Enter: Disable keyboard: no ACK\n"); + + /* Save current mode register settings */ + pcikbd_write(KBD_CNTL_REG, KBD_CCMD_READ_MODE); + if ((mode = pcikbd_wait_for_input()) == -1) + printk("Prom Enter: Read Mode: no ACK\n"); + + /* Disable PC scancode translation */ + pcikbd_write(KBD_CNTL_REG, KBD_CCMD_WRITE_MODE); + pcikbd_write(KBD_DATA_REG, mode & ~(KBD_MODE_KCC)); + pcikbd_write(KBD_DATA_REG, KBD_CMD_ENABLE); + if (pcikbd_wait_for_input() != KBD_REPLY_ACK) + printk("Prom Enter: Enable Keyboard: no ACK\n"); + + /* Drop into OBP. + * Note that we must flush the user windows + * first before giving up control. + */ + flush_user_windows(); + prom_cmdline(); + + /* Read prom's key up event (use short timeout) */ + do { + timeout = 10; + do { + mdelay(1); + status = pcikbd_inb(pcikbd_iobase + KBD_STATUS_REG); + if (!(status & KBD_STAT_OBF)) + continue; + data = pcikbd_inb(pcikbd_iobase + KBD_DATA_REG); + if (status & (KBD_STAT_GTO | KBD_STAT_PERR)) + continue; + break; + } while (--timeout > 0); + } while (timeout > 0); + + /* Reenable PC scancode translation */ + pcikbd_write(KBD_DATA_REG, KBD_CMD_DISABLE); + if(pcikbd_wait_for_input() != KBD_REPLY_ACK) + printk("Prom Leave: Disable keyboard: no ACK\n"); + + pcikbd_write(KBD_CNTL_REG, KBD_CCMD_WRITE_MODE); + pcikbd_write(KBD_DATA_REG, mode); + pcikbd_write(KBD_DATA_REG, KBD_CMD_ENABLE); + if (pcikbd_wait_for_input() != KBD_REPLY_ACK) + printk("Prom Leave: Enable Keyboard: no ACK\n"); + + /* Reset keyboard rate */ + pcikbd_write(KBD_DATA_REG, KBD_CMD_SET_RATE); + if(pcikbd_wait_for_input() != KBD_REPLY_ACK) + printk("Prom Leave: Set rate: no ACK\n"); + pcikbd_write(KBD_DATA_REG, 0x00); + if(pcikbd_wait_for_input() != KBD_REPLY_ACK) + printk("Prom Leave: Set rate: no ACK\n"); +} + int pcikbd_translate(unsigned char scancode, unsigned char *keycode, char raw_mode) { static int prev_scancode = 0; + int down = scancode & 0x80 ? 0 : 1; if (scancode == 0xe0 || scancode == 0xe1) { prev_scancode = scancode; @@ -297,6 +386,18 @@ } else *keycode = scancode; + + if (*keycode == E0_BREAK) { + if (down) + return 0; + + /* Handle ctrl-break event */ + ctrl_break(); + + /* Send ctrl up event to the keyboard driver */ + *keycode = 0x1d; + } + return 1; } @@ -338,11 +439,11 @@ int retries = 3; unsigned long flags; - spin_lock_irqsave(&pcikbd_lock, flags); - do { unsigned long timeout = 1000; + spin_lock_irqsave(&pcikbd_lock, flags); + kb_wait(); acknowledge = 0; @@ -350,24 +451,23 @@ reply_expected = 1; pcikbd_outb(data, pcikbd_iobase + KBD_DATA_REG); + + spin_unlock_irqrestore(&pcikbd_lock, flags); + do { if (acknowledge) - goto out_ack; + return 1; if (resend) break; mdelay(1); } while (--timeout); + if (timeout == 0) - goto out_timeout; + break; + } while (retries-- > 0); -out_timeout: - spin_unlock_irqrestore(&pcikbd_lock, flags); return 0; - -out_ack: - spin_unlock_irqrestore(&pcikbd_lock, flags); - return 1; } void pcikbd_leds(unsigned char leds) @@ -378,7 +478,7 @@ send_data(KBD_CMD_ENABLE); } -static int __init pcikbd_wait_for_input(void) +static int pcikbd_wait_for_input(void) { int status, data; unsigned long timeout = 1000; @@ -401,7 +501,7 @@ return -1; } -static void __init pcikbd_write(int address, int data) +static void pcikbd_write(int address, int data) { int status; @@ -664,6 +764,8 @@ kd_mksound = pcikbd_kd_mksound; printk("8042(speaker): iobase[%016lx]%s\n", pcibeep_iobase, edev ? "" : " (forced)"); + + prom_keyboard = pcikbd_enter_prom; #endif disable_irq(pcikbd_irq); diff -u --recursive --new-file v2.4.5/linux/drivers/sbus/char/sab82532.c linux/drivers/sbus/char/sab82532.c --- v2.4.5/linux/drivers/sbus/char/sab82532.c Thu Apr 19 08:38:49 2001 +++ linux/drivers/sbus/char/sab82532.c Fri Jun 29 19:38:26 2001 @@ -1,8 +1,11 @@ -/* $Id: sab82532.c,v 1.58 2001/04/17 06:30:36 davem Exp $ +/* $Id: sab82532.c,v 1.63 2001/06/29 21:23:44 davem Exp $ * sab82532.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) * + * Rewrote buffer handling to use CIRC(Circular Buffer) macros. + * Maxim Krasnyanskiy + * */ #include @@ -59,6 +62,7 @@ #undef SERIAL_DEBUG_WAIT_UNTIL_SENT #undef SERIAL_DEBUG_SEND_BREAK #undef SERIAL_DEBUG_INTR +#undef SERIAL_DEBUG_FIFO #define SERIAL_DEBUG_OVERFLOW 1 /* Trace things on serial device, useful for console debugging: */ @@ -209,22 +213,23 @@ save_flags(flags); cli(); - if (info->xmit_cnt <= 0) + if (info->xmit.head == info->xmit.tail) goto out; - if (!(readb(&info->regs->r.star) & SAB82532_STAR_XFW)) + if (!test_bit(SAB82532_XPR, &info->irqflags)) goto out; info->interrupt_mask1 &= ~(SAB82532_IMR1_ALLS); writeb(info->interrupt_mask1, &info->regs->w.imr1); - info->all_sent = 0; + clear_bit(SAB82532_ALLS, &info->irqflags); + clear_bit(SAB82532_XPR, &info->irqflags); for (i = 0; i < info->xmit_fifo_size; i++) { - u8 val = info->xmit_buf[info->xmit_tail++]; - writeb(val, &info->regs->w.xfifo[i]); - info->xmit_tail &= (SERIAL_XMIT_SIZE - 1); + writeb(info->xmit.buf[info->xmit.tail], + &info->regs->w.xfifo[i]); + info->xmit.tail = (info->xmit.tail + 1) & (SERIAL_XMIT_SIZE-1); info->icount.tx++; - if (--info->xmit_cnt <= 0) + if (info->xmit.head == info->xmit.tail) break; } @@ -397,20 +402,29 @@ if (stat->sreg.isr1 & SAB82532_ISR1_ALLS) { info->interrupt_mask1 |= SAB82532_IMR1_ALLS; writeb(info->interrupt_mask1, &info->regs->w.imr1); - info->all_sent = 1; + set_bit(SAB82532_ALLS, &info->irqflags); } if (!(stat->sreg.isr1 & SAB82532_ISR1_XPR)) return; + if (!(readb(&info->regs->r.star) & SAB82532_STAR_XFW)) { +#ifdef SERIAL_DEBUG_FIFO + printk("%s: XPR, but no XFW (?)\n", __FUNCTION__); +#endif + return; + } + + set_bit(SAB82532_XPR, &info->irqflags); + if (!info->tty) { info->interrupt_mask1 |= SAB82532_IMR1_XPR; writeb(info->interrupt_mask1, &info->regs->w.imr1); return; } - if ((info->xmit_cnt <= 0) || info->tty->stopped || - info->tty->hw_stopped) { + if ((info->xmit.head == info->xmit.tail) || + info->tty->stopped || info->tty->hw_stopped) { info->interrupt_mask1 |= SAB82532_IMR1_XPR; writeb(info->interrupt_mask1, &info->regs->w.imr1); return; @@ -418,15 +432,16 @@ info->interrupt_mask1 &= ~(SAB82532_IMR1_ALLS); writeb(info->interrupt_mask1, &info->regs->w.imr1); - info->all_sent = 0; + clear_bit(SAB82532_ALLS, &info->irqflags); /* Stuff 32 bytes into Transmit FIFO. */ + clear_bit(SAB82532_XPR, &info->irqflags); for (i = 0; i < info->xmit_fifo_size; i++) { - u8 val = info->xmit_buf[info->xmit_tail++]; - writeb(val, &info->regs->w.xfifo[i]); - info->xmit_tail &= (SERIAL_XMIT_SIZE - 1); + writeb(info->xmit.buf[info->xmit.tail], + &info->regs->w.xfifo[i]); + info->xmit.tail = (info->xmit.tail + 1) & (SERIAL_XMIT_SIZE-1); info->icount.tx++; - if (--info->xmit_cnt <= 0) + if (info->xmit.head == info->xmit.tail) break; } @@ -434,16 +449,12 @@ sab82532_cec_wait(info); writeb(SAB82532_CMDR_XF, &info->regs->w.cmdr); - if (info->xmit_cnt < WAKEUP_CHARS) + if (CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) < WAKEUP_CHARS) sab82532_sched_event(info, RS_EVENT_WRITE_WAKEUP); #ifdef SERIAL_DEBUG_INTR printk("THRE..."); #endif - if (info->xmit_cnt <= 0) { - info->interrupt_mask1 |= SAB82532_IMR1_XPR; - writeb(info->interrupt_mask1, &info->regs->w.imr1); - } } static void check_status(struct sab82532 *info, @@ -620,6 +631,7 @@ transmit_chars(info, &status); done: + ; #ifdef SERIAL_DEBUG_INTR printk("end.\n"); #endif @@ -774,10 +786,10 @@ retval = -ENODEV; goto errout; } - if (info->xmit_buf) + if (info->xmit.buf) free_page(page); else - info->xmit_buf = (unsigned char *)page; + info->xmit.buf = (unsigned char *)page; #ifdef SERIAL_DEBUG_OPEN printk("starting up serial port %d...", info->line); @@ -812,11 +824,13 @@ SAB82532_IMR1_CSC | SAB82532_IMR1_XON | SAB82532_IMR1_XPR; writeb(info->interrupt_mask1, &info->regs->w.imr1); - info->all_sent = 1; + set_bit(SAB82532_ALLS, &info->irqflags); if (info->tty) clear_bit(TTY_IO_ERROR, &info->tty->flags); - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + info->xmit.head = info->xmit.tail = 0; + + set_bit(SAB82532_XPR, &info->irqflags); /* * and set the speed of the serial port @@ -856,9 +870,9 @@ */ wake_up_interruptible(&info->delta_msr_wait); - if (info->xmit_buf) { - free_page((unsigned long)info->xmit_buf); - info->xmit_buf = 0; + if (info->xmit.buf) { + free_page((unsigned long)info->xmit.buf); + info->xmit.buf = 0; } #ifdef CONFIG_SERIAL_CONSOLE @@ -886,9 +900,11 @@ writeb(info->interrupt_mask1, &info->regs->w.imr1); if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { - writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FRTS, &info->regs->rw.mode); - writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode); - writeb(readb(&info->regs->rw.pvr) | info->pvr_dtr_bit, &info->regs->rw.pvr); + tmp = readb(&info->regs->r.mode); + tmp |= (SAB82532_MODE_FRTS | SAB82532_MODE_RTS); + writeb(tmp, &info->regs->rw.mode); + writeb(readb(&info->regs->rw.pvr) | info->pvr_dtr_bit, + &info->regs->rw.pvr); } /* Disable break condition */ @@ -1054,18 +1070,17 @@ if (serial_paranoia_check(info, tty->device, "sab82532_put_char")) return; - if (!tty || !info->xmit_buf) + if (!tty || !info->xmit.buf) return; save_flags(flags); cli(); - if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1) { + if (!CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE)) { restore_flags(flags); return; } - info->xmit_buf[info->xmit_head++] = ch; - info->xmit_head &= SERIAL_XMIT_SIZE-1; - info->xmit_cnt++; + info->xmit.buf[info->xmit.head] = ch; + info->xmit.head = (info->xmit.head + 1) & (SERIAL_XMIT_SIZE-1); restore_flags(flags); } @@ -1077,8 +1092,8 @@ if (serial_paranoia_check(info, tty->device, "sab82532_flush_chars")) return; - if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || - !info->xmit_buf) + if ((info->xmit.head == info->xmit.tail) || + tty->stopped || tty->hw_stopped || !info->xmit.buf) return; save_flags(flags); cli(); @@ -1098,42 +1113,63 @@ if (serial_paranoia_check(info, tty->device, "sab82532_write")) return 0; - if (!tty || !info->xmit_buf || !tmp_buf) + if (!tty || !info->xmit.buf || !tmp_buf) return 0; - if (from_user) - down(&tmp_buf_sem); save_flags(flags); - while (1) { - cli(); - c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - if (c <= 0) - break; + if (from_user) { + down(&tmp_buf_sem); + while (1) { + int c1; + c = CIRC_SPACE_TO_END(info->xmit.head, + info->xmit.tail, + SERIAL_XMIT_SIZE); + if (count < c) + c = count; + if (c <= 0) + break; - if (from_user) { c -= copy_from_user(tmp_buf, buf, c); if (!c) { if (!ret) ret = -EFAULT; break; } - c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); - } else - memcpy(info->xmit_buf + info->xmit_head, buf, c); - info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt += c; + cli(); + c1 = CIRC_SPACE_TO_END(info->xmit.head, + info->xmit.tail, + SERIAL_XMIT_SIZE); + if (c1 < c) + c = c1; + memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c); + info->xmit.head = (info->xmit.head + c) & (SERIAL_XMIT_SIZE-1); + restore_flags(flags); + buf += c; + count -= c; + ret += c; + } + up(&tmp_buf_sem); + } else { + cli(); + while (1) { + c = CIRC_SPACE_TO_END(info->xmit.head, + info->xmit.tail, + SERIAL_XMIT_SIZE); + if (count < c) + c = count; + if (c <= 0) + break; + memcpy(info->xmit.buf + info->xmit.head, buf, c); + info->xmit.head = (info->xmit.head + c) & (SERIAL_XMIT_SIZE-1); + buf += c; + count -= c; + ret += c; + } restore_flags(flags); - buf += c; - count -= c; - ret += c; } - if (from_user) - up(&tmp_buf_sem); - if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) { + if ((info->xmit.head != info->xmit.tail) && + !tty->stopped && !tty->hw_stopped) { info->interrupt_mask1 &= ~(SAB82532_IMR1_XPR); writeb(info->interrupt_mask1, &info->regs->w.imr1); sab82532_start_tx(info); @@ -1146,14 +1182,11 @@ static int sab82532_write_room(struct tty_struct *tty) { struct sab82532 *info = (struct sab82532 *)tty->driver_data; - int ret; if (serial_paranoia_check(info, tty->device, "sab82532_write_room")) return 0; - ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; - if (ret < 0) - ret = 0; - return ret; + + return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); } static int sab82532_chars_in_buffer(struct tty_struct *tty) @@ -1162,18 +1195,22 @@ if (serial_paranoia_check(info, tty->device, "sab82532_chars_in_buffer")) return 0; - return info->xmit_cnt; + + return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); } static void sab82532_flush_buffer(struct tty_struct *tty) { struct sab82532 *info = (struct sab82532 *)tty->driver_data; + unsigned long flags; if (serial_paranoia_check(info, tty->device, "sab82532_flush_buffer")) return; - cli(); - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - sti(); + + save_flags(flags); cli(); + info->xmit.head = info->xmit.tail = 0; + restore_flags(flags); + wake_up_interruptible(&tty->write_wait); if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) @@ -1221,6 +1258,12 @@ if (I_IXOFF(tty)) sab82532_send_xchar(tty, STOP_CHAR(tty)); + + if (tty->termios->c_cflag & CRTSCTS) { + u8 mode = readb(&info->regs->r.mode); + mode &= ~(SAB82532_MODE_FRTS | SAB82532_MODE_RTS); + writeb(mode, &info->regs->w.mode); + } } static void sab82532_unthrottle(struct tty_struct * tty) @@ -1242,6 +1285,13 @@ else sab82532_send_xchar(tty, START_CHAR(tty)); } + + if (tty->termios->c_cflag & CRTSCTS) { + u8 mode = readb(&info->regs->r.mode); + mode &= ~(SAB82532_MODE_RTS); + mode |= SAB82532_MODE_FRTS; + writeb(mode, &info->regs->w.mode); + } } /* @@ -1295,7 +1345,8 @@ { unsigned int result; - result = (!info->xmit_buf && info->all_sent) ? TIOCSER_TEMT : 0; + result = (!info->xmit.buf && test_bit(SAB82532_ALLS, &info->irqflags)) + ? TIOCSER_TEMT : 0; return put_user(result, value); } @@ -1317,12 +1368,10 @@ static int set_modem_info(struct sab82532 * info, unsigned int cmd, unsigned int *value) { - int error; unsigned int arg; - error = get_user(arg, value); - if (error) - return error; + if (get_user(arg, value)) + return -EFAULT; switch (cmd) { case TIOCMBIS: if (arg & TIOCM_RTS) { @@ -1391,7 +1440,6 @@ static int sab82532_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) { - int error; struct sab82532 * info = (struct sab82532 *)tty->driver_data; struct async_icount cprev, cnow; /* kernel counter temps */ struct serial_icounter_struct *p_cuser; /* user space */ @@ -1411,9 +1459,8 @@ case TIOCGSOFTCAR: return put_user(C_CLOCAL(tty) ? 1 : 0, (int *) arg); case TIOCSSOFTCAR: - error = get_user(arg, (unsigned int *) arg); - if (error) - return error; + if (get_user(arg, (unsigned int *) arg)) + return -EFAULT; tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); @@ -1483,14 +1530,11 @@ cnow = info->icount; sti(); p_cuser = (struct serial_icounter_struct *) arg; - error = put_user(cnow.cts, &p_cuser->cts); - if (error) return error; - error = put_user(cnow.dsr, &p_cuser->dsr); - if (error) return error; - error = put_user(cnow.rng, &p_cuser->rng); - if (error) return error; - error = put_user(cnow.dcd, &p_cuser->dcd); - if (error) return error; + if (put_user(cnow.cts, &p_cuser->cts) || + put_user(cnow.dsr, &p_cuser->dsr) || + put_user(cnow.rng, &p_cuser->rng) || + put_user(cnow.dcd, &p_cuser->dcd)) + return -EFAULT; return 0; default: @@ -1523,8 +1567,12 @@ if (!(old_termios->c_cflag & CBAUD) && (tty->termios->c_cflag & CBAUD)) { writeb(readb(&info->regs->w.pvr) & ~(info->pvr_dtr_bit), &info->regs->w.pvr); - if (!tty->hw_stopped || - !(tty->termios->c_cflag & CRTSCTS)) { + if (tty->termios->c_cflag & CRTSCTS) { + writeb(readb(&info->regs->w.mode) & ~(SAB82532_MODE_RTS), &info->regs->w.mode); + writeb(readb(&info->regs->w.mode) | SAB82532_MODE_FRTS, &info->regs->w.mode); + } else if (test_bit(TTY_THROTTLED, &tty->flags)) { + writeb(readb(&info->regs->w.mode) & ~(SAB82532_MODE_FRTS | SAB82532_MODE_RTS), &info->regs->w.mode); + } else { writeb(readb(&info->regs->w.mode) & ~(SAB82532_MODE_FRTS), &info->regs->w.mode); writeb(readb(&info->regs->w.mode) | SAB82532_MODE_RTS, &info->regs->w.mode); } @@ -1654,7 +1702,6 @@ if (serial_paranoia_check(info,tty->device,"sab82532_wait_until_sent")) return; - orig_jiffies = jiffies; /* * Set the check interval to be 1/5 of the estimated time to * send a single character, and make it at least 1. The check @@ -1670,10 +1717,15 @@ if (timeout) char_time = MIN(char_time, timeout); #ifdef SERIAL_DEBUG_WAIT_UNTIL_SENT - printk("In sab82532_wait_until_sent(%d) check=%lu...", timeout, char_time); - printk("jiff=%lu...", jiffies); + printk("In sab82532_wait_until_sent(%d) check=%lu " + "xmit_cnt = %ld, alls = %d (jiff=%lu)...\n", + timeout, char_time, + CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE), + test_bit(SAB82532_ALLS, &info->irqflags), jiffies); #endif - while (info->xmit_cnt || !info->all_sent) { + orig_jiffies = jiffies; + while ((info->xmit.head != info->xmit.tail) || + !test_bit(SAB82532_ALLS, &info->irqflags)) { current->state = TASK_INTERRUPTIBLE; schedule_timeout(char_time); if (signal_pending(current)) @@ -1682,7 +1734,9 @@ break; } #ifdef SERIAL_DEBUG_WAIT_UNTIL_SENT - printk("xmit_cnt = %d, alls = %d (jiff=%lu)...done\n", info->xmit_cnt, info->all_sent, jiffies); + printk("xmit_cnt = %ld, alls = %d (jiff=%lu)...done\n", + CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE), + test_bit(SAB82532_ALLS, &info->irqflags), jiffies); #endif } @@ -2151,7 +2205,7 @@ static inline void __init show_serial_version(void) { - char *revision = "$Revision: 1.58 $"; + char *revision = "$Revision: 1.63 $"; char *version, *p; version = strchr(revision, ' '); diff -u --recursive --new-file v2.4.5/linux/drivers/sbus/char/su.c linux/drivers/sbus/char/su.c --- v2.4.5/linux/drivers/sbus/char/su.c Sat May 19 12:48:33 2001 +++ linux/drivers/sbus/char/su.c Fri Jun 29 19:38:26 2001 @@ -1,4 +1,4 @@ -/* $Id: su.c,v 1.50 2001/05/16 08:37:03 davem Exp $ +/* $Id: su.c,v 1.52 2001/06/29 21:54:32 davem Exp $ * su.c: Small serial driver for keyboard/mouse interface on sparc32/PCI * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -228,9 +228,9 @@ kdev_t device, const char *routine) { #ifdef SERIAL_PARANOIA_CHECK - static const char *badmagic = + static const char *badmagic = KERN_WARNING "Warning: bad magic number for serial struct (%s) in %s\n"; - static const char *badinfo = + static const char *badinfo = KERN_WARNING "Warning: null su_struct for (%s) in %s\n"; if (!info) { @@ -1500,13 +1500,11 @@ static int set_modem_info(struct su_struct * info, unsigned int cmd, unsigned int *value) { - int error; unsigned int arg; unsigned long flags; - error = get_user(arg, value); - if (error) - return error; + if (get_user(arg, value)) + return -EFAULT; switch (cmd) { case TIOCMBIS: if (arg & TIOCM_RTS) @@ -1583,7 +1581,6 @@ su_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) { - int error; struct su_struct * info = (struct su_struct *)tty->driver_data; struct async_icount cprev, cnow; /* kernel counter temps */ struct serial_icounter_struct *p_cuser; /* user space */ @@ -1663,14 +1660,11 @@ cnow = info->icount; sti(); p_cuser = (struct serial_icounter_struct *) arg; - error = put_user(cnow.cts, &p_cuser->cts); - if (error) return error; - error = put_user(cnow.dsr, &p_cuser->dsr); - if (error) return error; - error = put_user(cnow.rng, &p_cuser->rng); - if (error) return error; - error = put_user(cnow.dcd, &p_cuser->dcd); - if (error) return error; + if (put_user(cnow.cts, &p_cuser->cts) || + put_user(cnow.dsr, &p_cuser->dsr) || + put_user(cnow.rng, &p_cuser->rng) || + put_user(cnow.dcd, &p_cuser->dcd)) + return -EFAULT; return 0; default: @@ -2261,7 +2255,7 @@ */ static __inline__ void __init show_su_version(void) { - char *revision = "$Revision: 1.50 $"; + char *revision = "$Revision: 1.52 $"; char *version, *p; version = strchr(revision, ' '); diff -u --recursive --new-file v2.4.5/linux/drivers/sbus/char/zs.c linux/drivers/sbus/char/zs.c --- v2.4.5/linux/drivers/sbus/char/zs.c Wed May 16 10:31:27 2001 +++ linux/drivers/sbus/char/zs.c Fri Jun 29 19:38:26 2001 @@ -1,4 +1,4 @@ -/* $Id: zs.c,v 1.65 2001/05/09 07:00:10 davem Exp $ +/* $Id: zs.c,v 1.66 2001/06/29 21:33:22 davem Exp $ * zs.c: Zilog serial port driver for the Sparc. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -177,7 +177,7 @@ #define REGCTRL 0xfd }; struct zs_logent zslog[32]; -int zs_curlog = 0; +int zs_curlog; #define ZSLOG(__reg, __val, __write) \ do{ int index = zs_curlog; \ zslog[index].reg = (__reg); \ @@ -1945,7 +1945,7 @@ static void show_serial_version(void) { - char *revision = "$Revision: 1.65 $"; + char *revision = "$Revision: 1.66 $"; char *version, *p; version = strchr(revision, ' '); diff -u --recursive --new-file v2.4.5/linux/drivers/scsi/3w-xxxx.c linux/drivers/scsi/3w-xxxx.c --- v2.4.5/linux/drivers/scsi/3w-xxxx.c Fri Apr 27 13:59:17 2001 +++ linux/drivers/scsi/3w-xxxx.c Wed Jun 27 17:10:55 2001 @@ -76,6 +76,20 @@ Make tw_setfeature() call with interrupts disabled. Register interrupt handler before enabling interrupts. Clear attention interrupt before draining aen queue. + 1.02.00.005 - Allocate bounce buffers and custom queue depth for raid5 for + 6000 and 5000 series controllers. + Reduce polling mdelays causing problems on some systems. + Fix use_sg = 1 calculation bug. + Check for scsi_register returning NULL. + Add aen count to /proc/scsi/3w-xxxx. + Remove aen code unit masking in tw_aen_complete(). + 1.02.00.006 - Remove unit from printk in tw_scsi_eh_abort(), causing + possible oops. + Fix possible null pointer dereference in tw_scsi_queue() + if done function pointer was invalid. + 1.02.00.007 - Fix possible null pointer dereferences in tw_ioctl(). + Remove check for invalid done function pointer from + tw_scsi_queue(). */ #include @@ -121,7 +135,7 @@ }; /* Globals */ -char *tw_driver_version="1.02.00.004"; +char *tw_driver_version="1.02.00.007"; TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT]; int tw_device_extension_count = 0; @@ -131,7 +145,7 @@ int tw_aen_complete(TW_Device_Extension *tw_dev, int request_id) { TW_Param *param; - unsigned short aen, aen_code; + unsigned short aen; if (tw_dev->alignment_virtual_address[request_id] == NULL) { printk(KERN_WARNING "3w-xxxx: tw_aen_complete(): Bad alignment virtual address.\n"); @@ -139,10 +153,9 @@ } param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; aen = *(unsigned short *)(param->data); - aen_code = (aen & 0x0ff); - dprintk(KERN_NOTICE "3w-xxxx: tw_aen_complete(): Queue'd code 0x%x\n", aen_code); + dprintk(KERN_NOTICE "3w-xxxx: tw_aen_complete(): Queue'd code 0x%x\n", aen); /* Now queue the code */ - tw_dev->aen_queue[tw_dev->aen_tail] = aen_code; + tw_dev->aen_queue[tw_dev->aen_tail] = aen; if (tw_dev->aen_tail == TW_Q_LENGTH - 1) { tw_dev->aen_tail = TW_Q_START; } else { @@ -241,7 +254,7 @@ /* Now poll for completion */ for (i=0;icommand_packet_virtual_address[request_id] = virt_addr; - tw_dev->command_packet_physical_address[request_id] = - virt_to_bus(virt_addr); - } else { + tw_dev->command_packet_physical_address[request_id] = virt_to_bus(virt_addr); + break; + case 1: tw_dev->alignment_virtual_address[request_id] = virt_addr; tw_dev->alignment_physical_address[request_id] = virt_to_bus(virt_addr); + break; + case 2: + tw_dev->bounce_buffer[request_id] = virt_addr; + break; + default: + printk(KERN_WARNING "3w-xxxx: tw_allocate_memory(): case slip in tw_allocate_memory()\n"); + return 1; } return 0; } /* End tw_allocate_memory() */ @@ -709,8 +730,8 @@ /* Register the card with the kernel SCSI layer */ host = scsi_register(tw_host, sizeof(TW_Device_Extension)); - if( host == NULL) - { + if (host == NULL) { + printk(KERN_WARNING "3w-xxxx: tw_findcards(): scsi_register() failed for card %d.\n", numcards-1); release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE); tw_free_device_extension(tw_dev); kfree(tw_dev); @@ -788,6 +809,9 @@ if (tw_dev->alignment_virtual_address[i]) kfree(tw_dev->alignment_virtual_address[i]); + + if (tw_dev->bounce_buffer[i]) + kfree(tw_dev->bounce_buffer[i]); } } /* End tw_free_device_extension() */ @@ -853,7 +877,7 @@ /* Poll for completion */ imax = TW_POLL_MAX_RETRIES; for (i=0;iaen_queue[i] = 0; } - for (i=0;iis_unit_present[i] = 0; + tw_dev->is_raid_five[i] = 0; + } tw_dev->num_units = 0; tw_dev->num_aborts = 0; @@ -928,6 +954,8 @@ tw_dev->aen_tail = 0; tw_dev->sector_count = 0; tw_dev->max_sector_count = 0; + tw_dev->aen_count = 0; + tw_dev->num_raid_five = 0; spin_lock_init(&tw_dev->tw_lock); tw_dev->flags = 0; return 0; @@ -940,13 +968,14 @@ unsigned char request_id = 0; TW_Command *command_packet; TW_Param *param; - int i, imax, num_units = 0; + int i, j, imax, num_units = 0, num_raid_five = 0; u32 status_reg_addr, status_reg_value; u32 command_que_addr, command_que_value; u32 response_que_addr; TW_Response_Queue response_queue; u32 param_value; unsigned char *is_unit_present; + unsigned char *raid_level; dprintk(KERN_NOTICE "3w-xxxx: tw_initialize_units()\n"); @@ -1001,7 +1030,7 @@ /* Poll for completion */ imax = TW_POLL_MAX_RETRIES; for(i=0; iis_unit_present[j] == 0) + continue; + command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; + if (command_packet == NULL) { + printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad command packet virtual address.\n"); + return 1; + } + memset(command_packet, 0, sizeof(TW_Sector)); + command_packet->byte0.opcode = TW_OP_GET_PARAM; + command_packet->byte0.sgl_offset = 2; + command_packet->size = 4; + command_packet->request_id = request_id; + command_packet->byte3.unit = 0; + command_packet->byte3.host_id = 0; + command_packet->status = 0; + command_packet->flags = 0; + command_packet->byte6.block_count = 1; + + /* Now setup the param */ + if (tw_dev->alignment_virtual_address[request_id] == NULL) { + printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad alignment virtual address.\n"); + return 1; + } + param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; + memset(param, 0, sizeof(TW_Sector)); + param->table_id = 0x300+j; /* unit summary table */ + param->parameter_id = 0x6; /* unit descriptor */ + param->parameter_size_bytes = 0xc; + param_value = tw_dev->alignment_physical_address[request_id]; + if (param_value == 0) { + printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad alignment physical address.\n"); + return 1; + } + + command_packet->byte8.param.sgl[0].address = param_value; + command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector); + + /* Post the command packet to the board */ + command_que_value = tw_dev->command_packet_physical_address[request_id]; + if (command_que_value == 0) { + printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad command packet physical address.\n"); + return 1; + } + outl(command_que_value, command_que_addr); + + /* Poll for completion */ + imax = TW_POLL_MAX_RETRIES; + for(i=0; istatus != 0) { + /* bad response */ + printk(KERN_WARNING "3w-xxxx: tw_initia +lize_units(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags); + return 1; + } + found = 1; + break; + } + } + if (found == 0) { + /* response never received */ + printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): No + response.\n"); + return 1; + } + + param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; + raid_level = (unsigned char *)&(param->data[1]); + if (*raid_level == 5) { + dprintk(KERN_WARNING "3w-xxxx: Found unit %d to be a raid5 unit.\n", j); + tw_dev->is_raid_five[j] = 1; + num_raid_five++; + } + } + tw_dev->num_raid_five = num_raid_five; + + /* Now allocate raid5 bounce buffers */ + if ((num_raid_five != 0) && (tw_dev->tw_pci_dev->device == TW_DEVICE_ID)) { + for (i=0;ibounce_buffer[i] == NULL) { + printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bounce buffer allocation failed.\n"); + return 1; + } + memset(tw_dev->bounce_buffer[i], 0, sizeof(TW_Sector)*256); + } + } return 0; } /* End tw_initialize_units() */ @@ -1288,12 +1421,17 @@ case TW_OP_SET_PARAM: dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_SET_PARAM: table_id = %d, parameter_id = %d, parameter_size_bytes = %d.\n", ioctl->table_id, ioctl->parameter_id, ioctl->parameter_size_bytes); - command_packet->byte0.opcode = TW_OP_SET_PARAM; - param->table_id = ioctl->table_id; - param->parameter_id = ioctl->parameter_id; - param->parameter_size_bytes = ioctl->parameter_size_bytes; - memcpy(param->data, ioctl->data, ioctl->parameter_size_bytes); - break; + if (ioctl->data != NULL) { + command_packet->byte0.opcode = TW_OP_SET_PARAM; + param->table_id = ioctl->table_id; + param->parameter_id = ioctl->parameter_id; + param->parameter_size_bytes = ioctl->parameter_size_bytes; + memcpy(param->data, ioctl->data, ioctl->parameter_size_bytes); + break; + } else { + printk(KERN_WARNING "3w-xxxx: tw_ioctl(): ioctl->data NULL.\n"); + return 1; + } case TW_OP_AEN_LISTEN: dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_AEN_LISTEN.\n"); if (tw_dev->aen_head == tw_dev->aen_tail) { @@ -1318,11 +1456,15 @@ tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); return 0; case TW_CMD_PACKET: - memcpy(command_packet, ioctl->data, sizeof(TW_Command)); - command_packet->request_id = request_id; - tw_post_command_packet(tw_dev, request_id); - - return 0; + if (ioctl->data != NULL) { + memcpy(command_packet, ioctl->data, sizeof(TW_Command)); + command_packet->request_id = request_id; + tw_post_command_packet(tw_dev, request_id); + return 0; + } else { + printk(KERN_WARNING "3w-xxxx: tw_ioctl(): ioctl->data NULL.\n"); + return 1; + } default: printk(KERN_WARNING "3w-xxxx: Unknown ioctl 0x%x.\n", opcode); tw_dev->state[request_id] = TW_S_COMPLETED; @@ -1602,10 +1744,8 @@ return 0; } - spin_unlock_irq(&io_request_lock); ret = tw_findcards(tw_host); - spin_lock_irq(&io_request_lock); - + return ret; } /* End tw_scsi_detect() */ @@ -1763,6 +1903,7 @@ tw_copy_info(&info, "Max sector count: %3d\n", tw_dev->max_sector_count); tw_copy_info(&info, "Resets: %3d\n", tw_dev->num_resets); tw_copy_info(&info, "Aborts: %3d\n", tw_dev->num_aborts); + tw_copy_info(&info, "AEN's: %3d\n", tw_dev->aen_count); } if (info.position > info.offset) { return (info.position - info.offset); @@ -1780,6 +1921,13 @@ int flags = 0; TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->host->hostdata; + if (tw_dev == NULL) { + printk(KERN_WARNING "3w-xxxx: tw_scsi_queue(): Invalid device extension.\n"); + SCpnt->result = (DID_ERROR << 16); + done(SCpnt); + return 0; + } + spin_lock_irqsave(&tw_dev->tw_lock, flags); dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue()\n"); @@ -1790,20 +1938,6 @@ spin_unlock_irqrestore(&tw_dev->tw_lock, flags); return 0; } - if (done == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_scsi_queue(): Invalid done function.\n"); - SCpnt->result = (DID_ERROR << 16); - done(SCpnt); - spin_unlock_irqrestore(&tw_dev->tw_lock, flags); - return 0; - } - if (tw_dev == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_scsi_queue(): Invalid device extension.\n"); - SCpnt->result = (DID_ERROR << 16); - done(SCpnt); - spin_unlock_irqrestore(&tw_dev->tw_lock, flags); - return 0; - } /* Save done function into Scsi_Cmnd struct */ SCpnt->scsi_done = done; @@ -2104,7 +2238,7 @@ TW_Command *command_packet; u32 command_que_addr, command_que_value = 0; u32 lba = 0x0, num_sectors = 0x0; - int i; + int i, count = 0; Scsi_Cmnd *srb; struct scatterlist *sglist; @@ -2161,23 +2295,45 @@ command_packet->byte8.io.lba = lba; command_packet->byte6.block_count = num_sectors; - /* Do this if there are no sg list entries */ - if (tw_dev->srb[request_id]->use_sg == 0) { - dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): SG = 0\n"); - command_packet->byte8.io.sgl[0].address = virt_to_bus(tw_dev->srb[request_id]->request_buffer); - command_packet->byte8.io.sgl[0].length = tw_dev->srb[request_id]->request_bufflen; - } - - /* Do this if we have multiple sg list entries */ - if (tw_dev->srb[request_id]->use_sg > 0) { - for (i=0;isrb[request_id]->use_sg; i++) { - command_packet->byte8.io.sgl[i].address = virt_to_bus(sglist[i].address); - command_packet->byte8.io.sgl[i].length = sglist[i].length; - command_packet->size+=2; + if ((tw_dev->is_raid_five[tw_dev->srb[request_id]->target] == 0) || (srb->cmnd[0] == READ_6) || (srb->cmnd[0] == READ_10) || (tw_dev->tw_pci_dev->device == TW_DEVICE_ID2)) { + /* Do this if there are no sg list entries */ + if (tw_dev->srb[request_id]->use_sg == 0) { + dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): SG = 0\n"); + command_packet->byte8.io.sgl[0].address = virt_to_bus(tw_dev->srb[request_id]->request_buffer); + command_packet->byte8.io.sgl[0].length = tw_dev->srb[request_id]->request_bufflen; + } + + /* Do this if we have multiple sg list entries */ + if (tw_dev->srb[request_id]->use_sg > 0) { + for (i=0;isrb[request_id]->use_sg; i++) { + command_packet->byte8.io.sgl[i].address = virt_to_bus(sglist[i].address); + command_packet->byte8.io.sgl[i].length = sglist[i].length; + command_packet->size+=2; + } + if (tw_dev->srb[request_id]->use_sg >= 1) + command_packet->size-=2; } - if (tw_dev->srb[request_id]->use_sg > 1) - command_packet->size-=2; - } + } else { + /* Do this if there are no sg list entries for raid 5 */ + if (tw_dev->srb[request_id]->use_sg == 0) { + dprintk(KERN_WARNING "doing raid 5 write use_sg = 0, bounce_buffer[%d] = 0x%p\n", request_id, tw_dev->bounce_buffer[request_id]); + memcpy(tw_dev->bounce_buffer[request_id], tw_dev->srb[request_id]->request_buffer, tw_dev->srb[request_id]->request_bufflen); + command_packet->byte8.io.sgl[0].address = virt_to_bus(tw_dev->bounce_buffer[request_id]); + command_packet->byte8.io.sgl[0].length = tw_dev->srb[request_id]->request_bufflen; + } + + /* Do this if we have multiple sg list entries for raid 5 */ + if (tw_dev->srb[request_id]->use_sg > 0) { + dprintk(KERN_WARNING "doing raid 5 write use_sg = %d, sglist[0].length = %d\n", tw_dev->srb[request_id]->use_sg, sglist[0].length); + for (i=0;isrb[request_id]->use_sg; i++) { + memcpy((char *)(tw_dev->bounce_buffer[request_id])+count, sglist[i].address, sglist[i].length); + count+=sglist[i].length; + } + command_packet->byte8.io.sgl[0].address = virt_to_bus(tw_dev->bounce_buffer[request_id]); + command_packet->byte8.io.sgl[0].length = count; + command_packet->size = 5; /* single sgl */ + } + } /* Update SG statistics */ tw_dev->sgl_entries = tw_dev->srb[request_id]->use_sg; @@ -2287,7 +2443,7 @@ /* Poll for completion */ imax = TW_POLL_MAX_RETRIES; for (i=0;ipresent = 1; tpnt->proc_name = "NCR53c406a"; @@ -665,7 +665,7 @@ } -static void wait_intr() { +static void wait_intr(void) { int i = jiffies + WATCHDOG; while(time_after(i,jiffies) && !(inb(STAT_REG)&0xe0)) /* wait for a pseudo-interrupt */ @@ -820,8 +820,8 @@ printk("\n"); #else printk(", pio=%02x\n", pio_status); -#endif USE_DMA -#endif NCR53C406A_DEBUG +#endif /* USE_DMA */ +#endif /* NCR53C406A_DEBUG */ if(int_reg & 0x80){ /* SCSI reset intr */ rtrc(3); @@ -840,7 +840,7 @@ current_SC->scsi_done(current_SC); return; } -#endif USE_PIO +#endif /* USE_PIO */ if(status & 0x20) { /* Parity error */ printk("NCR53c406a: Warning: parity error!\n"); @@ -885,7 +885,7 @@ #if USE_DMA /* No s/g support for DMA */ NCR53c406a_dma_write(current_SC->request_buffer, current_SC->request_bufflen); -#endif USE_DMA +#endif /* USE_DMA */ outb(TRANSFER_INFO | DMA_OP, CMD_REG); #if USE_PIO if (!current_SC->use_sg) /* Don't use scatter-gather */ @@ -900,7 +900,7 @@ } } REG0; -#endif USE_PIO +#endif /* USE_PIO */ } break; @@ -914,7 +914,7 @@ #if USE_DMA /* No s/g support for DMA */ NCR53c406a_dma_read(current_SC->request_buffer, current_SC->request_bufflen); -#endif USE_DMA +#endif /* USE_DMA */ outb(TRANSFER_INFO | DMA_OP, CMD_REG); #if USE_PIO if (!current_SC->use_sg) /* Don't use scatter-gather */ @@ -929,7 +929,7 @@ } } REG0; -#endif USE_PIO +#endif /* USE_PIO */ } break; @@ -981,7 +981,7 @@ } #ifndef IRQ_LEV -static int irq_probe() +static int irq_probe(void) { int irqs, irq; int i; @@ -1011,9 +1011,9 @@ return irq; } -#endif IRQ_LEV +#endif /* IRQ_LEV */ -static void chip_init() +static void chip_init(void) { REG1; #if USE_DMA diff -u --recursive --new-file v2.4.5/linux/drivers/scsi/aha152x.c linux/drivers/scsi/aha152x.c --- v2.4.5/linux/drivers/scsi/aha152x.c Tue Mar 6 19:44:37 2001 +++ linux/drivers/scsi/aha152x.c Wed Jun 27 17:10:55 2001 @@ -1998,14 +1998,14 @@ if (!HOSTDATA(shpnt)->commands) SETPORT(PORTA, 0); /* turn led off */ - kfree(DONE_SC->host_scribble); - DONE_SC->host_scribble=0; - DO_UNLOCK(flags); DPRINTK(debug_done, DEBUG_LEAD "calling scsi_done(%p)\n", CMDINFO(DONE_SC), DONE_SC); DONE_SC->scsi_done(DONE_SC); DPRINTK(debug_done, DEBUG_LEAD "scsi_done(%p) returned\n", CMDINFO(DONE_SC), DONE_SC); DO_LOCK(flags); + + kfree(DONE_SC->host_scribble); + DONE_SC->host_scribble=0; } DONE_SC=0; @@ -2872,11 +2872,11 @@ if (!ptr->device->soft_reset) { remove_SC(&DISCONNECTED_SC, ptr); - kfree(ptr->host_scribble); - ptr->host_scribble=0; - ptr->result = DID_RESET << 16; ptr->scsi_done(ptr); + + kfree(ptr->host_scribble); + ptr->host_scribble=0; } ptr = next; diff -u --recursive --new-file v2.4.5/linux/drivers/scsi/aic7xxx_old.c linux/drivers/scsi/aic7xxx_old.c --- v2.4.5/linux/drivers/scsi/aic7xxx_old.c Fri Apr 27 13:59:18 2001 +++ linux/drivers/scsi/aic7xxx_old.c Tue Jun 12 11:06:54 2001 @@ -10100,7 +10100,7 @@ } /* while(pdev=....) */ } /* for PCI_DEVICES */ } /* PCI BIOS present */ -#endif CONFIG_PCI +#endif /* CONFIG_PCI */ #if defined(__i386__) || defined(__alpha__) /* diff -u --recursive --new-file v2.4.5/linux/drivers/scsi/constants.c linux/drivers/scsi/constants.c --- v2.4.5/linux/drivers/scsi/constants.c Mon Jan 15 13:08:15 2001 +++ linux/drivers/scsi/constants.c Tue Jun 12 11:17:17 2001 @@ -689,7 +689,7 @@ kdev_t dev) { int i, s; - int sense_class, valid, code; + int sense_class, valid, code, info; const char * error = NULL; sense_class = (sense_buffer[0] >> 4) & 0x07; @@ -701,11 +701,14 @@ if(s > SCSI_SENSE_BUFFERSIZE) s = SCSI_SENSE_BUFFERSIZE; - if (!valid) - printk("[valid=0] "); - printk("Info fld=0x%x, ", (int)((sense_buffer[3] << 24) | - (sense_buffer[4] << 16) | (sense_buffer[5] << 8) | - sense_buffer[6])); + info = ((sense_buffer[3] << 24) | (sense_buffer[4] << 16) | + (sense_buffer[5] << 8) | sense_buffer[6]); + if (info || valid) { + printk("Info fld=0x%x", info); + if (!valid) /* info data not according to standard */ + printk(" (nonstd)"); + printk(", "); + } if (sense_buffer[2] & 0x80) printk( "FMK "); /* current command has read a filemark */ if (sense_buffer[2] & 0x40) diff -u --recursive --new-file v2.4.5/linux/drivers/scsi/cpqfcTSinit.c linux/drivers/scsi/cpqfcTSinit.c --- v2.4.5/linux/drivers/scsi/cpqfcTSinit.c Fri Apr 27 14:05:28 2001 +++ linux/drivers/scsi/cpqfcTSinit.c Wed Jun 20 11:19:02 2001 @@ -1808,7 +1808,7 @@ #ifdef MODULE -Scsi_Host_Template driver_template = CPQFCTS; +static Scsi_Host_Template driver_template = CPQFCTS; #include "scsi_module.c" diff -u --recursive --new-file v2.4.5/linux/drivers/scsi/dmx3191d.c linux/drivers/scsi/dmx3191d.c --- v2.4.5/linux/drivers/scsi/dmx3191d.c Fri Apr 27 13:59:18 2001 +++ linux/drivers/scsi/dmx3191d.c Wed Jun 27 17:10:55 2001 @@ -59,7 +59,7 @@ struct pci_dev *pdev = NULL; if (!pci_present()) { - dmx3191d_printk("PCI support not enabled\n"); + printk(KERN_WARNING "dmx3191: PCI support not enabled\n"); return 0; } @@ -75,7 +75,7 @@ port = pci_resource_start (pdev, 0); if (!request_region(port, DMX3191D_REGION, DMX3191D_DRIVER_NAME)) { - dmx3191d_printk("region 0x%lx-0x%lx already reserved\n", + printk(KERN_ERR "dmx3191: region 0x%lx-0x%lx already reserved\n", port, port + DMX3191D_REGION); continue; } @@ -93,7 +93,7 @@ if (request_irq(pdev->irq, dmx3191d_do_intr, SA_SHIRQ, DMX3191D_DRIVER_NAME, instance)) { - dmx3191d_printk("irq %d not available\n", pdev->irq); + printk(KERN_WARNING "dmx3191: IRQ %d not available - switching to polled mode.\n", pdev->irq); /* Steam powered scsi controllers run without an IRQ anyway */ instance->irq = IRQ_NONE; diff -u --recursive --new-file v2.4.5/linux/drivers/scsi/dmx3191d.h linux/drivers/scsi/dmx3191d.h --- v2.4.5/linux/drivers/scsi/dmx3191d.h Mon Sep 18 14:12:01 2000 +++ linux/drivers/scsi/dmx3191d.h Wed Jun 27 17:10:55 2001 @@ -20,8 +20,6 @@ #define PCI_DEVICE_ID_DOMEX_DMX3191D 0x0001 #endif -#define dmx3191d_printk( args... ) printk(__FILE__": " ##args) - #ifndef ASM int dmx3191d_abort(Scsi_Cmnd *); int dmx3191d_detect(Scsi_Host_Template *); diff -u --recursive --new-file v2.4.5/linux/drivers/scsi/eata_dma.c linux/drivers/scsi/eata_dma.c --- v2.4.5/linux/drivers/scsi/eata_dma.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/scsi/eata_dma.c Wed Jun 27 17:10:55 2001 @@ -482,6 +482,7 @@ DBG(DBG_REQSENSE, printk(KERN_DEBUG "Tried to REQUEST SENSE\n")); cmd->result = DID_OK << 16; done(cmd); + restore_flags(flags); return(0); } diff -u --recursive --new-file v2.4.5/linux/drivers/scsi/gdth.c linux/drivers/scsi/gdth.c --- v2.4.5/linux/drivers/scsi/gdth.c Sat May 19 17:43:06 2001 +++ linux/drivers/scsi/gdth.c Wed Jun 20 11:19:02 2001 @@ -4639,7 +4639,7 @@ #else -Scsi_Host_Template driver_template = GDTH; +static Scsi_Host_Template driver_template = GDTH; #include "scsi_module.c" #ifndef MODULE __setup("gdth=", option_setup); diff -u --recursive --new-file v2.4.5/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c --- v2.4.5/linux/drivers/scsi/hosts.c Mon Oct 30 14:44:29 2000 +++ linux/drivers/scsi/hosts.c Wed Jun 27 17:10:55 2001 @@ -168,6 +168,11 @@ retval->loaded_as_module = 1; if (flag_new) { shn = (Scsi_Host_Name *) kmalloc(sizeof(Scsi_Host_Name), GFP_ATOMIC); + if (!shn) { + kfree(retval); + printk(KERN_ERR "scsi: out of memory(2) in scsi_register.\n"); + return NULL; + } shn->name = kmalloc(hname_len + 1, GFP_ATOMIC); if (hname_len > 0) strncpy(shn->name, hname, hname_len); diff -u --recursive --new-file v2.4.5/linux/drivers/scsi/osst.c linux/drivers/scsi/osst.c --- v2.4.5/linux/drivers/scsi/osst.c Thu Jan 4 13:00:55 2001 +++ linux/drivers/scsi/osst.c Tue Jun 12 11:09:03 2001 @@ -16,22 +16,21 @@ Copyright 1992 - 2000 Kai Makisara email Kai.Makisara@metla.fi - $Header: /home/cvsroot/Driver/osst.c,v 1.51 2000/12/22 20:48:27 garloff Exp $ + $Header: /home/cvsroot/Driver/osst.c,v 1.61 2001/06/03 21:55:12 riede Exp $ Microscopic alterations - Rik Ling, 2000/12/21 Last modified: Wed Feb 2 22:04:05 2000 by makisara@kai.makisara.local Some small formal changes - aeb, 950809 */ -static const char * cvsid = "$Id: osst.c,v 1.51 2000/12/22 20:48:27 garloff Exp $"; -const char * osst_version = "0.9.4.3"; +static const char * cvsid = "$Id: osst.c,v 1.61 2001/06/03 21:55:12 riede Exp $"; +const char * osst_version = "0.9.8"; /* The "failure to reconnect" firmware bug */ -#define OSST_FW_NEED_POLL_MIN 10602 /*(107A)*/ -#define OSST_FW_NEED_POLL_MAX 10708 /*(108D)*/ +#define OSST_FW_NEED_POLL_MIN 10601 /*(107A)*/ +#define OSST_FW_NEED_POLL_MAX 10704 /*(108D)*/ #define OSST_FW_NEED_POLL(x,d) ((x) >= OSST_FW_NEED_POLL_MIN && (x) <= OSST_FW_NEED_POLL_MAX && d->host->this_id != 7) -#include #include #include @@ -112,6 +111,8 @@ #if DEBUG static int debugging = 1; +/* uncomment define below to test error recovery */ +// #define OSST_INJECT_ERRORS 1 #endif #define MAX_RETRIES 0 @@ -172,7 +173,7 @@ static int osst_get_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt); -static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int file_blk); +static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt); static int osst_write_error_recovery(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int pending); @@ -202,7 +203,7 @@ #if DEBUG if (debugging) { - printk(OSST_DEB_MSG "osst%d: Error: %x, cmd: %x %x %x %x %x %x Len: %d\n", + printk(OSST_DEB_MSG "osst%d:D: Error: %x, cmd: %x %x %x %x %x %x Len: %d\n", dev, result, SRpnt->sr_cmnd[0], SRpnt->sr_cmnd[1], SRpnt->sr_cmnd[2], SRpnt->sr_cmnd[3], SRpnt->sr_cmnd[4], SRpnt->sr_cmnd[5], @@ -222,16 +223,25 @@ SRpnt->sr_cmnd[0] != MODE_SENSE && SRpnt->sr_cmnd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */ if (driver_byte(result) & DRIVER_SENSE) { - printk(KERN_WARNING "osst%d: Error with sense data: ", dev); + printk(KERN_WARNING "osst%d:W: Error with sense data: ", dev); print_req_sense("osst", SRpnt); } - else + else { + static int notyetprinted = 1; + printk(KERN_WARNING - "osst%d: Error %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n", + "osst%d:W: Error %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n", dev, result, suggestion(result), driver_byte(result) & DRIVER_MASK, host_byte(result)); + if (notyetprinted) { + notyetprinted = 0; + printk(KERN_INFO + "osst%d:I: This error may be caused by your scsi controller,\n", dev); + printk(KERN_INFO + "osst%d:I: it has been reported with some Buslogic cards.\n", dev); + } + } } - if ((sense[0] & 0x70) == 0x70 && scode == RECOVERED_ERROR) { STp->recover_count++; @@ -244,7 +254,7 @@ stp = "write"; else stp = "ioctl"; - printk(OSST_DEB_MSG "osst%d: Recovered %s error (%d).\n", dev, stp, + printk(OSST_DEB_MSG "osst%d:D: Recovered %s error (%d).\n", dev, stp, os_scsi_tapes[dev]->recover_count); } #endif @@ -259,7 +269,6 @@ static void osst_sleep_done (Scsi_Cmnd * SCpnt) { unsigned int dev; - int remainder; OS_Scsi_Tape * STp; if ((dev = TAPE_NR(SCpnt->request.rq_dev)) < osst_template.nr_dev) { @@ -268,15 +277,7 @@ (SCpnt->sense_buffer[0] & 0x70) == 0x70 && (SCpnt->sense_buffer[2] & 0x40)) { /* EOM at write-behind, has all been written? */ - if ((SCpnt->sense_buffer[0] & 0x80) != 0) - remainder = (SCpnt->sense_buffer[3] << 24) | - (SCpnt->sense_buffer[4] << 16) | - (SCpnt->sense_buffer[5] << 8 ) | - SCpnt->sense_buffer[6]; - else - remainder = 0; - if ((SCpnt->sense_buffer[2] & 0x0f) == VOLUME_OVERFLOW || - remainder > 0) + if ((SCpnt->sense_buffer[2] & 0x0f) == VOLUME_OVERFLOW) (STp->buffer)->midlevel_result = SCpnt->result; /* Error */ else (STp->buffer)->midlevel_result = INT_MAX; /* OK */ @@ -293,7 +294,7 @@ } #if DEBUG else if (debugging) - printk(KERN_ERR "osst?: Illegal interrupt device %x\n", dev); + printk(OSST_DEB_MSG "osst?:D: Illegal interrupt device %x\n", dev); #endif } @@ -305,11 +306,13 @@ unsigned char *cmd, int bytes, int direction, int timeout, int retries, int do_wait) { unsigned char *bp; -//static int inject = 0; /* FIXME - take out inject occasional read errors */ -//static int repeat = 0; +#ifdef OSST_INJECT_ERRORS + static int inject = 0; + static int repeat = 0; +#endif if (SRpnt == NULL) { if ((SRpnt = scsi_allocate_request(STp->device)) == NULL) { - printk(KERN_ERR "osst%d: Can't get SCSI request.\n", TAPE_NR(STp->devt)); + printk(KERN_ERR "osst%d:E: Can't get SCSI request.\n", TAPE_NR(STp->devt)); if (signal_pending(current)) (STp->buffer)->syscall_result = (-EINTR); else @@ -341,12 +344,18 @@ down(SRpnt->sr_request.sem); SRpnt->sr_request.sem = NULL; STp->buffer->syscall_result = osst_chk_result(STp, SRpnt); -//if ((STp->buffer)->syscall_result == 0 && -// cmd[0] == READ_6 && cmd[4] && ( /* (++ inject % 83) == 29 || */ -// (STp->first_frame_position == 240 /* or STp->read_error_frame to fail again on the block calculated above */ && ++repeat < 3))) { -// printk(OSST_DEB_MSG "osst%d: injecting read error\n", TAPE_NR(STp->devt)); -// STp->buffer->last_result_fatal = 1; /* FIXME - take out inject occasional read errors */ -//} +#ifdef OSST_INJECT_ERRORS + if (STp->buffer->syscall_result == 0 && + cmd[0] == READ_6 && + cmd[4] && + ( (++ inject % 83) == 29 || + (STp->first_frame_position == 240 + /* or STp->read_error_frame to fail again on the block calculated above */ && + ++repeat < 3))) { + printk(OSST_DEB_MSG "osst%d:D: Injecting read error\n", TAPE_NR(STp->devt)); + STp->buffer->last_result_fatal = 1; + } +#endif } return SRpnt; } @@ -356,7 +365,6 @@ static void osst_write_behind_check(OS_Scsi_Tape *STp) { OSST_buffer * STbuffer; - ST_partstat * STps; STbuffer = STp->buffer; @@ -366,7 +374,6 @@ else STp->nbr_finished++; #endif - down(&(STp->sem)); (STp->buffer)->last_SRpnt->sr_request.sem = NULL; @@ -381,21 +388,9 @@ scsi_release_request((STp->buffer)->last_SRpnt); if (STbuffer->writing < STbuffer->buffer_bytes) -#if 0 - memcpy(STbuffer->b_data, - STbuffer->b_data + STbuffer->writing, - STbuffer->buffer_bytes - STbuffer->writing); -#else - printk(KERN_WARNING "osst: write_behind_check: something left in buffer!\n"); -#endif + printk(KERN_WARNING "osst:A: write_behind_check: something left in buffer!\n"); + STbuffer->buffer_bytes -= STbuffer->writing; - STps = &(STp->ps[STp->partition]); - if (STps->drv_block >= 0) { - if (STp->block_size == 0) - STps->drv_block++; - else - STps->drv_block += STbuffer->writing / STp->block_size; - } STbuffer->writing = 0; return; @@ -407,7 +402,8 @@ /* * Initialize the OnStream AUX */ -static void osst_init_aux(OS_Scsi_Tape * STp, int frame_type, int logical_blk_num) +static void osst_init_aux(OS_Scsi_Tape * STp, int frame_type, int frame_seq_number, + int logical_blk_num, int blk_sz, int blk_cnt) { os_aux_t *aux = STp->buffer->aux; os_partition_t *par = &aux->partition; @@ -441,9 +437,10 @@ dat->reserved1 = 0; dat->entry_cnt = 1; dat->reserved3 = 0; - dat->dat_list[0].blk_sz = htonl(frame_type==OS_FRAME_TYPE_DATA?STp->block_size:0); - dat->dat_list[0].blk_cnt = htons(1); - dat->dat_list[0].flags = frame_type==OS_FRAME_TYPE_MARKER?OS_DAT_FLAGS_MARK:OS_DAT_FLAGS_DATA; + dat->dat_list[0].blk_sz = htonl(blk_sz); + dat->dat_list[0].blk_cnt = htons(blk_cnt); + dat->dat_list[0].flags = frame_type==OS_FRAME_TYPE_MARKER? + OS_DAT_FLAGS_MARK:OS_DAT_FLAGS_DATA; dat->dat_list[0].reserved = 0; case OS_FRAME_TYPE_EOD: aux->update_frame_cntr = htonl(0); @@ -452,27 +449,28 @@ par->wrt_pass_cntr = htons(STp->wrt_pass_cntr); par->first_frame_ppos = htonl(STp->first_data_ppos); par->last_frame_ppos = htonl(STp->capacity); - aux->frame_seq_num = htonl(logical_blk_num); + aux->frame_seq_num = htonl(frame_seq_number); aux->logical_blk_num_high = htonl(0); aux->logical_blk_num = htonl(logical_blk_num); break; default: ; /* probably FILL */ } - aux->filemark_cnt = ntohl(STp->filemark_cnt); /* FIXME -- violates ADR spec */ + aux->filemark_cnt = ntohl(STp->filemark_cnt); aux->phys_fm = ntohl(0xffffffff); aux->last_mark_ppos = ntohl(STp->last_mark_ppos); + aux->last_mark_lbn = ntohl(STp->last_mark_lbn); } /* * Verify that we have the correct tape frame */ -static int osst_verify_frame(OS_Scsi_Tape * STp, int logical_blk_num, int quiet) +static int osst_verify_frame(OS_Scsi_Tape * STp, int frame_seq_number, int quiet) { os_aux_t * aux = STp->buffer->aux; os_partition_t * par = &(aux->partition); ST_partstat * STps = &(STp->ps[STp->partition]); - int i; int dev = TAPE_NR(STp->devt); + int blk_cnt, blk_sz, i; if (STp->raw) { if (STp->buffer->syscall_result) { @@ -483,55 +481,70 @@ return 1; } if (STp->buffer->syscall_result) { - printk(KERN_INFO "osst%d: Skipping frame, read error\n", dev); +#if DEBUG + printk(OSST_DEB_MSG "osst%d:D: Skipping frame, read error\n", dev); +#endif return 0; } if (ntohl(aux->format_id) != 0) { - printk(KERN_INFO "osst%d: Skipping frame, format_id %u\n", dev, ntohl(aux->format_id)); - return 0; +#if DEBUG + printk(OSST_DEB_MSG "osst%d:D: Skipping frame, format_id %u\n", dev, ntohl(aux->format_id)); +#endif + goto err_out; } if (memcmp(aux->application_sig, STp->application_sig, 4) != 0 && (memcmp(aux->application_sig, "LIN3", 4) != 0 || STp->linux_media_version != 4)) { - printk(KERN_INFO "osst%d: Skipping frame, incorrect application signature\n", dev); - return 0; +#if DEBUG + printk(OSST_DEB_MSG "osst%d:D: Skipping frame, incorrect application signature\n", dev); +#endif + goto err_out; } if (par->partition_num != OS_DATA_PARTITION) { if (!STp->linux_media || STp->linux_media_version != 2) { - printk(KERN_INFO "osst%d: Skipping frame, partition num %d\n", dev, par->partition_num); return 0; +#if DEBUG + printk(OSST_DEB_MSG "osst%d:D: Skipping frame, partition num %d\n", + dev, par->partition_num); +#endif + goto err_out; } } if (par->par_desc_ver != OS_PARTITION_VERSION) { - printk(KERN_INFO "osst%d: Skipping frame, partition version %d\n", dev, par->par_desc_ver); - return 0; +#if DEBUG + printk(OSST_DEB_MSG "osst%d:D: Skipping frame, partition version %d\n", dev, par->par_desc_ver); +#endif + goto err_out; } if (ntohs(par->wrt_pass_cntr) != STp->wrt_pass_cntr) { - printk(KERN_INFO "osst%d: Skipping frame, wrt_pass_cntr %d (expected %d)\n", - dev, ntohs(par->wrt_pass_cntr), STp->wrt_pass_cntr); - return 0; - } - if (aux->frame_seq_num != aux->logical_blk_num) { - printk(KERN_INFO "osst%d: Skipping frame, seq != logical\n", dev); - return 0; +#if DEBUG + printk(OSST_DEB_MSG "osst%d:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n", + dev, ntohs(par->wrt_pass_cntr), STp->wrt_pass_cntr); +#endif + goto err_out; } if (aux->frame_type != OS_FRAME_TYPE_DATA && aux->frame_type != OS_FRAME_TYPE_EOD && aux->frame_type != OS_FRAME_TYPE_MARKER) { if (!quiet) - printk(KERN_INFO "osst%d: Skipping frame, frame type %x\n", dev, aux->frame_type); - return 0; +#if DEBUG + printk(OSST_DEB_MSG "osst%d:D: Skipping frame, frame type %x\n", dev, aux->frame_type); +#endif + goto err_out; } if (aux->frame_type == OS_FRAME_TYPE_EOD && STp->first_frame_position < STp->eod_frame_ppos) { - printk(KERN_INFO "osst%d: Skipping premature EOD frame %d\n", dev, STp->first_frame_position); - return 0; + printk(KERN_INFO "osst%d:I: Skipping premature EOD frame %d\n", dev, + STp->first_frame_position); + goto err_out; } - STp->logical_blk_in_buffer = 1; + STp->frame_in_buffer = 1; - if (logical_blk_num != -1 && ntohl(aux->logical_blk_num) != logical_blk_num) { + if (frame_seq_number != -1 && ntohl(aux->frame_seq_num) != frame_seq_number) { if (!quiet) - printk(KERN_INFO "osst%d: Skipping frame, logical_blk_num %u (expected %d)\n", - dev, ntohl(aux->logical_blk_num), logical_blk_num); - return 0; +#if DEBUG + printk(OSST_DEB_MSG "osst%d:D: Skipping frame, sequence number %u (expected %d)\n", + dev, ntohl(aux->frame_seq_num), frame_seq_number); +#endif + goto err_out; } if (aux->frame_type == OS_FRAME_TYPE_MARKER) { STps->eof = ST_FM_HIT; @@ -539,8 +552,8 @@ i = ntohl(aux->filemark_cnt); if (STp->header_cache != NULL && i < OS_FM_TAB_MAX && (i > STp->filemark_cnt || STp->first_frame_position - 1 != ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i]))) { -#if 1 //DEBUG - printk(OSST_DEB_MSG "osst%i: %s filemark %d at frame %d\n", dev, +#if DEBUG + printk(OSST_DEB_MSG "osst%d:D: %s filemark %d at frame pos %d\n", dev, STp->header_cache->dat_fm_tab.fm_tab_ent[i] == 0?"Learned":"Corrected", i, STp->first_frame_position - 1); #endif @@ -553,9 +566,31 @@ STps->eof = ST_EOD_1; } if (aux->frame_type == OS_FRAME_TYPE_DATA) { + blk_cnt = ntohs(aux->dat.dat_list[0].blk_cnt); + blk_sz = ntohl(aux->dat.dat_list[0].blk_sz); + STp->buffer->buffer_bytes = blk_cnt * blk_sz; + STp->buffer->read_pointer = 0; + + /* See what block size was used to write file */ + if (STp->block_size != blk_sz && blk_sz > 0) { + printk(KERN_INFO + "osst%d:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n", + dev, blk_sz<1024?blk_sz:blk_sz/1024,blk_sz<1024?'b':'k', + STp->block_size<1024?STp->block_size:STp->block_size/1024, + STp->block_size<1024?'b':'k'); + STp->block_size = blk_sz; + STp->buffer->buffer_blocks = OS_DATA_SIZE / blk_sz; + } STps->eof = ST_NOEOF; } + STp->frame_seq_number = ntohl(aux->frame_seq_num); + STp->logical_blk_num = ntohl(aux->logical_blk_num); return 1; + +err_out: + if (STp->read_error_frame == 0) + STp->read_error_frame = STp->first_frame_position - 1; + return 0; } /* @@ -570,7 +605,7 @@ int dbg = debugging; int dev = TAPE_NR(STp->devt); - printk(OSST_DEB_MSG "osst%d: Reached onstream wait ready\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Reached onstream wait ready\n", dev); #endif memset(cmd, 0, MAX_COMMAND_SIZE); @@ -585,8 +620,8 @@ (SRpnt->sr_sense_buffer[13] == 1 || SRpnt->sr_sense_buffer[13] == 8) ) { #if DEBUG if (debugging) { - printk(OSST_DEB_MSG "osst%d: Sleeping in onstream wait ready\n", dev); - printk(OSST_DEB_MSG "osst%d: Turning off debugging for a while\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Sleeping in onstream wait ready\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Turning off debugging for a while\n", dev); debugging = 0; } #endif @@ -605,15 +640,15 @@ if ( STp->buffer->syscall_result && osst_write_error_recovery(STp, aSRpnt, 0) ) { #if DEBUG - printk(OSST_DEB_MSG "osst%d: Abnormal exit from onstream wait ready\n", dev); -printk(OSST_DEB_MSG "osst%d: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", dev, -STp->buffer->syscall_result, SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[2], -SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]); + printk(OSST_DEB_MSG "osst%d:D: Abnormal exit from onstream wait ready\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", dev, + STp->buffer->syscall_result, SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[2], + SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]); #endif return (-EIO); } #if DEBUG - printk(OSST_DEB_MSG "osst%d: Normal exit from onstream wait ready\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Normal exit from onstream wait ready\n", dev); #endif return 0; } @@ -641,7 +676,7 @@ #if DEBUG int dev = TAPE_NR(STp->devt); - printk(OSST_DEB_MSG "osst%d: Reached onstream flush drive buffer (write filemark)\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Reached onstream flush drive buffer (write filemark)\n", dev); #endif memset(cmd, 0, MAX_COMMAND_SIZE); @@ -668,10 +703,8 @@ #if DEBUG char notyetprinted = 1; #endif - if ((minlast >= 0 && STp->ps[STp->partition].rw != ST_READING) || - (minlast < 0 && STp->ps[STp->partition].rw != ST_WRITING) ) - printk(KERN_ERR "osst%i: waiting for frame without having initialized %s!\n", - dev, minlast<0?"write":"read"); + if (minlast >= 0 && STp->ps[STp->partition].rw != ST_READING) + printk(KERN_ERR "osst%i:A: Waiting for frame without having initialized read!\n", dev); while (time_before (jiffies, startwait + to*HZ)) { @@ -690,7 +723,7 @@ #if DEBUG if (debugging || jiffies - startwait >= 2*HZ/OSST_POLL_PER_SEC) printk (OSST_DEB_MSG - "osst%i: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n", + "osst%d:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n", dev, curr, curr+minlast, STp->first_frame_position, STp->last_frame_position, STp->cur_frames, result, (jiffies-startwait)/HZ, @@ -701,7 +734,7 @@ #if DEBUG if (jiffies - startwait >= 2*HZ/OSST_POLL_PER_SEC && notyetprinted) { - printk (OSST_DEB_MSG "osst%i: Wait for frame %i (>%i): %i-%i %i (%i)\n", + printk (OSST_DEB_MSG "osst%d:D: Wait for frame %i (>%i): %i-%i %i (%i)\n", dev, curr, curr+minlast, STp->first_frame_position, STp->last_frame_position, STp->cur_frames, result); notyetprinted--; @@ -711,7 +744,7 @@ schedule_timeout (HZ / OSST_POLL_PER_SEC); } #if DEBUG - printk (OSST_DEB_MSG "osst%i: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n", + printk (OSST_DEB_MSG "osst%d:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n", dev, curr, curr+minlast, STp->first_frame_position, STp->last_frame_position, STp->cur_frames, (jiffies-startwait)/HZ, (((jiffies-startwait)%HZ)*10)/HZ); @@ -720,9 +753,9 @@ } /* - * Read the next OnStream tape block at the current location + * Read the next OnStream tape frame at the current location */ -static int osst_read_block(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int timeout) +static int osst_read_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int timeout) { unsigned char cmd[MAX_COMMAND_SIZE]; Scsi_Request * SRpnt; @@ -746,7 +779,7 @@ #if DEBUG if (debugging) - printk(OSST_DEB_MSG "osst%i: Reading block from OnStream tape\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Reading frame from OnStream tape\n", dev); #endif SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_READ, STp->timeout, MAX_RETRIES, TRUE); @@ -758,11 +791,13 @@ retval = 1; if (STp->read_error_frame == 0) { STp->read_error_frame = STp->first_frame_position; - printk(OSST_DEB_MSG "osst: recording read error at %d\n", STp->read_error_frame);/*FIXME*/ +#if DEBUG + printk(OSST_DEB_MSG "osst%d:D: Recording read error at %d\n", dev, STp->read_error_frame); +#endif } #if DEBUG if (debugging) - printk(OSST_DEB_MSG "osst%d: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n", + printk(OSST_DEB_MSG "osst%d:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n", dev, SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[1], SRpnt->sr_sense_buffer[2], SRpnt->sr_sense_buffer[3], @@ -774,16 +809,19 @@ STp->first_frame_position++; #if DEBUG if (debugging) { - printk(OSST_DEB_MSG "osst%i: AUX: %c%c%c%c UpdFrCt#%d %s FrSeq#%d LogBlk#%d\n", dev, + printk(OSST_DEB_MSG + "osst%d:D: AUX: %c%c%c%c UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", dev, aux->application_sig[0], aux->application_sig[1], - aux->application_sig[2], aux->application_sig[3], ntohl(aux->update_frame_cntr), + aux->application_sig[2], aux->application_sig[3], + ntohl(aux->update_frame_cntr), ntohs(aux->partition.wrt_pass_cntr), aux->frame_type==1?"EOD":aux->frame_type==2?"MARK": aux->frame_type==8?"HEADR":aux->frame_type==0x80?"DATA":"FILL", - ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num) ); + ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num), + ntohs(aux->dat.dat_list[0].blk_cnt), ntohl(aux->dat.dat_list[0].blk_sz) ); if (aux->frame_type==2) - printk(OSST_DEB_MSG "osst%i: mark_cnt=%d, last_mark=%d, next_mark=%d\n", dev, - ntohl(aux->filemark_cnt), ntohl(aux->last_mark_ppos), ntohl(aux->next_mark_ppos)); - printk(OSST_DEB_MSG "osst%i: Exit read block from OnStream tape with code %d\n", dev, retval); + printk(OSST_DEB_MSG "osst%d:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", dev, + ntohl(aux->filemark_cnt), ntohl(aux->last_mark_ppos), ntohl(aux->last_mark_lbn)); + printk(OSST_DEB_MSG "osst%d:D: Exit read frame from OnStream tape with code %d\n", dev, retval); } #endif return (retval); @@ -801,22 +839,22 @@ if (STps->rw != ST_READING) { /* Initialize read operation */ if (STps->rw == ST_WRITING) { - osst_flush_write_buffer(STp, aSRpnt, 1); + osst_flush_write_buffer(STp, aSRpnt); osst_flush_drive_buffer(STp, aSRpnt); } STps->rw = ST_READING; - STp->logical_blk_in_buffer = 0; + STp->frame_in_buffer = 0; /* * Issue a read 0 command to get the OnStream drive - * read blocks into its buffer. + * read frames into its buffer. */ memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = READ_6; cmd[1] = 1; #if DEBUG - printk(OSST_DEB_MSG "osst%i: Start Read Ahead on OnStream tape\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Start Read Ahead on OnStream tape\n", dev); #endif SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_RETRIES, TRUE); *aSRpnt = SRpnt; @@ -826,7 +864,7 @@ return retval; } -static int osst_get_logical_blk(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int logical_blk_num, int quiet) +static int osst_get_logical_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int frame_seq_number, int quiet) { ST_partstat * STps = &(STp->ps[STp->partition]); int dev = TAPE_NR(STp->devt); @@ -837,16 +875,16 @@ position; /* - * Search and wait for the next logical tape block + * Search and wait for the next logical tape frame */ while (1) { if (cnt++ > 400) { - printk(KERN_WARNING "osst%d: Couldn't find logical block %d, aborting\n", - dev, logical_blk_num); + printk(KERN_ERR "osst%d:E: Couldn't find logical frame %d, aborting\n", + dev, frame_seq_number); if (STp->read_error_frame) { osst_set_frame_position(STp, aSRpnt, STp->read_error_frame, 0); -#if 1 //DEBUG - printk(OSST_DEB_MSG "osst%d: Repositioning tape to bad block %d\n", +#if DEBUG + printk(OSST_DEB_MSG "osst%d:D: Repositioning tape to bad frame %d\n", dev, STp->read_error_frame); #endif STp->read_error_frame = 0; @@ -855,16 +893,15 @@ } #if DEBUG if (debugging) - printk(OSST_DEB_MSG "osst%d: Looking for block %d, attempt %d\n", - dev, logical_blk_num, cnt); + printk(OSST_DEB_MSG "osst%d:D: Looking for frame %d, attempt %d\n", + dev, frame_seq_number, cnt); #endif if ( osst_initiate_read(STp, aSRpnt) - || ( (!STp->logical_blk_in_buffer) && osst_read_block(STp, aSRpnt, 30) ) ) { + || ( (!STp->frame_in_buffer) && osst_read_frame(STp, aSRpnt, 30) ) ) { position = osst_get_frame_position(STp, aSRpnt); if (position >= 0xbae && position < 0xbb8) position = 0xbb8; else if (position > STp->eod_frame_ppos || ++bad == 10) { -printk(OSST_DEB_MSG "osst%d: start again from pos %d, eod %d, bad %d\n", dev, position, STp->eod_frame_ppos, bad); /*FIXME*/ position = STp->read_error_frame - 1; } else { @@ -872,38 +909,40 @@ cnt += 20; } #if DEBUG - printk(OSST_DEB_MSG "osst%d: Bad block detected, positioning tape to block %d\n", + printk(OSST_DEB_MSG "osst%d:D: Bad frame detected, positioning tape to block %d\n", dev, position); #endif osst_set_frame_position(STp, aSRpnt, position, 0); continue; } - if (osst_verify_frame(STp, logical_blk_num, quiet)) + if (osst_verify_frame(STp, frame_seq_number, quiet)) break; if (osst_verify_frame(STp, -1, quiet)) { - x = ntohl(STp->buffer->aux->logical_blk_num); + x = ntohl(STp->buffer->aux->frame_seq_num); if (STp->fast_open) { -#if 1 //DEBUG - printk(OSST_DEB_MSG - "osst%d: Found logical block %d instead of %d after fast open\n", - dev, x, logical_blk_num); -#endif + printk(KERN_WARNING + "osst%d:W: Found logical frame %d instead of %d after fast open\n", + dev, x, frame_seq_number); STp->header_ok = 0; STp->read_error_frame = 0; return (-EIO); } - if (x > logical_blk_num) { + if (x > frame_seq_number) { if (++past > 3) { - /* positioning backwards did not bring us to the desired block */ + /* positioning backwards did not bring us to the desired frame */ position = STp->read_error_frame - 1; } - else + else { position = osst_get_frame_position(STp, aSRpnt) - + logical_blk_num - x - 1; -#if 1 //DEBUG + + frame_seq_number - x - 1; + + if (STp->first_frame_position >= 3000 && position < 3000) + position -= 10; + } +#if DEBUG printk(OSST_DEB_MSG - "osst%d: Found logical block %d while looking for %d: back up %d\n", - dev, x, logical_blk_num, + "osst%d:D: Found logical frame %d while looking for %d: back up %d\n", + dev, x, frame_seq_number, STp->first_frame_position - position); #endif osst_set_frame_position(STp, aSRpnt, position, 0); @@ -914,22 +953,26 @@ } if (osst_get_frame_position(STp, aSRpnt) == 0xbaf) { #if DEBUG - printk(OSST_DEB_MSG "osst%d: Skipping config partition\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Skipping config partition\n", dev); #endif osst_set_frame_position(STp, aSRpnt, 0xbb8, 0); cnt--; } - STp->logical_blk_in_buffer = 0; + STp->frame_in_buffer = 0; } if (cnt > 1) { STp->recover_count++; STp->recover_erreg++; + printk(KERN_WARNING "osst%d:I: Read error at position %d recovered\n", + dev, STp->read_error_frame); } - STp->logical_blk_num = ntohl(STp->buffer->aux->logical_blk_num); + STp->read_count++; #if DEBUG if (debugging || STps->eof) - printk(OSST_DEB_MSG "osst%i: Exit get logical block (%d=>%d) from OnStream tape with code %d\n", dev, logical_blk_num, STp->logical_blk_num, STps->eof); + printk(OSST_DEB_MSG + "osst%d:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n", + dev, frame_seq_number, STp->frame_seq_number, STps->eof); #endif STp->fast_open = FALSE; STp->read_error_frame = 0; @@ -938,60 +981,195 @@ static int osst_seek_logical_blk(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int logical_blk_num) { - int estimate; - int retries = 0; - int dev = TAPE_NR(STp->devt); - + ST_partstat * STps = &(STp->ps[STp->partition]); + int dev = TAPE_NR(STp->devt); + int retries = 0; + int frame_seq_estimate, ppos_estimate, move; + if (logical_blk_num < 0) logical_blk_num = 0; - /* FIXME -- this may not be valid for foreign formats */ - if (logical_blk_num < 2980) estimate = logical_blk_num + 10; - else estimate = logical_blk_num + 20; - #if DEBUG - printk(OSST_DEB_MSG "osst%d: Seeking logical block %d (now at %d)\n", - dev, logical_blk_num, STp->logical_blk_num); + printk(OSST_DEB_MSG "osst%d:D: Seeking logical block %d (now at %d, size %d%c)\n", + dev, logical_blk_num, STp->logical_blk_num, + STp->block_size<1024?STp->block_size:STp->block_size/1024, + STp->block_size<1024?'b':'k'); #endif + /* Do we know where we are? */ + if (STps->drv_block >= 0) { + move = logical_blk_num - STp->logical_blk_num; + if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1; + move /= (OS_DATA_SIZE / STp->block_size); + frame_seq_estimate = STp->frame_seq_number + move; + } else + frame_seq_estimate = logical_blk_num * STp->block_size / OS_DATA_SIZE; + + if (frame_seq_estimate < 2980) ppos_estimate = frame_seq_estimate + 10; + else ppos_estimate = frame_seq_estimate + 20; while (++retries < 10) { - osst_set_frame_position(STp, aSRpnt, estimate, 0); - if (osst_get_logical_blk(STp, aSRpnt, logical_blk_num, 1) >= 0) - return 0; - if (osst_get_logical_blk(STp, aSRpnt, -1, 1) < 0) + if (ppos_estimate > STp->eod_frame_ppos-2) { + frame_seq_estimate += STp->eod_frame_ppos - 2 - ppos_estimate; + ppos_estimate = STp->eod_frame_ppos - 2; + } + if (frame_seq_estimate < 0) { + frame_seq_estimate = 0; + ppos_estimate = 10; + } + osst_set_frame_position(STp, aSRpnt, ppos_estimate, 0); + if (osst_get_logical_frame(STp, aSRpnt, frame_seq_estimate, 1) >= 0) { + /* we've located the estimated frame, now does it have our block? */ + if (logical_blk_num < STp->logical_blk_num || + logical_blk_num >= STp->logical_blk_num + ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt)) { + if (STps->eof == ST_FM_HIT) + move = logical_blk_num < STp->logical_blk_num? -2 : 1; + else { + move = logical_blk_num - STp->logical_blk_num; + if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1; + move /= (OS_DATA_SIZE / STp->block_size); + } +#if DEBUG + printk(OSST_DEB_MSG + "osst%d:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n", + dev, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate, + STp->logical_blk_num, logical_blk_num, move); +#endif + frame_seq_estimate += move; + ppos_estimate += move; + continue; + } else { + STp->buffer->read_pointer = (logical_blk_num - STp->logical_blk_num) * STp->block_size; + STp->buffer->buffer_bytes -= STp->buffer->read_pointer; + STp->logical_blk_num = logical_blk_num; +#if DEBUG + printk(OSST_DEB_MSG + "osst%d:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n", + dev, ppos_estimate, STp->frame_seq_number, STp->frame_in_buffer, + STp->buffer->buffer_bytes, STp->buffer->read_pointer / STp->block_size, + STp->block_size); +#endif + STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt); + if (STps->eof == ST_FM_HIT) { + STps->drv_file++; + STps->drv_block = 0; + } else { + STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)? + STp->logical_blk_num - + (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0): + -1; + } + STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF; + return 0; + } + } + if (osst_get_logical_frame(STp, aSRpnt, -1, 1) < 0) goto error; - if (STp->logical_blk_num != logical_blk_num) - estimate += logical_blk_num - STp->logical_blk_num; + /* we are not yet at the estimated frame, adjust our estimate of its physical position */ +#if DEBUG + printk(OSST_DEB_MSG "osst%d:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n", + dev, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate, + STp->logical_blk_num, logical_blk_num); +#endif + if (frame_seq_estimate != STp->frame_seq_number) + ppos_estimate += frame_seq_estimate - STp->frame_seq_number; else break; } error: - printk(KERN_WARNING "osst%d: Couldn't seek to logical block %d (at %d), %d retries\n", + printk(KERN_ERR "osst%d:E: Couldn't seek to logical block %d (at %d), %d retries\n", dev, logical_blk_num, STp->logical_blk_num, retries); return (-EIO); } -static int osst_seek_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int frame) +/* The values below are based on the OnStream frame payload size of 32K == 2**15, + * that is, OSST_FRAME_SHIFT + OSST_SECTOR_SHIFT must be 15. With a minimum block + * size of 512 bytes, we need to be able to resolve 32K/512 == 64 == 2**6 positions + * inside each frame. Finaly, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1. + */ +#define OSST_FRAME_SHIFT 6 +#define OSST_SECTOR_SHIFT 9 +#define OSST_SECTOR_MASK 0x03F + +static int osst_get_sector(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt) +{ + int sector; +#if DEBUG + int dev = TAPE_NR(STp->devt); + + printk(OSST_DEB_MSG + "osst%d:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n", + dev, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num, + STp->ps[STp->partition].drv_file, STp->ps[STp->partition].drv_block, + STp->ps[STp->partition].rw == ST_WRITING?'w':'r', + STp->ps[STp->partition].rw == ST_WRITING?STp->buffer->buffer_bytes: + STp->buffer->read_pointer, STp->ps[STp->partition].eof); +#endif + /* do we know where we are inside a file? */ + if (STp->ps[STp->partition].drv_block >= 0) { + sector = (STp->frame_in_buffer ? STp->first_frame_position-1 : + STp->first_frame_position) << OSST_FRAME_SHIFT; + if (STp->ps[STp->partition].rw == ST_WRITING) + sector |= (STp->buffer->buffer_bytes >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK; + else + sector |= (STp->buffer->read_pointer >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK; + } else { + sector = osst_get_frame_position(STp, aSRpnt); + if (sector > 0) + sector <<= OSST_FRAME_SHIFT; + } + return sector; +} + +static int osst_seek_sector(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int sector) { - ST_partstat * STps = &(STp->ps[STp->partition]); - int r; + ST_partstat * STps = &(STp->ps[STp->partition]); + int frame = sector >> OSST_FRAME_SHIFT, + offset = (sector & OSST_SECTOR_MASK) << OSST_SECTOR_SHIFT, + r; +#if DEBUG + int dev = TAPE_NR(STp->devt); + printk(OSST_DEB_MSG "osst%d:D: Seeking sector %d in frame %d at offset %d\n", + dev, sector, frame, offset); +#endif if (frame < 0 || frame >= STp->capacity) return (-ENXIO); if (frame <= STp->first_data_ppos) { - STp->logical_blk_num = STps->drv_file = STps->drv_block = 0; + STp->frame_seq_number = STp->logical_blk_num = STps->drv_file = STps->drv_block = 0; return (osst_set_frame_position(STp, aSRpnt, frame, 0)); } - r = osst_set_frame_position(STp, aSRpnt, frame-1, 0); + r = osst_set_frame_position(STp, aSRpnt, offset?frame:frame-1, 0); if (r < 0) return r; - r = osst_get_logical_blk(STp, aSRpnt, -1, 1); + r = osst_get_logical_frame(STp, aSRpnt, -1, 1); if (r < 0) return r; - if (osst_get_frame_position(STp, aSRpnt) != frame) return (-EIO); + if (osst_get_frame_position(STp, aSRpnt) != (offset?frame+1:frame)) return (-EIO); - STp->logical_blk_num++; - STp->logical_blk_in_buffer = 0; - STps->drv_file = htonl(STp->buffer->aux->filemark_cnt); - STps->drv_block = -1; - STps->eof = ST_NOEOF; + if (offset) { + STp->logical_blk_num += offset / STp->block_size; + STp->buffer->read_pointer = offset; + STp->buffer->buffer_bytes -= offset; + } else { + STp->frame_seq_number++; + STp->frame_in_buffer = 0; + STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt); + STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0; + } + STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt); + if (STps->eof == ST_FM_HIT) { + STps->drv_file++; + STps->drv_block = 0; + } else { + STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)? + STp->logical_blk_num - + (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0): + -1; + } + STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF; +#if DEBUG + printk(OSST_DEB_MSG + "osst%d:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n", + dev, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num, + STps->drv_file, STps->drv_block, STp->buffer->read_pointer, STps->eof); +#endif return 0; } @@ -999,38 +1177,43 @@ * Read back the drive's internal buffer contents, as a part * of the write error recovery mechanism for old OnStream * firmware revisions. + * Precondition for this function to work: all frames in the + * drive's buffer must be of one type (DATA, MARK or EOD)! */ static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, - unsigned int block, unsigned int skip, int pending) + unsigned int frame, unsigned int skip, int pending) { Scsi_Request * SRpnt = * aSRpnt; unsigned char * buffer, * p; unsigned char cmd[MAX_COMMAND_SIZE]; - int frames, flag, new_block, i, logical_blk_num; - int dev = TAPE_NR(STp->devt); - long startwait = jiffies; + int flag, new_frame, i; + int nframes = STp->cur_frames; + int blks_per_frame = ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt); + int frame_seq_number = ntohl(STp->buffer->aux->frame_seq_num) + - (nframes + pending - 1); + int logical_blk_num = ntohl(STp->buffer->aux->logical_blk_num) + - (nframes + pending - 1) * blks_per_frame; + int dev = TAPE_NR(STp->devt); + long startwait = jiffies; #if DEBUG - int dbg = debugging; + int dbg = debugging; #endif - frames = STp->cur_frames; - if ((buffer = (unsigned char *)vmalloc((frames + pending) * OS_DATA_SIZE)) == NULL) + if ((buffer = (unsigned char *)vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL) return (-EIO); - logical_blk_num = STp->logical_blk_num - frames - pending; - printk(KERN_INFO "osst%d: Reading back %d frames from drive buffer%s\n", - dev, frames, pending?" and one that was pending":""); - - if (pending) { - osst_copy_from_buffer(STp->buffer, (p = &buffer[frames * OS_DATA_SIZE])); -// memcpy((p = &buffer[frames * OS_DATA_SIZE]), STp->buffer->b_data, OS_DATA_SIZE); + printk(KERN_INFO "osst%d:I: Reading back %d frames from drive buffer%s\n", + dev, nframes, pending?" and one that was pending":""); + + osst_copy_from_buffer(STp->buffer, (p = &buffer[nframes * OS_DATA_SIZE])); #if DEBUG - if (debugging) - printk(OSST_DEB_MSG "osst%d: Pending logical block %d, data %x %x %x %x\n", - dev, logical_blk_num + frames, p[0], p[1], p[2], p[3]); + if (pending && debugging) + printk(OSST_DEB_MSG "osst%d:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n", + dev, frame_seq_number + nframes, + logical_blk_num + nframes * blks_per_frame, + p[0], p[1], p[2], p[3]); #endif - } - for (i = 0, p = buffer; i < frames; i++, p += OS_DATA_SIZE) { + for (i = 0, p = buffer; i < nframes; i++, p += OS_DATA_SIZE) { memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = 0x3C; /* Buffer Read */ @@ -1041,63 +1224,63 @@ SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_READ, STp->timeout, MAX_RETRIES, TRUE); - if ((STp->buffer)->syscall_result) { - printk(KERN_ERR "osst%d: Failed to read block back from OnStream buffer\n", dev); + if ((STp->buffer)->syscall_result || !SRpnt) { + printk(KERN_ERR "osst%d:E: Failed to read frame back from OnStream buffer\n", dev); vfree((void *)buffer); *aSRpnt = SRpnt; return (-EIO); } osst_copy_from_buffer(STp->buffer, p); -// memcpy(p, STp->buffer->b_data, OS_DATA_SIZE); #if DEBUG if (debugging) - printk(OSST_DEB_MSG "osst%d: Read back logical block %d, data %x %x %x %x\n", - dev, logical_blk_num + i, p[0], p[1], p[2], p[3]); + printk(OSST_DEB_MSG "osst%d:D: Read back logical frame %d, data %02x %02x %02x %02x\n", + dev, frame_seq_number + i, p[0], p[1], p[2], p[3]); #endif } *aSRpnt = SRpnt; osst_get_frame_position(STp, aSRpnt); #if DEBUG - printk(OSST_DEB_MSG "osst%d: Frames left in buffer: %d\n", dev, STp->cur_frames); + printk(OSST_DEB_MSG "osst%d:D: Frames left in buffer: %d\n", dev, STp->cur_frames); #endif /* Write synchronously so we can be sure we're OK again and don't have to recover recursively */ - /* In the header we don't actually re-write the blocks that fail, just the ones after them */ + /* In the header we don't actually re-write the frames that fail, just the ones after them */ - for (flag=1, new_block=block, p=buffer, i=0; i < frames + pending; ) { + for (flag=1, new_frame=frame, p=buffer, i=0; i < nframes + pending; ) { if (flag) { if (STp->write_type == OS_WRITE_HEADER) { i += skip; p += skip * OS_DATA_SIZE; } - else if (new_block < 2990 && new_block+skip+frames+pending >= 2990) - new_block = 3000-i; + else if (new_frame < 2990 && new_frame+skip+nframes+pending >= 2990) + new_frame = 3000-i; else - new_block += skip; + new_frame += skip; #if DEBUG - printk(OSST_DEB_MSG "osst%d: Position to frame %d, write lblk %d\n", - dev, new_block+i, logical_blk_num+i); /* FIXME var blk sz */ + printk(OSST_DEB_MSG "osst%d:D: Position to frame %d, write fseq %d\n", + dev, new_frame+i, frame_seq_number+i); #endif - osst_set_frame_position(STp, aSRpnt, new_block + i, 0); + osst_set_frame_position(STp, aSRpnt, new_frame + i, 0); osst_wait_ready(STp, aSRpnt, 60); osst_get_frame_position(STp, aSRpnt); SRpnt = * aSRpnt; - if (new_block > block + 1000) { - printk(KERN_ERR "osst%d: Failed to find valid tape media\n", dev); + if (new_frame > frame + 1000) { + printk(KERN_ERR "osst%d:E: Failed to find writable tape media\n", dev); vfree((void *)buffer); return (-EIO); } flag = 0; - if ( i >= frames + pending ) break; + if ( i >= nframes + pending ) break; } osst_copy_to_buffer(STp->buffer, p); -// memcpy(STp->buffer->b_data, p, OS_DATA_SIZE); /* * IMPORTANT: for error recovery to work, _never_ queue frames with mixed frame type! */ - osst_init_aux(STp, STp->buffer->aux->frame_type, logical_blk_num+i ); + osst_init_aux(STp, STp->buffer->aux->frame_type, frame_seq_number+i, + logical_blk_num + i*blks_per_frame, + ntohl(STp->buffer->aux->dat.dat_list[0].blk_sz), blks_per_frame); memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = WRITE_6; cmd[1] = 1; @@ -1105,7 +1288,10 @@ #if DEBUG if (debugging) - printk(OSST_DEB_MSG "osst%d: About to attempt to write to frame %d\n", dev, new_block+i); + printk(OSST_DEB_MSG + "osst%d:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n", + dev, new_frame+i, frame_seq_number+i, logical_blk_num + i*blks_per_frame, + p[0], p[1], p[2], p[3]); #endif SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_WRITE, STp->timeout, MAX_WRITE_RETRIES, TRUE); @@ -1116,9 +1302,9 @@ p += OS_DATA_SIZE; i++; /* if we just sent the last frame, wait till all successfully written */ - if ( i == frames + pending ) { + if ( i == nframes + pending ) { #if DEBUG - printk(OSST_DEB_MSG "osst%d: Check re-write successful\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Check re-write successful\n", dev); #endif memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = WRITE_FILEMARKS; @@ -1127,8 +1313,8 @@ STp->timeout, MAX_WRITE_RETRIES, TRUE); #if DEBUG if (debugging) { - printk(OSST_DEB_MSG "osst%d: Sleeping in re-write wait ready\n", dev); - printk(OSST_DEB_MSG "osst%d: Turning off debugging for a while\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Sleeping in re-write wait ready\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Turning off debugging for a while\n", dev); debugging = 0; } #endif @@ -1153,44 +1339,47 @@ } #if DEBUG debugging = dbg; - printk(OSST_DEB_MSG "osst%d: Wait re-write finished\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Wait re-write finished\n", dev); #endif } } + *aSRpnt = SRpnt; if (flag) { if ((SRpnt->sr_sense_buffer[ 2] & 0x0f) == 13 && SRpnt->sr_sense_buffer[12] == 0 && SRpnt->sr_sense_buffer[13] == 2) { - printk(KERN_ERR "osst%d: Volume overflow in write error recovery\n", dev); + printk(KERN_ERR "osst%d:E: Volume overflow in write error recovery\n", dev); vfree((void *)buffer); return (-EIO); /* hit end of tape = fail */ } i = ((SRpnt->sr_sense_buffer[3] << 24) | (SRpnt->sr_sense_buffer[4] << 16) | (SRpnt->sr_sense_buffer[5] << 8) | - SRpnt->sr_sense_buffer[6] ) - new_block; + SRpnt->sr_sense_buffer[6] ) - new_frame; p = &buffer[i * OS_DATA_SIZE]; #if DEBUG - printk(OSST_DEB_MSG "osst%d: Additional write error at %d\n", dev, new_block+i); + printk(OSST_DEB_MSG "osst%d:D: Additional write error at %d\n", dev, new_frame+i); #endif osst_get_frame_position(STp, aSRpnt); #if DEBUG - printk(OSST_DEB_MSG "osst%d: reported frame positions: host = %d, tape = %d\n", + printk(OSST_DEB_MSG "osst%d:D: reported frame positions: host = %d, tape = %d\n", dev, STp->first_frame_position, STp->last_frame_position); #endif } - *aSRpnt = SRpnt; } + if (!pending) + osst_copy_to_buffer(STp->buffer, p); /* so buffer content == at entry in all cases */ vfree((void *)buffer); return 0; } static int osst_reposition_and_retry(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, - unsigned int block, unsigned int skip, int pending) + unsigned int frame, unsigned int skip, int pending) { unsigned char cmd[MAX_COMMAND_SIZE]; - Scsi_Request * SRpnt = * aSRpnt; + Scsi_Request * SRpnt; int dev = TAPE_NR(STp->devt); + int expected = 0; int attempts = 1000 / skip; int flag = 1; long startwait = jiffies; @@ -1203,23 +1392,24 @@ #if DEBUG debugging = dbg; #endif - if (block < 2990 && block+skip+STp->cur_frames+pending >= 2990) - block = 3000-skip; + if (frame < 2990 && frame+skip+STp->cur_frames+pending >= 2990) + frame = 3000-skip; + expected = frame+skip+STp->cur_frames+pending; #if DEBUG - printk(OSST_DEB_MSG "osst%d: Position to frame %d, re-write from lblk %d\n", - dev, block+skip, STp->logical_blk_num-STp->cur_frames-pending); + printk(OSST_DEB_MSG "osst%d:D: Position to fppos %d, re-write from fseq %d\n", + dev, frame+skip, STp->frame_seq_number-STp->cur_frames-pending); #endif - osst_set_frame_position(STp, aSRpnt, block + skip, 1); + osst_set_frame_position(STp, aSRpnt, frame + skip, 1); flag = 0; attempts--; } if (osst_get_frame_position(STp, aSRpnt) < 0) { /* additional write error */ #if DEBUG - printk(OSST_DEB_MSG "osst%d: Addl error, host %d, tape %d, buffer %d\n", + printk(OSST_DEB_MSG "osst%d:D: Addl error, host %d, tape %d, buffer %d\n", dev, STp->first_frame_position, STp->last_frame_position, STp->cur_frames); #endif - block = STp->last_frame_position; + frame = STp->last_frame_position; flag = 1; continue; } @@ -1230,19 +1420,19 @@ cmd[1] = 1; cmd[4] = 1; #if DEBUG - printk(OSST_DEB_MSG "osst%d: About to write pending lblk %d at frame %d\n", - dev, STp->logical_blk_num-1, STp->first_frame_position); + printk(OSST_DEB_MSG "osst%d:D: About to write pending fseq %d at fppos %d\n", + dev, STp->frame_seq_number-1, STp->first_frame_position); #endif - SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_WRITE, - STp->timeout, MAX_WRITE_RETRIES, TRUE); + SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_WRITE, + STp->timeout, MAX_WRITE_RETRIES, TRUE); *aSRpnt = SRpnt; if (STp->buffer->syscall_result) { /* additional write error */ if ((SRpnt->sr_sense_buffer[ 2] & 0x0f) == 13 && SRpnt->sr_sense_buffer[12] == 0 && SRpnt->sr_sense_buffer[13] == 2) { - printk(OSST_DEB_MSG - "osst%d: Volume overflow in write error recovery\n", + printk(KERN_ERR + "osst%d:E: Volume overflow in write error recovery\n", dev); break; /* hit end of tape = fail */ } @@ -1256,20 +1446,25 @@ if (STp->cur_frames == 0) { #if DEBUG debugging = dbg; - printk(OSST_DEB_MSG "osst%d: Wait re-write finished\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Wait re-write finished\n", dev); #endif + if (STp->first_frame_position != expected) { + printk(KERN_ERR "osst%d:A: Actual position %d - expected %d\n", + dev, STp->first_frame_position, expected); + return (-EIO); + } return 0; } #if DEBUG if (debugging) { - printk(OSST_DEB_MSG "osst%d: Sleeping in re-write wait ready\n", dev); - printk(OSST_DEB_MSG "osst%d: Turning off debugging for a while\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Sleeping in re-write wait ready\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Turning off debugging for a while\n", dev); debugging = 0; } #endif schedule_timeout(HZ / 10); } - printk(KERN_ERR "osst%d: Failed to find valid tape media\n", dev); + printk(KERN_ERR "osst%d:E: Failed to find valid tape media\n", dev); #if DEBUG debugging = dbg; #endif @@ -1287,7 +1482,7 @@ int dev = TAPE_NR(STp->devt); int retval = 0; int rw_state; - unsigned int block, skip; + unsigned int frame, skip; rw_state = STps->rw; @@ -1295,54 +1490,56 @@ || SRpnt->sr_sense_buffer[12] != 12 || SRpnt->sr_sense_buffer[13] != 0) { #if DEBUG - printk(OSST_DEB_MSG "osst%d: Write error recovery cannot handle %02x:%02x:%02x\n", - dev, SRpnt->sr_sense_buffer[2], SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]); + printk(OSST_DEB_MSG "osst%d:D: Write error recovery cannot handle %02x:%02x:%02x\n", dev, + SRpnt->sr_sense_buffer[2], SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]); #endif return (-EIO); } - block = (SRpnt->sr_sense_buffer[3] << 24) | + frame = (SRpnt->sr_sense_buffer[3] << 24) | (SRpnt->sr_sense_buffer[4] << 16) | (SRpnt->sr_sense_buffer[5] << 8) | SRpnt->sr_sense_buffer[6]; skip = SRpnt->sr_sense_buffer[9]; #if DEBUG - printk(OSST_DEB_MSG "osst%d: Detected physical bad block at %u, advised to skip %d\n", dev, block, skip); + printk(OSST_DEB_MSG "osst%d:D: Detected physical bad frame at %u, advised to skip %d\n", dev, frame, skip); #endif osst_get_frame_position(STp, aSRpnt); #if DEBUG - printk(OSST_DEB_MSG "osst%d: reported frame positions: host = %d, tape = %d\n", + printk(OSST_DEB_MSG "osst%d:D: reported frame positions: host = %d, tape = %d\n", dev, STp->first_frame_position, STp->last_frame_position); #endif switch (STp->write_type) { case OS_WRITE_DATA: case OS_WRITE_EOD: case OS_WRITE_NEW_MARK: - printk(KERN_WARNING "osst%d: Relocating %d buffered logical blocks to physical block %u\n", - dev, STp->cur_frames, block + skip); + printk(KERN_WARNING + "osst%d:I: Relocating %d buffered logical frames from position %u to %u\n", + dev, STp->cur_frames, frame, (frame + skip > 3000 && frame < 3000)?3000:frame + skip); if (STp->os_fw_rev >= 10600) - retval = osst_reposition_and_retry(STp, aSRpnt, block, skip, pending); + retval = osst_reposition_and_retry(STp, aSRpnt, frame, skip, pending); else - retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, block, skip, pending); + retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, skip, pending); + printk(KERN_WARNING "osst%d:I: Write error%srecovered\n", dev, retval?" not ":" "); break; case OS_WRITE_LAST_MARK: - printk(KERN_ERR "osst%d: Bad block in update last marker, fatal\n", dev); - osst_set_frame_position(STp, aSRpnt, block + STp->cur_frames + pending, 0); + printk(KERN_ERR "osst%d:E: Bad frame in update last marker, fatal\n", dev); + osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0); retval = -EIO; break; case OS_WRITE_HEADER: - printk(KERN_WARNING "osst%d: Bad block in header partition, skipped\n", dev); - retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, block, 1, pending); + printk(KERN_WARNING "osst%d:I: Bad frame in header partition, skipped\n", dev); + retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, 1, pending); break; default: - printk(KERN_WARNING "osst%d: Bad block in filler, ignored\n", dev); - osst_set_frame_position(STp, aSRpnt, block + STp->cur_frames + pending, 0); + printk(KERN_INFO "osst%d:I: Bad frame in filler, ignored\n", dev); + osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0); } osst_get_frame_position(STp, aSRpnt); #if DEBUG - printk(KERN_ERR "osst%d: Positioning complete, cur_frames %d, pos %d, tape pos %d\n", + printk(OSST_DEB_MSG "osst%d:D: Positioning complete, cur_frames %d, pos %d, tape pos %d\n", dev, STp->cur_frames, STp->first_frame_position, STp->last_frame_position); - printk(OSST_DEB_MSG "osst%d: next logical block to write: %d\n", dev, STp->logical_blk_num); + printk(OSST_DEB_MSG "osst%d:D: next logical frame to write: %d\n", dev, STp->logical_blk_num); #endif if (retval == 0) { STp->recover_count++; @@ -1360,10 +1557,12 @@ int last_mark_ppos = -1; #if DEBUG - printk(OSST_DEB_MSG "osst%d: Reached space_over_filemarks_backwards %d %d\n", dev, mt_op, mt_count); + printk(OSST_DEB_MSG "osst%d:D: Reached space_over_filemarks_backwards %d %d\n", dev, mt_op, mt_count); +#endif + if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) { +#if DEBUG + printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks_bwd\n", dev); #endif - if (osst_get_logical_blk(STp, aSRpnt, -1, 0) < 0) { - printk(KERN_INFO "osst%i: Couldn't get logical blk num in space_filemarks_bwd\n", dev); return -EIO; } if (STp->linux_media_version >= 4) { @@ -1379,12 +1578,12 @@ STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] == STp->buffer->aux->last_mark_ppos) last_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt - mt_count]); -#if 1 //DEBUG +#if DEBUG if (STp->header_cache == NULL || (cnt - mt_count) < 0 || (cnt - mt_count) >= OS_FM_TAB_MAX) - printk(OSST_DEB_MSG "osst%i: Filemark lookup fail due to %s\n", dev, + printk(OSST_DEB_MSG "osst%d:D: Filemark lookup fail due to %s\n", dev, STp->header_cache == NULL?"lack of header cache":"count out of range"); else - printk(OSST_DEB_MSG "osst%i: Filemark lookup: prev mark %d (%s), skip %d to %d\n", + printk(OSST_DEB_MSG "osst%d:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n", dev, cnt, ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) || (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] == @@ -1393,22 +1592,28 @@ #endif if (last_mark_ppos > 10 && last_mark_ppos < STp->eod_frame_ppos) { osst_set_frame_position(STp, aSRpnt, last_mark_ppos, 0); - if (osst_get_logical_blk(STp, aSRpnt, -1, 0) < 0) { - printk(KERN_INFO "osst%i: Couldn't get logical blk num in space_filemarks\n", dev); + if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) { +#if DEBUG + printk(OSST_DEB_MSG + "osst%d:D: Couldn't get logical blk num in space_filemarks\n", dev); +#endif return (-EIO); } if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "osst%i: Expected to find marker at block %d, not found\n", + printk(KERN_WARNING "osst%d:W: Expected to find marker at ppos %d, not found\n", dev, last_mark_ppos); return (-EIO); } if (mt_op == MTBSFM) { - STp->logical_blk_num++; - STp->logical_blk_in_buffer = 0; + STp->frame_seq_number++; + STp->frame_in_buffer = 0; + STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt); } return 0; } - printk(KERN_INFO "osst%i: Reverting to scan filemark backwards\n", dev); +#if DEBUG + printk(OSST_DEB_MSG "osst%d:D: Reverting to scan filemark backwards\n", dev); +#endif } cnt = 0; while (cnt != mt_count) { @@ -1416,22 +1621,26 @@ if (last_mark_ppos == -1) return (-EIO); #if DEBUG - printk(OSST_DEB_MSG "osst%i: Positioning to last mark at %d\n", dev, last_mark_ppos); + printk(OSST_DEB_MSG "osst%d:D: Positioning to last mark at %d\n", dev, last_mark_ppos); #endif osst_set_frame_position(STp, aSRpnt, last_mark_ppos, 0); cnt++; - if (osst_get_logical_blk(STp, aSRpnt, -1, 0) < 0) { - printk(KERN_INFO "osst%i: Couldn't get logical blk num in space_filemarks\n", dev); + if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) { +#if DEBUG + printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks\n", dev); +#endif return (-EIO); } if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "osst%i: Expected to find marker at block %d, not found\n", dev, last_mark_ppos); + printk(KERN_WARNING "osst%d:W: Expected to find marker at ppos %d, not found\n", + dev, last_mark_ppos); return (-EIO); } } if (mt_op == MTBSFM) { - STp->logical_blk_num++; - STp->logical_blk_in_buffer = 0; + STp->frame_seq_number++; + STp->frame_in_buffer = 0; + STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt); } return 0; } @@ -1444,30 +1653,34 @@ static int osst_space_over_filemarks_forward_slow(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int mt_op, int mt_count) { - int dev = TAPE_NR(STp->devt); int cnt = 0; +#if DEBUG + int dev = TAPE_NR(STp->devt); + printk(OSST_DEB_MSG "osst%d:D: Reached space_over_filemarks_forward_slow %d %d\n", dev, mt_op, mt_count); +#endif + if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) { #if DEBUG - printk(OSST_DEB_MSG "osst%d: Reached space_over_filemarks_forward_slow %d %d\n", dev, mt_op, mt_count); + printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks_fwd\n", dev); #endif - if (osst_get_logical_blk(STp, aSRpnt, -1, 0) < 0) { - printk(KERN_INFO "osst%i: Couldn't get logical blk num in space_filemarks_fwd\n", dev); return (-EIO); } while (1) { - if (osst_get_logical_blk(STp, aSRpnt, -1, 0) < 0) { - printk(KERN_INFO "osst%i: Couldn't get logical blk num in space_filemarks\n", dev); + if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) { +#if DEBUG + printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks\n", dev); +#endif return (-EIO); } if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER) cnt++; if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) { #if DEBUG - printk(OSST_DEB_MSG "osst%i: space_fwd: EOD reached\n", dev); + printk(OSST_DEB_MSG "osst%d:D: space_fwd: EOD reached\n", dev); #endif if (STp->first_frame_position > STp->eod_frame_ppos+1) { #if DEBUG - printk(OSST_DEB_MSG "osst%i: EOD position corrected (%d=>%d)\n", + printk(OSST_DEB_MSG "osst%d:D: EOD position corrected (%d=>%d)\n", dev, STp->eod_frame_ppos, STp->first_frame_position-1); #endif STp->eod_frame_ppos = STp->first_frame_position-1; @@ -1476,11 +1689,12 @@ } if (cnt == mt_count) break; - STp->logical_blk_in_buffer = 0; + STp->frame_in_buffer = 0; } if (mt_op == MTFSF) { - STp->logical_blk_num++; - STp->logical_blk_in_buffer = 0; + STp->frame_seq_number++; + STp->frame_in_buffer = 0; + STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt); } return 0; } @@ -1496,10 +1710,12 @@ next_mark_ppos = -1; #if DEBUG - printk(OSST_DEB_MSG "osst%d: Reached space_over_filemarks_forward_fast %d %d\n", dev, mt_op, mt_count); + printk(OSST_DEB_MSG "osst%d:D: Reached space_over_filemarks_forward_fast %d %d\n", dev, mt_op, mt_count); +#endif + if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) { +#if DEBUG + printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks_fwd\n", dev); #endif - if (osst_get_logical_blk(STp, aSRpnt, -1, 0) < 0) { - printk(KERN_INFO "osst%i: Couldn't get logical blk num in space_filemarks_fwd\n", dev); return (-EIO); } @@ -1516,33 +1732,39 @@ (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] == STp->buffer->aux->last_mark_ppos))) next_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt + mt_count]); -#if 1 //DEBUG +#if DEBUG if (STp->header_cache == NULL || (cnt + mt_count) >= OS_FM_TAB_MAX) - printk(OSST_DEB_MSG "osst%i: Filemark lookup fail due to %s\n", dev, + printk(OSST_DEB_MSG "osst%d:D: Filemark lookup fail due to %s\n", dev, STp->header_cache == NULL?"lack of header cache":"count out of range"); else - printk(OSST_DEB_MSG "osst%i: Filemark lookup: prev mark %d (%s), skip %d to %d\n", dev, cnt, + printk(OSST_DEB_MSG "osst%d:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n", + dev, cnt, ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) || (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] == STp->buffer->aux->last_mark_ppos))?"match":"error", mt_count, next_mark_ppos); #endif if (next_mark_ppos <= 10 || next_mark_ppos > STp->eod_frame_ppos) { - printk(KERN_INFO "osst%i: Reverting to slow filemark space\n", dev); +#if DEBUG + printk(OSST_DEB_MSG "osst%d:D: Reverting to slow filemark space\n", dev); +#endif return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count); } else { osst_set_frame_position(STp, aSRpnt, next_mark_ppos, 0); - if (osst_get_logical_blk(STp, aSRpnt, -1, 0) < 0) { - printk(KERN_INFO "osst%i: Couldn't get logical blk num in space_filemarks\n", dev); + if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) { +#if DEBUG + printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks\n", + dev); +#endif return (-EIO); } if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "osst%i: Expected to find marker at block %d, not found\n", + printk(KERN_WARNING "osst%d:W: Expected to find marker at ppos %d, not found\n", dev, next_mark_ppos); return (-EIO); } if (ntohl(STp->buffer->aux->filemark_cnt) != cnt + mt_count) { - printk(KERN_INFO "osst%i: Expected to find marker %d at block %d, not %d\n", + printk(KERN_WARNING "osst%d:W: Expected to find marker %d at ppos %d, not %d\n", dev, cnt+mt_count, next_mark_ppos, ntohl(STp->buffer->aux->filemark_cnt)); return (-EIO); @@ -1557,24 +1779,28 @@ break; if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) { #if DEBUG - printk(OSST_DEB_MSG "osst%i: space_fwd: EOD reached\n", dev); + printk(OSST_DEB_MSG "osst%d:D: space_fwd: EOD reached\n", dev); #endif return (-EIO); } if (ntohl(STp->buffer->aux->filemark_cnt) == 0) { if (STp->first_mark_ppos == -1) { - printk(KERN_INFO "osst%i: Reverting to slow filemark space\n", dev); +#if DEBUG + printk(OSST_DEB_MSG "osst%d:D: Reverting to slow filemark space\n", dev); +#endif return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count); } osst_set_frame_position(STp, aSRpnt, STp->first_mark_ppos, 0); - if (osst_get_logical_blk(STp, aSRpnt, -1, 0) < 0) { - printk(KERN_INFO - "osst%i: Couldn't get logical blk num in space_filemarks_fwd_fast\n", + if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) { +#if DEBUG + printk(OSST_DEB_MSG + "osst%d:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n", dev); +#endif return (-EIO); } if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "osst%i: Expected to find filemark at %d\n", + printk(KERN_WARNING "osst%d:W: Expected to find filemark at %d\n", dev, STp->first_mark_ppos); return (-EIO); } @@ -1588,28 +1814,35 @@ while (cnt != mt_count) { next_mark_ppos = ntohl(STp->buffer->aux->next_mark_ppos); if (!next_mark_ppos || next_mark_ppos > STp->eod_frame_ppos) { - printk(KERN_INFO "osst%i: Reverting to slow filemark space\n", dev); +#if DEBUG + printk(OSST_DEB_MSG "osst%d:D: Reverting to slow filemark space\n", dev); +#endif return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count - cnt); } #if DEBUG - else printk(OSST_DEB_MSG "osst%i: Positioning to next mark at %d\n", dev, next_mark_ppos); + else printk(OSST_DEB_MSG "osst%d:D: Positioning to next mark at %d\n", dev, next_mark_ppos); #endif osst_set_frame_position(STp, aSRpnt, next_mark_ppos, 0); cnt++; - if (osst_get_logical_blk(STp, aSRpnt, -1, 0) < 0) { - printk(KERN_INFO "osst%i: Couldn't get logical blk num in space_filemarks\n", dev); + if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) { +#if DEBUG + printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks\n", + dev); +#endif return (-EIO); } if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "osst%i: Expected to find marker at block %d, not found\n", + printk(KERN_WARNING "osst%d:W: Expected to find marker at ppos %d, not found\n", dev, next_mark_ppos); return (-EIO); } } } - if (mt_op == MTFSF) - STp->logical_blk_num++; - STp->logical_blk_in_buffer = 0; + if (mt_op == MTFSF) { + STp->frame_seq_number++; + STp->frame_in_buffer = 0; + STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt); + } return 0; } @@ -1639,75 +1872,22 @@ (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = retries; if (debugging) - printk(OSST_DEB_MSG "osst%i: Setting number of retries on OnStream tape to %d\n", dev, retries); + printk(OSST_DEB_MSG "osst%d:D: Setting number of retries on OnStream tape to %d\n", dev, retries); SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE, STp->timeout, 0, TRUE); *aSRpnt = SRpnt; if ((STp->buffer)->syscall_result) - printk (KERN_ERR "osst%d: Couldn't set retries to %d\n", dev, retries); + printk (KERN_ERR "osst%d:D: Couldn't set retries to %d\n", dev, retries); } #endif -#if 0 -static void osst_update_markers(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int last_mark_ppos, int this_mark_ppos) -{ - int dev = TAPE_NR(STp->devt); - int frame, - reslt; - - if (STp->raw) return; - - STp->last_mark_ppos = this_mark_ppos; - if (STp->header_cache != NULL && STp->filemark_cnt < OS_FM_TAB_MAX) - STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt] = htonl(this_mark_ppos); - if (STp->filemark_cnt++ == 0) - STp->first_mark_ppos = this_mark_ppos; - - if (STp->linux_media_version >= 4) return; - if (last_mark_ppos == -1) return; - - STp->write_type = OS_WRITE_LAST_MARK; - frame = osst_get_frame_position(STp, aSRpnt); -#if DEBUG - printk(OSST_DEB_MSG "osst%i: Update last_marker at frame %d\n", dev, last_mark_addr); - printk(OSST_DEB_MSG "osst%i: current position %d, lblk %d, tape blk %d\n", - dev, frame, STp->logical_blk_num, STp->last_frame_position); -#endif - osst_set_frame_position(STp, aSRpnt, last_mark_ppos, 0); - osst_initiate_read (STp, aSRpnt); - reslt = osst_read_block(STp, aSRpnt, 180); - - if (reslt) { - printk(KERN_WARNING "osst%i: couldn't read last marker\n", dev); - osst_set_frame_position(STp, aSRpnt, frame, 0); - return; - } - if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_WARNING "osst%i: expected marker at addr %d\n", dev, last_mark_ppos); - osst_set_frame_position(STp, aSRpnt, frame, 0); - return; - } -#if DEBUG - printk(OSST_DEB_MSG "osst%i: writing back marker\n", dev); -#endif - STp->buffer->aux->next_mark_ppos = htonl(this_mark_ppos); - osst_set_frame_position(STp, aSRpnt, last_mark_ppos, 0); - STp->dirty = 1; - if (osst_flush_write_buffer(STp, aSRpnt, 0) || - osst_flush_drive_buffer(STp, aSRpnt) ) { - printk(KERN_WARNING "osst%i: couldn't write marker back at addr %d\n", dev, last_mark_ppos); - } - osst_set_frame_position(STp, aSRpnt, frame, 0); - - return; /* FIXME -- errors should go back to user space */ -} -#endif static int osst_write_filemark(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt) { int result; - int this_mark_ppos; + int this_mark_ppos = STp->first_frame_position; + int this_mark_lbn = STp->logical_blk_num; #if DEBUG int dev = TAPE_NR(STp->devt); #endif @@ -1715,22 +1895,19 @@ if (STp->raw) return 0; STp->write_type = OS_WRITE_NEW_MARK; - this_mark_ppos = osst_get_frame_position(STp, aSRpnt); #if DEBUG - printk(OSST_DEB_MSG "osst%i: Writing Filemark %i at frame %d (lblk %d)\n", - dev, STp->filemark_cnt, this_mark_ppos, STp->logical_blk_num); + printk(OSST_DEB_MSG "osst%d:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n", + dev, STp->filemark_cnt, this_mark_ppos, STp->frame_seq_number, this_mark_lbn); #endif - osst_init_aux(STp, OS_FRAME_TYPE_MARKER, STp->logical_blk_num++); - STp->ps[STp->partition].rw = ST_WRITING; STp->dirty = 1; - result = osst_flush_write_buffer(STp, aSRpnt, 0); + result = osst_flush_write_buffer(STp, aSRpnt); result |= osst_flush_drive_buffer(STp, aSRpnt); STp->last_mark_ppos = this_mark_ppos; + STp->last_mark_lbn = this_mark_lbn; if (STp->header_cache != NULL && STp->filemark_cnt < OS_FM_TAB_MAX) STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt] = htonl(this_mark_ppos); if (STp->filemark_cnt++ == 0) STp->first_mark_ppos = this_mark_ppos; -// osst_update_markers(STp, aSRpnt, STp->last_mark_addr, this_mark_addr); return result; } @@ -1744,71 +1921,67 @@ if (STp->raw) return 0; STp->write_type = OS_WRITE_EOD; - STp->eod_frame_ppos = osst_get_frame_position(STp, aSRpnt); + STp->eod_frame_ppos = STp->first_frame_position; #if DEBUG - printk(OSST_DEB_MSG "osst%i: Writing EOD at %d=>%d\n", dev, STp->logical_blk_num, STp->eod_frame_ppos); + printk(OSST_DEB_MSG "osst%d:D: Writing EOD at fppos %d (fseq %d, lblk %d)\n", dev, + STp->eod_frame_ppos, STp->frame_seq_number, STp->logical_blk_num); #endif - osst_init_aux(STp, OS_FRAME_TYPE_EOD, STp->logical_blk_num++); - STp->ps[STp->partition].rw = ST_WRITING; STp->dirty = 1; - result = osst_flush_write_buffer(STp, aSRpnt, 0); + result = osst_flush_write_buffer(STp, aSRpnt); result |= osst_flush_drive_buffer(STp, aSRpnt); - STp->eod_frame_lfa = --(STp->logical_blk_num); + STp->eod_frame_lfa = --(STp->frame_seq_number); return result; } -static int osst_write_filler(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int block, int count) +static int osst_write_filler(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int where, int count) { int dev = TAPE_NR(STp->devt); #if DEBUG - printk(OSST_DEB_MSG "osst%i: Reached onstream write filler group %d\n", dev, block); + printk(OSST_DEB_MSG "osst%d:D: Reached onstream write filler group %d\n", dev, where); #endif osst_wait_ready(STp, aSRpnt, 60 * 5); - osst_set_frame_position(STp, aSRpnt, block, 0); + osst_set_frame_position(STp, aSRpnt, where, 0); STp->write_type = OS_WRITE_FILLER; - osst_init_aux(STp, OS_FRAME_TYPE_FILL, 0); while (count--) { memcpy(STp->buffer->b_data, "Filler", 6); STp->buffer->buffer_bytes = 6; STp->dirty = 1; - if (osst_flush_write_buffer(STp, aSRpnt, 0)) { - printk(KERN_INFO "osst%i: Couldn't write filler frame\n", dev); + if (osst_flush_write_buffer(STp, aSRpnt)) { + printk(KERN_INFO "osst%i:I: Couldn't write filler frame\n", dev); return (-EIO); } } #if DEBUG - printk(OSST_DEB_MSG "osst%i: Exiting onstream write filler group\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Exiting onstream write filler group\n", dev); #endif return osst_flush_drive_buffer(STp, aSRpnt); } -static int __osst_write_header(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int block, int count) +static int __osst_write_header(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int where, int count) { int dev = TAPE_NR(STp->devt); int result; #if DEBUG - printk(OSST_DEB_MSG "osst%i: Reached onstream write header group %d\n", dev, block); + printk(OSST_DEB_MSG "osst%d:D: Reached onstream write header group %d\n", dev, where); #endif osst_wait_ready(STp, aSRpnt, 60 * 5); - osst_set_frame_position(STp, aSRpnt, block, 0); + osst_set_frame_position(STp, aSRpnt, where, 0); STp->write_type = OS_WRITE_HEADER; - STp->ps[STp->partition].rw = ST_WRITING; - osst_init_aux(STp, OS_FRAME_TYPE_HEADER, STp->logical_blk_num); while (count--) { osst_copy_to_buffer(STp->buffer, (unsigned char *)STp->header_cache); STp->buffer->buffer_bytes = sizeof(os_header_t); STp->dirty = 1; - if (osst_flush_write_buffer(STp, aSRpnt, 0)) { - printk(KERN_INFO "osst%i: Couldn't write header frame\n", dev); + if (osst_flush_write_buffer(STp, aSRpnt)) { + printk(KERN_INFO "osst%i:I: Couldn't write header frame\n", dev); return (-EIO); } } result = osst_flush_drive_buffer(STp, aSRpnt); #if DEBUG - printk(OSST_DEB_MSG "osst%i: Write onstream header group %s\n", dev, result?"failed":"done"); + printk(OSST_DEB_MSG "osst%d:D: Write onstream header group %s\n", dev, result?"failed":"done"); #endif return result; } @@ -1820,18 +1993,18 @@ int dev = TAPE_NR(STp->devt); #if DEBUG - printk(OSST_DEB_MSG "osst%i: Writing tape header\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Writing tape header\n", dev); #endif if (STp->raw) return 0; if (STp->header_cache == NULL) { if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) { - printk(KERN_ERR "osst%i: Failed to allocate header cache\n", dev); + printk(KERN_ERR "osst%i:E: Failed to allocate header cache\n", dev); return (-ENOMEM); } memset(STp->header_cache, 0, sizeof(os_header_t)); #if DEBUG - printk(OSST_DEB_MSG "osst%d: Allocated and cleared memory for header cache\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Allocated and cleared memory for header cache\n", dev); #endif } if (STp->header_ok) STp->update_frame_cntr++; @@ -1872,12 +2045,12 @@ if (locate_eod) { #if DEBUG - printk(OSST_DEB_MSG "osst%i: locating back to eod frame addr %d\n", dev, STp->eod_frame_ppos); + printk(OSST_DEB_MSG "osst%d:D: Locating back to eod frame addr %d\n", dev, STp->eod_frame_ppos); #endif osst_set_frame_position(STp, aSRpnt, STp->eod_frame_ppos, 0); } if (result) - printk(KERN_WARNING "osst%i: write header failed\n", dev); + printk(KERN_ERR "osst%i:E: Write header failed\n", dev); else { memcpy(STp->application_sig, "LIN4", 4); STp->linux_media = 1; @@ -1892,15 +2065,15 @@ if (STp->header_cache != NULL) memset(STp->header_cache, 0, sizeof(os_header_t)); - STp->logical_blk_num = 0; - STp->logical_blk_in_buffer = 0; + STp->logical_blk_num = STp->frame_seq_number = 0; + STp->frame_in_buffer = 0; STp->eod_frame_ppos = STp->first_data_ppos = 0x0000000A; STp->filemark_cnt = 0; - STp->first_mark_ppos = STp->last_mark_ppos = -1; + STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1; return osst_write_header(STp, aSRpnt, 1); } -static int __osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int block) +static int __osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int ppos) { int dev = TAPE_NR(STp->devt); os_header_t * header; @@ -1912,17 +2085,17 @@ if (STp->raw) return 1; - if (block == 5 || block == 0xbae || STp->buffer->syscall_result) { - if (osst_set_frame_position(STp, aSRpnt, block, 0)) - printk(KERN_WARNING "osst%i: Couldn't position tape\n", dev); + if (ppos == 5 || ppos == 0xbae || STp->buffer->syscall_result) { + if (osst_set_frame_position(STp, aSRpnt, ppos, 0)) + printk(KERN_WARNING "osst%i:W: Couldn't position tape\n", dev); if (osst_initiate_read (STp, aSRpnt)) { - printk(KERN_WARNING "osst%i: Couldn't initiate read\n", dev); + printk(KERN_WARNING "osst%i:W: Couldn't initiate read\n", dev); return 0; } } - if (osst_read_block(STp, aSRpnt, 180)) { + if (osst_read_frame(STp, aSRpnt, 180)) { #if DEBUG - printk(OSST_DEB_MSG "osst%i: Couldn't read header frame\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Couldn't read header frame\n", dev); #endif return 0; } @@ -1930,7 +2103,20 @@ aux = STp->buffer->aux; if (aux->frame_type != OS_FRAME_TYPE_HEADER) { #if DEBUG - printk(OSST_DEB_MSG "osst%i: Skipping non-header frame (%d)\n", dev, block); + printk(OSST_DEB_MSG "osst%d:D: Skipping non-header frame (%d)\n", dev, ppos); +#endif + return 0; + } + if (ntohl(aux->frame_seq_num) != 0 || + ntohl(aux->logical_blk_num) != 0 || + aux->partition.partition_num != OS_CONFIG_PARTITION || + ntohl(aux->partition.first_frame_ppos) != 0 || + ntohl(aux->partition.last_frame_ppos) != 0xbb7 ) { +#if DEBUG + printk(OSST_DEB_MSG "osst%d:D: Invalid header frame (%d,%d,%d,%d,%d)\n", dev, + ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num), + aux->partition.partition_num, ntohl(aux->partition.first_frame_ppos), + ntohl(aux->partition.last_frame_ppos)); #endif return 0; } @@ -1938,51 +2124,57 @@ strncmp(header->ident_str, "ADR-SEQ", 7) != 0) { strncpy(id_string, header->ident_str, 7); id_string[7] = 0; - printk(KERN_INFO "osst%i: Invalid header identification string %s\n", dev, id_string); +#if DEBUG + printk(OSST_DEB_MSG "osst%d:D: Invalid header identification string %s\n", dev, id_string); +#endif return 0; } update_frame_cntr = ntohl(aux->update_frame_cntr); if (update_frame_cntr < STp->update_frame_cntr) { #if DEBUG - printk(OSST_DEB_MSG "osst%i: Skipping frame %d with update_frame_counter %d<%d\n", - dev, block, update_frame_cntr, STp->update_frame_cntr); + printk(OSST_DEB_MSG "osst%d:D: Skipping frame %d with update_frame_counter %d<%d\n", + dev, ppos, update_frame_cntr, STp->update_frame_cntr); #endif return 0; } if (header->major_rev != 1 || header->minor_rev != 4 ) { - printk(KERN_INFO "osst%i: %s revision %d.%d detected (1.4 supported)\n", +#if DEBUG + printk(OSST_DEB_MSG "osst%d:D: %s revision %d.%d detected (1.4 supported)\n", dev, (header->major_rev != 1 || header->minor_rev < 2 || header->minor_rev > 4 )? "Invalid" : "Warning:", header->major_rev, header->minor_rev); +#endif if (header->major_rev != 1 || header->minor_rev < 2 || header->minor_rev > 4) return 0; } +#if DEBUG if (header->pt_par_num != 1) - printk(KERN_INFO "osst%i: Warning: %d partitions defined, only one supported\n", + printk(KERN_INFO "osst%i:W: %d partitions defined, only one supported\n", dev, header->pt_par_num); +#endif memcpy(id_string, aux->application_sig, 4); id_string[4] = 0; if (memcmp(id_string, "LIN", 3) == 0) { STp->linux_media = 1; linux_media_version = id_string[3] - '0'; if (linux_media_version != 4) - printk(KERN_INFO "osst%i: Linux media version %d detected (current 4)\n", + printk(KERN_INFO "osst%i:I: Linux media version %d detected (current 4)\n", dev, linux_media_version); } else { - printk(KERN_WARNING "osst%i: non Linux media detected (%s)\n", dev, id_string); + printk(KERN_WARNING "osst%i:W: Non Linux media detected (%s)\n", dev, id_string); return 0; } if (linux_media_version < STp->linux_media_version) { #if DEBUG - printk(OSST_DEB_MSG "osst%i: Skipping frame %d with linux_media_version %d\n", - dev, block, linux_media_version); + printk(OSST_DEB_MSG "osst%d:D: Skipping frame %d with linux_media_version %d\n", + dev, ppos, linux_media_version); #endif return 0; } if (linux_media_version > STp->linux_media_version) { #if DEBUG - printk(OSST_DEB_MSG "osst%i: Frame %d sets linux_media_version to %d\n", - dev, block, linux_media_version); + printk(OSST_DEB_MSG "osst%d:D: Frame %d sets linux_media_version to %d\n", + dev, ppos, linux_media_version); #endif memcpy(STp->application_sig, id_string, 5); STp->linux_media_version = linux_media_version; @@ -1990,16 +2182,16 @@ } if (update_frame_cntr > STp->update_frame_cntr) { #if DEBUG - printk(OSST_DEB_MSG "osst%i: Frame %d sets update_frame_counter to %d\n", - dev, block, update_frame_cntr); + printk(OSST_DEB_MSG "osst%d:D: Frame %d sets update_frame_counter to %d\n", + dev, ppos, update_frame_cntr); #endif if (STp->header_cache == NULL) { if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) { - printk(KERN_ERR "osst%i: Failed to allocate header cache\n", dev); + printk(KERN_ERR "osst%i:E: Failed to allocate header cache\n", dev); return 0; } #if DEBUG - printk(OSST_DEB_MSG "osst%d: Allocated memory for header cache\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Allocated memory for header cache\n", dev); #endif } osst_copy_from_buffer(STp->buffer, (unsigned char *)STp->header_cache); @@ -2012,19 +2204,22 @@ STp->filemark_cnt = ntohl(aux->filemark_cnt); STp->first_mark_ppos = ntohl(aux->next_mark_ppos); STp->last_mark_ppos = ntohl(aux->last_mark_ppos); + STp->last_mark_lbn = ntohl(aux->last_mark_lbn); STp->update_frame_cntr = update_frame_cntr; #if DEBUG - printk(OSST_DEB_MSG "osst%i: detected write pass %d, update frame counter %d, filemark counter %d\n", + printk(OSST_DEB_MSG "osst%d:D: Detected write pass %d, update frame counter %d, filemark counter %d\n", dev, STp->wrt_pass_cntr, STp->update_frame_cntr, STp->filemark_cnt); - printk(OSST_DEB_MSG "osst%i: first data frame on tape = %d, last = %d, eod frame = %d\n", dev, + printk(OSST_DEB_MSG "osst%d:D: first data frame on tape = %d, last = %d, eod frame = %d\n", dev, STp->first_data_ppos, ntohl(header->partition[0].last_frame_ppos), ntohl(header->partition[0].eod_frame_ppos)); - printk(OSST_DEB_MSG "osst%i: first mark on tape = %d, last = %d, eod frame = %d\n", + printk(OSST_DEB_MSG "osst%d:D: first mark on tape = %d, last = %d, eod frame = %d\n", dev, STp->first_mark_ppos, STp->last_mark_ppos, STp->eod_frame_ppos); #endif if (header->minor_rev < 4 && STp->linux_media_version == 4) { - printk(OSST_DEB_MSG "osst%i: Moving filemark list to ADR 1.4 location\n", dev); +#if DEBUG + printk(OSST_DEB_MSG "osst%i:D: Moving filemark list to ADR 1.4 location\n", dev); +#endif memcpy((void *)header->dat_fm_tab.fm_tab_ent, (void *)header->old_filemark_list, sizeof(header->dat_fm_tab.fm_tab_ent)); memset((void *)header->old_filemark_list, 0, sizeof(header->old_filemark_list)); @@ -2048,9 +2243,8 @@ header->dat_fm_tab.fm_tab_ent_sz != 4 || header->dat_fm_tab.fm_tab_ent_cnt != htons(STp->filemark_cntfilemark_cnt:OS_FM_TAB_MAX))) - printk(KERN_WARNING "osst%i: Failed consistency check ADR 1.4 format\n", dev); + printk(KERN_WARNING "osst%i:W: Failed consistency check ADR 1.4 format\n", dev); -// memcpy(STp->header_cache, header, sizeof(os_header_t)); } return 1; @@ -2058,7 +2252,7 @@ static int osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt) { - int position, block; + int position, ppos; int first, last; int valid = 0; int dev = TAPE_NR(STp->devt); @@ -2073,37 +2267,37 @@ STp->header_ok = STp->linux_media = STp->linux_media_version = 0; STp->wrt_pass_cntr = STp->update_frame_cntr = -1; STp->eod_frame_ppos = STp->first_data_ppos = -1; - STp->first_mark_ppos = STp->last_mark_ppos = -1; + STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1; #if DEBUG - printk(OSST_DEB_MSG "osst%i: Reading header\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Reading header\n", dev); #endif - /* optimization for speed - if we are positioned at block 10, read second group first */ + /* optimization for speed - if we are positioned at ppos 10, read second group first */ /* TODO try the ADR 1.1 locations for the second group if we have no valid one yet... */ first = position==10?0xbae: 5; last = position==10?0xbb3:10; - for (block = first; block < last; block++) - if (__osst_analyze_headers(STp, aSRpnt, block)) + for (ppos = first; ppos < last; ppos++) + if (__osst_analyze_headers(STp, aSRpnt, ppos)) valid = 1; first = position==10? 5:0xbae; last = position==10?10:0xbb3; - for (block = first; block < last; block++) - if (__osst_analyze_headers(STp, aSRpnt, block)) + for (ppos = first; ppos < last; ppos++) + if (__osst_analyze_headers(STp, aSRpnt, ppos)) valid = 1; if (!valid) { - printk(KERN_ERR "osst%i: Failed to find valid ADRL header, new media?\n", dev); + printk(KERN_ERR "osst%i:E: Failed to find valid ADRL header, new media?\n", dev); STp->eod_frame_ppos = STp->first_data_ppos = 0; osst_set_frame_position(STp, aSRpnt, 10, 0); return 0; } if (position <= STp->first_data_ppos) { position = STp->first_data_ppos; - STp->ps[0].drv_file = STp->ps[0].drv_block = STp->logical_blk_num = 0; + STp->ps[0].drv_file = STp->ps[0].drv_block = STp->frame_seq_number = STp->logical_blk_num = 0; } osst_set_frame_position(STp, aSRpnt, position, 0); STp->header_ok = 1; @@ -2114,18 +2308,21 @@ static int osst_verify_position(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt) { int frame_position = STp->first_frame_position; + int frame_seq_numbr = STp->frame_seq_number; int logical_blk_num = STp->logical_blk_num; + int halfway_frame = STp->frame_in_buffer; + int read_pointer = STp->buffer->read_pointer; int prev_mark_ppos = -1; int actual_mark_ppos, i, n; -#if 1 //DEBUG +#if DEBUG int dev = TAPE_NR(STp->devt); - printk(OSST_DEB_MSG "osst%i: Verify that the tape is really the one we think before writing\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Verify that the tape is really the one we think before writing\n", dev); #endif osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0); - if (osst_get_logical_blk(STp, aSRpnt, -1, 0) < 0) { + if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) { #if DEBUG - printk(OSST_DEB_MSG "osst%i: Couldn't get logical blk num in verify_position\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in verify_position\n", dev); #endif return (-EIO); } @@ -2137,42 +2334,48 @@ prev_mark_ppos = frame_position - 1; /* usually - we don't really know */ actual_mark_ppos = STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER ? frame_position - 1 : ntohl(STp->buffer->aux->last_mark_ppos); - if (frame_position != STp->first_frame_position || - logical_blk_num != STp->logical_blk_num + 1 || - prev_mark_ppos != actual_mark_ppos ) { -#if 1 //DEBUG - printk(OSST_DEB_MSG "osst%i: Block mismatch: frame %d-%d, lblk %d-%d, mark %d-%d\n", dev, - STp->first_frame_position, frame_position, STp->logical_blk_num + 1, - logical_blk_num, actual_mark_ppos, prev_mark_ppos); + if (frame_position != STp->first_frame_position || + frame_seq_numbr != STp->frame_seq_number + (halfway_frame?0:1) || + prev_mark_ppos != actual_mark_ppos ) { +#if DEBUG + printk(OSST_DEB_MSG "osst%d:D: Block mismatch: fppos %d-%d, fseq %d-%d, mark %d-%d\n", dev, + STp->first_frame_position, frame_position, + STp->frame_seq_number + (halfway_frame?0:1), + frame_seq_numbr, actual_mark_ppos, prev_mark_ppos); #endif return (-EIO); } - STp->logical_blk_in_buffer = 0; - STp->logical_blk_num = logical_blk_num; + if (halfway_frame) { + /* prepare buffer for append and rewrite on top of original */ + osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0); + STp->buffer->buffer_bytes = read_pointer; + STp->ps[STp->partition].rw = ST_WRITING; + STp->dirty = 1; + } + STp->frame_in_buffer = halfway_frame; + STp->frame_seq_number = frame_seq_numbr; + STp->logical_blk_num = logical_blk_num; return 0; } /* Acc. to OnStream, the vers. numbering is the following: * X.XX for released versions (X=digit), * XXXY for unreleased versions (Y=letter) - * Ordering 1.05 < 106A < 106a < 106B < ... < 1.06 + * Ordering 1.05 < 106A < 106B < ... < 106a < ... < 1.06 * This fn makes monoton numbers out of this scheme ... */ static unsigned int osst_parse_firmware_rev (const char * str) { - unsigned int rev; if (str[1] == '.') { - rev = (str[0]-0x30)*10000 - +(str[2]-0x30)*1000 - +(str[3]-0x30)*100; + return (str[0]-'0')*10000 + +(str[2]-'0')*1000 + +(str[3]-'0')*100; } else { - rev = (str[0]-0x30)*10000 - +(str[1]-0x30)*1000 - +(str[2]-0x30)*100 - 100; - rev += 2*(str[3] & 0x1f) - +(str[3] >= 0x60? 1: 0); + return (str[0]-'0')*10000 + +(str[1]-'0')*1000 + +(str[2]-'0')*100 - 100 + +(str[3]-'@'); } - return rev; } /* @@ -2180,9 +2383,9 @@ */ static int osst_configure_onstream(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt) { - int dev = TAPE_NR(STp->devt); unsigned char cmd[MAX_COMMAND_SIZE]; - Scsi_Request * SRpnt = * aSRpnt; + int dev = TAPE_NR(STp->devt); + Scsi_Request * SRpnt = * aSRpnt; osst_mode_parameter_header_t * header; osst_block_size_page_t * bs; osst_capabilities_page_t * cp; @@ -2191,21 +2394,19 @@ if (STp->ready != ST_READY) { #if DEBUG - printk(OSST_DEB_MSG "osst%i: Not Ready\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Not Ready\n", dev); #endif return (-EIO); } if (STp->os_fw_rev < 10600) { - printk("osst%i: Old OnStream firmware revision detected (%s)\n", - dev, STp->device->rev); - printk("osst%i: An upgrade to version 1.06 or above is recommended\n", - dev); + printk(KERN_INFO "osst%i:I: Old OnStream firmware revision detected (%s),\n", dev, STp->device->rev); + printk(KERN_INFO "osst%d:I: an upgrade to version 1.06 or above is recommended\n", dev); } /* * Configure 32.5KB (data+aux) frame size. - * Get the current block size from the block size mode page + * Get the current frame size from the block size mode page */ memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = MODE_SENSE; @@ -2216,13 +2417,13 @@ SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_READ, STp->timeout, 0, TRUE); if (SRpnt == NULL) { #if DEBUG - printk(OSST_DEB_MSG "osst: Busy\n"); + printk(OSST_DEB_MSG "osst :D: Busy\n"); #endif return (-EBUSY); } *aSRpnt = SRpnt; if ((STp->buffer)->syscall_result != 0) { - printk (KERN_ERR "osst%i: Can't get tape block size mode page\n", dev); + printk (KERN_ERR "osst%i:E: Can't get tape block size mode page\n", dev); return (-EIO); } @@ -2230,10 +2431,10 @@ bs = (osst_block_size_page_t *) ((STp->buffer)->b_data + sizeof(osst_mode_parameter_header_t) + header->bdl); #if DEBUG - printk(KERN_INFO "osst%i: 32KB play back: %s\n", dev, bs->play32 ? "Yes" : "No"); - printk(KERN_INFO "osst%i: 32.5KB play back: %s\n", dev, bs->play32_5 ? "Yes" : "No"); - printk(KERN_INFO "osst%i: 32KB record: %s\n", dev, bs->record32 ? "Yes" : "No"); - printk(KERN_INFO "osst%i: 32.5KB record: %s\n", dev, bs->record32_5 ? "Yes" : "No"); + printk(OSST_DEB_MSG "osst%d:D: 32KB play back: %s\n", dev, bs->play32 ? "Yes" : "No"); + printk(OSST_DEB_MSG "osst%d:D: 32.5KB play back: %s\n", dev, bs->play32_5 ? "Yes" : "No"); + printk(OSST_DEB_MSG "osst%d:D: 32KB record: %s\n", dev, bs->record32 ? "Yes" : "No"); + printk(OSST_DEB_MSG "osst%d:D: 32.5KB record: %s\n", dev, bs->record32_5 ? "Yes" : "No"); #endif /* @@ -2253,16 +2454,12 @@ SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE, STp->timeout, 0, TRUE); *aSRpnt = SRpnt; if ((STp->buffer)->syscall_result != 0) { - printk (KERN_ERR "osst%i: Couldn't set tape block size mode page\n", dev); + printk (KERN_ERR "osst%i:E: Couldn't set tape block size mode page\n", dev); return (-EIO); } - STp->block_size = (STp->raw) ? OS_FRAME_SIZE : OS_DATA_SIZE; - STp->min_block = OS_FRAME_SIZE; /* FIXME */ - STp->max_block = STp->block_size; - #if DEBUG - printk(KERN_INFO "osst%i: Block Size changed to 32.5K\n", dev); + printk(KERN_INFO "osst%d:D: Block Size changed to 32.5K\n", dev); /* * In debug mode, we want to see as many errors as possible * to test the error recovery mechanism. @@ -2298,7 +2495,7 @@ *aSRpnt = SRpnt; if ((STp->buffer)->syscall_result != 0) { - printk (KERN_ERR "osst%i: Couldn't set vendor name to %s\n", dev, + printk (KERN_ERR "osst%i:E: Couldn't set vendor name to %s\n", dev, (char *) ((STp->buffer)->b_data + MODE_HEADER_LENGTH + 2)); return (-EIO); } @@ -2313,7 +2510,7 @@ *aSRpnt = SRpnt; if ((STp->buffer)->syscall_result != 0) { - printk (KERN_ERR "osst%i: can't get capabilities page\n", dev); + printk (KERN_ERR "osst%i:E: Can't get capabilities page\n", dev); return (-EIO); } @@ -2333,7 +2530,7 @@ *aSRpnt = SRpnt; if ((STp->buffer)->syscall_result != 0) { - printk (KERN_ERR "osst%i: can't get tape parameter page\n", dev); + printk (KERN_ERR "osst%i:E: Can't get tape parameter page\n", dev); return (-EIO); } @@ -2344,7 +2541,7 @@ STp->density = prm->density; STp->capacity = ntohs(prm->segtrk) * ntohs(prm->trks); #if DEBUG - printk(OSST_DEB_MSG "osst%d: Density %d, tape length: %dMB, drive buffer size: %dKB\n", + printk(OSST_DEB_MSG "osst%d:D: Density %d, tape length: %dMB, drive buffer size: %dKB\n", dev, STp->density, STp->capacity / 32, drive_buffer_size); #endif @@ -2362,7 +2559,7 @@ #if DEBUG if (debugging) - printk(OSST_DEB_MSG "osst%d: Stepping over filemark %s.\n", + printk(OSST_DEB_MSG "osst%d:D: Stepping over filemark %s.\n", dev, forward ? "forward" : "backward"); #endif @@ -2375,7 +2572,7 @@ result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - 1); if (result < 0) - printk(KERN_ERR "osst%d: Stepping over filemark %s failed.\n", + printk(KERN_WARNING "osst%d:W: Stepping over filemark %s failed.\n", dev, forward ? "forward" : "backward"); return result; @@ -2415,7 +2612,7 @@ result = ((SRpnt->sr_sense_buffer[2] & 0x0f) == 3) ? -EIO : -EINVAL; if (result == -EINVAL) - printk(KERN_ERR "osst%d: Can't read tape position.\n", dev); + printk(KERN_ERR "osst%d:E: Can't read tape position.\n", dev); else { if (result == -EIO) { /* re-read position */ @@ -2440,7 +2637,7 @@ STp->cur_frames = (STp->buffer)->b_data[15]; #if DEBUG if (debugging) { - printk(OSST_DEB_MSG "osst%d: Drive Positions: host %d, tape %d%s, buffer %d\n", dev, + printk(OSST_DEB_MSG "osst%d:D: Drive Positions: host %d, tape %d%s, buffer %d\n", dev, STp->first_frame_position, STp->last_frame_position, ((STp->buffer)->b_data[0]&0x80)?" (BOP)": ((STp->buffer)->b_data[0]&0x40)?" (EOP)":"", @@ -2449,7 +2646,7 @@ #endif if (STp->cur_frames == 0 && STp->first_frame_position != STp->last_frame_position) { #if DEBUG - printk(KERN_WARNING "osst%d: Correcting read position %d, %d, %d\n", dev, + printk(KERN_WARNING "osst%d:D: Correcting read position %d, %d, %d\n", dev, STp->first_frame_position, STp->last_frame_position, STp->cur_frames); #endif STp->first_frame_position = STp->last_frame_position; @@ -2462,55 +2659,61 @@ /* Set the tape block */ -static int osst_set_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int block, int skip) +static int osst_set_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int ppos, int skip) { unsigned char scmd[MAX_COMMAND_SIZE]; Scsi_Request * SRpnt; ST_partstat * STps; int result = 0; - int timeout; + int pp = (ppos == 3000 && !skip)? 0 : ppos; int dev = TAPE_NR(STp->devt); if (STp->ready != ST_READY) return (-EIO); - timeout = STp->long_timeout; STps = &(STp->ps[STp->partition]); - if (block < 0 || block > STp->capacity) { - printk(KERN_ERR "osst%d: Reposition request %d out of range\n", dev, block); - block = block < 0 ? 0 : (STp->capacity - 1); + if (ppos < 0 || ppos > STp->capacity) { + printk(KERN_WARNING "osst%d:W: Reposition request %d out of range\n", dev, ppos); + pp = ppos = ppos < 0 ? 0 : (STp->capacity - 1); result = (-EINVAL); } + + do { #if DEBUG - if (debugging) - printk(OSST_DEB_MSG "osst%d: Setting block to %d.\n", dev, block); + if (debugging) + printk(OSST_DEB_MSG "osst%d:D: Setting ppos to %d.\n", dev, pp); #endif - memset (scmd, 0, MAX_COMMAND_SIZE); - scmd[0] = SEEK_10; - scmd[1] = 1; - scmd[3] = (block >> 24); - scmd[4] = (block >> 16); - scmd[5] = (block >> 8); - scmd[6] = block; - if (skip) - scmd[9] = 0x80; + memset (scmd, 0, MAX_COMMAND_SIZE); + scmd[0] = SEEK_10; + scmd[1] = 1; + scmd[3] = (pp >> 24); + scmd[4] = (pp >> 16); + scmd[5] = (pp >> 8); + scmd[6] = pp; + if (skip) + scmd[9] = 0x80; - SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 0, SCSI_DATA_NONE, timeout, MAX_READY_RETRIES, TRUE); - if (!SRpnt) - return (-EBUSY); - *aSRpnt = SRpnt; + SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 0, SCSI_DATA_NONE, STp->long_timeout, + MAX_READY_RETRIES, TRUE); + if (!SRpnt) + return (-EBUSY); + *aSRpnt = SRpnt; - STp->first_frame_position = STp->last_frame_position = block; - STps->eof = ST_NOEOF; - if ((STp->buffer)->syscall_result != 0) { + if ((STp->buffer)->syscall_result != 0) { #if DEBUG - printk(OSST_DEB_MSG "osst%d: SEEK command failed.\n", dev); + printk(OSST_DEB_MSG "osst%d:D: SEEK command from %d to %d failed.\n", + dev, STp->first_frame_position, pp); #endif - result = (-EIO); - } + result = (-EIO); + } + if (pp != ppos) + osst_wait_ready(STp, aSRpnt, 5 * 60); + } while ((pp != ppos) && (pp = ppos)); + STp->first_frame_position = STp->last_frame_position = ppos; + STps->eof = ST_NOEOF; STps->at_sm = 0; STps->rw = ST_IDLE; - STp->logical_blk_in_buffer = 0; + STp->frame_in_buffer = 0; return result; } @@ -2519,7 +2722,7 @@ /* osst versions of st functions - augmented and stripped to suit OnStream only */ /* Flush the write buffer (never need to write if variable blocksize). */ -static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int file_blk) +static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt) { int offset, transfer, blks = 0; int result = 0; @@ -2532,19 +2735,19 @@ if (SRpnt == (STp->buffer)->last_SRpnt) #if DEBUG { printk(OSST_DEB_MSG - "osst%d: aSRpnt points to Scsi_Request that write_behind_check will release -- cleared\n", dev); + "osst%d:D: aSRpnt points to Scsi_Request that write_behind_check will release -- cleared\n", dev); #endif *aSRpnt = SRpnt = NULL; #if DEBUG } else if (SRpnt) printk(OSST_DEB_MSG - "osst%d: aSRpnt does not point to Scsi_Request that write_behind_check will release -- strange\n", dev); + "osst%d:D: aSRpnt does not point to Scsi_Request that write_behind_check will release -- strange\n", dev); #endif osst_write_behind_check(STp); if ((STp->buffer)->syscall_result) { #if DEBUG if (debugging) - printk(OSST_DEB_MSG "osst%d: Async write error (flush) %x.\n", + printk(OSST_DEB_MSG "osst%d:D: Async write error (flush) %x.\n", dev, (STp->buffer)->midlevel_result); #endif if ((STp->buffer)->midlevel_result == INT_MAX) @@ -2556,15 +2759,13 @@ result = 0; if (STp->dirty == 1) { + STp->write_count++; + STps = &(STp->ps[STp->partition]); + STps->rw = ST_WRITING; offset = STp->buffer->buffer_bytes; + blks = (offset + STp->block_size - 1) / STp->block_size; transfer = OS_FRAME_SIZE; - blks = 1; -#if DEBUG - if (debugging) - printk(OSST_DEB_MSG "osst%d: Flushing %d bytes, Tranfering %d bytes in %d blocks.\n", - dev, offset, transfer, blks); -#endif if (offset < OS_DATA_SIZE) osst_zero_buffer_tail(STp->buffer); @@ -2575,7 +2776,38 @@ memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = WRITE_6; cmd[1] = 1; - cmd[4] = blks; + cmd[4] = 1; + + switch (STp->write_type) { + case OS_WRITE_DATA: +#if DEBUG + if (debugging) + printk(OSST_DEB_MSG "osst%d:D: Writing %d blocks to frame %d, lblks %d-%d\n", + dev, blks, STp->frame_seq_number, + STp->logical_blk_num - blks, STp->logical_blk_num - 1); +#endif + osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++, + STp->logical_blk_num - blks, STp->block_size, blks); + break; + case OS_WRITE_EOD: + osst_init_aux(STp, OS_FRAME_TYPE_EOD, STp->frame_seq_number++, + STp->logical_blk_num, 0, 0); + break; + case OS_WRITE_NEW_MARK: + osst_init_aux(STp, OS_FRAME_TYPE_MARKER, STp->frame_seq_number++, + STp->logical_blk_num++, 0, blks=1); + break; + case OS_WRITE_HEADER: + osst_init_aux(STp, OS_FRAME_TYPE_HEADER, 0, 0, 0, blks=0); + break; + default: /* probably FILLER */ + osst_init_aux(STp, OS_FRAME_TYPE_FILL, 0, 0, 0, 0); + } +#if DEBUG + if (debugging) + printk(OSST_DEB_MSG "osst%d:D: Flushing %d bytes, Transfering %d bytes in %d lblocks.\n", + dev, offset, transfer, blks); +#endif SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, transfer, SCSI_DATA_WRITE, STp->timeout, MAX_WRITE_RETRIES, TRUE); @@ -2583,12 +2815,13 @@ if (!SRpnt) return (-EBUSY); - STps = &(STp->ps[STp->partition]); if ((STp->buffer)->syscall_result != 0) { +#if DEBUG printk(OSST_DEB_MSG - "osst%d: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n", + "osst%d:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n", dev, SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[2], SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]); +#endif if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 && (SRpnt->sr_sense_buffer[2] & 0x40) && /* FIXME - SC-30 drive doesn't assert EOM bit */ (SRpnt->sr_sense_buffer[2] & 0x0f) == NO_SENSE) { @@ -2598,22 +2831,20 @@ } else { if (osst_write_error_recovery(STp, aSRpnt, 1)) { - printk(KERN_ERR "osst%d: Error on flush.\n", dev); + printk(KERN_ERR "osst%d:E: Error on flush write.\n", dev); result = (-EIO); } } STps->drv_block = (-1); } else { - if (file_blk && STps->drv_block >= 0) - STps->drv_block += blks; - STp->first_frame_position += blks; + STp->first_frame_position++; STp->dirty = 0; (STp->buffer)->buffer_bytes = 0; } } #if DEBUG - printk(OSST_DEB_MSG "osst%d: Exit flush write buffer with code %d\n", dev, result); + printk(OSST_DEB_MSG "osst%d:D: Exit flush write buffer with code %d\n", dev, result); #endif return result; } @@ -2623,15 +2854,12 @@ seek_next is true. */ static int osst_flush_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int seek_next) { - int backspace, result; - OSST_buffer * STbuffer; - ST_partstat * STps; + ST_partstat * STps; + int backspace = 0, result = 0; #if DEBUG int dev = TAPE_NR(STp->devt); #endif - STbuffer = STp->buffer; - /* * If there was a bus reset, block further access * to this device. @@ -2644,19 +2872,23 @@ STps = &(STp->ps[STp->partition]); if (STps->rw == ST_WRITING) /* Writing */ - return osst_flush_write_buffer(STp, aSRpnt, 1); + return osst_flush_write_buffer(STp, aSRpnt); if (STp->block_size == 0) return 0; #if DEBUG - printk(OSST_DEB_MSG "osst%i: Reached flush (read) buffer\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Reached flush (read) buffer\n", dev); #endif - backspace = ((STp->buffer)->buffer_bytes + (STp->buffer)->read_pointer) / STp->block_size - - ((STp->buffer)->read_pointer + STp->block_size - 1 ) / STp->block_size ; - (STp->buffer)->buffer_bytes = 0; - (STp->buffer)->read_pointer = 0; - result = 0; + + if (!STp->can_bsr) { + backspace = ((STp->buffer)->buffer_bytes + (STp->buffer)->read_pointer) / STp->block_size - + ((STp->buffer)->read_pointer + STp->block_size - 1 ) / STp->block_size ; + (STp->buffer)->buffer_bytes = 0; + (STp->buffer)->read_pointer = 0; + STp->frame_in_buffer = 0; /* FIXME is this relevant w. OSST? */ + } + if (!seek_next) { if (STps->eof == ST_FM_HIT) { result = cross_eof(STp, aSRpnt, FALSE); /* Back over the EOF hit */ @@ -2681,6 +2913,88 @@ return result; } +static int osst_write_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int synchronous) +{ + unsigned char cmd[MAX_COMMAND_SIZE]; + Scsi_Request * SRpnt; + int blks; +#if DEBUG + int dev = TAPE_NR(STp->devt); +#endif + + if ((!STp-> raw) && (STp->first_frame_position == 0xbae)) { /* _must_ preserve buffer! */ +#if DEBUG + printk(OSST_DEB_MSG "osst%d:D: Reaching config partition.\n", dev); +#endif + if (osst_flush_drive_buffer(STp, aSRpnt) < 0) { + return (-EIO); + } + /* error recovery may have bumped us past the header partition */ + if (osst_get_frame_position(STp, aSRpnt) < 0xbb8) { +#if DEBUG + printk(OSST_DEB_MSG "osst%d:D: Skipping over config partition.\n", dev); +#endif + osst_position_tape_and_confirm(STp, aSRpnt, 0xbb8); + } + } + + if (STp->poll) + osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 60); + /* TODO: Check for an error ! */ + +// osst_build_stats(STp, &SRpnt); + + STp->ps[STp->partition].rw = ST_WRITING; + STp->write_type = OS_WRITE_DATA; + + memset(cmd, 0, MAX_COMMAND_SIZE); + cmd[0] = WRITE_6; + cmd[1] = 1; + cmd[4] = 1; /* one frame at a time... */ + blks = STp->buffer->buffer_bytes / STp->block_size; +#if DEBUG + if (debugging) + printk(OSST_DEB_MSG "osst%d:D: Writing %d blocks to frame %d, lblks %d-%d\n", dev, blks, + STp->frame_seq_number, STp->logical_blk_num - blks, STp->logical_blk_num - 1); +#endif + osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++, + STp->logical_blk_num - blks, STp->block_size, blks); + +#if DEBUG + if (!synchronous) + STp->write_pending = 1; +#endif + SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_WRITE, STp->timeout, + MAX_WRITE_RETRIES, synchronous); + if (!SRpnt) + return (-EBUSY); + *aSRpnt = SRpnt; + + if (synchronous) { + if (STp->buffer->syscall_result != 0) { +#if DEBUG + if (debugging) + printk(OSST_DEB_MSG "osst%d:D: Error on write:\n", dev); +#endif + if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 && + (SRpnt->sr_sense_buffer[2] & 0x40)) { + if ((SRpnt->sr_sense_buffer[2] & 0x0f) == VOLUME_OVERFLOW) + return (-ENOSPC); + } + else { + if (osst_write_error_recovery(STp, aSRpnt, 1)) + return (-EIO); + } + } + else + STp->first_frame_position++; + } + + STp->write_count++; + + return 0; +} + /* Entry points to osst */ @@ -2692,7 +3006,6 @@ ssize_t i, do_count, blks, transfer; int write_threshold; int doing_write = 0; - unsigned char cmd[MAX_COMMAND_SIZE]; const char *b_point; Scsi_Request * SRpnt = NULL; OS_Scsi_Tape * STp; @@ -2748,7 +3061,7 @@ #if DEBUG if (!STp->in_use) { - printk(OSST_DEB_MSG "osst%d: Incorrect device.\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Incorrect device.\n", dev); retval = (-EIO); goto out; } @@ -2761,14 +3074,15 @@ /* Write must be integral number of blocks */ if (STp->block_size != 0 && (count % STp->block_size) != 0) { - printk(KERN_WARNING "osst%d: Write (%ld bytes) not multiple of tape block size (32k).\n", - dev, (unsigned long)count); + printk(KERN_ERR "osst%d:E: Write (%ld bytes) not multiple of tape block size (%d%c).\n", + dev, (unsigned long)count, STp->block_size<1024? + STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k'); retval = (-EINVAL); goto out; } - if (STp->first_frame_position >= STp->capacity - 164) { - printk(KERN_WARNING "osst%d: Write truncated at EOM early warning (frame %d).\n", + if (STp->first_frame_position >= STp->capacity - OSST_EOM_RESERVE) { + printk(KERN_ERR "osst%d:E: Write truncated at EOM early warning (frame %d).\n", dev, STp->first_frame_position); retval = (-ENOSPC); goto out; @@ -2789,46 +3103,49 @@ } else if (STps->rw != ST_WRITING) { /* Are we totally rewriting this tape? */ - if (!STp->header_ok || STp->first_frame_position == STp->first_data_ppos || - (STps->drv_file == 0 && STps->drv_block == 0)) { + if (!STp->header_ok || + (STp->first_frame_position == STp->first_data_ppos && STps->drv_block < 0) || + (STps->drv_file == 0 && STps->drv_block == 0)) { STp->wrt_pass_cntr++; #if DEBUG - printk(OSST_DEB_MSG "osst%d: Allocating next write pass counter: %d\n", + printk(OSST_DEB_MSG "osst%d:D: Allocating next write pass counter: %d\n", dev, STp->wrt_pass_cntr); #endif osst_reset_header(STp, &SRpnt); - STps->drv_file = STps->drv_block = STp->logical_blk_num = 0; + STps->drv_file = STps->drv_block = 0; } /* Do we know where we'll be writing on the tape? */ else { if ((STp->fast_open && osst_verify_position(STp, &SRpnt)) || STps->drv_file < 0 || STps->drv_block < 0) { - if (STp->first_frame_position == STp->eod_frame_ppos) { + if (STp->first_frame_position == STp->eod_frame_ppos) { /* at EOD */ STps->drv_file = STp->filemark_cnt; STps->drv_block = 0; } else { /* We have no idea where the tape is positioned - give up */ #if DEBUG - printk(OSST_DEB_MSG "osst%d: Cannot write at indeterminate position.\n", dev); + printk(OSST_DEB_MSG + "osst%d:D: Cannot write at indeterminate position.\n", dev); #endif retval = (-EIO); goto out; } } - if (STps->drv_file > 0 && STps->drv_file < STp->filemark_cnt) { + if ((STps->drv_file + STps->drv_block) > 0 && STps->drv_file < STp->filemark_cnt) { STp->filemark_cnt = STps->drv_file; - STp->last_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt-1]); + STp->last_mark_ppos = + ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt-1]); printk(KERN_WARNING - "osst%d: Overwriting file %d with old write pass counter %d\n", + "osst%d:W: Overwriting file %d with old write pass counter %d\n", dev, STps->drv_file, STp->wrt_pass_cntr); printk(KERN_WARNING - "osst%d: may lead to stale data being accepted on reading back!\n", + "osst%d:W: may lead to stale data being accepted on reading back!\n", dev); #if DEBUG printk(OSST_DEB_MSG - "osst%d: resetting filemark count to %d and last mark ppos to %d\n", - dev, STp->filemark_cnt, STp->last_mark_ppos); + "osst%d:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n", + dev, STp->filemark_cnt, STp->last_mark_ppos, STp->last_mark_lbn); #endif } } @@ -2836,19 +3153,19 @@ } if (!STp->header_ok) { #if DEBUG - printk(OSST_DEB_MSG "osst%d: Write cannot proceed without valid headers\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Write cannot proceed without valid headers\n", dev); #endif retval = (-EIO); goto out; } if ((STp->buffer)->writing) { -if (SRpnt) printk(KERN_ERR "osst%d: Not supposed to have SRpnt at line %d\n", dev, __LINE__); +if (SRpnt) printk(KERN_ERR "osst%d:A: Not supposed to have SRpnt at line %d\n", dev, __LINE__); osst_write_behind_check(STp); if ((STp->buffer)->syscall_result) { #if DEBUG if (debugging) - printk(OSST_DEB_MSG "osst%d: Async write error (write) %x.\n", dev, + printk(OSST_DEB_MSG "osst%d:D: Async write error (write) %x.\n", dev, (STp->buffer)->midlevel_result); #endif if ((STp->buffer)->midlevel_result == INT_MAX) @@ -2875,10 +3192,6 @@ } if (!STm->do_buffer_writes) { -#if 0 - if (STp->block_size != 0 && (count % STp->block_size) != 0) - {retval=(-EIO);goto out;} /* Write must be integral number of blocks */ -#endif write_threshold = 1; } else @@ -2887,37 +3200,12 @@ write_threshold--; total = count; - - if ((!STp-> raw) && (STp->first_frame_position == 0xbae)) { #if DEBUG - printk(OSST_DEB_MSG "osst%d: Skipping over config partition.\n", dev); -#endif - if (osst_flush_drive_buffer(STp, &SRpnt) < 0) { - retval = (-EIO); - goto out; - } - /* error recovery may have bumped us past the header partition */ - if (osst_get_frame_position(STp, &SRpnt) < 0xbb8) - osst_position_tape_and_confirm(STp, &SRpnt, 0xbb8); - } - - if (STp->poll) - retval = osst_wait_frame (STp, &SRpnt, STp->first_frame_position, -50, 60); - /* TODO: Check for an error ! */ - - memset(cmd, 0, MAX_COMMAND_SIZE); - cmd[0] = WRITE_6; - cmd[1] = 1; - - STps->rw = ST_WRITING; - STp->write_type = OS_WRITE_DATA; - -#if DEBUG - printk(OSST_DEB_MSG "osst%d: Writing %d bytes to file %d block %d lblk %d frame %d\n", - dev, count, STps->drv_file, STps->drv_block, - STp->logical_blk_num, STp->first_frame_position); + if (debugging) + printk(OSST_DEB_MSG "osst%d:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n", + dev, count, STps->drv_file, STps->drv_block, + STp->logical_blk_num, STp->frame_seq_number, STp->first_frame_position); #endif - b_point = buf; while ((STp->buffer)->buffer_bytes + count > write_threshold) { @@ -2933,85 +3221,62 @@ goto out; } - transfer = OS_FRAME_SIZE; - blks = 1; - - osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->logical_blk_num++ ); - - cmd[2] = blks >> 16; - cmd[3] = blks >> 8; - cmd[4] = blks; - - SRpnt = osst_do_scsi(SRpnt, STp, cmd, transfer, SCSI_DATA_WRITE, - STp->timeout, MAX_WRITE_RETRIES, TRUE); - if (!SRpnt) { - retval = (STp->buffer)->syscall_result; - goto out; - } + blks = do_count / STp->block_size; + STp->logical_blk_num += blks; /* logical_blk_num is incremented as data is moved from user */ + + i = osst_write_frame(STp, &SRpnt, TRUE); - if ((STp->buffer)->syscall_result != 0) { -#if DEBUG - if (debugging) - printk(OSST_DEB_MSG "osst%d: Error on write:\n", dev); -#endif - if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 && - (SRpnt->sr_sense_buffer[2] & 0x40)) { - if ((SRpnt->sr_sense_buffer[0] & 0x80) != 0) - transfer = (SRpnt->sr_sense_buffer[3] << 24) | - (SRpnt->sr_sense_buffer[4] << 16) | - (SRpnt->sr_sense_buffer[5] << 8) | - SRpnt->sr_sense_buffer[6]; - else - transfer = 0; - transfer *= STp->block_size; - if (transfer <= do_count) { - filp->f_pos += do_count - transfer; - count -= do_count - transfer; - if (STps->drv_block >= 0) { - STps->drv_block += (do_count - transfer) / STp->block_size; - } - STps->eof = ST_EOM_OK; - retval = (-ENOSPC); /* EOM within current request */ -#if DEBUG - if (debugging) - printk(OSST_DEB_MSG "osst%d: EOM with %d bytes unwritten.\n", - dev, transfer); -#endif + if (i == (-ENOSPC)) { + transfer = STp->buffer->writing; /* FIXME -- check this logic */ + if (transfer <= do_count) { + filp->f_pos += do_count - transfer; + count -= do_count - transfer; + if (STps->drv_block >= 0) { + STps->drv_block += (do_count - transfer) / STp->block_size; } - else { - STps->eof = ST_EOM_ERROR; - STps->drv_block = (-1); /* Too cautious? */ - retval = (-EIO); /* EOM for old data */ + STps->eof = ST_EOM_OK; + retval = (-ENOSPC); /* EOM within current request */ #if DEBUG - if (debugging) - printk(OSST_DEB_MSG "osst%d: EOM with lost data.\n", dev); + if (debugging) + printk(OSST_DEB_MSG "osst%d:D: EOM with %d bytes unwritten.\n", + dev, transfer); #endif - } } else { - if (osst_write_error_recovery(STp, &SRpnt, 1) == 0) goto ok; - STps->drv_block = (-1); /* Too cautious? */ - retval = (-EIO); + STps->eof = ST_EOM_ERROR; + STps->drv_block = (-1); /* Too cautious? */ + retval = (-EIO); /* EOM for old data */ +#if DEBUG + if (debugging) + printk(OSST_DEB_MSG "osst%d:D: EOM with lost data.\n", dev); +#endif } - - (STp->buffer)->buffer_bytes = 0; + } + else + retval = i; + + if (retval < 0) { + if (SRpnt != NULL) { + scsi_release_request(SRpnt); + SRpnt = NULL; + } + STp->buffer->buffer_bytes = 0; STp->dirty = 0; if (count < total) retval = total - count; goto out; } - STp->first_frame_position++; -ok: + filp->f_pos += do_count; b_point += do_count; count -= do_count; if (STps->drv_block >= 0) { STps->drv_block += blks; } - STp->first_frame_position += blks; - (STp->buffer)->buffer_bytes = 0; + STp->buffer->buffer_bytes = 0; STp->dirty = 0; - } + } /* end while write threshold exceeded */ + if (count != 0) { STp->dirty = 1; i = append_to_buffer(b_point, STp->buffer, count); @@ -3019,6 +3284,11 @@ retval = i; goto out; } + blks = count / STp->block_size; + STp->logical_blk_num += blks; + if (STps->drv_block >= 0) { + STps->drv_block += blks; + } filp->f_pos += count; count = 0; } @@ -3028,41 +3298,23 @@ goto out; } - if (STm->do_async_writes && - ((STp->buffer)->buffer_bytes >= STp->write_threshold && - (STp->buffer)->buffer_bytes >= OS_DATA_SIZE) ) { + if (STm->do_async_writes && ((STp->buffer)->buffer_bytes >= STp->write_threshold)) { /* Schedule an asynchronous write */ (STp->buffer)->writing = ((STp->buffer)->buffer_bytes / STp->block_size) * STp->block_size; STp->dirty = !((STp->buffer)->writing == (STp->buffer)->buffer_bytes); - transfer = OS_FRAME_SIZE; - blks = 1; - - osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->logical_blk_num++ ); - - cmd[2] = blks >> 16; - cmd[3] = blks >> 8; - cmd[4] = blks; -#if DEBUG - STp->write_pending = 1; -#endif - - SRpnt = osst_do_scsi(SRpnt, STp, cmd, transfer, SCSI_DATA_WRITE, - STp->timeout, MAX_WRITE_RETRIES, FALSE); - if (SRpnt == NULL) { - retval = (STp->buffer)->syscall_result; + i = osst_write_frame(STp, &SRpnt, FALSE); + if (i < 0) { + retval = (-EIO); goto out; } + SRpnt = NULL; /* Prevent releasing this request! */ } -// else if (SRpnt != NULL) { -// scsi_release_request(SRpnt); /* FIXME -- this relesae no longer in st - why? */ - SRpnt = NULL; /* Prevent releasing this request! */ -// } STps->at_sm &= (total == 0); if (total > 0) - STps->eof = ST_NOEOF; + STps->eof = ST_NOEOF; retval = total; @@ -3124,7 +3376,7 @@ } #if DEBUG if (!STp->in_use) { - printk(OSST_DEB_MSG "osst%d: Incorrect device.\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Incorrect device.\n", dev); retval = (-EIO); goto out; } @@ -3135,13 +3387,6 @@ goto out; } - if ((count % STp->block_size) != 0) { - printk(KERN_WARNING "osst%d: Use multiple of %d bytes as block size (%ld requested)\n", - dev, STp->block_size, (unsigned long) count); - retval = (-EINVAL); /* Read must be integral number of blocks */ - goto out; - } - if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !osst_int_ioctl(STp, &SRpnt, MTLOCK, 0)) STp->door_locked = ST_LOCKED_AUTO; @@ -3154,9 +3399,15 @@ STps->rw = ST_IDLE; } + if ((count % STp->block_size) != 0) { + printk(KERN_WARNING + "osst%d:W: Read (%Zd bytes) not multiple of tape block size (%d%c).\n", dev, count, + STp->block_size<1024?STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k'); + } + #if DEBUG if (debugging && STps->eof != ST_NOEOF) - printk(OSST_DEB_MSG "osst%d: EOF/EOM flag up (%d). Bytes %d\n", dev, + printk(OSST_DEB_MSG "osst%d:D: EOF/EOM flag up (%d). Bytes %d\n", dev, STps->eof, (STp->buffer)->buffer_bytes); #endif if ((STp->buffer)->buffer_bytes == 0 && @@ -3181,41 +3432,51 @@ } /* Loop until enough data in buffer or a special condition found */ - for (total = 0, special = 0; total < count && !special; ) { + for (total = 0, special = 0; total < count - STp->block_size + 1 && !special; ) { /* Get new data if the buffer is empty */ if ((STp->buffer)->buffer_bytes == 0) { - special = osst_get_logical_blk(STp, &SRpnt, STp->logical_blk_num, 0); - STp->buffer->buffer_bytes = special ? 0 : OS_DATA_SIZE; - STp->buffer->read_pointer = 0; - STp->logical_blk_num++; /* block to look for next time */ - STp->logical_blk_in_buffer = 0; + if (STps->eof == ST_FM_HIT) + break; + special = osst_get_logical_frame(STp, &SRpnt, STp->frame_seq_number, 0); if (special < 0) { /* No need to continue read */ + STp->frame_in_buffer = 0; retval = special; goto out; } - STps->drv_block++; } /* Move the data from driver buffer to user buffer */ if ((STp->buffer)->buffer_bytes > 0) { #if DEBUG if (debugging && STps->eof != ST_NOEOF) - printk(OSST_DEB_MSG "osst%d: EOF up (%d). Left %d, needed %d.\n", dev, + printk(OSST_DEB_MSG "osst%d:D: EOF up (%d). Left %d, needed %d.\n", dev, STps->eof, (STp->buffer)->buffer_bytes, count - total); #endif - transfer = (STp->buffer)->buffer_bytes < count - total ? - (STp->buffer)->buffer_bytes : count - total; + transfer = (((STp->buffer)->buffer_bytes < count - total ? + (STp->buffer)->buffer_bytes : count - total)/ + STp->block_size) * STp->block_size; /* force multiple of block size */ i = from_buffer(STp->buffer, buf, transfer); if (i) { retval = i; goto out; } - filp->f_pos += transfer; - buf += transfer; - total += transfer; + STp->logical_blk_num += transfer / STp->block_size; + STps->drv_block += transfer / STp->block_size; + filp->f_pos += transfer; + buf += transfer; + total += transfer; + } + + if ((STp->buffer)->buffer_bytes == 0) { +#if DEBUG + if (debugging) + printk(OSST_DEB_MSG "osst%d:D: Finished with frame %d\n", + dev, STp->frame_seq_number); +#endif + STp->frame_in_buffer = 0; + STp->frame_seq_number++; /* frame to look for next time */ } - } /* for (total = 0, special = 0; total < count && !special; ) */ /* Change the eof state if no data from tape or buffer */ @@ -3253,21 +3514,21 @@ static void osst_log_options(OS_Scsi_Tape *STp, ST_mode *STm, int dev) { printk(KERN_INFO -"osst%d: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n", +"osst%d:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n", dev, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes, STm->do_read_ahead); printk(KERN_INFO -"osst%d: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n", +"osst%d:I: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n", dev, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock); printk(KERN_INFO -"osst%d: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n", +"osst%d:I: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n", dev, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions, STp->scsi2_logical); printk(KERN_INFO -"osst%d: sysv: %d\n", dev, STm->sysv); +"osst%d:I: sysv: %d\n", dev, STm->sysv); #if DEBUG printk(KERN_INFO - "osst%d: debugging: %d\n", + "osst%d:D: debugging: %d\n", dev, debugging); #endif } @@ -3286,7 +3547,7 @@ modes_defined = TRUE; #if DEBUG if (debugging) - printk(OSST_DEB_MSG "osst%d: Initialized mode %d definition from mode 0\n", + printk(OSST_DEB_MSG "osst%d:D: Initialized mode %d definition from mode 0\n", dev, STp->current_mode); #endif } @@ -3347,23 +3608,28 @@ else if (code == MT_ST_WRITE_THRESHOLD) { value = (options & ~MT_ST_OPTIONS) * ST_KILOBYTE; if (value < 1 || value > osst_buffer_size) { - printk(KERN_WARNING "osst%d: Write threshold %d too small or too large.\n", + printk(KERN_WARNING "osst%d:W: Write threshold %d too small or too large.\n", dev, value); return (-EIO); } STp->write_threshold = value; - printk(KERN_INFO "osst%d: Write threshold set to %d bytes.\n", + printk(KERN_INFO "osst%d:I: Write threshold set to %d bytes.\n", dev, value); } else if (code == MT_ST_DEF_BLKSIZE) { value = (options & ~MT_ST_OPTIONS); if (value == ~MT_ST_OPTIONS) { STm->default_blksize = (-1); - printk(KERN_INFO "osst%d: Default block size disabled.\n", dev); + printk(KERN_INFO "osst%d:I: Default block size disabled.\n", dev); } else { + if (value < 512 || value > OS_DATA_SIZE || OS_DATA_SIZE % value) { + printk(KERN_WARNING "osst%d:W: Default block size cannot be set to %d.\n", + dev, value); + return (-EINVAL); + } STm->default_blksize = value; - printk(KERN_INFO "osst%d: Default block size set to %d bytes.\n", + printk(KERN_INFO "osst%d:I: Default block size set to %d bytes.\n", dev, STm->default_blksize); } } @@ -3371,12 +3637,12 @@ value = (options & ~MT_ST_OPTIONS); if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) { STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ; - printk(KERN_INFO "osst%d: Long timeout set to %d seconds.\n", dev, + printk(KERN_INFO "osst%d:I: Long timeout set to %d seconds.\n", dev, (value & ~MT_ST_SET_LONG_TIMEOUT)); } else { STp->timeout = value * HZ; - printk(KERN_INFO "osst%d: Normal timeout set to %d seconds.\n", dev, value); + printk(KERN_INFO "osst%d:I: Normal timeout set to %d seconds.\n", dev, value); } } else if (code == MT_ST_DEF_OPTIONS) { @@ -3385,33 +3651,33 @@ if (code == MT_ST_DEF_DENSITY) { if (value == MT_ST_CLEAR_DEFAULT) { STm->default_density = (-1); - printk(KERN_INFO "osst%d: Density default disabled.\n", dev); + printk(KERN_INFO "osst%d:I: Density default disabled.\n", dev); } else { STm->default_density = value & 0xff; - printk(KERN_INFO "osst%d: Density default set to %x\n", + printk(KERN_INFO "osst%d:I: Density default set to %x\n", dev, STm->default_density); } } else if (code == MT_ST_DEF_DRVBUFFER) { if (value == MT_ST_CLEAR_DEFAULT) { STp->default_drvbuffer = 0xff; - printk(KERN_INFO "osst%d: Drive buffer default disabled.\n", dev); + printk(KERN_INFO "osst%d:I: Drive buffer default disabled.\n", dev); } else { STp->default_drvbuffer = value & 7; - printk(KERN_INFO "osst%d: Drive buffer default set to %x\n", + printk(KERN_INFO "osst%d:I: Drive buffer default set to %x\n", dev, STp->default_drvbuffer); } } else if (code == MT_ST_DEF_COMPRESSION) { if (value == MT_ST_CLEAR_DEFAULT) { STm->default_compression = ST_DONT_TOUCH; - printk(KERN_INFO "osst%d: Compression default disabled.\n", dev); + printk(KERN_INFO "osst%d:I: Compression default disabled.\n", dev); } else { STm->default_compression = (value & 1 ? ST_YES : ST_NO); - printk(KERN_INFO "osst%d: Compression default set to %x\n", + printk(KERN_INFO "osst%d:I: Compression default set to %x\n", dev, (value & 1)); } } @@ -3433,7 +3699,7 @@ unsigned char cmd[MAX_COMMAND_SIZE]; Scsi_Request * SRpnt = * aSRpnt; ST_partstat * STps; - int fileno, blkno, at_sm, logical_blk_num; + int fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num; int datalen = 0, direction = SCSI_DATA_NONE; int dev = TAPE_NR(STp->devt); @@ -3448,6 +3714,7 @@ fileno = STps->drv_file; blkno = STps->drv_block; at_sm = STps->at_sm; + frame_seq_numbr = STp->frame_seq_number; logical_blk_num = STp->logical_blk_num; memset(cmd, 0, MAX_COMMAND_SIZE); @@ -3461,7 +3728,6 @@ ioctl_result = osst_space_over_filemarks_forward_fast(STp, &SRpnt, cmd_in, arg); else ioctl_result = osst_space_over_filemarks_forward_slow(STp, &SRpnt, cmd_in, arg); - logical_blk_num = STp->logical_blk_num; if (fileno >= 0) fileno += arg; blkno = 0; @@ -3474,7 +3740,6 @@ if (STp->raw) return (-EIO); ioctl_result = osst_space_over_filemarks_backward(STp, &SRpnt, cmd_in, arg); - logical_blk_num = STp->logical_blk_num; if (fileno >= 0) fileno -= arg; blkno = (-1); /* We can't know the block number */ @@ -3485,7 +3750,7 @@ case MTBSR: #if DEBUG if (debugging) - printk(OSST_DEB_MSG "osst%i: Skipping %lu blocks %s from logical block %d\n", + printk(OSST_DEB_MSG "osst%d:D: Skipping %lu blocks %s from logical block %d\n", dev, arg, cmd_in==MTFSR?"forward":"backward", logical_blk_num); #endif if (cmd_in == MTFSR) { @@ -3496,8 +3761,9 @@ logical_blk_num -= arg; if (blkno >= 0) blkno -= arg; } - ioctl_result = osst_seek_logical_blk(STp, &SRpnt, logical_blk_num-1); - STp->logical_blk_in_buffer = 0; + ioctl_result = osst_seek_logical_blk(STp, &SRpnt, logical_blk_num); + fileno = STps->drv_file; + blkno = STps->drv_block; at_sm &= (arg == 0); goto os_bypass; @@ -3509,7 +3775,7 @@ cmd[4] = arg; #if DEBUG if (debugging) - printk(OSST_DEB_MSG "osst%d: Spacing tape forward %d setmarks.\n", dev, + printk(OSST_DEB_MSG "osst%d:D: Spacing tape forward %d setmarks.\n", dev, cmd[2] * 65536 + cmd[3] * 256 + cmd[4]); #endif if (arg != 0) { @@ -3528,33 +3794,32 @@ if (debugging) { if (cmd[2] & 0x80) ltmp = 0xff000000; - ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4]; - printk(OSST_DEB_MSG "osst%d: Spacing tape backward %ld setmarks.\n", + ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4]; + printk(OSST_DEB_MSG "osst%d:D: Spacing tape backward %ld setmarks.\n", dev, (-ltmp)); } #endif if (arg != 0) { blkno = fileno = (-1); - at_sm = 1; + at_sm = 1; } break; case MTWEOF: if ( STps->rw == ST_WRITING && !(STp->device)->was_reset) - ioctl_result = osst_flush_write_buffer(STp, &SRpnt, 1); + ioctl_result = osst_flush_write_buffer(STp, &SRpnt); else - ioctl_result = 0; + ioctl_result = 0; for (i=0; ilogical_blk_num; + ioctl_result |= osst_write_filemark(STp, &SRpnt); if (fileno >= 0) fileno += arg; if (blkno >= 0) blkno = 0; goto os_bypass; case MTWSM: if (STp->write_prot) - return (-EACCES); + return (-EACCES); if (!STp->raw) - return 0; + return 0; cmd[0] = WRITE_FILEMARKS; /* FIXME -- need OS version */ if (cmd_in == MTWSM) cmd[1] = 2; @@ -3564,16 +3829,16 @@ timeout = STp->timeout; #if DEBUG if (debugging) { - if (cmd_in == MTWEOF) - printk(OSST_DEB_MSG "osst%d: Writing %d filemarks.\n", dev, + if (cmd_in == MTWEOF) + printk(OSST_DEB_MSG "osst%d:D: Writing %d filemarks.\n", dev, cmd[2] * 65536 + cmd[3] * 256 + cmd[4]); - else - printk(OSST_DEB_MSG "osst%d: Writing %d setmarks.\n", dev, + else + printk(OSST_DEB_MSG "osst%d:D: Writing %d setmarks.\n", dev, cmd[2] * 65536 + cmd[3] * 256 + cmd[4]); } #endif if (fileno >= 0) - fileno += arg; + fileno += arg; blkno = 0; at_sm = (cmd_in == MTWSM); break; @@ -3594,50 +3859,49 @@ if (debugging) { switch (cmd_in) { case MTUNLOAD: - printk(OSST_DEB_MSG "osst%d: Unloading tape.\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Unloading tape.\n", dev); break; case MTLOAD: - printk(OSST_DEB_MSG "osst%d: Loading tape.\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Loading tape.\n", dev); break; case MTRETEN: - printk(OSST_DEB_MSG "osst%d: Retensioning tape.\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Retensioning tape.\n", dev); break; case MTOFFL: - printk(OSST_DEB_MSG "osst%d: Ejecting tape.\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Ejecting tape.\n", dev); break; } } #endif - fileno = blkno = at_sm = logical_blk_num = 0 ; + fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ; break; case MTNOP: #if DEBUG if (debugging) - printk(OSST_DEB_MSG "osst%d: No op on tape.\n", dev); + printk(OSST_DEB_MSG "osst%d:D: No-op on tape.\n", dev); #endif return 0; /* Should do something ? */ break; case MTEOM: #if DEBUG if (debugging) - printk(OSST_DEB_MSG "osst%d: Spacing to end of recorded medium.\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Spacing to end of recorded medium.\n", dev); #endif osst_set_frame_position(STp, &SRpnt, STp->eod_frame_ppos, 0); - if (osst_get_logical_blk(STp, &SRpnt, -1, 0) < 0) { + if (osst_get_logical_frame(STp, &SRpnt, -1, 0) < 0) { ioctl_result = -EIO; goto os_bypass; } if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_EOD) { #if DEBUG - printk(OSST_DEB_MSG "osst%d: No EOD frame found where expected.\n", dev); + printk(OSST_DEB_MSG "osst%d:D: No EOD frame found where expected.\n", dev); #endif ioctl_result = -EIO; goto os_bypass; } ioctl_result = osst_set_frame_position(STp, &SRpnt, STp->eod_frame_ppos, 0); - logical_blk_num = STp->logical_blk_num; - fileno = STp->filemark_cnt; - blkno = at_sm = 0; + fileno = STp->filemark_cnt; + blkno = at_sm = 0; goto os_bypass; case MTERASE: @@ -3648,7 +3912,7 @@ if (i < ioctl_result) ioctl_result = i; i = osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos); if (i < ioctl_result) ioctl_result = i; - fileno = blkno = at_sm = logical_blk_num = 0 ; + fileno = blkno = at_sm = 0 ; goto os_bypass; case MTREW: @@ -3656,9 +3920,9 @@ cmd[1] = 1; #if DEBUG if (debugging) - printk(OSST_DEB_MSG "osst%d: Rewinding tape, Immed=%d.\n", dev, cmd[1]); + printk(OSST_DEB_MSG "osst%d:D: Rewinding tape, Immed=%d.\n", dev, cmd[1]); #endif - fileno = blkno = at_sm = logical_blk_num = 0 ; + fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ; break; case MTLOCK: @@ -3667,8 +3931,8 @@ cmd[4] = SCSI_REMOVAL_PREVENT; #if DEBUG if (debugging) - printk(OSST_DEB_MSG "osst%d: Locking drive door.\n", dev); -#endif; + printk(OSST_DEB_MSG "osst%d:D: Locking drive door.\n", dev); +#endif break; case MTUNLOCK: @@ -3677,8 +3941,8 @@ cmd[4] = SCSI_REMOVAL_ALLOW; #if DEBUG if (debugging) - printk(OSST_DEB_MSG "osst%d: Unlocking drive door.\n", dev); -#endif; + printk(OSST_DEB_MSG "osst%d:D: Unlocking drive door.\n", dev); +#endif break; case MTSETBLK: /* Set block length */ @@ -3693,10 +3957,10 @@ ((arg & MT_ST_BLKSIZE_MASK) < STp->min_block || (arg & MT_ST_BLKSIZE_MASK) > STp->max_block || (arg & MT_ST_BLKSIZE_MASK) > osst_buffer_size)) { - printk(KERN_WARNING "osst%d: Illegal block size.\n", dev); + printk(KERN_WARNING "osst%d:W: Illegal block size.\n", dev); return (-EINVAL); } - return 0; /* silently ignore if block size didn't change */ + return 0; /* FIXME silently ignore if block size didn't change */ default: return (-ENOSYS); @@ -3708,18 +3972,23 @@ if (!SRpnt) { #if DEBUG - printk(OSST_DEB_MSG "osst%d: Couldn't exec scsi cmd for IOCTL\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Couldn't exec scsi cmd for IOCTL\n", dev); #endif return ioctl_result; } + if (!ioctl_result) { /* SCSI command successful */ + STp->frame_seq_number = frame_seq_numbr; + STp->logical_blk_num = logical_blk_num; + } + os_bypass: #if DEBUG if (debugging) - printk(OSST_DEB_MSG "osst%d: IOCTL (%d) Result=%d\n", dev, cmd_in, ioctl_result); + printk(OSST_DEB_MSG "osst%d:D: IOCTL (%d) Result=%d\n", dev, cmd_in, ioctl_result); #endif - if (!ioctl_result) { /* SCSI command successful */ + if (!ioctl_result) { if (cmd_in == MTFSFM) { fileno--; @@ -3732,7 +4001,6 @@ STps->drv_block = blkno; STps->drv_file = fileno; STps->at_sm = at_sm; - STp->logical_blk_num = logical_blk_num; if (cmd_in == MTLOCK) STp->door_locked = ST_LOCKED_EXPLICIT; @@ -3752,7 +4020,7 @@ /* STp->rew_at_close = (MINOR(inode->i_rdev) & 0x80) == 0; FIXME */ for (i=0; i < ST_NBR_PARTITIONS; i++) { STp->ps[i].rw = ST_IDLE; - STp->ps[i].last_block_valid = FALSE; + STp->ps[i].last_block_valid = FALSE;/* FIXME - where else is this field maintained? */ } STp->partition = 0; } @@ -3826,7 +4094,7 @@ if (STp->in_use) { #if DEBUG - printk(OSST_DEB_MSG "osst%d: Device already in use.\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Device already in use.\n", dev); #endif return (-EBUSY); } @@ -3841,7 +4109,7 @@ if (mode != STp->current_mode) { #if DEBUG if (debugging) - printk(OSST_DEB_MSG "osst%d: Mode change from %d to %d.\n", + printk(OSST_DEB_MSG "osst%d:D: Mode change from %d to %d.\n", dev, STp->current_mode, mode); #endif new_session = TRUE; @@ -3863,7 +4131,7 @@ if (i >= osst_nbr_buffers) { STp->buffer = new_tape_buffer(FALSE, need_dma_buffer); if (STp->buffer == NULL) { - printk(KERN_WARNING "osst%d: Can't allocate tape buffer.\n", dev); + printk(KERN_WARNING "osst%d:W: Can't allocate tape buffer.\n", dev); retval = (-EBUSY); goto err_out; } @@ -3890,7 +4158,6 @@ STps->rw = ST_IDLE; } STp->ready = ST_READY; - STp->recover_count = 0; #if DEBUG STp->nbr_waits = STp->nbr_finished = 0; #endif @@ -3907,7 +4174,7 @@ (SRpnt->sr_sense_buffer[2] & 0x0f) == NOT_READY && SRpnt->sr_sense_buffer[12] == 4 ) { #if DEBUG - printk(OSST_DEB_MSG "osst%d: Unit not ready, cause %x\n", dev, SRpnt->sr_sense_buffer[13]); + printk(OSST_DEB_MSG "osst%d:D: Unit not ready, cause %x\n", dev, SRpnt->sr_sense_buffer[13]); #endif if (SRpnt->sr_sense_buffer[13] == 2) { /* initialize command required (LOAD) */ memset (cmd, 0, MAX_COMMAND_SIZE); @@ -3922,7 +4189,7 @@ if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 && (SRpnt->sr_sense_buffer[2] & 0x0f) == UNIT_ATTENTION) { /* New media? */ #if DEBUG - printk(OSST_DEB_MSG "osst%d: Unit wants attention\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Unit wants attention\n", dev); #endif STp->header_ok = 0; @@ -3944,7 +4211,7 @@ STp->nbr_partitions = 1; /* This guess will be updated later if necessary */ for (i=0; i < ST_NBR_PARTITIONS; i++) { STps = &(STp->ps[i]); - STps->rw = ST_IDLE; + STps->rw = ST_IDLE; /* FIXME - seems to be redundant... */ STps->eof = ST_NOEOF; STps->at_sm = 0; STps->last_block_valid = FALSE; @@ -3952,6 +4219,7 @@ STps->drv_file = 0 ; } new_session = TRUE; + STp->recover_count = 0; } /* * if we have valid headers from before, and the drive/tape seem untouched, @@ -3974,7 +4242,7 @@ STp->buffer->b_data[MODE_HEADER_LENGTH + 4] != 'N' || STp->buffer->b_data[MODE_HEADER_LENGTH + 5] != '4' ) { #if DEBUG - printk(OSST_DEB_MSG "osst%d: signature was changed to %c%c%c%c\n", dev, + printk(OSST_DEB_MSG "osst%d:D: Signature was changed to %c%c%c%c\n", dev, STp->buffer->b_data[MODE_HEADER_LENGTH + 2], STp->buffer->b_data[MODE_HEADER_LENGTH + 3], STp->buffer->b_data[MODE_HEADER_LENGTH + 4], @@ -3986,17 +4254,23 @@ if (STp->header_ok && i == osst_get_frame_position(STp, &SRpnt)) { if (STp->door_locked == ST_UNLOCKED) { if (osst_int_ioctl(STp, &SRpnt, MTLOCK, 0)) - printk(KERN_WARNING "osst%d: Can't lock drive door\n", dev); + printk(KERN_INFO "osst%d:I: Can't lock drive door\n", dev); else STp->door_locked = ST_LOCKED_AUTO; } + if (!STp->frame_in_buffer) { + STp->block_size = (STp->raw) ? OS_FRAME_SIZE : ( + (STm->default_blksize > 0) ? STm->default_blksize : OS_DATA_SIZE); + STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0; + } + STp->buffer->buffer_blocks = OS_DATA_SIZE / STp->block_size; STp->fast_open = TRUE; scsi_release_request(SRpnt); return 0; } #if DEBUG if (i != STp->first_frame_position) - printk(OSST_DEB_MSG "osst%d: tape position changed from %d to %d\n", + printk(OSST_DEB_MSG "osst%d:D: Tape position changed from %d to %d\n", dev, i, STp->first_frame_position); #endif STp->header_ok = 0; @@ -4020,8 +4294,8 @@ (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 2; (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 3; -#if 1 //DEBUG - printk(OSST_DEB_MSG "osst%i: Applying soft reset\n", dev); +#if DEBUG + printk(OSST_DEB_MSG "osst%d:D: Applying soft reset\n", dev); #endif SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE, STp->timeout, 0, TRUE); @@ -4058,7 +4332,7 @@ } if (osst_wait_ready(STp, &SRpnt, 15 * 60)) /* FIXME - not allowed with NOBLOCK */ - printk(KERN_WARNING "osst%i: Device did not become Ready in open\n",dev); + printk(KERN_INFO "osst%i:I: Device did not become Ready in open\n",dev); if ((STp->buffer)->syscall_result != 0) { if ((STp->device)->scsi_level >= SCSI_2 && @@ -4087,7 +4361,7 @@ if (OS_FRAME_SIZE > (STp->buffer)->buffer_size && !enlarge_buffer(STp->buffer, OS_FRAME_SIZE, STp->restr_dma)) { - printk(KERN_NOTICE "osst%d: Framesize %d too large for buffer.\n", dev, + printk(KERN_NOTICE "osst%d:A: Framesize %d too large for buffer.\n", dev, OS_FRAME_SIZE); retval = (-EIO); goto err_out; @@ -4099,22 +4373,26 @@ b_size += STp->buffer->sg[i++].length); STp->buffer->aux = (os_aux_t *) (STp->buffer->sg[i].address + OS_DATA_SIZE - b_size); #if DEBUG - printk(OSST_DEB_MSG "osst%d: b_data points to %p in segment 0 at %p\n", dev, + printk(OSST_DEB_MSG "osst%d:D: b_data points to %p in segment 0 at %p\n", dev, STp->buffer->b_data, STp->buffer->sg[0].address); - printk(OSST_DEB_MSG "osst%d: AUX points to %p in segment %d at %p\n", dev, + printk(OSST_DEB_MSG "osst%d:D: AUX points to %p in segment %d at %p\n", dev, STp->buffer->aux, i, STp->buffer->sg[i].address); #endif } else STp->buffer->aux = NULL; /* this had better never happen! */ - (STp->buffer)->buffer_blocks = 1; - (STp->buffer)->buffer_bytes = - (STp->buffer)->read_pointer = - STp->logical_blk_in_buffer = 0; + STp->block_size = (STp->raw) ? OS_FRAME_SIZE : ( + (STm->default_blksize > 0) ? STm->default_blksize : OS_DATA_SIZE); + STp->min_block = 512; + STp->max_block = OS_DATA_SIZE; + STp->buffer->buffer_blocks = OS_DATA_SIZE / STp->block_size; + STp->buffer->buffer_bytes = + STp->buffer->read_pointer = + STp->frame_in_buffer = 0; #if DEBUG if (debugging) - printk(OSST_DEB_MSG "osst%d: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n", + printk(OSST_DEB_MSG "osst%d:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n", dev, STp->block_size, OS_FRAME_SIZE, (STp->buffer)->buffer_size, (STp->buffer)->buffer_blocks); #endif @@ -4123,7 +4401,7 @@ STp->write_prot = 1; #if DEBUG if (debugging) - printk(OSST_DEB_MSG "osst%d: Write protected\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Write protected\n", dev); #endif if ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR) { retval = (-EROFS); @@ -4134,7 +4412,7 @@ if (new_session) { /* Change the drive parameters for the new mode */ #if DEBUG if (debugging) - printk(OSST_DEB_MSG "osst%d: New Session\n", dev); + printk(OSST_DEB_MSG "osst%d:D: New Session\n", dev); #endif STp->density_changed = STp->blksize_changed = FALSE; STp->compression_changed = FALSE; @@ -4145,7 +4423,7 @@ */ if (STp->door_locked == ST_UNLOCKED) { if (osst_int_ioctl(STp, &SRpnt, MTLOCK, 0)) - printk(KERN_WARNING "osst%d: Can't lock drive door\n", dev); + printk(KERN_INFO "osst%d:I: Can't lock drive door\n", dev); else STp->door_locked = ST_LOCKED_AUTO; } @@ -4197,18 +4475,17 @@ STps = &(STp->ps[STp->partition]); if ( STps->rw == ST_WRITING && !(STp->device)->was_reset) { - result = osst_flush_write_buffer(STp, &SRpnt, 1); + result = osst_flush_write_buffer(STp, &SRpnt); if (result != 0 && result != (-ENOSPC)) - goto out; + goto out; } - if ( STps->rw == ST_WRITING && !(STp->device)->was_reset) { #if DEBUG if (debugging) { - printk(OSST_DEB_MSG "osst%d: File length %ld bytes.\n", + printk(OSST_DEB_MSG "osst%d:D: File length %ld bytes.\n", dev, (long)(filp->f_pos)); - printk(OSST_DEB_MSG "osst%d: Async write waits %d, finished %d.\n", + printk(OSST_DEB_MSG "osst%d:D: Async write waits %d, finished %d.\n", dev, STp->nbr_waits, STp->nbr_finished); } #endif @@ -4229,7 +4506,7 @@ #if DEBUG if (debugging) - printk(OSST_DEB_MSG "osst%d: Buffer flushed, %d EOF(s) written\n", + printk(OSST_DEB_MSG "osst%d:D: Buffer flushed, %d EOF(s) written\n", dev, 1+STp->two_fm); #endif } @@ -4237,7 +4514,7 @@ STps = &(STp->ps[STp->partition]); if (!STm->sysv || STps->rw != ST_READING) { if (STp->can_bsr) - result = osst_flush_buffer(STp, &SRpnt, 0); + result = osst_flush_buffer(STp, &SRpnt, 0); /* this is the default path */ else if (STps->eof == ST_FM_HIT) { result = cross_eof(STp, &SRpnt, FALSE); if (result) { @@ -4263,12 +4540,24 @@ out: if (STp->rew_at_close) { result2 = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos); - STps->drv_file = STps->drv_block = STp->logical_blk_num = 0; - if (result == 0) + STps->drv_file = STps->drv_block = STp->frame_seq_number = STp->logical_blk_num = 0; + if (result == 0 && result2 < 0) result = result2; } if (SRpnt) scsi_release_request(SRpnt); + if (STp->recover_count) { + printk(KERN_INFO "osst%d:I: %d recovered errors in", dev, STp->recover_count); + if (STp->write_count) + printk(" %d frames written", STp->write_count); + if (STp->read_count) + printk(" %d frames read", STp->read_count); + printk("\n"); + STp->recover_count = 0; + } + STp->write_count = 0; + STp->read_count = 0; + return result; } @@ -4322,7 +4611,7 @@ #if DEBUG if (debugging && !STp->in_use) { - printk(OSST_DEB_MSG "osst%d: Incorrect device.\n", dev); + printk(OSST_DEB_MSG "osst%d:D: Incorrect device.\n", dev); retval = (-EIO); goto out; } @@ -4359,7 +4648,7 @@ } if (mtc.mt_op == MTSETDRVBUFFER && !capable(CAP_SYS_ADMIN)) { - printk(KERN_WARNING "osst%d: MTSETDRVBUFFER only allowed for root.\n", dev); + printk(KERN_WARNING "osst%d:W: MTSETDRVBUFFER only allowed for root.\n", dev); retval = (-EPERM); goto out; } @@ -4419,7 +4708,7 @@ if (STp->door_locked != ST_UNLOCKED && STp->door_locked != ST_LOCK_FAILS) { if (osst_int_ioctl(STp, &SRpnt, MTLOCK, 0)) { - printk(KERN_NOTICE "osst%d: Could not relock door after bus reset.\n", + printk(KERN_NOTICE "osst%d:I: Could not relock door after bus reset.\n", dev); STp->door_locked = ST_UNLOCKED; } @@ -4479,7 +4768,7 @@ } if (mtc.mt_op == MTSEEK) { - i = osst_seek_frame(STp, &SRpnt, mtc.mt_count); + i = osst_seek_sector(STp, &SRpnt, mtc.mt_count); if (!STp->can_partitions) STp->ps[0].rw = ST_IDLE; retval = i; @@ -4584,7 +4873,7 @@ retval = (-EINVAL); goto out; } - blk = osst_get_frame_position(STp, &SRpnt); + blk = osst_get_sector(STp, &SRpnt); if (blk < 0) { retval = blk; goto out; @@ -4687,7 +4976,7 @@ } } if (!tb) { - printk(KERN_NOTICE "osst: Can't allocate new tape buffer (nbr %d).\n", + printk(KERN_NOTICE "osst :I: Can't allocate new tape buffer (nbr %d).\n", osst_nbr_buffers); return NULL; } @@ -4697,10 +4986,10 @@ #if DEBUG if (debugging) { printk(OSST_DEB_MSG - "osst: Allocated tape buffer %d (%d bytes, %d segments, dma: %d, a: %p).\n", + "osst :D: Allocated tape buffer %d (%d bytes, %d segments, dma: %d, a: %p).\n", osst_nbr_buffers, got, tb->sg_segs, need_dma, tb->b_data); printk(OSST_DEB_MSG - "osst: segment sizes: first %d, last %d bytes.\n", + "osst :D: segment sizes: first %d, last %d bytes.\n", tb->sg[0].length, tb->sg[segs-1].length); } #endif @@ -4745,7 +5034,7 @@ order--; continue; } - printk(KERN_NOTICE "osst: Failed to enlarge buffer to %d bytes.\n", + printk(KERN_WARNING "osst :W: Failed to enlarge buffer to %d bytes.\n", new_size); #if DEBUG STbuffer->buffer_size = got; @@ -4764,10 +5053,10 @@ if (debugging) { for (nbr=0; osst_buffers[nbr] != STbuffer && nbr < osst_nbr_buffers; nbr++); printk(OSST_DEB_MSG - "osst: Expanded tape buffer %d (%d bytes, %d->%d segments, dma: %d, a: %p).\n", + "osst :D: Expanded tape buffer %d (%d bytes, %d->%d segments, dma: %d, a: %p).\n", nbr, got, STbuffer->orig_sg_segs, STbuffer->sg_segs, need_dma, STbuffer->b_data); printk(OSST_DEB_MSG - "osst: segment sizes: first %d, last %d bytes.\n", + "osst :D: segment sizes: first %d, last %d bytes.\n", STbuffer->sg[0].length, STbuffer->sg[segs-1].length); } #endif @@ -4792,7 +5081,7 @@ } #if DEBUG if (debugging && STbuffer->orig_sg_segs < STbuffer->sg_segs) - printk(OSST_DEB_MSG "osst: Buffer at %p normalized to %d bytes (segs %d).\n", + printk(OSST_DEB_MSG "osst :D: Buffer at %p normalized to %d bytes (segs %d).\n", STbuffer->b_data, STbuffer->buffer_size, STbuffer->sg_segs); #endif STbuffer->sg_segs = STbuffer->orig_sg_segs; @@ -4809,7 +5098,7 @@ i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++) offset -= st_bp->sg[i].length; if (i == st_bp->sg_segs) { /* Should never happen */ - printk(KERN_WARNING "osst: Append_to_buffer offset overflow.\n"); + printk(KERN_WARNING "osst :A: Append_to_buffer offset overflow.\n"); return (-EIO); } for ( ; i < st_bp->sg_segs && do_count > 0; i++) { @@ -4824,7 +5113,7 @@ offset = 0; } if (do_count) { /* Should never happen */ - printk(KERN_WARNING "osst: Append_to_buffer overflow (left %d).\n", + printk(KERN_WARNING "osst :A: Append_to_buffer overflow (left %d).\n", do_count); return (-EIO); } @@ -4842,7 +5131,7 @@ i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++) offset -= st_bp->sg[i].length; if (i == st_bp->sg_segs) { /* Should never happen */ - printk(KERN_WARNING "osst: From_buffer offset overflow.\n"); + printk(KERN_WARNING "osst :A: From_buffer offset overflow.\n"); return (-EIO); } for ( ; i < st_bp->sg_segs && do_count > 0; i++) { @@ -4858,7 +5147,7 @@ offset = 0; } if (do_count) { /* Should never happen */ - printk(KERN_WARNING "osst: From_buffer overflow (left %d).\n", do_count); + printk(KERN_WARNING "osst :A: From_buffer overflow (left %d).\n", do_count); return (-EIO); } return 0; @@ -4874,10 +5163,10 @@ i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++) offset -= st_bp->sg[i].length; if (i == st_bp->sg_segs) { /* Should never happen */ - printk(KERN_WARNING "osst: Zero_buffer offset overflow.\n"); + printk(KERN_WARNING "osst :A: Zero_buffer offset overflow.\n"); return (-EIO); } - for (do_count = OS_DATA_SIZE - st_bp->read_pointer; + for (do_count = OS_DATA_SIZE - st_bp->buffer_bytes; i < st_bp->sg_segs && do_count > 0; i++) { cnt = st_bp->sg[i].length - offset < do_count ? st_bp->sg[i].length - offset : do_count ; @@ -4886,13 +5175,13 @@ offset = 0; } if (do_count) { /* Should never happen */ - printk(KERN_WARNING "osst: Zero_buffer overflow (left %d).\n", do_count); + printk(KERN_WARNING "osst :A: Zero_buffer overflow (left %d).\n", do_count); return (-EIO); } return 0; } -/* Copy a osst 32K block of memory into the buffer. +/* Copy a osst 32K chunk of memory into the buffer. Returns zero (success) or negative error code. */ static int osst_copy_to_buffer(OSST_buffer *st_bp, unsigned char *ptr) { @@ -4906,14 +5195,14 @@ ptr += cnt; } if (do_count || i != st_bp->sg_segs-1) { /* Should never happen */ - printk(KERN_WARNING "osst: Copy_to_buffer overflow (left %d at sg %d).\n", + printk(KERN_WARNING "osst :A: Copy_to_buffer overflow (left %d at sg %d).\n", do_count, i); return (-EIO); } return 0; } -/* Copy a osst 32K block of memory from the buffer. +/* Copy a osst 32K chunk of memory from the buffer. Returns zero (success) or negative error code. */ static int osst_copy_from_buffer(OSST_buffer *st_bp, unsigned char *ptr) { @@ -4927,7 +5216,7 @@ ptr += cnt; } if (do_count || i != st_bp->sg_segs-1) { /* Should never happen */ - printk(KERN_WARNING "osst: Copy_from_buffer overflow (left %d at sg %d).\n", + printk(KERN_WARNING "osst :A: Copy_from_buffer overflow (left %d at sg %d).\n", do_count, i); return (-EIO); } @@ -4949,9 +5238,12 @@ osst_max_buffers = max_buffers; if (max_sg_segs >= OSST_FIRST_SG) osst_max_sg_segs = max_sg_segs; - printk(KERN_INFO "osst: bufsize %d, wrt %d, max buffers %d, s/g segs %d.\n", +#if DEBUG + printk(OSST_DEB_MSG "osst :D: bufsize %d, wrt %d, max buffers %d, s/g segs %d.\n", osst_buffer_size, osst_write_threshold, osst_max_buffers, osst_max_sg_segs); -//printk(OSST_DEB_MSG "osst: sizeof(header) = %d (%s)\n",sizeof(os_header_t),sizeof(os_header_t)==OS_DATA_SIZE?"ok":"error"); +//printk(OSST_DEB_MSG "osst :D: sizeof(header) = %d (%s)\n", +// sizeof(os_header_t),sizeof(os_header_t)==OS_DATA_SIZE?"ok":"error"); +#endif } #ifndef MODULE @@ -4980,7 +5272,7 @@ } } if (i >= sizeof(parms) / sizeof(struct osst_dev_parm)) - printk(KERN_WARNING "osst: illegal parameter in '%s'\n", + printk(KERN_INFO "osst :I: Illegal parameter in '%s'\n", stp); stp = strchr(stp, ','); if (stp) @@ -5038,7 +5330,7 @@ OS_Scsi_Tape * tpnt; ST_mode * STm; ST_partstat * STps; - int i; + int i, dev; #ifdef CONFIG_DEVFS_FS int mode; #endif @@ -5059,16 +5351,17 @@ tpnt = (OS_Scsi_Tape *)kmalloc(sizeof(OS_Scsi_Tape), GFP_ATOMIC); if (tpnt == NULL) { SDp->attached--; - printk(KERN_ERR "osst: Can't allocate device descriptor.\n"); + printk(KERN_WARNING "osst :W: Can't allocate device descriptor.\n"); return 1; } memset(tpnt, 0, sizeof(OS_Scsi_Tape)); os_scsi_tapes[i] = tpnt; + dev = i; tpnt->capacity = 0xfffff; /* allocate a buffer for this device */ if (!new_tape_buffer(TRUE, TRUE)) - printk(KERN_ERR "osst: Unable to allocate a tape buffer.\n"); + printk(KERN_ERR "osst :W: Unable to allocate a tape buffer.\n"); #ifdef CONFIG_DEVFS_FS for (mode = 0; mode < ST_NBR_MODES; ++mode) { @@ -5131,17 +5424,12 @@ tpnt->long_timeout = OSST_LONG_TIMEOUT; /* Recognize OnStream tapes */ - printk ("osst%i: Tape driver with OnStream support osst %s\nosst%i: %s\n", - i, osst_version, i, cvsid); /* We don't need to test for OnStream, as this has been done in detect () */ tpnt->os_fw_rev = osst_parse_firmware_rev (SDp->rev); -#if DEBUG - printk ("osst%i: OnStream tape drive recognized, Model %s\n", i, SDp->model); -#endif tpnt->omit_blklims = 1; tpnt->poll = (strncmp(SDp->model, "DI-", 3) == 0) || OSST_FW_NEED_POLL(tpnt->os_fw_rev,SDp); - tpnt->logical_blk_in_buffer = 0; + tpnt->frame_in_buffer = 0; tpnt->header_ok = 0; tpnt->linux_media = 0; tpnt->header_cache = NULL; @@ -5155,7 +5443,7 @@ STm->do_buffer_writes = OSST_BUFFER_WRITES; STm->do_read_ahead = OSST_READ_AHEAD; STm->default_compression = ST_DONT_TOUCH; - STm->default_blksize = 32 * ST_KILOBYTE; /* No forced size */ + STm->default_blksize = 512; STm->default_density = (-1); /* No forced density */ } @@ -5175,6 +5463,11 @@ init_MUTEX(&tpnt->lock); osst_template.nr_dev++; + + printk(KERN_INFO + "osst :I: Attached OnStream %.5s tape at scsi%d, channel %d, id %d, lun %d as osst%d\n", + SDp->model, SDp->host->host_no, SDp->channel, SDp->id, SDp->lun, dev); + return 0; }; @@ -5183,10 +5476,7 @@ if (SDp->type != TYPE_TAPE) return 0; if ( ! osst_supports(SDp) ) return 0; - printk(KERN_WARNING - "Detected OnStream scsi tape osst%d at scsi%d, channel %d, id %d, lun %d\n", - osst_template.dev_noticed++, - SDp->host->host_no, SDp->channel, SDp->id, SDp->lun); + osst_template.dev_noticed++; return 1; } @@ -5205,7 +5495,7 @@ #else if (register_chrdev(MAJOR_NR,"osst",&osst_fops)) { #endif - printk(KERN_ERR "osst: Unable to get major %d for OnStream tapes\n",MAJOR_NR); + printk(KERN_ERR "osst :W: Unable to get major %d for OnStream tapes\n",MAJOR_NR); return 1; } osst_registered++; @@ -5214,12 +5504,12 @@ if (os_scsi_tapes) return 0; osst_template.dev_max = OSST_MAX_TAPES; if (osst_template.dev_max > 128 / ST_NBR_MODES) - printk(KERN_INFO "osst: Only %d tapes accessible.\n", 128 / ST_NBR_MODES); + printk(KERN_INFO "osst :I: Only %d tapes accessible.\n", 128 / ST_NBR_MODES); os_scsi_tapes = (OS_Scsi_Tape **)kmalloc(osst_template.dev_max * sizeof(OS_Scsi_Tape *), GFP_ATOMIC); if (os_scsi_tapes == NULL) { - printk(KERN_ERR "osst: Unable to allocate array for OnStream SCSI tapes.\n"); + printk(KERN_ERR "osst :W: Unable to allocate array for OnStream SCSI tapes.\n"); #ifdef CONFIG_DEVFS_FS devfs_unregister_chrdev(MAJOR_NR, "osst"); #else @@ -5235,7 +5525,7 @@ (OSST_buffer **)kmalloc(osst_template.dev_max * sizeof(OSST_buffer *), GFP_ATOMIC); if (osst_buffers == NULL) { - printk(KERN_ERR "osst: Unable to allocate tape buffer pointers.\n"); + printk(KERN_ERR "osst :W: Unable to allocate tape buffer pointers.\n"); #ifdef CONFIG_DEVFS_FS devfs_unregister_chrdev(MAJOR_NR, "osst"); #else @@ -5246,8 +5536,10 @@ } osst_nbr_buffers = 0; + printk(KERN_INFO "osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version, cvsid); + #if DEBUG - printk(OSST_DEB_MSG "osst: Buffer size %d bytes, write threshold %d bytes.\n", + printk(OSST_DEB_MSG "osst :D: Buffer size %d bytes, write threshold %d bytes.\n", osst_buffer_size, osst_write_threshold); #endif return 0; @@ -5287,9 +5579,9 @@ static int __init init_osst(void) { - validate_options(); - osst_template.module = THIS_MODULE; - return scsi_register_module(MODULE_SCSI_DEV, &osst_template); + validate_options(); + osst_template.module = THIS_MODULE; + return scsi_register_module(MODULE_SCSI_DEV, &osst_template); } static void __exit exit_osst (void) @@ -5325,7 +5617,7 @@ } } osst_template.dev_max = 0; - printk(KERN_INFO "osst: Unloaded.\n"); + printk(KERN_INFO "osst :I: Unloaded.\n"); } module_init(init_osst); diff -u --recursive --new-file v2.4.5/linux/drivers/scsi/osst.h linux/drivers/scsi/osst.h --- v2.4.5/linux/drivers/scsi/osst.h Sat Dec 30 11:23:14 2000 +++ linux/drivers/scsi/osst.h Mon Jun 11 19:15:27 2001 @@ -1,5 +1,5 @@ /* - * $Header: /home/cvsroot/Driver/osst.h,v 1.9 2000/10/08 03:09:43 riede Exp $ + * $Header: /home/cvsroot/Driver/osst.h,v 1.11 2001/01/26 01:54:49 riede Exp $ */ #include @@ -440,7 +440,8 @@ * Linux specific fields: */ __u32 next_mark_ppos; /* when known, points to next marker */ - __u8 linux_specific[28]; + __u32 last_mark_lbn; /* storing log_blk_num of last mark is extends ADR spec */ + __u8 linux_specific[24]; __u8 reserved_256_511[256]; } os_aux_t; @@ -581,6 +582,8 @@ int min_block; int max_block; int recover_count; /* from tape opening */ + int write_count; + int read_count; int recover_erreg; /* from last status call */ /* * OnStream specific data @@ -588,8 +591,9 @@ int os_fw_rev; /* the firmware revision * 10000 */ unsigned char raw; /* flag OnStream raw access (32.5KB block size) */ unsigned char poll; /* flag that this drive needs polling (IDE|firmware) */ - unsigned char logical_blk_in_buffer; /* flag that the block as per logical_blk_num + unsigned char frame_in_buffer; /* flag that the frame as per frame_seq_number * has been read into STp->buffer and is valid */ + int frame_seq_number; /* logical frame number */ int logical_blk_num; /* logical block number */ unsigned first_frame_position; /* physical frame to be transfered to/from host */ unsigned last_frame_position; /* physical frame to be transferd to/from tape */ @@ -607,6 +611,7 @@ int filemark_cnt; int first_mark_ppos; int last_mark_ppos; + int last_mark_lbn; /* storing log_blk_num of last mark is extends ADR spec */ int first_data_ppos; int eod_frame_ppos; int eod_frame_lfa; diff -u --recursive --new-file v2.4.5/linux/drivers/scsi/osst_options.h linux/drivers/scsi/osst_options.h --- v2.4.5/linux/drivers/scsi/osst_options.h Sat Dec 30 11:23:14 2000 +++ linux/drivers/scsi/osst_options.h Mon Jun 11 19:15:27 2001 @@ -8,7 +8,7 @@ Changed (and renamed) for OnStream SCSI drives garloff@suse.de 2000-06-21 - $Header: /home/cvsroot/Driver/osst_options.h,v 1.4 2000/06/26 01:44:01 riede Exp $ + $Header: /home/cvsroot/Driver/osst_options.h,v 1.5 2001/01/07 22:19:15 riede Exp $ */ #ifndef _OSST_OPTIONS_H @@ -24,7 +24,7 @@ because of buffered reads. Should be set to zero to support also drives that can't space backwards over records. NOTE: The tape will be spaced backwards over an "accidentally" crossed filemark in any case. */ -#define OSST_IN_FILE_POS 0 +#define OSST_IN_FILE_POS 1 /* The tape driver buffer size in kilobytes. */ /* Don't change, as this is the HW blocksize */ @@ -33,7 +33,13 @@ /* The number of kilobytes of data in the buffer that triggers an asynchronous write in fixed block mode. See also OSST_ASYNC_WRITES below. */ -#define OSST_WRITE_THRESHOLD_BLOCKS 30 +#define OSST_WRITE_THRESHOLD_BLOCKS 32 + +/* OSST_EOM_RESERVE defines the number of frames are kept in reserve for + * * write error recovery when writing near end of medium. ENOSPC is returned + * * when write() is called and the tape write position is within this number + * * of blocks from the tape capacity. */ +#define OSST_EOM_RESERVE 300 /* The maximum number of tape buffers the driver allocates. The number is also constrained by the number of drives detected. Determines the @@ -64,7 +70,7 @@ /* If OSST_BUFFER_WRITES is non-zero, writes in fixed block mode are buffered until the driver buffer is full or asynchronous write is - triggered. May make detection of End-Of-Medium early enough fail. */ + triggered. */ #define OSST_BUFFER_WRITES 1 /* If OSST_ASYNC_WRITES is non-zero, the SCSI write command may be started diff -u --recursive --new-file v2.4.5/linux/drivers/scsi/qla1280.c linux/drivers/scsi/qla1280.c --- v2.4.5/linux/drivers/scsi/qla1280.c Fri Apr 27 13:59:19 2001 +++ linux/drivers/scsi/qla1280.c Wed Jun 27 17:10:55 2001 @@ -1528,6 +1528,7 @@ if(test_and_set_bit(QLA1280_IN_ISR_BIT, &ha->flags)) { COMTRACE('X') + spin_unlock_irqrestore(&io_request_lock, cpu_flags); return; } ha->isr_count++; diff -u --recursive --new-file v2.4.5/linux/drivers/scsi/qlogicisp.c linux/drivers/scsi/qlogicisp.c --- v2.4.5/linux/drivers/scsi/qlogicisp.c Fri Apr 27 13:59:19 2001 +++ linux/drivers/scsi/qlogicisp.c Wed Jun 20 11:10:27 2001 @@ -62,8 +62,6 @@ #define DEFAULT_LOOP_COUNT 1000000 -#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) - /* End Configuration section *************************************************/ #include diff -u --recursive --new-file v2.4.5/linux/drivers/scsi/qlogicpti.c linux/drivers/scsi/qlogicpti.c --- v2.4.5/linux/drivers/scsi/qlogicpti.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/scsi/qlogicpti.c Mon Jun 11 19:15:27 2001 @@ -819,7 +819,8 @@ /* Is this a red snapper? */ if (strcmp(sdev->prom_name, "ptisp") && strcmp(sdev->prom_name, "PTI,ptisp") && - strcmp(sdev->prom_name, "QLGC,isp")) + strcmp(sdev->prom_name, "QLGC,isp") && + strcmp(sdev->prom_name, "SUNW,isp")) continue; /* Sometimes Antares cards come up not completely diff -u --recursive --new-file v2.4.5/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c --- v2.4.5/linux/drivers/scsi/scsi.c Thu May 24 15:34:14 2001 +++ linux/drivers/scsi/scsi.c Tue Jun 12 11:06:54 2001 @@ -2356,8 +2356,8 @@ /* The rest of these are not yet implemented. */ case MODULE_SCSI_CONST: case MODULE_SCSI_IOCTL: - break; default: + break; } return; } diff -u --recursive --new-file v2.4.5/linux/drivers/scsi/scsi_ioctl.c linux/drivers/scsi/scsi_ioctl.c --- v2.4.5/linux/drivers/scsi/scsi_ioctl.c Fri Apr 27 13:59:19 2001 +++ linux/drivers/scsi/scsi_ioctl.c Mon Jun 11 19:15:27 2001 @@ -312,17 +312,17 @@ /* * If there was an error condition, pass the info back to the user. */ + result = SRpnt->sr_result; if (SRpnt->sr_result) { int sb_len = sizeof(SRpnt->sr_sense_buffer); sb_len = (sb_len > OMAX_SB_LEN) ? OMAX_SB_LEN : sb_len; if (copy_to_user(cmd_in, SRpnt->sr_sense_buffer, sb_len)) - return -EFAULT; - } else + result = -EFAULT; + } else { if (copy_to_user(cmd_in, buf, outlen)) - return -EFAULT; - - result = SRpnt->sr_result; + result = -EFAULT; + } SDpnt = SRpnt->sr_device; scsi_release_request(SRpnt); diff -u --recursive --new-file v2.4.5/linux/drivers/scsi/scsi_proc.c linux/drivers/scsi/scsi_proc.c --- v2.4.5/linux/drivers/scsi/scsi_proc.c Sat May 19 17:43:06 2001 +++ linux/drivers/scsi/scsi_proc.c Wed Jun 27 17:10:55 2001 @@ -99,6 +99,9 @@ char * page; char *start; + if (hpnt->hostt->proc_info == NULL) + ret = -ENOSYS; + if (count > PROC_BLOCK_SIZE) return -EOVERFLOW; @@ -110,11 +113,9 @@ return -EFAULT; } - if (hpnt->hostt->proc_info == NULL) - ret = -ENOSYS; - else - ret = hpnt->hostt->proc_info(page, &start, 0, count, - hpnt->host_no, 1); + ret = hpnt->hostt->proc_info(page, &start, 0, count, + hpnt->host_no, 1); + free_page((ulong) page); return(ret); } @@ -125,6 +126,10 @@ char name[10]; /* see scsi_unregister_host() */ tpnt->proc_dir = proc_mkdir(tpnt->proc_name, proc_scsi); + if (!tpnt->proc_dir) { + printk(KERN_ERR "Unable to proc_mkdir in scsi.c/build_proc_dir_entries"); + return; + } tpnt->proc_dir->owner = tpnt->module; hpnt = scsi_hostlist; diff -u --recursive --new-file v2.4.5/linux/drivers/scsi/scsi_scan.c linux/drivers/scsi/scsi_scan.c --- v2.4.5/linux/drivers/scsi/scsi_scan.c Sun Apr 8 10:10:01 2001 +++ linux/drivers/scsi/scsi_scan.c Tue Jun 12 11:17:17 2001 @@ -328,8 +328,8 @@ } /* - * We need to increment the counter for this one device so we can track when - * things are quiet. + * We need to increment the counter for this one device so we can track + * when things are quiet. */ if (hardcoded == 1) { Scsi_Device *oldSDpnt = SDpnt; @@ -485,8 +485,8 @@ SDpnt->type = -1; /* - * Assume that the device will have handshaking problems, and then fix this - * field later if it turns out it doesn't + * Assume that the device will have handshaking problems, and then fix + * this field later if it turns out it doesn't */ SDpnt->borken = 1; SDpnt->was_reset = 0; @@ -524,9 +524,21 @@ SCSI_LOG_SCAN_BUS(3, printk("scsi: INQUIRY %s with code 0x%x\n", SRpnt->sr_result ? "failed" : "successful", SRpnt->sr_result)); + /* + * Now that we don't do TEST_UNIT_READY anymore, we must be prepared + * for media change conditions here, so cannot require zero result. + */ if (SRpnt->sr_result) { - scsi_release_request(SRpnt); - return 0; /* assume no peripheral if any sort of error */ + if ((driver_byte(SRpnt->sr_result) & DRIVER_SENSE) != 0 && + (SRpnt->sr_sense_buffer[2] & 0xf) == UNIT_ATTENTION && + SRpnt->sr_sense_buffer[12] == 0x28 && + SRpnt->sr_sense_buffer[13] == 0) { + /* not-ready to ready transition - good */ + } else { + /* assume no peripheral if any other sort of error */ + scsi_release_request(SRpnt); + return 0; + } } /* diff -u --recursive --new-file v2.4.5/linux/drivers/scsi/scsi_syms.c linux/drivers/scsi/scsi_syms.c --- v2.4.5/linux/drivers/scsi/scsi_syms.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/scsi/scsi_syms.c Mon Jul 2 15:27:56 2001 @@ -91,3 +91,10 @@ EXPORT_SYMBOL(scsi_devicelist); EXPORT_SYMBOL(scsi_device_types); +/* + * Externalize timers so that HBAs can safely start/restart commands. + */ +extern void scsi_add_timer(Scsi_Cmnd *, int, void ((*) (Scsi_Cmnd *))); +extern int scsi_delete_timer(Scsi_Cmnd *); +EXPORT_SYMBOL(scsi_add_timer); +EXPORT_SYMBOL(scsi_delete_timer); diff -u --recursive --new-file v2.4.5/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c --- v2.4.5/linux/drivers/scsi/sd.c Fri May 25 09:54:50 2001 +++ linux/drivers/scsi/sd.c Tue Jun 12 11:17:17 2001 @@ -861,8 +861,7 @@ driver_byte(the_result) ); if (driver_byte(the_result) & DRIVER_SENSE) - printk("%s : extended sense code = %1x \n", - nbuff, SRpnt->sr_sense_buffer[2] & 0xf); + print_req_sense("sd", SRpnt); else printk("%s : sense not available. \n", nbuff); diff -u --recursive --new-file v2.4.5/linux/drivers/scsi/sym53c416.c linux/drivers/scsi/sym53c416.c --- v2.4.5/linux/drivers/scsi/sym53c416.c Tue Mar 6 19:44:37 2001 +++ linux/drivers/scsi/sym53c416.c Wed Jun 27 17:10:55 2001 @@ -6,6 +6,9 @@ * Changes : * * Marcelo Tosatti : Added io_request_lock locking + * Alan Cox : Cleaned up code formatting + * Fixed an irq locking bug + * Added ISAPnP support * * LILO command line usage: sym53c416=[,] * @@ -36,12 +39,13 @@ #include #include #include +#include #include "scsi.h" #include "hosts.h" #include "sd.h" #include "sym53c416.h" -#define VERSION_STRING "Version 1.0.0" +#define VERSION_STRING "Version 1.0.0-ac" #define TC_LOW 0x00 /* Transfer counter low */ #define TC_MID 0x01 /* Transfer counter mid */ @@ -203,24 +207,24 @@ #define MAXHOSTS 4 enum phases - { - idle, - data_out, - data_in, - command_ph, - status_ph, - message_out, - message_in - }; +{ + idle, + data_out, + data_in, + command_ph, + status_ph, + message_out, + message_in +}; typedef struct - { - int base; - int irq; - int scsi_id; - } host; +{ + int base; + int irq; + int scsi_id; +} host; -host hosts[MAXHOSTS] = { +static host hosts[MAXHOSTS] = { {0, 0, SYM53C416_SCSI_ID}, {0, 0, SYM53C416_SCSI_ID}, {0, 0, SYM53C416_SCSI_ID}, @@ -228,579 +232,616 @@ }; static int host_index = 0; - static char info[120]; - static Scsi_Cmnd *current_command = NULL; +static int fastpio = 1; -int fastpio = 1; - -int probeaddrs[] = {0x200, 0x220, 0x240, 0}; +static int probeaddrs[] = {0x200, 0x220, 0x240, 0}; static void sym53c416_set_transfer_counter(int base, unsigned int len) - { - /* Program Transfer Counter */ - outb(len & 0x0000FF, base + TC_LOW); - outb((len & 0x00FF00) >> 8, base + TC_MID); - outb((len & 0xFF0000) >> 16, base + TC_HIGH); - } +{ + /* Program Transfer Counter */ + outb(len & 0x0000FF, base + TC_LOW); + outb((len & 0x00FF00) >> 8, base + TC_MID); + outb((len & 0xFF0000) >> 16, base + TC_HIGH); +} /* Returns the number of bytes read */ static __inline__ unsigned int sym53c416_read(int base, unsigned char *buffer, unsigned int len) - { - unsigned int orig_len = len; - unsigned long flags = 0; - unsigned int bytes_left; - int i; - int timeout = READ_TIMEOUT; - - /* Do transfer */ - save_flags(flags); - cli(); - while(len && timeout) - { - bytes_left = inb(base + PIO_FIFO_CNT); /* Number of bytes in the PIO FIFO */ - if(fastpio && bytes_left > 3) - { - insl(base + PIO_FIFO_1, buffer, bytes_left >> 2); - buffer += bytes_left & 0xFC; - len -= bytes_left & 0xFC; - } - else if(bytes_left > 0) - { - len -= bytes_left; - for(; bytes_left > 0; bytes_left--) - *(buffer++) = inb(base + PIO_FIFO_1); - } - else - { - i = jiffies + timeout; - restore_flags(flags); - while(jiffies < i && (inb(base + PIO_INT_REG) & EMPTY) && timeout) - if(inb(base + PIO_INT_REG) & SCI) - timeout = 0; - save_flags(flags); - cli(); - if(inb(base + PIO_INT_REG) & EMPTY) - timeout = 0; - } - } - restore_flags(flags); - return orig_len - len; - } +{ + unsigned int orig_len = len; + unsigned long flags = 0; + unsigned int bytes_left; + int i; + int timeout = READ_TIMEOUT; + + /* Do transfer */ + save_flags(flags); + cli(); + while(len && timeout) + { + bytes_left = inb(base + PIO_FIFO_CNT); /* Number of bytes in the PIO FIFO */ + if(fastpio && bytes_left > 3) + { + insl(base + PIO_FIFO_1, buffer, bytes_left >> 2); + buffer += bytes_left & 0xFC; + len -= bytes_left & 0xFC; + } + else if(bytes_left > 0) + { + len -= bytes_left; + for(; bytes_left > 0; bytes_left--) + *(buffer++) = inb(base + PIO_FIFO_1); + } + else + { + i = jiffies + timeout; + restore_flags(flags); + while(jiffies < i && (inb(base + PIO_INT_REG) & EMPTY) && timeout) + if(inb(base + PIO_INT_REG) & SCI) + timeout = 0; + save_flags(flags); + cli(); + if(inb(base + PIO_INT_REG) & EMPTY) + timeout = 0; + } + } + restore_flags(flags); + return orig_len - len; +} /* Returns the number of bytes written */ static __inline__ unsigned int sym53c416_write(int base, unsigned char *buffer, unsigned int len) - { - unsigned int orig_len = len; - unsigned long flags = 0; - unsigned int bufferfree; - unsigned int i; - unsigned int timeout = WRITE_TIMEOUT; - - /* Do transfer */ - save_flags(flags); - cli(); - while(len && timeout) - { - bufferfree = PIO_SIZE - inb(base + PIO_FIFO_CNT); - if(bufferfree > len) - bufferfree = len; - if(fastpio && bufferfree > 3) - { - outsl(base + PIO_FIFO_1, buffer, bufferfree >> 2); - buffer += bufferfree & 0xFC; - len -= bufferfree & 0xFC; - } - else if(bufferfree > 0) - { - len -= bufferfree; - for(; bufferfree > 0; bufferfree--) - outb(*(buffer++), base + PIO_FIFO_1); - } - else - { - i = jiffies + timeout; - restore_flags(flags); - while(jiffies < i && (inb(base + PIO_INT_REG) & FULL) && timeout) - ; - save_flags(flags); - cli(); - if(inb(base + PIO_INT_REG) & FULL) - timeout = 0; - } - } - restore_flags(flags); - return orig_len - len; - } +{ + unsigned int orig_len = len; + unsigned long flags = 0; + unsigned int bufferfree; + unsigned int i; + unsigned int timeout = WRITE_TIMEOUT; + + /* Do transfer */ + save_flags(flags); + cli(); + while(len && timeout) + { + bufferfree = PIO_SIZE - inb(base + PIO_FIFO_CNT); + if(bufferfree > len) + bufferfree = len; + if(fastpio && bufferfree > 3) + { + outsl(base + PIO_FIFO_1, buffer, bufferfree >> 2); + buffer += bufferfree & 0xFC; + len -= bufferfree & 0xFC; + } + else if(bufferfree > 0) + { + len -= bufferfree; + for(; bufferfree > 0; bufferfree--) + outb(*(buffer++), base + PIO_FIFO_1); + } + else + { + i = jiffies + timeout; + restore_flags(flags); + while(jiffies < i && (inb(base + PIO_INT_REG) & FULL) && timeout) + ; + save_flags(flags); + cli(); + if(inb(base + PIO_INT_REG) & FULL) + timeout = 0; + } + } + restore_flags(flags); + return orig_len - len; +} static void sym53c416_intr_handle(int irq, void *dev_id, struct pt_regs *regs) - { - int base = 0; - int i; - unsigned long flags = 0; - unsigned char status_reg, pio_int_reg, int_reg; - struct scatterlist *sglist; - unsigned int sgcount; - unsigned int tot_trans = 0; - - /* We search the base address of the host adapter which caused the interrupt */ - for(i = 0; i < host_index && !base; i++) - if(irq == hosts[i].irq) - base = hosts[i].base; - /* If no adapter found, we cannot handle the interrupt. Leave a message */ - /* and continue. This should never happen... */ - if(!base) - { - printk("sym53c416: No host adapter defined for interrupt %d\n", irq); - return; - } - /* Now we have the base address and we can start handling the interrupt */ - save_flags(flags); - cli(); - status_reg = inb(base + STATUS_REG); - pio_int_reg = inb(base + PIO_INT_REG); - int_reg = inb(base + INT_REG); - restore_flags(flags); - - /* First, we handle error conditions */ - if(int_reg & SCI) /* SCSI Reset */ - { - printk("sym53c416: Warning: Reset received\n"); - current_command->SCp.phase = idle; - current_command->result = DID_RESET << 16; - spin_lock_irqsave(&io_request_lock, flags); - current_command->scsi_done(current_command); - spin_unlock_irqrestore(&io_request_lock, flags); - return; - } - if(int_reg & ILCMD) /* Illegal Command */ - { - printk("sym53c416: Warning: Illegal Command: 0x%02x\n", inb(base + COMMAND_REG)); - current_command->SCp.phase = idle; - current_command->result = DID_ERROR << 16; - spin_lock_irqsave(&io_request_lock, flags); - current_command->scsi_done(current_command); - spin_unlock_irqrestore(&io_request_lock, flags); - return; - } - if(status_reg & GE) /* Gross Error */ - { - printk("sym53c416: Warning: Gross Error\n"); - current_command->SCp.phase = idle; - current_command->result = DID_ERROR << 16; - spin_lock_irqsave(&io_request_lock, flags); - current_command->scsi_done(current_command); - spin_unlock_irqrestore(&io_request_lock, flags); - return; - } - if(status_reg & PE) /* Parity Error */ - { - printk("sym53c416: Warning: Parity Error\n"); - current_command->SCp.phase = idle; - current_command->result = DID_PARITY << 16; - spin_lock_irqsave(&io_request_lock, flags); - current_command->scsi_done(current_command); - spin_unlock_irqrestore(&io_request_lock, flags); - return; - } - if(pio_int_reg & (CE | OUE)) - { - printk("sym53c416: Warning: PIO Interrupt Error\n"); - current_command->SCp.phase = idle; - current_command->result = DID_ERROR << 16; - spin_lock_irqsave(&io_request_lock, flags); - current_command->scsi_done(current_command); - spin_unlock_irqrestore(&io_request_lock, flags); - return; - } - if(int_reg & DIS) /* Disconnect */ - { - if(current_command->SCp.phase != message_in) - current_command->result = DID_NO_CONNECT << 16; - else - current_command->result = (current_command->SCp.Status & 0xFF) | ((current_command->SCp.Message & 0xFF) << 8) | (DID_OK << 16); - current_command->SCp.phase = idle; - - spin_lock_irqsave(&io_request_lock, flags); - current_command->scsi_done(current_command); - spin_unlock_irqrestore(&io_request_lock, flags); - return; - } - /* Now we handle SCSI phases */ - switch(status_reg & PHBITS) /* Filter SCSI phase out of status reg */ - { - case PHASE_DATA_OUT: - { - if(int_reg & BS) - { - current_command->SCp.phase = data_out; - outb(FLUSH_FIFO, base + COMMAND_REG); - sym53c416_set_transfer_counter(base, current_command->request_bufflen); - outb(TRANSFER_INFORMATION | PIO_MODE, base + COMMAND_REG); - if(!current_command->use_sg) - tot_trans = sym53c416_write(base, current_command->request_buffer, current_command->request_bufflen); - else - { - sgcount = current_command->use_sg; - sglist = current_command->request_buffer; - while(sgcount--) - { - tot_trans += sym53c416_write(base, sglist->address, sglist->length); - sglist++; - } - } - if(tot_trans < current_command->underflow) - printk("sym53c416: Warning: underflow, wrote %d bytes, request for %d bytes\n", tot_trans, current_command->underflow); - } - break; - } - case PHASE_DATA_IN: - { - if(int_reg & BS) - { - current_command->SCp.phase = data_in; - outb(FLUSH_FIFO, base + COMMAND_REG); - sym53c416_set_transfer_counter(base, current_command->request_bufflen); - outb(TRANSFER_INFORMATION | PIO_MODE, base + COMMAND_REG); - if(!current_command->use_sg) - tot_trans = sym53c416_read(base, current_command->request_buffer, current_command->request_bufflen); - else - { - sgcount = current_command->use_sg; - sglist = current_command->request_buffer; - while(sgcount--) - { - tot_trans += sym53c416_read(base, sglist->address, sglist->length); - sglist++; - } - } - if(tot_trans < current_command->underflow) - printk("sym53c416: Warning: underflow, read %d bytes, request for %d bytes\n", tot_trans, current_command->underflow); - } - break; - } - case PHASE_COMMAND: - { - current_command->SCp.phase = command_ph; - printk("sym53c416: Warning: Unknown interrupt in command phase\n"); - break; - } - case PHASE_STATUS: - { - current_command->SCp.phase = status_ph; - outb(FLUSH_FIFO, base + COMMAND_REG); - outb(INIT_COMM_COMPLETE_SEQ, base + COMMAND_REG); - break; - } - case PHASE_RESERVED_1: - case PHASE_RESERVED_2: - { - printk("sym53c416: Warning: Reserved phase\n"); - break; - } - case PHASE_MESSAGE_OUT: - { - current_command->SCp.phase = message_out; - outb(SET_ATN, base + COMMAND_REG); - outb(MSG_ACCEPTED, base + COMMAND_REG); - break; - } - case PHASE_MESSAGE_IN: - { - current_command->SCp.phase = message_in; - current_command->SCp.Status = inb(base + SCSI_FIFO); - current_command->SCp.Message = inb(base + SCSI_FIFO); - if(current_command->SCp.Message == SAVE_POINTERS || current_command->SCp.Message == DISCONNECT) - outb(SET_ATN, base + COMMAND_REG); - outb(MSG_ACCEPTED, base + COMMAND_REG); - break; - } - } - } +{ + int base = 0; + int i; + unsigned long flags = 0; + unsigned char status_reg, pio_int_reg, int_reg; + struct scatterlist *sglist; + unsigned int sgcount; + unsigned int tot_trans = 0; + + /* We search the base address of the host adapter which caused the interrupt */ + /* FIXME: should pass dev_id sensibly as hosts[i] */ + for(i = 0; i < host_index && !base; i++) + if(irq == hosts[i].irq) + base = hosts[i].base; + /* If no adapter found, we cannot handle the interrupt. Leave a message */ + /* and continue. This should never happen... */ + if(!base) + { + printk(KERN_ERR "sym53c416: No host adapter defined for interrupt %d\n", irq); + return; + } + /* Now we have the base address and we can start handling the interrupt */ + + spin_lock_irqsave(&io_request_lock,flags); + status_reg = inb(base + STATUS_REG); + pio_int_reg = inb(base + PIO_INT_REG); + int_reg = inb(base + INT_REG); + spin_unlock_irqrestore(&io_request_lock, flags); + + /* First, we handle error conditions */ + if(int_reg & SCI) /* SCSI Reset */ + { + printk(KERN_DEBUG "sym53c416: Reset received\n"); + current_command->SCp.phase = idle; + current_command->result = DID_RESET << 16; + spin_lock_irqsave(&io_request_lock, flags); + current_command->scsi_done(current_command); + spin_unlock_irqrestore(&io_request_lock, flags); + return; + } + if(int_reg & ILCMD) /* Illegal Command */ + { + printk(KERN_WARNING "sym53c416: Illegal Command: 0x%02x.\n", inb(base + COMMAND_REG)); + current_command->SCp.phase = idle; + current_command->result = DID_ERROR << 16; + spin_lock_irqsave(&io_request_lock, flags); + current_command->scsi_done(current_command); + spin_unlock_irqrestore(&io_request_lock, flags); + return; + } + if(status_reg & GE) /* Gross Error */ + { + printk(KERN_WARNING "sym53c416: Controller reports gross error.\n"); + current_command->SCp.phase = idle; + current_command->result = DID_ERROR << 16; + spin_lock_irqsave(&io_request_lock, flags); + current_command->scsi_done(current_command); + spin_unlock_irqrestore(&io_request_lock, flags); + return; + } + if(status_reg & PE) /* Parity Error */ + { + printk(KERN_WARNING "sym53c416:SCSI parity error.\n"); + current_command->SCp.phase = idle; + current_command->result = DID_PARITY << 16; + spin_lock_irqsave(&io_request_lock, flags); + current_command->scsi_done(current_command); + spin_unlock_irqrestore(&io_request_lock, flags); + return; + } + if(pio_int_reg & (CE | OUE)) + { + printk(KERN_WARNING "sym53c416: PIO interrupt error.\n"); + current_command->SCp.phase = idle; + current_command->result = DID_ERROR << 16; + spin_lock_irqsave(&io_request_lock, flags); + current_command->scsi_done(current_command); + spin_unlock_irqrestore(&io_request_lock, flags); + return; + } + if(int_reg & DIS) /* Disconnect */ + { + if(current_command->SCp.phase != message_in) + current_command->result = DID_NO_CONNECT << 16; + else + current_command->result = (current_command->SCp.Status & 0xFF) | ((current_command->SCp.Message & 0xFF) << 8) | (DID_OK << 16); + current_command->SCp.phase = idle; + spin_lock_irqsave(&io_request_lock, flags); + current_command->scsi_done(current_command); + spin_unlock_irqrestore(&io_request_lock, flags); + return; + } + /* Now we handle SCSI phases */ + + switch(status_reg & PHBITS) /* Filter SCSI phase out of status reg */ + { + case PHASE_DATA_OUT: + { + if(int_reg & BS) + { + current_command->SCp.phase = data_out; + outb(FLUSH_FIFO, base + COMMAND_REG); + sym53c416_set_transfer_counter(base, current_command->request_bufflen); + outb(TRANSFER_INFORMATION | PIO_MODE, base + COMMAND_REG); + if(!current_command->use_sg) + tot_trans = sym53c416_write(base, current_command->request_buffer, current_command->request_bufflen); + else + { + sgcount = current_command->use_sg; + sglist = current_command->request_buffer; + while(sgcount--) + { + tot_trans += sym53c416_write(base, sglist->address, sglist->length); + sglist++; + } + } + if(tot_trans < current_command->underflow) + printk(KERN_WARNING "sym53c416: Underflow, wrote %d bytes, request for %d bytes.\n", tot_trans, current_command->underflow); + } + break; + } + + case PHASE_DATA_IN: + { + if(int_reg & BS) + { + current_command->SCp.phase = data_in; + outb(FLUSH_FIFO, base + COMMAND_REG); + sym53c416_set_transfer_counter(base, current_command->request_bufflen); + outb(TRANSFER_INFORMATION | PIO_MODE, base + COMMAND_REG); + if(!current_command->use_sg) + tot_trans = sym53c416_read(base, current_command->request_buffer, current_command->request_bufflen); + else + { + sgcount = current_command->use_sg; + sglist = current_command->request_buffer; + while(sgcount--) + { + tot_trans += sym53c416_read(base, sglist->address, sglist->length); + sglist++; + } + } + if(tot_trans < current_command->underflow) + printk(KERN_WARNING "sym53c416: Underflow, read %d bytes, request for %d bytes.\n", tot_trans, current_command->underflow); + } + break; + } + + case PHASE_COMMAND: + { + current_command->SCp.phase = command_ph; + printk(KERN_ERR "sym53c416: Unknown interrupt in command phase.\n"); + break; + } + + case PHASE_STATUS: + { + current_command->SCp.phase = status_ph; + outb(FLUSH_FIFO, base + COMMAND_REG); + outb(INIT_COMM_COMPLETE_SEQ, base + COMMAND_REG); + break; + } + + case PHASE_RESERVED_1: + case PHASE_RESERVED_2: + { + printk(KERN_ERR "sym53c416: Reserved phase occurred.\n"); + break; + } + + case PHASE_MESSAGE_OUT: + { + current_command->SCp.phase = message_out; + outb(SET_ATN, base + COMMAND_REG); + outb(MSG_ACCEPTED, base + COMMAND_REG); + break; + } + + case PHASE_MESSAGE_IN: + { + current_command->SCp.phase = message_in; + current_command->SCp.Status = inb(base + SCSI_FIFO); + current_command->SCp.Message = inb(base + SCSI_FIFO); + if(current_command->SCp.Message == SAVE_POINTERS || current_command->SCp.Message == DISCONNECT) + outb(SET_ATN, base + COMMAND_REG); + outb(MSG_ACCEPTED, base + COMMAND_REG); + break; + } + } +} static void sym53c416_init(int base, int scsi_id) - { - outb(RESET_CHIP, base + COMMAND_REG); - outb(NOOP, base + COMMAND_REG); - outb(0x99, base + TOM); /* Time out of 250 ms */ - outb(0x05, base + STP); - outb(0x00, base + SYNC_OFFSET); - outb(EPC | scsi_id, base + CONF_REG_1); - outb(FE | SCSI2 | TBPA, base + CONF_REG_2); - outb(IDMRC | QTE | CDB10 | FSCSI | FCLK, base + CONF_REG_3); - outb(0x83 | EAN, base + CONF_REG_4); - outb(IE | WSE0, base + CONF_REG_5); - outb(0, base + FEATURE_EN); - } +{ + outb(RESET_CHIP, base + COMMAND_REG); + outb(NOOP, base + COMMAND_REG); + outb(0x99, base + TOM); /* Time out of 250 ms */ + outb(0x05, base + STP); + outb(0x00, base + SYNC_OFFSET); + outb(EPC | scsi_id, base + CONF_REG_1); + outb(FE | SCSI2 | TBPA, base + CONF_REG_2); + outb(IDMRC | QTE | CDB10 | FSCSI | FCLK, base + CONF_REG_3); + outb(0x83 | EAN, base + CONF_REG_4); + outb(IE | WSE0, base + CONF_REG_5); + outb(0, base + FEATURE_EN); +} static int sym53c416_probeirq(int base, int scsi_id) - { - int irq, irqs, i; +{ + int irq, irqs, i; - /* Clear interrupt register */ - inb(base + INT_REG); - /* Start probing for irq's */ - irqs = probe_irq_on(); - /* Reinit chip */ - sym53c416_init(base, scsi_id); - /* Cause interrupt */ - outb(NOOP, base + COMMAND_REG); - outb(ILLEGAL, base + COMMAND_REG); - outb(0x07, base + DEST_BUS_ID); - outb(0x00, base + DEST_BUS_ID); - /* Wait for interrupt to occur */ - i = jiffies + 20; - while(i > jiffies && !(inb(base + STATUS_REG) & SCI)) - barrier(); - if(i <= jiffies) /* timed out */ - return 0; - /* Get occurred irq */ - irq = probe_irq_off(irqs); - sym53c416_init(base, scsi_id); - return irq; - } + /* Clear interrupt register */ + inb(base + INT_REG); + /* Start probing for irq's */ + irqs = probe_irq_on(); + /* Reinit chip */ + sym53c416_init(base, scsi_id); + /* Cause interrupt */ + outb(NOOP, base + COMMAND_REG); + outb(ILLEGAL, base + COMMAND_REG); + outb(0x07, base + DEST_BUS_ID); + outb(0x00, base + DEST_BUS_ID); + /* Wait for interrupt to occur */ + i = jiffies + 20; + while(i > jiffies && !(inb(base + STATUS_REG) & SCI)) + barrier(); + if(i <= jiffies) /* timed out */ + return 0; + /* Get occurred irq */ + irq = probe_irq_off(irqs); + sym53c416_init(base, scsi_id); + return irq; +} /* Setup: sym53c416=base,irq */ void sym53c416_setup(char *str, int *ints) - { - int i; +{ + int i; - if(host_index >= MAXHOSTS) - { - printk("sym53c416.c: Too many hosts defined\n"); - } - else - { - if(ints[0] < 1 || ints[0] > 2) - { - printk("sym53c416.c: Wrong number of parameters:\n"); - printk("sym53c416.c: usage: sym53c416=[,]\n"); - } - else - { - for(i = 0; i < host_index && i >= 0; i++) - if(hosts[i].base == ints[1]) - i = -2; - if(i >= 0) - { - hosts[host_index].base = ints[1]; - hosts[host_index].irq = (ints[0] == 2)? ints[2] : 0; - host_index++; - } - } - } - } + if(host_index >= MAXHOSTS) + { + printk(KERN_WARNING "sym53c416: Too many hosts defined\n"); + return; + } + if(ints[0] < 1 || ints[0] > 2) + { + printk(KERN_ERR "sym53c416: Wrong number of parameters:\n"); + printk(KERN_ERR "sym53c416: usage: sym53c416=[,]\n"); + return; + } + for(i = 0; i < host_index && i >= 0; i++) + if(hosts[i].base == ints[1]) + i = -2; + if(i >= 0) + { + hosts[host_index].base = ints[1]; + hosts[host_index].irq = (ints[0] == 2)? ints[2] : 0; + host_index++; + } +} static int sym53c416_test(int base) - { - outb(RESET_CHIP, base + COMMAND_REG); - outb(NOOP, base + COMMAND_REG); - if(inb(base + COMMAND_REG) != NOOP) - return 0; - if(!inb(base + TC_HIGH) || inb(base + TC_HIGH) == 0xFF) - return 0; - if((inb(base + PIO_INT_REG) & (FULL | EMPTY | CE | OUE | FIE | EIE)) != EMPTY) - return 0; - return 1; - } +{ + outb(RESET_CHIP, base + COMMAND_REG); + outb(NOOP, base + COMMAND_REG); + if(inb(base + COMMAND_REG) != NOOP) + return 0; + if(!inb(base + TC_HIGH) || inb(base + TC_HIGH) == 0xFF) + return 0; + if((inb(base + PIO_INT_REG) & (FULL | EMPTY | CE | OUE | FIE | EIE)) != EMPTY) + return 0; + return 1; +} + + +static struct isapnp_device_id id_table[] = { + { ISAPNP_ANY_ID, ISAPNP_ANY_ID, + ISAPNP_VENDOR('S','L','I'), ISAPNP_FUNCTION(0x4163), 0 }, + {0} +}; + +MODULE_DEVICE_TABLE(isapnp, id_table); void sym53c416_probe(void) - { - int *base = probeaddrs; - int ints[2]; - - ints[0] = 1; - for(; *base; base++) - if(!check_region(*base, IO_RANGE) && sym53c416_test(*base)) - { - ints[1] = *base; - sym53c416_setup(NULL, ints); - } - } +{ + int *base = probeaddrs; + int ints[2]; + + ints[0] = 1; + for(; *base; base++) + { + if(!check_region(*base, IO_RANGE) && sym53c416_test(*base)) + { + ints[1] = *base; + sym53c416_setup(NULL, ints); + } + } +} int sym53c416_detect(Scsi_Host_Template *tpnt) - { - unsigned long flags; - struct Scsi_Host * shpnt = NULL; - int i; - int count; - +{ + unsigned long flags; + struct Scsi_Host * shpnt = NULL; + int i; + int count; + struct pci_dev *idev = NULL; + #ifdef MODULE - int ints[3]; + int ints[3]; - ints[0] = 2; - if(sym53c416_base) - { - ints[1] = sym53c416_base[0]; - ints[2] = sym53c416_base[1]; - sym53c416_setup(NULL, ints); - } - if(sym53c416_base_1) - { - ints[1] = sym53c416_base_1[0]; - ints[2] = sym53c416_base_1[1]; - sym53c416_setup(NULL, ints); - } - if(sym53c416_base_2) - { - ints[1] = sym53c416_base_2[0]; - ints[2] = sym53c416_base_2[1]; - sym53c416_setup(NULL, ints); - } - if(sym53c416_base_3) - { - ints[1] = sym53c416_base_3[0]; - ints[2] = sym53c416_base_3[1]; - sym53c416_setup(NULL, ints); - } + ints[0] = 2; + if(sym53c416_base) + { + ints[1] = sym53c416_base[0]; + ints[2] = sym53c416_base[1]; + sym53c416_setup(NULL, ints); + } + if(sym53c416_base_1) + { + ints[1] = sym53c416_base_1[0]; + ints[2] = sym53c416_base_1[1]; + sym53c416_setup(NULL, ints); + } + if(sym53c416_base_2) + { + ints[1] = sym53c416_base_2[0]; + ints[2] = sym53c416_base_2[1]; + sym53c416_setup(NULL, ints); + } + if(sym53c416_base_3) + { + ints[1] = sym53c416_base_3[0]; + ints[2] = sym53c416_base_3[1]; + sym53c416_setup(NULL, ints); + } #endif + printk(KERN_INFO "sym53c416.c: %s\n", VERSION_STRING); - printk("sym53c416.c: %s\n", VERSION_STRING); - - sym53c416_probe(); - - /* Now we register and set up each host adapter found... */ - for(count = 0, i = 0; i < host_index; i++) - if(!sym53c416_test(hosts[i].base)) - printk("No sym53c416 found at address 0x%03x\n", hosts[i].base); - else - { - if(hosts[i].irq == 0) - /* We don't have an irq yet, so we should probe for one */ - if((hosts[i].irq = sym53c416_probeirq(hosts[i].base, hosts[i].scsi_id)) == 0) - printk("irq autoprobing failed for sym53c416 at address 0x%03x\n", hosts[i].base); - if(hosts[i].irq && !check_region(hosts[i].base, IO_RANGE)) - { - shpnt = scsi_register(tpnt, 0); - if(shpnt==NULL) - continue; - save_flags(flags); - cli(); - /* Request for specified IRQ */ - if(request_irq(hosts[i].irq, sym53c416_intr_handle, 0, ID, NULL)) - { - restore_flags(flags); - printk("Unable to assign IRQ %d\n", hosts[i].irq); - scsi_unregister(shpnt); - } - else - { - /* Inform the kernel of our IO range */ - request_region(hosts[i].base, IO_RANGE, ID); - shpnt->unique_id = hosts[i].base; - shpnt->io_port = hosts[i].base; - shpnt->n_io_port = IO_RANGE; - shpnt->irq = hosts[i].irq; - shpnt->this_id = hosts[i].scsi_id; - sym53c416_init(hosts[i].base, hosts[i].scsi_id); - count++; - restore_flags(flags); - } - } - } - return count; - } + while((idev=isapnp_find_dev(NULL, ISAPNP_VENDOR('S','L','I'), + ISAPNP_FUNCTION(0x4163), idev))!=NULL) + { + int i[3]; + + if(idev->prepare(idev)<0) + { + printk(KERN_WARNING "sym53c416: unable to prepare PnP card.\n"); + continue; + } + if(idev->activate(idev)<0) + { + printk(KERN_WARNING "sym53c416: unable to activate PnP card.\n"); + continue; + } + + i[0] = 2; + i[1] = idev->resource[0].start; + i[2] = idev->irq_resource[0].start; + + printk(KERN_INFO "sym53c416: ISAPnP card found and configured at 0x%X, IRQ %d.\n", + i[1], i[2]); + sym53c416_setup(NULL, i); + } + sym53c416_probe(); + + /* Now we register and set up each host adapter found... */ + for(count = 0, i = 0; i < host_index; i++) + { + if(!sym53c416_test(hosts[i].base)) + printk(KERN_WARNING "No sym53c416 found at address 0x%03x\n", hosts[i].base); + else + { + if(hosts[i].irq == 0) + /* We don't have an irq yet, so we should probe for one */ + if((hosts[i].irq = sym53c416_probeirq(hosts[i].base, hosts[i].scsi_id)) == 0) + printk(KERN_WARNING "IRQ autoprobing failed for sym53c416 at address 0x%03x\n", hosts[i].base); + if(hosts[i].irq && !check_region(hosts[i].base, IO_RANGE)) + { + shpnt = scsi_register(tpnt, 0); + if(shpnt==NULL) + continue; + save_flags(flags); + cli(); + /* FIXME: Request_irq with CLI is not safe */ + /* Request for specified IRQ */ + if(request_irq(hosts[i].irq, sym53c416_intr_handle, 0, ID, NULL)) + { + restore_flags(flags); + printk(KERN_ERR "sym53c416: Unable to assign IRQ %d\n", hosts[i].irq); + scsi_unregister(shpnt); + } + else + { + /* Inform the kernel of our IO range */ + request_region(hosts[i].base, IO_RANGE, ID); + shpnt->unique_id = hosts[i].base; + shpnt->io_port = hosts[i].base; + shpnt->n_io_port = IO_RANGE; + shpnt->irq = hosts[i].irq; + shpnt->this_id = hosts[i].scsi_id; + sym53c416_init(hosts[i].base, hosts[i].scsi_id); + count++; + restore_flags(flags); + } + } + } + } + return count; +} const char *sym53c416_info(struct Scsi_Host *SChost) - { - int i; - int base = SChost->io_port; - int irq = SChost->irq; - int scsi_id = 0; - int rev = inb(base + TC_HIGH); - - for(i = 0; i < host_index; i++) - if(hosts[i].base == base) - scsi_id = hosts[i].scsi_id; - sprintf(info, "Symbios Logic 53c416 (rev. %d) at 0x%03x, irq %d, SCSI-ID %d, %s pio", rev, base, irq, scsi_id, (fastpio)? "fast" : "slow"); - return info; - } +{ + int i; + int base = SChost->io_port; + int irq = SChost->irq; + int scsi_id = 0; + int rev = inb(base + TC_HIGH); + + for(i = 0; i < host_index; i++) + if(hosts[i].base == base) + scsi_id = hosts[i].scsi_id; + sprintf(info, "Symbios Logic 53c416 (rev. %d) at 0x%03x, irq %d, SCSI-ID %d, %s pio", rev, base, irq, scsi_id, (fastpio)? "fast" : "slow"); + return info; +} int sym53c416_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) - { - int base; - unsigned long flags = 0; - int i; - - /* Store base register as we can have more than one controller in the system */ - base = SCpnt->host->io_port; - current_command = SCpnt; /* set current command */ - current_command->scsi_done = done; /* set ptr to done function */ - current_command->SCp.phase = command_ph; /* currect phase is the command phase */ - current_command->SCp.Status = 0; - current_command->SCp.Message = 0; - - save_flags(flags); - cli(); - outb(SCpnt->target, base + DEST_BUS_ID); /* Set scsi id target */ - outb(FLUSH_FIFO, base + COMMAND_REG); /* Flush SCSI and PIO FIFO's */ - /* Write SCSI command into the SCSI fifo */ - for(i = 0; i < SCpnt->cmd_len; i++) - outb(SCpnt->cmnd[i], base + SCSI_FIFO); - /* Start selection sequence */ - outb(SEL_WITHOUT_ATN_SEQ, base + COMMAND_REG); - /* Now an interrupt will be generated which we will catch in out interrupt routine */ - restore_flags(flags); - return 0; - } +{ + int base; + unsigned long flags = 0; + int i; + + /* Store base register as we can have more than one controller in the system */ + base = SCpnt->host->io_port; + current_command = SCpnt; /* set current command */ + current_command->scsi_done = done; /* set ptr to done function */ + current_command->SCp.phase = command_ph; /* currect phase is the command phase */ + current_command->SCp.Status = 0; + current_command->SCp.Message = 0; + + save_flags(flags); + cli(); + outb(SCpnt->target, base + DEST_BUS_ID); /* Set scsi id target */ + outb(FLUSH_FIFO, base + COMMAND_REG); /* Flush SCSI and PIO FIFO's */ + /* Write SCSI command into the SCSI fifo */ + for(i = 0; i < SCpnt->cmd_len; i++) + outb(SCpnt->cmnd[i], base + SCSI_FIFO); + /* Start selection sequence */ + outb(SEL_WITHOUT_ATN_SEQ, base + COMMAND_REG); + /* Now an interrupt will be generated which we will catch in out interrupt routine */ + restore_flags(flags); + return 0; +} static void internal_done(Scsi_Cmnd *SCpnt) - { - SCpnt->SCp.Status++; - } - -int sym53c416_command(Scsi_Cmnd *SCpnt) - { - sym53c416_queuecommand(SCpnt, internal_done); - SCpnt->SCp.Status = 0; - while(!SCpnt->SCp.Status) - barrier(); - return SCpnt->result; - } - -int sym53c416_abort(Scsi_Cmnd *SCpnt) - { - printk("sym53c416_abort\n"); - - /* We don't know how to abort for the moment */ - return SCSI_ABORT_SNOOZE; - } - -int sym53c416_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags) - { - int base; - int scsi_id = -1; - int i; - - printk("sym53c416_reset\n"); - base = SCpnt->host->io_port; - /* search scsi_id */ - for(i = 0; i < host_index && scsi_id != -1; i++) - if(hosts[i].base == base) - scsi_id = hosts[i].scsi_id; - outb(RESET_CHIP, base + COMMAND_REG); - outb(NOOP | PIO_MODE, base + COMMAND_REG); - outb(RESET_SCSI_BUS, base + COMMAND_REG); - sym53c416_init(base, scsi_id); - return SCSI_RESET_PENDING; - } - -int sym53c416_bios_param(Disk *disk, kdev_t dev, int *ip) - { - int size; - - size = disk->capacity; - ip[0] = 64; /* heads */ - ip[1] = 32; /* sectors */ - if((ip[2] = size >> 11) > 1024) /* cylinders, test for big disk */ - { - ip[0] = 255; /* heads */ - ip[1] = 63; /* sectors */ - ip[2] = size / (255 * 63); /* cylinders */ - } - return 0; - } +{ + SCpnt->SCp.Status++; +} + +static int sym53c416_command(Scsi_Cmnd *SCpnt) +{ + sym53c416_queuecommand(SCpnt, internal_done); + SCpnt->SCp.Status = 0; + while(!SCpnt->SCp.Status) + barrier(); + return SCpnt->result; +} + +static int sym53c416_abort(Scsi_Cmnd *SCpnt) +{ + //printk("sym53c416_abort\n"); + /* We don't know how to abort for the moment */ + return SCSI_ABORT_SNOOZE; +} + +static int sym53c416_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags) +{ + int base; + int scsi_id = -1; + int i; + + //printk("sym53c416_reset\n"); + base = SCpnt->host->io_port; + /* search scsi_id */ + for(i = 0; i < host_index && scsi_id != -1; i++) + if(hosts[i].base == base) + scsi_id = hosts[i].scsi_id; + outb(RESET_CHIP, base + COMMAND_REG); + outb(NOOP | PIO_MODE, base + COMMAND_REG); + outb(RESET_SCSI_BUS, base + COMMAND_REG); + sym53c416_init(base, scsi_id); + return SCSI_RESET_PENDING; +} + +static int sym53c416_bios_param(Disk *disk, kdev_t dev, int *ip) +{ + int size; + + size = disk->capacity; + ip[0] = 64; /* heads */ + ip[1] = 32; /* sectors */ + if((ip[2] = size >> 11) > 1024) /* cylinders, test for big disk */ + { + ip[0] = 255; /* heads */ + ip[1] = 63; /* sectors */ + ip[2] = size / (255 * 63); /* cylinders */ + } + return 0; +} /* Loadable module support */ #ifdef MODULE diff -u --recursive --new-file v2.4.5/linux/drivers/scsi/sym53c416.h linux/drivers/scsi/sym53c416.h --- v2.4.5/linux/drivers/scsi/sym53c416.h Mon Dec 11 13:19:20 2000 +++ linux/drivers/scsi/sym53c416.h Wed Jun 27 17:10:55 2001 @@ -31,14 +31,14 @@ #define SYM53C416_SCSI_ID 7 -extern int sym53c416_detect(Scsi_Host_Template *); -extern const char *sym53c416_info(struct Scsi_Host *); -extern int sym53c416_command(Scsi_Cmnd *); -extern int sym53c416_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -extern int sym53c416_abort(Scsi_Cmnd *); -extern int sym53c416_reset(Scsi_Cmnd *, unsigned int); -extern int sym53c416_bios_param(Disk *, kdev_t, int *); -extern void sym53c416_setup(char *str, int *ints); +static int sym53c416_detect(Scsi_Host_Template *); +static const char *sym53c416_info(struct Scsi_Host *); +static int sym53c416_command(Scsi_Cmnd *); +static int sym53c416_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +static int sym53c416_abort(Scsi_Cmnd *); +static int sym53c416_reset(Scsi_Cmnd *, unsigned int); +static int sym53c416_bios_param(Disk *, kdev_t, int *); +static void sym53c416_setup(char *str, int *ints); #define SYM53C416 { \ proc_name: "sym53c416", \ diff -u --recursive --new-file v2.4.5/linux/drivers/scsi/sym53c8xx.c linux/drivers/scsi/sym53c8xx.c --- v2.4.5/linux/drivers/scsi/sym53c8xx.c Fri Apr 27 13:59:19 2001 +++ linux/drivers/scsi/sym53c8xx.c Tue Jun 12 11:06:54 2001 @@ -11564,6 +11564,7 @@ OUTL_DSP (NCB_SCRIPT_PHYS (np, clrack)); return; out_stuck: + return; } diff -u --recursive --new-file v2.4.5/linux/drivers/sgi/char/linux_logo.h linux/drivers/sgi/char/linux_logo.h --- v2.4.5/linux/drivers/sgi/char/linux_logo.h Wed Dec 10 10:31:11 1997 +++ linux/drivers/sgi/char/linux_logo.h Wed Dec 31 16:00:00 1969 @@ -1,909 +0,0 @@ -/* This is a linux logo to be displayed on boot. - * - * You can put anything here, but: - * LINUX_LOGO_COLORS has to be less than 224 - * image size has to be 80x80 - * values have to start from0x20 - * (i.e. RGB(linux_logo_red[0], - * linux_logo_green[0], - * linux_logo_blue[0]) is color0x20) - */ - -#define LINUX_LOGO_COLORS 221 - -unsigned char linux_logo_red[] = { - 0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3, - 0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xE5, - 0xF1, 0xED, 0xEE, 0xE6, 0xC6, 0xDA, 0xDD, 0xE5, - 0xD9, 0xC6, 0xE3, 0xD0, 0xC6, 0xBA, 0xB0, 0xB6, - 0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xB0, 0xAD, - 0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x9D, - 0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99, - 0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D, - 0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x0D, 0x03, - 0x66, 0x44, 0x24, 0x08, 0xD6, 0xE6, 0xE9, 0xE6, - 0xE7, 0xCA, 0xDC, 0xDB, 0xD5, 0xD0, 0xC9, 0xE2, - 0xD5, 0xC6, 0xC4, 0xB3, 0xB2, 0xB9, 0xA9, 0x9A, - 0xB2, 0x9D, 0xE8, 0xEC, 0xF5, 0xF5, 0xF4, 0xF4, - 0xEC, 0xEE, 0xF0, 0xF5, 0xE0, 0xD6, 0xC5, 0xC2, - 0xD9, 0xD5, 0xD8, 0xD6, 0xF6, 0xF4, 0xED, 0xEC, - 0xEB, 0xF1, 0xF6, 0xF5, 0xF5, 0xEE, 0xEF, 0xEC, - 0xE7, 0xE3, 0xE6, 0xD6, 0xDD, 0xC3, 0xD6, 0xD7, - 0xCD, 0xCA, 0xC3, 0xAC, 0x95, 0x99, 0xB7, 0xA3, - 0x8B, 0x88, 0x95, 0x8A, 0x94, 0xD2, 0xCC, 0xC4, - 0xA8, 0x8E, 0x8F, 0xAE, 0xB8, 0xAC, 0xB6, 0xB4, - 0xAD, 0xA5, 0xA0, 0x9B, 0x8B, 0xA3, 0x94, 0x87, - 0x85, 0x89, 0x53, 0x80, 0x7D, 0x7C, 0x7A, 0x78, - 0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62, - 0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46, - 0x42, 0x0F, 0x75, 0x78, 0x7D, 0x72, 0x5F, 0x6E, - 0x7A, 0x75, 0x6A, 0x58, 0x48, 0x4F, 0x00, 0x2B, - 0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x3B, 0x11, - 0x1D, 0x14, 0x06, 0x02, 0x00 -}; - -unsigned char linux_logo_green[] = { - 0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3, - 0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xD3, - 0xDA, 0xD4, 0xD7, 0xCC, 0xC1, 0xCC, 0xCB, 0xC9, - 0xC5, 0xBC, 0xBC, 0xBB, 0xB7, 0xA5, 0xB0, 0xB6, - 0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xAD, 0xAD, - 0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x95, - 0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99, - 0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D, - 0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x08, 0x02, - 0x53, 0x2E, 0x19, 0x06, 0xC6, 0xC8, 0xCF, 0xBD, - 0xB3, 0xB6, 0xB4, 0xAB, 0xA5, 0xA3, 0x9B, 0xB6, - 0xA7, 0x99, 0x92, 0xA4, 0x9E, 0x9D, 0x98, 0x8C, - 0x8A, 0x86, 0xCD, 0xCC, 0xC9, 0xD7, 0xCA, 0xC4, - 0xCA, 0xC3, 0xC7, 0xC3, 0xC8, 0xB4, 0x91, 0x8E, - 0x8A, 0x82, 0x87, 0x85, 0xBD, 0xBF, 0xB6, 0xBC, - 0xAE, 0xB7, 0xBC, 0xB8, 0xBF, 0xB6, 0xBC, 0xB5, - 0xAB, 0xA6, 0xAD, 0xB2, 0xA5, 0x87, 0x9C, 0x96, - 0x95, 0x8E, 0x87, 0x8F, 0x86, 0x86, 0x8E, 0x80, - 0x7A, 0x70, 0x7B, 0x78, 0x78, 0x7F, 0x77, 0x6F, - 0x70, 0x76, 0x59, 0x77, 0x68, 0x64, 0x7B, 0x7C, - 0x75, 0x6D, 0x77, 0x69, 0x65, 0x5F, 0x5B, 0x54, - 0x4F, 0x5B, 0x39, 0x80, 0x7D, 0x7C, 0x7A, 0x78, - 0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62, - 0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46, - 0x42, 0x0B, 0x69, 0x66, 0x64, 0x57, 0x4A, 0x4E, - 0x55, 0x4B, 0x46, 0x3B, 0x30, 0x33, 0x00, 0x2B, - 0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x29, 0x0D, - 0x1D, 0x14, 0x06, 0x02, 0x00 -}; - -unsigned char linux_logo_blue[] = { - 0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xEE, 0xE5, 0xDE, - 0xD7, 0xD3, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xB5, - 0xB0, 0xA6, 0xAC, 0x9B, 0xB5, 0xB5, 0xAE, 0x84, - 0x90, 0xA9, 0x81, 0x8D, 0x96, 0x86, 0xB0, 0xB6, - 0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xA7, 0xAD, - 0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA5, 0x87, - 0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x9A, 0x9A, 0x99, - 0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D, - 0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0xC8, 0xD7, - 0x9B, 0x8E, 0x8C, 0xB2, 0x77, 0x77, 0x4E, 0x77, - 0x69, 0x71, 0x78, 0x6B, 0x65, 0x66, 0x64, 0x59, - 0x5C, 0x5A, 0x48, 0x72, 0x7B, 0x6B, 0x67, 0x6E, - 0x42, 0x5B, 0x29, 0x36, 0x25, 0x10, 0x17, 0x14, - 0x19, 0x16, 0x13, 0x0E, 0x08, 0x2E, 0x2E, 0x3D, - 0x24, 0x24, 0x24, 0x24, 0x13, 0x12, 0x14, 0x14, - 0x0E, 0x08, 0x0D, 0x0F, 0x08, 0x0D, 0x0E, 0x08, - 0x08, 0x0C, 0x06, 0x06, 0x07, 0x16, 0x07, 0x0E, - 0x08, 0x0A, 0x07, 0x0D, 0x2D, 0x3E, 0x09, 0x4E, - 0x68, 0x52, 0x56, 0x58, 0x4B, 0x22, 0x20, 0x20, - 0x27, 0x39, 0x28, 0x19, 0x1E, 0x1E, 0x08, 0x06, - 0x07, 0x09, 0x08, 0x08, 0x05, 0x1D, 0x1F, 0x17, - 0x18, 0x06, 0x79, 0x80, 0x7D, 0x7C, 0x7A, 0x78, - 0x76, 0x71, 0x73, 0x6E, 0x6B, 0x68, 0x65, 0x62, - 0x4B, 0x5B, 0x5F, 0x55, 0x56, 0x52, 0x4F, 0x46, - 0x42, 0x5A, 0x14, 0x23, 0x3D, 0x2B, 0x21, 0x14, - 0x06, 0x04, 0x03, 0x07, 0x09, 0x13, 0x2A, 0x3A, - 0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x07, 0x09, - 0x1D, 0x14, 0x06, 0x02, 0x00 -}; - -unsigned char linux_logo[] = { - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57, - 0x58, 0x58, 0x59, 0x5C, 0x5D, 0x5F, 0x60, 0x61, - 0x62, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63, - 0x61, 0x61, 0x61, 0x61, 0x61, 0x60, 0x5E, 0x5E, - 0x5E, 0x5D, 0x5D, 0x5C, 0x5D, 0x5B, 0x58, 0x58, - 0x58, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57, - 0x54, 0x56, 0x57, 0x67, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x67, 0x4C, - 0x4A, 0x49, 0x4A, 0x49, 0x4A, 0x49, 0x49, 0x4A, - 0x4A, 0x4B, 0x4B, 0x4B, 0x4C, 0x50, 0x51, 0x52, - 0x54, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57, 0x58, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x58, 0x56, 0x56, 0x53, - 0x52, 0x53, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB, - 0x4B, 0x4B, 0x4B, 0x4A, 0x49, 0x4A, 0x4A, 0x49, - 0x49, 0x49, 0x48, 0x49, 0x49, 0x4A, 0x4A, 0x4B, - 0x4C, 0x4D, 0x52, 0x54, 0x56, 0x55, 0x57, 0x58, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, - 0x50, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF0, 0xF4, 0xFB, - 0xFC, 0x67, 0x53, 0x50, 0x4D, 0x4C, 0x4C, 0x4C, - 0x4B, 0x4A, 0x4A, 0x48, 0x49, 0x48, 0x48, 0x49, - 0x49, 0x49, 0x4B, 0x4C, 0x50, 0x52, 0x53, 0x56, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x55, 0x54, 0x53, 0x51, 0x51, 0x50, 0x4C, 0x4D, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xD2, 0xD7, 0xF5, - 0xFC, 0xFC, 0x5D, 0x5D, 0x5C, 0x5C, 0x59, 0x58, - 0x58, 0x56, 0x52, 0x4C, 0x4B, 0x4A, 0x4A, 0x48, - 0x48, 0x48, 0x48, 0x48, 0x49, 0x4B, 0x4D, 0x51, - 0x54, 0x56, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x55, 0x54, - 0x53, 0x52, 0x51, 0x4D, 0x4D, 0x4D, 0x50, 0x50, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0x64, 0xD9, 0xF5, - 0xF9, 0xFC, 0xFC, 0x64, 0x63, 0x62, 0x61, 0x61, - 0x61, 0x60, 0x5E, 0x5B, 0x5A, 0x54, 0x52, 0x4C, - 0x4B, 0x49, 0x49, 0x47, 0x47, 0x48, 0x49, 0x4B, - 0x4C, 0x51, 0x53, 0x56, 0x57, 0x58, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x55, 0x53, 0x53, - 0x51, 0x50, 0x50, 0x50, 0x50, 0x50, 0x53, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xF5, 0xF9, 0xFC, - 0xFC, 0xFC, 0xFC, 0x64, 0x64, 0x64, 0x64, 0x64, - 0x64, 0x64, 0x64, 0x63, 0x61, 0x61, 0x5E, 0x59, - 0x55, 0x52, 0x4C, 0x4A, 0x49, 0x47, 0x48, 0x48, - 0x49, 0x4B, 0x4D, 0x51, 0x54, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x55, 0x54, 0x54, 0x52, 0x51, - 0x51, 0x51, 0x51, 0x51, 0x53, 0x54, 0x59, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xF7, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0x60, 0x60, 0x60, 0x61, - 0x62, 0x63, 0x64, 0x64, 0x65, 0x65, 0x64, 0x63, - 0x61, 0x5E, 0x59, 0x56, 0x4D, 0x4B, 0x48, 0x48, - 0x48, 0x48, 0x49, 0x4B, 0x50, 0x53, 0x56, 0x56, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x56, 0x54, 0x53, 0x52, 0x51, 0x51, - 0x51, 0x52, 0x53, 0x55, 0x59, 0x5D, 0x5E, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0x4C, 0x4E, 0x51, 0x52, - 0x57, 0x5A, 0x5E, 0x60, 0x61, 0x63, 0x65, 0xCB, - 0x64, 0x64, 0x63, 0x60, 0x5C, 0x57, 0x50, 0x4B, - 0x48, 0x47, 0x47, 0x47, 0x4A, 0x4C, 0x52, 0x53, - 0x54, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x55, 0x54, 0x53, 0x53, 0x51, 0x52, 0x52, 0x53, - 0x53, 0x57, 0x5A, 0x5D, 0x5E, 0x5E, 0x60, 0xFC, - 0xFC, 0xFC, 0xFB, 0xF9, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFA, 0xF9, 0xF5, 0xFB, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x45, 0x3F, 0x3F, - 0x45, 0x48, 0x4B, 0x4D, 0x54, 0x5A, 0x5E, 0x61, - 0x63, 0xCB, 0xCB, 0x65, 0x64, 0x62, 0x5E, 0x57, - 0x50, 0x4B, 0x48, 0x47, 0x47, 0x48, 0x4B, 0x4D, - 0x51, 0x56, 0x56, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, - 0x54, 0x54, 0x53, 0x53, 0x52, 0x53, 0x54, 0x57, - 0x59, 0x5C, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0xFC, - 0xFC, 0xFA, 0xFC, 0xFA, 0xE0, 0xFC, 0xFC, 0xFC, - 0xFB, 0xFB, 0xFB, 0xDF, 0xD8, 0xF9, 0xE0, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x4C, 0x4A, 0x48, - 0x48, 0x3E, 0x44, 0x43, 0x3F, 0x47, 0x4B, 0x52, - 0x5A, 0x5E, 0x62, 0x64, 0xCB, 0xCB, 0x64, 0x61, - 0x5E, 0x57, 0x4D, 0x49, 0x47, 0x47, 0x48, 0x4A, - 0x4C, 0x52, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, - 0x54, 0x53, 0x53, 0x54, 0x54, 0x55, 0x58, 0x5B, - 0x5C, 0x5D, 0x5E, 0x5D, 0x5D, 0x5B, 0x58, 0xFC, - 0xFC, 0xD8, 0x4C, 0x60, 0xFC, 0xF5, 0xFC, 0xFC, - 0xFC, 0xF7, 0x5F, 0x48, 0x48, 0x2C, 0xF8, 0xF9, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x4A, 0x49, - 0x49, 0x49, 0x49, 0x47, 0x3E, 0x44, 0x42, 0x3F, - 0x3E, 0x4B, 0x54, 0x5C, 0x61, 0x64, 0xCB, 0xCB, - 0x64, 0x61, 0x5D, 0x53, 0x4B, 0x49, 0x47, 0x47, - 0x49, 0x4B, 0x50, 0x53, 0x56, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x55, 0x54, - 0x53, 0x53, 0x54, 0x56, 0x58, 0x5A, 0x5B, 0x5D, - 0x5D, 0x5D, 0x5C, 0x5A, 0x54, 0x52, 0x4C, 0xFC, - 0xF7, 0x4E, 0x2D, 0x29, 0x4E, 0xFC, 0xFC, 0xFC, - 0xFB, 0x5F, 0x26, 0x24, 0x20, 0x2E, 0x65, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x45, 0x3F, 0x45, - 0x3E, 0x47, 0x47, 0x47, 0x47, 0x47, 0x3E, 0x44, - 0x43, 0x40, 0x44, 0x49, 0x51, 0x5C, 0x62, 0x64, - 0xCB, 0xCB, 0x63, 0x60, 0x58, 0x50, 0x49, 0x48, - 0x48, 0x48, 0x4A, 0x4D, 0x53, 0x54, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54, - 0x54, 0x54, 0x55, 0x57, 0x59, 0x5B, 0x5C, 0x5D, - 0x5C, 0x5A, 0x54, 0x51, 0x4C, 0x4C, 0x54, 0xFC, - 0xF9, 0x23, 0xDB, 0x2D, 0x23, 0xFA, 0xFB, 0xFA, - 0xF5, 0x27, 0x21, 0xD9, 0xF8, 0x20, 0x21, 0xFB, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x5D, 0x58, 0x55, - 0x50, 0x48, 0x45, 0x43, 0x44, 0x44, 0x45, 0x45, - 0x3E, 0x3F, 0x43, 0x41, 0x3F, 0x48, 0x52, 0x5D, - 0x63, 0x65, 0xCB, 0x65, 0x61, 0x5D, 0x52, 0x4B, - 0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54, - 0x54, 0x58, 0x5A, 0x59, 0x5B, 0x5B, 0x5B, 0x5A, - 0x55, 0x52, 0x4D, 0x4D, 0x55, 0x5B, 0x5D, 0xFC, - 0xF1, 0xF9, 0xFC, 0xD4, 0x21, 0xCC, 0xF7, 0xF8, - 0xF2, 0x21, 0xD9, 0xFC, 0xF2, 0xFB, 0x21, 0x45, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xD1, 0xD0, 0xCD, - 0xCC, 0x63, 0x5E, 0x58, 0x50, 0x47, 0x43, 0x3F, - 0x3F, 0x3F, 0x3F, 0x3F, 0x40, 0x41, 0x3F, 0x4A, - 0x56, 0x5E, 0x64, 0xCB, 0x65, 0x63, 0x5E, 0x56, - 0x4C, 0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54, - 0x58, 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, - 0x57, 0x5A, 0x5A, 0x5C, 0x5B, 0x5A, 0x58, 0x54, - 0x51, 0x4C, 0x55, 0x5D, 0x5D, 0x5B, 0x54, 0xFC, - 0xF0, 0xF9, 0xFC, 0x65, 0x45, 0xCD, 0xFB, 0xFB, - 0xF8, 0x26, 0xFB, 0xFC, 0xFC, 0xFC, 0x21, 0x27, - 0xFB, 0xFC, 0xFC, 0xFC, 0xFB, 0xD7, 0x35, 0x34, - 0x2F, 0x35, 0x36, 0x2F, 0x2F, 0x36, 0x2F, 0x2F, - 0x36, 0x36, 0x35, 0x35, 0x43, 0x42, 0x41, 0x2E, - 0x45, 0x4C, 0x5B, 0x62, 0x65, 0xCC, 0x64, 0x60, - 0x58, 0x4D, 0x49, 0x47, 0x47, 0x49, 0x4C, 0x51, - 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x57, - 0x58, 0x5A, 0x5A, 0x5B, 0x5A, 0x55, 0x54, 0x51, - 0x53, 0x5C, 0x5D, 0x5D, 0x54, 0x4B, 0x4D, 0xFC, - 0xFC, 0x44, 0xFC, 0xFB, 0x7B, 0xAB, 0xA8, 0xAE, - 0xAB, 0x7F, 0xFC, 0xFC, 0xFB, 0xFB, 0x22, 0x2A, - 0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x2F, 0x30, 0x30, - 0x32, 0x30, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x30, 0x2F, 0x2F, 0x40, 0x41, - 0x2E, 0x40, 0x48, 0x56, 0x5F, 0x64, 0xCC, 0x65, - 0x61, 0x59, 0x50, 0x49, 0x47, 0x47, 0x49, 0x4C, - 0x5A, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, - 0x5A, 0x5A, 0x5A, 0x58, 0x55, 0x52, 0x51, 0x5A, - 0x5D, 0x5D, 0x57, 0x4C, 0x51, 0x54, 0x5D, 0xFC, - 0xFC, 0x2A, 0xFC, 0xC9, 0xAA, 0x8B, 0x8A, 0x8C, - 0xAB, 0x8C, 0x8C, 0xFB, 0xFB, 0x23, 0x20, 0xF1, - 0xFC, 0xFC, 0xFC, 0x3B, 0x33, 0x33, 0x32, 0x32, - 0x31, 0x32, 0x30, 0x32, 0x32, 0x32, 0x32, 0x30, - 0x31, 0x31, 0x31, 0x32, 0x33, 0x33, 0x3C, 0x41, - 0x41, 0x2E, 0x2D, 0x45, 0x4D, 0x5D, 0x63, 0xCC, - 0x65, 0x62, 0x5D, 0x51, 0x49, 0x47, 0x47, 0x4A, - 0x59, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, 0x58, - 0x5A, 0x5A, 0x58, 0x55, 0x53, 0x53, 0x5C, 0x5E, - 0x59, 0x51, 0x4E, 0x54, 0x59, 0x5E, 0x62, 0xFC, - 0xFC, 0xDB, 0xAA, 0xA1, 0x95, 0x9C, 0x8C, 0x88, - 0x82, 0x83, 0x83, 0x8C, 0x88, 0xAE, 0xB9, 0xFB, - 0xFC, 0xFC, 0xFC, 0x3C, 0x3B, 0x72, 0x38, 0x33, - 0x33, 0x33, 0x31, 0x33, 0x31, 0x31, 0x31, 0x31, - 0x33, 0x33, 0x38, 0x33, 0x72, 0x3B, 0x44, 0x2E, - 0x41, 0x2E, 0x2E, 0x2D, 0x43, 0x4B, 0x5B, 0x63, - 0xCB, 0xCC, 0x63, 0x5D, 0x51, 0x49, 0x47, 0x49, - 0x5C, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, - 0x58, 0x58, 0x57, 0x53, 0x58, 0x5D, 0x5E, 0x55, - 0x51, 0x53, 0x58, 0x5E, 0x60, 0x63, 0x64, 0xFC, - 0xFC, 0xC0, 0xA6, 0x9D, 0x8B, 0x9C, 0x8C, 0x8C, - 0x6E, 0x83, 0x88, 0x8C, 0x8C, 0x8C, 0x83, 0xE8, - 0xFB, 0xFC, 0xFC, 0xFC, 0x33, 0x70, 0x70, 0x6F, - 0x6F, 0x6F, 0x6F, 0x3A, 0x6F, 0x6D, 0x6F, 0x6F, - 0x70, 0x6F, 0x6F, 0x70, 0x6F, 0x32, 0x5A, 0x48, - 0x41, 0x2D, 0x2D, 0x2D, 0x2C, 0x41, 0x49, 0x5A, - 0x62, 0xCB, 0xCB, 0x63, 0x5D, 0x50, 0x49, 0x4A, - 0x5C, 0x58, 0x58, 0x57, 0x55, 0x57, 0x57, 0x57, - 0x57, 0x55, 0x56, 0x59, 0x5E, 0x5C, 0x52, 0x53, - 0x55, 0x5B, 0x5E, 0x61, 0x63, 0x64, 0x63, 0xFC, - 0xE8, 0xBF, 0xA4, 0x99, 0x9C, 0x8C, 0x88, 0x88, - 0x6E, 0x88, 0x8C, 0x8C, 0x8C, 0xC2, 0xA6, 0xC4, - 0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x3A, 0x6F, 0x70, - 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, - 0x70, 0x70, 0x70, 0x70, 0x37, 0x32, 0xCD, 0x5E, - 0x4C, 0x43, 0x2C, 0x2D, 0x2D, 0x2C, 0x2E, 0x47, - 0x57, 0x61, 0x65, 0xCC, 0x63, 0x5C, 0x50, 0x4D, - 0x5C, 0x5A, 0x57, 0x55, 0x55, 0x55, 0x58, 0x58, - 0x55, 0x54, 0x5B, 0x5E, 0x5D, 0x53, 0x53, 0x55, - 0x5D, 0x5E, 0x61, 0x61, 0x61, 0x61, 0x5E, 0xFC, - 0xEA, 0xBE, 0xA4, 0x9B, 0x8B, 0x85, 0x8C, 0x6E, - 0x8C, 0x8C, 0x8C, 0xA3, 0xAA, 0xA4, 0xA4, 0xE9, - 0xFB, 0xFC, 0xFC, 0xFC, 0x36, 0x6D, 0x70, 0x73, - 0x70, 0x70, 0x70, 0x73, 0x73, 0x73, 0x73, 0x70, - 0x70, 0x70, 0x73, 0x70, 0x37, 0x38, 0xD1, 0xCF, - 0x61, 0x4D, 0x44, 0x2C, 0x2D, 0x2E, 0x2C, 0x2E, - 0x3E, 0x56, 0x61, 0xCB, 0xCC, 0x62, 0x5B, 0x57, - 0x59, 0x58, 0x55, 0x54, 0x54, 0x55, 0x58, 0x58, - 0x58, 0x5B, 0x5E, 0x5B, 0x53, 0x55, 0x55, 0x5C, - 0x5E, 0x61, 0x61, 0x60, 0x5D, 0x5A, 0x4E, 0xFC, - 0xFC, 0xEA, 0xAA, 0x9C, 0x8A, 0x85, 0x82, 0x8C, - 0x8C, 0xA8, 0xEB, 0xA8, 0xA4, 0xA4, 0xAA, 0xFC, - 0xFC, 0xFC, 0x64, 0xFB, 0x39, 0x31, 0x72, 0x78, - 0x73, 0x78, 0x73, 0x74, 0x74, 0x74, 0x74, 0x73, - 0x78, 0x70, 0x73, 0x73, 0x33, 0xCC, 0xD2, 0xD1, - 0xCE, 0x62, 0x53, 0x3F, 0x2D, 0x2D, 0x41, 0x2C, - 0x2E, 0x3E, 0x56, 0x62, 0xCB, 0xCB, 0x61, 0x5D, - 0x54, 0x54, 0x54, 0x54, 0x56, 0x58, 0x58, 0x58, - 0x5C, 0x5E, 0x5A, 0x55, 0x58, 0x58, 0x5B, 0x5E, - 0x61, 0x5E, 0x5D, 0x5A, 0x52, 0x55, 0xCD, 0xFC, - 0xFC, 0x34, 0xC9, 0xE8, 0xA8, 0xAE, 0xC2, 0xE8, - 0xC3, 0xA6, 0xA7, 0xA6, 0xAA, 0x78, 0x2E, 0x42, - 0xFC, 0xFC, 0xD2, 0x64, 0xF8, 0x31, 0x72, 0x73, - 0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x74, 0x73, - 0x73, 0x73, 0x73, 0x72, 0x33, 0x5C, 0x64, 0xD2, - 0xD1, 0xCF, 0x63, 0x54, 0x3F, 0x2C, 0x41, 0x41, - 0x2C, 0x2E, 0x47, 0x58, 0x63, 0xCB, 0xCB, 0x62, - 0x52, 0x53, 0x53, 0x56, 0x58, 0x58, 0x5A, 0x5B, - 0x5E, 0x5A, 0x57, 0x58, 0x58, 0x58, 0x60, 0x60, - 0x5D, 0x5A, 0x55, 0x4E, 0x64, 0xD2, 0xD1, 0xFC, - 0xFC, 0x41, 0x3E, 0xC1, 0xC0, 0xA3, 0xA6, 0xA7, - 0xA7, 0xA9, 0xAA, 0xB8, 0x2E, 0x3F, 0x2C, 0x41, - 0xFC, 0xFC, 0xF7, 0xCE, 0xCD, 0x36, 0x72, 0x73, - 0x74, 0x75, 0x78, 0x75, 0x75, 0x75, 0x74, 0x74, - 0x74, 0x74, 0x78, 0x72, 0x6D, 0x49, 0x59, 0xCB, - 0xD1, 0xD1, 0xD2, 0xCB, 0x56, 0x3F, 0x2C, 0x41, - 0x40, 0x2D, 0x2E, 0x49, 0x5B, 0x64, 0xCC, 0x64, - 0x51, 0x53, 0x53, 0x55, 0x58, 0x59, 0x5B, 0x5E, - 0x59, 0x58, 0x58, 0x58, 0x55, 0x60, 0x60, 0x5C, - 0x5A, 0x53, 0x5B, 0xD0, 0xD3, 0xD3, 0xD3, 0xFB, - 0xFC, 0x40, 0x41, 0x45, 0xC4, 0xC0, 0xBE, 0xBE, - 0xC1, 0xC0, 0x3C, 0x47, 0x2E, 0x21, 0x22, 0x20, - 0x65, 0xFC, 0xFC, 0xFC, 0xFC, 0x6D, 0x72, 0x75, - 0x78, 0x76, 0x75, 0x79, 0x76, 0x76, 0x76, 0x76, - 0x75, 0x75, 0x75, 0x72, 0x6D, 0x2E, 0x48, 0x5D, - 0xCE, 0xD1, 0xD4, 0xD3, 0xCB, 0x56, 0x43, 0x2C, - 0x42, 0x43, 0x2E, 0x2E, 0x4A, 0x5D, 0x64, 0x64, - 0x50, 0x52, 0x56, 0x58, 0x5C, 0x5D, 0x5E, 0x5D, - 0x5A, 0x58, 0x58, 0x55, 0x61, 0x60, 0x58, 0x58, - 0x4E, 0x61, 0xD1, 0xD4, 0xD4, 0xD1, 0xEE, 0xFC, - 0xFC, 0x2B, 0x29, 0x2E, 0x3F, 0xB0, 0xAD, 0x81, - 0x46, 0x2D, 0x46, 0x2C, 0x24, 0x22, 0x22, 0x23, - 0x25, 0xFC, 0xFC, 0xFC, 0xFC, 0x6E, 0x73, 0x76, - 0x76, 0x79, 0x79, 0x79, 0x76, 0x76, 0x79, 0x76, - 0x79, 0x79, 0x79, 0x74, 0x3F, 0x41, 0x2C, 0x48, - 0x5F, 0xCF, 0xD5, 0xD7, 0xD6, 0xCD, 0x57, 0x40, - 0x2E, 0x3F, 0x44, 0x2E, 0x41, 0x4C, 0x60, 0x61, - 0x51, 0x53, 0x58, 0x5C, 0x5D, 0x5E, 0x5D, 0x5C, - 0x58, 0x57, 0x54, 0x5F, 0x5E, 0x55, 0x55, 0x52, - 0x64, 0xD4, 0xD5, 0xD4, 0xD1, 0x5D, 0xFA, 0xFB, - 0xF4, 0x21, 0x24, 0x41, 0x40, 0x44, 0x2E, 0x2E, - 0x42, 0x41, 0x2A, 0x24, 0x22, 0x22, 0x22, 0x22, - 0x23, 0xD9, 0xFC, 0xFC, 0xFC, 0xFC, 0xE5, 0xB8, - 0x8F, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F, - 0x8F, 0x8F, 0xB8, 0xE5, 0x3F, 0x3E, 0x43, 0x2C, - 0x48, 0x61, 0xD1, 0xD7, 0xD9, 0xD7, 0xD0, 0x57, - 0x41, 0x2E, 0x3E, 0x44, 0x2D, 0x40, 0x52, 0x5D, - 0x53, 0x55, 0x59, 0x5D, 0x5E, 0x5E, 0x5D, 0x5A, - 0x57, 0x53, 0x5E, 0x5E, 0x54, 0x53, 0x54, 0x65, - 0xD5, 0xD6, 0xD4, 0xCE, 0x53, 0xFB, 0xF9, 0xFC, - 0x24, 0x22, 0x23, 0x23, 0x41, 0x42, 0x2E, 0x40, - 0x2B, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x23, 0x23, 0xFC, 0xFC, 0xFC, 0xFC, 0xE7, 0xBD, - 0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x93, 0xB5, 0xC6, 0xEB, 0x2D, 0x47, 0x4A, 0x47, - 0x2C, 0x3E, 0x61, 0xD4, 0xDC, 0xDC, 0xDA, 0xCF, - 0x54, 0x41, 0x41, 0x3E, 0x45, 0x2C, 0x3F, 0x4A, - 0x58, 0x5A, 0x5C, 0x5F, 0x60, 0x5E, 0x5D, 0x57, - 0x51, 0x5D, 0x5D, 0x51, 0x53, 0x53, 0xCB, 0xD5, - 0xD6, 0xD5, 0x63, 0x55, 0xFC, 0xFC, 0xFC, 0x2C, - 0x23, 0x22, 0x23, 0x22, 0x20, 0x2D, 0x2C, 0x26, - 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x21, 0xF0, 0xFC, 0xFC, 0xFC, 0xE2, 0xC6, - 0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x93, 0x93, 0xC7, 0xE3, 0x3E, 0x2E, 0x49, 0x52, - 0x4C, 0x41, 0x44, 0x62, 0xD6, 0xDE, 0xDE, 0xD9, - 0xD0, 0x51, 0x2E, 0x40, 0x47, 0x44, 0x2C, 0x42, - 0x5D, 0x5D, 0x5F, 0x60, 0x60, 0x5D, 0x57, 0x51, - 0x58, 0x5D, 0x4E, 0x52, 0x55, 0x64, 0xD5, 0xD6, - 0xD4, 0x61, 0x59, 0x6B, 0xFC, 0xFC, 0xFC, 0x21, - 0x23, 0x22, 0x23, 0x22, 0x23, 0x21, 0x23, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x21, 0x24, 0xFC, 0xFC, 0xFC, 0xE2, 0xC7, - 0xB5, 0x90, 0x93, 0x93, 0x93, 0x90, 0x93, 0x93, - 0x90, 0xB5, 0xC8, 0xE4, 0x5F, 0x45, 0x2E, 0x4D, - 0x57, 0x57, 0x44, 0x43, 0x63, 0xDA, 0xDF, 0xDF, - 0xD9, 0xCE, 0x4C, 0x2C, 0x3F, 0x3E, 0x40, 0x40, - 0x60, 0x5E, 0x61, 0x61, 0x5E, 0x5B, 0x53, 0x52, - 0x5C, 0x52, 0x52, 0x55, 0x61, 0xD4, 0xD5, 0xD1, - 0x5E, 0x5B, 0x5C, 0xFB, 0xFC, 0xFC, 0x2A, 0x21, - 0x23, 0x22, 0x23, 0x22, 0x22, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x22, 0x22, 0xFB, 0xFC, 0xFC, 0xB3, 0xC8, - 0xB5, 0x90, 0x92, 0xB5, 0x93, 0x93, 0xB5, 0x93, - 0x92, 0xB5, 0xC8, 0xB9, 0xD0, 0x5E, 0x44, 0x40, - 0x52, 0x58, 0x57, 0x48, 0x40, 0x63, 0xD9, 0xE0, - 0xE0, 0xD9, 0xCB, 0x49, 0x2D, 0x3F, 0x45, 0x3F, - 0x63, 0x61, 0x62, 0x60, 0x5E, 0x55, 0x4D, 0x59, - 0x53, 0x4E, 0x54, 0x5D, 0xD2, 0xD4, 0xD2, 0x5E, - 0x5C, 0x5D, 0xFC, 0xFC, 0xFC, 0xF8, 0x29, 0x23, - 0x23, 0x23, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x23, 0x22, 0x22, 0x23, 0x23, 0x23, 0x22, 0x22, - 0x22, 0x22, 0x22, 0xF0, 0xFC, 0xFC, 0xB3, 0xC7, - 0xB5, 0x93, 0xB5, 0x93, 0x93, 0x91, 0x93, 0x93, - 0x91, 0xB5, 0xC7, 0xAD, 0xD6, 0xD2, 0x5E, 0x3F, - 0x3F, 0x57, 0x57, 0x58, 0x4A, 0x41, 0x64, 0xDC, - 0xF1, 0xDF, 0xDA, 0x61, 0x45, 0x2E, 0x43, 0x47, - 0xCB, 0x63, 0x62, 0x5F, 0x58, 0x51, 0x53, 0x54, - 0x4C, 0x52, 0x5C, 0xCD, 0xD3, 0xD2, 0x60, 0x5D, - 0x5D, 0xFB, 0xFC, 0xFC, 0xFC, 0xDB, 0x49, 0x24, - 0x21, 0x23, 0x23, 0x22, 0x26, 0x26, 0x2A, 0x24, - 0x22, 0x23, 0x22, 0x21, 0x24, 0x26, 0x26, 0x2A, - 0x29, 0x2B, 0x24, 0x25, 0xFC, 0xFC, 0xB3, 0xC5, - 0x91, 0x91, 0x92, 0x91, 0x92, 0x92, 0x93, 0x93, - 0x91, 0x93, 0xC6, 0xAD, 0xDC, 0xD9, 0xD4, 0x60, - 0x43, 0x45, 0x58, 0x58, 0x57, 0x4B, 0x43, 0xCC, - 0xDD, 0xF1, 0xD8, 0xD5, 0x5D, 0x43, 0x41, 0x47, - 0xCD, 0x63, 0x62, 0x5D, 0x54, 0x4C, 0x55, 0x4B, - 0x51, 0x58, 0x62, 0xD0, 0xD0, 0x62, 0x5D, 0x5D, - 0x67, 0xFC, 0xFC, 0xFC, 0xFC, 0x58, 0x4E, 0x28, - 0x2A, 0x20, 0x23, 0x22, 0x23, 0x2A, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x23, 0x25, 0x2A, 0x2E, 0x2D, - 0x2E, 0x2E, 0x2E, 0x23, 0xFA, 0xFC, 0xB2, 0xBD, - 0xB5, 0x90, 0x91, 0x93, 0x92, 0x90, 0x91, 0x93, - 0x92, 0x91, 0xBD, 0xAD, 0xDE, 0xE0, 0xD8, 0xD7, - 0x61, 0x40, 0x48, 0x58, 0x58, 0x58, 0x48, 0x44, - 0xCF, 0xDE, 0xE0, 0xDD, 0xD0, 0x52, 0x41, 0x45, - 0xCD, 0x63, 0x61, 0x58, 0x4D, 0x51, 0x4C, 0x4B, - 0x54, 0x5D, 0xCC, 0xCE, 0x63, 0x61, 0x5D, 0x5D, - 0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x27, 0x21, - 0x22, 0x22, 0x23, 0x22, 0x22, 0x24, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x20, - 0x27, 0x2B, 0x41, 0x2B, 0x23, 0xFC, 0xB2, 0xB6, - 0x93, 0x90, 0x92, 0xB5, 0x92, 0x90, 0xB5, 0x90, - 0x92, 0x93, 0xBC, 0xAD, 0xDC, 0xF1, 0xF3, 0xF0, - 0xD9, 0x61, 0x41, 0x4A, 0x58, 0x57, 0x57, 0x44, - 0x49, 0xD2, 0xDD, 0xD8, 0xDA, 0x63, 0x4A, 0x45, - 0xCC, 0x63, 0x5E, 0x52, 0x4B, 0x4C, 0x49, 0x51, - 0x5C, 0x61, 0xCD, 0x65, 0x63, 0x5E, 0x4E, 0xCF, - 0xFB, 0xFB, 0xF0, 0xFC, 0xD2, 0x2A, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x26, 0x41, 0x27, 0xF9, 0x81, 0xB7, - 0xB5, 0x91, 0x92, 0xB5, 0x91, 0xB5, 0x93, 0xB5, - 0x93, 0xB6, 0xB7, 0xB9, 0xCB, 0xD8, 0xF3, 0xF2, - 0xF2, 0xDB, 0x61, 0x2D, 0x51, 0x58, 0x57, 0x58, - 0x41, 0x51, 0xD4, 0xDB, 0xDC, 0xD1, 0x5B, 0x4C, - 0xCB, 0x62, 0x59, 0x4C, 0x4A, 0x49, 0x4B, 0x55, - 0x60, 0x64, 0xCC, 0x64, 0x5E, 0x55, 0x60, 0xE1, - 0xFB, 0xF8, 0xFC, 0xFC, 0x21, 0x22, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x21, 0x24, 0x2D, 0x21, 0xB4, 0xBB, - 0xB6, 0xB5, 0xB6, 0xB7, 0xB7, 0xB7, 0xB7, 0xB6, - 0xB6, 0xB6, 0xBB, 0xB9, 0x45, 0xCB, 0xDF, 0xF3, - 0xF3, 0xF3, 0xDB, 0x5E, 0x2C, 0x51, 0x58, 0x58, - 0x52, 0x2D, 0x5C, 0xD4, 0xD9, 0xD5, 0x63, 0x58, - 0x64, 0x60, 0x53, 0x49, 0x4A, 0x49, 0x52, 0x5C, - 0x63, 0xCD, 0xCD, 0x63, 0x5C, 0x4E, 0x65, 0xFC, - 0xFC, 0xF5, 0xFC, 0xD2, 0x23, 0x22, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x21, 0x22, 0x25, 0x29, 0xB3, 0xC7, - 0xB5, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, - 0xB6, 0xB5, 0xC7, 0xAD, 0x57, 0x3F, 0xCB, 0xF0, - 0xF3, 0xF3, 0xF2, 0xD9, 0x58, 0x41, 0x4C, 0x58, - 0x57, 0x47, 0x42, 0x62, 0xD4, 0xD4, 0xCC, 0x60, - 0x63, 0x5D, 0x50, 0x47, 0x48, 0x4B, 0x58, 0x60, - 0xCC, 0xCE, 0xCD, 0x60, 0x53, 0x5C, 0x62, 0xFB, - 0xF9, 0xFC, 0xFC, 0x21, 0x23, 0x22, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x23, 0x23, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0x81, 0xC7, - 0xB7, 0xB7, 0xBC, 0xB7, 0xBC, 0xBC, 0xBC, 0xB7, - 0xB7, 0xB7, 0xC8, 0x80, 0x58, 0x57, 0x40, 0xCE, - 0xF3, 0xF2, 0xF2, 0xF0, 0xD5, 0x4C, 0x3F, 0x4B, - 0x52, 0x50, 0x2D, 0x4B, 0x64, 0xD2, 0xCC, 0x61, - 0x60, 0x58, 0x4A, 0x47, 0x47, 0x4C, 0x59, 0x64, - 0xD0, 0xD0, 0x64, 0x59, 0x49, 0x5D, 0xFB, 0xFC, - 0xD9, 0xFC, 0xD6, 0x23, 0x22, 0x22, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x23, 0x21, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0xB4, 0xC8, - 0xBD, 0xB7, 0xBD, 0xBC, 0xBD, 0xC5, 0xBC, 0xC5, - 0xBC, 0xBD, 0xC7, 0xAC, 0x58, 0x57, 0x58, 0x2C, - 0xD1, 0xF0, 0xF3, 0xF3, 0xE0, 0xCD, 0x45, 0x3E, - 0x48, 0x4B, 0x3F, 0x41, 0x56, 0x64, 0x65, 0x62, - 0x5D, 0x52, 0x47, 0x48, 0x48, 0x53, 0x60, 0xCC, - 0xD2, 0xD0, 0x63, 0x52, 0x4E, 0x53, 0xFB, 0xFB, - 0xFC, 0xFC, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x23, 0x20, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, 0xB4, 0xC7, - 0xC5, 0xBC, 0xC5, 0xBD, 0xC5, 0xC5, 0xBD, 0xC5, - 0xBC, 0xC6, 0xC7, 0xB9, 0x58, 0x57, 0x58, 0x57, - 0x2D, 0xD4, 0xF1, 0xF2, 0xF0, 0xD9, 0x5D, 0x47, - 0x48, 0x3F, 0x42, 0x2C, 0x48, 0x5C, 0x5F, 0x60, - 0x58, 0x50, 0x47, 0x4A, 0x49, 0x55, 0x63, 0xD0, - 0xD2, 0xCD, 0x5D, 0x49, 0x4E, 0xE1, 0xFC, 0xF0, - 0xFC, 0xF8, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x20, 0x21, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22, - 0x23, 0x22, 0x23, 0x23, 0x23, 0x22, 0xC4, 0xC8, - 0xBD, 0xBD, 0xC6, 0xBD, 0xC6, 0xC6, 0xC5, 0xC6, - 0xBD, 0xC6, 0xC7, 0xE4, 0x54, 0x57, 0x58, 0x57, - 0x57, 0x43, 0xD7, 0xE0, 0xF1, 0xD8, 0xCD, 0x4B, - 0x4A, 0x47, 0x42, 0x2C, 0x3F, 0x4D, 0x58, 0x5C, - 0x52, 0x4B, 0x48, 0x4B, 0x4A, 0x58, 0xCB, 0xD3, - 0xD2, 0xCD, 0x58, 0x47, 0x4A, 0xFC, 0xFC, 0xFB, - 0xFC, 0x2B, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x26, 0x21, 0x21, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, - 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0xE5, 0xC8, - 0xBA, 0xC5, 0xC6, 0xC6, 0xC6, 0xC7, 0xC6, 0xC7, - 0xC5, 0xC6, 0xC8, 0xE5, 0x2E, 0x54, 0x58, 0x57, - 0x57, 0x4C, 0x4D, 0xDA, 0xD8, 0xD8, 0xD4, 0x5C, - 0x4B, 0x4B, 0x3F, 0x42, 0x44, 0x4A, 0x51, 0x58, - 0x4B, 0x48, 0x4B, 0x51, 0x4D, 0x5F, 0xD0, 0xD1, - 0xD0, 0x64, 0x51, 0x44, 0x6B, 0xFC, 0xFB, 0xFC, - 0xFC, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x26, 0x21, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, - 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0xE5, 0xED, - 0xE7, 0xBA, 0xC8, 0xC6, 0xC6, 0xC6, 0xC6, 0xC7, - 0xC7, 0xE5, 0xED, 0xE6, 0x61, 0x41, 0x52, 0x58, - 0x58, 0x57, 0x45, 0x5E, 0xD7, 0xDD, 0xD5, 0x60, - 0x4B, 0x4C, 0x48, 0x4D, 0x4D, 0x50, 0x4D, 0x56, - 0x4A, 0x3E, 0x53, 0x53, 0x52, 0x63, 0xD3, 0xD0, - 0xCE, 0x60, 0x4A, 0x45, 0xFC, 0xFC, 0xF7, 0xFC, - 0xFC, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23, - 0x22, 0x23, 0x21, 0x2A, 0x20, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x23, 0x22, 0x21, 0x23, 0xEB, 0xF6, - 0xF6, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, - 0xF6, 0xF6, 0xF6, 0xE6, 0xDB, 0x58, 0x45, 0x4B, - 0x58, 0x57, 0x4D, 0x4B, 0x64, 0xD4, 0xD0, 0x5C, - 0x48, 0x51, 0x4C, 0x5D, 0x5E, 0x5C, 0x56, 0x59, - 0x3E, 0x4A, 0x58, 0x54, 0x52, 0x65, 0xD3, 0xD0, - 0xCF, 0x5D, 0x48, 0xFC, 0xFC, 0xFC, 0xFA, 0xFC, - 0xFC, 0x21, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, - 0x22, 0x23, 0x21, 0x2A, 0x21, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x23, 0x22, 0x21, 0x4F, 0xE6, 0xC6, - 0xC6, 0xBD, 0xC6, 0xBD, 0xBD, 0xBD, 0xBD, 0xC6, - 0xC5, 0xBA, 0xC7, 0xE6, 0xF2, 0xD4, 0x49, 0x4B, - 0x3E, 0x4D, 0x52, 0x3E, 0x52, 0x63, 0x64, 0x56, - 0x48, 0x54, 0x4D, 0x61, 0xCC, 0xCC, 0x60, 0x60, - 0x47, 0x4D, 0x5C, 0x53, 0x58, 0xCF, 0xD1, 0xCF, - 0xD0, 0x59, 0x45, 0xFC, 0xFC, 0xFC, 0xEF, 0xF9, - 0xFC, 0x21, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, - 0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x23, 0x22, 0x23, 0x4F, 0xE4, 0xB9, - 0xAF, 0x80, 0x80, 0x8E, 0x8E, 0x8E, 0x8E, 0x8F, - 0x80, 0xB4, 0xB9, 0xE4, 0x7F, 0xDE, 0x61, 0x52, - 0x54, 0x48, 0x3F, 0x43, 0x4D, 0x56, 0x59, 0x4B, - 0x3E, 0x58, 0x53, 0x61, 0xD3, 0xD4, 0xCF, 0xCD, - 0x4C, 0x58, 0x5F, 0x53, 0x5E, 0xD3, 0xD0, 0xCE, - 0xCE, 0x52, 0x3F, 0xFC, 0xFC, 0xFC, 0xF7, 0x65, - 0xFA, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, - 0x23, 0x22, 0x21, 0x2A, 0x23, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x23, 0x22, 0x21, 0xB1, 0xE4, 0xE6, - 0x7C, 0xB1, 0x7C, 0xB1, 0xB2, 0xB2, 0xB3, 0x3D, - 0xB3, 0x3C, 0xE5, 0xB3, 0xB0, 0xF1, 0xD0, 0x58, - 0x5D, 0x4D, 0x40, 0x41, 0x48, 0x51, 0x4C, 0x3F, - 0x3F, 0x4D, 0x5A, 0x5A, 0xD5, 0xD9, 0xD7, 0xD4, - 0x57, 0x5E, 0x61, 0x4C, 0x63, 0xD4, 0xCF, 0xCE, - 0xCB, 0x4D, 0x4A, 0xFC, 0xFC, 0xFC, 0xFC, 0xF0, - 0xFB, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, - 0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x22, 0x23, 0x22, 0x23, 0x23, 0xB1, 0x81, 0x7D, - 0x39, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x7C, 0xB2, 0xB0, 0xDF, 0xD2, 0x57, - 0x60, 0x59, 0x5B, 0x59, 0x52, 0x4C, 0x4A, 0x40, - 0x42, 0x4A, 0x53, 0x4D, 0xD2, 0xDE, 0xDE, 0xD9, - 0x5E, 0x5E, 0x60, 0x4A, 0xCD, 0xD1, 0xCF, 0xCE, - 0x63, 0x49, 0x5C, 0xFB, 0xE8, 0x89, 0x9F, 0xFC, - 0xD6, 0x21, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22, - 0x23, 0x22, 0x21, 0x2A, 0x22, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x7F, 0xB9, - 0x71, 0x6C, 0x38, 0x38, 0x33, 0x33, 0x33, 0x38, - 0x38, 0x71, 0xAD, 0xE4, 0xD3, 0xDA, 0xCC, 0x52, - 0x63, 0x60, 0xCE, 0xD4, 0xCF, 0x60, 0x4C, 0x40, - 0x3F, 0x45, 0x4B, 0x5A, 0xCB, 0xD8, 0xDE, 0xDC, - 0x5E, 0x5E, 0x5F, 0x4C, 0xD2, 0xD2, 0xCF, 0xCF, - 0x61, 0x45, 0x5E, 0xA7, 0x9D, 0x95, 0x8B, 0x99, - 0xFC, 0x41, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22, - 0x23, 0x22, 0x23, 0x2A, 0x23, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x77, 0x77, 0xF6, - 0xFC, 0x7D, 0x7D, 0x7E, 0x7E, 0x7E, 0x7E, 0x7D, - 0x7D, 0xFC, 0x47, 0x64, 0xD0, 0xD0, 0x5D, 0x4B, - 0x62, 0xCC, 0xD1, 0xDE, 0xDE, 0xD4, 0x5E, 0x43, - 0x3F, 0x3E, 0x48, 0x53, 0x58, 0xDB, 0xD8, 0xDC, - 0x5E, 0x5E, 0x5E, 0x53, 0xD4, 0xD2, 0xD0, 0xD0, - 0x5E, 0x49, 0xA7, 0xA6, 0x89, 0x95, 0x8B, 0x9C, - 0x9C, 0xFB, 0xD4, 0x22, 0x22, 0x22, 0x22, 0x23, - 0x22, 0x23, 0x23, 0x2A, 0x22, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, - 0x23, 0x22, 0x23, 0x23, 0x98, 0x8C, 0x8C, 0x88, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, - 0xE9, 0x9C, 0x48, 0x5C, 0xD0, 0xCB, 0x48, 0x49, - 0x5B, 0xCB, 0xCD, 0xE0, 0xF1, 0xDD, 0xD0, 0x4A, - 0x41, 0x47, 0x45, 0x4C, 0x48, 0xD7, 0xDE, 0xDC, - 0x5E, 0x5E, 0x5A, 0x58, 0xD1, 0xD0, 0xD0, 0xD2, - 0x5C, 0x55, 0xA7, 0xA6, 0x87, 0x86, 0x89, 0x94, - 0x9C, 0xA9, 0xFC, 0xF4, 0x22, 0x23, 0x22, 0x23, - 0x22, 0x23, 0x22, 0x2A, 0x21, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, - 0x22, 0x23, 0x22, 0x23, 0xA4, 0x89, 0x8C, 0xAA, - 0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF7, - 0x85, 0x88, 0x8D, 0x59, 0x64, 0x63, 0x47, 0x3E, - 0x4C, 0x60, 0x61, 0xE0, 0xF0, 0xDF, 0xD9, 0x5D, - 0x2E, 0x3E, 0x3E, 0x47, 0x4D, 0xCD, 0xDE, 0xDC, - 0x5D, 0x5C, 0x51, 0x5D, 0xD1, 0xD2, 0xD2, 0xD4, - 0x5A, 0xBE, 0xA7, 0x98, 0x8A, 0x8A, 0xA0, 0x8B, - 0x86, 0x86, 0xF7, 0xFC, 0xF7, 0x26, 0x23, 0x23, - 0x22, 0x22, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, - 0x22, 0x21, 0x21, 0x21, 0xA1, 0x98, 0x9F, 0xBF, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xA7, - 0x8C, 0x86, 0x8D, 0x59, 0x5E, 0x5D, 0x3F, 0x3E, - 0x47, 0x53, 0x63, 0xD9, 0xF0, 0xF1, 0xDE, 0xD0, - 0x43, 0x3E, 0x47, 0x45, 0x4A, 0x5B, 0xDC, 0xDA, - 0x5D, 0x59, 0x49, 0x5F, 0xD1, 0xD2, 0xD3, 0xB9, - 0xA5, 0xA7, 0x98, 0x9B, 0x96, 0x9D, 0x89, 0x89, - 0x8B, 0x9C, 0x9D, 0xFC, 0xFC, 0xFC, 0x26, 0x22, - 0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, - 0x22, 0x22, 0x29, 0x2D, 0x99, 0x99, 0xA2, 0xAA, - 0xC4, 0xFB, 0xFC, 0xFC, 0xFC, 0xF6, 0xBF, 0xA2, - 0x9C, 0x9C, 0x8E, 0xDC, 0xCD, 0x51, 0x41, 0x3E, - 0x45, 0x49, 0x58, 0xCD, 0xE0, 0xE0, 0xD8, 0xDA, - 0x4C, 0x4A, 0x45, 0x45, 0x48, 0x47, 0xDA, 0xDA, - 0x5C, 0x58, 0x44, 0x69, 0xA9, 0x98, 0xA4, 0xA6, - 0xA1, 0xA4, 0x99, 0x9E, 0x9D, 0x8B, 0x8A, 0x97, - 0x87, 0x9A, 0x8A, 0xC2, 0xFC, 0xFC, 0xFC, 0x4D, - 0x21, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22, - 0x21, 0x22, 0x2D, 0x34, 0xA4, 0xA2, 0xA2, 0xA9, - 0xBF, 0xC0, 0xC3, 0xC1, 0xC0, 0xBE, 0xA6, 0x9D, - 0x99, 0x87, 0xA2, 0xF1, 0xDC, 0x64, 0x42, 0x45, - 0x47, 0x3E, 0x49, 0x4C, 0xDD, 0xDF, 0xD8, 0xDB, - 0x5E, 0x4C, 0x48, 0x45, 0x45, 0x41, 0xD1, 0xD6, - 0x5A, 0x55, 0x3F, 0xA7, 0xA1, 0x98, 0x9F, 0x99, - 0x9F, 0x9D, 0x9A, 0x95, 0x8B, 0x97, 0x89, 0x8A, - 0x88, 0x94, 0x9C, 0x8C, 0xFC, 0xFC, 0xFC, 0xFC, - 0xF4, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, - 0x23, 0x23, 0x2C, 0x2C, 0xA8, 0xA2, 0xA4, 0xA4, - 0xA9, 0xAA, 0xAA, 0xAA, 0xA9, 0xA6, 0x98, 0x9C, - 0x8B, 0x88, 0x98, 0x8D, 0xD8, 0xD6, 0x4E, 0x47, - 0x47, 0x49, 0x47, 0x3F, 0xDA, 0xDD, 0xDE, 0xDD, - 0xCC, 0x4A, 0x4B, 0x3E, 0x45, 0x43, 0x61, 0xD4, - 0x56, 0x51, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0x9A, - 0xA0, 0xA2, 0x98, 0x98, 0x8B, 0x8B, 0x98, 0x98, - 0x84, 0x8B, 0x94, 0x8A, 0xA4, 0xFC, 0xFC, 0xFC, - 0xFC, 0xF2, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x23, - 0x23, 0x22, 0x2C, 0x2D, 0xC0, 0xA4, 0xA2, 0xA4, - 0xA4, 0xA6, 0xA6, 0xA6, 0xA4, 0xA2, 0x9F, 0x89, - 0x8B, 0x9C, 0x9C, 0x8B, 0x68, 0xDB, 0x5F, 0x4B, - 0x3E, 0x49, 0x4B, 0x3E, 0xCC, 0xDA, 0xDC, 0xDD, - 0xD3, 0x49, 0x52, 0x48, 0x45, 0x45, 0x53, 0xD0, - 0x51, 0x4A, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0xA0, - 0x9B, 0x86, 0x89, 0x98, 0x89, 0x8A, 0x96, 0x8A, - 0x9C, 0x89, 0x89, 0x9C, 0x8C, 0xF6, 0xFC, 0xFC, - 0xFC, 0xFC, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23, - 0x22, 0x21, 0x2B, 0x34, 0xC0, 0xA8, 0xA4, 0xA2, - 0xA2, 0x98, 0xA1, 0xA0, 0x98, 0x9F, 0x95, 0x8A, - 0x94, 0xA1, 0x8A, 0x84, 0x9B, 0x68, 0xCC, 0x49, - 0x4A, 0x47, 0x4C, 0x4B, 0x51, 0xD3, 0xDA, 0xDC, - 0xD5, 0x56, 0x56, 0x4A, 0x3E, 0x45, 0x48, 0x63, - 0x4A, 0x47, 0x3E, 0xA7, 0x98, 0x9D, 0x9E, 0x8B, - 0x95, 0x9B, 0x89, 0x86, 0x9B, 0x8B, 0x89, 0x84, - 0x9A, 0xA1, 0x95, 0x9A, 0x8C, 0xA4, 0xFC, 0xFC, - 0xFC, 0xFA, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23, - 0x21, 0x23, 0x2C, 0xF6, 0xBF, 0xA9, 0xA2, 0x99, - 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9B, 0x87, 0x8B, - 0x9C, 0x86, 0x9C, 0x8A, 0x87, 0x87, 0x89, 0x51, - 0x54, 0x47, 0x4B, 0x50, 0x4B, 0xCF, 0xD6, 0xDC, - 0xD5, 0x60, 0x54, 0x52, 0x48, 0x45, 0x40, 0x5A, - 0x45, 0x43, 0x47, 0xA7, 0x98, 0x9B, 0x95, 0x95, - 0x9A, 0x87, 0x98, 0x98, 0x8A, 0x86, 0x87, 0x9E, - 0x9B, 0x95, 0x9D, 0x9D, 0x99, 0x85, 0xA6, 0xFA, - 0xF2, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x22, - 0x21, 0x24, 0xFB, 0xF7, 0xBF, 0xA6, 0xA2, 0x99, - 0x97, 0x89, 0x86, 0x89, 0x9C, 0x96, 0x9E, 0x94, - 0x89, 0x99, 0x98, 0x89, 0x9E, 0x9B, 0x89, 0x8B, - 0x58, 0x4B, 0x4A, 0x52, 0x48, 0xCC, 0xD3, 0xDA, - 0xD3, 0x65, 0x4C, 0x58, 0x49, 0x3E, 0x2E, 0x4D, - 0x40, 0x41, 0x45, 0xA9, 0xA1, 0x9B, 0x9E, 0x9C, - 0x95, 0x8A, 0x94, 0x89, 0x96, 0x87, 0x9C, 0x9A, - 0x84, 0x9D, 0x9C, 0x9E, 0x9A, 0x9C, 0x9D, 0xBB, - 0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x23, 0x23, - 0x24, 0xFC, 0xFC, 0xF6, 0xBF, 0xA6, 0x9F, 0x99, - 0x89, 0x95, 0x87, 0x94, 0x9D, 0x9E, 0x97, 0x9E, - 0x95, 0x9B, 0x89, 0x95, 0x95, 0x9B, 0x89, 0x87, - 0x5D, 0x56, 0x3E, 0x51, 0x3E, 0x60, 0xCF, 0xD3, - 0xD2, 0xCD, 0x5C, 0x49, 0x4B, 0x3E, 0x2C, 0x48, - 0x3E, 0x43, 0x3E, 0xA9, 0xA1, 0x9B, 0x97, 0x94, - 0x95, 0x9A, 0x9C, 0x87, 0x87, 0x9B, 0x9C, 0x95, - 0x9D, 0x89, 0x9A, 0x89, 0x9E, 0x9E, 0x8C, 0xA6, - 0x20, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x21, 0x21, 0x20, 0x40, - 0xFC, 0xFC, 0xFC, 0xEC, 0xBE, 0xA4, 0x9F, 0x99, - 0x95, 0x9F, 0xA0, 0x88, 0x9D, 0x8B, 0x97, 0x95, - 0x87, 0x95, 0x96, 0x95, 0x97, 0x94, 0x94, 0x98, - 0xD3, 0x4C, 0x47, 0x4D, 0x42, 0x4C, 0x60, 0xCC, - 0xCE, 0xD0, 0x65, 0x4B, 0x47, 0x44, 0x2B, 0x45, - 0x4B, 0x47, 0x49, 0xA7, 0xA1, 0x9A, 0x97, 0x89, - 0x95, 0x97, 0x97, 0x9E, 0x89, 0x95, 0x89, 0x9C, - 0x87, 0x95, 0x97, 0x99, 0x95, 0x99, 0x9F, 0xA4, - 0xC4, 0x21, 0x21, 0x23, 0x21, 0x23, 0x23, 0x23, - 0x23, 0x23, 0x23, 0x23, 0x21, 0x20, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xEA, 0xAA, 0xA6, 0xA2, 0x99, - 0x8B, 0x9A, 0x95, 0x9E, 0x9E, 0x9A, 0x94, 0x87, - 0x94, 0x94, 0x89, 0x94, 0x9B, 0x9B, 0xA7, 0xDC, - 0xDB, 0x65, 0x2E, 0x3E, 0x43, 0x44, 0x49, 0x58, - 0x63, 0xD3, 0xD3, 0x5E, 0x42, 0x42, 0x2D, 0x40, - 0x54, 0x4C, 0x4A, 0xA7, 0xA0, 0x99, 0x9B, 0x94, - 0xA0, 0x8A, 0x9B, 0x9D, 0x87, 0x95, 0x94, 0x8B, - 0x8A, 0x98, 0x9C, 0x8A, 0x9B, 0x99, 0xA2, 0xA6, - 0xBF, 0xEC, 0x2A, 0x20, 0x21, 0x23, 0x21, 0x20, - 0x20, 0x20, 0x20, 0x4C, 0xF9, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xEB, 0xAA, 0xA4, 0x9F, 0x9C, - 0x8B, 0x9B, 0x88, 0x84, 0x9E, 0x9D, 0x96, 0x94, - 0x94, 0x9A, 0x9B, 0x9B, 0xA4, 0xD5, 0xCD, 0xDE, - 0xF1, 0xDA, 0x4C, 0x2D, 0x41, 0x2B, 0x42, 0x4C, - 0x5E, 0xD4, 0xD7, 0xCD, 0x49, 0x2E, 0x2E, 0x41, - 0x5E, 0x57, 0xA7, 0xA6, 0xA7, 0xA4, 0xA2, 0x98, - 0x9D, 0x9C, 0xA1, 0x99, 0x9D, 0x88, 0x8B, 0x9C, - 0x8A, 0x9C, 0x9C, 0x94, 0x9C, 0x89, 0xA0, 0xA6, - 0xAA, 0xEB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFB, 0xE9, 0xAA, 0xA6, 0xA2, 0x8B, - 0x8B, 0x8A, 0x86, 0x9B, 0x9C, 0x98, 0xA0, 0x9B, - 0x9B, 0x84, 0xA7, 0xB4, 0x61, 0xD1, 0xD2, 0xE0, - 0xF1, 0xDC, 0x61, 0x2D, 0x2E, 0x3F, 0x56, 0x62, - 0x5D, 0xD4, 0xD9, 0xD3, 0x54, 0x41, 0x41, 0x44, - 0xCB, 0x60, 0x52, 0xA9, 0xA9, 0xA9, 0xA7, 0xA6, - 0xA6, 0xA4, 0xA4, 0xA2, 0xA2, 0x9D, 0x95, 0x89, - 0x9C, 0x8A, 0x9E, 0x9C, 0x8A, 0x9E, 0xA0, 0xA8, - 0xC0, 0xE9, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xE9, 0xAA, 0xA6, 0xA0, 0x99, - 0x9C, 0x8B, 0x9A, 0x84, 0x9B, 0x9B, 0x98, 0x98, - 0xA9, 0xB9, 0x49, 0x57, 0xCB, 0xD4, 0xD3, 0xF1, - 0xD8, 0xDA, 0xCE, 0x3F, 0x41, 0x4B, 0x5D, 0xCB, - 0x5E, 0xD6, 0xDB, 0xD6, 0x5D, 0x43, 0x3F, 0x49, - 0xD1, 0xCC, 0x4F, 0xDD, 0xC3, 0xBB, 0xBF, 0xAA, - 0xAA, 0xA9, 0xAA, 0xA8, 0xA8, 0xA6, 0xA6, 0xA2, - 0x9C, 0x9F, 0x9B, 0x9A, 0x9D, 0xA2, 0xA8, 0xAA, - 0xC1, 0xEA, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xEA, 0xC0, 0xAA, 0xA6, 0xA2, - 0xA2, 0x99, 0xA0, 0xA0, 0xA4, 0xA7, 0xA9, 0xC0, - 0x67, 0x49, 0x54, 0x60, 0xD0, 0xD4, 0xCC, 0xDF, - 0xD9, 0xD5, 0xD2, 0x3E, 0x47, 0x56, 0x60, 0xCD, - 0x5D, 0xD9, 0xD9, 0xD6, 0x61, 0x3F, 0x47, 0x52, - 0xD6, 0xD3, 0x62, 0x4D, 0x40, 0x4A, 0x57, 0xCA, - 0xC3, 0xC1, 0xC1, 0xC0, 0xBF, 0xBF, 0xAA, 0xAA, - 0xA6, 0xA4, 0xA4, 0xA4, 0xA6, 0xA8, 0xBE, 0xC1, - 0xC9, 0xEB, 0xFB, 0xFB, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xEB, 0xC3, 0xC0, 0xAA, 0xA8, - 0xA6, 0xA6, 0xA6, 0xA9, 0xAA, 0xC0, 0xE8, 0xD0, - 0xD2, 0x4C, 0x5E, 0x64, 0xD0, 0xD1, 0x5F, 0xD9, - 0xD5, 0xD1, 0xD0, 0x48, 0x52, 0x5C, 0x64, 0xCD, - 0x5C, 0xDC, 0xD7, 0xD5, 0x62, 0x3F, 0x4C, 0x53, - 0xDA, 0xD7, 0xCE, 0x56, 0x40, 0x4B, 0x52, 0x56, - 0xCE, 0xDF, 0x6A, 0xEB, 0xE9, 0xC9, 0xC3, 0xC0, - 0xC0, 0xBF, 0xBE, 0xAA, 0xBF, 0xC0, 0xC3, 0xC9, - 0xEA, 0xF6, 0xEE, 0x58, 0x57, 0x5E, 0xD6, 0xD0, - 0xD2, 0x61, 0xCB, 0xD6, 0xD6, 0xD4, 0xDF, 0xF3, - 0xF2, 0xDD, 0xD7, 0xEB, 0xC9, 0xC1, 0xC0, 0xBF, - 0xAA, 0xAA, 0xAA, 0xBE, 0xC3, 0xF0, 0xD2, 0xD2, - 0xD2, 0x51, 0x62, 0xCC, 0xD0, 0xCC, 0x61, 0xD3, - 0xCF, 0xCE, 0xD2, 0x48, 0x5A, 0x61, 0xCC, 0xCE, - 0x5F, 0xD9, 0xD5, 0xD1, 0x63, 0x44, 0x56, 0x56, - 0xDC, 0xD9, 0xD4, 0x5E, 0x42, 0x4A, 0x4C, 0x57, - 0x5D, 0xD8, 0xE0, 0xD8, 0xDC, 0xCB, 0x66, 0xEC, - 0xE8, 0xC3, 0xC3, 0xC3, 0xC3, 0xC9, 0xE8, 0xEA, - 0xF6, 0x50, 0x3E, 0x58, 0x57, 0x5A, 0xD6, 0xD4, - 0xCC, 0x4B, 0x53, 0x5C, 0x64, 0xD1, 0xDF, 0xF3, - 0xF1, 0xDE, 0xD9, 0xF6, 0xEB, 0xC9, 0xC1, 0xC1, - 0xC0, 0xC0, 0xC1, 0xC9, 0xF0, 0xD6, 0xCD, 0xD6, - 0xD3, 0x53, 0xCB, 0xCF, 0xCD, 0x5F, 0x5F, 0xCE, - 0xCF, 0xCD, 0xD0, 0x47, 0x5F, 0xCB, 0xCE, 0xCD, - 0x63, 0xD6, 0xD3, 0xD1, 0x63, 0x3F, 0x58, 0x58, - 0xDB, 0xDC, 0xDA, 0x65, 0x3E, 0x49, 0x49, 0x4D, - 0x49, 0xDC, 0xDF, 0xE0, 0xDE, 0xD5, 0x47, 0x47, - 0x46, 0x6B, 0xEB, 0xEA, 0xE9, 0xEA, 0xEB, 0xF6, - 0xD0, 0x57, 0x57, 0x47, 0x47, 0x5B, 0xD4, 0xD4, - 0xCD, 0x44, 0x3E, 0x4B, 0x50, 0x4B, 0x51, 0xD5, - 0xDB, 0xD8, 0xDE, 0x4B, 0xF6, 0xF6, 0xEA, 0xE9, - 0xE8, 0xEA, 0xEB, 0x67, 0x5E, 0xCC, 0xD6, 0xDC, - 0xD5, 0x58, 0xCE, 0xCE, 0x62, 0x50, 0xCC, 0xD3, - 0xD2, 0xCD, 0xCD, 0x4B, 0x64, 0xCE, 0xCE, 0x64, - 0xCC, 0xD3, 0xD2, 0xD2, 0x61, 0x47, 0x5D, 0x5C, - 0xDD, 0xDD, 0xD9, 0xD1, 0x4C, 0x47, 0x49, 0x4A, - 0x4B, 0xD1, 0xD8, 0xE0, 0xDF, 0xDD, 0x5D, 0x4A, - 0x48, 0x52, 0x51, 0x3F, 0xF6, 0xEC, 0xE0, 0xE0, - 0xD3, 0x5E, 0x5F, 0x50, 0x4B, 0x50, 0xCB, 0xCE, - 0x64, 0x45, 0x4C, 0x57, 0x57, 0x58, 0x52, 0xD6, - 0xD3, 0xDE, 0xDF, 0xD1, 0x3E, 0x4B, 0xF6, 0xF6, - 0xEC, 0x66, 0x53, 0x43, 0x56, 0xD1, 0xD9, 0xDE, - 0xD4, 0x5E, 0xCE, 0xCC, 0x5B, 0x2C, 0xD4, 0xD5, - 0xD2, 0xD0, 0x63, 0x5D, 0xCD, 0xD0, 0xCD, 0x5E, - 0xD0, 0xCF, 0xCE, 0xD2, 0x5E, 0x50, 0x60, 0x5D, - 0xDE, 0xDD, 0xDC, 0xD7, 0x5D, 0x45, 0x47, 0x3E, - 0x4B, 0x5E, 0xDE, 0xDF, 0xE0, 0xD8, 0xCF, 0x3E, - 0x45, 0x51, 0x58, 0x42, 0xCB, 0xDA, 0xDE, 0xD8, - 0xD2, 0x61, 0xCC, 0xCF, 0xD6, 0xDA, 0xDA, 0xD5, - 0xD0, 0x50, 0x44, 0x57, 0x57, 0x58, 0x45, 0xD1, - 0xD1, 0xD7, 0xDF, 0xDF, 0xD7, 0xCF, 0x64, 0x60, - 0xCE, 0xCE, 0xCE, 0x63, 0xCF, 0xDA, 0xDE, 0xD9, - 0xCF, 0x63, 0xCD, 0x63, 0x4D, 0x4B, 0xD6, 0xD5, - 0xCE, 0xD3, 0x60, 0xCB, 0xD0, 0xD0, 0x65, 0x47, - 0xD0, 0xCC, 0xCC, 0xD1, 0x59, 0x5D, 0x63, 0x5E, - 0xDD, 0xDD, 0xDE, 0xDC, 0xCB, 0x40, 0x48, 0x45, - 0x3E, 0x3E, 0xD9, 0xDF, 0xE0, 0xDF, 0xDA, 0x51, - 0x4C, 0x48, 0x56, 0x4C, 0x5B, 0xD2, 0xDA, 0xDB, - 0xCB, 0x5F, 0xD0, 0xCC, 0xDC, 0xF0, 0xF3, 0xE0, - 0xDD, 0xCC, 0x41, 0x50, 0x57, 0x57, 0x4B, 0x5D, - 0xD3, 0xD1, 0xDE, 0xDF, 0xDE, 0xD7, 0xD0, 0xD0, - 0xD5, 0xD6, 0xD6, 0xCE, 0xD7, 0xDC, 0xDA, 0xD5, - 0x60, 0x63, 0x64, 0x5E, 0x47, 0x61, 0xD5, 0xD2, - 0xCF, 0xD0, 0x59, 0xCD, 0xD1, 0xCF, 0x61, 0x4D, - 0xCC, 0xCE, 0xCD, 0xD0, 0x52, 0x61, 0x64, 0x60, - 0xDA, 0xDE, 0xDE, 0xDD, 0xD1, 0x4B, 0x4A, 0x45, - 0x3E, 0x41, 0xCD, 0xDE, 0xE0, 0xF1, 0xDE, 0x63, - 0x4A, 0x4A, 0x4A, 0x4B, 0x50, 0xCB, 0xD4, 0xD7, - 0x5E, 0x54, 0x62, 0xD3, 0xD4, 0xF0, 0xF3, 0xF3, - 0xF2, 0xDE, 0x61, 0x40, 0x49, 0x56, 0x4D, 0x3E, - 0x4B, 0xCE, 0xD9, 0xD8, 0xD9, 0xD5, 0xCF, 0xD2, - 0xD6, 0xD6, 0xD1, 0xD1, 0xD7, 0xD5, 0xCF, 0xD0, - 0x54, 0x64, 0x63, 0x56, 0x2C, 0xCB, 0xD1, 0xCC, - 0xD3, 0xCD, 0x54, 0xCF, 0xD1, 0xCE, 0x5E, 0x5C, - 0xCE, 0xCE, 0xCE, 0xCB, 0x4B, 0x63, 0xCC, 0x61, - 0xD4, 0xDC, 0xDE, 0xDE, 0xDA, 0x5D, 0x45, 0x45, - 0x48, 0x3F, 0x52, 0xD9, 0xD8, 0xDF, 0xDF, 0xD2, - 0x52, 0x4B, 0x3E, 0x2E, 0x47, 0x60, 0xCF, 0xD3, - 0x59, 0x48, 0x50, 0x5E, 0xCC, 0xDE, 0xF2, 0xF2, - 0xF3, 0xF3, 0xDD, 0x5D, 0x3E, 0x48, 0x47, 0x47, - 0x58, 0xD1, 0xDA, 0xDA, 0xD5, 0xD1, 0xCD, 0xD2, - 0xD3, 0xCF, 0xD3, 0xD1, 0xCD, 0xD3, 0xD2, 0x5E, - 0x52, 0x64, 0x60, 0x4B, 0x45, 0x61, 0xCD, 0xD3, - 0xD3, 0x64, 0x61, 0xD0, 0xD0, 0x64, 0x45, 0x63, - 0xD0, 0xCE, 0xD0, 0x60, 0x56, 0xCB, 0xCC, 0x62, - 0xCE, 0xDA, 0xDE, 0xD8, 0xDD, 0xCC, 0x45, 0x49, - 0x3E, 0x47, 0x42, 0xD1, 0xDC, 0xD8, 0xD8, 0xD3, - 0x5D, 0x4C, 0x49, 0x3F, 0x47, 0x59, 0xCD, 0xCF, - 0x59, 0x2E, 0x48, 0x47, 0x52, 0x63, 0xF0, 0xF2, - 0xF3, 0xF3, 0xF2, 0xDA, 0x52, 0x4B, 0x52, 0x58, - 0x5E, 0x63, 0xD0, 0xD0, 0xD0, 0xCF, 0xCE, 0xCE, - 0xCF, 0x65, 0x61, 0xD6, 0xD6, 0xD6, 0xCB, 0x4B, - 0x61, 0x62, 0x5D, 0x43, 0x4B, 0x61, 0xD0, 0xD4, - 0xD1, 0x61, 0xCE, 0xD2, 0xCD, 0x5E, 0x4A, 0xCE, - 0xD0, 0xCC, 0xD0, 0x59, 0x61, 0xCC, 0xCC, 0x62, - 0xD1, 0xD5, 0xDE, 0xD8, 0xDD, 0xCF, 0x4B, 0x4A, - 0x45, 0x3E, 0x2D, 0xCB, 0xDC, 0xDE, 0xD8, 0xD5, - 0x60, 0x54, 0x51, 0x4C, 0x4D, 0x5C, 0xCC, 0xCE, - 0x5A, 0x2C, 0x50, 0x53, 0x3E, 0x59, 0xD8, 0xF3, - 0xF2, 0xF3, 0xF3, 0xE0, 0x5E, 0x4A, 0x4C, 0x53, - 0x5E, 0x63, 0xCC, 0xCC, 0xCC, 0xCD, 0xCF, 0xD3, - 0x62, 0x53, 0xD6, 0xD6, 0xD6, 0xD6, 0x5B, 0x48, - 0x64, 0x63, 0x59, 0x44, 0x57, 0x63, 0xD2, 0xD3, - 0xD0, 0x5E, 0xD0, 0xD1, 0xCB, 0x58, 0x4C, 0xCF, - 0xCF, 0xCE, 0xCE, 0x57, 0x63, 0xCC, 0xCD, 0x57, -}; - diff -u --recursive --new-file v2.4.5/linux/drivers/sound/Config.in linux/drivers/sound/Config.in --- v2.4.5/linux/drivers/sound/Config.in Wed Apr 18 11:49:11 2001 +++ linux/drivers/sound/Config.in Mon Jul 2 14:03:04 2001 @@ -81,6 +81,7 @@ fi dep_tristate ' VIA 82C686 Audio Codec' CONFIG_SOUND_VIA82CXXX $CONFIG_PCI +dep_mbool ' VIA 82C686 MIDI' CONFIG_MIDI_VIA82CXXX $CONFIG_SOUND_VIA82CXXX dep_tristate ' OSS sound modules' CONFIG_SOUND_OSS $CONFIG_SOUND diff -u --recursive --new-file v2.4.5/linux/drivers/sound/Makefile linux/drivers/sound/Makefile --- v2.4.5/linux/drivers/sound/Makefile Fri Apr 13 20:26:07 2001 +++ linux/drivers/sound/Makefile Mon Jul 2 14:03:04 2001 @@ -47,6 +47,9 @@ obj-$(CONFIG_SOUND_AWE32_SYNTH) += awe_wave.o obj-$(CONFIG_SOUND_VIA82CXXX) += via82cxxx_audio.o ac97_codec.o +ifeq ($(CONFIG_MIDI_VIA82CXXX),y) + obj-$(CONFIG_SOUND_VIA82CXXX) += sound.o uart401.o +endif obj-$(CONFIG_SOUND_YMFPCI) += ymfpci.o ac97_codec.o ifeq ($(CONFIG_SOUND_YMFPCI_LEGACY),y) obj-$(CONFIG_SOUND_YMFPCI) += opl3.o uart401.o diff -u --recursive --new-file v2.4.5/linux/drivers/sound/aci.c linux/drivers/sound/aci.c --- v2.4.5/linux/drivers/sound/aci.c Fri Apr 13 20:26:07 2001 +++ linux/drivers/sound/aci.c Tue Jun 12 10:56:11 2001 @@ -45,6 +45,8 @@ * ioctl bugfix, and integration of solo-mode into OSS-API, * added (OSS-limited) equalizer support, return value bugfix, * changed param aci_reset to reset, new params: ide, wss. + * 2001-04-20 Robert Siemer + * even more cleanups... */ #include @@ -95,17 +97,19 @@ MODULE_PARM_DESC(wss,"change between ACI/WSS-mixer; use 0 and 1 - untested" " default: do nothing; for PCM1-pro only"); +#if DEBUG static void print_bits(unsigned char c) { int j; printk(KERN_DEBUG "aci: "); for (j=7; j>=0; j--) { - printk(KERN_DEBUG "%d", (c >> j) & 0x1); + printk("%d", (c >> j) & 0x1); } - printk(KERN_DEBUG "\n"); + printk("\n"); } +#endif /* * This busy wait code normally requires less than 15 loops and @@ -269,12 +273,12 @@ int buf; /* left channel */ - if ((buf=aci_indexed_cmd(0xf0, left_index))<0) + if ((buf=aci_indexed_cmd(ACI_STATUS, left_index))<0) return buf; vol = SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0); /* right channel */ - if ((buf=aci_indexed_cmd(0xf0, right_index))<0) + if ((buf=aci_indexed_cmd(ACI_STATUS, right_index))<0) return buf; vol |= SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0) << 8; @@ -342,12 +346,12 @@ unsigned int vol; /* left channel */ - if ((buf=aci_indexed_cmd(0xf0, left_index))<0) + if ((buf=aci_indexed_cmd(ACI_STATUS, left_index))<0) return buf; vol = eq_aci2oss(buf); /* right channel */ - if ((buf=aci_indexed_cmd(0xf0, right_index))<0) + if ((buf=aci_indexed_cmd(ACI_STATUS, right_index))<0) return buf; vol |= eq_aci2oss(buf) << 8; @@ -399,7 +403,7 @@ if (vol > 100) vol = 100; vol = SCALE(100, 3, vol); - if ((buf=aci_write_cmd(0x03, vol))<0) + if ((buf=aci_write_cmd(ACI_WRITE_IGAIN, vol))<0) return buf; aci_micpreamp = vol; vol = SCALE(3, 100, vol); @@ -416,7 +420,7 @@ vol = 1; else vol = 0; - if ((buf=aci_write_cmd(0x0f, vol))<0) + if ((buf=aci_write_cmd(ACI_SET_POWERAMP, vol))<0) return buf; aci_amp = vol; if (aci_amp) @@ -433,7 +437,7 @@ /* unset solo when RECSRC for PCM is requested */ if (aci_idcode[1]=='B' || aci_idcode[1]=='C') { vol = !(buf & SOUND_MASK_PCM); - if ((buf=aci_write_cmd(0xd2, vol))<0) + if ((buf=aci_write_cmd(ACI_SET_SOLOMODE, vol))<0) return buf; aci_solo = vol; } @@ -502,7 +506,8 @@ case 'B': /* PCM12 */ case 'C': /* PCM20 radio */ if (aci_version >= 0xb0) { - if ((vol=aci_rw_cmd(0xf0, 0x00, -1))<0) + if ((vol=aci_rw_cmd(ACI_STATUS, + ACI_S_GENERAL, -1))<0) return vol; if (vol & 0x20) buf |= SOUND_MASK_PCM; @@ -555,7 +560,8 @@ if (aci_idcode[1]=='B' || aci_idcode[1]=='C') { /* aci_micpreamp or ACI? */ if (aci_version >= 0xb0) { - if ((buf=aci_indexed_cmd(0xf0, 0x21))<0) + if ((buf=aci_indexed_cmd(ACI_STATUS, + ACI_S_READ_IGAIN))<0) return buf; } else @@ -612,17 +618,17 @@ /* force ACI into a known state */ for (i=0; i<3; i++) - if (aci_rw_cmd(0xdf, -1, -1)<0) + if (aci_rw_cmd(ACI_ERROR_OP, -1, -1)<0) return -EFAULT; /* official this is one aci read call: */ - if ((aci_idcode[0]=aci_rw_cmd(0xf2, -1, -1))<0 || - (aci_idcode[1]=aci_rw_cmd(0xf2, -1, -1))<0) { + if ((aci_idcode[0]=aci_rw_cmd(ACI_READ_IDCODE, -1, -1))<0 || + (aci_idcode[1]=aci_rw_cmd(ACI_READ_IDCODE, -1, -1))<0) { printk(KERN_ERR "aci: Failed to read idcode on 0x%03x.\n", aci_port); return -EFAULT; } - if ((aci_version=aci_rw_cmd(0xf1, -1, -1))<0) { + if ((aci_version=aci_rw_cmd(ACI_READ_VERSION, -1, -1))<0) { printk(KERN_ERR "aci: Failed to read version on 0x%03x.\n", aci_port); return -EFAULT; } @@ -656,22 +662,22 @@ if (reset) { /* first write()s after reset fail with my PCM20 */ - if (aci_rw_cmd(0xff, -1, -1)<0 || - aci_rw_cmd(0xdf, 0xdf, 0xdf)<0 || - aci_rw_cmd(0xdf, 0xdf, 0xdf)<0) + if (aci_rw_cmd(ACI_INIT, -1, -1)<0 || + aci_rw_cmd(ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP)<0 || + aci_rw_cmd(ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP)<0) return -EBUSY; } /* the PCM20 is muted after reset (and reboot) */ - if (aci_rw_cmd(0x0d, 0x00, -1)<0) + if (aci_rw_cmd(ACI_SET_MUTE, 0x00, -1)<0) return -EBUSY; if (ide>=0) - if (aci_rw_cmd(0xd0, !ide, -1)<0) + if (aci_rw_cmd(ACI_SET_IDE, !ide, -1)<0) return -EBUSY; if (wss>=0 && aci_idcode[1]=='A') - if (aci_rw_cmd(0xd1, !!wss, -1)<0) + if (aci_rw_cmd(ACI_SET_WSS, !!wss, -1)<0) return -EBUSY; if (!request_region(aci_port, 3, "sound mixer (ACI)")) diff -u --recursive --new-file v2.4.5/linux/drivers/sound/aci.h linux/drivers/sound/aci.h --- v2.4.5/linux/drivers/sound/aci.h Fri Apr 13 20:26:07 2001 +++ linux/drivers/sound/aci.h Tue Jun 12 10:56:11 2001 @@ -6,9 +6,6 @@ extern int aci_version; /* ACI firmware version */ extern int aci_rw_cmd(int write1, int write2, int write3); -extern char * aci_radio_name; -extern int aci_rds_cmd(unsigned char cmd, unsigned char databuffer[], int datasize); - #define aci_indexed_cmd(a, b) aci_rw_cmd(a, b, -1) #define aci_write_cmd(a, b) aci_rw_cmd(a, b, -1) #define aci_read_cmd(a) aci_rw_cmd(a,-1, -1) @@ -19,15 +16,24 @@ #define RDS_REGISTER BUSY_REGISTER -#define RDS_STATUS 0x01 -#define RDS_STATIONNAME 0x02 -#define RDS_TEXT 0x03 -#define RDS_ALTFREQ 0x04 -#define RDS_TIMEDATE 0x05 -#define RDS_PI_CODE 0x06 -#define RDS_PTYTATP 0x07 -#define RDS_RESET 0x08 -#define RDS_RXVALUE 0x09 +#define ACI_SET_MUTE 0x0d +#define ACI_SET_POWERAMP 0x0f +#define ACI_SET_TUNERMUTE 0xa3 +#define ACI_SET_TUNERMONO 0xa4 +#define ACI_SET_IDE 0xd0 +#define ACI_SET_WSS 0xd1 +#define ACI_SET_SOLOMODE 0xd2 +#define ACI_WRITE_IGAIN 0x03 +#define ACI_WRITE_TUNE 0xa7 +#define ACI_READ_TUNERSTEREO 0xa8 +#define ACI_READ_TUNERSTATION 0xa9 +#define ACI_READ_VERSION 0xf1 +#define ACI_READ_IDCODE 0xf2 +#define ACI_INIT 0xff +#define ACI_STATUS 0xf0 +#define ACI_S_GENERAL 0x00 +#define ACI_S_READ_IGAIN 0x21 +#define ACI_ERROR_OP 0xdf /* * The following macro SCALE can be used to scale one integer volume @@ -47,9 +53,6 @@ */ #define SCALE(xmax,ymax,x) (((x)*(ymax)+(xmax)/2)/(xmax)) - -extern void __exit unload_aci_rds(void); -extern int __init attach_aci_rds(void); #endif /* _ACI_H_ */ diff -u --recursive --new-file v2.4.5/linux/drivers/sound/cmpci.c linux/drivers/sound/cmpci.c --- v2.4.5/linux/drivers/sound/cmpci.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/sound/cmpci.c Wed Jun 27 17:10:55 2001 @@ -1,12 +1,16 @@ /*****************************************************************************/ - /* * cmpci.c -- C-Media PCI audio driver. * - * Copyright (C) 1999 ChenLi Tien (cltien@home.com) + * Copyright (C) 1999 ChenLi Tien (cltien@cmedia.com.tw) + * C-media support (support@cmedia.com.tw) * - * Based on the PCI drivers by Thomas Sailer (sailer@ife.ee.ethz.ch) + * Based on the PCI drivers by Thomas Sailer (sailer@ife.ee.ethz.ch) * + * For update, visit: + * http://members.home.net/puresoft/cmedia.html + * http://www.cmedia.com.tw + * * 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 @@ -57,8 +61,6 @@ * reported by Johan Maes * 22.03.99 0.12 return EAGAIN instead of EBUSY when O_NONBLOCK * read/write cannot be executed - * 20 09 99 0.13 merged the generic changes in sonicvibes since this - * diverged. * 18.08.99 1.5 Only deallocate DMA buffer when unloading. * 02.09.99 1.6 Enable SPDIF LOOP * Change the mixer read back @@ -66,47 +68,32 @@ * Add support for modem, S/PDIF loop and 4 channels. * (8738 only) * Fix bug cause x11amp cannot play. - * $Log: cmpci.c,v $ - * Revision 2.41 1999/10/27 02:00:05 cltien - * Now the fragsize for modem is activated by parameter. - * - * Revision 2.40 1999/10/26 23:38:26 cltien - * Remove debugging message in cm_write which may cause module counter not 0. - * - * Revision 2.39 1999/10/26 21:52:50 cltien - * I forgor too adjust mic recording volume, as it should be moved to 5MUTEMONO. - * Change the DYNAMIC macro to FIXEDDMA, which means static DMA buffer. - * - * Revision 2.38 1999/10/08 21:59:03 cltien - * Set FLINKON and reset FLINKOFF for modem. - * - * Revision 2.37 1999/09/28 02:57:04 cltien - * Add set_bus_master() to make sure bus master enabled. - * - * Revision 2.36 1999/09/22 14:15:03 cltien - * Use open_sem to avoid multiple access to open_mode. - * Use wakeup in IntrClose to activate process in waiting queue. - * - * Revision 2.35 1999/09/22 13:20:53 cltien - * Use open_mode to check if DAC in used. Also more check in IntrWrite and IntrClose. Now the modem can access DAC safely. - * - * Revision 2.34 1999/09/22 03:29:57 cltien - * Use module count to decide which one to access the dac. * + * Fixes: + * Arnaldo Carvalho de Melo + * 18/05/2001 - .bss nitpicks, fix a bug in set_dac_channels where it + * was calling prog_dmabuf with s->lock held, call missing + * unlock_kernel in cm_midi_release + * + * Fri May 25 2001 - Carlos Eduardo Gorges + * - some driver cleanups + * - spin[un]lock* revision ( fix SMP support ) + * - cosmetic code changes * */ - + /*****************************************************************************/ -#include +#define EXPORT_SYMTAB #include +#include #include #include #include #include #include #include -#include +#include #include #include #include @@ -139,6 +126,9 @@ #ifndef PCI_DEVICE_ID_CMEDIA_CM8738 #define PCI_DEVICE_ID_CMEDIA_CM8738 0x0111 #endif +#ifndef PCI_DEVICE_ID_CMEDIA_CM8738B +#define PCI_DEVICE_ID_CMEDIA_CM8738B 0x0112 +#endif #define CM_MAGIC ((PCI_VENDOR_ID_CMEDIA<<16)|PCI_DEVICE_ID_CMEDIA_CM8338A) @@ -217,14 +207,14 @@ #define CM_CFMT_STEREO 0x01 #define CM_CFMT_16BIT 0x02 #define CM_CFMT_MASK 0x03 -#define CM_CFMT_DACSHIFT 0 -#define CM_CFMT_ADCSHIFT 2 +#define CM_CFMT_DACSHIFT 2 +#define CM_CFMT_ADCSHIFT 0 static const unsigned sample_size[] = { 1, 2, 2, 4 }; static const unsigned sample_shift[] = { 0, 1, 1, 2 }; -#define CM_CENABLE_RE 0x2 -#define CM_CENABLE_PE 0x1 +#define CM_ENABLE_CH1 0x2 +#define CM_ENABLE_CH0 0x1 /* MIDI buffer sizes */ @@ -238,6 +228,8 @@ #define FMODE_DMFM 0x10 +#define SND_DEV_DSP16 5 + /* --------------------------------------------------------------------- */ struct cm_state { @@ -255,6 +247,7 @@ /* hardware resources */ unsigned int iosb, iobase, iosynth, iomidi, iogame, irq; + unsigned short deviceid; /* mixer stuff */ struct { @@ -275,6 +268,7 @@ struct dmabuf { void *rawbuf; + unsigned rawphys; unsigned buforder; unsigned numfrag; unsigned fragshift; @@ -307,12 +301,48 @@ unsigned char ibuf[MIDIINBUF]; unsigned char obuf[MIDIOUTBUF]; } midi; + + /* misc stuff */ + int chip_version; + int max_channels; + int curr_channels; + int speakers; // number of speakers + int capability; // HW capability, various for chip versions + int status; // HW or SW state + + /* spdif frame counter */ + int spdif_counter; }; +/* flags used for capability */ +#define CAN_AC3_HW 0x00000001 // 037 or later +#define CAN_AC3_SW 0x00000002 // 033 or later +#define CAN_AC3 (CAN_AC3_HW | CAN_AC3_SW) +#define CAN_DUAL_DAC 0x00000004 // 033 or later +#define CAN_MULTI_CH_HW 0x00000008 // 039 or later +#define CAN_MULTI_CH (CAN_MULTI_CH_HW | CAN_DUAL_DAC) +#define CAN_LINE_AS_REAR 0x00000010 // 033 or later +#define CAN_LINE_AS_BASS 0x00000020 // 039 or later +#define CAN_MIC_AS_BASS 0x00000040 // 039 or later + +/* flags used for status */ +#define DO_AC3_HW 0x00000001 +#define DO_AC3_SW 0x00000002 +#define DO_AC3 (DO_AC3_HW | DO_AC3_SW) +#define DO_DUAL_DAC 0x00000004 +#define DO_MULTI_CH_HW 0x00000008 +#define DO_MULTI_CH (DO_MULTI_CH_HW | DO_DUAL_DAC) +#define DO_LINE_AS_REAR 0x00000010 // 033 or later +#define DO_LINE_AS_BASS 0x00000020 // 039 or later +#define DO_MIC_AS_BASS 0x00000040 // 039 or later +#define DO_SPDIF_OUT 0x00000100 +#define DO_SPDIF_IN 0x00000200 +#define DO_SPDIF_LOOP 0x00000400 + /* --------------------------------------------------------------------- */ -static struct cm_state *devs = NULL; -static unsigned long wavetable_mem = 0; +static struct cm_state *devs; +static unsigned long wavetable_mem; /* --------------------------------------------------------------------- */ @@ -361,35 +391,76 @@ /* --------------------------------------------------------------------- */ -static void set_dmadac(struct cm_state *s, unsigned int addr, unsigned int count) +/* + * Why use byte IO? Nobody knows, but S3 does it also in their Windows driver. + */ + +#undef DMABYTEIO + +static void maskb(unsigned int addr, unsigned int mask, unsigned int value) { - count--; - outl(addr, s->iobase + CODEC_CMI_CH0_FRAME1); - outw(count, s->iobase + CODEC_CMI_CH0_FRAME2); - outb(inb(s->iobase + CODEC_CMI_FUNCTRL0) & ~1, s->iobase + CODEC_CMI_FUNCTRL0); -// outb(inb(s->iobase + CODEC_CMI_FUNCTRL0 + 2) | 1, s->iobase + CODEC_CMI_FUNCTRL0 + 2); + outb((inb(addr) & mask) | value, addr); +} + +static void maskw(unsigned int addr, unsigned int mask, unsigned int value) +{ + outw((inw(addr) & mask) | value, addr); +} + +static void maskl(unsigned int addr, unsigned int mask, unsigned int value) +{ + outl((inl(addr) & mask) | value, addr); +} + +static void set_dmadac1(struct cm_state *s, unsigned int addr, unsigned int count) +{ + if (addr) + outl(addr, s->iobase + CODEC_CMI_CH0_FRAME1); + outw(count - 1, s->iobase + CODEC_CMI_CH0_FRAME2); + maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~1, 0); } static void set_dmaadc(struct cm_state *s, unsigned int addr, unsigned int count) { - count--; + outl(addr, s->iobase + CODEC_CMI_CH0_FRAME1); + outw(count - 1, s->iobase + CODEC_CMI_CH0_FRAME2); + maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~0, 1); +} + +static void set_dmadac(struct cm_state *s, unsigned int addr, unsigned int count) +{ outl(addr, s->iobase + CODEC_CMI_CH1_FRAME1); - outw(count, s->iobase + CODEC_CMI_CH1_FRAME2); - outb(inb(s->iobase + CODEC_CMI_FUNCTRL0) | 2, s->iobase + CODEC_CMI_FUNCTRL0); -// outb(inb(s->iobase + CODEC_CMI_FUNCTRL0 + 2) | 2, s->iobase + CODEC_CMI_FUNCTRL0 + 2); + outw(count - 1, s->iobase + CODEC_CMI_CH1_FRAME2); + maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~2, 0); + if (s->status & DO_DUAL_DAC) + set_dmadac1(s, 0, count); +} + +static void set_countadc(struct cm_state *s, unsigned count) +{ + outw(count - 1, s->iobase + CODEC_CMI_CH0_FRAME2 + 2); +} + +static void set_countdac(struct cm_state *s, unsigned count) +{ + outw(count - 1, s->iobase + CODEC_CMI_CH1_FRAME2 + 2); + if (s->status & DO_DUAL_DAC) + set_countadc(s, count); } extern __inline__ unsigned get_dmadac(struct cm_state *s) { unsigned int curr_addr; - if (!s->dma_dac.dmasize || !(s->enable & CM_CENABLE_PE)) - return 0; - - curr_addr = inl(s->iobase + CODEC_CMI_CH0_FRAME1); - curr_addr -= virt_to_bus(s->dma_dac.rawbuf); +#if 1 + curr_addr = inw(s->iobase + CODEC_CMI_CH1_FRAME2) + 1; + curr_addr <<= sample_shift[(s->fmt >> CM_CFMT_DACSHIFT) & CM_CFMT_MASK]; curr_addr = s->dma_dac.dmasize - curr_addr; +#else + curr_addr = inl(s->iobase + CODEC_CMI_CH1_FRAME1); curr_addr &= ~(sample_size[(s->fmt >> CM_CFMT_DACSHIFT) & CM_CFMT_MASK]-1); + curr_addr -= s->dma_dac.rawphys; +#endif return curr_addr; } @@ -397,22 +468,22 @@ { unsigned int curr_addr; - if (!s->dma_adc.dmasize || !(s->enable & CM_CENABLE_RE)) - return 0; - - curr_addr = inl(s->iobase + CODEC_CMI_CH1_FRAME1); - curr_addr -= virt_to_bus(s->dma_adc.rawbuf); +#if 1 + curr_addr = inw(s->iobase + CODEC_CMI_CH0_FRAME2) + 1; + curr_addr <<= sample_shift[(s->fmt >> CM_CFMT_ADCSHIFT) & CM_CFMT_MASK]; curr_addr = s->dma_adc.dmasize - curr_addr; +#else + curr_addr = inl(s->iobase + CODEC_CMI_CH0_FRAME1); curr_addr &= ~(sample_size[(s->fmt >> CM_CFMT_ADCSHIFT) & CM_CFMT_MASK]-1); + curr_addr -= s->dma_adc.rawphys; +#endif return curr_addr; } static void wrmixer(struct cm_state *s, unsigned char idx, unsigned char data) { outb(idx, s->iobase + CODEC_SB16_ADDR); - udelay(10); outb(data, s->iobase + CODEC_SB16_DATA); - udelay(10); } static unsigned char rdmixer(struct cm_state *s, unsigned char idx) @@ -420,33 +491,31 @@ unsigned char v; outb(idx, s->iobase + CODEC_SB16_ADDR); - udelay(10); v = inb(s->iobase + CODEC_SB16_DATA); - udelay(10); return v; } +static void set_fmt_unlocked(struct cm_state *s, unsigned char mask, unsigned char data) +{ + if (mask) + s->fmt = inb(s->iobase + CODEC_CMI_CHFORMAT); + s->fmt = (s->fmt & mask) | data; + outb(s->fmt, s->iobase + CODEC_CMI_CHFORMAT); +} + static void set_fmt(struct cm_state *s, unsigned char mask, unsigned char data) { unsigned long flags; spin_lock_irqsave(&s->lock, flags); - if (mask) { - s->fmt = inb(s->iobase + CODEC_CMI_CHFORMAT); - udelay(10); - } - s->fmt = (s->fmt & mask) | data; - outb(s->fmt, s->iobase + CODEC_CMI_CHFORMAT); + set_fmt_unlocked(s,mask,data); spin_unlock_irqrestore(&s->lock, flags); - udelay(10); } static void frobindir(struct cm_state *s, unsigned char idx, unsigned char mask, unsigned char data) { outb(idx, s->iobase + CODEC_SB16_ADDR); - udelay(10); outb((inb(s->iobase + CODEC_SB16_DATA) & mask) | data, s->iobase + CODEC_SB16_DATA); - udelay(10); } static struct { @@ -463,125 +532,461 @@ { 22050, (16000 + 22050) / 2, (22050 + 32000) / 2, 2 }, { 32000, (22050 + 32000) / 2, (32000 + 44100) / 2, 6 }, { 44100, (32000 + 44100) / 2, (44100 + 48000) / 2, 3 }, - { 48000, (44100 + 48000) /2, 48000, 7 } + { 48000, (44100 + 48000) / 2, 48000, 7 } }; -static void set_dac_rate(struct cm_state *s, unsigned rate) +static void set_spdifout_unlocked(struct cm_state *s, unsigned rate) +{ + if (rate == 48000 || rate == 44100) { + // SPDIFI48K SPDF_ACc97 + maskl(s->iobase + CODEC_CMI_MISC_CTRL, ~0x01008000, rate == 48000 ? 0x01008000 : 0); + // ENSPDOUT + maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 2, ~0, 0x80); + // SPDF_1 SPD2DAC + maskw(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x240); + // CDPLAY + if (s->chip_version >= 39) + maskb(s->iobase + CODEC_CMI_MIXER1, ~0, 1); + s->status |= DO_SPDIF_OUT; + } else { + maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 2, ~0x80, 0); + maskw(s->iobase + CODEC_CMI_FUNCTRL1, ~0x240, 0); + if (s->chip_version >= 39) + maskb(s->iobase + CODEC_CMI_MIXER1, ~1, 0); + s->status &= ~DO_SPDIF_OUT; + } +} + +static void set_spdifout(struct cm_state *s, unsigned rate) +{ + unsigned long flags; + + spin_lock_irqsave(&s->lock, flags); + set_spdifout_unlocked(s,rate); + spin_unlock_irqrestore(&s->lock, flags); +} + +/* find parity for bit 4~30 */ +static unsigned parity(unsigned data) +{ + unsigned parity = 0; + int counter = 4; + + data >>= 4; // start from bit 4 + while (counter <= 30) { + if (data & 1) + parity++; + data >>= 1; + counter++; + } + return parity & 1; +} + +static void set_ac3_unlocked(struct cm_state *s, unsigned rate) +{ + /* enable AC3 */ + if (rate == 48000 || rate == 44100) { + // mute DAC + maskb(s->iobase + CODEC_CMI_MIXER1, ~0, 0x40); + // AC3EN for 037, 0x10 + maskb(s->iobase + CODEC_CMI_CHFORMAT + 2, ~0, 0x10); + // AC3EN for 039, 0x04 + maskb(s->iobase + CODEC_CMI_MISC_CTRL + 2, ~0, 0x04); + if (s->capability & CAN_AC3_HW) { + // SPD24SEL for 037, 0x02 + // SPD24SEL for 039, 0x20, but cannot be set + maskb(s->iobase + CODEC_CMI_CHFORMAT + 2, ~0, 0x02); + s->status |= DO_AC3_HW; + if (s->chip_version >= 39) + maskb(s->iobase + CODEC_CMI_MIXER1, ~1, 0); + } else { + // SPD32SEL for 037 & 039, 0x20 + maskb(s->iobase + CODEC_CMI_MISC_CTRL + 2, ~0, 0x20); + // set 176K sample rate to fix 033 HW bug + if (s->chip_version == 33) { + if (rate == 48000) + maskb(s->iobase + CODEC_CMI_CHFORMAT + 1, ~0, 0x08); + else + maskb(s->iobase + CODEC_CMI_CHFORMAT + 1, ~0x08, 0); + } + s->status |= DO_AC3_SW; + } + } else { + maskb(s->iobase + CODEC_CMI_MIXER1, ~0x40, 0); + maskb(s->iobase + CODEC_CMI_CHFORMAT + 2, ~0x32, 0); + maskb(s->iobase + CODEC_CMI_MISC_CTRL + 2, ~0x24, 0); + maskb(s->iobase + CODEC_CMI_CHFORMAT + 1, ~0x08, 0); + if (s->chip_version == 33) + maskb(s->iobase + CODEC_CMI_CHFORMAT + 1, ~0x08, 0); + if (s->chip_version >= 39) + maskb(s->iobase + CODEC_CMI_MIXER1, ~0, 1); + s->status &= ~DO_AC3; + } + s->spdif_counter = 0; + +} + +static void set_ac3(struct cm_state *s, unsigned rate) { unsigned long flags; - unsigned char freq = 4, val; + + spin_lock_irqsave(&s->lock, flags); + set_spdifout_unlocked(s, rate); + set_ac3_unlocked(s,rate); + spin_unlock_irqrestore(&s->lock, flags); +} + +static void trans_ac3(struct cm_state *s, void *dest, const char *source, int size) +{ + int i = size / 2; + unsigned long data; + unsigned long *dst = (unsigned long *) dest; + unsigned short *src = (unsigned short *)source; + + do { + data = (unsigned long) *src++; + data <<= 12; // ok for 16-bit data + if (s->spdif_counter == 2 || s->spdif_counter == 3) + data |= 0x40000000; // indicate AC-3 raw data + if (parity(data)) + data |= 0x80000000; // parity + if (s->spdif_counter == 0) + data |= 3; // preamble 'M' + else if (s->spdif_counter & 1) + data |= 5; // odd, 'W' + else + data |= 9; // even, 'M' + *dst++ = data; + s->spdif_counter++; + if (s->spdif_counter == 384) + s->spdif_counter = 0; + } while (--i); +} + +static void set_adc_rate_unlocked(struct cm_state *s, unsigned rate) +{ + unsigned char freq = 4; int i; if (rate > 48000) rate = 48000; - if (rate < 5512) - rate = 5512; - for (i = 0; i < sizeof(rate_lookup) / sizeof(rate_lookup[0]); i++) - { - if (rate > rate_lookup[i].lower && rate <= rate_lookup[i].upper) - { + if (rate < 8000) + rate = 8000; + for (i = 0; i < sizeof(rate_lookup) / sizeof(rate_lookup[0]); i++) { + if (rate > rate_lookup[i].lower && rate <= rate_lookup[i].upper) { rate = rate_lookup[i].rate; freq = rate_lookup[i].freq; break; } } - s->ratedac = rate; + s->rateadc = rate; freq <<= 2; - spin_lock_irqsave(&s->lock, flags); - val = inb(s->iobase + CODEC_CMI_FUNCTRL1 + 1) & ~0x1c; - outb(val | freq, s->iobase + CODEC_CMI_FUNCTRL1 + 1); - spin_unlock_irqrestore(&s->lock, flags); + + maskb(s->iobase + CODEC_CMI_FUNCTRL1 + 1, ~0x1c, freq); } static void set_adc_rate(struct cm_state *s, unsigned rate) { unsigned long flags; - unsigned char freq = 4, val; + unsigned char freq = 4; int i; if (rate > 48000) rate = 48000; - if (rate < 5512) - rate = 5512; - for (i = 0; i < sizeof(rate_lookup) / sizeof(rate_lookup[0]); i++) - { - if (rate > rate_lookup[i].lower && rate <= rate_lookup[i].upper) - { + if (rate < 8000) + rate = 8000; + for (i = 0; i < sizeof(rate_lookup) / sizeof(rate_lookup[0]); i++) { + if (rate > rate_lookup[i].lower && rate <= rate_lookup[i].upper) { rate = rate_lookup[i].rate; freq = rate_lookup[i].freq; break; } } s->rateadc = rate; + freq <<= 2; + + spin_lock_irqsave(&s->lock, flags); + maskb(s->iobase + CODEC_CMI_FUNCTRL1 + 1, ~0x1c, freq); + spin_unlock_irqrestore(&s->lock, flags); +} + +static void set_dac_rate(struct cm_state *s, unsigned rate) +{ + unsigned long flags; + unsigned char freq = 4; + int i; + + if (rate > 48000) + rate = 48000; + if (rate < 8000) + rate = 8000; + for (i = 0; i < sizeof(rate_lookup) / sizeof(rate_lookup[0]); i++) { + if (rate > rate_lookup[i].lower && rate <= rate_lookup[i].upper) { + rate = rate_lookup[i].rate; + freq = rate_lookup[i].freq; + break; + } + } + s->ratedac = rate; freq <<= 5; + spin_lock_irqsave(&s->lock, flags); - val = inb(s->iobase + CODEC_CMI_FUNCTRL1 + 1) & ~0xe0; - outb(val | freq, s->iobase + CODEC_CMI_FUNCTRL1 + 1); + maskb(s->iobase + CODEC_CMI_FUNCTRL1 + 1, ~0xe0, freq); + + + if (s->curr_channels <= 2) + set_spdifout_unlocked(s, rate); + if (s->status & DO_DUAL_DAC) + set_adc_rate_unlocked(s, rate); + spin_unlock_irqrestore(&s->lock, flags); } /* --------------------------------------------------------------------- */ +static inline void reset_adc(struct cm_state *s) +{ + /* reset bus master */ + outb(s->enable | CM_CH0_RESET, s->iobase + CODEC_CMI_FUNCTRL0 + 2); + outb(s->enable & ~CM_CH0_RESET, s->iobase + CODEC_CMI_FUNCTRL0 + 2); +} + +static inline void reset_dac(struct cm_state *s) +{ + /* reset bus master */ + outb(s->enable | CM_CH1_RESET, s->iobase + CODEC_CMI_FUNCTRL0 + 2); + outb(s->enable & ~CM_CH1_RESET, s->iobase + CODEC_CMI_FUNCTRL0 + 2); + if (s->status & DO_DUAL_DAC) + reset_adc(s); +} + +static inline void pause_adc(struct cm_state *s) +{ + maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~0, 4); +} + +static inline void pause_dac(struct cm_state *s) +{ + maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~0, 8); + if (s->status & DO_DUAL_DAC) + pause_adc(s); +} + +extern inline void disable_adc(struct cm_state *s) +{ + /* disable channel */ + s->enable &= ~CM_ENABLE_CH0; + outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2); + reset_adc(s); +} + +extern inline void disable_dac(struct cm_state *s) +{ + /* disable channel */ + s->enable &= ~CM_ENABLE_CH1; + outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2); + reset_dac(s); + if (s->status & DO_DUAL_DAC) + disable_adc(s); +} + +extern inline void enable_adc(struct cm_state *s) +{ + if (!(s->enable & CM_ENABLE_CH0)) { + /* enable channel */ + s->enable |= CM_ENABLE_CH0; + outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2); + } + maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~4, 0); +} + +extern inline void enable_dac_unlocked(struct cm_state *s) +{ + if (!(s->enable & CM_ENABLE_CH1)) { + /* enable channel */ + s->enable |= CM_ENABLE_CH1; + outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2); + } + maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~8, 0); + + if (s->status & DO_DUAL_DAC) + enable_adc(s); +} + +extern inline void enable_dac(struct cm_state *s) +{ + unsigned long flags; + + spin_lock_irqsave(&s->lock, flags); + enable_dac_unlocked(s); + spin_unlock_irqrestore(&s->lock, flags); +} + +extern inline void stop_adc_unlocked(struct cm_state *s) +{ + if (s->enable & CM_ENABLE_CH0) { + /* disable interrupt */ + maskb(s->iobase + CODEC_CMI_INT_HLDCLR + 2, ~1, 0); + disable_adc(s); + } +} extern inline void stop_adc(struct cm_state *s) { unsigned long flags; spin_lock_irqsave(&s->lock, flags); - /* disable channel */ - outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2); - s->enable &= ~CM_CENABLE_RE; - /* disable interrupt */ - outb(inb(s->iobase + CODEC_CMI_INT_HLDCLR + 2) & ~2, s->iobase + CODEC_CMI_INT_HLDCLR + 2); - /* reset */ - outb(s->enable | CM_CH1_RESET, s->iobase + CODEC_CMI_FUNCTRL0 + 2); - udelay(10); - outb(s->enable & ~CM_CH1_RESET, s->iobase + CODEC_CMI_FUNCTRL0 + 2); + stop_adc_unlocked(s); spin_unlock_irqrestore(&s->lock, flags); -} + +} + +extern inline void stop_dac_unlocked(struct cm_state *s) +{ + if (s->enable & CM_ENABLE_CH1) { + /* disable interrupt */ + maskb(s->iobase + CODEC_CMI_INT_HLDCLR + 2, ~2, 0); + disable_dac(s); + } + if (s->status & DO_DUAL_DAC) + stop_adc_unlocked(s); +} extern inline void stop_dac(struct cm_state *s) { unsigned long flags; spin_lock_irqsave(&s->lock, flags); - /* disable channel */ - s->enable &= ~CM_CENABLE_PE; - outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2); - /* disable interrupt */ - outb(inb(s->iobase + CODEC_CMI_INT_HLDCLR + 2) & ~1, s->iobase + CODEC_CMI_INT_HLDCLR + 2); - /* reset */ - outb(s->enable | CM_CH0_RESET, s->iobase + CODEC_CMI_FUNCTRL0 + 2); - udelay(10); - outb(s->enable & ~CM_CH0_RESET, s->iobase + CODEC_CMI_FUNCTRL0 + 2); + stop_dac_unlocked(s); spin_unlock_irqrestore(&s->lock, flags); -} +} -static void start_dac(struct cm_state *s) +static void start_adc_unlocked(struct cm_state *s) +{ + if ((s->dma_adc.mapped || s->dma_adc.count < (signed)(s->dma_adc.dmasize - 2*s->dma_adc.fragsize)) + && s->dma_adc.ready) { + /* enable interrupt */ + maskb(s->iobase + CODEC_CMI_INT_HLDCLR + 2, ~0, 1); + enable_adc(s); + } +} + +static void start_adc(struct cm_state *s) { unsigned long flags; spin_lock_irqsave(&s->lock, flags); + start_adc_unlocked(s); + spin_unlock_irqrestore(&s->lock, flags); +} + +static void start_dac1_unlocked(struct cm_state *s) +{ + if ((s->dma_adc.mapped || s->dma_adc.count > 0) && s->dma_adc.ready) { + /* enable interrupt */ +// maskb(s->iobase + CODEC_CMI_INT_HLDCLR + 2, ~0, 1); + enable_dac_unlocked(s); + } +} + +//static void start_dac1(struct cm_state *s) +//{ +// unsigned long flags; +// +// spin_lock_irqsave(&s->lock, flags); +// start_dac1_unlocked(s); +// spin_unlock_irqrestore(&s->lock, flags); +//} + +static void start_dac_unlocked(struct cm_state *s) +{ if ((s->dma_dac.mapped || s->dma_dac.count > 0) && s->dma_dac.ready) { - outb(inb(s->iobase + CODEC_CMI_INT_HLDCLR + 2) | 1, s->iobase + CODEC_CMI_INT_HLDCLR + 2); - s->enable |= CM_CENABLE_PE; - outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2); + /* enable interrupt */ + maskb(s->iobase + CODEC_CMI_INT_HLDCLR + 2, ~0, 2); + enable_dac_unlocked(s); } + if (s->status & DO_DUAL_DAC) + start_dac1_unlocked(s); +} + +static void start_dac(struct cm_state *s) +{ + unsigned long flags; + + spin_lock_irqsave(&s->lock, flags); + start_dac_unlocked(s); spin_unlock_irqrestore(&s->lock, flags); } -static void start_adc(struct cm_state *s) +static int prog_dmabuf(struct cm_state *s, unsigned rec); + +static int set_dac_channels(struct cm_state *s, int channels) { unsigned long flags; - spin_lock_irqsave(&s->lock, flags); - if ((s->dma_adc.mapped || s->dma_adc.count < (signed)(s->dma_adc.dmasize - 2*s->dma_adc.fragsize)) - && s->dma_adc.ready) { - outb(inb(s->iobase + CODEC_CMI_INT_HLDCLR + 2) | 2, s->iobase + CODEC_CMI_INT_HLDCLR + 2); - s->enable |= CM_CENABLE_RE; - outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2); + + if ((channels > 2) && (channels <= s->max_channels) + && (((s->fmt >> CM_CFMT_DACSHIFT) & CM_CFMT_MASK) == (CM_CFMT_STEREO | CM_CFMT_16BIT))) { + set_spdifout_unlocked(s, 0); + if (s->capability & CAN_MULTI_CH_HW) { + // NXCHG + maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 3, ~0, 0x80); + // CHB3D or CHB3D5C + maskb(s->iobase + CODEC_CMI_CHFORMAT + 3, ~0xa0, channels > 4 ? 0x80 : 0x20); + // CHB3D6C + maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 1, ~0x80, channels == 6 ? 0x80 : 0); + // ENCENTER + maskb(s->iobase + CODEC_CMI_MISC_CTRL, ~0x80, channels == 6 ? 0x80 : 0); + s->status |= DO_MULTI_CH_HW; + } else if (s->capability & CAN_DUAL_DAC) { + unsigned char fmtm = ~0, fmts = 0; + ssize_t ret; + + // ENDBDAC, turn on double DAC mode + // XCHGDAC, CH0 -> back, CH1->front + maskb(s->iobase + CODEC_CMI_MISC_CTRL + 2, ~0, 0xC0); + s->status |= DO_DUAL_DAC; + // prepare secondary buffer + + spin_unlock_irqrestore(&s->lock, flags); + ret = prog_dmabuf(s, 1); + spin_lock_irqsave(&s->lock, flags); + + if (ret) return ret; + // copy the hw state + fmtm &= ~((CM_CFMT_STEREO | CM_CFMT_16BIT) << CM_CFMT_DACSHIFT); + fmtm &= ~((CM_CFMT_STEREO | CM_CFMT_16BIT) << CM_CFMT_ADCSHIFT); + // the HW only support 16-bit stereo + fmts |= CM_CFMT_16BIT << CM_CFMT_DACSHIFT; + fmts |= CM_CFMT_16BIT << CM_CFMT_ADCSHIFT; + fmts |= CM_CFMT_STEREO << CM_CFMT_DACSHIFT; + fmts |= CM_CFMT_STEREO << CM_CFMT_ADCSHIFT; + + set_fmt_unlocked(s, fmtm, fmts); + set_adc_rate_unlocked(s, s->ratedac); + + } + // N4SPK3D, disable 4 speaker mode (analog duplicate) + if (s->speakers > 2) + maskb(s->iobase + CODEC_CMI_MISC_CTRL + 3, ~0x04, 0); + s->curr_channels = channels; + } else { + if (s->status & DO_MULTI_CH_HW) { + maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 3, ~0x80, 0); + maskb(s->iobase + CODEC_CMI_CHFORMAT + 3, ~0xa0, 0); + maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 1, ~0x80, 0); + } else if (s->status & DO_DUAL_DAC) { + maskb(s->iobase + CODEC_CMI_MISC_CTRL + 2, ~0x80, 0); + } + // N4SPK3D, enable 4 speaker mode (analog duplicate) + if (s->speakers > 2) + maskb(s->iobase + CODEC_CMI_MISC_CTRL + 3, ~0, 0x04); + s->status &= ~DO_MULTI_CH; + s->curr_channels = s->fmt & (CM_CFMT_STEREO << CM_CFMT_DACSHIFT) ? 2 : 1; } + spin_unlock_irqrestore(&s->lock, flags); -} + return s->curr_channels; +} /* --------------------------------------------------------------------- */ @@ -591,7 +996,7 @@ static void dealloc_dmabuf(struct dmabuf *db) { struct page *pstart, *pend; - + if (db->rawbuf) { /* undo marking the pages as reserved */ pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); @@ -603,8 +1008,7 @@ db->mapped = db->ready = 0; } - -/* Ch0 is used for playback, Ch1 is used for recording */ +/* Ch1 is used for playback, Ch0 is used for recording */ static int prog_dmabuf(struct cm_state *s, unsigned rec) { @@ -617,17 +1021,15 @@ unsigned char fmt; unsigned long flags; - spin_lock_irqsave(&s->lock, flags); fmt = s->fmt; if (rec) { - s->enable &= ~CM_CENABLE_RE; + stop_adc(s); fmt >>= CM_CFMT_ADCSHIFT; } else { - s->enable &= ~CM_CENABLE_PE; + stop_dac(s); fmt >>= CM_CFMT_DACSHIFT; } - outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2); - spin_unlock_irqrestore(&s->lock, flags); + fmt &= CM_CFMT_MASK; db->hwptr = db->swptr = db->total_bytes = db->count = db->error = db->endcleared = 0; if (!db->rawbuf) { @@ -638,12 +1040,13 @@ if (!db->rawbuf) return -ENOMEM; db->buforder = order; - if ((virt_to_bus(db->rawbuf) ^ (virt_to_bus(db->rawbuf) + (PAGE_SIZE << db->buforder) - 1)) & ~0xffff) - printk(KERN_DEBUG "cmpci: DMA buffer crosses 64k boundary: busaddr 0x%lx size %ld\n", - virt_to_bus(db->rawbuf), PAGE_SIZE << db->buforder); - if ((virt_to_bus(db->rawbuf) + (PAGE_SIZE << db->buforder) - 1) & ~0xffffff) - printk(KERN_DEBUG "cmpci: DMA buffer beyond 16MB: busaddr 0x%lx size %ld\n", - virt_to_bus(db->rawbuf), PAGE_SIZE << db->buforder); + db->rawphys = virt_to_bus(db->rawbuf); + if ((db->rawphys ^ (db->rawphys + (PAGE_SIZE << db->buforder) - 1)) & ~0xffff) + printk(KERN_DEBUG "cm: DMA buffer crosses 64k boundary: busaddr 0x%lx size %ld\n", + (long) db->rawphys, PAGE_SIZE << db->buforder); + if ((db->rawphys + (PAGE_SIZE << db->buforder) - 1) & ~0xffffff) + printk(KERN_DEBUG "cm: DMA buffer beyond 16MB: busaddr 0x%lx size %ld\n", + (long) db->rawphys, PAGE_SIZE << db->buforder); /* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */ pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); for (pstart = virt_to_page(db->rawbuf); pstart <= pend; pstart++) @@ -670,30 +1073,22 @@ if (db->ossmaxfrags >= 4 && db->ossmaxfrags < db->numfrag) db->numfrag = db->ossmaxfrags; /* to make fragsize >= 4096 */ -#if 0 - if(s->modem) - { - while (db->fragsize < 4096 && db->numfrag >= 4) - { - db->fragsize *= 2; - db->fragshift++; - db->numfrag /= 2; - } - } -#endif db->fragsamples = db->fragsize >> sample_shift[fmt]; db->dmasize = db->numfrag << db->fragshift; db->dmasamples = db->dmasize >> sample_shift[fmt]; memset(db->rawbuf, (fmt & CM_CFMT_16BIT) ? 0 : 0x80, db->dmasize); spin_lock_irqsave(&s->lock, flags); if (rec) { - set_dmaadc(s, virt_to_bus(db->rawbuf), db->dmasize >> sample_shift[fmt]); + if (s->status & DO_DUAL_DAC) + set_dmadac1(s, db->rawphys, db->dmasize >> sample_shift[fmt]); + else + set_dmaadc(s, db->rawphys, db->dmasize >> sample_shift[fmt]); /* program sample counts */ - outw(db->fragsamples-1, s->iobase + CODEC_CMI_CH1_FRAME2 + 2); + set_countdac(s, db->fragsamples); } else { - set_dmadac(s, virt_to_bus(db->rawbuf), db->dmasize >> sample_shift[fmt]); + set_dmadac(s, db->rawphys, db->dmasize >> sample_shift[fmt]); /* program sample counts */ - outw(db->fragsamples-1, s->iobase + CODEC_CMI_CH0_FRAME2 + 2); + set_countdac(s, db->fragsamples); } spin_unlock_irqrestore(&s->lock, flags); db->ready = 1; @@ -704,6 +1099,7 @@ { unsigned char c = (s->fmt & (CM_CFMT_16BIT << CM_CFMT_DACSHIFT)) ? 0 : 0x80; unsigned char *buf = s->dma_dac.rawbuf; + unsigned char *buf1 = s->dma_adc.rawbuf; unsigned bsize = s->dma_dac.dmasize; unsigned bptr = s->dma_dac.swptr; unsigned len = s->dma_dac.fragsize; @@ -711,11 +1107,14 @@ if (bptr + len > bsize) { unsigned x = bsize - bptr; memset(buf + bptr, c, x); + if (s->status & DO_DUAL_DAC) + memset(buf1 + bptr, c, x); bptr = 0; len -= x; } memset(buf + bptr, c, len); - outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2); + if (s->status & DO_DUAL_DAC) + memset(buf1 + bptr, c, len); } /* call with spinlock held! */ @@ -726,7 +1125,29 @@ /* update ADC pointer */ if (s->dma_adc.ready) { - hwptr = (s->dma_adc.dmasize - get_dmaadc(s)) % s->dma_adc.dmasize; + if (s->status & DO_DUAL_DAC) { + hwptr = get_dmaadc(s) % s->dma_adc.dmasize; + diff = (s->dma_adc.dmasize + hwptr - s->dma_adc.hwptr) % s->dma_adc.dmasize; + s->dma_adc.hwptr = hwptr; + s->dma_adc.total_bytes += diff; + if (s->dma_adc.mapped) { + s->dma_adc.count += diff; + if (s->dma_adc.count >= (signed)s->dma_adc.fragsize) + wake_up(&s->dma_adc.wait); + } else { + s->dma_adc.count -= diff; + if (s->dma_adc.count <= 0) { + pause_adc(s); + s->dma_adc.error++; + } else if (s->dma_adc.count <= (signed)s->dma_adc.fragsize && !s->dma_adc.endcleared) { + clear_advance(s); + s->dma_adc.endcleared = 1; + } + if (s->dma_dac.count + (signed)s->dma_dac.fragsize <= (signed)s->dma_dac.dmasize) + wake_up(&s->dma_adc.wait); + } + } else { + hwptr = get_dmaadc(s) % s->dma_adc.dmasize; diff = (s->dma_adc.dmasize + hwptr - s->dma_adc.hwptr) % s->dma_adc.dmasize; s->dma_adc.hwptr = hwptr; s->dma_adc.total_bytes += diff; @@ -735,15 +1156,15 @@ wake_up(&s->dma_adc.wait); if (!s->dma_adc.mapped) { if (s->dma_adc.count > (signed)(s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1))) { - s->enable &= ~CM_CENABLE_RE; - outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2); + pause_adc(s); s->dma_adc.error++; } } + } } /* update DAC pointer */ if (s->dma_dac.ready) { - hwptr = (s->dma_dac.dmasize - get_dmadac(s)) % s->dma_dac.dmasize; + hwptr = get_dmadac(s) % s->dma_dac.dmasize; diff = (s->dma_dac.dmasize + hwptr - s->dma_dac.hwptr) % s->dma_dac.dmasize; s->dma_dac.hwptr = hwptr; s->dma_dac.total_bytes += diff; @@ -754,8 +1175,7 @@ } else { s->dma_dac.count -= diff; if (s->dma_dac.count <= 0) { - s->enable &= ~CM_CENABLE_PE; - outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2); + pause_dac(s); s->dma_dac.error++; } else if (s->dma_dac.count <= (signed)s->dma_dac.fragsize && !s->dma_dac.endcleared) { clear_advance(s); @@ -767,6 +1187,7 @@ } } +#ifdef CONFIG_SOUND_CMPCI_MIDI /* hold spinlock for the following! */ static void cm_handle_midi(struct cm_state *s) { @@ -796,11 +1217,13 @@ if (wake) wake_up(&s->midi.owait); } +#endif static void cm_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct cm_state *s = (struct cm_state *)dev_id; unsigned int intsrc, intstat; + unsigned char mask = 0; /* fastpath out, to ease interrupt sharing */ intsrc = inl(s->iobase + CODEC_CMI_INT_STATUS); @@ -810,22 +1233,19 @@ intstat = inb(s->iobase + CODEC_CMI_INT_HLDCLR + 2); /* acknowledge interrupt */ if (intsrc & CM_INT_CH0) - { - outb(intstat & ~1, s->iobase + CODEC_CMI_INT_HLDCLR + 2); - udelay(10); - outb(intstat | 1, s->iobase + CODEC_CMI_INT_HLDCLR + 2); - } + mask |= 1; if (intsrc & CM_INT_CH1) - { - outb(intstat & ~2, s->iobase + CODEC_CMI_INT_HLDCLR + 2); - udelay(10); - outb(intstat | 2, s->iobase + CODEC_CMI_INT_HLDCLR + 2); - } + mask |= 2; + outb(intstat & ~mask, s->iobase + CODEC_CMI_INT_HLDCLR + 2); + outb(intstat | mask, s->iobase + CODEC_CMI_INT_HLDCLR + 2); cm_update_ptr(s); +#ifdef CONFIG_SOUND_CMPCI_MIDI cm_handle_midi(s); +#endif spin_unlock(&s->lock); } +#ifdef CONFIG_SOUND_CMPCI_MIDI static void cm_midi_timer(unsigned long data) { struct cm_state *s = (struct cm_state *)data; @@ -837,10 +1257,11 @@ s->midi.timer.expires = jiffies+1; add_timer(&s->midi.timer); } +#endif /* --------------------------------------------------------------------- */ -static const char invalid_magic[] = KERN_CRIT "cmpci: invalid magic value\n"; +static const char invalid_magic[] = KERN_CRIT "cm: invalid magic value\n"; #ifdef CONFIG_SOUND_CMPCI /* support multiple chips */ #define VALIDATE_STATE(s) @@ -874,7 +1295,8 @@ [SOUND_MIXER_MIC] = { DSP_MIX_MICVOLIDX, DSP_MIX_MICVOLIDX, MT_5MUTEMONO, 0x01, 0x01 }, [SOUND_MIXER_SYNTH] = { DSP_MIX_FMVOLIDX_L, DSP_MIX_FMVOLIDX_R, MT_5MUTE, 0x40, 0x00 }, [SOUND_MIXER_VOLUME] = { DSP_MIX_MASTERVOLIDX_L, DSP_MIX_MASTERVOLIDX_R, MT_5MUTE, 0x00, 0x00 }, - [SOUND_MIXER_PCM] = { DSP_MIX_VOICEVOLIDX_L, DSP_MIX_VOICEVOLIDX_R, MT_5MUTE, 0x00, 0x00 } + [SOUND_MIXER_PCM] = { DSP_MIX_VOICEVOLIDX_L, DSP_MIX_VOICEVOLIDX_R, MT_5MUTE, 0x00, 0x00 }, + [SOUND_MIXER_SPEAKER]= { DSP_MIX_SPKRVOLIDX, DSP_MIX_SPKRVOLIDX, MT_5MUTEMONO, 0x01, 0x01 } }; #ifdef OSS_DOCUMENTED_MIXER_SEMANTICS @@ -937,7 +1359,8 @@ [SOUND_MIXER_MIC] = 3, [SOUND_MIXER_SYNTH] = 4, [SOUND_MIXER_VOLUME] = 5, - [SOUND_MIXER_PCM] = 6 + [SOUND_MIXER_PCM] = 6, + [SOUND_MIXER_SPEAKER]= 7 }; #endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */ @@ -983,9 +1406,9 @@ } if (cmd == OSS_GETVERSION) return put_user(SOUND_VERSION, (int *)arg); - if (_IOC_TYPE(cmd) != 'M' || _SIOC_SIZE(cmd) != sizeof(int)) + if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int)) return -EINVAL; - if (_SIOC_DIR(cmd) == _SIOC_READ) { + if (_IOC_DIR(cmd) == _IOC_READ) { switch (_IOC_NR(cmd)) { case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ return put_user(mixer_recmask(s), (int *)arg); @@ -1033,7 +1456,7 @@ #endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */ } } - if (_SIOC_DIR(cmd) != (_SIOC_READ|_SIOC_WRITE)) + if (_IOC_DIR(cmd) != (_IOC_READ|_IOC_WRITE)) return -EINVAL; s->mix.modcnt++; switch (_IOC_NR(cmd)) { @@ -1100,7 +1523,7 @@ rl = (l < 4 ? 0 : (l - 5) / 3) & 31; rr = (rl >> 2) & 7; wrmixer(s, mixtable[i].left, rl<<3); - outb((inb(s->iobase + CODEC_CMI_MIXER2) & ~0x0e) | rr<<1, s->iobase + CODEC_CMI_MIXER2); + maskb(s->iobase + CODEC_CMI_MIXER2, ~0x0e, rr<<1); break; case MT_5MUTEMONO: @@ -1108,7 +1531,7 @@ rl = l < 4 ? 0 : (l - 5) / 3; rr = rl >> 2; wrmixer(s, mixtable[i].left, rl<<3); - outb((inb(s->iobase + CODEC_CMI_MIXER2) & ~0x0e) | rr<<1, s->iobase + CODEC_CMI_MIXER2); + maskb(s->iobase + CODEC_CMI_MIXER2, ~0x0e, rr<<1); break; case MT_5MUTE: @@ -1117,7 +1540,7 @@ wrmixer(s, mixtable[i].left, rl<<3); wrmixer(s, mixtable[i].right, rr<<3); break; - + case MT_6MUTE: if (l < 6) rl = 0x00; @@ -1187,19 +1610,20 @@ release: cm_release_mixdev, }; + /* --------------------------------------------------------------------- */ static int drain_dac(struct cm_state *s, int nonblock) { - DECLARE_WAITQUEUE(wait, current); + DECLARE_WAITQUEUE(wait, current); unsigned long flags; int count, tmo; if (s->dma_dac.mapped || !s->dma_dac.ready) return 0; + current->state = TASK_INTERRUPTIBLE; add_wait_queue(&s->dma_dac.wait, &wait); for (;;) { - set_current_state(TASK_INTERRUPTIBLE); spin_lock_irqsave(&s->lock, flags); count = s->dma_dac.count; spin_unlock_irqrestore(&s->lock, flags); @@ -1212,10 +1636,10 @@ current->state = TASK_RUNNING; return -EBUSY; } - tmo = (count * HZ) / s->ratedac; + tmo = 3 * HZ * (count + s->dma_dac.fragsize) / 2 / s->ratedac; tmo >>= sample_shift[(s->fmt >> CM_CFMT_DACSHIFT) & CM_CFMT_MASK]; - if (!schedule_timeout(tmo ? : 1) && tmo) - printk(KERN_DEBUG "cmpci: dma timed out??\n"); + if (!schedule_timeout(tmo + 1)) + printk(KERN_DEBUG "cm: dma timed out??\n"); } remove_wait_queue(&s->dma_dac.wait, &wait); current->state = TASK_RUNNING; @@ -1263,14 +1687,14 @@ if (file->f_flags & O_NONBLOCK) return ret ? ret : -EAGAIN; if (!interruptible_sleep_on_timeout(&s->dma_adc.wait, HZ)) { - printk(KERN_DEBUG "cmpci: read: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n", + printk(KERN_DEBUG "cm: read: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n", s->dma_adc.dmasize, s->dma_adc.fragsize, s->dma_adc.count, s->dma_adc.hwptr, s->dma_adc.swptr); - stop_adc(s); spin_lock_irqsave(&s->lock, flags); - set_dmaadc(s, virt_to_bus(s->dma_adc.rawbuf), s->dma_adc.dmasamples); + stop_adc_unlocked(s); + set_dmaadc(s, s->dma_adc.rawphys, s->dma_adc.dmasamples); /* program sample counts */ - outw(s->dma_adc.fragsamples-1, s->iobase + CODEC_CMI_CH1_FRAME2 + 2); + set_countadc(s, s->dma_adc.fragsamples); s->dma_adc.count = s->dma_adc.hwptr = s->dma_adc.swptr = 0; spin_unlock_irqrestore(&s->lock, flags); } @@ -1284,11 +1708,11 @@ spin_lock_irqsave(&s->lock, flags); s->dma_adc.swptr = swptr; s->dma_adc.count -= cnt; - spin_unlock_irqrestore(&s->lock, flags); count -= cnt; buffer += cnt; ret += cnt; - start_adc(s); + start_adc_unlocked(s); + spin_unlock_irqrestore(&s->lock, flags); } return ret; } @@ -1310,62 +1734,113 @@ return ret; if (!access_ok(VERIFY_READ, buffer, count)) return -EFAULT; + if (s->status & DO_DUAL_DAC) { + if (s->dma_adc.mapped) + return -ENXIO; + if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1))) + return ret; + if (!access_ok(VERIFY_READ, buffer, count)) + return -EFAULT; + } ret = 0; #if 0 spin_lock_irqsave(&s->lock, flags); cm_update_ptr(s); spin_unlock_irqrestore(&s->lock, flags); -#endif +#endif while (count > 0) { spin_lock_irqsave(&s->lock, flags); if (s->dma_dac.count < 0) { s->dma_dac.count = 0; s->dma_dac.swptr = s->dma_dac.hwptr; } + if (s->status & DO_DUAL_DAC) { + s->dma_adc.swptr = s->dma_dac.swptr; + s->dma_adc.count = s->dma_dac.count; + s->dma_adc.endcleared = s->dma_dac.endcleared; + } swptr = s->dma_dac.swptr; cnt = s->dma_dac.dmasize-swptr; - if (s->dma_dac.count + cnt > s->dma_dac.dmasize) - cnt = s->dma_dac.dmasize - s->dma_dac.count; + if (s->status & DO_AC3_SW) { + if (s->dma_dac.count + 2 * cnt > s->dma_dac.dmasize) + cnt = (s->dma_dac.dmasize - s->dma_dac.count) / 2; + } else { + if (s->dma_dac.count + cnt > s->dma_dac.dmasize) + cnt = s->dma_dac.dmasize - s->dma_dac.count; + } spin_unlock_irqrestore(&s->lock, flags); if (cnt > count) cnt = count; + if ((s->status & DO_DUAL_DAC) && (cnt > count / 2)) + cnt = count / 2; if (cnt <= 0) { start_dac(s); if (file->f_flags & O_NONBLOCK) return ret ? ret : -EAGAIN; if (!interruptible_sleep_on_timeout(&s->dma_dac.wait, HZ)) { - printk(KERN_DEBUG "cmpci: write: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n", + printk(KERN_DEBUG "cm: write: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n", s->dma_dac.dmasize, s->dma_dac.fragsize, s->dma_dac.count, s->dma_dac.hwptr, s->dma_dac.swptr); - stop_dac(s); spin_lock_irqsave(&s->lock, flags); - set_dmadac(s, virt_to_bus(s->dma_dac.rawbuf), s->dma_dac.dmasamples); + stop_dac_unlocked(s); + set_dmadac(s, s->dma_dac.rawphys, s->dma_dac.dmasamples); /* program sample counts */ - outw(s->dma_dac.fragsamples-1, s->iobase + CODEC_CMI_CH0_FRAME2 + 2); + set_countdac(s, s->dma_dac.fragsamples); s->dma_dac.count = s->dma_dac.hwptr = s->dma_dac.swptr = 0; + if (s->status & DO_DUAL_DAC) { + set_dmadac1(s, s->dma_adc.rawphys, s->dma_adc.dmasamples); + s->dma_adc.count = s->dma_adc.hwptr = s->dma_adc.swptr = 0; + } spin_unlock_irqrestore(&s->lock, flags); } if (signal_pending(current)) return ret ? ret : -ERESTARTSYS; continue; } - if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt)) - return ret ? ret : -EFAULT; - swptr = (swptr + cnt) % s->dma_dac.dmasize; + if (s->status & DO_AC3_SW) { + // clip exceeded data, caught by 033 and 037 + if (swptr + 2 * cnt > s->dma_dac.dmasize) + cnt = (s->dma_dac.dmasize - swptr) / 2; + trans_ac3(s, s->dma_dac.rawbuf + swptr, buffer, cnt); + swptr = (swptr + 2 * cnt) % s->dma_dac.dmasize; + } else if (s->status & DO_DUAL_DAC) { + int i; + unsigned long *src, *dst0, *dst1; + + src = (unsigned long *) buffer; + dst0 = (unsigned long *) (s->dma_dac.rawbuf + swptr); + dst1 = (unsigned long *) (s->dma_adc.rawbuf + swptr); + // copy left/right sample at one time + for (i = 0; i <= cnt / 4; i++) { + *dst0++ = *src++; + *dst1++ = *src++; + } + swptr = (swptr + cnt) % s->dma_dac.dmasize; + } else { + if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt)) + return ret ? ret : -EFAULT; + swptr = (swptr + cnt) % s->dma_dac.dmasize; + } spin_lock_irqsave(&s->lock, flags); s->dma_dac.swptr = swptr; s->dma_dac.count += cnt; + if (s->status & DO_AC3_SW) + s->dma_dac.count += cnt; s->dma_dac.endcleared = 0; spin_unlock_irqrestore(&s->lock, flags); count -= cnt; buffer += cnt; ret += cnt; + if (s->status & DO_DUAL_DAC) { + count -= cnt; + buffer += cnt; + ret += cnt; + } start_dac(s); } return ret; } -/* No kernel lock - fine (we have our own spinlock) */ static unsigned int cm_poll(struct file *file, struct poll_table_struct *wait) { struct cm_state *s = (struct cm_state *)file->private_data; @@ -1373,17 +1848,10 @@ unsigned int mask = 0; VALIDATE_STATE(s); - if (file->f_mode & FMODE_WRITE) { - if (!s->dma_dac.ready && prog_dmabuf(s, 0)) - return 0; + if (file->f_mode & FMODE_WRITE) poll_wait(file, &s->dma_dac.wait, wait); - } - if (file->f_mode & FMODE_READ) { - if (!s->dma_adc.ready && prog_dmabuf(s, 1)) - return 0; + if (file->f_mode & FMODE_READ) poll_wait(file, &s->dma_adc.wait, wait); - } - spin_lock_irqsave(&s->lock, flags); cm_update_ptr(s); if (file->f_mode & FMODE_READ) { @@ -1413,14 +1881,14 @@ VALIDATE_STATE(s); lock_kernel(); if (vma->vm_flags & VM_WRITE) { - if ((ret = prog_dmabuf(s, 1)) != 0) + if ((ret = prog_dmabuf(s, 0)) != 0) goto out; db = &s->dma_dac; } else if (vma->vm_flags & VM_READ) { - if ((ret = prog_dmabuf(s, 0)) != 0) + if ((ret = prog_dmabuf(s, 1)) != 0) goto out; db = &s->dma_adc; - } else + } else goto out; ret = -EINVAL; if (vma->vm_pgoff != 0) @@ -1428,7 +1896,7 @@ size = vma->vm_end - vma->vm_start; if (size > (PAGE_SIZE << db->buforder)) goto out; - ret = -EAGAIN; + ret = -EINVAL; if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot)) goto out; db->mapped = 1; @@ -1463,13 +1931,15 @@ return 0; case SNDCTL_DSP_GETCAPS: - return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP, (int *)arg); + return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP | DSP_CAP_BIND, (int *)arg); case SNDCTL_DSP_RESET: if (file->f_mode & FMODE_WRITE) { stop_dac(s); synchronize_irq(); s->dma_dac.swptr = s->dma_dac.hwptr = s->dma_dac.count = s->dma_dac.total_bytes = 0; + if (s->status & DO_DUAL_DAC) + s->dma_adc.swptr = s->dma_adc.hwptr = s->dma_adc.count = s->dma_adc.total_bytes = 0; } if (file->f_mode & FMODE_READ) { stop_adc(s); @@ -1479,24 +1949,28 @@ return 0; case SNDCTL_DSP_SPEED: - if (get_user(val, (int *)arg)) + if (get_user(val, (int *)arg)) return -EFAULT; if (val >= 0) { if (file->f_mode & FMODE_READ) { - stop_adc(s); + spin_lock_irqsave(&s->lock, flags); + stop_adc_unlocked(s); s->dma_adc.ready = 0; - set_adc_rate(s, val); + set_adc_rate_unlocked(s, val); + spin_unlock_irqrestore(&s->lock, flags); } if (file->f_mode & FMODE_WRITE) { stop_dac(s); s->dma_dac.ready = 0; + if (s->status & DO_DUAL_DAC) + s->dma_adc.ready = 0; set_dac_rate(s, val); } } return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg); - + case SNDCTL_DSP_STEREO: - if (get_user(val, (int *)arg)) + if (get_user(val, (int *)arg)) return -EFAULT; fmtd = 0; fmtm = ~0; @@ -1515,12 +1989,19 @@ fmtd |= CM_CFMT_STEREO << CM_CFMT_DACSHIFT; else fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_DACSHIFT); + if (s->status & DO_DUAL_DAC) { + s->dma_adc.ready = 0; + if (val) + fmtd |= CM_CFMT_STEREO << CM_CFMT_ADCSHIFT; + else + fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_ADCSHIFT); + } } set_fmt(s, fmtm, fmtd); return 0; case SNDCTL_DSP_CHANNELS: - if (get_user(val, (int *)arg)) + if (get_user(val, (int *)arg)) return -EFAULT; if (val != 0) { fmtd = 0; @@ -1540,14 +2021,26 @@ fmtd |= CM_CFMT_STEREO << CM_CFMT_DACSHIFT; else fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_DACSHIFT); + if (s->status & DO_DUAL_DAC) { + s->dma_adc.ready = 0; + if (val >= 2) + fmtd |= CM_CFMT_STEREO << CM_CFMT_ADCSHIFT; + else + fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_ADCSHIFT); + } } set_fmt(s, fmtm, fmtd); - } + if ((s->capability & CAN_MULTI_CH) + && (file->f_mode & FMODE_WRITE)) { + val = set_dac_channels(s, val); + return put_user(val, (int *)arg); + } + } return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (CM_CFMT_STEREO << CM_CFMT_ADCSHIFT) : (CM_CFMT_STEREO << CM_CFMT_DACSHIFT))) ? 2 : 1, (int *)arg); case SNDCTL_DSP_GETFMTS: /* Returns a mask */ - return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg); + return put_user(AFMT_S16_LE|AFMT_U8|AFMT_AC3, (int *)arg); case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ if (get_user(val, (int *)arg)) @@ -1566,27 +2059,47 @@ if (file->f_mode & FMODE_WRITE) { stop_dac(s); s->dma_dac.ready = 0; - if (val == AFMT_S16_LE) + if (val == AFMT_S16_LE || val == AFMT_AC3) fmtd |= CM_CFMT_16BIT << CM_CFMT_DACSHIFT; else fmtm &= ~(CM_CFMT_16BIT << CM_CFMT_DACSHIFT); + if (val == AFMT_AC3) { + fmtd |= CM_CFMT_STEREO << CM_CFMT_DACSHIFT; + set_ac3(s, s->ratedac); + } else + set_ac3(s, 0); + if (s->status & DO_DUAL_DAC) { + s->dma_adc.ready = 0; + if (val == AFMT_S16_LE) + fmtd |= CM_CFMT_STEREO << CM_CFMT_ADCSHIFT; + else + fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_ADCSHIFT); + } } set_fmt(s, fmtm, fmtd); } - return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (CM_CFMT_16BIT << CM_CFMT_ADCSHIFT) + if (s->status & DO_AC3) return put_user(AFMT_AC3, (int *)arg); + return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (CM_CFMT_16BIT << CM_CFMT_ADCSHIFT) : (CM_CFMT_16BIT << CM_CFMT_DACSHIFT))) ? AFMT_S16_LE : AFMT_U8, (int *)arg); - + case SNDCTL_DSP_POST: return 0; case SNDCTL_DSP_GETTRIGGER: val = 0; - if (file->f_mode & FMODE_READ && s->enable & CM_CENABLE_RE) + if (s->status & DO_DUAL_DAC) { + if (file->f_mode & FMODE_WRITE && + (s->enable & CM_ENABLE_CH1) && + (s->enable & CM_ENABLE_CH0)) + val |= PCM_ENABLE_OUTPUT; + return put_user(val, (int *)arg); + } + if (file->f_mode & FMODE_READ && s->enable & CM_ENABLE_CH0) val |= PCM_ENABLE_INPUT; - if (file->f_mode & FMODE_WRITE && s->enable & CM_CENABLE_PE) + if (file->f_mode & FMODE_WRITE && s->enable & CM_ENABLE_CH1) val |= PCM_ENABLE_OUTPUT; return put_user(val, (int *)arg); - + case SNDCTL_DSP_SETTRIGGER: if (get_user(val, (int *)arg)) return -EFAULT; @@ -1602,6 +2115,10 @@ if (val & PCM_ENABLE_OUTPUT) { if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0))) return ret; + if (s->status & DO_DUAL_DAC) { + if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1))) + return ret; + } start_dac(s); } else stop_dac(s); @@ -1611,22 +2128,22 @@ case SNDCTL_DSP_GETOSPACE: if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; - if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0))) - return ret; + if (!(s->enable & CM_ENABLE_CH1) && (val = prog_dmabuf(s, 0)) != 0) + return val; spin_lock_irqsave(&s->lock, flags); cm_update_ptr(s); abinfo.fragsize = s->dma_dac.fragsize; abinfo.bytes = s->dma_dac.dmasize - s->dma_dac.count; abinfo.fragstotal = s->dma_dac.numfrag; - abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift; + abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift; spin_unlock_irqrestore(&s->lock, flags); return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; case SNDCTL_DSP_GETISPACE: if (!(file->f_mode & FMODE_READ)) return -EINVAL; - if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1))) - return ret; + if (!(s->enable & CM_ENABLE_CH0) && (val = prog_dmabuf(s, 1)) != 0) + return val; spin_lock_irqsave(&s->lock, flags); cm_update_ptr(s); abinfo.fragsize = s->dma_adc.fragsize; @@ -1643,8 +2160,6 @@ case SNDCTL_DSP_GETODELAY: if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; - if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0))) - return ret; spin_lock_irqsave(&s->lock, flags); cm_update_ptr(s); val = s->dma_dac.count; @@ -1654,8 +2169,6 @@ case SNDCTL_DSP_GETIPTR: if (!(file->f_mode & FMODE_READ)) return -EINVAL; - if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1))) - return ret; spin_lock_irqsave(&s->lock, flags); cm_update_ptr(s); cinfo.bytes = s->dma_adc.total_bytes; @@ -1669,8 +2182,6 @@ case SNDCTL_DSP_GETOPTR: if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; - if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0))) - return ret; spin_lock_irqsave(&s->lock, flags); cm_update_ptr(s); cinfo.bytes = s->dma_dac.total_bytes; @@ -1678,6 +2189,10 @@ cinfo.ptr = s->dma_dac.hwptr; if (s->dma_dac.mapped) s->dma_dac.count &= s->dma_dac.fragsize-1; + if (s->status & DO_DUAL_DAC) { + if (s->dma_adc.mapped) + s->dma_adc.count &= s->dma_adc.fragsize-1; + } spin_unlock_irqrestore(&s->lock, flags); return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); @@ -1685,6 +2200,11 @@ if (file->f_mode & FMODE_WRITE) { if ((val = prog_dmabuf(s, 0))) return val; + if (s->status & DO_DUAL_DAC) { + if ((val = prog_dmabuf(s, 1))) + return val; + return put_user(2 * s->dma_dac.fragsize, (int *)arg); + } return put_user(s->dma_dac.fragsize, (int *)arg); } if ((val = prog_dmabuf(s, 1))) @@ -1692,7 +2212,7 @@ return put_user(s->dma_adc.fragsize, (int *)arg); case SNDCTL_DSP_SETFRAGMENT: - if (get_user(val, (int *)arg)) + if (get_user(val, (int *)arg)) return -EFAULT; if (file->f_mode & FMODE_READ) { s->dma_adc.ossfragshift = val & 0xffff; @@ -1713,6 +2233,10 @@ s->dma_dac.ossfragshift = 15; if (s->dma_dac.ossmaxfrags < 4) s->dma_dac.ossmaxfrags = 4; + if (s->status & DO_DUAL_DAC) { + s->dma_adc.ossfragshift = s->dma_dac.ossfragshift; + s->dma_adc.ossmaxfrags = s->dma_dac.ossmaxfrags; + } } return 0; @@ -1720,14 +2244,17 @@ if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) || (file->f_mode & FMODE_WRITE && s->dma_dac.subdivision)) return -EINVAL; - if (get_user(val, (int *)arg)) + if (get_user(val, (int *)arg)) return -EFAULT; if (val != 1 && val != 2 && val != 4) return -EINVAL; if (file->f_mode & FMODE_READ) s->dma_adc.subdivision = val; - if (file->f_mode & FMODE_WRITE) + if (file->f_mode & FMODE_WRITE) { s->dma_dac.subdivision = val; + if (s->status & DO_DUAL_DAC) + s->dma_adc.subdivision = val; + } return 0; case SOUND_PCM_READ_RATE: @@ -1742,7 +2269,63 @@ case SOUND_PCM_READ_FILTER: return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg); - case SOUND_PCM_WRITE_FILTER: + case SNDCTL_DSP_GETCHANNELMASK: + return put_user(DSP_BIND_FRONT|DSP_BIND_SURR|DSP_BIND_CENTER_LFE|DSP_BIND_SPDIF, (int *)arg); + + case SNDCTL_DSP_BIND_CHANNEL: + if (get_user(val, (int *)arg)) + return -EFAULT; + if (val == DSP_BIND_QUERY) { + val = DSP_BIND_FRONT; + if (s->status & DO_SPDIF_OUT) + val |= DSP_BIND_SPDIF; + else { + if (s->curr_channels == 4) + val |= DSP_BIND_SURR; + if (s->curr_channels > 4) + val |= DSP_BIND_CENTER_LFE; + } + } else { + if (file->f_mode & FMODE_READ) { + stop_adc(s); + s->dma_adc.ready = 0; + } + if (file->f_mode & FMODE_WRITE) { + stop_dac(s); + s->dma_dac.ready = 0; + if (val & DSP_BIND_SPDIF) { + set_spdifout(s, s->ratedac); + set_dac_channels(s, s->fmt & (CM_CFMT_STEREO << CM_CFMT_DACSHIFT) ? 2 : 1); + if (!(s->status & DO_SPDIF_OUT)) + val &= ~DSP_BIND_SPDIF; + } else { + int channels; + int mask; + + mask = val & (DSP_BIND_FRONT|DSP_BIND_SURR|DSP_BIND_CENTER_LFE); + switch (mask) { + case DSP_BIND_FRONT: + channels = 2; + break; + case DSP_BIND_FRONT|DSP_BIND_SURR: + channels = 4; + break; + case DSP_BIND_FRONT|DSP_BIND_SURR|DSP_BIND_CENTER_LFE: + channels = 6; + break; + default: + channels = s->fmt & (CM_CFMT_STEREO << CM_CFMT_DACSHIFT) ? 2 : 1; + break; + } + set_dac_channels(s, channels); + } + } + } + return put_user(val, (int *)arg); + + case SOUND_PCM_WRITE_FILTER: + case SNDCTL_DSP_MAPINBUF: + case SNDCTL_DSP_MAPOUTBUF: case SNDCTL_DSP_SETSYNCRO: return -EINVAL; @@ -1788,6 +2371,12 @@ fmts |= CM_CFMT_16BIT << CM_CFMT_DACSHIFT; s->dma_dac.ossfragshift = s->dma_dac.ossmaxfrags = s->dma_dac.subdivision = 0; set_dac_rate(s, 8000); + // clear previous multichannel, spdif, ac3 state + set_spdifout(s, 0); + if (s->deviceid == PCI_DEVICE_ID_CMEDIA_CM8738) { + set_ac3(s, 0); + set_dac_channels(s, 1); + } } set_fmt(s, fmtm, fmts); s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); @@ -1806,11 +2395,23 @@ down(&s->open_sem); if (file->f_mode & FMODE_WRITE) { stop_dac(s); +#ifndef FIXEDDMA dealloc_dmabuf(&s->dma_dac); + if (s->status & DO_DUAL_DAC) + dealloc_dmabuf(&s->dma_adc); +#endif + if (s->status & DO_MULTI_CH) + set_dac_channels(s, 0); + if (s->status & DO_AC3) + set_ac3(s, 0); + if (s->status & DO_SPDIF_OUT) + set_spdifout(s, 0); } if (file->f_mode & FMODE_READ) { stop_adc(s); +#ifndef FIXEDDMA dealloc_dmabuf(&s->dma_adc); +#endif } s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE); up(&s->open_sem); @@ -1831,6 +2432,7 @@ release: cm_release, }; +#ifdef CONFIG_SOUND_CMPCI_MIDI /* --------------------------------------------------------------------- */ static ssize_t cm_midi_read(struct file *file, char *buffer, size_t count, loff_t *ppos) @@ -1847,12 +2449,9 @@ return -ESPIPE; if (!access_ok(VERIFY_WRITE, buffer, count)) return -EFAULT; - if (count == 0) - return 0; ret = 0; add_wait_queue(&s->midi.iwait, &wait); while (count > 0) { - set_current_state(TASK_INTERRUPTIBLE); spin_lock_irqsave(&s->lock, flags); ptr = s->midi.ird; cnt = MIDIINBUF - ptr; @@ -1862,14 +2461,15 @@ if (cnt > count) cnt = count; if (cnt <= 0) { - if (file->f_flags & O_NONBLOCK) + if (file->f_flags & O_NONBLOCK) { if (!ret) ret = -EAGAIN; break; } + __set_current_state(TASK_INTERRUPTIBLE); schedule(); - if (signal_pending(current)) + if (signal_pending(current)) { if (!ret) ret = -ERESTARTSYS; @@ -1877,7 +2477,8 @@ } continue; } - if (copy_to_user(buffer, s->midi.ibuf + ptr, cnt)) { + if (copy_to_user(buffer, s->midi.ibuf + ptr, cnt)) + { if (!ret) ret = -EFAULT; break; @@ -1916,7 +2517,6 @@ ret = 0; add_wait_queue(&s->midi.owait, &wait); while (count > 0) { - set_current_state(TASK_INTERRUPTIBLE); spin_lock_irqsave(&s->lock, flags); ptr = s->midi.owr; cnt = MIDIOUTBUF - ptr; @@ -1928,11 +2528,13 @@ if (cnt > count) cnt = count; if (cnt <= 0) { - if (file->f_flags & O_NONBLOCK) { + if (file->f_flags & O_NONBLOCK) + { if (!ret) ret = -EAGAIN; break; } + __set_current_state(TASK_INTERRUPTIBLE); schedule(); if (signal_pending(current)) { if (!ret) @@ -1941,7 +2543,8 @@ } continue; } - if (copy_from_user(s->midi.obuf + ptr, buffer, cnt)) { + if (copy_from_user(s->midi.obuf + ptr, buffer, cnt)) + { if (!ret) ret = -EFAULT; break; @@ -2017,7 +2620,7 @@ s->midi.ird = s->midi.iwr = s->midi.icnt = 0; s->midi.ord = s->midi.owr = s->midi.ocnt = 0; /* enable MPU-401 */ - outb(inb(s->iobase + CODEC_CMI_FUNCTRL1) | 4, s->iobase + CODEC_CMI_FUNCTRL1); + maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 4); outb(0xff, s->iomidi+1); /* reset command */ if (!(inb(s->iomidi+1) & 0x80)) inb(s->iomidi); @@ -2040,23 +2643,24 @@ spin_unlock_irqrestore(&s->lock, flags); s->open_mode |= (file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE); up(&s->open_sem); + MOD_INC_USE_COUNT; return 0; } static int cm_midi_release(struct inode *inode, struct file *file) { struct cm_state *s = (struct cm_state *)file->private_data; - DECLARE_WAITQUEUE(wait, current); + DECLARE_WAITQUEUE(wait, current); unsigned long flags; unsigned count, tmo; VALIDATE_STATE(s); - lock_kernel(); + if (file->f_mode & FMODE_WRITE) { + __set_current_state(TASK_INTERRUPTIBLE); add_wait_queue(&s->midi.owait, &wait); for (;;) { - set_current_state(TASK_INTERRUPTIBLE); spin_lock_irqsave(&s->lock, flags); count = s->midi.ocnt; spin_unlock_irqrestore(&s->lock, flags); @@ -2067,11 +2671,12 @@ if (file->f_flags & O_NONBLOCK) { remove_wait_queue(&s->midi.owait, &wait); set_current_state(TASK_RUNNING); + unlock_kernel(); return -EBUSY; } tmo = (count * HZ) / 3100; if (!schedule_timeout(tmo ? : 1) && tmo) - printk(KERN_DEBUG "cmpci: midi timed out??\n"); + printk(KERN_DEBUG "cm: midi timed out??\n"); } remove_wait_queue(&s->midi.owait, &wait); set_current_state(TASK_RUNNING); @@ -2085,7 +2690,7 @@ if (!(inb(s->iomidi+1) & 0x80)) inb(s->iomidi); /* disable MPU-401 */ - outb(inb(s->iobase + CODEC_CMI_FUNCTRL1) & ~4, s->iobase + CODEC_CMI_FUNCTRL1); + maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~4, 0); } spin_unlock_irqrestore(&s->lock, flags); up(&s->open_sem); @@ -2103,9 +2708,11 @@ open: cm_midi_open, release: cm_midi_release, }; +#endif /* --------------------------------------------------------------------- */ +#ifdef CONFIG_SOUND_CMPCI_FM static int cm_dmfm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { static const unsigned char op_offset[18] = { @@ -2197,10 +2804,8 @@ outb(5, s->iosynth+2); outb(arg & 1, s->iosynth+3); return 0; - - default: - return -EINVAL; } + return -EINVAL; } static int cm_dmfm_open(struct inode *inode, struct file *file) @@ -2236,6 +2841,7 @@ outb(1, s->iosynth+3); /* enable OPL3 */ s->open_mode |= FMODE_DMFM; up(&s->open_sem); + MOD_INC_USE_COUNT; return 0; } @@ -2267,6 +2873,7 @@ open: cm_dmfm_open, release: cm_dmfm_release, }; +#endif /* CONFIG_SOUND_CMPCI_FM */ /* --------------------------------------------------------------------- */ @@ -2285,46 +2892,125 @@ int mixch; int vol; } initvol[] __initdata = { - { SOUND_MIXER_WRITE_CD, 0x4040 }, - { SOUND_MIXER_WRITE_LINE, 0x4040 }, - { SOUND_MIXER_WRITE_MIC, 0x4040 }, - { SOUND_MIXER_WRITE_SYNTH, 0x4040 }, - { SOUND_MIXER_WRITE_VOLUME, 0x4040 }, - { SOUND_MIXER_WRITE_PCM, 0x4040 } + { SOUND_MIXER_WRITE_CD, 0x4f4f }, + { SOUND_MIXER_WRITE_LINE, 0x4f4f }, + { SOUND_MIXER_WRITE_MIC, 0x4f4f }, + { SOUND_MIXER_WRITE_SYNTH, 0x4f4f }, + { SOUND_MIXER_WRITE_VOLUME, 0x4f4f }, + { SOUND_MIXER_WRITE_PCM, 0x4f4f } }; -#ifdef MODULE -static int spdif_loop = 0; -static int four_ch = 0; -static int rear_out = 0; -MODULE_PARM(spdif_loop, "i"); -MODULE_PARM(four_ch, "i"); -MODULE_PARM(rear_out, "i"); +/* check chip version and capability */ +static int query_chip(struct cm_state *s) +{ + int ChipVersion = -1; + unsigned char RegValue; + + // check reg 0Ch, bit 24-31 + RegValue = inb(s->iobase + CODEC_CMI_INT_HLDCLR + 3); + if (RegValue == 0) { + // check reg 08h, bit 24-28 + RegValue = inb(s->iobase + CODEC_CMI_CHFORMAT + 3); + RegValue &= 0x1f; + if (RegValue == 0) { + ChipVersion = 33; + s->max_channels = 4; + s->capability |= CAN_AC3_SW; + s->capability |= CAN_DUAL_DAC; + } else { + ChipVersion = 37; + s->max_channels = 4; + s->capability |= CAN_AC3_HW; + s->capability |= CAN_DUAL_DAC; + } + } else { + // check reg 0Ch, bit 26 + if (RegValue & (1 << (26-24))) { + ChipVersion = 39; + if (RegValue & (1 << (24-24))) + s->max_channels = 6; + else + s->max_channels = 4; + s->capability |= CAN_AC3_HW; + s->capability |= CAN_DUAL_DAC; + s->capability |= CAN_MULTI_CH_HW; + } else { + ChipVersion = 55; // 4 or 6 channels + s->max_channels = 6; + s->capability |= CAN_AC3_HW; + s->capability |= CAN_DUAL_DAC; + s->capability |= CAN_MULTI_CH_HW; + } + } + // still limited to number of speakers + if (s->max_channels > s->speakers) + s->max_channels = s->speakers; + return ChipVersion; +} + +#ifdef CONFIG_SOUND_CMPCI_MIDI +static int mpu_io = CONFIG_SOUND_CMPCI_MPUIO; #else +static int mpu_io; +#endif +#ifdef CONFIG_SOUND_CMPCI_FM +static int fm_io = CONFIG_SOUND_CMPCI_FMIO; +#else +static int fm_io; +#endif +#ifdef CONFIG_SOUND_CMPCI_SPDIFINVERSE +static int spdif_inverse = 1; +#else +static int spdif_inverse; +#endif #ifdef CONFIG_SOUND_CMPCI_SPDIFLOOP -static int spdif_loop = 1; +static int spdif_loop = 1; +#else +static int spdif_loop; +#endif +#ifdef CONFIG_SOUND_CMPCI_SPEAKERS +static int speakers = CONFIG_SOUND_CMPCI_SPEAKERS; #else -static int spdif_loop = 0; +static int speakers = 2; #endif -#ifdef CONFIG_SOUND_CMPCI_4CH -static int four_ch = 1; +#ifdef CONFIG_SOUND_CMPCI_LINE_REAR +static int use_line_as_rear = 1; #else -static int four_ch = 0; +static int use_line_as_rear; #endif -#ifdef CONFIG_SOUND_CMPCI_REAR -static int rear_out = 1; +#ifdef CONFIG_SOUND_CMPCI_LINE_BASS +static int use_line_as_bass = 1; #else -static int rear_out = 0; +static int use_line_as_bass; #endif +#ifdef CONFIG_SOUND_CMPCI_JOYSTICK +static int joystick = 1; +#else +static int joystick; #endif +MODULE_PARM(mpu_io, "i"); +MODULE_PARM(fm_io, "i"); +MODULE_PARM(spdif_inverse, "i"); +MODULE_PARM(spdif_loop, "i"); +MODULE_PARM(speakers, "i"); +MODULE_PARM(use_line_as_rear, "i"); +MODULE_PARM(use_line_as_bass, "i"); +MODULE_PARM(joystick, "i"); +MODULE_PARM_DESC(mpu_io, "(0x330, 0x320, 0x310, 0x300) Base of MPU-401, 0 to disable"); +MODULE_PARM_DESC(fm_io, "(0x388, 0x3C8, 0x3E0) Base of OPL3, 0 to disable"); +MODULE_PARM_DESC(spdif_inverse, "(1/0) Invert S/PDIF-in signal"); +MODULE_PARM_DESC(spdif_loop, "(1/0) Route S/PDIF-in to S/PDIF-out directly"); +MODULE_PARM_DESC(speakers, "(2-6) Number of speakers you connect"); +MODULE_PARM_DESC(use_line_as_rear, "(1/0) Use line-in jack as rear-out"); +MODULE_PARM_DESC(use_line_as_bass, "(1/0) Use line-in jack as bass/center"); +MODULE_PARM_DESC(joystick, "(1/0) Enable joystick interface, still need joystick driver"); -static int __init init_cmpci(void) +void initialize_chip(struct pci_dev *pcidev) { struct cm_state *s; - struct pci_dev *pcidev = NULL; mm_segment_t fs; - int i, val, index = 0; - + int i, val; + unsigned char reg_mask = 0; struct { unsigned short deviceid; char *devicename; @@ -2333,33 +3019,21 @@ { PCI_DEVICE_ID_CMEDIA_CM8338A, "CM8338A" }, { PCI_DEVICE_ID_CMEDIA_CM8338B, "CM8338B" }, { PCI_DEVICE_ID_CMEDIA_CM8738, "CM8738" }, + { PCI_DEVICE_ID_CMEDIA_CM8738B, "CM8738B" }, }; char *devicename = "unknown"; - -#ifdef CONFIG_PCI - if (!pci_present()) /* No PCI bus in this machine! */ -#endif - return -ENODEV; - printk(KERN_INFO "cmpci: version v2.41-nomodem time " __TIME__ " " __DATE__ "\n"); -#if 0 - if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT))) - printk(KERN_INFO "cmpci: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n"); -#endif - while (index < NR_DEVICE && pcidev == NULL && ( - (pcidev = pci_find_device(PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338A, pcidev)) || - (pcidev = pci_find_device(PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338B, pcidev)) || - (pcidev = pci_find_device(PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738, pcidev)))) { + { if (pci_enable_device(pcidev)) - continue; + return; if (pcidev->irq == 0) - continue; - if (!(s = kmalloc(sizeof(struct cm_state), GFP_KERNEL))) { - printk(KERN_WARNING "cmpci: out of memory\n"); - continue; + return; + s = kmalloc(sizeof(*s), GFP_KERNEL); + if (!s) { + printk(KERN_WARNING "cm: out of memory\n"); + return; } /* search device name */ - for (i = 0; i < sizeof(devicetable) / sizeof(devicetable[0]); i++) - { + for (i = 0; i < sizeof(devicetable) / sizeof(devicetable[0]); i++) { if (devicetable[i].deviceid == pcidev->device) { devicename = devicetable[i].devicename; @@ -2376,35 +3050,96 @@ spin_lock_init(&s->lock); s->magic = CM_MAGIC; s->iobase = pci_resource_start(pcidev, 0); - s->iosynth = 0x388; - s->iomidi = 0x330; - spin_lock_init(&s->lock); + s->iosynth = fm_io; + s->iomidi = mpu_io; + s->status = 0; + /* range check */ + if (speakers < 2) + speakers = 2; + else if (speakers > 6) + speakers = 6; + s->speakers = speakers; if (s->iobase == 0) - continue; + return; s->irq = pcidev->irq; if (!request_region(s->iobase, CM_EXTENT_CODEC, "cmpci")) { - printk(KERN_ERR "cmpci: io ports %#x-%#x in use\n", s->iobase, s->iobase+CM_EXTENT_CODEC-1); + printk(KERN_ERR "cm: io ports %#x-%#x in use\n", s->iobase, s->iobase+CM_EXTENT_CODEC-1); goto err_region5; } - if (!request_region(s->iomidi, CM_EXTENT_MIDI, "cmpci Midi")) { - printk(KERN_WARNING "cmpci: io ports %#x-%#x in use, midi disabled.\n", s->iomidi, s->iomidi+CM_EXTENT_MIDI-1); +#ifdef CONFIG_SOUND_CMPCI_MIDI + /* disable MPU-401 */ + maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x04, 0); + if (s->iomidi) { + if (!request_region(s->iomidi, CM_EXTENT_MIDI, "cmpci Midi")) { + printk(KERN_ERR "cm: io ports %#x-%#x in use\n", s->iomidi, s->iomidi+CM_EXTENT_MIDI-1); s->iomidi = 0; + } else { + /* set IO based at 0x330 */ + switch (s->iomidi) { + case 0x330: + reg_mask = 0; + break; + case 0x320: + reg_mask = 0x20; + break; + case 0x310: + reg_mask = 0x40; + break; + case 0x300: + reg_mask = 0x60; + break; + default: + s->iomidi = 0; + break; + } + outb((inb(s->iobase + CODEC_CMI_LEGACY_CTRL + 3) & ~0x60) | reg_mask, s->iobase + CODEC_CMI_LEGACY_CTRL + 3); + /* enable MPU-401 */ + if (s->iomidi) { + maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x04); + } + } } - else - { - /* set IO based at 0x330 */ - outb(inb(s->iobase + CODEC_CMI_LEGACY_CTRL + 3) & ~0x60, s->iobase + CODEC_CMI_LEGACY_CTRL + 3); - } - if (!request_region(s->iosynth, CM_EXTENT_SYNTH, "cmpci FM")) { - printk(KERN_WARNING "cmpci: io ports %#x-%#x in use, synth disabled.\n", s->iosynth, s->iosynth+CM_EXTENT_SYNTH-1); +#endif +#ifdef CONFIG_SOUND_CMPCI_FM + /* disable FM */ + maskb(s->iobase + CODEC_CMI_MISC_CTRL + 2, ~8, 0); + if (s->iosynth) { + if (!request_region(s->iosynth, CM_EXTENT_SYNTH, "cmpci FM")) { + printk(KERN_ERR "cm: io ports %#x-%#x in use\n", s->iosynth, s->iosynth+CM_EXTENT_SYNTH-1); s->iosynth = 0; + } else { + /* set IO based at 0x388 */ + switch (s->iosynth) { + case 0x388: + reg_mask = 0; + break; + case 0x3C8: + reg_mask = 0x01; + break; + case 0x3E0: + reg_mask = 0x02; + break; + case 0x3E8: + reg_mask = 0x03; + break; + default: + s->iosynth = 0; + break; + } + maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 3, ~0x03, reg_mask); + /* enable FM */ + if (s->iosynth) { + maskb(s->iobase + CODEC_CMI_MISC_CTRL + 2, ~0, 8); + } + } } +#endif + /* enable joystick */ + if (joystick) + maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x02); else - { - /* enable FM */ - outb(inb(s->iobase + CODEC_CMI_MISC_CTRL + 2) | 8, s->iobase + CODEC_CMI_MISC_CTRL); - } + maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x02, 0); /* initialize codec registers */ outb(0, s->iobase + CODEC_CMI_INT_HLDCLR + 2); /* disable ints */ outb(0, s->iobase + CODEC_CMI_FUNCTRL0 + 2); /* disable channels */ @@ -2413,21 +3148,25 @@ /* request irq */ if (request_irq(s->irq, cm_interrupt, SA_SHIRQ, "cmpci", s)) { - printk(KERN_ERR "cmpci: irq %u in use\n", s->irq); + printk(KERN_ERR "cm: irq %u in use\n", s->irq); goto err_irq; } - printk(KERN_INFO "cmpci: found %s adapter at io %#06x irq %u\n", + printk(KERN_INFO "cm: found %s adapter at io %#06x irq %u\n", devicename, s->iobase, s->irq); /* register devices */ if ((s->dev_audio = register_sound_dsp(&cm_audio_fops, -1)) < 0) goto err_dev1; if ((s->dev_mixer = register_sound_mixer(&cm_mixer_fops, -1)) < 0) goto err_dev2; - if (s->iomidi && (s->dev_midi = register_sound_midi(&cm_midi_fops, -1)) < 0) +#ifdef CONFIG_SOUND_CMPCI_MIDI + if ((s->dev_midi = register_sound_midi(&cm_midi_fops, -1)) < 0) goto err_dev3; - if (s->iosynth && (s->dev_dmfm = register_sound_special(&cm_dmfm_fops, 15 /* ?? */)) < 0) +#endif +#ifdef CONFIG_SOUND_CMPCI_FM + if ((s->dev_dmfm = register_sound_special(&cm_dmfm_fops, 15 /* ?? */)) < 0) goto err_dev4; - pci_set_master(pcidev); +#endif + pci_set_master(pcidev); /* enable bus mastering */ /* initialize the chips */ fs = get_fs(); set_fs(KERNEL_DS); @@ -2440,59 +3179,78 @@ val = initvol[i].vol; mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val); } - set_fs(fs); - if (pcidev->device == PCI_DEVICE_ID_CMEDIA_CM8738) - { + /* use channel 0 for record, channel 1 for play */ + maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~2, 1); + s->deviceid = pcidev->device; + if (pcidev->device == PCI_DEVICE_ID_CMEDIA_CM8738) { + /* chip version and hw capability check */ + s->chip_version = query_chip(s); + printk(KERN_INFO "chip version = 0%d\n", s->chip_version); + /* seet SPDIF-in inverse before enable SPDIF loop */ + if (spdif_inverse) { + /* turn on spdif-in inverse */ + maskb(s->iobase + CODEC_CMI_CHFORMAT + 2, ~0, 1); + printk(KERN_INFO "cm: Inverse SPDIF-in\n"); + } else { + /* turn off spdif-ininverse */ + maskb(s->iobase + CODEC_CMI_CHFORMAT + 2, ~1, 0); + } + /* enable SPDIF loop */ - if (spdif_loop) - { + if (spdif_loop) { + s->status |= DO_SPDIF_LOOP; /* turn on spdif-in to spdif-out */ - outb(inb(s->iobase + CODEC_CMI_FUNCTRL1) | 0x80, s->iobase + CODEC_CMI_FUNCTRL1); - printk(KERN_INFO "cmpci: Enable SPDIF loop\n"); + maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x80); + printk(KERN_INFO "cm: Enable SPDIF loop\n"); + } else { + s->status &= ~DO_SPDIF_LOOP; + /* turn off spdif-in to spdif-out */ + maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x80, 0); } - else - outb(inb(s->iobase + CODEC_CMI_FUNCTRL1) & ~0x80, s->iobase + CODEC_CMI_FUNCTRL1); - /* enable 4 channels mode */ - if (four_ch) - { - /* 4 channel mode (analog duplicate) */ - outb(inb(s->iobase + CODEC_CMI_MISC_CTRL + 3) | 0x04, s->iobase + CODEC_CMI_MISC_CTRL + 3); - printk(KERN_INFO "cmpci: Enable 4 channels mode\n"); - /* has separate rear-out jack ? */ - if (rear_out) - { - /* has separate rear out jack */ - outb(inb(s->iobase + CODEC_CMI_MIXER1) & ~0x20, s->iobase + CODEC_CMI_MIXER1); - } - else - { - outb(inb(s->iobase + CODEC_CMI_MIXER1) | 0x20, s->iobase + CODEC_CMI_MIXER1); - printk(KERN_INFO "cmpci: line-in routed as rear-out\n"); - } + if (use_line_as_rear) { + s->capability |= CAN_LINE_AS_REAR; + s->status |= DO_LINE_AS_REAR; + maskb(s->iobase + CODEC_CMI_MIXER1, ~0, 0x20); + } else + maskb(s->iobase + CODEC_CMI_MIXER1, ~0x20, 0); + if (s->chip_version >= 39) { + if (use_line_as_bass) { + s->capability |= CAN_LINE_AS_BASS; + s->status |= DO_LINE_AS_BASS; + maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 1, ~0, 0x60); + } else + maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 1, ~0x60, 0); } - else - outb(inb(s->iobase + CODEC_CMI_MISC_CTRL + 3) & ~0x04, s->iobase + CODEC_CMI_MISC_CTRL + 3); + } else { + /* 8338 will fall here */ + s->max_channels = 2; } /* queue it for later freeing */ s->next = devs; devs = s; - index++; - continue; + return; +#ifdef CONFIG_SOUND_CMPCI_FM + unregister_sound_special(s->dev_dmfm); err_dev4: +#endif +#ifdef CONFIG_SOUND_CMPCI_MIDI unregister_sound_midi(s->dev_midi); err_dev3: +#endif unregister_sound_mixer(s->dev_mixer); err_dev2: unregister_sound_dsp(s->dev_audio); err_dev1: - printk(KERN_ERR "cmpci: cannot register misc device\n"); + printk(KERN_ERR "cm: cannot register misc device\n"); free_irq(s->irq, s); err_irq: - if(s->iosynth) - release_region(s->iosynth, CM_EXTENT_SYNTH); - if(s->iomidi) - release_region(s->iomidi, CM_EXTENT_MIDI); +#ifdef CONFIG_SOUND_CMPCI_FM + if (s->iosynth) release_region(s->iosynth, CM_EXTENT_SYNTH); +#endif +#ifdef CONFIG_SOUND_CMPCI_MIDI + if (s->iomidi) release_region(s->iomidi, CM_EXTENT_MIDI); +#endif release_region(s->iobase, CM_EXTENT_CODEC); err_region5: kfree(s); @@ -2500,15 +3258,47 @@ if (!devs) { if (wavetable_mem) free_pages(wavetable_mem, 20-PAGE_SHIFT); + return; + } + return; +} + +static int __init init_cmpci(void) +{ + struct pci_dev *pcidev = NULL; + int index = 0; + +#ifdef CONFIG_PCI + if (!pci_present()) /* No PCI bus in this machine! */ +#endif return -ENODEV; + printk(KERN_INFO "cm: version $Revision: 5.64 $ time " __TIME__ " " __DATE__ "\n"); +#if 0 + if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT))) + printk(KERN_INFO "cm: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n"); +#endif + while (index < NR_DEVICE && ( + (pcidev = pci_find_device(PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738, pcidev)))) { + initialize_chip(pcidev); + index++; + } + while (index < NR_DEVICE && ( + (pcidev = pci_find_device(PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338A, pcidev)))) { + initialize_chip(pcidev); + index++; + } + while (index < NR_DEVICE && ( + (pcidev = pci_find_device(PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338B, pcidev)))) { + initialize_chip(pcidev); + index++; } return 0; } /* --------------------------------------------------------------------- */ -MODULE_AUTHOR("ChenLi Tien, cltien@home.com"); -MODULE_DESCRIPTION("CMPCI Audio Driver"); +MODULE_AUTHOR("ChenLi Tien, cltien@cmedia.com.tw"); +MODULE_DESCRIPTION("CM8x38 Audio Driver"); static void __exit cleanup_cmpci(void) { @@ -2520,28 +3310,34 @@ synchronize_irq(); outb(0, s->iobase + CODEC_CMI_FUNCTRL0 + 2); /* disable channels */ free_irq(s->irq, s); +#ifdef FIXEDDMA + dealloc_dmabuf(&s->dma_dac); + dealloc_dmabuf(&s->dma_adc); +#endif /* reset mixer */ wrmixer(s, DSP_MIX_DATARESETIDX, 0); release_region(s->iobase, CM_EXTENT_CODEC); - if(s->iomidi) - { - release_region(s->iomidi, CM_EXTENT_MIDI); - unregister_sound_midi(s->dev_midi); - } - if(s->iosynth) - { - release_region(s->iosynth, CM_EXTENT_SYNTH); - unregister_sound_special(s->dev_dmfm); - } +#ifdef CONFIG_SOUND_CMPCI_MIDI + if (s->iomidi) release_region(s->iomidi, CM_EXTENT_MIDI); +#endif +#ifdef CONFIG_SOUND_CMPCI_FM + if (s->iosynth) release_region(s->iosynth, CM_EXTENT_SYNTH); +#endif unregister_sound_dsp(s->dev_audio); unregister_sound_mixer(s->dev_mixer); +#ifdef CONFIG_SOUND_CMPCI_MIDI + unregister_sound_midi(s->dev_midi); +#endif +#ifdef CONFIG_SOUND_CMPCI_FM + unregister_sound_special(s->dev_dmfm); +#endif kfree(s); } if (wavetable_mem) free_pages(wavetable_mem, 20-PAGE_SHIFT); - printk(KERN_INFO "cmpci: unloading\n"); + printk(KERN_INFO "cm: unloading\n"); } module_init(init_cmpci); diff -u --recursive --new-file v2.4.5/linux/drivers/sound/cs4232.c linux/drivers/sound/cs4232.c --- v2.4.5/linux/drivers/sound/cs4232.c Sat Nov 11 18:33:13 2000 +++ linux/drivers/sound/cs4232.c Mon Jul 2 13:56:41 2001 @@ -42,9 +42,11 @@ * Arnaldo C. de Melo got rid of attach_uart401 * Bartlomiej Zolnierkiewicz * Added some __init/__initdata/__exit + * Marcus Meissner Added ISA PnP support. */ #include +#include #include #include @@ -95,7 +97,7 @@ schedule_timeout(howlong); } -int __init probe_cs4232(struct address_info *hw_config) +int __init probe_cs4232(struct address_info *hw_config, int isapnp_configured) { int i, n; int base = hw_config->io_base, irq = hw_config->irq; @@ -110,8 +112,13 @@ printk(KERN_ERR "cs4232.c: I/O port 0x%03x not free\n", base); return 0; } - if (ad1848_detect(hw_config->io_base, NULL, hw_config->osp)) + if (ad1848_detect(hw_config->io_base, NULL, hw_config->osp)) { return 1; /* The card is already active */ + } + if (isapnp_configured) { + printk(KERN_ERR "cs4232.c: ISA PnP configured, but not detected?\n"); + return 0; + } /* * This version of the driver doesn't use the PnP method when configuring @@ -318,27 +325,97 @@ static int __initdata mpuirq = -1; static int __initdata synthio = -1; static int __initdata synthirq = -1; +static int __initdata isapnp = 1; - +MODULE_DESCRIPTION("CS4232 based soundcard driver"); +MODULE_AUTHOR("Hannu Savolainen, Paul Barton-Davis"); MODULE_PARM(io,"i"); +MODULE_PARM_DESC(io,"base I/O port for AD1848"); MODULE_PARM(irq,"i"); +MODULE_PARM_DESC(irq,"IRQ for AD1848 chip"); MODULE_PARM(dma,"i"); +MODULE_PARM_DESC(dma,"8 bit DMA for AD1848 chip"); MODULE_PARM(dma2,"i"); +MODULE_PARM_DESC(dma2,"16 bit DMA for AD1848 chip"); MODULE_PARM(mpuio,"i"); +MODULE_PARM_DESC(mpuio,"MPU 401 base address"); MODULE_PARM(mpuirq,"i"); +MODULE_PARM_DESC(mpuirq,"MPU 401 IRQ"); MODULE_PARM(synthio,"i"); +MODULE_PARM_DESC(synthio,"Maui WaveTable base I/O port"); MODULE_PARM(synthirq,"i"); +MODULE_PARM_DESC(synthirq,"Maui WaveTable IRQ"); +MODULE_PARM(isapnp,"i"); +MODULE_PARM_DESC(isapnp,"Enable ISAPnP probing (default 1)"); /* * Install a CS4232 based card. Need to have ad1848 and mpu401 * loaded ready. */ +/* All cs4232 based cards have the main ad1848 card either as CSC0000 or + * CSC0100. */ +struct isapnp_device_id isapnp_cs4232_list[] __initdata = { + { ISAPNP_ANY_ID, ISAPNP_ANY_ID, + ISAPNP_VENDOR('C','S','C'), ISAPNP_FUNCTION(0x0100), + 0 }, + { ISAPNP_ANY_ID, ISAPNP_ANY_ID, + ISAPNP_VENDOR('C','S','C'), ISAPNP_FUNCTION(0x0000), + 0 }, + /* Guillemot Turtlebeach something appears to be cs4232 compatible + * (untested) */ + { ISAPNP_VENDOR('C','S','C'), ISAPNP_ANY_ID, + ISAPNP_VENDOR('G','I','M'), ISAPNP_FUNCTION(0x0100), + 0 }, + {0} +}; + +MODULE_DEVICE_TABLE(isapnp, isapnp_cs4232_list); + +int cs4232_isapnp_probe(struct pci_dev *dev, const struct isapnp_device_id *id) +{ + int ret; + struct address_info *isapnpcfg; + + isapnpcfg=(struct address_info*)kmalloc(sizeof(*isapnpcfg),GFP_KERNEL); + if (!isapnpcfg) + return -ENOMEM; + /* + * If device is active, assume configured with /proc/isapnp + * and use anyway. Any other way to check this? + */ + ret = dev->prepare(dev); + if(ret && ret != -EBUSY) { + printk(KERN_ERR "cs4232: ISA PnP found device that could not be autoconfigured.\n"); + kfree(isapnpcfg); + return -ENODEV; + } + if(ret != -EBUSY) { + if(dev->activate(dev) < 0) { + printk(KERN_WARNING "cs4232: ISA PnP activate failed\n"); + kfree(isapnpcfg); + return -ENODEV; + } + } /* else subfunction is already activated */ + + isapnpcfg->irq = dev->irq_resource[0].start; + isapnpcfg->dma = dev->dma_resource[0].start; + isapnpcfg->dma2 = dev->dma_resource[1].start; + isapnpcfg->io_base = dev->resource[0].start; + if (probe_cs4232(isapnpcfg,TRUE) == 0) { + printk(KERN_ERR "cs4232: ISA PnP card found, but not detected?\n"); + return -ENODEV; + } + attach_cs4232(isapnpcfg); + pci_set_drvdata(dev,isapnpcfg); + return 0; +} + static int __init init_cs4232(void) { #ifdef CONFIG_SOUND_WAVEFRONT_MODULE if(synthio == -1) - printk(KERN_WARNING "cs4232: set synthio and synthirq to use the wavefront facilities.\n"); + printk(KERN_INFO "cs4232: set synthio and synthirq to use the wavefront facilities.\n"); else { synth_base = synthio; synth_irq = synthirq; @@ -347,6 +424,13 @@ if(synthio != -1) printk(KERN_WARNING "cs4232: wavefront support not enabled in this driver.\n"); #endif + cfg.irq = -1; + + if (isapnp && + (isapnp_probe_devs(isapnp_cs4232_list, cs4232_isapnp_probe) > 0) + ) + return 0; + if(io==-1||irq==-1||dma==-1) { printk(KERN_ERR "cs4232: Must set io, irq and dma.\n"); @@ -367,16 +451,27 @@ probe_cs4232_mpu(&cfg_mpu); /* Bug always returns 0 not OK -- AC */ } - if (probe_cs4232(&cfg) == 0) + if (probe_cs4232(&cfg,FALSE) == 0) return -ENODEV; attach_cs4232(&cfg); return 0; } +int cs4232_isapnp_remove(struct pci_dev *dev, const struct isapnp_device_id *id) +{ + struct address_info *cfg = (struct address_info*)pci_get_drvdata(dev); + if (cfg) unload_cs4232(cfg); + pci_set_drvdata(dev,NULL); + dev->deactivate(dev); + return 0; +} + static void __exit cleanup_cs4232(void) { - unload_cs4232(&cfg); /* unloads MPU as well, if needed */ + isapnp_probe_devs(isapnp_cs4232_list, cs4232_isapnp_remove); + if (cfg.irq != -1) + unload_cs4232(&cfg); /* Unloads global MPU as well, if needed */ } module_init(init_cs4232); @@ -387,6 +482,10 @@ { /* io, irq, dma, dma2 mpuio, mpuirq*/ int ints[7]; + + /* If we have isapnp cards, no need for options */ + if (isapnp_probe_devs(isapnp_cs4232_list, cs4232_isapnp_probe) > 0) + return 1; str = get_options(str, ARRAY_SIZE(ints), ints); diff -u --recursive --new-file v2.4.5/linux/drivers/sound/cs4232.h linux/drivers/sound/cs4232.h --- v2.4.5/linux/drivers/sound/cs4232.h Tue Mar 7 13:40:24 2000 +++ linux/drivers/sound/cs4232.h Mon Jul 2 13:56:41 2001 @@ -5,7 +5,7 @@ * */ -int probe_cs4232 (struct address_info *hw_config); +int probe_cs4232 (struct address_info *hw_config,int useisapnp); void attach_cs4232 (struct address_info *hw_config); int probe_cs4232_mpu (struct address_info *hw_config); void attach_cs4232_mpu (struct address_info *hw_config); diff -u --recursive --new-file v2.4.5/linux/drivers/sound/cs4281/cs4281m.c linux/drivers/sound/cs4281/cs4281m.c --- v2.4.5/linux/drivers/sound/cs4281/cs4281m.c Tue May 1 16:05:00 2001 +++ linux/drivers/sound/cs4281/cs4281m.c Wed Jun 27 17:10:55 2001 @@ -658,7 +658,7 @@ card->pBA0 + BA0_ACCTL); // Wait for the write to occur. - for (count = 0; count < 10; count++) { + for (count = 0; count < 100; count++) { // First, we want to wait for a short time. udelay(25); // Now, check to see if the write has completed. @@ -946,7 +946,7 @@ } #ifndef NOT_CS4281_PM -void printpm(struct cs4281_state *s) +static void printpm(struct cs4281_state *s) { CS_DBGOUT(CS_PM, 9, printk("pm struct:\n")); CS_DBGOUT(CS_PM, 9, printk("flags:0x%x u32CLKCR1_SAVE: 0%x u32SSPMValue: 0x%x\n", @@ -967,7 +967,7 @@ s->pm.u32MIDCR_Save)); } -void printpipe(struct cs4281_pipeline *pl) +static void printpipe(struct cs4281_pipeline *pl) { CS_DBGOUT(CS_PM, 9, printk("pm struct:\n")); @@ -1000,7 +1000,7 @@ CS_DBGOUT(CS_PM, 9, printk("u32FPDRnValue: 0x%x u32FPDRnAddress: 0x%x\n", pl->u32FPDRnValue,pl->u32FPDRnAddress)); } -void printpipelines(struct cs4281_state *s) +static void printpipelines(struct cs4281_state *s) { int i; for(i=0;idev_midi); iounmap(s->pBA1); iounmap(s->pBA0); - kfree(s); pci_set_drvdata(pci_dev,NULL); list_del(&s->list); + kfree(s); CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO "cs4281: cs4281_remove()-: remove successful\n")); } diff -u --recursive --new-file v2.4.5/linux/drivers/sound/cs46xx.c linux/drivers/sound/cs46xx.c --- v2.4.5/linux/drivers/sound/cs46xx.c Thu May 24 15:14:08 2001 +++ linux/drivers/sound/cs46xx.c Mon Jul 2 13:56:41 2001 @@ -50,6 +50,7 @@ * 20010409-tw add hercules game theatre XP amp code. * 20010420-tw cleanup powerdown/up code. * 20010521-tw eliminate pops, and fixes for powerdown. + * 20010525-tw added fixes for thinkpads with powerdown logic. * * Status: * Playback/Capture supported from 8k-48k. @@ -179,7 +180,7 @@ MODULE_PARM(hercules_egpio_disable, "i"); static unsigned long initdelay=700; /* PM delay in millisecs */ MODULE_PARM(initdelay, "i"); -static unsigned long powerdown=1; /* turn on/off powerdown processing in driver */ +static unsigned long powerdown=-1; /* turn on/off powerdown processing in driver */ MODULE_PARM(powerdown, "i"); #define DMABUF_DEFAULTORDER 3 static unsigned long defaultorder=DMABUF_DEFAULTORDER; @@ -190,6 +191,14 @@ static int thinkpad; MODULE_PARM(thinkpad, "i"); +/* +* set the powerdown module parm to 0 to disable all +* powerdown. also set thinkpad to 1 to disable powerdown, +* but also to enable the clkrun functionality. +*/ +static unsigned cs_powerdown=1; +static unsigned cs_laptop_wait=1; + /* An instance of the 4610 channel */ struct cs_channel { @@ -199,7 +208,7 @@ }; #define CS46XX_MAJOR_VERSION "1" -#define CS46XX_MINOR_VERSION "27" +#define CS46XX_MINOR_VERSION "28" #ifdef __ia64__ #define CS46XX_ARCH "64" //architecture key @@ -284,6 +293,8 @@ int ossmaxfrags; unsigned subdivision; } dmabuf; + /* Guard against mmap/write/read races */ + struct semaphore sem; }; struct cs_card { @@ -370,8 +381,10 @@ static loff_t cs_llseek(struct file *file, loff_t offset, int origin); static int cs_hardware_init(struct cs_card *card); static int cs46xx_powerup(struct cs_card *card, unsigned int type); -static int cs461x_powerdown(struct cs_card *card, unsigned int type); +static int cs461x_powerdown(struct cs_card *card, unsigned int type, int suspendflag); static void cs461x_clear_serial_FIFOs(struct cs_card *card, int type); +static int cs46xx_suspend_tbl(struct pci_dev *pcidev, u32 state); +static int cs46xx_resume_tbl(struct pci_dev *pcidev); static inline unsigned ld2(unsigned int x) { @@ -688,7 +701,7 @@ { struct ac97_codec *dev=card->ac97_codec[0]; - CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_mute()+ %s\n", + CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs46xx: cs_mute()+ %s\n", (state == CS_TRUE) ? "Muting" : "UnMuting") ); if(state == CS_TRUE) @@ -717,7 +730,7 @@ cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME_MONO, card->pm.u32AC97_master_volume_mono); cs_ac97_set(dev, (u8)BA0_AC97_PCM_OUT_VOLUME, card->pm.u32AC97_pcm_out_volume); } - CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_mute()-\n")); + CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs46xx: cs_mute()-\n")); } /* set playback sample rate */ @@ -1250,7 +1263,7 @@ dmabuf->SGok = 0; } -static int prog_dmabuf(struct cs_state *state) +static int __prog_dmabuf(struct cs_state *state) { struct dmabuf *dmabuf = &state->dmabuf; unsigned long flags; @@ -1431,6 +1444,17 @@ return 1; } +static int prog_dmabuf(struct cs_state *state) +{ + int ret; + + down(&state->sem); + ret = __prog_dmabuf(state); + up(&state->sem); + + return ret; +} + static void cs_clear_tail(struct cs_state *state) { } @@ -2089,11 +2113,12 @@ return -ESPIPE; if (dmabuf->mapped) return -ENXIO; - if (!dmabuf->ready && (ret = prog_dmabuf(state))) - return ret; if (!access_ok(VERIFY_WRITE, buffer, count)) return -EFAULT; - ret = 0; + + down(&state->sem); + if (!dmabuf->ready && (ret = __prog_dmabuf(state))) + goto out; add_wait_queue(&state->dmabuf.wait, &wait); while (count > 0) { @@ -2101,8 +2126,8 @@ { schedule(); if (signal_pending(current)) { - ret = ret ? ret : -ERESTARTSYS; - break; + if(!ret) ret = -ERESTARTSYS; + goto out; } } spin_lock_irqsave(&state->card->lock, flags); @@ -2122,12 +2147,20 @@ start_adc(state); if (file->f_flags & O_NONBLOCK) { if (!ret) ret = -EAGAIN; - break; + goto out; } + up(&state->sem); schedule(); if (signal_pending(current)) { - ret = ret ? ret : -ERESTARTSYS; - break; + if(!ret) ret = -ERESTARTSYS; + goto out; + } + down(&state->sem); + if (dmabuf->mapped) + { + if(!ret) + ret = -ENXIO; + goto out; } continue; } @@ -2142,7 +2175,7 @@ (void *)((unsigned)dmabuf->rawbuf + swptr), cnt, &copied)) { if (!ret) ret = -EFAULT; - break; + goto out; } swptr = (swptr + cnt) % dmabuf->dmasize; spin_lock_irqsave(&card->lock, flags); @@ -2154,6 +2187,8 @@ ret += copied; start_adc(state); } +out: + up(&state->sem); remove_wait_queue(&state->dmabuf.wait, &wait); set_current_state(TASK_RUNNING); CS_DBGOUT(CS_WAVE_READ | CS_FUNCTION, 4, @@ -2183,12 +2218,21 @@ if (ppos != &file->f_pos) return -ESPIPE; + + down(&state->sem); if (dmabuf->mapped) - return -ENXIO; - if (!dmabuf->ready && (ret = prog_dmabuf(state))) - return ret; + { + ret = -ENXIO; + goto out; + } + + if (!dmabuf->ready && (ret = __prog_dmabuf(state))) + goto out; if (!access_ok(VERIFY_READ, buffer, count)) - return -EFAULT; + { + ret = -EFAULT; + goto out; + } add_wait_queue(&state->dmabuf.wait, &wait); ret = 0; /* @@ -2200,8 +2244,8 @@ { schedule(); if (signal_pending(current)) { - ret = ret ? ret : -ERESTARTSYS; - break; + if(!ret) ret = -ERESTARTSYS; + goto out; } } spin_lock_irqsave(&state->card->lock, flags); @@ -2234,18 +2278,26 @@ start_dac(state); if (file->f_flags & O_NONBLOCK) { if (!ret) ret = -EAGAIN; - break; + goto out; } + up(&state->sem); schedule(); if (signal_pending(current)) { - ret = ret ? ret : -ERESTARTSYS; - break; + if(!ret) ret = -ERESTARTSYS; + goto out; } + down(&state->sem); + if (dmabuf->mapped) + { + if(!ret) + ret = -ENXIO; + goto out; + } continue; } if (copy_from_user(dmabuf->rawbuf + swptr, buffer, cnt)) { if (!ret) ret = -EFAULT; - return ret; + goto out; } spin_lock_irqsave(&state->card->lock, flags); swptr = (swptr + cnt) % dmabuf->dmasize; @@ -2265,6 +2317,8 @@ ret += cnt; start_dac(state); } +out: + up(&state->sem); remove_wait_queue(&state->dmabuf.wait, &wait); set_current_state(TASK_RUNNING); @@ -2352,9 +2406,9 @@ struct cs_card *card = (struct cs_card *)file->private_data; struct cs_state *state; struct dmabuf *dmabuf; - int ret; + int ret = 0; unsigned long size; - + CS_DBGOUT(CS_FUNCTION | CS_PARMS, 2, printk("cs46xx: cs_mmap()+ file=0x%x %s %s\n", (unsigned)file, vma->vm_flags & VM_WRITE ? "VM_WRITE" : "", vma->vm_flags & VM_READ ? "VM_READ" : "") ); @@ -2393,24 +2447,39 @@ */ state = card->states[1]; if(!(unsigned)state) - return -EINVAL; + { + ret = -EINVAL; + goto out; + } + down(&state->sem); dmabuf = &state->dmabuf; if (cs4x_pgoff(vma) != 0) - return -EINVAL; + { + ret = -EINVAL; + goto out; + } size = vma->vm_end - vma->vm_start; CS_DBGOUT(CS_PARMS, 2, printk("cs46xx: cs_mmap(): size=%d\n",(unsigned)size) ); if (size > (PAGE_SIZE << dmabuf->buforder)) - return -EINVAL; + { + ret = -EINVAL; + goto out; + } if (remap_page_range(vma->vm_start, virt_to_phys(dmabuf->rawbuf), size, vma->vm_page_prot)) - return -EAGAIN; + { + ret = -EAGAIN; + goto out; + } dmabuf->mapped = 1; CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_mmap()-\n") ); - return 0; +out: + up(&state->sem); + return ret; } static int cs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) @@ -3146,6 +3215,7 @@ if (state == NULL) return -ENOMEM; memset(state, 0, sizeof(struct cs_state)); + init_MUTEX(&state->sem); dmabuf = &state->dmabuf; dmabuf->pbuf = (void *)get_free_page(GFP_KERNEL | GFP_DMA); if(dmabuf->pbuf==NULL) @@ -3217,6 +3287,7 @@ if (state == NULL) return -ENOMEM; memset(state, 0, sizeof(struct cs_state)); + init_MUTEX(&state->sem); dmabuf = &state->dmabuf; dmabuf->pbuf = (void *)get_free_page(GFP_KERNEL | GFP_DMA); if(dmabuf->pbuf==NULL) @@ -3281,7 +3352,6 @@ if((ret = prog_dmabuf(state))) return ret; } - CS_DBGOUT(CS_OPEN | CS_FUNCTION, 2, printk("cs46xx: cs_open()- 0\n") ); return 0; } @@ -3321,11 +3391,10 @@ state->card->states[state->virt] = NULL; state->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE); - if( (tmp = cs461x_powerdown(card, CS_POWER_DAC )) ) + if( (tmp = cs461x_powerdown(card, CS_POWER_DAC, CS_FALSE )) ) { CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO "cs46xx: cs_release_mixdev() powerdown DAC failure (0x%x)\n",tmp) ); - return -EIO; } /* Now turn off external AMP if needed */ @@ -3355,11 +3424,10 @@ state->card->states[state->virt] = NULL; state->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE); - if( (tmp = cs461x_powerdown(card, CS_POWER_ADC )) ) + if( (tmp = cs461x_powerdown(card, CS_POWER_ADC, CS_FALSE )) ) { CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO "cs46xx: cs_release_mixdev() powerdown ADC failure (0x%x)\n",tmp) ); - return -EIO; } /* Now turn off external AMP if needed */ @@ -3375,7 +3443,7 @@ return 0; } -void printpm(struct cs_card *s) +static void printpm(struct cs_card *s) { CS_DBGOUT(CS_PM, 9, printk("pm struct:\n")); CS_DBGOUT(CS_PM, 9, printk("flags:0x%x u32CLKCR1_SAVE: 0%x u32SSPMValue: 0x%x\n", @@ -3419,8 +3487,8 @@ void cs46xx_ac97_suspend(struct cs_card *card) { int Count,i; - unsigned int tmp; struct ac97_codec *dev=card->ac97_codec[0]; + unsigned int tmp; CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_suspend()+\n")); @@ -3445,7 +3513,6 @@ * Save the ac97 volume registers as well as the current powerdown state. * Now, mute the all the outputs (master, headphone, and mono), as well * as the PCM volume, in preparation for powering down the entire part. -*/ card->pm.u32AC97_master_volume = (u32)cs_ac97_get( dev, (u8)BA0_AC97_MASTER_VOLUME); card->pm.u32AC97_headphone_volume = (u32)cs_ac97_get(dev, @@ -3454,22 +3521,27 @@ (u8)BA0_AC97_MASTER_VOLUME_MONO); card->pm.u32AC97_pcm_out_volume = (u32)cs_ac97_get(dev, (u8)BA0_AC97_PCM_OUT_VOLUME); - +*/ +/* +* mute the outputs +*/ cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME, 0x8000); cs_ac97_set(dev, (u8)BA0_AC97_HEADPHONE_VOLUME, 0x8000); cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME_MONO, 0x8000); cs_ac97_set(dev, (u8)BA0_AC97_PCM_OUT_VOLUME, 0x8000); +/* +* save the registers that cause pops +*/ card->pm.u32AC97_powerdown = (u32)cs_ac97_get(dev, (u8)AC97_POWER_CONTROL); card->pm.u32AC97_general_purpose = (u32)cs_ac97_get(dev, (u8)BA0_AC97_GENERAL_PURPOSE); - /* * And power down everything on the AC97 codec. * well, for now, only power down the DAC/ADC and MIXER VREFON components. * trouble with removing VREF. */ if( (tmp = cs461x_powerdown(card, CS_POWER_DAC | CS_POWER_ADC | - CS_POWER_MIXVON )) ) + CS_POWER_MIXVON, CS_TRUE )) ) { CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO "cs46xx: cs46xx_ac97_suspend() failure (0x%x)\n",tmp) ); @@ -3502,17 +3574,12 @@ */ cs_ac97_set(dev, (u8)BA0_AC97_GENERAL_PURPOSE, (u16)card->pm.u32AC97_general_purpose); - - cs_ac97_set(dev, (u8)AC97_POWER_CONTROL, - (u16)card->pm.u32AC97_powerdown); - mdelay(10); - /* * Now, while the outputs are still muted, restore the state of power * on the AC97 part. */ cs_ac97_set(dev, (u8)BA0_AC97_POWERDOWN, (u16)card->pm.u32AC97_powerdown); - mdelay(5); + mdelay(5 * cs_laptop_wait); /* * Restore just the first set of registers, from register number * 0x02 to the register number that ulHighestRegToRestore specifies. @@ -3544,7 +3611,7 @@ dmabuf->ready = 0; resync_dma_ptrs(card->states[1]); cs_set_divisor(dmabuf); - if(prog_dmabuf(card->states[1])) + if(__prog_dmabuf(card->states[1])) { CS_DBGOUT(CS_PM | CS_ERROR, 1, printk("cs46xx: cs46xx_restart_part()- (-1) prog_dmabuf() dac error\n")); @@ -3558,7 +3625,7 @@ dmabuf->ready = 0; resync_dma_ptrs(card->states[0]); cs_set_divisor(dmabuf); - if(prog_dmabuf(card->states[0])) + if(__prog_dmabuf(card->states[0])) { CS_DBGOUT(CS_PM | CS_ERROR, 1, printk("cs46xx: cs46xx_restart_part()- (-1) prog_dmabuf() adc error\n")); @@ -3588,7 +3655,7 @@ static void cs461x_reset(struct cs_card *card); static void cs461x_proc_stop(struct cs_card *card); -int cs46xx_suspend(struct cs_card *card) +static int cs46xx_suspend(struct cs_card *card, u32 state) { unsigned int tmp; CS_DBGOUT(CS_PM | CS_FUNCTION, 4, @@ -3680,7 +3747,7 @@ return 0; } -int cs46xx_resume(struct cs_card *card) +static int cs46xx_resume(struct cs_card *card) { int i; @@ -3704,7 +3771,7 @@ { CS_DBGOUT(CS_PM | CS_ERROR, 4, printk( "cs46xx: cs46xx_resume()- ERROR in cs_hardware_init()\n")); - mdelay(10); + mdelay(10 * cs_laptop_wait); cs461x_reset(card); continue; } @@ -3789,12 +3856,13 @@ if(!(card->pm.flags & CS46XX_PM_IDLE)) loopcnt = 2000; else - loopcnt = 500; + loopcnt = 500 * cs_laptop_wait; + loopcnt *= cs_laptop_wait; for (count = 0; count < loopcnt; count++) { /* * First, we want to wait for a short time. */ - udelay(10); + udelay(10 * cs_laptop_wait); /* * Now, check to see if the read has completed. * ACCTL = 460h, DCV should be reset by now and 460h = 17h @@ -3819,7 +3887,8 @@ if(!(card->pm.flags & CS46XX_PM_IDLE)) loopcnt = 2000; else - loopcnt = 100; + loopcnt = 1000; + loopcnt *= cs_laptop_wait; for (count = 0; count < loopcnt; count++) { /* * Read the AC97 status register. @@ -3828,16 +3897,16 @@ */ if (cs461x_peekBA0(card, BA0_ACSTS) & ACSTS_VSTS) break; - udelay(10); + udelay(10 * cs_laptop_wait); } /* * Make sure we got valid status. */ if (!( (tmp=cs461x_peekBA0(card, BA0_ACSTS)) & ACSTS_VSTS)) { - CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING - "cs46xx: AC'97 read problem (ACSTS_VSTS), reg = 0x%x val=0x%x \n", reg, tmp)); - CS_DBGOUT(CS_ERROR, 9, printk(KERN_WARNING "returning 0xffff\n")); + CS_DBGOUT(CS_ERROR, 2, printk(KERN_WARNING + "cs46xx: AC'97 read problem (ACSTS_VSTS), reg = 0x%x val=0x%x 0xffff \n", + reg, tmp)); return 0xffff; } @@ -3849,7 +3918,7 @@ "cs46xx: cs_ac97_get() reg = 0x%x, val = 0x%x, BA0_ACCAD = 0x%x\n", reg, cs461x_peekBA0(card, BA0_ACSDA), cs461x_peekBA0(card, BA0_ACCAD))); - return (cs461x_peekBA0(card, BA0_ACSDA)); + return(cs461x_peekBA0(card, BA0_ACSDA)); } static void cs_ac97_set(struct ac97_codec *dev, u8 reg, u16 val) @@ -3893,7 +3962,7 @@ /* * First, we want to wait for a short time. */ - udelay(10); + udelay(10 * cs_laptop_wait); /* * Now, check to see if the write has completed. * ACCTL = 460h, DCV should be reset by now and 460h = 07h @@ -4032,24 +4101,28 @@ return -ENODEV; } match: - card->active_ctrl(card, -1); - card->amplifier_ctrl(card, -1); MOD_DEC_USE_COUNT; if(!CS_DEC_AND_TEST(&card->mixer_use_cnt)) { CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 4, printk(KERN_INFO "cs46xx: cs_release_mixdev()- no powerdown, usecnt>0\n")); + card->active_ctrl(card, -1); + card->amplifier_ctrl(card, -1); return 0; } /* * ok, no outstanding mixer opens, so powerdown. */ - if( (tmp = cs461x_powerdown(card, CS_POWER_MIXVON )) ) + if( (tmp = cs461x_powerdown(card, CS_POWER_MIXVON, CS_FALSE )) ) { CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO "cs46xx: cs_release_mixdev() powerdown MIXVON failure (0x%x)\n",tmp) ); + card->active_ctrl(card, -1); + card->amplifier_ctrl(card, -1); return -EIO; } + card->active_ctrl(card, -1); + card->amplifier_ctrl(card, -1); CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 4, printk(KERN_INFO "cs46xx: cs_release_mixdev()- 0\n")); return 0; @@ -4101,7 +4174,7 @@ list_for_each(entry, &cs46xx_devs) { card = list_entry(entry, struct cs_card, list); - cs46xx_suspend(card); + cs46xx_suspend(card, 0); } } @@ -4341,14 +4414,14 @@ } -static int cs461x_powerdown(struct cs_card *card, unsigned int type) +static int cs461x_powerdown(struct cs_card *card, unsigned int type, int suspendflag) { int count; - unsigned int tmp=0; + unsigned int tmp=0,muted=0; CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO "cs46xx: cs461x_powerdown()+ type=0x%x\n",type)); - if(!powerdown) + if(!cs_powerdown && !suspendflag) { CS_DBGOUT(CS_FUNCTION, 8, printk(KERN_INFO "cs46xx: cs461x_powerdown() DISABLED exiting\n")); @@ -4380,8 +4453,6 @@ type &= ~CS_POWER_MIXVON; type &= ~CS_POWER_MIXVOFF; - cs_mute(card, CS_TRUE); - /* * Power down indicated areas. */ @@ -4396,6 +4467,11 @@ tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); if (tmp & CS_AC97_POWER_CONTROL_MIXVOFF_ON) { + if(!muted) + { + cs_mute(card, CS_TRUE); + muted=1; + } tmp |= CS_AC97_POWER_CONTROL_MIXVOFF; cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp ); /* @@ -4439,6 +4515,11 @@ tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); if (tmp & CS_AC97_POWER_CONTROL_MIXVON_ON) { + if(!muted) + { + cs_mute(card, CS_TRUE); + muted=1; + } tmp |= CS_AC97_POWER_CONTROL_MIXVON; cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp ); /* @@ -4480,6 +4561,11 @@ tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); if (tmp & CS_AC97_POWER_CONTROL_ADC_ON) { + if(!muted) + { + cs_mute(card, CS_TRUE); + muted=1; + } tmp |= CS_AC97_POWER_CONTROL_ADC; cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp ); @@ -4524,6 +4610,11 @@ tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); if (tmp & CS_AC97_POWER_CONTROL_DAC_ON) { + if(!muted) + { + cs_mute(card, CS_TRUE); + muted=1; + } tmp |= CS_AC97_POWER_CONTROL_DAC; cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp ); /* @@ -4557,7 +4648,8 @@ } } tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); - cs_mute(card, CS_FALSE); + if(muted) + cs_mute(card, CS_FALSE); CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO "cs46xx: cs461x_powerdown()- 0 tmp=0x%x\n",tmp)); return 0; @@ -4566,7 +4658,7 @@ static int cs46xx_powerup(struct cs_card *card, unsigned int type) { int count; - unsigned int tmp=0; + unsigned int tmp=0,muted=0; CS_DBGOUT(CS_FUNCTION, 8, printk(KERN_INFO "cs46xx: cs46xx_powerup()+ type=0x%x\n",type)); @@ -4578,7 +4670,6 @@ if(type & (CS_POWER_DAC | CS_POWER_ADC)) type |= CS_POWER_MIXVON | CS_POWER_MIXVOFF; - cs_mute(card, CS_TRUE); /* * Power up indicated areas. */ @@ -4593,6 +4684,11 @@ tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); if (!(tmp & CS_AC97_POWER_CONTROL_MIXVOFF_ON)) { + if(!muted) + { + cs_mute(card, CS_TRUE); + muted=1; + } tmp &= ~CS_AC97_POWER_CONTROL_MIXVOFF; cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp ); /* @@ -4636,6 +4732,11 @@ tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); if (!(tmp & CS_AC97_POWER_CONTROL_MIXVON_ON)) { + if(!muted) + { + cs_mute(card, CS_TRUE); + muted=1; + } tmp &= ~CS_AC97_POWER_CONTROL_MIXVON; cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp ); /* @@ -4677,6 +4778,11 @@ tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); if (!(tmp & CS_AC97_POWER_CONTROL_ADC_ON)) { + if(!muted) + { + cs_mute(card, CS_TRUE); + muted=1; + } tmp &= ~CS_AC97_POWER_CONTROL_ADC; cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp ); @@ -4721,6 +4827,11 @@ tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); if (!(tmp & CS_AC97_POWER_CONTROL_DAC_ON)) { + if(!muted) + { + cs_mute(card, CS_TRUE); + muted=1; + } tmp &= ~CS_AC97_POWER_CONTROL_DAC; cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp ); /* @@ -4754,7 +4865,8 @@ } } tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL); - cs_mute(card, CS_FALSE); + if(muted) + cs_mute(card, CS_FALSE); CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO "cs46xx: cs46xx_powerup()- 0 tmp=0x%x\n",tmp)); return 0; @@ -4843,7 +4955,7 @@ * generating bit clock (so we don't try to start the PLL without an * input clock). */ - mdelay(5); /* 1 should be enough ?? (and pigs might fly) */ + mdelay(5 * cs_laptop_wait); /* 1 should be enough ?? (and pigs might fly) */ /* * Set the serial port timing configuration, so that @@ -4876,7 +4988,7 @@ /* * Wait until the PLL has stabilized. */ - mdelay(5); /* Again 1 should be enough ?? */ + mdelay(5 * cs_laptop_wait); /* Again 1 should be enough ?? */ /* * Turn on clocking of the core so that we can setup the serial ports. @@ -4903,7 +5015,7 @@ cs461x_pokeBA0(card, BA0_SERMC1, SERMC1_PTC_AC97 | SERMC1_MSPE); - mdelay(5); /* Shouldnt be needed ?? */ + mdelay(5 * cs_laptop_wait); /* Shouldnt be needed ?? */ /* * If we are resuming under 2.2.x then we can not schedule a timeout. @@ -4930,7 +5042,7 @@ { for (count = 0; count < 100; count++) { // First, we want to wait for a short time. - udelay(25); + udelay(25 * cs_laptop_wait); if (cs461x_peekBA0(card, BA0_ACSTS) & ACSTS_CRDY) break; @@ -4978,7 +5090,7 @@ { for (count = 0; count < 100; count++) { // First, we want to wait for a short time. - udelay(25); + udelay(25 * cs_laptop_wait); if ((cs461x_peekBA0(card, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4)) break; @@ -5068,7 +5180,7 @@ */ if(card->pm.flags & CS46XX_PM_IDLE) { - if(!powerdown) + if(!cs_powerdown) { if( (tmp = cs46xx_powerup(card, CS_POWER_DAC | CS_POWER_ADC | CS_POWER_MIXVON )) ) @@ -5081,7 +5193,7 @@ else { if( (tmp = cs461x_powerdown(card, CS_POWER_DAC | CS_POWER_ADC | - CS_POWER_MIXVON )) ) + CS_POWER_MIXVON, CS_FALSE )) ) { CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO "cs46xx: cs461x_powerdown() failure (0x%x)\n",tmp) ); @@ -5148,6 +5260,7 @@ CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO "cs46xx: probe()+\n")); + dma_mask = 0xffffffff; /* this enables playback and recording */ if (pci_enable_device(pci_dev)) { CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_ERR "cs46xx: pci_enable_device() failed\n")); @@ -5169,8 +5282,6 @@ "cs46xx: probe() architecture does not support 32bit PCI busmaster DMA\n")); return -1; } - dma_mask = 0xffffffff; /* this enables playback and recording */ - pci_read_config_word(pci_dev, PCI_SUBSYSTEM_VENDOR_ID, &ss_vendor); pci_read_config_word(pci_dev, PCI_SUBSYSTEM_ID, &ss_card); @@ -5239,7 +5350,31 @@ printk(KERN_INFO "cs46xx: Activating CLKRUN hack for Thinkpad.\n"); card->active_ctrl = clkrun_hack; } - +/* +* The thinkpads don't work well without runtime updating on their kernel +* delay values (or any laptop with variable CPU speeds really). +* so, just to be safe set the init delay to 2100. Eliminates +* failures on T21 Thinkpads. remove this code when the udelay +* and mdelay kernel code is replaced by a pm timer, or the delays +* work well for battery and/or AC power both. +*/ + if(card->active_ctrl == clkrun_hack) + { + initdelay = 2100; + cs_laptop_wait = 5; + } + if((card->active_ctrl == clkrun_hack) && !(powerdown == 1)) + { +/* +* for some currently unknown reason, powering down the DAC and ADC component +* blocks on thinkpads causes some funky behavior... distoorrrtion and ac97 +* codec access problems. probably the serial clock becomes unsynced. +* added code to sync the chips back up, but only helped about 70% the time. +*/ + cs_powerdown = 0; + } + if(powerdown == 0) + cs_powerdown = 0; card->active_ctrl(card, 1); /* claim our iospace and irq */ @@ -5290,7 +5425,7 @@ unregister_sound_mixer(card->ac97_codec[j]->dev_mixer); kfree (card->ac97_codec[j]); } - mdelay(10); + mdelay(10 * cs_laptop_wait); continue; } break; @@ -5413,7 +5548,7 @@ * them. */ if( (tmp = cs461x_powerdown(card, CS_POWER_DAC | CS_POWER_ADC | - CS_POWER_MIXVON )) ) + CS_POWER_MIXVON, CS_TRUE )) ) { CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO "cs46xx: cs461x_powerdown() failure (0x%x)\n",tmp) ); @@ -5530,7 +5665,7 @@ case PM_SUSPEND: CS_DBGOUT(CS_PM, 2, printk(KERN_INFO "cs46xx: PM suspend request\n")); - if(cs46xx_suspend(card)) + if(cs46xx_suspend(card, 0)) { CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO "cs46xx: PM suspend request refused\n")); @@ -5553,21 +5688,22 @@ return 0; } -static void cs46xx_suspend_tbl(struct pci_dev *pcidev) +#if CS46XX_ACPI_SUPPORT +static int cs46xx_suspend_tbl(struct pci_dev *pcidev, u32 state) { struct cs_card *s = PCI_GET_DRIVER_DATA(pcidev); CS_DBGOUT(CS_PM | CS_FUNCTION, 2, printk(KERN_INFO "cs46xx: cs46xx_suspend_tbl request\n")); - cs46xx_suspend(s); - return; + cs46xx_suspend(s, 0); + return 0; } -static void cs46xx_resume_tbl(struct pci_dev *pcidev) +static int cs46xx_resume_tbl(struct pci_dev *pcidev) { struct cs_card *s = PCI_GET_DRIVER_DATA(pcidev); CS_DBGOUT(CS_PM | CS_FUNCTION, 2, printk(KERN_INFO "cs46xx: cs46xx_resume_tbl request\n")); cs46xx_resume(s); - return; + return 0; } - +#endif diff -u --recursive --new-file v2.4.5/linux/drivers/sound/cs46xxpm-24.h linux/drivers/sound/cs46xxpm-24.h --- v2.4.5/linux/drivers/sound/cs46xxpm-24.h Wed Apr 11 19:02:38 2001 +++ linux/drivers/sound/cs46xxpm-24.h Wed Jun 27 13:15:17 2001 @@ -36,8 +36,8 @@ * for now (12/22/00) only enable the pm_register PM support. * allow these table entries to be null. */ -static void cs46xx_suspend_tbl(struct pci_dev *pcidev); -static void cs46xx_resume_tbl(struct pci_dev *pcidev); +static int cs46xx_suspend_tbl(struct pci_dev *pcidev, u32 state); +static int cs46xx_resume_tbl(struct pci_dev *pcidev); #define cs_pm_register(a, b, c) 0 #define cs_pm_unregister_all(a) #define CS46XX_SUSPEND_TBL cs46xx_suspend_tbl diff -u --recursive --new-file v2.4.5/linux/drivers/sound/emu10k1/audio.c linux/drivers/sound/emu10k1/audio.c --- v2.4.5/linux/drivers/sound/emu10k1/audio.c Wed Apr 18 11:49:11 2001 +++ linux/drivers/sound/emu10k1/audio.c Mon Jul 2 13:56:41 2001 @@ -903,33 +903,46 @@ case SNDCTL_COPR_LOAD: { - copr_buffer buf; + copr_buffer *buf; u32 i; + int ret = -EFAULT; DPF(2, "SNDCTL_COPR_LOAD:\n"); + + buf = kmalloc(sizeof(copr_buffer), GFP_KERNEL); + if(buf == NULL) + return -ENOMEM; + + if (copy_from_user(buf, (copr_buffer *) arg, sizeof(buf))) + goto fail; + + if ((buf->command != 1) && (buf->command != 2)) + { + ret = -EINVAL; + goto fail; + } - if (copy_from_user(&buf, (copr_buffer *) arg, sizeof(buf))) - return -EFAULT; - - if ((buf.command != 1) && (buf.command != 2)) - return -EINVAL; - - if ((buf.offs < 0x100) - || (buf.offs < 0x000) - || (buf.offs + buf.len > 0x800) || (buf.len > 1000)) - return -EINVAL; - - if (buf.command == 1) { - for (i = 0; i < buf.len; i++) - ((u32 *) buf.data)[i] = sblive_readptr(wave_dev->card, buf.offs + i, 0); + if ((buf->offs < 0x100) + || (buf->offs < 0x000) + || (buf->offs + buf->len > 0x800) || (buf->len > 1000)) + { + ret = -EINVAL; + goto fail; + } + if (buf->command == 1) { + for (i = 0; i < buf->len; i++) + ((u32 *) buf->data)[i] = sblive_readptr(wave_dev->card, buf->offs + i, 0); - if (copy_to_user((copr_buffer *) arg, &buf, sizeof(buf))) - return -EFAULT; + if (copy_to_user((copr_buffer *) arg, buf, sizeof(buf))) + goto fail; } else { - for (i = 0; i < buf.len; i++) - sblive_writeptr(wave_dev->card, buf.offs + i, 0, ((u32 *) buf.data)[i]); + for (i = 0; i < buf->len; i++) + sblive_writeptr(wave_dev->card, buf->offs + i, 0, ((u32 *) buf->data)[i]); } - break; + ret = 0; + fail: + kfree(buf); + return ret; } default: /* Default is unrecognized command */ diff -u --recursive --new-file v2.4.5/linux/drivers/sound/gus_wave.c linux/drivers/sound/gus_wave.c --- v2.4.5/linux/drivers/sound/gus_wave.c Sun Nov 12 20:35:35 2000 +++ linux/drivers/sound/gus_wave.c Tue Jun 12 11:06:54 2001 @@ -2102,6 +2102,7 @@ break; default: + break; } } @@ -3282,6 +3283,7 @@ break; default: + break; } restore_flags(flags); } @@ -3423,6 +3425,7 @@ break; default: + break; } status = gus_look8(0x49); /* * Get Sampling IRQ Status diff -u --recursive --new-file v2.4.5/linux/drivers/sound/i810_audio.c linux/drivers/sound/i810_audio.c --- v2.4.5/linux/drivers/sound/i810_audio.c Sat May 19 17:43:07 2001 +++ linux/drivers/sound/i810_audio.c Tue Jul 3 07:59:51 2001 @@ -1446,7 +1446,7 @@ if (dmabuf->enable & ADC_RUNNING) { stop_adc(state); } - return ret; + return put_user(ret, (int *)arg); case SNDCTL_DSP_GETBLKSIZE: if (file->f_mode & FMODE_WRITE) { diff -u --recursive --new-file v2.4.5/linux/drivers/sound/maestro3.c linux/drivers/sound/maestro3.c --- v2.4.5/linux/drivers/sound/maestro3.c Sat Apr 21 10:36:30 2001 +++ linux/drivers/sound/maestro3.c Wed Jun 27 13:15:17 2001 @@ -371,7 +371,7 @@ * I'm not very good at laying out functions in a file :) */ static int m3_notifier(struct notifier_block *nb, unsigned long event, void *buf); -static void m3_suspend(struct pci_dev *pci_dev); +static int m3_suspend(struct pci_dev *pci_dev, u32 state); static void check_suspend(struct m3_card *card); struct notifier_block m3_reboot_nb = {m3_notifier, NULL, 0}; @@ -2771,12 +2771,12 @@ for(card = devs; card != NULL; card = card->next) { if(!card->in_suspend) - m3_suspend(card->pcidev); /* XXX legal? */ + m3_suspend(card->pcidev, 3); /* XXX legal? */ } return 0; } -static void m3_suspend(struct pci_dev *pci_dev) +static int m3_suspend(struct pci_dev *pci_dev, u32 state) { unsigned long flags; int i; @@ -2823,9 +2823,11 @@ card->in_suspend = 1; restore_flags(flags); + + return 0; } -static void m3_resume(struct pci_dev *pci_dev) +static int m3_resume(struct pci_dev *pci_dev) { unsigned long flags; int index; @@ -2904,6 +2906,8 @@ * when we suspended */ wake_up(&card->suspend_queue); + + return 0; } MODULE_AUTHOR("Zach Brown "); diff -u --recursive --new-file v2.4.5/linux/drivers/sound/pss.c linux/drivers/sound/pss.c --- v2.4.5/linux/drivers/sound/pss.c Sun Feb 4 10:05:29 2001 +++ linux/drivers/sound/pss.c Tue Jun 12 11:06:54 2001 @@ -766,6 +766,7 @@ break; default: + break; } return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/sound/sb_card.c linux/drivers/sound/sb_card.c --- v2.4.5/linux/drivers/sound/sb_card.c Tue May 22 10:23:16 2001 +++ linux/drivers/sound/sb_card.c Wed Jun 27 17:10:55 2001 @@ -298,6 +298,11 @@ ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0,0,0,0, 0,1,1,-1}, + {"Sound Blaster 16", + ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00ed), + ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), + 0,0,0,0, + 0,1,1,-1}, {"Sound Blaster Vibra16S", ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0051), ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001), @@ -518,6 +523,9 @@ { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002b), ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 }, + + { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00ed), + ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 }, { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0051), ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001), 0 }, diff -u --recursive --new-file v2.4.5/linux/drivers/sound/via82cxxx_audio.c linux/drivers/sound/via82cxxx_audio.c --- v2.4.5/linux/drivers/sound/via82cxxx_audio.c Tue May 1 16:05:00 2001 +++ linux/drivers/sound/via82cxxx_audio.c Mon Jul 2 14:03:04 2001 @@ -39,6 +39,9 @@ #include #include #include +#include "sound_config.h" +#include "dev_table.h" +#include "mpu401.h" #undef VIA_DEBUG /* define to enable debugging output and checks */ @@ -178,6 +181,8 @@ #define VIA_CR42_MIDI_ENABLE 0x02 #define VIA_CR42_FM_ENABLE 0x04 #define VIA_CR42_GAME_ENABLE 0x08 +#define VIA_CR42_MIDI_IRQMASK 0x40 +#define VIA_CR42_MIDI_PNP 0x80 #define VIA_CR44_SECOND_CODEC_SUPPORT (1 << 6) #define VIA_CR44_AC_LINK_ACCESS (1 << 7) @@ -290,6 +295,11 @@ struct via_channel ch_in; struct via_channel ch_out; struct via_channel ch_fm; + +#ifdef CONFIG_MIDI_VIA82CXXX + void *midi_devc; + struct address_info midi_info; +#endif }; @@ -720,12 +730,10 @@ /* set location of DMA-able scatter-gather info table */ DPRINTK ("outl (0x%X, 0x%04lX)\n", - cpu_to_le32 (chan->sgt_handle), - chan->iobase + VIA_PCM_TABLE_ADDR); + chan->sgt_handle, chan->iobase + VIA_PCM_TABLE_ADDR); via_ac97_wait_idle (card); - outl (cpu_to_le32 (chan->sgt_handle), - chan->iobase + VIA_PCM_TABLE_ADDR); + outl (chan->sgt_handle, chan->iobase + VIA_PCM_TABLE_ADDR); udelay (20); via_ac97_wait_idle (card); @@ -1216,25 +1224,28 @@ card = codec->private_data; - data = (reg << 16) | VIA_CR80_READ; + /* Every time we write to register 80 we cause a transaction. + The only safe way to clear the valid bit is to write it at + the same time as the command */ + data = (reg << 16) | VIA_CR80_READ | VIA_CR80_VALID; outl (data, card->baseaddr + VIA_BASE0_AC97_CTRL); - udelay (20); - for (counter = VIA_COUNTER_LIMIT; counter > 0; counter--) { - if (inl (card->baseaddr + 0x80) & VIA_CR80_VALID) + udelay (1); + if ((((data = inl(card->baseaddr + 0x80)) & + (VIA_CR80_VALID|VIA_CR80_BUSY)) == VIA_CR80_VALID)) goto out; - - udelay (15); } printk (KERN_WARNING PFX "timeout while reading AC97 codec (0x%lX)\n", data); goto err_out; out: + /* Once the valid bit has become set, we must wait a complete AC97 + frame before the data has settled. */ + udelay(25); data = (unsigned long) inl (card->baseaddr + 0x80); - outb (0x02, card->baseaddr + 0x83); - + if (((data & 0x007F0000) >> 16) == reg) { DPRINTK ("EXIT, success, data=0x%lx, retval=0x%lx\n", data, data & 0x0000FFFF); @@ -1371,7 +1382,6 @@ static int __init via_ac97_reset (struct via_info *card) { struct pci_dev *pdev = card->pdev; - u8 tmp8; u16 tmp16; DPRINTK ("ENTER\n"); @@ -1569,10 +1579,10 @@ * and advance the h/w ptr, wrapping around to zero if needed */ if (n == (chan->frag_number - 1)) { - chan->sgtable[n].count = (chan->frag_size | VIA_EOL); + chan->sgtable[n].count = cpu_to_le32(chan->frag_size | VIA_EOL); atomic_set (&chan->hw_ptr, 0); } else { - chan->sgtable[n].count = (chan->frag_size | VIA_FLAG); + chan->sgtable[n].count = cpu_to_le32(chan->frag_size | VIA_FLAG); atomic_inc (&chan->hw_ptr); } @@ -1628,8 +1638,12 @@ */ status32 = inl (card->baseaddr + VIA_BASE0_SGD_STATUS_SHADOW); if (!(status32 & VIA_INTR_MASK)) + { +#ifdef CONFIG_MIDI_VIA82CXXX + uart401intr(irq, card->midi_devc, regs); +#endif return; - + } DPRINTK ("intr, status32 == 0x%08X\n", status32); /* synchronize interrupt handling under SMP. this spinlock @@ -1781,10 +1795,8 @@ /* turn off legacy features, if not already */ pci_read_config_byte (card->pdev, VIA_FUNC_ENABLE, &tmp8); - if (tmp8 & (VIA_CR42_SB_ENABLE | VIA_CR42_MIDI_ENABLE | - VIA_CR42_FM_ENABLE)) { - tmp8 &= ~(VIA_CR42_SB_ENABLE | VIA_CR42_MIDI_ENABLE | - VIA_CR42_FM_ENABLE); + if (tmp8 & (VIA_CR42_SB_ENABLE | VIA_CR42_FM_ENABLE)) { + tmp8 &= ~(VIA_CR42_SB_ENABLE | VIA_CR42_FM_ENABLE); pci_write_config_byte (card->pdev, VIA_FUNC_ENABLE, tmp8); } @@ -2682,6 +2694,7 @@ /* wait until all buffers have been played, and then stop device */ case SNDCTL_DSP_SYNC: DPRINTK ("DSP_SYNC\n"); + rc = 0; if (wr) { DPRINTK ("SYNC EXIT (after calling via_dsp_drain_playback)\n"); rc = via_dsp_drain_playback (card, &card->ch_out, nonblock); @@ -3010,9 +3023,11 @@ static int __init via_init_one (struct pci_dev *pdev, const struct pci_device_id *id) { +#ifdef CONFIG_MIDI_VIA82CXXX + u8 r42; +#endif int rc; struct via_info *card; - u8 tmp; static int printed_version = 0; DPRINTK ("ENTER\n"); @@ -3020,25 +3035,19 @@ if (printed_version++ == 0) printk (KERN_INFO "Via 686a audio driver " VIA_VERSION "\n"); - if (pci_enable_device (pdev)) { - rc = -EIO; - goto err_out_none; - } - - if (!request_region (pci_resource_start (pdev, 0), - pci_resource_len (pdev, 0), - VIA_MODULE_NAME)) { - printk (KERN_ERR PFX "unable to obtain I/O resources, aborting\n"); - rc = -EBUSY; + rc = pci_enable_device (pdev); + if (rc) goto err_out; - } + rc = pci_request_regions (pdev, "via82cxxx_audio"); + if (rc) + goto err_out_disable; card = kmalloc (sizeof (*card), GFP_KERNEL); if (!card) { printk (KERN_ERR PFX "out of memory, aborting\n"); rc = -ENOMEM; - goto err_out_none; + goto err_out_res; } pci_set_drvdata (pdev, card); @@ -3109,22 +3118,37 @@ goto err_out_have_proc; } - pci_read_config_byte (pdev, 0x3C, &tmp); - if ((tmp & 0x0F) != pdev->irq) { - printk (KERN_WARNING PFX "IRQ fixup, 0x3C==0x%02X\n", tmp); - udelay (15); - tmp &= 0xF0; - tmp |= pdev->irq; - pci_write_config_byte (pdev, 0x3C, tmp); - DPRINTK ("new 0x3c==0x%02x\n", tmp); - } else { - DPRINTK ("IRQ reg 0x3c==0x%02x, irq==%d\n", - tmp, tmp & 0x0F); - } - printk (KERN_INFO PFX "board #%d at 0x%04lX, IRQ %d\n", card->card_num + 1, card->baseaddr, pdev->irq); +#ifdef CONFIG_MIDI_VIA82CXXX + /* Disable by default */ + card->midi_info.io_base = 0; + + pci_read_config_byte (pdev, 0x42, &r42); + /* Disable MIDI interrupt */ + pci_write_config_byte (pdev, 0x42, r42 | VIA_CR42_MIDI_IRQMASK); + if (r42 & VIA_CR42_MIDI_ENABLE) + { + if (r42 & VIA_CR42_MIDI_PNP) /* Address selected by iobase 2 - not tested */ + card->midi_info.io_base = pci_resource_start (pdev, 2); + else /* Address selected by byte 0x43 */ + { + u8 r43; + pci_read_config_byte (pdev, 0x43, &r43); + card->midi_info.io_base = 0x300 + ((r43 & 0x0c) << 2); + } + + card->midi_info.irq = -pdev->irq; + if (probe_uart401(& card->midi_info, THIS_MODULE)) + { + card->midi_devc=midi_devs[card->midi_info.slots[4]]->devc; + pci_write_config_byte(pdev, 0x42, r42 & ~VIA_CR42_MIDI_IRQMASK); + printk("Enabled Via MIDI\n"); + } + } +#endif + DPRINTK ("EXIT, returning 0\n"); return 0; @@ -3143,8 +3167,12 @@ #endif kfree (card); -err_out_none: - release_region (pci_resource_start (pdev, 0), pci_resource_len (pdev, 0)); +err_out_res: + pci_release_regions (pdev); + +err_out_disable: + pci_disable_device (pdev); + err_out: pci_set_drvdata (pdev, NULL); DPRINTK ("EXIT - returning %d\n", rc); @@ -3162,13 +3190,16 @@ card = pci_get_drvdata (pdev); assert (card != NULL); +#ifdef CONFIG_MIDI_VIA82CXXX + if (card->midi_info.io_base) + unload_uart401(&card->midi_info); +#endif + via_interrupt_cleanup (card); via_card_cleanup_proc (card); via_dsp_cleanup (card); via_ac97_cleanup (card); - release_region (pci_resource_start (pdev, 0), pci_resource_len (pdev, 0)); - #ifndef VIA_NDEBUG memset (card, 0xAB, sizeof (*card)); /* poison memory */ #endif @@ -3176,7 +3207,9 @@ pci_set_drvdata (pdev, NULL); + pci_release_regions (pdev); pci_set_power_state (pdev, 3); /* ...zzzzzz */ + pci_disable_device (pdev); DPRINTK ("EXIT\n"); return; diff -u --recursive --new-file v2.4.5/linux/drivers/sound/wavfront.c linux/drivers/sound/wavfront.c --- v2.4.5/linux/drivers/sound/wavfront.c Thu May 24 15:14:08 2001 +++ linux/drivers/sound/wavfront.c Wed Jun 27 17:10:55 2001 @@ -2045,19 +2045,17 @@ switch (cmd) { case SNDCTL_SYNTH_INFO: - memcpy (&((char *) arg)[0], &wavefront_info, - sizeof (wavefront_info)); + if(copy_to_user(&((char *) arg)[0], &wavefront_info, + sizeof (wavefront_info))) + return -EFAULT; return 0; - break; case SNDCTL_SEQ_RESETSAMPLES: - printk (KERN_WARNING LOGNAME "driver cannot reset samples.\n"); +// printk (KERN_WARNING LOGNAME "driver cannot reset samples.\n"); return 0; /* don't force an error */ - break; case SNDCTL_SEQ_PERCMODE: return 0; /* don't force an error */ - break; case SNDCTL_SYNTH_MEMAVL: if ((dev.freemem = wavefront_freemem ()) < 0) { @@ -2069,10 +2067,11 @@ break; case SNDCTL_SYNTH_CONTROL: - copy_from_user (&wc, arg, sizeof (wc)); - - if ((err = wavefront_synth_control (cmd, &wc)) == 0) { - copy_to_user (arg, &wc, sizeof (wc)); + if(copy_from_user (&wc, arg, sizeof (wc))) + err = -EFAULT; + else if ((err = wavefront_synth_control (cmd, &wc)) == 0) { + if(copy_to_user (arg, &wc, sizeof (wc))) + err = -EFAULT; } return err; diff -u --recursive --new-file v2.4.5/linux/drivers/sound/wf_midi.c linux/drivers/sound/wf_midi.c --- v2.4.5/linux/drivers/sound/wf_midi.c Sun Sep 17 09:45:07 2000 +++ linux/drivers/sound/wf_midi.c Wed Jun 27 17:10:55 2001 @@ -231,6 +231,7 @@ break; default: + break; } } else { mi->m_prev_status = midic; @@ -590,19 +591,17 @@ switch (cmd) { case SNDCTL_SYNTH_INFO: - copy_to_user (&((char *) arg)[0], + if(copy_to_user (&((char *) arg)[0], &wf_mpu_synth_info[index], - sizeof (struct synth_info)); - + sizeof (struct synth_info))) + return -EFAULT; return 0; - break; case SNDCTL_SYNTH_MEMAVL: return 0x7fffffff; - break; default: - return -(EINVAL); + return -EINVAL; } } diff -u --recursive --new-file v2.4.5/linux/drivers/sound/ymfpci.c linux/drivers/sound/ymfpci.c --- v2.4.5/linux/drivers/sound/ymfpci.c Sat May 19 17:47:55 2001 +++ linux/drivers/sound/ymfpci.c Tue Jun 12 11:06:54 2001 @@ -1829,6 +1829,7 @@ * for instance we get SNDCTL_TMR_CONTINUE here. * XXX Is there sound_generic_ioctl() around? */ + break; } return -ENOTTY; } diff -u --recursive --new-file v2.4.5/linux/drivers/telephony/ixj.c linux/drivers/telephony/ixj.c --- v2.4.5/linux/drivers/telephony/ixj.c Sat May 19 17:47:55 2001 +++ linux/drivers/telephony/ixj.c Wed Jun 27 17:10:55 2001 @@ -4480,9 +4480,15 @@ if (lcp == NULL) return -ENOMEM; if (copy_from_user(lcp, (char *) cp, sizeof(IXJ_FILTER_CADENCE))) + { + kfree(lcp); return -EFAULT; + } if (lcp->filter >= 4) + { + kfree(lcp); return -1; + } j->cadence_f[lcp->filter].state = 0; j->cadence_f[lcp->filter].enable = lcp->enable; j->filter_en[lcp->filter] = j->cadence_f[lcp->filter].en_filter = lcp->en_filter; @@ -4647,13 +4653,18 @@ } } -static int capabilities_check(IXJ *j, struct phone_capability *pcreq) +static int capabilities_check(IXJ *j, struct phone_capability *u_pcreq) { int cnt; int retval = 0; + struct phone_capability pcreq; + + if(copy_from_user(&pcreq, u_pcreq, sizeof(struct phone_capability))) + return -EFAULT; + for (cnt = 0; cnt < j->caps; cnt++) { - if (pcreq->captype == j->caplist[cnt].captype - && pcreq->cap == j->caplist[cnt].cap) { + if (pcreq.captype == j->caplist[cnt].captype + && pcreq.cap == j->caplist[cnt].cap) { retval = 1; break; } @@ -4704,7 +4715,8 @@ return -EFAULT; break; case PHONE_RING_CADENCE: - j->ring_cadence = arg; + if(get_user(j->ring_cadence, (int *)arg)) + return -EFAULT; break; case IXJCTL_CIDCW: if(arg) { @@ -6261,20 +6273,12 @@ return (((DWORD) wHi << 16) | wLo); } -#ifndef CONFIG_PCMCIA #ifndef CONFIG_ISAPNP -static int dspio[IXJMAX + 1] = -{ - 0, -}; -static int xio[IXJMAX + 1] = -{ - 0, -}; +static int dspio[IXJMAX + 1]; +static int xio[IXJMAX + 1]; MODULE_PARM(dspio, "1-" __MODULE_STRING(IXJMAX) "i"); MODULE_PARM(xio, "1-" __MODULE_STRING(IXJMAX) "i"); -#endif #endif void ixj_exit(void) diff -u --recursive --new-file v2.4.5/linux/drivers/usb/Config.in linux/drivers/usb/Config.in --- v2.4.5/linux/drivers/usb/Config.in Tue May 22 10:25:36 2001 +++ linux/drivers/usb/Config.in Wed Jun 27 13:59:32 2001 @@ -53,18 +53,20 @@ dep_tristate ' USB Kodak DC-2xx Camera support' CONFIG_USB_DC2XX $CONFIG_USB dep_tristate ' USB Mustek MDC800 Digital Camera support (EXPERIMENTAL)' CONFIG_USB_MDC800 $CONFIG_USB $CONFIG_EXPERIMENTAL dep_tristate ' USB Scanner support' CONFIG_USB_SCANNER $CONFIG_USB - dep_tristate ' Microtek X6USB scanner support (EXPERIMENTAL)' CONFIG_USB_MICROTEK $CONFIG_USB $CONFIG_SCSI $CONFIG_EXPERIMENTAL + dep_tristate ' Microtek X6USB scanner support' CONFIG_USB_MICROTEK $CONFIG_USB $CONFIG_SCSI comment 'USB Multimedia devices' dep_tristate ' USB IBM (Xirlink) C-it Camera support' CONFIG_USB_IBMCAM $CONFIG_USB $CONFIG_VIDEO_DEV dep_tristate ' USB OV511 Camera support' CONFIG_USB_OV511 $CONFIG_USB $CONFIG_VIDEO_DEV dep_tristate ' USB Philips Cameras' CONFIG_USB_PWC $CONFIG_USB $CONFIG_VIDEO_DEV + dep_tristate ' USB SE401 Camera support' CONFIG_USB_SE401 $CONFIG_USB $CONFIG_VIDEO_DEV dep_tristate ' D-Link USB FM radio support (EXPERIMENTAL)' CONFIG_USB_DSBR $CONFIG_USB $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL dep_tristate ' DABUSB driver' CONFIG_USB_DABUSB $CONFIG_USB comment 'USB Network adaptors' dep_tristate ' PLUSB Prolific USB-Network driver (EXPERIMENTAL)' CONFIG_USB_PLUSB $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL dep_tristate ' USB ADMtek Pegasus-based ethernet device support (EXPERIMENTAL)' CONFIG_USB_PEGASUS $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL + dep_tristate ' USB CATC NetMate-based Ethernet driver (EXPERIMENTAL)' CONFIG_USB_CATC $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL dep_tristate ' NetChip 1080-based USB Host-to-Host Link (EXPERIMENTAL)' CONFIG_USB_NET1080 $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL comment 'USB port drivers' diff -u --recursive --new-file v2.4.5/linux/drivers/usb/Makefile linux/drivers/usb/Makefile --- v2.4.5/linux/drivers/usb/Makefile Fri May 25 09:48:50 2001 +++ linux/drivers/usb/Makefile Wed Jun 27 13:59:32 2001 @@ -62,7 +62,9 @@ obj-$(CONFIG_USB_DABUSB) += dabusb.o obj-$(CONFIG_USB_PLUSB) += plusb.o obj-$(CONFIG_USB_OV511) += ov511.o +obj-$(CONFIG_USB_SE401) += se401.o obj-$(CONFIG_USB_PEGASUS) += pegasus.o +obj-$(CONFIG_USB_CATC) += catc.o obj-$(CONFIG_USB_RIO500) += rio500.o obj-$(CONFIG_USB_DSBR) += dsbr100.o obj-$(CONFIG_USB_MICROTEK) += microtek.o diff -u --recursive --new-file v2.4.5/linux/drivers/usb/acm.c linux/drivers/usb/acm.c --- v2.4.5/linux/drivers/usb/acm.c Mon May 21 15:02:06 2001 +++ linux/drivers/usb/acm.c Tue Jun 12 15:53:37 2001 @@ -709,8 +709,7 @@ return -1; } - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/audio.c linux/drivers/usb/audio.c --- v2.4.5/linux/drivers/usb/audio.c Mon May 21 15:02:06 2001 +++ linux/drivers/usb/audio.c Tue Jun 12 15:53:37 2001 @@ -3755,8 +3755,7 @@ static int __init usb_audio_init(void) { usb_register(&usb_audio_driver); - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/bluetooth.c linux/drivers/usb/bluetooth.c --- v2.4.5/linux/drivers/usb/bluetooth.c Mon May 21 15:02:06 2001 +++ linux/drivers/usb/bluetooth.c Wed Jun 20 16:52:30 2001 @@ -1,11 +1,28 @@ /* - * bluetooth.c Version 0.8 + * bluetooth.c Version 0.11 * - * Copyright (c) 2000 Greg Kroah-Hartman + * Copyright (c) 2000, 2001 Greg Kroah-Hartman * Copyright (c) 2000 Mark Douglas Corner * * USB Bluetooth driver, based on the Bluetooth Spec version 1.0B * + * (2001/06/05) Version 0.11 gkh + * - Fixed problem with read urb status saying that we have shutdown, + * and that we shouldn't resubmit the urb. Patch from unknown. + * + * (2001/05/28) Version 0.10 gkh + * - Fixed problem with using data from userspace in the bluetooth_write + * function as found by the CHECKER project. + * - Added a buffer to the write_urb_pool which reduces the number of + * buffers being created and destroyed for ever write. Also cleans + * up the logic a bit. + * - Added a buffer to the control_urb_pool which fixes a memory leak + * when the device is removed from the system. + * + * (2001/05/28) Version 0.9 gkh + * Fixed problem with bluetooth==NULL for bluetooth_read_bulk_callback + * which was found by both the CHECKER project and Mikko Rahkonen. + * * (08/04/2001) gb * Identify version on module load. * @@ -97,7 +114,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v0.8" +#define DRIVER_VERSION "v0.11" #define DRIVER_AUTHOR "Greg Kroah-Hartman, Mark Douglas Corner" #define DRIVER_DESC "USB Bluetooth driver" @@ -260,7 +277,7 @@ } -static int bluetooth_ctrl_msg (struct usb_bluetooth *bluetooth, int request, int value, void *buf, int len) +static int bluetooth_ctrl_msg (struct usb_bluetooth *bluetooth, int request, int value, const unsigned char *buf, int len) { struct urb *urb = NULL; devrequest *dr = NULL; @@ -282,11 +299,23 @@ return -ENOMEM; } - /* free up the last buffer that this urb used */ - if (urb->transfer_buffer != NULL) { - kfree(urb->transfer_buffer); - urb->transfer_buffer = NULL; + /* keep increasing the urb transfer buffer to fit the size of the message */ + if (urb->transfer_buffer == NULL) { + urb->transfer_buffer = kmalloc (len, GFP_KERNEL); + if (urb->transfer_buffer == NULL) { + err (__FUNCTION__" - out of memory"); + return -ENOMEM; + } } + if (urb->transfer_buffer_length < len) { + kfree (urb->transfer_buffer); + urb->transfer_buffer = kmalloc (len, GFP_KERNEL); + if (urb->transfer_buffer == NULL) { + err (__FUNCTION__" - out of memory"); + return -ENOMEM; + } + } + memcpy (urb->transfer_buffer, buf, len); dr->requesttype = BLUETOOTH_CONTROL_REQUEST_TYPE; dr->request = request; @@ -295,14 +324,14 @@ dr->length = cpu_to_le16p(&len); FILL_CONTROL_URB (urb, bluetooth->dev, usb_sndctrlpipe(bluetooth->dev, 0), - (unsigned char*)dr, buf, len, bluetooth_ctrl_callback, bluetooth); + (unsigned char*)dr, urb->transfer_buffer, len, bluetooth_ctrl_callback, bluetooth); /* send it down the pipe */ status = usb_submit_urb(urb); if (status) dbg(__FUNCTION__ " - usb_submit_urb(control) failed with status = %d", status); - return 0; + return status; } @@ -401,12 +430,13 @@ { struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__); struct urb *urb = NULL; - unsigned char *new_buffer; + unsigned char *temp_buffer = NULL; + const unsigned char *current_buffer; const unsigned char *current_position; - int status; int bytes_sent; int buffer_size; int i; + int retval = 0; if (!bluetooth) { return -ENODEV; @@ -436,38 +466,39 @@ printk ("\n"); #endif - switch (*buf) { + if (from_user) { + temp_buffer = kmalloc (count, GFP_KERNEL); + if (temp_buffer == NULL) { + err (__FUNCTION__ "- out of memory."); + retval = -ENOMEM; + goto exit; + } + copy_from_user (temp_buffer, buf, count); + current_buffer = temp_buffer; + } else { + current_buffer = buf; + } + + switch (*current_buffer) { /* First byte indicates the type of packet */ case CMD_PKT: /* dbg(__FUNCTION__ "- Send cmd_pkt len:%d", count);*/ if (in_interrupt()){ printk("cmd_pkt from interrupt!\n"); - return count; + retval = count; + goto exit; } - new_buffer = kmalloc (count-1, GFP_KERNEL); - - if (!new_buffer) { - err (__FUNCTION__ "- out of memory."); - return -ENOMEM; - } - - if (from_user) - copy_from_user (new_buffer, buf+1, count-1); - else - memcpy (new_buffer, buf+1, count-1); - - if (bluetooth_ctrl_msg (bluetooth, 0x00, 0x00, new_buffer, count-1) != 0) { - kfree (new_buffer); - return 0; + retval = bluetooth_ctrl_msg (bluetooth, 0x00, 0x00, ¤t_buffer[1], count-1); + if (retval) { + goto exit; } - - /* need to free new_buffer somehow... FIXME */ - return count; + retval = count; + break; case ACL_PKT: - current_position = buf; + current_position = current_buffer; ++current_position; --count; bytes_sent = 0; @@ -484,37 +515,25 @@ } if (urb == NULL) { dbg (__FUNCTION__ " - no free urbs"); - return bytes_sent; + retval = bytes_sent; + goto exit; } - /* free up the last buffer that this urb used */ - if (urb->transfer_buffer != NULL) { - kfree(urb->transfer_buffer); - urb->transfer_buffer = NULL; - } buffer_size = MIN (count, bluetooth->bulk_out_buffer_size); - - new_buffer = kmalloc (buffer_size, GFP_KERNEL); - if (new_buffer == NULL) { - err(__FUNCTION__" no more kernel memory..."); - return bytes_sent; - } - - if (from_user) - copy_from_user(new_buffer, current_position, buffer_size); - else - memcpy (new_buffer, current_position, buffer_size); + memcpy (urb->transfer_buffer, current_position, buffer_size); /* build up our urb */ FILL_BULK_URB (urb, bluetooth->dev, usb_sndbulkpipe(bluetooth->dev, bluetooth->bulk_out_endpointAddress), - new_buffer, buffer_size, bluetooth_write_bulk_callback, bluetooth); + urb->transfer_buffer, buffer_size, bluetooth_write_bulk_callback, bluetooth); urb->transfer_flags |= USB_QUEUE_BULK; /* send it down the pipe */ - status = usb_submit_urb(urb); - if (status) - dbg(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status); + retval = usb_submit_urb(urb); + if (retval) { + dbg(__FUNCTION__ " - usb_submit_urb(write bulk) failed with error = %d", retval); + goto exit; + } #ifdef BTBUGGYHARDWARE /* A workaround for the stalled data bug */ /* May or may not be needed...*/ @@ -527,13 +546,20 @@ count -= buffer_size; } - return bytes_sent + 1; + retval = bytes_sent + 1; + break; default : dbg(__FUNCTION__" - unsupported (at this time) write type"); + retval = -EINVAL; + break; } - return 0; +exit: + if (temp_buffer != NULL) + kfree (temp_buffer); + + return retval; } @@ -845,21 +871,6 @@ unsigned int packet_size; int result; -#ifdef BTBUGGYHARDWARE - if ((count == 4) && (data[0] == 0x00) && (data[1] == 0x00) - && (data[2] == 0x00) && (data[3] == 0x00)) { - urb->actual_length = 0; - FILL_BULK_URB(bluetooth->read_urb, bluetooth->dev, - usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress), - bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size, - bluetooth_read_bulk_callback, bluetooth); - result = usb_submit_urb(bluetooth->read_urb); - if (result) - err (__FUNCTION__ " - failed resubmitting read urb, error %d", result); - - return; - } -#endif dbg(__FUNCTION__); @@ -870,6 +881,10 @@ if (urb->status) { dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status); + if (urb->status == -ENOENT) { + dbg(__FUNCTION__ " - URB canceled, won't reschedule"); + return; + } goto exit; } @@ -887,6 +902,21 @@ printk ("\n"); } #endif +#ifdef BTBUGGYHARDWARE + if ((count == 4) && (data[0] == 0x00) && (data[1] == 0x00) + && (data[2] == 0x00) && (data[3] == 0x00)) { + urb->actual_length = 0; + FILL_BULK_URB(bluetooth->read_urb, bluetooth->dev, + usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress), + bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size, + bluetooth_read_bulk_callback, bluetooth); + result = usb_submit_urb(bluetooth->read_urb); + if (result) + err (__FUNCTION__ " - failed resubmitting read urb, error %d", result); + + return; + } +#endif /* We add a packet type identifier to the beginning of each HCI frame. This makes the data in the tty look like a serial USB devices. Each HCI frame can be broken across @@ -934,6 +964,9 @@ } exit: + if (!bluetooth || !bluetooth->active) + return; + FILL_BULK_URB(bluetooth->read_urb, bluetooth->dev, usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress), bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size, @@ -1114,7 +1147,11 @@ err("No free urbs available"); goto probe_error; } - urb->transfer_buffer = NULL; + urb->transfer_buffer = kmalloc (bluetooth->bulk_out_buffer_size, GFP_KERNEL); + if (urb->transfer_buffer == NULL) { + err("out of memory"); + goto probe_error; + } bluetooth->write_urb_pool[i] = urb; } @@ -1156,11 +1193,17 @@ if (bluetooth->interrupt_in_buffer) kfree (bluetooth->interrupt_in_buffer); for (i = 0; i < NUM_BULK_URBS; ++i) - if (bluetooth->write_urb_pool[i]) + if (bluetooth->write_urb_pool[i]) { + if (bluetooth->write_urb_pool[i]->transfer_buffer) + kfree (bluetooth->write_urb_pool[i]->transfer_buffer); usb_free_urb (bluetooth->write_urb_pool[i]); + } for (i = 0; i < NUM_CONTROL_URBS; ++i) - if (bluetooth->control_urb_pool[i]) + if (bluetooth->control_urb_pool[i]) { + if (bluetooth->control_urb_pool[i]->transfer_buffer) + kfree (bluetooth->control_urb_pool[i]->transfer_buffer); usb_free_urb (bluetooth->control_urb_pool[i]); + } bluetooth_table[minor] = NULL; @@ -1286,8 +1329,7 @@ return -1; } - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/catc.c linux/drivers/usb/catc.c --- v2.4.5/linux/drivers/usb/catc.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/catc.c Wed Jun 20 17:51:24 2001 @@ -0,0 +1,758 @@ +/* + * Copyright (c) 2001 Vojtech Pavlik + * + * CATC EL1210A NetMate USB Ethernet driver + * + * Sponsored by SuSE + * + * Based on the work of + * Donald Becker + */ + +/* + * 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 + * + * Should you need to contact me, the author, you can do so either by + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG + +#include + +/* + * Version information. + */ + +#define DRIVER_VERSION "v2.7" +#define DRIVER_AUTHOR "Vojtech Pavlik " +#define DRIVER_DESC "CATC EL1210A NetMate USB Ethernet driver" + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); + +/* + * Some defines. + */ + +#define STATS_UPDATE (HZ) /* Time between stats updates */ +#define TX_TIMEOUT (5*HZ) /* Max time the queue can be stopped */ +#define PKT_SZ 1536 /* Max Ethernet packet size */ +#define RX_MAX_BURST 15 /* Max packets per rx buffer (> 0, < 16) */ +#define TX_MAX_BURST 15 /* Max full sized packets per tx buffer (> 0) */ +#define CTRL_QUEUE 16 /* Max control requests in flight (power of two) */ + +/* + * Control requests. + */ + +enum control_requests { + ReadMem = 0xf1, + GetMac = 0xf2, + Reset = 0xf4, + SetMac = 0xf5, + WriteROM = 0xf8, + SetReg = 0xfa, + GetReg = 0xfb, + WriteMem = 0xfc, + ReadROM = 0xfd, +}; + +/* + * Registers. + */ + +enum register_offsets { + TxBufCount = 0x20, + RxBufCount = 0x21, + OpModes = 0x22, + TxQed = 0x23, + RxQed = 0x24, + MaxBurst = 0x25, + RxUnit = 0x60, + EthStatus = 0x61, + StationAddr0 = 0x67, + EthStats = 0x69, + LEDCtrl = 0x81, +}; + +enum eth_stats { + TxSingleColl = 0x00, + TxMultiColl = 0x02, + TxExcessColl = 0x04, + RxFramErr = 0x06, +}; + +enum op_mode_bits { + Op3MemWaits = 0x03, + OpLenInclude = 0x08, + OpRxMerge = 0x10, + OpTxMerge = 0x20, + OpWin95bugfix = 0x40, + OpLoopback = 0x80, +}; + +enum rx_filter_bits { + RxEnable = 0x01, + RxPolarity = 0x02, + RxForceOK = 0x04, + RxMultiCast = 0x08, + RxPromisc = 0x10, +}; + +enum led_values { + LEDFast = 0x01, + LEDSlow = 0x02, + LEDFlash = 0x03, + LEDPulse = 0x04, + LEDLink = 0x08, +}; + +/* + * The catc struct. + */ + +#define CTRL_RUNNING 0 +#define RX_RUNNING 1 +#define TX_RUNNING 2 + +struct catc { + struct net_device *netdev; + struct usb_device *usbdev; + + struct net_device_stats stats; + unsigned long flags; + + unsigned int tx_ptr, tx_idx; + unsigned int ctrl_head, ctrl_tail; + spinlock_t tx_lock, ctrl_lock; + + u8 tx_buf[2][TX_MAX_BURST * (PKT_SZ + 2)]; + u8 rx_buf[RX_MAX_BURST * (PKT_SZ + 2)]; + u8 irq_buf[2]; + u8 ctrl_buf[64]; + devrequest ctrl_dr; + + struct timer_list timer; + u8 stats_buf[8]; + u16 stats_vals[4]; + unsigned long last_stats; + + u8 multicast[64]; + + struct ctrl_queue { + u8 dir; + u8 request; + u16 value; + u16 index; + void *buf; + int len; + void (*callback)(struct catc *catc, struct ctrl_queue *q); + } ctrl_queue[CTRL_QUEUE]; + + struct urb tx_urb, rx_urb, irq_urb, ctrl_urb; +}; + +/* + * Useful macros. + */ + +#define catc_get_mac(catc, mac) catc_ctrl_msg(catc, USB_DIR_IN, GetMac, 0, 0, mac, 6) +#define catc_reset(catc) catc_ctrl_msg(catc, USB_DIR_OUT, Reset, 0, 0, NULL, 0) +#define catc_set_reg(catc, reg, val) catc_ctrl_msg(catc, USB_DIR_OUT, SetReg, val, reg, NULL, 0) +#define catc_get_reg(catc, reg, buf) catc_ctrl_msg(catc, USB_DIR_IN, GetReg, 0, reg, buf, 1) +#define catc_write_mem(catc, addr, buf, size) catc_ctrl_msg(catc, USB_DIR_OUT, WriteMem, 0, addr, buf, size) +#define catc_read_mem(catc, addr, buf, size) catc_ctrl_msg(catc, USB_DIR_IN, ReadMem, 0, addr, buf, size) + +#define catc_set_reg_async(catc, reg, val) catc_ctrl_async(catc, USB_DIR_OUT, SetReg, val, reg, NULL, 0, NULL) +#define catc_get_reg_async(catc, reg, cb) catc_ctrl_async(catc, USB_DIR_IN, GetReg, 0, reg, NULL, 1, cb) +#define catc_write_mem_async(catc, addr, buf, size) catc_ctrl_async(catc, USB_DIR_OUT, WriteMem, 0, addr, buf, size, NULL) + +/* + * Receive routines. + */ + +static void catc_rx_done(struct urb *urb) +{ + struct catc *catc = urb->context; + u8 *pkt_start = urb->transfer_buffer; + struct sk_buff *skb; + int pkt_len; + + clear_bit(RX_RUNNING, &catc->flags); + + if (urb->status) { + dbg("rx_done, status %d, length %d", urb->status, urb->actual_length); + return; + } + + do { + pkt_len = le16_to_cpup((u16*)pkt_start); + + if (pkt_len > urb->actual_length) { + catc->stats.rx_length_errors++; + catc->stats.rx_errors++; + break; + } + + if (!(skb = dev_alloc_skb(pkt_len))) + return; + + skb->dev = catc->netdev; + eth_copy_and_sum(skb, pkt_start + 2, pkt_len, 0); + skb_put(skb, pkt_len); + + skb->protocol = eth_type_trans(skb, catc->netdev); + netif_rx(skb); + + catc->stats.rx_packets++; + catc->stats.rx_bytes += pkt_len; + + pkt_start += (((pkt_len + 1) >> 6) + 1) << 6; + + } while (pkt_start - (u8 *) urb->transfer_buffer < urb->actual_length); + + catc->netdev->last_rx = jiffies; +} + +static void catc_irq_done(struct urb *urb) +{ + struct catc *catc = urb->context; + u8 *data = urb->transfer_buffer; + int status; + + if (urb->status) { + dbg("irq_done, status %d, data %02x %02x.", urb->status, data[0], data[1]); + return; + } + + if ((data[1] & 0x80) && !test_and_set_bit(RX_RUNNING, &catc->flags)) { + catc->rx_urb.dev = catc->usbdev; + if ((status = usb_submit_urb(&catc->rx_urb)) < 0) { + err("submit(rx_urb) status %d", status); + return; + } + } + + if (data[1] & 0x40) + dbg("link ok"); + + if (data[1] & 0x20) + dbg("link bad"); +} + +/* + * Transmit routines. + */ + +static void catc_tx_run(struct catc *catc) +{ + int status; + + catc->tx_urb.transfer_buffer_length = catc->tx_ptr; + catc->tx_urb.transfer_buffer = catc->tx_buf[catc->tx_idx]; + catc->tx_urb.dev = catc->usbdev; + + if ((status = usb_submit_urb(&catc->tx_urb)) < 0) + err("submit(tx_urb), status %d", status); + + catc->tx_idx = !catc->tx_idx; + catc->tx_ptr = 0; + + catc->netdev->trans_start = jiffies; +} + +static void catc_tx_done(struct urb *urb) +{ + struct catc *catc = urb->context; + unsigned long flags; + + if (urb->status == -ECONNRESET) { + dbg("Tx Reset."); + urb->transfer_flags &= ~USB_ASYNC_UNLINK; + urb->status = 0; + catc->netdev->trans_start = jiffies; + catc->stats.tx_errors++; + clear_bit(TX_RUNNING, &catc->flags); + netif_wake_queue(catc->netdev); + return; + } + + if (urb->status) { + dbg("tx_done, status %d, length %d", urb->status, urb->actual_length); + return; + } + + spin_lock_irqsave(&catc->tx_lock, flags); + + if (catc->tx_ptr) + catc_tx_run(catc); + else + clear_bit(TX_RUNNING, &catc->flags); + + netif_wake_queue(catc->netdev); + + spin_unlock_irqrestore(&catc->tx_lock, flags); +} + +static int catc_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev) +{ + struct catc *catc = netdev->priv; + unsigned long flags; + char *tx_buf; + + spin_lock_irqsave(&catc->tx_lock, flags); + + catc->tx_ptr = (((catc->tx_ptr - 1) >> 6) + 1) << 6; + tx_buf = catc->tx_buf[catc->tx_idx] + catc->tx_ptr; + *((u16*)tx_buf) = cpu_to_le16p(&skb->len); + memcpy(tx_buf + 2, skb->data, skb->len); + catc->tx_ptr += skb->len + 2; + + if (!test_and_set_bit(TX_RUNNING, &catc->flags)) + catc_tx_run(catc); + + if (catc->tx_ptr >= ((TX_MAX_BURST - 1) * (PKT_SZ + 2))) + netif_stop_queue(netdev); + + spin_unlock_irqrestore(&catc->tx_lock, flags); + + catc->stats.tx_bytes += skb->len; + catc->stats.tx_packets++; + + dev_kfree_skb(skb); + + return 0; +} + +static void catc_tx_timeout(struct net_device *netdev) +{ + struct catc *catc = netdev->priv; + + warn("Transmit timed out."); + catc->tx_urb.transfer_flags |= USB_ASYNC_UNLINK; + usb_unlink_urb(&catc->tx_urb); +} + +/* + * Control messages. + */ + +static int catc_ctrl_msg(struct catc *catc, u8 dir, u8 request, u16 value, u16 index, void *buf, int len) +{ + int retval = usb_control_msg(catc->usbdev, + dir ? usb_rcvctrlpipe(catc->usbdev, 0) : usb_sndctrlpipe(catc->usbdev, 0), + request, 0x40 | dir, value, index, buf, len, HZ); + return retval < 0 ? retval : 0; +} + +static void catc_ctrl_run(struct catc *catc) +{ + struct ctrl_queue *q = catc->ctrl_queue + catc->ctrl_tail; + struct usb_device *usbdev = catc->usbdev; + struct urb *urb = &catc->ctrl_urb; + devrequest *dr = &catc->ctrl_dr; + int status; + + dr->request = q->request; + dr->requesttype = 0x40 | q->dir; + dr->value = cpu_to_le16(q->value); + dr->index = cpu_to_le16(q->index); + dr->length = cpu_to_le16(q->len); + + urb->pipe = q->dir ? usb_rcvctrlpipe(usbdev, 0) : usb_sndctrlpipe(usbdev, 0); + urb->transfer_buffer_length = q->len; + urb->transfer_buffer = catc->ctrl_buf; + urb->setup_packet = (void *) dr; + urb->dev = usbdev; + + if (!q->dir && q->buf && q->len) + memcpy(catc->ctrl_buf, q->buf, q->len); + + if ((status = usb_submit_urb(&catc->ctrl_urb))) + err("submit(ctrl_urb) status %d", status); +} + +static void catc_ctrl_done(struct urb *urb) +{ + struct catc *catc = urb->context; + struct ctrl_queue *q; + long flags; + + if (urb->status) + dbg("ctrl_done, status %d, len %d.", urb->status, urb->actual_length); + + spin_lock_irqsave(&catc->ctrl_lock, flags); + + q = catc->ctrl_queue + catc->ctrl_tail; + + if (q->dir) { + if (q->buf && q->len) + memcpy(q->buf, catc->ctrl_buf, q->len); + else + q->buf = catc->ctrl_buf; + } + + if (q->callback) + q->callback(catc, q); + + catc->ctrl_tail = (catc->ctrl_tail + 1) & (CTRL_QUEUE - 1); + + if (catc->ctrl_head != catc->ctrl_tail) + catc_ctrl_run(catc); + else + clear_bit(CTRL_RUNNING, &catc->flags); + + spin_unlock_irqrestore(&catc->ctrl_lock, flags); +} + +static int catc_ctrl_async(struct catc *catc, u8 dir, u8 request, u16 value, + u16 index, void *buf, int len, void (*callback)(struct catc *catc, struct ctrl_queue *q)) +{ + struct ctrl_queue *q; + int retval = 0; + long flags; + + spin_lock_irqsave(&catc->ctrl_lock, flags); + + q = catc->ctrl_queue + catc->ctrl_head; + + q->dir = dir; + q->request = request; + q->value = value; + q->index = index; + q->buf = buf; + q->len = len; + q->callback = callback; + + catc->ctrl_head = (catc->ctrl_head + 1) & (CTRL_QUEUE - 1); + + if (catc->ctrl_head == catc->ctrl_tail) { + err("ctrl queue full"); + catc->ctrl_tail = (catc->ctrl_tail + 1) & (CTRL_QUEUE - 1); + retval = -1; + } + + if (!test_and_set_bit(CTRL_RUNNING, &catc->flags)) + catc_ctrl_run(catc); + + spin_unlock_irqrestore(&catc->ctrl_lock, flags); + + return retval; +} + +/* + * Statistics. + */ + +static void catc_stats_done(struct catc *catc, struct ctrl_queue *q) +{ + int index = q->index - EthStats; + u16 data, last; + + catc->stats_buf[index] = *((char *)q->buf); + + if (index & 1) + return; + + data = ((u16)catc->stats_buf[index] << 8) | catc->stats_buf[index + 1]; + last = catc->stats_vals[index >> 1]; + + switch (index) { + case TxSingleColl: + case TxMultiColl: + catc->stats.collisions += data - last; + break; + case TxExcessColl: + catc->stats.tx_aborted_errors += data - last; + catc->stats.tx_errors += data - last; + break; + case RxFramErr: + catc->stats.rx_frame_errors += data - last; + catc->stats.rx_errors += data - last; + break; + } + + catc->stats_vals[index >> 1] = data; +} + +static void catc_stats_timer(unsigned long data) +{ + struct catc *catc = (void *) data; + int i; + + for (i = 0; i < 8; i++) + catc_get_reg_async(catc, EthStats + 7 - i, catc_stats_done); + + mod_timer(&catc->timer, jiffies + STATS_UPDATE); +} + +static struct net_device_stats *catc_get_stats(struct net_device *netdev) +{ + struct catc *catc = netdev->priv; + return &catc->stats; +} + +/* + * Receive modes. Broadcast, Multicast, Promisc. + */ + +static void catc_multicast(unsigned char *addr, u8 *multicast) +{ + unsigned int crc = 0xffffffff; + u8 byte, idx, bit; + + for (idx = 0; idx < 6; idx++) + for (byte = *addr++, bit = 0; bit < 8; bit++, byte >>= 1) + crc = (crc >> 1) ^ (((crc ^ byte) & 1) ? 0xedb88320U : 0); + + multicast[(crc >> 3) & 0x3f] |= 1 << (crc & 7); +} + +static void catc_set_multicast_list(struct net_device *netdev) +{ + struct catc *catc = netdev->priv; + struct dev_mc_list *mc; + u8 broadcast[6]; + u8 rx = RxEnable | RxPolarity | RxMultiCast; + int i; + + memset(broadcast, 0xff, 6); + memset(catc->multicast, 0, 64); + + catc_multicast(broadcast, catc->multicast); + catc_multicast(netdev->dev_addr, catc->multicast); + + if (netdev->flags & IFF_PROMISC) { + memset(catc->multicast, 0xff, 64); + rx |= RxPromisc; + } + + if (netdev->flags & IFF_ALLMULTI) + memset(catc->multicast, 0xff, 64); + + for (i = 0, mc = netdev->mc_list; mc && i < netdev->mc_count; i++, mc = mc->next) + catc_multicast(mc->dmi_addr, catc->multicast); + + catc_set_reg_async(catc, RxUnit, rx); + catc_write_mem_async(catc, 0xfa80, catc->multicast, 64); +} + +/* + * Open, close. + */ + +static int catc_open(struct net_device *netdev) +{ + struct catc *catc = netdev->priv; + int status; + + catc->irq_urb.dev = catc->usbdev; + if ((status = usb_submit_urb(&catc->irq_urb)) < 0) { + err("submit(irq_urb) status %d", status); + return -1; + } + + netif_start_queue(netdev); + + mod_timer(&catc->timer, jiffies + STATS_UPDATE); + + return 0; +} + +static int catc_stop(struct net_device *netdev) +{ + struct catc *catc = netdev->priv; + + netif_stop_queue(netdev); + + del_timer_sync(&catc->timer); + + usb_unlink_urb(&catc->rx_urb); + usb_unlink_urb(&catc->tx_urb); + usb_unlink_urb(&catc->irq_urb); + usb_unlink_urb(&catc->ctrl_urb); + + return 0; +} + +/* + * USB probe, disconnect. + */ + +static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const struct usb_device_id *id) +{ + struct net_device *netdev; + struct catc *catc; + u8 broadcast[6]; + int i; + + if (usb_set_interface(usbdev, ifnum, 1)) { + err("Can't set altsetting 1."); + return NULL; + } + + catc = kmalloc(sizeof(struct catc), GFP_KERNEL); + memset(catc, 0, sizeof(struct catc)); + + netdev = init_etherdev(0, 0); + + netdev->open = catc_open; + netdev->hard_start_xmit = catc_hard_start_xmit; + netdev->stop = catc_stop; + netdev->get_stats = catc_get_stats; + netdev->tx_timeout = catc_tx_timeout; + netdev->watchdog_timeo = TX_TIMEOUT; + netdev->set_multicast_list = catc_set_multicast_list; + netdev->priv = catc; + + catc->usbdev = usbdev; + catc->netdev = netdev; + + catc->tx_lock = SPIN_LOCK_UNLOCKED; + catc->ctrl_lock = SPIN_LOCK_UNLOCKED; + + init_timer(&catc->timer); + catc->timer.data = (long) catc; + catc->timer.function = catc_stats_timer; + + FILL_CONTROL_URB(&catc->ctrl_urb, usbdev, usb_sndctrlpipe(usbdev, 0), + NULL, NULL, 0, catc_ctrl_done, catc); + + FILL_BULK_URB(&catc->tx_urb, usbdev, usb_sndbulkpipe(usbdev, 1), + NULL, 0, catc_tx_done, catc); + + FILL_BULK_URB(&catc->rx_urb, usbdev, usb_rcvbulkpipe(usbdev, 1), + catc->rx_buf, RX_MAX_BURST * (PKT_SZ + 2), catc_rx_done, catc); + + FILL_INT_URB(&catc->irq_urb, usbdev, usb_rcvintpipe(usbdev, 2), + catc->irq_buf, 2, catc_irq_done, catc, 1); + + dbg("Checking memory size\n"); + + i = 0x12345678; + catc_write_mem(catc, 0x7a80, &i, 4); + i = 0x87654321; + catc_write_mem(catc, 0xfa80, &i, 4); + catc_read_mem(catc, 0x7a80, &i, 4); + + switch (i) { + case 0x12345678: + catc_set_reg(catc, TxBufCount, 8); + catc_set_reg(catc, RxBufCount, 32); + dbg("64k Memory\n"); + break; + default: + warn("Couldn't detect memory size, assuming 32k"); + case 0x87654321: + catc_set_reg(catc, TxBufCount, 4); + catc_set_reg(catc, RxBufCount, 16); + dbg("32k Memory\n"); + break; + } + + dbg("Getting MAC from SEEROM."); + + catc_get_mac(catc, netdev->dev_addr); + + dbg("Setting MAC into registers."); + + for (i = 0; i < 6; i++) + catc_set_reg(catc, StationAddr0 - i, netdev->dev_addr[i]); + + dbg("Filling the multicast list."); + + memset(broadcast, 0xff, 8); + catc_multicast(broadcast, catc->multicast); + catc_multicast(netdev->dev_addr, catc->multicast); + catc_write_mem(catc, 0xfa80, catc->multicast, 64); + + dbg("Clearing error counters."); + + for (i = 0; i < 8; i++) + catc_set_reg(catc, EthStats + i, 0); + catc->last_stats = jiffies; + + dbg("Enabling."); + + catc_set_reg(catc, MaxBurst, RX_MAX_BURST); + catc_set_reg(catc, OpModes, OpTxMerge | OpRxMerge | OpLenInclude | Op3MemWaits); + catc_set_reg(catc, LEDCtrl, LEDLink); + catc_set_reg(catc, RxUnit, RxEnable | RxPolarity | RxMultiCast); + + dbg("Init done."); + + printk(KERN_INFO "%s: CATC EL1210A NetMate USB Ethernet at usb%d:%d.%d, ", + netdev->name, usbdev->bus->busnum, usbdev->devnum, ifnum); + for (i = 0; i < 5; i++) printk("%2.2x:", netdev->dev_addr[i]); + printk("%2.2x.\n", netdev->dev_addr[i]); + + return catc; +} + +static void catc_disconnect(struct usb_device *usbdev, void *dev_ptr) +{ + struct catc *catc = dev_ptr; + unregister_netdev(catc->netdev); + kfree(catc->netdev); + kfree(catc); +} + +/* + * Module functions and tables. + */ + +static struct usb_device_id catc_id_table [] = { + { USB_DEVICE(0x0423, 0xa) }, /* CATC Netmate */ + { USB_DEVICE(0x0423, 0xc) }, /* CATC Netmate II, Belkin F5U111 */ + { USB_DEVICE(0x08d1, 0x1) }, /* smartBridges smartNIC */ + { } +}; + +MODULE_DEVICE_TABLE(usb, catc_id_table); + +static struct usb_driver catc_driver = { + name: "catc", + probe: catc_probe, + disconnect: catc_disconnect, + id_table: catc_id_table, +}; + +static int __init catc_init(void) +{ + info(DRIVER_VERSION " " DRIVER_DESC); + usb_register(&catc_driver); + return 0; +} + +static void __exit catc_exit(void) +{ + usb_deregister(&catc_driver); +} + +module_init(catc_init); +module_exit(catc_exit); diff -u --recursive --new-file v2.4.5/linux/drivers/usb/dabusb.c linux/drivers/usb/dabusb.c --- v2.4.5/linux/drivers/usb/dabusb.c Mon May 21 15:02:06 2001 +++ linux/drivers/usb/dabusb.c Tue Jun 12 15:53:37 2001 @@ -837,8 +837,7 @@ dbg("dabusb_init: driver registered"); - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/dc2xx.c linux/drivers/usb/dc2xx.c --- v2.4.5/linux/drivers/usb/dc2xx.c Thu May 24 14:55:51 2001 +++ linux/drivers/usb/dc2xx.c Tue Jun 12 15:53:37 2001 @@ -499,8 +499,7 @@ { if (usb_register (&camera_driver) < 0) return -1; - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/dsbr100.c linux/drivers/usb/dsbr100.c --- v2.4.5/linux/drivers/usb/dsbr100.c Mon May 21 15:02:06 2001 +++ linux/drivers/usb/dsbr100.c Tue Jun 12 15:53:37 2001 @@ -342,8 +342,7 @@ warn("couldn't register video device"); return -EINVAL; } - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/hid.c linux/drivers/usb/hid.c --- v2.4.5/linux/drivers/usb/hid.c Mon May 21 15:02:06 2001 +++ linux/drivers/usb/hid.c Tue Jun 12 15:53:37 2001 @@ -1559,8 +1559,7 @@ static int __init hid_init(void) { usb_register(&hid_driver); - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/ibmcam.c linux/drivers/usb/ibmcam.c --- v2.4.5/linux/drivers/usb/ibmcam.c Thu May 24 14:55:51 2001 +++ linux/drivers/usb/ibmcam.c Tue Jun 12 15:53:37 2001 @@ -3147,8 +3147,7 @@ struct usb_ibmcam *ibmcam = &cams[u]; memset (ibmcam, 0, sizeof(struct usb_ibmcam)); } - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return usb_register(&ibmcam_driver); } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/mdc800.c linux/drivers/usb/mdc800.c --- v2.4.5/linux/drivers/usb/mdc800.c Mon May 21 15:02:06 2001 +++ linux/drivers/usb/mdc800.c Tue Jun 12 15:53:37 2001 @@ -932,8 +932,7 @@ if (usb_register (&mdc800_usb_driver) < 0) goto cleanup_on_fail; - info (DRIVER_VERSION " " DRIVER_AUTHOR); - info (DRIVER_DESC); + info (DRIVER_VERSION ":" DRIVER_DESC); return 0; diff -u --recursive --new-file v2.4.5/linux/drivers/usb/microtek.c linux/drivers/usb/microtek.c --- v2.4.5/linux/drivers/usb/microtek.c Mon May 21 15:02:06 2001 +++ linux/drivers/usb/microtek.c Tue Jun 12 15:53:37 2001 @@ -1029,8 +1029,7 @@ MTS_DEBUG("driver registered.\n"); } - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/net1080.c linux/drivers/usb/net1080.c --- v2.4.5/linux/drivers/usb/net1080.c Mon May 21 15:02:06 2001 +++ linux/drivers/usb/net1080.c Tue Jun 12 15:53:37 2001 @@ -599,7 +599,7 @@ } #ifdef VERBOSE dbg ("no read resubmitted"); -#endif VERBOSE +#endif /* VERBOSE */ } /*-------------------------------------------------------------------------*/ @@ -1111,8 +1111,7 @@ get_random_bytes (node_id, sizeof node_id); node_id [0] &= 0x7f; - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/ov511.c linux/drivers/usb/ov511.c --- v2.4.5/linux/drivers/usb/ov511.c Thu May 24 15:24:37 2001 +++ linux/drivers/usb/ov511.c Tue Jun 12 15:53:37 2001 @@ -337,7 +337,7 @@ /* IMPORTANT: This output MUST be kept under PAGE_SIZE * or we need to get more sophisticated. */ - out += sprintf (out, "driver_version : %s\n", version); + out += sprintf (out, "driver_version : %s\n", DRIVER_VERSION); out += sprintf (out, "custom_id : %d\n", ov511->customid); out += sprintf (out, "model : %s\n", ov511->desc ? clist[ov511->desc].description : "unknown"); @@ -3426,8 +3426,7 @@ if (usb_register(&ov511_driver) < 0) return -1; - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/pegasus.c linux/drivers/usb/pegasus.c --- v2.4.5/linux/drivers/usb/pegasus.c Mon May 21 15:02:06 2001 +++ linux/drivers/usb/pegasus.c Wed Jun 27 13:59:32 2001 @@ -53,8 +53,8 @@ /* * Version Information */ -#define DRIVER_VERSION "v0.4.18 2001/03/18 (C) 1999-2000" -#define DRIVER_AUTHOR "Petko Manolov " +#define DRIVER_VERSION "v0.4.19 2001/06/07 (C) 1999-2001" +#define DRIVER_AUTHOR "Petko Manolov " #define DRIVER_DESC "ADMtek AN986 Pegasus USB Ethernet driver" #define PEGASUS_USE_INTR @@ -117,8 +117,7 @@ warn( __FUNCTION__ " status %d", urb->status); } pegasus->flags &= ~ETH_REGS_CHANGED; - if ( pegasus->flags & CTRL_URB_SLEEP ) { - pegasus->flags &= ~CTRL_URB_SLEEP; + if ( waitqueue_active(&pegasus->ctrl_wait) ) { wake_up_interruptible( &pegasus->ctrl_wait ); } } @@ -127,12 +126,19 @@ static int get_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data) { int ret; + unsigned char *buffer; DECLARE_WAITQUEUE(wait, current); - while ( pegasus->flags & ETH_REGS_CHANGED ) { - pegasus->flags |= CTRL_URB_SLEEP; - interruptible_sleep_on( &pegasus->ctrl_wait ); + buffer = kmalloc(size,GFP_KERNEL); + if (!buffer) { + err("unable to allocate memory for configuration descriptors"); + return 0; } + memcpy(buffer,data,size); + + while ( pegasus->flags & ETH_REGS_CHANGED ) + interruptible_sleep_on( &pegasus->ctrl_wait ); + pegasus->dr.requesttype = PEGASUS_REQT_READ; pegasus->dr.request = PEGASUS_REQ_GET_REGS; pegasus->dr.value = cpu_to_le16 (0); @@ -143,11 +149,10 @@ FILL_CONTROL_URB( &pegasus->ctrl_urb, pegasus->usb, usb_rcvctrlpipe(pegasus->usb,0), (char *)&pegasus->dr, - data, size, ctrl_callback, pegasus ); + buffer, size, ctrl_callback, pegasus ); add_wait_queue( &pegasus->ctrl_wait, &wait ); set_current_state( TASK_INTERRUPTIBLE ); - pegasus->flags |= CTRL_URB_SLEEP; if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) ) { err( __FUNCTION__ " BAD CTRLs %d", ret); @@ -155,21 +160,31 @@ } schedule(); - remove_wait_queue( &pegasus->ctrl_wait, &wait ); out: - return ret; + remove_wait_queue( &pegasus->ctrl_wait, &wait ); + memcpy(data,buffer,size); + kfree(buffer); + + return ret; } static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data) { int ret; + unsigned char *buffer; DECLARE_WAITQUEUE(wait, current); - while ( pegasus->flags & ETH_REGS_CHANGED ) { - pegasus->flags |= CTRL_URB_SLEEP ; - interruptible_sleep_on( &pegasus->ctrl_wait ); + buffer = kmalloc(size, GFP_KERNEL); + if (!buffer) { + err("unable to allocate memory for configuration descriptors"); + return 0; } + memcpy(buffer, data, size); + + while ( pegasus->flags & ETH_REGS_CHANGED ) + interruptible_sleep_on( &pegasus->ctrl_wait ); + pegasus->dr.requesttype = PEGASUS_REQT_WRITE; pegasus->dr.request = PEGASUS_REQ_SET_REGS; pegasus->dr.value = cpu_to_le16 (0); @@ -180,34 +195,42 @@ FILL_CONTROL_URB( &pegasus->ctrl_urb, pegasus->usb, usb_sndctrlpipe(pegasus->usb,0), (char *)&pegasus->dr, - data, size, ctrl_callback, pegasus ); + buffer, size, ctrl_callback, pegasus ); add_wait_queue( &pegasus->ctrl_wait, &wait ); set_current_state( TASK_INTERRUPTIBLE ); - pegasus->flags |= CTRL_URB_SLEEP; if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) ) { err( __FUNCTION__ " BAD CTRL %d", ret); - return ret; + goto out; } - + schedule(); +out: remove_wait_queue( &pegasus->ctrl_wait, &wait ); - - return ret; + kfree(buffer); + + return ret; } static int set_register( pegasus_t *pegasus, __u16 indx, __u8 data ) { int ret; + unsigned char *buffer; __u16 dat = data; DECLARE_WAITQUEUE(wait, current); - while ( pegasus->flags & ETH_REGS_CHANGED ) { - pegasus->flags |= CTRL_URB_SLEEP; - interruptible_sleep_on( &pegasus->ctrl_wait ); + buffer = kmalloc(1, GFP_KERNEL); + if (!buffer) { + err("unable to allocate memory for configuration descriptors"); + return 0; } + memcpy(buffer, &data, 1); + + while ( pegasus->flags & ETH_REGS_CHANGED ) + interruptible_sleep_on( &pegasus->ctrl_wait ); + pegasus->dr.requesttype = PEGASUS_REQT_WRITE; pegasus->dr.request = PEGASUS_REQ_SET_REG; pegasus->dr.value = cpu_to_le16p( &dat); @@ -218,21 +241,22 @@ FILL_CONTROL_URB( &pegasus->ctrl_urb, pegasus->usb, usb_sndctrlpipe(pegasus->usb,0), (char *)&pegasus->dr, - &data, 1, ctrl_callback, pegasus ); + buffer, 1, ctrl_callback, pegasus ); add_wait_queue( &pegasus->ctrl_wait, &wait ); set_current_state( TASK_INTERRUPTIBLE ); - pegasus->flags |= CTRL_URB_SLEEP; if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) ) { err( __FUNCTION__ " BAD CTRL %d", ret); - return ret; + goto out; } schedule(); +out: remove_wait_queue( &pegasus->ctrl_wait, &wait ); + kfree(buffer); - return ret; + return ret; } @@ -421,7 +445,7 @@ return 1; if ( usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS || - usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK1 ) { + usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK ) { __u16 auxmode; read_mii_word( pegasus, 0, 0x1b, &auxmode ); @@ -767,7 +791,6 @@ } else { pegasus->eth_regs[EthCtrl0] &= ~RX_MULTICAST; pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS; - info("%s: set Rx mode", net->name); } pegasus->flags |= ETH_REGS_CHANGE; @@ -905,8 +928,7 @@ int __init pegasus_init(void) { - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return usb_register( &pegasus_driver ); } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/pegasus.h linux/drivers/usb/pegasus.h --- v2.4.5/linux/drivers/usb/pegasus.h Mon May 21 17:04:24 2001 +++ linux/drivers/usb/pegasus.h Wed Jun 27 13:59:32 2001 @@ -128,30 +128,51 @@ }; #define VENDOR_3COM 0x0506 -#define VENDOR_ACCTON 0x083a -#define VENDOR_ADMTEK 0x07a6 -#define VENDOR_BILLIONTON 0x08dd -#define VENDOR_COREGA 0x07aa -#define VENDOR_DLINK1 0x2001 -#define VENDOR_DLINK2 0x07b8 -#define VENDOR_IODATA 0x04bb -#define VENDOR_LANEED 0x056e -#define VENDOR_LINKSYS 0x066b -#define VENDOR_MELCO 0x0411 -#define VENDOR_SMARTBRIDGES 0x08d1 -#define VENDOR_SMC 0x0707 -#define VENDOR_SOHOWARE 0x15e8 +#define VENDOR_ABOCOM 0x07b8 +#define VENDOR_ACCTON 0x083a +#define VENDOR_ADMTEK 0x07a6 +#define VENDOR_BILLIONTON 0x08dd +#define VENDOR_COREGA 0x07aa +#define VENDOR_DLINK 0x2001 +#define VENDOR_ELSA 0x05cc +#define VENDOR_IODATA 0x04bb +#define VENDOR_LANEED 0x056e +#define VENDOR_LINKSYS 0x066b +#define VENDOR_MELCO 0x0411 +#define VENDOR_SMARTBRIDGES 0x08d1 +#define VENDOR_SMC 0x0707 +#define VENDOR_SOHOWARE 0x15e8 #else /* PEGASUS_DEV */ PEGASUS_DEV( "3Com USB Ethernet 3C460B", VENDOR_3COM, 0x4601, DEFAULT_GPIO_RESET | PEGASUS_II ) +PEGASUS_DEV( "USB HPNA/Ethernet", VENDOR_ABOCOM, 0x110c, + DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA ) +PEGASUS_DEV( "USB HPNA/Ethernet", VENDOR_ABOCOM, 0x4104, + DEFAULT_GPIO_RESET | HAS_HOME_PNA ) +PEGASUS_DEV( "USB HPNA/Ethernet", VENDOR_ABOCOM, 0x4004, + DEFAULT_GPIO_RESET | HAS_HOME_PNA ) +PEGASUS_DEV( "USB HPNA/Ethernet", VENDOR_ABOCOM, 0x4007, + DEFAULT_GPIO_RESET | HAS_HOME_PNA ) +PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x4102, + DEFAULT_GPIO_RESET | PEGASUS_II ) +PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x4002, + DEFAULT_GPIO_RESET ) +PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x400b, + DEFAULT_GPIO_RESET | PEGASUS_II ) +PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x400c, + DEFAULT_GPIO_RESET | PEGASUS_II ) +PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0xabc1, + DEFAULT_GPIO_RESET ) +PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x200c, + DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "Accton USB 10/100 Ethernet Adapter", VENDOR_ACCTON, 0x1046, DEFAULT_GPIO_RESET ) PEGASUS_DEV( "ADMtek ADM8511 \"Pegasus II\" USB Ethernet", VENDOR_ADMTEK, 0x8511, DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "ADMtek AN986 \"Pegasus\" USB Ethernet (eval board)", +PEGASUS_DEV( "ADMtek AN986 \"Pegasus\" USB Ethernet (eval. board)", VENDOR_ADMTEK, 0x0986, DEFAULT_GPIO_RESET | HAS_HOME_PNA ) PEGASUS_DEV( "Billionton USB-100", VENDOR_BILLIONTON, 0x0986, @@ -164,24 +185,32 @@ DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "Corega FEter USB-TX", VENDOR_COREGA, 0x0004, DEFAULT_GPIO_RESET ) -PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK1, 0x4001, +PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4001, LINKSYS_GPIO_RESET ) -PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK1, 0x4002, +PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4002, LINKSYS_GPIO_RESET ) -PEGASUS_DEV( "D-Link DSB-650TX(PNA)", VENDOR_DLINK1, 0x4003, +PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4102, + LINKSYS_GPIO_RESET | PEGASUS_II ) +PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x400b, + LINKSYS_GPIO_RESET | PEGASUS_II ) +PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x200c, + LINKSYS_GPIO_RESET | PEGASUS_II ) +PEGASUS_DEV( "D-Link DSB-650TX(PNA)", VENDOR_DLINK, 0x4003, DEFAULT_GPIO_RESET | HAS_HOME_PNA ) -PEGASUS_DEV( "D-Link DSB-650", VENDOR_DLINK1, 0xabc1, +PEGASUS_DEV( "D-Link DSB-650", VENDOR_DLINK, 0xabc1, DEFAULT_GPIO_RESET ) -PEGASUS_DEV( "D-Link DU-E10", VENDOR_DLINK2, 0xabc1, +PEGASUS_DEV( "Elsa Micolink USB2Ethernet", VENDOR_ELSA, 0x3000, DEFAULT_GPIO_RESET ) -PEGASUS_DEV( "D-Link DU-E100", VENDOR_DLINK2, 0x4002, - DEFAULT_GPIO_RESET ) -PEGASUS_DEV( "FiberLine USB", VENDOR_DLINK2, 0x4102, - DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "IO DATA USB ET/TX", VENDOR_IODATA, 0x0904, DEFAULT_GPIO_RESET ) PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x4002, DEFAULT_GPIO_RESET ) +PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x400b, + DEFAULT_GPIO_RESET | PEGASUS_II ) +PEGASUS_DEV( "LANEED USB Ethernet LD-USB/T", VENDOR_LANEED, 0xabc1, + DEFAULT_GPIO_RESET ) +PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x200c, + DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "Linksys USB10TX", VENDOR_LINKSYS, 0x2202, LINKSYS_GPIO_RESET ) PEGASUS_DEV( "Linksys USB100TX", VENDOR_LINKSYS, 0x2203, @@ -190,8 +219,16 @@ LINKSYS_GPIO_RESET | HAS_HOME_PNA ) PEGASUS_DEV( "Linksys USB Ethernet Adapter", VENDOR_LINKSYS, 0x2206, LINKSYS_GPIO_RESET ) +PEGASUS_DEV( "Linksys USB USB10TX", VENDOR_LINKSYS, 0x400b, + LINKSYS_GPIO_RESET | PEGASUS_II ) +PEGASUS_DEV( "Linksys USB10TX", VENDOR_LINKSYS, 0x200c, + LINKSYS_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "MELCO/BUFFALO LUA-TX", VENDOR_MELCO, 0x0001, DEFAULT_GPIO_RESET ) +PEGASUS_DEV( "MELCO/BUFFALO LUA-TX", VENDOR_MELCO, 0x0005, + DEFAULT_GPIO_RESET ) +PEGASUS_DEV( "MELCO/BUFFALO LUA2-TX", VENDOR_MELCO, 0x0009, + DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "smartNIC 2 PnP Adapter", VENDOR_SMARTBRIDGES, 0x0003, DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "SMC 202 USB Ethernet", VENDOR_SMC, 0x0200, diff -u --recursive --new-file v2.4.5/linux/drivers/usb/plusb.c linux/drivers/usb/plusb.c --- v2.4.5/linux/drivers/usb/plusb.c Mon May 21 15:02:06 2001 +++ linux/drivers/usb/plusb.c Tue Jun 12 15:53:37 2001 @@ -1014,8 +1014,7 @@ dbg("plusb_init: driver registered"); - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/printer.c linux/drivers/usb/printer.c --- v2.4.5/linux/drivers/usb/printer.c Mon May 21 15:02:06 2001 +++ linux/drivers/usb/printer.c Tue Jun 12 15:53:37 2001 @@ -662,8 +662,7 @@ { if (usb_register(&usblp_driver)) return -1; - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/pwc-ctrl.c linux/drivers/usb/pwc-ctrl.c --- v2.4.5/linux/drivers/usb/pwc-ctrl.c Fri May 25 09:48:50 2001 +++ linux/drivers/usb/pwc-ctrl.c Wed Jun 20 17:42:09 2001 @@ -236,9 +236,7 @@ if (ret < 0) return ret; if (pEntry->compressed) - ret = pdev->decompressor->init(pdev->release, buf, &pdev->decompress_data); - if (ret < 0) - return ret; + pdev->decompressor->init(pdev->release, buf, pdev->decompress_data); /* Set various parameters */ pdev->vframes = frames; @@ -303,9 +301,7 @@ return ret; if (pChoose->bandlength > 0) - ret = pdev->decompressor->init(pdev->release, buf, &pdev->decompress_data); - if (ret < 0) - return ret; + pdev->decompressor->init(pdev->release, buf, pdev->decompress_data); /* Set various parameters */ pdev->vframes = frames; @@ -366,9 +362,7 @@ return ret; if (pChoose->bandlength > 0) - ret = pdev->decompressor->init(pdev->release, buf, &pdev->decompress_data); - if (ret < 0) - return ret; + pdev->decompressor->init(pdev->release, buf, pdev->decompress_data); /* All set and go */ pdev->vframes = frames; @@ -429,14 +423,11 @@ return ret; } } - /* If the video mode was not supported, we still adjust the view size, - since xawtv (Again! Stupid program...) doesn't care zit about - return values. - */ pdev->view.x = width; pdev->view.y = height; pwc_set_image_buffer_size(pdev); - Trace(TRACE_SIZE, "Set viewport to %dx%d, image size is %dx%d. Palette = %d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y, pdev->vpalette); + Trace(TRACE_SIZE, "Set viewport to %dx%d, image size is %dx%d, palette = %d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y, pdev->vpalette); +Debug("bandlength = %d\n", pdev->vbandlength); return 0; } @@ -482,22 +473,15 @@ pdev->image.size = pdev->image.x * pdev->image.y * factor / 4; pdev->view.size = pdev->view.x * pdev->view.y * factor / 4; - pdev->offset.x = (pdev->view.x - pdev->image.x) / 2; - pdev->offset.y = (pdev->view.y - pdev->image.y) / 2; - if (pdev->vpalette == VIDEO_PALETTE_YUV420 || pdev->vpalette == VIDEO_PALETTE_YUV420P) { - /* Align offset, or you'll get some very weird results in - YUV mode... x must be multiple of 4 (to get the Y's in - place), and y even (or you'll mixup U & V). - */ - pdev->offset.x &= 0xFFFC; - pdev->offset.y &= 0xFFFE; - /* This is the offset in the Y area, hence no factor */ - pdev->offset.size = (pdev->offset.y * pdev->view.x + pdev->offset.x); - } - else - pdev->offset.size = (pdev->offset.y * pdev->view.x + pdev->offset.x) * factor / 4; + /* Align offset, or you'll get some very weird results in + YUV420 mode... x must be multiple of 4 (to get the Y's in + place), and y even (or you'll mixup U & V). This is less of a + problem for YUV420P. + */ + pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC; + pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE; - /* Set buffers to gray */ + /* Fill buffers with gray or black */ for (i = 0; i < MAX_IMAGES; i++) { if (pdev->image_ptr[i] != NULL) memset(pdev->image_ptr[i], filler, pdev->view.size); diff -u --recursive --new-file v2.4.5/linux/drivers/usb/pwc-if.c linux/drivers/usb/pwc-if.c --- v2.4.5/linux/drivers/usb/pwc-if.c Fri May 25 09:48:50 2001 +++ linux/drivers/usb/pwc-if.c Wed Jun 20 17:42:09 2001 @@ -84,10 +84,10 @@ static int default_size = PSZ_QCIF; static int default_fps = 10; -static int default_palette = VIDEO_PALETTE_RGB24; /* This is normal for webcams */ +static int default_palette = VIDEO_PALETTE_YUV420P; /* This format is understood by most tools */ static int default_fbufs = 3; /* Default number of frame buffers */ static int default_mbufs = 2; /* Default number of mmap() buffers */ - int pwc_trace = TRACE_MODULE | TRACE_FLOW; + int pwc_trace = TRACE_MODULE | TRACE_FLOW | TRACE_PWCX; static int power_save = 0; int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */ @@ -110,7 +110,7 @@ owner: THIS_MODULE, name: "Philips Webcam", /* Filled in later */ type: VID_TYPE_CAPTURE, - hardware: VID_HARDWARE_PWC, /* Let's pretend for now */ + hardware: VID_HARDWARE_PWC, open: pwc_video_open, close: pwc_video_close, read: pwc_video_read, @@ -321,14 +321,16 @@ } } - /* Allocate decompressor buffer space */ - kbuf = vmalloc(FRAME_SIZE); - if (kbuf == NULL) { - Err("Failed to allocate compressed image buffer.\n"); - return -ENOMEM; + /* Allocate decompressor table space */ + kbuf = NULL; + if (pdev->decompressor != NULL) { + kbuf = kmalloc(pdev->decompressor->table_size, GFP_KERNEL); + if (kbuf == NULL) { + Err("Failed to allocate decompress table.\n"); + return -ENOMEM; + } } - memset(kbuf, 0, FRAME_SIZE); - pdev->decompress_buffer = kbuf; + pdev->decompress_data = kbuf; /* Allocate image buffer; double buffer for mmap() */ kbuf = rvmalloc(default_mbufs * pdev->view_max.size * 4); @@ -361,6 +363,7 @@ return; } #endif + /* Release Iso-pipe buffers */ Trace(TRACE_MEMORY, "Freeing ISO buffers.\n"); for (i = 0; i < MAX_ISO_BUFS; i++) @@ -368,6 +371,7 @@ kfree(pdev->sbuf[i].data); pdev->sbuf[i].data = NULL; } + /* The same for frame buffers */ Trace(TRACE_MEMORY, "Freeing frame buffers.\n"); if (pdev->fbuf != NULL) { @@ -380,11 +384,14 @@ kfree(pdev->fbuf); pdev->fbuf = NULL; } - /* Intermediate decompression buffer */ + + /* Intermediate decompression buffer & tables */ Trace(TRACE_MEMORY, "Freeing decompression buffer\n"); - if (pdev->decompress_buffer != NULL) - vfree(pdev->decompress_buffer); - pdev->decompress_buffer = NULL; + if (pdev->decompress_data != NULL) { + kfree(pdev->decompress_data); + pdev->decompress_data = NULL; + } + pdev->decompressor = NULL; /* Release image buffers */ Trace(TRACE_MEMORY, "Freeing image buffers\n"); @@ -401,7 +408,7 @@ the user program. The first scheme involves the ISO buffers (called thus since they transport ISO data from the USB controller), and not really interesting. Suffices to say the data from this buffer is quickly - gathered in an interrupt handler (pwc_isoc_hanlder) and placed into the + gathered in an interrupt handler (pwc_isoc_handler) and placed into the frame buffer. The frame buffer is the second scheme, and is the central element here. @@ -412,8 +419,8 @@ either read() or mmap(). The image buffer is the third scheme, in which frames are decompressed - and converted into any of the desired image formats (rgb, bgr, yuv, etc). - For mmap() there is more than one image buffer available. + and possibly converted into planar format. For mmap() there is more than + one image buffer available. The frame buffers provide the image buffering, in case the user process is a bit slow. This introduces lag and some undesired side-effects. @@ -500,7 +507,7 @@ /** \brief Reset all buffers, pointers and lists, except for the image_used[] buffer. - If the image_used[] buffer is cleared too mmap()/VIDIOCSYNC will run into trouble. + If the image_used[] buffer is cleared too, mmap()/VIDIOCSYNC will run into trouble. */ static void pwc_reset_buffers(struct pwc_device *pdev) { @@ -589,10 +596,11 @@ pdev->fill_image = (pdev->fill_image + 1) % default_mbufs; } +/* XXX: 2001-06-17: The YUV420 palette will be phased out soon */ static int pwc_set_palette(struct pwc_device *pdev, int pal) { - if ( - pal == VIDEO_PALETTE_YUV420 + if ( pal == VIDEO_PALETTE_YUV420 + || pal == VIDEO_PALETTE_YUV420P #if PWC_DEBUG || pal == VIDEO_PALETTE_RAW #endif @@ -640,10 +648,7 @@ fbuf = pdev->fill_frame; if (fbuf == NULL) { Err("pwc_isoc_handler without valid fill frame.\n"); - if (waitqueue_active(&pdev->frameq)) - wake_up_interruptible(&pdev->frameq); - if (waitqueue_active(&pdev->pollq)) - wake_up_interruptible(&pdev->pollq); + wake_up_interruptible(&pdev->frameq); return; } fillptr = fbuf->data + fbuf->filled; @@ -750,12 +755,8 @@ pdev->vlast_packet_size = flen; } /* ..status == 0 */ } - if (awake) { - if (waitqueue_active(&pdev->frameq)) - wake_up_interruptible(&pdev->frameq); - if (waitqueue_active(&pdev->pollq)) - wake_up_interruptible(&pdev->pollq); - } + if (awake) + wake_up_interruptible(&pdev->frameq); } @@ -811,6 +812,7 @@ while (i >= 0) { if (pdev->sbuf[i].urb != NULL) usb_free_urb(pdev->sbuf[i].urb); + pdev->sbuf[i].urb = NULL; i--; } return ret; @@ -842,6 +844,8 @@ ret = usb_submit_urb(pdev->sbuf[i].urb); if (ret) Err("isoc_init() submit_urb %d failed with error %d\n", i, ret); + else + Trace(TRACE_OPEN, "pwc_isoc_init(): URB submitted.\n"); } /* data should stream in now */ @@ -945,10 +949,16 @@ } } + /* Find our decompressor, if any */ + pdev->decompressor = pwc_find_decompressor(pdev->type); +#if PWC_DEBUG + Debug("Found decompressor for %d at 0x%p\n", pdev->type, pdev->decompressor); +#endif + /* So far, so good. Allocate memory. */ i = pwc_allocate_buffers(pdev); if (i < 0) { - Trace(TRACE_OPEN, "Failed to allocate memory.\n"); + Trace(TRACE_OPEN, "Failed to allocate buffer memory.\n"); up(&pdev->modlock); return i; } @@ -965,12 +975,6 @@ pdev->sequence = 0; #endif - /* Find our decompressor, if any */ - pdev->decompressor = pwc_find_decompressor(pdev->type); -#if PWC_DEBUG - Debug("Found decompressor for %d at 0x%p\n", pdev->type, pdev->decompressor); -#endif - /* Set some defaults */ pdev->vsnapshot = 0; if (pdev->type == 730 || pdev->type == 740) @@ -1064,12 +1068,11 @@ } pdev->vopen = 0; - pwc_free_buffers(pdev); if (pdev->decompressor != NULL) { - pdev->decompressor->exit(&pdev->decompress_data); + pdev->decompressor->exit(); pdev->decompressor->unlock(); } - pdev->decompressor = NULL; + pwc_free_buffers(pdev); /* wake up _disconnect() routine */ if (pdev->unplugged) @@ -1078,11 +1081,20 @@ /* * FIXME: what about two parallel reads ???? + * ANSWER: Not supported. You can't open the device more than once, + despite what the V4L1 interface says. First, I don't see + the need, second there's no mechanism of alerting the + 2nd/3rd/... process of events like changing image size. + And I don't see the point of blocking that for the + 2nd/3rd/... process. + In multi-threaded environments reading parallel from any + device is tricky anyhow. */ static long pwc_video_read(struct video_device *vdev, char *buf, unsigned long count, int noblock) { struct pwc_device *pdev; + DECLARE_WAITQUEUE(wait, current); Trace(TRACE_READ, "video_read(0x%p, %p, %ld, %d) called.\n", vdev, buf, count, noblock); if (vdev == NULL) @@ -1097,20 +1109,26 @@ /* In case we're doing partial reads, we don't have to wait for a frame */ if (pdev->image_read_pos == 0) { - /* See if a frame is completed, process that */ - if (noblock && pdev->full_frames == NULL) - return -EAGAIN; + /* Do wait queueing according to the (doc)book */ + add_wait_queue(&pdev->frameq, &wait); while (pdev->full_frames == NULL) { - interruptible_sleep_on(&pdev->frameq); - if (pdev->unplugged) { - Debug("pwc_video_read: Device got unplugged (2).\n"); - return -EPIPE; - } - if (signal_pending(current)) - return -EINTR; - } - - /* Decompress & convert now */ + if (noblock) { + remove_wait_queue(&pdev->frameq, &wait); + current->state = TASK_RUNNING; + return -EWOULDBLOCK; + } + if (signal_pending(current)) { + remove_wait_queue(&pdev->frameq, &wait); + current->state = TASK_RUNNING; + return -ERESTARTSYS; + } + schedule(); + current->state = TASK_INTERRUPTIBLE; + } + remove_wait_queue(&pdev->frameq, &wait); + current->state = TASK_RUNNING; + + /* Decompress [, convert] and release frame */ if (pwc_handle_frame(pdev)) return -EFAULT; } @@ -1145,7 +1163,7 @@ if (pdev == NULL) return -EFAULT; - poll_wait(file, &pdev->pollq, wait); + poll_wait(file, &pdev->frameq, wait); if (pdev->unplugged) { Debug("pwc_video_poll: Device got unplugged.\n"); return POLLERR; @@ -1159,6 +1177,7 @@ static int pwc_video_ioctl(struct video_device *vdev, unsigned int cmd, void *arg) { struct pwc_device *pdev; + DECLARE_WAITQUEUE(wait, current); if (vdev == NULL) return -EFAULT; @@ -1271,6 +1290,11 @@ /* * FIXME: Suppose we are mid read + ANSWER: No problem: the firmware of the camera + can handle brightness/contrast/etc + changes at _any_ time, and the palette + is used exactly once in the uncompress + routine. */ pwc_set_brightness(pdev, p.brightness); pwc_set_contrast(pdev, p.contrast); @@ -1309,11 +1333,6 @@ if (copy_from_user(&vw, arg, sizeof(vw))) return -EFAULT; -/* - size = pwc_decode_size(pdev, vw.width, vw.height); - if (size < 0) - return -EINVAL; -*/ fps = (vw.flags & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT; snapshot = vw.flags & PWC_FPS_SNAPSHOT; if (fps == 0) @@ -1385,11 +1404,6 @@ int ret; Trace(TRACE_OPEN, "VIDIOCMCAPTURE: changing size to please xawtv :-(.\n"); -/* - size = pwc_decode_size(pdev, vm.width, vm.height); - if (size < 0) - return -EINVAL; -*/ ret = pwc_try_video_mode(pdev, vm.width, vm.height, pdev->vframes, pdev->vcompression, pdev->vsnapshot); if (ret) return ret; @@ -1435,28 +1449,32 @@ Trace(TRACE_READ, "VIDIOCSYNC called (%d).\n", mbuf); + /* bounds check */ if (mbuf < 0 || mbuf >= default_mbufs) return -EINVAL; /* check if this buffer was requested anyway */ if (pdev->image_used[mbuf] == 0) return -EINVAL; - /* We (re)use the frame-waitqueue here. That may - conflict with read(), but any programmer that uses - read() and mmap() simultaneously should be given - a job at Micro$oft. As janitor. + /* Add ourselves to the frame wait-queue. FIXME: needs auditing for safety. + QUSTION: In what respect? I think that using the + frameq is safe now. */ + add_wait_queue(&pdev->frameq, &wait); while (pdev->full_frames == NULL) { - interruptible_sleep_on(&pdev->frameq); - if (pdev->unplugged) { - Debug("VIDIOCSYNC: Device got unplugged.\n"); - return -EPIPE; - } - if (signal_pending(current)) - return -EINTR; + if (signal_pending(current)) { + remove_wait_queue(&pdev->frameq, &wait); + current->state = TASK_RUNNING; + return -ERESTARTSYS; + } + schedule(); + current->state = TASK_INTERRUPTIBLE; } + remove_wait_queue(&pdev->frameq, &wait); + current->state = TASK_RUNNING; + /* The frame is ready. Expand in the image buffer requested by the user. I don't care if you mmap() 5 buffers and request data in this order: @@ -1537,7 +1555,6 @@ vendor_id = udev->descriptor.idVendor; product_id = udev->descriptor.idProduct; - if (vendor_id == 0x0471) { switch (product_id) { @@ -1612,7 +1629,6 @@ pdev->udev = udev; init_waitqueue_head(&pdev->frameq); - init_waitqueue_head(&pdev->pollq); init_waitqueue_head(&pdev->remove_ok); pdev->vcompression = pwc_preferred_compression; @@ -1691,7 +1707,6 @@ a frame, let them return an error condition */ wake_up(&pdev->frameq); - wake_up(&pdev->pollq); /* Wait until we get a 'go' from _close(). This had a gigantic race condition, since we kfree() @@ -1736,7 +1751,7 @@ MODULE_PARM(fps, "i"); MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30"); MODULE_PARM(palette, "s"); -MODULE_PARM_DESC(palette, "Initial colour format of images. One of rgb24, bgr24, rgb32, bgr32, yuyv, yuv420, yuv420p"); +MODULE_PARM_DESC(palette, "Initial colour format of images. One of yuv420, yuv420p"); MODULE_PARM(fbufs, "i"); MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve"); MODULE_PARM(mbufs, "i"); @@ -1786,8 +1801,10 @@ /* Determine default palette */ if (!strcmp(palette, "yuv420")) default_palette = VIDEO_PALETTE_YUV420; + if (!strcmp(palette, "yuv420p")) + default_palette = VIDEO_PALETTE_YUV420P; else { - Err("Palette not recognized: try palette=yuv420.\n"); + Err("Palette not recognized: try palette=yuv420 or yuv420p.\n"); return -EINVAL; } Info("Default palette set to %d.\n", default_palette); diff -u --recursive --new-file v2.4.5/linux/drivers/usb/pwc-uncompress.c linux/drivers/usb/pwc-uncompress.c --- v2.4.5/linux/drivers/usb/pwc-uncompress.c Fri May 25 09:48:50 2001 +++ linux/drivers/usb/pwc-uncompress.c Wed Jun 20 17:42:09 2001 @@ -21,6 +21,8 @@ themselves. It also has a decompressor wrapper function. */ +#include + #include "pwc.h" #include "pwc-uncompress.h" @@ -38,7 +40,7 @@ void pwc_register_decompressor(struct pwc_decompressor *pwcd) { if (pwc_find_decompressor(pwcd->type) == NULL) { - Debug("Adding decompressor for model %d.\n", pwcd->type); + Trace(TRACE_PWCX, "Adding decompressor for model %d.\n", pwcd->type); list_add_tail(&pwcd->pwcd_list, &pwc_decompressor_list); } } @@ -50,7 +52,7 @@ find = pwc_find_decompressor(type); if (find != NULL) { - Debug("Removing decompressor for model %d.\n", type); + Trace(TRACE_PWCX, "Removing decompressor for model %d.\n", type); list_del(&find->pwcd_list); } } @@ -74,8 +76,11 @@ int pwc_decompress(struct pwc_device *pdev) { struct pwc_frame_buf *fbuf; - int n, l, c, w; + int n, line, col, stride; void *yuv, *image, *dst; + u16 *src; + u16 *dsty, *dstu, *dstv; + if (pdev == NULL) return -EFAULT; @@ -92,7 +97,7 @@ image = pdev->image_ptr[pdev->fill_image]; if (!image) return -EFAULT; - + #if PWC_DEBUG /* This is a quickie */ if (pdev->vpalette == VIDEO_PALETTE_RAW) { @@ -101,49 +106,78 @@ } #endif - /* Compressed formats are decompressed in decompress_buffer, then - * transformed into the desired format - */ - yuv = pdev->decompress_buffer; - n = 0; - if (pdev->vbandlength == 0) { /* uncompressed */ - yuv = fbuf->data + pdev->frame_header_size; /* Skip header */ - } - else { - if (pdev->decompressor) - n = pdev->decompressor->decompress(pdev->decompress_data, pdev->image.x, pdev->image.y, pdev->vbandlength, yuv, fbuf->data + pdev->frame_header_size, 0); - else - n = -ENXIO; /* No such device or address: missing decompressor */ - } - if (n < 0) { - Err("Error in decompression engine: %d\n", n); - return n; - } - - /* At this point 'yuv' always points to the uncompressed, non-scaled YUV420I data */ - if (pdev->image.x == pdev->view.x && pdev->image.y == pdev->view.y) { - /* Sizes matches; make it quick */ - switch(pdev->vpalette) { + yuv = fbuf->data + pdev->frame_header_size; /* Skip header */ + if (pdev->vbandlength == 0) { + /* Uncompressed mode. We copy the data into the output buffer, + using the viewport size (which may be larger than the image + size). Unfortunately we have to do a bit of byte stuffing + to get the desired output format/size. + */ + switch (pdev->vpalette) { case VIDEO_PALETTE_YUV420: - memcpy(image, yuv, pdev->image.size); + /* Calculate byte offsets per line in image & view */ + n = (pdev->image.x * 3) / 2; + col = (pdev->view.x * 3) / 2; + /* Offset into image */ + dst = image + (pdev->view.x * pdev->offset.y + pdev->offset.x) * 3 / 2; + for (line = 0; line < pdev->image.y; line++) { + memcpy(dst, yuv, n); + yuv += n; + dst += col; + } break; - } - } - else { - /* Size mismatch; use viewport conversion routines */ - switch(pdev->vpalette) { - case VIDEO_PALETTE_YUV420: - dst = image + pdev->offset.size; - w = pdev->view.x * 6; - c = pdev->image.x * 6; - for (l = 0; l < pdev->image.y; l++) { - memcpy(dst, yuv, c); - dst += w; - yuv += c; + + case VIDEO_PALETTE_YUV420P: + /* + * We do some byte shuffling here to go from the + * native format to YUV420P. + */ + src = (u16 *)yuv; + n = pdev->view.x * pdev->view.y; + + /* offset in Y plane */ + stride = pdev->view.x * pdev->offset.y + pdev->offset.x; + dsty = (u16 *)(image + stride); + + /* offsets in U/V planes */ + stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2; + dstu = (u16 *)(image + n + stride); + dstv = (u16 *)(image + n + n / 4 + stride); + + /* increment after each line */ + stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */ + + for (line = 0; line < pdev->image.y; line++) { + for (col = 0; col < pdev->image.x; col += 4) { + *dsty++ = *src++; + *dsty++ = *src++; + if (line & 1) + *dstv++ = *src++; + else + *dstu++ = *src++; + } + dsty += stride; + if (line & 1) + dstv += (stride >> 1); + else + dstu += (stride >> 1); } break; - } - } + } + } + else { + /* Compressed; the decompressor routines will write the data + in interlaced or planar format immediately. + */ + if (pdev->decompressor) + pdev->decompressor->decompress( + &pdev->image, &pdev->view, &pdev->offset, + yuv, image, + pdev->vpalette == VIDEO_PALETTE_YUV420P ? 1 : 0, + pdev->decompress_data, pdev->vbandlength); + else + return -ENXIO; /* No such device or address: missing decompressor */ + } return 0; } @@ -154,4 +188,3 @@ EXPORT_SYMBOL_NOVERS(pwc_decompressor_version); EXPORT_SYMBOL(pwc_register_decompressor); EXPORT_SYMBOL(pwc_unregister_decompressor); -EXPORT_SYMBOL(pwc_find_decompressor); diff -u --recursive --new-file v2.4.5/linux/drivers/usb/pwc-uncompress.h linux/drivers/usb/pwc-uncompress.h --- v2.4.5/linux/drivers/usb/pwc-uncompress.h Tue May 22 10:25:36 2001 +++ linux/drivers/usb/pwc-uncompress.h Wed Jun 20 17:42:09 2001 @@ -15,13 +15,19 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* This file is the bridge between the kernel module and the plugin; it + describes the structures and datatypes used in both modules. Any + significant change should be reflected by increasing the + pwc_decompressor_version major number. + */ #ifndef PWC_DEC_H #define PWC_DEC_H #include - #include +#include "pwc.h" + #ifdef __cplusplus extern "C" { #endif @@ -33,12 +39,16 @@ */ struct pwc_decompressor { - int type; /* type of camera (645, 646, etc) */ - int (* init)(int release, void *buffer, void **data); /* Initialization routine; should be called after each set_video_mode */ - void (* exit)(void **data); /* Cleanup routine */ - int (* decompress)(void *data, int width, int height, int bandlength, void *dst, void *src, int planar); /* The decompression routine itself */ - void (* lock)(void); /* make sure module cannot be unloaded */ - void (* unlock)(void); /* release lock on module */ + int type; /* type of camera (645, 680, etc) */ + int table_size; /* memory needed */ + + void (* init)(int release, void *buffer, void *table); /* Initialization routine; should be called after each set_video_mode */ + void (* exit)(void); /* Cleanup routine */ + void (* decompress)(struct pwc_coord *image, struct pwc_coord *view, struct pwc_coord *offset, + void *src, void *dst, int planar, + void *table, int bandlength); + void (* lock)(void); /* make sure module cannot be unloaded */ + void (* unlock)(void); /* release lock on module */ struct list_head pwcd_list; }; diff -u --recursive --new-file v2.4.5/linux/drivers/usb/pwc.h linux/drivers/usb/pwc.h --- v2.4.5/linux/drivers/usb/pwc.h Fri May 25 09:48:50 2001 +++ linux/drivers/usb/pwc.h Wed Jun 20 17:42:09 2001 @@ -43,6 +43,7 @@ #define TRACE_MEMORY 0x0010 #define TRACE_FLOW 0x0020 #define TRACE_SIZE 0x0040 +#define TRACE_PWCX 0x0080 #define TRACE_SEQUENCE 0x1000 #define Trace(R, A...) if (pwc_trace & R) printk(KERN_DEBUG PWC_NAME " " A) @@ -56,28 +57,10 @@ #define TOUCAM_TRAILER_SIZE 4 /* Version block */ -#define PWC_MAJOR 7 -#define PWC_MINOR 1 -#define PWC_RELEASE "7.1" - -#if defined(CONFIG_ARM) - #define PWC_PROCESSOR "ARM" -#endif -#if defined(CONFIG_M686) - #define PWC_PROCESSOR "PPro" -#endif -#if !defined(PWC_PROCESSOR) - #define PWC_PROCESSOR "P5" -#endif - -#if defined(__SMP__) || defined(CONFIG_SMP) -#define PWC_SMP "(SMP)" -#else -#define PWC_SMP "(UP)" -#endif - -#define PWC_VERSION PWC_RELEASE " " PWC_PROCESSOR " " PWC_SMP -#define PWC_NAME "pwc" +#define PWC_MAJOR 8 +#define PWC_MINOR 0 +#define PWC_VERSION "8.0" +#define PWC_NAME "pwc" /* Turn certain features on/off */ #define PWC_INT_PIPE 0 @@ -156,12 +139,12 @@ char vsnapshot; /* snapshot mode */ char vsync; /* used by isoc handler */ - /* The image acquisition requires 3 to 5 steps: + /* The image acquisition requires 3 to 4 steps: 1. data is gathered in short packets from the USB controller 2. data is synchronized and packed into a frame buffer - 3. in case data is compressed, decompress it into a separate buffer - 4. data is optionally converted to RGB/YUV - 5. data is transfered to the user process + 3a. in case data is compressed, decompress it directly into image buffer + 3b. in case data is uncompressed, copy into image buffer with viewport + 4. data is transfered to the user process Note that MAX_ISO_BUFS != MAX_FRAMES != MAX_IMAGES.... We have in effect a back-to-back-double-buffer system. @@ -171,11 +154,11 @@ char iso_init; /* 2: frame */ - struct pwc_frame_buf *fbuf; - struct pwc_frame_buf *empty_frames, *empty_frames_tail; - struct pwc_frame_buf *full_frames, *full_frames_tail; - struct pwc_frame_buf *read_frame; - struct pwc_frame_buf *fill_frame; + struct pwc_frame_buf *fbuf; /* all frames */ + struct pwc_frame_buf *empty_frames, *empty_frames_tail; /* all empty frames */ + struct pwc_frame_buf *full_frames, *full_frames_tail; /* all filled frames */ + struct pwc_frame_buf *fill_frame; /* frame currently filled */ + struct pwc_frame_buf *read_frame; /* frame currently read by user process */ int frame_size; int frame_header_size, frame_trailer_size; int drop_frames; @@ -186,7 +169,6 @@ /* 3: decompression */ struct pwc_decompressor *decompressor; /* function block with decompression routines */ void *decompress_data; /* private data for decompression engine */ - void *decompress_buffer; /* decompressed data */ /* 4: image */ /* We have an 'image' and a 'view', where 'image' is the fixed-size image @@ -205,20 +187,11 @@ int image_read_pos; /* In case we read data in pieces, keep track of were we are in the imagebuffer */ int image_used[MAX_IMAGES]; /* For MCAPTURE and SYNC */ - /* Kernel specific structures. These were once moved to the end - of the structure and padded with bytes after I found out - some of these have different sizes in different kernel versions. - But since this is now a source release, I don't have this problem - anymore. - - Fortunately none of these structures are needed in the pwcx module. - */ struct semaphore modlock; /* to prevent races in video_open(), etc */ spinlock_t ptrlock; /* for manipulating the buffer pointers */ /*** Misc. data ***/ wait_queue_head_t frameq; /* When waiting for a frame to finish... */ - wait_queue_head_t pollq; /* poll() has it's own waitqueue */ wait_queue_head_t remove_ok; /* When we got hot unplugged, we have to avoid a few race conditions */ #if PWC_INT_PIPE void *usb_int_handler; /* for the interrupt endpoint */ diff -u --recursive --new-file v2.4.5/linux/drivers/usb/rio500.c linux/drivers/usb/rio500.c --- v2.4.5/linux/drivers/usb/rio500.c Mon May 21 15:02:06 2001 +++ linux/drivers/usb/rio500.c Tue Jun 12 15:53:37 2001 @@ -492,8 +492,7 @@ if (usb_register(&rio_driver) < 0) return -1; - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/se401.c linux/drivers/usb/se401.c --- v2.4.5/linux/drivers/usb/se401.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/se401.c Mon Jul 2 13:56:41 2001 @@ -0,0 +1,1678 @@ +/* + * Endpoints (formerly known as AOX) se401 USB Camera Driver + * + * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org) + * + * Still somewhat based on the Linux ov511 driver. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * Thanks to Endpoints Inc. (www.endpoints.com) for making documentation on + * their chipset available and supporting me while writing this driver. + * - Jeroen Vreeken + */ + +static const char version[] = "0.22"; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0) +#define virt_to_page(arg) MAP_NR(arg) +#define vmalloc_32 vmalloc +#endif + +#include "se401.h" + +static int flickerless=0; +static int video_nr = -1; + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 3, 0) +static __devinitdata struct usb_device_id device_table [] = { + { USB_DEVICE(0x03e8, 0x0004) },/* Endpoints/Aox SE401 */ + { USB_DEVICE(0x0471, 0x030b) },/* Philips PCVC665K */ + { USB_DEVICE(0x047d, 0x5001) },/* Kensington 67014 */ + { USB_DEVICE(0x047d, 0x5002) },/* Kensington 6701(5/7) */ + { USB_DEVICE(0x047d, 0x5003) },/* Kensington 67016 */ + { } +}; + +MODULE_DEVICE_TABLE(usb, device_table); +#endif + +MODULE_AUTHOR("Jeroen Vreeken "); +MODULE_DESCRIPTION("SE401 USB Camera Driver"); +MODULE_PARM(flickerless, "i"); +MODULE_PARM_DESC(flickerless, "Net frequency to adjust exposure time to (0/50/60)"); +MODULE_PARM(video_nr, "i"); +EXPORT_NO_SYMBOLS; + + +static struct usb_driver se401_driver; + + +/********************************************************************** + * + * Memory management + * + * This is a shameless copy from the USB-cpia driver (linux kernel + * version 2.3.29 or so, I have no idea what this code actually does ;). + * Actually it seems to be a copy of a shameless copy of the bttv-driver. + * Or that is a copy of a shameless copy of ... (To the powers: is there + * no generic kernel-function to do this sort of stuff?) + * + * Yes, it was a shameless copy from the bttv-driver. IIRC, Alan says + * there will be one, but apparentely not yet -jerdfelt + * + * So I copied it again for the ov511 driver -claudio + * + * Same for the se401 driver -Jeroen + **********************************************************************/ + +/* Given PGD from the address space's page table, return the kernel + * virtual mapping of the physical memory mapped at ADR. + */ +static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr) +{ + unsigned long ret = 0UL; + pmd_t *pmd; + pte_t *ptep, pte; + + if (!pgd_none(*pgd)) { + pmd = pmd_offset(pgd, adr); + if (!pmd_none(*pmd)) { + ptep = pte_offset(pmd, adr); + pte = *ptep; + if (pte_present(pte)) { + ret = (unsigned long) page_address(pte_page(pte)); + ret |= (adr & (PAGE_SIZE - 1)); + } + } + } + + return ret; +} + +/* Here we want the physical address of the memory. + * This is used when initializing the contents of the + * area and marking the pages as reserved. + */ +static inline unsigned long kvirt_to_pa(unsigned long adr) +{ + unsigned long va, kva, ret; + + va = VMALLOC_VMADDR(adr); + kva = uvirt_to_kva(pgd_offset_k(va), va); + ret = __pa(kva); + return ret; +} + +static void *rvmalloc(unsigned long size) +{ + void *mem; + unsigned long adr, page; + + /* Round it off to PAGE_SIZE */ + size += (PAGE_SIZE - 1); + size &= ~(PAGE_SIZE - 1); + + mem = vmalloc_32(size); + if (!mem) + return NULL; + + memset(mem, 0, size); /* Clear the ram out, no junk to the user */ + adr = (unsigned long) mem; + while (size > 0) { + page = kvirt_to_pa(adr); + mem_map_reserve(virt_to_page(__va(page))); + adr += PAGE_SIZE; + if (size > PAGE_SIZE) + size -= PAGE_SIZE; + else + size = 0; + } + + return mem; +} + +static void rvfree(void *mem, unsigned long size) +{ + unsigned long adr, page; + + if (!mem) + return; + + size += (PAGE_SIZE - 1); + size &= ~(PAGE_SIZE - 1); + + adr=(unsigned long) mem; + while (size > 0) { + page = kvirt_to_pa(adr); + mem_map_unreserve(virt_to_page(__va(page))); + adr += PAGE_SIZE; + if (size > PAGE_SIZE) + size -= PAGE_SIZE; + else + size = 0; + } + vfree(mem); +} + + + +/**************************************************************************** + * + * /proc interface + * + ***************************************************************************/ + +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) + +static struct proc_dir_entry *se401_proc_entry = NULL; +extern struct proc_dir_entry *video_proc_entry; + +#define YES_NO(x) ((x) ? "yes" : "no") + +static int se401_read_proc(char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + char *out = page; + int i, len; + struct usb_se401 *se401 = data; + + /* Stay under PAGE_SIZE or else bla bla bla.... */ + + out+=sprintf(out, "driver_version : %s\n", version); + out+=sprintf(out, "model : %s\n", se401->camera_name); + out+=sprintf(out, "in use : %s\n", YES_NO (se401->user)); + out+=sprintf(out, "streaming : %s\n", YES_NO (se401->streaming)); + out+=sprintf(out, "button state : %s\n", YES_NO (se401->button)); + out+=sprintf(out, "button pressed : %s\n", YES_NO (se401->buttonpressed)); + out+=sprintf(out, "num_frames : %d\n", SE401_NUMFRAMES); + + out+=sprintf(out, "Sizes :"); + for (i=0; isizes; i++) { + out+=sprintf(out, " %dx%d", se401->width[i], + se401->height[i]); + } + out+=sprintf(out, "\n"); + + out+=sprintf(out, "Frames total : %d\n", se401->readcount); + out+=sprintf(out, "Frames read : %d\n", se401->framecount); + out+=sprintf(out, "Packets dropped : %d\n", se401->dropped); + out+=sprintf(out, "Decoding Errors : %d\n", se401->error); + + len = out - page; + len -= off; + if (len < count) { + *eof = 1; + if (len <= 0) return 0; + } else + len = count; + + *start = page + off; + + return len; +} + +static int se401_write_proc(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + return -EINVAL; +} + +static void create_proc_se401_cam (struct usb_se401 *se401) +{ + char name[7]; + struct proc_dir_entry *ent; + + if (!se401_proc_entry || !se401) + return; + + sprintf (name, "video%d", se401->vdev.minor); + + ent = create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR, + se401_proc_entry); + + if (!ent) + return; + + ent->data = se401; + ent->read_proc = se401_read_proc; + ent->write_proc = se401_write_proc; + se401->proc_entry = ent; +} + +static void destroy_proc_se401_cam (struct usb_se401 *se401) +{ + /* One to much, just to be sure :) */ + char name[9]; + + if (!se401 || !se401->proc_entry) + return; + + sprintf(name, "video%d", se401->vdev.minor); + remove_proc_entry(name, se401_proc_entry); + se401->proc_entry = NULL; +} + +static void proc_se401_create (void) +{ + if (video_proc_entry == NULL) { + err("/proc/video/ doesn't exist"); + return; + } + + se401_proc_entry=create_proc_entry("se401", S_IFDIR, video_proc_entry); + + if (se401_proc_entry) + se401_proc_entry->owner = THIS_MODULE; + else + err("Unable to initialize /proc/video/se401"); +} + +static void proc_se401_destroy(void) +{ + if (se401_proc_entry == NULL) + return; + + remove_proc_entry("se401", video_proc_entry); +} +#endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */ + + +/**************************************************************************** + * + * se401 register read/write functions + * + ***************************************************************************/ + +static int se401_sndctrl(int set, struct usb_se401 *se401, unsigned short req, + unsigned short value, unsigned char *cp, int size) +{ + return usb_control_msg ( + se401->dev, + set ? usb_sndctrlpipe(se401->dev, 0) : usb_rcvctrlpipe(se401->dev, 0), + req, + (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, + 0, + cp, + size, + HZ + ); +} + +static int se401_set_feature(struct usb_se401 *se401, unsigned short selector, + unsigned short param) +{ + /* specs say that the selector (address) should go in the value field + and the param in index, but in the logs of the windows driver they do + this the other way around... + */ + return usb_control_msg ( + se401->dev, + usb_sndctrlpipe(se401->dev, 0), + SE401_REQ_SET_EXT_FEATURE, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + param, + selector, + NULL, + 0, + HZ + ); +} + +static unsigned short se401_get_feature(struct usb_se401 *se401, + unsigned short selector) +{ + /* For 'set' the selecetor should be in index, not sure if the spec is + wrong here to.... + */ + unsigned char cp[2]; + usb_control_msg ( + se401->dev, + usb_rcvctrlpipe(se401->dev, 0), + SE401_REQ_GET_EXT_FEATURE, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, + selector, + cp, + 2, + HZ + ); + return cp[0]+cp[1]*256; +} + +/**************************************************************************** + * + * Camera control + * + ***************************************************************************/ + + +static int se401_send_pict(struct usb_se401 *se401) +{ + se401_set_feature(se401, HV7131_REG_TITL, se401->expose_l);/* integration time low */ + se401_set_feature(se401, HV7131_REG_TITM, se401->expose_m);/* integration time mid */ + se401_set_feature(se401, HV7131_REG_TITU, se401->expose_h);/* integration time mid */ + se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel);/* reset level value */ + se401_set_feature(se401, HV7131_REG_ARCG, se401->rgain);/* red color gain */ + se401_set_feature(se401, HV7131_REG_AGCG, se401->ggain);/* green color gain */ + se401_set_feature(se401, HV7131_REG_ABCG, se401->bgain);/* blue color gain */ + + return 0; +} + +static void se401_set_exposure(struct usb_se401 *se401, int brightness) +{ + int integration=brightness<<5; + + if (flickerless==50) { + integration=integration-integration%106667; + } + if (flickerless==60) { + integration=integration-integration%88889; + } + se401->brightness=integration>>5; + se401->expose_h=(integration>>16)&0xff; + se401->expose_m=(integration>>8)&0xff; + se401->expose_l=integration&0xff; +} + +static int se401_get_pict(struct usb_se401 *se401, struct video_picture *p) +{ + p->brightness=se401->brightness; + if (se401->enhance) { + p->whiteness=32768; + } else { + p->whiteness=0; + } + p->colour=65535; + p->contrast=65535; + p->hue=se401->rgain<<10; + p->palette=se401->palette; + p->depth=3; /* rgb24 */ + return 0; +} + + +static int se401_set_pict(struct usb_se401 *se401, struct video_picture *p) +{ + if (p->palette != VIDEO_PALETTE_RGB24) + return 1; + se401->palette=p->palette; + if (p->hue!=se401->hue) { + se401->rgain= p->hue>>10; + se401->bgain= 0x40-(p->hue>>10); + se401->hue=p->hue; + } + if (p->brightness!=se401->brightness) { + se401_set_exposure(se401, p->brightness); + } + if (p->whiteness>=32768) { + se401->enhance=1; + } else { + se401->enhance=0; + } + se401_send_pict(se401); + se401_send_pict(se401); + return 0; +} + +/* + Hyundai have some really nice docs about this and other sensor related + stuff on their homepage: www.hei.co.kr +*/ +static void se401_auto_resetlevel(struct usb_se401 *se401) +{ + unsigned int ahrc, alrc; + int oldreset=se401->resetlevel; + + /* For some reason this normally read-only register doesn't get reset + to zero after reading them just once... + */ + se401_get_feature(se401, HV7131_REG_HIREFNOH); + se401_get_feature(se401, HV7131_REG_HIREFNOL); + se401_get_feature(se401, HV7131_REG_LOREFNOH); + se401_get_feature(se401, HV7131_REG_LOREFNOL); + ahrc=256*se401_get_feature(se401, HV7131_REG_HIREFNOH) + + se401_get_feature(se401, HV7131_REG_HIREFNOL); + alrc=256*se401_get_feature(se401, HV7131_REG_LOREFNOH) + + se401_get_feature(se401, HV7131_REG_LOREFNOL); + + /* Not an exact science, but it seems to work pretty well... */ + if (alrc > 10) { + while (alrc>=10 && se401->resetlevel < 63) { + se401->resetlevel++; + alrc /=2; + } + } else if (ahrc > 20) { + while (ahrc>=20 && se401->resetlevel > 0) { + se401->resetlevel--; + ahrc /=2; + } + } + if (se401->resetlevel!=oldreset) + se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel); + + return; +} + +/* irq handler for snapshot button */ +static void se401_button_irq(struct urb *urb) +{ + struct usb_se401 *se401=urb->context; + + if (!urb) { + info("ohoh: null urb"); + return; + } + if (!se401->dev) { + info("ohoh: device vapourished"); + return; + } + + if (urb->actual_length >=2 && !urb->status) { + if (se401->button) + se401->buttonpressed=1; + } +} + +static void se401_video_irq(struct urb *urb) +{ + struct usb_se401 *se401=urb->context; + int length=urb->actual_length; + + /* ohoh... */ + if (!se401->streaming) { + return; + } + if (!urb) { + info ("ohoh: null urb"); + return; + } + if (!se401->dev) { + info ("ohoh: device vapourished"); + return; + } + + /* 0 sized packets happen if we are to fast, but sometimes the camera + keeps sending them forever... + */ + if (length && !urb->status) { + se401->nullpackets=0; + switch(se401->scratch[se401->scratch_next].state) { + case BUFFER_READY: + case BUFFER_BUSY: { + se401->dropped++; + break; + } + case BUFFER_UNUSED: { + memcpy(se401->scratch[se401->scratch_next].data, (unsigned char *)urb->transfer_buffer, length); + se401->scratch[se401->scratch_next].state=BUFFER_READY; + se401->scratch[se401->scratch_next].offset=se401->bayeroffset; + se401->scratch[se401->scratch_next].length=length; + if (waitqueue_active(&se401->wq)) { + wake_up_interruptible(&se401->wq); + } + se401->scratch_overflow=0; + se401->scratch_next++; + if (se401->scratch_next>=SE401_NUMSCRATCH) + se401->scratch_next=0;; + break; + } + } + se401->bayeroffset+=length; + if (se401->bayeroffset>=se401->cheight*se401->cwidth) { + se401->bayeroffset=0; + } + } else { + se401->nullpackets++; + if (se401->nullpackets > SE401_MAX_NULLPACKETS) { + if (waitqueue_active(&se401->wq)) { + wake_up_interruptible(&se401->wq); + } + } + } + + /* Resubmit urb for new data */ + urb->status=0; + urb->dev=se401->dev; + if(usb_submit_urb(urb)) + info("urb burned down"); + return; +} + +static void se401_send_size(struct usb_se401 *se401, int width, int height) +{ + int i=0; + int mode=0x03; /* No compression */ + int sendheight=height; + int sendwidth=width; + + /* JangGu compression can only be used with the camera supported sizes, + but bayer seems to work with any size that fits on the sensor. + We check if we can use compression with the current size with either + 4 or 16 times subcapturing, if not we use uncompressed bayer data + but this will result in cutouts of the maximum size.... + */ + while (isizes && !(se401->width[i]==width && se401->height[i]==height)) + i++; + while (isizes) { + if (se401->width[i]==width*2 && se401->height[i]==height*2) { + sendheight=se401->height[i]; + sendwidth=se401->width[i]; + mode=0x40; + } + if (se401->width[i]==width*4 && se401->height[i]==height*4) { + sendheight=se401->height[i]; + sendwidth=se401->width[i]; + mode=0x42; + } + i++; + } + + se401_sndctrl(1, se401, SE401_REQ_SET_WIDTH, sendwidth, NULL, 0); + se401_sndctrl(1, se401, SE401_REQ_SET_HEIGHT, sendheight, NULL, 0); + se401_set_feature(se401, SE401_OPERATINGMODE, mode); + + if (mode==0x03) { + se401->format=FMT_BAYER; + } else { + se401->format=FMT_JANGGU; + } + + return; +} + +/* + In this function se401_send_pict is called several times, + for some reason (depending on the state of the sensor and the phase of + the moon :) doing this only in either place doesn't always work... +*/ +static int se401_start_stream(struct usb_se401 *se401) +{ + urb_t *urb; + int err=0, i; + se401->streaming=1; + + se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0); + se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); + + /* Set picture settings */ + se401_set_feature(se401, HV7131_REG_MODE_B, 0x05);/*windowed + pix intg */ + se401_send_pict(se401); + + se401_send_size(se401, se401->cwidth, se401->cheight); + + se401_sndctrl(1, se401, SE401_REQ_START_CONTINUOUS_CAPTURE, 0, NULL, 0); + + /* Do some memory allocation */ + for (i=0; iframe[i].data=se401->fbuf + i * se401->maxframesize; + se401->frame[i].curpix=0; + } + for (i=0; isbuf[i].data=kmalloc(SE401_PACKETSIZE, GFP_KERNEL); + } + + se401->bayeroffset=0; + se401->scratch_next=0; + se401->scratch_use=0; + se401->scratch_overflow=0; + for (i=0; iscratch[i].data=kmalloc(SE401_PACKETSIZE, GFP_KERNEL); + se401->scratch[i].state=BUFFER_UNUSED; + } + + for (i=0; idev, + usb_rcvbulkpipe(se401->dev, SE401_VIDEO_ENDPOINT), + se401->sbuf[i].data, SE401_PACKETSIZE, + se401_video_irq, + se401); + urb->transfer_flags |= USB_QUEUE_BULK; + + se401->urb[i]=urb; + + err=usb_submit_urb(se401->urb[i]); + if(err) + err("urb burned down"); + } + + se401->framecount=0; + + return 0; +} + +static int se401_stop_stream(struct usb_se401 *se401) +{ + int i; + + if (!se401->streaming || !se401->dev) + return 1; + + se401->streaming=0; + + se401_sndctrl(1, se401, SE401_REQ_STOP_CONTINUOUS_CAPTURE, 0, NULL, 0); + + se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0); + se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0); + + for (i=0; iurb[i]) { + se401->urb[i]->next=NULL; + usb_unlink_urb(se401->urb[i]); + usb_free_urb(se401->urb[i]); + se401->urb[i]=NULL; + kfree(se401->sbuf[i].data); + } + for (i=0; iscratch[i].data); + se401->scratch[i].data=NULL; + } + + return 0; +} + +static int se401_set_size(struct usb_se401 *se401, int width, int height) +{ + int wasstreaming=se401->streaming; + /* Check to see if we need to change */ + if (se401->cwidth==width && se401->cheight==height) + return 0; + + /* Check for a valid mode */ + if (!width || !height) + return 1; + if ((width & 1) || (height & 1)) + return 1; + if (width>se401->width[se401->sizes-1]) + return 1; + if (height>se401->height[se401->sizes-1]) + return 1; + + /* Stop a current stream and start it again at the new size */ + if (wasstreaming) + se401_stop_stream(se401); + se401->cwidth=width; + se401->cheight=height; + if (wasstreaming) + se401_start_stream(se401); + return 0; +} + + +/**************************************************************************** + * + * Video Decoding + * + ***************************************************************************/ + +/* + This shouldn't really be done in a v4l driver.... + But it does make the image look a lot more usable. + Basicly it lifts the dark pixels more than the light pixels. +*/ +static inline void enhance_picture(unsigned char *frame, int len) +{ + while (len--) { + *frame++=(((*frame^255)*(*frame^255))/255)^255; + } +} + +static inline void decode_JangGu_integrate(struct usb_se401 *se401, int data) +{ + struct se401_frame *frame=&se401->frame[se401->curframe]; + int linelength=se401->cwidth*3; + + if (frame->curlinepix >= linelength) { + frame->curlinepix=0; + frame->curline+=linelength; + } + + /* First three are absolute, all others relative. + * Format is rgb from right to left (mirrorred image), + * we flip it to get bgr from left to right. */ + if (frame->curlinepix < 3) { + *(frame->curline-frame->curlinepix)=1+data*4; + } else { + *(frame->curline-frame->curlinepix)= + *(frame->curline-frame->curlinepix+3)+data*4; + } + frame->curlinepix++; +} + +static inline void decode_JangGu_vlc (struct usb_se401 *se401, unsigned char *data, int bit_exp, int packetlength) +{ + int pos=0; + int vlc_cod=0; + int vlc_size=0; + int vlc_data=0; + int bit_cur; + int bit; + data+=4; + while (pos < packetlength) { + bit_cur=8; + while (bit_cur && bit_exp) { + bit=((*data)>>(bit_cur-1))&1; + if (!vlc_cod) { + if (bit) { + vlc_size++; + } else { + if (!vlc_size) { + decode_JangGu_integrate(se401, 0); + } else { + vlc_cod=2; + vlc_data=0; + } + } + } else { + if (vlc_cod==2) { + if (!bit) vlc_data=-(1<data; + int len=buffer->length; + int bit_exp=0, pix_exp=0, frameinfo=0, packetlength=0, size; + int datapos=0; + + /* New image? */ + if (!se401->frame[se401->curframe].curpix) { + se401->frame[se401->curframe].curlinepix=0; + se401->frame[se401->curframe].curline= + se401->frame[se401->curframe].data+ + se401->cwidth*3-1; + if (se401->frame[se401->curframe].grabstate==FRAME_READY) + se401->frame[se401->curframe].grabstate=FRAME_GRABBING; + se401->vlcdatapos=0; + } + while (datapos < len) { + size=1024-se401->vlcdatapos; + if (size+datapos > len) + size=len-datapos; + memcpy(se401->vlcdata+se401->vlcdatapos, data+datapos, size); + se401->vlcdatapos+=size; + packetlength=0; + if (se401->vlcdatapos >= 4) { + bit_exp=se401->vlcdata[3]+(se401->vlcdata[2]<<8); + pix_exp=se401->vlcdata[1]+((se401->vlcdata[0]&0x3f)<<8); + frameinfo=se401->vlcdata[0]&0xc0; + packetlength=((bit_exp+47)>>4)<<1; + if (packetlength > 1024) { + se401->vlcdatapos=0; + datapos=len; + packetlength=0; + se401->error++; + se401->frame[se401->curframe].curpix=0; + } + } + if (packetlength && se401->vlcdatapos >= packetlength) { + decode_JangGu_vlc(se401, se401->vlcdata, bit_exp, packetlength); + se401->frame[se401->curframe].curpix+=pix_exp*3; + datapos+=size-(se401->vlcdatapos-packetlength); + se401->vlcdatapos=0; + if (se401->frame[se401->curframe].curpix>=se401->cwidth*se401->cheight*3) { + if (se401->frame[se401->curframe].curpix==se401->cwidth*se401->cheight*3) { + if (se401->frame[se401->curframe].grabstate==FRAME_GRABBING) { + se401->frame[se401->curframe].grabstate=FRAME_DONE; + se401->framecount++; + se401->readcount++; + } + if (se401->frame[(se401->curframe+1)&(SE401_NUMFRAMES-1)].grabstate==FRAME_READY) { + se401->curframe=(se401->curframe+1) & (SE401_NUMFRAMES-1); + } + } else { + se401->error++; + } + se401->frame[se401->curframe].curpix=0; + datapos=len; + } + } else { + datapos+=size; + } + } +} + +static inline void decode_bayer (struct usb_se401 *se401, struct se401_scratch *buffer) +{ + unsigned char *data=buffer->data; + int len=buffer->length; + int offset=buffer->offset; + int datasize=se401->cwidth*se401->cheight; + struct se401_frame *frame=&se401->frame[se401->curframe]; + + unsigned char *framedata=frame->data, *curline, *nextline; + int width=se401->cwidth; + int blineoffset=0, bline; + int linelength=width*3, i; + + + if (frame->curpix==0) { + if (frame->grabstate==FRAME_READY) { + frame->grabstate=FRAME_GRABBING; + } + frame->curline=framedata+linelength; + frame->curlinepix=0; + } + + if (offset!=frame->curpix) { + /* Regard frame as lost :( */ + frame->curpix=0; + se401->error++; + return; + } + + /* Check if we have to much data */ + if (frame->curpix+len > datasize) { + len=datasize-frame->curpix; + } + if (se401->cheight%4) + blineoffset=1; + bline=frame->curpix/se401->cwidth+blineoffset; + + curline=frame->curline; + nextline=curline+linelength; + if (nextline >= framedata+datasize*3) + nextline=curline; + while (len) { + if (frame->curlinepix>=width) { + frame->curlinepix-=width; + bline=frame->curpix/width+blineoffset; + curline+=linelength*2; + nextline+=linelength*2; + if (curline >= framedata+datasize*3) { + frame->curlinepix++; + curline-=3; + nextline-=3; + len--; + data++; + frame->curpix++; + } + if (nextline >= framedata+datasize*3) + nextline=curline; + } + if ((bline&1)) { + if ((frame->curlinepix&1)) { + *(curline+2)=*data; + *(curline-1)=*data; + *(nextline+2)=*data; + *(nextline-1)=*data; + } else { + *(curline+1)= + (*(curline+1)+*data)/2; + *(curline-2)= + (*(curline-2)+*data)/2; + *(nextline+1)=*data; + *(nextline-2)=*data; + } + } else { + if ((frame->curlinepix&1)) { + *(curline+1)= + (*(curline+1)+*data)/2; + *(curline-2)= + (*(curline-2)+*data)/2; + *(nextline+1)=*data; + *(nextline-2)=*data; + } else { + *curline=*data; + *(curline-3)=*data; + *nextline=*data; + *(nextline-3)=*data; + } + } + frame->curlinepix++; + curline-=3; + nextline-=3; + len--; + data++; + frame->curpix++; + } + frame->curline=curline; + + if (frame->curpix>=datasize) { + /* Fix the top line */ + framedata+=linelength; + for (i=0; icheight; i++) { + *framedata=*(framedata+3); + *(framedata+1)=*(framedata+4); + *(framedata+2)=*(framedata+5); + framedata+=linelength; + } + frame->curpix=0; + frame->grabstate=FRAME_DONE; + se401->framecount++; + se401->readcount++; + if (se401->frame[(se401->curframe+1)&(SE401_NUMFRAMES-1)].grabstate==FRAME_READY) { + se401->curframe=(se401->curframe+1) & (SE401_NUMFRAMES-1); + } + } +} + +static int se401_newframe(struct usb_se401 *se401, int framenr) +{ + DECLARE_WAITQUEUE(wait, current); + int errors=0; + + while (se401->streaming && + (se401->frame[framenr].grabstate==FRAME_READY || + se401->frame[framenr].grabstate==FRAME_GRABBING) ) { + if(!se401->frame[framenr].curpix) { + errors++; + } + wait_interruptible( + se401->scratch[se401->scratch_use].state!=BUFFER_READY, + &se401->wq, + &wait + ); + if (se401->nullpackets > SE401_MAX_NULLPACKETS) { + se401->nullpackets=0; + info("to many null length packets, restarting capture"); + se401_stop_stream(se401); + se401_start_stream(se401); + } else { + if (se401->scratch[se401->scratch_use].state!=BUFFER_READY) { + se401->frame[framenr].grabstate=FRAME_ERROR; + return -EIO; + } + se401->scratch[se401->scratch_use].state=BUFFER_BUSY; + if (se401->format==FMT_JANGGU) { + decode_JangGu(se401, &se401->scratch[se401->scratch_use]); + } else { + decode_bayer(se401, &se401->scratch[se401->scratch_use]); + } + se401->scratch[se401->scratch_use].state=BUFFER_UNUSED; + se401->scratch_use++; + if (se401->scratch_use>=SE401_NUMSCRATCH) + se401->scratch_use=0; + if (errors > SE401_MAX_ERRORS) { + errors=0; + info("to much errors, restarting capture"); + se401_stop_stream(se401); + se401_start_stream(se401); + } + } + } + + if (se401->frame[framenr].grabstate==FRAME_DONE) + if (se401->enhance) + enhance_picture(se401->frame[framenr].data, se401->cheight*se401->cwidth*3); + return 0; +} + + +/**************************************************************************** + * + * Video4Linux + * + ***************************************************************************/ + + +static int se401_open(struct video_device *dev, int flags) +{ + struct usb_se401 *se401 = (struct usb_se401 *)dev; + int err = 0; + + MOD_INC_USE_COUNT; + down(&se401->lock); + + se401->fbuf=rvmalloc(se401->maxframesize * SE401_NUMFRAMES); + if(!se401->fbuf) err=-ENOMEM; + + if (err) { + MOD_DEC_USE_COUNT; + up(&se401->lock); + return err; + } + + se401->user=1; + + up(&se401->lock); + + return 0; +} + +static void se401_close(struct video_device *dev) +{ + struct usb_se401 *se401 = (struct usb_se401 *)dev; + int i; + + down(&se401->lock); + + for (i=0; iframe[i].grabstate=FRAME_UNUSED; + if (se401->streaming) + se401_stop_stream(se401); + + rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES); + se401->user=0; + up(&se401->lock); + + if (!se401->dev) { + video_unregister_device(&se401->vdev); + kfree(se401->width); + kfree(se401->height); + kfree(se401); + se401 = NULL; + info("device unregistered"); + } + + MOD_DEC_USE_COUNT; +} + +static int se401_init_done(struct video_device *dev) +{ +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) + create_proc_se401_cam((struct usb_se401 *)dev); +#endif + + return 0; +} + +static long se401_write(struct video_device *dev, const char *buf, unsigned long + count, int noblock) +{ + return -EINVAL; +} + +static int se401_ioctl(struct video_device *vdev, unsigned int cmd, void *arg) +{ + struct usb_se401 *se401 = (struct usb_se401 *)vdev; + + if (!se401->dev) + return -EIO; + + switch (cmd) { + case VIDIOCGCAP: + { + struct video_capability b; + strcpy(b.name, se401->camera_name); + b.type = VID_TYPE_CAPTURE; + b.channels = 1; + b.audios = 0; + b.maxwidth = se401->width[se401->sizes-1]; + b.maxheight = se401->height[se401->sizes-1]; + b.minwidth = se401->width[0]; + b.minheight = se401->height[0]; + + if (copy_to_user(arg, &b, sizeof(b))) + return -EFAULT; + + return 0; + } + case VIDIOCGCHAN: + { + struct video_channel v; + + if (copy_from_user(&v, arg, sizeof(v))) + return -EFAULT; + if (v.channel != 0) + return -EINVAL; + + v.flags = 0; + v.tuners = 0; + v.type = VIDEO_TYPE_CAMERA; + strcpy(v.name, "Camera"); + + if (copy_to_user(arg, &v, sizeof(v))) + return -EFAULT; + + return 0; + } + case VIDIOCSCHAN: + { + int v; + + if (copy_from_user(&v, arg, sizeof(v))) + return -EFAULT; + + if (v != 0) + return -EINVAL; + + return 0; + } + case VIDIOCGPICT: + { + struct video_picture p; + + se401_get_pict(se401, &p); + + if (copy_to_user(arg, &p, sizeof(p))) + return -EFAULT; + return 0; + } + case VIDIOCSPICT: + { + struct video_picture p; + + if (copy_from_user(&p, arg, sizeof(p))) + return -EFAULT; + + if (se401_set_pict(se401, &p)) + return -EINVAL; + return 0; + } + case VIDIOCSWIN: + { + struct video_window vw; + + if (copy_from_user(&vw, arg, sizeof(vw))) + return -EFAULT; + if (vw.flags) + return -EINVAL; + if (vw.clipcount) + return -EINVAL; + if (se401_set_size(se401, vw.width, vw.height)) + return -EINVAL; + + return 0; + } + case VIDIOCGWIN: + { + struct video_window vw; + + vw.x = 0; /* FIXME */ + vw.y = 0; + vw.chromakey = 0; + vw.flags = 0; + vw.clipcount = 0; + vw.width = se401->cwidth; + vw.height = se401->cheight; + + if (copy_to_user(arg, &vw, sizeof(vw))) + return -EFAULT; + + return 0; + } + case VIDIOCGMBUF: + { + struct video_mbuf vm; + int i; + + memset(&vm, 0, sizeof(vm)); + vm.size = SE401_NUMFRAMES * se401->maxframesize; + vm.frames = SE401_NUMFRAMES; + for (i=0; imaxframesize * i; + + if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm))) + return -EFAULT; + + return 0; + } + case VIDIOCMCAPTURE: + { + struct video_mmap vm; + + if (copy_from_user(&vm, arg, sizeof(vm))) + return -EFAULT; + if (vm.format != VIDEO_PALETTE_RGB24) + return -EINVAL; + if (vm.frame >= SE401_NUMFRAMES) + return -EINVAL; + if (se401->frame[vm.frame].grabstate != FRAME_UNUSED) + return -EBUSY; + + /* Is this according to the v4l spec??? */ + if (se401_set_size(se401, vm.width, vm.height)) + return -EINVAL; + se401->frame[vm.frame].grabstate=FRAME_READY; + + if (!se401->streaming) + se401_start_stream(se401); + + /* Set the picture properties */ + if (se401->framecount==0) + se401_send_pict(se401); + /* Calibrate the reset level after a few frames. */ + if (se401->framecount%20==1) + se401_auto_resetlevel(se401); + + return 0; + } + case VIDIOCSYNC: + { + int frame, ret=0; + + if (copy_from_user((void *)&frame, arg, sizeof(int))) + return -EFAULT; + + if(frame <0 || frame >= SE401_NUMFRAMES) + return -EINVAL; + + ret=se401_newframe(se401, frame); + se401->frame[frame].grabstate=FRAME_UNUSED; + return ret; + } + case VIDIOCGFBUF: + { + struct video_buffer vb; + + memset(&vb, 0, sizeof(vb)); + vb.base = NULL; /* frame buffer not supported, not used */ + + if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb))) + return -EFAULT; + + return 0; + } + case VIDIOCKEY: + return 0; + case VIDIOCCAPTURE: + return -EINVAL; + case VIDIOCSFBUF: + return -EINVAL; + case VIDIOCGTUNER: + case VIDIOCSTUNER: + return -EINVAL; + case VIDIOCGFREQ: + case VIDIOCSFREQ: + return -EINVAL; + case VIDIOCGAUDIO: + case VIDIOCSAUDIO: + return -EINVAL; + default: + return -ENOIOCTLCMD; + } /* end switch */ + + return 0; +} + +static long se401_read(struct video_device *dev, char *buf, unsigned long count, + int noblock) +{ + int realcount=count, ret=0; + struct usb_se401 *se401 = (struct usb_se401 *)dev; + + + if (se401->dev == NULL) + return -EIO; + if (realcount > se401->cwidth*se401->cheight*3) + realcount=se401->cwidth*se401->cheight*3; + + /* Shouldn't happen: */ + if (se401->frame[0].grabstate==FRAME_GRABBING) + return -EBUSY; + se401->frame[0].grabstate=FRAME_READY; + se401->frame[1].grabstate=FRAME_UNUSED; + se401->curframe=0; + + if (!se401->streaming) + se401_start_stream(se401); + + /* Set the picture properties */ + if (se401->framecount==0) + se401_send_pict(se401); + /* Calibrate the reset level after a few frames. */ + if (se401->framecount%20==1) + se401_auto_resetlevel(se401); + + ret=se401_newframe(se401, 0); + + if (!ret) { + copy_to_user(buf, se401->frame[0].data, realcount); + } else { + realcount=ret; + } + se401->frame[0].grabstate=FRAME_UNUSED; + + return realcount; +} + +static int se401_mmap(struct video_device *dev, const char *adr, + unsigned long size) +{ + struct usb_se401 *se401 = (struct usb_se401 *)dev; + unsigned long start = (unsigned long)adr; + unsigned long page, pos; + + down(&se401->lock); + + if (se401->dev == NULL) { + up(&se401->lock); + return -EIO; + } + if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) { + up(&se401->lock); + return -EINVAL; + } + pos = (unsigned long)se401->fbuf; + while (size > 0) { + page = kvirt_to_pa(pos); + if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) { + up(&se401->lock); + return -EAGAIN; + } + start += PAGE_SIZE; + pos += PAGE_SIZE; + if (size > PAGE_SIZE) + size -= PAGE_SIZE; + else + size = 0; + } + up(&se401->lock); + + return 0; +} + +static struct video_device se401_template = { + name: "se401 USB camera", + type: VID_TYPE_CAPTURE, + hardware: VID_HARDWARE_SE401, + open: se401_open, + close: se401_close, + read: se401_read, + write: se401_write, + ioctl: se401_ioctl, + mmap: se401_mmap, + initialize: se401_init_done, +}; + + + +/***************************/ +static int se401_init(struct usb_se401 *se401) +{ + int i=0, rc; + unsigned char cp[0x40]; + char temp[200]; + + /* led on */ + se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); + + /* get camera descriptor */ + rc=se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0, cp, sizeof(cp)); + if (cp[1]!=0x41) { + err("Wrong descriptor type"); + return 1; + } + sprintf (temp, "ExtraFeatures: %d", cp[3]); + + se401->sizes=cp[4]+cp[5]*256; + se401->width=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL); + se401->height=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL); + for (i=0; isizes; i++) { + se401->width[i]=cp[6+i*4+0]+cp[6+i*4+1]*256; + se401->height[i]=cp[6+i*4+2]+cp[6+i*4+3]*256; + } + sprintf (temp, "%s Sizes:", temp); + for (i=0; isizes; i++) { + sprintf(temp, "%s %dx%d", temp, se401->width[i], se401->height[i]); + } + info("%s", temp); + se401->maxframesize=se401->width[se401->sizes-1]*se401->height[se401->sizes-1]*3; + + rc=se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp)); + se401->cwidth=cp[0]+cp[1]*256; + rc=se401_sndctrl(0, se401, SE401_REQ_GET_HEIGHT, 0, cp, sizeof(cp)); + se401->cheight=cp[0]+cp[1]*256; + + if (!cp[2] && SE401_FORMAT_BAYER) { + err("Bayer format not supported!"); + return 1; + } + /* set output mode (BAYER) */ + se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE, SE401_FORMAT_BAYER, NULL, 0); + + rc=se401_sndctrl(0, se401, SE401_REQ_GET_BRT, 0, cp, sizeof(cp)); + se401->brightness=cp[0]+cp[1]*256; + /* some default values */ + se401->resetlevel=0x2d; + se401->rgain=0x20; + se401->ggain=0x20; + se401->bgain=0x20; + se401_set_exposure(se401, 20000); + se401->palette=VIDEO_PALETTE_RGB24; + se401->enhance=1; + se401->dropped=0; + se401->error=0; + se401->framecount=0; + se401->readcount=0; + + /* Start interrupt transfers for snapshot button */ + se401->inturb=usb_alloc_urb(0); + if (!se401->inturb) { + info("Allocation of inturb failed"); + return 1; + } + FILL_INT_URB(se401->inturb, se401->dev, + usb_rcvintpipe(se401->dev, SE401_BUTTON_ENDPOINT), + &se401->button, sizeof(se401->button), + se401_button_irq, + se401, + HZ/10 + ); + if (usb_submit_urb(se401->inturb)) { + info("int urb burned down"); + return 1; + } + + /* Flash the led */ + se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0); + se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); + se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0); + se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0); + + return 0; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0) +static void* se401_probe(struct usb_device *dev, unsigned int ifnum) +#else +static void* __devinit se401_probe(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id) +#endif +{ + struct usb_interface_descriptor *interface; + struct usb_se401 *se401; + char *camera_name=NULL; + + /* We don't handle multi-config cameras */ + if (dev->descriptor.bNumConfigurations != 1) + return NULL; + + interface = &dev->actconfig->interface[ifnum].altsetting[0]; + + /* Is it an se401? */ + if (dev->descriptor.idVendor == 0x03e8 && + dev->descriptor.idProduct == 0x0004) { + camera_name="Endpoints/Aox SE401"; + } else if (dev->descriptor.idVendor == 0x0471 && + dev->descriptor.idProduct == 0x030b) { + camera_name="Philips PCVC665K"; + } else if (dev->descriptor.idVendor == 0x047d && + dev->descriptor.idProduct == 0x5001) { + camera_name="Kensington VideoCAM 67014"; + } else if (dev->descriptor.idVendor == 0x047d && + dev->descriptor.idProduct == 0x5002) { + camera_name="Kensington VideoCAM 6701(5/7)"; + } else if (dev->descriptor.idVendor == 0x047d && + dev->descriptor.idProduct == 0x5003) { + camera_name="Kensington VideoCAM 67016"; + } else + return NULL; + + /* Checking vendor/product should be enough, but what the hell */ + if (interface->bInterfaceClass != 0x00) + return NULL; + if (interface->bInterfaceSubClass != 0x00) + return NULL; + + /* We found one */ + info("SE401 camera found: %s", camera_name); + + if ((se401 = kmalloc(sizeof(*se401), GFP_KERNEL)) == NULL) { + err("couldn't kmalloc se401 struct"); + return NULL; + } + + memset(se401, 0, sizeof(*se401)); + + se401->dev = dev; + se401->iface = interface->bInterfaceNumber; + se401->camera_name = camera_name; + + info("firmware version: %02x", dev->descriptor.bcdDevice & 255); + + if (se401_init(se401)) + return NULL; + memcpy(&se401->vdev, &se401_template, sizeof(se401_template)); + memcpy(se401->vdev.name, se401->camera_name, strlen(se401->camera_name)); + if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) == -1) { + err("video_register_device failed"); + return NULL; + } + info("registered new video device: video%d", se401->vdev.minor); + + init_waitqueue_head(&se401->wq); + init_MUTEX(&se401->lock); + + return se401; +} + +static void se401_disconnect(struct usb_device *dev, void *ptr) +{ + int i; + struct usb_se401 *se401 = (struct usb_se401 *) ptr; + + /* We don't want people trying to open up the device */ + if (!se401->user) + video_unregister_device(&se401->vdev); + + usb_driver_release_interface(&se401_driver, + &se401->dev->actconfig->interface[se401->iface]); + + se401->dev = NULL; + se401->frame[0].grabstate = FRAME_ERROR; + se401->frame[1].grabstate = FRAME_ERROR; + + se401->streaming = 0; + + if (waitqueue_active(&se401->wq)) + wake_up_interruptible(&se401->wq); + + for (i=0; iurb[i]) { + se401->urb[i]->next = NULL; + usb_unlink_urb(se401->urb[i]); + usb_free_urb(se401->urb[i]); + se401->urb[i] = NULL; + kfree(se401->sbuf[i].data); + } + for (i=0; iscratch[i].data) { + kfree(se401->scratch[i].data); + } + if (se401->inturb) { + usb_unlink_urb(se401->inturb); + usb_free_urb(se401->inturb); + } + info("%s disconnected", se401->camera_name); + +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) + destroy_proc_se401_cam(se401); +#endif + + /* Free the memory */ + if (!se401->user) { + kfree(se401->width); + kfree(se401->height); + kfree(se401); + se401 = NULL; + } +} + + +static struct usb_driver se401_driver = { + name: "se401", +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 3, 0) + id_table: device_table, +#endif + probe: se401_probe, + disconnect: se401_disconnect +}; + + + +/**************************************************************************** + * + * Module routines + * + ***************************************************************************/ + +static int __init usb_se401_init(void) +{ +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) + proc_se401_create(); +#endif + + info("SE401 usb camera driver version %s registering", version); + if (flickerless) + if (flickerless!=50 && flickerless!=60) { + info("Invallid flickerless value, use 0, 50 or 60."); + return -1; + } + if (usb_register(&se401_driver) < 0) + return -1; + return 0; +} + +static void __exit usb_se401_exit(void) +{ + usb_deregister(&se401_driver); + info("SE401 driver deregistered"); + +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) + proc_se401_destroy(); +#endif +} + +module_init(usb_se401_init); +module_exit(usb_se401_exit); diff -u --recursive --new-file v2.4.5/linux/drivers/usb/se401.h linux/drivers/usb/se401.h --- v2.4.5/linux/drivers/usb/se401.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/se401.h Wed Jun 27 13:59:32 2001 @@ -0,0 +1,234 @@ + +#ifndef __LINUX_se401_H +#define __LINUX_se401_H + +#include +#include +#include + +#define se401_DEBUG /* Turn on debug messages */ + +#ifdef se401_DEBUG +# define PDEBUG(level, fmt, args...) \ +if (debug >= level) info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args) +#else +# define PDEBUG(level, fmt, args...) do {} while(0) +#endif + +/* An almost drop-in replacement for sleep_on_interruptible */ +#define wait_interruptible(test, queue, wait) \ +{ \ + add_wait_queue(queue, wait); \ + set_current_state(TASK_INTERRUPTIBLE); \ + if (test) \ + schedule(); \ + remove_wait_queue(queue, wait); \ + set_current_state(TASK_RUNNING); \ + if (signal_pending(current)) \ + break; \ +} + +#define SE401_REQ_GET_CAMERA_DESCRIPTOR 0x06 +#define SE401_REQ_START_CONTINUOUS_CAPTURE 0x41 +#define SE401_REQ_STOP_CONTINUOUS_CAPTURE 0x42 +#define SE401_REQ_CAPTURE_FRAME 0x43 +#define SE401_REQ_GET_BRT 0x44 +#define SE401_REQ_SET_BRT 0x45 +#define SE401_REQ_GET_WIDTH 0x4c +#define SE401_REQ_SET_WIDTH 0x4d +#define SE401_REQ_GET_HEIGHT 0x4e +#define SE401_REQ_SET_HEIGHT 0x4f +#define SE401_REQ_GET_OUTPUT_MODE 0x50 +#define SE401_REQ_SET_OUTPUT_MODE 0x51 +#define SE401_REQ_GET_EXT_FEATURE 0x52 +#define SE401_REQ_SET_EXT_FEATURE 0x53 +#define SE401_REQ_CAMERA_POWER 0x56 +#define SE401_REQ_LED_CONTROL 0x57 +#define SE401_REQ_BIOS 0xff + +#define SE401_BIOS_READ 0x07 + +#define SE401_FORMAT_BAYER 0x40 + +/* Hyundai hv7131b registers + 7121 and 7141 should be the same (haven't really checked...) */ +/* Mode registers: */ +#define HV7131_REG_MODE_A 0x00 +#define HV7131_REG_MODE_B 0x01 +#define HV7131_REG_MODE_C 0x02 +/* Frame registers: */ +#define HV7131_REG_FRSU 0x10 +#define HV7131_REG_FRSL 0x11 +#define HV7131_REG_FCSU 0x12 +#define HV7131_REG_FCSL 0x13 +#define HV7131_REG_FWHU 0x14 +#define HV7131_REG_FWHL 0x15 +#define HV7131_REG_FWWU 0x16 +#define HV7131_REG_FWWL 0x17 +/* Timing registers: */ +#define HV7131_REG_THBU 0x20 +#define HV7131_REG_THBL 0x21 +#define HV7131_REG_TVBU 0x22 +#define HV7131_REG_TVBL 0x23 +#define HV7131_REG_TITU 0x25 +#define HV7131_REG_TITM 0x26 +#define HV7131_REG_TITL 0x27 +#define HV7131_REG_TMCD 0x28 +/* Adjust Registers: */ +#define HV7131_REG_ARLV 0x30 +#define HV7131_REG_ARCG 0x31 +#define HV7131_REG_AGCG 0x32 +#define HV7131_REG_ABCG 0x33 +#define HV7131_REG_APBV 0x34 +#define HV7131_REG_ASLP 0x54 +/* Offset Registers: */ +#define HV7131_REG_OFSR 0x50 +#define HV7131_REG_OFSG 0x51 +#define HV7131_REG_OFSB 0x52 +/* REset level statistics registers: */ +#define HV7131_REG_LOREFNOH 0x57 +#define HV7131_REG_LOREFNOL 0x58 +#define HV7131_REG_HIREFNOH 0x59 +#define HV7131_REG_HIREFNOL 0x5a + +/* se401 registers */ +#define SE401_OPERATINGMODE 0x2000 + + +/* size of usb transfers */ +#define SE401_PACKETSIZE 4096 +/* number of queued bulk transfers to use, should be about 8 */ +#define SE401_NUMSBUF 1 +/* read the usb specs for this one :) */ +#define SE401_VIDEO_ENDPOINT 1 +#define SE401_BUTTON_ENDPOINT 2 +/* number of frames supported by the v4l part */ +#define SE401_NUMFRAMES 2 +/* scratch buffers for passing data to the decoders */ +#define SE401_NUMSCRATCH 32 +/* maximum amount of data in a JangGu packet */ +#define SE401_VLCDATALEN 1024 +/* number of nul sized packets to receive before kicking the camera */ +#define SE401_MAX_NULLPACKETS 4000 +/* number of decoding errors before kicking the camera */ +#define SE401_MAX_ERRORS 200 + +struct usb_device; + +struct se401_sbuf { + unsigned char *data; +}; + +enum { + FRAME_UNUSED, /* Unused (no MCAPTURE) */ + FRAME_READY, /* Ready to start grabbing */ + FRAME_GRABBING, /* In the process of being grabbed into */ + FRAME_DONE, /* Finished grabbing, but not been synced yet */ + FRAME_ERROR, /* Something bad happened while processing */ +}; + +enum { + FMT_BAYER, + FMT_JANGGU, +}; + +enum { + BUFFER_UNUSED, + BUFFER_READY, + BUFFER_BUSY, + BUFFER_DONE, +}; + +struct se401_scratch { + unsigned char *data; + volatile int state; + int offset; + int length; +}; + +struct se401_frame { + unsigned char *data; /* Frame buffer */ + + volatile int grabstate; /* State of grabbing */ + + unsigned char *curline; + int curlinepix; + int curpix; +}; + +struct usb_se401 { + struct video_device vdev; + + /* Device structure */ + struct usb_device *dev; + + unsigned char iface; + + char *camera_name; + + int change; + int brightness; + int hue; + int rgain; + int ggain; + int bgain; + int expose_h; + int expose_m; + int expose_l; + int resetlevel; + + int enhance; + + int format; + int sizes; + int *width; + int *height; + int cwidth; /* current width */ + int cheight; /* current height */ + int palette; + int maxframesize; + int cframesize; /* current framesize */ + + struct semaphore lock; + int user; /* user count for exclusive use */ + + int streaming; /* Are we streaming video? */ + + char *fbuf; /* Videodev buffer area */ + + urb_t *urb[SE401_NUMSBUF]; + urb_t *inturb; + + int button; + int buttonpressed; + + int curframe; /* Current receiving frame */ + struct se401_frame frame[SE401_NUMFRAMES]; + int readcount; + int framecount; + int error; + int dropped; + + int scratch_next; + int scratch_use; + int scratch_overflow; + struct se401_scratch scratch[SE401_NUMSCRATCH]; + + /* Decoder specific data: */ + unsigned char vlcdata[SE401_VLCDATALEN]; + int vlcdatapos; + int bayeroffset; + + struct se401_sbuf sbuf[SE401_NUMSBUF]; + + wait_queue_head_t wq; /* Processes waiting */ + + /* proc interface */ + struct proc_dir_entry *proc_entry; /* /proc/se401/videoX */ + + int nullpackets; +}; + + +#endif + diff -u --recursive --new-file v2.4.5/linux/drivers/usb/serial/Config.in linux/drivers/usb/serial/Config.in --- v2.4.5/linux/drivers/usb/serial/Config.in Fri Apr 6 15:51:50 2001 +++ linux/drivers/usb/serial/Config.in Wed Jun 27 13:59:32 2001 @@ -28,6 +28,8 @@ bool ' USB Keyspan USA-49W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA49W fi dep_tristate ' USB MCT Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_MCT_U232 $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL + dep_tristate ' USB Prolific 2303 Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_PL2303 $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL + dep_tristate ' USB REINER SCT cyberJack pinpad/e-com chipcard reader (EXPERIMENTAL)' CONFIG_USB_SERIAL_CYBERJACK $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL dep_tristate ' USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_OMNINET $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL fi diff -u --recursive --new-file v2.4.5/linux/drivers/usb/serial/Makefile linux/drivers/usb/serial/Makefile --- v2.4.5/linux/drivers/usb/serial/Makefile Mon Mar 19 17:21:54 2001 +++ linux/drivers/usb/serial/Makefile Wed Jun 27 13:59:32 2001 @@ -18,6 +18,8 @@ obj-$(CONFIG_USB_SERIAL_EMPEG) += empeg.o obj-$(CONFIG_USB_SERIAL_MCT_U232) += mct_u232.o obj-$(CONFIG_USB_SERIAL_EDGEPORT) += io_edgeport.o +obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o +obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.o # Objects that export symbols. export-objs := usbserial.o diff -u --recursive --new-file v2.4.5/linux/drivers/usb/serial/belkin_sa.c linux/drivers/usb/serial/belkin_sa.c --- v2.4.5/linux/drivers/usb/serial/belkin_sa.c Mon May 21 15:02:06 2001 +++ linux/drivers/usb/serial/belkin_sa.c Wed Jun 20 16:52:30 2001 @@ -24,6 +24,9 @@ * -- Add support for flush commands * -- Add everything that is missing :) * + * (30-May-2001 gkh + * switched from using spinlock to a semaphore, which fixes lots of problems. + * * 08-Apr-2001 gb * - Identify version on module load. * @@ -85,7 +88,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.0.0" +#define DRIVER_VERSION "v1.1" #define DRIVER_AUTHOR "William Greathouse " #define DRIVER_DESC "USB Belkin Serial converter driver" @@ -282,11 +285,11 @@ static int belkin_sa_open (struct usb_serial_port *port, struct file *filp) { - unsigned long flags; + int retval = 0; dbg(__FUNCTION__" port %d", port->number); - spin_lock_irqsave (&port->port_lock, flags); + down (&port->sem); ++port->open_count; MOD_INC_USE_COUNT; @@ -299,30 +302,32 @@ * enhance buffering. Win trace shows 16 initial read URBs. */ port->read_urb->dev = port->serial->dev; - if (usb_submit_urb(port->read_urb)) + retval = usb_submit_urb(port->read_urb); + if (retval) { err("usb_submit_urb(read bulk) failed"); + goto exit; + } port->interrupt_in_urb->dev = port->serial->dev; - if (usb_submit_urb(port->interrupt_in_urb)) + retval = usb_submit_urb(port->interrupt_in_urb); + if (retval) err(" usb_submit_urb(read int) failed"); } - spin_unlock_irqrestore (&port->port_lock, flags); +exit: + up (&port->sem); - return 0; + return retval; } /* belkin_sa_open */ static void belkin_sa_close (struct usb_serial_port *port, struct file *filp) { - unsigned long flags; - dbg(__FUNCTION__" port %d", port->number); - spin_lock_irqsave (&port->port_lock, flags); + down (&port->sem); --port->open_count; - MOD_DEC_USE_COUNT; if (port->open_count <= 0) { /* shutdown our bulk reads and writes */ @@ -332,7 +337,8 @@ port->active = 0; } - spin_unlock_irqrestore (&port->port_lock, flags); + up (&port->sem); + MOD_DEC_USE_COUNT; } /* belkin_sa_close */ @@ -600,8 +606,7 @@ usb_serial_register (&belkin_old_device); usb_serial_register (&peracom_device); usb_serial_register (&gocom232_device); - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/serial/cyberjack.c linux/drivers/usb/serial/cyberjack.c --- v2.4.5/linux/drivers/usb/serial/cyberjack.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/serial/cyberjack.c Wed Jun 27 13:59:32 2001 @@ -0,0 +1,520 @@ +/* + * REINER SCT cyberJack pinpad/e-com USB Chipcard Reader Driver + * + * Copyright (C) 2001 REINER SCT + * Author: Matthias Bruestle + * + * Contact: linux-usb@sii.li (see MAINTAINERS) + * + * This program is largely derived from work by the linux-usb group + * and associated source files. Please see the usb/serial files for + * individual credits and copyrights. + * + * 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. + * + * Thanks to Greg Kroah-Hartman (greg@kroah.com) for his help and + * patience. + * + * In case of problems, please write to the contact e-mail address + * mentioned above. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_USB_SERIAL_DEBUG + static int debug = 1; +#else + static int debug; +#endif + +#include "usb-serial.h" + +/* + * Version Information + */ +#define DRIVER_VERSION "v1.0" +#define DRIVER_AUTHOR "Matthias Bruestle" +#define DRIVER_DESC "REINER SCT cyberJack pinpad/e-com USB Chipcard Reader Driver" + + +#define CYBERJACK_VENDOR_ID 0x0C4B +#define CYBERJACK_PRODUCT_ID 0x0100 + +/* Function prototypes */ +static int cyberjack_startup (struct usb_serial *serial); +static void cyberjack_shutdown (struct usb_serial *serial); +static int cyberjack_open (struct usb_serial_port *port, struct file *filp); +static void cyberjack_close (struct usb_serial_port *port, struct file *filp); +static int cyberjack_write (struct usb_serial_port *port, int from_user, + const unsigned char *buf, int count); +static void cyberjack_read_int_callback( struct urb *urb ); +static void cyberjack_read_bulk_callback (struct urb *urb); +static void cyberjack_write_bulk_callback (struct urb *urb); + +static __devinitdata struct usb_device_id id_table [] = { + { USB_DEVICE(CYBERJACK_VENDOR_ID, CYBERJACK_PRODUCT_ID) }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, id_table); + +struct usb_serial_device_type cyberjack_device = { + name: "Reiner SCT Cyberjack USB card reader", + id_table: id_table, + needs_interrupt_in: MUST_HAVE, + needs_bulk_in: MUST_HAVE, + needs_bulk_out: MUST_HAVE, + num_interrupt_in: 1, + num_bulk_in: 1, + num_bulk_out: 1, + num_ports: 1, + startup: cyberjack_startup, + shutdown: cyberjack_shutdown, + open: cyberjack_open, + close: cyberjack_close, + write: cyberjack_write, + read_int_callback: cyberjack_read_int_callback, + read_bulk_callback: cyberjack_read_bulk_callback, + write_bulk_callback: cyberjack_write_bulk_callback, +}; + +struct cyberjack_private { + short rdtodo; /* Bytes still to read */ + unsigned char wrbuf[5*64]; /* Buffer for collecting data to write */ + short wrfilled; /* Overall data size we already got */ + short wrsent; /* Data akready sent */ +}; + +/* do some startup allocations not currently performed by usb_serial_probe() */ +static int cyberjack_startup (struct usb_serial *serial) +{ + struct cyberjack_private *priv; + + dbg (__FUNCTION__); + + /* allocate the private data structure */ + serial->port->private = kmalloc(sizeof(struct cyberjack_private), GFP_KERNEL); + if (!serial->port->private) + return (-1); /* error */ + + /* set initial values */ + priv = (struct cyberjack_private *)serial->port->private; + priv->rdtodo = 0; + priv->wrfilled = 0; + priv->wrsent = 0; + + init_waitqueue_head(&serial->port->write_wait); + + return( 0 ); +} + +static void cyberjack_shutdown (struct usb_serial *serial) +{ + int i; + + dbg (__FUNCTION__); + + /* stop reads and writes on all ports */ + for (i=0; i < serial->num_ports; ++i) { + while (serial->port[i].open_count > 0) { + cyberjack_close (&serial->port[i], NULL); + } + /* My special items, the standard routines free my urbs */ + if (serial->port[i].private) + kfree(serial->port[i].private); + } +} + +static int cyberjack_open (struct usb_serial_port *port, struct file *filp) +{ + struct cyberjack_private *priv; + int result = 0; + + if (port_paranoia_check (port, __FUNCTION__)) + return -ENODEV; + + MOD_INC_USE_COUNT; + + dbg(__FUNCTION__ " - port %d", port->number); + + down (&port->sem); + + ++port->open_count; + + if (!port->active) { + port->active = 1; + /* force low_latency on so that our tty_push actually forces + * the data through, otherwise it is scheduled, and with high + * data rates (like with OHCI) data can get lost. + */ + port->tty->low_latency = 1; + + priv = (struct cyberjack_private *)port->private; + priv->rdtodo = 0; + priv->wrfilled = 0; + priv->wrsent = 0; + + /* shutdown any bulk reads that might be going on */ + usb_unlink_urb (port->write_urb); + usb_unlink_urb (port->read_urb); + usb_unlink_urb (port->interrupt_in_urb); + + port->interrupt_in_urb->dev = port->serial->dev; + result = usb_submit_urb(port->interrupt_in_urb); + if (result) + err(" usb_submit_urb(read int) failed"); + dbg(__FUNCTION__ " - usb_submit_urb(int urb)"); + } + + up (&port->sem); + + return result; +} + +static void cyberjack_close (struct usb_serial_port *port, struct file *filp) +{ + dbg(__FUNCTION__ " - port %d", port->number); + + down (&port->sem); + + --port->open_count; + + if (port->open_count <= 0) { + /* shutdown any bulk reads that might be going on */ + usb_unlink_urb (port->write_urb); + usb_unlink_urb (port->read_urb); + usb_unlink_urb (port->interrupt_in_urb); + + port->active = 0; + port->open_count = 0; + } + + up (&port->sem); + MOD_DEC_USE_COUNT; +} + +static int cyberjack_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) +{ + struct usb_serial *serial = port->serial; + struct cyberjack_private *priv = (struct cyberjack_private *)port->private; + int result; + int wrexpected; + + dbg(__FUNCTION__ " - port %d", port->number); + dbg(__FUNCTION__ " - from_user %d", from_user); + + if (count == 0) { + dbg(__FUNCTION__ " - write request of 0 bytes"); + return (0); + } + + if (port->write_urb->status == -EINPROGRESS) { + dbg (__FUNCTION__ " - already writing"); + return (0); + } + + down (&port->sem); + + if( (count+priv->wrfilled)>sizeof(priv->wrbuf) ) { + /* To much data for buffer. Reset buffer. */ + priv->wrfilled=0; + return (0); + } + + /* Copy data */ + if (from_user) { + copy_from_user(priv->wrbuf+priv->wrfilled, buf, count); + } else { + memcpy (priv->wrbuf+priv->wrfilled, buf, count); + } + usb_serial_debug_data (__FILE__, __FUNCTION__, count, + priv->wrbuf+priv->wrfilled); + priv->wrfilled += count; + + if( priv->wrfilled >= 3 ) { + wrexpected = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3; + dbg(__FUNCTION__ " - expected data: %d", wrexpected); + } else { + wrexpected = sizeof(priv->wrbuf); + } + + if( priv->wrfilled >= wrexpected ) { + /* We have enough data to begin transmission */ + int length; + + dbg(__FUNCTION__ " - transmitting data (frame 1)"); + length = (wrexpected > port->bulk_out_size) ? port->bulk_out_size : wrexpected; + + memcpy (port->write_urb->transfer_buffer, priv->wrbuf, length ); + priv->wrsent=length; + + /* set up our urb */ + FILL_BULK_URB(port->write_urb, serial->dev, + usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress), + port->write_urb->transfer_buffer, length, + ((serial->type->write_bulk_callback) ? + serial->type->write_bulk_callback : + cyberjack_write_bulk_callback), + port); + + /* send the data out the bulk port */ + result = usb_submit_urb(port->write_urb); + if (result) { + err(__FUNCTION__ " - failed submitting write urb, error %d", result); + /* Throw away data. No better idea what to do with it. */ + priv->wrfilled=0; + priv->wrsent=0; + up (&port->sem); + return 0; + } + + dbg(__FUNCTION__ " - priv->wrsent=%d",priv->wrsent); + dbg(__FUNCTION__ " - priv->wrfilled=%d",priv->wrfilled); + + if( priv->wrsent>=priv->wrfilled ) { + dbg(__FUNCTION__ " - buffer cleaned"); + memset( priv->wrbuf, 0, sizeof(priv->wrbuf) ); + priv->wrfilled=0; + priv->wrsent=0; + } + } + + up (&port->sem); + return (count); +} + +static void cyberjack_read_int_callback( struct urb *urb ) +{ + struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct cyberjack_private *priv = (struct cyberjack_private *)port->private; + struct usb_serial *serial; + unsigned char *data = urb->transfer_buffer; + + dbg(__FUNCTION__ " - port %d", port->number); + + /* the urb might have been killed. */ + if (urb->status) + return; + + if (port_paranoia_check (port, "cyberjack_read_interrupt")) return; + + serial = port->serial; + if (serial_paranoia_check (serial, "cyberjack_read_interrupt")) return; + + usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data); + + /* React only to interrupts signaling a bulk_in transfer */ + if( (urb->actual_length==4) && (data[0]==0x01) ) { + short old_rdtodo = priv->rdtodo; + int result; + + /* This is a announcement of comming bulk_ins. */ + unsigned short size = ((unsigned short)data[3]<<8)+data[2]+3; + + if( (size>259) || (size==0) ) { + dbg( "Bad announced bulk_in data length: %d", size ); + /* Dunno what is most reliable to do here. */ + /* return; */ + } + + if( (old_rdtodo+size)<(old_rdtodo) ) { + dbg( "To many bulk_in urbs to do." ); + return; + } + + /* "+=" is probably more fault tollerant than "=" */ + priv->rdtodo += size; + + dbg(__FUNCTION__ " - rdtodo: %d", priv->rdtodo); + + if( !old_rdtodo ) { + port->read_urb->dev = port->serial->dev; + result = usb_submit_urb(port->read_urb); + if( result ) + err(__FUNCTION__ " - failed resubmitting read urb, error %d", result); + dbg(__FUNCTION__ " - usb_submit_urb(read urb)"); + } + } +} + +static void cyberjack_read_bulk_callback (struct urb *urb) +{ + struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct cyberjack_private *priv = (struct cyberjack_private *)port->private; + struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); + struct tty_struct *tty; + unsigned char *data = urb->transfer_buffer; + int i; + int result; + + dbg(__FUNCTION__ " - port %d", port->number); + + if (!serial) { + dbg(__FUNCTION__ " - bad serial pointer, exiting"); + return; + } + + if (urb->status) { + usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, urb->transfer_buffer); + dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status); + return; + } + + usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data); + + tty = port->tty; + if (urb->actual_length) { + for (i = 0; i < urb->actual_length ; ++i) { + /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */ + if(tty->flip.count >= TTY_FLIPBUF_SIZE) { + tty_flip_buffer_push(tty); + } + /* this doesn't actually push the data through unless tty->low_latency is set */ + tty_insert_flip_char(tty, data[i], 0); + } + tty_flip_buffer_push(tty); + } + + /* Reduce urbs to do by one. */ + priv->rdtodo-=urb->actual_length; + /* Just to be sure */ + if( priv->rdtodo<0 ) priv->rdtodo=0; + + dbg(__FUNCTION__ " - rdtodo: %d", priv->rdtodo); + + /* Continue to read if we have still urbs to do. */ + if( priv->rdtodo /* || (urb->actual_length==port->bulk_in_endpointAddress)*/ ) { + port->read_urb->dev = port->serial->dev; + result = usb_submit_urb(port->read_urb); + if (result) + err(__FUNCTION__ " - failed resubmitting read urb, error %d", result); + dbg(__FUNCTION__ " - usb_submit_urb(read urb)"); + } +} + +static void cyberjack_write_bulk_callback (struct urb *urb) +{ + struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct cyberjack_private *priv = (struct cyberjack_private *)port->private; + struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); + + dbg(__FUNCTION__ " - port %d", port->number); + + if (!serial) { + dbg(__FUNCTION__ " - bad serial pointer, exiting"); + return; + } + + if (urb->status) { + dbg(__FUNCTION__ " - nonzero write bulk status received: %d", urb->status); + return; + } + + /* only do something if we have more data to send */ + if( priv->wrfilled ) { + int length, blksize, result; + + if (port->write_urb->status == -EINPROGRESS) { + dbg (__FUNCTION__ " - already writing"); + return; + } + + down (&port->sem); + + dbg(__FUNCTION__ " - transmitting data (frame n)"); + + length = ((priv->wrfilled - priv->wrsent) > port->bulk_out_size) ? + port->bulk_out_size : (priv->wrfilled - priv->wrsent); + + memcpy (port->write_urb->transfer_buffer, priv->wrbuf + priv->wrsent, + length ); + priv->wrsent+=length; + + /* set up our urb */ + FILL_BULK_URB(port->write_urb, serial->dev, + usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress), + port->write_urb->transfer_buffer, length, + ((serial->type->write_bulk_callback) ? + serial->type->write_bulk_callback : + cyberjack_write_bulk_callback), + port); + + /* send the data out the bulk port */ + result = usb_submit_urb(port->write_urb); + if (result) { + err(__FUNCTION__ " - failed submitting write urb, error %d", result); + /* Throw away data. No better idea what to do with it. */ + priv->wrfilled=0; + priv->wrsent=0; + up (&port->sem); + queue_task(&port->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); + return; + } + + dbg(__FUNCTION__ " - priv->wrsent=%d",priv->wrsent); + dbg(__FUNCTION__ " - priv->wrfilled=%d",priv->wrfilled); + + blksize = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3; + + if( (priv->wrsent>=priv->wrfilled) || (priv->wrsent>=blksize) ) { + dbg(__FUNCTION__ " - buffer cleaned"); + memset( priv->wrbuf, 0, sizeof(priv->wrbuf) ); + priv->wrfilled=0; + priv->wrsent=0; + } + + up (&port->sem); + queue_task(&port->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); + return; + } + + queue_task(&port->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); + + return; +} + +static int __init cyberjack_init (void) +{ + usb_serial_register (&cyberjack_device); + + info(DRIVER_VERSION " " DRIVER_AUTHOR); + info(DRIVER_DESC); + + return 0; +} + +static void __exit cyberjack_exit (void) +{ + usb_serial_deregister (&cyberjack_device); +} + +module_init(cyberjack_init); +module_exit(cyberjack_exit); + +MODULE_AUTHOR( DRIVER_AUTHOR ); +MODULE_DESCRIPTION( DRIVER_DESC ); + +MODULE_PARM(debug, "i"); +MODULE_PARM_DESC(debug, "Debug enabled or not"); + diff -u --recursive --new-file v2.4.5/linux/drivers/usb/serial/digi_acceleport.c linux/drivers/usb/serial/digi_acceleport.c --- v2.4.5/linux/drivers/usb/serial/digi_acceleport.c Mon May 21 15:02:06 2001 +++ linux/drivers/usb/serial/digi_acceleport.c Tue Jun 12 15:53:37 2001 @@ -2078,8 +2078,7 @@ { usb_serial_register (&digi_acceleport_2_device); usb_serial_register (&digi_acceleport_4_device); - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/serial/empeg.c linux/drivers/usb/serial/empeg.c --- v2.4.5/linux/drivers/usb/serial/empeg.c Mon May 21 15:02:06 2001 +++ linux/drivers/usb/serial/empeg.c Wed Jun 20 16:52:30 2001 @@ -1,10 +1,10 @@ /* * USB Empeg empeg-car player driver * - * Copyright (C) 2000 + * Copyright (C) 2000, 2001 * Gary Brubaker (xavyer@ix.netcom.com) * - * Copyright (C) 1999, 2000 + * Copyright (C) 1999 - 2001 * Greg Kroah-Hartman (greg@kroah.com) * * This program is free software; you can redistribute it and/or modify @@ -13,6 +13,9 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (05/30/2001) gkh + * switched from using spinlock to a semaphore, which fixes lots of problems. + * * (04/08/2001) gb * Identify version on module load. * @@ -71,7 +74,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.0.0" +#define DRIVER_VERSION "v1.1" #define DRIVER_AUTHOR "Greg Kroah-Hartman , Gary Brubaker " #define DRIVER_DESC "USB Empeg Mark I/II Driver" @@ -147,15 +150,14 @@ static int empeg_open (struct usb_serial_port *port, struct file *filp) { struct usb_serial *serial = port->serial; - unsigned long flags; - int result; + int result = 0;; if (port_paranoia_check (port, __FUNCTION__)) return -ENODEV; dbg(__FUNCTION__ " - port %d", port->number); - spin_lock_irqsave (&port->port_lock, flags); + down (&port->sem); ++port->open_count; MOD_INC_USE_COUNT; @@ -236,9 +238,9 @@ } - spin_unlock_irqrestore (&port->port_lock, flags); + up (&port->sem); - return 0; + return result; } @@ -246,7 +248,6 @@ { struct usb_serial *serial; unsigned char *transfer_buffer; - unsigned long flags; if (port_paranoia_check (port, __FUNCTION__)) return; @@ -257,7 +258,7 @@ if (!serial) return; - spin_lock_irqsave (&port->port_lock, flags); + down (&port->sem); --port->open_count; @@ -276,13 +277,12 @@ port->open_count = 0; } - spin_unlock_irqrestore (&port->port_lock, flags); + up (&port->sem); /* Uncomment the following line if you want to see some statistics in your syslog */ /* info ("Bytes In = %d Bytes Out = %d", bytes_in, bytes_out); */ MOD_DEC_USE_COUNT; - } @@ -377,7 +377,7 @@ dbg(__FUNCTION__ " - port %d", port->number); - spin_lock_irqsave (&port->port_lock, flags); + spin_lock_irqsave (&write_urb_pool_lock, flags); /* tally up the number of bytes available */ for (i = 0; i < NUM_URBS; ++i) { @@ -386,7 +386,7 @@ } } - spin_unlock_irqrestore (&port->port_lock, flags); + spin_unlock_irqrestore (&write_urb_pool_lock, flags); dbg(__FUNCTION__ " - returns %d", room); @@ -403,7 +403,7 @@ dbg(__FUNCTION__ " - port %d", port->number); - spin_lock_irqsave (&port->port_lock, flags); + spin_lock_irqsave (&write_urb_pool_lock, flags); /* tally up the number of bytes waiting */ for (i = 0; i < NUM_URBS; ++i) { @@ -412,7 +412,7 @@ } } - spin_unlock_irqrestore (&port->port_lock, flags); + spin_unlock_irqrestore (&write_urb_pool_lock, flags); dbg (__FUNCTION__ " - returns %d", chars); @@ -514,15 +514,13 @@ static void empeg_throttle (struct usb_serial_port *port) { - unsigned long flags; - dbg(__FUNCTION__ " - port %d", port->number); - spin_lock_irqsave (&port->port_lock, flags); + down (&port->sem); usb_unlink_urb (port->read_urb); - spin_unlock_irqrestore (&port->port_lock, flags); + up (&port->sem); return; @@ -531,12 +529,11 @@ static void empeg_unthrottle (struct usb_serial_port *port) { - unsigned long flags; int result; dbg(__FUNCTION__ " - port %d", port->number); - spin_lock_irqsave (&port->port_lock, flags); + down (&port->sem); port->read_urb->dev = port->serial->dev; @@ -545,7 +542,7 @@ if (result) err(__FUNCTION__ " - failed submitting read urb, error %d", result); - spin_unlock_irqrestore (&port->port_lock, flags); + up (&port->sem); return; @@ -680,8 +677,7 @@ } } - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; diff -u --recursive --new-file v2.4.5/linux/drivers/usb/serial/ftdi_sio.c linux/drivers/usb/serial/ftdi_sio.c --- v2.4.5/linux/drivers/usb/serial/ftdi_sio.c Thu May 24 14:55:51 2001 +++ linux/drivers/usb/serial/ftdi_sio.c Wed Jun 20 16:52:30 2001 @@ -1,7 +1,7 @@ /* * USB FTDI SIO driver * - * Copyright (C) 1999, 2000 + * Copyright (C) 1999 - 2001 * Greg Kroah-Hartman (greg@kroah.com) * Bill Ryder (bryder@sgi.com) * @@ -15,6 +15,9 @@ * See http://reality.sgi.com/bryder_wellington/ftdi_sio for upto date testing info * and extra documentation * + * (31/May/2001) gkh + * switched from using spinlock to a semaphore, which fixes lots of problems. + * * (23/May/2001) Bill Ryder * Added runtime debug patch (thanx Tyson D Sawyer). * Cleaned up comments for 8U232 @@ -253,7 +256,7 @@ priv = serial->port->private = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL); if (!priv){ - err(__FUNCTION__"- kmalloc(%d) failed.", sizeof(struct ftdi_private)); + err(__FUNCTION__"- kmalloc(%Zd) failed.", sizeof(struct ftdi_private)); return -ENOMEM; } @@ -271,7 +274,7 @@ priv = serial->port->private = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL); if (!priv){ - err(__FUNCTION__"- kmalloc(%d) failed.", sizeof(struct ftdi_private)); + err(__FUNCTION__"- kmalloc(%Zd) failed.", sizeof(struct ftdi_private)); return -ENOMEM; } @@ -301,13 +304,12 @@ { /* ftdi_sio_open */ struct termios tmp_termios; struct usb_serial *serial = port->serial; - unsigned long flags; /* Used for spinlock */ - int result; + int result = 0; char buf[1]; /* Needed for the usb_control_msg I think */ dbg(__FUNCTION__); - spin_lock_irqsave (&port->port_lock, flags); + down (&port->sem); MOD_INC_USE_COUNT; ++port->open_count; @@ -315,8 +317,6 @@ if (!port->active){ port->active = 1; - spin_unlock_irqrestore (&port->port_lock, flags); - /* This will push the characters through immediately rather than queue a task to deliver them */ port->tty->low_latency = 1; @@ -352,11 +352,10 @@ result = usb_submit_urb(port->read_urb); if (result) err(__FUNCTION__ " - failed submitting read urb, error %d", result); - } else { /* the port was already active - so no initialisation is done */ - spin_unlock_irqrestore (&port->port_lock, flags); } - return (0); + up (&port->sem); + return result; } /* ftdi_sio_open */ @@ -365,15 +364,13 @@ struct usb_serial *serial = port->serial; unsigned int c_cflag = port->tty->termios->c_cflag; char buf[1]; - unsigned long flags; dbg( __FUNCTION__); - spin_lock_irqsave (&port->port_lock, flags); + down (&port->sem); --port->open_count; if (port->open_count <= 0) { - spin_unlock_irqrestore (&port->port_lock, flags); if (c_cflag & HUPCL){ /* Disable flow control */ if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), @@ -400,8 +397,6 @@ port->active = 0; port->open_count = 0; } else { - spin_unlock_irqrestore (&port->port_lock, flags); - /* Send a HUP if necessary */ if (!(port->tty->termios->c_cflag & CLOCAL)){ tty_hangup(port->tty); @@ -409,6 +404,7 @@ } + up (&port->sem); MOD_DEC_USE_COUNT; } /* ftdi_sio_close */ @@ -985,8 +981,7 @@ dbg(__FUNCTION__); usb_serial_register (&ftdi_sio_device); usb_serial_register (&ftdi_8U232AM_device); - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/serial/io_edgeport.c linux/drivers/usb/serial/io_edgeport.c --- v2.4.5/linux/drivers/usb/serial/io_edgeport.c Mon May 21 15:02:06 2001 +++ linux/drivers/usb/serial/io_edgeport.c Tue Jun 12 15:53:37 2001 @@ -944,7 +944,7 @@ } if (status) { - dbg(__FUNCTION__" - nonzero write bulk status received: %d", urb->status); + dbg(__FUNCTION__" - nonzero write bulk status received: %d", status); return; } @@ -3037,8 +3037,7 @@ usb_serial_register (&edgeport_16dual_device); usb_serial_register (&edgeport_compat_id_device); usb_serial_register (&edgeport_8i_device); - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/serial/keyspan.c linux/drivers/usb/serial/keyspan.c --- v2.4.5/linux/drivers/usb/serial/keyspan.c Mon May 21 15:02:06 2001 +++ linux/drivers/usb/serial/keyspan.c Wed Jun 20 16:52:30 2001 @@ -28,6 +28,9 @@ open source projects. Change History + Thu May 31 11:56:42 PDT 2001 gkh + switched from using spinlock to a semaphore + (04/08/2001) gb Identify version on module load. @@ -177,8 +180,7 @@ usb_serial_register (&keyspan_usa28x_device); usb_serial_register (&keyspan_usa49w_device); - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } @@ -833,7 +835,6 @@ struct usb_serial *serial = port->serial; const keyspan_device_details *d_details; int i, already_active, err; - unsigned long flags; urb_t *urb; s_priv = (struct keyspan_serial_private *)(serial->private); @@ -843,11 +844,11 @@ /* dbg("keyspan_open called."); */ MOD_INC_USE_COUNT; - spin_lock_irqsave (&port->port_lock, flags); + down (&port->sem); ++port->open_count; already_active = port->active; port->active = 1; - spin_unlock_irqrestore (&port->port_lock, flags); + up (&port->sem); if (already_active) return 0; @@ -887,13 +888,12 @@ struct usb_serial *serial = port->serial; /* FIXME should so sanity check */ struct keyspan_serial_private *s_priv; struct keyspan_port_private *p_priv; - unsigned long flags; /* dbg("keyspan_close called"); */ s_priv = (struct keyspan_serial_private *)(serial->private); p_priv = (struct keyspan_port_private *)(port->private); - spin_lock_irqsave (&port->port_lock, flags); + down (&port->sem); if (--port->open_count <= 0) { if (port->active) { @@ -914,7 +914,7 @@ port->open_count = 0; port->tty = 0; } - spin_unlock_irqrestore (&port->port_lock, flags); + up (&port->sem); MOD_DEC_USE_COUNT; } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/serial/keyspan_pda.c linux/drivers/usb/serial/keyspan_pda.c --- v2.4.5/linux/drivers/usb/serial/keyspan_pda.c Mon May 21 15:02:06 2001 +++ linux/drivers/usb/serial/keyspan_pda.c Wed Jun 20 16:52:30 2001 @@ -1,7 +1,7 @@ /* * USB Keyspan PDA Converter driver * - * Copyright (c) 1999, 2000 Greg Kroah-Hartman + * Copyright (c) 1999 - 2001 Greg Kroah-Hartman * Copyright (c) 1999, 2000 Brian Warner * Copyright (c) 2000 Al Borchers * @@ -12,6 +12,9 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (05/31/2001) gkh + * switched from using spinlock to a semaphore, which fixes lots of problems. + * * (04/08/2001) gb * Identify version on module load. * @@ -452,7 +455,6 @@ int request_unthrottle = 0; int rc = 0; struct keyspan_pda_private *priv; - unsigned long flags; priv = (struct keyspan_pda_private *)(port->private); /* guess how much room is left in the device's ring buffer, and if we @@ -482,7 +484,6 @@ finished). Also, the tx process is not throttled. So we are ready to write. */ - spin_lock_irqsave (&port->port_lock, flags); count = (count > port->bulk_out_size) ? port->bulk_out_size : count; /* Check if we might overrun the Tx buffer. If so, ask the @@ -502,13 +503,12 @@ 2*HZ); if (rc < 0) { dbg(" roomquery failed"); - spin_unlock_irqrestore (&port->port_lock, flags); - return rc; /* failed */ + goto exit; } if (rc == 0) { dbg(" roomquery returned 0 bytes"); - spin_unlock_irqrestore (&port->port_lock, flags); - return -EIO; /* device didn't return any data */ + rc = -EIO; /* device didn't return any data */ + goto exit; } dbg(" roomquery says %d", room); priv->tx_room = room; @@ -525,8 +525,8 @@ if (from_user) { if( copy_from_user(port->write_urb->transfer_buffer, buf, count) ) { - spin_unlock_irqrestore (&port->port_lock, flags); - return( -EFAULT ); + rc = -EFAULT; + goto exit; } } else { @@ -538,10 +538,10 @@ priv->tx_room -= count; port->write_urb->dev = port->serial->dev; - if (usb_submit_urb(port->write_urb)) { + rc = usb_submit_urb(port->write_urb); + if (rc) { dbg(" usb_submit_urb(write bulk) failed"); - spin_unlock_irqrestore (&port->port_lock, flags); - return (0); + goto exit; } } else { @@ -557,8 +557,9 @@ MOD_DEC_USE_COUNT; } - spin_unlock_irqrestore (&port->port_lock, flags); - return (count); + rc = count; +exit: + return rc; } @@ -616,11 +617,10 @@ { struct usb_serial *serial = port->serial; unsigned char room; - int rc; + int rc = 0; struct keyspan_pda_private *priv; - unsigned long flags; - spin_lock_irqsave (&port->port_lock, flags); + down (&port->sem); MOD_INC_USE_COUNT; ++port->open_count; @@ -629,7 +629,6 @@ port->active = 1; /* find out how much room is in the Tx ring */ - spin_unlock_irqrestore (&port->port_lock, flags); rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), 6, /* write_room */ USB_TYPE_VENDOR | USB_RECIP_INTERFACE @@ -639,7 +638,6 @@ &room, 1, 2*HZ); - spin_lock_irqsave (&port->port_lock, flags); if (rc < 0) { dbg(__FUNCTION__" - roomquery failed"); goto error; @@ -655,7 +653,6 @@ /* the normal serial device seems to always turn on DTR and RTS here, so do the same */ - spin_unlock_irqrestore (&port->port_lock, flags); if (port->tty->termios->c_cflag & CBAUD) keyspan_pda_set_modem_info(serial, (1<<7) | (1<<2) ); else @@ -663,19 +660,22 @@ /*Start reading from the device*/ port->interrupt_in_urb->dev = serial->dev; - if (usb_submit_urb(port->interrupt_in_urb)) + rc = usb_submit_urb(port->interrupt_in_urb); + if (rc) { dbg(__FUNCTION__" - usb_submit_urb(read int) failed"); - } else { - spin_unlock_irqrestore (&port->port_lock, flags); + goto error; + } + } - return (0); + up (&port->sem); + return rc; error: --port->open_count; port->active = 0; MOD_DEC_USE_COUNT; - spin_unlock_irqrestore (&port->port_lock, flags); + up (&port->sem); return rc; } @@ -683,19 +683,15 @@ static void keyspan_pda_close(struct usb_serial_port *port, struct file *filp) { struct usb_serial *serial = port->serial; - unsigned long flags; - spin_lock_irqsave (&port->port_lock, flags); + down (&port->sem); --port->open_count; - MOD_DEC_USE_COUNT; if (port->open_count <= 0) { /* the normal serial device seems to always shut off DTR and RTS now */ - spin_unlock_irqrestore (&port->port_lock, flags); if (port->tty->termios->c_cflag & HUPCL) keyspan_pda_set_modem_info(serial, 0); - spin_lock_irqsave (&port->port_lock, flags); /* shutdown our bulk reads and writes */ usb_unlink_urb (port->write_urb); @@ -704,7 +700,8 @@ port->open_count = 0; } - spin_unlock_irqrestore (&port->port_lock, flags); + up (&port->sem); + MOD_DEC_USE_COUNT; } @@ -817,8 +814,7 @@ { usb_serial_register (&keyspan_pda_fake_device); usb_serial_register (&keyspan_pda_device); - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/serial/mct_u232.c linux/drivers/usb/serial/mct_u232.c --- v2.4.5/linux/drivers/usb/serial/mct_u232.c Thu May 24 14:55:51 2001 +++ linux/drivers/usb/serial/mct_u232.c Wed Jun 20 16:52:30 2001 @@ -24,6 +24,9 @@ * Basic tests have been performed with minicom/zmodem transfers and * modem dialing under Linux 2.4.0-test10 (for me it works fine). * + * 30-May-2001 Greg Kroah-Hartman + * switched from using spinlock to a semaphore, which fixes lots of problems. + * * 04-May-2001 Stelian Pop * - Set the maximum bulk output size for Sitecom U232-P25 model to 16 bytes * instead of the device reported 32 (using 32 bytes causes many data @@ -79,7 +82,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.0.0" +#define DRIVER_VERSION "v1.1" #define DRIVER_AUTHOR "Wolfgang Grandegger " #define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver" @@ -391,13 +394,13 @@ static int mct_u232_open (struct usb_serial_port *port, struct file *filp) { - unsigned long flags; struct usb_serial *serial = port->serial; struct mct_u232_private *priv = (struct mct_u232_private *)port->private; + int retval = 0; dbg(__FUNCTION__" port %d", port->number); - spin_lock_irqsave (&port->port_lock, flags); + down (&port->sem); ++port->open_count; MOD_INC_USE_COUNT; @@ -443,16 +446,21 @@ } port->read_urb->dev = port->serial->dev; - if (usb_submit_urb(port->read_urb)) + retval = usb_submit_urb(port->read_urb); + if (retval) { err("usb_submit_urb(read bulk) failed"); + goto exit; + } port->interrupt_in_urb->dev = port->serial->dev; - if (usb_submit_urb(port->interrupt_in_urb)) + retval = usb_submit_urb(port->interrupt_in_urb); + if (retval) err(" usb_submit_urb(read int) failed"); } - spin_unlock_irqrestore (&port->port_lock, flags); +exit: + up (&port->sem); return 0; } /* mct_u232_open */ @@ -460,14 +468,11 @@ static void mct_u232_close (struct usb_serial_port *port, struct file *filp) { - unsigned long flags; - dbg(__FUNCTION__" port %d", port->number); - spin_lock_irqsave (&port->port_lock, flags); + down (&port->sem); --port->open_count; - MOD_DEC_USE_COUNT; if (port->open_count <= 0) { /* shutdown our bulk reads and writes */ @@ -478,8 +483,8 @@ port->active = 0; } - spin_unlock_irqrestore (&port->port_lock, flags); - + up (&port->sem); + MOD_DEC_USE_COUNT; } /* mct_u232_close */ @@ -490,7 +495,6 @@ const unsigned char *buf, int count) { struct usb_serial *serial = port->serial; - unsigned long flags; int result, bytes_sent, size; dbg(__FUNCTION__ " - port %d", port->number); @@ -513,7 +517,7 @@ bytes_sent = 0; while (count > 0) { - spin_lock_irqsave (&port->port_lock, flags); + down (&port->sem); size = (count > port->bulk_out_size) ? port->bulk_out_size : count; @@ -541,11 +545,11 @@ if (result) { err(__FUNCTION__ " - failed submitting write urb, error %d", result); - spin_unlock_irqrestore (&port->port_lock, flags); - return bytes_sent; + up (&port->sem); + return result; } - spin_unlock_irqrestore (&port->port_lock, flags); + up (&port->sem); bytes_sent += size; if (write_blocking) @@ -870,8 +874,7 @@ usb_serial_register (&mct_u232_device); usb_serial_register (&mct_u232_sitecom_device); usb_serial_register (&mct_u232_du_h3sp_device); - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/serial/omninet.c linux/drivers/usb/serial/omninet.c --- v2.4.5/linux/drivers/usb/serial/omninet.c Mon May 21 15:02:06 2001 +++ linux/drivers/usb/serial/omninet.c Wed Jun 20 16:52:30 2001 @@ -10,6 +10,9 @@ * * Please report both successes and troubles to the author at omninet@kroah.com * + * (05/30/2001) gkh + * switched from using spinlock to a semaphore, which fixes lots of problems. + * * (04/08/2001) gb * Identify version on module load. * @@ -60,7 +63,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.0.0" +#define DRIVER_VERSION "v1.1" #define DRIVER_AUTHOR "Anonymous" #define DRIVER_DESC "USB ZyXEL omni.net LCD PLUS Driver" @@ -145,8 +148,7 @@ struct usb_serial *serial; struct usb_serial_port *wport; struct omninet_data *od; - unsigned long flags; - int result; + int result = 0; if (port_paranoia_check (port, __FUNCTION__)) return -ENODEV; @@ -157,7 +159,7 @@ if (!serial) return -ENODEV; - spin_lock_irqsave (&port->port_lock, flags); + down (&port->sem); MOD_INC_USE_COUNT; ++port->open_count; @@ -170,7 +172,7 @@ err(__FUNCTION__"- kmalloc(%Zd) failed.", sizeof(struct omninet_data)); --port->open_count; port->active = 0; - spin_unlock_irqrestore (&port->port_lock, flags); + up (&port->sem); MOD_DEC_USE_COUNT; return -ENOMEM; } @@ -189,9 +191,9 @@ err(__FUNCTION__ " - failed submitting read urb, error %d", result); } - spin_unlock_irqrestore (&port->port_lock, flags); + up (&port->sem); - return (0); + return result; } static void omninet_close (struct usb_serial_port *port, struct file * filp) @@ -199,7 +201,6 @@ struct usb_serial *serial; struct usb_serial_port *wport; struct omninet_data *od; - unsigned long flags; if (port_paranoia_check (port, __FUNCTION__)) return; @@ -210,10 +211,9 @@ if (!serial) return; - spin_lock_irqsave (&port->port_lock, flags); + down (&port->sem); --port->open_count; - MOD_DEC_USE_COUNT; if (port->open_count <= 0) { od = (struct omninet_data *)port->private; @@ -228,7 +228,8 @@ kfree(od); } - spin_unlock_irqrestore (&port->port_lock, flags); + up (&port->sem); + MOD_DEC_USE_COUNT; } @@ -296,7 +297,6 @@ struct omninet_data *od = (struct omninet_data *) port->private; struct omninet_header *header = (struct omninet_header *) wport->write_urb->transfer_buffer; - unsigned long flags; int result; // dbg("omninet_write port %d", port->number); @@ -310,12 +310,13 @@ return (0); } - spin_lock_irqsave (&port->port_lock, flags); - count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count; if (from_user) { - copy_from_user(wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET, buf, count); + if (copy_from_user(wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET, buf, count) != 0) { + result = -EFAULT; + goto exit; + } } else { memcpy (wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET, buf, count); @@ -333,16 +334,13 @@ wport->write_urb->dev = serial->dev; result = usb_submit_urb(wport->write_urb); - if (result) { + if (result) err(__FUNCTION__ " - failed submitting write urb, error %d", result); - spin_unlock_irqrestore (&port->port_lock, flags); - return 0; - } - -// dbg("omninet_write returns %d", count); + else + result = count; - spin_unlock_irqrestore (&port->port_lock, flags); - return (count); +exit: + return result; } @@ -406,8 +404,7 @@ static int __init omninet_init (void) { usb_serial_register (&zyxel_omninet_device); - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/serial/pl2303.c linux/drivers/usb/serial/pl2303.c --- v2.4.5/linux/drivers/usb/serial/pl2303.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/serial/pl2303.c Wed Jun 27 13:59:32 2001 @@ -0,0 +1,844 @@ +/* + * Prolific PL2303 USB to serial adaptor driver + * + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * + * Original driver for 2.2.x by anonymous + * + * 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. + * + * See Documentation/usb/usb-serial.txt for more information on using this driver + * + * 2001_Jun_06 gkh + * finished porting to 2.4 format. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_USB_SERIAL_DEBUG + static int debug = 1; +#else + static int debug; +#endif + +#include "usb-serial.h" +#include "pl2303.h" + +/* + * Version Information + */ +#define DRIVER_VERSION "v0.5" +#define DRIVER_DESC "Prolific PL2303 USB to serial adaptor driver" + + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + + +#define PL2303_LOCK(port,flags) \ + do { \ + spin_lock_irqsave(&((struct pl2303_private *)(port->private))->lock, flags); \ + } while (0) + +#define PL2303_UNLOCK(port,flags) \ + do { \ + spin_unlock_irqrestore(&((struct pl2303_private *)(port->private))->lock, flags); \ + } while (0) + + + +static __devinitdata struct usb_device_id id_table [] = { + { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) }, + { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, id_table); + +struct pl2303_private { + spinlock_t lock; + unsigned char *xmit_buf; + int xmit_head; + int xmit_tail; + int xmit_cnt; +}; + +/* function prototypes for a PL2303 serial converter */ +static int pl2303_startup (struct usb_serial *serial); +static int pl2303_open (struct usb_serial_port *port, struct file *filp); +static void pl2303_close (struct usb_serial_port *port, struct file *filp); +static void pl2303_set_termios (struct usb_serial_port *port, + struct termios *old); +static int pl2303_ioctl (struct usb_serial_port *port, struct file *file, + unsigned int cmd, unsigned long arg); +static void pl2303_throttle (struct usb_serial_port *port); +static void pl2303_unthrottle (struct usb_serial_port *port); +static void pl2303_read_int_callback (struct urb *urb); +static void pl2303_read_bulk_callback (struct urb *urb); +static void pl2303_write_bulk_callback (struct urb *urb); +static int pl2303_write (struct usb_serial_port *port, int from_user, + const unsigned char *buf, int count); +static int pl2303_write_room(struct usb_serial_port *port); +static int pl2303_chars_in_buffer(struct usb_serial_port *port); +static void pl2303_break_ctl(struct usb_serial_port *port,int break_state); +static void start_xmit (struct usb_serial_port *port); + + +/* All of the device info needed for the PL2303 SIO serial converter */ +static struct usb_serial_device_type pl2303_device = { + name: "PL-2303", + id_table: id_table, + needs_interrupt_in: DONT_CARE, /* this device must have an interrupt in endpoint */ + needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */ + needs_bulk_out: MUST_HAVE, /* this device must have a bulk out endpoint */ + num_interrupt_in: NUM_DONT_CARE, + num_bulk_in: 1, + num_bulk_out: 1, + num_ports: 1, + open: pl2303_open, + close: pl2303_close, + throttle: pl2303_throttle, + unthrottle: pl2303_unthrottle, + write: pl2303_write, + ioctl: pl2303_ioctl, + write_room: pl2303_write_room, + chars_in_buffer: pl2303_chars_in_buffer, + break_ctl: pl2303_break_ctl, + set_termios: pl2303_set_termios, + read_bulk_callback: pl2303_read_bulk_callback, + read_int_callback: pl2303_read_int_callback, + write_bulk_callback: pl2303_write_bulk_callback, + startup: pl2303_startup, +}; + + +#define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */ + +static unsigned char *tmp_buf; +static DECLARE_MUTEX (tmp_buf_sem); + + + +static int +pl2303_write (struct usb_serial_port *port, int from_user, + const unsigned char *buf, int count) +{ /* pl2303_write */ + struct pl2303_private *info = (struct pl2303_private *)port->private; + unsigned long flags; + int c,ret=0; + struct tty_struct *tty=port->tty; + + dbg ("pl2303_write port %d, %d bytes", port->number, count); + + if (!info) { + return -ENODEV; + } + + if (!tty || !info->xmit_buf || !tmp_buf) { + return 0; + } + + + PL2303_LOCK(port,flags); + + + if (from_user) { + down(&tmp_buf_sem); + while (1) { + c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) + break; + + c -= copy_from_user(tmp_buf, buf, c); + if (!c) { + if (!ret) { + ret = -EFAULT; + } + break; + } + c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); + info->xmit_head = ((info->xmit_head + c) & (SERIAL_XMIT_SIZE-1)); + info->xmit_cnt += c; + buf += c; + count -= c; + ret += c; + } + up(&tmp_buf_sem); + } else { + while (1) { + c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) { + break; + } + memcpy(info->xmit_buf + info->xmit_head, buf, c); + info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); + info->xmit_cnt += c; + buf += c; + count -= c; + ret += c; + } + } + PL2303_UNLOCK(port, flags); + + if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) { + start_xmit(port); + } + return ret; +} + +static int pl2303_write_room(struct usb_serial_port *port) +{ + struct pl2303_private *info = (struct pl2303_private *)port->private; + int ret; + + if (!info) + return 0; + + ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; + if (ret < 0) + ret = 0; + return ret; +} + +static int pl2303_chars_in_buffer(struct usb_serial_port *port) +{ + struct pl2303_private *info = (struct pl2303_private *)port->private; + + if (!info) + return 0; + + return info->xmit_cnt; +} + +static void pl2303_throttle(struct usb_serial_port *port) +{ +#if 0 + //struct usb_serial *serial = port->serial; + struct tty_struct *tty=port->tty; + unsigned long flags; + + + char buf[64]; + + dbg("throttle %s: %d....", tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty)); + +//FIXME FIXME FIXME + if (I_IXOFF(tty)) + rs_send_xchar(tty, STOP_CHAR(tty)); + + PL2303_LOCK(port,flags); + //Should remove read request if one is present + PL2303_UNLOCK(port,flags); +#endif +} + +static void pl2303_unthrottle(struct usb_serial_port *port) +{ +#if 0 + //struct usb_serial *serial = port->serial; + struct tty_struct *tty=port->tty; + unsigned long flags; + + + char buf[64]; + + dbg("unthrottle %s: %d....", tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty)); + + //FIXME FIXME FIXME FIXME FIXME + if (I_IXOFF(tty)) { + if (info->x_char) + info->x_char = 0; + else + rs_send_xchar(tty, START_CHAR(tty)); + } + + PL2303_LOCK(port,flags); + //Should add read request if one is not present + PL2303_UNLOCK(fport,flags); +#endif +} + + +static void +pl2303_set_termios (struct usb_serial_port *port, struct termios *old_termios) +{ /* pl2303_set_termios */ + struct usb_serial *serial = port->serial; + unsigned int cflag = port->tty->termios->c_cflag; + unsigned char buf[7] = { 0, 0, 0, 0, 0, 0, 0}; + int baud; + int i; + + + dbg ("pl2303_set_termios port %d", port->number); + + + i = usb_control_msg (serial->dev, usb_rcvctrlpipe (serial->dev, 0), + 0x21, 0xa1, 0, 0, buf, 7, 100); + + dbg ("0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x", i, + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); + + + i = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0), + 1, 0x40, 0, 1, NULL, 0, 100); + + dbg ("0x40:1:0:1 %d", i); + + + + if (cflag & CSIZE) { + switch (cflag & CSIZE) { + case CS6: + buf[6] = 6; + dbg ("Setting CS6"); + break; + case CS7: + buf[6] = 7; + dbg ("Setting CS7"); + break; + case CS8: + buf[6] = 8; + dbg ("Setting CS8"); + break; + default: + err ("CSIZE was set but not CS6-CS8"); + } + } + + baud = 0; + switch (cflag & CBAUD) { + case B0: + err ("Can't do B0 yet"); //FIXME + break; + case B300: + baud = 300; + break; + case B600: + baud = 600; + break; + case B1200: + baud = 1200; + break; + case B2400: + baud = 2400; + break; + case B4800: + baud = 4800; + break; + case B9600: + baud = 9600; + break; + case B19200: + baud = 19200; + break; + case B38400: + baud = 38400; + break; + case B57600: + baud = 57600; + break; + case B115200: + baud = 115200; + break; + default: + dbg ("pl2303 driver does not support the baudrate requested (fix it)"); + break; + } + + if (baud) { + buf[0] = baud & 0xff; + buf[1] = (baud >> 8) & 0xff; + buf[2] = (baud >> 16) & 0xff; + buf[3] = (baud >> 24) & 0xff; + } + + + /* For reference buf[4]=1 is 1.5 stop bits */ + + if (cflag & CSTOPB) { + buf[4] = 2; + } + + + if (cflag & PARENB) { + /* For reference buf[5]=3 is mark parity */ + /* For reference buf[5]=4 is space parity */ + if (cflag & PARODD) { + buf[5] = 1; + } else { + buf[5] = 2; + } + } + + i = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0), + 0x20, 0x21, 0, 0, buf, 7, 100); + + dbg ("0x21:0x20:0:0 %d", i); + + i = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0), + 0x22, 0x21, 1, 0, NULL, 0, 100); + + dbg ("0x21:0x22:1:0 %d", i); + + i = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0), + 0x22, 0x21, 3, 0, NULL, 0, 100); + + dbg ("0x21:0x22:3:0 %d", i); + + buf[0] = buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0; + + i = usb_control_msg (serial->dev, usb_rcvctrlpipe (serial->dev, 0), + 0x21, 0xa1, 0, 0, buf, 7, 100); + + dbg ("0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x", i, + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); + + if (cflag & CRTSCTS) { + + i = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0), + 0x01, 0x40, 0x0, 0x41, NULL, 0, 100); + + dbg ("0x40:0x1:0x0:0x41 %d", i); + + } + + + return; +} + + +static int +pl2303_open (struct usb_serial_port *port, struct file *filp) +{ /* pl2303_open */ + struct termios tmp_termios; + struct usb_serial *serial = port->serial; + unsigned char buf[10]; + int i; + + dbg ("pl2303_open port %d", port->number); + + port->active++; + +#define FISH(a,b,c,d) \ + i=usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev,0), \ + b, a,c , d, buf, 1, 100); \ + dbg("0x%x:0x%x:0x%x:0x%x %d - %x",a,b,c,d,i,buf[0]); + +#define SOUP(a,b,c,d) \ + i=usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev,0), \ + b, a,c , d, NULL, 0, 100); \ + dbg("0x%x:0x%x:0x%x:0x%x %d",a,b,c,d,i); + + + FISH (0xc0, 1, 0x8484, 0); + SOUP (0x40, 1, 0x0404, 0); + FISH (0xc0, 1, 0x8484, 0); + FISH (0xc0, 1, 0x8383, 0); + FISH (0xc0, 1, 0x8484, 0); + SOUP (0x40, 1, 0x0404, 1); + FISH (0xc0, 1, 0x8484, 0); + FISH (0xc0, 1, 0x8383, 0); + SOUP (0x40, 1, 0, 1); + SOUP (0x40, 1, 1, 0xc0); + SOUP (0x40, 1, 2, 4); + + /* Setup termios */ + + if (port->active == 1) { + *(port->tty->termios) = tty_std_termios; + port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + } + + + pl2303_set_termios (port, &tmp_termios); + + //FIXME: need to assert RTS and DTR if CRTSCTS off + + + if (port->active == 1) { + struct pl2303_private *info; + unsigned long flags,page; + int i; + + info = (struct pl2303_private *)kmalloc (sizeof(struct pl2303_private), GFP_KERNEL); + if (info == NULL) { + err(__FUNCTION__ " - out of memory"); + pl2303_close (port, NULL); + return -ENOMEM; + } + spin_lock_init(&info->lock); + port->private = info; + + + page = get_free_page(GFP_KERNEL); + if (!page) { + pl2303_close (port, NULL); + return -ENOMEM; + } + + PL2303_LOCK(port,flags); + + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + + if (tmp_buf) + free_page(page); + else + tmp_buf = (unsigned char *) page; + + PL2303_UNLOCK(port,flags); + + page = get_free_page(GFP_KERNEL); + if (!page) { + pl2303_close (port, NULL); + return -ENOMEM; + } + + PL2303_LOCK(port,flags); + + if (info->xmit_buf) + free_page(page); + else + info->xmit_buf=(unsigned char *) page; + + PL2303_UNLOCK(port,flags); + + + if ((i = usb_submit_urb (port->read_urb))) { + err ("usb_submit_urb(read bulk 1) failed"); + dbg ("i=%d", i); + pl2303_close (port, NULL); + return -EPROTO; + + } + + if ((i = usb_submit_urb (port->interrupt_in_urb))) { + err ("usb_submit_urb(interrupt ink) failed"); + dbg ("i=%d", i); + pl2303_close (port, NULL); + + return -EPROTO; + } + } + + return(0); +} /* pl2303_open */ + + +static void +pl2303_close (struct usb_serial_port *port, struct file *filp) +{ /* pl2303_close */ + struct pl2303_private *info; + unsigned int c_cflag = port->tty->termios->c_cflag; + unsigned long flags; + + dbg ("pl2303_close port %d", port->number); + + /* shutdown our bulk reads and writes */ + if (port->active == 1) { + + if (c_cflag & HUPCL) { + //FIXME: Do drop DTR + //FIXME: Do drop RTS + } + + usb_unlink_urb (port->write_urb); + usb_unlink_urb (port->read_urb); + usb_unlink_urb (port->interrupt_in_urb); + + info = (struct pl2303_private *)port->private; + if (info) { + PL2303_LOCK(port,flags); + if (info->xmit_buf) { + unsigned char * temp; + temp = info->xmit_buf; + info->xmit_buf = 0; + free_page((unsigned long) temp); + } + PL2303_UNLOCK(port,flags); + } + + //FIXME: tmp_buf memory leak + + + } + port->active--; +} /* pl2303_close */ + + +/* do some startup allocations not currently performed by usb_serial_probe() */ +static int +pl2303_startup (struct usb_serial *serial) +{ + return(0); +} + + +static int +pl2303_ioctl (struct usb_serial_port *port, struct file *file, + unsigned int cmd, unsigned long arg) +{ +// struct usb_serial *serial = port->serial; +// __u16 urb_value=0; /* Will hold the new flags */ +// char buf[1]; +// int ret, mask; + + + dbg ("pl2303_sio ioctl 0x%04x", cmd); + + /* Based on code from acm.c and others */ + switch (cmd) { + + case TIOCMGET: + dbg ("TIOCMGET"); + + + return put_user (0, (unsigned long *) arg); + break; + case TIOCMBIS: + case TIOCMBIC: + case TIOCMSET: + return 0; + + default: + /* This is not an error - turns out the higher layers will do + * some ioctls itself (see comment above) + */ + dbg ("pl2303_sio ioctl arg not supported - it was 0x%04x", cmd); + return(-ENOIOCTLCMD); + break; + } + dbg ("pl2303_ioctl returning 0"); + + return 0; +} /* pl2303_ioctl */ + + +static void pl2303_break_ctl(struct usb_serial_port *port,int break_state) +{ +//FIXME +} + + +static void +pl2303_read_int_callback (struct urb *urb) +{ + struct usb_serial_port *port = (struct usb_serial_port *) urb->context; + struct usb_serial *serial = get_usb_serial (port, "pl2303_read_int_callback"); + //unsigned char *data = urb->transfer_buffer; + //int i; + +//ints auto restart... + + if (!serial) { + return; + } + + if (urb->status) { + urb->status = 0; + return; + } + + +#if 0 +//FIXME need to update state of terminal lines variable + if (urb->actual_length) { + printk (KERN_DEBUG __FILE__ ": INT data read - length = %d, data = ", + urb->actual_length); + for (i = 0; i < urb->actual_length; ++i) { + printk ("%.2x ", data[i]); + } + printk ("\n"); + } +#endif + + return; +} + +static void +pl2303_read_bulk_callback (struct urb *urb) +{ + struct usb_serial_port *port = (struct usb_serial_port *) urb->context; + struct usb_serial *serial = get_usb_serial (port, "pl2303_read_bulk_callback"); + struct tty_struct *tty; + unsigned char *data = urb->transfer_buffer; + int i; + + if (!serial) { + return; + } + +// PL2303 mysteriously fails with -EPROTO reschedule the read + if (urb->status) { + urb->status = 0; + if (usb_submit_urb (urb)) + dbg ("failed resubmitting read bulk urb"); + return; + } + + if (debug) { + if (urb->actual_length) { + printk (KERN_DEBUG __FILE__ ": BULK data read - length = %d, data = ", + urb->actual_length); + for (i = 0; i < urb->actual_length; ++i) { + printk ("%.2x ", data[i]); + } + printk ("\n"); + } + } + + tty = port->tty; + if (urb->actual_length) { + for (i = 0; i < urb->actual_length; ++i) { + if (tty->flip.count >= TTY_FLIPBUF_SIZE) { + dbg ("ARGH ------------ Flip buffer overrun..."); + + break; + } + tty_insert_flip_char (tty, data[i], 0); + } + tty_flip_buffer_push (tty); + } + + + /* Schedule the next read*/ + if (usb_submit_urb (urb)) + dbg ("failed submitting read bulk urb"); + + return; +} + + + +static void +pl2303_write_bulk_callback (struct urb *urb) +{ + struct usb_serial_port *port = (struct usb_serial_port *) urb->context; + struct usb_serial *serial; + struct tty_struct *tty = port->tty; + + dbg ("pl2303_write_bulk_callback"); + + + if (port_paranoia_check (port, "pl2303_write_bulk_callback")) { + return; + } + + serial = port->serial; + if (serial_paranoia_check (serial, "pl2303_write_bulk_callback")) { + return; + } + + + if (urb->status) { + dbg ("Overflow in write"); + dbg ("nonzero write bulk status received: %d", urb->status); + //need to resubmit frame; + + port->write_urb->transfer_buffer_length = 1; + + //Resubmit ourselves + + if (usb_submit_urb (port->write_urb)) + err ("usb_submit_urb(write bulk) failed"); + + return; + } + + wake_up_interruptible (&port->write_wait); + + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup) (tty); + + wake_up_interruptible (&tty->write_wait); + + start_xmit(port); + + return; +} + + + +static void +start_xmit (struct usb_serial_port *port) +{ + struct usb_serial *serial; + struct pl2303_private *info; + unsigned long flags; + + serial = port->serial; + info = (struct pl2303_private *)port->private; + + if (info) { + PL2303_LOCK(port,flags); + + if (port->write_urb->status != -EINPROGRESS) { + if (info->xmit_tail != info->xmit_head) { + + memcpy (port->write_urb->transfer_buffer, &info->xmit_buf[info->xmit_tail],1); + info->xmit_cnt--; + info->xmit_tail = (info->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1); + + + port->write_urb->transfer_buffer_length = 1; + + + if (usb_submit_urb (port->write_urb)) + err ("usb_submit_urb(write bulk) failed"); + + + } + } + + PL2303_UNLOCK(port,flags); + } +} + + +static int __init pl2303_init (void) +{ + usb_serial_register (&pl2303_device); + info(DRIVER_VERSION " : " DRIVER_DESC); + return 0; +} + + +static void __exit pl2303_exit (void) +{ + usb_serial_deregister (&pl2303_device); +} + + +module_init(pl2303_init); +module_exit(pl2303_exit); + +MODULE_DESCRIPTION(DRIVER_DESC); + +MODULE_PARM(debug, "i"); +MODULE_PARM_DESC(debug, "Debug enabled or not"); + diff -u --recursive --new-file v2.4.5/linux/drivers/usb/serial/pl2303.h linux/drivers/usb/serial/pl2303.h --- v2.4.5/linux/drivers/usb/serial/pl2303.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/serial/pl2303.h Wed Jun 20 16:52:30 2001 @@ -0,0 +1,15 @@ +/* + * Prolific PL2303 USB to serial adaptor driver header file + * + * 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. + * + */ +#define PL2303_VENDOR_ID 0x067b +#define PL2303_PRODUCT_ID 0x2303 + +#define ATEN_VENDOR_ID 0x0557 +#define ATEN_PRODUCT_ID 0x2008 + diff -u --recursive --new-file v2.4.5/linux/drivers/usb/serial/usb-serial.h linux/drivers/usb/serial/usb-serial.h --- v2.4.5/linux/drivers/usb/serial/usb-serial.h Fri Apr 6 15:51:52 2001 +++ linux/drivers/usb/serial/usb-serial.h Wed Jun 20 16:52:30 2001 @@ -1,7 +1,7 @@ /* * USB Serial Converter driver * - * Copyright (C) 1999, 2000 + * Copyright (C) 1999 - 2001 * Greg Kroah-Hartman (greg@kroah.com) * * This program is free software; you can redistribute it and/or modify @@ -11,6 +11,9 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (05/30/2001) gkh + * added sem to port structure and removed port_lock + * * (10/05/2000) gkh * Added interrupt_in_endpointAddress and bulk_in_endpointAddress to help * fix bug with urb->dev not being set properly, now that the usb core @@ -77,7 +80,7 @@ struct tq_struct tqueue; /* task queue for line discipline waking up */ int open_count; /* number of times this port has been opened */ - spinlock_t port_lock; + struct semaphore sem; /* locks this structure */ void * private; /* data private to the specific port */ }; diff -u --recursive --new-file v2.4.5/linux/drivers/usb/serial/usbserial.c linux/drivers/usb/serial/usbserial.c --- v2.4.5/linux/drivers/usb/serial/usbserial.c Mon May 21 15:02:06 2001 +++ linux/drivers/usb/serial/usbserial.c Wed Jun 20 16:52:30 2001 @@ -1,7 +1,7 @@ /* * USB Serial Converter driver * - * Copyright (C) 1999, 2000 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 1999 - 2001 Greg Kroah-Hartman (greg@kroah.com) * Copyright (c) 2000 Peter Berger (pberger@brimson.com) * Copyright (c) 2000 Al Borchers (borchers@steinerpoint.com) * @@ -15,6 +15,13 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (06/06/2001) gkh + * added evil hack that is needed for the prolific pl2303 device due to the + * crazy way its endpoints are set up. + * + * (05/30/2001) gkh + * switched from using spinlock to a semaphore, which fixes lots of problems. + * * (04/08/2001) gb * Identify version on module load. * @@ -284,13 +291,14 @@ #endif #include "usb-serial.h" +#include "pl2303.h" /* * Version Information */ -#define DRIVER_VERSION "v1.0.0" +#define DRIVER_VERSION "v1.2" #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux-usb/" -#define DRIVER_DESC "USB Serial Driver" +#define DRIVER_DESC "USB Serial Driver core" #define MAX(a,b) (((a)>(b))?(a):(b)) @@ -735,8 +743,7 @@ static int generic_open (struct usb_serial_port *port, struct file *filp) { struct usb_serial *serial = port->serial; - unsigned long flags; - int result; + int result = 0; if (port_paranoia_check (port, __FUNCTION__)) return -ENODEV; @@ -745,7 +752,7 @@ dbg(__FUNCTION__ " - port %d", port->number); - spin_lock_irqsave (&port->port_lock, flags); + down (&port->sem); ++port->open_count; @@ -773,20 +780,19 @@ } } - spin_unlock_irqrestore (&port->port_lock, flags); + up (&port->sem); - return 0; + return result; } static void generic_close (struct usb_serial_port *port, struct file * filp) { struct usb_serial *serial = port->serial; - unsigned long flags; dbg(__FUNCTION__ " - port %d", port->number); - spin_lock_irqsave (&port->port_lock, flags); + down (&port->sem); --port->open_count; @@ -801,7 +807,7 @@ port->open_count = 0; } - spin_unlock_irqrestore (&port->port_lock, flags); + up (&port->sem); MOD_DEC_USE_COUNT; } @@ -809,7 +815,6 @@ static int generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) { struct usb_serial *serial = port->serial; - unsigned long flags; int result; dbg(__FUNCTION__ " - port %d", port->number); @@ -826,7 +831,6 @@ return (0); } - spin_lock_irqsave (&port->port_lock, flags); count = (count > port->bulk_out_size) ? port->bulk_out_size : count; if (from_user) { @@ -849,14 +853,12 @@ /* send the data out the bulk port */ result = usb_submit_urb(port->write_urb); - if (result) { + if (result) err(__FUNCTION__ " - failed submitting write urb, error %d", result); - spin_unlock_irqrestore (&port->port_lock, flags); - return 0; - } + else + result = count; - spin_unlock_irqrestore (&port->port_lock, flags); - return (count); + return result; } /* no bulk out, so return 0 bytes written */ @@ -871,9 +873,10 @@ dbg(__FUNCTION__ " - port %d", port->number); - if (serial->num_bulk_out) + if (serial->num_bulk_out) { if (port->write_urb->status != -EINPROGRESS) room = port->bulk_out_size; + } dbg(__FUNCTION__ " - returns %d", room); return (room); @@ -887,9 +890,10 @@ dbg(__FUNCTION__ " - port %d", port->number); - if (serial->num_bulk_out) + if (serial->num_bulk_out) { if (port->write_urb->status == -EINPROGRESS) chars = port->write_urb->transfer_buffer_length; + } dbg (__FUNCTION__ " - returns %d", chars); return (chars); @@ -1091,6 +1095,33 @@ } } +#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE) + /* BEGIN HORRIBLE HACK FOR PL2303 */ + /* this is needed due to the looney way its endpoints are set up */ + if (ifnum == 1) { + if (((dev->descriptor.idVendor == PL2303_VENDOR_ID) && + (dev->descriptor.idProduct == PL2303_PRODUCT_ID)) || + ((dev->descriptor.idVendor == ATEN_VENDOR_ID) && + (dev->descriptor.idProduct == ATEN_PRODUCT_ID))) { + /* check out the endpoints of the other interface*/ + interface = &dev->actconfig->interface[ifnum ^ 1]; + iface_desc = &interface->altsetting[0]; + for (i = 0; i < iface_desc->bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i]; + if ((endpoint->bEndpointAddress & 0x80) && + ((endpoint->bmAttributes & 3) == 0x03)) { + /* we found a interrupt in endpoint */ + dbg("found interrupt in for Prolific device on separate interface"); + interrupt_pipe = HAS; + interrupt_in_endpoint[num_interrupt_in] = endpoint; + ++num_interrupt_in; + } + } + } + } + /* END HORRIBLE HACK FOR PL2303 */ +#endif + /* verify that we found all of the endpoints that we need */ if (!((interrupt_pipe & type->needs_interrupt_in) && (bulk_in_pipe & type->needs_bulk_in) && @@ -1222,7 +1253,7 @@ port->magic = USB_SERIAL_PORT_MAGIC; port->tqueue.routine = port_softint; port->tqueue.data = port; - spin_lock_init (&port->port_lock); + init_MUTEX (&port->sem); } /* initialize the devfs nodes for this device and let the user know what ports we are bound to */ @@ -1395,8 +1426,7 @@ return -1; } - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/serial/visor.c linux/drivers/usb/serial/visor.c --- v2.4.5/linux/drivers/usb/serial/visor.c Mon May 21 15:02:06 2001 +++ linux/drivers/usb/serial/visor.c Wed Jun 20 16:52:30 2001 @@ -1,7 +1,7 @@ /* * USB HandSpring Visor driver * - * Copyright (C) 1999, 2000 + * Copyright (C) 1999 - 2001 * Greg Kroah-Hartman (greg@kroah.com) * * This program is free software; you can redistribute it and/or modify @@ -11,6 +11,12 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (05/30/2001) gkh + * switched from using spinlock to a semaphore, which fixes lots of problems. + * + * (05/28/2000) gkh + * Added initial support for the Palm m500 and Palm m505 devices. + * * (04/08/2001) gb * Identify version on module load. * @@ -109,7 +115,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.0.0" +#define DRIVER_VERSION "v1.2" #define DRIVER_AUTHOR "Greg Kroah-Hartman " #define DRIVER_DESC "USB HandSpring Visor driver" @@ -131,8 +137,26 @@ static void visor_read_bulk_callback (struct urb *urb); +static __devinitdata struct usb_device_id visor_id_table [] = { + { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) }, + { } /* Terminating entry */ +}; + +static __devinitdata struct usb_device_id palm_m500_id_table [] = { + { USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID) }, + { } /* Terminating entry */ +}; + +static __devinitdata struct usb_device_id palm_m505_id_table [] = { + { USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) }, + { } /* Terminating entry */ +}; + + static __devinitdata struct usb_device_id id_table [] = { { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) }, + { USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID) }, + { USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) }, { } /* Terminating entry */ }; @@ -143,7 +167,7 @@ /* All of the device info needed for the Handspring Visor */ struct usb_serial_device_type handspring_device = { name: "Handspring Visor", - id_table: id_table, + id_table: visor_id_table, needs_interrupt_in: MUST_HAVE_NOT, /* this device must not have an interrupt in endpoint */ needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */ needs_bulk_out: MUST_HAVE, /* this device must have a bulk out endpoint */ @@ -166,6 +190,57 @@ read_bulk_callback: visor_read_bulk_callback, }; +/* device info for the Palm M500 */ +struct usb_serial_device_type palm_m500_device = { + name: "Palm M500", + id_table: palm_m500_id_table, + needs_interrupt_in: MUST_HAVE_NOT, /* this device must not have an interrupt in endpoint */ + needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */ + needs_bulk_out: MUST_HAVE, /* this device must have a bulk out endpoint */ + num_interrupt_in: 0, + num_bulk_in: 2, + num_bulk_out: 2, + num_ports: 2, + open: visor_open, + close: visor_close, + throttle: visor_throttle, + unthrottle: visor_unthrottle, + startup: visor_startup, + shutdown: visor_shutdown, + ioctl: visor_ioctl, + set_termios: visor_set_termios, + write: visor_write, + write_room: visor_write_room, + chars_in_buffer: visor_chars_in_buffer, + write_bulk_callback: visor_write_bulk_callback, + read_bulk_callback: visor_read_bulk_callback, +}; + +/* device info for the Palm M505 */ +struct usb_serial_device_type palm_m505_device = { + name: "Palm M505", + id_table: palm_m505_id_table, + needs_interrupt_in: MUST_HAVE_NOT, /* this device must not have an interrupt in endpoint */ + needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */ + needs_bulk_out: MUST_HAVE, /* this device must have a bulk out endpoint */ + num_interrupt_in: 0, + num_bulk_in: 2, + num_bulk_out: 2, + num_ports: 2, + open: visor_open, + close: visor_close, + throttle: visor_throttle, + unthrottle: visor_unthrottle, + startup: visor_startup, + shutdown: visor_shutdown, + ioctl: visor_ioctl, + set_termios: visor_set_termios, + write: visor_write, + write_room: visor_write_room, + chars_in_buffer: visor_chars_in_buffer, + write_bulk_callback: visor_write_bulk_callback, + read_bulk_callback: visor_read_bulk_callback, +}; #define NUM_URBS 24 #define URB_TRANSFER_BUFFER_SIZE 768 @@ -181,15 +256,14 @@ static int visor_open (struct usb_serial_port *port, struct file *filp) { struct usb_serial *serial = port->serial; - unsigned long flags; - int result; + int result = 0; if (port_paranoia_check (port, __FUNCTION__)) return -ENODEV; dbg(__FUNCTION__ " - port %d", port->number); - spin_lock_irqsave (&port->port_lock, flags); + down (&port->sem); ++port->open_count; MOD_INC_USE_COUNT; @@ -214,9 +288,9 @@ err(__FUNCTION__ " - failed submitting read urb, error %d", result); } - spin_unlock_irqrestore (&port->port_lock, flags); + up (&port->sem); - return 0; + return result; } @@ -224,7 +298,6 @@ { struct usb_serial *serial; unsigned char *transfer_buffer; - unsigned long flags; if (port_paranoia_check (port, __FUNCTION__)) return; @@ -235,7 +308,7 @@ if (!serial) return; - spin_lock_irqsave (&port->port_lock, flags); + down (&port->sem); --port->open_count; @@ -256,7 +329,7 @@ port->open_count = 0; } - spin_unlock_irqrestore (&port->port_lock, flags); + up (&port->sem); /* Uncomment the following line if you want to see some statistics in your syslog */ /* info ("Bytes In = %d Bytes Out = %d", bytes_in, bytes_out); */ @@ -338,7 +411,7 @@ dbg(__FUNCTION__ " - port %d", port->number); - spin_lock_irqsave (&port->port_lock, flags); + spin_lock_irqsave (&write_urb_pool_lock, flags); for (i = 0; i < NUM_URBS; ++i) { if (write_urb_pool[i]->status != -EINPROGRESS) { @@ -346,7 +419,7 @@ } } - spin_unlock_irqrestore (&port->port_lock, flags); + spin_unlock_irqrestore (&write_urb_pool_lock, flags); dbg(__FUNCTION__ " - returns %d", room); return (room); @@ -361,7 +434,7 @@ dbg(__FUNCTION__ " - port %d", port->number); - spin_lock_irqsave (&port->port_lock, flags); + spin_lock_irqsave (&write_urb_pool_lock, flags); for (i = 0; i < NUM_URBS; ++i) { if (write_urb_pool[i]->status == -EINPROGRESS) { @@ -369,7 +442,7 @@ } } - spin_unlock_irqrestore (&port->port_lock, flags); + spin_unlock_irqrestore (&write_urb_pool_lock, flags); dbg (__FUNCTION__ " - returns %d", chars); return (chars); @@ -451,15 +524,14 @@ static void visor_throttle (struct usb_serial_port *port) { - unsigned long flags; dbg(__FUNCTION__ " - port %d", port->number); - spin_lock_irqsave (&port->port_lock, flags); + down (&port->sem); usb_unlink_urb (port->read_urb); - spin_unlock_irqrestore (&port->port_lock, flags); + up (&port->sem); return; } @@ -467,19 +539,18 @@ static void visor_unthrottle (struct usb_serial_port *port) { - unsigned long flags; int result; dbg(__FUNCTION__ " - port %d", port->number); - spin_lock_irqsave (&port->port_lock, flags); + down (&port->sem); port->read_urb->dev = port->serial->dev; result = usb_submit_urb(port->read_urb); if (result) err(__FUNCTION__ " - failed submitting read urb, error %d", result); - spin_unlock_irqrestore (&port->port_lock, flags); + up (&port->sem); return; } @@ -496,6 +567,10 @@ return -ENOMEM; } + /* force debugging on for the palm devices for now */ + if (serial->dev->descriptor.idVendor == PALM_VENDOR_ID) + debug = 1; + dbg(__FUNCTION__); dbg(__FUNCTION__ " - Set config to 1"); @@ -537,6 +612,28 @@ } } + if (serial->dev->descriptor.idVendor == PALM_VENDOR_ID) { + /* Palm USB Hack */ + response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), + PALM_GET_SOME_UNKNOWN_INFORMATION, + 0xc2, 0x0000, 0x0000, transfer_buffer, + 0x14, 300); + if (response < 0) { + err(__FUNCTION__ " - error getting first unknown palm command"); + } else { + usb_serial_debug_data (__FILE__, __FUNCTION__, 0x14, transfer_buffer); + } + response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), + PALM_GET_SOME_UNKNOWN_INFORMATION, + 0xc2, 0x0000, 0x0000, transfer_buffer, + 0x14, 300); + if (response < 0) { + err(__FUNCTION__ " - error getting second unknown palm command"); + } else { + usb_serial_debug_data (__FILE__, __FUNCTION__, 0x14, transfer_buffer); + } + } + /* ask for the number of bytes available, but ignore the response as it is broken */ response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_REQUEST_BYTES_AVAILABLE, 0xc2, 0x0000, 0x0005, transfer_buffer, 0x02, 300); @@ -645,6 +742,8 @@ int i; usb_serial_register (&handspring_device); + usb_serial_register (&palm_m500_device); + usb_serial_register (&palm_m505_device); /* create our write urb pool and transfer buffers */ spin_lock_init (&write_urb_pool_lock); @@ -664,8 +763,7 @@ } } - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } @@ -677,6 +775,8 @@ unsigned long flags; usb_serial_deregister (&handspring_device); + usb_serial_deregister (&palm_m500_device); + usb_serial_deregister (&palm_m505_device); spin_lock_irqsave (&write_urb_pool_lock, flags); diff -u --recursive --new-file v2.4.5/linux/drivers/usb/serial/visor.h linux/drivers/usb/serial/visor.h --- v2.4.5/linux/drivers/usb/serial/visor.h Wed Apr 18 11:49:12 2001 +++ linux/drivers/usb/serial/visor.h Mon Jun 11 19:15:27 2001 @@ -1,7 +1,7 @@ /* * USB HandSpring Visor driver * - * Copyright (C) 1999, 2000 + * Copyright (C) 1999 - 2001 * Greg Kroah-Hartman (greg@kroah.com) * * This program is free software; you can redistribute it and/or modify @@ -20,6 +20,10 @@ #define HANDSPRING_VENDOR_ID 0x082d #define HANDSPRING_VISOR_ID 0x0100 +#define PALM_VENDOR_ID 0x0830 +#define PALM_M500_ID 0x0001 +#define PALM_M505_ID 0x0002 + /**************************************************************************** * Handspring Visor Vendor specific request codes (bRequest values) * A big thank you to Handspring for providing the following information. @@ -69,6 +73,13 @@ #define VISOR_FUNCTION_HOTSYNC 0x02 #define VISOR_FUNCTION_CONSOLE 0x03 #define VISOR_FUNCTION_REMOTE_FILE_SYS 0x04 + + +/**************************************************************************** + * PALM_GET_SOME_UNKNOWN_INFORMATION is sent by the host during enumeration to + * get some information from the M series devices, that is currently unknown. + ****************************************************************************/ +#define PALM_GET_SOME_UNKNOWN_INFORMATION 0x04 #endif diff -u --recursive --new-file v2.4.5/linux/drivers/usb/serial/whiteheat.c linux/drivers/usb/serial/whiteheat.c --- v2.4.5/linux/drivers/usb/serial/whiteheat.c Mon May 21 15:02:06 2001 +++ linux/drivers/usb/serial/whiteheat.c Wed Jun 20 16:52:30 2001 @@ -11,6 +11,9 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (05/30/2001) gkh + * switched from using spinlock to a semaphore, which fixes lots of problems. + * * (04/08/2001) gb * Identify version on module load. * @@ -85,7 +88,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.0.0" +#define DRIVER_VERSION "v1.1" #define DRIVER_AUTHOR "Greg Kroah-Hartman " #define DRIVER_DESC "USB ConnectTech WhiteHEAT driver" @@ -251,6 +254,7 @@ struct usb_serial_port *port; int timeout; __u8 *transfer_buffer; + int retval = 0; dbg(__FUNCTION__" - command %d", command); @@ -263,9 +267,10 @@ memcpy (&transfer_buffer[1], data, datasize); port->write_urb->transfer_buffer_length = datasize + 1; port->write_urb->dev = serial->dev; - if (usb_submit_urb (port->write_urb)) { + retval = usb_submit_urb (port->write_urb); + if (retval) { dbg (__FUNCTION__" - submit urb failed"); - return -1; + goto exit; } /* wait for the command to complete */ @@ -276,20 +281,21 @@ if (info->command_finished == FALSE) { dbg (__FUNCTION__ " - command timed out."); - return -1; + retval = -ETIMEDOUT; + goto exit; } if (info->command_finished == WHITEHEAT_CMD_FAILURE) { dbg (__FUNCTION__ " - command failed."); - return -1; + retval = -EIO; + goto exit; } - if (info->command_finished == WHITEHEAT_CMD_COMPLETE) { + if (info->command_finished == WHITEHEAT_CMD_COMPLETE) dbg (__FUNCTION__ " - command completed."); - return 0; - } - return 0; +exit: + return retval; } @@ -298,10 +304,12 @@ struct whiteheat_min_set open_command; struct usb_serial_port *command_port; struct whiteheat_private *info; - int result; + int retval = 0; dbg(__FUNCTION__" - port %d", port->number); + down (&port->sem); + ++port->open_count; MOD_INC_USE_COUNT; @@ -314,7 +322,8 @@ info = (struct whiteheat_private *)kmalloc (sizeof(struct whiteheat_private), GFP_KERNEL); if (info == NULL) { err(__FUNCTION__ " - out of memory"); - return -ENOMEM; + retval = -ENOMEM; + goto error_exit; } init_waitqueue_head(&info->wait_command); @@ -323,27 +332,45 @@ command_port->read_urb->complete = command_port_read_callback; command_port->read_urb->dev = port->serial->dev; command_port->tty = port->tty; /* need this to "fake" our our sanity check macros */ - usb_submit_urb (command_port->read_urb); + retval = usb_submit_urb (command_port->read_urb); + if (retval) { + err(__FUNCTION__ " - failed submitting read urb, error %d", retval); + goto error_exit; + } } /* Start reading from the device */ port->read_urb->dev = port->serial->dev; - result = usb_submit_urb(port->read_urb); - if (result) - err(__FUNCTION__ " - failed submitting read urb, error %d", result); + retval = usb_submit_urb(port->read_urb); + if (retval) { + err(__FUNCTION__ " - failed submitting read urb, error %d", retval); + goto error_exit; + } /* send an open port command */ /* firmware uses 1 based port numbering */ open_command.port = port->number - port->serial->minor + 1; - whiteheat_send_cmd (port->serial, WHITEHEAT_OPEN, (__u8 *)&open_command, sizeof(open_command)); + retval = whiteheat_send_cmd (port->serial, WHITEHEAT_OPEN, (__u8 *)&open_command, sizeof(open_command)); + if (retval) + goto error_exit; /* Need to do device specific setup here (control lines, baud rate, etc.) */ /* FIXME!!! */ } dbg(__FUNCTION__ " - exit"); + up (&port->sem); - return 0; + return retval; + +error_exit: + --port->open_count; + MOD_DEC_USE_COUNT; + + dbg(__FUNCTION__ " - error_exit"); + up (&port->sem); + + return retval; } @@ -353,6 +380,7 @@ dbg(__FUNCTION__ " - port %d", port->number); + down (&port->sem); --port->open_count; if (port->open_count <= 0) { @@ -370,6 +398,7 @@ port->active = 0; } MOD_DEC_USE_COUNT; + up (&port->sem); } @@ -388,18 +417,19 @@ dbg(__FUNCTION__ " -port %d", port->number); + down (&port->sem); /* check that they really want us to change something */ if (old_termios) { if ((cflag == old_termios->c_cflag) && (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) { dbg(__FUNCTION__ " - nothing to change..."); - return; + goto exit; } } if ((!port->tty) || (!port->tty->termios)) { dbg(__FUNCTION__" - no tty structures"); - return; + goto exit; } /* set the port number */ @@ -466,6 +496,8 @@ /* now send the message to the device */ whiteheat_send_cmd (port->serial, WHITEHEAT_SETUP_PORT, (__u8 *)&port_settings, sizeof(port_settings)); +exit: + up (&port->sem); return; } @@ -626,8 +658,7 @@ { usb_serial_register (&whiteheat_fake_device); usb_serial_register (&whiteheat_device); - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/storage/debug.c linux/drivers/usb/storage/debug.c --- v2.4.5/linux/drivers/usb/storage/debug.c Fri Sep 8 16:39:12 2000 +++ linux/drivers/usb/storage/debug.c Tue Jun 12 11:17:17 2001 @@ -302,6 +302,8 @@ case 0x1C00: what="defect list not found"; break; case 0x2400: what="invalid field in CDB"; break; case 0x2703: what="associated write protect"; break; + case 0x2800: what="not ready to ready transition (media change?)"; + break; case 0x2903: what="bus device reset function occurred"; break; case 0x2904: what="device internal reset"; break; case 0x2B00: what="copy can't execute since host can't disconnect"; diff -u --recursive --new-file v2.4.5/linux/drivers/usb/uhci.c linux/drivers/usb/uhci.c --- v2.4.5/linux/drivers/usb/uhci.c Mon May 21 15:02:06 2001 +++ linux/drivers/usb/uhci.c Tue Jun 12 17:03:01 2001 @@ -425,8 +425,7 @@ /* Only go through the hoops if it's actually linked in */ if (list_empty(&qh->list)) { - uhci_free_qh(uhci, qh); - return; + goto list; } qh->urbp = NULL; @@ -444,6 +443,7 @@ spin_unlock_irqrestore(&uhci->frame_list_lock, flags); +list: spin_lock_irqsave(&uhci->qh_remove_list_lock, flags); /* Check to see if the remove list is empty. Set the IOC bit */ @@ -2922,15 +2922,17 @@ } #ifdef CONFIG_PM -static void uhci_pci_suspend(struct pci_dev *dev) +static int uhci_pci_suspend(struct pci_dev *dev, u32 state) { reset_hc((struct uhci *) dev->driver_data); + return 0; } -static void uhci_pci_resume(struct pci_dev *dev) +static int uhci_pci_resume(struct pci_dev *dev) { reset_hc((struct uhci *) dev->driver_data); start_hc((struct uhci *) dev->driver_data); + return 0; } #endif @@ -2990,8 +2992,7 @@ if (retval) goto init_failed; - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; diff -u --recursive --new-file v2.4.5/linux/drivers/usb/usb-ohci.c linux/drivers/usb/usb-ohci.c --- v2.4.5/linux/drivers/usb/usb-ohci.c Tue May 22 13:55:49 2001 +++ linux/drivers/usb/usb-ohci.c Wed Jun 27 13:15:17 2001 @@ -2585,15 +2585,15 @@ /*-------------------------------------------------------------------------*/ -static void -ohci_pci_suspend (struct pci_dev *dev) +static int +ohci_pci_suspend (struct pci_dev *dev, u32 state) { ohci_t *ohci = (ohci_t *) dev->driver_data; 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; + return -EIO; } /* act as if usb suspend can always be used */ @@ -2605,11 +2605,13 @@ ohci->hc_control = OHCI_USB_SUSPEND; writel (ohci->hc_control, &ohci->regs->control); wait_ms (10); + + return 0; } /*-------------------------------------------------------------------------*/ -static void +static int ohci_pci_resume (struct pci_dev *dev) { ohci_t *ohci = (ohci_t *) dev->driver_data; @@ -2620,7 +2622,7 @@ if (atomic_read (&ohci->resume_count) != 1) { err ("concurrent PCI resumes for usb-%s", dev->slot_name); atomic_dec (&ohci->resume_count); - return; + return -EBUSY; } /* did we suspend, or were we powered off? */ @@ -2653,7 +2655,7 @@ if (temp != OHCI_USB_RESUME) { err ("controller usb-%s won't resume", dev->slot_name); ohci->disabled = 1; - return; + return -EIO; } ohci->disabled = 0; @@ -2676,6 +2678,8 @@ /* controller is operational, extra resumes are harmless */ atomic_dec (&ohci->resume_count); + + return 0; } #endif /* CONFIG_PM */ @@ -2774,8 +2778,7 @@ #ifdef CONFIG_PMAC_PBOOK pmu_register_sleep_notifier (&ohci_sleep_notifier); #endif - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return ret; } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/usb-ohci.h linux/drivers/usb/usb-ohci.h --- v2.4.5/linux/drivers/usb/usb-ohci.h Sun May 20 12:11:39 2001 +++ linux/drivers/usb/usb-ohci.h Tue Jun 12 15:53:37 2001 @@ -116,7 +116,7 @@ dma_addr_t td_dma; dma_addr_t data_dma; __u32 unused2[2]; -} __attribute((aligned(16))); +} __attribute((aligned(32))); /* normally 16, iso needs 32 */ typedef struct td td_t; #define OHCI_ED_SKIP (1 << 14) @@ -562,7 +562,7 @@ { ohci->td_cache = pci_pool_create ("ohci_td", ohci->ohci_dev, sizeof (struct td), - 16 /* byte alignment */, + 32 /* byte alignment */, 0 /* no page-crossing issues */, GFP_KERNEL | OHCI_MEM_FLAGS); if (!ohci->td_cache) diff -u --recursive --new-file v2.4.5/linux/drivers/usb/usb-uhci.c linux/drivers/usb/usb-uhci.c --- v2.4.5/linux/drivers/usb/usb-uhci.c Mon May 21 15:02:06 2001 +++ linux/drivers/usb/usb-uhci.c Wed Jun 27 13:15:17 2001 @@ -2897,16 +2897,18 @@ } #ifdef CONFIG_PM -_static void -uhci_pci_suspend (struct pci_dev *dev) +_static int +uhci_pci_suspend (struct pci_dev *dev, u32 state) { reset_hc((uhci_t *) dev->driver_data); + return 0; } -_static void +_static int uhci_pci_resume (struct pci_dev *dev) { start_hc((uhci_t *) dev->driver_data); + return 0; } #endif @@ -3108,8 +3110,7 @@ } #endif - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return retval; } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/usb.c linux/drivers/usb/usb.c --- v2.4.5/linux/drivers/usb/usb.c Sat Apr 28 11:28:09 2001 +++ linux/drivers/usb/usb.c Tue Jun 12 15:53:37 2001 @@ -449,7 +449,7 @@ */ list_del(&bus->bus_list); - usbdevfs_remove_bus(bus); + usbdevfs_remove_bus(bus); clear_bit(bus->busnum, busmap.busmap); @@ -1869,6 +1869,7 @@ { int result; __u16 status; + unsigned char *buffer; int endp=usb_pipeendpoint(pipe)|(usb_pipein(pipe)<<7); /* @@ -1883,9 +1884,19 @@ 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, - &status, sizeof(status), HZ * SET_TIMEOUT); + buffer, sizeof(status), HZ * SET_TIMEOUT); + + memcpy(&status, buffer, sizeof(status)); + kfree(buffer); + if (result < 0) return result; @@ -1970,10 +1981,9 @@ { int result; unsigned int cfgno, length; - unsigned char buffer[8]; + unsigned char *buffer; unsigned char *bigbuffer; - struct usb_config_descriptor *desc = - (struct usb_config_descriptor *)buffer; + struct usb_config_descriptor *desc; if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) { warn("too many configurations"); @@ -2002,6 +2012,13 @@ 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 */ @@ -2052,8 +2069,10 @@ } } + kfree(buffer); return 0; err: + kfree(buffer); dev->descriptor.bNumConfigurations = cfgno; return result; } @@ -2162,7 +2181,7 @@ dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0; err = usb_get_device_descriptor(dev); - if (err < sizeof(dev->descriptor)) { + if (err < (signed)sizeof(dev->descriptor)) { if (err < 0) err("unable to get device descriptor (error=%d)", err); else diff -u --recursive --new-file v2.4.5/linux/drivers/usb/usbkbd.c linux/drivers/usb/usbkbd.c --- v2.4.5/linux/drivers/usb/usbkbd.c Mon May 21 15:02:06 2001 +++ linux/drivers/usb/usbkbd.c Tue Jun 12 15:53:37 2001 @@ -280,8 +280,7 @@ static int __init usb_kbd_init(void) { usb_register(&usb_kbd_driver); - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/usbmouse.c linux/drivers/usb/usbmouse.c --- v2.4.5/linux/drivers/usb/usbmouse.c Mon May 21 15:02:06 2001 +++ linux/drivers/usb/usbmouse.c Tue Jun 12 15:53:37 2001 @@ -194,8 +194,7 @@ static int __init usb_mouse_init(void) { usb_register(&usb_mouse_driver); - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/uss720.c linux/drivers/usb/uss720.c --- v2.4.5/linux/drivers/usb/uss720.c Mon May 21 15:02:06 2001 +++ linux/drivers/usb/uss720.c Tue Jun 12 15:53:37 2001 @@ -659,8 +659,7 @@ if (usb_register(&uss720_driver) < 0) return -1; - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/usb/wacom.c linux/drivers/usb/wacom.c --- v2.4.5/linux/drivers/usb/wacom.c Mon May 21 15:02:06 2001 +++ linux/drivers/usb/wacom.c Tue Jun 12 15:53:37 2001 @@ -415,8 +415,7 @@ static int __init wacom_init(void) { usb_register(&wacom_driver); - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/video/aty128fb.c linux/drivers/video/aty128fb.c --- v2.4.5/linux/drivers/video/aty128fb.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/video/aty128fb.c Mon Jul 2 14:13:40 2001 @@ -111,7 +111,6 @@ }; #endif /* CONFIG_PPC */ -#ifndef MODULE /* default modedb mode */ /* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */ static struct fb_videomode defaultmode __initdata = { @@ -128,7 +127,6 @@ sync: 0, vmode: FB_VMODE_NONINTERLACED }; -#endif /* MODULE */ /* struct to hold chip description information */ struct aty128_chip_info { @@ -213,11 +211,13 @@ static const char *aty128fb_name = "ATY Rage128"; static char fontname[40] __initdata = { 0 }; + static int noaccel __initdata = 0; +static char *font __initdata = NULL; +static char *mode __initdata = NULL; +static int nomtrr __initdata = 0; -#ifndef MODULE static const char *mode_option __initdata = NULL; -#endif #ifdef CONFIG_PPC static int default_vmode __initdata = VMODE_1024_768_60; @@ -274,10 +274,10 @@ struct fb_info fb_info; struct fb_info_aty128 *next; struct aty128_constants constants; /* PLL and others */ - u32 regbase_phys; /* physical mmio */ + unsigned long regbase_phys; /* physical mmio */ void *regbase; /* remapped mmio */ - u32 frame_buffer_phys; /* physical fb memory */ - u32 frame_buffer; /* remaped framebuffer */ + unsigned long frame_buffer_phys; /* physical fb memory */ + void *frame_buffer; /* remaped framebuffer */ u32 vram_size; /* onboard video ram */ int chip_gen; const struct aty128_meminfo *mem; /* onboard mem info */ @@ -528,7 +528,7 @@ } if (reset) /* reset engine?? */ - printk(KERN_DEBUG "aty128fb: PLL write timeout!"); + printk(KERN_DEBUG "aty128fb: PLL write timeout!\n"); } @@ -1380,7 +1380,7 @@ struct fb_fix_screeninfo fix; aty128_encode_fix(&fix, &par, info); - display->screen_base = (char *)info->frame_buffer; + display->screen_base = info->frame_buffer; display->visual = fix.visual; display->type = fix.type; display->type_aux = fix.type_aux; @@ -1605,7 +1605,6 @@ } -#ifndef MODULE int __init aty128fb_setup(char *options) { @@ -1663,7 +1662,6 @@ } return 0; } -#endif /* !MODULE */ /* @@ -1710,10 +1708,7 @@ info->fb_info.blank = &aty128fbcon_blank; info->fb_info.flags = FBINFO_FLAG_DEFAULT; -#ifdef MODULE var = default_var; -#else - memset(&var, 0, sizeof(var)); #ifdef CONFIG_PPC if (_machine == _MACH_Pmac) { if (mode_option) { @@ -1736,7 +1731,6 @@ &defaultmode, 8) == 0) var = default_var; } -#endif /* MODULE */ if (noaccel) var.accel_flags &= ~FB_ACCELF_TEXT; @@ -1833,7 +1827,7 @@ const struct aty128_chip_info *aci) { struct fb_info_aty128 *info = NULL; - u32 fb_addr, reg_addr; + unsigned long fb_addr, reg_addr; int err; #if !defined(CONFIG_PPC) && !defined(__sparc__) char *bios_seg = NULL; @@ -1885,7 +1879,7 @@ /* Virtualize the framebuffer */ info->frame_buffer_phys = fb_addr; - info->frame_buffer = (u32)ioremap(fb_addr, info->vram_size); + info->frame_buffer = ioremap(fb_addr, info->vram_size); if (!info->frame_buffer) { iounmap((void *)info->regbase); @@ -1931,8 +1925,8 @@ return 0; err_out: - iounmap((void *)info->frame_buffer); - iounmap((void *)info->regbase); + iounmap(info->frame_buffer); + iounmap(info->regbase); err_free_info: kfree(info); err_unmap_out: @@ -2598,10 +2592,39 @@ #ifdef MODULE MODULE_AUTHOR("(c)1999-2000 Brad Douglas "); MODULE_DESCRIPTION("FBDev driver for ATI Rage128 / Pro cards"); +MODULE_PARM(noaccel, "i"); +MODULE_PARM_DESC(noaccel, "Disable hardware acceleration (0 or 1=disabled) (default=0)"); +MODULE_PARM(font, "s"); +MODULE_PARM_DESC(font, "Specify one of the compiled-in fonts (default=none)"); +MODULE_PARM(mode, "s"); +MODULE_PARM_DESC(mode, "Specify resolution as \"x[-][@]\" "); +#ifdef CONFIG_MTRR +MODULE_PARM(nomtrr, "i"); +MODULE_PARM_DESC(nomtrr, "Disable MTRR support (0 or 1=disabled) (default=0)"); +#endif int __init init_module(void) { + if (noaccel) { + noaccel = 1; + printk(KERN_INFO "aty128fb: Parameter NOACCEL set\n"); + } + if (font) { + strncpy(fontname, font, sizeof(fontname)-1); + printk(KERN_INFO "aty128fb: Parameter FONT set to %s\n", font); + } + if (mode) { + mode_option = mode; + printk(KERN_INFO "aty128fb: Parameter MODE set to %s\n", mode); + } +#ifdef CONFIG_MTRR + if (nomtrr) { + mtrr = 0; + printk(KERN_INFO "aty128fb: Parameter NOMTRR set\n"); + } +#endif + aty128fb_init(); return 0; } @@ -2622,7 +2645,7 @@ info->vram_size); #endif /* CONFIG_MTRR */ iounmap(info->regbase); - iounmap(&info->frame_buffer); + iounmap(info->frame_buffer); release_mem_region(pci_resource_start(info->pdev, 0), pci_resource_len(info->pdev, 0)); diff -u --recursive --new-file v2.4.5/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c --- v2.4.5/linux/drivers/video/atyfb.c Wed May 16 10:31:23 2001 +++ linux/drivers/video/atyfb.c Mon Jun 11 19:15:27 2001 @@ -3213,7 +3213,7 @@ static void atyfb_save_palette(struct fb_info *fb, int enter) { struct fb_info_aty *info = (struct fb_info_aty *)fb; - int i, tmp, scale; + int i, tmp; for (i = 0; i < 256; i++) { tmp = aty_ld_8(DAC_CNTL, info) & 0xfc; @@ -3225,14 +3225,11 @@ aty_st_8(DAC_CNTL, tmp, info); aty_st_8(DAC_MASK, 0xff, info); - scale = ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID) && - (info->current_par.crtc.bpp == 16)) ? 3 : 0; - writeb(i << scale, &info->aty_cmap_regs->rindex); - + writeb(i, &info->aty_cmap_regs->rindex); atyfb_save.r[enter][i] = readb(&info->aty_cmap_regs->lut); atyfb_save.g[enter][i] = readb(&info->aty_cmap_regs->lut); atyfb_save.b[enter][i] = readb(&info->aty_cmap_regs->lut); - writeb(i << scale, &info->aty_cmap_regs->windex); + writeb(i, &info->aty_cmap_regs->windex); writeb(atyfb_save.r[1-enter][i], &info->aty_cmap_regs->lut); writeb(atyfb_save.g[1-enter][i], &info->aty_cmap_regs->lut); writeb(atyfb_save.b[1-enter][i], &info->aty_cmap_regs->lut); diff -u --recursive --new-file v2.4.5/linux/drivers/video/creatorfb.c linux/drivers/video/creatorfb.c --- v2.4.5/linux/drivers/video/creatorfb.c Sun Mar 25 18:14:20 2001 +++ linux/drivers/video/creatorfb.c Tue Jun 12 11:08:46 2001 @@ -1,4 +1,4 @@ -/* $Id: creatorfb.c,v 1.34 2001/03/16 10:22:02 davem Exp $ +/* $Id: creatorfb.c,v 1.35 2001/06/08 21:48:37 davem Exp $ * creatorfb.c: Creator/Creator3D frame buffer driver * * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz) @@ -69,6 +69,15 @@ #define FFB_DAC_POFF 0x00400000UL #define FFB_PROM_POFF 0x00000000UL #define FFB_EXP_POFF 0x00200000UL +#define FFB_DFB422A_POFF 0x09000000UL +#define FFB_DFB422AD_POFF 0x09800000UL +#define FFB_DFB24B_POFF 0x0a000000UL +#define FFB_DFB422B_POFF 0x0b000000UL +#define FFB_DFB422BD_POFF 0x0b800000UL +#define FFB_SFB16Z_POFF 0x0c800000UL +#define FFB_SFB8Z_POFF 0x0c000000UL +#define FFB_SFB422_POFF 0x0d000000UL +#define FFB_SFB422D_POFF 0x0d800000UL /* Draw operations */ #define FFB_DRAWOP_DOT 0x00 @@ -330,6 +339,15 @@ { FFB_DAC_VOFF, FFB_DAC_POFF, 0x0002000 }, { FFB_PROM_VOFF, FFB_PROM_POFF, 0x0010000 }, { FFB_EXP_VOFF, FFB_EXP_POFF, 0x0002000 }, + { FFB_DFB422A_VOFF, FFB_DFB422A_POFF, 0x0800000 }, + { FFB_DFB422AD_VOFF, FFB_DFB422AD_POFF, 0x0800000 }, + { FFB_DFB24B_VOFF, FFB_DFB24B_POFF, 0x1000000 }, + { FFB_DFB422B_VOFF, FFB_DFB422B_POFF, 0x0800000 }, + { FFB_DFB422BD_VOFF, FFB_DFB422BD_POFF, 0x0800000 }, + { FFB_SFB16Z_VOFF, FFB_SFB16Z_POFF, 0x0800000 }, + { FFB_SFB8Z_VOFF, FFB_SFB8Z_POFF, 0x0800000 }, + { FFB_SFB422_VOFF, FFB_SFB422_POFF, 0x0800000 }, + { FFB_SFB422D_VOFF, FFB_SFB422D_POFF, 0x0800000 }, { 0, 0, 0 } }; diff -u --recursive --new-file v2.4.5/linux/drivers/video/cyber2000fb.c linux/drivers/video/cyber2000fb.c --- v2.4.5/linux/drivers/video/cyber2000fb.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/video/cyber2000fb.c Wed Jun 27 13:15:17 2001 @@ -1612,14 +1612,15 @@ } } -static void cyberpro_suspend(struct pci_dev *dev) +static int cyberpro_suspend(struct pci_dev *dev, u32 state) { + return 0; } /* * Re-initialise the CyberPro hardware */ -static void cyberpro_resume(struct pci_dev *dev) +static int cyberpro_resume(struct pci_dev *dev) { struct cfb_info *cfb = (struct cfb_info *)dev->driver_data; @@ -1633,6 +1634,8 @@ cfb->fb.var.activate = FB_ACTIVATE_NOW; cyber2000fb_set_var(&cfb->fb.var, -1, &cfb->fb); } + + return 0; } static struct pci_device_id cyberpro_pci_table[] __devinitdata = { diff -u --recursive --new-file v2.4.5/linux/drivers/video/fbcon.c linux/drivers/video/fbcon.c --- v2.4.5/linux/drivers/video/fbcon.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/video/fbcon.c Mon Jun 11 19:15:27 2001 @@ -2060,44 +2060,32 @@ if (!fb) return 0; - /* Set colors if visual is PSEUDOCOLOR and we have enough colors, or for - * DIRECTCOLOR */ - if ((p->visual == FB_VISUAL_PSEUDOCOLOR && depth >= 4) || - p->visual == FB_VISUAL_DIRECTCOLOR) { - int is_truecolor = (p->visual == FB_VISUAL_DIRECTCOLOR); - int use_256 = (!is_truecolor && depth >= 8) || - (is_truecolor && depth >= 24); - int first_col = use_256 ? 32 : depth > 4 ? 16 : 0; - int num_cols = use_256 ? LINUX_LOGO_COLORS : 16; - unsigned char *red, *green, *blue; - - if (use_256) { - red = linux_logo_red; - green = linux_logo_green; - blue = linux_logo_blue; - } - else { - red = linux_logo16_red; - green = linux_logo16_green; - blue = linux_logo16_blue; - } - - for( i = 0; i < num_cols; i += n ) { - n = num_cols - i; + /* + * Set colors if visual is PSEUDOCOLOR and we have enough colors, or for + * DIRECTCOLOR + * We don't have to set the colors for the 16-color logo, since that logo + * uses the standard VGA text console palette + */ + if ((p->visual == FB_VISUAL_PSEUDOCOLOR && depth >= 8) || + (p->visual == FB_VISUAL_DIRECTCOLOR && depth >= 24)) + for (i = 0; i < LINUX_LOGO_COLORS; i += n) { + n = LINUX_LOGO_COLORS - i; if (n > 16) /* palette_cmap provides space for only 16 colors at once */ n = 16; - palette_cmap.start = first_col + i; + palette_cmap.start = 32 + i; palette_cmap.len = n; for( j = 0; j < n; ++j ) { - palette_cmap.red[j] = (red[i+j] << 8) | red[i+j]; - palette_cmap.green[j] = (green[i+j] << 8) | green[i+j]; - palette_cmap.blue[j] = (blue[i+j] << 8) | blue[i+j]; + palette_cmap.red[j] = (linux_logo_red[i+j] << 8) | + linux_logo_red[i+j]; + palette_cmap.green[j] = (linux_logo_green[i+j] << 8) | + linux_logo_green[i+j]; + palette_cmap.blue[j] = (linux_logo_blue[i+j] << 8) | + linux_logo_blue[i+j]; } p->fb_info->fbops->fb_set_cmap(&palette_cmap, 1, fg_console, p->fb_info); } - } if (depth >= 8) { logo = linux_logo; @@ -2155,15 +2143,15 @@ } } } - else if (depth >= 15 && depth <= 23) { - /* have 5..7 bits per color, using 16 color image */ + else if (depth >= 12 && depth <= 23) { + /* have 4..7 bits per color, using 16 color image */ unsigned int pix; src = linux_logo16; bdepth = (depth+7)/8; for( y1 = 0; y1 < LOGO_H; y1++ ) { dst = fb + y1*line + x*bdepth; for( x1 = 0; x1 < LOGO_W/2; x1++, src++ ) { - pix = (*src >> 4) | 0x10; /* upper nibble */ + pix = *src >> 4; /* upper nibble */ val = (pix << redshift) | (pix << greenshift) | (pix << blueshift); @@ -2173,7 +2161,7 @@ for( i = bdepth-1; i >= 0; --i ) #endif fb_writeb (val >> (i*8), dst++); - pix = (*src & 0x0f) | 0x10; /* lower nibble */ + pix = *src & 0x0f; /* lower nibble */ val = (pix << redshift) | (pix << greenshift) | (pix << blueshift); @@ -2297,16 +2285,13 @@ } } - /* fill remaining planes - * special case for logo_depth == 4: we used color registers 16..31, - * so fill plane 4 with 1 bits instead of 0 */ + /* fill remaining planes */ if (depth > logo_depth) { for( y1 = 0; y1 < LOGO_H; y1++ ) { for( x1 = 0; x1 < LOGO_LINE; x1++ ) { dst = fb + y1*line + MAP_X(x/8+x1) + logo_depth*plane; for( i = logo_depth; i < depth; i++, dst += plane ) - *dst = (i == logo_depth && logo_depth == 4) - ? 0xff : 0x00; + *dst = 0x00; } } } diff -u --recursive --new-file v2.4.5/linux/drivers/video/imsttfb.c linux/drivers/video/imsttfb.c --- v2.4.5/linux/drivers/video/imsttfb.c Wed Apr 18 11:49:12 2001 +++ linux/drivers/video/imsttfb.c Wed Jun 27 17:10:55 2001 @@ -6,6 +6,7 @@ * With additional hacking by Jeffrey Kuskin (jsk@mojave.stanford.edu) * Modified by Danilo Beuche 1998 * Some register values added by Damien Doligez, INRIA Rocquencourt + * Various cleanups by Paul Mundt (lethal@chaoticdreams.org) * * This file was written by Ryan Nielsen (ran@krazynet.com) * Most of the frame buffer device stuff was copied from atyfb.c @@ -378,6 +379,7 @@ #define CURSOR_DRAW_DELAY 2 static int currcon = 0; +static int inverse = 0; static char fontname[40] __initdata = { 0 }; static char curblink __initdata = 1; static char noaccel __initdata = 0; @@ -1235,7 +1237,6 @@ { struct fb_info_imstt *p = (struct fb_info_imstt *)info; u_int bpp = fb_display[currcon].var.bits_per_pixel; - u_int i; if (regno > 255) return 1; @@ -1413,7 +1414,7 @@ disp->type_aux = p->fix.type_aux; disp->line_length = disp->var.xres * (disp->var.bits_per_pixel >> 3); disp->can_soft_blank = 1; - disp->inverse = 0; + disp->inverse = inverse; disp->ypanstep = 1; disp->ywrapstep = 0; if (accel) { @@ -1887,7 +1888,6 @@ struct pci_dev *pdev = NULL; struct fb_info_imstt *p; unsigned long addr, size; - __u16 cmd; while ((pdev = pci_find_device(PCI_VENDOR_ID_IMS, PCI_ANY_ID, pdev))) { if ((pdev->class >> 16) != PCI_BASE_CLASS_DISPLAY) @@ -1963,6 +1963,9 @@ curblink = 0; } else if (!strncmp(this_opt, "noaccel", 7)) { noaccel = 1; + } else if (!strncmp(this_opt, "inverse", 7)) { + inverse = 1; + fb_invert_cmaps(); } #if defined(CONFIG_PPC) else if (!strncmp(this_opt, "vmode:", 6)) { @@ -1994,16 +1997,8 @@ } #else /* MODULE */ - -int __init -init_module (void) -{ - - return imsttfb_init(); -} - -void -cleanup_module (void) +static void __exit +imsttfb_exit(void) { struct fb_info_imstt *p; __u32 i; @@ -2012,13 +2007,18 @@ p = fb_info_imstt_p[i]; if (!p) continue; + unregister_framebuffer(&p->info); iounmap(p->cmap_regs); iounmap(p->dc_regs); iounmap(p->frame_buffer); - kfree(p); release_mem_region(p->frame_buffer_phys, p->board_size); + kfree(p); } } #include "macmodes.c" + +module_init(imsttfb_init); +module_exit(imsttfb_exit); #endif /* MODULE */ + diff -u --recursive --new-file v2.4.5/linux/drivers/video/macmodes.c linux/drivers/video/macmodes.c --- v2.4.5/linux/drivers/video/macmodes.c Fri Mar 2 18:38:39 2001 +++ linux/drivers/video/macmodes.c Wed Jun 27 17:10:55 2001 @@ -94,7 +94,15 @@ /* 1280x1024, 75 Hz, Non-Interlaced (135.00 MHz dotclock) */ "mac20", 75, 1280, 1024, 7408, 232, 64, 38, 1, 112, 3, FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED - }, + }, { + /* 1152x768, 60 Hz, Titanium PowerBook */ + "mac21", 60, 1152, 768, 15386, 158, 26, 29, 3, 136, 6, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + }, { + /* 1600x1024, 60 Hz, Non-Interlaced (112.27 MHz dotclock) */ + "mac22", 60, 1600, 1024, 8908, 88, 104, 1, 10, 16, 1, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + } #if 0 /* Anyone who has timings for these? */ @@ -154,12 +162,16 @@ { VMODE_1024_768_75V, &mac_modedb[9] }, { VMODE_1024_768_70, &mac_modedb[8] }, { VMODE_1024_768_60, &mac_modedb[7] }, + /* 1152x768 */ + { VMODE_1152_768_60, &mac_modedb[14] }, /* 1152x870 */ { VMODE_1152_870_75, &mac_modedb[11] }, /* 1280x960 */ { VMODE_1280_960_75, &mac_modedb[12] }, /* 1280x1024 */ { VMODE_1280_1024_75, &mac_modedb[13] }, + /* 1600x1024 */ + { VMODE_1600_1024_60, &mac_modedb[15] }, { -1, NULL } }; @@ -191,6 +203,7 @@ { 0x730, VMODE_768_576_50I }, /* PAL (Alternate) */ { 0x73a, VMODE_1152_870_75 }, /* 3rd party 19" */ { 0x73f, VMODE_640_480_67 }, /* no sense lines connected at all */ + { 0xBEEF, VMODE_1600_1024_60 }, /* 22" Apple Cinema Display */ { -1, VMODE_640_480_60 }, /* catch-all, must be last */ }; diff -u --recursive --new-file v2.4.5/linux/drivers/video/matrox/matroxfb_DAC1064.c linux/drivers/video/matrox/matroxfb_DAC1064.c --- v2.4.5/linux/drivers/video/matrox/matroxfb_DAC1064.c Wed Apr 11 19:21:35 2001 +++ linux/drivers/video/matrox/matroxfb_DAC1064.c Wed Jun 27 17:10:55 2001 @@ -4,7 +4,7 @@ * * (c) 1998-2001 Petr Vandrovec * - * Version: 1.52 2001/02/02 + * Version: 1.53 2001/06/18 * * See matroxfb_base.c for contributors. * @@ -33,12 +33,14 @@ #define DAC1064_OPT_RESERVED 0x10 static void matroxfb_DAC1064_flashcursor(unsigned long ptr) { + unsigned long flags; + #define minfo ((struct matrox_fb_info*)ptr) - matroxfb_DAC_lock(); + matroxfb_DAC_lock_irqsave(flags); outDAC1064(PMINFO M1064_XCURCTRL, inDAC1064(PMINFO M1064_XCURCTRL) ^ M1064_XCURCTRL_DIS ^ M1064_XCURCTRL_XGA); ACCESS_FBINFO(cursor.timer.expires) = jiffies + HZ/2; add_timer(&ACCESS_FBINFO(cursor.timer)); - matroxfb_DAC_unlock(); + matroxfb_DAC_unlock_irqrestore(flags); #undef minfo } @@ -719,7 +721,8 @@ ACCESS_FBINFO(capable.vxres) = vxres_g100; ACCESS_FBINFO(features.accel.has_cacheflush) = 1; ACCESS_FBINFO(cursor.timer.function) = matroxfb_DAC1064_flashcursor; - ACCESS_FBINFO(capable.plnwt) = ACCESS_FBINFO(devflags.accelerator) != FB_ACCEL_MATROX_MGAG100; + ACCESS_FBINFO(capable.plnwt) = ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG100 + ? ACCESS_FBINFO(devflags.sgram) : 1; ACCESS_FBINFO(primout) = &m1064; diff -u --recursive --new-file v2.4.5/linux/drivers/video/matrox/matroxfb_Ti3026.c linux/drivers/video/matrox/matroxfb_Ti3026.c --- v2.4.5/linux/drivers/video/matrox/matroxfb_Ti3026.c Thu Aug 10 12:34:31 2000 +++ linux/drivers/video/matrox/matroxfb_Ti3026.c Wed Jun 27 17:10:55 2001 @@ -279,12 +279,14 @@ 0x00, 0x00, TVP3026_XCURCTRL_DIS }; static void matroxfb_ti3026_flashcursor(unsigned long ptr) { + unsigned long flags; + #define minfo ((struct matrox_fb_info*)ptr) - matroxfb_DAC_lock(); + matroxfb_DAC_lock_irqsave(flags); outTi3026(PMINFO TVP3026_XCURCTRL, inTi3026(PMINFO TVP3026_XCURCTRL) ^ TVP3026_XCURCTRL_DIS ^ TVP3026_XCURCTRL_XGA); ACCESS_FBINFO(cursor.timer.expires) = jiffies + HZ/2; add_timer(&ACCESS_FBINFO(cursor.timer)); - matroxfb_DAC_unlock(); + matroxfb_DAC_unlock_irqrestore(flags); #undef minfo } diff -u --recursive --new-file v2.4.5/linux/drivers/video/matrox/matroxfb_accel.c linux/drivers/video/matrox/matroxfb_accel.c --- v2.4.5/linux/drivers/video/matrox/matroxfb_accel.c Thu Aug 10 12:34:31 2000 +++ linux/drivers/video/matrox/matroxfb_accel.c Wed Jun 27 17:10:55 2001 @@ -2,9 +2,9 @@ * * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400 * - * (c) 1998,1999,2000 Petr Vandrovec + * (c) 1998-2001 Petr Vandrovec * - * Version: 1.50 2000/08/10 + * Version: 1.51 2001/06/18 * * MTRR stuff: 1998 Tom Rini * @@ -129,6 +129,10 @@ mga_outl(M_YDSTORG, curr_ydstorg(MINFO)); if (ACCESS_FBINFO(capable.plnwt)) mga_outl(M_PLNWT, -1); + if (ACCESS_FBINFO(capable.srcorg)) { + mga_outl(M_SRCORG, 0); + mga_outl(M_DSTORG, 0); + } mga_outl(M_OPMODE, mopmode); mga_outl(M_CXBNDRY, 0xFFFF0000); mga_outl(M_YTOP, 0); diff -u --recursive --new-file v2.4.5/linux/drivers/video/matrox/matroxfb_base.c linux/drivers/video/matrox/matroxfb_base.c --- v2.4.5/linux/drivers/video/matrox/matroxfb_base.c Sun Feb 4 10:05:30 2001 +++ linux/drivers/video/matrox/matroxfb_base.c Wed Jun 27 17:10:55 2001 @@ -4,7 +4,7 @@ * * (c) 1998-2001 Petr Vandrovec * - * Version: 1.52 2001/02/02 + * Version: 1.53 2001/06/18 * * MTRR stuff: 1998 Tom Rini * @@ -72,6 +72,9 @@ * "Ken Aaker" * memtype extension (needed for GXT130P RS/6000 adapter) * + * "Uns Lider" + * G100 PLNWT fixes + * * (following author is not in any relation with this code, but his code * is included in this driver) * @@ -1409,7 +1412,7 @@ #define DEVF_VIDEO64BIT 0x0001 #define DEVF_SWAPS 0x0002 -/* #define DEVF_recycled 0x0004 */ +#define DEVF_SRCORG 0x0004 /* #define DEVF_recycled 0x0008 */ #define DEVF_CROSS4MB 0x0010 #define DEVF_TEXT4B 0x0020 @@ -1424,12 +1427,12 @@ #define DEVF_G450DAC 0x4000 #define DEVF_GCORE (DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB | DEVF_DDC_8_2) -#define DEVF_G2CORE (DEVF_GCORE | DEVF_ANY_VXRES | DEVF_MAVEN_CAPABLE | DEVF_PANELLINK_CAPABLE) +#define DEVF_G2CORE (DEVF_GCORE | DEVF_ANY_VXRES | DEVF_MAVEN_CAPABLE | DEVF_PANELLINK_CAPABLE | DEVF_SRCORG) #define DEVF_G100 (DEVF_GCORE) /* no doc, no vxres... */ #define DEVF_G200 (DEVF_G2CORE) #define DEVF_G400 (DEVF_G2CORE | DEVF_SUPPORT32MB | DEVF_TEXT16B | DEVF_CRTC2) /* if you'll find how to drive DFP... */ -#define DEVF_G450 (DEVF_GCORE | DEVF_ANY_VXRES | DEVF_SUPPORT32MB | DEVF_TEXT16B | DEVF_CRTC2 | DEVF_G450DAC) +#define DEVF_G450 (DEVF_GCORE | DEVF_ANY_VXRES | DEVF_SUPPORT32MB | DEVF_TEXT16B | DEVF_CRTC2 | DEVF_G450DAC | DEVF_SRCORG) static struct board { unsigned short vendor, device, rev, svid, sid; @@ -1556,7 +1559,7 @@ DEVF_G200, 230000, &vbG200, - "unknown G200 (AGP)"}, + "G200 (AGP)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400_AGP, 0x80, PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MILLENNIUM_G400_MAX_AGP, DEVF_G400, @@ -1568,13 +1571,13 @@ DEVF_G400, 300000, &vbG400, - "unknown G400 (AGP)"}, + "G400 (AGP)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400_AGP, 0xFF, 0, 0, DEVF_G450, 500000, /* ??? vco goes up to 900MHz... */ &vbG400, - "unknown G450 (AGP)"}, + "G450 (AGP)"}, #endif {0, 0, 0xFF, 0, 0, @@ -1611,6 +1614,7 @@ printk(KERN_INFO "matroxfb: Matrox %s detected\n", b->name); ACCESS_FBINFO(capable.plnwt) = 1; + ACCESS_FBINFO(capable.srcorg) = b->flags & DEVF_SRCORG; ACCESS_FBINFO(devflags.video64bits) = b->flags & DEVF_VIDEO64BIT; if (b->flags & DEVF_TEXT4B) { ACCESS_FBINFO(devflags.vgastep) = 4; @@ -2483,7 +2487,7 @@ return 0; } -static int __init initialized = 0; +static int __initdata initialized = 0; int __init matroxfb_init(void) { @@ -2495,6 +2499,7 @@ initialized = 1; matrox_init(); } + hotplug = 1; /* never return failure, user can hotplug matrox later... */ return 0; } @@ -2526,7 +2531,7 @@ MODULE_PARM(mtrr, "i"); MODULE_PARM_DESC(mtrr, "This speeds up video memory accesses (0=disabled or 1) (default=1)"); MODULE_PARM(sgram, "i"); -MODULE_PARM_DESC(sgram, "Indicates that G200/G400 has SGRAM memory (0=SDRAM, 1=SGRAM) (default=0)"); +MODULE_PARM_DESC(sgram, "Indicates that G100/G200/G400 has SGRAM memory (0=SDRAM, 1=SGRAM) (default=0)"); MODULE_PARM(inv24, "i"); MODULE_PARM_DESC(inv24, "Inverts clock polarity for 24bpp and loop frequency > 100MHz (default=do not invert polarity)"); MODULE_PARM(inverse, "i"); diff -u --recursive --new-file v2.4.5/linux/drivers/video/matrox/matroxfb_base.h linux/drivers/video/matrox/matroxfb_base.h --- v2.4.5/linux/drivers/video/matrox/matroxfb_base.h Fri Feb 9 11:30:23 2001 +++ linux/drivers/video/matrox/matroxfb_base.h Wed Jun 27 17:10:55 2001 @@ -492,6 +492,7 @@ int cross4MB; int text; int plnwt; + int srcorg; } capable; struct { unsigned int size; @@ -738,6 +739,7 @@ /* G200 only */ #define M_SRCORG 0x2CB4 +#define M_DSTORG 0x2CB8 #define M_RAMDAC_BASE 0x3C00 diff -u --recursive --new-file v2.4.5/linux/drivers/video/matrox/matroxfb_g450.c linux/drivers/video/matrox/matroxfb_g450.c --- v2.4.5/linux/drivers/video/matrox/matroxfb_g450.c Fri Dec 29 14:07:23 2000 +++ linux/drivers/video/matrox/matroxfb_g450.c Wed Jun 27 17:10:55 2001 @@ -6,17 +6,20 @@ static int matroxfb_g450_get_reg(WPMINFO int reg) { int val; + unsigned long flags; - matroxfb_DAC_lock(); + matroxfb_DAC_lock_irqsave(flags); val = matroxfb_DAC_in(PMINFO reg); - matroxfb_DAC_unlock(); + matroxfb_DAC_unlock_irqrestore(flags); return val; } static int matroxfb_g450_set_reg(WPMINFO int reg, int val) { - matroxfb_DAC_lock(); + unsigned long flags; + + matroxfb_DAC_lock_irqsave(flags); matroxfb_DAC_out(PMINFO reg, val); - matroxfb_DAC_unlock(); + matroxfb_DAC_unlock_irqrestore(flags); return 0; } diff -u --recursive --new-file v2.4.5/linux/drivers/video/mdacon.c linux/drivers/video/mdacon.c --- v2.4.5/linux/drivers/video/mdacon.c Fri Feb 9 11:30:23 2001 +++ linux/drivers/video/mdacon.c Wed Jun 27 17:10:55 2001 @@ -21,6 +21,9 @@ * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive for * more details. + * + * Changelog: + * Paul G. (03/2001) Fix mdacon= boot prompt to use __setup(). */ #include @@ -129,6 +132,7 @@ spin_unlock_irqrestore(&mda_lock, flags); } +#ifdef TEST_MDA_B static int test_mda_b(unsigned char val, unsigned char reg) { unsigned long flags; @@ -143,6 +147,7 @@ spin_unlock_irqrestore(&mda_lock, flags); return val; } +#endif static inline void mda_set_origin(unsigned int location) { @@ -182,20 +187,27 @@ #ifndef MODULE -void __init mdacon_setup(char *str, int *ints) +static int __init mdacon_setup(char *str) { /* command line format: mdacon=, */ + int ints[3]; + + str = get_options(str, ARRAY_SIZE(ints), ints); + if (ints[0] < 2) - return; + return 0; if (ints[1] < 1 || ints[1] > MAX_NR_CONSOLES || ints[2] < 1 || ints[2] > MAX_NR_CONSOLES) - return; + return 0; - mda_first_vc = ints[1]-1; - mda_last_vc = ints[2]-1; + mda_first_vc = ints[1]; + mda_last_vc = ints[2]; + return 1; } + +__setup("mdacon=", mdacon_setup); #endif static int __init mda_detect(void) @@ -237,17 +249,19 @@ * memory location, so now we do an I/O port test. */ +#ifdef TEST_MDA_B /* Edward: These two mess `tests' mess up my cursor on bootup */ /* cursor low register */ - /* if (! test_mda_b(0x66, 0x0f)) { + if (! test_mda_b(0x66, 0x0f)) { return 0; - } */ + } /* cursor low register */ - /* if (! test_mda_b(0x99, 0x0f)) { + if (! test_mda_b(0x99, 0x0f)) { return 0; - } */ + } +#endif /* See if the card is a Hercules, by checking whether the vsync * bit of the status register is changing. This test lasts for diff -u --recursive --new-file v2.4.5/linux/fs/Config.in linux/fs/Config.in --- v2.4.5/linux/fs/Config.in Sun May 20 12:11:38 2001 +++ linux/fs/Config.in Mon Jul 2 14:03:04 2001 @@ -27,8 +27,8 @@ dep_tristate ' VFAT (Windows-95) fs support' CONFIG_VFAT_FS $CONFIG_FAT_FS dep_tristate 'EFS file system support (read only) (EXPERIMENTAL)' CONFIG_EFS_FS $CONFIG_EXPERIMENTAL dep_tristate 'Journalling Flash File System (JFFS) support (EXPERIMENTAL)' CONFIG_JFFS_FS $CONFIG_EXPERIMENTAL $CONFIG_MTD -if [ "$CONFIG_JFFS_FS" != "n" ] ; then - int 'JFFS debugging verbosity (0 = quiet, 3 = noisy)' CONFIG_JFFS_FS_VERBOSE 0 +if [ "$CONFIG_JFFS_FS" = "y" -o "$CONFIG_JFFS_FS" = "m" ] ; then + int 'JFFS debugging verbosity (0 = quiet, 3 = noisy)' CONFIG_JFFS_FS_VERBOSE 0 fi tristate 'Compressed ROM file system support' CONFIG_CRAMFS bool 'Virtual memory file system support (former shm fs)' CONFIG_TMPFS @@ -64,8 +64,7 @@ tristate 'Second extended fs support' CONFIG_EXT2_FS -tristate 'System V and Coherent file system support (read only)' CONFIG_SYSV_FS -dep_mbool ' SYSV file system write support (DANGEROUS)' CONFIG_SYSV_FS_WRITE $CONFIG_SYSV_FS $CONFIG_EXPERIMENTAL +tristate 'System V/Xenix/V7/Coherent file system support' CONFIG_SYSV_FS tristate 'UDF file system support (read only)' CONFIG_UDF_FS dep_mbool ' UDF write support (DANGEROUS)' CONFIG_UDF_RW $CONFIG_UDF_FS $CONFIG_EXPERIMENTAL @@ -104,9 +103,9 @@ dep_tristate 'SMB file system support (to mount Windows shares etc.)' CONFIG_SMB_FS $CONFIG_INET if [ "$CONFIG_SMB_FS" != "n" ]; then - bool ' Use a default NLS' CONFIG_SMB_NLS_DEFAULT + bool ' Use a default NLS' CONFIG_SMB_NLS_DEFAULT if [ "$CONFIG_SMB_NLS_DEFAULT" = "y" ]; then - string ' Default Remote NLS Option' CONFIG_SMB_NLS_REMOTE "cp437" + string ' Default Remote NLS Option' CONFIG_SMB_NLS_REMOTE "cp437" fi fi if [ "$CONFIG_IPX" != "n" -o "$CONFIG_INET" != "n" ]; then diff -u --recursive --new-file v2.4.5/linux/fs/affs/file.c linux/fs/affs/file.c --- v2.4.5/linux/fs/affs/file.c Thu Apr 19 22:57:06 2001 +++ linux/fs/affs/file.c Fri Jun 29 15:36:10 2001 @@ -90,7 +90,7 @@ int i, j, key; if (!AFFS_INODE->i_lc) { - char *ptr = (char *)get_zeroed_page(GFP_BUFFER); + char *ptr = (char *)get_zeroed_page(GFP_NOFS); if (!ptr) return -ENOMEM; AFFS_INODE->i_lc = (u32 *)ptr; diff -u --recursive --new-file v2.4.5/linux/fs/autofs/autofs_i.h linux/fs/autofs/autofs_i.h --- v2.4.5/linux/fs/autofs/autofs_i.h Fri Feb 9 11:29:44 2001 +++ linux/fs/autofs/autofs_i.h Thu Jun 14 14:16:58 2001 @@ -89,7 +89,8 @@ #define AUTOFS_FIRST_SYMLINK 2 #define AUTOFS_FIRST_DIR_INO (AUTOFS_FIRST_SYMLINK+AUTOFS_MAX_SYMLINKS) -#define AUTOFS_SYMLINK_BITMAP_LEN ((AUTOFS_MAX_SYMLINKS+31)/32) +#define AUTOFS_SYMLINK_BITMAP_LEN \ + ((AUTOFS_MAX_SYMLINKS+((sizeof(long)*1)-1))/(sizeof(long)*8)) #define AUTOFS_SBI_MAGIC 0x6d4a556d @@ -103,7 +104,7 @@ struct autofs_wait_queue *queues; /* Wait queue pointer */ struct autofs_dirhash dirhash; /* Root directory hash */ struct autofs_symlink symlink[AUTOFS_MAX_SYMLINKS]; - u32 symlink_bitmap[AUTOFS_SYMLINK_BITMAP_LEN]; + unsigned long symlink_bitmap[AUTOFS_SYMLINK_BITMAP_LEN]; }; extern inline struct autofs_sb_info *autofs_sbi(struct super_block *sb) diff -u --recursive --new-file v2.4.5/linux/fs/autofs/inode.c linux/fs/autofs/inode.c --- v2.4.5/linux/fs/autofs/inode.c Fri Feb 9 11:29:44 2001 +++ linux/fs/autofs/inode.c Thu Jun 14 14:16:58 2001 @@ -132,7 +132,7 @@ sbi->oz_pgrp = current->pgrp; autofs_initialize_hash(&sbi->dirhash); sbi->queues = NULL; - memset(sbi->symlink_bitmap, 0, sizeof(u32)*AUTOFS_SYMLINK_BITMAP_LEN); + memset(sbi->symlink_bitmap, 0, sizeof(long)*AUTOFS_SYMLINK_BITMAP_LEN); sbi->next_dir_ino = AUTOFS_FIRST_DIR_INO; s->s_blocksize = 1024; s->s_blocksize_bits = 10; diff -u --recursive --new-file v2.4.5/linux/fs/autofs4/expire.c linux/fs/autofs4/expire.c --- v2.4.5/linux/fs/autofs4/expire.c Fri Apr 20 22:57:51 2001 +++ linux/fs/autofs4/expire.c Mon Jun 11 19:15:27 2001 @@ -66,19 +66,11 @@ non-busy mounts */ static int check_vfsmnt(struct vfsmount *mnt, struct dentry *dentry) { - int ret = 0; - struct list_head *tmp; - - list_for_each(tmp, &dentry->d_vfsmnt) { - struct vfsmount *vfs = list_entry(tmp, struct vfsmount, - mnt_clash); - DPRINTK(("check_vfsmnt: mnt=%p, dentry=%p, tmp=%p, vfs=%p\n", - mnt, dentry, tmp, vfs)); - if (vfs->mnt_parent != mnt || /* don't care about busy-ness of other namespaces */ - !is_vfsmnt_tree_busy(vfs)) - ret++; - } + int ret = dentry->d_mounted; + struct vfsmount *vfs = lookup_mnt(mnt, dentry); + if (vfs && is_vfsmnt_tree_busy(vfs)) + ret--; DPRINTK(("check_vfsmnt: ret=%d\n", ret)); return ret; } diff -u --recursive --new-file v2.4.5/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c --- v2.4.5/linux/fs/binfmt_elf.c Sat May 19 18:09:15 2001 +++ linux/fs/binfmt_elf.c Mon Jul 2 14:38:38 2001 @@ -396,7 +396,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) { struct file *interpreter = NULL; /* to shut gcc up */ - unsigned long load_addr = 0, load_bias; + unsigned long load_addr = 0, load_bias = 0; int load_addr_set = 0; char * elf_interpreter = NULL; unsigned int interpreter_type = INTERPRETER_NONE; @@ -595,12 +595,6 @@ setup_arg_pages(bprm); /* XXX: check error */ current->mm->start_stack = bprm->p; - /* Try and get dynamic programs out of the way of the default mmap - base, as well as whatever program they might try to exec. This - is because the brk will follow the loader, and is not movable. */ - - load_bias = ELF_PAGESTART(elf_ex.e_type==ET_DYN ? ELF_ET_DYN_BASE : 0); - /* Now we do a little grungy work by mmaping the ELF image into the correct location in memory. At this point, we assume that the image should be loaded at fixed address, not at a variable @@ -624,6 +618,11 @@ vaddr = elf_ppnt->p_vaddr; if (elf_ex.e_type == ET_EXEC || load_addr_set) { elf_flags |= MAP_FIXED; + } else if (elf_ex.e_type == ET_DYN) { + /* Try and get dynamic programs out of the way of the default mmap + base, as well as whatever program they might try to exec. This + is because the brk will follow the loader, and is not movable. */ + load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr); } error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags); diff -u --recursive --new-file v2.4.5/linux/fs/block_dev.c linux/fs/block_dev.c --- v2.4.5/linux/fs/block_dev.c Tue May 22 09:35:42 2001 +++ linux/fs/block_dev.c Mon Jun 11 19:15:27 2001 @@ -595,14 +595,15 @@ int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg) { - kdev_t rdev = to_kdev_t(bdev->bd_dev); struct inode inode_fake; int res; mm_segment_t old_fs = get_fs(); if (!bdev->bd_op->ioctl) return -EINVAL; - inode_fake.i_rdev=rdev; + memset(&inode_fake, 0, sizeof(inode_fake)); + inode_fake.i_rdev = to_kdev_t(bdev->bd_dev); + inode_fake.i_bdev = bdev; init_waitqueue_head(&inode_fake.i_wait); set_fs(KERNEL_DS); res = bdev->bd_op->ioctl(&inode_fake, NULL, cmd, arg); diff -u --recursive --new-file v2.4.5/linux/fs/buffer.c linux/fs/buffer.c --- v2.4.5/linux/fs/buffer.c Fri May 25 17:57:46 2001 +++ linux/fs/buffer.c Sat Jun 30 10:44:32 2001 @@ -61,7 +61,7 @@ #define BUFSIZE_INDEX(X) ((int) buffersize_index[(X)>>9]) #define MAX_BUF_PER_PAGE (PAGE_CACHE_SIZE / 512) -#define NR_RESERVED (2*MAX_BUF_PER_PAGE) +#define NR_RESERVED (10*MAX_BUF_PER_PAGE) #define MAX_UNUSED_BUFFERS NR_RESERVED+20 /* don't ever have more than this number of unused buffer heads */ @@ -161,144 +161,131 @@ atomic_dec(&bh->b_count); } -/* Call sync_buffers with wait!=0 to ensure that the call does not - * return until all buffer writes have completed. Sync() may return - * before the writes have finished; fsync() may not. - */ +/* End-of-write handler.. Just mark it up-to-date and unlock the buffer. */ +static void end_buffer_write(struct buffer_head *bh, int uptodate) +{ + mark_buffer_uptodate(bh, uptodate); + unlock_buffer(bh); +} -/* Godamity-damn. Some buffers (bitmaps for filesystems) - * spontaneously dirty themselves without ever brelse being called. - * We will ultimately want to put these in a separate list, but for - * now we search all of the lists for dirty buffers. +/* + * The buffers have been marked clean and locked. Just submit the dang + * things.. + * + * We'll wait for the first one of them - "sync" is not exactly + * performance-critical, and this makes us not hog the IO subsystem + * completely, while still allowing for a fair amount of concurrent IO. */ -static int sync_buffers(kdev_t dev, int wait) +static void write_locked_buffers(struct buffer_head **array, unsigned int count) { - int i, retry, pass = 0, err = 0; - struct buffer_head * bh, *next; - - /* One pass for no-wait, three for wait: - * 0) write out all dirty, unlocked buffers; - * 1) write out all dirty buffers, waiting if locked; - * 2) wait for completion by waiting for all buffers to unlock. - */ + struct buffer_head *wait = *array; + atomic_inc(&wait->b_count); do { - retry = 0; - - /* We search all lists as a failsafe mechanism, not because we expect - * there to be dirty buffers on any of the other lists. - */ -repeat: - spin_lock(&lru_list_lock); - bh = lru_list[BUF_DIRTY]; - if (!bh) - goto repeat2; - - for (i = nr_buffers_type[BUF_DIRTY]*2 ; i-- > 0 ; bh = next) { - next = bh->b_next_free; + struct buffer_head * bh = *array++; + bh->b_end_io = end_buffer_write; + submit_bh(WRITE, bh); + } while (--count); + wait_on_buffer(wait); + atomic_dec(&wait->b_count); +} - if (!lru_list[BUF_DIRTY]) - break; - if (dev && bh->b_dev != dev) - continue; - if (buffer_locked(bh)) { - /* Buffer is locked; skip it unless wait is - * requested AND pass > 0. - */ - if (!wait || !pass) { - retry = 1; - continue; - } - atomic_inc(&bh->b_count); - spin_unlock(&lru_list_lock); - wait_on_buffer (bh); - atomic_dec(&bh->b_count); - goto repeat; - } +#define NRSYNC (32) +static void write_unlocked_buffers(kdev_t dev) +{ + struct buffer_head *next; + struct buffer_head *array[NRSYNC]; + unsigned int count; + int nr; - /* If an unlocked buffer is not uptodate, there has - * been an IO error. Skip it. - */ - if (wait && buffer_req(bh) && !buffer_locked(bh) && - !buffer_dirty(bh) && !buffer_uptodate(bh)) { - err = -EIO; - continue; - } +repeat: + spin_lock(&lru_list_lock); + next = lru_list[BUF_DIRTY]; + nr = nr_buffers_type[BUF_DIRTY] * 2; + count = 0; + while (next && --nr >= 0) { + struct buffer_head * bh = next; + next = bh->b_next_free; - /* Don't write clean buffers. Don't write ANY buffers - * on the third pass. - */ - if (!buffer_dirty(bh) || pass >= 2) + if (dev && bh->b_dev != dev) + continue; + if (test_and_set_bit(BH_Lock, &bh->b_state)) + continue; + if (atomic_set_buffer_clean(bh)) { + __refile_buffer(bh); + array[count++] = bh; + if (count < NRSYNC) continue; - atomic_inc(&bh->b_count); spin_unlock(&lru_list_lock); - ll_rw_block(WRITE, 1, &bh); - atomic_dec(&bh->b_count); - retry = 1; + write_locked_buffers(array, count); goto repeat; } + unlock_buffer(bh); + } + spin_unlock(&lru_list_lock); - repeat2: - bh = lru_list[BUF_LOCKED]; - if (!bh) { - spin_unlock(&lru_list_lock); - break; - } - for (i = nr_buffers_type[BUF_LOCKED]*2 ; i-- > 0 ; bh = next) { - next = bh->b_next_free; + if (count) + write_locked_buffers(array, count); +} - if (!lru_list[BUF_LOCKED]) - break; - if (dev && bh->b_dev != dev) - continue; - if (buffer_locked(bh)) { - /* Buffer is locked; skip it unless wait is - * requested AND pass > 0. - */ - if (!wait || !pass) { - retry = 1; - continue; - } - atomic_inc(&bh->b_count); - spin_unlock(&lru_list_lock); - wait_on_buffer (bh); - spin_lock(&lru_list_lock); - atomic_dec(&bh->b_count); - goto repeat2; - } +static int wait_for_locked_buffers(kdev_t dev, int index, int refile) +{ + struct buffer_head * next; + int nr; + +repeat: + spin_lock(&lru_list_lock); + next = lru_list[index]; + nr = nr_buffers_type[index] * 2; + while (next && --nr >= 0) { + struct buffer_head *bh = next; + next = bh->b_next_free; + + if (!buffer_locked(bh)) { + if (refile) + __refile_buffer(bh); + continue; } - spin_unlock(&lru_list_lock); + if (dev && bh->b_dev != dev) + continue; - /* If we are waiting for the sync to succeed, and if any dirty - * blocks were written, then repeat; on the second pass, only - * wait for buffers being written (do not pass to write any - * more buffers on the second pass). - */ - } while (wait && retry && ++pass<=2); - return err; + atomic_inc(&bh->b_count); + spin_unlock(&lru_list_lock); + wait_on_buffer (bh); + atomic_dec(&bh->b_count); + goto repeat; + } + spin_unlock(&lru_list_lock); + return 0; } -void sync_dev(kdev_t dev) +/* Call sync_buffers with wait!=0 to ensure that the call does not + * return until all buffer writes have completed. Sync() may return + * before the writes have finished; fsync() may not. + */ + +/* Godamity-damn. Some buffers (bitmaps for filesystems) + * spontaneously dirty themselves without ever brelse being called. + * We will ultimately want to put these in a separate list, but for + * now we search all of the lists for dirty buffers. + */ +static int sync_buffers(kdev_t dev, int wait) { - sync_supers(dev); - sync_inodes(dev); - DQUOT_SYNC(dev); - /* sync all the dirty buffers out to disk only _after_ all the - high level layers finished generated buffer dirty data - (or we'll return with some buffer still dirty on the blockdevice - so breaking the semantics of this call) */ - sync_buffers(dev, 0); - /* - * FIXME(eric) we need to sync the physical devices here. - * This is because some (scsi) controllers have huge amounts of - * cache onboard (hundreds of Mb), and we need to instruct - * them to commit all of the dirty memory to disk, and we should - * not return until this has happened. - * - * This would need to get implemented by going through the assorted - * layers so that each block major number can be synced, and this - * would call down into the upper and mid-layer scsi. + int err = 0; + + /* One pass for no-wait, three for wait: + * 0) write out all dirty, unlocked buffers; + * 1) wait for all dirty locked buffers; + * 2) write out all dirty, unlocked buffers; + * 2) wait for completion by waiting for all buffers to unlock. */ + write_unlocked_buffers(dev); + if (wait) { + err = wait_for_locked_buffers(dev, BUF_DIRTY, 0); + write_unlocked_buffers(dev); + err |= wait_for_locked_buffers(dev, BUF_LOCKED, 1); + } + return err; } int fsync_super(struct super_block *sb) @@ -331,6 +318,15 @@ return sync_buffers(dev, 1); } +/* + * There's no real reason to pretend we should + * ever do anything differently + */ +void sync_dev(kdev_t dev) +{ + fsync_dev(dev); +} + asmlinkage long sys_sync(void) { fsync_dev(0); @@ -646,8 +642,8 @@ /* Another device? */ if (bh->b_dev != dev) continue; - /* Part of a mapping? */ - if (bh->b_page->mapping) + /* Not hashed? */ + if (!bh->b_pprev) continue; if (buffer_locked(bh)) { atomic_inc(&bh->b_count); @@ -711,6 +707,9 @@ bh_next = bh->b_next_free; if (bh->b_dev != dev || bh->b_size == size) continue; + /* Unhashed? */ + if (!bh->b_pprev) + continue; if (buffer_locked(bh)) { atomic_inc(&bh->b_count); spin_unlock(&lru_list_lock); @@ -759,7 +758,7 @@ { balance_dirty(NODEV); if (free_shortage()) - page_launder(GFP_BUFFER, 0); + page_launder(GFP_NOFS, 0); if (!grow_buffers(size)) { wakeup_bdflush(1); current->policy |= SCHED_YIELD; @@ -1220,11 +1219,11 @@ } spin_unlock(&unused_list_lock); - /* This is critical. We can't swap out pages to get - * more buffer heads, because the swap-out may need - * more buffer-heads itself. Thus SLAB_BUFFER. + /* This is critical. We can't call out to the FS + * to get more buffer heads, because the FS may need + * more buffer-heads itself. Thus SLAB_NOFS. */ - if((bh = kmem_cache_alloc(bh_cachep, SLAB_BUFFER)) != NULL) { + if((bh = kmem_cache_alloc(bh_cachep, SLAB_NOFS)) != NULL) { bh->b_blocknr = -1; bh->b_this_page = NULL; return bh; @@ -1348,11 +1347,9 @@ */ run_task_queue(&tq_disk); - /* - * Set our state for sleeping, then check again for buffer heads. - * This ensures we won't miss a wake_up from an interrupt. - */ - wait_event(buffer_wait, nr_unused_buffer_heads >= MAX_BUF_PER_PAGE); + current->policy |= SCHED_YIELD; + __set_current_state(TASK_RUNNING); + schedule(); goto try_again; } @@ -2242,7 +2239,7 @@ return 0; } - page = alloc_page(GFP_BUFFER); + page = alloc_page(GFP_NOFS); if (!page) goto out; LockPage(page); @@ -2304,7 +2301,7 @@ * 1 - start IO for dirty buffers * 2 - wait for completion of locked buffers */ -static void sync_page_buffers(struct buffer_head *bh, int wait) +static void sync_page_buffers(struct buffer_head *bh, unsigned int gfp_mask) { struct buffer_head * tmp = bh; @@ -2312,7 +2309,7 @@ struct buffer_head *p = tmp; tmp = tmp->b_this_page; if (buffer_locked(p)) { - if (wait > 1) + if (gfp_mask & __GFP_WAIT) __wait_on_buffer(p); } else if (buffer_dirty(p)) ll_rw_block(WRITE, 1, &p); @@ -2336,7 +2333,7 @@ * obtain a reference to a buffer head within a page. So we must * lock out all of these paths to cleanly toss the page. */ -int try_to_free_buffers(struct page * page, int wait) +int try_to_free_buffers(struct page * page, unsigned int gfp_mask) { struct buffer_head * tmp, * bh = page->buffers; int index = BUFSIZE_INDEX(bh->b_size); @@ -2387,10 +2384,10 @@ spin_unlock(&free_list[index].lock); write_unlock(&hash_table_lock); spin_unlock(&lru_list_lock); - if (wait) { - sync_page_buffers(bh, wait); + if (gfp_mask & __GFP_IO) { + sync_page_buffers(bh, gfp_mask); /* We waited synchronously, so we can free the buffers. */ - if (wait > 1 && !loop) { + if ((gfp_mask & __GFP_WAIT) && !loop) { loop = 1; goto cleaned_buffers_try_again; } diff -u --recursive --new-file v2.4.5/linux/fs/dcache.c linux/fs/dcache.c --- v2.4.5/linux/fs/dcache.c Tue May 22 09:35:42 2001 +++ linux/fs/dcache.c Mon Jun 11 19:15:27 2001 @@ -616,7 +616,7 @@ dentry->d_name.hash = name->hash; dentry->d_op = NULL; dentry->d_fsdata = NULL; - INIT_LIST_HEAD(&dentry->d_vfsmnt); + dentry->d_mounted = 0; INIT_LIST_HEAD(&dentry->d_hash); INIT_LIST_HEAD(&dentry->d_lru); INIT_LIST_HEAD(&dentry->d_subdirs); @@ -1283,6 +1283,7 @@ dcache_init(mempages); inode_init(mempages); + mnt_init(mempages); bdev_cache_init(); cdev_cache_init(); } diff -u --recursive --new-file v2.4.5/linux/fs/devfs/base.c linux/fs/devfs/base.c --- v2.4.5/linux/fs/devfs/base.c Tue May 22 09:35:42 2001 +++ linux/fs/devfs/base.c Wed Jun 20 10:54:31 2001 @@ -1,6 +1,6 @@ /* devfs (Device FileSystem) driver. - Copyright (C) 1998-2000 Richard Gooch + Copyright (C) 1998-2001 Richard Gooch This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -481,6 +481,32 @@ Simplified interface to . Work sponsored by SGI. v0.102 + 20010519 Richard Gooch + Ensure terminates string for root entry. + Exported to modules. + 20010520 Richard Gooch + Make send events to devfsd. + Cleaned up option processing in . + 20010521 Richard Gooch + Fixed bugs in handling symlinks: could leak or cause Oops. + 20010522 Richard Gooch + Cleaned up directory handling by separating fops. + v0.103 + 20010601 Richard Gooch + Fixed handling of inverted options in . + v0.104 + 20010604 Richard Gooch + Adjusted to account for fix. + v0.105 + 20010617 Richard Gooch + Answered question posed by Al Viro and removed his comments. + Moved setting of registered flag after other fields are changed. + Fixed race between and . + Global VFS changes added bogus BKL to : removed. + Widened locking in and . + Replaced stack usage with kmalloc. + Simplified locking in and fixed memory leak. + v0.106 */ #include #include @@ -515,7 +541,7 @@ #include #include -#define DEVFS_VERSION "0.102 (20000622)" +#define DEVFS_VERSION "0.106 (20010617)" #define DEVFS_NAME "devfs" @@ -560,7 +586,7 @@ #define OPTION_NONE 0x00 #define OPTION_SHOW 0x01 -#define OPTION_NOMOUNT 0x02 +#define OPTION_MOUNT 0x02 #define OPTION_ONLY 0x04 #define OOPS(format, args...) {printk (format, ## args); \ @@ -665,26 +691,27 @@ gid_t gid; }; -struct fs_info /* This structure is for each mounted devfs */ +struct fs_info /* This structure is for the mounted devfs */ { unsigned int num_inodes; /* Number of inodes created */ unsigned int table_size; /* Size of the inode pointer table */ struct devfs_entry **table; struct super_block *sb; volatile struct devfsd_buf_entry *devfsd_buffer; + spinlock_t devfsd_buffer_lock; volatile unsigned int devfsd_buf_in; volatile unsigned int devfsd_buf_out; volatile int devfsd_sleeping; - volatile int devfsd_buffer_in_use; volatile struct task_struct *devfsd_task; volatile struct file *devfsd_file; + struct devfsd_notify_struct *devfsd_info; volatile unsigned long devfsd_event_mask; atomic_t devfsd_overrun_count; wait_queue_head_t devfsd_wait_queue; wait_queue_head_t revalidate_wait_queue; }; -static struct fs_info fs_info; +static struct fs_info fs_info = {devfsd_buffer_lock: SPIN_LOCK_UNLOCKED}; static unsigned int next_devnum_char = MIN_DEVNUM; static unsigned int next_devnum_block = MIN_DEVNUM; static const int devfsd_buf_size = PAGE_SIZE / sizeof(struct devfsd_buf_entry); @@ -694,9 +721,9 @@ #endif #ifdef CONFIG_DEVFS_MOUNT -static unsigned int boot_options = OPTION_NONE; +static unsigned int boot_options = OPTION_MOUNT; #else -static unsigned int boot_options = OPTION_NOMOUNT; +static unsigned int boot_options = OPTION_NONE; #endif /* Forward function declarations */ @@ -851,14 +878,13 @@ /* Always ensure the root is created */ if (root_entry != NULL) return root_entry; if ( ( root_entry = create_entry (NULL, NULL, 0) ) == NULL ) return NULL; - root_entry->registered = TRUE; root_entry->mode = S_IFDIR; /* Force an inode update, because lookup() is never done for the root */ update_devfs_inode_from_entry (root_entry); + root_entry->registered = TRUE; /* And create the entry for ".devfsd" */ if ( ( new = create_entry (root_entry, ".devfsd", 0) ) == NULL ) return NULL; - new->registered = TRUE; new->u.fcb.u.device.major = next_devnum_char >> 8; new->u.fcb.u.device.minor = next_devnum_char & 0xff; ++next_devnum_char; @@ -866,6 +892,7 @@ new->u.fcb.default_uid = 0; new->u.fcb.default_gid = 0; new->u.fcb.ops = &devfsd_fops; + new->registered = TRUE; return root_entry; } /* End Function get_root_entry */ @@ -943,8 +970,8 @@ return NULL; } /* Ensure an unregistered entry is re-registered and visible */ - entry->registered = TRUE; entry->hide = FALSE; + entry->registered = TRUE; subname = ptr + 1; dir = entry; } @@ -1053,8 +1080,10 @@ return find_by_dev (root_entry, major, minor, type); } /* End Function find_entry */ -static struct devfs_entry *get_devfs_entry_from_vfs_inode (struct inode *inode) +static struct devfs_entry *get_devfs_entry_from_vfs_inode (struct inode *inode, + int do_check) { + struct devfs_entry *de; struct fs_info *fs_info; if (inode == NULL) return NULL; @@ -1062,7 +1091,9 @@ fs_info = inode->i_sb->u.generic_sbp; if (fs_info == NULL) return NULL; if (inode->i_ino - FIRST_INODE >= fs_info->num_inodes) return NULL; - return fs_info->table[inode->i_ino - FIRST_INODE]; + de = fs_info->table[inode->i_ino - FIRST_INODE]; + if (do_check && de && !de->registered) de = NULL; + return de; } /* End Function get_devfs_entry_from_vfs_inode */ @@ -1075,19 +1106,19 @@ { struct dentry *dentry; - spin_lock(&dcache_lock); + spin_lock (&dcache_lock); dentry = de->inode.dentry; if (dentry != NULL) { dget_locked (dentry); de->inode.dentry = NULL; - spin_unlock(&dcache_lock); + spin_unlock (&dcache_lock); /* Forcefully remove the inode */ if (dentry->d_inode != NULL) dentry->d_inode->i_nlink = 0; d_drop (dentry); dput (dentry); - } else - spin_unlock(&dcache_lock); + } + else spin_unlock (&dcache_lock); } /* End Function free_dentries */ @@ -1140,7 +1171,7 @@ add_wait_queue (&fs_info->revalidate_wait_queue, &wait); current->state = TASK_UNINTERRUPTIBLE; if (!devfsd_queue_empty (fs_info) || !fs_info->devfsd_sleeping) - if (fs_info->devfsd_task) schedule(); + if (fs_info->devfsd_task) schedule (); remove_wait_queue (&fs_info->revalidate_wait_queue, &wait); current->state = TASK_RUNNING; return (TRUE); @@ -1165,7 +1196,6 @@ unsigned int next_pos; unsigned long flags; struct devfsd_buf_entry *entry; - static spinlock_t lock = SPIN_LOCK_UNLOCKED; if ( !( fs_info->devfsd_event_mask & (1 << type) ) ) return (FALSE); next_pos = fs_info->devfsd_buf_in + 1; @@ -1176,8 +1206,7 @@ atomic_inc (&fs_info->devfsd_overrun_count); return (FALSE); } - spin_lock_irqsave (&lock, flags); - fs_info->devfsd_buffer_in_use = TRUE; + spin_lock_irqsave (&fs_info->devfsd_buffer_lock, flags); next_pos = fs_info->devfsd_buf_in + 1; if (next_pos >= devfsd_buf_size) next_pos = 0; entry = (struct devfsd_buf_entry *) fs_info->devfsd_buffer + @@ -1188,8 +1217,7 @@ entry->uid = uid; entry->gid = gid; fs_info->devfsd_buf_in = next_pos; - fs_info->devfsd_buffer_in_use = FALSE; - spin_unlock_irqrestore (&lock, flags); + spin_unlock_irqrestore (&fs_info->devfsd_buffer_lock, flags); wake_up_interruptible (&fs_info->devfsd_wait_queue); return (TRUE); } /* End Function devfsd_notify_one */ @@ -1322,7 +1350,6 @@ return NULL; } } - de->registered = TRUE; if ( S_ISCHR (mode) || S_ISBLK (mode) ) { de->u.fcb.u.device.major = major; @@ -1347,7 +1374,6 @@ de->u.fcb.default_uid = 0; de->u.fcb.default_gid = 0; } - de->registered = TRUE; de->u.fcb.ops = ops; de->u.fcb.auto_owner = (flags & DEVFS_FL_AUTO_OWNER) ? TRUE : FALSE; de->u.fcb.aopen_notify = (flags & DEVFS_FL_AOPEN_NOTIFY) ? TRUE : FALSE; @@ -1361,6 +1387,7 @@ || (flags & DEVFS_FL_SHOW_UNREG) ) ? TRUE : FALSE; de->hide = (flags & DEVFS_FL_HIDE) ? TRUE : FALSE; de->no_persistence = (flags & DEVFS_FL_NO_PERSISTENCE) ? TRUE : FALSE; + de->registered = TRUE; devfsd_notify (de, DEVFSD_NOTIFY_REGISTERED, flags & DEVFS_FL_WAIT); return de; } /* End Function devfs_register */ @@ -1392,11 +1419,10 @@ de->u.fcb.ops = NULL; return; } - if ( S_ISLNK (de->mode) ) + if (S_ISLNK (de->mode) && de->registered) { de->registered = FALSE; - if (de->u.symlink.linkname != NULL) kfree (de->u.symlink.linkname); - de->u.symlink.linkname = NULL; + kfree (de->u.symlink.linkname); return; } if ( S_ISFIFO (de->mode) ) @@ -1441,22 +1467,9 @@ unregister (de); } /* End Function devfs_unregister */ - -/** - * devfs_mk_symlink Create a symbolic link in the devfs namespace. - * @dir: The handle to the parent devfs directory entry. If this is %NULL the - * new name is relative to the root of the devfs. - * @name: The name of the entry. - * @flags: A set of bitwise-ORed flags (DEVFS_FL_*). - * @link: The destination name. - * @handle: The handle to the symlink entry is written here. This may be %NULL. - * @info: An arbitrary pointer which will be associated with the entry. - * - * Returns 0 on success, else a negative error code is returned. - */ - -int devfs_mk_symlink (devfs_handle_t dir, const char *name, unsigned int flags, - const char *link, devfs_handle_t *handle, void *info) +static int devfs_do_symlink (devfs_handle_t dir, const char *name, + unsigned int flags, const char *link, + devfs_handle_t *handle, void *info) { int is_new; unsigned int linklength; @@ -1466,16 +1479,16 @@ if (handle != NULL) *handle = NULL; if (name == NULL) { - printk ("%s: devfs_mk_symlink(): NULL name pointer\n", DEVFS_NAME); + printk ("%s: devfs_do_symlink(): NULL name pointer\n", DEVFS_NAME); return -EINVAL; } #ifdef CONFIG_DEVFS_DEBUG if (devfs_debug & DEBUG_REGISTER) - printk ("%s: devfs_mk_symlink(%s)\n", DEVFS_NAME, name); + printk ("%s: devfs_do_symlink(%s)\n", DEVFS_NAME, name); #endif if (link == NULL) { - printk ("%s: devfs_mk_symlink(): NULL link pointer\n", DEVFS_NAME); + printk ("%s: devfs_do_symlink(): NULL link pointer\n", DEVFS_NAME); return -EINVAL; } linklength = strlen (link); @@ -1484,7 +1497,7 @@ if (de == NULL) return -ENOMEM; if (!S_ISLNK (de->mode) && de->registered) { - printk ("%s: devfs_mk_symlink(): non-link entry already exists\n", + printk ("%s: devfs_do_symlink(): non-link entry already exists\n", DEVFS_NAME); return -EEXIST; } @@ -1504,7 +1517,6 @@ } /* Have to create/update */ if (de->registered) return -EEXIST; - de->registered = TRUE; if ( ( newname = kmalloc (linklength + 1, GFP_KERNEL) ) == NULL ) { struct devfs_entry *parent = de->parent; @@ -1518,11 +1530,39 @@ kfree (de); return -ENOMEM; } - if (de->u.symlink.linkname != NULL) kfree (de->u.symlink.linkname); de->u.symlink.linkname = newname; memcpy (de->u.symlink.linkname, link, linklength); de->u.symlink.linkname[linklength] = '\0'; de->u.symlink.length = linklength; + de->registered = TRUE; + return 0; +} /* End Function devfs_do_symlink */ + + +/** + * devfs_mk_symlink Create a symbolic link in the devfs namespace. + * @dir: The handle to the parent devfs directory entry. If this is %NULL the + * new name is relative to the root of the devfs. + * @name: The name of the entry. + * @flags: A set of bitwise-ORed flags (DEVFS_FL_*). + * @link: The destination name. + * @handle: The handle to the symlink entry is written here. This may be %NULL. + * @info: An arbitrary pointer which will be associated with the entry. + * + * Returns 0 on success, else a negative error code is returned. + */ + +int devfs_mk_symlink (devfs_handle_t dir, const char *name, unsigned int flags, + const char *link, devfs_handle_t *handle, void *info) +{ + int err; + devfs_handle_t de; + + if (handle != NULL) *handle = NULL; + err = devfs_do_symlink (dir, name, flags, link, &de, info); + if (err) return err; + if (handle != NULL) *handle = de; + devfsd_notify (de, DEVFSD_NOTIFY_REGISTERED, flags & DEVFS_FL_WAIT); return 0; } /* End Function devfs_mk_symlink */ @@ -1579,9 +1619,9 @@ de->mode = S_IFDIR | S_IRUGO | S_IXUGO; de->info = info; if (!de->registered) de->u.dir.num_removable = 0; - de->registered = TRUE; de->show_unreg = (boot_options & OPTION_SHOW) ? TRUE : FALSE; de->hide = FALSE; + de->registered = TRUE; return de; } /* End Function devfs_mk_dir */ @@ -1716,7 +1756,7 @@ { if (!inode || !inode->i_sb) return NULL; if (inode->i_sb->s_magic != DEVFS_SUPER_MAGIC) return NULL; - return get_devfs_entry_from_vfs_inode (inode); + return get_devfs_entry_from_vfs_inode (inode, TRUE); } /* End Function devfs_get_handle_from_inode */ @@ -1737,10 +1777,10 @@ if (de == NULL) return -EINVAL; if (de->namelen >= buflen) return -ENAMETOOLONG; /* Must be first */ - if (de->parent == NULL) return buflen; /* Don't prepend root */ + path[buflen - 1] = '\0'; + if (de->parent == NULL) return buflen - 1; /* Don't prepend root */ pos = buflen - de->namelen - 1; memcpy (path + pos, de->name, de->namelen); - path[buflen - 1] = '\0'; for (de = de->parent; de->parent != NULL; de = de->parent) { if (pos - de->namelen - 1 < 0) return -ENAMETOOLONG; @@ -1999,84 +2039,56 @@ static int __init devfs_setup (char *str) { - while ( (*str != '\0') && !isspace (*str) ) + static struct { -#ifdef CONFIG_DEVFS_DEBUG - if (strncmp (str, "dall", 4) == 0) - { - devfs_debug_init |= DEBUG_ALL; - str += 4; - } - else if (strncmp (str, "dmod", 4) == 0) - { - devfs_debug_init |= DEBUG_MODULE_LOAD; - str += 4; - } - else if (strncmp (str, "dreg", 4) == 0) - { - devfs_debug_init |= DEBUG_REGISTER; - str += 4; - } - else if (strncmp (str, "dunreg", 6) == 0) - { - devfs_debug_init |= DEBUG_UNREGISTER; - str += 6; - } - else if (strncmp (str, "diread", 6) == 0) - { - devfs_debug_init |= DEBUG_I_READ; - str += 6; - } - else if (strncmp (str, "dchange", 7) == 0) - { - devfs_debug_init |= DEBUG_SET_FLAGS; - str += 7; - } - else if (strncmp (str, "diwrite", 7) == 0) - { - devfs_debug_init |= DEBUG_I_WRITE; - str += 7; - } - else if (strncmp (str, "dimknod", 7) == 0) - { - devfs_debug_init |= DEBUG_I_MKNOD; - str += 7; - } - else if (strncmp (str, "dilookup", 8) == 0) - { - devfs_debug_init |= DEBUG_I_LOOKUP; - str += 8; - } - else if (strncmp (str, "diunlink", 8) == 0) - { - devfs_debug_init |= DEBUG_I_UNLINK; - str += 8; - } - else + char *name; + unsigned int mask; + unsigned int *opt; + } devfs_options_tab[] __initdata = + { +#ifdef CONFIG_DEVFS_DEBUG + {"dall", DEBUG_ALL, &devfs_debug_init}, + {"dmod", DEBUG_MODULE_LOAD, &devfs_debug_init}, + {"dreg", DEBUG_REGISTER, &devfs_debug_init}, + {"dunreg", DEBUG_UNREGISTER, &devfs_debug_init}, + {"diread", DEBUG_I_READ, &devfs_debug_init}, + {"dchange", DEBUG_SET_FLAGS, &devfs_debug_init}, + {"diwrite", DEBUG_I_WRITE, &devfs_debug_init}, + {"dimknod", DEBUG_I_MKNOD, &devfs_debug_init}, + {"dilookup", DEBUG_I_LOOKUP, &devfs_debug_init}, + {"diunlink", DEBUG_I_UNLINK, &devfs_debug_init}, #endif /* CONFIG_DEVFS_DEBUG */ - if (strncmp (str, "show", 4) == 0) - { - boot_options |= OPTION_SHOW; - str += 4; - } - else if (strncmp (str, "only", 4) == 0) - { - boot_options |= OPTION_ONLY; - str += 4; - } - else if (strncmp (str, "mount", 5) == 0) + {"show", OPTION_SHOW, &boot_options}, + {"only", OPTION_ONLY, &boot_options}, + {"mount", OPTION_MOUNT, &boot_options}, + }; + + while ( (*str != '\0') && !isspace (*str) ) + { + int i, found = 0, invert = 0; + + if (strncmp (str, "no", 2) == 0) { - boot_options &= ~OPTION_NOMOUNT; - str += 5; + invert = 1; + str += 2; } - else if (strncmp (str, "nomount", 7) == 0) + for (i = 0; i < sizeof (devfs_options_tab); i++) { - boot_options |= OPTION_NOMOUNT; - str += 7; + int len = strlen (devfs_options_tab[i].name); + + if (strncmp (str, devfs_options_tab[i].name, len) == 0) + { + if (invert) + *devfs_options_tab[i].opt &= ~devfs_options_tab[i].mask; + else + *devfs_options_tab[i].opt |= devfs_options_tab[i].mask; + str += len; + found = 1; + break; + } } - else - return 0; - if (*str != ',') return 0; + if (!found) return 0; /* No match */ + if (*str != ',') return 0; /* No more options */ ++str; } return 1; @@ -2103,6 +2115,7 @@ EXPORT_SYMBOL(devfs_get_next_sibling); EXPORT_SYMBOL(devfs_auto_unregister); EXPORT_SYMBOL(devfs_get_unregister_slave); +EXPORT_SYMBOL(devfs_get_name); EXPORT_SYMBOL(devfs_register_chrdev); EXPORT_SYMBOL(devfs_register_blkdev); EXPORT_SYMBOL(devfs_unregister_chrdev); @@ -2125,15 +2138,15 @@ const char *name, unsigned namelen, char buf[STRING_LENGTH]) { - int pos; + int pos = STRING_LENGTH - namelen - 1; if ( !( fs_info->devfsd_event_mask & (1 << DEVFSD_NOTIFY_LOOKUP) ) ) return -ENOENT; if ( is_devfsd_or_child (fs_info) ) return -ENOENT; if (namelen >= STRING_LENGTH) return -ENAMETOOLONG; - memcpy (buf + STRING_LENGTH - namelen - 1, name, namelen); + memcpy (buf + pos, name, namelen); buf[STRING_LENGTH - 1] = '\0'; - pos = devfs_generate_path (parent, buf, STRING_LENGTH - namelen - 1); + if (parent->parent != NULL) pos = devfs_generate_path (parent, buf, pos); if (pos < 0) return pos; buf[STRING_LENGTH - namelen - 2] = '/'; if ( !devfsd_notify_one (buf + pos, DEVFSD_NOTIFY_LOOKUP, 0, @@ -2229,13 +2242,14 @@ static struct inode_operations devfs_iops; static struct inode_operations devfs_dir_iops; static struct file_operations devfs_fops; +static struct file_operations devfs_dir_fops; static struct inode_operations devfs_symlink_iops; static void devfs_read_inode (struct inode *inode) { struct devfs_entry *de; - de = get_devfs_entry_from_vfs_inode (inode); + de = get_devfs_entry_from_vfs_inode (inode, TRUE); if (de == NULL) { printk ("%s: read_inode(%d): VFS inode: %p NO devfs_entry\n", @@ -2273,7 +2287,11 @@ } else if ( S_ISFIFO (de->inode.mode) ) inode->i_fop = &def_fifo_fops; else if ( S_ISREG (de->inode.mode) ) inode->i_size = de->u.fcb.u.file.size; - else if ( S_ISDIR (de->inode.mode) ) inode->i_op = &devfs_dir_iops; + else if ( S_ISDIR (de->inode.mode) ) + { + inode->i_op = &devfs_dir_iops; + inode->i_fop = &devfs_dir_fops; + } else if ( S_ISLNK (de->inode.mode) ) { inode->i_op = &devfs_symlink_iops; @@ -2302,12 +2320,12 @@ if (inode->i_ino < FIRST_INODE) return; index = inode->i_ino - FIRST_INODE; - lock_kernel(); + lock_kernel (); if (index >= fs_info->num_inodes) { printk ("%s: writing inode: %lu for which there is no entry!\n", DEVFS_NAME, inode->i_ino); - unlock_kernel(); + unlock_kernel (); return; } de = fs_info->table[index]; @@ -2327,7 +2345,7 @@ de->inode.atime = inode->i_atime; de->inode.mtime = inode->i_mtime; de->inode.ctime = inode->i_ctime; - unlock_kernel(); + unlock_kernel (); } /* End Function devfs_write_inode */ static int devfs_notify_change (struct dentry *dentry, struct iattr *iattr) @@ -2337,7 +2355,7 @@ struct inode *inode = dentry->d_inode; struct fs_info *fs_info = inode->i_sb->u.generic_sbp; - de = get_devfs_entry_from_vfs_inode (inode); + de = get_devfs_entry_from_vfs_inode (inode, TRUE); if (de == NULL) return -ENODEV; retval = inode_change_ok (inode, iattr); if (retval != 0) return retval; @@ -2399,12 +2417,6 @@ /* File operations for device entries follow */ -static ssize_t devfs_read (struct file *file, char *buf, size_t len, loff_t *ppos) -{ - if ( S_ISDIR (file->f_dentry->d_inode->i_mode) ) return -EISDIR; - return -EINVAL; -} /* End Function devfs_read */ - static int devfs_readdir (struct file *file, void *dirent, filldir_t filldir) { int err, count; @@ -2413,13 +2425,8 @@ struct devfs_entry *parent, *de; struct inode *inode = file->f_dentry->d_inode; - if ( !S_ISDIR (inode->i_mode) ) - { - printk ("%s: readdir(): inode is not a directory\n", DEVFS_NAME); - return -ENOTDIR; - } fs_info = inode->i_sb->u.generic_sbp; - parent = get_devfs_entry_from_vfs_inode (file->f_dentry->d_inode); + parent = get_devfs_entry_from_vfs_inode (file->f_dentry->d_inode, TRUE); if ( (long) file->f_pos < 0 ) return -EINVAL; #ifdef CONFIG_DEVFS_DEBUG if (devfs_debug & DEBUG_F_READDIR) @@ -2473,8 +2480,8 @@ struct devfs_entry *de; struct fs_info *fs_info = inode->i_sb->u.generic_sbp; - lock_kernel(); - de = get_devfs_entry_from_vfs_inode (inode); + lock_kernel (); + de = get_devfs_entry_from_vfs_inode (inode, TRUE); err = -ENODEV; if (de == NULL) goto out; @@ -2482,34 +2489,18 @@ if ( S_ISDIR (de->mode) ) goto out; df = &de->u.fcb; - err = -ENODEV; - if (!de->registered) - goto out; file->private_data = de->info; if ( S_ISBLK (inode->i_mode) ) { file->f_op = &def_blk_fops; if (df->ops) inode->i_bdev->bd_op = df->ops; } - else file->f_op = fops_get((struct file_operations*)df->ops); + else file->f_op = fops_get ( (struct file_operations*) df->ops ); if (file->f_op) err = file->f_op->open ? (*file->f_op->open) (inode, file) : 0; else { /* Fallback to legacy scheme */ - /* - * Do we need it? Richard, could you verify it? - * It can legitimately happen if - * it is a character device and - * df->ops == NULL and - * de->registered is true, - * but AFAICS it can't happen - in devfs_register() we never set - * ->ops to NULL, in unregister() we set ->registered to false, - * in devfs_mknod() we set it to NULL only if ->register is false. - * - * Looks like this fallback is not needed at all. - * AV - */ if ( S_ISCHR (inode->i_mode) ) err = chrdev_open (inode, file); else err = -ENODEV; } @@ -2532,13 +2523,18 @@ devfsd_notify_one (de, DEVFSD_NOTIFY_ASYNC_OPEN, inode->i_mode, current->euid, current->egid, fs_info); out: - unlock_kernel(); + unlock_kernel (); return err; } /* End Function devfs_open */ static struct file_operations devfs_fops = { - read: devfs_read, + open: devfs_open, +}; + +static struct file_operations devfs_dir_fops = +{ + read: generic_read_dir, readdir: devfs_readdir, open: devfs_open, }; @@ -2574,7 +2570,7 @@ struct devfs_entry *de; lock_kernel (); - de = get_devfs_entry_from_vfs_inode (inode); + de = get_devfs_entry_from_vfs_inode (inode, FALSE); #ifdef CONFIG_DEVFS_DEBUG if (devfs_debug & DEBUG_D_IPUT) printk ("%s: d_iput(): dentry: %p inode: %p de: %p de->dentry: %p\n", @@ -2627,7 +2623,7 @@ return 1; } fs_info = inode->i_sb->u.generic_sbp; - de = get_devfs_entry_from_vfs_inode (inode); + de = get_devfs_entry_from_vfs_inode (inode, TRUE); #ifdef CONFIG_DEVFS_DEBUG if (devfs_debug & DEBUG_D_DELETE) printk ("%s: d_delete(): dentry: %p inode: %p devfs_entry: %p\n", @@ -2682,7 +2678,7 @@ { devfs_handle_t parent; - parent = get_devfs_entry_from_vfs_inode (dir); + parent = get_devfs_entry_from_vfs_inode (dir, TRUE); de = search_for_entry_in_dir (parent, dentry->d_name.name, dentry->d_name.len, FALSE); } @@ -2723,12 +2719,6 @@ /* Set up the dentry operations before anything else, to ensure cleaning up on any error */ dentry->d_op = &devfs_dops; - if (dir == NULL) - { - printk ("%s: lookup(): NULL directory inode\n", DEVFS_NAME); - return ERR_PTR (-ENOTDIR); - } - if ( !S_ISDIR (dir->i_mode) ) return ERR_PTR (-ENOTDIR); memset (txt, 0, STRING_LENGTH); memcpy (txt, dentry->d_name.name, (dentry->d_name.len >= STRING_LENGTH) ? @@ -2740,9 +2730,8 @@ #endif fs_info = dir->i_sb->u.generic_sbp; /* First try to get the devfs entry for this directory */ - parent = get_devfs_entry_from_vfs_inode (dir); - if (parent == NULL) return ERR_PTR (-EINVAL); - if (!parent->registered) return ERR_PTR (-ENOENT); + parent = get_devfs_entry_from_vfs_inode (dir, TRUE); + if (parent == NULL) return ERR_PTR (-ENOENT); /* Try to reclaim an existing devfs entry */ de = search_for_entry_in_dir (parent, dentry->d_name.name, dentry->d_name.len, @@ -2845,13 +2834,11 @@ } #endif - if ( !dir || !S_ISDIR (dir->i_mode) ) return -ENOTDIR; - if (!dentry || !dentry->d_inode) return -ENOENT; - de = get_devfs_entry_from_vfs_inode (dentry->d_inode); + de = get_devfs_entry_from_vfs_inode (dentry->d_inode, TRUE); if (de == NULL) return -ENOENT; - if (!de->registered) return -ENOENT; de->registered = FALSE; de->hide = TRUE; + if ( S_ISLNK (de->mode) ) kfree (de->u.symlink.linkname); free_dentries (de); return 0; } /* End Function devfs_unlink */ @@ -2864,17 +2851,15 @@ struct devfs_entry *parent, *de; struct inode *inode; - if ( !dir || !S_ISDIR (dir->i_mode) ) return -ENOTDIR; fs_info = dir->i_sb->u.generic_sbp; /* First try to get the devfs entry for this directory */ - parent = get_devfs_entry_from_vfs_inode (dir); - if (parent == NULL) return -EINVAL; - if (!parent->registered) return -ENOENT; - err = devfs_mk_symlink (parent, dentry->d_name.name, DEVFS_FL_NONE, + parent = get_devfs_entry_from_vfs_inode (dir, TRUE); + if (parent == NULL) return -ENOENT; + err = devfs_do_symlink (parent, dentry->d_name.name, DEVFS_FL_NONE, symname, &de, NULL); #ifdef CONFIG_DEVFS_DEBUG if (devfs_debug & DEBUG_DISABLED) - printk ("%s: symlink(): errcode from : %d\n", + printk ("%s: symlink(): errcode from : %d\n", DEVFS_NAME, err); #endif if (err < 0) return err; @@ -2904,13 +2889,10 @@ struct inode *inode; mode = (mode & ~S_IFMT) | S_IFDIR; - if ( !dir || !S_ISDIR (dir->i_mode) ) return -ENOTDIR; fs_info = dir->i_sb->u.generic_sbp; - /* We are allowed to create the directory */ /* First try to get the devfs entry for this directory */ - parent = get_devfs_entry_from_vfs_inode (dir); - if (parent == NULL) return -EINVAL; - if (!parent->registered) return -ENOENT; + parent = get_devfs_entry_from_vfs_inode (dir, TRUE); + if (parent == NULL) return -ENOENT; /* Try to reclaim an existing devfs entry, create if there isn't one */ de = search_for_entry (parent, dentry->d_name.name, dentry->d_name.len, FALSE, TRUE, &is_new, FALSE); @@ -2920,7 +2902,6 @@ printk ("%s: mkdir(): existing entry\n", DEVFS_NAME); return -EEXIST; } - de->registered = TRUE; de->hide = FALSE; if (!S_ISDIR (de->mode) && !is_new) { @@ -2936,6 +2917,7 @@ de->inode.atime = CURRENT_TIME; de->inode.mtime = CURRENT_TIME; de->inode.ctime = CURRENT_TIME; + de->registered = TRUE; if ( ( inode = get_vfs_inode (dir->i_sb, de, dentry) ) == NULL ) return -ENOMEM; #ifdef CONFIG_DEVFS_DEBUG @@ -2956,13 +2938,10 @@ struct devfs_entry *de, *child; struct inode *inode = dentry->d_inode; - if ( !dir || !S_ISDIR (dir->i_mode) ) return -ENOTDIR; if (dir->i_sb->u.generic_sbp != inode->i_sb->u.generic_sbp) return -EINVAL; - if (inode == dir) return -EPERM; fs_info = dir->i_sb->u.generic_sbp; - de = get_devfs_entry_from_vfs_inode (inode); + de = get_devfs_entry_from_vfs_inode (inode, TRUE); if (de == NULL) return -ENOENT; - if (!de->registered) return -ENOENT; if ( !S_ISDIR (de->mode) ) return -ENOTDIR; for (child = de->u.dir.first; child != NULL; child = child->next) { @@ -2973,8 +2952,8 @@ } } if (has_children) return -ENOTEMPTY; - de->registered = FALSE; de->hide = TRUE; + de->registered = FALSE; free_dentries (de); return 0; } /* End Function devfs_rmdir */ @@ -3000,15 +2979,10 @@ } #endif - if ( !dir || !S_ISDIR (dir->i_mode) ) return -ENOTDIR; fs_info = dir->i_sb->u.generic_sbp; - if ( !S_ISBLK (mode) && !S_ISCHR (mode) && !S_ISFIFO (mode) && - !S_ISSOCK (mode) ) return -EPERM; - /* We are allowed to create the node */ /* First try to get the devfs entry for this directory */ - parent = get_devfs_entry_from_vfs_inode (dir); - if (parent == NULL) return -EINVAL; - if (!parent->registered) return -ENOENT; + parent = get_devfs_entry_from_vfs_inode (dir, TRUE); + if (parent == NULL) return -ENOENT; /* Try to reclaim an existing devfs entry, create if there isn't one */ de = search_for_entry (parent, dentry->d_name.name, dentry->d_name.len, FALSE, TRUE, &is_new, FALSE); @@ -3035,7 +3009,6 @@ de->u.fifo.gid = current->egid; } } - de->registered = TRUE; de->show_unreg = FALSE; de->hide = FALSE; de->inode.mode = mode; @@ -3044,6 +3017,7 @@ de->inode.atime = CURRENT_TIME; de->inode.mtime = CURRENT_TIME; de->inode.ctime = CURRENT_TIME; + de->registered = TRUE; if ( ( inode = get_vfs_inode (dir->i_sb, de, dentry) ) == NULL ) return -ENOMEM; #ifdef CONFIG_DEVFS_DEBUG @@ -3059,32 +3033,31 @@ static int devfs_readlink (struct dentry *dentry, char *buffer, int buflen) { + int err; struct devfs_entry *de; lock_kernel (); - de = get_devfs_entry_from_vfs_inode (dentry->d_inode); + de = get_devfs_entry_from_vfs_inode (dentry->d_inode, TRUE); + err = de ? vfs_readlink (dentry, buffer, buflen, + de->u.symlink.linkname) : -ENODEV; unlock_kernel (); - return vfs_readlink (dentry, buffer, buflen, de->u.symlink.linkname); + return err; } /* End Function devfs_readlink */ static int devfs_follow_link (struct dentry *dentry, struct nameidata *nd) { + int err; struct devfs_entry *de; lock_kernel (); - de = get_devfs_entry_from_vfs_inode (dentry->d_inode); + de = get_devfs_entry_from_vfs_inode (dentry->d_inode, TRUE); + err = de ? vfs_follow_link (nd, de->u.symlink.linkname) : -ENODEV; unlock_kernel (); - return vfs_follow_link (nd, de->u.symlink.linkname); + return err; } /* End Function devfs_follow_link */ static struct inode_operations devfs_iops = { - link: devfs_link, - unlink: devfs_unlink, - symlink: devfs_symlink, - mkdir: devfs_mkdir, - rmdir: devfs_rmdir, - mknod: devfs_mknod, setattr: devfs_notify_change, }; @@ -3151,17 +3124,17 @@ int done = FALSE; int ival; loff_t pos, devname_offset, tlen, rpos; - struct devfsd_notify_struct info; struct devfsd_buf_entry *entry; struct fs_info *fs_info = file->f_dentry->d_inode->i_sb->u.generic_sbp; + struct devfsd_notify_struct *info = fs_info->devfsd_info; DECLARE_WAITQUEUE (wait, current); /* Can't seek (pread) on this device */ if (ppos != &file->f_pos) return -ESPIPE; /* Verify the task has grabbed the queue */ if (fs_info->devfsd_task != current) return -EPERM; - info.major = 0; - info.minor = 0; + info->major = 0; + info->minor = 0; /* Block for a new entry */ add_wait_queue (&fs_info->devfsd_wait_queue, &wait); current->state = TASK_INTERRUPTIBLE; @@ -3184,18 +3157,18 @@ /* Now play with the data */ ival = atomic_read (&fs_info->devfsd_overrun_count); if (ival > 0) atomic_sub (ival, &fs_info->devfsd_overrun_count); - info.overrun_count = ival; + info->overrun_count = ival; entry = (struct devfsd_buf_entry *) fs_info->devfsd_buffer + fs_info->devfsd_buf_out; - info.type = entry->type; - info.mode = entry->mode; - info.uid = entry->uid; - info.gid = entry->gid; + info->type = entry->type; + info->mode = entry->mode; + info->uid = entry->uid; + info->gid = entry->gid; if (entry->type == DEVFSD_NOTIFY_LOOKUP) { - info.namelen = strlen (entry->data); + info->namelen = strlen (entry->data); pos = 0; - memcpy (info.devname, entry->data, info.namelen + 1); + memcpy (info->devname, entry->data, info->namelen + 1); } else { @@ -3203,22 +3176,22 @@ if ( S_ISCHR (de->mode) || S_ISBLK (de->mode) || S_ISREG (de->mode) ) { - info.major = de->u.fcb.u.device.major; - info.minor = de->u.fcb.u.device.minor; + info->major = de->u.fcb.u.device.major; + info->minor = de->u.fcb.u.device.minor; } - pos = devfs_generate_path (de, info.devname, DEVFS_PATHLEN); + pos = devfs_generate_path (de, info->devname, DEVFS_PATHLEN); if (pos < 0) return pos; - info.namelen = DEVFS_PATHLEN - pos - 1; - if (info.mode == 0) info.mode = de->mode; + info->namelen = DEVFS_PATHLEN - pos - 1; + if (info->mode == 0) info->mode = de->mode; } - devname_offset = info.devname - (char *) &info; + devname_offset = info->devname - (char *) info; rpos = *ppos; if (rpos < devname_offset) { /* Copy parts of the header */ tlen = devname_offset - rpos; if (tlen > len) tlen = len; - if ( copy_to_user (buf, (char *) &info + rpos, tlen) ) + if ( copy_to_user (buf, (char *) info + rpos, tlen) ) { return -EFAULT; } @@ -3229,10 +3202,10 @@ if ( (rpos >= devname_offset) && (len > 0) ) { /* Copy the name */ - tlen = info.namelen + 1; + tlen = info->namelen + 1; if (tlen > len) tlen = len; else done = TRUE; - if ( copy_to_user (buf, info.devname + pos + rpos - devname_offset, + if ( copy_to_user (buf, info->devname + pos + rpos - devname_offset, tlen) ) { return -EFAULT; @@ -3257,6 +3230,7 @@ { int ival; struct fs_info *fs_info = inode->i_sb->u.generic_sbp; + static spinlock_t lock = SPIN_LOCK_UNLOCKED; switch (cmd) { @@ -3270,30 +3244,21 @@ doesn't matter who gets in first, as long as only one gets it */ if (fs_info->devfsd_task == NULL) { -#ifdef CONFIG_SMP - /* Looks like no-one has it: check again and grab, with interrupts - disabled */ - __cli (); - if (fs_info->devfsd_task == NULL) -#endif + if ( !spin_trylock (&lock) ) return -EBUSY; + fs_info->devfsd_task = current; + spin_unlock (&lock); + fs_info->devfsd_file = file; + fs_info->devfsd_buffer = (void *) __get_free_page (GFP_KERNEL); + fs_info->devfsd_info = kmalloc (sizeof *fs_info->devfsd_info, + GFP_KERNEL); + if (!fs_info->devfsd_buffer || !fs_info->devfsd_info) { - fs_info->devfsd_event_mask = 0; /* Temporary disable */ - fs_info->devfsd_task = current; + devfsd_close (inode, file); + return -ENOMEM; } -#ifdef CONFIG_SMP - __sti (); -#endif - } - /* Verify the task has grabbed the queue */ - if (fs_info->devfsd_task != current) return -EBUSY; - fs_info->devfsd_file = file; - fs_info->devfsd_buffer = (void *) __get_free_page (GFP_KERNEL); - if (fs_info->devfsd_buffer == NULL) - { - devfsd_close (inode, file); - return -ENOMEM; + fs_info->devfsd_buf_out = fs_info->devfsd_buf_in; } - fs_info->devfsd_buf_out = fs_info->devfsd_buf_in; + else if (fs_info->devfsd_task != current) return -EBUSY; fs_info->devfsd_event_mask = arg; /* Let the masses come forth */ break; case DEVFSDIOC_RELEASE_EVENT_QUEUE: @@ -3314,25 +3279,26 @@ static int devfsd_close (struct inode *inode, struct file *file) { + unsigned long flags; struct fs_info *fs_info = inode->i_sb->u.generic_sbp; - lock_kernel(); - if (fs_info->devfsd_file != file) - { - unlock_kernel(); - return 0; - } + if (fs_info->devfsd_file != file) return 0; fs_info->devfsd_event_mask = 0; fs_info->devfsd_file = NULL; + spin_lock_irqsave (&fs_info->devfsd_buffer_lock, flags); if (fs_info->devfsd_buffer) { - while (fs_info->devfsd_buffer_in_use) schedule (); free_page ( (unsigned long) fs_info->devfsd_buffer ); + fs_info->devfsd_buffer = NULL; + } + if (fs_info->devfsd_info) + { + kfree (fs_info->devfsd_info); + fs_info->devfsd_info = NULL; } - fs_info->devfsd_buffer = NULL; + spin_unlock_irqrestore (&fs_info->devfsd_buffer_lock, flags); fs_info->devfsd_task = NULL; wake_up (&fs_info->revalidate_wait_queue); - unlock_kernel(); return 0; } /* End Function devfsd_close */ @@ -3362,7 +3328,7 @@ { int err; - if ( (boot_options & OPTION_NOMOUNT) ) return; + if ( !(boot_options & OPTION_MOUNT) ) return; err = do_mount ("none", "/dev", "devfs", 0, ""); if (err == 0) printk ("Mounted devfs on /dev\n"); else printk ("Warning: unable to mount devfs, err: %d\n", err); diff -u --recursive --new-file v2.4.5/linux/fs/devfs/util.c linux/fs/devfs/util.c --- v2.4.5/linux/fs/devfs/util.c Mon Oct 16 12:58:51 2000 +++ linux/fs/devfs/util.c Tue Jun 12 10:57:46 2001 @@ -1,6 +1,6 @@ /* devfs (Device FileSystem) utilities. - Copyright (C) 1999-2000 Richard Gooch + Copyright (C) 1999-2001 Richard Gooch This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -33,6 +33,8 @@ 20000622 Richard Gooch Took account of interface change to . Took account of interface change to . + 20010519 Richard Gooch + Documentation cleanup. */ #include #include @@ -132,9 +134,10 @@ /** * devfs_register_series - Register a sequence of device entries. - * @dir: The handle to the parent devfs directory entry. If this is %NULL the - * new names are relative to the root of the devfs. + * @dir: The handle to the parent devfs directory entry. If this is %NULL + * the new names are relative to the root of the devfs. * @format: The printf-style format string. A single "\%u" is allowed. + * @num_entries: The number of entries to register. * @flags: A set of bitwise-ORed flags (DEVFS_FL_*). * @major: The major number. Not needed for regular files. * @minor_start: The starting minor number. Not needed for regular files. @@ -142,9 +145,9 @@ * @ops: The &file_operations or &block_device_operations structure. * This must not be externally deallocated. * @info: An arbitrary pointer which will be written to the private_data - * field of the &file structure passed to the device driver. You can set - * this to whatever you like, and change it once the file is opened (the next - * file opened will not see this change). + * field of the &file structure passed to the device driver. You + * can set this to whatever you like, and change it once the file + * is opened (the next file opened will not see this change). */ void devfs_register_series (devfs_handle_t dir, const char *format, diff -u --recursive --new-file v2.4.5/linux/fs/dquot.c linux/fs/dquot.c --- v2.4.5/linux/fs/dquot.c Sun May 20 11:32:11 2001 +++ linux/fs/dquot.c Tue Jun 12 16:03:27 2001 @@ -325,7 +325,7 @@ memset(&dquot->dq_dqb, 0, sizeof(struct dqblk)); } -void invalidate_dquots(kdev_t dev, short type) +static void invalidate_dquots(kdev_t dev, short type) { struct dquot *dquot, *next; int need_restart; @@ -651,8 +651,6 @@ { int cnt; - if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))) - return 0; if (is_quotafile(inode)) return 0; if (type != -1) @@ -1022,9 +1020,6 @@ unsigned int id = 0; short cnt; - if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode) && - !S_ISLNK(inode->i_mode)) - return; lock_kernel(); /* We don't want to have quotas on quota files - nasty deadlocks possible */ if (is_quotafile(inode)) { @@ -1388,7 +1383,7 @@ } /* Function in inode.c - remove pointers to dquots in icache */ -extern void remove_dquot_ref(kdev_t, short); +extern void remove_dquot_ref(struct super_block *, short); /* * Turn quota off on a device. type == -1 ==> quotaoff for all types (umount) @@ -1413,7 +1408,7 @@ reset_enable_flags(dqopt, cnt); /* Note: these are blocking operations */ - remove_dquot_ref(sb->s_dev, cnt); + remove_dquot_ref(sb, cnt); invalidate_dquots(sb->s_dev, cnt); /* Wait for any pending IO - remove me as soon as invalidate is more polite */ diff -u --recursive --new-file v2.4.5/linux/fs/ext2/dir.c linux/fs/ext2/dir.c --- v2.4.5/linux/fs/ext2/dir.c Fri Dec 8 17:35:54 2000 +++ linux/fs/ext2/dir.c Wed Jun 20 11:40:14 2001 @@ -16,167 +16,567 @@ * * Big-endian to little-endian byte-swapping/bitmaps by * David S. Miller (davem@caip.rutgers.edu), 1995 + * + * All code that works with directory layout had been switched to pagecache + * and moved here. AV */ #include #include +#include -static unsigned char ext2_filetype_table[] = { - DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK -}; +typedef struct ext2_dir_entry_2 ext2_dirent; -static int ext2_readdir(struct file *, void *, filldir_t); +/* + * ext2 uses block-sized chunks. Arguably, sector-sized ones would be + * more robust, but we have what we have + */ +static inline unsigned ext2_chunk_size(struct inode *inode) +{ + return inode->i_sb->s_blocksize; +} -struct file_operations ext2_dir_operations = { - read: generic_read_dir, - readdir: ext2_readdir, - ioctl: ext2_ioctl, - fsync: ext2_sync_file, +static inline void ext2_put_page(struct page *page) +{ + kunmap(page); + page_cache_release(page); +} + +static inline unsigned long dir_pages(struct inode *inode) +{ + return (inode->i_size+PAGE_CACHE_SIZE-1)>>PAGE_CACHE_SHIFT; +} + +static int ext2_commit_chunk(struct page *page, unsigned from, unsigned to) +{ + struct inode *dir = page->mapping->host; + int err = 0; + dir->i_version = ++event; + page->mapping->a_ops->commit_write(NULL, page, from, to); + if (IS_SYNC(dir)) + err = waitfor_one_page(page); + return err; +} + +static void ext2_check_page(struct page *page) +{ + struct inode *dir = page->mapping->host; + struct super_block *sb = dir->i_sb; + unsigned chunk_size = ext2_chunk_size(dir); + char *kaddr = page_address(page); + u32 max_inumber = le32_to_cpu(sb->u.ext2_sb.s_es->s_inodes_count); + unsigned offs, rec_len; + unsigned limit = PAGE_CACHE_SIZE; + ext2_dirent *p; + char *error; + + if ((dir->i_size >> PAGE_CACHE_SHIFT) == page->index) { + limit = dir->i_size & ~PAGE_CACHE_MASK; + if (limit & (chunk_size - 1)) + goto Ebadsize; + for (offs = limit; offsrec_len = cpu_to_le16(chunk_size); + } + if (!limit) + goto out; + } + for (offs = 0; offs <= limit - EXT2_DIR_REC_LEN(1); offs += rec_len) { + p = (ext2_dirent *)(kaddr + offs); + rec_len = le16_to_cpu(p->rec_len); + + if (rec_len < EXT2_DIR_REC_LEN(1)) + goto Eshort; + if (rec_len & 3) + goto Ealign; + if (rec_len < EXT2_DIR_REC_LEN(p->name_len)) + goto Enamelen; + if (((offs + rec_len - 1) ^ offs) & ~(chunk_size-1)) + goto Espan; + if (le32_to_cpu(p->inode) > max_inumber) + goto Einumber; + } + if (offs != limit) + goto Eend; +out: + SetPageChecked(page); + return; + + /* Too bad, we had an error */ + +Ebadsize: + ext2_error(sb, "ext2_check_page", + "size of directory #%lu is not a multiple of chunk size", + dir->i_ino + ); + goto fail; +Eshort: + error = "rec_len is smaller than minimal"; + goto bad_entry; +Ealign: + error = "unaligned directory entry"; + goto bad_entry; +Enamelen: + error = "rec_len is too small for name_len"; + goto bad_entry; +Espan: + error = "directory entry across blocks"; + goto bad_entry; +Einumber: + error = "inode out of bounds"; +bad_entry: + ext2_error (sb, "ext2_check_page", "bad entry in directory #%lu: %s - " + "offset=%lu, inode=%lu, rec_len=%d, name_len=%d", + dir->i_ino, error, (page->index<inode), + rec_len, p->name_len); + goto fail; +Eend: + p = (ext2_dirent *)(kaddr + offs); + ext2_error (sb, "ext2_check_page", + "entry in directory #%lu spans the page boundary" + "offset=%lu, inode=%lu", + dir->i_ino, (page->index<inode)); +fail: + SetPageChecked(page); + SetPageError(page); +} + +static struct page * ext2_get_page(struct inode *dir, unsigned long n) +{ + struct address_space *mapping = dir->i_mapping; + struct page *page = read_cache_page(mapping, n, + (filler_t*)mapping->a_ops->readpage, NULL); + if (!IS_ERR(page)) { + wait_on_page(page); + kmap(page); + if (!Page_Uptodate(page)) + goto fail; + if (!PageChecked(page)) + ext2_check_page(page); + if (PageError(page)) + goto fail; + } + return page; + +fail: + ext2_put_page(page); + return ERR_PTR(-EIO); +} + +/* + * NOTE! unlike strncmp, ext2_match returns 1 for success, 0 for failure. + * + * len <= EXT2_NAME_LEN and de != NULL are guaranteed by caller. + */ +static inline int ext2_match (int len, const char * const name, + struct ext2_dir_entry_2 * de) +{ + if (len != de->name_len) + return 0; + if (!de->inode) + return 0; + return !memcmp(name, de->name, len); +} + +/* + * p is at least 6 bytes before the end of page + */ +static inline ext2_dirent *ext2_next_entry(ext2_dirent *p) +{ + return (ext2_dirent *)((char*)p + le16_to_cpu(p->rec_len)); +} + +static inline unsigned +ext2_validate_entry(char *base, unsigned offset, unsigned mask) +{ + ext2_dirent *de = (ext2_dirent*)(base + offset); + ext2_dirent *p = (ext2_dirent*)(base + (offset&mask)); + while ((char*)p < (char*)de) + p = ext2_next_entry(p); + return (char *)p - base; +} + +static unsigned char ext2_filetype_table[EXT2_FT_MAX] = { + [EXT2_FT_UNKNOWN] DT_UNKNOWN, + [EXT2_FT_REG_FILE] DT_REG, + [EXT2_FT_DIR] DT_DIR, + [EXT2_FT_CHRDEV] DT_CHR, + [EXT2_FT_BLKDEV] DT_BLK, + [EXT2_FT_FIFO] DT_FIFO, + [EXT2_FT_SOCK] DT_SOCK, + [EXT2_FT_SYMLINK] DT_LNK, }; -int ext2_check_dir_entry (const char * function, struct inode * dir, - struct ext2_dir_entry_2 * de, - struct buffer_head * bh, - unsigned long offset) -{ - const char * error_msg = NULL; - - if (le16_to_cpu(de->rec_len) < EXT2_DIR_REC_LEN(1)) - error_msg = "rec_len is smaller than minimal"; - else if (le16_to_cpu(de->rec_len) % 4 != 0) - error_msg = "rec_len % 4 != 0"; - else if (le16_to_cpu(de->rec_len) < EXT2_DIR_REC_LEN(de->name_len)) - error_msg = "rec_len is too small for name_len"; - else if (dir && ((char *) de - bh->b_data) + le16_to_cpu(de->rec_len) > - dir->i_sb->s_blocksize) - error_msg = "directory entry across blocks"; - else if (dir && le32_to_cpu(de->inode) > le32_to_cpu(dir->i_sb->u.ext2_sb.s_es->s_inodes_count)) - error_msg = "inode out of bounds"; - - if (error_msg != NULL) - ext2_error (dir->i_sb, function, "bad entry in directory #%lu: %s - " - "offset=%lu, inode=%lu, rec_len=%d, name_len=%d", - dir->i_ino, error_msg, offset, - (unsigned long) le32_to_cpu(de->inode), - le16_to_cpu(de->rec_len), de->name_len); - return error_msg == NULL ? 1 : 0; -} - -static int ext2_readdir(struct file * filp, - void * dirent, filldir_t filldir) -{ - int error = 0; - unsigned long offset, blk; - int i, num, stored; - struct buffer_head * bh, * tmp, * bha[16]; - struct ext2_dir_entry_2 * de; - struct super_block * sb; - int err; - struct inode *inode = filp->f_dentry->d_inode; +#define S_SHIFT 12 +static unsigned char ext2_type_by_mode[S_IFMT >> S_SHIFT] = { + [S_IFREG >> S_SHIFT] EXT2_FT_REG_FILE, + [S_IFDIR >> S_SHIFT] EXT2_FT_DIR, + [S_IFCHR >> S_SHIFT] EXT2_FT_CHRDEV, + [S_IFBLK >> S_SHIFT] EXT2_FT_BLKDEV, + [S_IFIFO >> S_SHIFT] EXT2_FT_FIFO, + [S_IFSOCK >> S_SHIFT] EXT2_FT_SOCK, + [S_IFLNK >> S_SHIFT] EXT2_FT_SYMLINK, +}; + +static inline void ext2_set_de_type(ext2_dirent *de, struct inode *inode) +{ + mode_t mode = inode->i_mode; + if (EXT2_HAS_INCOMPAT_FEATURE(inode->i_sb, EXT2_FEATURE_INCOMPAT_FILETYPE)) + de->file_type = ext2_type_by_mode[(mode & S_IFMT)>>S_SHIFT]; + else + de->file_type = 0; +} - sb = inode->i_sb; +static int +ext2_readdir (struct file * filp, void * dirent, filldir_t filldir) +{ + loff_t pos = filp->f_pos; + struct inode *inode = filp->f_dentry->d_inode; + struct super_block *sb = inode->i_sb; + unsigned offset = pos & ~PAGE_CACHE_MASK; + unsigned long n = pos >> PAGE_CACHE_SHIFT; + unsigned long npages = dir_pages(inode); + unsigned chunk_mask = ~(ext2_chunk_size(inode)-1); + unsigned char *types = NULL; + int need_revalidate = (filp->f_version != inode->i_version); + + if (pos > inode->i_size - EXT2_DIR_REC_LEN(1)) + goto done; + + if (EXT2_HAS_INCOMPAT_FEATURE(sb, EXT2_FEATURE_INCOMPAT_FILETYPE)) + types = ext2_filetype_table; + + for ( ; n < npages; n++, offset = 0) { + char *kaddr, *limit; + ext2_dirent *de; + struct page *page = ext2_get_page(inode, n); - stored = 0; - bh = NULL; - offset = filp->f_pos & (sb->s_blocksize - 1); - - while (!error && !stored && filp->f_pos < inode->i_size) { - blk = (filp->f_pos) >> EXT2_BLOCK_SIZE_BITS(sb); - bh = ext2_bread (inode, blk, 0, &err); - if (!bh) { - ext2_error (sb, "ext2_readdir", - "directory #%lu contains a hole at offset %lu", - inode->i_ino, (unsigned long)filp->f_pos); - filp->f_pos += sb->s_blocksize - offset; + if (IS_ERR(page)) continue; + kaddr = page_address(page); + if (need_revalidate) { + offset = ext2_validate_entry(kaddr, offset, chunk_mask); + need_revalidate = 0; } + de = (ext2_dirent *)(kaddr+offset); + limit = kaddr + PAGE_CACHE_SIZE - EXT2_DIR_REC_LEN(1); + for ( ;(char*)de <= limit; de = ext2_next_entry(de)) + if (de->inode) { + int over; + unsigned char d_type = DT_UNKNOWN; - /* - * Do the readahead - */ - if (!offset) { - for (i = 16 >> (EXT2_BLOCK_SIZE_BITS(sb) - 9), num = 0; - i > 0; i--) { - tmp = ext2_getblk (inode, ++blk, 0, &err); - if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp)) - bha[num++] = tmp; - else - brelse (tmp); - } - if (num) { - ll_rw_block (READA, num, bha); - for (i = 0; i < num; i++) - brelse (bha[i]); - } - } - -revalidate: - /* If the dir block has changed since the last call to - * readdir(2), then we might be pointing to an invalid - * dirent right now. Scan from the start of the block - * to make sure. */ - if (filp->f_version != inode->i_version) { - for (i = 0; i < sb->s_blocksize && i < offset; ) { - de = (struct ext2_dir_entry_2 *) - (bh->b_data + i); - /* It's too expensive to do a full - * dirent test each time round this - * loop, but we do have to test at - * least that it is non-zero. A - * failure will be detected in the - * dirent test below. */ - if (le16_to_cpu(de->rec_len) < EXT2_DIR_REC_LEN(1)) - break; - i += le16_to_cpu(de->rec_len); + if (types && de->file_type < EXT2_FT_MAX) + d_type = types[de->file_type]; + + offset = (char *)de - kaddr; + over = filldir(dirent, de->name, de->name_len, + (n<inode), d_type); + if (over) { + ext2_put_page(page); + goto done; + } } - offset = i; - filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1)) - | offset; - filp->f_version = inode->i_version; + ext2_put_page(page); + } + +done: + filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset; + filp->f_version = inode->i_version; + UPDATE_ATIME(inode); + return 0; +} + +/* + * ext2_find_entry() + * + * finds an entry in the specified directory with the wanted name. It + * returns the page in which the entry was found, and the entry itself + * (as a parameter - res_dir). Page is returned mapped and unlocked. + * Entry is guaranteed to be valid. + */ +struct ext2_dir_entry_2 * ext2_find_entry (struct inode * dir, + struct dentry *dentry, struct page ** res_page) +{ + const char *name = dentry->d_name.name; + int namelen = dentry->d_name.len; + unsigned reclen = EXT2_DIR_REC_LEN(namelen); + unsigned long n; + unsigned long npages = dir_pages(dir); + struct page *page = NULL; + ext2_dirent * de; + + /* OFFSET_CACHE */ + *res_page = NULL; + + for (n = 0; n < npages; n++) { + char *kaddr; + page = ext2_get_page(dir, n); + if (IS_ERR(page)) + continue; + + kaddr = page_address(page); + de = (ext2_dirent *) kaddr; + kaddr += PAGE_CACHE_SIZE - reclen; + for ( ; (char *) de <= kaddr ; de = ext2_next_entry(de)) + if (ext2_match (namelen, name, de)) + goto found; + ext2_put_page(page); + } + return NULL; + +found: + *res_page = page; + return de; +} + +struct ext2_dir_entry_2 * ext2_dotdot (struct inode *dir, struct page **p) +{ + struct page *page = ext2_get_page(dir, 0); + ext2_dirent *de = NULL; + + if (!IS_ERR(page)) { + de = ext2_next_entry((ext2_dirent *) page_address(page)); + *p = page; + } + return de; +} + +ino_t ext2_inode_by_name(struct inode * dir, struct dentry *dentry) +{ + ino_t res = 0; + struct ext2_dir_entry_2 * de; + struct page *page; + + de = ext2_find_entry (dir, dentry, &page); + if (de) { + res = le32_to_cpu(de->inode); + kunmap(page); + page_cache_release(page); + } + return res; +} + +/* Releases the page */ +void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de, + struct page *page, struct inode *inode) +{ + unsigned from = (char *)de-(char*)page_address(page); + unsigned to = from + le16_to_cpu(de->rec_len); + int err; + + lock_page(page); + err = page->mapping->a_ops->prepare_write(NULL, page, from, to); + if (err) + BUG(); + de->inode = cpu_to_le32(inode->i_ino); + ext2_set_de_type (de, inode); + err = ext2_commit_chunk(page, from, to); + UnlockPage(page); + ext2_put_page(page); + dir->i_mtime = dir->i_ctime = CURRENT_TIME; + mark_inode_dirty(dir); +} + +/* + * Parent is locked. + */ +int ext2_add_link (struct dentry *dentry, struct inode *inode) +{ + struct inode *dir = dentry->d_parent->d_inode; + const char *name = dentry->d_name.name; + int namelen = dentry->d_name.len; + unsigned reclen = EXT2_DIR_REC_LEN(namelen); + unsigned short rec_len, name_len; + struct page *page = NULL; + ext2_dirent * de; + unsigned long npages = dir_pages(dir); + unsigned long n; + char *kaddr; + unsigned from, to; + int err; + + /* We take care of directory expansion in the same loop */ + for (n = 0; n <= npages; n++) { + page = ext2_get_page(dir, n); + err = PTR_ERR(page); + if (IS_ERR(page)) + goto out; + kaddr = page_address(page); + de = (ext2_dirent *)kaddr; + kaddr += PAGE_CACHE_SIZE - reclen; + while ((char *)de <= kaddr) { + err = -EEXIST; + if (ext2_match (namelen, name, de)) + goto out_page; + name_len = EXT2_DIR_REC_LEN(de->name_len); + rec_len = le16_to_cpu(de->rec_len); + if (!de->inode && rec_len >= reclen) + goto got_it; + if (rec_len >= name_len + reclen) + goto got_it; + de = (ext2_dirent *) ((char *) de + rec_len); } - - while (!error && filp->f_pos < inode->i_size - && offset < sb->s_blocksize) { - de = (struct ext2_dir_entry_2 *) (bh->b_data + offset); - if (!ext2_check_dir_entry ("ext2_readdir", inode, de, - bh, offset)) { - /* On error, skip the f_pos to the - next block. */ - filp->f_pos = (filp->f_pos | (sb->s_blocksize - 1)) - + 1; - brelse (bh); - return stored; - } - offset += le16_to_cpu(de->rec_len); - if (le32_to_cpu(de->inode)) { - /* We might block in the next section - * if the data destination is - * currently swapped out. So, use a - * version stamp to detect whether or - * not the directory has been modified - * during the copy operation. - */ - unsigned long version = filp->f_version; - unsigned char d_type = DT_UNKNOWN; + ext2_put_page(page); + } + BUG(); + return -EINVAL; - if (EXT2_HAS_INCOMPAT_FEATURE(sb, EXT2_FEATURE_INCOMPAT_FILETYPE) - && de->file_type < EXT2_FT_MAX) - d_type = ext2_filetype_table[de->file_type]; - error = filldir(dirent, de->name, - de->name_len, - filp->f_pos, le32_to_cpu(de->inode), - d_type); - if (error) - break; - if (version != filp->f_version) - goto revalidate; - stored ++; +got_it: + from = (char*)de - (char*)page_address(page); + to = from + rec_len; + lock_page(page); + err = page->mapping->a_ops->prepare_write(NULL, page, from, to); + if (err) + goto out_unlock; + if (de->inode) { + ext2_dirent *de1 = (ext2_dirent *) ((char *) de + name_len); + de1->rec_len = cpu_to_le16(rec_len - name_len); + de->rec_len = cpu_to_le16(name_len); + de = de1; + } + de->name_len = namelen; + memcpy (de->name, name, namelen); + de->inode = cpu_to_le32(inode->i_ino); + ext2_set_de_type (de, inode); + err = ext2_commit_chunk(page, from, to); + dir->i_mtime = dir->i_ctime = CURRENT_TIME; + mark_inode_dirty(dir); + /* OFFSET_CACHE */ +out_unlock: + UnlockPage(page); +out_page: + ext2_put_page(page); +out: + return err; +} + +/* + * ext2_delete_entry deletes a directory entry by merging it with the + * previous entry. Page is up-to-date. Releases the page. + */ +int ext2_delete_entry (struct ext2_dir_entry_2 * dir, struct page * page ) +{ + struct address_space *mapping = page->mapping; + struct inode *inode = mapping->host; + char *kaddr = page_address(page); + unsigned from = ((char*)dir - kaddr) & ~(ext2_chunk_size(inode)-1); + unsigned to = ((char*)dir - kaddr) + le16_to_cpu(dir->rec_len); + ext2_dirent * pde = NULL; + ext2_dirent * de = (ext2_dirent *) (kaddr + from); + int err; + + while ((char*)de < (char*)dir) { + pde = de; + de = ext2_next_entry(de); + } + if (pde) + from = (char*)pde - (char*)page_address(page); + lock_page(page); + err = mapping->a_ops->prepare_write(NULL, page, from, to); + if (err) + BUG(); + if (pde) + pde->rec_len = cpu_to_le16(to-from); + dir->inode = 0; + err = ext2_commit_chunk(page, from, to); + UnlockPage(page); + ext2_put_page(page); + inode->i_ctime = inode->i_mtime = CURRENT_TIME; + mark_inode_dirty(inode); + return err; +} + +/* + * Set the first fragment of directory. + */ +int ext2_make_empty(struct inode *inode, struct inode *parent) +{ + struct address_space *mapping = inode->i_mapping; + struct page *page = grab_cache_page(mapping, 0); + unsigned chunk_size = ext2_chunk_size(inode); + struct ext2_dir_entry_2 * de; + char *base; + int err; + + if (!page) + return -ENOMEM; + err = mapping->a_ops->prepare_write(NULL, page, 0, chunk_size); + if (err) + goto fail; + + base = page_address(page); + + de = (struct ext2_dir_entry_2 *) base; + de->name_len = 1; + de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(1)); + memcpy (de->name, ".\0\0", 4); + de->inode = cpu_to_le32(inode->i_ino); + ext2_set_de_type (de, inode); + + de = (struct ext2_dir_entry_2 *) (base + EXT2_DIR_REC_LEN(1)); + de->name_len = 2; + de->rec_len = cpu_to_le16(chunk_size - EXT2_DIR_REC_LEN(1)); + de->inode = cpu_to_le32(parent->i_ino); + memcpy (de->name, "..\0", 4); + ext2_set_de_type (de, inode); + + err = ext2_commit_chunk(page, 0, chunk_size); +fail: + UnlockPage(page); + page_cache_release(page); + return err; +} + +/* + * routine to check that the specified directory is empty (for rmdir) + */ +int ext2_empty_dir (struct inode * inode) +{ + struct page *page = NULL; + unsigned long i, npages = dir_pages(inode); + + for (i = 0; i < npages; i++) { + char *kaddr; + ext2_dirent * de; + page = ext2_get_page(inode, i); + + if (IS_ERR(page)) + continue; + + kaddr = page_address(page); + de = (ext2_dirent *)kaddr; + kaddr += PAGE_CACHE_SIZE-EXT2_DIR_REC_LEN(1); + + while ((char *)de <= kaddr) { + if (de->inode != 0) { + /* check for . and .. */ + if (de->name[0] != '.') + goto not_empty; + if (de->name_len > 2) + goto not_empty; + if (de->name_len < 2) { + if (de->inode != + cpu_to_le32(inode->i_ino)) + goto not_empty; + } else if (de->name[1] != '.') + goto not_empty; } - filp->f_pos += le16_to_cpu(de->rec_len); + de = ext2_next_entry(de); } - offset = 0; - brelse (bh); + ext2_put_page(page); } - UPDATE_ATIME(inode); + return 1; + +not_empty: + ext2_put_page(page); return 0; } + +struct file_operations ext2_dir_operations = { + read: generic_read_dir, + readdir: ext2_readdir, + fsync: ext2_sync_file, +}; diff -u --recursive --new-file v2.4.5/linux/fs/ext2/ialloc.c linux/fs/ext2/ialloc.c --- v2.4.5/linux/fs/ext2/ialloc.c Fri Mar 23 12:15:07 2001 +++ linux/fs/ext2/ialloc.c Tue Jul 3 07:58:47 2001 @@ -194,15 +194,21 @@ * Note: we must free any quota before locking the superblock, * as writing the quota to disk may need the lock as well. */ + DQUOT_INIT(inode); DQUOT_FREE_INODE(sb, inode); DQUOT_DROP(inode); lock_super (sb); es = sb->u.ext2_sb.s_es; - if (ino < EXT2_FIRST_INO(sb) || + is_directory = S_ISDIR(inode->i_mode); + + /* Do this BEFORE marking the inode not in use or returning an error */ + clear_inode (inode); + + if (ino < EXT2_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) { - ext2_error (sb, "free_inode", - "reserved inode or nonexistent inode"); + ext2_error (sb, "ext2_free_inode", + "reserved or nonexistent inode %lu", ino); goto error_return; } block_group = (ino - 1) / EXT2_INODES_PER_GROUP(sb); @@ -210,13 +216,8 @@ bitmap_nr = load_inode_bitmap (sb, block_group); if (bitmap_nr < 0) goto error_return; - - bh = sb->u.ext2_sb.s_inode_bitmap[bitmap_nr]; - is_directory = S_ISDIR(inode->i_mode); - - /* Do this BEFORE marking the inode not in use */ - clear_inode (inode); + bh = sb->u.ext2_sb.s_inode_bitmap[bitmap_nr]; /* Ok, now we can actually update the inode bitmaps.. */ if (!ext2_clear_bit (bit, bh->b_data)) @@ -417,7 +418,6 @@ cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) - 1); mark_buffer_dirty(sb->u.ext2_sb.s_sbh); sb->s_dirt = 1; - inode->i_mode = mode; inode->i_uid = current->fsuid; if (test_opt (sb, GRPID)) inode->i_gid = dir->i_gid; @@ -427,6 +427,7 @@ mode |= S_ISGID; } else inode->i_gid = current->fsgid; + inode->i_mode = mode; inode->i_ino = j; inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size (for stat), not the fs block size */ diff -u --recursive --new-file v2.4.5/linux/fs/ext2/inode.c linux/fs/ext2/inode.c --- v2.4.5/linux/fs/ext2/inode.c Thu Apr 26 10:44:10 2001 +++ linux/fs/ext2/inode.c Mon Jun 11 19:15:27 2001 @@ -230,11 +230,11 @@ * or when it reads all @depth-1 indirect blocks successfully and finds * the whole chain, all way to the data (returns %NULL, *err == 0). */ -static inline Indirect *ext2_get_branch(struct inode *inode, - int depth, - int *offsets, - Indirect chain[4], - int *err) +static Indirect *ext2_get_branch(struct inode *inode, + int depth, + int *offsets, + Indirect chain[4], + int *err) { kdev_t dev = inode->i_dev; int size = inode->i_sb->s_blocksize; @@ -574,82 +574,6 @@ goto reread; } -struct buffer_head * ext2_getblk(struct inode * inode, long block, int create, int * err) -{ - struct buffer_head dummy; - int error; - - dummy.b_state = 0; - dummy.b_blocknr = -1000; - error = ext2_get_block(inode, block, &dummy, create); - *err = error; - if (!error && buffer_mapped(&dummy)) { - struct buffer_head *bh; - bh = getblk(dummy.b_dev, dummy.b_blocknr, inode->i_sb->s_blocksize); - if (buffer_new(&dummy)) { - lock_buffer(bh); - memset(bh->b_data, 0, inode->i_sb->s_blocksize); - mark_buffer_uptodate(bh, 1); - unlock_buffer(bh); - mark_buffer_dirty_inode(bh, inode); - } - return bh; - } - return NULL; -} - -struct buffer_head * ext2_bread (struct inode * inode, int block, - int create, int *err) -{ - struct buffer_head * bh; - int prev_blocks; - - prev_blocks = inode->i_blocks; - - bh = ext2_getblk (inode, block, create, err); - if (!bh) - return bh; - - /* - * If the inode has grown, and this is a directory, then perform - * preallocation of a few more blocks to try to keep directory - * fragmentation down. - */ - if (create && - S_ISDIR(inode->i_mode) && - inode->i_blocks > prev_blocks && - EXT2_HAS_COMPAT_FEATURE(inode->i_sb, - EXT2_FEATURE_COMPAT_DIR_PREALLOC)) { - int i; - struct buffer_head *tmp_bh; - - for (i = 1; - i < EXT2_SB(inode->i_sb)->s_es->s_prealloc_dir_blocks; - i++) { - /* - * ext2_getblk will zero out the contents of the - * directory for us - */ - tmp_bh = ext2_getblk(inode, block+i, create, err); - if (!tmp_bh) { - brelse (bh); - return 0; - } - brelse (tmp_bh); - } - } - - if (buffer_uptodate(bh)) - return bh; - ll_rw_block (READ, 1, &bh); - wait_on_buffer (bh); - if (buffer_uptodate(bh)) - return bh; - brelse (bh); - *err = -EIO; - return NULL; -} - static int ext2_writepage(struct page *page) { return block_write_full_page(page,ext2_get_block); @@ -1067,6 +991,7 @@ } else if (S_ISDIR(inode->i_mode)) { inode->i_op = &ext2_dir_inode_operations; inode->i_fop = &ext2_dir_operations; + inode->i_mapping->a_ops = &ext2_aops; } else if (S_ISLNK(inode->i_mode)) { if (!inode->i_blocks) inode->i_op = &ext2_fast_symlink_inode_operations; diff -u --recursive --new-file v2.4.5/linux/fs/ext2/namei.c linux/fs/ext2/namei.c --- v2.4.5/linux/fs/ext2/namei.c Thu Feb 15 12:32:21 2001 +++ linux/fs/ext2/namei.c Mon Jun 11 19:15:27 2001 @@ -1,5 +1,18 @@ /* - * linux/fs/ext2/namei.c + * linux/fs/ext2/namei.c + * + * Rewrite to pagecache. Almost all code had been changed, so blame me + * if the things go wrong. Please, send bug reports to viro@math.psu.edu + * + * Stuff here is basically a glue between the VFS and generic UNIXish + * filesystem that keeps everything in pagecache. All knowledge of the + * directory layout is in fs/ext2/dir.c - it turned out to be easily separatable + * and it's easier to debug that way. In principle we might want to + * generalize that a bit and turn it into a library. Or not. + * + * The only non-static object here is ext2_dir_inode_operations. + * + * TODO: get rid of kmap() use, add readahead. * * Copyright (C) 1992, 1993, 1994, 1995 * Remy Card (card@masi.ibp.fr) @@ -14,344 +27,63 @@ * * Big-endian to little-endian byte-swapping/bitmaps by * David S. Miller (davem@caip.rutgers.edu), 1995 - * Directory entry file type support and forward compatibility hooks - * for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998 */ #include #include -#include -#include - - +#include /* - * define how far ahead to read directories while searching them. + * Couple of helper functions - make the code slightly cleaner. */ -#define NAMEI_RA_CHUNKS 2 -#define NAMEI_RA_BLOCKS 4 -#define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS) -#define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b)) -/* - * NOTE! unlike strncmp, ext2_match returns 1 for success, 0 for failure. - * - * `len <= EXT2_NAME_LEN' is guaranteed by caller. - * `de != NULL' is guaranteed by caller. - */ -static inline int ext2_match (int len, const char * const name, - struct ext2_dir_entry_2 * de) +static inline void ext2_inc_count(struct inode *inode) { - if (len != de->name_len) - return 0; - if (!de->inode) - return 0; - return !memcmp(name, de->name, len); + inode->i_nlink++; + mark_inode_dirty(inode); } -/* - * ext2_find_entry() - * - * finds an entry in the specified directory with the wanted name. It - * returns the cache buffer in which the entry was found, and the entry - * itself (as a parameter - res_dir). It does NOT read the inode of the - * entry - you'll have to do that yourself if you want to. - */ -static struct buffer_head * ext2_find_entry (struct inode * dir, - const char * const name, int namelen, - struct ext2_dir_entry_2 ** res_dir) -{ - struct super_block * sb; - struct buffer_head * bh_use[NAMEI_RA_SIZE]; - struct buffer_head * bh_read[NAMEI_RA_SIZE]; - unsigned long offset; - int block, toread, i, err; - - *res_dir = NULL; - sb = dir->i_sb; - - if (namelen > EXT2_NAME_LEN) - return NULL; - - memset (bh_use, 0, sizeof (bh_use)); - toread = 0; - for (block = 0; block < NAMEI_RA_SIZE; ++block) { - struct buffer_head * bh; - - if ((block << EXT2_BLOCK_SIZE_BITS (sb)) >= dir->i_size) - break; - bh = ext2_getblk (dir, block, 0, &err); - bh_use[block] = bh; - if (bh && !buffer_uptodate(bh)) - bh_read[toread++] = bh; - } - - for (block = 0, offset = 0; offset < dir->i_size; block++) { - struct buffer_head * bh; - struct ext2_dir_entry_2 * de; - char * dlimit; - - if ((block % NAMEI_RA_BLOCKS) == 0 && toread) { - ll_rw_block (READ, toread, bh_read); - toread = 0; - } - bh = bh_use[block % NAMEI_RA_SIZE]; - if (!bh) { -#if 0 - ext2_error (sb, "ext2_find_entry", - "directory #%lu contains a hole at offset %lu", - dir->i_ino, offset); -#endif - offset += sb->s_blocksize; - continue; - } - wait_on_buffer (bh); - if (!buffer_uptodate(bh)) { - /* - * read error: all bets are off - */ - break; - } - - de = (struct ext2_dir_entry_2 *) bh->b_data; - dlimit = bh->b_data + sb->s_blocksize; - while ((char *) de < dlimit) { - /* this code is executed quadratically often */ - /* do minimal checking `by hand' */ - int de_len; - - if ((char *) de + namelen <= dlimit && - ext2_match (namelen, name, de)) { - /* found a match - - just to be sure, do a full check */ - if (!ext2_check_dir_entry("ext2_find_entry", - dir, de, bh, offset)) - goto failure; - for (i = 0; i < NAMEI_RA_SIZE; ++i) { - if (bh_use[i] != bh) - brelse (bh_use[i]); - } - *res_dir = de; - return bh; - } - /* prevent looping on a bad block */ - de_len = le16_to_cpu(de->rec_len); - if (de_len <= 0) - goto failure; - offset += de_len; - de = (struct ext2_dir_entry_2 *) - ((char *) de + de_len); - } +static inline void ext2_dec_count(struct inode *inode) +{ + inode->i_nlink--; + mark_inode_dirty(inode); +} - brelse (bh); - if (((block + NAMEI_RA_SIZE) << EXT2_BLOCK_SIZE_BITS (sb)) >= - dir->i_size) - bh = NULL; - else - bh = ext2_getblk (dir, block + NAMEI_RA_SIZE, 0, &err); - bh_use[block % NAMEI_RA_SIZE] = bh; - if (bh && !buffer_uptodate(bh)) - bh_read[toread++] = bh; +static inline int ext2_add_nondir(struct dentry *dentry, struct inode *inode) +{ + int err = ext2_add_link(dentry, inode); + if (!err) { + d_instantiate(dentry, inode); + return 0; } - -failure: - for (i = 0; i < NAMEI_RA_SIZE; ++i) - brelse (bh_use[i]); - return NULL; + ext2_dec_count(inode); + iput(inode); + return err; } +/* + * Methods themselves. + */ + static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry) { struct inode * inode; - struct ext2_dir_entry_2 * de; - struct buffer_head * bh; - + ino_t ino; + if (dentry->d_name.len > EXT2_NAME_LEN) return ERR_PTR(-ENAMETOOLONG); - bh = ext2_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de); + ino = ext2_inode_by_name(dir, dentry); inode = NULL; - if (bh) { - unsigned long ino = le32_to_cpu(de->inode); - brelse (bh); + if (ino) { inode = iget(dir->i_sb, ino); - - if (!inode) + if (!inode) return ERR_PTR(-EACCES); } d_add(dentry, inode); return NULL; } -#define S_SHIFT 12 -static unsigned char ext2_type_by_mode[S_IFMT >> S_SHIFT] = { - [S_IFREG >> S_SHIFT] EXT2_FT_REG_FILE, - [S_IFDIR >> S_SHIFT] EXT2_FT_DIR, - [S_IFCHR >> S_SHIFT] EXT2_FT_CHRDEV, - [S_IFBLK >> S_SHIFT] EXT2_FT_BLKDEV, - [S_IFIFO >> S_SHIFT] EXT2_FT_FIFO, - [S_IFSOCK >> S_SHIFT] EXT2_FT_SOCK, - [S_IFLNK >> S_SHIFT] EXT2_FT_SYMLINK, -}; - -static inline void ext2_set_de_type(struct super_block *sb, - struct ext2_dir_entry_2 *de, - umode_t mode) { - if (EXT2_HAS_INCOMPAT_FEATURE(sb, EXT2_FEATURE_INCOMPAT_FILETYPE)) - de->file_type = ext2_type_by_mode[(mode & S_IFMT)>>S_SHIFT]; -} - -/* - * ext2_add_entry() - * - * adds a file entry to the specified directory. - */ -int ext2_add_entry (struct inode * dir, const char * name, int namelen, - struct inode *inode) -{ - unsigned long offset; - unsigned short rec_len; - struct buffer_head * bh; - struct ext2_dir_entry_2 * de, * de1; - struct super_block * sb; - int retval; - - sb = dir->i_sb; - - if (!namelen) - return -EINVAL; - bh = ext2_bread (dir, 0, 0, &retval); - if (!bh) - return retval; - rec_len = EXT2_DIR_REC_LEN(namelen); - offset = 0; - de = (struct ext2_dir_entry_2 *) bh->b_data; - while (1) { - if ((char *)de >= sb->s_blocksize + bh->b_data) { - brelse (bh); - bh = NULL; - bh = ext2_bread (dir, offset >> EXT2_BLOCK_SIZE_BITS(sb), 1, &retval); - if (!bh) - return retval; - if (dir->i_size <= offset) { - if (dir->i_size == 0) { - brelse(bh); - return -ENOENT; - } - - ext2_debug ("creating next block\n"); - - de = (struct ext2_dir_entry_2 *) bh->b_data; - de->inode = 0; - de->rec_len = le16_to_cpu(sb->s_blocksize); - dir->i_size = offset + sb->s_blocksize; - dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; - mark_inode_dirty(dir); - } else { - - ext2_debug ("skipping to next block\n"); - - de = (struct ext2_dir_entry_2 *) bh->b_data; - } - } - if (!ext2_check_dir_entry ("ext2_add_entry", dir, de, bh, - offset)) { - brelse (bh); - return -ENOENT; - } - if (ext2_match (namelen, name, de)) { - brelse (bh); - return -EEXIST; - } - if ((le32_to_cpu(de->inode) == 0 && le16_to_cpu(de->rec_len) >= rec_len) || - (le16_to_cpu(de->rec_len) >= EXT2_DIR_REC_LEN(de->name_len) + rec_len)) { - offset += le16_to_cpu(de->rec_len); - if (le32_to_cpu(de->inode)) { - de1 = (struct ext2_dir_entry_2 *) ((char *) de + - EXT2_DIR_REC_LEN(de->name_len)); - de1->rec_len = cpu_to_le16(le16_to_cpu(de->rec_len) - - EXT2_DIR_REC_LEN(de->name_len)); - de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(de->name_len)); - de = de1; - } - de->file_type = EXT2_FT_UNKNOWN; - if (inode) { - de->inode = cpu_to_le32(inode->i_ino); - ext2_set_de_type(dir->i_sb, de, inode->i_mode); - } else - de->inode = 0; - de->name_len = namelen; - memcpy (de->name, name, namelen); - /* - * XXX shouldn't update any times until successful - * completion of syscall, but too many callers depend - * on this. - * - * XXX similarly, too many callers depend on - * ext2_new_inode() setting the times, but error - * recovery deletes the inode, so the worst that can - * happen is that the times are slightly out of date - * and/or different from the directory change time. - */ - dir->i_mtime = dir->i_ctime = CURRENT_TIME; - dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; - mark_inode_dirty(dir); - dir->i_version = ++event; - mark_buffer_dirty_inode(bh, dir); - if (IS_SYNC(dir)) { - ll_rw_block (WRITE, 1, &bh); - wait_on_buffer (bh); - } - brelse(bh); - return 0; - } - offset += le16_to_cpu(de->rec_len); - de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); - } - brelse (bh); - return -ENOSPC; -} - -/* - * ext2_delete_entry deletes a directory entry by merging it with the - * previous entry - */ -static int ext2_delete_entry (struct inode * dir, - struct ext2_dir_entry_2 * de_del, - struct buffer_head * bh) -{ - struct ext2_dir_entry_2 * de, * pde; - int i; - - i = 0; - pde = NULL; - de = (struct ext2_dir_entry_2 *) bh->b_data; - while (i < bh->b_size) { - if (!ext2_check_dir_entry ("ext2_delete_entry", NULL, - de, bh, i)) - return -EIO; - if (de == de_del) { - if (pde) - pde->rec_len = - cpu_to_le16(le16_to_cpu(pde->rec_len) + - le16_to_cpu(de->rec_len)); - else - de->inode = 0; - dir->i_version = ++event; - mark_buffer_dirty_inode(bh, dir); - if (IS_SYNC(dir)) { - ll_rw_block (WRITE, 1, &bh); - wait_on_buffer (bh); - } - return 0; - } - i += le16_to_cpu(de->rec_len); - pde = de; - de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); - } - return -ENOENT; -} - /* * By the time this is called, we already have created * the directory cache entry for the new file, but it @@ -364,454 +96,245 @@ { struct inode * inode = ext2_new_inode (dir, mode); int err = PTR_ERR(inode); - if (IS_ERR(inode)) - return err; - - inode->i_op = &ext2_file_inode_operations; - inode->i_fop = &ext2_file_operations; - inode->i_mapping->a_ops = &ext2_aops; - inode->i_mode = mode; - mark_inode_dirty(inode); - err = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, - inode); - if (err) { - inode->i_nlink--; + if (!IS_ERR(inode)) { + inode->i_op = &ext2_file_inode_operations; + inode->i_fop = &ext2_file_operations; + inode->i_mapping->a_ops = &ext2_aops; mark_inode_dirty(inode); - iput (inode); - return err; + err = ext2_add_nondir(dentry, inode); } - d_instantiate(dentry, inode); - return 0; + return err; } static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev) { struct inode * inode = ext2_new_inode (dir, mode); int err = PTR_ERR(inode); - - if (IS_ERR(inode)) - return err; - - inode->i_uid = current->fsuid; - init_special_inode(inode, mode, rdev); - err = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, - inode); - if (err) - goto out_no_entry; - mark_inode_dirty(inode); - d_instantiate(dentry, inode); - return 0; - -out_no_entry: - inode->i_nlink--; - mark_inode_dirty(inode); - iput(inode); + if (!IS_ERR(inode)) { + init_special_inode(inode, mode, rdev); + mark_inode_dirty(inode); + err = ext2_add_nondir(dentry, inode); + } return err; } -static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode) +static int ext2_symlink (struct inode * dir, struct dentry * dentry, + const char * symname) { + struct super_block * sb = dir->i_sb; + int err = -ENAMETOOLONG; + unsigned l = strlen(symname)+1; struct inode * inode; - struct buffer_head * dir_block; - struct ext2_dir_entry_2 * de; - int err; - if (dir->i_nlink >= EXT2_LINK_MAX) - return -EMLINK; + if (l > sb->s_blocksize) + goto out; - inode = ext2_new_inode (dir, S_IFDIR); + inode = ext2_new_inode (dir, S_IFLNK | S_IRWXUGO); err = PTR_ERR(inode); if (IS_ERR(inode)) - return err; + goto out; - inode->i_op = &ext2_dir_inode_operations; - inode->i_fop = &ext2_dir_operations; - inode->i_size = inode->i_sb->s_blocksize; - inode->i_blocks = 0; - dir_block = ext2_bread (inode, 0, 1, &err); - if (!dir_block) { - inode->i_nlink--; /* is this nlink == 0? */ - mark_inode_dirty(inode); - iput (inode); - return err; + if (l > sizeof (inode->u.ext2_i.i_data)) { + /* slow symlink */ + inode->i_op = &page_symlink_inode_operations; + inode->i_mapping->a_ops = &ext2_aops; + err = block_symlink(inode, symname, l); + if (err) + goto out_fail; + } else { + /* fast symlink */ + inode->i_op = &ext2_fast_symlink_inode_operations; + memcpy((char*)&inode->u.ext2_i.i_data,symname,l); + inode->i_size = l-1; } - de = (struct ext2_dir_entry_2 *) dir_block->b_data; - de->inode = cpu_to_le32(inode->i_ino); - de->name_len = 1; - de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(de->name_len)); - strcpy (de->name, "."); - ext2_set_de_type(dir->i_sb, de, S_IFDIR); - de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); - de->inode = cpu_to_le32(dir->i_ino); - de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize - EXT2_DIR_REC_LEN(1)); - de->name_len = 2; - strcpy (de->name, ".."); - ext2_set_de_type(dir->i_sb, de, S_IFDIR); - inode->i_nlink = 2; - mark_buffer_dirty_inode(dir_block, dir); - brelse (dir_block); - inode->i_mode = S_IFDIR | mode; - if (dir->i_mode & S_ISGID) - inode->i_mode |= S_ISGID; mark_inode_dirty(inode); - err = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, - inode); - if (err) - goto out_no_entry; - dir->i_nlink++; - dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; - mark_inode_dirty(dir); - d_instantiate(dentry, inode); - return 0; -out_no_entry: - inode->i_nlink = 0; - mark_inode_dirty(inode); - iput (inode); + err = ext2_add_nondir(dentry, inode); +out: return err; -} -/* - * routine to check that the specified directory is empty (for rmdir) - */ -static int empty_dir (struct inode * inode) -{ - unsigned long offset; - struct buffer_head * bh; - struct ext2_dir_entry_2 * de, * de1; - struct super_block * sb; - int err; - - sb = inode->i_sb; - if (inode->i_size < EXT2_DIR_REC_LEN(1) + EXT2_DIR_REC_LEN(2) || - !(bh = ext2_bread (inode, 0, 0, &err))) { - ext2_warning (inode->i_sb, "empty_dir", - "bad directory (dir #%lu) - no data block", - inode->i_ino); - return 1; - } - de = (struct ext2_dir_entry_2 *) bh->b_data; - de1 = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); - if (le32_to_cpu(de->inode) != inode->i_ino || !le32_to_cpu(de1->inode) || - strcmp (".", de->name) || strcmp ("..", de1->name)) { - ext2_warning (inode->i_sb, "empty_dir", - "bad directory (dir #%lu) - no `.' or `..'", - inode->i_ino); - brelse (bh); - return 1; - } - offset = le16_to_cpu(de->rec_len) + le16_to_cpu(de1->rec_len); - de = (struct ext2_dir_entry_2 *) ((char *) de1 + le16_to_cpu(de1->rec_len)); - while (offset < inode->i_size ) { - if (!bh || (void *) de >= (void *) (bh->b_data + sb->s_blocksize)) { - brelse (bh); - bh = ext2_bread (inode, offset >> EXT2_BLOCK_SIZE_BITS(sb), 0, &err); - if (!bh) { -#if 0 - ext2_error (sb, "empty_dir", - "directory #%lu contains a hole at offset %lu", - inode->i_ino, offset); -#endif - offset += sb->s_blocksize; - continue; - } - de = (struct ext2_dir_entry_2 *) bh->b_data; - } - if (!ext2_check_dir_entry ("empty_dir", inode, de, bh, - offset)) { - brelse (bh); - return 1; - } - if (le32_to_cpu(de->inode)) { - brelse (bh); - return 0; - } - offset += le16_to_cpu(de->rec_len); - de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); - } - brelse (bh); - return 1; +out_fail: + ext2_dec_count(inode); + iput (inode); + goto out; } -static int ext2_rmdir (struct inode * dir, struct dentry *dentry) +static int ext2_link (struct dentry * old_dentry, struct inode * dir, + struct dentry *dentry) { - int retval; - struct inode * inode; - struct buffer_head * bh; - struct ext2_dir_entry_2 * de; + struct inode *inode = old_dentry->d_inode; - retval = -ENOENT; - bh = ext2_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de); - if (!bh) - goto end_rmdir; - - inode = dentry->d_inode; - DQUOT_INIT(inode); - - retval = -EIO; - if (le32_to_cpu(de->inode) != inode->i_ino) - goto end_rmdir; - - retval = -ENOTEMPTY; - if (!empty_dir (inode)) - goto end_rmdir; - - retval = ext2_delete_entry(dir, de, bh); - if (retval) - goto end_rmdir; - if (inode->i_nlink != 2) - ext2_warning (inode->i_sb, "ext2_rmdir", - "empty directory has nlink!=2 (%d)", - inode->i_nlink); - inode->i_version = ++event; - inode->i_nlink = 0; - inode->i_size = 0; - mark_inode_dirty(inode); - dir->i_nlink--; - inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; - dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; - mark_inode_dirty(dir); - -end_rmdir: - brelse (bh); - return retval; -} + if (S_ISDIR(inode->i_mode)) + return -EPERM; -static int ext2_unlink(struct inode * dir, struct dentry *dentry) -{ - int retval; - struct inode * inode; - struct buffer_head * bh; - struct ext2_dir_entry_2 * de; + if (inode->i_nlink >= EXT2_LINK_MAX) + return -EMLINK; - retval = -ENOENT; - bh = ext2_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de); - if (!bh) - goto end_unlink; - - inode = dentry->d_inode; - DQUOT_INIT(inode); - - retval = -EIO; - if (le32_to_cpu(de->inode) != inode->i_ino) - goto end_unlink; - - if (!inode->i_nlink) { - ext2_warning (inode->i_sb, "ext2_unlink", - "Deleting nonexistent file (%lu), %d", - inode->i_ino, inode->i_nlink); - inode->i_nlink = 1; - } - retval = ext2_delete_entry(dir, de, bh); - if (retval) - goto end_unlink; - dir->i_ctime = dir->i_mtime = CURRENT_TIME; - dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; - mark_inode_dirty(dir); - inode->i_nlink--; - mark_inode_dirty(inode); - inode->i_ctime = dir->i_ctime; - retval = 0; + inode->i_ctime = CURRENT_TIME; + ext2_inc_count(inode); + atomic_inc(&inode->i_count); -end_unlink: - brelse (bh); - return retval; + return ext2_add_nondir(dentry, inode); } -static int ext2_symlink (struct inode * dir, struct dentry *dentry, const char * symname) +static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode) { struct inode * inode; - int l, err; + int err = -EMLINK; - l = strlen(symname)+1; - if (l > dir->i_sb->s_blocksize) - return -ENAMETOOLONG; + if (dir->i_nlink >= EXT2_LINK_MAX) + goto out; + + ext2_inc_count(dir); - inode = ext2_new_inode (dir, S_IFLNK); + inode = ext2_new_inode (dir, S_IFDIR | mode); err = PTR_ERR(inode); if (IS_ERR(inode)) - return err; + goto out_dir; - inode->i_mode = S_IFLNK | S_IRWXUGO; + inode->i_op = &ext2_dir_inode_operations; + inode->i_fop = &ext2_dir_operations; + inode->i_mapping->a_ops = &ext2_aops; - if (l > sizeof (inode->u.ext2_i.i_data)) { - inode->i_op = &page_symlink_inode_operations; - inode->i_mapping->a_ops = &ext2_aops; - err = block_symlink(inode, symname, l); - if (err) - goto out_no_entry; - } else { - inode->i_op = &ext2_fast_symlink_inode_operations; - memcpy((char*)&inode->u.ext2_i.i_data,symname,l); - inode->i_size = l-1; - } - mark_inode_dirty(inode); + ext2_inc_count(inode); - err = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, - inode); + err = ext2_make_empty(inode, dir); if (err) - goto out_no_entry; - d_instantiate(dentry, inode); - return 0; + goto out_fail; -out_no_entry: - inode->i_nlink--; - mark_inode_dirty(inode); - iput (inode); + err = ext2_add_link(dentry, inode); + if (err) + goto out_fail; + + d_instantiate(dentry, inode); +out: return err; + +out_fail: + ext2_dec_count(inode); + ext2_dec_count(inode); + iput(inode); +out_dir: + ext2_dec_count(dir); + goto out; } -static int ext2_link (struct dentry * old_dentry, - struct inode * dir, struct dentry *dentry) +static int ext2_unlink(struct inode * dir, struct dentry *dentry) { - struct inode *inode = old_dentry->d_inode; - int err; + struct inode * inode = dentry->d_inode; + struct ext2_dir_entry_2 * de; + struct page * page; + int err = -ENOENT; - if (S_ISDIR(inode->i_mode)) - return -EPERM; + de = ext2_find_entry (dir, dentry, &page); + if (!de) + goto out; - if (inode->i_nlink >= EXT2_LINK_MAX) - return -EMLINK; - - err = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, - inode); + err = ext2_delete_entry (de, page); if (err) - return err; + goto out; - inode->i_nlink++; - inode->i_ctime = CURRENT_TIME; - mark_inode_dirty(inode); - atomic_inc(&inode->i_count); - d_instantiate(dentry, inode); - return 0; + inode->i_ctime = dir->i_ctime; + ext2_dec_count(inode); + err = 0; +out: + return err; } -#define PARENT_INO(buffer) \ - ((struct ext2_dir_entry_2 *) ((char *) buffer + \ - le16_to_cpu(((struct ext2_dir_entry_2 *) buffer)->rec_len)))->inode - -/* - * Anybody can rename anything with this: the permission checks are left to the - * higher-level routines. - */ -static int ext2_rename (struct inode * old_dir, struct dentry *old_dentry, - struct inode * new_dir,struct dentry *new_dentry) +static int ext2_rmdir (struct inode * dir, struct dentry *dentry) { - struct inode * old_inode, * new_inode; - struct buffer_head * old_bh, * new_bh, * dir_bh; - struct ext2_dir_entry_2 * old_de, * new_de; - int retval; - - old_bh = new_bh = dir_bh = NULL; - - old_bh = ext2_find_entry (old_dir, old_dentry->d_name.name, old_dentry->d_name.len, &old_de); - /* - * Check for inode number is _not_ due to possible IO errors. - * We might rmdir the source, keep it as pwd of some process - * and merrily kill the link to whatever was created under the - * same name. Goodbye sticky bit ;-< - */ - old_inode = old_dentry->d_inode; - retval = -ENOENT; - if (!old_bh || le32_to_cpu(old_de->inode) != old_inode->i_ino) - goto end_rename; - - new_inode = new_dentry->d_inode; - new_bh = ext2_find_entry (new_dir, new_dentry->d_name.name, - new_dentry->d_name.len, &new_de); - if (new_bh) { - if (!new_inode) { - brelse (new_bh); - new_bh = NULL; - } else { - DQUOT_INIT(new_inode); + struct inode * inode = dentry->d_inode; + int err = -ENOTEMPTY; + + if (ext2_empty_dir(inode)) { + err = ext2_unlink(dir, dentry); + if (!err) { + inode->i_size = 0; + ext2_dec_count(inode); + ext2_dec_count(dir); } } + return err; +} + +static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry, + struct inode * new_dir, struct dentry * new_dentry ) +{ + struct inode * old_inode = old_dentry->d_inode; + struct inode * new_inode = new_dentry->d_inode; + struct page * dir_page = NULL; + struct ext2_dir_entry_2 * dir_de = NULL; + struct page * old_page; + struct ext2_dir_entry_2 * old_de; + int err = -ENOENT; + + old_de = ext2_find_entry (old_dir, old_dentry, &old_page); + if (!old_de) + goto out; + if (S_ISDIR(old_inode->i_mode)) { - if (new_inode) { - retval = -ENOTEMPTY; - if (!empty_dir (new_inode)) - goto end_rename; - } - retval = -EIO; - dir_bh = ext2_bread (old_inode, 0, 0, &retval); - if (!dir_bh) - goto end_rename; - if (le32_to_cpu(PARENT_INO(dir_bh->b_data)) != old_dir->i_ino) - goto end_rename; - retval = -EMLINK; - if (!new_inode && new_dir!=old_dir && - new_dir->i_nlink >= EXT2_LINK_MAX) - goto end_rename; + err = -EIO; + dir_de = ext2_dotdot(old_inode, &dir_page); + if (!dir_de) + goto out_old; } - if (!new_bh) { - retval = ext2_add_entry (new_dir, new_dentry->d_name.name, - new_dentry->d_name.len, - old_inode); - if (retval) - goto end_rename; - } else { - new_de->inode = le32_to_cpu(old_inode->i_ino); - if (EXT2_HAS_INCOMPAT_FEATURE(new_dir->i_sb, - EXT2_FEATURE_INCOMPAT_FILETYPE)) - new_de->file_type = old_de->file_type; - new_dir->i_version = ++event; - mark_buffer_dirty_inode(new_bh, new_dir); - if (IS_SYNC(new_dir)) { - ll_rw_block (WRITE, 1, &new_bh); - wait_on_buffer (new_bh); - } - brelse(new_bh); - new_bh = NULL; - } - - /* - * Like most other Unix systems, set the ctime for inodes on a - * rename. - */ - old_inode->i_ctime = CURRENT_TIME; - mark_inode_dirty(old_inode); - - /* - * ok, that's it - */ - ext2_delete_entry(old_dir, old_de, old_bh); if (new_inode) { - new_inode->i_nlink--; + struct page *new_page; + struct ext2_dir_entry_2 *new_de; + + err = -ENOTEMPTY; + if (dir_de && !ext2_empty_dir (new_inode)) + goto out_dir; + + err = -ENOENT; + new_de = ext2_find_entry (new_dir, new_dentry, &new_page); + if (!new_de) + goto out_dir; + ext2_inc_count(old_inode); + ext2_set_link(new_dir, new_de, new_page, old_inode); new_inode->i_ctime = CURRENT_TIME; - mark_inode_dirty(new_inode); - } - old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; - old_dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; - mark_inode_dirty(old_dir); - if (dir_bh) { - PARENT_INO(dir_bh->b_data) = le32_to_cpu(new_dir->i_ino); - mark_buffer_dirty_inode(dir_bh, old_inode); - old_dir->i_nlink--; - mark_inode_dirty(old_dir); - if (new_inode) { + if (dir_de) new_inode->i_nlink--; - mark_inode_dirty(new_inode); - } else { - new_dir->i_nlink++; - new_dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; - mark_inode_dirty(new_dir); - } + ext2_dec_count(new_inode); + } else { + if (dir_de) { + err = -EMLINK; + if (new_dir->i_nlink >= EXT2_LINK_MAX) + goto out_dir; + } + ext2_inc_count(old_inode); + err = ext2_add_link(new_dentry, old_inode); + if (err) { + ext2_dec_count(old_inode); + goto out_dir; + } + if (dir_de) + ext2_inc_count(new_dir); + } + + ext2_delete_entry (old_de, old_page); + ext2_dec_count(old_inode); + + if (dir_de) { + ext2_set_link(old_inode, dir_de, dir_page, new_dir); + ext2_dec_count(old_dir); } + return 0; - retval = 0; -end_rename: - brelse (dir_bh); - brelse (old_bh); - brelse (new_bh); - return retval; +out_dir: + if (dir_de) { + kunmap(dir_page); + page_cache_release(dir_page); + } +out_old: + kunmap(old_page); + page_cache_release(old_page); +out: + return err; } -/* - * directories can handle most operations... - */ struct inode_operations ext2_dir_inode_operations = { create: ext2_create, lookup: ext2_lookup, diff -u --recursive --new-file v2.4.5/linux/fs/fat/inode.c linux/fs/fat/inode.c --- v2.4.5/linux/fs/fat/inode.c Thu May 24 15:36:34 2001 +++ linux/fs/fat/inode.c Mon Jun 11 19:15:27 2001 @@ -28,6 +28,7 @@ #include #include #include +#include #include #include "msbuffer.h" diff -u --recursive --new-file v2.4.5/linux/fs/freevxfs/vxfs_bmap.c linux/fs/freevxfs/vxfs_bmap.c --- v2.4.5/linux/fs/freevxfs/vxfs_bmap.c Thu May 24 15:00:59 2001 +++ linux/fs/freevxfs/vxfs_bmap.c Wed Jun 27 17:10:55 2001 @@ -27,7 +27,7 @@ * SUCH DAMAGE. */ -#ident "$Id: vxfs_bmap.c,v 1.20 2001/04/25 18:11:23 hch Exp hch $" +#ident "$Id: vxfs_bmap.c,v 1.22 2001/05/26 22:41:23 hch Exp hch $" /* * Veritas filesystem driver - filesystem to disk block mapping. @@ -70,7 +70,7 @@ struct super_block *sbp = ip->i_sb; kdev_t dev = ip->i_dev; u_long bsize = sbp->s_blocksize; - u_long size = 0; + long size = 0; int i; for (i = 0; i < VXFS_NDADDR; i++) { @@ -135,7 +135,7 @@ for (i = 0; i < size * VXFS_TYPED_PER_BLOCK(ip->i_sb); i++) { struct vxfs_typed *typ; - u_int64_t off; + int64_t off; bp = bread(ip->i_dev, indir + (i / VXFS_TYPED_PER_BLOCK(ip->i_sb)), @@ -166,10 +166,12 @@ goto out; case VXFS_TYPED_INDIRECT_DEV4: case VXFS_TYPED_DATA_DEV4: { - struct vxfs_typed_dev4 *typ4 = (struct vxfs_typed_dev4 *)typ; + struct vxfs_typed_dev4 *typ4 = + (struct vxfs_typed_dev4 *)typ; + printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n"); - printk(KERN_INFO "block: %Ld\tsize: %Ld\tdev: %d\n", - (long long)typ4->vd4_block, (long long)typ4->vd4_size, typ4->vd4_dev); + printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n", + typ4->vd4_block, typ4->vd4_size, typ4->vd4_dev); goto fail; } default: @@ -205,7 +207,7 @@ for (i = 0; i < VXFS_NTYPED; i++) { struct vxfs_typed *typ = vip->vii_org.typed + i; - u_int64_t off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK); + int64_t off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK); #ifdef DIAGNOSTIC vxfs_typdump(typ); @@ -225,10 +227,12 @@ break; case VXFS_TYPED_INDIRECT_DEV4: case VXFS_TYPED_DATA_DEV4: { - struct vxfs_typed_dev4 *typ4 = (struct vxfs_typed_dev4 *)typ; + struct vxfs_typed_dev4 *typ4 = + (struct vxfs_typed_dev4 *)typ; + printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n"); - printk(KERN_INFO "block: %Ld\tsize: %Ld\tdev: %d\n", - (long long)typ4->vd4_block, (long long)typ4->vd4_size, typ4->vd4_dev); + printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n", + typ4->vd4_block, typ4->vd4_size, typ4->vd4_dev); return 0; } default: diff -u --recursive --new-file v2.4.5/linux/fs/freevxfs/vxfs_fshead.h linux/fs/freevxfs/vxfs_fshead.h --- v2.4.5/linux/fs/freevxfs/vxfs_fshead.h Mon May 21 12:31:06 2001 +++ linux/fs/freevxfs/vxfs_fshead.h Wed Jun 27 17:10:55 2001 @@ -30,7 +30,7 @@ #ifndef _VXFS_FSHEAD_H_ #define _VXFS_FSHEAD_H_ -#ident "$Id: vxfs_fshead.h,v 1.6 2001/04/25 18:11:23 hch Exp hch $" +#ident "$Id: vxfs_fshead.h,v 1.7 2001/05/23 17:27:39 hch Exp hch $" /* * Veritas filesystem driver - fileset header structures. @@ -61,8 +61,8 @@ /* * Slightly more fields follow, but they - * a) are not of any interested for us, and - * b) differ much in different vxfs versions/ports + * a) are not of any interest for us, and + * b) differ a lot in different vxfs versions/ports */ }; diff -u --recursive --new-file v2.4.5/linux/fs/freevxfs/vxfs_inode.c linux/fs/freevxfs/vxfs_inode.c --- v2.4.5/linux/fs/freevxfs/vxfs_inode.c Mon May 21 12:31:06 2001 +++ linux/fs/freevxfs/vxfs_inode.c Thu Jun 28 14:44:10 2001 @@ -27,7 +27,7 @@ * SUCH DAMAGE. */ -#ident "$Id: vxfs_inode.c,v 1.34 2001/05/21 15:33:08 hch Exp hch $" +#ident "$Id: vxfs_inode.c,v 1.36 2001/05/26 22:28:02 hch Exp hch $" /* * Veritas filesystem driver - inode routines. @@ -91,7 +91,7 @@ * Returns the matching VxFS inode on success, else a NULL pointer. * * NOTE: - * While __vxfs_iget uses that pagecache this function uses the + * While __vxfs_iget uses the pagecache vxfs_blkiget uses the * buffercache. This function should not be used outside the * read_super() method, othwerwise the data may be incoherent. */ @@ -138,7 +138,7 @@ * Returns the matching VxFS inode on success, else a NULL pointer. */ static struct vxfs_inode_info * -__vxfs_iget(struct super_block *sbp, ino_t ino, struct inode *ilistp) +__vxfs_iget(ino_t ino, struct inode *ilistp) { struct page *pp; u_long offset; @@ -184,7 +184,7 @@ struct vxfs_inode_info * vxfs_stiget(struct super_block *sbp, ino_t ino) { - return __vxfs_iget(sbp, ino, VXFS_SBI(sbp)->vsi_stilist); + return __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_stilist); } /** @@ -288,7 +288,7 @@ struct address_space_operations *aops; ino_t ino = ip->i_ino; - if (!(vip = __vxfs_iget(sbp, ino, VXFS_SBI(sbp)->vsi_ilist))) + if (!(vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_ilist))) return; vxfs_iinit(ip, vip); diff -u --recursive --new-file v2.4.5/linux/fs/freevxfs/vxfs_inode.h linux/fs/freevxfs/vxfs_inode.h --- v2.4.5/linux/fs/freevxfs/vxfs_inode.h Mon May 21 12:31:06 2001 +++ linux/fs/freevxfs/vxfs_inode.h Wed Jun 27 17:10:55 2001 @@ -30,7 +30,7 @@ #ifndef _VXFS_INODE_H_ #define _VXFS_INODE_H_ -#ident "$Id: vxfs_inode.h,v 1.14 2001/04/25 18:11:23 hch Exp hch $" +#ident "$Id: vxfs_inode.h,v 1.15 2001/05/26 22:41:23 hch Exp hch $" /* * Veritas filesystem driver - inode structure. @@ -77,7 +77,7 @@ vx_daddr_t ve4_indir[VXFS_NIADDR]; /* Indirect extents */ struct direct { /* Direct extents */ vx_daddr_t extent; /* Extent number */ - u_int32_t size; /* Size of extent */ + int32_t size; /* Size of extent */ } ve4_direct[VXFS_NDADDR]; }; diff -u --recursive --new-file v2.4.5/linux/fs/freevxfs/vxfs_lookup.c linux/fs/freevxfs/vxfs_lookup.c --- v2.4.5/linux/fs/freevxfs/vxfs_lookup.c Mon May 21 12:31:06 2001 +++ linux/fs/freevxfs/vxfs_lookup.c Wed Jun 27 17:10:55 2001 @@ -27,7 +27,7 @@ * SUCH DAMAGE. */ -#ident "$Id: vxfs_lookup.c,v 1.17 2001/05/21 15:23:53 hch Exp hch $" +#ident "$Id: vxfs_lookup.c,v 1.19 2001/05/30 19:50:20 hch Exp hch $" /* * Veritas filesystem driver - lookup and other directory related code. @@ -240,9 +240,8 @@ struct inode *ip = fp->f_dentry->d_inode; struct super_block *sbp = ip->i_sb; u_long bsize = sbp->s_blocksize; - u_long page, npages, block, nblocks, offset; + u_long page, npages, block, pblocks, nblocks, offset; loff_t pos; - int pblocks; switch ((long)fp->f_pos) { case 0: @@ -262,14 +261,14 @@ if (pos > VXFS_DIRROUND(ip->i_size)) return 0; - page = pos >> PAGE_CACHE_SHIFT; - offset = pos & ~PAGE_CACHE_MASK; - block = pos >> sbp->s_blocksize_bits; - npages = dir_pages(ip); nblocks = dir_blocks(ip); pblocks = VXFS_BLOCK_PER_PAGE(sbp); + page = pos >> PAGE_CACHE_SHIFT; + offset = pos & ~PAGE_CACHE_MASK; + block = (u_long)(pos >> sbp->s_blocksize_bits) % pblocks; + for (; page < npages; page++, block = 0) { caddr_t kaddr; struct page *pp; @@ -310,6 +309,7 @@ goto done; } } + offset = 0; } vxfs_put_page(pp); offset = 0; diff -u --recursive --new-file v2.4.5/linux/fs/freevxfs/vxfs_super.c linux/fs/freevxfs/vxfs_super.c --- v2.4.5/linux/fs/freevxfs/vxfs_super.c Mon May 21 12:31:06 2001 +++ linux/fs/freevxfs/vxfs_super.c Wed Jun 27 17:10:55 2001 @@ -27,7 +27,7 @@ * SUCH DAMAGE. */ -#ident "$Id: vxfs_super.c,v 1.24 2001/05/20 15:21:14 hch Exp hch $" +#ident "$Id: vxfs_super.c,v 1.25 2001/05/25 18:25:55 hch Exp hch $" /* * Veritas filesystem driver - superblock related routines. @@ -168,18 +168,18 @@ bp = bread(dev, 1, bsize); if (!bp) { printk(KERN_WARNING "vxfs: unable to read disk superblock\n"); - return NULL; + goto out; } rsbp = (struct vxfs_sb *)bp->b_data; if (rsbp->vs_magic != VXFS_SUPER_MAGIC) { printk(KERN_NOTICE "vxfs: WRONG superblock magic\n"); - return NULL; + goto out; } if (rsbp->vs_version < 2 || rsbp->vs_version > 4) { printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n", rsbp->vs_version); - return NULL; + goto out; } #ifdef DIAGNOSTIC @@ -210,12 +210,12 @@ default: printk(KERN_WARNING "vxfs: unsupported blocksise: %d\n", rsbp->vs_bsize); - return NULL; + goto out; } if (vxfs_read_olt(sbp, bsize)) { printk(KERN_WARNING "vxfs: unable to read olt\n"); - return NULL; + goto out; } if (vxfs_read_fshead(sbp)) { @@ -228,6 +228,8 @@ return (sbp); printk(KERN_WARNING "vxfs: unable to get root dentry.\n"); +out: + kfree(infp); return NULL; } diff -u --recursive --new-file v2.4.5/linux/fs/hpfs/anode.c linux/fs/hpfs/anode.c --- v2.4.5/linux/fs/hpfs/anode.c Tue Sep 5 14:07:29 2000 +++ linux/fs/hpfs/anode.c Mon Jun 11 19:15:27 2001 @@ -161,6 +161,7 @@ if ((a == node && fnod) || na == -1) return se; c2 = 0; while (up != -1) { + struct anode *new_anode; if (s->s_hpfs_chk) if (hpfs_stop_cycles(s, up, &c1, &c2, "hpfs_add_sector_to_btree #2")) return -1; if (up != node || !fnod) { @@ -194,7 +195,8 @@ mark_buffer_dirty(bh); brelse(bh); a = na; - if ((anode = hpfs_alloc_anode(s, a, &na, &bh))) { + if ((new_anode = hpfs_alloc_anode(s, a, &na, &bh))) { + anode = new_anode; /*anode->up = up != -1 ? up : ra;*/ anode->btree.internal = 1; anode->btree.n_used_nodes = 1; @@ -282,7 +284,7 @@ if (s->s_hpfs_chk) if (hpfs_stop_cycles(s, ano, &d1, &d2, "hpfs_remove_btree #1")) return; - anode = hpfs_map_anode(s, ano, &bh); + if (!(anode = hpfs_map_anode(s, ano, &bh))) return; btree1 = &anode->btree; level++; pos = 0; @@ -291,14 +293,14 @@ hpfs_free_sectors(s, btree1->u.external[i].disk_secno, btree1->u.external[i].length); go_up: if (!level) return; + brelse(bh); if (s->s_hpfs_chk) if (hpfs_stop_cycles(s, ano, &c1, &c2, "hpfs_remove_btree #2")) return; - brelse(bh); hpfs_free_sectors(s, ano, 1); oano = ano; ano = anode->up; if (--level) { - anode = hpfs_map_anode(s, ano, &bh); + if (!(anode = hpfs_map_anode(s, ano, &bh))) return; btree1 = &anode->btree; } else btree1 = btree; for (i = 0; i < btree1->n_used_nodes; i++) { diff -u --recursive --new-file v2.4.5/linux/fs/hpfs/dir.c linux/fs/hpfs/dir.c --- v2.4.5/linux/fs/hpfs/dir.c Fri Aug 11 14:29:01 2000 +++ linux/fs/hpfs/dir.c Mon Jun 11 19:15:27 2001 @@ -212,7 +212,7 @@ hpfs_lock_iget(dir->i_sb, de->directory || (de->ea_size && dir->i_sb->s_hpfs_eas) ? 1 : 2); if (!(result = iget(dir->i_sb, ino))) { hpfs_unlock_iget(dir->i_sb); - hpfs_error(result->i_sb, "hpfs_lookup: can't get inode"); + hpfs_error(dir->i_sb, "hpfs_lookup: can't get inode"); goto bail1; } if (!de->directory) result->i_hpfs_parent_dir = dir->i_ino; diff -u --recursive --new-file v2.4.5/linux/fs/hpfs/super.c linux/fs/hpfs/super.c --- v2.4.5/linux/fs/hpfs/super.c Tue Apr 17 23:16:39 2001 +++ linux/fs/hpfs/super.c Mon Jun 11 19:15:27 2001 @@ -212,6 +212,8 @@ return 0; } else if (!strcmp(p, "case")) { + if (!rhs || !*rhs) + return 0; if (!strcmp(rhs, "lower")) *lowercase = 1; else if (!strcmp(rhs, "asis")) @@ -220,6 +222,8 @@ return 0; } else if (!strcmp(p, "conv")) { + if (!rhs || !*rhs) + return 0; if (!strcmp(rhs, "binary")) *conv = CONV_BINARY; else if (!strcmp(rhs, "text")) @@ -230,6 +234,8 @@ return 0; } else if (!strcmp(p, "check")) { + if (!rhs || !*rhs) + return 0; if (!strcmp(rhs, "none")) *chk = 0; else if (!strcmp(rhs, "normal")) @@ -240,6 +246,8 @@ return 0; } else if (!strcmp(p, "errors")) { + if (!rhs || !*rhs) + return 0; if (!strcmp(rhs, "continue")) *errs = 0; else if (!strcmp(rhs, "remount-ro")) @@ -250,6 +258,8 @@ return 0; } else if (!strcmp(p, "eas")) { + if (!rhs || !*rhs) + return 0; if (!strcmp(rhs, "no")) *eas = 0; else if (!strcmp(rhs, "ro")) @@ -260,6 +270,8 @@ return 0; } else if (!strcmp(p, "chkdsk")) { + if (!rhs || !*rhs) + return 0; if (!strcmp(rhs, "no")) *chkdsk = 0; else if (!strcmp(rhs, "errors")) diff -u --recursive --new-file v2.4.5/linux/fs/inode.c linux/fs/inode.c --- v2.4.5/linux/fs/inode.c Tue May 22 09:35:42 2001 +++ linux/fs/inode.c Tue Jun 12 11:02:44 2001 @@ -1044,6 +1044,8 @@ inode->i_state|=I_FREEING; inodes_stat.nr_inodes--; spin_unlock(&inode_lock); + if (inode->i_data.nrpages) + truncate_inode_pages(&inode->i_data, 0); clear_inode(inode); } } @@ -1162,14 +1164,13 @@ void put_dquot_list(struct list_head *); int remove_inode_dquot_ref(struct inode *, short, struct list_head *); -void remove_dquot_ref(kdev_t dev, short type) +void remove_dquot_ref(struct super_block *sb, short type) { - struct super_block *sb = get_super(dev); struct inode *inode; struct list_head *act_head; LIST_HEAD(tofree_head); - if (!sb || !sb->dq_op) + if (!sb->dq_op) return; /* nothing to do */ /* We have to be protected against other CPUs */ diff -u --recursive --new-file v2.4.5/linux/fs/jffs/inode-v23.c linux/fs/jffs/inode-v23.c --- v2.4.5/linux/fs/jffs/inode-v23.c Sun May 20 11:35:00 2001 +++ linux/fs/jffs/inode-v23.c Wed Jun 27 13:51:50 2001 @@ -16,6 +16,7 @@ * Ported to Linux 2.3.x and MTD: * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB * + * Copyright 2000, 2001 Red Hat, Inc. */ /* inode.c -- Contains the code that is called from the VFS. */ @@ -1719,9 +1720,6 @@ static int __init init_jffs_fs(void) { - printk("JFFS version " - JFFS_VERSION_STRING - ", (C) 1999, 2000 Axis Communications AB\n"); return register_filesystem(&jffs_fs_type); } diff -u --recursive --new-file v2.4.5/linux/fs/lockd/mon.c linux/fs/lockd/mon.c --- v2.4.5/linux/fs/lockd/mon.c Mon Oct 16 12:58:51 2000 +++ linux/fs/lockd/mon.c Mon Jun 11 19:15:27 2001 @@ -146,7 +146,7 @@ u32 addr = ntohl(argp->addr); dprintk("nsm: xdr_encode_mon(%08x, %d, %d, %d)\n", - htonl(argp->addr), htonl(argp->proc), + htonl(argp->addr), htonl(argp->prog), htonl(argp->vers), htonl(argp->proc)); /* diff -u --recursive --new-file v2.4.5/linux/fs/locks.c linux/fs/locks.c --- v2.4.5/linux/fs/locks.c Fri Feb 9 11:29:44 2001 +++ linux/fs/locks.c Sat Jun 16 10:42:53 2001 @@ -857,7 +857,7 @@ new_fl2 = locks_alloc_lock(0); error = -ENOLCK; /* "no luck" */ if (!(new_fl && new_fl2)) - goto out; + goto out_nolock; lock_kernel(); if (caller->fl_type != F_UNLCK) { @@ -1005,6 +1005,7 @@ } out: unlock_kernel(); +out_nolock: /* * Free any unused locks. */ diff -u --recursive --new-file v2.4.5/linux/fs/minix/itree_common.c linux/fs/minix/itree_common.c --- v2.4.5/linux/fs/minix/itree_common.c Sun Apr 8 12:30:59 2001 +++ linux/fs/minix/itree_common.c Wed Jun 20 11:10:27 2001 @@ -80,13 +80,13 @@ break; branch[n].key = cpu_to_block(nr); bh = getblk(inode->i_dev, parent, BLOCK_SIZE); - if (!buffer_uptodate(bh)) - wait_on_buffer(bh); + lock_buffer(bh); memset(bh->b_data, 0, BLOCK_SIZE); branch[n].bh = bh; branch[n].p = (block_t*) bh->b_data + offsets[n]; *branch[n].p = branch[n].key; mark_buffer_uptodate(bh, 1); + unlock_buffer(bh); mark_buffer_dirty(bh); parent = nr; } diff -u --recursive --new-file v2.4.5/linux/fs/namei.c linux/fs/namei.c --- v2.4.5/linux/fs/namei.c Sat May 19 18:02:45 2001 +++ linux/fs/namei.c Tue Jul 3 08:05:42 2001 @@ -15,21 +15,15 @@ */ #include -#include -#include -#include +#include +#include #include #include -#include #include - -#include -#include -#include -#include -#include +#include #include +#include #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE]) @@ -351,22 +345,17 @@ static inline int __follow_down(struct vfsmount **mnt, struct dentry **dentry) { - struct list_head *p; + struct vfsmount *mounted; + spin_lock(&dcache_lock); - p = (*dentry)->d_vfsmnt.next; - while (p != &(*dentry)->d_vfsmnt) { - struct vfsmount *tmp; - tmp = list_entry(p, struct vfsmount, mnt_clash); - if (tmp->mnt_parent == *mnt) { - *mnt = mntget(tmp); - spin_unlock(&dcache_lock); - mntput(tmp->mnt_parent); - /* tmp holds the mountpoint, so... */ - dput(*dentry); - *dentry = dget(tmp->mnt_root); - return 1; - } - p = p->next; + mounted = lookup_mnt(*mnt, *dentry); + if (mounted) { + *mnt = mntget(mounted); + spin_unlock(&dcache_lock); + dput(*dentry); + mntput(mounted->mnt_parent); + *dentry = dget(mounted->mnt_root); + return 1; } spin_unlock(&dcache_lock); return 0; @@ -1137,10 +1126,10 @@ putname(nd->last.name); goto exit; } + error = -ELOOP; if (count++==32) { - dentry = nd->dentry; putname(nd->last.name); - goto ok; + goto exit; } dir = nd->dentry; down(&dir->d_inode->i_sem); diff -u --recursive --new-file v2.4.5/linux/fs/nfs/dir.c linux/fs/nfs/dir.c --- v2.4.5/linux/fs/nfs/dir.c Sat May 19 18:02:45 2001 +++ linux/fs/nfs/dir.c Tue Jun 12 11:15:08 2001 @@ -73,7 +73,7 @@ struct file *file; struct page *page; unsigned long page_index; - unsigned page_offset; + u32 *ptr; u64 target; struct nfs_entry *entry; decode_dirent_t decode; @@ -100,18 +100,17 @@ struct inode *inode = file->f_dentry->d_inode; struct rpc_cred *cred = nfs_file_cred(file); void *buffer = kmap(page); - int plus = NFS_USE_READDIRPLUS(inode); int error; dfprintk(VFS, "NFS: nfs_readdir_filler() reading cookie %Lu into page %lu.\n", (long long)desc->entry->cookie, page->index); again: error = NFS_PROTO(inode)->readdir(inode, cred, desc->entry->cookie, buffer, - NFS_SERVER(inode)->dtsize, plus); + NFS_SERVER(inode)->dtsize, desc->plus); /* We requested READDIRPLUS, but the server doesn't grok it */ if (desc->plus && error == -ENOTSUPP) { NFS_FLAGS(inode) &= ~NFS_INO_ADVISE_RDPLUS; - plus = 0; + desc->plus = 0; goto again; } if (error < 0) @@ -135,6 +134,26 @@ return -EIO; } +static inline +int dir_decode(nfs_readdir_descriptor_t *desc) +{ + u32 *p = desc->ptr; + p = desc->decode(p, desc->entry, desc->plus); + if (IS_ERR(p)) + return PTR_ERR(p); + desc->ptr = p; + return 0; +} + +static inline +void dir_page_release(nfs_readdir_descriptor_t *desc) +{ + kunmap(desc->page); + page_cache_release(desc->page); + desc->page = NULL; + desc->ptr = NULL; +} + /* * Given a pointer to a buffer that has already been filled by a call * to readdir, find the next entry. @@ -147,18 +166,10 @@ int find_dirent(nfs_readdir_descriptor_t *desc, struct page *page) { struct nfs_entry *entry = desc->entry; - char *start = kmap(page), - *p = start; int loop_count = 0, - status = 0; + status; - for(;;) { - p = (char *)desc->decode((u32*)p, entry, desc->plus); - if (IS_ERR(p)) { - status = PTR_ERR(p); - break; - } - desc->page_offset = p - start; + while((status = dir_decode(desc)) == 0) { dfprintk(VFS, "NFS: found cookie %Lu\n", (long long)entry->cookie); if (entry->prev_cookie == desc->target) break; @@ -167,7 +178,6 @@ schedule(); } } - kunmap(page); dfprintk(VFS, "NFS: find_dirent() returns %d\n", status); return status; } @@ -181,17 +191,12 @@ { struct inode *inode = desc->file->f_dentry->d_inode; struct page *page; - unsigned long index = desc->page_index; int status; dfprintk(VFS, "NFS: find_dirent_page() searching directory page %ld\n", desc->page_index); - if (desc->page) { - page_cache_release(desc->page); - desc->page = NULL; - } - - page = read_cache_page(&inode->i_data, index, + desc->plus = NFS_USE_READDIRPLUS(inode); + page = read_cache_page(&inode->i_data, desc->page_index, (filler_t *)nfs_readdir_filler, desc); if (IS_ERR(page)) { status = PTR_ERR(page); @@ -201,12 +206,11 @@ goto read_error; /* NOTE: Someone else may have changed the READDIRPLUS flag */ - desc->plus = NFS_USE_READDIRPLUS(inode); + desc->page = page; + desc->ptr = kmap(page); status = find_dirent(desc, page); - if (status >= 0) - desc->page = page; - else - page_cache_release(page); + if (status < 0) + dir_page_release(desc); out: dfprintk(VFS, "NFS: find_dirent_page() returns %d\n", status); return status; @@ -224,8 +228,8 @@ static inline int readdir_search_pagecache(nfs_readdir_descriptor_t *desc) { - int res = 0; int loop_count = 0; + int res; dfprintk(VFS, "NFS: readdir_search_pagecache() searching for cookie %Lu\n", (long long)desc->target); for (;;) { @@ -233,7 +237,6 @@ if (res != -EAGAIN) break; /* Align to beginning of next page */ - desc->page_offset = 0; desc->page_index ++; if (loop_count++ > 200) { loop_count = 0; @@ -253,11 +256,9 @@ { struct file *file = desc->file; struct nfs_entry *entry = desc->entry; - char *start = kmap(desc->page), - *p = start + desc->page_offset; unsigned long fileid; int loop_count = 0, - res = 0; + res; dfprintk(VFS, "NFS: nfs_do_filldir() filling starting @ cookie %Lu\n", (long long)desc->target); @@ -270,23 +271,16 @@ if (res < 0) break; file->f_pos = desc->target = entry->cookie; - p = (char *)desc->decode((u32 *)p, entry, desc->plus); - if (IS_ERR(p)) { - if (PTR_ERR(p) == -EAGAIN) { - desc->page_offset = 0; - desc->page_index ++; - } + if (dir_decode(desc) != 0) { + desc->page_index ++; break; } - desc->page_offset = p - start; if (loop_count++ > 200) { loop_count = 0; schedule(); } } - kunmap(desc->page); - page_cache_release(desc->page); - desc->page = NULL; + dir_page_release(desc); dfprintk(VFS, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n", (long long)desc->target, res); return res; @@ -312,49 +306,40 @@ struct inode *inode = file->f_dentry->d_inode; struct rpc_cred *cred = nfs_file_cred(file); struct page *page = NULL; - u32 *p; - int status = -EIO; + int status; dfprintk(VFS, "NFS: uncached_readdir() searching for cookie %Lu\n", (long long)desc->target); - if (desc->page) { - page_cache_release(desc->page); - desc->page = NULL; - } page = alloc_page(GFP_HIGHUSER); if (!page) { status = -ENOMEM; goto out; } - p = kmap(page); - status = NFS_PROTO(inode)->readdir(inode, cred, desc->target, p, - NFS_SERVER(inode)->dtsize, 0); - if (status >= 0) { - p = desc->decode(p, desc->entry, 0); - if (IS_ERR(p)) - status = PTR_ERR(p); - else + desc->page = page; + desc->ptr = kmap(page); + desc->error = NFS_PROTO(inode)->readdir(inode, cred, desc->target, + desc->ptr, + NFS_SERVER(inode)->dtsize, + desc->plus); + if (desc->error >= 0) { + if ((status = dir_decode(desc)) == 0) desc->entry->prev_cookie = desc->target; - } - kunmap(page); + } else + status = -EIO; if (status < 0) goto out_release; - desc->page_index = 0; - desc->page_offset = 0; - desc->page = page; status = nfs_do_filldir(desc, dirent, filldir); /* Reset read descriptor so it searches the page cache from * the start upon the next call to readdir_search_pagecache() */ desc->page_index = 0; - desc->page_offset = 0; memset(desc->entry, 0, sizeof(*desc->entry)); out: dfprintk(VFS, "NFS: uncached_readdir() returns %d\n", status); return status; out_release: - page_cache_release(page); + dir_page_release(desc); goto out; } @@ -392,16 +377,15 @@ res = readdir_search_pagecache(desc); if (res == -EBADCOOKIE) { /* This means either end of directory */ - if (desc->entry->cookie == desc->target) { - res = 0; - break; + if (desc->entry->cookie != desc->target) { + /* Or that the server has 'lost' a cookie */ + res = uncached_readdir(desc, dirent, filldir); + if (res >= 0) + continue; } - /* Or that the server has 'lost' a cookie */ - res = uncached_readdir(desc, dirent, filldir); - if (res >= 0) - continue; - } - if (res < 0) + res = 0; + break; + } else if (res < 0) break; res = nfs_do_filldir(desc, dirent, filldir); @@ -410,8 +394,6 @@ break; } } - if (desc->page) - page_cache_release(desc->page); if (desc->error < 0) return desc->error; if (res < 0) @@ -753,6 +735,8 @@ nfs_zap_caches(dir); error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name); + if (!error) + dentry->d_inode->i_nlink = 0; return error; } @@ -870,6 +854,8 @@ error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); if (error < 0) goto out; + if (inode) + inode->i_nlink--; out_delete: /* diff -u --recursive --new-file v2.4.5/linux/fs/nfs/inode.c linux/fs/nfs/inode.c --- v2.4.5/linux/fs/nfs/inode.c Sat May 19 18:14:38 2001 +++ linux/fs/nfs/inode.c Wed Jun 27 14:02:29 2001 @@ -100,6 +100,8 @@ inode->i_blksize = inode->i_sb->s_blocksize; inode->i_mode = 0; inode->i_rdev = 0; + /* We can't support UPDATE_ATIME(), since the server will reset it */ + inode->i_flags |= S_NOATIME; NFS_FILEID(inode) = 0; NFS_FSID(inode) = 0; NFS_FLAGS(inode) = 0; @@ -973,12 +975,9 @@ NFS_CACHE_CTIME(inode) = fattr->ctime; inode->i_ctime = nfs_time_to_secs(fattr->ctime); - /* If we've been messing around with atime, don't - * update it. Save the server value in NFS_CACHE_ATIME. - */ + NFS_CACHE_ATIME(inode) = fattr->atime; - if (time_before(inode->i_atime, nfs_time_to_secs(fattr->atime))) - inode->i_atime = nfs_time_to_secs(fattr->atime); + inode->i_atime = nfs_time_to_secs(fattr->atime); NFS_CACHE_MTIME(inode) = new_mtime; inode->i_mtime = nfs_time_to_secs(new_mtime); diff -u --recursive --new-file v2.4.5/linux/fs/nfsd/export.c linux/fs/nfsd/export.c --- v2.4.5/linux/fs/nfsd/export.c Fri Feb 9 11:29:44 2001 +++ linux/fs/nfsd/export.c Mon Jul 2 14:14:59 2001 @@ -213,7 +213,8 @@ err = -EINVAL; if (!(inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) || - inode->i_sb->s_op->read_inode == NULL) { + (inode->i_sb->s_op->read_inode == NULL + && inode->i_sb->s_op->fh_to_dentry == NULL)) { dprintk("exp_export: export of invalid fs type.\n"); goto finish; } @@ -427,7 +428,7 @@ * fh must be initialized before calling fh_compose */ fh_init(&fh, maxsize); - if (fh_compose(&fh, exp, dget(nd.dentry))) + if (fh_compose(&fh, exp, dget(nd.dentry), NULL)) err = -EINVAL; else err = 0; diff -u --recursive --new-file v2.4.5/linux/fs/nfsd/nfs3proc.c linux/fs/nfsd/nfs3proc.c --- v2.4.5/linux/fs/nfsd/nfs3proc.c Wed Apr 25 14:58:17 2001 +++ linux/fs/nfsd/nfs3proc.c Mon Jul 2 14:14:59 2001 @@ -91,7 +91,8 @@ SVCFH_fmt(&argp->fh)); fh_copy(&resp->fh, &argp->fh); - nfserr = nfsd_setattr(rqstp, &resp->fh, &argp->attrs); + nfserr = nfsd_setattr(rqstp, &resp->fh, &argp->attrs, + argp->check_guard, argp->guardtime); RETURN_STATUS(nfserr); } diff -u --recursive --new-file v2.4.5/linux/fs/nfsd/nfs3xdr.c linux/fs/nfsd/nfs3xdr.c --- v2.4.5/linux/fs/nfsd/nfs3xdr.c Sat May 19 18:02:45 2001 +++ linux/fs/nfsd/nfs3xdr.c Mon Jul 2 14:14:59 2001 @@ -716,7 +716,7 @@ dchild = lookup_one_len(name, dparent,namlen); if (IS_ERR(dchild)) goto noexec; - if (fh_compose(&fh, exp, dchild) != 0 || !dchild->d_inode) + if (fh_compose(&fh, exp, dchild, cd->dirfh) != 0 || !dchild->d_inode) goto noexec; p = encode_post_op_attr(cd->rqstp, p, fh.fh_dentry); *p++ = xdr_one; /* yes, a file handle follows */ diff -u --recursive --new-file v2.4.5/linux/fs/nfsd/nfsfh.c linux/fs/nfsd/nfsfh.c --- v2.4.5/linux/fs/nfsd/nfsfh.c Sat May 19 17:47:55 2001 +++ linux/fs/nfsd/nfsfh.c Mon Jul 2 14:14:59 2001 @@ -134,7 +134,11 @@ struct inode *inode; struct list_head *lp; struct dentry *result; + if (ino == 0) + return ERR_PTR(-ESTALE); inode = iget(sb, ino); + if (inode == NULL) + return ERR_PTR(-ENOMEM); if (is_bad_inode(inode) || (generation && inode->i_generation != generation) ) { @@ -169,10 +173,34 @@ return ERR_PTR(-ENOMEM); } result->d_flags |= DCACHE_NFSD_DISCONNECTED; - d_rehash(result); /* so a dput won't loose it */ return result; } +static struct dentry *nfsd_get_dentry(struct super_block *sb, __u32 *fh, + int len, int fhtype, int parent) +{ + if (sb->s_op->fh_to_dentry) + return sb->s_op->fh_to_dentry(sb, fh, len, fhtype, parent); + switch (fhtype) { + case 1: + if (len < 2) + break; + if (parent) + break; + return nfsd_iget(sb, fh[0], fh[1]); + + case 2: + if (len < 3) + break; + if (parent) + return nfsd_iget(sb,fh[2],0); + return nfsd_iget(sb,fh[0],fh[1]); + default: break; + } + return ERR_PTR(-EINVAL); +} + + /* this routine links an IS_ROOT dentry into the dcache tree. It gains "parent" * as a parent and "name" as a name * It should possibly go in dcache.c @@ -196,7 +224,7 @@ * make it an IS_ROOT instead */ spin_lock(&dcache_lock); - list_del(&tdentry->d_child); + list_del_init(&tdentry->d_child); tdentry->d_parent = tdentry; spin_unlock(&dcache_lock); d_rehash(target); @@ -270,10 +298,10 @@ } spin_unlock(&dcache_lock); if (pdentry == NULL) { - pdentry = d_alloc_root(igrab(tdentry->d_inode)); + pdentry = d_alloc_root(tdentry->d_inode); if (pdentry) { + igrab(tdentry->d_inode); pdentry->d_flags |= DCACHE_NFSD_DISCONNECTED; - d_rehash(pdentry); } } if (pdentry == NULL) @@ -347,11 +375,10 @@ * connection if made. */ static struct dentry * -find_fh_dentry(struct super_block *sb, ino_t ino, int generation, ino_t dirino, int needpath) +find_fh_dentry(struct super_block *sb, __u32 *datap, int len, int fhtype, int needpath) { struct dentry *dentry, *result = NULL; struct dentry *tmp; - int found =0; int err = -ESTALE; /* the sb->s_nfsd_free_path_sem semaphore is needed to make sure that only one unconnected (free) * dcache path ever exists, as otherwise two partial paths might get @@ -367,7 +394,7 @@ */ retry: down(&sb->s_nfsd_free_path_sem); - result = nfsd_iget(sb, ino, generation); + result = nfsd_get_dentry(sb, datap, len, fhtype, 0); if (IS_ERR(result) || !(result->d_flags & DCACHE_NFSD_DISCONNECTED) || (!S_ISDIR(result->d_inode->i_mode) && ! needpath)) { @@ -384,16 +411,12 @@ /* It's a directory, or we are required to confirm the file's * location in the tree. */ - dprintk("nfs_fh: need to look harder for %d/%ld\n",sb->s_dev,ino); + dprintk("nfs_fh: need to look harder for %d/%d\n",sb->s_dev,datap[0]); - found = 0; if (!S_ISDIR(result->d_inode->i_mode)) { nfsdstats.fh_nocache_nondir++; - if (dirino == 0) - goto err_result; /* don't know how to find parent */ - else { /* need to iget dirino and make sure this inode is in that directory */ - dentry = nfsd_iget(sb, dirino, 0); + dentry = nfsd_get_dentry(sb, datap, len, fhtype, 1); err = PTR_ERR(dentry); if (IS_ERR(dentry)) goto err_result; @@ -402,8 +425,6 @@ || !S_ISDIR(dentry->d_inode->i_mode)) { goto err_dentry; } - if (!(dentry->d_flags & DCACHE_NFSD_DISCONNECTED)) - found = 1; tmp = splice(result, dentry); err = PTR_ERR(tmp); if (IS_ERR(tmp)) @@ -413,15 +434,13 @@ d_drop(result); dput(result); result = tmp; - /* If !found, then this is really weird, but it shouldn't hurt */ } - } } else { nfsdstats.fh_nocache_dir++; dentry = dget(result); } - while(!found) { + while(dentry->d_flags & DCACHE_NFSD_DISCONNECTED) { /* LOOP INVARIANT */ /* haven't found a place in the tree yet, but we do have a free path * from dentry down to result, and dentry is a directory. @@ -440,12 +459,9 @@ goto err_dentry; } - if (!(dentry->d_flags & DCACHE_NFSD_DISCONNECTED)) - found = 1; - tmp = splice(dentry, pdentry); if (tmp != dentry) { - /* Something wrong. We need to drop thw whole dentry->result path + /* Something wrong. We need to drop the whole dentry->result path * whatever it was */ struct dentry *d; @@ -580,31 +596,23 @@ case 0: dentry = dget(exp->ex_dentry); break; - case 1: - if ((data_left-=2)<0) goto out; - dentry = find_fh_dentry(exp->ex_dentry->d_inode->i_sb, - datap[0], datap[1], - 0, - !(exp->ex_flags & NFSEXP_NOSUBTREECHECK)); - break; - case 2: - if ((data_left-=3)<0) goto out; + default: dentry = find_fh_dentry(exp->ex_dentry->d_inode->i_sb, - datap[0], datap[1], - datap[2], + datap, data_left, fh->fh_fileid_type, !(exp->ex_flags & NFSEXP_NOSUBTREECHECK)); - break; - default: goto out; } } else { - + __u32 tfh[3]; + tfh[0] = fh->ofh_ino; + tfh[1] = fh->ofh_generation; + tfh[2] = fh->ofh_dirino; dentry = find_fh_dentry(exp->ex_dentry->d_inode->i_sb, - fh->ofh_ino, fh->ofh_generation, - fh->ofh_dirino, + tfh, 3, fh->ofh_dirino?2:1, !(exp->ex_flags & NFSEXP_NOSUBTREECHECK)); } if (IS_ERR(dentry)) { - error = nfserrno(PTR_ERR(dentry)); + if (PTR_ERR(dentry) != EINVAL) + error = nfserrno(PTR_ERR(dentry)); goto out; } #ifdef NFSD_PARANOIA @@ -709,9 +717,20 @@ __u32 **datapp, int maxsize) { __u32 *datap= *datapp; + struct super_block *sb = dentry->d_inode->i_sb; + if (dentry == exp->ex_dentry) return 0; - /* if super_operations provides dentry_to_fh lookup, should use that */ + + if (sb->s_op->dentry_to_fh) { + int need_parent = !S_ISDIR(dentry->d_inode->i_mode) && + !(exp->ex_flags & NFSEXP_NOSUBTREECHECK); + + int type = sb->s_op->dentry_to_fh(dentry, datap, &maxsize, need_parent); + datap += maxsize; + *datapp = datap; + return type; + } *datap++ = ino_t_to_u32(dentry->d_inode->i_ino); *datap++ = dentry->d_inode->i_generation; @@ -724,9 +743,31 @@ return 2; } +/* + * for composing old style file handles + */ +inline void _fh_update_old(struct dentry *dentry, struct svc_export *exp, + struct knfsd_fh *fh) +{ + fh->ofh_ino = ino_t_to_u32(dentry->d_inode->i_ino); + fh->ofh_generation = dentry->d_inode->i_generation; + if (S_ISDIR(dentry->d_inode->i_mode) || + (exp->ex_flags & NFSEXP_NOSUBTREECHECK)) + fh->ofh_dirino = 0; +} + int -fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry) +fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, struct svc_fh *ref_fh) { + /* ref_fh is a reference file handle. + * if it is non-null, then we should compose a filehandle which is + * of the same version, where possible. + * Currently, that means that if ref_fh->fh_handle.fh_version == 0xca + * Then create a 32byte filehandle using nfs_fhbase_old + * But only do this if dentry_to_fh is not available + * + */ + struct inode * inode = dentry->d_inode; struct dentry *parent = dentry->d_parent; __u32 *datap; @@ -747,20 +788,32 @@ fhp->fh_dentry = dentry; /* our internal copy */ fhp->fh_export = exp; - fhp->fh_handle.fh_version = 1; - fhp->fh_handle.fh_auth_type = 0; - fhp->fh_handle.fh_fsid_type = 0; - datap = fhp->fh_handle.fh_auth+0; - /* fsid_type 0 == 2byte major, 2byte minor, 4byte inode */ - *datap++ = htonl((MAJOR(exp->ex_dev)<<16)| MINOR(exp->ex_dev)); - *datap++ = ino_t_to_u32(exp->ex_ino); - - if (inode) - fhp->fh_handle.fh_fileid_type = - _fh_update(dentry, exp, &datap, fhp->fh_maxsize-3); - - fhp->fh_handle.fh_size = (datap-fhp->fh_handle.fh_auth+1)*4; - + if (ref_fh && + ref_fh->fh_handle.fh_version == 0xca && + parent->d_inode->i_sb->s_op->dentry_to_fh == NULL) { + /* old style filehandle please */ + memset(&fhp->fh_handle.fh_base, 0, NFS_FHSIZE); + fhp->fh_handle.fh_size = NFS_FHSIZE; + fhp->fh_handle.ofh_dcookie = 0xfeebbaca; + fhp->fh_handle.ofh_dev = htonl((MAJOR(exp->ex_dev)<<16)| MINOR(exp->ex_dev)); + fhp->fh_handle.ofh_xdev = fhp->fh_handle.ofh_dev; + fhp->fh_handle.ofh_xino = ino_t_to_u32(exp->ex_ino); + fhp->fh_handle.ofh_dirino = ino_t_to_u32(dentry->d_parent->d_inode->i_ino); + if (inode) + _fh_update_old(dentry, exp, &fhp->fh_handle); + } else { + fhp->fh_handle.fh_version = 1; + fhp->fh_handle.fh_auth_type = 0; + fhp->fh_handle.fh_fsid_type = 0; + datap = fhp->fh_handle.fh_auth+0; + /* fsid_type 0 == 2byte major, 2byte minor, 4byte inode */ + *datap++ = htonl((MAJOR(exp->ex_dev)<<16)| MINOR(exp->ex_dev)); + *datap++ = ino_t_to_u32(exp->ex_ino); + if (inode) + fhp->fh_handle.fh_fileid_type = + _fh_update(dentry, exp, &datap, fhp->fh_maxsize-3); + fhp->fh_handle.fh_size = (datap-fhp->fh_handle.fh_auth+1)*4; + } nfsd_nr_verified++; if (fhp->fh_handle.fh_fileid_type == 255) @@ -786,11 +839,15 @@ goto out_negative; if (fhp->fh_handle.fh_fileid_type != 0) goto out_uptodate; - datap = fhp->fh_handle.fh_auth+ - fhp->fh_handle.fh_size/4 -1; - fhp->fh_handle.fh_fileid_type = - _fh_update(dentry, fhp->fh_export, &datap, fhp->fh_maxsize-fhp->fh_handle.fh_size); - fhp->fh_handle.fh_size = (datap-fhp->fh_handle.fh_auth+1)*4; + if (fhp->fh_handle.fh_version != 1) { + _fh_update_old(dentry, fhp->fh_export, &fhp->fh_handle); + } else { + datap = fhp->fh_handle.fh_auth+ + fhp->fh_handle.fh_size/4 -1; + fhp->fh_handle.fh_fileid_type = + _fh_update(dentry, fhp->fh_export, &datap, fhp->fh_maxsize-fhp->fh_handle.fh_size); + fhp->fh_handle.fh_size = (datap-fhp->fh_handle.fh_auth+1)*4; + } out: return 0; diff -u --recursive --new-file v2.4.5/linux/fs/nfsd/nfsproc.c linux/fs/nfsd/nfsproc.c --- v2.4.5/linux/fs/nfsd/nfsproc.c Sat May 19 18:02:45 2001 +++ linux/fs/nfsd/nfsproc.c Mon Jul 2 14:14:59 2001 @@ -71,7 +71,7 @@ argp->attrs.ia_valid, (long) argp->attrs.ia_size); fh_copy(&resp->fh, &argp->fh); - return nfsd_setattr(rqstp, &resp->fh, &argp->attrs); + return nfsd_setattr(rqstp, &resp->fh, &argp->attrs,0, (time_t)0); } /* @@ -222,7 +222,7 @@ goto out_unlock; } fh_init(newfhp, NFS_FHSIZE); - nfserr = fh_compose(newfhp, dirfhp->fh_export, dchild); + nfserr = fh_compose(newfhp, dirfhp->fh_export, dchild, dirfhp); if (!nfserr && !dchild->d_inode) nfserr = nfserr_noent; if (nfserr) { @@ -331,7 +331,7 @@ */ attr->ia_valid &= ATTR_SIZE; if (attr->ia_valid) - nfserr = nfsd_setattr(rqstp, newfhp, attr); + nfserr = nfsd_setattr(rqstp, newfhp, attr, 0, (time_t)0); } out_unlock: diff -u --recursive --new-file v2.4.5/linux/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c --- v2.4.5/linux/fs/nfsd/vfs.c Sat May 19 18:02:45 2001 +++ linux/fs/nfsd/vfs.c Mon Jul 2 14:14:59 2001 @@ -176,7 +176,7 @@ * Note: we compose the file handle now, but as the * dentry may be negative, it may need to be updated. */ - err = fh_compose(resfh, exp, dentry); + err = fh_compose(resfh, exp, dentry, fhp); if (!err && !dentry->d_inode) err = nfserr_noent; out: @@ -192,7 +192,8 @@ * N.B. After this call fhp needs an fh_put */ int -nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap) +nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, + int check_guard, time_t guardtime) { struct dentry *dentry; struct inode *inode; @@ -310,21 +311,23 @@ fh_lock(fhp); size_change = 1; } + err = nfserr_notsync; + if (!check_guard || guardtime == inode->i_ctime) { #ifdef CONFIG_QUOTA - if (iap->ia_valid & (ATTR_UID|ATTR_GID)) - err = DQUOT_TRANSFER(dentry, iap); - else + if (iap->ia_valid & (ATTR_UID|ATTR_GID)) + err = DQUOT_TRANSFER(dentry, iap); + else #endif - err = notify_change(dentry, iap); + err = notify_change(dentry, iap); + err = nfserrno(err); + } if (size_change) { fh_unlock(fhp); put_write_access(inode); } - if (err) - goto out_nfserr; - if (EX_ISSYNC(fhp->fh_export)) - write_inode_now(inode, 1); - err = 0; + if (!err) + if (EX_ISSYNC(fhp->fh_export)) + write_inode_now(inode, 1); out: return err; @@ -849,7 +852,7 @@ err = PTR_ERR(dchild); if (IS_ERR(dchild)) goto out_nfserr; - err = fh_compose(resfhp, fhp->fh_export, dchild); + err = fh_compose(resfhp, fhp->fh_export, dchild, fhp); if (err) goto out; } else { @@ -916,7 +919,7 @@ */ err = 0; if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0) - err = nfsd_setattr(rqstp, resfhp, iap); + err = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); /* * Update the file handle to get the new inode info. */ @@ -975,7 +978,7 @@ if (IS_ERR(dchild)) goto out_nfserr; - err = fh_compose(resfhp, fhp->fh_export, dchild); + err = fh_compose(resfhp, fhp->fh_export, dchild, fhp); if (err) goto out; @@ -1051,7 +1054,7 @@ */ set_attr: if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0) - err = nfsd_setattr(rqstp, resfhp, iap); + err = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); out: fh_unlock(fhp); @@ -1159,7 +1162,7 @@ fh_unlock(fhp); /* Compose the fh so the dentry will be freed ... */ - cerr = fh_compose(resfhp, fhp->fh_export, dnew); + cerr = fh_compose(resfhp, fhp->fh_export, dnew, fhp); if (err==0) err = cerr; out: return err; diff -u --recursive --new-file v2.4.5/linux/fs/nls/Config.in linux/fs/nls/Config.in --- v2.4.5/linux/fs/nls/Config.in Sat May 19 17:47:55 2001 +++ linux/fs/nls/Config.in Wed Jun 27 17:10:55 2001 @@ -29,7 +29,7 @@ tristate 'Codepage 852 (Central/Eastern Europe)' CONFIG_NLS_CODEPAGE_852 tristate 'Codepage 855 (Cyrillic)' CONFIG_NLS_CODEPAGE_855 tristate 'Codepage 857 (Turkish)' CONFIG_NLS_CODEPAGE_857 - tristate 'Codepage 860 (Portugese)' CONFIG_NLS_CODEPAGE_860 + tristate 'Codepage 860 (Portuguese)' CONFIG_NLS_CODEPAGE_860 tristate 'Codepage 861 (Icelandic)' CONFIG_NLS_CODEPAGE_861 tristate 'Codepage 862 (Hebrew)' CONFIG_NLS_CODEPAGE_862 tristate 'Codepage 863 (Canadian French)' CONFIG_NLS_CODEPAGE_863 @@ -43,7 +43,7 @@ tristate 'Korean charset (CP949, EUC-KR)' CONFIG_NLS_CODEPAGE_949 tristate 'Thai charset (CP874, TIS-620)' CONFIG_NLS_CODEPAGE_874 tristate 'Hebrew charsets (ISO-8859-8, CP1255)' CONFIG_NLS_ISO8859_8 - tristate 'Windows CP1251 (Bulgarian, Belarussian)' CONFIG_NLS_CODEPAGE_1251 + tristate 'Windows CP1251 (Bulgarian, Belarusian)' CONFIG_NLS_CODEPAGE_1251 tristate 'NLS ISO 8859-1 (Latin 1; Western European Languages)' CONFIG_NLS_ISO8859_1 tristate 'NLS ISO 8859-2 (Latin 2; Slavic/Central European Languages)' CONFIG_NLS_ISO8859_2 tristate 'NLS ISO 8859-3 (Latin 3; Esperanto, Galician, Maltese, Turkish)' CONFIG_NLS_ISO8859_3 @@ -56,7 +56,7 @@ tristate 'NLS ISO 8859-14 (Latin 8; Celtic)' CONFIG_NLS_ISO8859_14 tristate 'NLS ISO 8859-15 (Latin 9; Western European Languages with Euro)' CONFIG_NLS_ISO8859_15 tristate 'NLS KOI8-R (Russian)' CONFIG_NLS_KOI8_R - tristate 'NLS KOI8-U/RU (Ukrainian, Belarussian)' CONFIG_NLS_KOI8_U + tristate 'NLS KOI8-U/RU (Ukrainian, Belarusian)' CONFIG_NLS_KOI8_U tristate 'NLS UTF8' CONFIG_NLS_UTF8 endmenu fi diff -u --recursive --new-file v2.4.5/linux/fs/partitions/check.c linux/fs/partitions/check.c --- v2.4.5/linux/fs/partitions/check.c Wed May 16 14:01:32 2001 +++ linux/fs/partitions/check.c Tue Jun 12 11:17:17 2001 @@ -418,11 +418,10 @@ blk_size[dev->major] = NULL; dev->part[first_minor].nr_sects = size; - /* No Such Agen^Wdevice or no minors to use for partitions */ + /* No such device or no minors to use for partitions */ if (!size || minors == 1) return; - blk_size[dev->major] = NULL; check_partition(dev, MKDEV(dev->major, first_minor), 1 + first_minor); /* diff -u --recursive --new-file v2.4.5/linux/fs/proc/array.c linux/fs/proc/array.c --- v2.4.5/linux/fs/proc/array.c Fri May 4 14:44:06 2001 +++ linux/fs/proc/array.c Tue Jun 12 17:27:29 2001 @@ -421,13 +421,12 @@ ++*total; if (!pte_present(page)) continue; + ptpage = pte_page(page); + if ((!VALID_PAGE(ptpage)) || PageReserved(ptpage)) + continue; ++*pages; if (pte_dirty(page)) ++*dirty; - ptpage = pte_page(page); - if ((!VALID_PAGE(ptpage)) || - PageReserved(ptpage)) - continue; if (page_count(pte_page(page)) > 1) ++*shared; } while (address < end); diff -u --recursive --new-file v2.4.5/linux/fs/proc/base.c linux/fs/proc/base.c --- v2.4.5/linux/fs/proc/base.c Fri May 4 14:44:06 2001 +++ linux/fs/proc/base.c Tue Jul 3 08:04:00 2001 @@ -312,6 +312,13 @@ #define MAY_PTRACE(p) \ (p==current||(p->p_pptr==current&&(p->ptrace & PT_PTRACED)&&p->state==TASK_STOPPED)) + +static int mem_open(struct inode* inode, struct file* file) +{ + file->private_data = (void*)((long)current->self_exec_id); + return 0; +} + static ssize_t mem_read(struct file * file, char * buf, size_t count, loff_t *ppos) { @@ -319,6 +326,8 @@ char *page; unsigned long src = *ppos; int copied = 0; + struct mm_struct *mm; + if (!MAY_PTRACE(task)) return -ESRCH; @@ -327,6 +336,20 @@ if (!page) return -ENOMEM; + task_lock(task); + mm = task->mm; + if (mm) + atomic_inc(&mm->mm_users); + task_unlock(task); + if (!mm) + return 0; + + if (file->private_data != (void*)((long)current->self_exec_id) ) { + mmput(mm); + return -EIO; + } + + while (count > 0) { int this_len, retval; @@ -347,6 +370,7 @@ count -= retval; } *ppos = src; + mmput(mm); free_page((unsigned long) page); return copied; } @@ -398,6 +422,7 @@ static struct file_operations proc_mem_operations = { read: mem_read, write: mem_write, + open: mem_open, }; static struct inode_operations proc_mem_inode_operations = { @@ -635,15 +660,14 @@ inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_ino = fake_ino(task->pid, ino); - inode->u.proc_i.file = NULL; + if (!task->pid) + goto out_unlock; + /* * grab the reference to task. */ - inode->u.proc_i.task = task; get_task_struct(task); - if (!task->pid) - goto out_unlock; - + inode->u.proc_i.task = task; inode->i_uid = 0; inode->i_gid = 0; if (ino == PROC_PID_INO || task->dumpable) { diff -u --recursive --new-file v2.4.5/linux/fs/proc/generic.c linux/fs/proc/generic.c --- v2.4.5/linux/fs/proc/generic.c Fri May 25 17:56:44 2001 +++ linux/fs/proc/generic.c Sat Jun 30 21:42:21 2001 @@ -190,15 +190,24 @@ return 0; } -static unsigned char proc_alloc_map[PROC_NDYNAMIC / 8]; +static unsigned long proc_alloc_map[(PROC_NDYNAMIC + BITS_PER_LONG - 1) / BITS_PER_LONG]; + +spinlock_t proc_alloc_map_lock = SPIN_LOCK_UNLOCKED; static int make_inode_number(void) { - int i = find_first_zero_bit((void *) proc_alloc_map, PROC_NDYNAMIC); - if (i<0 || i>=PROC_NDYNAMIC) - return -1; - set_bit(i, (void *) proc_alloc_map); - return PROC_DYNAMIC_FIRST + i; + int i; + spin_lock(&proc_alloc_map_lock); + i = find_first_zero_bit(proc_alloc_map, PROC_NDYNAMIC); + if (i < 0 || i >= PROC_NDYNAMIC) { + i = -1; + goto out; + } + set_bit(i, proc_alloc_map); + i += PROC_DYNAMIC_FIRST; +out: + spin_unlock(&proc_alloc_map_lock); + return i; } static int proc_readlink(struct dentry *dentry, char *buffer, int buflen) @@ -546,8 +555,8 @@ de->next = NULL; if (S_ISDIR(de->mode)) parent->nlink--; - clear_bit(de->low_ino-PROC_DYNAMIC_FIRST, - (void *) proc_alloc_map); + clear_bit(de->low_ino - PROC_DYNAMIC_FIRST, + proc_alloc_map); proc_kill_inodes(de); de->nlink = 0; if (!atomic_read(&de->count)) diff -u --recursive --new-file v2.4.5/linux/fs/reiserfs/dir.c linux/fs/reiserfs/dir.c --- v2.4.5/linux/fs/reiserfs/dir.c Fri Mar 2 10:06:47 2001 +++ linux/fs/reiserfs/dir.c Fri Jun 29 15:36:23 2001 @@ -157,7 +157,7 @@ if (d_reclen <= 32) { local_buf = small_buf ; } else { - local_buf = kmalloc(d_reclen, GFP_BUFFER) ; + local_buf = kmalloc(d_reclen, GFP_NOFS) ; if (!local_buf) { pathrelse (&path_to_entry); return -ENOMEM ; diff -u --recursive --new-file v2.4.5/linux/fs/reiserfs/fix_node.c linux/fs/reiserfs/fix_node.c --- v2.4.5/linux/fs/reiserfs/fix_node.c Fri Apr 13 20:26:07 2001 +++ linux/fs/reiserfs/fix_node.c Fri Jun 29 15:36:49 2001 @@ -936,6 +936,7 @@ if (p_s_tb->FEB[p_s_tb->cur_blknum]) BUG(); + mark_buffer_journal_new(p_s_new_bh) ; p_s_tb->FEB[p_s_tb->cur_blknum++] = p_s_new_bh; } @@ -2249,7 +2250,7 @@ dcache shrinking). So, release path and collected resourses here */ free_buffers_in_tb (tb); - buf = reiserfs_kmalloc(size, GFP_BUFFER, tb->tb_sb); + buf = reiserfs_kmalloc(size, GFP_NOFS, tb->tb_sb); if ( !buf ) { #ifdef CONFIG_REISERFS_CHECK reiserfs_warning ("vs-8345: get_mem_for_virtual_node: " @@ -2719,12 +2720,6 @@ { int i; -#ifdef CONFIG_REISERFS_CHECK - if ( ! tb->vn_buf ) - reiserfs_panic (tb->tb_sb, - "PAP-16050: unfix_nodes: pointer to the virtual node is NULL"); -#endif - /* Release path buffers. */ pathrelse_and_restore (tb->tb_sb, tb->tb_path); @@ -2781,7 +2776,8 @@ } } #endif /* 0 */ - reiserfs_kfree (tb->vn_buf, tb->vn_buf_size, tb->tb_sb); + if (tb->vn_buf) + reiserfs_kfree (tb->vn_buf, tb->vn_buf_size, tb->tb_sb); } diff -u --recursive --new-file v2.4.5/linux/fs/reiserfs/inode.c linux/fs/reiserfs/inode.c --- v2.4.5/linux/fs/reiserfs/inode.c Fri Apr 27 14:18:08 2001 +++ linux/fs/reiserfs/inode.c Mon Jul 2 14:48:43 2001 @@ -21,6 +21,7 @@ #define GET_BLOCK_CREATE 1 /* add anything you need to find block */ #define GET_BLOCK_NO_HOLE 2 /* return -ENOENT for file holes */ #define GET_BLOCK_READ_DIRECT 4 /* read the tail if indirect item not found */ +#define GET_BLOCK_NO_ISEM 8 /* i_sem is not held, don't preallocate */ // // initially this function was derived from minix or ext2's analog and @@ -539,6 +540,19 @@ return retval ; } +static inline int _allocate_block(struct reiserfs_transaction_handle *th, + struct inode *inode, + b_blocknr_t *allocated_block_nr, + unsigned long tag, + int flags) { + +#ifdef REISERFS_PREALLOCATE + if (!(flags & GET_BLOCK_NO_ISEM)) { + return reiserfs_new_unf_blocknrs2(th, inode, allocated_block_nr, tag); + } +#endif + return reiserfs_new_unf_blocknrs (th, allocated_block_nr, tag); +} // // initially this function was derived from ext2's analog and evolved // as the prototype did. You'll need to look at the ext2 version to @@ -632,11 +646,7 @@ goto research ; } -#ifdef REISERFS_PREALLOCATE - repeat = reiserfs_new_unf_blocknrs2 (&th, inode, &allocated_block_nr, tag); -#else - repeat = reiserfs_new_unf_blocknrs (&th, &allocated_block_nr, tag); -#endif + repeat = _allocate_block(&th, inode, &allocated_block_nr, tag, create); if (repeat == NO_DISK_SPACE) { /* restart the transaction to give the journal a chance to free @@ -644,11 +654,7 @@ ** research if we succeed on the second try */ restart_transaction(&th, inode, &path) ; -#ifdef REISERFS_PREALLOCATE - repeat = reiserfs_new_unf_blocknrs2 (&th, inode, &allocated_block_nr, tag); -#else - repeat = reiserfs_new_unf_blocknrs (&th, &allocated_block_nr, tag); -#endif + repeat = _allocate_block(&th, inode,&allocated_block_nr,tag,create); if (repeat != NO_DISK_SPACE) { goto research ; @@ -736,10 +742,6 @@ retval = reiserfs_insert_item (&th, &path, &tmp_key, &tmp_ih, (char *)&unp); if (retval) { reiserfs_free_block (&th, allocated_block_nr); - -#ifdef REISERFS_PREALLOCATE - reiserfs_discard_prealloc (&th, inode); -#endif goto failure; // retval == -ENOSPC or -EIO or -EEXIST } if (unp) @@ -787,10 +789,6 @@ mark_buffer_uptodate (unbh, 1); if (retval) { reiserfs_free_block (&th, allocated_block_nr); - -#ifdef REISERFS_PREALLOCATE - reiserfs_discard_prealloc (&th, inode); -#endif goto failure; } /* we've converted the tail, so we must @@ -832,10 +830,6 @@ retval = reiserfs_paste_into_item (&th, &path, &tmp_key, (char *)&un, UNFM_P_SIZE); if (retval) { reiserfs_free_block (&th, allocated_block_nr); - -#ifdef REISERFS_PREALLOCATE - reiserfs_discard_prealloc (&th, inode); -#endif goto failure; } if (un.unfm_nodenum) @@ -872,6 +866,8 @@ reiserfs_warning ("vs-: reiserfs_get_block: " "%k should not be found", &key); retval = -EEXIST; + if (allocated_block_nr) + reiserfs_free_block (&th, allocated_block_nr); pathrelse(&path) ; goto failure; } @@ -921,6 +917,8 @@ inode->i_generation = INODE_PKEY (inode)->k_dir_id; inode->i_blksize = PAGE_SIZE; + INIT_LIST_HEAD(&inode->u.reiserfs_i.i_prealloc_list) ; + if (stat_data_v1 (ih)) { struct stat_data_v1 * sd = (struct stat_data_v1 *)B_I_PITEM (bh, ih); unsigned long blocks; @@ -1163,7 +1161,7 @@ return; } if (retval != ITEM_FOUND) { - reiserfs_warning ("vs-13042: reiserfs_read_inode2: %K not found\n", &key); + /* a stale NFS handle can trigger this without it being an error */ pathrelse (&path_to_sd); make_bad_inode(inode) ; return; @@ -1185,23 +1183,86 @@ if (!inode) return inode ; - if (is_bad_inode (inode)) { - reiserfs_warning ("vs-13048: reiserfs_iget: " - "bad_inode. Stat data of (%lu %lu) not found\n", - key->on_disk_key.k_dir_id, key->on_disk_key.k_objectid); - iput (inode); - inode = 0; - } else if (comp_short_keys (INODE_PKEY (inode), key)) { - reiserfs_warning ("vs-13049: reiserfs_iget: " - "Looking for (%lu %lu), found inode of (%lu %lu)\n", - key->on_disk_key.k_dir_id, key->on_disk_key.k_objectid, - INODE_PKEY (inode)->k_dir_id, INODE_PKEY (inode)->k_objectid); + if (comp_short_keys (INODE_PKEY (inode), key) || is_bad_inode (inode)) { + /* either due to i/o error or a stale NFS handle */ iput (inode); inode = 0; } return inode; } +struct dentry *reiserfs_fh_to_dentry(struct super_block *sb, __u32 *data, + int len, int fhtype, int parent) { + struct cpu_key key ; + struct inode *inode = NULL ; + struct list_head *lp; + struct dentry *result; + + if (fhtype < 2 || (parent && fhtype < 4)) + goto out ; + + if (! parent) { + /* this works for handles from old kernels because the default + ** reiserfs generation number is the packing locality. + */ + key.on_disk_key.k_objectid = data[0] ; + key.on_disk_key.k_dir_id = data[1] ; + inode = reiserfs_iget(sb, &key) ; + } else { + key.on_disk_key.k_objectid = data[2] ; + key.on_disk_key.k_dir_id = data[3] ; + inode = reiserfs_iget(sb, &key) ; + } +out: + if (!inode) + return ERR_PTR(-ESTALE) ; + + /* now to find a dentry. + * If possible, get a well-connected one + */ + spin_lock(&dcache_lock); + for (lp = inode->i_dentry.next; lp != &inode->i_dentry ; lp=lp->next) { + result = list_entry(lp,struct dentry, d_alias); + if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED)) { + dget_locked(result); + result->d_vfs_flags |= DCACHE_REFERENCED; + spin_unlock(&dcache_lock); + iput(inode); + return result; + } + } + spin_unlock(&dcache_lock); + result = d_alloc_root(inode); + if (result == NULL) { + iput(inode); + return ERR_PTR(-ENOMEM); + } + result->d_flags |= DCACHE_NFSD_DISCONNECTED; + return result; + +} + +int reiserfs_dentry_to_fh(struct dentry *dentry, __u32 *data, int *lenp, int need_parent) { + struct inode *inode = dentry->d_inode ; + int maxlen = *lenp; + + if (maxlen < 2) + return 255 ; + + data[0] = inode->i_ino ; + data[1] = le32_to_cpu(INODE_PKEY (inode)->k_dir_id) ; + *lenp = 2; + /* no room for directory info? return what we've stored so far */ + if (maxlen < 4 || ! need_parent) + return 2 ; + + inode = dentry->d_parent->d_inode ; + data[2] = inode->i_ino ; + data[3] = le32_to_cpu(INODE_PKEY (inode)->k_dir_id) ; + *lenp = 4; + return 4; +} + // // initially this function was derived from minix or ext2's analog and @@ -1223,7 +1284,12 @@ inode->i_ino) ; return ; } - if (do_sync) { + /* memory pressure can sometimes initiate write_inode calls with sync == 1, + ** these cases are just when the system needs ram, not when the + ** inode needs to reach disk for safety, and they can safely be + ** ignored because the altered inode has already been logged. + */ + if (do_sync && !(current->flags & PF_MEMALLOC)) { lock_kernel() ; journal_begin(&th, inode->i_sb, jbegin_count) ; reiserfs_update_sd (&th, inode); @@ -1421,6 +1487,8 @@ inode->u.reiserfs_i.i_first_direct_byte = S_ISLNK(mode) ? 1 : U32_MAX/*NO_BYTES_IN_DIRECT_ITEM*/; + INIT_LIST_HEAD(&inode->u.reiserfs_i.i_prealloc_list) ; + if (old_format_only (sb)) inode2sd_v1 (&sd, inode); else @@ -1723,7 +1791,8 @@ /* this is where we fill in holes in the file. */ if (use_get_block) { kmap(bh_result->b_page) ; - retval = reiserfs_get_block(inode, block, bh_result, 1) ; + retval = reiserfs_get_block(inode, block, bh_result, + GET_BLOCK_CREATE | GET_BLOCK_NO_ISEM) ; kunmap(bh_result->b_page) ; if (!retval) { if (!buffer_mapped(bh_result) || bh_result->b_blocknr == 0) { diff -u --recursive --new-file v2.4.5/linux/fs/reiserfs/journal.c linux/fs/reiserfs/journal.c --- v2.4.5/linux/fs/reiserfs/journal.c Fri Apr 27 14:18:08 2001 +++ linux/fs/reiserfs/journal.c Fri Jun 29 15:37:16 2001 @@ -128,11 +128,11 @@ struct reiserfs_bitmap_node *bn ; static int id = 0 ; - bn = kmalloc(sizeof(struct reiserfs_bitmap_node), GFP_BUFFER) ; + bn = kmalloc(sizeof(struct reiserfs_bitmap_node), GFP_NOFS) ; if (!bn) { return NULL ; } - bn->data = kmalloc(p_s_sb->s_blocksize, GFP_BUFFER) ; + bn->data = kmalloc(p_s_sb->s_blocksize, GFP_NOFS) ; if (!bn->data) { kfree(bn) ; return NULL ; @@ -1492,8 +1492,8 @@ } trans_id = le32_to_cpu(desc->j_trans_id) ; /* now we know we've got a good transaction, and it was inside the valid time ranges */ - log_blocks = kmalloc(le32_to_cpu(desc->j_len) * sizeof(struct buffer_head *), GFP_BUFFER) ; - real_blocks = kmalloc(le32_to_cpu(desc->j_len) * sizeof(struct buffer_head *), GFP_BUFFER) ; + log_blocks = kmalloc(le32_to_cpu(desc->j_len) * sizeof(struct buffer_head *), GFP_NOFS) ; + real_blocks = kmalloc(le32_to_cpu(desc->j_len) * sizeof(struct buffer_head *), GFP_NOFS) ; if (!log_blocks || !real_blocks) { brelse(c_bh) ; brelse(d_bh) ; @@ -1786,10 +1786,10 @@ static void commit_flush_async(struct super_block *p_s_sb, int jindex) { struct reiserfs_journal_commit_task *ct ; - /* using GFP_BUFFER, GFP_KERNEL could try to flush inodes, which will try + /* using GFP_NOFS, GFP_KERNEL could try to flush inodes, which will try ** to start/join a transaction, which will deadlock */ - ct = kmalloc(sizeof(struct reiserfs_journal_commit_task), GFP_BUFFER) ; + ct = kmalloc(sizeof(struct reiserfs_journal_commit_task), GFP_NOFS) ; if (ct) { setup_commit_task_arg(ct, p_s_sb, jindex) ; queue_task(&(ct->task), &reiserfs_commit_thread_tq); @@ -2553,6 +2553,7 @@ bh = get_hash_table(p_s_sb->s_dev, blocknr, p_s_sb->s_blocksize) ; /* if it is journal new, we just remove it from this transaction */ if (bh && buffer_journal_new(bh)) { + mark_buffer_notjournal_new(bh) ; clear_prepared_bits(bh) ; cleaned = remove_from_transaction(p_s_sb, blocknr, cleaned) ; } else { @@ -2885,7 +2886,7 @@ #endif get_page(bh->b_page) ; - new_pl = reiserfs_kmalloc(sizeof(struct reiserfs_page_list), GFP_BUFFER, + new_pl = reiserfs_kmalloc(sizeof(struct reiserfs_page_list), GFP_NOFS, inode->i_sb) ; if (!new_pl) { put_page(bh->b_page) ; diff -u --recursive --new-file v2.4.5/linux/fs/reiserfs/namei.c linux/fs/reiserfs/namei.c --- v2.4.5/linux/fs/reiserfs/namei.c Fri Apr 27 14:18:08 2001 +++ linux/fs/reiserfs/namei.c Fri Jun 29 15:37:56 2001 @@ -437,7 +437,7 @@ /* get memory for composing the entry */ buflen = DEH_SIZE + ROUND_UP (namelen); if (buflen > sizeof (small_buf)) { - buffer = reiserfs_kmalloc (buflen, GFP_BUFFER, dir->i_sb); + buffer = reiserfs_kmalloc (buflen, GFP_NOFS, dir->i_sb); if (buffer == 0) return -ENOMEM; } else @@ -878,7 +878,7 @@ return -ENAMETOOLONG; } - name = kmalloc (item_len, GFP_BUFFER); + name = kmalloc (item_len, GFP_NOFS); if (!name) { iput(inode) ; return -ENOMEM; diff -u --recursive --new-file v2.4.5/linux/fs/reiserfs/stree.c linux/fs/reiserfs/stree.c --- v2.4.5/linux/fs/reiserfs/stree.c Fri Apr 13 20:26:07 2001 +++ linux/fs/reiserfs/stree.c Tue Jun 12 10:44:58 2001 @@ -1724,7 +1724,7 @@ continue; reiserfs_warning ("PAP-5610: reiserfs_cut_from_item: item %K not found\n", p_s_item_key); - pathrelse (p_s_path); + unfix_nodes (&s_cut_balance); return (n_ret_value == IO_ERROR) ? -EIO : -ENOENT; } /* while */ @@ -1994,12 +1994,14 @@ while ( (retval = fix_nodes(M_PASTE, &s_paste_balance, NULL, p_c_body)) == REPEAT_SEARCH ) { /* file system changed while we were in the fix_nodes */ retval = search_for_position_by_key (th->t_super, p_s_key, p_s_search_path); - if (retval == IO_ERROR) - return -EIO; + if (retval == IO_ERROR) { + retval = -EIO ; + goto error_out ; + } if (retval == POSITION_FOUND) { reiserfs_warning ("PAP-5710: reiserfs_paste_into_item: entry or pasted byte (%K) exists", p_s_key); - pathrelse (p_s_search_path); - return -EEXIST; + retval = -EEXIST ; + goto error_out ; } #ifdef CONFIG_REISERFS_CHECK @@ -2013,9 +2015,11 @@ do_balance(&s_paste_balance, NULL/*ih*/, p_c_body, M_PASTE); return 0; } - + retval = (retval == NO_DISK_SPACE) ? -ENOSPC : -EIO; +error_out: + /* this also releases the path */ unfix_nodes(&s_paste_balance); - return (retval == NO_DISK_SPACE) ? -ENOSPC : -EIO; + return retval ; } @@ -2040,14 +2044,15 @@ while ( (retval = fix_nodes(M_INSERT, &s_ins_balance, p_s_ih, p_c_body)) == REPEAT_SEARCH) { /* file system changed while we were in the fix_nodes */ retval = search_item (th->t_super, key, p_s_path); - if (retval == IO_ERROR) - return -EIO; - + if (retval == IO_ERROR) { + retval = -EIO; + goto error_out ; + } if (retval == ITEM_FOUND) { reiserfs_warning ("PAP-5760: reiserfs_insert_item: " "key %K already exists in the tree\n", key); - pathrelse (p_s_path); - return -EEXIST; + retval = -EEXIST ; + goto error_out; } } @@ -2057,8 +2062,11 @@ return 0; } + retval = (retval == NO_DISK_SPACE) ? -ENOSPC : -EIO; +error_out: + /* also releases the path */ unfix_nodes(&s_ins_balance); - return (retval == NO_DISK_SPACE) ? -ENOSPC : -EIO; + return retval; } diff -u --recursive --new-file v2.4.5/linux/fs/reiserfs/super.c linux/fs/reiserfs/super.c --- v2.4.5/linux/fs/reiserfs/super.c Fri Apr 27 14:18:08 2001 +++ linux/fs/reiserfs/super.c Fri Jun 29 15:38:17 2001 @@ -149,6 +149,9 @@ statfs: reiserfs_statfs, remount_fs: reiserfs_remount, + fh_to_dentry: reiserfs_fh_to_dentry, + dentry_to_fh: reiserfs_dentry_to_fh, + }; /* this was (ext2)parse_options */ @@ -302,7 +305,7 @@ int i, bmp, dl ; struct reiserfs_super_block * rs = SB_DISK_SUPER_BLOCK(s); - SB_AP_BITMAP (s) = reiserfs_kmalloc (sizeof (struct buffer_head *) * le16_to_cpu (rs->s_bmap_nr), GFP_BUFFER, s); + SB_AP_BITMAP (s) = reiserfs_kmalloc (sizeof (struct buffer_head *) * le16_to_cpu (rs->s_bmap_nr), GFP_NOFS, s); if (SB_AP_BITMAP (s) == 0) return 1; memset (SB_AP_BITMAP (s), 0, sizeof (struct buffer_head *) * le16_to_cpu (rs->s_bmap_nr)); @@ -331,7 +334,7 @@ int bmp1 = (REISERFS_OLD_DISK_OFFSET_IN_BYTES / s->s_blocksize) + 1; /* first of bitmap blocks */ /* read true bitmap */ - SB_AP_BITMAP (s) = reiserfs_kmalloc (sizeof (struct buffer_head *) * le16_to_cpu (rs->s_bmap_nr), GFP_BUFFER, s); + SB_AP_BITMAP (s) = reiserfs_kmalloc (sizeof (struct buffer_head *) * le16_to_cpu (rs->s_bmap_nr), GFP_NOFS, s); if (SB_AP_BITMAP (s) == 0) return 1; diff -u --recursive --new-file v2.4.5/linux/fs/select.c linux/fs/select.c --- v2.4.5/linux/fs/select.c Wed May 16 10:31:27 2001 +++ linux/fs/select.c Wed Jun 27 17:10:55 2001 @@ -260,7 +260,7 @@ fd_set_bits fds; char *bits; long timeout; - int ret, size; + int ret, size, max_fdset; timeout = MAX_SCHEDULE_TIMEOUT; if (tvp) { @@ -285,8 +285,10 @@ if (n < 0) goto out_nofds; - if (n > current->files->max_fdset) - n = current->files->max_fdset; + /* max_fdset can increase, so grab it once to avoid race */ + max_fdset = current->files->max_fdset; + if (n > max_fdset) + n = max_fdset; /* * We need 6 bitmaps (in/out/ex for both incoming and outgoing), diff -u --recursive --new-file v2.4.5/linux/fs/smbfs/ChangeLog linux/fs/smbfs/ChangeLog --- v2.4.5/linux/fs/smbfs/ChangeLog Tue May 15 13:40:55 2001 +++ linux/fs/smbfs/ChangeLog Wed Jun 20 16:07:57 2001 @@ -1,5 +1,10 @@ ChangeLog for smbfs. +2001-06-12 Urban Widmark + + * proc.c: replace the win95-flush fix with smb_seek, when needed. + * proc.c: readdir 'lastname' bug (NetApp dir listing fix) + 2001-05-08 Urban Widmark * inode.c: Fix for changes on the server side not being detected diff -u --recursive --new-file v2.4.5/linux/fs/smbfs/file.c linux/fs/smbfs/file.c --- v2.4.5/linux/fs/smbfs/file.c Tue May 15 13:40:55 2001 +++ linux/fs/smbfs/file.c Wed Jun 20 16:07:57 2001 @@ -151,6 +151,7 @@ * Update the inode now rather than waiting for a refresh. */ inode->i_mtime = inode->i_atime = CURRENT_TIME; + inode->u.smbfs_i.flags |= SMB_F_LOCALWRITE; if (offset > inode->i_size) inode->i_size = offset; } while (count); diff -u --recursive --new-file v2.4.5/linux/fs/smbfs/inode.c linux/fs/smbfs/inode.c --- v2.4.5/linux/fs/smbfs/inode.c Tue May 15 13:40:55 2001 +++ linux/fs/smbfs/inode.c Wed Jun 20 16:07:57 2001 @@ -141,8 +141,8 @@ inode->u.smbfs_i.oldmtime = jiffies; if (inode->i_mtime != last_time || inode->i_size != last_sz) { - VERBOSE("%s/%s changed, old=%ld, new=%ld, oz=%ld, nz=%ld\n", - DENTRY_PATH(dentry), + VERBOSE("%ld changed, old=%ld, new=%ld, oz=%ld, nz=%ld\n", + inode->i_ino, (long) last_time, (long) inode->i_mtime, (long) last_sz, (long) inode->i_size); diff -u --recursive --new-file v2.4.5/linux/fs/smbfs/proc.c linux/fs/smbfs/proc.c --- v2.4.5/linux/fs/smbfs/proc.c Tue May 15 13:40:55 2001 +++ linux/fs/smbfs/proc.c Wed Jun 20 16:07:57 2001 @@ -919,6 +919,31 @@ } /* + * Called with the server locked + */ +static int +smb_proc_seek(struct smb_sb_info *server, __u16 fileid, + __u16 mode, off_t offset) +{ + int result; + + smb_setup_header(server, SMBlseek, 4, 0); + WSET(server->packet, smb_vwv0, fileid); + WSET(server->packet, smb_vwv1, mode); + DSET(server->packet, smb_vwv2, offset); + + result = smb_request_ok(server, SMBlseek, 2, 0); + if (result < 0) { + result = 0; + goto out; + } + + result = DVAL(server->packet, smb_vwv0); +out: + return result; +} + +/* * We're called with the server locked, and we leave it that way. */ static int @@ -1210,11 +1235,6 @@ if (result >= 0) result = WVAL(server->packet, smb_vwv0); - /* flush to disk, to trigger win9x to update its filesize */ - /* FIXME: this will be rather costly, won't it? */ - if (server->mnt->flags & SMB_MOUNT_WIN95) - smb_proc_flush(server, fileid); - smb_unlock_server(server); return result; } @@ -1858,6 +1878,7 @@ result = mask_len; goto unlock_return; } + mask_len--; /* mask_len is strlen, not #bytes */ first = 1; VERBOSE("starting mask_len=%d, mask=%s\n", mask_len, mask); @@ -1946,18 +1967,28 @@ * Note that some servers (win95?) point to the filename and * others (NT4, Samba using NT1) to the dir entry. We assume * here that those who do not point to a filename do not need - * this info to continue the listing. OS/2 needs this, but it - * talks "infolevel 1" + * this info to continue the listing. + * + * OS/2 needs this and talks infolevel 1 + * NetApps want lastname with infolevel 260 + * + * Both are happy if we return the data they point to. So we do. */ mask_len = 0; - if (info_level == 1 && ff_lastname > 0 && - ff_lastname < resp_data_len) { + if (ff_lastname > 0 && ff_lastname < resp_data_len) { lastname = resp_data + ff_lastname; - /* lastname points to a length byte */ - mask_len = *lastname++; - if (ff_lastname + 1 + mask_len > resp_data_len) - mask_len = resp_data_len-ff_lastname-1; + switch (info_level) { + case 260: + mask_len = resp_data_len - ff_lastname; + break; + case 1: + /* lastname points to a length byte */ + mask_len = *lastname++; + if (ff_lastname + 1 + mask_len > resp_data_len) + mask_len = resp_data_len - ff_lastname - 1; + break; + } /* * Update the mask string for the next message. @@ -2062,7 +2093,7 @@ DSET(param, 8, 0); result = smb_trans2_request(server, TRANSACT2_FINDFIRST, - 0, NULL, 12 + mask_len + 1, param, + 0, NULL, 12 + mask_len, param, &resp_data_len, &resp_data, &resp_param_len, &resp_param); if (result < 0) @@ -2246,6 +2277,7 @@ struct smb_fattr *fattr) { int result; + struct inode *inode = dir->d_inode; smb_init_dirent(server, fattr); @@ -2261,6 +2293,21 @@ result = smb_proc_getattr_ff(server, dir, fattr); else result = smb_proc_getattr_trans2(server, dir, fattr); + } + + /* + * None of the getattr versions here can make win9x return the right + * filesize if there are changes made to an open file. + * A seek-to-end does return the right size, but we only need to do + * that on files we have written. + */ + if (server->mnt->flags & SMB_MOUNT_WIN95 && + inode && + inode->u.smbfs_i.flags & SMB_F_LOCALWRITE && + smb_is_open(inode)) + { + __u16 fileid = inode->u.smbfs_i.fileid; + fattr->f_size = smb_proc_seek(server, fileid, 2, 0); } smb_finish_dirent(server, fattr); diff -u --recursive --new-file v2.4.5/linux/fs/super.c linux/fs/super.c --- v2.4.5/linux/fs/super.c Fri May 25 12:38:52 2001 +++ linux/fs/super.c Thu Jun 14 14:16:58 2001 @@ -55,7 +55,6 @@ extern int root_mountflags; static int do_remount_sb(struct super_block *sb, int flags, char * data); -static int do_remount(const char *dir, int flags, char * data); /* this is initialized in init/main.c */ kdev_t ROOT_DEV; @@ -282,13 +281,25 @@ static LIST_HEAD(vfsmntlist); +static struct list_head *mount_hashtable; +static int hash_mask, hash_bits; +static kmem_cache_t *mnt_cache; + +static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry) +{ + unsigned long tmp = ((unsigned long) mnt / L1_CACHE_BYTES); + tmp += ((unsigned long) dentry / L1_CACHE_BYTES); + tmp = tmp + (tmp >> hash_mask); + return tmp & hash_bits; +} + struct vfsmount *alloc_vfsmnt(void) { - struct vfsmount *mnt = kmalloc(sizeof(struct vfsmount), GFP_KERNEL); + struct vfsmount *mnt = kmem_cache_alloc(mnt_cache, GFP_KERNEL); if (mnt) { memset(mnt, 0, sizeof(struct vfsmount)); atomic_set(&mnt->mnt_count,1); - INIT_LIST_HEAD(&mnt->mnt_clash); + INIT_LIST_HEAD(&mnt->mnt_hash); INIT_LIST_HEAD(&mnt->mnt_child); INIT_LIST_HEAD(&mnt->mnt_mounts); INIT_LIST_HEAD(&mnt->mnt_list); @@ -297,6 +308,24 @@ return mnt; } +struct vfsmount *lookup_mnt(struct vfsmount *mnt, struct dentry *dentry) +{ + struct list_head * head = mount_hashtable + hash(mnt, dentry); + struct list_head * tmp = head; + struct vfsmount *p; + + for (;;) { + tmp = tmp->next; + p = NULL; + if (tmp == head) + break; + p = list_entry(tmp, struct vfsmount, mnt_hash); + if (p->mnt_parent == mnt && p->mnt_mountpoint == dentry) + break; + } + return p; +} + static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd) { old_nd->dentry = mnt->mnt_mountpoint; @@ -304,15 +333,17 @@ mnt->mnt_parent = mnt; mnt->mnt_mountpoint = mnt->mnt_root; list_del_init(&mnt->mnt_child); - list_del_init(&mnt->mnt_clash); + list_del_init(&mnt->mnt_hash); + old_nd->dentry->d_mounted--; } static void attach_mnt(struct vfsmount *mnt, struct nameidata *nd) { mnt->mnt_parent = mntget(nd->mnt); mnt->mnt_mountpoint = dget(nd->dentry); - list_add(&mnt->mnt_clash, &nd->dentry->d_vfsmnt); + list_add(&mnt->mnt_hash, mount_hashtable+hash(nd->mnt, nd->dentry)); list_add(&mnt->mnt_child, &nd->mnt->mnt_mounts); + nd->dentry->d_mounted++; } /** @@ -331,9 +362,7 @@ * dentry (if any). */ -static struct vfsmount *add_vfsmnt(struct nameidata *nd, - struct dentry *root, - const char *dev_name) +static struct vfsmount *add_vfsmnt(struct dentry *root, const char *dev_name) { struct vfsmount *mnt; struct super_block *sb = root->d_inode->i_sb; @@ -352,18 +381,11 @@ } } mnt->mnt_sb = sb; - - spin_lock(&dcache_lock); - if (nd && !IS_ROOT(nd->dentry) && d_unhashed(nd->dentry)) - goto fail; mnt->mnt_root = dget(root); + mnt->mnt_mountpoint = mnt->mnt_root; + mnt->mnt_parent = mnt; - if (nd) { - attach_mnt(mnt, nd); - } else { - mnt->mnt_mountpoint = mnt->mnt_root; - mnt->mnt_parent = mnt; - } + spin_lock(&dcache_lock); list_add(&mnt->mnt_instances, &sb->s_mounts); list_add(&mnt->mnt_list, vfsmntlist.prev); spin_unlock(&dcache_lock); @@ -371,14 +393,63 @@ get_filesystem(sb->s_type); out: return mnt; +} + +static struct vfsmount *clone_mnt(struct vfsmount *old_mnt, struct dentry *root) +{ + char *name = old_mnt->mnt_devname; + struct vfsmount *mnt = alloc_vfsmnt(); + + if (!mnt) + goto out; + + if (name) { + mnt->mnt_devname = kmalloc(strlen(name)+1, GFP_KERNEL); + if (mnt->mnt_devname) + strcpy(mnt->mnt_devname, name); + } + mnt->mnt_sb = old_mnt->mnt_sb; + mnt->mnt_root = dget(root); + mnt->mnt_mountpoint = mnt->mnt_root; + mnt->mnt_parent = mnt; + + spin_lock(&dcache_lock); + list_add(&mnt->mnt_instances, &old_mnt->mnt_instances); + spin_unlock(&dcache_lock); +out: + return mnt; +} + +static int graft_tree(struct vfsmount *mnt, struct nameidata *nd) +{ + if (S_ISDIR(nd->dentry->d_inode->i_mode) != + S_ISDIR(mnt->mnt_root->d_inode->i_mode)) + return -ENOTDIR; + + down(&nd->dentry->d_inode->i_zombie); + if (IS_DEADDIR(nd->dentry->d_inode)) + goto fail1; + + spin_lock(&dcache_lock); + if (!IS_ROOT(nd->dentry) && d_unhashed(nd->dentry)) + goto fail; + + attach_mnt(mnt, nd); + list_add(&mnt->mnt_list, vfsmntlist.prev); + spin_unlock(&dcache_lock); + up(&nd->dentry->d_inode->i_zombie); + if (mnt->mnt_sb->s_type->fs_flags & FS_SINGLE) + get_filesystem(mnt->mnt_sb->s_type); + mntget(mnt); + return 0; fail: spin_unlock(&dcache_lock); - if (mnt->mnt_devname) - kfree(mnt->mnt_devname); - kfree(mnt); - return NULL; +fail1: + up(&nd->dentry->d_inode->i_zombie); + return -ENOENT; } +#ifdef CONFIG_BLK_DEV_INITRD static void move_vfsmnt(struct vfsmount *mnt, struct nameidata *nd, const char *dev_name) @@ -407,6 +478,7 @@ if (parent_nd.mnt != mnt) path_release(&parent_nd); } +#endif static void kill_super(struct super_block *); @@ -420,7 +492,7 @@ spin_unlock(&dcache_lock); if (mnt->mnt_devname) kfree(mnt->mnt_devname); - kfree(mnt); + kmem_cache_free(mnt_cache, mnt); kill_super(sb); } @@ -734,7 +806,7 @@ * filesystems which don't use real block-devices. -- jrs */ -static unsigned int unnamed_dev_in_use[256/(8*sizeof(unsigned int))]; +static unsigned long unnamed_dev_in_use[256/(8*sizeof(unsigned long))]; kdev_t get_unnamed_dev(void) { @@ -873,6 +945,7 @@ } spin_unlock(&dcache_lock); down_write(&sb->s_umount); + lock_kernel(); sb->s_root = NULL; /* Need to clean after the sucker */ if (fs->fs_flags & FS_LITTER) @@ -901,6 +974,7 @@ put_filesystem(fs); sb->s_type = NULL; unlock_super(sb); + unlock_kernel(); up_write(&sb->s_umount); if (bdev) { blkdev_put(bdev, BDEV_FS); @@ -921,6 +995,10 @@ if (!(flags & MS_RDONLY) && sb->s_dev && is_read_only(sb->s_dev)) return -EACCES; /*flags |= MS_RDONLY;*/ + if (flags & MS_RDONLY) + acct_auto_close(sb->s_dev); + shrink_dcache_sb(sb); + fsync_dev(sb->s_dev); /* If we are remounting RDONLY, make sure there are no rw files open */ if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY)) if (!fs_may_remount_ro(sb)) @@ -954,13 +1032,13 @@ dev = get_unnamed_dev(); if (!dev) { - kfree(mnt); + kmem_cache_free(mnt_cache, mnt); return ERR_PTR(-EMFILE); } sb = read_super(dev, NULL, type, 0, NULL, 0); if (!sb) { put_unnamed_dev(dev); - kfree(mnt); + kmem_cache_free(mnt_cache, mnt); return ERR_PTR(-EINVAL); } mnt->mnt_sb = sb; @@ -1002,11 +1080,14 @@ * call reboot(9). Then init(8) could umount root and exec /reboot. */ if (mnt == current->fs->rootmnt) { + int retval = 0; /* * Special case for "unmounting" root ... * we just try to remount it readonly. */ - return do_remount("/", MS_RDONLY, NULL); + if (!(sb->s_flags & MS_RDONLY)) + retval = do_remount_sb(sb, MS_RDONLY, 0); + return retval; } spin_lock(&dcache_lock); @@ -1143,44 +1224,33 @@ /* * do loopback mount. */ -static int do_loopback(char *old_name, char *new_name) +static int do_loopback(struct nameidata *nd, char *old_name) { - struct nameidata old_nd, new_nd; - int err = 0; + struct nameidata old_nd; + struct vfsmount *mnt; + int err; + + err = mount_is_safe(nd); + if (err) + return err; + if (!old_name || !*old_name) return -EINVAL; - if (path_init(old_name, LOOKUP_POSITIVE, &old_nd)) + + if (path_init(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd)) err = path_walk(old_name, &old_nd); if (err) - goto out; - if (path_init(new_name, LOOKUP_POSITIVE, &new_nd)) - err = path_walk(new_name, &new_nd); - if (err) - goto out1; - err = mount_is_safe(&new_nd); - if (err) - goto out2; - err = -EINVAL; - if (S_ISDIR(new_nd.dentry->d_inode->i_mode) != - S_ISDIR(old_nd.dentry->d_inode->i_mode)) - goto out2; + return err; - err = -ENOMEM; - down(&mount_sem); - /* there we go */ - down(&new_nd.dentry->d_inode->i_zombie); - if (IS_DEADDIR(new_nd.dentry->d_inode)) - err = -ENOENT; - else if (add_vfsmnt(&new_nd, old_nd.dentry, old_nd.mnt->mnt_devname)) - err = 0; - up(&new_nd.dentry->d_inode->i_zombie); + err = -ENOMEM; + mnt = clone_mnt(old_nd.mnt, old_nd.dentry); + if (mnt) { + err = graft_tree(mnt, nd); + mntput(mnt); + } up(&mount_sem); -out2: - path_release(&new_nd); -out1: path_release(&old_nd); -out: return err; } @@ -1190,34 +1260,87 @@ * on it - tough luck. */ -static int do_remount(const char *dir,int flags,char *data) +static int do_remount(struct nameidata *nd, int flags, char *data) { - struct nameidata nd; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (nd->dentry != nd->mnt->mnt_root) + return -EINVAL; + + return do_remount_sb(nd->mnt->mnt_sb, flags, data); +} + +static int do_add_mount(struct nameidata *nd, char *type, int flags, + char *name, void *data) +{ + struct file_system_type * fstype; + struct vfsmount *mnt = NULL; + struct super_block *sb; int retval = 0; + if (!type || !memchr(type, 0, PAGE_SIZE)) + return -EINVAL; + + /* we need capabilities... */ if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (path_init(dir, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd)) - retval = path_walk(dir, &nd); - if (!retval) { - struct super_block * sb = nd.dentry->d_inode->i_sb; - retval = -ENODEV; - if (sb) { - retval = -EINVAL; - if (nd.dentry == sb->s_root) { - /* - * Shrink the dcache and sync the device. - */ - shrink_dcache_sb(sb); - fsync_dev(sb->s_dev); - if (flags & MS_RDONLY) - acct_auto_close(sb->s_dev); - retval = do_remount_sb(sb, flags, data); - } - } - path_release(&nd); + /* ... filesystem driver... */ + fstype = get_fs_type(type); + if (!fstype) + return -ENODEV; + + /* ... allocated vfsmount... */ + retval = -ENOMEM; + mnt = alloc_vfsmnt(); + if (!mnt) + goto fs_out; + if (name) { + mnt->mnt_devname = kmalloc(strlen(name)+1, GFP_KERNEL); + if (mnt->mnt_devname) + strcpy(mnt->mnt_devname, name); + } + + /* get superblock, locks mount_sem on success */ + if (fstype->fs_flags & FS_NOMOUNT) + sb = ERR_PTR(-EINVAL); + else if (fstype->fs_flags & FS_REQUIRES_DEV) + sb = get_sb_bdev(fstype, name, flags, data); + else if (fstype->fs_flags & FS_SINGLE) + sb = get_sb_single(fstype, flags, data); + else + sb = get_sb_nodev(fstype, flags, data); + + retval = PTR_ERR(sb); + if (IS_ERR(sb)) { + if (mnt->mnt_devname) + kfree(mnt->mnt_devname); + kmem_cache_free(mnt_cache, mnt); + goto fs_out; } + + mnt->mnt_sb = sb; + mnt->mnt_root = dget(sb->s_root); + mnt->mnt_mountpoint = mnt->mnt_root; + mnt->mnt_parent = mnt; + spin_lock(&dcache_lock); + list_add(&mnt->mnt_instances, &sb->s_mounts); + spin_unlock(&dcache_lock); + + /* Something was mounted here while we slept */ + while(d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry)) + ; + + /* Refuse the same filesystem on the same mount point */ + if (nd->mnt->mnt_sb == sb && nd->mnt->mnt_root == nd->dentry) + retval = -EBUSY; + else + retval = graft_tree(mnt, nd); + mntput(mnt); + up(&mount_sem); +fs_out: + put_filesystem(fstype); return retval; } @@ -1271,10 +1394,7 @@ long do_mount(char * dev_name, char * dir_name, char *type_page, unsigned long flags, void *data_page) { - struct file_system_type * fstype; struct nameidata nd; - struct vfsmount *mnt = NULL; - struct super_block *sb; int retval = 0; /* Discard magic */ @@ -1288,86 +1408,22 @@ if (dev_name && !memchr(dev_name, 0, PAGE_SIZE)) return -EINVAL; - /* OK, looks good, now let's see what do they want */ - - /* just change the flags? - capabilities are checked in do_remount() */ - if (flags & MS_REMOUNT) - return do_remount(dir_name, flags & ~MS_REMOUNT, - (char *) data_page); - - /* "mount --bind"? Equivalent to older "mount -t bind" */ - /* No capabilities? What if users do thousands of these? */ - if (flags & MS_BIND) - return do_loopback(dev_name, dir_name); - - /* For the rest we need the type */ - - if (!type_page || !memchr(type_page, 0, PAGE_SIZE)) - return -EINVAL; - - /* for the rest we _really_ need capabilities... */ - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - /* ... filesystem driver... */ - fstype = get_fs_type(type_page); - if (!fstype) - return -ENODEV; - - /* ... and mountpoint. Do the lookup first to force automounting. */ - if (path_init(dir_name, - LOOKUP_FOLLOW|LOOKUP_POSITIVE|LOOKUP_DIRECTORY, &nd)) + /* ... and get the mountpoint */ + if (path_init(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd)) retval = path_walk(dir_name, &nd); if (retval) - goto fs_out; + return retval; - /* get superblock, locks mount_sem on success */ - if (fstype->fs_flags & FS_NOMOUNT) - sb = ERR_PTR(-EINVAL); - else if (fstype->fs_flags & FS_REQUIRES_DEV) - sb = get_sb_bdev(fstype, dev_name, flags, data_page); - else if (fstype->fs_flags & FS_SINGLE) - sb = get_sb_single(fstype, flags, data_page); + if (flags & MS_REMOUNT) + retval = do_remount(&nd, flags&~MS_REMOUNT, + (char *)data_page); + else if (flags & MS_BIND) + retval = do_loopback(&nd, dev_name); else - sb = get_sb_nodev(fstype, flags, data_page); - - retval = PTR_ERR(sb); - if (IS_ERR(sb)) - goto dput_out; - - /* Something was mounted here while we slept */ - while(d_mountpoint(nd.dentry) && follow_down(&nd.mnt, &nd.dentry)) - ; - - /* Refuse the same filesystem on the same mount point */ - retval = -EBUSY; - if (nd.mnt && nd.mnt->mnt_sb == sb - && nd.mnt->mnt_root == nd.dentry) - goto fail; - - retval = -ENOENT; - if (!nd.dentry->d_inode) - goto fail; - down(&nd.dentry->d_inode->i_zombie); - if (!IS_DEADDIR(nd.dentry->d_inode)) { - retval = -ENOMEM; - mnt = add_vfsmnt(&nd, sb->s_root, dev_name); - } - up(&nd.dentry->d_inode->i_zombie); - if (!mnt) - goto fail; - retval = 0; -unlock_out: - up(&mount_sem); -dput_out: + retval = do_add_mount(&nd, type_page, flags, + dev_name, data_page); path_release(&nd); -fs_out: - put_filesystem(fstype); return retval; - -fail: - kill_super(sb); - goto unlock_out; } asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type, @@ -1555,10 +1611,10 @@ devfs_mk_symlink (NULL, "root", DEVFS_FL_DEFAULT, path + 5 + path_start, NULL, NULL); memcpy (path + path_start, "/dev/", 5); - vfsmnt = add_vfsmnt(NULL, sb->s_root, path + path_start); + vfsmnt = add_vfsmnt(sb->s_root, path + path_start); } else - vfsmnt = add_vfsmnt(NULL, sb->s_root, "/dev/root"); + vfsmnt = add_vfsmnt(sb->s_root, "/dev/root"); /* FIXME: if something will try to umount us right now... */ if (vfsmnt) { set_fs_root(current->fs, vfsmnt, sb->s_root); @@ -1776,3 +1832,51 @@ } #endif + +void __init mnt_init(unsigned long mempages) +{ + struct list_head *d; + unsigned long order; + unsigned int nr_hash; + int i; + + mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct vfsmount), + 0, SLAB_HWCACHE_ALIGN, NULL, NULL); + if (!mnt_cache) + panic("Cannot create vfsmount cache"); + + mempages >>= (16 - 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); + hash_mask = (nr_hash - 1); + + tmp = nr_hash; + hash_bits = 0; + while ((tmp >>= 1UL) != 0UL) + hash_bits++; + + mount_hashtable = (struct list_head *) + __get_free_pages(GFP_ATOMIC, order); + } while (mount_hashtable == NULL && --order >= 0); + + printk("Mount-cache hash table entries: %d (order: %ld, %ld bytes)\n", + nr_hash, order, (PAGE_SIZE << order)); + + if (!mount_hashtable) + panic("Failed to allocate mount hash table\n"); + + d = mount_hashtable; + i = nr_hash; + do { + INIT_LIST_HEAD(d); + d++; + i--; + } while (i); +} diff -u --recursive --new-file v2.4.5/linux/fs/sysv/Makefile linux/fs/sysv/Makefile --- v2.4.5/linux/fs/sysv/Makefile Fri Dec 29 14:07:23 2000 +++ linux/fs/sysv/Makefile Mon Jul 2 14:03:04 2001 @@ -9,7 +9,7 @@ O_TARGET := sysv.o -obj-y := ialloc.o balloc.o inode.o file.o dir.o namei.o fsync.o truncate.o +obj-y := ialloc.o balloc.o inode.o itree.o file.o dir.o namei.o super.o obj-m := $(O_TARGET) include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.5/linux/fs/sysv/balloc.c linux/fs/sysv/balloc.c --- v2.4.5/linux/fs/sysv/balloc.c Tue Sep 5 14:07:30 2000 +++ linux/fs/sysv/balloc.c Mon Jul 2 14:03:04 2001 @@ -19,311 +19,201 @@ * This file contains code for allocating/freeing blocks. */ -#include #include #include -#include #include /* We don't trust the value of - sb->sv_sbd2->s_tfree = *sb->sv_sb_total_free_blocks + sb->sv_sbd2->s_tfree = *sb->sv_free_blocks but we nevertheless keep it up to date. */ -void sysv_free_block(struct super_block * sb, unsigned int block) +static inline u32 *get_chunk(struct super_block *sb, struct buffer_head *bh) +{ + char *bh_data = bh->b_data; + + if (sb->sv_type == FSTYPE_SYSV4) + return (u32*)(bh_data+4); + else + return (u32*)(bh_data+2); +} + +/* NOTE NOTE NOTE: nr is a block number _as_ _stored_ _on_ _disk_ */ + +void sysv_free_block(struct super_block * sb, u32 nr) { struct buffer_head * bh; - char * bh_data; + u32 *blocks = sb->sv_bcache; + unsigned count; + unsigned block = fs32_to_cpu(sb, nr); - if (!sb) { - printk("sysv_free_block: trying to free block on nonexistent device\n"); - return; - } if (block < sb->sv_firstdatazone || block >= sb->sv_nzones) { printk("sysv_free_block: trying to free block not in datazone\n"); return; } + lock_super(sb); - if (*sb->sv_sb_flc_count > sb->sv_flc_size) { + count = fs16_to_cpu(sb, *sb->sv_bcache_count); + + if (count > sb->sv_flc_size) { printk("sysv_free_block: flc_count > flc_size\n"); unlock_super(sb); return; } /* If the free list head in super-block is full, it is copied - * into this block being freed: + * into this block being freed, ditto if it's completely empty + * (applies only on Coherent). */ - if (*sb->sv_sb_flc_count == sb->sv_flc_size) { - u16 * flc_count; - u32 * flc_blocks; - - bh = sv_getblk(sb, sb->s_dev, block); + if (count == sb->sv_flc_size || count == 0) { + block += sb->sv_block_base; + bh = getblk(sb->s_dev, block, sb->s_blocksize); if (!bh) { printk("sysv_free_block: getblk() failed\n"); unlock_super(sb); return; } - bh_data = bh->b_data; - switch (sb->sv_type) { - case FSTYPE_XENIX: - flc_count = &((struct xenix_freelist_chunk *) bh_data)->fl_nfree; - flc_blocks = &((struct xenix_freelist_chunk *) bh_data)->fl_free[0]; - break; - case FSTYPE_SYSV4: - flc_count = &((struct sysv4_freelist_chunk *) bh_data)->fl_nfree; - flc_blocks = &((struct sysv4_freelist_chunk *) bh_data)->fl_free[0]; - break; - case FSTYPE_SYSV2: - flc_count = &((struct sysv2_freelist_chunk *) bh_data)->fl_nfree; - flc_blocks = &((struct sysv2_freelist_chunk *) bh_data)->fl_free[0]; - break; - case FSTYPE_COH: - flc_count = &((struct coh_freelist_chunk *) bh_data)->fl_nfree; - flc_blocks = &((struct coh_freelist_chunk *) bh_data)->fl_free[0]; - break; - default: panic("sysv_free_block: invalid fs type\n"); - } - *flc_count = *sb->sv_sb_flc_count; /* = sb->sv_flc_size */ - memcpy(flc_blocks, sb->sv_sb_flc_blocks, *flc_count * sizeof(sysv_zone_t)); + memset(bh->b_data, 0, sb->s_blocksize); + *(u16*)bh->b_data = cpu_to_fs16(sb, count); + memcpy(get_chunk(sb,bh), blocks, count * sizeof(sysv_zone_t)); mark_buffer_dirty(bh); mark_buffer_uptodate(bh, 1); brelse(bh); - *sb->sv_sb_flc_count = 0; - } else - /* If the free list head in super-block is empty, create a new head - * in this block being freed: - */ - if (*sb->sv_sb_flc_count == 0) { /* Applies only to Coherent FS */ - bh = sv_getblk(sb, sb->s_dev, block); - if (!bh) { - printk("sysv_free_block: getblk() failed\n"); - unlock_super(sb); - return; - } - memset(bh->b_data, 0, sb->sv_block_size); - /* this implies ((struct ..._freelist_chunk *) bh->b_data)->flc_count = 0; */ - mark_buffer_dirty(bh); - mark_buffer_uptodate(bh, 1); - brelse(bh); - /* still *sb->sv_sb_flc_count = 0 */ - } else { - /* Throw away block's contents */ - bh = sv_get_hash_table(sb, sb->s_dev, block); - if (bh) - mark_buffer_clean(bh); - brelse(bh); + count = 0; } - if (sb->sv_convert) - block = to_coh_ulong(block); - sb->sv_sb_flc_blocks[(*sb->sv_sb_flc_count)++] = block; - if (sb->sv_convert) - *sb->sv_sb_total_free_blocks = - to_coh_ulong(from_coh_ulong(*sb->sv_sb_total_free_blocks) + 1); - else - *sb->sv_sb_total_free_blocks = *sb->sv_sb_total_free_blocks + 1; - mark_buffer_dirty(sb->sv_bh1); /* super-block has been modified */ - if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2); - sb->s_dirt = 1; /* and needs time stamp */ + sb->sv_bcache[count++] = nr; + + *sb->sv_bcache_count = cpu_to_fs16(sb, count); + fs32_add(sb, sb->sv_free_blocks, 1); + dirty_sb(sb); unlock_super(sb); } -int sysv_new_block(struct super_block * sb) +u32 sysv_new_block(struct super_block * sb) { unsigned int block; + u32 nr; struct buffer_head * bh; - char * bh_data; + unsigned count; - if (!sb) { - printk("sysv_new_block: trying to get new block from nonexistent device\n"); - return 0; - } lock_super(sb); - if (*sb->sv_sb_flc_count == 0) { /* Applies only to Coherent FS */ - unlock_super(sb); - return 0; /* no blocks available */ - } - block = sb->sv_sb_flc_blocks[(*sb->sv_sb_flc_count)-1]; - if (sb->sv_convert) - block = from_coh_ulong(block); - if (block == 0) { /* Applies only to Xenix FS, SystemV FS */ - unlock_super(sb); - return 0; /* no blocks available */ - } - (*sb->sv_sb_flc_count)--; + count = fs16_to_cpu(sb, *sb->sv_bcache_count); + + if (count == 0) /* Applies only to Coherent FS */ + goto Enospc; + nr = sb->sv_bcache[--count]; + if (nr == 0) /* Applies only to Xenix FS, SystemV FS */ + goto Enospc; + + block = fs32_to_cpu(sb, nr); + + *sb->sv_bcache_count = cpu_to_fs16(sb, count); + if (block < sb->sv_firstdatazone || block >= sb->sv_nzones) { - printk("sysv_new_block: new block %d is not in data zone\n",block); - unlock_super(sb); - return 0; + printk("sysv_new_block: new block %d is not in data zone\n", + block); + goto Enospc; } - if (*sb->sv_sb_flc_count == 0) { /* the last block continues the free list */ - u16 * flc_count; - u32 * flc_blocks; - if (!(bh = sv_bread(sb, sb->s_dev, block))) { + if (count == 0) { /* the last block continues the free list */ + unsigned count; + + block += sb->sv_block_base; + if (!(bh = bread(sb->s_dev, block, sb->s_blocksize))) { printk("sysv_new_block: cannot read free-list block\n"); /* retry this same block next time */ - (*sb->sv_sb_flc_count)++; - unlock_super(sb); - return 0; - } - bh_data = bh->b_data; - switch (sb->sv_type) { - case FSTYPE_XENIX: - flc_count = &((struct xenix_freelist_chunk *) bh_data)->fl_nfree; - flc_blocks = &((struct xenix_freelist_chunk *) bh_data)->fl_free[0]; - break; - case FSTYPE_SYSV4: - flc_count = &((struct sysv4_freelist_chunk *) bh_data)->fl_nfree; - flc_blocks = &((struct sysv4_freelist_chunk *) bh_data)->fl_free[0]; - break; - case FSTYPE_SYSV2: - flc_count = &((struct sysv2_freelist_chunk *) bh_data)->fl_nfree; - flc_blocks = &((struct sysv2_freelist_chunk *) bh_data)->fl_free[0]; - break; - case FSTYPE_COH: - flc_count = &((struct coh_freelist_chunk *) bh_data)->fl_nfree; - flc_blocks = &((struct coh_freelist_chunk *) bh_data)->fl_free[0]; - break; - default: panic("sysv_new_block: invalid fs type\n"); + *sb->sv_bcache_count = cpu_to_fs16(sb, 1); + goto Enospc; } - if (*flc_count > sb->sv_flc_size) { + count = fs16_to_cpu(sb, *(u16*)bh->b_data); + if (count > sb->sv_flc_size) { printk("sysv_new_block: free-list block with >flc_size entries\n"); brelse(bh); - unlock_super(sb); - return 0; + goto Enospc; } - *sb->sv_sb_flc_count = *flc_count; - memcpy(sb->sv_sb_flc_blocks, flc_blocks, *flc_count * sizeof(sysv_zone_t)); + *sb->sv_bcache_count = cpu_to_fs16(sb, count); + memcpy(sb->sv_bcache, get_chunk(sb, bh), + count * sizeof(sysv_zone_t)); brelse(bh); } /* Now the free list head in the superblock is valid again. */ - bh = sv_getblk(sb, sb->s_dev, block); - if (!bh) { - printk("sysv_new_block: getblk() failed\n"); - unlock_super(sb); - return 0; - } - if (atomic_read(&bh->b_count) != 1) { - printk("sysv_new_block: block already in use\n"); - unlock_super(sb); - return 0; - } - memset(bh->b_data, 0, sb->sv_block_size); - mark_buffer_dirty(bh); - mark_buffer_uptodate(bh, 1); - brelse(bh); - if (sb->sv_convert) - *sb->sv_sb_total_free_blocks = - to_coh_ulong(from_coh_ulong(*sb->sv_sb_total_free_blocks) - 1); - else - *sb->sv_sb_total_free_blocks = *sb->sv_sb_total_free_blocks - 1; - mark_buffer_dirty(sb->sv_bh1); /* super-block has been modified */ - if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2); - sb->s_dirt = 1; /* and needs time stamp */ + fs32_add(sb, sb->sv_free_blocks, -1); + dirty_sb(sb); + unlock_super(sb); + return nr; + +Enospc: unlock_super(sb); - return block; + return 0; } unsigned long sysv_count_free_blocks(struct super_block * sb) { -#if 1 /* test */ - int count, old_count; - unsigned int block; - struct buffer_head * bh; - char * bh_data; - int i; + int sb_count; + int count; + struct buffer_head * bh = NULL; + u32 *blocks; + unsigned block; + int n; + + lock_super(sb); + sb_count = fs32_to_cpu(sb, *sb->sv_free_blocks); + + if (0) + goto trust_sb; /* this causes a lot of disk traffic ... */ count = 0; - lock_super(sb); - if (*sb->sv_sb_flc_count > 0) { - for (i = *sb->sv_sb_flc_count ; /* i > 0 */ ; ) { - block = sb->sv_sb_flc_blocks[--i]; - if (sb->sv_convert) - block = from_coh_ulong(block); - if (block == 0) /* block 0 terminates list */ - goto done; + n = fs16_to_cpu(sb, *sb->sv_bcache_count); + blocks = sb->sv_bcache; + while (1) { + if (n > sb->sv_flc_size) + goto E2big; + block = 0; + while (n && (block = blocks[--n]) != 0) count++; - if (i == 0) - break; - } - /* block = sb->sv_sb_flc_blocks[0], the last block continues the free list */ - while (1) { - u16 * flc_count; - u32 * flc_blocks; - - if (block < sb->sv_firstdatazone || block >= sb->sv_nzones) { - printk("sysv_count_free_blocks: new block %d is not in data zone\n",block); - break; - } - if (!(bh = sv_bread(sb, sb->s_dev, block))) { - printk("sysv_count_free_blocks: cannot read free-list block\n"); - break; - } - bh_data = bh->b_data; - switch (sb->sv_type) { - case FSTYPE_XENIX: - flc_count = &((struct xenix_freelist_chunk *) bh_data)->fl_nfree; - flc_blocks = &((struct xenix_freelist_chunk *) bh_data)->fl_free[0]; - break; - case FSTYPE_SYSV4: - flc_count = &((struct sysv4_freelist_chunk *) bh_data)->fl_nfree; - flc_blocks = &((struct sysv4_freelist_chunk *) bh_data)->fl_free[0]; - break; - case FSTYPE_SYSV2: - flc_count = &((struct sysv2_freelist_chunk *) bh_data)->fl_nfree; - flc_blocks = &((struct sysv2_freelist_chunk *) bh_data)->fl_free[0]; - break; - case FSTYPE_COH: - flc_count = &((struct coh_freelist_chunk *) bh_data)->fl_nfree; - flc_blocks = &((struct coh_freelist_chunk *) bh_data)->fl_free[0]; - break; - default: panic("sysv_count_free_blocks: invalid fs type\n"); - } - if (*flc_count > sb->sv_flc_size) { - printk("sysv_count_free_blocks: free-list block with >flc_size entries\n"); - brelse(bh); - break; - } - if (*flc_count == 0) { /* Applies only to Coherent FS */ - brelse(bh); - break; - } - for (i = *flc_count ; /* i > 0 */ ; ) { - block = flc_blocks[--i]; - if (sb->sv_convert) - block = from_coh_ulong(block); - if (block == 0) /* block 0 terminates list */ - break; - count++; - if (i == 0) - break; - } - /* block = flc_blocks[0], the last block continues the free list */ + if (block == 0) + break; + + block = fs32_to_cpu(sb, block); + if (bh) brelse(bh); - if (block == 0) /* Applies only to Xenix FS and SystemV FS */ - break; - } - done: ; - } - old_count = *sb->sv_sb_total_free_blocks; - if (sb->sv_convert) - old_count = from_coh_ulong(old_count); - if (count != old_count) { - printk("sysv_count_free_blocks: free block count was %d, correcting to %d\n",old_count,count); - if (!(sb->s_flags & MS_RDONLY)) { - *sb->sv_sb_total_free_blocks = (sb->sv_convert ? to_coh_ulong(count) : count); - mark_buffer_dirty(sb->sv_bh2); /* super-block has been modified */ - sb->s_dirt = 1; /* and needs time stamp */ - } + + if (block < sb->sv_firstdatazone || block >= sb->sv_nzones) + goto Einval; + block += sb->sv_block_base; + bh = bread(sb->s_dev, block, sb->s_blocksize); + if (!bh) + goto Eio; + n = fs16_to_cpu(sb, *(u16*)bh->b_data); + blocks = get_chunk(sb, bh); } + if (bh) + brelse(bh); + if (count != sb_count) + goto Ecount; +done: unlock_super(sb); return count; -#else - int count; - count = *sb->sv_sb_total_free_blocks; - if (sb->sv_convert) - count = from_coh_ulong(count); - return count; -#endif +Einval: + printk("sysv_count_free_blocks: new block %d is not in data zone\n", + block); + goto trust_sb; +Eio: + printk("sysv_count_free_blocks: cannot read free-list block\n"); + goto trust_sb; +E2big: + printk("sysv_count_free_blocks: >flc_size entries in free-list block\n"); + if (bh) + brelse(bh); +trust_sb: + count = sb_count; + goto done; +Ecount: + printk("sysv_count_free_blocks: free block count was %d, " + "correcting to %d\n", sb_count, count); + if (!(sb->s_flags & MS_RDONLY)) { + *sb->sv_free_blocks = cpu_to_fs32(sb, count); + dirty_sb(sb); + } + goto done; } - diff -u --recursive --new-file v2.4.5/linux/fs/sysv/dir.c linux/fs/sysv/dir.c --- v2.4.5/linux/fs/sysv/dir.c Fri Aug 11 14:29:01 2000 +++ linux/fs/sysv/dir.c Mon Jul 2 14:03:04 2001 @@ -13,63 +13,356 @@ * SystemV/Coherent directory handling functions */ -#include #include #include -#include -#include +#include static int sysv_readdir(struct file *, void *, filldir_t); struct file_operations sysv_dir_operations = { read: generic_read_dir, readdir: sysv_readdir, - fsync: file_fsync, + fsync: sysv_sync_file, }; +static inline void dir_put_page(struct page *page) +{ + kunmap(page); + page_cache_release(page); +} + +static inline unsigned long dir_pages(struct inode *inode) +{ + return (inode->i_size+PAGE_CACHE_SIZE-1)>>PAGE_CACHE_SHIFT; +} + +static int dir_commit_chunk(struct page *page, unsigned from, unsigned to) +{ + 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)) + err = waitfor_one_page(page); + return err; +} + +static struct page * dir_get_page(struct inode *dir, unsigned long n) +{ + struct address_space *mapping = dir->i_mapping; + struct page *page = read_cache_page(mapping, n, + (filler_t*)mapping->a_ops->readpage, NULL); + if (!IS_ERR(page)) { + wait_on_page(page); + kmap(page); + if (!Page_Uptodate(page)) + goto fail; + } + return page; + +fail: + dir_put_page(page); + return ERR_PTR(-EIO); +} + static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir) { + unsigned long pos = filp->f_pos; struct inode *inode = filp->f_dentry->d_inode; - struct super_block * sb = inode->i_sb; - unsigned int offset,i; - struct buffer_head * bh; - char* bh_data; - struct sysv_dir_entry * de, sde; - - if ((unsigned long)(filp->f_pos) % SYSV_DIRSIZE) - return -EBADF; - while (filp->f_pos < inode->i_size) { - offset = filp->f_pos & sb->sv_block_size_1; - bh = sysv_file_bread(inode, filp->f_pos >> sb->sv_block_size_bits, 0); - if (!bh) { - filp->f_pos += sb->sv_block_size - offset; + struct super_block *sb = inode->i_sb; + unsigned offset = pos & ~PAGE_CACHE_MASK; + unsigned long n = pos >> PAGE_CACHE_SHIFT; + unsigned long npages = dir_pages(inode); + + pos = (pos + SYSV_DIRSIZE-1) & ~(SYSV_DIRSIZE-1); + if (pos >= inode->i_size) + goto done; + + for ( ; n < npages; n++, offset = 0) { + char *kaddr, *limit; + struct sysv_dir_entry *de; + struct page *page = dir_get_page(inode, n); + + if (IS_ERR(page)) + continue; + kaddr = (char *)page_address(page); + de = (struct sysv_dir_entry *)(kaddr+offset); + limit = kaddr + PAGE_CACHE_SIZE - SYSV_DIRSIZE; + for ( ;(char*)de <= limit; de++) { + char *name = de->name; + int over; + + if (!de->inode) + continue; + + offset = (char *)de - kaddr; + + over = filldir(dirent, name, strnlen(name,SYSV_NAMELEN), + (n<inode), DT_UNKNOWN); + if (over) { + dir_put_page(page); + goto done; + } + } + dir_put_page(page); + } + +done: + filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset; + UPDATE_ATIME(inode); + return 0; +} + +/* compare strings: name[0..len-1] (not zero-terminated) and + * buffer[0..] (filled with zeroes up to buffer[0..maxlen-1]) + */ +static inline int namecompare(int len, int maxlen, + const char * name, const char * buffer) +{ + if (len < maxlen && buffer[len]) + return 0; + return !memcmp(name, buffer, len); +} + +/* + * sysv_find_entry() + * + * finds an entry in the specified directory with the wanted name. It + * returns the cache buffer in which the entry was found, and the entry + * itself (as a parameter - res_dir). It does NOT read the inode of the + * entry - you'll have to do that yourself if you want to. + */ +struct sysv_dir_entry *sysv_find_entry(struct dentry *dentry, struct page **res_page) +{ + const char * name = dentry->d_name.name; + int namelen = dentry->d_name.len; + struct inode * dir = dentry->d_parent->d_inode; + unsigned long n; + unsigned long npages = dir_pages(dir); + struct page *page = NULL; + struct sysv_dir_entry *de; + + *res_page = NULL; + + for (n = 0; n < npages; n++) { + char *kaddr; + page = dir_get_page(dir, n); + if (IS_ERR(page)) continue; + + kaddr = (char*)page_address(page); + de = (struct sysv_dir_entry *) kaddr; + kaddr += PAGE_CACHE_SIZE - SYSV_DIRSIZE; + for ( ; (char *) de <= kaddr ; de++) { + if (!de->inode) + continue; + if (namecompare(namelen, SYSV_NAMELEN, name, de->name)) + goto found; + } + dir_put_page(page); + } + return NULL; + +found: + *res_page = page; + return de; +} + +int sysv_add_link(struct dentry *dentry, struct inode *inode) +{ + struct inode *dir = dentry->d_parent->d_inode; + const char * name = dentry->d_name.name; + int namelen = dentry->d_name.len; + struct page *page = NULL; + struct sysv_dir_entry * de; + unsigned long npages = dir_pages(dir); + unsigned long n; + char *kaddr; + unsigned from, to; + int err; + + /* We take care of directory expansion in the same loop */ + for (n = 0; n <= npages; n++) { + page = dir_get_page(dir, n); + err = PTR_ERR(page); + if (IS_ERR(page)) + goto out; + kaddr = (char*)page_address(page); + de = (struct sysv_dir_entry *)kaddr; + kaddr += PAGE_CACHE_SIZE - SYSV_DIRSIZE; + while ((char *)de <= kaddr) { + if (!de->inode) + goto got_it; + err = -EEXIST; + if (namecompare(namelen, SYSV_NAMELEN, name, de->name)) + goto out_page; + de++; } - bh_data = bh->b_data; - while (offset < sb->sv_block_size && filp->f_pos < inode->i_size) { - de = (struct sysv_dir_entry *) (offset + bh_data); - if (de->inode) { - /* Copy the directory entry first, because the directory - * might be modified while we sleep in filldir()... - */ - memcpy(&sde, de, sizeof(struct sysv_dir_entry)); - - if (sde.inode > inode->i_sb->sv_ninodes) - printk("sysv_readdir: Bad inode number on dev " - "%s, ino %ld, offset 0x%04lx: %d is out of range\n", - kdevname(inode->i_dev), - inode->i_ino, (off_t) filp->f_pos, sde.inode); - - i = strnlen(sde.name, SYSV_NAMELEN); - if (filldir(dirent, sde.name, i, filp->f_pos, sde.inode, DT_UNKNOWN) < 0) { - brelse(bh); - return 0; - } + dir_put_page(page); + } + BUG(); + return -EINVAL; + +got_it: + from = (char*)de - (char*)page_address(page); + to = from + SYSV_DIRSIZE; + lock_page(page); + err = page->mapping->a_ops->prepare_write(NULL, page, from, to); + if (err) + goto out_unlock; + memcpy (de->name, name, namelen); + memset (de->name + namelen, 0, SYSV_DIRSIZE - namelen); + de->inode = cpu_to_fs16(inode->i_sb, inode->i_ino); + err = dir_commit_chunk(page, from, to); + dir->i_mtime = dir->i_ctime = CURRENT_TIME; + mark_inode_dirty(dir); +out_unlock: + UnlockPage(page); +out_page: + dir_put_page(page); +out: + return err; +} + +int sysv_delete_entry(struct sysv_dir_entry *de, struct page *page) +{ + struct address_space *mapping = page->mapping; + struct inode *inode = (struct inode*)mapping->host; + char *kaddr = (char*)page_address(page); + unsigned from = (char*)de - kaddr; + unsigned to = from + SYSV_DIRSIZE; + int err; + + lock_page(page); + err = mapping->a_ops->prepare_write(NULL, page, from, to); + if (err) + BUG(); + de->inode = 0; + err = dir_commit_chunk(page, from, to); + UnlockPage(page); + dir_put_page(page); + inode->i_ctime = inode->i_mtime = CURRENT_TIME; + mark_inode_dirty(inode); + return err; +} + +int sysv_make_empty(struct inode *inode, struct inode *dir) +{ + struct address_space *mapping = inode->i_mapping; + struct page *page = grab_cache_page(mapping, 0); + struct sysv_dir_entry * de; + char *base; + int err; + + if (!page) + return -ENOMEM; + err = mapping->a_ops->prepare_write(NULL, page, 0, 2 * SYSV_DIRSIZE); + if (err) + goto fail; + + base = (char*)page_address(page); + memset(base, 0, PAGE_CACHE_SIZE); + + de = (struct sysv_dir_entry *) base; + de->inode = cpu_to_fs16(inode->i_sb, inode->i_ino); + strcpy(de->name,"."); + de++; + de->inode = cpu_to_fs16(inode->i_sb, dir->i_ino); + strcpy(de->name,".."); + + err = dir_commit_chunk(page, 0, 2 * SYSV_DIRSIZE); +fail: + UnlockPage(page); + page_cache_release(page); + return err; +} + +/* + * routine to check that the specified directory is empty (for rmdir) + */ +int sysv_empty_dir(struct inode * inode) +{ + struct super_block *sb = inode->i_sb; + struct page *page = NULL; + unsigned long i, npages = dir_pages(inode); + + for (i = 0; i < npages; i++) { + char *kaddr; + struct sysv_dir_entry * de; + page = dir_get_page(inode, i); + + if (IS_ERR(page)) + continue; + + kaddr = (char *)page_address(page); + de = (struct sysv_dir_entry *)kaddr; + kaddr += PAGE_CACHE_SIZE-SYSV_DIRSIZE; + + for ( ;(char *)de <= kaddr; de++) { + if (!de->inode) + continue; + /* check for . and .. */ + if (de->name[0] != '.') + goto not_empty; + if (!de->name[1]) { + if (de->inode == cpu_to_fs16(sb, inode->i_ino)) + continue; + goto not_empty; } - offset += SYSV_DIRSIZE; - filp->f_pos += SYSV_DIRSIZE; + if (de->name[1] != '.' || de->name[2]) + goto not_empty; } - brelse(bh); + dir_put_page(page); } + return 1; + +not_empty: + dir_put_page(page); return 0; +} + +/* Releases the page */ +void sysv_set_link(struct sysv_dir_entry *de, struct page *page, + struct inode *inode) +{ + struct inode *dir = (struct inode*)page->mapping->host; + unsigned from = (char *)de-(char*)page_address(page); + unsigned to = from + SYSV_DIRSIZE; + int err; + + lock_page(page); + err = page->mapping->a_ops->prepare_write(NULL, page, from, to); + if (err) + BUG(); + de->inode = cpu_to_fs16(inode->i_sb, inode->i_ino); + err = dir_commit_chunk(page, from, to); + UnlockPage(page); + dir_put_page(page); + dir->i_mtime = dir->i_ctime = CURRENT_TIME; + mark_inode_dirty(dir); +} + +struct sysv_dir_entry * sysv_dotdot (struct inode *dir, struct page **p) +{ + struct page *page = dir_get_page(dir, 0); + struct sysv_dir_entry *de = NULL; + + if (!IS_ERR(page)) { + de = (struct sysv_dir_entry*) page_address(page) + 1; + *p = page; + } + return de; +} + +ino_t sysv_inode_by_name(struct dentry *dentry) +{ + struct page *page; + struct sysv_dir_entry *de = sysv_find_entry (dentry, &page); + ino_t res = 0; + + if (de) { + res = fs16_to_cpu(dentry->d_sb, de->inode); + dir_put_page(page); + } + return res; } diff -u --recursive --new-file v2.4.5/linux/fs/sysv/file.c linux/fs/sysv/file.c --- v2.4.5/linux/fs/sysv/file.c Sat Feb 26 20:33:43 2000 +++ linux/fs/sysv/file.c Mon Jul 2 14:03:04 2001 @@ -31,3 +31,17 @@ truncate: sysv_truncate, setattr: sysv_notify_change, }; + +int sysv_sync_file(struct file * file, struct dentry *dentry, int datasync) +{ + struct inode *inode = dentry->d_inode; + int err = fsync_inode_buffers(inode); + + if (!(inode->i_state & I_DIRTY)) + return err; + if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) + return err; + + err |= sysv_sync_inode(inode); + return err ? -EIO : 0; +} diff -u --recursive --new-file v2.4.5/linux/fs/sysv/fsync.c linux/fs/sysv/fsync.c --- v2.4.5/linux/fs/sysv/fsync.c Thu Jun 29 16:06:54 2000 +++ linux/fs/sysv/fsync.c Wed Dec 31 16:00:00 1969 @@ -1,200 +0,0 @@ -/* - * linux/fs/sysv/fsync.c - * - * minix/fsync.c - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright (C) 1993 Stephen Tweedie (sct@dcs.ed.ac.uk) - * - * coh/fsync.c - * Copyright (C) 1993 Pascal Haible, Bruno Haible - * - * sysv/fsync.c - * Copyright (C) 1993 Bruno Haible - * - * SystemV/Coherent fsync primitive - */ - -#include -#include -#include -#include -#include - - -/* return values: 0 means OK/done, 1 means redo, -1 means I/O error. */ - -/* Sync one block. The block number is - * from_coh_ulong(*blockp) if convert=1, *blockp if convert=0. - */ -static int sync_block (struct inode * inode, u32 *blockp, int convert, int wait) -{ - struct buffer_head * bh; - u32 tmp, block; - struct super_block * sb; - - block = tmp = *blockp; - if (convert) - block = from_coh_ulong(block); - if (!block) - return 0; - sb = inode->i_sb; - bh = sv_get_hash_table(sb, inode->i_dev, block); - if (!bh) - return 0; - if (*blockp != tmp) { - brelse (bh); - return 1; - } - if (wait && buffer_req(bh) && !buffer_uptodate(bh)) { - brelse(bh); - return -1; - } - if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) { - brelse(bh); - return 0; - } - ll_rw_block(WRITE, 1, &bh); - atomic_dec(&bh->b_count); - return 0; -} - -/* Sync one block full of indirect pointers and read it because we'll need it. */ -static int sync_iblock (struct inode * inode, u32 * iblockp, int convert, - struct buffer_head * *bh, int wait) -{ - int rc; - u32 tmp, block; - - *bh = NULL; - block = tmp = *iblockp; - if (convert) - block = from_coh_ulong(block); - if (!block) - return 0; - rc = sync_block (inode, iblockp, convert, wait); - if (rc) - return rc; - *bh = sv_bread(inode->i_sb, inode->i_dev, block); - if (tmp != *iblockp) { - brelse(*bh); - *bh = NULL; - return 1; - } - if (!*bh) - return -1; - return 0; -} - - -static int sync_direct(struct inode *inode, int wait) -{ - int i; - int rc, err = 0; - - for (i = 0; i < 10; i++) { - rc = sync_block (inode, inode->u.sysv_i.i_data + i, 0, wait); - if (rc > 0) - break; - if (rc) - err = rc; - } - return err; -} - -static int sync_indirect(struct inode *inode, u32 *iblockp, int convert, int wait) -{ - int i; - struct buffer_head * ind_bh; - int rc, err = 0; - struct super_block * sb; - - rc = sync_iblock (inode, iblockp, convert, &ind_bh, wait); - if (rc || !ind_bh) - return rc; - - sb = inode->i_sb; - for (i = 0; i < sb->sv_ind_per_block; i++) { - rc = sync_block (inode, - ((u32 *) ind_bh->b_data) + i, sb->sv_convert, - wait); - if (rc > 0) - break; - if (rc) - err = rc; - } - brelse(ind_bh); - return err; -} - -static int sync_dindirect(struct inode *inode, u32 *diblockp, int convert, - int wait) -{ - int i; - struct buffer_head * dind_bh; - int rc, err = 0; - struct super_block * sb; - - rc = sync_iblock (inode, diblockp, convert, &dind_bh, wait); - if (rc || !dind_bh) - return rc; - - sb = inode->i_sb; - for (i = 0; i < sb->sv_ind_per_block; i++) { - rc = sync_indirect (inode, - ((u32 *) dind_bh->b_data) + i, sb->sv_convert, - wait); - if (rc > 0) - break; - if (rc) - err = rc; - } - brelse(dind_bh); - return err; -} - -static int sync_tindirect(struct inode *inode, u32 *tiblockp, int convert, - int wait) -{ - int i; - struct buffer_head * tind_bh; - int rc, err = 0; - struct super_block * sb; - - rc = sync_iblock (inode, tiblockp, convert, &tind_bh, wait); - if (rc || !tind_bh) - return rc; - - sb = inode->i_sb; - for (i = 0; i < sb->sv_ind_per_block; i++) { - rc = sync_dindirect (inode, - ((u32 *) tind_bh->b_data) + i, sb->sv_convert, - wait); - if (rc > 0) - break; - if (rc) - err = rc; - } - brelse(tind_bh); - return err; -} - -int sysv_sync_file(struct file * file, struct dentry *dentry, int datasync) -{ - int wait, err = 0; - struct inode *inode = dentry->d_inode; - - if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode))) - return -EINVAL; - - lock_kernel(); - for (wait=0; wait<=1; wait++) { - err |= sync_direct(inode, wait); - err |= sync_indirect(inode, inode->u.sysv_i.i_data+10, 0, wait); - err |= sync_dindirect(inode, inode->u.sysv_i.i_data+11, 0, wait); - err |= sync_tindirect(inode, inode->u.sysv_i.i_data+12, 0, wait); - } - err |= sysv_sync_inode (inode); - unlock_kernel(); - return (err < 0) ? -EIO : 0; -} diff -u --recursive --new-file v2.4.5/linux/fs/sysv/ialloc.c linux/fs/sysv/ialloc.c --- v2.4.5/linux/fs/sysv/ialloc.c Fri Nov 17 11:35:27 2000 +++ linux/fs/sysv/ialloc.c Mon Jul 2 14:03:04 2001 @@ -19,7 +19,6 @@ * This file contains code for allocating/freeing inodes. */ -#include #include #include #include @@ -35,7 +34,8 @@ /* An inode on disk is considered free if both i_mode == 0 and i_nlink == 0. */ /* return &sb->sv_sb_fic_inodes[i] = &sbd->s_inode[i]; */ -static inline sysv_ino_t * sv_sb_fic_inode (struct super_block * sb, unsigned int i) +static inline sysv_ino_t * +sv_sb_fic_inode(struct super_block * sb, unsigned int i) { if (sb->sv_bh1 == sb->sv_bh2) return &sb->sv_sb_fic_inodes[i]; @@ -49,12 +49,55 @@ } } +struct sysv_inode * +sysv_raw_inode(struct super_block *sb, unsigned ino, struct buffer_head **bh) +{ + struct sysv_inode *res; + int block = sb->sv_firstinodezone + sb->sv_block_base; + block += (ino-1) >> sb->sv_inodes_per_block_bits; + *bh = bread(sb->s_dev, block, sb->s_blocksize); + if (!*bh) + return NULL; + res = (struct sysv_inode *) (*bh)->b_data; + return res + ((ino-1) & sb->sv_inodes_per_block_1); +} + +static int refill_free_cache(struct super_block *sb) +{ + struct buffer_head * bh; + struct sysv_inode * raw_inode; + int i = 0, ino; + + ino = SYSV_ROOT_INO+1; + raw_inode = sysv_raw_inode(sb, ino, &bh); + if (!raw_inode) + goto out; + while (ino <= sb->sv_ninodes) { + if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0) { + *sv_sb_fic_inode(sb,i++) = cpu_to_fs16(sb, ino); + if (i == sb->sv_fic_size) + break; + } + if ((ino++ & sb->sv_inodes_per_block_1) == 0) { + brelse(bh); + raw_inode = sysv_raw_inode(sb, ino, &bh); + if (!raw_inode) + goto out; + } else + raw_inode++; + } + brelse(bh); +out: + return i; +} + void sysv_free_inode(struct inode * inode) { struct super_block * sb; unsigned int ino; struct buffer_head * bh; struct sysv_inode * raw_inode; + unsigned count; sb = inode->i_sb; ino = inode->i_ino; @@ -62,137 +105,119 @@ printk("sysv_free_inode: inode 0,1,2 or nonexistent inode\n"); return; } - if (!(bh = sv_bread(sb, inode->i_dev, sb->sv_firstinodezone + ((ino-1) >> sb->sv_inodes_per_block_bits)))) { + raw_inode = sysv_raw_inode(sb, ino, &bh); + clear_inode(inode); + if (!raw_inode) { printk("sysv_free_inode: unable to read inode block on device " - "%s\n", kdevname(inode->i_dev)); - clear_inode(inode); + "%s\n", bdevname(inode->i_dev)); return; } - raw_inode = (struct sysv_inode *) bh->b_data + ((ino-1) & sb->sv_inodes_per_block_1); - clear_inode(inode); lock_super(sb); - if (*sb->sv_sb_fic_count < sb->sv_fic_size) - *sv_sb_fic_inode(sb,(*sb->sv_sb_fic_count)++) = ino; - (*sb->sv_sb_total_free_inodes)++; - mark_buffer_dirty(sb->sv_bh1); /* super-block has been modified */ - if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2); - sb->s_dirt = 1; /* and needs time stamp */ + count = fs16_to_cpu(sb, *sb->sv_sb_fic_count); + if (count < sb->sv_fic_size) { + *sv_sb_fic_inode(sb,count++) = cpu_to_fs16(sb, ino); + *sb->sv_sb_fic_count = cpu_to_fs16(sb, count); + } + fs16_add(sb, sb->sv_sb_total_free_inodes, 1); + dirty_sb(sb); memset(raw_inode, 0, sizeof(struct sysv_inode)); mark_buffer_dirty(bh); unlock_super(sb); brelse(bh); } -struct inode * sysv_new_inode(const struct inode * dir) +struct inode * sysv_new_inode(const struct inode * dir, mode_t mode) { struct inode * inode; struct super_block * sb; - struct buffer_head * bh; - struct sysv_inode * raw_inode; - int i,j,ino,block; + u16 ino; + unsigned count; - if (!dir) - return NULL; sb = dir->i_sb; inode = new_inode(sb); if (!inode) return NULL; - lock_super(sb); /* protect against task switches */ - if ((*sb->sv_sb_fic_count == 0) - || (*sv_sb_fic_inode(sb,(*sb->sv_sb_fic_count)-1) == 0) /* Applies only to SystemV2 FS */ - ) { - /* Rebuild cache of free inodes: */ - /* i : index into cache slot being filled */ - /* ino : inode we are trying */ - /* block : firstinodezone + (ino-1)/inodes_per_block */ - /* j : (ino-1)%inodes_per_block */ - /* bh : buffer for block */ - /* raw_inode : pointer to inode ino in the block */ - for (i = 0, ino = SYSV_ROOT_INO+1, block = sb->sv_firstinodezone, j = SYSV_ROOT_INO ; i < sb->sv_fic_size && block < sb->sv_firstdatazone ; block++, j = 0) { - if (!(bh = sv_bread(sb, sb->s_dev, block))) { - printk("sysv_new_inode: unable to read inode table\n"); - break; /* go with what we've got */ - /* FIXME: Perhaps try the next block? */ - } - raw_inode = (struct sysv_inode *) bh->b_data + j; - for (; j < sb->sv_inodes_per_block && i < sb->sv_fic_size; ino++, j++, raw_inode++) { - if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0) - *sv_sb_fic_inode(sb,i++) = ino; - } - brelse(bh); - } - if (i == 0) { + lock_super(sb); + count = fs16_to_cpu(sb, *sb->sv_sb_fic_count); + if (count == 0 || (*sv_sb_fic_inode(sb,count-1) == 0)) { + count = refill_free_cache(sb); + if (count == 0) { iput(inode); unlock_super(sb); - return NULL; /* no inodes available */ + return NULL; } - *sb->sv_sb_fic_count = i; } - /* Now *sb->sv_sb_fic_count > 0. */ - ino = *sv_sb_fic_inode(sb,--(*sb->sv_sb_fic_count)); - mark_buffer_dirty(sb->sv_bh1); /* super-block has been modified */ - if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2); - sb->s_dirt = 1; /* and needs time stamp */ + /* Now count > 0. */ + ino = *sv_sb_fic_inode(sb,--count); + *sb->sv_sb_fic_count = cpu_to_fs16(sb, count); + fs16_add(sb, sb->sv_sb_total_free_inodes, -1); + dirty_sb(sb); inode->i_uid = current->fsuid; inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; - inode->i_ino = ino; + inode->i_ino = fs16_to_cpu(sb, ino); inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_blocks = inode->i_blksize = 0; insert_inode_hash(inode); mark_inode_dirty(inode); - /* Change directory entry: */ - inode->i_mode = 0; /* for sysv_write_inode() */ + inode->i_mode = mode; /* for sysv_write_inode() */ sysv_write_inode(inode, 0); /* ensure inode not allocated again */ /* FIXME: caller may call this too. */ mark_inode_dirty(inode); /* cleared by sysv_write_inode() */ /* That's it. */ - (*sb->sv_sb_total_free_inodes)--; - mark_buffer_dirty(sb->sv_bh2); /* super-block has been modified again */ - sb->s_dirt = 1; /* and needs time stamp again */ unlock_super(sb); return inode; } unsigned long sysv_count_free_inodes(struct super_block * sb) { -#if 1 /* test */ struct buffer_head * bh; struct sysv_inode * raw_inode; - int j,block,count; + int ino, count, sb_count; + + lock_super(sb); + + sb_count = fs16_to_cpu(sb, *sb->sv_sb_total_free_inodes); + + if (0) + goto trust_sb; /* this causes a lot of disk traffic ... */ count = 0; - lock_super(sb); - /* i : index into cache slot being filled */ - /* ino : inode we are trying */ - /* block : firstinodezone + (ino-1)/inodes_per_block */ - /* j : (ino-1)%inodes_per_block */ - /* bh : buffer for block */ - /* raw_inode : pointer to inode ino in the block */ - for (block = sb->sv_firstinodezone, j = SYSV_ROOT_INO ; block < sb->sv_firstdatazone ; block++, j = 0) { - if (!(bh = sv_bread(sb, sb->s_dev, block))) { - printk("sysv_count_free_inodes: unable to read inode table\n"); - break; /* go with what we've got */ - /* FIXME: Perhaps try the next block? */ - } - raw_inode = (struct sysv_inode *) bh->b_data + j; - for (; j < sb->sv_inodes_per_block ; j++, raw_inode++) - if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0) - count++; - brelse(bh); - } - if (count != *sb->sv_sb_total_free_inodes) { - printk("sysv_count_free_inodes: free inode count was %d, correcting to %d\n",(short)(*sb->sv_sb_total_free_inodes),count); - if (!(sb->s_flags & MS_RDONLY)) { - *sb->sv_sb_total_free_inodes = count; - mark_buffer_dirty(sb->sv_bh2); /* super-block has been modified */ - sb->s_dirt = 1; /* and needs time stamp */ - } + ino = SYSV_ROOT_INO+1; + raw_inode = sysv_raw_inode(sb, ino, &bh); + if (!raw_inode) + goto Eio; + while (ino <= sb->sv_ninodes) { + if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0) + count++; + if ((ino++ & sb->sv_inodes_per_block_1) == 0) { + brelse(bh); + raw_inode = sysv_raw_inode(sb, ino, &bh); + if (!raw_inode) + goto Eio; + } else + raw_inode++; } + brelse(bh); + if (count != sb_count) + goto Einval; +out: unlock_super(sb); return count; -#else - return *sb->sv_sb_total_free_inodes; -#endif -} +Einval: + printk("sysv_count_free_inodes: " + "free inode count was %d, correcting to %d\n", + sb_count, count); + if (!(sb->s_flags & MS_RDONLY)) { + *sb->sv_sb_total_free_inodes = cpu_to_fs16(sb, count); + dirty_sb(sb); + } + goto out; + +Eio: + printk("sysv_count_free_inodes: unable to read inode table\n"); +trust_sb: + count = sb_count; + goto out; +} diff -u --recursive --new-file v2.4.5/linux/fs/sysv/inode.c linux/fs/sysv/inode.c --- v2.4.5/linux/fs/sysv/inode.c Tue Apr 17 23:16:39 2001 +++ linux/fs/sysv/inode.c Mon Jul 2 14:03:04 2001 @@ -21,499 +21,13 @@ * the superblock. */ -#include -#include - -#include -#include #include #include -#include -#include #include -#include #include #include #include -#include - -#if 0 -void sysv_print_inode(struct inode * inode) -{ - printk("ino %lu mode 0%6.6o lk %d uid %d gid %d" - " sz %lu blks %lu cnt %u\n", - inode->i_ino, inode->i_mode, inode->i_nlink, inode->i_uid, - inode->i_gid, inode->i_size, inode->i_blocks, - atomic_read(&inode->i_count)); - printk(" db <0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx" - " 0x%lx 0x%lx>\n", - inode->u.sysv_i.i_data[0], inode->u.sysv_i.i_data[1], - inode->u.sysv_i.i_data[2], inode->u.sysv_i.i_data[3], - inode->u.sysv_i.i_data[4], inode->u.sysv_i.i_data[5], - inode->u.sysv_i.i_data[6], inode->u.sysv_i.i_data[7], - inode->u.sysv_i.i_data[8], inode->u.sysv_i.i_data[9]); - printk(" ib <0x%lx 0x%lx 0x%lx>\n", - inode->u.sysv_i.i_data[10], - inode->u.sysv_i.i_data[11], - inode->u.sysv_i.i_data[12]); -} -#endif - -static void sysv_delete_inode(struct inode *inode) -{ - lock_kernel(); - inode->i_size = 0; - sysv_truncate(inode); - sysv_free_inode(inode); - unlock_kernel(); -} - -static void sysv_put_super(struct super_block *); -static void sysv_write_super(struct super_block *); -static void sysv_read_inode(struct inode *); -static int sysv_statfs(struct super_block *, struct statfs *); - -static struct super_operations sysv_sops = { - read_inode: sysv_read_inode, - write_inode: sysv_write_inode, - delete_inode: sysv_delete_inode, - put_super: sysv_put_super, - write_super: sysv_write_super, - statfs: sysv_statfs, -}; - -/* The following functions try to recognize specific filesystems. - * We recognize: - * - Xenix FS by its magic number. - * - SystemV FS by its magic number. - * - Coherent FS by its funny fname/fpack field. - * We discriminate among SystemV4 and SystemV2 FS by the assumption that - * the time stamp is not < 01-01-1980. - */ - -static void detected_bs (u_char type, struct super_block *sb) -{ - u_char n_bits = type+8; - int bsize = 1 << n_bits; - int bsize_4 = bsize >> 2; - - sb->sv_block_size = bsize; - sb->sv_block_size_1 = bsize-1; - sb->sv_block_size_bits = n_bits; - sb->sv_block_size_dec_bits = (bsize==512) ? 1 : 0; - sb->sv_block_size_inc_bits = (bsize==2048) ? 1 : 0; - sb->sv_inodes_per_block = bsize >> 6; - sb->sv_inodes_per_block_1 = (bsize >> 6)-1; - sb->sv_inodes_per_block_bits = n_bits-6; - sb->sv_toobig_block = 10 + - (sb->sv_ind_per_block = bsize_4) + - (sb->sv_ind_per_block_2 = bsize_4*bsize_4) + - (sb->sv_ind_per_block_3 = bsize_4*bsize_4*bsize_4); - sb->sv_ind_per_block_1 = bsize_4-1; - sb->sv_ind_per_block_2_1 = bsize_4*bsize_4-1; - sb->sv_ind_per_block_2_bits = 2 * - (sb->sv_ind_per_block_bits = n_bits-2); - sb->sv_ind_per_block_block_size_1 = bsize_4*bsize-1; - sb->sv_ind_per_block_block_size_bits = 2*n_bits-2; - sb->sv_ind_per_block_2_block_size_1 = bsize_4*bsize_4*bsize-1; - sb->sv_ind_per_block_2_block_size_bits = 3*n_bits-4; - sb->sv_ind0_size = 10 * bsize; - sb->sv_ind1_size = (10 + bsize_4)* bsize; - sb->sv_ind2_size = (10 + bsize_4 + bsize_4*bsize_4) * bsize; -} - -static const char* detect_xenix (struct super_block *sb, struct buffer_head *bh) -{ - struct xenix_super_block * sbd; - - sbd = (struct xenix_super_block *) bh->b_data; - if (sbd->s_magic != 0x2b5544) - return NULL; - if (sbd->s_type > 2 || sbd->s_type < 1) - return NULL; - detected_bs(sbd->s_type, sb); - sb->sv_type = FSTYPE_XENIX; - return "Xenix"; -} -static struct super_block * detected_xenix (struct super_block *sb, struct buffer_head *bh1, struct buffer_head *bh2) -{ - struct xenix_super_block * sbd1; - struct xenix_super_block * sbd2; - - if (sb->sv_block_size >= BLOCK_SIZE) - /* block size >= 1024, so bh1 = bh2 */ - sbd1 = sbd2 = (struct xenix_super_block *) bh1->b_data; - else { - /* block size = 512, so bh1 != bh2 */ - sbd1 = (struct xenix_super_block *) bh1->b_data; - sbd2 = (struct xenix_super_block *) (bh2->b_data - BLOCK_SIZE/2); - /* sanity check */ - if (sbd2->s_magic != 0x2b5544) - return NULL; - } - - sb->sv_convert = 0; - sb->sv_kludge_symlinks = 1; - sb->sv_truncate = 1; - sb->sv_link_max = XENIX_LINK_MAX; - sb->sv_fic_size = XENIX_NICINOD; - sb->sv_flc_size = XENIX_NICFREE; - sb->sv_bh1 = bh1; - sb->sv_bh2 = bh2; - sb->sv_sbd1 = (char *) sbd1; - sb->sv_sbd2 = (char *) sbd2; - sb->sv_sb_fic_count = &sbd1->s_ninode; - sb->sv_sb_fic_inodes = &sbd1->s_inode[0]; - sb->sv_sb_total_free_inodes = &sbd2->s_tinode; - sb->sv_sb_flc_count = &sbd1->s_nfree; - sb->sv_sb_flc_blocks = &sbd1->s_free[0]; - sb->sv_sb_total_free_blocks = &sbd2->s_tfree; - sb->sv_sb_time = &sbd2->s_time; - sb->sv_firstinodezone = 2; - sb->sv_firstdatazone = sbd1->s_isize; - sb->sv_nzones = sbd1->s_fsize; - sb->sv_ndatazones = sb->sv_nzones - sb->sv_firstdatazone; - return sb; -} - -static const char* detect_sysv4 (struct super_block *sb, struct buffer_head *bh) -{ - struct sysv4_super_block * sbd; - - sbd = (struct sysv4_super_block *) (bh->b_data + BLOCK_SIZE/2); - if (sbd->s_magic != 0xfd187e20) - return NULL; - if (sbd->s_time < 315532800) /* this is likely to happen on SystemV2 FS */ - return NULL; - if ((sbd->s_type > 3 || sbd->s_type < 1) && (sbd->s_type > 0x30 || sbd->s_type < 0x10)) - return NULL; - - /* On Interactive Unix (ISC) Version 4.0/3.x s_type field = 0x10, - 0x20 or 0x30 indicates that symbolic links and the 14-character - filename limit is gone. Due to lack of information about this - feature read-only mode seems to be a reasonable approach... -KGB */ - - if (sbd->s_type >= 0x10) { - printk("SysV FS: can't handle long file names on %s, " - "forcing read-only mode.\n", kdevname(sb->s_dev)); - sb->s_flags |= MS_RDONLY; - } - - detected_bs(sbd->s_type >= 0x10 ? (sbd->s_type >> 4) : sbd->s_type, sb); - sb->sv_type = FSTYPE_SYSV4; - return "SystemV"; -} - -static struct super_block * detected_sysv4 (struct super_block *sb, struct buffer_head *bh) -{ - struct sysv4_super_block * sbd; - - if (sb->sv_block_size >= BLOCK_SIZE) - sbd = (struct sysv4_super_block *) (bh->b_data + BLOCK_SIZE/2); - else { - sbd = (struct sysv4_super_block *) bh->b_data; - /* sanity check */ - if (sbd->s_magic != 0xfd187e20) - return NULL; - if (sbd->s_time < 315532800) - return NULL; - } - - sb->sv_convert = 0; - sb->sv_kludge_symlinks = 0; /* ?? */ - sb->sv_truncate = 1; - sb->sv_link_max = SYSV_LINK_MAX; - sb->sv_fic_size = SYSV_NICINOD; - sb->sv_flc_size = SYSV_NICFREE; - sb->sv_bh1 = bh; - sb->sv_bh2 = bh; - sb->sv_sbd1 = (char *) sbd; - sb->sv_sbd2 = (char *) sbd; - sb->sv_sb_fic_count = &sbd->s_ninode; - sb->sv_sb_fic_inodes = &sbd->s_inode[0]; - sb->sv_sb_total_free_inodes = &sbd->s_tinode; - sb->sv_sb_flc_count = &sbd->s_nfree; - sb->sv_sb_flc_blocks = &sbd->s_free[0]; - sb->sv_sb_total_free_blocks = &sbd->s_tfree; - sb->sv_sb_time = &sbd->s_time; - sb->sv_sb_state = &sbd->s_state; - sb->sv_firstinodezone = 2; - sb->sv_firstdatazone = sbd->s_isize; - sb->sv_nzones = sbd->s_fsize; - sb->sv_ndatazones = sb->sv_nzones - sb->sv_firstdatazone; - return sb; -} - -static const char* detect_sysv2 (struct super_block *sb, struct buffer_head *bh) -{ - struct sysv2_super_block * sbd; - - sbd = (struct sysv2_super_block *) (bh->b_data + BLOCK_SIZE/2); - if (sbd->s_magic != 0xfd187e20) - return NULL; - if (sbd->s_time < 315532800) /* this is likely to happen on SystemV4 FS */ - return NULL; - if (sbd->s_type > 3 || sbd->s_type < 1) - return NULL; - detected_bs(sbd->s_type, sb); - sb->sv_type = FSTYPE_SYSV2; - return "SystemV Release 2"; -} -static struct super_block * detected_sysv2 (struct super_block *sb, struct buffer_head *bh) -{ - struct sysv2_super_block * sbd; - - if (sb->sv_block_size >= BLOCK_SIZE) - sbd = (struct sysv2_super_block *) (bh->b_data + BLOCK_SIZE/2); - else { - sbd = (struct sysv2_super_block *) bh->b_data; - /* sanity check */ - if (sbd->s_magic != 0xfd187e20) - return NULL; - if (sbd->s_time < 315532800) - return NULL; - } - - sb->sv_convert = 0; - sb->sv_kludge_symlinks = 0; /* ?? */ - sb->sv_truncate = 1; - sb->sv_link_max = SYSV_LINK_MAX; - sb->sv_fic_size = SYSV_NICINOD; - sb->sv_flc_size = SYSV_NICFREE; - sb->sv_bh1 = bh; - sb->sv_bh2 = bh; - sb->sv_sbd1 = (char *) sbd; - sb->sv_sbd2 = (char *) sbd; - sb->sv_sb_fic_count = &sbd->s_ninode; - sb->sv_sb_fic_inodes = &sbd->s_inode[0]; - sb->sv_sb_total_free_inodes = &sbd->s_tinode; - sb->sv_sb_flc_count = &sbd->s_nfree; - sb->sv_sb_flc_blocks = &sbd->s_free[0]; - sb->sv_sb_total_free_blocks = &sbd->s_tfree; - sb->sv_sb_time = &sbd->s_time; - sb->sv_sb_state = &sbd->s_state; - sb->sv_firstinodezone = 2; - sb->sv_firstdatazone = sbd->s_isize; - sb->sv_nzones = sbd->s_fsize; - sb->sv_ndatazones = sb->sv_nzones - sb->sv_firstdatazone; - return sb; -} - -static const char* detect_coherent (struct super_block *sb, struct buffer_head *bh) -{ - struct coh_super_block * sbd; - - sbd = (struct coh_super_block *) (bh->b_data + BLOCK_SIZE/2); - if ((memcmp(sbd->s_fname,"noname",6) && memcmp(sbd->s_fname,"xxxxx ",6)) - || (memcmp(sbd->s_fpack,"nopack",6) && memcmp(sbd->s_fpack,"xxxxx\n",6))) - return NULL; - detected_bs(1, sb); - sb->sv_type = FSTYPE_COH; - return "Coherent"; -} -static struct super_block * detected_coherent (struct super_block *sb, struct buffer_head *bh) -{ - struct coh_super_block * sbd; - - sbd = (struct coh_super_block *) bh->b_data; - /* sanity check */ - if ((memcmp(sbd->s_fname,"noname",6) && memcmp(sbd->s_fname,"xxxxx ",6)) - || (memcmp(sbd->s_fpack,"nopack",6) && memcmp(sbd->s_fpack,"xxxxx\n",6))) - return NULL; - - sb->sv_convert = 1; - sb->sv_kludge_symlinks = 1; - sb->sv_truncate = 1; - sb->sv_link_max = COH_LINK_MAX; - sb->sv_fic_size = COH_NICINOD; - sb->sv_flc_size = COH_NICFREE; - sb->sv_bh1 = bh; - sb->sv_bh2 = bh; - sb->sv_sbd1 = (char *) sbd; - sb->sv_sbd2 = (char *) sbd; - sb->sv_sb_fic_count = &sbd->s_ninode; - sb->sv_sb_fic_inodes = &sbd->s_inode[0]; - sb->sv_sb_total_free_inodes = &sbd->s_tinode; - sb->sv_sb_flc_count = &sbd->s_nfree; - sb->sv_sb_flc_blocks = &sbd->s_free[0]; - sb->sv_sb_total_free_blocks = &sbd->s_tfree; - sb->sv_sb_time = &sbd->s_time; - sb->sv_firstinodezone = 2; - sb->sv_firstdatazone = sbd->s_isize; - sb->sv_nzones = from_coh_ulong(sbd->s_fsize); - sb->sv_ndatazones = sb->sv_nzones - sb->sv_firstdatazone; - return sb; -} -static struct super_block *sysv_read_super(struct super_block *sb, - void *data, int silent) -{ - struct buffer_head *bh; - const char *found; - kdev_t dev = sb->s_dev; - struct inode *root_inode; - unsigned long blocknr; - - if (1024 != sizeof (struct xenix_super_block)) - panic("Xenix FS: bad super-block size"); - if ((512 != sizeof (struct sysv4_super_block)) - || (512 != sizeof (struct sysv2_super_block))) - panic("SystemV FS: bad super-block size"); - if (500 != sizeof (struct coh_super_block)) - panic("Coherent FS: bad super-block size"); - if (64 != sizeof (struct sysv_inode)) - panic("sysv fs: bad i-node size"); - set_blocksize(dev,BLOCK_SIZE); - sb->sv_block_base = 0; - - /* Try to read Xenix superblock */ - if ((bh = bread(dev, 1, BLOCK_SIZE)) != NULL) { - if ((found = detect_xenix(sb,bh)) != NULL) - goto ok; - brelse(bh); - } - if ((bh = bread(dev, 0, BLOCK_SIZE)) != NULL) { - /* Try to recognize SystemV superblock */ - if ((found = detect_sysv4(sb,bh)) != NULL) - goto ok; - if ((found = detect_sysv2(sb,bh)) != NULL) - goto ok; - /* Try to recognize Coherent superblock */ - if ((found = detect_coherent(sb,bh)) != NULL) - goto ok; - brelse(bh); - } - /* Try to recognize SystemV superblock */ - /* Offset by 1 track, i.e. most probably 9, 15, or 18 kilobytes. */ - /* 2kB blocks with offset of 9 and 15 kilobytes are not supported. */ - /* Maybe we should also check the device geometry ? */ - { static int offsets[] = { 9, 15, 18, }; - int i; - for (i = 0; i < sizeof(offsets)/sizeof(offsets[0]); i++) - if ((bh = bread(dev, offsets[i], BLOCK_SIZE)) != NULL) { - /* Try to recognize SystemV superblock */ - if ((found = detect_sysv4(sb,bh)) != NULL) { - if (sb->sv_block_size>BLOCK_SIZE && (offsets[i] % 2)) - goto bad_shift; - sb->sv_block_base = (offsets[i] << sb->sv_block_size_dec_bits) >> sb->sv_block_size_inc_bits; - goto ok; - } - if ((found = detect_sysv2(sb,bh)) != NULL) { - if (sb->sv_block_size>BLOCK_SIZE && (offsets[i] % 2)) - goto bad_shift; - sb->sv_block_base = (offsets[i] << sb->sv_block_size_dec_bits) >> sb->sv_block_size_inc_bits; - goto ok; - } - brelse(bh); - } - } - bad_shift: - if (!silent) - printk("VFS: unable to read Xenix/SystemV/Coherent superblock on device " - "%s\n", kdevname(dev)); - failed: - return NULL; - - ok: - if (sb->sv_block_size >= BLOCK_SIZE) { - if (sb->sv_block_size != BLOCK_SIZE) { - brelse(bh); - set_blocksize(dev, sb->sv_block_size); - blocknr = (bh->b_blocknr << sb->sv_block_size_dec_bits) >> sb->sv_block_size_inc_bits; - if ((bh = bread(dev, blocknr, sb->sv_block_size)) == NULL) - goto bad_superblock; - } - switch (sb->sv_type) { - case FSTYPE_XENIX: - if (!detected_xenix(sb,bh,bh)) - goto bad_superblock; - break; - case FSTYPE_SYSV4: - if (!detected_sysv4(sb,bh)) - goto bad_superblock; - break; - case FSTYPE_SYSV2: - if (!detected_sysv2(sb,bh)) - goto bad_superblock; - break; - default: goto bad_superblock; - goto superblock_ok; - bad_superblock: - brelse(bh); - printk("SysV FS: cannot read superblock in %d byte mode\n", sb->sv_block_size); - goto failed; - superblock_ok: - } - } else { - /* Switch to 512 block size. Unfortunately, we have to - release the block bh and read it again. */ - struct buffer_head *bh1, *bh2; - unsigned long blocknr = (bh->b_blocknr << sb->sv_block_size_dec_bits) >> sb->sv_block_size_inc_bits; - - brelse(bh); - set_blocksize(dev,sb->sv_block_size); - bh1 = NULL; bh2 = NULL; - switch (sb->sv_type) { - case FSTYPE_XENIX: - if ((bh1 = bread(dev, blocknr, sb->sv_block_size)) == NULL) - goto bad_superblock2; - if ((bh2 = bread(dev, blocknr+1, sb->sv_block_size)) == NULL) - goto bad_superblock2; - if (!detected_xenix(sb,bh1,bh2)) - goto bad_superblock2; - break; - case FSTYPE_SYSV4: - if ((bh2 = bread(dev, blocknr+1, sb->sv_block_size)) == NULL) - goto bad_superblock2; - if (!detected_sysv4(sb,bh2)) - goto bad_superblock2; - break; - case FSTYPE_SYSV2: - if ((bh2 = bread(dev, blocknr+1, sb->sv_block_size)) == NULL) - goto bad_superblock2; - if (!detected_sysv2(sb,bh2)) - goto bad_superblock2; - break; - case FSTYPE_COH: - if ((bh2 = bread(dev, blocknr+1, sb->sv_block_size)) == NULL) - goto bad_superblock2; - if (!detected_coherent(sb,bh2)) - goto bad_superblock2; - break; - default: - bad_superblock2: - brelse(bh1); - brelse(bh2); - set_blocksize(sb->s_dev,BLOCK_SIZE); - printk("SysV FS: cannot read superblock in 512 byte mode\n"); - goto failed; - } - } - sb->sv_ninodes = (sb->sv_firstdatazone - sb->sv_firstinodezone) << sb->sv_inodes_per_block_bits; - if (!silent) - printk("VFS: Found a %s FS (block size = %d) on device %s\n", - found, sb->sv_block_size, kdevname(dev)); - sb->s_magic = SYSV_MAGIC_BASE + sb->sv_type; - /* The buffer code now supports block size 512 as well as 1024. */ - sb->s_blocksize = sb->sv_block_size; - sb->s_blocksize_bits = sb->sv_block_size_bits; - /* set up enough so that it can read an inode */ - sb->s_op = &sysv_sops; - root_inode = iget(sb,SYSV_ROOT_INO); - sb->s_root = d_alloc_root(root_inode); - if (!sb->s_root) { - printk("SysV FS: get root inode failed\n"); - sysv_put_super(sb); - return NULL; - } -#ifndef CONFIG_SYSV_FS_WRITE - sb->s_flags |= MS_RDONLY; -#endif - sb->s_dirt = 1; - /* brelse(bh); resp. brelse(bh1); brelse(bh2); - occurs when the disk is unmounted. */ - return sb; -} /* This is only called on sync() and umount(), when s_dirt=1. */ static void sysv_write_super(struct super_block *sb) @@ -523,15 +37,11 @@ then attach current time stamp. But if the filesystem was marked clean, keep it clean. */ unsigned long time = CURRENT_TIME; - unsigned long old_time = *sb->sv_sb_time; - if (sb->sv_convert) - old_time = from_coh_ulong(old_time); + unsigned long old_time = fs32_to_cpu(sb, *sb->sv_sb_time); if (sb->sv_type == FSTYPE_SYSV4) - if (*sb->sv_sb_state == 0x7c269d38 - old_time) - *sb->sv_sb_state = 0x7c269d38 - time; - if (sb->sv_convert) - time = to_coh_ulong(time); - *sb->sv_sb_time = time; + if (*sb->sv_sb_state == cpu_to_fs32(sb, 0x7c269d38 - old_time)) + *sb->sv_sb_state = cpu_to_fs32(sb, 0x7c269d38 - time); + *sb->sv_sb_time = cpu_to_fs32(sb, time); mark_buffer_dirty(sb->sv_bh2); } sb->s_dirt = 0; @@ -550,445 +60,81 @@ static int sysv_statfs(struct super_block *sb, struct statfs *buf) { - buf->f_type = sb->s_magic; /* type of filesystem */ - buf->f_bsize = sb->sv_block_size; /* block size */ - buf->f_blocks = sb->sv_ndatazones; /* total data blocks in file system */ - buf->f_bfree = sysv_count_free_blocks(sb); /* free blocks in fs */ - buf->f_bavail = buf->f_bfree; /* free blocks available to non-superuser */ - buf->f_files = sb->sv_ninodes; /* total file nodes in file system */ - buf->f_ffree = sysv_count_free_inodes(sb); /* free file nodes in fs */ + buf->f_type = sb->s_magic; + buf->f_bsize = sb->s_blocksize; + buf->f_blocks = sb->sv_ndatazones; + buf->f_bavail = buf->f_bfree = sysv_count_free_blocks(sb); + buf->f_files = sb->sv_ninodes; + buf->f_ffree = sysv_count_free_inodes(sb); buf->f_namelen = SYSV_NAMELEN; - /* Don't know what value to put in buf->f_fsid */ /* file system id */ return 0; } - -/* bmap support for running executables and shared libraries. */ - -static inline int inode_bmap(struct super_block * sb, struct inode * inode, int nr) -{ - int tmp = inode->u.sysv_i.i_data[nr]; - if (!tmp) - return 0; - return tmp + sb->sv_block_base; -} - -static int block_bmap(struct super_block * sb, struct buffer_head * bh, int nr, int convert) -{ - int tmp; - - if (!bh) - return 0; - tmp = ((sysv_zone_t *) bh->b_data) [nr]; - if (convert) - tmp = from_coh_ulong(tmp); - brelse(bh); - if (!tmp) - return 0; - return tmp + sb->sv_block_base; -} - -static unsigned int sysv_block_map(struct inode *inode, unsigned int block) -{ - struct super_block *sb; - int i, ret, convert; - - ret = 0; - lock_kernel(); - sb = inode->i_sb; - if (block < 10) { - ret = inode_bmap(sb, inode, block); - goto out; - } - block -= 10; - convert = sb->sv_convert; - if (block < sb->sv_ind_per_block) { - i = inode_bmap(sb, inode, 10); - if (!i) - goto out; - ret = block_bmap(sb, - bread(inode->i_dev, i, sb->sv_block_size), - block, convert); - goto out; - } - block -= sb->sv_ind_per_block; - if (block < sb->sv_ind_per_block_2) { - i = inode_bmap(sb, inode, 11); - if (!i) - goto out; - i = block_bmap(sb, - bread(inode->i_dev, i, sb->sv_block_size), - (block >> sb->sv_ind_per_block_bits), convert); - if (!i) - goto out; - ret = block_bmap(sb, - bread(inode->i_dev, i, sb->sv_block_size), - (block & sb->sv_ind_per_block_1), convert); - goto out; - } - block -= sb->sv_ind_per_block_2; - if (block < sb->sv_ind_per_block_3) { - i = inode_bmap(sb, inode, 12); - if (!i) - goto out; - i = block_bmap(sb, - bread(inode->i_dev, i, sb->sv_block_size), - (block >> sb->sv_ind_per_block_2_bits), convert); - if (!i) - goto out; - ret = block_bmap(sb, - bread(inode->i_dev, i, sb->sv_block_size), - ((block >> sb->sv_ind_per_block_bits) & - sb->sv_ind_per_block_1), convert); - if (!i) - goto out; - ret = block_bmap(sb, - bread(inode->i_dev, i, sb->sv_block_size), - (block & sb->sv_ind_per_block_1), convert); - goto out; - } - if ((int)block < 0) - printk("sysv_block_map: block < 0\n"); - else - printk("sysv_block_map: block > big\n"); -out: - unlock_kernel(); - return ret; -} - -/* End of bmap support. */ - - -/* Access selected blocks of regular files (or directories) */ - -static struct buffer_head *inode_getblk(struct inode *inode, int nr, int new_block, - int *err, int metadata, long *phys, int *new) +/* + * NXI <-> N0XI for PDP, XIN <-> XIN0 for le32, NIX <-> 0NIX for be32 + */ +static inline void read3byte(struct super_block *sb, + unsigned char * from, unsigned char * to) { - struct super_block *sb; - u32 tmp; - u32 *p; - struct buffer_head * result; - - sb = inode->i_sb; - p = inode->u.sysv_i.i_data + nr; -repeat: - tmp = *p; - if (tmp) { - if (metadata) { - result = sv_getblk(sb, inode->i_dev, tmp); - if (tmp == *p) - return result; - brelse(result); - goto repeat; - } else { - *phys = tmp; - return NULL; - } - } - - tmp = sysv_new_block(sb); - if (!tmp) { - *err = -ENOSPC; - return NULL; - } - if (metadata) { - result = sv_getblk(sb, inode->i_dev, tmp); - if (*p) { - sysv_free_block(sb, tmp); - brelse(result); - goto repeat; - } + if (sb->sv_bytesex == BYTESEX_PDP) { + to[0] = from[0]; + to[1] = 0; + to[2] = from[1]; + to[3] = from[2]; + } else if (sb->sv_bytesex == BYTESEX_LE) { + to[0] = from[0]; + to[1] = from[1]; + to[2] = from[2]; + to[3] = 0; } else { - if (*p) { - /* - * Nobody is allowed to change block allocation - * state from under us: - */ - BUG(); - sysv_free_block(sb, tmp); - goto repeat; - } - *phys = tmp; - result = NULL; - *err = 0; - *new = 1; + to[0] = 0; + to[1] = from[0]; + to[2] = from[1]; + to[3] = from[2]; } - *p = tmp; - - inode->i_ctime = CURRENT_TIME; - mark_inode_dirty(inode); - return result; } -static struct buffer_head *block_getblk(struct inode *inode, - struct buffer_head *bh, int nr, int new_block, int *err, - int metadata, long *phys, int *new) -{ - struct super_block *sb; - u32 tmp, block; - sysv_zone_t *p; - struct buffer_head * result; - - result = NULL; - if (!bh) - goto out; - if (!buffer_uptodate(bh)) { - ll_rw_block(READ, 1, &bh); - wait_on_buffer(bh); - if (!buffer_uptodate(bh)) - goto out; - } - sb = inode->i_sb; - p = nr + (sysv_zone_t *) bh->b_data; -repeat: - block = tmp = *p; - if (sb->sv_convert) - block = from_coh_ulong(block); - if (tmp) { - if (metadata) { - result = sv_getblk(sb, bh->b_dev, block); - if (tmp == *p) - goto out; - brelse(result); - goto repeat; - } else { - *phys = tmp; - goto out; - } - } - - block = sysv_new_block(sb); - if (!block) - goto out; - if (metadata) { - result = sv_getblk(sb, bh->b_dev, block); - if (*p) { - sysv_free_block(sb, block); - brelse(result); - goto repeat; - } - memset(result->b_data, 0, sb->sv_block_size); - mark_buffer_uptodate(result, 1); - mark_buffer_dirty(result); +static inline void write3byte(struct super_block *sb, + unsigned char * from, unsigned char * to) +{ + if (sb->sv_bytesex == BYTESEX_PDP) { + to[0] = from[0]; + to[1] = from[2]; + to[2] = from[3]; + } else if (sb->sv_bytesex == BYTESEX_LE) { + to[0] = from[0]; + to[1] = from[1]; + to[2] = from[2]; } else { - *phys = tmp; - *new = 1; - } - if (*p) { - sysv_free_block(sb, block); - brelse(result); - goto repeat; + to[0] = from[1]; + to[1] = from[2]; + to[2] = from[3]; } - *p = (sb->sv_convert ? to_coh_ulong(block) : block); - mark_buffer_dirty(bh); - *err = 0; -out: - brelse(bh); - return result; } -static int sysv_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create) -{ - struct super_block *sb; - int ret, err, new; - struct buffer_head *bh; - unsigned long ptr, phys; - - if (!create) { - phys = sysv_block_map(inode, iblock); - if (phys) { - bh_result->b_dev = inode->i_dev; - bh_result->b_blocknr = phys; - bh_result->b_state |= (1UL << BH_Mapped); - } - return 0; - } - - err = -EIO; - new = 0; - ret = 0; - bh = NULL; - - lock_kernel(); - sb = inode->i_sb; - if (iblock < 0) - goto abort_negative; - if (iblock > sb->sv_ind_per_block_3) - goto abort_too_big; - - err = 0; - ptr = iblock; - - /* - * ok, these macros clean the logic up a bit and make - * it much more readable: - */ -#define GET_INODE_DATABLOCK(x) \ - inode_getblk(inode, x, iblock, &err, 0, &phys, &new) -#define GET_INODE_PTR(x) \ - inode_getblk(inode, x, iblock, &err, 1, NULL, NULL) -#define GET_INDIRECT_DATABLOCK(x) \ - block_getblk (inode, bh, x, iblock, &err, 0, &phys, &new); -#define GET_INDIRECT_PTR(x) \ - block_getblk (inode, bh, x, iblock, &err, 1, NULL, NULL); - - if (ptr < 10) { - bh = GET_INODE_DATABLOCK(ptr); - goto out; - } - ptr -= 10; - if (ptr < sb->sv_ind_per_block) { - bh = GET_INODE_PTR(10); - goto get_indirect; - } - ptr -= sb->sv_ind_per_block; - if (ptr < sb->sv_ind_per_block_2) { - bh = GET_INODE_PTR(11); - goto get_double; - } - ptr -= sb->sv_ind_per_block_2; - bh = GET_INODE_PTR(12); - bh = GET_INDIRECT_PTR(ptr >> sb->sv_ind_per_block_2_bits); -get_double: - bh = GET_INDIRECT_PTR((ptr >> sb->sv_ind_per_block_bits) & sb->sv_ind_per_block_1); -get_indirect: - bh = GET_INDIRECT_DATABLOCK(ptr & sb->sv_ind_per_block_1); - -#undef GET_INODE_DATABLOCK -#undef GET_INODE_PTR -#undef GET_INDIRECT_DATABLOCK -#undef GET_INDIRECT_PTR - -out: - if (err) - goto abort; - bh_result->b_dev = inode->i_dev; - bh_result->b_blocknr = phys; - bh_result->b_state |= (1UL << BH_Mapped); - if (new) - bh_result->b_state |= (1UL << BH_New); -abort: - unlock_kernel(); - return err; - -abort_negative: - printk("sysv_get_block: block < 0\n"); - goto abort; - -abort_too_big: - printk("sysv_get_block: block > big\n"); - goto abort; -} - -static struct buffer_head *sysv_getblk(struct inode *inode, unsigned int block, int create) -{ - struct buffer_head dummy; - int error; - - dummy.b_state = 0; - dummy.b_blocknr = -1000; - error = sysv_get_block(inode, block, &dummy, create); - if (!error && buffer_mapped(&dummy)) { - struct buffer_head *bh; - bh = getblk(dummy.b_dev, dummy.b_blocknr, inode->i_sb->sv_block_size); - if (buffer_new(&dummy)) { - memset(bh->b_data, 0, inode->i_sb->sv_block_size); - mark_buffer_uptodate(bh, 1); - mark_buffer_dirty(bh); - } - return bh; - } - return NULL; -} - -struct buffer_head *sysv_file_bread(struct inode *inode, int block, int create) -{ - struct buffer_head *bh; - - bh = sysv_getblk(inode, block, create); - if (!bh || buffer_uptodate(bh)) - return bh; - ll_rw_block(READ, 1, &bh); - wait_on_buffer(bh); - if (buffer_uptodate(bh)) - return bh; - brelse(bh); - return NULL; -} - -static int sysv_writepage(struct page *page) -{ - return block_write_full_page(page,sysv_get_block); -} -static int sysv_readpage(struct file *file, struct page *page) -{ - return block_read_full_page(page,sysv_get_block); -} -static int sysv_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to) -{ - return block_prepare_write(page,from,to,sysv_get_block); -} -static int sysv_bmap(struct address_space *mapping, long block) -{ - return generic_block_bmap(mapping,block,sysv_get_block); -} -struct address_space_operations sysv_aops = { - readpage: sysv_readpage, - writepage: sysv_writepage, - sync_page: block_sync_page, - prepare_write: sysv_prepare_write, - commit_write: generic_commit_write, - bmap: sysv_bmap -}; - -#ifdef __BIG_ENDIAN - -static inline unsigned long read3byte (unsigned char * p) -{ - return (p[2] | (p[1]<<8) | (p[0]<<16)); -} - -static inline void write3byte (unsigned char *p , unsigned long val) -{ - p[2]=val&0xFF; - p[1]=(val>>8)&0xFF; - p[0]=(val>>16)&0xFF; -} - -#else - -static inline unsigned long read3byte (unsigned char * p) -{ - return (unsigned long)(*(unsigned short *)p) - | (unsigned long)(*(unsigned char *)(p+2)) << 16; -} - -static inline void write3byte (unsigned char * p, unsigned long val) -{ - *(unsigned short *)p = (unsigned short) val; - *(unsigned char *)(p+2) = val >> 16; -} - -#endif - -static inline unsigned long coh_read3byte (unsigned char * p) -{ - return (unsigned long)(*(unsigned char *)p) << 16 - | (unsigned long)(*(unsigned short *)(p+1)); -} - -static inline void coh_write3byte (unsigned char * p, unsigned long val) -{ - *(unsigned char *)p = val >> 16; - *(unsigned short *)(p+1) = (unsigned short) val; -} - -struct inode_operations sysv_symlink_inode_operations = { +static struct inode_operations sysv_symlink_inode_operations = { readlink: page_readlink, follow_link: page_follow_link, setattr: sysv_notify_change, }; +void sysv_set_inode(struct inode *inode, dev_t rdev) +{ + if (S_ISREG(inode->i_mode)) { + inode->i_op = &sysv_file_inode_operations; + inode->i_fop = &sysv_file_operations; + inode->i_mapping->a_ops = &sysv_aops; + } else if (S_ISDIR(inode->i_mode)) { + inode->i_op = &sysv_dir_inode_operations; + inode->i_fop = &sysv_dir_operations; + inode->i_mapping->a_ops = &sysv_aops; + } else if (S_ISLNK(inode->i_mode)) { + inode->i_op = &sysv_symlink_inode_operations; + inode->i_mapping->a_ops = &sysv_aops; + } else + init_special_inode(inode, inode->i_mode, rdev); +} + static void sysv_read_inode(struct inode *inode) { struct super_block * sb = inode->i_sb; @@ -996,67 +142,41 @@ struct sysv_inode * raw_inode; unsigned int block, ino; umode_t mode; + dev_t rdev = 0; ino = inode->i_ino; - inode->i_mode = 0; if (!ino || ino > sb->sv_ninodes) { printk("Bad inode number on dev %s" ": %d is out of range\n", kdevname(inode->i_dev), ino); return; } - block = sb->sv_firstinodezone + ((ino-1) >> sb->sv_inodes_per_block_bits); - if (!(bh = sv_bread(sb,inode->i_dev,block))) { - printk("Major problem: unable to read inode from dev " - "%s\n", - kdevname(inode->i_dev)); + raw_inode = sysv_raw_inode(sb, ino, &bh); + if (!raw_inode) { + printk("Major problem: unable to read inode from dev %s\n", + bdevname(inode->i_dev)); return; } - raw_inode = (struct sysv_inode *) bh->b_data + ((ino-1) & sb->sv_inodes_per_block_1); - mode = raw_inode->i_mode; + mode = fs16_to_cpu(sb, raw_inode->i_mode); if (sb->sv_kludge_symlinks) mode = from_coh_imode(mode); /* SystemV FS: kludge permissions if ino==SYSV_ROOT_INO ?? */ inode->i_mode = mode; - inode->i_uid = (uid_t)raw_inode->i_uid; - inode->i_gid = (gid_t)raw_inode->i_gid; - inode->i_nlink = raw_inode->i_nlink; - if (sb->sv_convert) { - inode->i_size = from_coh_ulong(raw_inode->i_size); - inode->i_atime = from_coh_ulong(raw_inode->i_atime); - inode->i_mtime = from_coh_ulong(raw_inode->i_mtime); - inode->i_ctime = from_coh_ulong(raw_inode->i_ctime); - } else { - inode->i_size = raw_inode->i_size; - inode->i_atime = raw_inode->i_atime; - inode->i_mtime = raw_inode->i_mtime; - inode->i_ctime = raw_inode->i_ctime; - } + inode->i_uid = (uid_t)fs16_to_cpu(sb, raw_inode->i_uid); + inode->i_gid = (gid_t)fs16_to_cpu(sb, raw_inode->i_gid); + inode->i_nlink = fs16_to_cpu(sb, raw_inode->i_nlink); + inode->i_size = fs32_to_cpu(sb, raw_inode->i_size); + inode->i_atime = fs32_to_cpu(sb, raw_inode->i_atime); + inode->i_mtime = fs32_to_cpu(sb, raw_inode->i_mtime); + inode->i_ctime = fs32_to_cpu(sb, raw_inode->i_ctime); inode->i_blocks = inode->i_blksize = 0; - if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - ; - else - if (sb->sv_convert) - for (block = 0; block < 10+1+1+1; block++) - inode->u.sysv_i.i_data[block] = - coh_read3byte(&raw_inode->i_a.i_addb[3*block]); - else - for (block = 0; block < 10+1+1+1; block++) - inode->u.sysv_i.i_data[block] = - read3byte(&raw_inode->i_a.i_addb[3*block]); - if (S_ISREG(inode->i_mode)) { - inode->i_op = &sysv_file_inode_operations; - inode->i_fop = &sysv_file_operations; - inode->i_mapping->a_ops = &sysv_aops; - } else if (S_ISDIR(inode->i_mode)) { - inode->i_op = &sysv_dir_inode_operations; - inode->i_fop = &sysv_dir_operations; - } else if (S_ISLNK(inode->i_mode)) { - inode->i_op = &sysv_symlink_inode_operations; - inode->i_mapping->a_ops = &sysv_aops; - } else - init_special_inode(inode, inode->i_mode,raw_inode->i_a.i_rdev); + for (block = 0; block < 10+1+1+1; block++) + read3byte(sb, &raw_inode->i_a.i_addb[3*block], + (unsigned char*)&inode->u.sysv_i.i_data[block]); brelse(bh); + if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) + rdev = (u16)fs32_to_cpu(sb, inode->u.sysv_i.i_data[0]); + sysv_set_inode(inode, rdev); } /* To avoid inconsistencies between inodes in memory and inodes on disk. */ @@ -1088,44 +208,32 @@ ino = inode->i_ino; if (!ino || ino > sb->sv_ninodes) { - printk("Bad inode number on dev %s" - ": %d is out of range\n", - kdevname(inode->i_dev), ino); + printk("Bad inode number on dev %s: %d is out of range\n", + bdevname(inode->i_dev), ino); return 0; } - block = sb->sv_firstinodezone + ((ino-1) >> sb->sv_inodes_per_block_bits); - if (!(bh = sv_bread(sb,inode->i_dev,block))) { + raw_inode = sysv_raw_inode(sb, ino, &bh); + if (!raw_inode) { printk("unable to read i-node block\n"); return 0; } - raw_inode = (struct sysv_inode *) bh->b_data + ((ino-1) & sb->sv_inodes_per_block_1); mode = inode->i_mode; if (sb->sv_kludge_symlinks) mode = to_coh_imode(mode); - raw_inode->i_mode = mode; - raw_inode->i_uid = fs_high2lowuid(inode->i_uid); - raw_inode->i_gid = fs_high2lowgid(inode->i_gid); - raw_inode->i_nlink = inode->i_nlink; - if (sb->sv_convert) { - raw_inode->i_size = to_coh_ulong(inode->i_size); - raw_inode->i_atime = to_coh_ulong(inode->i_atime); - raw_inode->i_mtime = to_coh_ulong(inode->i_mtime); - raw_inode->i_ctime = to_coh_ulong(inode->i_ctime); - } else { - raw_inode->i_size = inode->i_size; - raw_inode->i_atime = inode->i_atime; - raw_inode->i_mtime = inode->i_mtime; - raw_inode->i_ctime = inode->i_ctime; - } + raw_inode->i_mode = cpu_to_fs16(sb, mode); + raw_inode->i_uid = cpu_to_fs16(sb, fs_high2lowuid(inode->i_uid)); + raw_inode->i_gid = cpu_to_fs16(sb, fs_high2lowgid(inode->i_gid)); + raw_inode->i_nlink = cpu_to_fs16(sb, inode->i_nlink); + raw_inode->i_size = cpu_to_fs32(sb, inode->i_size); + raw_inode->i_atime = cpu_to_fs32(sb, inode->i_atime); + raw_inode->i_mtime = cpu_to_fs32(sb, inode->i_mtime); + raw_inode->i_ctime = cpu_to_fs32(sb, inode->i_ctime); if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - raw_inode->i_a.i_rdev = kdev_t_to_nr(inode->i_rdev); /* write 2 or 3 bytes ?? */ - else - if (sb->sv_convert) - for (block = 0; block < 10+1+1+1; block++) - coh_write3byte(&raw_inode->i_a.i_addb[3*block],inode->u.sysv_i.i_data[block]); - else - for (block = 0; block < 10+1+1+1; block++) - write3byte(&raw_inode->i_a.i_addb[3*block],inode->u.sysv_i.i_data[block]); + inode->u.sysv_i.i_data[0] = + cpu_to_fs32(sb, kdev_t_to_nr(inode->i_rdev)); + for (block = 0; block < 10+1+1+1; block++) + write3byte(sb, (unsigned char*)&inode->u.sysv_i.i_data[block], + &raw_inode->i_a.i_addb[3*block]); mark_buffer_dirty(bh); return bh; } @@ -1148,11 +256,9 @@ if (bh && buffer_dirty(bh)) { ll_rw_block(WRITE, 1, &bh); wait_on_buffer(bh); - if (buffer_req(bh) && !buffer_uptodate(bh)) - { - printk ("IO error syncing sysv inode [" - "%s:%08lx]\n", - kdevname(inode->i_dev), inode->i_ino); + if (buffer_req(bh) && !buffer_uptodate(bh)) { + printk ("IO error syncing sysv inode [%s:%08lx]\n", + bdevname(inode->i_dev), inode->i_ino); err = -1; } } @@ -1162,21 +268,20 @@ return err; } -/* Every kernel module contains stuff like this. */ - -static DECLARE_FSTYPE_DEV(sysv_fs_type, "sysv", sysv_read_super); - -static int __init init_sysv_fs(void) -{ - return register_filesystem(&sysv_fs_type); -} - -static void __exit exit_sysv_fs(void) +static void sysv_delete_inode(struct inode *inode) { - unregister_filesystem(&sysv_fs_type); + lock_kernel(); + inode->i_size = 0; + sysv_truncate(inode); + sysv_free_inode(inode); + unlock_kernel(); } -EXPORT_NO_SYMBOLS; - -module_init(init_sysv_fs) -module_exit(exit_sysv_fs) +struct super_operations sysv_sops = { + read_inode: sysv_read_inode, + write_inode: sysv_write_inode, + delete_inode: sysv_delete_inode, + put_super: sysv_put_super, + write_super: sysv_write_super, + statfs: sysv_statfs, +}; diff -u --recursive --new-file v2.4.5/linux/fs/sysv/itree.c linux/fs/sysv/itree.c --- v2.4.5/linux/fs/sysv/itree.c Wed Dec 31 16:00:00 1969 +++ linux/fs/sysv/itree.c Mon Jul 2 14:03:04 2001 @@ -0,0 +1,440 @@ +/* + * linux/fs/sysv/itree.c + * + * Handling of indirect blocks' trees. + * AV, Sep--Dec 2000 + */ + +#include +#include +#include +#include + +enum {DIRECT = 10, DEPTH = 4}; /* Have triple indirect */ + +static inline void dirty_indirect(struct buffer_head *bh, struct inode *inode) +{ + mark_buffer_dirty_inode(bh, inode); + if (IS_SYNC(inode)) { + ll_rw_block (WRITE, 1, &bh); + wait_on_buffer (bh); + } +} + +static int block_to_path(struct inode *inode, long block, int offsets[DEPTH]) +{ + struct super_block *sb = inode->i_sb; + int ptrs_bits = sb->sv_ind_per_block_bits; + unsigned long indirect_blocks = sb->sv_ind_per_block, + double_blocks = sb->sv_ind_per_block_2; + int n = 0; + + if (block < 0) { + printk("sysv_block_map: block < 0\n"); + } else if (block < DIRECT) { + offsets[n++] = block; + } else if ( (block -= DIRECT) < indirect_blocks) { + offsets[n++] = DIRECT; + offsets[n++] = block; + } else if ((block -= indirect_blocks) < double_blocks) { + offsets[n++] = DIRECT+1; + offsets[n++] = block >> ptrs_bits; + offsets[n++] = block & (indirect_blocks - 1); + } else if (((block -= double_blocks) >> (ptrs_bits * 2)) < indirect_blocks) { + offsets[n++] = DIRECT+2; + offsets[n++] = block >> (ptrs_bits * 2); + offsets[n++] = (block >> ptrs_bits) & (indirect_blocks - 1); + offsets[n++] = block & (indirect_blocks - 1); + } else { + /* nothing */; + } + return n; +} + +static inline int block_to_cpu(struct super_block *sb, u32 nr) +{ + return sb->sv_block_base + fs32_to_cpu(sb, nr); +} + +typedef struct { + u32 *p; + u32 key; + struct buffer_head *bh; +} Indirect; + +static inline void add_chain(Indirect *p, struct buffer_head *bh, u32 *v) +{ + p->key = *(p->p = v); + p->bh = bh; +} + +static inline int verify_chain(Indirect *from, Indirect *to) +{ + while (from <= to && from->key == *from->p) + from++; + return (from > to); +} + +static inline u32 *block_end(struct buffer_head *bh) +{ + return (u32*)((char*)bh->b_data + bh->b_size); +} + +static Indirect *get_branch(struct inode *inode, + int depth, + int offsets[], + Indirect chain[], + int *err) +{ + kdev_t dev = inode->i_dev; + int size = inode->i_sb->s_blocksize; + Indirect *p = chain; + struct buffer_head *bh; + + *err = 0; + add_chain (chain, NULL, inode->u.sysv_i.i_data + *offsets); + if (!p->key) + goto no_block; + while (--depth) { + int block = block_to_cpu(inode->i_sb, p->key); + bh = bread(dev, block, size); + if (!bh) + goto failure; + if (!verify_chain(chain, p)) + goto changed; + add_chain(++p, bh, (u32*)bh->b_data + *++offsets); + if (!p->key) + goto no_block; + } + return NULL; + +changed: + *err = -EAGAIN; + goto no_block; +failure: + *err = -EIO; +no_block: + return p; +} + +static int alloc_branch(struct inode *inode, + int num, + int *offsets, + Indirect *branch) +{ + int blocksize = inode->i_sb->s_blocksize; + int n = 0; + int i; + + branch[0].key = sysv_new_block(inode->i_sb); + if (branch[0].key) for (n = 1; n < num; n++) { + struct buffer_head *bh; + int parent; + /* Allocate the next block */ + branch[n].key = sysv_new_block(inode->i_sb); + if (!branch[n].key) + break; + /* + * Get buffer_head for parent block, zero it out and set + * the pointer to new one, then send parent to disk. + */ + parent = block_to_cpu(inode->i_sb, branch[n-1].key); + bh = getblk(inode->i_dev, parent, blocksize); + lock_buffer(bh); + memset(bh->b_data, 0, blocksize); + branch[n].bh = bh; + branch[n].p = (u32*) bh->b_data + offsets[n]; + *branch[n].p = branch[n].key; + mark_buffer_uptodate(bh, 1); + unlock_buffer(bh); + dirty_indirect(bh, inode); + } + if (n == num) + return 0; + + /* Allocation failed, free what we already allocated */ + for (i = 1; i < n; i++) + bforget(branch[i].bh); + for (i = 0; i < n; i++) + sysv_free_block(inode->i_sb, branch[i].key); + return -ENOSPC; +} + +static inline int splice_branch(struct inode *inode, + Indirect chain[], + Indirect *where, + int num) +{ + int i; + /* Verify that place we are splicing to is still there and vacant */ + + if (!verify_chain(chain, where-1) || *where->p) + goto changed; + + *where->p = where->key; + inode->i_ctime = CURRENT_TIME; + + /* had we spliced it onto indirect block? */ + if (where->bh) + dirty_indirect(where->bh, inode); + + if (IS_SYNC(inode)) + sysv_sync_inode(inode); + else + mark_inode_dirty(inode); + return 0; + +changed: + for (i = 1; i < num; i++) + bforget(where[i].bh); + for (i = 0; i < num; i++) + sysv_free_block(inode->i_sb, where[i].key); + return -EAGAIN; +} + +static int get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create) +{ + int err = -EIO; + int offsets[DEPTH]; + Indirect chain[DEPTH]; + struct super_block *sb = inode->i_sb; + Indirect *partial; + int left; + int depth = block_to_path(inode, iblock, offsets); + + if (depth == 0) + goto out; + + lock_kernel(); +reread: + partial = get_branch(inode, depth, offsets, chain, &err); + + /* Simplest case - block found, no allocation needed */ + if (!partial) { +got_it: + bh_result->b_dev = sb->s_dev; + bh_result->b_blocknr = block_to_cpu(sb, chain[depth-1].key); + bh_result->b_state |= (1UL << BH_Mapped); + /* Clean up and exit */ + partial = chain+depth-1; /* the whole chain */ + goto cleanup; + } + + /* Next simple case - plain lookup or failed read of indirect block */ + if (!create || err == -EIO) { +cleanup: + while (partial > chain) { + brelse(partial->bh); + partial--; + } + unlock_kernel(); +out: + return err; + } + + /* + * Indirect block might be removed by truncate while we were + * reading it. Handling of that case (forget what we've got and + * reread) is taken out of the main path. + */ + if (err == -EAGAIN) + goto changed; + + left = (chain + depth) - partial; + err = alloc_branch(inode, left, offsets+(partial-chain), partial); + if (err) + goto cleanup; + + if (splice_branch(inode, chain, partial, left) < 0) + goto changed; + + bh_result->b_state |= (1UL << BH_New); + goto got_it; + +changed: + while (partial > chain) { + brelse(partial->bh); + partial--; + } + goto reread; +} + +static inline int all_zeroes(u32 *p, u32 *q) +{ + while (p < q) + if (*p++) + return 0; + return 1; +} + +static Indirect *find_shared(struct inode *inode, + int depth, + int offsets[], + Indirect chain[], + u32 *top) +{ + Indirect *partial, *p; + int k, err; + + *top = 0; + for (k = depth; k > 1 && !offsets[k-1]; k--) + ; + partial = get_branch(inode, k, offsets, chain, &err); + if (!partial) + partial = chain + k-1; + /* + * If the branch acquired continuation since we've looked at it - + * fine, it should all survive and (new) top doesn't belong to us. + */ + if (!partial->key && *partial->p) + goto no_top; + for (p=partial; p>chain && all_zeroes((u32*)p->bh->b_data,p->p); p--) + ; + /* + * OK, we've found the last block that must survive. The rest of our + * branch should be detached before unlocking. However, if that rest + * of branch is all ours and does not grow immediately from the inode + * it's easier to cheat and just decrement partial->p. + */ + if (p == chain + k - 1 && p > chain) { + p->p--; + } else { + *top = *p->p; + *p->p = 0; + } + + while(partial > p) { + brelse(partial->bh); + partial--; + } +no_top: + return partial; +} + +static inline void free_data(struct inode *inode, u32 *p, u32 *q) +{ + for ( ; p < q ; p++) { + u32 nr = *p; + if (nr) { + *p = 0; + sysv_free_block(inode->i_sb, nr); + mark_inode_dirty(inode); + } + } +} + +static void free_branches(struct inode *inode, u32 *p, u32 *q, int depth) +{ + struct buffer_head * bh; + struct super_block *sb = inode->i_sb; + + if (depth--) { + for ( ; p < q ; p++) { + int block; + u32 nr = *p; + if (!nr) + continue; + *p = 0; + block = block_to_cpu(sb, nr); + bh = bread(inode->i_dev, block, sb->s_blocksize); + if (!bh) + continue; + free_branches(inode, (u32*)bh->b_data, + block_end(bh), depth); + bforget(bh); + sysv_free_block(sb, nr); + mark_inode_dirty(inode); + } + } else + free_data(inode, p, q); +} + +void sysv_truncate (struct inode * inode) +{ + u32 *i_data = inode->u.sysv_i.i_data; + int offsets[DEPTH]; + Indirect chain[DEPTH]; + Indirect *partial; + int nr = 0; + int n; + long iblock; + unsigned blocksize; + + if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || + S_ISLNK(inode->i_mode))) + return; + + blocksize = inode->i_sb->s_blocksize; + iblock = (inode->i_size + blocksize-1) + >> inode->i_sb->s_blocksize_bits; + + block_truncate_page(inode->i_mapping, inode->i_size, get_block); + + n = block_to_path(inode, iblock, offsets); + if (n == 0) + return; + + if (n == 1) { + free_data(inode, i_data+offsets[0], i_data + DIRECT); + goto do_indirects; + } + + partial = find_shared(inode, n, offsets, chain, &nr); + /* Kill the top of shared branch (already detached) */ + if (nr) { + if (partial == chain) + mark_inode_dirty(inode); + else + dirty_indirect(partial->bh, inode); + free_branches(inode, &nr, &nr+1, (chain+n-1) - partial); + } + /* Clear the ends of indirect blocks on the shared branch */ + while (partial > chain) { + free_branches(inode, partial->p + 1, block_end(partial->bh), + (chain+n-1) - partial); + dirty_indirect(partial->bh, inode); + brelse (partial->bh); + partial--; + } +do_indirects: + /* Kill the remaining (whole) subtrees (== subtrees deeper than...) */ + while (n < DEPTH) { + nr = i_data[DIRECT + n - 1]; + if (nr) { + i_data[DIRECT + n - 1] = 0; + mark_inode_dirty(inode); + free_branches(inode, &nr, &nr+1, n); + } + n++; + } + inode->i_mtime = inode->i_ctime = CURRENT_TIME; + if (IS_SYNC(inode)) + sysv_sync_inode (inode); + else + mark_inode_dirty(inode); +} + +static int sysv_writepage(struct page *page) +{ + return block_write_full_page(page,get_block); +} +static int sysv_readpage(struct file *file, struct page *page) +{ + return block_read_full_page(page,get_block); +} +static int sysv_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to) +{ + return block_prepare_write(page,from,to,get_block); +} +static int sysv_bmap(struct address_space *mapping, long block) +{ + return generic_block_bmap(mapping,block,get_block); +} +struct address_space_operations sysv_aops = { + readpage: sysv_readpage, + writepage: sysv_writepage, + sync_page: block_sync_page, + prepare_write: sysv_prepare_write, + commit_write: generic_commit_write, + bmap: sysv_bmap +}; diff -u --recursive --new-file v2.4.5/linux/fs/sysv/namei.c linux/fs/sysv/namei.c --- v2.4.5/linux/fs/sysv/namei.c Tue Sep 5 14:07:30 2000 +++ linux/fs/sysv/namei.c Mon Jul 2 14:03:04 2001 @@ -12,108 +12,70 @@ * Copyright (C) 1997, 1998 Krzysztof G. Baranowski */ - -#include -#include #include #include -#include -#include -#include +#include -/* compare strings: name[0..len-1] (not zero-terminated) and - * buffer[0..] (filled with zeroes up to buffer[0..maxlen-1]) - */ -static inline int namecompare(int len, int maxlen, - const char * name, const char * buffer) +static inline void inc_count(struct inode *inode) { - if (len > maxlen) - return 0; - if (len < maxlen && buffer[len]) - return 0; - return !memcmp(name, buffer, len); + inode->i_nlink++; + mark_inode_dirty(inode); } -/* - * ok, we cannot use strncmp, as the name is not in our data space. [Now it is!] - * Thus we'll have to use sysv_match. No big problem. Match also makes - * some sanity tests. - * - * NOTE! unlike strncmp, sysv_match returns 1 for success, 0 for failure. - */ -static int sysv_match(int len, const char * name, struct sysv_dir_entry * de) +static inline void dec_count(struct inode *inode) { - if (!de->inode || len > SYSV_NAMELEN) - return 0; - /* "" means "." ---> so paths like "/usr/lib//libc.a" work */ - if (!len && (de->name[0]=='.') && (de->name[1]=='\0')) - return 1; - return namecompare(len, SYSV_NAMELEN, name, de->name); + inode->i_nlink--; + mark_inode_dirty(inode); } -/* - * sysv_find_entry() - * - * finds an entry in the specified directory with the wanted name. It - * returns the cache buffer in which the entry was found, and the entry - * itself (as a parameter - res_dir). It does NOT read the inode of the - * entry - you'll have to do that yourself if you want to. - */ -static struct buffer_head * sysv_find_entry(struct inode * dir, - const char * name, int namelen, struct sysv_dir_entry ** res_dir) +static int add_nondir(struct dentry *dentry, struct inode *inode) { - struct super_block * sb; - unsigned long pos, block, offset; /* pos = block * block_size + offset */ - struct buffer_head * bh; - - *res_dir = NULL; - sb = dir->i_sb; - if (namelen > SYSV_NAMELEN) { - if (sb->sv_truncate) - namelen = SYSV_NAMELEN; - else - return NULL; - } - bh = NULL; - pos = block = offset = 0; - while (pos < dir->i_size) { - if (!bh) { - bh = sysv_file_bread(dir, block, 0); - if (!bh) { - /* offset = 0; */ block++; - pos += sb->sv_block_size; - continue; - } - } - if (sysv_match(namelen, name, - *res_dir = (struct sysv_dir_entry *) (bh->b_data + offset) )) - return bh; - pos += SYSV_DIRSIZE; - offset += SYSV_DIRSIZE; - if (offset < sb->sv_block_size) - continue; - brelse(bh); - bh = NULL; - offset = 0; block++; + int err = sysv_add_link(dentry, inode); + if (!err) { + d_instantiate(dentry, inode); + return 0; } - brelse(bh); - *res_dir = NULL; - return NULL; + dec_count(inode); + iput(inode); + return err; } +static int sysv_hash(struct dentry *dentry, struct qstr *qstr) +{ + unsigned long hash; + int i; + const unsigned char *name; + + i = SYSV_NAMELEN; + if (i >= qstr->len) + return 0; + /* Truncate the name in place, avoids having to define a compare + function. */ + qstr->len = i; + name = qstr->name; + hash = init_name_hash(); + while (i--) + hash = partial_name_hash(*name++, hash); + qstr->hash = end_name_hash(hash); + return 0; +} + +struct dentry_operations sysv_dentry_operations = { + d_hash: sysv_hash, +}; + static struct dentry *sysv_lookup(struct inode * dir, struct dentry * dentry) { struct inode * inode = NULL; - struct sysv_dir_entry * de; - struct buffer_head * bh; + ino_t ino; - bh = sysv_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de); + dentry->d_op = dir->i_sb->s_root->d_op; + if (dentry->d_name.len > SYSV_NAMELEN) + return ERR_PTR(-ENAMETOOLONG); + ino = sysv_inode_by_name(dentry); - if (bh) { - int ino = de->inode; - brelse(bh); + if (ino) { inode = iget(dir->i_sb, ino); - if (!inode) return ERR_PTR(-EACCES); } @@ -121,399 +83,146 @@ return NULL; } -/* - * sysv_add_entry() - * - * adds a file entry to the specified directory, returning a possible - * error value if it fails. - * - * NOTE!! The inode part of 'de' is left at 0 - which means you - * may not sleep between calling this and putting something into - * the entry, as someone else might have used it while you slept. - */ -static int sysv_add_entry(struct inode * dir, - const char * name, int namelen, - struct buffer_head ** res_buf, - struct sysv_dir_entry ** res_dir) +static int sysv_mknod(struct inode * dir, struct dentry * dentry, int mode, int rdev) { - struct super_block * sb; - int i; - unsigned long pos, block, offset; /* pos = block * block_size + offset */ - struct buffer_head * bh; - struct sysv_dir_entry * de; - - *res_buf = NULL; - *res_dir = NULL; - sb = dir->i_sb; - if (namelen > SYSV_NAMELEN) { - if (sb->sv_truncate) - namelen = SYSV_NAMELEN; - else - return -ENAMETOOLONG; - } - if (!namelen) - return -ENOENT; - bh = NULL; - pos = block = offset = 0; - while (1) { - if (!bh) { - bh = sysv_file_bread(dir, block, 1); - if (!bh) - return -ENOSPC; - } - de = (struct sysv_dir_entry *) (bh->b_data + offset); - pos += SYSV_DIRSIZE; - offset += SYSV_DIRSIZE; - if (pos > dir->i_size) { - de->inode = 0; - dir->i_size = pos; - mark_inode_dirty(dir); - } - if (de->inode) { - if (namecompare(namelen, SYSV_NAMELEN, name, de->name)) { - brelse(bh); - return -EEXIST; - } - } else { - dir->i_mtime = dir->i_ctime = CURRENT_TIME; - mark_inode_dirty(dir); - for (i = 0; i < SYSV_NAMELEN ; i++) - de->name[i] = (i < namelen) ? name[i] : 0; - mark_buffer_dirty(bh); - *res_dir = de; - break; - } - if (offset < sb->sv_block_size) - continue; - brelse(bh); - bh = NULL; - offset = 0; block++; - } - *res_buf = bh; - return 0; + struct inode * inode = sysv_new_inode(dir, mode); + if (!inode) + return -ENOSPC; + sysv_set_inode(inode, rdev); + mark_inode_dirty(inode); + return add_nondir(dentry, inode); } static int sysv_create(struct inode * dir, struct dentry * dentry, int mode) { - int error; - struct inode * inode; - struct buffer_head * bh; - struct sysv_dir_entry * de; - - inode = sysv_new_inode(dir); - if (!inode) - return -ENOSPC; - inode->i_op = &sysv_file_inode_operations; - inode->i_fop = &sysv_file_operations; - inode->i_mapping->a_ops = &sysv_aops; - inode->i_mode = mode; - mark_inode_dirty(inode); - error = sysv_add_entry(dir, dentry->d_name.name, - dentry->d_name.len, &bh, &de); - if (error) { - inode->i_nlink--; - mark_inode_dirty(inode); - iput(inode); - return error; - } - de->inode = inode->i_ino; - mark_buffer_dirty(bh); - brelse(bh); - d_instantiate(dentry, inode); - return 0; + return sysv_mknod(dir, dentry, mode, 0); } -static int sysv_mknod(struct inode * dir, struct dentry * dentry, int mode, int rdev) +static int sysv_symlink(struct inode * dir, struct dentry * dentry, + const char * symname) { - int error; + int err = -ENAMETOOLONG; + int l = strlen(symname)+1; struct inode * inode; - struct buffer_head * bh; - struct sysv_dir_entry * de; - bh = sysv_find_entry(dir, dentry->d_name.name, - dentry->d_name.len, &de); - if (bh) { - brelse(bh); - return -EEXIST; - } - inode = sysv_new_inode(dir); + if (l > dir->i_sb->s_blocksize) + goto out; + + err = -ENOSPC; + inode = sysv_new_inode(dir, S_IFLNK|0777); if (!inode) - return -ENOSPC; - inode->i_uid = current->fsuid; - init_special_inode(inode, mode, rdev); - mark_inode_dirty(inode); - error = sysv_add_entry(dir, dentry->d_name.name, - dentry->d_name.len, &bh, &de); - if (error) { - inode->i_nlink--; - mark_inode_dirty(inode); - iput(inode); - return error; - } - de->inode = inode->i_ino; - mark_buffer_dirty(bh); - brelse(bh); - d_instantiate(dentry, inode); - return 0; + goto out; + + sysv_set_inode(inode, 0); + err = block_symlink(inode, symname, l); + if (err) + goto out_fail; + + err = add_nondir(dentry, inode); +out: + return err; + +out_fail: + dec_count(inode); + iput(inode); + goto out; } -static int sysv_mkdir(struct inode * dir, struct dentry *dentry, int mode) +static int sysv_link(struct dentry * old_dentry, struct inode * dir, + struct dentry * dentry) { - int error; - struct inode * inode; - struct buffer_head * bh, *dir_block; - struct sysv_dir_entry * de; + struct inode *inode = old_dentry->d_inode; - bh = sysv_find_entry(dir, dentry->d_name.name, - dentry->d_name.len, &de); - if (bh) { - brelse(bh); - return -EEXIST; - } - if (dir->i_nlink >= dir->i_sb->sv_link_max) + if (S_ISDIR(inode->i_mode)) + return -EPERM; + + if (inode->i_nlink >= inode->i_sb->sv_link_max) return -EMLINK; - inode = sysv_new_inode(dir); - if (!inode) - return -ENOSPC; - inode->i_op = &sysv_dir_inode_operations; - inode->i_fop = &sysv_dir_operations; - inode->i_size = 2 * SYSV_DIRSIZE; - dir_block = sysv_file_bread(inode,0,1); - if (!dir_block) { - inode->i_nlink--; - mark_inode_dirty(inode); - iput(inode); - return -ENOSPC; - } - de = (struct sysv_dir_entry *) (dir_block->b_data + 0*SYSV_DIRSIZE); - de->inode = inode->i_ino; - strcpy(de->name,"."); /* rest of de->name is zero, see sysv_new_block */ - de = (struct sysv_dir_entry *) (dir_block->b_data + 1*SYSV_DIRSIZE); - de->inode = dir->i_ino; - strcpy(de->name,".."); /* rest of de->name is zero, see sysv_new_block */ - inode->i_nlink = 2; - mark_buffer_dirty(dir_block); - brelse(dir_block); - inode->i_mode = S_IFDIR | mode; - if (dir->i_mode & S_ISGID) - inode->i_mode |= S_ISGID; - mark_inode_dirty(inode); - error = sysv_add_entry(dir, dentry->d_name.name, - dentry->d_name.len, &bh, &de); - if (error) { - inode->i_nlink=0; - iput(inode); - return error; - } - de->inode = inode->i_ino; - mark_buffer_dirty(bh); - dir->i_nlink++; - mark_inode_dirty(dir); - brelse(bh); - d_instantiate(dentry, inode); - return 0; -} -/* - * routine to check that the specified directory is empty (for rmdir) - */ -static int empty_dir(struct inode * inode) -{ - struct super_block * sb; - unsigned long pos, block, offset; /* pos = block * block_size + offset */ - struct buffer_head * bh; - struct sysv_dir_entry * de; + inode->i_ctime = CURRENT_TIME; + inc_count(inode); + atomic_inc(&inode->i_count); - block = 0; - bh = NULL; - pos = offset = 2*SYSV_DIRSIZE; - if ((unsigned long)(inode->i_size) % SYSV_DIRSIZE) - goto bad_dir; - if (inode->i_size < pos) - goto bad_dir; - bh = sysv_file_bread(inode, 0, 0); - if (!bh) - goto bad_dir; - de = (struct sysv_dir_entry *) (bh->b_data + 0*SYSV_DIRSIZE); - if (!de->inode || strcmp(de->name,".")) - goto bad_dir; - de = (struct sysv_dir_entry *) (bh->b_data + 1*SYSV_DIRSIZE); - if (!de->inode || strcmp(de->name,"..")) - goto bad_dir; - sb = inode->i_sb; - while (pos < inode->i_size) { - if (!bh) { - bh = sysv_file_bread(inode, block, 0); - if (!bh) { - /* offset = 0; */ block++; - pos += sb->sv_block_size; - continue; - } - } - de = (struct sysv_dir_entry *) (bh->b_data + offset); - pos += SYSV_DIRSIZE; - offset += SYSV_DIRSIZE; - if (de->inode) { - brelse(bh); - return 0; - } - if (offset < sb->sv_block_size) - continue; - brelse(bh); - bh = NULL; - offset = 0; block++; - } - brelse(bh); - return 1; -bad_dir: - brelse(bh); - printk("Bad directory on device %s\n", - kdevname(inode->i_dev)); - return 1; + return add_nondir(dentry, inode); } -static int sysv_rmdir(struct inode * dir, struct dentry * dentry) +static int sysv_mkdir(struct inode * dir, struct dentry *dentry, int mode) { - int retval; struct inode * inode; - struct buffer_head * bh; - struct sysv_dir_entry * de; + int err = -EMLINK; - inode = dentry->d_inode; - bh = sysv_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de); - retval = -ENOENT; - if (!bh || de->inode != inode->i_ino) - goto end_rmdir; - - if (!empty_dir(inode)) { - retval = -ENOTEMPTY; - goto end_rmdir; - } - if (inode->i_nlink != 2) - printk("empty directory has nlink!=2 (%d)\n", inode->i_nlink); - de->inode = 0; - mark_buffer_dirty(bh); - inode->i_nlink=0; - dir->i_nlink--; - inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; - mark_inode_dirty(inode); - mark_inode_dirty(dir); - retval = 0; -end_rmdir: - brelse(bh); - return retval; -} + if (dir->i_nlink >= dir->i_sb->sv_link_max) + goto out; -static int sysv_unlink(struct inode * dir, struct dentry * dentry) -{ - int retval; - struct inode * inode; - struct buffer_head * bh; - struct sysv_dir_entry * de; + inc_count(dir); - retval = -ENOENT; - inode = dentry->d_inode; - bh = sysv_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de); - if (!bh || de->inode != inode->i_ino) - goto end_unlink; - if (!inode->i_nlink) { - printk("Deleting nonexistent file (%s:%lu), %d\n", - kdevname(inode->i_dev), inode->i_ino, inode->i_nlink); - inode->i_nlink=1; - } - de->inode = 0; - mark_buffer_dirty(bh); - dir->i_ctime = dir->i_mtime = CURRENT_TIME; - mark_inode_dirty(dir); - inode->i_nlink--; - inode->i_ctime = dir->i_ctime; - mark_inode_dirty(inode); - retval = 0; -end_unlink: - brelse(bh); - return retval; -} + if (dir->i_mode & S_ISGID) + mode |= S_ISGID; -static int sysv_symlink(struct inode * dir, struct dentry * dentry, - const char * symname) -{ - struct inode * inode; - struct sysv_dir_entry * de; - struct buffer_head * bh; - int err; - int l; - - err = -ENAMETOOLONG; - l = strlen(symname)+1; - if (l > dir->i_sb->sv_block_size_1) - goto out; err = -ENOSPC; - if (!(inode = sysv_new_inode(dir))) - goto out; + inode = sysv_new_inode(dir, S_IFDIR|mode); + if (!inode) + goto out_dir; + sysv_set_inode(inode, 0); - inode->i_mode = S_IFLNK | 0777; - inode->i_op = &sysv_symlink_inode_operations; - inode->i_mapping->a_ops = &sysv_aops; - err = block_symlink(inode, symname, l); + inc_count(inode); + + err = sysv_make_empty(inode, dir); if (err) - goto out_no_entry; - mark_inode_dirty(inode); - err = sysv_add_entry(dir, dentry->d_name.name, - dentry->d_name.len, &bh, &de); + goto out_fail; + + err = sysv_add_link(dentry, inode); if (err) - goto out_no_entry; - de->inode = inode->i_ino; - mark_buffer_dirty(bh); - brelse(bh); + goto out_fail; + d_instantiate(dentry, inode); out: return err; -out_no_entry: - inode->i_nlink--; - mark_inode_dirty(inode); + +out_fail: + dec_count(inode); + dec_count(inode); iput(inode); +out_dir: + dec_count(dir); goto out; } -static int sysv_link(struct dentry * old_dentry, struct inode * dir, - struct dentry * dentry) +static int sysv_unlink(struct inode * dir, struct dentry * dentry) { - struct inode *oldinode = old_dentry->d_inode; - int error; + struct inode * inode = dentry->d_inode; + struct page * page; struct sysv_dir_entry * de; - struct buffer_head * bh; + int err = -ENOENT; - if (S_ISDIR(oldinode->i_mode)) { - return -EPERM; - } - if (oldinode->i_nlink >= oldinode->i_sb->sv_link_max) { - return -EMLINK; - } - bh = sysv_find_entry(dir, dentry->d_name.name, - dentry->d_name.len, &de); - if (bh) { - brelse(bh); - return -EEXIST; - } - error = sysv_add_entry(dir, dentry->d_name.name, - dentry->d_name.len, &bh, &de); - if (error) { - brelse(bh); - return error; - } - de->inode = oldinode->i_ino; - mark_buffer_dirty(bh); - brelse(bh); - oldinode->i_nlink++; - oldinode->i_ctime = CURRENT_TIME; - mark_inode_dirty(oldinode); - atomic_inc(&oldinode->i_count); - d_instantiate(dentry, oldinode); - return 0; + de = sysv_find_entry(dentry, &page); + if (!de) + goto out; + + err = sysv_delete_entry (de, page); + if (err) + goto out; + + inode->i_ctime = dir->i_ctime; + dec_count(inode); +out: + return err; } -#define PARENT_INO(buffer) \ -(((struct sysv_dir_entry *) ((buffer) + 1*SYSV_DIRSIZE))->inode) +static int sysv_rmdir(struct inode * dir, struct dentry * dentry) +{ + struct inode *inode = dentry->d_inode; + int err = -ENOTEMPTY; + + if (sysv_empty_dir(inode)) { + err = sysv_unlink(dir, dentry); + if (!err) { + dec_count(inode); + dec_count(dir); + } + } + return err; +} /* * Anybody can rename anything with this: the permission checks are left to the @@ -522,83 +231,78 @@ static int sysv_rename(struct inode * old_dir, struct dentry * old_dentry, struct inode * new_dir, struct dentry * new_dentry) { - struct inode * old_inode, * new_inode; - struct buffer_head * old_bh, * new_bh, * dir_bh; - struct sysv_dir_entry * old_de, * new_de; - int retval; - - old_inode = old_dentry->d_inode; - new_inode = new_dentry->d_inode; - new_bh = dir_bh = NULL; - old_bh = sysv_find_entry(old_dir, old_dentry->d_name.name, - old_dentry->d_name.len, &old_de); - retval = -ENOENT; - if (!old_bh || old_de->inode != old_inode->i_ino) - goto end_rename; - retval = -EPERM; - new_bh = sysv_find_entry(new_dir, new_dentry->d_name.name, - new_dentry->d_name.len, &new_de); - if (new_bh) { - if (!new_inode) { - brelse(new_bh); - new_bh = NULL; - } - } + struct inode * old_inode = old_dentry->d_inode; + struct inode * new_inode = new_dentry->d_inode; + struct page * dir_page = NULL; + struct sysv_dir_entry * dir_de = NULL; + struct page * old_page; + struct sysv_dir_entry * old_de; + int err = -ENOENT; + + old_de = sysv_find_entry(old_dentry, &old_page); + if (!old_de) + goto out; + if (S_ISDIR(old_inode->i_mode)) { - if (new_inode) { - retval = -ENOTEMPTY; - if (!empty_dir(new_inode)) - goto end_rename; - } - retval = -EIO; - dir_bh = sysv_file_bread(old_inode, 0, 0); - if (!dir_bh) - goto end_rename; - if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino) - goto end_rename; - retval = -EMLINK; - if (!new_inode && new_dir != old_dir && - new_dir->i_nlink >= new_dir->i_sb->sv_link_max) - goto end_rename; + err = -EIO; + dir_de = sysv_dotdot(old_inode, &dir_page); + if (!dir_de) + goto out_old; } - if (!new_bh) { - retval = sysv_add_entry(new_dir, new_dentry->d_name.name, - new_dentry->d_name.len, &new_bh, &new_de); - if (retval) - goto end_rename; - } - new_de->inode = old_inode->i_ino; - old_de->inode = 0; - old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; - mark_inode_dirty(old_dir); - new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME; - mark_inode_dirty(new_dir); + if (new_inode) { - new_inode->i_nlink--; + struct page * new_page; + struct sysv_dir_entry * new_de; + + err = -ENOTEMPTY; + if (dir_de && !sysv_empty_dir(new_inode)) + goto out_dir; + + err = -ENOENT; + new_de = sysv_find_entry(new_dentry, &new_page); + if (!new_de) + goto out_dir; + inc_count(old_inode); + sysv_set_link(new_de, new_page, old_inode); new_inode->i_ctime = CURRENT_TIME; - mark_inode_dirty(new_inode); - } - mark_buffer_dirty(old_bh); - mark_buffer_dirty(new_bh); - if (dir_bh) { - PARENT_INO(dir_bh->b_data) = new_dir->i_ino; - mark_buffer_dirty(dir_bh); - old_dir->i_nlink--; - mark_inode_dirty(old_dir); - if (new_inode) { + if (dir_de) new_inode->i_nlink--; - mark_inode_dirty(new_inode); - } else { - new_dir->i_nlink++; - mark_inode_dirty(new_dir); + dec_count(new_inode); + } else { + if (dir_de) { + err = -EMLINK; + if (new_dir->i_nlink >= new_dir->i_sb->sv_link_max) + goto out_dir; + } + inc_count(old_inode); + err = sysv_add_link(new_dentry, old_inode); + if (err) { + dec_count(old_inode); + goto out_dir; } + if (dir_de) + inc_count(new_dir); + } + + sysv_delete_entry(old_de, old_page); + dec_count(old_inode); + + if (dir_de) { + sysv_set_link(dir_de, dir_page, new_dir); + dec_count(old_dir); } - retval = 0; -end_rename: - brelse(dir_bh); - brelse(old_bh); - brelse(new_bh); - return retval; + return 0; + +out_dir: + if (dir_de) { + kunmap(dir_page); + page_cache_release(dir_page); + } +out_old: + kunmap(old_page); + page_cache_release(old_page); +out: + return err; } /* diff -u --recursive --new-file v2.4.5/linux/fs/sysv/super.c linux/fs/sysv/super.c --- v2.4.5/linux/fs/sysv/super.c Wed Dec 31 16:00:00 1969 +++ linux/fs/sysv/super.c Mon Jul 2 14:03:04 2001 @@ -0,0 +1,467 @@ +/* + * linux/fs/sysv/inode.c + * + * minix/inode.c + * Copyright (C) 1991, 1992 Linus Torvalds + * + * xenix/inode.c + * Copyright (C) 1992 Doug Evans + * + * coh/inode.c + * Copyright (C) 1993 Pascal Haible, Bruno Haible + * + * sysv/inode.c + * Copyright (C) 1993 Paul B. Monday + * + * sysv/inode.c + * Copyright (C) 1993 Bruno Haible + * Copyright (C) 1997, 1998 Krzysztof G. Baranowski + * + * This file contains code for read/parsing the superblock. + */ + +#include + +#include +#include +#include + +/* The following functions try to recognize specific filesystems. + * We recognize: + * - Xenix FS by its magic number. + * - SystemV FS by its magic number. + * - Coherent FS by its funny fname/fpack field. + * We discriminate among SystemV4 and SystemV2 FS by the assumption that + * the time stamp is not < 01-01-1980. + */ + +enum { + JAN_1_1980 = (10*365 + 2) * 24 * 60 * 60 +}; + +static void detected_xenix(struct super_block *sb) +{ + struct buffer_head *bh1 = sb->sv_bh1; + struct buffer_head *bh2 = sb->sv_bh2; + struct xenix_super_block * sbd1; + struct xenix_super_block * sbd2; + + if (bh1 != bh2) + sbd1 = sbd2 = (struct xenix_super_block *) bh1->b_data; + else { + /* block size = 512, so bh1 != bh2 */ + sbd1 = (struct xenix_super_block *) bh1->b_data; + sbd2 = (struct xenix_super_block *) (bh2->b_data - 512); + } + + sb->sv_link_max = XENIX_LINK_MAX; + sb->sv_fic_size = XENIX_NICINOD; + sb->sv_flc_size = XENIX_NICFREE; + sb->sv_sbd1 = (char *) sbd1; + sb->sv_sbd2 = (char *) sbd2; + sb->sv_sb_fic_count = &sbd1->s_ninode; + sb->sv_sb_fic_inodes = &sbd1->s_inode[0]; + sb->sv_sb_total_free_inodes = &sbd2->s_tinode; + sb->sv_bcache_count = &sbd1->s_nfree; + sb->sv_bcache = &sbd1->s_free[0]; + sb->sv_free_blocks = &sbd2->s_tfree; + sb->sv_sb_time = &sbd2->s_time; + sb->sv_firstdatazone = fs16_to_cpu(sb, sbd1->s_isize); + sb->sv_nzones = fs32_to_cpu(sb, sbd1->s_fsize); +} + +static void detected_sysv4(struct super_block *sb) +{ + struct sysv4_super_block * sbd; + struct buffer_head *bh1 = sb->sv_bh1; + struct buffer_head *bh2 = sb->sv_bh2; + + if (bh1 == bh2) + sbd = (struct sysv4_super_block *) (bh1->b_data + BLOCK_SIZE/2); + else + sbd = (struct sysv4_super_block *) bh2->b_data; + + sb->sv_link_max = SYSV_LINK_MAX; + sb->sv_fic_size = SYSV_NICINOD; + sb->sv_flc_size = SYSV_NICFREE; + sb->sv_sbd1 = (char *) sbd; + sb->sv_sbd2 = (char *) sbd; + sb->sv_sb_fic_count = &sbd->s_ninode; + sb->sv_sb_fic_inodes = &sbd->s_inode[0]; + sb->sv_sb_total_free_inodes = &sbd->s_tinode; + sb->sv_bcache_count = &sbd->s_nfree; + sb->sv_bcache = &sbd->s_free[0]; + sb->sv_free_blocks = &sbd->s_tfree; + sb->sv_sb_time = &sbd->s_time; + sb->sv_sb_state = &sbd->s_state; + sb->sv_firstdatazone = fs16_to_cpu(sb, sbd->s_isize); + sb->sv_nzones = fs32_to_cpu(sb, sbd->s_fsize); +} + +static void detected_sysv2(struct super_block *sb) +{ + struct sysv2_super_block * sbd; + struct buffer_head *bh1 = sb->sv_bh1; + struct buffer_head *bh2 = sb->sv_bh2; + + if (bh1 == bh2) + sbd = (struct sysv2_super_block *) (bh1->b_data + BLOCK_SIZE/2); + else + sbd = (struct sysv2_super_block *) bh2->b_data; + + sb->sv_link_max = SYSV_LINK_MAX; + sb->sv_fic_size = SYSV_NICINOD; + sb->sv_flc_size = SYSV_NICFREE; + sb->sv_sbd1 = (char *) sbd; + sb->sv_sbd2 = (char *) sbd; + sb->sv_sb_fic_count = &sbd->s_ninode; + sb->sv_sb_fic_inodes = &sbd->s_inode[0]; + sb->sv_sb_total_free_inodes = &sbd->s_tinode; + sb->sv_bcache_count = &sbd->s_nfree; + sb->sv_bcache = &sbd->s_free[0]; + sb->sv_free_blocks = &sbd->s_tfree; + sb->sv_sb_time = &sbd->s_time; + sb->sv_sb_state = &sbd->s_state; + sb->sv_firstdatazone = fs16_to_cpu(sb, sbd->s_isize); + sb->sv_nzones = fs32_to_cpu(sb, sbd->s_fsize); +} + +static void detected_coherent(struct super_block *sb) +{ + struct coh_super_block * sbd; + struct buffer_head *bh1 = sb->sv_bh1; + + sbd = (struct coh_super_block *) bh1->b_data; + + sb->sv_link_max = COH_LINK_MAX; + sb->sv_fic_size = COH_NICINOD; + sb->sv_flc_size = COH_NICFREE; + sb->sv_sbd1 = (char *) sbd; + sb->sv_sbd2 = (char *) sbd; + sb->sv_sb_fic_count = &sbd->s_ninode; + sb->sv_sb_fic_inodes = &sbd->s_inode[0]; + sb->sv_sb_total_free_inodes = &sbd->s_tinode; + sb->sv_bcache_count = &sbd->s_nfree; + sb->sv_bcache = &sbd->s_free[0]; + sb->sv_free_blocks = &sbd->s_tfree; + sb->sv_sb_time = &sbd->s_time; + sb->sv_firstdatazone = fs16_to_cpu(sb, sbd->s_isize); + sb->sv_nzones = fs32_to_cpu(sb, sbd->s_fsize); +} + +static void detected_v7(struct super_block *sb) +{ + struct buffer_head *bh2 = sb->sv_bh2; + struct v7_super_block *sbd = (struct v7_super_block *)bh2->b_data; + + sb->sv_link_max = V7_LINK_MAX; + sb->sv_fic_size = V7_NICINOD; + sb->sv_flc_size = V7_NICFREE; + sb->sv_sbd1 = (char *)sbd; + sb->sv_sbd2 = (char *)sbd; + sb->sv_sb_fic_count = &sbd->s_ninode; + sb->sv_sb_fic_inodes = &sbd->s_inode[0]; + sb->sv_sb_total_free_inodes = &sbd->s_tinode; + sb->sv_bcache_count = &sbd->s_nfree; + sb->sv_bcache = &sbd->s_free[0]; + sb->sv_free_blocks = &sbd->s_tfree; + sb->sv_sb_time = &sbd->s_time; + sb->sv_firstdatazone = fs16_to_cpu(sb, sbd->s_isize); + sb->sv_nzones = fs32_to_cpu(sb, sbd->s_fsize); +} + +static int detect_xenix (struct super_block *sb, struct buffer_head *bh) +{ + struct xenix_super_block * sbd = (struct xenix_super_block *)bh->b_data; + if (sbd->s_magic == cpu_to_le32(0x2b5544)) + sb->sv_bytesex = BYTESEX_LE; + else if (sbd->s_magic == cpu_to_be32(0x2b5544)) + sb->sv_bytesex = BYTESEX_BE; + else + return 0; + if (sbd->s_type > 2 || sbd->s_type < 1) + return 0; + sb->sv_type = FSTYPE_XENIX; + return sbd->s_type; +} + +static int detect_sysv (struct super_block *sb, struct buffer_head *bh) +{ + /* All relevant fields are at the same offsets in R2 and R4 */ + struct sysv4_super_block * sbd; + + sbd = (struct sysv4_super_block *) (bh->b_data + BLOCK_SIZE/2); + if (sbd->s_magic == cpu_to_le32(0xfd187e20)) + sb->sv_bytesex = BYTESEX_LE; + else if (sbd->s_magic == cpu_to_be32(0xfd187e20)) + sb->sv_bytesex = BYTESEX_BE; + else + return 0; + if (sbd->s_time < JAN_1_1980) { + /* this is likely to happen on SystemV2 FS */ + if (sbd->s_type > 3 || sbd->s_type < 1) + return 0; + sb->sv_type = FSTYPE_SYSV2; + return sbd->s_type; + } + if ((sbd->s_type > 3 || sbd->s_type < 1) && + (sbd->s_type > 0x30 || sbd->s_type < 0x10)) + return 0; + + /* On Interactive Unix (ISC) Version 4.0/3.x s_type field = 0x10, + 0x20 or 0x30 indicates that symbolic links and the 14-character + filename limit is gone. Due to lack of information about this + feature read-only mode seems to be a reasonable approach... -KGB */ + + if (sbd->s_type >= 0x10) { + printk("SysV FS: can't handle long file names on %s, " + "forcing read-only mode.\n", kdevname(sb->s_dev)); + sb->s_flags |= MS_RDONLY; + } + + sb->sv_type = FSTYPE_SYSV4; + return sbd->s_type >= 0x10 ? (sbd->s_type >> 4) : sbd->s_type; +} + +static int detect_coherent (struct super_block *sb, struct buffer_head *bh) +{ + struct coh_super_block * sbd; + + sbd = (struct coh_super_block *) (bh->b_data + BLOCK_SIZE/2); + if ((memcmp(sbd->s_fname,"noname",6) && memcmp(sbd->s_fname,"xxxxx ",6)) + || (memcmp(sbd->s_fpack,"nopack",6) && memcmp(sbd->s_fpack,"xxxxx\n",6))) + return 0; + sb->sv_bytesex = BYTESEX_PDP; + sb->sv_type = FSTYPE_COH; + return 1; +} + +static int detect_sysv_odd(struct super_block *sb, struct buffer_head *bh) +{ + int size = detect_sysv(sb, bh); + + return size>2 ? 0 : size; +} + +static struct { + int block; + int (*test)(struct super_block *, struct buffer_head *); +} flavours[] = { + {1, detect_xenix}, + {0, detect_sysv}, + {0, detect_coherent}, + {9, detect_sysv_odd}, + {15,detect_sysv_odd}, + {18,detect_sysv}, +}; + +static char *flavour_names[] = { + [FSTYPE_XENIX] "Xenix", + [FSTYPE_SYSV4] "SystemV", + [FSTYPE_SYSV2] "SystemV Release 2", + [FSTYPE_COH] "Coherent", + [FSTYPE_V7] "V7", +}; + +static void (*flavour_setup[])(struct super_block *) = { + [FSTYPE_XENIX] detected_xenix, + [FSTYPE_SYSV4] detected_sysv4, + [FSTYPE_SYSV2] detected_sysv2, + [FSTYPE_COH] detected_coherent, + [FSTYPE_V7] detected_v7, +}; + +static int complete_read_super(struct super_block *sb, int silent, int size) +{ + struct inode *root_inode; + char *found = flavour_names[sb->sv_type]; + u_char n_bits = size+8; + int bsize = 1 << n_bits; + int bsize_4 = bsize >> 2; + + sb->sv_kludge_symlinks = 1; + sb->sv_firstinodezone = 2; + + flavour_setup[sb->sv_type](sb); + + sb->sv_truncate = 1; + sb->sv_ndatazones = sb->sv_nzones - sb->sv_firstdatazone; + sb->sv_inodes_per_block = bsize >> 6; + sb->sv_inodes_per_block_1 = (bsize >> 6)-1; + sb->sv_inodes_per_block_bits = n_bits-6; + sb->sv_ind_per_block = bsize_4; + sb->sv_ind_per_block_2 = bsize_4*bsize_4; + sb->sv_toobig_block = 10 + bsize_4 * (1 + bsize_4 * (1 + bsize_4)); + sb->sv_ind_per_block_bits = n_bits-2; + + sb->sv_ninodes = (sb->sv_firstdatazone - sb->sv_firstinodezone) << sb->sv_inodes_per_block_bits; + + sb->s_blocksize = bsize; + sb->s_blocksize_bits = n_bits; + if (!silent) + printk("VFS: Found a %s FS (block size = %ld) on device %s\n", + found, sb->s_blocksize, bdevname(sb->s_dev)); + + sb->s_magic = SYSV_MAGIC_BASE + sb->sv_type; + /* set up enough so that it can read an inode */ + sb->s_op = &sysv_sops; + root_inode = iget(sb,SYSV_ROOT_INO); + if (!root_inode) { + printk("SysV FS: get root inode failed\n"); + return 0; + } + sb->s_root = d_alloc_root(root_inode); + if (!sb->s_root) { + iput(root_inode); + printk("SysV FS: get root dentry failed\n"); + return 0; + } + if (sb->sv_truncate) + sb->s_root->d_op = &sysv_dentry_operations; + sb->s_flags |= MS_RDONLY; + sb->s_dirt = 1; + return 1; +} + +static struct super_block *sysv_read_super(struct super_block *sb, + void *data, int silent) +{ + struct buffer_head *bh1; + struct buffer_head *bh = NULL; + kdev_t dev = sb->s_dev; + unsigned long blocknr; + int size = 0; + int i; + + if (1024 != sizeof (struct xenix_super_block)) + panic("Xenix FS: bad super-block size"); + if ((512 != sizeof (struct sysv4_super_block)) + || (512 != sizeof (struct sysv2_super_block))) + panic("SystemV FS: bad super-block size"); + if (500 != sizeof (struct coh_super_block)) + panic("Coherent FS: bad super-block size"); + if (64 != sizeof (struct sysv_inode)) + panic("sysv fs: bad i-node size"); + set_blocksize(dev,BLOCK_SIZE); + sb->sv_block_base = 0; + + for (i = 0; i < sizeof(flavours)/sizeof(flavours[0]) && !size; i++) { + struct buffer_head *next_bh; + next_bh = bread(dev, flavours[i].block, BLOCK_SIZE); + if (!next_bh) + continue; + brelse(bh); + bh = next_bh; + + size = flavours[i].test(sb, bh); + } + + if (!size) + goto Eunknown; + + switch (size) { + case 1: + blocknr = bh->b_blocknr << 1; + brelse(bh); + set_blocksize(dev, 512); + bh1 = bread(dev, blocknr, 512); + bh = bread(dev, blocknr + 1, 512); + break; + case 2: + bh1 = bh; + break; + case 3: + blocknr = bh->b_blocknr >> 1; + brelse(bh); + set_blocksize(dev, 2048); + bh1 = bh = bread(dev, blocknr, 2048); + break; + default: + goto Ebadsize; + } + + if (bh && bh1) { + sb->sv_bh1 = bh1; + sb->sv_bh2 = bh; + if (complete_read_super(sb, silent, size)) + return sb; + } + + brelse(bh1); + brelse(bh); + set_blocksize(sb->s_dev,BLOCK_SIZE); + printk("oldfs: cannot read superblock\n"); +failed: + return NULL; + +Eunknown: + brelse(bh); + if (!silent) + printk("VFS: unable to find oldfs superblock on device %s\n", + bdevname(dev)); + goto failed; +Ebadsize: + brelse(bh); + if (!silent) + printk("VFS: oldfs: unsupported block size (%dKb)\n", + 1<<(size-2)); + goto failed; +} + +static struct super_block *v7_read_super(struct super_block *sb,void *data, + int silent) +{ + struct buffer_head *bh; + kdev_t dev = sb->s_dev; + + if (440 != sizeof (struct v7_super_block)) + panic("V7 FS: bad super-block size"); + if (64 != sizeof (struct sysv_inode)) + panic("sysv fs: bad i-node size"); + + sb->sv_type = FSTYPE_V7; + sb->sv_bytesex = BYTESEX_PDP; + + set_blocksize(dev,512); + + if ((bh = bread(dev, 1, 512)) == NULL) { + if (!silent) + printk("VFS: unable to read V7 FS superblock on device " + "%s.\n", bdevname(dev)); + goto failed; + } + + + sb->sv_bh1 = bh; + sb->sv_bh2 = bh; + if (complete_read_super(sb, silent, 1)) + return sb; + + brelse(bh); +failed: + return NULL; +} + +/* Every kernel module contains stuff like this. */ + +static DECLARE_FSTYPE_DEV(sysv_fs_type, "sysv", sysv_read_super); +static DECLARE_FSTYPE_DEV(v7_fs_type, "v7", v7_read_super); + +static int __init init_sysv_fs(void) +{ + int err = register_filesystem(&sysv_fs_type); + if (!err) + err = register_filesystem(&v7_fs_type); + return err; +} + +static void __exit exit_sysv_fs(void) +{ + unregister_filesystem(&sysv_fs_type); + unregister_filesystem(&v7_fs_type); +} + +EXPORT_NO_SYMBOLS; + +module_init(init_sysv_fs) +module_exit(exit_sysv_fs) diff -u --recursive --new-file v2.4.5/linux/fs/sysv/truncate.c linux/fs/sysv/truncate.c --- v2.4.5/linux/fs/sysv/truncate.c Tue Sep 5 14:07:30 2000 +++ linux/fs/sysv/truncate.c Wed Dec 31 16:00:00 1969 @@ -1,293 +0,0 @@ -/* - * linux/fs/sysv/truncate.c - * - * minix/truncate.c - * Copyright (C) 1991, 1992 Linus Torvalds - * - * coh/truncate.c - * Copyright (C) 1993 Pascal Haible, Bruno Haible - * - * sysv/truncate.c - * Copyright (C) 1993 Bruno Haible - */ - -#include -#include -#include -#include - - -/* Linus' implementation of truncate. - * It doesn't need locking because it can tell from looking at bh->b_count - * whether a given block is in use elsewhere. - */ - -/* - * Truncate has the most races in the whole filesystem: coding it is - * a pain in the a**, especially as I don't do any locking. - * - * The code may look a bit weird, but that's just because I've tried to - * handle things like file-size changes in a somewhat graceful manner. - * Anyway, truncating a file at the same time somebody else writes to it - * is likely to result in pretty weird behaviour... - * - * The new code handles normal truncates (size = 0) as well as the more - * general case (size = XXX). I hope. - */ - -#define DATA_BUFFER_USED(bh) \ - (atomic_read(&bh->b_count)>1 || buffer_locked(bh)) - -/* We throw away any data beyond inode->i_size. */ - -static int trunc_direct(struct inode * inode) -{ - struct super_block * sb; - unsigned int i; - u32 * p; - u32 block; - struct buffer_head * bh; - int retry = 0; - - sb = inode->i_sb; -repeat: - for (i = ((unsigned long) inode->i_size + sb->sv_block_size_1) >> sb->sv_block_size_bits; i < 10; i++) { - p = inode->u.sysv_i.i_data + i; - block = *p; - if (!block) - continue; - bh = sv_get_hash_table(sb, inode->i_dev, block); - if ((i << sb->sv_block_size_bits) < inode->i_size) { - brelse(bh); - goto repeat; - } - if ((bh && DATA_BUFFER_USED(bh)) || (block != *p)) { - retry = 1; - brelse(bh); - continue; - } - *p = 0; - mark_inode_dirty(inode); - brelse(bh); - sysv_free_block(sb,block); - } - return retry; -} - -static int trunc_indirect(struct inode * inode, unsigned long offset, sysv_zone_t * p, int convert, unsigned char * dirt) -{ - unsigned long indtmp, indblock; - struct super_block * sb; - struct buffer_head * indbh; - unsigned int i; - sysv_zone_t * ind; - unsigned long tmp, block; - struct buffer_head * bh; - int retry = 0; - - indblock = indtmp = *p; - if (convert) - indblock = from_coh_ulong(indblock); - if (!indblock) - return 0; - sb = inode->i_sb; - indbh = sv_bread(sb, inode->i_dev, indblock); - if (indtmp != *p) { - brelse(indbh); - return 1; - } - if (!indbh) { - *p = 0; - *dirt = 1; - return 0; - } -repeat: - if (inode->i_size < offset) - i = 0; - else - i = (inode->i_size - offset + sb->sv_block_size_1) >> sb->sv_block_size_bits; - for (; i < sb->sv_ind_per_block; i++) { - ind = ((sysv_zone_t *) indbh->b_data) + i; - block = tmp = *ind; - if (sb->sv_convert) - block = from_coh_ulong(block); - if (!block) - continue; - bh = sv_get_hash_table(sb, inode->i_dev, block); - if ((i << sb->sv_block_size_bits) + offset < inode->i_size) { - brelse(bh); - goto repeat; - } - if ((bh && DATA_BUFFER_USED(bh)) || (tmp != *ind)) { - retry = 1; - brelse(bh); - continue; - } - *ind = 0; - mark_buffer_dirty(indbh); - brelse(bh); - sysv_free_block(sb,block); - } - for (i = 0; i < sb->sv_ind_per_block; i++) - if (((sysv_zone_t *) indbh->b_data)[i]) - goto done; - if (DATA_BUFFER_USED(indbh) || (indtmp != *p)) { - brelse(indbh); - return 1; - } - *p = 0; - *dirt = 1; - sysv_free_block(sb,indblock); -done: - brelse(indbh); - return retry; -} - -static int trunc_dindirect(struct inode * inode, unsigned long offset, sysv_zone_t * p, int convert, unsigned char * dirt) -{ - u32 indtmp, indblock; - struct super_block * sb; - struct buffer_head * indbh; - unsigned int i; - sysv_zone_t * ind; - u32 tmp, block; - int retry = 0; - - indblock = indtmp = *p; - if (convert) - indblock = from_coh_ulong(indblock); - if (!indblock) - return 0; - sb = inode->i_sb; - indbh = sv_bread(sb, inode->i_dev, indblock); - if (indtmp != *p) { - brelse(indbh); - return 1; - } - if (!indbh) { - *p = 0; - *dirt = 1; - return 0; - } - if (inode->i_size < offset) - i = 0; - else - i = (inode->i_size - offset + sb->sv_ind_per_block_block_size_1) >> sb->sv_ind_per_block_block_size_bits; - for (; i < sb->sv_ind_per_block; i++) { - unsigned char dirty = 0; - ind = ((sysv_zone_t *) indbh->b_data) + i; - block = tmp = *ind; - if (sb->sv_convert) - block = from_coh_ulong(block); - if (!block) - continue; - retry |= trunc_indirect(inode,offset+(i<sv_ind_per_block_bits),ind,sb->sv_convert,&dirty); - if (dirty) - mark_buffer_dirty(indbh); - } - for (i = 0; i < sb->sv_ind_per_block; i++) - if (((sysv_zone_t *) indbh->b_data)[i]) - goto done; - if (DATA_BUFFER_USED(indbh) || (indtmp != *p)) { - brelse(indbh); - return 1; - } - *p = 0; - *dirt = 1; - sysv_free_block(sb,indblock); -done: - brelse(indbh); - return retry; -} - -static int trunc_tindirect(struct inode * inode, unsigned long offset, sysv_zone_t * p, int convert, unsigned char * dirt) -{ - u32 indtmp, indblock; - struct super_block * sb; - struct buffer_head * indbh; - unsigned int i; - sysv_zone_t * ind; - u32 tmp, block; - int retry = 0; - - indblock = indtmp = *p; - if (convert) - indblock = from_coh_ulong(indblock); - if (!indblock) - return 0; - sb = inode->i_sb; - indbh = sv_bread(sb, inode->i_dev, indblock); - if (indtmp != *p) { - brelse(indbh); - return 1; - } - if (!indbh) { - *p = 0; - *dirt = 1; - return 0; - } - if (inode->i_size < offset) - i = 0; - else - i = (inode->i_size - offset + sb->sv_ind_per_block_2_block_size_1) >> sb->sv_ind_per_block_2_block_size_bits; - for (; i < sb->sv_ind_per_block; i++) { - unsigned char dirty = 0; - ind = ((sysv_zone_t *) indbh->b_data) + i; - block = tmp = *ind; - if (sb->sv_convert) - block = from_coh_ulong(block); - if (!block) - continue; - retry |= trunc_dindirect(inode,offset+(i<sv_ind_per_block_2_bits),ind,sb->sv_convert,&dirty); - if (dirty) - mark_buffer_dirty(indbh); - } - for (i = 0; i < sb->sv_ind_per_block; i++) - if (((sysv_zone_t *) indbh->b_data)[i]) - goto done; - if (DATA_BUFFER_USED(indbh) || (indtmp != *p)) { - brelse(indbh); - return 1; - } - *p = 0; - *dirt = 1; - sysv_free_block(sb,indblock); -done: - brelse(indbh); - return retry; -} - -static int trunc_all(struct inode * inode) -{ - struct super_block * sb; - char dirty; - - sb = inode->i_sb; - return trunc_direct(inode) - | trunc_indirect(inode,sb->sv_ind0_size,&inode->u.sysv_i.i_data[10],0,&dirty) - | trunc_dindirect(inode,sb->sv_ind1_size,&inode->u.sysv_i.i_data[11],0,&dirty) - | trunc_tindirect(inode,sb->sv_ind2_size,&inode->u.sysv_i.i_data[12],0,&dirty); -} - - -void sysv_truncate(struct inode * inode) -{ - /* If this is called from sysv_put_inode, we needn't worry about - * races as we are just losing the last reference to the inode. - * If this is called from another place, let's hope it's a regular - * file. - * Truncating symbolic links is strange. We assume we don't truncate - * a directory we are just modifying. We ensure we don't truncate - * a regular file we are just writing to, by use of a lock. - */ - if (S_ISLNK(inode->i_mode)) - printk("sysv_truncate: truncating symbolic link\n"); - else if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) - return; - while (trunc_all(inode)) { - current->counter = 0; - schedule(); - } - inode->i_mtime = inode->i_ctime = CURRENT_TIME; - mark_inode_dirty(inode); -} diff -u --recursive --new-file v2.4.5/linux/fs/udf/Makefile linux/fs/udf/Makefile --- v2.4.5/linux/fs/udf/Makefile Fri Dec 29 14:07:23 2000 +++ linux/fs/udf/Makefile Mon Jun 11 19:15:27 2001 @@ -9,9 +9,9 @@ O_TARGET := udf.o -obj-y := balloc.o dir.o file.o ialloc.o inode.o lowlevel.o namei.o \ +obj-y := balloc.o dir.o file.o ialloc.o inode.o lowlevel.o namei.o \ partition.o super.o truncate.o symlink.o fsync.o \ crc.o directory.o misc.o udftime.o unicode.o -obj-m := $(O_TARGET) +obj-m := $(O_TARGET) include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.5/linux/fs/udf/balloc.c linux/fs/udf/balloc.c --- v2.4.5/linux/fs/udf/balloc.c Tue Sep 5 14:07:30 2000 +++ linux/fs/udf/balloc.c Mon Jun 11 19:15:27 2001 @@ -7,7 +7,7 @@ * CONTACTS * E-mail regarding any portion of the Linux UDF file system should be * directed to the development team mailing list (run by majordomo): - * linux_udf@hootie.lvld.hp.com + * linux_udf@hpesjro.fc.hp.com * * COPYRIGHT * This file is distributed under the terms of the GNU General Public @@ -85,14 +85,14 @@ #define find_first_one_bit(addr, size)\ find_next_one_bit((addr), (size), 0) -static int read_block_bitmap(struct super_block * sb, Uint32 bitmap, - unsigned int block, unsigned long bitmap_nr) +static int read_block_bitmap(struct super_block * sb, + struct udf_bitmap *bitmap, unsigned int block, unsigned long bitmap_nr) { struct buffer_head *bh = NULL; int retval = 0; lb_addr loc; - loc.logicalBlockNum = bitmap; + loc.logicalBlockNum = bitmap->s_extPosition; loc.partitionReferenceNum = UDF_SB_PARTITION(sb); bh = udf_tread(sb, udf_get_lb_pblock(sb, loc, block), sb->s_blocksize); @@ -100,110 +100,50 @@ { retval = -EIO; } - UDF_SB_BLOCK_BITMAP_NUMBER(sb, bitmap_nr) = block; - UDF_SB_BLOCK_BITMAP(sb, bitmap_nr) = bh; + bitmap->s_block_bitmap[bitmap_nr] = bh; return retval; } -static int __load_block_bitmap(struct super_block * sb, Uint32 bitmap, - unsigned int block_group) +static int __load_block_bitmap(struct super_block * sb, + struct udf_bitmap *bitmap, unsigned int block_group) { - int i, j, retval = 0; - unsigned long block_bitmap_number; - struct buffer_head * block_bitmap = NULL; - int nr_groups = (UDF_SB_PARTLEN(sb, UDF_SB_PARTITION(sb)) + - (sizeof(struct SpaceBitmapDesc) << 3) + (sb->s_blocksize * 8) - 1) / (sb->s_blocksize * 8); + int retval = 0; + int nr_groups = bitmap->s_nr_groups; if (block_group >= nr_groups) { udf_debug("block_group (%d) > nr_groups (%d)\n", block_group, nr_groups); } - if (nr_groups <= UDF_MAX_BLOCK_LOADED) + if (bitmap->s_block_bitmap[block_group]) + return block_group; + else { - if (UDF_SB_BLOCK_BITMAP(sb, block_group)) - { - if (UDF_SB_BLOCK_BITMAP_NUMBER(sb, block_group) == block_group) - return block_group; - } retval = read_block_bitmap(sb, bitmap, block_group, block_group); if (retval < 0) return retval; return block_group; } - - for (i=0; i0; j--) - { - UDF_SB_BLOCK_BITMAP_NUMBER(sb, j) = UDF_SB_BLOCK_BITMAP_NUMBER(sb, j-1); - UDF_SB_BLOCK_BITMAP(sb, j) = UDF_SB_BLOCK_BITMAP(sb, j-1); - } - UDF_SB_BLOCK_BITMAP_NUMBER(sb, 0) = block_bitmap_number; - UDF_SB_BLOCK_BITMAP(sb, 0) = block_bitmap; - - if (!block_bitmap) - retval = read_block_bitmap(sb, bitmap, block_group, 0); - } - else - { - if (UDF_SB_LOADED_BLOCK_BITMAPS(sb) < UDF_MAX_BLOCK_LOADED) - UDF_SB_LOADED_BLOCK_BITMAPS(sb) ++; - else - brelse(UDF_SB_BLOCK_BITMAP(sb, UDF_MAX_BLOCK_LOADED-1)); - for (j=UDF_SB_LOADED_BLOCK_BITMAPS(sb)-1; j>0; j--) - { - UDF_SB_BLOCK_BITMAP_NUMBER(sb, j) = UDF_SB_BLOCK_BITMAP_NUMBER(sb, j-1); - UDF_SB_BLOCK_BITMAP(sb, j) = UDF_SB_BLOCK_BITMAP(sb, j-1); - } - retval = read_block_bitmap(sb, bitmap, block_group, 0); - } - return retval; } -static inline int load_block_bitmap(struct super_block *sb, Uint32 bitmap, - unsigned int block_group) +static inline int load_block_bitmap(struct super_block *sb, + struct udf_bitmap *bitmap, unsigned int block_group) { int slot; - int nr_groups = (UDF_SB_PARTLEN(sb, UDF_SB_PARTITION(sb)) + - (sizeof(struct SpaceBitmapDesc) << 3) + (sb->s_blocksize * 8) - 1) / (sb->s_blocksize * 8); - if (UDF_SB_LOADED_BLOCK_BITMAPS(sb) > 0 && - UDF_SB_BLOCK_BITMAP_NUMBER(sb, 0) == block_group && - UDF_SB_BLOCK_BITMAP(sb, block_group)) - { - return 0; - } - else if (nr_groups <= UDF_MAX_BLOCK_LOADED && - UDF_SB_BLOCK_BITMAP_NUMBER(sb, block_group) == block_group && - UDF_SB_BLOCK_BITMAP(sb, block_group)) - { - slot = block_group; - } - else - { - slot = __load_block_bitmap(sb, bitmap, block_group); - } + slot = __load_block_bitmap(sb, bitmap, block_group); if (slot < 0) return slot; - if (!UDF_SB_BLOCK_BITMAP(sb, slot)) + if (!bitmap->s_block_bitmap[slot]) return -EIO; return slot; } -static void udf_bitmap_free_blocks(const struct inode * inode, Uint32 bitmap, - lb_addr bloc, Uint32 offset, Uint32 count) +static void udf_bitmap_free_blocks(const struct inode * inode, + struct udf_bitmap *bitmap, lb_addr bloc, Uint32 offset, Uint32 count) { struct buffer_head * bh = NULL; unsigned long block; @@ -250,7 +190,7 @@ if (bitmap_nr < 0) goto error_return; - bh = UDF_SB_BLOCK_BITMAP(sb, bitmap_nr); + bh = bitmap->s_block_bitmap[bitmap_nr]; for (i=0; i < count; i++) { if (udf_set_bit(bit + i, bh->b_data)) @@ -283,8 +223,9 @@ return; } -static int udf_bitmap_prealloc_blocks(const struct inode * inode, Uint32 bitmap, - Uint16 partition, Uint32 first_block, Uint32 block_count) +static int udf_bitmap_prealloc_blocks(const struct inode * inode, + struct udf_bitmap *bitmap, Uint16 partition, Uint32 first_block, + Uint32 block_count) { int alloc_count = 0; int bit, block, block_group, group_start; @@ -303,6 +244,9 @@ if (first_block < 0 || first_block >= UDF_SB_PARTLEN(sb, partition)) goto out; + if (first_block + block_count > UDF_SB_PARTLEN(sb, partition)) + block_count = UDF_SB_PARTLEN(sb, partition) - first_block; + repeat: nr_groups = (UDF_SB_PARTLEN(sb, partition) + (sizeof(struct SpaceBitmapDesc) << 3) + (sb->s_blocksize * 8) - 1) / (sb->s_blocksize * 8); @@ -313,7 +257,7 @@ bitmap_nr = load_block_bitmap(sb, bitmap, block_group); if (bitmap_nr < 0) goto out; - bh = UDF_SB_BLOCK_BITMAP(sb, bitmap_nr); + bh = bitmap->s_block_bitmap[bitmap_nr]; bit = block % (sb->s_blocksize << 3); @@ -349,10 +293,10 @@ return alloc_count; } -static int udf_bitmap_new_block(const struct inode * inode, Uint32 bitmap, - Uint16 partition, Uint32 goal, int *err) +static int udf_bitmap_new_block(const struct inode * inode, + struct udf_bitmap *bitmap, Uint16 partition, Uint32 goal, int *err) { - int tmp, newbit, bit=0, block, block_group, group_start; + int newbit, bit=0, block, block_group, group_start; int end_goal, nr_groups, bitmap_nr, i; struct buffer_head *bh = NULL; struct super_block *sb; @@ -372,8 +316,7 @@ if (goal < 0 || goal >= UDF_SB_PARTLEN(sb, partition)) goal = 0; - nr_groups = (UDF_SB_PARTLEN(sb, partition) + - (sizeof(struct SpaceBitmapDesc) << 3) + (sb->s_blocksize * 8) - 1) / (sb->s_blocksize * 8); + nr_groups = bitmap->s_nr_groups; block = goal + (sizeof(struct SpaceBitmapDesc) << 3); block_group = block >> (sb->s_blocksize_bits + 3); group_start = block_group ? 0 : sizeof(struct SpaceBitmapDesc); @@ -381,7 +324,7 @@ bitmap_nr = load_block_bitmap(sb, bitmap, block_group); if (bitmap_nr < 0) goto error_return; - bh = UDF_SB_BLOCK_BITMAP(sb, bitmap_nr); + bh = bitmap->s_block_bitmap[bitmap_nr]; ptr = memscan((char *)bh->b_data + group_start, 0xFF, sb->s_blocksize - group_start); if ((ptr - ((char *)bh->b_data)) < sb->s_blocksize) @@ -421,7 +364,7 @@ bitmap_nr = load_block_bitmap(sb, bitmap, block_group); if (bitmap_nr < 0) goto error_return; - bh = UDF_SB_BLOCK_BITMAP(sb, bitmap_nr); + bh = bitmap->s_block_bitmap[bitmap_nr]; if (i < nr_groups) { ptr = memscan((char *)bh->b_data + group_start, 0xFF, sb->s_blocksize - group_start); @@ -471,7 +414,6 @@ newblock = bit + (block_group << (sb->s_blocksize_bits + 3)) - (sizeof(struct SpaceBitmapDesc) << 3); - tmp = udf_get_pblock(sb, newblock, partition, 0); if (!udf_clear_bit(bit, bh->b_data)) { udf_debug("bit already cleared for block %d\n", bit); @@ -497,19 +439,479 @@ return 0; } +static void udf_table_free_blocks(const struct inode * inode, + struct inode * table, lb_addr bloc, Uint32 offset, Uint32 count) +{ + struct super_block * sb; + Uint32 start, end; + Uint32 nextoffset, oextoffset, elen; + lb_addr nbloc, obloc, eloc; + struct buffer_head *obh, *nbh; + char etype; + int i; + + udf_debug("ino=%ld, bloc=%d, offset=%d, count=%d\n", + inode->i_ino, bloc.logicalBlockNum, offset, count); + + sb = inode->i_sb; + if (!sb) + { + udf_debug("nonexistent device"); + return; + } + + if (table == NULL) + return; + + lock_super(sb); + if (bloc.logicalBlockNum < 0 || + (bloc.logicalBlockNum + count) > UDF_SB_PARTLEN(sb, bloc.partitionReferenceNum)) + { + udf_debug("%d < %d || %d + %d > %d\n", + bloc.logicalBlockNum, 0, bloc.logicalBlockNum, count, + UDF_SB_PARTLEN(sb, bloc.partitionReferenceNum)); + goto error_return; + } + + /* We do this up front - There are some error conditions that could occure, + but.. oh well */ + DQUOT_FREE_BLOCK(sb, inode, count); + if (UDF_SB_LVIDBH(sb)) + { + UDF_SB_LVID(sb)->freeSpaceTable[UDF_SB_PARTITION(sb)] = + cpu_to_le32(le32_to_cpu(UDF_SB_LVID(sb)->freeSpaceTable[UDF_SB_PARTITION(sb)])+count); + mark_buffer_dirty(UDF_SB_LVIDBH(sb)); + } + + start = bloc.logicalBlockNum + offset; + end = bloc.logicalBlockNum + offset + count - 1; + + oextoffset = nextoffset = sizeof(struct UnallocatedSpaceEntry); + elen = 0; + obloc = nbloc = UDF_I_LOCATION(table); + + obh = nbh = udf_tread(sb, udf_get_lb_pblock(sb, nbloc, 0), sb->s_blocksize); + atomic_inc(&nbh->b_count); + + while (count && (etype = + udf_next_aext(table, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1) + { + if (((eloc.logicalBlockNum + (elen >> sb->s_blocksize_bits)) == + start)) + { + if ((0x3FFFFFFF - elen) < (count << sb->s_blocksize_bits)) + { + count -= ((0x3FFFFFFF - elen) >> sb->s_blocksize_bits); + start += ((0x3FFFFFFF - elen) >> sb->s_blocksize_bits); + elen = (etype << 30) | (0x40000000 - sb->s_blocksize); + } + else + { + elen = (etype << 30) | + (elen + (count << sb->s_blocksize_bits)); + start += count; + count = 0; + } + udf_write_aext(table, obloc, &oextoffset, eloc, elen, obh, 1); + } + else if (eloc.logicalBlockNum == (end + 1)) + { + if ((0x3FFFFFFF - elen) < (count << sb->s_blocksize_bits)) + { + count -= ((0x3FFFFFFF - elen) >> sb->s_blocksize_bits); + end -= ((0x3FFFFFFF - elen) >> sb->s_blocksize_bits); + eloc.logicalBlockNum -= + ((0x3FFFFFFF - elen) >> sb->s_blocksize_bits); + elen = (etype << 30) | (0x40000000 - sb->s_blocksize); + } + else + { + eloc.logicalBlockNum = start; + elen = (etype << 30) | + (elen + (count << sb->s_blocksize_bits)); + end -= count; + count = 0; + } + udf_write_aext(table, obloc, &oextoffset, eloc, elen, obh, 1); + } + + if (memcmp(&nbloc, &obloc, sizeof(lb_addr))) + { + i = -1; + obloc = nbloc; + udf_release_data(obh); + atomic_inc(&nbh->b_count); + obh = nbh; + oextoffset = 0; + } + else + oextoffset = nextoffset; + } + + if (count) + { + /* NOTE: we CANNOT use udf_add_aext here, as it can try to allocate + a new block, and since we hold the super block lock already + very bad things would happen :) + + We copy the behavior of udf_add_aext, but instead of + trying to allocate a new block close to the existing one, + we just steal a block from the extent we are trying to add. + + It would be nice if the blocks were close together, but it + isn't required. + */ + + int adsize; + short_ad *sad = NULL; + long_ad *lad = NULL; + struct AllocExtDesc *aed; + + eloc.logicalBlockNum = start; + elen = (EXTENT_RECORDED_ALLOCATED << 30) | + (count << sb->s_blocksize_bits); + + if (UDF_I_ALLOCTYPE(table) == ICB_FLAG_AD_SHORT) + adsize = sizeof(short_ad); + else if (UDF_I_ALLOCTYPE(table) == ICB_FLAG_AD_LONG) + adsize = sizeof(long_ad); + else + { + udf_release_data(obh); + udf_release_data(nbh); + goto error_return; + } + + if (nextoffset + (2 * adsize) > sb->s_blocksize) + { + char *sptr, *dptr; + int loffset; + + udf_release_data(obh); + obh = nbh; + obloc = nbloc; + oextoffset = nextoffset; + + /* Steal a block from the extent being free'd */ + nbloc.logicalBlockNum = eloc.logicalBlockNum; + eloc.logicalBlockNum ++; + elen -= sb->s_blocksize; + + if (!(nbh = udf_tread(sb, + udf_get_lb_pblock(sb, nbloc, 0), + sb->s_blocksize))) + { + udf_release_data(obh); + goto error_return; + } + aed = (struct AllocExtDesc *)(nbh->b_data); + aed->previousAllocExtLocation = cpu_to_le32(obloc.logicalBlockNum); + if (nextoffset + adsize > sb->s_blocksize) + { + loffset = nextoffset; + aed->lengthAllocDescs = cpu_to_le32(adsize); + sptr = (obh)->b_data + nextoffset - adsize; + dptr = nbh->b_data + sizeof(struct AllocExtDesc); + memcpy(dptr, sptr, adsize); + nextoffset = sizeof(struct AllocExtDesc) + adsize; + } + else + { + loffset = nextoffset + adsize; + aed->lengthAllocDescs = cpu_to_le32(0); + sptr = (obh)->b_data + nextoffset; + nextoffset = sizeof(struct AllocExtDesc); + + if (memcmp(&UDF_I_LOCATION(table), &obloc, sizeof(lb_addr))) + { + aed = (struct AllocExtDesc *)(obh)->b_data; + aed->lengthAllocDescs = + cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize); + } + else + { + UDF_I_LENALLOC(table) += adsize; + mark_inode_dirty(table); + } + } + udf_new_tag(nbh->b_data, TID_ALLOC_EXTENT_DESC, 2, 1, + nbloc.logicalBlockNum, sizeof(tag)); + switch (UDF_I_ALLOCTYPE(table)) + { + case ICB_FLAG_AD_SHORT: + { + sad = (short_ad *)sptr; + sad->extLength = cpu_to_le32( + EXTENT_NEXT_EXTENT_ALLOCDECS << 30 | + sb->s_blocksize); + sad->extPosition = cpu_to_le32(nbloc.logicalBlockNum); + break; + } + case ICB_FLAG_AD_LONG: + { + lad = (long_ad *)sptr; + lad->extLength = cpu_to_le32( + EXTENT_NEXT_EXTENT_ALLOCDECS << 30 | + sb->s_blocksize); + lad->extLocation = cpu_to_lelb(nbloc); + break; + } + } + udf_update_tag(obh->b_data, loffset); + mark_buffer_dirty(obh); + } + + if (elen) /* It's possible that stealing the block emptied the extent */ + { + udf_write_aext(table, nbloc, &nextoffset, eloc, elen, nbh, 1); + + if (!memcmp(&UDF_I_LOCATION(table), &nbloc, sizeof(lb_addr))) + { + UDF_I_LENALLOC(table) += adsize; + mark_inode_dirty(table); + } + else + { + aed = (struct AllocExtDesc *)nbh->b_data; + aed->lengthAllocDescs = + cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize); + udf_update_tag(nbh->b_data, nextoffset); + mark_buffer_dirty(nbh); + } + } + } + + udf_release_data(nbh); + udf_release_data(obh); + +error_return: + sb->s_dirt = 1; + unlock_super(sb); + return; +} + +static int udf_table_prealloc_blocks(const struct inode * inode, + struct inode *table, Uint16 partition, Uint32 first_block, + Uint32 block_count) +{ + struct super_block *sb; + int alloc_count = 0; + Uint32 extoffset, elen, adsize; + lb_addr bloc, eloc; + struct buffer_head *bh; + char etype = -1; + + udf_debug("ino=%ld, partition=%d, first_block=%d, block_count=%d\n", + inode->i_ino, partition, first_block, block_count); + + sb = inode->i_sb; + if (!sb) + { + udf_debug("nonexistent device\n"); + return 0; + } + + if (first_block < 0 || first_block >= UDF_SB_PARTLEN(sb, partition)) + return 0; + + if (table == NULL) + return 0; + + if (UDF_I_ALLOCTYPE(table) == ICB_FLAG_AD_SHORT) + adsize = sizeof(short_ad); + else if (UDF_I_ALLOCTYPE(table) == ICB_FLAG_AD_LONG) + adsize = sizeof(long_ad); + else + return 0; + + lock_super(sb); + + extoffset = sizeof(struct UnallocatedSpaceEntry); + bloc = UDF_I_LOCATION(table); + + bh = udf_tread(sb, udf_get_lb_pblock(sb, bloc, 0), sb->s_blocksize); + eloc.logicalBlockNum = 0xFFFFFFFF; + + while (first_block != eloc.logicalBlockNum && (etype = + udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1) + { + udf_debug("eloc=%d, elen=%d, first_block=%d\n", + eloc.logicalBlockNum, elen, first_block); + ; /* empty loop body */ + } + + if (first_block == eloc.logicalBlockNum) + { + extoffset -= adsize; + + alloc_count = (elen >> sb->s_blocksize_bits); + if (alloc_count > block_count) + { + alloc_count = block_count; + eloc.logicalBlockNum += alloc_count; + elen -= (alloc_count << sb->s_blocksize_bits); + udf_write_aext(table, bloc, &extoffset, eloc, (etype << 30) | elen, bh, 1); + } + else + udf_delete_aext(table, bloc, extoffset, eloc, (etype << 30) | elen, bh); + } + else + alloc_count = 0; + + udf_release_data(bh); + + if (alloc_count && UDF_SB_LVIDBH(sb)) + { + UDF_SB_LVID(sb)->freeSpaceTable[partition] = + cpu_to_le32(le32_to_cpu(UDF_SB_LVID(sb)->freeSpaceTable[partition])-alloc_count); + mark_buffer_dirty(UDF_SB_LVIDBH(sb)); + } + sb->s_dirt = 1; + unlock_super(sb); + udf_debug("alloc_count=%d\n", alloc_count); + return alloc_count; +} + +static int udf_table_new_block(const struct inode * inode, + struct inode *table, Uint16 partition, Uint32 goal, int *err) +{ + struct super_block *sb; + Uint32 spread = 0xFFFFFFFF, nspread; + Uint32 newblock = 0, adsize; + Uint32 extoffset, goal_extoffset, elen, goal_elen = 0; + lb_addr bloc, goal_bloc, eloc, goal_eloc; + struct buffer_head *bh, *goal_bh; + char etype; + + udf_debug("ino=%ld, partition=%d, goal=%d\n", + inode->i_ino, partition, goal); + + *err = -ENOSPC; + sb = inode->i_sb; + if (!sb) + { + udf_debug("nonexistent device\n"); + return newblock; + } + + if (table == NULL) + return newblock; + + if (UDF_I_ALLOCTYPE(table) == ICB_FLAG_AD_SHORT) + adsize = sizeof(short_ad); + else if (UDF_I_ALLOCTYPE(table) == ICB_FLAG_AD_LONG) + adsize = sizeof(long_ad); + else + return newblock; + + lock_super(sb); + + if (goal < 0 || goal >= UDF_SB_PARTLEN(sb, partition)) + goal = 0; + + /* We search for the closest matching block to goal. If we find a exact hit, we stop. Otherwise we keep going till we run out of extents. + We store the buffer_head, bloc, and extoffset of the current closest + match and use that when we are done. + */ + + extoffset = sizeof(struct UnallocatedSpaceEntry); + bloc = UDF_I_LOCATION(table); + + goal_bh = bh = udf_tread(sb, udf_get_lb_pblock(sb, bloc, 0), sb->s_blocksize); + atomic_inc(&goal_bh->b_count); + + while (spread && (etype = + udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1) + { + if (goal >= eloc.logicalBlockNum) + { + if (goal < eloc.logicalBlockNum + (elen >> sb->s_blocksize_bits)) + nspread = 0; + else + nspread = goal - eloc.logicalBlockNum - + (elen >> sb->s_blocksize_bits); + } + else + nspread = eloc.logicalBlockNum - goal; + + if (nspread < spread) + { + spread = nspread; + if (goal_bh != bh) + { + udf_release_data(goal_bh); + goal_bh = bh; + atomic_inc(&goal_bh->b_count); + } + goal_bloc = bloc; + goal_extoffset = extoffset - adsize; + goal_eloc = eloc; + goal_elen = (etype << 30) | elen; + } + } + + udf_release_data(bh); + + if (spread == 0xFFFFFFFF) + { + udf_release_data(goal_bh); + unlock_super(sb); + return 0; + } + + /* Only allocate blocks from the beginning of the extent. + That way, we only delete (empty) extents, never have to insert an + extent because of splitting */ + /* This works, but very poorly.... */ + + newblock = goal_eloc.logicalBlockNum; + goal_eloc.logicalBlockNum ++; + goal_elen -= sb->s_blocksize; + + if (goal_elen) + udf_write_aext(table, goal_bloc, &goal_extoffset, goal_eloc, goal_elen, goal_bh, 1); + else + udf_delete_aext(table, goal_bloc, goal_extoffset, goal_eloc, goal_elen, goal_bh); + udf_release_data(goal_bh); + + if (UDF_SB_LVIDBH(sb)) + { + UDF_SB_LVID(sb)->freeSpaceTable[partition] = + cpu_to_le32(le32_to_cpu(UDF_SB_LVID(sb)->freeSpaceTable[partition])-1); + mark_buffer_dirty(UDF_SB_LVIDBH(sb)); + } + + sb->s_dirt = 1; + unlock_super(sb); + *err = 0; + return newblock; +} + inline void udf_free_blocks(const struct inode * inode, lb_addr bloc, - Uint32 offset, Uint32 count) + Uint32 offset, Uint32 count) { if (UDF_SB_PARTFLAGS(inode->i_sb, bloc.partitionReferenceNum) & UDF_PART_FLAG_UNALLOC_BITMAP) { return udf_bitmap_free_blocks(inode, - UDF_SB_PARTMAPS(inode->i_sb)[bloc.partitionReferenceNum].s_uspace.bitmap, + UDF_SB_PARTMAPS(inode->i_sb)[bloc.partitionReferenceNum].s_uspace.s_bitmap, + bloc, offset, count); + } + else if (UDF_SB_PARTFLAGS(inode->i_sb, bloc.partitionReferenceNum) & UDF_PART_FLAG_UNALLOC_TABLE) + { + return udf_table_free_blocks(inode, + UDF_SB_PARTMAPS(inode->i_sb)[bloc.partitionReferenceNum].s_uspace.s_table, bloc, offset, count); } else if (UDF_SB_PARTFLAGS(inode->i_sb, bloc.partitionReferenceNum) & UDF_PART_FLAG_FREED_BITMAP) { return udf_bitmap_free_blocks(inode, - UDF_SB_PARTMAPS(inode->i_sb)[bloc.partitionReferenceNum].s_fspace.bitmap, + UDF_SB_PARTMAPS(inode->i_sb)[bloc.partitionReferenceNum].s_fspace.s_bitmap, + bloc, offset, count); + } + else if (UDF_SB_PARTFLAGS(inode->i_sb, bloc.partitionReferenceNum) & UDF_PART_FLAG_FREED_TABLE) + { + return udf_table_free_blocks(inode, + UDF_SB_PARTMAPS(inode->i_sb)[bloc.partitionReferenceNum].s_fspace.s_table, bloc, offset, count); } else @@ -522,13 +924,25 @@ if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_UNALLOC_BITMAP) { return udf_bitmap_prealloc_blocks(inode, - UDF_SB_PARTMAPS(inode->i_sb)[partition].s_uspace.bitmap, + UDF_SB_PARTMAPS(inode->i_sb)[partition].s_uspace.s_bitmap, + partition, first_block, block_count); + } + else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_UNALLOC_TABLE) + { + return udf_table_prealloc_blocks(inode, + UDF_SB_PARTMAPS(inode->i_sb)[partition].s_uspace.s_table, partition, first_block, block_count); } else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_FREED_BITMAP) { return udf_bitmap_prealloc_blocks(inode, - UDF_SB_PARTMAPS(inode->i_sb)[partition].s_fspace.bitmap, + UDF_SB_PARTMAPS(inode->i_sb)[partition].s_fspace.s_bitmap, + partition, first_block, block_count); + } + else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_FREED_TABLE) + { + return udf_table_prealloc_blocks(inode, + UDF_SB_PARTMAPS(inode->i_sb)[partition].s_fspace.s_table, partition, first_block, block_count); } else @@ -541,13 +955,25 @@ if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_UNALLOC_BITMAP) { return udf_bitmap_new_block(inode, - UDF_SB_PARTMAPS(inode->i_sb)[partition].s_uspace.bitmap, + UDF_SB_PARTMAPS(inode->i_sb)[partition].s_uspace.s_bitmap, + partition, goal, err); + } + else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_UNALLOC_TABLE) + { + return udf_table_new_block(inode, + UDF_SB_PARTMAPS(inode->i_sb)[partition].s_uspace.s_table, partition, goal, err); } else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_FREED_BITMAP) { return udf_bitmap_new_block(inode, - UDF_SB_PARTMAPS(inode->i_sb)[partition].s_fspace.bitmap, + UDF_SB_PARTMAPS(inode->i_sb)[partition].s_fspace.s_bitmap, + partition, goal, err); + } + else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_FREED_TABLE) + { + return udf_table_new_block(inode, + UDF_SB_PARTMAPS(inode->i_sb)[partition].s_fspace.s_table, partition, goal, err); } else @@ -556,4 +982,3 @@ return 0; } } - diff -u --recursive --new-file v2.4.5/linux/fs/udf/crc.c linux/fs/udf/crc.c --- v2.4.5/linux/fs/udf/crc.c Sat Sep 4 12:42:30 1999 +++ linux/fs/udf/crc.c Mon Jun 11 19:15:27 2001 @@ -17,7 +17,7 @@ * CONTACTS * E-mail regarding any portion of the Linux UDF file system should be * directed to the development team mailing list (run by majordomo): - * linux_udf@hootie.lvld.hp.com + * linux_udf@hpesjro.fc.hp.com * * COPYRIGHT * This file is distributed under the terms of the GNU General Public diff -u --recursive --new-file v2.4.5/linux/fs/udf/dir.c linux/fs/udf/dir.c --- v2.4.5/linux/fs/udf/dir.c Fri Feb 9 11:29:44 2001 +++ linux/fs/udf/dir.c Mon Jun 11 19:15:27 2001 @@ -7,7 +7,7 @@ * CONTACTS * E-mail regarding any portion of the Linux UDF file system should be * directed to the development team mailing list (run by majordomo): - * linux_udf@hootie.lvld.hp.com + * linux_udf@hpesjro.fc.hp.com * * COPYRIGHT * This file is distributed under the terms of the GNU General Public @@ -49,10 +49,10 @@ /* readdir and lookup functions */ struct file_operations udf_dir_operations = { - read: generic_read_dir, - readdir: udf_readdir, - ioctl: udf_ioctl, - fsync: udf_sync_file, + read: generic_read_dir, + readdir: udf_readdir, + ioctl: udf_ioctl, + fsync: udf_fsync_file, }; /* @@ -88,8 +88,9 @@ if ( filp->f_pos == 0 ) { - if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino, DT_DIR)) + if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino, DT_DIR) < 0) return 0; + filp->f_pos ++; } result = do_udf_readdir(dir, filp, filldir, dirent); @@ -104,19 +105,21 @@ struct FileIdentDesc *fi=NULL; struct FileIdentDesc cfi; int block, iblock; - loff_t nf_pos = filp->f_pos; + loff_t nf_pos = filp->f_pos - 1; int flen; char fname[255]; char *nameptr; Uint16 liu; Uint8 lfi; loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2; - struct buffer_head * bh = NULL; + struct buffer_head * bh = NULL, * tmp, * bha[16]; lb_addr bloc, eloc; Uint32 extoffset, elen, offset; + int i, num; + unsigned int dt_type; if (nf_pos >= size) - return 1; + return 0; if (nf_pos == 0) nf_pos = (udf_ext0_offset(dir) >> 2); @@ -125,6 +128,7 @@ if (inode_bmap(dir, nf_pos >> (dir->i_sb->s_blocksize_bits - 2), &bloc, &extoffset, &eloc, &elen, &offset, &bh) == EXTENT_RECORDED_ALLOCATED) { + offset >>= dir->i_sb->s_blocksize_bits; block = udf_get_lb_pblock(dir->i_sb, eloc, offset); if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { @@ -139,18 +143,40 @@ else { udf_release_data(bh); - return 0; + return -ENOENT; } if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize))) { udf_release_data(bh); - return 0; + return -EIO; + } + + if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9))-1))) + { + i = 16 >> (dir->i_sb->s_blocksize_bits - 9); + if (i+offset > (elen >> dir->i_sb->s_blocksize_bits)) + i = (elen >> dir->i_sb->s_blocksize_bits)-offset; + for (num=0; i>0; i--) + { + block = udf_get_lb_pblock(dir->i_sb, eloc, offset+i); + tmp = udf_tgetblk(dir->i_sb, block, dir->i_sb->s_blocksize); + if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp)) + bha[num++] = tmp; + else + brelse(tmp); + } + if (num) + { + ll_rw_block(READA, num, bha); + for (i=0; if_pos = nf_pos; + filp->f_pos = nf_pos + 1; fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh); @@ -160,7 +186,7 @@ udf_release_data(fibh.ebh); udf_release_data(fibh.sbh); udf_release_data(bh); - return 1; + return -ENOENT; } liu = le16_to_cpu(cfi.lengthOfImpUse); @@ -196,44 +222,39 @@ continue; } - iblock = udf_get_lb_pblock(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation), 0); - - if (!lfi) /* parent directory */ - { - if (filldir(dirent, "..", 2, filp->f_pos, filp->f_dentry->d_parent->d_inode->i_ino, DT_DIR)) + if ( cfi.fileCharacteristics & FILE_PARENT ) + { + iblock = udf_get_lb_pblock(dir->i_sb, UDF_I_LOCATION(filp->f_dentry->d_parent->d_inode), 0); + flen = 2; + memcpy(fname, "..", flen); + dt_type = DT_DIR; + } + else + { + iblock = udf_get_lb_pblock(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation), 0); + flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); + dt_type = DT_UNKNOWN; + } + + if (flen) + { + if (filldir(dirent, fname, flen, filp->f_pos, iblock, dt_type) < 0) { if (fibh.sbh != fibh.ebh) udf_release_data(fibh.ebh); udf_release_data(fibh.sbh); udf_release_data(bh); - return 1; - } - } - else - { - if ((flen = udf_get_filename(nameptr, fname, lfi))) - { - if (filldir(dirent, fname, flen, filp->f_pos, iblock, DT_UNKNOWN)) - { - if (fibh.sbh != fibh.ebh) - udf_release_data(fibh.ebh); - udf_release_data(fibh.sbh); - udf_release_data(bh); - return 1; /* halt enum */ - } + return 0; } } } /* end while */ - filp->f_pos = nf_pos; + filp->f_pos = nf_pos + 1; if (fibh.sbh != fibh.ebh) udf_release_data(fibh.ebh); udf_release_data(fibh.sbh); udf_release_data(bh); - if ( filp->f_pos >= size) - return 1; - else - return 0; + return 0; } diff -u --recursive --new-file v2.4.5/linux/fs/udf/directory.c linux/fs/udf/directory.c --- v2.4.5/linux/fs/udf/directory.c Thu Mar 2 11:17:32 2000 +++ linux/fs/udf/directory.c Mon Jun 11 19:15:27 2001 @@ -7,7 +7,7 @@ * CONTACTS * E-mail regarding any portion of the Linux UDF file system should be * directed to the development team mailing list (run by majordomo): - * linux_udf@hootie.lvld.hp.com + * linux_udf@hpesjro.fc.hp.com * * COPYRIGHT * This file is distributed under the terms of the GNU General Public @@ -92,7 +92,8 @@ Uint32 *offset, struct buffer_head **bh) { struct FileIdentDesc *fi; - int block; + int i, num, block; + struct buffer_head * tmp, * bha[16]; fibh->soffset = fibh->eoffset; @@ -119,6 +120,28 @@ if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize))) return NULL; fibh->soffset = fibh->eoffset = 0; + + if (!(*offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9))-1))) + { + i = 16 >> (dir->i_sb->s_blocksize_bits - 9); + if (i+*offset > (*elen >> dir->i_sb->s_blocksize_bits)) + i = (*elen >> dir->i_sb->s_blocksize_bits)-*offset; + for (num=0; i>0; i--) + { + block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset+i); + tmp = udf_tgetblk(dir->i_sb, block, dir->i_sb->s_blocksize); + if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp)) + bha[num++] = tmp; + else + brelse(tmp); + } + if (num) + { + ll_rw_block(READA, num, bha); + for (i=0; isbh != fibh->ebh) { diff -u --recursive --new-file v2.4.5/linux/fs/udf/file.c linux/fs/udf/file.c --- v2.4.5/linux/fs/udf/file.c Sun Jan 28 13:28:09 2001 +++ linux/fs/udf/file.c Mon Jun 11 19:15:27 2001 @@ -7,7 +7,7 @@ * CONTACTS * E-mail regarding any portion of the Linux UDF file system should be * directed to the development team mailing list (run by majordomo): - * linux_udf@hootie.lvld.hp.com + * linux_udf@hpesjro.fc.hp.com * * COPYRIGHT * This file is distributed under the terms of the GNU General Public @@ -119,8 +119,8 @@ } struct address_space_operations udf_adinicb_aops = { - readpage: udf_adinicb_readpage, - writepage: udf_adinicb_writepage, + readpage: udf_adinicb_readpage, + writepage: udf_adinicb_writepage, sync_page: block_sync_page, prepare_write: udf_adinicb_prepare_write, commit_write: udf_adinicb_commit_write, @@ -208,7 +208,6 @@ { int result = -1; struct buffer_head *bh = NULL; - Uint16 ident; long_ad eaicb; Uint8 *ea = NULL; @@ -232,17 +231,28 @@ if ( (result == verify_area(VERIFY_WRITE, (char *)arg, 32)) == 0) result = copy_to_user((char *)arg, UDF_SB_VOLIDENT(inode->i_sb), 32); return result; + case UDF_RELOCATE_BLOCKS: + { + long old, new; + + if (!capable(CAP_SYS_ADMIN)) return -EACCES; + get_user(old, (long *)arg); + if ((result = udf_relocate_blocks(inode->i_sb, old, &new)) == 0) + result = put_user(new, (long *)arg); + return result; + } } /* ok, we need to read the inode */ - bh = udf_read_ptagged(inode->i_sb, UDF_I_LOCATION(inode), 0, &ident); + bh = udf_tread(inode->i_sb, + udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0), + inode->i_sb->s_blocksize); - if (!bh || (ident != TID_FILE_ENTRY && ident != TID_EXTENDED_FILE_ENTRY)) + if (!bh) { - udf_debug("bread failed (ino=%ld) or ident (%d) != TID_(EXTENDED_)FILE_ENTRY", - inode->i_ino, ident); - return -EFAULT; + udf_debug("bread failed (inode=%ld)\n", inode->i_ino); + return -EIO; } if (UDF_I_EXTENDED_FE(inode) == 0) @@ -277,7 +287,6 @@ break; default: - udf_debug("ino=%ld, cmd=%d\n", inode->i_ino, cmd); break; } @@ -299,7 +308,8 @@ */ static int udf_release_file(struct inode * inode, struct file * filp) { - if (filp->f_mode & FMODE_WRITE) { + if (filp->f_mode & FMODE_WRITE) + { lock_kernel(); udf_discard_prealloc(inode); unlock_kernel(); @@ -322,21 +332,21 @@ */ static int udf_open_file(struct inode * inode, struct file * filp) { - if ((inode->i_size & 0xFFFFFFFF00000000ULL) && !(filp->f_flags & O_LARGEFILE)) + if ((inode->i_size & 0xFFFFFFFF80000000ULL) && !(filp->f_flags & O_LARGEFILE)) return -EFBIG; return 0; } struct file_operations udf_file_operations = { - read: generic_file_read, - ioctl: udf_ioctl, - open: udf_open_file, - mmap: generic_file_mmap, - write: udf_file_write, - release: udf_release_file, - fsync: udf_sync_file, + read: generic_file_read, + ioctl: udf_ioctl, + open: udf_open_file, + mmap: generic_file_mmap, + write: udf_file_write, + release: udf_release_file, + fsync: udf_fsync_file, }; struct inode_operations udf_file_inode_operations = { - truncate: udf_truncate, + truncate: udf_truncate, }; diff -u --recursive --new-file v2.4.5/linux/fs/udf/fsync.c linux/fs/udf/fsync.c --- v2.4.5/linux/fs/udf/fsync.c Thu Jun 29 16:23:11 2000 +++ linux/fs/udf/fsync.c Mon Jun 11 19:15:27 2001 @@ -7,7 +7,7 @@ * CONTACTS * E-mail regarding any portion of the Linux UDF file system should be * directed to the development team mailing list (run by majordomo): - * linux_udf@hootie.lvld.hp.com + * linux_udf@hpesjro.fc.hp.com * * COPYRIGHT * This file is distributed under the terms of the GNU General Public @@ -28,96 +28,28 @@ #include #include #include -#include -#include "udf_i.h" - -static int sync_extent_block (struct inode * inode, Uint32 block, int wait) -{ - struct buffer_head * bh; - - if (!block) - return 0; - bh = get_hash_table (inode->i_dev, block, inode->i_sb->s_blocksize); - if (!bh) - return 0; - if (wait && buffer_req(bh) && !buffer_uptodate(bh)) { - /* There can be a parallell read(2) that started read-I/O - on the buffer so we can't assume that there's been - an I/O error without first waiting I/O completation. */ - wait_on_buffer(bh); - if (!buffer_uptodate(bh)) - { - brelse (bh); - return -1; - } - } - if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) { - if (wait) - /* when we return from fsync all the blocks - must be _just_ stored on disk */ - wait_on_buffer(bh); - brelse (bh); - return 0; - } - ll_rw_block (WRITE, 1, &bh); - atomic_dec(&bh->b_count); - return 0; -} - -static int sync_all_extents(struct inode * inode, int wait) -{ - lb_addr bloc, eloc; - Uint32 extoffset, lextoffset, elen, offset, block; - int err = 0, etype; - struct buffer_head *bh = NULL; - - if ((etype = inode_bmap(inode, 0, &bloc, &extoffset, &eloc, &elen, &offset, &bh)) != -1) - { - block = udf_get_lb_pblock(inode->i_sb, bloc, 0); - err |= sync_extent_block(inode, block, wait); - lextoffset = extoffset; - - while ((etype = udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1) - { - if (lextoffset > extoffset) - { - block = udf_get_lb_pblock(inode->i_sb, bloc, 0); - err |= sync_extent_block(inode, block, wait); - } - lextoffset = extoffset; - } - } - udf_release_data(bh); - return err; -} /* * File may be NULL when we are called. Perhaps we shouldn't * even pass file to fsync ? */ -int udf_sync_file(struct file * file, struct dentry *dentry, int datasync) +int udf_fsync_file(struct file * file, struct dentry *dentry, int datasync) { - int wait, err = 0; struct inode *inode = dentry->d_inode; + return udf_fsync_inode(inode, datasync); +} + +int udf_fsync_inode(struct inode *inode, int datasync) +{ + int err; + + err = fsync_inode_buffers(inode); + if (!(inode->i_state & I_DIRTY)) + return err; + if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) + return err; - lock_kernel(); - if (S_ISLNK(inode->i_mode) && !(inode->i_blocks)) - { - /* - * Don't sync fast links! or ICB_FLAG_AD_IN_ICB - */ - goto skip; - } - - err = generic_buffer_fdatasync(inode, 0, ~0UL); - - for (wait=0; wait<=1; wait++) - { - err |= sync_all_extents (inode, wait); - } -skip: err |= udf_sync_inode (inode); - unlock_kernel(); return err ? -EIO : 0; } diff -u --recursive --new-file v2.4.5/linux/fs/udf/ialloc.c linux/fs/udf/ialloc.c --- v2.4.5/linux/fs/udf/ialloc.c Fri Nov 17 11:35:27 2000 +++ linux/fs/udf/ialloc.c Mon Jul 2 14:10:02 2001 @@ -7,7 +7,7 @@ * CONTACTS * E-mail regarding any portion of the Linux UDF file system should be * directed to the development team mailing list (run by majordomo): - * linux_udf@hootie.lvld.hp.com + * linux_udf@hpesjro.fc.hp.com * * COPYRIGHT * This file is distributed under the terms of the GNU General Public @@ -79,6 +79,7 @@ sb = dir->i_sb; inode = new_inode(sb); + if (!inode) { *err = -ENOMEM; @@ -114,7 +115,8 @@ } inode->i_mode = mode; inode->i_uid = current->fsuid; - if (dir->i_mode & S_ISGID) { + if (dir->i_mode & S_ISGID) + { inode->i_gid = dir->i_gid; if (S_ISDIR(mode)) mode |= S_ISGID; @@ -142,8 +144,10 @@ UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_SHORT; else UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG; - inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; - UDF_I_UMTIME(inode) = UDF_I_UATIME(inode) = UDF_I_UCTIME(inode) = CURRENT_UTIME; + inode->i_mtime = inode->i_atime = inode->i_ctime = + UDF_I_CRTIME(inode) = CURRENT_TIME; + UDF_I_UMTIME(inode) = UDF_I_UCTIME(inode) = + UDF_I_UCRTIME(inode) = CURRENT_UTIME; UDF_I_NEW_INODE(inode) = 1; insert_inode_hash(inode); mark_inode_dirty(inode); diff -u --recursive --new-file v2.4.5/linux/fs/udf/inode.c linux/fs/udf/inode.c --- v2.4.5/linux/fs/udf/inode.c Sun Jan 28 13:28:09 2001 +++ linux/fs/udf/inode.c Mon Jul 2 14:10:02 2001 @@ -7,7 +7,7 @@ * CONTACTS * E-mail regarding any portion of the Linux UDF file system should be * directed to the development team mailing list (run by majordomo): - * linux_udf@hootie.lvld.hp.com + * linux_udf@hpesjro.fc.hp.com * * COPYRIGHT * This file is distributed under the terms of the GNU General Public @@ -106,23 +106,27 @@ lock_kernel(); if (is_bad_inode(inode)) - { - clear_inode(inode); - goto out; - } + goto no_delete; inode->i_size = 0; udf_truncate(inode); udf_update_inode(inode, IS_SYNC(inode)); udf_free_inode(inode); -out: + unlock_kernel(); + return; +no_delete: + unlock_kernel(); + clear_inode(inode); } void udf_discard_prealloc(struct inode * inode) { - if (inode->i_size && UDF_I_ALLOCTYPE(inode) != ICB_FLAG_AD_IN_ICB) - udf_trunc(inode); + if (inode->i_size && inode->i_size != UDF_I_LENEXTENTS(inode) && + UDF_I_ALLOCTYPE(inode) != ICB_FLAG_AD_IN_ICB) + { + udf_truncate_extents(inode); + } } static int udf_writepage(struct page *page) @@ -146,18 +150,19 @@ } struct address_space_operations udf_aops = { - readpage: udf_readpage, - writepage: udf_writepage, + readpage: udf_readpage, + writepage: udf_writepage, sync_page: block_sync_page, prepare_write: udf_prepare_write, commit_write: generic_commit_write, - bmap: udf_bmap, + bmap: udf_bmap, }; void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err) { struct buffer_head *bh = NULL; struct page *page; + char *kaddr; int block; /* from now on we have normal address_space methods */ @@ -182,7 +187,7 @@ PAGE_BUG(page); if (!Page_Uptodate(page)) { - char *kaddr = kmap(page); + kaddr = kmap(page); memset(kaddr + UDF_I_LENALLOC(inode), 0x00, PAGE_CACHE_SIZE - UDF_I_LENALLOC(inode)); memcpy(kaddr, bh->b_data + udf_file_entry_alloc_offset(inode), @@ -198,8 +203,7 @@ UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_SHORT; else UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG; - inode->i_blocks = inode->i_sb->s_blocksize / 512; - mark_buffer_dirty(bh); + mark_buffer_dirty_inode(bh, inode); udf_release_data(bh); inode->i_data.a_ops->writepage(page); @@ -245,9 +249,14 @@ sbh = udf_tread(inode->i_sb, inode->i_ino, inode->i_sb->s_blocksize); if (!sbh) return NULL; - dbh = udf_tread(inode->i_sb, newblock, inode->i_sb->s_blocksize); + dbh = udf_tgetblk(inode->i_sb, newblock, inode->i_sb->s_blocksize); if (!dbh) return NULL; + lock_buffer(dbh); + memset(dbh->b_data, 0x00, inode->i_sb->s_blocksize); + mark_buffer_uptodate(dbh, 1); + unlock_buffer(dbh); + mark_buffer_dirty_inode(dbh, inode); sfibh.soffset = sfibh.eoffset = (f_pos & ((inode->i_sb->s_blocksize - 1) >> 2)) << 2; sfibh.sbh = sfibh.ebh = sbh; @@ -266,7 +275,7 @@ dfibh.soffset = dfibh.eoffset; dfibh.eoffset += (sfibh.eoffset - sfibh.soffset); dfi = (struct FileIdentDesc *)(dbh->b_data + dfibh.soffset); - if (udf_write_fi(sfi, dfi, &dfibh, sfi->impUse, + if (udf_write_fi(inode, sfi, dfi, &dfibh, sfi->impUse, sfi->fileIdent + sfi->lengthOfImpUse)) { udf_release_data(sbh); @@ -274,7 +283,7 @@ return NULL; } } - mark_buffer_dirty(dbh); + mark_buffer_dirty_inode(dbh, inode); memset(sbh->b_data + udf_file_entry_alloc_offset(inode), 0, UDF_I_LENALLOC(inode)); @@ -288,6 +297,7 @@ eloc.logicalBlockNum = *block; eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum; elen = inode->i_size; + UDF_I_LENEXTENTS(inode) = elen; extoffset = udf_file_entry_alloc_offset(inode); udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &sbh, 0); /* UniqueID stuff */ @@ -361,23 +371,21 @@ int create, int * err) { struct buffer_head dummy; - int error; dummy.b_state = 0; dummy.b_blocknr = -1000; - error = udf_get_block(inode, block, &dummy, create); - *err = error; - if (!error & buffer_mapped(&dummy)) + *err = udf_get_block(inode, block, &dummy, create); + if (!*err && buffer_mapped(&dummy)) { struct buffer_head *bh; bh = getblk(dummy.b_dev, dummy.b_blocknr, inode->i_sb->s_blocksize); if (buffer_new(&dummy)) { - if (!buffer_uptodate(bh)) - wait_on_buffer(bh); + lock_buffer(bh); memset(bh->b_data, 0x00, inode->i_sb->s_blocksize); mark_buffer_uptodate(bh, 1); - mark_buffer_dirty(bh); + unlock_buffer(bh); + mark_buffer_dirty_inode(bh, inode); } return bh; } @@ -387,22 +395,22 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block, int *err, long *phys, int *new) { - struct buffer_head *pbh = NULL, *cbh = NULL, *result = NULL; + struct buffer_head *pbh = NULL, *cbh = NULL, *nbh = NULL, *result = NULL; long_ad laarr[EXTENT_MERGE_SIZE]; Uint32 pextoffset = 0, cextoffset = 0, nextoffset = 0; int count = 0, startnum = 0, endnum = 0; Uint32 elen = 0; - lb_addr eloc, pbloc = UDF_I_LOCATION(inode), cbloc = UDF_I_LOCATION(inode); + lb_addr eloc, pbloc, cbloc, nbloc; int c = 1; int lbcount = 0, b_off = 0, offset = 0; Uint32 newblocknum, newblock; - int etype; + char etype; int goal = 0, pgoal = UDF_I_LOCATION(inode).logicalBlockNum; char lastblock = 0; pextoffset = cextoffset = nextoffset = udf_file_entry_alloc_offset(inode); b_off = block << inode->i_sb->s_blocksize_bits; - pbloc = cbloc = UDF_I_LOCATION(inode); + pbloc = cbloc = nbloc = UDF_I_LOCATION(inode); /* find the extent which contains the block we are looking for. alternate between laarr[0] and laarr[1] for locations of the @@ -412,17 +420,25 @@ if (pbh != cbh) { udf_release_data(pbh); - pbh = cbh; atomic_inc(&cbh->b_count); - pbloc = cbloc; + pbh = cbh; + } + if (cbh != nbh) + { + udf_release_data(cbh); + atomic_inc(&nbh->b_count); + cbh = nbh; } lbcount += elen; + pbloc = cbloc; + cbloc = nbloc; + pextoffset = cextoffset; cextoffset = nextoffset; - if ((etype = udf_next_aext(inode, &cbloc, &nextoffset, &eloc, &elen, &cbh, 1)) == -1) + if ((etype = udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) == -1) break; c = !c; @@ -433,7 +449,7 @@ if (etype != EXTENT_NOT_RECORDED_NOT_ALLOCATED) pgoal = eloc.logicalBlockNum + ((elen + inode->i_sb->s_blocksize - 1) >> - inode->i_sb->s_blocksize); + inode->i_sb->s_blocksize_bits); count ++; } while (lbcount + elen <= b_off); @@ -451,10 +467,11 @@ elen = (EXTENT_RECORDED_ALLOCATED << 30) | ((elen + inode->i_sb->s_blocksize - 1) & ~(inode->i_sb->s_blocksize - 1)); - etype = udf_write_aext(inode, cbloc, &cextoffset, eloc, elen, &cbh, 1); + etype = udf_write_aext(inode, nbloc, &cextoffset, eloc, elen, nbh, 1); } udf_release_data(pbh); udf_release_data(cbh); + udf_release_data(nbh); newblock = udf_get_lb_pblock(inode->i_sb, eloc, offset); *phys = newblock; return NULL; @@ -470,6 +487,9 @@ (((laarr[c].extLength & UDF_EXTENT_LENGTH_MASK) + inode->i_sb->s_blocksize - 1) & ~(inode->i_sb->s_blocksize - 1)); + UDF_I_LENEXTENTS(inode) = + (UDF_I_LENEXTENTS(inode) + inode->i_sb->s_blocksize - 1) & + ~(inode->i_sb->s_blocksize - 1); } c = !c; laarr[c].extLength = (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30) | @@ -494,7 +514,7 @@ /* if the current block is located in a extent, read the next extent */ if (etype != -1) { - if ((etype = udf_next_aext(inode, &cbloc, &nextoffset, &eloc, &elen, &cbh, 0)) != -1) + if ((etype = udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 0)) != -1) { laarr[c+1].extLength = (etype << 30) | elen; laarr[c+1].extLocation = eloc; @@ -505,7 +525,11 @@ else lastblock = 1; } - udf_release_data(cbh); + udf_release_data(nbh); + if (!pbh) + pbh = cbh; + else + udf_release_data(cbh); /* if the current extent is not recorded but allocated, get the block in the extent corresponding to the requested block */ @@ -529,6 +553,7 @@ *err = -ENOSPC; return NULL; } + UDF_I_LENEXTENTS(inode) += inode->i_sb->s_blocksize; } /* if the extent the requsted block is located in contains multiple blocks, @@ -629,17 +654,24 @@ { int start, length = 0, currlength = 0, i; - if (*endnum >= (c+1) && !lastblock) - return; - - if ((laarr[c+1].extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED) + if (*endnum >= (c+1)) { - start = c+1; - length = currlength = (((laarr[c+1].extLength & UDF_EXTENT_LENGTH_MASK) + - inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits); + if (!lastblock) + return; + else + start = c; } else - start = c; + { + if ((laarr[c+1].extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED) + { + start = c+1; + length = currlength = (((laarr[c+1].extLength & UDF_EXTENT_LENGTH_MASK) + + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits); + } + else + start = c; + } for (i=start+1; i<=*endnum; i++) { @@ -667,6 +699,7 @@ if (numalloc) { + UDF_I_LENEXTENTS(inode) += numalloc << inode->i_sb->s_blocksize_bits; if (start == (c+1)) laarr[start].extLength += (numalloc << inode->i_sb->s_blocksize_bits); @@ -784,7 +817,7 @@ { udf_next_aext(inode, &pbloc, &pextoffset, &tmploc, &tmplen, pbh, 0); udf_write_aext(inode, pbloc, &pextoffset, laarr[i].extLocation, - laarr[i].extLength, pbh, 1); + laarr[i].extLength, *pbh, 1); } } @@ -800,29 +833,6 @@ if (!bh) return NULL; -#if 0 - if (create && - S_ISDIR(inode->i_mode) && - inode->i_blocks > prev_blocks) - { - int i; - struct buffer_head *tmp_bh = NULL; - - for (i=1; - i < UDF_DEFAULT_PREALLOC_DIR_BLOCKS; - i++) - { - tmp_bh = udf_getblk(inode, block+i, create, err); - if (!tmp_bh) - { - udf_release_data(bh); - return 0; - } - udf_release_data(tmp_bh); - } - } -#endif - if (buffer_uptodate(bh)) return bh; ll_rw_block(READ, 1, &bh); @@ -834,6 +844,62 @@ return NULL; } +void udf_truncate(struct inode * inode) +{ + int offset; + struct buffer_head *bh; + int err; + + if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || + S_ISLNK(inode->i_mode))) + return; + if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) + return; + + if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB) + { + if (inode->i_sb->s_blocksize < (udf_file_entry_alloc_offset(inode) + + inode->i_size)) + { + udf_expand_file_adinicb(inode, inode->i_size, &err); + if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB) + { + inode->i_size = UDF_I_LENALLOC(inode); + return; + } + else + udf_truncate_extents(inode); + } + else + { + offset = (inode->i_size & (inode->i_sb->s_blocksize - 1)) + + udf_file_entry_alloc_offset(inode); + + if ((bh = udf_tread(inode->i_sb, + udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0), + inode->i_sb->s_blocksize))) + { + memset(bh->b_data + offset, 0x00, inode->i_sb->s_blocksize - offset); + mark_buffer_dirty(bh); + udf_release_data(bh); + } + UDF_I_LENALLOC(inode) = inode->i_size; + } + } + else + { + block_truncate_page(inode->i_mapping, inode->i_size, udf_get_block); + udf_truncate_extents(inode); + } + + inode->i_mtime = inode->i_ctime = CURRENT_TIME; + UDF_I_UMTIME(inode) = UDF_I_UCTIME(inode) = CURRENT_UTIME; + if (IS_SYNC(inode)) + udf_sync_inode (inode); + else + mark_inode_dirty(inode); +} + /* * udf_read_inode * @@ -891,7 +957,8 @@ return; } - if (ident != TID_FILE_ENTRY && ident != TID_EXTENDED_FILE_ENTRY) + if (ident != TID_FILE_ENTRY && ident != TID_EXTENDED_FILE_ENTRY && + ident != TID_UNALLOCATED_SPACE_ENTRY) { printk(KERN_ERR "udf: udf_read_inode(ino %ld) failed ident=%d\n", inode->i_ino, ident); @@ -969,16 +1036,24 @@ fe = (struct FileEntry *)bh->b_data; efe = (struct ExtendedFileEntry *)bh->b_data; - if (fe->descTag.tagIdent == TID_EXTENDED_FILE_ENTRY) - UDF_I_EXTENDED_FE(inode) = 1; - else /* fe->descTag.tagIdent == TID_FILE_ENTRY */ - UDF_I_EXTENDED_FE(inode) = 0; - if (le16_to_cpu(fe->icbTag.strategyType) == 4) UDF_I_STRAT4096(inode) = 0; else /* if (le16_to_cpu(fe->icbTag.strategyType) == 4096) */ UDF_I_STRAT4096(inode) = 1; + UDF_I_ALLOCTYPE(inode) = le16_to_cpu(fe->icbTag.flags) & ICB_FLAG_ALLOC_MASK; + if (fe->descTag.tagIdent == TID_EXTENDED_FILE_ENTRY) + UDF_I_EXTENDED_FE(inode) = 1; + else if (fe->descTag.tagIdent == TID_FILE_ENTRY) + UDF_I_EXTENDED_FE(inode) = 0; + else if (fe->descTag.tagIdent == TID_UNALLOCATED_SPACE_ENTRY) + { + UDF_I_LENALLOC(inode) = + le32_to_cpu( + ((struct UnallocatedSpaceEntry *)bh->b_data)->lengthAllocDescs); + return; + } + inode->i_uid = le32_to_cpu(fe->uid); if ( inode->i_uid == -1 ) inode->i_uid = UDF_SB(inode->i_sb)->s_uid; @@ -990,6 +1065,7 @@ inode->i_nlink = 1; inode->i_size = le64_to_cpu(fe->informationLength); + UDF_I_LENEXTENTS(inode) = inode->i_size; inode->i_mode = udf_convert_permissions(fe); inode->i_mode &= ~UDF_SB(inode->i_sb)->s_umask; @@ -997,39 +1073,43 @@ UDF_I_NEXT_ALLOC_BLOCK(inode) = 0; UDF_I_NEXT_ALLOC_GOAL(inode) = 0; - UDF_I_ALLOCTYPE(inode) = le16_to_cpu(fe->icbTag.flags) & ICB_FLAG_ALLOC_MASK; - if (UDF_I_EXTENDED_FE(inode) == 0) { inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) << (inode->i_sb->s_blocksize_bits - 9); if ( udf_stamp_to_time(&convtime, &convtime_usec, + lets_to_cpu(fe->accessTime)) ) + { + inode->i_atime = convtime; + } + else + { + inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb); + } + + if ( udf_stamp_to_time(&convtime, &convtime_usec, lets_to_cpu(fe->modificationTime)) ) { inode->i_mtime = convtime; UDF_I_UMTIME(inode) = convtime_usec; - inode->i_ctime = convtime; - UDF_I_UCTIME(inode) = convtime_usec; } else { inode->i_mtime = UDF_SB_RECORDTIME(inode->i_sb); UDF_I_UMTIME(inode) = 0; - inode->i_ctime = UDF_SB_RECORDTIME(inode->i_sb); - UDF_I_UCTIME(inode) = 0; } if ( udf_stamp_to_time(&convtime, &convtime_usec, - lets_to_cpu(fe->accessTime)) ) + lets_to_cpu(fe->attrTime)) ) { - inode->i_atime = convtime; - UDF_I_UATIME(inode) = convtime_usec; + inode->i_ctime = convtime; + UDF_I_UCTIME(inode) = convtime_usec; } else { - inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb); - UDF_I_UATIME(inode) = convtime_usec; + inode->i_ctime = UDF_SB_RECORDTIME(inode->i_sb); + UDF_I_UCTIME(inode) = 0; } UDF_I_UNIQUE(inode) = le64_to_cpu(fe->uniqueID); @@ -1044,6 +1124,16 @@ (inode->i_sb->s_blocksize_bits - 9); if ( udf_stamp_to_time(&convtime, &convtime_usec, + lets_to_cpu(efe->accessTime)) ) + { + inode->i_atime = convtime; + } + else + { + inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb); + } + + if ( udf_stamp_to_time(&convtime, &convtime_usec, lets_to_cpu(efe->modificationTime)) ) { inode->i_mtime = convtime; @@ -1056,19 +1146,19 @@ } if ( udf_stamp_to_time(&convtime, &convtime_usec, - lets_to_cpu(efe->accessTime)) ) + lets_to_cpu(efe->createTime)) ) { - inode->i_atime = convtime; - UDF_I_UATIME(inode) = convtime_usec; + UDF_I_CRTIME(inode) = convtime; + UDF_I_UCRTIME(inode) = convtime_usec; } else { - inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb); - UDF_I_UATIME(inode) = 0; + UDF_I_CRTIME(inode) = UDF_SB_RECORDTIME(inode->i_sb); + UDF_I_UCRTIME(inode) = 0; } if ( udf_stamp_to_time(&convtime, &convtime_usec, - lets_to_cpu(efe->createTime)) ) + lets_to_cpu(efe->attrTime)) ) { inode->i_ctime = convtime; UDF_I_UCTIME(inode) = convtime_usec; @@ -1096,6 +1186,7 @@ inode->i_nlink ++; break; } + case FILE_TYPE_REALTIME: case FILE_TYPE_REGULAR: case FILE_TYPE_NONE: { @@ -1171,11 +1262,11 @@ flags = le16_to_cpu(fe->icbTag.flags); mode = (( permissions ) & S_IRWXO) | - (( permissions >> 2 ) & S_IRWXG) | - (( permissions >> 4 ) & S_IRWXU) | - (( flags & ICB_FLAG_SETUID) ? S_ISUID : 0) | - (( flags & ICB_FLAG_SETGID) ? S_ISGID : 0) | - (( flags & ICB_FLAG_STICKY) ? S_ISVTX : 0); + (( permissions >> 2 ) & S_IRWXG) | + (( permissions >> 4 ) & S_IRWXU) | + (( flags & ICB_FLAG_SETUID) ? S_ISUID : 0) | + (( flags & ICB_FLAG_SETGID) ? S_ISGID : 0) | + (( flags & ICB_FLAG_STICKY) ? S_ISVTX : 0); return mode; } @@ -1221,8 +1312,9 @@ int err = 0; bh = udf_tread(inode->i_sb, - udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0), - inode->i_sb->s_blocksize); + udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0), + inode->i_sb->s_blocksize); + if (!bh) { udf_debug("bread failure\n"); @@ -1233,7 +1325,7 @@ if (UDF_I_NEW_INODE(inode) == 1) { if (UDF_I_EXTENDED_FE(inode) == 0) - memset(bh->b_data, 0x0, sizeof(struct FileEntry)); + memset(bh->b_data, 0x00, sizeof(struct FileEntry)); else memset(bh->b_data, 0x00, sizeof(struct ExtendedFileEntry)); memset(bh->b_data + udf_file_entry_alloc_offset(inode) + @@ -1242,20 +1334,41 @@ UDF_I_NEW_INODE(inode) = 0; } + if (fe->descTag.tagIdent == TID_UNALLOCATED_SPACE_ENTRY) + { + struct UnallocatedSpaceEntry *use = + (struct UnallocatedSpaceEntry *)bh->b_data; + + use->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode)); + crclen = sizeof(struct UnallocatedSpaceEntry) + UDF_I_LENALLOC(inode) - + sizeof(tag); + use->descTag.descCRCLength = cpu_to_le16(crclen); + use->descTag.descCRC = cpu_to_le16(udf_crc((char *)use + sizeof(tag), crclen, 0)); + + use->descTag.tagChecksum = 0; + for (i=0; i<16; i++) + if (i != 4) + use->descTag.tagChecksum += ((Uint8 *)&(use->descTag))[i]; + + mark_buffer_dirty(bh); + udf_release_data(bh); + return err; + } + if (inode->i_uid != UDF_SB(inode->i_sb)->s_uid) fe->uid = cpu_to_le32(inode->i_uid); if (inode->i_gid != UDF_SB(inode->i_sb)->s_gid) fe->gid = cpu_to_le32(inode->i_gid); - udfperms = ((inode->i_mode & S_IRWXO) ) | - ((inode->i_mode & S_IRWXG) << 2) | - ((inode->i_mode & S_IRWXU) << 4); - - udfperms |= (le32_to_cpu(fe->permissions) & - (PERM_O_DELETE | PERM_O_CHATTR | - PERM_G_DELETE | PERM_G_CHATTR | - PERM_U_DELETE | PERM_U_CHATTR)); + udfperms = ((inode->i_mode & S_IRWXO) ) | + ((inode->i_mode & S_IRWXG) << 2) | + ((inode->i_mode & S_IRWXU) << 4); + + udfperms |= (le32_to_cpu(fe->permissions) & + (PERM_O_DELETE | PERM_O_CHATTR | + PERM_G_DELETE | PERM_G_CHATTR | + PERM_U_DELETE | PERM_U_CHATTR)); fe->permissions = cpu_to_le32(udfperms); if (S_ISDIR(inode->i_mode)) @@ -1292,7 +1405,7 @@ eid->identSuffix[1] = UDF_OS_ID_LINUX; dsea->majorDeviceIdent = kdev_t_to_nr(inode->i_rdev) >> 8; dsea->minorDeviceIdent = kdev_t_to_nr(inode->i_rdev) & 0xFF; - mark_buffer_dirty(tbh); + mark_buffer_dirty_inode(tbh, inode); udf_release_data(tbh); } @@ -1302,10 +1415,12 @@ (inode->i_blocks + (1 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >> (inode->i_sb->s_blocksize_bits - 9)); - if (udf_time_to_stamp(&cpu_time, inode->i_atime, UDF_I_UATIME(inode))) + if (udf_time_to_stamp(&cpu_time, inode->i_atime, 0)) fe->accessTime = cpu_to_lets(cpu_time); if (udf_time_to_stamp(&cpu_time, inode->i_mtime, UDF_I_UMTIME(inode))) fe->modificationTime = cpu_to_lets(cpu_time); + if (udf_time_to_stamp(&cpu_time, inode->i_ctime, UDF_I_UCTIME(inode))) + fe->attrTime = cpu_to_lets(cpu_time); memset(&(fe->impIdent), 0, sizeof(EntityID)); strcpy(fe->impIdent.ident, UDF_ID_DEVELOPER); fe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; @@ -1318,16 +1433,40 @@ } else { + efe->objectSize = cpu_to_le64(inode->i_size); efe->logicalBlocksRecorded = cpu_to_le64( - (inode->i_blocks + (2 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >> + (inode->i_blocks + (1 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >> (inode->i_sb->s_blocksize_bits - 9)); - if (udf_time_to_stamp(&cpu_time, inode->i_atime, UDF_I_UATIME(inode))) + if (UDF_I_CRTIME(inode) >= inode->i_atime) + { + UDF_I_CRTIME(inode) = inode->i_atime; + UDF_I_UCRTIME(inode) = 0; + } + if (UDF_I_CRTIME(inode) > inode->i_mtime || + (UDF_I_CRTIME(inode) == inode->i_mtime && + UDF_I_UCRTIME(inode) > UDF_I_UMTIME(inode))) + { + UDF_I_CRTIME(inode) = inode->i_mtime; + UDF_I_UCRTIME(inode) = UDF_I_UMTIME(inode); + } + if (UDF_I_CRTIME(inode) > inode->i_ctime || + (UDF_I_CRTIME(inode) == inode->i_ctime && + UDF_I_UCRTIME(inode) > UDF_I_UCTIME(inode))) + { + UDF_I_CRTIME(inode) = inode->i_ctime; + UDF_I_UCRTIME(inode) = UDF_I_UCTIME(inode); + } + + if (udf_time_to_stamp(&cpu_time, inode->i_atime, 0)) efe->accessTime = cpu_to_lets(cpu_time); if (udf_time_to_stamp(&cpu_time, inode->i_mtime, UDF_I_UMTIME(inode))) efe->modificationTime = cpu_to_lets(cpu_time); - if (udf_time_to_stamp(&cpu_time, inode->i_ctime, UDF_I_UCTIME(inode))) + if (udf_time_to_stamp(&cpu_time, UDF_I_CRTIME(inode), UDF_I_UCRTIME(inode))) efe->createTime = cpu_to_lets(cpu_time); + if (udf_time_to_stamp(&cpu_time, inode->i_ctime, UDF_I_UCTIME(inode))) + efe->attrTime = cpu_to_lets(cpu_time); + memset(&(efe->impIdent), 0, sizeof(EntityID)); strcpy(efe->impIdent.ident, UDF_ID_DEVELOPER); efe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; @@ -1363,7 +1502,7 @@ else if (S_ISFIFO(inode->i_mode)) fe->icbTag.fileType = FILE_TYPE_FIFO; - icbflags = UDF_I_ALLOCTYPE(inode) | + icbflags = UDF_I_ALLOCTYPE(inode) | ((inode->i_mode & S_ISUID) ? ICB_FLAG_SETUID : 0) | ((inode->i_mode & S_ISGID) ? ICB_FLAG_SETGID : 0) | ((inode->i_mode & S_ISVTX) ? ICB_FLAG_STICKY : 0) | @@ -1444,12 +1583,19 @@ { memcpy(&UDF_I_LOCATION(inode), &ino, sizeof(lb_addr)); __udf_read_inode(inode); + if (is_bad_inode(inode)) + { + iput(inode); + return NULL; + } } if ( ino.logicalBlockNum >= UDF_SB_PARTLEN(sb, ino.partitionReferenceNum) ) { udf_debug("block=%d, partition=%d out of range\n", ino.logicalBlockNum, ino.partitionReferenceNum); + make_bad_inode(inode); + iput(inode); return NULL; } @@ -1496,13 +1642,20 @@ { return -1; } - if (!(nbh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, + if (!(nbh = udf_tgetblk(inode->i_sb, udf_get_lb_pblock(inode->i_sb, *bloc, 0), inode->i_sb->s_blocksize))) { return -1; } + lock_buffer(nbh); + memset(nbh->b_data, 0x00, inode->i_sb->s_blocksize); + mark_buffer_uptodate(nbh, 1); + unlock_buffer(nbh); + mark_buffer_dirty_inode(nbh, inode); + aed = (struct AllocExtDesc *)(nbh->b_data); - aed->previousAllocExtLocation = cpu_to_le32(obloc.logicalBlockNum); + if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT)) + aed->previousAllocExtLocation = cpu_to_le32(obloc.logicalBlockNum); if (*extoffset + adsize > inode->i_sb->s_blocksize) { loffset = *extoffset; @@ -1551,16 +1704,20 @@ EXTENT_NEXT_EXTENT_ALLOCDECS << 30 | inode->i_sb->s_blocksize); lad->extLocation = cpu_to_lelb(*bloc); + memset(lad->impUse, 0x00, sizeof(lad->impUse)); break; } } - udf_update_tag((*bh)->b_data, loffset); - mark_buffer_dirty(*bh); + if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201) + udf_update_tag((*bh)->b_data, loffset); + else + udf_update_tag((*bh)->b_data, sizeof(struct AllocExtDesc)); + mark_buffer_dirty_inode(*bh, inode); udf_release_data(*bh); *bh = nbh; } - ret = udf_write_aext(inode, *bloc, extoffset, eloc, elen, bh, inc); + ret = udf_write_aext(inode, *bloc, extoffset, eloc, elen, *bh, inc); if (!memcmp(&UDF_I_LOCATION(inode), bloc, sizeof(lb_addr))) { @@ -1572,23 +1729,26 @@ aed = (struct AllocExtDesc *)(*bh)->b_data; aed->lengthAllocDescs = cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize); - udf_update_tag((*bh)->b_data, *extoffset + (inc ? 0 : adsize)); - mark_buffer_dirty(*bh); + if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201) + udf_update_tag((*bh)->b_data, *extoffset + (inc ? 0 : adsize)); + else + udf_update_tag((*bh)->b_data, sizeof(struct AllocExtDesc)); + mark_buffer_dirty_inode(*bh, inode); } return ret; } int udf_write_aext(struct inode *inode, lb_addr bloc, int *extoffset, - lb_addr eloc, Uint32 elen, struct buffer_head **bh, int inc) + lb_addr eloc, Uint32 elen, struct buffer_head *bh, int inc) { int adsize; short_ad *sad = NULL; long_ad *lad = NULL; - if (!(*bh)) + if (!(bh)) { - if (!(*bh = udf_tread(inode->i_sb, + if (!(bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, bloc, 0), inode->i_sb->s_blocksize))) { @@ -1597,6 +1757,8 @@ return -1; } } + else + atomic_inc(&bh->b_count); if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_SHORT) adsize = sizeof(short_ad); @@ -1609,39 +1771,47 @@ { case ICB_FLAG_AD_SHORT: { - sad = (short_ad *)((*bh)->b_data + *extoffset); + sad = (short_ad *)((bh)->b_data + *extoffset); sad->extLength = cpu_to_le32(elen); sad->extPosition = cpu_to_le32(eloc.logicalBlockNum); break; } case ICB_FLAG_AD_LONG: { - lad = (long_ad *)((*bh)->b_data + *extoffset); + lad = (long_ad *)((bh)->b_data + *extoffset); lad->extLength = cpu_to_le32(elen); lad->extLocation = cpu_to_lelb(eloc); + memset(lad->impUse, 0x00, sizeof(lad->impUse)); break; } } if (memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr))) { - struct AllocExtDesc *aed = (struct AllocExtDesc *)(*bh)->b_data; - udf_update_tag((*bh)->b_data, - le32_to_cpu(aed->lengthAllocDescs) + sizeof(struct AllocExtDesc)); + if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201) + { + struct AllocExtDesc *aed = (struct AllocExtDesc *)(bh)->b_data; + udf_update_tag((bh)->b_data, + le32_to_cpu(aed->lengthAllocDescs) + sizeof(struct AllocExtDesc)); + } + mark_buffer_dirty_inode(bh, inode); } else + { mark_inode_dirty(inode); - - mark_buffer_dirty(*bh); + mark_buffer_dirty(bh); + } if (inc) *extoffset += adsize; + udf_release_data(bh); return (elen >> 30); } int udf_next_aext(struct inode *inode, lb_addr *bloc, int *extoffset, lb_addr *eloc, Uint32 *elen, struct buffer_head **bh, int inc) { + Uint16 tagIdent; int pos, alen; Uint8 etype; @@ -1657,18 +1827,33 @@ } } + tagIdent = ((tag *)(*bh)->b_data)->tagIdent; + if (!memcmp(&UDF_I_LOCATION(inode), bloc, sizeof(lb_addr))) { - pos = udf_file_entry_alloc_offset(inode); - alen = UDF_I_LENALLOC(inode) + pos; + if (tagIdent == TID_FILE_ENTRY || tagIdent == TID_EXTENDED_FILE_ENTRY || + UDF_I_NEW_INODE(inode)) + { + pos = udf_file_entry_alloc_offset(inode); + alen = UDF_I_LENALLOC(inode) + pos; + } + else if (tagIdent == TID_UNALLOCATED_SPACE_ENTRY) + { + pos = sizeof(struct UnallocatedSpaceEntry); + alen = UDF_I_LENALLOC(inode) + pos; + } + else + return -1; } - else + else if (tagIdent == TID_ALLOC_EXTENT_DESC) { struct AllocExtDesc *aed = (struct AllocExtDesc *)(*bh)->b_data; pos = sizeof(struct AllocExtDesc); alen = le32_to_cpu(aed->lengthAllocDescs) + pos; } + else + return -1; if (!(*extoffset)) *extoffset = pos; @@ -1829,7 +2014,7 @@ } int udf_insert_aext(struct inode *inode, lb_addr bloc, int extoffset, - lb_addr neloc, Uint32 nelen, struct buffer_head *bh) + lb_addr neloc, Uint32 nelen, struct buffer_head *bh) { lb_addr oeloc; Uint32 oelen; @@ -1851,7 +2036,7 @@ while ((type = udf_next_aext(inode, &bloc, &extoffset, &oeloc, &oelen, &bh, 0)) != -1) { - udf_write_aext(inode, bloc, &extoffset, neloc, nelen, &bh, 1); + udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 1); neloc = oeloc; nelen = (type << 30) | oelen; @@ -1867,7 +2052,7 @@ struct buffer_head *obh; lb_addr obloc; int oextoffset, adsize; - int type; + char type; struct AllocExtDesc *aed; if (!(nbh)) @@ -1901,7 +2086,7 @@ while ((type = udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1) { - udf_write_aext(inode, obloc, &oextoffset, eloc, (type << 30) | elen, &obh, 1); + udf_write_aext(inode, obloc, &oextoffset, eloc, (type << 30) | elen, obh, 1); if (memcmp(&nbloc, &obloc, sizeof(lb_addr))) { obloc = nbloc; @@ -1917,8 +2102,8 @@ if (memcmp(&nbloc, &obloc, sizeof(lb_addr))) { udf_free_blocks(inode, nbloc, 0, 1); - udf_write_aext(inode, obloc, &oextoffset, eloc, elen, &obh, 1); - udf_write_aext(inode, obloc, &oextoffset, eloc, elen, &obh, 1); + udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1); + udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1); if (!memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr))) { UDF_I_LENALLOC(inode) -= (adsize * 2); @@ -1929,13 +2114,16 @@ aed = (struct AllocExtDesc *)(obh)->b_data; aed->lengthAllocDescs = cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) - (2*adsize)); - udf_update_tag((obh)->b_data, oextoffset - (2*adsize)); - mark_buffer_dirty(obh); + if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201) + udf_update_tag((obh)->b_data, oextoffset - (2*adsize)); + else + udf_update_tag((obh)->b_data, sizeof(struct AllocExtDesc)); + mark_buffer_dirty_inode(obh, inode); } } else { - udf_write_aext(inode, obloc, &oextoffset, eloc, elen, &obh, 1); + udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1); if (!memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr))) { UDF_I_LENALLOC(inode) -= adsize; @@ -1946,8 +2134,11 @@ aed = (struct AllocExtDesc *)(obh)->b_data; aed->lengthAllocDescs = cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) - adsize); - udf_update_tag((obh)->b_data, oextoffset - adsize); - mark_buffer_dirty(obh); + if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201) + udf_update_tag((obh)->b_data, oextoffset - adsize); + else + udf_update_tag((obh)->b_data, sizeof(struct AllocExtDesc)); + mark_buffer_dirty_inode(obh, inode); } } @@ -1959,7 +2150,8 @@ int inode_bmap(struct inode *inode, int block, lb_addr *bloc, Uint32 *extoffset, lb_addr *eloc, Uint32 *elen, Uint32 *offset, struct buffer_head **bh) { - int etype, lbcount = 0; + Uint64 lbcount = 0, bcount = block << inode->i_sb->s_blocksize_bits; + char etype; if (block < 0) { @@ -1980,31 +2172,34 @@ { if ((etype = udf_next_aext(inode, bloc, extoffset, eloc, elen, bh, 1)) == -1) { - *offset = block - lbcount; + *offset = bcount - lbcount; + UDF_I_LENEXTENTS(inode) = lbcount; return -1; } - lbcount += ((*elen + inode->i_sb->s_blocksize - 1) >> - inode->i_sb->s_blocksize_bits); - } while (lbcount <= block); + lbcount += *elen; + } while (lbcount <= bcount); - *offset = block + ((*elen + inode->i_sb->s_blocksize - 1) >> - inode->i_sb->s_blocksize_bits) - lbcount; + *offset = bcount + *elen - lbcount; return etype; } -long udf_locked_block_map(struct inode *inode, long block) +long udf_block_map(struct inode *inode, long block) { lb_addr eloc, bloc; Uint32 offset, extoffset, elen; struct buffer_head *bh = NULL; int ret; + lock_kernel(); + if (inode_bmap(inode, block, &bloc, &extoffset, &eloc, &elen, &offset, &bh) == EXTENT_RECORDED_ALLOCATED) - ret = udf_get_lb_pblock(inode->i_sb, eloc, offset); + ret = udf_get_lb_pblock(inode->i_sb, eloc, offset >> inode->i_sb->s_blocksize_bits); else ret = 0; + unlock_kernel(); + if (bh) udf_release_data(bh); @@ -2012,14 +2207,4 @@ return udf_fixed_to_variable(ret); else return ret; -} - -long udf_block_map(struct inode *inode, long block) -{ - int ret; - - lock_kernel(); - ret = udf_locked_block_map(inode, block); - unlock_kernel(); - return ret; } diff -u --recursive --new-file v2.4.5/linux/fs/udf/lowlevel.c linux/fs/udf/lowlevel.c --- v2.4.5/linux/fs/udf/lowlevel.c Mon Mar 20 08:17:43 2000 +++ linux/fs/udf/lowlevel.c Mon Jun 11 19:15:27 2001 @@ -7,7 +7,7 @@ * CONTACTS * E-mail regarding any portion of the Linux UDF file system should be * directed to the development team mailing list (run by majordomo): - * linux_udf@hootie.lvld.hp.com + * linux_udf@hpesjro.fc.hp.com * * COPYRIGHT * This file is distributed under the terms of the GNU General Public diff -u --recursive --new-file v2.4.5/linux/fs/udf/misc.c linux/fs/udf/misc.c --- v2.4.5/linux/fs/udf/misc.c Mon Mar 20 08:17:43 2000 +++ linux/fs/udf/misc.c Mon Jun 11 19:15:27 2001 @@ -7,7 +7,7 @@ * CONTACTS * E-mail regarding any portion of the Linux UDF file system should be * directed to the development team mailing list (run by majordomo): - * linux_udf@hootie.lvld.hp.com + * linux_udf@hpesjro.fc.hp.com * * COPYRIGHT * This file is distributed under the terms of the GNU General Public @@ -67,6 +67,15 @@ #if defined(__linux__) && defined(__KERNEL__) extern struct buffer_head * +udf_tgetblk(struct super_block *sb, int block, int size) +{ + if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV)) + return getblk(sb->s_dev, udf_fixed_to_variable(block), size); + else + return getblk(sb->s_dev, block, size); +} + +extern struct buffer_head * udf_tread(struct super_block *sb, int block, int size) { if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV)) @@ -309,7 +318,7 @@ if ( location != le32_to_cpu(tag_p->tagLocation) ) { - udf_debug("location mismatch block %d, tag %d != %d\n", + udf_debug("location mismatch block %u, tag %u != %u\n", block, le32_to_cpu(tag_p->tagLocation), location); goto error_out; } @@ -424,32 +433,35 @@ if ( size < udf_blocksize ) { - udf_errno=3; + udf_errno = 3; return -1; } - udf_errno=0; + udf_errno = 0; - offs=(long)block * udf_blocksize; - if ( lseek(fd, offs, SEEK_SET) != offs ) { - udf_errno=4; + offs = (long)block * udf_blocksize; + if ( lseek(fd, offs, SEEK_SET) != offs ) + { + udf_errno = 4; return -1; } - i=read(fd, buffer, udf_blocksize); - if ( i < udf_blocksize ) { - udf_errno=5; + i = read(fd, buffer, udf_blocksize); + if ( i < udf_blocksize ) + { + udf_errno = 5; return -1; } tag_p = (tag *)(buffer); /* Verify the tag location */ - if ((block-offset) != tag_p->tagLocation) { + if ((block-offset) != tag_p->tagLocation) + { #ifdef __KERNEL__ printk(KERN_ERR "udf: location mismatch block %d, tag %d\n", block, tag_p->tagLocation); #else - udf_errno=6; + udf_errno = 6; #endif goto error_out; } @@ -460,35 +472,38 @@ checksum += (Uint8)(buffer[i]); for (i = 5; i < 16; i++) checksum += (Uint8)(buffer[i]); - if (checksum != tag_p->tagChecksum) { + if (checksum != tag_p->tagChecksum) + { #ifdef __KERNEL__ printk(KERN_ERR "udf: tag checksum failed\n"); #else - udf_errno=7; + udf_errno = 7; #endif goto error_out; } /* Verify the tag version */ - if (tag_p->descVersion != 0x0002U) { + if (tag_p->descVersion != 0x0002U) + { #ifdef __KERNEL__ printk(KERN_ERR "udf: tag version 0x%04x != 0x0002U\n", tag_p->descVersion); #else - udf_errno=8; + udf_errno = 8; #endif goto error_out; } /* Verify the descriptor CRC */ - if (tag_p->descCRC == udf_crc(buffer + 16, tag_p->descCRCLength, 0)) { - udf_errno=0; + if (tag_p->descCRC == udf_crc(buffer + 16, tag_p->descCRCLength, 0)) + { + udf_errno = 0; return 0; } #ifdef __KERNEL__ printk(KERN_ERR "udf: crc failure in udf_read_tagged\n"); #else - udf_errno=9; + udf_errno = 9; #endif error_out: diff -u --recursive --new-file v2.4.5/linux/fs/udf/namei.c linux/fs/udf/namei.c --- v2.4.5/linux/fs/udf/namei.c Fri Feb 9 11:29:44 2001 +++ linux/fs/udf/namei.c Mon Jun 11 19:15:27 2001 @@ -7,7 +7,7 @@ * CONTACTS * E-mail regarding any portion of the Linux UDF file system should be * directed to the development team mailing list (run by majordomo): - * linux_udf@hootie.lvld.hp.com + * linux_udf@hpesjro.fc.hp.com * * COPYRIGHT * This file is distributed under the terms of the GNU General Public @@ -33,6 +33,8 @@ #include #include #include +#include +#include #include static inline int udf_match(int len, const char * const name, struct qstr *qs) @@ -42,8 +44,8 @@ return !memcmp(name, qs->name, len); } -int udf_write_fi(struct FileIdentDesc *cfi, struct FileIdentDesc *sfi, - struct udf_fileident_bh *fibh, +int udf_write_fi(struct inode *inode, struct FileIdentDesc *cfi, + struct FileIdentDesc *sfi, struct udf_fileident_bh *fibh, Uint8 *impuse, Uint8 *fileident) { Uint16 crclen = fibh->eoffset - fibh->soffset - sizeof(tag); @@ -56,7 +58,6 @@ int padlen = fibh->eoffset - fibh->soffset - liu - lfi - sizeof(struct FileIdentDesc); - offset = fibh->soffset + sizeof(struct FileIdentDesc); if (impuse) @@ -133,8 +134,8 @@ } if (fibh->sbh != fibh->ebh) - mark_buffer_dirty(fibh->ebh); - mark_buffer_dirty(fibh->sbh); + mark_buffer_dirty_inode(fibh->ebh, inode); + mark_buffer_dirty_inode(fibh->sbh, inode); return 0; } @@ -164,6 +165,7 @@ if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2), &bloc, &extoffset, &eloc, &elen, &offset, &bh) == EXTENT_RECORDED_ALLOCATED) { + offset >>= dir->i_sb->s_blocksize_bits; block = udf_get_lb_pblock(dir->i_sb, eloc, offset); if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { @@ -238,7 +240,7 @@ if (!lfi) continue; - if ((flen = udf_get_filename(nameptr, fname, lfi))) + if ((flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi))) { if (udf_match(flen, fname, &(dentry->d_name))) { @@ -348,28 +350,41 @@ if (dentry) { - if ( !(udf_char_to_ustr(&unifilename, dentry->d_name.name, dentry->d_name.len)) ) + if (!dentry->d_name.len) { - *err = -ENAMETOOLONG; + *err = -EINVAL; return NULL; } - if ( !(namelen = udf_UTF8toCS0(name, &unifilename, UDF_NAME_LEN)) ) + if ( !(udf_char_to_ustr(&unifilename, dentry->d_name.name, dentry->d_name.len)) ) { *err = -ENAMETOOLONG; return NULL; } + + if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8)) + { + if ( !(namelen = udf_UTF8toCS0(name, &unifilename, UDF_NAME_LEN)) ) + { + *err = -ENAMETOOLONG; + return NULL; + } + } + else if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP)) + { + if ( !(namelen = udf_NLStoCS0(UDF_SB(sb)->s_nls_map, name, &unifilename, UDF_NAME_LEN)) ) + { + *err = -ENAMETOOLONG; + return NULL; + } + } + else + return NULL; } - else if (dir->i_size != 0) - { - /* WTF??? */ - *err = -ENOENT; - return NULL; - } - else /* .. */ + else namelen = 0; - nfidlen = (sizeof(struct FileIdentDesc) + 0 + namelen + 3) & ~3; + nfidlen = (sizeof(struct FileIdentDesc) + namelen + 3) & ~3; f_pos = (udf_ext0_offset(dir) >> 2); @@ -377,6 +392,7 @@ if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2), &bloc, &extoffset, &eloc, &elen, &offset, &bh) == EXTENT_RECORDED_ALLOCATED) { + offset >>= dir->i_sb->s_blocksize_bits; block = udf_get_lb_pblock(dir->i_sb, eloc, offset); if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { @@ -391,6 +407,7 @@ if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize))) { udf_release_data(bh); + *err = -EIO; return NULL; } @@ -406,6 +423,7 @@ udf_release_data(fibh->ebh); udf_release_data(fibh->sbh); udf_release_data(bh); + *err = -EIO; return NULL; } @@ -440,18 +458,22 @@ cfi->fileCharacteristics = 0; cfi->lengthFileIdent = namelen; cfi->lengthOfImpUse = cpu_to_le16(0); - if (!udf_write_fi(cfi, fi, fibh, NULL, name)) + if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name)) return fi; else + { + *err = -EIO; return NULL; + } } } - + if (!lfi || !dentry) continue; - - if ((flen = udf_get_filename(nameptr, fname, lfi)) && - udf_match(flen, fname, &(dentry->d_name))) { + + if ((flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi)) && + udf_match(flen, fname, &(dentry->d_name))) + { if (fibh->sbh != fibh->ebh) udf_release_data(fibh->ebh); udf_release_data(fibh->sbh); @@ -533,7 +555,6 @@ block = eloc.logicalBlockNum + ((elen - 1) >> dir->i_sb->s_blocksize_bits); - *err = -ENOSPC; if (!(fibh->ebh = udf_bread(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2), 1, err))) { udf_release_data(bh); @@ -568,7 +589,7 @@ cfi->fileVersionNum = cpu_to_le16(1); cfi->lengthFileIdent = namelen; cfi->lengthOfImpUse = cpu_to_le16(0); - if (!udf_write_fi(cfi, fi, fibh, NULL, name)) + if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name)) { udf_release_data(bh); dir->i_size += nfidlen; @@ -584,16 +605,18 @@ if (fibh->sbh != fibh->ebh) udf_release_data(fibh->ebh); udf_release_data(fibh->sbh); + *err = -EIO; return NULL; } } -static int udf_delete_entry(struct FileIdentDesc *fi, - struct udf_fileident_bh *fibh, - struct FileIdentDesc *cfi) +static int udf_delete_entry(struct inode *inode, struct FileIdentDesc *fi, + struct udf_fileident_bh *fibh, struct FileIdentDesc *cfi) { cfi->fileCharacteristics |= FILE_DELETED; - return udf_write_fi(cfi, fi, fibh, NULL, NULL); + if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT)) + memset(&(cfi->icb), 0x00, sizeof(long_ad)); + return udf_write_fi(inode, cfi, fi, fibh, NULL, NULL); } static int udf_create(struct inode *dir, struct dentry *dentry, int mode) @@ -627,7 +650,7 @@ cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode)); *(Uint32 *)((struct ADImpUse *)cfi.icb.impUse)->impUse = cpu_to_le32(UDF_I_UNIQUE(inode) & 0x00000000FFFFFFFFUL); - udf_write_fi(&cfi, fi, &fibh, NULL, NULL); + udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL); if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_IN_ICB) { mark_inode_dirty(dir); @@ -665,7 +688,7 @@ cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode)); *(Uint32 *)((struct ADImpUse *)cfi.icb.impUse)->impUse = cpu_to_le32(UDF_I_UNIQUE(inode) & 0x00000000FFFFFFFFUL); - udf_write_fi(&cfi, fi, &fibh, NULL, NULL); + udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL); if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_IN_ICB) { mark_inode_dirty(dir); @@ -700,7 +723,6 @@ inode->i_op = &udf_dir_inode_operations; inode->i_fop = &udf_dir_operations; - inode->i_size = 0; if (!(fi = udf_add_entry(inode, NULL, &fibh, &cfi, &err))) { inode->i_nlink--; @@ -714,7 +736,7 @@ *(Uint32 *)((struct ADImpUse *)cfi.icb.impUse)->impUse = cpu_to_le32(UDF_I_UNIQUE(dir) & 0x00000000FFFFFFFFUL); cfi.fileCharacteristics = FILE_DIRECTORY | FILE_PARENT; - udf_write_fi(&cfi, fi, &fibh, NULL, NULL); + udf_write_fi(inode, &cfi, fi, &fibh, NULL, NULL); udf_release_data(fibh.sbh); inode->i_mode = S_IFDIR | mode; if (dir->i_mode & S_ISGID) @@ -733,7 +755,7 @@ *(Uint32 *)((struct ADImpUse *)cfi.icb.impUse)->impUse = cpu_to_le32(UDF_I_UNIQUE(inode) & 0x00000000FFFFFFFFUL); cfi.fileCharacteristics |= FILE_DIRECTORY; - udf_write_fi(&cfi, fi, &fibh, NULL, NULL); + udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL); dir->i_version = ++event; dir->i_nlink++; mark_inode_dirty(dir); @@ -763,6 +785,7 @@ if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2), &bloc, &extoffset, &eloc, &elen, &offset, &bh) == EXTENT_RECORDED_ALLOCATED) { + offset >>= dir->i_sb->s_blocksize_bits; block = udf_get_lb_pblock(dir->i_sb, eloc, offset); if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { @@ -830,7 +853,7 @@ retval = -ENOTEMPTY; if (!empty_dir(inode)) goto end_rmdir; - retval = udf_delete_entry(fi, &fibh, &cfi); + retval = udf_delete_entry(dir, fi, &fibh, &cfi); dir->i_version = ++event; if (retval) goto end_rmdir; @@ -885,7 +908,7 @@ inode->i_ino, inode->i_nlink); inode->i_nlink = 1; } - retval = udf_delete_entry(fi, &fibh, &cfi); + retval = udf_delete_entry(dir, fi, &fibh, &cfi); if (retval) goto end_unlink; dir->i_ctime = dir->i_mtime = CURRENT_TIME; @@ -940,6 +963,7 @@ eloc.logicalBlockNum = block; eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum; elen = inode->i_sb->s_blocksize; + UDF_I_LENEXTENTS(inode) = elen; extoffset = udf_file_entry_alloc_offset(inode); udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 0); udf_release_data(bh); @@ -947,11 +971,18 @@ inode->i_blocks = inode->i_sb->s_blocksize / 512; block = udf_get_pblock(inode->i_sb, block, UDF_I_LOCATION(inode).partitionReferenceNum, 0); + bh = udf_tread(inode->i_sb, block, inode->i_sb->s_blocksize); + lock_buffer(bh); + memset(bh->b_data, 0x00, inode->i_sb->s_blocksize); + mark_buffer_uptodate(bh, 1); + unlock_buffer(bh); + mark_buffer_dirty_inode(bh, inode); } else + { block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0); - - bh = udf_tread(inode->i_sb, block, inode->i_sb->s_blocksize); + bh = udf_tread(inode->i_sb, block, inode->i_sb->s_blocksize); + } ea = bh->b_data + udf_ext0_offset(inode); eoffset = inode->i_sb->s_blocksize - udf_ext0_offset(inode); @@ -1042,7 +1073,7 @@ lvhd->uniqueID = cpu_to_le64(uniqueID); mark_buffer_dirty(UDF_SB_LVIDBH(inode->i_sb)); } - udf_write_fi(&cfi, fi, &fibh, NULL, NULL); + udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL); if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_IN_ICB) { mark_inode_dirty(dir); @@ -1095,7 +1126,7 @@ lvhd->uniqueID = cpu_to_le64(uniqueID); mark_buffer_dirty(UDF_SB_LVIDBH(inode->i_sb)); } - udf_write_fi(&cfi, fi, &fibh, NULL, NULL); + udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL); if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_IN_ICB) { mark_inode_dirty(dir); @@ -1126,7 +1157,12 @@ int retval = -ENOENT; old_inode = old_dentry->d_inode; - ofi = udf_find_entry(old_dir, old_dentry, &ofibh, &ocfi); + if ((ofi = udf_find_entry(old_dir, old_dentry, &ofibh, &ocfi))) + { + if (ofibh.sbh != ofibh.ebh) + udf_release_data(ofibh.ebh); + udf_release_data(ofibh.sbh); + } if (!ofi || udf_get_lb_pblock(old_dir->i_sb, lelb_to_cpu(ocfi.icb.extLocation), 0) != old_inode->i_ino) { @@ -1197,9 +1233,11 @@ ncfi.fileVersionNum = ocfi.fileVersionNum; ncfi.fileCharacteristics = ocfi.fileCharacteristics; memcpy(&(ncfi.icb), &(ocfi.icb), sizeof(long_ad)); - udf_write_fi(&ncfi, nfi, &nfibh, NULL, NULL); + udf_write_fi(new_dir, &ncfi, nfi, &nfibh, NULL, NULL); - udf_delete_entry(ofi, &ofibh, &ocfi); + /* The old fid may have moved - find it again */ + ofi = udf_find_entry(old_dir, old_dentry, &ofibh, &ocfi); + udf_delete_entry(old_dir, ofi, &ofibh, &ocfi); old_dir->i_version = ++event; if (new_inode) @@ -1216,15 +1254,15 @@ if (dir_bh) { dir_fi->icb.extLocation = lelb_to_cpu(UDF_I_LOCATION(new_dir)); - udf_update_tag((char *)dir_fi, sizeof(struct FileIdentDesc) + - cpu_to_le16(dir_fi->lengthOfImpUse)); + udf_update_tag((char *)dir_fi, (sizeof(struct FileIdentDesc) + + cpu_to_le16(dir_fi->lengthOfImpUse) + 3) & ~3); if (UDF_I_ALLOCTYPE(old_inode) == ICB_FLAG_AD_IN_ICB) { mark_inode_dirty(old_inode); old_inode->i_version = ++event; } else - mark_buffer_dirty(dir_bh); + mark_buffer_dirty_inode(dir_bh, old_inode); old_dir->i_nlink --; mark_inode_dirty(old_dir); if (new_inode) @@ -1239,16 +1277,17 @@ } } - retval = 0; - -end_rename: - udf_release_data(dir_bh); if (ofi) { if (ofibh.sbh != ofibh.ebh) udf_release_data(ofibh.ebh); udf_release_data(ofibh.sbh); } + + retval = 0; + +end_rename: + udf_release_data(dir_bh); if (nfi) { if (nfibh.sbh != nfibh.ebh) diff -u --recursive --new-file v2.4.5/linux/fs/udf/partition.c linux/fs/udf/partition.c --- v2.4.5/linux/fs/udf/partition.c Fri Apr 13 20:26:07 2001 +++ linux/fs/udf/partition.c Mon Jun 11 19:15:27 2001 @@ -7,7 +7,7 @@ * CONTACTS * E-mail regarding any portion of the Linux UDF file system should be * directed to the development team mailing list (run by majordomo): - * linux_udf@hootie.lvld.hp.com + * linux_udf@hpesjro.fc.hp.com * * COPYRIGHT * This file is distributed under the terms of the GNU General Public @@ -74,7 +74,7 @@ index = UDF_SB_TYPEVIRT(sb,partition).s_start_offset / sizeof(Uint32) + block; } - loc = udf_locked_block_map(UDF_SB_VAT(sb), newblock); + loc = udf_block_map(UDF_SB_VAT(sb), newblock); if (!(bh = bread(sb->s_dev, loc, sb->s_blocksize))) { @@ -103,135 +103,123 @@ Uint32 udf_get_pblock_spar15(struct super_block *sb, Uint32 block, Uint16 partition, Uint32 offset) { - Uint32 packet = (block + offset) >> UDF_SB_TYPESPAR(sb,partition).s_spar_pshift; - Uint32 index = 0; - - if (UDF_SB_TYPESPAR(sb,partition).s_spar_indexsize == 8) - index = UDF_SB_TYPESPAR(sb,partition).s_spar_remap.s_spar_remap8[packet]; - else if (UDF_SB_TYPESPAR(sb,partition).s_spar_indexsize == 16) - index = UDF_SB_TYPESPAR(sb,partition).s_spar_remap.s_spar_remap16[packet]; - else if (UDF_SB_TYPESPAR(sb,partition).s_spar_indexsize == 32) - index = UDF_SB_TYPESPAR(sb,partition).s_spar_remap.s_spar_remap32[packet]; - - if (index == ((1 << UDF_SB_TYPESPAR(sb,partition).s_spar_indexsize)-1)) - return UDF_SB_PARTROOT(sb,partition) + block + offset; - - packet = UDF_SB_TYPESPAR(sb,partition).s_spar_map[index]; - return packet + ((block + offset) & ((1 << UDF_SB_TYPESPAR(sb,partition).s_spar_pshift)-1)); -} - -void udf_fill_spartable(struct super_block *sb, struct udf_sparing_data *sdata, int partlen) -{ - Uint16 ident; - Uint32 spartable; int i; - struct buffer_head *bh; - struct SparingTable *st; + struct SparingTable *st = NULL; + Uint32 packet = (block + offset) & ~(UDF_SB_TYPESPAR(sb,partition).s_packet_len - 1); for (i=0; i<4; i++) { - if (!(spartable = sdata->s_spar_loc[i])) - continue; - - bh = udf_read_tagged(sb, spartable, spartable, &ident); - - if (!bh) + if (UDF_SB_TYPESPAR(sb,partition).s_spar_map[i] != NULL) { - sdata->s_spar_loc[i] = 0; - continue; + st = (struct SparingTable *)UDF_SB_TYPESPAR(sb,partition).s_spar_map[i]->b_data; + break; } + } - if (ident == 0) + if (st) + { + for (i=0; ireallocationTableLen; i++) { - st = (struct SparingTable *)bh->b_data; - if (!strncmp(st->sparingIdent.ident, UDF_ID_SPARING, strlen(UDF_ID_SPARING))) + if (le32_to_cpu(st->mapEntry[i].origLocation) >= 0xFFFFFFF0) + break; + else if (le32_to_cpu(st->mapEntry[i].origLocation) == packet) { - SparingEntry *se; - Uint16 rtl = le16_to_cpu(st->reallocationTableLen); - int index; + return le32_to_cpu(st->mapEntry[i].mappedLocation) + + ((block + offset) & (UDF_SB_TYPESPAR(sb,partition).s_packet_len - 1)); + } + else if (le32_to_cpu(st->mapEntry[i].origLocation) > packet) + break; + } + } + return UDF_SB_PARTROOT(sb,partition) + block + offset; +} - if (!sdata->s_spar_map) +int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block) +{ + struct udf_sparing_data *sdata; + struct SparingTable *st = NULL; + SparingEntry mapEntry; + Uint32 packet; + int i, j, k, l; + + for (i=0; i UDF_SB_PARTROOT(sb,i) && + old_block < UDF_SB_PARTROOT(sb,i) + UDF_SB_PARTLEN(sb,i)) + { + sdata = &UDF_SB_TYPESPAR(sb,i); + packet = (old_block - UDF_SB_PARTROOT(sb,i)) & ~(sdata->s_packet_len - 1); + + for (j=0; j<4; j++) + { + if (UDF_SB_TYPESPAR(sb,i).s_spar_map[j] != NULL) { - int num = 1, mapsize; - sdata->s_spar_indexsize = 8; - while (rtl*sizeof(Uint32) >= (1 << sdata->s_spar_indexsize)) - { - num ++; - sdata->s_spar_indexsize <<= 1; - } - mapsize = (rtl * sizeof(Uint32)) + - ((partlen/(1 << sdata->s_spar_pshift)) * sizeof(Uint8) * num); - sdata->s_spar_map = kmalloc(mapsize, GFP_KERNEL); - if (!sdata->s_spar_map) { - printk("couldnt allocate UDF s_spar_map!\n"); - return; - } - sdata->s_spar_remap.s_spar_remap32 = &sdata->s_spar_map[rtl]; - memset(sdata->s_spar_map, 0xFF, mapsize); + st = (struct SparingTable *)sdata->s_spar_map[j]->b_data; + break; } + } + + if (!st) + return 1; - index = sizeof(struct SparingTable); - for (i=0; ireallocationTableLen; k++) + { + if (le32_to_cpu(st->mapEntry[k].origLocation) == 0xFFFFFFFF) { - if (index > sb->s_blocksize) + for (; j<4; j++) { - udf_release_data(bh); - bh = udf_tread(sb, ++spartable, sb->s_blocksize); - if (!bh) + if (sdata->s_spar_map[j]) { - sdata->s_spar_loc[i] = 0; - continue; + st = (struct SparingTable *)sdata->s_spar_map[j]->b_data; + st->mapEntry[k].origLocation = cpu_to_le32(packet); + udf_update_tag((char *)st, sizeof(struct SparingTable) + st->reallocationTableLen * sizeof(SparingEntry)); + mark_buffer_dirty(sdata->s_spar_map[j]); } - index = 0; } - se = (SparingEntry *)&(bh->b_data[index]); - index += sizeof(SparingEntry); - - if (sdata->s_spar_map[i] == 0xFFFFFFFF) - sdata->s_spar_map[i] = le32_to_cpu(se->mappedLocation); - else if (sdata->s_spar_map[i] != le32_to_cpu(se->mappedLocation)) - { - udf_debug("Found conflicting Sparing Data (%d vs %d for entry %d)\n", - sdata->s_spar_map[i], le32_to_cpu(se->mappedLocation), i); - } - - if (le32_to_cpu(se->origLocation) < 0xFFFFFFF0) + *new_block = le32_to_cpu(st->mapEntry[k].mappedLocation) + + ((old_block - UDF_SB_PARTROOT(sb,i)) & (sdata->s_packet_len - 1)); + return 0; + } + else if (le32_to_cpu(st->mapEntry[k].origLocation) == packet) + { + *new_block = le32_to_cpu(st->mapEntry[k].mappedLocation) + + ((old_block - UDF_SB_PARTROOT(sb,i)) & (sdata->s_packet_len - 1)); + return 0; + } + else if (le32_to_cpu(st->mapEntry[k].origLocation) > packet) + break; + } + for (l=k; lreallocationTableLen; l++) + { + if (le32_to_cpu(st->mapEntry[l].origLocation) == 0xFFFFFFFF) + { + for (; j<4; j++) { - int packet = le32_to_cpu(se->origLocation) >> sdata->s_spar_pshift; - if (sdata->s_spar_indexsize == 8) - { - if (sdata->s_spar_remap.s_spar_remap8[packet] == 0xFF) - sdata->s_spar_remap.s_spar_remap8[packet] = i; - else if (sdata->s_spar_remap.s_spar_remap8[packet] != i) - { - udf_debug("Found conflicting Sparing Data (%d vs %d)\n", - sdata->s_spar_remap.s_spar_remap8[packet], i); - } - } - else if (sdata->s_spar_indexsize == 16) + if (sdata->s_spar_map[j]) { - if (sdata->s_spar_remap.s_spar_remap16[packet] == 0xFFFF) - sdata->s_spar_remap.s_spar_remap16[packet] = i; - else if (sdata->s_spar_remap.s_spar_remap16[packet] != i) - { - udf_debug("Found conflicting Sparing Data (%d vs %d)\n", - sdata->s_spar_remap.s_spar_remap16[packet], i); - } - } - else if (sdata->s_spar_indexsize == 32) - { - if (sdata->s_spar_remap.s_spar_remap32[packet] == 0xFFFFFFFF) - sdata->s_spar_remap.s_spar_remap32[packet] = i; - else if (sdata->s_spar_remap.s_spar_remap32[packet] != i) - { - udf_debug("Found conflicting Sparing Data (%d vs %d)\n", - sdata->s_spar_remap.s_spar_remap32[packet], i); - } + st = (struct SparingTable *)sdata->s_spar_map[j]->b_data; + mapEntry = st->mapEntry[l]; + mapEntry.origLocation = cpu_to_le32(packet); + memmove(&st->mapEntry[k+1], &st->mapEntry[k], (l-k)*sizeof(SparingEntry)); + st->mapEntry[k] = mapEntry; + udf_update_tag((char *)st, sizeof(struct SparingTable) + st->reallocationTableLen * sizeof(SparingEntry)); + mark_buffer_dirty(sdata->s_spar_map[j]); } } + *new_block = le32_to_cpu(st->mapEntry[k].mappedLocation) + + ((old_block - UDF_SB_PARTROOT(sb,i)) & (sdata->s_packet_len - 1)); + return 0; } } + return 1; } - udf_release_data(bh); } + if (i == UDF_SB_NUMPARTS(sb)) + { + /* outside of partitions */ + /* for now, fail =) */ + return 1; + } + + return 0; } diff -u --recursive --new-file v2.4.5/linux/fs/udf/super.c linux/fs/udf/super.c --- v2.4.5/linux/fs/udf/super.c Mon Apr 23 10:00:21 2001 +++ linux/fs/udf/super.c Mon Jun 11 19:15:27 2001 @@ -17,7 +17,7 @@ * CONTACTS * E-mail regarding any portion of the Linux UDF file system should be * directed to the development team mailing list (run by majordomo): - * linux_udf@hootie.lvld.hp.com + * linux_udf@hpesjro.fc.hp.com * * COPYRIGHT * This file is distributed under the terms of the GNU General Public @@ -71,7 +71,7 @@ #define VDS_POS_IMP_USE_VOL_DESC 4 #define VDS_POS_VOL_DESC_PTR 5 #define VDS_POS_TERMINATING_DESC 6 -#define VDS_POS_LENGTH 7 +#define VDS_POS_LENGTH 7 static char error_buf[1024]; @@ -125,6 +125,7 @@ mode_t umask; gid_t gid; uid_t uid; + struct nls_table *nls_map; }; static int __init init_udf_fs(void) @@ -139,6 +140,8 @@ unregister_filesystem(&udf_fstype); } +EXPORT_NO_SYMBOLS; + module_init(init_udf_fs) module_exit(exit_udf_fs) @@ -161,7 +164,8 @@ * noadinicb Don't embed data in the inode * shortad Use short ad's * longad Use long ad's (default) - * strict Set strict conformance (unused) + * strict Set strict conformance + * iocharset= Set the NLS character set * * The remaining are for debugging and disaster recovery: * @@ -209,6 +213,7 @@ uopt->volume = 0xFFFFFFFF; uopt->rootdir = 0xFFFFFFFF; uopt->fileset = 0xFFFFFFFF; + uopt->nls_map = NULL; if (!options) return 1; @@ -257,6 +262,15 @@ uopt->fileset = simple_strtoul(val, NULL, 0); else if (!strcmp(opt, "rootdir") && val) uopt->rootdir = simple_strtoul(val, NULL, 0); +#ifdef CONFIG_NLS + else if (!strcmp(opt, "iocharset") && val) + { + uopt->nls_map = load_nls(val); + uopt->flags |= (1 << UDF_FLAG_NLS_MAP); + } +#endif + else if (!strcmp(opt, "utf8") && !val) + uopt->flags |= (1 << UDF_FLAG_UTF8); else if (val) { printk(KERN_ERR "udf: bad mount option \"%s=%s\"\n", @@ -280,7 +294,7 @@ udf_open_lvid(sb); sb->s_dirt = 0; } - + static int udf_remount_fs(struct super_block *sb, int *flags, char *options) { @@ -299,7 +313,7 @@ UDF_SB(sb)->s_gid = uopt.gid; UDF_SB(sb)->s_umask = uopt.umask; -#if CONFIG_UDF_RW != 1 +#if UDFFS_RW != 1 *flags |= MS_RDONLY; #endif @@ -344,12 +358,14 @@ udf_set_blocksize(struct super_block *sb, int bsize) { /* Use specified block size if specified */ - sb->s_blocksize = get_hardsect_size(sb->s_dev); - if (bsize > sb->s_blocksize) + if (bsize) sb->s_blocksize = bsize; + if (get_hardsect_size(sb->s_dev) > sb->s_blocksize) + sb->s_blocksize = get_hardsect_size(sb->s_dev); /* Block size must be an even multiple of 512 */ - switch (sb->s_blocksize) { + switch (sb->s_blocksize) + { case 512: sb->s_blocksize_bits = 9; break; case 1024: sb->s_blocksize_bits = 10; break; case 2048: sb->s_blocksize_bits = 11; break; @@ -373,6 +389,7 @@ { struct VolStructDesc *vsd = NULL; int sector = 32768; + int sectorsize; struct buffer_head *bh = NULL; int iso9660=0; int nsr02=0; @@ -380,14 +397,19 @@ /* Block size must be a multiple of 512 */ if (sb->s_blocksize & 511) - return sector; + return 0; + + if (sb->s_blocksize < sizeof(struct VolStructDesc)) + sectorsize = sizeof(struct VolStructDesc); + else + sectorsize = sb->s_blocksize; sector += (UDF_SB_SESSION(sb) << sb->s_blocksize_bits); udf_debug("Starting at sector %u (%ld byte sectors)\n", (sector >> sb->s_blocksize_bits), sb->s_blocksize); /* Process the sequence (if applicable) */ - for (;!nsr02 && !nsr03; sector += 2048) + for (;!nsr02 && !nsr03; sector += sectorsize) { /* Read a block */ bh = udf_tread(sb, sector >> sb->s_blocksize_bits, sb->s_blocksize); @@ -479,9 +501,9 @@ { int varlastblock = udf_variable_to_fixed(lastblock); int last[] = { lastblock, lastblock - 2, - lastblock - 150, lastblock - 152, - varlastblock, varlastblock - 2, - varlastblock - 150, varlastblock - 152 }; + lastblock - 150, lastblock - 152, + varlastblock, varlastblock - 2, + varlastblock - 150, varlastblock - 152 }; struct buffer_head *bh = NULL; Uint16 ident; Uint32 location; @@ -504,7 +526,7 @@ for (i=0; (!lastblock && is_dev, last[i], sb->s_blocksize))) + if (last[i] < 0 || !(bh = bread(sb->s_dev, last[i], sb->s_blocksize))) { ident = location = 0; } @@ -777,7 +799,7 @@ struct PartitionDesc *p; int i; - p=(struct PartitionDesc *)bh->b_data; + p = (struct PartitionDesc *)bh->b_data; for (i=0; ipartitionLength); /* blocks */ UDF_SB_PARTROOT(sb,i) = le32_to_cpu(p->partitionStartingLocation) + UDF_SB_SESSION(sb); - if (UDF_SB_PARTTYPE(sb,i) == UDF_SPARABLE_MAP15) - udf_fill_spartable(sb, &UDF_SB_TYPESPAR(sb,i), UDF_SB_PARTLEN(sb,i)); - if (!strcmp(p->partitionContents.ident, PARTITION_CONTENTS_NSR02) || !strcmp(p->partitionContents.ident, PARTITION_CONTENTS_NSR03)) { @@ -798,26 +817,54 @@ phd = (struct PartitionHeaderDesc *)(p->partitionContentsUse); if (phd->unallocatedSpaceTable.extLength) - udf_debug("unallocatedSpaceTable (part %d)\n", i); + { + lb_addr loc = { le32_to_cpu(phd->unallocatedSpaceTable.extPosition), i }; + + UDF_SB_PARTMAPS(sb)[i].s_uspace.s_table = + udf_iget(sb, loc); + UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_UNALLOC_TABLE; + udf_debug("unallocatedSpaceTable (part %d) @ %ld\n", + i, UDF_SB_PARTMAPS(sb)[i].s_uspace.s_table->i_ino); + } if (phd->unallocatedSpaceBitmap.extLength) { - UDF_SB_PARTMAPS(sb)[i].s_uspace.bitmap = - le32_to_cpu(phd->unallocatedSpaceBitmap.extPosition); - UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_UNALLOC_BITMAP; - udf_debug("unallocatedSpaceBitmap (part %d) @ %d\n", - i, UDF_SB_PARTMAPS(sb)[i].s_uspace.bitmap); + UDF_SB_ALLOC_BITMAP(sb, i, s_uspace); + if (UDF_SB_PARTMAPS(sb)[i].s_uspace.s_bitmap != NULL) + { + UDF_SB_PARTMAPS(sb)[i].s_uspace.s_bitmap->s_extLength = + le32_to_cpu(phd->unallocatedSpaceBitmap.extLength); + UDF_SB_PARTMAPS(sb)[i].s_uspace.s_bitmap->s_extPosition = + le32_to_cpu(phd->unallocatedSpaceBitmap.extPosition); + UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_UNALLOC_BITMAP; + udf_debug("unallocatedSpaceBitmap (part %d) @ %d\n", + i, UDF_SB_PARTMAPS(sb)[i].s_uspace.s_bitmap->s_extPosition); + } } if (phd->partitionIntegrityTable.extLength) udf_debug("partitionIntegrityTable (part %d)\n", i); if (phd->freedSpaceTable.extLength) - udf_debug("freedSpaceTable (part %d)\n", i); + { + lb_addr loc = { le32_to_cpu(phd->freedSpaceTable.extPosition), i }; + + UDF_SB_PARTMAPS(sb)[i].s_fspace.s_table = + udf_iget(sb, loc); + UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_FREED_TABLE; + udf_debug("freedSpaceTable (part %d) @ %ld\n", + i, UDF_SB_PARTMAPS(sb)[i].s_fspace.s_table->i_ino); + } if (phd->freedSpaceBitmap.extLength) { - UDF_SB_PARTMAPS(sb)[i].s_fspace.bitmap = - le32_to_cpu(phd->freedSpaceBitmap.extPosition); - UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_FREED_BITMAP; - udf_debug("freedSpaceBitmap (part %d) @ %d\n", - i, UDF_SB_PARTMAPS(sb)[i].s_fspace.bitmap); + UDF_SB_ALLOC_BITMAP(sb, i, s_fspace); + if (UDF_SB_PARTMAPS(sb)[i].s_fspace.s_bitmap != NULL) + { + UDF_SB_PARTMAPS(sb)[i].s_fspace.s_bitmap->s_extLength = + le32_to_cpu(phd->freedSpaceBitmap.extLength); + UDF_SB_PARTMAPS(sb)[i].s_fspace.s_bitmap->s_extPosition = + le32_to_cpu(phd->freedSpaceBitmap.extPosition); + UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_FREED_BITMAP; + udf_debug("freedSpaceBitmap (part %d) @ %d\n", + i, UDF_SB_PARTMAPS(sb)[i].s_fspace.s_bitmap->s_extPosition); + } } } break; @@ -844,15 +891,13 @@ lvd = (struct LogicalVolDesc *)bh->b_data; - UDF_SB_NUMPARTS(sb) = le32_to_cpu(lvd->numPartitionMaps); - UDF_SB_ALLOC_PARTMAPS(sb, UDF_SB_NUMPARTS(sb)); + UDF_SB_ALLOC_PARTMAPS(sb, le32_to_cpu(lvd->numPartitionMaps)); for (i=0,offset=0; imapTableLength); i++,offset+=((struct GenericPartitionMap *)&(lvd->partitionMaps[offset]))->partitionMapLength) { type = ((struct GenericPartitionMap *)&(lvd->partitionMaps[offset]))->partitionMapType; - udf_debug("Partition (%d) type %d\n", i, type); if (type == 1) { struct GenericPartitionMap1 *gpm1 = (struct GenericPartitionMap1 *)&(lvd->partitionMaps[offset]); @@ -879,16 +924,29 @@ } else if (!strncmp(upm2->partIdent.ident, UDF_ID_SPARABLE, strlen(UDF_ID_SPARABLE))) { - int plen; - + Uint32 loc; + Uint16 ident; + struct SparingTable *st; struct SparablePartitionMap *spm = (struct SparablePartitionMap *)&(lvd->partitionMaps[offset]); + UDF_SB_PARTTYPE(sb,i) = UDF_SPARABLE_MAP15; - plen = le16_to_cpu(spm->packetLength); - UDF_SB_TYPESPAR(sb,i).s_spar_pshift = 0; - while (plen >>= 1) - UDF_SB_TYPESPAR(sb,i).s_spar_pshift ++; + UDF_SB_TYPESPAR(sb,i).s_packet_len = le16_to_cpu(spm->packetLength); for (j=0; jnumSparingTables; j++) - UDF_SB_TYPESPAR(sb,i).s_spar_loc[j] = le32_to_cpu(spm->locSparingTable[j]); + { + loc = le32_to_cpu(spm->locSparingTable[j]); + UDF_SB_TYPESPAR(sb,i).s_spar_map[j] = + udf_read_tagged(sb, loc, loc, &ident); + if (UDF_SB_TYPESPAR(sb,i).s_spar_map[j] != NULL) + { + st = (struct SparingTable *)UDF_SB_TYPESPAR(sb,i).s_spar_map[j]->b_data; + if (ident != 0 || + strncmp(st->sparingIdent.ident, UDF_ID_SPARING, strlen(UDF_ID_SPARING))) + { + udf_release_data(UDF_SB_TYPESPAR(sb,i).s_spar_map[j]); + UDF_SB_TYPESPAR(sb,i).s_spar_map[j] = NULL; + } + } + } UDF_SB_PARTFUNC(sb,i) = udf_get_pblock_spar15; } else @@ -899,6 +957,8 @@ UDF_SB_PARTVSN(sb,i) = le16_to_cpu(upm2->volSeqNum); UDF_SB_PARTNUM(sb,i) = le16_to_cpu(upm2->partitionNum); } + udf_debug("Partition (%d:%d) type %d on volume %d\n", + i, UDF_SB_PARTNUM(sb,i), type, UDF_SB_PARTVSN(sb,i)); } if (fileset) @@ -963,10 +1023,12 @@ struct buffer_head *bh = NULL; struct udf_vds_record vds[VDS_POS_LENGTH]; struct GenericDesc *gd; + struct VolDescPtr *vdp; int done=0; int i,j; Uint32 vdsn; Uint16 ident; + long next_s = 0, next_e = 0; memset(vds, 0, sizeof(struct udf_vds_record) * VDS_POS_LENGTH); @@ -995,6 +1057,12 @@ { vds[VDS_POS_VOL_DESC_PTR].volDescSeqNum = vdsn; vds[VDS_POS_VOL_DESC_PTR].block = block; + + vdp = (struct VolDescPtr *)bh->b_data; + next_s = le32_to_cpu(vdp->nextVolDescSeqExt.extLocation); + next_e = le32_to_cpu(vdp->nextVolDescSeqExt.extLength); + next_e = next_e >> sb->s_blocksize_bits; + next_e += next_s; } break; case TID_IMP_USE_VOL_DESC: /* ISO 13346 3/10.4 */ @@ -1024,7 +1092,14 @@ break; case TID_TERMINATING_DESC: /* ISO 13346 3/10.9 */ vds[VDS_POS_TERMINATING_DESC].block = block; - done = 1; + if (next_e) + { + block = next_s; + lastblock = next_e; + next_s = next_e = 0; + } + else + done = 1; break; } udf_release_data(bh); @@ -1098,7 +1173,7 @@ for (i=0; ib_data; @@ -1155,10 +1230,10 @@ UDF_SB_PARTVSN(sb,i) == UDF_SB_PARTVSN(sb,j) && UDF_SB_PARTNUM(sb,i) == UDF_SB_PARTNUM(sb,j)) { - ino.partitionReferenceNum = j; - ino.logicalBlockNum = UDF_SB_LASTBLOCK(sb) - - UDF_SB_PARTROOT(sb,j); - break; + ino.partitionReferenceNum = j; + ino.logicalBlockNum = UDF_SB_LASTBLOCK(sb) - + UDF_SB_PARTROOT(sb,j); + break; } } @@ -1219,7 +1294,6 @@ ((Uint8 *)&(UDF_SB_LVID(sb)->descTag))[i]; mark_buffer_dirty(UDF_SB_LVIDBH(sb)); - sb->s_dirt = 0; } } @@ -1276,10 +1350,10 @@ static struct super_block * udf_read_super(struct super_block *sb, void *options, int silent) { + int i; struct inode *inode=NULL; struct udf_options uopt; lb_addr rootdir, fileset; - int i; uopt.flags = (1 << UDF_FLAG_USE_AD_IN_ICB); uopt.uid = -1; @@ -1288,13 +1362,33 @@ memset(UDF_SB(sb), 0x00, sizeof(struct udf_sb_info)); -#if CONFIG_UDF_RW != 1 +#if UDFFS_RW != 1 sb->s_flags |= MS_RDONLY; #endif if (!udf_parse_options((char *)options, &uopt)) goto error_out; + if (uopt.flags & (1 << UDF_FLAG_UTF8) && + uopt.flags & (1 << UDF_FLAG_NLS_MAP)) + { + udf_error(sb, "udf_read_super", + "utf8 cannot be combined with iocharset\n"); + goto error_out; + } +#ifdef CONFIG_NLS + if ((uopt.flags & (1 << UDF_FLAG_NLS_MAP)) && !uopt.nls_map) + { + uopt.nls_map = load_nls_default(); + if (!uopt.nls_map) + uopt.flags &= ~(1 << UDF_FLAG_NLS_MAP); + else + udf_debug("Using default NLS map\n"); + } +#endif + if (!(uopt.flags & (1 << UDF_FLAG_NLS_MAP))) + uopt.flags |= (1 << UDF_FLAG_UTF8); + fileset.logicalBlockNum = 0xFFFFFFFF; fileset.partitionReferenceNum = 0xFFFF; @@ -1302,6 +1396,7 @@ UDF_SB(sb)->s_uid = uopt.uid; UDF_SB(sb)->s_gid = uopt.gid; UDF_SB(sb)->s_umask = uopt.umask; + UDF_SB(sb)->s_nls_map = uopt.nls_map; /* Set the block size for all transfers */ if (!udf_set_blocksize(sb, uopt.blocksize)) @@ -1335,13 +1430,6 @@ sb->s_dirt = 0; sb->s_magic = UDF_SUPER_MAGIC; - for (i=0; is_flags |= MS_RDONLY; } + UDF_SB_UDFREV(sb) = minUDFWriteRev; + if (minUDFReadRev >= UDF_VERS_USE_EXTENDED_FE) UDF_SET_FLAG(sb, UDF_FLAG_USE_EXTENDED_FE); if (minUDFReadRev >= UDF_VERS_USE_STREAMS) @@ -1387,8 +1477,8 @@ { timestamp ts; udf_time_to_stamp(&ts, UDF_SB_RECORDTIME(sb), 0); - udf_info("UDF %s (%s) Mounting volume '%s', timestamp %04u/%02u/%02u %02u:%02u (%x)\n", - UDFFS_VERSION, UDFFS_DATE, + udf_info("UDF %s-%s (%s) Mounting volume '%s', timestamp %04u/%02u/%02u %02u:%02u (%x)\n", + UDFFS_VERSION, UDFFS_RW ? "rw" : "ro", UDFFS_DATE, UDF_SB_VOLIDENT(sb), ts.year, ts.month, ts.day, ts.hour, ts.minute, ts.typeAndTimezone); } @@ -1420,6 +1510,40 @@ error_out: if (UDF_SB_VAT(sb)) iput(UDF_SB_VAT(sb)); + if (UDF_SB_NUMPARTS(sb)) + { + if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_UNALLOC_TABLE) + iput(UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_uspace.s_table); + if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_FREED_TABLE) + iput(UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_fspace.s_table); + if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_UNALLOC_BITMAP) + { + for (i=0; is_nls_map); +#endif if (!(sb->s_flags & MS_RDONLY)) udf_close_lvid(sb); udf_release_data(UDF_SB_LVIDBH(sb)); @@ -1476,11 +1600,43 @@ if (UDF_SB_VAT(sb)) iput(UDF_SB_VAT(sb)); + if (UDF_SB_NUMPARTS(sb)) + { + if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_UNALLOC_TABLE) + iput(UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_uspace.s_table); + if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_FREED_TABLE) + iput(UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_fspace.s_table); + if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_UNALLOC_BITMAP) + { + for (i=0; is_nls_map); +#endif if (!(sb->s_flags & MS_RDONLY)) udf_close_lvid(sb); udf_release_data(UDF_SB_LVIDBH(sb)); - for (i=0; is_extPosition; + loc.partitionReferenceNum = UDF_SB_PARTITION(sb); + bh = udf_read_ptagged(sb, loc, 0, &ident); - if (bitmap != 0xFFFFFFFF) + if (!bh) + { + printk(KERN_ERR "udf: udf_count_free failed\n"); + return 0; + } + else if (ident != TID_SPACE_BITMAP_DESC) { - struct SpaceBitmapDesc *bm; - int block = 0, newblock, index; - Uint16 ident; - Uint32 bytes; - Uint8 value; - Uint8 * ptr; - - loc.logicalBlockNum = bitmap; - loc.partitionReferenceNum = UDF_SB_PARTITION(sb); - bh = udf_read_ptagged(sb, loc, 0, &ident); + udf_release_data(bh); + printk(KERN_ERR "udf: udf_count_free failed\n"); + return 0; + } - if (!bh) - { - printk(KERN_ERR "udf: udf_count_free failed\n"); - return 0; + bm = (struct SpaceBitmapDesc *)bh->b_data; + bytes = bm->numOfBytes; + index = sizeof(struct SpaceBitmapDesc); /* offset in first block only */ + ptr = (Uint8 *)bh->b_data; + + while ( bytes > 0 ) + { + while ((bytes > 0) && (index < sb->s_blocksize)) + { + value = ptr[index]; + accum += udf_bitmap_lookup[ value & 0x0f ]; + accum += udf_bitmap_lookup[ value >> 4 ]; + index++; + bytes--; } - else if (ident != TID_SPACE_BITMAP_DESC) + if ( bytes ) { udf_release_data(bh); - printk(KERN_ERR "udf: udf_count_free failed\n"); - return 0; - } - - bm = (struct SpaceBitmapDesc *)bh->b_data; - bytes = bm->numOfBytes; - index = sizeof(struct SpaceBitmapDesc); /* offset in first block only */ - ptr = (Uint8 *)bh->b_data; - - while ( bytes > 0 ) - { - while ((bytes > 0) && (index < sb->s_blocksize)) - { - value = ptr[index]; - accum += udf_bitmap_lookup[ value & 0x0f ]; - accum += udf_bitmap_lookup[ value >> 4 ]; - index++; - bytes--; - } - if ( bytes ) + newblock = udf_get_lb_pblock(sb, loc, ++block); + bh = udf_tread(sb, newblock, sb->s_blocksize); + if (!bh) { - udf_release_data(bh); - newblock = udf_get_lb_pblock(sb, loc, ++block); - bh = udf_tread(sb, newblock, sb->s_blocksize); - if (!bh) - { - udf_debug("read failed\n"); - return accum; - } - index = 0; - ptr = (Uint8 *)bh->b_data; + udf_debug("read failed\n"); + return accum; } + index = 0; + ptr = (Uint8 *)bh->b_data; } - udf_release_data(bh); } - else + udf_release_data(bh); + return accum; +} + +static unsigned int +udf_count_free_table(struct super_block *sb, struct inode * table) +{ + unsigned int accum = 0; + Uint32 extoffset, elen; + lb_addr bloc, eloc; + char etype; + struct buffer_head *bh = NULL; + + bloc = UDF_I_LOCATION(table); + extoffset = sizeof(struct UnallocatedSpaceEntry); + + while ((etype = udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1) { - if (UDF_SB_LVIDBH(sb)) + accum += (elen >> table->i_sb->s_blocksize_bits); + } + udf_release_data(bh); + return accum; +} + +static unsigned int +udf_count_free(struct super_block *sb) +{ + unsigned int accum = 0; + + if (UDF_SB_PARTFLAGS(sb,UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_UNALLOC_BITMAP) + { + accum += udf_count_free_bitmap(sb, + UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_uspace.s_bitmap); + } + if (UDF_SB_PARTFLAGS(sb,UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_FREED_BITMAP) + { + accum += udf_count_free_bitmap(sb, + UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_fspace.s_bitmap); + } + if (accum) + return accum; + + if (UDF_SB_PARTFLAGS(sb,UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_UNALLOC_TABLE) + { + accum += udf_count_free_table(sb, + UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_uspace.s_table); + } + if (UDF_SB_PARTFLAGS(sb,UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_FREED_TABLE) + { + accum += udf_count_free_table(sb, + UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_fspace.s_table); + } + if (accum) + return accum; + + if (UDF_SB_LVIDBH(sb)) + { + if (le32_to_cpu(UDF_SB_LVID(sb)->numOfPartitions) > UDF_SB_PARTITION(sb)) { - if (le32_to_cpu(UDF_SB_LVID(sb)->numOfPartitions) > UDF_SB_PARTITION(sb)) - accum = le32_to_cpu(UDF_SB_LVID(sb)->freeSpaceTable[UDF_SB_PARTITION(sb)]); + accum = le32_to_cpu(UDF_SB_LVID(sb)->freeSpaceTable[UDF_SB_PARTITION(sb)]); if (accum == 0xFFFFFFFF) accum = 0; } } - return accum; } diff -u --recursive --new-file v2.4.5/linux/fs/udf/symlink.c linux/fs/udf/symlink.c --- v2.4.5/linux/fs/udf/symlink.c Fri Feb 9 11:29:44 2001 +++ linux/fs/udf/symlink.c Mon Jun 11 19:15:27 2001 @@ -7,7 +7,7 @@ * CONTACTS * E-mail regarding any portion of the Linux UDF file system should be * directed to the development team mailing list (run by majordomo): - * linux_udf@hootie.lvld.hp.com + * linux_udf@hpesjro.fc.hp.com * * COPYRIGHT * This file is distributed under the terms of the GNU General Public @@ -126,5 +126,5 @@ * symlinks can't do much... */ struct address_space_operations udf_symlink_aops = { - readpage: udf_symlink_filler, + readpage: udf_symlink_filler, }; diff -u --recursive --new-file v2.4.5/linux/fs/udf/truncate.c linux/fs/udf/truncate.c --- v2.4.5/linux/fs/udf/truncate.c Tue Sep 5 14:07:30 2000 +++ linux/fs/udf/truncate.c Mon Jun 11 19:15:27 2001 @@ -7,7 +7,7 @@ * CONTACTS * E-mail regarding any portion of the Linux UDF file system should be * directed to the development team mailing list (run by majordomo): - * linux_udf@hootie.lvld.hp.com + * linux_udf@hpesjro.fc.hp.com * * COPYRIGHT * This file is distributed under the terms of the GNU General Public @@ -33,7 +33,7 @@ #include "udf_sb.h" static void extent_trunc(struct inode * inode, lb_addr bloc, int extoffset, - lb_addr eloc, Uint8 etype, Uint32 elen, struct buffer_head **bh, Uint32 nelen) + lb_addr eloc, Uint8 etype, Uint32 elen, struct buffer_head *bh, Uint32 nelen) { lb_addr neloc = { 0, 0 }; int blocks = inode->i_sb->s_blocksize / 512; @@ -62,7 +62,7 @@ } } -void udf_trunc(struct inode * inode) +void udf_truncate_extents(struct inode * inode) { lb_addr bloc, eloc, neloc = { 0, 0 }; Uint32 extoffset, elen, offset, nelen = 0, lelen = 0, lenalloc; @@ -79,12 +79,11 @@ adsize = 0; etype = inode_bmap(inode, first_block, &bloc, &extoffset, &eloc, &elen, &offset, &bh); - offset = (offset << inode->i_sb->s_blocksize_bits) | - (inode->i_size & (inode->i_sb->s_blocksize - 1)); + offset += (inode->i_size & (inode->i_sb->s_blocksize - 1)); if (etype != -1) { extoffset -= adsize; - extent_trunc(inode, bloc, extoffset, eloc, etype, elen, &bh, offset); + extent_trunc(inode, bloc, extoffset, eloc, etype, elen, bh, offset); extoffset += adsize; if (offset) @@ -101,7 +100,7 @@ { if (etype == EXTENT_NEXT_EXTENT_ALLOCDECS) { - udf_write_aext(inode, bloc, &extoffset, neloc, nelen, &bh, 0); + udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 0); extoffset = 0; if (lelen) { @@ -122,9 +121,12 @@ { struct AllocExtDesc *aed = (struct AllocExtDesc *)(bh->b_data); aed->lengthAllocDescs = cpu_to_le32(lenalloc); - udf_update_tag(bh->b_data, lenalloc + - sizeof(struct AllocExtDesc)); - mark_buffer_dirty(bh); + if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201) + udf_update_tag(bh->b_data, lenalloc + + sizeof(struct AllocExtDesc)); + else + udf_update_tag(bh->b_data, sizeof(struct AllocExtDesc)); + mark_buffer_dirty_inode(bh, inode); } } @@ -140,7 +142,7 @@ } else { - extent_trunc(inode, bloc, extoffset, eloc, etype, elen, &bh, 0); + extent_trunc(inode, bloc, extoffset, eloc, etype, elen, bh, 0); extoffset += adsize; } } @@ -164,9 +166,12 @@ { struct AllocExtDesc *aed = (struct AllocExtDesc *)(bh->b_data); aed->lengthAllocDescs = cpu_to_le32(lenalloc); - udf_update_tag(bh->b_data, lenalloc + - sizeof(struct AllocExtDesc)); - mark_buffer_dirty(bh); + if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201) + udf_update_tag(bh->b_data, lenalloc + + sizeof(struct AllocExtDesc)); + else + udf_update_tag(bh->b_data, sizeof(struct AllocExtDesc)); + mark_buffer_dirty_inode(bh, inode); } } } @@ -180,7 +185,7 @@ { extoffset -= adsize; elen = (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30) | (elen + offset); - udf_write_aext(inode, bloc, &extoffset, eloc, elen, &bh, 0); + udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 0); } else if (etype == EXTENT_NOT_RECORDED_ALLOCATED) { @@ -189,7 +194,7 @@ nelen = (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30) | ((elen + offset + inode->i_sb->s_blocksize - 1) & ~(inode->i_sb->s_blocksize - 1)); - udf_write_aext(inode, bloc, &extoffset, neloc, nelen, &bh, 1); + udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 1); udf_add_aext(inode, &bloc, &extoffset, eloc, (etype << 30) | elen, &bh, 1); } else @@ -200,7 +205,7 @@ elen = (EXTENT_RECORDED_ALLOCATED << 30) | ((elen + inode->i_sb->s_blocksize - 1) & ~(inode->i_sb->s_blocksize - 1)); - udf_write_aext(inode, bloc, &extoffset, eloc, elen, &bh, 1); + udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 1); } memset(&eloc, 0x00, sizeof(lb_addr)); elen = (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30) | offset; @@ -208,40 +213,7 @@ } } } + UDF_I_LENEXTENTS(inode) = inode->i_size; udf_release_data(bh); -} - -void udf_truncate(struct inode * inode) -{ - int err; - - if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode))) - return; - if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) - return; - - if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB) - { - if (inode->i_sb->s_blocksize < (udf_file_entry_alloc_offset(inode) + - inode->i_size)) - { - udf_expand_file_adinicb(inode, inode->i_size, &err); - if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB) - { - inode->i_size = UDF_I_LENALLOC(inode); - return; - } - else - udf_trunc(inode); - } - else - UDF_I_LENALLOC(inode) = inode->i_size; - } - else - udf_trunc(inode); - - inode->i_mtime = inode->i_ctime = CURRENT_TIME; - mark_inode_dirty(inode); } diff -u --recursive --new-file v2.4.5/linux/fs/udf/udf_i.h linux/fs/udf/udf_i.h --- v2.4.5/linux/fs/udf/udf_i.h Thu Mar 2 11:17:32 2000 +++ linux/fs/udf/udf_i.h Mon Jul 2 14:10:02 2001 @@ -6,6 +6,7 @@ #define UDF_I_LOCATION(X) ( UDF_I(X)->i_location ) #define UDF_I_LENEATTR(X) ( UDF_I(X)->i_lenEAttr ) #define UDF_I_LENALLOC(X) ( UDF_I(X)->i_lenAlloc ) +#define UDF_I_LENEXTENTS(X) ( UDF_I(X)->i_lenExtents ) #define UDF_I_UNIQUE(X) ( UDF_I(X)->i_unique ) #define UDF_I_ALLOCTYPE(X) ( UDF_I(X)->i_alloc_type ) #define UDF_I_EXTENDED_FE(X)( UDF_I(X)->i_extended_fe ) @@ -13,8 +14,9 @@ #define UDF_I_NEW_INODE(X) ( UDF_I(X)->i_new_inode ) #define UDF_I_NEXT_ALLOC_BLOCK(X) ( UDF_I(X)->i_next_alloc_block ) #define UDF_I_NEXT_ALLOC_GOAL(X) ( UDF_I(X)->i_next_alloc_goal ) -#define UDF_I_UATIME(X) ( UDF_I(X)->i_uatime ) #define UDF_I_UMTIME(X) ( UDF_I(X)->i_umtime ) #define UDF_I_UCTIME(X) ( UDF_I(X)->i_uctime ) +#define UDF_I_CRTIME(X) ( UDF_I(X)->i_crtime ) +#define UDF_I_UCRTIME(X) ( UDF_I(X)->i_ucrtime ) #endif /* !defined(_LINUX_UDF_I_H) */ diff -u --recursive --new-file v2.4.5/linux/fs/udf/udf_sb.h linux/fs/udf/udf_sb.h --- v2.4.5/linux/fs/udf/udf_sb.h Mon Mar 20 08:17:43 2000 +++ linux/fs/udf/udf_sb.h Mon Jun 11 19:15:27 2001 @@ -1,11 +1,11 @@ #ifndef __LINUX_UDF_SB_H #define __LINUX_UDF_SB_H -/* Since UDF 1.50 is ISO 13346 based... */ -#define UDF_SUPER_MAGIC 0x15013346 +/* Since UDF 2.01 is ISO 13346 based... */ +#define UDF_SUPER_MAGIC 0x15013346 -#define UDF_MAX_READ_VERSION 0x0200 -#define UDF_MAX_WRITE_VERSION 0x0200 +#define UDF_MAX_READ_VERSION 0x0201 +#define UDF_MAX_WRITE_VERSION 0x0201 #define UDF_FLAG_USE_EXTENDED_FE 0 #define UDF_VERS_USE_EXTENDED_FE 0x0200 @@ -14,16 +14,18 @@ #define UDF_FLAG_USE_SHORT_AD 2 #define UDF_FLAG_USE_AD_IN_ICB 3 #define UDF_FLAG_USE_FILE_CTIME_EA 4 -#define UDF_FLAG_STRICT 5 -#define UDF_FLAG_UNDELETE 6 -#define UDF_FLAG_UNHIDE 7 -#define UDF_FLAG_VARCONV 8 - -#define UDF_PART_FLAG_UNALLOC_BITMAP 0x0001 -#define UDF_PART_FLAG_UNALLOC_TABLE 0x0002 -#define UDF_PART_FLAG_FREED_BITMAP 0x0004 -#define UDF_PART_FLAG_FREED_TABLE 0x0008 - +#define UDF_FLAG_STRICT 5 +#define UDF_FLAG_UNDELETE 6 +#define UDF_FLAG_UNHIDE 7 +#define UDF_FLAG_VARCONV 8 +#define UDF_FLAG_NLS_MAP 9 +#define UDF_FLAG_UTF8 10 + +#define UDF_PART_FLAG_UNALLOC_BITMAP 0x0001 +#define UDF_PART_FLAG_UNALLOC_TABLE 0x0002 +#define UDF_PART_FLAG_FREED_BITMAP 0x0004 +#define UDF_PART_FLAG_FREED_TABLE 0x0008 + #define UDF_SB_FREE(X)\ {\ if (UDF_SB(X))\ @@ -37,11 +39,41 @@ #define UDF_SB_ALLOC_PARTMAPS(X,Y)\ {\ - UDF_SB_NUMPARTS(X) = Y;\ UDF_SB_PARTMAPS(X) = kmalloc(sizeof(struct udf_part_map) * Y, GFP_KERNEL);\ - memset(UDF_SB_PARTMAPS(X), 0x00, sizeof(struct udf_part_map) * Y);\ + if (UDF_SB_PARTMAPS(X) != NULL)\ + {\ + UDF_SB_NUMPARTS(X) = Y;\ + memset(UDF_SB_PARTMAPS(X), 0x00, sizeof(struct udf_part_map) * Y);\ + }\ + else\ + {\ + UDF_SB_NUMPARTS(X) = 0;\ + udf_error(X, __FUNCTION__, "Unable to allocate space for %d partition maps", Y);\ + }\ } +#define UDF_SB_ALLOC_BITMAP(X,Y,Z)\ +{\ + int nr_groups = ((UDF_SB_PARTLEN((X),(Y)) + (sizeof(struct SpaceBitmapDesc) << 3) +\ + ((X)->s_blocksize * 8) - 1) / ((X)->s_blocksize * 8));\ + UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap = kmalloc(sizeof(struct udf_bitmap) +\ + sizeof(struct buffer_head *) * nr_groups,\ + GFP_KERNEL);\ + if (UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap != NULL)\ + {\ + memset(UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap, 0x00,\ + sizeof(struct udf_bitmap) + sizeof(struct buffer_head *) * nr_groups);\ + UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap->s_block_bitmap =\ + (struct buffer_head **)(UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap + 1);\ + UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap->s_nr_groups = nr_groups;\ + }\ + else\ + {\ + udf_error(X, __FUNCTION__, "Unable to allocate space for bitmap and %d buffer_head pointers", nr_groups);\ + }\ +} + + #define UDF_QUERY_FLAG(X,Y) ( UDF_SB(X)->s_flags & ( 1 << (Y) ) ) #define UDF_SET_FLAG(X,Y) ( UDF_SB(X)->s_flags |= ( 1 << (Y) ) ) #define UDF_CLEAR_FLAG(X,Y) ( UDF_SB(X)->s_flags &= ~( 1 << (Y) ) ) @@ -58,6 +90,8 @@ #define UDF_SB_TYPEVIRT(X,Y) ( UDF_SB_PARTMAPS(X)[(Y)].s_type_specific.s_virtual ) #define UDF_SB_PARTFUNC(X,Y) ( UDF_SB_PARTMAPS(X)[(Y)].s_partition_func ) #define UDF_SB_PARTFLAGS(X,Y) ( UDF_SB_PARTMAPS(X)[(Y)].s_partition_flags ) +#define UDF_SB_BITMAP(X,Y,Z,I) ( UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap->s_block_bitmap[I] ) +#define UDF_SB_BITMAP_NR_GROUPS(X,Y,Z) ( UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap->s_nr_groups ) #define UDF_SB_VOLIDENT(X) ( UDF_SB(X)->s_volident ) #define UDF_SB_NUMPARTS(X) ( UDF_SB(X)->s_partitions ) @@ -69,9 +103,6 @@ #define UDF_SB_LVID(X) ( (struct LogicalVolIntegrityDesc *)UDF_SB_LVIDBH(X)->b_data ) #define UDF_SB_LVIDIU(X) ( (struct LogicalVolIntegrityDescImpUse *)&(UDF_SB_LVID(X)->impUse[UDF_SB_LVID(X)->numOfPartitions * 2 * sizeof(Uint32)/sizeof(Uint8)]) ) -#define UDF_SB_LOADED_BLOCK_BITMAPS(X) ( UDF_SB(X)->s_loaded_block_bitmaps ) -#define UDF_SB_BLOCK_BITMAP_NUMBER(X,Y) ( UDF_SB(X)->s_block_bitmap_number[(Y)] ) -#define UDF_SB_BLOCK_BITMAP(X,Y) ( UDF_SB(X)->s_block_bitmap[(Y)] ) #define UDF_SB_UMASK(X) ( UDF_SB(X)->s_umask ) #define UDF_SB_GID(X) ( UDF_SB(X)->s_gid ) #define UDF_SB_UID(X) ( UDF_SB(X)->s_uid ) diff -u --recursive --new-file v2.4.5/linux/fs/udf/udfdecl.h linux/fs/udf/udfdecl.h --- v2.4.5/linux/fs/udf/udfdecl.h Mon Dec 11 13:27:05 2000 +++ linux/fs/udf/udfdecl.h Mon Jun 11 19:15:27 2001 @@ -12,14 +12,6 @@ #include #include -#ifndef LINUX_VERSION_CODE -#include -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,7) -#error "The UDF Module Current Requires Kernel Version 2.3.7 or greater" -#endif - #include #if !defined(CONFIG_UDF_FS) && !defined(CONFIG_UDF_FS_MODULE) @@ -119,7 +111,7 @@ extern void udf_warning(struct super_block *, const char *, const char *, ...); /* namei.c */ -extern int udf_write_fi(struct FileIdentDesc *, struct FileIdentDesc *, struct udf_fileident_bh *, Uint8 *, Uint8 *); +extern int udf_write_fi(struct inode *inode, struct FileIdentDesc *, struct FileIdentDesc *, struct udf_fileident_bh *, Uint8 *, Uint8 *); /* file.c */ extern int udf_ioctl(struct inode *, struct file *, unsigned int, unsigned long); @@ -131,15 +123,15 @@ extern struct buffer_head * udf_expand_dir_adinicb(struct inode *, int *, int *); extern struct buffer_head * udf_getblk(struct inode *, long, int, int *); extern struct buffer_head * udf_bread(struct inode *, int, int, int *); +extern void udf_truncate(struct inode *); extern void udf_read_inode(struct inode *); extern void udf_put_inode(struct inode *); extern void udf_delete_inode(struct inode *); extern void udf_write_inode(struct inode *, int); -extern long udf_locked_block_map(struct inode *, long); extern long udf_block_map(struct inode *, long); extern int inode_bmap(struct inode *, int, lb_addr *, Uint32 *, lb_addr *, Uint32 *, Uint32 *, struct buffer_head **); extern int udf_add_aext(struct inode *, lb_addr *, int *, lb_addr, Uint32, struct buffer_head **, int); -extern int udf_write_aext(struct inode *, lb_addr, int *, lb_addr, Uint32, struct buffer_head **, int); +extern int udf_write_aext(struct inode *, lb_addr, int *, lb_addr, Uint32, struct buffer_head *, int); extern int udf_insert_aext(struct inode *, lb_addr, int, lb_addr, Uint32, struct buffer_head *); extern int udf_delete_aext(struct inode *, lb_addr, int, lb_addr, Uint32, struct buffer_head *); extern int udf_next_aext(struct inode *, lb_addr *, int *, lb_addr *, Uint32 *, struct buffer_head **, int); @@ -148,6 +140,7 @@ /* misc.c */ extern int udf_read_tagged_data(char *, int size, int fd, int block, int partref); +extern struct buffer_head *udf_tgetblk(struct super_block *, int, int); extern struct buffer_head *udf_tread(struct super_block *, int, int); extern struct GenericAttrFormat *udf_add_extendedattr(struct inode *, Uint32, Uint32, Uint8, struct buffer_head **); extern struct GenericAttrFormat *udf_get_extendedattr(struct inode *, Uint32, Uint8, struct buffer_head **); @@ -165,18 +158,17 @@ extern Uint32 udf_get_pblock_virt15(struct super_block *, Uint32, Uint16, Uint32); extern Uint32 udf_get_pblock_virt20(struct super_block *, Uint32, Uint16, Uint32); extern Uint32 udf_get_pblock_spar15(struct super_block *, Uint32, Uint16, Uint32); -extern void udf_fill_spartable(struct super_block *, struct udf_sparing_data *, int); +extern int udf_relocate_blocks(struct super_block *, long, long *); /* unicode.c */ -extern int udf_get_filename(Uint8 *, Uint8 *, int); +extern int udf_get_filename(struct super_block *, Uint8 *, Uint8 *, int); /* ialloc.c */ extern void udf_free_inode(struct inode *); extern struct inode * udf_new_inode (const struct inode *, int, int *); /* truncate.c */ -extern void udf_trunc(struct inode *); -extern void udf_truncate(struct inode *); +extern void udf_truncate_extents(struct inode *); /* balloc.c */ extern void udf_free_blocks(const struct inode *, lb_addr, Uint32, Uint32); @@ -184,7 +176,8 @@ extern int udf_new_block(const struct inode *, Uint16, Uint32, int *); /* fsync.c */ -extern int udf_sync_file(struct file *, struct dentry *, int); +extern int udf_fsync_file(struct file *, struct dentry *, int); +extern int udf_fsync_inode(struct inode *, int); /* directory.c */ extern Uint8 * udf_filead_read(struct inode *, Uint8 *, Uint8, lb_addr, int *, int *, struct buffer_head **, int *); @@ -206,6 +199,10 @@ extern int udf_build_ustr_exact(struct ustr *, dstring *, int); extern int udf_CS0toUTF8(struct ustr *, struct ustr *); extern int udf_UTF8toCS0(dstring *, struct ustr *, int); +#ifdef __KERNEL__ +extern int udf_CS0toNLS(struct nls_table *, struct ustr *, struct ustr *); +extern int udf_NLStoCS0(struct nls_table *, dstring *, struct ustr *, int); +#endif /* crc.c */ extern Uint16 udf_crc(Uint8 *, Uint32, Uint16); diff -u --recursive --new-file v2.4.5/linux/fs/udf/udfend.h linux/fs/udf/udfend.h --- v2.4.5/linux/fs/udf/udfend.h Mon Dec 11 13:27:05 2000 +++ linux/fs/udf/udfend.h Mon Jun 11 19:15:27 2001 @@ -80,6 +80,22 @@ return out; } +static inline short_ad lesa_to_cpu(short_ad in) +{ + short_ad out; + out.extLength = le32_to_cpu(in.extLength); + out.extPosition = le32_to_cpu(in.extPosition); + return out; +} + +static inline short_ad cpu_to_lesa(short_ad in) +{ + short_ad out; + out.extLength = cpu_to_le32(in.extLength); + out.extPosition = cpu_to_le32(in.extPosition); + return out; +} + static inline long_ad lela_to_cpu(long_ad in) { long_ad out; diff -u --recursive --new-file v2.4.5/linux/fs/udf/udftime.c linux/fs/udf/udftime.c --- v2.4.5/linux/fs/udf/udftime.c Thu Mar 2 11:17:32 2000 +++ linux/fs/udf/udftime.c Mon Jun 11 19:15:27 2001 @@ -105,6 +105,8 @@ offset = src.typeAndTimezone << 4; /* sign extent offset */ offset = (offset >> 4); + if (offset == -2047) /* unspecified offset */ + offset = 0; } else offset = 0; diff -u --recursive --new-file v2.4.5/linux/fs/udf/unicode.c linux/fs/udf/unicode.c --- v2.4.5/linux/fs/udf/unicode.c Mon Mar 20 08:17:43 2000 +++ linux/fs/udf/unicode.c Mon Jun 11 19:15:27 2001 @@ -14,7 +14,7 @@ * CONTACTS * E-mail regarding any portion of the Linux UDF file system should be * directed to the development team's mailing list (run by majordomo): - * linux_udf@hootie.lvld.hp.com + * linux_udf@hpesjro.fc.hp.com * * COPYRIGHT * This file is distributed under the terms of the GNU General Public @@ -27,7 +27,9 @@ #ifdef __KERNEL__ #include #include /* for memset */ +#include #include +#include "udf_sb.h" #else #include #endif @@ -127,7 +129,7 @@ } /* - * udf_ocu_to_udf8 + * udf_ocu_to_utf8 * * PURPOSE * Convert OSTA Compressed Unicode to the UTF-8 equivalent. @@ -327,7 +329,88 @@ } #ifdef __KERNEL__ -int udf_get_filename(Uint8 *sname, Uint8 *dname, int flen) +int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, struct ustr *ocu_i) +{ + Uint8 *ocu; + Uint32 c; + Uint8 cmp_id, ocu_len; + int i; + + ocu = ocu_i->u_name; + + ocu_len = ocu_i->u_len; + cmp_id = ocu_i->u_cmpID; + utf_o->u_len = 0; + + if (ocu_len == 0) + { + memset(utf_o, 0, sizeof(struct ustr)); + utf_o->u_cmpID = 0; + utf_o->u_len = 0; + return 0; + } + + if ((cmp_id != 8) && (cmp_id != 16)) + { + printk(KERN_ERR "udf: unknown compression code (%d) stri=%s\n", cmp_id, ocu_i->u_name); + return 0; + } + + for (i = 0; (i < ocu_len) && (utf_o->u_len <= (UDF_NAME_LEN-3)) ;) + { + /* Expand OSTA compressed Unicode to Unicode */ + c = ocu[i++]; + if (cmp_id == 16) + c = (c << 8) | ocu[i++]; + + utf_o->u_len += nls->uni2char(c, &utf_o->u_name[utf_o->u_len], + UDF_NAME_LEN - utf_o->u_len); + } + utf_o->u_cmpID=8; + utf_o->u_hash=0L; + utf_o->padding=0; + + return utf_o->u_len; +} + +int udf_NLStoCS0(struct nls_table *nls, dstring *ocu, struct ustr *uni, int length) +{ + unsigned len, i, max_val; + Uint16 uni_char; + int uni_cnt; + int u_len = 0; + + memset(ocu, 0, sizeof(dstring) * length); + ocu[0] = 8; + max_val = 0xffU; + +try_again: + uni_char = 0U; + uni_cnt = 0U; + for (i = 0U; i < uni->u_len; i++) + { + len = nls->char2uni(&uni->u_name[i], uni->u_len-i, &uni_char); + + if (len == 2 && max_val == 0xff) + { + max_val = 0xffffU; + ocu[0] = (Uint8)0x10U; + goto try_again; + } + + if (max_val == 0xffffU) + { + ocu[++u_len] = (Uint8)(uni_char >> 8); + i++; + } + ocu[++u_len] = (Uint8)(uni_char & 0xffU); + } + + ocu[length - 1] = (Uint8)u_len + 1; + return u_len + 1; +} + +int udf_get_filename(struct super_block *sb, Uint8 *sname, Uint8 *dname, int flen) { struct ustr filename, unifilename; int len; @@ -337,11 +420,24 @@ return 0; } - if (!udf_CS0toUTF8(&filename, &unifilename) ) + if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8)) { - udf_debug("Failed in udf_get_filename: sname = %s\n", sname); - return 0; + if (!udf_CS0toUTF8(&filename, &unifilename) ) + { + udf_debug("Failed in udf_get_filename: sname = %s\n", sname); + return 0; + } + } + else if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP)) + { + if (!udf_CS0toNLS(UDF_SB(sb)->s_nls_map, &filename, &unifilename) ) + { + udf_debug("Failed in udf_get_filename: sname = %s\n", sname); + return 0; + } } + else + return 0; if ((len = udf_translate_to_linux(dname, filename.u_name, filename.u_len, unifilename.u_name, unifilename.u_len))) diff -u --recursive --new-file v2.4.5/linux/include/asm-alpha/delay.h linux/include/asm-alpha/delay.h --- v2.4.5/linux/include/asm-alpha/delay.h Tue Jan 2 16:45:37 2001 +++ linux/include/asm-alpha/delay.h Wed Jun 20 11:10:27 2001 @@ -1,48 +1,8 @@ #ifndef __ALPHA_DELAY_H #define __ALPHA_DELAY_H -#include -#include -#include - -/* - * Copyright (C) 1993, 2000 Linus Torvalds - * - * Delay routines, using a pre-computed "loops_per_jiffy" value. - */ - -/* - * Use only for very small delays (< 1 msec). - * - * The active part of our cycle counter is only 32-bits wide, and - * we're treating the difference between two marks as signed. On - * a 1GHz box, that's about 2 seconds. - */ - -extern __inline__ void -__delay(int loops) -{ - int tmp; - __asm__ __volatile__( - " rpcc %0\n" - " addl %1,%0,%1\n" - "1: rpcc %0\n" - " subl %1,%0,%0\n" - " bgt %0,1b" - : "=&r" (tmp), "=r" (loops) : "1"(loops)); -} - -extern __inline__ void -__udelay(unsigned long usecs, unsigned long lpj) -{ - usecs *= (((unsigned long)HZ << 32) / 1000000) * lpj; - __delay((long)usecs >> 32); -} - -#ifdef CONFIG_SMP -#define udelay(u) __udelay((u), cpu_data[smp_processor_id()].loops_per_jiffy) -#else -#define udelay(u) __udelay((u), loops_per_jiffy) -#endif +extern void __delay(int loops); +extern void __udelay(unsigned long usecs, unsigned long lpj); +extern void udelay(unsigned long usecs); #endif /* defined(__ALPHA_DELAY_H) */ diff -u --recursive --new-file v2.4.5/linux/include/asm-alpha/hardirq.h linux/include/asm-alpha/hardirq.h --- v2.4.5/linux/include/asm-alpha/hardirq.h Fri Aug 4 16:15:37 2000 +++ linux/include/asm-alpha/hardirq.h Mon Jun 11 19:15:27 2001 @@ -6,8 +6,7 @@ /* entry.S is sensitive to the offsets of these fields */ typedef struct { - unsigned int __softirq_active; - unsigned int __softirq_mask; + unsigned long __softirq_pending; unsigned int __local_irq_count; unsigned int __local_bh_count; unsigned int __syscall_count; diff -u --recursive --new-file v2.4.5/linux/include/asm-alpha/linux_logo.h linux/include/asm-alpha/linux_logo.h --- v2.4.5/linux/include/asm-alpha/linux_logo.h Thu Oct 1 10:02:22 1998 +++ linux/include/asm-alpha/linux_logo.h Mon Jun 11 19:15:27 2001 @@ -23,26 +23,5 @@ #define linux_logo_banner "Linux/AXP version " UTS_RELEASE -#define LINUX_LOGO_COLORS 214 - -#ifdef INCLUDE_LINUX_LOGO_DATA - -#define INCLUDE_LINUX_LOGOBW -#define INCLUDE_LINUX_LOGO16 - #include -#else - -/* prototypes only */ -extern unsigned char linux_logo_red[]; -extern unsigned char linux_logo_green[]; -extern unsigned char linux_logo_blue[]; -extern unsigned char linux_logo[]; -extern unsigned char linux_logo_bw[]; -extern unsigned char linux_logo16_red[]; -extern unsigned char linux_logo16_green[]; -extern unsigned char linux_logo16_blue[]; -extern unsigned char linux_logo16[]; - -#endif diff -u --recursive --new-file v2.4.5/linux/include/asm-alpha/socket.h linux/include/asm-alpha/socket.h --- v2.4.5/linux/include/asm-alpha/socket.h Sat Feb 3 11:26:44 2001 +++ linux/include/asm-alpha/socket.h Wed Jun 20 21:00:55 2001 @@ -66,6 +66,7 @@ /* level. For writing rarp and */ /* other similar things on the */ /* user level. */ +#define SOCK_MAX (SOCK_PACKET+1) #endif #endif /* _ASM_SOCKET_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-alpha/softirq.h linux/include/asm-alpha/softirq.h --- v2.4.5/linux/include/asm-alpha/softirq.h Sun Aug 6 12:42:21 2000 +++ linux/include/asm-alpha/softirq.h Mon Jun 11 19:15:27 2001 @@ -18,8 +18,11 @@ } #define local_bh_enable() cpu_bh_enable(smp_processor_id()) +#define __local_bh_enable local_bh_enable #define local_bh_disable() cpu_bh_disable(smp_processor_id()) #define in_softirq() (local_bh_count(smp_processor_id()) != 0) + +#define __cpu_raise_softirq(cpu,nr) set_bit((nr), &softirq_pending(cpu)) #endif /* _ALPHA_SOFTIRQ_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-alpha/termios.h linux/include/asm-alpha/termios.h --- v2.4.5/linux/include/asm-alpha/termios.h Sat Feb 3 20:00:45 2001 +++ linux/include/asm-alpha/termios.h Mon Jun 11 19:15:27 2001 @@ -82,6 +82,7 @@ #define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */ #define N_HDLC 13 /* synchronous HDLC */ #define N_SYNC_PPP 14 +#define N_HCI 15 /* Bluetooth HCI UART */ #ifdef __KERNEL__ /* eof=^D eol=\0 eol2=\0 erase=del diff -u --recursive --new-file v2.4.5/linux/include/asm-arm/bitops.h linux/include/asm-arm/bitops.h --- v2.4.5/linux/include/asm-arm/bitops.h Mon Nov 27 17:07:59 2000 +++ linux/include/asm-arm/bitops.h Wed Jun 27 14:12:04 2001 @@ -24,12 +24,62 @@ * Function prototypes to keep gcc -Wall happy. */ extern void set_bit(int nr, volatile void * addr); + +static inline void __set_bit(int nr, volatile void *addr) +{ + ((unsigned char *) addr)[nr >> 3] |= (1U << (nr & 7)); +} + extern void clear_bit(int nr, volatile void * addr); + +static inline void __clear_bit(int nr, volatile void *addr) +{ + ((unsigned char *) addr)[nr >> 3] &= ~(1U << (nr & 7)); +} + extern void change_bit(int nr, volatile void * addr); +static inline void __change_bit(int nr, volatile void *addr) +{ + ((unsigned char *) addr)[nr >> 3] ^= (1U << (nr & 7)); +} + extern int test_and_set_bit(int nr, volatile void * addr); + +static inline int __test_and_set_bit(int nr, volatile void *addr) +{ + unsigned int mask = 1 << (nr & 7); + unsigned int oldval; + + oldval = ((unsigned char *) addr)[nr >> 3]; + ((unsigned char *) addr)[nr >> 3] = oldval | mask; + return oldval & mask; +} + extern int test_and_clear_bit(int nr, volatile void * addr); + +static inline int __test_and_clear_bit(int nr, volatile void *addr) +{ + unsigned int mask = 1 << (nr & 7); + unsigned int oldval; + + oldval = ((unsigned char *) addr)[nr >> 3]; + ((unsigned char *) addr)[nr >> 3] = oldval & ~mask; + return oldval & mask; +} + extern int test_and_change_bit(int nr, volatile void * addr); + +static inline int __test_and_change_bit(int nr, volatile void *addr) +{ + unsigned int mask = 1 << (nr & 7); + unsigned int oldval; + + oldval = ((unsigned char *) addr)[nr >> 3]; + ((unsigned char *) addr)[nr >> 3] = oldval ^ mask; + return oldval & mask; +} + extern int find_first_zero_bit(void * addr, unsigned size); extern int find_next_zero_bit(void * addr, int size, int offset); diff -u --recursive --new-file v2.4.5/linux/include/asm-arm/io.h linux/include/asm-arm/io.h --- v2.4.5/linux/include/asm-arm/io.h Thu Apr 12 12:20:31 2001 +++ linux/include/asm-arm/io.h Wed Jun 27 14:12:04 2001 @@ -119,7 +119,7 @@ * is in pci.h */ extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle); -extern void consistent_free(void *vaddr); +extern void consistent_free(void *vaddr, size_t size, dma_addr_t handle); extern void consistent_sync(void *vaddr, size_t size, int rw); #define __raw_writeb(v,a) __arch_putb(v,a) diff -u --recursive --new-file v2.4.5/linux/include/asm-arm/linux_logo.h linux/include/asm-arm/linux_logo.h --- v2.4.5/linux/include/asm-arm/linux_logo.h Thu Feb 8 16:32:44 2001 +++ linux/include/asm-arm/linux_logo.h Mon Jun 11 19:15:27 2001 @@ -15,26 +15,5 @@ #define linux_logo_banner "ARM Linux version " UTS_RELEASE -#define LINUX_LOGO_COLORS 214 - -#ifdef INCLUDE_LINUX_LOGO_DATA - -#define INCLUDE_LINUX_LOGOBW -#define INCLUDE_LINUX_LOGO16 - #include -#else - -/* prototypes only */ -extern unsigned char linux_logo_red[]; -extern unsigned char linux_logo_green[]; -extern unsigned char linux_logo_blue[]; -extern unsigned char linux_logo[]; -extern unsigned char linux_logo_bw[]; -extern unsigned char linux_logo16[]; -extern unsigned char *linux_serial_image; - -extern int (*console_show_logo)(void); - -#endif diff -u --recursive --new-file v2.4.5/linux/include/asm-arm/pci.h linux/include/asm-arm/pci.h --- v2.4.5/linux/include/asm-arm/pci.h Wed May 16 10:31:27 2001 +++ linux/include/asm-arm/pci.h Wed Jun 27 14:12:04 2001 @@ -41,7 +41,7 @@ pci_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) { - consistent_free(vaddr); + consistent_free(vaddr, size, dma_handle); } /* Map a single buffer of the indicated size for DMA in streaming mode. diff -u --recursive --new-file v2.4.5/linux/include/asm-arm/proc-armo/system.h linux/include/asm-arm/proc-armo/system.h --- v2.4.5/linux/include/asm-arm/proc-armo/system.h Mon Sep 18 15:15:24 2000 +++ linux/include/asm-arm/proc-armo/system.h Wed Jun 27 14:12:04 2001 @@ -12,6 +12,8 @@ #include +#define vectors_base() (0) + extern __inline__ unsigned long __xchg(unsigned long x, volatile void *ptr, int size) { extern void __bad_xchg(volatile void *, int); diff -u --recursive --new-file v2.4.5/linux/include/asm-arm/proc-armv/system.h linux/include/asm-arm/proc-armv/system.h --- v2.4.5/linux/include/asm-arm/proc-armv/system.h Mon Nov 27 17:07:59 2000 +++ linux/include/asm-arm/proc-armv/system.h Wed Jun 27 14:12:04 2001 @@ -17,8 +17,30 @@ "mcr p15, 0, %0, c1, c0 @ set CR" \ : : "r" (x)) +#define CR_M (1 << 0) /* MMU enable */ +#define CR_A (1 << 1) /* Alignment abort enable */ +#define CR_C (1 << 2) /* Dcache enable */ +#define CR_W (1 << 3) /* Write buffer enable */ +#define CR_P (1 << 4) /* 32-bit exception handler */ +#define CR_D (1 << 5) /* 32-bit data address range */ +#define CR_L (1 << 6) /* Implementation defined */ +#define CD_B (1 << 7) /* Big endian */ +#define CR_S (1 << 8) /* System MMU protection */ +#define CD_R (1 << 9) /* ROM MMU protection */ +#define CR_F (1 << 10) /* Implementation defined */ +#define CR_Z (1 << 11) /* Implementation defined */ +#define CR_I (1 << 12) /* Icache enable */ +#define CR_V (1 << 13) /* Vectors relocated to 0xffff0000 */ +#define CR_RR (1 << 14) /* Round Robin cache replacement */ + extern unsigned long cr_no_alignment; /* defined in entry-armv.S */ extern unsigned long cr_alignment; /* defined in entry-armv.S */ + +#ifdef __ARM_ARCH_4__ +#define vectors_base() ((cr_alignment & CR_V) ? 0xffff0000 : 0) +#else +#define vectors_base() (0) +#endif /* * A couple of speedups for the ARM diff -u --recursive --new-file v2.4.5/linux/include/asm-arm/socket.h linux/include/asm-arm/socket.h --- v2.4.5/linux/include/asm-arm/socket.h Sat Feb 3 11:26:44 2001 +++ linux/include/asm-arm/socket.h Wed Jun 20 21:00:55 2001 @@ -58,6 +58,7 @@ /* level. For writing rarp and */ /* other similar things on the */ /* user level. */ +#define SOCK_MAX (SOCK_PACKET+1) #endif #endif /* _ASM_SOCKET_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-arm/termios.h linux/include/asm-arm/termios.h --- v2.4.5/linux/include/asm-arm/termios.h Sat Feb 3 20:00:45 2001 +++ linux/include/asm-arm/termios.h Mon Jun 11 19:15:27 2001 @@ -65,6 +65,7 @@ #define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */ #define N_HDLC 13 /* synchronous HDLC */ #define N_SYNC_PPP 14 +#define N_HCI 15 /* Bluetooth HCI UART */ #ifdef __KERNEL__ diff -u --recursive --new-file v2.4.5/linux/include/asm-arm/xor.h linux/include/asm-arm/xor.h --- v2.4.5/linux/include/asm-arm/xor.h Thu Apr 12 12:20:31 2001 +++ linux/include/asm-arm/xor.h Wed Jun 27 14:12:04 2001 @@ -7,290 +7,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ - -/* - * linux/include/asm-arm/xor.h - * - * Copyright (C) 2001 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. - */ - -/* - * linux/include/asm-arm/xor.h - * - * Copyright (C) 2001 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. - */ - #include - -#define __XOR(a1, a2) a1 ^= a2 - -#define GET_BLOCK_2(dst) \ - __asm__("ldmia %0, {%1, %2}" \ - : "=r" (dst), "=r" (a1), "=r" (a2) \ - : "0" (dst)) - -#define GET_BLOCK_4(dst) \ - __asm__("ldmia %0, {%1, %2, %3, %4}" \ - : "=r" (dst), "=r" (a1), "=r" (a2), "=r" (a3), "=r" (a4) \ - : "0" (dst)) - -#define XOR_BLOCK_2(src) \ - __asm__("ldmia %0!, {%1, %2}" \ - : "=r" (src), "=r" (b1), "=r" (b2) \ - : "0" (src)); \ - __XOR(a1, b1); __XOR(a2, b2); - -#define XOR_BLOCK_4(src) \ - __asm__("ldmia %0!, {%1, %2, %3, %4}" \ - : "=r" (src), "=r" (b1), "=r" (b2), "=r" (b3), "=r" (b4) \ - : "0" (src)); \ - __XOR(a1, b1); __XOR(a2, b2); __XOR(a3, b3); __XOR(a4, b4) - -#define PUT_BLOCK_2(dst) \ - __asm__ __volatile__("stmia %0!, {%2, %3}" \ - : "=r" (dst) \ - : "0" (dst), "r" (a1), "r" (a2)) - -#define PUT_BLOCK_4(dst) \ - __asm__ __volatile__("stmia %0!, {%2, %3, %4, %5}" \ - : "=r" (dst) \ - : "0" (dst), "r" (a1), "r" (a2), "r" (a3), "r" (a4)) - -static void -xor_arm4regs_2(unsigned long bytes, unsigned long *p1, unsigned long *p2) -{ - unsigned int lines = bytes / sizeof(unsigned long) / 4; - register unsigned int a1 __asm__("r4"); - register unsigned int a2 __asm__("r5"); - register unsigned int a3 __asm__("r6"); - register unsigned int a4 __asm__("r7"); - register unsigned int b1 __asm__("r8"); - register unsigned int b2 __asm__("r9"); - register unsigned int b3 __asm__("ip"); - register unsigned int b4 __asm__("lr"); - - do { - GET_BLOCK_4(p1); - XOR_BLOCK_4(p2); - PUT_BLOCK_4(p1); - } while (--lines); -} - -static void -xor_arm4regs_3(unsigned long bytes, unsigned long *p1, unsigned long *p2, - unsigned long *p3) -{ - unsigned int lines = bytes / sizeof(unsigned long) / 4; - register unsigned int a1 __asm__("r4"); - register unsigned int a2 __asm__("r5"); - register unsigned int a3 __asm__("r6"); - register unsigned int a4 __asm__("r7"); - register unsigned int b1 __asm__("r8"); - register unsigned int b2 __asm__("r9"); - register unsigned int b3 __asm__("ip"); - register unsigned int b4 __asm__("lr"); - - do { - GET_BLOCK_4(p1); - XOR_BLOCK_4(p2); - XOR_BLOCK_4(p3); - PUT_BLOCK_4(p1); - } while (--lines); -} - -static void -xor_arm4regs_4(unsigned long bytes, unsigned long *p1, unsigned long *p2, - unsigned long *p3, unsigned long *p4) -{ - unsigned int lines = bytes / sizeof(unsigned long) / 2; - register unsigned int a1 __asm__("r8"); - register unsigned int a2 __asm__("r9"); - register unsigned int b1 __asm__("ip"); - register unsigned int b2 __asm__("lr"); - - do { - GET_BLOCK_2(p1); - XOR_BLOCK_2(p2); - XOR_BLOCK_2(p3); - XOR_BLOCK_2(p4); - PUT_BLOCK_2(p1); - } while (--lines); -} - -static void -xor_arm4regs_5(unsigned long bytes, unsigned long *p1, unsigned long *p2, - unsigned long *p3, unsigned long *p4, unsigned long *p5) -{ - unsigned int lines = bytes / sizeof(unsigned long) / 2; - register unsigned int a1 __asm__("r8"); - register unsigned int a2 __asm__("r9"); - register unsigned int b1 __asm__("ip"); - register unsigned int b2 __asm__("lr"); - - do { - GET_BLOCK_2(p1); - XOR_BLOCK_2(p2); - XOR_BLOCK_2(p3); - XOR_BLOCK_2(p4); - XOR_BLOCK_2(p5); - PUT_BLOCK_2(p1); - } while (--lines); -} - -static struct xor_block_template xor_block_arm4regs = { - name: "arm4regs", - do_2: xor_arm4regs_2, - do_3: xor_arm4regs_3, - do_4: xor_arm4regs_4, - do_5: xor_arm4regs_5, -}; - -#undef XOR_TRY_TEMPLATES -#define XOR_TRY_TEMPLATES \ - do { \ - xor_speed(&xor_block_arm4regs); \ - xor_speed(&xor_block_8regs); \ - xor_speed(&xor_block_32regs); \ - } while (0) - -#define __XOR(a1, a2) a1 ^= a2 - -#define GET_BLOCK_2(dst) \ - __asm__("ldmia %0, {%1, %2}" \ - : "=r" (dst), "=r" (a1), "=r" (a2) \ - : "0" (dst)) - -#define GET_BLOCK_4(dst) \ - __asm__("ldmia %0, {%1, %2, %3, %4}" \ - : "=r" (dst), "=r" (a1), "=r" (a2), "=r" (a3), "=r" (a4) \ - : "0" (dst)) - -#define XOR_BLOCK_2(src) \ - __asm__("ldmia %0!, {%1, %2}" \ - : "=r" (src), "=r" (b1), "=r" (b2) \ - : "0" (src)); \ - __XOR(a1, b1); __XOR(a2, b2); - -#define XOR_BLOCK_4(src) \ - __asm__("ldmia %0!, {%1, %2, %3, %4}" \ - : "=r" (src), "=r" (b1), "=r" (b2), "=r" (b3), "=r" (b4) \ - : "0" (src)); \ - __XOR(a1, b1); __XOR(a2, b2); __XOR(a3, b3); __XOR(a4, b4) - -#define PUT_BLOCK_2(dst) \ - __asm__ __volatile__("stmia %0!, {%2, %3}" \ - : "=r" (dst) \ - : "0" (dst), "r" (a1), "r" (a2)) - -#define PUT_BLOCK_4(dst) \ - __asm__ __volatile__("stmia %0!, {%2, %3, %4, %5}" \ - : "=r" (dst) \ - : "0" (dst), "r" (a1), "r" (a2), "r" (a3), "r" (a4)) - -static void -xor_arm4regs_2(unsigned long bytes, unsigned long *p1, unsigned long *p2) -{ - unsigned int lines = bytes / sizeof(unsigned long) / 4; - register unsigned int a1 __asm__("r4"); - register unsigned int a2 __asm__("r5"); - register unsigned int a3 __asm__("r6"); - register unsigned int a4 __asm__("r7"); - register unsigned int b1 __asm__("r8"); - register unsigned int b2 __asm__("r9"); - register unsigned int b3 __asm__("ip"); - register unsigned int b4 __asm__("lr"); - - do { - GET_BLOCK_4(p1); - XOR_BLOCK_4(p2); - PUT_BLOCK_4(p1); - } while (--lines); -} - -static void -xor_arm4regs_3(unsigned long bytes, unsigned long *p1, unsigned long *p2, - unsigned long *p3) -{ - unsigned int lines = bytes / sizeof(unsigned long) / 4; - register unsigned int a1 __asm__("r4"); - register unsigned int a2 __asm__("r5"); - register unsigned int a3 __asm__("r6"); - register unsigned int a4 __asm__("r7"); - register unsigned int b1 __asm__("r8"); - register unsigned int b2 __asm__("r9"); - register unsigned int b3 __asm__("ip"); - register unsigned int b4 __asm__("lr"); - - do { - GET_BLOCK_4(p1); - XOR_BLOCK_4(p2); - XOR_BLOCK_4(p3); - PUT_BLOCK_4(p1); - } while (--lines); -} - -static void -xor_arm4regs_4(unsigned long bytes, unsigned long *p1, unsigned long *p2, - unsigned long *p3, unsigned long *p4) -{ - unsigned int lines = bytes / sizeof(unsigned long) / 2; - register unsigned int a1 __asm__("r8"); - register unsigned int a2 __asm__("r9"); - register unsigned int b1 __asm__("ip"); - register unsigned int b2 __asm__("lr"); - - do { - GET_BLOCK_2(p1); - XOR_BLOCK_2(p2); - XOR_BLOCK_2(p3); - XOR_BLOCK_2(p4); - PUT_BLOCK_2(p1); - } while (--lines); -} - -static void -xor_arm4regs_5(unsigned long bytes, unsigned long *p1, unsigned long *p2, - unsigned long *p3, unsigned long *p4, unsigned long *p5) -{ - unsigned int lines = bytes / sizeof(unsigned long) / 2; - register unsigned int a1 __asm__("r8"); - register unsigned int a2 __asm__("r9"); - register unsigned int b1 __asm__("ip"); - register unsigned int b2 __asm__("lr"); - - do { - GET_BLOCK_2(p1); - XOR_BLOCK_2(p2); - XOR_BLOCK_2(p3); - XOR_BLOCK_2(p4); - XOR_BLOCK_2(p5); - PUT_BLOCK_2(p1); - } while (--lines); -} - -static struct xor_block_template xor_block_arm4regs = { - name: "arm4regs", - do_2: xor_arm4regs_2, - do_3: xor_arm4regs_3, - do_4: xor_arm4regs_4, - do_5: xor_arm4regs_5, -}; - -#undef XOR_TRY_TEMPLATES -#define XOR_TRY_TEMPLATES \ - do { \ - xor_speed(&xor_block_arm4regs); \ - xor_speed(&xor_block_8regs); \ - xor_speed(&xor_block_32regs); \ - } while (0) #define __XOR(a1, a2) a1 ^= a2 diff -u --recursive --new-file v2.4.5/linux/include/asm-cris/socket.h linux/include/asm-cris/socket.h --- v2.4.5/linux/include/asm-cris/socket.h Fri Apr 6 10:51:19 2001 +++ linux/include/asm-cris/socket.h Wed Jun 20 21:00:55 2001 @@ -59,6 +59,7 @@ /* level. For writing rarp and */ /* other similar things on the */ /* user level. */ +#define SOCK_MAX (SOCK_PACKET+1) #endif #endif /* _ASM_SOCKET_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-i386/elf.h linux/include/asm-i386/elf.h --- v2.4.5/linux/include/asm-i386/elf.h Fri May 25 18:01:26 2001 +++ linux/include/asm-i386/elf.h Tue Jul 3 15:45:56 2001 @@ -55,7 +55,7 @@ the loader. We need to make sure that it is out of the way of the program that it will "exec", and that there is sufficient room for the brk. */ -#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3) +#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) /* Wow, the "main" arch needs arch dependent functions too.. :) */ diff -u --recursive --new-file v2.4.5/linux/include/asm-i386/hardirq.h linux/include/asm-i386/hardirq.h --- v2.4.5/linux/include/asm-i386/hardirq.h Fri May 25 18:01:27 2001 +++ linux/include/asm-i386/hardirq.h Tue Jul 3 15:42:55 2001 @@ -5,10 +5,9 @@ #include #include -/* entry.S is sensitive to the offsets of these fields */ +/* assembly code in softirq.h is sensitive to the offsets of these fields */ typedef struct { - unsigned int __softirq_active; - unsigned int __softirq_mask; + unsigned int __softirq_pending; unsigned int __local_irq_count; unsigned int __local_bh_count; unsigned int __syscall_count; diff -u --recursive --new-file v2.4.5/linux/include/asm-i386/hw_irq.h linux/include/asm-i386/hw_irq.h --- v2.4.5/linux/include/asm-i386/hw_irq.h Fri May 25 18:01:26 2001 +++ linux/include/asm-i386/hw_irq.h Tue Jul 3 15:42:54 2001 @@ -13,6 +13,7 @@ */ #include +#include #include /* @@ -83,7 +84,9 @@ extern void send_IPI(int dest, int vector); extern unsigned long io_apic_irqs; -extern volatile unsigned long irq_err_count; + +extern atomic_t irq_err_count; +extern atomic_t irq_mis_count; extern char _stext, _etext; diff -u --recursive --new-file v2.4.5/linux/include/asm-i386/io_apic.h linux/include/asm-i386/io_apic.h --- v2.4.5/linux/include/asm-i386/io_apic.h Fri May 25 18:01:26 2001 +++ linux/include/asm-i386/io_apic.h Tue Jul 3 15:42:54 2001 @@ -12,6 +12,8 @@ #ifdef CONFIG_X86_IO_APIC +#define APIC_MISMATCH_DEBUG + #define IO_APIC_BASE(idx) \ ((volatile int *)__fix_to_virt(FIX_IO_APIC_BASE_0 + idx)) diff -u --recursive --new-file v2.4.5/linux/include/asm-i386/linux_logo.h linux/include/asm-i386/linux_logo.h --- v2.4.5/linux/include/asm-i386/linux_logo.h Fri May 25 18:02:51 2001 +++ linux/include/asm-i386/linux_logo.h Mon Jun 11 19:15:27 2001 @@ -23,26 +23,5 @@ #define linux_logo_banner "Linux/ia32 version " UTS_RELEASE -#define LINUX_LOGO_COLORS 214 - -#ifdef INCLUDE_LINUX_LOGO_DATA - -#define INCLUDE_LINUX_LOGOBW -#define INCLUDE_LINUX_LOGO16 - #include -#else - -/* prototypes only */ -extern unsigned char linux_logo_red[]; -extern unsigned char linux_logo_green[]; -extern unsigned char linux_logo_blue[]; -extern unsigned char linux_logo[]; -extern unsigned char linux_logo_bw[]; -extern unsigned char linux_logo16_red[]; -extern unsigned char linux_logo16_green[]; -extern unsigned char linux_logo16_blue[]; -extern unsigned char linux_logo16[]; - -#endif diff -u --recursive --new-file v2.4.5/linux/include/asm-i386/mca_dma.h linux/include/asm-i386/mca_dma.h --- v2.4.5/linux/include/asm-i386/mca_dma.h Wed Apr 12 09:47:29 2000 +++ linux/include/asm-i386/mca_dma.h Tue Jun 12 11:06:54 2001 @@ -199,4 +199,4 @@ outb(mode, MCA_DMA_REG_EXE); } -#endif MCA_DMA_H +#endif /* MCA_DMA_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-i386/pci.h linux/include/asm-i386/pci.h --- v2.4.5/linux/include/asm-i386/pci.h Fri May 25 18:02:07 2001 +++ linux/include/asm-i386/pci.h Tue Jul 3 15:43:41 2001 @@ -1,13 +1,19 @@ #ifndef __i386_PCI_H #define __i386_PCI_H +#include + #ifdef __KERNEL__ /* Can be used to override the logic in pci_scan_bus for skipping already-configured bus numbers - to be used for buggy BIOSes or architectures with incomplete PCI setup by the loader */ +#ifdef CONFIG_PCI +extern unsigned int pcibios_assign_all_busses(void); +#else #define pcibios_assign_all_busses() 0 +#endif extern unsigned long pci_mem_start; #define PCIBIOS_MIN_IO 0x1000 diff -u --recursive --new-file v2.4.5/linux/include/asm-i386/socket.h linux/include/asm-i386/socket.h --- v2.4.5/linux/include/asm-i386/socket.h Sat Feb 3 11:26:44 2001 +++ linux/include/asm-i386/socket.h Wed Jun 20 21:00:55 2001 @@ -58,6 +58,7 @@ /* level. For writing rarp and */ /* other similar things on the */ /* user level. */ +#define SOCK_MAX (SOCK_PACKET+1) #endif #endif /* _ASM_SOCKET_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-i386/softirq.h linux/include/asm-i386/softirq.h --- v2.4.5/linux/include/asm-i386/softirq.h Fri May 25 18:01:27 2001 +++ linux/include/asm-i386/softirq.h Tue Jul 3 15:42:55 2001 @@ -4,12 +4,46 @@ #include #include -#define cpu_bh_disable(cpu) do { local_bh_count(cpu)++; barrier(); } while (0) -#define cpu_bh_enable(cpu) do { barrier(); local_bh_count(cpu)--; } while (0) +#define __cpu_bh_enable(cpu) \ + do { barrier(); local_bh_count(cpu)--; } while (0) +#define cpu_bh_disable(cpu) \ + do { local_bh_count(cpu)++; barrier(); } while (0) #define local_bh_disable() cpu_bh_disable(smp_processor_id()) -#define local_bh_enable() cpu_bh_enable(smp_processor_id()) +#define __local_bh_enable() __cpu_bh_enable(smp_processor_id()) +#define __cpu_raise_softirq(cpu,nr) set_bit((nr), &softirq_pending(cpu)); +#define raise_softirq(nr) __cpu_raise_softirq(smp_processor_id(), (nr)) #define in_softirq() (local_bh_count(smp_processor_id()) != 0) + +/* + * NOTE: this assembly code assumes: + * + * (char *)&local_bh_count - 8 == (char *)&softirq_pending + * + * If you change the offsets in irq_stat then you have to + * update this code as well. + */ +#define local_bh_enable() \ +do { \ + unsigned int *ptr = &local_bh_count(smp_processor_id()); \ + \ + if (!--*ptr) \ + __asm__ __volatile__ ( \ + "cmpl $0, -8(%0);" \ + "jnz 2f;" \ + "1:;" \ + \ + ".section .text.lock,\"ax\";" \ + "2: pushl %%eax; pushl %%ecx; pushl %%edx;" \ + "call %c1;" \ + "popl %%edx; popl %%ecx; popl %%eax;" \ + "jmp 1b;" \ + ".previous;" \ + \ + : /* no output */ \ + : "r" (ptr), "i" (do_softirq) \ + /* no registers clobbered */ ); \ +} while (0) #endif /* __ASM_SOFTIRQ_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-i386/termios.h linux/include/asm-i386/termios.h --- v2.4.5/linux/include/asm-i386/termios.h Sat Feb 3 20:00:45 2001 +++ linux/include/asm-i386/termios.h Mon Jun 11 19:15:27 2001 @@ -55,6 +55,7 @@ #define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */ #define N_HDLC 13 /* synchronous HDLC */ #define N_SYNC_PPP 14 /* synchronous PPP */ +#define N_HCI 15 /* Bluetooth HCI UART */ #ifdef __KERNEL__ diff -u --recursive --new-file v2.4.5/linux/include/asm-i386/uaccess.h linux/include/asm-i386/uaccess.h --- v2.4.5/linux/include/asm-i386/uaccess.h Fri May 25 18:01:28 2001 +++ linux/include/asm-i386/uaccess.h Tue Jul 3 15:42:55 2001 @@ -129,12 +129,6 @@ extern void __put_user_bad(void); -#define __put_user_x(size,ret,x,ptr) \ - __asm__ __volatile__("call __put_user_" #size \ - :"=a" (ret) \ - :"0" (ptr),"d" (x) \ - :"cx") - #define put_user(x,ptr) \ __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) diff -u --recursive --new-file v2.4.5/linux/include/asm-ia64/linux_logo.h linux/include/asm-ia64/linux_logo.h --- v2.4.5/linux/include/asm-ia64/linux_logo.h Sun Feb 6 18:42:40 2000 +++ linux/include/asm-ia64/linux_logo.h Mon Jun 11 19:15:27 2001 @@ -24,26 +24,5 @@ #define linux_logo_banner "Linux/ia64 version " UTS_RELEASE -#define LINUX_LOGO_COLORS 214 - -#ifdef INCLUDE_LINUX_LOGO_DATA - -#define INCLUDE_LINUX_LOGOBW -#define INCLUDE_LINUX_LOGO16 - #include -#else - -/* prototypes only */ -extern unsigned char linux_logo_red[]; -extern unsigned char linux_logo_green[]; -extern unsigned char linux_logo_blue[]; -extern unsigned char linux_logo[]; -extern unsigned char linux_logo_bw[]; -extern unsigned char linux_logo16_red[]; -extern unsigned char linux_logo16_green[]; -extern unsigned char linux_logo16_blue[]; -extern unsigned char linux_logo16[]; - -#endif diff -u --recursive --new-file v2.4.5/linux/include/asm-ia64/socket.h linux/include/asm-ia64/socket.h --- v2.4.5/linux/include/asm-ia64/socket.h Sat Feb 3 11:26:44 2001 +++ linux/include/asm-ia64/socket.h Wed Jun 20 21:00:55 2001 @@ -65,6 +65,7 @@ /* level. For writing rarp and */ /* other similar things on the */ /* user level. */ +#define SOCK_MAX (SOCK_PACKET+1) #endif #endif /* _ASM_IA64_SOCKET_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-ia64/termios.h linux/include/asm-ia64/termios.h --- v2.4.5/linux/include/asm-ia64/termios.h Sat Feb 3 20:00:45 2001 +++ linux/include/asm-ia64/termios.h Mon Jun 11 19:15:27 2001 @@ -62,6 +62,7 @@ #define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS msgs */ #define N_HDLC 13 /* synchronous HDLC */ #define N_SYNC_PPP 14 /* synchronous PPP */ +#define N_HCI 15 /* Bluetooth HCI UART */ # ifdef __KERNEL__ diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/amigahw.h linux/include/asm-m68k/amigahw.h --- v2.4.5/linux/include/asm-m68k/amigahw.h Mon Nov 27 17:57:34 2000 +++ linux/include/asm-m68k/amigahw.h Mon Jun 11 19:15:27 2001 @@ -106,6 +106,7 @@ AMIGAHW_DECLARE(ALICE_NTSC); /* NTSC Alice (8374) */ AMIGAHW_DECLARE(MAGIC_REKICK); /* A3000 Magic Hard Rekick */ AMIGAHW_DECLARE(PCMCIA); /* PCMCIA Slot */ + AMIGAHW_DECLARE(GG2_ISA); /* GG2 Zorro2ISA Bridge */ AMIGAHW_DECLARE(ZORRO); /* Zorro AutoConfig */ AMIGAHW_DECLARE(ZORRO3); /* Zorro III */ }; diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/amigayle.h linux/include/asm-m68k/amigayle.h --- v2.4.5/linux/include/asm-m68k/amigayle.h Thu Jul 30 11:08:20 1998 +++ linux/include/asm-m68k/amigayle.h Mon Jun 11 19:15:27 2001 @@ -17,8 +17,8 @@ #ifndef _M68K_AMIGAYLE_H_ #define _M68K_AMIGAYLE_H_ +#include #include -#include /* memory layout */ @@ -59,11 +59,13 @@ #define gayle_attribute ((volatile u_char *)(GAYLE_ATTRIBUTE)) +#if 0 #define gayle_inb(a) readb( GAYLE_IO+(a)+(((a)&1)*GAYLE_ODD) ) #define gayle_outb(v,a) writeb( v, GAYLE_IO+(a)+(((a)&1)*GAYLE_ODD) ) #define gayle_inw(a) readw( GAYLE_IO+(a) ) #define gayle_outw(v,a) writew( v, GAYLE_IO+(a) ) +#endif /* GAYLE_CARDSTATUS bit def */ diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/bitops.h linux/include/asm-m68k/bitops.h --- v2.4.5/linux/include/asm-m68k/bitops.h Sat Feb 3 11:26:44 2001 +++ linux/include/asm-m68k/bitops.h Mon Jun 11 19:15:27 2001 @@ -19,23 +19,23 @@ __constant_test_and_set_bit(nr, vaddr) : \ __generic_test_and_set_bit(nr, vaddr)) -extern __inline__ int __constant_test_and_set_bit(int nr,void * vaddr) +extern __inline__ int __constant_test_and_set_bit(int nr,volatile void * vaddr) { char retval; - __asm__ __volatile__ ("bset %1,%2; sne %0" - : "=d" (retval) - : "di" (nr & 7), "m" (((char *)vaddr)[(nr^31) >> 3])); + __asm__ __volatile__ ("bset %2,%1; sne %0" + : "=d" (retval), "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) + : "di" (nr & 7)); return retval; } -extern __inline__ int __generic_test_and_set_bit(int nr,void * vaddr) +extern __inline__ int __generic_test_and_set_bit(int nr,volatile void * vaddr) { char retval; __asm__ __volatile__ ("bfset %2@{%1:#1}; sne %0" - : "=d" (retval) : "d" (nr^31), "a" (vaddr)); + : "=d" (retval) : "d" (nr^31), "a" (vaddr) : "memory"); return retval; } @@ -45,16 +45,16 @@ __constant_set_bit(nr, vaddr) : \ __generic_set_bit(nr, vaddr)) -extern __inline__ void __constant_set_bit(int nr, void * vaddr) +extern __inline__ void __constant_set_bit(int nr, volatile void * vaddr) { - __asm__ __volatile__ ("bset %0,%1" - : : "di" (nr & 7), "m" (((char *)vaddr)[(nr^31) >> 3])); + __asm__ __volatile__ ("bset %1,%0" + : "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) : "di" (nr & 7)); } -extern __inline__ void __generic_set_bit(int nr, void * vaddr) +extern __inline__ void __generic_set_bit(int nr, volatile void * vaddr) { __asm__ __volatile__ ("bfset %1@{%0:#1}" - : : "d" (nr^31), "a" (vaddr)); + : : "d" (nr^31), "a" (vaddr) : "memory"); } #define test_and_clear_bit(nr,vaddr) \ @@ -62,23 +62,23 @@ __constant_test_and_clear_bit(nr, vaddr) : \ __generic_test_and_clear_bit(nr, vaddr)) -extern __inline__ int __constant_test_and_clear_bit(int nr, void * vaddr) +extern __inline__ int __constant_test_and_clear_bit(int nr, volatile void * vaddr) { char retval; - __asm__ __volatile__ ("bclr %1,%2; sne %0" - : "=d" (retval) - : "di" (nr & 7), "m" (((char *)vaddr)[(nr^31) >> 3])); + __asm__ __volatile__ ("bclr %2,%1; sne %0" + : "=d" (retval), "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) + : "di" (nr & 7)); return retval; } -extern __inline__ int __generic_test_and_clear_bit(int nr, void * vaddr) +extern __inline__ int __generic_test_and_clear_bit(int nr, volatile void * vaddr) { char retval; __asm__ __volatile__ ("bfclr %2@{%1:#1}; sne %0" - : "=d" (retval) : "d" (nr^31), "a" (vaddr)); + : "=d" (retval) : "d" (nr^31), "a" (vaddr) : "memory"); return retval; } @@ -94,16 +94,16 @@ __constant_clear_bit(nr, vaddr) : \ __generic_clear_bit(nr, vaddr)) -extern __inline__ void __constant_clear_bit(int nr, void * vaddr) +extern __inline__ void __constant_clear_bit(int nr, volatile void * vaddr) { - __asm__ __volatile__ ("bclr %0,%1" - : : "di" (nr & 7), "m" (((char *)vaddr)[(nr^31) >> 3])); + __asm__ __volatile__ ("bclr %1,%0" + : "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) : "di" (nr & 7)); } -extern __inline__ void __generic_clear_bit(int nr, void * vaddr) +extern __inline__ void __generic_clear_bit(int nr, volatile void * vaddr) { __asm__ __volatile__ ("bfclr %1@{%0:#1}" - : : "d" (nr^31), "a" (vaddr)); + : : "d" (nr^31), "a" (vaddr) : "memory"); } #define test_and_change_bit(nr,vaddr) \ @@ -111,23 +111,26 @@ __constant_test_and_change_bit(nr, vaddr) : \ __generic_test_and_change_bit(nr, vaddr)) -extern __inline__ int __constant_test_and_change_bit(int nr, void * vaddr) +#define __test_and_change_bit(nr,vaddr) test_and_change_bit(nr,vaddr) +#define __change_bit(nr,vaddr) change_bit(nr,vaddr) + +extern __inline__ int __constant_test_and_change_bit(int nr, volatile void * vaddr) { char retval; - __asm__ __volatile__ ("bchg %1,%2; sne %0" - : "=d" (retval) - : "di" (nr & 7), "m" (((char *)vaddr)[(nr^31) >> 3])); + __asm__ __volatile__ ("bchg %2,%1; sne %0" + : "=d" (retval), "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) + : "di" (nr & 7)); return retval; } -extern __inline__ int __generic_test_and_change_bit(int nr, void * vaddr) +extern __inline__ int __generic_test_and_change_bit(int nr, volatile void * vaddr) { char retval; __asm__ __volatile__ ("bfchg %2@{%1:#1}; sne %0" - : "=d" (retval) : "d" (nr^31), "a" (vaddr)); + : "=d" (retval) : "d" (nr^31), "a" (vaddr) : "memory"); return retval; } @@ -137,21 +140,21 @@ __constant_change_bit(nr, vaddr) : \ __generic_change_bit(nr, vaddr)) -extern __inline__ void __constant_change_bit(int nr, void * vaddr) +extern __inline__ void __constant_change_bit(int nr, volatile void * vaddr) { - __asm__ __volatile__ ("bchg %0,%1" - : : "di" (nr & 7), "m" (((char *)vaddr)[(nr^31) >> 3])); + __asm__ __volatile__ ("bchg %1,%0" + : "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) : "di" (nr & 7)); } -extern __inline__ void __generic_change_bit(int nr, void * vaddr) +extern __inline__ void __generic_change_bit(int nr, volatile void * vaddr) { __asm__ __volatile__ ("bfchg %1@{%0:#1}" - : : "d" (nr^31), "a" (vaddr)); + : : "d" (nr^31), "a" (vaddr) : "memory"); } -extern __inline__ int test_bit(int nr, const void * vaddr) +extern __inline__ int test_bit(int nr, const volatile void * vaddr) { - return ((1UL << (nr & 31)) & (((const unsigned int *) vaddr)[nr >> 5])) != 0; + return ((1UL << (nr & 31)) & (((const volatile unsigned int *) vaddr)[nr >> 5])) != 0; } extern __inline__ int find_first_zero_bit(void * vaddr, unsigned size) @@ -228,7 +231,7 @@ { int cnt; - asm ("bfffo %1{#0:#0},%0" : "=d" (cnt) : "dm" (x & -x)); + __asm__ __volatile__("bfffo %1{#0:#0},%0" : "=d" (cnt) : "dm" (x & -x)); return 32 - cnt; } @@ -268,12 +271,12 @@ } extern __inline__ int -minix_test_and_set_bit (int nr, void *vaddr) +minix_test_and_set_bit (int nr, volatile void *vaddr) { char retval; __asm__ __volatile__ ("bfset %2{%1:#1}; sne %0" - : "=d" (retval) : "d" (nr^15), "m" (*(char *)vaddr)); + : "=d" (retval) : "d" (nr^15), "m" (*(volatile char *)vaddr) : "memory"); return retval; } @@ -281,50 +284,50 @@ #define minix_set_bit(nr,addr) ((void)minix_test_and_set_bit(nr,addr)) extern __inline__ int -minix_test_and_clear_bit (int nr, void *vaddr) +minix_test_and_clear_bit (int nr, volatile void *vaddr) { char retval; __asm__ __volatile__ ("bfclr %2{%1:#1}; sne %0" - : "=d" (retval) : "d" (nr^15), "m" (*(char *) vaddr)); + : "=d" (retval) : "d" (nr^15), "m" (*(volatile char *) vaddr) : "memory"); return retval; } extern __inline__ int -minix_test_bit (int nr, const void *vaddr) +minix_test_bit (int nr, const volatile void *vaddr) { - return ((1U << (nr & 15)) & (((const unsigned short *) vaddr)[nr >> 4])) != 0; + return ((1U << (nr & 15)) & (((const volatile unsigned short *) vaddr)[nr >> 4])) != 0; } /* Bitmap functions for the ext2 filesystem. */ extern __inline__ int -ext2_set_bit (int nr, void *vaddr) +ext2_set_bit (int nr, volatile void *vaddr) { char retval; __asm__ __volatile__ ("bfset %2{%1,#1}; sne %0" - : "=d" (retval) : "d" (nr^7), "m" (*(char *) vaddr)); + : "=d" (retval) : "d" (nr^7), "m" (*(volatile char *) vaddr) : "memory"); return retval; } extern __inline__ int -ext2_clear_bit (int nr, void *vaddr) +ext2_clear_bit (int nr, volatile void *vaddr) { char retval; __asm__ __volatile__ ("bfclr %2{%1,#1}; sne %0" - : "=d" (retval) : "d" (nr^7), "m" (*(char *) vaddr)); + : "=d" (retval) : "d" (nr^7), "m" (*(volatile char *) vaddr) : "memory"); return retval; } extern __inline__ int -ext2_test_bit (int nr, const void *vaddr) +ext2_test_bit (int nr, const volatile void *vaddr) { - return ((1U << (nr & 7)) & (((const unsigned char *) vaddr)[nr >> 3])) != 0; + return ((1U << (nr & 7)) & (((const volatile unsigned char *) vaddr)[nr >> 3])) != 0; } extern __inline__ int diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/dvma.h linux/include/asm-m68k/dvma.h --- v2.4.5/linux/include/asm-m68k/dvma.h Fri Dec 29 14:07:23 2000 +++ linux/include/asm-m68k/dvma.h Mon Jun 11 19:15:27 2001 @@ -11,17 +11,37 @@ #include +#define DVMA_PAGE_SHIFT 13 +#define DVMA_PAGE_SIZE (1UL << DVMA_PAGE_SHIFT) +#define DVMA_PAGE_MASK (~(DVMA_PAGE_SIZE-1)) +#define DVMA_PAGE_ALIGN(addr) (((addr)+DVMA_PAGE_SIZE-1)&DVMA_PAGE_MASK) + +extern void dvma_init(void); +extern int dvma_map_iommu(unsigned long kaddr, unsigned long baddr, + int len); + +#define dvma_malloc(x) dvma_malloc_align(x, 0) +#define dvma_map(x, y) dvma_map_align(x, y, 0) + +extern unsigned long dvma_map_align(unsigned long kaddr, int len, + int align); +extern void *dvma_malloc_align(unsigned long len, unsigned long align); + +extern void dvma_unmap(void *baddr); +extern void dvma_free(void *vaddr); + + #ifdef CONFIG_SUN3 /* sun3 dvma page support */ -#define DVMA_RESERVED_PMEGS 2 /* 256k of dvma */ - /* memory and pmegs potentially reserved for dvma */ #define DVMA_PMEG_START 10 #define DVMA_PMEG_END 16 -#define DVMA_START 0xff00000 -#define DVMA_END 0xffe0000 +#define DVMA_START 0xf00000 +#define DVMA_END 0xfe0000 #define DVMA_SIZE (DVMA_END-DVMA_START) +#define IOMMU_TOTAL_ENTRIES 128 +#define IOMMU_ENTRIES 120 /* empirical kludge -- dvma regions only seem to work right on 0x10000 byte boundries */ @@ -29,15 +49,40 @@ #define DVMA_ALIGN(addr) (((addr)+DVMA_REGION_SIZE-1) & \ ~(DVMA_REGION_SIZE-1)) - /* virt <-> phys conversions */ -#define sun3_dvma_vtop(x) ((unsigned long)(x) & 0xffffff) -#define sun3_dvma_ptov(x) ((unsigned long)(x) | 0xf000000) +#define dvma_vtop(x) ((unsigned long)(x) & 0xffffff) +#define dvma_ptov(x) ((unsigned long)(x) | 0xf000000) +#define dvma_vtob(x) dvma_vtop(x) +#define dvma_btov(x) dvma_ptov(x) + +extern inline int dvma_map_cpu(unsigned long kaddr, unsigned long vaddr, int len) +{ + return 0; +} + +extern unsigned long dvma_page(unsigned long kaddr, unsigned long vaddr); -extern void sun3_dvma_init(void); -extern void *sun3_dvma_malloc(int len); #else /* Sun3x */ +/* sun3x dvma page support */ + +#define DVMA_START 0x0 +#define DVMA_END 0xf00000 +#define DVMA_SIZE (DVMA_END-DVMA_START) +#define IOMMU_TOTAL_ENTRIES 2048 +/* the prom takes the top meg */ +#define IOMMU_ENTRIES (IOMMU_TOTAL_ENTRIES - 0x80) + +#define dvma_vtob(x) ((unsigned long)(x) & 0x00ffffff) +#define dvma_btov(x) ((unsigned long)(x) | 0xff000000) + +extern int dvma_map_cpu(unsigned long kaddr, unsigned long vaddr, int len); + + + +/* everything below this line is specific to dma used for the onboard + ESP scsi on sun3x */ + /* Structure to describe the current status of DMA registers on the Sparc */ struct sparc_dma_registers { __volatile__ unsigned long cond_reg; /* DMA condition register */ @@ -188,7 +233,7 @@ dma->running = 0; \ } while(0) -extern unsigned long dvma_alloc (unsigned long, unsigned long); -extern void dvma_free (unsigned long, unsigned long); + #endif /* !CONFIG_SUN3 */ + #endif /* !(__M68K_DVMA_H) */ diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/floppy.h linux/include/asm-m68k/floppy.h --- v2.4.5/linux/include/asm-m68k/floppy.h Thu Jan 4 13:00:55 2001 +++ linux/include/asm-m68k/floppy.h Mon Jun 11 19:15:27 2001 @@ -1,23 +1,58 @@ /* - * Q40 Architecture specific parts of the Floppy driver + * Implementation independent bits of the Floppy driver. + * + * much of this file is derived from what was originally the Q40 floppy driver. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1999 + * Copyright (C) 1999, 2000, 2001 + * + * Sun3x support added 2/4/2000 Sam Creasey (sammy@oh.verio.com) + * */ #include #include - asmlinkage void floppy_hardint(int irq, void *dev_id, struct pt_regs * regs); +/* constants... */ + #undef MAX_DMA_ADDRESS #define MAX_DMA_ADDRESS 0x00 /* nothing like that */ + +/* + * Again, the CMOS information doesn't work on m68k.. + */ +#define FLOPPY0_TYPE (MACH_IS_Q40 ? 6 : 4) +#define FLOPPY1_TYPE 0 + +#define FLOPPY_MOTOR_MASK 0xf0 + + +/* basically PC init + set use_virtual_dma */ +#define FDC1 m68k_floppy_init() +static int FDC2 = -1; + + +#define N_FDC 1 +#define N_DRIVE 8 + + +/* vdma globals adapted from asm-i386/floppy.h */ + +static int virtual_dma_count=0; +static int virtual_dma_residue=0; +static char *virtual_dma_addr=0; +static int virtual_dma_mode=0; +static int doing_pdma=0; + +#include + extern spinlock_t dma_spin_lock; static __inline__ unsigned long claim_dma_lock(void) @@ -33,23 +68,46 @@ } +static __inline__ unsigned char fd_inb(int port) +{ + if(MACH_IS_Q40) + return inb_p(port); + else if(MACH_IS_SUN3X) + return sun3x_82072_fd_inb(port); +} -#define fd_inb(port) inb_p(port) -#define fd_outb(port,value) outb_p(port,value) +static __inline__ void fd_outb(unsigned char value, int port) +{ + if(MACH_IS_Q40) + outb_p(value, port); + else if(MACH_IS_SUN3X) + sun3x_82072_fd_outb(value, port); +} -#define fd_request_dma() vdma_request_dma(FLOPPY_DMA,"floppy") -/*#define fd_free_dma() */ +static int fd_request_irq(void) +{ + if(MACH_IS_Q40) + return request_irq(FLOPPY_IRQ, floppy_hardint,SA_INTERRUPT, + "floppy", NULL); + else if(MACH_IS_SUN3X) + return sun3xflop_request_irq(); + +} +static void fd_free_irq(void) +{ + if(MACH_IS_Q40) + free_irq(FLOPPY_IRQ, NULL); +} +#define fd_request_dma() vdma_request_dma(FLOPPY_DMA,"floppy") #define fd_get_dma_residue() vdma_get_dma_residue(FLOPPY_DMA) #define fd_dma_mem_alloc(size) vdma_mem_alloc(size) #define fd_dma_setup(addr, size, mode, io) vdma_dma_setup(addr, size, mode, io) - #define fd_enable_irq() /* nothing... */ #define fd_disable_irq() /* nothing... */ -#define fd_free_irq() free_irq(FLOPPY_IRQ, NULL) #define fd_free_dma() /* nothing */ @@ -60,62 +118,71 @@ #define DMA_MODE_WRITE 0x48 -static int q40_floppy_init(void) +static int m68k_floppy_init(void) { use_virtual_dma =1; - /* FLOPPY_IRQ=6; */ - + can_use_virtual_dma = 1; + + if (MACH_IS_Q40) - return 0x3f0; + return 0x3f0; + else if(MACH_IS_SUN3X) + return sun3xflop_init(); else return -1; } +static int vdma_request_dma(unsigned int dmanr, const char * device_id) +{ + return 0; +} -/* - * Again, the CMOS information doesn't work on the Q40.. - */ -#define FLOPPY0_TYPE 6 -#define FLOPPY1_TYPE 0 - - - - -#define FLOPPY_MOTOR_MASK 0xf0 - - - +static int vdma_get_dma_residue(unsigned int dummy) +{ + return virtual_dma_count + virtual_dma_residue; +} -/* basically PC init + set use_virtual_dma */ -#define FDC1 q40_floppy_init() -static int FDC2 = -1; +static unsigned long vdma_mem_alloc(unsigned long size) +{ + return (unsigned long) vmalloc(size); -#define N_FDC 1 -#define N_DRIVE 8 +} +static void _fd_dma_mem_free(unsigned long addr, unsigned long size) +{ + vfree((void *)addr); +} +#define fd_dma_mem_free(addr,size) _fd_dma_mem_free(addr, size) -/* vdma stuff adapted from asm-i386/floppy.h */ +/* choose_dma_mode ???*/ -static int virtual_dma_count=0; -static int virtual_dma_residue=0; -static char *virtual_dma_addr=0; -static int virtual_dma_mode=0; -static int doing_pdma=0; +static int vdma_dma_setup(char *addr, unsigned long size, int mode, int io) +{ + doing_pdma = 1; + virtual_dma_port = (MACH_IS_Q40 ? io : 0); + virtual_dma_mode = (mode == DMA_MODE_WRITE); + virtual_dma_addr = addr; + virtual_dma_count = size; + virtual_dma_residue = 0; + return 0; +} -static int fd_request_irq(void) +static void fd_disable_dma(void) { - return request_irq(FLOPPY_IRQ, floppy_hardint,SA_INTERRUPT, - "floppy", NULL); + doing_pdma = 0; + virtual_dma_residue += virtual_dma_count; + virtual_dma_count=0; } -/*#define SLOW_DOWN do{outb(0,0x80);}while(0)*/ -#define SLOW_DOWN do{int count=1;do{if(!jiffies)break;}while(count-->0);}while(0) + + +/* this is the only truly Q40 specific function */ asmlinkage void floppy_hardint(int irq, void *dev_id, struct pt_regs * regs) { @@ -185,55 +252,6 @@ if(!virtual_dma_count) dma_wait++; #endif -} - - - -static int vdma_request_dma(unsigned int dmanr, const char * device_id) -{ - return 0; -} - - -static int vdma_get_dma_residue(unsigned int dummy) -{ - return virtual_dma_count + virtual_dma_residue; -} - - -static unsigned long vdma_mem_alloc(unsigned long size) -{ - return (unsigned long) vmalloc(size); - -} - -static void _fd_dma_mem_free(unsigned long addr, unsigned long size) -{ - vfree((void *)addr); -} -#define fd_dma_mem_free(addr,size) _fd_dma_mem_free(addr, size) - - -/* choose_dma_mode ???*/ - -static int vdma_dma_setup(char *addr, unsigned long size, int mode, int io) -{ - doing_pdma = 1; - virtual_dma_port = io; - virtual_dma_mode = (mode == DMA_MODE_WRITE); - virtual_dma_addr = addr; - virtual_dma_count = size; - virtual_dma_residue = 0; - return 0; -} - - - -static void fd_disable_dma(void) -{ - doing_pdma = 0; - virtual_dma_residue += virtual_dma_count; - virtual_dma_count=0; } diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/ide.h linux/include/asm-m68k/ide.h --- v2.4.5/linux/include/asm-m68k/ide.h Fri Dec 29 14:07:23 2000 +++ linux/include/asm-m68k/ide.h Mon Jun 11 19:15:27 2001 @@ -61,10 +61,6 @@ return 0; } -/* - * Can we do this in a generic manner?? - */ - /* * Set up a hw structure for a specified data port, control port and IRQ. @@ -160,219 +156,64 @@ #define SUPPORT_VLB_SYNC 0 /* this definition is used only on startup .. */ -#ifndef CONFIG_Q40 #undef HD_DATA #define HD_DATA NULL + + +/* get rid of defs from io.h - ide has its private and conflicting versions */ +#undef inb +#undef inw +#undef outb +#undef outw +#undef inb_p +#undef outb_p +#undef insw +#undef outsw +#undef insw_swapw +#undef outsw_swapw + +/* + * define IO method and translation, + * so far only Q40 has ide-if on ISA +*/ +#ifndef CONFIG_Q40 + +#define ADDR_TRANS_B(_addr_) (_addr_) +#define ADDR_TRANS_W(_addr_) (_addr_) + #else -#ifdef MACH_Q40_ONLY -#undef HD_DATA -#define HD_DATA ((ide_ioreg_t)0x1f0) -#else -#undef HD_DATA -#define HD_DATA (MACH_IS_Q40 ? (ide_ioreg_t)0x1f0 : 0) -#endif + +#define ADDR_TRANS_B(_addr_) (MACH_IS_Q40 ? ((unsigned char *)Q40_ISA_IO_B(_addr_)) : (_addr_)) +#define ADDR_TRANS_W(_addr_) (MACH_IS_Q40 ? ((unsigned char *)Q40_ISA_IO_W(_addr_)) : (_addr_)) #endif +#define inb(p) in_8(ADDR_TRANS_B(p)) +#define inb_p(p) in_8(ADDR_TRANS_B(p)) +#define inw(p) in_be16(ADDR_TRANS_W(p)) +#define outb(v,p) out_8(ADDR_TRANS_B(p),v) +#define outb_p(v,p) out_8(ADDR_TRANS_B(p),v) +#define outw(v,p) out_be16(ADDR_TRANS_W(p),v) + +#define insw(port, buf, nr) raw_insw(ADDR_TRANS_W(port), buf, nr) +#define outsw(port, buf, nr) raw_outsw(ADDR_TRANS_W(port), buf, nr) #define insl(data_reg, buffer, wcount) insw(data_reg, buffer, (wcount)<<1) #define outsl(data_reg, buffer, wcount) outsw(data_reg, buffer, (wcount)<<1) -#ifdef CONFIG_Q40 -#ifdef MACH_Q40_ONLY -#define ADDR_TRANS(_addr_) (Q40_ISA_IO_W(_addr_)) -#else -#define ADDR_TRANS(_addr_) (MACH_IS_Q40 ? ((unsigned char *)Q40_ISA_IO_W(_addr_)) : (_addr_)) -#endif -#else -#define ADDR_TRANS(_addr_) (_addr_) -#endif -#define insw(port, buf, nr) ({ \ - unsigned char *_port = (unsigned char *) ADDR_TRANS(port); \ - unsigned char *_buf = (buf); \ - int _nr = (nr); \ - unsigned long _tmp; \ - \ - if (_nr & 15) { \ - _tmp = (_nr & 15) - 1; \ - asm volatile ( \ - "1: movew %2@,%0@+; dbra %1,1b" \ - : "=a" (_buf), "=d" (_tmp) \ - : "a" (_port), "0" (_buf), \ - "1" (_tmp)); \ - } \ - if (_nr >> 4) { \ - _tmp = (_nr >> 4) - 1; \ - asm volatile ( \ - "1: " \ - "movew %2@,%0@+; " \ - "movew %2@,%0@+; " \ - "movew %2@,%0@+; " \ - "movew %2@,%0@+; " \ - "movew %2@,%0@+; " \ - "movew %2@,%0@+; " \ - "movew %2@,%0@+; " \ - "movew %2@,%0@+; " \ - "movew %2@,%0@+; " \ - "movew %2@,%0@+; " \ - "movew %2@,%0@+; " \ - "movew %2@,%0@+; " \ - "movew %2@,%0@+; " \ - "movew %2@,%0@+; " \ - "movew %2@,%0@+; " \ - "movew %2@,%0@+; " \ - "dbra %1,1b" \ - : "=a" (_buf), "=d" (_tmp) \ - : "a" (_port), "0" (_buf), \ - "1" (_tmp)); \ - } \ -}) - -#define outsw(port, buf, nr) ({ \ - unsigned char *_port = (unsigned char *) ADDR_TRANS(port); \ - unsigned char *_buf = (buf); \ - int _nr = (nr); \ - unsigned long _tmp; \ - \ - if (_nr & 15) { \ - _tmp = (_nr & 15) - 1; \ - asm volatile ( \ - "1: movew %0@+,%2@; dbra %1,1b" \ - : "=a" (_buf), "=d" (_tmp) \ - : "a" (_port), "0" (_buf), \ - "1" (_tmp)); \ - } \ - if (_nr >> 4) { \ - _tmp = (_nr >> 4) - 1; \ - asm volatile ( \ - "1: " \ - "movew %0@+,%2@; " \ - "movew %0@+,%2@; " \ - "movew %0@+,%2@; " \ - "movew %0@+,%2@; " \ - "movew %0@+,%2@; " \ - "movew %0@+,%2@; " \ - "movew %0@+,%2@; " \ - "movew %0@+,%2@; " \ - "movew %0@+,%2@; " \ - "movew %0@+,%2@; " \ - "movew %0@+,%2@; " \ - "movew %0@+,%2@; " \ - "movew %0@+,%2@; " \ - "movew %0@+,%2@; " \ - "movew %0@+,%2@; " \ - "movew %0@+,%2@; " \ - "dbra %1,1b" \ - : "=a" (_buf), "=d" (_tmp) \ - : "a" (_port), "0" (_buf), \ - "1" (_tmp)); \ - } \ -}) #if defined(CONFIG_ATARI) || defined(CONFIG_Q40) + #define insl_swapw(data_reg, buffer, wcount) \ insw_swapw(data_reg, buffer, (wcount)<<1) #define outsl_swapw(data_reg, buffer, wcount) \ outsw_swapw(data_reg, buffer, (wcount)<<1) -#define insw_swapw(port, buf, nr) \ - if ((nr) % 8) \ - __asm__ __volatile__ \ - ("movel %0,%/a0; \ - movel %1,%/a1; \ - movel %2,%/d6; \ - subql #1,%/d6; \ - 1:movew %/a0@,%/d0; \ - rolw #8,%/d0; \ - movew %/d0,%/a1@+; \ - dbra %/d6,1b" : \ - : "g" (ADDR_TRANS(port)), "g" (buf), "g" (nr) \ - : "d0", "a0", "a1", "d6"); \ - else \ - __asm__ __volatile__ \ - ("movel %0,%/a0; \ - movel %1,%/a1; \ - movel %2,%/d6; \ - lsrl #3,%/d6; \ - subql #1,%/d6; \ - 1:movew %/a0@,%/d0; \ - rolw #8,%/d0; \ - movew %/d0,%/a1@+; \ - movew %/a0@,%/d0; \ - rolw #8,%/d0; \ - movew %/d0,%/a1@+; \ - movew %/a0@,%/d0; \ - rolw #8,%/d0; \ - movew %/d0,%/a1@+; \ - movew %/a0@,%/d0; \ - rolw #8,%/d0; \ - movew %/d0,%/a1@+; \ - movew %/a0@,%/d0; \ - rolw #8,%/d0; \ - movew %/d0,%/a1@+; \ - movew %/a0@,%/d0; \ - rolw #8,%/d0; \ - movew %/d0,%/a1@+; \ - movew %/a0@,%/d0; \ - rolw #8,%/d0; \ - movew %/d0,%/a1@+; \ - movew %/a0@,%/d0; \ - rolw #8,%/d0; \ - movew %/d0,%/a1@+; \ - dbra %/d6,1b" : \ - : "g" (ADDR_TRANS(port)), "g" (buf), "g" (nr) \ - : "d0", "a0", "a1", "d6") - - -#define outsw_swapw(port, buf, nr) \ - if ((nr) % 8) \ - __asm__ __volatile__ \ - ("movel %0,%/a0; \ - movel %1,%/a1; \ - movel %2,%/d6; \ - subql #1,%/d6; \ - 1:movew %/a1@+,%/d0; \ - rolw #8,%/d0; \ - movew %/d0,%/a0@; \ - dbra %/d6,1b" : \ - : "g" (ADDR_TRANS(port)), "g" (buf), "g" (nr) \ - : "d0", "a0", "a1", "d6"); \ - else \ - __asm__ __volatile__ \ - ("movel %0,%/a0; \ - movel %1,%/a1; \ - movel %2,%/d6; \ - lsrl #3,%/d6; \ - subql #1,%/d6; \ - 1:movew %/a1@+,%/d0; \ - rolw #8,%/d0; \ - movew %/d0,%/a0@; \ - movew %/a1@+,%/d0; \ - rolw #8,%/d0; \ - movew %/d0,%/a0@; \ - movew %/a1@+,%/d0; \ - rolw #8,%/d0; \ - movew %/d0,%/a0@; \ - movew %/a1@+,%/d0; \ - rolw #8,%/d0; \ - movew %/d0,%/a0@; \ - movew %/a1@+,%/d0; \ - rolw #8,%/d0; \ - movew %/d0,%/a0@; \ - movew %/a1@+,%/d0; \ - rolw #8,%/d0; \ - movew %/d0,%/a0@; \ - movew %/a1@+,%/d0; \ - rolw #8,%/d0; \ - movew %/d0,%/a0@; \ - movew %/a1@+,%/d0; \ - rolw #8,%/d0; \ - movew %/d0,%/a0@; \ - dbra %/d6,1b" : \ - : "g" (ADDR_TRANS(port)), "g" (buf), "g" (nr) \ - : "d0", "a0", "a1", "d6") +#define insw_swapw(port, buf, nr) raw_insw_swapw(ADDR_TRANS_W(port), buf, nr) +#define outsw_swapw(port, buf, nr) raw_outsw_swapw(ADDR_TRANS_W(port),buf,nr) + +#endif /* CONFIG_ATARI || CONFIG_Q40 */ -#endif /* CONFIG_ATARI */ #define T_CHAR (0x0000) /* char: don't touch */ #define T_SHORT (0x4000) /* short: 12 -> 21 */ @@ -387,7 +228,15 @@ #define D_INT(cnt) (T_INT | (cnt)) #define D_TEXT(cnt) (T_TEXT | (cnt)) -#if defined(CONFIG_AMIGA) || defined (CONFIG_MAC) +/* Q40 and Atari have byteswapped IDE bus and since many interesting + * values in the identification string are text, chars and words they + * happened to be almost correct without swapping.. However *_capacity + * is needed for drives over 8 GB. RZ */ +#if defined(CONFIG_Q40) || defined(CONFIG_ATARI) +#define M68K_IDE_SWAPW (MACH_IS_Q40 || MACH_IS_ATARI) +#endif + +#if defined(CONFIG_AMIGA) || defined (CONFIG_MAC) || defined(M68K_IDE_SWAPW) static u_short driveid_types[] = { D_SHORT(10), /* config - vendor2 */ D_TEXT(20), /* serial_no */ @@ -402,7 +251,7 @@ D_INT(1), /* cur_capacity */ D_CHAR(2), /* multsect - multsect_valid */ D_INT(1), /* lba_capacity */ - D_SHORT(194) /* dma_1word - reservedyy */ + D_SHORT(194) /* dma_1word - reserved */ }; #define num_driveid_types (sizeof(driveid_types)/sizeof(*driveid_types)) @@ -410,13 +259,19 @@ static __inline__ void ide_fix_driveid(struct hd_driveid *id) { -#if defined(CONFIG_AMIGA) || defined (CONFIG_MAC) +#if defined(CONFIG_AMIGA) || defined (CONFIG_MAC) || defined(M68K_IDE_SWAPW) u_char *p = (u_char *)id; int i, j, cnt; u_char t; - if (!MACH_IS_AMIGA && !MACH_IS_MAC) + if (!MACH_IS_AMIGA && !MACH_IS_MAC && !MACH_IS_Q40 && !MACH_IS_ATARI) return; +#ifdef M68K_IDE_SWAPW + if (M68K_IDE_SWAPW) /* fix bus byteorder first */ + for (i=0; i < 512; i+=2) { + t = p[i]; p[i] = p[i+1]; p[i+1] = t; + } +#endif for (i = 0; i < num_driveid_types; i++) { cnt = driveid_types[i] & T_MASK_COUNT; switch (driveid_types[i] & T_MASK_TYPE) { @@ -425,28 +280,28 @@ break; case T_SHORT: for (j = 0; j < cnt; j++) { - t = p[0]; - p[0] = p[1]; - p[1] = t; + t = p[0]; + p[0] = p[1]; + p[1] = t; p += 2; } break; case T_INT: for (j = 0; j < cnt; j++) { - t = p[0]; - p[0] = p[3]; - p[3] = t; - t = p[1]; - p[1] = p[2]; - p[2] = t; + t = p[0]; + p[0] = p[3]; + p[3] = t; + t = p[1]; + p[1] = p[2]; + p[2] = t; p += 4; } break; case T_TEXT: for (j = 0; j < cnt; j += 2) { - t = p[0]; - p[0] = p[1]; - p[1] = t; + t = p[0]; + p[0] = p[1]; + p[1] = t; p += 2; } break; diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/intersil.h linux/include/asm-m68k/intersil.h --- v2.4.5/linux/include/asm-m68k/intersil.h Fri Dec 29 14:07:23 2000 +++ linux/include/asm-m68k/intersil.h Mon Jun 11 19:15:27 2001 @@ -25,21 +25,21 @@ #define INTERSIL_HZ_100_MASK 0x02 struct intersil_dt { - u_char csec; - u_char hour; - u_char minute; - u_char second; - u_char month; - u_char day; - u_char year; - u_char weekday; + unsigned char csec; + unsigned char hour; + unsigned char minute; + unsigned char second; + unsigned char month; + unsigned char day; + unsigned char year; + unsigned char weekday; }; struct intersil_7170 { struct intersil_dt counter; struct intersil_dt alarm; - u_char int_reg; - u_char cmd_reg; + unsigned char int_reg; + unsigned char cmd_reg; }; extern volatile char* clock_va; diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/io.h linux/include/asm-m68k/io.h --- v2.4.5/linux/include/asm-m68k/io.h Thu Jan 4 13:00:55 2001 +++ linux/include/asm-m68k/io.h Mon Jun 11 19:15:27 2001 @@ -1,57 +1,260 @@ -#ifndef _M68K_IO_H -#define _M68K_IO_H +/* + * linux/include/asm-m68k/io.h + * + * 4/1/00 RZ: - rewritten to avoid clashes between ISA/PCI and other + * IO access + * - added Q40 support + * - added skeleton for GG-II and Amiga PCMCIA + * 2/3/01 RZ: - moved a few more defs into raw_io.h + * + * inX/outX/readX/writeX should not be used by any driver unless it does + * ISA or PCI access. Other drivers should use function defined in raw_io.h + * or define its own macros on top of these. + * + * inX(),outX() are for PCI and ISA I/O + * readX(),writeX() are for PCI memory + * isa_readX(),isa_writeX() are for ISA memory + * + * moved mem{cpy,set}_*io inside CONFIG_PCI + */ + +#ifndef _IO_H +#define _IO_H #ifdef __KERNEL__ #include +#include +#include + #ifdef CONFIG_ATARI #include - -#define SLOW_DOWN_IO do { if (MACH_IS_ATARI) MFPDELAY(); } while (0) #endif -#include /* - * These are for PCI shared memory _only_ and should never be used - * on any other type of memory, including Zorro memory. They are meant to - * access the bus in the bus byte order which is little-endian!. - * - * readX/writeX() are used to access memory mapped devices. On some - * architectures the memory mapped IO stuff needs to be accessed - * differently. On the m68k architecture, we just read/write the - * memory location directly. + * IO/MEM definitions for various ISA bridges */ -/* ++roman: The assignments to temp. vars avoid that gcc sometimes generates - * two accesses to memory, which may be undesireable for some devices. + + +#ifdef CONFIG_Q40 + +#define q40_isa_io_base 0xff400000 +#define q40_isa_mem_base 0xff800000 + +#define Q40_ISA_IO_B(ioaddr) (q40_isa_io_base+1+4*((unsigned long)(ioaddr))) +#define Q40_ISA_IO_W(ioaddr) (q40_isa_io_base+ 4*((unsigned long)(ioaddr))) +#define Q40_ISA_MEM_B(madr) (q40_isa_mem_base+1+4*((unsigned long)(madr))) +#define Q40_ISA_MEM_W(madr) (q40_isa_mem_base+ 4*((unsigned long)(madr))) + +#define MACH_HAS_ISA 1 +#endif /* Q40 */ + +/* GG-II Zorro to ISA bridge */ +#ifdef CONFIG_GG2 + +extern unsigned long gg2_isa_base; +#define GG2_ISA_IO_B(ioaddr) (gg2_isa_base+1+((unsigned long)(ioaddr)*4)) +#define GG2_ISA_IO_W(ioaddr) (gg2_isa_base+ ((unsigned long)(ioaddr)*4)) +#define GG2_ISA_MEM_B(madr) (gg2_isa_base+1+(((unsigned long)(madr)*4) & 0xfffff)) +#define GG2_ISA_MEM_W(madr) (gg2_isa_base+ (((unsigned long)(madr)*4) & 0xfffff)) + +#ifndef MACH_HAS_ISA +#define MACH_HAS_ISA 1 +#else +#undef MACH_HAS_ISA +#define MACH_HAS_ISA m +#endif +#endif /* GG2 */ + +#ifdef CONFIG_AMIGA_PCMCIA +#include + +#define AG_ISA_IO_B(ioaddr) ( GAYLE_IO+(ioaddr)+(((ioaddr)&1)*GAYLE_ODD) ) +#define AG_ISA_IO_W(ioaddr) ( GAYLE_IO+(ioaddr) ) + +#ifndef MACH_HAS_ISA +#define MACH_HAS_ISA 1 +#else +#undef MACH_HAS_ISA +#define MACH_HAS_ISA m +#endif +#endif /* AMIGA_PCMCIA */ + + + +#ifdef MACH_HAS_ISA + +#define Q40_ISA (1) +#define GG2_ISA (2) +#define AG_ISA (3) + +#if defined(CONFIG_Q40) && MACH_HAS_ISA==1 +#define ISA_TYPE Q40_ISA +#define ISA_SEX 0 +#endif +#if defined(CONFIG_AMIGA_PCMCIA) && MACH_HAS_ISA==1 +#define ISA_TYPE AG_ISA +#define ISA_SEX 1 +#endif +#if defined(CONFIG_GG2) && MACH_HAS_ISA==1 +#define ISA_TYPE GG2_ISA +#define ISA_SEX 0 +#endif + +#ifdef CONFIG_ISA +extern int isa_type; +extern int isa_sex; + +#define ISA_TYPE isa_type +#define ISA_SEX isa_sex +#endif + +/* + * define inline addr translation functions. Normally only one variant will + * be compiled in so the case statement will be optimised away */ -#define readb(addr) \ - ({ unsigned char __v = (*(volatile unsigned char *) (addr)); __v; }) -#define readw(addr) \ - ({ unsigned short __v = (*(volatile unsigned short *) (addr)); __v; }) -#define readl(addr) \ - ({ unsigned int __v = (*(volatile unsigned int *) (addr)); __v; }) - -#define writeb(b,addr) (void)((*(volatile unsigned char *) (addr)) = (b)) -#define writew(b,addr) (void)((*(volatile unsigned short *) (addr)) = (b)) -#define writel(b,addr) (void)((*(volatile unsigned int *) (addr)) = (b)) - -#define memset_io(a,b,c) memset((void *)(a),(b),(c)) -#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c)) -#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c)) -#define inb_p(addr) readb(addr) -#define inb(addr) readb(addr) +static inline unsigned long isa_itb(long addr) +{ + switch(ISA_TYPE) + { +#ifdef CONFIG_Q40 + case Q40_ISA: return Q40_ISA_IO_B(addr); +#endif +#ifdef CONFIG_GG2 + case GG2_ISA: return GG2_ISA_IO_B(addr); +#endif +#ifdef CONFIG_AMIGA_PCMCIA + case AG_ISA: return AG_ISA_IO_B(addr); +#endif + default: return 0; /* avoid warnings, just in case */ + } +} +static inline unsigned long isa_itw(long addr) +{ + switch(ISA_TYPE) + { +#ifdef CONFIG_Q40 + case Q40_ISA: return Q40_ISA_IO_W(addr); +#endif +#ifdef CONFIG_GG2 + case GG2_ISA: return GG2_ISA_IO_W(addr); +#endif +#ifdef CONFIG_AMIGA_PCMCIA + case AG_ISA: return AG_ISA_IO_W(addr); +#endif + default: return 0; /* avoid warnings, just in case */ + } +} +static inline unsigned long isa_mtb(long addr) +{ + switch(ISA_TYPE) + { +#ifdef CONFIG_Q40 + case Q40_ISA: return Q40_ISA_MEM_B(addr); +#endif +#ifdef CONFIG_GG2 + case GG2_ISA: return GG2_ISA_MEM_B(addr); +#endif + /* FIXME: any ISA mem mapping for PCMCIA? */ + default: return 0; /* avoid warnings, just in case */ + } +} +static inline unsigned long isa_mtw(long addr) +{ + switch(ISA_TYPE) + { +#ifdef CONFIG_Q40 + case Q40_ISA: return Q40_ISA_MEM_W(addr); +#endif +#ifdef CONFIG_GG2 + case GG2_ISA: return GG2_ISA_MEM_W(addr); +#endif + default: return 0; /* avoid warnings, just in case */ + } +} -#define outb(x,addr) ((void) writeb(x,addr)) -#define outb_p(x,addr) outb(x,addr) -#ifndef CONFIG_SUN3 -#define IO_SPACE_LIMIT 0xffff +#define isa_inb(port) in_8(isa_itb(port)) +#define isa_inw(port) (ISA_SEX ? in_be16(isa_itw(port)) : in_le16(isa_itw(port))) +#define isa_outb(val,port) out_8(isa_itb(port),(val)) +#define isa_outw(val,port) (ISA_SEX ? out_be16(isa_itw(port),(val)) : out_le16(isa_itw(port),(val))) + +#define isa_readb(p) in_8(isa_mtb(p)) +#define isa_readw(p) in_le16(isa_mtw(p)) +#define isa_writeb(val,p) out_8(isa_mtb(p),(val)) +#define isa_writew(val,p) out_le16(isa_mtw(p),(val)) + +#define isa_inb_p(p) ({unsigned char v=isa_inb(p);isa_outb(0,0x80);v;}) +#define isa_outb_p(v,p) ({isa_outb((v),(p));isa_outb(0,0x80);}) + +#define isa_insb(port, buf, nr) raw_insb(isa_itb(port), (buf), (nr)) +#define isa_outsb(port, buf, nr) raw_outsb(isa_itb(port), (buf), (nr)) + +#define isa_insw(port, buf, nr) \ + (ISA_SEX ? raw_insw(isa_itw(port), (buf), (nr)) : \ + raw_insw_swapw(isa_itw(port), (buf), (nr))) + +#define isa_outsw(port, buf, nr) \ + (ISA_SEX ? raw_outsw(isa_itw(port), (buf), (nr)) : \ + raw_outsw_swapw(isa_itw(port), (buf), (nr))) +#endif /* MACH_HAS_ISA */ + + +#if defined(CONFIG_ISA) && !defined(CONFIG_PCI) +#define inb isa_inb +#define inb_p isa_inb_p +#define outb isa_outb +#define outb_p isa_outb_p +#define inw isa_inw +#define outw isa_outw +#define inl isa_inw +#define outl isa_outw +#define insb isa_insb +#define insw isa_insw +#define outsb isa_outsb +#define outsw isa_outsw +#endif /* MACH_HAS_ISA */ + + +#if defined(CONFIG_PCI) + +#define inl(port) in_le32(port) +#define outl(val,port) out_le32((port),(val)) + +#define readb(addr) in_8(addr) +#define readw(addr) in_le16(addr) +#define readl(addr) in_le32(addr) + +#define writeb(val,addr) out_8((addr),(val)) +#define writew(val,addr) out_le16((addr),(val)) +#define writel(val,addr) out_le32((addr),(val)) + + +#ifndef CONFIG_ISA +#define inb(port) in_8(port) +#define outb(val,port) out_8((port),(val)) +#define inw(port) in_le16(port) +#define outw(val,port) out_le16((port),(val)) + #else -#define IO_SPACE_LIMIT 0x0fffffff +/* + * kernel with both ISA and PCI compiled in, those have + * conflicting defs for in/out. Simply consider port < 1024 + * ISA and everything else PCI + */ +#define inb(port) ((port)<1024 ? isa_inb(port) : in_8(port)) +#define inb_p(port) ((port)<1024 ? isa_inb_p(port) : in_8(port)) +#define inw(port) ((port)<1024 ? isa_inw(port) : in_le16(port)) + +#define outb(val,port) ((port)<1024 ? isa_outb((val),(port)) : out_8((port),(val))) +#define outb_p(val,port) ((port)<1024 ? isa_outb_p((val),(port)) : out_8((port),(val))) +#define outw(val,port) ((port)<1024 ? isa_outw((val),(port)) : out_le16((port),(val))) #endif +#endif /* CONFIG_PCI */ + /* Values for nocacheflag and cmode */ #define IOMAP_FULL_CACHING 0 @@ -59,7 +262,10 @@ #define IOMAP_NOCACHE_NONSER 2 #define IOMAP_WRITETHROUGH 3 -extern void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag); +extern void iounmap(void *addr); + +extern void *__ioremap(unsigned long physaddr, unsigned long size, + int cacheflag); extern void __iounmap(void *addr, unsigned long size); extern inline void *ioremap(unsigned long physaddr, unsigned long size) @@ -70,11 +276,13 @@ { return __ioremap(physaddr, size, IOMAP_NOCACHE_SER); } -extern inline void *ioremap_writethrough(unsigned long physaddr, unsigned long size) +extern inline void *ioremap_writethrough(unsigned long physaddr, + unsigned long size) { return __ioremap(physaddr, size, IOMAP_WRITETHROUGH); } -extern inline void *ioremap_fullcache(unsigned long physaddr, unsigned long size) +extern inline void *ioremap_fullcache(unsigned long physaddr, + unsigned long size) { return __ioremap(physaddr, size, IOMAP_FULL_CACHING); } @@ -87,6 +295,11 @@ #define dma_cache_wback(_start,_size) do { } while (0) #define dma_cache_wback_inv(_start,_size) do { } while (0) -#endif /* __KERNEL__ */ +#ifndef CONFIG_SUN3 +#define IO_SPACE_LIMIT 0xffff +#else +#define IO_SPACE_LIMIT 0x0fffffff +#endif -#endif /* _M68K_IO_H */ +#endif /* __KERNEL__ */ +#endif /* _IO_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/linux_logo.h linux/include/asm-m68k/linux_logo.h --- v2.4.5/linux/include/asm-m68k/linux_logo.h Mon Oct 5 13:54:39 1998 +++ linux/include/asm-m68k/linux_logo.h Tue Jun 12 10:39:50 2001 @@ -26,883 +26,899 @@ #ifdef CONFIG_MAC -#define LINUX_LOGO_COLORS 95 +#define __HAVE_ARCH_LINUX_LOGO + +#define LINUX_LOGO_COLORS 185 #ifdef INCLUDE_LINUX_LOGO_DATA unsigned char linux_logo_red[] __initdata = { - 0x02, 0x82, 0xEA, 0x42, 0xC2, 0x82, 0xE2, 0xA2, - 0xDA, 0xC2, 0x22, 0x62, 0xB2, 0x92, 0xD2, 0x8A, - 0xB2, 0xFA, 0xDA, 0x32, 0x72, 0x12, 0xF2, 0x52, - 0xF2, 0xEA, 0xFA, 0xAA, 0xCA, 0x9A, 0xE2, 0xAA, - 0x8A, 0xEA, 0xD2, 0x92, 0xEA, 0xDA, 0x2A, 0x6A, - 0xDA, 0xBA, 0xD2, 0x52, 0x7A, 0x2A, 0x5A, 0x0A, - 0x6A, 0xEA, 0xE2, 0xC6, 0x96, 0xF2, 0x3A, 0x1A, - 0xB2, 0xBA, 0xF2, 0xDA, 0x0A, 0x86, 0x4A, 0xCA, - 0x8A, 0xE2, 0xA6, 0xDA, 0x66, 0xBA, 0x92, 0xDA, - 0xA2, 0xB6, 0x76, 0x12, 0xF2, 0xFA, 0xEA, 0xAE, - 0xCE, 0x9E, 0xB2, 0x8E, 0xF2, 0xD2, 0xA2, 0x6E, - 0xBE, 0xD6, 0x7E, 0x5E, 0xC2, 0xFA, 0x3A + 0x00, 0x06, 0x0a, 0x0e, 0x16, 0x1a, 0x1e, 0x22, + 0x12, 0x00, 0x2a, 0x36, 0x42, 0x4e, 0x4a, 0x56, + 0x26, 0x46, 0x2e, 0x32, 0x52, 0x3a, 0x02, 0xfa, + 0xf2, 0xf6, 0xe7, 0x74, 0x65, 0x7b, 0xea, 0xdd, + 0xd6, 0x5e, 0xbe, 0x5a, 0xe2, 0xda, 0xee, 0xb6, + 0xce, 0x65, 0x6e, 0x6a, 0xd2, 0xc6, 0x90, 0xca, + 0x9e, 0xbb, 0xb2, 0x8a, 0xa2, 0x9a, 0x86, 0xc3, + 0xfd, 0xae, 0x3e, 0xaa, 0x95, 0x80, 0x76, 0x79, + 0x62, 0x36, 0x9a, 0xe2, 0xec, 0xe1, 0xb8, 0xd7, + 0xaf, 0x25, 0xbc, 0xc0, 0xef, 0xea, 0xe8, 0xe8, + 0xf5, 0xf1, 0xda, 0xd3, 0x79, 0xdb, 0xf4, 0xf6, + 0xf6, 0xf6, 0xe2, 0x3d, 0xb4, 0xce, 0xe6, 0xee, + 0xf6, 0xa6, 0x68, 0xd8, 0xec, 0xf5, 0xc6, 0xc8, + 0x9c, 0x89, 0xd2, 0xee, 0xcb, 0xb9, 0xd2, 0x66, + 0x5e, 0x8b, 0xbe, 0xa8, 0xd5, 0xca, 0xb6, 0xae, + 0x9c, 0xc5, 0x8d, 0xbe, 0xbe, 0xb2, 0x9a, 0xa8, + 0x16, 0x12, 0x4a, 0x8e, 0xf2, 0xf6, 0xe4, 0xf1, + 0x26, 0x9a, 0xea, 0xf6, 0xe0, 0xd2, 0x9a, 0x2e, + 0x70, 0xd6, 0x46, 0x7c, 0xb4, 0x62, 0xd6, 0xa3, + 0x74, 0xa7, 0xa2, 0xca, 0xe0, 0xae, 0xbe, 0xce, + 0xa3, 0x8e, 0x6d, 0x8e, 0x32, 0xaf, 0x50, 0x9e, + 0x5b, 0x8a, 0x98, 0x82, 0x7a, 0x82, 0x56, 0x7c, + 0x8a, 0x56, 0x5e, 0x86, 0x6a, 0x52, 0x59, 0x64, + 0x5e, }; unsigned char linux_logo_green[] __initdata = { - 0x02, 0x82, 0xC2, 0x42, 0x8A, 0x56, 0xE2, 0xA2, - 0xAA, 0xC2, 0x22, 0x62, 0x86, 0x92, 0x9E, 0x6E, - 0xB2, 0xB2, 0xD2, 0x32, 0x72, 0x12, 0xD2, 0x52, - 0xF2, 0xB2, 0xC2, 0xAA, 0xCA, 0x9A, 0xA2, 0x7E, - 0x8A, 0xCA, 0x92, 0x66, 0xEA, 0xB2, 0x2A, 0x6A, - 0xA2, 0xBA, 0xD2, 0x36, 0x7A, 0x1A, 0x5A, 0x0A, - 0x4A, 0xE6, 0xAE, 0xC6, 0x96, 0xBA, 0x3A, 0x1A, - 0xAA, 0x7A, 0xCA, 0xDA, 0x02, 0x86, 0x4A, 0x8A, - 0x5E, 0xE2, 0xA6, 0xAE, 0x66, 0x82, 0x92, 0x9A, - 0x72, 0xB6, 0x76, 0x12, 0xD2, 0xFA, 0xB2, 0xAE, - 0xCE, 0x9E, 0x7A, 0x8E, 0xCA, 0x92, 0x6A, 0x6E, - 0xBE, 0xD6, 0x7E, 0x5E, 0xC6, 0xBA, 0x3E + 0x00, 0x06, 0x0a, 0x0e, 0x16, 0x1a, 0x1e, 0x22, + 0x12, 0x00, 0x2a, 0x36, 0x42, 0x4e, 0x4a, 0x56, + 0x26, 0x46, 0x2e, 0x32, 0x52, 0x3a, 0x02, 0xfa, + 0xf2, 0xf6, 0xe7, 0x74, 0x65, 0x7b, 0xea, 0xdd, + 0xd6, 0x5e, 0xbe, 0x5a, 0xe2, 0xda, 0xee, 0xb6, + 0xce, 0x62, 0x6e, 0x6a, 0xd2, 0xc6, 0x90, 0xca, + 0x9e, 0xbb, 0xb2, 0x8a, 0xa2, 0x9a, 0x86, 0xc3, + 0xfd, 0xae, 0x3e, 0xaa, 0x95, 0x80, 0x62, 0x5c, + 0x4e, 0x26, 0x72, 0xaa, 0xba, 0xaf, 0x90, 0xae, + 0x92, 0x1a, 0xa4, 0x85, 0xb6, 0xbe, 0xc3, 0xc8, + 0xcf, 0xd0, 0xc2, 0xce, 0x57, 0xa2, 0xd6, 0xda, + 0xda, 0xd7, 0xb8, 0x2a, 0x7b, 0x91, 0xae, 0xca, + 0xda, 0xa6, 0x45, 0x9e, 0xb2, 0xd7, 0x9b, 0x90, + 0x76, 0x5c, 0xa2, 0xbe, 0xa6, 0x85, 0x96, 0x4e, + 0x46, 0x66, 0x92, 0x7a, 0x9a, 0x96, 0x9d, 0x9a, + 0x6b, 0x8a, 0x8d, 0x8e, 0xb2, 0xa6, 0x79, 0x7c, + 0x12, 0x0e, 0x36, 0x86, 0xba, 0xbe, 0xb8, 0xc4, + 0x1e, 0x8e, 0xae, 0xba, 0xb2, 0xa6, 0x7a, 0x20, + 0x64, 0xaa, 0x2f, 0x70, 0x85, 0x46, 0xa6, 0x6e, + 0x51, 0x72, 0x92, 0xa2, 0xa6, 0x87, 0x96, 0xa2, + 0x85, 0x7a, 0x6a, 0x6e, 0x22, 0x76, 0x36, 0x76, + 0x3c, 0x6e, 0x63, 0x53, 0x66, 0x62, 0x42, 0x50, + 0x56, 0x42, 0x56, 0x56, 0x56, 0x3e, 0x51, 0x52, + 0x56, }; unsigned char linux_logo_blue[] __initdata = { - 0x04, 0x84, 0x04, 0x44, 0x04, 0x04, 0xDC, 0xA4, - 0x0C, 0xC4, 0x1C, 0x64, 0x04, 0x8C, 0x04, 0x34, - 0xB4, 0x0C, 0xAC, 0x34, 0x74, 0x04, 0x0C, 0x4C, - 0xF4, 0x0C, 0x0C, 0xAC, 0xCC, 0x9C, 0x0C, 0x04, - 0x8C, 0x0C, 0x04, 0x04, 0xEC, 0x2C, 0x2C, 0x6C, - 0x04, 0xBC, 0xD4, 0x04, 0x7C, 0x04, 0x5C, 0x0C, - 0x04, 0xEC, 0x04, 0xC4, 0x94, 0x14, 0x3C, 0x1C, - 0xA4, 0x04, 0x24, 0xDC, 0x04, 0x84, 0x4C, 0x0C, - 0x04, 0xE4, 0xA4, 0x04, 0x64, 0x04, 0x94, 0x14, - 0x0C, 0xB4, 0x74, 0x14, 0x24, 0xFC, 0x14, 0xAC, - 0xCC, 0x9C, 0x0C, 0x8C, 0x14, 0x14, 0x04, 0x6C, - 0xBC, 0xD4, 0x7C, 0x5C, 0xD4, 0x14, 0x3C + 0x00, 0x06, 0x0a, 0x0e, 0x16, 0x1a, 0x1e, 0x22, + 0x12, 0x01, 0x2a, 0x36, 0x42, 0x4e, 0x4a, 0x56, + 0x26, 0x46, 0x2e, 0x32, 0x52, 0x3a, 0x06, 0xfa, + 0xf2, 0xf6, 0xe7, 0x74, 0x65, 0x7b, 0xea, 0xdd, + 0xd6, 0x5e, 0xbe, 0x5a, 0xe2, 0xda, 0xee, 0xb6, + 0xce, 0x59, 0x6e, 0x6a, 0xd2, 0xc6, 0x90, 0xca, + 0x9e, 0xbb, 0xb2, 0x8a, 0xa2, 0x9a, 0x86, 0xc3, + 0xfd, 0xae, 0x3e, 0xaa, 0x95, 0x80, 0x2e, 0x08, + 0x0a, 0x06, 0x0a, 0x0b, 0x0b, 0x0f, 0x0c, 0x0f, + 0x3d, 0x09, 0x73, 0x09, 0x0d, 0x0a, 0x10, 0x1e, + 0x2d, 0x13, 0x86, 0xba, 0x19, 0x0a, 0x36, 0x3c, + 0x26, 0x14, 0x0d, 0x06, 0x07, 0x0a, 0x0b, 0x0f, + 0x4a, 0xa6, 0x06, 0x0a, 0x0c, 0x2b, 0x0a, 0x0b, + 0x0a, 0x06, 0x0a, 0x0a, 0x11, 0x0b, 0x0a, 0x0a, + 0x1e, 0x0f, 0x0d, 0x0a, 0x0b, 0x22, 0x6a, 0x72, + 0x0b, 0x0b, 0x8d, 0x22, 0x90, 0x92, 0x3c, 0x2c, + 0x06, 0x06, 0x0e, 0x6a, 0x0e, 0x0e, 0x3e, 0x0e, + 0x0a, 0x5a, 0x0d, 0x0e, 0x3e, 0x0a, 0x2e, 0x06, + 0x4e, 0x36, 0x06, 0x58, 0x24, 0x06, 0x3a, 0x08, + 0x08, 0x07, 0x5e, 0x45, 0x0a, 0x32, 0x2e, 0x2a, + 0x43, 0x48, 0x5f, 0x2e, 0x06, 0x06, 0x07, 0x24, + 0x06, 0x32, 0x06, 0x06, 0x46, 0x2e, 0x22, 0x06, + 0x06, 0x1e, 0x4c, 0x06, 0x3a, 0x22, 0x42, 0x34, + 0x42, }; unsigned char linux_logo[] __initdata = { - 0x53, 0x3D, 0x40, 0x73, 0x71, 0x3B, 0x3B, 0x71, - 0x3D, 0x54, 0x73, 0x40, 0x73, 0x3D, 0x27, 0x71, - 0x40, 0x6A, 0x7A, 0x3D, 0x3B, 0x30, 0x30, 0x62, - 0x40, 0x6A, 0x21, 0x62, 0x78, 0x29, 0x49, 0x30, - 0x6F, 0x27, 0x54, 0x3D, 0x62, 0x27, 0x54, 0x66, - 0x71, 0x6F, 0x6F, 0x6F, 0x78, 0x53, 0x29, 0x29, - 0x53, 0x70, 0x53, 0x3D, 0x40, 0x73, 0x71, 0x3B, - 0x3B, 0x71, 0x3D, 0x54, 0x73, 0x40, 0x73, 0x3D, - 0x27, 0x71, 0x40, 0x6A, 0x7A, 0x3D, 0x3B, 0x30, - 0x30, 0x62, 0x40, 0x6A, 0x21, 0x62, 0x78, 0x29, - 0x71, 0x4C, 0x6A, 0x40, 0x71, 0x62, 0x27, 0x71, - 0x54, 0x66, 0x73, 0x40, 0x73, 0x3D, 0x3D, 0x40, - 0x6A, 0x77, 0x7A, 0x71, 0x30, 0x69, 0x6F, 0x71, - 0x54, 0x73, 0x3D, 0x30, 0x49, 0x30, 0x3B, 0x62, - 0x27, 0x3D, 0x54, 0x3D, 0x71, 0x71, 0x27, 0x62, - 0x62, 0x3B, 0x62, 0x27, 0x3B, 0x69, 0x69, 0x69, - 0x69, 0x30, 0x71, 0x4C, 0x6A, 0x40, 0x71, 0x62, - 0x27, 0x71, 0x54, 0x66, 0x73, 0x40, 0x73, 0x3D, - 0x3D, 0x40, 0x6A, 0x77, 0x7A, 0x71, 0x30, 0x69, - 0x6F, 0x71, 0x54, 0x73, 0x3D, 0x30, 0x49, 0x30, - 0x40, 0x34, 0x34, 0x40, 0x27, 0x6F, 0x62, 0x3D, - 0x54, 0x66, 0x40, 0x73, 0x66, 0x66, 0x2D, 0x5D, - 0x7A, 0x5D, 0x3D, 0x6F, 0x69, 0x69, 0x30, 0x27, - 0x27, 0x27, 0x62, 0x6F, 0x30, 0x3B, 0x62, 0x27, - 0x3D, 0x54, 0x2D, 0x54, 0x27, 0x71, 0x3D, 0x27, - 0x62, 0x62, 0x62, 0x62, 0x3B, 0x30, 0x6F, 0x6F, - 0x6F, 0x71, 0x40, 0x34, 0x34, 0x40, 0x27, 0x6F, - 0x62, 0x3D, 0x54, 0x66, 0x40, 0x73, 0x66, 0x66, - 0x2D, 0x5D, 0x7A, 0x5D, 0x3D, 0x6F, 0x69, 0x69, - 0x30, 0x27, 0x27, 0x27, 0x62, 0x6F, 0x30, 0x6F, - 0x4C, 0x77, 0x6A, 0x2D, 0x3B, 0x6F, 0x3B, 0x71, - 0x54, 0x66, 0x2D, 0x73, 0x66, 0x54, 0x73, 0x73, - 0x73, 0x3D, 0x62, 0x6F, 0x69, 0x30, 0x6F, 0x27, - 0x3D, 0x3D, 0x27, 0x62, 0x62, 0x62, 0x27, 0x71, - 0x54, 0x73, 0x73, 0x54, 0x3D, 0x3D, 0x20, 0x20, - 0x20, 0x20, 0x3B, 0x62, 0x3B, 0x62, 0x71, 0x71, - 0x3D, 0x2D, 0x4C, 0x77, 0x6A, 0x66, 0x3B, 0x6F, - 0x3B, 0x71, 0x54, 0x66, 0x2D, 0x73, 0x66, 0x54, - 0x73, 0x73, 0x73, 0x3D, 0x62, 0x6F, 0x69, 0x30, - 0x6F, 0x27, 0x3D, 0x3D, 0x27, 0x62, 0x62, 0x27, - 0x4C, 0x4C, 0x5D, 0x71, 0x30, 0x30, 0x3B, 0x27, - 0x54, 0x66, 0x73, 0x66, 0x66, 0x54, 0x54, 0x3D, - 0x27, 0x62, 0x6F, 0x30, 0x30, 0x6F, 0x27, 0x3D, - 0x54, 0x54, 0x3D, 0x71, 0x3D, 0x71, 0x3D, 0x3D, - 0x66, 0x73, 0x66, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x71, 0x3D, - 0x66, 0x40, 0x4C, 0x4C, 0x5D, 0x71, 0x30, 0x30, - 0x3B, 0x27, 0x54, 0x66, 0x73, 0x66, 0x66, 0x54, - 0x54, 0x3D, 0x27, 0x62, 0x6F, 0x30, 0x30, 0x6F, - 0x27, 0x3D, 0x54, 0x54, 0x3D, 0x71, 0x71, 0x71, - 0x5D, 0x5D, 0x54, 0x62, 0x69, 0x69, 0x3B, 0x3D, - 0x66, 0x40, 0x73, 0x66, 0x54, 0x54, 0x71, 0x62, - 0x3B, 0x6F, 0x6F, 0x6F, 0x3B, 0x27, 0x3D, 0x2D, - 0x66, 0x54, 0x71, 0x71, 0x27, 0x71, 0x71, 0x3D, - 0x3D, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x54, - 0x73, 0x40, 0x5D, 0x5D, 0x54, 0x62, 0x69, 0x69, - 0x3B, 0x3D, 0x66, 0x40, 0x73, 0x66, 0x54, 0x54, - 0x71, 0x62, 0x3B, 0x6F, 0x6F, 0x6F, 0x3B, 0x27, - 0x3D, 0x66, 0x66, 0x54, 0x71, 0x71, 0x27, 0x71, - 0x66, 0x73, 0x3D, 0x27, 0x6F, 0x6F, 0x62, 0x54, - 0x40, 0x21, 0x5D, 0x73, 0x3D, 0x27, 0x62, 0x6F, - 0x6F, 0x3B, 0x3B, 0x62, 0x27, 0x71, 0x3D, 0x3D, - 0x3D, 0x71, 0x62, 0x62, 0x62, 0x27, 0x27, 0x71, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x4F, 0x46, 0x2A, 0x20, 0x20, - 0x20, 0x73, 0x66, 0x73, 0x3D, 0x27, 0x6F, 0x6F, - 0x62, 0x54, 0x40, 0x21, 0x5D, 0x73, 0x3D, 0x27, - 0x62, 0x6F, 0x6F, 0x3B, 0x3B, 0x62, 0x27, 0x71, - 0x3D, 0x3D, 0x3D, 0x71, 0x62, 0x27, 0x62, 0x27, - 0x3D, 0x40, 0x66, 0x27, 0x3B, 0x3B, 0x71, 0x66, - 0x7A, 0x21, 0x40, 0x54, 0x27, 0x3B, 0x6F, 0x3B, - 0x62, 0x62, 0x27, 0x6D, 0x6D, 0x6D, 0x6D, 0x38, - 0x6D, 0x6D, 0x38, 0x6D, 0x38, 0x6D, 0x38, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x6D, 0x6D, 0x38, 0x6D, 0x6D, 0x38, - 0x38, 0x6D, 0x38, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, - 0x6F, 0x3B, 0x62, 0x62, 0x27, 0x27, 0x27, 0x27, - 0x71, 0x3D, 0x71, 0x71, 0x71, 0x71, 0x3D, 0x3D, - 0x27, 0x40, 0x54, 0x62, 0x30, 0x30, 0x27, 0x40, - 0x7A, 0x5D, 0x54, 0x3D, 0x62, 0x30, 0x30, 0x3B, - 0x71, 0x3D, 0x71, 0x38, 0x6D, 0x6D, 0x6D, 0x6D, - 0x38, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x38, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x6D, 0x6D, 0x38, 0x6D, 0x6D, - 0x6D, 0x6D, 0x38, 0x6D, 0x38, 0x6D, 0x6D, 0x6D, - 0x30, 0x3B, 0x71, 0x3D, 0x71, 0x27, 0x71, 0x71, - 0x3D, 0x66, 0x73, 0x40, 0x73, 0x66, 0x2D, 0x66, - 0x30, 0x66, 0x71, 0x6F, 0x69, 0x6F, 0x54, 0x21, - 0x7A, 0x66, 0x3D, 0x3B, 0x6F, 0x6F, 0x3B, 0x71, - 0x54, 0x66, 0x3D, 0x4C, 0x44, 0x51, 0x44, 0x44, - 0x44, 0x38, 0x44, 0x38, 0x44, 0x38, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x6D, 0x38, 0x6D, 0x6D, 0x6D, - 0x38, 0x6D, 0x6D, 0x38, 0x6D, 0x38, 0x38, 0x51, - 0x3B, 0x71, 0x54, 0x66, 0x3D, 0x3D, 0x3D, 0x2D, - 0x40, 0x40, 0x5D, 0x40, 0x73, 0x66, 0x66, 0x3D, - 0x69, 0x27, 0x3B, 0x30, 0x69, 0x3B, 0x73, 0x7A, - 0x21, 0x3D, 0x62, 0x3B, 0x6F, 0x3B, 0x27, 0x66, - 0x73, 0x73, 0x54, 0x4E, 0x44, 0x26, 0x26, 0x5B, - 0x26, 0x44, 0x44, 0x44, 0x44, 0x44, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x38, 0x38, 0x38, 0x38, 0x38, - 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x6D, 0x26, - 0x27, 0x66, 0x73, 0x73, 0x66, 0x2D, 0x66, 0x2D, - 0x66, 0x54, 0x54, 0x71, 0x27, 0x27, 0x27, 0x62, - 0x69, 0x3B, 0x6F, 0x6F, 0x62, 0x54, 0x40, 0x21, - 0x73, 0x27, 0x3B, 0x3B, 0x71, 0x54, 0x66, 0x66, - 0x73, 0x73, 0x2D, 0x37, 0x44, 0x51, 0x38, 0x38, - 0x44, 0x6D, 0x38, 0x6D, 0x38, 0x38, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x38, 0x6D, 0x38, 0x6D, - 0x38, 0x6D, 0x6D, 0x6D, 0x38, 0x38, 0x6D, 0x70, - 0x2D, 0x66, 0x73, 0x66, 0x66, 0x54, 0x54, 0x54, - 0x27, 0x62, 0x6F, 0x6F, 0x6F, 0x6F, 0x3B, 0x62, - 0x3B, 0x27, 0x27, 0x27, 0x3D, 0x40, 0x21, 0x40, - 0x54, 0x62, 0x3B, 0x71, 0x73, 0x5D, 0x40, 0x73, - 0x66, 0x66, 0x2D, 0x33, 0x6D, 0x26, 0x44, 0x4F, - 0x5E, 0x5E, 0x37, 0x5E, 0x37, 0x46, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x44, 0x26, 0x26, 0x44, - 0x70, 0x38, 0x26, 0x38, 0x38, 0x44, 0x6D, 0x53, - 0x40, 0x73, 0x66, 0x2D, 0x66, 0x73, 0x66, 0x54, - 0x27, 0x6F, 0x30, 0x69, 0x30, 0x6F, 0x62, 0x62, - 0x62, 0x71, 0x3D, 0x54, 0x73, 0x5D, 0x5D, 0x66, - 0x27, 0x62, 0x71, 0x54, 0x5D, 0x5D, 0x66, 0x3D, - 0x3D, 0x73, 0x40, 0x37, 0x44, 0x44, 0x51, 0x20, - 0x6F, 0x6F, 0x62, 0x27, 0x27, 0x20, 0x20, 0x20, - 0x4F, 0x20, 0x2A, 0x2A, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x77, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x71, 0x3D, 0x73, 0x5D, - 0x40, 0x54, 0x27, 0x3B, 0x2D, 0x6D, 0x38, 0x3C, - 0x66, 0x3D, 0x54, 0x66, 0x40, 0x40, 0x73, 0x54, - 0x62, 0x6F, 0x30, 0x6F, 0x62, 0x71, 0x71, 0x71, - 0x62, 0x3D, 0x66, 0x73, 0x40, 0x5D, 0x73, 0x71, - 0x62, 0x27, 0x54, 0x73, 0x5D, 0x73, 0x27, 0x62, - 0x71, 0x40, 0x21, 0x37, 0x26, 0x51, 0x44, 0x4E, - 0x3B, 0x71, 0x2D, 0x73, 0x2D, 0x20, 0x20, 0x20, - 0x35, 0x73, 0x77, 0x4F, 0x6B, 0x20, 0x20, 0x4F, - 0x20, 0x73, 0x73, 0x73, 0x58, 0x20, 0x77, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x2D, 0x40, 0x40, 0x5D, - 0x73, 0x71, 0x62, 0x27, 0x71, 0x38, 0x44, 0x49, - 0x27, 0x62, 0x3D, 0x40, 0x21, 0x40, 0x54, 0x27, - 0x3B, 0x6F, 0x3B, 0x71, 0x54, 0x66, 0x66, 0x3D, - 0x62, 0x54, 0x40, 0x21, 0x7A, 0x40, 0x3D, 0x62, - 0x62, 0x71, 0x66, 0x40, 0x66, 0x71, 0x62, 0x3B, - 0x54, 0x5D, 0x73, 0x23, 0x51, 0x26, 0x26, 0x30, - 0x3B, 0x3D, 0x66, 0x73, 0x66, 0x20, 0x20, 0x4F, - 0x58, 0x7C, 0x62, 0x34, 0x57, 0x20, 0x20, 0x20, - 0x73, 0x58, 0x49, 0x7C, 0x79, 0x73, 0x20, 0x4F, - 0x20, 0x20, 0x20, 0x20, 0x40, 0x21, 0x7A, 0x40, - 0x3D, 0x27, 0x62, 0x71, 0x49, 0x44, 0x6D, 0x78, - 0x62, 0x3B, 0x3D, 0x5D, 0x40, 0x3D, 0x3B, 0x69, - 0x49, 0x49, 0x3B, 0x71, 0x66, 0x73, 0x66, 0x54, - 0x27, 0x66, 0x5D, 0x7A, 0x21, 0x73, 0x71, 0x62, - 0x27, 0x54, 0x73, 0x66, 0x3D, 0x27, 0x62, 0x62, - 0x54, 0x73, 0x71, 0x37, 0x26, 0x5B, 0x44, 0x5B, - 0x27, 0x54, 0x40, 0x2D, 0x54, 0x20, 0x20, 0x77, - 0x78, 0x6D, 0x6D, 0x6D, 0x20, 0x20, 0x20, 0x20, - 0x79, 0x38, 0x38, 0x6D, 0x6D, 0x69, 0x2D, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x7A, 0x7A, 0x40, - 0x71, 0x62, 0x27, 0x54, 0x79, 0x26, 0x38, 0x49, - 0x3B, 0x27, 0x54, 0x2D, 0x71, 0x6F, 0x49, 0x53, - 0x78, 0x30, 0x27, 0x54, 0x40, 0x73, 0x54, 0x3D, - 0x71, 0x66, 0x5D, 0x7A, 0x21, 0x66, 0x27, 0x3B, - 0x27, 0x66, 0x73, 0x54, 0x27, 0x27, 0x27, 0x3D, - 0x3D, 0x71, 0x6F, 0x5E, 0x26, 0x79, 0x26, 0x78, - 0x5D, 0x4C, 0x4C, 0x21, 0x73, 0x20, 0x20, 0x2D, - 0x35, 0x5C, 0x46, 0x38, 0x77, 0x20, 0x4F, 0x20, - 0x51, 0x6D, 0x20, 0x2D, 0x20, 0x6D, 0x6D, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x7A, 0x21, 0x54, - 0x62, 0x3B, 0x27, 0x2D, 0x29, 0x26, 0x44, 0x70, - 0x27, 0x3D, 0x3D, 0x71, 0x6F, 0x78, 0x53, 0x29, - 0x69, 0x3D, 0x21, 0x4C, 0x4C, 0x5D, 0x66, 0x54, - 0x54, 0x73, 0x21, 0x6A, 0x21, 0x3D, 0x3B, 0x3B, - 0x71, 0x66, 0x66, 0x3D, 0x27, 0x27, 0x71, 0x3D, - 0x27, 0x6F, 0x49, 0x7E, 0x61, 0x5B, 0x44, 0x26, - 0x34, 0x34, 0x6A, 0x21, 0x73, 0x66, 0x20, 0x32, - 0x20, 0x20, 0x2D, 0x6D, 0x77, 0x2A, 0x37, 0x20, - 0x6D, 0x20, 0x20, 0x20, 0x7E, 0x38, 0x38, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x4C, 0x21, 0x3D, - 0x3B, 0x3B, 0x71, 0x73, 0x69, 0x44, 0x38, 0x71, - 0x27, 0x3D, 0x71, 0x3B, 0x49, 0x29, 0x29, 0x6F, - 0x54, 0x7A, 0x34, 0x77, 0x6A, 0x21, 0x66, 0x66, - 0x4C, 0x7A, 0x21, 0x4C, 0x21, 0x71, 0x3B, 0x3B, - 0x54, 0x73, 0x3D, 0x62, 0x3B, 0x62, 0x62, 0x62, - 0x62, 0x69, 0x29, 0x2B, 0x79, 0x79, 0x26, 0x38, - 0x47, 0x6A, 0x5D, 0x54, 0x27, 0x3D, 0x20, 0x29, - 0x57, 0x20, 0x2D, 0x61, 0x37, 0x5C, 0x20, 0x20, - 0x29, 0x20, 0x20, 0x20, 0x20, 0x29, 0x6D, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x6A, 0x21, 0x3D, - 0x3B, 0x3B, 0x54, 0x66, 0x78, 0x26, 0x26, 0x30, - 0x62, 0x62, 0x3B, 0x69, 0x78, 0x78, 0x6F, 0x66, - 0x6A, 0x64, 0x47, 0x4C, 0x5D, 0x54, 0x71, 0x71, - 0x4C, 0x5D, 0x5D, 0x21, 0x5D, 0x71, 0x3B, 0x62, - 0x54, 0x66, 0x27, 0x3B, 0x6F, 0x6F, 0x3B, 0x3B, - 0x6F, 0x49, 0x78, 0x23, 0x4A, 0x79, 0x4A, 0x6D, - 0x34, 0x21, 0x66, 0x3D, 0x62, 0x27, 0x20, 0x20, - 0x38, 0x20, 0x20, 0x52, 0x3A, 0x52, 0x63, 0x36, - 0x48, 0x4D, 0x20, 0x20, 0x20, 0x6D, 0x38, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x5D, 0x3D, - 0x3B, 0x62, 0x2D, 0x66, 0x79, 0x26, 0x51, 0x54, - 0x3B, 0x62, 0x6F, 0x49, 0x78, 0x30, 0x66, 0x34, - 0x2B, 0x2B, 0x34, 0x21, 0x66, 0x71, 0x62, 0x62, - 0x3D, 0x3D, 0x54, 0x5D, 0x40, 0x71, 0x3B, 0x3B, - 0x54, 0x54, 0x3B, 0x69, 0x30, 0x6F, 0x3B, 0x27, - 0x6F, 0x78, 0x78, 0x46, 0x26, 0x5B, 0x4A, 0x51, - 0x5D, 0x54, 0x71, 0x62, 0x3B, 0x3B, 0x20, 0x20, - 0x6D, 0x20, 0x72, 0x55, 0x3A, 0x74, 0x41, 0x39, - 0x45, 0x5A, 0x24, 0x2F, 0x6D, 0x38, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x5D, 0x40, 0x27, - 0x3B, 0x62, 0x3D, 0x54, 0x30, 0x5B, 0x26, 0x27, - 0x3B, 0x62, 0x6F, 0x78, 0x78, 0x3B, 0x21, 0x64, - 0x7B, 0x77, 0x5D, 0x54, 0x71, 0x62, 0x62, 0x3B, - 0x53, 0x62, 0x71, 0x73, 0x73, 0x27, 0x6F, 0x3B, - 0x3D, 0x3D, 0x3B, 0x49, 0x30, 0x62, 0x27, 0x27, - 0x6F, 0x78, 0x49, 0x46, 0x79, 0x53, 0x4A, 0x38, - 0x2D, 0x71, 0x62, 0x6F, 0x6F, 0x6F, 0x20, 0x20, - 0x20, 0x24, 0x52, 0x3A, 0x22, 0x41, 0x5A, 0x45, - 0x45, 0x63, 0x41, 0x22, 0x36, 0x28, 0x4D, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x73, 0x27, - 0x6F, 0x3B, 0x3D, 0x3D, 0x49, 0x51, 0x61, 0x69, - 0x27, 0x27, 0x30, 0x78, 0x69, 0x71, 0x4C, 0x64, - 0x34, 0x5D, 0x66, 0x71, 0x62, 0x6F, 0x6F, 0x6F, - 0x79, 0x27, 0x66, 0x73, 0x66, 0x62, 0x6F, 0x6F, - 0x3D, 0x3D, 0x3B, 0x30, 0x30, 0x62, 0x3D, 0x71, - 0x6F, 0x69, 0x6F, 0x23, 0x5B, 0x4A, 0x4A, 0x38, - 0x66, 0x3D, 0x3B, 0x6F, 0x6F, 0x3B, 0x20, 0x4D, - 0x43, 0x48, 0x39, 0x55, 0x22, 0x22, 0x41, 0x45, - 0x45, 0x45, 0x45, 0x41, 0x22, 0x45, 0x5A, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x2D, 0x62, - 0x30, 0x3B, 0x3D, 0x3D, 0x27, 0x26, 0x61, 0x27, - 0x3D, 0x27, 0x6F, 0x69, 0x6F, 0x54, 0x4C, 0x34, - 0x7A, 0x40, 0x66, 0x54, 0x62, 0x30, 0x6F, 0x3B, - 0x53, 0x7A, 0x7A, 0x73, 0x54, 0x62, 0x30, 0x3B, - 0x3D, 0x3D, 0x62, 0x30, 0x30, 0x3B, 0x71, 0x62, - 0x30, 0x30, 0x27, 0x7E, 0x70, 0x70, 0x3C, 0x6D, - 0x21, 0x66, 0x3B, 0x69, 0x3B, 0x71, 0x20, 0x72, - 0x24, 0x67, 0x22, 0x22, 0x36, 0x36, 0x45, 0x45, - 0x45, 0x22, 0x41, 0x41, 0x3F, 0x42, 0x52, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x54, 0x62, - 0x30, 0x3B, 0x3D, 0x54, 0x62, 0x26, 0x79, 0x3B, - 0x71, 0x27, 0x30, 0x30, 0x27, 0x5D, 0x4C, 0x6A, - 0x7A, 0x7A, 0x5D, 0x54, 0x3B, 0x30, 0x6F, 0x71, - 0x27, 0x64, 0x77, 0x40, 0x71, 0x62, 0x3B, 0x62, - 0x3D, 0x54, 0x27, 0x3B, 0x6F, 0x3B, 0x27, 0x27, - 0x62, 0x3B, 0x3D, 0x23, 0x26, 0x5B, 0x3C, 0x38, - 0x5D, 0x71, 0x69, 0x69, 0x62, 0x54, 0x20, 0x50, - 0x5F, 0x48, 0x3A, 0x55, 0x41, 0x63, 0x70, 0x22, - 0x22, 0x45, 0x3F, 0x42, 0x48, 0x48, 0x45, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x71, 0x62, - 0x3B, 0x62, 0x3D, 0x54, 0x30, 0x26, 0x61, 0x71, - 0x27, 0x27, 0x62, 0x62, 0x54, 0x5D, 0x7A, 0x4C, - 0x4C, 0x4C, 0x5D, 0x71, 0x30, 0x69, 0x62, 0x54, - 0x7A, 0x64, 0x34, 0x73, 0x71, 0x27, 0x62, 0x62, - 0x71, 0x54, 0x71, 0x3B, 0x6F, 0x3B, 0x71, 0x3D, - 0x3D, 0x71, 0x2D, 0x7E, 0x79, 0x53, 0x3C, 0x38, - 0x3D, 0x6F, 0x78, 0x49, 0x71, 0x73, 0x20, 0x20, - 0x25, 0x3F, 0x3A, 0x41, 0x5A, 0x45, 0x41, 0x45, - 0x3F, 0x50, 0x24, 0x28, 0x28, 0x3F, 0x4D, 0x20, - 0x20, 0x77, 0x77, 0x20, 0x20, 0x20, 0x71, 0x27, - 0x62, 0x62, 0x71, 0x54, 0x78, 0x79, 0x38, 0x71, - 0x71, 0x3D, 0x71, 0x71, 0x66, 0x5D, 0x5D, 0x21, - 0x21, 0x21, 0x54, 0x30, 0x78, 0x69, 0x27, 0x66, - 0x7A, 0x4C, 0x40, 0x3D, 0x27, 0x62, 0x62, 0x3B, - 0x62, 0x71, 0x62, 0x30, 0x69, 0x6F, 0x71, 0x54, - 0x3D, 0x3D, 0x54, 0x23, 0x4A, 0x3C, 0x3C, 0x38, - 0x6F, 0x29, 0x53, 0x30, 0x54, 0x66, 0x20, 0x57, - 0x7C, 0x25, 0x4B, 0x3F, 0x43, 0x4B, 0x4B, 0x2C, - 0x2E, 0x2E, 0x2E, 0x24, 0x58, 0x58, 0x78, 0x20, - 0x20, 0x20, 0x34, 0x77, 0x20, 0x20, 0x20, 0x62, - 0x62, 0x3B, 0x62, 0x71, 0x29, 0x79, 0x61, 0x27, - 0x27, 0x54, 0x54, 0x71, 0x54, 0x54, 0x66, 0x54, - 0x66, 0x71, 0x6F, 0x78, 0x53, 0x69, 0x54, 0x73, - 0x73, 0x73, 0x3D, 0x27, 0x27, 0x27, 0x62, 0x3B, - 0x62, 0x71, 0x71, 0x3B, 0x6F, 0x3B, 0x27, 0x54, - 0x66, 0x3D, 0x3D, 0x37, 0x53, 0x78, 0x49, 0x38, - 0x78, 0x29, 0x78, 0x3B, 0x66, 0x73, 0x20, 0x20, - 0x7C, 0x69, 0x68, 0x68, 0x52, 0x2E, 0x42, 0x67, - 0x5F, 0x45, 0x2C, 0x69, 0x78, 0x32, 0x78, 0x78, - 0x20, 0x20, 0x34, 0x77, 0x35, 0x20, 0x20, 0x27, - 0x62, 0x3B, 0x62, 0x71, 0x30, 0x26, 0x61, 0x73, - 0x27, 0x3D, 0x66, 0x3D, 0x3D, 0x27, 0x27, 0x62, - 0x62, 0x6F, 0x78, 0x53, 0x78, 0x62, 0x54, 0x66, - 0x27, 0x71, 0x3D, 0x71, 0x62, 0x62, 0x27, 0x3B, - 0x62, 0x71, 0x71, 0x27, 0x27, 0x27, 0x27, 0x3D, - 0x54, 0x3D, 0x27, 0x7E, 0x29, 0x29, 0x29, 0x6D, - 0x49, 0x49, 0x6F, 0x54, 0x73, 0x54, 0x20, 0x20, - 0x29, 0x7C, 0x69, 0x43, 0x76, 0x72, 0x2C, 0x76, - 0x68, 0x62, 0x78, 0x29, 0x6D, 0x38, 0x6D, 0x32, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, - 0x27, 0x3B, 0x62, 0x71, 0x78, 0x61, 0x6D, 0x3C, - 0x27, 0x3D, 0x54, 0x3D, 0x27, 0x62, 0x3B, 0x6F, - 0x6F, 0x69, 0x49, 0x49, 0x6F, 0x3D, 0x73, 0x66, - 0x3D, 0x3D, 0x3D, 0x3D, 0x71, 0x27, 0x71, 0x62, - 0x62, 0x71, 0x3D, 0x71, 0x71, 0x71, 0x27, 0x71, - 0x54, 0x3D, 0x27, 0x46, 0x49, 0x78, 0x49, 0x6D, - 0x6F, 0x27, 0x54, 0x73, 0x40, 0x20, 0x20, 0x20, - 0x44, 0x32, 0x29, 0x49, 0x77, 0x2F, 0x73, 0x62, - 0x29, 0x32, 0x29, 0x51, 0x6D, 0x38, 0x6D, 0x38, - 0x56, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x71, 0x62, 0x62, 0x71, 0x6F, 0x70, 0x38, 0x71, - 0x27, 0x71, 0x54, 0x3D, 0x62, 0x3B, 0x3B, 0x6F, - 0x6F, 0x6F, 0x3B, 0x27, 0x54, 0x40, 0x73, 0x66, - 0x40, 0x40, 0x66, 0x3D, 0x71, 0x3D, 0x71, 0x71, - 0x27, 0x27, 0x3D, 0x54, 0x3D, 0x3D, 0x71, 0x54, - 0x73, 0x73, 0x3D, 0x46, 0x78, 0x49, 0x78, 0x44, - 0x66, 0x73, 0x5D, 0x5D, 0x35, 0x20, 0x20, 0x78, - 0x6D, 0x51, 0x78, 0x49, 0x58, 0x29, 0x29, 0x49, - 0x29, 0x79, 0x38, 0x38, 0x6D, 0x6D, 0x38, 0x6D, - 0x6D, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x6B, 0x71, 0x27, 0x27, 0x29, 0x3C, 0x44, 0x40, - 0x3D, 0x54, 0x73, 0x73, 0x54, 0x71, 0x71, 0x3D, - 0x3D, 0x3D, 0x66, 0x40, 0x5D, 0x5D, 0x5D, 0x40, - 0x21, 0x5D, 0x73, 0x66, 0x3D, 0x3D, 0x71, 0x71, - 0x27, 0x27, 0x3D, 0x54, 0x54, 0x66, 0x54, 0x73, - 0x5D, 0x21, 0x40, 0x33, 0x69, 0x49, 0x30, 0x38, - 0x7A, 0x7A, 0x7A, 0x21, 0x6B, 0x20, 0x20, 0x6D, - 0x38, 0x6D, 0x38, 0x7C, 0x49, 0x29, 0x69, 0x78, - 0x38, 0x38, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x38, - 0x6D, 0x37, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x71, 0x27, 0x71, 0x78, 0x3C, 0x26, 0x30, - 0x66, 0x66, 0x5D, 0x21, 0x5D, 0x73, 0x73, 0x40, - 0x5D, 0x21, 0x7A, 0x4C, 0x21, 0x5D, 0x21, 0x21, - 0x5D, 0x54, 0x54, 0x54, 0x3D, 0x71, 0x3D, 0x71, - 0x27, 0x27, 0x71, 0x54, 0x66, 0x54, 0x66, 0x66, - 0x5D, 0x21, 0x5D, 0x7E, 0x29, 0x69, 0x49, 0x6D, - 0x4C, 0x7A, 0x5D, 0x20, 0x20, 0x20, 0x51, 0x38, - 0x6D, 0x6D, 0x6D, 0x44, 0x69, 0x78, 0x5B, 0x6D, - 0x6D, 0x6D, 0x6D, 0x6D, 0x38, 0x6D, 0x6D, 0x6D, - 0x38, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x62, 0x27, 0x3C, 0x69, 0x38, 0x71, - 0x54, 0x73, 0x5D, 0x21, 0x40, 0x73, 0x66, 0x73, - 0x21, 0x4C, 0x4C, 0x7A, 0x5D, 0x5D, 0x5D, 0x4C, - 0x66, 0x62, 0x62, 0x27, 0x71, 0x71, 0x71, 0x27, - 0x27, 0x27, 0x71, 0x3D, 0x54, 0x54, 0x54, 0x54, - 0x73, 0x73, 0x3D, 0x57, 0x29, 0x69, 0x30, 0x38, - 0x73, 0x73, 0x20, 0x20, 0x20, 0x2D, 0x6D, 0x6D, - 0x38, 0x6D, 0x6D, 0x6D, 0x38, 0x38, 0x6D, 0x6D, - 0x6D, 0x38, 0x6D, 0x6D, 0x38, 0x6D, 0x6D, 0x6D, - 0x6D, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x27, 0x5B, 0x53, 0x6D, 0x73, - 0x54, 0x54, 0x73, 0x73, 0x3D, 0x27, 0x27, 0x71, - 0x66, 0x40, 0x73, 0x40, 0x66, 0x73, 0x40, 0x21, - 0x62, 0x30, 0x6F, 0x62, 0x27, 0x71, 0x3D, 0x71, - 0x27, 0x71, 0x71, 0x71, 0x3D, 0x3D, 0x3D, 0x3D, - 0x3D, 0x27, 0x58, 0x46, 0x69, 0x30, 0x6F, 0x6D, - 0x3D, 0x71, 0x20, 0x20, 0x20, 0x44, 0x6D, 0x6D, - 0x6D, 0x6D, 0x6D, 0x38, 0x6D, 0x6D, 0x38, 0x6D, - 0x38, 0x6D, 0x38, 0x6D, 0x6D, 0x6D, 0x38, 0x6D, - 0x6D, 0x6D, 0x2F, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x70, 0x53, 0x38, 0x27, - 0x3D, 0x3D, 0x3D, 0x71, 0x3B, 0x30, 0x62, 0x3D, - 0x66, 0x54, 0x3D, 0x71, 0x3D, 0x3D, 0x66, 0x66, - 0x3B, 0x69, 0x69, 0x6F, 0x62, 0x27, 0x3D, 0x71, - 0x27, 0x27, 0x27, 0x27, 0x71, 0x3D, 0x3D, 0x3D, - 0x3D, 0x27, 0x3B, 0x46, 0x62, 0x3B, 0x49, 0x38, - 0x3D, 0x20, 0x20, 0x20, 0x34, 0x44, 0x6D, 0x6D, - 0x38, 0x6D, 0x6D, 0x38, 0x6D, 0x6D, 0x38, 0x6D, - 0x6D, 0x6D, 0x6D, 0x38, 0x6D, 0x6D, 0x38, 0x6D, - 0x38, 0x6D, 0x26, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x21, 0x49, 0x79, 0x51, 0x5D, - 0x3D, 0x3D, 0x71, 0x27, 0x62, 0x62, 0x3D, 0x73, - 0x40, 0x66, 0x3D, 0x3D, 0x54, 0x3D, 0x3D, 0x71, - 0x78, 0x49, 0x69, 0x30, 0x3B, 0x62, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x71, 0x71, 0x71, 0x3D, 0x3D, - 0x3D, 0x27, 0x3D, 0x33, 0x49, 0x69, 0x62, 0x44, - 0x20, 0x20, 0x20, 0x20, 0x2D, 0x32, 0x6D, 0x38, - 0x6D, 0x6D, 0x6D, 0x6D, 0x38, 0x38, 0x6D, 0x6D, - 0x6D, 0x6D, 0x38, 0x6D, 0x38, 0x6D, 0x38, 0x51, - 0x26, 0x61, 0x44, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x6A, 0x70, 0x6F, 0x6D, 0x21, - 0x71, 0x3D, 0x3D, 0x71, 0x3D, 0x66, 0x40, 0x5D, - 0x40, 0x73, 0x66, 0x73, 0x66, 0x54, 0x3D, 0x71, - 0x70, 0x78, 0x49, 0x30, 0x6F, 0x6F, 0x62, 0x62, - 0x62, 0x27, 0x71, 0x3D, 0x54, 0x54, 0x54, 0x3D, - 0x3D, 0x71, 0x3D, 0x2A, 0x30, 0x2D, 0x3B, 0x26, - 0x38, 0x20, 0x20, 0x20, 0x2D, 0x62, 0x32, 0x26, - 0x38, 0x6D, 0x6D, 0x38, 0x5B, 0x38, 0x6D, 0x38, - 0x6D, 0x6D, 0x6D, 0x26, 0x32, 0x29, 0x29, 0x29, - 0x53, 0x29, 0x61, 0x6D, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x44, 0x3D, 0x3C, 0x62, 0x79, 0x7A, - 0x54, 0x54, 0x71, 0x27, 0x3D, 0x66, 0x73, 0x40, - 0x73, 0x66, 0x66, 0x73, 0x2D, 0x54, 0x71, 0x71, - 0x4A, 0x3B, 0x62, 0x3B, 0x3B, 0x3B, 0x3B, 0x27, - 0x27, 0x27, 0x71, 0x3D, 0x2D, 0x73, 0x73, 0x54, - 0x3D, 0x71, 0x71, 0x33, 0x30, 0x71, 0x5D, 0x38, - 0x6D, 0x6D, 0x38, 0x38, 0x38, 0x6D, 0x6D, 0x6D, - 0x6D, 0x6D, 0x44, 0x38, 0x6F, 0x7A, 0x64, 0x64, - 0x23, 0x23, 0x56, 0x23, 0x23, 0x7B, 0x47, 0x64, - 0x54, 0x29, 0x44, 0x38, 0x38, 0x6D, 0x38, 0x38, - 0x6D, 0x38, 0x38, 0x6D, 0x53, 0x49, 0x6D, 0x34, - 0x73, 0x54, 0x3D, 0x71, 0x71, 0x3D, 0x54, 0x3D, - 0x3D, 0x54, 0x66, 0x66, 0x66, 0x54, 0x54, 0x3D, - 0x49, 0x3D, 0x54, 0x54, 0x3D, 0x71, 0x27, 0x27, - 0x71, 0x71, 0x71, 0x3D, 0x54, 0x54, 0x54, 0x3D, - 0x3D, 0x71, 0x71, 0x33, 0x29, 0x3D, 0x3D, 0x6D, - 0x38, 0x6D, 0x6D, 0x38, 0x6D, 0x38, 0x38, 0x6D, - 0x38, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x38, 0x6D, - 0x38, 0x6D, 0x38, 0x6D, 0x6D, 0x38, 0x6D, 0x6D, - 0x38, 0x6D, 0x6D, 0x6D, 0x38, 0x38, 0x6D, 0x44, - 0x6D, 0x38, 0x38, 0x6D, 0x69, 0x78, 0x61, 0x73, - 0x54, 0x3D, 0x3D, 0x71, 0x71, 0x3D, 0x3D, 0x3D, - 0x71, 0x3D, 0x3D, 0x3D, 0x3D, 0x54, 0x3D, 0x71, - 0x3B, 0x66, 0x73, 0x73, 0x2D, 0x2D, 0x54, 0x3D, - 0x71, 0x71, 0x3D, 0x71, 0x71, 0x71, 0x27, 0x27, - 0x27, 0x71, 0x71, 0x33, 0x3B, 0x62, 0x27, 0x3D, - 0x27, 0x3B, 0x3B, 0x27, 0x62, 0x3B, 0x3D, 0x3D, - 0x30, 0x27, 0x62, 0x62, 0x62, 0x71, 0x30, 0x27, - 0x3B, 0x6F, 0x30, 0x30, 0x3B, 0x30, 0x3B, 0x62, - 0x3B, 0x69, 0x49, 0x30, 0x29, 0x29, 0x29, 0x29, - 0x49, 0x29, 0x30, 0x29, 0x29, 0x29, 0x51, 0x21, - 0x27, 0x27, 0x71, 0x71, 0x71, 0x3D, 0x3D, 0x71, - 0x71, 0x71, 0x71, 0x3D, 0x71, 0x71, 0x71, 0x62, - 0x3B, 0x54, 0x66, 0x66, 0x66, 0x54, 0x3D, 0x54, - 0x66, 0x54, 0x3D, 0x27, 0x62, 0x62, 0x3B, 0x3B, - 0x3B, 0x62, 0x27, 0x33, 0x30, 0x6F, 0x71, 0x3B, - 0x62, 0x3B, 0x62, 0x27, 0x27, 0x30, 0x62, 0x27, - 0x62, 0x27, 0x3B, 0x49, 0x3B, 0x30, 0x29, 0x3B, - 0x3B, 0x30, 0x30, 0x69, 0x30, 0x6F, 0x30, 0x49, - 0x3B, 0x6F, 0x49, 0x29, 0x49, 0x49, 0x3C, 0x29, - 0x49, 0x49, 0x69, 0x70, 0x70, 0x29, 0x51, 0x27, - 0x3B, 0x3B, 0x3B, 0x62, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x3D, 0x3D, 0x3D, 0x71, 0x27, 0x27, 0x27, - 0x69, 0x71, 0x3D, 0x54, 0x71, 0x62, 0x27, 0x71, - 0x54, 0x2D, 0x3D, 0x27, 0x62, 0x3B, 0x3B, 0x3B, - 0x3B, 0x62, 0x62, 0x33, 0x27, 0x27, 0x3B, 0x71, - 0x27, 0x71, 0x27, 0x62, 0x71, 0x6F, 0x27, 0x71, - 0x3B, 0x62, 0x62, 0x6F, 0x62, 0x6F, 0x6F, 0x6F, - 0x6F, 0x69, 0x62, 0x49, 0x69, 0x49, 0x6F, 0x62, - 0x62, 0x49, 0x69, 0x71, 0x6F, 0x6F, 0x6F, 0x69, - 0x69, 0x69, 0x30, 0x29, 0x30, 0x69, 0x44, 0x7B, - 0x3B, 0x3B, 0x3B, 0x62, 0x62, 0x62, 0x62, 0x62, - 0x27, 0x3D, 0x3D, 0x54, 0x71, 0x3D, 0x3D, 0x54, - 0x69, 0x71, 0x3D, 0x71, 0x62, 0x3B, 0x3B, 0x27, - 0x54, 0x54, 0x3D, 0x71, 0x71, 0x71, 0x27, 0x62, - 0x62, 0x62, 0x27, 0x2A, 0x3D, 0x71, 0x3D, 0x71, - 0x3D, 0x62, 0x27, 0x30, 0x30, 0x62, 0x3B, 0x71, - 0x3B, 0x30, 0x30, 0x49, 0x29, 0x30, 0x30, 0x30, - 0x27, 0x49, 0x62, 0x30, 0x6F, 0x30, 0x3B, 0x3B, - 0x6F, 0x3B, 0x49, 0x30, 0x30, 0x3C, 0x3B, 0x49, - 0x30, 0x69, 0x6F, 0x78, 0x30, 0x62, 0x44, 0x7B, - 0x27, 0x62, 0x62, 0x62, 0x71, 0x71, 0x3D, 0x54, - 0x3D, 0x73, 0x66, 0x73, 0x66, 0x73, 0x73, 0x66, - 0x62, 0x66, 0x66, 0x3D, 0x27, 0x3B, 0x3B, 0x71, - 0x3D, 0x3D, 0x3D, 0x54, 0x54, 0x71, 0x3D, 0x3D, - 0x54, 0x73, 0x5D, 0x33, 0x62, 0x27, 0x54, 0x27, - 0x71, 0x3B, 0x71, 0x71, 0x62, 0x3B, 0x54, 0x3B, - 0x71, 0x6F, 0x62, 0x62, 0x62, 0x62, 0x69, 0x71, - 0x71, 0x6F, 0x3B, 0x71, 0x30, 0x62, 0x71, 0x6F, - 0x3B, 0x62, 0x6F, 0x62, 0x6F, 0x69, 0x6F, 0x69, - 0x6F, 0x30, 0x49, 0x3C, 0x69, 0x3B, 0x79, 0x21, - 0x20, 0x3D, 0x54, 0x73, 0x5D, 0x5D, 0x5D, 0x40, - 0x40, 0x73, 0x73, 0x73, 0x2D, 0x66, 0x66, 0x3D, - 0x3D, 0x54, 0x54, 0x3D, 0x71, 0x27, 0x62, 0x27, - 0x71, 0x71, 0x3D, 0x54, 0x54, 0x3D, 0x3D, 0x54, - 0x5D, 0x6A, 0x77, 0x46, 0x71, 0x2D, 0x54, 0x27, - 0x54, 0x3B, 0x3B, 0x3B, 0x6F, 0x3B, 0x71, 0x27, - 0x3B, 0x27, 0x3B, 0x3B, 0x27, 0x27, 0x3B, 0x3B, - 0x3B, 0x62, 0x3D, 0x62, 0x3D, 0x27, 0x3B, 0x54, - 0x3B, 0x2D, 0x49, 0x3B, 0x3B, 0x29, 0x49, 0x3C, - 0x53, 0x69, 0x53, 0x3C, 0x78, 0x3D, 0x78, 0x5D, - 0x20, 0x66, 0x5D, 0x6A, 0x47, 0x77, 0x4C, 0x5D, - 0x66, 0x3D, 0x3D, 0x66, 0x73, 0x66, 0x3D, 0x62, - 0x62, 0x62, 0x71, 0x3D, 0x71, 0x27, 0x27, 0x27, - 0x71, 0x71, 0x71, 0x3D, 0x3D, 0x71, 0x71, 0x73, - 0x7A, 0x77, 0x47, 0x46, 0x27, 0x73, 0x27, 0x54, - 0x3D, 0x71, 0x62, 0x6F, 0x27, 0x71, 0x27, 0x71, - 0x71, 0x71, 0x62, 0x62, 0x71, 0x71, 0x71, 0x62, - 0x62, 0x3B, 0x69, 0x49, 0x62, 0x6F, 0x62, 0x3D, - 0x6F, 0x6F, 0x62, 0x78, 0x2A, 0x20, 0x6B, 0x20, - 0x2A, 0x20, 0x20, 0x2A, 0x3B, 0x6F, 0x3C, 0x4C, - 0x20, 0x20, 0x7A, 0x77, 0x47, 0x6A, 0x5D, 0x54, - 0x27, 0x6F, 0x3B, 0x54, 0x40, 0x2D, 0x71, 0x6F, - 0x49, 0x6F, 0x27, 0x3D, 0x71, 0x62, 0x62, 0x3B, - 0x62, 0x27, 0x71, 0x3D, 0x3D, 0x71, 0x71, 0x66, - 0x7A, 0x34, 0x6A, 0x46, 0x27, 0x5D, 0x3D, 0x54, - 0x3D, 0x3D, 0x3D, 0x62, 0x27, 0x71, 0x27, 0x3D, - 0x3B, 0x3D, 0x30, 0x27, 0x27, 0x3B, 0x27, 0x3D, - 0x20, 0x20, 0x2A, 0x46, 0x46, 0x2A, 0x35, 0x2A, - 0x46, 0x46, 0x23, 0x2A, 0x7A, 0x4F, 0x4F, 0x6B, - 0x6B, 0x4F, 0x4F, 0x62, 0x3B, 0x62, 0x78, 0x20, - 0x20, 0x20, 0x7A, 0x34, 0x34, 0x40, 0x54, 0x71, - 0x3B, 0x69, 0x6F, 0x40, 0x7A, 0x66, 0x62, 0x69, - 0x3C, 0x3B, 0x71, 0x3D, 0x27, 0x3B, 0x6F, 0x27, - 0x71, 0x3D, 0x3D, 0x66, 0x2D, 0x3D, 0x62, 0x27, - 0x2D, 0x4C, 0x7A, 0x33, 0x27, 0x3D, 0x54, 0x2D, - 0x54, 0x62, 0x54, 0x27, 0x54, 0x27, 0x54, 0x71, - 0x62, 0x71, 0x71, 0x62, 0x62, 0x54, 0x71, 0x62, - 0x7A, 0x6B, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x35, 0x57, - 0x6B, 0x20, 0x20, 0x30, 0x6F, 0x27, 0x29, 0x20, - 0x20, 0x20, 0x66, 0x4C, 0x7A, 0x54, 0x62, 0x3B, - 0x6F, 0x30, 0x71, 0x7A, 0x4C, 0x3D, 0x69, 0x78, - 0x53, 0x3D, 0x73, 0x2D, 0x71, 0x62, 0x3B, 0x71, - 0x3D, 0x2D, 0x2D, 0x40, 0x73, 0x3D, 0x27, 0x71, - 0x40, 0x6A, 0x20, 0x20, 0x71, 0x2D, 0x62, 0x2D, - 0x3D, 0x3B, 0x71, 0x27, 0x54, 0x27, 0x3D, 0x3D, - 0x27, 0x2D, 0x27, 0x3D, 0x3B, 0x2D, 0x3D, 0x3B, - 0x34, 0x2D, 0x77, 0x6A, 0x77, 0x2D, 0x6A, 0x7A, - 0x5D, 0x6A, 0x5D, 0x54, 0x71, 0x44, 0x6D, 0x6D, - 0x6D, 0x38, 0x26, 0x30, 0x54, 0x62, 0x20, 0x20, - 0x20, 0x20, 0x40, 0x6A, 0x4C, 0x54, 0x6F, 0x69, - 0x30, 0x62, 0x40, 0x6A, 0x21, 0x62, 0x49, 0x29, - 0x71, 0x4C, 0x34, 0x5D, 0x71, 0x3B, 0x27, 0x71, - 0x54, 0x54, 0x40, 0x40, 0x73, 0x3D, 0x3D, 0x40, - 0x6A, 0x20, 0x20, 0x33, 0x2D, 0x73, 0x40, 0x4E, - 0x77, 0x7A, 0x3D, 0x54, 0x2D, 0x54, 0x71, 0x54, - 0x62, 0x71, 0x71, 0x62, 0x71, 0x71, 0x71, 0x71, - 0x2D, 0x3B, 0x27, 0x3B, 0x49, 0x6F, 0x3B, 0x3B, - 0x27, 0x3B, 0x3B, 0x30, 0x49, 0x53, 0x6F, 0x6F, - 0x69, 0x3B, 0x6F, 0x53, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x6A, 0x77, 0x21, 0x27, 0x30, 0x30, - 0x6F, 0x71, 0x66, 0x73, 0x3D, 0x30, 0x49, 0x30, - 0x5D, 0x34, 0x34, 0x40, 0x27, 0x6F, 0x62, 0x3D, - 0x54, 0x66, 0x40, 0x73, 0x2D, 0x66, 0x2D, 0x5D, - 0x7A, 0x20, 0x20, 0x56, 0x20, 0x54, 0x5D, 0x5E, - 0x33, 0x71, 0x3D, 0x62, 0x27, 0x3B, 0x27, 0x30, - 0x3B, 0x3D, 0x27, 0x3D, 0x3D, 0x3D, 0x3B, 0x73, - 0x54, 0x62, 0x62, 0x62, 0x30, 0x6F, 0x71, 0x6F, - 0x6F, 0x6F, 0x6F, 0x71, 0x62, 0x3B, 0x3B, 0x49, - 0x3B, 0x3B, 0x3B, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x7A, 0x21, 0x54, 0x3B, 0x69, 0x69, - 0x30, 0x62, 0x27, 0x71, 0x62, 0x30, 0x30, 0x6F, - 0x4C, 0x77, 0x6A, 0x66, 0x62, 0x6F, 0x62, 0x71, - 0x54, 0x66, 0x2D, 0x73, 0x66, 0x54, 0x73, 0x73, - 0x73, 0x20, 0x20, 0x7E, 0x20, 0x3D, 0x27, 0x6B, - 0x35, 0x21, 0x54, 0x3D, 0x71, 0x71, 0x54, 0x62, - 0x62, 0x71, 0x71, 0x69, 0x71, 0x54, 0x54, 0x30, - 0x27, 0x3B, 0x3B, 0x3B, 0x6F, 0x30, 0x3B, 0x30, - 0x3B, 0x30, 0x30, 0x27, 0x30, 0x6F, 0x62, 0x69, - 0x6F, 0x6F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x73, 0x3D, 0x62, 0x6F, 0x69, 0x69, - 0x6F, 0x71, 0x3D, 0x71, 0x27, 0x62, 0x62, 0x27, - 0x4C, 0x4C, 0x5D, 0x71, 0x30, 0x69, 0x3B, 0x71, - 0x54, 0x66, 0x73, 0x66, 0x66, 0x66, 0x54, 0x3D, - 0x71, 0x20, 0x20, 0x7E, 0x20, 0x20, 0x21, 0x62, - 0x69, 0x27, 0x5D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3B, - 0x3D, 0x3D, 0x27, 0x3B, 0x27, 0x3D, 0x71, 0x6F, - 0x54, 0x62, 0x6F, 0x30, 0x6F, 0x6F, 0x62, 0x6F, - 0x62, 0x62, 0x62, 0x62, 0x3B, 0x3B, 0x27, 0x3B, - 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x27, 0x3B, 0x6F, 0x30, 0x6F, 0x6F, - 0x62, 0x3D, 0x66, 0x54, 0x54, 0x71, 0x71, 0x71, - 0x5D, 0x5D, 0x54, 0x3B, 0x69, 0x69, 0x3B, 0x71, - 0x54, 0x40, 0x73, 0x66, 0x54, 0x3D, 0x71, 0x62, - 0x6F, 0x20, 0x20, 0x39, 0x20, 0x20, 0x20, 0x2D, - 0x2D, 0x73, 0x40, 0x54, 0x54, 0x54, 0x71, 0x73, - 0x54, 0x73, 0x71, 0x54, 0x54, 0x54, 0x27, 0x3B, - 0x3D, 0x3B, 0x27, 0x62, 0x3B, 0x3B, 0x3B, 0x27, - 0x27, 0x3B, 0x3B, 0x27, 0x62, 0x62, 0x71, 0x62, - 0x71, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x3B, 0x6F, 0x30, 0x6F, 0x3B, 0x27, - 0x3D, 0x66, 0x66, 0x54, 0x71, 0x71, 0x27, 0x71, - 0x66, 0x73, 0x54, 0x27, 0x6F, 0x6F, 0x27, 0x54, - 0x40, 0x21, 0x5D, 0x73, 0x3D, 0x27, 0x62, 0x3B, - 0x3B, 0x42, 0x74, 0x52, 0x52, 0x6E, 0x20, 0x20, - 0x40, 0x54, 0x3D, 0x3D, 0x3D, 0x40, 0x27, 0x3B, - 0x30, 0x40, 0x27, 0x27, 0x27, 0x71, 0x54, 0x6F, - 0x5D, 0x6F, 0x3B, 0x71, 0x71, 0x6F, 0x73, 0x6F, - 0x54, 0x6F, 0x54, 0x27, 0x39, 0x6E, 0x6E, 0x3B, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x3B, 0x3B, 0x3B, 0x62, 0x27, 0x71, - 0x3D, 0x3D, 0x3D, 0x27, 0x62, 0x27, 0x62, 0x27, - 0x3D, 0x40, 0x54, 0x27, 0x3B, 0x3B, 0x27, 0x73, - 0x7A, 0x21, 0x40, 0x54, 0x71, 0x62, 0x6F, 0x6F, - 0x3B, 0x67, 0x3A, 0x3A, 0x5A, 0x48, 0x3A, 0x20, - 0x20, 0x53, 0x6D, 0x38, 0x38, 0x6D, 0x38, 0x38, - 0x6D, 0x38, 0x79, 0x6D, 0x38, 0x6D, 0x6D, 0x6D, - 0x6D, 0x6D, 0x38, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, - 0x6D, 0x6D, 0x6D, 0x67, 0x52, 0x41, 0x22, 0x2F, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4F, 0x6B, - 0x43, 0x3A, 0x3B, 0x27, 0x27, 0x62, 0x27, 0x71, - 0x71, 0x71, 0x71, 0x3D, 0x71, 0x71, 0x3D, 0x3D, - 0x27, 0x40, 0x54, 0x27, 0x30, 0x30, 0x27, 0x40, - 0x7A, 0x5D, 0x54, 0x71, 0x3B, 0x30, 0x30, 0x3B, - 0x42, 0x67, 0x67, 0x3E, 0x3A, 0x48, 0x22, 0x5A, - 0x4F, 0x20, 0x2D, 0x6D, 0x6D, 0x6D, 0x6D, 0x38, - 0x6D, 0x6D, 0x26, 0x6D, 0x38, 0x6D, 0x38, 0x6D, - 0x6D, 0x6D, 0x38, 0x6D, 0x38, 0x38, 0x6D, 0x38, - 0x6D, 0x38, 0x38, 0x3E, 0x55, 0x6C, 0x22, 0x73, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4D, - 0x5A, 0x45, 0x36, 0x3D, 0x71, 0x27, 0x27, 0x71, - 0x54, 0x66, 0x73, 0x40, 0x73, 0x66, 0x2D, 0x66, - 0x30, 0x66, 0x71, 0x30, 0x69, 0x6F, 0x3D, 0x21, - 0x7A, 0x66, 0x3D, 0x62, 0x3B, 0x6F, 0x3B, 0x28, - 0x67, 0x52, 0x5A, 0x74, 0x41, 0x3A, 0x74, 0x3A, - 0x52, 0x20, 0x20, 0x7E, 0x38, 0x6D, 0x6D, 0x6D, - 0x6D, 0x38, 0x38, 0x6D, 0x6D, 0x6D, 0x6D, 0x38, - 0x38, 0x6D, 0x6D, 0x38, 0x6D, 0x6D, 0x38, 0x6D, - 0x6D, 0x6D, 0x6D, 0x2F, 0x52, 0x22, 0x28, 0x50, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2E, - 0x41, 0x5A, 0x5A, 0x66, 0x54, 0x3D, 0x54, 0x66, - 0x73, 0x40, 0x40, 0x40, 0x73, 0x66, 0x66, 0x3D, - 0x69, 0x27, 0x3B, 0x30, 0x30, 0x62, 0x73, 0x7A, - 0x21, 0x3D, 0x3B, 0x6F, 0x6F, 0x62, 0x2F, 0x75, - 0x28, 0x55, 0x22, 0x3A, 0x31, 0x3A, 0x41, 0x3A, - 0x5A, 0x2E, 0x20, 0x4F, 0x20, 0x6D, 0x6D, 0x6D, - 0x6D, 0x6D, 0x38, 0x6D, 0x38, 0x6D, 0x6D, 0x6D, - 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x38, - 0x6D, 0x6D, 0x78, 0x2F, 0x31, 0x55, 0x2E, 0x3F, - 0x50, 0x20, 0x20, 0x20, 0x20, 0x4D, 0x24, 0x52, - 0x22, 0x22, 0x31, 0x2D, 0x66, 0x54, 0x66, 0x66, - 0x66, 0x66, 0x54, 0x71, 0x27, 0x27, 0x27, 0x62, - 0x30, 0x3B, 0x3B, 0x6F, 0x3B, 0x3D, 0x40, 0x21, - 0x73, 0x71, 0x5F, 0x6E, 0x2E, 0x2E, 0x67, 0x52, - 0x52, 0x31, 0x7D, 0x48, 0x3A, 0x3A, 0x74, 0x74, - 0x55, 0x39, 0x20, 0x20, 0x20, 0x20, 0x38, 0x6D, - 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, - 0x38, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, - 0x6D, 0x29, 0x29, 0x2F, 0x55, 0x52, 0x2E, 0x24, - 0x72, 0x68, 0x25, 0x76, 0x68, 0x3F, 0x2E, 0x39, - 0x52, 0x74, 0x3A, 0x73, 0x66, 0x66, 0x54, 0x54, - 0x27, 0x3B, 0x6F, 0x6F, 0x6F, 0x6F, 0x3B, 0x62, - 0x3B, 0x62, 0x27, 0x71, 0x54, 0x40, 0x21, 0x40, - 0x3D, 0x2E, 0x48, 0x6E, 0x55, 0x55, 0x6E, 0x55, - 0x3A, 0x74, 0x3E, 0x55, 0x74, 0x5A, 0x22, 0x3A, - 0x3A, 0x36, 0x2E, 0x20, 0x20, 0x20, 0x20, 0x38, - 0x6D, 0x6D, 0x38, 0x6D, 0x38, 0x6D, 0x6D, 0x6D, - 0x38, 0x6D, 0x38, 0x38, 0x6D, 0x38, 0x6D, 0x38, - 0x6D, 0x32, 0x78, 0x62, 0x3E, 0x52, 0x28, 0x42, - 0x65, 0x24, 0x5F, 0x24, 0x5F, 0x2E, 0x55, 0x22, - 0x3A, 0x41, 0x74, 0x31, 0x54, 0x73, 0x66, 0x54, - 0x27, 0x6F, 0x30, 0x69, 0x30, 0x6F, 0x62, 0x62, - 0x62, 0x71, 0x3D, 0x54, 0x73, 0x5D, 0x5D, 0x66, - 0x71, 0x2E, 0x22, 0x31, 0x55, 0x3A, 0x31, 0x5A, - 0x3A, 0x3A, 0x74, 0x5A, 0x74, 0x3E, 0x31, 0x3A, - 0x55, 0x22, 0x22, 0x35, 0x20, 0x20, 0x20, 0x20, - 0x34, 0x38, 0x6D, 0x6D, 0x6D, 0x38, 0x38, 0x6D, - 0x6D, 0x38, 0x6D, 0x6D, 0x38, 0x6D, 0x6D, 0x6D, - 0x38, 0x79, 0x29, 0x2F, 0x42, 0x52, 0x28, 0x48, - 0x48, 0x2E, 0x2E, 0x48, 0x3E, 0x52, 0x3A, 0x74, - 0x7D, 0x3A, 0x3A, 0x3E, 0x40, 0x40, 0x40, 0x54, - 0x27, 0x6F, 0x30, 0x6F, 0x62, 0x71, 0x71, 0x71, - 0x62, 0x3D, 0x66, 0x73, 0x40, 0x5D, 0x73, 0x71, - 0x62, 0x28, 0x55, 0x5A, 0x5A, 0x55, 0x3A, 0x41, - 0x55, 0x3A, 0x3A, 0x31, 0x55, 0x55, 0x5A, 0x74, - 0x3A, 0x31, 0x22, 0x48, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x6D, 0x38, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, - 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x38, 0x6D, 0x6D, - 0x6D, 0x6D, 0x29, 0x2F, 0x24, 0x28, 0x28, 0x52, - 0x52, 0x48, 0x48, 0x28, 0x39, 0x52, 0x74, 0x48, - 0x74, 0x55, 0x22, 0x41, 0x5A, 0x40, 0x54, 0x27, - 0x3B, 0x6F, 0x3B, 0x71, 0x54, 0x66, 0x66, 0x3D, - 0x62, 0x54, 0x40, 0x21, 0x7A, 0x40, 0x3D, 0x62, - 0x62, 0x48, 0x52, 0x55, 0x6C, 0x5A, 0x31, 0x31, - 0x5A, 0x41, 0x31, 0x3A, 0x3A, 0x7D, 0x31, 0x3A, - 0x41, 0x41, 0x22, 0x36, 0x42, 0x20, 0x20, 0x20, - 0x20, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x38, - 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x38, - 0x6D, 0x6D, 0x29, 0x25, 0x59, 0x2E, 0x39, 0x39, - 0x55, 0x39, 0x39, 0x39, 0x31, 0x22, 0x3A, 0x74, - 0x5A, 0x3E, 0x6C, 0x3E, 0x31, 0x3E, 0x3A, 0x69, - 0x49, 0x49, 0x3B, 0x71, 0x66, 0x73, 0x66, 0x54, - 0x27, 0x66, 0x5D, 0x7A, 0x21, 0x73, 0x71, 0x62, - 0x27, 0x75, 0x39, 0x41, 0x3A, 0x36, 0x7D, 0x74, - 0x74, 0x41, 0x55, 0x55, 0x3A, 0x3A, 0x3A, 0x3A, - 0x31, 0x31, 0x5A, 0x22, 0x52, 0x20, 0x20, 0x20, - 0x26, 0x38, 0x6D, 0x38, 0x6D, 0x38, 0x6D, 0x38, - 0x6D, 0x38, 0x38, 0x6D, 0x6D, 0x6D, 0x6D, 0x38, - 0x38, 0x6D, 0x20, 0x60, 0x24, 0x48, 0x39, 0x3A, - 0x55, 0x55, 0x31, 0x55, 0x41, 0x74, 0x41, 0x22, - 0x7D, 0x3A, 0x22, 0x3E, 0x41, 0x5A, 0x3A, 0x74, - 0x78, 0x30, 0x27, 0x54, 0x40, 0x73, 0x54, 0x3D, - 0x71, 0x54, 0x5D, 0x7A, 0x21, 0x66, 0x62, 0x3B, - 0x71, 0x5F, 0x52, 0x3E, 0x41, 0x5A, 0x5A, 0x22, - 0x3E, 0x3A, 0x74, 0x3E, 0x55, 0x55, 0x3A, 0x31, - 0x41, 0x3A, 0x48, 0x55, 0x41, 0x42, 0x6D, 0x38, - 0x38, 0x6D, 0x6D, 0x6D, 0x38, 0x6D, 0x6D, 0x6D, - 0x38, 0x6D, 0x6D, 0x38, 0x6D, 0x38, 0x6D, 0x6D, - 0x6D, 0x20, 0x20, 0x25, 0x24, 0x28, 0x52, 0x3A, - 0x5A, 0x5A, 0x5A, 0x5A, 0x74, 0x74, 0x7D, 0x74, - 0x3A, 0x74, 0x3A, 0x41, 0x7D, 0x41, 0x3A, 0x3A, - 0x69, 0x3D, 0x21, 0x4C, 0x4C, 0x5D, 0x66, 0x54, - 0x66, 0x73, 0x21, 0x6A, 0x21, 0x3D, 0x3B, 0x6F, - 0x71, 0x75, 0x48, 0x31, 0x5A, 0x3A, 0x3E, 0x48, - 0x74, 0x7D, 0x3A, 0x7D, 0x3A, 0x3A, 0x55, 0x74, - 0x5A, 0x3A, 0x41, 0x55, 0x22, 0x22, 0x3F, 0x6D, - 0x6D, 0x38, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, - 0x6D, 0x6D, 0x6D, 0x38, 0x6D, 0x6D, 0x6D, 0x38, - 0x20, 0x20, 0x20, 0x60, 0x42, 0x28, 0x39, 0x3A, - 0x3A, 0x31, 0x41, 0x3A, 0x22, 0x55, 0x74, 0x55, - 0x74, 0x74, 0x74, 0x3A, 0x3A, 0x74, 0x3A, 0x67, - 0x54, 0x7A, 0x34, 0x77, 0x6A, 0x21, 0x66, 0x66, - 0x7A, 0x21, 0x21, 0x4C, 0x21, 0x3D, 0x3B, 0x62, - 0x66, 0x67, 0x28, 0x55, 0x41, 0x31, 0x55, 0x3A, - 0x74, 0x41, 0x31, 0x3A, 0x3A, 0x41, 0x3A, 0x36, - 0x5A, 0x5A, 0x31, 0x31, 0x39, 0x22, 0x24, 0x43, - 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x38, 0x6D, 0x6D, - 0x6D, 0x38, 0x6D, 0x6D, 0x6D, 0x38, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x60, 0x24, 0x63, 0x39, 0x55, - 0x31, 0x5A, 0x3A, 0x74, 0x3A, 0x31, 0x3A, 0x31, - 0x5A, 0x48, 0x3A, 0x7D, 0x48, 0x41, 0x31, 0x3E, - 0x6A, 0x64, 0x47, 0x4C, 0x5D, 0x54, 0x71, 0x71, - 0x6A, 0x5D, 0x5D, 0x21, 0x5D, 0x3D, 0x3B, 0x62, - 0x66, 0x42, 0x39, 0x3A, 0x41, 0x3A, 0x31, 0x3A, - 0x7D, 0x3A, 0x74, 0x41, 0x31, 0x31, 0x3E, 0x41, - 0x5A, 0x41, 0x3A, 0x31, 0x39, 0x52, 0x48, 0x25, - 0x62, 0x6D, 0x38, 0x38, 0x6D, 0x38, 0x6D, 0x6D, - 0x6D, 0x6D, 0x6D, 0x6D, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x4D, 0x43, 0x5F, 0x28, 0x52, 0x3E, - 0x22, 0x31, 0x3A, 0x3A, 0x55, 0x3A, 0x3E, 0x31, - 0x74, 0x67, 0x3E, 0x3A, 0x3E, 0x67, 0x54, 0x34, - 0x2B, 0x2B, 0x34, 0x21, 0x66, 0x71, 0x62, 0x62, - 0x3D, 0x3D, 0x54, 0x5D, 0x40, 0x27, 0x6F, 0x3B, - 0x67, 0x48, 0x48, 0x39, 0x52, 0x7D, 0x7D, 0x22, - 0x74, 0x3A, 0x5A, 0x5A, 0x3A, 0x55, 0x31, 0x3A, - 0x41, 0x7D, 0x3A, 0x22, 0x55, 0x48, 0x42, 0x76, - 0x4B, 0x20, 0x37, 0x6D, 0x6D, 0x6D, 0x38, 0x78, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x4D, 0x76, 0x42, 0x48, 0x55, 0x74, - 0x41, 0x6C, 0x48, 0x31, 0x31, 0x3A, 0x5A, 0x74, - 0x31, 0x6C, 0x22, 0x3E, 0x67, 0x62, 0x7A, 0x64, - 0x7B, 0x77, 0x5D, 0x54, 0x71, 0x62, 0x62, 0x3B, - 0x53, 0x62, 0x71, 0x73, 0x73, 0x27, 0x6F, 0x3B, - 0x67, 0x2E, 0x5F, 0x48, 0x48, 0x52, 0x52, 0x52, - 0x52, 0x52, 0x31, 0x41, 0x74, 0x41, 0x74, 0x31, - 0x74, 0x3A, 0x74, 0x74, 0x48, 0x48, 0x42, 0x72, - 0x4B, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x4B, 0x68, 0x42, 0x28, 0x55, 0x74, - 0x5A, 0x3A, 0x48, 0x55, 0x5A, 0x31, 0x55, 0x55, - 0x39, 0x67, 0x2F, 0x49, 0x69, 0x27, 0x4C, 0x64, - 0x34, 0x5D, 0x66, 0x71, 0x62, 0x6F, 0x6F, 0x6F, - 0x79, 0x27, 0x66, 0x73, 0x66, 0x27, 0x6F, 0x3B, - 0x54, 0x24, 0x5F, 0x59, 0x24, 0x24, 0x42, 0x2E, - 0x48, 0x67, 0x28, 0x39, 0x52, 0x39, 0x31, 0x3E, - 0x55, 0x3A, 0x3A, 0x31, 0x39, 0x48, 0x24, 0x76, - 0x50, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x4B, 0x76, 0x24, 0x42, 0x52, 0x55, - 0x41, 0x31, 0x31, 0x39, 0x52, 0x52, 0x48, 0x67, - 0x72, 0x71, 0x6F, 0x69, 0x58, 0x2D, 0x4C, 0x34, - 0x7A, 0x40, 0x66, 0x54, 0x62, 0x30, 0x6F, 0x3B, - 0x53, 0x7A, 0x7A, 0x73, 0x3D, 0x62, 0x30, 0x6F, - 0x3D, 0x3D, 0x3B, 0x60, 0x2F, 0x76, 0x59, 0x59, - 0x59, 0x24, 0x24, 0x5F, 0x42, 0x2E, 0x28, 0x55, - 0x3A, 0x39, 0x39, 0x48, 0x48, 0x65, 0x68, 0x25, - 0x4B, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x4B, 0x25, 0x72, 0x65, 0x2E, 0x28, - 0x52, 0x28, 0x48, 0x48, 0x2E, 0x24, 0x3F, 0x4B, - 0x71, 0x27, 0x30, 0x30, 0x27, 0x5D, 0x4C, 0x6A, - 0x7A, 0x7A, 0x5D, 0x54, 0x3B, 0x30, 0x6F, 0x71, - 0x27, 0x64, 0x34, 0x40, 0x3D, 0x62, 0x3B, 0x27, - 0x3D, 0x54, 0x71, 0x3B, 0x3B, 0x62, 0x71, 0x4B, - 0x43, 0x43, 0x76, 0x76, 0x72, 0x59, 0x24, 0x24, - 0x42, 0x2E, 0x42, 0x24, 0x2C, 0x76, 0x60, 0x50, - 0x4D, 0x20, 0x20, 0x20, 0x20, 0x62, 0x27, 0x3D, - 0x3D, 0x27, 0x62, 0x62, 0x27, 0x27, 0x62, 0x30, - 0x20, 0x20, 0x4B, 0x25, 0x76, 0x59, 0x24, 0x24, - 0x42, 0x42, 0x42, 0x65, 0x3F, 0x60, 0x6F, 0x62, - 0x27, 0x27, 0x62, 0x3B, 0x3D, 0x5D, 0x7A, 0x4C, - 0x4C, 0x4C, 0x5D, 0x71, 0x30, 0x69, 0x62, 0x54, - 0x7A, 0x2B, 0x34, 0x2D, 0x71, 0x27, 0x58, 0x62, - 0x71, 0x3D, 0x71, 0x6F, 0x30, 0x6F, 0x27, 0x54, - 0x3D, 0x71, 0x66, 0x4B, 0x25, 0x60, 0x76, 0x76, - 0x72, 0x72, 0x3F, 0x76, 0x76, 0x60, 0x50, 0x4B, - 0x20, 0x73, 0x3D, 0x62, 0x3B, 0x27, 0x71, 0x3D, - 0x3D, 0x71, 0x27, 0x62, 0x62, 0x27, 0x62, 0x3B, - 0x30, 0x27, 0x4D, 0x4B, 0x25, 0x76, 0x72, 0x2C, - 0x59, 0x2C, 0x3F, 0x76, 0x25, 0x62, 0x30, 0x3B, - 0x71, 0x3D, 0x71, 0x71, 0x66, 0x5D, 0x5D, 0x21, - 0x21, 0x21, 0x54, 0x30, 0x78, 0x69, 0x27, 0x66, - 0x7A, 0x4C, 0x5D, 0x3D, 0x27, 0x62, 0x62, 0x3B, - 0x62, 0x3D, 0x27, 0x6F, 0x30, 0x3B, 0x71, 0x54, - 0x3D, 0x3D, 0x54, 0x66, 0x66, 0x66, 0x4B, 0x25, - 0x25, 0x25, 0x25, 0x60, 0x25, 0x50, 0x4B, 0x71, - 0x54, 0x54, 0x71, 0x27, 0x3D, 0x54, 0x54, 0x3D, - 0x3D, 0x71, 0x3B, 0x3B, 0x62, 0x3B, 0x62, 0x3B, - 0x27, 0x54, 0x4C, 0x4D, 0x4B, 0x25, 0x76, 0x76, - 0x68, 0x43, 0x25, 0x50, 0x27, 0x30, 0x30, 0x58, - 0x27, 0x54, 0x54, 0x3D, 0x54, 0x54, 0x66, 0x54, - 0x66, 0x71, 0x6F, 0x78, 0x53, 0x69, 0x54, 0x73, - 0x66, 0x66, 0x54, 0x27, 0x27, 0x27, 0x62, 0x3B, - 0x3B, 0x27, 0x27, 0x3B, 0x6F, 0x62, 0x27, 0x54, - 0x66, 0x3D, 0x3D, 0x27, 0x27, 0x27, 0x62, 0x6F, - 0x78, 0x53, 0x78, 0x62, 0x66, 0x73, 0x3D, 0x3D, - 0x66, 0x2D, 0x54, 0x54, 0x73, 0x73, 0x54, 0x71, - 0x71, 0x27, 0x3B, 0x6F, 0x3B, 0x3B, 0x62, 0x3B, - 0x3B, 0x71, 0x73, 0x73, 0x54, 0x71, 0x62, 0x27, - 0x27, 0x58, 0x62, 0x71, 0x71, 0x6F, 0x6F, 0x62, - 0x27, 0x54, 0x66, 0x3D, 0x3D, 0x27, 0x27, 0x62, - 0x62, 0x6F, 0x78, 0x53, 0x78, 0x62, 0x54, 0x66, - 0x71, 0x3D, 0x71, 0x71, 0x62, 0x27, 0x27, 0x62, - 0x62, 0x71, 0x3D, 0x27, 0x27, 0x62, 0x27, 0x3D, - 0x54, 0x3D, 0x27, 0x62, 0x3B, 0x6F, 0x6F, 0x69, - 0x78, 0x78, 0x6F, 0x54, 0x73, 0x66, 0x54, 0x54, - 0x40, 0x5D, 0x40, 0x40, 0x40, 0x66, 0x3D, 0x71, - 0x27, 0x27, 0x3B, 0x30, 0x6F, 0x3B, 0x3B, 0x62, - 0x3B, 0x3B, 0x27, 0x71, 0x71, 0x27, 0x62, 0x62, - 0x62, 0x62, 0x62, 0x71, 0x71, 0x71, 0x62, 0x62, - 0x27, 0x71, 0x54, 0x3D, 0x27, 0x62, 0x3B, 0x6F, - 0x6F, 0x69, 0x49, 0x49, 0x6F, 0x3D, 0x73, 0x66 + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, + 0x22, 0x21, 0x21, 0x21, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x26, 0x26, 0x25, 0x28, 0x23, 0x22, 0x21, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x23, 0x25, 0x2a, 0x2b, 0x2c, 0x2d, 0x2d, + 0x2d, 0x2e, 0x2c, 0x2b, 0x2a, 0x25, 0x28, 0x22, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x24, 0x2a, 0x2c, 0x2f, 0x2c, 0x30, 0x30, 0x24, + 0x25, 0x27, 0x2b, 0x2c, 0x2f, 0x31, 0x32, 0x25, + 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x25, + 0x33, 0x34, 0x35, 0x21, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x21, 0x2b, 0x2f, 0x2c, + 0x30, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, 0x33, + 0x2d, 0x27, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x31, + 0x2d, 0x32, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x37, 0x37, 0x37, 0x37, 0x38, + 0x37, 0x37, 0x39, 0x37, 0x39, 0x38, 0x39, 0x3a, + 0x32, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x23, 0x32, 0x27, 0x21, 0x36, + 0x34, 0x38, 0x38, 0x39, 0x38, 0x37, 0x38, 0x39, + 0x38, 0x37, 0x38, 0x37, 0x37, 0x37, 0x37, 0x37, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x38, 0x37, 0x37, 0x37, 0x37, + 0x38, 0x39, 0x37, 0x37, 0x37, 0x37, 0x38, 0x3b, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x25, 0x2f, 0x3c, 0x32, 0x22, + 0x36, 0x3d, 0x38, 0x37, 0x39, 0x37, 0x38, 0x37, + 0x39, 0x37, 0x38, 0x37, 0x38, 0x37, 0x37, 0x37, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x3d, 0x3e, 0x3a, 0x3e, 0x3e, + 0x3e, 0x3f, 0x3e, 0x3a, 0x3e, 0x3e, 0x40, 0x22, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x26, 0x41, 0x41, 0x35, 0x25, + 0x36, 0x22, 0x42, 0x38, 0x38, 0x37, 0x37, 0x38, + 0x39, 0x37, 0x37, 0x38, 0x37, 0x38, 0x38, 0x3a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x43, 0x3e, 0x44, 0x44, 0x45, + 0x44, 0x40, 0x3a, 0x3f, 0x3a, 0x3f, 0x3b, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x25, 0x2b, 0x30, 0x28, 0x22, + 0x36, 0x36, 0x35, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x37, 0x44, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x34, 0x3e, 0x3a, 0x38, 0x38, + 0x3e, 0x3e, 0x46, 0x3e, 0x46, 0x46, 0x33, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x22, 0x22, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x47, 0x38, 0x37, 0x37, 0x37, + 0x38, 0x37, 0x37, 0x37, 0x38, 0x38, 0x37, 0x48, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x33, 0x37, 0x44, 0x3e, 0x22, + 0x2d, 0x2c, 0x49, 0x43, 0x4a, 0x4b, 0x22, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x49, 0x4c, 0x46, 0x44, 0x46, + 0x4c, 0x38, 0x44, 0x38, 0x38, 0x3e, 0x37, 0x4d, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x34, 0x3e, 0x3e, 0x3a, 0x36, + 0x20, 0x20, 0x20, 0x23, 0x2a, 0x34, 0x36, 0x36, + 0x36, 0x21, 0x22, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x21, 0x23, 0x22, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x28, 0x34, 0x27, 0x22, 0x20, + 0x21, 0x20, 0x20, 0x20, 0x4e, 0x37, 0x38, 0x4f, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x34, 0x44, 0x3a, 0x3e, 0x43, + 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x36, + 0x21, 0x21, 0x24, 0x27, 0x21, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x28, 0x27, 0x22, 0x33, 0x24, 0x36, + 0x36, 0x36, 0x36, 0x22, 0x2f, 0x2a, 0x23, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x50, 0x38, 0x3e, 0x51, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x2c, 0x3a, 0x44, 0x44, 0x52, + 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x36, + 0x30, 0x3b, 0x41, 0x24, 0x24, 0x36, 0x36, 0x36, + 0x23, 0x2f, 0x53, 0x54, 0x55, 0x30, 0x25, 0x21, + 0x36, 0x36, 0x36, 0x36, 0x2f, 0x32, 0x23, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x51, 0x3e, 0x37, 0x42, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x34, 0x44, 0x45, 0x3e, 0x45, + 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x23, + 0x56, 0x4d, 0x57, 0x3b, 0x22, 0x36, 0x36, 0x21, + 0x49, 0x51, 0x4c, 0x45, 0x40, 0x56, 0x23, 0x21, + 0x36, 0x36, 0x36, 0x36, 0x2f, 0x33, 0x28, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x40, 0x44, 0x38, 0x51, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x29, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x2e, 0x44, 0x40, 0x44, 0x42, + 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x2b, + 0x45, 0x57, 0x44, 0x39, 0x35, 0x36, 0x36, 0x26, + 0x4c, 0x58, 0x59, 0x3d, 0x3f, 0x3e, 0x2e, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x31, 0x35, 0x24, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x57, 0x44, 0x3e, 0x48, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x5a, 0x44, 0x45, 0x3e, 0x44, + 0x20, 0x20, 0x20, 0x23, 0x32, 0x34, 0x36, 0x4b, + 0x5b, 0x25, 0x2f, 0x44, 0x3d, 0x22, 0x23, 0x32, + 0x3a, 0x42, 0x21, 0x31, 0x43, 0x46, 0x50, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x31, 0x35, 0x24, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x47, 0x3e, 0x38, 0x50, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x29, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x49, 0x40, 0x40, 0x44, 0x38, + 0x20, 0x20, 0x20, 0x23, 0x2a, 0x2f, 0x21, 0x3b, + 0x4b, 0x21, 0x31, 0x5c, 0x5d, 0x28, 0x30, 0x2b, + 0x3f, 0x4b, 0x36, 0x23, 0x32, 0x42, 0x4d, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x2e, 0x5a, 0x24, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x42, 0x44, 0x44, 0x52, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x29, 0x20, 0x29, 0x20, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x2c, 0x4c, 0x40, 0x4c, 0x37, + 0x20, 0x20, 0x20, 0x23, 0x2a, 0x41, 0x23, 0x3c, + 0x5d, 0x36, 0x28, 0x3b, 0x5e, 0x5f, 0x5f, 0x60, + 0x54, 0x4b, 0x36, 0x36, 0x36, 0x57, 0x57, 0x21, + 0x36, 0x36, 0x36, 0x36, 0x2e, 0x5a, 0x24, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x40, 0x44, 0x3a, 0x5c, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x29, 0x29, 0x29, 0x20, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x2a, 0x44, 0x45, 0x4c, 0x3a, + 0x20, 0x20, 0x20, 0x22, 0x30, 0x43, 0x23, 0x35, + 0x4c, 0x25, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x67, 0x68, 0x69, 0x36, 0x31, 0x39, 0x53, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x31, 0x2c, 0x25, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x52, 0x45, 0x44, 0x54, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x2a, 0x40, 0x4d, 0x4c, 0x38, + 0x20, 0x20, 0x20, 0x22, 0x30, 0x2f, 0x23, 0x22, + 0x57, 0x6a, 0x6b, 0x65, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x6e, 0x66, 0x72, 0x73, 0x2a, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x33, 0x2e, 0x26, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x51, 0x3a, 0x44, 0x47, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x2c, 0x45, 0x4c, 0x4c, 0x38, + 0x20, 0x20, 0x20, 0x22, 0x27, 0x2f, 0x23, 0x36, + 0x74, 0x6b, 0x75, 0x6c, 0x64, 0x6e, 0x71, 0x76, + 0x77, 0x78, 0x79, 0x71, 0x71, 0x7a, 0x74, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x33, 0x34, 0x27, 0x22, + 0x20, 0x20, 0x20, 0x20, 0x54, 0x44, 0x44, 0x54, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x5a, 0x48, 0x48, 0x4f, 0x37, + 0x20, 0x20, 0x20, 0x22, 0x27, 0x34, 0x26, 0x7b, + 0x7c, 0x7d, 0x7e, 0x6c, 0x6d, 0x7f, 0x71, 0x80, + 0x78, 0x79, 0x79, 0x79, 0x7a, 0x67, 0x66, 0x21, + 0x36, 0x36, 0x36, 0x36, 0x25, 0x41, 0x2a, 0x23, + 0x20, 0x20, 0x20, 0x20, 0x81, 0x44, 0x40, 0x5b, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x2c, 0x44, 0x45, 0x4f, 0x38, + 0x20, 0x20, 0x20, 0x22, 0x26, 0x2d, 0x33, 0x82, + 0x6b, 0x83, 0x84, 0x64, 0x6e, 0x71, 0x76, 0x85, + 0x79, 0x79, 0x71, 0x86, 0x87, 0x83, 0x88, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x21, 0x43, 0x2b, 0x28, + 0x21, 0x20, 0x20, 0x20, 0x52, 0x44, 0x44, 0x50, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x5a, 0x40, 0x4d, 0x4f, 0x38, + 0x20, 0x20, 0x20, 0x22, 0x26, 0x2d, 0x32, 0x24, + 0x89, 0x8a, 0x6c, 0x8b, 0x7f, 0x71, 0x79, 0x79, + 0x71, 0x8c, 0x8d, 0x8e, 0x83, 0x8e, 0x8f, 0x36, + 0x21, 0x2b, 0x23, 0x36, 0x36, 0x5a, 0x2e, 0x26, + 0x22, 0x20, 0x20, 0x20, 0x42, 0x40, 0x38, 0x50, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x2c, 0x4c, 0x4f, 0x4f, 0x38, + 0x20, 0x20, 0x20, 0x22, 0x27, 0x2d, 0x33, 0x21, + 0x90, 0x91, 0x92, 0x7a, 0x6f, 0x6e, 0x67, 0x92, + 0x93, 0x6b, 0x8e, 0x94, 0x95, 0x96, 0x49, 0x36, + 0x36, 0x2d, 0x3b, 0x35, 0x36, 0x24, 0x43, 0x32, + 0x28, 0x21, 0x20, 0x20, 0x57, 0x40, 0x44, 0x54, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x34, 0x4d, 0x42, 0x51, 0x38, + 0x20, 0x20, 0x20, 0x22, 0x30, 0x2f, 0x33, 0x21, + 0x5d, 0x97, 0x98, 0x93, 0x86, 0x66, 0x99, 0x87, + 0x7d, 0x7d, 0x99, 0x6a, 0x57, 0x4d, 0x59, 0x23, + 0x36, 0x24, 0x3b, 0x3b, 0x24, 0x36, 0x2e, 0x31, + 0x26, 0x22, 0x20, 0x20, 0x52, 0x44, 0x44, 0x9a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x5a, 0x57, 0x57, 0x57, 0x37, + 0x20, 0x20, 0x21, 0x28, 0x33, 0x3c, 0x25, 0x22, + 0x53, 0x42, 0x97, 0x98, 0x99, 0x87, 0x99, 0x6b, + 0x7c, 0x9b, 0x9c, 0x51, 0x4f, 0x3f, 0x40, 0x2c, + 0x36, 0x36, 0x33, 0x5a, 0x21, 0x36, 0x22, 0x43, + 0x33, 0x28, 0x21, 0x20, 0x42, 0x44, 0x37, 0x4f, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x2a, 0x51, 0x42, 0x51, 0x37, + 0x20, 0x20, 0x22, 0x27, 0x2e, 0x2e, 0x36, 0x21, + 0x4e, 0x4d, 0x42, 0x9d, 0x9e, 0x98, 0x98, 0x9f, + 0x97, 0x51, 0x42, 0x4c, 0x39, 0x58, 0x58, 0x47, + 0x21, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x5a, + 0x2e, 0x27, 0x23, 0x20, 0x59, 0x48, 0x38, 0x50, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x2a, 0x42, 0x51, 0x42, 0x3e, + 0x20, 0x22, 0x24, 0x2b, 0x41, 0x28, 0x36, 0x32, + 0x3e, 0x3f, 0x42, 0x42, 0x42, 0x51, 0x51, 0x42, + 0x42, 0x57, 0x40, 0x38, 0x58, 0x58, 0x58, 0x58, + 0x34, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x23, + 0x2f, 0x2b, 0x24, 0x21, 0x57, 0x4f, 0x3e, 0x53, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x33, 0x47, 0x51, 0x52, 0x38, + 0x21, 0x28, 0x32, 0x43, 0x32, 0x28, 0x21, 0x47, + 0x58, 0x39, 0x48, 0x42, 0x42, 0x42, 0x42, 0x42, + 0x48, 0x3a, 0x37, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x4f, 0x23, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x2a, 0x2f, 0x2a, 0x28, 0x42, 0x4f, 0x44, 0x52, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x5a, 0x57, 0x47, 0x51, 0x37, + 0x23, 0x30, 0x2e, 0x2c, 0x36, 0x21, 0x43, 0x37, + 0x58, 0x58, 0x46, 0x4d, 0x42, 0x42, 0x57, 0x3f, + 0x39, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x34, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x2d, 0x31, 0x27, 0x4f, 0x47, 0x38, 0x50, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x25, 0x57, 0x47, 0x52, 0x38, + 0x27, 0x2c, 0x2d, 0x21, 0x36, 0x28, 0x45, 0x58, + 0x58, 0x58, 0x58, 0x39, 0x44, 0x3a, 0x39, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x52, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x28, 0x43, 0x5a, 0x45, 0x4d, 0x37, 0x9a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x2a, 0x47, 0x52, 0x59, 0x37, + 0x35, 0x43, 0x28, 0x36, 0x36, 0x4a, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x37, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x3a, 0x28, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x28, 0x41, 0x48, 0x4d, 0x38, 0x54, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x2a, 0x81, 0x5b, 0x51, 0x38, + 0x43, 0x25, 0x36, 0x36, 0x23, 0x57, 0x37, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x37, 0x38, 0x2b, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x30, 0x51, 0x40, 0x3a, 0x56, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x33, 0x51, 0x47, 0x81, 0x3e, + 0x27, 0x36, 0x36, 0x36, 0x2a, 0x57, 0x39, 0x58, + 0x58, 0x58, 0x58, 0x37, 0x38, 0x38, 0x37, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x37, 0x39, 0x46, + 0x44, 0x3a, 0x3c, 0x21, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x48, 0x59, 0x37, 0x5d, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x27, 0x52, 0x4e, 0x5b, 0x44, + 0x36, 0x36, 0x36, 0x21, 0x31, 0x5b, 0x48, 0x3e, + 0x39, 0x37, 0x37, 0x46, 0x44, 0x3a, 0x46, 0x37, + 0x37, 0x37, 0x39, 0x3a, 0x40, 0x48, 0x4f, 0x4f, + 0x4d, 0x4f, 0x47, 0x28, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x4f, 0x81, 0x40, 0x5d, + 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x33, 0x52, 0x50, 0x56, 0x38, + 0x36, 0x36, 0x36, 0x22, 0x41, 0x47, 0x45, 0x38, + 0x37, 0x58, 0x58, 0x37, 0x3e, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x39, 0x46, 0x44, 0x4c, 0x4f, + 0x57, 0x57, 0x4c, 0x50, 0x21, 0x23, 0x33, 0x23, + 0x36, 0x36, 0x36, 0x36, 0x4d, 0x51, 0x39, 0x3b, + 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x33, 0x57, 0x55, 0x55, 0x37, + 0x37, 0x37, 0x38, 0x38, 0x38, 0x37, 0x37, 0x37, + 0x37, 0x37, 0x38, 0x37, 0x37, 0x37, 0x38, 0x37, + 0x37, 0x37, 0x37, 0x39, 0x3e, 0x37, 0x38, 0x38, + 0x38, 0x37, 0x38, 0x38, 0x38, 0x37, 0x38, 0x38, + 0x37, 0x38, 0x38, 0x37, 0x47, 0x42, 0x48, 0x9a, + 0x25, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x33, 0x5b, 0x81, 0x5d, 0x37, + 0x38, 0x37, 0x37, 0x38, 0x37, 0x38, 0x38, 0x37, + 0x38, 0x37, 0x37, 0x37, 0x37, 0x37, 0x38, 0x37, + 0x38, 0x37, 0x38, 0x37, 0x37, 0x38, 0x37, 0x37, + 0x38, 0x37, 0x37, 0x37, 0x38, 0x38, 0x37, 0x3e, + 0x37, 0x38, 0x38, 0x37, 0x57, 0x57, 0x48, 0x5d, + 0x2a, 0x23, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x33, 0x52, 0x59, 0x50, 0x5b, + 0x54, 0x5b, 0x5b, 0x54, 0x81, 0x5b, 0x55, 0x55, + 0x52, 0x54, 0x81, 0x81, 0x81, 0x50, 0x52, 0x54, + 0x5b, 0x59, 0x52, 0x52, 0x5b, 0x52, 0x5b, 0x81, + 0x5b, 0x47, 0x51, 0x52, 0x57, 0x57, 0x57, 0x57, + 0x51, 0x57, 0x52, 0x57, 0x48, 0x57, 0x4c, 0x3b, + 0x35, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x21, 0x33, 0x54, 0x54, 0x5b, 0x50, + 0x54, 0x50, 0x54, 0x81, 0x50, 0x59, 0x54, 0x50, + 0x5b, 0x81, 0x81, 0x59, 0x81, 0x59, 0x59, 0x59, + 0x59, 0x47, 0x81, 0x51, 0x47, 0x51, 0x59, 0x81, + 0x81, 0x51, 0x47, 0x50, 0x59, 0x59, 0x59, 0x47, + 0x47, 0x47, 0x52, 0x57, 0x52, 0x47, 0x59, 0x26, + 0x2d, 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x22, 0x27, 0x55, 0x50, 0x55, 0x50, + 0x55, 0x81, 0x54, 0x52, 0x52, 0x81, 0x5b, 0x50, + 0x5b, 0x52, 0x52, 0x51, 0x57, 0x52, 0x52, 0x52, + 0x54, 0x51, 0x81, 0x52, 0x59, 0x52, 0x5b, 0x5b, + 0x59, 0x5b, 0x51, 0x52, 0x52, 0x4f, 0x5b, 0x51, + 0x52, 0x47, 0x59, 0x42, 0x47, 0x81, 0x5c, 0x21, + 0x2f, 0x32, 0x23, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x21, 0x23, 0x33, 0x81, 0x54, 0x5c, 0x54, + 0x50, 0x5b, 0x50, 0x50, 0x81, 0x5b, 0x5c, 0x5b, + 0x50, 0x59, 0x81, 0x81, 0x81, 0x81, 0x47, 0x50, + 0x50, 0x59, 0x5b, 0x50, 0x52, 0x81, 0x50, 0x59, + 0x5b, 0x81, 0x59, 0x81, 0x59, 0x47, 0x59, 0x47, + 0x59, 0x52, 0x51, 0x48, 0x51, 0x52, 0x5d, 0x36, + 0x2e, 0x35, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x22, 0x25, 0x2a, 0x50, 0x4e, 0x5c, 0x54, + 0x5c, 0x5b, 0x5b, 0x5b, 0x59, 0x5b, 0x50, 0x54, + 0x5b, 0x54, 0x5b, 0x5b, 0x54, 0x54, 0x5b, 0x5b, + 0x5b, 0x81, 0x55, 0x81, 0x55, 0x54, 0x5b, 0x5c, + 0x5b, 0x4e, 0x51, 0x5b, 0x5b, 0x57, 0x51, 0x4f, + 0x4d, 0x47, 0x4f, 0x4c, 0x51, 0x52, 0x4b, 0x36, + 0x2a, 0x2e, 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x23, 0x2a, 0x2a, 0x50, 0x9a, 0x54, 0x5c, + 0x55, 0x50, 0x81, 0x59, 0x54, 0x50, 0x54, 0x50, + 0x50, 0x50, 0x81, 0x81, 0x50, 0x50, 0x50, 0x81, + 0x81, 0x5b, 0x47, 0x51, 0x81, 0x59, 0x81, 0x55, + 0x59, 0x59, 0x81, 0x42, 0x27, 0x36, 0x28, 0x36, + 0x27, 0x36, 0x28, 0x2d, 0x47, 0x52, 0x2d, 0x36, + 0x22, 0x2f, 0x30, 0x22, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x22, 0x25, 0x2c, 0x26, 0x53, 0x4e, 0x55, 0x5c, + 0x55, 0x55, 0x55, 0x81, 0x54, 0x50, 0x54, 0x55, + 0x5b, 0x55, 0x52, 0x54, 0x54, 0x5b, 0x54, 0x55, + 0x36, 0x36, 0x27, 0x2a, 0x2a, 0x27, 0xa0, 0x27, + 0x2a, 0x2a, 0x2c, 0x27, 0x5d, 0x22, 0x22, 0x28, + 0x28, 0x22, 0x25, 0x59, 0x51, 0x53, 0x27, 0x36, + 0x21, 0x2f, 0x32, 0x23, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x28, 0x32, 0x2f, 0x21, 0x4a, 0x54, 0x5c, 0x4e, + 0x5c, 0x81, 0x5c, 0x54, 0x5c, 0x54, 0x5c, 0x50, + 0x81, 0x50, 0x50, 0x81, 0x81, 0x5c, 0x50, 0x81, + 0x5d, 0x28, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xa0, 0x25, + 0x28, 0x21, 0x28, 0x81, 0x59, 0x4a, 0x28, 0x36, + 0x36, 0x34, 0x2b, 0x28, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x25, 0x2c, 0x5a, 0x36, 0x32, 0x9a, 0x81, 0x4e, + 0x55, 0x5b, 0x50, 0x54, 0x5c, 0x54, 0x55, 0x55, + 0x54, 0x4e, 0x54, 0x55, 0x5b, 0x4e, 0x55, 0x5b, + 0x3b, 0x4e, 0x4a, 0x3b, 0x4a, 0x4e, 0x3b, 0x5d, + 0x56, 0x3b, 0x56, 0x5c, 0x50, 0x3a, 0x3e, 0x40, + 0x4f, 0x57, 0x81, 0x4e, 0x4e, 0x27, 0x36, 0x36, + 0x36, 0x2c, 0x35, 0x24, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x30, 0x2d, 0x21, 0x36, 0x23, 0x3d, 0x53, 0x43, + 0x4a, 0x5d, 0x55, 0x5c, 0x4e, 0x5c, 0x50, 0x5c, + 0x81, 0x50, 0x50, 0x81, 0x50, 0x50, 0x50, 0x50, + 0x4e, 0x5b, 0x54, 0x5b, 0x51, 0x59, 0x5b, 0x5b, + 0x54, 0x5b, 0x5b, 0x52, 0x51, 0x42, 0x5b, 0x5c, + 0x5c, 0x53, 0x5b, 0x3b, 0x28, 0x36, 0x36, 0x36, + 0x36, 0x2c, 0x5a, 0x24, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28, + 0x33, 0x2e, 0x36, 0x36, 0x23, 0x41, 0x56, 0x2e, + 0x33, 0x50, 0x55, 0x81, 0x54, 0x5b, 0x54, 0x52, + 0x5b, 0x55, 0x54, 0x55, 0x55, 0x55, 0x5b, 0x9a, + 0x5c, 0x81, 0x81, 0x81, 0x52, 0x59, 0x50, 0x59, + 0x59, 0x59, 0x59, 0x50, 0x81, 0x81, 0x5b, 0x5b, + 0x5b, 0x54, 0x34, 0x22, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x2c, 0x5a, 0x24, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28, + 0x2b, 0x5a, 0x36, 0x36, 0x36, 0x27, 0x3d, 0x28, + 0xa0, 0x5d, 0x5c, 0x55, 0x50, 0x50, 0x5c, 0x81, + 0x81, 0x50, 0x50, 0x47, 0x50, 0x5c, 0x5c, 0x52, + 0x54, 0x5b, 0x5b, 0x5b, 0x59, 0x52, 0x5b, 0x52, + 0x5b, 0x52, 0x52, 0x54, 0x59, 0x5b, 0x81, 0x81, + 0x9a, 0x33, 0x26, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x2c, 0x35, 0x24, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, + 0x35, 0x5a, 0x36, 0x36, 0x36, 0x36, 0x30, 0x4e, + 0x52, 0x54, 0x56, 0x55, 0x55, 0x55, 0x55, 0x5b, + 0x55, 0x55, 0x54, 0x5b, 0x54, 0x55, 0x50, 0x59, + 0x5c, 0x81, 0x59, 0x52, 0x59, 0x59, 0x81, 0x59, + 0x81, 0x81, 0x81, 0x81, 0x5b, 0x5b, 0x81, 0x53, + 0x2a, 0x27, 0xa1, 0x24, 0x25, 0x28, 0x21, 0x36, + 0x36, 0x34, 0x2b, 0x28, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x25, + 0x5a, 0x4b, 0xa2, 0x8d, 0x8a, 0x5f, 0x21, 0x2d, + 0x55, 0x5c, 0x9a, 0x5c, 0x5c, 0x5c, 0x50, 0x9a, + 0x5c, 0x9a, 0x50, 0x5c, 0x5c, 0x5c, 0x54, 0x5b, + 0x55, 0x5b, 0x54, 0x81, 0x5b, 0x5b, 0x5b, 0x54, + 0x54, 0x5b, 0x5b, 0x5b, 0x5b, 0x54, 0x54, 0x30, + 0x23, 0x36, 0x36, 0x36, 0x21, 0x28, 0x2c, 0x30, + 0x21, 0x41, 0x33, 0x28, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x21, 0x22, 0x22, 0x28, 0x30, + 0x2d, 0xa3, 0x83, 0xa4, 0xa5, 0xa5, 0x88, 0x22, + 0x3b, 0x47, 0x53, 0x55, 0x55, 0x53, 0x54, 0x5b, + 0x52, 0x53, 0x54, 0x54, 0x54, 0x50, 0x5c, 0x59, + 0x56, 0x59, 0x5b, 0x50, 0x50, 0x59, 0x9a, 0x59, + 0x5c, 0x81, 0x50, 0x59, 0x9a, 0x52, 0x68, 0x69, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x30, 0x32, + 0x25, 0x4b, 0x2b, 0x28, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x21, 0x23, 0x24, 0x26, 0x30, 0x33, 0x31, + 0x4b, 0x9b, 0x63, 0xa4, 0xa5, 0xa5, 0xa5, 0x62, + 0x21, 0x2e, 0x44, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x3a, 0x37, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x58, 0xa6, 0xa7, 0x71, 0x6e, 0xa8, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x26, 0x25, + 0x8c, 0xa9, 0x2c, 0x25, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x28, 0x30, 0x35, 0x2d, 0x2f, 0x3c, 0x3d, + 0x68, 0x8e, 0xaa, 0xab, 0xa5, 0xa5, 0xa5, 0x8b, + 0x8f, 0x36, 0x32, 0x4d, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x3e, 0x38, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x58, 0xac, 0xa4, 0xa7, 0xad, 0xa0, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x5f, + 0x7f, 0x6e, 0x34, 0x27, 0x22, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x23, 0x30, 0x31, 0xae, 0x9b, 0x87, 0x99, 0x99, + 0x94, 0x63, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0x65, 0xaf, 0x36, 0x24, 0x50, 0x37, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x37, 0x38, 0xac, 0x6c, 0x64, 0x94, 0xaf, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x7b, 0x65, + 0x8b, 0x64, 0xb0, 0x2a, 0x23, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x24, 0x2b, 0xae, 0x94, 0x63, 0x7e, 0x63, 0x63, + 0x84, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa7, 0x66, 0x22, 0x36, 0x21, 0x3b, 0x38, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x3a, 0x4d, 0xb1, 0x84, 0x84, 0x8e, 0x89, + 0xa1, 0x36, 0x36, 0x36, 0x21, 0xb2, 0x87, 0x84, + 0x6c, 0x6c, 0xb3, 0x35, 0x24, 0x21, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x26, 0x31, 0xb4, 0x63, 0x6c, 0xa4, 0xa4, 0xab, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0x6e, 0xb5, 0x36, 0x36, 0x36, 0x2c, 0x3f, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x48, 0x4d, 0xb6, 0x7e, 0x7e, 0x83, 0x6b, + 0xb7, 0xb8, 0x8f, 0xb8, 0xb9, 0x99, 0x63, 0x6c, + 0xa4, 0xa4, 0xba, 0x2d, 0x27, 0x23, 0x21, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x26, 0x2d, 0x9b, 0x63, 0x6c, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa7, 0x8c, 0xa0, 0x36, 0x36, 0x36, 0x30, + 0x45, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x37, 0x48, 0x4d, 0xbb, 0x63, 0x84, 0xbc, 0x8e, + 0x87, 0x99, 0x6b, 0x99, 0x8e, 0x63, 0xa4, 0xa5, + 0xa5, 0xab, 0x65, 0xb3, 0x5a, 0x26, 0x23, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x26, 0x2d, 0xbd, 0xbc, 0x6c, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa7, 0x91, 0x36, 0x36, 0x36, 0x36, + 0x2d, 0x37, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x37, 0x40, 0x4d, 0xbe, 0x75, 0x84, 0xaa, 0xbc, + 0x83, 0x94, 0x94, 0x83, 0x63, 0x6c, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa4, 0xbf, 0x3c, 0x35, 0x26, 0x23, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x26, 0x2e, 0xbd, 0x83, 0x84, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa7, 0x7a, 0x7b, 0x36, 0x36, 0x36, + 0x24, 0x46, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x44, 0x51, 0xb4, 0x83, 0x84, 0x6c, 0x84, + 0x7e, 0x63, 0x63, 0x7e, 0x84, 0xa4, 0xa5, 0xa5, + 0xa5, 0xa5, 0xab, 0x6c, 0xbf, 0x4b, 0x2c, 0x27, + 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x25, 0x31, 0xc0, 0x94, 0x84, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa7, 0x92, 0xa1, 0x36, 0x36, + 0x32, 0x39, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x3f, 0x2f, 0x98, 0x83, 0x84, 0xa4, 0xab, + 0xa4, 0x6c, 0x6c, 0xa4, 0xa4, 0xab, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa4, 0x65, 0xc1, 0x2c, + 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x25, 0x31, 0xc0, 0x8e, 0x84, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0x6e, 0x5f, 0x27, 0x4b, + 0x3f, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x38, 0x34, 0xa1, 0xb7, 0x83, 0x84, 0xa4, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa4, 0xc0, + 0x32, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x26, 0x2d, 0xc0, 0x8e, 0x84, 0xab, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa7, 0x67, 0x9c, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x45, + 0x35, 0x36, 0xa0, 0xb9, 0x83, 0x84, 0xab, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xab, 0xa4, 0xbe, + 0x2b, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23, + 0x30, 0x2f, 0xb4, 0x94, 0x84, 0xab, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0x6e, 0x92, 0x40, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x37, 0x5b, 0x25, + 0x36, 0x36, 0x69, 0xb7, 0x75, 0x6c, 0xab, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xab, 0x84, 0xbc, 0xc1, + 0x32, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28, + 0x33, 0xc2, 0x6b, 0xbc, 0xa4, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa4, 0x7a, 0x8a, 0xc3, + 0x44, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x4d, 0x2c, 0x36, 0x36, + 0x36, 0x36, 0xc4, 0x98, 0x75, 0x6c, 0xab, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa4, 0xaa, 0x94, 0xae, 0x2c, + 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, + 0x35, 0x9e, 0x7d, 0xaa, 0xa4, 0xab, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xab, 0x84, 0x8a, 0xb7, + 0x7b, 0x53, 0x45, 0x37, 0x58, 0x58, 0x58, 0x37, + 0x38, 0x4c, 0x4e, 0x2c, 0x21, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x7b, 0xb7, 0x83, 0x84, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0x6c, 0x7e, 0x83, 0x9b, 0xb3, 0x31, 0x30, + 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, + 0x5a, 0x9f, 0x7d, 0xbc, 0x84, 0x6c, 0xa4, 0xa4, + 0xab, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0x84, 0x83, 0xc5, + 0xc6, 0x36, 0x21, 0x26, 0x2b, 0x5a, 0x33, 0x30, + 0x23, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x21, 0xc6, 0xb9, 0x94, 0x84, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa4, 0x6c, 0x6c, + 0x7e, 0x8e, 0xbd, 0xb3, 0x34, 0x2b, 0x27, 0x28, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28, + 0x33, 0xc7, 0x6b, 0x87, 0x83, 0x75, 0xbc, 0x63, + 0x7e, 0x84, 0x6c, 0x6c, 0xa4, 0xab, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xab, 0x7e, 0x8e, 0xb7, + 0x82, 0x22, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x21, 0xc8, 0xb9, 0x7d, 0x7e, 0xa4, 0xa5, + 0xa5, 0xa5, 0xab, 0xa4, 0x6c, 0x7e, 0xbc, 0x94, + 0xb4, 0xb3, 0x2f, 0x35, 0x30, 0x24, 0x22, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23, + 0x27, 0x31, 0xc9, 0xc7, 0xb9, 0x7c, 0x6b, 0x99, + 0x87, 0x7d, 0x94, 0x75, 0xbc, 0x7e, 0x6c, 0xa4, + 0xab, 0xab, 0xab, 0xab, 0x6c, 0x83, 0x8d, 0xca, + 0x82, 0xa1, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x21, 0xc6, 0xca, 0x6b, 0x75, 0x84, 0x6c, + 0xab, 0xa4, 0x6c, 0x84, 0xbc, 0x7d, 0x6b, 0x9e, + 0x41, 0x5a, 0x2a, 0x24, 0x23, 0x21, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x28, 0x27, 0x35, 0x2d, 0x49, 0xb3, 0xc3, 0x98, + 0xb7, 0xb9, 0xc5, 0x7c, 0x8d, 0x99, 0x8e, 0x75, + 0x63, 0x84, 0x84, 0xaa, 0x75, 0x99, 0xb7, 0xcb, + 0xc8, 0x22, 0x36, 0x36, 0x28, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x25, 0x36, + 0x36, 0x21, 0xb2, 0x89, 0xc5, 0x87, 0x75, 0x7e, + 0xaa, 0x7e, 0x75, 0x8e, 0x6b, 0xb7, 0xb3, 0x34, + 0x33, 0x26, 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x23, 0x24, 0x27, 0x2a, 0x35, 0x2e, 0x2f, + 0x49, 0xcc, 0xcd, 0x74, 0x89, 0xca, 0xb7, 0x7c, + 0x8d, 0x99, 0x7d, 0x87, 0x7c, 0x98, 0xcb, 0x82, + 0xc4, 0x2b, 0x4a, 0x49, 0x2f, 0x34, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x34, 0x2f, 0x41, + 0x4b, 0x3c, 0xce, 0xcf, 0x98, 0x7c, 0x6b, 0x87, + 0x7d, 0x87, 0x6b, 0xc5, 0x91, 0xc2, 0x31, 0x2a, + 0x24, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x21, 0x22, 0x23, 0x24, 0x26, 0x30, + 0x33, 0x5a, 0x2e, 0x43, 0x49, 0xb0, 0x74, 0xcf, + 0x89, 0xca, 0xca, 0xca, 0xd0, 0xcf, 0xb5, 0xd1, + 0x49, 0x34, 0x35, 0x32, 0x30, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x30, 0x2a, + 0x2b, 0x34, 0xd2, 0xc8, 0xd3, 0x98, 0xb9, 0xc5, + 0xc5, 0xb9, 0xca, 0x74, 0x49, 0x5a, 0x27, 0x28, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22, + 0x28, 0x24, 0x26, 0x2a, 0x33, 0x2c, 0x2f, 0x49, + 0xd4, 0xb5, 0x82, 0x82, 0x82, 0xc8, 0xd5, 0x43, + 0x5a, 0x30, 0x24, 0x23, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x22, 0x23, + 0x24, 0x2a, 0x31, 0xd6, 0xc6, 0x82, 0xcf, 0x89, + 0xd3, 0xb8, 0xd7, 0x2f, 0x35, 0x26, 0x23, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x21, 0x22, 0x23, 0x28, 0x25, 0x30, 0x2b, + 0x31, 0x2f, 0xd2, 0xd6, 0xd6, 0x2f, 0x2e, 0x33, + 0x26, 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x28, 0x27, 0x35, 0x34, 0xd6, 0xd6, 0xd6, + 0xd8, 0xd2, 0x2e, 0x33, 0x25, 0x23, 0x21, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x23, 0x28, + 0x26, 0x30, 0x32, 0x2b, 0x33, 0x2a, 0x26, 0x28, + 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x21, 0x23, 0x25, 0x30, 0x33, 0x35, 0x35, + 0x2b, 0x2a, 0x26, 0x28, 0x22, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x21, 0x22, 0x23, 0x28, 0x28, 0x23, 0x22, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x21, 0x23, 0x28, 0x24, 0x24, + 0x28, 0x23, 0x22, 0x21, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, }; -#endif - -#else +#endif /* !INCLUDE_LINUX_LOGO_DATA */ -#define LINUX_LOGO_COLORS 214 +#endif /* CONFIG_MAC */ -#endif - -#ifdef INCLUDE_LINUX_LOGO_DATA - -#define INCLUDE_LINUX_LOGOBW -#define INCLUDE_LINUX_LOGO16 #include -#else - -/* prototypes only */ -extern unsigned char linux_logo_red[]; -extern unsigned char linux_logo_green[]; -extern unsigned char linux_logo_blue[]; -extern unsigned char linux_logo[]; -extern unsigned char linux_logo_bw[]; -extern unsigned char linux_logo16_red[]; -extern unsigned char linux_logo16_green[]; -extern unsigned char linux_logo16_blue[]; -extern unsigned char linux_logo16[]; - -#endif diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/mac_psc.h linux/include/asm-m68k/mac_psc.h --- v2.4.5/linux/include/asm-m68k/mac_psc.h Sat Sep 4 13:06:41 1999 +++ linux/include/asm-m68k/mac_psc.h Mon Jun 11 19:15:27 2001 @@ -51,6 +51,8 @@ * One-shot DMA control registers */ +#define PSC_MYSTERY 0x804 + #define PSC_CTL_BASE 0xC00 #define PSC_SCSI_CTL 0xC00 @@ -70,6 +72,9 @@ #define PSC_ADDR_BASE 0x1000 #define PSC_LEN_BASE 0x1004 #define PSC_CMD_BASE 0x1008 + +#define PSC_SET0 0x00 +#define PSC_SET1 0x10 #define PSC_SCSI_ADDR 0x1000 /* confirmed */ #define PSC_SCSI_LEN 0x1004 /* confirmed */ diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/mc146818rtc.h linux/include/asm-m68k/mc146818rtc.h --- v2.4.5/linux/include/asm-m68k/mc146818rtc.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-m68k/mc146818rtc.h Mon Jun 11 19:15:27 2001 @@ -0,0 +1,48 @@ +/* + * Machine dependent access functions for RTC registers. + */ +#ifndef _ASM_MC146818RTC_H +#define _ASM_MC146818RTC_H + +#include + +#ifdef CONFIG_ATARI +/* RTC in Atari machines */ + +#include +#include +#include +#define RTC_HAS_IRQ (ATARIHW_PRESENT(TT_MFP)) +#define RTC_IRQ IRQ_TT_MFP_RTC +#define RTC_IRQ_FLAGS IRQ_TYPE_FAST +#define RTC_PORT(x) (TT_RTC_BAS + 2*(x)) +#define RTC_ALWAYS_BCD 0 /* TOS uses binary mode, Linux should be able + * to deal with both modes */ + +#define RTC_CHECK_DRIVER_INIT() (MACH_IS_ATARI && ATARIHW_PRESENT(TT_CLK)) +#define RTC_MACH_INIT() \ + do { \ + epoch = atari_rtc_year_offset + 1900; \ + if (RTC_HAS_IRQ) \ + /* select RTC int on H->L edge */ \ + tt_mfp.active_edge &= ~0x40; \ + } while(0) +#define RTC_MACH_EXIT() + +/* On Atari, the year was stored with base 1970 in old TOS versions (before + * 3.06). Later, Atari recognized that this broke leap year recognition, and + * changed the base to 1968. Medusa and Hades always use the new version. */ +#define RTC_CENTURY_SWITCH -1 /* no century switch */ +#define RTC_MINYEAR epoch + +#define CMOS_READ(addr) ({ \ +outb_p((addr),RTC_PORT(0)); \ +inb_p(RTC_PORT(1)); \ +}) +#define CMOS_WRITE(val, addr) ({ \ +outb_p((addr),RTC_PORT(0)); \ +outb_p((val),RTC_PORT(1)); \ +}) +#endif /* CONFIG_ATARI */ + +#endif /* _ASM_MC146818RTC_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/motorola_pgalloc.h linux/include/asm-m68k/motorola_pgalloc.h --- v2.4.5/linux/include/asm-m68k/motorola_pgalloc.h Mon Apr 23 15:28:07 2001 +++ linux/include/asm-m68k/motorola_pgalloc.h Mon Jun 11 19:15:27 2001 @@ -21,6 +21,22 @@ extern pmd_t *get_pointer_table(void); extern int free_pointer_table(pmd_t *); + +extern inline void flush_tlb_kernel_page(unsigned long addr) +{ + if (CPU_IS_040_OR_060) { + mm_segment_t old_fs = get_fs(); + set_fs(KERNEL_DS); + __asm__ __volatile__(".chip 68040\n\t" + "pflush (%0)\n\t" + ".chip 68k" + : : "a" (addr)); + set_fs(old_fs); + } else + __asm__ __volatile__("pflush #4,#4,(%0)" : : "a" (addr)); +} + + extern inline pte_t *get_pte_fast(void) { unsigned long *ret; @@ -33,6 +49,29 @@ } return (pte_t *)ret; } +#define pte_alloc_one_fast(mm,addr) get_pte_fast() + +static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address) +{ + pte_t *pte; + + pte = (pte_t *) __get_free_page(GFP_KERNEL); + if (pte) { + clear_page(pte); + __flush_page_to_ram((unsigned long)pte); + flush_tlb_kernel_page((unsigned long)pte); + nocache_page((unsigned long)pte); + } + + return pte; +} + + +extern __inline__ pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address) +{ + return get_pointer_table(); +} + extern inline void free_pte_fast(pte_t *pte) { @@ -59,6 +98,7 @@ } return (pmd_t *)ret; } +#define pmd_alloc_one_fast(mm,addr) get_pmd_fast() extern inline void free_pmd_fast(pmd_t *pmd) { @@ -94,46 +134,11 @@ free_pte_fast(pte); } -extern inline pte_t *pte_alloc(pmd_t *pmd, unsigned long address) -{ - address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); - if (pmd_none(*pmd)) { - pte_t *page = get_pte_fast(); - - if (!page) - return get_pte_slow(pmd, address); - pmd_set(pmd,page); - return page + address; - } - if (pmd_bad(*pmd)) { - __bad_pte(pmd); - return NULL; - } - return (pte_t *)__pmd_page(*pmd) + address; -} - extern inline void pmd_free(pmd_t *pmd) { free_pmd_fast(pmd); } -extern inline pmd_t *pmd_alloc(pgd_t *pgd, unsigned long address) -{ - address = (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1); - if (pgd_none(*pgd)) { - pmd_t *page = get_pmd_fast(); - - if (!page) - return get_pmd_slow(pgd, address); - pgd_set(pgd, page); - return page + address; - } - if (pgd_bad(*pgd)) { - __bad_pmd(pgd); - return NULL; - } - return (pmd_t *)__pgd_page(*pgd) + address; -} extern inline void pte_free_kernel(pte_t *pte) { @@ -142,7 +147,7 @@ extern inline pte_t *pte_alloc_kernel(pmd_t *pmd, unsigned long address) { - return pte_alloc(pmd, address); + return pte_alloc(&init_mm,pmd, address); } extern inline void pmd_free_kernel(pmd_t *pmd) @@ -152,7 +157,7 @@ extern inline pmd_t *pmd_alloc_kernel(pgd_t *pgd, unsigned long address) { - return pmd_alloc(pgd, address); + return pmd_alloc(&init_mm,pgd, address); } extern inline void pgd_free(pgd_t *pgd) @@ -168,6 +173,11 @@ return pgd; } + +#define pmd_populate(MM, PMD, PTE) pmd_set(PMD, PTE) +#define pgd_populate(MM, PGD, PMD) pgd_set(PGD, PMD) + + extern int do_check_pgt_cache(int, int); extern inline void set_pgdir(unsigned long address, pgd_t entry) @@ -238,19 +248,6 @@ __flush_tlb(); } -extern inline void flush_tlb_kernel_page(unsigned long addr) -{ - if (CPU_IS_040_OR_060) { - mm_segment_t old_fs = get_fs(); - set_fs(KERNEL_DS); - __asm__ __volatile__(".chip 68040\n\t" - "pflush (%0)\n\t" - ".chip 68k" - : : "a" (addr)); - set_fs(old_fs); - } else - __asm__ __volatile__("pflush #4,#4,(%0)" : : "a" (addr)); -} extern inline void flush_tlb_pgtables(struct mm_struct *mm, unsigned long start, unsigned long end) diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/openprom.h linux/include/asm-m68k/openprom.h --- v2.4.5/linux/include/asm-m68k/openprom.h Fri Nov 12 04:29:47 1999 +++ linux/include/asm-m68k/openprom.h Mon Jun 11 19:15:27 2001 @@ -89,7 +89,7 @@ int *fd_stdout; }; -#ifdef CONFIG_SUN3 +#if defined(CONFIG_SUN3) || defined(CONFIG_SUN3X) struct linux_romvec { char *pv_initsp; int (*pv_startmon)(void); @@ -173,12 +173,15 @@ void (*pv_halt)(void); unsigned char *pv_memorybitmap; + +#ifdef CONFIG_SUN3 void (*pv_setctxt)(int ctxt, char *va, int pmeg); void (*pv_vector_cmd)(void); int dummy1z; int dummy2z; int dummy3z; int dummy4z; +#endif }; #else /* The top level PROM vector. */ diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/parport.h linux/include/asm-m68k/parport.h --- v2.4.5/linux/include/asm-m68k/parport.h Mon Nov 27 17:11:26 2000 +++ linux/include/asm-m68k/parport.h Mon Jun 11 19:15:27 2001 @@ -11,6 +11,9 @@ #ifndef _ASM_M68K_PARPORT_H #define _ASM_M68K_PARPORT_H 1 +#define insl(port,buf,len) isa_insb(port,buf,(len)<<2) +#define outsl(port,buf,len) isa_outsb(port,buf,(len)<<2) + /* no dma, or IRQ autoprobing */ static int __devinit parport_pc_find_isa_ports (int autoirq, int autodma); static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma) diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/pgalloc.h linux/include/asm-m68k/pgalloc.h --- v2.4.5/linux/include/asm-m68k/pgalloc.h Tue Dec 5 12:43:48 2000 +++ linux/include/asm-m68k/pgalloc.h Mon Jun 11 19:15:27 2001 @@ -105,14 +105,14 @@ } /* Push the page at kernel virtual address and clear the icache */ +/* RZ: use cpush %bc instead of cpush %dc, cinv %ic */ #define flush_page_to_ram(page) __flush_page_to_ram((unsigned long) page_address(page)) extern inline void __flush_page_to_ram(unsigned long address) { if (CPU_IS_040_OR_060) { __asm__ __volatile__("nop\n\t" ".chip 68040\n\t" - "cpushp %%dc,(%0)\n\t" - "cinvp %%ic,(%0)\n\t" + "cpushp %%bc,(%0)\n\t" ".chip 68k" : : "a" (__pa((void *)address))); } else { @@ -128,6 +128,7 @@ #define flush_dcache_page(page) do { } while (0) /* Push n pages at kernel virtual address and clear the icache */ +/* RZ: use cpush %bc instead of cpush %dc, cinv %ic */ extern inline void flush_icache_range (unsigned long address, unsigned long endaddr) { @@ -137,8 +138,7 @@ while (--n >= 0) { __asm__ __volatile__("nop\n\t" ".chip 68040\n\t" - "cpushp %%dc,(%0)\n\t" - "cinvp %%ic,(%0)\n\t" + "cpushp %%bc,(%0)\n\t" ".chip 68k" : : "a" (virt_to_phys((void *)address))); address += PAGE_SIZE; diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/q40_keyboard.h linux/include/asm-m68k/q40_keyboard.h --- v2.4.5/linux/include/asm-m68k/q40_keyboard.h Mon Nov 27 17:57:34 2000 +++ linux/include/asm-m68k/q40_keyboard.h Mon Jun 11 19:15:27 2001 @@ -1,11 +1,7 @@ /* * linux/include/asm-m68k/q40_keyboard.h * - * Created - */ - -/* - * This file contains the Q40 specific keyboard definitions + * Q40 specific keyboard definitions */ @@ -23,23 +19,12 @@ char raw_mode); extern char q40kbd_unexpected_up(unsigned char keycode); extern void q40kbd_leds(unsigned char leds); +extern int q40kbd_is_sysrq(unsigned char keycode); extern void q40kbd_init_hw(void); extern unsigned char q40kbd_sysrq_xlate[128]; -#if 0 -#define kbd_setkeycode q40kbd_setkeycode -#define kbd_getkeycode q40kbd_getkeycode -#define kbd_pretranslate q40kbd_pretranslate -#define kbd_translate q40kbd_translate -#define kbd_unexpected_up q40kbd_unexpected_up -#define kbd_leds q40kbd_leds -#define kbd_init_hw q40kbd_init_hw -#define kbd_sysrq_xlate q40kbd_sysrq_xlate - -#define SYSRQ_KEY 0x54 -#endif #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/q40_master.h linux/include/asm-m68k/q40_master.h --- v2.4.5/linux/include/asm-m68k/q40_master.h Mon Nov 27 17:11:26 2000 +++ linux/include/asm-m68k/q40_master.h Mon Jun 11 19:15:27 2001 @@ -6,7 +6,7 @@ #ifndef _Q40_MASTER_H #define _Q40_MASTER_H -#include +#include #define q40_master_addr 0xff000000 @@ -17,6 +17,10 @@ #define KEYCODE_REG 0x1c /* value of received scancode */ #define DISPLAY_CONTROL_REG 0x18 #define FRAME_CLEAR_REG 0x24 +#define LED_REG 0x30 + +#define Q40_LED_ON() master_outb(1,LED_REG) +#define Q40_LED_OFF() master_outb(0,LED_REG) #define INTERRUPT_REG IIRQ_REG /* "native" ints */ #define KEY_IRQ_ENABLE_REG 0x08 /**/ @@ -35,13 +39,10 @@ #endif #define EXT_ENABLE_REG 0x10 /* ... rest of the ISA ints ... */ -#if 0 -#define master_inb(_reg_) (*(((unsigned char *)q40_master_addr)+_reg_)) -#define master_outb(_b_,_reg_) (*(((unsigned char *)q40_master_addr)+_reg_)=(_b_)) -#else -#define master_inb(_reg_) native_inb((unsigned char *)q40_master_addr+_reg_) -#define master_outb(_b_,_reg_) native_outb(_b_,(unsigned char *)q40_master_addr+_reg_) -#endif + +#define master_inb(_reg_) in_8((unsigned char *)q40_master_addr+_reg_) +#define master_outb(_b_,_reg_) out_8((unsigned char *)q40_master_addr+_reg_,_b_) + /* define some Q40 specific ints */ #include "q40ints.h" diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/raw_io.h linux/include/asm-m68k/raw_io.h --- v2.4.5/linux/include/asm-m68k/raw_io.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-m68k/raw_io.h Mon Jun 11 19:15:27 2001 @@ -0,0 +1,242 @@ +/* + * linux/include/asm-m68k/io_native.h + * + * 10/20/00 RZ: - created from bits of io.h and ide.h to cleanup namespace + * + */ + +#ifndef _RAW_IO_H +#define _RAW_IO_H + +#ifdef __KERNEL__ + + +/* ++roman: The assignments to temp. vars avoid that gcc sometimes generates + * two accesses to memory, which may be undesirable for some devices. + */ +#define in_8(addr) \ + ({ unsigned char __v = (*(volatile unsigned char *) (addr)); __v; }) +#define in_be16(addr) \ + ({ unsigned short __v = (*(volatile unsigned short *) (addr)); __v; }) +#define in_be32(addr) \ + ({ unsigned int __v = (*(volatile unsigned int *) (addr)); __v; }) + +#define out_8(addr,b) (void)((*(volatile unsigned char *) (addr)) = (b)) +#define out_be16(addr,b) (void)((*(volatile unsigned short *) (addr)) = (b)) +#define out_be32(addr,b) (void)((*(volatile unsigned int *) (addr)) = (b)) + +#define raw_inb in_8 +#define raw_inw in_be16 +#define raw_inl in_be32 + +#define raw_outb(val,port) out_8((port),(val)) +#define raw_outw(val,port) out_be16((port),(val)) +#define raw_outl(val,port) out_be32((port),(val)) + +#define raw_insb(port, buf, len) ({ \ + volatile unsigned char *_port = (volatile unsigned char *) (port); \ + unsigned char *_buf =(unsigned char *)(buf); \ + unsigned int _i,_len=(unsigned int)(len); \ + for(_i=0; _i< _len; _i++) \ + *_buf++=in_8(_port); \ + }) + +#define raw_outsb(port, buf, len) ({ \ + volatile unsigned char *_port = (volatile unsigned char *) (port); \ + unsigned char *_buf =(unsigned char *)(buf); \ + unsigned int _i,_len=(unsigned int)(len); \ + for( _i=0; _i< _len; _i++) \ + out_8(_port,*_buf++); \ + }) + + +#define raw_insw(port, buf, nr) ({ \ + volatile unsigned char *_port = (volatile unsigned char *) (port); \ + unsigned char *_buf = (unsigned char *)(buf); \ + unsigned int _nr = (unsigned int)(nr); \ + unsigned long _tmp; \ + \ + if (_nr & 15) { \ + _tmp = (_nr & 15) - 1; \ + asm volatile ( \ + "1: movew %2@,%0@+; dbra %1,1b" \ + : "=a" (_buf), "=d" (_tmp) \ + : "a" (_port), "0" (_buf), \ + "1" (_tmp)); \ + } \ + if (_nr >> 4) { \ + _tmp = (_nr >> 4) - 1; \ + asm volatile ( \ + "1: " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "dbra %1,1b" \ + : "=a" (_buf), "=d" (_tmp) \ + : "a" (_port), "0" (_buf), \ + "1" (_tmp)); \ + } \ +}) + +#define raw_outsw(port, buf, nr) ({ \ + volatile unsigned char *_port = (volatile unsigned char *) (port); \ + unsigned char *_buf = (unsigned char *)(buf); \ + unsigned int _nr = (unsigned int)(nr); \ + unsigned long _tmp; \ + \ + if (_nr & 15) { \ + _tmp = (_nr & 15) - 1; \ + asm volatile ( \ + "1: movew %0@+,%2@; dbra %1,1b" \ + : "=a" (_buf), "=d" (_tmp) \ + : "a" (_port), "0" (_buf), \ + "1" (_tmp)); \ + } \ + if (_nr >> 4) { \ + _tmp = (_nr >> 4) - 1; \ + asm volatile ( \ + "1: " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "dbra %1,1b" \ + : "=a" (_buf), "=d" (_tmp) \ + : "a" (_port), "0" (_buf), \ + "1" (_tmp)); \ + } \ +}) + + +#define raw_insw_swapw(port, buf, nr) \ +({ if ((nr) % 8) \ + __asm__ __volatile__ \ + ("movel %0,%/a0; \ + movel %1,%/a1; \ + movel %2,%/d6; \ + subql #1,%/d6; \ + 1:movew %/a0@,%/d0; \ + rolw #8,%/d0; \ + movew %/d0,%/a1@+; \ + dbra %/d6,1b" \ + : \ + : "g" (port), "g" (buf), "g" (nr) \ + : "d0", "a0", "a1", "d6"); \ + else \ + __asm__ __volatile__ \ + ("movel %0,%/a0; \ + movel %1,%/a1; \ + movel %2,%/d6; \ + lsrl #3,%/d6; \ + subql #1,%/d6; \ + 1:movew %/a0@,%/d0; \ + rolw #8,%/d0; \ + movew %/d0,%/a1@+; \ + movew %/a0@,%/d0; \ + rolw #8,%/d0; \ + movew %/d0,%/a1@+; \ + movew %/a0@,%/d0; \ + rolw #8,%/d0; \ + movew %/d0,%/a1@+; \ + movew %/a0@,%/d0; \ + rolw #8,%/d0; \ + movew %/d0,%/a1@+; \ + movew %/a0@,%/d0; \ + rolw #8,%/d0; \ + movew %/d0,%/a1@+; \ + movew %/a0@,%/d0; \ + rolw #8,%/d0; \ + movew %/d0,%/a1@+; \ + movew %/a0@,%/d0; \ + rolw #8,%/d0; \ + movew %/d0,%/a1@+; \ + movew %/a0@,%/d0; \ + rolw #8,%/d0; \ + movew %/d0,%/a1@+; \ + dbra %/d6,1b" \ + : \ + : "g" (port), "g" (buf), "g" (nr) \ + : "d0", "a0", "a1", "d6"); \ +}) + + +#define raw_outsw_swapw(port, buf, nr) \ +({ if ((nr) % 8) \ + __asm__ __volatile__ \ + ("movel %0,%/a0; \ + movel %1,%/a1; \ + movel %2,%/d6; \ + subql #1,%/d6; \ + 1:movew %/a1@+,%/d0; \ + rolw #8,%/d0; \ + movew %/d0,%/a0@; \ + dbra %/d6,1b" \ + : \ + : "g" (port), "g" (buf), "g" (nr) \ + : "d0", "a0", "a1", "d6"); \ + else \ + __asm__ __volatile__ \ + ("movel %0,%/a0; \ + movel %1,%/a1; \ + movel %2,%/d6; \ + lsrl #3,%/d6; \ + subql #1,%/d6; \ + 1:movew %/a1@+,%/d0; \ + rolw #8,%/d0; \ + movew %/d0,%/a0@; \ + movew %/a1@+,%/d0; \ + rolw #8,%/d0; \ + movew %/d0,%/a0@; \ + movew %/a1@+,%/d0; \ + rolw #8,%/d0; \ + movew %/d0,%/a0@; \ + movew %/a1@+,%/d0; \ + rolw #8,%/d0; \ + movew %/d0,%/a0@; \ + movew %/a1@+,%/d0; \ + rolw #8,%/d0; \ + movew %/d0,%/a0@; \ + movew %/a1@+,%/d0; \ + rolw #8,%/d0; \ + movew %/d0,%/a0@; \ + movew %/a1@+,%/d0; \ + rolw #8,%/d0; \ + movew %/d0,%/a0@; \ + movew %/a1@+,%/d0; \ + rolw #8,%/d0; \ + movew %/d0,%/a0@; \ + dbra %/d6,1b" \ + : \ + : "g" (port), "g" (buf), "g" (nr) \ + : "d0", "a0", "a1", "d6"); \ +}) + + +#endif /* __KERNEL__ */ + +#endif /* _RAW_IO_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/rtc.h linux/include/asm-m68k/rtc.h --- v2.4.5/linux/include/asm-m68k/rtc.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-m68k/rtc.h Mon Jun 11 19:15:27 2001 @@ -0,0 +1,49 @@ +/* asm-m68k/rtc.h + * + * Copyright Richard Zidlicky + * implementation details for genrtc/q40rtc driver + */ +/* permission is hereby granted to copy, modify and redistribute this code + * in terms of the GNU Library General Public License, Version 2 or later, + * at your option. + */ + +#ifndef _ASM_RTC_H +#define _ASM_RTC_H + +#ifdef __KERNEL__ + +#include + +struct hwclk_time { + unsigned sec; /* 0..59 */ + unsigned min; /* 0..59 */ + unsigned hour; /* 0..23 */ + unsigned day; /* 1..31 */ + unsigned mon; /* 0..11 */ + unsigned year; /* 70... */ + int wday; /* 0..6, 0 is Sunday, -1 means unknown/don't set */ +}; + +/* a few implementation details for the emulation : */ + +extern unsigned gen_rtc_irq_flags; /* which sort(s) of interrupts caused int */ +extern unsigned gen_rtc_irq_ctrl; /* are enabled */ +extern short q40rtc_oldsecs; + +#define RTC_PIE 0x40 /* periodic interrupt enable */ +#define RTC_AIE 0x20 /* alarm interrupt enable */ +#define RTC_UIE 0x10 /* update-finished interrupt enable */ + +extern void gen_rtc_interrupt(unsigned long); + +/* some dummy definitions */ +#define RTC_SQWE 0x08 /* enable square-wave output */ +#define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */ +#define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */ +#define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */ + + +#endif /* __KERNEL__ */ + +#endif /* _ASM__RTC_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/sbus.h linux/include/asm-m68k/sbus.h --- v2.4.5/linux/include/asm-m68k/sbus.h Sat Sep 4 13:06:41 1999 +++ linux/include/asm-m68k/sbus.h Mon Jun 11 19:15:27 2001 @@ -17,4 +17,27 @@ #define ARCH_SUN4 0 +/* sbus IO functions stolen from include/asm-sparc/io.h for the serial driver */ +/* No SBUS on the Sun3, kludge -- sam */ + +extern inline void _sbus_writeb(unsigned char val, unsigned long addr) +{ + *(volatile unsigned char *)addr = val; +} + +extern inline unsigned char _sbus_readb(unsigned long addr) +{ + return *(volatile unsigned char *)addr; +} + +extern inline void _sbus_writel(unsigned long val, unsigned long addr) +{ + *(volatile unsigned long *)addr = val; + +} + +#define sbus_readb(a) _sbus_readb((unsigned long)a) +#define sbus_writeb(v, a) _sbus_writeb(v, (unsigned long)a) +#define sbus_writel(v, a) _sbus_writel(v, (unsigned long)a) + #endif diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/serial.h linux/include/asm-m68k/serial.h --- v2.4.5/linux/include/asm-m68k/serial.h Wed Apr 18 11:49:13 2001 +++ linux/include/asm-m68k/serial.h Mon Jun 11 19:15:27 2001 @@ -7,11 +7,6 @@ */ #include -#if 0 -#define rs_init serial_rs_init -#define register_serial serial_register_serial -#define unregister_serial serial_unregister_serial -#endif /* * This assumes you have a 1.8432 MHz clock for your UART. diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/socket.h linux/include/asm-m68k/socket.h --- v2.4.5/linux/include/asm-m68k/socket.h Sat Feb 3 11:26:44 2001 +++ linux/include/asm-m68k/socket.h Wed Jun 20 21:00:55 2001 @@ -58,6 +58,7 @@ /* level. For writing rarp and */ /* other similar things on the */ /* user level. */ +#define SOCK_MAX (SOCK_PACKET+1) #endif #endif /* _ASM_SOCKET_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/string.h linux/include/asm-m68k/string.h --- v2.4.5/linux/include/asm-m68k/string.h Thu Apr 27 15:55:09 2000 +++ linux/include/asm-m68k/string.h Mon Jun 11 19:15:27 2001 @@ -80,8 +80,9 @@ return( (char *) s); } +#if 0 #define __HAVE_ARCH_STRPBRK -static inline char * strpbrk(const char * cs,const char * ct) +extern inline char * strpbrk(const char * cs,const char * ct) { const char *sc1,*sc2; @@ -91,7 +92,9 @@ return((char *) sc1); return( NULL ); } +#endif +#if 0 #define __HAVE_ARCH_STRSPN static inline size_t strspn(const char *s, const char *accept) { @@ -112,9 +115,11 @@ return count; } +#endif +#if 0 #define __HAVE_ARCH_STRTOK -static inline char * strtok(char * s,const char * ct) +extern inline char * strtok(char * s,const char * ct) { char *sbegin, *send; @@ -133,6 +138,7 @@ ___strtok = send; return (sbegin); } +#endif /* strstr !! */ @@ -318,7 +324,7 @@ #ifdef CPU_M68040_OR_M68060_ONLY if (((unsigned long) s) & 0x0f) - memset(s, c, count); + __memset_g(s, c, count); else{ *((unsigned long *)(s))++ = data; *((unsigned long *)(s))++ = data; @@ -356,6 +362,8 @@ return xs; } +extern void *memset(void *,int,__kernel_size_t); + #define __memset_const(s,c,count) \ ((count==PAGE_SIZE) ? \ __memset_page((s),(c),(count)) : \ @@ -364,7 +372,7 @@ #define memset(s, c, count) \ (__builtin_constant_p(count) ? \ __memset_const((s),(c),(count)) : \ - memset((s),(c),(count))) + __memset_g((s),(c),(count))) #define __HAVE_ARCH_MEMCPY /* @@ -541,5 +549,15 @@ (__builtin_constant_p(n) ? \ __builtin_memcmp((cs),(ct),(n)) : \ memcmp((cs),(ct),(n))) + +#define __HAVE_ARCH_MEMCHR +extern inline void * memchr(const void * cs, int c, size_t count) { + /* Someone else can optimize this, I don't care - tonym@mac.linux-m68k.org */ + unsigned char *ret = (unsigned char *)cs; + for(;count>0;count--,ret++) + if(*ret == c) return ret; + + return NULL; +} #endif /* _M68K_STRING_H_ */ diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/sun3_pgalloc.h linux/include/asm-m68k/sun3_pgalloc.h --- v2.4.5/linux/include/asm-m68k/sun3_pgalloc.h Mon Apr 23 15:28:07 2001 +++ linux/include/asm-m68k/sun3_pgalloc.h Mon Jun 11 19:15:27 2001 @@ -74,46 +74,30 @@ return (pmd_t *) pgd; } +#define pmd_alloc_one_fast(mm, address) ({ BUG(); ((pmd_t *)1); }) +#define pmd_alloc_one(mm,address) ({ BUG(); ((pmd_t *)2); }) + extern inline void pte_free(pte_t * pte) { free_page((unsigned long) pte); } -extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address) -{ - address = (address >> (PAGE_SHIFT-2)) & 4*(PTRS_PER_PTE - 1); - -repeat: - if (pmd_none(*pmd)) - goto getnew; - if (pmd_bad(*pmd)) - goto fix; - return (pte_t *) (__pmd_page(*pmd) + address); - -getnew: +static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address) { unsigned long page = __get_free_page(GFP_KERNEL); - if (!pmd_none(*pmd)) - goto freenew; + if (!page) - goto oom; + return NULL; + memset((void *)page, 0, PAGE_SIZE); // pmd_val(*pmd) = SUN3_PMD_MAGIC + __pa(page); - pmd_val(*pmd) = __pa(page); - return (pte_t *) (page + address); -freenew: - free_page(page); - goto repeat; +/* pmd_val(*pmd) = __pa(page); */ + return (pte_t *) (page); } -fix: - printk(bad_pmd_string, pmd_val(*pmd)); - printk("in normal pgd offset %08x\n", (unsigned int)pmd); -oom: -// pmd_val(*pmd) = SUN3_PMD_MAGIC + __pa(BAD_PAGETABLE); - pmd_val(*pmd) = __pa(BAD_PAGETABLE); - return NULL; -} +#define pte_alloc_one_fast(mm,addr) pte_alloc_one(mm,addr) + +#define pmd_populate(mm, pmd, pte) (pmd_val(*pmd) = __pa((unsigned long)pte)) /* * allocating and freeing a pmd is trivial: the 1-entry pmd is @@ -124,11 +108,6 @@ pmd_val(*pmd) = 0; } -extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address) -{ - return (pmd_t *) pgd; -} - extern inline void pgd_free(pgd_t * pgd) { free_page((unsigned long) pgd); @@ -143,6 +122,8 @@ memset(new_pgd, 0, (PAGE_OFFSET >> PGDIR_SHIFT)); return new_pgd; } + +#define pgd_populate(mm, pmd, pte) BUG() /* FIXME: the sun3 doesn't have a page table cache! (but the motorola routine should just return 0) */ diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/sun3_pgtable.h linux/include/asm-m68k/sun3_pgtable.h --- v2.4.5/linux/include/asm-m68k/sun3_pgtable.h Mon Nov 27 18:00:49 2000 +++ linux/include/asm-m68k/sun3_pgtable.h Mon Jun 11 19:15:27 2001 @@ -135,12 +135,13 @@ extern inline int pmd_bad2 (pmd_t *pmd) { return 0; } #define pmd_bad(pmd) pmd_bad2(&(pmd)) extern inline int pmd_present2 (pmd_t *pmd) { return pmd_val (*pmd) & SUN3_PMD_VALID; } -#define pmd_present(pmd) pmd_present2(&(pmd)) +/* #define pmd_present(pmd) pmd_present2(&(pmd)) */ +#define pmd_present(pmd) (!pmd_none2(&(pmd))) extern inline void pmd_clear (pmd_t *pmdp) { pmd_val (*pmdp) = 0; } extern inline int pgd_none (pgd_t pgd) { return 0; } extern inline int pgd_bad (pgd_t pgd) { return 0; } -extern inline int pgd_present (pgd_t pgd) { return 0; } +extern inline int pgd_present (pgd_t pgd) { return 1; } extern inline void pgd_clear (pgd_t *pgdp) {} diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/sun3ints.h linux/include/asm-m68k/sun3ints.h --- v2.4.5/linux/include/asm-m68k/sun3ints.h Fri Nov 12 04:29:47 1999 +++ linux/include/asm-m68k/sun3ints.h Mon Jun 11 19:15:27 2001 @@ -26,5 +26,15 @@ void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id ); +extern void sun3_init_IRQ (void); +extern void (*sun3_default_handler[]) (int, void *, struct pt_regs *); +extern void (*sun3_inthandler[]) (int, void *, struct pt_regs *); +extern void sun3_free_irq (unsigned int irq, void *dev_id); +extern void sun3_enable_interrupts (void); +extern void sun3_disable_interrupts (void); +extern int sun3_get_irq_list(char *buf); +extern void sun3_process_int(int, struct pt_regs *); +extern volatile unsigned char* sun3_intreg; + #endif /* SUN3INTS_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/sun3x.h linux/include/asm-m68k/sun3x.h --- v2.4.5/linux/include/asm-m68k/sun3x.h Tue May 11 09:57:14 1999 +++ linux/include/asm-m68k/sun3x.h Mon Jun 11 19:15:27 2001 @@ -15,6 +15,9 @@ #define SUN3X_VIDEO_P4ID 0x50300000 #define SUN3X_ESP_BASE 0x66000000 #define SUN3X_ESP_DMA 0x66001000 +#define SUN3X_FDC 0x6e000000 +#define SUN3X_FDC_FCR 0x6e000400 +#define SUN3X_FDC_FVR 0x6e000800 /* some NVRAM addresses */ #define SUN3X_EEPROM_CONS (SUN3X_EEPROM + 0x1f) diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/sun3xflop.h linux/include/asm-m68k/sun3xflop.h --- v2.4.5/linux/include/asm-m68k/sun3xflop.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-m68k/sun3xflop.h Mon Jun 11 19:15:27 2001 @@ -0,0 +1,263 @@ +/* sun3xflop.h: Sun3/80 specific parts of the floppy driver. + * + * Derived partially from asm-sparc/floppy.h, which is: + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + * + * Sun3x version 2/4/2000 Sam Creasey (sammy@oh.verio.com) + */ + +#ifndef __ASM_SUN3X_FLOPPY_H +#define __ASM_SUN3X_FLOPPY_H + +#include +#include +#include +#include +#include + +/* default interrupt vector */ +#define SUN3X_FDC_IRQ 0x40 + +/* some constants */ +#define FCR_TC 0x1 +#define FCR_EJECT 0x2 +#define FCR_MTRON 0x4 +#define FCR_DSEL1 0x8 +#define FCR_DSEL0 0x10 + +/* We don't need no stinkin' I/O port allocation crap. */ +#undef release_region +#undef check_region +#undef request_region +#define release_region(X, Y) do { } while(0) +#define check_region(X, Y) (0) +#define request_region(X, Y, Z) (1) + +struct sun3xflop_private { + volatile unsigned char *status_r; + volatile unsigned char *data_r; + volatile unsigned char *fcr_r; + volatile unsigned char *fvr_r; + unsigned char fcr; +} sun3x_fdc; + +/* Super paranoid... */ +#undef HAVE_DISABLE_HLT + +/* Routines unique to each controller type on a Sun. */ +static unsigned char sun3x_82072_fd_inb(int port) +{ + static int once = 0; +// udelay(5); + switch(port & 7) { + default: + printk("floppy: Asked to read unknown port %d\n", port); + panic("floppy: Port bolixed."); + case 4: /* FD_STATUS */ + return (*sun3x_fdc.status_r) & ~STATUS_DMA; + case 5: /* FD_DATA */ + return (*sun3x_fdc.data_r); + case 7: /* FD_DIR */ + /* ugly hack, I can't find a way to actually detect the disk */ + if(!once) { + once = 1; + return 0x80; + } + return 0; + }; + panic("sun_82072_fd_inb: How did I get here?"); +} + +static void sun3x_82072_fd_outb(unsigned char value, int port) +{ +// udelay(5); + switch(port & 7) { + default: + printk("floppy: Asked to write to unknown port %d\n", port); + panic("floppy: Port bolixed."); + case 2: /* FD_DOR */ + /* Oh geese, 82072 on the Sun has no DOR register, + * so we make do with taunting the FCR. + * + * ASSUMPTIONS: There will only ever be one floppy + * drive attached to a Sun controller + * and it will be at drive zero. + */ + + { + unsigned char fcr = sun3x_fdc.fcr; + + if(value & 0x10) { + fcr |= (FCR_DSEL0 | FCR_MTRON); + } else + fcr &= ~(FCR_DSEL0 | FCR_MTRON); + + + if(fcr != sun3x_fdc.fcr) { + *(sun3x_fdc.fcr_r) = fcr; + sun3x_fdc.fcr = fcr; + } + } + break; + case 5: /* FD_DATA */ + *(sun3x_fdc.data_r) = value; + break; + case 7: /* FD_DCR */ + *(sun3x_fdc.status_r) = value; + break; + case 4: /* FD_STATUS */ + *(sun3x_fdc.status_r) = value; + break; + }; + return; +} + + +asmlinkage void sun3xflop_hardint(int irq, void *dev_id, struct pt_regs * regs) +{ + register unsigned char st; + +#undef TRACE_FLPY_INT +#define NO_FLOPPY_ASSEMBLER + +#ifdef TRACE_FLPY_INT + static int calls=0; + static int bytes=0; + static int dma_wait=0; +#endif + if(!doing_pdma) { + floppy_interrupt(irq, dev_id, regs); + return; + } + +// printk("doing pdma\n");// st %x\n", sun_fdc->status_82072); + +#ifdef TRACE_FLPY_INT + if(!calls) + bytes = virtual_dma_count; +#endif + + { + register int lcount; + register char *lptr; + + for(lcount=virtual_dma_count, lptr=virtual_dma_addr; + lcount; lcount--, lptr++) { +// st=fd_inb(virtual_dma_port+4) & 0x80 ; + st = *(sun3x_fdc.status_r); +// if(st != 0xa0) +// break; + + if((st & 0x80) == 0) { + virtual_dma_count = lcount; + virtual_dma_addr = lptr; + return; + } + + if((st & 0x20) == 0) + break; + + if(virtual_dma_mode) +// fd_outb(*lptr, virtual_dma_port+5); + *(sun3x_fdc.data_r) = *lptr; + else +// *lptr = fd_inb(virtual_dma_port+5); + *lptr = *(sun3x_fdc.data_r); + } + + virtual_dma_count = lcount; + virtual_dma_addr = lptr; +// st = fd_inb(virtual_dma_port+4); + st = *(sun3x_fdc.status_r); + } + +#ifdef TRACE_FLPY_INT + calls++; +#endif +// printk("st=%02x\n", st); + if(st == 0x20) + return; + if(!(st & 0x20)) { + virtual_dma_residue += virtual_dma_count; + virtual_dma_count=0; + doing_pdma = 0; + +#ifdef TRACE_FLPY_INT + printk("count=%x, residue=%x calls=%d bytes=%x dma_wait=%d\n", + virtual_dma_count, virtual_dma_residue, calls, bytes, + dma_wait); + calls = 0; + dma_wait=0; +#endif + + floppy_interrupt(irq, dev_id, regs); + return; + } + + +#ifdef TRACE_FLPY_INT + if(!virtual_dma_count) + dma_wait++; +#endif +} + +static int sun3xflop_request_irq(void) +{ + static int once = 0; + int error; + + if(!once) { + once = 1; + error = request_irq(FLOPPY_IRQ, sun3xflop_hardint, SA_INTERRUPT, "floppy", 0); + return ((error == 0) ? 0 : -1); + } else return 0; +} + +static void __init floppy_set_flags(int *ints,int param, int param2); + +static int sun3xflop_init(void) +{ + if(FLOPPY_IRQ < 0x40) + FLOPPY_IRQ = SUN3X_FDC_IRQ; + + sun3x_fdc.status_r = (volatile unsigned char *)SUN3X_FDC; + sun3x_fdc.data_r = (volatile unsigned char *)(SUN3X_FDC+1); + sun3x_fdc.fcr_r = (volatile unsigned char *)SUN3X_FDC_FCR; + sun3x_fdc.fvr_r = (volatile unsigned char *)SUN3X_FDC_FVR; + sun3x_fdc.fcr = 0; + + /* Last minute sanity check... */ + if(*sun3x_fdc.status_r == 0xff) { + return -1; + } + + *sun3x_fdc.fvr_r = FLOPPY_IRQ; + + *sun3x_fdc.fcr_r = FCR_TC; + udelay(10); + *sun3x_fdc.fcr_r = 0; + + /* Success... */ + floppy_set_flags(0, 1, FD_BROKEN_DCL); // I don't know how to detect this. + allowed_drive_mask = 0x01; + return (int) SUN3X_FDC; +} + +/* I'm not precisely sure this eject routine works */ +static int sun3x_eject(void) +{ + if(MACH_IS_SUN3X) { + + sun3x_fdc.fcr |= (FCR_DSEL0 | FCR_EJECT); + *(sun3x_fdc.fcr_r) = sun3x_fdc.fcr; + udelay(10); + sun3x_fdc.fcr &= ~(FCR_DSEL0 | FCR_EJECT); + *(sun3x_fdc.fcr_r) = sun3x_fdc.fcr; + } + + return 0; +} + +#define fd_eject(drive) sun3x_eject() + +#endif /* !(__ASM_SUN3X_FLOPPY_H) */ diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/sun3xprom.h linux/include/asm-m68k/sun3xprom.h --- v2.4.5/linux/include/asm-m68k/sun3xprom.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-m68k/sun3xprom.h Mon Jun 11 19:15:27 2001 @@ -0,0 +1,43 @@ +/* Useful PROM locations */ + +#ifndef SUN3X_PROM_H +#define SUN3X_PROM_H + +extern void (*sun3x_putchar)(int); +extern int (*sun3x_getchar)(void); +extern int (*sun3x_mayget)(void); +extern int (*sun3x_mayput)(int); + +void sun3x_reboot(void); +void sun3x_abort(void); +void sun3x_prom_init(void); +unsigned long sun3x_prom_ptov(unsigned long pa, unsigned long size); + +/* interesting hardware locations */ +#define SUN3X_IOMMU 0x60000000 +#define SUN3X_ENAREG 0x61000000 +#define SUN3X_INTREG 0x61001400 +#define SUN3X_DIAGREG 0x61001800 +#define SUN3X_ZS1 0x62000000 +#define SUN3X_ZS2 0x62002000 +#define SUN3X_LANCE 0x65002000 +#define SUN3X_EEPROM 0x64000000 +#define SUN3X_IDPROM 0x640007d8 +#define SUN3X_VIDEO_BASE 0x50400000 +#define SUN3X_VIDEO_REGS 0x50300000 + +/* vector table */ +#define SUN3X_PROM_BASE 0xfefe0000 +#define SUN3X_P_GETCHAR (SUN3X_PROM_BASE + 20) +#define SUN3X_P_PUTCHAR (SUN3X_PROM_BASE + 24) +#define SUN3X_P_MAYGET (SUN3X_PROM_BASE + 28) +#define SUN3X_P_MAYPUT (SUN3X_PROM_BASE + 32) +#define SUN3X_P_REBOOT (SUN3X_PROM_BASE + 96) +#define SUN3X_P_SETLEDS (SUN3X_PROM_BASE + 144) +#define SUN3X_P_ABORT (SUN3X_PROM_BASE + 152) + +/* mapped area */ +#define SUN3X_MAP_START 0xfee00000 +#define SUN3X_MAP_END 0xff000000 + +#endif diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/system.h linux/include/asm-m68k/system.h --- v2.4.5/linux/include/asm-m68k/system.h Mon Nov 27 18:00:49 2000 +++ linux/include/asm-m68k/system.h Mon Jun 11 19:15:27 2001 @@ -52,9 +52,9 @@ #define __sti() asm volatile ("andiw %0,%%sr": : "i" (ALLOWINT) : "memory") #else #include -#define __sti() ({ \ - if (!local_irq_count(smp_processor_id())) \ - asm volatile ("andiw %0,%%sr": : "i" (ALLOWINT) : "memory"); \ +#define __sti() ({ \ + if (MACH_IS_Q40 || !local_irq_count(smp_processor_id())) \ + asm volatile ("andiw %0,%%sr": : "i" (ALLOWINT) : "memory"); \ }) #endif #define __cli() asm volatile ("oriw #0x0700,%%sr": : : "memory") diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/termios.h linux/include/asm-m68k/termios.h --- v2.4.5/linux/include/asm-m68k/termios.h Sat Feb 3 20:00:45 2001 +++ linux/include/asm-m68k/termios.h Mon Jun 11 19:15:27 2001 @@ -65,6 +65,7 @@ #define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */ #define N_HDLC 13 /* synchronous HDLC */ #define N_SYNC_PPP 14 +#define N_HCI 15 /* Bluetooth HCI UART */ #ifdef __KERNEL__ diff -u --recursive --new-file v2.4.5/linux/include/asm-m68k/zorro.h linux/include/asm-m68k/zorro.h --- v2.4.5/linux/include/asm-m68k/zorro.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-m68k/zorro.h Mon Jun 11 19:15:27 2001 @@ -0,0 +1,18 @@ +#ifndef _ASM_ZORRO_H +#define _ASM_ZORRO_H +#include + +#define z_readb raw_inb +#define z_readw raw_inw +#define z_readl raw_inl + +#define z_writeb raw_outb +#define z_writew raw_outw +#define z_writel raw_outl + +#define z_memset_io(a,b,c) memset((void *)(a),(b),(c)) +#define z_memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c)) +#define z_memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c)) + + +#endif /* _ASM_ZORRO_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/addrspace.h linux/include/asm-mips/addrspace.h --- v2.4.5/linux/include/asm-mips/addrspace.h Thu Jun 26 12:33:39 1997 +++ linux/include/asm-mips/addrspace.h Mon Jul 2 13:56:40 2001 @@ -4,6 +4,7 @@ * for more details. * * Copyright (C) 1996 by Ralf Baechle + * Copyright (C) 2000 by Maciej W. Rozycki * * Defitions for the address spaces of the MIPS CPUs. */ @@ -19,23 +20,40 @@ #define KSEG2 0xc0000000 #define KSEG3 0xe0000000 +#define K0BASE KSEG0 + /* * Returns the kernel segment base of a given address */ +#ifndef __ASSEMBLY__ #define KSEGX(a) (((unsigned long)(a)) & 0xe0000000) +#else +#define KSEGX(a) ((a) & 0xe0000000) +#endif /* * Returns the physical address of a KSEG0/KSEG1 address */ +#ifndef __ASSEMBLY__ #define PHYSADDR(a) (((unsigned long)(a)) & 0x1fffffff) +#else +#define PHYSADDR(a) ((a) & 0x1fffffff) +#endif /* * Map an address to a certain kernel segment */ +#ifndef __ASSEMBLY__ #define KSEG0ADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG0)) #define KSEG1ADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG1)) #define KSEG2ADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG2)) #define KSEG3ADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG3)) +#else +#define KSEG0ADDR(a) (((a) & 0x1fffffff) | KSEG0) +#define KSEG1ADDR(a) (((a) & 0x1fffffff) | KSEG1) +#define KSEG2ADDR(a) (((a) & 0x1fffffff) | KSEG2) +#define KSEG3ADDR(a) (((a) & 0x1fffffff) | KSEG3) +#endif /* * Memory segments (64bit kernel mode addresses) diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/asmmacro.h linux/include/asm-mips/asmmacro.h --- v2.4.5/linux/include/asm-mips/asmmacro.h Sat May 13 08:31:25 2000 +++ linux/include/asm-mips/asmmacro.h Mon Jul 2 13:56:40 2001 @@ -3,124 +3,122 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * Copyright (C) 1998 Ralf Baechle - * - * $Id: asmmacro.h,v 1.3 1998/03/27 04:47:58 ralf Exp $ */ -#ifndef __MIPS_ASMMACRO_H -#define __MIPS_ASMMACRO_H +#ifndef _ASM_ASMMACRO_H +#define _ASM_ASMMACRO_H #include #define FPU_SAVE_DOUBLE(thread, tmp) \ cfc1 tmp, fcr31; \ sdc1 $f0, (THREAD_FPU + 0x000)(thread); \ - sdc1 $f2, (THREAD_FPU + 0x008)(thread); \ - sdc1 $f4, (THREAD_FPU + 0x010)(thread); \ - sdc1 $f6, (THREAD_FPU + 0x018)(thread); \ - sdc1 $f8, (THREAD_FPU + 0x020)(thread); \ - sdc1 $f10, (THREAD_FPU + 0x028)(thread); \ - sdc1 $f12, (THREAD_FPU + 0x030)(thread); \ - sdc1 $f14, (THREAD_FPU + 0x038)(thread); \ - sdc1 $f16, (THREAD_FPU + 0x040)(thread); \ - sdc1 $f18, (THREAD_FPU + 0x048)(thread); \ - sdc1 $f20, (THREAD_FPU + 0x050)(thread); \ - sdc1 $f22, (THREAD_FPU + 0x058)(thread); \ - sdc1 $f24, (THREAD_FPU + 0x060)(thread); \ - sdc1 $f26, (THREAD_FPU + 0x068)(thread); \ - sdc1 $f28, (THREAD_FPU + 0x070)(thread); \ - sdc1 $f30, (THREAD_FPU + 0x078)(thread); \ - sw tmp, (THREAD_FPU + 0x080)(thread) + sdc1 $f2, (THREAD_FPU + 0x010)(thread); \ + sdc1 $f4, (THREAD_FPU + 0x020)(thread); \ + sdc1 $f6, (THREAD_FPU + 0x030)(thread); \ + sdc1 $f8, (THREAD_FPU + 0x040)(thread); \ + sdc1 $f10, (THREAD_FPU + 0x050)(thread); \ + sdc1 $f12, (THREAD_FPU + 0x060)(thread); \ + sdc1 $f14, (THREAD_FPU + 0x070)(thread); \ + sdc1 $f16, (THREAD_FPU + 0x080)(thread); \ + sdc1 $f18, (THREAD_FPU + 0x090)(thread); \ + sdc1 $f20, (THREAD_FPU + 0x0a0)(thread); \ + sdc1 $f22, (THREAD_FPU + 0x0b0)(thread); \ + sdc1 $f24, (THREAD_FPU + 0x0c0)(thread); \ + sdc1 $f26, (THREAD_FPU + 0x0d0)(thread); \ + sdc1 $f28, (THREAD_FPU + 0x0e0)(thread); \ + sdc1 $f30, (THREAD_FPU + 0x0f0)(thread); \ + sw tmp, (THREAD_FPU + 0x100)(thread) #define FPU_SAVE_SINGLE(thread,tmp) \ cfc1 tmp, fcr31; \ swc1 $f0, (THREAD_FPU + 0x000)(thread); \ - swc1 $f1, (THREAD_FPU + 0x004)(thread); \ - swc1 $f2, (THREAD_FPU + 0x008)(thread); \ - swc1 $f3, (THREAD_FPU + 0x00c)(thread); \ - swc1 $f4, (THREAD_FPU + 0x010)(thread); \ - swc1 $f5, (THREAD_FPU + 0x014)(thread); \ - swc1 $f6, (THREAD_FPU + 0x018)(thread); \ - swc1 $f7, (THREAD_FPU + 0x01c)(thread); \ - swc1 $f8, (THREAD_FPU + 0x020)(thread); \ - swc1 $f9, (THREAD_FPU + 0x024)(thread); \ - swc1 $f10, (THREAD_FPU + 0x028)(thread); \ - swc1 $f11, (THREAD_FPU + 0x02c)(thread); \ - swc1 $f12, (THREAD_FPU + 0x030)(thread); \ - swc1 $f13, (THREAD_FPU + 0x034)(thread); \ - swc1 $f14, (THREAD_FPU + 0x038)(thread); \ - swc1 $f15, (THREAD_FPU + 0x03c)(thread); \ - swc1 $f16, (THREAD_FPU + 0x040)(thread); \ - swc1 $f17, (THREAD_FPU + 0x044)(thread); \ - swc1 $f18, (THREAD_FPU + 0x048)(thread); \ - swc1 $f19, (THREAD_FPU + 0x04c)(thread); \ - swc1 $f20, (THREAD_FPU + 0x050)(thread); \ - swc1 $f21, (THREAD_FPU + 0x054)(thread); \ - swc1 $f22, (THREAD_FPU + 0x058)(thread); \ - swc1 $f23, (THREAD_FPU + 0x05c)(thread); \ - swc1 $f24, (THREAD_FPU + 0x060)(thread); \ - swc1 $f25, (THREAD_FPU + 0x064)(thread); \ - swc1 $f26, (THREAD_FPU + 0x068)(thread); \ - swc1 $f27, (THREAD_FPU + 0x06c)(thread); \ - swc1 $f28, (THREAD_FPU + 0x070)(thread); \ - swc1 $f29, (THREAD_FPU + 0x074)(thread); \ - swc1 $f30, (THREAD_FPU + 0x078)(thread); \ - swc1 $f31, (THREAD_FPU + 0x07c)(thread); \ - sw tmp, (THREAD_FPU + 0x080)(thread) + swc1 $f1, (THREAD_FPU + 0x008)(thread); \ + swc1 $f2, (THREAD_FPU + 0x010)(thread); \ + swc1 $f3, (THREAD_FPU + 0x018)(thread); \ + swc1 $f4, (THREAD_FPU + 0x020)(thread); \ + swc1 $f5, (THREAD_FPU + 0x028)(thread); \ + swc1 $f6, (THREAD_FPU + 0x030)(thread); \ + swc1 $f7, (THREAD_FPU + 0x038)(thread); \ + swc1 $f8, (THREAD_FPU + 0x040)(thread); \ + swc1 $f9, (THREAD_FPU + 0x048)(thread); \ + swc1 $f10, (THREAD_FPU + 0x050)(thread); \ + swc1 $f11, (THREAD_FPU + 0x058)(thread); \ + swc1 $f12, (THREAD_FPU + 0x060)(thread); \ + swc1 $f13, (THREAD_FPU + 0x068)(thread); \ + swc1 $f14, (THREAD_FPU + 0x070)(thread); \ + swc1 $f15, (THREAD_FPU + 0x078)(thread); \ + swc1 $f16, (THREAD_FPU + 0x080)(thread); \ + swc1 $f17, (THREAD_FPU + 0x088)(thread); \ + swc1 $f18, (THREAD_FPU + 0x090)(thread); \ + swc1 $f19, (THREAD_FPU + 0x098)(thread); \ + swc1 $f20, (THREAD_FPU + 0x0a0)(thread); \ + swc1 $f21, (THREAD_FPU + 0x0a8)(thread); \ + swc1 $f22, (THREAD_FPU + 0x0b0)(thread); \ + swc1 $f23, (THREAD_FPU + 0x0b8)(thread); \ + swc1 $f24, (THREAD_FPU + 0x0c0)(thread); \ + swc1 $f25, (THREAD_FPU + 0x0c8)(thread); \ + swc1 $f26, (THREAD_FPU + 0x0d0)(thread); \ + swc1 $f27, (THREAD_FPU + 0x0d8)(thread); \ + swc1 $f28, (THREAD_FPU + 0x0e0)(thread); \ + swc1 $f29, (THREAD_FPU + 0x0e8)(thread); \ + swc1 $f30, (THREAD_FPU + 0x0f0)(thread); \ + swc1 $f31, (THREAD_FPU + 0x0f8)(thread); \ + sw tmp, (THREAD_FPU + 0x100)(thread) #define FPU_RESTORE_DOUBLE(thread, tmp) \ - lw tmp, (THREAD_FPU + 0x080)(thread); \ + lw tmp, (THREAD_FPU + 0x100)(thread); \ ldc1 $f0, (THREAD_FPU + 0x000)(thread); \ - ldc1 $f2, (THREAD_FPU + 0x008)(thread); \ - ldc1 $f4, (THREAD_FPU + 0x010)(thread); \ - ldc1 $f6, (THREAD_FPU + 0x018)(thread); \ - ldc1 $f8, (THREAD_FPU + 0x020)(thread); \ - ldc1 $f10, (THREAD_FPU + 0x028)(thread); \ - ldc1 $f12, (THREAD_FPU + 0x030)(thread); \ - ldc1 $f14, (THREAD_FPU + 0x038)(thread); \ - ldc1 $f16, (THREAD_FPU + 0x040)(thread); \ - ldc1 $f18, (THREAD_FPU + 0x048)(thread); \ - ldc1 $f20, (THREAD_FPU + 0x050)(thread); \ - ldc1 $f22, (THREAD_FPU + 0x058)(thread); \ - ldc1 $f24, (THREAD_FPU + 0x060)(thread); \ - ldc1 $f26, (THREAD_FPU + 0x068)(thread); \ - ldc1 $f28, (THREAD_FPU + 0x070)(thread); \ - ldc1 $f30, (THREAD_FPU + 0x078)(thread); \ + ldc1 $f2, (THREAD_FPU + 0x010)(thread); \ + ldc1 $f4, (THREAD_FPU + 0x020)(thread); \ + ldc1 $f6, (THREAD_FPU + 0x030)(thread); \ + ldc1 $f8, (THREAD_FPU + 0x040)(thread); \ + ldc1 $f10, (THREAD_FPU + 0x050)(thread); \ + ldc1 $f12, (THREAD_FPU + 0x060)(thread); \ + ldc1 $f14, (THREAD_FPU + 0x070)(thread); \ + ldc1 $f16, (THREAD_FPU + 0x080)(thread); \ + ldc1 $f18, (THREAD_FPU + 0x090)(thread); \ + ldc1 $f20, (THREAD_FPU + 0x0a0)(thread); \ + ldc1 $f22, (THREAD_FPU + 0x0b0)(thread); \ + ldc1 $f24, (THREAD_FPU + 0x0c0)(thread); \ + ldc1 $f26, (THREAD_FPU + 0x0d0)(thread); \ + ldc1 $f28, (THREAD_FPU + 0x0e0)(thread); \ + ldc1 $f30, (THREAD_FPU + 0x0f0)(thread); \ ctc1 tmp, fcr31 #define FPU_RESTORE_SINGLE(thread,tmp) \ - lw tmp, (THREAD_FPU + 0x080)(thread); \ + lw tmp, (THREAD_FPU + 0x100)(thread); \ lwc1 $f0, (THREAD_FPU + 0x000)(thread); \ - lwc1 $f1, (THREAD_FPU + 0x004)(thread); \ - lwc1 $f2, (THREAD_FPU + 0x008)(thread); \ - lwc1 $f3, (THREAD_FPU + 0x00c)(thread); \ - lwc1 $f4, (THREAD_FPU + 0x010)(thread); \ - lwc1 $f5, (THREAD_FPU + 0x014)(thread); \ - lwc1 $f6, (THREAD_FPU + 0x018)(thread); \ - lwc1 $f7, (THREAD_FPU + 0x01c)(thread); \ - lwc1 $f8, (THREAD_FPU + 0x020)(thread); \ - lwc1 $f9, (THREAD_FPU + 0x024)(thread); \ - lwc1 $f10, (THREAD_FPU + 0x028)(thread); \ - lwc1 $f11, (THREAD_FPU + 0x02c)(thread); \ - lwc1 $f12, (THREAD_FPU + 0x030)(thread); \ - lwc1 $f13, (THREAD_FPU + 0x034)(thread); \ - lwc1 $f14, (THREAD_FPU + 0x038)(thread); \ - lwc1 $f15, (THREAD_FPU + 0x03c)(thread); \ - lwc1 $f16, (THREAD_FPU + 0x040)(thread); \ - lwc1 $f17, (THREAD_FPU + 0x044)(thread); \ - lwc1 $f18, (THREAD_FPU + 0x048)(thread); \ - lwc1 $f19, (THREAD_FPU + 0x04c)(thread); \ - lwc1 $f20, (THREAD_FPU + 0x050)(thread); \ - lwc1 $f21, (THREAD_FPU + 0x054)(thread); \ - lwc1 $f22, (THREAD_FPU + 0x058)(thread); \ - lwc1 $f23, (THREAD_FPU + 0x05c)(thread); \ - lwc1 $f24, (THREAD_FPU + 0x060)(thread); \ - lwc1 $f25, (THREAD_FPU + 0x064)(thread); \ - lwc1 $f26, (THREAD_FPU + 0x068)(thread); \ - lwc1 $f27, (THREAD_FPU + 0x06c)(thread); \ - lwc1 $f28, (THREAD_FPU + 0x070)(thread); \ - lwc1 $f29, (THREAD_FPU + 0x074)(thread); \ - lwc1 $f30, (THREAD_FPU + 0x078)(thread); \ - lwc1 $f31, (THREAD_FPU + 0x07c)(thread); \ + lwc1 $f1, (THREAD_FPU + 0x008)(thread); \ + lwc1 $f2, (THREAD_FPU + 0x010)(thread); \ + lwc1 $f3, (THREAD_FPU + 0x018)(thread); \ + lwc1 $f4, (THREAD_FPU + 0x020)(thread); \ + lwc1 $f5, (THREAD_FPU + 0x028)(thread); \ + lwc1 $f6, (THREAD_FPU + 0x030)(thread); \ + lwc1 $f7, (THREAD_FPU + 0x038)(thread); \ + lwc1 $f8, (THREAD_FPU + 0x040)(thread); \ + lwc1 $f9, (THREAD_FPU + 0x048)(thread); \ + lwc1 $f10, (THREAD_FPU + 0x050)(thread); \ + lwc1 $f11, (THREAD_FPU + 0x058)(thread); \ + lwc1 $f12, (THREAD_FPU + 0x060)(thread); \ + lwc1 $f13, (THREAD_FPU + 0x068)(thread); \ + lwc1 $f14, (THREAD_FPU + 0x070)(thread); \ + lwc1 $f15, (THREAD_FPU + 0x078)(thread); \ + lwc1 $f16, (THREAD_FPU + 0x080)(thread); \ + lwc1 $f17, (THREAD_FPU + 0x088)(thread); \ + lwc1 $f18, (THREAD_FPU + 0x090)(thread); \ + lwc1 $f19, (THREAD_FPU + 0x098)(thread); \ + lwc1 $f20, (THREAD_FPU + 0x0a0)(thread); \ + lwc1 $f21, (THREAD_FPU + 0x0a8)(thread); \ + lwc1 $f22, (THREAD_FPU + 0x0b0)(thread); \ + lwc1 $f23, (THREAD_FPU + 0x0b8)(thread); \ + lwc1 $f24, (THREAD_FPU + 0x0c0)(thread); \ + lwc1 $f25, (THREAD_FPU + 0x0c8)(thread); \ + lwc1 $f26, (THREAD_FPU + 0x0d0)(thread); \ + lwc1 $f27, (THREAD_FPU + 0x0d8)(thread); \ + lwc1 $f28, (THREAD_FPU + 0x0e0)(thread); \ + lwc1 $f29, (THREAD_FPU + 0x0e8)(thread); \ + lwc1 $f30, (THREAD_FPU + 0x0f0)(thread); \ + lwc1 $f31, (THREAD_FPU + 0x0f8)(thread); \ ctc1 tmp, fcr31 #define CPU_SAVE_NONSCRATCH(thread) \ @@ -148,4 +146,4 @@ lw fp, THREAD_REG30(thread); \ lw ra, THREAD_REG31(thread) -#endif /* !(__MIPS_ASMMACRO_H) */ +#endif /* _ASM_ASMMACRO_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/atomic.h linux/include/asm-mips/atomic.h --- v2.4.5/linux/include/asm-mips/atomic.h Sat May 13 08:31:25 2000 +++ linux/include/asm-mips/atomic.h Mon Jul 2 13:56:40 2001 @@ -9,25 +9,35 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1996, 1997 by Ralf Baechle - * - * $Id: atomic.h,v 1.6 1999/07/26 19:42:42 harald Exp $ + * Copyright (C) 1996, 1997, 2000 by Ralf Baechle */ #ifndef __ASM_ATOMIC_H #define __ASM_ATOMIC_H #include -#ifdef CONFIG_SMP typedef struct { volatile int counter; } atomic_t; -#else -typedef struct { int counter; } atomic_t; -#endif #ifdef __KERNEL__ #define ATOMIC_INIT(i) { (i) } +/* + * atomic_read - read atomic variable + * @v: pointer of type atomic_t + * + * Atomically reads the value of @v. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ #define atomic_read(v) ((v)->counter) + +/* + * atomic_set - set atomic variable + * @v: pointer of type atomic_t + * @i: required value + * + * Atomically sets the value of @v to @i. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ #define atomic_set(v,i) ((v)->counter = (i)) #if !defined(CONFIG_CPU_HAS_LLSC) @@ -37,8 +47,15 @@ /* * The MIPS I implementation is only atomic with respect to * interrupts. R3000 based multiprocessor machines are rare anyway ... + * + * atomic_add - add integer to atomic variable + * @i: integer value to add + * @v: pointer of type atomic_t + * + * Atomically adds @i to @v. Note that the guaranteed useful range + * of an atomic_t is only 24 bits. */ -extern __inline__ void atomic_add(int i, volatile atomic_t * v) +extern __inline__ void atomic_add(int i, atomic_t * v) { int flags; @@ -48,7 +65,15 @@ restore_flags(flags); } -extern __inline__ void atomic_sub(int i, volatile atomic_t * v) +/* + * atomic_sub - subtract the atomic variable + * @i: integer value to subtract + * @v: pointer of type atomic_t + * + * Atomically subtracts @i from @v. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +extern __inline__ void atomic_sub(int i, atomic_t * v) { int flags; @@ -86,21 +111,6 @@ return temp; } -extern __inline__ void atomic_clear_mask(unsigned long mask, unsigned long * v) -{ - unsigned long temp; - int flags; - - save_flags(flags); - cli(); - temp = *v; - temp &= ~mask; - *v = temp; - restore_flags(flags); - - return; -} - #else /* @@ -109,40 +119,45 @@ */ /* - * Make sure gcc doesn't try to be clever and move things around - * on us. We need to use _exactly_ the address the user gave us, - * not some alias that contains the same information. + * atomic_add - add integer to atomic variable + * @i: integer value to add + * @v: pointer of type atomic_t + * + * Atomically adds @i to @v. Note that the guaranteed useful range + * of an atomic_t is only 24 bits. */ -#define __atomic_fool_gcc(x) (*(volatile struct { int a[100]; } *)x) - -extern __inline__ void atomic_add(int i, volatile atomic_t * v) +extern __inline__ void atomic_add(int i, atomic_t * v) { unsigned long temp; __asm__ __volatile__( - "1:\tll\t%0,%1\n\t" - "addu\t%0,%2\n\t" - "sc\t%0,%1\n\t" - "beqz\t%0,1b" - :"=&r" (temp), - "=m" (__atomic_fool_gcc(v)) - :"Ir" (i), - "m" (__atomic_fool_gcc(v))); + "1: ll %0, %1 # atomic_add\n" + " addu %0, %2 \n" + " sc %0, %1 \n" + " beqz %0, 1b \n" + : "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter)); } -extern __inline__ void atomic_sub(int i, volatile atomic_t * v) +/* + * atomic_sub - subtract the atomic variable + * @i: integer value to subtract + * @v: pointer of type atomic_t + * + * Atomically subtracts @i from @v. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +extern __inline__ void atomic_sub(int i, atomic_t * v) { unsigned long temp; __asm__ __volatile__( - "1:\tll\t%0,%1\n\t" - "subu\t%0,%2\n\t" - "sc\t%0,%1\n\t" - "beqz\t%0,1b" - :"=&r" (temp), - "=m" (__atomic_fool_gcc(v)) - :"Ir" (i), - "m" (__atomic_fool_gcc(v))); + "1: ll %0, %1 # atomic_sub\n" + " subu %0, %2 \n" + " sc %0, %1 \n" + " beqz %0, 1b \n" + : "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter)); } /* @@ -153,18 +168,17 @@ unsigned long temp, result; __asm__ __volatile__( - ".set\tnoreorder\n" - "1:\tll\t%1,%2\n\t" - "addu\t%0,%1,%3\n\t" - "sc\t%0,%2\n\t" - "beqz\t%0,1b\n\t" - "addu\t%0,%1,%3\n\t" - ".set\treorder" - :"=&r" (result), - "=&r" (temp), - "=m" (__atomic_fool_gcc(v)) - :"Ir" (i), - "m" (__atomic_fool_gcc(v))); + ".set push # atomic_add_return\n" + ".set noreorder \n" + "1: ll %1, %2 \n" + " addu %0, %1, %3 \n" + " sc %0, %2 \n" + " beqz %0, 1b \n" + " addu %0, %1, %3 \n" + ".set pop \n" + : "=&r" (result), "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter) + : "memory"); return result; } @@ -174,18 +188,17 @@ unsigned long temp, result; __asm__ __volatile__( - ".set\tnoreorder\n" - "1:\tll\t%1,%2\n\t" - "subu\t%0,%1,%3\n\t" - "sc\t%0,%2\n\t" - "beqz\t%0,1b\n\t" - "subu\t%0,%1,%3\n\t" - ".set\treorder" - :"=&r" (result), - "=&r" (temp), - "=m" (__atomic_fool_gcc(v)) - :"Ir" (i), - "m" (__atomic_fool_gcc(v))); + ".set push \n" + ".set noreorder # atomic_sub_return\n" + "1: ll %1, %2 \n" + " subu %0, %1, %3 \n" + " sc %0, %2 \n" + " beqz %0, 1b \n" + " subu %0, %1, %3 \n" + ".set pop \n" + : "=&r" (result), "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter) + : "memory"); return result; } @@ -194,11 +207,71 @@ #define atomic_dec_return(v) atomic_sub_return(1,(v)) #define atomic_inc_return(v) atomic_add_return(1,(v)) +/* + * atomic_sub_and_test - subtract value from variable and test result + * @i: integer value to subtract + * @v: pointer of type atomic_t + * + * Atomically subtracts @i from @v and returns + * true if the result is zero, or false for all + * other cases. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ #define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0) + +/* + * atomic_inc_and_test - increment and test + * @v: pointer of type atomic_t + * + * Atomically increments @v by 1 + * and returns true if the result is zero, or false for all + * other cases. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +#define atomic_inc_and_test(v) (atomic_inc_return(1, (v)) == 0) + +/* + * atomic_dec_and_test - decrement by 1 and test + * @v: pointer of type atomic_t + * + * Atomically decrements @v by 1 and + * returns true if the result is 0, or false for all other + * cases. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ #define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0) +/* + * atomic_inc - increment atomic variable + * @v: pointer of type atomic_t + * + * Atomically increments @v by 1. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ #define atomic_inc(v) atomic_add(1,(v)) + +/* + * atomic_dec - decrement and test + * @v: pointer of type atomic_t + * + * Atomically decrements @v by 1. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ #define atomic_dec(v) atomic_sub(1,(v)) + +/* + * atomic_add_negative - add and test if negative + * @v: pointer of type atomic_t + * @i: integer value to add + * + * Atomically adds @i to @v and returns true + * if the result is negative, or false when + * result is greater than or equal to zero. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + * + * Currently not implemented for MIPS. + */ + #endif /* defined(__KERNEL__) */ -#endif /* __ASM_MIPS_ATOMIC_H */ +#endif /* __ASM_ATOMIC_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/bcache.h linux/include/asm-mips/bcache.h --- v2.4.5/linux/include/asm-mips/bcache.h Sat May 13 08:31:25 2000 +++ linux/include/asm-mips/bcache.h Mon Jul 2 13:56:40 2001 @@ -1,14 +1,19 @@ -/* $Id$ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 1997, 1999 by Ralf Baechle + * Copyright (c) 1997, 1999, 2000 by Ralf Baechle + * Copyright (c) 2000 by Silicon Graphics, Inc. */ #ifndef _ASM_BCACHE_H #define _ASM_BCACHE_H +#include + +/* Some R4000 / R4400 / R4600 / R5000 machines may have a non-dma-coherent, + chipset implemented caches. On machines with other CPUs the CPU does the + cache thing itself. */ struct bcache_ops { void (*bc_enable)(void); void (*bc_disable)(void); @@ -19,6 +24,39 @@ extern void indy_sc_init(void); extern void sni_pcimt_sc_init(void); +#ifdef CONFIG_BOARD_SCACHE + extern struct bcache_ops *bcops; + +extern inline void bc_enable(void) +{ + bcops->bc_enable(); +} + +extern inline void bc_disable(void) +{ + bcops->bc_disable(); +} + +extern inline void bc_wback_inv(unsigned long page, unsigned long size) +{ + bcops->bc_wback_inv(page, size); +} + +extern inline void bc_inv(unsigned long page, unsigned long size) +{ + bcops->bc_inv(page, size); +} + +#else /* !defined(CONFIG_BOARD_SCACHE) */ + +/* Not R4000 / R4400 / R4600 / R5000. */ + +#define bc_enable() do { } while (0) +#define bc_disable() do { } while (0) +#define bc_wback_inv(page, size) do { } while (0) +#define bc_inv(page, size) do { } while (0) + +#endif /* !defined(CONFIG_BOARD_SCACHE) */ #endif /* _ASM_BCACHE_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/bitops.h linux/include/asm-mips/bitops.h --- v2.4.5/linux/include/asm-mips/bitops.h Wed Jul 5 22:15:26 2000 +++ linux/include/asm-mips/bitops.h Mon Jul 2 13:56:40 2001 @@ -1,10 +1,10 @@ -/* $Id: bitops.h,v 1.7 1999/08/19 22:56:33 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 1994 - 1997, 1999 Ralf Baechle (ralf@gnu.org) + * Copyright (c) 1994 - 1997, 1999, 2000 Ralf Baechle (ralf@gnu.org) + * Copyright (c) 2000 Silicon Graphics, Inc. */ #ifndef _ASM_BITOPS_H #define _ASM_BITOPS_H @@ -19,6 +19,12 @@ #include /* + * clear_bit() doesn't provide any barrier for the compiler. + */ +#define smp_mb__before_clear_bit() barrier() +#define smp_mb__after_clear_bit() barrier() + +/* * Only disable interrupt for kernel mode stuff to keep usermode stuff * that dares to use kernel include files alive. */ @@ -35,25 +41,6 @@ #define __bi_restore_flags(x) #endif /* __KERNEL__ */ -/* - * Note that the bit operations are defined on arrays of 32 bit sized - * elements. With respect to a future 64 bit implementation it is - * wrong to use long *. Use u32 * or int *. - */ -extern __inline__ void set_bit(int nr, void *addr); -extern __inline__ void clear_bit(int nr, void *addr); -extern __inline__ void change_bit(int nr, void *addr); -extern __inline__ int test_and_set_bit(int nr, void *addr); -extern __inline__ int test_and_clear_bit(int nr, void *addr); -extern __inline__ int test_and_change_bit(int nr, void *addr); - -extern __inline__ int test_bit(int nr, const void *addr); -#ifndef __MIPSEB__ -extern __inline__ int find_first_zero_bit (void *addr, unsigned size); -#endif -extern __inline__ int find_next_zero_bit (void * addr, int size, int offset); -extern __inline__ unsigned long ffz(unsigned long word); - #if defined(CONFIG_CPU_HAS_LLSC) #include @@ -64,92 +51,281 @@ */ /* - * The following functions will only work for the R4000! - */ + * set_bit - Atomically set a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * This function is atomic and may not be reordered. See __set_bit() + * if you do not require the atomic guarantees. + * Note that @nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +extern __inline__ void +set_bit(int nr, volatile void *addr) +{ + unsigned long *m = ((unsigned long *) addr) + (nr >> 5); + unsigned long temp; + + __asm__ __volatile__( + "1:\tll\t%0, %1\t\t# set_bit\n\t" + "or\t%0, %2\n\t" + "sc\t%0, %1\n\t" + "beqz\t%0, 1b" + : "=&r" (temp), "=m" (*m) + : "ir" (1UL << (nr & 0x1f)), "m" (*m)); +} -extern __inline__ void set_bit(int nr, void *addr) +/* + * __set_bit - Set a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * Unlike set_bit(), this function is non-atomic and may be reordered. + * If it's called on the same region of memory simultaneously, the effect + * may be that only one operation succeeds. + */ +extern __inline__ void __set_bit(int nr, volatile void * addr) { - int mask, mw; + unsigned long * m = ((unsigned long *) addr) + (nr >> 5); - addr += ((nr >> 3) & ~3); - mask = 1 << (nr & 0x1f); - do { - mw = load_linked(addr); - } while (!store_conditional(addr, mw|mask)); + *m |= 1UL << (nr & 31); +} + +/* + * clear_bit - Clears a bit in memory + * @nr: Bit to clear + * @addr: Address to start counting from + * + * clear_bit() is atomic and may not be reordered. However, it does + * not contain a memory barrier, so if it is used for locking purposes, + * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit() + * in order to ensure changes are visible on other processors. + */ +extern __inline__ void +clear_bit(int nr, volatile void *addr) +{ + unsigned long *m = ((unsigned long *) addr) + (nr >> 5); + unsigned long temp; + + __asm__ __volatile__( + "1:\tll\t%0, %1\t\t# clear_bit\n\t" + "and\t%0, %2\n\t" + "sc\t%0, %1\n\t" + "beqz\t%0, 1b\n\t" + : "=&r" (temp), "=m" (*m) + : "ir" (~(1UL << (nr & 0x1f))), "m" (*m)); } -extern __inline__ void clear_bit(int nr, void *addr) +/* + * change_bit - Toggle a bit in memory + * @nr: Bit to clear + * @addr: Address to start counting from + * + * change_bit() is atomic and may not be reordered. + * Note that @nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +extern __inline__ void +change_bit(int nr, volatile void *addr) +{ + unsigned long *m = ((unsigned long *) addr) + (nr >> 5); + unsigned long temp; + + __asm__ __volatile__( + "1:\tll\t%0, %1\t\t# change_bit\n\t" + "xor\t%0, %2\n\t" + "sc\t%0, %1\n\t" + "beqz\t%0, 1b" + : "=&r" (temp), "=m" (*m) + : "ir" (1UL << (nr & 0x1f)), "m" (*m)); +} + +/* + * __change_bit - Toggle a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * Unlike change_bit(), this function is non-atomic and may be reordered. + * If it's called on the same region of memory simultaneously, the effect + * may be that only one operation succeeds. + */ +extern __inline__ void __change_bit(int nr, volatile void * addr) { - int mask, mw; + unsigned long * m = ((unsigned long *) addr) + (nr >> 5); - addr += ((nr >> 3) & ~3); - mask = 1 << (nr & 0x1f); - do { - mw = load_linked(addr); - } - while (!store_conditional(addr, mw & ~mask)); + *m ^= 1UL << (nr & 31); } -extern __inline__ void change_bit(int nr, void *addr) +/* + * test_and_set_bit - Set a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It also implies a memory barrier. + */ +extern __inline__ int +test_and_set_bit(int nr, volatile void *addr) { - int mask, mw; + unsigned long *m = ((unsigned long *) addr) + (nr >> 5); + unsigned long temp, res; - addr += ((nr >> 3) & ~3); - mask = 1 << (nr & 0x1f); - do { - mw = load_linked(addr); - } while (!store_conditional(addr, mw ^ mask)); + __asm__ __volatile__( + ".set\tnoreorder\t\t# test_and_set_bit\n" + "1:\tll\t%0, %1\n\t" + "or\t%2, %0, %3\n\t" + "sc\t%2, %1\n\t" + "beqz\t%2, 1b\n\t" + " and\t%2, %0, %3\n\t" + ".set\treorder" + : "=&r" (temp), "=m" (*m), "=&r" (res) + : "r" (1UL << (nr & 0x1f)), "m" (*m) + : "memory"); + + return res != 0; } -extern __inline__ int test_and_set_bit(int nr, void *addr) +/* + * __test_and_set_bit - Set a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered. + * If two examples of this operation race, one can appear to succeed + * but actually fail. You must protect multiple accesses with a lock. + */ +extern __inline__ int __test_and_set_bit(int nr, volatile void * addr) { - int mask, retval, mw; + int mask, retval; + volatile int *a = addr; - addr += ((nr >> 3) & ~3); + a += nr >> 5; mask = 1 << (nr & 0x1f); - do { - mw = load_linked(addr); - retval = (mask & mw) != 0; - } while (!store_conditional(addr, mw|mask)); + retval = (mask & *a) != 0; + *a |= mask; return retval; } -extern __inline__ int test_and_clear_bit(int nr, void *addr) +/* + * test_and_clear_bit - Clear a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It also implies a memory barrier. + */ +extern __inline__ int +test_and_clear_bit(int nr, volatile void *addr) +{ + unsigned long *m = ((unsigned long *) addr) + (nr >> 5); + unsigned long temp, res; + + __asm__ __volatile__( + ".set\tnoreorder\t\t# test_and_clear_bit\n" + "1:\tll\t%0, %1\n\t" + "or\t%2, %0, %3\n\t" + "xor\t%2, %3\n\t" + "sc\t%2, %1\n\t" + "beqz\t%2, 1b\n\t" + " and\t%2, %0, %3\n\t" + ".set\treorder" + : "=&r" (temp), "=m" (*m), "=&r" (res) + : "r" (1UL << (nr & 0x1f)), "m" (*m) + : "memory"); + + return res != 0; +} + +/* + * __test_and_clear_bit - Clear a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered. + * If two examples of this operation race, one can appear to succeed + * but actually fail. You must protect multiple accesses with a lock. + */ +extern __inline__ int __test_and_clear_bit(int nr, volatile void * addr) { - int mask, retval, mw; + int mask, retval; + volatile int *a = addr; - addr += ((nr >> 3) & ~3); + a += nr >> 5; mask = 1 << (nr & 0x1f); - do { - mw = load_linked(addr); - retval = (mask & mw) != 0; - } - while (!store_conditional(addr, mw & ~mask)); + retval = (mask & *a) != 0; + *a &= ~mask; return retval; } -extern __inline__ int test_and_change_bit(int nr, void *addr) +/* + * test_and_change_bit - Change a bit and return its new value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It also implies a memory barrier. + */ +extern __inline__ int +test_and_change_bit(int nr, volatile void *addr) +{ + unsigned long *m = ((unsigned long *) addr) + (nr >> 5); + unsigned long temp, res; + + __asm__ __volatile__( + ".set\tnoreorder\t\t# test_and_change_bit\n" + "1:\tll\t%0, %1\n\t" + "xor\t%2, %0, %3\n\t" + "sc\t%2, %1\n\t" + "beqz\t%2, 1b\n\t" + " and\t%2, %0, %3\n\t" + ".set\treorder" + : "=&r" (temp), "=m" (*m), "=&r" (res) + : "r" (1UL << (nr & 0x1f)), "m" (*m) + : "memory"); + + return res != 0; +} + +/* + * __test_and_change_bit - Change a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered. + * If two examples of this operation race, one can appear to succeed + * but actually fail. You must protect multiple accesses with a lock. + */ +extern __inline__ int __test_and_change_bit(int nr, volatile void * addr) { - int mask, retval, mw; + int mask, retval; + volatile int *a = addr; - addr += ((nr >> 3) & ~3); + a += nr >> 5; mask = 1 << (nr & 0x1f); - do { - mw = load_linked(addr); - retval = (mask & mw) != 0; - } while (!store_conditional(addr, mw ^ mask)); + retval = (mask & *a) != 0; + *a ^= mask; return retval; } #else /* MIPS I */ -extern __inline__ void set_bit(int nr, void * addr) +/* + * set_bit - Atomically set a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * This function is atomic and may not be reordered. See __set_bit() + * if you do not require the atomic guarantees. + * Note that @nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +extern __inline__ void set_bit(int nr, volatile void * addr) { int mask; - int *a = addr; + volatile int *a = addr; __bi_flags; a += nr >> 5; @@ -159,10 +335,39 @@ __bi_restore_flags(flags); } -extern __inline__ void clear_bit(int nr, void * addr) +/* + * __set_bit - Set a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * Unlike set_bit(), this function is non-atomic and may be reordered. + * If it's called on the same region of memory simultaneously, the effect + * may be that only one operation succeeds. + */ +extern __inline__ void __set_bit(int nr, volatile void * addr) { int mask; - int *a = addr; + volatile int *a = addr; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + *a |= mask; +} + +/* + * clear_bit - Clears a bit in memory + * @nr: Bit to clear + * @addr: Address to start counting from + * + * clear_bit() is atomic and may not be reordered. However, it does + * not contain a memory barrier, so if it is used for locking purposes, + * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit() + * in order to ensure changes are visible on other processors. + */ +extern __inline__ void clear_bit(int nr, volatile void * addr) +{ + int mask; + volatile int *a = addr; __bi_flags; a += nr >> 5; @@ -172,10 +377,19 @@ __bi_restore_flags(flags); } -extern __inline__ void change_bit(int nr, void * addr) +/* + * change_bit - Toggle a bit in memory + * @nr: Bit to clear + * @addr: Address to start counting from + * + * change_bit() is atomic and may not be reordered. + * Note that @nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +extern __inline__ void change_bit(int nr, volatile void * addr) { int mask; - int *a = addr; + volatile int *a = addr; __bi_flags; a += nr >> 5; @@ -185,10 +399,34 @@ __bi_restore_flags(flags); } -extern __inline__ int test_and_set_bit(int nr, void * addr) +/* + * __change_bit - Toggle a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * Unlike change_bit(), this function is non-atomic and may be reordered. + * If it's called on the same region of memory simultaneously, the effect + * may be that only one operation succeeds. + */ +extern __inline__ void __change_bit(int nr, volatile void * addr) +{ + unsigned long * m = ((unsigned long *) addr) + (nr >> 5); + + *m ^= 1UL << (nr & 31); +} + +/* + * test_and_set_bit - Set a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It also implies a memory barrier. + */ +extern __inline__ int test_and_set_bit(int nr, volatile void * addr) { int mask, retval; - int *a = addr; + volatile int *a = addr; __bi_flags; a += nr >> 5; @@ -201,10 +439,40 @@ return retval; } -extern __inline__ int test_and_clear_bit(int nr, void * addr) +/* + * __test_and_set_bit - Set a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered. + * If two examples of this operation race, one can appear to succeed + * but actually fail. You must protect multiple accesses with a lock. + */ +extern __inline__ int __test_and_set_bit(int nr, volatile void * addr) +{ + int mask, retval; + volatile int *a = addr; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + retval = (mask & *a) != 0; + *a |= mask; + + return retval; +} + +/* + * test_and_clear_bit - Clear a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It also implies a memory barrier. + */ +extern __inline__ int test_and_clear_bit(int nr, volatile void * addr) { int mask, retval; - int *a = addr; + volatile int *a = addr; __bi_flags; a += nr >> 5; @@ -217,10 +485,40 @@ return retval; } -extern __inline__ int test_and_change_bit(int nr, void * addr) +/* + * __test_and_clear_bit - Clear a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered. + * If two examples of this operation race, one can appear to succeed + * but actually fail. You must protect multiple accesses with a lock. + */ +extern __inline__ int __test_and_clear_bit(int nr, volatile void * addr) { int mask, retval; - int *a = addr; + volatile int *a = addr; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + retval = (mask & *a) != 0; + *a &= ~mask; + + return retval; +} + +/* + * test_and_change_bit - Change a bit and return its new value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It also implies a memory barrier. + */ +extern __inline__ int test_and_change_bit(int nr, volatile void * addr) +{ + int mask, retval; + volatile int *a = addr; __bi_flags; a += nr >> 5; @@ -233,14 +531,41 @@ return retval; } +/* + * __test_and_change_bit - Change a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered. + * If two examples of this operation race, one can appear to succeed + * but actually fail. You must protect multiple accesses with a lock. + */ +extern __inline__ int __test_and_change_bit(int nr, volatile void * addr) +{ + int mask, retval; + volatile int *a = addr; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + retval = (mask & *a) != 0; + *a ^= mask; + + return retval; +} + #undef __bi_flags -#undef __bi_cli() -#undef __bi_save_flags(x) -#undef __bi_restore_flags(x) +#undef __bi_cli +#undef __bi_save_flags +#undef __bi_restore_flags #endif /* MIPS I */ -extern __inline__ int test_bit(int nr, const void *addr) +/* + * test_bit - Determine whether a bit is set + * @nr: bit number to test + * @addr: Address to start counting from + */ +extern __inline__ int test_bit(int nr, volatile void *addr) { return ((1UL << (nr & 31)) & (((const unsigned int *) addr)[nr >> 5])) != 0; } @@ -249,6 +574,14 @@ /* Little endian versions. */ +/* + * find_first_zero_bit - find the first zero bit in a memory region + * @addr: The address to start the search at + * @size: The maximum size to search + * + * Returns the bit-number of the first zero bit, not the number of the byte + * containing a bit. + */ extern __inline__ int find_first_zero_bit (void *addr, unsigned size) { unsigned long dummy; @@ -285,18 +618,20 @@ ".set\tat\n\t" ".set\treorder\n" "2:" - : "=r" (res), - "=r" (dummy), - "=r" (addr) - : "0" ((signed int) 0), - "1" ((unsigned int) 0xffffffff), - "2" (addr), - "r" (size) + : "=r" (res), "=r" (dummy), "=r" (addr) + : "0" ((signed int) 0), "1" ((unsigned int) 0xffffffff), + "2" (addr), "r" (size) : "$1"); return res; } +/* + * find_next_zero_bit - find the first zero bit in a memory region + * @addr: The address to base the search on + * @offset: The bitnumber to start searching at + * @size: The maximum size to search + */ extern __inline__ int find_next_zero_bit (void * addr, int size, int offset) { unsigned int *p = ((unsigned int *) addr) + (offset >> 5); @@ -320,11 +655,8 @@ ".set\tat\n\t" ".set\treorder\n" "1:" - : "=r" (set), - "=r" (dummy) - : "0" (0), - "1" (1 << bit), - "r" (*p) + : "=r" (set), "=r" (dummy) + : "0" (0), "1" (1 << bit), "r" (*p) : "$1"); if (set < (32 - bit)) return set + offset; @@ -341,8 +673,10 @@ #endif /* !(__MIPSEB__) */ /* - * ffz = Find First Zero in word. Undefined if no zero exists, - * so code should check against ~0UL first.. + * ffz - find first zero in word. + * @word: The word to search + * + * Undefined if no zero exists, so code should check against ~0UL first. */ extern __inline__ unsigned long ffz(unsigned long word) { @@ -370,8 +704,11 @@ #ifdef __KERNEL__ -/* - * ffs: find first bit set. This is defined the same way as +/** + * ffs - find first bit set + * @x: the word to search + * + * This is defined the same way as * the libc and compiler builtin ffs routines, therefore * differs in spirit from the above ffz (man ffs). */ @@ -379,8 +716,10 @@ #define ffs(x) generic_ffs(x) /* - * hweightN: returns the hamming weight (i.e. the number - * of bits set) of a N-bit word + * hweightN - returns the hamming weight of a N-bit word + * @x: the word to weigh + * + * The Hamming Weight of a number is the total number of bits set in it. */ #define hweight32(x) generic_hweight32(x) @@ -390,14 +729,12 @@ #endif /* __KERNEL__ */ #ifdef __MIPSEB__ -/* For now I steal the Sparc C versions, no need for speed, just need to - * get it working. - */ -/* find_next_zero_bit() finds the first zero bit in a bit string of length - * 'size' bits, starting the search at bit 'offset'. This is largely based - * on Linus's ALPHA routines, which are pretty portable BTW. +/* + * find_next_zero_bit - find the first zero bit in a memory region + * @addr: The address to base the search on + * @offset: The bitnumber to start searching at + * @size: The maximum size to search */ - extern __inline__ int find_next_zero_bit(void *addr, int size, int offset) { unsigned long *p = ((unsigned long *) addr) + (offset >> 5); @@ -438,6 +775,18 @@ * holds on the Sparc as it does for the ALPHA. */ +#if 0 /* Fool kernel-doc since it doesn't do macros yet */ +/* + * find_first_zero_bit - find the first zero bit in a memory region + * @addr: The address to start the search at + * @size: The maximum size to search + * + * Returns the bit-number of the first zero bit, not the number of the byte + * containing a bit. + */ +extern int find_first_zero_bit (void *addr, unsigned size); +#endif + #define find_first_zero_bit(addr, size) \ find_next_zero_bit((addr), (size), 0) @@ -451,7 +800,6 @@ int mask, retval, flags; unsigned char *ADDR = (unsigned char *) addr; - ADDR += nr >> 3; mask = 1 << (nr & 0x07); save_and_cli(flags); retval = (mask & *ADDR) != 0; diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/bootinfo.h linux/include/asm-mips/bootinfo.h --- v2.4.5/linux/include/asm-mips/bootinfo.h Fri Apr 13 20:26:07 2001 +++ linux/include/asm-mips/bootinfo.h Mon Jul 2 13:56:40 2001 @@ -18,14 +18,23 @@ #define MACH_GROUP_ARC 3 /* Wreckstation Tyne, rPC44, possibly other */ #define MACH_GROUP_SNI_RM 4 /* Siemens Nixdorf RM series */ #define MACH_GROUP_ACN 5 -#define MACH_GROUP_SGI 6 /* Silicon Graphics workstations and servers */ +#define MACH_GROUP_SGI 6 /* Silicon Graphics */ #define MACH_GROUP_COBALT 7 /* Cobalt servers */ -#define MACH_GROUP_NEC_DDB 8 /* NEC DDB */ -#define MACH_GROUP_BAGET 9 /* Baget */ -#define MACH_GROUP_ORION 10 /* CoSine Orion */ - -#define GROUP_NAMES { "unknown", "Jazz", "Digital", "ARC", \ - "SNI", "ACN", "SGI", "Cobalt", "NEC DDB", "Baget", "Orion" } +#define MACH_GROUP_NEC_DDB 8 /* NEC DDB */ +#define MACH_GROUP_BAGET 9 /* Baget */ +#define MACH_GROUP_COSINE 10 /* CoSine Orion */ +#define MACH_GROUP_GALILEO 11 /* Galileo Eval Boards */ +#define MACH_GROUP_MOMENCO 12 /* Momentum Boards */ +#define MACH_GROUP_ITE 13 /* ITE Semi Eval Boards */ +#define MACH_GROUP_PHILIPS 14 +#define MACH_GROUP_GLOBESPAN 15 /* Globespan PVR Referrence Board */ +#define MACH_GROUP_SIBYTE 16 /* Sibyte Eval Boards */ +#define MACH_GROUP_TOSHIBA 17 /* Toshiba Reference Systems TSBREF */ +#define MACH_GROUP_ALCHEMY 18 /* Alchemy Semi Eval Boards*/ + +#define GROUP_NAMES { "unknown", "Jazz", "Digital", "ARC", "SNI", "ACN", \ + "SGI", "Cobalt", "NEC DDB", "Baget", "Cosine", "Galileo", "Momentum", \ + "ITE", "Philips", "Globepspan", "SiByte", "Toshiba", "Alchemy" } /* * Valid machtype values for group unknown (low order halfword of mips_machtype) @@ -87,9 +96,11 @@ /* * Valid machtype for group SGI */ -#define MACH_SGI_INDY 0 /* R4?K and R5K Indy workstaions */ +#define MACH_SGI_INDY 0 /* R4?K and R5K Indy workstations */ +#define MACH_SGI_CHALLENGE_S 1 /* The Challenge S server */ +#define MACH_SGI_INDIGO2 2 /* The Indigo2 system */ -#define GROUP_SGI_NAMES { "Indy" } +#define GROUP_SGI_NAMES { "Indy", "Challenge S", "Indigo2" } /* * Valid machtype for group COBALT @@ -103,8 +114,9 @@ */ #define MACH_NEC_DDB5074 0 /* NEC DDB Vrc-5074 */ #define MACH_NEC_DDB5476 1 /* NEC DDB Vrc-5476 */ +#define MACH_NEC_DDB5477 2 /* NEC DDB Vrc-5477 */ -#define GROUP_NEC_DDB_NAMES { "Vrc-5074", "Vrc-5476"} +#define GROUP_NEC_DDB_NAMES { "Vrc-5074", "Vrc-5476", "Vrc-5477"} /* * Valid machtype for group BAGET @@ -115,6 +127,74 @@ #define GROUP_BAGET_NAMES { "BT23-201", "BT23-202" } /* + * Cosine boards. + */ +#define MACH_COSINE_ORION 0 + +#define GROUP_COSINE_NAMES { "Orion" } + +/* + * Valid machtype for group GALILEO + */ +#define MACH_EV96100 0 /* EV96100 */ +#define MACH_EV64120A 1 /* EV64120A */ + +#define GROUP_GALILEO_NAMES { "EV96100" , "EV64120A" } + +/* + * Valid machtype for group MOMENCO + */ +#define MACH_MOMENCO_OCELOT 0 + +#define GROUP_MOMENCO_NAMES { "Ocelot" } + + +/* + * Valid machtype for group ITE + */ +#define MACH_QED_4N_S01B 0 /* ITE8172 based eval board */ + +#define GROUP_ITE_NAMES { "QED-4N-S01B" } /* the actual board name */ + +/* + * Valid machtype for group Globespan + */ +#define MACH_IVR 0 /* IVR eval board */ + +#define GROUP_GLOBESPAN_NAMES { "IVR" } /* the actual board name */ + +/* + * Valid machtype for group PHILIPS + */ +#define MACH_PHILIPS_NINO 0 /* Nino */ +#define MACH_PHILIPS_VELO 1 /* Velo */ + +#define GROUP_PHILIPS_NAMES { "Nino" , "Velo" } + +/* + * Valid machtype for group SIBYTE + */ +#define MACH_SWARM 0 + +#define GROUP_SIBYTE_NAMES {"SWARM" } + +/* + * Valid machtypes for group Toshiba + */ +#define MACH_PALLAS 0 +#define MACH_TOPAS 1 +#define MACH_JMR 2 + +#define GROUP_TOSHIBA_NAMES { "Pallas", "TopasCE", "JMR" } + +/* + * Valid machtype for group Alchemy + */ +#define MACH_PB1000 0 /* Au1000-based eval board */ + +#define GROUP_ALCHEMY_NAMES { "PB1000" } /* the actual board name */ + +/* * Valid cputype values */ #define CPU_UNKNOWN 0 @@ -145,17 +225,36 @@ #define CPU_R5000A 25 #define CPU_R4640 26 #define CPU_NEVADA 27 /* RM5230, RM5260 */ -#define CPU_LAST 27 +#define CPU_RM7000 28 +#define CPU_R5432 29 +#define CPU_4KC 30 +#define CPU_5KC 31 +#define CPU_R4310 32 +#define CPU_SB1 33 +#define CPU_TX3912 34 +#define CPU_TX3922 35 +#define CPU_TX3927 36 +#define CPU_AU1000 37 +#define CPU_4KEC 37 +#define CPU_4KSC 38 +#define CPU_LAST 39 #define CPU_NAMES { "unknown", "R2000", "R3000", "R3000A", "R3041", "R3051", \ "R3052", "R3081", "R3081E", "R4000PC", "R4000SC", "R4000MC", \ "R4200", "R4400PC", "R4400SC", "R4400MC", "R4600", "R6000", \ "R6000A", "R8000", "R10000", "R4300", "R4650", "R4700", "R5000", \ - "R5000A", "R4640", "Nevada" } + "R5000A", "R4640", "Nevada", "RM7000", "R5432", "MIPS 4Kc", \ + "MIPS 5Kc", "R4310", "SiByte SB1", "TX3912", "TX3922", "TX3927", \ + "Au1000", "MIPS 4KEc", "MIPS 4KSc" } + +#define COMMAND_LINE_SIZE 256 + +#define BOOT_MEM_MAP_MAX 32 +#define BOOT_MEM_RAM 1 +#define BOOT_MEM_ROM_DATA 2 +#define BOOT_MEM_RESERVED 3 -#define CL_SIZE (80) - -#ifndef _LANGUAGE_ASSEMBLY +#ifndef __ASSEMBLY__ /* * Some machine parameters passed by the bootloaders. @@ -183,12 +282,29 @@ * values in setup.c (or whereever suitable) so they are in * .data section */ -extern unsigned long mips_memory_upper; -extern unsigned long mips_cputype; +extern struct mips_cpu mips_cpu; extern unsigned long mips_machtype; extern unsigned long mips_machgroup; extern unsigned long mips_tlb_entries; -#endif /* _LANGUAGE_ASSEMBLY */ +/* + * A memory map that's built upon what was determined + * or specified on the command line. + */ +struct boot_mem_map { + int nr_map; + struct { + unsigned long addr; /* start of memory segment */ + unsigned long size; /* size of memory segment */ + long type; /* type of memory segment */ + } map[BOOT_MEM_MAP_MAX]; +}; + +extern struct boot_mem_map boot_mem_map; + +extern void add_memory_region(unsigned long start, unsigned long size, + long type); + +#endif /* !__ASSEMBLY__ */ -#endif /* __ASM_MIPS_BOOTINFO_H */ +#endif /* _ASM_BOOTINFO_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/bugs.h linux/include/asm-mips/bugs.h --- v2.4.5/linux/include/asm-mips/bugs.h Sat May 13 08:31:25 2000 +++ linux/include/asm-mips/bugs.h Mon Jul 2 13:56:40 2001 @@ -1,9 +1,9 @@ -/* $Id: bugs.h,v 1.4 1999/08/18 23:37:49 ralf Exp $ - * +/* * Copyright (C) 1995 Waldorf Electronics * Copyright (C) 1997, 1999 Ralf Baechle */ #include +#include /* * This is included by init/main.c to check for architecture-dependent bugs. @@ -16,7 +16,7 @@ static inline void check_wait(void) { printk("Checking for 'wait' instruction... "); - switch(mips_cputype) { + switch(mips_cpu.cputype) { case CPU_R3081: case CPU_R3081E: cpu_wait = r3081_wait; @@ -30,6 +30,7 @@ case CPU_R4700: case CPU_R5000: case CPU_NEVADA: + case CPU_RM7000: cpu_wait = r4k_wait; printk(" available.\n"); break; diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/cache.h linux/include/asm-mips/cache.h --- v2.4.5/linux/include/asm-mips/cache.h Sat May 13 08:31:25 2000 +++ linux/include/asm-mips/cache.h Mon Jul 2 13:56:40 2001 @@ -1,16 +1,32 @@ -/* $Id: cache.h,v 1.4 2000/02/04 07:40:53 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1997, 1998, 1999 Ralf Baechle + * Copyright (C) 1997, 98, 99, 2000 Ralf Baechle * Copyright (C) 1999 Silicon Graphics, Inc. */ #ifndef _ASM_CACHE_H #define _ASM_CACHE_H #include + +#ifndef _LANGUAGE_ASSEMBLY +/* + * Descriptor for a cache + */ +struct cache_desc { + int linesz; + int sets; + int ways; + int flags; /* Details like write thru/back, coherent, etc. */ +}; +#endif + +/* + * Flag definitions + */ +#define MIPS_CACHE_NOT_PRESENT 0x00000001 #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_R6000) #define L1_CACHE_BYTES 16 diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/checksum.h linux/include/asm-mips/checksum.h --- v2.4.5/linux/include/asm-mips/checksum.h Sat May 13 08:31:25 2000 +++ linux/include/asm-mips/checksum.h Mon Jul 2 13:56:40 2001 @@ -1,10 +1,9 @@ -/* $Id: checksum.h,v 1.8 2000/02/18 00:24:48 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle + * Copyright (C) 1995, 1996, 1997, 1998, 2001 by Ralf Baechle */ #ifndef _ASM_CHECKSUM_H #define _ASM_CHECKSUM_H @@ -23,7 +22,7 @@ * * it's best to have buff aligned on a 32-bit boundary */ -unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum); +unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum); /* * this is a new version of the above that records errors it finds in *errp, @@ -42,9 +41,9 @@ * Copy and checksum to user */ #define HAVE_CSUM_COPY_USER -extern inline unsigned int -csum_and_copy_to_user (const char *src, char *dst, - int len, int sum, int *err_ptr) +extern inline unsigned int csum_and_copy_to_user (const char *src, char *dst, + int len, int sum, + int *err_ptr) { sum = csum_partial(src, len, sum); @@ -63,22 +62,23 @@ * this is obsolete and will go away. */ #define csum_partial_copy_fromuser csum_partial_copy -unsigned int csum_partial_copy(const char *src, char *dst, int len, unsigned int sum); - +unsigned int csum_partial_copy(const char *src, char *dst, int len, + unsigned int sum); + /* * Fold a partial checksum without adding pseudo headers */ static inline unsigned short int csum_fold(unsigned int sum) { - __asm__(" - .set noat - sll $1,%0,16 - addu %0,$1 - sltu $1,%0,$1 - srl %0,%0,16 - addu %0,$1 - xori %0,0xffff - .set at" + __asm__( + ".set\tnoat\t\t\t# csum_fold\n\t" + "sll\t$1,%0,16\n\t" + "addu\t%0,$1\n\t" + "sltu\t$1,%0,$1\n\t" + "srl\t%0,%0,16\n\t" + "addu\t%0,$1\n\t" + "xori\t%0,0xffff\n\t" + ".set\tat" : "=r" (sum) : "0" (sum) : "$1"); @@ -93,7 +93,7 @@ * By Jorge Cwik , adapted for linux by * Arnt Gulbrandsen. */ -static inline unsigned short ip_fast_csum(unsigned char * iph, +static inline unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl) { unsigned int sum; @@ -102,37 +102,36 @@ /* * This is for 32-bit MIPS processors. */ - __asm__ __volatile__(" - .set noreorder - .set noat - lw %0,(%1) - subu %2,4 - #blez %2,2f - sll %2,2 # delay slot - - lw %3,4(%1) - addu %2,%1 # delay slot - addu %0,%3 - sltu $1,%0,%3 - lw %3,8(%1) - addu %0,$1 - addu %0,%3 - sltu $1,%0,%3 - lw %3,12(%1) - addu %0,$1 - addu %0,%3 - sltu $1,%0,%3 - addu %0,$1 - -1: lw %3,16(%1) - addiu %1,4 - addu %0,%3 - sltu $1,%0,%3 - bne %2,%1,1b - addu %0,$1 # delay slot + __asm__ __volatile__( + ".set\tnoreorder\t\t\t# ip_fast_csum\n\t" + ".set\tnoat\n\t" + "lw\t%0, (%1)\n\t" + "subu\t%2, 4\n\t" + "#blez\t%2, 2f\n\t" + " sll\t%2, 2\n\t" + "lw\t%3, 4(%1)\n\t" + "addu\t%2, %1\n\t" + "addu\t%0, %3\n\t" + "sltu\t$1, %0, %3\n\t" + "lw\t%3, 8(%1)\n\t" + "addu\t%0, $1\n\t" + "addu\t%0, %3\n\t" + "sltu\t$1, %0, %3\n\t" + "lw\t%3, 12(%1)\n\t" + "addu\t%0, $1\n\t" + "addu\t%0, %3\n\t" + "sltu\t$1, %0, %3\n\t" + "addu\t%0, $1\n" + + "1:\tlw\t%3, 16(%1)\n\t" + "addiu\t%1, 4\n\t" + "addu\t%0, %3\n\t" + "sltu\t$1, %0, %3\n\t" + "bne\t%2, %1, 1b\n\t" + " addu\t%0, $1\n" -2: .set at - .set reorder" + "2:\t.set\tat\n\t" + ".set\treorder" : "=&r" (sum), "=&r" (iph), "=&r" (ihl), "=&r" (dummy) : "1" (iph), "2" (ihl) : "$1"); @@ -150,28 +149,28 @@ unsigned short proto, unsigned int sum) { - __asm__(" - .set noat - addu %0,%2 - sltu $1,%0,%2 - addu %0,$1 - - addu %0,%3 - sltu $1,%0,%3 - addu %0,$1 - - addu %0,%4 - sltu $1,%0,%4 - addu %0,$1 - .set at" + __asm__( + ".set\tnoat\t\t\t# csum_tcpudp_nofold\n\t" + "addu\t%0, %2\n\t" + "sltu\t$1, %0, %2\n\t" + "addu\t%0, $1\n\t" + + "addu\t%0, %3\n\t" + "sltu\t$1, %0, %3\n\t" + "addu\t%0, $1\n\t" + + "addu\t%0, %4\n\t" + "sltu\t$1, %0, %4\n\t" + "addu\t%0, $1\n\t" + ".set\tat" : "=r" (sum) : "0" (daddr), "r"(saddr), #ifdef __MIPSEL__ - "r" ((ntohs(len)<<16)+proto*256), + "r" ((ntohs(len)<<16)+proto*256), #else - "r" (((proto)<<16)+len), + "r" (((proto)<<16)+len), #endif - "r"(sum) + "r" (sum) : "$1"); return sum; @@ -187,7 +186,7 @@ unsigned short proto, unsigned int sum) { - return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); + return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum)); } /* @@ -206,64 +205,60 @@ unsigned short proto, unsigned int sum) { - __asm__(" - .set noreorder - .set noat - addu %0,%5 # proto (long in network byte order) - sltu $1,%0,%5 - addu %0,$1 - - addu %0,%6 # csum - sltu $1,%0,%6 - lw %1,0(%2) # four words source address - addu %0,$1 - addu %0,%1 - sltu $1,%0,$1 - - lw %1,4(%2) - addu %0,$1 - addu %0,%1 - sltu $1,%0,$1 - - lw %1,8(%2) - addu %0,$1 - addu %0,%1 - sltu $1,%0,$1 - - lw %1,12(%2) - addu %0,$1 - addu %0,%1 - sltu $1,%0,$1 - - lw %1,0(%3) - addu %0,$1 - addu %0,%1 - sltu $1,%0,$1 - - lw %1,4(%3) - addu %0,$1 - addu %0,%1 - sltu $1,%0,$1 - - lw %1,8(%3) - addu %0,$1 - addu %0,%1 - sltu $1,%0,$1 - - lw %1,12(%3) - addu %0,$1 - addu %0,%1 - sltu $1,%0,$1 - .set noat - .set noreorder" - : "=r" (sum), - "=r" (proto) - : "r" (saddr), - "r" (daddr), - "0" (htonl(len)), - "1" (htonl(proto)), - "r"(sum) - : "$1"); + __asm__( + ".set\tnoreorder\t\t\t# csum_ipv6_magic\n\t" + ".set\tnoat\n\t" + "addu\t%0, %5\t\t\t# proto (long in network byte order)\n\t" + "sltu\t$1, %0, %5\n\t" + "addu\t%0, $1\n\t" + + "addu\t%0, %6\t\t\t# csum\n\t" + "sltu\t$1, %0, %6\n\t" + "lw\t%1, 0(%2)\t\t\t# four words source address\n\t" + "addu\t%0, $1\n\t" + "addu\t%0, %1\n\t" + "sltu\t$1, %0, $1\n\t" + + "lw\t%1, 4(%2)\n\t" + "addu\t%0, $1\n\t" + "addu\t%0, %1\n\t" + "sltu\t$1, %0, $1\n\t" + + "lw\t%1, 8(%2)\n\t" + "addu\t%0, $1\n\t" + "addu\t%0, %1\n\t" + "sltu\t$1, %0, $1\n\t" + + "lw\t%1, 12(%2)\n\t" + "addu\t%0, $1\n\t" + "addu\t%0, %1\n\t" + "sltu\t$1, %0, $1\n\t" + + "lw\t%1, 0(%3)\n\t" + "addu\t%0, $1\n\t" + "addu\t%0, %1\n\t" + "sltu\t$1, %0, $1\n\t" + + "lw\t%1, 4(%3)\n\t" + "addu\t%0, $1\n\t" + "addu\t%0, %1\n\t" + "sltu\t$1, %0, $1\n\t" + + "lw\t%1, 8(%3)\n\t" + "addu\t%0, $1\n\t" + "addu\t%0, %1\n\t" + "sltu\t$1, %0, $1\n\t" + + "lw\t%1, 12(%3)\n\t" + "addu\t%0, $1\n\t" + "addu\t%0, %1\n\t" + "sltu\t$1, %0, $1\n\t" + ".set\tnoat\n\t" + ".set\tnoreorder" + : "=r" (sum), "=r" (proto) + : "r" (saddr), "r" (daddr), + "0" (htonl(len)), "1" (htonl(proto)), "r" (sum) + : "$1"); return csum_fold(sum); } diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/cpu.h linux/include/asm-mips/cpu.h --- v2.4.5/linux/include/asm-mips/cpu.h Sat May 13 08:31:25 2000 +++ linux/include/asm-mips/cpu.h Mon Jul 2 13:56:40 2001 @@ -1,40 +1,132 @@ -/* $Id: cpu.h,v 1.1 1996/06/23 09:38:33 dm Exp $ +/* * cpu.h: Values of the PRId register used to match up * various MIPS cpu types. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) */ -#ifndef _MIPS_CPU_H -#define _MIPS_CPU_H +#ifndef _ASM_CPU_H +#define _ASM_CPU_H + +#include +/* Assigned Company values for bits 23:16 of the PRId Register + (CP0 register 15, select 0). As of the MIPS32 and MIPS64 specs from + MTI, the PRId register is defined in this (backwards compatible) + way: + + +----------------+----------------+----------------+----------------+ + | Company Options| Company ID | Processor ID | Revision | + +----------------+----------------+----------------+----------------+ + 31 24 23 16 15 8 7 + + I don't have docs for all the previous processors, but my impression is + that bits 16-23 have been 0 for all MIPS processors before the MIPS32/64 + spec. +*/ + +#define PRID_COMP_LEGACY 0x000000 +#define PRID_COMP_MIPS 0x010000 +#define PRID_COMP_ALCHEMY 0x030000 +/* + * Don't know who should be here...QED and Sandcraft, maybe? + */ +#define PRID_COMP_SIBYTE 0x040000 /* * Assigned values for the product ID register. In order to detect a * certain CPU type exactly eventually additional registers may need to - * be examined. + * be examined. These are valid when 23:16 == PRID_COMP_LEGACY + */ +#define PRID_IMP_R2000 0x0100 +#define PRID_IMP_AU1000 0x0100 +#define PRID_IMP_R3000 0x0200 /* Same as R2000A */ +#define PRID_IMP_R6000 0x0300 /* Same as R3000A */ +#define PRID_IMP_R4000 0x0400 +#define PRID_IMP_R6000A 0x0600 +#define PRID_IMP_R10000 0x0900 +#define PRID_IMP_R4300 0x0b00 +#define PRID_IMP_R12000 0x0e00 +#define PRID_IMP_R8000 0x1000 +#define PRID_IMP_R4600 0x2000 +#define PRID_IMP_R4700 0x2100 +#define PRID_IMP_TX39 0x2200 +#define PRID_IMP_R4640 0x2200 +#define PRID_IMP_R4650 0x2200 /* Same as R4640 */ +#define PRID_IMP_R5000 0x2300 +#define PRID_IMP_R5432 0x5400 +#define PRID_IMP_SONIC 0x2400 +#define PRID_IMP_MAGIC 0x2500 +#define PRID_IMP_RM7000 0x2700 +#define PRID_IMP_NEVADA 0x2800 /* RM5260 ??? */ +#define PRID_IMP_4KC 0x8000 +#define PRID_IMP_5KC 0x8100 +#define PRID_IMP_4KEC 0x8400 +#define PRID_IMP_4KSC 0x8600 + + +#define PRID_IMP_UNKNOWN 0xff00 + +/* + * These are the PRID's for when 23:16 == PRID_COMP_SIBYTE + */ + +#define PRID_IMP_SB1 0x0100 + +/* + * Definitions for 7:0 on legacy processors + */ + + +#define PRID_REV_R4400 0x0040 +#define PRID_REV_R3000A 0x0030 +#define PRID_REV_R3000 0x0020 +#define PRID_REV_R2000A 0x0010 +#define PRID_REV_TX3912 0x0010 +#define PRID_REV_TX3922 0x0030 +#define PRID_REV_TX3927 0x0040 + +#ifndef _LANGUAGE_ASSEMBLY +/* + * Capability and feature descriptor structure for MIPS CPU + */ +struct mips_cpu { + unsigned int processor_id; + unsigned int cputype; /* Old "mips_cputype" code */ + int isa_level; + int options; + int tlbsize; + struct cache_desc icache; /* Primary I-cache */ + struct cache_desc dcache; /* Primary D or combined I/D cache */ + struct cache_desc scache; /* Secondary cache */ + struct cache_desc tcache; /* Tertiary/split secondary cache */ +}; + +#endif + +/* + * ISA Level encodings + */ +#define MIPS_CPU_ISA_I 0x00000001 +#define MIPS_CPU_ISA_II 0x00000002 +#define MIPS_CPU_ISA_III 0x00000003 +#define MIPS_CPU_ISA_IV 0x00000004 +#define MIPS_CPU_ISA_V 0x00000005 +#define MIPS_CPU_ISA_M32 0x00000020 +#define MIPS_CPU_ISA_M64 0x00000040 + +/* + * CPU Option encodings */ -#define PRID_IMP_R2000 0x0100 -#define PRID_IMP_R3000 0x0200 -#define PRID_IMP_R6000 0x0300 -#define PRID_IMP_R4000 0x0400 -#define PRID_IMP_R6000A 0x0600 -#define PRID_IMP_R10000 0x0900 -#define PRID_IMP_R4300 0x0b00 -#define PRID_IMP_R8000 0x1000 -#define PRID_IMP_R4600 0x2000 -#define PRID_IMP_R4700 0x2100 -#define PRID_IMP_R4640 0x2200 -#define PRID_IMP_R4650 0x2200 /* Same as R4640 */ -#define PRID_IMP_R5000 0x2300 -#define PRID_IMP_SONIC 0x2400 -#define PRID_IMP_MAGIC 0x2500 -#define PRID_IMP_RM7000 0x2700 -#define PRID_IMP_NEVADA 0x2800 /* RM5260 ??? */ - -#define PRID_IMP_UNKNOWN 0xff00 - -#define PRID_REV_R4400 0x0040 -#define PRID_REV_R3000A 0x0030 -#define PRID_REV_R3000 0x0020 -#define PRID_REV_R2000A 0x0010 +#define MIPS_CPU_TLB 0x00000001 /* CPU has TLB */ +/* Leave a spare bit for variant MMU types... */ +#define MIPS_CPU_4KEX 0x00000004 /* "R4K" exception model */ +#define MIPS_CPU_4KTLB 0x00000008 /* "R4K" TLB handler */ +#define MIPS_CPU_FPU 0x00000010 /* CPU has FPU */ +#define MIPS_CPU_32FPR 0x00000020 /* 32 dbl. prec. FP registers */ +#define MIPS_CPU_COUNTER 0x00000040 /* Cycle count/compare */ +#define MIPS_CPU_WATCH 0x00000080 /* watchpoint registers */ +#define MIPS_CPU_MIPS16 0x00000100 /* code compression */ +#define MIPS_CPU_DIVEC 0x00000200 /* dedicated interrupt vector */ +#define MIPS_CPU_VCE 0x00000400 /* virt. coherence conflict possible */ +#define MIPS_CPU_CACHE_CDEX 0x00000800 /* Create_Dirty_Exclusive CACHE op */ -#endif /* !(_MIPS_CPU_H) */ +#endif /* _ASM_CPU_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/current.h linux/include/asm-mips/current.h --- v2.4.5/linux/include/asm-mips/current.h Sat May 13 08:31:25 2000 +++ linux/include/asm-mips/current.h Mon Jul 2 13:56:40 2001 @@ -1,5 +1,4 @@ -/* $Id: current.h,v 1.5 1999/07/26 19:42:43 harald Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -16,21 +15,5 @@ register struct task_struct *current asm("$28"); #endif /* _LANGUAGE_C */ -#ifdef _LANGUAGE_ASSEMBLY - -/* - * Special variant for use by exception handlers when the stack pointer - * is not loaded. - */ -#define _GET_CURRENT(reg) \ - lui reg, %hi(kernelsp); \ - .set push; \ - .set reorder; \ - lw reg, %lo(kernelsp)(reg); \ - .set pop; \ - ori reg, 8191; \ - xori reg, 8191 - -#endif #endif /* _ASM_CURRENT_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/delay.h linux/include/asm-mips/delay.h --- v2.4.5/linux/include/asm-mips/delay.h Sun Jul 9 22:18:15 2000 +++ linux/include/asm-mips/delay.h Mon Jul 2 13:56:40 2001 @@ -1,17 +1,18 @@ -/* $Id: delay.h,v 1.2 1999/01/04 16:09:20 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 1994 by Waldorf Electronics - * Copyright (C) 1995 - 1998 by Ralf Baechle + * Copyright (C) 1995 - 1998, 2001 by Ralf Baechle */ #ifndef _ASM_DELAY_H #define _ASM_DELAY_H #include +extern unsigned long loops_per_jiffy; + extern __inline__ void __delay(unsigned long loops) { @@ -34,21 +35,21 @@ * first constant multiplications gets optimized away if the delay is * a constant) */ -extern __inline__ void __udelay(unsigned long usecs, unsigned long lps) +extern __inline__ void __udelay(unsigned long usecs, unsigned long lpj) { unsigned long lo; - usecs *= 0x000010c6; /* 2**32 / 1000000 */ + usecs *= 0x00068db8; /* 2**32 / (1000000 / HZ) */ __asm__("multu\t%2,%3" :"=h" (usecs), "=l" (lo) - :"r" (usecs),"r" (lps)); + :"r" (usecs),"r" (lpj)); __delay(usecs); } #ifdef CONFIG_SMP #define __udelay_val cpu_data[smp_processor_id()].udelay_val #else -#define __udelay_val loops_per_sec +#define __udelay_val loops_per_jiffy #endif #define udelay(usecs) __udelay((usecs),__udelay_val) diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/div64.h linux/include/asm-mips/div64.h --- v2.4.5/linux/include/asm-mips/div64.h Sat May 13 08:31:25 2000 +++ linux/include/asm-mips/div64.h Mon Jul 2 13:56:40 2001 @@ -1,4 +1,7 @@ -/* $Id: div64.h,v 1.1 2000/01/28 23:18:43 ralf Exp $ +/* + * include/asm-mips/div64.h + * + * Copyright (C) 2000 Maciej W. Rozycki * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -7,14 +10,104 @@ #ifndef _ASM_DIV64_H #define _ASM_DIV64_H +#include + /* - * Hey, we're already 64-bit, no - * need to play games.. + * No traps on overflows for any of these... */ -#define do_div(n,base) ({ \ - int __res; \ - __res = ((unsigned long) n) % (unsigned) base; \ - n = ((unsigned long) n) / (unsigned) base; \ - __res; }) + +#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) + +#define do_div64_32(res, high, low, base) ({ \ + unsigned long __quot, __mod; \ + unsigned long __cf, __tmp, __i; \ + \ + __asm__(".set push\n\t" \ + ".set noat\n\t" \ + ".set noreorder\n\t" \ + "b 1f\n\t" \ + " li %4,0x21\n" \ + "0:\n\t" \ + "sll $1,%0,0x1\n\t" \ + "srl %3,%0,0x1f\n\t" \ + "or %0,$1,$2\n\t" \ + "sll %1,%1,0x1\n\t" \ + "sll %2,%2,0x1\n" \ + "1:\n\t" \ + "bnez %3,2f\n\t" \ + "sltu $2,%0,%z5\n\t" \ + "bnez $2,3f\n\t" \ + "2:\n\t" \ + " addiu %4,%4,-1\n\t" \ + "subu %0,%0,%z5\n\t" \ + "addiu %2,%2,1\n" \ + "3:\n\t" \ + "bnez %4,0b\n\t" \ + " srl $2,%1,0x1f\n\t" \ + ".set pop" \ + : "=&r" (__mod), "=&r" (__tmp), "=&r" (__quot), "=&r" (__cf), \ + "=&r" (__i) \ + : "Jr" (base), "0" (high), "1" (low), "2" (0), "3" (0) \ + /* Aarrgh! Ran out of gcc's limit on constraints... */ \ + : "$1", "$2"); \ + \ + (res) = __quot; \ + __mod; }) + +#define do_div(n, base) ({ \ + unsigned long long __quot; \ + unsigned long __upper, __low, __high, __mod; \ + \ + __quot = (n); \ + __high = __quot >> 32; \ + __low = __quot; \ + __upper = __high; \ + \ + if (__high) \ + __asm__("divu $0,%z2,%z3" \ + : "=h" (__upper), "=l" (__high) \ + : "Jr" (__high), "Jr" (base)); \ + \ + __mod = do_div64_32(__low, __upper, __low, base); \ + \ + __quot = __high; \ + __quot = __quot << 32 | __low; \ + (n) = __quot; \ + __mod; }) + +#else + +#define do_div64_32(res, high, low, base) ({ \ + unsigned long __quot, __mod, __r0; \ + \ + __asm__("dsll32 %2,%z3,0\n\t" \ + "or %2,%2,%z4\n\t" \ + "ddivu $0,%2,%z5" \ + : "=h" (__mod), "=l" (__quot), "=&r" (__r0) \ + : "Jr" (high), "Jr" (low), "Jr" (base)); \ + \ + (res) = __quot; \ + __mod; }) + +#define do_div(n, base) ({ \ + unsigned long long __quot; \ + unsigned long __mod, __r0; \ + \ + __quot = (n); \ + \ + __asm__("dsll32 %2,%M3,0\n\t" \ + "or %2,%2,%L3\n\t" \ + "ddivu $0,%2,%z4\n\t" \ + "mflo %L1\n\t" \ + "dsra32 %M1,%L1,0\n\t" \ + "dsll32 %L1,%L1,0\n\t" \ + "dsra32 %L1,%L1,0" \ + : "=h" (__mod), "=r" (__quot), "=&r" (__r0) \ + : "r" (n), "Jr" (base)); \ + \ + (n) = __quot; \ + __mod; }) + +#endif #endif /* _ASM_DIV64_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/elf.h linux/include/asm-mips/elf.h --- v2.4.5/linux/include/asm-mips/elf.h Thu Jul 27 18:36:54 2000 +++ linux/include/asm-mips/elf.h Mon Jul 2 13:56:40 2001 @@ -25,8 +25,7 @@ int __res = 1; \ struct elfhdr *__h = (hdr); \ \ - if ((__h->e_machine != EM_MIPS) && \ - (__h->e_machine != EM_MIPS_RS4_BE)) \ + if (__h->e_machine != EM_MIPS) \ __res = 0; \ if (__h->e_flags & EF_MIPS_ARCH) \ __res = 0; \ @@ -35,17 +34,7 @@ }) /* This one accepts IRIX binaries. */ -#define irix_elf_check_arch(hdr) \ -({ \ - int __res = 1; \ - struct elfhdr *__h = (hdr); \ - \ - if ((__h->e_machine != EM_MIPS) && \ - (__h->e_machine != EM_MIPS_RS4_BE)) \ - __res = 0; \ - \ - __res; \ -}) +#define irix_elf_check_arch(hdr) ((hdr)->e_machine == EM_MIPS) /* * These are used to set parameters in the core dumps. diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/errno.h linux/include/asm-mips/errno.h --- v2.4.5/linux/include/asm-mips/errno.h Thu Feb 24 22:52:30 2000 +++ linux/include/asm-mips/errno.h Mon Jul 2 13:56:40 2001 @@ -1,11 +1,9 @@ /* - * include/asm-mips/errno.h - * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995, 1999 by Ralf Baechle + * Copyright (C) 1995, 1999, 2001 by Ralf Baechle */ #ifndef _ASM_ERRNO_H #define _ASM_ERRNO_H diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/fcntl.h linux/include/asm-mips/fcntl.h --- v2.4.5/linux/include/asm-mips/fcntl.h Fri Sep 22 14:21:20 2000 +++ linux/include/asm-mips/fcntl.h Mon Jul 2 13:56:40 2001 @@ -1,13 +1,12 @@ -/* $Id: fcntl.h,v 1.4 1998/09/19 19:19:36 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle */ -#ifndef __ASM_MIPS_FCNTL_H -#define __ASM_MIPS_FCNTL_H +#ifndef __ASM_FCNTL_H +#define __ASM_FCNTL_H /* open/fcntl - O_SYNC is only implemented on blocks devices and on files located on an ext2 file system */ @@ -44,6 +43,10 @@ #define F_SETSIG 10 /* for sockets. */ #define F_GETSIG 11 /* for sockets. */ +#define F_GETLK64 33 /* using 'struct flock64' */ +#define F_SETLK64 34 +#define F_SETLKW64 35 + /* for F_[GET|SET]FL */ #define FD_CLOEXEC 1 /* actually anything with low bit set goes */ @@ -76,10 +79,19 @@ short l_whence; __kernel_off_t l_start; __kernel_off_t l_len; - long l_sysid; /* XXXXXXXXXXXXXXXXXXXXXXXXX */ + long l_sysid; /* ABI junk, unused on Linux */ __kernel_pid_t l_pid; - long pad[4]; /* ZZZZZZZZZZZZZZZZZZZZZZZZZZ */ + long pad[4]; /* ABI junk, unused on Linux */ } flock_t; +typedef struct flock64 { + short l_type; + short l_whence; + loff_t l_start; + loff_t l_len; + pid_t l_pid; +} flock64_t; + #define F_LINUX_SPECIFIC_BASE 1024 -#endif /* __ASM_MIPS_FCNTL_H */ + +#endif /* __ASM_FCNTL_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/fpu_emulator.h linux/include/asm-mips/fpu_emulator.h --- v2.4.5/linux/include/asm-mips/fpu_emulator.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/fpu_emulator.h Mon Jul 2 13:56:40 2001 @@ -0,0 +1,44 @@ +/* + * Definitiona for the Algorithmics FPU Emulator port into MIPS Linux + */ +/************************************************************************** + * + * include/asm-mips/fpu_emulator.h + * + * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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. + * + *************************************************************************/ +/* + * Further private data for which no space exists in mips_fpu_soft_struct. + * This should be subsumed into the mips_fpu_soft_struct structure as + * defined in processor.h as soon as the absurd wired absolute assembler + * offsets become dynamic at compile time. + */ + +struct mips_fpu_emulator_private { + unsigned int eir; + struct { + unsigned int emulated; + unsigned int loads; + unsigned int stores; + unsigned int cp1ops; + unsigned int cp1xops; + unsigned int errors; + } stats; +}; diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/hardirq.h linux/include/asm-mips/hardirq.h --- v2.4.5/linux/include/asm-mips/hardirq.h Fri Aug 4 16:15:37 2000 +++ linux/include/asm-mips/hardirq.h Mon Jul 2 13:56:40 2001 @@ -1,5 +1,4 @@ -/* $Id: hardirq.h,v 1.8 2000/03/02 02:37:13 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -13,6 +12,7 @@ #include #include #include +#include /* entry.S is sensitive to the offsets of these fields */ typedef struct { @@ -38,14 +38,60 @@ #define hardirq_trylock(cpu) (local_irq_count(cpu) == 0) #define hardirq_endlock(cpu) do { } while (0) -#define irq_enter(cpu) (local_irq_count(cpu)++) -#define irq_exit(cpu) (local_irq_count(cpu)--) +#define irq_enter(cpu, irq) (local_irq_count(cpu)++) +#define irq_exit(cpu, irq) (local_irq_count(cpu)--) #define synchronize_irq() barrier(); #else -#error No habla MIPS SMP +#include +#include +#include + +extern int global_irq_holder; +extern spinlock_t global_irq_lock; + +static inline int irqs_running (void) +{ + int i; + + for (i = 0; i < smp_num_cpus; i++) + if (local_irq_count(i)) + return 1; + return 0; +} + +static inline void release_irqlock(int cpu) +{ + /* if we didn't own the irq lock, just ignore.. */ + if (global_irq_holder == cpu) { + global_irq_holder = NO_PROC_ID; + spin_unlock(&global_irq_lock); + } +} + +static inline int hardirq_trylock(int cpu) +{ + return !local_irq_count(cpu) && !spin_is_locked(&global_irq_lock); +} + +#define hardirq_endlock(cpu) do { } while (0) + +static inline void irq_enter(int cpu, int irq) +{ + ++local_irq_count(cpu); + + while (spin_is_locked(&global_irq_lock)) + barrier(); +} + +static inline void irq_exit(int cpu, int irq) +{ + --local_irq_count(cpu); +} + +extern void synchronize_irq(void); #endif /* CONFIG_SMP */ #endif /* _ASM_HARDIRQ_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/hdreg.h linux/include/asm-mips/hdreg.h --- v2.4.5/linux/include/asm-mips/hdreg.h Sat May 13 08:31:25 2000 +++ linux/include/asm-mips/hdreg.h Mon Jul 2 13:56:40 2001 @@ -1,18 +1,15 @@ -/* $Id: hdreg.h,v 1.4 1998/05/08 21:05:26 davem Exp $ - * - * linux/include/asm-mips/hdreg.h - * +/* * Copyright (C) 1994-1996 Linus Torvalds & authors + * Copyright (C) 2001 Ralf Baechle */ /* * This file contains the MIPS architecture specific IDE code. */ -#ifndef __ASM_MIPS_HDREG_H -#define __ASM_MIPS_HDREG_H - -typedef unsigned short ide_ioreg_t; +#ifndef _ASM_HDREG_H +#define _ASM_HDREG_H -#endif /* __ASM_MIPS_HDREG_H */ +typedef unsigned long ide_ioreg_t; +#endif /* _ASM_HDREG_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/hw_irq.h linux/include/asm-mips/hw_irq.h --- v2.4.5/linux/include/asm-mips/hw_irq.h Sat May 13 08:31:25 2000 +++ linux/include/asm-mips/hw_irq.h Mon Jul 2 13:56:40 2001 @@ -1,5 +1,16 @@ -/* This exists merely to satisfy . There is - nothing that would go here of general interest. +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2000, 2001 by Ralf Baechle + */ +#ifndef _ASM_HW_IRQ_H +#define _ASM_HW_IRQ_H - Everything of consequence is in arch/alpha/kernel/irq_impl.h, - to be used only in arch/alpha/kernel/. */ +/* This may not be apropriate for all machines, we'll see ... */ +static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) +{ +} + +#endif /* _ASM_HW_IRQ_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/ide.h linux/include/asm-mips/ide.h --- v2.4.5/linux/include/asm-mips/ide.h Sun Jul 9 22:18:15 2000 +++ linux/include/asm-mips/ide.h Mon Jul 2 13:56:40 2001 @@ -8,16 +8,13 @@ * Copyright (C) 1994-1996 Linus Torvalds & authors */ -/* - * This file contains the MIPS architecture specific IDE code. - */ - #ifndef __ASM_IDE_H #define __ASM_IDE_H #ifdef __KERNEL__ #include +#include #ifndef MAX_HWIFS # ifdef CONFIG_BLK_DEV_IDEPCI @@ -93,13 +90,21 @@ typedef union { unsigned all : 8; /* all of the bits together */ struct { +#ifdef __MIPSEB__ + unsigned bit7 : 1; /* always 1 */ + unsigned lba : 1; /* using LBA instead of CHS */ + unsigned bit5 : 1; /* always 1 */ + unsigned unit : 1; /* drive select number, 0 or 1 */ + unsigned head : 4; /* always zeros here */ +#else unsigned head : 4; /* always zeros here */ unsigned unit : 1; /* drive select number, 0 or 1 */ unsigned bit5 : 1; /* always 1 */ unsigned lba : 1; /* using LBA instead of CHS */ unsigned bit7 : 1; /* always 1 */ +#endif } b; - } select_t; +} select_t; static __inline__ int ide_request_irq(unsigned int irq, void (*handler)(int,void *, struct pt_regs *), unsigned long flags, const char *device, void *dev_id) @@ -129,11 +134,96 @@ ide_ops->ide_release_region(from, extent); } +#undef SUPPORT_VLB_SYNC +#define SUPPORT_VLB_SYNC 0 + +#if defined(__MIPSEB__) + +#define T_CHAR (0x0000) /* char: don't touch */ +#define T_SHORT (0x4000) /* short: 12 -> 21 */ +#define T_INT (0x8000) /* int: 1234 -> 4321 */ +#define T_TEXT (0xc000) /* text: 12 -> 21 */ + +#define T_MASK_TYPE (0xc000) +#define T_MASK_COUNT (0x3fff) + +#define D_CHAR(cnt) (T_CHAR | (cnt)) +#define D_SHORT(cnt) (T_SHORT | (cnt)) +#define D_INT(cnt) (T_INT | (cnt)) +#define D_TEXT(cnt) (T_TEXT | (cnt)) + +static u_short driveid_types[] = { + D_SHORT(10), /* config - vendor2 */ + D_TEXT(20), /* serial_no */ + D_SHORT(3), /* buf_type - ecc_bytes */ + D_TEXT(48), /* fw_rev - model */ + D_CHAR(2), /* max_multsect - vendor3 */ + D_SHORT(1), /* dword_io */ + D_CHAR(2), /* vendor4 - capability */ + D_SHORT(1), /* reserved50 */ + D_CHAR(4), /* vendor5 - tDMA */ + D_SHORT(4), /* field_valid - cur_sectors */ + D_INT(1), /* cur_capacity */ + D_CHAR(2), /* multsect - multsect_valid */ + D_INT(1), /* lba_capacity */ + D_SHORT(194) /* dma_1word - reservedyy */ +}; + +#define num_driveid_types (sizeof(driveid_types)/sizeof(*driveid_types)) + +static __inline__ void ide_fix_driveid(struct hd_driveid *id) +{ + u_char *p = (u_char *)id; + int i, j, cnt; + u_char t; + + for (i = 0; i < num_driveid_types; i++) { + cnt = driveid_types[i] & T_MASK_COUNT; + switch (driveid_types[i] & T_MASK_TYPE) { + case T_CHAR: + p += cnt; + break; + case T_SHORT: + for (j = 0; j < cnt; j++) { + t = p[0]; + p[0] = p[1]; + p[1] = t; + p += 2; + } + break; + case T_INT: + for (j = 0; j < cnt; j++) { + t = p[0]; + p[0] = p[3]; + p[3] = t; + t = p[1]; + p[1] = p[2]; + p[2] = t; + p += 4; + } + break; + case T_TEXT: + for (j = 0; j < cnt; j += 2) { + t = p[0]; + p[0] = p[1]; + p[1] = t; + p += 2; + } + break; + }; + } +} + +#else /* defined(CONFIG_SWAP_IO_SPACE) && defined(__MIPSEB__) */ + +#define ide_fix_driveid(id) do {} while (0) + +#endif + /* * The following are not needed for the non-m68k ports */ #define ide_ack_intr(hwif) (1) -#define ide_fix_driveid(id) do {} while (0) #define ide_release_lock(lock) do {} while (0) #define ide_get_lock(lock, hdlr, data) do {} while (0) diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/inst.h linux/include/asm-mips/inst.h --- v2.4.5/linux/include/asm-mips/inst.h Thu Jun 26 12:33:39 1997 +++ linux/include/asm-mips/inst.h Mon Jul 2 13:56:40 2001 @@ -5,10 +5,10 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1996 by Ralf Baechle + * Copyright (C) 1996, 2000 by Ralf Baechle */ -#ifndef __ASM_MIPS_INST_H -#define __ASM_MIPS_INST_H +#ifndef _ASM_INST_H +#define _ASM_INST_H /* * Major opcodes; before MIPS IV cop1x was called cop3. @@ -21,7 +21,7 @@ cop0_op, cop1_op, cop2_op, cop1x_op, beql_op, bnel_op, blezl_op, bgtzl_op, daddi_op, daddiu_op, ldl_op, ldr_op, - major_1c_op, major_1d_op, major_1e_op, major_1f_op, + major_1c_op, jalx_op, major_1e_op, major_1f_op, lb_op, lh_op, lwl_op, lw_op, lbu_op, lhu_op, lwr_op, lwu_op, sb_op, sh_op, swl_op, sw_op, @@ -80,6 +80,13 @@ }; /* + * rt field of cop.bc_op opcodes + */ +enum bcop_op { + bcf_op, bct_op, bcfl_op, bctl_op +}; + +/* * func field of cop0 coi opcodes. */ enum cop0_coi_func { @@ -301,4 +308,64 @@ struct ma_format ma_format; }; -#endif /* __ASM_MIPS_INST_H */ +/* HACHACHAHCAHC ... */ + +/* In case some other massaging is needed, keep MIPSInst as wrapper */ + +#define MIPSInst(x) x + +#define I_OPCODE_SFT 26 +#define MIPSInst_OPCODE(x) (MIPSInst(x) >> I_OPCODE_SFT) + +#define I_JTARGET_SFT 0 +#define MIPSInst_JTARGET(x) (MIPSInst(x) & 0x03ffffff) + +#define I_RS_SFT 21 +#define MIPSInst_RS(x) ((MIPSInst(x) & 0x03e00000) >> I_RS_SFT) + +#define I_RT_SFT 16 +#define MIPSInst_RT(x) ((MIPSInst(x) & 0x001f0000) >> I_RT_SFT) + +#define I_IMM_SFT 0 +#define MIPSInst_SIMM(x) ((int)((short)(MIPSInst(x) & 0xffff))) +#define MIPSInst_UIMM(x) (MIPSInst(x) & 0xffff) + +#define I_CACHEOP_SFT 18 +#define MIPSInst_CACHEOP(x) ((MIPSInst(x) & 0x001c0000) >> I_CACHEOP_SFT) + +#define I_CACHESEL_SFT 16 +#define MIPSInst_CACHESEL(x) ((MIPSInst(x) & 0x00030000) >> I_CACHESEL_SFT) + +#define I_RD_SFT 11 +#define MIPSInst_RD(x) ((MIPSInst(x) & 0x0000f800) >> I_RD_SFT) + +#define I_RE_SFT 6 +#define MIPSInst_RE(x) ((MIPSInst(x) & 0x000007c0) >> I_RE_SFT) + +#define I_FUNC_SFT 0 +#define MIPSInst_FUNC(x) (MIPSInst(x) & 0x0000003f) + +#define I_FFMT_SFT 21 +#define MIPSInst_FFMT(x) ((MIPSInst(x) & 0x01e00000) >> I_FFMT_SFT) + +#define I_FT_SFT 16 +#define MIPSInst_FT(x) ((MIPSInst(x) & 0x001f0000) >> I_FT_SFT) + +#define I_FS_SFT 11 +#define MIPSInst_FS(x) ((MIPSInst(x) & 0x0000f800) >> I_FS_SFT) + +#define I_FD_SFT 6 +#define MIPSInst_FD(x) ((MIPSInst(x) & 0x000007c0) >> I_FD_SFT) + +#define I_FR_SFT 21 +#define MIPSInst_FR(x) ((MIPSInst(x) & 0x03e00000) >> I_FR_SFT) + +#define I_FMA_FUNC_SFT 2 +#define MIPSInst_FMA_FUNC(x) ((MIPSInst(x) & 0x0000003c) >> I_FMA_FUNC_SFT) + +#define I_FMA_FFMT_SFT 0 +#define MIPSInst_FMA_FFMT(x) (MIPSInst(x) & 0x00000003) + +typedef unsigned int mips_instruction; + +#endif /* _ASM_INST_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/io.h linux/include/asm-mips/io.h --- v2.4.5/linux/include/asm-mips/io.h Mon Feb 28 07:18:20 2000 +++ linux/include/asm-mips/io.h Mon Jul 2 13:56:40 2001 @@ -1,5 +1,4 @@ -/* $Id: io.h,v 1.13 2000/02/24 00:13:19 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -7,16 +6,38 @@ * Copyright (C) 1994, 1995 Waldorf GmbH * Copyright (C) 1994 - 2000 Ralf Baechle * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 FSMLabs, Inc. */ #ifndef _ASM_IO_H #define _ASM_IO_H +#include +#include +#include +#include + /* * Slowdown I/O port space accesses for antique hardware. */ #undef CONF_SLOWDOWN_IO -#include +/* + * Sane hardware offers swapping of I/O space accesses in hardware; less + * sane hardware forces software to fiddle with this ... + */ +#if defined(CONFIG_SWAP_IO_SPACE) && defined(__MIPSEB__) + +#define __ioswab8(x) (x) +#define __ioswab16(x) swab16(x) +#define __ioswab32(x) swab32(x) + +#else + +#define __ioswab8(x) (x) +#define __ioswab16(x) (x) +#define __ioswab32(x) (x) + +#endif /* * This file contains the definitions for the MIPS counterpart of the @@ -91,9 +112,6 @@ return (void *)KSEG0ADDR(address); } -extern void * ioremap(unsigned long phys_addr, unsigned long size); -extern void iounmap(void *addr); - /* * IO bus memory addresses are also 1:1 with the physical address */ @@ -113,54 +131,35 @@ */ extern unsigned long isa_slot_offset; -/* - * readX/writeX() are used to access memory mapped devices. On some - * architectures the memory mapped IO stuff needs to be accessed - * differently. On the x86 architecture, we just read/write the - * memory location directly. - * - * On MIPS, we have the whole physical address space mapped at all - * times, so "ioremap()" and "iounmap()" do not need to do anything. - * (This isn't true for all machines but we still handle these cases - * with wired TLB entries anyway ...) - * - * We cheat a bit and always return uncachable areas until we've fixed - * the drivers to handle caching properly. - */ -extern inline void * ioremap(unsigned long offset, unsigned long size) -{ - return (void *) KSEG1ADDR(offset); -} +extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags); -/* - * This one maps high address device memory and turns off caching for that area. - * it's useful if some control registers are in such an area and write combining - * or read caching is not desirable: - */ -extern inline void * ioremap_nocache (unsigned long offset, unsigned long size) +extern inline void *ioremap(unsigned long offset, unsigned long size) { - return (void *) KSEG1ADDR(offset); + return __ioremap(offset, size, _CACHE_UNCACHED); } -extern inline void iounmap(void *addr) +extern inline void *ioremap_nocache(unsigned long offset, unsigned long size) { + return __ioremap(offset, size, _CACHE_UNCACHED); } +extern void iounmap(void *addr); + /* * XXX We need system specific versions of these to handle EISA address bits * 24-31 on SNI. * XXX more SNI hacks. */ #define readb(addr) (*(volatile unsigned char *)(addr)) -#define readw(addr) (*(volatile unsigned short *)(addr)) -#define readl(addr) (*(volatile unsigned int *)(addr)) +#define readw(addr) __ioswab16((*(volatile unsigned short *)(addr))) +#define readl(addr) __ioswab32((*(volatile unsigned int *)(addr))) #define __raw_readb readb #define __raw_readw readw #define __raw_readl readl #define writeb(b,addr) (*(volatile unsigned char *)(addr)) = (b) -#define writew(b,addr) (*(volatile unsigned short *)(addr)) = (b) -#define writel(b,addr) (*(volatile unsigned int *)(addr)) = (b) +#define writew(b,addr) (*(volatile unsigned short *)(addr)) = (__ioswab16(b)) +#define writel(b,addr) (*(volatile unsigned int *)(addr)) = (__ioswab32(b)) #define __raw_writeb writeb #define __raw_writew writew #define __raw_writel writel @@ -226,12 +225,12 @@ #define __OUT2(m) \ __asm__ __volatile__ ("s" #m "\t%0,%1(%2)" -#define __OUT(m,s) \ -__OUT1(s) __OUT2(m) : : "r" (value), "i" (0), "r" (mips_io_port_base+port)); } \ -__OUT1(s##c) __OUT2(m) : : "r" (value), "ir" (port), "r" (mips_io_port_base)); } \ -__OUT1(s##_p) __OUT2(m) : : "r" (value), "i" (0), "r" (mips_io_port_base+port)); \ +#define __OUT(m,s,w) \ +__OUT1(s) __OUT2(m) : : "r" (__ioswab##w(value)), "i" (0), "r" (mips_io_port_base+port)); } \ +__OUT1(s##c) __OUT2(m) : : "r" (__ioswab##w(value)), "ir" (port), "r" (mips_io_port_base)); } \ +__OUT1(s##_p) __OUT2(m) : : "r" (__ioswab##w(value)), "i" (0), "r" (mips_io_port_base+port)); \ SLOW_DOWN_IO; } \ -__OUT1(s##c_p) __OUT2(m) : : "r" (value), "ir" (port), "r" (mips_io_port_base)); \ +__OUT1(s##c_p) __OUT2(m) : : "r" (__ioswab##w(value)), "ir" (port), "r" (mips_io_port_base)); \ SLOW_DOWN_IO; } #define __IN1(t,s) \ @@ -243,11 +242,11 @@ #define __IN2(m) \ __asm__ __volatile__ ("l" #m "\t%0,%1(%2)" -#define __IN(t,m,s) \ -__IN1(t,s) __IN2(m) : "=r" (_v) : "i" (0), "r" (mips_io_port_base+port)); return _v; } \ -__IN1(t,s##c) __IN2(m) : "=r" (_v) : "ir" (port), "r" (mips_io_port_base)); return _v; } \ -__IN1(t,s##_p) __IN2(m) : "=r" (_v) : "i" (0), "r" (mips_io_port_base+port)); SLOW_DOWN_IO; return _v; } \ -__IN1(t,s##c_p) __IN2(m) : "=r" (_v) : "ir" (port), "r" (mips_io_port_base)); SLOW_DOWN_IO; return _v; } +#define __IN(t,m,s,w) \ +__IN1(t,s) __IN2(m) : "=r" (_v) : "i" (0), "r" (mips_io_port_base+port)); return __ioswab##w(_v); } \ +__IN1(t,s##c) __IN2(m) : "=r" (_v) : "ir" (port), "r" (mips_io_port_base)); return __ioswab##w(_v); } \ +__IN1(t,s##_p) __IN2(m) : "=r" (_v) : "i" (0), "r" (mips_io_port_base+port)); SLOW_DOWN_IO; return __ioswab##w(_v); } \ +__IN1(t,s##c_p) __IN2(m) : "=r" (_v) : "ir" (port), "r" (mips_io_port_base)); SLOW_DOWN_IO; return __ioswab##w(_v); } #define __INS1(s) \ extern inline void __ins##s(unsigned int port, void * addr, unsigned long count) { @@ -268,11 +267,13 @@ #define __INS(m,s,i) \ __INS1(s) __INS2(m) \ : "=r" (addr), "=r" (count) \ - : "0" (addr), "1" (count), "i" (0), "r" (mips_io_port_base+port), "I" (i) \ + : "0" (addr), "1" (count), "i" (0), \ + "r" (mips_io_port_base+port), "I" (i) \ : "$1");} \ __INS1(s##c) __INS2(m) \ : "=r" (addr), "=r" (count) \ - : "0" (addr), "1" (count), "ir" (port), "r" (mips_io_port_base), "I" (i) \ + : "0" (addr), "1" (count), "ir" (port), \ + "r" (mips_io_port_base), "I" (i) \ : "$1");} #define __OUTS1(s) \ @@ -301,13 +302,13 @@ : "0" (addr), "1" (count), "ir" (port), "r" (mips_io_port_base), "I" (i) \ : "$1");} -__IN(unsigned char,b,b) -__IN(unsigned short,h,w) -__IN(unsigned int,w,l) - -__OUT(b,b) -__OUT(h,w) -__OUT(w,l) +__IN(unsigned char,b,b,8) +__IN(unsigned short,h,w,16) +__IN(unsigned int,w,l,32) + +__OUT(b,b,8) +__OUT(h,w,16) +__OUT(w,l,32) __INS(b,b,1) __INS(h,w,2) @@ -316,6 +317,7 @@ __OUTS(b,b,1) __OUTS(h,w,2) __OUTS(w,l,4) + /* * Note that due to the way __builtin_constant_p() works, you diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/ioctl.h linux/include/asm-mips/ioctl.h --- v2.4.5/linux/include/asm-mips/ioctl.h Thu Jun 26 12:33:39 1997 +++ linux/include/asm-mips/ioctl.h Mon Jul 2 13:56:40 2001 @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995, 1996 by Ralf Baechle + * Copyright (C) 1995, 1996, 2001 by Ralf Baechle */ #ifndef __ASM_MIPS_IOCTL_H #define __ASM_MIPS_IOCTL_H @@ -40,11 +40,6 @@ #define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS) /* - * We to additionally limit parameters to a maximum 255 bytes. - */ -#define _IOC_SLMASK 0xff - -/* * Direction bits _IOC_NONE could be 0, but OSF/1 gives it a bit. * And this turns out useful to catch old ioctl numbers in header * files for us. @@ -65,7 +60,7 @@ (((dir) << _IOC_DIRSHIFT) | \ ((type) << _IOC_TYPESHIFT) | \ ((nr) << _IOC_NRSHIFT) | \ - (((size) & _IOC_SLMASK) << _IOC_SIZESHIFT)) + ((size) << _IOC_SIZESHIFT)) /* used to create numbers */ #define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/ioctls.h linux/include/asm-mips/ioctls.h --- v2.4.5/linux/include/asm-mips/ioctls.h Sat May 13 08:31:25 2000 +++ linux/include/asm-mips/ioctls.h Mon Jul 2 13:56:40 2001 @@ -58,6 +58,7 @@ #define FIONCLEX 0x6602 /* these numbers need to be adjusted. */ #define FIOASYNC 0x667d #define FIONBIO 0x667e +#define FIOQSIZE 0x667f #if defined(__USE_MISC) || defined (__KERNEL__) #define TIOCGLTC (tIOC | 116) /* get special local chars */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/irq.h linux/include/asm-mips/irq.h --- v2.4.5/linux/include/asm-mips/irq.h Sat May 13 08:31:25 2000 +++ linux/include/asm-mips/irq.h Mon Jul 2 13:56:40 2001 @@ -1,25 +1,39 @@ -/* $Id: irq.h,v 1.6 2000/01/26 00:07:45 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 1994 by Waldorf GMBH, written by Ralf Baechle - * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle + * Copyright (C) 1995, 96, 97, 98, 99, 2000, 2001 by Ralf Baechle */ #ifndef _ASM_IRQ_H #define _ASM_IRQ_H -#define NR_IRQS 64 +#include + +#define NR_IRQS 64 /* Largest number of ints of all machines. */ #define TIMER_IRQ 0 -extern int (*irq_cannonicalize)(int irq); +#ifdef CONFIG_I8259 +static inline int irq_cannonicalize(int irq) +{ + return ((irq == 2) ? 9 : irq); +} +#else +#define irq_cannonicalize(irq) (irq) /* Sane hardware, sane code ... */ +#endif struct irqaction; extern int i8259_setup_irq(int irq, struct irqaction * new); extern void disable_irq(unsigned int); + +#ifdef CONFIG_ROTTEN_IRQ #define disable_irq_nosync disable_irq +#else +extern void disable_irq_nosync(unsigned int); +#endif + extern void enable_irq(unsigned int); /* Machine specific interrupt initialization */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/jazzdma.h linux/include/asm-mips/jazzdma.h --- v2.4.5/linux/include/asm-mips/jazzdma.h Sat May 13 08:31:25 2000 +++ linux/include/asm-mips/jazzdma.h Mon Jul 2 13:56:40 2001 @@ -1,29 +1,28 @@ /* * Helpfile for jazzdma.c -- Mips Jazz R4030 DMA controller support - * - * $Id:$ */ -#ifndef __ASM_MIPS_JAZZDMA_H -#define __ASM_MIPS_JAZZDMA_H +#ifndef _ASM_JAZZDMA_H +#define _ASM_JAZZDMA_H /* * Prototypes and macros */ -unsigned long vdma_init(unsigned long memory_start, unsigned long memory_end); -unsigned long vdma_alloc(unsigned long paddr, unsigned long size); -int vdma_free(unsigned long laddr); -int vdma_remap(unsigned long laddr, unsigned long paddr, unsigned long size); -unsigned long vdma_phys2log(unsigned long paddr); -unsigned long vdma_log2phys(unsigned long laddr); -void vdma_stats(void); /* for debugging only */ - -void vdma_enable(int channel); -void vdma_disable(int channel); -void vdma_set_mode(int channel, int mode); -void vdma_set_addr(int channel, long addr); -void vdma_set_count(int channel, int count); -int vdma_get_residue(int channel); -int vdma_get_enable(int channel); +extern void vdma_init(void); +extern unsigned long vdma_alloc(unsigned long paddr, unsigned long size); +extern int vdma_free(unsigned long laddr); +extern int vdma_remap(unsigned long laddr, unsigned long paddr, + unsigned long size); +extern unsigned long vdma_phys2log(unsigned long paddr); +extern unsigned long vdma_log2phys(unsigned long laddr); +extern void vdma_stats(void); /* for debugging only */ + +extern void vdma_enable(int channel); +extern void vdma_disable(int channel); +extern void vdma_set_mode(int channel, int mode); +extern void vdma_set_addr(int channel, long addr); +extern void vdma_set_count(int channel, int count); +extern int vdma_get_residue(int channel); +extern int vdma_get_enable(int channel); /* * some definitions used by the driver functions @@ -49,8 +48,7 @@ /* * VDMA pagetable entry description */ -typedef volatile struct VDMA_PGTBL_ENTRY -{ +typedef volatile struct VDMA_PGTBL_ENTRY { unsigned int frame; /* physical frame no. */ unsigned int owner; /* owner of this entry (0=free) */ } VDMA_PGTBL_ENTRY; @@ -95,4 +93,4 @@ #define R4030_MODE_BURST (1<<6) /* Rev. 2 only */ #define R4030_MODE_FAST_ACK (1<<7) /* Rev. 2 only */ -#endif /* __ASM_MIPS_JAZZDMA_H */ +#endif /* _ASM_JAZZDMA_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/keyboard.h linux/include/asm-mips/keyboard.h --- v2.4.5/linux/include/asm-mips/keyboard.h Fri Apr 13 20:26:07 2001 +++ linux/include/asm-mips/keyboard.h Mon Jul 2 13:56:40 2001 @@ -13,10 +13,13 @@ #include #include +#include #include #define DISABLE_KBD_DURING_INTERRUPTS 0 +#ifdef CONFIG_PC_KEYB + extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode); extern int pckbd_getkeycode(unsigned int scancode); extern int pckbd_translate(unsigned char scancode, unsigned char *keycode, @@ -34,6 +37,19 @@ #define kbd_leds pckbd_leds #define kbd_init_hw pckbd_init_hw #define kbd_sysrq_xlate pckbd_sysrq_xlate + +#else + +extern int kbd_setkeycode(unsigned int scancode, unsigned int keycode); +extern int kbd_getkeycode(unsigned int scancode); +extern int kbd_translate(unsigned char scancode, unsigned char *keycode, + char raw_mode); +extern char kbd_unexpected_up(unsigned char keycode); +extern void kbd_leds(unsigned char leds); +extern void kbd_init_hw(void); +extern unsigned char *kbd_sysrq_xlate; + +#endif #define SYSRQ_KEY 0x54 diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/linux_logo.h linux/include/asm-mips/linux_logo.h --- v2.4.5/linux/include/asm-mips/linux_logo.h Sat May 13 08:31:25 2000 +++ linux/include/asm-mips/linux_logo.h Mon Jun 11 19:15:27 2001 @@ -24,918 +24,897 @@ #define linux_logo_banner "Linux/MIPS version " UTS_RELEASE -#define LINUX_LOGO_COLORS 212 +#define __HAVE_ARCH_LINUX_LOGO + +#define LINUX_LOGO_COLORS 187 #ifdef INCLUDE_LINUX_LOGO_DATA unsigned char linux_logo_red[] __initdata = { - 0x03, 0x82, 0xE9, 0xBF, 0x42, 0xC9, 0x7E, 0xC0, - 0xE9, 0xE3, 0xC2, 0x24, 0xA4, 0x65, 0xEC, 0xC4, - 0x82, 0x9F, 0xF3, 0x12, 0x5F, 0xA0, 0xC2, 0xED, - 0x3E, 0xD5, 0xDB, 0xA0, 0x1C, 0xF4, 0xEB, 0xA4, - 0xCD, 0x0A, 0x9A, 0x51, 0xCC, 0xBE, 0xC0, 0xBA, - 0x74, 0xDC, 0xAA, 0xF6, 0xD3, 0xC5, 0xE6, 0x26, - 0xC2, 0x83, 0x38, 0xEA, 0x49, 0xB0, 0xED, 0xE5, - 0xF4, 0x96, 0x96, 0x1B, 0xFA, 0xCC, 0xF2, 0x0F, - 0xCD, 0xE5, 0xF4, 0xD3, 0x50, 0x7A, 0xB5, 0xDE, - 0xD5, 0xB6, 0x60, 0x0A, 0x6A, 0xEA, 0xD4, 0xEB, - 0xC1, 0xCA, 0xEA, 0xEC, 0x2A, 0x96, 0x95, 0xDC, - 0xE4, 0xCE, 0xEC, 0x1E, 0xDC, 0x8A, 0xD1, 0xF6, - 0x3C, 0x5E, 0xC6, 0xB4, 0xB2, 0xAC, 0xBA, 0x9E, - 0x0F, 0x59, 0xBA, 0xFA, 0xCC, 0xBF, 0x82, 0xCE, - 0xE6, 0x4F, 0xAA, 0x4C, 0xCA, 0x8E, 0x8E, 0xDF, - 0x2C, 0xB6, 0x3B, 0xDE, 0xCE, 0xEE, 0x46, 0x4A, - 0x6F, 0x7A, 0x82, 0xE4, 0xAA, 0x88, 0xE2, 0xCE, - 0xAE, 0xB6, 0x70, 0xC2, 0x9A, 0xDA, 0x35, 0x9E, - 0x95, 0xC0, 0x7E, 0x8C, 0xC2, 0xB6, 0xCE, 0xB9, - 0xD5, 0xAA, 0xC1, 0xF4, 0xC7, 0xB6, 0xB6, 0xA3, - 0xF2, 0x68, 0xDB, 0x76, 0xDC, 0x57, 0xD3, 0xA8, - 0xC0, 0xEF, 0x46, 0xF4, 0x2F, 0xD7, 0x53, 0x36, - 0xE6, 0xA7, 0xCA, 0xCB, 0x7E, 0xE4, 0x86, 0x9A, - 0xCE, 0x94, 0xB4, 0x1D, 0xDA, 0xCE, 0x6C, 0xE6, - 0x9E, 0xC6, 0xDA, 0x16, 0xFA, 0xAA, 0x56, 0xB6, - 0xFE, 0x6E, 0xEA, 0xCE, 0xE5, 0xCC, 0xDB, 0xD3, - 0xED, 0xDC, 0xF4, 0x72 + 0x00, 0x06, 0x0a, 0x0e, 0x16, 0x1a, 0x1e, 0x22, + 0x12, 0x00, 0x2a, 0x36, 0x42, 0x4e, 0x4a, 0x56, + 0x26, 0x46, 0x2e, 0x32, 0x52, 0x3a, 0x02, 0x65, + 0x5e, 0x3e, 0x74, 0x8a, 0xa2, 0x9a, 0x86, 0xc6, + 0xc3, 0x65, 0xbb, 0xd2, 0xda, 0xd6, 0xe2, 0xf6, + 0xfd, 0xae, 0x7b, 0xdd, 0xea, 0x6a, 0xaa, 0xe7, + 0xbe, 0x5a, 0xee, 0x9e, 0x95, 0x80, 0x76, 0x79, + 0x62, 0x36, 0x9a, 0xe2, 0xec, 0xe1, 0xb8, 0xd7, + 0xaf, 0x25, 0xbc, 0xc0, 0xef, 0xea, 0xe8, 0xe8, + 0xf5, 0xf1, 0xda, 0xd3, 0x79, 0xdb, 0xf4, 0xf6, + 0xf6, 0xf6, 0xe2, 0x3d, 0xb4, 0xce, 0xe6, 0xee, + 0xf6, 0x68, 0xd8, 0xec, 0xf5, 0xc6, 0xc8, 0x9c, + 0x89, 0xd2, 0xee, 0xcb, 0xb9, 0xd2, 0x66, 0x5e, + 0x8b, 0xbe, 0xa8, 0xd5, 0xca, 0xb6, 0xae, 0x9c, + 0xc5, 0xbe, 0xbe, 0xca, 0x90, 0xb2, 0x9a, 0xa8, + 0xb6, 0xf2, 0xce, 0xfa, 0xb2, 0x6e, 0xa6, 0x8d, + 0x12, 0x4a, 0x8e, 0xf2, 0xf6, 0xee, 0xb5, 0xe4, + 0xf1, 0x26, 0x9a, 0xea, 0xf6, 0xe0, 0xd2, 0x16, + 0x9a, 0x2e, 0x70, 0xd6, 0x46, 0x7c, 0xb4, 0x62, + 0xd6, 0xa3, 0x74, 0xa7, 0xa2, 0xca, 0xe0, 0xae, + 0xbe, 0xce, 0xa3, 0x8e, 0x6d, 0x8e, 0x32, 0xaf, + 0x50, 0x9e, 0x5b, 0x8a, 0x98, 0x82, 0x7a, 0x82, + 0x56, 0x7c, 0x8a, 0x56, 0x5e, 0x86, 0x6a, 0x52, + 0x59, 0x64, 0x5e, }; unsigned char linux_logo_green[] __initdata = { - 0x03, 0x82, 0xC4, 0x83, 0x42, 0xA2, 0x4A, 0xA4, - 0xE5, 0xA6, 0xC2, 0x24, 0xA4, 0x65, 0xB4, 0x94, - 0x66, 0x87, 0xB6, 0x12, 0x44, 0x6C, 0x96, 0xD4, - 0x36, 0x95, 0xB2, 0x92, 0x0E, 0xF4, 0xBC, 0x77, - 0xA5, 0x0A, 0x92, 0x52, 0xB4, 0x9A, 0x8C, 0xB2, - 0x74, 0xC2, 0x8E, 0xBD, 0xA2, 0xCA, 0xD2, 0x12, - 0xB6, 0x61, 0x24, 0xDA, 0x33, 0x79, 0xCB, 0xAC, - 0xDA, 0x84, 0x7A, 0x1B, 0xFA, 0x8D, 0xBE, 0x06, - 0x93, 0xBB, 0xBC, 0xAB, 0x44, 0x62, 0x83, 0xDA, - 0x9B, 0xA2, 0x4C, 0x04, 0x6A, 0xB6, 0xC8, 0xBD, - 0x8D, 0xB6, 0xAD, 0xEC, 0x2A, 0x68, 0x62, 0x9D, - 0xC4, 0xC4, 0xB4, 0x13, 0xA3, 0x8A, 0xD2, 0xD6, - 0x3C, 0x5D, 0x8C, 0x7E, 0x82, 0xAC, 0x96, 0x7E, - 0x0D, 0x5A, 0xBA, 0xBB, 0xCC, 0xBE, 0x76, 0xB6, - 0xDE, 0x4E, 0x9A, 0x3C, 0xBE, 0x8E, 0x6E, 0xCB, - 0x1C, 0xAA, 0x2E, 0xBE, 0xAA, 0xDE, 0x3E, 0x4B, - 0x4D, 0x7A, 0x54, 0xE4, 0x8E, 0x6E, 0xCA, 0x9B, - 0x70, 0x9E, 0x5A, 0xAA, 0x9A, 0xBE, 0x34, 0x9E, - 0x71, 0x9E, 0x7E, 0x5F, 0xAA, 0x8A, 0xBE, 0x91, - 0xCE, 0x88, 0x92, 0xDB, 0xC6, 0xAB, 0x8A, 0x72, - 0xE2, 0x44, 0xC3, 0x54, 0xAA, 0x45, 0xBB, 0x92, - 0xBA, 0xC4, 0x46, 0xCA, 0x2D, 0xD6, 0x3B, 0x1A, - 0xC2, 0x7E, 0xA6, 0xCB, 0x7A, 0xDC, 0x86, 0x72, - 0xB6, 0x94, 0xB4, 0x1C, 0xBC, 0xAE, 0x4C, 0xD6, - 0x62, 0x86, 0xD3, 0x16, 0xF6, 0x7A, 0x55, 0x79, - 0xFE, 0x6E, 0xC6, 0xC6, 0xAA, 0x93, 0xDC, 0x9D, - 0xAE, 0xA4, 0xD4, 0x56 + 0x00, 0x06, 0x0a, 0x0e, 0x16, 0x1a, 0x1e, 0x22, + 0x12, 0x00, 0x2a, 0x36, 0x42, 0x4e, 0x4a, 0x56, + 0x26, 0x46, 0x2e, 0x32, 0x52, 0x3a, 0x02, 0x65, + 0x5e, 0x3e, 0x74, 0x8a, 0xa2, 0x9a, 0x86, 0xc6, + 0xc3, 0x62, 0xbb, 0xd2, 0xda, 0xd6, 0xe2, 0xf6, + 0xfd, 0xae, 0x7b, 0xdd, 0xea, 0x6a, 0xaa, 0xe7, + 0xbe, 0x5a, 0xee, 0x9e, 0x95, 0x80, 0x62, 0x5c, + 0x4e, 0x26, 0x72, 0xaa, 0xba, 0xaf, 0x90, 0xae, + 0x92, 0x1a, 0xa4, 0x85, 0xb6, 0xbe, 0xc3, 0xc8, + 0xcf, 0xd0, 0xc2, 0xce, 0x57, 0xa2, 0xd6, 0xda, + 0xda, 0xd7, 0xb8, 0x2a, 0x7b, 0x91, 0xae, 0xca, + 0xda, 0x45, 0x9e, 0xb2, 0xd7, 0x9b, 0x90, 0x76, + 0x5c, 0xa2, 0xbe, 0xa6, 0x85, 0x96, 0x4e, 0x46, + 0x66, 0x92, 0x7a, 0x9a, 0x96, 0x9d, 0x9a, 0x6b, + 0x8a, 0x8e, 0xb2, 0xca, 0x90, 0xa6, 0x79, 0x7c, + 0xb6, 0xf2, 0xce, 0xfa, 0xb2, 0x6e, 0xa6, 0x8d, + 0x0e, 0x36, 0x86, 0xba, 0xbe, 0xcc, 0x8e, 0xb8, + 0xc4, 0x1e, 0x8e, 0xae, 0xba, 0xb2, 0xa6, 0x12, + 0x7a, 0x20, 0x64, 0xaa, 0x2f, 0x70, 0x85, 0x46, + 0xa6, 0x6e, 0x51, 0x72, 0x92, 0xa2, 0xa6, 0x87, + 0x96, 0xa2, 0x85, 0x7a, 0x6a, 0x6e, 0x22, 0x76, + 0x36, 0x76, 0x3c, 0x6e, 0x63, 0x53, 0x66, 0x62, + 0x42, 0x50, 0x56, 0x42, 0x56, 0x56, 0x56, 0x3e, + 0x51, 0x52, 0x56, }; unsigned char linux_logo_blue[] __initdata = { - 0x04, 0x84, 0x10, 0x0C, 0x41, 0x14, 0x04, 0x78, - 0xC7, 0x0E, 0xC4, 0x24, 0xA4, 0x64, 0x0C, 0x0D, - 0x17, 0x24, 0x0D, 0x13, 0x11, 0x07, 0x40, 0x22, - 0x0C, 0x0C, 0x11, 0x78, 0x06, 0xF4, 0x0B, 0x0A, - 0x47, 0x0B, 0x7C, 0x54, 0x6C, 0x0C, 0x0D, 0x9C, - 0x73, 0x54, 0x14, 0x0C, 0x0F, 0xC7, 0x94, 0x04, - 0x94, 0x17, 0x0A, 0x6C, 0x08, 0x0F, 0x14, 0x0B, - 0x12, 0x68, 0x28, 0x11, 0xFA, 0x0A, 0x34, 0x09, - 0x0A, 0x2F, 0x15, 0x19, 0x14, 0x3C, 0x06, 0xC4, - 0x0B, 0x84, 0x24, 0x08, 0x69, 0x38, 0xBC, 0x15, - 0x1F, 0xA0, 0x0A, 0xEC, 0x2A, 0x0C, 0x0C, 0x0C, - 0x2C, 0xA0, 0x15, 0x07, 0x0B, 0x8C, 0xD3, 0x10, - 0x3B, 0x5C, 0x0C, 0x04, 0x3C, 0xAC, 0x54, 0x1C, - 0x0B, 0x5B, 0xBB, 0x0A, 0xC1, 0xBB, 0x5C, 0x3C, - 0xBC, 0x4D, 0x74, 0x10, 0x8C, 0x8C, 0x14, 0x91, - 0x0C, 0x74, 0x17, 0x0C, 0x48, 0x9C, 0x3C, 0x4C, - 0x09, 0x7C, 0x05, 0xE4, 0x34, 0x38, 0x6C, 0x11, - 0x08, 0x7C, 0x18, 0x2C, 0x9C, 0x4C, 0x34, 0x9C, - 0x29, 0x54, 0x7C, 0x0C, 0x78, 0x18, 0x9C, 0x14, - 0xBA, 0x30, 0x27, 0x31, 0xC2, 0x97, 0x24, 0x09, - 0xB4, 0x04, 0x87, 0x0C, 0x14, 0x1F, 0x7C, 0x64, - 0xB0, 0x0F, 0x45, 0x10, 0x2C, 0xD4, 0x0A, 0x04, - 0x44, 0x1F, 0x2C, 0xCC, 0x7C, 0xD8, 0x84, 0x0C, - 0x8C, 0x94, 0xB4, 0x1D, 0x20, 0x5C, 0x18, 0xB4, - 0x04, 0x09, 0xBC, 0x14, 0xF4, 0x08, 0x54, 0x07, - 0xFC, 0x6C, 0x24, 0xB4, 0x15, 0x18, 0xDB, 0x17, - 0x17, 0x18, 0x21, 0x24 + 0x00, 0x06, 0x0a, 0x0e, 0x16, 0x1a, 0x1e, 0x22, + 0x12, 0x01, 0x2a, 0x36, 0x42, 0x4e, 0x4a, 0x56, + 0x26, 0x46, 0x2e, 0x32, 0x52, 0x3a, 0x06, 0x65, + 0x5e, 0x3e, 0x74, 0x8a, 0xa2, 0x9a, 0x86, 0xc6, + 0xc3, 0x59, 0xbb, 0xd2, 0xda, 0xd6, 0xe2, 0xf6, + 0xfd, 0xae, 0x7b, 0xdd, 0xea, 0x6a, 0xaa, 0xe7, + 0xbe, 0x5a, 0xee, 0x9e, 0x95, 0x80, 0x2e, 0x08, + 0x0a, 0x06, 0x0a, 0x0b, 0x0b, 0x0f, 0x0c, 0x0f, + 0x3d, 0x09, 0x73, 0x09, 0x0d, 0x0a, 0x10, 0x1e, + 0x2d, 0x13, 0x86, 0xba, 0x19, 0x0a, 0x36, 0x3c, + 0x26, 0x14, 0x0d, 0x06, 0x07, 0x0a, 0x0b, 0x0f, + 0x4a, 0x06, 0x0a, 0x0c, 0x2b, 0x0a, 0x0b, 0x0a, + 0x06, 0x0a, 0x0a, 0x11, 0x0b, 0x0a, 0x0a, 0x1e, + 0x0f, 0x0d, 0x0a, 0x0b, 0x22, 0x6a, 0x72, 0x0b, + 0x0b, 0x22, 0x90, 0xca, 0x90, 0x92, 0x3c, 0x2c, + 0xb6, 0xf2, 0xce, 0xfa, 0xb2, 0x6e, 0xa6, 0x8d, + 0x06, 0x0e, 0x6a, 0x0e, 0x0e, 0x5b, 0x2c, 0x3e, + 0x0e, 0x0a, 0x5a, 0x0d, 0x0e, 0x3e, 0x0a, 0x06, + 0x2e, 0x06, 0x4e, 0x36, 0x06, 0x58, 0x24, 0x06, + 0x3a, 0x08, 0x08, 0x07, 0x5e, 0x45, 0x0a, 0x32, + 0x2e, 0x2a, 0x43, 0x48, 0x5f, 0x2e, 0x06, 0x06, + 0x07, 0x24, 0x06, 0x32, 0x06, 0x06, 0x46, 0x2e, + 0x22, 0x06, 0x06, 0x1e, 0x4c, 0x06, 0x3a, 0x22, + 0x42, 0x34, 0x42, }; unsigned char linux_logo[] __initdata = { - 0xBC, 0xAC, 0x7D, 0x95, 0xAF, 0x85, 0x2C, 0x2C, - 0xAC, 0xD9, 0x95, 0x7D, 0x95, 0xAC, 0x2C, 0xAF, - 0x7D, 0x48, 0xB2, 0xAC, 0x85, 0xDA, 0xDA, 0x2C, - 0x7D, 0x48, 0x21, 0x2C, 0x8D, 0x2A, 0x8A, 0xDA, - 0x85, 0x2C, 0xD9, 0xAC, 0x2C, 0x2C, 0xD9, 0xD9, - 0xAF, 0x85, 0x85, 0x85, 0x8D, 0xBC, 0x2A, 0x2A, - 0xBC, 0x8C, 0xBC, 0xAC, 0x7D, 0x95, 0xAF, 0x85, - 0x2C, 0x2C, 0xAC, 0xD9, 0x95, 0x7D, 0x95, 0xAC, - 0x2C, 0xAF, 0x7D, 0x48, 0xB2, 0xAC, 0x85, 0xDA, - 0xDA, 0x2C, 0x7D, 0x48, 0x21, 0x2C, 0x8D, 0x2A, - 0xAF, 0xA1, 0x48, 0x7D, 0xAF, 0x2C, 0x2C, 0xAC, - 0xD9, 0xD9, 0x95, 0x7D, 0x95, 0xAC, 0xD9, 0x7D, - 0x48, 0xE9, 0x21, 0xAF, 0xDA, 0xDA, 0x85, 0x2C, - 0xD9, 0xD9, 0xAC, 0xDA, 0x8A, 0xDA, 0x85, 0x2C, - 0x2C, 0xAC, 0xD9, 0xAC, 0xAF, 0xAF, 0x2C, 0x2C, - 0x2C, 0x85, 0x2C, 0x2C, 0x85, 0xDA, 0xDA, 0xDA, - 0xDA, 0xDA, 0xAF, 0xA1, 0x48, 0x7D, 0xAF, 0x2C, - 0x2C, 0xAC, 0xD9, 0xD9, 0x95, 0x7D, 0x95, 0xAC, - 0xD9, 0x7D, 0x48, 0xE9, 0x21, 0xAF, 0xDA, 0xDA, - 0x85, 0x2C, 0xD9, 0xD9, 0xAC, 0xDA, 0x8A, 0xDA, - 0x7D, 0x48, 0x48, 0x7D, 0x2C, 0x85, 0x2C, 0xAF, - 0xD9, 0xD9, 0x7D, 0x95, 0xD9, 0xD9, 0xD9, 0x7D, - 0xB2, 0x21, 0xD9, 0x85, 0xDA, 0xDA, 0x85, 0x2C, - 0xAF, 0x2C, 0x2C, 0xDA, 0x85, 0x85, 0x2C, 0x2C, - 0xAC, 0xD9, 0xD9, 0xAF, 0xDA, 0x85, 0x2C, 0x2C, - 0x85, 0xDA, 0xDA, 0x85, 0x85, 0xDA, 0x85, 0x85, - 0x85, 0xAF, 0x7D, 0x48, 0x48, 0x7D, 0x2C, 0x85, - 0x2C, 0xAF, 0xD9, 0xD9, 0x7D, 0x95, 0xD9, 0xD9, - 0xD9, 0x7D, 0xB2, 0x21, 0xD9, 0x85, 0xDA, 0xDA, - 0x85, 0x2C, 0xAF, 0x2C, 0x2C, 0xDA, 0xDA, 0x85, - 0xA1, 0xE9, 0x48, 0x95, 0x85, 0xDA, 0x85, 0xAF, - 0xD9, 0xD9, 0x95, 0x95, 0xD9, 0xD9, 0x95, 0x95, - 0xD9, 0xAC, 0x85, 0x85, 0xDA, 0xDA, 0x85, 0x2C, - 0xAC, 0xAC, 0x2C, 0x2C, 0x85, 0x2C, 0x2C, 0xAC, - 0xD9, 0xD9, 0x2C, 0x91, 0x41, 0x20, 0x6B, 0x20, - 0x6B, 0x20, 0x6B, 0xAE, 0x2C, 0x85, 0x2C, 0x2C, - 0xAC, 0xD9, 0xA1, 0xE9, 0x48, 0x95, 0x85, 0xDA, - 0x85, 0xAF, 0xD9, 0xD9, 0x95, 0x95, 0xD9, 0xD9, - 0x95, 0x95, 0xD9, 0xAC, 0x85, 0x85, 0xDA, 0xDA, - 0x85, 0x2C, 0xAC, 0xAC, 0x2C, 0x2C, 0x2C, 0x2C, - 0xA1, 0xA1, 0xD6, 0xAF, 0xDA, 0xDA, 0x85, 0x2C, - 0xD9, 0xD9, 0x95, 0x95, 0xD9, 0xD9, 0xD9, 0xD9, - 0x2C, 0x2C, 0xDA, 0xDA, 0xDA, 0x85, 0x2C, 0xD9, - 0xD9, 0xD9, 0xD9, 0xAC, 0xAC, 0xAC, 0xAF, 0xAC, - 0x2C, 0xB2, 0x88, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x6B, 0x80, 0x85, 0x2C, - 0xD9, 0xD6, 0xA1, 0xA1, 0xD6, 0xAF, 0xDA, 0xDA, - 0x85, 0x2C, 0xD9, 0xD9, 0x95, 0x95, 0xD9, 0xD9, - 0xD9, 0xD9, 0x2C, 0x2C, 0xDA, 0xDA, 0xDA, 0x85, - 0x2C, 0xD9, 0xD9, 0xD9, 0xD9, 0xAF, 0xAF, 0xAF, - 0xD6, 0xD6, 0xD9, 0x2C, 0xDA, 0xDA, 0x2C, 0xAC, - 0xD9, 0x7D, 0x95, 0xD9, 0xD9, 0xD9, 0xAF, 0x2C, - 0x85, 0x85, 0x85, 0x85, 0x2C, 0x2C, 0xAC, 0xD9, - 0xD9, 0xD9, 0xAF, 0xAF, 0x2C, 0x2C, 0xAF, 0xDA, - 0xAE, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x41, 0xE3, 0x20, 0x6B, 0x48, - 0xAC, 0x95, 0xD6, 0xD6, 0xD9, 0x2C, 0xDA, 0xDA, - 0x2C, 0xAC, 0xD9, 0x7D, 0x95, 0xD9, 0xD9, 0xD9, - 0xAF, 0x2C, 0x85, 0x85, 0x85, 0x85, 0x2C, 0x2C, - 0xAC, 0xD9, 0xD9, 0xD9, 0xAF, 0xAF, 0xAF, 0xAF, - 0xD9, 0xD9, 0xD9, 0x2C, 0x85, 0x85, 0x2C, 0xD9, - 0x7D, 0x21, 0xD6, 0xD9, 0xAF, 0x2C, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x2C, 0xAF, 0xAF, 0xAC, - 0xAF, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x89, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x74, 0x43, 0x80, 0x41, 0x20, - 0x9F, 0x2C, 0xD9, 0xD9, 0xD9, 0x2C, 0x85, 0x85, - 0x2C, 0xD9, 0x7D, 0x21, 0xD6, 0xD9, 0xAF, 0x2C, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x2C, 0xAF, - 0xAF, 0xAC, 0xAF, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, - 0xD9, 0x7D, 0xD9, 0xAF, 0x85, 0x85, 0x2C, 0xD9, - 0xB2, 0x21, 0x7D, 0xD9, 0xAF, 0x2C, 0x85, 0x85, - 0x85, 0x2C, 0x2C, 0x2C, 0x2C, 0xAF, 0xAF, 0xAC, - 0xAF, 0xAC, 0xAF, 0xAF, 0xAC, 0xAC, 0x85, 0x41, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0xAE, 0x48, 0x89, 0x74, 0x41, - 0x6B, 0xD6, 0xD9, 0x7D, 0xD9, 0xAF, 0x85, 0x85, - 0x2C, 0xD9, 0xB2, 0x21, 0x7D, 0xD9, 0xAF, 0x2C, - 0x85, 0x85, 0x85, 0x2C, 0x2C, 0x2C, 0x2C, 0xAF, - 0xAF, 0xAC, 0xAF, 0xAC, 0xAC, 0x2C, 0xAF, 0xAC, - 0x2C, 0x7D, 0xD9, 0x2C, 0xDA, 0x85, 0x2C, 0x7D, - 0xB2, 0xD6, 0xD9, 0xAF, 0x85, 0x85, 0x85, 0x85, - 0xAF, 0xAC, 0xAC, 0xAF, 0xAF, 0xAC, 0xAC, 0xD9, - 0x95, 0x7D, 0x95, 0x95, 0xD9, 0xD9, 0x48, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x6B, 0xAE, 0xE6, 0x80, 0x2B, 0x88, - 0x20, 0x33, 0xDA, 0x95, 0xD9, 0x2C, 0xDA, 0x85, - 0x2C, 0x7D, 0xB2, 0xD6, 0xD9, 0xAF, 0x85, 0x85, - 0x85, 0x85, 0xAF, 0xAC, 0xAC, 0xAF, 0xAF, 0xAC, - 0xAC, 0xD9, 0x95, 0x95, 0x7D, 0x95, 0x95, 0xD9, - 0x85, 0xD9, 0x2C, 0x85, 0xDA, 0xDA, 0xD9, 0x21, - 0xA1, 0xD9, 0xAF, 0x2C, 0x85, 0xDA, 0x85, 0xAF, - 0xD9, 0xD9, 0xAC, 0xAC, 0xAC, 0xD9, 0x7D, 0xD6, - 0xD6, 0x7D, 0x95, 0xD9, 0xD9, 0x85, 0xDB, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0xDB, 0xE3, 0x6B, 0x20, 0x20, - 0x20, 0x20, 0xE9, 0xD9, 0x2C, 0x85, 0xDA, 0xDA, - 0xD9, 0x21, 0xA1, 0xD9, 0xAF, 0x2C, 0x85, 0xDA, - 0x85, 0xAF, 0xD9, 0xD9, 0xAC, 0xAC, 0xAC, 0xD9, - 0x7D, 0xD6, 0xD6, 0x7D, 0x95, 0xD9, 0xD9, 0xD9, - 0xDA, 0x2C, 0x85, 0xDA, 0xDA, 0x85, 0x95, 0x21, - 0x21, 0xD9, 0x85, 0x85, 0x85, 0x2C, 0x2C, 0xD9, - 0x95, 0x95, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, - 0xAC, 0xAC, 0x2C, 0xAF, 0x2C, 0x85, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x88, 0xDA, 0x85, 0xDA, 0xDA, 0x85, - 0x95, 0x21, 0x21, 0xD9, 0x85, 0x85, 0x85, 0x2C, - 0x2C, 0xD9, 0x95, 0x95, 0xD9, 0xD9, 0xD9, 0xD9, - 0xD9, 0xD9, 0xD9, 0xAF, 0x2C, 0x2C, 0x2C, 0x2C, - 0xDA, 0x2C, 0x85, 0x85, 0x2C, 0xD9, 0xD6, 0xB2, - 0x95, 0x2C, 0x85, 0x85, 0xAF, 0xAC, 0x95, 0x95, - 0x7D, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0x2C, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0xAC, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0xAC, 0x85, 0x85, 0x2C, 0xD9, - 0xD6, 0xB2, 0x95, 0x2C, 0x85, 0x85, 0xAF, 0xAC, - 0x95, 0x95, 0x7D, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, - 0x2C, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x2C, 0x2C, 0x2C, 0xAC, 0x95, 0xD6, 0x7D, - 0xD9, 0x2C, 0x2C, 0xAF, 0x95, 0x7D, 0x7D, 0x95, - 0x95, 0xD9, 0xD9, 0x95, 0xD9, 0xD9, 0x2C, 0x85, - 0xDA, 0xDA, 0xDA, 0x85, 0x85, 0x21, 0x20, 0x20, - 0x6B, 0x41, 0xDB, 0x6B, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x41, 0xDB, 0xDB, 0x20, 0x20, - 0x20, 0x20, 0x20, 0xE6, 0x2C, 0x2C, 0xAC, 0x95, - 0xD6, 0x7D, 0xD9, 0x2C, 0x2C, 0xAF, 0x95, 0x7D, - 0x7D, 0x95, 0x95, 0xD9, 0xD9, 0x95, 0xD9, 0xD9, - 0x2C, 0x85, 0xDA, 0xDA, 0xDA, 0x85, 0x2C, 0x2C, - 0x2C, 0xAF, 0xAC, 0xD9, 0x95, 0xD6, 0xD6, 0xD9, - 0x2C, 0x2C, 0x2C, 0xD9, 0xD6, 0xD6, 0xD9, 0xAF, - 0xAC, 0x95, 0xD6, 0x7D, 0x7D, 0xD9, 0x2C, 0x85, - 0xDA, 0xDA, 0x2C, 0xAF, 0xAF, 0x21, 0x20, 0x20, - 0x88, 0x2B, 0x88, 0x74, 0x20, 0x20, 0x20, 0x20, - 0x20, 0xAE, 0x2D, 0x2D, 0x74, 0x74, 0x88, 0x20, - 0x20, 0x20, 0x20, 0x80, 0xAC, 0xD9, 0x95, 0xD6, - 0xD6, 0xD9, 0x2C, 0x2C, 0x2C, 0xD9, 0xD6, 0xD6, - 0xD9, 0xAF, 0xAC, 0x95, 0xD6, 0x7D, 0x7D, 0xD9, - 0x2C, 0xDA, 0xDA, 0x85, 0x2C, 0xAF, 0xAF, 0xAF, - 0x2C, 0xAF, 0xD9, 0x95, 0xD6, 0xD6, 0x95, 0xAF, - 0x2C, 0x2C, 0xD9, 0x95, 0xD6, 0x95, 0xAF, 0x2C, - 0xAC, 0x7D, 0x21, 0x95, 0xD9, 0x2C, 0x85, 0x85, - 0x85, 0xAF, 0xD9, 0x95, 0xD9, 0x7D, 0x20, 0x33, - 0x7D, 0x8A, 0x7D, 0x5B, 0x6B, 0x20, 0x20, 0x6B, - 0xE6, 0xD9, 0x85, 0x2A, 0xDA, 0x2B, 0x41, 0x20, - 0x20, 0x20, 0x6B, 0x74, 0xD9, 0x95, 0xD6, 0xD6, - 0x95, 0xAF, 0x2C, 0x2C, 0xD9, 0x95, 0xD6, 0x95, - 0xAF, 0x2C, 0xAC, 0x7D, 0x21, 0x95, 0xD9, 0x2C, - 0x85, 0x85, 0x85, 0x2C, 0xD9, 0xD9, 0xD9, 0xD9, - 0x85, 0xD9, 0x7D, 0x21, 0x21, 0x7D, 0xAC, 0x2C, - 0x2C, 0xAC, 0xD9, 0x7D, 0xD9, 0xAF, 0x2C, 0x85, - 0xAC, 0x7D, 0x7D, 0xAC, 0x85, 0xDA, 0x8A, 0xDA, - 0x85, 0xAF, 0xD9, 0x7D, 0xD9, 0x95, 0x20, 0x91, - 0xBC, 0x73, 0xEE, 0x7D, 0x20, 0x20, 0x20, 0x80, - 0x4D, 0x3D, 0x73, 0x73, 0xA3, 0xD6, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x2B, 0x7D, 0x21, 0x21, 0x7D, - 0xAC, 0x2C, 0x2C, 0xAC, 0xD9, 0x7D, 0xD9, 0xAF, - 0x2C, 0x85, 0xAC, 0x7D, 0x7D, 0xAC, 0x85, 0xDA, - 0x8A, 0x8A, 0x85, 0xAC, 0xD9, 0x7D, 0xD9, 0xAC, - 0x2C, 0xD9, 0xD6, 0xB2, 0xB2, 0x7D, 0xAF, 0x85, - 0x2C, 0xD9, 0x95, 0x95, 0xAF, 0x2C, 0x2C, 0x2C, - 0xD9, 0xD9, 0xAC, 0x85, 0x8D, 0x2A, 0x2A, 0xDA, - 0xAF, 0xD9, 0x95, 0x95, 0xD9, 0xAC, 0x20, 0xAF, - 0x2C, 0xE6, 0x8D, 0x73, 0xE3, 0x20, 0x20, 0x48, - 0x5C, 0xDA, 0x5B, 0x43, 0xBC, 0x73, 0x2B, 0x20, - 0x20, 0x20, 0x20, 0x41, 0xD6, 0xB2, 0xB2, 0x7D, - 0xAF, 0x85, 0x2C, 0xD9, 0x95, 0x95, 0xAF, 0x2C, - 0x2C, 0x2C, 0xD9, 0xD9, 0xAC, 0x85, 0x8A, 0x2A, - 0x8D, 0xDA, 0xAF, 0xD9, 0x95, 0x95, 0xD9, 0xAF, - 0xAC, 0xD9, 0xD6, 0xB2, 0x21, 0xD9, 0x2C, 0x85, - 0x2C, 0xD9, 0x95, 0xD9, 0xAF, 0x2C, 0x2C, 0xAC, - 0xAC, 0xAF, 0x85, 0x8D, 0xBC, 0xBC, 0xDA, 0xD9, - 0xD6, 0xA1, 0xA1, 0x21, 0xD9, 0xAC, 0x20, 0x2A, - 0xCC, 0xAE, 0x9F, 0xE4, 0xAE, 0x5B, 0x74, 0xA1, - 0xE4, 0xAE, 0x20, 0x9F, 0x89, 0xE8, 0xE6, 0x20, - 0x20, 0x20, 0x20, 0x41, 0xD6, 0xB2, 0x21, 0xD9, - 0x2C, 0x85, 0x2C, 0xD9, 0x95, 0xD9, 0xAF, 0x2C, - 0x2C, 0xAC, 0xAC, 0xAF, 0x85, 0x8D, 0xBC, 0x2A, - 0xDA, 0xD9, 0xD6, 0xA1, 0xA1, 0x21, 0xD9, 0xD9, - 0xD9, 0x95, 0x21, 0xA1, 0x21, 0xAC, 0x85, 0x85, - 0xAC, 0xD9, 0xD9, 0xAF, 0x2C, 0x2C, 0xAF, 0xAC, - 0xAF, 0x85, 0x8A, 0x2A, 0x2A, 0xDA, 0xD9, 0xA1, - 0x48, 0xE9, 0x48, 0x21, 0x95, 0xAC, 0x20, 0x2A, - 0xDB, 0x41, 0x74, 0xBC, 0x2B, 0x7B, 0x7B, 0x80, - 0x73, 0x41, 0x20, 0x6B, 0x2B, 0xE8, 0x2D, 0x20, - 0x20, 0x20, 0x20, 0x33, 0x21, 0xA1, 0x21, 0xAC, - 0x85, 0x85, 0xAC, 0xD9, 0xD9, 0xAF, 0x2C, 0x2C, - 0xAF, 0xAC, 0xAF, 0x85, 0x8A, 0xBC, 0x2A, 0xDA, - 0xD9, 0xA1, 0x48, 0xE9, 0x48, 0x21, 0xD9, 0xD9, - 0xA1, 0xB2, 0xB2, 0x48, 0xD6, 0xAC, 0x2C, 0x2C, - 0xD9, 0x95, 0xAF, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, - 0x85, 0x8A, 0x8D, 0x8D, 0x85, 0x95, 0xA1, 0x6C, - 0x6C, 0x48, 0xD6, 0xD9, 0x2C, 0x85, 0x20, 0x2C, - 0x89, 0x20, 0x3C, 0xB9, 0xA7, 0x63, 0xD2, 0xB9, - 0xC6, 0x9A, 0x20, 0x20, 0x43, 0x5C, 0xE6, 0x20, - 0x20, 0x20, 0x20, 0x33, 0xB2, 0x48, 0xD6, 0xAC, - 0x2C, 0x2C, 0xD9, 0x95, 0xAF, 0x2C, 0x2C, 0x2C, - 0x2C, 0x2C, 0x85, 0x8A, 0x8D, 0x8D, 0x85, 0x95, - 0xA1, 0x6C, 0x6C, 0x48, 0xD6, 0xD9, 0xAF, 0xAC, - 0xA1, 0xD6, 0x7D, 0xB2, 0xD6, 0xAF, 0x85, 0x85, - 0xD9, 0x95, 0x2C, 0x85, 0xDA, 0x85, 0x85, 0x2C, - 0x85, 0x8A, 0x8D, 0xDA, 0xD9, 0x48, 0x81, 0x2D, - 0x48, 0xD6, 0xD9, 0xAC, 0x2C, 0x85, 0x20, 0x2D, - 0xEE, 0x93, 0xD1, 0xA7, 0x3E, 0x3E, 0x3A, 0x25, - 0x56, 0xAB, 0xAA, 0xC5, 0xEE, 0xEE, 0x33, 0x20, - 0x20, 0x20, 0x20, 0x41, 0xD9, 0xB2, 0xD6, 0xAF, - 0x85, 0x85, 0xD9, 0x95, 0x2C, 0x85, 0xDA, 0x85, - 0x85, 0x2C, 0x85, 0x8A, 0x8D, 0xDA, 0xD9, 0x48, - 0x81, 0x2D, 0x48, 0xD6, 0xD9, 0xAF, 0x2C, 0x2C, - 0xAC, 0xAF, 0xD9, 0x7D, 0xD6, 0x2C, 0x85, 0x2C, - 0xD9, 0xD9, 0x2C, 0xDA, 0xDA, 0xDA, 0x2C, 0x2C, - 0x85, 0x8D, 0x8D, 0x2C, 0x21, 0x2D, 0x2D, 0xE9, - 0xD6, 0xD9, 0xAF, 0x2C, 0x85, 0xDA, 0x20, 0xE3, - 0xB4, 0xBE, 0xF1, 0x3E, 0x9B, 0x22, 0x56, 0xF2, - 0xBB, 0x7F, 0x56, 0xDC, 0x8F, 0x5A, 0x5F, 0x20, - 0x20, 0x20, 0x20, 0x6B, 0x2C, 0x7D, 0xD6, 0x2C, - 0x85, 0x2C, 0xD9, 0xD9, 0x2C, 0xDA, 0xDA, 0xDA, - 0x2C, 0x2C, 0x85, 0x8D, 0x8A, 0x85, 0x21, 0x2D, - 0x2D, 0xE9, 0xD6, 0xD9, 0xAF, 0x2C, 0x85, 0x85, - 0x2A, 0x85, 0xAC, 0x95, 0x95, 0x2C, 0x85, 0x85, - 0xAC, 0xAF, 0x85, 0xDA, 0xDA, 0x85, 0x2C, 0x2C, - 0xDA, 0x8A, 0x8A, 0xAF, 0xA1, 0x2D, 0xE9, 0xD6, - 0xD9, 0xAC, 0x85, 0x85, 0x85, 0xDA, 0x20, 0x52, - 0x55, 0xED, 0x57, 0x3E, 0x22, 0x56, 0x37, 0xBB, - 0xBB, 0x58, 0x7F, 0x7F, 0x56, 0x5E, 0xC5, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x2C, 0x95, 0x95, 0x2C, - 0x85, 0x85, 0xAC, 0xAF, 0x85, 0xDA, 0xDA, 0x85, - 0x2C, 0x2C, 0xDA, 0x8D, 0xDA, 0xAF, 0xA1, 0x2D, - 0xE9, 0xD6, 0xD9, 0xAF, 0x2C, 0x85, 0x85, 0x85, - 0xCD, 0xAF, 0xD9, 0x95, 0xD9, 0x2C, 0xDA, 0x85, - 0xAF, 0xD9, 0x85, 0xDA, 0x85, 0x2C, 0xAC, 0xAF, - 0x85, 0x8A, 0x85, 0xD9, 0x48, 0x48, 0xB2, 0x95, - 0x95, 0xAC, 0x2C, 0x85, 0xDA, 0xDA, 0x6B, 0xB3, - 0x46, 0x7C, 0x2E, 0x9B, 0x22, 0x56, 0xBB, 0x37, - 0x58, 0x58, 0xF2, 0x3A, 0x46, 0x63, 0x64, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x2D, 0x95, 0xD9, 0x2C, - 0xDA, 0x85, 0xAF, 0xD9, 0x85, 0xDA, 0x85, 0x2C, - 0xAC, 0xAF, 0x85, 0xDA, 0x85, 0xD9, 0x48, 0x48, - 0xB2, 0x95, 0x95, 0xD9, 0x85, 0xDA, 0x85, 0x85, - 0xBC, 0xB2, 0xB2, 0x7D, 0xD9, 0x2C, 0xDA, 0x85, - 0xAF, 0xD9, 0x85, 0xDA, 0x85, 0x85, 0xAF, 0x2C, - 0x85, 0xDA, 0x2C, 0x7D, 0xA1, 0x48, 0xB2, 0x21, - 0xD6, 0xD9, 0x85, 0xDA, 0x85, 0xDA, 0x41, 0x51, - 0xB7, 0xEC, 0x2E, 0x22, 0x56, 0x37, 0xBB, 0xF2, - 0x37, 0xEA, 0x2F, 0x2F, 0x77, 0xA7, 0x38, 0x20, - 0x20, 0x6B, 0x20, 0x20, 0x5B, 0x2C, 0xD9, 0x2C, - 0xDA, 0x85, 0xAF, 0xD9, 0x85, 0xDA, 0x85, 0x85, - 0xAF, 0x2C, 0xDA, 0xDA, 0x2C, 0x7D, 0xA1, 0x48, - 0xB2, 0x21, 0xD6, 0xD9, 0x2C, 0xDA, 0x85, 0xAF, - 0x2C, 0x2D, 0x48, 0x7D, 0xAF, 0x2C, 0x85, 0x2C, - 0xD9, 0xAC, 0xAF, 0x85, 0x85, 0x2C, 0x2C, 0x2C, - 0x85, 0x2C, 0xD9, 0xD6, 0xA1, 0xA1, 0x48, 0xA1, - 0x21, 0x2C, 0xDA, 0xDA, 0x2C, 0x85, 0x41, 0x98, - 0xA2, 0xA7, 0x6F, 0xC9, 0x37, 0xF2, 0xF2, 0x9B, - 0xB7, 0x66, 0x60, 0x4C, 0xED, 0x84, 0x3C, 0x20, - 0x5B, 0x2D, 0x2B, 0x6B, 0x20, 0xAF, 0xAF, 0x2C, - 0x85, 0x2C, 0xD9, 0xAC, 0xAF, 0x85, 0x85, 0x2C, - 0x2C, 0x2C, 0x2C, 0x85, 0xD9, 0xD6, 0xA1, 0xA1, - 0x48, 0xA1, 0xD6, 0xAF, 0xDA, 0x8A, 0x2C, 0xD9, - 0xB2, 0x2D, 0x48, 0x95, 0x2C, 0x2C, 0x2C, 0x85, - 0xAC, 0xAC, 0xAF, 0x85, 0xDA, 0x85, 0xAF, 0xAC, - 0xAF, 0x2C, 0xD9, 0xD6, 0xD6, 0xD6, 0x21, 0xD6, - 0xD9, 0xDA, 0x8D, 0xDA, 0xAF, 0x2C, 0x20, 0x88, - 0x42, 0x51, 0x3F, 0x2F, 0x45, 0xB7, 0x66, 0x55, - 0x46, 0x60, 0x5D, 0x36, 0xD8, 0x71, 0x43, 0x20, - 0x20, 0x2D, 0xB2, 0x80, 0x20, 0x2D, 0x2C, 0x2C, - 0x2C, 0x85, 0xAC, 0xAC, 0xAF, 0x85, 0xDA, 0x85, - 0xAF, 0xAC, 0xAC, 0xAF, 0xD9, 0xD6, 0xD6, 0xD6, - 0x21, 0xD6, 0xD9, 0xDA, 0x8D, 0x8A, 0x2C, 0xD9, - 0xB2, 0x48, 0xD6, 0xAC, 0xAF, 0x2C, 0x2C, 0x85, - 0x2C, 0xAC, 0x2C, 0xDA, 0xDA, 0x85, 0xAF, 0xD9, - 0xD9, 0xAC, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xAC, - 0x85, 0x8D, 0xBC, 0xDA, 0xD9, 0xDA, 0x20, 0xE3, - 0xDA, 0x69, 0x96, 0xB5, 0xF1, 0x68, 0x5D, 0x82, - 0xE1, 0xBE, 0x27, 0x8D, 0x4D, 0xD3, 0x7D, 0x20, - 0x20, 0xDB, 0xA1, 0xCA, 0x20, 0x88, 0x85, 0x2C, - 0x2C, 0x85, 0x2C, 0xAC, 0x2C, 0xDA, 0xDA, 0x85, - 0xAF, 0xD9, 0xAC, 0xAF, 0xD9, 0xD9, 0xD9, 0xD9, - 0xD9, 0xAC, 0xDA, 0x8D, 0xBC, 0xDA, 0xD9, 0x95, - 0xD9, 0x95, 0xAC, 0x2C, 0x2C, 0x2C, 0x2C, 0x85, - 0x85, 0xAF, 0xAF, 0x85, 0x85, 0x2C, 0x2C, 0xAC, - 0xD9, 0xAC, 0xAF, 0x2C, 0x2C, 0x2C, 0x2C, 0x85, - 0x8D, 0x2A, 0x2A, 0x85, 0xD9, 0x95, 0x20, 0xDB, - 0x8D, 0x8D, 0x99, 0xB0, 0x35, 0xE5, 0x3F, 0x35, - 0xB9, 0x50, 0x8A, 0x4D, 0x73, 0xE8, 0xA3, 0xCC, - 0x20, 0x20, 0x33, 0x6B, 0x20, 0x20, 0xCC, 0x85, - 0x2C, 0x85, 0x85, 0xAF, 0xAF, 0x85, 0x85, 0x85, - 0x2C, 0xD9, 0xD9, 0xAC, 0xAF, 0x2C, 0x2C, 0x2C, - 0x2C, 0x85, 0x8A, 0x2A, 0x8D, 0x2C, 0xD9, 0xD9, - 0xAF, 0xAF, 0xAC, 0xAF, 0x2C, 0x2C, 0x2C, 0x85, - 0x2C, 0xAF, 0xAF, 0xAF, 0x2C, 0x2C, 0x2C, 0xAC, - 0xD9, 0xAC, 0xAF, 0x2C, 0x85, 0x85, 0xDA, 0xDA, - 0x8A, 0x8A, 0x85, 0xD9, 0x2C, 0x2B, 0x20, 0xAE, - 0xA3, 0xBC, 0x8D, 0xC8, 0xA9, 0xC7, 0x92, 0x47, - 0x8D, 0x8D, 0x7E, 0xE4, 0xE8, 0xE8, 0x5C, 0x2C, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6B, 0xAF, - 0x2C, 0x85, 0x2C, 0xAF, 0xAF, 0xAF, 0x2C, 0x2C, - 0x2C, 0xAF, 0xD9, 0xAC, 0x2C, 0x2C, 0x85, 0x85, - 0x85, 0xDA, 0x8D, 0x8A, 0x85, 0xAC, 0x95, 0xD9, - 0xAC, 0xAC, 0xAC, 0xAC, 0x2C, 0xAF, 0xAF, 0x2C, - 0x2C, 0xAF, 0xAF, 0xAC, 0x2C, 0xAF, 0x2C, 0xAF, - 0xD9, 0xAC, 0x2C, 0x2C, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x2C, 0xD9, 0xD9, 0x2D, 0x6B, 0x41, 0x2A, - 0xE8, 0xA3, 0xC8, 0x8D, 0x8A, 0x8A, 0x8A, 0x8D, - 0x4D, 0xA3, 0x3D, 0xE8, 0xE8, 0xE8, 0xE8, 0x5C, - 0xAE, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xDB, - 0xDA, 0x2C, 0x2C, 0xAF, 0xAF, 0xAC, 0xAC, 0xAF, - 0x2C, 0xAC, 0xD9, 0xAC, 0x2C, 0x2C, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x2C, 0xD9, 0x95, 0x7D, 0xD9, - 0x7D, 0x7D, 0xD9, 0xAC, 0xAC, 0xAF, 0xAF, 0xAF, - 0x2C, 0x2C, 0xAC, 0xAC, 0xD9, 0xAC, 0xAC, 0xD9, - 0x95, 0xD9, 0xAC, 0xAF, 0xAF, 0xAC, 0xAF, 0xAC, - 0xD9, 0x7D, 0x7D, 0x7D, 0x33, 0x41, 0x2D, 0xE8, - 0xE8, 0x5C, 0xD3, 0x8D, 0x8D, 0x8D, 0x8D, 0x7E, - 0x3D, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, - 0xDA, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x81, 0x2C, 0x2C, 0x2C, 0xAC, 0xAC, 0xAC, 0xAC, - 0xAC, 0xD9, 0x95, 0x95, 0xAC, 0xAF, 0xAF, 0xAF, - 0xAF, 0xAC, 0xD9, 0x95, 0x7D, 0xD6, 0xD6, 0x7D, - 0x21, 0xD6, 0x95, 0xD9, 0xD9, 0xAC, 0xAF, 0xAF, - 0x2C, 0xAF, 0xAC, 0xAC, 0xD9, 0xD9, 0xD9, 0xD9, - 0x21, 0x21, 0x7D, 0x95, 0x95, 0x7D, 0xD6, 0x21, - 0xB2, 0xA1, 0x2C, 0x88, 0x20, 0xE3, 0xA3, 0xE8, - 0xE8, 0xE8, 0xE4, 0xEE, 0xD3, 0x7E, 0x73, 0x5C, - 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, - 0x5C, 0x2B, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x2C, 0xAF, 0xAF, 0xAC, 0xD9, 0xD9, 0xD9, - 0xD9, 0xD9, 0xD6, 0x21, 0x7D, 0x95, 0x95, 0x7D, - 0xD6, 0xB2, 0xA1, 0xA1, 0xB2, 0xD6, 0x21, 0x21, - 0x21, 0xD9, 0xD9, 0xD9, 0xAC, 0xAF, 0xAC, 0xAF, - 0x2C, 0x2C, 0xAC, 0xD9, 0xD9, 0xD9, 0xD9, 0x95, - 0x7D, 0xB2, 0xD6, 0x95, 0xD9, 0x95, 0xD6, 0xA1, - 0xA1, 0xAF, 0x5B, 0x20, 0x20, 0xD6, 0xE8, 0xE8, - 0xE8, 0xE8, 0xE8, 0xE8, 0x5C, 0xE8, 0xE8, 0xE8, - 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, - 0xE8, 0x48, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0xE3, 0x8A, 0x2C, 0xAC, 0xAC, 0xD9, 0xD9, - 0xD9, 0x95, 0xD6, 0xB2, 0xD6, 0x95, 0xD9, 0x95, - 0x21, 0xB2, 0xA1, 0xB2, 0xD6, 0xD6, 0xD6, 0xA1, - 0xD9, 0x2C, 0x2C, 0x2C, 0xAF, 0xAF, 0xAC, 0xAF, - 0x2C, 0x2C, 0xAF, 0xAC, 0xD9, 0xAC, 0xD9, 0xD9, - 0xD9, 0x95, 0xAC, 0x2C, 0x2C, 0xAC, 0x95, 0x7D, - 0xD9, 0x91, 0x20, 0x20, 0xE3, 0xA3, 0xE8, 0xE8, - 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, - 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, - 0xE8, 0x85, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x2B, 0x8A, 0xAF, 0xAC, 0xD9, 0xAC, - 0xD9, 0xD9, 0xD9, 0x95, 0xAC, 0x2C, 0x2C, 0xAC, - 0x95, 0x7D, 0x95, 0x95, 0xD9, 0x95, 0x7D, 0x21, - 0x2C, 0xDA, 0xDA, 0x85, 0x2C, 0xAF, 0xAF, 0xAF, - 0xAF, 0xAF, 0x2C, 0xAF, 0xAF, 0xAC, 0xAC, 0xAC, - 0xD9, 0xAF, 0x85, 0x85, 0x2C, 0xAF, 0xD9, 0xAF, - 0x48, 0x20, 0x20, 0x20, 0xE6, 0xA3, 0xE8, 0xE8, - 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, - 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0x5C, - 0xE4, 0x73, 0x41, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x2B, 0xDA, 0xAF, 0xAF, 0xAC, - 0xAC, 0xAF, 0xD9, 0x2C, 0x85, 0x85, 0x2C, 0xAF, - 0xD9, 0xD9, 0xAC, 0xAF, 0xAC, 0xD9, 0xD9, 0xD9, - 0x85, 0xDA, 0xDA, 0x85, 0x2C, 0x2C, 0xAC, 0xAF, - 0xAF, 0xAF, 0xAF, 0x2C, 0xAF, 0xAF, 0xAC, 0xAC, - 0xAF, 0x2C, 0x2C, 0x2C, 0xAC, 0x95, 0x95, 0xA1, - 0x20, 0x20, 0x20, 0x20, 0xE9, 0x8C, 0x5C, 0xE8, - 0xE8, 0xE8, 0xE8, 0x3D, 0x73, 0x73, 0xE8, 0xE8, - 0xE8, 0xE8, 0xE8, 0xE4, 0x73, 0x73, 0x73, 0xCD, - 0x7E, 0xA3, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x24, 0x85, 0xAF, 0xAF, - 0xAC, 0xAC, 0xAC, 0xAF, 0x85, 0x2C, 0xAC, 0x95, - 0x95, 0xD9, 0xAC, 0xAC, 0xAC, 0xD9, 0xAC, 0xAF, - 0x8A, 0x8A, 0xDA, 0xDA, 0x85, 0x2C, 0x2C, 0x2C, - 0x2C, 0x2C, 0x2C, 0xAF, 0xAF, 0xAC, 0xAF, 0xAC, - 0xAC, 0xAF, 0xAF, 0xD9, 0xD6, 0xD6, 0x2C, 0x88, - 0x20, 0x20, 0x20, 0x88, 0xB2, 0xDA, 0x7E, 0x73, - 0xE8, 0xE8, 0xE8, 0x3D, 0x73, 0xE8, 0xE8, 0xE8, - 0xE8, 0xE8, 0xE8, 0xA3, 0xCD, 0xD3, 0x2A, 0x2A, - 0x2A, 0x8C, 0x8D, 0x88, 0x20, 0xE3, 0x6B, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x41, 0x85, 0xAF, 0xAC, - 0xAC, 0xAC, 0xAC, 0xAF, 0xAC, 0xD9, 0x7D, 0xD6, - 0x7D, 0x7D, 0xD9, 0x95, 0xD9, 0xAC, 0xAC, 0xAF, - 0xD3, 0x8D, 0xDA, 0xDA, 0x85, 0x85, 0x2C, 0x2C, - 0x2C, 0xAF, 0xAF, 0xAC, 0xD9, 0xD9, 0xD9, 0xD9, - 0xAF, 0xAF, 0xAC, 0xD9, 0x95, 0x7D, 0xAC, 0x20, - 0x20, 0x20, 0x20, 0xDB, 0x2C, 0xA3, 0x5C, 0xE8, - 0xE8, 0xE8, 0xE8, 0x5C, 0x3D, 0x3D, 0xE8, 0xE8, - 0xE8, 0xE4, 0xE8, 0xE8, 0xE8, 0xE4, 0x73, 0xEE, - 0xD3, 0x2A, 0xEE, 0xAC, 0x20, 0x33, 0x2B, 0xE3, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x9F, 0xAF, 0xD9, - 0xD9, 0xAC, 0xAF, 0xAF, 0xAC, 0xD9, 0x95, 0x7D, - 0xD9, 0x95, 0x95, 0x95, 0x95, 0xD9, 0xAF, 0xAF, - 0x7E, 0x85, 0x85, 0x2C, 0x85, 0x85, 0x85, 0x2C, - 0x2C, 0x2C, 0xAF, 0xD9, 0xD9, 0x95, 0xD9, 0xAC, - 0xAC, 0xAF, 0xAF, 0xAC, 0xAC, 0xAC, 0x91, 0x20, - 0x33, 0xE3, 0x41, 0x48, 0x73, 0x5C, 0xE8, 0xE8, - 0xE8, 0xE8, 0xE8, 0xA3, 0xD6, 0x6C, 0x85, 0xE8, - 0xDA, 0xAE, 0xB2, 0xA3, 0x5C, 0xE8, 0xE8, 0xE8, - 0x3D, 0xEE, 0x4D, 0xA3, 0x24, 0x20, 0x6B, 0xDB, - 0x2B, 0x20, 0x20, 0x20, 0x20, 0x20, 0x85, 0x95, - 0xD9, 0xD9, 0xAC, 0xAF, 0xAF, 0xAC, 0xD9, 0xAC, - 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xAC, 0xD9, 0xAC, - 0x8A, 0xD9, 0xAC, 0xD9, 0xAC, 0xAC, 0x2C, 0x2C, - 0xAF, 0xAF, 0xAF, 0xAC, 0xD9, 0xD9, 0xD9, 0xD9, - 0xAF, 0xAF, 0xAF, 0xAC, 0xAC, 0x85, 0x33, 0x20, - 0xCC, 0x20, 0xE3, 0xA3, 0xE8, 0xE8, 0xE8, 0xE8, - 0xE8, 0xA3, 0xD9, 0x81, 0xAC, 0xDA, 0x2D, 0x5C, - 0x48, 0x41, 0x88, 0x74, 0x21, 0xA3, 0xE8, 0xE8, - 0xE8, 0xE8, 0x73, 0x8C, 0x8A, 0x20, 0x20, 0x20, - 0xDB, 0x33, 0x20, 0x20, 0x20, 0x20, 0xE6, 0xD9, - 0xD9, 0xAC, 0xAC, 0xAF, 0xAC, 0xAF, 0xAC, 0xAF, - 0xAF, 0xAC, 0xD9, 0xAF, 0xD9, 0xAC, 0xAC, 0xAF, - 0x85, 0xD9, 0x95, 0xD9, 0x95, 0xD9, 0xD9, 0xAC, - 0xAF, 0xAC, 0xAF, 0xAF, 0x2C, 0xAF, 0x2C, 0x2C, - 0xAF, 0xAF, 0xAF, 0xAC, 0xAC, 0x2C, 0x20, 0x5B, - 0x33, 0x20, 0xD6, 0xE8, 0xE8, 0xE8, 0xE8, 0x73, - 0xAF, 0x2D, 0xD9, 0xDA, 0xB2, 0x81, 0x81, 0xE4, - 0xA1, 0x91, 0x2B, 0x88, 0x33, 0x80, 0xAF, 0x73, - 0xE8, 0xE8, 0xE8, 0x5C, 0xA3, 0x80, 0x41, 0xCC, - 0x2B, 0xCC, 0x20, 0x20, 0x20, 0x20, 0x88, 0xDA, - 0x2C, 0x2C, 0x2C, 0xAF, 0xAF, 0xAC, 0xAC, 0xAF, - 0xAF, 0xAF, 0xAF, 0xAC, 0xAF, 0xAF, 0xAF, 0x2C, - 0x85, 0xD9, 0xD9, 0xD9, 0xD9, 0xAC, 0xAC, 0xD9, - 0xD9, 0xD9, 0xAC, 0x2C, 0x2C, 0x2C, 0x85, 0x85, - 0x85, 0x2C, 0x2C, 0xAF, 0x2C, 0x91, 0x20, 0xAE, - 0x20, 0xDB, 0x3D, 0xE8, 0xE8, 0x5C, 0xB2, 0x80, - 0xB2, 0xAF, 0x48, 0xB2, 0x48, 0x89, 0x89, 0x3D, - 0x21, 0x48, 0x6C, 0x2D, 0x2B, 0x41, 0xE3, 0xAE, - 0xD9, 0x5C, 0xE8, 0xE8, 0xE8, 0x95, 0x33, 0x80, - 0xAE, 0x33, 0x2B, 0x20, 0x20, 0x20, 0x20, 0x95, - 0x85, 0x2C, 0x85, 0x2C, 0x2C, 0xAF, 0x2C, 0x2C, - 0x2C, 0xAF, 0xAC, 0xAF, 0xAF, 0x2C, 0x2C, 0x2C, - 0xDA, 0xAF, 0xD9, 0xD9, 0xAF, 0x2C, 0x2C, 0x2C, - 0xAC, 0xD9, 0xAC, 0xAF, 0x2C, 0x85, 0x2C, 0x85, - 0x85, 0x2C, 0x2C, 0x2C, 0x8A, 0x41, 0xDB, 0x33, - 0x20, 0x95, 0xE8, 0xE8, 0xE8, 0xA3, 0xDB, 0x88, - 0xDB, 0x80, 0xD6, 0x7E, 0x85, 0x2D, 0xE6, 0x5C, - 0x21, 0x48, 0xD9, 0x7E, 0xD6, 0x2B, 0xCC, 0xAC, - 0x85, 0xBC, 0xE8, 0xE8, 0xE8, 0xCD, 0x88, 0x5B, - 0x41, 0x20, 0xAE, 0x20, 0x20, 0x20, 0x20, 0x74, - 0xDA, 0x85, 0x85, 0x85, 0x2C, 0x2C, 0x2C, 0x2C, - 0xAF, 0xAC, 0xD9, 0xD9, 0xAC, 0xAC, 0xAC, 0xD9, - 0x8A, 0xAF, 0xAC, 0xAC, 0x2C, 0x85, 0x2C, 0xAF, - 0xD9, 0xD9, 0xAF, 0xAF, 0xAF, 0x2C, 0xAF, 0x2C, - 0x2C, 0x2C, 0x2C, 0xAF, 0x95, 0x20, 0x74, 0x20, - 0x33, 0xA3, 0xE8, 0xE8, 0xE8, 0xE4, 0x7D, 0xCC, - 0x6B, 0x33, 0xAE, 0x2C, 0x85, 0x2D, 0x9F, 0x73, - 0xA1, 0x2D, 0x2C, 0xDA, 0x89, 0x48, 0xD3, 0xD9, - 0x21, 0xA3, 0xE8, 0xE8, 0xE8, 0xE8, 0xE3, 0x20, - 0x20, 0x20, 0xDB, 0x41, 0x20, 0x20, 0x20, 0x20, - 0xDA, 0x2C, 0x2C, 0x2C, 0x2C, 0xAF, 0xAC, 0xAC, - 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0x95, 0x95, 0xD9, - 0x2C, 0xD9, 0xD9, 0xAC, 0x2C, 0x2C, 0x85, 0xAF, - 0xAF, 0xAF, 0xAC, 0xAC, 0xD9, 0xAC, 0xAF, 0xAC, - 0xAC, 0x95, 0xD6, 0x7D, 0xAE, 0x88, 0x2B, 0x20, - 0x6C, 0xE8, 0xE8, 0xE8, 0x73, 0xEE, 0x73, 0x2C, - 0x89, 0x2B, 0x41, 0x33, 0xCC, 0xCC, 0x80, 0x3D, - 0x2D, 0x74, 0x80, 0x48, 0x8D, 0x95, 0x48, 0x95, - 0xEE, 0x5C, 0x5C, 0xE8, 0xE8, 0xE8, 0x24, 0x20, - 0x20, 0x20, 0x5B, 0xDB, 0x20, 0x20, 0x20, 0x20, - 0xAF, 0xAC, 0xD9, 0x95, 0xD6, 0xD6, 0xD6, 0x7D, - 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0xD9, 0xAC, - 0xAC, 0xD9, 0xD9, 0xAC, 0x2C, 0x2C, 0x2C, 0xAF, - 0xAC, 0xAC, 0xAC, 0xAC, 0xD9, 0xAC, 0xAC, 0xD9, - 0xD6, 0x48, 0xE9, 0x95, 0x20, 0x2B, 0x41, 0x6B, - 0x8D, 0xE8, 0xE8, 0xCD, 0x2B, 0x2B, 0x2C, 0x73, - 0xCD, 0x48, 0xCA, 0x5B, 0x41, 0x5B, 0x74, 0xDA, - 0x80, 0xE6, 0xC8, 0x85, 0xA1, 0x7D, 0x8D, 0x3D, - 0x7E, 0xE9, 0x7D, 0xEE, 0xE8, 0xE8, 0x81, 0x20, - 0x20, 0x20, 0xE3, 0xE3, 0x20, 0x20, 0x20, 0x20, - 0x2D, 0xD9, 0xD6, 0x48, 0x6C, 0xE9, 0xA1, 0xD6, - 0xD9, 0xD9, 0xAC, 0xD9, 0xD9, 0x95, 0xAC, 0x2C, - 0x2C, 0x2C, 0x2C, 0xD9, 0xAC, 0x2C, 0x2C, 0x2C, - 0xAF, 0x2C, 0xAF, 0xD9, 0xAC, 0xAF, 0xAF, 0x95, - 0xB2, 0xE9, 0x21, 0x2B, 0x41, 0x2B, 0x20, 0x5B, - 0x3D, 0xE8, 0xE8, 0x8D, 0x2B, 0x88, 0x5B, 0xE6, - 0xBC, 0x73, 0x85, 0x89, 0x80, 0x5B, 0xE3, 0xAE, - 0x2C, 0x8A, 0xD6, 0xB2, 0x2C, 0xA3, 0xA3, 0xD9, - 0xA1, 0x2C, 0x85, 0x8D, 0xE8, 0xE8, 0x48, 0x20, - 0x20, 0x20, 0xE3, 0x88, 0x20, 0x20, 0x20, 0x20, - 0xAE, 0xD9, 0xB2, 0xE9, 0x6C, 0x48, 0xD6, 0xD9, - 0x2C, 0x85, 0x2C, 0xD9, 0x7D, 0xD9, 0x2C, 0x85, - 0x8D, 0x85, 0x2C, 0xAC, 0xAF, 0x2C, 0x2C, 0x85, - 0x2C, 0x2C, 0xAF, 0xAC, 0xAC, 0xAF, 0xAF, 0xD9, - 0xB2, 0x48, 0xB2, 0x20, 0x20, 0xCC, 0x20, 0x9F, - 0xE8, 0xE8, 0xE8, 0xCD, 0x48, 0x89, 0xDB, 0x88, - 0x2B, 0xE9, 0xCD, 0x2A, 0x48, 0x80, 0xAE, 0xAE, - 0x7D, 0x48, 0x21, 0xEE, 0x3D, 0x2C, 0x48, 0x85, - 0x2C, 0x95, 0x7D, 0x8C, 0xE8, 0xE8, 0xB2, 0x20, - 0x20, 0x20, 0xDB, 0x20, 0x20, 0x20, 0x20, 0x20, - 0xDB, 0x2C, 0xB2, 0x48, 0x48, 0x7D, 0xD9, 0xAF, - 0x85, 0x8A, 0x85, 0x7D, 0xB2, 0x95, 0x85, 0xDA, - 0xD3, 0x85, 0xAF, 0xAC, 0x2C, 0x85, 0x85, 0x2C, - 0xAC, 0xAC, 0xAC, 0xD9, 0xD9, 0xAC, 0x2C, 0x2C, - 0xD9, 0xAC, 0x5B, 0x20, 0x20, 0xAE, 0x20, 0x2D, - 0xE8, 0xE8, 0xE8, 0x7E, 0xD6, 0x48, 0xE9, 0xAE, - 0x88, 0x5B, 0x80, 0x6C, 0xAE, 0xCA, 0x91, 0xE9, - 0x43, 0x9F, 0xE6, 0x2C, 0x48, 0x21, 0xBC, 0x95, - 0x95, 0xD6, 0x21, 0x7E, 0xE8, 0xE8, 0x7D, 0x20, - 0x20, 0x20, 0x2B, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x6B, 0xDA, 0xD9, 0x48, 0xB2, 0xD9, 0x2C, 0x85, - 0xDA, 0xDA, 0x2C, 0xA1, 0x48, 0xAC, 0xDA, 0x8D, - 0x2A, 0xAC, 0x7D, 0x95, 0xAF, 0x85, 0x2C, 0x2C, - 0xAC, 0xD9, 0x95, 0x7D, 0x95, 0xAC, 0x2C, 0xAF, - 0x7D, 0xD6, 0x20, 0x20, 0x88, 0x9F, 0x20, 0xA1, - 0xE8, 0xE8, 0xE8, 0xA3, 0xD6, 0x6C, 0xB2, 0x2C, - 0x89, 0xE3, 0x88, 0xDB, 0xCC, 0x24, 0x7D, 0xEE, - 0xB2, 0xCC, 0xAE, 0x2D, 0xDA, 0x2C, 0xD6, 0x2C, - 0xB2, 0x2D, 0xD6, 0xEE, 0xE8, 0xE8, 0x95, 0x20, - 0x20, 0x20, 0xDB, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x6B, 0xDA, 0x95, 0xA1, 0xB2, 0xAC, 0x85, 0x85, - 0xDA, 0x2C, 0x95, 0xA1, 0x21, 0x2C, 0x8A, 0x2A, - 0xAF, 0xA1, 0x48, 0xD6, 0xAF, 0x2C, 0x2C, 0xAC, - 0xD9, 0xD9, 0x95, 0x7D, 0x95, 0xAC, 0xD9, 0x7D, - 0x48, 0xE6, 0x20, 0x20, 0x33, 0x89, 0x6B, 0x95, - 0xE8, 0xE8, 0xE8, 0xA3, 0x21, 0x48, 0xAF, 0xAF, - 0x9F, 0xE9, 0x43, 0x33, 0x33, 0x2D, 0xDA, 0xCD, - 0xD6, 0xAE, 0x85, 0x2C, 0x7D, 0xD6, 0x91, 0xB8, - 0xD4, 0x48, 0x7D, 0xA3, 0xE8, 0xE8, 0x95, 0x20, - 0x20, 0x33, 0xE3, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x2C, 0x48, 0x6C, 0xB2, 0xAF, 0xDA, 0xDA, - 0x85, 0xAF, 0xD9, 0x95, 0xAC, 0xDA, 0x8A, 0xDA, - 0x7D, 0x48, 0x48, 0x7D, 0x2C, 0x85, 0x2C, 0xAF, - 0xD9, 0xD9, 0x7D, 0x95, 0xD9, 0xD9, 0x95, 0xD6, - 0x21, 0x24, 0x20, 0x20, 0x20, 0x5B, 0xDB, 0xAC, - 0xE8, 0xE8, 0xE8, 0x3D, 0x7D, 0x48, 0xE6, 0x2D, - 0x85, 0x81, 0x81, 0x48, 0xAE, 0xCA, 0x89, 0xCC, - 0xAE, 0xDB, 0x2D, 0x95, 0x21, 0xCC, 0xDB, 0xAE, - 0x91, 0xE9, 0x7D, 0x73, 0xE8, 0xE8, 0x48, 0x20, - 0x6B, 0x74, 0x41, 0x88, 0x6B, 0x20, 0x20, 0x20, - 0x6B, 0x95, 0xB2, 0xD6, 0xD9, 0x85, 0xDA, 0xDA, - 0xDA, 0x2C, 0xAF, 0xAF, 0x2C, 0xDA, 0xDA, 0x85, - 0xA1, 0xE9, 0x48, 0x95, 0x85, 0xDA, 0x85, 0xAC, - 0xD9, 0xD9, 0x95, 0x95, 0xD9, 0xD9, 0xD9, 0x95, - 0x95, 0x6C, 0x41, 0x93, 0x93, 0x41, 0xDB, 0x95, - 0xE8, 0xE8, 0xE8, 0x3D, 0x95, 0xD4, 0x6C, 0x21, - 0x2D, 0x95, 0xCD, 0x2C, 0xD6, 0xD9, 0x6C, 0x91, - 0x89, 0x7D, 0xAC, 0x2A, 0x8D, 0xE6, 0xCC, 0x88, - 0x74, 0x48, 0xD9, 0xE4, 0xE8, 0xE8, 0xE6, 0x88, - 0x2B, 0x88, 0x20, 0x33, 0xDB, 0x2B, 0xDB, 0x20, - 0x91, 0x7D, 0xD9, 0xD9, 0x85, 0x85, 0xDA, 0xDA, - 0x85, 0xAF, 0xAC, 0xAF, 0x2C, 0x2C, 0x2C, 0x2C, - 0xA1, 0xA1, 0xD6, 0xAF, 0x85, 0xDA, 0x85, 0x2C, - 0xD9, 0xD9, 0x95, 0x95, 0xD9, 0xD9, 0xD9, 0xAC, - 0x2C, 0x47, 0x87, 0x3E, 0x3E, 0xA4, 0x7B, 0x80, - 0xA3, 0xE8, 0xE8, 0x5C, 0x7D, 0x48, 0xE6, 0xD9, - 0xBC, 0xEE, 0x7D, 0x43, 0xD6, 0x21, 0x43, 0x6C, - 0x43, 0x7D, 0x7D, 0xB2, 0x8A, 0xEE, 0x2C, 0xCA, - 0xAE, 0x48, 0x2C, 0xE4, 0xE8, 0x5C, 0xCC, 0x88, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x41, 0x91, 0xE3, - 0x21, 0xD9, 0x2C, 0x2C, 0xDA, 0xDA, 0xDA, 0x85, - 0x2C, 0xAC, 0xD9, 0xD9, 0xAC, 0xAF, 0xAF, 0xAF, - 0xD6, 0x7D, 0xD9, 0x2C, 0xDA, 0xDA, 0x85, 0xAC, - 0xD9, 0x7D, 0x7D, 0xD9, 0xD9, 0xD9, 0x2C, 0x2C, - 0xB8, 0x9C, 0xEC, 0x62, 0x6F, 0x62, 0x70, 0x3C, - 0xAE, 0xCD, 0xE8, 0xE8, 0x8C, 0x7D, 0xC8, 0x3D, - 0x8A, 0xE9, 0x2D, 0x9E, 0xA1, 0xD6, 0x48, 0x73, - 0x81, 0xD6, 0xD6, 0xAE, 0x5B, 0x2D, 0xA3, 0xA3, - 0x21, 0x21, 0xCD, 0xE8, 0xC0, 0x56, 0x31, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x33, 0xCC, 0xDB, - 0x42, 0x85, 0x85, 0x85, 0x85, 0x85, 0x2C, 0x2C, - 0xAC, 0xD9, 0xD9, 0xD9, 0xAC, 0xAF, 0xAF, 0xAF, - 0xD9, 0x95, 0xAC, 0x2C, 0x85, 0x85, 0x2C, 0xD9, - 0x7D, 0xD6, 0xD6, 0xD9, 0xAC, 0xAF, 0x8A, 0xBC, - 0xC2, 0x68, 0x2E, 0x4B, 0xC9, 0x8B, 0x62, 0x87, - 0x3C, 0x74, 0xBC, 0xE8, 0xE8, 0xE4, 0xEE, 0xA1, - 0xE9, 0x21, 0xE6, 0x89, 0x48, 0x7D, 0xB2, 0x5C, - 0x6C, 0x7D, 0x21, 0x80, 0xE3, 0x33, 0xCC, 0x2C, - 0x3D, 0x3D, 0xE8, 0xE8, 0xEC, 0xCB, 0x5A, 0x6B, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x88, 0x41, 0x51, - 0x49, 0x28, 0x85, 0x85, 0x85, 0x85, 0x2C, 0xAF, - 0xAC, 0xAC, 0xAF, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, - 0xD9, 0x95, 0xD9, 0x2C, 0x85, 0x85, 0x2C, 0xD9, - 0xB2, 0xB2, 0x2C, 0x2A, 0x79, 0x79, 0x97, 0x44, - 0xED, 0x29, 0x32, 0x62, 0x4B, 0x62, 0x6F, 0x22, - 0xF3, 0x6B, 0x33, 0x85, 0x73, 0xE4, 0x2D, 0x2B, - 0xCC, 0x9F, 0xDA, 0xBC, 0x48, 0xD6, 0xA1, 0xE4, - 0xE9, 0xD6, 0xD9, 0x2A, 0xB2, 0x2B, 0x2B, 0xA1, - 0xB8, 0xE8, 0xE8, 0xE8, 0xEC, 0x3E, 0x30, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x6B, 0x54, 0xDC, - 0xC9, 0x53, 0xBC, 0x2C, 0x2C, 0x2C, 0xAF, 0xAF, - 0xAF, 0xAC, 0xAF, 0xAC, 0xAC, 0x2C, 0xAF, 0xAC, - 0x2C, 0x7D, 0xD9, 0x2C, 0x85, 0xDA, 0xAF, 0x7D, - 0xB2, 0xAC, 0xC6, 0xBA, 0x4C, 0xEF, 0xA7, 0xEF, - 0xEC, 0x7A, 0x62, 0x4B, 0x62, 0x4B, 0x8B, 0x4B, - 0x3A, 0x52, 0x20, 0x6B, 0x21, 0x73, 0xAC, 0x2B, - 0x41, 0x33, 0x48, 0x67, 0xA1, 0xD6, 0xD6, 0x5C, - 0xE9, 0xD6, 0x2C, 0xEE, 0xB2, 0x9F, 0x8A, 0x95, - 0x4D, 0xE8, 0xE8, 0x3D, 0x7A, 0x57, 0xD1, 0x7B, - 0x20, 0x20, 0x20, 0x20, 0x6B, 0xCF, 0xBA, 0x3E, - 0x3E, 0xD0, 0xBC, 0xAC, 0xAC, 0x2C, 0x2C, 0xAC, - 0xD9, 0xD9, 0x95, 0x95, 0x7D, 0x95, 0x95, 0xD9, - 0x85, 0xD9, 0xAF, 0xDA, 0xDA, 0x85, 0xAC, 0x21, - 0xB2, 0x2A, 0xBA, 0x57, 0x2E, 0x2E, 0x2E, 0x7A, - 0x32, 0x62, 0x8B, 0x4B, 0x8B, 0x4B, 0x4B, 0x4B, - 0xC9, 0x4A, 0x5F, 0x20, 0x20, 0x2D, 0xA3, 0xD9, - 0xCA, 0x88, 0xDB, 0x24, 0x48, 0x7D, 0xB2, 0xE4, - 0x2D, 0x7D, 0x7D, 0x81, 0xA1, 0xDA, 0x21, 0xDA, - 0xE4, 0xE8, 0xEE, 0xF1, 0x2E, 0x57, 0x82, 0x76, - 0x52, 0x4F, 0x4F, 0x98, 0xDE, 0xB5, 0xEC, 0x2E, - 0x3E, 0x6D, 0x85, 0x2C, 0xAC, 0xAC, 0xD9, 0xD9, - 0x95, 0xD6, 0x7D, 0x7D, 0x95, 0xD9, 0xD9, 0xD9, - 0xDA, 0x2C, 0x85, 0xDA, 0xDA, 0x2C, 0x95, 0xB2, - 0x21, 0xB8, 0xED, 0x2E, 0x3E, 0x4B, 0xC9, 0x4B, - 0x8B, 0x62, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, - 0x22, 0x6F, 0xCE, 0x20, 0x20, 0x20, 0x80, 0xCD, - 0xDA, 0x2D, 0x2B, 0xDB, 0xE9, 0xD6, 0x95, 0x5C, - 0x2D, 0x7D, 0x7D, 0xAF, 0xAF, 0xAC, 0xEE, 0x5C, - 0xE8, 0xE8, 0xEB, 0x25, 0x7A, 0x57, 0x39, 0xE1, - 0x83, 0xA8, 0x55, 0x83, 0x82, 0x57, 0x32, 0x8B, - 0x62, 0x6D, 0xEB, 0x95, 0xD9, 0xD9, 0xD9, 0xD9, - 0xD9, 0xD9, 0xD9, 0xAF, 0x2C, 0x2C, 0x2C, 0x2C, - 0xDA, 0x2C, 0x85, 0x85, 0x85, 0xAC, 0xD6, 0x21, - 0x95, 0x6E, 0xED, 0x57, 0x62, 0x4B, 0x8B, 0x4B, - 0x4B, 0x62, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x62, - 0x62, 0x62, 0x25, 0x3C, 0x20, 0x20, 0x20, 0xE3, - 0x2A, 0xBC, 0x7D, 0xCA, 0x6C, 0xD6, 0x95, 0x3D, - 0x81, 0x7D, 0xD6, 0xD6, 0xDA, 0x73, 0xE8, 0xE8, - 0xE8, 0x4D, 0x94, 0xED, 0x72, 0x3A, 0xF1, 0xA7, - 0x39, 0xED, 0x39, 0xEF, 0x57, 0x32, 0x8B, 0x4B, - 0x62, 0x62, 0xA6, 0x2A, 0xD9, 0xD9, 0xD9, 0xD9, - 0x2C, 0x2C, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x2C, 0x2C, 0xAF, 0xAC, 0x95, 0x21, 0x7D, - 0xAC, 0x8C, 0x46, 0xC4, 0x62, 0x8B, 0x4B, 0x4B, - 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, - 0x4B, 0x62, 0xC9, 0x30, 0x7B, 0x20, 0x20, 0x20, - 0x41, 0x4D, 0x3D, 0x85, 0x48, 0x21, 0xDA, 0x3D, - 0xE9, 0xD6, 0xD9, 0xCD, 0x5C, 0xE8, 0xE8, 0xE8, - 0xE8, 0x4D, 0x71, 0x46, 0xEC, 0x2E, 0x72, 0xEC, - 0x29, 0x29, 0x7C, 0x29, 0x2E, 0x4B, 0x4B, 0x62, - 0x62, 0x4B, 0x3A, 0xAD, 0xE2, 0xAF, 0xD9, 0xD9, - 0x2C, 0xDA, 0xDA, 0xDA, 0xDA, 0x85, 0x2C, 0x2C, - 0x2C, 0xAF, 0xAC, 0xD9, 0x95, 0xD6, 0xD6, 0xD9, - 0x2C, 0x8C, 0xBA, 0x7C, 0x2E, 0x4B, 0x4B, 0x4B, - 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, - 0x4B, 0x62, 0xC9, 0xDC, 0x34, 0x20, 0x20, 0x20, - 0x20, 0xAC, 0xE8, 0x5C, 0x8C, 0xBC, 0xE4, 0xE8, - 0xEE, 0x2A, 0xA3, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, - 0xE4, 0x7E, 0x65, 0x46, 0x29, 0x62, 0x62, 0x2E, - 0x2E, 0x72, 0x2E, 0x2E, 0x32, 0x4B, 0x4B, 0x62, - 0x4B, 0x4B, 0x4B, 0x32, 0x61, 0x9D, 0x2C, 0xD9, - 0x2C, 0x85, 0xDA, 0x85, 0x2C, 0xAF, 0xAF, 0xAF, - 0x2C, 0xAC, 0xD9, 0x95, 0xD6, 0x7D, 0x95, 0xAC, - 0x2C, 0xDA, 0x40, 0x7C, 0x2E, 0x4B, 0x4B, 0x4B, - 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, - 0x4B, 0x62, 0x62, 0x22, 0xB7, 0xCE, 0x20, 0x20, - 0x20, 0x95, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, - 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0x5C, - 0x3D, 0xE9, 0x9A, 0x46, 0x7C, 0x32, 0x8B, 0x62, - 0x4B, 0x8B, 0x8B, 0x4B, 0x4B, 0x4B, 0x4B, 0x62, - 0x4B, 0x4B, 0x4B, 0x4B, 0x62, 0x61, 0x4E, 0xDA, - 0x85, 0x85, 0x85, 0x2C, 0xD9, 0xD9, 0xD9, 0xD9, - 0x85, 0xD9, 0x7D, 0x21, 0x21, 0xD6, 0xAC, 0x2C, - 0x2C, 0xDA, 0xDD, 0x77, 0x8B, 0x62, 0x4B, 0x4B, - 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, - 0x3E, 0x8B, 0x32, 0xC9, 0x22, 0x68, 0x88, 0x33, - 0xA1, 0x73, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, - 0xE8, 0xE8, 0xE8, 0x5C, 0x5C, 0x5C, 0x5C, 0x3D, - 0x89, 0x20, 0x54, 0x23, 0x29, 0x2E, 0x4B, 0x62, - 0x4B, 0x3E, 0x4B, 0x62, 0x4B, 0x4B, 0x4B, 0x8B, - 0x8B, 0xC9, 0x6F, 0x4B, 0x8B, 0x4B, 0x78, 0xE2, - 0x8A, 0x8A, 0x85, 0xAC, 0xD9, 0x7D, 0xD9, 0xAC, - 0x2C, 0xD9, 0xD6, 0xB2, 0x21, 0x7D, 0xAF, 0x85, - 0x2C, 0xDA, 0x40, 0xEF, 0x62, 0x62, 0x4B, 0x4B, - 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, - 0x4B, 0x4B, 0x8B, 0x4B, 0xC9, 0x63, 0xB4, 0x5C, - 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, - 0xE8, 0xE8, 0xE8, 0xE8, 0x5C, 0x5C, 0xCD, 0xAE, - 0x20, 0x20, 0xCE, 0xE1, 0x57, 0x32, 0x4B, 0x4B, - 0x8B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, - 0x8B, 0x4B, 0x62, 0x4B, 0x62, 0x2E, 0x61, 0x28, - 0x8D, 0xDA, 0xAF, 0xD9, 0x95, 0x95, 0xD9, 0xAF, - 0xAF, 0xD9, 0xD6, 0xB2, 0x21, 0xD9, 0x2C, 0x85, - 0xAF, 0xEB, 0xE1, 0x57, 0x2E, 0x62, 0x4B, 0x4B, - 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, - 0x4B, 0x4B, 0x4B, 0x4B, 0x3E, 0x9B, 0x31, 0x6E, - 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, - 0x5C, 0xE8, 0xE8, 0xE8, 0x3D, 0x7D, 0x33, 0x6B, - 0x20, 0x20, 0x34, 0x23, 0x29, 0x3E, 0x4B, 0x4B, - 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, - 0x4B, 0x3E, 0x62, 0x62, 0x2E, 0xC4, 0x49, 0xD5, - 0xDA, 0xD9, 0xD6, 0xA1, 0xA1, 0x21, 0xD9, 0xD9, - 0xD9, 0x95, 0x21, 0x48, 0xD6, 0xAC, 0x85, 0x85, - 0xAF, 0xB6, 0x5D, 0x2E, 0x32, 0x4B, 0x4B, 0x4B, - 0x4B, 0x4B, 0x62, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, - 0x4B, 0x4B, 0x4B, 0x4B, 0x62, 0x2E, 0x45, 0xDE, - 0xDA, 0x5C, 0xE8, 0x5C, 0xE8, 0xE8, 0x5C, 0xE8, - 0x5C, 0x5C, 0xA3, 0xAC, 0x2B, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x34, 0x23, 0x29, 0x62, 0x4B, 0x4B, - 0x4B, 0x4B, 0x4B, 0x4B, 0x62, 0x4B, 0x4B, 0x4B, - 0x4B, 0x3E, 0x3E, 0x63, 0x40, 0x97, 0x28, 0xDA, - 0xD9, 0xA1, 0x48, 0xE9, 0x48, 0x21, 0xD9, 0xD9, - 0xA1, 0xB2, 0xB2, 0xA1, 0x21, 0xAC, 0x85, 0x2C, - 0xDA, 0x36, 0x77, 0x72, 0x62, 0x8B, 0x62, 0x4B, - 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, - 0x4B, 0x4B, 0x4B, 0x4B, 0x3E, 0xEC, 0x2F, 0x51, - 0xE3, 0xAE, 0x48, 0x2C, 0xDA, 0xDA, 0x85, 0xAC, - 0x48, 0x9E, 0x88, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x41, 0xA0, 0x23, 0x72, 0x2E, 0x4B, 0x4B, - 0x4B, 0x62, 0x62, 0x4B, 0x4B, 0x4B, 0x2E, 0x8B, - 0xF0, 0x4C, 0x40, 0xC2, 0x90, 0x8D, 0x85, 0xD9, - 0xA1, 0x6C, 0x6C, 0x48, 0xD6, 0xD9, 0xAF, 0xAC, - 0xA1, 0xD6, 0xD6, 0xB2, 0xD6, 0xAC, 0x85, 0x85, - 0x4D, 0xBE, 0x39, 0x4C, 0x57, 0x2E, 0x2E, 0x2E, - 0x3E, 0x3E, 0x62, 0x3E, 0x4B, 0x4B, 0x4B, 0x4B, - 0x4B, 0x4B, 0x4B, 0x8B, 0x8B, 0x57, 0x60, 0x76, - 0x52, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x3C, 0xA0, 0x23, 0x7C, 0x2E, 0x4B, 0x4B, - 0x8B, 0x62, 0x4B, 0x4B, 0x3E, 0x7A, 0xF0, 0x29, - 0x36, 0x97, 0xBC, 0x8A, 0x8D, 0xDA, 0xD9, 0x48, - 0x81, 0x2D, 0x48, 0xD6, 0xD9, 0xAF, 0x2C, 0x2C, - 0xAC, 0xAF, 0xD9, 0x7D, 0x7D, 0x2C, 0x85, 0x85, - 0x85, 0xB4, 0x66, 0x23, 0x46, 0x2F, 0x60, 0x68, - 0x77, 0x29, 0x29, 0xF0, 0x2E, 0x2E, 0x62, 0x4B, - 0x4B, 0x4B, 0x4B, 0x4B, 0x32, 0x7C, 0x83, 0xB3, - 0x54, 0x6B, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x6B, 0x7B, 0xC3, 0xE7, 0x39, 0x72, 0x62, 0x62, - 0x62, 0x62, 0x62, 0x2E, 0x29, 0x77, 0xA7, 0x36, - 0xB8, 0x85, 0x85, 0x8D, 0x8D, 0x85, 0xB2, 0x2D, - 0x2D, 0xE9, 0xD6, 0xD9, 0xAF, 0x2C, 0x85, 0x85, - 0x2A, 0x85, 0xAC, 0x95, 0x95, 0xAF, 0x85, 0x85, - 0xAF, 0x8C, 0xDF, 0xC6, 0xB1, 0xD1, 0xE5, 0xE7, - 0x83, 0x23, 0x5D, 0x60, 0x39, 0x77, 0xEC, 0x2E, - 0x2E, 0x32, 0x32, 0x2E, 0x7C, 0x5D, 0x35, 0xA2, - 0x54, 0x6B, 0x6B, 0x20, 0x6B, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x6B, 0x88, 0xC1, 0x35, 0xE1, 0x77, 0x57, 0x2E, - 0x2E, 0x72, 0x29, 0x77, 0x60, 0xB5, 0x44, 0xE2, - 0x2C, 0x2C, 0xDA, 0x8A, 0xDA, 0xAF, 0xA1, 0x2D, - 0xE9, 0xD6, 0xD9, 0xAF, 0x2C, 0x85, 0x85, 0x85, - 0xEE, 0xAF, 0xD9, 0x7D, 0xD9, 0x2C, 0xDA, 0x85, - 0xAC, 0xAF, 0x85, 0xDA, 0x8A, 0x2A, 0xE2, 0x50, - 0x86, 0xD7, 0x75, 0x35, 0xA8, 0xE7, 0xE1, 0x5D, - 0x68, 0x7C, 0xF1, 0x68, 0xE1, 0xBF, 0xA2, 0xC1, - 0x52, 0x2B, 0x7D, 0xAC, 0xAF, 0x2C, 0x2C, 0x2C, - 0x2C, 0x85, 0x85, 0x85, 0x2C, 0x2C, 0x2C, 0x95, - 0xE9, 0x74, 0xCE, 0xE0, 0xE7, 0x60, 0x77, 0x77, - 0x7C, 0xEF, 0x5D, 0x23, 0x3F, 0xB6, 0x8A, 0x2C, - 0xAC, 0xAF, 0x85, 0x8A, 0x85, 0xD9, 0x48, 0x48, - 0xB2, 0x95, 0x95, 0xD9, 0x85, 0xDA, 0x85, 0x85, - 0xD3, 0xB2, 0x21, 0x7D, 0xAC, 0x2C, 0xDA, 0x85, - 0xAC, 0xAC, 0x85, 0x85, 0x85, 0x2C, 0xAF, 0x2C, - 0xDA, 0x8C, 0x79, 0xC7, 0xB0, 0x51, 0xB3, 0x35, - 0xBF, 0xE5, 0xE7, 0xA8, 0xE0, 0xA2, 0xC1, 0x34, - 0x7D, 0x85, 0xAC, 0xD9, 0xAC, 0xAF, 0xAC, 0xAC, - 0xAF, 0x2C, 0x2C, 0x2C, 0x2C, 0xAF, 0xAF, 0x85, - 0xC8, 0xCD, 0x6A, 0x26, 0x35, 0x3F, 0x83, 0x23, - 0x23, 0xE7, 0xBF, 0x96, 0xEB, 0xDA, 0xDA, 0x2C, - 0x2C, 0x2C, 0x85, 0xDA, 0x2C, 0x7D, 0xA1, 0x48, - 0xB2, 0x21, 0xD6, 0xD9, 0x2C, 0xDA, 0x85, 0xAF, - 0xAF, 0x2D, 0xE9, 0x7D, 0xAC, 0x2C, 0x85, 0x2C, - 0xD9, 0xD9, 0xAF, 0x85, 0x85, 0x85, 0x2C, 0x2C, - 0x2C, 0x85, 0xD9, 0x21, 0xAC, 0x2C, 0xBD, 0xA5, - 0xC3, 0xA2, 0xA2, 0xA2, 0x26, 0xC1, 0xCE, 0x2A, - 0xAF, 0x95, 0xD9, 0x2C, 0x2C, 0x85, 0x2C, 0xAF, - 0xAC, 0x2C, 0x85, 0x2C, 0xAF, 0x2C, 0x85, 0xDA, - 0x8D, 0x2A, 0x85, 0x34, 0xC1, 0xB3, 0x76, 0x35, - 0xE0, 0x30, 0xA5, 0xB6, 0x2C, 0x85, 0x85, 0x85, - 0xAF, 0x2C, 0x85, 0x85, 0xD9, 0xD6, 0xA1, 0xA1, - 0x48, 0xA1, 0xD6, 0xAF, 0xDA, 0x8A, 0x2C, 0xD9, - 0xB2, 0x2D, 0x48, 0xD9, 0xAF, 0x2C, 0x2C, 0x85, - 0xAF, 0xAC, 0x2C, 0x85, 0x85, 0x85, 0xAF, 0xAC, - 0xAC, 0x2C, 0xD9, 0xD6, 0xD6, 0x21, 0xB2, 0x2C, - 0xC8, 0x3B, 0x65, 0xC5, 0xCE, 0x8E, 0xC8, 0x2C, - 0xD9, 0x95, 0xAC, 0x2C, 0x2C, 0x2C, 0xAF, 0xAC, - 0xAC, 0xAF, 0x2C, 0x85, 0x2C, 0x2C, 0x2C, 0x85, - 0xDA, 0x2C, 0xD6, 0xAF, 0x59, 0x65, 0xDE, 0xF3, - 0xF3, 0x59, 0xBC, 0xAC, 0xAF, 0x85, 0x85, 0x85, - 0xAF, 0xD9, 0xAF, 0x2C, 0xD9, 0xD6, 0xD6, 0xD6, - 0x21, 0xD6, 0xD9, 0xDA, 0x8D, 0x8A, 0x2C, 0xD9, - 0xB2, 0xA1, 0xD6, 0xAC, 0x2C, 0x2C, 0x2C, 0x85, - 0x2C, 0xAC, 0x2C, 0xDA, 0xDA, 0x85, 0xAF, 0xD9, - 0xD9, 0xAC, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xAC, - 0x85, 0x2A, 0x4D, 0xBC, 0x85, 0xAC, 0xAF, 0xAF, - 0xAC, 0xD9, 0xAF, 0x2C, 0xAF, 0xD9, 0xD9, 0xAC, - 0xAC, 0xAF, 0x85, 0x2C, 0x85, 0x2C, 0x2C, 0x2C, - 0x2C, 0xD9, 0xB2, 0xD4, 0xD6, 0x2C, 0x8A, 0xDA, - 0xC8, 0x85, 0x2C, 0xAC, 0x2C, 0xDA, 0xDA, 0x85, - 0xAF, 0xAC, 0xD9, 0xAC, 0xD9, 0xD9, 0xD9, 0xD9, - 0xD9, 0xAC, 0xDA, 0x8D, 0xBC, 0xDA, 0xD9, 0x95, - 0x95, 0xD9, 0xD9, 0xAF, 0x2C, 0x2C, 0x2C, 0x85, - 0x2C, 0xAF, 0xAF, 0x85, 0x85, 0x85, 0x2C, 0xAC, - 0xD9, 0xAF, 0xAF, 0xAF, 0x2C, 0x2C, 0x2C, 0x85, - 0x8A, 0x2A, 0x8D, 0x2C, 0xD9, 0x95, 0xAC, 0xAC, - 0xD9, 0xD9, 0xD9, 0xD9, 0x95, 0x95, 0xD9, 0xAF, - 0xAF, 0x2C, 0x85, 0x85, 0x85, 0x85, 0x85, 0x2C, - 0x85, 0x2C, 0xD9, 0xD9, 0xD9, 0x2C, 0x2C, 0x2C, - 0x2C, 0x85, 0x85, 0xAF, 0xAF, 0x85, 0x85, 0x85, - 0xAF, 0xD9, 0xD9, 0xAC, 0xAF, 0x2C, 0x2C, 0x2C, - 0x2C, 0x85, 0x8A, 0x2A, 0x8D, 0x2C, 0xD9, 0xD9, - 0x2C, 0xAC, 0xAF, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, - 0x85, 0xAF, 0xAC, 0x2C, 0x2C, 0x2C, 0x2C, 0xAC, - 0xD9, 0xD9, 0xAF, 0x85, 0x85, 0x85, 0xDA, 0xDA, - 0x8A, 0x8A, 0x85, 0xAC, 0xD9, 0xD9, 0xAC, 0xD9, - 0xD6, 0xD6, 0x7D, 0x95, 0x7D, 0xD9, 0xAF, 0xAF, - 0xAF, 0x2C, 0x85, 0x85, 0xDA, 0x85, 0x2C, 0x85, - 0x85, 0x2C, 0xAF, 0xAC, 0xAF, 0xAF, 0x2C, 0x2C, - 0x2C, 0x2C, 0x2C, 0xAF, 0xAC, 0x2C, 0x2C, 0x2C, - 0x2C, 0xAF, 0xD9, 0xAC, 0xAF, 0x2C, 0x85, 0x85, - 0x85, 0xDA, 0x8D, 0x8A, 0x85, 0xAC, 0x95, 0xD9 + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, + 0x22, 0x21, 0x21, 0x21, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x26, 0x26, 0x25, 0x28, 0x23, 0x22, 0x21, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x23, 0x25, 0x2a, 0x2b, 0x2c, 0x2d, 0x2d, + 0x2d, 0x2e, 0x2c, 0x2b, 0x2a, 0x25, 0x28, 0x22, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x24, 0x2a, 0x2c, 0x2f, 0x2c, 0x30, 0x30, 0x24, + 0x25, 0x27, 0x2b, 0x2c, 0x2f, 0x31, 0x32, 0x25, + 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x25, + 0x33, 0x34, 0x35, 0x21, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x21, 0x2b, 0x2f, 0x2c, + 0x30, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, 0x33, + 0x2d, 0x27, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x31, + 0x2d, 0x32, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x21, 0x28, 0x2a, 0x34, + 0x25, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x23, 0x32, 0x27, 0x21, 0x36, + 0x2a, 0x2d, 0x2a, 0x28, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x22, 0x26, 0x2c, 0x35, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x25, 0x2f, 0x37, 0x32, 0x22, + 0x36, 0x35, 0x31, 0x27, 0x22, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x23, 0x2a, 0x2f, 0x22, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x26, 0x38, 0x38, 0x35, 0x25, + 0x36, 0x21, 0x2d, 0x2b, 0x24, 0x21, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x21, 0x24, 0x39, 0x39, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x25, 0x2b, 0x30, 0x28, 0x22, + 0x36, 0x36, 0x27, 0x34, 0x30, 0x23, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x21, 0x26, 0x2d, 0x26, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x22, 0x22, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x2d, 0x33, 0x28, 0x21, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x30, 0x2f, 0x23, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x2b, 0x2c, 0x25, 0x21, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x2a, 0x34, 0x36, 0x36, + 0x36, 0x21, 0x22, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x21, 0x23, 0x22, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x28, 0x34, 0x27, 0x22, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x36, + 0x21, 0x21, 0x24, 0x27, 0x21, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x28, 0x27, 0x22, 0x33, 0x24, 0x36, + 0x36, 0x36, 0x36, 0x22, 0x2f, 0x2a, 0x23, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x36, + 0x30, 0x3a, 0x38, 0x24, 0x24, 0x36, 0x36, 0x36, + 0x23, 0x2f, 0x3b, 0x3c, 0x3d, 0x30, 0x25, 0x21, + 0x36, 0x36, 0x36, 0x36, 0x2f, 0x32, 0x23, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x23, + 0x3e, 0x3f, 0x40, 0x3a, 0x22, 0x36, 0x36, 0x21, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x3e, 0x23, 0x21, + 0x36, 0x36, 0x36, 0x36, 0x2f, 0x33, 0x28, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x29, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x2b, + 0x44, 0x40, 0x46, 0x47, 0x35, 0x36, 0x36, 0x26, + 0x43, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x2e, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x31, 0x35, 0x24, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x32, 0x34, 0x36, 0x4d, + 0x4e, 0x25, 0x2f, 0x46, 0x4a, 0x22, 0x23, 0x32, + 0x4f, 0x50, 0x21, 0x31, 0x51, 0x52, 0x53, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x31, 0x35, 0x24, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x29, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x2a, 0x2f, 0x21, 0x3a, + 0x4d, 0x21, 0x31, 0x54, 0x55, 0x28, 0x30, 0x2b, + 0x4b, 0x4d, 0x36, 0x23, 0x32, 0x50, 0x3f, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x2e, 0x39, 0x24, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x29, 0x20, 0x29, 0x20, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x2a, 0x38, 0x23, 0x37, + 0x55, 0x36, 0x28, 0x3a, 0x56, 0x57, 0x57, 0x58, + 0x3c, 0x4d, 0x36, 0x36, 0x36, 0x40, 0x40, 0x21, + 0x36, 0x36, 0x36, 0x36, 0x2e, 0x39, 0x24, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x29, 0x29, 0x29, 0x20, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x30, 0x51, 0x23, 0x35, + 0x43, 0x25, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, + 0x5f, 0x60, 0x61, 0x36, 0x31, 0x47, 0x3b, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x31, 0x2c, 0x25, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x30, 0x2f, 0x23, 0x22, + 0x40, 0x62, 0x63, 0x5d, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x66, 0x5e, 0x6a, 0x6b, 0x2a, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x33, 0x2e, 0x26, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x27, 0x2f, 0x23, 0x36, + 0x6c, 0x63, 0x6d, 0x64, 0x5c, 0x66, 0x69, 0x6e, + 0x6f, 0x70, 0x71, 0x69, 0x69, 0x72, 0x6c, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x33, 0x34, 0x27, 0x22, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x27, 0x34, 0x26, 0x73, + 0x74, 0x75, 0x76, 0x64, 0x65, 0x77, 0x69, 0x78, + 0x70, 0x71, 0x71, 0x71, 0x72, 0x5f, 0x5e, 0x21, + 0x36, 0x36, 0x36, 0x36, 0x25, 0x38, 0x2a, 0x23, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x26, 0x2d, 0x33, 0x79, + 0x63, 0x7a, 0x7b, 0x5c, 0x66, 0x69, 0x6e, 0x7c, + 0x71, 0x71, 0x69, 0x7d, 0x7e, 0x7a, 0x7f, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x21, 0x51, 0x2b, 0x28, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x26, 0x2d, 0x32, 0x24, + 0x80, 0x81, 0x64, 0x82, 0x77, 0x69, 0x71, 0x71, + 0x69, 0x83, 0x84, 0x85, 0x7a, 0x85, 0x86, 0x36, + 0x21, 0x2b, 0x23, 0x36, 0x36, 0x39, 0x2e, 0x26, + 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x27, 0x2d, 0x33, 0x21, + 0x87, 0x88, 0x89, 0x72, 0x67, 0x66, 0x5f, 0x89, + 0x8a, 0x63, 0x85, 0x8b, 0x8c, 0x8d, 0x41, 0x36, + 0x36, 0x2d, 0x3a, 0x35, 0x36, 0x24, 0x51, 0x32, + 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x30, 0x2f, 0x33, 0x21, + 0x55, 0x8e, 0x8f, 0x8a, 0x7d, 0x5e, 0x90, 0x7e, + 0x75, 0x75, 0x90, 0x62, 0x40, 0x3f, 0x49, 0x23, + 0x36, 0x24, 0x3a, 0x3a, 0x24, 0x36, 0x2e, 0x31, + 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x21, 0x28, 0x33, 0x37, 0x25, 0x22, + 0x3b, 0x50, 0x8e, 0x8f, 0x90, 0x7e, 0x90, 0x63, + 0x74, 0x91, 0x92, 0x42, 0x93, 0x4b, 0x45, 0x2c, + 0x36, 0x36, 0x33, 0x39, 0x21, 0x36, 0x22, 0x51, + 0x33, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x22, 0x27, 0x2e, 0x2e, 0x36, 0x21, + 0x94, 0x3f, 0x50, 0x95, 0x96, 0x8f, 0x8f, 0x97, + 0x8e, 0x42, 0x50, 0x43, 0x47, 0x48, 0x48, 0x98, + 0x21, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x39, + 0x2e, 0x27, 0x23, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x22, 0x24, 0x2b, 0x38, 0x28, 0x36, 0x32, + 0x4c, 0x4b, 0x50, 0x50, 0x50, 0x42, 0x42, 0x50, + 0x50, 0x40, 0x45, 0x99, 0x48, 0x48, 0x48, 0x48, + 0x34, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x23, + 0x2f, 0x2b, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x28, 0x32, 0x51, 0x32, 0x28, 0x21, 0x98, + 0x48, 0x47, 0x9a, 0x50, 0x50, 0x50, 0x50, 0x50, + 0x9a, 0x4f, 0x9b, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x93, 0x23, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x2a, 0x2f, 0x2a, 0x28, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x23, 0x30, 0x2e, 0x2c, 0x36, 0x21, 0x51, 0x9b, + 0x48, 0x48, 0x52, 0x3f, 0x50, 0x50, 0x40, 0x4b, + 0x47, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x34, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x2d, 0x31, 0x27, 0x23, 0x21, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23, + 0x27, 0x2c, 0x2d, 0x21, 0x36, 0x28, 0x44, 0x48, + 0x48, 0x48, 0x48, 0x47, 0x46, 0x4f, 0x47, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x9c, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x28, 0x51, 0x39, 0x26, 0x22, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x25, + 0x35, 0x51, 0x28, 0x36, 0x36, 0x9d, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x9b, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x4f, 0x28, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x28, 0x38, 0x2b, 0x25, 0x22, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, 0x33, + 0x51, 0x25, 0x36, 0x36, 0x23, 0x40, 0x9b, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x9b, 0x99, 0x2b, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x30, 0x2f, 0x33, 0x24, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x21, 0x23, 0x30, 0x34, + 0x27, 0x36, 0x36, 0x36, 0x2a, 0x40, 0x47, 0x48, + 0x48, 0x48, 0x48, 0x9b, 0x99, 0x99, 0x9b, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x9b, 0x47, 0x52, + 0x46, 0x4f, 0x37, 0x21, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x30, 0x34, 0x2a, 0x23, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x22, 0x25, 0x39, 0x2c, + 0x36, 0x36, 0x36, 0x21, 0x31, 0x4e, 0x9a, 0x4c, + 0x47, 0x9b, 0x9b, 0x52, 0x46, 0x4f, 0x52, 0x9b, + 0x9b, 0x9b, 0x47, 0x4f, 0x45, 0x9a, 0x93, 0x93, + 0x3f, 0x93, 0x98, 0x28, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x39, 0x2c, 0x26, + 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x23, 0x2a, 0x34, 0x28, + 0x36, 0x36, 0x36, 0x22, 0x38, 0x98, 0x44, 0x99, + 0x9b, 0x48, 0x48, 0x9b, 0x4c, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x47, 0x52, 0x46, 0x43, 0x93, + 0x40, 0x40, 0x43, 0x53, 0x21, 0x23, 0x33, 0x23, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x2f, 0x32, + 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x21, 0x24, 0x2b, 0x31, 0x36, + 0x36, 0x22, 0x36, 0x24, 0x9e, 0x4f, 0x9b, 0x48, + 0x48, 0x48, 0x48, 0x9b, 0x99, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x47, + 0x4f, 0x9a, 0x3f, 0x46, 0x38, 0x36, 0x21, 0x30, + 0x26, 0x36, 0x36, 0x36, 0x36, 0x36, 0x39, 0x2c, + 0x25, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x26, 0x2e, 0x33, 0x36, + 0x25, 0x25, 0x36, 0x4d, 0x52, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x4f, 0x3e, 0x4d, 0x49, 0x48, + 0x98, 0x2b, 0x55, 0x4f, 0x9b, 0x48, 0x48, 0x48, + 0x48, 0x47, 0x44, 0x93, 0x43, 0x23, 0x36, 0x36, + 0x26, 0x24, 0x36, 0x36, 0x36, 0x36, 0x28, 0x2f, + 0x2a, 0x23, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x2a, 0x51, 0x24, 0x36, + 0x2a, 0x36, 0x28, 0x44, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x4f, 0x54, 0x38, 0x3d, 0x98, 0x37, 0x9b, + 0x3a, 0x22, 0x23, 0x2a, 0x55, 0x4f, 0x48, 0x48, + 0x48, 0x48, 0x9b, 0x4b, 0x44, 0x37, 0x36, 0x23, + 0x28, 0x30, 0x22, 0x36, 0x36, 0x36, 0x36, 0x2d, + 0x35, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x21, 0x28, 0x2b, 0x34, 0x36, 0x25, + 0x24, 0x36, 0x4a, 0x48, 0x48, 0x48, 0x48, 0x52, + 0x53, 0x37, 0x54, 0x98, 0x55, 0x38, 0x38, 0x47, + 0x4a, 0x2d, 0x30, 0x23, 0x28, 0x39, 0x53, 0x52, + 0x48, 0x48, 0x48, 0x9b, 0x52, 0x3f, 0x21, 0x30, + 0x35, 0x25, 0x30, 0x36, 0x36, 0x36, 0x36, 0x32, + 0x2d, 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x22, 0x26, 0x2e, 0x35, 0x36, 0x2a, + 0x36, 0x24, 0x4f, 0x48, 0x48, 0x9b, 0x55, 0x39, + 0x55, 0x53, 0x3a, 0x55, 0x3a, 0x51, 0x51, 0x47, + 0x55, 0x3a, 0x4d, 0x37, 0x30, 0x22, 0x24, 0x2b, + 0x54, 0x9b, 0x48, 0x48, 0x48, 0x47, 0x32, 0x30, + 0x2a, 0x23, 0x30, 0x23, 0x36, 0x36, 0x36, 0x21, + 0x2f, 0x32, 0x23, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x21, 0x23, 0x2a, 0x51, 0x28, 0x28, 0x25, + 0x36, 0x3a, 0x48, 0x48, 0x48, 0x4f, 0x26, 0x23, + 0x26, 0x39, 0x3e, 0x43, 0x49, 0x37, 0x2f, 0x9b, + 0x55, 0x3a, 0x54, 0x43, 0x3e, 0x30, 0x32, 0x3d, + 0x49, 0x3f, 0x48, 0x48, 0x48, 0x48, 0x38, 0x21, + 0x36, 0x36, 0x22, 0x27, 0x36, 0x36, 0x36, 0x36, + 0x2e, 0x35, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x22, 0x25, 0x2c, 0x34, 0x36, 0x30, 0x21, + 0x23, 0x43, 0x48, 0x48, 0x48, 0x47, 0x3b, 0x32, + 0x21, 0x28, 0x2b, 0x9e, 0x49, 0x37, 0x2e, 0x52, + 0x4a, 0x37, 0x9e, 0x98, 0x51, 0x3a, 0x93, 0x54, + 0x55, 0x4f, 0x48, 0x48, 0x48, 0x48, 0x94, 0x36, + 0x36, 0x36, 0x36, 0x32, 0x36, 0x36, 0x36, 0x36, + 0x2a, 0x2e, 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x23, 0x2a, 0x51, 0x25, 0x21, 0x2a, 0x36, + 0x2e, 0x9b, 0x48, 0x48, 0x52, 0x4b, 0x52, 0x9e, + 0x51, 0x30, 0x22, 0x28, 0x32, 0x32, 0x39, 0x47, + 0x37, 0x2a, 0x39, 0x3a, 0x50, 0x9f, 0x3a, 0x9f, + 0x4b, 0x9b, 0x48, 0x48, 0x48, 0x48, 0x98, 0x36, + 0x36, 0x36, 0x36, 0x32, 0x36, 0x36, 0x36, 0x36, + 0x22, 0x2f, 0x30, 0x22, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x22, 0x25, 0x2c, 0x34, 0x36, 0x24, 0x28, 0x36, + 0x54, 0x48, 0x48, 0x45, 0x30, 0x30, 0x9e, 0x52, + 0x45, 0x3a, 0x31, 0x25, 0x22, 0x25, 0x2a, 0x98, + 0x39, 0x2f, 0x42, 0x49, 0x4a, 0x3b, 0x50, 0x47, + 0x43, 0x9d, 0x3b, 0x4b, 0x48, 0x48, 0x9a, 0x36, + 0x36, 0x36, 0x36, 0x30, 0x36, 0x36, 0x36, 0x36, + 0x21, 0x2f, 0x32, 0x23, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x28, 0x32, 0x2f, 0x28, 0x36, 0x27, 0x22, 0x21, + 0x43, 0x48, 0x48, 0x50, 0x30, 0x23, 0x25, 0x2f, + 0x3f, 0x52, 0x49, 0x51, 0x39, 0x25, 0x24, 0x2b, + 0x9e, 0x42, 0x3e, 0x55, 0x9e, 0x4f, 0x4f, 0x54, + 0x4a, 0x9e, 0x49, 0x50, 0x48, 0x48, 0x4b, 0x21, + 0x36, 0x36, 0x21, 0x26, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x34, 0x2b, 0x28, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x25, 0x2c, 0x39, 0x36, 0x36, 0x30, 0x22, 0x25, + 0x52, 0x48, 0x48, 0x45, 0x3a, 0x51, 0x26, 0x23, + 0x30, 0x9d, 0x45, 0x40, 0x3a, 0x39, 0x2b, 0x2b, + 0x3b, 0x3a, 0x55, 0x4b, 0x47, 0x9e, 0x3a, 0x49, + 0x9e, 0x9f, 0x3b, 0x9a, 0x48, 0x48, 0x4f, 0x21, + 0x36, 0x36, 0x22, 0x26, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x2c, 0x35, 0x24, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x30, 0x2d, 0x21, 0x36, 0x36, 0x32, 0x23, 0x2a, + 0x47, 0x48, 0x48, 0x43, 0x3e, 0x3a, 0x9d, 0x2b, + 0x23, 0x25, 0x39, 0x4d, 0x2b, 0x31, 0x2d, 0x9d, + 0x34, 0x2e, 0x2f, 0x9e, 0x3a, 0x55, 0x3f, 0x9f, + 0x9f, 0x3e, 0x55, 0x43, 0x48, 0x48, 0x4c, 0x22, + 0x36, 0x36, 0x24, 0x23, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x2c, 0x39, 0x24, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28, + 0x33, 0x2e, 0x36, 0x36, 0x23, 0x31, 0x27, 0x39, + 0x9b, 0x48, 0x48, 0x4f, 0x3e, 0x4d, 0x55, 0x9e, + 0x51, 0x24, 0x23, 0x26, 0x32, 0x2c, 0x3b, 0x4b, + 0x55, 0x32, 0x2b, 0x37, 0x98, 0x9e, 0x3e, 0x9e, + 0x55, 0x37, 0x3e, 0x4b, 0x48, 0x48, 0x4c, 0x23, + 0x36, 0x36, 0x26, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x2c, 0x39, 0x24, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28, + 0x2b, 0x39, 0x36, 0x36, 0x36, 0x26, 0x32, 0x31, + 0x9b, 0x48, 0x48, 0x4f, 0x55, 0x3a, 0x53, 0x53, + 0x2e, 0x9d, 0x34, 0x28, 0x28, 0x37, 0x98, 0x45, + 0x3e, 0x2b, 0x49, 0x9e, 0x3b, 0x3e, 0x2d, 0x6b, + 0x4a, 0x3a, 0x3b, 0x4f, 0x48, 0x48, 0x46, 0x22, + 0x36, 0x21, 0x26, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x2c, 0x35, 0x24, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, + 0x35, 0x39, 0x36, 0x36, 0x36, 0x36, 0x26, 0x2d, + 0x9b, 0x48, 0x48, 0x47, 0x3b, 0x3a, 0x2f, 0x37, + 0x49, 0x38, 0x38, 0x3a, 0x2b, 0x31, 0x51, 0x32, + 0x2b, 0x26, 0x37, 0x9f, 0x55, 0x32, 0x26, 0x2b, + 0x2d, 0x9d, 0x3b, 0x52, 0x48, 0x48, 0x9a, 0x36, + 0x24, 0x27, 0xa0, 0x24, 0x25, 0x28, 0x21, 0x36, + 0x36, 0x34, 0x2b, 0x28, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x25, + 0x39, 0x4d, 0xa1, 0x84, 0x81, 0x57, 0x21, 0x39, + 0x52, 0x48, 0x48, 0x47, 0x9f, 0x4a, 0x4d, 0x55, + 0x37, 0x9f, 0x45, 0x9e, 0x3e, 0x54, 0x4d, 0x2d, + 0x51, 0x3b, 0x3d, 0x40, 0x50, 0x2f, 0x32, 0x23, + 0x2a, 0x3a, 0x54, 0x47, 0x48, 0x48, 0x53, 0x28, + 0x23, 0x36, 0x36, 0x36, 0x21, 0x28, 0x2c, 0x30, + 0x21, 0x38, 0x33, 0x28, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x21, 0x22, 0x22, 0x28, 0x30, + 0x2d, 0xa2, 0x7a, 0xa3, 0xa4, 0xa4, 0x7f, 0x22, + 0x51, 0x52, 0x48, 0x9b, 0x3b, 0x3a, 0x2f, 0x54, + 0x3f, 0x4b, 0x3b, 0x34, 0x3e, 0x55, 0x34, 0x4d, + 0x34, 0x3b, 0x3b, 0x55, 0x42, 0x4b, 0x9e, 0x31, + 0x2b, 0x3a, 0x9e, 0x47, 0xa5, 0xa5, 0xa6, 0x61, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x30, 0x32, + 0x25, 0x4d, 0x2b, 0x28, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x21, 0x23, 0x24, 0x26, 0x30, 0x33, 0x31, + 0x4d, 0x91, 0x5b, 0xa3, 0xa4, 0xa4, 0xa4, 0x5a, + 0x21, 0x2e, 0x46, 0x48, 0x9a, 0x3b, 0x42, 0x47, + 0x42, 0x9d, 0x37, 0x39, 0x4a, 0x3e, 0x3a, 0x52, + 0x38, 0x3e, 0x3e, 0x2b, 0x25, 0x37, 0x4f, 0x4f, + 0x55, 0x55, 0x45, 0xa7, 0xa8, 0x69, 0x66, 0xa9, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x26, 0x25, + 0x83, 0xaa, 0x2c, 0x25, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x28, 0x30, 0x35, 0x2d, 0x2f, 0x37, 0x4a, + 0x60, 0x85, 0xab, 0xac, 0xa4, 0xa4, 0xa4, 0x82, + 0x86, 0x36, 0x32, 0x3f, 0x48, 0x47, 0x4b, 0x4a, + 0x9d, 0x55, 0x2f, 0x51, 0x3a, 0x3b, 0x55, 0x9b, + 0x4d, 0x3b, 0x55, 0x39, 0x24, 0x28, 0x32, 0x9e, + 0x47, 0x47, 0x48, 0xad, 0xa3, 0xa8, 0xae, 0xaf, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x57, + 0x77, 0x66, 0x34, 0x27, 0x22, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x23, 0x30, 0x31, 0xb0, 0x91, 0x7e, 0x90, 0x90, + 0x8b, 0x5b, 0xa3, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0x5d, 0xb1, 0x36, 0x24, 0x53, 0x47, 0x37, 0x30, + 0x32, 0x2e, 0x98, 0x3f, 0x3a, 0x3e, 0x4a, 0x47, + 0x9d, 0x3e, 0x54, 0x40, 0x55, 0x30, 0x30, 0x4a, + 0x6b, 0x9b, 0x99, 0xad, 0x64, 0x5c, 0x8b, 0xb1, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x73, 0x5d, + 0x82, 0x5c, 0xb2, 0x2a, 0x23, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x24, 0x2b, 0xb0, 0x8b, 0x5b, 0x76, 0x5b, 0x5b, + 0x7b, 0xa3, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa8, 0x5e, 0x22, 0x36, 0x21, 0x3a, 0x3d, 0x30, + 0x22, 0x28, 0x3a, 0x44, 0x4a, 0x3e, 0x3e, 0x9b, + 0x9d, 0x3e, 0x9e, 0x4b, 0x55, 0x2e, 0x42, 0x9f, + 0x93, 0x4f, 0x3f, 0xb3, 0x7b, 0x7b, 0x85, 0x80, + 0xa0, 0x36, 0x36, 0x36, 0x21, 0xb4, 0x7e, 0x7b, + 0x64, 0x64, 0xb5, 0x35, 0x24, 0x21, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x26, 0x31, 0xb6, 0x5b, 0x64, 0xa3, 0xa3, 0xac, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0x66, 0xb7, 0x36, 0x36, 0x36, 0x2c, 0x54, + 0x31, 0x23, 0x26, 0x2c, 0x3a, 0x3b, 0x55, 0x47, + 0x37, 0x3b, 0x3b, 0x38, 0x4a, 0x98, 0x55, 0x98, + 0x47, 0x9a, 0x3f, 0xb8, 0x76, 0x76, 0x7a, 0x63, + 0xb9, 0xba, 0x86, 0xba, 0xbb, 0x90, 0x5b, 0x64, + 0xa3, 0xa3, 0xbc, 0x2d, 0x27, 0x23, 0x21, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x26, 0x2d, 0x91, 0x5b, 0x64, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa8, 0x83, 0xaf, 0x36, 0x36, 0x36, 0x30, + 0x98, 0x37, 0x30, 0x26, 0x9d, 0x3e, 0x9f, 0x9b, + 0x37, 0x3b, 0x3b, 0x53, 0x53, 0x3d, 0x4b, 0x48, + 0x9b, 0x9a, 0x3f, 0xbd, 0x5b, 0x7b, 0xbe, 0x85, + 0x7e, 0x90, 0x63, 0x90, 0x85, 0x5b, 0xa3, 0xa4, + 0xa4, 0xac, 0x5d, 0xb5, 0x39, 0x26, 0x23, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x26, 0x2d, 0xbf, 0xbe, 0x64, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa8, 0x88, 0x36, 0x36, 0x36, 0x36, + 0x2d, 0x3f, 0x3b, 0x31, 0x4d, 0x3e, 0x9f, 0x47, + 0x38, 0x3b, 0x3e, 0x3e, 0x98, 0x52, 0x48, 0x48, + 0x9b, 0x45, 0x3f, 0xc0, 0x6d, 0x7b, 0xab, 0xbe, + 0x7a, 0x8b, 0x8b, 0x7a, 0x5b, 0x64, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa3, 0xc1, 0x37, 0x35, 0x26, 0x23, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x26, 0x2e, 0xbf, 0x7a, 0x7b, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa8, 0x72, 0x73, 0x36, 0x36, 0x36, + 0x24, 0x52, 0x47, 0x49, 0x3a, 0x55, 0x98, 0x47, + 0x9d, 0x3e, 0x54, 0x45, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x46, 0x42, 0xb6, 0x7a, 0x7b, 0x64, 0x7b, + 0x76, 0x5b, 0x5b, 0x76, 0x7b, 0xa3, 0xa4, 0xa4, + 0xa4, 0xa4, 0xac, 0x64, 0xc1, 0x4d, 0x2c, 0x27, + 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x25, 0x31, 0xc2, 0x8b, 0x7b, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa8, 0x89, 0xa0, 0x36, 0x36, + 0x32, 0x47, 0x48, 0x9b, 0x9a, 0x3f, 0x47, 0x48, + 0x4b, 0x40, 0x4f, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x4b, 0x2f, 0x8f, 0x7a, 0x7b, 0xa3, 0xac, + 0xa3, 0x64, 0x64, 0xa3, 0xa3, 0xac, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa3, 0x5d, 0xc3, 0x2c, + 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x25, 0x31, 0xc2, 0x85, 0x7b, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0x66, 0x57, 0x27, 0x4d, + 0x4b, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x99, 0x34, 0xa0, 0xb9, 0x7a, 0x7b, 0xa3, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa3, 0xc2, + 0x32, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x26, 0x2d, 0xc2, 0x85, 0x7b, 0xac, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa8, 0x5f, 0x92, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x44, + 0x35, 0x36, 0xaf, 0xbb, 0x7a, 0x7b, 0xac, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xac, 0xa3, 0xc0, + 0x2b, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23, + 0x30, 0x2f, 0xb6, 0x8b, 0x7b, 0xac, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0x66, 0x89, 0x45, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x9b, 0x4e, 0x25, + 0x36, 0x36, 0x61, 0xb9, 0x6d, 0x64, 0xac, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xac, 0x7b, 0xbe, 0xc3, + 0x32, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28, + 0x33, 0xc4, 0x63, 0xbe, 0xa3, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa3, 0x72, 0x81, 0xc5, + 0x46, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x3f, 0x2c, 0x36, 0x36, + 0x36, 0x36, 0xc6, 0x8f, 0x6d, 0x64, 0xac, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa3, 0xab, 0x8b, 0xb0, 0x2c, + 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, + 0x35, 0x96, 0x75, 0xab, 0xa3, 0xac, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xac, 0x7b, 0x81, 0xb9, + 0x73, 0x3b, 0x44, 0x9b, 0x48, 0x48, 0x48, 0x9b, + 0x99, 0x43, 0x94, 0x2c, 0x21, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x73, 0xb9, 0x7a, 0x7b, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0x64, 0x76, 0x7a, 0x91, 0xb5, 0x31, 0x30, + 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, + 0x39, 0x97, 0x75, 0xbe, 0x7b, 0x64, 0xa3, 0xa3, + 0xac, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0x7b, 0x7a, 0xc7, + 0xc8, 0x36, 0x21, 0x26, 0x2b, 0x39, 0x33, 0x30, + 0x23, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x21, 0xc8, 0xbb, 0x8b, 0x7b, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa3, 0x64, 0x64, + 0x76, 0x85, 0xbf, 0xb5, 0x34, 0x2b, 0x27, 0x28, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28, + 0x33, 0xc9, 0x63, 0x7e, 0x7a, 0x6d, 0xbe, 0x5b, + 0x76, 0x7b, 0x64, 0x64, 0xa3, 0xac, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xac, 0x76, 0x85, 0xb9, + 0x79, 0x22, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x21, 0xca, 0xbb, 0x75, 0x76, 0xa3, 0xa4, + 0xa4, 0xa4, 0xac, 0xa3, 0x64, 0x76, 0xbe, 0x8b, + 0xb6, 0xb5, 0x2f, 0x35, 0x30, 0x24, 0x22, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23, + 0x27, 0x31, 0xcb, 0xc9, 0xbb, 0x74, 0x63, 0x90, + 0x7e, 0x75, 0x8b, 0x6d, 0xbe, 0x76, 0x64, 0xa3, + 0xac, 0xac, 0xac, 0xac, 0x64, 0x7a, 0x84, 0xcc, + 0x79, 0xa0, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x21, 0xc8, 0xcc, 0x63, 0x6d, 0x7b, 0x64, + 0xac, 0xa3, 0x64, 0x7b, 0xbe, 0x75, 0x63, 0x96, + 0x38, 0x39, 0x2a, 0x24, 0x23, 0x21, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x28, 0x27, 0x35, 0x2d, 0x41, 0xb5, 0xc5, 0x8f, + 0xb9, 0xbb, 0xc7, 0x74, 0x84, 0x90, 0x85, 0x6d, + 0x5b, 0x7b, 0x7b, 0xab, 0x6d, 0x90, 0xb9, 0xcd, + 0xca, 0x22, 0x36, 0x36, 0x28, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x25, 0x36, + 0x36, 0x21, 0xb4, 0x80, 0xc7, 0x7e, 0x6d, 0x76, + 0xab, 0x76, 0x6d, 0x85, 0x63, 0xb9, 0xb5, 0x34, + 0x33, 0x26, 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x23, 0x24, 0x27, 0x2a, 0x35, 0x2e, 0x2f, + 0x41, 0xce, 0xcf, 0x6c, 0x80, 0xcc, 0xb9, 0x74, + 0x84, 0x90, 0x75, 0x7e, 0x74, 0x8f, 0xcd, 0x79, + 0xc6, 0x2b, 0x9d, 0x41, 0x2f, 0x34, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x34, 0x2f, 0x38, + 0x4d, 0x37, 0xd0, 0xd1, 0x8f, 0x74, 0x63, 0x7e, + 0x75, 0x7e, 0x63, 0xc7, 0x88, 0xc4, 0x31, 0x2a, + 0x24, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x21, 0x22, 0x23, 0x24, 0x26, 0x30, + 0x33, 0x39, 0x2e, 0x51, 0x41, 0xb2, 0x6c, 0xd1, + 0x80, 0xcc, 0xcc, 0xcc, 0xd2, 0xd1, 0xb7, 0xd3, + 0x41, 0x34, 0x35, 0x32, 0x30, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x30, 0x2a, + 0x2b, 0x34, 0xd4, 0xca, 0xd5, 0x8f, 0xbb, 0xc7, + 0xc7, 0xbb, 0xcc, 0x6c, 0x41, 0x39, 0x27, 0x28, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22, + 0x28, 0x24, 0x26, 0x2a, 0x33, 0x2c, 0x2f, 0x41, + 0xd6, 0xb7, 0x79, 0x79, 0x79, 0xca, 0xd7, 0x51, + 0x39, 0x30, 0x24, 0x23, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x22, 0x23, + 0x24, 0x2a, 0x31, 0xd8, 0xc8, 0x79, 0xd1, 0x80, + 0xd5, 0xba, 0xd9, 0x2f, 0x35, 0x26, 0x23, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x21, 0x22, 0x23, 0x28, 0x25, 0x30, 0x2b, + 0x31, 0x2f, 0xd4, 0xd8, 0xd8, 0x2f, 0x2e, 0x33, + 0x26, 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x28, 0x27, 0x35, 0x34, 0xd8, 0xd8, 0xd8, + 0xda, 0xd4, 0x2e, 0x33, 0x25, 0x23, 0x21, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x23, 0x28, + 0x26, 0x30, 0x32, 0x2b, 0x33, 0x2a, 0x26, 0x28, + 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x21, 0x23, 0x25, 0x30, 0x33, 0x35, 0x35, + 0x2b, 0x2a, 0x26, 0x28, 0x22, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x21, 0x22, 0x23, 0x28, 0x28, 0x23, 0x22, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x21, 0x23, 0x28, 0x24, 0x24, + 0x28, 0x23, 0x22, 0x21, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, }; -#define INCLUDE_LINUX_LOGOBW -#define INCLUDE_LINUX_LOGO16 -#include - -#else +#endif /* INCLUDE_LINUX_LOGO_DATA */ -/* prototypes only */ -extern unsigned char linux_logo_red[]; -extern unsigned char linux_logo_green[]; -extern unsigned char linux_logo_blue[]; -extern unsigned char linux_logo[]; -extern unsigned char linux_logo_bw[]; -extern unsigned char linux_logo16_red[]; -extern unsigned char linux_logo16_green[]; -extern unsigned char linux_logo16_blue[]; -extern unsigned char linux_logo16[]; +#include -#endif diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/mc146818rtc.h linux/include/asm-mips/mc146818rtc.h --- v2.4.5/linux/include/asm-mips/mc146818rtc.h Fri Aug 4 18:31:19 2000 +++ linux/include/asm-mips/mc146818rtc.h Mon Jul 2 13:56:40 2001 @@ -14,8 +14,12 @@ #include #ifndef RTC_PORT +#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) +#define RTC_PORT(x) (0x14014800 + (x)) +#else #define RTC_PORT(x) (0x70 + (x)) #endif +#endif /* * The yet supported machines all access the RTC index register via @@ -45,8 +49,13 @@ #ifdef CONFIG_DECSTATION #define RTC_IRQ 0 +#elif defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) +#include +#define RTC_IRQ IT8172_RTC_IRQ #else #define RTC_IRQ 8 #endif + +#define RTC_DEC_YEAR 0x3f /* Where we store the real year on DECs. */ #endif /* _ASM_MC146818RTC_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/mips32_cache.h linux/include/asm-mips/mips32_cache.h --- v2.4.5/linux/include/asm-mips/mips32_cache.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/mips32_cache.h Mon Jul 2 13:56:40 2001 @@ -0,0 +1,288 @@ +/* + * mips32_cache.h + * + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * + * ######################################################################## + * + * This program is free software; you can distribute 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 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. + * + * ######################################################################## + * + * Inline assembly cache operations. + * + * This file is the original r4cache.c file with modification that makes the + * cache handling more generic. + * + * FIXME: Handle split L2 caches. + * + */ +#ifndef _MIPS_R4KCACHE_H +#define _MIPS_R4KCACHE_H + +#include +#include + +extern inline void flush_icache_line_indexed(unsigned long addr) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "cache %1, (%0)\n\t" + ".set mips0\n\t" + ".set reorder" + : + : "r" (addr), + "i" (Index_Invalidate_I)); +} + +extern inline void flush_dcache_line_indexed(unsigned long addr) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "cache %1, (%0)\n\t" + ".set mips0\n\t" + ".set reorder" + : + : "r" (addr), + "i" (Index_Writeback_Inv_D)); +} + +extern inline void flush_scache_line_indexed(unsigned long addr) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "cache %1, (%0)\n\t" + ".set mips0\n\t" + ".set reorder" + : + : "r" (addr), + "i" (Index_Writeback_Inv_SD)); +} + +extern inline void flush_icache_line(unsigned long addr) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "cache %1, (%0)\n\t" + ".set mips0\n\t" + ".set reorder" + : + : "r" (addr), + "i" (Hit_Invalidate_I)); +} + +extern inline void flush_dcache_line(unsigned long addr) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "cache %1, (%0)\n\t" + ".set mips0\n\t" + ".set reorder" + : + : "r" (addr), + "i" (Hit_Writeback_Inv_D)); +} + +extern inline void invalidate_dcache_line(unsigned long addr) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "cache %1, (%0)\n\t" + ".set mips0\n\t" + ".set reorder" + : + : "r" (addr), + "i" (Hit_Invalidate_D)); +} + +extern inline void invalidate_scache_line(unsigned long addr) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "cache %1, (%0)\n\t" + ".set mips0\n\t" + ".set reorder" + : + : "r" (addr), + "i" (Hit_Invalidate_SD)); +} + +extern inline void flush_scache_line(unsigned long addr) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "cache %1, (%0)\n\t" + ".set mips0\n\t" + ".set reorder" + : + : "r" (addr), + "i" (Hit_Writeback_Inv_SD)); +} + +/* + * The next two are for badland addresses like signal trampolines. + */ +extern inline void protected_flush_icache_line(unsigned long addr) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n" + "1:\tcache %1,(%0)\n" + "2:\t.set mips0\n\t" + ".set reorder\n\t" + ".section\t__ex_table,\"a\"\n\t" + STR(PTR)"\t1b,2b\n\t" + ".previous" + : + : "r" (addr), + "i" (Hit_Invalidate_I)); +} + +extern inline void protected_writeback_dcache_line(unsigned long addr) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n" + "1:\tcache %1,(%0)\n" + "2:\t.set mips0\n\t" + ".set reorder\n\t" + ".section\t__ex_table,\"a\"\n\t" + STR(PTR)"\t1b,2b\n\t" + ".previous" + : + : "r" (addr), + "i" (Hit_Writeback_D)); +} + +#define cache_unroll(base,op) \ + __asm__ __volatile__(" \ + .set noreorder; \ + .set mips3; \ + cache %1, (%0); \ + .set mips0; \ + .set reorder" \ + : \ + : "r" (base), \ + "i" (op)); + + +extern inline void blast_dcache(void) +{ + unsigned long start = KSEG0; + unsigned long end = (start + dcache_size); + + while(start < end) { + cache_unroll(start,Index_Writeback_Inv_D); + start += dc_lsize; + } +} + +extern inline void blast_dcache_page(unsigned long page) +{ + unsigned long start = page; + unsigned long end = (start + PAGE_SIZE); + + while(start < end) { + cache_unroll(start,Hit_Writeback_Inv_D); + start += dc_lsize; + } +} + +extern inline void blast_dcache_page_indexed(unsigned long page) +{ + unsigned long start = page; + unsigned long end = (start + PAGE_SIZE); + + while(start < end) { + cache_unroll(start,Index_Writeback_Inv_D); + start += dc_lsize; + } +} + +extern inline void blast_icache(void) +{ + unsigned long start = KSEG0; + unsigned long end = (start + icache_size); + + while(start < end) { + cache_unroll(start,Index_Invalidate_I); + start += ic_lsize; + } +} + +extern inline void blast_icache_page(unsigned long page) +{ + unsigned long start = page; + unsigned long end = (start + PAGE_SIZE); + + while(start < end) { + cache_unroll(start,Hit_Invalidate_I); + start += ic_lsize; + } +} + +extern inline void blast_icache_page_indexed(unsigned long page) +{ + unsigned long start = page; + unsigned long end = (start + PAGE_SIZE); + + while(start < end) { + cache_unroll(start,Index_Invalidate_I); + start += ic_lsize; + } +} + +extern inline void blast_scache(void) +{ + unsigned long start = KSEG0; + unsigned long end = KSEG0 + scache_size; + + while(start < end) { + cache_unroll(start,Index_Writeback_Inv_SD); + start += sc_lsize; + } +} + +extern inline void blast_scache_page(unsigned long page) +{ + unsigned long start = page; + unsigned long end = page + PAGE_SIZE; + + while(start < end) { + cache_unroll(start,Hit_Writeback_Inv_SD); + start += sc_lsize; + } +} + +extern inline void blast_scache_page_indexed(unsigned long page) +{ + unsigned long start = page; + unsigned long end = page + PAGE_SIZE; + + while(start < end) { + cache_unroll(start,Index_Writeback_Inv_SD); + start += sc_lsize; + } +} + +#endif /* !(_MIPS_R4KCACHE_H) */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/mipsregs.h linux/include/asm-mips/mipsregs.h --- v2.4.5/linux/include/asm-mips/mipsregs.h Fri Apr 13 20:26:07 2001 +++ linux/include/asm-mips/mipsregs.h Mon Jul 2 13:56:40 2001 @@ -1,14 +1,16 @@ -/* $Id: mipsregs.h,v 1.6 1999/07/26 19:42:43 harald Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1994, 1995, 1996, 1997 by Ralf Baechle + * Copyright (C) 1994, 1995, 1996, 1997, 2000, 2001 by Ralf Baechle + * Copyright (C) 2000 Silicon Graphics, Inc. * Modified for further R[236]000 support by Paul M. Antoine, 1996. + * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. */ -#ifndef __ASM_MIPS_MIPSREGS_H -#define __ASM_MIPS_MIPSREGS_H +#ifndef _ASM_MIPSREGS_H +#define _ASM_MIPSREGS_H #include @@ -70,6 +72,12 @@ #define CP0_IWATCH $18 #define CP0_DWATCH $19 +/* + * Coprocessor 0 Set 1 register names + */ +#define CP0_S1_DERRADDR0 $26 +#define CP0_S1_DERRADDR1 $27 +#define CP0_S1_INTCONTROL $20 /* * Coprocessor 1 (FPU) register names */ @@ -77,6 +85,58 @@ #define CP1_STATUS $31 /* + * FPU Status Register Values + */ +/* + * Status Register Values + */ + +#define FPU_CSR_FLUSH 0x01000000 /* flush denormalised results to 0 */ +#define FPU_CSR_COND 0x00800000 /* $fcc0 */ +#define FPU_CSR_COND0 0x00800000 /* $fcc0 */ +#define FPU_CSR_COND1 0x02000000 /* $fcc1 */ +#define FPU_CSR_COND2 0x04000000 /* $fcc2 */ +#define FPU_CSR_COND3 0x08000000 /* $fcc3 */ +#define FPU_CSR_COND4 0x10000000 /* $fcc4 */ +#define FPU_CSR_COND5 0x20000000 /* $fcc5 */ +#define FPU_CSR_COND6 0x40000000 /* $fcc6 */ +#define FPU_CSR_COND7 0x80000000 /* $fcc7 */ + +/* + * X the exception cause indicator + * E the exception enable + * S the sticky/flag bit +*/ +#define FPU_CSR_ALL_X 0x0003f000 +#define FPU_CSR_UNI_X 0x00020000 +#define FPU_CSR_INV_X 0x00010000 +#define FPU_CSR_DIV_X 0x00008000 +#define FPU_CSR_OVF_X 0x00004000 +#define FPU_CSR_UDF_X 0x00002000 +#define FPU_CSR_INE_X 0x00001000 + +#define FPU_CSR_ALL_E 0x00000f80 +#define FPU_CSR_INV_E 0x00000800 +#define FPU_CSR_DIV_E 0x00000400 +#define FPU_CSR_OVF_E 0x00000200 +#define FPU_CSR_UDF_E 0x00000100 +#define FPU_CSR_INE_E 0x00000080 + +#define FPU_CSR_ALL_S 0x0000007c +#define FPU_CSR_INV_S 0x00000040 +#define FPU_CSR_DIV_S 0x00000020 +#define FPU_CSR_OVF_S 0x00000010 +#define FPU_CSR_UDF_S 0x00000008 +#define FPU_CSR_INE_S 0x00000004 + +/* rounding mode */ +#define FPU_CSR_RN 0x0 /* nearest */ +#define FPU_CSR_RZ 0x1 /* towards zero */ +#define FPU_CSR_RU 0x2 /* towards +Infinity */ +#define FPU_CSR_RD 0x3 /* towards -Infinity */ + + +/* * Values for PageMask register */ #define PM_4K 0x00000000 @@ -111,6 +171,16 @@ : "=r" (__res)); \ __res;}) +#define read_32bit_cp0_set1_register(source) \ +({ int __res; \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\treorder\n\t" \ + "cfc0\t%0,"STR(source)"\n\t" \ + ".set\tpop" \ + : "=r" (__res)); \ + __res;}) + /* * For now use this only with interrupts disabled! */ @@ -129,12 +199,36 @@ "nop" \ : : "r" (value)); +#define write_32bit_cp0_set1_register(register,value) \ + __asm__ __volatile__( \ + "ctc0\t%0,"STR(register)"\n\t" \ + "nop" \ + : : "r" (value)); + #define write_64bit_cp0_register(register,value) \ __asm__ __volatile__( \ ".set\tmips3\n\t" \ "dmtc0\t%0,"STR(register)"\n\t" \ ".set\tmips0" \ : : "r" (value)) + +#ifdef CONFIG_CPU_MIPS32 +/* + * This should be changed when we get a compiler that support the MIPS32 ISA. + */ +#define read_mips32_cp0_config1() \ +({ int __res; \ + __asm__ __volatile__( \ + ".set\tnoreorder\n\t" \ + ".set\tnoat\n\t" \ + ".word\t0x40018001\n\t" \ + "move\t%0,$1\n\t" \ + ".set\tat\n\t" \ + ".set\treorder" \ + :"=r" (__res)); \ + __res;}) +#endif + /* * R4x00 interrupt enable / cause bits */ @@ -166,7 +260,31 @@ */ #define __BUILD_SET_CP0(name,register) \ extern __inline__ unsigned int \ -set_cp0_##name(unsigned int change, unsigned int new) \ +set_cp0_##name(unsigned int set) \ +{ \ + unsigned int res; \ + \ + res = read_32bit_cp0_register(register); \ + res |= set; \ + write_32bit_cp0_register(register, res); \ + \ + return res; \ +} \ + \ +extern __inline__ unsigned int \ +clear_cp0_##name(unsigned int clear) \ +{ \ + unsigned int res; \ + \ + res = read_32bit_cp0_register(register); \ + res &= ~clear; \ + write_32bit_cp0_register(register, res); \ + \ + return res; \ +} \ + \ +extern __inline__ unsigned int \ +change_cp0_##name(unsigned int change, unsigned int new) \ { \ unsigned int res; \ \ @@ -186,42 +304,6 @@ #endif /* defined (_LANGUAGE_ASSEMBLY) */ /* - * Inline code for use of the ll and sc instructions - * - * FIXME: This instruction is only available on MIPS ISA >=2. - * Since these operations are only being used for atomic operations - * the easiest workaround for the R[23]00 is to disable interrupts. - * This fails for R3000 SMP machines which use that many different - * technologies as replacement that it is difficult to create even - * just a hook for for all machines to hook into. The only good - * thing is that there is currently no R3000 SMP machine on the - * Linux/MIPS target list ... - */ -#define load_linked(addr) \ -({ \ - unsigned int __res; \ - \ - __asm__ __volatile__( \ - "ll\t%0,(%1)" \ - : "=r" (__res) \ - : "r" ((unsigned long) (addr))); \ - \ - __res; \ -}) - -#define store_conditional(addr,value) \ -({ \ - int __res; \ - \ - __asm__ __volatile__( \ - "sc\t%0,(%2)" \ - : "=r" (__res) \ - : "0" (value), "r" (addr)); \ - \ - __res; \ -}) - -/* * Bitfields in the R4xx0 cp0 status register */ #define ST0_IE 0x00000001 @@ -253,11 +335,44 @@ /* * Bits specific to the R4640/R4650 */ -#define ST0_UM <1 << 4) +#define ST0_UM (1 << 4) #define ST0_IL (1 << 23) #define ST0_DL (1 << 24) /* + * Bitfields in the TX39 family CP0 Configuration Register 3 + */ +#define TX39_CONF_ICS_SHIFT 19 +#define TX39_CONF_ICS_MASK 0x00380000 +#define TX39_CONF_ICS_1KB 0x00000000 +#define TX39_CONF_ICS_2KB 0x00080000 +#define TX39_CONF_ICS_4KB 0x00100000 +#define TX39_CONF_ICS_8KB 0x00180000 +#define TX39_CONF_ICS_16KB 0x00200000 + +#define TX39_CONF_DCS_SHIFT 16 +#define TX39_CONF_DCS_MASK 0x00070000 +#define TX39_CONF_DCS_1KB 0x00000000 +#define TX39_CONF_DCS_2KB 0x00010000 +#define TX39_CONF_DCS_4KB 0x00020000 +#define TX39_CONF_DCS_8KB 0x00030000 +#define TX39_CONF_DCS_16KB 0x00040000 + +#define TX39_CONF_CWFON 0x00004000 +#define TX39_CONF_WBON 0x00002000 +#define TX39_CONF_RF_SHIFT 10 +#define TX39_CONF_RF_MASK 0x00000c00 +#define TX39_CONF_DOZE 0x00000200 +#define TX39_CONF_HALT 0x00000100 +#define TX39_CONF_LOCK 0x00000080 +#define TX39_CONF_ICE 0x00000020 +#define TX39_CONF_DCE 0x00000010 +#define TX39_CONF_IRSIZE_SHIFT 2 +#define TX39_CONF_IRSIZE_MASK 0x0000000c +#define TX39_CONF_DRSIZE_SHIFT 0 +#define TX39_CONF_DRSIZE_MASK 0x00000003 + +/* * Status register bits available in all MIPS CPUs. */ #define ST0_IM 0x0000ff00 @@ -277,6 +392,22 @@ #define STATUSF_IP6 (1 << 14) #define STATUSB_IP7 15 #define STATUSF_IP7 (1 << 15) +#define STATUSB_IP8 0 +#define STATUSF_IP8 (1 << 0) +#define STATUSB_IP9 1 +#define STATUSF_IP9 (1 << 1) +#define STATUSB_IP10 2 +#define STATUSF_IP10 (1 << 2) +#define STATUSB_IP11 3 +#define STATUSF_IP11 (1 << 3) +#define STATUSB_IP12 4 +#define STATUSF_IP12 (1 << 4) +#define STATUSB_IP13 5 +#define STATUSF_IP13 (1 << 5) +#define STATUSB_IP14 6 +#define STATUSF_IP14 (1 << 6) +#define STATUSB_IP15 7 +#define STATUSF_IP15 (1 << 7) #define ST0_CH 0x00040000 #define ST0_SR 0x00100000 #define ST0_BEV 0x00400000 @@ -405,4 +536,4 @@ extern asmlinkage void write_perf_cntl(unsigned int counter, unsigned int val); #endif -#endif /* __ASM_MIPS_MIPSREGS_H */ +#endif /* _ASM_MIPSREGS_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/mmu_context.h linux/include/asm-mips/mmu_context.h --- v2.4.5/linux/include/asm-mips/mmu_context.h Thu Aug 10 13:30:05 2000 +++ linux/include/asm-mips/mmu_context.h Mon Jul 2 13:56:40 2001 @@ -1,5 +1,4 @@ -/* $Id: mmu_context.h,v 1.7 2000/02/04 07:40:53 ralf Exp $ - * +/* * Switch a MMU context. * * This file is subject to the terms and conditions of the GNU General Public @@ -13,11 +12,12 @@ #define _ASM_MMU_CONTEXT_H #include +#include #include /* Fuck. The f-word is here so you can grep for it :-) */ extern unsigned long asid_cache; -extern pgd_t *current_pgd; +extern pgd_t *current_pgd[]; #if defined(CONFIG_CPU_R3000) @@ -60,7 +60,19 @@ extern inline int init_new_context(struct task_struct *tsk, struct mm_struct *mm) { +#ifndef CONFIG_SMP mm->context = 0; +#else + mm->context = (unsigned long)kmalloc(smp_num_cpus * + sizeof(unsigned long), GFP_KERNEL); + /* + * Init the "context" values so that a tlbpid allocation + * happens on the first switch. + */ + if (mm->context == 0) + return -ENOMEM; + memset((void *)mm->context, 0, smp_num_cpus * sizeof(unsigned long)); +#endif return 0; } @@ -73,7 +85,7 @@ if ((next->context ^ asid) & ASID_VERSION_MASK) get_new_mmu_context(next, asid); - current_pgd = next->pgd; + current_pgd[cpu] = next->pgd; set_entryhi(next->context); } @@ -96,7 +108,7 @@ /* Unconditionally get a new ASID. */ get_new_mmu_context(next, asid_cache); - current_pgd = next->pgd; + current_pgd[smp_processor_id()] = next->pgd; set_entryhi(next->context); } diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/orion.h linux/include/asm-mips/orion.h --- v2.4.5/linux/include/asm-mips/orion.h Tue Jul 11 11:15:02 2000 +++ linux/include/asm-mips/orion.h Wed Dec 31 16:00:00 1969 @@ -1,14 +0,0 @@ -/* - * Orion/Galileo specific header file. - * -- Cort - */ -#ifndef __LINUX_MIPS_ORION_H -#define __LINUX_MIPS_ORION_H - -/* base address for the GT-64120 internal registers */ -#define GT64120_BASE (0x14000000) -/* GT64120 and PCI_0 interrupt cause register */ -#define GT64120_CAUSE_LOW *(unsigned long *)(GT64120_BASE + 0xc18) -#define GT64120_CAUSE_HIGH *(unsigned long *)(GT64120_BASE + 0xc1c) - -#endif /* __LINUX_MIPS_ORION_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/param.h linux/include/asm-mips/param.h --- v2.4.5/linux/include/asm-mips/param.h Wed Jul 12 15:15:10 2000 +++ linux/include/asm-mips/param.h Mon Jul 2 13:56:40 2001 @@ -64,4 +64,8 @@ #define MAXHOSTNAMELEN 64 /* max length of hostname */ +#ifdef __KERNEL__ +# define CLOCKS_PER_SEC 100 /* frequency at which times() counts */ +#endif + #endif /* _ASM_PARAM_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/pci.h linux/include/asm-mips/pci.h --- v2.4.5/linux/include/asm-mips/pci.h Wed May 16 10:31:27 2001 +++ linux/include/asm-mips/pci.h Mon Jul 2 13:56:40 2001 @@ -1,5 +1,4 @@ -/* $Id: pci.h,v 1.10 2000/03/23 02:26:00 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -13,7 +12,8 @@ already-configured bus numbers - to be used for buggy BIOSes or architectures with incomplete PCI setup by the loader */ -#define pcibios_assign_all_busses() 0 +//#define pcibios_assign_all_busses() 0 +#define pcibios_assign_all_busses() 1 #define PCIBIOS_MIN_IO 0x1000 #define PCIBIOS_MIN_MEM 0x10000000 @@ -201,8 +201,27 @@ #endif } -/* Return the index of the PCI controller for device PDEV. */ -#define pci_controller_num(PDEV) (0) +/* Return whether the given PCI device DMA address mask can + * be supported properly. For example, if your device can + * only drive the low 24-bits during PCI bus mastering, then + * you would pass 0x00ffffff as the mask to this function. + */ +extern inline int pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask) +{ + /* + * we fall back to GFP_DMA when the mask isn't all 1s, + * so we can't guarantee allocations that must be + * within a tighter range than GFP_DMA.. + */ + if (mask < 0x00ffffff) + return 0; + + return 1; +} + + +/* Return the index of the PCI controller for device. */ +#define pci_controller_num(pdev) (0) /* * These macros should be used after a pci_map_sg call has been done diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/pgalloc.h linux/include/asm-mips/pgalloc.h --- v2.4.5/linux/include/asm-mips/pgalloc.h Mon Apr 23 15:28:07 2001 +++ linux/include/asm-mips/pgalloc.h Mon Jul 2 13:56:40 2001 @@ -1,16 +1,16 @@ -/* $Id: pgalloc.h,v 1.3 2000/02/23 00:41:38 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1994 - 2000 by Ralf Baechle at alii + * Copyright (C) 1994 - 2001 by Ralf Baechle * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ #ifndef _ASM_PGALLOC_H #define _ASM_PGALLOC_H #include +#include /* TLB flushing: * @@ -33,9 +33,7 @@ /* - * Allocate and free page tables. The xxx_kernel() versions are - * used to allocate a kernel page table - this turns on ASN bits - * if any. + * Allocate and free page tables. */ #define pgd_quicklist (current_cpu_data.pgd_quick) @@ -43,6 +41,13 @@ #define pte_quicklist (current_cpu_data.pte_quick) #define pgtable_cache_size (current_cpu_data.pgtable_cache_sz) +#define pmd_populate(mm, pmd, pte) pmd_set(pmd, pte) + +/* + * Initialize new page directory with pointers to invalid ptes + */ +extern void pgd_init(unsigned long page); + extern __inline__ pgd_t *get_pgd_slow(void) { pgd_t *ret = (pgd_t *)__get_free_page(GFP_KERNEL), *init; @@ -82,7 +87,6 @@ } extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted); -extern pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long address_preadjusted); extern __inline__ pte_t *get_pte_fast(void) { @@ -123,94 +127,54 @@ } extern void __bad_pte(pmd_t *pmd); -extern void __bad_pte_kernel(pmd_t *pmd); - -#define pte_free_kernel(pte) free_pte_fast(pte) -#define pte_free(pte) free_pte_fast(pte) -#define pgd_free(pgd) free_pgd_fast(pgd) -#define pgd_alloc(mm) get_pgd_fast() -extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address) +static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address) { - address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); + pte_t *pte; - if (pmd_none(*pmd)) { - pte_t *page = get_pte_fast(); - if (page) { - pmd_val(*pmd) = (unsigned long)page; - return page + address; - } - return get_pte_kernel_slow(pmd, address); - } - if (pmd_bad(*pmd)) { - __bad_pte_kernel(pmd); - return NULL; - } - return (pte_t *) pmd_page(*pmd) + address; + pte = (pte_t *) __get_free_page(GFP_KERNEL); + if (pte) + clear_page(pte); + return pte; } -extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address) +static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm, unsigned long address) { - address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); + unsigned long *ret; - if (pmd_none(*pmd)) { - pte_t *page = get_pte_fast(); - if (page) { - pmd_val(*pmd) = (unsigned long)page; - return page + address; - } - return get_pte_slow(pmd, address); - } - if (pmd_bad(*pmd)) { - __bad_pte(pmd); - return NULL; + if ((ret = (unsigned long *)pte_quicklist) != NULL) { + pte_quicklist = (unsigned long *)(*ret); + ret[0] = ret[1]; + pgtable_cache_size--; } - return (pte_t *) pmd_page(*pmd) + address; + return (pte_t *)ret; } -/* - * allocating and freeing a pmd is trivial: the 1-entry pmd is - * inside the pgd, so has no extra memory associated with it. - */ -extern inline void pmd_free(pmd_t * pmd) +extern __inline__ void pte_free_fast(pte_t *pte) { + *(unsigned long *)pte = (unsigned long) pte_quicklist; + pte_quicklist = (unsigned long *) pte; + pgtable_cache_size++; } -extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address) +extern __inline__ void pte_free_slow(pte_t *pte) { - return (pmd_t *) pgd; + free_page((unsigned long)pte); } -#define pmd_free_kernel pmd_free -#define pmd_alloc_kernel pmd_alloc +#define pte_free(pte) pte_free_slow(pte) +#define pgd_free(pgd) free_pgd_fast(pgd) +#define pgd_alloc(mm) get_pgd_fast() + +/* + * allocating and freeing a pmd is trivial: the 1-entry pmd is + * inside the pgd, so has no extra memory associated with it. + */ +#define pmd_alloc_one_fast(mm, addr) ({ BUG(); ((pmd_t *)1); }) +#define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *)2); }) +#define pmd_free(x) do { } while (0) +#define pgd_populate(mm, pmd, pte) BUG() extern int do_check_pgt_cache(int, int); - -extern inline void set_pgdir(unsigned long address, pgd_t entry) -{ - struct task_struct * p; - pgd_t *pgd; -#ifdef CONFIG_SMP - int i; -#endif - - read_lock(&tasklist_lock); - for_each_task(p) { - if (!p->mm) - continue; - *pgd_offset(p->mm,address) = entry; - } - read_unlock(&tasklist_lock); -#ifndef CONFIG_SMP - for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)*(unsigned long *)pgd) - pgd[address >> PGDIR_SHIFT] = entry; -#else - /* To pgd_alloc/pgd_free, one holds master kernel lock and so does our - callee, so we can modify pgd caches of other CPUs as well. -jj */ - for (i = 0; i < NR_CPUS; i++) - for (pgd = (pgd_t *)cpu_data[i].pgd_quick; pgd; pgd = (pgd_t *)*(unsigned long *)pgd) - pgd[address >> PGDIR_SHIFT] = entry; -#endif -} #endif /* _ASM_PGALLOC_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/pgtable.h linux/include/asm-mips/pgtable.h --- v2.4.5/linux/include/asm-mips/pgtable.h Tue Nov 7 10:46:04 2000 +++ linux/include/asm-mips/pgtable.h Mon Jul 2 13:56:40 2001 @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1994 - 1999 by Ralf Baechle at alii + * Copyright (C) 1994, 95, 96, 97, 98, 99, 2000 by Ralf Baechle at alii * Copyright (C) 1999 Silicon Graphics, Inc. */ #ifndef _ASM_PGTABLE_H @@ -25,32 +25,32 @@ * - flush_cache_page(mm, vmaddr) flushes a single page * - flush_cache_range(mm, start, end) flushes a range of pages * - flush_page_to_ram(page) write back kernel page to ram + * - flush_icache_range(start, end) flush a range of instructions */ extern void (*_flush_cache_all)(void); +extern void (*___flush_cache_all)(void); extern void (*_flush_cache_mm)(struct mm_struct *mm); extern void (*_flush_cache_range)(struct mm_struct *mm, unsigned long start, unsigned long end); extern void (*_flush_cache_page)(struct vm_area_struct *vma, unsigned long page); extern void (*_flush_cache_sigtramp)(unsigned long addr); extern void (*_flush_page_to_ram)(struct page * page); +extern void (*_flush_icache_range)(unsigned long start, unsigned long end); +extern void (*_flush_icache_page)(struct vm_area_struct *vma, + struct page *page); #define flush_dcache_page(page) do { } while (0) #define flush_cache_all() _flush_cache_all() +#define __flush_cache_all() ___flush_cache_all() #define flush_cache_mm(mm) _flush_cache_mm(mm) #define flush_cache_range(mm,start,end) _flush_cache_range(mm,start,end) #define flush_cache_page(vma,page) _flush_cache_page(vma, page) #define flush_cache_sigtramp(addr) _flush_cache_sigtramp(addr) #define flush_page_to_ram(page) _flush_page_to_ram(page) -#define flush_icache_range(start, end) flush_cache_all() - -#define flush_icache_page(vma, page) \ -do { \ - unsigned long addr; \ - addr = (unsigned long) page_address(page); \ - _flush_cache_page(vma, addr); \ -} while (0) +#define flush_icache_range(start, end) _flush_icache_range(start,end) +#define flush_icache_page(vma, page) _flush_icache_page(vma, page) /* @@ -59,6 +59,16 @@ extern void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, unsigned long entryhi, unsigned long pagemask); +/* + * - add_temporary_entry() add a temporary TLB entry. We use TLB entries + * starting at the top and working down. This is for populating the + * TLB before trap_init() puts the TLB miss handler in place. It + * should be used only for entries matching the actual page tables, + * to prevent inconsistencies. + */ +extern int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1, + unsigned long entryhi, unsigned long pagemask); + /* Basically we have the same two-level (which is the logical three level * Linux page table layout folded) page tables as the i386. Some day @@ -130,13 +140,25 @@ #define _CACHE_CACHABLE_NONCOHERENT 0 #else - #define _PAGE_R4KBUG (1<<5) /* workaround for r4k bug */ #define _PAGE_GLOBAL (1<<6) #define _PAGE_VALID (1<<7) #define _PAGE_SILENT_READ (1<<7) /* synonym */ #define _PAGE_DIRTY (1<<8) /* The MIPS dirty bit */ #define _PAGE_SILENT_WRITE (1<<8) +#define _CACHE_MASK (7<<9) + +#if defined(CONFIG_CPU_SB1) + +/* No penalty for being coherent on the SB1, so just + use it for "noncoherent" spaces, too. Shouldn't hurt. */ + +#define _CACHE_UNCACHED (2<<9) +#define _CACHE_CACHABLE_COW (5<<9) +#define _CACHE_CACHABLE_NONCOHERENT (5<<9) + +#else + #define _CACHE_CACHABLE_NO_WA (0<<9) /* R4600 only */ #define _CACHE_CACHABLE_WA (1<<9) /* R4600 only */ #define _CACHE_UNCACHED (2<<9) /* R4[0246]00 */ @@ -145,26 +167,36 @@ #define _CACHE_CACHABLE_COW (5<<9) /* R4[04]00 only */ #define _CACHE_CACHABLE_CUW (6<<9) /* R4[04]00 only */ #define _CACHE_CACHABLE_ACCELERATED (7<<9) /* R10000 only */ -#define _CACHE_MASK (7<<9) #endif +#endif #define __READABLE (_PAGE_READ | _PAGE_SILENT_READ | _PAGE_ACCESSED) #define __WRITEABLE (_PAGE_WRITE | _PAGE_SILENT_WRITE | _PAGE_MODIFIED) #define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_MODIFIED | _CACHE_MASK) +#ifdef CONFIG_MIPS_UNCACHED +#define PAGE_CACHABLE_DEFAULT _CACHE_UNCACHED +#else +#ifdef CONFIG_CPU_SB1 +#define PAGE_CACHABLE_DEFAULT _CACHE_CACHABLE_COW +#else +#define PAGE_CACHABLE_DEFAULT _CACHE_CACHABLE_NONCOHERENT +#endif +#endif + #define PAGE_NONE __pgprot(_PAGE_PRESENT | _CACHE_CACHABLE_NONCOHERENT) #define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ - _CACHE_CACHABLE_NONCOHERENT) + PAGE_CACHABLE_DEFAULT) #define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_READ | \ - _CACHE_CACHABLE_NONCOHERENT) + PAGE_CACHABLE_DEFAULT) #define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_READ | \ - _CACHE_CACHABLE_NONCOHERENT) + PAGE_CACHABLE_DEFAULT) #define PAGE_KERNEL __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \ - _CACHE_CACHABLE_NONCOHERENT) + PAGE_CACHABLE_DEFAULT) #define PAGE_USERIO __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ - _CACHE_UNCACHED) + PAGE_CACHABLE_DEFAULT) #define PAGE_KERNEL_UNCACHED __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \ _CACHE_UNCACHED) @@ -200,21 +232,9 @@ #define pgd_ERROR(e) \ printk("%s:%d: bad pgd %016lx.\n", __FILE__, __LINE__, pgd_val(e)) -/* - * BAD_PAGETABLE is used when we need a bogus page-table, while - * BAD_PAGE is used for a bogus page. - * - * ZERO_PAGE is a global shared page that is always zero: used - * for zero-mapped memory areas etc.. - */ -extern pte_t __bad_page(void); -extern pte_t *__bad_pagetable(void); - extern unsigned long empty_zero_page; extern unsigned long zero_page_mask; -#define BAD_PAGETABLE __bad_pagetable() -#define BAD_PAGE __bad_page() #define ZERO_PAGE(vaddr) \ (virt_to_page(empty_zero_page + (((unsigned long)(vaddr)) & zero_page_mask))) @@ -269,6 +289,13 @@ } /* + * (pmds are folded into pgds so this doesnt get actually called, + * but the define is needed for a generic inline function.) + */ +#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval) +#define set_pgd(pgdptr, pgdval) (*(pgdptr) = pgdval) + +/* * Empty pgd/pmd entries point to the invalid_pte_table. */ extern inline int pmd_none(pmd_t pmd) @@ -284,7 +311,7 @@ extern inline int pmd_present(pmd_t pmd) { - return pmd_val(pmd); + return (pmd_val(pmd) != (unsigned long) invalid_pte_table); } extern inline void pmd_clear(pmd_t *pmdp) @@ -303,7 +330,7 @@ extern inline void pgd_clear(pgd_t *pgdp) { } /* - * Permanent address of a page. On MIPS64 we never have highmem, so this + * Permanent address of a page. On MIPS we never have highmem, so this * is simple. */ #define page_address(page) ((page)->virtual) @@ -390,7 +417,7 @@ extern inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot) { - return __pte(((physpage & PAGE_MASK) - PAGE_OFFSET) | pgprot_val(pgprot)); + return __pte(physpage | pgprot_val(pgprot)); } extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot) @@ -424,19 +451,6 @@ ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)); } -/* - * Initialize new page directory with pointers to invalid ptes - */ -extern void pgd_init(unsigned long page); - -extern void __bad_pte(pmd_t *pmd); -extern void __bad_pte_kernel(pmd_t *pmd); - -#define pte_free_kernel(pte) free_pte_fast(pte) -#define pte_free(pte) free_pte_fast(pte) -#define pgd_free(pgd) free_pgd_fast(pgd) -#define pgd_alloc() get_pgd_fast() - extern int do_check_pgt_cache(int, int); extern pgd_t swapper_pg_dir[1024]; @@ -637,6 +651,19 @@ "mtc0 %0, $6\n\t" ".set pop" : : "r" (val)); +} + +extern inline unsigned long get_info(void) +{ + unsigned long val; + + __asm__( + ".set push\n\t" + ".set reorder\n\t" + "mfc0 %0, $7\n\t" + ".set pop" + : "=r" (val)); + return val; } /* CP0_TAGLO and CP0_TAGHI registers */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/pmc/ev64120.h linux/include/asm-mips/pmc/ev64120.h --- v2.4.5/linux/include/asm-mips/pmc/ev64120.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/pmc/ev64120.h Mon Jul 2 13:56:40 2001 @@ -0,0 +1,59 @@ +/* + * This is a direct copy of the ev96100.h file, with a global search and + * replace. The numbers are the same. + * + * The reason I'm duplicating this is so that the 64120/96100 + * defines won't be confusing in the source code. + */ +#ifndef _ASM_PMC_CP7000_H +#define _ASM_PMC_CP7000_H + +#include + +/* + * GT64120 config space base address + */ +#define GT64120_BASE (KSEG1ADDR(0x14000000)) +#define MIPS_GT_BASE GT64120_BASE + +/* + * PCI Bus allocation + */ +#define GT_PCI_MEM_BASE 0x12000000 +#define GT_PCI_MEM_SIZE 0x02000000 +#define GT_PCI_IO_BASE 0x10000000 +#define GT_PCI_IO_SIZE 0x02000000 +#define GT_ISA_IO_BASE PCI_IO_BASE + +/* + * Duart I/O ports. + */ +#define EV64120_COM1_BASE_ADDR (0x1d000000 + 0x20) +#define EV64120_COM2_BASE_ADDR (0x1d000000 + 0x00) + + +/* + * EV64120 interrupt controller register base. + */ +#define EV64120_ICTRL_REGS_BASE (KSEG1ADDR(0x1f000000)) + +/* + * EV64120 UART register base. + */ +#define EV64120_UART0_REGS_BASE (KSEG1ADDR(EV64120_COM1_BASE_ADDR)) +#define EV64120_UART1_REGS_BASE (KSEG1ADDR(EV64120_COM2_BASE_ADDR)) +#define EV64120_BASE_BAUD ( 3686400 / 16 ) + + +/* + * Because of an error/peculiarity in the Galileo chip, we need to swap the + * bytes when running bigendian. + */ + +#define GT_WRITE(ofs, data) \ + *(volatile u32 *)(MIPS_GT_BASE+ofs) = cpu_to_le32(data) +#define GT_READ(ofs, data) \ + *data = le32_to_cpu(*(volatile u32 *)(MIPS_GT_BASE+ofs)) + + +#endif /* _ASM_PMC_CP7000_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/pmc/ev64120int.h linux/include/asm-mips/pmc/ev64120int.h --- v2.4.5/linux/include/asm-mips/pmc/ev64120int.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/pmc/ev64120int.h Mon Jul 2 13:56:40 2001 @@ -0,0 +1,32 @@ +#ifndef _ASM_PMC_CP7000INT_H +#define _ASM_PMC_CP7000INT_H + +#define INT_CAUSE_MAIN 0 +#define INT_CAUSE_HIGH 1 + +#define MAX_CAUSE_REGS 4 +#define MAX_CAUSE_REG_WIDTH 32 + +void hook_irq_handler (int int_cause , int bit_num , void *isr_ptr); +int disable_galileo_irq (int int_cause , int bit_num); +int enable_galileo_irq (int int_cause , int bit_num); + +extern struct tq_struct irq_handlers[MAX_CAUSE_REGS][MAX_CAUSE_REG_WIDTH]; + +/* + * PCI interrupts will come in on either the INTA or INTD interrups lines, + * which are mapped to the #2 and #5 interrupt pins of the MIPS. On our + * boards, they all either come in on IntD or they all come in on IntA, they + * aren't mixed. There can be numerous PCI interrupts, so we keep a list of the + * "requested" interrupt numbers and go through the list whenever we get an + * IntA/D. + * + * All PCI interrupts have numbers >= 20 by arbitrary convention. Any + * interrupt < 8 is an interrupt that is maskable on MIPS. + */ + +#define TIMER 4 +#define INTA 2 +#define INTD 5 + +#endif /* _ASM_PMC_CP7000INT_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/processor.h linux/include/asm-mips/processor.h --- v2.4.5/linux/include/asm-mips/processor.h Fri Apr 13 20:26:07 2001 +++ linux/include/asm-mips/processor.h Mon Jul 2 13:56:40 2001 @@ -1,11 +1,10 @@ -/* $Id: processor.h,v 1.25 2000/02/05 06:47:37 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 1994 Waldorf GMBH - * Copyright (C) 1995, 1996, 1997, 1998 Ralf Baechle + * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2001 Ralf Baechle * Copyright (C) 1996 Paul M. Antoine * Copyright (C) 1999 Silicon Graphics, Inc. */ @@ -30,6 +29,7 @@ #include struct mips_cpuinfo { + unsigned long udelay_val; unsigned long *pgd_quick; unsigned long *pte_quick; unsigned long pgtable_cache_sz; @@ -44,7 +44,6 @@ extern void r4k_wait(void); extern char cyclecounter_available; /* only available from R4000 upwards. */ extern char dedicated_iv_available; /* some embedded MIPS like Nevada */ -extern char vce_available; /* Supports VCED / VCEI exceptions */ extern struct mips_cpuinfo boot_cpu_data; extern unsigned int vced_count, vcei_count; @@ -83,7 +82,7 @@ * for a 64 bit kernel expandable to 8192EB, of which the current MIPS * implementations will "only" be able to use 1TB ... */ -#define TASK_SIZE (0x80000000UL) +#define TASK_SIZE (0x7fff8000UL) /* This decides where the kernel will search for a free chunk of vm * space during mmap's. diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/ptrace.h linux/include/asm-mips/ptrace.h --- v2.4.5/linux/include/asm-mips/ptrace.h Sun Jul 9 22:18:15 2000 +++ linux/include/asm-mips/ptrace.h Mon Jul 2 13:56:40 2001 @@ -1,16 +1,15 @@ -/* $Id: ptrace.h,v 1.7 1999/09/28 22:27:17 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1994, 1995, 1996, 1997, 1998 by Ralf Baechle + * Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000 by Ralf Baechle * * Machine dependent structs and defines to help the user use * the ptrace system call. */ -#ifndef __ASM_MIPS_PTRACE_H -#define __ASM_MIPS_PTRACE_H +#ifndef _ASM_PTRACE_H +#define _ASM_PTRACE_H #include #include @@ -52,6 +51,19 @@ #endif /* !(_LANGUAGE_ASSEMBLY) */ +/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */ +/* #define PTRACE_GETREGS 12 */ +/* #define PTRACE_SETREGS 13 */ +/* #define PTRACE_GETFPREGS 14 */ +/* #define PTRACE_SETFPREGS 15 */ +/* #define PTRACE_GETFPXREGS 18 */ +/* #define PTRACE_SETFPXREGS 19 */ + +#define PTRACE_SETOPTIONS 21 + +/* options set using PTRACE_SETOPTIONS */ +#define PTRACE_O_TRACESYSGOOD 0x00000001 + #ifdef _LANGUAGE_ASSEMBLY #include #endif @@ -71,4 +83,4 @@ #endif -#endif /* __ASM_MIPS_PTRACE_H */ +#endif /* _ASM_PTRACE_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/resource.h linux/include/asm-mips/resource.h --- v2.4.5/linux/include/asm-mips/resource.h Fri Sep 22 14:21:20 2000 +++ linux/include/asm-mips/resource.h Mon Jul 2 13:56:40 2001 @@ -1,10 +1,9 @@ -/* $Id: resource.h,v 1.4 2000/01/27 23:45:30 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995, 1996, 1998 by Ralf Baechle + * Copyright (C) 1995, 96, 98, 2000 by Ralf Baechle */ #ifndef _ASM_RESOURCE_H #define _ASM_RESOURCE_H @@ -26,13 +25,13 @@ #define RLIM_NLIMITS 11 /* Number of limit flavors. */ +#ifdef __KERNEL__ + /* * SuS says limits have to be unsigned. * Which makes a ton more sense anyway. */ #define RLIM_INFINITY 0x7fffffffUL - -#ifdef __KERNEL__ #define INIT_RLIMITS \ { \ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/riscos-syscall.h linux/include/asm-mips/riscos-syscall.h --- v2.4.5/linux/include/asm-mips/riscos-syscall.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/riscos-syscall.h Mon Jul 2 13:56:40 2001 @@ -0,0 +1,979 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995, 96, 97, 98, 99, 2000 by Ralf Baechle + */ +#ifndef _ASM_RISCOS_SYSCALL_H +#define _ASM_RISCOS_SYSCALL_H + +/* + * The syscalls 0 - 3999 are reserved for a down to the root syscall + * compatibility with RISC/os and IRIX. We'll see how to deal with the + * various "real" BSD variants like Ultrix, NetBSD ... + */ + +/* + * SVR4 syscalls are in the range from 1 to 999 + */ +#define __NR_SVR4 0 +#define __NR_SVR4_syscall (__NR_SVR4 + 0) +#define __NR_SVR4_exit (__NR_SVR4 + 1) +#define __NR_SVR4_fork (__NR_SVR4 + 2) +#define __NR_SVR4_read (__NR_SVR4 + 3) +#define __NR_SVR4_write (__NR_SVR4 + 4) +#define __NR_SVR4_open (__NR_SVR4 + 5) +#define __NR_SVR4_close (__NR_SVR4 + 6) +#define __NR_SVR4_wait (__NR_SVR4 + 7) +#define __NR_SVR4_creat (__NR_SVR4 + 8) +#define __NR_SVR4_link (__NR_SVR4 + 9) +#define __NR_SVR4_unlink (__NR_SVR4 + 10) +#define __NR_SVR4_exec (__NR_SVR4 + 11) +#define __NR_SVR4_chdir (__NR_SVR4 + 12) +#define __NR_SVR4_gtime (__NR_SVR4 + 13) +#define __NR_SVR4_mknod (__NR_SVR4 + 14) +#define __NR_SVR4_chmod (__NR_SVR4 + 15) +#define __NR_SVR4_chown (__NR_SVR4 + 16) +#define __NR_SVR4_sbreak (__NR_SVR4 + 17) +#define __NR_SVR4_stat (__NR_SVR4 + 18) +#define __NR_SVR4_lseek (__NR_SVR4 + 19) +#define __NR_SVR4_getpid (__NR_SVR4 + 20) +#define __NR_SVR4_mount (__NR_SVR4 + 21) +#define __NR_SVR4_umount (__NR_SVR4 + 22) +#define __NR_SVR4_setuid (__NR_SVR4 + 23) +#define __NR_SVR4_getuid (__NR_SVR4 + 24) +#define __NR_SVR4_stime (__NR_SVR4 + 25) +#define __NR_SVR4_ptrace (__NR_SVR4 + 26) +#define __NR_SVR4_alarm (__NR_SVR4 + 27) +#define __NR_SVR4_fstat (__NR_SVR4 + 28) +#define __NR_SVR4_pause (__NR_SVR4 + 29) +#define __NR_SVR4_utime (__NR_SVR4 + 30) +#define __NR_SVR4_stty (__NR_SVR4 + 31) +#define __NR_SVR4_gtty (__NR_SVR4 + 32) +#define __NR_SVR4_access (__NR_SVR4 + 33) +#define __NR_SVR4_nice (__NR_SVR4 + 34) +#define __NR_SVR4_statfs (__NR_SVR4 + 35) +#define __NR_SVR4_sync (__NR_SVR4 + 36) +#define __NR_SVR4_kill (__NR_SVR4 + 37) +#define __NR_SVR4_fstatfs (__NR_SVR4 + 38) +#define __NR_SVR4_setpgrp (__NR_SVR4 + 39) +#define __NR_SVR4_cxenix (__NR_SVR4 + 40) +#define __NR_SVR4_dup (__NR_SVR4 + 41) +#define __NR_SVR4_pipe (__NR_SVR4 + 42) +#define __NR_SVR4_times (__NR_SVR4 + 43) +#define __NR_SVR4_profil (__NR_SVR4 + 44) +#define __NR_SVR4_plock (__NR_SVR4 + 45) +#define __NR_SVR4_setgid (__NR_SVR4 + 46) +#define __NR_SVR4_getgid (__NR_SVR4 + 47) +#define __NR_SVR4_sig (__NR_SVR4 + 48) +#define __NR_SVR4_msgsys (__NR_SVR4 + 49) +#define __NR_SVR4_sysmips (__NR_SVR4 + 50) +#define __NR_SVR4_sysacct (__NR_SVR4 + 51) +#define __NR_SVR4_shmsys (__NR_SVR4 + 52) +#define __NR_SVR4_semsys (__NR_SVR4 + 53) +#define __NR_SVR4_ioctl (__NR_SVR4 + 54) +#define __NR_SVR4_uadmin (__NR_SVR4 + 55) +#define __NR_SVR4_exch (__NR_SVR4 + 56) +#define __NR_SVR4_utssys (__NR_SVR4 + 57) +#define __NR_SVR4_fsync (__NR_SVR4 + 58) +#define __NR_SVR4_exece (__NR_SVR4 + 59) +#define __NR_SVR4_umask (__NR_SVR4 + 60) +#define __NR_SVR4_chroot (__NR_SVR4 + 61) +#define __NR_SVR4_fcntl (__NR_SVR4 + 62) +#define __NR_SVR4_ulimit (__NR_SVR4 + 63) +#define __NR_SVR4_reserved1 (__NR_SVR4 + 64) +#define __NR_SVR4_reserved2 (__NR_SVR4 + 65) +#define __NR_SVR4_reserved3 (__NR_SVR4 + 66) +#define __NR_SVR4_reserved4 (__NR_SVR4 + 67) +#define __NR_SVR4_reserved5 (__NR_SVR4 + 68) +#define __NR_SVR4_reserved6 (__NR_SVR4 + 69) +#define __NR_SVR4_advfs (__NR_SVR4 + 70) +#define __NR_SVR4_unadvfs (__NR_SVR4 + 71) +#define __NR_SVR4_unused1 (__NR_SVR4 + 72) +#define __NR_SVR4_unused2 (__NR_SVR4 + 73) +#define __NR_SVR4_rfstart (__NR_SVR4 + 74) +#define __NR_SVR4_unused3 (__NR_SVR4 + 75) +#define __NR_SVR4_rdebug (__NR_SVR4 + 76) +#define __NR_SVR4_rfstop (__NR_SVR4 + 77) +#define __NR_SVR4_rfsys (__NR_SVR4 + 78) +#define __NR_SVR4_rmdir (__NR_SVR4 + 79) +#define __NR_SVR4_mkdir (__NR_SVR4 + 80) +#define __NR_SVR4_getdents (__NR_SVR4 + 81) +#define __NR_SVR4_libattach (__NR_SVR4 + 82) +#define __NR_SVR4_libdetach (__NR_SVR4 + 83) +#define __NR_SVR4_sysfs (__NR_SVR4 + 84) +#define __NR_SVR4_getmsg (__NR_SVR4 + 85) +#define __NR_SVR4_putmsg (__NR_SVR4 + 86) +#define __NR_SVR4_poll (__NR_SVR4 + 87) +#define __NR_SVR4_lstat (__NR_SVR4 + 88) +#define __NR_SVR4_symlink (__NR_SVR4 + 89) +#define __NR_SVR4_readlink (__NR_SVR4 + 90) +#define __NR_SVR4_setgroups (__NR_SVR4 + 91) +#define __NR_SVR4_getgroups (__NR_SVR4 + 92) +#define __NR_SVR4_fchmod (__NR_SVR4 + 93) +#define __NR_SVR4_fchown (__NR_SVR4 + 94) +#define __NR_SVR4_sigprocmask (__NR_SVR4 + 95) +#define __NR_SVR4_sigsuspend (__NR_SVR4 + 96) +#define __NR_SVR4_sigaltstack (__NR_SVR4 + 97) +#define __NR_SVR4_sigaction (__NR_SVR4 + 98) +#define __NR_SVR4_sigpending (__NR_SVR4 + 99) +#define __NR_SVR4_setcontext (__NR_SVR4 + 100) +#define __NR_SVR4_evsys (__NR_SVR4 + 101) +#define __NR_SVR4_evtrapret (__NR_SVR4 + 102) +#define __NR_SVR4_statvfs (__NR_SVR4 + 103) +#define __NR_SVR4_fstatvfs (__NR_SVR4 + 104) +#define __NR_SVR4_reserved7 (__NR_SVR4 + 105) +#define __NR_SVR4_nfssys (__NR_SVR4 + 106) +#define __NR_SVR4_waitid (__NR_SVR4 + 107) +#define __NR_SVR4_sigsendset (__NR_SVR4 + 108) +#define __NR_SVR4_hrtsys (__NR_SVR4 + 109) +#define __NR_SVR4_acancel (__NR_SVR4 + 110) +#define __NR_SVR4_async (__NR_SVR4 + 111) +#define __NR_SVR4_priocntlset (__NR_SVR4 + 112) +#define __NR_SVR4_pathconf (__NR_SVR4 + 113) +#define __NR_SVR4_mincore (__NR_SVR4 + 114) +#define __NR_SVR4_mmap (__NR_SVR4 + 115) +#define __NR_SVR4_mprotect (__NR_SVR4 + 116) +#define __NR_SVR4_munmap (__NR_SVR4 + 117) +#define __NR_SVR4_fpathconf (__NR_SVR4 + 118) +#define __NR_SVR4_vfork (__NR_SVR4 + 119) +#define __NR_SVR4_fchdir (__NR_SVR4 + 120) +#define __NR_SVR4_readv (__NR_SVR4 + 121) +#define __NR_SVR4_writev (__NR_SVR4 + 122) +#define __NR_SVR4_xstat (__NR_SVR4 + 123) +#define __NR_SVR4_lxstat (__NR_SVR4 + 124) +#define __NR_SVR4_fxstat (__NR_SVR4 + 125) +#define __NR_SVR4_xmknod (__NR_SVR4 + 126) +#define __NR_SVR4_clocal (__NR_SVR4 + 127) +#define __NR_SVR4_setrlimit (__NR_SVR4 + 128) +#define __NR_SVR4_getrlimit (__NR_SVR4 + 129) +#define __NR_SVR4_lchown (__NR_SVR4 + 130) +#define __NR_SVR4_memcntl (__NR_SVR4 + 131) +#define __NR_SVR4_getpmsg (__NR_SVR4 + 132) +#define __NR_SVR4_putpmsg (__NR_SVR4 + 133) +#define __NR_SVR4_rename (__NR_SVR4 + 134) +#define __NR_SVR4_nuname (__NR_SVR4 + 135) +#define __NR_SVR4_setegid (__NR_SVR4 + 136) +#define __NR_SVR4_sysconf (__NR_SVR4 + 137) +#define __NR_SVR4_adjtime (__NR_SVR4 + 138) +#define __NR_SVR4_sysinfo (__NR_SVR4 + 139) +#define __NR_SVR4_reserved8 (__NR_SVR4 + 140) +#define __NR_SVR4_seteuid (__NR_SVR4 + 141) +#define __NR_SVR4_PYRAMID_statis (__NR_SVR4 + 142) +#define __NR_SVR4_PYRAMID_tuning (__NR_SVR4 + 143) +#define __NR_SVR4_PYRAMID_forcerr (__NR_SVR4 + 144) +#define __NR_SVR4_PYRAMID_mpcntl (__NR_SVR4 + 145) +#define __NR_SVR4_reserved9 (__NR_SVR4 + 146) +#define __NR_SVR4_reserved10 (__NR_SVR4 + 147) +#define __NR_SVR4_reserved11 (__NR_SVR4 + 148) +#define __NR_SVR4_reserved12 (__NR_SVR4 + 149) +#define __NR_SVR4_reserved13 (__NR_SVR4 + 150) +#define __NR_SVR4_reserved14 (__NR_SVR4 + 151) +#define __NR_SVR4_reserved15 (__NR_SVR4 + 152) +#define __NR_SVR4_reserved16 (__NR_SVR4 + 153) +#define __NR_SVR4_reserved17 (__NR_SVR4 + 154) +#define __NR_SVR4_reserved18 (__NR_SVR4 + 155) +#define __NR_SVR4_reserved19 (__NR_SVR4 + 156) +#define __NR_SVR4_reserved20 (__NR_SVR4 + 157) +#define __NR_SVR4_reserved21 (__NR_SVR4 + 158) +#define __NR_SVR4_reserved22 (__NR_SVR4 + 159) +#define __NR_SVR4_reserved23 (__NR_SVR4 + 160) +#define __NR_SVR4_reserved24 (__NR_SVR4 + 161) +#define __NR_SVR4_reserved25 (__NR_SVR4 + 162) +#define __NR_SVR4_reserved26 (__NR_SVR4 + 163) +#define __NR_SVR4_reserved27 (__NR_SVR4 + 164) +#define __NR_SVR4_reserved28 (__NR_SVR4 + 165) +#define __NR_SVR4_reserved29 (__NR_SVR4 + 166) +#define __NR_SVR4_reserved30 (__NR_SVR4 + 167) +#define __NR_SVR4_reserved31 (__NR_SVR4 + 168) +#define __NR_SVR4_reserved32 (__NR_SVR4 + 169) +#define __NR_SVR4_reserved33 (__NR_SVR4 + 170) +#define __NR_SVR4_reserved34 (__NR_SVR4 + 171) +#define __NR_SVR4_reserved35 (__NR_SVR4 + 172) +#define __NR_SVR4_reserved36 (__NR_SVR4 + 173) +#define __NR_SVR4_reserved37 (__NR_SVR4 + 174) +#define __NR_SVR4_reserved38 (__NR_SVR4 + 175) +#define __NR_SVR4_reserved39 (__NR_SVR4 + 176) +#define __NR_SVR4_reserved40 (__NR_SVR4 + 177) +#define __NR_SVR4_reserved41 (__NR_SVR4 + 178) +#define __NR_SVR4_reserved42 (__NR_SVR4 + 179) +#define __NR_SVR4_reserved43 (__NR_SVR4 + 180) +#define __NR_SVR4_reserved44 (__NR_SVR4 + 181) +#define __NR_SVR4_reserved45 (__NR_SVR4 + 182) +#define __NR_SVR4_reserved46 (__NR_SVR4 + 183) +#define __NR_SVR4_reserved47 (__NR_SVR4 + 184) +#define __NR_SVR4_reserved48 (__NR_SVR4 + 185) +#define __NR_SVR4_reserved49 (__NR_SVR4 + 186) +#define __NR_SVR4_reserved50 (__NR_SVR4 + 187) +#define __NR_SVR4_reserved51 (__NR_SVR4 + 188) +#define __NR_SVR4_reserved52 (__NR_SVR4 + 189) +#define __NR_SVR4_reserved53 (__NR_SVR4 + 190) +#define __NR_SVR4_reserved54 (__NR_SVR4 + 191) +#define __NR_SVR4_reserved55 (__NR_SVR4 + 192) +#define __NR_SVR4_reserved56 (__NR_SVR4 + 193) +#define __NR_SVR4_reserved57 (__NR_SVR4 + 194) +#define __NR_SVR4_reserved58 (__NR_SVR4 + 195) +#define __NR_SVR4_reserved59 (__NR_SVR4 + 196) +#define __NR_SVR4_reserved60 (__NR_SVR4 + 197) +#define __NR_SVR4_reserved61 (__NR_SVR4 + 198) +#define __NR_SVR4_reserved62 (__NR_SVR4 + 199) +#define __NR_SVR4_reserved63 (__NR_SVR4 + 200) +#define __NR_SVR4_aread (__NR_SVR4 + 201) +#define __NR_SVR4_awrite (__NR_SVR4 + 202) +#define __NR_SVR4_listio (__NR_SVR4 + 203) +#define __NR_SVR4_mips_acancel (__NR_SVR4 + 204) +#define __NR_SVR4_astatus (__NR_SVR4 + 205) +#define __NR_SVR4_await (__NR_SVR4 + 206) +#define __NR_SVR4_areadv (__NR_SVR4 + 207) +#define __NR_SVR4_awritev (__NR_SVR4 + 208) +#define __NR_SVR4_MIPS_reserved1 (__NR_SVR4 + 209) +#define __NR_SVR4_MIPS_reserved2 (__NR_SVR4 + 210) +#define __NR_SVR4_MIPS_reserved3 (__NR_SVR4 + 211) +#define __NR_SVR4_MIPS_reserved4 (__NR_SVR4 + 212) +#define __NR_SVR4_MIPS_reserved5 (__NR_SVR4 + 213) +#define __NR_SVR4_MIPS_reserved6 (__NR_SVR4 + 214) +#define __NR_SVR4_MIPS_reserved7 (__NR_SVR4 + 215) +#define __NR_SVR4_MIPS_reserved8 (__NR_SVR4 + 216) +#define __NR_SVR4_MIPS_reserved9 (__NR_SVR4 + 217) +#define __NR_SVR4_MIPS_reserved10 (__NR_SVR4 + 218) +#define __NR_SVR4_MIPS_reserved11 (__NR_SVR4 + 219) +#define __NR_SVR4_MIPS_reserved12 (__NR_SVR4 + 220) +#define __NR_SVR4_CDC_reserved1 (__NR_SVR4 + 221) +#define __NR_SVR4_CDC_reserved2 (__NR_SVR4 + 222) +#define __NR_SVR4_CDC_reserved3 (__NR_SVR4 + 223) +#define __NR_SVR4_CDC_reserved4 (__NR_SVR4 + 224) +#define __NR_SVR4_CDC_reserved5 (__NR_SVR4 + 225) +#define __NR_SVR4_CDC_reserved6 (__NR_SVR4 + 226) +#define __NR_SVR4_CDC_reserved7 (__NR_SVR4 + 227) +#define __NR_SVR4_CDC_reserved8 (__NR_SVR4 + 228) +#define __NR_SVR4_CDC_reserved9 (__NR_SVR4 + 229) +#define __NR_SVR4_CDC_reserved10 (__NR_SVR4 + 230) +#define __NR_SVR4_CDC_reserved11 (__NR_SVR4 + 231) +#define __NR_SVR4_CDC_reserved12 (__NR_SVR4 + 232) +#define __NR_SVR4_CDC_reserved13 (__NR_SVR4 + 233) +#define __NR_SVR4_CDC_reserved14 (__NR_SVR4 + 234) +#define __NR_SVR4_CDC_reserved15 (__NR_SVR4 + 235) +#define __NR_SVR4_CDC_reserved16 (__NR_SVR4 + 236) +#define __NR_SVR4_CDC_reserved17 (__NR_SVR4 + 237) +#define __NR_SVR4_CDC_reserved18 (__NR_SVR4 + 238) +#define __NR_SVR4_CDC_reserved19 (__NR_SVR4 + 239) +#define __NR_SVR4_CDC_reserved20 (__NR_SVR4 + 240) + +/* + * SYS V syscalls are in the range from 1000 to 1999 + */ +#define __NR_SYSV 1000 +#define __NR_SYSV_syscall (__NR_SYSV + 0) +#define __NR_SYSV_exit (__NR_SYSV + 1) +#define __NR_SYSV_fork (__NR_SYSV + 2) +#define __NR_SYSV_read (__NR_SYSV + 3) +#define __NR_SYSV_write (__NR_SYSV + 4) +#define __NR_SYSV_open (__NR_SYSV + 5) +#define __NR_SYSV_close (__NR_SYSV + 6) +#define __NR_SYSV_wait (__NR_SYSV + 7) +#define __NR_SYSV_creat (__NR_SYSV + 8) +#define __NR_SYSV_link (__NR_SYSV + 9) +#define __NR_SYSV_unlink (__NR_SYSV + 10) +#define __NR_SYSV_execv (__NR_SYSV + 11) +#define __NR_SYSV_chdir (__NR_SYSV + 12) +#define __NR_SYSV_time (__NR_SYSV + 13) +#define __NR_SYSV_mknod (__NR_SYSV + 14) +#define __NR_SYSV_chmod (__NR_SYSV + 15) +#define __NR_SYSV_chown (__NR_SYSV + 16) +#define __NR_SYSV_brk (__NR_SYSV + 17) +#define __NR_SYSV_stat (__NR_SYSV + 18) +#define __NR_SYSV_lseek (__NR_SYSV + 19) +#define __NR_SYSV_getpid (__NR_SYSV + 20) +#define __NR_SYSV_mount (__NR_SYSV + 21) +#define __NR_SYSV_umount (__NR_SYSV + 22) +#define __NR_SYSV_setuid (__NR_SYSV + 23) +#define __NR_SYSV_getuid (__NR_SYSV + 24) +#define __NR_SYSV_stime (__NR_SYSV + 25) +#define __NR_SYSV_ptrace (__NR_SYSV + 26) +#define __NR_SYSV_alarm (__NR_SYSV + 27) +#define __NR_SYSV_fstat (__NR_SYSV + 28) +#define __NR_SYSV_pause (__NR_SYSV + 29) +#define __NR_SYSV_utime (__NR_SYSV + 30) +#define __NR_SYSV_stty (__NR_SYSV + 31) +#define __NR_SYSV_gtty (__NR_SYSV + 32) +#define __NR_SYSV_access (__NR_SYSV + 33) +#define __NR_SYSV_nice (__NR_SYSV + 34) +#define __NR_SYSV_statfs (__NR_SYSV + 35) +#define __NR_SYSV_sync (__NR_SYSV + 36) +#define __NR_SYSV_kill (__NR_SYSV + 37) +#define __NR_SYSV_fstatfs (__NR_SYSV + 38) +#define __NR_SYSV_setpgrp (__NR_SYSV + 39) +#define __NR_SYSV_syssgi (__NR_SYSV + 40) +#define __NR_SYSV_dup (__NR_SYSV + 41) +#define __NR_SYSV_pipe (__NR_SYSV + 42) +#define __NR_SYSV_times (__NR_SYSV + 43) +#define __NR_SYSV_profil (__NR_SYSV + 44) +#define __NR_SYSV_plock (__NR_SYSV + 45) +#define __NR_SYSV_setgid (__NR_SYSV + 46) +#define __NR_SYSV_getgid (__NR_SYSV + 47) +#define __NR_SYSV_sig (__NR_SYSV + 48) +#define __NR_SYSV_msgsys (__NR_SYSV + 49) +#define __NR_SYSV_sysmips (__NR_SYSV + 50) +#define __NR_SYSV_acct (__NR_SYSV + 51) +#define __NR_SYSV_shmsys (__NR_SYSV + 52) +#define __NR_SYSV_semsys (__NR_SYSV + 53) +#define __NR_SYSV_ioctl (__NR_SYSV + 54) +#define __NR_SYSV_uadmin (__NR_SYSV + 55) +#define __NR_SYSV_sysmp (__NR_SYSV + 56) +#define __NR_SYSV_utssys (__NR_SYSV + 57) +#define __NR_SYSV_USG_reserved1 (__NR_SYSV + 58) +#define __NR_SYSV_execve (__NR_SYSV + 59) +#define __NR_SYSV_umask (__NR_SYSV + 60) +#define __NR_SYSV_chroot (__NR_SYSV + 61) +#define __NR_SYSV_fcntl (__NR_SYSV + 62) +#define __NR_SYSV_ulimit (__NR_SYSV + 63) +#define __NR_SYSV_SAFARI4_reserved1 (__NR_SYSV + 64) +#define __NR_SYSV_SAFARI4_reserved2 (__NR_SYSV + 65) +#define __NR_SYSV_SAFARI4_reserved3 (__NR_SYSV + 66) +#define __NR_SYSV_SAFARI4_reserved4 (__NR_SYSV + 67) +#define __NR_SYSV_SAFARI4_reserved5 (__NR_SYSV + 68) +#define __NR_SYSV_SAFARI4_reserved6 (__NR_SYSV + 69) +#define __NR_SYSV_advfs (__NR_SYSV + 70) +#define __NR_SYSV_unadvfs (__NR_SYSV + 71) +#define __NR_SYSV_rmount (__NR_SYSV + 72) +#define __NR_SYSV_rumount (__NR_SYSV + 73) +#define __NR_SYSV_rfstart (__NR_SYSV + 74) +#define __NR_SYSV_getrlimit64 (__NR_SYSV + 75) +#define __NR_SYSV_setrlimit64 (__NR_SYSV + 76) +#define __NR_SYSV_nanosleep (__NR_SYSV + 77) +#define __NR_SYSV_lseek64 (__NR_SYSV + 78) +#define __NR_SYSV_rmdir (__NR_SYSV + 79) +#define __NR_SYSV_mkdir (__NR_SYSV + 80) +#define __NR_SYSV_getdents (__NR_SYSV + 81) +#define __NR_SYSV_sginap (__NR_SYSV + 82) +#define __NR_SYSV_sgikopt (__NR_SYSV + 83) +#define __NR_SYSV_sysfs (__NR_SYSV + 84) +#define __NR_SYSV_getmsg (__NR_SYSV + 85) +#define __NR_SYSV_putmsg (__NR_SYSV + 86) +#define __NR_SYSV_poll (__NR_SYSV + 87) +#define __NR_SYSV_sigreturn (__NR_SYSV + 88) +#define __NR_SYSV_accept (__NR_SYSV + 89) +#define __NR_SYSV_bind (__NR_SYSV + 90) +#define __NR_SYSV_connect (__NR_SYSV + 91) +#define __NR_SYSV_gethostid (__NR_SYSV + 92) +#define __NR_SYSV_getpeername (__NR_SYSV + 93) +#define __NR_SYSV_getsockname (__NR_SYSV + 94) +#define __NR_SYSV_getsockopt (__NR_SYSV + 95) +#define __NR_SYSV_listen (__NR_SYSV + 96) +#define __NR_SYSV_recv (__NR_SYSV + 97) +#define __NR_SYSV_recvfrom (__NR_SYSV + 98) +#define __NR_SYSV_recvmsg (__NR_SYSV + 99) +#define __NR_SYSV_select (__NR_SYSV + 100) +#define __NR_SYSV_send (__NR_SYSV + 101) +#define __NR_SYSV_sendmsg (__NR_SYSV + 102) +#define __NR_SYSV_sendto (__NR_SYSV + 103) +#define __NR_SYSV_sethostid (__NR_SYSV + 104) +#define __NR_SYSV_setsockopt (__NR_SYSV + 105) +#define __NR_SYSV_shutdown (__NR_SYSV + 106) +#define __NR_SYSV_socket (__NR_SYSV + 107) +#define __NR_SYSV_gethostname (__NR_SYSV + 108) +#define __NR_SYSV_sethostname (__NR_SYSV + 109) +#define __NR_SYSV_getdomainname (__NR_SYSV + 110) +#define __NR_SYSV_setdomainname (__NR_SYSV + 111) +#define __NR_SYSV_truncate (__NR_SYSV + 112) +#define __NR_SYSV_ftruncate (__NR_SYSV + 113) +#define __NR_SYSV_rename (__NR_SYSV + 114) +#define __NR_SYSV_symlink (__NR_SYSV + 115) +#define __NR_SYSV_readlink (__NR_SYSV + 116) +#define __NR_SYSV_lstat (__NR_SYSV + 117) +#define __NR_SYSV_nfsmount (__NR_SYSV + 118) +#define __NR_SYSV_nfssvc (__NR_SYSV + 119) +#define __NR_SYSV_getfh (__NR_SYSV + 120) +#define __NR_SYSV_async_daemon (__NR_SYSV + 121) +#define __NR_SYSV_exportfs (__NR_SYSV + 122) +#define __NR_SYSV_setregid (__NR_SYSV + 123) +#define __NR_SYSV_setreuid (__NR_SYSV + 124) +#define __NR_SYSV_getitimer (__NR_SYSV + 125) +#define __NR_SYSV_setitimer (__NR_SYSV + 126) +#define __NR_SYSV_adjtime (__NR_SYSV + 127) +#define __NR_SYSV_BSD_getime (__NR_SYSV + 128) +#define __NR_SYSV_sproc (__NR_SYSV + 129) +#define __NR_SYSV_prctl (__NR_SYSV + 130) +#define __NR_SYSV_procblk (__NR_SYSV + 131) +#define __NR_SYSV_sprocsp (__NR_SYSV + 132) +#define __NR_SYSV_sgigsc (__NR_SYSV + 133) +#define __NR_SYSV_mmap (__NR_SYSV + 134) +#define __NR_SYSV_munmap (__NR_SYSV + 135) +#define __NR_SYSV_mprotect (__NR_SYSV + 136) +#define __NR_SYSV_msync (__NR_SYSV + 137) +#define __NR_SYSV_madvise (__NR_SYSV + 138) +#define __NR_SYSV_pagelock (__NR_SYSV + 139) +#define __NR_SYSV_getpagesize (__NR_SYSV + 140) +#define __NR_SYSV_quotactl (__NR_SYSV + 141) +#define __NR_SYSV_libdetach (__NR_SYSV + 142) +#define __NR_SYSV_BSDgetpgrp (__NR_SYSV + 143) +#define __NR_SYSV_BSDsetpgrp (__NR_SYSV + 144) +#define __NR_SYSV_vhangup (__NR_SYSV + 145) +#define __NR_SYSV_fsync (__NR_SYSV + 146) +#define __NR_SYSV_fchdir (__NR_SYSV + 147) +#define __NR_SYSV_getrlimit (__NR_SYSV + 148) +#define __NR_SYSV_setrlimit (__NR_SYSV + 149) +#define __NR_SYSV_cacheflush (__NR_SYSV + 150) +#define __NR_SYSV_cachectl (__NR_SYSV + 151) +#define __NR_SYSV_fchown (__NR_SYSV + 152) +#define __NR_SYSV_fchmod (__NR_SYSV + 153) +#define __NR_SYSV_wait3 (__NR_SYSV + 154) +#define __NR_SYSV_socketpair (__NR_SYSV + 155) +#define __NR_SYSV_sysinfo (__NR_SYSV + 156) +#define __NR_SYSV_nuname (__NR_SYSV + 157) +#define __NR_SYSV_xstat (__NR_SYSV + 158) +#define __NR_SYSV_lxstat (__NR_SYSV + 159) +#define __NR_SYSV_fxstat (__NR_SYSV + 160) +#define __NR_SYSV_xmknod (__NR_SYSV + 161) +#define __NR_SYSV_ksigaction (__NR_SYSV + 162) +#define __NR_SYSV_sigpending (__NR_SYSV + 163) +#define __NR_SYSV_sigprocmask (__NR_SYSV + 164) +#define __NR_SYSV_sigsuspend (__NR_SYSV + 165) +#define __NR_SYSV_sigpoll (__NR_SYSV + 166) +#define __NR_SYSV_swapctl (__NR_SYSV + 167) +#define __NR_SYSV_getcontext (__NR_SYSV + 168) +#define __NR_SYSV_setcontext (__NR_SYSV + 169) +#define __NR_SYSV_waitsys (__NR_SYSV + 170) +#define __NR_SYSV_sigstack (__NR_SYSV + 171) +#define __NR_SYSV_sigaltstack (__NR_SYSV + 172) +#define __NR_SYSV_sigsendset (__NR_SYSV + 173) +#define __NR_SYSV_statvfs (__NR_SYSV + 174) +#define __NR_SYSV_fstatvfs (__NR_SYSV + 175) +#define __NR_SYSV_getpmsg (__NR_SYSV + 176) +#define __NR_SYSV_putpmsg (__NR_SYSV + 177) +#define __NR_SYSV_lchown (__NR_SYSV + 178) +#define __NR_SYSV_priocntl (__NR_SYSV + 179) +#define __NR_SYSV_ksigqueue (__NR_SYSV + 180) +#define __NR_SYSV_readv (__NR_SYSV + 181) +#define __NR_SYSV_writev (__NR_SYSV + 182) +#define __NR_SYSV_truncate64 (__NR_SYSV + 183) +#define __NR_SYSV_ftruncate64 (__NR_SYSV + 184) +#define __NR_SYSV_mmap64 (__NR_SYSV + 185) +#define __NR_SYSV_dmi (__NR_SYSV + 186) +#define __NR_SYSV_pread (__NR_SYSV + 187) +#define __NR_SYSV_pwrite (__NR_SYSV + 188) + +/* + * BSD 4.3 syscalls are in the range from 2000 to 2999 + */ +#define __NR_BSD43 2000 +#define __NR_BSD43_syscall (__NR_BSD43 + 0) +#define __NR_BSD43_exit (__NR_BSD43 + 1) +#define __NR_BSD43_fork (__NR_BSD43 + 2) +#define __NR_BSD43_read (__NR_BSD43 + 3) +#define __NR_BSD43_write (__NR_BSD43 + 4) +#define __NR_BSD43_open (__NR_BSD43 + 5) +#define __NR_BSD43_close (__NR_BSD43 + 6) +#define __NR_BSD43_wait (__NR_BSD43 + 7) +#define __NR_BSD43_creat (__NR_BSD43 + 8) +#define __NR_BSD43_link (__NR_BSD43 + 9) +#define __NR_BSD43_unlink (__NR_BSD43 + 10) +#define __NR_BSD43_exec (__NR_BSD43 + 11) +#define __NR_BSD43_chdir (__NR_BSD43 + 12) +#define __NR_BSD43_time (__NR_BSD43 + 13) +#define __NR_BSD43_mknod (__NR_BSD43 + 14) +#define __NR_BSD43_chmod (__NR_BSD43 + 15) +#define __NR_BSD43_chown (__NR_BSD43 + 16) +#define __NR_BSD43_sbreak (__NR_BSD43 + 17) +#define __NR_BSD43_oldstat (__NR_BSD43 + 18) +#define __NR_BSD43_lseek (__NR_BSD43 + 19) +#define __NR_BSD43_getpid (__NR_BSD43 + 20) +#define __NR_BSD43_oldmount (__NR_BSD43 + 21) +#define __NR_BSD43_umount (__NR_BSD43 + 22) +#define __NR_BSD43_setuid (__NR_BSD43 + 23) +#define __NR_BSD43_getuid (__NR_BSD43 + 24) +#define __NR_BSD43_stime (__NR_BSD43 + 25) +#define __NR_BSD43_ptrace (__NR_BSD43 + 26) +#define __NR_BSD43_alarm (__NR_BSD43 + 27) +#define __NR_BSD43_oldfstat (__NR_BSD43 + 28) +#define __NR_BSD43_pause (__NR_BSD43 + 29) +#define __NR_BSD43_utime (__NR_BSD43 + 30) +#define __NR_BSD43_stty (__NR_BSD43 + 31) +#define __NR_BSD43_gtty (__NR_BSD43 + 32) +#define __NR_BSD43_access (__NR_BSD43 + 33) +#define __NR_BSD43_nice (__NR_BSD43 + 34) +#define __NR_BSD43_ftime (__NR_BSD43 + 35) +#define __NR_BSD43_sync (__NR_BSD43 + 36) +#define __NR_BSD43_kill (__NR_BSD43 + 37) +#define __NR_BSD43_stat (__NR_BSD43 + 38) +#define __NR_BSD43_oldsetpgrp (__NR_BSD43 + 39) +#define __NR_BSD43_lstat (__NR_BSD43 + 40) +#define __NR_BSD43_dup (__NR_BSD43 + 41) +#define __NR_BSD43_pipe (__NR_BSD43 + 42) +#define __NR_BSD43_times (__NR_BSD43 + 43) +#define __NR_BSD43_profil (__NR_BSD43 + 44) +#define __NR_BSD43_msgsys (__NR_BSD43 + 45) +#define __NR_BSD43_setgid (__NR_BSD43 + 46) +#define __NR_BSD43_getgid (__NR_BSD43 + 47) +#define __NR_BSD43_ssig (__NR_BSD43 + 48) +#define __NR_BSD43_reserved1 (__NR_BSD43 + 49) +#define __NR_BSD43_reserved2 (__NR_BSD43 + 50) +#define __NR_BSD43_sysacct (__NR_BSD43 + 51) +#define __NR_BSD43_phys (__NR_BSD43 + 52) +#define __NR_BSD43_lock (__NR_BSD43 + 53) +#define __NR_BSD43_ioctl (__NR_BSD43 + 54) +#define __NR_BSD43_reboot (__NR_BSD43 + 55) +#define __NR_BSD43_mpxchan (__NR_BSD43 + 56) +#define __NR_BSD43_symlink (__NR_BSD43 + 57) +#define __NR_BSD43_readlink (__NR_BSD43 + 58) +#define __NR_BSD43_execve (__NR_BSD43 + 59) +#define __NR_BSD43_umask (__NR_BSD43 + 60) +#define __NR_BSD43_chroot (__NR_BSD43 + 61) +#define __NR_BSD43_fstat (__NR_BSD43 + 62) +#define __NR_BSD43_reserved3 (__NR_BSD43 + 63) +#define __NR_BSD43_getpagesize (__NR_BSD43 + 64) +#define __NR_BSD43_mremap (__NR_BSD43 + 65) +#define __NR_BSD43_vfork (__NR_BSD43 + 66) +#define __NR_BSD43_vread (__NR_BSD43 + 67) +#define __NR_BSD43_vwrite (__NR_BSD43 + 68) +#define __NR_BSD43_sbrk (__NR_BSD43 + 69) +#define __NR_BSD43_sstk (__NR_BSD43 + 70) +#define __NR_BSD43_mmap (__NR_BSD43 + 71) +#define __NR_BSD43_vadvise (__NR_BSD43 + 72) +#define __NR_BSD43_munmap (__NR_BSD43 + 73) +#define __NR_BSD43_mprotect (__NR_BSD43 + 74) +#define __NR_BSD43_madvise (__NR_BSD43 + 75) +#define __NR_BSD43_vhangup (__NR_BSD43 + 76) +#define __NR_BSD43_vlimit (__NR_BSD43 + 77) +#define __NR_BSD43_mincore (__NR_BSD43 + 78) +#define __NR_BSD43_getgroups (__NR_BSD43 + 79) +#define __NR_BSD43_setgroups (__NR_BSD43 + 80) +#define __NR_BSD43_getpgrp (__NR_BSD43 + 81) +#define __NR_BSD43_setpgrp (__NR_BSD43 + 82) +#define __NR_BSD43_setitimer (__NR_BSD43 + 83) +#define __NR_BSD43_wait3 (__NR_BSD43 + 84) +#define __NR_BSD43_swapon (__NR_BSD43 + 85) +#define __NR_BSD43_getitimer (__NR_BSD43 + 86) +#define __NR_BSD43_gethostname (__NR_BSD43 + 87) +#define __NR_BSD43_sethostname (__NR_BSD43 + 88) +#define __NR_BSD43_getdtablesize (__NR_BSD43 + 89) +#define __NR_BSD43_dup2 (__NR_BSD43 + 90) +#define __NR_BSD43_getdopt (__NR_BSD43 + 91) +#define __NR_BSD43_fcntl (__NR_BSD43 + 92) +#define __NR_BSD43_select (__NR_BSD43 + 93) +#define __NR_BSD43_setdopt (__NR_BSD43 + 94) +#define __NR_BSD43_fsync (__NR_BSD43 + 95) +#define __NR_BSD43_setpriority (__NR_BSD43 + 96) +#define __NR_BSD43_socket (__NR_BSD43 + 97) +#define __NR_BSD43_connect (__NR_BSD43 + 98) +#define __NR_BSD43_oldaccept (__NR_BSD43 + 99) +#define __NR_BSD43_getpriority (__NR_BSD43 + 100) +#define __NR_BSD43_send (__NR_BSD43 + 101) +#define __NR_BSD43_recv (__NR_BSD43 + 102) +#define __NR_BSD43_sigreturn (__NR_BSD43 + 103) +#define __NR_BSD43_bind (__NR_BSD43 + 104) +#define __NR_BSD43_setsockopt (__NR_BSD43 + 105) +#define __NR_BSD43_listen (__NR_BSD43 + 106) +#define __NR_BSD43_vtimes (__NR_BSD43 + 107) +#define __NR_BSD43_sigvec (__NR_BSD43 + 108) +#define __NR_BSD43_sigblock (__NR_BSD43 + 109) +#define __NR_BSD43_sigsetmask (__NR_BSD43 + 110) +#define __NR_BSD43_sigpause (__NR_BSD43 + 111) +#define __NR_BSD43_sigstack (__NR_BSD43 + 112) +#define __NR_BSD43_oldrecvmsg (__NR_BSD43 + 113) +#define __NR_BSD43_oldsendmsg (__NR_BSD43 + 114) +#define __NR_BSD43_vtrace (__NR_BSD43 + 115) +#define __NR_BSD43_gettimeofday (__NR_BSD43 + 116) +#define __NR_BSD43_getrusage (__NR_BSD43 + 117) +#define __NR_BSD43_getsockopt (__NR_BSD43 + 118) +#define __NR_BSD43_reserved4 (__NR_BSD43 + 119) +#define __NR_BSD43_readv (__NR_BSD43 + 120) +#define __NR_BSD43_writev (__NR_BSD43 + 121) +#define __NR_BSD43_settimeofday (__NR_BSD43 + 122) +#define __NR_BSD43_fchown (__NR_BSD43 + 123) +#define __NR_BSD43_fchmod (__NR_BSD43 + 124) +#define __NR_BSD43_oldrecvfrom (__NR_BSD43 + 125) +#define __NR_BSD43_setreuid (__NR_BSD43 + 126) +#define __NR_BSD43_setregid (__NR_BSD43 + 127) +#define __NR_BSD43_rename (__NR_BSD43 + 128) +#define __NR_BSD43_truncate (__NR_BSD43 + 129) +#define __NR_BSD43_ftruncate (__NR_BSD43 + 130) +#define __NR_BSD43_flock (__NR_BSD43 + 131) +#define __NR_BSD43_semsys (__NR_BSD43 + 132) +#define __NR_BSD43_sendto (__NR_BSD43 + 133) +#define __NR_BSD43_shutdown (__NR_BSD43 + 134) +#define __NR_BSD43_socketpair (__NR_BSD43 + 135) +#define __NR_BSD43_mkdir (__NR_BSD43 + 136) +#define __NR_BSD43_rmdir (__NR_BSD43 + 137) +#define __NR_BSD43_utimes (__NR_BSD43 + 138) +#define __NR_BSD43_sigcleanup (__NR_BSD43 + 139) +#define __NR_BSD43_adjtime (__NR_BSD43 + 140) +#define __NR_BSD43_oldgetpeername (__NR_BSD43 + 141) +#define __NR_BSD43_gethostid (__NR_BSD43 + 142) +#define __NR_BSD43_sethostid (__NR_BSD43 + 143) +#define __NR_BSD43_getrlimit (__NR_BSD43 + 144) +#define __NR_BSD43_setrlimit (__NR_BSD43 + 145) +#define __NR_BSD43_killpg (__NR_BSD43 + 146) +#define __NR_BSD43_shmsys (__NR_BSD43 + 147) +#define __NR_BSD43_quota (__NR_BSD43 + 148) +#define __NR_BSD43_qquota (__NR_BSD43 + 149) +#define __NR_BSD43_oldgetsockname (__NR_BSD43 + 150) +#define __NR_BSD43_sysmips (__NR_BSD43 + 151) +#define __NR_BSD43_cacheflush (__NR_BSD43 + 152) +#define __NR_BSD43_cachectl (__NR_BSD43 + 153) +#define __NR_BSD43_debug (__NR_BSD43 + 154) +#define __NR_BSD43_reserved5 (__NR_BSD43 + 155) +#define __NR_BSD43_reserved6 (__NR_BSD43 + 156) +#define __NR_BSD43_nfs_mount (__NR_BSD43 + 157) +#define __NR_BSD43_nfs_svc (__NR_BSD43 + 158) +#define __NR_BSD43_getdirentries (__NR_BSD43 + 159) +#define __NR_BSD43_statfs (__NR_BSD43 + 160) +#define __NR_BSD43_fstatfs (__NR_BSD43 + 161) +#define __NR_BSD43_unmount (__NR_BSD43 + 162) +#define __NR_BSD43_async_daemon (__NR_BSD43 + 163) +#define __NR_BSD43_nfs_getfh (__NR_BSD43 + 164) +#define __NR_BSD43_getdomainname (__NR_BSD43 + 165) +#define __NR_BSD43_setdomainname (__NR_BSD43 + 166) +#define __NR_BSD43_pcfs_mount (__NR_BSD43 + 167) +#define __NR_BSD43_quotactl (__NR_BSD43 + 168) +#define __NR_BSD43_oldexportfs (__NR_BSD43 + 169) +#define __NR_BSD43_smount (__NR_BSD43 + 170) +#define __NR_BSD43_mipshwconf (__NR_BSD43 + 171) +#define __NR_BSD43_exportfs (__NR_BSD43 + 172) +#define __NR_BSD43_nfsfh_open (__NR_BSD43 + 173) +#define __NR_BSD43_libattach (__NR_BSD43 + 174) +#define __NR_BSD43_libdetach (__NR_BSD43 + 175) +#define __NR_BSD43_accept (__NR_BSD43 + 176) +#define __NR_BSD43_reserved7 (__NR_BSD43 + 177) +#define __NR_BSD43_reserved8 (__NR_BSD43 + 178) +#define __NR_BSD43_recvmsg (__NR_BSD43 + 179) +#define __NR_BSD43_recvfrom (__NR_BSD43 + 180) +#define __NR_BSD43_sendmsg (__NR_BSD43 + 181) +#define __NR_BSD43_getpeername (__NR_BSD43 + 182) +#define __NR_BSD43_getsockname (__NR_BSD43 + 183) +#define __NR_BSD43_aread (__NR_BSD43 + 184) +#define __NR_BSD43_awrite (__NR_BSD43 + 185) +#define __NR_BSD43_listio (__NR_BSD43 + 186) +#define __NR_BSD43_acancel (__NR_BSD43 + 187) +#define __NR_BSD43_astatus (__NR_BSD43 + 188) +#define __NR_BSD43_await (__NR_BSD43 + 189) +#define __NR_BSD43_areadv (__NR_BSD43 + 190) +#define __NR_BSD43_awritev (__NR_BSD43 + 191) + +/* + * POSIX syscalls are in the range from 3000 to 3999 + */ +#define __NR_POSIX 3000 +#define __NR_POSIX_syscall (__NR_POSIX + 0) +#define __NR_POSIX_exit (__NR_POSIX + 1) +#define __NR_POSIX_fork (__NR_POSIX + 2) +#define __NR_POSIX_read (__NR_POSIX + 3) +#define __NR_POSIX_write (__NR_POSIX + 4) +#define __NR_POSIX_open (__NR_POSIX + 5) +#define __NR_POSIX_close (__NR_POSIX + 6) +#define __NR_POSIX_wait (__NR_POSIX + 7) +#define __NR_POSIX_creat (__NR_POSIX + 8) +#define __NR_POSIX_link (__NR_POSIX + 9) +#define __NR_POSIX_unlink (__NR_POSIX + 10) +#define __NR_POSIX_exec (__NR_POSIX + 11) +#define __NR_POSIX_chdir (__NR_POSIX + 12) +#define __NR_POSIX_gtime (__NR_POSIX + 13) +#define __NR_POSIX_mknod (__NR_POSIX + 14) +#define __NR_POSIX_chmod (__NR_POSIX + 15) +#define __NR_POSIX_chown (__NR_POSIX + 16) +#define __NR_POSIX_sbreak (__NR_POSIX + 17) +#define __NR_POSIX_stat (__NR_POSIX + 18) +#define __NR_POSIX_lseek (__NR_POSIX + 19) +#define __NR_POSIX_getpid (__NR_POSIX + 20) +#define __NR_POSIX_mount (__NR_POSIX + 21) +#define __NR_POSIX_umount (__NR_POSIX + 22) +#define __NR_POSIX_setuid (__NR_POSIX + 23) +#define __NR_POSIX_getuid (__NR_POSIX + 24) +#define __NR_POSIX_stime (__NR_POSIX + 25) +#define __NR_POSIX_ptrace (__NR_POSIX + 26) +#define __NR_POSIX_alarm (__NR_POSIX + 27) +#define __NR_POSIX_fstat (__NR_POSIX + 28) +#define __NR_POSIX_pause (__NR_POSIX + 29) +#define __NR_POSIX_utime (__NR_POSIX + 30) +#define __NR_POSIX_stty (__NR_POSIX + 31) +#define __NR_POSIX_gtty (__NR_POSIX + 32) +#define __NR_POSIX_access (__NR_POSIX + 33) +#define __NR_POSIX_nice (__NR_POSIX + 34) +#define __NR_POSIX_statfs (__NR_POSIX + 35) +#define __NR_POSIX_sync (__NR_POSIX + 36) +#define __NR_POSIX_kill (__NR_POSIX + 37) +#define __NR_POSIX_fstatfs (__NR_POSIX + 38) +#define __NR_POSIX_getpgrp (__NR_POSIX + 39) +#define __NR_POSIX_syssgi (__NR_POSIX + 40) +#define __NR_POSIX_dup (__NR_POSIX + 41) +#define __NR_POSIX_pipe (__NR_POSIX + 42) +#define __NR_POSIX_times (__NR_POSIX + 43) +#define __NR_POSIX_profil (__NR_POSIX + 44) +#define __NR_POSIX_lock (__NR_POSIX + 45) +#define __NR_POSIX_setgid (__NR_POSIX + 46) +#define __NR_POSIX_getgid (__NR_POSIX + 47) +#define __NR_POSIX_sig (__NR_POSIX + 48) +#define __NR_POSIX_msgsys (__NR_POSIX + 49) +#define __NR_POSIX_sysmips (__NR_POSIX + 50) +#define __NR_POSIX_sysacct (__NR_POSIX + 51) +#define __NR_POSIX_shmsys (__NR_POSIX + 52) +#define __NR_POSIX_semsys (__NR_POSIX + 53) +#define __NR_POSIX_ioctl (__NR_POSIX + 54) +#define __NR_POSIX_uadmin (__NR_POSIX + 55) +#define __NR_POSIX_exch (__NR_POSIX + 56) +#define __NR_POSIX_utssys (__NR_POSIX + 57) +#define __NR_POSIX_USG_reserved1 (__NR_POSIX + 58) +#define __NR_POSIX_exece (__NR_POSIX + 59) +#define __NR_POSIX_umask (__NR_POSIX + 60) +#define __NR_POSIX_chroot (__NR_POSIX + 61) +#define __NR_POSIX_fcntl (__NR_POSIX + 62) +#define __NR_POSIX_ulimit (__NR_POSIX + 63) +#define __NR_POSIX_SAFARI4_reserved1 (__NR_POSIX + 64) +#define __NR_POSIX_SAFARI4_reserved2 (__NR_POSIX + 65) +#define __NR_POSIX_SAFARI4_reserved3 (__NR_POSIX + 66) +#define __NR_POSIX_SAFARI4_reserved4 (__NR_POSIX + 67) +#define __NR_POSIX_SAFARI4_reserved5 (__NR_POSIX + 68) +#define __NR_POSIX_SAFARI4_reserved6 (__NR_POSIX + 69) +#define __NR_POSIX_advfs (__NR_POSIX + 70) +#define __NR_POSIX_unadvfs (__NR_POSIX + 71) +#define __NR_POSIX_rmount (__NR_POSIX + 72) +#define __NR_POSIX_rumount (__NR_POSIX + 73) +#define __NR_POSIX_rfstart (__NR_POSIX + 74) +#define __NR_POSIX_reserved1 (__NR_POSIX + 75) +#define __NR_POSIX_rdebug (__NR_POSIX + 76) +#define __NR_POSIX_rfstop (__NR_POSIX + 77) +#define __NR_POSIX_rfsys (__NR_POSIX + 78) +#define __NR_POSIX_rmdir (__NR_POSIX + 79) +#define __NR_POSIX_mkdir (__NR_POSIX + 80) +#define __NR_POSIX_getdents (__NR_POSIX + 81) +#define __NR_POSIX_sginap (__NR_POSIX + 82) +#define __NR_POSIX_sgikopt (__NR_POSIX + 83) +#define __NR_POSIX_sysfs (__NR_POSIX + 84) +#define __NR_POSIX_getmsg (__NR_POSIX + 85) +#define __NR_POSIX_putmsg (__NR_POSIX + 86) +#define __NR_POSIX_poll (__NR_POSIX + 87) +#define __NR_POSIX_sigreturn (__NR_POSIX + 88) +#define __NR_POSIX_accept (__NR_POSIX + 89) +#define __NR_POSIX_bind (__NR_POSIX + 90) +#define __NR_POSIX_connect (__NR_POSIX + 91) +#define __NR_POSIX_gethostid (__NR_POSIX + 92) +#define __NR_POSIX_getpeername (__NR_POSIX + 93) +#define __NR_POSIX_getsockname (__NR_POSIX + 94) +#define __NR_POSIX_getsockopt (__NR_POSIX + 95) +#define __NR_POSIX_listen (__NR_POSIX + 96) +#define __NR_POSIX_recv (__NR_POSIX + 97) +#define __NR_POSIX_recvfrom (__NR_POSIX + 98) +#define __NR_POSIX_recvmsg (__NR_POSIX + 99) +#define __NR_POSIX_select (__NR_POSIX + 100) +#define __NR_POSIX_send (__NR_POSIX + 101) +#define __NR_POSIX_sendmsg (__NR_POSIX + 102) +#define __NR_POSIX_sendto (__NR_POSIX + 103) +#define __NR_POSIX_sethostid (__NR_POSIX + 104) +#define __NR_POSIX_setsockopt (__NR_POSIX + 105) +#define __NR_POSIX_shutdown (__NR_POSIX + 106) +#define __NR_POSIX_socket (__NR_POSIX + 107) +#define __NR_POSIX_gethostname (__NR_POSIX + 108) +#define __NR_POSIX_sethostname (__NR_POSIX + 109) +#define __NR_POSIX_getdomainname (__NR_POSIX + 110) +#define __NR_POSIX_setdomainname (__NR_POSIX + 111) +#define __NR_POSIX_truncate (__NR_POSIX + 112) +#define __NR_POSIX_ftruncate (__NR_POSIX + 113) +#define __NR_POSIX_rename (__NR_POSIX + 114) +#define __NR_POSIX_symlink (__NR_POSIX + 115) +#define __NR_POSIX_readlink (__NR_POSIX + 116) +#define __NR_POSIX_lstat (__NR_POSIX + 117) +#define __NR_POSIX_nfs_mount (__NR_POSIX + 118) +#define __NR_POSIX_nfs_svc (__NR_POSIX + 119) +#define __NR_POSIX_nfs_getfh (__NR_POSIX + 120) +#define __NR_POSIX_async_daemon (__NR_POSIX + 121) +#define __NR_POSIX_exportfs (__NR_POSIX + 122) +#define __NR_POSIX_SGI_setregid (__NR_POSIX + 123) +#define __NR_POSIX_SGI_setreuid (__NR_POSIX + 124) +#define __NR_POSIX_getitimer (__NR_POSIX + 125) +#define __NR_POSIX_setitimer (__NR_POSIX + 126) +#define __NR_POSIX_adjtime (__NR_POSIX + 127) +#define __NR_POSIX_SGI_bsdgettime (__NR_POSIX + 128) +#define __NR_POSIX_SGI_sproc (__NR_POSIX + 129) +#define __NR_POSIX_SGI_prctl (__NR_POSIX + 130) +#define __NR_POSIX_SGI_blkproc (__NR_POSIX + 131) +#define __NR_POSIX_SGI_reserved1 (__NR_POSIX + 132) +#define __NR_POSIX_SGI_sgigsc (__NR_POSIX + 133) +#define __NR_POSIX_SGI_mmap (__NR_POSIX + 134) +#define __NR_POSIX_SGI_munmap (__NR_POSIX + 135) +#define __NR_POSIX_SGI_mprotect (__NR_POSIX + 136) +#define __NR_POSIX_SGI_msync (__NR_POSIX + 137) +#define __NR_POSIX_SGI_madvise (__NR_POSIX + 138) +#define __NR_POSIX_SGI_mpin (__NR_POSIX + 139) +#define __NR_POSIX_SGI_getpagesize (__NR_POSIX + 140) +#define __NR_POSIX_SGI_libattach (__NR_POSIX + 141) +#define __NR_POSIX_SGI_libdetach (__NR_POSIX + 142) +#define __NR_POSIX_SGI_getpgrp (__NR_POSIX + 143) +#define __NR_POSIX_SGI_setpgrp (__NR_POSIX + 144) +#define __NR_POSIX_SGI_reserved2 (__NR_POSIX + 145) +#define __NR_POSIX_SGI_reserved3 (__NR_POSIX + 146) +#define __NR_POSIX_SGI_reserved4 (__NR_POSIX + 147) +#define __NR_POSIX_SGI_reserved5 (__NR_POSIX + 148) +#define __NR_POSIX_SGI_reserved6 (__NR_POSIX + 149) +#define __NR_POSIX_cacheflush (__NR_POSIX + 150) +#define __NR_POSIX_cachectl (__NR_POSIX + 151) +#define __NR_POSIX_fchown (__NR_POSIX + 152) +#define __NR_POSIX_fchmod (__NR_POSIX + 153) +#define __NR_POSIX_wait3 (__NR_POSIX + 154) +#define __NR_POSIX_mmap (__NR_POSIX + 155) +#define __NR_POSIX_munmap (__NR_POSIX + 156) +#define __NR_POSIX_madvise (__NR_POSIX + 157) +#define __NR_POSIX_BSD_getpagesize (__NR_POSIX + 158) +#define __NR_POSIX_setreuid (__NR_POSIX + 159) +#define __NR_POSIX_setregid (__NR_POSIX + 160) +#define __NR_POSIX_setpgid (__NR_POSIX + 161) +#define __NR_POSIX_getgroups (__NR_POSIX + 162) +#define __NR_POSIX_setgroups (__NR_POSIX + 163) +#define __NR_POSIX_gettimeofday (__NR_POSIX + 164) +#define __NR_POSIX_getrusage (__NR_POSIX + 165) +#define __NR_POSIX_getrlimit (__NR_POSIX + 166) +#define __NR_POSIX_setrlimit (__NR_POSIX + 167) +#define __NR_POSIX_waitpid (__NR_POSIX + 168) +#define __NR_POSIX_dup2 (__NR_POSIX + 169) +#define __NR_POSIX_reserved2 (__NR_POSIX + 170) +#define __NR_POSIX_reserved3 (__NR_POSIX + 171) +#define __NR_POSIX_reserved4 (__NR_POSIX + 172) +#define __NR_POSIX_reserved5 (__NR_POSIX + 173) +#define __NR_POSIX_reserved6 (__NR_POSIX + 174) +#define __NR_POSIX_reserved7 (__NR_POSIX + 175) +#define __NR_POSIX_reserved8 (__NR_POSIX + 176) +#define __NR_POSIX_reserved9 (__NR_POSIX + 177) +#define __NR_POSIX_reserved10 (__NR_POSIX + 178) +#define __NR_POSIX_reserved11 (__NR_POSIX + 179) +#define __NR_POSIX_reserved12 (__NR_POSIX + 180) +#define __NR_POSIX_reserved13 (__NR_POSIX + 181) +#define __NR_POSIX_reserved14 (__NR_POSIX + 182) +#define __NR_POSIX_reserved15 (__NR_POSIX + 183) +#define __NR_POSIX_reserved16 (__NR_POSIX + 184) +#define __NR_POSIX_reserved17 (__NR_POSIX + 185) +#define __NR_POSIX_reserved18 (__NR_POSIX + 186) +#define __NR_POSIX_reserved19 (__NR_POSIX + 187) +#define __NR_POSIX_reserved20 (__NR_POSIX + 188) +#define __NR_POSIX_reserved21 (__NR_POSIX + 189) +#define __NR_POSIX_reserved22 (__NR_POSIX + 190) +#define __NR_POSIX_reserved23 (__NR_POSIX + 191) +#define __NR_POSIX_reserved24 (__NR_POSIX + 192) +#define __NR_POSIX_reserved25 (__NR_POSIX + 193) +#define __NR_POSIX_reserved26 (__NR_POSIX + 194) +#define __NR_POSIX_reserved27 (__NR_POSIX + 195) +#define __NR_POSIX_reserved28 (__NR_POSIX + 196) +#define __NR_POSIX_reserved29 (__NR_POSIX + 197) +#define __NR_POSIX_reserved30 (__NR_POSIX + 198) +#define __NR_POSIX_reserved31 (__NR_POSIX + 199) +#define __NR_POSIX_reserved32 (__NR_POSIX + 200) +#define __NR_POSIX_reserved33 (__NR_POSIX + 201) +#define __NR_POSIX_reserved34 (__NR_POSIX + 202) +#define __NR_POSIX_reserved35 (__NR_POSIX + 203) +#define __NR_POSIX_reserved36 (__NR_POSIX + 204) +#define __NR_POSIX_reserved37 (__NR_POSIX + 205) +#define __NR_POSIX_reserved38 (__NR_POSIX + 206) +#define __NR_POSIX_reserved39 (__NR_POSIX + 207) +#define __NR_POSIX_reserved40 (__NR_POSIX + 208) +#define __NR_POSIX_reserved41 (__NR_POSIX + 209) +#define __NR_POSIX_reserved42 (__NR_POSIX + 210) +#define __NR_POSIX_reserved43 (__NR_POSIX + 211) +#define __NR_POSIX_reserved44 (__NR_POSIX + 212) +#define __NR_POSIX_reserved45 (__NR_POSIX + 213) +#define __NR_POSIX_reserved46 (__NR_POSIX + 214) +#define __NR_POSIX_reserved47 (__NR_POSIX + 215) +#define __NR_POSIX_reserved48 (__NR_POSIX + 216) +#define __NR_POSIX_reserved49 (__NR_POSIX + 217) +#define __NR_POSIX_reserved50 (__NR_POSIX + 218) +#define __NR_POSIX_reserved51 (__NR_POSIX + 219) +#define __NR_POSIX_reserved52 (__NR_POSIX + 220) +#define __NR_POSIX_reserved53 (__NR_POSIX + 221) +#define __NR_POSIX_reserved54 (__NR_POSIX + 222) +#define __NR_POSIX_reserved55 (__NR_POSIX + 223) +#define __NR_POSIX_reserved56 (__NR_POSIX + 224) +#define __NR_POSIX_reserved57 (__NR_POSIX + 225) +#define __NR_POSIX_reserved58 (__NR_POSIX + 226) +#define __NR_POSIX_reserved59 (__NR_POSIX + 227) +#define __NR_POSIX_reserved60 (__NR_POSIX + 228) +#define __NR_POSIX_reserved61 (__NR_POSIX + 229) +#define __NR_POSIX_reserved62 (__NR_POSIX + 230) +#define __NR_POSIX_reserved63 (__NR_POSIX + 231) +#define __NR_POSIX_reserved64 (__NR_POSIX + 232) +#define __NR_POSIX_reserved65 (__NR_POSIX + 233) +#define __NR_POSIX_reserved66 (__NR_POSIX + 234) +#define __NR_POSIX_reserved67 (__NR_POSIX + 235) +#define __NR_POSIX_reserved68 (__NR_POSIX + 236) +#define __NR_POSIX_reserved69 (__NR_POSIX + 237) +#define __NR_POSIX_reserved70 (__NR_POSIX + 238) +#define __NR_POSIX_reserved71 (__NR_POSIX + 239) +#define __NR_POSIX_reserved72 (__NR_POSIX + 240) +#define __NR_POSIX_reserved73 (__NR_POSIX + 241) +#define __NR_POSIX_reserved74 (__NR_POSIX + 242) +#define __NR_POSIX_reserved75 (__NR_POSIX + 243) +#define __NR_POSIX_reserved76 (__NR_POSIX + 244) +#define __NR_POSIX_reserved77 (__NR_POSIX + 245) +#define __NR_POSIX_reserved78 (__NR_POSIX + 246) +#define __NR_POSIX_reserved79 (__NR_POSIX + 247) +#define __NR_POSIX_reserved80 (__NR_POSIX + 248) +#define __NR_POSIX_reserved81 (__NR_POSIX + 249) +#define __NR_POSIX_reserved82 (__NR_POSIX + 250) +#define __NR_POSIX_reserved83 (__NR_POSIX + 251) +#define __NR_POSIX_reserved84 (__NR_POSIX + 252) +#define __NR_POSIX_reserved85 (__NR_POSIX + 253) +#define __NR_POSIX_reserved86 (__NR_POSIX + 254) +#define __NR_POSIX_reserved87 (__NR_POSIX + 255) +#define __NR_POSIX_reserved88 (__NR_POSIX + 256) +#define __NR_POSIX_reserved89 (__NR_POSIX + 257) +#define __NR_POSIX_reserved90 (__NR_POSIX + 258) +#define __NR_POSIX_reserved91 (__NR_POSIX + 259) +#define __NR_POSIX_netboot (__NR_POSIX + 260) +#define __NR_POSIX_netunboot (__NR_POSIX + 261) +#define __NR_POSIX_rdump (__NR_POSIX + 262) +#define __NR_POSIX_setsid (__NR_POSIX + 263) +#define __NR_POSIX_getmaxsig (__NR_POSIX + 264) +#define __NR_POSIX_sigpending (__NR_POSIX + 265) +#define __NR_POSIX_sigprocmask (__NR_POSIX + 266) +#define __NR_POSIX_sigsuspend (__NR_POSIX + 267) +#define __NR_POSIX_sigaction (__NR_POSIX + 268) +#define __NR_POSIX_MIPS_reserved1 (__NR_POSIX + 269) +#define __NR_POSIX_MIPS_reserved2 (__NR_POSIX + 270) +#define __NR_POSIX_MIPS_reserved3 (__NR_POSIX + 271) +#define __NR_POSIX_MIPS_reserved4 (__NR_POSIX + 272) +#define __NR_POSIX_MIPS_reserved5 (__NR_POSIX + 273) +#define __NR_POSIX_MIPS_reserved6 (__NR_POSIX + 274) +#define __NR_POSIX_MIPS_reserved7 (__NR_POSIX + 275) +#define __NR_POSIX_MIPS_reserved8 (__NR_POSIX + 276) +#define __NR_POSIX_MIPS_reserved9 (__NR_POSIX + 277) +#define __NR_POSIX_MIPS_reserved10 (__NR_POSIX + 278) +#define __NR_POSIX_MIPS_reserved11 (__NR_POSIX + 279) +#define __NR_POSIX_TANDEM_reserved1 (__NR_POSIX + 280) +#define __NR_POSIX_TANDEM_reserved2 (__NR_POSIX + 281) +#define __NR_POSIX_TANDEM_reserved3 (__NR_POSIX + 282) +#define __NR_POSIX_TANDEM_reserved4 (__NR_POSIX + 283) +#define __NR_POSIX_TANDEM_reserved5 (__NR_POSIX + 284) +#define __NR_POSIX_TANDEM_reserved6 (__NR_POSIX + 285) +#define __NR_POSIX_TANDEM_reserved7 (__NR_POSIX + 286) +#define __NR_POSIX_TANDEM_reserved8 (__NR_POSIX + 287) +#define __NR_POSIX_TANDEM_reserved9 (__NR_POSIX + 288) +#define __NR_POSIX_TANDEM_reserved10 (__NR_POSIX + 289) +#define __NR_POSIX_TANDEM_reserved11 (__NR_POSIX + 290) +#define __NR_POSIX_TANDEM_reserved12 (__NR_POSIX + 291) +#define __NR_POSIX_TANDEM_reserved13 (__NR_POSIX + 292) +#define __NR_POSIX_TANDEM_reserved14 (__NR_POSIX + 293) +#define __NR_POSIX_TANDEM_reserved15 (__NR_POSIX + 294) +#define __NR_POSIX_TANDEM_reserved16 (__NR_POSIX + 295) +#define __NR_POSIX_TANDEM_reserved17 (__NR_POSIX + 296) +#define __NR_POSIX_TANDEM_reserved18 (__NR_POSIX + 297) +#define __NR_POSIX_TANDEM_reserved19 (__NR_POSIX + 298) +#define __NR_POSIX_TANDEM_reserved20 (__NR_POSIX + 299) +#define __NR_POSIX_SGI_reserved7 (__NR_POSIX + 300) +#define __NR_POSIX_SGI_reserved8 (__NR_POSIX + 301) +#define __NR_POSIX_SGI_reserved9 (__NR_POSIX + 302) +#define __NR_POSIX_SGI_reserved10 (__NR_POSIX + 303) +#define __NR_POSIX_SGI_reserved11 (__NR_POSIX + 304) +#define __NR_POSIX_SGI_reserved12 (__NR_POSIX + 305) +#define __NR_POSIX_SGI_reserved13 (__NR_POSIX + 306) +#define __NR_POSIX_SGI_reserved14 (__NR_POSIX + 307) +#define __NR_POSIX_SGI_reserved15 (__NR_POSIX + 308) +#define __NR_POSIX_SGI_reserved16 (__NR_POSIX + 309) +#define __NR_POSIX_SGI_reserved17 (__NR_POSIX + 310) +#define __NR_POSIX_SGI_reserved18 (__NR_POSIX + 311) +#define __NR_POSIX_SGI_reserved19 (__NR_POSIX + 312) +#define __NR_POSIX_SGI_reserved20 (__NR_POSIX + 313) +#define __NR_POSIX_SGI_reserved21 (__NR_POSIX + 314) +#define __NR_POSIX_SGI_reserved22 (__NR_POSIX + 315) +#define __NR_POSIX_SGI_reserved23 (__NR_POSIX + 316) +#define __NR_POSIX_SGI_reserved24 (__NR_POSIX + 317) +#define __NR_POSIX_SGI_reserved25 (__NR_POSIX + 318) +#define __NR_POSIX_SGI_reserved26 (__NR_POSIX + 319) + +#endif /* _ASM_RISCOS_SYSCALL_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/semaphore-helper.h linux/include/asm-mips/semaphore-helper.h --- v2.4.5/linux/include/asm-mips/semaphore-helper.h Sun Jul 9 22:18:15 2000 +++ linux/include/asm-mips/semaphore-helper.h Mon Jul 2 13:56:40 2001 @@ -1,11 +1,11 @@ -/* $Id: semaphore-helper.h,v 1.6 1999/10/20 21:10:58 ralf Exp $ - * +/* * SMP- and interrupt-safe semaphores helper functions. * - * (C) Copyright 1996 Linus Torvalds - * (C) Copyright 1999 Andrea Arcangeli - * (C) Copyright 1999 Ralf Baechle - * (C) Copyright 1999 Silicon Graphics, Inc. + * Copyright (C) 1996 Linus Torvalds + * Copyright (C) 1999 Andrea Arcangeli + * Copyright (C) 1999 Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 2000 MIPS Technologies, Inc. */ #ifndef _ASM_SEMAPHORE_HELPER_H #define _ASM_SEMAPHORE_HELPER_H @@ -20,7 +20,7 @@ atomic_inc(&sem->waking); } -#if !defined(CONFIG_CPU_HAS_LLSC) +#if !defined(CONFIG_CPU_HAS_LLSC) || defined(CONFIG_CPU_MIPS32) /* * It doesn't make sense, IMHO, to endlessly turn interrupts off and on again. @@ -75,6 +75,7 @@ ret = 0; } restore_flags(flags); + return ret; } @@ -92,7 +93,7 @@ "sc\t%0, %2\n\t" "beqz\t%0, 1b\n\t" "2:" - : "=r"(ret), "=r"(tmp), "=m"(__atomic_fool_gcc(&sem->waking)) + : "=r" (ret), "=r" (tmp), "=m" (sem->waking) : "0"(0)); return ret; @@ -133,29 +134,26 @@ { long ret, tmp; - __asm__ __volatile__(" - .set push - .set mips3 - .set noat -0: lld %1, %2 - li %0, 0 - sll $1, %1, 0 - blez $1, 1f - daddiu %1, %1, -1 - li %0, 1 - b 2f -1: - beqz %3, 2f - li %0, %4 - dli $1, 0x0000000100000000 - daddu %1, %1, $1 -2: - scd %1, %2 - beqz %1, 0b - - .set pop" - : "=&r"(ret), "=&r"(tmp), "=m"(*sem) - : "r"(signal_pending(tsk)), "i"(-EINTR)); + __asm__ __volatile__( + ".set\tpush\n\t" + ".set\tmips3\n\t" + ".set\tnoat\n" + "0:\tlld\t%1, %2\n\t" + "li\t%0, 0\n\t" + "sll\t$1, %1, 0\n\t" + "blez\t$1, 1f\n\t" + "daddiu\t%1, %1, -1\n\t" + "li\t%0, 1\n\t" + "b\t2f\n" + "1:\tbeqz\t%3, 2f\n\t" + "li\t%0, %4\n\t" + "dli\t$1, 0x0000000100000000\n\t" + "daddu\t%1, %1, $1\n" + "2:\tscd\t%1, %2\n\t" + "beqz\t%1, 0b\n\t" + ".set\tpop" + : "=&r" (ret), "=&r" (tmp), "=m" (*sem) + : "r" (signal_pending(tsk)), "i" (-EINTR)); return ret; } diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/semaphore.h linux/include/asm-mips/semaphore.h --- v2.4.5/linux/include/asm-mips/semaphore.h Tue Apr 17 17:19:31 2001 +++ linux/include/asm-mips/semaphore.h Mon Jul 2 13:56:40 2001 @@ -1,5 +1,4 @@ -/* $Id: semaphore.h,v 1.12 1999/12/08 22:05:10 harald Exp $ - * +/* * SMP- and interrupt-safe semaphores.. * * This file is subject to the terms and conditions of the GNU General Public @@ -9,6 +8,7 @@ * (C) Copyright 1996 Linus Torvalds * (C) Copyright 1998, 1999, 2000 Ralf Baechle * (C) Copyright 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. */ #ifndef _ASM_SEMAPHORE_H #define _ASM_SEMAPHORE_H @@ -60,7 +60,7 @@ #define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1) #define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0) -extern inline void sema_init (struct semaphore *sem, int val) +static inline void sema_init (struct semaphore *sem, int val) { atomic_set(&sem->count, val); atomic_set(&sem->waking, 0); @@ -85,7 +85,7 @@ asmlinkage int __down_trylock(struct semaphore * sem); asmlinkage void __up(struct semaphore * sem); -extern inline void down(struct semaphore * sem) +static inline void down(struct semaphore * sem) { #if WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); @@ -94,7 +94,7 @@ __down(sem); } -extern inline int down_interruptible(struct semaphore * sem) +static inline int down_interruptible(struct semaphore * sem) { int ret = 0; @@ -106,9 +106,9 @@ return ret; } -#if !defined(CONFIG_CPU_HAS_LLSC) +#if !defined(CONFIG_CPU_HAS_LLSC) || defined(CONFIG_CPU_MIPS32) -extern inline int down_trylock(struct semaphore * sem) +static inline int down_trylock(struct semaphore * sem) { int ret = 0; if (atomic_dec_return(&sem->count) < 0) @@ -140,7 +140,7 @@ * } * } */ -extern inline int down_trylock(struct semaphore * sem) +static inline int down_trylock(struct semaphore * sem) { long ret, tmp, tmp2, sub; @@ -148,29 +148,25 @@ CHECK_MAGIC(sem->__magic); #endif - __asm__ __volatile__(" - .set mips3 - - 0: lld %1, %4 - dli %3, 0x0000000100000000 - dsubu %1, %3 - li %0, 0 - bgez %1, 2f - sll %2, %1, 0 - blez %2, 1f - daddiu %1, %1, -1 - b 2f - 1: - daddu %1, %1, %3 - li %0, 1 - 2: - scd %1, %4 - beqz %1, 0b - - .set mips0" - : "=&r"(ret), "=&r"(tmp), "=&r"(tmp2), "=&r"(sub) - : "m"(*sem) - : "memory"); + __asm__ __volatile__( + ".set\tmips3\t\t\t# down_trylock\n" + "0:\tlld\t%1, %4\n\t" + "dli\t%3, 0x0000000100000000\n\t" + "dsubu\t%1, %3\n\t" + "li\t%0, 0\n\t" + "bgez\t%1, 2f\n\t" + "sll\t%2, %1, 0\n\t" + "blez\t%2, 1f\n\t" + "daddiu\t%1, %1, -1\n\t" + "b\t2f\n\t" + "1:\tdaddu\t%1, %1, %3\n" + "li\t%0, 1\n" + "2:\tscd\t%1, %4\n\t" + "beqz\t%1, 0b\n\t" + ".set mips0" + : "=&r"(ret), "=&r"(tmp), "=&r"(tmp2), "=&r"(sub) + : "m"(*sem) + : "memory"); return ret; } @@ -181,183 +177,13 @@ * Note! This is subtle. We jump to wake people up only if * the semaphore was negative (== somebody was waiting on it). */ -extern inline void up(struct semaphore * sem) +static inline void up(struct semaphore * sem) { #if WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); #endif if (atomic_inc_return(&sem->count) <= 0) __up(sem); -} - -/* - * rw mutexes (should that be mutices? =) -- throw rw spinlocks and - * semaphores together, and this is what we end up with... - * - * The lock is initialized to BIAS. This way, a writer subtracts BIAS ands - * gets 0 for the case of an uncontended lock. Readers decrement by 1 and - * see a positive value when uncontended, negative if there are writers - * waiting (in which case it goes to sleep). - * - * The value 0x01000000 supports up to 128 processors and lots of processes. - * BIAS must be chosen such that subtracting BIAS once per CPU will result - * in the int remaining negative. In terms of fairness, this should result - * in the lock flopping back and forth between readers and writers under - * heavy use. - * - * Once we start supporting machines with more than 128 CPUs, we should go - * for using a 64bit atomic type instead of 32bit as counter. We shall - * probably go for bias 0x80000000 then, so that single sethi can set it. - * */ - -#define RW_LOCK_BIAS 0x01000000 - -struct rw_semaphore { - atomic_t count; - /* bit 0 means read bias granted; - bit 1 means write bias granted. */ - unsigned long granted; /* pedant: long req'd for set_bit */ - wait_queue_head_t wait; - wait_queue_head_t write_bias_wait; -#if WAITQUEUE_DEBUG - long __magic; - atomic_t readers; - atomic_t writers; -#endif -}; - -#if WAITQUEUE_DEBUG -#define __RWSEM_DEBUG_INIT , ATOMIC_INIT(0), ATOMIC_INIT(0) -#else -#define __RWSEM_DEBUG_INIT /* */ -#endif - -#define __RWSEM_INITIALIZER(name,count) \ - { ATOMIC_INIT(count), 0, \ - __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \ - __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait) \ - __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT } - -#define __DECLARE_RWSEM_GENERIC(name,count) \ - struct rw_semaphore name = __RWSEM_INITIALIZER(name,count) - -#define DECLARE_RWSEM(name) \ - __DECLARE_RWSEM_GENERIC(name, RW_LOCK_BIAS) -#define DECLARE_RWSEM_READ_LOCKED(name) \ - __DECLARE_RWSEM_GENERIC(name, RW_LOCK_BIAS-1) -#define DECLARE_RWSEM_WRITE_LOCKED(name) \ - __DECLARE_RWSEM_GENERIC(name, 0) - -extern inline void init_rwsem(struct rw_semaphore *sem) -{ - atomic_set(&sem->count, RW_LOCK_BIAS); - sem->granted = 0; - init_waitqueue_head(&sem->wait); - init_waitqueue_head(&sem->write_bias_wait); -#if WAITQUEUE_DEBUG - sem->__magic = (long)&sem->__magic; - atomic_set(&sem->readers, 0); - atomic_set(&sem->writers, 0); -#endif -} - -/* The expensive part is outlined. */ -extern void __down_read(struct rw_semaphore *sem, int count); -extern void __down_write(struct rw_semaphore *sem, int count); -extern void __rwsem_wake(struct rw_semaphore *sem, unsigned long readers); - -extern inline void down_read(struct rw_semaphore *sem) -{ - int count; - -#if WAITQUEUE_DEBUG - CHECK_MAGIC(sem->__magic); -#endif - - count = atomic_dec_return(&sem->count); - if (count < 0) { - __down_read(sem, count); - } - mb(); - -#if WAITQUEUE_DEBUG - if (sem->granted & 2) - BUG(); - if (atomic_read(&sem->writers)) - BUG(); - atomic_inc(&sem->readers); -#endif -} - -extern inline void down_write(struct rw_semaphore *sem) -{ - int count; - -#if WAITQUEUE_DEBUG - CHECK_MAGIC(sem->__magic); -#endif - - count = atomic_sub_return(RW_LOCK_BIAS, &sem->count); - if (count) { - __down_write(sem, count); - } - mb(); - -#if WAITQUEUE_DEBUG - if (atomic_read(&sem->writers)) - BUG(); - if (atomic_read(&sem->readers)) - BUG(); - if (sem->granted & 3) - BUG(); - atomic_inc(&sem->writers); -#endif -} - -/* When a reader does a release, the only significant case is when - there was a writer waiting, and we've bumped the count to 0: we must - wake the writer up. */ - -extern inline void up_read(struct rw_semaphore *sem) -{ -#if WAITQUEUE_DEBUG - CHECK_MAGIC(sem->__magic); - if (sem->granted & 2) - BUG(); - if (atomic_read(&sem->writers)) - BUG(); - atomic_dec(&sem->readers); -#endif - - mb(); - if (atomic_inc_return(&sem->count) == 0) - __rwsem_wake(sem, 0); -} - -/* - * Releasing the writer is easy -- just release it and wake up any sleepers. - */ -extern inline void up_write(struct rw_semaphore *sem) -{ - int count; - -#if WAITQUEUE_DEBUG - CHECK_MAGIC(sem->__magic); - if (sem->granted & 3) - BUG(); - if (atomic_read(&sem->readers)) - BUG(); - if (atomic_read(&sem->writers) != 1) - BUG(); - atomic_dec(&sem->writers); -#endif - - mb(); - count = atomic_add_return(RW_LOCK_BIAS, &sem->count); - if (count - RW_LOCK_BIAS < 0 && count >= 0) { - /* Only do the wake if we're no longer negative. */ - __rwsem_wake(sem, count); - } } #endif /* _ASM_SEMAPHORE_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/serial.h linux/include/asm-mips/serial.h --- v2.4.5/linux/include/asm-mips/serial.h Sat May 13 08:31:25 2000 +++ linux/include/asm-mips/serial.h Mon Jul 2 13:56:40 2001 @@ -1,5 +1,4 @@ -/* $Id: serial.h,v 1.9 2000/02/16 01:45:55 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -76,6 +75,81 @@ #define JAZZ_SERIAL_PORT_DEFNS #endif +#ifdef CONFIG_MIPS_ATLAS +#include +#include +#define ATLAS_SERIAL_PORT_DEFNS \ + /* UART CLK PORT IRQ FLAGS */ \ + { 0, ATLAS_BASE_BAUD, ATLAS_UART_REGS_BASE, ATLASINT_UART, STD_COM_FLAGS }, /* ttyS0 */ +#else +#define ATLAS_SERIAL_PORT_DEFNS +#endif + +/* + * Both Galileo boards have the same UART mappings. + */ +#if defined (CONFIG_MIPS_EV96100) || defined (CONFIG_MIPS_EV64120) +#include +#include +#define EV96100_SERIAL_PORT_DEFNS \ + { baud_base: EV96100_BASE_BAUD, port: EV96100_UART0_REGS_BASE, \ + irq: EV96100INT_UART_0, flags: STD_COM_FLAGS, type: 0x3, \ + iomem_base: EV96100_UART0_REGS_BASE }, \ + { baud_base: EV96100_BASE_BAUD, port: EV96100_UART1_REGS_BASE, \ + irq: EV96100INT_UART_0, flags: STD_COM_FLAGS, type: 0x3, \ + iomem_base: EV96100_UART1_REGS_BASE }, +#else +#define EV96100_SERIAL_PORT_DEFNS +#endif + +#ifdef CONFIG_MIPS_ITE8172 +#include +#include +#include +#define ITE_SERIAL_PORT_DEFNS \ + { baud_base: BASE_BAUD, port: (IT8172_PCI_IO_BASE + IT_UART_BASE), \ + irq: IT8172_UART_IRQ, flags: STD_COM_FLAGS, type: 0x3 }, \ + { baud_base: (24000000/(16*13)), port: (IT8172_PCI_IO_BASE + IT8712_UART1_PORT), \ + irq: IT8172_SERIRQ_4, flags: STD_COM_FLAGS, type: 0x3 }, \ + /* Smart Card Reader 0 */ \ + { baud_base: BASE_BAUD, port: (IT8172_PCI_IO_BASE + IT_SCR0_BASE), \ + irq: IT8172_SCR0_IRQ, flags: STD_COM_FLAGS, type: 0x3 }, \ + /* Smart Card Reader 1 */ \ + { baud_base: BASE_BAUD, port: (IT8172_PCI_IO_BASE + IT_SCR1_BASE), \ + irq: IT8172_SCR1_IRQ, flags: STD_COM_FLAGS, type: 0x3 }, +#else +#define ITE_SERIAL_PORT_DEFNS +#endif + +#ifdef CONFIG_MIPS_IVR +#include +#include +#define IVR_SERIAL_PORT_DEFNS \ + { baud_base: BASE_BAUD, port: (IT8172_PCI_IO_BASE + IT_UART_BASE), \ + irq: IT8172_UART_IRQ, flags: STD_COM_FLAGS, type: 0x3 }, \ + /* Smart Card Reader 1 */ \ + { baud_base: BASE_BAUD, port: (IT8172_PCI_IO_BASE + IT_SCR1_BASE), \ + irq: IT8172_SCR1_IRQ, flags: STD_COM_FLAGS, type: 0x3 }, +#else +#define IVR_SERIAL_PORT_DEFNS +#endif + +#ifdef CONFIG_AU1000_UART +#include +#define AU1000_SERIAL_PORT_DEFNS \ + { baud_base: 0, port: UART0_ADDR, irq: AU1000_UART0_INT, \ + flags: STD_COM_FLAGS, type: 1 }, \ + { baud_base: 0, port: UART1_ADDR, irq: AU1000_UART1_INT, \ + flags: STD_COM_FLAGS, type: 1 }, \ + { baud_base: 0, port: UART2_ADDR, irq: AU1000_UART2_INT, \ + flags: STD_COM_FLAGS, type: 1 }, \ + { baud_base: 0, port: UART3_ADDR, irq: AU1000_UART3_INT, \ + flags: STD_COM_FLAGS, type: 1 }, +#else +#define AU1000_SERIAL_PORT_DEFNS +#endif + +#ifdef CONFIG_HAVE_STD_PC_SERIAL_PORT #define STD_SERIAL_PORT_DEFNS \ /* UART CLK PORT IRQ FLAGS */ \ { 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS }, /* ttyS0 */ \ @@ -83,7 +157,6 @@ { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS }, /* ttyS2 */ \ { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS }, /* ttyS3 */ - #ifdef CONFIG_SERIAL_MANY_PORTS #define EXTRA_SERIAL_PORT_DEFNS \ { 0, BASE_BAUD, 0x1A0, 9, FOURPORT_FLAGS }, /* ttyS4 */ \ @@ -96,8 +169,8 @@ { 0, BASE_BAUD, 0x2B8, 5, FOURPORT_FLAGS }, /* ttyS11 */ \ { 0, BASE_BAUD, 0x330, 4, ACCENT_FLAGS }, /* ttyS12 */ \ { 0, BASE_BAUD, 0x338, 4, ACCENT_FLAGS }, /* ttyS13 */ \ - { 0, BASE_BAUD, 0x000, 0, 0 }, /* ttyS14 (spare) */ \ - { 0, BASE_BAUD, 0x000, 0, 0 }, /* ttyS15 (spare) */ \ + { 0, BASE_BAUD, 0x000, 0, 0 }, /* ttyS14 (spare) */ \ + { 0, BASE_BAUD, 0x000, 0, 0 }, /* ttyS15 (spare) */ \ { 0, BASE_BAUD, 0x100, 12, BOCA_FLAGS }, /* ttyS16 */ \ { 0, BASE_BAUD, 0x108, 12, BOCA_FLAGS }, /* ttyS17 */ \ { 0, BASE_BAUD, 0x110, 12, BOCA_FLAGS }, /* ttyS18 */ \ @@ -114,9 +187,14 @@ { 0, BASE_BAUD, 0x168, 12, BOCA_FLAGS }, /* ttyS29 */ \ { 0, BASE_BAUD, 0x170, 12, BOCA_FLAGS }, /* ttyS30 */ \ { 0, BASE_BAUD, 0x178, 12, BOCA_FLAGS }, /* ttyS31 */ -#else +#else /* CONFIG_SERIAL_MANY_PORTS */ #define EXTRA_SERIAL_PORT_DEFNS -#endif +#endif /* CONFIG_SERIAL_MANY_PORTS */ + +#else /* CONFIG_HAVE_STD_PC_SERIAL_PORTS */ +#define STD_SERIAL_PORT_DEFNS +#define EXTRA_SERIAL_PORT_DEFNS +#endif /* CONFIG_HAVE_STD_PC_SERIAL_PORTS */ /* You can have up to four HUB6's in the system, but I've only * included two cards here for a total of twelve ports. @@ -151,8 +229,44 @@ #define MCA_SERIAL_PORT_DFNS #endif +#ifdef CONFIG_MOMENCO_OCELOT +/* Ordinary NS16552 duart with a 20MHz crystal. */ +#define OCELOT_BASE_BAUD ( 20000000 / 16 ) + +#define OCELOT_SERIAL1_IRQ 4 +#define OCELOT_SERIAL1_BASE 0xe0001020 + +#define _OCELOT_SERIAL_INIT(int, base) \ + { baud_base: OCELOT_BASE_BAUD, irq: int, flags: STD_COM_FLAGS, \ + iomem_base: (u8 *) base, iomem_reg_shift: 2, \ + io_type: SERIAL_IO_MEM } +#define MOMENCO_OCELOT_SERIAL_PORT_DEFNS \ + _OCELOT_SERIAL_INIT(OCELOT_SERIAL1_IRQ, OCELOT_SERIAL1_BASE) +#else +#define MOMENCO_OCELOT_SERIAL_PORT_DEFNS +#endif + +#ifdef CONFIG_DDB5477 +#define DDB5477_SERIAL_PORT_DEFNS \ + { baud_base: BASE_BAUD, irq: 12, flags: STD_COM_FLAGS, \ + iomem_base: (u8*)0xbfa04200, iomem_reg_shift: 3, \ + io_type: SERIAL_IO_MEM},\ + { baud_base: BASE_BAUD, irq: 28, flags: STD_COM_FLAGS, \ + iomem_base: (u8*)0xbfa04240, iomem_reg_shift: 3, \ + io_type: SERIAL_IO_MEM}, +#else +#define DDB5477_SERIAL_PORT_DEFNS +#endif + #define SERIAL_PORT_DFNS \ + IVR_SERIAL_PORT_DEFNS \ + ITE_SERIAL_PORT_DEFNS \ + ATLAS_SERIAL_PORT_DEFNS \ + EV96100_SERIAL_PORT_DEFNS \ JAZZ_SERIAL_PORT_DEFNS \ STD_SERIAL_PORT_DEFNS \ EXTRA_SERIAL_PORT_DEFNS \ - HUB6_SERIAL_PORT_DFNS + HUB6_SERIAL_PORT_DFNS \ + MOMENCO_OCELOT_SERIAL_PORT_DEFNS\ + AU1000_SERIAL_PORT_DEFNS \ + DDB5477_SERIAL_PORT_DEFNS diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/sgi/sgint23.h linux/include/asm-mips/sgi/sgint23.h --- v2.4.5/linux/include/asm-mips/sgi/sgint23.h Sat May 13 08:31:25 2000 +++ linux/include/asm-mips/sgi/sgint23.h Mon Jul 2 13:56:40 2001 @@ -1,5 +1,4 @@ -/* $Id: sgint23.h,v 1.4 1999/09/28 21:02:12 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -7,6 +6,7 @@ * sgint23.h: Defines for the SGI INT2 and INT3 chipsets. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 1997, 98, 1999, 2000 Ralf Baechle * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) - INT2 corrections */ #ifndef _ASM_SGI_SGINT23_H @@ -25,20 +25,8 @@ #define SGINT_HPCDMA 41 /* INDY has 11 HPCDMA irq _sources_ */ #define SGINT_END 52 /* End of 'spaces' */ -/* Individual interrupt definitions for the INDY and Indigo2 - */ - -#define SGI_WD93_0_IRQ SGINT_LOCAL0 + 1 /* 1st onboard WD93 */ -#define SGI_WD93_1_IRQ SGINT_LOCAL0 + 2 /* 2nd onboard WD93 */ -#define SGI_ENET_IRQ SGINT_LOCAL0 + 3 /* onboard ethernet */ - -#define SGI_PANEL_IRQ SGINT_LOCAL1 + 1 /* front panel */ - -#define SGI_EISA_IRQ SGINT_LOCAL2 + 3 /* EISA interrupts */ -#define SGI_KEYBOARD_IRQ SGINT_LOCAL2 + 4 /* keyboard */ -#define SGI_SERIAL_IRQ SGINT_LOCAL2 + 5 /* onboard serial */ - -/* Individual interrupt definitions for the INDY and Indigo2 +/* + * Individual interrupt definitions for the INDY and Indigo2 */ #define SGI_WD93_0_IRQ SGINT_LOCAL0 + 1 /* 1st onboard WD93 */ @@ -215,4 +203,4 @@ extern void sgint_init(void); extern void indy_timer_init(void); -#endif /* !(_ASM_SGINT23_H) */ +#endif /* _ASM_SGI_SGINT23_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/sgialib.h linux/include/asm-mips/sgialib.h --- v2.4.5/linux/include/asm-mips/sgialib.h Sat May 13 08:31:25 2000 +++ linux/include/asm-mips/sgialib.h Mon Jul 2 13:56:40 2001 @@ -1,9 +1,8 @@ -/* $Id: sgialib.h,v 1.5 2000/03/19 01:28:58 ralf Exp $ +/* * sgialib.h: SGI ARCS firmware interface library for the Linux kernel. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) */ - #ifndef _ASM_SGIALIB_H #define _ASM_SGIALIB_H @@ -21,7 +20,7 @@ * Init the PROM library and it's internal data structures. Called * at boot time from head.S before start_kernel is invoked. */ -extern int prom_init(int argc, char **argv, char **envp, int *prom_vec); +extern void prom_init(int argc, char **argv, char **envp, int *prom_vec); /* Simple char-by-char console I/O. */ extern void prom_putchar(char c); @@ -30,28 +29,12 @@ /* Generic printf() using ARCS console I/O. */ extern void prom_printf(char *fmt, ...); -/* Memory descriptor management. */ -#define PROM_MAX_PMEMBLOCKS 32 -struct prom_pmemblock { - unsigned long base; /* Within KSEG0. */ - unsigned int size; /* In bytes. */ - unsigned int type; /* free or prom memory */ -}; - -/* Get next memory descriptor after CURR, returns first descriptor - * in chain is CURR is NULL. - */ -extern struct linux_mdesc *prom_getmdesc(struct linux_mdesc *curr); #define PROM_NULL_MDESC ((struct linux_mdesc *) 0) /* Called by prom_init to setup the physical memory pmemblock * array. */ extern void prom_meminit(void); -extern void prom_fixup_mem_map(unsigned long start_mem, unsigned long end_mem); - -/* Returns pointer to PROM physical memory block array. */ -extern struct prom_pmemblock *prom_getpblock_array(void); /* PROM device tree library routines. */ #define PROM_NULL_COMPONENT ((pcomponent *) 0) @@ -81,9 +64,9 @@ */ extern void prom_identify_arch(void); -/* Environemt variable routines. */ +/* Environment variable routines. */ extern PCHAR ArcGetEnvironmentVariable(CHAR *name); -extern LONG SetEnvironmentVariable(PCHAR name, PCHAR value); +extern LONG ArcSetEnvironmentVariable(PCHAR name, PCHAR value); /* ARCS command line acquisition and parsing. */ extern char *prom_getcmdline(void); @@ -115,7 +98,7 @@ extern void prom_powerdown(void) __attribute__((noreturn)); extern void prom_restart(void) __attribute__((noreturn)); extern void prom_reboot(void) __attribute__((noreturn)); -extern void prom_imode(void) __attribute__((noreturn)); +extern void ArcEnterInteractiveMode(void) __attribute__((noreturn)); extern long prom_cfgsave(void); extern struct linux_sysid *prom_getsysid(void); extern void prom_cacheflush(void); diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/shmbuf.h linux/include/asm-mips/shmbuf.h --- v2.4.5/linux/include/asm-mips/shmbuf.h Thu Feb 24 22:52:30 2000 +++ linux/include/asm-mips/shmbuf.h Mon Jul 2 13:56:40 2001 @@ -7,7 +7,7 @@ * between kernel and user space. * * Pad space is left for: - * - 2 miscellaneous 64-bit values + * - 2 miscellaneous 32-bit values */ struct shmid64_ds { diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/smp.h linux/include/asm-mips/smp.h --- v2.4.5/linux/include/asm-mips/smp.h Tue Oct 20 13:52:54 1998 +++ linux/include/asm-mips/smp.h Mon Jul 2 13:56:40 2001 @@ -1,6 +1,37 @@ #ifndef __ASM_MIPS_SMP_H #define __ASM_MIPS_SMP_H +#include + +#ifdef CONFIG_SMP + +#include +#include +#include + + +/* Mappings are straight across. If we want + to add support for disabling cpus and such, + we'll have to do what the mips64 port does here */ #define cpu_logical_map(cpu) (cpu) +#define cpu_number_map(cpu) (cpu) + +#define smp_processor_id() (current->processor) + + +/* I've no idea what the real meaning of this is */ +#define PROC_CHANGE_PENALTY 20 + +#define NO_PROC_ID (-1) + +struct smp_fn_call_struct { + spinlock_t lock; + atomic_t finished; + void (*fn)(void *); + void *data; +}; + +extern struct smp_fn_call_struct smp_fn_call; +#endif /* CONFIG_SMP */ #endif /* __ASM_MIPS_SMP_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/sni.h linux/include/asm-mips/sni.h --- v2.4.5/linux/include/asm-mips/sni.h Sat May 13 08:31:25 2000 +++ linux/include/asm-mips/sni.h Mon Jul 2 13:56:40 2001 @@ -30,6 +30,14 @@ #define PCIMT_ERRADDR 0xbfff0040 #define PCIMT_SYNDROME 0xbfff0048 #define PCIMT_ITPEND 0xbfff0050 +#define IT_INT2 0x01 +#define IT_INTD 0x02 +#define IT_INTC 0x04 +#define IT_INTB 0x08 +#define IT_INTA 0x10 +#define IT_EISA 0x20 +#define IT_SCSI 0x40 +#define IT_ETH 0x80 #define PCIMT_IRQSEL 0xbfff0058 #define PCIMT_TESTMEM 0xbfff0060 #define PCIMT_ECCREG 0xbfff0068 @@ -73,16 +81,18 @@ * to the other interrupts generated by ASIC PCI. */ #define PCIMT_KEYBOARD_IRQ 1 -#define PCIMT_IRQ_ETHERNET 16 -#define PCIMT_IRQ_TEMPERATURE 17 -#define PCIMT_IRQ_EISA_NMI 18 -#define PCIMT_IRQ_POWER_OFF 19 -#define PCIMT_IRQ_BUTTON 20 -#define PCIMT_IRQ_INTA 21 -#define PCIMT_IRQ_INTB 22 -#define PCIMT_IRQ_INTC 23 -#define PCIMT_IRQ_INTD 24 -#define PCIMT_IRQ_SCSI 25 +#define PCIMT_IRQ_INT2 16 /* What is that? */ +#define PCIMT_IRQ_INTD 17 +#define PCIMT_IRQ_INTC 18 +#define PCIMT_IRQ_INTB 19 +#define PCIMT_IRQ_INTA 20 +#define PCIMT_IRQ_EISA 21 +#define PCIMT_IRQ_SCSI 22 +#define PCIMT_IRQ_ETHERNET 23 +#define PCIMT_IRQ_TEMPERATURE 24 +#define PCIMT_IRQ_EISA_NMI 25 +#define PCIMT_IRQ_POWER_OFF 26 +#define PCIMT_IRQ_BUTTON 27 /* * Base address for the mapped 16mb EISA bus segment. diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/socket.h linux/include/asm-mips/socket.h --- v2.4.5/linux/include/asm-mips/socket.h Sat Feb 3 11:26:44 2001 +++ linux/include/asm-mips/socket.h Mon Jul 2 13:56:40 2001 @@ -33,7 +33,7 @@ #define SO_RCVLOWAT 0x1004 /* receive low-water mark */ #define SO_SNDTIMEO 0x1005 /* send timeout */ #define SO_RCVTIMEO 0x1006 /* receive timeout */ -#define SO_ACCEPTCONN 0x1007 +#define SO_ACCEPTCONN 0x1009 /* linux-specific, might as well be the same as on i386 */ #define SO_NO_CHECK 11 @@ -71,6 +71,7 @@ /* level. For writing rarp and */ /* other similar things on the */ /* user level. */ +#define SOCK_MAX (SOCK_PACKET+1) #endif #endif /* _ASM_SOCKET_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/spinlock.h linux/include/asm-mips/spinlock.h --- v2.4.5/linux/include/asm-mips/spinlock.h Sat May 13 08:31:25 2000 +++ linux/include/asm-mips/spinlock.h Mon Jul 2 13:56:40 2001 @@ -1,5 +1,4 @@ -/* $Id: spinlock.h,v 1.8 2000/01/23 21:15:52 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -22,6 +21,9 @@ #define spin_lock_init(x) do { (x)->lock = 0; } while(0); +#define spin_is_locked(x) ((x)->lock != 0) +#define spin_unlock_wait(x) ({ do { barrier(); } while ((x)->lock); }) + /* * Simple spin lock operations. There are two variants, one clears IRQ's * on the local processor, one does not. @@ -29,9 +31,6 @@ * We make no fairness assumptions. They have a cost. */ -typedef struct { unsigned long a[100]; } __dummy_lock_t; -#define __dummy_lock(lock) (*(__dummy_lock_t *)(lock)) - static inline void spin_lock(spinlock_t *lock) { unsigned int tmp; @@ -45,8 +44,8 @@ "beqz\t%1, 1b\n\t" " sync\n\t" ".set\treorder" - : "=o" (__dummy_lock(lock)), "=&r" (tmp) - : "o" (__dummy_lock(lock)) + : "=o" (lock->lock), "=&r" (tmp) + : "o" (lock->lock) : "memory"); } @@ -57,8 +56,8 @@ "sync\n\t" "sw\t$0, %0\n\t" ".set\treorder" - : "=o" (__dummy_lock(lock)) - : "o" (__dummy_lock(lock)) + : "=o" (lock->lock) + : "o" (lock->lock) : "memory"); } @@ -92,8 +91,8 @@ "beqz\t%1, 1b\n\t" " sync\n\t" ".set\treorder" - : "=o" (__dummy_lock(rw)), "=&r" (tmp) - : "o" (__dummy_lock(rw)) + : "=o" (rw->lock), "=&r" (tmp) + : "o" (rw->lock) : "memory"); } @@ -111,8 +110,8 @@ "sc\t%1, %0\n\t" "beqz\t%1, 1b\n\t" ".set\treorder" - : "=o" (__dummy_lock(rw)), "=&r" (tmp) - : "o" (__dummy_lock(rw)) + : "=o" (rw->lock), "=&r" (tmp) + : "o" (rw->lock) : "memory"); } @@ -129,8 +128,8 @@ "beqz\t%1, 1b\n\t" " sync\n\t" ".set\treorder" - : "=o" (__dummy_lock(rw)), "=&r" (tmp) - : "o" (__dummy_lock(rw)) + : "=o" (rw->lock), "=&r" (tmp) + : "o" (rw->lock) : "memory"); } @@ -141,8 +140,8 @@ "sync\n\t" "sw\t$0, %0\n\t" ".set\treorder" - : "=o" (__dummy_lock(rw)) - : "o" (__dummy_lock(rw)) + : "=o" (rw->lock) + : "o" (rw->lock) : "memory"); } diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/stackframe.h linux/include/asm-mips/stackframe.h --- v2.4.5/linux/include/asm-mips/stackframe.h Sat May 13 08:31:25 2000 +++ linux/include/asm-mips/stackframe.h Mon Jul 2 13:56:40 2001 @@ -1,13 +1,17 @@ /* - * include/asm-mips/stackframe.h + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. * - * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Paul M. Antoine. - * - * $Id: stackframe.h,v 1.10 1999/08/13 17:07:27 harald Exp $ + * Copyright (C) 1994, 1995, 1996, 2001 Ralf Baechle + * Copyright (C) 1994, 1995, 1996 Paul M. Antoine. */ -#ifndef __ASM_MIPS_STACKFRAME_H -#define __ASM_MIPS_STACKFRAME_H +#ifndef __ASM_STACKFRAME_H +#define __ASM_STACKFRAME_H +#include +#include +#include #include #include #include @@ -47,20 +51,45 @@ #define __str2(x) #x #define __str(x) __str2(x) -#define save_static(frame) \ - __asm__ __volatile__( \ - "sw\t$16,"__str(PT_R16)"(%0)\n\t" \ - "sw\t$17,"__str(PT_R17)"(%0)\n\t" \ - "sw\t$18,"__str(PT_R18)"(%0)\n\t" \ - "sw\t$19,"__str(PT_R19)"(%0)\n\t" \ - "sw\t$20,"__str(PT_R20)"(%0)\n\t" \ - "sw\t$21,"__str(PT_R21)"(%0)\n\t" \ - "sw\t$22,"__str(PT_R22)"(%0)\n\t" \ - "sw\t$23,"__str(PT_R23)"(%0)\n\t" \ - "sw\t$30,"__str(PT_R30)"(%0)\n\t" \ - : /* No outputs */ \ - : "r" (frame)) +#define save_static_function(symbol) \ +__asm__ ( \ + ".globl\t" #symbol "\n\t" \ + ".align\t2\n\t" \ + ".type\t" #symbol ", @function\n\t" \ + ".ent\t" #symbol ", 0\n" \ + #symbol":\n\t" \ + ".frame\t$29, 0, $31\n\t" \ + "sw\t$16,"__str(PT_R16)"($29)\t\t\t# save_static_function\n\t" \ + "sw\t$17,"__str(PT_R17)"($29)\n\t" \ + "sw\t$18,"__str(PT_R18)"($29)\n\t" \ + "sw\t$19,"__str(PT_R19)"($29)\n\t" \ + "sw\t$20,"__str(PT_R20)"($29)\n\t" \ + "sw\t$21,"__str(PT_R21)"($29)\n\t" \ + "sw\t$22,"__str(PT_R22)"($29)\n\t" \ + "sw\t$23,"__str(PT_R23)"($29)\n\t" \ + "sw\t$30,"__str(PT_R30)"($29)\n\t" \ + ".end\t" #symbol "\n\t" \ + ".size\t" #symbol",. - " #symbol) + +/* Used in declaration of save_static functions. */ +#define static_unused static __attribute__((unused)) + + +#ifdef CONFIG_SMP +# define GET_SAVED_SP \ + mfc0 k0, CP0_CONTEXT; \ + lui k1, %hi(kernelsp); \ + srl k0, k0, 23; \ + sll k0, k0, 2; \ + addu k1, k0; \ + lw k1, %lo(kernelsp)(k1); +#else +# define GET_SAVED_SP \ + lui k1, %hi(kernelsp); \ + lw k1, %lo(kernelsp)(k1); +#endif + #define SAVE_SOME \ .set push; \ .set reorder; \ @@ -71,13 +100,12 @@ move k1, sp; \ .set reorder; \ /* Called from user mode, new stack. */ \ - lui k1, %hi(kernelsp); \ - lw k1, %lo(kernelsp)(k1); \ + GET_SAVED_SP \ 8: \ move k0, sp; \ subu sp, k1, PT_SIZE; \ sw k0, PT_R29(sp); \ - sw $3, PT_R3(sp); \ + sw $3, PT_R3(sp); \ sw $0, PT_R0(sp); \ mfc0 v1, CP0_STATUS; \ sw $2, PT_R2(sp); \ @@ -208,6 +236,16 @@ #endif +#define RESTORE_SP \ + lw sp, PT_R29(sp); \ + +#define RESTORE_ALL \ + RESTORE_SOME; \ + RESTORE_AT; \ + RESTORE_TEMP; \ + RESTORE_STATIC; \ + RESTORE_SP + #define RESTORE_ALL_AND_RET \ RESTORE_SOME; \ RESTORE_AT; \ @@ -215,6 +253,7 @@ RESTORE_STATIC; \ RESTORE_SP_AND_RET + /* * Move to kernel mode and disable interrupts. * Set cp0 enable bit as sign that we're running on the kernel stack @@ -248,4 +287,4 @@ xori t0,0x1e; \ mtc0 t0,CP0_STATUS -#endif /* __ASM_MIPS_STACKFRAME_H */ +#endif /* __ASM_STACKFRAME_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/stat.h linux/include/asm-mips/stat.h --- v2.4.5/linux/include/asm-mips/stat.h Sun Jul 9 22:18:15 2000 +++ linux/include/asm-mips/stat.h Mon Jul 2 13:56:40 2001 @@ -17,8 +17,7 @@ unsigned int st_ctime, st_res3; unsigned int st_blksize; int st_blocks; - unsigned int st_flags; - unsigned int st_gen; + unsigned int st_unused0[2]; }; struct stat { @@ -45,11 +44,7 @@ long reserved2; long st_blksize; long st_blocks; - char st_fstype[16]; /* Filesystem type name */ - long st_pad4[8]; - /* Linux specific fields */ - unsigned int st_flags; - unsigned int st_gen; + long st_pad4[14]; }; /* @@ -61,25 +56,36 @@ struct stat64 { unsigned long st_dev; unsigned long st_pad0[3]; /* Reserved for st_dev expansion */ - ino_t st_ino; + + unsigned long long st_ino; + mode_t st_mode; nlink_t st_nlink; + uid_t st_uid; gid_t st_gid; + unsigned long st_rdev; unsigned long st_pad1[3]; /* Reserved for st_rdev expansion */ + long long st_size; + /* * Actually this should be timestruc_t st_atime, st_mtime and st_ctime * but we don't have it under Linux. */ time_t st_atime; unsigned long reserved0; /* Reserved for st_atime expansion */ + time_t st_mtime; - unsigned long reserved1; /* Reserved for st_atime expansion */ + unsigned long reserved1; /* Reserved for st_mtime expansion */ + time_t st_ctime; - unsigned long reserved2; /* Reserved for st_atime expansion */ + unsigned long reserved2; /* Reserved for st_ctime expansion */ + unsigned long st_blksize; + unsigned long st_pad2; + long long st_blocks; }; diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/system.h linux/include/asm-mips/system.h --- v2.4.5/linux/include/asm-mips/system.h Thu Aug 3 15:38:11 2000 +++ linux/include/asm-mips/system.h Mon Jul 2 13:56:40 2001 @@ -1,5 +1,4 @@ -/* $Id: system.h,v 1.20 1999/12/06 23:13:21 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -7,6 +6,12 @@ * Copyright (C) 1994 - 1999 by Ralf Baechle * Copyright (C) 1996 by Paul M. Antoine * Copyright (C) 1994 - 1999 by Ralf Baechle + * + * Changed set_except_vector declaration to allow return of previous + * vector address value - necessary for "borrowing" vectors. + * + * Kevin D. Kissell, kevink@mips.org and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. */ #ifndef _ASM_SYSTEM_H #define _ASM_SYSTEM_H @@ -61,65 +66,76 @@ : "$1", "memory"); } -#define __save_flags(x) \ -__asm__ __volatile__( \ - ".set\tpush\n\t" \ - ".set\treorder\n\t" \ - "mfc0\t%0,$12\n\t" \ - ".set\tpop\n\t" \ - : "=r" (x) \ - : /* no inputs */ \ - : "memory") - -#define __save_and_cli(x) \ -__asm__ __volatile__( \ - ".set\tpush\n\t" \ - ".set\treorder\n\t" \ - ".set\tnoat\n\t" \ - "mfc0\t%0,$12\n\t" \ - "ori\t$1,%0,1\n\t" \ - "xori\t$1,1\n\t" \ - ".set\tnoreorder\n\t" \ - "mtc0\t$1,$12\n\t" \ - "nop\n\t" \ - "nop\n\t" \ - "nop\n\t" \ - ".set\tpop\n\t" \ - : "=r" (x) \ - : /* no inputs */ \ +#define __save_flags(x) \ +__asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\treorder\n\t" \ + "mfc0\t%0,$12\n\t" \ + ".set\tpop\n\t" \ + : "=r" (x)) + +#define __save_and_cli(x) \ +__asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\treorder\n\t" \ + ".set\tnoat\n\t" \ + "mfc0\t%0,$12\n\t" \ + "ori\t$1,%0,1\n\t" \ + "xori\t$1,1\n\t" \ + ".set\tnoreorder\n\t" \ + "mtc0\t$1,$12\n\t" \ + "nop\n\t" \ + "nop\n\t" \ + "nop\n\t" \ + ".set\tpop\n\t" \ + : "=r" (x) \ + : /* no inputs */ \ : "$1", "memory") -extern void __inline__ -__restore_flags(int flags) -{ - __asm__ __volatile__( - ".set\tpush\n\t" - ".set\treorder\n\t" - "mfc0\t$8,$12\n\t" - "li\t$9,0xff00\n\t" - "and\t$8,$9\n\t" - "nor\t$9,$0,$9\n\t" - "and\t%0,$9\n\t" - "or\t%0,$8\n\t" - ".set\tnoreorder\n\t" - "mtc0\t%0,$12\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - ".set\tpop\n\t" - : - : "r" (flags) - : "$8", "$9", "memory"); -} +#define __restore_flags(flags) \ +do { \ + unsigned long __tmp1; \ + \ + __asm__ __volatile__( \ + ".set\tnoreorder\t\t\t# __restore_flags\n\t" \ + ".set\tnoat\n\t" \ + "mfc0\t$1, $12\n\t" \ + "andi\t%0, 1\n\t" \ + "ori\t$1, 1\n\t" \ + "xori\t$1, 1\n\t" \ + "or\t%0, $1\n\t" \ + "mtc0\t%0, $12\n\t" \ + "nop\n\t" \ + "nop\n\t" \ + "nop\n\t" \ + ".set\tat\n\t" \ + ".set\treorder" \ + : "=r" (__tmp1) \ + : "0" (flags) \ + : "$1", "memory"); \ +} while(0) -/* - * Non-SMP versions ... - */ -#define sti() __sti() -#define cli() __cli() -#define save_flags(x) __save_flags(x) -#define save_and_cli(x) __save_and_cli(x) -#define restore_flags(x) __restore_flags(x) +#ifdef CONFIG_SMP + +extern void __global_sti(void); +extern void __global_cli(void); +extern unsigned long __global_save_flags(void); +extern void __global_restore_flags(unsigned long); +# define sti() __global_sti() +# define cli() __global_cli() +# define save_flags(x) do { x = __global_save_flags(); } while (0) +# define restore_flags(x) __global_restore_flags(x) +# define save_and_cli(x) do { save_flags(x); cli(); } while(0) + +#else /* Single processor */ + +# define sti() __sti() +# define cli() __cli() +# define save_flags(x) __save_flags(x) +# define save_and_cli(x) __save_and_cli(x) +# define restore_flags(x) __restore_flags(x) + +#endif /* SMP */ /* For spinlocks etc */ #define local_irq_save(x) __save_and_cli(x); @@ -131,11 +147,14 @@ * These are probably defined overly paranoid ... */ #ifdef CONFIG_CPU_HAS_WB + #include -#define rmb() -#define wmb() wbflush() -#define mb() wbflush() -#else +#define rmb() do { } while(0) +#define wmb() wbflush() +#define mb() wbflush() + +#else /* CONFIG_CPU_HAS_WB */ + #define mb() \ __asm__ __volatile__( \ "# prevent instructions being moved around\n\t" \ @@ -148,6 +167,17 @@ : "memory") #define rmb() mb() #define wmb() mb() + +#endif /* CONFIG_CPU_HAS_WB */ + +#ifdef CONFIG_SMP +#define smp_mb() mb() +#define smp_rmb() rmb() +#define smp_wmb() wmb() +#else +#define smp_mb() barrier() +#define smp_rmb() barrier() +#define smp_wmb() barrier() #endif #define set_mb(var, value) \ @@ -180,17 +210,17 @@ unsigned long dummy; __asm__ __volatile__( - ".set\tnoreorder\n\t" + ".set\tnoreorder\t\t\t# xchg_u32\n\t" ".set\tnoat\n\t" - "ll\t%0,(%1)\n" - "1:\tmove\t$1,%2\n\t" - "sc\t$1,(%1)\n\t" - "beqzl\t$1,1b\n\t" - "ll\t%0,(%1)\n\t" + "ll\t%0, %3\n" + "1:\tmove\t$1, %2\n\t" + "sc\t$1, %1\n\t" + "beqzl\t$1, 1b\n\t" + " ll\t%0, %3\n\t" ".set\tat\n\t" ".set\treorder" - : "=r" (val), "=r" (m), "=r" (dummy) - : "1" (m), "2" (val) + : "=r" (val), "=o" (*m), "=r" (dummy) + : "o" (*m), "2" (val) : "memory"); return val; @@ -207,64 +237,25 @@ #endif /* Processor-dependent optimization */ } -/* - * Only used for 64 bit kernel. - */ -extern __inline__ unsigned long xchg_u64(volatile long * m, unsigned long val) -{ - unsigned long dummy; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "lld\t%0,(%1)\n" - "1:\tmove\t$1,%2\n\t" - "scd\t$1,(%1)\n\t" - "beqzl\t$1,1b\n\t" - "lld\t%0,(%1)\n\t" - ".set\tat\n\t" - ".set\treorder" - : "=r" (val), "=r" (m), "=r" (dummy) - : "1" (m), "2" (val) - : "memory"); - - return val; -} - #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) #define tas(ptr) (xchg((ptr),1)) -/* - * This function doesn't exist, so you'll get a linker error - * if something tries to do an invalid xchg(). - * - * This only works if the compiler isn't horribly bad at optimizing. - * gcc-2.5.8 reportedly can't handle this, but I define that one to - * be dead anyway. - */ -extern void __xchg_called_with_bad_pointer(void); - -static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr, int size) +static __inline__ unsigned long +__xchg(unsigned long x, volatile void * ptr, int size) { switch (size) { case 4: return xchg_u32(ptr, x); -#if defined(__mips64) - case 8: - return xchg_u64(ptr, x); -#endif } - __xchg_called_with_bad_pointer(); return x; } -extern void set_except_vector(int n, void *addr); +extern void *set_except_vector(int n, void *addr); extern void __die(const char *, struct pt_regs *, const char *where, unsigned long line) __attribute__((noreturn)); extern void __die_if_kernel(const char *, struct pt_regs *, const char *where, unsigned long line); -extern int abs(int); #define die(msg, regs) \ __die(msg, regs, __FILE__ ":"__FUNCTION__, __LINE__) diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/termios.h linux/include/asm-mips/termios.h --- v2.4.5/linux/include/asm-mips/termios.h Sat Feb 3 20:00:45 2001 +++ linux/include/asm-mips/termios.h Mon Jul 2 13:56:40 2001 @@ -1,10 +1,9 @@ -/* $Id: termios.h,v 1.8 2000/01/27 23:45:30 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995, 1996 by Ralf Baechle + * Copyright (C) 1995, 1996, 2001 by Ralf Baechle */ #ifndef _ASM_TERMIOS_H #define _ASM_TERMIOS_H @@ -101,6 +100,7 @@ #define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */ #define N_HDLC 13 /* synchronous HDLC */ #define N_SYNC_PPP 14 /* synchronous PPP */ +#define N_HCI 15 /* Bluetooth HCI UART */ #ifdef __KERNEL__ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/time.h linux/include/asm-mips/time.h --- v2.4.5/linux/include/asm-mips/time.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/time.h Mon Jul 2 13:56:40 2001 @@ -0,0 +1,66 @@ +/*********************************************************************** + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * include/asm-mips/time.h + * header file for the new style time.c file and time services. + * + * 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. + *********************************************************************** + */ + +#ifndef _ASM_TIME_H +#define _ASM_TIME_H + +#include /* for struct pt_regs */ +#include /* for asmlinkage */ + +/* + * RTC ops. By default, they point a no-RTC functions. + * rtc_get_time - mktime(year, mon, day, hour, min, sec) in seconds. + * rtc_set_time - reverse the above translation + */ +extern unsigned long (*rtc_get_time)(void); +extern int (*rtc_set_time)(unsigned long); + +/* + * do_gettimeoffset(). By default, this func pointer points to + * do_null_gettimeoffset(), which leads to the same resolution as HZ. + * Higher resolution versions are vailable. + */ +extern unsigned long (*do_gettimeoffset)(void); + +extern unsigned long null_gettimeoffset(void); +extern unsigned long fixed_rate_gettimeoffset(void); +extern unsigned long calibrate_div32_gettimeoffset(void); +extern unsigned long calibrate_div64_gettimeoffset(void); + +/* + * high-level timer interrupt routines. + */ +extern void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs); + +/* + * the corresponding low-level timer interrupt routine. + */ +asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs); + +/* + * board specific routines required by time_init(). + * board_time_init is defaulted to NULL and can remains so. + * board_timer_setup must be setup properly in machine setup routine. + */ +struct irqaction; +extern void (*board_time_init)(void); +extern void (*board_timer_setup)(struct irqaction *irq); + +/* + * mips_counter_frequency - must be set if you intend to use + * counter as timer interrupt source or use fixed_rate_gettimeoffset. + */ +extern unsigned int mips_counter_frequency; + +#endif /* _ASM_TIME_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/tlb.h linux/include/asm-mips/tlb.h --- v2.4.5/linux/include/asm-mips/tlb.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/tlb.h Mon Jul 2 13:56:40 2001 @@ -0,0 +1 @@ +#include diff -u --recursive --new-file v2.4.5/linux/include/asm-mips/tx3912.h linux/include/asm-mips/tx3912.h --- v2.4.5/linux/include/asm-mips/tx3912.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/tx3912.h Mon Jul 2 13:56:40 2001 @@ -0,0 +1,576 @@ +/* + * linux/include/asm-mips/tx3912.h + * + * Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com) + * + * 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. + * + * Register includes for TMPR3912/05 and PR31700 processors + */ +#ifndef __TX3912_H__ +#define __TX3912_H__ + +#include + +#define inb(addr) (*(volatile unsigned char *)(addr)) +#define inw(addr) (*(volatile unsigned short *)(addr)) +#define inl(addr) (*(volatile unsigned int *)(addr)) +#define outb(b,addr) (*(volatile unsigned char *)(addr)) = (b) +#define outw(b,addr) (*(volatile unsigned short *)(addr)) = (b) +#define outl(b,addr) (*(volatile unsigned int *)(addr)) = (b) + + +/****************************************************************************** +* +* 01 General macro definitions +* +******************************************************************************/ + +#define REGISTER_BASE 0xb0c00000 + +#ifndef _LANGUAGE_ASSEMBLY + + #define REG_AT(x) (*((volatile unsigned long *)(REGISTER_BASE + x))) + +#else + + #define REG_AT(x) (REGISTER_BASE + x) + +#endif + +#define BIT(x) (1 << x) + +/****************************************************************************** +* +* 02 Bus Interface Unit +* +******************************************************************************/ + +#define MemConfig0 REG_AT(0x000) +#define MemConfig1 REG_AT(0x004) +#define MemConfig2 REG_AT(0x008) +#define MemConfig3 REG_AT(0x00c) +#define MemConfig4 REG_AT(0x010) +#define MemConfig5 REG_AT(0x014) +#define MemConfig6 REG_AT(0x018) +#define MemConfig7 REG_AT(0x01c) +#define MemConfig8 REG_AT(0x020) + +/* Memory config register 1 */ +#define MEM1_ENCS1USER BIT(21) + +/* Memory config register 3 */ +#define MEM3_CARD1ACCVAL_MASK (BIT(24) | BIT(25) | BIT(26) | BIT(27)) +#define MEM3_CARD1IOEN BIT(4) + +/* Memory config register 4 */ +#define MEM4_ARBITRATIONEN BIT(29) +#define MEM4_MEMPOWERDOWN BIT(16) +#define MEM4_ENREFRESH1 BIT(15) +#define MEM4_ENREFRESH0 BIT(14) +#define MEM4_ENWATCH BIT(24) +#define MEM4_WATCHTIMEVAL_MASK (0xf) +#define MEM4_WATCHTIMEVAL_SHIFT (20) +#define MEM4_WATCHTIME_VALUE (0xf) + +/* + *********************************************************************** + * * + * 06 Clock Module * + * * + *********************************************************************** + */ +#define TX3912_CLK_CTRL_BASE (REGISTER_BASE + 0x1c0) + +#define TX3912_CLK_CTRL_CHICLKDIV_MASK 0xff000000 +#define TX3912_CLK_CTRL_CHICLKDIV_SHIFT 24 +#define TX3912_CLK_CTRL_ENCLKTEST 0x00800000 +#define TX3912_CLK_CTRL_CLKTESTSELSIB 0x00400000 +#define TX3912_CLK_CTRL_CHIMCLKSEL 0x00200000 +#define TX3912_CLK_CTRL_CHICLKDIR 0x00100000 +#define TX3912_CLK_CTRL_ENCHIMCLK 0x00080000 +#define TX3912_CLK_CTRL_ENVIDCLK 0x00040000 +#define TX3912_CLK_CTRL_ENMBUSCLK 0x00020000 +#define TX3912_CLK_CTRL_ENSPICLK 0x00010000 +#define TX3912_CLK_CTRL_ENTIMERCLK 0x00008000 +#define TX3912_CLK_CTRL_ENFASTTIMERCLK 0x00004000 +#define TX3912_CLK_CTRL_SIBMCLKDIR 0x00002000 +#define TX3912_CLK_CTRL_RESERVED 0x00001000 +#define TX3912_CLK_CTRL_ENSIBMCLK 0x00000800 +#define TX3912_CLK_CTRL_SIBMCLKDIV_MASK 0x00000700 +#define TX3912_CLK_CTRL_SIBMCLKDIV_SHIFT 8 +#define TX3912_CLK_CTRL_CSERSEL 0x00000080 +#define TX3912_CLK_CTRL_CSERDIV_MASK 0x00000070 +#define TX3912_CLK_CTRL_CSERDIV_SHIFT 4 +#define TX3912_CLK_CTRL_ENCSERCLK 0x00000008 +#define TX3912_CLK_CTRL_ENIRCLK 0x00000004 +#define TX3912_CLK_CTRL_ENUARTACLK 0x00000002 +#define TX3912_CLK_CTRL_ENUARTBCLK 0x00000001 + + + + +/****************************************************************************** +* +* 07 CHI module +* +******************************************************************************/ + +#define CHIControl REG_AT(0x1D8) +#define CHIPointerEnable REG_AT(0x1DC) +#define CHIReceivePtrA REG_AT(0x1E0) +#define CHIReceivePtrB REG_AT(0x1E4) +#define CHITransmitPtrA REG_AT(0x1E8) +#define CHITransmitPtrB REG_AT(0x1EC) +#define CHISize REG_AT(0x1F0) +#define CHIReceiveStart REG_AT(0x1F4) +#define CHITransmitStart REG_AT(0x1F8) +#define CHIHoldingReg REG_AT(0x1FC) + +/* CHI Control Register */ +/* */ +#define CHI_RXEN BIT(2) +#define CHI_TXEN BIT(1) +#define CHI_ENCHI BIT(0) + +/****************************************************************************** +* +* 08 Interrupt module +* +******************************************************************************/ + +/* Register locations */ + +#define IntStatus1 REG_AT(0x100) +#define IntStatus2 REG_AT(0x104) +#define IntStatus3 REG_AT(0x108) +#define IntStatus4 REG_AT(0x10c) +#define IntStatus5 REG_AT(0x110) +#define IntStatus6 REG_AT(0x114) + +#define IntClear1 REG_AT(0x100) +#define IntClear2 REG_AT(0x104) +#define IntClear3 REG_AT(0x108) +#define IntClear4 REG_AT(0x10c) +#define IntClear5 REG_AT(0x110) +#define IntClear6 REG_AT(0x114) + +#define IntEnable1 REG_AT(0x118) +#define IntEnable2 REG_AT(0x11c) +#define IntEnable3 REG_AT(0x120) +#define IntEnable4 REG_AT(0x124) +#define IntEnable5 REG_AT(0x128) +#define IntEnable6 REG_AT(0x12c) + +/* Interrupt Status Register 1 at offset 100 */ +#define INT1_LCDINT BIT(31) +#define INT1_DFINT BIT(30) +#define INT1_CHIDMAHALF BIT(29) +#define INT1_CHIDMAFULL BIT(28) +#define INT1_CHIDMACNTINT BIT(27) +#define INT1_CHIRXAINT BIT(26) +#define INT1_CHIRXBINT BIT(25) +#define INT1_CHIACTINT BIT(24) +#define INT1_CHIERRINT BIT(23) +#define INT1_SND0_5INT BIT(22) +#define INT1_SND1_0INT BIT(21) +#define INT1_TEL0_5INT BIT(20) +#define INT1_TEL1_0INT BIT(19) +#define INT1_SNDDMACNTINT BIT(18) +#define INT1_TELDMACNTINT BIT(17) +#define INT1_LSNDCLIPINT BIT(16) +#define INT1_RSNDCLIPINT BIT(15) +#define INT1_VALSNDPOSINT BIT(14) +#define INT1_VALSNDNEGINT BIT(13) +#define INT1_VALTELPOSINT BIT(12) +#define INT1_VALTELNEGINT BIT(11) +#define INT1_SNDININT BIT(10) +#define INT1_TELININT BIT(9) +#define INT1_SIBSF0INT BIT(8) +#define INT1_SIBSF1INT BIT(7) +#define INT1_SIBIRQPOSINT BIT(6) +#define INT1_SIBIRQNEGINT BIT(5) + +/* Interrupt Status Register 2 at offset 104 */ +#define INT2_UARTARXINT BIT(31) +#define INT2_UARTARXOVERRUN BIT(30) +#define INT2_UARTAFRAMEINT BIT(29) +#define INT2_UARTABREAKINT BIT(28) +#define INT2_UARTATXINT BIT(26) +#define INT2_UARTATXOVERRUN BIT(25) +#define INT2_UARTAEMPTY BIT(24) + +#define INT2_UARTBRXINT BIT(21) +#define INT2_UARTBRXOVERRUN BIT(20) +#define INT2_UARTBFRAMEINT BIT(29) +#define INT2_UARTBBREAKINT BIT(18) +#define INT2_UARTBTXINT BIT(16) +#define INT2_UARTBTXOVERRUN BIT(15) +#define INT2_UARTBEMPTY BIT(14) + +#define INT2_UARTA_RX (BIT(31) | BIT(30) | BIT(29) | BIT(28) | BIT(27)) +#define INT2_UARTA_TX (BIT(26) | BIT(25) | BIT(24)) +#define INT2_UARTA_DMA (BIT(23) | BIT(22)) + +#define INT2_UARTB_RX (BIT(21) | BIT(20) | BIT(19) | BIT(18) | BIT(17)) +#define INT2_UARTB_TX (BIT(16) | BIT(15) | BIT(14)) +#define INT2_UARTB_DMA (BIT(13) | BIT(12)) + +/* Interrupt Status Register 5 */ +#define INT5_RTCINT BIT(31) +#define INT5_ALARMINT BIT(30) +#define INT5_PERIODICINT BIT(29) +#define INT5_POSPWRINT BIT(27) +#define INT5_NEGPWRINT BIT(26) +#define INT5_POSPWROKINT BIT(25) +#define INT5_NEGPWROKINT BIT(24) +#define INT5_POSONBUTINT BIT(23) +#define INT5_NEGONBUTINT BIT(22) +#define INT5_SPIAVAILINT BIT(21) /* 0x0020 0000 */ +#define INT5_SPIERRINT BIT(20) /* 0x0010 0000 */ +#define INT5_SPIRCVINT BIT(19) /* 0x0008 0000 */ +#define INT5_SPIEMPTYINT BIT(18) /* 0x0004 0000 */ +#define INT5_IOPOSINT6 BIT(13) +#define INT5_IOPOSINT5 BIT(12) +#define INT5_IOPOSINT4 BIT(11) +#define INT5_IOPOSINT3 BIT(10) +#define INT5_IOPOSINT2 BIT(9) +#define INT5_IOPOSINT1 BIT(8) +#define INT5_IOPOSINT0 BIT(7) +#define INT5_IONEGINT6 BIT(6) +#define INT5_IONEGINT5 BIT(5) +#define INT5_IONEGINT4 BIT(4) +#define INT5_IONEGINT3 BIT(3) +#define INT5_IONEGINT2 BIT(2) +#define INT5_IONEGINT1 BIT(1) +#define INT5_IONEGINT0 BIT(0) + +#define INT5_IONEGINT_SHIFT 0 +#define INT5_IONEGINT_MASK (0x7F< - -#else +#endif /* INCLUDE_LINUX_LOGO_DATA */ -/* prototypes only */ -extern unsigned char linux_logo_red[]; -extern unsigned char linux_logo_green[]; -extern unsigned char linux_logo_blue[]; -extern unsigned char linux_logo[]; -extern unsigned char linux_logo_bw[]; -extern unsigned char linux_logo16_red[]; -extern unsigned char linux_logo16_green[]; -extern unsigned char linux_logo16_blue[]; -extern unsigned char linux_logo16[]; +#include -#endif diff -u --recursive --new-file v2.4.5/linux/include/asm-mips64/socket.h linux/include/asm-mips64/socket.h --- v2.4.5/linux/include/asm-mips64/socket.h Sat Feb 3 11:26:44 2001 +++ linux/include/asm-mips64/socket.h Wed Jun 20 21:00:55 2001 @@ -79,6 +79,7 @@ /* level. For writing rarp and */ /* other similar things on the */ /* user level. */ +#define SOCK_MAX (SOCK_PACKET+1) #endif #endif /* _ASM_SOCKET_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-mips64/termios.h linux/include/asm-mips64/termios.h --- v2.4.5/linux/include/asm-mips64/termios.h Sat Feb 3 20:00:45 2001 +++ linux/include/asm-mips64/termios.h Mon Jun 11 19:15:27 2001 @@ -101,6 +101,7 @@ #define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */ #define N_HDLC 13 /* synchronous HDLC */ #define N_SYNC_PPP 14 /* synchronous PPP */ +#define N_HCI 15 /* Bluetooth HCI UART */ #ifdef __KERNEL__ diff -u --recursive --new-file v2.4.5/linux/include/asm-parisc/linux_logo.h linux/include/asm-parisc/linux_logo.h --- v2.4.5/linux/include/asm-parisc/linux_logo.h Tue Dec 5 12:29:39 2000 +++ linux/include/asm-parisc/linux_logo.h Mon Jun 11 19:15:27 2001 @@ -23,26 +23,5 @@ #define linux_logo_banner "Linux/PA-RISC version " UTS_RELEASE -#define LINUX_LOGO_COLORS 214 - -#ifdef INCLUDE_LINUX_LOGO_DATA - -#define INCLUDE_LINUX_LOGOBW -#define INCLUDE_LINUX_LOGO16 - #include -#else - -/* prototypes only */ -extern unsigned char linux_logo_red[]; -extern unsigned char linux_logo_green[]; -extern unsigned char linux_logo_blue[]; -extern unsigned char linux_logo[]; -extern unsigned char linux_logo_bw[]; -extern unsigned char linux_logo16_red[]; -extern unsigned char linux_logo16_green[]; -extern unsigned char linux_logo16_blue[]; -extern unsigned char linux_logo16[]; - -#endif diff -u --recursive --new-file v2.4.5/linux/include/asm-parisc/socket.h linux/include/asm-parisc/socket.h --- v2.4.5/linux/include/asm-parisc/socket.h Sat Feb 3 11:26:44 2001 +++ linux/include/asm-parisc/socket.h Wed Jun 20 21:00:55 2001 @@ -56,6 +56,7 @@ /* level. For writing rarp and */ /* other similar things on the */ /* user level. */ +#define SOCK_MAX (SOCK_PACKET+1) #endif #endif /* _ASM_SOCKET_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-parisc/termios.h linux/include/asm-parisc/termios.h --- v2.4.5/linux/include/asm-parisc/termios.h Sat Feb 3 20:00:45 2001 +++ linux/include/asm-parisc/termios.h Mon Jun 11 19:15:27 2001 @@ -53,6 +53,7 @@ #define N_PROFIBUS_FDL 10 /* Reserved for Profibus */ #define N_IRDA 11 /* Linux IR - http://irda.sourceforge.net/ */ #define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */ +#define N_HCI 15 /* Bluetooth HCI UART */ #ifdef __KERNEL__ diff -u --recursive --new-file v2.4.5/linux/include/asm-ppc/bitops.h linux/include/asm-ppc/bitops.h --- v2.4.5/linux/include/asm-ppc/bitops.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/bitops.h Mon Jun 11 19:15:27 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.bitops.h 1.7 05/17/01 18:14:24 cort + * BK Id: SCCS/s.bitops.h 1.9 05/26/01 14:48:14 paulus */ /* * bitops.h: Bit string operations on the ppc @@ -24,12 +24,9 @@ #define SMP_MB #endif /* CONFIG_SMP */ -#define __INLINE_BITOPS 1 - -#if __INLINE_BITOPS /* * These used to be if'd out here because using : "cc" as a constraint - * resulted in errors from egcs. Things may be OK with gcc-2.95. + * resulted in errors from egcs. Things appear to be OK with gcc-2.95. */ static __inline__ void set_bit(int nr, volatile void * addr) { @@ -80,6 +77,17 @@ : "cc"); } +/* + * non-atomic version + */ +static __inline__ void __clear_bit(int nr, volatile void *addr) +{ + unsigned long mask = 1 << (nr & 0x1f); + unsigned long *p = ((unsigned long *)addr) + (nr >> 5); + + *p &= ~mask; +} + static __inline__ void change_bit(int nr, volatile void *addr) { unsigned long old; @@ -97,6 +105,17 @@ } /* + * non-atomic version + */ +static __inline__ void __change_bit(int nr, volatile void *addr) +{ + unsigned long mask = 1 << (nr & 0x1f); + unsigned long *p = ((unsigned long *)addr) + (nr >> 5); + + *p ^= mask; +} + +/* * test_and_*_bit do imply a memory barrier (?) */ static __inline__ int test_and_set_bit(int nr, volatile void *addr) @@ -181,16 +200,19 @@ return (old & mask) != 0; } -#else /* __INLINE_BITOPS */ -extern void set_bit(int nr, volatile void *addr); -extern void clear_bit(int nr, volatile void *addr); -extern void change_bit(int nr, volatile void *addr); -extern int test_and_set_bit(int nr, volatile void *addr); -extern int test_and_clear_bit(int nr, volatile void *addr); -extern int test_and_change_bit(int nr, volatile void *addr); +/* + * non-atomic version + */ +static __inline__ int __test_and_change_bit(int nr, volatile void *addr) +{ + unsigned long mask = 1 << (nr & 0x1f); + unsigned long *p = ((unsigned long *)addr) + (nr >> 5); + unsigned long old = *p; -#endif /* __INLINE_BITOPS */ + *p = old ^ mask; + return (old & mask) != 0; +} static __inline__ int test_bit(int nr, __const__ volatile void *addr) { @@ -283,8 +305,6 @@ return result + ffz(tmp); } - -#define _EXT2_HAVE_ASM_BITOPS_ #ifdef __KERNEL__ diff -u --recursive --new-file v2.4.5/linux/include/asm-ppc/bootinfo.h linux/include/asm-ppc/bootinfo.h --- v2.4.5/linux/include/asm-ppc/bootinfo.h Thu May 24 15:03:05 2001 +++ linux/include/asm-ppc/bootinfo.h Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.bootinfo.h 1.7 05/23/01 00:38:42 cort + * BK Id: SCCS/s.bootinfo.h 1.9 06/13/01 15:28:43 paulus */ /* * Non-machine dependent bootinfo structure. Basic idea @@ -34,27 +34,6 @@ #endif /* CONFIG_APUS */ -/* - * prom_init() is called very early on, before the kernel text - * and data have been mapped to KERNELBASE. At this point the code - * is running at whatever address it has been loaded at, so - * references to extern and static variables must be relocated - * explicitly. The procedure reloc_offset() returns the address - * we're currently running at minus the address we were linked at. - * (Note that strings count as static variables.) - * - * Because OF may have mapped I/O devices into the area starting at - * KERNELBASE, particularly on CHRP machines, we can't safely call - * OF once the kernel has been mapped to KERNELBASE. Therefore all - * OF calls should be done within prom_init(), and prom_init() - * and all routines called within it must be careful to relocate - * references as necessary. - */ -#define PTRRELOC(x) ((typeof(x))((unsigned long)(x) + offset)) -#define PTRUNRELOC(x) ((typeof(x))((unsigned long)(x) - offset)) -#define RELOC(x) (*PTRRELOC(&(x))) #endif /* _PPC_BOOTINFO_H */ #endif /* __KERNEL__ */ - - diff -u --recursive --new-file v2.4.5/linux/include/asm-ppc/hardirq.h linux/include/asm-ppc/hardirq.h --- v2.4.5/linux/include/asm-ppc/hardirq.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/hardirq.h Tue Jun 12 11:07:16 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.hardirq.h 1.7 05/17/01 18:14:24 cort + * BK Id: SCCS/s.hardirq.h 1.10 06/09/01 22:16:38 paulus */ #ifdef __KERNEL__ #ifndef __ASM_HARDIRQ_H @@ -15,8 +15,7 @@ * for uniformity. */ typedef struct { - unsigned int __softirq_active; - unsigned int __softirq_mask; + unsigned long __softirq_pending; /* set_bit is used on this */ unsigned int __local_irq_count; unsigned int __local_bh_count; unsigned int __syscall_count; diff -u --recursive --new-file v2.4.5/linux/include/asm-ppc/highmem.h linux/include/asm-ppc/highmem.h --- v2.4.5/linux/include/asm-ppc/highmem.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/highmem.h Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.highmem.h 1.7 05/17/01 18:14:24 cort + * BK Id: SCCS/s.highmem.h 1.10 06/28/01 15:50:17 paulus */ /* * highmem.h: virtual kernel memory mappings for high memory @@ -94,7 +94,7 @@ BUG(); #endif set_pte(kmap_pte+idx, mk_pte(page, kmap_prot)); - flush_hash_page(0, vaddr); + flush_tlb_page(0, vaddr); return (void*) vaddr; } @@ -116,7 +116,7 @@ * this pte without first remap it */ pte_clear(kmap_pte+idx); - flush_hash_page(0, vaddr); + flush_tlb_page(0, vaddr); #endif } diff -u --recursive --new-file v2.4.5/linux/include/asm-ppc/linux_logo.h linux/include/asm-ppc/linux_logo.h --- v2.4.5/linux/include/asm-ppc/linux_logo.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/linux_logo.h Mon Jun 11 19:15:27 2001 @@ -21,23 +21,7 @@ #define LINUX_LOGO_HEIGHT 80 #define LINUX_LOGO_WIDTH 80 -#define LINUX_LOGO_COLORS 214 -#ifdef INCLUDE_LINUX_LOGO_DATA - -#define INCLUDE_LINUX_LOGOBW -#define INCLUDE_LINUX_LOGO16 #include -#else - -/* prototypes only */ -extern unsigned char linux_logo_red[]; -extern unsigned char linux_logo_green[]; -extern unsigned char linux_logo_blue[]; -extern unsigned char linux_logo[]; -extern unsigned char linux_logo_bw[]; -extern unsigned char linux_logo16[]; - -#endif #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.4.5/linux/include/asm-ppc/machdep.h linux/include/asm-ppc/machdep.h --- v2.4.5/linux/include/asm-ppc/machdep.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/machdep.h Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.machdep.h 1.11 05/17/01 18:14:25 cort + * BK Id: SCCS/s.machdep.h 1.14 06/28/01 16:13:50 paulus */ #ifdef __KERNEL__ #ifndef _PPC_MACHDEP_H @@ -67,26 +67,19 @@ * optional PCI "hooks" */ - /* Called after scanning the bus, before allocating - * resources - */ + /* Called after scanning the bus, before allocating resources */ void (*pcibios_fixup)(void); - /* Called for each PCI bus in the system - * when it's probed - */ + /* Called for each PCI bus in the system when it's probed */ void (*pcibios_fixup_bus)(struct pci_bus *); - - /* Called when pci_enable_device() is called (initial=0) or - * when a device with no assigned resource is found (initial=1). - * Returns 0 to allow assignement/enabling of the device - */ + + /* Called when pci_enable_device() is called (initial=0) or + * when a device with no assigned resource is found (initial=1). + * Returns 0 to allow assignment/enabling of the device. */ int (*pcibios_enable_device_hook)(struct pci_dev *, int initial); - /* Called at then very end of pcibios_init() - */ + /* Called at then very end of pcibios_init() */ void (*pcibios_after_init)(void); - /* this is for modules, since _machine can be a define -- Cort */ int ppc_machine; diff -u --recursive --new-file v2.4.5/linux/include/asm-ppc/mmu.h linux/include/asm-ppc/mmu.h --- v2.4.5/linux/include/asm-ppc/mmu.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/mmu.h Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.mmu.h 1.7 05/17/01 18:14:25 cort + * BK Id: SCCS/s.mmu.h 1.10 06/28/01 15:50:17 paulus */ /* * PowerPC memory management structures @@ -115,34 +115,6 @@ P601_BATL batl; /* Lower register */ } P601_BAT; -/* - * Simulated two-level MMU. This structure is used by the kernel - * to keep track of MMU mappings and is used to update/maintain - * the hardware HASH table which is really a cache of mappings. - * - * The simulated structures mimic the hardware available on other - * platforms, notably the 80x86 and 680x0. - */ - -typedef struct _pte { - unsigned long page_num:20; - unsigned long flags:12; /* Page flags (some unused bits) */ -} pte; - -#define PD_SHIFT (10+12) /* Page directory */ -#define PD_MASK 0x02FF -#define PT_SHIFT (12) /* Page Table */ -#define PT_MASK 0x02FF -#define PG_SHIFT (12) /* Page Entry */ - - -/* MMU context */ - -typedef struct _MMU_context { - SEGREG segs[16]; /* Segment registers */ - pte **pmap; /* Two-level page-map structure */ -} MMU_context; - extern void _tlbie(unsigned long va); /* invalidate a TLB entry */ extern void _tlbia(void); /* invalidate all TLB entries */ @@ -166,22 +138,6 @@ #define BPP_XX 0x00 /* No access */ #define BPP_RX 0x01 /* Read only */ #define BPP_RW 0x02 /* Read/write */ - -/* Used to set up SDR1 register */ -#define HASH_TABLE_SIZE_64K 0x00010000 -#define HASH_TABLE_SIZE_128K 0x00020000 -#define HASH_TABLE_SIZE_256K 0x00040000 -#define HASH_TABLE_SIZE_512K 0x00080000 -#define HASH_TABLE_SIZE_1M 0x00100000 -#define HASH_TABLE_SIZE_2M 0x00200000 -#define HASH_TABLE_SIZE_4M 0x00400000 -#define HASH_TABLE_MASK_64K 0x000 -#define HASH_TABLE_MASK_128K 0x001 -#define HASH_TABLE_MASK_256K 0x003 -#define HASH_TABLE_MASK_512K 0x007 -#define HASH_TABLE_MASK_1M 0x00F -#define HASH_TABLE_MASK_2M 0x01F -#define HASH_TABLE_MASK_4M 0x03F /* Control/status registers for the MPC8xx. * A write operation to these registers causes serialized access. diff -u --recursive --new-file v2.4.5/linux/include/asm-ppc/mmu_context.h linux/include/asm-ppc/mmu_context.h --- v2.4.5/linux/include/asm-ppc/mmu_context.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/mmu_context.h Mon Jul 2 14:34:57 2001 @@ -1,18 +1,40 @@ /* - * BK Id: SCCS/s.mmu_context.h 1.9 05/17/01 18:14:25 cort + * BK Id: SCCS/s.mmu_context.h 1.12 06/28/01 15:50:17 paulus */ -#include - #ifdef __KERNEL__ #ifndef __PPC_MMU_CONTEXT_H #define __PPC_MMU_CONTEXT_H -/* the way contexts are handled on the ppc they are vsid's and - don't need any special treatment right now. - perhaps I can defer flushing the tlb by keeping a list of - zombie vsid/context's and handling that through destroy_context - later -- Cort +#include +#include +#include +#include + +/* + * On 32-bit PowerPC 6xx/7xx/7xxx CPUs, we use a set of 16 VSIDs + * (virtual segment identifiers) for each context. Although the + * hardware supports 24-bit VSIDs, and thus >1 million contexts, + * we only use 32,768 of them. That is ample, since there can be + * at most around 30,000 tasks in the system anyway, and it means + * that we can use a bitmap to indicate which contexts are in use. + * Using a bitmap means that we entirely avoid all of the problems + * that we used to have when the context number overflowed, + * particularly on SMP systems. + * -- paulus. + */ +/* + * This function defines the mapping from contexts to VSIDs (virtual + * segment IDs). We use a skew on both the context and the high 4 bits + * of the 32-bit virtual address (the "effective segment ID") in order + * to spread out the entries in the MMU hash table. Note, if this + * function is changed then arch/ppc/mm/hashtable.S will have to be + * changed correspondly. + */ +#define CTX_TO_VSID(ctx, va) (((ctx) * (897 * 16) + ((va) >> 28) * 0x111) \ + & 0xffffff) + +/* The MPC8xx has only 16 contexts. We rotate through them on each task switch. A better way would be to keep track of tasks that own contexts, and implement an LRU usage. That way very active @@ -32,38 +54,22 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu) { } + #ifdef CONFIG_8xx #define NO_CONTEXT 16 #define LAST_CONTEXT 15 -#define BASE_CONTEXT (-1) -#define MUNGE_CONTEXT(n) (n) -#define flush_hash_segments(X, Y) do { } while (0) #elif CONFIG_4xx #define NO_CONTEXT 256 #define LAST_CONTEXT 255 -#define BASE_CONTEXT (0) -#define MUNGE_CONTEXT(n) (n) -#define flush_hash_segments(X, Y) do { } while (0) #else /* PPC 6xx, 7xx CPUs */ -#define NO_CONTEXT 0 -#define BASE_CONTEXT (0) -#define LAST_CONTEXT 0xfffff - -/* - * Allocating context numbers this way tends to spread out - * the entries in the hash table better than a simple linear - * allocation. - */ -#define MUNGE_CONTEXT(n) (((n) * 897) & LAST_CONTEXT) +#define NO_CONTEXT ((mm_context_t) -1) +#define LAST_CONTEXT 32767 #endif -extern atomic_t next_mmu_context; -extern void mmu_context_overflow(void); - /* * Set the current MMU context. * On 32-bit PowerPCs (other than the 8xx embedded chips), this is done by @@ -73,19 +79,58 @@ * and once I implement a real TLB context manager this will disappear. * The PGD is ignored on other processors. - Dan */ -extern void set_context(int context, void *pgd); +extern void set_context(mm_context_t context); /* - * Get a new mmu context for task tsk if necessary. + * Bitmap of contexts in use. + * The size of this bitmap is LAST_CONTEXT + 1 bits. */ -#define get_mmu_context(mm) \ -do { \ - if (mm->context == NO_CONTEXT) { \ - if (atomic_read(&next_mmu_context) == LAST_CONTEXT) \ - mmu_context_overflow(); \ - mm->context = MUNGE_CONTEXT(atomic_inc_return(&next_mmu_context));\ - } \ -} while (0) +extern unsigned long context_map[(LAST_CONTEXT+1) / (8*sizeof(unsigned long))]; + +/* + * This caches the next context number that we expect to be free. + * Its use is an optimization only, we can't rely on this context + * number to be free, but it usually will be. + */ +extern mm_context_t next_mmu_context; + +/* + * If we don't have sufficient contexts to give one to every task + * that could be in the system, we need to be able to steal contexts. + * These variables support that. + */ +#if LAST_CONTEXT < 30000 +#define FEW_CONTEXTS 1 +extern atomic_t nr_free_contexts; +extern struct mm_struct *context_mm[LAST_CONTEXT+1]; +extern void steal_context(void); +#endif + +/* + * Get a new mmu context for the address space described by `mm'. + */ +static inline void get_mmu_context(struct mm_struct *mm) +{ + mm_context_t ctx; + + if (mm->context != NO_CONTEXT) + return; +#ifdef FEW_CONTEXTS + while (atomic_dec_if_positive(&nr_free_contexts) < 0) + steal_context(); +#endif + ctx = next_mmu_context; + while (test_and_set_bit(ctx, context_map)) { + ctx = find_next_zero_bit(context_map, LAST_CONTEXT+1, ctx); + if (ctx > LAST_CONTEXT) + ctx = 0; + } + next_mmu_context = (ctx + 1) & LAST_CONTEXT; + mm->context = ctx; +#ifdef FEW_CONTEXTS + context_mm[ctx] = mm; +#endif +} /* * Set up the context for a new address space. @@ -95,14 +140,23 @@ /* * We're finished using the context for an address space. */ -#define destroy_context(mm) do { } while (0) +static inline void destroy_context(struct mm_struct *mm) +{ + if (mm->context != NO_CONTEXT) { + clear_bit(mm->context, context_map); + mm->context = NO_CONTEXT; +#ifdef FEW_CONTEXTS + atomic_inc(&nr_free_contexts); +#endif + } +} static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk, int cpu) { tsk->thread.pgdir = next->pgd; get_mmu_context(next); - set_context(next->context, next->pgd); + set_context(next->context); } /* @@ -113,16 +167,8 @@ { current->thread.pgdir = mm->pgd; get_mmu_context(mm); - set_context(mm->context, mm->pgd); + set_context(mm->context); } -/* - * compute the vsid from the context and segment - * segments > 7 are kernel segments and their - * vsid is the segment -- Cort - */ -#define VSID_FROM_CONTEXT(segment,context) \ - ((segment < 8) ? ((segment) | (context)<<4) : (segment)) - -#endif +#endif /* __PPC_MMU_CONTEXT_H */ #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.4.5/linux/include/asm-ppc/pgtable.h linux/include/asm-ppc/pgtable.h --- v2.4.5/linux/include/asm-ppc/pgtable.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/pgtable.h Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.pgtable.h 1.9 05/17/01 18:14:25 cort + * BK Id: SCCS/s.pgtable.h 1.12 06/28/01 15:50:17 paulus */ #ifdef __KERNEL__ #ifndef _PPC_PGTABLE_H @@ -20,8 +20,8 @@ extern void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); extern void local_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end); -static inline void flush_hash_page(unsigned context, unsigned long va) - { } +#define update_mmu_cache(vma, addr, pte) do { } while (0) + #elif defined(CONFIG_8xx) #define __tlbia() asm volatile ("tlbia" : : ) @@ -35,9 +35,9 @@ static inline void local_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) { __tlbia(); } -static inline void flush_hash_page(unsigned context, unsigned long va) - { } -#else +#define update_mmu_cache(vma, addr, pte) do { } while (0) + +#else /* 6xx, 7xx, 7xxx cpus */ struct mm_struct; struct vm_area_struct; extern void local_flush_tlb_all(void); @@ -45,6 +45,15 @@ extern void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); extern void local_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end); + +/* + * This gets called at the end of handling a page fault, when + * the kernel has put a new PTE into the page table for the process. + * We use it to put a corresponding HPTE into the hash table + * ahead of time, instead of waiting for the inevitable extra + * hash-table miss exception. + */ +extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); #endif #define flush_tlb_all local_flush_tlb_all @@ -52,16 +61,20 @@ #define flush_tlb_page local_flush_tlb_page #define flush_tlb_range local_flush_tlb_range +/* + * This is called in munmap when we have freed up some page-table + * pages. We don't need to do anything here, there's nothing special + * about our page-table pages. -- paulus + */ static inline void flush_tlb_pgtables(struct mm_struct *mm, - unsigned long start, unsigned long end) + unsigned long start, unsigned long end) { - /* PPC has hw page tables. */ } /* * No cache flushing is required when address mappings are * changed, because the caches on PowerPCs are physically - * addressed. + * addressed. -- paulus * Also, when SMP we use the coherency (M) bit of the * BATs and PTEs. -- Cort */ @@ -88,12 +101,12 @@ * the virtual to physical address mapping. * * We use the hash table as an extended TLB, i.e. a cache of currently - * active mappings. We maintain a two-level page table tree, much like - * that used by the i386, for the sake of the Linux memory management code. - * Low-level assembler code in head.S (procedure hash_page) is responsible - * for extracting ptes from the tree and putting them into the hash table - * when necessary, and updating the accessed and modified bits in the - * page table tree. + * active mappings. We maintain a two-level page table tree, much + * like that used by the i386, for the sake of the Linux memory + * management code. Low-level assembler code in hashtable.S + * (procedure hash_page) is responsible for extracting ptes from the + * tree and putting them into the hash table when necessary, and + * updating the accessed and modified bits in the page table tree. */ /* @@ -189,12 +202,11 @@ #define _PAGE_NO_CACHE 0x004 /* I: caching is inhibited */ #define _PAGE_WRITETHRU 0x008 /* W: caching is write-through */ #define _PAGE_USER 0x010 /* matches one of the zone permission bits */ +#define _PAGE_EXEC 0x020 /* software: i-cache coherency required */ #define _PAGE_PRESENT 0x040 /* software: PTE contains a translation */ #define _PAGE_DIRTY 0x100 /* C: page changed */ #define _PAGE_RW 0x200 /* Writes permitted */ #define _PAGE_ACCESSED 0x400 /* R: page referenced */ -#define _PAGE_HWWRITE 0x800 /* software: _PAGE_RW & _PAGE_DIRTY */ -#define _PAGE_SHARED 0 #elif defined(CONFIG_8xx) /* Definitions for 8xx embedded chips. */ @@ -205,48 +217,62 @@ /* These five software bits must be masked out when the entry is loaded * into the TLB. */ -#define _PAGE_DIRTY 0x0008 /* software: page changed */ +#define _PAGE_EXEC 0x0008 /* software: i-cache coherency required */ #define _PAGE_GUARDED 0x0010 /* software: guarded access */ #define _PAGE_WRITETHRU 0x0020 /* software: use writethrough cache */ #define _PAGE_RW 0x0040 /* software: user write access allowed */ #define _PAGE_ACCESSED 0x0080 /* software: page referenced */ -#define _PAGE_HWWRITE 0x0100 /* C: page changed (write protect) */ -#define _PAGE_USER 0x0800 /* One of the PP bits, the other must be 0 */ +#define _PAGE_DIRTY 0x0100 /* C: page changed (write protect) */ +#define _PAGE_USER 0x0800 /* One of the PP bits, the other is USER&~RW */ #else /* CONFIG_6xx */ /* Definitions for 60x, 740/750, etc. */ #define _PAGE_PRESENT 0x001 /* software: pte contains a translation */ -#define _PAGE_USER 0x002 /* matches one of the PP bits */ -#define _PAGE_RW 0x004 /* software: user write access allowed */ -#define _PAGE_GUARDED 0x008 +#define _PAGE_HASHPTE 0x002 /* hash_page has made an HPTE for this pte */ +#define _PAGE_USER 0x004 /* usermode access allowed */ +#define _PAGE_GUARDED 0x008 /* G: prohibit speculative access */ #define _PAGE_COHERENT 0x010 /* M: enforce memory coherence (SMP systems) */ #define _PAGE_NO_CACHE 0x020 /* I: cache inhibit */ #define _PAGE_WRITETHRU 0x040 /* W: cache write-through */ #define _PAGE_DIRTY 0x080 /* C: page changed */ #define _PAGE_ACCESSED 0x100 /* R: page referenced */ -#define _PAGE_HWWRITE 0x200 /* software: _PAGE_RW & _PAGE_DIRTY */ +#define _PAGE_EXEC 0x200 /* software: i-cache coherency required */ +#define _PAGE_RW 0x400 /* software: user write access allowed */ +#endif + +#ifndef _PAGE_HASHPTE +#define _PAGE_HASHPTE 0 +#endif +#ifndef _PAGE_SHARED #define _PAGE_SHARED 0 #endif #define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) -#ifdef CONFIG_SMP -#define _PAGE_BASE _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_COHERENT -#else +/* + * Note: the _PAGE_COHERENT bit automatically gets set in the hardware + * PTE if CONFIG_SMP is defined (hash_page does this); there is no need + * to have it in the Linux PTE, and in fact the bit could be reused for + * another purpose. -- paulus. + */ #define _PAGE_BASE _PAGE_PRESENT | _PAGE_ACCESSED -#endif -#define _PAGE_WRENABLE _PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE +#define _PAGE_WRENABLE _PAGE_RW | _PAGE_DIRTY -#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED) +#define _PAGE_KERNEL _PAGE_BASE | _PAGE_WRENABLE | _PAGE_SHARED +#define _PAGE_IO _PAGE_KERNEL | _PAGE_NO_CACHE | _PAGE_GUARDED -#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_RW | _PAGE_USER | \ - _PAGE_SHARED) -#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER) +#define PAGE_NONE __pgprot(_PAGE_BASE) #define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER) -#define PAGE_KERNEL __pgprot(_PAGE_BASE | _PAGE_WRENABLE | _PAGE_SHARED) -#define PAGE_KERNEL_CI __pgprot(_PAGE_BASE | _PAGE_WRENABLE | _PAGE_SHARED | \ - _PAGE_NO_CACHE ) +#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) +#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW) +#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC) +#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER) +#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) + +#define PAGE_KERNEL __pgprot(_PAGE_KERNEL) +#define PAGE_KERNEL_RO __pgprot(_PAGE_BASE | _PAGE_SHARED) +#define PAGE_KERNEL_CI __pgprot(_PAGE_IO) /* * The PowerPC can only do execute protection on a segment (256MB) basis, @@ -255,22 +281,22 @@ * This is the closest we can get.. */ #define __P000 PAGE_NONE -#define __P001 PAGE_READONLY +#define __P001 PAGE_READONLY_X #define __P010 PAGE_COPY -#define __P011 PAGE_COPY +#define __P011 PAGE_COPY_X #define __P100 PAGE_READONLY -#define __P101 PAGE_READONLY +#define __P101 PAGE_READONLY_X #define __P110 PAGE_COPY -#define __P111 PAGE_COPY +#define __P111 PAGE_COPY_X #define __S000 PAGE_NONE -#define __S001 PAGE_READONLY +#define __S001 PAGE_READONLY_X #define __S010 PAGE_SHARED -#define __S011 PAGE_SHARED +#define __S011 PAGE_SHARED_X #define __S100 PAGE_READONLY -#define __S101 PAGE_READONLY +#define __S101 PAGE_READONLY_X #define __S110 PAGE_SHARED -#define __S111 PAGE_SHARED +#define __S111 PAGE_SHARED_X #ifndef __ASSEMBLY__ /* @@ -280,33 +306,11 @@ extern unsigned long empty_zero_page[1024]; #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) -/* - * BAD_PAGETABLE is used when we need a bogus page-table, while - * BAD_PAGE is used for a bogus page. - * - * ZERO_PAGE is a global shared page that is always zero: used - * for zero-mapped memory areas etc.. - */ -extern pte_t __bad_page(void); -extern pte_t * __bad_pagetable(void); - -#define BAD_PAGETABLE __bad_pagetable() -#define BAD_PAGE __bad_page() #endif /* __ASSEMBLY__ */ -/* number of bits that fit into a memory pointer */ -#define BITS_PER_PTR (8*sizeof(unsigned long)) - -/* to align the pointer to a pointer address */ -#define PTR_MASK (~(sizeof(void*)-1)) - -/* sizeof(void*) == 1<virtual) -#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) +#define page_address(page) ((page)->virtual) #define pte_page(x) (mem_map+(unsigned long)((pte_val(x) >> PAGE_SHIFT))) #ifndef __ASSEMBLY__ @@ -340,7 +343,7 @@ */ static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; } static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; } -static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_USER; } +static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_EXEC; } static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } @@ -349,42 +352,26 @@ static inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_USER; return pte; } -static inline pte_t pte_exprotect(pte_t pte) { - pte_val(pte) &= ~_PAGE_USER; return pte; } static inline pte_t pte_wrprotect(pte_t pte) { - pte_val(pte) &= ~(_PAGE_RW | _PAGE_HWWRITE); return pte; } + pte_val(pte) &= ~_PAGE_RW; return pte; } +static inline pte_t pte_exprotect(pte_t pte) { + pte_val(pte) &= ~_PAGE_EXEC; return pte; } static inline pte_t pte_mkclean(pte_t pte) { - pte_val(pte) &= ~(_PAGE_DIRTY | _PAGE_HWWRITE); return pte; } + pte_val(pte) &= ~_PAGE_DIRTY; return pte; } static inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; } static inline pte_t pte_mkread(pte_t pte) { pte_val(pte) |= _PAGE_USER; return pte; } static inline pte_t pte_mkexec(pte_t pte) { - pte_val(pte) |= _PAGE_USER; return pte; } -static inline pte_t pte_mkwrite(pte_t pte) -{ - pte_val(pte) |= _PAGE_RW; - if (pte_val(pte) & _PAGE_DIRTY) - pte_val(pte) |= _PAGE_HWWRITE; - return pte; -} -static inline pte_t pte_mkdirty(pte_t pte) -{ - pte_val(pte) |= _PAGE_DIRTY; - if (pte_val(pte) & _PAGE_RW) - pte_val(pte) |= _PAGE_HWWRITE; - return pte; -} + pte_val(pte) |= _PAGE_USER | _PAGE_EXEC; return pte; } +static inline pte_t pte_mkwrite(pte_t pte) { + pte_val(pte) |= _PAGE_RW; return pte; } +static inline pte_t pte_mkdirty(pte_t pte) { + pte_val(pte) |= _PAGE_DIRTY; return pte; } static inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; } -/* Certain architectures need to do special things when pte's - * within a page table are directly modified. Thus, the following - * hook is made available. - */ -#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval)) - /* * Conversion functions: convert a page and protection to a page entry, * and a page entry and page directory to the page they refer to. @@ -421,11 +408,11 @@ { unsigned long old, tmp; - __asm__ __volatile__("\n\ -1: lwarx %0,0,%3 \n\ - andc %1,%0,%4 \n\ - or %1,%1,%5 \n\ - stwcx. %1,0,%3 \n\ + __asm__ __volatile__("\ +1: lwarx %0,0,%3\n\ + andc %1,%0,%4\n\ + or %1,%1,%5\n\ + stwcx. %1,0,%3\n\ bne- 1b" : "=&r" (old), "=&r" (tmp), "=m" (*p) : "r" (p), "r" (clr), "r" (set), "m" (*p) @@ -433,6 +420,12 @@ return old; } +/* + * Writing a new value into the PTE doesn't disturb the state of the + * _PAGE_HASHPTE bit, on those machines which use an MMU hash table. + */ +extern void set_pte(pte_t *ptep, pte_t pte); + static inline int ptep_test_and_clear_young(pte_t *ptep) { return (pte_update(ptep, _PAGE_ACCESSED, 0) & _PAGE_ACCESSED) != 0; @@ -440,36 +433,25 @@ static inline int ptep_test_and_clear_dirty(pte_t *ptep) { - return (pte_update(ptep, _PAGE_DIRTY | _PAGE_HWWRITE, 0) - & _PAGE_DIRTY) != 0; + return (pte_update(ptep, _PAGE_DIRTY, 0) & _PAGE_DIRTY) != 0; } static inline pte_t ptep_get_and_clear(pte_t *ptep) { - return __pte(pte_update(ptep, ~0UL, 0)); + return __pte(pte_update(ptep, ~_PAGE_HASHPTE, 0)); } static inline void ptep_set_wrprotect(pte_t *ptep) { - pte_update(ptep, _PAGE_RW | _PAGE_HWWRITE, 0); + pte_update(ptep, _PAGE_RW, 0); } static inline void ptep_mkdirty(pte_t *ptep) { - /* - * N.B. this doesn't set the _PAGE_HWWRITE bit in the case - * where _PAGE_RW is set and _PAGE_DIRTY was clear. This - * doesn't matter; all it will mean is that if the next call - * to hash_page for this page is for a read, it will put a - * readonly HPTE into the hash table rather than a R/W HPTE. - * A call to hash_page for a write to this page will set - * _PAGE_HWWRITE and put a R/W HPTE into the hash table. - * -- paulus. - */ pte_update(ptep, 0, _PAGE_DIRTY); } -#define pte_same(A,B) (pte_val(A) == pte_val(B)) +#define pte_same(A,B) (((pte_val(A) ^ pte_val(B)) & ~_PAGE_HASHPTE) == 0) #define pmd_page(pmd) (pmd_val(pmd)) @@ -496,25 +478,25 @@ extern void paging_init(void); /* - * Page tables may have changed. We don't need to do anything here - * as entries are faulted into the hash table by the low-level - * data/instruction access exception handlers. + * When flushing the tlb entry for a page, we also need to flush the hash + * table entry. flush_hash_page is assembler (for speed) in hashtable.S. */ -#define update_mmu_cache(vma, addr, pte) do { } while (0) +extern int flush_hash_page(unsigned context, unsigned long va, pte_t *ptep); + +/* Add an HPTE to the hash table */ +extern void add_hash_page(unsigned context, unsigned long va, pte_t *ptep); /* - * When flushing the tlb entry for a page, we also need to flush the - * hash table entry. flush_hash_page is assembler (for speed) in head.S. + * Encode and decode a swap entry. + * Note that the bits we use in a PTE for representing a swap entry + * must not include the _PAGE_PRESENT bit, or the _PAGE_HASHPTE bit + * (if used). -- paulus */ -extern void flush_hash_segments(unsigned low_vsid, unsigned high_vsid); -extern void flush_hash_page(unsigned context, unsigned long va); - -/* 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) }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) +#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 */ @@ -545,7 +527,6 @@ unsigned int cmode); /* 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 -u --recursive --new-file v2.4.5/linux/include/asm-ppc/processor.h linux/include/asm-ppc/processor.h --- v2.4.5/linux/include/asm-ppc/processor.h Thu May 24 15:03:05 2001 +++ linux/include/asm-ppc/processor.h Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.processor.h 1.19 05/18/01 08:18:10 patch + * BK Id: SCCS/s.processor.h 1.24 06/15/01 13:56:56 paulus */ #ifdef __KERNEL__ #ifndef __ASM_PPC_PROCESSOR_H @@ -445,6 +445,7 @@ #define PVR_403GC 0x00200200 #define PVR_403GCX 0x00201400 #define PVR_405GP 0x40110000 +#define PVR_STB03XXX 0x40310000 #define PVR_601 0x00010000 #define PVR_602 0x00050000 #define PVR_603 0x00030000 @@ -459,6 +460,8 @@ #define PVR_750 PVR_740 #define PVR_740P 0x10080000 #define PVR_750P PVR_740P +#define PVR_7400 0x000C0000 +#define PVR_7410 0x800C0000 /* * For the 8xx processors, all of them report the same PVR family for * the PowerPC core. The various versions of these processors must be @@ -469,7 +472,6 @@ #define PVR_823 PVR_821 #define PVR_850 PVR_821 #define PVR_860 PVR_821 -#define PVR_7400 0x000C0000 #define PVR_8240 0x00810100 #define PVR_8260 PVR_8240 diff -u --recursive --new-file v2.4.5/linux/include/asm-ppc/prom.h linux/include/asm-ppc/prom.h --- v2.4.5/linux/include/asm-ppc/prom.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/prom.h Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.prom.h 1.11 05/18/01 08:18:10 patch + * BK Id: SCCS/s.prom.h 1.14 06/13/01 15:28:43 paulus */ /* * Definitions for talking to the Open Firmware PROM on @@ -45,6 +45,9 @@ struct property *next; }; +/* + * Note: don't change this structure for now or you'll break BootX ! + */ struct device_node { char *name; char *type; @@ -60,10 +63,6 @@ struct device_node *sibling; struct device_node *next; /* next device of same type */ struct device_node *allnext; /* next in list of all nodes */ -#if 0 /* Don't change this structure for now or you'll break BootX ! */ - int n_addr_cells; - int n_size_cells; -#endif }; struct prom_args; @@ -101,6 +100,24 @@ extern void map_bootx_text(void); extern void bootx_update_display(unsigned long phys, int width, int height, int depth, int pitch); + +/* + * When we call back to the Open Firmware client interface, we usually + * have to do that before the kernel is relocated to its final location + * (this is because we can't use OF after we have overwritten the + * exception vectors with our exception handlers). These macros assist + * in performing the address calculations that we need to do to access + * data when the kernel is running at an address that is different from + * the address that the kernel is linked at. The reloc_offset() function + * returns the difference between these two addresses and the macros + * simplify the process of adding or subtracting this offset to/from + * pointer values. See arch/ppc/kernel/prom.c for how these are used. + */ +extern unsigned long reloc_offset(void); + +#define PTRRELOC(x) ((typeof(x))((unsigned long)(x) + offset)) +#define PTRUNRELOC(x) ((typeof(x))((unsigned long)(x) - offset)) +#define RELOC(x) (*PTRRELOC(&(x))) #endif /* _PPC_PROM_H */ #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.4.5/linux/include/asm-ppc/socket.h linux/include/asm-ppc/socket.h --- v2.4.5/linux/include/asm-ppc/socket.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/socket.h Wed Jun 20 21:00:55 2001 @@ -67,6 +67,7 @@ /* level. For writing rarp and */ /* other similar things on the */ /* user level. */ +#define SOCK_MAX (SOCK_PACKET+1) #endif #endif /* _ASM_SOCKET_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-ppc/softirq.h linux/include/asm-ppc/softirq.h --- v2.4.5/linux/include/asm-ppc/softirq.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/softirq.h Tue Jun 12 11:07:16 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.softirq.h 1.5 05/17/01 18:14:25 cort + * BK Id: SCCS/s.softirq.h 1.10 06/09/01 22:16:38 paulus */ #ifdef __KERNEL__ #ifndef __ASM_SOFTIRQ_H @@ -8,8 +8,29 @@ #include #include -#define local_bh_disable() do { local_bh_count(smp_processor_id())++; barrier(); } while (0) -#define local_bh_enable() do { barrier(); local_bh_count(smp_processor_id())--; } while (0) +#define local_bh_disable() \ +do { \ + local_bh_count(smp_processor_id())++; \ + barrier(); \ +} while (0) + +#define __local_bh_enable() \ +do { \ + barrier(); \ + local_bh_count(smp_processor_id())--; \ +} while (0) + +#define local_bh_enable() \ +do { \ + if (!--local_bh_count(smp_processor_id()) \ + && softirq_pending(smp_processor_id())) { \ + do_softirq(); \ + __sti(); \ + } \ +} while (0) + +#define __cpu_raise_softirq(cpu, nr) set_bit((nr), &softirq_pending(cpu)); +#define raise_softirq(nr) __cpu_raise_softirq(smp_processor_id(), (nr)) #define in_softirq() (local_bh_count(smp_processor_id()) != 0) diff -u --recursive --new-file v2.4.5/linux/include/asm-ppc/termios.h linux/include/asm-ppc/termios.h --- v2.4.5/linux/include/asm-ppc/termios.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/termios.h Mon Jun 11 19:15:27 2001 @@ -193,6 +193,7 @@ #define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */ #define N_HDLC 13 /* synchronous HDLC */ #define N_SYNC_PPP 14 +#define N_HCI 15 /* Bluetooth HCI UART */ #ifdef __KERNEL__ diff -u --recursive --new-file v2.4.5/linux/include/asm-ppc/time.h linux/include/asm-ppc/time.h --- v2.4.5/linux/include/asm-ppc/time.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/time.h Mon Jul 2 14:34:57 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.time.h 1.10 05/17/01 18:14:26 cort + * BK Id: SCCS/s.time.h 1.13 06/27/01 14:49:58 trini */ /* * Common time prototypes and such for all ppc machines. @@ -23,6 +23,8 @@ extern void to_tm(int tim, struct rtc_time * tm); extern time_t last_rtc_update; + +extern void set_dec_cpu6(unsigned int val); int via_calibrate_decr(void); diff -u --recursive --new-file v2.4.5/linux/include/asm-s390/socket.h linux/include/asm-s390/socket.h --- v2.4.5/linux/include/asm-s390/socket.h Sat Feb 3 11:26:44 2001 +++ linux/include/asm-s390/socket.h Wed Jun 20 21:00:55 2001 @@ -66,6 +66,7 @@ /* level. For writing rarp and */ /* other similar things on the */ /* user level. */ +#define SOCK_MAX (SOCK_PACKET+1) #endif #endif /* _ASM_SOCKET_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-s390/termios.h linux/include/asm-s390/termios.h --- v2.4.5/linux/include/asm-s390/termios.h Tue Feb 13 14:13:44 2001 +++ linux/include/asm-s390/termios.h Mon Jun 11 19:15:27 2001 @@ -63,6 +63,7 @@ #define N_IRDA 11 /* Linux IR - http://irda.sourceforge.net/ */ #define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */ #define N_HDLC 13 /* synchronous HDLC */ +#define N_HCI 15 /* Bluetooth HCI UART */ #ifdef __KERNEL__ diff -u --recursive --new-file v2.4.5/linux/include/asm-s390x/socket.h linux/include/asm-s390x/socket.h --- v2.4.5/linux/include/asm-s390x/socket.h Fri Mar 2 11:12:06 2001 +++ linux/include/asm-s390x/socket.h Wed Jun 20 21:00:55 2001 @@ -65,6 +65,7 @@ /* level. For writing rarp and */ /* other similar things on the */ /* user level. */ +#define SOCK_MAX (SOCK_PACKET+1) #endif #endif /* _ASM_SOCKET_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-s390x/termios.h linux/include/asm-s390x/termios.h --- v2.4.5/linux/include/asm-s390x/termios.h Wed Apr 11 19:02:29 2001 +++ linux/include/asm-s390x/termios.h Mon Jun 11 19:15:27 2001 @@ -63,6 +63,7 @@ #define N_IRDA 11 /* Linux IR - http://irda.sourceforge.net/ */ #define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */ #define N_HDLC 13 /* synchronous HDLC */ +#define N_BT 15 /* bluetooth */ #ifdef __KERNEL__ diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/bigsur.h linux/include/asm-sh/bigsur.h --- v2.4.5/linux/include/asm-sh/bigsur.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-sh/bigsur.h Wed Jun 27 13:55:29 2001 @@ -0,0 +1,80 @@ +/* + * + * Hitachi Big Sur Eval Board support + * + * Dustin McIntire (dustin@sensoria.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Derived from Hitachi SH7751 reference manual + * + */ + +#ifndef _ASM_BIGSUR_H_ +#define _ASM_BIGSUR_H_ + +#include +#include + +/* 7751 Internal IRQ's used by external CPLD controller */ +#define BIGSUR_IRQ_LOW 0 +#define BIGSUR_IRQ_NUM 14 /* External CPLD level 1 IRQs */ +#define BIGSUR_IRQ_HIGH (BIGSUR_IRQ_LOW + BIGSUR_IRQ_NUM) +#define BIGSUR_2NDLVL_IRQ_LOW (HD64465_IRQ_BASE+HD64465_IRQ_NUM) +#define BIGSUR_2NDLVL_IRQ_NUM 32 /* Level 2 IRQs = 4 regs * 8 bits */ +#define BIGSUR_2NDLVL_IRQ_HIGH (BIGSUR_2NDLVL_IRQ_LOW + \ + BIGSUR_2NDLVL_IRQ_NUM) + +/* PCI interrupt base number (A_INTA-A_INTD) */ +#define BIGSUR_SH7751_PCI_IRQ_BASE (BIGSUR_2NDLVL_IRQ_LOW+10) + +/* CPLD registers and external chip addresses */ +#define BIGSUR_HD64464_ADDR 0xB2000000 +#define BIGSUR_DGDR 0xB1FFFE00 +#define BIGSUR_BIDR 0xB1FFFD00 +#define BIGSUR_CSLR 0xB1FFFC00 +#define BIGSUR_SW1R 0xB1FFFB00 +#define BIGSUR_DBGR 0xB1FFFA00 +#define BIGSUR_BDTR 0xB1FFF900 +#define BIGSUR_BDRR 0xB1FFF800 +#define BIGSUR_PPR1 0xB1FFF700 +#define BIGSUR_PPR2 0xB1FFF600 +#define BIGSUR_IDE2 0xB1FFF500 +#define BIGSUR_IDE3 0xB1FFF400 +#define BIGSUR_SPCR 0xB1FFF300 +#define BIGSUR_ETHR 0xB1FE0000 +#define BIGSUR_PPDR 0xB1FDFF00 +#define BIGSUR_ICTL 0xB1FDFE00 +#define BIGSUR_ICMD 0xB1FDFD00 +#define BIGSUR_DMA0 0xB1FDFC00 +#define BIGSUR_DMA1 0xB1FDFB00 +#define BIGSUR_IRQ0 0xB1FDFA00 +#define BIGSUR_IRQ1 0xB1FDF900 +#define BIGSUR_IRQ2 0xB1FDF800 +#define BIGSUR_IRQ3 0xB1FDF700 +#define BIGSUR_IMR0 0xB1FDF600 +#define BIGSUR_IMR1 0xB1FDF500 +#define BIGSUR_IMR2 0xB1FDF400 +#define BIGSUR_IMR3 0xB1FDF300 +#define BIGSUR_IRLMR0 0xB1FDF200 +#define BIGSUR_IRLMR1 0xB1FDF100 +#define BIGSUR_V320USC_ADDR 0xB1000000 +#define BIGSUR_HD64465_ADDR 0xB0000000 +#define BIGSUR_INTERNAL_BASE 0xB0000000 + +/* SMC ethernet card parameters */ +#define BIGSUR_ETHER_IOPORT 0x220 + +/* IDE register paramters */ +#define BIGSUR_IDECMD_IOPORT 0x1f0 +#define BIGSUR_IDECTL_IOPORT 0x1f8 + +/* LED bit position in BIGSUR_CSLR */ +#define BIGSUR_LED (1<<4) + +/* PCI: default LOCAL memory window sizes (seen from PCI bus) */ +#define BIGSUR_LSR0_SIZE (64*(1<<20)) //64MB +#define BIGSUR_LSR1_SIZE (64*(1<<20)) //64MB + +#endif /* _ASM_BIGSUR_H_ */ diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/bitops.h linux/include/asm-sh/bitops.h --- v2.4.5/linux/include/asm-sh/bitops.h Mon Oct 2 11:57:34 2000 +++ linux/include/asm-sh/bitops.h Wed Jun 27 13:55:29 2001 @@ -19,6 +19,16 @@ restore_flags(flags); } +static __inline__ void __set_bit(int nr, volatile void * addr) +{ + int mask; + volatile unsigned int *a = addr; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + *a |= mask; +} + /* * clear_bit() doesn't provide any barrier for the compiler. */ @@ -37,6 +47,16 @@ restore_flags(flags); } +static __inline__ void __clear_bit(int nr, volatile void * addr) +{ + int mask; + volatile unsigned int *a = addr; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + *a &= ~mask; +} + static __inline__ void change_bit(int nr, volatile void * addr) { int mask; @@ -50,6 +70,16 @@ restore_flags(flags); } +static __inline__ void __change_bit(int nr, volatile void * addr) +{ + int mask; + volatile unsigned int *a = addr; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + *a ^= mask; +} + static __inline__ int test_and_set_bit(int nr, volatile void * addr) { int mask, retval; @@ -66,6 +96,19 @@ return retval; } +static __inline__ int __test_and_set_bit(int nr, volatile void * addr) +{ + int mask, retval; + volatile unsigned int *a = addr; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + retval = (mask & *a) != 0; + *a |= mask; + + return retval; +} + static __inline__ int test_and_clear_bit(int nr, volatile void * addr) { int mask, retval; @@ -82,6 +125,19 @@ return retval; } +static __inline__ int __test_and_clear_bit(int nr, volatile void * addr) +{ + int mask, retval; + volatile unsigned int *a = addr; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + retval = (mask & *a) != 0; + *a &= ~mask; + + return retval; +} + static __inline__ int test_and_change_bit(int nr, volatile void * addr) { int mask, retval; @@ -98,6 +154,18 @@ return retval; } +static __inline__ int __test_and_change_bit(int nr, volatile void * addr) +{ + int mask, retval; + volatile unsigned int *a = addr; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + retval = (mask & *a) != 0; + *a ^= mask; + + return retval; +} static __inline__ int test_bit(int nr, const volatile void *addr) { @@ -156,6 +224,23 @@ #define find_first_zero_bit(addr, size) \ find_next_zero_bit((addr), (size), 0) + +/* + * ffs: find first bit set. This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ + +#define ffs(x) generic_ffs(x) + +/* + * hweightN: returns the hamming weight (i.e. the number + * of bits set) of a N-bit word + */ + +#define hweight32(x) generic_hweight32(x) +#define hweight16(x) generic_hweight16(x) +#define hweight8(x) generic_hweight8(x) #ifdef __LITTLE_ENDIAN__ #define ext2_set_bit(nr, addr) test_and_set_bit((nr), (addr)) diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/bugs.h linux/include/asm-sh/bugs.h --- v2.4.5/linux/include/asm-sh/bugs.h Wed Apr 11 21:24:52 2001 +++ linux/include/asm-sh/bugs.h Wed Jun 27 13:55:29 2001 @@ -32,7 +32,7 @@ break; case CPU_SH7750: *p++ = '4'; - printk("CPU: SH7750\n"); + printk("CPU: SH7750/SH7751\n"); break; case CPU_ST40STB1: *p++ = '4'; diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/dc_sysasic.h linux/include/asm-sh/dc_sysasic.h --- v2.4.5/linux/include/asm-sh/dc_sysasic.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-sh/dc_sysasic.h Wed Jun 27 13:55:29 2001 @@ -0,0 +1,35 @@ +/* include/asm-sh/dc_sysasic.h + * + * Definitions for the Dreamcast System ASIC and related peripherals. + * + * Copyright (c) 2001 M. R. Brown + * + * This file is part of the LinuxDC project (www.linuxdc.org) + * + * Released under the terms of the GNU GPL v2.0. + * + */ + +#include + +/* Hardware events - + + Each of these events correspond to a bit within the Event Mask Registers/ + Event Status Registers. Because of the virtual IRQ numbering scheme, a + base offset must be used when calculating the virtual IRQ that each event + takes. +*/ + +#define HW_EVENT_IRQ_BASE OFFCHIP_IRQ_BASE /* 48 */ + +/* IRQ 13 */ +#define HW_EVENT_VSYNC (HW_EVENT_IRQ_BASE + 5) /* VSync */ +#define HW_EVENT_MAPLE_DMA (HW_EVENT_IRQ_BASE + 12) /* Maple DMA complete */ +#define HW_EVENT_GDROM_DMA (HW_EVENT_IRQ_BASE + 14) /* GD-ROM DMA complete */ + +/* IRQ 11 */ +#define HW_EVENT_GDROM_CMD (HW_EVENT_IRQ_BASE + 32) /* GD-ROM cmd. complete */ +#define HW_EVENT_AICA_SYS (HW_EVENT_IRQ_BASE + 33) /* AICA-related */ +#define HW_EVENT_EXTERNAL (HW_EVENT_IRQ_BASE + 35) /* Ext. (expansion) */ + +#define HW_EVENT_IRQ_MAX (HW_EVENT_IRQ_BASE + 95) diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/hardirq.h linux/include/asm-sh/hardirq.h --- v2.4.5/linux/include/asm-sh/hardirq.h Fri Aug 4 16:15:37 2000 +++ linux/include/asm-sh/hardirq.h Wed Jun 27 13:55:29 2001 @@ -6,8 +6,7 @@ /* entry.S is sensitive to the offsets of these fields */ typedef struct { - unsigned int __softirq_active; - unsigned int __softirq_mask; + unsigned int __softirq_pending; unsigned int __local_irq_count; unsigned int __local_bh_count; unsigned int __syscall_count; diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/hd64465_gpio.h linux/include/asm-sh/hd64465_gpio.h --- v2.4.5/linux/include/asm-sh/hd64465_gpio.h Sun May 20 12:11:39 2001 +++ linux/include/asm-sh/hd64465_gpio.h Wed Jun 27 13:55:29 2001 @@ -1,7 +1,7 @@ #ifndef _ASM_SH_HD64465_GPIO_ #define _ASM_SH_HD64465_GPIO_ 1 /* - * $Id: hd64465_gpio.h,v 1.1 2001/01/02 15:35:22 mjd Exp $ + * $Id: hd64465_gpio.h,v 1.2 2001/05/24 00:14:13 gniibe Exp $ * * Hitachi HD64465 companion chip: General Purpose IO pins support. * This layer enables other device drivers to configure GPIO diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/hitachi_se.h linux/include/asm-sh/hitachi_se.h --- v2.4.5/linux/include/asm-sh/hitachi_se.h Mon Jun 19 17:59:38 2000 +++ linux/include/asm-sh/hitachi_se.h Mon Jul 2 13:56:40 2001 @@ -38,7 +38,7 @@ #define PA_LED 0xb0c00000 /* LED */ #define PA_BCR 0xb1400000 /* FPGA */ -#define PA_MRSHPC 0xb83fffe0 /* MR-SHPC-01 PCMCIA controler */ +#define PA_MRSHPC 0xb83fffe0 /* MR-SHPC-01 PCMCIA controller */ #define PA_MRSHPC_MW1 0xb8400000 /* MR-SHPC-01 memory window base */ #define PA_MRSHPC_MW2 0xb8500000 /* MR-SHPC-01 attribute window base */ #define PA_MRSHPC_IO 0xb8600000 /* MR-SHPC-01 I/O window base */ diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/io.h linux/include/asm-sh/io.h --- v2.4.5/linux/include/asm-sh/io.h Wed Apr 11 21:24:52 2001 +++ linux/include/asm-sh/io.h Wed Jun 27 13:55:29 2001 @@ -109,10 +109,10 @@ # if defined(CONFIG_SH_HP600) # include -# elif defined(CONFIG_SH_7750_OVERDRIVE) -# include -# elif defined(CONFIG_SH_SOLUTION_ENGINE) +# elif (defined(CONFIG_SH_SOLUTION_ENGINE) || defined(CONFIG_SH_7751_SOLUTION_ENGINE)) # include +# elif defined(CONFIG_SH_SH2000) +# include # elif defined(CONFIG_SH_DMIDA) || \ defined(CONFIG_SH_STB1_HARP) || \ defined(CONFIG_SH_STB1_OVERDRIVE) @@ -123,6 +123,8 @@ # include # elif defined(CONFIG_SH_CAT68701) # include +# elif defined(CONFIG_SH_BIGSUR) +# include # elif defined(CONFIG_SH_UNKNOWN) # include # else diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/io_bigsur.h linux/include/asm-sh/io_bigsur.h --- v2.4.5/linux/include/asm-sh/io_bigsur.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-sh/io_bigsur.h Wed Jun 27 13:55:29 2001 @@ -0,0 +1,89 @@ +/* + * include/asm-sh/io_bigsur.h + * + * By Dustin McIntire (dustin@sensoria.com) (c)2001 + * Derived from io_hd64465.h, which bore the message: + * By Greg Banks + * (c) 2000 PocketPenguins Inc. + * and from io_hd64461.h, which bore the message: + * Copyright 2000 Stuart Menefy (stuart.menefy@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * IO functions for a Hitachi Big Sur Evaluation Board. + */ + +#ifndef _ASM_SH_IO_BIGSUR_H +#define _ASM_SH_IO_BIGSUR_H + +#include +#include + +extern unsigned char bigsur_inb(unsigned long port); +extern unsigned short bigsur_inw(unsigned long port); +extern unsigned int bigsur_inl(unsigned long port); + +extern void bigsur_outb(unsigned char value, unsigned long port); +extern void bigsur_outw(unsigned short value, unsigned long port); +extern void bigsur_outl(unsigned int value, unsigned long port); + +extern unsigned char bigsur_inb_p(unsigned long port); +extern void bigsur_outb_p(unsigned char value, unsigned long port); + +extern void bigsur_insb(unsigned long port, void *addr, unsigned long count); +extern void bigsur_insw(unsigned long port, void *addr, unsigned long count); +extern void bigsur_insl(unsigned long port, void *addr, unsigned long count); +extern void bigsur_outsb(unsigned long port, const void *addr, unsigned long count); +extern void bigsur_outsw(unsigned long port, const void *addr, unsigned long count); +extern void bigsur_outsl(unsigned long port, const void *addr, unsigned long count); +extern unsigned long bigsur_isa_port2addr(unsigned long offset); +extern int bigsur_irq_demux(int irq); +extern void bigsur_init_pci(void); +/* Provision for generic secondary demux step -- used by PCMCIA code */ +extern void bigsur_register_irq_demux(int irq, + int (*demux)(int irq, void *dev), void *dev); +extern void bigsur_unregister_irq_demux(int irq); +/* Set this variable to 1 to see port traffic */ +extern int bigsur_io_debug; +/* Map a range of ports to a range of kernel virtual memory. */ +extern void bigsur_port_map(u32 baseport, u32 nports, u32 addr, u8 shift); +extern void bigsur_port_unmap(u32 baseport, u32 nports); + +#endif /* _ASM_SH_IO_BIGSUR_H */ + +#ifdef __WANT_IO_DEF + +# define __inb bigsur_inb +# define __inw bigsur_inw +# define __inl bigsur_inl +# define __outb bigsur_outb +# define __outw bigsur_outw +# define __outl bigsur_outl + +# define __inb_p bigsur_inb_p +# define __inw_p bigsur_inw +# define __inl_p bigsur_inl +# define __outb_p bigsur_outb_p +# define __outw_p bigsur_outw +# define __outl_p bigsur_outl + +# define __insb bigsur_insb +# define __insw bigsur_insw +# define __insl bigsur_insl +# define __outsb bigsur_outsb +# define __outsw bigsur_outsw +# define __outsl bigsur_outsl + +# define __readb generic_readb +# define __readw generic_readw +# define __readl generic_readl +# define __writeb generic_writeb +# define __writew generic_writew +# define __writel generic_writel + +# define __isa_port2addr bigsur_isa_port2addr +# define __ioremap generic_ioremap +# define __iounmap generic_iounmap + +#endif diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/io_od.h linux/include/asm-sh/io_od.h --- v2.4.5/linux/include/asm-sh/io_od.h Wed Apr 11 21:24:52 2001 +++ linux/include/asm-sh/io_od.h Wed Dec 31 16:00:00 1969 @@ -1,77 +0,0 @@ -/* - * include/asm-sh/io_od.h - * - * Copyright 2000 Stuart Menefy (stuart.menefy@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * IO functions for an STMicroelectronics Overdrive - */ - -#ifndef _ASM_SH_IO_OD_H -#define _ASM_SH_IO_OD_H - -#include - -extern unsigned char od_inb(unsigned long port); -extern unsigned short od_inw(unsigned long port); -extern unsigned int od_inl(unsigned long port); - -extern void od_outb(unsigned char value, unsigned long port); -extern void od_outw(unsigned short value, unsigned long port); -extern void od_outl(unsigned int value, unsigned long port); - -extern unsigned char od_inb_p(unsigned long port); -extern unsigned short od_inw_p(unsigned long port); -extern unsigned int od_inl_p(unsigned long port); -extern void od_outb_p(unsigned char value, unsigned long port); -extern void od_outw_p(unsigned short value, unsigned long port); -extern void od_outl_p(unsigned int value, unsigned long port); - -extern void od_insb(unsigned long port, void *addr, unsigned long count); -extern void od_insw(unsigned long port, void *addr, unsigned long count); -extern void od_insl(unsigned long port, void *addr, unsigned long count); -extern void od_outsb(unsigned long port, const void *addr, unsigned long count); -extern void od_outsw(unsigned long port, const void *addr, unsigned long count); -extern void od_outsl(unsigned long port, const void *addr, unsigned long count); - -extern unsigned long od_isa_port2addr(unsigned long offset); - -#ifdef __WANT_IO_DEF - -# define __inb od_inb -# define __inw od_inw -# define __inl od_inl -# define __outb od_outb -# define __outw od_outw -# define __outl od_outl - -# define __inb_p od_inb_p -# define __inw_p od_inw_p -# define __inl_p od_inl_p -# define __outb_p od_outb_p -# define __outw_p od_outw_p -# define __outl_p od_outl_p - -# define __insb od_insb -# define __insw od_insw -# define __insl od_insl -# define __outsb od_outsb -# define __outsw od_outsw -# define __outsl od_outsl - -# define __readb generic_readb -# define __readw generic_readw -# define __readl generic_readl -# define __writeb generic_writeb -# define __writew generic_writew -# define __writel generic_writel - -# define __isa_port2addr od_isa_port2addr -# define __ioremap generic_ioremap -# define __iounmap generic_iounmap - -#endif - -#endif /* _ASM_SH_IO_OD_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/io_sh2000.h linux/include/asm-sh/io_sh2000.h --- v2.4.5/linux/include/asm-sh/io_sh2000.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-sh/io_sh2000.h Wed Jun 27 13:55:29 2001 @@ -0,0 +1,56 @@ +/* + * include/asm-sh/io_sh2000.h + * + * Copyright 2000 Stuart Menefy (stuart.menefy@st.com) + * 2001 SUGIOKA Toshinobu (sugioka@itonet.co.jp) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * IO functions for use when we don't know what machine we are on + */ + +#ifndef _ASM_SH_IO_SH2000_H +#define _ASM_SH_IO_SH2000_H + +#include + +unsigned long sh2000_isa_port2addr(unsigned long offset); + +#ifdef __WANT_IO_DEF + +# define __inb generic_inb +# define __inw generic_inw +# define __inl generic_inl +# define __outb generic_outb +# define __outw generic_outw +# define __outl generic_outl + +# define __inb_p generic_inb_p +# define __inw_p generic_inw +# define __inl_p generic_inl +# define __outb_p generic_outb_p +# define __outw_p generic_outw +# define __outl_p generic_outl + +# define __insb generic_insb +# define __insw generic_insw +# define __insl generic_insl +# define __outsb generic_outsb +# define __outsw generic_outsw +# define __outsl generic_outsl + +# define __readb generic_readb +# define __readw generic_readw +# define __readl generic_readl +# define __writeb generic_writeb +# define __writew generic_writew +# define __writel generic_writel + +# define __isa_port2addr sh2000_isa_port2addr +# define __ioremap generic_ioremap +# define __iounmap generic_iounmap + +#endif + +#endif /* _ASM_SH_IO_SH2000_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/irq.h linux/include/asm-sh/irq.h --- v2.4.5/linux/include/asm-sh/irq.h Wed Apr 11 21:24:52 2001 +++ linux/include/asm-sh/irq.h Wed Jun 27 13:55:29 2001 @@ -43,7 +43,8 @@ #define DMA_PRIORITY 7 #if defined (CONFIG_CPU_SUBTYPE_SH7707) || defined (CONFIG_CPU_SUBTYPE_SH7708) || \ - defined (CONFIG_CPU_SUBTYPE_SH7709) || defined (CONFIG_CPU_SUBTYPE_SH7750) + defined (CONFIG_CPU_SUBTYPE_SH7709) || defined (CONFIG_CPU_SUBTYPE_SH7750) || \ + defined (CONFIG_CPU_SUBTYPE_SH7751) #define SCI_ERI_IRQ 23 #define SCI_RXI_IRQ 24 #define SCI_TXI_IRQ 25 @@ -68,7 +69,8 @@ #define IRDA_IPR_ADDR INTC_IPRE #define IRDA_IPR_POS 2 #define IRDA_PRIORITY 3 -#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_ST40STB1) +#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751) || \ + defined(CONFIG_CPU_SUBTYPE_ST40STB1) #define SCIF_ERI_IRQ 40 #define SCIF_RXI_IRQ 41 #define SCIF_BRI_IRQ 42 @@ -95,7 +97,7 @@ /* 1. ONCHIP_NR_IRQS */ #ifdef CONFIG_SH_GENERIC -# define ONCHIP_NR_IRQS 89 +# define ONCHIP_NR_IRQS 144 #else # if defined(CONFIG_CPU_SUBTYPE_SH7707) # define ONCHIP_NR_IRQS 64 @@ -107,8 +109,10 @@ # define PINT_NR_IRQS 16 # elif defined(CONFIG_CPU_SUBTYPE_SH7750) # define ONCHIP_NR_IRQS 48 // Actually 44 +# elif defined(CONFIG_CPU_SUBTYPE_SH7751) +# define ONCHIP_NR_IRQS 72 # elif defined(CONFIG_CPU_SUBTYPE_ST40STB1) -# define ONCHIP_NR_IRQS 89 +# define ONCHIP_NR_IRQS 144 # endif #endif @@ -131,10 +135,14 @@ #else # if defined(CONFIG_HD64461) # define OFFCHIP_NR_IRQS 16 +# elif defined (CONFIG_SH_BIGSUR) /* must be before CONFIG_HD64465 */ +# define OFFCHIP_NR_IRQS 48 # elif defined(CONFIG_HD64465) # define OFFCHIP_NR_IRQS 16 # elif defined (CONFIG_SH_EC3104) # define OFFCHIP_NR_IRQS 16 +# elif defined (CONFIG_SH_DREAMCAST) +# define OFFCHIP_NR_IRQS 96 # else # define OFFCHIP_NR_IRQS 0 # endif @@ -240,6 +248,16 @@ #define __irq_demux(irq) irq #endif /* CONFIG_CPU_SUBTYPE_SH7707 || CONFIG_CPU_SUBTYPE_SH7709 */ +#if defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751) || \ + defined(CONFIG_CPU_SUBTYPE_ST40STB1) +#define INTC_ICR 0xffd00000 +#define INTC_ICR_NMIL (1<<15) +#define INTC_ICR_MAI (1<<14) +#define INTC_ICR_NMIB (1<<9) +#define INTC_ICR_NMIE (1<<8) +#define INTC_ICR_IRLM (1<<7) +#endif + #ifdef CONFIG_CPU_SUBTYPE_ST40STB1 #define INTC2_FIRST_IRQ 64 #define NR_INTC2_IRQS 25 @@ -266,6 +284,11 @@ return __irq_demux(irq); } +#elif defined(CONFIG_SH_BIGSUR) + +extern int bigsur_irq_demux(int irq); +#define irq_demux(irq) bigsur_irq_demux(irq) + #elif defined(CONFIG_HD64461) extern int hd64461_irq_demux(int irq); @@ -285,6 +308,11 @@ extern int cat68701_irq_demux(int irq); #define irq_demux cat68701_irq_demux + +#elif defined(CONFIG_SH_DREAMCAST) + +extern int systemasic_irq_demux(int irq); +#define irq_demux systemasic_irq_demux #else diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/linux_logo.h linux/include/asm-sh/linux_logo.h --- v2.4.5/linux/include/asm-sh/linux_logo.h Mon Jun 19 17:59:38 2000 +++ linux/include/asm-sh/linux_logo.h Mon Jun 11 19:15:27 2001 @@ -23,26 +23,5 @@ #define linux_logo_banner "Linux/SuperH version " UTS_RELEASE -#define LINUX_LOGO_COLORS 214 - -#ifdef INCLUDE_LINUX_LOGO_DATA - -#define INCLUDE_LINUX_LOGOBW -#define INCLUDE_LINUX_LOGO16 - #include -#else - -/* prototypes only */ -extern unsigned char linux_logo_red[]; -extern unsigned char linux_logo_green[]; -extern unsigned char linux_logo_blue[]; -extern unsigned char linux_logo[]; -extern unsigned char linux_logo_bw[]; -extern unsigned char linux_logo16_red[]; -extern unsigned char linux_logo16_green[]; -extern unsigned char linux_logo16_blue[]; -extern unsigned char linux_logo16[]; - -#endif diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/machvec.h linux/include/asm-sh/machvec.h --- v2.4.5/linux/include/asm-sh/machvec.h Wed Apr 11 21:24:52 2001 +++ linux/include/asm-sh/machvec.h Wed Jun 27 13:55:29 2001 @@ -72,8 +72,10 @@ unsigned int mv_hw_hp680 : 1; unsigned int mv_hw_hp690 : 1; unsigned int mv_hw_hd64461 : 1; + unsigned int mv_hw_sh2000 : 1; unsigned int mv_hw_hd64465 : 1; unsigned int mv_hw_dreamcast : 1; + unsigned int mv_hw_bigsur : 1; }; extern struct sh_machine_vector sh_mv; @@ -87,9 +89,12 @@ #define MACH_HP690 (sh_mv.mv_hw_hp690) #define MACH_HD64461 (sh_mv.mv_hw_hd64461) #define MACH_HD64465 (sh_mv.mv_hw_hd64465) +#define MACH_SH2000 (sh_mv.mv_hw_sh2000) #define MACH_DREAMCAST (sh_mv.mv_hw_dreamcast) +#define MACH_BIGSUR (sh_mv.mv_hw_bigsur) #else -# ifdef CONFIG_SH_SOLUTION_ENGINE +# if defined(CONFIG_SH_SOLUTION_ENGINE) || \ + defined(CONFIG_SH_7751_SOLUTION_ENGINE) # define MACH_SE 1 # else # define MACH_SE 0 @@ -114,6 +119,7 @@ # else # define MACH_HP690 0 # endif +# endif # ifdef CONFIG_HD64461 # define MACH_HD64461 1 # else @@ -124,6 +130,11 @@ # else # define MACH_HD64465 0 # endif +# ifdef CONFIG_SH_SH2000 +# define MACH_SH2000 1 +# else +# define MACH_SH2000 0 +# endif # ifdef CONFIG_SH_EC3104 # define MACH_EC3104 1 # else @@ -134,6 +145,10 @@ # else # define MACH_DREAMCAST 0 # endif +# ifdef CONFIG_SH_BIGSUR +# define MACH_BIGSUR 1 +# else +# define MACH_BIGSUR 0 #endif #endif /* _ASM_SH_MACHVEC_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/mc146818rtc.h linux/include/asm-sh/mc146818rtc.h --- v2.4.5/linux/include/asm-sh/mc146818rtc.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-sh/mc146818rtc.h Wed Jun 27 13:55:29 2001 @@ -0,0 +1,159 @@ +/* + * Machine dependent access functions for RTC registers. + */ +#ifndef _ASM_MC146818RTC_H +#define _ASM_MC146818RTC_H + +#include + +#define RTC_ALWAYS_BCD 1 + +/* FIXME:RTC Interrupt feature is not implemented yet. */ +#undef RTC_IRQ +#define RTC_IRQ 0 + +#if defined(__sh3__) +#define RTC_PORT(n) (R64CNT+(n)*2) +#define CMOS_READ(addr) __CMOS_READ(addr,b) +#define CMOS_WRITE(val,addr) __CMOS_WRITE(val,addr,b) + +#elif defined(__SH4__) +#define RTC_PORT(n) (R64CNT+(n)*4) +#define CMOS_READ(addr) __CMOS_READ(addr,w) +#define CMOS_WRITE(val,addr) __CMOS_WRITE(val,addr,w) +#endif + +#define __CMOS_READ(addr, s) ({ \ + unsigned char val=0, rcr1, rcr2, r64cnt, retry; \ + switch(addr) { \ + case RTC_SECONDS: \ + val = ctrl_inb(RSECCNT); \ + break; \ + case RTC_SECONDS_ALARM: \ + val = ctrl_inb(RSECAR); \ + break; \ + case RTC_MINUTES: \ + val = ctrl_inb(RMINCNT); \ + break; \ + case RTC_MINUTES_ALARM: \ + val = ctrl_inb(RMINAR); \ + break; \ + case RTC_HOURS: \ + val = ctrl_inb(RHRCNT); \ + break; \ + case RTC_HOURS_ALARM: \ + val = ctrl_inb(RHRAR); \ + break; \ + case RTC_DAY_OF_WEEK: \ + val = ctrl_inb(RWKCNT); \ + break; \ + case RTC_DAY_OF_MONTH: \ + val = ctrl_inb(RDAYCNT); \ + break; \ + case RTC_MONTH: \ + val = ctrl_inb(RMONCNT); \ + break; \ + case RTC_YEAR: \ + val = ctrl_in##s(RYRCNT); \ + break; \ + case RTC_REG_A: /* RTC_FREQ_SELECT */ \ + rcr2 = ctrl_inb(RCR2); \ + val = (rcr2 & RCR2_PESMASK) >> 4; \ + rcr1 = ctrl_inb(RCR1); \ + rcr1 = (rcr1 & (RCR1_CIE | RCR1_AIE)) | RCR1_AF;\ + retry = 0; \ + do { \ + ctrl_outb(rcr1, RCR1); /* clear CF */ \ + r64cnt = ctrl_inb(R64CNT); \ + } while((ctrl_inb(RCR1) & RCR1_CF) && retry++ < 1000);\ + r64cnt ^= RTC_BIT_INVERTED; \ + if(r64cnt == 0x7f || r64cnt == 0) \ + val |= RTC_UIP; \ + break; \ + case RTC_REG_B: /* RTC_CONTROL */ \ + rcr1 = ctrl_inb(RCR1); \ + rcr2 = ctrl_inb(RCR2); \ + if(rcr1 & RCR1_CIE) val |= RTC_UIE; \ + if(rcr1 & RCR1_AIE) val |= RTC_AIE; \ + if(rcr2 & RCR2_PESMASK) val |= RTC_PIE; \ + if(!(rcr2 & RCR2_START))val |= RTC_SET; \ + val |= RTC_24H; \ + break; \ + case RTC_REG_C: /* RTC_INTR_FLAGS */ \ + rcr1 = ctrl_inb(RCR1); \ + rcr1 &= ~(RCR1_CF | RCR1_AF); \ + ctrl_outb(rcr1, RCR1); \ + rcr2 = ctrl_inb(RCR2); \ + rcr2 &= ~RCR2_PEF; \ + ctrl_outb(rcr2, RCR2); \ + break; \ + case RTC_REG_D: /* RTC_VALID */ \ + /* Always valid ... */ \ + val = RTC_VRT; \ + break; \ + default: \ + break; \ + } \ + val; \ +}) + +#define __CMOS_WRITE(val, addr, s) ({ \ + unsigned char rcr1,rcr2; \ + switch(addr) { \ + case RTC_SECONDS: \ + ctrl_outb(val, RSECCNT); \ + break; \ + case RTC_SECONDS_ALARM: \ + ctrl_outb(val, RSECAR); \ + break; \ + case RTC_MINUTES: \ + ctrl_outb(val, RMINCNT); \ + break; \ + case RTC_MINUTES_ALARM: \ + ctrl_outb(val, RMINAR); \ + break; \ + case RTC_HOURS: \ + ctrl_outb(val, RHRCNT); \ + break; \ + case RTC_HOURS_ALARM: \ + ctrl_outb(val, RHRAR); \ + break; \ + case RTC_DAY_OF_WEEK: \ + ctrl_outb(val, RWKCNT); \ + break; \ + case RTC_DAY_OF_MONTH: \ + ctrl_outb(val, RDAYCNT); \ + break; \ + case RTC_MONTH: \ + ctrl_outb(val, RMONCNT); \ + break; \ + case RTC_YEAR: \ + ctrl_out##s((ctrl_in##s(RYRCNT) & 0xff00) | (val & 0xff), RYRCNT);\ + break; \ + case RTC_REG_A: /* RTC_FREQ_SELECT */ \ + rcr2 = ctrl_inb(RCR2); \ + if((val & RTC_DIV_CTL) == RTC_DIV_RESET2) \ + rcr2 |= RCR2_RESET; \ + ctrl_outb(rcr2, RCR2); \ + break; \ + case RTC_REG_B: /* RTC_CONTROL */ \ + rcr1 = (ctrl_inb(RCR1) & 0x99) | RCR1_AF; \ + if(val & RTC_AIE) rcr1 |= RCR1_AIE; \ + else rcr1 &= ~RCR1_AIE; \ + if(val & RTC_UIE) rcr1 |= RCR1_CIE; \ + else rcr1 &= ~RCR1_CIE; \ + ctrl_outb(rcr1, RCR1); \ + rcr2 = ctrl_inb(RCR2); \ + if(val & RTC_SET) rcr2 &= ~RCR2_START; \ + else rcr2 |= RCR2_START; \ + ctrl_outb(rcr2, RCR2); \ + break; \ + case RTC_REG_C: /* RTC_INTR_FLAGS */ \ + break; \ + case RTC_REG_D: /* RTC_VALID */ \ + break; \ + default: \ + break; \ + } \ +}) +#endif /* _ASM_MC146818RTC_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/pci-sh7751.h linux/include/asm-sh/pci-sh7751.h --- v2.4.5/linux/include/asm-sh/pci-sh7751.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-sh/pci-sh7751.h Wed Jun 27 13:55:29 2001 @@ -0,0 +1,281 @@ +/* + * Low-Level PCI Support for SH7751 targets + * + * Dustin McIntire (dustin@sensoria.com) (c) 2001 + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + */ + +#ifndef _PCI_SH7751_H_ +#define _PCI_SH7751_H_ + +#include + +/* set debug level 4=verbose...1=terse */ +//#define DEBUG_PCI 3 +#undef DEBUG_PCI + +#ifdef DEBUG_PCI +#define PCIDBG(n, x...) { if(DEBUG_PCI>=n) printk(x); } +#else +#define PCIDBG(n, x...) +#endif + +/* startup values */ +#define PCI_PROBE_BIOS 1 +#define PCI_PROBE_CONF1 2 +#define PCI_PROBE_CONF2 4 +#define PCI_NO_SORT 0x100 +#define PCI_BIOS_SORT 0x200 +#define PCI_NO_CHECKS 0x400 +#define PCI_ASSIGN_ROMS 0x1000 +#define PCI_BIOS_IRQ_SCAN 0x2000 + +/* Platform Specific Values */ +#define SH7751_VENDOR_ID 0x1054 +#define SH7751_DEVICE_ID 0x3505 + +/* SH7751 Specific Values */ +#define SH7751_PCI_CONFIG_BASE 0xFD000000 /* Config space base addr */ +#define SH7751_PCI_CONFIG_SIZE 0x1000000 /* Config space size */ +#define SH7751_PCI_MEMORY_BASE 0xFD000000 /* Memory space base addr */ +#define SH7751_PCI_MEM_SIZE 0x01000000 /* Size of Memory window */ +#define SH7751_PCI_IO_BASE 0xFE240000 /* IO space base address */ +#define SH7751_PCI_IO_SIZE 0x40000 /* Size of IO window */ + +#define SH7751_PCIREG_BASE 0xFE200000 /* PCI regs base address */ +#define PCI_REG(n) (SH7751_PCIREG_BASE+ n) + +#define SH7751_PCICONF0 0x0 /* PCI Config Reg 0 */ + #define SH7751_PCICONF0_DEVID 0xFFFF0000 /* Device ID */ + #define SH7751_PCICONF0_VNDID 0x0000FFFF /* Vendor ID */ +#define SH7751_PCICONF1 0x4 /* PCI Config Reg 1 */ + #define SH7751_PCICONF1_DPE 0x80000000 /* Data Parity Error */ + #define SH7751_PCICONF1_SSE 0x40000000 /* System Error Status */ + #define SH7751_PCICONF1_RMA 0x20000000 /* Master Abort */ + #define SH7751_PCICONF1_RTA 0x10000000 /* Target Abort Rx Status */ + #define SH7751_PCICONF1_STA 0x08000000 /* Target Abort Exec Status */ + #define SH7751_PCICONF1_DEV 0x06000000 /* Timing Status */ + #define SH7751_PCICONF1_DPD 0x01000000 /* Data Parity Status */ + #define SH7751_PCICONF1_FBBC 0x00800000 /* Back 2 Back Status */ + #define SH7751_PCICONF1_UDF 0x00400000 /* User Defined Status */ + #define SH7751_PCICONF1_66M 0x00200000 /* 66Mhz Operation Status */ + #define SH7751_PCICONF1_PM 0x00100000 /* Power Management Status */ + #define SH7751_PCICONF1_PBBE 0x00000200 /* Back 2 Back Control */ + #define SH7751_PCICONF1_SER 0x00000100 /* SERR Output Control */ + #define SH7751_PCICONF1_WCC 0x00000080 /* Wait Cycle Control */ + #define SH7751_PCICONF1_PER 0x00000040 /* Parity Error Response */ + #define SH7751_PCICONF1_VPS 0x00000020 /* VGA Pallet Snoop */ + #define SH7751_PCICONF1_MWIE 0x00000010 /* Memory Write+Invalidate */ + #define SH7751_PCICONF1_SPC 0x00000008 /* Special Cycle Control */ + #define SH7751_PCICONF1_BUM 0x00000004 /* Bus Master Control */ + #define SH7751_PCICONF1_MES 0x00000002 /* Memory Space Control */ + #define SH7751_PCICONF1_IOS 0x00000001 /* I/O Space Control */ +#define SH7751_PCICONF2 0x8 /* PCI Config Reg 2 */ + #define SH7751_PCICONF2_BCC 0xFF000000 /* Base Class Code */ + #define SH7751_PCICONF2_SCC 0x00FF0000 /* Sub-Class Code */ + #define SH7751_PCICONF2_RLPI 0x0000FF00 /* Programming Interface */ + #define SH7751_PCICONF2_REV 0x000000FF /* Revision ID */ +#define SH7751_PCICONF3 0xC /* PCI Config Reg 3 */ + #define SH7751_PCICONF3_BIST7 0x80000000 /* Bist Supported */ + #define SH7751_PCICONF3_BIST6 0x40000000 /* Bist Executing */ + #define SH7751_PCICONF3_BIST3_0 0x0F000000 /* Bist Passed */ + #define SH7751_PCICONF3_HD7 0x00800000 /* Single Funtion device */ + #define SH7751_PCICONF3_HD6_0 0x007F0000 /* Configuration Layout */ + #define SH7751_PCICONF3_LAT 0x0000FF00 /* Latency Timer */ + #define SH7751_PCICONF3_CLS 0x000000FF /* Cache Line Size */ +#define SH7751_PCICONF4 0x10 /* PCI Config Reg 4 */ + #define SH7751_PCICONF4_BASE 0xFFFFFFFC /* I/O Space Base Addr */ + #define SH7751_PCICONF4_ASI 0x00000001 /* Address Space Type */ +#define SH7751_PCICONF5 0x14 /* PCI Config Reg 5 */ + #define SH7751_PCICONF5_BASE 0xFFFFFFF0 /* Mem Space Base Addr */ + #define SH7751_PCICONF5_LAP 0x00000008 /* Prefetch Enabled */ + #define SH7751_PCICONF5_LAT 0x00000006 /* Local Memory type */ + #define SH7751_PCICONF5_ASI 0x00000001 /* Address Space Type */ +#define SH7751_PCICONF6 0x18 /* PCI Config Reg 6 */ + #define SH7751_PCICONF6_BASE 0xFFFFFFF0 /* Mem Space Base Addr */ + #define SH7751_PCICONF6_LAP 0x00000008 /* Prefetch Enabled */ + #define SH7751_PCICONF6_LAT 0x00000006 /* Local Memory type */ + #define SH7751_PCICONF6_ASI 0x00000001 /* Address Space Type */ +/* PCICONF7 - PCICONF10 are undefined */ +#define SH7751_PCICONF11 0x2C /* PCI Config Reg 11 */ + #define SH7751_PCICONF11_SSID 0xFFFF0000 /* Subsystem ID */ + #define SH7751_PCICONF11_SVID 0x0000FFFF /* Subsystem Vendor ID */ +/* PCICONF12 is undefined */ +#define SH7751_PCICONF13 0x34 /* PCI Config Reg 13 */ + #define SH7751_PCICONF13_CPTR 0x000000FF /* PM function pointer */ +/* PCICONF14 is undefined */ +#define SH7751_PCICONF15 0x3C /* PCI Config Reg 15 */ + #define SH7751_PCICONF15_IPIN 0x000000FF /* Interrupt Pin */ +#define SH7751_PCICONF16 0x40 /* PCI Config Reg 16 */ + #define SH7751_PCICONF16_PMES 0xF8000000 /* PME Support */ + #define SH7751_PCICONF16_D2S 0x04000000 /* D2 Support */ + #define SH7751_PCICONF16_D1S 0x02000000 /* D1 Support */ + #define SH7751_PCICONF16_DSI 0x00200000 /* Bit Device Init. */ + #define SH7751_PCICONF16_PMCK 0x00080000 /* Clock for PME req. */ + #define SH7751_PCICONF16_VER 0x00070000 /* PM Version */ + #define SH7751_PCICONF16_NIP 0x0000FF00 /* Next Item Pointer */ + #define SH7751_PCICONF16_CID 0x000000FF /* Capability Identifier */ +#define SH7751_PCICONF17 0x44 /* PCI Config Reg 17 */ + #define SH7751_PCICONF17_DATA 0xFF000000 /* Data field for PM */ + #define SH7751_PCICONF17_PMES 0x00800000 /* PME Status */ + #define SH7751_PCICONF17_DSCL 0x00600000 /* Data Scaling Value */ + #define SH7751_PCICONF17_DSEL 0x001E0000 /* Data Select */ + #define SH7751_PCICONF17_PMEN 0x00010000 /* PME Enable */ + #define SH7751_PCICONF17_PWST 0x00000003 /* Power State */ +/* SH7715 Internal PCI Registers */ +#define SH7751_PCICR 0x100 /* PCI Control Register */ + #define SH7751_PCICR_PREFIX 0xA5000000 /* CR prefix for write */ + #define SH7751_PCICR_TRSB 0x00000200 /* Target Read Single */ + #define SH7751_PCICR_BSWP 0x00000100 /* Target Byte Swap */ + #define SH7751_PCICR_PLUP 0x00000080 /* Enable PCI Pullup */ + #define SH7751_PCICR_ARBM 0x00000040 /* PCI Arbitration Mode */ + #define SH7751_PCICR_MD 0x00000030 /* MD9 and MD10 status */ + #define SH7751_PCICR_SERR 0x00000008 /* SERR output assert */ + #define SH7751_PCICR_INTA 0x00000004 /* INTA output assert */ + #define SH7751_PCICR_PRST 0x00000002 /* PCI Reset Assert */ + #define SH7751_PCICR_CFIN 0x00000001 /* Central Fun. Init Done */ +#define SH7751_PCILSR0 0x104 /* PCI Local Space Register0 */ +#define SH7751_PCILSR1 0x108 /* PCI Local Space Register1 */ +#define SH7751_PCILAR0 0x10C /* PCI Local Address Register1 */ +#define SH7751_PCILAR1 0x110 /* PCI Local Address Register1 */ +#define SH7751_PCIINT 0x114 /* PCI Interrupt Register */ + #define SH7751_PCIINT_MLCK 0x00008000 /* Master Lock Error */ + #define SH7751_PCIINT_TABT 0x00004000 /* Target Abort Error */ + #define SH7751_PCIINT_TRET 0x00000200 /* Target Retry Error */ + #define SH7751_PCIINT_MFDE 0x00000100 /* Master Func. Disable Error */ + #define SH7751_PCIINT_PRTY 0x00000080 /* Address Parity Error */ + #define SH7751_PCIINT_SERR 0x00000040 /* SERR Detection Error */ + #define SH7751_PCIINT_TWDP 0x00000020 /* Tgt. Write Parity Error */ + #define SH7751_PCIINT_TRDP 0x00000010 /* Tgt. Read Parity Error Det. */ + #define SH7751_PCIINT_MTABT 0x00000008 /* Master-Tgt. Abort Error */ + #define SH7751_PCIINT_MMABT 0x00000004 /* Master-Master Abort Error */ + #define SH7751_PCIINT_MWPD 0x00000002 /* Master Write PERR Detect */ + #define SH7751_PCIINT_MRPD 0x00000002 /* Master Read PERR Detect */ +#define SH7751_PCIINTM 0x118 /* PCI Interrupt Mask Register */ +#define SH7751_PCIALR 0x11C /* Error Address Register */ +#define SH7751_PCICLR 0x120 /* Error Command/Data Register */ + #define SH7751_PCICLR_MPIO 0x80000000 /* Error Command/Data Register */ + #define SH7751_PCICLR_MDMA0 0x40000000 /* DMA0 Transfer Error */ + #define SH7751_PCICLR_MDMA1 0x20000000 /* DMA1 Transfer Error */ + #define SH7751_PCICLR_MDMA2 0x10000000 /* DMA2 Transfer Error */ + #define SH7751_PCICLR_MDMA3 0x08000000 /* DMA3 Transfer Error */ + #define SH7751_PCICLR_TGT 0x04000000 /* Target Transfer Error */ + #define SH7751_PCICLR_CMDL 0x0000000F /* PCI Command at Error */ +#define SH7751_PCIAINT 0x130 /* Arbiter Interrupt Register */ + #define SH7751_PCIAINT_MBKN 0x00002000 /* Master Broken Interrupt */ + #define SH7751_PCIAINT_TBTO 0x00001000 /* Target Bus Time Out */ + #define SH7751_PCIAINT_MBTO 0x00001000 /* Master Bus Time Out */ + #define SH7751_PCIAINT_TABT 0x00000008 /* Target Abort */ + #define SH7751_PCIAINT_MABT 0x00000004 /* Master Abort */ + #define SH7751_PCIAINT_RDPE 0x00000002 /* Read Data Parity Error */ + #define SH7751_PCIAINT_WDPE 0x00000002 /* Write Data Parity Error */ +#define SH7751_PCIAINTM 0x134 /* Arbiter Int. Mask Register */ +#define SH7751_PCIBMLR 0x138 /* Error Bus Master Register */ + #define SH7751_PCIBMLR_REQ4 0x00000010 /* REQ4 bus master at error */ + #define SH7751_PCIBMLR_REQ3 0x00000008 /* REQ3 bus master at error */ + #define SH7751_PCIBMLR_REQ2 0x00000004 /* REQ2 bus master at error */ + #define SH7751_PCIBMLR_REQ1 0x00000002 /* REQ1 bus master at error */ + #define SH7751_PCIBMLR_REQ0 0x00000001 /* REQ0 bus master at error */ +#define SH7751_PCIDMABT 0x140 /* DMA Transfer Arb. Register */ + #define SH7751_PCIDMABT_RRBN 0x00000001 /* DMA Arbitor Round-Robin */ +#define SH7751_PCIDPA0 0x180 /* DMA0 Transfer Addr. Register */ +#define SH7751_PCIDLA0 0x184 /* DMA0 Local Addr. Register */ +#define SH7751_PCIDTC0 0x188 /* DMA0 Transfer Cnt. Register */ +#define SH7751_PCIDCR0 0x18C /* DMA0 Control Register */ + #define SH7751_PCIDCR_ALGN 0x00000600 /* DMA Alignment Mode */ + #define SH7751_PCIDCR_MAST 0x00000100 /* DMA Termination Type */ + #define SH7751_PCIDCR_INTM 0x00000080 /* DMA Interrupt Done Mask*/ + #define SH7751_PCIDCR_INTS 0x00000040 /* DMA Interrupt Done Status */ + #define SH7751_PCIDCR_LHLD 0x00000020 /* Local Address Control */ + #define SH7751_PCIDCR_PHLD 0x00000010 /* PCI Address Control*/ + #define SH7751_PCIDCR_IOSEL 0x00000008 /* PCI Address Space Type */ + #define SH7751_PCIDCR_DIR 0x00000004 /* DMA Transfer Direction */ + #define SH7751_PCIDCR_STOP 0x00000002 /* Force DMA Stop */ + #define SH7751_PCIDCR_STRT 0x00000001 /* DMA Start */ +#define SH7751_PCIDPA1 0x190 /* DMA1 Transfer Addr. Register */ +#define SH7751_PCIDLA1 0x194 /* DMA1 Local Addr. Register */ +#define SH7751_PCIDTC1 0x198 /* DMA1 Transfer Cnt. Register */ +#define SH7751_PCIDCR1 0x19C /* DMA1 Control Register */ +#define SH7751_PCIDPA2 0x1A0 /* DMA2 Transfer Addr. Register */ +#define SH7751_PCIDLA2 0x1A4 /* DMA2 Local Addr. Register */ +#define SH7751_PCIDTC2 0x1A8 /* DMA2 Transfer Cnt. Register */ +#define SH7751_PCIDCR2 0x1AC /* DMA2 Control Register */ +#define SH7751_PCIDPA3 0x1B0 /* DMA3 Transfer Addr. Register */ +#define SH7751_PCIDLA3 0x1B4 /* DMA3 Local Addr. Register */ +#define SH7751_PCIDTC3 0x1B8 /* DMA3 Transfer Cnt. Register */ +#define SH7751_PCIDCR3 0x1BC /* DMA3 Control Register */ +#define SH7751_PCIPAR 0x1C0 /* PIO Address Register */ + #define SH7751_PCIPAR_CFGEN 0x80000000 /* Configuration Enable */ + #define SH7751_PCIPAR_BUSNO 0x00FF0000 /* Config. Bus Number */ + #define SH7751_PCIPAR_DEVNO 0x0000FF00 /* Config. Device Number */ + #define SH7751_PCIPAR_REGAD 0x000000FC /* Register Address Number */ +#define SH7751_PCIMBR 0x1C4 /* Memory Base Address Register */ + #define SH7751_PCIMBR_MASK 0xFF000000 /* Memory Space Mask */ + #define SH7751_PCIMBR_LOCK 0x00000001 /* Lock Memory Space */ +#define SH7751_PCIIOBR 0x1C8 /* I/O Base Address Register */ + #define SH7751_PCIIOBR_MASK 0xFFFC0000 /* IO Space Mask */ + #define SH7751_PCIIOBR_LOCK 0x00000001 /* Lock IO Space */ +#define SH7751_PCIPINT 0x1CC /* Power Mgmnt Int. Register */ + #define SH7751_PCIPINT_D3 0x00000002 /* D3 Pwr Mgmt. Interrupt */ + #define SH7751_PCIPINT_D0 0x00000001 /* D0 Pwr Mgmt. Interrupt */ +#define SH7751_PCIPINTM 0x1D0 /* Power Mgmnt Mask Register */ +#define SH7751_PCICLKR 0x1D4 /* Clock Ctrl. Register */ + #define SH7751_PCICLKR_PCSTP 0x00000002 /* PCI Clock Stop */ + #define SH7751_PCICLKR_BCSTP 0x00000002 /* BCLK Clock Stop */ +/* For definitions of BCR, MCR see ... */ +#define SH7751_PCIBCR1 0x1E0 /* Memory BCR1 Register */ +#define SH7751_PCIBCR2 0x1E4 /* Memory BCR2 Register */ +#define SH7751_PCIWCR1 0x1E8 /* Wait Control 1 Register */ +#define SH7751_PCIWCR2 0x1EC /* Wait Control 2 Register */ +#define SH7751_PCIWCR3 0x1F0 /* Wait Control 3 Register */ +#define SH7751_PCIMCR 0x1F4 /* Memory Control Register */ +#define SH7751_PCIPCTR 0x200 /* Port Control Register */ + #define SH7751_PCIPCTR_P2EN 0x000400000 /* Port 2 Enable */ + #define SH7751_PCIPCTR_P1EN 0x000200000 /* Port 1 Enable */ + #define SH7751_PCIPCTR_P0EN 0x000100000 /* Port 0 Enable */ + #define SH7751_PCIPCTR_P2UP 0x000000020 /* Port2 Pull Up Enable */ + #define SH7751_PCIPCTR_P2IO 0x000000010 /* Port2 Output Enable */ + #define SH7751_PCIPCTR_P1UP 0x000000008 /* Port1 Pull Up Enable */ + #define SH7751_PCIPCTR_P1IO 0x000000004 /* Port1 Output Enable */ + #define SH7751_PCIPCTR_P0UP 0x000000002 /* Port0 Pull Up Enable */ + #define SH7751_PCIPCTR_P0IO 0x000000001 /* Port0 Output Enable */ +#define SH7751_PCIPDTR 0x204 /* Port Data Register */ + #define SH7751_PCIPDTR_PB5 0x000000020 /* Port 5 Enable */ + #define SH7751_PCIPDTR_PB4 0x000000010 /* Port 4 Enable */ + #define SH7751_PCIPDTR_PB3 0x000000008 /* Port 3 Enable */ + #define SH7751_PCIPDTR_PB2 0x000000004 /* Port 2 Enable */ + #define SH7751_PCIPDTR_PB1 0x000000002 /* Port 1 Enable */ + #define SH7751_PCIPDTR_PB0 0x000000001 /* Port 0 Enable */ +#define SH7751_PCIPDR 0x220 /* Port IO Data Register */ + +/* Memory Control Registers */ +#define SH7751_BCR1 0xFF800000 /* Memory BCR1 Register */ +#define SH7751_BCR2 0xFF800004 /* Memory BCR2 Register */ +#define SH7751_WCR1 0xFF800008 /* Wait Control 1 Register */ +#define SH7751_WCR2 0xFF80000C /* Wait Control 2 Register */ +#define SH7751_WCR3 0xFF800010 /* Wait Control 3 Register */ +#define SH7751_MCR 0xFF800014 /* Memory Control Register */ + +/* General Memory Config Addresses */ +#define SH7751_CS0_BASE_ADDR 0x0 +#define SH7751_MEM_REGION_SIZE 0x04000000 +#define SH7751_CS1_BASE_ADDR (SH7751_CS0_BASE_ADDR + SH7751_MEM_REGION_SIZE) +#define SH7751_CS2_BASE_ADDR (SH7751_CS1_BASE_ADDR + SH7751_MEM_REGION_SIZE) +#define SH7751_CS3_BASE_ADDR (SH7751_CS2_BASE_ADDR + SH7751_MEM_REGION_SIZE) +#define SH7751_CS4_BASE_ADDR (SH7751_CS3_BASE_ADDR + SH7751_MEM_REGION_SIZE) +#define SH7751_CS5_BASE_ADDR (SH7751_CS4_BASE_ADDR + SH7751_MEM_REGION_SIZE) +#define SH7751_CS6_BASE_ADDR (SH7751_CS5_BASE_ADDR + SH7751_MEM_REGION_SIZE) + +/* General PCI values */ +#define SH7751_PCI_HOST_BRIDGE 0x6 + +/* External functions defined per platform i.e. Big Sur, SE... (these could be routed + * through the machine vectors... */ +extern int pcibios_init_platform(void); +extern int pcibios_map_platform_irq(u8 slot, u8 pin); + +#endif /* _PCI_SH7751_H_ */ + diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/pci.h linux/include/asm-sh/pci.h --- v2.4.5/linux/include/asm-sh/pci.h Wed May 16 10:31:27 2001 +++ linux/include/asm-sh/pci.h Wed Jun 27 13:55:29 2001 @@ -9,19 +9,33 @@ #define pcibios_assign_all_busses() 1 +#if defined(CONFIG_CPU_SUBTYPE_ST40STB1) /* These are currently the correct values for the STM overdrive board. * We need some way of setting this on a board specific way, it will * not be the same on other boards I think */ -#if 1 /* def CONFIG_SH_7750_OVERDRIVE || def CONFIG_CPU_SUBTYPE_ST40STB1 */ #define PCIBIOS_MIN_IO 0x2000 #define PCIBIOS_MIN_MEM 0x10000000 + +#elif defined(CONFIG_SH_DREAMCAST) +#define PCIBIOS_MIN_IO 0x2000 +#define PCIBIOS_MIN_MEM 0x10000000 +#elif defined(CONFIG_SH_BIGSUR) && defined(CONFIG_CPU_SUBTYPE_SH7751) +#define PCIBIOS_MIN_IO 0x2000 +#define PCIBIOS_MIN_MEM 0xFD000000 + +#elif defined(CONFIG_SH_7751_SOLUTION_ENGINE) && defined(CONFIG_CPU_SUBTYPE_SH7751) +#define PCIBIOS_MIN_IO 0x4000 +#define PCIBIOS_MIN_MEM 0xFD000000 #endif -static inline void pcibios_set_master(struct pci_dev *dev) -{ +struct pci_dev; + +extern void pcibios_set_master(struct pci_dev *dev); +//static inline void pcibios_set_master(struct pci_dev *dev) +//{ /* No special bus mastering setup handling */ -} +//} static inline void pcibios_penalize_isa_irq(int irq) { @@ -37,8 +51,6 @@ #include #include #include - -struct pci_dev; /* Allocate and map kernel buffer using consistent mode DMA for a device. * hwdev should be valid struct pci_dev pointer for PCI devices, diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/pgalloc.h linux/include/asm-sh/pgalloc.h --- v2.4.5/linux/include/asm-sh/pgalloc.h Mon Apr 23 15:28:07 2001 +++ linux/include/asm-sh/pgalloc.h Wed Jun 27 13:55:29 2001 @@ -17,7 +17,7 @@ * Allocate and free page tables. */ -static __inline__ pgd_t *get_pgd_slow(void) +static inline pgd_t *get_pgd_slow(void) { unsigned int pgd_size = (USER_PTRS_PER_PGD * sizeof(pgd_t)); pgd_t *pgd = (pgd_t *)kmalloc(pgd_size, GFP_KERNEL); @@ -28,7 +28,7 @@ return pgd; } -static __inline__ pgd_t *get_pgd_fast(void) +static inline pgd_t *get_pgd_fast(void) { unsigned long *ret; @@ -41,14 +41,14 @@ return (pgd_t *)ret; } -static __inline__ void free_pgd_fast(pgd_t *pgd) +static inline void free_pgd_fast(pgd_t *pgd) { *(unsigned long *)pgd = (unsigned long) pgd_quicklist; pgd_quicklist = (unsigned long *) pgd; pgtable_cache_size++; } -static __inline__ void free_pgd_slow(pgd_t *pgd) +static inline void free_pgd_slow(pgd_t *pgd) { kfree(pgd); } @@ -69,33 +69,33 @@ if ((ret = (unsigned long *)pte_quicklist) != NULL) { pte_quicklist = (unsigned long *)(*ret); - ret[0] = ret[1]; + ret[0] = 0; pgtable_cache_size--; } return (pte_t *)ret; } -static __inline__ void pte_free_fast(pte_t *pte) +static inline void pte_free_fast(pte_t *pte) { *(unsigned long *)pte = (unsigned long) pte_quicklist; pte_quicklist = (unsigned long *) pte; pgtable_cache_size++; } -static __inline__ void pte_free_slow(pte_t *pte) +static inline void pte_free_slow(pte_t *pte) { free_page((unsigned long)pte); } -#define pte_free(pte) pte_free_slow(pte) -#define pgd_free(pgd) free_pgd_slow(pgd) +#define pte_free(pte) pte_free_fast(pte) +#define pgd_free(pgd) free_pgd_fast(pgd) #define pgd_alloc(mm) get_pgd_fast() /* * allocating and freeing a pmd is trivial: the 1-entry pmd is * inside the pgd, so has no extra memory associated with it. */ -static __inline__ void pmd_free(pmd_t * pmd) +static inline void pmd_free(pmd_t * pmd) { } @@ -116,7 +116,7 @@ * - flush_tlb_mm(mm) flushes the specified mm context TLB's * - flush_tlb_page(vma, vmaddr) flushes one page * - flush_tlb_range(mm, start, end) flushes a range of pages - * + * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables */ extern void flush_tlb(void); @@ -126,9 +126,9 @@ unsigned long end); extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long page); -static __inline__ void flush_tlb_pgtables(struct mm_struct *mm, - unsigned long start, unsigned long end) -{ +static inline void flush_tlb_pgtables(struct mm_struct *mm, + unsigned long start, unsigned long end) +{ /* Nothing to do */ } #endif /* __ASM_SH_PGALLOC_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/pgtable-2level.h linux/include/asm-sh/pgtable-2level.h --- v2.4.5/linux/include/asm-sh/pgtable-2level.h Wed Apr 11 21:24:52 2001 +++ linux/include/asm-sh/pgtable-2level.h Wed Jun 27 13:55:29 2001 @@ -17,6 +17,7 @@ #define PTRS_PER_PTE 1024 +#ifndef __ASSEMBLY__ #define pte_ERROR(e) \ printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e)) #define pmd_ERROR(e) \ @@ -32,7 +33,7 @@ static inline int pgd_none(pgd_t pgd) { return 0; } static inline int pgd_bad(pgd_t pgd) { return 0; } static inline int pgd_present(pgd_t pgd) { return 1; } -static inline void pgd_clear (pgd_t * pgd) { } +static inline void pgd_clear (pgd_t * pgdp) { pgd_val(*(pgdp)) = 0; } /* * Certain architectures need to do special things when PTEs @@ -54,5 +55,6 @@ { return (pmd_t *) dir; } +#endif /* !__ASSEMBLY__ */ #endif /* __ASM_SH_PGTABLE_2LEVEL_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/pgtable.h linux/include/asm-sh/pgtable.h --- v2.4.5/linux/include/asm-sh/pgtable.h Wed Apr 11 21:24:52 2001 +++ linux/include/asm-sh/pgtable.h Wed Jun 27 13:55:29 2001 @@ -3,6 +3,8 @@ /* Copyright (C) 1999 Niibe Yutaka */ +#include + /* * This file contains the functions and defines necessary to modify and use * the SuperH page table tree. @@ -12,7 +14,7 @@ #include #include -extern pgd_t swapper_pg_dir[1024]; +extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; extern void paging_init(void); #if defined(__sh3__) @@ -70,8 +72,6 @@ #endif /* !__ASSEMBLY__ */ -#include - #define __beep() asm("") #define PMD_SIZE (1UL << PMD_SHIFT) @@ -82,13 +82,6 @@ #define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE) #define FIRST_USER_PGD_NR 0 -#define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT) -#define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS) - -#define TWOLEVEL_PGDIR_SHIFT 22 -#define BOOT_USER_PGD_PTRS (PAGE_OFFSET >> TWOLEVEL_PGDIR_SHIFT) -#define BOOT_KERNEL_PGD_PTRS (1024-BOOT_USER_PGD_PTRS) - #ifndef __ASSEMBLY__ #define VMALLOC_START P3SEG #define VMALLOC_VMADDR(x) ((unsigned long)(x)) @@ -123,7 +116,15 @@ /* Mask which drop software flags */ +#if defined(__sh3__) +/* + * MMU on SH-3 has bug on SH-bit: We can't use it if MMUCR.IX=1. + * Work around: Just drop SH-bit. + */ +#define _PAGE_FLAGS_HARDWARE_MASK 0x1ffff1fc +#else #define _PAGE_FLAGS_HARDWARE_MASK 0x1ffff1fe +#endif /* Hardware flags: SZ=1 (4k-byte) */ #define _PAGE_FLAGS_HARD 0x00000010 @@ -240,9 +241,6 @@ /* to find an entry in a kernel page-table-directory */ #define pgd_offset_k(address) pgd_offset(&init_mm, address) -#define __pmd_offset(address) \ - (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) - /* Find an entry in the third-level page table.. */ #define __pte_offset(address) \ ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) @@ -263,6 +261,12 @@ #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 + * + * We just can use generic implementation, as SuperH has no SMP feature. + * (We needed atomic implementation for SMP) + */ #include #endif /* !__ASSEMBLY__ */ diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/processor.h linux/include/asm-sh/processor.h --- v2.4.5/linux/include/asm-sh/processor.h Wed Apr 11 21:24:52 2001 +++ linux/include/asm-sh/processor.h Wed Jun 27 13:55:29 2001 @@ -23,7 +23,7 @@ enum cpu_type { CPU_SH7708, /* Represents 7707, 7708, 7708S, 7708R, 7709 */ CPU_SH7729, /* Represents 7709A, 7729 */ - CPU_SH7750, + CPU_SH7750, /* Represents 7750, 7751 */ CPU_ST40STB1, CPU_SH_NONE }; @@ -38,6 +38,9 @@ unsigned long *pte_quick; unsigned long pgtable_cache_sz; unsigned int cpu_clock, master_clock, bus_clock, module_clock; +#ifdef CONFIG_CPU_SUBTYPE_ST40STB1 + unsigned int memory_clock; +#endif }; extern struct sh_cpuinfo boot_cpu_data; @@ -76,7 +79,7 @@ struct sh_fpu_hard_struct { unsigned long fp_regs[16]; - unsigned long long xd_regs[8]; + unsigned long xfp_regs[16]; unsigned long fpscr; unsigned long fpul; @@ -86,7 +89,7 @@ /* Dummy fpu emulator */ struct sh_fpu_soft_struct { unsigned long fp_regs[16]; - unsigned long long xd_regs[8]; + unsigned long xfp_regs[16]; unsigned long fpscr; unsigned long fpul; @@ -112,7 +115,7 @@ }; #define INIT_MMAP \ -{ &init_mm, 0x80000000, 0xa0000000, NULL, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL } +{ &init_mm, 0, 0, NULL, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL } #define INIT_THREAD { \ sizeof(init_stack) + (long) &init_stack, /* sp */ \ diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/rtc.h linux/include/asm-sh/rtc.h --- v2.4.5/linux/include/asm-sh/rtc.h Thu Jan 4 13:19:13 2001 +++ linux/include/asm-sh/rtc.h Wed Jun 27 13:55:29 2001 @@ -9,4 +9,60 @@ extern void sh_rtc_gettimeofday(struct timeval *tv); extern int sh_rtc_settimeofday(const struct timeval *tv); +/* RCR1 Bits */ +#define RCR1_CF 0x80 /* Carry Flag */ +#define RCR1_CIE 0x10 /* Carry Interrupt Enable */ +#define RCR1_AIE 0x08 /* Alarm Interrupt Enable */ +#define RCR1_AF 0x01 /* Alarm Flag */ + +/* RCR2 Bits */ +#define RCR2_PEF 0x80 /* PEriodic interrupt Flag */ +#define RCR2_PESMASK 0x70 /* Periodic interrupt Set */ +#define RCR2_RTCEN 0x08 /* ENable RTC */ +#define RCR2_ADJ 0x04 /* ADJustment (30-second) */ +#define RCR2_RESET 0x02 /* Reset bit */ +#define RCR2_START 0x01 /* Start bit */ + +#if defined(__sh3__) +/* SH-3 RTC */ +#define R64CNT 0xfffffec0 +#define RSECCNT 0xfffffec2 +#define RMINCNT 0xfffffec4 +#define RHRCNT 0xfffffec6 +#define RWKCNT 0xfffffec8 +#define RDAYCNT 0xfffffeca +#define RMONCNT 0xfffffecc +#define RYRCNT 0xfffffece +#define RSECAR 0xfffffed0 +#define RMINAR 0xfffffed2 +#define RHRAR 0xfffffed4 +#define RWKAR 0xfffffed6 +#define RDAYAR 0xfffffed8 +#define RMONAR 0xfffffeda +#define RCR1 0xfffffedc +#define RCR2 0xfffffede + +#define RTC_BIT_INVERTED 0 /* No bug on SH7708, SH7709A */ +#elif defined(__SH4__) +/* SH-4 RTC */ +#define R64CNT 0xffc80000 +#define RSECCNT 0xffc80004 +#define RMINCNT 0xffc80008 +#define RHRCNT 0xffc8000c +#define RWKCNT 0xffc80010 +#define RDAYCNT 0xffc80014 +#define RMONCNT 0xffc80018 +#define RYRCNT 0xffc8001c /* 16bit */ +#define RSECAR 0xffc80020 +#define RMINAR 0xffc80024 +#define RHRAR 0xffc80028 +#define RWKAR 0xffc8002c +#define RDAYAR 0xffc80030 +#define RMONAR 0xffc80034 +#define RCR1 0xffc80038 +#define RCR2 0xffc8003c + +#define RTC_BIT_INVERTED 0x40 /* bug on SH7750, SH7750S */ +#endif + #endif /* _ASM_RTC_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/semaphore.h linux/include/asm-sh/semaphore.h --- v2.4.5/linux/include/asm-sh/semaphore.h Tue Apr 17 17:19:31 2001 +++ linux/include/asm-sh/semaphore.h Wed Jun 27 13:55:29 2001 @@ -3,6 +3,7 @@ #include +#ifdef __KERNEL__ /* * SMP- and interrupt-safe semaphores. * @@ -84,13 +85,10 @@ asmlinkage int __down_interruptible(struct semaphore * sem); asmlinkage int __down_trylock(struct semaphore * sem); asmlinkage void __up(struct semaphore * sem); -extern struct rw_semaphore *__down_read(struct rw_semaphore *sem, int carry); -extern struct rw_semaphore *__down_write(struct rw_semaphore *sem, int carry); -asmlinkage struct rw_semaphore *__rwsem_wake(struct rw_semaphore *sem); extern spinlock_t semaphore_wake_lock; -extern __inline__ void down(struct semaphore * sem) +static inline void down(struct semaphore * sem) { #if WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); @@ -100,7 +98,7 @@ __down(sem); } -extern __inline__ int down_interruptible(struct semaphore * sem) +static inline int down_interruptible(struct semaphore * sem) { int ret = 0; #if WAITQUEUE_DEBUG @@ -112,7 +110,7 @@ return ret; } -extern __inline__ int down_trylock(struct semaphore * sem) +static inline int down_trylock(struct semaphore * sem) { int ret = 0; #if WAITQUEUE_DEBUG @@ -128,7 +126,7 @@ * Note! This is subtle. We jump to wake people up only if * the semaphore was negative (== somebody was waiting on it). */ -extern __inline__ void up(struct semaphore * sem) +static inline void up(struct semaphore * sem) { #if WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); @@ -137,4 +135,5 @@ __up(sem); } +#endif #endif /* __ASM_SH_SEMAPHORE_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/serial-bigsur.h linux/include/asm-sh/serial-bigsur.h --- v2.4.5/linux/include/asm-sh/serial-bigsur.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-sh/serial-bigsur.h Wed Jun 27 13:55:29 2001 @@ -0,0 +1,30 @@ +/* + * include/asm-sh/serial-bigsur.h + * + * Configuration details for Big Sur 16550 based serial ports + * i.e. HD64465, PCMCIA, etc. + */ + +#ifndef _ASM_SERIAL_BIGSUR_H +#define _ASM_SERIAL_BIGSUR_H +#include + +#define BASE_BAUD (3379200 / 16) + +/* Leave 2 spare for possible PCMCIA serial cards */ +#define RS_TABLE_SIZE 3 + +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) + + +#define STD_SERIAL_PORT_DEFNS \ + /* UART CLK PORT IRQ FLAGS */ \ + { 0, BASE_BAUD, 0x3F8, HD64465_IRQ_UART, STD_COM_FLAGS } /* ttyS0 */ + + +#define SERIAL_PORT_DFNS STD_SERIAL_PORT_DEFNS + +/* XXX: This should be moved ino irq.h */ +#define irq_cannonicalize(x) (x) + +#endif /* _ASM_SERIAL_BIGSUR_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/serial.h linux/include/asm-sh/serial.h --- v2.4.5/linux/include/asm-sh/serial.h Wed Apr 11 21:24:52 2001 +++ linux/include/asm-sh/serial.h Wed Jun 27 13:55:29 2001 @@ -12,8 +12,9 @@ #ifdef CONFIG_SH_EC3104 #include +#elif defined (CONFIG_SH_BIGSUR) +#include #else - /* * This assumes you have a 1.8432 MHz clock for your UART. * diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/socket.h linux/include/asm-sh/socket.h --- v2.4.5/linux/include/asm-sh/socket.h Sat Feb 3 11:26:44 2001 +++ linux/include/asm-sh/socket.h Wed Jun 20 21:00:55 2001 @@ -58,6 +58,7 @@ /* level. For writing rarp and */ /* other similar things on the */ /* user level. */ +#define SOCK_MAX (SOCK_PACKET+1) #endif #endif /* __ASM_SH_SOCKET_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/softirq.h linux/include/asm-sh/softirq.h --- v2.4.5/linux/include/asm-sh/softirq.h Fri Aug 4 16:15:37 2000 +++ linux/include/asm-sh/softirq.h Wed Jun 27 13:55:29 2001 @@ -4,11 +4,29 @@ #include #include -#define cpu_bh_disable(cpu) do { local_bh_count(cpu)++; barrier(); } while (0) -#define cpu_bh_enable(cpu) do { barrier(); local_bh_count(cpu)--; } while (0) +#define local_bh_disable() \ +do { \ + local_bh_count(smp_processor_id())++; \ + barrier(); \ +} while (0) -#define local_bh_disable() cpu_bh_disable(smp_processor_id()) -#define local_bh_enable() cpu_bh_enable(smp_processor_id()) +#define __local_bh_enable() \ +do { \ + barrier(); \ + local_bh_count(smp_processor_id())--; \ +} while (0) + +#define local_bh_enable() \ +do { \ + if (!--local_bh_count(smp_processor_id()) \ + && softirq_pending(smp_processor_id())) { \ + do_softirq(); \ + __sti(); \ + } \ +} while (0) + +#define __cpu_raise_softirq(cpu, nr) set_bit((nr), &softirq_pending(cpu)); +#define raise_softirq(nr) __cpu_raise_softirq(smp_processor_id(), (nr)) #define in_softirq() (local_bh_count(smp_processor_id()) != 0) diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/string.h linux/include/asm-sh/string.h --- v2.4.5/linux/include/asm-sh/string.h Mon Oct 2 11:57:34 2000 +++ linux/include/asm-sh/string.h Wed Jun 27 13:55:29 2001 @@ -7,7 +7,7 @@ */ #define __HAVE_ARCH_STRCPY -extern __inline__ char *strcpy(char *__dest, const char *__src) +static __inline__ char *strcpy(char *__dest, const char *__src) { register char *__xdest = __dest; unsigned long __dummy; @@ -26,7 +26,7 @@ } #define __HAVE_ARCH_STRNCPY -extern __inline__ char *strncpy(char *__dest, const char *__src, size_t __n) +static __inline__ char *strncpy(char *__dest, const char *__src, size_t __n) { register char *__xdest = __dest; unsigned long __dummy; @@ -52,7 +52,7 @@ } #define __HAVE_ARCH_STRCMP -extern __inline__ int strcmp(const char *__cs, const char *__ct) +static __inline__ int strcmp(const char *__cs, const char *__ct) { register int __res; unsigned long __dummy; @@ -78,7 +78,7 @@ } #define __HAVE_ARCH_STRNCMP -extern __inline__ int strncmp(const char *__cs, const char *__ct, size_t __n) +static __inline__ int strncmp(const char *__cs, const char *__ct, size_t __n) { register int __res; unsigned long __dummy; diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/termios.h linux/include/asm-sh/termios.h --- v2.4.5/linux/include/asm-sh/termios.h Sat Feb 3 20:00:45 2001 +++ linux/include/asm-sh/termios.h Mon Jun 11 19:15:27 2001 @@ -55,6 +55,7 @@ #define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */ #define N_HDLC 13 /* synchronous HDLC */ #define N_SYNC_PPP 14 +#define N_HCI 15 /* Bluetooth HCI UART */ #ifdef __KERNEL__ diff -u --recursive --new-file v2.4.5/linux/include/asm-sh/user.h linux/include/asm-sh/user.h --- v2.4.5/linux/include/asm-sh/user.h Mon Mar 27 10:26:15 2000 +++ linux/include/asm-sh/user.h Wed Jun 27 13:55:29 2001 @@ -31,7 +31,7 @@ struct user_fpu_struct { unsigned long fp_regs[16]; - unsigned long long xd_regs[8]; + unsigned long xfp_regs[16]; unsigned long fpscr; unsigned long fpul; }; diff -u --recursive --new-file v2.4.5/linux/include/asm-sparc/audioio.h linux/include/asm-sparc/audioio.h --- v2.4.5/linux/include/asm-sparc/audioio.h Tue Oct 10 10:33:52 2000 +++ linux/include/asm-sparc/audioio.h Mon Jun 11 19:15:27 2001 @@ -428,9 +428,6 @@ extern int unregister_sparcaudio_driver(struct sparcaudio_driver *, int); extern void sparcaudio_output_done(struct sparcaudio_driver *, int); extern void sparcaudio_input_done(struct sparcaudio_driver *, int); -extern int amd7930_init(void); -extern int cs4231_init(void); -extern int dbri_init(void); #endif diff -u --recursive --new-file v2.4.5/linux/include/asm-sparc/hardirq.h linux/include/asm-sparc/hardirq.h --- v2.4.5/linux/include/asm-sparc/hardirq.h Mon Aug 28 21:20:03 2000 +++ linux/include/asm-sparc/hardirq.h Mon Jul 2 13:56:40 2001 @@ -1,7 +1,7 @@ /* hardirq.h: 32-bit Sparc hard IRQ support. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1998-2000 Anton Blanchard (anton@linuxcare.com) + * Copyright (C) 1998-2000 Anton Blanchard (anton@samba.org) */ #ifndef __SPARC_HARDIRQ_H @@ -14,8 +14,8 @@ /* entry.S is sensitive to the offsets of these fields */ typedef struct { - unsigned int __softirq_active; - unsigned int __softirq_mask; + unsigned int __softirq_pending; + unsigned int __unused_1; #ifndef CONFIG_SMP unsigned int __local_irq_count; #else diff -u --recursive --new-file v2.4.5/linux/include/asm-sparc/linux_logo.h linux/include/asm-sparc/linux_logo.h --- v2.4.5/linux/include/asm-sparc/linux_logo.h Wed Sep 30 14:16:33 1998 +++ linux/include/asm-sparc/linux_logo.h Tue Jun 12 11:08:46 2001 @@ -1,4 +1,4 @@ -/* $Id: linux_logo.h,v 1.6 1998/08/20 04:44:39 ecd Exp $ +/* $Id: linux_logo.h,v 1.7 2001/06/08 23:01:58 davem Exp $ * include/asm-sparc/linux_logo.h: This is a linux logo * to be displayed on boot. * @@ -23,1025 +23,912 @@ #define linux_logo_banner "Linux/SPARC version " UTS_RELEASE -#define LINUX_LOGO_COLORS 219 +#define __HAVE_ARCH_LINUX_LOGO +#define __HAVE_ARCH_LINUX_LOGO16 + +#define LINUX_LOGO_COLORS 221 #ifdef INCLUDE_LINUX_LOGO_DATA unsigned char linux_logo_red[] __initdata = { - 0x03, 0x9E, 0xEC, 0xEE, 0xC4, 0xDA, 0x50, 0xC9, - 0xC5, 0xED, 0x65, 0xE3, 0xE3, 0xF4, 0x24, 0xA4, - 0xEC, 0xEE, 0x94, 0xE5, 0xE3, 0x6A, 0xA6, 0xC4, - 0xDC, 0xE5, 0x13, 0xF3, 0xD1, 0xFD, 0xE2, 0xDB, - 0xA0, 0xC2, 0xEC, 0xB8, 0xC2, 0xD5, 0xF2, 0xF4, - 0xC5, 0x3E, 0xF1, 0x1B, 0x55, 0xF5, 0xCF, 0xF7, - 0xA9, 0xB4, 0xEB, 0x6C, 0x0A, 0x74, 0xB4, 0xF7, - 0xF0, 0xF5, 0xD4, 0xF2, 0xCE, 0xF5, 0xC7, 0x26, - 0x5B, 0xF4, 0xBC, 0x7F, 0xAB, 0x82, 0x94, 0xE5, - 0xFC, 0x3A, 0xF2, 0xFD, 0xF0, 0x1C, 0xEF, 0xD4, - 0xF3, 0x0F, 0xED, 0xF7, 0xC9, 0x49, 0xC3, 0xBA, - 0xC8, 0xD4, 0xE7, 0xF3, 0xF5, 0xA7, 0xEC, 0xF9, - 0xFA, 0x0A, 0xF5, 0xCF, 0xFC, 0xEA, 0xE1, 0xA6, - 0xD6, 0xBC, 0xF8, 0xF7, 0xB4, 0xEB, 0xDC, 0x84, - 0xCE, 0xBA, 0x45, 0xD6, 0x86, 0x50, 0x96, 0xC6, - 0x8C, 0x6E, 0xE8, 0x60, 0x3C, 0x70, 0xF0, 0x93, - 0x7C, 0xDA, 0xDA, 0x9C, 0xBA, 0x6D, 0x4D, 0x2B, - 0x2F, 0x8B, 0xE0, 0xCC, 0xDA, 0x5C, 0x3D, 0xEE, - 0xDB, 0x46, 0xAC, 0x96, 0xCE, 0xD1, 0xE3, 0xF1, - 0x96, 0x7A, 0x80, 0xB2, 0xBA, 0xB6, 0xD2, 0x1E, - 0x7E, 0xAA, 0xC4, 0xF0, 0x96, 0x65, 0x9E, 0xC2, - 0xAA, 0xF5, 0xF2, 0xE9, 0xE6, 0xD1, 0x35, 0xC7, - 0xF6, 0xB6, 0xE8, 0x82, 0xBE, 0xC2, 0xF2, 0x9E, - 0xC7, 0xB4, 0x0F, 0xF7, 0xE8, 0xD8, 0xCC, 0x9C, - 0xD8, 0xD8, 0xA0, 0xEA, 0xC6, 0xA8, 0xE0, 0xEC, - 0xD1, 0xF7, 0xF4, 0xFC, 0x75, 0xBD, 0xDC, 0xDD, - 0xCC, 0xE1, 0xFA, 0xEE, 0xAA, 0xEC, 0xF2, 0xB8, - 0xE2, 0xCD, 0x87 + 0x00, 0x06, 0x0a, 0x0e, 0x16, 0x1a, 0x1e, 0x22, + 0x12, 0x00, 0x2a, 0x36, 0x42, 0x4e, 0x4a, 0x56, + 0x26, 0x46, 0x2e, 0x32, 0x52, 0x3a, 0x02, 0x65, + 0x5e, 0x3e, 0x74, 0x8a, 0xa2, 0x9a, 0x86, 0xc6, + 0xc3, 0x65, 0xbb, 0xd2, 0xda, 0xd6, 0xe2, 0xf6, + 0xfd, 0xae, 0x7b, 0xdd, 0xea, 0x6a, 0xaa, 0xe7, + 0xbe, 0x5a, 0xee, 0x9e, 0x95, 0x80, 0x76, 0x79, + 0x62, 0x36, 0x9a, 0xe2, 0xec, 0xe1, 0xb8, 0xd7, + 0xaf, 0x25, 0xbc, 0xc0, 0xef, 0xea, 0xe8, 0xe8, + 0xf5, 0xf1, 0xda, 0xd3, 0x79, 0xdb, 0xf4, 0xf6, + 0xf6, 0xf6, 0xe2, 0x3d, 0xb4, 0xce, 0xe6, 0xee, + 0xf6, 0x68, 0xd8, 0xec, 0xf5, 0xc6, 0xc8, 0x9c, + 0x89, 0xd2, 0xee, 0xcb, 0xb9, 0xd2, 0x66, 0x5e, + 0x8b, 0xbe, 0xa8, 0xd5, 0xca, 0xb6, 0xae, 0x9c, + 0xc5, 0xbe, 0xbe, 0xca, 0x90, 0xb2, 0x9a, 0xa8, + 0xb6, 0xf2, 0xce, 0xfa, 0xb2, 0x6e, 0xa6, 0xfe, + 0xf6, 0xec, 0xfe, 0xd2, 0xea, 0xf5, 0xf2, 0xf2, + 0xe9, 0xee, 0xf6, 0xf2, 0xee, 0xf6, 0xda, 0xd4, + 0xfa, 0xca, 0xf2, 0xf6, 0xfe, 0xf2, 0xda, 0xe4, + 0xf6, 0xdd, 0xf2, 0xee, 0xfa, 0xf0, 0x12, 0x4a, + 0xd6, 0xf2, 0x8e, 0xf2, 0xf6, 0xf6, 0xb5, 0xf1, + 0x26, 0x9a, 0xea, 0xf6, 0xe0, 0xd2, 0x16, 0x9a, + 0x2e, 0xd2, 0x70, 0xd6, 0x46, 0x7c, 0xb4, 0x62, + 0xda, 0xee, 0xd6, 0xa3, 0x74, 0xa7, 0xa2, 0xe0, + 0xae, 0xbe, 0xce, 0xe2, 0xa3, 0x8e, 0x6d, 0x8e, + 0x32, 0xaf, 0x50, 0x9e, 0x5b, 0x8a, 0x98, 0x82, + 0x7a, 0x82, 0x56, 0x7c, 0x8a, 0x56, 0x5e, 0x86, + 0x6a, 0x52, 0x59, 0x64, 0x5e, }; unsigned char linux_logo_green[] __initdata = { - 0x03, 0x88, 0xC4, 0xE2, 0x85, 0xC2, 0x44, 0xA3, - 0xA9, 0xD3, 0x65, 0xA6, 0xC5, 0xF3, 0x24, 0xA4, - 0xB4, 0xD6, 0x63, 0xD5, 0xB7, 0x44, 0x86, 0x94, - 0xC2, 0xE4, 0x14, 0xB6, 0xD2, 0xFB, 0xD4, 0xB2, - 0x73, 0x96, 0xDB, 0x92, 0xC2, 0x95, 0xC2, 0xDA, - 0xA4, 0x36, 0xD4, 0x0E, 0x55, 0xF4, 0xC4, 0xE9, - 0x75, 0xB4, 0xBC, 0x52, 0x0A, 0x74, 0x84, 0xEB, - 0xDC, 0xDA, 0xA2, 0xD6, 0x9B, 0xBD, 0xB7, 0x12, - 0x44, 0xCA, 0x8C, 0x65, 0x7B, 0x54, 0x94, 0xAB, - 0xF4, 0x25, 0xC4, 0xFD, 0xE4, 0x1C, 0xDD, 0xAB, - 0xBD, 0x06, 0xCB, 0xD6, 0xCA, 0x33, 0x8C, 0xA2, - 0x92, 0x9C, 0xBC, 0xDB, 0xCD, 0x6E, 0xEC, 0xEE, - 0xBC, 0x03, 0xDA, 0xCE, 0xF4, 0xB6, 0xDB, 0x92, - 0xAD, 0xBC, 0xDE, 0xD5, 0x7B, 0xAE, 0x9D, 0x84, - 0xB6, 0x96, 0x44, 0xBA, 0x6E, 0x3C, 0x7A, 0xB2, - 0x8C, 0x4C, 0xCE, 0x4C, 0x3C, 0x5A, 0xCA, 0x6D, - 0x7C, 0xCE, 0xDA, 0x9C, 0xAA, 0x6D, 0x4D, 0x2B, - 0x1B, 0x5E, 0xCB, 0xAC, 0xBE, 0x5C, 0x2E, 0xDC, - 0xBD, 0x3E, 0xAC, 0x82, 0xB6, 0xBE, 0xD3, 0xBD, - 0x72, 0x62, 0x6C, 0x82, 0x92, 0x9E, 0xB0, 0x13, - 0x4A, 0x8E, 0xBE, 0xCE, 0x86, 0x45, 0x6B, 0xAA, - 0x9A, 0xC5, 0xC6, 0xDA, 0xC5, 0xC4, 0x34, 0x9B, - 0xCC, 0xAC, 0xC4, 0x76, 0x9A, 0x9E, 0xEE, 0x62, - 0xC6, 0x76, 0x0D, 0xE4, 0xDA, 0xD5, 0xA5, 0x92, - 0xCD, 0xB2, 0x7C, 0xCC, 0xBE, 0x7E, 0xDC, 0xD6, - 0xB9, 0xE3, 0xD4, 0xF6, 0x55, 0x82, 0xA4, 0xAA, - 0x8D, 0xBB, 0xCE, 0xD5, 0x8A, 0xDB, 0xD4, 0x8B, - 0xCA, 0x93, 0x63 + 0x00, 0x06, 0x0a, 0x0e, 0x16, 0x1a, 0x1e, 0x22, + 0x12, 0x00, 0x2a, 0x36, 0x42, 0x4e, 0x4a, 0x56, + 0x26, 0x46, 0x2e, 0x32, 0x52, 0x3a, 0x02, 0x65, + 0x5e, 0x3e, 0x74, 0x8a, 0xa2, 0x9a, 0x86, 0xc6, + 0xc3, 0x62, 0xbb, 0xd2, 0xda, 0xd6, 0xe2, 0xf6, + 0xfd, 0xae, 0x7b, 0xdd, 0xea, 0x6a, 0xaa, 0xe7, + 0xbe, 0x5a, 0xee, 0x9e, 0x95, 0x80, 0x62, 0x5c, + 0x4e, 0x26, 0x72, 0xaa, 0xba, 0xaf, 0x90, 0xae, + 0x92, 0x1a, 0xa4, 0x85, 0xb6, 0xbe, 0xc3, 0xc8, + 0xcf, 0xd0, 0xc2, 0xce, 0x57, 0xa2, 0xd6, 0xda, + 0xda, 0xd7, 0xb8, 0x2a, 0x7b, 0x91, 0xae, 0xca, + 0xda, 0x45, 0x9e, 0xb2, 0xd7, 0x9b, 0x90, 0x76, + 0x5c, 0xa2, 0xbe, 0xa6, 0x85, 0x96, 0x4e, 0x46, + 0x66, 0x92, 0x7a, 0x9a, 0x96, 0x9d, 0x9a, 0x6b, + 0x8a, 0x8e, 0xb2, 0xca, 0x90, 0xa6, 0x79, 0x7c, + 0xb6, 0xf2, 0xce, 0xfa, 0xb2, 0x6e, 0xa6, 0xfa, + 0xea, 0xd7, 0xf6, 0xbc, 0xda, 0xde, 0xda, 0xe6, + 0xca, 0xd8, 0xea, 0xe0, 0xcc, 0xf2, 0xce, 0xb2, + 0xee, 0xa2, 0xd6, 0xe6, 0xf6, 0xd7, 0xc5, 0xb8, + 0xc6, 0xb9, 0xce, 0xde, 0xce, 0xc6, 0x0e, 0x36, + 0xae, 0xbe, 0x86, 0xba, 0xbe, 0xe6, 0x8e, 0xc4, + 0x1e, 0x8e, 0xae, 0xba, 0xb2, 0xa6, 0x12, 0x7a, + 0x20, 0xc6, 0x64, 0xaa, 0x2f, 0x70, 0x85, 0x46, + 0xce, 0xd6, 0xa6, 0x6e, 0x51, 0x72, 0x92, 0xa6, + 0x87, 0x96, 0xa2, 0xd6, 0x85, 0x7a, 0x6a, 0x6e, + 0x22, 0x76, 0x36, 0x76, 0x3c, 0x6e, 0x63, 0x53, + 0x66, 0x62, 0x42, 0x50, 0x56, 0x42, 0x56, 0x56, + 0x56, 0x3e, 0x51, 0x52, 0x56, }; unsigned char linux_logo_blue[] __initdata = { - 0x04, 0x28, 0x10, 0x8C, 0x0B, 0x84, 0x14, 0x1A, - 0x77, 0x1F, 0x64, 0x0E, 0x85, 0xD2, 0x24, 0xA4, - 0x0F, 0x54, 0x0C, 0x7C, 0x3F, 0x04, 0x20, 0x0D, - 0x54, 0xDF, 0x14, 0x0D, 0xD1, 0xE9, 0xB0, 0x11, - 0x0A, 0x40, 0x57, 0x14, 0xC3, 0x0C, 0x04, 0x12, - 0x50, 0x0C, 0x7D, 0x05, 0x55, 0xF2, 0xBA, 0xC7, - 0x09, 0xB4, 0x0E, 0x24, 0x0B, 0x74, 0x0C, 0xB6, - 0x80, 0x48, 0x10, 0x34, 0x0F, 0x0C, 0xA0, 0x04, - 0x19, 0x10, 0x0E, 0x14, 0x0E, 0x05, 0x94, 0x0E, - 0xCA, 0x0B, 0x46, 0xFB, 0xB4, 0x1C, 0x9B, 0x1A, - 0x21, 0x09, 0x14, 0x4D, 0xCB, 0x08, 0x11, 0x7C, - 0x20, 0x10, 0x24, 0x66, 0x79, 0x07, 0xEA, 0xC9, - 0x0C, 0x08, 0x38, 0xC4, 0xD8, 0x24, 0xBE, 0x6C, - 0x51, 0xBB, 0x8C, 0x36, 0x0A, 0x0F, 0x0C, 0x84, - 0x3C, 0x54, 0x44, 0x7C, 0x28, 0x0E, 0x28, 0x7F, - 0x8C, 0x0F, 0x54, 0x24, 0x3C, 0x18, 0x54, 0x17, - 0x7C, 0x9C, 0xDA, 0x9C, 0x7C, 0x6C, 0x4D, 0x2C, - 0x09, 0x0E, 0x8A, 0x50, 0x4C, 0x5B, 0x14, 0xAC, - 0x19, 0x3C, 0xAC, 0x5C, 0x64, 0x97, 0x94, 0x37, - 0x29, 0x3C, 0x44, 0x3C, 0x2C, 0x7C, 0x70, 0x07, - 0x04, 0x29, 0xB2, 0x64, 0x74, 0x07, 0x07, 0x2C, - 0x74, 0x2E, 0x6C, 0xA4, 0x29, 0x9E, 0x34, 0x27, - 0x2F, 0x98, 0x48, 0x5C, 0x0C, 0x5C, 0xE8, 0x04, - 0xC2, 0x0C, 0x0A, 0xB2, 0x74, 0xCB, 0x46, 0x78, - 0xB4, 0x5C, 0x18, 0x80, 0x8C, 0x24, 0xD9, 0xAC, - 0x87, 0x99, 0x1D, 0xE8, 0x14, 0x0D, 0x10, 0x17, - 0x0A, 0x67, 0x3C, 0x68, 0x3C, 0x69, 0x90, 0x22, - 0x6C, 0x0D, 0x17 + 0x00, 0x06, 0x0a, 0x0e, 0x16, 0x1a, 0x1e, 0x22, + 0x12, 0x01, 0x2a, 0x36, 0x42, 0x4e, 0x4a, 0x56, + 0x26, 0x46, 0x2e, 0x32, 0x52, 0x3a, 0x06, 0x65, + 0x5e, 0x3e, 0x74, 0x8a, 0xa2, 0x9a, 0x86, 0xc6, + 0xc3, 0x59, 0xbb, 0xd2, 0xda, 0xd6, 0xe2, 0xf6, + 0xfd, 0xae, 0x7b, 0xdd, 0xea, 0x6a, 0xaa, 0xe7, + 0xbe, 0x5a, 0xee, 0x9e, 0x95, 0x80, 0x2e, 0x08, + 0x0a, 0x06, 0x0a, 0x0b, 0x0b, 0x0f, 0x0c, 0x0f, + 0x3d, 0x09, 0x73, 0x09, 0x0d, 0x0a, 0x10, 0x1e, + 0x2d, 0x13, 0x86, 0xba, 0x19, 0x0a, 0x36, 0x3c, + 0x26, 0x14, 0x0d, 0x06, 0x07, 0x0a, 0x0b, 0x0f, + 0x4a, 0x06, 0x0a, 0x0c, 0x2b, 0x0a, 0x0b, 0x0a, + 0x06, 0x0a, 0x0a, 0x11, 0x0b, 0x0a, 0x0a, 0x1e, + 0x0f, 0x0d, 0x0a, 0x0b, 0x22, 0x6a, 0x72, 0x0b, + 0x0b, 0x22, 0x90, 0xca, 0x90, 0x92, 0x3c, 0x2c, + 0xb6, 0xf2, 0xce, 0xfa, 0xb2, 0x6e, 0xa6, 0xea, + 0xb6, 0x7c, 0xda, 0x8e, 0xa6, 0x87, 0x66, 0xb6, + 0x81, 0x6a, 0xc6, 0x9a, 0x5b, 0xd2, 0xb6, 0x6a, + 0xca, 0x45, 0x92, 0xb2, 0xca, 0x52, 0x8a, 0x3e, + 0x2e, 0x66, 0x66, 0xae, 0x3e, 0x47, 0x06, 0x0e, + 0x52, 0x36, 0x6a, 0x0e, 0x0e, 0xbe, 0x2c, 0x0e, + 0x0a, 0x5a, 0x0d, 0x0e, 0x3e, 0x0a, 0x06, 0x2e, + 0x06, 0x9e, 0x4e, 0x36, 0x06, 0x58, 0x24, 0x06, + 0x9e, 0xae, 0x3a, 0x08, 0x08, 0x07, 0x5e, 0x0a, + 0x32, 0x2e, 0x2a, 0xb2, 0x43, 0x48, 0x5f, 0x2e, + 0x06, 0x06, 0x07, 0x24, 0x06, 0x32, 0x06, 0x06, + 0x46, 0x2e, 0x22, 0x06, 0x06, 0x1e, 0x4c, 0x06, + 0x3a, 0x22, 0x42, 0x34, 0x42, }; unsigned char linux_logo[] __initdata = { - 0xD8, 0xA3, 0x98, 0x98, 0xA3, 0xB2, 0x2F, 0x2F, - 0xA3, 0x66, 0x98, 0x98, 0x98, 0xA3, 0x2F, 0xA3, - 0x98, 0x55, 0xA0, 0xA3, 0xB2, 0x51, 0x51, 0x2F, - 0x98, 0x55, 0x8F, 0x2F, 0x89, 0x44, 0x89, 0x51, - 0xB2, 0x2F, 0x66, 0xA3, 0x2F, 0x2F, 0x66, 0x66, - 0xA3, 0xB2, 0xB2, 0xB2, 0x89, 0xD8, 0x44, 0x44, - 0xD8, 0x83, 0xD8, 0xA3, 0x98, 0x98, 0xA3, 0xB2, - 0x2F, 0x2F, 0xA3, 0x66, 0x98, 0x98, 0x98, 0xA3, - 0x2F, 0xA3, 0x98, 0x55, 0xA0, 0xA3, 0xB2, 0x51, - 0x51, 0x2F, 0x98, 0x55, 0x8F, 0x2F, 0x89, 0x44, - 0xA3, 0x55, 0x55, 0x98, 0x2F, 0x2F, 0x2F, 0xA3, - 0x66, 0x66, 0x98, 0x98, 0x66, 0x66, 0x66, 0x98, - 0x55, 0xA5, 0x8F, 0xA3, 0x51, 0x51, 0xB2, 0x2F, - 0x66, 0x66, 0xA3, 0x51, 0x89, 0x51, 0xB2, 0x2F, - 0x2F, 0xA3, 0x66, 0xA3, 0xA3, 0xA3, 0x2F, 0x2F, - 0xB2, 0xB2, 0x2F, 0x2F, 0xB2, 0x51, 0x51, 0x51, - 0x51, 0x51, 0xA3, 0x55, 0x55, 0x98, 0x2F, 0x2F, - 0x2F, 0xA3, 0x66, 0x66, 0x98, 0x98, 0x66, 0x66, - 0x66, 0x98, 0x55, 0xA5, 0x8F, 0xA3, 0x51, 0x51, - 0xB2, 0x2F, 0x66, 0x66, 0xA3, 0x51, 0x89, 0x51, - 0x98, 0xA5, 0x55, 0x8F, 0x2F, 0xB2, 0x2F, 0xA3, - 0x66, 0x66, 0x98, 0x8F, 0x66, 0x66, 0x66, 0x98, - 0xA0, 0x8F, 0xA3, 0xB2, 0x51, 0x51, 0xB2, 0x2F, - 0xA3, 0xA3, 0x2F, 0xB2, 0x51, 0xB2, 0x2F, 0x2F, - 0xA3, 0x66, 0x98, 0xA3, 0x51, 0xB2, 0x2F, 0xA3, - 0xB2, 0x51, 0x51, 0xB2, 0xB2, 0x51, 0xB2, 0xB2, - 0xB2, 0x2F, 0x98, 0xA5, 0x55, 0x8F, 0x2F, 0xB2, - 0x2F, 0xA3, 0x66, 0x66, 0x98, 0x8F, 0x66, 0x66, - 0x66, 0x98, 0xA0, 0x8F, 0xA3, 0xB2, 0x51, 0x51, - 0xB2, 0x2F, 0xA3, 0xA3, 0x2F, 0x51, 0x51, 0xB2, - 0xA0, 0xA5, 0x55, 0x66, 0xB2, 0x51, 0xB2, 0xA3, - 0x66, 0x66, 0x98, 0x66, 0x66, 0x66, 0x98, 0x98, - 0x66, 0xA3, 0x2F, 0xB2, 0x51, 0x51, 0xB2, 0xA3, - 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0xA3, - 0x66, 0x98, 0xB2, 0x4C, 0x54, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0xCE, 0x2F, 0xB2, 0x2F, 0x2F, - 0xA3, 0x98, 0xA0, 0xA5, 0x55, 0x66, 0xB2, 0x51, - 0xB2, 0xA3, 0x66, 0x66, 0x98, 0x66, 0x66, 0x66, - 0x98, 0x98, 0x66, 0xA3, 0x2F, 0xB2, 0x51, 0x51, - 0xB2, 0xA3, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, 0x2F, - 0xA0, 0xA0, 0x8F, 0xA3, 0xB2, 0x51, 0xB2, 0x2F, - 0x66, 0x66, 0x98, 0x66, 0x66, 0x66, 0x66, 0x66, - 0xA3, 0x2F, 0x51, 0x51, 0x51, 0xB2, 0x2F, 0xA3, - 0x66, 0x66, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, - 0x2F, 0xA0, 0xDA, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x9C, 0xB2, 0xA3, - 0x66, 0x98, 0xA0, 0xA0, 0x8F, 0xA3, 0xB2, 0x51, - 0xB2, 0x2F, 0x66, 0x66, 0x98, 0x66, 0x66, 0x66, - 0x66, 0x66, 0xA3, 0x2F, 0x51, 0x51, 0x51, 0xB2, - 0x2F, 0xA3, 0x66, 0x66, 0x66, 0xA3, 0xA3, 0xA3, - 0x8F, 0x8F, 0x66, 0x2F, 0x51, 0x51, 0xB2, 0xA3, - 0x66, 0x98, 0x98, 0x66, 0x66, 0x66, 0x2F, 0x2F, - 0xB2, 0x51, 0xB2, 0xB2, 0x2F, 0x2F, 0xA3, 0x66, - 0x66, 0x66, 0xA3, 0xA3, 0x2F, 0xA3, 0xA3, 0xB2, - 0x9C, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0xDA, 0x3A, 0x20, 0x54, 0x55, - 0xA3, 0x98, 0x8F, 0x8F, 0x66, 0x2F, 0x51, 0x51, - 0xB2, 0xA3, 0x66, 0x98, 0x98, 0x66, 0x66, 0x66, - 0x2F, 0x2F, 0xB2, 0x51, 0xB2, 0xB2, 0x2F, 0x2F, - 0xA3, 0x66, 0x66, 0x66, 0x2F, 0xA3, 0x2F, 0x2F, - 0x66, 0x66, 0xA3, 0x2F, 0xB2, 0xB2, 0x2F, 0x66, - 0x8F, 0x8F, 0x8F, 0x66, 0xA3, 0xA3, 0xB2, 0xB2, - 0xB2, 0xB2, 0xB2, 0xB2, 0x2F, 0xA3, 0xA3, 0xA3, - 0xA3, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0xAD, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0xA7, 0x4C, 0xCE, 0xDA, 0x20, - 0xA6, 0x2F, 0x66, 0x66, 0xA3, 0x2F, 0xB2, 0xB2, - 0x2F, 0x66, 0x8F, 0x8F, 0x8F, 0x66, 0xA3, 0xA3, - 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0x2F, 0xA3, - 0xA3, 0xA3, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, 0x2F, - 0xA3, 0x98, 0x66, 0x2F, 0xB2, 0xB2, 0x2F, 0x98, - 0x8F, 0x8F, 0x98, 0x66, 0xA3, 0xB2, 0xB2, 0xB2, - 0x2F, 0x2F, 0x2F, 0x2F, 0xA3, 0x2F, 0xA3, 0xA3, - 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0x51, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0xCE, 0x55, 0xAD, 0xA7, 0x54, - 0x20, 0x8F, 0xA3, 0x98, 0x66, 0x2F, 0xB2, 0xB2, - 0x2F, 0x98, 0x8F, 0x8F, 0x98, 0x66, 0xA3, 0xB2, - 0xB2, 0xB2, 0x2F, 0x2F, 0x2F, 0x2F, 0xA3, 0x2F, - 0xA3, 0xA3, 0xA3, 0x2F, 0xA3, 0xA3, 0xA3, 0xA3, - 0xA3, 0x8F, 0x66, 0x2F, 0xB2, 0x51, 0x2F, 0x98, - 0xA0, 0x8F, 0x66, 0xA3, 0x2F, 0x51, 0x51, 0xB2, - 0xA3, 0xA3, 0xA3, 0x2F, 0xA3, 0xA3, 0x66, 0x66, - 0x98, 0x98, 0x98, 0x66, 0x98, 0x66, 0x55, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0xCE, 0x4C, 0x9C, 0x2E, 0xDA, - 0x20, 0xDA, 0x51, 0x8F, 0x66, 0x2F, 0xB2, 0x51, - 0x2F, 0x98, 0xA0, 0x8F, 0x66, 0xA3, 0x2F, 0x51, - 0x51, 0xB2, 0xA3, 0xA3, 0xA3, 0x2F, 0xA3, 0xA3, - 0x66, 0x66, 0x98, 0x98, 0x98, 0x98, 0x98, 0x66, - 0x51, 0x66, 0x2F, 0xB2, 0x51, 0xB2, 0xA3, 0xA0, - 0xA0, 0x66, 0xA3, 0xB2, 0xB2, 0xB2, 0xB2, 0xA3, - 0x66, 0x66, 0x66, 0xA3, 0xA3, 0x66, 0x98, 0x98, - 0x98, 0x98, 0x98, 0x66, 0x66, 0xB2, 0x6D, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x6D, 0x3A, 0x20, 0x20, 0x20, - 0x20, 0x20, 0xA5, 0x66, 0x2F, 0xB2, 0x51, 0xB2, - 0xA3, 0xA0, 0xA0, 0x66, 0xA3, 0xB2, 0xB2, 0xB2, - 0xB2, 0xA3, 0x66, 0x66, 0x66, 0xA3, 0xA3, 0x66, - 0x98, 0x98, 0x8F, 0x98, 0x66, 0x66, 0x66, 0x66, - 0x51, 0x2F, 0xB2, 0x51, 0x51, 0x2F, 0x66, 0xA0, - 0x8F, 0xA3, 0x2F, 0xB2, 0xB2, 0x2F, 0x2F, 0x66, - 0x98, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x2F, 0xA3, 0x2F, 0x2F, 0x51, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0xDA, 0x51, 0xB2, 0x51, 0x51, 0x2F, - 0x66, 0xA0, 0x8F, 0xA3, 0x2F, 0xB2, 0xB2, 0x2F, - 0x2F, 0x66, 0x98, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0xA3, 0x2F, 0x2F, 0x2F, 0x2F, - 0x51, 0x2F, 0xB2, 0x51, 0x2F, 0xA3, 0x8F, 0x8F, - 0x98, 0xA3, 0xB2, 0xB2, 0x2F, 0xA3, 0x98, 0x66, - 0x98, 0x98, 0x66, 0x66, 0x66, 0x66, 0xA3, 0x2F, - 0xB2, 0xB2, 0x51, 0xB2, 0xB2, 0x66, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0xA3, 0xB2, 0x51, 0x2F, 0xA3, - 0x8F, 0x8F, 0x98, 0xA3, 0xB2, 0xB2, 0x2F, 0xA3, - 0x98, 0x66, 0x98, 0x98, 0x66, 0x66, 0x66, 0x66, - 0xA3, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, - 0xB2, 0x2F, 0xA3, 0x2F, 0x66, 0x98, 0x8F, 0x98, - 0xA3, 0x2F, 0x2F, 0xA3, 0x98, 0x98, 0x98, 0x98, - 0x66, 0x98, 0x66, 0x98, 0x66, 0xA3, 0x2F, 0xB2, - 0x51, 0x51, 0x51, 0xB2, 0xB2, 0x8F, 0x20, 0x20, - 0x20, 0x54, 0x6D, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x54, 0x6D, 0x6D, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x4C, 0xA3, 0x2F, 0x66, 0x98, - 0x8F, 0x98, 0xA3, 0x2F, 0x2F, 0xA3, 0x98, 0x98, - 0x98, 0x98, 0x66, 0x98, 0x66, 0x98, 0x66, 0xA3, - 0x2F, 0xB2, 0x51, 0x51, 0x51, 0xB2, 0x2F, 0x2F, - 0x2F, 0xA3, 0xA3, 0x66, 0x98, 0x98, 0x8F, 0x98, - 0x2F, 0x2F, 0x2F, 0x66, 0x8F, 0x8F, 0x98, 0xA3, - 0x66, 0x66, 0x8F, 0x98, 0x98, 0x66, 0x2F, 0xB2, - 0x51, 0xB2, 0x2F, 0xA3, 0xA3, 0xA0, 0x20, 0x20, - 0xDA, 0x2E, 0x3A, 0xA7, 0x20, 0x20, 0x20, 0x20, - 0x20, 0xCE, 0x2A, 0x2A, 0x2E, 0xA7, 0xDA, 0x20, - 0x20, 0x20, 0x20, 0x9C, 0xA3, 0x66, 0x98, 0x98, - 0x8F, 0x98, 0x2F, 0x2F, 0x2F, 0x66, 0x8F, 0x8F, - 0x98, 0xA3, 0x66, 0x66, 0x8F, 0x98, 0x98, 0x66, - 0x2F, 0xB2, 0x51, 0xB2, 0x2F, 0x2F, 0xA3, 0xA3, - 0xB2, 0xA3, 0x66, 0x98, 0x8F, 0x8F, 0x66, 0xA3, - 0x2F, 0x2F, 0x66, 0x98, 0x98, 0x66, 0x2F, 0x2F, - 0xA3, 0x98, 0x8F, 0x98, 0x66, 0x2F, 0xB2, 0xB2, - 0xB2, 0xA3, 0x66, 0x66, 0x66, 0x98, 0x20, 0x3A, - 0x98, 0x89, 0x8F, 0x6D, 0x20, 0x20, 0x20, 0x20, - 0x4C, 0x66, 0x51, 0x44, 0x51, 0x2E, 0x54, 0x20, - 0x20, 0x20, 0x20, 0xA7, 0x66, 0x98, 0x8F, 0x8F, - 0x66, 0xA3, 0x2F, 0x2F, 0x66, 0x98, 0x98, 0x66, - 0x2F, 0x2F, 0xA3, 0x98, 0x8F, 0x98, 0x66, 0x2F, - 0xB2, 0xB2, 0xB2, 0xA3, 0x66, 0x66, 0x66, 0xA3, - 0x2F, 0x66, 0x98, 0x8F, 0x8F, 0x98, 0x66, 0x2F, - 0x2F, 0xA3, 0x66, 0x98, 0x98, 0xA3, 0x2F, 0xB2, - 0xA3, 0x8F, 0x98, 0xA3, 0xB2, 0x51, 0x89, 0x89, - 0xB2, 0xA3, 0x66, 0x98, 0x66, 0x98, 0x20, 0xA6, - 0x44, 0x39, 0xE6, 0x98, 0x20, 0x20, 0x20, 0x9C, - 0x74, 0xD6, 0x7E, 0xD6, 0x39, 0x8F, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x2E, 0x98, 0x8F, 0x8F, 0x98, - 0x66, 0x2F, 0x2F, 0xA3, 0x66, 0x98, 0x98, 0xA3, - 0x2F, 0xB2, 0x66, 0x98, 0x8F, 0xA3, 0xB2, 0x51, - 0x89, 0x89, 0xB2, 0xA3, 0x66, 0x98, 0x66, 0x66, - 0x2F, 0x66, 0x8F, 0xA0, 0x8F, 0x98, 0xA3, 0xB2, - 0x2F, 0x66, 0x66, 0x66, 0xA3, 0x2F, 0x2F, 0x2F, - 0x66, 0x98, 0xA3, 0xB2, 0x89, 0x44, 0x89, 0x51, - 0x2F, 0x66, 0x98, 0x98, 0xA3, 0x66, 0x20, 0x2F, - 0x2F, 0xAD, 0x89, 0xD6, 0x3A, 0x20, 0x20, 0x55, - 0x6B, 0x51, 0x6D, 0x4C, 0xD8, 0xD6, 0x2E, 0x20, - 0x20, 0x20, 0x20, 0x54, 0x8F, 0xA0, 0x8F, 0x98, - 0xA3, 0xB2, 0x2F, 0x66, 0x66, 0x66, 0xA3, 0x2F, - 0xB2, 0x2F, 0x66, 0x66, 0xA3, 0xB2, 0x89, 0x44, - 0x89, 0x51, 0x2F, 0x66, 0x98, 0x98, 0xA3, 0xA3, - 0xA3, 0x66, 0x8F, 0xA0, 0x8F, 0x66, 0x2F, 0xB2, - 0xA3, 0x66, 0x98, 0x66, 0xA3, 0x2F, 0x2F, 0xA3, - 0xA3, 0x2F, 0xB2, 0x89, 0xD8, 0xD8, 0x51, 0x66, - 0x8F, 0xA0, 0xA0, 0x8F, 0x98, 0xA3, 0x20, 0x44, - 0xA7, 0xCE, 0xA6, 0x4D, 0xCE, 0x6D, 0xA7, 0xA0, - 0x6B, 0xA7, 0x20, 0x92, 0xAD, 0x6B, 0x4C, 0x20, - 0x20, 0x20, 0x20, 0x54, 0x98, 0xA0, 0x8F, 0x66, - 0x2F, 0xB2, 0xA3, 0x66, 0x98, 0x66, 0xA3, 0x2F, - 0x2F, 0xA3, 0xA3, 0xA3, 0xB2, 0x89, 0xD8, 0xD8, - 0x51, 0x66, 0x8F, 0xA0, 0xA0, 0x8F, 0x98, 0x66, - 0x66, 0x66, 0x8F, 0x55, 0x8F, 0xA3, 0xB2, 0xB2, - 0xA3, 0x66, 0x66, 0xA3, 0x2F, 0xA3, 0xA3, 0xA3, - 0xA3, 0xB2, 0x89, 0x44, 0x44, 0x51, 0x66, 0xA0, - 0x55, 0xA5, 0x55, 0x8F, 0x66, 0xA3, 0x20, 0x44, - 0x6D, 0x54, 0xA7, 0x74, 0x2E, 0x4B, 0xBF, 0x9C, - 0x7E, 0xDA, 0x20, 0x54, 0x2E, 0x6B, 0x2A, 0x20, - 0x20, 0x20, 0x20, 0x3A, 0x8F, 0x55, 0x8F, 0xA3, - 0xB2, 0xB2, 0xA3, 0x66, 0x66, 0xA3, 0xA3, 0x2F, - 0xA3, 0xA3, 0xA3, 0xB2, 0x89, 0x44, 0x44, 0x51, - 0x66, 0xA0, 0xA5, 0xA5, 0x55, 0x8F, 0x66, 0x66, - 0xA0, 0xA0, 0xA0, 0xA0, 0x8F, 0xA3, 0x2F, 0xB2, - 0x66, 0x98, 0xA3, 0x2F, 0x2F, 0xB2, 0x2F, 0x2F, - 0xB2, 0x51, 0x89, 0x89, 0xB2, 0x98, 0xA0, 0x2A, - 0xA5, 0x55, 0x98, 0x66, 0xA3, 0xB2, 0x20, 0x2F, - 0x4C, 0x20, 0x4B, 0xBB, 0xCF, 0x6F, 0x27, 0x36, - 0x93, 0xCE, 0x20, 0x20, 0xA6, 0x3D, 0x4C, 0x20, - 0x20, 0x20, 0x20, 0xDA, 0xA0, 0xA0, 0x8F, 0xA3, - 0x2F, 0xB2, 0x66, 0x98, 0xA3, 0x2F, 0xB2, 0x2F, - 0x2F, 0x2F, 0xB2, 0x51, 0x89, 0x89, 0xB2, 0x98, - 0xA0, 0x2A, 0xA5, 0xA0, 0x8F, 0x66, 0xA3, 0xA3, - 0xA0, 0x8F, 0x8F, 0xA0, 0x8F, 0xA3, 0xB2, 0x2F, - 0x66, 0x98, 0x2F, 0xB2, 0xB2, 0xB2, 0xB2, 0x2F, - 0xB2, 0x89, 0x44, 0x51, 0x66, 0x55, 0xAD, 0x2A, - 0x55, 0x8F, 0x66, 0xA3, 0x2F, 0xB2, 0x20, 0x2A, - 0xE6, 0x95, 0xE5, 0x5A, 0x52, 0x52, 0x3F, 0x27, - 0x22, 0xC7, 0x9D, 0x60, 0xA2, 0xA2, 0x3A, 0x20, - 0x20, 0x20, 0x20, 0x54, 0x66, 0xA0, 0x8F, 0xA3, - 0xB2, 0x2F, 0x66, 0x98, 0x2F, 0xB2, 0xB2, 0xB2, - 0xB2, 0x2F, 0xB2, 0x89, 0x44, 0x51, 0x66, 0x55, - 0x2A, 0x2A, 0xA5, 0x8F, 0x66, 0xA3, 0x2F, 0x2F, - 0xA3, 0xA3, 0x66, 0x98, 0x98, 0x2F, 0xB2, 0xB2, - 0xA3, 0xA3, 0x2F, 0x51, 0x51, 0x51, 0x2F, 0x2F, - 0x51, 0x89, 0x89, 0x2F, 0x8F, 0x2A, 0x2A, 0xA5, - 0x8F, 0x66, 0xA3, 0xB2, 0x2F, 0x51, 0x20, 0x6D, - 0x77, 0xF7, 0xEE, 0x30, 0xB0, 0x72, 0x72, 0x5B, - 0x82, 0xEA, 0x72, 0xB0, 0x90, 0x96, 0x71, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x2F, 0x98, 0x98, 0x2F, - 0xB2, 0xB2, 0x66, 0xA3, 0x2F, 0x51, 0x51, 0xB2, - 0xB2, 0x2F, 0x51, 0x89, 0x89, 0x2F, 0x8F, 0x2A, - 0xAD, 0xA5, 0x98, 0x66, 0xA3, 0xB2, 0x2F, 0xB2, - 0xD8, 0xB2, 0xA3, 0x98, 0x98, 0x2F, 0xB2, 0xB2, - 0x66, 0xA3, 0xB2, 0x51, 0x51, 0xB2, 0x2F, 0xA3, - 0x51, 0x89, 0x89, 0xA3, 0xA0, 0x2A, 0xA5, 0x8F, - 0x66, 0xA3, 0x2F, 0xB2, 0xB2, 0x51, 0x20, 0x69, - 0x64, 0xF9, 0x3F, 0x52, 0x52, 0x72, 0x29, 0x82, - 0x47, 0x47, 0x47, 0x8B, 0x72, 0xB7, 0x60, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x2F, 0x98, 0x98, 0x2F, - 0xB2, 0xB2, 0xA3, 0xA3, 0xB2, 0x89, 0x51, 0x2F, - 0x2F, 0xA3, 0x51, 0x89, 0x89, 0xA3, 0xA0, 0x2A, - 0xA5, 0x8F, 0x66, 0xA3, 0x2F, 0xB2, 0xB2, 0xB2, - 0xDD, 0xA3, 0x66, 0x98, 0x66, 0x2F, 0xB2, 0xB2, - 0xA3, 0xA3, 0xB2, 0x51, 0xB2, 0x2F, 0xA3, 0x2F, - 0xB2, 0x89, 0xB2, 0x66, 0xA0, 0xA5, 0x8F, 0x98, - 0x66, 0x66, 0xB2, 0x51, 0x51, 0x51, 0x81, 0xFA, - 0x62, 0xEE, 0x30, 0x52, 0x22, 0x72, 0x82, 0x82, - 0x47, 0x47, 0xEA, 0x3F, 0x37, 0x6F, 0x26, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x2A, 0x98, 0x66, 0x2F, - 0x51, 0xB2, 0xA3, 0x66, 0xB2, 0x51, 0x51, 0xB2, - 0xA3, 0x2F, 0xB2, 0x89, 0xB2, 0x66, 0x55, 0x55, - 0x8F, 0x98, 0x66, 0xA3, 0xB2, 0x51, 0x51, 0xB2, - 0x74, 0xA0, 0x8F, 0x98, 0x66, 0xB2, 0xB2, 0xB2, - 0xA3, 0xA3, 0x2F, 0x51, 0x51, 0x2F, 0xA3, 0x2F, - 0xB2, 0x51, 0xA3, 0x98, 0xA0, 0x55, 0xA0, 0xA0, - 0x8F, 0x66, 0x2F, 0x51, 0xB2, 0x51, 0x54, 0xA9, - 0x62, 0xEF, 0x52, 0x22, 0x72, 0x29, 0xEA, 0xEA, - 0x29, 0x22, 0x37, 0x37, 0x8E, 0xCF, 0x49, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x6D, 0x2F, 0x66, 0x2F, - 0x51, 0xB2, 0xA3, 0x66, 0x2F, 0xB2, 0xB2, 0x2F, - 0xA3, 0x2F, 0xB2, 0x51, 0x2F, 0x98, 0xA0, 0x55, - 0xA0, 0xA0, 0x8F, 0x66, 0x2F, 0x51, 0xB2, 0xA3, - 0xA3, 0x2A, 0xA5, 0x98, 0xA3, 0x2F, 0xB2, 0x2F, - 0x66, 0x66, 0x2F, 0xB2, 0xB2, 0xB2, 0x2F, 0x2F, - 0xB2, 0x2F, 0xA3, 0x8F, 0xA0, 0xA0, 0xA0, 0xA0, - 0x8F, 0xA3, 0x51, 0x51, 0x2F, 0xB2, 0x54, 0xA8, - 0x65, 0x5C, 0x52, 0x22, 0x29, 0x29, 0x29, 0xB0, - 0x62, 0x56, 0xF9, 0x79, 0xF9, 0xBB, 0x4B, 0x20, - 0x6D, 0xA5, 0x2E, 0x20, 0x20, 0xA3, 0xA3, 0x2F, - 0xB2, 0x2F, 0xA3, 0x66, 0x2F, 0xB2, 0xB2, 0xB2, - 0x2F, 0x2F, 0xB2, 0x2F, 0x66, 0x8F, 0xA0, 0xA0, - 0x55, 0xA0, 0x8F, 0xA3, 0x51, 0x51, 0x2F, 0xA3, - 0xA0, 0x2A, 0x55, 0x66, 0xA3, 0x2F, 0xB2, 0xB2, - 0xA3, 0x66, 0xA3, 0xB2, 0xB2, 0xB2, 0xA3, 0x66, - 0xA3, 0xA3, 0x66, 0x8F, 0x8F, 0x8F, 0xA0, 0x98, - 0xA3, 0x51, 0x89, 0x89, 0xA3, 0x2F, 0x20, 0x54, - 0xDF, 0xFA, 0x40, 0x37, 0xD4, 0x43, 0x56, 0x64, - 0x76, 0xF9, 0x78, 0x41, 0x5E, 0x5E, 0x4C, 0x20, - 0x20, 0xAD, 0x8F, 0x9C, 0x20, 0xA5, 0xA3, 0x2F, - 0x2F, 0x2F, 0xA3, 0x66, 0x2F, 0xB2, 0xB2, 0xB2, - 0xA3, 0x66, 0xA3, 0x2F, 0x66, 0x8F, 0x8F, 0x8F, - 0x8F, 0x8F, 0xA3, 0x51, 0x89, 0x51, 0xA3, 0x66, - 0xA0, 0xA0, 0x8F, 0xA3, 0x2F, 0x2F, 0x2F, 0xB2, - 0x2F, 0xA3, 0x2F, 0xB2, 0x51, 0xB2, 0x2F, 0x66, - 0xA3, 0xA3, 0x66, 0x66, 0x66, 0x66, 0x66, 0xA3, - 0xB2, 0x89, 0xD8, 0x51, 0x66, 0x51, 0x20, 0x6D, - 0x51, 0x77, 0x9F, 0xF7, 0xEE, 0x8E, 0xF9, 0xF0, - 0x24, 0xF7, 0x77, 0x5E, 0x74, 0xD8, 0x98, 0x20, - 0x20, 0x2E, 0x55, 0x92, 0x20, 0x54, 0x51, 0x2F, - 0x2F, 0xB2, 0xB2, 0xA3, 0x2F, 0x51, 0x51, 0xB2, - 0xA3, 0xA3, 0x66, 0xA3, 0x66, 0x66, 0x66, 0x66, - 0x66, 0xA3, 0xB2, 0x89, 0xD8, 0x51, 0xA3, 0x98, - 0x98, 0x66, 0x66, 0xA3, 0x2F, 0x2F, 0x2F, 0xB2, - 0xB2, 0x2F, 0x2F, 0xB2, 0xB2, 0x2F, 0x2F, 0x66, - 0x66, 0xA3, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, 0xB2, - 0x89, 0xD8, 0x89, 0xB2, 0x66, 0x66, 0x20, 0x6D, - 0x89, 0xC2, 0xA4, 0x96, 0xC6, 0x64, 0x50, 0x40, - 0xF4, 0x97, 0x89, 0x74, 0x7E, 0x6B, 0x39, 0xA7, - 0x20, 0x20, 0x3A, 0x54, 0x20, 0x20, 0xA7, 0x51, - 0x2F, 0xB2, 0xB2, 0xA3, 0xA3, 0xB2, 0xB2, 0xB2, - 0xA3, 0xA3, 0x66, 0xA3, 0xA3, 0xA3, 0x2F, 0x2F, - 0x2F, 0xB2, 0x89, 0xD8, 0x44, 0x2F, 0x66, 0x66, - 0x2F, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, 0x2F, 0xB2, - 0x2F, 0xA3, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, 0xA3, - 0x66, 0xA3, 0x2F, 0xB2, 0xB2, 0xB2, 0x51, 0x51, - 0x89, 0x89, 0xB2, 0x66, 0x2F, 0x6D, 0x20, 0xCE, - 0x39, 0x74, 0x89, 0x5E, 0xBD, 0x87, 0xC8, 0xD1, - 0x89, 0x44, 0x3C, 0x4D, 0x6B, 0x6B, 0x6B, 0x2F, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xA3, - 0x2F, 0x2F, 0x2F, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, - 0x2F, 0xA3, 0x66, 0x66, 0x2F, 0xB2, 0xB2, 0xB2, - 0x51, 0x51, 0x89, 0x89, 0xB2, 0xA3, 0x98, 0x66, - 0xA3, 0x66, 0x66, 0xA3, 0xA3, 0xA3, 0xA3, 0x2F, - 0x2F, 0xA3, 0xA3, 0xA3, 0x2F, 0xA3, 0x2F, 0xA3, - 0x66, 0x66, 0x2F, 0x2F, 0xB2, 0xB2, 0xB2, 0xB2, - 0xB2, 0x2F, 0x66, 0x66, 0x2A, 0x20, 0x54, 0x44, - 0x6B, 0x39, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0xD8, 0x39, 0x4D, 0x6B, 0x6B, 0x6B, 0x6B, 0x4D, - 0x9C, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6D, - 0x51, 0x2F, 0x2F, 0x2F, 0xA3, 0xA3, 0xA3, 0x2F, - 0xA3, 0xA3, 0x66, 0xA3, 0x2F, 0xB2, 0xB2, 0xB2, - 0xB2, 0xB2, 0xB2, 0x2F, 0x66, 0x98, 0x98, 0x66, - 0x98, 0x98, 0x66, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, - 0x2F, 0x2F, 0xA3, 0xA3, 0x66, 0xA3, 0xA3, 0x66, - 0x98, 0x66, 0x66, 0x2F, 0xA3, 0xA3, 0xA3, 0xA3, - 0x66, 0x98, 0x98, 0x98, 0x3A, 0x54, 0x2A, 0x6B, - 0x6B, 0x6B, 0x83, 0x44, 0x89, 0x89, 0x44, 0x3C, - 0xD6, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, - 0xB2, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0xAD, 0x2F, 0x2F, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, - 0xA3, 0x66, 0x66, 0x98, 0x66, 0xA3, 0xA3, 0xA3, - 0xA3, 0xA3, 0x66, 0x98, 0x8F, 0x8F, 0x8F, 0x98, - 0x8F, 0x98, 0x98, 0x66, 0xA3, 0xA3, 0xA3, 0xA3, - 0x2F, 0xA3, 0xA3, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x8F, 0x8F, 0x8F, 0x98, 0x98, 0x98, 0x8F, 0xA0, - 0xA0, 0xA0, 0xA3, 0xDA, 0x20, 0x3A, 0x39, 0x6B, - 0x6B, 0x6B, 0x4D, 0xA2, 0x74, 0x3C, 0x7E, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, - 0x6B, 0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x2F, 0x2F, 0xA3, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x98, 0x8F, 0x8F, 0x98, 0x98, 0x98, 0x98, - 0x8F, 0xA0, 0xA0, 0xA0, 0x8F, 0x8F, 0x8F, 0xA0, - 0x8F, 0x66, 0x66, 0xA3, 0x66, 0xA3, 0xA3, 0x2F, - 0x2F, 0x2F, 0xA3, 0xA3, 0x66, 0x66, 0x66, 0x98, - 0x98, 0xA0, 0x98, 0x66, 0x66, 0x98, 0x8F, 0xA0, - 0xA0, 0xA3, 0x2E, 0x20, 0x20, 0x8F, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x3D, 0x6B, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, - 0x6B, 0x55, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x3A, 0x51, 0x2F, 0xA3, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x98, 0x8F, 0x8F, 0x98, 0x66, 0x98, - 0x8F, 0xA0, 0xA0, 0x8F, 0x8F, 0x8F, 0x8F, 0xA0, - 0x66, 0x2F, 0x2F, 0x2F, 0x2F, 0xA3, 0xA3, 0xA3, - 0x2F, 0x2F, 0xA3, 0xA3, 0x66, 0xA3, 0x66, 0x66, - 0x66, 0x98, 0xA3, 0x2F, 0x2F, 0xA3, 0x66, 0x8F, - 0x66, 0xA6, 0x20, 0x20, 0x6D, 0x39, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, - 0x6B, 0xB2, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x2E, 0x89, 0xA3, 0xA3, 0x66, 0x66, - 0x66, 0x66, 0x98, 0x98, 0xA3, 0x2F, 0x2F, 0xA3, - 0x66, 0x8F, 0x98, 0x98, 0x66, 0x98, 0x98, 0x8F, - 0x2F, 0x51, 0xB2, 0xB2, 0x2F, 0xA3, 0xA3, 0xA3, - 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, - 0xA3, 0xA3, 0x2F, 0xB2, 0x2F, 0xA3, 0x66, 0x2F, - 0x55, 0x20, 0x20, 0x20, 0x4C, 0x39, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, - 0x4D, 0x7E, 0x54, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x2E, 0x51, 0xA3, 0xA3, 0xA3, - 0xA3, 0xA3, 0xA3, 0x2F, 0xB2, 0xB2, 0x2F, 0xA3, - 0x66, 0x66, 0xA3, 0xA3, 0xA3, 0xA3, 0x66, 0x66, - 0xB2, 0x51, 0x51, 0xB2, 0xB2, 0xA3, 0x2F, 0xA3, - 0x2F, 0x2F, 0x2F, 0xA3, 0xA3, 0xA3, 0xA3, 0x66, - 0xA3, 0x2F, 0xB2, 0x2F, 0xA3, 0x98, 0x98, 0xA0, - 0x20, 0x20, 0x20, 0x20, 0xA5, 0x83, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x4D, 0x7E, 0x4D, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x4D, 0x4D, 0xD6, 0x7E, 0xDD, - 0x3C, 0x39, 0xA7, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x92, 0xB2, 0xA3, 0xA3, - 0xA3, 0x66, 0xA3, 0x2F, 0x2F, 0x2F, 0xA3, 0x98, - 0x98, 0x66, 0xA3, 0xA3, 0x66, 0x66, 0x66, 0xA3, - 0x89, 0x89, 0x51, 0xB2, 0xB2, 0x2F, 0x2F, 0x2F, - 0x2F, 0xA3, 0xA3, 0x2F, 0xA3, 0xA3, 0xA3, 0xA3, - 0xA3, 0xA3, 0xA3, 0x66, 0x8F, 0x8F, 0x2F, 0xDA, - 0x20, 0x20, 0x20, 0xDA, 0xA0, 0x51, 0x3C, 0x7E, - 0x6B, 0x6B, 0x6B, 0x4D, 0x7E, 0x6B, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x7E, 0x3C, 0xD8, 0x44, 0xD8, - 0x44, 0x83, 0x89, 0xDA, 0x20, 0x3A, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0xB2, 0xA3, 0xA3, - 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0x66, 0x8F, 0x8F, - 0x98, 0x98, 0x98, 0x98, 0x66, 0xA3, 0xA3, 0x2F, - 0x3C, 0x89, 0x89, 0x51, 0xB2, 0xB2, 0x2F, 0x2F, - 0x2F, 0x2F, 0xA3, 0xA3, 0x66, 0x66, 0x66, 0xA3, - 0xA3, 0xA3, 0xA3, 0x66, 0x98, 0x98, 0xA3, 0x20, - 0x20, 0x20, 0x20, 0x6D, 0x2F, 0xE6, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x3D, 0xD6, 0x3D, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x4D, 0x7E, 0xA2, - 0x74, 0x44, 0xA2, 0xA3, 0x20, 0x3A, 0x2E, 0x6D, - 0x20, 0x20, 0x20, 0x20, 0x20, 0xA6, 0xA3, 0x66, - 0x66, 0x66, 0xA3, 0x2F, 0xA3, 0x66, 0x66, 0x98, - 0x66, 0x66, 0x98, 0x98, 0x98, 0x66, 0xA3, 0xA3, - 0x83, 0xB2, 0x2F, 0x2F, 0xB2, 0xB2, 0xB2, 0x2F, - 0x2F, 0x2F, 0xA3, 0x66, 0x66, 0x98, 0x98, 0x66, - 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0x66, 0xA6, 0x20, - 0x3A, 0x3A, 0x54, 0x55, 0x7E, 0x6B, 0x6B, 0x6B, - 0x4D, 0x3D, 0x6B, 0x6B, 0x6B, 0x57, 0x33, 0xEB, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, - 0x4D, 0xA2, 0x74, 0x39, 0x92, 0x20, 0x20, 0x6D, - 0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2F, 0x98, - 0x98, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0xA3, 0x66, 0xA3, - 0x89, 0xA3, 0x66, 0x66, 0xA3, 0xA3, 0x2F, 0x2F, - 0xA3, 0x2F, 0xA3, 0xA3, 0x66, 0x66, 0x66, 0xA3, - 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xB2, 0x3A, 0x20, - 0xA7, 0x20, 0x3A, 0x39, 0x6B, 0x6B, 0x6B, 0x6B, - 0xB5, 0xCB, 0x6B, 0x6B, 0x3D, 0x8A, 0x42, 0x3D, - 0x6B, 0x6B, 0x6B, 0x84, 0x6C, 0x4D, 0x6B, 0x6B, - 0x6B, 0x6B, 0x7E, 0x83, 0x51, 0x20, 0x20, 0x20, - 0x6D, 0x3A, 0x20, 0x20, 0x20, 0x20, 0xAD, 0x66, - 0x66, 0x66, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, - 0xA3, 0xA3, 0xA3, 0xA3, 0x66, 0xA3, 0xA3, 0xA3, - 0xB2, 0x98, 0x66, 0x66, 0x98, 0x66, 0x66, 0xA3, - 0xA3, 0xA3, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, 0x2F, - 0xA3, 0x2F, 0xA3, 0xA3, 0xA3, 0x2F, 0x20, 0x6D, - 0x3A, 0x20, 0x98, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, - 0xAA, 0x33, 0x6B, 0x6B, 0x3D, 0xF5, 0x7B, 0x3D, - 0x6B, 0x6B, 0x4F, 0x4A, 0x58, 0x3D, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x7E, 0x7E, 0x9C, 0x54, 0xA7, - 0x2E, 0xA7, 0x20, 0x20, 0x20, 0x20, 0x54, 0x51, - 0x2F, 0x2F, 0xA3, 0x2F, 0xA3, 0xA3, 0xA3, 0xA3, - 0x2F, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0x2F, - 0xB2, 0x66, 0x66, 0x66, 0x66, 0xA3, 0x66, 0xA3, - 0x66, 0x66, 0xA3, 0x2F, 0x2F, 0xB2, 0x2F, 0xB2, - 0x2F, 0x2F, 0x2F, 0xA3, 0x2F, 0xA6, 0x20, 0xCE, - 0x20, 0x6D, 0x4D, 0x6B, 0xD6, 0x7E, 0x6B, 0x6B, - 0x6E, 0x9A, 0x57, 0x6B, 0x2D, 0x7B, 0x7B, 0x3D, - 0x6B, 0x84, 0xF5, 0x7B, 0x84, 0x6B, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x98, 0x3A, 0x9C, - 0xCE, 0x3A, 0x2E, 0x20, 0x20, 0x20, 0x20, 0x98, - 0xB2, 0xB2, 0x2F, 0x2F, 0x2F, 0xA3, 0x2F, 0x2F, - 0x2F, 0xA3, 0xA3, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, - 0x89, 0xA3, 0x66, 0x66, 0xA3, 0x2F, 0x2F, 0xA3, - 0x66, 0x66, 0xA3, 0xA3, 0x2F, 0x2F, 0xB2, 0xB2, - 0xB2, 0x2F, 0x2F, 0x2F, 0x89, 0x54, 0x6D, 0x3A, - 0x20, 0x98, 0x6B, 0x6B, 0xE0, 0xB4, 0x6B, 0x6B, - 0x2D, 0x9E, 0x4A, 0x3D, 0x84, 0xF5, 0xF5, 0x84, - 0x6B, 0x6E, 0x59, 0x6C, 0x6B, 0x6B, 0x6B, 0x6B, - 0x3D, 0x6B, 0x6B, 0x6B, 0x6B, 0xDD, 0xDA, 0x6D, - 0x54, 0x20, 0xCE, 0x20, 0x20, 0x20, 0x20, 0xA7, - 0x51, 0xB2, 0xB2, 0xB2, 0x2F, 0xB2, 0x2F, 0x2F, - 0x2F, 0x66, 0x66, 0xA3, 0xA3, 0xA3, 0xA3, 0x66, - 0x89, 0xA3, 0xA3, 0xA3, 0x2F, 0xB2, 0xB2, 0x2F, - 0x66, 0x66, 0xA3, 0xA3, 0x2F, 0xA3, 0xA3, 0x2F, - 0xB2, 0x2F, 0x2F, 0xA3, 0x98, 0x20, 0xA7, 0x20, - 0x3A, 0x7E, 0x6B, 0x6B, 0x7F, 0xDE, 0xF6, 0x3D, - 0x6B, 0xDB, 0x8A, 0xDB, 0xE9, 0xF3, 0xF3, 0xDB, - 0x68, 0xF3, 0x73, 0x7F, 0x6B, 0x6B, 0x57, 0x58, - 0xDC, 0x2D, 0x6B, 0x6B, 0x6B, 0x6B, 0x3A, 0x20, - 0x20, 0x20, 0x6D, 0x54, 0x20, 0x20, 0x20, 0x20, - 0x51, 0x2F, 0x2F, 0x2F, 0xA3, 0xA3, 0xA3, 0x66, - 0xA3, 0x66, 0x98, 0x98, 0x66, 0x98, 0x98, 0x66, - 0x2F, 0x66, 0x66, 0xA3, 0x2F, 0xB2, 0x2F, 0xA3, - 0xA3, 0xA3, 0xA3, 0xA3, 0x66, 0xA3, 0xA3, 0xA3, - 0x66, 0x98, 0x8F, 0x98, 0xCE, 0xDA, 0x2E, 0x20, - 0x2A, 0x6B, 0x6B, 0x6B, 0x6B, 0x2C, 0x34, 0xCB, - 0xEB, 0x6C, 0x31, 0x59, 0x82, 0x82, 0x8B, 0x82, - 0xF3, 0x73, 0xE9, 0x6B, 0x3D, 0x6E, 0xF3, 0x4A, - 0x4F, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x92, 0x20, - 0x20, 0x20, 0x6D, 0x6D, 0x20, 0x20, 0x20, 0x20, - 0xA3, 0xA3, 0x66, 0x98, 0x98, 0x8F, 0x8F, 0x98, - 0x98, 0x98, 0x98, 0x66, 0x98, 0x66, 0x66, 0xA3, - 0xA3, 0x66, 0x66, 0x66, 0xA3, 0x2F, 0x2F, 0xA3, - 0xA3, 0xA3, 0x66, 0x66, 0xA3, 0xA3, 0xA3, 0x66, - 0x8F, 0x55, 0xA5, 0x98, 0x20, 0x2E, 0x54, 0x54, - 0x89, 0x6B, 0x6B, 0x6B, 0x6B, 0x84, 0xE3, 0x4A, - 0x58, 0x42, 0x5B, 0x8B, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x59, 0x58, 0x57, 0x57, 0x59, 0x7B, 0x84, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0xAD, 0x20, - 0x20, 0x20, 0x3A, 0x3A, 0x20, 0x20, 0x20, 0x20, - 0x2A, 0x66, 0x8F, 0x55, 0xA5, 0xA5, 0xA0, 0x8F, - 0x66, 0xA3, 0xA3, 0x66, 0x98, 0x66, 0x66, 0x2F, - 0x2F, 0x2F, 0x2F, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, - 0xA3, 0x2F, 0xA3, 0xA3, 0x66, 0xA3, 0xA3, 0x66, - 0x8F, 0xA5, 0x8F, 0x2E, 0x20, 0x2E, 0x20, 0x3A, - 0x4D, 0x6B, 0xE6, 0x84, 0x3D, 0x6B, 0xEB, 0x4A, - 0xC9, 0x8B, 0x8B, 0x31, 0x59, 0x82, 0x59, 0x59, - 0x5B, 0x82, 0x59, 0x73, 0x7B, 0xDC, 0x57, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x55, 0x20, - 0x20, 0x20, 0x6D, 0xDA, 0x20, 0x20, 0x20, 0x20, - 0x9C, 0x66, 0x8F, 0xA5, 0xA5, 0x55, 0x8F, 0x66, - 0x2F, 0xB2, 0x2F, 0x66, 0x98, 0x98, 0x2F, 0x51, - 0x89, 0xB2, 0x2F, 0xA3, 0xA3, 0xB2, 0xB2, 0xB2, - 0x2F, 0x2F, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0x66, - 0x8F, 0xA5, 0x8F, 0x20, 0x20, 0xA7, 0x20, 0xA6, - 0x6B, 0x6B, 0xE4, 0x48, 0x2C, 0xDB, 0x4F, 0x9E, - 0xD0, 0xD0, 0x8B, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x59, 0x82, 0x82, 0x73, 0x7B, 0x68, 0x6B, 0x3D, - 0x68, 0x68, 0x84, 0x3D, 0x6B, 0x6B, 0xA0, 0x20, - 0x20, 0x20, 0x6D, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x6D, 0x2F, 0xA0, 0xA5, 0x55, 0x98, 0x66, 0xA3, - 0xB2, 0x89, 0xB2, 0x98, 0x8F, 0x98, 0x2F, 0x51, - 0x74, 0xB2, 0xA3, 0xA3, 0x2F, 0x2F, 0xB2, 0x2F, - 0xA3, 0xA3, 0xA3, 0x66, 0x66, 0xA3, 0x2F, 0xA3, - 0x98, 0xA3, 0x6D, 0x20, 0x20, 0xCE, 0x20, 0x2A, - 0x6B, 0x6B, 0xEB, 0x2C, 0xE1, 0xF1, 0x7C, 0xD0, - 0x8B, 0x8B, 0x82, 0x82, 0x82, 0x82, 0x82, 0x59, - 0x82, 0x82, 0x42, 0x82, 0x31, 0x57, 0x4F, 0x7B, - 0x7B, 0xF5, 0xF6, 0xDB, 0x6B, 0x6B, 0x98, 0x20, - 0x20, 0x20, 0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x51, 0x66, 0xA0, 0xA0, 0x66, 0x2F, 0xB2, - 0xB2, 0x51, 0x2F, 0xA0, 0x55, 0xA3, 0x51, 0x89, - 0x44, 0xA3, 0x98, 0x98, 0x2F, 0x2F, 0x2F, 0xA3, - 0xA3, 0x66, 0x98, 0x98, 0x98, 0xA3, 0x2F, 0x2F, - 0x98, 0x8F, 0x20, 0x20, 0x3A, 0xA6, 0x20, 0xA0, - 0x6B, 0x6B, 0x6B, 0x6B, 0x7F, 0x7F, 0xC3, 0xC9, - 0xD0, 0xD0, 0x29, 0x59, 0x82, 0x73, 0x82, 0x73, - 0x59, 0x59, 0x59, 0x59, 0x59, 0x58, 0xAF, 0xF5, - 0x8A, 0x68, 0xEB, 0x6B, 0x6B, 0x6B, 0x98, 0x20, - 0x20, 0x20, 0x6D, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x51, 0x98, 0x55, 0xA0, 0xA3, 0xB2, 0x51, - 0x51, 0x2F, 0x98, 0x55, 0x8F, 0xB2, 0x89, 0x44, - 0xA3, 0x55, 0x55, 0x98, 0xA3, 0xB2, 0x2F, 0xA3, - 0x66, 0x66, 0x98, 0x8F, 0x66, 0xA3, 0x66, 0x98, - 0x55, 0x4C, 0x20, 0x20, 0xDA, 0xAD, 0x20, 0x98, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x3D, 0x9A, 0xD0, - 0xF2, 0x8B, 0x8B, 0x8B, 0x73, 0x82, 0x5B, 0x82, - 0x82, 0x59, 0x59, 0x73, 0x73, 0x58, 0x3D, 0x3D, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x66, 0x20, - 0x20, 0x3A, 0x3A, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x2F, 0x55, 0xA5, 0x8F, 0xA3, 0x51, 0x51, - 0xB2, 0xA3, 0x66, 0x66, 0xA3, 0xB2, 0x89, 0x51, - 0x98, 0xA5, 0x55, 0x8F, 0x2F, 0xB2, 0xB2, 0xA3, - 0x66, 0x66, 0x98, 0x98, 0x98, 0x66, 0x66, 0x8F, - 0x8F, 0x92, 0x20, 0x20, 0x20, 0x6D, 0x6D, 0xA3, - 0x6B, 0x6B, 0xEB, 0x7F, 0x4F, 0xDB, 0xD2, 0xC9, - 0xC9, 0xD0, 0x8B, 0x8B, 0x73, 0x82, 0x59, 0x8B, - 0x59, 0x82, 0x59, 0x59, 0x73, 0xF5, 0xEB, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x55, 0x20, - 0x20, 0xA7, 0x54, 0xDA, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x98, 0xA0, 0x8F, 0xA3, 0xB2, 0x51, 0x51, - 0x51, 0x2F, 0xA3, 0xA3, 0xB2, 0xB2, 0x51, 0xB2, - 0xA0, 0xA5, 0x55, 0x66, 0x2F, 0x51, 0x2F, 0xA3, - 0x66, 0x66, 0x66, 0x98, 0x66, 0x66, 0x98, 0x98, - 0x98, 0x2A, 0x54, 0x95, 0x95, 0x71, 0x2E, 0x98, - 0x6B, 0x6B, 0x4D, 0x28, 0xDE, 0x88, 0xB7, 0x70, - 0xC9, 0xC9, 0xD0, 0xF2, 0x8B, 0x8B, 0x8B, 0x59, - 0x59, 0x59, 0x59, 0x5B, 0x59, 0xF3, 0x57, 0xE9, - 0xDB, 0x84, 0x6B, 0x6B, 0x6B, 0x6B, 0x4C, 0xDA, - 0x2E, 0xDA, 0x20, 0xDA, 0x2E, 0x2E, 0x6D, 0x20, - 0x4C, 0x98, 0x66, 0xA3, 0x2F, 0xB2, 0x51, 0x51, - 0xB2, 0xA3, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, 0x2F, - 0xA0, 0xA0, 0x8F, 0x2F, 0xB2, 0x89, 0xB2, 0xA3, - 0x66, 0x66, 0x98, 0x66, 0x66, 0x66, 0x66, 0xA3, - 0x2F, 0xD1, 0xE2, 0x52, 0x52, 0xF4, 0xBF, 0x9C, - 0x39, 0x6B, 0x6B, 0x6B, 0x7F, 0x4F, 0xE3, 0x6A, - 0xD0, 0xC9, 0xC9, 0xD0, 0xD0, 0x8B, 0x8B, 0x82, - 0x5B, 0x5B, 0x73, 0x8B, 0x59, 0x23, 0x6E, 0x31, - 0x59, 0x7B, 0xDB, 0x84, 0x68, 0x7F, 0xAE, 0x54, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x54, 0xA6, 0x3A, - 0xA0, 0xA3, 0xA3, 0x2F, 0x51, 0x51, 0x51, 0xB2, - 0x2F, 0xA3, 0x66, 0x66, 0xA3, 0xA3, 0xA3, 0xA3, - 0x8F, 0x8F, 0x66, 0x2F, 0x51, 0x51, 0xB2, 0xA3, - 0x66, 0x98, 0x98, 0x66, 0x66, 0xA3, 0x2F, 0x2F, - 0x3C, 0x88, 0x8D, 0x52, 0x52, 0x5D, 0xF7, 0xBF, - 0xCE, 0xA2, 0x6B, 0x6B, 0x6B, 0x6B, 0x7F, 0x85, - 0x70, 0xC9, 0xC9, 0xC9, 0xD0, 0xEA, 0x8B, 0x5B, - 0x82, 0xEA, 0x82, 0x82, 0x42, 0x57, 0x3D, 0x68, - 0x68, 0x57, 0x4A, 0x34, 0x22, 0xCC, 0x21, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0xDA, 0xA7, 0x6D, - 0xDF, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0x2F, 0x2F, - 0xA3, 0x66, 0x66, 0x66, 0xA3, 0xA3, 0x2F, 0x2F, - 0x66, 0x66, 0xA3, 0x2F, 0xB2, 0xB2, 0x2F, 0x66, - 0x8F, 0x8F, 0x8F, 0x98, 0xA3, 0xA3, 0x89, 0xD8, - 0x25, 0x5C, 0x3B, 0x5D, 0x52, 0x80, 0x70, 0x36, - 0x71, 0xA7, 0x44, 0x6B, 0x84, 0xCB, 0xAA, 0xF3, - 0xC9, 0xC9, 0xC9, 0xC9, 0xD0, 0x8B, 0x5B, 0x5B, - 0x5B, 0xEA, 0x82, 0x47, 0x7B, 0x68, 0x3D, 0x3D, - 0x6B, 0x3D, 0x6C, 0x2B, 0x80, 0x61, 0x96, 0x81, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3A, 0xDA, 0x63, - 0xAC, 0x6C, 0xB2, 0xB2, 0xB2, 0xB2, 0x2F, 0xA3, - 0xA3, 0x66, 0xA3, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, - 0x66, 0x98, 0x66, 0xA3, 0xB2, 0xB2, 0x2F, 0x66, - 0x8F, 0x8F, 0x2F, 0xD8, 0xE4, 0xCD, 0xAA, 0xB4, - 0x78, 0x2B, 0x3B, 0x70, 0x46, 0x5D, 0x5D, 0x52, - 0x9D, 0x81, 0x3A, 0xA3, 0xCD, 0x48, 0xBE, 0x4F, - 0xC3, 0xC9, 0xD0, 0xD0, 0xD0, 0xEA, 0x5B, 0x8B, - 0x5B, 0x82, 0x8B, 0x59, 0x4A, 0xF3, 0x33, 0x7F, - 0x3D, 0x6B, 0x4F, 0x6F, 0x5D, 0x52, 0x63, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x75, 0x85, - 0x72, 0xDC, 0xD8, 0x2F, 0xA3, 0x2F, 0xA3, 0xA3, - 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, - 0xA3, 0x98, 0x66, 0x2F, 0xB2, 0x51, 0xA3, 0x98, - 0xA0, 0xA3, 0x93, 0xCF, 0x79, 0x27, 0x5C, 0x79, - 0x2B, 0x30, 0x80, 0x80, 0x5D, 0x5D, 0x5D, 0x5D, - 0x3F, 0x69, 0x20, 0x20, 0x2A, 0xD6, 0x3D, 0x6B, - 0x84, 0xE3, 0x34, 0xB7, 0xC9, 0xD0, 0xD0, 0xF2, - 0xD0, 0x8B, 0x31, 0x68, 0x68, 0x6E, 0x31, 0x33, - 0x7F, 0x7E, 0xA1, 0x6F, 0x52, 0x8D, 0xE5, 0xBF, - 0x20, 0x20, 0x20, 0x20, 0x81, 0xA8, 0x78, 0x52, - 0x52, 0xD2, 0xD8, 0xA3, 0xA3, 0x2F, 0x2F, 0xA3, - 0xA3, 0x66, 0x98, 0x98, 0x98, 0x98, 0x98, 0x66, - 0x51, 0x66, 0x2F, 0x51, 0x51, 0xB2, 0xA3, 0xA0, - 0xA0, 0x44, 0x78, 0xEF, 0x52, 0x30, 0x30, 0x30, - 0x3B, 0x70, 0x5D, 0x5D, 0x5D, 0x80, 0x5D, 0x5D, - 0x46, 0xC1, 0x71, 0x20, 0x81, 0xB1, 0xDD, 0x3D, - 0xA1, 0xE7, 0xDB, 0xCA, 0xD2, 0x6A, 0x6A, 0x6A, - 0xF3, 0xE9, 0xDB, 0x8A, 0x84, 0x3D, 0x84, 0xDC, - 0x25, 0x44, 0xB5, 0xEE, 0x30, 0xEF, 0xF0, 0x32, - 0x69, 0x5F, 0x4B, 0xA8, 0x99, 0x56, 0x67, 0x30, - 0x30, 0x34, 0xB2, 0x2F, 0xA3, 0xA3, 0x66, 0x66, - 0x98, 0x8F, 0x98, 0x98, 0x66, 0x66, 0x66, 0x66, - 0x51, 0x2F, 0xB2, 0x51, 0x51, 0x2F, 0x66, 0xA0, - 0x8F, 0xE0, 0xF9, 0x8D, 0x52, 0x5D, 0x46, 0x5D, - 0x80, 0x5D, 0x80, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, - 0x52, 0x52, 0x60, 0x81, 0x20, 0x20, 0x6D, 0xD1, - 0x48, 0xE7, 0x6B, 0x33, 0xF6, 0x7F, 0x7F, 0xDB, - 0x84, 0x6B, 0x6C, 0x6A, 0xF3, 0xEB, 0x6B, 0x3D, - 0x4F, 0xD8, 0xCD, 0x79, 0x30, 0x67, 0xF9, 0x24, - 0xED, 0xD9, 0x8C, 0xED, 0x37, 0x2B, 0x3B, 0x5D, - 0x80, 0x85, 0x4E, 0x98, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0xA3, 0x2F, 0x2F, 0x2F, 0x2F, - 0x51, 0x2F, 0xB2, 0xB2, 0xB2, 0xA3, 0x8F, 0x8F, - 0x98, 0xE0, 0xF0, 0x67, 0x5D, 0x80, 0x80, 0x5D, - 0x5D, 0x5D, 0x5D, 0x5D, 0x80, 0x5D, 0x5D, 0x5D, - 0x5D, 0x70, 0x27, 0x4B, 0x20, 0x81, 0x71, 0x3A, - 0xB5, 0xEB, 0x3D, 0xF1, 0xE1, 0x84, 0x84, 0xF1, - 0xE3, 0x3D, 0x6B, 0x6C, 0x34, 0xE7, 0x6B, 0x6B, - 0xD6, 0x74, 0x5E, 0x78, 0x67, 0x30, 0xEE, 0x5C, - 0xF9, 0xF9, 0x45, 0x5C, 0x2B, 0x3B, 0x5D, 0x5D, - 0x5D, 0x5D, 0xF8, 0x44, 0x66, 0x66, 0x66, 0x66, - 0x2F, 0x2F, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, - 0xB2, 0x2F, 0xA3, 0xA3, 0xA3, 0x98, 0x8F, 0x98, - 0x66, 0x83, 0x76, 0x67, 0x30, 0x80, 0x5D, 0x80, - 0x5D, 0x5D, 0x80, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, - 0x80, 0x5D, 0x22, 0xFA, 0x20, 0x81, 0x20, 0x20, - 0xA5, 0x6B, 0x6B, 0xE8, 0xBE, 0x3D, 0x6B, 0x2C, - 0xE1, 0xEB, 0x6B, 0x3D, 0x3E, 0xA1, 0x6B, 0x6B, - 0x4D, 0x74, 0xE8, 0x62, 0x67, 0x30, 0x8D, 0x67, - 0xEE, 0xEE, 0xEE, 0x67, 0x30, 0x80, 0x5D, 0x5D, - 0x52, 0x5D, 0x85, 0xAC, 0x3E, 0xA3, 0x66, 0x66, - 0x2F, 0x51, 0x51, 0x51, 0x51, 0xB2, 0x2F, 0x2F, - 0x2F, 0xA3, 0xA3, 0x66, 0x98, 0x8F, 0x8F, 0x66, - 0x2F, 0x83, 0xBC, 0xEE, 0x5D, 0x5D, 0x5D, 0x5D, - 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x80, 0x5D, 0x5D, - 0x5D, 0x5D, 0x22, 0xB0, 0xAE, 0x81, 0x20, 0x20, - 0x4C, 0x3D, 0xEB, 0x39, 0x57, 0x6B, 0x6B, 0x3E, - 0x97, 0x3D, 0x6B, 0x3D, 0x6B, 0x6B, 0x6B, 0x6B, - 0x3D, 0x3C, 0xBA, 0x62, 0xEE, 0x5D, 0x5D, 0x30, - 0x30, 0x8D, 0x8D, 0x30, 0x52, 0x5D, 0x5D, 0x80, - 0x5D, 0x5D, 0x5D, 0x85, 0xB0, 0x6E, 0x2F, 0x66, - 0x2F, 0xB2, 0x51, 0xB2, 0x2F, 0x2F, 0xA3, 0xA3, - 0xB2, 0xA3, 0x66, 0x98, 0x98, 0x8F, 0x98, 0xA3, - 0x2F, 0x51, 0xDE, 0x8E, 0x30, 0x5D, 0x5D, 0x5D, - 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, - 0x52, 0x80, 0x5D, 0x22, 0x43, 0x4B, 0x20, 0x6D, - 0x44, 0x6B, 0x6B, 0x3D, 0x6B, 0x6B, 0x6B, 0x4D, - 0x3D, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x3D, 0x6B, - 0x4D, 0x2A, 0xAE, 0x76, 0xEE, 0x30, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x5D, 0x5D, 0x5D, 0x80, - 0x5D, 0x5D, 0x80, 0x80, 0x5D, 0x7A, 0xB6, 0x51, - 0xB2, 0xB2, 0xB2, 0xA3, 0x66, 0x66, 0x66, 0xA3, - 0x2F, 0x66, 0x98, 0x8F, 0xA0, 0x98, 0xA3, 0x2F, - 0x2F, 0x51, 0xAB, 0x8E, 0x5D, 0x5D, 0x5D, 0x5D, - 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x80, - 0x5D, 0x80, 0x5D, 0x52, 0x52, 0x94, 0x2F, 0x7E, - 0x6B, 0x3D, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x7E, - 0xAD, 0x54, 0xAE, 0x24, 0x2B, 0x3B, 0x5D, 0x52, - 0x5D, 0x5D, 0x5D, 0x5D, 0x80, 0x5D, 0x5D, 0x80, - 0x5D, 0x52, 0x52, 0x5D, 0x5D, 0x5D, 0xD2, 0x3E, - 0x89, 0x89, 0xB2, 0xA3, 0x66, 0x98, 0x66, 0x66, - 0x2F, 0x66, 0x8F, 0x8F, 0xA0, 0x98, 0xA3, 0xB2, - 0x2F, 0x51, 0xDE, 0x79, 0x5D, 0x80, 0x5D, 0x5D, - 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, - 0x5D, 0x5D, 0x80, 0x5D, 0x52, 0x6F, 0xA4, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x4D, 0xA2, 0xCE, - 0x20, 0x20, 0x95, 0x24, 0x67, 0x3B, 0x80, 0x80, - 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, - 0x80, 0x5D, 0x5D, 0x5D, 0x5D, 0x30, 0xB0, 0x86, - 0x89, 0x51, 0x2F, 0x66, 0x98, 0x98, 0xA3, 0xA3, - 0xA3, 0x66, 0x8F, 0xA0, 0x8F, 0x66, 0x2F, 0xB2, - 0x2F, 0x4E, 0x76, 0x2B, 0x30, 0x5D, 0x5D, 0x5D, - 0x80, 0x80, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, - 0x80, 0x5D, 0x5D, 0x5D, 0x46, 0x52, 0x21, 0x74, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x7E, 0x98, 0x3A, 0x20, - 0x20, 0x81, 0x60, 0xED, 0x2B, 0x52, 0x5D, 0x5D, - 0x80, 0x5D, 0x5D, 0x80, 0x5D, 0x5D, 0x5D, 0x80, - 0x22, 0x5D, 0x5D, 0x5D, 0x8D, 0x2B, 0x38, 0x39, - 0x51, 0x66, 0x8F, 0xA0, 0xA0, 0x8F, 0x98, 0x66, - 0x66, 0x66, 0x8F, 0x55, 0x8F, 0xA3, 0xB2, 0xB2, - 0xA3, 0xE8, 0xF9, 0x30, 0x3B, 0x80, 0x5D, 0x5D, - 0x5D, 0x80, 0x80, 0x5D, 0x5D, 0x5D, 0x80, 0x5D, - 0x5D, 0x5D, 0x5D, 0x5D, 0x52, 0x30, 0xD4, 0x99, - 0x51, 0x4D, 0x6B, 0x6B, 0x6B, 0x6B, 0x4D, 0x6B, - 0x6B, 0x6B, 0x7E, 0xA3, 0x2E, 0x20, 0x20, 0x20, - 0x20, 0x81, 0xC5, 0xED, 0x2B, 0x3B, 0x5D, 0x5D, - 0x5D, 0x5D, 0x5D, 0x5D, 0x80, 0x5D, 0x5D, 0x80, - 0x5D, 0x52, 0x52, 0x6F, 0xDE, 0x2C, 0x39, 0x51, - 0x66, 0xA0, 0xA5, 0xA5, 0x55, 0x8F, 0x66, 0x66, - 0xA0, 0xA0, 0xA0, 0xA0, 0x8F, 0xA3, 0x2F, 0x2F, - 0x51, 0xD5, 0x45, 0x8D, 0x3B, 0x5D, 0x80, 0x5D, - 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, - 0x80, 0x5D, 0x5D, 0x5D, 0x52, 0x67, 0x37, 0xA9, - 0x3A, 0xCE, 0xA0, 0x2F, 0x51, 0x51, 0xB2, 0xA3, - 0xA5, 0x9C, 0x54, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x54, 0x99, 0xED, 0x67, 0x30, 0x5D, 0x5D, - 0x5D, 0x80, 0x5D, 0x5D, 0x5D, 0x5D, 0x3B, 0x80, - 0x8D, 0x79, 0x48, 0x2C, 0x39, 0x44, 0xB2, 0x66, - 0xA0, 0x2A, 0xA5, 0xA0, 0x8F, 0x66, 0xA3, 0xA3, - 0xA0, 0x8F, 0x8F, 0xA0, 0x8F, 0xA3, 0xB2, 0xB2, - 0xD8, 0xBC, 0x45, 0xEE, 0x67, 0x8D, 0x30, 0x30, - 0x52, 0x52, 0x80, 0x5D, 0x5D, 0x5D, 0x5D, 0x80, - 0x5D, 0x5D, 0x5D, 0x80, 0x3B, 0x67, 0xF9, 0x32, - 0x69, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0xBF, 0xEC, 0xED, 0x2B, 0x30, 0x5D, 0x5D, - 0x80, 0x5D, 0x5D, 0x5D, 0x52, 0x30, 0x67, 0x2B, - 0xCF, 0xAA, 0xD8, 0x89, 0x89, 0x51, 0x66, 0x55, - 0x2A, 0x2A, 0xA5, 0x8F, 0x66, 0xA3, 0x2F, 0x2F, - 0xA3, 0xA3, 0x66, 0x98, 0x98, 0x2F, 0xB2, 0x2F, - 0xD1, 0x28, 0x56, 0xED, 0x62, 0x37, 0x5C, 0x79, - 0x8E, 0x2B, 0x2B, 0x30, 0x30, 0x30, 0x5D, 0x5D, - 0x5D, 0x5D, 0x5D, 0x80, 0x3B, 0xEE, 0x56, 0xA9, - 0x75, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x5F, 0x99, 0xD9, 0x45, 0x8D, 0x3B, 0x5D, - 0x5D, 0x3B, 0x5D, 0x8D, 0x2B, 0x79, 0x79, 0x41, - 0x83, 0xB2, 0xB2, 0x89, 0x89, 0x2F, 0xA0, 0x2A, - 0xAD, 0xA5, 0x98, 0x66, 0xA3, 0xB2, 0x2F, 0xB2, - 0xD8, 0xB2, 0xA3, 0x98, 0x98, 0x2F, 0x51, 0xB2, - 0xA3, 0x83, 0x3E, 0x25, 0xD5, 0xE5, 0x50, 0x8C, - 0xED, 0x24, 0x24, 0xF0, 0x45, 0x8E, 0x2B, 0x30, - 0x30, 0x5D, 0x3B, 0x30, 0xEE, 0xF0, 0xC6, 0x65, - 0x75, 0x71, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x4B, 0xC5, 0x7D, 0x24, 0xEE, 0x67, 0x30, - 0x30, 0x8D, 0x67, 0x8E, 0xF9, 0xF7, 0x97, 0xDD, - 0x2F, 0x2F, 0x51, 0x89, 0x89, 0x2F, 0x55, 0x2A, - 0xA5, 0x8F, 0x66, 0xA3, 0x2F, 0xB2, 0xB2, 0xB2, - 0xDD, 0xA3, 0x66, 0x98, 0x66, 0x2F, 0xB2, 0xB2, - 0xA3, 0xA3, 0xB2, 0x51, 0x89, 0x44, 0xE0, 0x5E, - 0x91, 0x9F, 0x9F, 0x7D, 0x7D, 0xD9, 0x24, 0xF0, - 0x79, 0x8E, 0xEE, 0x8E, 0x24, 0x40, 0x65, 0x35, - 0x69, 0x2E, 0x98, 0xA3, 0x2F, 0x2F, 0x2F, 0x2F, - 0x2F, 0xB2, 0xB2, 0xB2, 0x2F, 0x2F, 0x2F, 0x98, - 0xA5, 0xA7, 0x95, 0xD7, 0x8C, 0xF0, 0x8E, 0x8E, - 0xEE, 0x79, 0xF0, 0xED, 0x50, 0xE8, 0x89, 0x2F, - 0xA3, 0xA3, 0xB2, 0x89, 0xB2, 0x66, 0xA0, 0x55, - 0x8F, 0x98, 0x66, 0xA3, 0xB2, 0x51, 0x51, 0xB2, - 0x74, 0xA0, 0xA0, 0x98, 0x66, 0xB2, 0xB2, 0xB2, - 0xA3, 0xA3, 0x2F, 0xB2, 0xB2, 0xB2, 0xA3, 0x2F, - 0x51, 0x83, 0xE4, 0x87, 0xB8, 0xFA, 0xA9, 0xC6, - 0x40, 0x64, 0x64, 0x50, 0xD7, 0x65, 0x35, 0x60, - 0x98, 0xB2, 0x66, 0x66, 0xA3, 0x2F, 0xA3, 0xA3, - 0xA3, 0x2F, 0x2F, 0x2F, 0x2F, 0xA3, 0x2F, 0xB2, - 0x89, 0xDD, 0x9B, 0xC0, 0x7D, 0x50, 0x8C, 0xED, - 0xED, 0x8C, 0x40, 0x9F, 0x4E, 0x51, 0xB2, 0x2F, - 0x2F, 0x2F, 0xB2, 0x51, 0xA3, 0x98, 0xA0, 0x55, - 0xA0, 0xA0, 0x8F, 0x66, 0x2F, 0x51, 0xB2, 0xA3, - 0xA3, 0x2A, 0x55, 0x98, 0xA3, 0x2F, 0xB2, 0x2F, - 0x66, 0x66, 0x2F, 0xB2, 0xD1, 0x2F, 0x2F, 0xA3, - 0xB2, 0xB2, 0xA3, 0x8F, 0xA3, 0x2F, 0xD1, 0x94, - 0xEC, 0x65, 0x65, 0xC0, 0xC0, 0x35, 0x95, 0xC2, - 0xA3, 0x98, 0x66, 0xA3, 0x2F, 0x2F, 0x2F, 0xA3, - 0xA3, 0x2F, 0xB2, 0x2F, 0x2F, 0x2F, 0x2F, 0x51, - 0x89, 0x44, 0xD1, 0x60, 0x35, 0xA9, 0x32, 0xC6, - 0xD7, 0x32, 0x94, 0x44, 0x2F, 0xB2, 0xB2, 0xB2, - 0xA3, 0x2F, 0xB2, 0x2F, 0xA3, 0x8F, 0xA0, 0xA0, - 0x55, 0xA0, 0x8F, 0xA3, 0x51, 0x51, 0x2F, 0xA3, - 0x8F, 0x2A, 0x55, 0x66, 0xA3, 0x2F, 0x2F, 0xB2, - 0xA3, 0x66, 0x2F, 0xB2, 0x51, 0xB2, 0x2F, 0x66, - 0xA3, 0xA3, 0x66, 0x8F, 0x8F, 0x8F, 0xA0, 0x2F, - 0x5E, 0xDF, 0xB9, 0x60, 0x95, 0xD3, 0x89, 0x2F, - 0xA3, 0x66, 0xA3, 0x2F, 0xB2, 0x2F, 0xA3, 0xA3, - 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0xB2, - 0x51, 0x2F, 0x8F, 0x2F, 0xC4, 0xB9, 0x9B, 0xEC, - 0x53, 0xB3, 0x4E, 0xA3, 0x2F, 0xB2, 0xB2, 0xB2, - 0xA3, 0x66, 0xA3, 0xA3, 0x66, 0x8F, 0x8F, 0x8F, - 0x8F, 0x8F, 0xA3, 0x51, 0x89, 0x51, 0xA3, 0x66, - 0xA0, 0x55, 0x8F, 0xA3, 0x2F, 0x2F, 0x2F, 0xB2, - 0x2F, 0xA3, 0x2F, 0x51, 0x51, 0xB2, 0xA3, 0x66, - 0x66, 0xA3, 0x66, 0x66, 0x66, 0x66, 0x66, 0xA3, - 0xB2, 0xC2, 0x74, 0xD8, 0xB2, 0xA3, 0xA3, 0xA3, - 0x66, 0x66, 0x2F, 0x2F, 0xA3, 0x66, 0x66, 0x66, - 0xA3, 0xA3, 0xB2, 0xB2, 0xB2, 0xB2, 0x2F, 0xB2, - 0x2F, 0x66, 0xA0, 0x55, 0x98, 0x2F, 0x89, 0x89, - 0x89, 0xB2, 0x2F, 0xA3, 0x2F, 0x51, 0x51, 0xB2, - 0x2F, 0x66, 0xA3, 0xA3, 0x66, 0x66, 0x66, 0x66, - 0x66, 0xA3, 0xB2, 0x89, 0xD8, 0x51, 0xA3, 0x98, - 0x66, 0x98, 0x66, 0x2F, 0x2F, 0x2F, 0x2F, 0xB2, - 0xB2, 0xA3, 0xA3, 0xB2, 0xB2, 0xB2, 0x2F, 0xA3, - 0x66, 0xA3, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, 0xB2, - 0x89, 0xD8, 0x89, 0x2F, 0x66, 0x66, 0xA3, 0xA3, - 0x98, 0x98, 0x66, 0x66, 0x98, 0x98, 0x66, 0xA3, - 0x2F, 0xA3, 0xB2, 0xB2, 0xB2, 0xB2, 0x2F, 0x2F, - 0xB2, 0x2F, 0x66, 0x98, 0x66, 0xA3, 0x2F, 0x2F, - 0x2F, 0xB2, 0x2F, 0xA3, 0xA3, 0xB2, 0xB2, 0x2F, - 0x2F, 0x66, 0x66, 0xA3, 0xA3, 0xA3, 0x2F, 0x2F, - 0x2F, 0xB2, 0x89, 0xD8, 0x44, 0x2F, 0x66, 0x66, - 0xA3, 0xA3, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, 0x2F, - 0x2F, 0xA3, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, 0xA3, - 0x66, 0xA3, 0x2F, 0xB2, 0xB2, 0xB2, 0x51, 0x51, - 0x89, 0x89, 0xB2, 0xA3, 0x98, 0x66, 0xA3, 0x66, - 0x98, 0x98, 0x98, 0x98, 0x98, 0x66, 0xA3, 0x2F, - 0xA3, 0x2F, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, - 0xB2, 0x2F, 0xA3, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, - 0x2F, 0xB2, 0xB2, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, - 0x2F, 0xA3, 0x66, 0xA3, 0x2F, 0xB2, 0xB2, 0xB2, - 0x51, 0x51, 0x89, 0x89, 0xB2, 0xA3, 0x98, 0x66 -}; - -unsigned char linux_logo_bw[] __initdata = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x3F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, - 0xFE, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFE, 0x3F, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xC7, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xC3, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, - 0xFB, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFD, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, - 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF9, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xF9, 0xCF, 0xC3, 0xF8, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x87, 0x81, 0xF9, - 0xF8, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xA7, - 0x99, 0xF9, 0xC2, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF9, 0xF3, 0xBC, 0xF9, 0x90, 0x00, 0x1F, 0xFF, - 0xFF, 0xFF, 0xF9, 0xE3, 0xBC, 0xF9, 0xA0, 0x00, - 0x8F, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0, 0x3C, 0xF9, - 0x83, 0xE0, 0x2F, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0, - 0x19, 0xF0, 0x1F, 0xFE, 0x0F, 0xFF, 0xFF, 0xFF, - 0xF9, 0xC0, 0x03, 0xF0, 0x3F, 0xF7, 0x8F, 0xFF, - 0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8, 0x7F, 0xF7, - 0xC7, 0xFF, 0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8, - 0x6F, 0xF7, 0xE7, 0xFF, 0xFF, 0xFF, 0xF9, 0x80, - 0x01, 0xF8, 0x7F, 0xF7, 0xE7, 0xFF, 0xFF, 0xFF, - 0xF9, 0xC0, 0x21, 0xD8, 0x7F, 0xE7, 0xEF, 0xFF, - 0xFF, 0xFF, 0xF9, 0xB1, 0x80, 0xEC, 0x7B, 0xFF, - 0xEF, 0xFF, 0xFF, 0xFF, 0xF1, 0x90, 0x00, 0xE4, - 0x7B, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xF1, 0x8C, - 0xC0, 0x7C, 0x79, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, - 0xE3, 0x80, 0x00, 0x7C, 0x7C, 0xFF, 0xCF, 0xFF, - 0xFF, 0xFF, 0xE3, 0x80, 0x00, 0x7F, 0x77, 0xFF, - 0xDF, 0xFF, 0xFF, 0xFF, 0x87, 0x00, 0x00, 0x3F, - 0x3F, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0x0E, 0x00, - 0x00, 0x3F, 0xBF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, - 0x1E, 0x00, 0x00, 0x1F, 0x9F, 0xFF, 0x3F, 0xFF, - 0xFF, 0xFE, 0x1C, 0x00, 0x00, 0x1F, 0x9F, 0xFF, - 0x7F, 0xFF, 0xFF, 0xFE, 0x3C, 0x00, 0x00, 0x1F, - 0x8F, 0xFE, 0x7F, 0xFF, 0xFF, 0xFC, 0x7C, 0x00, - 0x00, 0x0F, 0xC7, 0xFC, 0xFF, 0xFF, 0xFF, 0xFC, - 0xF8, 0x00, 0x00, 0x0F, 0xF7, 0xF9, 0xFF, 0xFF, - 0xFF, 0xFC, 0xF8, 0x00, 0x00, 0x07, 0xFB, 0xF3, - 0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0x00, 0x00, 0x07, - 0xFD, 0xE7, 0xFF, 0xFF, 0xFF, 0xF9, 0xF0, 0x00, - 0x00, 0x03, 0xFE, 0x8F, 0xFF, 0xFF, 0xFF, 0xF1, - 0xF0, 0x00, 0x00, 0x03, 0xFE, 0x1F, 0xFF, 0xFF, - 0xFF, 0xF1, 0xE0, 0x00, 0x00, 0x00, 0xFF, 0xBF, - 0xFF, 0xFF, 0xFF, 0xE3, 0xE0, 0x00, 0x00, 0x00, - 0xFE, 0xBF, 0xFF, 0xFF, 0xFF, 0xE3, 0xC0, 0x00, - 0x00, 0x00, 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0xC7, - 0xC0, 0x00, 0x00, 0x01, 0xFE, 0xBF, 0xFF, 0xFF, - 0xFF, 0xC7, 0x80, 0x00, 0x00, 0x01, 0xFE, 0x9F, - 0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00, 0x00, 0x01, - 0xFE, 0x07, 0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00, - 0x00, 0x01, 0xFE, 0x87, 0xFF, 0xFF, 0xFF, 0x9F, - 0x80, 0x00, 0x00, 0x01, 0xFD, 0x33, 0xFF, 0xFF, - 0xFF, 0x9F, 0x80, 0x00, 0x00, 0x01, 0x80, 0xF3, - 0xFF, 0xFF, 0xFF, 0x9E, 0x80, 0x00, 0x00, 0x03, - 0x8B, 0xF9, 0xFF, 0xFF, 0xFF, 0x9F, 0x80, 0x00, - 0x00, 0x02, 0x27, 0xF8, 0xFF, 0xFF, 0xFF, 0x99, - 0x80, 0x00, 0x00, 0x00, 0x07, 0xF8, 0xFF, 0xFF, - 0xFF, 0x00, 0x80, 0x00, 0x00, 0x01, 0x8F, 0xF8, - 0xFF, 0xFF, 0xFE, 0x20, 0x60, 0x00, 0x00, 0x00, - 0xE3, 0xF8, 0xFF, 0xFF, 0xF8, 0x00, 0x30, 0x00, - 0x00, 0x00, 0xF8, 0x78, 0xFF, 0xFF, 0xC0, 0x40, - 0x38, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x7F, 0xFF, - 0x81, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xFC, 0x20, - 0x7F, 0xFF, 0x90, 0x00, 0x1E, 0x00, 0x00, 0x00, - 0x78, 0x10, 0xFF, 0xFF, 0x80, 0x00, 0x0F, 0x80, - 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x80, 0x00, - 0x07, 0xC0, 0x00, 0x00, 0x00, 0x08, 0xFF, 0xFF, - 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x04, - 0x7F, 0xFF, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x10, - 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x01, 0x80, - 0x00, 0x30, 0x00, 0x00, 0x0F, 0xFF, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, 0x4F, 0xFF, - 0x80, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, - 0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x80, 0x03, 0xF0, - 0x00, 0x00, 0x8F, 0xFF, 0x80, 0x00, 0x00, 0x40, - 0x0F, 0xF0, 0x00, 0x04, 0x1F, 0xFF, 0x80, 0x00, - 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x10, 0x1F, 0xFF, - 0xC0, 0x00, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x40, - 0xFF, 0xFF, 0x98, 0x00, 0x00, 0xFF, 0xFF, 0xF0, - 0x00, 0x83, 0xFF, 0xFF, 0x81, 0xE0, 0x01, 0xFF, - 0xFF, 0xF8, 0x02, 0x07, 0xFF, 0xFF, 0x80, 0x3F, - 0x07, 0xE0, 0x00, 0x1C, 0x0C, 0x1F, 0xFF, 0xFF, - 0xF8, 0x03, 0xFF, 0x80, 0x00, 0x1F, 0x78, 0x1F, - 0xFF, 0xFF, 0xFF, 0x80, 0x7F, 0x00, 0x07, 0x0F, - 0xF0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0x0C, 0x07, - 0xFF, 0x83, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x1F, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x07, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, + 0x22, 0x21, 0x21, 0x21, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x26, 0x26, 0x25, 0x28, 0x23, 0x22, 0x21, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x23, 0x25, 0x2a, 0x2b, 0x2c, 0x2d, 0x2d, + 0x2d, 0x2e, 0x2c, 0x2b, 0x2a, 0x25, 0x28, 0x22, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x24, 0x2a, 0x2c, 0x2f, 0x2c, 0x30, 0x30, 0x24, + 0x25, 0x27, 0x2b, 0x2c, 0x2f, 0x31, 0x32, 0x25, + 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x25, + 0x33, 0x34, 0x35, 0x21, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x21, 0x2b, 0x2f, 0x2c, + 0x30, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, 0x33, + 0x2d, 0x27, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x31, + 0x2d, 0x32, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x21, 0x28, 0x2a, 0x34, + 0x25, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x23, 0x32, 0x27, 0x21, 0x36, + 0x2a, 0x2d, 0x2a, 0x28, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x22, 0x26, 0x2c, 0x35, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x25, 0x2f, 0x37, 0x32, 0x22, + 0x36, 0x35, 0x31, 0x27, 0x22, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x23, 0x2a, 0x2f, 0x22, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x26, 0x38, 0x38, 0x35, 0x25, + 0x36, 0x21, 0x2d, 0x2b, 0x24, 0x21, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x21, 0x24, 0x39, 0x39, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x25, 0x2b, 0x30, 0x28, 0x22, + 0x36, 0x36, 0x27, 0x34, 0x30, 0x23, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x21, 0x26, 0x2d, 0x26, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x22, 0x22, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x2d, 0x33, 0x28, 0x21, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x30, 0x2f, 0x23, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x2b, 0x2c, 0x25, 0x21, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x2a, 0x34, 0x36, 0x36, + 0x36, 0x21, 0x22, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x21, 0x23, 0x22, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x28, 0x34, 0x27, 0x22, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x36, + 0x21, 0x21, 0x24, 0x27, 0x21, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x28, 0x27, 0x22, 0x33, 0x24, 0x36, + 0x36, 0x36, 0x36, 0x22, 0x2f, 0x2a, 0x23, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x36, + 0x30, 0x3a, 0x38, 0x24, 0x24, 0x36, 0x36, 0x36, + 0x23, 0x2f, 0x3b, 0x3c, 0x3d, 0x30, 0x25, 0x21, + 0x36, 0x36, 0x36, 0x36, 0x2f, 0x32, 0x23, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x23, + 0x3e, 0x3f, 0x40, 0x3a, 0x22, 0x36, 0x36, 0x21, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x3e, 0x23, 0x21, + 0x36, 0x36, 0x36, 0x36, 0x2f, 0x33, 0x28, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x29, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x2b, + 0x44, 0x40, 0x46, 0x47, 0x35, 0x36, 0x36, 0x26, + 0x43, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x2e, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x31, 0x35, 0x24, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x32, 0x34, 0x36, 0x4d, + 0x4e, 0x25, 0x2f, 0x46, 0x4a, 0x22, 0x23, 0x32, + 0x4f, 0x50, 0x21, 0x31, 0x51, 0x52, 0x53, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x31, 0x35, 0x24, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x29, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x2a, 0x2f, 0x21, 0x3a, + 0x4d, 0x21, 0x31, 0x54, 0x55, 0x28, 0x30, 0x2b, + 0x4b, 0x4d, 0x36, 0x23, 0x32, 0x50, 0x3f, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x2e, 0x39, 0x24, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x29, 0x20, 0x29, 0x20, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x2a, 0x38, 0x23, 0x37, + 0x55, 0x36, 0x28, 0x3a, 0x56, 0x57, 0x57, 0x58, + 0x3c, 0x4d, 0x36, 0x36, 0x36, 0x40, 0x40, 0x21, + 0x36, 0x36, 0x36, 0x36, 0x2e, 0x39, 0x24, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x29, 0x29, 0x29, 0x20, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x30, 0x51, 0x23, 0x35, + 0x43, 0x25, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, + 0x5f, 0x60, 0x61, 0x36, 0x31, 0x47, 0x3b, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x31, 0x2c, 0x25, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x30, 0x2f, 0x23, 0x22, + 0x40, 0x62, 0x63, 0x5d, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x66, 0x5e, 0x6a, 0x6b, 0x2a, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x33, 0x2e, 0x26, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x27, 0x2f, 0x23, 0x36, + 0x6c, 0x63, 0x6d, 0x64, 0x5c, 0x66, 0x69, 0x6e, + 0x6f, 0x70, 0x71, 0x69, 0x69, 0x72, 0x6c, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x33, 0x34, 0x27, 0x22, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x27, 0x34, 0x26, 0x73, + 0x74, 0x75, 0x76, 0x64, 0x65, 0x77, 0x69, 0x78, + 0x70, 0x71, 0x71, 0x71, 0x72, 0x5f, 0x5e, 0x21, + 0x36, 0x36, 0x36, 0x36, 0x25, 0x38, 0x2a, 0x23, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x26, 0x2d, 0x33, 0x79, + 0x63, 0x7a, 0x7b, 0x5c, 0x66, 0x69, 0x6e, 0x7c, + 0x71, 0x71, 0x69, 0x7d, 0x7e, 0x7a, 0x7f, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x21, 0x51, 0x2b, 0x28, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x26, 0x2d, 0x32, 0x24, + 0x80, 0x81, 0x64, 0x82, 0x77, 0x69, 0x71, 0x71, + 0x69, 0x83, 0x84, 0x85, 0x7a, 0x85, 0x86, 0x36, + 0x21, 0x2b, 0x23, 0x36, 0x36, 0x39, 0x2e, 0x26, + 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x27, 0x2d, 0x33, 0x21, + 0x87, 0x88, 0x89, 0x72, 0x67, 0x66, 0x5f, 0x89, + 0x8a, 0x63, 0x85, 0x8b, 0x8c, 0x8d, 0x41, 0x36, + 0x36, 0x2d, 0x3a, 0x35, 0x36, 0x24, 0x51, 0x32, + 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x30, 0x2f, 0x33, 0x21, + 0x55, 0x8e, 0x8f, 0x8a, 0x7d, 0x5e, 0x90, 0x7e, + 0x75, 0x75, 0x90, 0x62, 0x40, 0x3f, 0x49, 0x23, + 0x36, 0x24, 0x3a, 0x3a, 0x24, 0x36, 0x2e, 0x31, + 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x21, 0x28, 0x33, 0x37, 0x25, 0x22, + 0x3b, 0x50, 0x8e, 0x8f, 0x90, 0x7e, 0x90, 0x63, + 0x74, 0x91, 0x92, 0x42, 0x93, 0x4b, 0x45, 0x2c, + 0x36, 0x36, 0x33, 0x39, 0x21, 0x36, 0x22, 0x51, + 0x33, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x22, 0x27, 0x2e, 0x2e, 0x36, 0x21, + 0x94, 0x3f, 0x50, 0x95, 0x96, 0x8f, 0x8f, 0x97, + 0x8e, 0x42, 0x50, 0x43, 0x47, 0x48, 0x48, 0x98, + 0x21, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x39, + 0x2e, 0x27, 0x23, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x22, 0x24, 0x2b, 0x38, 0x28, 0x36, 0x32, + 0x4c, 0x4b, 0x50, 0x50, 0x50, 0x42, 0x42, 0x50, + 0x50, 0x40, 0x45, 0x99, 0x48, 0x48, 0x48, 0x48, + 0x34, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x23, + 0x2f, 0x2b, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x28, 0x32, 0x51, 0x32, 0x28, 0x21, 0x98, + 0x48, 0x47, 0x9a, 0x50, 0x50, 0x50, 0x50, 0x50, + 0x9a, 0x4f, 0x9b, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x93, 0x23, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x2a, 0x2f, 0x2a, 0x28, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x23, 0x30, 0x2e, 0x2c, 0x36, 0x21, 0x51, 0x9b, + 0x48, 0x48, 0x52, 0x3f, 0x50, 0x50, 0x40, 0x4b, + 0x47, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x34, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x2d, 0x31, 0x27, 0x23, 0x21, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23, + 0x27, 0x2c, 0x2d, 0x21, 0x36, 0x28, 0x44, 0x48, + 0x48, 0x48, 0x48, 0x47, 0x46, 0x4f, 0x47, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x9c, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x28, 0x51, 0x39, 0x26, 0x22, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x25, + 0x35, 0x51, 0x28, 0x36, 0x36, 0x9d, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x9b, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x4f, 0x28, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x28, 0x38, 0x2b, 0x25, 0x22, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, 0x33, + 0x51, 0x25, 0x36, 0x36, 0x23, 0x40, 0x9b, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x9b, 0x99, 0x2b, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x30, 0x2f, 0x33, 0x24, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x21, 0x23, 0x30, 0x34, + 0x27, 0x36, 0x36, 0x36, 0x2a, 0x40, 0x47, 0x48, + 0x48, 0x48, 0x48, 0x9b, 0x99, 0x99, 0x9b, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x9b, 0x47, 0x52, + 0x46, 0x4f, 0x37, 0x21, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x30, 0x34, 0x2a, 0x23, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x22, 0x25, 0x39, 0x2c, + 0x36, 0x36, 0x36, 0x21, 0x31, 0x4e, 0x9a, 0x4c, + 0x47, 0x9b, 0x9b, 0x52, 0x46, 0x4f, 0x52, 0x9b, + 0x9b, 0x9b, 0x47, 0x4f, 0x45, 0x9a, 0x93, 0x93, + 0x3f, 0x93, 0x98, 0x28, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x39, 0x2c, 0x26, + 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x23, 0x2a, 0x34, 0x28, + 0x36, 0x36, 0x36, 0x22, 0x38, 0x98, 0x44, 0x99, + 0x9b, 0x48, 0x48, 0x9b, 0x4c, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x47, 0x52, 0x46, 0x43, 0x93, + 0x40, 0x40, 0x43, 0x53, 0x21, 0x23, 0x33, 0x23, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x2f, 0x32, + 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x21, 0x24, 0x2b, 0x31, 0x36, + 0x36, 0x22, 0x36, 0x24, 0x9e, 0x4f, 0x9b, 0x48, + 0x48, 0x48, 0x48, 0x9b, 0x99, 0x9f, 0x52, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x47, + 0x4f, 0x9a, 0x3f, 0x46, 0x38, 0x36, 0x21, 0x30, + 0x26, 0x36, 0x36, 0x36, 0x36, 0x36, 0x39, 0x2c, + 0x25, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x26, 0x2e, 0x33, 0x36, + 0x25, 0x25, 0x36, 0x4d, 0x52, 0x48, 0x48, 0x48, + 0x47, 0x9f, 0x48, 0x48, 0x48, 0xa0, 0xa1, 0xa2, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x47, 0x44, 0x93, 0x43, 0x23, 0x36, 0x36, + 0x26, 0x24, 0x36, 0x36, 0x36, 0x36, 0x28, 0x2f, + 0x2a, 0x23, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x2a, 0x51, 0x24, 0x36, + 0x2a, 0x36, 0x28, 0x44, 0x48, 0x48, 0x48, 0x48, + 0xa3, 0xa4, 0x48, 0x48, 0x9f, 0xa5, 0xa6, 0x9f, + 0x48, 0x48, 0x48, 0xa2, 0xa7, 0x47, 0x48, 0x48, + 0x48, 0x48, 0x9b, 0x4b, 0x44, 0x37, 0x36, 0x23, + 0x28, 0x30, 0x22, 0x36, 0x36, 0x36, 0x36, 0x2d, + 0x35, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x21, 0x28, 0x2b, 0x34, 0x36, 0x25, + 0x24, 0x36, 0x4a, 0x48, 0x48, 0x48, 0x48, 0x48, + 0xa8, 0xa1, 0x48, 0x48, 0x9f, 0xa9, 0xa6, 0x9f, + 0x48, 0x48, 0xaa, 0xa1, 0xa5, 0x9f, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x9b, 0x52, 0x3f, 0x21, 0x30, + 0x35, 0x25, 0x30, 0x36, 0x36, 0x36, 0x36, 0x32, + 0x2d, 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x22, 0x26, 0x2e, 0x35, 0x36, 0x2a, + 0x36, 0x24, 0x4f, 0x48, 0x52, 0x52, 0x48, 0x48, + 0xab, 0xac, 0xa0, 0x48, 0xad, 0xa6, 0xa6, 0x9f, + 0x48, 0xa2, 0xa9, 0xa6, 0xa2, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x47, 0x32, 0x30, + 0x2a, 0x23, 0x30, 0x23, 0x36, 0x36, 0x36, 0x21, + 0x2f, 0x32, 0x23, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x21, 0x23, 0x2a, 0x51, 0x28, 0x28, 0x25, + 0x36, 0x3a, 0x48, 0x48, 0xae, 0xaf, 0x48, 0x48, + 0xad, 0xac, 0xa1, 0x9f, 0xa2, 0xa9, 0xa9, 0xa2, + 0x48, 0xab, 0x78, 0xa7, 0x48, 0x48, 0x48, 0x48, + 0x9f, 0x48, 0x48, 0x48, 0x48, 0x48, 0x38, 0x21, + 0x36, 0x36, 0x22, 0x27, 0x36, 0x36, 0x36, 0x36, + 0x2e, 0x35, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x22, 0x25, 0x2c, 0x34, 0x36, 0x30, 0x21, + 0x23, 0x43, 0x48, 0x48, 0xb0, 0xb1, 0xb2, 0x9f, + 0x48, 0xb3, 0xa5, 0xb3, 0xab, 0xa9, 0xa9, 0xb3, + 0xb4, 0xa9, 0xb5, 0xb0, 0x48, 0x48, 0xa0, 0xa5, + 0xa1, 0xad, 0x48, 0x48, 0x48, 0x48, 0x94, 0x36, + 0x36, 0x36, 0x36, 0x32, 0x36, 0x36, 0x36, 0x36, + 0x2a, 0x2e, 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x23, 0x2a, 0x51, 0x25, 0x21, 0x2a, 0x36, + 0x2e, 0x9b, 0x48, 0x48, 0x48, 0xb6, 0xb7, 0xa4, + 0xa2, 0xa7, 0xb5, 0x78, 0x6f, 0x6f, 0x6e, 0x6f, + 0xa9, 0xb5, 0xab, 0x48, 0x9f, 0xab, 0xa9, 0xa1, + 0xaa, 0x48, 0x48, 0x48, 0x48, 0x48, 0x98, 0x36, + 0x36, 0x36, 0x36, 0x32, 0x36, 0x36, 0x36, 0x36, + 0x22, 0x2f, 0x30, 0x22, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x22, 0x25, 0x2c, 0x34, 0x36, 0x24, 0x28, 0x36, + 0x54, 0x48, 0x48, 0x48, 0x48, 0xa2, 0xa8, 0xa1, + 0xa5, 0xa6, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x6f, + 0x6f, 0x78, 0xa5, 0xa0, 0xa0, 0x78, 0xa6, 0xa2, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x9a, 0x36, + 0x36, 0x36, 0x36, 0x30, 0x36, 0x36, 0x36, 0x36, + 0x21, 0x2f, 0x32, 0x23, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x28, 0x32, 0x2f, 0x28, 0x36, 0x27, 0x22, 0x21, + 0x43, 0x48, 0x4b, 0xa2, 0x9f, 0x48, 0xa2, 0xa1, + 0xb8, 0x6e, 0x6e, 0xb5, 0x78, 0x6f, 0x78, 0x78, + 0x6e, 0x6f, 0x78, 0xb5, 0xa6, 0xa1, 0xa0, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x4b, 0x21, + 0x36, 0x36, 0x21, 0x26, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x34, 0x2b, 0x28, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x25, 0x2c, 0x39, 0x36, 0x36, 0x30, 0x22, 0x25, + 0x52, 0x48, 0xa3, 0xb1, 0xb6, 0xb3, 0xaa, 0xac, + 0x68, 0x68, 0x6e, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, + 0x78, 0x6f, 0x6f, 0xb5, 0xa6, 0xb4, 0x48, 0x9f, + 0xb4, 0xb4, 0xa2, 0x9f, 0x48, 0x48, 0x4f, 0x21, + 0x36, 0x36, 0x22, 0x26, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x2c, 0x35, 0x24, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x30, 0x2d, 0x21, 0x36, 0x36, 0x32, 0x23, 0x2a, + 0x47, 0x48, 0xa2, 0xb6, 0xaf, 0xb9, 0xba, 0x68, + 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x78, + 0x6f, 0x6f, 0xa6, 0x6f, 0xb5, 0xa0, 0xaa, 0xa6, + 0xa6, 0xa9, 0xb2, 0xb3, 0x48, 0x48, 0x4c, 0x22, + 0x36, 0x36, 0x24, 0x23, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x2c, 0x39, 0x24, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28, + 0x33, 0x2e, 0x36, 0x36, 0x23, 0x31, 0x27, 0x39, + 0x9b, 0x48, 0x48, 0x48, 0xb0, 0xb0, 0xba, 0xb8, + 0x68, 0x68, 0x69, 0x78, 0x6f, 0xb5, 0x6f, 0xb5, + 0x78, 0x78, 0x78, 0x78, 0x78, 0xa5, 0xbb, 0xa9, + 0xa5, 0x48, 0x48, 0x48, 0x48, 0x48, 0x4c, 0x23, + 0x36, 0x36, 0x26, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x2c, 0x39, 0x24, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28, + 0x2b, 0x39, 0x36, 0x36, 0x36, 0x26, 0x32, 0x31, + 0x9b, 0x48, 0x48, 0x48, 0x48, 0x9f, 0xac, 0x68, + 0xbc, 0x6e, 0x6e, 0x6e, 0xb5, 0x6f, 0x6e, 0x6f, + 0x6f, 0x78, 0x78, 0xb5, 0xb5, 0xa5, 0x9f, 0x9f, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x46, 0x22, + 0x36, 0x21, 0x26, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x2c, 0x35, 0x24, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, + 0x35, 0x39, 0x36, 0x36, 0x36, 0x36, 0x26, 0x2d, + 0x9b, 0x48, 0x48, 0xb0, 0xaa, 0xb3, 0xbd, 0xb8, + 0xb8, 0x68, 0x6e, 0x6e, 0xb5, 0x6f, 0x78, 0x6e, + 0x78, 0x6f, 0x78, 0x78, 0xb5, 0xa9, 0xa2, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x9a, 0x36, + 0x24, 0x27, 0xbe, 0x24, 0x25, 0x28, 0x21, 0x36, + 0x36, 0x34, 0x2b, 0x28, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x25, + 0x39, 0x4d, 0xbf, 0x84, 0x81, 0x57, 0x21, 0x39, + 0x52, 0x48, 0x48, 0x62, 0xb1, 0xc0, 0xc1, 0xc1, + 0xb8, 0xb8, 0x68, 0xbc, 0x6e, 0x6e, 0x6e, 0x78, + 0x78, 0x78, 0x78, 0x6e, 0x78, 0xa9, 0xa0, 0xab, + 0xb3, 0xa2, 0x48, 0x48, 0x48, 0x48, 0x53, 0x28, + 0x23, 0x36, 0x36, 0x36, 0x21, 0x28, 0x2c, 0x30, + 0x21, 0x38, 0x33, 0x28, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x21, 0x22, 0x22, 0x28, 0x30, + 0x2d, 0xc2, 0x7a, 0xc3, 0xc4, 0xc4, 0x7f, 0x22, + 0x51, 0x52, 0x48, 0x48, 0xb0, 0xaa, 0xa8, 0xbd, + 0x68, 0xb8, 0xb8, 0x68, 0x68, 0x6e, 0x6e, 0x6f, + 0x6e, 0x6e, 0xb5, 0x6e, 0x78, 0xab, 0xab, 0xb5, + 0x78, 0xa6, 0xb3, 0xc5, 0xac, 0xac, 0xc6, 0x61, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x30, 0x32, + 0x25, 0x4d, 0x2b, 0x28, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x21, 0x23, 0x24, 0x26, 0x30, 0x33, 0x31, + 0x4d, 0x91, 0x5b, 0xc3, 0xc4, 0xc4, 0xc4, 0x5a, + 0x21, 0x2e, 0x46, 0x48, 0x48, 0x48, 0xb0, 0x64, + 0xc1, 0xb8, 0xb8, 0xb8, 0x68, 0x71, 0x6e, 0x6e, + 0x6f, 0x71, 0x6f, 0x6f, 0xa6, 0xa0, 0x9f, 0xb4, + 0xb4, 0xa0, 0xa1, 0xb7, 0xc7, 0x69, 0x66, 0xc8, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x26, 0x25, + 0x83, 0xc9, 0x2c, 0x25, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x28, 0x30, 0x35, 0x2d, 0x2f, 0x37, 0x4a, + 0x60, 0x85, 0xca, 0xcb, 0xc4, 0xc4, 0xc4, 0x82, + 0x86, 0x36, 0x32, 0x3f, 0xa2, 0xa4, 0xa8, 0xa9, + 0xb8, 0xb8, 0xb8, 0xb8, 0x68, 0x6e, 0x6e, 0x6e, + 0x6e, 0x71, 0x6f, 0x71, 0xa6, 0xb4, 0x9f, 0x9f, + 0x48, 0x48, 0x48, 0xcc, 0xc3, 0xc7, 0xcd, 0xce, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x57, + 0x77, 0x66, 0x34, 0x27, 0x22, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x23, 0x30, 0x31, 0xcf, 0x91, 0x7e, 0x90, 0x90, + 0x8b, 0x5b, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0x5d, 0xd0, 0x36, 0x24, 0xd1, 0xb1, 0xaf, 0xaa, + 0xba, 0xb8, 0x68, 0x68, 0x68, 0x71, 0x6e, 0x6e, + 0x6e, 0x6f, 0x6e, 0x78, 0xa1, 0xa9, 0xa1, 0xb0, + 0x9f, 0x9b, 0x99, 0xcc, 0x64, 0x5c, 0x8b, 0xd0, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x73, 0x5d, + 0x82, 0x5c, 0xd2, 0x2a, 0x23, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x24, 0x2b, 0xcf, 0x8b, 0x5b, 0x76, 0x5b, 0x5b, + 0x7b, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc7, 0x5e, 0x22, 0x36, 0x21, 0x3a, 0x99, 0x48, + 0xa2, 0xa8, 0xb7, 0xc1, 0xb8, 0x68, 0x68, 0xbc, + 0x68, 0x6e, 0xb5, 0xb4, 0xb4, 0xab, 0xb5, 0xa1, + 0xb0, 0x4f, 0x3f, 0xd3, 0x7b, 0x7b, 0x85, 0x80, + 0xbe, 0x36, 0x36, 0x36, 0x21, 0xd4, 0x7e, 0x7b, + 0x64, 0x64, 0xd5, 0x35, 0x24, 0x21, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x26, 0x31, 0xd6, 0x5b, 0x64, 0xc3, 0xc3, 0xcb, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0x66, 0xd7, 0x36, 0x36, 0x36, 0x2c, 0x4b, + 0xd8, 0xd9, 0xb3, 0xa8, 0xbd, 0xbd, 0xbd, 0xbd, + 0xa9, 0xab, 0xb3, 0xa5, 0xa2, 0x9f, 0xa2, 0xa1, + 0x6a, 0x9a, 0x3f, 0xda, 0x76, 0x76, 0x7a, 0x63, + 0xdb, 0xdc, 0x86, 0xdc, 0xdd, 0x90, 0x5b, 0x64, + 0xc3, 0xc3, 0xde, 0x2d, 0x27, 0x23, 0x21, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x26, 0x2d, 0x91, 0x5b, 0x64, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc7, 0x83, 0xce, 0x36, 0x36, 0x36, 0x30, + 0xb1, 0xd9, 0x48, 0xa1, 0xb2, 0xb0, 0xb0, 0xb3, + 0xa2, 0x48, 0xa7, 0xbd, 0xa9, 0xa2, 0x48, 0x9f, + 0xaa, 0x9a, 0x3f, 0xb1, 0x5b, 0x7b, 0xdf, 0x85, + 0x7e, 0x90, 0x63, 0x90, 0x85, 0x5b, 0xc3, 0xc4, + 0xc4, 0xcb, 0x5d, 0xd5, 0x39, 0x26, 0x23, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x26, 0x2d, 0xe0, 0xdf, 0x64, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc7, 0x88, 0x36, 0x36, 0x36, 0x36, + 0x2d, 0x9b, 0x48, 0xb9, 0xaf, 0xa2, 0xa2, 0xb9, + 0xa8, 0x9f, 0x48, 0xa7, 0xb7, 0xd9, 0x48, 0x48, + 0x9b, 0x45, 0x3f, 0xe1, 0x6d, 0x7b, 0xca, 0xdf, + 0x7a, 0x8b, 0x8b, 0x7a, 0x5b, 0x64, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc3, 0xe2, 0x37, 0x35, 0x26, 0x23, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x26, 0x2e, 0xe0, 0x7a, 0x7b, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc7, 0x72, 0x73, 0x36, 0x36, 0x36, + 0x24, 0x52, 0x48, 0xa3, 0xaf, 0x9f, 0x48, 0xb6, + 0xaf, 0xa2, 0x48, 0x9f, 0xe3, 0xd8, 0x48, 0x48, + 0x48, 0x46, 0x42, 0xd6, 0x7a, 0x7b, 0x64, 0x7b, + 0x76, 0x5b, 0x5b, 0x76, 0x7b, 0xc3, 0xc4, 0xc4, + 0xc4, 0xc4, 0xcb, 0x64, 0xe2, 0x4d, 0x2c, 0x27, + 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x25, 0x31, 0xe4, 0x8b, 0x7b, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc7, 0x89, 0xbe, 0x36, 0x36, + 0x32, 0x47, 0x48, 0x4f, 0xa0, 0x48, 0x48, 0xe3, + 0x92, 0x9f, 0x48, 0x9f, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x4b, 0x2f, 0x8f, 0x7a, 0x7b, 0xc3, 0xcb, + 0xc3, 0x64, 0x64, 0xc3, 0xc3, 0xcb, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc3, 0x5d, 0xe5, 0x2c, + 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x25, 0x31, 0xe4, 0x85, 0x7b, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0x66, 0x57, 0x27, 0x4d, + 0x4b, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x99, 0x34, 0xbe, 0xdb, 0x7a, 0x7b, 0xc3, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc3, 0xe4, + 0x32, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x26, 0x2d, 0xe4, 0x85, 0x7b, 0xcb, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc7, 0x5f, 0x92, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x44, + 0x35, 0x36, 0xce, 0xdd, 0x7a, 0x7b, 0xcb, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xcb, 0xc3, 0xe1, + 0x2b, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23, + 0x30, 0x2f, 0xd6, 0x8b, 0x7b, 0xcb, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0x66, 0x89, 0x45, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x9b, 0x4e, 0x25, + 0x36, 0x36, 0x61, 0xdb, 0x6d, 0x64, 0xcb, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xcb, 0x7b, 0xdf, 0xe5, + 0x32, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28, + 0x33, 0xe6, 0x63, 0xdf, 0xc3, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc3, 0x72, 0x81, 0xe7, + 0x46, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x3f, 0x2c, 0x36, 0x36, + 0x36, 0x36, 0xe8, 0x8f, 0x6d, 0x64, 0xcb, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc3, 0xca, 0x8b, 0xcf, 0x2c, + 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, + 0x35, 0x96, 0x75, 0xca, 0xc3, 0xcb, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xcb, 0x7b, 0x81, 0xdb, + 0x73, 0x3b, 0x44, 0x9b, 0x48, 0x48, 0x48, 0x9b, + 0x99, 0x43, 0x94, 0x2c, 0x21, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x73, 0xdb, 0x7a, 0x7b, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0x64, 0x76, 0x7a, 0x91, 0xd5, 0x31, 0x30, + 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, + 0x39, 0x97, 0x75, 0xdf, 0x7b, 0x64, 0xc3, 0xc3, + 0xcb, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0x7b, 0x7a, 0xe9, + 0xea, 0x36, 0x21, 0x26, 0x2b, 0x39, 0x33, 0x30, + 0x23, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x21, 0xea, 0xdd, 0x8b, 0x7b, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc3, 0x64, 0x64, + 0x76, 0x85, 0xe0, 0xd5, 0x34, 0x2b, 0x27, 0x28, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28, + 0x33, 0xeb, 0x63, 0x7e, 0x7a, 0x6d, 0xdf, 0x5b, + 0x76, 0x7b, 0x64, 0x64, 0xc3, 0xcb, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xcb, 0x76, 0x85, 0xdb, + 0x79, 0x22, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x21, 0xec, 0xdd, 0x75, 0x76, 0xc3, 0xc4, + 0xc4, 0xc4, 0xcb, 0xc3, 0x64, 0x76, 0xdf, 0x8b, + 0xd6, 0xd5, 0x2f, 0x35, 0x30, 0x24, 0x22, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23, + 0x27, 0x31, 0xed, 0xeb, 0xdd, 0x74, 0x63, 0x90, + 0x7e, 0x75, 0x8b, 0x6d, 0xdf, 0x76, 0x64, 0xc3, + 0xcb, 0xcb, 0xcb, 0xcb, 0x64, 0x7a, 0x84, 0xee, + 0x79, 0xbe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x21, 0xea, 0xee, 0x63, 0x6d, 0x7b, 0x64, + 0xcb, 0xc3, 0x64, 0x7b, 0xdf, 0x75, 0x63, 0x96, + 0x38, 0x39, 0x2a, 0x24, 0x23, 0x21, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x28, 0x27, 0x35, 0x2d, 0x41, 0xd5, 0xe7, 0x8f, + 0xdb, 0xdd, 0xe9, 0x74, 0x84, 0x90, 0x85, 0x6d, + 0x5b, 0x7b, 0x7b, 0xca, 0x6d, 0x90, 0xdb, 0xef, + 0xec, 0x22, 0x36, 0x36, 0x28, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x25, 0x36, + 0x36, 0x21, 0xd4, 0x80, 0xe9, 0x7e, 0x6d, 0x76, + 0xca, 0x76, 0x6d, 0x85, 0x63, 0xdb, 0xd5, 0x34, + 0x33, 0x26, 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x23, 0x24, 0x27, 0x2a, 0x35, 0x2e, 0x2f, + 0x41, 0xf0, 0xf1, 0x6c, 0x80, 0xee, 0xdb, 0x74, + 0x84, 0x90, 0x75, 0x7e, 0x74, 0x8f, 0xef, 0x79, + 0xe8, 0x2b, 0x9d, 0x41, 0x2f, 0x34, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x34, 0x2f, 0x38, + 0x4d, 0x37, 0xf2, 0xf3, 0x8f, 0x74, 0x63, 0x7e, + 0x75, 0x7e, 0x63, 0xe9, 0x88, 0xe6, 0x31, 0x2a, + 0x24, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x21, 0x22, 0x23, 0x24, 0x26, 0x30, + 0x33, 0x39, 0x2e, 0x51, 0x41, 0xd2, 0x6c, 0xf3, + 0x80, 0xee, 0xee, 0xee, 0xf4, 0xf3, 0xd7, 0xf5, + 0x41, 0x34, 0x35, 0x32, 0x30, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x30, 0x2a, + 0x2b, 0x34, 0xf6, 0xec, 0xf7, 0x8f, 0xdd, 0xe9, + 0xe9, 0xdd, 0xee, 0x6c, 0x41, 0x39, 0x27, 0x28, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22, + 0x28, 0x24, 0x26, 0x2a, 0x33, 0x2c, 0x2f, 0x41, + 0xf8, 0xd7, 0x79, 0x79, 0x79, 0xec, 0xf9, 0x51, + 0x39, 0x30, 0x24, 0x23, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x22, 0x23, + 0x24, 0x2a, 0x31, 0xfa, 0xea, 0x79, 0xf3, 0x80, + 0xf7, 0xdc, 0xfb, 0x2f, 0x35, 0x26, 0x23, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x21, 0x22, 0x23, 0x28, 0x25, 0x30, 0x2b, + 0x31, 0x2f, 0xf6, 0xfa, 0xfa, 0x2f, 0x2e, 0x33, + 0x26, 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x28, 0x27, 0x35, 0x34, 0xfa, 0xfa, 0xfa, + 0xfc, 0xf6, 0x2e, 0x33, 0x25, 0x23, 0x21, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x23, 0x28, + 0x26, 0x30, 0x32, 0x2b, 0x33, 0x2a, 0x26, 0x28, + 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x21, 0x23, 0x25, 0x30, 0x33, 0x35, 0x35, + 0x2b, 0x2a, 0x26, 0x28, 0x22, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x21, 0x22, 0x23, 0x28, 0x28, 0x23, 0x22, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x21, 0x23, 0x28, 0x24, 0x24, + 0x28, 0x23, 0x22, 0x21, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, }; -unsigned char linux_logo16_red[1]; -unsigned char linux_logo16_green[1]; -unsigned char linux_logo16_blue[1]; unsigned char linux_logo16[1]; -#else +#endif /* INCLUDE_LINUX_LOGO_DATA */ -/* prototypes only */ -extern unsigned char linux_logo_red[]; -extern unsigned char linux_logo_green[]; -extern unsigned char linux_logo_blue[]; -extern unsigned char linux_logo[]; -extern unsigned char linux_logo_bw[]; -extern unsigned char linux_logo16_red[]; -extern unsigned char linux_logo16_green[]; -extern unsigned char linux_logo16_blue[]; -extern unsigned char linux_logo16[]; +#include -#endif diff -u --recursive --new-file v2.4.5/linux/include/asm-sparc/socket.h linux/include/asm-sparc/socket.h --- v2.4.5/linux/include/asm-sparc/socket.h Sat Feb 3 11:26:44 2001 +++ linux/include/asm-sparc/socket.h Wed Jun 20 21:00:55 2001 @@ -1,4 +1,4 @@ -/* $Id: socket.h,v 1.16 2001/01/30 07:48:30 davem Exp $ */ +/* $Id: socket.h,v 1.17 2001/06/13 16:25:03 davem Exp $ */ #ifndef _ASM_SOCKET_H #define _ASM_SOCKET_H @@ -63,6 +63,7 @@ /* level. For writing rarp and */ /* other similar things on the */ /* user level. */ +#define SOCK_MAX (SOCK_PACKET+1) #endif #endif /* _ASM_SOCKET_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-sparc/softirq.h linux/include/asm-sparc/softirq.h --- v2.4.5/linux/include/asm-sparc/softirq.h Sun Aug 6 12:42:21 2000 +++ linux/include/asm-sparc/softirq.h Tue Jun 12 11:08:46 2001 @@ -14,8 +14,21 @@ #include #define local_bh_disable() (local_bh_count(smp_processor_id())++) -#define local_bh_enable() (local_bh_count(smp_processor_id())--) - +#define __local_bh_enable() (local_bh_count(smp_processor_id())--) +#define local_bh_enable() \ +do { if (!--local_bh_count(smp_processor_id()) && \ + softirq_pending(smp_processor_id())) { \ + do_softirq(); \ + __sti(); \ + } \ +} while (0) +#define __cpu_raise_softirq(cpu, nr) (softirq_pending(cpu) |= (1< +#include /* FIXME: All of this should be checked for sun4u. It has /sbus/auxio, but I don't know whether it is the same and don't have a floppy */ diff -u --recursive --new-file v2.4.5/linux/include/asm-sparc64/bitops.h linux/include/asm-sparc64/bitops.h --- v2.4.5/linux/include/asm-sparc64/bitops.h Thu Apr 26 22:17:26 2001 +++ linux/include/asm-sparc64/bitops.h Wed Jun 20 21:00:55 2001 @@ -1,4 +1,4 @@ -/* $Id: bitops.h,v 1.33 2001/04/24 01:09:12 davem Exp $ +/* $Id: bitops.h,v 1.36 2001/06/14 12:34:49 davem Exp $ * bitops.h: Bit string operations on the V9. * * Copyright 1996, 1997 David S. Miller (davem@caip.rutgers.edu) @@ -20,13 +20,46 @@ #define clear_bit(nr,addr) ((void)___test_and_clear_bit(nr,addr)) #define change_bit(nr,addr) ((void)___test_and_change_bit(nr,addr)) -/* "non-atomic" versions, nothing special for now... */ -#define __set_bit(X,Y) set_bit(X,Y) -#define __clear_bit(X,Y) clear_bit(X,Y) -#define __change_bit(X,Y) change_bit(X,Y) -#define __test_and_set_bit(X,Y) test_and_set_bit(X,Y) -#define __test_and_clear_bit(X,Y) test_and_clear_bit(X,Y) -#define __test_and_change_bit(X,Y) test_and_change_bit(X,Y) +/* "non-atomic" versions... */ +#define __set_bit(X,Y) \ +do { unsigned long __nr = (X); \ + long *__m = ((long *) (Y)) + (__nr >> 6); \ + *__m |= (1UL << (__nr & 63)); \ +} while (0) +#define __clear_bit(X,Y) \ +do { unsigned long __nr = (X); \ + long *__m = ((long *) (Y)) + (__nr >> 6); \ + *__m &= ~(1UL << (__nr & 63)); \ +} while (0) +#define __change_bit(X,Y) \ +do { unsigned long __nr = (X); \ + long *__m = ((long *) (Y)) + (__nr >> 6); \ + *__m ^= (1UL << (__nr & 63)); \ +} while (0) +#define __test_and_set_bit(X,Y) \ +({ unsigned long __nr = (X); \ + long *__m = ((long *) (Y)) + (__nr >> 6); \ + long __old = *__m; \ + long __mask = (1UL << (__nr & 63)); \ + *__m = (__old | __mask); \ + ((__old & __mask) != 0); \ +}) +#define __test_and_clear_bit(X,Y) \ +({ unsigned long __nr = (X); \ + long *__m = ((long *) (Y)) + (__nr >> 6); \ + long __old = *__m; \ + long __mask = (1UL << (__nr & 63)); \ + *__m = (__old & ~__mask); \ + ((__old & __mask) != 0); \ +}) +#define __test_and_change_bit(X,Y) \ +({ unsigned long __nr = (X); \ + long *__m = ((long *) (Y)) + (__nr >> 6); \ + long __old = *__m; \ + long __mask = (1UL << (__nr & 63)); \ + *__m = (__old ^ __mask); \ + ((__old & __mask) != 0); \ +}) #define smp_mb__before_clear_bit() do { } while(0) #define smp_mb__after_clear_bit() do { } while(0) diff -u --recursive --new-file v2.4.5/linux/include/asm-sparc64/hardirq.h linux/include/asm-sparc64/hardirq.h --- v2.4.5/linux/include/asm-sparc64/hardirq.h Wed Aug 23 09:30:13 2000 +++ linux/include/asm-sparc64/hardirq.h Tue Jun 12 11:08:46 2001 @@ -13,8 +13,8 @@ /* entry.S is sensitive to the offsets of these fields */ typedef struct { - unsigned int __softirq_active; - unsigned int __softirq_mask; + unsigned int __softirq_pending; + unsigned int __unused_1; #ifndef CONFIG_SMP unsigned int __local_irq_count; #else diff -u --recursive --new-file v2.4.5/linux/include/asm-sparc64/linux_logo.h linux/include/asm-sparc64/linux_logo.h --- v2.4.5/linux/include/asm-sparc64/linux_logo.h Tue Aug 4 16:03:35 1998 +++ linux/include/asm-sparc64/linux_logo.h Tue Jun 12 11:08:46 2001 @@ -1,4 +1,4 @@ -/* $Id: linux_logo.h,v 1.6 1998/07/30 16:30:48 jj Exp $ +/* $Id: linux_logo.h,v 1.7 2001/06/08 23:01:58 davem Exp $ * include/asm-sparc64/linux_logo.h: This is a linux logo * to be displayed on boot. * @@ -23,1025 +23,912 @@ #define linux_logo_banner "Linux/UltraSPARC version " UTS_RELEASE -#define LINUX_LOGO_COLORS 219 +#define __HAVE_ARCH_LINUX_LOGO +#define __HAVE_ARCH_LINUX_LOGO16 + +#define LINUX_LOGO_COLORS 221 #ifdef INCLUDE_LINUX_LOGO_DATA unsigned char linux_logo_red[] __initdata = { - 0x03, 0x9E, 0xEC, 0xEE, 0xC4, 0xDA, 0x50, 0xC9, - 0xC5, 0xED, 0x65, 0xE3, 0xE3, 0xF4, 0x24, 0xA4, - 0xEC, 0xEE, 0x94, 0xE5, 0xE3, 0x6A, 0xA6, 0xC4, - 0xDC, 0xE5, 0x13, 0xF3, 0xD1, 0xFD, 0xE2, 0xDB, - 0xA0, 0xC2, 0xEC, 0xB8, 0xC2, 0xD5, 0xF2, 0xF4, - 0xC5, 0x3E, 0xF1, 0x1B, 0x55, 0xF5, 0xCF, 0xF7, - 0xA9, 0xB4, 0xEB, 0x6C, 0x0A, 0x74, 0xB4, 0xF7, - 0xF0, 0xF5, 0xD4, 0xF2, 0xCE, 0xF5, 0xC7, 0x26, - 0x5B, 0xF4, 0xBC, 0x7F, 0xAB, 0x82, 0x94, 0xE5, - 0xFC, 0x3A, 0xF2, 0xFD, 0xF0, 0x1C, 0xEF, 0xD4, - 0xF3, 0x0F, 0xED, 0xF7, 0xC9, 0x49, 0xC3, 0xBA, - 0xC8, 0xD4, 0xE7, 0xF3, 0xF5, 0xA7, 0xEC, 0xF9, - 0xFA, 0x0A, 0xF5, 0xCF, 0xFC, 0xEA, 0xE1, 0xA6, - 0xD6, 0xBC, 0xF8, 0xF7, 0xB4, 0xEB, 0xDC, 0x84, - 0xCE, 0xBA, 0x45, 0xD6, 0x86, 0x50, 0x96, 0xC6, - 0x8C, 0x6E, 0xE8, 0x60, 0x3C, 0x70, 0xF0, 0x93, - 0x7C, 0xDA, 0xDA, 0x9C, 0xBA, 0x6D, 0x4D, 0x2B, - 0x2F, 0x8B, 0xE0, 0xCC, 0xDA, 0x5C, 0x3D, 0xEE, - 0xDB, 0x46, 0xAC, 0x96, 0xCE, 0xD1, 0xE3, 0xF1, - 0x96, 0x7A, 0x80, 0xB2, 0xBA, 0xB6, 0xD2, 0x1E, - 0x7E, 0xAA, 0xC4, 0xF0, 0x96, 0x65, 0x9E, 0xC2, - 0xAA, 0xF5, 0xF2, 0xE9, 0xE6, 0xD1, 0x35, 0xC7, - 0xF6, 0xB6, 0xE8, 0x82, 0xBE, 0xC2, 0xF2, 0x9E, - 0xC7, 0xB4, 0x0F, 0xF7, 0xE8, 0xD8, 0xCC, 0x9C, - 0xD8, 0xD8, 0xA0, 0xEA, 0xC6, 0xA8, 0xE0, 0xEC, - 0xD1, 0xF7, 0xF4, 0xFC, 0x75, 0xBD, 0xDC, 0xDD, - 0xCC, 0xE1, 0xFA, 0xEE, 0xAA, 0xEC, 0xF2, 0xB8, - 0xE2, 0xCD, 0x87 + 0x00, 0x06, 0x0a, 0x0e, 0x16, 0x1a, 0x1e, 0x22, + 0x12, 0x00, 0x2a, 0x36, 0x42, 0x4e, 0x4a, 0x56, + 0x26, 0x46, 0x2e, 0x32, 0x52, 0x3a, 0x02, 0x65, + 0x5e, 0x3e, 0x74, 0x8a, 0xa2, 0x9a, 0x86, 0xc6, + 0xc3, 0x65, 0xbb, 0xd2, 0xda, 0xd6, 0xe2, 0xf6, + 0xfd, 0xae, 0x7b, 0xdd, 0xea, 0x6a, 0xaa, 0xe7, + 0xbe, 0x5a, 0xee, 0x9e, 0x95, 0x80, 0x76, 0x79, + 0x62, 0x36, 0x9a, 0xe2, 0xec, 0xe1, 0xb8, 0xd7, + 0xaf, 0x25, 0xbc, 0xc0, 0xef, 0xea, 0xe8, 0xe8, + 0xf5, 0xf1, 0xda, 0xd3, 0x79, 0xdb, 0xf4, 0xf6, + 0xf6, 0xf6, 0xe2, 0x3d, 0xb4, 0xce, 0xe6, 0xee, + 0xf6, 0x68, 0xd8, 0xec, 0xf5, 0xc6, 0xc8, 0x9c, + 0x89, 0xd2, 0xee, 0xcb, 0xb9, 0xd2, 0x66, 0x5e, + 0x8b, 0xbe, 0xa8, 0xd5, 0xca, 0xb6, 0xae, 0x9c, + 0xc5, 0xbe, 0xbe, 0xca, 0x90, 0xb2, 0x9a, 0xa8, + 0xb6, 0xf2, 0xce, 0xfa, 0xb2, 0x6e, 0xa6, 0xfe, + 0xf6, 0xec, 0xfe, 0xd2, 0xea, 0xf5, 0xf2, 0xf2, + 0xe9, 0xee, 0xf6, 0xf2, 0xee, 0xf6, 0xda, 0xd4, + 0xfa, 0xca, 0xf2, 0xf6, 0xfe, 0xf2, 0xda, 0xe4, + 0xf6, 0xdd, 0xf2, 0xee, 0xfa, 0xf0, 0x12, 0x4a, + 0xd6, 0xf2, 0x8e, 0xf2, 0xf6, 0xf6, 0xb5, 0xf1, + 0x26, 0x9a, 0xea, 0xf6, 0xe0, 0xd2, 0x16, 0x9a, + 0x2e, 0xd2, 0x70, 0xd6, 0x46, 0x7c, 0xb4, 0x62, + 0xda, 0xee, 0xd6, 0xa3, 0x74, 0xa7, 0xa2, 0xe0, + 0xae, 0xbe, 0xce, 0xe2, 0xa3, 0x8e, 0x6d, 0x8e, + 0x32, 0xaf, 0x50, 0x9e, 0x5b, 0x8a, 0x98, 0x82, + 0x7a, 0x82, 0x56, 0x7c, 0x8a, 0x56, 0x5e, 0x86, + 0x6a, 0x52, 0x59, 0x64, 0x5e, }; unsigned char linux_logo_green[] __initdata = { - 0x03, 0x88, 0xC4, 0xE2, 0x85, 0xC2, 0x44, 0xA3, - 0xA9, 0xD3, 0x65, 0xA6, 0xC5, 0xF3, 0x24, 0xA4, - 0xB4, 0xD6, 0x63, 0xD5, 0xB7, 0x44, 0x86, 0x94, - 0xC2, 0xE4, 0x14, 0xB6, 0xD2, 0xFB, 0xD4, 0xB2, - 0x73, 0x96, 0xDB, 0x92, 0xC2, 0x95, 0xC2, 0xDA, - 0xA4, 0x36, 0xD4, 0x0E, 0x55, 0xF4, 0xC4, 0xE9, - 0x75, 0xB4, 0xBC, 0x52, 0x0A, 0x74, 0x84, 0xEB, - 0xDC, 0xDA, 0xA2, 0xD6, 0x9B, 0xBD, 0xB7, 0x12, - 0x44, 0xCA, 0x8C, 0x65, 0x7B, 0x54, 0x94, 0xAB, - 0xF4, 0x25, 0xC4, 0xFD, 0xE4, 0x1C, 0xDD, 0xAB, - 0xBD, 0x06, 0xCB, 0xD6, 0xCA, 0x33, 0x8C, 0xA2, - 0x92, 0x9C, 0xBC, 0xDB, 0xCD, 0x6E, 0xEC, 0xEE, - 0xBC, 0x03, 0xDA, 0xCE, 0xF4, 0xB6, 0xDB, 0x92, - 0xAD, 0xBC, 0xDE, 0xD5, 0x7B, 0xAE, 0x9D, 0x84, - 0xB6, 0x96, 0x44, 0xBA, 0x6E, 0x3C, 0x7A, 0xB2, - 0x8C, 0x4C, 0xCE, 0x4C, 0x3C, 0x5A, 0xCA, 0x6D, - 0x7C, 0xCE, 0xDA, 0x9C, 0xAA, 0x6D, 0x4D, 0x2B, - 0x1B, 0x5E, 0xCB, 0xAC, 0xBE, 0x5C, 0x2E, 0xDC, - 0xBD, 0x3E, 0xAC, 0x82, 0xB6, 0xBE, 0xD3, 0xBD, - 0x72, 0x62, 0x6C, 0x82, 0x92, 0x9E, 0xB0, 0x13, - 0x4A, 0x8E, 0xBE, 0xCE, 0x86, 0x45, 0x6B, 0xAA, - 0x9A, 0xC5, 0xC6, 0xDA, 0xC5, 0xC4, 0x34, 0x9B, - 0xCC, 0xAC, 0xC4, 0x76, 0x9A, 0x9E, 0xEE, 0x62, - 0xC6, 0x76, 0x0D, 0xE4, 0xDA, 0xD5, 0xA5, 0x92, - 0xCD, 0xB2, 0x7C, 0xCC, 0xBE, 0x7E, 0xDC, 0xD6, - 0xB9, 0xE3, 0xD4, 0xF6, 0x55, 0x82, 0xA4, 0xAA, - 0x8D, 0xBB, 0xCE, 0xD5, 0x8A, 0xDB, 0xD4, 0x8B, - 0xCA, 0x93, 0x63 + 0x00, 0x06, 0x0a, 0x0e, 0x16, 0x1a, 0x1e, 0x22, + 0x12, 0x00, 0x2a, 0x36, 0x42, 0x4e, 0x4a, 0x56, + 0x26, 0x46, 0x2e, 0x32, 0x52, 0x3a, 0x02, 0x65, + 0x5e, 0x3e, 0x74, 0x8a, 0xa2, 0x9a, 0x86, 0xc6, + 0xc3, 0x62, 0xbb, 0xd2, 0xda, 0xd6, 0xe2, 0xf6, + 0xfd, 0xae, 0x7b, 0xdd, 0xea, 0x6a, 0xaa, 0xe7, + 0xbe, 0x5a, 0xee, 0x9e, 0x95, 0x80, 0x62, 0x5c, + 0x4e, 0x26, 0x72, 0xaa, 0xba, 0xaf, 0x90, 0xae, + 0x92, 0x1a, 0xa4, 0x85, 0xb6, 0xbe, 0xc3, 0xc8, + 0xcf, 0xd0, 0xc2, 0xce, 0x57, 0xa2, 0xd6, 0xda, + 0xda, 0xd7, 0xb8, 0x2a, 0x7b, 0x91, 0xae, 0xca, + 0xda, 0x45, 0x9e, 0xb2, 0xd7, 0x9b, 0x90, 0x76, + 0x5c, 0xa2, 0xbe, 0xa6, 0x85, 0x96, 0x4e, 0x46, + 0x66, 0x92, 0x7a, 0x9a, 0x96, 0x9d, 0x9a, 0x6b, + 0x8a, 0x8e, 0xb2, 0xca, 0x90, 0xa6, 0x79, 0x7c, + 0xb6, 0xf2, 0xce, 0xfa, 0xb2, 0x6e, 0xa6, 0xfa, + 0xea, 0xd7, 0xf6, 0xbc, 0xda, 0xde, 0xda, 0xe6, + 0xca, 0xd8, 0xea, 0xe0, 0xcc, 0xf2, 0xce, 0xb2, + 0xee, 0xa2, 0xd6, 0xe6, 0xf6, 0xd7, 0xc5, 0xb8, + 0xc6, 0xb9, 0xce, 0xde, 0xce, 0xc6, 0x0e, 0x36, + 0xae, 0xbe, 0x86, 0xba, 0xbe, 0xe6, 0x8e, 0xc4, + 0x1e, 0x8e, 0xae, 0xba, 0xb2, 0xa6, 0x12, 0x7a, + 0x20, 0xc6, 0x64, 0xaa, 0x2f, 0x70, 0x85, 0x46, + 0xce, 0xd6, 0xa6, 0x6e, 0x51, 0x72, 0x92, 0xa6, + 0x87, 0x96, 0xa2, 0xd6, 0x85, 0x7a, 0x6a, 0x6e, + 0x22, 0x76, 0x36, 0x76, 0x3c, 0x6e, 0x63, 0x53, + 0x66, 0x62, 0x42, 0x50, 0x56, 0x42, 0x56, 0x56, + 0x56, 0x3e, 0x51, 0x52, 0x56, }; unsigned char linux_logo_blue[] __initdata = { - 0x04, 0x28, 0x10, 0x8C, 0x0B, 0x84, 0x14, 0x1A, - 0x77, 0x1F, 0x64, 0x0E, 0x85, 0xD2, 0x24, 0xA4, - 0x0F, 0x54, 0x0C, 0x7C, 0x3F, 0x04, 0x20, 0x0D, - 0x54, 0xDF, 0x14, 0x0D, 0xD1, 0xE9, 0xB0, 0x11, - 0x0A, 0x40, 0x57, 0x14, 0xC3, 0x0C, 0x04, 0x12, - 0x50, 0x0C, 0x7D, 0x05, 0x55, 0xF2, 0xBA, 0xC7, - 0x09, 0xB4, 0x0E, 0x24, 0x0B, 0x74, 0x0C, 0xB6, - 0x80, 0x48, 0x10, 0x34, 0x0F, 0x0C, 0xA0, 0x04, - 0x19, 0x10, 0x0E, 0x14, 0x0E, 0x05, 0x94, 0x0E, - 0xCA, 0x0B, 0x46, 0xFB, 0xB4, 0x1C, 0x9B, 0x1A, - 0x21, 0x09, 0x14, 0x4D, 0xCB, 0x08, 0x11, 0x7C, - 0x20, 0x10, 0x24, 0x66, 0x79, 0x07, 0xEA, 0xC9, - 0x0C, 0x08, 0x38, 0xC4, 0xD8, 0x24, 0xBE, 0x6C, - 0x51, 0xBB, 0x8C, 0x36, 0x0A, 0x0F, 0x0C, 0x84, - 0x3C, 0x54, 0x44, 0x7C, 0x28, 0x0E, 0x28, 0x7F, - 0x8C, 0x0F, 0x54, 0x24, 0x3C, 0x18, 0x54, 0x17, - 0x7C, 0x9C, 0xDA, 0x9C, 0x7C, 0x6C, 0x4D, 0x2C, - 0x09, 0x0E, 0x8A, 0x50, 0x4C, 0x5B, 0x14, 0xAC, - 0x19, 0x3C, 0xAC, 0x5C, 0x64, 0x97, 0x94, 0x37, - 0x29, 0x3C, 0x44, 0x3C, 0x2C, 0x7C, 0x70, 0x07, - 0x04, 0x29, 0xB2, 0x64, 0x74, 0x07, 0x07, 0x2C, - 0x74, 0x2E, 0x6C, 0xA4, 0x29, 0x9E, 0x34, 0x27, - 0x2F, 0x98, 0x48, 0x5C, 0x0C, 0x5C, 0xE8, 0x04, - 0xC2, 0x0C, 0x0A, 0xB2, 0x74, 0xCB, 0x46, 0x78, - 0xB4, 0x5C, 0x18, 0x80, 0x8C, 0x24, 0xD9, 0xAC, - 0x87, 0x99, 0x1D, 0xE8, 0x14, 0x0D, 0x10, 0x17, - 0x0A, 0x67, 0x3C, 0x68, 0x3C, 0x69, 0x90, 0x22, - 0x6C, 0x0D, 0x17 + 0x00, 0x06, 0x0a, 0x0e, 0x16, 0x1a, 0x1e, 0x22, + 0x12, 0x01, 0x2a, 0x36, 0x42, 0x4e, 0x4a, 0x56, + 0x26, 0x46, 0x2e, 0x32, 0x52, 0x3a, 0x06, 0x65, + 0x5e, 0x3e, 0x74, 0x8a, 0xa2, 0x9a, 0x86, 0xc6, + 0xc3, 0x59, 0xbb, 0xd2, 0xda, 0xd6, 0xe2, 0xf6, + 0xfd, 0xae, 0x7b, 0xdd, 0xea, 0x6a, 0xaa, 0xe7, + 0xbe, 0x5a, 0xee, 0x9e, 0x95, 0x80, 0x2e, 0x08, + 0x0a, 0x06, 0x0a, 0x0b, 0x0b, 0x0f, 0x0c, 0x0f, + 0x3d, 0x09, 0x73, 0x09, 0x0d, 0x0a, 0x10, 0x1e, + 0x2d, 0x13, 0x86, 0xba, 0x19, 0x0a, 0x36, 0x3c, + 0x26, 0x14, 0x0d, 0x06, 0x07, 0x0a, 0x0b, 0x0f, + 0x4a, 0x06, 0x0a, 0x0c, 0x2b, 0x0a, 0x0b, 0x0a, + 0x06, 0x0a, 0x0a, 0x11, 0x0b, 0x0a, 0x0a, 0x1e, + 0x0f, 0x0d, 0x0a, 0x0b, 0x22, 0x6a, 0x72, 0x0b, + 0x0b, 0x22, 0x90, 0xca, 0x90, 0x92, 0x3c, 0x2c, + 0xb6, 0xf2, 0xce, 0xfa, 0xb2, 0x6e, 0xa6, 0xea, + 0xb6, 0x7c, 0xda, 0x8e, 0xa6, 0x87, 0x66, 0xb6, + 0x81, 0x6a, 0xc6, 0x9a, 0x5b, 0xd2, 0xb6, 0x6a, + 0xca, 0x45, 0x92, 0xb2, 0xca, 0x52, 0x8a, 0x3e, + 0x2e, 0x66, 0x66, 0xae, 0x3e, 0x47, 0x06, 0x0e, + 0x52, 0x36, 0x6a, 0x0e, 0x0e, 0xbe, 0x2c, 0x0e, + 0x0a, 0x5a, 0x0d, 0x0e, 0x3e, 0x0a, 0x06, 0x2e, + 0x06, 0x9e, 0x4e, 0x36, 0x06, 0x58, 0x24, 0x06, + 0x9e, 0xae, 0x3a, 0x08, 0x08, 0x07, 0x5e, 0x0a, + 0x32, 0x2e, 0x2a, 0xb2, 0x43, 0x48, 0x5f, 0x2e, + 0x06, 0x06, 0x07, 0x24, 0x06, 0x32, 0x06, 0x06, + 0x46, 0x2e, 0x22, 0x06, 0x06, 0x1e, 0x4c, 0x06, + 0x3a, 0x22, 0x42, 0x34, 0x42, }; unsigned char linux_logo[] __initdata = { - 0xD8, 0xA3, 0x98, 0x98, 0xA3, 0xB2, 0x2F, 0x2F, - 0xA3, 0x66, 0x98, 0x98, 0x98, 0xA3, 0x2F, 0xA3, - 0x98, 0x55, 0xA0, 0xA3, 0xB2, 0x51, 0x51, 0x2F, - 0x98, 0x55, 0x8F, 0x2F, 0x89, 0x44, 0x89, 0x51, - 0xB2, 0x2F, 0x66, 0xA3, 0x2F, 0x2F, 0x66, 0x66, - 0xA3, 0xB2, 0xB2, 0xB2, 0x89, 0xD8, 0x44, 0x44, - 0xD8, 0x83, 0xD8, 0xA3, 0x98, 0x98, 0xA3, 0xB2, - 0x2F, 0x2F, 0xA3, 0x66, 0x98, 0x98, 0x98, 0xA3, - 0x2F, 0xA3, 0x98, 0x55, 0xA0, 0xA3, 0xB2, 0x51, - 0x51, 0x2F, 0x98, 0x55, 0x8F, 0x2F, 0x89, 0x44, - 0xA3, 0x55, 0x55, 0x98, 0x2F, 0x2F, 0x2F, 0xA3, - 0x66, 0x66, 0x98, 0x98, 0x66, 0x66, 0x66, 0x98, - 0x55, 0xA5, 0x8F, 0xA3, 0x51, 0x51, 0xB2, 0x2F, - 0x66, 0x66, 0xA3, 0x51, 0x89, 0x51, 0xB2, 0x2F, - 0x2F, 0xA3, 0x66, 0xA3, 0xA3, 0xA3, 0x2F, 0x2F, - 0xB2, 0xB2, 0x2F, 0x2F, 0xB2, 0x51, 0x51, 0x51, - 0x51, 0x51, 0xA3, 0x55, 0x55, 0x98, 0x2F, 0x2F, - 0x2F, 0xA3, 0x66, 0x66, 0x98, 0x98, 0x66, 0x66, - 0x66, 0x98, 0x55, 0xA5, 0x8F, 0xA3, 0x51, 0x51, - 0xB2, 0x2F, 0x66, 0x66, 0xA3, 0x51, 0x89, 0x51, - 0x98, 0xA5, 0x55, 0x8F, 0x2F, 0xB2, 0x2F, 0xA3, - 0x66, 0x66, 0x98, 0x8F, 0x66, 0x66, 0x66, 0x98, - 0xA0, 0x8F, 0xA3, 0xB2, 0x51, 0x51, 0xB2, 0x2F, - 0xA3, 0xA3, 0x2F, 0xB2, 0x51, 0xB2, 0x2F, 0x2F, - 0xA3, 0x66, 0x98, 0xA3, 0x51, 0xB2, 0x2F, 0xA3, - 0xB2, 0x51, 0x51, 0xB2, 0xB2, 0x51, 0xB2, 0xB2, - 0xB2, 0x2F, 0x98, 0xA5, 0x55, 0x8F, 0x2F, 0xB2, - 0x2F, 0xA3, 0x66, 0x66, 0x98, 0x8F, 0x66, 0x66, - 0x66, 0x98, 0xA0, 0x8F, 0xA3, 0xB2, 0x51, 0x51, - 0xB2, 0x2F, 0xA3, 0xA3, 0x2F, 0x51, 0x51, 0xB2, - 0xA0, 0xA5, 0x55, 0x66, 0xB2, 0x51, 0xB2, 0xA3, - 0x66, 0x66, 0x98, 0x66, 0x66, 0x66, 0x98, 0x98, - 0x66, 0xA3, 0x2F, 0xB2, 0x51, 0x51, 0xB2, 0xA3, - 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0xA3, - 0x66, 0x98, 0xB2, 0x4C, 0x54, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0xCE, 0x2F, 0xB2, 0x2F, 0x2F, - 0xA3, 0x98, 0xA0, 0xA5, 0x55, 0x66, 0xB2, 0x51, - 0xB2, 0xA3, 0x66, 0x66, 0x98, 0x66, 0x66, 0x66, - 0x98, 0x98, 0x66, 0xA3, 0x2F, 0xB2, 0x51, 0x51, - 0xB2, 0xA3, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, 0x2F, - 0xA0, 0xA0, 0x8F, 0xA3, 0xB2, 0x51, 0xB2, 0x2F, - 0x66, 0x66, 0x98, 0x66, 0x66, 0x66, 0x66, 0x66, - 0xA3, 0x2F, 0x51, 0x51, 0x51, 0xB2, 0x2F, 0xA3, - 0x66, 0x66, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, - 0x2F, 0xA0, 0xDA, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x9C, 0xB2, 0xA3, - 0x66, 0x98, 0xA0, 0xA0, 0x8F, 0xA3, 0xB2, 0x51, - 0xB2, 0x2F, 0x66, 0x66, 0x98, 0x66, 0x66, 0x66, - 0x66, 0x66, 0xA3, 0x2F, 0x51, 0x51, 0x51, 0xB2, - 0x2F, 0xA3, 0x66, 0x66, 0x66, 0xA3, 0xA3, 0xA3, - 0x8F, 0x8F, 0x66, 0x2F, 0x51, 0x51, 0xB2, 0xA3, - 0x66, 0x98, 0x98, 0x66, 0x66, 0x66, 0x2F, 0x2F, - 0xB2, 0x51, 0xB2, 0xB2, 0x2F, 0x2F, 0xA3, 0x66, - 0x66, 0x66, 0xA3, 0xA3, 0x2F, 0xA3, 0xA3, 0xB2, - 0x9C, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0xDA, 0x3A, 0x20, 0x54, 0x55, - 0xA3, 0x98, 0x8F, 0x8F, 0x66, 0x2F, 0x51, 0x51, - 0xB2, 0xA3, 0x66, 0x98, 0x98, 0x66, 0x66, 0x66, - 0x2F, 0x2F, 0xB2, 0x51, 0xB2, 0xB2, 0x2F, 0x2F, - 0xA3, 0x66, 0x66, 0x66, 0x2F, 0xA3, 0x2F, 0x2F, - 0x66, 0x66, 0xA3, 0x2F, 0xB2, 0xB2, 0x2F, 0x66, - 0x8F, 0x8F, 0x8F, 0x66, 0xA3, 0xA3, 0xB2, 0xB2, - 0xB2, 0xB2, 0xB2, 0xB2, 0x2F, 0xA3, 0xA3, 0xA3, - 0xA3, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0xAD, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0xA7, 0x4C, 0xCE, 0xDA, 0x20, - 0xA6, 0x2F, 0x66, 0x66, 0xA3, 0x2F, 0xB2, 0xB2, - 0x2F, 0x66, 0x8F, 0x8F, 0x8F, 0x66, 0xA3, 0xA3, - 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0x2F, 0xA3, - 0xA3, 0xA3, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, 0x2F, - 0xA3, 0x98, 0x66, 0x2F, 0xB2, 0xB2, 0x2F, 0x98, - 0x8F, 0x8F, 0x98, 0x66, 0xA3, 0xB2, 0xB2, 0xB2, - 0x2F, 0x2F, 0x2F, 0x2F, 0xA3, 0x2F, 0xA3, 0xA3, - 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0x51, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0xCE, 0x55, 0xAD, 0xA7, 0x54, - 0x20, 0x8F, 0xA3, 0x98, 0x66, 0x2F, 0xB2, 0xB2, - 0x2F, 0x98, 0x8F, 0x8F, 0x98, 0x66, 0xA3, 0xB2, - 0xB2, 0xB2, 0x2F, 0x2F, 0x2F, 0x2F, 0xA3, 0x2F, - 0xA3, 0xA3, 0xA3, 0x2F, 0xA3, 0xA3, 0xA3, 0xA3, - 0xA3, 0x8F, 0x66, 0x2F, 0xB2, 0x51, 0x2F, 0x98, - 0xA0, 0x8F, 0x66, 0xA3, 0x2F, 0x51, 0x51, 0xB2, - 0xA3, 0xA3, 0xA3, 0x2F, 0xA3, 0xA3, 0x66, 0x66, - 0x98, 0x98, 0x98, 0x66, 0x98, 0x66, 0x55, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0xCE, 0x4C, 0x9C, 0x2E, 0xDA, - 0x20, 0xDA, 0x51, 0x8F, 0x66, 0x2F, 0xB2, 0x51, - 0x2F, 0x98, 0xA0, 0x8F, 0x66, 0xA3, 0x2F, 0x51, - 0x51, 0xB2, 0xA3, 0xA3, 0xA3, 0x2F, 0xA3, 0xA3, - 0x66, 0x66, 0x98, 0x98, 0x98, 0x98, 0x98, 0x66, - 0x51, 0x66, 0x2F, 0xB2, 0x51, 0xB2, 0xA3, 0xA0, - 0xA0, 0x66, 0xA3, 0xB2, 0xB2, 0xB2, 0xB2, 0xA3, - 0x66, 0x66, 0x66, 0xA3, 0xA3, 0x66, 0x98, 0x98, - 0x98, 0x98, 0x98, 0x66, 0x66, 0xB2, 0x6D, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x6D, 0x3A, 0x20, 0x20, 0x20, - 0x20, 0x20, 0xA5, 0x66, 0x2F, 0xB2, 0x51, 0xB2, - 0xA3, 0xA0, 0xA0, 0x66, 0xA3, 0xB2, 0xB2, 0xB2, - 0xB2, 0xA3, 0x66, 0x66, 0x66, 0xA3, 0xA3, 0x66, - 0x98, 0x98, 0x8F, 0x98, 0x66, 0x66, 0x66, 0x66, - 0x51, 0x2F, 0xB2, 0x51, 0x51, 0x2F, 0x66, 0xA0, - 0x8F, 0xA3, 0x2F, 0xB2, 0xB2, 0x2F, 0x2F, 0x66, - 0x98, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x2F, 0xA3, 0x2F, 0x2F, 0x51, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0xDA, 0x51, 0xB2, 0x51, 0x51, 0x2F, - 0x66, 0xA0, 0x8F, 0xA3, 0x2F, 0xB2, 0xB2, 0x2F, - 0x2F, 0x66, 0x98, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0xA3, 0x2F, 0x2F, 0x2F, 0x2F, - 0x51, 0x2F, 0xB2, 0x51, 0x2F, 0xA3, 0x8F, 0x8F, - 0x98, 0xA3, 0xB2, 0xB2, 0x2F, 0xA3, 0x98, 0x66, - 0x98, 0x98, 0x66, 0x66, 0x66, 0x66, 0xA3, 0x2F, - 0xB2, 0xB2, 0x51, 0xB2, 0xB2, 0x66, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0xA3, 0xB2, 0x51, 0x2F, 0xA3, - 0x8F, 0x8F, 0x98, 0xA3, 0xB2, 0xB2, 0x2F, 0xA3, - 0x98, 0x66, 0x98, 0x98, 0x66, 0x66, 0x66, 0x66, - 0xA3, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, - 0xB2, 0x2F, 0xA3, 0x2F, 0x66, 0x98, 0x8F, 0x98, - 0xA3, 0x2F, 0x2F, 0xA3, 0x98, 0x98, 0x98, 0x98, - 0x66, 0x98, 0x66, 0x98, 0x66, 0xA3, 0x2F, 0xB2, - 0x51, 0x51, 0x51, 0xB2, 0xB2, 0x8F, 0x20, 0x20, - 0x20, 0x54, 0x6D, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x54, 0x6D, 0x6D, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x4C, 0xA3, 0x2F, 0x66, 0x98, - 0x8F, 0x98, 0xA3, 0x2F, 0x2F, 0xA3, 0x98, 0x98, - 0x98, 0x98, 0x66, 0x98, 0x66, 0x98, 0x66, 0xA3, - 0x2F, 0xB2, 0x51, 0x51, 0x51, 0xB2, 0x2F, 0x2F, - 0x2F, 0xA3, 0xA3, 0x66, 0x98, 0x98, 0x8F, 0x98, - 0x2F, 0x2F, 0x2F, 0x66, 0x8F, 0x8F, 0x98, 0xA3, - 0x66, 0x66, 0x8F, 0x98, 0x98, 0x66, 0x2F, 0xB2, - 0x51, 0xB2, 0x2F, 0xA3, 0xA3, 0xA0, 0x20, 0x20, - 0xDA, 0x2E, 0x3A, 0xA7, 0x20, 0x20, 0x20, 0x20, - 0x20, 0xCE, 0x2A, 0x2A, 0x2E, 0xA7, 0xDA, 0x20, - 0x20, 0x20, 0x20, 0x9C, 0xA3, 0x66, 0x98, 0x98, - 0x8F, 0x98, 0x2F, 0x2F, 0x2F, 0x66, 0x8F, 0x8F, - 0x98, 0xA3, 0x66, 0x66, 0x8F, 0x98, 0x98, 0x66, - 0x2F, 0xB2, 0x51, 0xB2, 0x2F, 0x2F, 0xA3, 0xA3, - 0xB2, 0xA3, 0x66, 0x98, 0x8F, 0x8F, 0x66, 0xA3, - 0x2F, 0x2F, 0x66, 0x98, 0x98, 0x66, 0x2F, 0x2F, - 0xA3, 0x98, 0x8F, 0x98, 0x66, 0x2F, 0xB2, 0xB2, - 0xB2, 0xA3, 0x66, 0x66, 0x66, 0x98, 0x20, 0x3A, - 0x98, 0x89, 0x8F, 0x6D, 0x20, 0x20, 0x20, 0x20, - 0x4C, 0x66, 0x51, 0x44, 0x51, 0x2E, 0x54, 0x20, - 0x20, 0x20, 0x20, 0xA7, 0x66, 0x98, 0x8F, 0x8F, - 0x66, 0xA3, 0x2F, 0x2F, 0x66, 0x98, 0x98, 0x66, - 0x2F, 0x2F, 0xA3, 0x98, 0x8F, 0x98, 0x66, 0x2F, - 0xB2, 0xB2, 0xB2, 0xA3, 0x66, 0x66, 0x66, 0xA3, - 0x2F, 0x66, 0x98, 0x8F, 0x8F, 0x98, 0x66, 0x2F, - 0x2F, 0xA3, 0x66, 0x98, 0x98, 0xA3, 0x2F, 0xB2, - 0xA3, 0x8F, 0x98, 0xA3, 0xB2, 0x51, 0x89, 0x89, - 0xB2, 0xA3, 0x66, 0x98, 0x66, 0x98, 0x20, 0xA6, - 0x44, 0x39, 0xE6, 0x98, 0x20, 0x20, 0x20, 0x9C, - 0x74, 0xD6, 0x7E, 0xD6, 0x39, 0x8F, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x2E, 0x98, 0x8F, 0x8F, 0x98, - 0x66, 0x2F, 0x2F, 0xA3, 0x66, 0x98, 0x98, 0xA3, - 0x2F, 0xB2, 0x66, 0x98, 0x8F, 0xA3, 0xB2, 0x51, - 0x89, 0x89, 0xB2, 0xA3, 0x66, 0x98, 0x66, 0x66, - 0x2F, 0x66, 0x8F, 0xA0, 0x8F, 0x98, 0xA3, 0xB2, - 0x2F, 0x66, 0x66, 0x66, 0xA3, 0x2F, 0x2F, 0x2F, - 0x66, 0x98, 0xA3, 0xB2, 0x89, 0x44, 0x89, 0x51, - 0x2F, 0x66, 0x98, 0x98, 0xA3, 0x66, 0x20, 0x2F, - 0x2F, 0xAD, 0x89, 0xD6, 0x3A, 0x20, 0x20, 0x55, - 0x6B, 0x51, 0x6D, 0x4C, 0xD8, 0xD6, 0x2E, 0x20, - 0x20, 0x20, 0x20, 0x54, 0x8F, 0xA0, 0x8F, 0x98, - 0xA3, 0xB2, 0x2F, 0x66, 0x66, 0x66, 0xA3, 0x2F, - 0xB2, 0x2F, 0x66, 0x66, 0xA3, 0xB2, 0x89, 0x44, - 0x89, 0x51, 0x2F, 0x66, 0x98, 0x98, 0xA3, 0xA3, - 0xA3, 0x66, 0x8F, 0xA0, 0x8F, 0x66, 0x2F, 0xB2, - 0xA3, 0x66, 0x98, 0x66, 0xA3, 0x2F, 0x2F, 0xA3, - 0xA3, 0x2F, 0xB2, 0x89, 0xD8, 0xD8, 0x51, 0x66, - 0x8F, 0xA0, 0xA0, 0x8F, 0x98, 0xA3, 0x20, 0x44, - 0xA7, 0xCE, 0xA6, 0x4D, 0xCE, 0x6D, 0xA7, 0xA0, - 0x6B, 0xA7, 0x20, 0x92, 0xAD, 0x6B, 0x4C, 0x20, - 0x20, 0x20, 0x20, 0x54, 0x98, 0xA0, 0x8F, 0x66, - 0x2F, 0xB2, 0xA3, 0x66, 0x98, 0x66, 0xA3, 0x2F, - 0x2F, 0xA3, 0xA3, 0xA3, 0xB2, 0x89, 0xD8, 0xD8, - 0x51, 0x66, 0x8F, 0xA0, 0xA0, 0x8F, 0x98, 0x66, - 0x66, 0x66, 0x8F, 0x55, 0x8F, 0xA3, 0xB2, 0xB2, - 0xA3, 0x66, 0x66, 0xA3, 0x2F, 0xA3, 0xA3, 0xA3, - 0xA3, 0xB2, 0x89, 0x44, 0x44, 0x51, 0x66, 0xA0, - 0x55, 0xA5, 0x55, 0x8F, 0x66, 0xA3, 0x20, 0x44, - 0x6D, 0x54, 0xA7, 0x74, 0x2E, 0x4B, 0xBF, 0x9C, - 0x7E, 0xDA, 0x20, 0x54, 0x2E, 0x6B, 0x2A, 0x20, - 0x20, 0x20, 0x20, 0x3A, 0x8F, 0x55, 0x8F, 0xA3, - 0xB2, 0xB2, 0xA3, 0x66, 0x66, 0xA3, 0xA3, 0x2F, - 0xA3, 0xA3, 0xA3, 0xB2, 0x89, 0x44, 0x44, 0x51, - 0x66, 0xA0, 0xA5, 0xA5, 0x55, 0x8F, 0x66, 0x66, - 0xA0, 0xA0, 0xA0, 0xA0, 0x8F, 0xA3, 0x2F, 0xB2, - 0x66, 0x98, 0xA3, 0x2F, 0x2F, 0xB2, 0x2F, 0x2F, - 0xB2, 0x51, 0x89, 0x89, 0xB2, 0x98, 0xA0, 0x2A, - 0xA5, 0x55, 0x98, 0x66, 0xA3, 0xB2, 0x20, 0x2F, - 0x4C, 0x20, 0x4B, 0xBB, 0xCF, 0x6F, 0x27, 0x36, - 0x93, 0xCE, 0x20, 0x20, 0xA6, 0x3D, 0x4C, 0x20, - 0x20, 0x20, 0x20, 0xDA, 0xA0, 0xA0, 0x8F, 0xA3, - 0x2F, 0xB2, 0x66, 0x98, 0xA3, 0x2F, 0xB2, 0x2F, - 0x2F, 0x2F, 0xB2, 0x51, 0x89, 0x89, 0xB2, 0x98, - 0xA0, 0x2A, 0xA5, 0xA0, 0x8F, 0x66, 0xA3, 0xA3, - 0xA0, 0x8F, 0x8F, 0xA0, 0x8F, 0xA3, 0xB2, 0x2F, - 0x66, 0x98, 0x2F, 0xB2, 0xB2, 0xB2, 0xB2, 0x2F, - 0xB2, 0x89, 0x44, 0x51, 0x66, 0x55, 0xAD, 0x2A, - 0x55, 0x8F, 0x66, 0xA3, 0x2F, 0xB2, 0x20, 0x2A, - 0xE6, 0x95, 0xE5, 0x5A, 0x52, 0x52, 0x3F, 0x27, - 0x22, 0xC7, 0x9D, 0x60, 0xA2, 0xA2, 0x3A, 0x20, - 0x20, 0x20, 0x20, 0x54, 0x66, 0xA0, 0x8F, 0xA3, - 0xB2, 0x2F, 0x66, 0x98, 0x2F, 0xB2, 0xB2, 0xB2, - 0xB2, 0x2F, 0xB2, 0x89, 0x44, 0x51, 0x66, 0x55, - 0x2A, 0x2A, 0xA5, 0x8F, 0x66, 0xA3, 0x2F, 0x2F, - 0xA3, 0xA3, 0x66, 0x98, 0x98, 0x2F, 0xB2, 0xB2, - 0xA3, 0xA3, 0x2F, 0x51, 0x51, 0x51, 0x2F, 0x2F, - 0x51, 0x89, 0x89, 0x2F, 0x8F, 0x2A, 0x2A, 0xA5, - 0x8F, 0x66, 0xA3, 0xB2, 0x2F, 0x51, 0x20, 0x6D, - 0x77, 0xF7, 0xEE, 0x30, 0xB0, 0x72, 0x72, 0x5B, - 0x82, 0xEA, 0x72, 0xB0, 0x90, 0x96, 0x71, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x2F, 0x98, 0x98, 0x2F, - 0xB2, 0xB2, 0x66, 0xA3, 0x2F, 0x51, 0x51, 0xB2, - 0xB2, 0x2F, 0x51, 0x89, 0x89, 0x2F, 0x8F, 0x2A, - 0xAD, 0xA5, 0x98, 0x66, 0xA3, 0xB2, 0x2F, 0xB2, - 0xD8, 0xB2, 0xA3, 0x98, 0x98, 0x2F, 0xB2, 0xB2, - 0x66, 0xA3, 0xB2, 0x51, 0x51, 0xB2, 0x2F, 0xA3, - 0x51, 0x89, 0x89, 0xA3, 0xA0, 0x2A, 0xA5, 0x8F, - 0x66, 0xA3, 0x2F, 0xB2, 0xB2, 0x51, 0x20, 0x69, - 0x64, 0xF9, 0x3F, 0x52, 0x52, 0x72, 0x29, 0x82, - 0x47, 0x47, 0x47, 0x8B, 0x72, 0xB7, 0x60, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x2F, 0x98, 0x98, 0x2F, - 0xB2, 0xB2, 0xA3, 0xA3, 0xB2, 0x89, 0x51, 0x2F, - 0x2F, 0xA3, 0x51, 0x89, 0x89, 0xA3, 0xA0, 0x2A, - 0xA5, 0x8F, 0x66, 0xA3, 0x2F, 0xB2, 0xB2, 0xB2, - 0xDD, 0xA3, 0x66, 0x98, 0x66, 0x2F, 0xB2, 0xB2, - 0xA3, 0xA3, 0xB2, 0x51, 0xB2, 0x2F, 0xA3, 0x2F, - 0xB2, 0x89, 0xB2, 0x66, 0xA0, 0xA5, 0x8F, 0x98, - 0x66, 0x66, 0xB2, 0x51, 0x51, 0x51, 0x81, 0xFA, - 0x62, 0xEE, 0x30, 0x52, 0x22, 0x72, 0x82, 0x82, - 0x47, 0x47, 0xEA, 0x3F, 0x37, 0x6F, 0x26, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x2A, 0x98, 0x66, 0x2F, - 0x51, 0xB2, 0xA3, 0x66, 0xB2, 0x51, 0x51, 0xB2, - 0xA3, 0x2F, 0xB2, 0x89, 0xB2, 0x66, 0x55, 0x55, - 0x8F, 0x98, 0x66, 0xA3, 0xB2, 0x51, 0x51, 0xB2, - 0x74, 0xA0, 0x8F, 0x98, 0x66, 0xB2, 0xB2, 0xB2, - 0xA3, 0xA3, 0x2F, 0x51, 0x51, 0x2F, 0xA3, 0x2F, - 0xB2, 0x51, 0xA3, 0x98, 0xA0, 0x55, 0xA0, 0xA0, - 0x8F, 0x66, 0x2F, 0x51, 0xB2, 0x51, 0x54, 0xA9, - 0x62, 0xEF, 0x52, 0x22, 0x72, 0x29, 0xEA, 0xEA, - 0x29, 0x22, 0x37, 0x37, 0x8E, 0xCF, 0x49, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x6D, 0x2F, 0x66, 0x2F, - 0x51, 0xB2, 0xA3, 0x66, 0x2F, 0xB2, 0xB2, 0x2F, - 0xA3, 0x2F, 0xB2, 0x51, 0x2F, 0x98, 0xA0, 0x55, - 0xA0, 0xA0, 0x8F, 0x66, 0x2F, 0x51, 0xB2, 0xA3, - 0xA3, 0x2A, 0xA5, 0x98, 0xA3, 0x2F, 0xB2, 0x2F, - 0x66, 0x66, 0x2F, 0xB2, 0xB2, 0xB2, 0x2F, 0x2F, - 0xB2, 0x2F, 0xA3, 0x8F, 0xA0, 0xA0, 0xA0, 0xA0, - 0x8F, 0xA3, 0x51, 0x51, 0x2F, 0xB2, 0x54, 0xA8, - 0x65, 0x5C, 0x52, 0x22, 0x29, 0x29, 0x29, 0xB0, - 0x62, 0x56, 0xF9, 0x79, 0xF9, 0xBB, 0x4B, 0x20, - 0x6D, 0xA5, 0x2E, 0x20, 0x20, 0xA3, 0xA3, 0x2F, - 0xB2, 0x2F, 0xA3, 0x66, 0x2F, 0xB2, 0xB2, 0xB2, - 0x2F, 0x2F, 0xB2, 0x2F, 0x66, 0x8F, 0xA0, 0xA0, - 0x55, 0xA0, 0x8F, 0xA3, 0x51, 0x51, 0x2F, 0xA3, - 0xA0, 0x2A, 0x55, 0x66, 0xA3, 0x2F, 0xB2, 0xB2, - 0xA3, 0x66, 0xA3, 0xB2, 0xB2, 0xB2, 0xA3, 0x66, - 0xA3, 0xA3, 0x66, 0x8F, 0x8F, 0x8F, 0xA0, 0x98, - 0xA3, 0x51, 0x89, 0x89, 0xA3, 0x2F, 0x20, 0x54, - 0xDF, 0xFA, 0x40, 0x37, 0xD4, 0x43, 0x56, 0x64, - 0x76, 0xF9, 0x78, 0x41, 0x5E, 0x5E, 0x4C, 0x20, - 0x20, 0xAD, 0x8F, 0x9C, 0x20, 0xA5, 0xA3, 0x2F, - 0x2F, 0x2F, 0xA3, 0x66, 0x2F, 0xB2, 0xB2, 0xB2, - 0xA3, 0x66, 0xA3, 0x2F, 0x66, 0x8F, 0x8F, 0x8F, - 0x8F, 0x8F, 0xA3, 0x51, 0x89, 0x51, 0xA3, 0x66, - 0xA0, 0xA0, 0x8F, 0xA3, 0x2F, 0x2F, 0x2F, 0xB2, - 0x2F, 0xA3, 0x2F, 0xB2, 0x51, 0xB2, 0x2F, 0x66, - 0xA3, 0xA3, 0x66, 0x66, 0x66, 0x66, 0x66, 0xA3, - 0xB2, 0x89, 0xD8, 0x51, 0x66, 0x51, 0x20, 0x6D, - 0x51, 0x77, 0x9F, 0xF7, 0xEE, 0x8E, 0xF9, 0xF0, - 0x24, 0xF7, 0x77, 0x5E, 0x74, 0xD8, 0x98, 0x20, - 0x20, 0x2E, 0x55, 0x92, 0x20, 0x54, 0x51, 0x2F, - 0x2F, 0xB2, 0xB2, 0xA3, 0x2F, 0x51, 0x51, 0xB2, - 0xA3, 0xA3, 0x66, 0xA3, 0x66, 0x66, 0x66, 0x66, - 0x66, 0xA3, 0xB2, 0x89, 0xD8, 0x51, 0xA3, 0x98, - 0x98, 0x66, 0x66, 0xA3, 0x2F, 0x2F, 0x2F, 0xB2, - 0xB2, 0x2F, 0x2F, 0xB2, 0xB2, 0x2F, 0x2F, 0x66, - 0x66, 0xA3, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, 0xB2, - 0x89, 0xD8, 0x89, 0xB2, 0x66, 0x66, 0x20, 0x6D, - 0x89, 0xC2, 0xA4, 0x96, 0xC6, 0x64, 0x50, 0x40, - 0xF4, 0x97, 0x89, 0x74, 0x7E, 0x6B, 0x39, 0xA7, - 0x20, 0x20, 0x3A, 0x54, 0x20, 0x20, 0xA7, 0x51, - 0x2F, 0xB2, 0xB2, 0xA3, 0xA3, 0xB2, 0xB2, 0xB2, - 0xA3, 0xA3, 0x66, 0xA3, 0xA3, 0xA3, 0x2F, 0x2F, - 0x2F, 0xB2, 0x89, 0xD8, 0x44, 0x2F, 0x66, 0x66, - 0x2F, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, 0x2F, 0xB2, - 0x2F, 0xA3, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, 0xA3, - 0x66, 0xA3, 0x2F, 0xB2, 0xB2, 0xB2, 0x51, 0x51, - 0x89, 0x89, 0xB2, 0x66, 0x2F, 0x6D, 0x20, 0xCE, - 0x39, 0x74, 0x89, 0x5E, 0xBD, 0x87, 0xC8, 0xD1, - 0x89, 0x44, 0x3C, 0x4D, 0x6B, 0x6B, 0x6B, 0x2F, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xA3, - 0x2F, 0x2F, 0x2F, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, - 0x2F, 0xA3, 0x66, 0x66, 0x2F, 0xB2, 0xB2, 0xB2, - 0x51, 0x51, 0x89, 0x89, 0xB2, 0xA3, 0x98, 0x66, - 0xA3, 0x66, 0x66, 0xA3, 0xA3, 0xA3, 0xA3, 0x2F, - 0x2F, 0xA3, 0xA3, 0xA3, 0x2F, 0xA3, 0x2F, 0xA3, - 0x66, 0x66, 0x2F, 0x2F, 0xB2, 0xB2, 0xB2, 0xB2, - 0xB2, 0x2F, 0x66, 0x66, 0x2A, 0x20, 0x54, 0x44, - 0x6B, 0x39, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0xD8, 0x39, 0x4D, 0x6B, 0x6B, 0x6B, 0x6B, 0x4D, - 0x9C, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6D, - 0x51, 0x2F, 0x2F, 0x2F, 0xA3, 0xA3, 0xA3, 0x2F, - 0xA3, 0xA3, 0x66, 0xA3, 0x2F, 0xB2, 0xB2, 0xB2, - 0xB2, 0xB2, 0xB2, 0x2F, 0x66, 0x98, 0x98, 0x66, - 0x98, 0x98, 0x66, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, - 0x2F, 0x2F, 0xA3, 0xA3, 0x66, 0xA3, 0xA3, 0x66, - 0x98, 0x66, 0x66, 0x2F, 0xA3, 0xA3, 0xA3, 0xA3, - 0x66, 0x98, 0x98, 0x98, 0x3A, 0x54, 0x2A, 0x6B, - 0x6B, 0x6B, 0x83, 0x44, 0x89, 0x89, 0x44, 0x3C, - 0xD6, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, - 0xB2, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0xAD, 0x2F, 0x2F, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, - 0xA3, 0x66, 0x66, 0x98, 0x66, 0xA3, 0xA3, 0xA3, - 0xA3, 0xA3, 0x66, 0x98, 0x8F, 0x8F, 0x8F, 0x98, - 0x8F, 0x98, 0x98, 0x66, 0xA3, 0xA3, 0xA3, 0xA3, - 0x2F, 0xA3, 0xA3, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x8F, 0x8F, 0x8F, 0x98, 0x98, 0x98, 0x8F, 0xA0, - 0xA0, 0xA0, 0xA3, 0xDA, 0x20, 0x3A, 0x39, 0x6B, - 0x6B, 0x6B, 0x4D, 0xA2, 0x74, 0x3C, 0x7E, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, - 0x6B, 0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x2F, 0x2F, 0xA3, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x98, 0x8F, 0x8F, 0x98, 0x98, 0x98, 0x98, - 0x8F, 0xA0, 0xA0, 0xA0, 0x8F, 0x8F, 0x8F, 0xA0, - 0x8F, 0x66, 0x66, 0xA3, 0x66, 0xA3, 0xA3, 0x2F, - 0x2F, 0x2F, 0xA3, 0xA3, 0x66, 0x66, 0x66, 0x98, - 0x98, 0xA0, 0x98, 0x66, 0x66, 0x98, 0x8F, 0xA0, - 0xA0, 0xA3, 0x2E, 0x20, 0x20, 0x8F, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x3D, 0x6B, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, - 0x6B, 0x55, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x3A, 0x51, 0x2F, 0xA3, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x98, 0x8F, 0x8F, 0x98, 0x66, 0x98, - 0x8F, 0xA0, 0xA0, 0x8F, 0x8F, 0x8F, 0x8F, 0xA0, - 0x66, 0x2F, 0x2F, 0x2F, 0x2F, 0xA3, 0xA3, 0xA3, - 0x2F, 0x2F, 0xA3, 0xA3, 0x66, 0xA3, 0x66, 0x66, - 0x66, 0x98, 0xA3, 0x2F, 0x2F, 0xA3, 0x66, 0x8F, - 0x66, 0xA6, 0x20, 0x20, 0x6D, 0x39, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, - 0x6B, 0xB2, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x2E, 0x89, 0xA3, 0xA3, 0x66, 0x66, - 0x66, 0x66, 0x98, 0x98, 0xA3, 0x2F, 0x2F, 0xA3, - 0x66, 0x8F, 0x98, 0x98, 0x66, 0x98, 0x98, 0x8F, - 0x2F, 0x51, 0xB2, 0xB2, 0x2F, 0xA3, 0xA3, 0xA3, - 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, - 0xA3, 0xA3, 0x2F, 0xB2, 0x2F, 0xA3, 0x66, 0x2F, - 0x55, 0x20, 0x20, 0x20, 0x4C, 0x39, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, - 0x4D, 0x7E, 0x54, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x2E, 0x51, 0xA3, 0xA3, 0xA3, - 0xA3, 0xA3, 0xA3, 0x2F, 0xB2, 0xB2, 0x2F, 0xA3, - 0x66, 0x66, 0xA3, 0xA3, 0xA3, 0xA3, 0x66, 0x66, - 0xB2, 0x51, 0x51, 0xB2, 0xB2, 0xA3, 0x2F, 0xA3, - 0x2F, 0x2F, 0x2F, 0xA3, 0xA3, 0xA3, 0xA3, 0x66, - 0xA3, 0x2F, 0xB2, 0x2F, 0xA3, 0x98, 0x98, 0xA0, - 0x20, 0x20, 0x20, 0x20, 0xA5, 0x83, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x4D, 0x7E, 0x4D, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x4D, 0x4D, 0xD6, 0x7E, 0xDD, - 0x3C, 0x39, 0xA7, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x92, 0xB2, 0xA3, 0xA3, - 0xA3, 0x66, 0xA3, 0x2F, 0x2F, 0x2F, 0xA3, 0x98, - 0x98, 0x66, 0xA3, 0xA3, 0x66, 0x66, 0x66, 0xA3, - 0x89, 0x89, 0x51, 0xB2, 0xB2, 0x2F, 0x2F, 0x2F, - 0x2F, 0xA3, 0xA3, 0x2F, 0xA3, 0xA3, 0xA3, 0xA3, - 0xA3, 0xA3, 0xA3, 0x66, 0x8F, 0x8F, 0x2F, 0xDA, - 0x20, 0x20, 0x20, 0xDA, 0xA0, 0x51, 0x3C, 0x7E, - 0x6B, 0x6B, 0x6B, 0x4D, 0x7E, 0x6B, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x7E, 0x3C, 0xD8, 0x44, 0xD8, - 0x44, 0x83, 0x89, 0xDA, 0x20, 0x3A, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0xB2, 0xA3, 0xA3, - 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0x66, 0x8F, 0x8F, - 0x98, 0x98, 0x98, 0x98, 0x66, 0xA3, 0xA3, 0x2F, - 0x3C, 0x89, 0x89, 0x51, 0xB2, 0xB2, 0x2F, 0x2F, - 0x2F, 0x2F, 0xA3, 0xA3, 0x66, 0x66, 0x66, 0xA3, - 0xA3, 0xA3, 0xA3, 0x66, 0x98, 0x98, 0xA3, 0x20, - 0x20, 0x20, 0x20, 0x6D, 0x2F, 0xE6, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x3D, 0xD6, 0x3D, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x4D, 0x7E, 0xA2, - 0x74, 0x44, 0xA2, 0xA3, 0x20, 0x3A, 0x2E, 0x6D, - 0x20, 0x20, 0x20, 0x20, 0x20, 0xA6, 0xA3, 0x66, - 0x66, 0x66, 0xA3, 0x2F, 0xA3, 0x66, 0x66, 0x98, - 0x66, 0x66, 0x98, 0x98, 0x98, 0x66, 0xA3, 0xA3, - 0x83, 0xB2, 0x2F, 0x2F, 0xB2, 0xB2, 0xB2, 0x2F, - 0x2F, 0x2F, 0xA3, 0x66, 0x66, 0x98, 0x98, 0x66, - 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0x66, 0xA6, 0x20, - 0x3A, 0x3A, 0x54, 0x55, 0x7E, 0x6B, 0x6B, 0x6B, - 0x4D, 0x3D, 0x6B, 0x6B, 0x6B, 0x57, 0x33, 0xEB, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, - 0x4D, 0xA2, 0x74, 0x39, 0x92, 0x20, 0x20, 0x6D, - 0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2F, 0x98, - 0x98, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0xA3, 0x66, 0xA3, - 0x89, 0xA3, 0x66, 0x66, 0xA3, 0xA3, 0x2F, 0x2F, - 0xA3, 0x2F, 0xA3, 0xA3, 0x66, 0x66, 0x66, 0xA3, - 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xB2, 0x3A, 0x20, - 0xA7, 0x20, 0x3A, 0x39, 0x6B, 0x6B, 0x6B, 0x6B, - 0xB5, 0xCB, 0x6B, 0x6B, 0x3D, 0x8A, 0x42, 0x3D, - 0x6B, 0x6B, 0x6B, 0x84, 0x6C, 0x4D, 0x6B, 0x6B, - 0x6B, 0x6B, 0x7E, 0x83, 0x51, 0x20, 0x20, 0x20, - 0x6D, 0x3A, 0x20, 0x20, 0x20, 0x20, 0xAD, 0x66, - 0x66, 0x66, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, - 0xA3, 0xA3, 0xA3, 0xA3, 0x66, 0xA3, 0xA3, 0xA3, - 0xB2, 0x98, 0x66, 0x66, 0x98, 0x66, 0x66, 0xA3, - 0xA3, 0xA3, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, 0x2F, - 0xA3, 0x2F, 0xA3, 0xA3, 0xA3, 0x2F, 0x20, 0x6D, - 0x3A, 0x20, 0x98, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, - 0xAA, 0x33, 0x6B, 0x6B, 0x3D, 0xF5, 0x7B, 0x3D, - 0x6B, 0x6B, 0x4F, 0x4A, 0x58, 0x3D, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x7E, 0x7E, 0x9C, 0x54, 0xA7, - 0x2E, 0xA7, 0x20, 0x20, 0x20, 0x20, 0x54, 0x51, - 0x2F, 0x2F, 0xA3, 0x2F, 0xA3, 0xA3, 0xA3, 0xA3, - 0x2F, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0x2F, - 0xB2, 0x66, 0x66, 0x66, 0x66, 0xA3, 0x66, 0xA3, - 0x66, 0x66, 0xA3, 0x2F, 0x2F, 0xB2, 0x2F, 0xB2, - 0x2F, 0x2F, 0x2F, 0xA3, 0x2F, 0xA6, 0x20, 0xCE, - 0x20, 0x6D, 0x4D, 0x6B, 0xD6, 0x7E, 0x6B, 0x6B, - 0x6E, 0x9A, 0x57, 0x6B, 0x2D, 0x7B, 0x7B, 0x3D, - 0x6B, 0x84, 0xF5, 0x7B, 0x84, 0x6B, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x98, 0x3A, 0x9C, - 0xCE, 0x3A, 0x2E, 0x20, 0x20, 0x20, 0x20, 0x98, - 0xB2, 0xB2, 0x2F, 0x2F, 0x2F, 0xA3, 0x2F, 0x2F, - 0x2F, 0xA3, 0xA3, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, - 0x89, 0xA3, 0x66, 0x66, 0xA3, 0x2F, 0x2F, 0xA3, - 0x66, 0x66, 0xA3, 0xA3, 0x2F, 0x2F, 0xB2, 0xB2, - 0xB2, 0x2F, 0x2F, 0x2F, 0x89, 0x54, 0x6D, 0x3A, - 0x20, 0x98, 0x6B, 0x6B, 0xE0, 0xB4, 0x6B, 0x6B, - 0x2D, 0x9E, 0x4A, 0x3D, 0x84, 0xF5, 0xF5, 0x84, - 0x6B, 0x6E, 0x59, 0x6C, 0x6B, 0x6B, 0x6B, 0x6B, - 0x3D, 0x6B, 0x6B, 0x6B, 0x6B, 0xDD, 0xDA, 0x6D, - 0x54, 0x20, 0xCE, 0x20, 0x20, 0x20, 0x20, 0xA7, - 0x51, 0xB2, 0xB2, 0xB2, 0x2F, 0xB2, 0x2F, 0x2F, - 0x2F, 0x66, 0x66, 0xA3, 0xA3, 0xA3, 0xA3, 0x66, - 0x89, 0xA3, 0xA3, 0xA3, 0x2F, 0xB2, 0xB2, 0x2F, - 0x66, 0x66, 0xA3, 0xA3, 0x2F, 0xA3, 0xA3, 0x2F, - 0xB2, 0x2F, 0x2F, 0xA3, 0x98, 0x20, 0xA7, 0x20, - 0x3A, 0x7E, 0x6B, 0x6B, 0x7F, 0xDE, 0xF6, 0x3D, - 0x6B, 0xDB, 0x8A, 0xDB, 0xE9, 0xF3, 0xF3, 0xDB, - 0x68, 0xF3, 0x73, 0x7F, 0x6B, 0x6B, 0x57, 0x58, - 0xDC, 0x2D, 0x6B, 0x6B, 0x6B, 0x6B, 0x3A, 0x20, - 0x20, 0x20, 0x6D, 0x54, 0x20, 0x20, 0x20, 0x20, - 0x51, 0x2F, 0x2F, 0x2F, 0xA3, 0xA3, 0xA3, 0x66, - 0xA3, 0x66, 0x98, 0x98, 0x66, 0x98, 0x98, 0x66, - 0x2F, 0x66, 0x66, 0xA3, 0x2F, 0xB2, 0x2F, 0xA3, - 0xA3, 0xA3, 0xA3, 0xA3, 0x66, 0xA3, 0xA3, 0xA3, - 0x66, 0x98, 0x8F, 0x98, 0xCE, 0xDA, 0x2E, 0x20, - 0x2A, 0x6B, 0x6B, 0x6B, 0x6B, 0x2C, 0x34, 0xCB, - 0xEB, 0x6C, 0x31, 0x59, 0x82, 0x82, 0x8B, 0x82, - 0xF3, 0x73, 0xE9, 0x6B, 0x3D, 0x6E, 0xF3, 0x4A, - 0x4F, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x92, 0x20, - 0x20, 0x20, 0x6D, 0x6D, 0x20, 0x20, 0x20, 0x20, - 0xA3, 0xA3, 0x66, 0x98, 0x98, 0x8F, 0x8F, 0x98, - 0x98, 0x98, 0x98, 0x66, 0x98, 0x66, 0x66, 0xA3, - 0xA3, 0x66, 0x66, 0x66, 0xA3, 0x2F, 0x2F, 0xA3, - 0xA3, 0xA3, 0x66, 0x66, 0xA3, 0xA3, 0xA3, 0x66, - 0x8F, 0x55, 0xA5, 0x98, 0x20, 0x2E, 0x54, 0x54, - 0x89, 0x6B, 0x6B, 0x6B, 0x6B, 0x84, 0xE3, 0x4A, - 0x58, 0x42, 0x5B, 0x8B, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x59, 0x58, 0x57, 0x57, 0x59, 0x7B, 0x84, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0xAD, 0x20, - 0x20, 0x20, 0x3A, 0x3A, 0x20, 0x20, 0x20, 0x20, - 0x2A, 0x66, 0x8F, 0x55, 0xA5, 0xA5, 0xA0, 0x8F, - 0x66, 0xA3, 0xA3, 0x66, 0x98, 0x66, 0x66, 0x2F, - 0x2F, 0x2F, 0x2F, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, - 0xA3, 0x2F, 0xA3, 0xA3, 0x66, 0xA3, 0xA3, 0x66, - 0x8F, 0xA5, 0x8F, 0x2E, 0x20, 0x2E, 0x20, 0x3A, - 0x4D, 0x6B, 0xE6, 0x84, 0x3D, 0x6B, 0xEB, 0x4A, - 0xC9, 0x8B, 0x8B, 0x31, 0x59, 0x82, 0x59, 0x59, - 0x5B, 0x82, 0x59, 0x73, 0x7B, 0xDC, 0x57, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x55, 0x20, - 0x20, 0x20, 0x6D, 0xDA, 0x20, 0x20, 0x20, 0x20, - 0x9C, 0x66, 0x8F, 0xA5, 0xA5, 0x55, 0x8F, 0x66, - 0x2F, 0xB2, 0x2F, 0x66, 0x98, 0x98, 0x2F, 0x51, - 0x89, 0xB2, 0x2F, 0xA3, 0xA3, 0xB2, 0xB2, 0xB2, - 0x2F, 0x2F, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0x66, - 0x8F, 0xA5, 0x8F, 0x20, 0x20, 0xA7, 0x20, 0xA6, - 0x6B, 0x6B, 0xE4, 0x48, 0x2C, 0xDB, 0x4F, 0x9E, - 0xD0, 0xD0, 0x8B, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x59, 0x82, 0x82, 0x73, 0x7B, 0x68, 0x6B, 0x3D, - 0x68, 0x68, 0x84, 0x3D, 0x6B, 0x6B, 0xA0, 0x20, - 0x20, 0x20, 0x6D, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x6D, 0x2F, 0xA0, 0xA5, 0x55, 0x98, 0x66, 0xA3, - 0xB2, 0x89, 0xB2, 0x98, 0x8F, 0x98, 0x2F, 0x51, - 0x74, 0xB2, 0xA3, 0xA3, 0x2F, 0x2F, 0xB2, 0x2F, - 0xA3, 0xA3, 0xA3, 0x66, 0x66, 0xA3, 0x2F, 0xA3, - 0x98, 0xA3, 0x6D, 0x20, 0x20, 0xCE, 0x20, 0x2A, - 0x6B, 0x6B, 0xEB, 0x2C, 0xE1, 0xF1, 0x7C, 0xD0, - 0x8B, 0x8B, 0x82, 0x82, 0x82, 0x82, 0x82, 0x59, - 0x82, 0x82, 0x42, 0x82, 0x31, 0x57, 0x4F, 0x7B, - 0x7B, 0xF5, 0xF6, 0xDB, 0x6B, 0x6B, 0x98, 0x20, - 0x20, 0x20, 0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x51, 0x66, 0xA0, 0xA0, 0x66, 0x2F, 0xB2, - 0xB2, 0x51, 0x2F, 0xA0, 0x55, 0xA3, 0x51, 0x89, - 0x44, 0xA3, 0x98, 0x98, 0x2F, 0x2F, 0x2F, 0xA3, - 0xA3, 0x66, 0x98, 0x98, 0x98, 0xA3, 0x2F, 0x2F, - 0x98, 0x8F, 0x20, 0x20, 0x3A, 0xA6, 0x20, 0xA0, - 0x6B, 0x6B, 0x6B, 0x6B, 0x7F, 0x7F, 0xC3, 0xC9, - 0xD0, 0xD0, 0x29, 0x59, 0x82, 0x73, 0x82, 0x73, - 0x59, 0x59, 0x59, 0x59, 0x59, 0x58, 0xAF, 0xF5, - 0x8A, 0x68, 0xEB, 0x6B, 0x6B, 0x6B, 0x98, 0x20, - 0x20, 0x20, 0x6D, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x51, 0x98, 0x55, 0xA0, 0xA3, 0xB2, 0x51, - 0x51, 0x2F, 0x98, 0x55, 0x8F, 0xB2, 0x89, 0x44, - 0xA3, 0x55, 0x55, 0x98, 0xA3, 0xB2, 0x2F, 0xA3, - 0x66, 0x66, 0x98, 0x8F, 0x66, 0xA3, 0x66, 0x98, - 0x55, 0x4C, 0x20, 0x20, 0xDA, 0xAD, 0x20, 0x98, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x3D, 0x9A, 0xD0, - 0xF2, 0x8B, 0x8B, 0x8B, 0x73, 0x82, 0x5B, 0x82, - 0x82, 0x59, 0x59, 0x73, 0x73, 0x58, 0x3D, 0x3D, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x66, 0x20, - 0x20, 0x3A, 0x3A, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x2F, 0x55, 0xA5, 0x8F, 0xA3, 0x51, 0x51, - 0xB2, 0xA3, 0x66, 0x66, 0xA3, 0xB2, 0x89, 0x51, - 0x98, 0xA5, 0x55, 0x8F, 0x2F, 0xB2, 0xB2, 0xA3, - 0x66, 0x66, 0x98, 0x98, 0x98, 0x66, 0x66, 0x8F, - 0x8F, 0x92, 0x20, 0x20, 0x20, 0x6D, 0x6D, 0xA3, - 0x6B, 0x6B, 0xEB, 0x7F, 0x4F, 0xDB, 0xD2, 0xC9, - 0xC9, 0xD0, 0x8B, 0x8B, 0x73, 0x82, 0x59, 0x8B, - 0x59, 0x82, 0x59, 0x59, 0x73, 0xF5, 0xEB, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x55, 0x20, - 0x20, 0xA7, 0x54, 0xDA, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x98, 0xA0, 0x8F, 0xA3, 0xB2, 0x51, 0x51, - 0x51, 0x2F, 0xA3, 0xA3, 0xB2, 0xB2, 0x51, 0xB2, - 0xA0, 0xA5, 0x55, 0x66, 0x2F, 0x51, 0x2F, 0xA3, - 0x66, 0x66, 0x66, 0x98, 0x66, 0x66, 0x98, 0x98, - 0x98, 0x2A, 0x54, 0x95, 0x95, 0x71, 0x2E, 0x98, - 0x6B, 0x6B, 0x4D, 0x28, 0xDE, 0x88, 0xB7, 0x70, - 0xC9, 0xC9, 0xD0, 0xF2, 0x8B, 0x8B, 0x8B, 0x59, - 0x59, 0x59, 0x59, 0x5B, 0x59, 0xF3, 0x57, 0xE9, - 0xDB, 0x84, 0x6B, 0x6B, 0x6B, 0x6B, 0x4C, 0xDA, - 0x2E, 0xDA, 0x20, 0xDA, 0x2E, 0x2E, 0x6D, 0x20, - 0x4C, 0x98, 0x66, 0xA3, 0x2F, 0xB2, 0x51, 0x51, - 0xB2, 0xA3, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, 0x2F, - 0xA0, 0xA0, 0x8F, 0x2F, 0xB2, 0x89, 0xB2, 0xA3, - 0x66, 0x66, 0x98, 0x66, 0x66, 0x66, 0x66, 0xA3, - 0x2F, 0xD1, 0xE2, 0x52, 0x52, 0xF4, 0xBF, 0x9C, - 0x39, 0x6B, 0x6B, 0x6B, 0x7F, 0x4F, 0xE3, 0x6A, - 0xD0, 0xC9, 0xC9, 0xD0, 0xD0, 0x8B, 0x8B, 0x82, - 0x5B, 0x5B, 0x73, 0x8B, 0x59, 0x23, 0x6E, 0x31, - 0x59, 0x7B, 0xDB, 0x84, 0x68, 0x7F, 0xAE, 0x54, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x54, 0xA6, 0x3A, - 0xA0, 0xA3, 0xA3, 0x2F, 0x51, 0x51, 0x51, 0xB2, - 0x2F, 0xA3, 0x66, 0x66, 0xA3, 0xA3, 0xA3, 0xA3, - 0x8F, 0x8F, 0x66, 0x2F, 0x51, 0x51, 0xB2, 0xA3, - 0x66, 0x98, 0x98, 0x66, 0x66, 0xA3, 0x2F, 0x2F, - 0x3C, 0x88, 0x8D, 0x52, 0x52, 0x5D, 0xF7, 0xBF, - 0xCE, 0xA2, 0x6B, 0x6B, 0x6B, 0x6B, 0x7F, 0x85, - 0x70, 0xC9, 0xC9, 0xC9, 0xD0, 0xEA, 0x8B, 0x5B, - 0x82, 0xEA, 0x82, 0x82, 0x42, 0x57, 0x3D, 0x68, - 0x68, 0x57, 0x4A, 0x34, 0x22, 0xCC, 0x21, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0xDA, 0xA7, 0x6D, - 0xDF, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0x2F, 0x2F, - 0xA3, 0x66, 0x66, 0x66, 0xA3, 0xA3, 0x2F, 0x2F, - 0x66, 0x66, 0xA3, 0x2F, 0xB2, 0xB2, 0x2F, 0x66, - 0x8F, 0x8F, 0x8F, 0x98, 0xA3, 0xA3, 0x89, 0xD8, - 0x25, 0x5C, 0x3B, 0x5D, 0x52, 0x80, 0x70, 0x36, - 0x71, 0xA7, 0x44, 0x6B, 0x84, 0xCB, 0xAA, 0xF3, - 0xC9, 0xC9, 0xC9, 0xC9, 0xD0, 0x8B, 0x5B, 0x5B, - 0x5B, 0xEA, 0x82, 0x47, 0x7B, 0x68, 0x3D, 0x3D, - 0x6B, 0x3D, 0x6C, 0x2B, 0x80, 0x61, 0x96, 0x81, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3A, 0xDA, 0x63, - 0xAC, 0x6C, 0xB2, 0xB2, 0xB2, 0xB2, 0x2F, 0xA3, - 0xA3, 0x66, 0xA3, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, - 0x66, 0x98, 0x66, 0xA3, 0xB2, 0xB2, 0x2F, 0x66, - 0x8F, 0x8F, 0x2F, 0xD8, 0xE4, 0xCD, 0xAA, 0xB4, - 0x78, 0x2B, 0x3B, 0x70, 0x46, 0x5D, 0x5D, 0x52, - 0x9D, 0x81, 0x3A, 0xA3, 0xCD, 0x48, 0xBE, 0x4F, - 0xC3, 0xC9, 0xD0, 0xD0, 0xD0, 0xEA, 0x5B, 0x8B, - 0x5B, 0x82, 0x8B, 0x59, 0x4A, 0xF3, 0x33, 0x7F, - 0x3D, 0x6B, 0x4F, 0x6F, 0x5D, 0x52, 0x63, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x75, 0x85, - 0x72, 0xDC, 0xD8, 0x2F, 0xA3, 0x2F, 0xA3, 0xA3, - 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, - 0xA3, 0x98, 0x66, 0x2F, 0xB2, 0x51, 0xA3, 0x98, - 0xA0, 0xA3, 0x93, 0xCF, 0x79, 0x27, 0x5C, 0x79, - 0x2B, 0x30, 0x80, 0x80, 0x5D, 0x5D, 0x5D, 0x5D, - 0x3F, 0x69, 0x20, 0x20, 0x2A, 0xD6, 0x3D, 0x6B, - 0x84, 0xE3, 0x34, 0xB7, 0xC9, 0xD0, 0xD0, 0xF2, - 0xD0, 0x8B, 0x31, 0x68, 0x68, 0x6E, 0x31, 0x33, - 0x7F, 0x7E, 0xA1, 0x6F, 0x52, 0x8D, 0xE5, 0xBF, - 0x20, 0x20, 0x20, 0x20, 0x81, 0xA8, 0x78, 0x52, - 0x52, 0xD2, 0xD8, 0xA3, 0xA3, 0x2F, 0x2F, 0xA3, - 0xA3, 0x66, 0x98, 0x98, 0x98, 0x98, 0x98, 0x66, - 0x51, 0x66, 0x2F, 0x51, 0x51, 0xB2, 0xA3, 0xA0, - 0xA0, 0x44, 0x78, 0xEF, 0x52, 0x30, 0x30, 0x30, - 0x3B, 0x70, 0x5D, 0x5D, 0x5D, 0x80, 0x5D, 0x5D, - 0x46, 0xC1, 0x71, 0x20, 0x81, 0xB1, 0xDD, 0x3D, - 0xA1, 0xE7, 0xDB, 0xCA, 0xD2, 0x6A, 0x6A, 0x6A, - 0xF3, 0xE9, 0xDB, 0x8A, 0x84, 0x3D, 0x84, 0xDC, - 0x25, 0x44, 0xB5, 0xEE, 0x30, 0xEF, 0xF0, 0x32, - 0x69, 0x5F, 0x4B, 0xA8, 0x99, 0x56, 0x67, 0x30, - 0x30, 0x34, 0xB2, 0x2F, 0xA3, 0xA3, 0x66, 0x66, - 0x98, 0x8F, 0x98, 0x98, 0x66, 0x66, 0x66, 0x66, - 0x51, 0x2F, 0xB2, 0x51, 0x51, 0x2F, 0x66, 0xA0, - 0x8F, 0xE0, 0xF9, 0x8D, 0x52, 0x5D, 0x46, 0x5D, - 0x80, 0x5D, 0x80, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, - 0x52, 0x52, 0x60, 0x81, 0x20, 0x20, 0x6D, 0xD1, - 0x48, 0xE7, 0x6B, 0x33, 0xF6, 0x7F, 0x7F, 0xDB, - 0x84, 0x6B, 0x6C, 0x6A, 0xF3, 0xEB, 0x6B, 0x3D, - 0x4F, 0xD8, 0xCD, 0x79, 0x30, 0x67, 0xF9, 0x24, - 0xED, 0xD9, 0x8C, 0xED, 0x37, 0x2B, 0x3B, 0x5D, - 0x80, 0x85, 0x4E, 0x98, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0xA3, 0x2F, 0x2F, 0x2F, 0x2F, - 0x51, 0x2F, 0xB2, 0xB2, 0xB2, 0xA3, 0x8F, 0x8F, - 0x98, 0xE0, 0xF0, 0x67, 0x5D, 0x80, 0x80, 0x5D, - 0x5D, 0x5D, 0x5D, 0x5D, 0x80, 0x5D, 0x5D, 0x5D, - 0x5D, 0x70, 0x27, 0x4B, 0x20, 0x81, 0x71, 0x3A, - 0xB5, 0xEB, 0x3D, 0xF1, 0xE1, 0x84, 0x84, 0xF1, - 0xE3, 0x3D, 0x6B, 0x6C, 0x34, 0xE7, 0x6B, 0x6B, - 0xD6, 0x74, 0x5E, 0x78, 0x67, 0x30, 0xEE, 0x5C, - 0xF9, 0xF9, 0x45, 0x5C, 0x2B, 0x3B, 0x5D, 0x5D, - 0x5D, 0x5D, 0xF8, 0x44, 0x66, 0x66, 0x66, 0x66, - 0x2F, 0x2F, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, - 0xB2, 0x2F, 0xA3, 0xA3, 0xA3, 0x98, 0x8F, 0x98, - 0x66, 0x83, 0x76, 0x67, 0x30, 0x80, 0x5D, 0x80, - 0x5D, 0x5D, 0x80, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, - 0x80, 0x5D, 0x22, 0xFA, 0x20, 0x81, 0x20, 0x20, - 0xA5, 0x6B, 0x6B, 0xE8, 0xBE, 0x3D, 0x6B, 0x2C, - 0xE1, 0xEB, 0x6B, 0x3D, 0x3E, 0xA1, 0x6B, 0x6B, - 0x4D, 0x74, 0xE8, 0x62, 0x67, 0x30, 0x8D, 0x67, - 0xEE, 0xEE, 0xEE, 0x67, 0x30, 0x80, 0x5D, 0x5D, - 0x52, 0x5D, 0x85, 0xAC, 0x3E, 0xA3, 0x66, 0x66, - 0x2F, 0x51, 0x51, 0x51, 0x51, 0xB2, 0x2F, 0x2F, - 0x2F, 0xA3, 0xA3, 0x66, 0x98, 0x8F, 0x8F, 0x66, - 0x2F, 0x83, 0xBC, 0xEE, 0x5D, 0x5D, 0x5D, 0x5D, - 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x80, 0x5D, 0x5D, - 0x5D, 0x5D, 0x22, 0xB0, 0xAE, 0x81, 0x20, 0x20, - 0x4C, 0x3D, 0xEB, 0x39, 0x57, 0x6B, 0x6B, 0x3E, - 0x97, 0x3D, 0x6B, 0x3D, 0x6B, 0x6B, 0x6B, 0x6B, - 0x3D, 0x3C, 0xBA, 0x62, 0xEE, 0x5D, 0x5D, 0x30, - 0x30, 0x8D, 0x8D, 0x30, 0x52, 0x5D, 0x5D, 0x80, - 0x5D, 0x5D, 0x5D, 0x85, 0xB0, 0x6E, 0x2F, 0x66, - 0x2F, 0xB2, 0x51, 0xB2, 0x2F, 0x2F, 0xA3, 0xA3, - 0xB2, 0xA3, 0x66, 0x98, 0x98, 0x8F, 0x98, 0xA3, - 0x2F, 0x51, 0xDE, 0x8E, 0x30, 0x5D, 0x5D, 0x5D, - 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, - 0x52, 0x80, 0x5D, 0x22, 0x43, 0x4B, 0x20, 0x6D, - 0x44, 0x6B, 0x6B, 0x3D, 0x6B, 0x6B, 0x6B, 0x4D, - 0x3D, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x3D, 0x6B, - 0x4D, 0x2A, 0xAE, 0x76, 0xEE, 0x30, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x5D, 0x5D, 0x5D, 0x80, - 0x5D, 0x5D, 0x80, 0x80, 0x5D, 0x7A, 0xB6, 0x51, - 0xB2, 0xB2, 0xB2, 0xA3, 0x66, 0x66, 0x66, 0xA3, - 0x2F, 0x66, 0x98, 0x8F, 0xA0, 0x98, 0xA3, 0x2F, - 0x2F, 0x51, 0xAB, 0x8E, 0x5D, 0x5D, 0x5D, 0x5D, - 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x80, - 0x5D, 0x80, 0x5D, 0x52, 0x52, 0x94, 0x2F, 0x7E, - 0x6B, 0x3D, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x7E, - 0xAD, 0x54, 0xAE, 0x24, 0x2B, 0x3B, 0x5D, 0x52, - 0x5D, 0x5D, 0x5D, 0x5D, 0x80, 0x5D, 0x5D, 0x80, - 0x5D, 0x52, 0x52, 0x5D, 0x5D, 0x5D, 0xD2, 0x3E, - 0x89, 0x89, 0xB2, 0xA3, 0x66, 0x98, 0x66, 0x66, - 0x2F, 0x66, 0x8F, 0x8F, 0xA0, 0x98, 0xA3, 0xB2, - 0x2F, 0x51, 0xDE, 0x79, 0x5D, 0x80, 0x5D, 0x5D, - 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, - 0x5D, 0x5D, 0x80, 0x5D, 0x52, 0x6F, 0xA4, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x4D, 0xA2, 0xCE, - 0x20, 0x20, 0x95, 0x24, 0x67, 0x3B, 0x80, 0x80, - 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, - 0x80, 0x5D, 0x5D, 0x5D, 0x5D, 0x30, 0xB0, 0x86, - 0x89, 0x51, 0x2F, 0x66, 0x98, 0x98, 0xA3, 0xA3, - 0xA3, 0x66, 0x8F, 0xA0, 0x8F, 0x66, 0x2F, 0xB2, - 0x2F, 0x4E, 0x76, 0x2B, 0x30, 0x5D, 0x5D, 0x5D, - 0x80, 0x80, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, - 0x80, 0x5D, 0x5D, 0x5D, 0x46, 0x52, 0x21, 0x74, - 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, - 0x6B, 0x6B, 0x6B, 0x6B, 0x7E, 0x98, 0x3A, 0x20, - 0x20, 0x81, 0x60, 0xED, 0x2B, 0x52, 0x5D, 0x5D, - 0x80, 0x5D, 0x5D, 0x80, 0x5D, 0x5D, 0x5D, 0x80, - 0x22, 0x5D, 0x5D, 0x5D, 0x8D, 0x2B, 0x38, 0x39, - 0x51, 0x66, 0x8F, 0xA0, 0xA0, 0x8F, 0x98, 0x66, - 0x66, 0x66, 0x8F, 0x55, 0x8F, 0xA3, 0xB2, 0xB2, - 0xA3, 0xE8, 0xF9, 0x30, 0x3B, 0x80, 0x5D, 0x5D, - 0x5D, 0x80, 0x80, 0x5D, 0x5D, 0x5D, 0x80, 0x5D, - 0x5D, 0x5D, 0x5D, 0x5D, 0x52, 0x30, 0xD4, 0x99, - 0x51, 0x4D, 0x6B, 0x6B, 0x6B, 0x6B, 0x4D, 0x6B, - 0x6B, 0x6B, 0x7E, 0xA3, 0x2E, 0x20, 0x20, 0x20, - 0x20, 0x81, 0xC5, 0xED, 0x2B, 0x3B, 0x5D, 0x5D, - 0x5D, 0x5D, 0x5D, 0x5D, 0x80, 0x5D, 0x5D, 0x80, - 0x5D, 0x52, 0x52, 0x6F, 0xDE, 0x2C, 0x39, 0x51, - 0x66, 0xA0, 0xA5, 0xA5, 0x55, 0x8F, 0x66, 0x66, - 0xA0, 0xA0, 0xA0, 0xA0, 0x8F, 0xA3, 0x2F, 0x2F, - 0x51, 0xD5, 0x45, 0x8D, 0x3B, 0x5D, 0x80, 0x5D, - 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, - 0x80, 0x5D, 0x5D, 0x5D, 0x52, 0x67, 0x37, 0xA9, - 0x3A, 0xCE, 0xA0, 0x2F, 0x51, 0x51, 0xB2, 0xA3, - 0xA5, 0x9C, 0x54, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x54, 0x99, 0xED, 0x67, 0x30, 0x5D, 0x5D, - 0x5D, 0x80, 0x5D, 0x5D, 0x5D, 0x5D, 0x3B, 0x80, - 0x8D, 0x79, 0x48, 0x2C, 0x39, 0x44, 0xB2, 0x66, - 0xA0, 0x2A, 0xA5, 0xA0, 0x8F, 0x66, 0xA3, 0xA3, - 0xA0, 0x8F, 0x8F, 0xA0, 0x8F, 0xA3, 0xB2, 0xB2, - 0xD8, 0xBC, 0x45, 0xEE, 0x67, 0x8D, 0x30, 0x30, - 0x52, 0x52, 0x80, 0x5D, 0x5D, 0x5D, 0x5D, 0x80, - 0x5D, 0x5D, 0x5D, 0x80, 0x3B, 0x67, 0xF9, 0x32, - 0x69, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0xBF, 0xEC, 0xED, 0x2B, 0x30, 0x5D, 0x5D, - 0x80, 0x5D, 0x5D, 0x5D, 0x52, 0x30, 0x67, 0x2B, - 0xCF, 0xAA, 0xD8, 0x89, 0x89, 0x51, 0x66, 0x55, - 0x2A, 0x2A, 0xA5, 0x8F, 0x66, 0xA3, 0x2F, 0x2F, - 0xA3, 0xA3, 0x66, 0x98, 0x98, 0x2F, 0xB2, 0x2F, - 0xD1, 0x28, 0x56, 0xED, 0x62, 0x37, 0x5C, 0x79, - 0x8E, 0x2B, 0x2B, 0x30, 0x30, 0x30, 0x5D, 0x5D, - 0x5D, 0x5D, 0x5D, 0x80, 0x3B, 0xEE, 0x56, 0xA9, - 0x75, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x5F, 0x99, 0xD9, 0x45, 0x8D, 0x3B, 0x5D, - 0x5D, 0x3B, 0x5D, 0x8D, 0x2B, 0x79, 0x79, 0x41, - 0x83, 0xB2, 0xB2, 0x89, 0x89, 0x2F, 0xA0, 0x2A, - 0xAD, 0xA5, 0x98, 0x66, 0xA3, 0xB2, 0x2F, 0xB2, - 0xD8, 0xB2, 0xA3, 0x98, 0x98, 0x2F, 0x51, 0xB2, - 0xA3, 0x83, 0x3E, 0x25, 0xD5, 0xE5, 0x50, 0x8C, - 0xED, 0x24, 0x24, 0xF0, 0x45, 0x8E, 0x2B, 0x30, - 0x30, 0x5D, 0x3B, 0x30, 0xEE, 0xF0, 0xC6, 0x65, - 0x75, 0x71, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x4B, 0xC5, 0x7D, 0x24, 0xEE, 0x67, 0x30, - 0x30, 0x8D, 0x67, 0x8E, 0xF9, 0xF7, 0x97, 0xDD, - 0x2F, 0x2F, 0x51, 0x89, 0x89, 0x2F, 0x55, 0x2A, - 0xA5, 0x8F, 0x66, 0xA3, 0x2F, 0xB2, 0xB2, 0xB2, - 0xDD, 0xA3, 0x66, 0x98, 0x66, 0x2F, 0xB2, 0xB2, - 0xA3, 0xA3, 0xB2, 0x51, 0x89, 0x44, 0xE0, 0x5E, - 0x91, 0x9F, 0x9F, 0x7D, 0x7D, 0xD9, 0x24, 0xF0, - 0x79, 0x8E, 0xEE, 0x8E, 0x24, 0x40, 0x65, 0x35, - 0x69, 0x2E, 0x98, 0xA3, 0x2F, 0x2F, 0x2F, 0x2F, - 0x2F, 0xB2, 0xB2, 0xB2, 0x2F, 0x2F, 0x2F, 0x98, - 0xA5, 0xA7, 0x95, 0xD7, 0x8C, 0xF0, 0x8E, 0x8E, - 0xEE, 0x79, 0xF0, 0xED, 0x50, 0xE8, 0x89, 0x2F, - 0xA3, 0xA3, 0xB2, 0x89, 0xB2, 0x66, 0xA0, 0x55, - 0x8F, 0x98, 0x66, 0xA3, 0xB2, 0x51, 0x51, 0xB2, - 0x74, 0xA0, 0xA0, 0x98, 0x66, 0xB2, 0xB2, 0xB2, - 0xA3, 0xA3, 0x2F, 0xB2, 0xB2, 0xB2, 0xA3, 0x2F, - 0x51, 0x83, 0xE4, 0x87, 0xB8, 0xFA, 0xA9, 0xC6, - 0x40, 0x64, 0x64, 0x50, 0xD7, 0x65, 0x35, 0x60, - 0x98, 0xB2, 0x66, 0x66, 0xA3, 0x2F, 0xA3, 0xA3, - 0xA3, 0x2F, 0x2F, 0x2F, 0x2F, 0xA3, 0x2F, 0xB2, - 0x89, 0xDD, 0x9B, 0xC0, 0x7D, 0x50, 0x8C, 0xED, - 0xED, 0x8C, 0x40, 0x9F, 0x4E, 0x51, 0xB2, 0x2F, - 0x2F, 0x2F, 0xB2, 0x51, 0xA3, 0x98, 0xA0, 0x55, - 0xA0, 0xA0, 0x8F, 0x66, 0x2F, 0x51, 0xB2, 0xA3, - 0xA3, 0x2A, 0x55, 0x98, 0xA3, 0x2F, 0xB2, 0x2F, - 0x66, 0x66, 0x2F, 0xB2, 0xD1, 0x2F, 0x2F, 0xA3, - 0xB2, 0xB2, 0xA3, 0x8F, 0xA3, 0x2F, 0xD1, 0x94, - 0xEC, 0x65, 0x65, 0xC0, 0xC0, 0x35, 0x95, 0xC2, - 0xA3, 0x98, 0x66, 0xA3, 0x2F, 0x2F, 0x2F, 0xA3, - 0xA3, 0x2F, 0xB2, 0x2F, 0x2F, 0x2F, 0x2F, 0x51, - 0x89, 0x44, 0xD1, 0x60, 0x35, 0xA9, 0x32, 0xC6, - 0xD7, 0x32, 0x94, 0x44, 0x2F, 0xB2, 0xB2, 0xB2, - 0xA3, 0x2F, 0xB2, 0x2F, 0xA3, 0x8F, 0xA0, 0xA0, - 0x55, 0xA0, 0x8F, 0xA3, 0x51, 0x51, 0x2F, 0xA3, - 0x8F, 0x2A, 0x55, 0x66, 0xA3, 0x2F, 0x2F, 0xB2, - 0xA3, 0x66, 0x2F, 0xB2, 0x51, 0xB2, 0x2F, 0x66, - 0xA3, 0xA3, 0x66, 0x8F, 0x8F, 0x8F, 0xA0, 0x2F, - 0x5E, 0xDF, 0xB9, 0x60, 0x95, 0xD3, 0x89, 0x2F, - 0xA3, 0x66, 0xA3, 0x2F, 0xB2, 0x2F, 0xA3, 0xA3, - 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0xB2, - 0x51, 0x2F, 0x8F, 0x2F, 0xC4, 0xB9, 0x9B, 0xEC, - 0x53, 0xB3, 0x4E, 0xA3, 0x2F, 0xB2, 0xB2, 0xB2, - 0xA3, 0x66, 0xA3, 0xA3, 0x66, 0x8F, 0x8F, 0x8F, - 0x8F, 0x8F, 0xA3, 0x51, 0x89, 0x51, 0xA3, 0x66, - 0xA0, 0x55, 0x8F, 0xA3, 0x2F, 0x2F, 0x2F, 0xB2, - 0x2F, 0xA3, 0x2F, 0x51, 0x51, 0xB2, 0xA3, 0x66, - 0x66, 0xA3, 0x66, 0x66, 0x66, 0x66, 0x66, 0xA3, - 0xB2, 0xC2, 0x74, 0xD8, 0xB2, 0xA3, 0xA3, 0xA3, - 0x66, 0x66, 0x2F, 0x2F, 0xA3, 0x66, 0x66, 0x66, - 0xA3, 0xA3, 0xB2, 0xB2, 0xB2, 0xB2, 0x2F, 0xB2, - 0x2F, 0x66, 0xA0, 0x55, 0x98, 0x2F, 0x89, 0x89, - 0x89, 0xB2, 0x2F, 0xA3, 0x2F, 0x51, 0x51, 0xB2, - 0x2F, 0x66, 0xA3, 0xA3, 0x66, 0x66, 0x66, 0x66, - 0x66, 0xA3, 0xB2, 0x89, 0xD8, 0x51, 0xA3, 0x98, - 0x66, 0x98, 0x66, 0x2F, 0x2F, 0x2F, 0x2F, 0xB2, - 0xB2, 0xA3, 0xA3, 0xB2, 0xB2, 0xB2, 0x2F, 0xA3, - 0x66, 0xA3, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, 0xB2, - 0x89, 0xD8, 0x89, 0x2F, 0x66, 0x66, 0xA3, 0xA3, - 0x98, 0x98, 0x66, 0x66, 0x98, 0x98, 0x66, 0xA3, - 0x2F, 0xA3, 0xB2, 0xB2, 0xB2, 0xB2, 0x2F, 0x2F, - 0xB2, 0x2F, 0x66, 0x98, 0x66, 0xA3, 0x2F, 0x2F, - 0x2F, 0xB2, 0x2F, 0xA3, 0xA3, 0xB2, 0xB2, 0x2F, - 0x2F, 0x66, 0x66, 0xA3, 0xA3, 0xA3, 0x2F, 0x2F, - 0x2F, 0xB2, 0x89, 0xD8, 0x44, 0x2F, 0x66, 0x66, - 0xA3, 0xA3, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, 0x2F, - 0x2F, 0xA3, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, 0xA3, - 0x66, 0xA3, 0x2F, 0xB2, 0xB2, 0xB2, 0x51, 0x51, - 0x89, 0x89, 0xB2, 0xA3, 0x98, 0x66, 0xA3, 0x66, - 0x98, 0x98, 0x98, 0x98, 0x98, 0x66, 0xA3, 0x2F, - 0xA3, 0x2F, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, - 0xB2, 0x2F, 0xA3, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, - 0x2F, 0xB2, 0xB2, 0xA3, 0xA3, 0x2F, 0x2F, 0x2F, - 0x2F, 0xA3, 0x66, 0xA3, 0x2F, 0xB2, 0xB2, 0xB2, - 0x51, 0x51, 0x89, 0x89, 0xB2, 0xA3, 0x98, 0x66 -}; - -unsigned char linux_logo_bw[] __initdata = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x3F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, - 0xFE, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFE, 0x3F, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xC7, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xC3, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, - 0xFB, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFD, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, - 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF9, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xF9, 0xCF, 0xC3, 0xF8, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x87, 0x81, 0xF9, - 0xF8, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xA7, - 0x99, 0xF9, 0xC2, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF9, 0xF3, 0xBC, 0xF9, 0x90, 0x00, 0x1F, 0xFF, - 0xFF, 0xFF, 0xF9, 0xE3, 0xBC, 0xF9, 0xA0, 0x00, - 0x8F, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0, 0x3C, 0xF9, - 0x83, 0xE0, 0x2F, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0, - 0x19, 0xF0, 0x1F, 0xFE, 0x0F, 0xFF, 0xFF, 0xFF, - 0xF9, 0xC0, 0x03, 0xF0, 0x3F, 0xF7, 0x8F, 0xFF, - 0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8, 0x7F, 0xF7, - 0xC7, 0xFF, 0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8, - 0x6F, 0xF7, 0xE7, 0xFF, 0xFF, 0xFF, 0xF9, 0x80, - 0x01, 0xF8, 0x7F, 0xF7, 0xE7, 0xFF, 0xFF, 0xFF, - 0xF9, 0xC0, 0x21, 0xD8, 0x7F, 0xE7, 0xEF, 0xFF, - 0xFF, 0xFF, 0xF9, 0xB1, 0x80, 0xEC, 0x7B, 0xFF, - 0xEF, 0xFF, 0xFF, 0xFF, 0xF1, 0x90, 0x00, 0xE4, - 0x7B, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xF1, 0x8C, - 0xC0, 0x7C, 0x79, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, - 0xE3, 0x80, 0x00, 0x7C, 0x7C, 0xFF, 0xCF, 0xFF, - 0xFF, 0xFF, 0xE3, 0x80, 0x00, 0x7F, 0x77, 0xFF, - 0xDF, 0xFF, 0xFF, 0xFF, 0x87, 0x00, 0x00, 0x3F, - 0x3F, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0x0E, 0x00, - 0x00, 0x3F, 0xBF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, - 0x1E, 0x00, 0x00, 0x1F, 0x9F, 0xFF, 0x3F, 0xFF, - 0xFF, 0xFE, 0x1C, 0x00, 0x00, 0x1F, 0x9F, 0xFF, - 0x7F, 0xFF, 0xFF, 0xFE, 0x3C, 0x00, 0x00, 0x1F, - 0x8F, 0xFE, 0x7F, 0xFF, 0xFF, 0xFC, 0x7C, 0x00, - 0x00, 0x0F, 0xC7, 0xFC, 0xFF, 0xFF, 0xFF, 0xFC, - 0xF8, 0x00, 0x00, 0x0F, 0xF7, 0xF9, 0xFF, 0xFF, - 0xFF, 0xFC, 0xF8, 0x00, 0x00, 0x07, 0xFB, 0xF3, - 0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0x00, 0x00, 0x07, - 0xFD, 0xE7, 0xFF, 0xFF, 0xFF, 0xF9, 0xF0, 0x00, - 0x00, 0x03, 0xFE, 0x8F, 0xFF, 0xFF, 0xFF, 0xF1, - 0xF0, 0x00, 0x00, 0x03, 0xFE, 0x1F, 0xFF, 0xFF, - 0xFF, 0xF1, 0xE0, 0x00, 0x00, 0x00, 0xFF, 0xBF, - 0xFF, 0xFF, 0xFF, 0xE3, 0xE0, 0x00, 0x00, 0x00, - 0xFE, 0xBF, 0xFF, 0xFF, 0xFF, 0xE3, 0xC0, 0x00, - 0x00, 0x00, 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0xC7, - 0xC0, 0x00, 0x00, 0x01, 0xFE, 0xBF, 0xFF, 0xFF, - 0xFF, 0xC7, 0x80, 0x00, 0x00, 0x01, 0xFE, 0x9F, - 0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00, 0x00, 0x01, - 0xFE, 0x07, 0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00, - 0x00, 0x01, 0xFE, 0x87, 0xFF, 0xFF, 0xFF, 0x9F, - 0x80, 0x00, 0x00, 0x01, 0xFD, 0x33, 0xFF, 0xFF, - 0xFF, 0x9F, 0x80, 0x00, 0x00, 0x01, 0x80, 0xF3, - 0xFF, 0xFF, 0xFF, 0x9E, 0x80, 0x00, 0x00, 0x03, - 0x8B, 0xF9, 0xFF, 0xFF, 0xFF, 0x9F, 0x80, 0x00, - 0x00, 0x02, 0x27, 0xF8, 0xFF, 0xFF, 0xFF, 0x99, - 0x80, 0x00, 0x00, 0x00, 0x07, 0xF8, 0xFF, 0xFF, - 0xFF, 0x00, 0x80, 0x00, 0x00, 0x01, 0x8F, 0xF8, - 0xFF, 0xFF, 0xFE, 0x20, 0x60, 0x00, 0x00, 0x00, - 0xE3, 0xF8, 0xFF, 0xFF, 0xF8, 0x00, 0x30, 0x00, - 0x00, 0x00, 0xF8, 0x78, 0xFF, 0xFF, 0xC0, 0x40, - 0x38, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x7F, 0xFF, - 0x81, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xFC, 0x20, - 0x7F, 0xFF, 0x90, 0x00, 0x1E, 0x00, 0x00, 0x00, - 0x78, 0x10, 0xFF, 0xFF, 0x80, 0x00, 0x0F, 0x80, - 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x80, 0x00, - 0x07, 0xC0, 0x00, 0x00, 0x00, 0x08, 0xFF, 0xFF, - 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x04, - 0x7F, 0xFF, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x10, - 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x01, 0x80, - 0x00, 0x30, 0x00, 0x00, 0x0F, 0xFF, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, 0x4F, 0xFF, - 0x80, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, - 0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x80, 0x03, 0xF0, - 0x00, 0x00, 0x8F, 0xFF, 0x80, 0x00, 0x00, 0x40, - 0x0F, 0xF0, 0x00, 0x04, 0x1F, 0xFF, 0x80, 0x00, - 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x10, 0x1F, 0xFF, - 0xC0, 0x00, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x40, - 0xFF, 0xFF, 0x98, 0x00, 0x00, 0xFF, 0xFF, 0xF0, - 0x00, 0x83, 0xFF, 0xFF, 0x81, 0xE0, 0x01, 0xFF, - 0xFF, 0xF8, 0x02, 0x07, 0xFF, 0xFF, 0x80, 0x3F, - 0x07, 0xE0, 0x00, 0x1C, 0x0C, 0x1F, 0xFF, 0xFF, - 0xF8, 0x03, 0xFF, 0x80, 0x00, 0x1F, 0x78, 0x1F, - 0xFF, 0xFF, 0xFF, 0x80, 0x7F, 0x00, 0x07, 0x0F, - 0xF0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0x0C, 0x07, - 0xFF, 0x83, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x1F, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x07, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, + 0x22, 0x21, 0x21, 0x21, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x26, 0x26, 0x25, 0x28, 0x23, 0x22, 0x21, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x23, 0x25, 0x2a, 0x2b, 0x2c, 0x2d, 0x2d, + 0x2d, 0x2e, 0x2c, 0x2b, 0x2a, 0x25, 0x28, 0x22, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x24, 0x2a, 0x2c, 0x2f, 0x2c, 0x30, 0x30, 0x24, + 0x25, 0x27, 0x2b, 0x2c, 0x2f, 0x31, 0x32, 0x25, + 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x25, + 0x33, 0x34, 0x35, 0x21, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x21, 0x2b, 0x2f, 0x2c, + 0x30, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, 0x33, + 0x2d, 0x27, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x31, + 0x2d, 0x32, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x21, 0x28, 0x2a, 0x34, + 0x25, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x23, 0x32, 0x27, 0x21, 0x36, + 0x2a, 0x2d, 0x2a, 0x28, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x22, 0x26, 0x2c, 0x35, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x25, 0x2f, 0x37, 0x32, 0x22, + 0x36, 0x35, 0x31, 0x27, 0x22, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x23, 0x2a, 0x2f, 0x22, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x26, 0x38, 0x38, 0x35, 0x25, + 0x36, 0x21, 0x2d, 0x2b, 0x24, 0x21, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x21, 0x24, 0x39, 0x39, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x25, 0x2b, 0x30, 0x28, 0x22, + 0x36, 0x36, 0x27, 0x34, 0x30, 0x23, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x21, 0x26, 0x2d, 0x26, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x22, 0x22, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x2d, 0x33, 0x28, 0x21, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x30, 0x2f, 0x23, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x2b, 0x2c, 0x25, 0x21, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x2a, 0x34, 0x36, 0x36, + 0x36, 0x21, 0x22, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x21, 0x23, 0x22, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x28, 0x34, 0x27, 0x22, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x36, + 0x21, 0x21, 0x24, 0x27, 0x21, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x28, 0x27, 0x22, 0x33, 0x24, 0x36, + 0x36, 0x36, 0x36, 0x22, 0x2f, 0x2a, 0x23, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x36, + 0x30, 0x3a, 0x38, 0x24, 0x24, 0x36, 0x36, 0x36, + 0x23, 0x2f, 0x3b, 0x3c, 0x3d, 0x30, 0x25, 0x21, + 0x36, 0x36, 0x36, 0x36, 0x2f, 0x32, 0x23, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x23, + 0x3e, 0x3f, 0x40, 0x3a, 0x22, 0x36, 0x36, 0x21, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x3e, 0x23, 0x21, + 0x36, 0x36, 0x36, 0x36, 0x2f, 0x33, 0x28, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x29, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x2b, + 0x44, 0x40, 0x46, 0x47, 0x35, 0x36, 0x36, 0x26, + 0x43, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x2e, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x31, 0x35, 0x24, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x32, 0x34, 0x36, 0x4d, + 0x4e, 0x25, 0x2f, 0x46, 0x4a, 0x22, 0x23, 0x32, + 0x4f, 0x50, 0x21, 0x31, 0x51, 0x52, 0x53, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x31, 0x35, 0x24, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x29, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x2a, 0x2f, 0x21, 0x3a, + 0x4d, 0x21, 0x31, 0x54, 0x55, 0x28, 0x30, 0x2b, + 0x4b, 0x4d, 0x36, 0x23, 0x32, 0x50, 0x3f, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x2e, 0x39, 0x24, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x29, 0x20, 0x29, 0x20, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x2a, 0x38, 0x23, 0x37, + 0x55, 0x36, 0x28, 0x3a, 0x56, 0x57, 0x57, 0x58, + 0x3c, 0x4d, 0x36, 0x36, 0x36, 0x40, 0x40, 0x21, + 0x36, 0x36, 0x36, 0x36, 0x2e, 0x39, 0x24, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x29, 0x29, 0x29, 0x20, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x30, 0x51, 0x23, 0x35, + 0x43, 0x25, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, + 0x5f, 0x60, 0x61, 0x36, 0x31, 0x47, 0x3b, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x31, 0x2c, 0x25, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x30, 0x2f, 0x23, 0x22, + 0x40, 0x62, 0x63, 0x5d, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x66, 0x5e, 0x6a, 0x6b, 0x2a, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x33, 0x2e, 0x26, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x27, 0x2f, 0x23, 0x36, + 0x6c, 0x63, 0x6d, 0x64, 0x5c, 0x66, 0x69, 0x6e, + 0x6f, 0x70, 0x71, 0x69, 0x69, 0x72, 0x6c, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x33, 0x34, 0x27, 0x22, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x27, 0x34, 0x26, 0x73, + 0x74, 0x75, 0x76, 0x64, 0x65, 0x77, 0x69, 0x78, + 0x70, 0x71, 0x71, 0x71, 0x72, 0x5f, 0x5e, 0x21, + 0x36, 0x36, 0x36, 0x36, 0x25, 0x38, 0x2a, 0x23, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x26, 0x2d, 0x33, 0x79, + 0x63, 0x7a, 0x7b, 0x5c, 0x66, 0x69, 0x6e, 0x7c, + 0x71, 0x71, 0x69, 0x7d, 0x7e, 0x7a, 0x7f, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x21, 0x51, 0x2b, 0x28, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x26, 0x2d, 0x32, 0x24, + 0x80, 0x81, 0x64, 0x82, 0x77, 0x69, 0x71, 0x71, + 0x69, 0x83, 0x84, 0x85, 0x7a, 0x85, 0x86, 0x36, + 0x21, 0x2b, 0x23, 0x36, 0x36, 0x39, 0x2e, 0x26, + 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x27, 0x2d, 0x33, 0x21, + 0x87, 0x88, 0x89, 0x72, 0x67, 0x66, 0x5f, 0x89, + 0x8a, 0x63, 0x85, 0x8b, 0x8c, 0x8d, 0x41, 0x36, + 0x36, 0x2d, 0x3a, 0x35, 0x36, 0x24, 0x51, 0x32, + 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x30, 0x2f, 0x33, 0x21, + 0x55, 0x8e, 0x8f, 0x8a, 0x7d, 0x5e, 0x90, 0x7e, + 0x75, 0x75, 0x90, 0x62, 0x40, 0x3f, 0x49, 0x23, + 0x36, 0x24, 0x3a, 0x3a, 0x24, 0x36, 0x2e, 0x31, + 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x21, 0x28, 0x33, 0x37, 0x25, 0x22, + 0x3b, 0x50, 0x8e, 0x8f, 0x90, 0x7e, 0x90, 0x63, + 0x74, 0x91, 0x92, 0x42, 0x93, 0x4b, 0x45, 0x2c, + 0x36, 0x36, 0x33, 0x39, 0x21, 0x36, 0x22, 0x51, + 0x33, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x22, 0x27, 0x2e, 0x2e, 0x36, 0x21, + 0x94, 0x3f, 0x50, 0x95, 0x96, 0x8f, 0x8f, 0x97, + 0x8e, 0x42, 0x50, 0x43, 0x47, 0x48, 0x48, 0x98, + 0x21, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x39, + 0x2e, 0x27, 0x23, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x22, 0x24, 0x2b, 0x38, 0x28, 0x36, 0x32, + 0x4c, 0x4b, 0x50, 0x50, 0x50, 0x42, 0x42, 0x50, + 0x50, 0x40, 0x45, 0x99, 0x48, 0x48, 0x48, 0x48, + 0x34, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x23, + 0x2f, 0x2b, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x28, 0x32, 0x51, 0x32, 0x28, 0x21, 0x98, + 0x48, 0x47, 0x9a, 0x50, 0x50, 0x50, 0x50, 0x50, + 0x9a, 0x4f, 0x9b, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x93, 0x23, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x2a, 0x2f, 0x2a, 0x28, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x23, 0x30, 0x2e, 0x2c, 0x36, 0x21, 0x51, 0x9b, + 0x48, 0x48, 0x52, 0x3f, 0x50, 0x50, 0x40, 0x4b, + 0x47, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x34, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x2d, 0x31, 0x27, 0x23, 0x21, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23, + 0x27, 0x2c, 0x2d, 0x21, 0x36, 0x28, 0x44, 0x48, + 0x48, 0x48, 0x48, 0x47, 0x46, 0x4f, 0x47, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x9c, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x28, 0x51, 0x39, 0x26, 0x22, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x25, + 0x35, 0x51, 0x28, 0x36, 0x36, 0x9d, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x9b, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x4f, 0x28, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x28, 0x38, 0x2b, 0x25, 0x22, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, 0x33, + 0x51, 0x25, 0x36, 0x36, 0x23, 0x40, 0x9b, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x9b, 0x99, 0x2b, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x30, 0x2f, 0x33, 0x24, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x21, 0x23, 0x30, 0x34, + 0x27, 0x36, 0x36, 0x36, 0x2a, 0x40, 0x47, 0x48, + 0x48, 0x48, 0x48, 0x9b, 0x99, 0x99, 0x9b, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x9b, 0x47, 0x52, + 0x46, 0x4f, 0x37, 0x21, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x30, 0x34, 0x2a, 0x23, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x22, 0x25, 0x39, 0x2c, + 0x36, 0x36, 0x36, 0x21, 0x31, 0x4e, 0x9a, 0x4c, + 0x47, 0x9b, 0x9b, 0x52, 0x46, 0x4f, 0x52, 0x9b, + 0x9b, 0x9b, 0x47, 0x4f, 0x45, 0x9a, 0x93, 0x93, + 0x3f, 0x93, 0x98, 0x28, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x39, 0x2c, 0x26, + 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x23, 0x2a, 0x34, 0x28, + 0x36, 0x36, 0x36, 0x22, 0x38, 0x98, 0x44, 0x99, + 0x9b, 0x48, 0x48, 0x9b, 0x4c, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x47, 0x52, 0x46, 0x43, 0x93, + 0x40, 0x40, 0x43, 0x53, 0x21, 0x23, 0x33, 0x23, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x2f, 0x32, + 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x21, 0x24, 0x2b, 0x31, 0x36, + 0x36, 0x22, 0x36, 0x24, 0x9e, 0x4f, 0x9b, 0x48, + 0x48, 0x48, 0x48, 0x9b, 0x99, 0x9f, 0x52, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x47, + 0x4f, 0x9a, 0x3f, 0x46, 0x38, 0x36, 0x21, 0x30, + 0x26, 0x36, 0x36, 0x36, 0x36, 0x36, 0x39, 0x2c, + 0x25, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x26, 0x2e, 0x33, 0x36, + 0x25, 0x25, 0x36, 0x4d, 0x52, 0x48, 0x48, 0x48, + 0x47, 0x9f, 0x48, 0x48, 0x48, 0xa0, 0xa1, 0xa2, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x47, 0x44, 0x93, 0x43, 0x23, 0x36, 0x36, + 0x26, 0x24, 0x36, 0x36, 0x36, 0x36, 0x28, 0x2f, + 0x2a, 0x23, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x2a, 0x51, 0x24, 0x36, + 0x2a, 0x36, 0x28, 0x44, 0x48, 0x48, 0x48, 0x48, + 0xa3, 0xa4, 0x48, 0x48, 0x9f, 0xa5, 0xa6, 0x9f, + 0x48, 0x48, 0x48, 0xa2, 0xa7, 0x47, 0x48, 0x48, + 0x48, 0x48, 0x9b, 0x4b, 0x44, 0x37, 0x36, 0x23, + 0x28, 0x30, 0x22, 0x36, 0x36, 0x36, 0x36, 0x2d, + 0x35, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x21, 0x28, 0x2b, 0x34, 0x36, 0x25, + 0x24, 0x36, 0x4a, 0x48, 0x48, 0x48, 0x48, 0x48, + 0xa8, 0xa1, 0x48, 0x48, 0x9f, 0xa9, 0xa6, 0x9f, + 0x48, 0x48, 0xaa, 0xa1, 0xa5, 0x9f, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x9b, 0x52, 0x3f, 0x21, 0x30, + 0x35, 0x25, 0x30, 0x36, 0x36, 0x36, 0x36, 0x32, + 0x2d, 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x22, 0x26, 0x2e, 0x35, 0x36, 0x2a, + 0x36, 0x24, 0x4f, 0x48, 0x52, 0x52, 0x48, 0x48, + 0xab, 0xac, 0xa0, 0x48, 0xad, 0xa6, 0xa6, 0x9f, + 0x48, 0xa2, 0xa9, 0xa6, 0xa2, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x47, 0x32, 0x30, + 0x2a, 0x23, 0x30, 0x23, 0x36, 0x36, 0x36, 0x21, + 0x2f, 0x32, 0x23, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x21, 0x23, 0x2a, 0x51, 0x28, 0x28, 0x25, + 0x36, 0x3a, 0x48, 0x48, 0xae, 0xaf, 0x48, 0x48, + 0xad, 0xac, 0xa1, 0x9f, 0xa2, 0xa9, 0xa9, 0xa2, + 0x48, 0xab, 0x78, 0xa7, 0x48, 0x48, 0x48, 0x48, + 0x9f, 0x48, 0x48, 0x48, 0x48, 0x48, 0x38, 0x21, + 0x36, 0x36, 0x22, 0x27, 0x36, 0x36, 0x36, 0x36, + 0x2e, 0x35, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x22, 0x25, 0x2c, 0x34, 0x36, 0x30, 0x21, + 0x23, 0x43, 0x48, 0x48, 0xb0, 0xb1, 0xb2, 0x9f, + 0x48, 0xb3, 0xa5, 0xb3, 0xab, 0xa9, 0xa9, 0xb3, + 0xb4, 0xa9, 0xb5, 0xb0, 0x48, 0x48, 0xa0, 0xa5, + 0xa1, 0xad, 0x48, 0x48, 0x48, 0x48, 0x94, 0x36, + 0x36, 0x36, 0x36, 0x32, 0x36, 0x36, 0x36, 0x36, + 0x2a, 0x2e, 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x23, 0x2a, 0x51, 0x25, 0x21, 0x2a, 0x36, + 0x2e, 0x9b, 0x48, 0x48, 0x48, 0xb6, 0xb7, 0xa4, + 0xa2, 0xa7, 0xb5, 0x78, 0x6f, 0x6f, 0x6e, 0x6f, + 0xa9, 0xb5, 0xab, 0x48, 0x9f, 0xab, 0xa9, 0xa1, + 0xaa, 0x48, 0x48, 0x48, 0x48, 0x48, 0x98, 0x36, + 0x36, 0x36, 0x36, 0x32, 0x36, 0x36, 0x36, 0x36, + 0x22, 0x2f, 0x30, 0x22, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x22, 0x25, 0x2c, 0x34, 0x36, 0x24, 0x28, 0x36, + 0x54, 0x48, 0x48, 0x48, 0x48, 0xa2, 0xa8, 0xa1, + 0xa5, 0xa6, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x6f, + 0x6f, 0x78, 0xa5, 0xa0, 0xa0, 0x78, 0xa6, 0xa2, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x9a, 0x36, + 0x36, 0x36, 0x36, 0x30, 0x36, 0x36, 0x36, 0x36, + 0x21, 0x2f, 0x32, 0x23, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x28, 0x32, 0x2f, 0x28, 0x36, 0x27, 0x22, 0x21, + 0x43, 0x48, 0x4b, 0xa2, 0x9f, 0x48, 0xa2, 0xa1, + 0xb8, 0x6e, 0x6e, 0xb5, 0x78, 0x6f, 0x78, 0x78, + 0x6e, 0x6f, 0x78, 0xb5, 0xa6, 0xa1, 0xa0, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x4b, 0x21, + 0x36, 0x36, 0x21, 0x26, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x34, 0x2b, 0x28, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x25, 0x2c, 0x39, 0x36, 0x36, 0x30, 0x22, 0x25, + 0x52, 0x48, 0xa3, 0xb1, 0xb6, 0xb3, 0xaa, 0xac, + 0x68, 0x68, 0x6e, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, + 0x78, 0x6f, 0x6f, 0xb5, 0xa6, 0xb4, 0x48, 0x9f, + 0xb4, 0xb4, 0xa2, 0x9f, 0x48, 0x48, 0x4f, 0x21, + 0x36, 0x36, 0x22, 0x26, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x2c, 0x35, 0x24, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x30, 0x2d, 0x21, 0x36, 0x36, 0x32, 0x23, 0x2a, + 0x47, 0x48, 0xa2, 0xb6, 0xaf, 0xb9, 0xba, 0x68, + 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x78, + 0x6f, 0x6f, 0xa6, 0x6f, 0xb5, 0xa0, 0xaa, 0xa6, + 0xa6, 0xa9, 0xb2, 0xb3, 0x48, 0x48, 0x4c, 0x22, + 0x36, 0x36, 0x24, 0x23, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x2c, 0x39, 0x24, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28, + 0x33, 0x2e, 0x36, 0x36, 0x23, 0x31, 0x27, 0x39, + 0x9b, 0x48, 0x48, 0x48, 0xb0, 0xb0, 0xba, 0xb8, + 0x68, 0x68, 0x69, 0x78, 0x6f, 0xb5, 0x6f, 0xb5, + 0x78, 0x78, 0x78, 0x78, 0x78, 0xa5, 0xbb, 0xa9, + 0xa5, 0x48, 0x48, 0x48, 0x48, 0x48, 0x4c, 0x23, + 0x36, 0x36, 0x26, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x2c, 0x39, 0x24, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28, + 0x2b, 0x39, 0x36, 0x36, 0x36, 0x26, 0x32, 0x31, + 0x9b, 0x48, 0x48, 0x48, 0x48, 0x9f, 0xac, 0x68, + 0xbc, 0x6e, 0x6e, 0x6e, 0xb5, 0x6f, 0x6e, 0x6f, + 0x6f, 0x78, 0x78, 0xb5, 0xb5, 0xa5, 0x9f, 0x9f, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x46, 0x22, + 0x36, 0x21, 0x26, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x2c, 0x35, 0x24, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, + 0x35, 0x39, 0x36, 0x36, 0x36, 0x36, 0x26, 0x2d, + 0x9b, 0x48, 0x48, 0xb0, 0xaa, 0xb3, 0xbd, 0xb8, + 0xb8, 0x68, 0x6e, 0x6e, 0xb5, 0x6f, 0x78, 0x6e, + 0x78, 0x6f, 0x78, 0x78, 0xb5, 0xa9, 0xa2, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x9a, 0x36, + 0x24, 0x27, 0xbe, 0x24, 0x25, 0x28, 0x21, 0x36, + 0x36, 0x34, 0x2b, 0x28, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x25, + 0x39, 0x4d, 0xbf, 0x84, 0x81, 0x57, 0x21, 0x39, + 0x52, 0x48, 0x48, 0x62, 0xb1, 0xc0, 0xc1, 0xc1, + 0xb8, 0xb8, 0x68, 0xbc, 0x6e, 0x6e, 0x6e, 0x78, + 0x78, 0x78, 0x78, 0x6e, 0x78, 0xa9, 0xa0, 0xab, + 0xb3, 0xa2, 0x48, 0x48, 0x48, 0x48, 0x53, 0x28, + 0x23, 0x36, 0x36, 0x36, 0x21, 0x28, 0x2c, 0x30, + 0x21, 0x38, 0x33, 0x28, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x21, 0x22, 0x22, 0x28, 0x30, + 0x2d, 0xc2, 0x7a, 0xc3, 0xc4, 0xc4, 0x7f, 0x22, + 0x51, 0x52, 0x48, 0x48, 0xb0, 0xaa, 0xa8, 0xbd, + 0x68, 0xb8, 0xb8, 0x68, 0x68, 0x6e, 0x6e, 0x6f, + 0x6e, 0x6e, 0xb5, 0x6e, 0x78, 0xab, 0xab, 0xb5, + 0x78, 0xa6, 0xb3, 0xc5, 0xac, 0xac, 0xc6, 0x61, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x30, 0x32, + 0x25, 0x4d, 0x2b, 0x28, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x21, 0x23, 0x24, 0x26, 0x30, 0x33, 0x31, + 0x4d, 0x91, 0x5b, 0xc3, 0xc4, 0xc4, 0xc4, 0x5a, + 0x21, 0x2e, 0x46, 0x48, 0x48, 0x48, 0xb0, 0x64, + 0xc1, 0xb8, 0xb8, 0xb8, 0x68, 0x71, 0x6e, 0x6e, + 0x6f, 0x71, 0x6f, 0x6f, 0xa6, 0xa0, 0x9f, 0xb4, + 0xb4, 0xa0, 0xa1, 0xb7, 0xc7, 0x69, 0x66, 0xc8, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x26, 0x25, + 0x83, 0xc9, 0x2c, 0x25, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x28, 0x30, 0x35, 0x2d, 0x2f, 0x37, 0x4a, + 0x60, 0x85, 0xca, 0xcb, 0xc4, 0xc4, 0xc4, 0x82, + 0x86, 0x36, 0x32, 0x3f, 0xa2, 0xa4, 0xa8, 0xa9, + 0xb8, 0xb8, 0xb8, 0xb8, 0x68, 0x6e, 0x6e, 0x6e, + 0x6e, 0x71, 0x6f, 0x71, 0xa6, 0xb4, 0x9f, 0x9f, + 0x48, 0x48, 0x48, 0xcc, 0xc3, 0xc7, 0xcd, 0xce, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x57, + 0x77, 0x66, 0x34, 0x27, 0x22, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x23, 0x30, 0x31, 0xcf, 0x91, 0x7e, 0x90, 0x90, + 0x8b, 0x5b, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0x5d, 0xd0, 0x36, 0x24, 0xd1, 0xb1, 0xaf, 0xaa, + 0xba, 0xb8, 0x68, 0x68, 0x68, 0x71, 0x6e, 0x6e, + 0x6e, 0x6f, 0x6e, 0x78, 0xa1, 0xa9, 0xa1, 0xb0, + 0x9f, 0x9b, 0x99, 0xcc, 0x64, 0x5c, 0x8b, 0xd0, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x73, 0x5d, + 0x82, 0x5c, 0xd2, 0x2a, 0x23, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x24, 0x2b, 0xcf, 0x8b, 0x5b, 0x76, 0x5b, 0x5b, + 0x7b, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc7, 0x5e, 0x22, 0x36, 0x21, 0x3a, 0x99, 0x48, + 0xa2, 0xa8, 0xb7, 0xc1, 0xb8, 0x68, 0x68, 0xbc, + 0x68, 0x6e, 0xb5, 0xb4, 0xb4, 0xab, 0xb5, 0xa1, + 0xb0, 0x4f, 0x3f, 0xd3, 0x7b, 0x7b, 0x85, 0x80, + 0xbe, 0x36, 0x36, 0x36, 0x21, 0xd4, 0x7e, 0x7b, + 0x64, 0x64, 0xd5, 0x35, 0x24, 0x21, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x26, 0x31, 0xd6, 0x5b, 0x64, 0xc3, 0xc3, 0xcb, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0x66, 0xd7, 0x36, 0x36, 0x36, 0x2c, 0x4b, + 0xd8, 0xd9, 0xb3, 0xa8, 0xbd, 0xbd, 0xbd, 0xbd, + 0xa9, 0xab, 0xb3, 0xa5, 0xa2, 0x9f, 0xa2, 0xa1, + 0x6a, 0x9a, 0x3f, 0xda, 0x76, 0x76, 0x7a, 0x63, + 0xdb, 0xdc, 0x86, 0xdc, 0xdd, 0x90, 0x5b, 0x64, + 0xc3, 0xc3, 0xde, 0x2d, 0x27, 0x23, 0x21, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x26, 0x2d, 0x91, 0x5b, 0x64, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc7, 0x83, 0xce, 0x36, 0x36, 0x36, 0x30, + 0xb1, 0xd9, 0x48, 0xa1, 0xb2, 0xb0, 0xb0, 0xb3, + 0xa2, 0x48, 0xa7, 0xbd, 0xa9, 0xa2, 0x48, 0x9f, + 0xaa, 0x9a, 0x3f, 0xb1, 0x5b, 0x7b, 0xdf, 0x85, + 0x7e, 0x90, 0x63, 0x90, 0x85, 0x5b, 0xc3, 0xc4, + 0xc4, 0xcb, 0x5d, 0xd5, 0x39, 0x26, 0x23, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x26, 0x2d, 0xe0, 0xdf, 0x64, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc7, 0x88, 0x36, 0x36, 0x36, 0x36, + 0x2d, 0x9b, 0x48, 0xb9, 0xaf, 0xa2, 0xa2, 0xb9, + 0xa8, 0x9f, 0x48, 0xa7, 0xb7, 0xd9, 0x48, 0x48, + 0x9b, 0x45, 0x3f, 0xe1, 0x6d, 0x7b, 0xca, 0xdf, + 0x7a, 0x8b, 0x8b, 0x7a, 0x5b, 0x64, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc3, 0xe2, 0x37, 0x35, 0x26, 0x23, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x26, 0x2e, 0xe0, 0x7a, 0x7b, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc7, 0x72, 0x73, 0x36, 0x36, 0x36, + 0x24, 0x52, 0x48, 0xa3, 0xaf, 0x9f, 0x48, 0xb6, + 0xaf, 0xa2, 0x48, 0x9f, 0xe3, 0xd8, 0x48, 0x48, + 0x48, 0x46, 0x42, 0xd6, 0x7a, 0x7b, 0x64, 0x7b, + 0x76, 0x5b, 0x5b, 0x76, 0x7b, 0xc3, 0xc4, 0xc4, + 0xc4, 0xc4, 0xcb, 0x64, 0xe2, 0x4d, 0x2c, 0x27, + 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x25, 0x31, 0xe4, 0x8b, 0x7b, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc7, 0x89, 0xbe, 0x36, 0x36, + 0x32, 0x47, 0x48, 0x4f, 0xa0, 0x48, 0x48, 0xe3, + 0x92, 0x9f, 0x48, 0x9f, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x4b, 0x2f, 0x8f, 0x7a, 0x7b, 0xc3, 0xcb, + 0xc3, 0x64, 0x64, 0xc3, 0xc3, 0xcb, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc3, 0x5d, 0xe5, 0x2c, + 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x25, 0x31, 0xe4, 0x85, 0x7b, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0x66, 0x57, 0x27, 0x4d, + 0x4b, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x99, 0x34, 0xbe, 0xdb, 0x7a, 0x7b, 0xc3, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc3, 0xe4, + 0x32, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x26, 0x2d, 0xe4, 0x85, 0x7b, 0xcb, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc7, 0x5f, 0x92, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x44, + 0x35, 0x36, 0xce, 0xdd, 0x7a, 0x7b, 0xcb, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xcb, 0xc3, 0xe1, + 0x2b, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23, + 0x30, 0x2f, 0xd6, 0x8b, 0x7b, 0xcb, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0x66, 0x89, 0x45, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x9b, 0x4e, 0x25, + 0x36, 0x36, 0x61, 0xdb, 0x6d, 0x64, 0xcb, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xcb, 0x7b, 0xdf, 0xe5, + 0x32, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28, + 0x33, 0xe6, 0x63, 0xdf, 0xc3, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc3, 0x72, 0x81, 0xe7, + 0x46, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x3f, 0x2c, 0x36, 0x36, + 0x36, 0x36, 0xe8, 0x8f, 0x6d, 0x64, 0xcb, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc3, 0xca, 0x8b, 0xcf, 0x2c, + 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, + 0x35, 0x96, 0x75, 0xca, 0xc3, 0xcb, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xcb, 0x7b, 0x81, 0xdb, + 0x73, 0x3b, 0x44, 0x9b, 0x48, 0x48, 0x48, 0x9b, + 0x99, 0x43, 0x94, 0x2c, 0x21, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x73, 0xdb, 0x7a, 0x7b, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0x64, 0x76, 0x7a, 0x91, 0xd5, 0x31, 0x30, + 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, + 0x39, 0x97, 0x75, 0xdf, 0x7b, 0x64, 0xc3, 0xc3, + 0xcb, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0x7b, 0x7a, 0xe9, + 0xea, 0x36, 0x21, 0x26, 0x2b, 0x39, 0x33, 0x30, + 0x23, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x21, 0xea, 0xdd, 0x8b, 0x7b, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc3, 0x64, 0x64, + 0x76, 0x85, 0xe0, 0xd5, 0x34, 0x2b, 0x27, 0x28, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28, + 0x33, 0xeb, 0x63, 0x7e, 0x7a, 0x6d, 0xdf, 0x5b, + 0x76, 0x7b, 0x64, 0x64, 0xc3, 0xcb, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xcb, 0x76, 0x85, 0xdb, + 0x79, 0x22, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x21, 0xec, 0xdd, 0x75, 0x76, 0xc3, 0xc4, + 0xc4, 0xc4, 0xcb, 0xc3, 0x64, 0x76, 0xdf, 0x8b, + 0xd6, 0xd5, 0x2f, 0x35, 0x30, 0x24, 0x22, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23, + 0x27, 0x31, 0xed, 0xeb, 0xdd, 0x74, 0x63, 0x90, + 0x7e, 0x75, 0x8b, 0x6d, 0xdf, 0x76, 0x64, 0xc3, + 0xcb, 0xcb, 0xcb, 0xcb, 0x64, 0x7a, 0x84, 0xee, + 0x79, 0xbe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x21, 0xea, 0xee, 0x63, 0x6d, 0x7b, 0x64, + 0xcb, 0xc3, 0x64, 0x7b, 0xdf, 0x75, 0x63, 0x96, + 0x38, 0x39, 0x2a, 0x24, 0x23, 0x21, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x28, 0x27, 0x35, 0x2d, 0x41, 0xd5, 0xe7, 0x8f, + 0xdb, 0xdd, 0xe9, 0x74, 0x84, 0x90, 0x85, 0x6d, + 0x5b, 0x7b, 0x7b, 0xca, 0x6d, 0x90, 0xdb, 0xef, + 0xec, 0x22, 0x36, 0x36, 0x28, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x25, 0x36, + 0x36, 0x21, 0xd4, 0x80, 0xe9, 0x7e, 0x6d, 0x76, + 0xca, 0x76, 0x6d, 0x85, 0x63, 0xdb, 0xd5, 0x34, + 0x33, 0x26, 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x23, 0x24, 0x27, 0x2a, 0x35, 0x2e, 0x2f, + 0x41, 0xf0, 0xf1, 0x6c, 0x80, 0xee, 0xdb, 0x74, + 0x84, 0x90, 0x75, 0x7e, 0x74, 0x8f, 0xef, 0x79, + 0xe8, 0x2b, 0x9d, 0x41, 0x2f, 0x34, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x34, 0x2f, 0x38, + 0x4d, 0x37, 0xf2, 0xf3, 0x8f, 0x74, 0x63, 0x7e, + 0x75, 0x7e, 0x63, 0xe9, 0x88, 0xe6, 0x31, 0x2a, + 0x24, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x21, 0x22, 0x23, 0x24, 0x26, 0x30, + 0x33, 0x39, 0x2e, 0x51, 0x41, 0xd2, 0x6c, 0xf3, + 0x80, 0xee, 0xee, 0xee, 0xf4, 0xf3, 0xd7, 0xf5, + 0x41, 0x34, 0x35, 0x32, 0x30, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x30, 0x2a, + 0x2b, 0x34, 0xf6, 0xec, 0xf7, 0x8f, 0xdd, 0xe9, + 0xe9, 0xdd, 0xee, 0x6c, 0x41, 0x39, 0x27, 0x28, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22, + 0x28, 0x24, 0x26, 0x2a, 0x33, 0x2c, 0x2f, 0x41, + 0xf8, 0xd7, 0x79, 0x79, 0x79, 0xec, 0xf9, 0x51, + 0x39, 0x30, 0x24, 0x23, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x22, 0x23, + 0x24, 0x2a, 0x31, 0xfa, 0xea, 0x79, 0xf3, 0x80, + 0xf7, 0xdc, 0xfb, 0x2f, 0x35, 0x26, 0x23, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x21, 0x22, 0x23, 0x28, 0x25, 0x30, 0x2b, + 0x31, 0x2f, 0xf6, 0xfa, 0xfa, 0x2f, 0x2e, 0x33, + 0x26, 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x28, 0x27, 0x35, 0x34, 0xfa, 0xfa, 0xfa, + 0xfc, 0xf6, 0x2e, 0x33, 0x25, 0x23, 0x21, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x23, 0x28, + 0x26, 0x30, 0x32, 0x2b, 0x33, 0x2a, 0x26, 0x28, + 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x21, 0x23, 0x25, 0x30, 0x33, 0x35, 0x35, + 0x2b, 0x2a, 0x26, 0x28, 0x22, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x21, 0x22, 0x23, 0x28, 0x28, 0x23, 0x22, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x21, 0x23, 0x28, 0x24, 0x24, + 0x28, 0x23, 0x22, 0x21, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, }; -unsigned char linux_logo16_red[0]; -unsigned char linux_logo16_green[0]; -unsigned char linux_logo16_blue[0]; unsigned char linux_logo16[0]; -#else +#endif /* INCLUDE_LINUX_LOGO_DATA */ -/* prototypes only */ -extern unsigned char linux_logo_red[]; -extern unsigned char linux_logo_green[]; -extern unsigned char linux_logo_blue[]; -extern unsigned char linux_logo[]; -extern unsigned char linux_logo_bw[]; -extern unsigned char linux_logo16_red[]; -extern unsigned char linux_logo16_green[]; -extern unsigned char linux_logo16_blue[]; -extern unsigned char linux_logo16[]; +#include -#endif diff -u --recursive --new-file v2.4.5/linux/include/asm-sparc64/sab82532.h linux/include/asm-sparc64/sab82532.h --- v2.4.5/linux/include/asm-sparc64/sab82532.h Fri Apr 14 09:37:10 2000 +++ linux/include/asm-sparc64/sab82532.h Mon Jun 11 19:15:27 2001 @@ -1,4 +1,4 @@ -/* $Id: sab82532.h,v 1.6 2000/04/13 07:22:35 ecd Exp $ +/* $Id: sab82532.h,v 1.7 2001/05/23 23:09:10 ecd Exp $ * sab82532.h: Register Definitions for the Siemens SAB82532 DUSCC * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -9,6 +9,7 @@ #include #include +#include struct sab82532_async_rd_regs { u8 rfifo[0x20]; /* Receive FIFO */ @@ -150,7 +151,7 @@ int close_delay; unsigned short closing_wait; unsigned short closing_wait2; - int all_sent; + unsigned long irqflags; int is_console; unsigned char interrupt_mask0; unsigned char interrupt_mask1; @@ -166,10 +167,7 @@ int blocked_open; long session; long pgrp; - unsigned char *xmit_buf; - int xmit_head; - int xmit_tail; - int xmit_cnt; + struct circ_buf xmit; struct tq_struct tqueue; struct tq_struct tqueue_hangup; struct async_icount icount; @@ -181,6 +179,11 @@ struct sab82532 *next; struct sab82532 *prev; }; + + +/* irqflags bits */ +#define SAB82532_ALLS 0x00000001 +#define SAB82532_XPR 0x00000002 /* RFIFO Status Byte */ diff -u --recursive --new-file v2.4.5/linux/include/asm-sparc64/socket.h linux/include/asm-sparc64/socket.h --- v2.4.5/linux/include/asm-sparc64/socket.h Sat Feb 3 11:26:44 2001 +++ linux/include/asm-sparc64/socket.h Wed Jun 20 21:00:55 2001 @@ -1,4 +1,4 @@ -/* $Id: socket.h,v 1.9 2001/01/30 07:48:30 davem Exp $ */ +/* $Id: socket.h,v 1.10 2001/06/13 16:25:03 davem Exp $ */ #ifndef _ASM_SOCKET_H #define _ASM_SOCKET_H @@ -63,6 +63,7 @@ /* level. For writing rarp and */ /* other similar things on the */ /* user level. */ +#define SOCK_MAX (SOCK_PACKET+1) #endif #endif /* _ASM_SOCKET_H */ diff -u --recursive --new-file v2.4.5/linux/include/asm-sparc64/softirq.h linux/include/asm-sparc64/softirq.h --- v2.4.5/linux/include/asm-sparc64/softirq.h Sun Aug 6 12:42:21 2000 +++ linux/include/asm-sparc64/softirq.h Tue Jun 12 11:08:46 2001 @@ -11,8 +11,21 @@ #include /* for membar() */ #define local_bh_disable() (local_bh_count(smp_processor_id())++) -#define local_bh_enable() (local_bh_count(smp_processor_id())--) - +#define __local_bh_enable() (local_bh_count(smp_processor_id())--) +#define local_bh_enable() \ +do { if (!--local_bh_count(smp_processor_id()) && \ + softirq_pending(smp_processor_id())) { \ + do_softirq(); \ + __sti(); \ + } \ +} while (0) +#define __cpu_raise_softirq(cpu, nr) (softirq_pending(cpu) |= (1<d_vfsmnt); + return dentry->d_mounted; } +extern struct vfsmount *lookup_mnt(struct vfsmount *, struct dentry *); #endif /* __KERNEL__ */ #endif /* __LINUX_DCACHE_H */ diff -u --recursive --new-file v2.4.5/linux/include/linux/devfs_fs_kernel.h linux/include/linux/devfs_fs_kernel.h --- v2.4.5/linux/include/linux/devfs_fs_kernel.h Fri May 25 18:01:28 2001 +++ linux/include/linux/devfs_fs_kernel.h Tue Jul 3 15:42:55 2001 @@ -163,7 +163,7 @@ { return -ENOSYS; } -static inline void *devfs_get_info (devfs_handle_t de, unsigned long size) +static inline void *devfs_get_info (devfs_handle_t de) { return NULL; } diff -u --recursive --new-file v2.4.5/linux/include/linux/ext2_fs.h linux/include/linux/ext2_fs.h --- v2.4.5/linux/include/linux/ext2_fs.h Fri May 25 18:01:27 2001 +++ linux/include/linux/ext2_fs.h Tue Jul 3 15:42:55 2001 @@ -498,16 +498,17 @@ * Ext2 directory file types. Only the low 3 bits are used. The * other bits are reserved for now. */ -#define EXT2_FT_UNKNOWN 0 -#define EXT2_FT_REG_FILE 1 -#define EXT2_FT_DIR 2 -#define EXT2_FT_CHRDEV 3 -#define EXT2_FT_BLKDEV 4 -#define EXT2_FT_FIFO 5 -#define EXT2_FT_SOCK 6 -#define EXT2_FT_SYMLINK 7 - -#define EXT2_FT_MAX 8 +enum { + EXT2_FT_UNKNOWN, + EXT2_FT_REG_FILE, + EXT2_FT_DIR, + EXT2_FT_CHRDEV, + EXT2_FT_BLKDEV, + EXT2_FT_FIFO, + EXT2_FT_SOCK, + EXT2_FT_SYMLINK, + EXT2_FT_MAX +}; /* * EXT2_DIR_PAD defines the directory entries boundaries @@ -552,9 +553,6 @@ extern unsigned long ext2_count_free (struct buffer_head *, unsigned); /* dir.c */ -extern int ext2_check_dir_entry (const char *, struct inode *, - struct ext2_dir_entry_2 *, struct buffer_head *, - unsigned long); /* file.c */ extern int ext2_read (struct inode *, struct file *, char *, int); @@ -613,6 +611,14 @@ /* dir.c */ extern struct file_operations ext2_dir_operations; +extern int ext2_add_link (struct dentry *, struct inode *); +extern ino_t ext2_inode_by_name(struct inode *, struct dentry *); +extern int ext2_make_empty(struct inode *, struct inode *); +extern struct ext2_dir_entry_2 * ext2_find_entry (struct inode *,struct dentry *, struct page **); +extern int ext2_delete_entry (struct ext2_dir_entry_2 *, struct page *); +extern int ext2_empty_dir (struct inode *); +extern struct ext2_dir_entry_2 * ext2_dotdot (struct inode *, struct page **); +extern void ext2_set_link(struct inode *, struct ext2_dir_entry_2 *, struct page *, struct inode *); /* file.c */ extern struct inode_operations ext2_file_inode_operations; diff -u --recursive --new-file v2.4.5/linux/include/linux/fs.h linux/include/linux/fs.h --- v2.4.5/linux/include/linux/fs.h Fri May 25 18:01:28 2001 +++ linux/include/linux/fs.h Tue Jul 3 15:42:55 2001 @@ -204,15 +204,22 @@ extern void buffer_init(unsigned long); extern void inode_init(unsigned long); +extern void mnt_init(unsigned long); /* bh state bits */ -#define BH_Uptodate 0 /* 1 if the buffer contains valid data */ -#define BH_Dirty 1 /* 1 if the buffer is dirty */ -#define BH_Lock 2 /* 1 if the buffer is locked */ -#define BH_Req 3 /* 0 if the buffer has been invalidated */ -#define BH_Mapped 4 /* 1 if the buffer has a disk mapping */ -#define BH_New 5 /* 1 if the buffer is new and not yet written out */ -#define BH_Protected 6 /* 1 if the buffer is protected */ +enum bh_state_bits { + BH_Uptodate, /* 1 if the buffer contains valid data */ + BH_Dirty, /* 1 if the buffer is dirty */ + BH_Lock, /* 1 if the buffer is locked */ + BH_Req, /* 0 if the buffer has been invalidated */ + BH_Mapped, /* 1 if the buffer has a disk mapping */ + BH_New, /* 1 if the buffer is new and not yet written out */ + BH_Protected, /* 1 if the buffer is protected */ + + BH_PrivateStart,/* not a state bit, but the first bit available + * for private allocation by other entities + */ +}; /* * Try to keep the most commonly used fields in single cache lines (16 @@ -835,6 +842,31 @@ int (*remount_fs) (struct super_block *, int *, char *); void (*clear_inode) (struct inode *); void (*umount_begin) (struct super_block *); + + /* Following are for knfsd to interact with "interesting" filesystems + * Currently just reiserfs, but possibly FAT and others later + * + * fh_to_dentry is given a filehandle fragement with length, and a type flag + * and must return a dentry for the referenced object or, if "parent" is + * set, a dentry for the parent of the object. + * If a dentry cannot be found, a "root" dentry should be created and + * flaged as DCACHE_NFSD_DISCONNECTED. nfsd_iget is an example implementation. + * + * dentry_to_fh is given a dentry and must generate the filesys specific + * part of the file handle. Available length is passed in *lenp and used + * length should be returned therein. + * If need_parent is set, then dentry_to_fh should encode sufficient information + * to find the (current) parent. + * dentry_to_fh should return a 1byte "type" which will be passed back in + * the fhtype arguement to fh_to_dentry. Type of 0 is reserved. + * If filesystem was exportable before the introduction of fh_to_dentry, + * types 1 and 2 should be used is that same way as the generic code. + * Type 255 means error. + * + * Lengths are in units of 4bytes, not bytes. + */ + struct dentry * (*fh_to_dentry)(struct super_block *sb, __u32 *fh, int len, int fhtype, int parent); + int (*dentry_to_fh)(struct dentry *, __u32 *fh, int *lenp, int need_parent); }; /* Inode state bits.. */ @@ -1024,7 +1056,7 @@ extern int fs_may_remount_ro(struct super_block *); -extern int try_to_free_buffers(struct page *, int); +extern int try_to_free_buffers(struct page *, unsigned int); extern void refile_buffer(struct buffer_head * buf); /* reiserfs_writepage needs this */ @@ -1312,7 +1344,6 @@ extern struct file_system_type *get_fs_type(const char *name); extern struct super_block *get_super(kdev_t); -extern void put_super(kdev_t); static inline int is_mounted(kdev_t dev) { struct super_block *sb = get_super(dev); diff -u --recursive --new-file v2.4.5/linux/include/linux/ibmtr.h linux/include/linux/ibmtr.h --- v2.4.5/linux/include/linux/ibmtr.h Sun Apr 2 15:38:54 2000 +++ linux/include/linux/ibmtr.h Wed Jun 20 11:13:18 2001 @@ -1,3 +1,6 @@ +#ifndef __LINUX_IBMTR_H__ +#define __LINUX_IBMTR_H__ + /* Definitions for an IBM Token Ring card. */ /* This file is distributed under the GNU GPL */ @@ -452,3 +455,4 @@ unsigned char funct_address[4]; }; +#endif /* __LINUX_IBMTR_H__ */ diff -u --recursive --new-file v2.4.5/linux/include/linux/if_arp.h linux/include/linux/if_arp.h --- v2.4.5/linux/include/linux/if_arp.h Fri May 25 18:02:10 2001 +++ linux/include/linux/if_arp.h Tue Jul 3 15:43:04 2001 @@ -79,6 +79,7 @@ #define ARPHRD_FCFABRIC 787 /* Fibrechannel fabric */ /* 787->799 reserved for fibrechannel media types */ #define ARPHRD_IEEE802_TR 800 /* Magic type ident for TR */ +#define ARPHRD_IEEE80211 801 /* IEEE 802.11 */ #define ARPHRD_VOID 0xFFFF /* Void type, nothing is known */ diff -u --recursive --new-file v2.4.5/linux/include/linux/if_hippi.h linux/include/linux/if_hippi.h --- v2.4.5/linux/include/linux/if_hippi.h Fri May 25 18:02:32 2001 +++ linux/include/linux/if_hippi.h Tue Jul 3 15:46:21 2001 @@ -110,13 +110,13 @@ struct hippi_le_hdr { #if defined (__BIG_ENDIAN_BITFIELD) - unsigned long fc:3; - unsigned long double_wide:1; - unsigned long message_type:4; + __u8 fc:3; + __u8 double_wide:1; + __u8 message_type:4; #elif defined(__LITTLE_ENDIAN_BITFIELD) - unsigned long message_type:4; - unsigned long double_wide:1; - unsigned long fc:3; + __u8 message_type:4; + __u8 double_wide:1; + __u8 fc:3; #endif __u8 dest_switch_addr[3]; #if defined (__BIG_ENDIAN_BITFIELD) diff -u --recursive --new-file v2.4.5/linux/include/linux/if_tun.h linux/include/linux/if_tun.h --- v2.4.5/linux/include/linux/if_tun.h Wed Aug 23 09:30:13 2000 +++ linux/include/linux/if_tun.h Mon Jun 11 19:15:27 2001 @@ -12,7 +12,7 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * $Id: if_tun.h,v 1.1 2000/08/23 05:59:28 davem Exp $ + * $Id: if_tun.h,v 1.2 2001/06/01 18:39:47 davem Exp $ */ #ifndef __IF_TUN_H @@ -32,15 +32,18 @@ #endif struct tun_struct { - char name[8]; + char *name; unsigned long flags; + int attached; + uid_t owner; - struct fasync_struct *fasync; wait_queue_head_t read_wait; + struct sk_buff_head readq; struct net_device dev; - struct sk_buff_head txq; - struct net_device_stats stats; + struct net_device_stats stats; + + struct fasync_struct *fasync; #ifdef TUN_DEBUG int debug; @@ -53,14 +56,8 @@ #endif /* __KERNEL__ */ -/* Number of devices */ -#define TUN_MAX_DEV 255 - -/* TX queue size */ -#define TUN_TXQ_SIZE 10 - -/* Max frame size */ -#define TUN_MAX_FRAME 4096 +/* Read queue size */ +#define TUN_READQ_SIZE 10 /* TUN device flags */ #define TUN_TUN_DEV 0x0001 @@ -70,22 +67,25 @@ #define TUN_FASYNC 0x0010 #define TUN_NOCHECKSUM 0x0020 #define TUN_NO_PI 0x0040 - -#define TUN_IFF_SET 0x1000 +#define TUN_ONE_QUEUE 0x0080 +#define TUN_PERSIST 0x0100 /* Ioctl defines */ -#define TUNSETNOCSUM (('T'<< 8) | 200) -#define TUNSETDEBUG (('T'<< 8) | 201) -#define TUNSETIFF (('T'<< 8) | 202) +#define TUNSETNOCSUM _IOW('T', 200, int) +#define TUNSETDEBUG _IOW('T', 201, int) +#define TUNSETIFF _IOW('T', 202, int) +#define TUNSETPERSIST _IOW('T', 203, int) +#define TUNSETOWNER _IOW('T', 204, int) /* TUNSETIFF ifr flags */ #define IFF_TUN 0x0001 #define IFF_TAP 0x0002 #define IFF_NO_PI 0x1000 +#define IFF_ONE_QUEUE 0x2000 struct tun_pi { - unsigned short flags; - unsigned short proto; + unsigned short flags; + unsigned short proto; }; #define TUN_PKT_STRIP 0x0001 diff -u --recursive --new-file v2.4.5/linux/include/linux/interrupt.h linux/include/linux/interrupt.h --- v2.4.5/linux/include/linux/interrupt.h Fri May 25 18:01:27 2001 +++ linux/include/linux/interrupt.h Tue Jul 3 15:42:55 2001 @@ -74,22 +74,6 @@ asmlinkage void do_softirq(void); extern void open_softirq(int nr, void (*action)(struct softirq_action*), void *data); -static inline void __cpu_raise_softirq(int cpu, int nr) -{ - softirq_active(cpu) |= (1<state)) -#define tasklet_unlock_wait(t) while (test_bit(TASKLET_STATE_RUN, &(t)->state)) { barrier(); } #define tasklet_unlock(t) clear_bit(TASKLET_STATE_RUN, &(t)->state) -#else -#define tasklet_trylock(t) 1 -#define tasklet_unlock_wait(t) do { } while (0) -#define tasklet_unlock(t) do { } while (0) -#endif - -static inline void tasklet_schedule(struct tasklet_struct *t) -{ - if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) { - int cpu = smp_processor_id(); - unsigned long flags; - - local_irq_save(flags); - t->next = tasklet_vec[cpu].list; - tasklet_vec[cpu].list = t; - __cpu_raise_softirq(cpu, TASKLET_SOFTIRQ); - local_irq_restore(flags); - } -} - -static inline void tasklet_hi_schedule(struct tasklet_struct *t) -{ - if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) { - int cpu = smp_processor_id(); - unsigned long flags; - - local_irq_save(flags); - t->next = tasklet_hi_vec[cpu].list; - tasklet_hi_vec[cpu].list = t; - __cpu_raise_softirq(cpu, HI_SOFTIRQ); - local_irq_restore(flags); - } -} +#define tasklet_unlock_wait(t) while (test_bit(TASKLET_STATE_RUN, &(t)->state)) { barrier(); } +extern void tasklet_schedule(struct tasklet_struct *t); +extern void tasklet_hi_schedule(struct tasklet_struct *t); static inline void tasklet_disable_nosync(struct tasklet_struct *t) { @@ -196,7 +148,14 @@ static inline void tasklet_enable(struct tasklet_struct *t) { - atomic_dec(&t->count); + if (atomic_dec_and_test(&t->count)) + tasklet_schedule(t); +} + +static inline void tasklet_hi_enable(struct tasklet_struct *t) +{ + if (atomic_dec_and_test(&t->count)) + tasklet_hi_schedule(t); } extern void tasklet_kill(struct tasklet_struct *t); diff -u --recursive --new-file v2.4.5/linux/include/linux/irq.h linux/include/linux/irq.h --- v2.4.5/linux/include/linux/irq.h Fri May 25 18:01:27 2001 +++ linux/include/linux/irq.h Tue Jul 3 15:42:55 2001 @@ -62,7 +62,4 @@ extern hw_irq_controller no_irq_type; /* needed in every arch ? */ extern void no_action(int cpl, void *dev_id, struct pt_regs *regs); -extern volatile unsigned long irq_err_count; - #endif /* __asm_h */ - diff -u --recursive --new-file v2.4.5/linux/include/linux/irq_cpustat.h linux/include/linux/irq_cpustat.h --- v2.4.5/linux/include/linux/irq_cpustat.h Fri May 25 18:01:26 2001 +++ linux/include/linux/irq_cpustat.h Tue Jul 3 15:42:54 2001 @@ -26,8 +26,7 @@ #endif /* arch independent irq_stat fields */ -#define softirq_active(cpu) __IRQ_STAT((cpu), __softirq_active) -#define softirq_mask(cpu) __IRQ_STAT((cpu), __softirq_mask) +#define softirq_pending(cpu) __IRQ_STAT((cpu), __softirq_pending) #define local_irq_count(cpu) __IRQ_STAT((cpu), __local_irq_count) #define local_bh_count(cpu) __IRQ_STAT((cpu), __local_bh_count) #define syscall_count(cpu) __IRQ_STAT((cpu), __syscall_count) diff -u --recursive --new-file v2.4.5/linux/include/linux/isdn/tpam.h linux/include/linux/isdn/tpam.h --- v2.4.5/linux/include/linux/isdn/tpam.h Wed Dec 31 16:00:00 1969 +++ linux/include/linux/isdn/tpam.h Mon Jul 2 14:07:55 2001 @@ -0,0 +1,56 @@ +/* $Id: tpam.h,v 1.1.2.1 2001/06/08 08:23:46 kai Exp $ + * + * Turbo PAM ISDN driver for Linux. (Kernel Driver) + * + * Copyright 2001 Stelian Pop , Alcôve + * + * For all support questions please contact: + * + * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _TPAM_H_ +#define _TPAM_H_ + +#include +#include + +/* IOCTL commands */ +#define TPAM_CMD_DSPLOAD 0x0001 +#define TPAM_CMD_DSPSAVE 0x0002 +#define TPAM_CMD_DSPRUN 0x0003 +#define TPAM_CMD_LOOPMODEON 0x0004 +#define TPAM_CMD_LOOPMODEOFF 0x0005 + +/* addresses of debug information zones on board */ +#define TPAM_TRAPAUDIT_REGISTER 0x005493e4 +#define TPAM_NCOAUDIT_REGISTER 0x00500000 +#define TPAM_MSGAUDIT_REGISTER 0x008E30F0 + +/* length of debug information zones on board */ +#define TPAM_TRAPAUDIT_LENGTH 10000 +#define TPAM_NCOAUDIT_LENGTH 300000 +#define TPAM_NCOAUDIT_COUNT 30 +#define TPAM_MSGAUDIT_LENGTH 60000 + +/* IOCTL load/save parameter */ +typedef struct tpam_dsp_ioctl { + __u32 address; /* address to load/save data */ + __u32 data_len; /* size of data to be loaded/saved */ + __u8 data[0]; /* data */ +} tpam_dsp_ioctl; + +#endif /* _TPAM_H_ */ diff -u --recursive --new-file v2.4.5/linux/include/linux/isdn.h linux/include/linux/isdn.h --- v2.4.5/linux/include/linux/isdn.h Sat May 19 17:54:14 2001 +++ linux/include/linux/isdn.h Mon Jul 2 14:13:40 2001 @@ -1,4 +1,4 @@ -/* $Id: isdn.h,v 1.111.6.6 2001/05/17 21:15:34 kai Exp $ +/* $Id: isdn.h,v 1.111.6.7 2001/06/30 19:47:51 kai Exp $ * Main header for the Linux ISDN subsystem (linklevel). * @@ -27,6 +27,15 @@ #include +#ifdef CONFIG_COBALT_MICRO_SERVER +/* Save memory */ +#define ISDN_MAX_DRIVERS 2 +#define ISDN_MAX_CHANNELS 8 +#else +#define ISDN_MAX_DRIVERS 32 +#define ISDN_MAX_CHANNELS 64 +#endif + /* New ioctl-codes */ #define IIOCNETAIF _IO('I',1) #define IIOCNETDIF _IO('I',2) @@ -181,14 +190,6 @@ * the correspondent code in isdn.c */ -#ifdef CONFIG_COBALT_MICRO_SERVER -/* Save memory */ -#define ISDN_MAX_DRIVERS 2 -#define ISDN_MAX_CHANNELS 8 -#else -#define ISDN_MAX_DRIVERS 32 -#define ISDN_MAX_CHANNELS 64 -#endif #define ISDN_MINOR_B 0 #define ISDN_MINOR_BMAX (ISDN_MAX_CHANNELS-1) #define ISDN_MINOR_CTRL 64 diff -u --recursive --new-file v2.4.5/linux/include/linux/isdnif.h linux/include/linux/isdnif.h --- v2.4.5/linux/include/linux/isdnif.h Sat May 19 17:54:14 2001 +++ linux/include/linux/isdnif.h Mon Jul 2 14:07:55 2001 @@ -1,4 +1,4 @@ -/* $Id: isdnif.h,v 1.37.6.2 2001/05/17 21:15:34 kai Exp $ +/* $Id: isdnif.h,v 1.37.6.4 2001/06/09 15:14:19 kai Exp $ * Linux ISDN subsystem * @@ -433,6 +433,7 @@ #ifdef CONFIG_ISDN_TTY_FAX T30_s *fax; /* Pointer to ttys fax struct */ #endif + ulong userdata; /* User Data */ } parm; } isdn_ctrl; diff -u --recursive --new-file v2.4.5/linux/include/linux/kernel.h linux/include/linux/kernel.h --- v2.4.5/linux/include/linux/kernel.h Sun May 20 12:11:39 2001 +++ linux/include/linux/kernel.h Tue Jun 12 11:51:43 2001 @@ -125,6 +125,7 @@ unsigned long totalswap; /* Total swap space size */ unsigned long freeswap; /* swap space still available */ unsigned short procs; /* Number of current processes */ + unsigned short pad; /* explicit padding for m68k */ unsigned long totalhigh; /* Total high memory size */ unsigned long freehigh; /* Available high memory size */ unsigned int mem_unit; /* Memory unit size in bytes */ diff -u --recursive --new-file v2.4.5/linux/include/linux/linux_logo.h linux/include/linux/linux_logo.h --- v2.4.5/linux/include/linux/linux_logo.h Wed Sep 30 14:16:33 1998 +++ linux/include/linux/linux_logo.h Mon Jun 11 19:15:27 2001 @@ -18,1428 +18,1403 @@ * but should contain %s to display the version */ -#if LINUX_LOGO_COLORS == 214 +#ifndef __HAVE_ARCH_LINUX_LOGO +#define LINUX_LOGO_COLORS 187 +#endif + +#ifdef INCLUDE_LINUX_LOGO_DATA + +#ifndef __HAVE_ARCH_LINUX_LOGO unsigned char linux_logo_red[] __initdata = { - 0x02, 0x9E, 0xE9, 0xC4, 0x50, 0xC9, 0xC4, 0xE9, - 0x65, 0xE3, 0xC2, 0x25, 0xA4, 0xEC, 0x90, 0xA6, - 0xC4, 0x6A, 0xD1, 0xF3, 0x12, 0xED, 0xA0, 0xC2, - 0xB8, 0xD5, 0xDB, 0xD2, 0x3E, 0x16, 0xEB, 0x54, - 0xA9, 0xCD, 0xF5, 0x0A, 0xBA, 0xB3, 0xDC, 0x74, - 0xCE, 0xF6, 0xD3, 0xC5, 0xEA, 0xB8, 0xED, 0x5E, - 0xE5, 0x26, 0xF4, 0xA9, 0x82, 0x94, 0xE6, 0x38, - 0xF2, 0x0F, 0x7F, 0x49, 0xE5, 0xF4, 0xD3, 0xC3, - 0xC2, 0x1E, 0xD5, 0xC6, 0xA4, 0xFA, 0x0A, 0xBA, - 0xD4, 0xEB, 0xEA, 0xEC, 0xA8, 0xBC, 0xB4, 0xDC, - 0x84, 0xE4, 0xCE, 0xEC, 0x92, 0xCD, 0xDC, 0x8B, - 0xCC, 0x1E, 0xF6, 0xB2, 0x60, 0x2A, 0x96, 0x52, - 0x0F, 0xBD, 0xFA, 0xCC, 0xB8, 0x7A, 0x4C, 0xD2, - 0x06, 0xEF, 0x44, 0x64, 0xF4, 0xBA, 0xCE, 0xE6, - 0x8A, 0x6F, 0x3C, 0x70, 0x7C, 0x9C, 0xBA, 0xDF, - 0x2C, 0x4D, 0x3B, 0xCA, 0xDE, 0xCE, 0xEE, 0x46, - 0x6A, 0xAC, 0x96, 0xE5, 0x96, 0x7A, 0xBA, 0xB6, - 0xE2, 0x7E, 0xAA, 0xC5, 0x96, 0x9E, 0xC2, 0xAA, - 0xDA, 0x35, 0xB6, 0x82, 0x88, 0xBE, 0xC2, 0x9E, - 0xB4, 0xD5, 0xDA, 0x9C, 0xA0, 0xD0, 0xA8, 0xC7, - 0x72, 0xF2, 0xDB, 0x76, 0xDC, 0xBE, 0xAA, 0xF4, - 0x87, 0x2F, 0x53, 0x8E, 0x36, 0xCE, 0xE6, 0xCA, - 0xCB, 0xE4, 0xD6, 0xAA, 0x42, 0x5D, 0xB4, 0x59, - 0x1C, 0xC8, 0x96, 0x6C, 0xDA, 0xCE, 0xE6, 0xCB, - 0x96, 0x16, 0xFA, 0xBE, 0xAE, 0xFE, 0x6E, 0xD6, - 0xCE, 0xB6, 0xE5, 0xED, 0xDB, 0xDC, 0xF4, 0x72, - 0x1F, 0xAE, 0xE6, 0xC2, 0xCA, 0xC4 + 0x00, 0x06, 0x0a, 0x0e, 0x16, 0x1a, 0x1e, 0x22, + 0x12, 0x00, 0x2a, 0x36, 0x42, 0x4e, 0x4a, 0x56, + 0x26, 0x46, 0x2e, 0x32, 0x52, 0x3a, 0x02, 0x65, + 0x5e, 0x3e, 0x74, 0x8a, 0xa2, 0x9a, 0x86, 0xc6, + 0xc3, 0x65, 0xbb, 0xd2, 0xda, 0xd6, 0xe2, 0xf6, + 0xfd, 0xae, 0x7b, 0xdd, 0xea, 0x6a, 0xaa, 0xe7, + 0xbe, 0x5a, 0xee, 0x9e, 0x95, 0x80, 0x76, 0x79, + 0x62, 0x36, 0x9a, 0xe2, 0xec, 0xe1, 0xb8, 0xd7, + 0xaf, 0x25, 0xbc, 0xc0, 0xef, 0xea, 0xe8, 0xe8, + 0xf5, 0xf1, 0xda, 0xd3, 0x79, 0xdb, 0xf4, 0xf6, + 0xf6, 0xf6, 0xe2, 0x3d, 0xb4, 0xce, 0xe6, 0xee, + 0xf6, 0x68, 0xd8, 0xec, 0xf5, 0xc6, 0xc8, 0x9c, + 0x89, 0xd2, 0xee, 0xcb, 0xb9, 0xd2, 0x66, 0x5e, + 0x8b, 0xbe, 0xa8, 0xd5, 0xca, 0xb6, 0xae, 0x9c, + 0xc5, 0xbe, 0xbe, 0xca, 0x90, 0xb2, 0x9a, 0xa8, + 0xb6, 0xf2, 0xce, 0xfa, 0xb2, 0x6e, 0xa6, 0x12, + 0x4a, 0x8e, 0xf2, 0xf6, 0xf6, 0xee, 0xb5, 0xe4, + 0xf1, 0x26, 0x9a, 0xea, 0xf6, 0xe0, 0xd2, 0x16, + 0x9a, 0x2e, 0x70, 0xd6, 0x46, 0x7c, 0xb4, 0x62, + 0xd6, 0xa3, 0x74, 0xa7, 0xa2, 0xca, 0xe0, 0xae, + 0xbe, 0xce, 0xa3, 0x8e, 0x6d, 0x8e, 0x32, 0xaf, + 0x50, 0x9e, 0x5b, 0x8a, 0x98, 0x82, 0x7a, 0x82, + 0x56, 0x7c, 0x8a, 0x56, 0x5e, 0x86, 0x6a, 0x52, + 0x59, 0x64, 0x5e, }; unsigned char linux_logo_green[] __initdata = { - 0x02, 0x88, 0xC4, 0x85, 0x44, 0xA2, 0xA8, 0xE5, - 0x65, 0xA6, 0xC2, 0x24, 0xA4, 0xB4, 0x62, 0x86, - 0x94, 0x44, 0xD2, 0xB6, 0x12, 0xD4, 0x73, 0x96, - 0x92, 0x95, 0xB2, 0xC2, 0x36, 0x0E, 0xBC, 0x54, - 0x75, 0xA5, 0xF5, 0x0A, 0xB2, 0x83, 0xC2, 0x74, - 0x9B, 0xBD, 0xA2, 0xCA, 0xDA, 0x8C, 0xCB, 0x42, - 0xAC, 0x12, 0xDA, 0x7B, 0x54, 0x94, 0xD2, 0x24, - 0xBE, 0x06, 0x65, 0x33, 0xBB, 0xBC, 0xAB, 0x8C, - 0x92, 0x1E, 0x9B, 0xB6, 0x6E, 0xFB, 0x04, 0xA2, - 0xC8, 0xBD, 0xAD, 0xEC, 0x92, 0xBC, 0x7B, 0x9D, - 0x84, 0xC4, 0xC4, 0xB4, 0x6C, 0x93, 0xA3, 0x5E, - 0x8D, 0x13, 0xD6, 0x82, 0x4C, 0x2A, 0x7A, 0x5A, - 0x0D, 0x82, 0xBB, 0xCC, 0x8B, 0x6A, 0x3C, 0xBE, - 0x06, 0xC4, 0x44, 0x45, 0xDB, 0x96, 0xB6, 0xDE, - 0x8A, 0x4D, 0x3C, 0x5A, 0x7C, 0x9C, 0xAA, 0xCB, - 0x1C, 0x4D, 0x2E, 0xB2, 0xBE, 0xAA, 0xDE, 0x3E, - 0x6A, 0xAC, 0x82, 0xE5, 0x72, 0x62, 0x92, 0x9E, - 0xCA, 0x4A, 0x8E, 0xBE, 0x86, 0x6B, 0xAA, 0x9A, - 0xBE, 0x34, 0xAB, 0x76, 0x6E, 0x9A, 0x9E, 0x62, - 0x76, 0xCE, 0xD3, 0x92, 0x7C, 0xB8, 0x7E, 0xC6, - 0x5E, 0xE2, 0xC3, 0x54, 0xAA, 0x9E, 0x8A, 0xCA, - 0x63, 0x2D, 0x3B, 0x8E, 0x1A, 0x9E, 0xC2, 0xA6, - 0xCB, 0xDC, 0xD6, 0x8E, 0x26, 0x5C, 0xB4, 0x45, - 0x1C, 0xB8, 0x6E, 0x4C, 0xBC, 0xAE, 0xD6, 0x92, - 0x63, 0x16, 0xF6, 0x8C, 0x7A, 0xFE, 0x6E, 0xBA, - 0xC6, 0x86, 0xAA, 0xAE, 0xDB, 0xA4, 0xD4, 0x56, - 0x0E, 0x6E, 0xB6, 0xB2, 0xBE, 0xBE + 0x00, 0x06, 0x0a, 0x0e, 0x16, 0x1a, 0x1e, 0x22, + 0x12, 0x00, 0x2a, 0x36, 0x42, 0x4e, 0x4a, 0x56, + 0x26, 0x46, 0x2e, 0x32, 0x52, 0x3a, 0x02, 0x65, + 0x5e, 0x3e, 0x74, 0x8a, 0xa2, 0x9a, 0x86, 0xc6, + 0xc3, 0x62, 0xbb, 0xd2, 0xda, 0xd6, 0xe2, 0xf6, + 0xfd, 0xae, 0x7b, 0xdd, 0xea, 0x6a, 0xaa, 0xe7, + 0xbe, 0x5a, 0xee, 0x9e, 0x95, 0x80, 0x62, 0x5c, + 0x4e, 0x26, 0x72, 0xaa, 0xba, 0xaf, 0x90, 0xae, + 0x92, 0x1a, 0xa4, 0x85, 0xb6, 0xbe, 0xc3, 0xc8, + 0xcf, 0xd0, 0xc2, 0xce, 0x57, 0xa2, 0xd6, 0xda, + 0xda, 0xd7, 0xb8, 0x2a, 0x7b, 0x91, 0xae, 0xca, + 0xda, 0x45, 0x9e, 0xb2, 0xd7, 0x9b, 0x90, 0x76, + 0x5c, 0xa2, 0xbe, 0xa6, 0x85, 0x96, 0x4e, 0x46, + 0x66, 0x92, 0x7a, 0x9a, 0x96, 0x9d, 0x9a, 0x6b, + 0x8a, 0x8e, 0xb2, 0xca, 0x90, 0xa6, 0x79, 0x7c, + 0xb6, 0xf2, 0xce, 0xfa, 0xb2, 0x6e, 0xa6, 0x0e, + 0x36, 0x86, 0xba, 0xbe, 0xe6, 0xcc, 0x8e, 0xb8, + 0xc4, 0x1e, 0x8e, 0xae, 0xba, 0xb2, 0xa6, 0x12, + 0x7a, 0x20, 0x64, 0xaa, 0x2f, 0x70, 0x85, 0x46, + 0xa6, 0x6e, 0x51, 0x72, 0x92, 0xa2, 0xa6, 0x87, + 0x96, 0xa2, 0x85, 0x7a, 0x6a, 0x6e, 0x22, 0x76, + 0x36, 0x76, 0x3c, 0x6e, 0x63, 0x53, 0x66, 0x62, + 0x42, 0x50, 0x56, 0x42, 0x56, 0x56, 0x56, 0x3e, + 0x51, 0x52, 0x56, }; unsigned char linux_logo_blue[] __initdata = { - 0x04, 0x28, 0x10, 0x0B, 0x14, 0x14, 0x74, 0xC7, - 0x64, 0x0E, 0xC3, 0x24, 0xA4, 0x0C, 0x10, 0x20, - 0x0D, 0x04, 0xD1, 0x0D, 0x13, 0x22, 0x0A, 0x40, - 0x14, 0x0C, 0x11, 0x94, 0x0C, 0x08, 0x0B, 0x56, - 0x09, 0x47, 0xF4, 0x0B, 0x9C, 0x07, 0x54, 0x74, - 0x0F, 0x0C, 0x0F, 0xC7, 0x6C, 0x14, 0x14, 0x11, - 0x0B, 0x04, 0x12, 0x0C, 0x05, 0x94, 0x94, 0x0A, - 0x34, 0x09, 0x14, 0x08, 0x2F, 0x15, 0x19, 0x11, - 0x28, 0x0C, 0x0B, 0x94, 0x08, 0xFA, 0x08, 0x7C, - 0xBC, 0x15, 0x0A, 0xEC, 0x64, 0xBB, 0x0A, 0x0C, - 0x84, 0x2C, 0xA0, 0x15, 0x10, 0x0D, 0x0B, 0x0E, - 0x0A, 0x07, 0x10, 0x3C, 0x24, 0x2C, 0x28, 0x5C, - 0x0A, 0x0D, 0x0A, 0xC1, 0x22, 0x4C, 0x10, 0x94, - 0x04, 0x0F, 0x45, 0x08, 0x31, 0x54, 0x3C, 0xBC, - 0x8C, 0x09, 0x3C, 0x18, 0x7C, 0x9C, 0x7C, 0x91, - 0x0C, 0x4D, 0x17, 0x74, 0x0C, 0x48, 0x9C, 0x3C, - 0x6A, 0xAC, 0x5C, 0xE3, 0x29, 0x3C, 0x2C, 0x7C, - 0x6C, 0x04, 0x14, 0xA9, 0x74, 0x07, 0x2C, 0x74, - 0x4C, 0x34, 0x97, 0x5C, 0x38, 0x0C, 0x5C, 0x04, - 0x0C, 0xBA, 0xBC, 0x78, 0x18, 0x88, 0x24, 0xC2, - 0x3C, 0xB4, 0x87, 0x0C, 0x14, 0x4C, 0x3C, 0x10, - 0x17, 0x2C, 0x0A, 0x8C, 0x04, 0x1C, 0x44, 0x2C, - 0xCD, 0xD8, 0xD4, 0x34, 0x0C, 0x5B, 0xB4, 0x1E, - 0x1D, 0xAC, 0x24, 0x18, 0x20, 0x5C, 0xB4, 0x1C, - 0x09, 0x14, 0xFC, 0x0C, 0x10, 0xFC, 0x6C, 0x7C, - 0xB4, 0x1C, 0x15, 0x17, 0xDB, 0x18, 0x21, 0x24, - 0x04, 0x04, 0x44, 0x8C, 0x8C, 0xB7 + 0x00, 0x06, 0x0a, 0x0e, 0x16, 0x1a, 0x1e, 0x22, + 0x12, 0x01, 0x2a, 0x36, 0x42, 0x4e, 0x4a, 0x56, + 0x26, 0x46, 0x2e, 0x32, 0x52, 0x3a, 0x06, 0x65, + 0x5e, 0x3e, 0x74, 0x8a, 0xa2, 0x9a, 0x86, 0xc6, + 0xc3, 0x59, 0xbb, 0xd2, 0xda, 0xd6, 0xe2, 0xf6, + 0xfd, 0xae, 0x7b, 0xdd, 0xea, 0x6a, 0xaa, 0xe7, + 0xbe, 0x5a, 0xee, 0x9e, 0x95, 0x80, 0x2e, 0x08, + 0x0a, 0x06, 0x0a, 0x0b, 0x0b, 0x0f, 0x0c, 0x0f, + 0x3d, 0x09, 0x73, 0x09, 0x0d, 0x0a, 0x10, 0x1e, + 0x2d, 0x13, 0x86, 0xba, 0x19, 0x0a, 0x36, 0x3c, + 0x26, 0x14, 0x0d, 0x06, 0x07, 0x0a, 0x0b, 0x0f, + 0x4a, 0x06, 0x0a, 0x0c, 0x2b, 0x0a, 0x0b, 0x0a, + 0x06, 0x0a, 0x0a, 0x11, 0x0b, 0x0a, 0x0a, 0x1e, + 0x0f, 0x0d, 0x0a, 0x0b, 0x22, 0x6a, 0x72, 0x0b, + 0x0b, 0x22, 0x90, 0xca, 0x90, 0x92, 0x3c, 0x2c, + 0xb6, 0xf2, 0xce, 0xfa, 0xb2, 0x6e, 0xa6, 0x06, + 0x0e, 0x6a, 0x0e, 0x0e, 0xbe, 0x5b, 0x2c, 0x3e, + 0x0e, 0x0a, 0x5a, 0x0d, 0x0e, 0x3e, 0x0a, 0x06, + 0x2e, 0x06, 0x4e, 0x36, 0x06, 0x58, 0x24, 0x06, + 0x3a, 0x08, 0x08, 0x07, 0x5e, 0x45, 0x0a, 0x32, + 0x2e, 0x2a, 0x43, 0x48, 0x5f, 0x2e, 0x06, 0x06, + 0x07, 0x24, 0x06, 0x32, 0x06, 0x06, 0x46, 0x2e, + 0x22, 0x06, 0x06, 0x1e, 0x4c, 0x06, 0x3a, 0x22, + 0x42, 0x34, 0x42, }; unsigned char linux_logo[] __initdata = { - 0xBF, 0x95, 0x90, 0xCB, 0x95, 0xA1, 0x2C, 0x2C, - 0x95, 0x55, 0xCB, 0x90, 0xCB, 0x95, 0x2C, 0x95, - 0xCB, 0x47, 0x94, 0x95, 0xA1, 0xD6, 0xD6, 0x2C, - 0x90, 0x47, 0x70, 0x2C, 0x6D, 0x2A, 0x6D, 0xD6, - 0xA1, 0x2C, 0x55, 0x95, 0x2C, 0x2C, 0x55, 0x55, - 0x95, 0xA1, 0xA1, 0xA1, 0x6D, 0xBF, 0x2A, 0x2A, - 0xBF, 0x83, 0xBF, 0x95, 0x90, 0xCB, 0x95, 0xA1, - 0x2C, 0x2C, 0x95, 0x55, 0xCB, 0x90, 0xCB, 0x95, - 0x2C, 0x95, 0xCB, 0x47, 0x94, 0x95, 0xA1, 0xD6, - 0xD6, 0x2C, 0x90, 0x47, 0x70, 0x2C, 0x6D, 0x2A, - 0x95, 0x47, 0x47, 0x90, 0x2C, 0x2C, 0x2C, 0x95, - 0x55, 0x55, 0xCB, 0x90, 0xCB, 0x55, 0x55, 0xCB, - 0x47, 0xE6, 0x70, 0x95, 0xD6, 0xD6, 0xA1, 0x2C, - 0x55, 0x55, 0x95, 0xD6, 0x6D, 0xD6, 0xA1, 0x2C, - 0x2C, 0x95, 0x55, 0x95, 0x95, 0x95, 0x2C, 0x2C, - 0xA1, 0xA1, 0x2C, 0x2C, 0xA1, 0xD6, 0xD6, 0xD6, - 0xD6, 0xD6, 0x95, 0x47, 0x47, 0x90, 0x2C, 0x2C, - 0x2C, 0x95, 0x55, 0x55, 0xCB, 0x90, 0xCB, 0x55, - 0x55, 0xCB, 0x47, 0xE6, 0x70, 0x95, 0xD6, 0xD6, - 0xA1, 0x2C, 0x55, 0x55, 0x95, 0xD6, 0x6D, 0xD6, - 0x90, 0x47, 0x47, 0x70, 0x2C, 0xA1, 0x2C, 0x95, - 0x55, 0x55, 0x90, 0xCB, 0x55, 0x55, 0x55, 0x70, - 0x94, 0x70, 0x95, 0xA1, 0xD6, 0xD6, 0xA1, 0x2C, - 0x95, 0x95, 0x2C, 0xA1, 0xD6, 0xA1, 0x2C, 0x2C, - 0x95, 0x55, 0xCB, 0x95, 0xD6, 0xA1, 0x2C, 0x95, - 0xA1, 0xD6, 0xD6, 0xA1, 0xA1, 0xD6, 0xA1, 0xA1, - 0xA1, 0x2C, 0x90, 0x47, 0x47, 0x70, 0x2C, 0xA1, - 0x2C, 0x95, 0x55, 0x55, 0x90, 0xCB, 0x55, 0x55, - 0x55, 0x70, 0x94, 0x70, 0x95, 0xA1, 0xD6, 0xD6, - 0xA1, 0x2C, 0x95, 0x95, 0x2C, 0xD6, 0xD6, 0xA1, - 0x94, 0xA0, 0x47, 0x55, 0x2C, 0xD6, 0xA1, 0x95, - 0x55, 0x55, 0xCB, 0xCB, 0x55, 0x55, 0xCB, 0xCB, - 0x55, 0x95, 0x2C, 0xA1, 0xD6, 0xD6, 0xA1, 0x2C, - 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x95, - 0x55, 0x55, 0x2C, 0x3F, 0x80, 0x20, 0x88, 0x88, - 0x88, 0x20, 0x88, 0xB1, 0x2C, 0xA1, 0x2C, 0x2C, - 0x95, 0xCB, 0x94, 0xA0, 0x47, 0x55, 0x2C, 0xD6, - 0xA1, 0x95, 0x55, 0x55, 0xCB, 0xCB, 0x55, 0x55, - 0xCB, 0xCB, 0x55, 0x95, 0x2C, 0xA1, 0xD6, 0xD6, - 0xA1, 0x2C, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C, - 0x94, 0x94, 0x70, 0x2C, 0xA1, 0xD6, 0xA1, 0x2C, - 0x55, 0x55, 0xCB, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x95, 0x2C, 0xD6, 0xD6, 0xD6, 0xA1, 0x2C, 0x95, - 0x55, 0x55, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, - 0x2C, 0x94, 0x80, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x88, 0x92, 0xA1, 0x95, - 0x55, 0x90, 0x94, 0x94, 0x70, 0x2C, 0xA1, 0xD6, - 0xA1, 0x2C, 0x55, 0x55, 0xCB, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x95, 0x2C, 0xD6, 0xD6, 0xD6, 0xA1, - 0x2C, 0x95, 0x55, 0x55, 0x55, 0x95, 0x95, 0x95, - 0x70, 0x70, 0x55, 0x2C, 0xD6, 0xD6, 0xA1, 0x95, - 0x55, 0x90, 0xCB, 0xCB, 0x55, 0x55, 0x2C, 0x2C, - 0xA1, 0xD6, 0xA1, 0xA1, 0x2C, 0x2C, 0x95, 0x55, - 0x55, 0x55, 0x95, 0x95, 0x2C, 0x95, 0x95, 0xD6, - 0xB1, 0x88, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x80, 0x34, 0x88, 0x43, 0x47, - 0x95, 0xCB, 0x70, 0x70, 0x55, 0x2C, 0xD6, 0xD6, - 0xA1, 0x95, 0x55, 0x90, 0xCB, 0xCB, 0x55, 0x55, - 0x2C, 0x2C, 0xA1, 0xD6, 0xA1, 0xA1, 0xA1, 0x2C, - 0x55, 0x55, 0x55, 0x55, 0x2C, 0x95, 0x2C, 0x2C, - 0x55, 0x55, 0x95, 0x2C, 0xA1, 0xA1, 0x2C, 0x55, - 0x90, 0x70, 0x90, 0x55, 0x95, 0x95, 0xA1, 0xA1, - 0xA1, 0xA1, 0xA1, 0xA1, 0x2C, 0x95, 0x95, 0x95, - 0x95, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0xD5, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x88, 0x7D, 0x3F, 0xB1, 0x80, 0x20, - 0x99, 0x2C, 0x55, 0x55, 0x95, 0x2C, 0xA1, 0xA1, - 0x2C, 0x55, 0x90, 0x70, 0x90, 0x55, 0x95, 0x95, - 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0x2C, 0x2C, 0x2C, - 0x95, 0x55, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C, - 0x95, 0x90, 0x55, 0x2C, 0xA1, 0xA1, 0x95, 0xCB, - 0x70, 0x94, 0x90, 0x55, 0x95, 0xA1, 0xA1, 0xA1, - 0x2C, 0x2C, 0x2C, 0x2C, 0x95, 0x95, 0x95, 0x95, - 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0xA1, 0x88, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0xB1, 0x47, 0xD5, 0x7D, 0x43, - 0x20, 0x70, 0x95, 0x90, 0x55, 0x2C, 0xA1, 0xA1, - 0x95, 0xCB, 0x70, 0x94, 0x90, 0x55, 0x95, 0xA1, - 0xA1, 0xA1, 0x2C, 0x95, 0x2C, 0x2C, 0x95, 0x95, - 0x95, 0x95, 0x95, 0x2C, 0x95, 0x95, 0x95, 0x95, - 0x95, 0x90, 0x55, 0x2C, 0xD6, 0xD6, 0x2C, 0x90, - 0x94, 0x70, 0x55, 0x95, 0x2C, 0xD6, 0xD6, 0xA1, - 0x95, 0x95, 0x95, 0x2C, 0x2C, 0x95, 0x55, 0x55, - 0xCB, 0xCB, 0xCB, 0x55, 0xCB, 0x55, 0x47, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x88, 0xB1, 0x3F, 0x92, 0x2B, 0x80, - 0x20, 0x80, 0xD6, 0x70, 0x55, 0x2C, 0xD6, 0xD6, - 0x2C, 0x90, 0x94, 0x70, 0x55, 0x95, 0x2C, 0xD6, - 0xD6, 0xA1, 0x2C, 0x95, 0x95, 0x2C, 0x2C, 0x95, - 0x95, 0x55, 0x90, 0xCB, 0xCB, 0xCB, 0xCB, 0x55, - 0xD6, 0x55, 0x95, 0xA1, 0xD6, 0xA1, 0x55, 0x70, - 0x94, 0x55, 0x95, 0xA1, 0xA1, 0xA1, 0xA1, 0x95, - 0x55, 0x55, 0x55, 0x95, 0x55, 0x55, 0xCB, 0x90, - 0x70, 0x90, 0xCB, 0x55, 0x55, 0xA1, 0xD8, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x88, 0xD8, 0xE1, 0x88, 0x20, 0x20, - 0x88, 0x88, 0xE6, 0x55, 0x2C, 0xA1, 0xD6, 0xA1, - 0x55, 0x70, 0x94, 0x55, 0x95, 0xA1, 0xA1, 0xA1, - 0xA1, 0x95, 0x55, 0x55, 0x95, 0x95, 0x55, 0x55, - 0x90, 0x90, 0x90, 0x90, 0xCB, 0x55, 0x55, 0x55, - 0xD6, 0x2C, 0xA1, 0xD6, 0xD6, 0xA1, 0xCB, 0x70, - 0x70, 0x95, 0x2C, 0xA1, 0xA1, 0x2C, 0x2C, 0x55, - 0xCB, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x95, 0x2C, 0x95, 0x2C, 0xD6, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x80, 0xD6, 0xA1, 0xD6, 0xD6, 0xA1, - 0xCB, 0x70, 0x70, 0x95, 0x2C, 0xA1, 0xA1, 0x2C, - 0x2C, 0x55, 0xCB, 0xCB, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x95, 0x2C, 0x2C, 0x2C, 0x2C, - 0xD6, 0xA1, 0xA1, 0xA1, 0xA1, 0x55, 0x70, 0x94, - 0xCB, 0x95, 0xA1, 0xA1, 0x2C, 0x95, 0xCB, 0x55, - 0x90, 0xCB, 0x55, 0x55, 0x55, 0x55, 0x95, 0xA1, - 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0x95, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x88, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x88, 0x95, 0xA1, 0xA1, 0xA1, 0x55, - 0x70, 0x94, 0xCB, 0x95, 0xA1, 0xA1, 0x2C, 0x95, - 0xCB, 0xCB, 0x90, 0xCB, 0x55, 0x55, 0x55, 0x55, - 0x95, 0x2C, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, - 0x2C, 0x2C, 0x2C, 0x95, 0x95, 0xCB, 0x70, 0x70, - 0x95, 0x2C, 0x2C, 0x95, 0xCB, 0x70, 0x90, 0xCB, - 0xCB, 0x55, 0x55, 0xCB, 0x55, 0x55, 0x2C, 0xD6, - 0xD6, 0xD6, 0xD6, 0xA1, 0x2C, 0x70, 0x20, 0x20, - 0x88, 0x43, 0xD8, 0x43, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x88, 0x88, 0x43, 0x2B, 0xD8, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x3F, 0x2C, 0x95, 0x95, 0xCB, - 0x70, 0x70, 0x95, 0x2C, 0x2C, 0x95, 0xCB, 0x90, - 0x90, 0xCB, 0x55, 0xCB, 0x55, 0xCB, 0x55, 0x95, - 0x2C, 0xD6, 0xD6, 0xD6, 0xD6, 0xA1, 0x2C, 0x2C, - 0xA1, 0x95, 0x95, 0x55, 0xCB, 0x70, 0x90, 0x55, - 0x2C, 0x2C, 0x2C, 0x55, 0x70, 0x70, 0x55, 0x95, - 0x95, 0xCB, 0x90, 0x90, 0x90, 0x95, 0x2C, 0xA1, - 0xD6, 0xD6, 0x2C, 0x2C, 0x95, 0x70, 0x20, 0x20, - 0x80, 0x2B, 0x34, 0x2B, 0x88, 0x20, 0x20, 0x20, - 0x88, 0xB1, 0x28, 0x28, 0x2B, 0x7D, 0x80, 0x20, - 0x20, 0x20, 0x20, 0x92, 0x95, 0x55, 0xCB, 0x70, - 0x90, 0x55, 0x2C, 0x2C, 0x2C, 0x55, 0x70, 0x70, - 0x55, 0x95, 0x55, 0x55, 0x90, 0x90, 0x90, 0x55, - 0x2C, 0xA1, 0xD6, 0xA1, 0x2C, 0x2C, 0x95, 0x95, - 0xA1, 0x95, 0x55, 0xCB, 0x90, 0x70, 0xCB, 0x95, - 0xA1, 0x95, 0x95, 0xCB, 0x90, 0xCB, 0x95, 0x2C, - 0x95, 0x70, 0x70, 0x90, 0x55, 0x2C, 0xA1, 0xA1, - 0x2C, 0x2C, 0x55, 0xCB, 0x55, 0x90, 0x20, 0x34, - 0x90, 0x6D, 0x70, 0xD8, 0x43, 0x20, 0x20, 0x88, - 0x3F, 0x55, 0xA1, 0x2A, 0xD6, 0x7D, 0x43, 0x20, - 0x20, 0x20, 0x88, 0x7D, 0x55, 0xCB, 0x90, 0x70, - 0xCB, 0x95, 0xA1, 0x95, 0x95, 0xCB, 0x70, 0xCB, - 0x95, 0xA1, 0x95, 0x70, 0x70, 0xCB, 0x55, 0x2C, - 0xA1, 0xA1, 0xA1, 0x95, 0x55, 0x55, 0x55, 0x95, - 0x2C, 0x55, 0x90, 0x70, 0x94, 0x90, 0x95, 0x2C, - 0x2C, 0x95, 0xCB, 0x90, 0x55, 0x95, 0xA1, 0xA1, - 0x95, 0x90, 0x90, 0x95, 0xA1, 0xD6, 0xD6, 0x6D, - 0xA1, 0x95, 0x55, 0xCB, 0x55, 0xCB, 0x20, 0x99, - 0xBF, 0xA3, 0xA3, 0x90, 0x20, 0x20, 0x20, 0x92, - 0x83, 0x6B, 0x6B, 0x6B, 0xA3, 0x70, 0x88, 0x20, - 0x20, 0x20, 0x20, 0x2B, 0x90, 0x70, 0x94, 0x90, - 0x95, 0x2C, 0x2C, 0x95, 0xCB, 0x90, 0x55, 0x95, - 0xA1, 0x2C, 0x55, 0x90, 0x90, 0x95, 0xA1, 0xD6, - 0xD6, 0x6D, 0xA1, 0x95, 0x55, 0xCB, 0x55, 0x55, - 0x2C, 0x55, 0x70, 0x70, 0x94, 0x90, 0x95, 0x2C, - 0x2C, 0x55, 0xCB, 0xCB, 0x95, 0x2C, 0x2C, 0x2C, - 0x55, 0x55, 0x95, 0xA1, 0x6D, 0xBF, 0x6D, 0xD6, - 0x95, 0x55, 0x90, 0xCB, 0x55, 0x95, 0x88, 0x95, - 0x2C, 0x3F, 0x6D, 0x6B, 0x34, 0x20, 0x20, 0x47, - 0x65, 0xD6, 0xE1, 0x3F, 0x2A, 0x6B, 0x2B, 0x20, - 0x20, 0x20, 0x20, 0x43, 0x70, 0x70, 0x94, 0x90, - 0x95, 0x2C, 0x2C, 0x55, 0x55, 0x55, 0x95, 0x2C, - 0xA1, 0x2C, 0x55, 0xCB, 0x95, 0xA1, 0x6D, 0xBF, - 0x6D, 0xD6, 0x2C, 0x55, 0x90, 0xCB, 0x95, 0x95, - 0x95, 0x55, 0x70, 0x94, 0x70, 0x55, 0x2C, 0xA1, - 0x2C, 0x55, 0xCB, 0x55, 0x2C, 0x95, 0x2C, 0x95, - 0x95, 0x95, 0xA1, 0x6D, 0xBF, 0x2A, 0xD6, 0x95, - 0x70, 0x94, 0x94, 0x70, 0x55, 0x55, 0x20, 0xBF, - 0xC9, 0xB1, 0x99, 0x42, 0xB1, 0x61, 0x7D, 0x94, - 0x65, 0xB1, 0x88, 0x99, 0xD5, 0xE5, 0x7F, 0x20, - 0x20, 0x20, 0x20, 0x43, 0x70, 0x94, 0x70, 0x55, - 0x2C, 0xA1, 0x2C, 0x55, 0x90, 0x55, 0x2C, 0x95, - 0x2C, 0x95, 0x95, 0x2C, 0xA1, 0x6D, 0xBF, 0xBF, - 0xD6, 0x55, 0x70, 0x94, 0x94, 0x70, 0xCB, 0x55, - 0x55, 0xCB, 0x70, 0x94, 0x70, 0x95, 0xA1, 0xA1, - 0x95, 0x55, 0x55, 0x95, 0x2C, 0x95, 0x95, 0x95, - 0x95, 0xA1, 0x6D, 0x2A, 0x2A, 0xD6, 0x55, 0x94, - 0xE6, 0xE6, 0x47, 0x70, 0x55, 0x95, 0x20, 0x2A, - 0xD8, 0x43, 0xC9, 0x83, 0x98, 0x79, 0x34, 0x9F, - 0x6B, 0x43, 0x20, 0x88, 0x2B, 0x65, 0xA0, 0x20, - 0x20, 0x20, 0x20, 0xE1, 0x70, 0x94, 0x70, 0x95, - 0xA1, 0xA1, 0x95, 0x55, 0x55, 0x95, 0x2C, 0x95, - 0x95, 0x95, 0x95, 0xA1, 0x6D, 0xBF, 0x2A, 0xD6, - 0x55, 0x94, 0xE6, 0xE6, 0x47, 0x70, 0x55, 0x55, - 0x94, 0x70, 0x94, 0x47, 0x70, 0x95, 0x2C, 0x2C, - 0x95, 0xCB, 0x95, 0x2C, 0x2C, 0xA1, 0x2C, 0x2C, - 0xA1, 0xD6, 0x6D, 0x6D, 0xA1, 0xCB, 0x47, 0x28, - 0xE6, 0x47, 0x70, 0x55, 0x95, 0xA1, 0x20, 0x2C, - 0x7F, 0x88, 0xF0, 0xC6, 0x25, 0x5E, 0xCF, 0x2F, - 0xE7, 0x9A, 0x20, 0x88, 0x99, 0x65, 0x3F, 0x20, - 0x20, 0x20, 0x20, 0x34, 0x94, 0x47, 0x70, 0x95, - 0xA1, 0x2C, 0x55, 0xCB, 0x95, 0x2C, 0x2C, 0xA1, - 0x2C, 0x2C, 0xA1, 0xD6, 0x6D, 0x6D, 0xA1, 0xCB, - 0x94, 0x28, 0xA0, 0x47, 0x70, 0x55, 0x95, 0x95, - 0x47, 0x70, 0x90, 0x94, 0x70, 0x95, 0xA1, 0x2C, - 0x55, 0x55, 0x2C, 0xA1, 0xA1, 0xA1, 0xA1, 0x2C, - 0xA1, 0x6D, 0x2A, 0xD6, 0x55, 0x47, 0x28, 0x28, - 0x47, 0x70, 0x55, 0x95, 0x2C, 0xA1, 0x20, 0x28, - 0xEC, 0x86, 0xBE, 0x48, 0x3E, 0x3E, 0x3A, 0x25, - 0x4E, 0xAE, 0x93, 0xD7, 0xEC, 0xD1, 0x34, 0x20, - 0x20, 0x20, 0x20, 0x43, 0x55, 0x94, 0x70, 0x95, - 0xA1, 0xA1, 0x55, 0xCB, 0x2C, 0xA1, 0xA1, 0xA1, - 0xA1, 0x2C, 0xA1, 0x6D, 0x6D, 0xD6, 0x55, 0x47, - 0x28, 0x28, 0x47, 0x70, 0x55, 0x95, 0x2C, 0x2C, - 0x95, 0x95, 0x55, 0x90, 0xCB, 0x2C, 0xA1, 0xA1, - 0x55, 0x55, 0x2C, 0xD6, 0xD6, 0xA1, 0xA1, 0x2C, - 0xD6, 0x6D, 0x6D, 0xA1, 0x70, 0x28, 0xD5, 0xE6, - 0x70, 0x55, 0x95, 0x2C, 0xA1, 0xD6, 0x20, 0xE1, - 0x26, 0x84, 0x76, 0x73, 0x9C, 0x22, 0x4E, 0x35, - 0x8C, 0x7A, 0x4E, 0xDC, 0x8E, 0x7E, 0x3D, 0x88, - 0x20, 0x20, 0x20, 0x88, 0x2C, 0x90, 0x90, 0x95, - 0xA1, 0x2C, 0x55, 0x55, 0x2C, 0xD6, 0xD6, 0xD6, - 0x2C, 0x2C, 0xD6, 0x2A, 0x6D, 0x2C, 0x70, 0x28, - 0xD5, 0xE6, 0x70, 0x55, 0x95, 0xA1, 0x2C, 0xA1, - 0xBF, 0xA1, 0x95, 0xCB, 0xCB, 0x2C, 0xA1, 0xA1, - 0x95, 0x95, 0xA1, 0xD6, 0xD6, 0xA1, 0x2C, 0x95, - 0xD6, 0x6D, 0xD6, 0x95, 0x94, 0x28, 0xE6, 0x70, - 0x55, 0x95, 0xA1, 0xA1, 0xA1, 0xD6, 0x20, 0x57, - 0xE4, 0xDF, 0x50, 0x3E, 0x22, 0x4E, 0x35, 0x8C, - 0x8C, 0x52, 0x52, 0x7A, 0x4E, 0x58, 0xD7, 0x20, - 0x20, 0x20, 0x20, 0x88, 0x2C, 0xCB, 0x55, 0x2C, - 0xA1, 0xA1, 0x95, 0x95, 0xA1, 0xD6, 0xD6, 0xA1, - 0x2C, 0x95, 0xA1, 0x6D, 0x6D, 0x95, 0x47, 0xA0, - 0xE6, 0x70, 0x55, 0x95, 0x2C, 0xA1, 0xA1, 0xA1, - 0xD2, 0x95, 0x55, 0x90, 0x55, 0x2C, 0xD6, 0xA1, - 0x95, 0x95, 0xA1, 0xD6, 0xD6, 0x2C, 0x95, 0x2C, - 0xA1, 0x6D, 0xA1, 0x55, 0x94, 0x47, 0x94, 0xCB, - 0x55, 0x95, 0x2C, 0xA1, 0xD6, 0xD6, 0x59, 0xC8, - 0xE3, 0x76, 0x2D, 0x3E, 0x22, 0x4E, 0x8C, 0x35, - 0x52, 0x52, 0xEE, 0x3A, 0x4D, 0xED, 0x24, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x28, 0xCB, 0x55, 0x2C, - 0xD6, 0xA1, 0x95, 0x95, 0xA1, 0xD6, 0xA1, 0x2C, - 0x95, 0x2C, 0xD6, 0x6D, 0xA1, 0x55, 0x94, 0xE6, - 0x70, 0xCB, 0x55, 0x95, 0xA1, 0xD6, 0xD6, 0xA1, - 0xD0, 0x94, 0x94, 0x90, 0x55, 0x2C, 0xA1, 0xA1, - 0x55, 0x95, 0xA1, 0xA1, 0xA1, 0x2C, 0x95, 0x2C, - 0xA1, 0xD6, 0x2C, 0x70, 0x94, 0x94, 0x94, 0x94, - 0x70, 0x55, 0xA1, 0xD6, 0xA1, 0xD6, 0x88, 0x77, - 0x38, 0xC4, 0x3E, 0x69, 0x4E, 0x35, 0x8C, 0xEE, - 0x35, 0x89, 0x30, 0x30, 0x4A, 0x48, 0x3C, 0x20, - 0x20, 0x88, 0x20, 0x20, 0xD8, 0x2C, 0x55, 0x2C, - 0xD6, 0xA1, 0x95, 0x95, 0x2C, 0xD6, 0xA1, 0x2C, - 0x95, 0x2C, 0xA1, 0xD6, 0x2C, 0x90, 0x94, 0x47, - 0x94, 0x94, 0x70, 0x55, 0x2C, 0xD6, 0xA1, 0x95, - 0x95, 0x28, 0x47, 0x90, 0x95, 0x2C, 0xA1, 0x2C, - 0x95, 0x55, 0x95, 0xA1, 0xD6, 0xA1, 0x2C, 0x2C, - 0xA1, 0xA1, 0x55, 0x70, 0x94, 0x47, 0x94, 0x94, - 0x70, 0x2C, 0xD6, 0xD6, 0x2C, 0xA1, 0x43, 0x98, - 0x54, 0x48, 0x3E, 0x22, 0x35, 0xEE, 0xEE, 0x9C, - 0x4D, 0x45, 0x75, 0x4A, 0xDF, 0x7B, 0x3D, 0x20, - 0xD8, 0x28, 0x2B, 0x88, 0x20, 0x95, 0x95, 0x2C, - 0xA1, 0x2C, 0x55, 0x55, 0x2C, 0xA1, 0xD6, 0xA1, - 0x2C, 0x95, 0xA1, 0x2C, 0x55, 0x70, 0x94, 0x94, - 0x94, 0x94, 0x70, 0x95, 0xD6, 0xD6, 0x2C, 0x95, - 0x70, 0x28, 0x47, 0x55, 0x95, 0x2C, 0x2C, 0x2C, - 0x95, 0x95, 0x95, 0xA1, 0xA1, 0xA1, 0x95, 0x55, - 0x95, 0x95, 0x55, 0x70, 0x70, 0x70, 0x94, 0x70, - 0x55, 0xD6, 0x6D, 0xD6, 0x95, 0x2C, 0x20, 0x43, - 0xBB, 0xC8, 0x36, 0x30, 0x30, 0x38, 0x45, 0x6E, - 0xE3, 0x75, 0x78, 0x37, 0xBD, 0xD9, 0x3F, 0x20, - 0x88, 0xD5, 0x70, 0xB1, 0x88, 0xA0, 0x95, 0x2C, - 0x2C, 0xA1, 0x95, 0x55, 0x95, 0xA1, 0xA1, 0xA1, - 0x2C, 0x55, 0x95, 0x2C, 0x55, 0x70, 0x70, 0x70, - 0x94, 0x70, 0x55, 0xD6, 0x6D, 0x6D, 0x95, 0x55, - 0x94, 0x47, 0x70, 0x95, 0x2C, 0x2C, 0x2C, 0xA1, - 0x2C, 0x95, 0x2C, 0xA1, 0xD6, 0xA1, 0x2C, 0x55, - 0x55, 0x95, 0x95, 0x55, 0x55, 0x55, 0x55, 0x95, - 0xA1, 0x6D, 0x4B, 0xD6, 0x55, 0xD6, 0x20, 0xD8, - 0xD6, 0x67, 0xDA, 0x4D, 0xED, 0x62, 0x78, 0x78, - 0x23, 0x84, 0x67, 0xF5, 0x4B, 0xBF, 0x90, 0x88, - 0x88, 0x2B, 0x47, 0x99, 0x20, 0x43, 0xD6, 0x2C, - 0x2C, 0xA1, 0x2C, 0x95, 0x2C, 0xA1, 0xD6, 0xA1, - 0x95, 0x95, 0x55, 0x95, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x95, 0xD6, 0x6D, 0xBF, 0xD6, 0x55, 0xCB, - 0x55, 0x55, 0x55, 0x2C, 0x2C, 0x2C, 0x2C, 0xA1, - 0x2C, 0x2C, 0x2C, 0xA1, 0xA1, 0x2C, 0x2C, 0x95, - 0x55, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C, 0xA1, - 0x6D, 0x2A, 0x2A, 0xA1, 0x55, 0x55, 0x20, 0xD8, - 0x6D, 0xAB, 0x96, 0x7E, 0x64, 0x53, 0x36, 0x36, - 0xC6, 0x63, 0x6D, 0xD0, 0x6B, 0xE5, 0xA3, 0x7D, - 0x20, 0x88, 0x80, 0x88, 0x20, 0x20, 0xC9, 0xA1, - 0x2C, 0xA1, 0xA1, 0x2C, 0x2C, 0xA1, 0xA1, 0xA1, - 0x95, 0x95, 0x55, 0x95, 0x95, 0x2C, 0x2C, 0x2C, - 0x2C, 0xA1, 0x6D, 0xBF, 0x6D, 0xA1, 0x55, 0x55, - 0x95, 0x95, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0xA1, - 0xA1, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C, 0x95, - 0x55, 0x55, 0x2C, 0x2C, 0xA1, 0xA1, 0xD6, 0xD6, - 0x6D, 0x6D, 0xA1, 0x55, 0x2C, 0xD8, 0x20, 0xB1, - 0xA3, 0x4B, 0x6D, 0xD9, 0xA7, 0x6C, 0xAF, 0xB2, - 0x6D, 0x2A, 0x83, 0x42, 0xE5, 0xE5, 0x65, 0x2C, - 0x20, 0x20, 0x88, 0x20, 0x20, 0x20, 0x88, 0x95, - 0x2C, 0xA1, 0x2C, 0x95, 0x95, 0x2C, 0x2C, 0x2C, - 0x2C, 0x95, 0x55, 0x55, 0x2C, 0x2C, 0xA1, 0xA1, - 0xD6, 0xD6, 0x6D, 0x6D, 0xA1, 0x55, 0xCB, 0x55, - 0x95, 0x55, 0x95, 0x95, 0x2C, 0x2C, 0x95, 0x2C, - 0x2C, 0x95, 0x95, 0x95, 0x95, 0x95, 0x2C, 0x95, - 0x55, 0x95, 0x2C, 0x2C, 0xA1, 0xA1, 0xD6, 0xA1, - 0xA1, 0x2C, 0x55, 0x55, 0x28, 0x88, 0x43, 0x2A, - 0xE5, 0xA3, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, - 0xBF, 0xA3, 0x42, 0xE5, 0xE5, 0xE5, 0xE5, 0x65, - 0xB1, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xD8, - 0xD6, 0x2C, 0x2C, 0x95, 0x95, 0x95, 0x95, 0x2C, - 0x95, 0x95, 0x55, 0x95, 0x2C, 0x2C, 0xA1, 0xA1, - 0xA1, 0xA1, 0xA1, 0x2C, 0x95, 0x90, 0x90, 0x55, - 0x90, 0xCB, 0x55, 0x95, 0x95, 0x95, 0x95, 0x95, - 0x2C, 0x2C, 0x95, 0x55, 0x95, 0x95, 0x95, 0x55, - 0x55, 0xCB, 0x55, 0x2C, 0x95, 0x95, 0x95, 0x95, - 0x55, 0x90, 0x90, 0x90, 0xE1, 0x43, 0x28, 0xE5, - 0xE5, 0x65, 0xD0, 0x6D, 0x6D, 0x6D, 0x2A, 0xD2, - 0x42, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xD6, 0x20, 0x20, 0x20, 0x20, 0x20, 0x88, 0x88, - 0xD5, 0x2C, 0x2C, 0x2C, 0x95, 0x55, 0x95, 0x95, - 0x95, 0x55, 0x55, 0xCB, 0x55, 0x95, 0x2C, 0x95, - 0x95, 0x95, 0x55, 0x90, 0x70, 0x70, 0x70, 0x90, - 0x70, 0x70, 0xCB, 0x55, 0x55, 0x95, 0x95, 0x95, - 0x2C, 0x95, 0x95, 0x55, 0x55, 0x55, 0x55, 0xCB, - 0x70, 0x70, 0x70, 0xCB, 0x90, 0x90, 0x70, 0x94, - 0x94, 0x94, 0x2C, 0x80, 0x20, 0xE1, 0xA3, 0xE5, - 0xE5, 0xE5, 0x42, 0xEC, 0xD0, 0x83, 0xA3, 0x65, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0x65, 0x7D, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x88, 0x2C, 0x95, 0x95, 0x95, 0x55, 0x55, 0x55, - 0x55, 0xCB, 0x70, 0x70, 0x90, 0x90, 0x90, 0x90, - 0x70, 0x94, 0x94, 0x94, 0x70, 0x70, 0x70, 0x70, - 0x70, 0x55, 0x55, 0x55, 0x95, 0x95, 0x95, 0x95, - 0x2C, 0x2C, 0x95, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x90, 0x70, 0x90, 0x55, 0x55, 0xCB, 0x70, 0x94, - 0x94, 0x95, 0xD8, 0x20, 0x88, 0x70, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0x65, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0x47, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0xE1, 0x6D, 0x2C, 0x95, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x90, 0x70, 0x70, 0x55, 0x55, 0xCB, - 0x70, 0x94, 0x94, 0x94, 0x70, 0x90, 0x70, 0x94, - 0x55, 0x2C, 0x2C, 0x2C, 0x95, 0x2C, 0x95, 0x95, - 0x2C, 0x2C, 0x2C, 0x55, 0x55, 0x55, 0x55, 0x55, - 0xCB, 0xCB, 0x95, 0x2C, 0x2C, 0x95, 0x55, 0x90, - 0x55, 0x99, 0x20, 0x20, 0xE1, 0xA3, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xD6, 0x88, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x2B, 0x6D, 0x95, 0x95, 0x55, 0x55, - 0x55, 0x55, 0xCB, 0x55, 0x95, 0x2C, 0x2C, 0x95, - 0x55, 0x90, 0xCB, 0xCB, 0xCB, 0xCB, 0x90, 0x70, - 0x2C, 0xD6, 0xD6, 0x2C, 0x2C, 0x95, 0x95, 0x95, - 0x95, 0x95, 0x95, 0x2C, 0x95, 0x95, 0x95, 0x95, - 0x95, 0x95, 0x2C, 0xA1, 0x2C, 0x95, 0x55, 0x95, - 0xE6, 0x88, 0x20, 0x20, 0x3F, 0xA3, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0x42, 0xA3, 0x88, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x88, 0x2B, 0xD6, 0x95, 0x95, 0x95, - 0x95, 0x95, 0x95, 0x95, 0x2C, 0xA1, 0x2C, 0x95, - 0x55, 0x55, 0x95, 0x95, 0x95, 0x55, 0x55, 0x55, - 0xA1, 0xD6, 0xD6, 0xA1, 0x2C, 0x2C, 0x95, 0x2C, - 0x2C, 0x2C, 0x95, 0x2C, 0x95, 0x95, 0x55, 0x95, - 0x95, 0x2C, 0x2C, 0x2C, 0x95, 0xCB, 0xCB, 0x94, - 0x20, 0x20, 0x20, 0x20, 0xE6, 0x83, 0x65, 0xE5, - 0xE5, 0xE5, 0xE5, 0x42, 0x6B, 0x6B, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0x42, 0x6B, 0x6B, 0xA3, 0xD2, - 0xD2, 0x6B, 0xC9, 0x20, 0x20, 0x88, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x88, 0x8A, 0xA1, 0x95, 0x95, - 0x95, 0x55, 0x95, 0x2C, 0xA1, 0x2C, 0x95, 0xCB, - 0xCB, 0x55, 0x95, 0x95, 0x95, 0x55, 0x55, 0x95, - 0x6D, 0x6D, 0x6D, 0xD6, 0xA1, 0x2C, 0x2C, 0x95, - 0x2C, 0x95, 0x2C, 0x95, 0x95, 0x95, 0x95, 0x95, - 0x95, 0x95, 0x95, 0x55, 0x70, 0x70, 0x2C, 0x80, - 0x88, 0x20, 0x20, 0x80, 0x94, 0xD6, 0x32, 0x6B, - 0xE5, 0xE5, 0xE5, 0x42, 0x6B, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xA3, 0xD2, 0xD0, 0xBF, 0x2A, - 0x2A, 0xD0, 0x6D, 0x34, 0x20, 0xE1, 0x88, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x88, 0xA1, 0x95, 0x95, - 0x95, 0x95, 0x95, 0x95, 0x95, 0x55, 0x70, 0x70, - 0x70, 0x90, 0xCB, 0xCB, 0xCB, 0x95, 0x95, 0x2C, - 0xD0, 0x6D, 0xD6, 0xD6, 0xA1, 0xA1, 0xA1, 0x2C, - 0x2C, 0x2C, 0x2C, 0x95, 0x55, 0x55, 0x55, 0x95, - 0x95, 0x2C, 0x95, 0x55, 0xCB, 0xCB, 0x95, 0x88, - 0x20, 0x20, 0x88, 0xD8, 0x2C, 0xD1, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0x65, 0x65, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x42, 0x6B, 0xEC, - 0xBF, 0x2A, 0xEC, 0x95, 0x20, 0x34, 0x2B, 0xE1, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x99, 0x95, 0x55, - 0x55, 0x55, 0x95, 0x95, 0x95, 0x55, 0xCB, 0xCB, - 0x55, 0x55, 0xCB, 0xCB, 0xCB, 0x55, 0x95, 0x95, - 0x32, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0x2C, 0x2C, - 0xA1, 0x95, 0x95, 0x95, 0x55, 0xCB, 0xCB, 0x55, - 0x95, 0x95, 0x95, 0x95, 0x95, 0x55, 0x99, 0x20, - 0xE1, 0xE1, 0x43, 0x47, 0x6B, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0x42, 0xEC, 0xBF, 0xA3, 0x8A, 0x20, 0x88, 0xD8, - 0x2B, 0x20, 0x20, 0x20, 0x88, 0x88, 0x2C, 0xCB, - 0xCB, 0x95, 0x95, 0x2C, 0x95, 0x95, 0x55, 0x95, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x95, 0x55, 0x95, - 0x6D, 0x55, 0x55, 0x55, 0x95, 0x95, 0x2C, 0x95, - 0x2C, 0x95, 0x95, 0x55, 0x55, 0x55, 0x55, 0x95, - 0x95, 0x95, 0x95, 0x95, 0x95, 0xA1, 0x34, 0x20, - 0xC9, 0x20, 0xE1, 0xA3, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xA3, 0x83, 0x6D, 0x20, 0x88, 0x88, - 0x2B, 0x34, 0x20, 0x20, 0x20, 0x88, 0xD5, 0x55, - 0x55, 0x55, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, - 0x95, 0x95, 0x95, 0x95, 0x55, 0x55, 0x95, 0x95, - 0x2C, 0x55, 0xCB, 0x55, 0xCB, 0x55, 0x55, 0x95, - 0x95, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, - 0x2C, 0x95, 0x95, 0x55, 0x95, 0x2C, 0x20, 0xD8, - 0xE1, 0x20, 0x70, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0x65, 0xA3, 0x92, 0x43, 0x7D, - 0xD8, 0xC9, 0x88, 0x20, 0x20, 0x20, 0x43, 0xD6, - 0x2C, 0x2C, 0x95, 0x95, 0x95, 0x55, 0x95, 0x2C, - 0x95, 0x95, 0x95, 0x95, 0x95, 0x2C, 0x95, 0x2C, - 0xA1, 0x55, 0x55, 0x55, 0x55, 0x95, 0x95, 0x55, - 0x55, 0x55, 0x95, 0x95, 0x2C, 0x2C, 0xA1, 0x2C, - 0xA1, 0x2C, 0x2C, 0x95, 0x2C, 0x99, 0x88, 0xB1, - 0x20, 0xD8, 0x42, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xCB, 0x34, 0x8A, - 0xC9, 0x34, 0x2B, 0x20, 0x20, 0x20, 0x20, 0x90, - 0xA1, 0xA1, 0xA1, 0x2C, 0x2C, 0x95, 0x95, 0x2C, - 0x2C, 0x95, 0x95, 0x95, 0x95, 0x2C, 0x2C, 0x2C, - 0xD6, 0x2C, 0x55, 0x55, 0x95, 0x2C, 0x2C, 0x2C, - 0x55, 0xCB, 0x55, 0x2C, 0x2C, 0xA1, 0x2C, 0xA1, - 0xA1, 0xA1, 0x2C, 0x2C, 0x6D, 0x43, 0xD8, 0x80, - 0x88, 0xCB, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x32, 0x80, 0xE1, - 0x80, 0x20, 0xB1, 0x20, 0x20, 0x20, 0x20, 0xC9, - 0xD6, 0xA1, 0xA1, 0xA1, 0x2C, 0xA1, 0x2C, 0x2C, - 0x2C, 0x55, 0x55, 0x55, 0x95, 0x95, 0x95, 0x55, - 0xD6, 0x95, 0x95, 0x95, 0x2C, 0xA1, 0x2C, 0x2C, - 0x95, 0x95, 0x95, 0x95, 0x95, 0x2C, 0x95, 0x2C, - 0x2C, 0x2C, 0x2C, 0x95, 0xCB, 0x20, 0xC9, 0x20, - 0xE1, 0xA3, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0x42, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xD8, 0x20, - 0x20, 0x20, 0x2B, 0x43, 0x20, 0x20, 0x20, 0x88, - 0xD6, 0x2C, 0x2C, 0x2C, 0x95, 0x95, 0x95, 0x55, - 0x95, 0x55, 0x55, 0xCB, 0x55, 0xCB, 0xCB, 0x55, - 0x2C, 0x55, 0x55, 0x95, 0x2C, 0x2C, 0xA1, 0x95, - 0x55, 0x95, 0x55, 0x95, 0x95, 0x95, 0x95, 0x95, - 0x55, 0xCB, 0x70, 0xCB, 0xC9, 0x80, 0x2B, 0x20, - 0xA0, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0x42, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x92, 0x20, - 0x20, 0x20, 0xE1, 0xD8, 0x20, 0x20, 0x20, 0x20, - 0x95, 0x95, 0x55, 0xCB, 0x90, 0x90, 0x70, 0x90, - 0x90, 0x90, 0xCB, 0xCB, 0xCB, 0xCB, 0x55, 0x95, - 0x95, 0x55, 0x55, 0x95, 0x95, 0x2C, 0x2C, 0x2C, - 0x95, 0x95, 0x55, 0x55, 0x55, 0x95, 0x95, 0x55, - 0x90, 0x47, 0xA0, 0x55, 0x20, 0x2B, 0x43, 0x88, - 0x6D, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0x6B, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x28, 0x20, - 0x20, 0x20, 0xE1, 0xE1, 0x20, 0x20, 0x20, 0x20, - 0x28, 0x55, 0x90, 0x47, 0xA0, 0x47, 0x94, 0x70, - 0x55, 0x95, 0x95, 0x55, 0xCB, 0x55, 0x55, 0x2C, - 0x2C, 0x2C, 0x95, 0x95, 0x95, 0x2C, 0x2C, 0x2C, - 0x95, 0x2C, 0x95, 0x95, 0x95, 0x95, 0x95, 0x55, - 0x94, 0xE6, 0x70, 0x2B, 0x88, 0x2B, 0x88, 0xE1, - 0x65, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0x6B, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x47, 0x20, - 0x20, 0x20, 0xE1, 0x34, 0x20, 0x20, 0x20, 0x20, - 0xB1, 0x95, 0x94, 0xE6, 0xA0, 0x47, 0x70, 0x55, - 0x2C, 0xA1, 0x2C, 0x55, 0x90, 0xCB, 0x2C, 0xD6, - 0x6D, 0xA1, 0x2C, 0x95, 0x95, 0xA1, 0x2C, 0xA1, - 0x2C, 0x2C, 0x95, 0x95, 0x95, 0x95, 0x95, 0x55, - 0x70, 0xE6, 0x70, 0x20, 0x20, 0x7D, 0x20, 0x8A, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0x65, 0xA3, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x94, 0x20, - 0x20, 0x20, 0xD8, 0x88, 0x20, 0x20, 0x20, 0x20, - 0xD8, 0x2C, 0x94, 0x47, 0x47, 0x90, 0x95, 0x95, - 0xA1, 0x6D, 0xA1, 0x90, 0x94, 0x55, 0x2C, 0xD6, - 0xD0, 0xA1, 0x95, 0x95, 0x2C, 0x2C, 0xA1, 0x2C, - 0x95, 0x95, 0x55, 0x55, 0x55, 0x95, 0x2C, 0x2C, - 0xCB, 0x95, 0xD8, 0x20, 0x20, 0xB1, 0x88, 0x28, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE2, 0xA3, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xCB, 0x20, - 0x20, 0x20, 0x2B, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x88, 0xD6, 0x55, 0x47, 0x94, 0x55, 0x2C, 0xA1, - 0xA1, 0xD6, 0x95, 0x94, 0x94, 0x55, 0xD6, 0x6D, - 0xBF, 0x95, 0x90, 0xCB, 0x2C, 0x2C, 0x2C, 0x2C, - 0x55, 0x95, 0xCB, 0x90, 0x90, 0x95, 0x2C, 0x95, - 0x90, 0x70, 0x20, 0x20, 0x34, 0x8A, 0x20, 0x94, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0x65, 0x6B, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xCB, 0x20, - 0x20, 0x88, 0x2B, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x88, 0xD6, 0xCB, 0x47, 0x94, 0x55, 0xA1, 0xD6, - 0xD6, 0x2C, 0xCB, 0x47, 0x70, 0xA1, 0x6D, 0x2A, - 0x95, 0x47, 0x47, 0x70, 0x95, 0xA1, 0x2C, 0x95, - 0x55, 0x55, 0x90, 0x90, 0x55, 0x55, 0x55, 0x90, - 0x47, 0xD5, 0x20, 0x20, 0x80, 0xD5, 0x43, 0xCB, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0x42, 0x6B, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xCB, 0x20, - 0x20, 0x80, 0x34, 0x20, 0x20, 0x20, 0x88, 0x20, - 0x20, 0x2C, 0x47, 0xE6, 0x70, 0x2C, 0xD6, 0xD6, - 0xA1, 0x2C, 0x55, 0xCB, 0x95, 0xA1, 0x6D, 0xD6, - 0x90, 0x47, 0x47, 0x90, 0x2C, 0xA1, 0x2C, 0x95, - 0x55, 0x55, 0x90, 0x90, 0x55, 0x55, 0x55, 0x70, - 0x94, 0x8A, 0x20, 0x88, 0x88, 0xE1, 0xD8, 0x95, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE2, 0x42, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x47, 0x20, - 0x43, 0x7D, 0x43, 0x80, 0x88, 0x20, 0x20, 0x20, - 0x88, 0xCB, 0x94, 0x70, 0x55, 0xA1, 0xD6, 0xD6, - 0xA1, 0x2C, 0x2C, 0x95, 0xA1, 0xA1, 0xD6, 0xA1, - 0x94, 0xE6, 0x47, 0x55, 0x2C, 0xD6, 0xA1, 0x95, - 0x55, 0x55, 0xCB, 0xCB, 0x55, 0x55, 0xCB, 0xCB, - 0x55, 0xA0, 0x43, 0x86, 0x86, 0x43, 0xD8, 0xCB, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0x65, 0x6B, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x3F, 0x80, - 0xD8, 0x80, 0x88, 0x34, 0xD8, 0x2B, 0xD8, 0x20, - 0x99, 0x90, 0x55, 0x95, 0x2C, 0xA1, 0xD6, 0xD6, - 0xA1, 0x95, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C, - 0x94, 0x94, 0x70, 0x2C, 0xA1, 0xD6, 0xA1, 0x2C, - 0x55, 0x55, 0xCB, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x95, 0x44, 0xBC, 0x3E, 0x5D, 0xD3, 0x79, 0x92, - 0xA3, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0x65, 0x42, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x65, 0x9A, 0x34, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x43, 0x99, 0xE1, - 0x70, 0x55, 0x95, 0xA1, 0xD6, 0xD6, 0xD6, 0xA1, - 0x2C, 0x95, 0x55, 0x55, 0x95, 0x95, 0x95, 0x95, - 0x70, 0x70, 0x55, 0x2C, 0xD6, 0xD6, 0xA1, 0x95, - 0x55, 0x90, 0xCB, 0xCB, 0x55, 0x55, 0x2C, 0x2C, - 0x32, 0x9D, 0xEB, 0x5D, 0x69, 0x49, 0x84, 0xF0, - 0xB1, 0xEC, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0x42, 0x6B, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xC1, 0x4E, 0x21, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x34, 0xC9, 0xD8, - 0xBB, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0x2C, 0x2C, - 0x95, 0x55, 0x55, 0x55, 0x95, 0x95, 0x2C, 0x2C, - 0x55, 0xCB, 0x95, 0x2C, 0xA1, 0xA1, 0x2C, 0x55, - 0x90, 0x70, 0x90, 0x55, 0x95, 0x95, 0x6D, 0xD0, - 0xC2, 0x48, 0x6A, 0x49, 0x69, 0x82, 0x5D, 0x2F, - 0x59, 0x7D, 0xBF, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0x65, 0x6B, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xEA, 0xC7, 0x7E, 0x66, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x34, 0x43, 0x5A, - 0x46, 0x27, 0xA1, 0xA1, 0xA1, 0xA1, 0x2C, 0x95, - 0x95, 0x55, 0x95, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, - 0x95, 0x90, 0x55, 0x2C, 0xA1, 0xA1, 0x95, 0x55, - 0x94, 0x94, 0x2C, 0x2A, 0x72, 0x3B, 0x56, 0xDD, - 0xDF, 0x29, 0x5D, 0x49, 0x89, 0x5D, 0x3E, 0x69, - 0x93, 0x66, 0x34, 0xA1, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0x65, 0x42, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xEA, 0x3E, 0x5A, 0x66, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x5B, 0x73, - 0x89, 0x4C, 0xBF, 0x2C, 0x95, 0x2C, 0x2C, 0x95, - 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, - 0x2C, 0x70, 0x55, 0x2C, 0xD6, 0xD6, 0x2C, 0xCB, - 0x70, 0x55, 0xE7, 0x60, 0x4A, 0x48, 0xCD, 0x4A, - 0x29, 0x73, 0x5D, 0x82, 0x49, 0x49, 0x49, 0x49, - 0x3A, 0x57, 0x88, 0x88, 0x70, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0x42, 0x73, 0x50, 0xBE, 0x79, - 0x20, 0x20, 0x20, 0x20, 0x66, 0xCC, 0x37, 0x9C, - 0x3E, 0xCE, 0xBF, 0x95, 0x95, 0x95, 0x2C, 0x95, - 0x95, 0x55, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0x55, - 0xA1, 0x55, 0x95, 0xA1, 0xD6, 0xA1, 0x55, 0x94, - 0x94, 0xE8, 0x60, 0xC4, 0x3E, 0x2D, 0x2D, 0x2D, - 0x33, 0x5D, 0x82, 0x49, 0x49, 0x49, 0x49, 0x49, - 0x89, 0xAA, 0x59, 0x20, 0x20, 0x28, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xEC, 0x4A, 0x2D, 0x50, 0x78, 0x2E, - 0x57, 0x51, 0xF0, 0x57, 0x31, 0x4D, 0x50, 0x2D, - 0x5D, 0xF2, 0xA1, 0x2C, 0x95, 0x95, 0x55, 0x55, - 0x90, 0x90, 0x70, 0x90, 0xCB, 0x55, 0x55, 0x55, - 0x6D, 0x2C, 0xA1, 0xD6, 0xD6, 0xA1, 0x55, 0x94, - 0x70, 0xB9, 0x75, 0x50, 0x3E, 0x49, 0x49, 0x49, - 0x5D, 0x82, 0x49, 0x49, 0x82, 0x49, 0x49, 0x49, - 0x89, 0x69, 0x4F, 0x20, 0x20, 0x20, 0x8A, 0x42, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0x83, 0x4A, 0x3A, 0x50, 0x62, 0x23, - 0x81, 0xB8, 0xB8, 0xE9, 0x5F, 0x29, 0x33, 0x5D, - 0x5D, 0x73, 0xE8, 0xCB, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C, - 0xD6, 0xA1, 0xA1, 0xA1, 0xA1, 0x55, 0x70, 0x70, - 0xCB, 0x68, 0x75, 0x50, 0x82, 0x49, 0x49, 0x49, - 0x5D, 0x49, 0x49, 0x5D, 0x49, 0x49, 0x5D, 0x82, - 0x69, 0x5D, 0x25, 0xF0, 0x20, 0x20, 0x20, 0xE1, - 0x2A, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0x4B, 0xF4, 0xDF, 0x50, 0x73, 0x76, 0x48, - 0x75, 0xDF, 0x75, 0x62, 0xC4, 0x33, 0x82, 0x49, - 0x5D, 0x5D, 0xA8, 0xF5, 0x55, 0x55, 0x55, 0x55, - 0x2C, 0x2C, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, - 0x2C, 0x2C, 0x2C, 0x95, 0x95, 0xCB, 0x70, 0x70, - 0x95, 0x83, 0x5F, 0xEA, 0x2D, 0x49, 0x49, 0x49, - 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, - 0x5D, 0x49, 0x22, 0x5A, 0x79, 0x20, 0x20, 0x20, - 0x80, 0xD2, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0x65, 0xD0, 0x63, 0x5F, 0x29, 0x2D, 0x2D, 0xEA, - 0x29, 0x29, 0x76, 0x50, 0x2D, 0x82, 0x49, 0x49, - 0x3E, 0x49, 0x5C, 0xB0, 0xBA, 0x95, 0x55, 0x55, - 0x2C, 0xA1, 0xD6, 0xD6, 0xD6, 0xA1, 0x2C, 0x2C, - 0xA1, 0x95, 0x95, 0x55, 0xCB, 0x70, 0x70, 0x55, - 0x2C, 0x83, 0x60, 0x76, 0x5D, 0x49, 0x49, 0x49, - 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, - 0x49, 0x5D, 0x89, 0xDC, 0x8B, 0x20, 0x20, 0x20, - 0x20, 0x95, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE2, 0x32, 0x85, 0xE3, 0x29, 0x2D, 0x33, 0x2D, - 0x2D, 0x2D, 0x6A, 0x2D, 0x33, 0x5D, 0x49, 0x82, - 0x49, 0x49, 0x82, 0x73, 0x5C, 0x9E, 0x2C, 0x55, - 0x2C, 0xA1, 0xD6, 0xA1, 0x2C, 0x2C, 0x95, 0x95, - 0x2C, 0x95, 0x55, 0xCB, 0x90, 0x90, 0xCB, 0x95, - 0x2C, 0x6D, 0x41, 0x6F, 0x3E, 0x49, 0x49, 0x49, - 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, - 0x49, 0x82, 0x3E, 0x4E, 0x38, 0xCA, 0x20, 0x20, - 0x20, 0x55, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x65, - 0x42, 0xA0, 0xD4, 0xE3, 0x29, 0x2D, 0x82, 0x5D, - 0x5D, 0x82, 0x82, 0x49, 0x49, 0x49, 0x49, 0x49, - 0x49, 0x3E, 0x49, 0x49, 0x49, 0x5C, 0x56, 0xD6, - 0xA1, 0xA1, 0xA1, 0x95, 0x55, 0x55, 0x55, 0x95, - 0xA1, 0x55, 0x90, 0x70, 0x94, 0x70, 0x95, 0x2C, - 0x2C, 0xD6, 0xDD, 0x6F, 0x33, 0x49, 0x49, 0x49, - 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, - 0x5D, 0x5D, 0x82, 0x69, 0x22, 0x62, 0x80, 0x34, - 0x94, 0x6B, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0x65, 0xE5, 0x65, 0x6B, - 0xD5, 0x88, 0x5B, 0xE3, 0x29, 0x5D, 0x5D, 0x5D, - 0x5D, 0x5D, 0x5D, 0x5D, 0x49, 0x49, 0x49, 0x82, - 0x49, 0x49, 0x89, 0x49, 0x82, 0x49, 0x71, 0xBA, - 0x6D, 0x6D, 0xA1, 0x95, 0x55, 0xCB, 0x55, 0x55, - 0x2C, 0x55, 0x70, 0x70, 0x70, 0x90, 0x95, 0xA1, - 0x2C, 0xA1, 0x41, 0x76, 0x5D, 0x5D, 0x49, 0x49, - 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, - 0x49, 0x5D, 0x82, 0x5D, 0x89, 0x5E, 0x96, 0x65, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0xE5, 0xE5, 0xE5, 0xE5, 0x65, 0x65, 0xEC, 0xB1, - 0x20, 0x20, 0xCA, 0x23, 0x29, 0x33, 0x49, 0x5D, - 0x49, 0x82, 0x49, 0x49, 0x49, 0x49, 0x49, 0x82, - 0x49, 0x82, 0x5D, 0x5D, 0x5D, 0x2D, 0x5C, 0x8F, - 0x6D, 0xD6, 0x2C, 0x55, 0x90, 0xCB, 0x95, 0x95, - 0x95, 0x55, 0x70, 0x94, 0x70, 0x55, 0x2C, 0xA1, - 0x95, 0xE8, 0x5F, 0x76, 0x33, 0x5D, 0x49, 0x49, - 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, - 0x49, 0x49, 0x49, 0x49, 0x3E, 0x9C, 0x2F, 0x68, - 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, - 0x65, 0xE5, 0x65, 0xE5, 0x6B, 0x90, 0x80, 0x20, - 0x20, 0x20, 0x4F, 0x81, 0x50, 0x3E, 0x49, 0x49, - 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, - 0x69, 0x69, 0x49, 0x5D, 0x2D, 0xC4, 0x46, 0xA3, - 0xD6, 0x55, 0x70, 0x94, 0x94, 0x70, 0xCB, 0x55, - 0x55, 0xCB, 0x70, 0x47, 0x70, 0x95, 0xA1, 0xA1, - 0x95, 0xBD, 0x75, 0x2D, 0x33, 0x49, 0x49, 0x49, - 0x49, 0x49, 0x5D, 0x49, 0x49, 0x49, 0x49, 0x49, - 0x49, 0x49, 0x49, 0x49, 0x5D, 0x2D, 0xB5, 0xDB, - 0xD6, 0x65, 0xE5, 0x65, 0xE5, 0xE5, 0x65, 0xE5, - 0x65, 0x65, 0x6B, 0x95, 0x2B, 0x88, 0x20, 0x20, - 0x20, 0x20, 0x8B, 0x81, 0x29, 0x33, 0x49, 0x49, - 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, - 0x49, 0x3E, 0x3E, 0x5E, 0x41, 0x97, 0x27, 0xD6, - 0x55, 0x94, 0xE6, 0xE6, 0x47, 0x70, 0x55, 0x55, - 0x94, 0x70, 0x94, 0x94, 0x70, 0x55, 0xA1, 0x2C, - 0x6D, 0xC5, 0x39, 0x6A, 0x5D, 0x5D, 0x49, 0x49, - 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, - 0x49, 0x49, 0x49, 0x49, 0x3E, 0xEA, 0x30, 0x77, - 0xE1, 0xC9, 0x94, 0x2C, 0xD6, 0xD6, 0xA1, 0x55, - 0x47, 0x9F, 0x43, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x80, 0x91, 0x81, 0x6A, 0x2D, 0x49, 0x49, - 0x49, 0x5D, 0x5D, 0x49, 0x49, 0x5D, 0x5D, 0x82, - 0xEB, 0x4A, 0x41, 0xC2, 0x8F, 0xF5, 0xA1, 0x55, - 0x94, 0x28, 0xA0, 0x47, 0x70, 0x55, 0x95, 0x95, - 0x47, 0x70, 0x70, 0x94, 0x90, 0x95, 0xA1, 0x2C, - 0xE8, 0xA6, 0x39, 0x76, 0x50, 0x50, 0x2D, 0x2D, - 0x3E, 0x3E, 0x5D, 0x3E, 0x5D, 0x5D, 0x49, 0x82, - 0x49, 0x49, 0x49, 0x82, 0x82, 0x50, 0x75, 0xE0, - 0x57, 0x20, 0x88, 0x88, 0x20, 0x20, 0x88, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x79, 0x91, 0x81, 0x76, 0x33, 0x49, 0x49, - 0x5D, 0x82, 0x49, 0x49, 0x3E, 0x6A, 0xEA, 0x29, - 0xDF, 0x97, 0xBF, 0x6D, 0x6D, 0xD6, 0x55, 0x47, - 0x28, 0x28, 0x47, 0x70, 0x55, 0x95, 0x2C, 0x2C, - 0x95, 0x95, 0x55, 0x90, 0x90, 0x95, 0xA1, 0xA1, - 0xD6, 0x26, 0x45, 0x81, 0x5F, 0x30, 0x48, 0x6F, - 0x6F, 0x29, 0x29, 0x6A, 0x2D, 0x2D, 0x5D, 0x49, - 0x49, 0x49, 0x49, 0x49, 0x2D, 0x76, 0x6E, 0x77, - 0x5B, 0x66, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x79, 0xA9, 0xB8, 0x39, 0x50, 0x5D, 0x5D, - 0x5D, 0x5D, 0x3E, 0x2D, 0x29, 0x76, 0xCD, 0x37, - 0xB9, 0xA1, 0xA1, 0x6D, 0x6D, 0x2C, 0x94, 0x28, - 0xD5, 0xE6, 0x70, 0x55, 0x95, 0xA1, 0x2C, 0xA1, - 0xBF, 0xA1, 0x95, 0xCB, 0x55, 0x95, 0xA1, 0x2C, - 0x95, 0x83, 0xDE, 0x87, 0xB6, 0xBE, 0x40, 0x6E, - 0x81, 0x81, 0x78, 0x78, 0x39, 0x6F, 0xEA, 0x2D, - 0x2D, 0x33, 0x33, 0x33, 0x76, 0x30, 0x64, 0x54, - 0x5B, 0x66, 0x20, 0x20, 0x66, 0x20, 0x88, 0x20, - 0x20, 0x20, 0x88, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x88, 0x34, 0x8B, 0xF1, 0x23, 0x6F, 0x50, 0x2D, - 0x2D, 0x6A, 0x29, 0x6F, 0x78, 0x84, 0x9B, 0xD2, - 0x2C, 0x2C, 0xD6, 0x6D, 0x6D, 0x2C, 0x47, 0xA0, - 0xE6, 0x70, 0x55, 0x95, 0x2C, 0xA1, 0xA1, 0xA1, - 0xD2, 0x95, 0x55, 0xCB, 0x55, 0x2C, 0xD6, 0xA1, - 0x95, 0x95, 0xA1, 0xD6, 0x6D, 0x6D, 0xBA, 0xF3, - 0x8D, 0x36, 0x74, 0x36, 0xF1, 0xB8, 0x23, 0x78, - 0x62, 0x4A, 0x29, 0x62, 0x23, 0xF1, 0x54, 0x31, - 0x57, 0x2B, 0x90, 0x95, 0x2C, 0x2C, 0x2C, 0x2C, - 0xA1, 0xA1, 0xA1, 0xA1, 0x2C, 0x2C, 0x2C, 0xCB, - 0xE6, 0x7D, 0xCA, 0xB7, 0xB8, 0x75, 0x6F, 0x6F, - 0x76, 0x6F, 0x78, 0x81, 0x53, 0xBD, 0x6D, 0x2C, - 0x95, 0x95, 0xA1, 0x6D, 0xA1, 0x55, 0x94, 0xE6, - 0x70, 0xCB, 0x55, 0x95, 0xA1, 0xD6, 0xD6, 0xA1, - 0xD0, 0x94, 0x94, 0x90, 0x95, 0x2C, 0xD6, 0xA1, - 0x95, 0x55, 0x2C, 0xA1, 0xD6, 0xA1, 0x95, 0x2C, - 0xD6, 0x68, 0xAB, 0x6C, 0xA4, 0x77, 0x77, 0xAD, - 0x40, 0x53, 0x6E, 0x40, 0xB7, 0x54, 0x31, 0xD7, - 0xAC, 0xD6, 0x55, 0x55, 0x95, 0x95, 0x95, 0x55, - 0x95, 0x2C, 0x2C, 0xA1, 0x95, 0x95, 0x2C, 0xA1, - 0x6D, 0xD2, 0x7C, 0x54, 0xAD, 0x40, 0x6E, 0x81, - 0x81, 0x6E, 0x36, 0xDA, 0xE8, 0xD6, 0xD6, 0x2C, - 0x2C, 0x2C, 0xA1, 0xD6, 0x95, 0x90, 0x94, 0x47, - 0x94, 0x94, 0x70, 0x55, 0x2C, 0xD6, 0xA1, 0x95, - 0x95, 0x28, 0x47, 0x90, 0x95, 0x2C, 0xA1, 0x2C, - 0x55, 0x95, 0x2C, 0xA1, 0xA1, 0x2C, 0x2C, 0x2C, - 0x2C, 0xA1, 0x55, 0x70, 0x95, 0x2C, 0xB2, 0xB4, - 0xC3, 0xC3, 0x54, 0x54, 0xA9, 0x31, 0xCA, 0x2A, - 0x95, 0x90, 0x55, 0x95, 0x2C, 0xA1, 0x2C, 0x95, - 0x95, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0xD6, - 0x6D, 0x2A, 0xB2, 0x4F, 0x31, 0x2E, 0xE0, 0xAD, - 0xB7, 0xC8, 0xB4, 0xF5, 0x2C, 0xA1, 0xA1, 0xA1, - 0x95, 0x2C, 0xA1, 0x2C, 0x95, 0x70, 0x94, 0x94, - 0x94, 0x94, 0x70, 0x95, 0xD6, 0xD6, 0x2C, 0x95, - 0x94, 0x28, 0x47, 0xCB, 0x95, 0x2C, 0xA1, 0xA1, - 0x95, 0x55, 0x2C, 0xA1, 0xD6, 0xA1, 0x95, 0x95, - 0x95, 0x2C, 0x55, 0x70, 0x70, 0x70, 0x94, 0x2C, - 0x63, 0xBB, 0xA5, 0xD7, 0xCA, 0xB3, 0x6D, 0x2C, - 0x55, 0x55, 0x95, 0x2C, 0x2C, 0x2C, 0x95, 0x95, - 0x95, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0xA1, - 0xD6, 0x2C, 0x70, 0x95, 0xAC, 0xC0, 0xDB, 0xEF, - 0xEF, 0xA2, 0xE8, 0x95, 0x95, 0xA1, 0xD6, 0xA1, - 0x95, 0x55, 0x2C, 0x95, 0x55, 0x70, 0x70, 0x70, - 0x94, 0x70, 0x55, 0xD6, 0x6D, 0x6D, 0x95, 0x55, - 0x70, 0x47, 0x70, 0x95, 0x2C, 0x2C, 0x2C, 0xA1, - 0x2C, 0x95, 0x2C, 0xA1, 0xD6, 0xA1, 0x95, 0x55, - 0x55, 0x95, 0x55, 0x55, 0x55, 0x55, 0x55, 0x95, - 0xA1, 0xF5, 0xBF, 0xBF, 0xA1, 0x95, 0x95, 0x95, - 0x95, 0x55, 0x2C, 0x2C, 0x95, 0x55, 0x55, 0x95, - 0x95, 0x95, 0xA1, 0xA1, 0xA1, 0xA1, 0x2C, 0xA1, - 0x2C, 0x55, 0x70, 0x94, 0x90, 0x2C, 0x6D, 0x6D, - 0x6D, 0xA1, 0x2C, 0x95, 0x2C, 0xA1, 0xD6, 0xA1, - 0x2C, 0x55, 0x55, 0x95, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x95, 0xD6, 0x6D, 0xBF, 0xD6, 0x55, 0xCB, - 0x55, 0x55, 0x55, 0x2C, 0x2C, 0x2C, 0x2C, 0xA1, - 0xA1, 0x95, 0x2C, 0xA1, 0xA1, 0xA1, 0x2C, 0x95, - 0x55, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C, 0xA1, - 0x6D, 0xBF, 0x6D, 0x2C, 0x55, 0x55, 0x95, 0x95, - 0xCB, 0xCB, 0x55, 0x55, 0xCB, 0x55, 0x55, 0x95, - 0x95, 0x2C, 0x2C, 0xA1, 0xA1, 0xA1, 0x2C, 0x2C, - 0xA1, 0x95, 0xCB, 0xCB, 0x95, 0x95, 0x2C, 0x2C, - 0x2C, 0xA1, 0x2C, 0x2C, 0x2C, 0xA1, 0xA1, 0x2C, - 0x2C, 0x95, 0x55, 0x95, 0x95, 0x2C, 0x2C, 0x2C, - 0x2C, 0xA1, 0x6D, 0xBF, 0x6D, 0xA1, 0x55, 0x55, - 0x95, 0x95, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C, - 0x2C, 0x95, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x95, - 0x55, 0x95, 0x2C, 0x2C, 0xA1, 0xA1, 0xD6, 0xD6, - 0x6D, 0x6D, 0xA1, 0x95, 0xCB, 0x55, 0x95, 0x55, - 0x90, 0x70, 0xCB, 0xCB, 0x90, 0xCB, 0x95, 0x95, - 0x2C, 0x2C, 0xA1, 0xD6, 0xA1, 0xA1, 0xA1, 0xA1, - 0xA1, 0xA1, 0x2C, 0x95, 0x95, 0x2C, 0x2C, 0x2C, - 0x2C, 0xA1, 0x2C, 0x95, 0x95, 0x95, 0x2C, 0x2C, - 0x2C, 0x95, 0x55, 0x55, 0x2C, 0x2C, 0xA1, 0xA1, - 0xD6, 0xD6, 0x6D, 0x6D, 0xA1, 0x55, 0xCB, 0x55 + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, + 0x22, 0x21, 0x21, 0x21, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x26, 0x26, 0x25, 0x28, 0x23, 0x22, 0x21, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x23, 0x25, 0x2a, 0x2b, 0x2c, 0x2d, 0x2d, + 0x2d, 0x2e, 0x2c, 0x2b, 0x2a, 0x25, 0x28, 0x22, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x24, 0x2a, 0x2c, 0x2f, 0x2c, 0x30, 0x30, 0x24, + 0x25, 0x27, 0x2b, 0x2c, 0x2f, 0x31, 0x32, 0x25, + 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x25, + 0x33, 0x34, 0x35, 0x21, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x21, 0x2b, 0x2f, 0x2c, + 0x30, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, 0x33, + 0x2d, 0x27, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x31, + 0x2d, 0x32, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x21, 0x28, 0x2a, 0x34, + 0x25, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x23, 0x32, 0x27, 0x21, 0x36, + 0x2a, 0x2d, 0x2a, 0x28, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x22, 0x26, 0x2c, 0x35, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x25, 0x2f, 0x37, 0x32, 0x22, + 0x36, 0x35, 0x31, 0x27, 0x22, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x23, 0x2a, 0x2f, 0x22, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x26, 0x38, 0x38, 0x35, 0x25, + 0x36, 0x21, 0x2d, 0x2b, 0x24, 0x21, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x21, 0x24, 0x39, 0x39, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x25, 0x2b, 0x30, 0x28, 0x22, + 0x36, 0x36, 0x27, 0x34, 0x30, 0x23, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x21, 0x26, 0x2d, 0x26, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x22, 0x22, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x2d, 0x33, 0x28, 0x21, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x30, 0x2f, 0x23, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x2b, 0x2c, 0x25, 0x21, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x2a, 0x34, 0x36, 0x36, + 0x36, 0x21, 0x22, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x21, 0x23, 0x22, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x28, 0x34, 0x27, 0x22, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x36, + 0x21, 0x21, 0x24, 0x27, 0x21, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x28, 0x27, 0x22, 0x33, 0x24, 0x36, + 0x36, 0x36, 0x36, 0x22, 0x2f, 0x2a, 0x23, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x36, + 0x30, 0x3a, 0x38, 0x24, 0x24, 0x36, 0x36, 0x36, + 0x23, 0x2f, 0x3b, 0x3c, 0x3d, 0x30, 0x25, 0x21, + 0x36, 0x36, 0x36, 0x36, 0x2f, 0x32, 0x23, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x23, + 0x3e, 0x3f, 0x40, 0x3a, 0x22, 0x36, 0x36, 0x21, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x3e, 0x23, 0x21, + 0x36, 0x36, 0x36, 0x36, 0x2f, 0x33, 0x28, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x29, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x32, 0x2f, 0x36, 0x2b, + 0x44, 0x40, 0x46, 0x47, 0x35, 0x36, 0x36, 0x26, + 0x43, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x2e, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x31, 0x35, 0x24, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x32, 0x34, 0x36, 0x4d, + 0x4e, 0x25, 0x2f, 0x46, 0x4a, 0x22, 0x23, 0x32, + 0x4f, 0x50, 0x21, 0x31, 0x51, 0x52, 0x53, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x31, 0x35, 0x24, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x29, 0x20, 0x29, 0x29, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x2a, 0x2f, 0x21, 0x3a, + 0x4d, 0x21, 0x31, 0x54, 0x55, 0x28, 0x30, 0x2b, + 0x4b, 0x4d, 0x36, 0x23, 0x32, 0x50, 0x3f, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x2e, 0x39, 0x24, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x29, 0x20, 0x29, 0x20, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x2a, 0x38, 0x23, 0x37, + 0x55, 0x36, 0x28, 0x3a, 0x56, 0x57, 0x57, 0x58, + 0x3c, 0x4d, 0x36, 0x36, 0x36, 0x40, 0x40, 0x21, + 0x36, 0x36, 0x36, 0x36, 0x2e, 0x39, 0x24, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x29, 0x29, 0x29, 0x20, 0x29, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x30, 0x51, 0x23, 0x35, + 0x43, 0x25, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, + 0x5f, 0x60, 0x61, 0x36, 0x31, 0x47, 0x3b, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x31, 0x2c, 0x25, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x30, 0x2f, 0x23, 0x22, + 0x40, 0x62, 0x63, 0x5d, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x66, 0x5e, 0x6a, 0x6b, 0x2a, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x33, 0x2e, 0x26, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x27, 0x2f, 0x23, 0x36, + 0x6c, 0x63, 0x6d, 0x64, 0x5c, 0x66, 0x69, 0x6e, + 0x6f, 0x70, 0x71, 0x69, 0x69, 0x72, 0x6c, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x33, 0x34, 0x27, 0x22, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x27, 0x34, 0x26, 0x73, + 0x74, 0x75, 0x76, 0x64, 0x65, 0x77, 0x69, 0x78, + 0x70, 0x71, 0x71, 0x71, 0x72, 0x5f, 0x5e, 0x21, + 0x36, 0x36, 0x36, 0x36, 0x25, 0x38, 0x2a, 0x23, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x26, 0x2d, 0x33, 0x79, + 0x63, 0x7a, 0x7b, 0x5c, 0x66, 0x69, 0x6e, 0x7c, + 0x71, 0x71, 0x69, 0x7d, 0x7e, 0x7a, 0x7f, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x21, 0x51, 0x2b, 0x28, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x26, 0x2d, 0x32, 0x24, + 0x80, 0x81, 0x64, 0x82, 0x77, 0x69, 0x71, 0x71, + 0x69, 0x83, 0x84, 0x85, 0x7a, 0x85, 0x86, 0x36, + 0x21, 0x2b, 0x23, 0x36, 0x36, 0x39, 0x2e, 0x26, + 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x27, 0x2d, 0x33, 0x21, + 0x87, 0x88, 0x89, 0x72, 0x67, 0x66, 0x5f, 0x89, + 0x8a, 0x63, 0x85, 0x8b, 0x8c, 0x8d, 0x41, 0x36, + 0x36, 0x2d, 0x3a, 0x35, 0x36, 0x24, 0x51, 0x32, + 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x30, 0x2f, 0x33, 0x21, + 0x55, 0x8e, 0x8f, 0x8a, 0x7d, 0x5e, 0x90, 0x7e, + 0x75, 0x75, 0x90, 0x62, 0x40, 0x3f, 0x49, 0x23, + 0x36, 0x24, 0x3a, 0x3a, 0x24, 0x36, 0x2e, 0x31, + 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x21, 0x28, 0x33, 0x37, 0x25, 0x22, + 0x3b, 0x50, 0x8e, 0x8f, 0x90, 0x7e, 0x90, 0x63, + 0x74, 0x91, 0x92, 0x42, 0x93, 0x4b, 0x45, 0x2c, + 0x36, 0x36, 0x33, 0x39, 0x21, 0x36, 0x22, 0x51, + 0x33, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x22, 0x27, 0x2e, 0x2e, 0x36, 0x21, + 0x94, 0x3f, 0x50, 0x95, 0x96, 0x8f, 0x8f, 0x97, + 0x8e, 0x42, 0x50, 0x43, 0x47, 0x48, 0x48, 0x98, + 0x21, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x39, + 0x2e, 0x27, 0x23, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x22, 0x24, 0x2b, 0x38, 0x28, 0x36, 0x32, + 0x4c, 0x4b, 0x50, 0x50, 0x50, 0x42, 0x42, 0x50, + 0x50, 0x40, 0x45, 0x99, 0x48, 0x48, 0x48, 0x48, + 0x34, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x23, + 0x2f, 0x2b, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x28, 0x32, 0x51, 0x32, 0x28, 0x21, 0x98, + 0x48, 0x47, 0x9a, 0x50, 0x50, 0x50, 0x50, 0x50, + 0x9a, 0x4f, 0x9b, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x93, 0x23, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x2a, 0x2f, 0x2a, 0x28, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x23, 0x30, 0x2e, 0x2c, 0x36, 0x21, 0x51, 0x9b, + 0x48, 0x48, 0x52, 0x3f, 0x50, 0x50, 0x40, 0x4b, + 0x47, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x34, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x2d, 0x31, 0x27, 0x23, 0x21, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23, + 0x27, 0x2c, 0x2d, 0x21, 0x36, 0x28, 0x44, 0x48, + 0x48, 0x48, 0x48, 0x47, 0x46, 0x4f, 0x47, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x9c, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x28, 0x51, 0x39, 0x26, 0x22, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x25, + 0x35, 0x51, 0x28, 0x36, 0x36, 0x9d, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x9b, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x4f, 0x28, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x28, 0x38, 0x2b, 0x25, 0x22, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, 0x33, + 0x51, 0x25, 0x36, 0x36, 0x23, 0x40, 0x9b, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x9b, 0x99, 0x2b, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x30, 0x2f, 0x33, 0x24, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x21, 0x23, 0x30, 0x34, + 0x27, 0x36, 0x36, 0x36, 0x2a, 0x40, 0x47, 0x48, + 0x48, 0x48, 0x48, 0x9b, 0x99, 0x99, 0x9b, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x9b, 0x47, 0x52, + 0x46, 0x4f, 0x37, 0x21, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x30, 0x34, 0x2a, 0x23, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x22, 0x25, 0x39, 0x2c, + 0x36, 0x36, 0x36, 0x21, 0x31, 0x4e, 0x9a, 0x4c, + 0x47, 0x9b, 0x9b, 0x52, 0x46, 0x4f, 0x52, 0x9b, + 0x9b, 0x9b, 0x47, 0x4f, 0x45, 0x9a, 0x93, 0x93, + 0x3f, 0x93, 0x98, 0x28, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x39, 0x2c, 0x26, + 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x23, 0x2a, 0x34, 0x28, + 0x36, 0x36, 0x36, 0x22, 0x38, 0x98, 0x44, 0x99, + 0x9b, 0x48, 0x48, 0x9b, 0x4c, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x47, 0x52, 0x46, 0x43, 0x93, + 0x40, 0x40, 0x43, 0x53, 0x21, 0x23, 0x33, 0x23, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x2f, 0x32, + 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x21, 0x24, 0x2b, 0x31, 0x36, + 0x36, 0x22, 0x36, 0x24, 0x9e, 0x4f, 0x9b, 0x48, + 0x48, 0x48, 0x48, 0x9b, 0x99, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x47, + 0x4f, 0x9a, 0x3f, 0x46, 0x38, 0x36, 0x21, 0x30, + 0x26, 0x36, 0x36, 0x36, 0x36, 0x36, 0x39, 0x2c, + 0x25, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x22, 0x26, 0x2e, 0x33, 0x36, + 0x25, 0x25, 0x36, 0x4d, 0x52, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x47, 0x44, 0x93, 0x43, 0x23, 0x36, 0x36, + 0x26, 0x24, 0x36, 0x36, 0x36, 0x36, 0x28, 0x2f, + 0x2a, 0x23, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x2a, 0x51, 0x24, 0x36, + 0x2a, 0x36, 0x28, 0x44, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x9b, 0x4b, 0x44, 0x37, 0x36, 0x23, + 0x28, 0x30, 0x22, 0x36, 0x36, 0x36, 0x36, 0x2d, + 0x35, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x21, 0x28, 0x2b, 0x34, 0x36, 0x25, + 0x24, 0x36, 0x4a, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x9b, 0x52, 0x3f, 0x21, 0x30, + 0x35, 0x25, 0x30, 0x36, 0x36, 0x36, 0x36, 0x32, + 0x2d, 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x22, 0x26, 0x2e, 0x35, 0x36, 0x2a, + 0x36, 0x24, 0x4f, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x9b, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x47, 0x32, 0x30, + 0x2a, 0x23, 0x30, 0x23, 0x36, 0x36, 0x36, 0x21, + 0x2f, 0x32, 0x23, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x21, 0x23, 0x2a, 0x51, 0x28, 0x28, 0x25, + 0x36, 0x3a, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x9b, 0x52, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x38, 0x21, + 0x36, 0x36, 0x22, 0x27, 0x36, 0x36, 0x36, 0x36, + 0x2e, 0x35, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x22, 0x25, 0x2c, 0x34, 0x36, 0x30, 0x21, + 0x23, 0x43, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x47, 0x99, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x94, 0x36, + 0x36, 0x36, 0x36, 0x32, 0x36, 0x36, 0x36, 0x36, + 0x2a, 0x2e, 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x23, 0x2a, 0x51, 0x25, 0x21, 0x2a, 0x36, + 0x2e, 0x9b, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x99, 0x99, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x98, 0x36, + 0x36, 0x36, 0x36, 0x32, 0x36, 0x36, 0x36, 0x36, + 0x22, 0x2f, 0x30, 0x22, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x22, 0x25, 0x2c, 0x34, 0x36, 0x24, 0x28, 0x36, + 0x54, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x4c, 0x99, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x9a, 0x36, + 0x36, 0x36, 0x36, 0x30, 0x36, 0x36, 0x36, 0x36, + 0x21, 0x2f, 0x32, 0x23, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x28, 0x32, 0x2f, 0x28, 0x36, 0x27, 0x22, 0x21, + 0x43, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x4c, 0x99, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x4b, 0x21, + 0x36, 0x36, 0x21, 0x26, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x34, 0x2b, 0x28, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x25, 0x2c, 0x39, 0x36, 0x36, 0x30, 0x22, 0x25, + 0x52, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x4f, 0x52, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x4f, 0x21, + 0x36, 0x36, 0x22, 0x26, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x2c, 0x35, 0x24, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x30, 0x2d, 0x21, 0x36, 0x36, 0x32, 0x23, 0x2a, + 0x47, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x4f, 0x99, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x4c, 0x22, + 0x36, 0x36, 0x24, 0x23, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x2c, 0x39, 0x24, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28, + 0x33, 0x2e, 0x36, 0x36, 0x23, 0x31, 0x27, 0x39, + 0x9b, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x4f, 0x47, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x4c, 0x23, + 0x36, 0x36, 0x26, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x2c, 0x39, 0x24, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28, + 0x2b, 0x39, 0x36, 0x36, 0x36, 0x26, 0x32, 0x31, + 0x9b, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x4f, 0x47, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x46, 0x22, + 0x36, 0x21, 0x26, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x2c, 0x35, 0x24, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, + 0x35, 0x39, 0x36, 0x36, 0x36, 0x36, 0x26, 0x2d, + 0x9b, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x4f, 0x47, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x9a, 0x36, + 0x24, 0x27, 0x9f, 0x24, 0x25, 0x28, 0x21, 0x36, + 0x36, 0x34, 0x2b, 0x28, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x25, + 0x39, 0x4d, 0xa0, 0x84, 0x81, 0x57, 0x21, 0x39, + 0x52, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x4f, 0x47, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x53, 0x28, + 0x23, 0x36, 0x36, 0x36, 0x21, 0x28, 0x2c, 0x30, + 0x21, 0x38, 0x33, 0x28, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x21, 0x22, 0x22, 0x28, 0x30, + 0x2d, 0xa1, 0x7a, 0xa2, 0xa3, 0xa3, 0x7f, 0x22, + 0x51, 0x52, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x4f, 0x9b, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0xa4, 0xa5, 0xa5, 0xa6, 0x61, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x30, 0x32, + 0x25, 0x4d, 0x2b, 0x28, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x21, 0x23, 0x24, 0x26, 0x30, 0x33, 0x31, + 0x4d, 0x91, 0x5b, 0xa2, 0xa3, 0xa3, 0xa3, 0x5a, + 0x21, 0x2e, 0x46, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x4f, 0x9b, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0xa7, 0xa8, 0x69, 0x66, 0xa9, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x26, 0x25, + 0x83, 0xaa, 0x2c, 0x25, 0x21, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x28, 0x30, 0x35, 0x2d, 0x2f, 0x37, 0x4a, + 0x60, 0x85, 0xab, 0xac, 0xa3, 0xa3, 0xa3, 0x82, + 0x86, 0x36, 0x32, 0x3f, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x4c, 0x99, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0xad, 0xa2, 0xa8, 0xae, 0xaf, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x57, + 0x77, 0x66, 0x34, 0x27, 0x22, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x23, 0x30, 0x31, 0xb0, 0x91, 0x7e, 0x90, 0x90, + 0x8b, 0x5b, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0x5d, 0xb1, 0x36, 0x24, 0x53, 0x9b, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x9b, 0x99, 0xad, 0x64, 0x5c, 0x8b, 0xb1, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x73, 0x5d, + 0x82, 0x5c, 0xb2, 0x2a, 0x23, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x24, 0x2b, 0xb0, 0x8b, 0x5b, 0x76, 0x5b, 0x5b, + 0x7b, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa8, 0x5e, 0x22, 0x36, 0x21, 0x3a, 0x99, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x4f, 0x3f, 0xb3, 0x7b, 0x7b, 0x85, 0x80, + 0x9f, 0x36, 0x36, 0x36, 0x21, 0xb4, 0x7e, 0x7b, + 0x64, 0x64, 0xb5, 0x35, 0x24, 0x21, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x26, 0x31, 0xb6, 0x5b, 0x64, 0xa2, 0xa2, 0xac, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0x66, 0xb7, 0x36, 0x36, 0x36, 0x2c, 0x4b, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x9a, 0x3f, 0xb8, 0x76, 0x76, 0x7a, 0x63, + 0xb9, 0xba, 0x86, 0xba, 0xbb, 0x90, 0x5b, 0x64, + 0xa2, 0xa2, 0xbc, 0x2d, 0x27, 0x23, 0x21, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x26, 0x2d, 0x91, 0x5b, 0x64, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa8, 0x83, 0xaf, 0x36, 0x36, 0x36, 0x30, + 0x44, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x9b, 0x9a, 0x3f, 0xbd, 0x5b, 0x7b, 0xbe, 0x85, + 0x7e, 0x90, 0x63, 0x90, 0x85, 0x5b, 0xa2, 0xa3, + 0xa3, 0xac, 0x5d, 0xb5, 0x39, 0x26, 0x23, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x26, 0x2d, 0xbf, 0xbe, 0x64, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa8, 0x88, 0x36, 0x36, 0x36, 0x36, + 0x2d, 0x9b, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x9b, 0x45, 0x3f, 0xc0, 0x6d, 0x7b, 0xab, 0xbe, + 0x7a, 0x8b, 0x8b, 0x7a, 0x5b, 0x64, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa2, 0xc1, 0x37, 0x35, 0x26, 0x23, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x26, 0x2e, 0xbf, 0x7a, 0x7b, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa8, 0x72, 0x73, 0x36, 0x36, 0x36, + 0x24, 0x52, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x46, 0x42, 0xb6, 0x7a, 0x7b, 0x64, 0x7b, + 0x76, 0x5b, 0x5b, 0x76, 0x7b, 0xa2, 0xa3, 0xa3, + 0xa3, 0xa3, 0xac, 0x64, 0xc1, 0x4d, 0x2c, 0x27, + 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x25, 0x31, 0xc2, 0x8b, 0x7b, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa8, 0x89, 0x9f, 0x36, 0x36, + 0x32, 0x47, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x4b, 0x2f, 0x8f, 0x7a, 0x7b, 0xa2, 0xac, + 0xa2, 0x64, 0x64, 0xa2, 0xa2, 0xac, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa2, 0x5d, 0xc3, 0x2c, + 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x25, 0x31, 0xc2, 0x85, 0x7b, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0x66, 0x57, 0x27, 0x4d, + 0x4b, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x99, 0x34, 0x9f, 0xb9, 0x7a, 0x7b, 0xa2, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa2, 0xc2, + 0x32, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x26, 0x2d, 0xc2, 0x85, 0x7b, 0xac, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa8, 0x5f, 0x92, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x44, + 0x35, 0x36, 0xaf, 0xbb, 0x7a, 0x7b, 0xac, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xac, 0xa2, 0xc0, + 0x2b, 0x24, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23, + 0x30, 0x2f, 0xb6, 0x8b, 0x7b, 0xac, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0x66, 0x89, 0x45, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x9b, 0x4e, 0x25, + 0x36, 0x36, 0x61, 0xb9, 0x6d, 0x64, 0xac, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xac, 0x7b, 0xbe, 0xc3, + 0x32, 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28, + 0x33, 0xc4, 0x63, 0xbe, 0xa2, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa2, 0x72, 0x81, 0xc5, + 0x46, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x3f, 0x2c, 0x36, 0x36, + 0x36, 0x36, 0xc6, 0x8f, 0x6d, 0x64, 0xac, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa2, 0xab, 0x8b, 0xb0, 0x2c, + 0x26, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, + 0x35, 0x96, 0x75, 0xab, 0xa2, 0xac, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xac, 0x7b, 0x81, 0xb9, + 0x73, 0x3b, 0x44, 0x9b, 0x48, 0x48, 0x48, 0x9b, + 0x99, 0x43, 0x94, 0x2c, 0x21, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x73, 0xb9, 0x7a, 0x7b, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0x64, 0x76, 0x7a, 0x91, 0xb5, 0x31, 0x30, + 0x28, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x24, + 0x39, 0x97, 0x75, 0xbe, 0x7b, 0x64, 0xa2, 0xa2, + 0xac, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0x7b, 0x7a, 0xc7, + 0xc8, 0x36, 0x21, 0x26, 0x2b, 0x39, 0x33, 0x30, + 0x23, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x21, 0xc8, 0xbb, 0x8b, 0x7b, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa2, 0x64, 0x64, + 0x76, 0x85, 0xbf, 0xb5, 0x34, 0x2b, 0x27, 0x28, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x28, + 0x33, 0xc9, 0x63, 0x7e, 0x7a, 0x6d, 0xbe, 0x5b, + 0x76, 0x7b, 0x64, 0x64, 0xa2, 0xac, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xac, 0x76, 0x85, 0xb9, + 0x79, 0x22, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x21, 0xca, 0xbb, 0x75, 0x76, 0xa2, 0xa3, + 0xa3, 0xa3, 0xac, 0xa2, 0x64, 0x76, 0xbe, 0x8b, + 0xb6, 0xb5, 0x2f, 0x35, 0x30, 0x24, 0x22, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23, + 0x27, 0x31, 0xcb, 0xc9, 0xbb, 0x74, 0x63, 0x90, + 0x7e, 0x75, 0x8b, 0x6d, 0xbe, 0x76, 0x64, 0xa2, + 0xac, 0xac, 0xac, 0xac, 0x64, 0x7a, 0x84, 0xcc, + 0x79, 0x9f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x21, 0xc8, 0xcc, 0x63, 0x6d, 0x7b, 0x64, + 0xac, 0xa2, 0x64, 0x7b, 0xbe, 0x75, 0x63, 0x96, + 0x38, 0x39, 0x2a, 0x24, 0x23, 0x21, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x28, 0x27, 0x35, 0x2d, 0x41, 0xb5, 0xc5, 0x8f, + 0xb9, 0xbb, 0xc7, 0x74, 0x84, 0x90, 0x85, 0x6d, + 0x5b, 0x7b, 0x7b, 0xab, 0x6d, 0x90, 0xb9, 0xcd, + 0xca, 0x22, 0x36, 0x36, 0x28, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x25, 0x36, + 0x36, 0x21, 0xb4, 0x80, 0xc7, 0x7e, 0x6d, 0x76, + 0xab, 0x76, 0x6d, 0x85, 0x63, 0xb9, 0xb5, 0x34, + 0x33, 0x26, 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x23, 0x24, 0x27, 0x2a, 0x35, 0x2e, 0x2f, + 0x41, 0xce, 0xcf, 0x6c, 0x80, 0xcc, 0xb9, 0x74, + 0x84, 0x90, 0x75, 0x7e, 0x74, 0x8f, 0xcd, 0x79, + 0xc6, 0x2b, 0x9d, 0x41, 0x2f, 0x34, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x34, 0x2f, 0x38, + 0x4d, 0x37, 0xd0, 0xd1, 0x8f, 0x74, 0x63, 0x7e, + 0x75, 0x7e, 0x63, 0xc7, 0x88, 0xc4, 0x31, 0x2a, + 0x24, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x21, 0x22, 0x23, 0x24, 0x26, 0x30, + 0x33, 0x39, 0x2e, 0x51, 0x41, 0xb2, 0x6c, 0xd1, + 0x80, 0xcc, 0xcc, 0xcc, 0xd2, 0xd1, 0xb7, 0xd3, + 0x41, 0x34, 0x35, 0x32, 0x30, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x30, 0x2a, + 0x2b, 0x34, 0xd4, 0xca, 0xd5, 0x8f, 0xbb, 0xc7, + 0xc7, 0xbb, 0xcc, 0x6c, 0x41, 0x39, 0x27, 0x28, + 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22, + 0x28, 0x24, 0x26, 0x2a, 0x33, 0x2c, 0x2f, 0x41, + 0xd6, 0xb7, 0x79, 0x79, 0x79, 0xca, 0xd7, 0x51, + 0x39, 0x30, 0x24, 0x23, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x22, 0x23, + 0x24, 0x2a, 0x31, 0xd8, 0xc8, 0x79, 0xd1, 0x80, + 0xd5, 0xba, 0xd9, 0x2f, 0x35, 0x26, 0x23, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x21, 0x22, 0x23, 0x28, 0x25, 0x30, 0x2b, + 0x31, 0x2f, 0xd4, 0xd8, 0xd8, 0x2f, 0x2e, 0x33, + 0x26, 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x28, 0x27, 0x35, 0x34, 0xd8, 0xd8, 0xd8, + 0xda, 0xd4, 0x2e, 0x33, 0x25, 0x23, 0x21, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x23, 0x28, + 0x26, 0x30, 0x32, 0x2b, 0x33, 0x2a, 0x26, 0x28, + 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x21, 0x23, 0x25, 0x30, 0x33, 0x35, 0x35, + 0x2b, 0x2a, 0x26, 0x28, 0x22, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x21, 0x22, 0x23, 0x28, 0x28, 0x23, 0x22, 0x21, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x21, 0x23, 0x28, 0x24, 0x24, + 0x28, 0x23, 0x22, 0x21, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, }; -#endif +#endif /* !__HAVE_ARCH_LINUX_LOGO */ -#ifdef INCLUDE_LINUX_LOGOBW +#ifndef __HAVE_ARCH_LINUX_LOGOBW unsigned char linux_logo_bw[] __initdata = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x3F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, - 0xFE, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFE, 0x3F, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xC7, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xC3, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, - 0xFB, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFD, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, - 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF9, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xF9, 0xCF, 0xC3, 0xF8, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x87, 0x81, 0xF9, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xA7, - 0x99, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF9, 0xF3, 0xBC, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xF9, 0xE3, 0xBC, 0xF9, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0, 0x3C, 0xF9, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0, - 0x19, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF9, 0xC0, 0x03, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x80, - 0x01, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF9, 0xC0, 0x21, 0xD8, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xF9, 0xB1, 0x80, 0xEC, 0xC0, 0x1F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x90, 0x00, 0xE4, - 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x8C, - 0xC0, 0x7C, 0x04, 0x81, 0xFF, 0xFF, 0xFF, 0xFF, - 0xE3, 0x80, 0x00, 0x7C, 0x40, 0x11, 0xFF, 0xFF, - 0xFF, 0xFF, 0xE3, 0x80, 0x00, 0x7F, 0xD2, 0x29, - 0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0x00, 0x00, 0x3F, - 0x80, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0x0E, 0x00, - 0x00, 0x3F, 0x80, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, - 0x1E, 0x00, 0x00, 0x1F, 0x80, 0x19, 0xFF, 0xFF, - 0xFF, 0xFE, 0x1C, 0x00, 0x00, 0x1E, 0x80, 0x19, - 0xFF, 0xFF, 0xFF, 0xFE, 0x3C, 0x00, 0x00, 0x1E, - 0x80, 0x11, 0xFF, 0xFF, 0xFF, 0xFC, 0x7C, 0x00, - 0x00, 0x0F, 0x80, 0x11, 0xFF, 0xFF, 0xFF, 0xFC, - 0xF8, 0x00, 0x00, 0x0E, 0x80, 0x11, 0xFF, 0xFF, - 0xFF, 0xFC, 0xF8, 0x00, 0x00, 0x06, 0x00, 0x11, - 0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0x00, 0x00, 0x06, - 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xF9, 0xF0, 0x00, - 0x00, 0x02, 0x00, 0x09, 0xFF, 0xFF, 0xFF, 0xF1, - 0xF0, 0x00, 0x00, 0x02, 0x80, 0x10, 0xFF, 0xFF, - 0xFF, 0xF1, 0xE0, 0x00, 0x00, 0x00, 0x97, 0x10, - 0xFF, 0xFF, 0xFF, 0xE3, 0xE0, 0x00, 0x00, 0x00, - 0xDF, 0xF0, 0xFF, 0xFF, 0xFF, 0xE3, 0xC0, 0x00, - 0x00, 0x00, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xC7, - 0xC0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF, - 0xFF, 0xC7, 0x80, 0x00, 0x00, 0x01, 0xFF, 0xF8, - 0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00, 0x00, 0x01, - 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00, - 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x9F, - 0x80, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF, - 0xFF, 0x9F, 0x80, 0x00, 0x00, 0x01, 0x80, 0x18, - 0xFF, 0xFF, 0xFF, 0x9E, 0x80, 0x00, 0x00, 0x03, - 0xA8, 0x11, 0xFF, 0xFF, 0xFF, 0x9F, 0x80, 0x00, - 0x00, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x99, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x09, 0xFF, 0xFF, - 0xFF, 0x00, 0x80, 0x00, 0x00, 0x01, 0xC0, 0x01, - 0xFF, 0xFF, 0xFE, 0x20, 0x60, 0x00, 0x00, 0x00, - 0xFF, 0xC3, 0xFF, 0xFF, 0xF8, 0x00, 0x30, 0x00, - 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0xFF, 0xC0, 0x40, - 0x38, 0x00, 0x00, 0x00, 0xFE, 0x47, 0xFF, 0xFF, - 0x81, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xFC, 0x23, - 0xFF, 0xFF, 0x90, 0x00, 0x1E, 0x00, 0x00, 0x00, - 0x78, 0x11, 0xFF, 0xFF, 0x80, 0x00, 0x0F, 0x80, - 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, - 0x07, 0xC0, 0x00, 0x00, 0x00, 0x08, 0xFF, 0xFF, - 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x04, - 0x7F, 0xFF, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x10, - 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x01, 0x80, - 0x00, 0x30, 0x00, 0x00, 0x0F, 0xFF, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, 0x4F, 0xFF, - 0x80, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, - 0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x80, 0x03, 0xF0, - 0x00, 0x00, 0x8F, 0xFF, 0x80, 0x00, 0x00, 0x40, - 0x0F, 0xF0, 0x00, 0x04, 0x1F, 0xFF, 0x80, 0x00, - 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x10, 0x1F, 0xFF, - 0xC0, 0x00, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x40, - 0xFF, 0xFF, 0x98, 0x00, 0x00, 0xFF, 0xFF, 0xF0, - 0x00, 0x83, 0xFF, 0xFF, 0x81, 0xE0, 0x01, 0xFF, - 0xFF, 0xF8, 0x02, 0x07, 0xFF, 0xFF, 0x80, 0x3F, - 0x07, 0xE0, 0x00, 0x1C, 0x0C, 0x1F, 0xFF, 0xFF, - 0xF8, 0x03, 0xFF, 0x80, 0x00, 0x1F, 0x78, 0x1F, - 0xFF, 0xFF, 0xFF, 0x80, 0x7F, 0x00, 0x07, 0x0F, - 0xF0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0x0C, 0x07, - 0xFF, 0x83, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x1F, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x07, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xcf, 0xf3, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xbf, 0xfc, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfd, 0xff, 0xf3, 0xdf, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfd, 0xff, 0xf7, 0xef, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfb, 0x9f, 0x87, 0xfb, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfb, 0x0f, 0x03, 0xfb, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfb, 0x67, 0x33, 0xfb, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfb, 0xe7, 0x79, 0xfb, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfb, 0xf7, 0x79, 0xfb, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfb, 0xff, 0xf9, 0xf7, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfb, 0x60, 0x3b, 0xf7, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfb, 0x89, 0x07, 0xfb, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfb, 0x00, 0x03, 0xfb, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfb, 0x00, 0x0d, 0xfb, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfb, 0x80, 0x33, 0xfd, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfb, 0xc0, 0xc3, 0xfd, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfb, 0xff, 0x0d, 0xdd, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfb, 0x40, 0x31, 0xee, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf7, 0x20, 0xc1, 0xee, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf7, 0x1f, 0x00, 0xff, 0x7f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xef, 0x00, 0x00, 0x7f, 0xbf, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xee, 0x00, 0x00, 0x7f, 0xbf, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xde, 0x00, 0x00, 0x7f, 0xdf, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xbc, 0x00, 0x00, 0x3f, 0xef, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x7c, 0x00, 0x00, 0x3f, 0xf7, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x7c, 0x00, 0x00, 0x1f, 0xf7, 0xff, 0xff, + 0xff, 0xff, 0xfe, 0xff, 0x1c, 0x07, 0xdf, 0xfb, 0xff, 0xff, + 0xff, 0xff, 0xfd, 0xfc, 0x08, 0x0f, 0xef, 0xfd, 0xff, 0xff, + 0xff, 0xff, 0xfd, 0xf8, 0x00, 0x01, 0xef, 0xfd, 0xff, 0xff, + 0xff, 0xff, 0xfb, 0xf0, 0x00, 0x00, 0x7f, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0xfb, 0xe0, 0x00, 0x00, 0x1f, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0xf7, 0xe0, 0x00, 0x00, 0x07, 0xbf, 0x7f, 0xff, + 0xff, 0xff, 0xf7, 0xc0, 0x00, 0x00, 0x03, 0xbf, 0x7f, 0xff, + 0xff, 0xff, 0xef, 0xc0, 0x00, 0x00, 0x03, 0xdf, 0xbf, 0xff, + 0xff, 0xff, 0xef, 0x80, 0x00, 0x00, 0x03, 0xdf, 0xbf, 0xff, + 0xff, 0xff, 0xdf, 0x80, 0x00, 0x00, 0x03, 0xdf, 0xbf, 0xff, + 0xff, 0xff, 0xdf, 0x80, 0x00, 0x00, 0x01, 0xef, 0xdf, 0xff, + 0xff, 0xff, 0xdf, 0x80, 0x00, 0x00, 0x01, 0xef, 0xdf, 0xff, + 0xff, 0xff, 0xbf, 0x00, 0x20, 0x00, 0x01, 0xef, 0xdf, 0xff, + 0xff, 0xff, 0xbf, 0x00, 0x20, 0x00, 0x01, 0xef, 0xdf, 0xff, + 0xff, 0xff, 0xbf, 0x00, 0x20, 0x00, 0x01, 0xef, 0xdf, 0xff, + 0xff, 0xff, 0xbf, 0x00, 0x20, 0x00, 0x01, 0xef, 0xdf, 0xff, + 0xff, 0xff, 0xbf, 0x00, 0x20, 0x00, 0x03, 0x03, 0xdf, 0xff, + 0xff, 0xff, 0xbf, 0x00, 0x20, 0x00, 0x02, 0xfd, 0xdf, 0xff, + 0xff, 0xff, 0xa3, 0x80, 0x00, 0x00, 0x1f, 0xff, 0xdf, 0xff, + 0xff, 0xff, 0xc1, 0xc0, 0x00, 0x00, 0x11, 0xff, 0x3f, 0xff, + 0xff, 0xff, 0x80, 0xe0, 0x00, 0x00, 0x21, 0xfe, 0x3f, 0xff, + 0xff, 0xff, 0x00, 0x70, 0x00, 0x00, 0x21, 0xfc, 0x3f, 0xff, + 0xff, 0xfe, 0x00, 0x3c, 0x00, 0x00, 0x20, 0xf8, 0x3f, 0xff, + 0xff, 0xf0, 0x00, 0x3e, 0x00, 0x00, 0x20, 0x00, 0x3f, 0xff, + 0xff, 0xc0, 0x00, 0x1f, 0x00, 0x00, 0x20, 0x00, 0x3f, 0xff, + 0xff, 0xc0, 0x00, 0x1f, 0x80, 0x00, 0x20, 0x00, 0x1f, 0xff, + 0xff, 0xc0, 0x00, 0x0f, 0x80, 0x00, 0x20, 0x00, 0x07, 0xff, + 0xff, 0xc0, 0x00, 0x07, 0x80, 0x00, 0x20, 0x00, 0x03, 0xff, + 0xff, 0xc0, 0x00, 0x07, 0x80, 0x00, 0x60, 0x00, 0x01, 0xff, + 0xff, 0xc0, 0x00, 0x02, 0x00, 0x00, 0xe0, 0x00, 0x01, 0xff, + 0xff, 0xc0, 0x00, 0x01, 0x00, 0x01, 0xe0, 0x00, 0x01, 0xff, + 0xff, 0xc0, 0x00, 0x00, 0x80, 0x07, 0xe0, 0x00, 0x03, 0xff, + 0xff, 0xc0, 0x00, 0x00, 0x80, 0x3f, 0xe0, 0x00, 0x0f, 0xff, + 0xff, 0xc0, 0x00, 0x00, 0x7f, 0xff, 0xc0, 0x00, 0x1f, 0xff, + 0xff, 0xc0, 0x00, 0x00, 0x7f, 0xff, 0xc0, 0x00, 0x7f, 0xff, + 0xff, 0xe0, 0x00, 0x00, 0x7f, 0xff, 0xc0, 0x00, 0xff, 0xff, + 0xff, 0xfc, 0x00, 0x00, 0x7f, 0xff, 0xc0, 0x03, 0xff, 0xff, + 0xff, 0xff, 0xc0, 0x00, 0x70, 0x00, 0xc0, 0x07, 0xff, 0xff, + 0xff, 0xff, 0xfc, 0x00, 0x8f, 0xff, 0x20, 0x0f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xe0, 0x1f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; -#endif +#endif /* !__HAVE_ARCH_LINUX_LOGOBW */ -#ifdef INCLUDE_LINUX_LOGO16 +#ifndef __HAVE_ARCH_LINUX_LOGO16 -unsigned char linux_logo16_red[] __initdata = { - 0x00, 0x90, 0xb0, 0x9c, 0xf7, 0x35, 0x83, 0xa5, - 0x65, 0x8f, 0x98, 0xc9, 0xdb, 0xe1, 0xe7, 0xf8 +unsigned char linux_logo16[] __initdata = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x88, 0x88, 0x88, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x88, 0x80, 0x00, 0x00, 0x08, 0x88, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x80, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x08, 0x70, 0x00, 0x00, 0x00, 0x77, 0x70, 0x00, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x87, 0x77, 0x00, 0x00, 0x07, 0xff, 0xf7, 0x00, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, + 0x77, 0xff, 0x00, 0x00, 0x7f, 0x77, 0xf7, 0x00, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, + 0x70, 0x0f, 0x80, 0x00, 0xf7, 0x08, 0x7f, 0x70, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, + 0x80, 0x07, 0x80, 0x00, 0xf8, 0x00, 0x8f, 0x70, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, + 0x70, 0x07, 0x88, 0x88, 0xf8, 0x00, 0x8f, 0x70, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0xf0, 0x06, 0xe6, 0xe6, 0xe6, 0x00, 0x8f, 0x00, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x77, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x77, 0x00, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x06, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0x00, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x60, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, + 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0x60, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, + 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x66, 0x66, 0x80, + 0x08, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, + 0x86, 0xe6, 0xe6, 0xe6, 0x66, 0x66, 0x66, 0x80, + 0x08, 0x78, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, + 0x86, 0x66, 0x66, 0x66, 0x66, 0x66, 0x77, 0x70, + 0x00, 0x77, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x87, 0x66, 0x66, 0x66, 0x66, 0x77, 0x77, 0x78, + 0x00, 0x88, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x87, 0x76, 0x66, 0x66, 0x77, 0x77, 0xff, 0xf7, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, + 0xff, 0x77, 0x77, 0x77, 0x77, 0xff, 0xff, 0xff, + 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, + 0xff, 0x77, 0x77, 0x77, 0x7f, 0xff, 0xff, 0xff, + 0x70, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x8f, + 0xff, 0xf7, 0x77, 0x77, 0xff, 0xff, 0xff, 0xff, + 0xf0, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x7f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf8, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf7, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x87, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x87, 0x77, + 0xff, 0xf7, 0x77, 0xff, 0xff, 0xff, 0x77, 0x77, + 0x77, 0x78, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x77, 0x7f, + 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x77, + 0x77, 0x78, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x7f, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf7, 0x77, 0x00, 0x08, 0x80, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x80, 0x08, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x77, 0x80, 0x00, 0x08, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x80, 0x07, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x78, 0x00, 0x08, 0x80, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x08, 0x00, 0x8f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xf7, 0x08, 0x80, 0x80, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x08, 0x08, 0x7f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xf7, 0x08, 0x80, 0x80, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x08, 0x07, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x80, 0x00, 0x08, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x80, 0x0f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x70, 0x00, 0x08, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x80, 0x8f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x70, 0x00, 0x08, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x08, 0x00, 0x7f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x70, 0x00, 0x08, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x08, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf0, 0x00, 0x08, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x08, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf0, 0x00, 0x08, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x08, 0x08, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf0, 0x00, 0x08, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x08, 0x08, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf0, 0x00, 0x08, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x88, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf0, 0x00, 0x08, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x08, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf0, 0x88, 0x88, 0x80, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x06, 0xe6, 0x00, 0x8f, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x08, 0x80, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x6e, 0x6e, 0x60, 0x08, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xe6, 0xe0, 0x00, 0x00, 0x00, 0x88, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0xe6, 0xe6, 0xe6, 0x00, 0x8f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfe, 0x6e, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x6e, 0x6e, 0x6e, 0x6e, 0x60, 0x08, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xf6, 0xe6, 0xe0, 0x00, 0x00, 0x00, 0x06, + 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xe6, 0xe6, + 0xe6, 0xe6, 0xe6, 0xe6, 0xe0, 0x00, 0x8f, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfe, 0x6e, 0x60, 0x00, 0x00, 0x00, 0x0e, + 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x6e, 0x6e, + 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x00, 0x08, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x76, 0xe6, 0xe6, 0x00, 0x00, 0x00, 0xe6, + 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xe6, 0xe6, + 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe0, 0x00, 0x8f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf7, 0x7e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, + 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x6e, 0x6e, + 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x60, 0x00, 0x08, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf7, 0x76, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, + 0xe6, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xe6, 0xe6, + 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0x00, 0x00, + 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf7, 0x7e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, + 0x6e, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x6e, 0x6e, + 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x60, 0x00, + 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf7, 0x76, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, + 0xe6, 0xe6, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xe6, 0xe6, + 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe0, 0x00, + 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf7, 0x8e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, + 0x6e, 0x6e, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x6e, 0x6e, + 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x88, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x78, 0x86, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, + 0xe6, 0xe6, 0xe6, 0xe6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xe6, 0xe6, + 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xef, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, + 0x80, 0x06, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, + 0x6e, 0x6e, 0x6e, 0x6e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x6e, 0x6e, + 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, + 0x00, 0x06, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, + 0xe6, 0xe6, 0xe6, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xe6, 0xe6, + 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, + 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x80, + 0x00, 0x06, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, + 0x6e, 0x6e, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x6e, 0x6e, 0x6e, + 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x66, + 0x67, 0xff, 0xff, 0xff, 0xff, 0x78, 0x80, 0x00, + 0x00, 0x86, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, + 0xe6, 0xe6, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0xe6, 0xe6, 0xe6, + 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, + 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x86, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, + 0x66, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x6e, 0x6e, 0x6e, + 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x66, + 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x86, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, + 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xe6, 0xe6, + 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, + 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x86, 0x6e, 0x6e, 0x6e, 0x6e, 0x66, 0x66, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, + 0x66, 0x66, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x66, + 0x60, 0x00, 0x88, 0x88, 0x88, 0x88, 0x88, 0x80, + 0x00, 0x06, 0x66, 0xe6, 0xe6, 0xe6, 0x66, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x66, 0x66, 0x66, 0x66, 0xe6, 0xe6, 0x66, + 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x88, 0x86, 0x66, 0x6e, 0x6e, 0x66, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x66, 0x66, 0x66, 0x66, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x06, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x66, 0x66, 0x60, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x66, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; -unsigned char linux_logo16_green[] __initdata = { - 0x00, 0x90, 0xb0, 0x9c, 0xf7, 0x2e, 0x83, 0xa5, - 0x65, 0x6e, 0x98, 0x89, 0xbf, 0xac, 0xda, 0xf8 -}; +#endif /* !__HAVE_ARCH_LINUX_LOGO16 */ -unsigned char linux_logo16_blue[] __initdata = { - 0x00, 0x90, 0xaf, 0x9c, 0xf7, 0x2b, 0x82, 0xa5, - 0x65, 0x41, 0x97, 0x1e, 0x60, 0x29, 0xa5, 0xf8 -}; +#else /* !INCLUDE_LINUX_LOGO_DATA */ -unsigned char linux_logo16[] __initdata = { - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa1, 0x11, 0x11, - 0x61, 0x16, 0x66, 0x66, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x1a, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0xa8, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x87, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x73, 0x33, 0x33, 0x3a, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xa3, 0x33, 0x33, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x27, 0x77, 0x77, 0x77, 0x33, 0x3a, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xa3, 0x33, 0x33, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x55, 0x50, 0x08, 0x33, 0x77, 0x77, - 0x77, 0x72, 0x72, 0x27, 0x77, 0x77, 0x33, 0x33, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xa3, 0x33, 0x33, 0x77, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x58, 0x85, 0x00, 0x11, 0x11, 0xaa, - 0xa3, 0x37, 0x77, 0x72, 0x22, 0x22, 0x77, 0x73, - 0x33, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa3, - 0x33, 0x37, 0x77, 0x33, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x56, 0x85, 0x00, 0x06, 0x66, 0x11, - 0x11, 0x1a, 0xa3, 0x37, 0x77, 0x72, 0x22, 0x77, - 0x73, 0x33, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33, - 0x33, 0x33, 0x33, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x55, 0x00, 0x00, 0x06, 0x66, 0x66, - 0x66, 0x66, 0x11, 0x1a, 0xa3, 0x77, 0x72, 0x22, - 0x77, 0x73, 0x3a, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x33, - 0x33, 0x33, 0x33, 0xa0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, - 0x66, 0x66, 0x66, 0x66, 0x11, 0xa3, 0x77, 0x22, - 0x22, 0x77, 0x33, 0x33, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x33, 0x33, - 0x33, 0x3a, 0xa1, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x33, - 0xaa, 0x11, 0x16, 0x66, 0x66, 0x61, 0x1a, 0x37, - 0x22, 0x22, 0x77, 0x33, 0x3a, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xa3, 0x33, 0x33, 0x33, - 0x3a, 0xa1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x22, - 0x22, 0x77, 0x3a, 0x11, 0x66, 0x66, 0x66, 0x1a, - 0x37, 0x22, 0x22, 0x77, 0x33, 0x3a, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x33, 0x33, 0x3a, - 0xa1, 0x11, 0x11, 0x10, 0x00, 0x00, 0x50, 0x00, - 0x00, 0x05, 0x80, 0x50, 0x00, 0x00, 0x07, 0x72, - 0x22, 0x22, 0x22, 0x73, 0xa1, 0x66, 0x66, 0x61, - 0x1a, 0x77, 0x22, 0x27, 0x73, 0x33, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x33, 0x3a, 0xaa, - 0x11, 0x11, 0x1a, 0xa0, 0x08, 0x71, 0x05, 0x00, - 0x00, 0x12, 0x22, 0x50, 0x00, 0x00, 0x07, 0x77, - 0x77, 0x72, 0x22, 0x22, 0x27, 0x31, 0x16, 0x66, - 0x61, 0x13, 0x77, 0x22, 0x77, 0x33, 0x3a, 0xaa, - 0xaa, 0xaa, 0xaa, 0xa3, 0x33, 0x33, 0xaa, 0xa1, - 0x11, 0x1a, 0x33, 0x70, 0x07, 0x2e, 0x70, 0x00, - 0x01, 0x44, 0x42, 0x60, 0x00, 0x00, 0x02, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x27, 0x31, 0x66, - 0x66, 0x61, 0xa3, 0x72, 0x22, 0x77, 0x33, 0xaa, - 0xaa, 0xaa, 0xa3, 0x33, 0x33, 0xaa, 0xaa, 0x11, - 0x1a, 0x33, 0x77, 0x30, 0x04, 0x82, 0x40, 0x00, - 0x54, 0x48, 0x54, 0x40, 0x00, 0x00, 0x01, 0xaa, - 0x32, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x31, - 0x66, 0x66, 0x11, 0x37, 0x22, 0x27, 0x73, 0x3a, - 0xaa, 0xaa, 0xa3, 0x33, 0x3a, 0xaa, 0xaa, 0xaa, - 0xa3, 0x77, 0xaa, 0x10, 0x50, 0x08, 0x46, 0x05, - 0x54, 0x80, 0x50, 0x42, 0x00, 0x00, 0x08, 0x66, - 0x66, 0x1a, 0x32, 0x22, 0x22, 0x22, 0x22, 0x27, - 0x31, 0x66, 0x66, 0x13, 0x72, 0x22, 0x77, 0x33, - 0xaa, 0xaa, 0xaa, 0x33, 0xaa, 0xa1, 0xaa, 0xa3, - 0x37, 0xa1, 0x1a, 0x30, 0x50, 0x06, 0x26, 0x00, - 0x54, 0x00, 0x00, 0x44, 0x00, 0x00, 0x08, 0xe2, - 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0x22, 0x22, - 0x27, 0xa6, 0x66, 0x61, 0xa7, 0x72, 0x27, 0x73, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33, - 0x31, 0x11, 0x37, 0x70, 0x02, 0x00, 0xab, 0xbb, - 0xb6, 0x00, 0x00, 0xf4, 0x00, 0x00, 0xee, 0xee, - 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0x22, - 0x22, 0x23, 0x16, 0x66, 0x1a, 0x37, 0x22, 0x77, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa3, 0x3a, - 0x11, 0xa7, 0x33, 0x10, 0x04, 0x09, 0xbd, 0xdd, - 0xbd, 0xd0, 0x04, 0x45, 0x00, 0x0e, 0xee, 0xee, - 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0x22, - 0x22, 0x22, 0x71, 0x66, 0x66, 0x13, 0x72, 0x27, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x11, - 0xa3, 0x73, 0xa1, 0x60, 0x08, 0xbd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdb, 0x90, 0x00, 0x02, 0xec, 0xee, - 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xce, 0x22, - 0x22, 0x22, 0x27, 0xa6, 0x66, 0x61, 0x37, 0x27, - 0x1a, 0xaa, 0xaa, 0xaa, 0xaa, 0xa3, 0xa1, 0x1a, - 0x33, 0xa1, 0x16, 0x60, 0x0b, 0xbd, 0xdd, 0xdd, - 0xcd, 0xdd, 0xdd, 0xd9, 0x00, 0x00, 0xec, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0xa2, - 0x22, 0x22, 0x22, 0x7a, 0x66, 0x66, 0x13, 0x77, - 0x1a, 0xaa, 0xaa, 0xaa, 0xaa, 0x3a, 0x11, 0x33, - 0xaa, 0x11, 0x66, 0x60, 0x9b, 0xdd, 0xdd, 0xdd, - 0xcd, 0xdd, 0xdb, 0xb9, 0x00, 0x00, 0xec, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xee, 0x61, - 0x72, 0x22, 0x22, 0x22, 0xa1, 0x66, 0x61, 0x37, - 0x1a, 0xaa, 0xaa, 0xaa, 0xa3, 0xa1, 0x13, 0x3a, - 0x11, 0x11, 0x11, 0x10, 0x5b, 0xdd, 0xdd, 0xdc, - 0xdd, 0xdd, 0xbd, 0xd9, 0x00, 0x00, 0xec, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xee, 0x86, - 0x17, 0x22, 0x22, 0x22, 0x23, 0x16, 0x66, 0xaa, - 0xaa, 0xa3, 0x3a, 0xaa, 0xaa, 0x1a, 0x3a, 0xa1, - 0x11, 0x11, 0x1a, 0x70, 0x05, 0xbd, 0xdd, 0xdd, - 0xdb, 0x5b, 0xdd, 0xb0, 0x00, 0x60, 0x2e, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xe6, 0x88, - 0x66, 0x32, 0x22, 0x22, 0x22, 0x36, 0x66, 0x11, - 0x33, 0x33, 0x3a, 0xaa, 0x11, 0xaa, 0xaa, 0xa1, - 0x11, 0x1a, 0x3a, 0x60, 0x02, 0x99, 0xbb, 0xb9, - 0x9b, 0xbb, 0xbc, 0x22, 0x00, 0x86, 0x5e, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xe1, 0x68, - 0x86, 0x63, 0x22, 0x22, 0x22, 0x2a, 0x66, 0x66, - 0x33, 0x33, 0xaa, 0xaa, 0x1a, 0xaa, 0xaa, 0x11, - 0x1a, 0xa7, 0x68, 0x80, 0x02, 0x2b, 0xbd, 0xbb, - 0xbb, 0xb9, 0x22, 0x22, 0x00, 0x06, 0x6e, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xc7, 0xa6, - 0x88, 0x86, 0x32, 0x22, 0x22, 0x27, 0xa6, 0x66, - 0x33, 0x3a, 0xaa, 0xa1, 0xaa, 0xaa, 0xa1, 0x11, - 0xa3, 0xa6, 0x88, 0x80, 0x02, 0x22, 0x9b, 0xbb, - 0xbb, 0x22, 0x24, 0xf4, 0x60, 0x00, 0x0c, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xc2, 0x21, - 0x68, 0x88, 0x63, 0x22, 0x22, 0x22, 0x71, 0x66, - 0x33, 0x3a, 0x11, 0x11, 0xaa, 0xaa, 0x11, 0xaa, - 0x71, 0x88, 0x88, 0x00, 0x02, 0xe2, 0x26, 0x99, - 0x22, 0x22, 0x4f, 0xf4, 0x40, 0x00, 0x0c, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x22, 0x22, - 0x16, 0x88, 0x86, 0xa2, 0x22, 0x22, 0x27, 0x11, - 0x33, 0xa1, 0x11, 0x11, 0xaa, 0x31, 0x1a, 0xa3, - 0x68, 0x88, 0x81, 0x00, 0x54, 0x42, 0x22, 0x22, - 0x22, 0x44, 0xff, 0xff, 0x48, 0x00, 0x00, 0x99, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x22, 0x22, - 0x21, 0x88, 0x88, 0x6a, 0x22, 0x22, 0x22, 0x31, - 0x3a, 0xa1, 0x11, 0x1a, 0xa3, 0x11, 0x33, 0x36, - 0x88, 0x86, 0x30, 0x00, 0x4f, 0x44, 0x22, 0x22, - 0x24, 0xff, 0xff, 0xff, 0x44, 0x00, 0x00, 0x99, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x95, 0x22, 0x72, - 0x22, 0x18, 0x88, 0x86, 0x32, 0x22, 0x22, 0x27, - 0xaa, 0x11, 0x11, 0x1a, 0x31, 0x13, 0x33, 0x68, - 0x88, 0x6a, 0x00, 0x02, 0x4f, 0x4f, 0x42, 0x24, - 0x4f, 0xff, 0xff, 0xff, 0xf4, 0x50, 0x00, 0x99, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x22, 0x73, - 0x72, 0x26, 0x88, 0x88, 0x63, 0x22, 0x22, 0x22, - 0x11, 0x11, 0x11, 0xa3, 0xa1, 0x73, 0xa6, 0x88, - 0x81, 0xa5, 0x00, 0x04, 0x4f, 0x4f, 0x44, 0x4f, - 0xff, 0xff, 0xff, 0xff, 0xf4, 0x40, 0x00, 0x99, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x12, 0x27, - 0xaa, 0x22, 0x68, 0x55, 0x86, 0x72, 0x22, 0x22, - 0x11, 0x11, 0x1a, 0x33, 0x13, 0x3a, 0x18, 0x88, - 0x1a, 0x10, 0x00, 0x44, 0x4f, 0x4f, 0xff, 0x4f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x99, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x61, 0x22, - 0x3a, 0xa2, 0x26, 0x85, 0x58, 0x67, 0x22, 0x22, - 0x61, 0x61, 0x1a, 0x7a, 0x37, 0x31, 0x88, 0x81, - 0x11, 0x00, 0x05, 0xe4, 0x44, 0xff, 0xff, 0xff, - 0x4f, 0xf4, 0x44, 0xff, 0xff, 0xf5, 0x00, 0x99, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x88, 0x12, - 0x2a, 0xaa, 0x72, 0x68, 0x55, 0x81, 0x22, 0x22, - 0x66, 0x61, 0xa3, 0x33, 0x73, 0x16, 0x88, 0x11, - 0x10, 0x00, 0x08, 0x74, 0x44, 0x4f, 0x44, 0x44, - 0xf4, 0xf4, 0x44, 0x44, 0xe2, 0x44, 0x00, 0x99, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x88, 0x81, - 0x22, 0xaa, 0xa7, 0x26, 0x85, 0x88, 0x12, 0x22, - 0x66, 0x61, 0x37, 0xa7, 0x3a, 0x66, 0x66, 0x11, - 0x80, 0x00, 0x0a, 0x72, 0x44, 0x4f, 0x44, 0x4f, - 0xff, 0x44, 0x44, 0x22, 0x22, 0x24, 0x00, 0x99, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x85, 0x88, - 0x12, 0x2a, 0xaa, 0x22, 0x68, 0x58, 0x63, 0x22, - 0x66, 0x1a, 0x73, 0x77, 0x31, 0x66, 0x61, 0x11, - 0x00, 0x00, 0x07, 0x44, 0xff, 0x4f, 0xf4, 0x4f, - 0xff, 0x4f, 0x44, 0xf4, 0x42, 0x22, 0x40, 0x9b, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xb9, 0x85, 0x55, - 0x81, 0x27, 0xaa, 0xa2, 0x78, 0x88, 0x86, 0x72, - 0x66, 0x13, 0x77, 0x73, 0x11, 0x66, 0x61, 0x76, - 0x00, 0x50, 0x84, 0xf4, 0xff, 0x4f, 0xf4, 0xff, - 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x42, 0x40, 0x9b, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xb9, 0x68, 0x55, - 0x58, 0x12, 0x3a, 0xaa, 0x23, 0x88, 0x88, 0xa7, - 0x66, 0xa7, 0x77, 0x7a, 0x16, 0x66, 0x1a, 0x15, - 0x05, 0x00, 0x4f, 0xf4, 0xff, 0x4f, 0xf4, 0xff, - 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x44, 0x24, 0x9b, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xb9, 0x26, 0x55, - 0x55, 0x81, 0x23, 0xaa, 0x32, 0x18, 0x88, 0x6a, - 0x61, 0x37, 0x77, 0x31, 0x66, 0x66, 0x17, 0x60, - 0x05, 0x08, 0x4f, 0xf4, 0xff, 0x4f, 0xf4, 0xff, - 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x4e, 0x99, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0xa2, 0x65, - 0x55, 0x58, 0xa2, 0x7a, 0xa2, 0x26, 0x88, 0x61, - 0x61, 0x32, 0x27, 0xa1, 0x66, 0x61, 0x31, 0x60, - 0x00, 0x04, 0x4f, 0xf4, 0xff, 0x44, 0x44, 0xff, - 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x44, 0xf4, 0x99, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x9b, 0xaa, 0x26, - 0x55, 0x55, 0x87, 0x27, 0x33, 0x27, 0x68, 0x61, - 0x1a, 0x72, 0x27, 0xa6, 0x66, 0x6a, 0x71, 0x00, - 0x80, 0x84, 0xff, 0xf4, 0xff, 0x44, 0x44, 0xff, - 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x44, 0xf4, 0x99, - 0x9b, 0x9b, 0x99, 0xb9, 0xb9, 0x99, 0xaa, 0xa2, - 0x85, 0x55, 0x56, 0x22, 0x27, 0x22, 0x36, 0x66, - 0x13, 0x22, 0x23, 0x16, 0x86, 0x63, 0x73, 0x00, - 0x00, 0x44, 0xf4, 0xf4, 0xff, 0x44, 0x44, 0xff, - 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x4f, 0x99, - 0x9b, 0x99, 0x99, 0x99, 0xb9, 0x99, 0xaa, 0xaa, - 0x28, 0x55, 0x58, 0x12, 0x22, 0x22, 0x21, 0x11, - 0xa3, 0x27, 0x7a, 0x66, 0x86, 0x17, 0x75, 0x05, - 0x05, 0xff, 0xf4, 0xf4, 0xff, 0x44, 0x44, 0xff, - 0xff, 0x4f, 0x44, 0x4f, 0x4f, 0x44, 0x4f, 0x99, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x3a, 0xaa, - 0xa2, 0x85, 0x58, 0x67, 0x72, 0x22, 0x27, 0xa1, - 0x37, 0x27, 0x7a, 0x68, 0x86, 0xa2, 0x70, 0x00, - 0x02, 0xff, 0xf4, 0xf4, 0xff, 0x44, 0x44, 0x4f, - 0xff, 0x4f, 0x44, 0xf4, 0xf4, 0xf4, 0xf4, 0x99, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x23, 0xaa, - 0xa7, 0x78, 0x88, 0x81, 0x77, 0x22, 0x27, 0x3a, - 0x72, 0x73, 0x71, 0x68, 0x66, 0x32, 0x50, 0x00, - 0x04, 0x4f, 0xf4, 0xf4, 0xff, 0x44, 0x44, 0x4f, - 0xff, 0x4f, 0x44, 0xf4, 0xf4, 0xf4, 0x44, 0x95, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x55, 0x12, 0x3a, - 0xaa, 0x21, 0x88, 0x81, 0x77, 0x27, 0x73, 0x73, - 0x72, 0x33, 0x36, 0x86, 0x61, 0x72, 0x00, 0x00, - 0x04, 0x44, 0xf4, 0xf4, 0xf4, 0x44, 0x44, 0x4f, - 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x44, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x8a, 0x27, - 0xaa, 0x77, 0x68, 0x61, 0x23, 0x71, 0x11, 0x3a, - 0x27, 0xa3, 0x36, 0x86, 0x61, 0x20, 0x00, 0x00, - 0x04, 0xf4, 0xf4, 0xf4, 0xf4, 0x44, 0x44, 0x4f, - 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x41, 0x59, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x95, 0x58, 0x77, - 0x27, 0x32, 0x36, 0x63, 0x23, 0x71, 0x66, 0x11, - 0x27, 0x13, 0xa6, 0x86, 0x6a, 0x20, 0x00, 0x50, - 0x04, 0x4f, 0x4f, 0x4f, 0x4f, 0x44, 0x44, 0x4f, - 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x41, 0x99, - 0x9b, 0xbb, 0xbb, 0xbb, 0xb9, 0x99, 0x68, 0x13, - 0x32, 0x22, 0x73, 0xa7, 0x2a, 0x31, 0x88, 0x66, - 0x7a, 0x13, 0x18, 0x66, 0x63, 0x20, 0x00, 0x06, - 0x0f, 0x4f, 0x4f, 0x4f, 0x4f, 0x44, 0x44, 0x4f, - 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x49, 0x95, - 0xa9, 0xa9, 0x99, 0x97, 0x92, 0x99, 0x65, 0x6a, - 0x17, 0x22, 0x23, 0x72, 0x27, 0xaa, 0x88, 0x88, - 0xa1, 0x17, 0x68, 0x66, 0x67, 0x70, 0x00, 0x05, - 0x0f, 0x4f, 0x4f, 0x4f, 0x4f, 0x44, 0x44, 0x4f, - 0xff, 0x4f, 0x44, 0xff, 0xf4, 0xf4, 0x49, 0x9c, - 0x2e, 0xee, 0xee, 0xee, 0xee, 0xa9, 0x65, 0x8a, - 0x1a, 0xaa, 0x37, 0x72, 0x27, 0x37, 0x88, 0x88, - 0x11, 0x17, 0x68, 0x66, 0x67, 0x10, 0x9d, 0xd0, - 0x84, 0x44, 0xff, 0x4f, 0x4f, 0x44, 0xf4, 0x4f, - 0xff, 0x4f, 0x44, 0xff, 0xf4, 0xf4, 0x4f, 0x69, - 0xcc, 0xee, 0xee, 0xee, 0xec, 0x99, 0x88, 0x63, - 0x61, 0x68, 0x61, 0x72, 0x22, 0x7a, 0x68, 0x88, - 0x11, 0x17, 0x88, 0x66, 0x12, 0x1b, 0xdd, 0xdd, - 0x02, 0x44, 0x4f, 0x4f, 0x4f, 0x44, 0x44, 0x4f, - 0xff, 0x4f, 0x44, 0xff, 0xff, 0x4f, 0x4c, 0xc5, - 0x0c, 0xc1, 0x11, 0x1c, 0xc0, 0x26, 0x66, 0x17, - 0x66, 0x88, 0x88, 0x12, 0x22, 0x23, 0xa8, 0x88, - 0x11, 0x13, 0x88, 0x66, 0x17, 0xbb, 0xdd, 0xdd, - 0xd0, 0x8f, 0xff, 0xf4, 0xf4, 0x44, 0xf4, 0x4f, - 0xff, 0x4f, 0x44, 0xf4, 0x4f, 0x44, 0xdd, 0xdd, - 0x00, 0x00, 0x00, 0x05, 0x9d, 0x21, 0x66, 0x27, - 0xa6, 0x65, 0x58, 0x67, 0x22, 0x27, 0x28, 0x88, - 0x11, 0xaa, 0x86, 0x68, 0x1a, 0xbb, 0xdd, 0xdd, - 0xdb, 0x05, 0xf4, 0xf4, 0xf4, 0xf4, 0x44, 0x4f, - 0xff, 0x4f, 0x44, 0xf4, 0xf4, 0xf4, 0xdd, 0xdb, - 0x00, 0x00, 0x00, 0x00, 0xdd, 0xda, 0x66, 0x22, - 0x71, 0x15, 0x55, 0x81, 0x22, 0x22, 0x76, 0x88, - 0x11, 0x31, 0x88, 0x88, 0xab, 0xbd, 0xdd, 0xdd, - 0xdd, 0x00, 0x04, 0x44, 0xff, 0xff, 0x4f, 0x4f, - 0xff, 0x4f, 0x44, 0xf4, 0xf4, 0x44, 0xdd, 0xdb, - 0x00, 0x00, 0x00, 0x0b, 0xdd, 0xda, 0x11, 0x22, - 0x23, 0x68, 0x55, 0x86, 0x22, 0x22, 0x7a, 0x88, - 0x1a, 0x71, 0x88, 0x89, 0xbb, 0xdd, 0xdd, 0xdd, - 0xdd, 0xd0, 0x00, 0x4f, 0x44, 0xff, 0x4f, 0x4f, - 0xff, 0x4f, 0x44, 0xf4, 0xff, 0xe2, 0xdd, 0xdb, - 0x90, 0x00, 0x05, 0xbd, 0xdd, 0xb8, 0x63, 0x22, - 0x27, 0xa6, 0x55, 0x88, 0x77, 0x22, 0x22, 0x88, - 0x1a, 0x28, 0xbd, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdb, 0x00, 0x07, 0x44, 0x4f, 0x4f, 0x4f, - 0xff, 0x4f, 0x44, 0x4f, 0x4f, 0x22, 0xdd, 0xdb, - 0xbb, 0x9b, 0xbb, 0xbd, 0xdd, 0xd5, 0x86, 0x22, - 0x22, 0x77, 0x85, 0x88, 0x17, 0x22, 0x22, 0x88, - 0xaa, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0x00, 0x00, 0x54, 0x4f, 0x4f, 0x4f, - 0xff, 0x4f, 0x44, 0xf4, 0x44, 0x22, 0xbd, 0xdd, - 0xbb, 0xbb, 0xbb, 0xdd, 0xdd, 0xdd, 0x88, 0x72, - 0x27, 0x22, 0x88, 0x88, 0x67, 0x72, 0x22, 0x18, - 0x33, 0x2d, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xd0, 0x00, 0x05, 0x4f, 0x4f, 0x4f, - 0xff, 0x4f, 0x44, 0x44, 0x4f, 0x22, 0xbd, 0xdd, - 0xdb, 0xbb, 0xdd, 0xdd, 0xdd, 0xdd, 0x88, 0x17, - 0x27, 0x72, 0x68, 0x88, 0x87, 0x32, 0x22, 0x36, - 0x37, 0x2d, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xd5, 0x00, 0x00, 0x4f, 0x4f, 0x4f, - 0xff, 0xf4, 0xf4, 0xf4, 0xf4, 0x22, 0xbb, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd8, 0x67, - 0x72, 0x77, 0x38, 0x88, 0x83, 0x37, 0x22, 0x26, - 0x72, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0x00, 0x00, 0x4f, 0x4f, 0x4f, - 0xff, 0xf4, 0xf4, 0xf4, 0x44, 0x25, 0xbb, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd3, - 0x32, 0x73, 0x76, 0x88, 0x81, 0x33, 0x22, 0x2a, - 0x22, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xb0, 0x54, 0x4f, 0x4f, 0x4f, - 0xff, 0xf4, 0xf4, 0xff, 0x44, 0x00, 0xbb, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xa7, 0x73, 0x26, 0x88, 0x86, 0x7a, 0x72, 0x27, - 0x22, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdb, 0x44, 0xff, 0x4f, 0x4f, - 0xff, 0xf4, 0xf4, 0x44, 0x40, 0x05, 0xbb, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0x13, 0x23, 0x21, 0x68, 0x86, 0x17, 0x72, 0x22, - 0x22, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdb, 0x44, 0x4f, 0x4f, 0x4f, - 0xff, 0xff, 0x44, 0x42, 0x00, 0x05, 0xbd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0x87, 0x27, 0x27, 0x16, 0x66, 0x67, 0x22, 0x22, - 0x72, 0x7b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0x94, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x44, 0x00, 0x00, 0x05, 0xbb, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xb8, - 0x86, 0x22, 0x22, 0x7a, 0x68, 0x81, 0x22, 0x22, - 0x37, 0x7b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdb, 0xb5, 0x44, 0x44, 0x44, - 0x44, 0x47, 0x00, 0x00, 0x00, 0x05, 0xbd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd8, 0x68, - 0x58, 0x72, 0x22, 0x27, 0x18, 0x86, 0x72, 0x22, - 0x1a, 0xbb, 0xbd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdb, 0xb5, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xbb, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xb9, 0x18, 0x85, - 0x58, 0x12, 0x22, 0x36, 0x18, 0x88, 0x32, 0x22, - 0x61, 0x3b, 0xbb, 0xbb, 0xbd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdb, 0xb9, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xbb, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xb9, 0x7a, 0x68, 0x85, - 0x88, 0x62, 0x27, 0x16, 0x18, 0x88, 0x12, 0x27, - 0x86, 0x18, 0x9b, 0xbb, 0xbb, 0xbb, 0xbb, 0xbd, - 0xdd, 0xdd, 0xdd, 0xbb, 0xb5, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xbb, 0xbd, - 0xdd, 0xdd, 0xdb, 0xbb, 0x87, 0x31, 0x68, 0x65, - 0x88, 0x82, 0x23, 0x16, 0x18, 0x88, 0x12, 0x23, - 0x88, 0x67, 0x27, 0xa8, 0x9b, 0xbb, 0xbb, 0xbb, - 0xbd, 0xdd, 0xbb, 0xbb, 0x95, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x9b, 0xbb, - 0xbb, 0xbb, 0xbb, 0x96, 0x87, 0x16, 0x68, 0x18, - 0x88, 0x62, 0x31, 0x66, 0x18, 0x88, 0x62, 0x73, - 0x88, 0x63, 0x27, 0x33, 0x65, 0x55, 0x99, 0x9b, - 0xbb, 0xbb, 0xbb, 0x99, 0x55, 0x0a, 0xa1, 0x86, - 0x81, 0x68, 0x88, 0x55, 0x58, 0x85, 0x9b, 0xbb, - 0xbb, 0xbb, 0x95, 0x88, 0x83, 0x66, 0x66, 0x18, - 0x66, 0x82, 0xa1, 0x66, 0x18, 0x88, 0x62, 0x33, - 0x88, 0x81, 0x27, 0x7a, 0x18, 0x58, 0x86, 0x85, - 0x99, 0x99, 0x99, 0x95, 0x53, 0x2a, 0xaa, 0x88, - 0x67, 0x31, 0x68, 0x55, 0x58, 0x85, 0x59, 0xbb, - 0xbb, 0xb9, 0x58, 0x68, 0x83, 0x66, 0x61, 0x16, - 0x66, 0x62, 0x16, 0x66, 0x68, 0x88, 0x62, 0xaa, - 0x88, 0x86, 0x27, 0x77, 0x78, 0x55, 0x88, 0x22, - 0x25, 0x55, 0x95, 0x55, 0x6a, 0xa2, 0x2a, 0x88, - 0x62, 0x27, 0x37, 0x38, 0x88, 0x87, 0x55, 0x59, - 0x95, 0x58, 0x16, 0x88, 0x8a, 0x66, 0x63, 0x68, - 0x86, 0x67, 0x66, 0x66, 0x68, 0x88, 0x12, 0x11, - 0x88, 0x88, 0x72, 0x77, 0x78, 0x85, 0x58, 0x17, - 0x23, 0x32, 0x55, 0x55, 0x81, 0x13, 0x73, 0x66, - 0x62, 0x7a, 0xaa, 0x38, 0x88, 0x58, 0x27, 0x55, - 0x58, 0x32, 0x38, 0x88, 0x81, 0x66, 0xa2, 0x88, - 0x86, 0x61, 0x66, 0x61, 0x66, 0x68, 0x13, 0x11, - 0x88, 0x88, 0x12, 0x22, 0x71, 0x85, 0x58, 0x62, - 0x23, 0xa2, 0x68, 0x88, 0x81, 0x66, 0x88, 0x88, - 0x63, 0x2a, 0xaa, 0x28, 0x88, 0x55, 0x86, 0x61, - 0x66, 0x66, 0x68, 0x88, 0x66, 0x66, 0x77, 0x88, - 0x68, 0x16, 0x66, 0x62, 0x66, 0x68, 0xa1, 0x61, - 0x88, 0x88, 0x62, 0x22, 0x22, 0x85, 0x55, 0x83, - 0x72, 0x37, 0xa8, 0x88, 0x61, 0x66, 0x85, 0x55, - 0x86, 0x23, 0xaa, 0x71, 0x88, 0x85, 0x88, 0x66, - 0x88, 0x86, 0x88, 0x88, 0x16, 0x61, 0x21, 0x88, - 0x66, 0xa6, 0x86, 0x17, 0x66, 0x66, 0x31, 0x61, - 0x88, 0x88, 0x87, 0x72, 0x22, 0x68, 0x55, 0x86, - 0x77, 0x77, 0x36, 0x88, 0x13, 0x68, 0x85, 0x55, - 0x58, 0x12, 0x73, 0x72, 0x76, 0x88, 0x88, 0x68, - 0x88, 0x88, 0x88, 0x66, 0x36, 0x63, 0x26, 0x86, - 0x86, 0x36, 0x86, 0x11, 0x66, 0x66, 0x76, 0x61, - 0x88, 0x88, 0x81, 0x22, 0x22, 0x38, 0x85, 0x58, - 0x37, 0x22, 0x21, 0x68, 0xa2, 0x31, 0x68, 0x55, - 0x55, 0x81, 0x22, 0x22, 0xa8, 0x88, 0x88, 0x68, - 0x86, 0x88, 0x68, 0x81, 0x36, 0x17, 0x21, 0x68, - 0x86, 0x16, 0x66, 0x26, 0x66, 0x61, 0x36, 0x66, - 0x68, 0x88, 0x86, 0x27, 0x22, 0x28, 0x88, 0x88, - 0x17, 0x72, 0x2a, 0x66, 0xa2, 0x22, 0x36, 0x55, - 0x55, 0x58, 0x37, 0x3a, 0x16, 0x66, 0x66, 0x66, - 0x66, 0x18, 0x88, 0x67, 0x16, 0x12, 0x71, 0x68, - 0x81, 0x68, 0x61, 0x76, 0x66, 0x6a, 0x16, 0x66, - 0x88, 0x88, 0x86, 0x77, 0x22, 0x26, 0x88, 0x88, - 0x13, 0x37, 0x71, 0x66, 0xa2, 0x33, 0x2a, 0x85, - 0x55, 0x55, 0x17, 0x73, 0x16, 0x66, 0x66, 0x68, - 0x63, 0x88, 0x88, 0xa2, 0x66, 0xa2, 0xa6, 0x88, - 0x61, 0x68, 0x6a, 0x76, 0x66, 0x6a, 0x66, 0x6a -}; +/* prototypes only */ +extern unsigned char linux_logo_red[]; +extern unsigned char linux_logo_green[]; +extern unsigned char linux_logo_blue[]; +extern unsigned char linux_logo[]; +extern unsigned char linux_logo_bw[]; +extern unsigned char linux_logo16[]; + +#endif /* !INCLUDE_LINUX_LOGO_DATA */ -#endif diff -u --recursive --new-file v2.4.5/linux/include/linux/mii.h linux/include/linux/mii.h --- v2.4.5/linux/include/linux/mii.h Wed May 16 10:25:38 2001 +++ linux/include/linux/mii.h Tue Jul 3 15:46:16 2001 @@ -8,6 +8,8 @@ #ifndef __LINUX_MII_H__ #define __LINUX_MII_H__ +#include + /* Inside the Happy Meal transceiver is the physical layer, they use an * implementations for National Semiconductor, part number DP83840VCE. * You can retrieve the data sheets and programming docs for this beast @@ -125,6 +127,16 @@ #define CSCONFIG_TCDISABLE 0x2000 /* Disable timeout counter */ #define CSCONFIG_RESV4 0x4000 /* Unused... */ #define CSCONFIG_NDISABLE 0x8000 /* Disable NRZI */ + + +/* This structure is used in all SIOCxMIIxxx ioctl calls */ +struct mii_ioctl_data { + u16 phy_id; + u16 reg_num; + u16 val_in; + u16 val_out; +}; + /** * mii_nway_result diff -u --recursive --new-file v2.4.5/linux/include/linux/mm.h linux/include/linux/mm.h --- v2.4.5/linux/include/linux/mm.h Fri May 25 18:01:28 2001 +++ linux/include/linux/mm.h Tue Jul 3 15:42:55 2001 @@ -10,6 +10,7 @@ #include #include #include +#include extern unsigned long max_mapnr; extern unsigned long num_physpages; @@ -39,32 +40,37 @@ * library, the executable area etc). */ struct vm_area_struct { - struct mm_struct * vm_mm; /* VM area parameters */ - unsigned long vm_start; - unsigned long vm_end; + struct mm_struct * vm_mm; /* The address space we belong to. */ + unsigned long vm_start; /* Our start address within vm_mm. */ + unsigned long vm_end; /* Our end address within vm_mm. */ /* linked list of VM areas per task, sorted by address */ struct vm_area_struct *vm_next; - pgprot_t vm_page_prot; - unsigned long vm_flags; + pgprot_t vm_page_prot; /* Access permissions of this VMA. */ + unsigned long vm_flags; /* Flags, listed below. */ /* AVL tree of VM areas per task, sorted by address */ short vm_avl_height; struct vm_area_struct * vm_avl_left; struct vm_area_struct * vm_avl_right; - /* For areas with an address space and backing store, + /* + * For areas with an address space and backing store, * one of the address_space->i_mmap{,shared} lists, * for shm areas, the list of attaches, otherwise unused. */ struct vm_area_struct *vm_next_share; struct vm_area_struct **vm_pprev_share; + /* Function pointers to deal with this struct. */ struct vm_operations_struct * vm_ops; - unsigned long vm_pgoff; /* offset in PAGE_SIZE units, *not* PAGE_CACHE_SIZE */ - struct file * vm_file; - unsigned long vm_raend; + + /* Information about our backing store: */ + unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE + units, *not* PAGE_CACHE_SIZE */ + struct file * vm_file; /* File we map to (can be NULL). */ + unsigned long vm_raend; /* XXX: put full readahead info here. */ void * vm_private_data; /* was vm_pte (shared mem) */ }; @@ -90,6 +96,7 @@ #define VM_LOCKED 0x00002000 #define VM_IO 0x00004000 /* Memory mapped I/O or similar */ + /* Used by sys_madvise() */ #define VM_SEQ_READ 0x00008000 /* App will access data sequentially */ #define VM_RAND_READ 0x00010000 /* App will not benefit from clustered reads */ @@ -124,37 +131,144 @@ }; /* + * Each physical page in the system has a struct page associated with + * it to keep track of whatever it is we are using the page for at the + * moment. Note that we have no way to track which tasks are using + * a page. + * * Try to keep the most commonly accessed fields in single cache lines * here (16 bytes or greater). This ordering should be particularly * beneficial on 32-bit processors. * * The first line is data used in page cache lookup, the second line * is used for linear searches (eg. clock algorithm scans). + * + * TODO: make this structure smaller, it could be as small as 32 bytes. */ typedef struct page { - struct list_head list; - struct address_space *mapping; - unsigned long index; - struct page *next_hash; - atomic_t count; - unsigned long flags; /* atomic flags, some possibly updated asynchronously */ - struct list_head lru; - unsigned long age; - wait_queue_head_t wait; - struct page **pprev_hash; - struct buffer_head * buffers; - void *virtual; /* non-NULL if kmapped */ - struct zone_struct *zone; + struct list_head list; /* ->mapping has some page lists. */ + struct address_space *mapping; /* The inode (or ...) we belong to. */ + unsigned long index; /* Our offset within mapping. */ + struct page *next_hash; /* Next page sharing our hash bucket in + the pagecache hash table. */ + atomic_t count; /* Usage count, see below. */ + unsigned long flags; /* atomic flags, some possibly + updated asynchronously */ + struct list_head lru; /* Pageout list, eg. active_list; + protected by pagemap_lru_lock !! */ + unsigned long age; /* Page aging counter. */ + wait_queue_head_t wait; /* Page locked? Stand in line... */ + struct page **pprev_hash; /* Complement to *next_hash. */ + struct buffer_head * buffers; /* Buffer maps us to a disk block. */ + void *virtual; /* Kernel virtual address (NULL if + not kmapped, ie. highmem) */ + struct zone_struct *zone; /* Memory zone we are in. */ } mem_map_t; +/* + * Methods to modify the page usage count. + * + * What counts for a page usage: + * - cache mapping (page->mapping) + * - disk mapping (page->buffers) + * - page mapped in a task's page tables, each mapping + * is counted separately + * + * Also, many kernel routines increase the page count before a critical + * routine so they can be sure the page doesn't go away from under them. + */ #define get_page(p) atomic_inc(&(p)->count) #define put_page(p) __free_page(p) #define put_page_testzero(p) atomic_dec_and_test(&(p)->count) #define page_count(p) atomic_read(&(p)->count) #define set_page_count(p,v) atomic_set(&(p)->count, v) -/* Page flag bit values */ -#define PG_locked 0 +/* + * Various page->flags bits: + * + * PG_reserved is set for special pages, which can never be swapped + * out. Some of them might not even exist (eg. empty_bad_page)... + * + * Multiple processes may "see" the same page. E.g. for untouched + * mappings of /dev/null, all processes see the same page full of + * zeroes, and text pages of executables and shared libraries have + * only one copy in memory, at most, normally. + * + * For the non-reserved pages, page->count denotes a reference count. + * page->count == 0 means the page is free. + * page->count == 1 means the page is used for exactly one purpose + * (e.g. a private data page of one process). + * + * A page may be used for kmalloc() or anyone else who does a + * __get_free_page(). In this case the page->count is at least 1, and + * all other fields are unused but should be 0 or NULL. The + * management of this page is the responsibility of the one who uses + * it. + * + * The other pages (we may call them "process pages") are completely + * managed by the Linux memory manager: I/O, buffers, swapping etc. + * The following discussion applies only to them. + * + * A page may belong to an inode's memory mapping. In this case, + * page->mapping is the pointer to the inode, and page->offset is the + * file offset of the page (not necessarily a multiple of PAGE_SIZE). + * + * A page may have buffers allocated to it. In this case, + * page->buffers is a circular list of these buffer heads. Else, + * page->buffers == NULL. + * + * For pages belonging to inodes, the page->count is the number of + * attaches, plus 1 if buffers are allocated to the page, plus one + * for the page cache itself. + * + * All pages belonging to an inode are in these doubly linked lists: + * mapping->clean_pages, mapping->dirty_pages and mapping->locked_pages; + * using the page->list list_head. These fields are also used for + * freelist managemet (when page->count==0). + * + * There is also a hash table mapping (inode,offset) to the page + * in memory if present. The lists for this hash table use the fields + * page->next_hash and page->pprev_hash. + * + * All process pages can do I/O: + * - inode pages may need to be read from disk, + * - inode pages which have been modified and are MAP_SHARED may need + * to be written to disk, + * - private pages which have been modified may need to be swapped out + * to swap space and (later) to be read back into memory. + * During disk I/O, PG_locked is used. This bit is set before I/O + * and reset when I/O completes. page->wait is a wait queue of all + * tasks waiting for the I/O on this page to complete. + * PG_uptodate tells whether the page's contents is valid. + * When a read completes, the page becomes uptodate, unless a disk I/O + * error happened. + * + * For choosing which pages to swap out, inode pages carry a + * PG_referenced bit, which is set any time the system accesses + * that page through the (inode,offset) hash table. This referenced + * bit, together with the referenced bit in the page tables, is used + * to manipulate page->age and move the page across the active, + * inactive_dirty and inactive_clean lists. + * + * Note that the referenced bit, the page->lru list_head and the + * active, inactive_dirty and inactive_clean lists are protected by + * the pagemap_lru_lock, and *NOT* by the usual PG_locked bit! + * + * PG_skip is used on sparc/sparc64 architectures to "skip" certain + * parts of the address space. + * + * PG_error is set to indicate that an I/O error occurred on this page. + * + * PG_arch_1 is an architecture specific page state bit. The generic + * code guarentees that this bit is cleared for a page when it first + * is entered into the page cache. + * + * PG_highmem pages are not permanently mapped into the kernel virtual + * address space, they need to be kmapped separately for doing IO on + * the pages. The struct page (these bits with information) are always + * mapped into kernel address space... + */ +#define PG_locked 0 /* Page is locked. Don't touch. */ #define PG_error 1 #define PG_referenced 2 #define PG_uptodate 3 @@ -167,6 +281,7 @@ #define PG_skip 10 #define PG_inactive_clean 11 #define PG_highmem 12 +#define PG_checked 13 /* kill me in 2.5.. */ /* bits 21-29 unused */ #define PG_arch_1 30 #define PG_reserved 31 @@ -181,6 +296,8 @@ #define PageLocked(page) test_bit(PG_locked, &(page)->flags) #define LockPage(page) set_bit(PG_locked, &(page)->flags) #define TryLockPage(page) test_and_set_bit(PG_locked, &(page)->flags) +#define PageChecked(page) test_bit(PG_checked, &(page)->flags) +#define SetPageChecked(page) set_bit(PG_checked, &(page)->flags) extern void __set_page_dirty(struct page *); @@ -254,81 +371,7 @@ #define NOPAGE_SIGBUS (NULL) #define NOPAGE_OOM ((struct page *) (-1)) - -/* - * Various page->flags bits: - * - * PG_reserved is set for a page which must never be accessed (which - * may not even be present). - * - * PG_DMA has been removed, page->zone now tells exactly wether the - * page is suited to do DMAing into. - * - * Multiple processes may "see" the same page. E.g. for untouched - * mappings of /dev/null, all processes see the same page full of - * zeroes, and text pages of executables and shared libraries have - * only one copy in memory, at most, normally. - * - * For the non-reserved pages, page->count denotes a reference count. - * page->count == 0 means the page is free. - * page->count == 1 means the page is used for exactly one purpose - * (e.g. a private data page of one process). - * - * A page may be used for kmalloc() or anyone else who does a - * __get_free_page(). In this case the page->count is at least 1, and - * all other fields are unused but should be 0 or NULL. The - * management of this page is the responsibility of the one who uses - * it. - * - * The other pages (we may call them "process pages") are completely - * managed by the Linux memory manager: I/O, buffers, swapping etc. - * The following discussion applies only to them. - * - * A page may belong to an inode's memory mapping. In this case, - * page->inode is the pointer to the inode, and page->offset is the - * file offset of the page (not necessarily a multiple of PAGE_SIZE). - * - * A page may have buffers allocated to it. In this case, - * page->buffers is a circular list of these buffer heads. Else, - * page->buffers == NULL. - * - * For pages belonging to inodes, the page->count is the number of - * attaches, plus 1 if buffers are allocated to the page. - * - * All pages belonging to an inode make up a doubly linked list - * inode->i_pages, using the fields page->next and page->prev. (These - * fields are also used for freelist management when page->count==0.) - * There is also a hash table mapping (inode,offset) to the page - * in memory if present. The lists for this hash table use the fields - * page->next_hash and page->pprev_hash. - * - * All process pages can do I/O: - * - inode pages may need to be read from disk, - * - inode pages which have been modified and are MAP_SHARED may need - * to be written to disk, - * - private pages which have been modified may need to be swapped out - * to swap space and (later) to be read back into memory. - * During disk I/O, PG_locked is used. This bit is set before I/O - * and reset when I/O completes. page->wait is a wait queue of all - * tasks waiting for the I/O on this page to complete. - * PG_uptodate tells whether the page's contents is valid. - * When a read completes, the page becomes uptodate, unless a disk I/O - * error happened. - * - * For choosing which pages to swap out, inode pages carry a - * PG_referenced bit, which is set any time the system accesses - * that page through the (inode,offset) hash table. - * - * PG_skip is used on sparc/sparc64 architectures to "skip" certain - * parts of the address space. - * - * PG_error is set to indicate that an I/O error occurred on this page. - * - * PG_arch_1 is an architecture specific page state bit. The generic - * code guarentees that this bit is cleared for a page when it first - * is entered into the page cache. - */ - +/* The array of struct pages */ extern mem_map_t * mem_map; /* @@ -337,10 +380,10 @@ * can allocate highmem pages, the *get*page*() variants return * virtual kernel addresses to the allocated page(s). */ -extern struct page * FASTCALL(__alloc_pages(zonelist_t *zonelist, unsigned long order)); +extern struct page * FASTCALL(_alloc_pages(unsigned int gfp_mask, unsigned long order)); +extern struct page * FASTCALL(__alloc_pages(unsigned int gfp_mask, unsigned long order, zonelist_t *zonelist)); extern struct page * alloc_pages_node(int nid, int gfp_mask, unsigned long order); -#ifndef CONFIG_DISCONTIGMEM static inline struct page * alloc_pages(int gfp_mask, unsigned long order) { /* @@ -348,11 +391,8 @@ */ if (order >= MAX_ORDER) return NULL; - return __alloc_pages(contig_page_data.node_zonelists+(gfp_mask), order); + return _alloc_pages(gfp_mask, order); } -#else /* !CONFIG_DISCONTIGMEM */ -extern struct page * alloc_pages(int gfp_mask, unsigned long order); -#endif /* !CONFIG_DISCONTIGMEM */ #define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0) @@ -427,6 +467,23 @@ extern void si_meminfo(struct sysinfo * val); extern void swapin_readahead(swp_entry_t); +/* + * Work out if there are any other processes sharing this + * swap cache page. Never mind the buffers. + */ +static inline int exclusive_swap_page(struct page *page) +{ + unsigned int count; + + if (!PageLocked(page)) + BUG(); + if (!PageSwapCache(page)) + return 0; + count = page_count(page) - !!page->buffers; /* 2: us + swap cache */ + count += swap_count(page); /* +1: just swap cache */ + return count == 3; /* =3: total */ +} + /* mmap.c */ extern void lock_vma_mappings(struct vm_area_struct *); extern void unlock_vma_mappings(struct vm_area_struct *); @@ -471,24 +528,24 @@ /* * GFP bitmasks.. */ -#define __GFP_WAIT 0x01 -#define __GFP_HIGH 0x02 -#define __GFP_IO 0x04 -#define __GFP_DMA 0x08 -#ifdef CONFIG_HIGHMEM -#define __GFP_HIGHMEM 0x10 -#else -#define __GFP_HIGHMEM 0x0 /* noop */ -#endif +/* Zone modifiers in GFP_ZONEMASK (see linux/mmzone.h - low four bits) */ +#define __GFP_DMA 0x01 +#define __GFP_HIGHMEM 0x02 + +/* Action modifiers - doesn't change the zoning */ +#define __GFP_WAIT 0x10 /* Can wait and reschedule? */ +#define __GFP_HIGH 0x20 /* Should access emergency pools? */ +#define __GFP_IO 0x40 /* Can start physical IO? */ +#define __GFP_FS 0x80 /* Can call down to low-level FS? */ - -#define GFP_BUFFER (__GFP_HIGH | __GFP_WAIT) +#define GFP_NOIO (__GFP_HIGH | __GFP_WAIT) +#define GFP_NOFS (__GFP_HIGH | __GFP_WAIT | __GFP_IO) #define GFP_ATOMIC (__GFP_HIGH) -#define GFP_USER ( __GFP_WAIT | __GFP_IO) -#define GFP_HIGHUSER ( __GFP_WAIT | __GFP_IO | __GFP_HIGHMEM) -#define GFP_KERNEL (__GFP_HIGH | __GFP_WAIT | __GFP_IO) -#define GFP_NFS (__GFP_HIGH | __GFP_WAIT | __GFP_IO) -#define GFP_KSWAPD ( __GFP_IO) +#define GFP_USER ( __GFP_WAIT | __GFP_IO | __GFP_FS) +#define GFP_HIGHUSER ( __GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HIGHMEM) +#define GFP_KERNEL (__GFP_HIGH | __GFP_WAIT | __GFP_IO | __GFP_FS) +#define GFP_NFS (__GFP_HIGH | __GFP_WAIT | __GFP_IO | __GFP_FS) +#define GFP_KSWAPD ( __GFP_IO | __GFP_FS) /* Flag - indicates that the buffer will be suitable for DMA. Ignored on some platforms, used as appropriate on others */ @@ -533,11 +590,6 @@ } extern struct vm_area_struct *find_extend_vma(struct mm_struct *mm, unsigned long addr); - -#define buffer_under_min() (atomic_read(&buffermem_pages) * 100 < \ - buffer_mem.min_percent * num_physpages) -#define pgcache_under_min() (atomic_read(&page_cache_size) * 100 < \ - page_cache.min_percent * num_physpages) #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.4.5/linux/include/linux/mmzone.h linux/include/linux/mmzone.h --- v2.4.5/linux/include/linux/mmzone.h Fri May 25 18:01:27 2001 +++ linux/include/linux/mmzone.h Tue Jul 3 15:42:55 2001 @@ -78,10 +78,9 @@ */ typedef struct zonelist_struct { zone_t * zones [MAX_NR_ZONES+1]; // NULL delimited - int gfp_mask; } zonelist_t; -#define NR_GFPINDEX 0x20 +#define GFP_ZONEMASK 0x0f /* * The pg_data_t structure is used in machines with CONFIG_DISCONTIGMEM @@ -97,7 +96,7 @@ struct bootmem_data; typedef struct pglist_data { zone_t node_zones[MAX_NR_ZONES]; - zonelist_t node_zonelists[NR_GFPINDEX]; + zonelist_t node_zonelists[GFP_ZONEMASK+1]; struct page *node_mem_map; unsigned long *valid_addr_bitmap; struct bootmem_data *bdata; diff -u --recursive --new-file v2.4.5/linux/include/linux/mount.h linux/include/linux/mount.h --- v2.4.5/linux/include/linux/mount.h Fri May 25 12:36:42 2001 +++ linux/include/linux/mount.h Mon Jun 11 19:15:27 2001 @@ -14,12 +14,11 @@ struct vfsmount { + struct list_head mnt_hash; + struct vfsmount *mnt_parent; /* fs we are mounted on */ struct dentry *mnt_mountpoint; /* dentry of mountpoint */ struct dentry *mnt_root; /* root of the mounted tree */ - struct vfsmount *mnt_parent; /* fs we are mounted on */ struct list_head mnt_instances; /* other vfsmounts of the same fs */ - struct list_head mnt_clash; /* those who are mounted on (other */ - /* instances) of the same dentry */ struct super_block *mnt_sb; /* pointer to superblock */ struct list_head mnt_mounts; /* list of children, anchored here */ struct list_head mnt_child; /* and going through their mnt_child */ diff -u --recursive --new-file v2.4.5/linux/include/linux/mtd/cfi.h linux/include/linux/mtd/cfi.h --- v2.4.5/linux/include/linux/mtd/cfi.h Mon Dec 11 13:16:46 2000 +++ linux/include/linux/mtd/cfi.h Tue Jun 12 10:30:27 2001 @@ -1,14 +1,160 @@ /* Common Flash Interface structures * See http://support.intel.com/design/flash/technote/index.htm - * $Id: cfi.h,v 1.6 2000/07/03 13:29:16 dwmw2 Exp $ + * $Id: cfi.h,v 1.21 2001/06/03 01:32:57 nico Exp $ */ #ifndef __MTD_CFI_H__ #define __MTD_CFI_H__ +#include +#include #include #include +#include + +/* + * You can optimize the code size and performance by defining only + * the geometry(ies) available on your hardware. + * CFIDEV_INTERLEAVE_n, where represents the interleave (number of chips to fill the bus width) + * CFIDEV_BUSWIDTH_n, where n is the bus width in bytes (1, 2 or 4 bytes) + * + * By default, all (known) geometries are supported. + */ + +#ifndef CONFIG_MTD_CFI_GEOMETRY + +#define CFIDEV_INTERLEAVE_1 (1) +#define CFIDEV_INTERLEAVE_2 (2) +#define CFIDEV_INTERLEAVE_4 (4) + +#define CFIDEV_BUSWIDTH_1 (1) +#define CFIDEV_BUSWIDTH_2 (2) +#define CFIDEV_BUSWIDTH_4 (4) + +#else + +#ifdef CONFIG_MTD_CFI_I1 +#define CFIDEV_INTERLEAVE_1 (1) +#endif +#ifdef CONFIG_MTD_CFI_I2 +#define CFIDEV_INTERLEAVE_2 (2) +#endif +#ifdef CONFIG_MTD_CFI_I4 +#define CFIDEV_INTERLEAVE_4 (4) +#endif + +#ifdef CONFIG_MTD_CFI_B1 +#define CFIDEV_BUSWIDTH_1 (1) +#endif +#ifdef CONFIG_MTD_CFI_B2 +#define CFIDEV_BUSWIDTH_2 (2) +#endif +#ifdef CONFIG_MTD_CFI_B4 +#define CFIDEV_BUSWIDTH_4 (4) +#endif + +#endif + +/* + * The following macros are used to select the code to execute: + * cfi_buswidth_is_*() + * cfi_interleave_is_*() + * [where * is either 1, 2 or 4] + * Those macros should be used with 'if' statements. If only one of few + * geometry arrangements are selected, they expand to constants thus allowing + * the compiler (most of them being 0) to optimize away all the unneeded code, + * while still validating the syntax (which is not possible with embedded + * #if ... #endif constructs). + */ + +#ifdef CFIDEV_INTERLEAVE_1 +# ifdef CFIDEV_INTERLEAVE +# undef CFIDEV_INTERLEAVE +# define CFIDEV_INTERLEAVE (cfi->interleave) +# else +# define CFIDEV_INTERLEAVE CFIDEV_INTERLEAVE_1 +# endif +# define cfi_interleave_is_1() (CFIDEV_INTERLEAVE == CFIDEV_INTERLEAVE_1) +#else +# define cfi_interleave_is_1() (0) +#endif + +#ifdef CFIDEV_INTERLEAVE_2 +# ifdef CFIDEV_INTERLEAVE +# undef CFIDEV_INTERLEAVE +# define CFIDEV_INTERLEAVE (cfi->interleave) +# else +# define CFIDEV_INTERLEAVE CFIDEV_INTERLEAVE_2 +# endif +# define cfi_interleave_is_2() (CFIDEV_INTERLEAVE == CFIDEV_INTERLEAVE_2) +#else +# define cfi_interleave_is_2() (0) +#endif + +#ifdef CFIDEV_INTERLEAVE_4 +# ifdef CFIDEV_INTERLEAVE +# undef CFIDEV_INTERLEAVE +# define CFIDEV_INTERLEAVE (cfi->interleave) +# else +# define CFIDEV_INTERLEAVE CFIDEV_INTERLEAVE_4 +# endif +# define cfi_interleave_is_4() (CFIDEV_INTERLEAVE == CFIDEV_INTERLEAVE_4) +#else +# define cfi_interleave_is_4() (0) +#endif + +#ifndef CFIDEV_INTERLEAVE +#error You must define at least one interleave to support! +#endif + +#ifdef CFIDEV_BUSWIDTH_1 +# ifdef CFIDEV_BUSWIDTH +# undef CFIDEV_BUSWIDTH +# define CFIDEV_BUSWIDTH (map->buswidth) +# else +# define CFIDEV_BUSWIDTH CFIDEV_BUSWIDTH_1 +# endif +# define cfi_buswidth_is_1() (CFIDEV_BUSWIDTH == CFIDEV_BUSWIDTH_1) +#else +# define cfi_buswidth_is_1() (0) +#endif + +#ifdef CFIDEV_BUSWIDTH_2 +# ifdef CFIDEV_BUSWIDTH +# undef CFIDEV_BUSWIDTH +# define CFIDEV_BUSWIDTH (map->buswidth) +# else +# define CFIDEV_BUSWIDTH CFIDEV_BUSWIDTH_2 +# endif +# define cfi_buswidth_is_2() (CFIDEV_BUSWIDTH == CFIDEV_BUSWIDTH_2) +#else +# define cfi_buswidth_is_2() (0) +#endif + +#ifdef CFIDEV_BUSWIDTH_4 +# ifdef CFIDEV_BUSWIDTH +# undef CFIDEV_BUSWIDTH +# define CFIDEV_BUSWIDTH (map->buswidth) +# else +# define CFIDEV_BUSWIDTH CFIDEV_BUSWIDTH_4 +# endif +# define cfi_buswidth_is_4() (CFIDEV_BUSWIDTH == CFIDEV_BUSWIDTH_4) +#else +# define cfi_buswidth_is_4() (0) +#endif + +#ifndef CFIDEV_BUSWIDTH +#error You must define at least one bus width to support! +#endif + +/* NB: these values must represents the number of bytes needed to meet the + * device type (x8, x16, x32). Eg. a 32 bit device is 4 x 8 bytes. + * These numbers are used in calculations. + */ +#define CFI_DEVICETYPE_X8 (8 / 8) +#define CFI_DEVICETYPE_X16 (16 / 8) +#define CFI_DEVICETYPE_X32 (32 / 8) /* NB: We keep these structures in memory in HOST byteorder, except * where individually noted. @@ -37,7 +183,7 @@ __u16 InterfaceDesc; __u16 MaxBufWriteSize; __u8 NumEraseRegions; - __u32 EraseRegionInfo[1]; /* Not host ordered */ + __u32 EraseRegionInfo[0]; /* Not host ordered */ } __attribute__((packed)); /* Extended Query Structure for both PRI and ALT */ @@ -82,20 +228,164 @@ #define P_ID_RESERVED 65535 +#define CFI_MODE_CFI 0 +#define CFI_MODE_JEDEC 1 + struct cfi_private { __u16 cmdset; void *cmdset_priv; int interleave; + int device_type; + int cfi_mode; /* Are we a JEDEC device pretending to be CFI? */ + int addr_unlock1; + int addr_unlock2; + int fast_prog; struct mtd_info *(*cmdset_setup)(struct map_info *); - struct cfi_ident cfiq; /* For now only one. We insist that all devs + struct cfi_ident *cfiq; /* For now only one. We insist that all devs must be of the same type. */ + __u8 mfr, id; int numchips; unsigned long chipshift; /* Because they're of the same type */ const char *im_name; /* inter_module name for cmdset_setup */ struct flchip chips[0]; /* per-chip data structure for each chip */ - /* do not add extra fields after "chips" */ }; #define MAX_CFI_CHIPS 8 /* Entirely arbitrary to avoid realloc() */ + +/* + * Returns the command address according to the given geometry. + */ +static inline __u32 cfi_build_cmd_addr(__u32 cmd_ofs, int interleave, int type) +{ + return (cmd_ofs * type) * interleave; +} + +/* + * Transforms the CFI command for the given geometry (bus width & interleave. + */ +static inline __u32 cfi_build_cmd(u_char cmd, struct map_info *map, struct cfi_private *cfi) +{ + __u32 val = 0; + + if (cfi_buswidth_is_1()) { + /* 1 x8 device */ + val = cmd; + } else if (cfi_buswidth_is_2()) { + if (cfi_interleave_is_1()) { + /* 1 x16 device in x16 mode */ + val = cpu_to_cfi16(cmd); + } else if (cfi_interleave_is_2()) { + /* 2 (x8, x16 or x32) devices in x8 mode */ + val = cpu_to_cfi16((cmd << 8) | cmd); + } + } else if (cfi_buswidth_is_4()) { + if (cfi_interleave_is_1()) { + /* 1 x32 device in x32 mode */ + val = cpu_to_cfi32(cmd); + } else if (cfi_interleave_is_2()) { + /* 2 x16 device in x16 mode */ + val = cpu_to_cfi32((cmd << 16) | cmd); + } else if (cfi_interleave_is_4()) { + /* 4 (x8, x16 or x32) devices in x8 mode */ + val = (cmd << 16) | cmd; + val = cpu_to_cfi32((val << 8) | val); + } + } + return val; +} +#define CMD(x) cfi_build_cmd((x), map, cfi) + +/* + * Read a value according to the bus width. + */ + +static inline __u32 cfi_read(struct map_info *map, __u32 addr) +{ + if (cfi_buswidth_is_1()) { + return map->read8(map, addr); + } else if (cfi_buswidth_is_2()) { + return map->read16(map, addr); + } else if (cfi_buswidth_is_4()) { + return map->read32(map, addr); + } else { + return 0; + } +} + +/* + * Write a value according to the bus width. + */ + +static inline void cfi_write(struct map_info *map, __u32 val, __u32 addr) +{ + if (cfi_buswidth_is_1()) { + map->write8(map, val, addr); + } else if (cfi_buswidth_is_2()) { + map->write16(map, val, addr); + } else if (cfi_buswidth_is_4()) { + map->write32(map, val, addr); + } +} + +/* + * Sends a CFI command to a bank of flash for the given geometry. + * + * Returns the offset in flash where the command was written. + * If prev_val is non-null, it will be set to the value at the command address, + * before the command was written. + */ +static inline __u32 cfi_send_gen_cmd(u_char cmd, __u32 cmd_addr, __u32 base, + struct map_info *map, struct cfi_private *cfi, + int type, __u32 *prev_val) +{ + __u32 val; + __u32 addr = base + cfi_build_cmd_addr(cmd_addr, CFIDEV_INTERLEAVE, type); + + val = cfi_build_cmd(cmd, map, cfi); + + if (prev_val) + *prev_val = cfi_read(map, addr); + + cfi_write(map, val, addr); + + return addr - base; +} + +static inline __u8 cfi_read_query(struct map_info *map, __u32 addr) +{ + if (cfi_buswidth_is_1()) { + return map->read8(map, addr); + } else if (cfi_buswidth_is_2()) { + return cfi16_to_cpu(map->read16(map, addr)); + } else if (cfi_buswidth_is_4()) { + return cfi32_to_cpu(map->read32(map, addr)); + } else { + return 0; + } +} + +#ifndef min +#define min(x,y) ( (x)<(y)?(x):(y) ) +#endif + +static inline void cfi_udelay(int us) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) + if (current->need_resched) + schedule(); + else +#endif + udelay(us); +} +static inline void cfi_spin_lock(spinlock_t *mutex) +{ + spin_lock_bh(mutex); +} + +static inline void cfi_spin_unlock(spinlock_t *mutex) +{ + spin_unlock_bh(mutex); +} + #endif /* __MTD_CFI_H__ */ diff -u --recursive --new-file v2.4.5/linux/include/linux/mtd/cfi_endian.h linux/include/linux/mtd/cfi_endian.h --- v2.4.5/linux/include/linux/mtd/cfi_endian.h Wed Dec 31 16:00:00 1969 +++ linux/include/linux/mtd/cfi_endian.h Tue Jun 12 10:30:27 2001 @@ -0,0 +1,141 @@ +/* + * $Id: cfi_endian.h,v 1.9 2001/04/23 21:19:11 nico Exp $ + * + * It seems that some helpful people decided to make life easier + * for software engineers who aren't capable of dealing with the + * concept of byteswapping, and advise engineers to swap the bytes + * by wiring the data lines up to flash chips from BE hosts backwards. + * + * So we have ugly stuff here to disable the byteswapping where necessary. + * I'm not going to try to do this dynamically. + * + * At first I thought these guys were on crack, but then I discovered the + * LART. + * + */ + +#include + +#ifndef CONFIG_MTD_CFI_ADV_OPTIONS + +#define CFI_HOST_ENDIAN + +#else + +#ifdef CONFIG_MTD_CFI_NOSWAP +#define CFI_HOST_ENDIAN +#endif + +#ifdef CONFIG_MTD_CFI_LE_BYTE_SWAP +#define CFI_LITTLE_ENDIAN +#endif + +#ifdef CONFIG_MTD_CFI_BE_BYTE_SWAP +#define CFI_BIG_ENDIAN +#endif + +#ifdef CONFIG_MTD_CFI_LART_BIT_SWAP +#define CFI_LART_ENDIAN +#endif + +#endif + +#if defined(CFI_LITTLE_ENDIAN) +#define cpu_to_cfi8(x) (x) +#define cfi8_to_cpu(x) (x) +#define cpu_to_cfi16(x) cpu_to_le16(x) +#define cpu_to_cfi32(x) cpu_to_le32(x) +#define cfi16_to_cpu(x) le16_to_cpu(x) +#define cfi32_to_cpu(x) le32_to_cpu(x) +#elif defined (CFI_BIG_ENDIAN) +#define cpu_to_cfi8(x) (x) +#define cfi8_to_cpu(x) (x) +#define cpu_to_cfi16(x) cpu_to_be16(x) +#define cpu_to_cfi32(x) cpu_to_be32(x) +#define cfi16_to_cpu(x) be16_to_cpu(x) +#define cfi32_to_cpu(x) be32_to_cpu(x) +#elif defined (CFI_HOST_ENDIAN) +#define cpu_to_cfi8(x) (x) +#define cfi8_to_cpu(x) (x) +#define cpu_to_cfi16(x) (x) +#define cpu_to_cfi32(x) (x) +#define cfi16_to_cpu(x) (x) +#define cfi32_to_cpu(x) (x) +#elif defined (CFI_LART_ENDIAN) +/* + Fuck me backwards. The data line mapping on LART is as follows: + + U2 CPU | U3 CPU + 0 20 | 0 12 + 1 22 | 1 14 + 2 19 | 2 11 + 3 17 | 3 9 + 4 24 | 4 0 + 5 26 | 5 2 + 6 31 | 6 7 + 7 29 | 7 5 + 8 21 | 8 13 + 9 23 | 9 15 + 10 18 | 10 10 + 11 16 | 11 8 + 12 25 | 12 1 + 13 27 | 13 3 + 14 30 | 14 6 + 15 28 | 15 4 + + For historical reference: the reason why the LART has this strange + mapping is that the designer of the board wanted address lines to + be as short as possible. Why? Because in that way you don't need + drivers in the address lines so the memory access time can be held + short. -- Erik Mouw +*/ +/* cpu_to_cfi16() and cfi16_to_cpu() are not needed because the LART + * only has 32 bit wide Flash memory. -- Erik + */ +#define cpu_to_cfi16(x) (x) +#define cfi16_to_cpu(x) (x) +static inline __u32 cfi32_to_cpu(__u32 x) +{ + __u32 ret; + + ret = (x & 0x08009000) >> 11; + ret |= (x & 0x00002000) >> 10; + ret |= (x & 0x04004000) >> 8; + ret |= (x & 0x00000010) >> 4; + ret |= (x & 0x91000820) >> 3; + ret |= (x & 0x22080080) >> 2; + ret |= (x & 0x40000400); + ret |= (x & 0x00040040) << 1; + ret |= (x & 0x00110000) << 4; + ret |= (x & 0x00220100) << 5; + ret |= (x & 0x00800208) << 6; + ret |= (x & 0x00400004) << 9; + ret |= (x & 0x00000001) << 12; + ret |= (x & 0x00000002) << 13; + + return ret; +} +static inline __u32 cpu_to_cfi32(__u32 x) +{ + __u32 ret; + + ret = (x & 0x00010012) << 11; + ret |= (x & 0x00000008) << 10; + ret |= (x & 0x00040040) << 8; + ret |= (x & 0x00000001) << 4; + ret |= (x & 0x12200104) << 3; + ret |= (x & 0x08820020) << 2; + ret |= (x & 0x40000400); + ret |= (x & 0x00080080) >> 1; + ret |= (x & 0x01100000) >> 4; + ret |= (x & 0x04402000) >> 5; + ret |= (x & 0x20008200) >> 6; + ret |= (x & 0x80000800) >> 9; + ret |= (x & 0x00001000) >> 12; + ret |= (x & 0x00004000) >> 13; + + return ret; +} +#else +#error No CFI endianness defined +#endif diff -u --recursive --new-file v2.4.5/linux/include/linux/mtd/doc2000.h linux/include/linux/mtd/doc2000.h --- v2.4.5/linux/include/linux/mtd/doc2000.h Mon Dec 11 14:57:58 2000 +++ linux/include/linux/mtd/doc2000.h Tue Jun 12 10:30:27 2001 @@ -2,7 +2,7 @@ /* Linux driver for Disk-On-Chip 2000 */ /* (c) 1999 Machine Vision Holdings, Inc. */ /* Author: David Woodhouse */ -/* $Id: doc2000.h,v 1.12 2000/11/03 12:43:43 dwmw2 Exp $ */ +/* $Id: doc2000.h,v 1.13 2001/05/29 12:03:45 dwmw2 Exp $ */ #ifndef __MTD_DOC2000_H__ #define __MTD_DOC2000_H__ @@ -43,15 +43,19 @@ * On PPC, it's mmap'd and 16-bit wide. * Others use readb/writeb */ -#if defined(__arm__) -#define ReadDOC_(adr, reg) ((unsigned char)(*(__u32 *)(((unsigned long)adr)+(reg<<2)))) -#define WriteDOC_(d, adr, reg) do{ *(__u32 *)(((unsigned long)adr)+(reg<<2)) = (__u32)d} while(0) +#if defined(__arm__) +#define ReadDOC_(adr, reg) ((unsigned char)(*(__u32 *)(((unsigned long)adr)+((reg)<<2)))) +#define WriteDOC_(d, adr, reg) do{ *(__u32 *)(((unsigned long)adr)+((reg)<<2)) = (__u32)d; wmb();} while(0) +#define DOC_IOREMAP_LEN 0x8000 #elif defined(__ppc__) -#define ReadDOC_(adr, reg) ((unsigned char)(*(__u16 *)(((unsigned long)adr)+(reg<<1)))) -#define WriteDOC_(d, adr, reg) do{ *(__u16 *)(((unsigned long)adr)+(reg<<1)) = (__u16)d} while(0) +#define ReadDOC_(adr, reg) ((unsigned char)(*(__u16 *)(((unsigned long)adr)+((reg)<<1)))) +#define WriteDOC_(d, adr, reg) do{ *(__u16 *)(((unsigned long)adr)+((reg)<<1)) = (__u16)d; wmb();} while(0) +#define DOC_IOREMAP_LEN 0x4000 #else -#define ReadDOC_(adr, reg) readb(((unsigned long)adr) + reg) -#define WriteDOC_(d, adr, reg) writeb(d, ((unsigned long)adr) + reg) +#define ReadDOC_(adr, reg) readb(((unsigned long)adr) + (reg)) +#define WriteDOC_(d, adr, reg) writeb(d, ((unsigned long)adr) + (reg)) +#define DOC_IOREMAP_LEN 0x2000 + #endif #if defined(__i386__) diff -u --recursive --new-file v2.4.5/linux/include/linux/mtd/flashchip.h linux/include/linux/mtd/flashchip.h --- v2.4.5/linux/include/linux/mtd/flashchip.h Mon Dec 11 13:16:46 2000 +++ linux/include/linux/mtd/flashchip.h Tue Jun 12 10:30:27 2001 @@ -6,7 +6,7 @@ * * (C) 2000 Red Hat. GPLd. * - * $Id: flashchip.h,v 1.4 2000/07/03 12:58:41 dwmw2 Exp $ + * $Id: flashchip.h,v 1.7 2001/01/18 03:52:36 nico Exp $ * */ @@ -25,12 +25,17 @@ FL_CFI_QUERY, FL_JEDEC_QUERY, FL_ERASING, + FL_ERASE_SUSPENDING, FL_ERASE_SUSPENDED, FL_WRITING, + FL_WRITING_TO_BUFFER, + FL_WRITE_SUSPENDING, FL_WRITE_SUSPENDED, FL_PM_SUSPENDED, FL_SYNCING, FL_UNLOADING, + FL_LOCKING, + FL_UNLOCKING, FL_UNKNOWN } flstate_t; diff -u --recursive --new-file v2.4.5/linux/include/linux/mtd/map.h linux/include/linux/mtd/map.h --- v2.4.5/linux/include/linux/mtd/map.h Fri Feb 9 11:29:44 2001 +++ linux/include/linux/mtd/map.h Tue Jun 12 10:30:27 2001 @@ -1,6 +1,6 @@ /* Overhauled routines for dealing with different mmap regions of flash */ -/* $Id: map.h,v 1.10.2.2 2001/01/09 00:44:51 dwmw2 Exp $ */ +/* $Id: map.h,v 1.24 2001/06/09 19:53:16 dwmw2 Exp $ */ #ifndef __LINUX_MTD_MAP_H__ #define __LINUX_MTD_MAP_H__ @@ -53,47 +53,23 @@ unsigned long map_priv_1; unsigned long map_priv_2; void *fldrv_priv; - void (*fldrv_destroy)(struct mtd_info *); - const char *im_name; + struct mtd_chip_driver *fldrv; }; -#ifdef CONFIG_MODULES -/* - * Probe for the contents of a map device and make an MTD structure - * if anything is recognised. Doesn't register it because the calling - * map driver needs to set the 'module' field first. - */ -static inline struct mtd_info *do_map_probe(struct map_info *map, const char *funcname, const char *modname) -{ - struct mtd_info *(*probe_p)(struct map_info *); - struct mtd_info *mtd = NULL; - if ((probe_p = inter_module_get_request(modname, funcname))) - mtd = (*probe_p)(map); /* map->im_name is set by probe */ +struct mtd_chip_driver { + struct mtd_info *(*probe)(struct map_info *map); + void (*destroy)(struct mtd_info *); + struct module *module; + char *name; + struct list_head list; +}; - return mtd; -} +void register_mtd_chip_driver(struct mtd_chip_driver *); +void unregister_mtd_chip_driver(struct mtd_chip_driver *); +struct mtd_info *do_map_probe(char *name, struct map_info *map); -/* - * Commonly-used probe functions for different types of chip. - */ -#define do_cfi_probe(x) do_map_probe(x, "cfi_probe", "cfi_probe") -#define do_jedec_probe(x) do_map_probe(x, "jedec_probe", "jedec_probe") -#define do_ram_probe(x) do_map_probe(x, "map_ram_probe", "map_ram") -#define do_rom_probe(x) do_map_probe(x, "map_rom_probe", "map_rom") -#else - /* without module support, call probe function directly */ -extern struct mtd_info *cfi_probe(struct map_info *); -extern struct mtd_info *jedec_probe(struct map_info *); -extern struct mtd_info *map_ram_probe(struct map_info *); -extern struct mtd_info *map_rom_probe(struct map_info *); - -#define do_cfi_probe(x) cfi_probe(x) -#define do_jedec_probe(x) jedec_probe(x) -#define do_ram_probe(x) map_ram_probe(x) -#define do_rom_probe(x) map_rom_probe(x) -#endif /* * Destroy an MTD device which was created for a map device. @@ -103,8 +79,11 @@ { struct map_info *map = mtd->priv; - map->fldrv_destroy(mtd); - inter_module_put(map->im_name); + map->fldrv->destroy(mtd); +#ifdef CONFIG_MODULES + if (map->fldrv->module) + __MOD_DEC_USE_COUNT(map->fldrv->module); +#endif kfree(mtd); } diff -u --recursive --new-file v2.4.5/linux/include/linux/mtd/mapped.h linux/include/linux/mtd/mapped.h --- v2.4.5/linux/include/linux/mtd/mapped.h Tue Jul 4 10:12:33 2000 +++ linux/include/linux/mtd/mapped.h Wed Dec 31 16:00:00 1969 @@ -1,92 +0,0 @@ -// -*- mode: cpp; mode: fold -*- -// Description /*{{{*/ -// $Id: mapped.h,v 1.2 2000/03/14 17:13:12 dwmw2 Exp $ -/* ###################################################################### - - Memory Mapped MTD Routines - - These routines are support routines for memory mapped chips, with - routines to support common sorts of flash. For devices that are based - on a memory mapped interface these routines provide everything necessary, - only a window changing function is required by the low level implementation. - - The entry point to setup and register a memory mapped MTD device, - mtd_mapped_setup will perform a detection sequence that can determine - the type size and configuration of many sorts of chip setups. - - ROMs and RAMs are detected and passed off to very simple routines, Flash - writing and erasing is handled as well. - - ##################################################################### */ - /*}}}*/ -#ifndef __MTD_FLASH_H__ -#define __MTD_FLASH_H__ - -#include -#include - -// MTD flags for ordinary flash -struct JEDECTable -{ - u_short jedec; - char *name; - u_long size; - u_long sectorsize; - u_long capabilities; -}; - -// JEDEC being 0 is the end of the chip array -struct flash_chip -{ - u_short jedec; - u_long size; - u_long sectorsize; - u_long base; - u_long capabilities; - - // These markers are filled in by the flash_chip_scan function - u_long start; - u_long length; -}; - -struct mapped_mtd_info -{ - struct mtd_info mtd; - u_long pagesize; // Size of the memory window - u_long maxsize; // Maximum MTD size in pages - u_char mfr,id; - char part[100]; // Part Catalogue number if available - int *lock; - // Multiple chip support, only used if this is type MTD_FLASH - u_char interleve; // Address chip interleve (0 = concatination) - struct flash_chip chips[5]; - - // Operations - unsigned long (*page)(struct mapped_mtd_info *map,unsigned long page); - int (*jedec_sense)(struct mapped_mtd_info *map); -}; - -extern struct JEDECTable mtd_JEDEC_table[]; - -// Automatic configurators -extern int mtd_mapped_setup(struct mapped_mtd_info *map); -extern int mtd_mapped_remove(struct mapped_mtd_info *map); - -// Generic functions -extern int flash_jedec(struct mapped_mtd_info *map); -extern int flash_erase(struct mtd_info *map, struct erase_info *instr); -extern int flash_write(struct mtd_info *map, loff_t start, size_t len, - size_t *retlen, const u_char *buf); -extern int rom_read(struct mtd_info *map, loff_t start, size_t len, - size_t *retlen, u_char *buf); -extern int ram_write(struct mtd_info *map, loff_t start, size_t len, - size_t *retlen, const u_char *buf); - -// Helpers -extern int page_jump(struct mapped_mtd_info *map,unsigned long start, - unsigned long len,unsigned long *buffer, - unsigned long *size); -extern void flash_chip_scan(struct mapped_mtd_info *map,unsigned long start, - unsigned long len); - -#endif /* __MTD_FLASH_H__ */ diff -u --recursive --new-file v2.4.5/linux/include/linux/mtd/mtd.h linux/include/linux/mtd/mtd.h --- v2.4.5/linux/include/linux/mtd/mtd.h Fri Dec 29 14:07:24 2000 +++ linux/include/linux/mtd/mtd.h Tue Jun 12 10:30:27 2001 @@ -1,5 +1,5 @@ -/* $Id: mtd.h,v 1.26 2000/10/30 17:18:04 sjhill Exp $ */ +/* $Id: mtd.h,v 1.33 2001/06/09 00:08:59 dwmw2 Exp $ */ #ifndef __MTD_MTD_H__ #define __MTD_MTD_H__ @@ -16,13 +16,13 @@ #endif /* __KERNEL__ */ struct erase_info_user { - unsigned long start; - unsigned long length; + u_int32_t start; + u_int32_t length; }; struct mtd_oob_buf { - loff_t start; - ssize_t length; + u_int32_t start; + u_int32_t length; unsigned char *ptr; }; @@ -68,13 +68,21 @@ struct mtd_info_user { u_char type; - u_long flags; - u_long size; // Total size of the MTD - u_long erasesize; - u_long oobblock; // Size of OOB blocks (e.g. 512) - u_long oobsize; // Amount of OOB data per block (e.g. 16) - u_long ecctype; - u_long eccsize; + u_int32_t flags; + u_int32_t size; // Total size of the MTD + u_int32_t erasesize; + u_int32_t oobblock; // Size of OOB blocks (e.g. 512) + u_int32_t oobsize; // Amount of OOB data per block (e.g. 16) + u_int32_t ecctype; + u_int32_t eccsize; +}; + +struct region_info_user { + u_int32_t offset; /* At which this region starts, + * from the beginning of the MTD */ + u_int32_t erasesize; /* For this region */ + u_int32_t numblocks; /* Number of blocks in this region */ + u_int32_t regionindex; }; #define MEMGETINFO _IOR('M', 1, struct mtd_info_user) @@ -83,11 +91,14 @@ #define MEMREADOOB _IOWR('M', 4, struct mtd_oob_buf) #define MEMLOCK _IOW('M', 5, struct erase_info_user) #define MEMUNLOCK _IOW('M', 6, struct erase_info_user) +#define MEMGETREGIONCOUNT _IOR('M', 7, int) +#define MEMGETREGIONINFO _IOWR('M', 8, struct region_info_user) #ifndef __KERNEL__ typedef struct mtd_info_user mtd_info_t; typedef struct erase_info_user erase_info_t; +typedef struct region_info_user region_info_t; /* User-space ioctl definitions */ @@ -103,8 +114,8 @@ struct erase_info { struct mtd_info *mtd; - u_long addr; - u_long len; + u_int32_t addr; + u_int32_t len; u_long time; u_long retries; u_int dev; @@ -115,22 +126,40 @@ struct erase_info *next; }; +struct mtd_erase_region_info { + u_int32_t offset; /* At which this region starts, from the beginning of the MTD */ + u_int32_t erasesize; /* For this region */ + u_int32_t numblocks; /* Number of blocks of erasesize in this region */ +}; struct mtd_info { u_char type; - u_long flags; - u_long size; // Total size of the MTD - u_long erasesize; - u_long oobblock; // Size of OOB blocks (e.g. 512) - u_long oobsize; // Amount of OOB data per block (e.g. 16) - u_long ecctype; - u_long eccsize; + u_int32_t flags; + u_int32_t size; // Total size of the MTD + + /* "Major" erase size for the device. Naďve users may take this + * to be the only erase size available, or may use the more detailed + * information below if they desire + */ + u_int32_t erasesize; + + u_int32_t oobblock; // Size of OOB blocks (e.g. 512) + u_int32_t oobsize; // Amount of OOB data per block (e.g. 16) + u_int32_t ecctype; + u_int32_t eccsize; // Kernel-only stuff starts here. char *name; int index; - u_long bank_size; + /* Data for variable erase regions. If numeraseregions is zero, + * it means that the whole device has erasesize as given above. + */ + int numeraseregions; + struct mtd_erase_region_info *eraseregions; + + /* This really shouldn't be here. It can go away in 2.5 */ + u_int32_t bank_size; struct module *module; int (*erase) (struct mtd_info *mtd, struct erase_info *instr); diff -u --recursive --new-file v2.4.5/linux/include/linux/mtd/nand_ecc.h linux/include/linux/mtd/nand_ecc.h --- v2.4.5/linux/include/linux/mtd/nand_ecc.h Wed Dec 31 16:00:00 1969 +++ linux/include/linux/mtd/nand_ecc.h Tue Jun 12 10:30:27 2001 @@ -0,0 +1,28 @@ +/* + * drivers/mtd/nand_ecc.h + * + * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com) + * + * $Id: nand_ecc.h,v 1.1 2000/10/12 00:57:15 sjhill 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 + * published by the Free Software Foundation. + * + * This file is the header for the ECC algorithm. + */ + +/* + * Creates non-inverted ECC code from line parity + */ +void nand_trans_result(u_char reg2, u_char reg3, u_char *ecc_code); + +/* + * Calculate 3 byte ECC code for 256 byte block + */ +void nand_calculate_ecc (const u_char *dat, u_char *ecc_code); + +/* + * Detect and correct a 1 bit error for 256 byte block + */ +int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc); diff -u --recursive --new-file v2.4.5/linux/include/linux/mtd/nftl.h linux/include/linux/mtd/nftl.h --- v2.4.5/linux/include/linux/mtd/nftl.h Mon Dec 11 14:57:58 2000 +++ linux/include/linux/mtd/nftl.h Tue Jun 12 10:30:27 2001 @@ -2,7 +2,7 @@ /* Defines for NAND Flash Translation Layer */ /* (c) 1999 Machine Vision Holdings, Inc. */ /* Author: David Woodhouse */ -/* $Id: nftl.h,v 1.9 2000/11/07 05:48:49 ollie Exp $ */ +/* $Id: nftl.h,v 1.10 2000/12/29 00:25:38 dwmw2 Exp $ */ #ifndef __MTD_NFTL_H__ #define __MTD_NFTL_H__ @@ -115,6 +115,7 @@ #define MAX_NFTLS 16 #define MAX_SECTORS_PER_UNIT 32 +#define NFTL_PARTN_BITS 4 #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.4.5/linux/include/linux/mtd/partitions.h linux/include/linux/mtd/partitions.h --- v2.4.5/linux/include/linux/mtd/partitions.h Mon Dec 11 14:57:58 2000 +++ linux/include/linux/mtd/partitions.h Tue Jun 12 10:30:27 2001 @@ -5,7 +5,7 @@ * * This code is GPL * - * $Id: partitions.h,v 1.3 2000/11/10 23:35:12 nico Exp $ + * $Id: partitions.h,v 1.6 2001/03/17 17:10:21 dwmw2 Exp $ */ #ifndef MTD_PARTITIONS_H @@ -22,10 +22,11 @@ * * For each partition, these fields are available: * name: string that will be used to label the partition's MTD device. - * size: the partition size; if 0, the partition will extend to the end of the - * master MTD device. - * offset: absolute starting position within the master MTD device; if 0, - * partition will start where the previous one ended. + * size: the partition size; if defined as MTDPART_SIZ_FULL, the partition + * will extend to the end of the master MTD device. + * offset: absolute starting position within the master MTD device; if + * defined as MTDPART_OFS_APPEND, the partition will start where the + * previous one ended. * mask_flags: contains flags that have to be masked (removed) from the * master MTD flag set for the corresponding MTD partition. * For example, to force a read-only partition, simply adding @@ -37,10 +38,13 @@ struct mtd_partition { char *name; /* identifier string */ - u_long size; /* partition size */ - u_long offset; /* offset within the master MTD space */ - u_long mask_flags; /* master MTD flags to mask out for this partition */ + u_int32_t size; /* partition size */ + u_int32_t offset; /* offset within the master MTD space */ + u_int32_t mask_flags; /* master MTD flags to mask out for this partition */ }; + +#define MTDPART_OFS_APPEND (-1) +#define MTDPART_SIZ_FULL (0) int add_mtd_partitions(struct mtd_info *, struct mtd_partition *, int); diff -u --recursive --new-file v2.4.5/linux/include/linux/netfilter_bridge.h linux/include/linux/netfilter_bridge.h --- v2.4.5/linux/include/linux/netfilter_bridge.h Wed Dec 31 16:00:00 1969 +++ linux/include/linux/netfilter_bridge.h Mon Jun 11 19:15:27 2001 @@ -0,0 +1,24 @@ +#ifndef __LINUX_BRIDGE_NETFILTER_H +#define __LINUX_BRIDGE_NETFILTER_H + +/* bridge-specific defines for netfilter. + */ + +#include +#include + +/* Bridge Hooks */ +/* After promisc drops, checksum checks. */ +#define NF_BR_PRE_ROUTING 0 +/* If the packet is destined for this box. */ +#define NF_BR_LOCAL_IN 1 +/* If the packet is destined for another interface. */ +#define NF_BR_FORWARD 2 +/* Packets coming from a local process. */ +#define NF_BR_LOCAL_OUT 3 +/* Packets about to hit the wire. */ +#define NF_BR_POST_ROUTING 4 +#define NF_BR_NUMHOOKS 5 + + +#endif diff -u --recursive --new-file v2.4.5/linux/include/linux/netfilter_ipv4/ip_tables.h linux/include/linux/netfilter_ipv4/ip_tables.h --- v2.4.5/linux/include/linux/netfilter_ipv4/ip_tables.h Mon Dec 11 13:31:24 2000 +++ linux/include/linux/netfilter_ipv4/ip_tables.h Mon Jun 11 19:15:27 2001 @@ -300,14 +300,14 @@ ({ \ unsigned int __i; \ int __ret = 0; \ - struct ipt_entry_match *__m; \ + struct ipt_entry_match *__match; \ \ for (__i = sizeof(struct ipt_entry); \ __i < (e)->target_offset; \ - __i += __m->u.match_size) { \ - __m = (void *)(e) + __i; \ + __i += __match->u.match_size) { \ + __match = (void *)(e) + __i; \ \ - __ret = fn(__m , ## args); \ + __ret = fn(__match , ## args); \ if (__ret != 0) \ break; \ } \ @@ -319,12 +319,12 @@ ({ \ unsigned int __i; \ int __ret = 0; \ - struct ipt_entry *__e; \ + struct ipt_entry *__entry; \ \ - for (__i = 0; __i < (size); __i += __e->next_offset) { \ - __e = (void *)(entries) + __i; \ + for (__i = 0; __i < (size); __i += __entry->next_offset) { \ + __entry = (void *)(entries) + __i; \ \ - __ret = fn(__e , ## args); \ + __ret = fn(__entry , ## args); \ if (__ret != 0) \ break; \ } \ diff -u --recursive --new-file v2.4.5/linux/include/linux/nfsd/nfsd.h linux/include/linux/nfsd/nfsd.h --- v2.4.5/linux/include/linux/nfsd/nfsd.h Fri May 25 18:02:17 2001 +++ linux/include/linux/nfsd/nfsd.h Tue Jul 3 15:44:05 2001 @@ -81,7 +81,7 @@ int nfsd_lookup(struct svc_rqst *, struct svc_fh *, const char *, int, struct svc_fh *); int nfsd_setattr(struct svc_rqst *, struct svc_fh *, - struct iattr *); + struct iattr *, int, time_t); int nfsd_create(struct svc_rqst *, struct svc_fh *, char *name, int len, struct iattr *attrs, int type, dev_t rdev, struct svc_fh *res); @@ -143,6 +143,7 @@ #define nfserr_noent __constant_htonl(NFSERR_NOENT) #define nfserr_io __constant_htonl(NFSERR_IO) #define nfserr_nxio __constant_htonl(NFSERR_NXIO) +#define nfserr_eagain __constant_htonl(NFSERR_EAGAIN) #define nfserr_acces __constant_htonl(NFSERR_ACCES) #define nfserr_exist __constant_htonl(NFSERR_EXIST) #define nfserr_xdev __constant_htonl(NFSERR_XDEV) @@ -160,9 +161,10 @@ #define nfserr_dquot __constant_htonl(NFSERR_DQUOT) #define nfserr_stale __constant_htonl(NFSERR_STALE) #define nfserr_remote __constant_htonl(NFSERR_REMOTE) +#define nfserr_wflush __constant_htonl(NFSERR_WFLUSH) #define nfserr_badhandle __constant_htonl(NFSERR_BADHANDLE) -#define nfserr_notsync __constant_htonl(NFSERR_NOTSYNC) -#define nfserr_badcookie __constant_htonl(NFSERR_BADCOOKIE) +#define nfserr_notsync __constant_htonl(NFSERR_NOT_SYNC) +#define nfserr_badcookie __constant_htonl(NFSERR_BAD_COOKIE) #define nfserr_notsupp __constant_htonl(NFSERR_NOTSUPP) #define nfserr_toosmall __constant_htonl(NFSERR_TOOSMALL) #define nfserr_serverfault __constant_htonl(NFSERR_SERVERFAULT) diff -u --recursive --new-file v2.4.5/linux/include/linux/nfsd/nfsfh.h linux/include/linux/nfsd/nfsfh.h --- v2.4.5/linux/include/linux/nfsd/nfsfh.h Fri May 25 18:02:17 2001 +++ linux/include/linux/nfsd/nfsfh.h Tue Jul 3 15:44:05 2001 @@ -199,7 +199,7 @@ * Function prototypes */ u32 fh_verify(struct svc_rqst *, struct svc_fh *, int, int); -int fh_compose(struct svc_fh *, struct svc_export *, struct dentry *); +int fh_compose(struct svc_fh *, struct svc_export *, struct dentry *, struct svc_fh *); int fh_update(struct svc_fh *); void fh_put(struct svc_fh *); diff -u --recursive --new-file v2.4.5/linux/include/linux/parport_pc.h linux/include/linux/parport_pc.h --- v2.4.5/linux/include/linux/parport_pc.h Sat May 19 18:07:04 2001 +++ linux/include/linux/parport_pc.h Mon Jun 11 19:15:27 2001 @@ -224,5 +224,6 @@ unsigned long base_hi, int irq, int dma, struct pci_dev *dev); +extern void parport_pc_unregister_port (struct parport *p); #endif diff -u --recursive --new-file v2.4.5/linux/include/linux/pci.h linux/include/linux/pci.h --- v2.4.5/linux/include/linux/pci.h Fri May 25 18:02:11 2001 +++ linux/include/linux/pci.h Tue Jul 3 15:43:41 2001 @@ -327,6 +327,9 @@ #define pci_for_each_dev_reverse(dev) \ for(dev = pci_dev_g(pci_devices.prev); dev != pci_dev_g(&pci_devices); dev = pci_dev_g(dev->global_list.prev)) +#define pci_for_each_bus(bus) \ +for(bus = pci_bus_b(pci_root_buses.next); bus != pci_bus_b(&pci_root_buses); bus = pci_bus_b(bus->node.next)) + /* * The pci_dev structure is used to describe both PCI and ISAPnP devices. */ @@ -356,6 +359,10 @@ this if your device has broken DMA or supports 64-bit transfers. */ + u32 current_state; /* Current operating state. In ACPI-speak, + this is D0-D3, D0 being fully functional, + and D3 being off. */ + /* device is compatible with these IDs */ unsigned short vendor_compatible[DEVICE_COUNT_COMPATIBLE]; unsigned short device_compatible[DEVICE_COUNT_COMPATIBLE]; @@ -469,10 +476,12 @@ struct list_head node; char *name; const struct pci_device_id *id_table; /* NULL if wants all devices */ - int (*probe)(struct pci_dev *dev, const struct pci_device_id *id); /* New device inserted */ - void (*remove)(struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */ - void (*suspend)(struct pci_dev *dev); /* Device suspended */ - void (*resume)(struct pci_dev *dev); /* Device woken up */ + int (*probe) (struct pci_dev *dev, const struct pci_device_id *id); /* New device inserted */ + void (*remove) (struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */ + int (*save_state) (struct pci_dev *dev, u32 state); /* Save Device Context */ + int (*suspend)(struct pci_dev *dev, u32 state); /* Device suspended */ + int (*resume) (struct pci_dev *dev); /* Device woken up */ + int (*enable_wake) (struct pci_dev *dev, u32 state, int enable); /* Enable wake event */ }; @@ -547,14 +556,18 @@ int pci_write_config_word(struct pci_dev *dev, int where, u16 val); int pci_write_config_dword(struct pci_dev *dev, int where, u32 val); -#define HAVE_PCI_DISABLE_DEVICE int pci_enable_device(struct pci_dev *dev); void pci_disable_device(struct pci_dev *dev); void pci_set_master(struct pci_dev *dev); int pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask); -int pci_set_power_state(struct pci_dev *dev, int state); int pci_assign_resource(struct pci_dev *dev, int i); +/* Power management related routines */ +int pci_save_state(struct pci_dev *dev, u32 *buffer); +int pci_restore_state(struct pci_dev *dev, u32 *buffer); +int pci_set_power_state(struct pci_dev *dev, int state); +int pci_enable_wake(struct pci_dev *dev, u32 state, int enable); + /* Helper functions for low-level code (drivers/pci/setup-[bus,res].c) */ int pci_claim_resource(struct pci_dev *, int); @@ -628,12 +641,19 @@ static inline int pci_enable_device(struct pci_dev *dev) { return -EIO; } static inline void pci_disable_device(struct pci_dev *dev) { } static inline int pci_module_init(struct pci_driver *drv) { return -ENODEV; } +static inline int pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask) { return -EIO; } static inline int pci_assign_resource(struct pci_dev *dev, int i) { return -EBUSY;} static inline int pci_register_driver(struct pci_driver *drv) { return 0;} static inline void pci_unregister_driver(struct pci_driver *drv) { } static inline int scsi_to_pci_dma_dir(unsigned char scsi_dir) { return scsi_dir; } static inline int pci_find_capability (struct pci_dev *dev, int cap) {return 0; } static inline const struct pci_device_id *pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev) { return NULL; } + +/* Power management related routines */ +static inline int pci_save_state(struct pci_dev *dev, u32 *buffer) { return 0; } +static inline int pci_restore_state(struct pci_dev *dev, u32 *buffer) { return 0; } +static inline int pci_set_power_state(struct pci_dev *dev, int state) { return 0; } +static inline int pci_enable_wake(struct pci_dev *dev, u32 state, int enable) { return 0; } #define pci_for_each_dev(dev) \ for(dev = NULL; 0; ) diff -u --recursive --new-file v2.4.5/linux/include/linux/pci_ids.h linux/include/linux/pci_ids.h --- v2.4.5/linux/include/linux/pci_ids.h Wed May 16 10:25:39 2001 +++ linux/include/linux/pci_ids.h Tue Jul 3 07:55:20 2001 @@ -160,20 +160,37 @@ #define PCI_DEVICE_ID_NCR_YELLOWFIN 0x0701 #define PCI_VENDOR_ID_ATI 0x1002 +/* Mach64 */ #define PCI_DEVICE_ID_ATI_68800 0x4158 #define PCI_DEVICE_ID_ATI_215CT222 0x4354 #define PCI_DEVICE_ID_ATI_210888CX 0x4358 +#define PCI_DEVICE_ID_ATI_215ET222 0x4554 +/* Mach64 / Rage */ #define PCI_DEVICE_ID_ATI_215GB 0x4742 #define PCI_DEVICE_ID_ATI_215GD 0x4744 #define PCI_DEVICE_ID_ATI_215GI 0x4749 #define PCI_DEVICE_ID_ATI_215GP 0x4750 #define PCI_DEVICE_ID_ATI_215GQ 0x4751 +#define PCI_DEVICE_ID_ATI_215XL 0x4752 #define PCI_DEVICE_ID_ATI_215GT 0x4754 #define PCI_DEVICE_ID_ATI_215GTB 0x4755 +#define PCI_DEVICE_ID_ATI_215_IV 0x4756 +#define PCI_DEVICE_ID_ATI_215_IW 0x4757 +#define PCI_DEVICE_ID_ATI_215_IZ 0x475A #define PCI_DEVICE_ID_ATI_210888GX 0x4758 -#define PCI_DEVICE_ID_ATI_215LG 0x4c47 -#define PCI_DEVICE_ID_ATI_264LT 0x4c54 +#define PCI_DEVICE_ID_ATI_215_LB 0x4c42 +#define PCI_DEVICE_ID_ATI_215_LD 0x4c44 +#define PCI_DEVICE_ID_ATI_215_LG 0x4c47 +#define PCI_DEVICE_ID_ATI_215_LI 0x4c49 +#define PCI_DEVICE_ID_ATI_215_LM 0x4c4D +#define PCI_DEVICE_ID_ATI_215_LN 0x4c4E +#define PCI_DEVICE_ID_ATI_215_LR 0x4c52 +#define PCI_DEVICE_ID_ATI_215_LS 0x4c53 +#define PCI_DEVICE_ID_ATI_264_LT 0x4c54 +/* Mach64 VT */ #define PCI_DEVICE_ID_ATI_264VT 0x5654 +#define PCI_DEVICE_ID_ATI_264VU 0x5655 +#define PCI_DEVICE_ID_ATI_264VV 0x5656 /* Rage128 Pro GL */ #define PCI_DEVICE_ID_ATI_Rage128_PA 0x5041 #define PCI_DEVICE_ID_ATI_Rage128_PB 0x5042 @@ -194,6 +211,7 @@ #define PCI_DEVICE_ID_ATI_RAGE128_PP 0x5050 #define PCI_DEVICE_ID_ATI_RAGE128_PQ 0x5051 #define PCI_DEVICE_ID_ATI_RAGE128_PR 0x5052 +#define PCI_DEVICE_ID_ATI_RAGE128_TR 0x5452 #define PCI_DEVICE_ID_ATI_RAGE128_PS 0x5053 #define PCI_DEVICE_ID_ATI_RAGE128_PT 0x5054 #define PCI_DEVICE_ID_ATI_RAGE128_PU 0x5055 @@ -309,6 +327,7 @@ #define PCI_DEVICE_ID_IBM_TR_WAKE 0x003e #define PCI_DEVICE_ID_IBM_MPIC 0x0046 #define PCI_DEVICE_ID_IBM_3780IDSP 0x007d +#define PCI_DEVICE_ID_IBM_CHUKAR 0x0096 #define PCI_DEVICE_ID_IBM_405GP 0x0156 #define PCI_DEVICE_ID_IBM_MPIC_2 0xffff @@ -328,6 +347,9 @@ #define PCI_DEVICE_ID_AMD_LANCE_HOME 0x2001 #define PCI_DEVICE_ID_AMD_SCSI 0x2020 #define PCI_DEVICE_ID_AMD_FE_GATE_7006 0x7006 +#define PCI_DEVICE_ID_AMD_FE_GATE_7007 0x7007 +#define PCI_DEVICE_ID_AMD_FE_GATE_700E 0x700E +#define PCI_DEVICE_ID_AMD_FE_GATE_700F 0x700F #define PCI_DEVICE_ID_AMD_COBRA_7400 0x7400 #define PCI_DEVICE_ID_AMD_COBRA_7401 0x7401 #define PCI_DEVICE_ID_AMD_COBRA_7403 0x7403 @@ -336,6 +358,10 @@ #define PCI_DEVICE_ID_AMD_VIPER_7409 0x7409 #define PCI_DEVICE_ID_AMD_VIPER_740B 0x740B #define PCI_DEVICE_ID_AMD_VIPER_740C 0x740C +#define PCI_DEVICE_ID_AMD_VIPER_7410 0x7410 +#define PCI_DEVICE_ID_AMD_VIPER_7411 0x7411 +#define PCI_DEVICE_ID_AMD_VIPER_7413 0x7413 +#define PCI_DEVICE_ID_AMD_VIPER_7414 0x7414 #define PCI_VENDOR_ID_TRIDENT 0x1023 #define PCI_DEVICE_ID_TRIDENT_4DWAVE_DX 0x2000 @@ -386,6 +412,7 @@ #define PCI_VENDOR_ID_NEC 0x1033 #define PCI_DEVICE_ID_NEC_PCX2 0x0046 #define PCI_DEVICE_ID_NEC_NILE4 0x005a +#define PCI_DEVICE_ID_NEC_VRC5476 0x009b #define PCI_VENDOR_ID_FD 0x1036 #define PCI_DEVICE_ID_FD_36C70 0x0000 @@ -400,15 +427,20 @@ #define PCI_DEVICE_ID_SI_501 0x0406 #define PCI_DEVICE_ID_SI_496 0x0496 #define PCI_DEVICE_ID_SI_300 0x0300 +#define PCI_DEVICE_ID_SI_315H 0x0310 +#define PCI_DEVICE_ID_SI_315 0x0315 #define PCI_DEVICE_ID_SI_530 0x0530 #define PCI_DEVICE_ID_SI_540 0x0540 +#define PCI_DEVICE_ID_SI_550 0x0550 #define PCI_DEVICE_ID_SI_540_VGA 0x5300 +#define PCI_DEVICE_ID_SI_550_VGA 0x5315 #define PCI_DEVICE_ID_SI_601 0x0601 #define PCI_DEVICE_ID_SI_620 0x0620 #define PCI_DEVICE_ID_SI_630 0x0630 -#define PCI_DEVICE_ID_SI_730 0x0730 +#define PCI_DEVICE_ID_SI_730 0x0730 #define PCI_DEVICE_ID_SI_630_VGA 0x6300 #define PCI_DEVICE_ID_SI_730_VGA 0x7300 +#define PCI_DEVICE_ID_SI_900 0x0900 #define PCI_DEVICE_ID_SI_5107 0x5107 #define PCI_DEVICE_ID_SI_5300 0x5300 #define PCI_DEVICE_ID_SI_5511 0x5511 @@ -422,6 +454,7 @@ #define PCI_DEVICE_ID_SI_6306 0x6306 #define PCI_DEVICE_ID_SI_6326 0x6326 #define PCI_DEVICE_ID_SI_7001 0x7001 +#define PCI_DEVICE_ID_SI_7016 0x7016 #define PCI_VENDOR_ID_HP 0x103c #define PCI_DEVICE_ID_HP_DONNER_GFX 0x1008 @@ -486,11 +519,14 @@ #define PCI_DEVICE_ID_TI_1220 0xac17 #define PCI_DEVICE_ID_TI_1221 0xac19 #define PCI_DEVICE_ID_TI_1210 0xac1a +#define PCI_DEVICE_ID_TI_1410 0xac50 #define PCI_DEVICE_ID_TI_1450 0xac1b #define PCI_DEVICE_ID_TI_1225 0xac1c #define PCI_DEVICE_ID_TI_1251A 0xac1d #define PCI_DEVICE_ID_TI_1211 0xac1e #define PCI_DEVICE_ID_TI_1251B 0xac1f +#define PCI_DEVICE_ID_TI_4410 0xac41 +#define PCI_DEVICE_ID_TI_4451 0xac42 #define PCI_DEVICE_ID_TI_1420 0xac51 #define PCI_VENDOR_ID_SONY 0x104d @@ -527,6 +563,7 @@ #define PCI_DEVICE_ID_PROMISE_20267 0x4d30 #define PCI_DEVICE_ID_PROMISE_20246 0x4d33 #define PCI_DEVICE_ID_PROMISE_20262 0x4d38 +#define PCI_DEVICE_ID_PROMISE_20268 0x4d68 #define PCI_DEVICE_ID_PROMISE_5300 0x5300 #define PCI_VENDOR_ID_N9 0x105d @@ -783,6 +820,8 @@ #define PCI_VENDOR_ID_IMS 0x10e0 #define PCI_DEVICE_ID_IMS_8849 0x8849 +#define PCI_DEVICE_ID_IMS_TT128 0x9128 +#define PCI_DEVICE_ID_IMS_TT3D 0x9135 #define PCI_VENDOR_ID_TEKRAM2 0x10e1 #define PCI_DEVICE_ID_TEKRAM2_690c 0x690c @@ -808,6 +847,9 @@ #define PCI_DEVICE_ID_REALTEK_8129 0x8129 #define PCI_DEVICE_ID_REALTEK_8139 0x8139 +#define PCI_VENDOR_ID_XILINX 0x10ee +#define PCI_DEVICE_ID_TURBOPAM 0x4020 + #define PCI_VENDOR_ID_TRUEVISION 0x10fa #define PCI_DEVICE_ID_TRUEVISION_T1000 0x000c @@ -986,15 +1028,18 @@ #define PCI_DEVICE_ID_RENDITION_VERITE 0x0001 #define PCI_DEVICE_ID_RENDITION_VERITE2100 0x2000 -#define PCI_VENDOR_ID_SERVERWORKS 0x1166 -#define PCI_DEVICE_ID_SERVERWORKS_HE 0x0008 -#define PCI_DEVICE_ID_SERVERWORKS_LE 0x0009 -#define PCI_DEVICE_ID_SERVERWORKS_CIOB30 0x0010 -#define PCI_DEVICE_ID_SERVERWORKS_CMIC_HE 0x0011 -#define PCI_DEVICE_ID_SERVERWORKS_CSB5 0x0201 -#define PCI_DEVICE_ID_SERVERWORKS_OSB4 0x0200 +#define PCI_VENDOR_ID_SERVERWORKS 0x1166 +#define PCI_DEVICE_ID_SERVERWORKS_HE 0x0008 +#define PCI_DEVICE_ID_SERVERWORKS_LE 0x0009 +#define PCI_DEVICE_ID_SERVERWORKS_CIOB30 0x0010 +#define PCI_DEVICE_ID_SERVERWORKS_CMIC_HE 0x0011 +#define PCI_DEVICE_ID_SERVERWORKS_CSB5 0x0201 +#define PCI_DEVICE_ID_SERVERWORKS_OSB4 0x0200 #define PCI_DEVICE_ID_SERVERWORKS_OSB4IDE 0x0211 +#define PCI_DEVICE_ID_SERVERWORKS_CSB5IDE 0x0212 #define PCI_DEVICE_ID_SERVERWORKS_OSB4USB 0x0220 +#define PCI_DEVICE_ID_SERVERWORKS_CSB5USB PCI_DEVICE_ID_SERVERWORKS_OSB4USB +#define PCI_DEVICE_ID_SERVERWORKS_CSB5ISA 0x0230 #define PCI_VENDOR_ID_SBE 0x1176 #define PCI_DEVICE_ID_SBE_WANXL100 0x0301 @@ -1135,6 +1180,7 @@ #define PCI_DEVICE_ID_AVM_B1 0x0700 #define PCI_DEVICE_ID_AVM_C4 0x0800 #define PCI_DEVICE_ID_AVM_A1 0x0a00 +#define PCI_DEVICE_ID_AVM_C2 0x1100 #define PCI_DEVICE_ID_AVM_T1 0x1200 #define PCI_VENDOR_ID_DIPIX 0x1246 @@ -1171,6 +1217,9 @@ #define PCI_VENDOR_ID_ROCKWELL 0x127A +#define PCI_VENDOR_ID_ITE 0x1283 +#define PCI_DEVICE_ID_ITE_IT8172G 0x8172 + /* formerly Platform Tech */ #define PCI_VENDOR_ID_ESS_OLD 0x1285 #define PCI_DEVICE_ID_ESS_ESS0100 0x0100 @@ -1281,6 +1330,9 @@ #define PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2 0x0108 #define PCI_SUBDEVICE_ID_HYPERCOPE_PLEXUS 0x0109 +#define PCI_VENDOR_ID_KAWASAKI 0x136b +#define PCI_DEVICE_ID_MCHIP_KL5A72002 0xff01 + #define PCI_VENDOR_ID_LMC 0x1376 #define PCI_DEVICE_ID_LMC_HSSI 0x0003 #define PCI_DEVICE_ID_LMC_DS3 0x0004 @@ -1354,6 +1406,8 @@ #define PCI_DEVICE_ID_AIRONET_4500 0x4800 // drivers/net/aironet4500_card.c #define PCI_VENDOR_ID_TITAN 0x14D2 +#define PCI_DEVICE_ID_TITAN_110L 0x8011 +#define PCI_DEVICE_ID_TITAN_210L 0x8021 #define PCI_DEVICE_ID_TITAN_100 0xA001 #define PCI_DEVICE_ID_TITAN_200 0xA005 #define PCI_DEVICE_ID_TITAN_400 0xA003 @@ -1366,6 +1420,9 @@ #define PCI_VENDOR_ID_AFAVLAB 0x14db #define PCI_DEVICE_ID_AFAVLAB_TK9902 0x2120 +#define PCI_VENDOR_ID_BROADCOM 0x14e4 +#define PCI_DEVICE_ID_TIGON3 0x1644 + #define PCI_VENDOR_ID_SYBA 0x1592 #define PCI_DEVICE_ID_SYBA_2P_EPP 0x0782 #define PCI_DEVICE_ID_SYBA_1P_ECP 0x0783 @@ -1476,13 +1533,18 @@ #define PCI_DEVICE_ID_INTEL_82801AB_5 0x2425 #define PCI_DEVICE_ID_INTEL_82801AB_6 0x2426 #define PCI_DEVICE_ID_INTEL_82801AB_8 0x2428 -#define PCI_DEVICE_ID_INTEL_82820FW_0 0x2440 -#define PCI_DEVICE_ID_INTEL_82820FW_1 0x2442 -#define PCI_DEVICE_ID_INTEL_82820FW_2 0x2443 -#define PCI_DEVICE_ID_INTEL_82820FW_3 0x2444 -#define PCI_DEVICE_ID_INTEL_82820FW_4 0x2449 -#define PCI_DEVICE_ID_INTEL_82820FW_5 0x244b -#define PCI_DEVICE_ID_INTEL_82820FW_6 0x244e +#define PCI_DEVICE_ID_INTEL_82801BA_0 0x2440 +#define PCI_DEVICE_ID_INTEL_82801BA_1 0x2442 +#define PCI_DEVICE_ID_INTEL_82801BA_2 0x2443 +#define PCI_DEVICE_ID_INTEL_82801BA_3 0x2444 +#define PCI_DEVICE_ID_INTEL_82801BA_4 0x2445 +#define PCI_DEVICE_ID_INTEL_82801BA_5 0x2446 +#define PCI_DEVICE_ID_INTEL_82801BA_6 0x2448 +#define PCI_DEVICE_ID_INTEL_82801BA_7 0x2449 +#define PCI_DEVICE_ID_INTEL_82801BA_8 0x244a +#define PCI_DEVICE_ID_INTEL_82801BA_9 0x244b +#define PCI_DEVICE_ID_INTEL_82801BA_10 0x244c +#define PCI_DEVICE_ID_INTEL_82801BA_11 0x244e #define PCI_DEVICE_ID_INTEL_82810_MC1 0x7120 #define PCI_DEVICE_ID_INTEL_82810_IG1 0x7121 #define PCI_DEVICE_ID_INTEL_82810_MC3 0x7122 @@ -1565,6 +1627,10 @@ #define PCI_VENDOR_ID_HOLTEK 0x9412 #define PCI_DEVICE_ID_HOLTEK_6565 0x6565 + +#define PCI_VENDOR_ID_NETMOS 0x9710 +#define PCI_DEVICE_ID_NETMOS_9735 0x9735 +#define PCI_DEVICE_ID_NETMOS_9835 0x9835 #define PCI_SUBVENDOR_ID_EXSYS 0xd84d #define PCI_SUBDEVICE_ID_EXSYS_4014 0x4014 diff -u --recursive --new-file v2.4.5/linux/include/linux/pm.h linux/include/linux/pm.h --- v2.4.5/linux/include/linux/pm.h Fri May 25 18:01:26 2001 +++ linux/include/linux/pm.h Tue Jul 3 15:42:55 2001 @@ -34,6 +34,8 @@ PM_SUSPEND, /* enter D1-D3 */ PM_RESUME, /* enter D0 */ + PM_SAVE_STATE, /* save device's state */ + /* enable wake-on */ PM_SET_WAKEUP, diff -u --recursive --new-file v2.4.5/linux/include/linux/quotaops.h linux/include/linux/quotaops.h --- v2.4.5/linux/include/linux/quotaops.h Fri May 25 18:01:57 2001 +++ linux/include/linux/quotaops.h Tue Jul 3 15:43:22 2001 @@ -21,7 +21,6 @@ */ extern void dquot_initialize(struct inode *inode, short type); extern void dquot_drop(struct inode *inode); -extern void invalidate_dquots(kdev_t dev, short type); extern int quota_off(struct super_block *sb, short type); extern int sync_dquots(kdev_t dev, short type); diff -u --recursive --new-file v2.4.5/linux/include/linux/raid/raid5.h linux/include/linux/raid/raid5.h --- v2.4.5/linux/include/linux/raid/raid5.h Thu Feb 8 19:38:38 2001 +++ linux/include/linux/raid/raid5.h Wed Jun 20 20:55:08 2001 @@ -132,6 +132,7 @@ struct buffer_head *bh_read[MD_SB_DISKS]; /* read request buffers of the MD device */ struct buffer_head *bh_write[MD_SB_DISKS]; /* write request buffers of the MD device */ struct buffer_head *bh_written[MD_SB_DISKS]; /* write request buffers of the MD device that have been scheduled for write */ + struct page *bh_page[MD_SB_DISKS]; /* saved bh_cache[n]->b_page when reading around the cache */ unsigned long sector; /* sector of this row */ int size; /* buffers size */ int pd_idx; /* parity disk index */ @@ -157,6 +158,32 @@ #define STRIPE_HANDLE 2 #define STRIPE_SYNCING 3 #define STRIPE_INSYNC 4 +#define STRIPE_PREREAD_ACTIVE 5 +#define STRIPE_DELAYED 6 + +/* + * Plugging: + * + * To improve write throughput, we need to delay the handling of some + * stripes until there has been a chance that several write requests + * for the one stripe have all been collected. + * In particular, any write request that would require pre-reading + * is put on a "delayed" queue until there are no stripes currently + * in a pre-read phase. Further, if the "delayed" queue is empty when + * a stripe is put on it then we "plug" the queue and do not process it + * until an unplg call is made. (the tq_disk list is run). + * + * When preread is initiated on a stripe, we set PREREAD_ACTIVE and add + * it to the count of prereading stripes. + * When write is initiated, or the stripe refcnt == 0 (just in case) we + * clear the PREREAD_ACTIVE flag and decrement the count + * Whenever the delayed queue is empty and the device is not plugged, we + * move any strips from delayed to handle and clear the DELAYED flag and set PREREAD_ACTIVE. + * In stripe_handle, if we find pre-reading is necessary, we do it if + * PREREAD_ACTIVE is set, else we set DELAYED which will send it to the delayed queue. + * HANDLE gets cleared if stripe_handle leave nothing locked. + */ + struct disk_info { kdev_t dev; @@ -181,14 +208,21 @@ int max_nr_stripes; struct list_head handle_list; /* stripes needing handling */ + struct list_head delayed_list; /* stripes that have plugged requests */ + atomic_t preread_active_stripes; /* stripes with scheduled io */ /* * Free stripes pool */ atomic_t active_stripes; struct list_head inactive_list; md_wait_queue_head_t wait_for_stripe; - + int inactive_blocked; /* release of inactive stripes blocked, + * waiting for 25% to be free + */ md_spinlock_t device_lock; + + int plugged; + struct tq_struct plug_tq; }; typedef struct raid5_private_data raid5_conf_t; diff -u --recursive --new-file v2.4.5/linux/include/linux/reiserfs_fs.h linux/include/linux/reiserfs_fs.h --- v2.4.5/linux/include/linux/reiserfs_fs.h Fri Apr 27 14:18:08 2001 +++ linux/include/linux/reiserfs_fs.h Tue Jun 12 11:12:47 2001 @@ -1806,6 +1806,10 @@ extern int reiserfs_notify_change(struct dentry * dentry, struct iattr * attr); void reiserfs_write_inode (struct inode * inode, int) ; +/* nfsd support functions */ +struct dentry *reiserfs_fh_to_dentry(struct super_block *sb, __u32 *fh, int len, int fhtype, int parent); +int reiserfs_dentry_to_fh(struct dentry *, __u32 *fh, int *lenp, int need_parent); + /* we don't mark inodes dirty, we just log them */ void reiserfs_dirty_inode (struct inode * inode) ; diff -u --recursive --new-file v2.4.5/linux/include/linux/slab.h linux/include/linux/slab.h --- v2.4.5/linux/include/linux/slab.h Fri May 25 18:01:28 2001 +++ linux/include/linux/slab.h Tue Jul 3 15:42:55 2001 @@ -15,14 +15,15 @@ #include /* flags for kmem_cache_alloc() */ -#define SLAB_BUFFER GFP_BUFFER +#define SLAB_NOFS GFP_NOFS +#define SLAB_NOIO GFP_NOIO #define SLAB_ATOMIC GFP_ATOMIC #define SLAB_USER GFP_USER #define SLAB_KERNEL GFP_KERNEL #define SLAB_NFS GFP_NFS #define SLAB_DMA GFP_DMA -#define SLAB_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO) +#define SLAB_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS) #define SLAB_NO_GROW 0x00001000UL /* don't grow a cache */ /* flags to pass to kmem_cache_create(). diff -u --recursive --new-file v2.4.5/linux/include/linux/smb_fs.h linux/include/linux/smb_fs.h --- v2.4.5/linux/include/linux/smb_fs.h Tue May 15 13:40:55 2001 +++ linux/include/linux/smb_fs.h Wed Jun 20 16:07:57 2001 @@ -93,6 +93,11 @@ #endif /* DEBUG_SMB_MALLOC */ +/* + * Flags for the in-memory inode + */ +#define SMB_F_LOCALWRITE 0x02 /* file modified locally */ + /* NT1 protocol capability bits */ #define SMB_CAP_RAW_MODE 0x0001 diff -u --recursive --new-file v2.4.5/linux/include/linux/smb_fs_i.h linux/include/linux/smb_fs_i.h --- v2.4.5/linux/include/linux/smb_fs_i.h Fri May 25 18:01:26 2001 +++ linux/include/linux/smb_fs_i.h Tue Jul 3 15:42:54 2001 @@ -26,6 +26,7 @@ __u16 attr; /* Attribute fields, DOS value */ __u16 access; /* Access mode */ + __u16 flags; unsigned long oldmtime; /* last time refreshed */ unsigned long closed; /* timestamp when closed */ unsigned openers; /* number of fileid users */ diff -u --recursive --new-file v2.4.5/linux/include/linux/socket.h linux/include/linux/socket.h --- v2.4.5/linux/include/linux/socket.h Fri May 25 18:01:26 2001 +++ linux/include/linux/socket.h Tue Jul 3 15:42:54 2001 @@ -156,6 +156,7 @@ #define AF_IRDA 23 /* IRDA sockets */ #define AF_PPPOX 24 /* PPPoX sockets */ #define AF_WANPIPE 25 /* Wanpipe API Sockets */ +#define AF_BLUETOOTH 31 /* Bluetooth sockets */ #define AF_MAX 32 /* For now.. */ /* Protocol families, same as address families. */ @@ -186,6 +187,7 @@ #define PF_IRDA AF_IRDA #define PF_PPPOX AF_PPPOX #define PF_WANPIPE AF_WANPIPE +#define PF_BLUETOOTH AF_BLUETOOTH #define PF_MAX AF_MAX /* Maximum queue length specifiable by listen. */ diff -u --recursive --new-file v2.4.5/linux/include/linux/sockios.h linux/include/linux/sockios.h --- v2.4.5/linux/include/linux/sockios.h Sat Nov 11 19:02:40 2000 +++ linux/include/linux/sockios.h Wed Jun 27 14:15:30 2001 @@ -77,6 +77,10 @@ #define SIOCETHTOOL 0x8946 /* Ethtool interface */ +#define SIOCGMIIPHY 0x8947 /* Get address of MII PHY in use. */ +#define SIOCGMIIREG 0x8948 /* Read MII PHY register. */ +#define SIOCSMIIREG 0x8949 /* Write MII PHY register. */ + /* ARP cache control calls. */ /* 0x8950 - 0x8952 * obsolete calls, don't re-use */ #define SIOCDARP 0x8953 /* delete ARP table entry */ diff -u --recursive --new-file v2.4.5/linux/include/linux/sunrpc/xprt.h linux/include/linux/sunrpc/xprt.h --- v2.4.5/linux/include/linux/sunrpc/xprt.h Fri May 25 18:01:27 2001 +++ linux/include/linux/sunrpc/xprt.h Tue Jul 3 15:44:05 2001 @@ -138,7 +138,7 @@ struct rpc_wait_queue reconn; /* waiting for reconnect */ struct rpc_rqst * free; /* free slots */ struct rpc_rqst slot[RPC_MAXREQS]; - unsigned int sockstate; /* Socket state */ + unsigned long sockstate; /* Socket state */ unsigned char shutdown : 1, /* being shut down */ nocong : 1, /* no congestion control */ stream : 1, /* TCP */ diff -u --recursive --new-file v2.4.5/linux/include/linux/swap.h linux/include/linux/swap.h --- v2.4.5/linux/include/linux/swap.h Fri May 25 18:01:27 2001 +++ linux/include/linux/swap.h Tue Jul 3 15:42:55 2001 @@ -133,6 +133,7 @@ extern void __delete_from_swap_cache(struct page *page); extern void delete_from_swap_cache(struct page *page); extern void delete_from_swap_cache_nolock(struct page *page); +extern void free_page_and_swap_cache(struct page *page); /* linux/mm/swapfile.c */ extern unsigned int nr_swapfiles; diff -u --recursive --new-file v2.4.5/linux/include/linux/sysv_fs.h linux/include/linux/sysv_fs.h --- v2.4.5/linux/include/linux/sysv_fs.h Mon Dec 11 13:26:16 2000 +++ linux/include/linux/sysv_fs.h Mon Jul 2 14:03:04 2001 @@ -7,7 +7,6 @@ /* This code assumes - - a little endian processor like 386, - sizeof(short) = 2, sizeof(int) = 4, sizeof(long) = 4, - alignof(short) = 2, alignof(long) = 4. */ @@ -26,27 +25,17 @@ /* Layout on disk */ /* ============== */ - -/* The block size is sb->sv_block_size which may be smaller than BLOCK_SIZE. */ - -/* zones (= data allocation units) are blocks */ - -/* On Coherent FS, 32 bit quantities are stored using (I quote the Coherent - manual) a "canonical byte ordering". This is the PDP-11 byte ordering: - x = 2^24 * byte3 + 2^16 * byte2 + 2^8 * byte1 + byte0 is stored - as { byte2, byte3, byte0, byte1 }. We need conversions. -*/ - -typedef u32 coh_ulong; - -static inline coh_ulong to_coh_ulong (u32 x) -{ - return ((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16); -} - -static inline u32 from_coh_ulong (coh_ulong x) +static inline u32 PDP_swab(u32 x) { +#ifdef __LITTLE_ENDIAN return ((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16); +#else +#ifdef __BIG_ENDIAN + return ((x & 0xff00ff) << 8) | ((x & 0xff00ff00) >> 8); +#else +#error BYTESEX +#endif +#endif } /* inode numbers are 16 bit */ @@ -103,12 +92,6 @@ }; -/* Xenix free list block on disk */ -struct xenix_freelist_chunk { - u16 fl_nfree; /* number of free blocks in fl_free, <= XENIX_NICFREE] */ - u32 fl_free[XENIX_NICFREE] __packed2__; -}; - /* SystemV FS comes in two variants: * sysv2: System V Release 2 (e.g. Microport), structure elements aligned(2). * sysv4: System V Release 4 (e.g. Consensys), structure elements aligned(4). @@ -148,12 +131,6 @@ 2 for 1024 byte blocks */ }; -/* SystemV4 free list block on disk */ -struct sysv4_freelist_chunk { - u16 fl_nfree; /* number of free blocks in fl_free, <= SYSV_NICFREE] */ - u32 fl_free[SYSV_NICFREE]; -}; - /* SystemV2 super-block data on disk */ struct sysv2_super_block { u16 s_isize; /* index of first data zone */ @@ -182,10 +159,31 @@ 2 for 1024 byte blocks */ }; -/* SystemV2 free list block on disk */ -struct sysv2_freelist_chunk { - u16 fl_nfree; /* number of free blocks in fl_free, <= SYSV_NICFREE] */ - u32 fl_free[SYSV_NICFREE] __packed2__; +/* V7 super-block data on disk */ +#define V7_NICINOD 100 /* number of inode cache entries */ +#define V7_NICFREE 50 /* number of free block list chunk entries */ +struct v7_super_block { + u16 s_isize; /* index of first data zone */ + u32 s_fsize __packed2__; /* total number of zones of this fs */ + /* the start of the free block list: */ + u16 s_nfree; /* number of free blocks in s_free, <= V7_NICFREE */ + u32 s_free[V7_NICFREE]; /* first free block list chunk */ + /* the cache of free inodes: */ + u16 s_ninode; /* number of free inodes in s_inode, <= V7_NICINOD */ + sysv_ino_t s_inode[V7_NICINOD]; /* some free inodes */ + /* locks, not used by Linux or V7: */ + char s_flock; /* lock during free block list manipulation */ + char s_ilock; /* lock during inode cache manipulation */ + char s_fmod; /* super-block modified flag */ + char s_ronly; /* flag whether fs is mounted read-only */ + u32 s_time __packed2__; /* time of last super block update */ + /* the following fields are not maintained by V7: */ + u32 s_tfree __packed2__; /* total number of free zones */ + u16 s_tinode; /* total number of free inodes */ + u16 s_m; /* interleave factor */ + u16 s_n; /* interleave factor */ + char s_fname[6]; /* file system name */ + char s_fpack[6]; /* file system pack name */ }; /* Coherent super-block data on disk */ @@ -193,10 +191,10 @@ #define COH_NICFREE 64 /* number of free block list chunk entries */ struct coh_super_block { u16 s_isize; /* index of first data zone */ - coh_ulong s_fsize __packed2__; /* total number of zones of this fs */ + u32 s_fsize __packed2__; /* total number of zones of this fs */ /* the start of the free block list: */ u16 s_nfree; /* number of free blocks in s_free, <= COH_NICFREE */ - coh_ulong s_free[COH_NICFREE] __packed2__; /* first free block list chunk */ + u32 s_free[COH_NICFREE] __packed2__; /* first free block list chunk */ /* the cache of free inodes: */ u16 s_ninode; /* number of free inodes in s_inode, <= COH_NICINOD */ sysv_ino_t s_inode[COH_NICINOD]; /* some free inodes */ @@ -205,8 +203,8 @@ char s_ilock; /* lock during inode cache manipulation */ char s_fmod; /* super-block modified flag */ char s_ronly; /* flag whether fs is mounted read-only */ - coh_ulong s_time __packed2__; /* time of last super block update */ - coh_ulong s_tfree __packed2__; /* total number of free zones */ + u32 s_time __packed2__; /* time of last super block update */ + u32 s_tfree __packed2__; /* total number of free zones */ u16 s_tinode; /* total number of free inodes */ u16 s_interleave_m; /* interleave factor */ u16 s_interleave_n; @@ -215,13 +213,6 @@ u32 s_unique; /* zero, not used */ }; -/* Coherent free list block on disk */ -struct coh_freelist_chunk { - u16 fl_nfree; /* number of free blocks in fl_free, <= COH_NICFREE] */ - u32 fl_free[COH_NICFREE] __packed2__; -}; - - /* SystemV/Coherent inode data on disk */ struct sysv_inode { @@ -237,8 +228,6 @@ * then 1 triple indirection block. * Then maybe a "file generation number" ?? */ - /* devices */ - dev_t i_rdev; /* named pipes on Coherent */ struct { char p_addp[30]; @@ -300,9 +289,12 @@ } /* Admissible values for i_nlink: 0.._LINK_MAX */ -#define XENIX_LINK_MAX 126 /* ?? */ -#define SYSV_LINK_MAX 126 /* 127? 251? */ -#define COH_LINK_MAX 10000 /* max number of hard links to an inode */ +enum { + XENIX_LINK_MAX = 126, /* ?? */ + SYSV_LINK_MAX = 126, /* 127? 251? */ + V7_LINK_MAX = 126, /* ?? */ + COH_LINK_MAX = 10000, +}; /* The number of inodes per block is sb->sv_inodes_per_block = block_size / sizeof(struct sysv_inode) */ @@ -325,12 +317,16 @@ /* Operations */ /* ========== */ - /* identify the FS in memory */ -#define FSTYPE_XENIX 1 -#define FSTYPE_SYSV4 2 -#define FSTYPE_SYSV2 3 -#define FSTYPE_COH 4 +enum { + FSTYPE_NONE = 0, + FSTYPE_XENIX, + FSTYPE_SYSV4, + FSTYPE_SYSV2, + FSTYPE_COH, + FSTYPE_V7, + FSTYPE_END, +}; #define SYSV_MAGIC_BASE 0x012FF7B3 @@ -341,55 +337,112 @@ #ifdef __KERNEL__ -/* sv_get_hash_table(sb,dev,block) is equivalent to get_hash_table(dev,block,block_size) */ -static inline struct buffer_head * -sv_get_hash_table (struct super_block *sb, kdev_t dev, unsigned int block) -{ - return get_hash_table (dev, block + sb->sv_block_base, sb->sv_block_size); -} - -/* sv_getblk(sb,dev,block) is equivalent to getblk(dev,block,block_size) */ -static inline struct buffer_head * -sv_getblk (struct super_block *sb, kdev_t dev, unsigned int block) -{ - return getblk (dev, block + sb->sv_block_base, sb->sv_block_size); -} - -/* sv_bread(sb,dev,block) is equivalent to bread(dev,block,block_size) */ -static inline struct buffer_head * -sv_bread (struct super_block *sb, kdev_t dev, unsigned int block) -{ - return bread (dev, block + sb->sv_block_base, sb->sv_block_size); -} - +enum { + BYTESEX_LE, + BYTESEX_PDP, + BYTESEX_BE, +}; /* * Function prototypes */ -extern struct inode * sysv_new_inode(const struct inode * dir); -extern void sysv_free_inode(struct inode * inode); -extern unsigned long sysv_count_free_inodes(struct super_block *sb); -extern int sysv_new_block(struct super_block * sb); -extern void sysv_free_block(struct super_block * sb, unsigned int block); -extern unsigned long sysv_count_free_blocks(struct super_block *sb); - -extern struct buffer_head * sysv_file_bread(struct inode *, int, int); +extern struct inode * sysv_new_inode(const struct inode *, mode_t); +extern void sysv_free_inode(struct inode *); +extern unsigned long sysv_count_free_inodes(struct super_block *); +extern u32 sysv_new_block(struct super_block *); +extern void sysv_free_block(struct super_block *, u32); +extern unsigned long sysv_count_free_blocks(struct super_block *); extern void sysv_truncate(struct inode *); + extern void sysv_write_inode(struct inode *, int); extern int sysv_sync_inode(struct inode *); extern int sysv_sync_file(struct file *, struct dentry *, int); extern int sysv_notify_change(struct dentry *, struct iattr *); +extern void sysv_set_inode(struct inode *, dev_t); + +extern struct sysv_dir_entry *sysv_find_entry(struct dentry*, struct page**); +extern int sysv_add_link(struct dentry*, struct inode*); +extern int sysv_delete_entry(struct sysv_dir_entry*, struct page*); +extern int sysv_make_empty(struct inode*, struct inode*); +extern int sysv_empty_dir(struct inode*); +extern void sysv_set_link(struct sysv_dir_entry*, struct page*, struct inode*); +extern struct sysv_dir_entry *sysv_dotdot(struct inode*, struct page**); +extern ino_t sysv_inode_by_name(struct dentry*); extern struct inode_operations sysv_file_inode_operations; -extern struct inode_operations sysv_symlink_inode_operations; extern struct inode_operations sysv_dir_inode_operations; extern struct file_operations sysv_file_operations; extern struct file_operations sysv_dir_operations; extern struct address_space_operations sysv_aops; +extern struct super_operations sysv_sops; +extern struct dentry_operations sysv_dentry_operations; + +extern struct sysv_inode *sysv_raw_inode(struct super_block *, unsigned, struct buffer_head **); + +static inline void dirty_sb(struct super_block *sb) +{ + mark_buffer_dirty(sb->sv_bh1); + if (sb->sv_bh1 != sb->sv_bh2) + mark_buffer_dirty(sb->sv_bh2); + sb->s_dirt = 1; +} + +static inline u32 fs32_to_cpu(struct super_block *sb, u32 n) +{ + if (sb->sv_bytesex == BYTESEX_PDP) + return PDP_swab(n); + else if (sb->sv_bytesex == BYTESEX_LE) + return le32_to_cpu(n); + else + return be32_to_cpu(n); +} + +static inline u32 cpu_to_fs32(struct super_block *sb, u32 n) +{ + if (sb->sv_bytesex == BYTESEX_PDP) + return PDP_swab(n); + else if (sb->sv_bytesex == BYTESEX_LE) + return cpu_to_le32(n); + else + return cpu_to_be32(n); +} + +static inline u32 fs32_add(struct super_block *sb, u32 *n, int d) +{ + if (sb->sv_bytesex == BYTESEX_PDP) + return *n = PDP_swab(PDP_swab(*n)+d); + else if (sb->sv_bytesex == BYTESEX_LE) + return *n = cpu_to_le32(le32_to_cpu(*n)+d); + else + return *n = cpu_to_be32(be32_to_cpu(*n)+d); +} + +static inline u16 fs16_to_cpu(struct super_block *sb, u16 n) +{ + if (sb->sv_bytesex != BYTESEX_BE) + return le16_to_cpu(n); + else + return be16_to_cpu(n); +} + +static inline u16 cpu_to_fs16(struct super_block *sb, u16 n) +{ + if (sb->sv_bytesex != BYTESEX_BE) + return cpu_to_le16(n); + else + return cpu_to_be16(n); +} + +static inline u16 fs16_add(struct super_block *sb, u16 *n, int d) +{ + if (sb->sv_bytesex != BYTESEX_BE) + return *n = cpu_to_le16(le16_to_cpu(*n)+d); + else + return *n = cpu_to_be16(be16_to_cpu(*n)+d); +} #endif /* __KERNEL__ */ #endif - diff -u --recursive --new-file v2.4.5/linux/include/linux/sysv_fs_i.h linux/include/linux/sysv_fs_i.h --- v2.4.5/linux/include/linux/sysv_fs_i.h Sun Sep 13 10:27:07 1998 +++ linux/include/linux/sysv_fs_i.h Mon Jul 2 14:03:04 2001 @@ -2,7 +2,7 @@ #define _SYSV_FS_I /* - * SystemV/Coherent FS inode data in memory + * SystemV/V7/Coherent FS inode data in memory */ struct sysv_inode_info { u32 i_data[10+1+1+1]; /* zone numbers: max. 10 data blocks, diff -u --recursive --new-file v2.4.5/linux/include/linux/sysv_fs_sb.h linux/include/linux/sysv_fs_sb.h --- v2.4.5/linux/include/linux/sysv_fs_sb.h Sun Sep 13 10:27:07 1998 +++ linux/include/linux/sysv_fs_sb.h Mon Jul 2 14:03:04 2001 @@ -2,8 +2,8 @@ #define _SYSV_FS_SB /* - * SystemV/Coherent super-block data in memory - * The SystemV/Coherent superblock contains dynamic data (it gets modified + * SystemV/V7/Coherent super-block data in memory + * The SystemV/V7/Coherent superblock contains dynamic data (it gets modified * while the system is running). This is in contrast to the Minix and Berkeley * filesystems (where the superblock is never modified). This affects the * sync() operation: we must keep the superblock in a disk buffer and use this @@ -12,12 +12,7 @@ struct sysv_sb_info { int s_type; /* file system type: FSTYPE_{XENIX|SYSV|COH} */ - unsigned int s_block_size; /* zone size, = 512 or = 1024 */ - unsigned int s_block_size_1; /* block_size - 1 */ - unsigned int s_block_size_bits; /* log2(block_size) */ - unsigned int s_block_size_inc_bits; /* log2(block_size/BLOCK_SIZE) if >0 */ - unsigned int s_block_size_dec_bits; /* log2(BLOCK_SIZE/block_size) if >0 */ - char s_convert; /* flag whether byte ordering requires conversion */ + char s_bytesex; /* bytesex (le/be/pdp) */ char s_kludge_symlinks; /* flag whether symlinks have a kludgey mode */ char s_truncate; /* if 1: names > SYSV_NAMELEN chars are truncated */ /* if 0: they are disallowed (ENAMETOOLONG) */ @@ -26,19 +21,8 @@ unsigned int s_inodes_per_block_1; /* inodes_per_block - 1 */ unsigned int s_inodes_per_block_bits; /* log2(inodes_per_block) */ unsigned int s_ind_per_block; /* number of indirections per block */ - unsigned int s_ind_per_block_1; /* ind_per_block - 1 */ unsigned int s_ind_per_block_bits; /* log2(ind_per_block) */ unsigned int s_ind_per_block_2; /* ind_per_block ^ 2 */ - unsigned int s_ind_per_block_2_1; /* ind_per_block ^ 2 - 1 */ - unsigned int s_ind_per_block_2_bits; /* log2(ind_per_block^2) */ - unsigned int s_ind_per_block_3; /* ind_per_block ^ 3 */ - unsigned int s_ind_per_block_block_size_1; /* ind_per_block*block_size - 1 */ - unsigned int s_ind_per_block_block_size_bits; /* log2(ind_per_block*block_size) */ - unsigned int s_ind_per_block_2_block_size_1; /* ind_per_block^2 * block_size - 1 */ - unsigned int s_ind_per_block_2_block_size_bits; /* log2(ind_per_block^2 * block_size) */ - unsigned int s_ind0_size; /* 10 * block_size */ - unsigned int s_ind1_size; /* (10 + ipb) * block_size */ - unsigned int s_ind2_size; /* (10 + ipb + ipb^2) * block_size */ unsigned int s_toobig_block; /* 10 + ipb + ipb^2 + ipb^3 */ unsigned int s_block_base; /* physical block number of block 0 */ unsigned short s_fic_size; /* free inode cache size, NICINOD */ @@ -53,9 +37,9 @@ u16 *s_sb_fic_count; /* pointer to s_sbd->s_ninode */ u16 *s_sb_fic_inodes; /* pointer to s_sbd->s_inode */ u16 *s_sb_total_free_inodes; /* pointer to s_sbd->s_tinode */ - u16 *s_sb_flc_count; /* pointer to s_sbd->s_nfree */ - u32 *s_sb_flc_blocks; /* pointer to s_sbd->s_free */ - u32 *s_sb_total_free_blocks;/* pointer to s_sbd->s_tfree */ + u16 *s_bcache_count; /* pointer to s_sbd->s_nfree */ + u32 *s_bcache; /* pointer to s_sbd->s_free */ + u32 *s_free_blocks; /* pointer to s_sbd->s_tfree */ u32 *s_sb_time; /* pointer to s_sbd->s_time */ u32 *s_sb_state; /* pointer to s_sbd->s_state, only FSTYPE_SYSV */ /* We keep those superblock entities that don't change here; @@ -65,17 +49,13 @@ u32 s_ninodes; /* total number of inodes */ u32 s_ndatazones; /* total number of data zones */ u32 s_nzones; /* same as s_sbd->s_fsize */ + u16 s_namelen; /* max length of dir entry */ }; -/* The fields s_ind_per_block_2_1, s_toobig_block are currently unused. */ +/* The field s_toobig_block is currently unused. */ /* sv_ == u.sysv_sb.s_ */ #define sv_type u.sysv_sb.s_type -#define sv_block_size u.sysv_sb.s_block_size -#define sv_block_size_1 u.sysv_sb.s_block_size_1 -#define sv_block_size_bits u.sysv_sb.s_block_size_bits -#define sv_block_size_inc_bits u.sysv_sb.s_block_size_inc_bits -#define sv_block_size_dec_bits u.sysv_sb.s_block_size_dec_bits -#define sv_convert u.sysv_sb.s_convert +#define sv_bytesex u.sysv_sb.s_bytesex #define sv_kludge_symlinks u.sysv_sb.s_kludge_symlinks #define sv_truncate u.sysv_sb.s_truncate #define sv_link_max u.sysv_sb.s_link_max @@ -83,19 +63,8 @@ #define sv_inodes_per_block_1 u.sysv_sb.s_inodes_per_block_1 #define sv_inodes_per_block_bits u.sysv_sb.s_inodes_per_block_bits #define sv_ind_per_block u.sysv_sb.s_ind_per_block -#define sv_ind_per_block_1 u.sysv_sb.s_ind_per_block_1 #define sv_ind_per_block_bits u.sysv_sb.s_ind_per_block_bits #define sv_ind_per_block_2 u.sysv_sb.s_ind_per_block_2 -#define sv_ind_per_block_2_1 u.sysv_sb.s_ind_per_block_2_1 -#define sv_ind_per_block_2_bits u.sysv_sb.s_ind_per_block_2_bits -#define sv_ind_per_block_3 u.sysv_sb.s_ind_per_block_3 -#define sv_ind_per_block_block_size_1 u.sysv_sb.s_ind_per_block_block_size_1 -#define sv_ind_per_block_block_size_bits u.sysv_sb.s_ind_per_block_block_size_bits -#define sv_ind_per_block_2_block_size_1 u.sysv_sb.s_ind_per_block_2_block_size_1 -#define sv_ind_per_block_2_block_size_bits u.sysv_sb.s_ind_per_block_2_block_size_bits -#define sv_ind0_size u.sysv_sb.s_ind0_size -#define sv_ind1_size u.sysv_sb.s_ind1_size -#define sv_ind2_size u.sysv_sb.s_ind2_size #define sv_toobig_block u.sysv_sb.s_toobig_block #define sv_block_base u.sysv_sb.s_block_base #define sv_fic_size u.sysv_sb.s_fic_size @@ -107,9 +76,9 @@ #define sv_sb_fic_count u.sysv_sb.s_sb_fic_count #define sv_sb_fic_inodes u.sysv_sb.s_sb_fic_inodes #define sv_sb_total_free_inodes u.sysv_sb.s_sb_total_free_inodes -#define sv_sb_flc_count u.sysv_sb.s_sb_flc_count -#define sv_sb_flc_blocks u.sysv_sb.s_sb_flc_blocks -#define sv_sb_total_free_blocks u.sysv_sb.s_sb_total_free_blocks +#define sv_bcache_count u.sysv_sb.s_bcache_count +#define sv_bcache u.sysv_sb.s_bcache +#define sv_free_blocks u.sysv_sb.s_free_blocks #define sv_sb_time u.sysv_sb.s_sb_time #define sv_sb_state u.sysv_sb.s_sb_state #define sv_firstinodezone u.sysv_sb.s_firstinodezone @@ -117,6 +86,6 @@ #define sv_ninodes u.sysv_sb.s_ninodes #define sv_ndatazones u.sysv_sb.s_ndatazones #define sv_nzones u.sysv_sb.s_nzones +#define sv_namelen u.sysv_sb.s_namelen #endif - diff -u --recursive --new-file v2.4.5/linux/include/linux/udf_167.h linux/include/linux/udf_167.h --- v2.4.5/linux/include/linux/udf_167.h Mon Dec 11 13:27:05 2000 +++ linux/include/linux/udf_167.h Mon Jun 11 19:15:27 2001 @@ -31,7 +31,7 @@ * CONTACTS * E-mail regarding any portion of the Linux UDF file system should be * directed to the development team mailing list (run by majordomo): - * linux_udf@hootie.lvld.hp.com + * linux_udf@hpesjro.fc.hp.com * * COPYRIGHT * This file is distributed under the terms of the GNU General Public diff -u --recursive --new-file v2.4.5/linux/include/linux/udf_fs.h linux/include/linux/udf_fs.h --- v2.4.5/linux/include/linux/udf_fs.h Mon Jan 1 09:57:08 2001 +++ linux/include/linux/udf_fs.h Mon Jul 2 14:10:02 2001 @@ -16,7 +16,7 @@ * CONTACTS * E-mail regarding any portion of the Linux UDF file system should be * directed to the development team mailing list (run by majordomo): - * linux_udf@hootie.lvld.hp.com + * linux_udf@hpesjro.fc.hp.com * * COPYRIGHT * This file is distributed under the terms of the GNU General Public @@ -35,10 +35,20 @@ #define _LINUX_UDF_FS_H #define UDF_PREALLOCATE -#define UDF_DEFAULT_PREALLOC_BLOCKS 8 +#define UDF_DEFAULT_PREALLOC_BLOCKS 8 -#define UDFFS_DATE "2000/02/29" -#define UDFFS_VERSION "0.9.1" +#define UDFFS_DATE "2001/06/13" +#define UDFFS_VERSION "0.9.4.1" + +#if !defined(UDFFS_RW) + +#if defined(CONFIG_UDF_RW) +#define UDFFS_RW 1 +#else /* !defined(CONFIG_UDF_RW) */ +#define UDFFS_RW 0 +#endif /* defined(CONFIG_UDF_RW) */ + +#endif /* !defined(UDFFS_RW) */ #define UDFFS_DEBUG diff -u --recursive --new-file v2.4.5/linux/include/linux/udf_fs_i.h linux/include/linux/udf_fs_i.h --- v2.4.5/linux/include/linux/udf_fs_i.h Thu Mar 2 11:17:32 2000 +++ linux/include/linux/udf_fs_i.h Mon Jul 2 14:10:02 2001 @@ -6,7 +6,7 @@ * CONTACTS * E-mail regarding any portion of the Linux UDF file system should be * directed to the development team mailing list (run by majordomo): - * linux_udf@hootie.lvld.hp.com + * linux_udf@hpesjro.fc.hp.com * * COPYRIGHT * This file is distributed under the terms of the GNU General Public @@ -30,14 +30,16 @@ struct udf_inode_info { - long i_uatime; long i_umtime; long i_uctime; + long i_crtime; + long i_ucrtime; /* Physical address of inode */ lb_addr i_location; __u64 i_unique; __u32 i_lenEAttr; __u32 i_lenAlloc; + __u64 i_lenExtents; __u32 i_next_alloc_block; __u32 i_next_alloc_goal; unsigned i_alloc_type : 3; @@ -54,5 +56,6 @@ #define UDF_GETEASIZE _IOR('l', 0x40, int) #define UDF_GETEABLOCK _IOR('l', 0x41, void *) #define UDF_GETVOLIDENT _IOR('l', 0x42, void *) +#define UDF_RELOCATE_BLOCKS _IOWR('l', 0x43, long) #endif /* !defined(_LINUX_UDF_FS_I_H) */ diff -u --recursive --new-file v2.4.5/linux/include/linux/udf_fs_sb.h linux/include/linux/udf_fs_sb.h --- v2.4.5/linux/include/linux/udf_fs_sb.h Mon Mar 20 08:17:43 2000 +++ linux/include/linux/udf_fs_sb.h Tue Jul 3 15:42:52 2001 @@ -6,7 +6,7 @@ * CONTACTS * E-mail regarding any portion of the Linux UDF file system should be * directed to the development team mailing list (run by majordomo): - * linux_udf@hootie.lvld.hp.com + * linux_udf@hpesjro.fc.hp.com * * COPYRIGHT * This file is distributed under the terms of the GNU General Public @@ -18,6 +18,10 @@ #if !defined(_LINUX_UDF_FS_SB_H) #define _LINUX_UDF_FS_SB_H +#ifndef LINUX_VERSION_CODE +#include +#endif + #pragma pack(1) #define UDF_MAX_BLOCK_LOADED 8 @@ -29,16 +33,8 @@ struct udf_sparing_data { - __u32 s_spar_loc[4]; - __u8 s_spar_pshift; - __u8 s_spar_indexsize; - __u32 *s_spar_map; - union - { - __u8 *s_spar_remap8; - __u16 *s_spar_remap16; - __u32 *s_spar_remap32; - } s_spar_remap; + __u16 s_packet_len; + struct buffer_head *s_spar_map[4]; }; struct udf_virtual_data @@ -47,18 +43,26 @@ __u16 s_start_offset; }; +struct udf_bitmap +{ + __u32 s_extLength; + __u32 s_extPosition; + __u16 s_nr_groups; + struct buffer_head **s_block_bitmap; +}; + struct udf_part_map { union { - __u32 bitmap; - struct inode *table; - } s_uspace; + struct udf_bitmap *s_bitmap; + struct inode *s_table; + } s_uspace; union { - __u32 bitmap; - struct inode *table; - } s_fspace; + struct udf_bitmap *s_bitmap; + struct inode *s_table; + } s_fspace; __u32 s_partition_root; __u32 s_partition_len; __u16 s_partition_type; @@ -77,43 +81,42 @@ struct udf_sb_info { - struct udf_part_map *s_partmaps; - __u8 s_volident[32]; + struct udf_part_map *s_partmaps; + __u8 s_volident[32]; /* Overall info */ - __u16 s_partitions; - __u16 s_partition; + __u16 s_partitions; + __u16 s_partition; /* Sector headers */ - __u32 s_session; - __u32 s_anchor[4]; - __u32 s_lastblock; - - struct buffer_head *s_lvidbh; - - __u16 s_loaded_block_bitmaps; - __u32 s_block_bitmap_number[UDF_MAX_BLOCK_LOADED]; - struct buffer_head *s_block_bitmap[UDF_MAX_BLOCK_LOADED]; + __u32 s_session; + __u32 s_anchor[4]; + __u32 s_lastblock; + + struct buffer_head *s_lvidbh; /* Default permissions */ - mode_t s_umask; - gid_t s_gid; - uid_t s_uid; + mode_t s_umask; + gid_t s_gid; + uid_t s_uid; /* Root Info */ - time_t s_recordtime; + time_t s_recordtime; /* Fileset Info */ - __u16 s_serialnum; + __u16 s_serialnum; /* highest UDF revision we have recorded to this media */ - __u16 s_udfrev; + __u16 s_udfrev; /* Miscellaneous flags */ - __u32 s_flags; + __u32 s_flags; + + /* Encoding info */ + struct nls_table *s_nls_map; /* VAT inode */ - struct inode *s_vat; + struct inode *s_vat; }; #endif /* !defined(_LINUX_UDF_FS_SB_H) */ diff -u --recursive --new-file v2.4.5/linux/include/linux/udf_udf.h linux/include/linux/udf_udf.h --- v2.4.5/linux/include/linux/udf_udf.h Mon Dec 11 13:27:05 2000 +++ linux/include/linux/udf_udf.h Mon Jul 2 14:10:02 2001 @@ -10,7 +10,7 @@ * CONTACTS * E-mail regarding any portion of the Linux UDF file system should be * directed to the development team mailing list (run by majordomo): - * linux_udf@hootie.lvld.hp.com + * linux_udf@hpesjro.fc.hp.com * * COPYRIGHT * This file is distributed under the terms of the GNU General Public @@ -161,6 +161,10 @@ Uint8 impUse[0]; Uint32 vatEntry[0]; }; + +/* ----------- 2.01 ------------- */ +/* UDF 2.01 6.11 */ +#define FILE_TYPE_REALTIME 0xf9U /* Sparing maps, see UDF 1.5 2.2.11 */ typedef struct { diff -u --recursive --new-file v2.4.5/linux/include/net/bluetooth/bluetooth.h linux/include/net/bluetooth/bluetooth.h --- v2.4.5/linux/include/net/bluetooth/bluetooth.h Wed Dec 31 16:00:00 1969 +++ linux/include/net/bluetooth/bluetooth.h Mon Jun 11 19:15:27 2001 @@ -0,0 +1,82 @@ +/* + BlueZ - Bluetooth protocol stack for Linux + Copyright (C) 2000-2001 Qualcomm Incorporated + + Written 2000,2001 by Maxim Krasnyansky + + 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; + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY + CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, + COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS + SOFTWARE IS DISCLAIMED. +*/ + +/* + * $Id: bluetooth.h,v 1.1 2001/06/01 08:12:11 davem Exp $ + */ + +#ifndef __IF_BLUETOOTH_H +#define __IF_BLUETOOTH_H + +#include +#include + +#define BTPROTO_L2CAP 0 +#define BTPROTO_HCI 1 + +#define SOL_HCI 0 +#define SOL_L2CAP 6 + +typedef struct { + __u8 b0, b1, b2, b3, b4, b5; +} bdaddr_t; + +#define BDADDR_ANY ((bdaddr_t *)"\000\000\000\000\000") + +/* Connection and socket states */ +enum { + BT_CONNECTED = 1, /* Equal to TCP_ESTABLISHED to make net code happy */ + BT_OPEN, + BT_BOUND, + BT_LISTEN, + BT_CONNECT, + BT_CONFIG, + BT_DISCONN, + BT_CLOSED +}; + +/* Copy, swap, convert BD Address */ +static __inline__ int bacmp(bdaddr_t *ba1, bdaddr_t *ba2) +{ + return memcmp(ba1, ba2, sizeof(bdaddr_t)); +} +static __inline__ void bacpy(bdaddr_t *dst, bdaddr_t *src) +{ + memcpy(dst, src, sizeof(bdaddr_t)); +} + +extern void baswap(bdaddr_t *dst, bdaddr_t *src); + +extern char *batostr(bdaddr_t *ba); +extern bdaddr_t *strtoba(char *str); + +/* Endianness conversions */ +#define htobs(a) __cpu_to_le16(a) +#define htobl(a) __cpu_to_le32(a) +#define btohs(a) __le16_to_cpu(a) +#define btohl(a) __le32_to_cpu(a) + +int bterr(__u16 code); + +#endif /* __IF_BLUETOOTH_H */ diff -u --recursive --new-file v2.4.5/linux/include/net/bluetooth/bluez.h linux/include/net/bluetooth/bluez.h --- v2.4.5/linux/include/net/bluetooth/bluez.h Wed Dec 31 16:00:00 1969 +++ linux/include/net/bluetooth/bluez.h Mon Jun 11 19:15:27 2001 @@ -0,0 +1,176 @@ +/* + BlueZ - Bluetooth protocol stack for Linux + Copyright (C) 2000-2001 Qualcomm Incorporated + + Written 2000,2001 by Maxim Krasnyansky + + 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; + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY + CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, + COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS + SOFTWARE IS DISCLAIMED. +*/ + +/* + * $Id: bluez.h,v 1.1 2001/06/01 08:12:11 davem Exp $ + */ + +#ifndef __IF_BLUEZ_H +#define __IF_BLUEZ_H + +#include + +#define BLUEZ_VER "1.0" + +#define BLUEZ_MAX_PROTO 2 + +/* Reserv for core and drivers use */ +#define BLUEZ_SKB_RESERVE 8 + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +/* Debugging */ +#ifdef BLUEZ_DEBUG + +#define HCI_CORE_DEBUG 1 +#define HCI_SOCK_DEBUG 1 +#define HCI_UART_DEBUG 1 +#define HCI_USB_DEBUG 1 +//#define HCI_DATA_DUMP 1 + +#define L2CAP_DEBUG 1 + +#endif /* BLUEZ_DEBUG */ + +extern void bluez_dump(char *pref, __u8 *buf, int count); + +#define INF(fmt, arg...) printk(KERN_INFO fmt "\n" , ## arg) +#define DBG(fmt, arg...) printk(KERN_INFO __FUNCTION__ ": " fmt "\n" , ## arg) +#define ERR(fmt, arg...) printk(KERN_ERR __FUNCTION__ ": " fmt "\n" , ## arg) + +#ifdef HCI_DATA_DUMP +#define DMP(buf, len) bluez_dump(__FUNCTION__, buf, len) +#else +#define DMP(D...) +#endif + +/* ----- Sockets ------ */ +struct bluez_sock_list { + struct sock *head; + rwlock_t lock; +}; + +extern int bluez_sock_register(int proto, struct net_proto_family *ops); +extern int bluez_sock_unregister(int proto); + +extern void bluez_sock_link(struct bluez_sock_list *l, struct sock *s); +extern void bluez_sock_unlink(struct bluez_sock_list *l, struct sock *s); + +/* ----- SKB helpers ----- */ +struct bluez_skb_cb { + int incomming, fragmented; + struct sk_buff_head frags; +}; +#define bluez_cb(skb) ((struct bluez_skb_cb *)(skb->cb)) + +static __inline__ struct sk_buff *bluez_skb_alloc(unsigned int len, int how) +{ + struct sk_buff *skb; + + if ((skb = alloc_skb(len + BLUEZ_SKB_RESERVE, how))) { + bluez_cb(skb)->incomming = 0; + bluez_cb(skb)->fragmented = 0; + skb_reserve(skb, BLUEZ_SKB_RESERVE); + } + return skb; +} + +static __inline__ struct sk_buff *bluez_skb_clone(struct sk_buff *skb, int how) +{ + struct sk_buff *new; + + if ((new = skb_clone(skb, how))) + bluez_cb(new)->fragmented = 0; + return new; +} + +static __inline__ struct sk_buff *bluez_skb_send_alloc(struct sock *sk, unsigned long len, + int nb, int *err) +{ + struct sk_buff *skb; + + if ((skb = sock_alloc_send_skb(sk, len + BLUEZ_SKB_RESERVE, nb, err))) { + bluez_cb(skb)->incomming = 0; + bluez_cb(skb)->fragmented = 0; + skb_reserve(skb, BLUEZ_SKB_RESERVE); + } + + return skb; +} + +static __inline__ int bluez_skb_frags(struct sk_buff *skb) +{ + if (bluez_cb(skb)->fragmented) + return skb_queue_len(&bluez_cb(skb)->frags); + return 0; +} + +static __inline__ void bluez_skb_add_frag(struct sk_buff *skb, struct sk_buff *frag) +{ + if (!bluez_cb(skb)->fragmented) { + skb_queue_head_init(&bluez_cb(skb)->frags); + bluez_cb(skb)->fragmented = 1; + } + __skb_queue_tail(&bluez_cb(skb)->frags, frag); +} + +static __inline__ struct sk_buff *bluez_skb_next_frag(struct sk_buff *skb) +{ + if (bluez_cb(skb)->fragmented) + return skb_peek(&bluez_cb(skb)->frags); + if (skb->next == (void *) skb->list) + return NULL; + return skb->next; +} + +static __inline__ struct sk_buff *bluez_skb_get_frag(struct sk_buff *skb) +{ + if (bluez_cb(skb)->fragmented) + return __skb_dequeue(&bluez_cb(skb)->frags); + return NULL; +} + +static __inline__ void bluez_skb_free(struct sk_buff *skb) +{ + if (bluez_cb(skb)->fragmented) + __skb_queue_purge(&bluez_cb(skb)->frags); + kfree_skb(skb); +} + +static __inline__ void bluez_skb_queue_purge(struct sk_buff_head *q) +{ + struct sk_buff *skb; + + while((skb = skb_dequeue(q))) + bluez_skb_free(skb); +} + +extern int hci_core_init(void); +extern int hci_core_cleanup(void); +extern int hci_sock_init(void); +extern int hci_sock_cleanup(void); + +#endif /* __IF_BLUEZ_H */ diff -u --recursive --new-file v2.4.5/linux/include/net/bluetooth/hci.h linux/include/net/bluetooth/hci.h --- v2.4.5/linux/include/net/bluetooth/hci.h Wed Dec 31 16:00:00 1969 +++ linux/include/net/bluetooth/hci.h Mon Jun 11 19:15:27 2001 @@ -0,0 +1,370 @@ +/* + BlueZ - Bluetooth protocol stack for Linux + Copyright (C) 2000-2001 Qualcomm Incorporated + + Written 2000,2001 by Maxim Krasnyansky + + 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; + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY + CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, + COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS + SOFTWARE IS DISCLAIMED. +*/ + +/* + * $Id: hci.h,v 1.1 2001/06/01 08:12:11 davem Exp $ + */ + +#ifndef __IF_HCI_H +#define __IF_HCI_H + +#include + +/* HCI Packet types */ +#define HCI_COMMAND_PKT 0x01 +#define HCI_ACLDATA_PKT 0x02 +#define HCI_SCODATA_PKT 0x03 +#define HCI_EVENT_PKT 0x04 +#define HCI_UNKNOWN_PKT 0xff + +/* ----- HCI Commands ----- */ +/* OGF & OCF values */ + +/* Informational Parameters */ +#define OGF_INFO_PARAM 0x04 +#define OCF_NOP 0x0000 + +#define OCF_READ_BUFFER_SIZE 0x0005 +typedef struct { + __u8 status; + __u16 acl_mtu; + __u8 sco_mtu; + __u16 acl_max_pkt; + __u16 sco_max_pkt; +} __attribute__ ((packed)) read_buffer_size_rp; + +#define OCF_READ_BD_ADDR 0x0009 +typedef struct { + __u8 status; + bdaddr_t bdaddr; +} __attribute__ ((packed)) read_bd_addr_rp; + +/* Host Controller and Baseband */ +#define OGF_HOST_CTL 0x03 +#define OCF_RESET 0x0003 +#define OCF_WRITE_AUTH_ENABLE 0x0020 + #define AUTH_DISABLED 0x00 + #define AUTH_ENABLED 0x01 + +#define OCF_WRITE_CA_TIMEOUT 0x0016 /* Write_Connection_Accept_Timeout */ +#define OCF_WRITE_PG_TIMEOUT 0x0018 /* Write_Page_Timeout */ + +#define OCF_WRITE_SCAN_ENABLE 0x001A + #define SCANS_DISABLED 0x00 + #define IS_ENA_PS_DIS 0x01 /* Inquiry scan enabled Page Scan disabled */ + #define IS_DIS_PS_ENA 0x02 /* Inquiry scan disabled Page Scan enabled */ + #define IS_ENA_PS_ENA 0x03 /* Inquiry scan enabled Page Scan enabled */ + +#define OCF_SET_EVENT_FLT 0x0005 +typedef struct { + __u8 flt_type; + __u8 cond_type; + __u8 condition; +} __attribute__ ((packed)) set_event_flt_cp; +#define SET_EVENT_FLT_CP_SIZE 3 + +/* Filter types */ +#define FLT_CLEAR_ALL 0x00 +#define FLT_INQ_RESULT 0x01 +#define FLT_CONN_SETUP 0x02 + +/* CONN_SETUP Condition types */ +#define CONN_SETUP_ALLOW_ALL 0x00 +#define CONN_SETUP_ALLOW_CLASS 0x01 +#define CONN_SETUP_ALLOW_BDADDR 0x02 + +/* CONN_SETUP Conditions */ +#define CONN_SETUP_AUTO_OFF 0x01 +#define CONN_SETUP_AUTO_ON 0x02 + +/* Link Control */ +#define OGF_LINK_CTL 0x01 +#define OCF_CREATE_CONN 0x0005 +typedef struct { + bdaddr_t bdaddr; + __u16 pkt_type; + __u8 pscan_rep_mode; + __u8 pscan_mode; + __u16 clock_offset; + __u8 role_switch; +} __attribute__ ((packed)) create_conn_cp; +#define CREATE_CONN_CP_SIZE 13 + +#define OCF_ACCEPT_CONN_REQ 0x0009 +typedef struct { + bdaddr_t bdaddr; + __u8 role; +} __attribute__ ((packed)) accept_conn_req_cp; +#define ACCEPT_CONN_REQ_CP_SIZE 7 + +#define OCF_DISCONNECT 0x0006 +typedef struct { + __u16 handle; + __u8 reason; +} __attribute__ ((packed)) disconnect_cp; +#define DISCONNECT_CP_SIZE 3 + +#define OCF_INQUIRY 0x0001 +typedef struct { + __u8 lap[3]; + __u8 lenght; + __u8 num_rsp; +} __attribute__ ((packed)) inquiry_cp; +#define INQUIRY_CP_SIZE 5 + +#define OGF_LINK_POLICY 0x02 /* Link Policy */ + +/* --------- HCI Events --------- */ +#define EVT_INQUIRY_COMPLETE 0x01 + +#define EVT_INQUIRY_RESULT 0x02 +typedef struct { + bdaddr_t bdaddr; + __u8 pscan_rep_mode; + __u8 pscan_period_mode; + __u8 pscan_mode; + __u8 class[3]; + __u16 clock_offset; +} __attribute__ ((packed)) inquiry_info; +#define INQUIRY_INFO_SIZE 14 + +#define EVT_CONN_COMPLETE 0x03 +typedef struct { + __u8 status; + __u16 handle; + bdaddr_t bdaddr; + __u8 link_type; + __u8 encr_mode; +} __attribute__ ((packed)) evt_conn_complete; +#define EVT_CONN_COMPLETE_SIZE 13 + +#define EVT_CONN_REQUEST 0x04 +typedef struct { + bdaddr_t bdaddr; +#if defined (__LITTLE_ENDIAN_BITFIELD) + __u32 class :24; + __u32 type :8; +#else /* (__BIG_ENDIAN_BITFIELD) */ + __u32 type :8; + __u32 class :24; +#endif +} __attribute__ ((packed)) evt_conn_request; +#define EVT_CONN_REQUEST_SIZE 10 + +#define EVT_DISCONN_COMPLETE 0x05 +typedef struct { + __u8 status; + __u16 handle; + __u8 reason; +} __attribute__ ((packed)) evt_disconn_complete; +#define EVT_DISCONN_COMPLETE_SIZE 4 + +#define EVT_CMD_COMPLETE 0x0e +typedef struct { + __u8 ncmd; + __u16 opcode; +} __attribute__ ((packed)) evt_cmd_complete; +#define EVT_CMD_COMPLETE_SIZE 3 + +#define EVT_CMD_STATUS 0x0f +typedef struct { + __u8 status; + __u8 ncmd; + __u16 opcode; +} __attribute__ ((packed)) evt_cmd_status; +#define EVT_CMD_STATUS_SIZE 4 + +#define EVT_NUM_COMP_PKTS 0x13 +typedef struct { + __u8 num_hndl; + /* variable lenght part */ +} __attribute__ ((packed)) evt_num_comp_pkts; +#define EVT_NUM_COMP_PKTS_SIZE 1 + +#define EVT_HCI_DEV_EVENT 0xfd +typedef struct { + __u16 event; + __u16 param; +} __attribute__ ((packed)) evt_hci_dev_event; +#define EVT_HCI_DEV_EVENT_SIZE 4 + +/* -------- HCI Packet structures -------- */ +#define HCI_TYPE_LEN 1 + +typedef struct { + __u16 opcode; /* OCF & OGF */ + __u8 plen; +} __attribute__ ((packed)) hci_command_hdr; +#define HCI_COMMAND_HDR_SIZE 3 + +typedef struct { + __u8 evt; + __u8 plen; +} __attribute__ ((packed)) hci_event_hdr; +#define HCI_EVENT_HDR_SIZE 2 + +typedef struct { + __u16 handle; /* Handle & Flags(PB, BC) */ + __u16 dlen; +} __attribute__ ((packed)) hci_acl_hdr; +#define HCI_ACL_HDR_SIZE 4 + +typedef struct { + __u16 handle; + __u8 dlen; +} __attribute__ ((packed)) hci_sco_hdr; +#define HCI_SCO_HDR_SIZE 3 + +/* Command opcode pack/unpack */ +#define cmd_opcode_pack(ocf, ogf) (__u16)((ocf & 0x03ff)|(ogf << 10)) +#define cmd_opcode_ogf(op) (op >> 10) +#define cmd_opcode_ocf(op) (op & 0x03ff) + +/* ACL handle and flags pack/unpack */ +#define acl_handle_pack(h, f) (__u16)((h & 0x0fff)|(f << 12)) +#define acl_handle(h) (h & 0x0fff) +#define acl_flags(h) (h >> 12) + +/* ACL flags */ +#define ACL_CONT 0x0001 +#define ACL_START 0x0002 +#define ACL_ACTIVE_BCAST 0x0010 +#define ACL_PICO_BCAST 0x0020 + +/* Max frame size */ +#define HCI_MAX_FRAME 4096 + +/* HCI device types */ +#define HCI_UART 0 +#define HCI_USB 1 +#define HCI_EMU 2 + +/* HCI device modes */ +#define HCI_NORMAL 0x0001 +#define HCI_RAW 0x0002 +#define HCI_MODE_MASK (HCI_NORMAL | HCI_RAW) +#define HCI_SOCK 0x1000 + +/* HCI device states */ +#define HCI_INIT 0x0010 +#define HCI_UP 0x0020 +#define HCI_RUNNING 0x0040 + +/* HCI device flags */ +#define HCI_PSCAN 0x0100 +#define HCI_ISCAN 0x0200 +#define HCI_AUTH 0x0400 + +/* HCI Packet types */ +#define HCI_DM1 0x0008 +#define HCI_DM3 0x0400 +#define HCI_DM5 0x4000 +#define HCI_DH1 0x0010 +#define HCI_DH3 0x0800 +#define HCI_DH5 0x8000 + +/* HCI Ioctl defines */ +#define HCIDEVUP _IOW('H', 201, int) +#define HCIDEVDOWN _IOW('H', 202, int) +#define HCIDEVRESET _IOW('H', 203, int) +#define HCIRESETSTAT _IOW('H', 204, int) +#define HCIGETINFO _IOR('H', 205, int) +#define HCIGETDEVLIST _IOR('H', 206, int) +#define HCISETRAW _IOW('H', 207, int) +#define HCISETSCAN _IOW('H', 208, int) +#define HCISETAUTH _IOW('H', 209, int) +#define HCIINQUIRY _IOWR('H', 210, int) + +/* HCI Socket options */ +#define HCI_DATA_DIR 0x0001 +#define HCI_FILTER 0x0002 + +/* HCI CMSG types */ +#define HCI_CMSG_DIR 0x0001 + +struct sockaddr_hci { + sa_family_t hci_family; + unsigned short hci_dev; +}; +#define HCI_DEV_NONE 0xffff + +struct hci_dev_req { + __u16 dev_id; + __u32 dev_opt; +}; + +struct hci_dev_list_req { + __u16 dev_num; + struct hci_dev_req dev_req[0]; /* hci_dev_req structures */ +}; + +struct hci_inquiry_req { + __u16 dev_id; + __u16 flags; + __u8 lap[3]; + __u8 length; + __u8 num_rsp; +}; +#define IREQ_CACHE_FLUSH 0x0001 + +struct hci_dev_stats { + __u32 err_rx; + __u32 err_tx; + __u32 cmd_tx; + __u32 evt_rx; + __u32 acl_tx; + __u32 acl_rx; + __u32 sco_tx; + __u32 sco_rx; + __u32 byte_rx; + __u32 byte_tx; +}; + +struct hci_dev_info { + __u16 dev_id; + char name[8]; + + __u32 flags; + __u8 type; + + __u16 acl_mtu; + __u16 acl_max; + __u16 sco_mtu; + __u16 sco_max; + + bdaddr_t bdaddr; + + struct hci_dev_stats stat; +}; + +/* Number of devices */ +#define HCI_MAX_DEV 8 + +/* HCI dev events */ +#define HCI_DEV_REG 1 +#define HCI_DEV_UNREG 2 +#define HCI_DEV_UP 3 +#define HCI_DEV_DOWN 4 + +#endif /* __IF_HCI_H */ diff -u --recursive --new-file v2.4.5/linux/include/net/bluetooth/hci_core.h linux/include/net/bluetooth/hci_core.h --- v2.4.5/linux/include/net/bluetooth/hci_core.h Wed Dec 31 16:00:00 1969 +++ linux/include/net/bluetooth/hci_core.h Mon Jun 11 19:15:27 2001 @@ -0,0 +1,343 @@ +/* + BlueZ - Bluetooth protocol stack for Linux + Copyright (C) 2000-2001 Qualcomm Incorporated + + Written 2000,2001 by Maxim Krasnyansky + + 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; + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY + CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, + COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS + SOFTWARE IS DISCLAIMED. +*/ + +/* + * $Id: hci_core.h,v 1.1 2001/06/01 08:12:11 davem Exp $ + */ + +#ifndef __IF_HCI_CORE_H +#define __IF_HCI_CORE_H + +#include "hci.h" + +/* HCI upper protocols */ +#define HCI_MAX_PROTO 1 +#define HCI_PROTO_L2CAP 0 + +#define HCI_INIT_TIMEOUT (HZ * 10) + +/* ----- Inquiry cache ----- */ +#define INQUIRY_CACHE_AGE_MAX (HZ*5) // 5 seconds +#define INQUIRY_ENTRY_AGE_MAX (HZ*60) // 60 seconds + +struct inquiry_entry { + struct inquiry_entry *next; + __u32 timestamp; + inquiry_info info; +}; + +struct inquiry_cache { + spinlock_t lock; + __u32 timestamp; + struct inquiry_entry *list; +}; + +static __inline__ void inquiry_cache_init(struct inquiry_cache *cache) +{ + spin_lock_init(&cache->lock); + cache->list = NULL; +} + +static __inline__ void inquiry_cache_lock(struct inquiry_cache *cache) +{ + spin_lock(&cache->lock); +} + +static __inline__ void inquiry_cache_unlock(struct inquiry_cache *cache) +{ + spin_unlock(&cache->lock); +} + +static __inline__ void inquiry_cache_lock_bh(struct inquiry_cache *cache) +{ + spin_lock_bh(&cache->lock); +} + +static __inline__ void inquiry_cache_unlock_bh(struct inquiry_cache *cache) +{ + spin_unlock_bh(&cache->lock); +} + +static __inline__ long inquiry_cache_age(struct inquiry_cache *cache) +{ + return jiffies - cache->timestamp; +} + +static __inline__ long inquiry_entry_age(struct inquiry_entry *e) +{ + return jiffies - e->timestamp; +} +extern void inquiry_cache_flush(struct inquiry_cache *cache); + +/* ----- Connection hash ----- */ +#define HCI_MAX_CONN 10 + +/* FIXME: + * We assume that handle is a number - 0 ... HCI_MAX_CONN. + */ +struct conn_hash { + spinlock_t lock; + unsigned int num; + void *conn[HCI_MAX_CONN]; +}; + +static __inline__ void conn_hash_init(struct conn_hash *h) +{ + memset(h, 0, sizeof(struct conn_hash)); + spin_lock_init(&h->lock); +} + +static __inline__ void conn_hash_lock(struct conn_hash *h) +{ + spin_lock(&h->lock); +} + +static __inline__ void conn_hash_unlock(struct conn_hash *h) +{ + spin_unlock(&h->lock); +} + +static __inline__ void *__conn_hash_add(struct conn_hash *h, __u16 handle, void *conn) +{ + if (!h->conn[handle]) { + h->conn[handle] = conn; + h->num++; + return conn; + } else + return NULL; +} + +static __inline__ void *conn_hash_add(struct conn_hash *h, __u16 handle, void *conn) +{ + if (handle >= HCI_MAX_CONN) + return NULL; + + conn_hash_lock(h); + conn = __conn_hash_add(h, handle, conn); + conn_hash_unlock(h); + + return conn; +} + +static __inline__ void *__conn_hash_del(struct conn_hash *h, __u16 handle) +{ + void *conn = h->conn[handle]; + + if (conn) { + h->conn[handle] = NULL; + h->num--; + return conn; + } else + return NULL; +} + +static __inline__ void *conn_hash_del(struct conn_hash *h, __u16 handle) +{ + void *conn; + + if (handle >= HCI_MAX_CONN) + return NULL; + conn_hash_lock(h); + conn = __conn_hash_del(h, handle); + conn_hash_unlock(h); + + return conn; +} + +static __inline__ void *__conn_hash_lookup(struct conn_hash *h, __u16 handle) +{ + return h->conn[handle]; +} + +static __inline__ void *conn_hash_lookup(struct conn_hash *h, __u16 handle) +{ + void *conn; + + if (handle >= HCI_MAX_CONN) + return NULL; + + conn_hash_lock(h); + conn = __conn_hash_lookup(h, handle); + conn_hash_unlock(h); + + return conn; +} + +struct hci_dev; + +/* ----- HCI Connections ----- */ +struct hci_conn { + bdaddr_t dst; + __u16 handle; + + unsigned int acl_sent; + unsigned int sco_sent; + + struct hci_dev *hdev; + void *l2cap_data; + void *priv; + + struct sk_buff_head acl_q; + struct sk_buff_head sco_q; +}; + +/* ----- HCI Devices ----- */ +struct hci_dev { + atomic_t refcnt; + + char name[8]; + __u32 flags; + __u16 id; + __u8 type; + bdaddr_t bdaddr; + + atomic_t cmd_cnt; + unsigned int acl_cnt; + unsigned int sco_cnt; + + unsigned int acl_mtu; + unsigned int sco_mtu; + unsigned int acl_max; + unsigned int sco_max; + + void *driver_data; + void *l2cap_data; + void *priv; + + struct tasklet_struct cmd_task; + struct tasklet_struct rx_task; + struct tasklet_struct tx_task; + + struct sk_buff_head rx_q; + struct sk_buff_head raw_q; + struct sk_buff_head cmd_q; + struct sk_buff *cmd_sent; + + struct semaphore req_lock; + wait_queue_head_t req_wait_q; + __u32 req_status; + __u32 req_result; + + struct inquiry_cache inq_cache; + + struct conn_hash conn_hash; + + struct hci_dev_stats stat; + + int (*open)(struct hci_dev *hdev); + int (*close)(struct hci_dev *hdev); + int (*flush)(struct hci_dev *hdev); + int (*send)(struct sk_buff *skb); +}; + +static __inline__ void hci_dev_hold(struct hci_dev *hdev) +{ + atomic_inc(&hdev->refcnt); +} + +static __inline__ void hci_dev_put(struct hci_dev *hdev) +{ + atomic_dec(&hdev->refcnt); +} + +extern struct hci_dev *hci_dev_get(int index); + +#define SENT_CMD_PARAM(X) (((X->cmd_sent->data) + HCI_COMMAND_HDR_SIZE)) + +extern int hci_register_dev(struct hci_dev *hdev); +extern int hci_unregister_dev(struct hci_dev *hdev); +extern int hci_dev_open(__u16 dev); +extern int hci_dev_close(__u16 dev); +extern int hci_dev_reset(__u16 dev); +extern int hci_dev_reset_stat(__u16 dev); +extern int hci_dev_info(unsigned long arg); +extern int hci_dev_list(unsigned long arg); +extern int hci_dev_setscan(unsigned long arg); +extern int hci_dev_setauth(unsigned long arg); +extern int hci_inquiry(unsigned long arg); + +extern __u32 hci_dev_setmode(struct hci_dev *hdev, __u32 mode); +extern __u32 hci_dev_getmode(struct hci_dev *hdev); + +extern int hci_recv_frame(struct sk_buff *skb); + +/* ----- HCI tasks ----- */ +static __inline__ void hci_sched_cmd(struct hci_dev *hdev) +{ + tasklet_schedule(&hdev->cmd_task); +} + +static __inline__ void hci_sched_rx(struct hci_dev *hdev) +{ + tasklet_schedule(&hdev->rx_task); +} + +static __inline__ void hci_sched_tx(struct hci_dev *hdev) +{ + tasklet_schedule(&hdev->tx_task); +} + +/* ----- HCI protocols ----- */ +struct hci_proto { + char *name; + __u32 id; + __u32 flags; + + void *priv; + + int (*connect_ind) (struct hci_dev *hdev, bdaddr_t *bdaddr); + int (*connect_cfm) (struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 status, struct hci_conn *conn); + int (*disconn_ind) (struct hci_conn *conn, __u8 reason); + int (*recv_acldata) (struct hci_conn *conn, struct sk_buff *skb , __u16 flags); + int (*recv_scodata) (struct hci_conn *conn, struct sk_buff *skb); +}; + +extern int hci_register_proto(struct hci_proto *hproto); +extern int hci_unregister_proto(struct hci_proto *hproto); +extern int hci_register_notifier(struct notifier_block *nb); +extern int hci_unregister_notifier(struct notifier_block *nb); +extern int hci_connect(struct hci_dev * hdev, bdaddr_t * bdaddr); +extern int hci_disconnect(struct hci_conn *conn, __u8 reason); +extern int hci_send_cmd(struct hci_dev *hdev, __u16 ogf, __u16 ocf, __u32 plen, void * param); +extern int hci_send_raw(struct sk_buff *skb); +extern int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags); +extern int hci_send_sco(struct hci_conn *conn, struct sk_buff *skb); + +/* ----- HCI Sockets ----- */ +extern void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb); + +/* HCI info for socket */ +#define hci_pi(sk) ((struct hci_pinfo *) &sk->protinfo) +struct hci_pinfo { + struct hci_dev *hdev; + __u32 cmsg_flags; + __u32 mask; +}; + +/* ----- HCI requests ----- */ +#define HCI_REQ_DONE 0 +#define HCI_REQ_PEND 1 +#define HCI_REQ_CANCELED 2 + +#endif /* __IF_HCI_CORE_H */ diff -u --recursive --new-file v2.4.5/linux/include/net/bluetooth/hci_emu.h linux/include/net/bluetooth/hci_emu.h --- v2.4.5/linux/include/net/bluetooth/hci_emu.h Wed Dec 31 16:00:00 1969 +++ linux/include/net/bluetooth/hci_emu.h Mon Jun 11 19:15:27 2001 @@ -0,0 +1,52 @@ +/* + BlueZ - Bluetooth protocol stack for Linux + Copyright (C) 2000-2001 Qualcomm Incorporated + + Written 2000,2001 by Maxim Krasnyansky + + 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; + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY + CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, + COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS + SOFTWARE IS DISCLAIMED. +*/ + +/* + * $Id: hci_emu.h,v 1.1 2001/06/01 08:12:11 davem Exp $ + */ + +#ifndef __IF_HCI_EMU_H +#define __IF_HCI_EMU_H + +#ifdef __KERNEL__ + +struct hci_emu_struct { + struct hci_dev hdev; + __u32 flags; + wait_queue_head_t read_wait; + struct sk_buff_head readq; + struct fasync_struct *fasync; +}; + +#endif /* __KERNEL__ */ + +#define HCI_EMU_MINOR 250 + +/* Max frame size */ +#define HCI_EMU_MAX_FRAME 4096 + +/* HCI_EMU device flags */ +#define HCI_EMU_FASYNC 0x0010 + +#endif /* __IF_HCI_EMU_H */ diff -u --recursive --new-file v2.4.5/linux/include/net/bluetooth/hci_uart.h linux/include/net/bluetooth/hci_uart.h --- v2.4.5/linux/include/net/bluetooth/hci_uart.h Wed Dec 31 16:00:00 1969 +++ linux/include/net/bluetooth/hci_uart.h Mon Jun 11 19:15:27 2001 @@ -0,0 +1,60 @@ +/* + BlueZ - Bluetooth protocol stack for Linux + Copyright (C) 2000-2001 Qualcomm Incorporated + + Written 2000,2001 by Maxim Krasnyansky + + 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; + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY + CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, + COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS + SOFTWARE IS DISCLAIMED. +*/ + +/* + * $Id: hci_uart.h,v 1.1 2001/06/01 08:12:11 davem Exp $ + */ + +#define HCI_MAX_READ 2048 + +#ifdef __KERNEL__ + +#define tty2n_hci(tty) ((struct n_hci *)((tty)->disc_data)) +#define n_hci2tty(n_hci) ((n_hci)->tty) + +struct n_hci { + struct tty_struct *tty; + struct hci_dev hdev; + + struct sk_buff_head txq; + unsigned long tx_state; + + spinlock_t rx_lock; + unsigned long rx_state; + unsigned long rx_count; + struct sk_buff *rx_skb; +}; + +/* Transmit states */ +#define TRANS_SENDING 1 +#define TRANS_WAKEUP 2 + +/* Receiver States */ +#define WAIT_PACKET_TYPE 0 +#define WAIT_EVENT_HDR 1 +#define WAIT_ACL_HDR 2 +#define WAIT_SCO_HDR 3 +#define WAIT_DATA 4 + +#endif /* __KERNEL__ */ diff -u --recursive --new-file v2.4.5/linux/include/net/bluetooth/hci_usb.h linux/include/net/bluetooth/hci_usb.h --- v2.4.5/linux/include/net/bluetooth/hci_usb.h Wed Dec 31 16:00:00 1969 +++ linux/include/net/bluetooth/hci_usb.h Mon Jun 11 19:15:27 2001 @@ -0,0 +1,70 @@ +/* + BlueZ - Bluetooth protocol stack for Linux + Copyright (C) 2000-2001 Qualcomm Incorporated + + Written 2000,2001 by Maxim Krasnyansky + + 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; + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY + CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, + COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS + SOFTWARE IS DISCLAIMED. +*/ + +/* + * $Id: hci_usb.h,v 1.1 2001/06/01 08:12:11 davem Exp $ + */ + +#ifdef __KERNEL__ + +#define HCI_USB_MAX_READ 2048 + +/* Class, SubClass, and Protocol codes that describe a Bluetooth device */ +#define HCI_DEV_CLASS 0xe0 /* Wireless class */ +#define HCI_DEV_SUBCLASS 0x01 /* RF subclass */ +#define HCI_DEV_PROTOCOL 0x01 /* Bluetooth programming protocol */ + +#define HCI_CTRL_REQ 0x20 + +struct hci_usb { + struct usb_device *udev; + + devrequest dev_req; + struct urb *ctrl_urb; + struct urb *intr_urb; + struct urb *read_urb; + struct urb *write_urb; + + __u8 *read_buf; + __u8 *intr_buf; + struct sk_buff *intr_skb; + int intr_count; + + __u8 bulk_out_ep_addr; + __u8 bulk_in_ep_addr; + __u8 intr_in_ep_addr; + __u8 intr_in_interval; + + struct hci_dev hdev; + + unsigned long tx_state; + struct sk_buff_head tx_ctrl_q; + struct sk_buff_head tx_write_q; +}; + +/* Transmit states */ +#define HCI_TX_CTRL 1 +#define HCI_TX_WRITE 2 + +#endif /* __KERNEL__ */ diff -u --recursive --new-file v2.4.5/linux/include/net/bluetooth/l2cap.h linux/include/net/bluetooth/l2cap.h --- v2.4.5/linux/include/net/bluetooth/l2cap.h Wed Dec 31 16:00:00 1969 +++ linux/include/net/bluetooth/l2cap.h Mon Jun 11 19:15:27 2001 @@ -0,0 +1,155 @@ +/* + BlueZ - Bluetooth protocol stack for Linux + Copyright (C) 2000-2001 Qualcomm Incorporated + + Written 2000,2001 by Maxim Krasnyansky + + 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; + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY + CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, + COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS + SOFTWARE IS DISCLAIMED. +*/ + +/* + * $Id: l2cap.h,v 1.1 2001/06/01 08:12:11 davem Exp $ + */ + +#ifndef __L2CAP_H +#define __L2CAP_H + +#include +#include + +/* L2CAP socket address */ +struct sockaddr_l2 { + sa_family_t l2_family; + unsigned short l2_psm; + bdaddr_t l2_bdaddr; +}; + +/* set/get sockopt defines */ +#define L2CAP_OPTIONS 0x01 +struct l2cap_options { + __u16 omtu; + __u16 imtu; + __u16 flush_to; + __u32 token_rate; + __u32 bucket_size; + __u32 pick_band; + __u32 latency; + __u32 delay_var; +}; + +/* L2CAP defaults */ +#define L2CAP_DEFAULT_MTU 672 +#define L2CAP_DEFAULT_FLUSH_TO 0xFFFF + +#define L2CAP_CONN_TIMEOUT (HZ * 40) + +/* L2CAP command codes */ +#define L2CAP_COMMAND_REJ 0x01 +#define L2CAP_CONN_REQ 0x02 +#define L2CAP_CONN_RSP 0x03 +#define L2CAP_CONF_REQ 0x04 +#define L2CAP_CONF_RSP 0x05 +#define L2CAP_DISCONN_REQ 0x06 +#define L2CAP_DISCONN_RSP 0x07 +#define L2CAP_ECHO_REQ 0x08 +#define L2CAP_ECHO_RSP 0x09 +#define L2CAP_INFO_REQ 0x0a +#define L2CAP_INFO_RSP 0x0b + +/* L2CAP structures */ + +typedef struct { + __u16 len; + __u16 cid; +} __attribute__ ((packed)) l2cap_hdr; +#define L2CAP_HDR_SIZE 4 + +typedef struct { + __u8 code; + __u8 ident; + __u16 len; +} __attribute__ ((packed)) l2cap_cmd_hdr; +#define L2CAP_CMD_HDR_SIZE 4 + +typedef struct { + __u16 reason; +} __attribute__ ((packed)) l2cap_cmd_rej; +#define L2CAP_CMD_REJ_SIZE 2 + +typedef struct { + __u16 psm; + __u16 scid; +} __attribute__ ((packed)) l2cap_conn_req; +#define L2CAP_CONN_REQ_SIZE 4 + +typedef struct { + __u16 dcid; + __u16 scid; + __u16 result; + __u16 status; +} __attribute__ ((packed)) l2cap_conn_rsp; +#define L2CAP_CONN_RSP_SIZE 8 + +#define L2CAP_CONN_SUCCESS 0x0000 +#define L2CAP_CONN_PEND 0x0001 +#define L2CAP_CONN_BAD_PSM 0x0002 +#define L2CAP_CONN_SEC_BLOCK 0x0003 +#define L2CAP_CONN_NO_MEM 0x0004 + +typedef struct { + __u16 dcid; + __u16 flags; + __u8 data[0]; +} __attribute__ ((packed)) l2cap_conf_req; +#define L2CAP_CONF_REQ_SIZE 4 + +typedef struct { + __u16 scid; + __u16 flags; + __u16 result; + __u8 data[0]; +} __attribute__ ((packed)) l2cap_conf_rsp; +#define L2CAP_CONF_RSP_SIZE 6 + +#define L2CAP_CONF_SUCCESS 0x00 +#define L2CAP_CONF_UNACCEPT 0x01 + +typedef struct { + __u8 type; + __u8 len; + __u8 val[0]; +} __attribute__ ((packed)) l2cap_conf_opt; +#define L2CAP_CONF_OPT_SIZE 2 + +#define L2CAP_CONF_MTU 0x01 +#define L2CAP_CONF_FLUSH_TO 0x02 +#define L2CAP_CONF_QOS 0x03 + +typedef struct { + __u16 dcid; + __u16 scid; +} __attribute__ ((packed)) l2cap_disconn_req; +#define L2CAP_DISCONN_REQ_SIZE 4 + +typedef struct { + __u16 dcid; + __u16 scid; +} __attribute__ ((packed)) l2cap_disconn_rsp; +#define L2CAP_DISCONN_RSP_SIZE 4 + +#endif /* __L2CAP_H */ diff -u --recursive --new-file v2.4.5/linux/include/net/bluetooth/l2cap_core.h linux/include/net/bluetooth/l2cap_core.h --- v2.4.5/linux/include/net/bluetooth/l2cap_core.h Wed Dec 31 16:00:00 1969 +++ linux/include/net/bluetooth/l2cap_core.h Mon Jun 11 19:15:27 2001 @@ -0,0 +1,142 @@ +/* + BlueZ - Bluetooth protocol stack for Linux + Copyright (C) 2000-2001 Qualcomm Incorporated + + Written 2000,2001 by Maxim Krasnyansky + + 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; + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY + CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, + COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS + SOFTWARE IS DISCLAIMED. +*/ + +/* + * $Id: l2cap_core.h,v 1.1 2001/06/01 08:12:11 davem Exp $ + */ + +#ifndef __L2CAP_CORE_H +#define __L2CAP_CORE_H + +#ifdef __KERNEL__ + +/* ----- L2CAP interface ----- */ +struct l2cap_iff { + struct list_head list; + struct hci_dev *hdev; + bdaddr_t *bdaddr; + __u16 mtu; + spinlock_t lock; + struct list_head conn_list; +}; + +static __inline__ void l2cap_iff_lock(struct l2cap_iff *iff) +{ + spin_lock(&iff->lock); +} + +static __inline__ void l2cap_iff_unlock(struct l2cap_iff *iff) +{ + spin_unlock(&iff->lock); +} + +/* ----- L2CAP connections ----- */ +struct l2cap_chan_list { + struct sock *head; + rwlock_t lock; + long num; +}; + +struct l2cap_conn { + struct l2cap_iff *iff; + struct list_head list; + + struct hci_conn *hconn; + + __u16 state; + __u8 out; + bdaddr_t src; + bdaddr_t dst; + + spinlock_t lock; + atomic_t refcnt; + + struct sk_buff *rx_skb; + __u32 rx_len; + __u8 rx_ident; + __u8 tx_ident; + + struct l2cap_chan_list chan_list; +}; + +static __inline__ void __l2cap_conn_link(struct l2cap_iff *iff, struct l2cap_conn *c) +{ + list_add(&c->list, &iff->conn_list); +} + +static __inline__ void __l2cap_conn_unlink(struct l2cap_iff *iff, struct l2cap_conn *c) +{ + list_del(&c->list); +} + +/* ----- L2CAP channel and socket info ----- */ +#define l2cap_pi(sk) ((struct l2cap_pinfo *) &sk->protinfo) + +struct l2cap_accept_q { + struct sock *head; + struct sock *tail; +}; + +struct l2cap_pinfo { + bdaddr_t src; + bdaddr_t dst; + __u16 psm; + __u16 dcid; + __u16 scid; + __u32 flags; + + __u16 imtu; + __u16 omtu; + __u16 flush_to; + + __u8 conf_state; + __u16 conf_mtu; + + __u8 ident; + + struct l2cap_conn *conn; + struct sock *next_c; + struct sock *prev_c; + + struct sock *parent; + struct sock *next_q; + struct sock *prev_q; + + struct l2cap_accept_q accept_q; +}; + +#define CONF_INPUT 0x01 +#define CONF_OUTPUT 0x02 +#define CONF_DONE (CONF_INPUT | CONF_OUTPUT) + +extern struct bluez_sock_list l2cap_sk_list; +extern struct list_head l2cap_iff_list; +extern rwlock_t l2cap_rt_lock; + +extern void l2cap_register_proc(void); +extern void l2cap_unregister_proc(void); + +#endif /* __KERNEL__ */ + +#endif /* __L2CAP_CORE_H */ diff -u --recursive --new-file v2.4.5/linux/include/net/irda/irdacall.h linux/include/net/irda/irdacall.h --- v2.4.5/linux/include/net/irda/irdacall.h Thu Dec 17 09:01:03 1998 +++ linux/include/net/irda/irdacall.h Wed Dec 31 16:00:00 1969 @@ -1,2 +0,0 @@ -/* Separate to keep compilation of protocols.c simpler */ -extern void irda_proto_init(struct net_proto *pro); diff -u --recursive --new-file v2.4.5/linux/include/net/protocol.h linux/include/net/protocol.h --- v2.4.5/linux/include/net/protocol.h Fri May 25 18:01:27 2001 +++ linux/include/net/protocol.h Tue Jul 3 15:42:55 2001 @@ -63,19 +63,46 @@ #endif +/* This is used to register socket interfaces for IP protocols. */ +struct inet_protosw { + struct list_head list; + + /* These two fields form the lookup key. */ + unsigned short type; /* This is the 2nd argument to socket(2). */ + int protocol; /* This is the L4 protocol number. */ + + struct proto *prot; + struct proto_ops *ops; + + int capability; /* Which (if any) capability do + * we need to use this socket + * interface? + */ + char no_check; /* checksum on rcv/xmit/none? */ + unsigned char flags; /* See INET_PROTOSW_* below. */ +}; +#define INET_PROTOSW_REUSE 0x01 /* Are ports automatically reusable? */ +#define INET_PROTOSW_PERMANENT 0x02 /* Permanent protocols are unremovable. */ + extern struct inet_protocol *inet_protocol_base; extern struct inet_protocol *inet_protos[MAX_INET_PROTOS]; +extern struct list_head inetsw[SOCK_MAX]; #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) extern struct inet6_protocol *inet6_protos[MAX_INET_PROTOS]; +extern struct list_head inetsw6[SOCK_MAX]; #endif extern void inet_add_protocol(struct inet_protocol *prot); extern int inet_del_protocol(struct inet_protocol *prot); +extern void inet_register_protosw(struct inet_protosw *p); +extern void inet_unregister_protosw(struct inet_protosw *p); #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) extern void inet6_add_protocol(struct inet6_protocol *prot); extern int inet6_del_protocol(struct inet6_protocol *prot); +extern void inet6_register_protosw(struct inet_protosw *p); +extern void inet6_unregister_protosw(struct inet_protosw *p); #endif #endif /* _PROTOCOL_H */ diff -u --recursive --new-file v2.4.5/linux/include/net/snmp.h linux/include/net/snmp.h --- v2.4.5/linux/include/net/snmp.h Fri May 25 18:01:27 2001 +++ linux/include/net/snmp.h Tue Jul 3 15:42:55 2001 @@ -14,7 +14,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * $Id: snmp.h,v 1.18 2001/05/16 16:45:35 davem Exp $ + * $Id: snmp.h,v 1.19 2001/06/14 13:40:46 davem Exp $ * */ @@ -119,6 +119,7 @@ unsigned long IcmpOutTimestampReps; unsigned long IcmpOutAddrMasks; unsigned long IcmpOutAddrMaskReps; + unsigned long dummy; unsigned long __pad[0]; } ____cacheline_aligned; diff -u --recursive --new-file v2.4.5/linux/include/video/macmodes.h linux/include/video/macmodes.h --- v2.4.5/linux/include/video/macmodes.h Wed Feb 9 19:43:57 2000 +++ linux/include/video/macmodes.h Wed Jun 27 17:10:55 2001 @@ -38,7 +38,9 @@ #define VMODE_1152_870_75 18 /* 1152x870, 75Hz */ #define VMODE_1280_960_75 19 /* 1280x960, 75Hz */ #define VMODE_1280_1024_75 20 /* 1280x1024, 75Hz */ -#define VMODE_MAX 20 +#define VMODE_1152_768_60 21 /* 1152x768, 60Hz Titanium PowerBook */ +#define VMODE_1600_1024_60 22 /* 1600x1024, 60Hz 22" Cinema Display */ +#define VMODE_MAX 22 #define VMODE_CHOOSE 99 #define CMODE_NVRAM -1 diff -u --recursive --new-file v2.4.5/linux/init/main.c linux/init/main.c --- v2.4.5/linux/init/main.c Tue May 22 09:35:42 2001 +++ linux/init/main.c Wed Jun 20 11:10:27 2001 @@ -62,7 +62,8 @@ #endif #ifdef CONFIG_IRDA -#include +extern int irda_proto_init(void); +extern int irda_device_init(void); #endif #ifdef CONFIG_X86_IO_APIC diff -u --recursive --new-file v2.4.5/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v2.4.5/linux/kernel/ksyms.c Thu May 24 15:20:18 2001 +++ linux/kernel/ksyms.c Mon Jun 11 19:15:27 2001 @@ -90,17 +90,13 @@ EXPORT_SYMBOL(exit_sighand); /* internal kernel memory management */ +EXPORT_SYMBOL(_alloc_pages); EXPORT_SYMBOL(__alloc_pages); EXPORT_SYMBOL(alloc_pages_node); EXPORT_SYMBOL(__get_free_pages); EXPORT_SYMBOL(get_zeroed_page); EXPORT_SYMBOL(__free_pages); EXPORT_SYMBOL(free_pages); -#ifndef CONFIG_DISCONTIGMEM -EXPORT_SYMBOL(contig_page_data); -#else -EXPORT_SYMBOL(alloc_pages); -#endif EXPORT_SYMBOL(num_physpages); EXPORT_SYMBOL(kmem_find_general_cachep); EXPORT_SYMBOL(kmem_cache_create); @@ -144,6 +140,7 @@ EXPORT_SYMBOL(force_delete); EXPORT_SYMBOL(follow_up); EXPORT_SYMBOL(follow_down); +EXPORT_SYMBOL(lookup_mnt); EXPORT_SYMBOL(path_init); EXPORT_SYMBOL(path_walk); EXPORT_SYMBOL(path_release); @@ -539,6 +536,9 @@ EXPORT_SYMBOL(tasklet_init); EXPORT_SYMBOL(tasklet_kill); EXPORT_SYMBOL(__run_task_queue); +EXPORT_SYMBOL(do_softirq); +EXPORT_SYMBOL(tasklet_schedule); +EXPORT_SYMBOL(tasklet_hi_schedule); /* init task, for moving kthread roots - ought to export a function ?? */ diff -u --recursive --new-file v2.4.5/linux/kernel/sched.c linux/kernel/sched.c --- v2.4.5/linux/kernel/sched.c Fri Apr 20 18:26:16 2001 +++ linux/kernel/sched.c Wed Jun 27 14:12:04 2001 @@ -544,7 +544,7 @@ release_kernel_lock(prev, this_cpu); /* Do "administrative" work here while we don't hold any locks */ - if (softirq_active(this_cpu) & softirq_mask(this_cpu)) + if (softirq_pending(this_cpu)) goto handle_softirq; handle_softirq_back: @@ -1104,7 +1104,7 @@ int state; static const char * stat_nam[] = { "R", "S", "D", "Z", "T", "W" }; - printk("%-8s ", p->comm); + printk("%-13.13s ", p->comm); state = p->state ? ffz(~p->state) + 1 : 0; if (((unsigned) state) < sizeof(stat_nam)/sizeof(char *)) printk(stat_nam[state]); @@ -1132,21 +1132,21 @@ printk("%5d ", p->p_cptr->pid); else printk(" "); - if (!p->mm) - printk(" (L-TLB) "); - else - printk(" (NOTLB) "); if (p->p_ysptr) printk("%7d", p->p_ysptr->pid); else printk(" "); if (p->p_osptr) - printk(" %5d\n", p->p_osptr->pid); + printk(" %5d", p->p_osptr->pid); + else + printk(" "); + if (!p->mm) + printk(" (L-TLB)\n"); else - printk("\n"); + printk(" (NOTLB)\n"); -#if defined(CONFIG_X86) || defined(CONFIG_SPARC64) -/* This is very useful, but only works on x86 and sparc64 right now */ +#if defined(CONFIG_X86) || defined(CONFIG_SPARC64) || defined(CONFIG_ARM) +/* This is very useful, but only works on ARM, x86 and sparc64 right now */ { extern void show_trace_task(struct task_struct *tsk); show_trace_task(p); diff -u --recursive --new-file v2.4.5/linux/kernel/softirq.c linux/kernel/softirq.c --- v2.4.5/linux/kernel/softirq.c Fri Dec 29 14:07:24 2000 +++ linux/kernel/softirq.c Mon Jun 11 19:15:27 2001 @@ -50,70 +50,50 @@ asmlinkage void do_softirq() { int cpu = smp_processor_id(); - __u32 active, mask; + __u32 pending; if (in_interrupt()) return; - local_bh_disable(); - local_irq_disable(); - mask = softirq_mask(cpu); - active = softirq_active(cpu) & mask; - if (active) { + pending = softirq_pending(cpu); + + if (pending) { struct softirq_action *h; + local_bh_disable(); restart: - /* Reset active bitmask before enabling irqs */ - softirq_active(cpu) &= ~active; + /* Reset the pending bitmask before enabling irqs */ + softirq_pending(cpu) = 0; local_irq_enable(); h = softirq_vec; - mask &= ~active; do { - if (active & 1) + if (pending & 1) h->action(h); h++; - active >>= 1; - } while (active); + pending >>= 1; + } while (pending); local_irq_disable(); - active = softirq_active(cpu); - if ((active &= mask) != 0) - goto retry; + pending = softirq_pending(cpu); + if (pending) + goto restart; + __local_bh_enable(); } - local_bh_enable(); - - /* Leave with locally disabled hard irqs. It is critical to close - * window for infinite recursion, while we help local bh count, - * it protected us. Now we are defenceless. - */ - return; - -retry: - goto restart; + local_irq_enable(); } -static spinlock_t softirq_mask_lock = SPIN_LOCK_UNLOCKED; - void open_softirq(int nr, void (*action)(struct softirq_action*), void *data) { - unsigned long flags; - int i; - - spin_lock_irqsave(&softirq_mask_lock, flags); softirq_vec[nr].data = data; softirq_vec[nr].action = action; - - for (i=0; istate) && + tasklet_trylock(t)) { + t->next = tasklet_vec[cpu].list; + tasklet_vec[cpu].list = t; + __cpu_raise_softirq(cpu, TASKLET_SOFTIRQ); + tasklet_unlock(t); + } + local_irq_restore(flags); +} + +void tasklet_hi_schedule(struct tasklet_struct *t) +{ + unsigned long flags; + int cpu; + + cpu = smp_processor_id(); + local_irq_save(flags); + + if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state) && + tasklet_trylock(t)) { + t->next = tasklet_hi_vec[cpu].list; + tasklet_hi_vec[cpu].list = t; + __cpu_raise_softirq(cpu, HI_SOFTIRQ); + tasklet_unlock(t); + } + local_irq_restore(flags); +} + static void tasklet_action(struct softirq_action *a) { int cpu = smp_processor_id(); @@ -129,37 +148,37 @@ local_irq_disable(); list = tasklet_vec[cpu].list; tasklet_vec[cpu].list = NULL; - local_irq_enable(); - while (list != NULL) { + while (list) { struct tasklet_struct *t = list; list = list->next; - if (tasklet_trylock(t)) { - if (atomic_read(&t->count) == 0) { - clear_bit(TASKLET_STATE_SCHED, &t->state); - - t->func(t->data); - /* - * talklet_trylock() uses test_and_set_bit that imply - * an mb when it returns zero, thus we need the explicit - * mb only here: while closing the critical section. - */ -#ifdef CONFIG_SMP - smp_mb__before_clear_bit(); -#endif - tasklet_unlock(t); - continue; - } - tasklet_unlock(t); + /* + * A tasklet is only added to the queue while it's + * locked, so no other CPU can have this tasklet + * pending: + */ + if (!tasklet_trylock(t)) + BUG(); +repeat: + if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state)) + BUG(); + if (!atomic_read(&t->count)) { + local_irq_enable(); + t->func(t->data); + local_irq_disable(); + /* + * One more run if the tasklet got reactivated: + */ + if (test_bit(TASKLET_STATE_SCHED, &t->state)) + goto repeat; } - local_irq_disable(); - t->next = tasklet_vec[cpu].list; - tasklet_vec[cpu].list = t; - __cpu_raise_softirq(cpu, TASKLET_SOFTIRQ); - local_irq_enable(); + tasklet_unlock(t); + if (test_bit(TASKLET_STATE_SCHED, &t->state)) + tasklet_schedule(t); } + local_irq_enable(); } @@ -174,39 +193,40 @@ local_irq_disable(); list = tasklet_hi_vec[cpu].list; tasklet_hi_vec[cpu].list = NULL; - local_irq_enable(); - while (list != NULL) { + while (list) { struct tasklet_struct *t = list; list = list->next; - if (tasklet_trylock(t)) { - if (atomic_read(&t->count) == 0) { - clear_bit(TASKLET_STATE_SCHED, &t->state); - - t->func(t->data); - tasklet_unlock(t); - continue; - } - tasklet_unlock(t); + if (!tasklet_trylock(t)) + BUG(); +repeat: + if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state)) + BUG(); + if (!atomic_read(&t->count)) { + local_irq_enable(); + t->func(t->data); + local_irq_disable(); + if (test_bit(TASKLET_STATE_SCHED, &t->state)) + goto repeat; } - local_irq_disable(); - t->next = tasklet_hi_vec[cpu].list; - tasklet_hi_vec[cpu].list = t; - __cpu_raise_softirq(cpu, HI_SOFTIRQ); - local_irq_enable(); + tasklet_unlock(t); + if (test_bit(TASKLET_STATE_SCHED, &t->state)) + tasklet_hi_schedule(t); } + local_irq_enable(); } void tasklet_init(struct tasklet_struct *t, void (*func)(unsigned long), unsigned long data) { - t->func = func; - t->data = data; + t->next = NULL; t->state = 0; atomic_set(&t->count, 0); + t->func = func; + t->data = data; } void tasklet_kill(struct tasklet_struct *t) diff -u --recursive --new-file v2.4.5/linux/kernel/timer.c linux/kernel/timer.c --- v2.4.5/linux/kernel/timer.c Sun Dec 10 09:53:19 2000 +++ linux/kernel/timer.c Tue Jun 12 16:40:11 2001 @@ -32,7 +32,7 @@ long tick = (1000000 + HZ/2) / HZ; /* timer interrupt period */ /* The current time */ -volatile struct timeval xtime __attribute__ ((aligned (16))); +struct timeval xtime __attribute__ ((aligned (16))); /* Don't completely fail for HZ > 500. */ int tickadj = 500/HZ ? : 1; /* microsecs */ diff -u --recursive --new-file v2.4.5/linux/lib/brlock.c linux/lib/brlock.c --- v2.4.5/linux/lib/brlock.c Mon Apr 24 13:59:56 2000 +++ linux/lib/brlock.c Fri Jun 29 19:38:26 2001 @@ -25,7 +25,7 @@ int i; for (i = 0; i < smp_num_cpus; i++) - write_lock(__brlock_array[idx] + cpu_logical_map(i)); + write_lock(&__brlock_array[cpu_logical_map(i)][idx]); } void __br_write_unlock (enum brlock_indices idx) @@ -33,7 +33,7 @@ int i; for (i = 0; i < smp_num_cpus; i++) - write_unlock(__brlock_array[idx] + cpu_logical_map(i)); + write_unlock(&__brlock_array[cpu_logical_map(i)][idx]); } #else /* ! __BRLOCK_USE_ATOMICS */ @@ -48,11 +48,14 @@ { int i; - spin_lock(&__br_write_locks[idx].lock); again: + spin_lock(&__br_write_locks[idx].lock); for (i = 0; i < smp_num_cpus; i++) - if (__brlock_array[cpu_logical_map(i)][idx] != 0) + if (__brlock_array[cpu_logical_map(i)][idx] != 0) { + spin_unlock(&__br_write_locks[idx].lock); + barrier(); goto again; + } } void __br_write_unlock (enum brlock_indices idx) diff -u --recursive --new-file v2.4.5/linux/mm/bootmem.c linux/mm/bootmem.c --- v2.4.5/linux/mm/bootmem.c Thu May 24 15:20:18 2001 +++ linux/mm/bootmem.c Mon Jul 2 13:56:40 2001 @@ -1,5 +1,5 @@ /* - * linux/mm/initmem.c + * linux/mm/bootmem.c * * Copyright (C) 1999 Ingo Molnar * Discontiguous memory support, Kanoj Sarcar, SGI, Nov 1999 diff -u --recursive --new-file v2.4.5/linux/mm/filemap.c linux/mm/filemap.c --- v2.4.5/linux/mm/filemap.c Tue May 22 10:52:35 2001 +++ linux/mm/filemap.c Tue Jun 12 11:16:41 2001 @@ -230,17 +230,17 @@ unsigned long offset; page = list_entry(curr, struct page, list); - curr = curr->next; offset = page->index; /* Is one of the pages to truncate? */ if ((offset >= start) || (*partial && (offset + 1) == start)) { + list_del(head); + list_add(head, curr); if (TryLockPage(page)) { page_cache_get(page); spin_unlock(&pagecache_lock); wait_on_page(page); - page_cache_release(page); - return 1; + goto out_restart; } page_cache_get(page); spin_unlock(&pagecache_lock); @@ -252,11 +252,15 @@ truncate_complete_page(page); UnlockPage(page); - page_cache_release(page); - return 1; + goto out_restart; } + curr = curr->next; } return 0; +out_restart: + page_cache_release(page); + spin_lock(&pagecache_lock); + return 1; } @@ -273,15 +277,19 @@ { unsigned long start = (lstart + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; unsigned partial = lstart & (PAGE_CACHE_SIZE - 1); + int complete; -repeat: spin_lock(&pagecache_lock); - if (truncate_list_pages(&mapping->clean_pages, start, &partial)) - goto repeat; - if (truncate_list_pages(&mapping->dirty_pages, start, &partial)) - goto repeat; - if (truncate_list_pages(&mapping->locked_pages, start, &partial)) - goto repeat; + do { + complete = 1; + while (truncate_list_pages(&mapping->clean_pages, start, &partial)) + complete = 0; + while (truncate_list_pages(&mapping->dirty_pages, start, &partial)) + complete = 0; + while (truncate_list_pages(&mapping->locked_pages, start, &partial)) + complete = 0; + } while (!complete); + /* Traversed all three lists without dropping the lock */ spin_unlock(&pagecache_lock); } @@ -529,7 +537,7 @@ if (PageLocked(page)) BUG(); - flags = page->flags & ~((1 << PG_uptodate) | (1 << PG_error) | (1 << PG_dirty) | (1 << PG_referenced) | (1 << PG_arch_1)); + flags = page->flags & ~((1 << PG_uptodate) | (1 << PG_error) | (1 << PG_dirty) | (1 << PG_referenced) | (1 << PG_arch_1) | (1 << PG_checked)); page->flags = flags | (1 << PG_locked); page_cache_get(page); page->index = offset; diff -u --recursive --new-file v2.4.5/linux/mm/highmem.c linux/mm/highmem.c --- v2.4.5/linux/mm/highmem.c Fri May 25 17:57:46 2001 +++ linux/mm/highmem.c Fri Jun 29 16:17:34 2001 @@ -302,7 +302,7 @@ struct page *page; repeat_alloc: - page = alloc_page(GFP_BUFFER); + page = alloc_page(GFP_NOIO); if (page) return page; /* @@ -340,7 +340,7 @@ struct buffer_head *bh; repeat_alloc: - bh = kmem_cache_alloc(bh_cachep, SLAB_BUFFER); + bh = kmem_cache_alloc(bh_cachep, SLAB_NOIO); if (bh) return bh; /* diff -u --recursive --new-file v2.4.5/linux/mm/memory.c linux/mm/memory.c --- v2.4.5/linux/mm/memory.c Fri Apr 27 14:23:25 2001 +++ linux/mm/memory.c Mon Jun 11 19:15:27 2001 @@ -274,7 +274,7 @@ */ if (pte_dirty(pte) && page->mapping) set_page_dirty(page); - page_cache_release(page); + free_page_and_swap_cache(page); return 1; } swap_free(pte_to_swp_entry(pte)); @@ -870,24 +870,6 @@ flush_cache_page(vma, address); establish_pte(vma, address, page_table, pte_mkwrite(pte_mkdirty(mk_pte(new_page, vma->vm_page_prot)))); } - -/* - * Work out if there are any other processes sharing this - * swap cache page. Never mind the buffers. - */ -static inline int exclusive_swap_page(struct page *page) -{ - unsigned int count; - - if (!PageLocked(page)) - BUG(); - if (!PageSwapCache(page)) - return 0; - count = page_count(page) - !!page->buffers; /* 2: us + swap cache */ - count += swap_count(page); /* +1: just swap cache */ - return count == 3; /* =3: total */ -} - /* * This routine handles present pages, when users try to write diff -u --recursive --new-file v2.4.5/linux/mm/numa.c linux/mm/numa.c --- v2.4.5/linux/mm/numa.c Mon Oct 16 15:25:45 2000 +++ linux/mm/numa.c Mon Jul 2 14:12:20 2001 @@ -34,7 +34,7 @@ struct page * alloc_pages_node(int nid, int gfp_mask, unsigned long order) { #ifdef CONFIG_NUMA - return __alloc_pages(NODE_DATA(nid)->node_zonelists + gfp_mask, order); + return __alloc_pages(gfp_mask, order, NODE_DATA(nid)->node_zonelists + (gfp_mask & GFP_ZONEMASK)); #else return alloc_pages(gfp_mask, order); #endif @@ -85,14 +85,14 @@ static struct page * alloc_pages_pgdat(pg_data_t *pgdat, int gfp_mask, unsigned long order) { - return __alloc_pages(pgdat->node_zonelists + gfp_mask, order); + return __alloc_pages(gfp_mask, order, pgdat->node_zonelists + (gfp_mask & GFP_ZONEMASK)); } /* * This can be refined. Currently, tries to do round robin, instead * should do concentratic circle search, starting from current node. */ -struct page * alloc_pages(int gfp_mask, unsigned long order) +struct page * _alloc_pages(unsigned int gfp_mask, unsigned long order) { struct page *ret = 0; pg_data_t *start, *temp; diff -u --recursive --new-file v2.4.5/linux/mm/page_alloc.c linux/mm/page_alloc.c --- v2.4.5/linux/mm/page_alloc.c Fri May 25 16:55:23 2001 +++ linux/mm/page_alloc.c Fri Jun 29 15:39:41 2001 @@ -268,15 +268,21 @@ return NULL; } +#ifndef CONFIG_DISCONTIGMEM +struct page *_alloc_pages(unsigned int gfp_mask, unsigned long order) +{ + return __alloc_pages(gfp_mask, order, + contig_page_data.node_zonelists+(gfp_mask & GFP_ZONEMASK)); +} +#endif /* * This is the 'heart' of the zoned buddy allocator: */ -struct page * __alloc_pages(zonelist_t *zonelist, unsigned long order) +struct page * __alloc_pages(unsigned int gfp_mask, unsigned long order, zonelist_t *zonelist) { zone_t **zone; int direct_reclaim = 0; - unsigned int gfp_mask = zonelist->gfp_mask; struct page * page; /* @@ -428,18 +434,30 @@ } /* * When we arrive here, we are really tight on memory. + * Since kswapd didn't succeed in freeing pages for us, + * we try to help it. * - * We try to free pages ourselves by: - * - shrinking the i/d caches. - * - reclaiming unused memory from the slab caches. - * - swapping/syncing pages to disk (done by page_launder) - * - moving clean pages from the inactive dirty list to - * the inactive clean list. (done by page_launder) + * Single page allocs loop until the allocation succeeds. + * Multi-page allocs can fail due to memory fragmentation; + * in that case we bail out to prevent infinite loops and + * hanging device drivers ... + * + * Another issue are GFP_NOFS allocations; because they + * do not have __GFP_FS set it's possible we cannot make + * any progress freeing pages, in that case it's better + * to give up than to deadlock the kernel looping here. */ if (gfp_mask & __GFP_WAIT) { - memory_pressure++; - try_to_free_pages(gfp_mask); - goto try_again; + if (!order || free_shortage()) { + int progress = try_to_free_pages(gfp_mask); + if (progress || (gfp_mask & __GFP_FS)) + goto try_again; + /* + * Fail in case no progress was made and the + * allocation may not be able to block on IO. + */ + return NULL; + } } } @@ -671,14 +689,13 @@ { int i, j, k; - for (i = 0; i < NR_GFPINDEX; i++) { + for (i = 0; i <= GFP_ZONEMASK; i++) { zonelist_t *zonelist; zone_t *zone; zonelist = pgdat->node_zonelists + i; memset(zonelist, 0, sizeof(*zonelist)); - zonelist->gfp_mask = i; j = 0; k = ZONE_NORMAL; if (i & __GFP_HIGHMEM) diff -u --recursive --new-file v2.4.5/linux/mm/swap_state.c linux/mm/swap_state.c --- v2.4.5/linux/mm/swap_state.c Thu May 24 15:20:18 2001 +++ linux/mm/swap_state.c Mon Jun 11 19:15:27 2001 @@ -145,6 +145,30 @@ UnlockPage(page); } +/* + * Perform a free_page(), also freeing any swap cache associated with + * this page if it is the last user of the page. Can not do a lock_page, + * as we are holding the page_table_lock spinlock. + */ +void free_page_and_swap_cache(struct page *page) +{ + /* + * If we are the only user, then try to free up the swap cache. + * + * Its ok to check for PageSwapCache without the page lock + * here because we are going to recheck again inside + * exclusive_swap_page() _with_ the lock. + * - Marcelo + */ + if (PageSwapCache(page) && !TryLockPage(page)) { + if (exclusive_swap_page(page)) + delete_from_swap_cache_nolock(page); + UnlockPage(page); + } + page_cache_release(page); +} + + /* * Lookup a swap entry in the swap cache. A found page will be returned * unlocked and with its refcount incremented - we rely on the kernel diff -u --recursive --new-file v2.4.5/linux/mm/swapfile.c linux/mm/swapfile.c --- v2.4.5/linux/mm/swapfile.c Sat May 19 17:16:18 2001 +++ linux/mm/swapfile.c Mon Jun 11 19:15:27 2001 @@ -343,6 +343,16 @@ while (1) { /* + * The algorithm is inefficient but seldomly used + * and probably not worth fixing. + * + * Make sure that we aren't completely killing + * interactive performance. + */ + if (current->need_resched) + schedule(); + + /* * Find a swap page in use and read it in. */ swap_device_lock(si); diff -u --recursive --new-file v2.4.5/linux/mm/vmscan.c linux/mm/vmscan.c --- v2.4.5/linux/mm/vmscan.c Fri May 25 17:00:18 2001 +++ linux/mm/vmscan.c Fri Jun 29 16:35:36 2001 @@ -265,12 +265,9 @@ return !count; } -/* - * N.B. This function returns only 0 or 1. Return values != 1 from - * the lower level routines result in continued processing. - */ -#define SWAP_SHIFT 5 -#define SWAP_MIN 8 +#define SWAP_MM_SHIFT 4 +#define SWAP_SHIFT 5 +#define SWAP_MIN 8 static inline int swap_amount(struct mm_struct *mm) { @@ -283,7 +280,7 @@ return nr; } -static int swap_out(unsigned int priority, int gfp_mask) +static void swap_out(unsigned int priority, int gfp_mask) { int counter; int retval = 0; @@ -294,7 +291,7 @@ retval = swap_out_mm(mm, swap_amount(mm)); /* Then, look at the other mm's */ - counter = (mmlist_nr << SWAP_SHIFT) >> priority; + counter = (mmlist_nr << SWAP_MM_SHIFT) >> priority; do { struct list_head *p; @@ -316,11 +313,10 @@ retval |= swap_out_mm(mm, swap_amount(mm)); mmput(mm); } while (--counter >= 0); - return retval; + return; empty: spin_unlock(&mmlist_lock); - return 0; } @@ -395,6 +391,7 @@ goto out; found_page: + memory_pressure++; del_page_from_inactive_clean_list(page); UnlockPage(page); page->age = PAGE_AGE_START; @@ -404,14 +401,13 @@ out: spin_unlock(&pagemap_lru_lock); spin_unlock(&pagecache_lock); - memory_pressure++; return page; } /** * page_launder - clean dirty inactive pages, move to inactive_clean list * @gfp_mask: what operations we are allowed to do - * @sync: should we wait synchronously for the cleaning of pages + * @sync: are we allowed to do synchronous IO in emergencies ? * * When this function is called, we are most likely low on free + * inactive_clean pages. Since we want to refill those pages as @@ -428,19 +424,14 @@ * go out to Matthew Dillon. */ #define MAX_LAUNDER (4 * (1 << page_cluster)) +#define CAN_DO_FS (gfp_mask & __GFP_FS) +#define CAN_DO_IO (gfp_mask & __GFP_IO) int page_launder(int gfp_mask, int sync) { int launder_loop, maxscan, cleaned_pages, maxlaunder; - int can_get_io_locks; struct list_head * page_lru; struct page * page; - /* - * We can only grab the IO locks (eg. for flushing dirty - * buffers to disk) if __GFP_IO is set. - */ - can_get_io_locks = gfp_mask & __GFP_IO; - launder_loop = 0; maxlaunder = 0; cleaned_pages = 0; @@ -491,7 +482,7 @@ goto page_active; /* First time through? Move it to the back of the list */ - if (!launder_loop) { + if (!launder_loop || !CAN_DO_FS) { list_del(page_lru); list_add(page_lru, &inactive_dirty_list); UnlockPage(page); @@ -521,7 +512,8 @@ * buffer pages */ if (page->buffers) { - int wait, clearedbuf; + unsigned int buffer_mask; + int clearedbuf; int freed_page = 0; /* * Since we might be doing disk IO, we have to @@ -534,14 +526,14 @@ /* Will we do (asynchronous) IO? */ if (launder_loop && maxlaunder == 0 && sync) - wait = 2; /* Synchrounous IO */ + buffer_mask = gfp_mask; /* Do as much as we can */ else if (launder_loop && maxlaunder-- > 0) - wait = 1; /* Async IO */ + buffer_mask = gfp_mask & ~__GFP_WAIT; /* Don't wait, async write-out */ else - wait = 0; /* No IO */ + buffer_mask = gfp_mask & ~(__GFP_WAIT | __GFP_IO); /* Don't even start IO */ /* Try to free the page buffers. */ - clearedbuf = try_to_free_buffers(page, wait); + clearedbuf = try_to_free_buffers(page, buffer_mask); /* * Re-take the spinlock. Note that we cannot @@ -621,7 +613,7 @@ * loads, flush out the dirty pages before we have to wait on * IO. */ - if (can_get_io_locks && !launder_loop && free_shortage()) { + if ((CAN_DO_IO || CAN_DO_FS) && !launder_loop && free_shortage()) { launder_loop = 1; /* If we cleaned pages, never do synchronous IO. */ if (cleaned_pages) @@ -655,24 +647,10 @@ /* * When we are background aging, we try to increase the page aging - * information in the system. When we have too many inactive pages - * we don't do background aging since having all pages on the - * inactive list decreases aging information. - * - * Since not all active pages have to be on the active list, we round - * nr_active_pages up to num_physpages/2, if needed. + * information in the system. */ - if (!target) { - int inactive = nr_free_pages() + nr_inactive_clean_pages() + - nr_inactive_dirty_pages; - int active = MAX(nr_active_pages, num_physpages / 2); - if (active > 10 * inactive) - maxscan = nr_active_pages >> 4; - else if (active > 3 * inactive) - maxscan = nr_active_pages >> 8; - else - return 0; - } + if (!target) + maxscan = nr_active_pages >> 4; /* Take the lock while messing with the list... */ spin_lock(&pagemap_lru_lock); @@ -792,6 +770,8 @@ int zone_shortage; zone_t *zone = pgdat->node_zones+ i; + if (!zone->size) + continue; zone_shortage = zone->pages_high; zone_shortage -= zone->inactive_dirty_pages; zone_shortage -= zone->inactive_clean_pages; @@ -843,12 +823,12 @@ return 1; } + /* Walk the VM space for a bit.. */ + swap_out(DEF_PRIORITY, gfp_mask); + count -= refill_inactive_scan(DEF_PRIORITY, count); if (count <= 0) goto done; - - /* If refill_inactive_scan failed, try to page stuff out.. */ - swap_out(DEF_PRIORITY, gfp_mask); if (--maxtry <= 0) return 0; diff -u --recursive --new-file v2.4.5/linux/net/802/hippi.c linux/net/802/hippi.c --- v2.4.5/linux/net/802/hippi.c Wed Aug 18 11:38:48 1999 +++ linux/net/802/hippi.c Wed Jun 20 21:00:55 2001 @@ -98,7 +98,7 @@ memcpy(&skb->private.ifield, daddr + 2, 4); return HIPPI_HLEN; } - return -HIPPI_HLEN; + return -((int)HIPPI_HLEN); } diff -u --recursive --new-file v2.4.5/linux/net/Makefile linux/net/Makefile --- v2.4.5/linux/net/Makefile Fri Dec 29 14:07:24 2000 +++ linux/net/Makefile Mon Jun 11 19:15:27 2001 @@ -7,7 +7,7 @@ O_TARGET := network.o -mod-subdirs := ipv4/netfilter ipv6/netfilter ipx irda atm netlink sched +mod-subdirs := ipv4/netfilter ipv6/netfilter ipx irda bluetooth atm netlink sched export-objs := netsyms.o subdir-y := core ethernet @@ -40,6 +40,7 @@ subdir-$(CONFIG_ROSE) += rose subdir-$(CONFIG_AX25) += ax25 subdir-$(CONFIG_IRDA) += irda +subdir-$(CONFIG_BLUEZ) += bluetooth subdir-$(CONFIG_SUNRPC) += sunrpc subdir-$(CONFIG_ATM) += atm subdir-$(CONFIG_DECNET) += decnet diff -u --recursive --new-file v2.4.5/linux/net/README linux/net/README --- v2.4.5/linux/net/README Wed May 16 10:31:27 2001 +++ linux/net/README Mon Jun 11 19:15:27 2001 @@ -22,5 +22,5 @@ wanrouter gene@compuserve.com, jaspreet@sangoma and dm@sangoma.com unix alan@lxorguk.ukuu.org.uk x25 g4klx@g4klx.demon.co.uk - +bluetooth maxk@qualcomm.com diff -u --recursive --new-file v2.4.5/linux/net/appletalk/aarp.c linux/net/appletalk/aarp.c --- v2.4.5/linux/net/appletalk/aarp.c Mon Jan 22 13:32:10 2001 +++ linux/net/appletalk/aarp.c Fri Jun 29 19:38:26 2001 @@ -97,11 +97,7 @@ */ static void __aarp_expire(struct aarp_entry *a) { - struct sk_buff *skb; - - while ((skb = skb_dequeue(&a->packet_queue)) != NULL) - kfree_skb(skb); - + skb_queue_purge(&a->packet_queue); kfree(a); } @@ -844,9 +840,7 @@ } static struct notifier_block aarp_notifier = { - aarp_device_event, - NULL, - 0 + notifier_call: aarp_device_event, }; static char aarp_snap_id[] = { 0x00, 0x00, 0x00, 0x80, 0xF3 }; @@ -888,8 +882,8 @@ int len, ct; len = sprintf(buffer, - "%-10.10s ""%-10.10s""%-18.18s""%12.12s""%12.12s"" xmit_count status\n", - "address","device","hw addr","last_sent", "expires"); + "%-10.10s %-10.10s%-18.18s%12.12s%12.12s xmit_count status\n", + "address", "device", "hw addr", "last_sent", "expires"); spin_lock_bh(&aarp_lock); diff -u --recursive --new-file v2.4.5/linux/net/atm/clip.c linux/net/atm/clip.c --- v2.4.5/linux/net/atm/clip.c Wed Apr 18 14:40:07 2001 +++ linux/net/atm/clip.c Wed Jun 27 17:10:55 2001 @@ -685,8 +685,6 @@ static void atmarpd_close(struct atm_vcc *vcc) { - struct sk_buff *skb; - DPRINTK("atmarpd_close\n"); atmarpd = NULL; /* assumed to be atomic */ barrier(); @@ -695,7 +693,7 @@ if (skb_peek(&vcc->recvq)) printk(KERN_ERR "atmarpd_close: closing with requests " "pending\n"); - while ((skb = skb_dequeue(&vcc->recvq))) kfree_skb(skb); + skb_queue_purge(&vcc->recvq); DPRINTK("(done)\n"); } diff -u --recursive --new-file v2.4.5/linux/net/atm/common.c linux/net/atm/common.c --- v2.4.5/linux/net/atm/common.c Fri Apr 6 10:51:19 2001 +++ linux/net/atm/common.c Wed Jun 27 17:10:55 2001 @@ -544,7 +544,7 @@ { struct atm_dev *dev; struct atm_vcc *vcc; - int *tmp_buf; + int *tmp_buf, *tmp_p; void *buf; int error,len,size,number, ret_val; @@ -598,14 +598,13 @@ ret_val = -ENOMEM; goto done; } + tmp_p = tmp_buf; for (dev = atm_devs; dev; dev = dev->next) - *tmp_buf++ = dev->number; - if (copy_to_user(buf,(char *) tmp_buf-size,size)) { - ret_val = -EFAULT; - goto done; - } - ret_val = put_user(size, - &((struct atm_iobuf *) arg)->length) ? -EFAULT : 0; + *tmp_p++ = dev->number; + ret_val = ((copy_to_user(buf, tmp_buf, size)) || + put_user(size, &((struct atm_iobuf *) arg)->length) + ) ? -EFAULT : 0; + kfree(tmp_buf); goto done; case SIOCGSTAMP: /* borrowed from IP */ if (!vcc->timestamp.tv_sec) { diff -u --recursive --new-file v2.4.5/linux/net/atm/lec.c linux/net/atm/lec.c --- v2.4.5/linux/net/atm/lec.c Tue Mar 6 19:28:33 2001 +++ linux/net/atm/lec.c Wed Jun 27 17:10:55 2001 @@ -281,6 +281,10 @@ dev->name, skb->len,skb->truesize); nb=(unsigned char*)kmalloc(64, GFP_ATOMIC); + if (nb == NULL) { + dev_kfree_skb(skb); + return 0; + } memcpy(nb,skb->data,skb->len); kfree(skb->head); skb->head = skb->data = nb; @@ -1796,6 +1800,10 @@ entry = lec_arp_find(priv, mac_addr); if (!entry) { entry = make_entry(priv, mac_addr); + if (!entry) { + lec_arp_unlock(priv); + return; + } entry->status = ESI_UNKNOWN; lec_arp_put(priv->lec_arp_tables, entry); /* Temporary, changes before end of function */ @@ -1890,6 +1898,10 @@ ioc_data->atm_addr[16],ioc_data->atm_addr[17], ioc_data->atm_addr[18],ioc_data->atm_addr[19]); entry = make_entry(priv, bus_mac); + if (entry == NULL) { + lec_arp_unlock(priv); + return; + } memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN); memset(entry->mac_addr, 0, ETH_ALEN); entry->recv_vcc = vcc; @@ -1967,6 +1979,10 @@ /* Not found, snatch address from first data packet that arrives from this vcc */ entry = make_entry(priv, bus_mac); + if (!entry) { + lec_arp_unlock(priv); + return; + } entry->vcc = vcc; entry->old_push = old_push; memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN); diff -u --recursive --new-file v2.4.5/linux/net/atm/mpc.c linux/net/atm/mpc.c --- v2.4.5/linux/net/atm/mpc.c Wed Aug 9 13:51:09 2000 +++ linux/net/atm/mpc.c Wed Jun 27 17:10:55 2001 @@ -772,6 +772,8 @@ if (mpc == NULL) { dprintk("mpoa: mpoad_attach: allocating new mpc for itf %d\n", arg); mpc = alloc_mpc(); + if (mpc == NULL) + return -ENOMEM; mpc->dev_num = arg; mpc->dev = find_lec_by_itfnum(arg); /* NULL if there was no lec */ } diff -u --recursive --new-file v2.4.5/linux/net/atm/signaling.c linux/net/atm/signaling.c --- v2.4.5/linux/net/atm/signaling.c Fri Dec 29 14:35:47 2000 +++ linux/net/atm/signaling.c Wed Jun 27 17:10:55 2001 @@ -211,14 +211,13 @@ static void sigd_close(struct atm_vcc *vcc) { - struct sk_buff *skb; struct atm_dev *dev; DPRINTK("sigd_close\n"); sigd = NULL; if (skb_peek(&vcc->recvq)) printk(KERN_ERR "sigd_close: closing with requests pending\n"); - while ((skb = skb_dequeue(&vcc->recvq))) kfree_skb(skb); + skb_queue_purge(&vcc->recvq); purge_vccs(nodev_vccs); spin_lock (&atm_dev_lock); diff -u --recursive --new-file v2.4.5/linux/net/ax25/ax25_in.c linux/net/ax25/ax25_in.c --- v2.4.5/linux/net/ax25/ax25_in.c Fri Feb 9 11:30:57 2001 +++ linux/net/ax25/ax25_in.c Fri Jun 29 19:38:26 2001 @@ -83,9 +83,11 @@ /* Last fragment received ? */ if (ax25->fragno == 0) { - if ((skbn = alloc_skb(AX25_MAX_HEADER_LEN + ax25->fraglen, GFP_ATOMIC)) == NULL) { - while ((skbo = skb_dequeue(&ax25->frag_queue)) != NULL) - kfree_skb(skbo); + skbn = alloc_skb(AX25_MAX_HEADER_LEN + + ax25->fraglen, + GFP_ATOMIC); + if (!skbn) { + skb_queue_purge(&ax25->frag_queue); return 1; } @@ -113,8 +115,7 @@ } else { /* First fragment received */ if (*skb->data & AX25_SEG_FIRST) { - while ((skbo = skb_dequeue(&ax25->frag_queue)) != NULL) - kfree_skb(skbo); + skb_queue_purge(&ax25->frag_queue); ax25->fragno = *skb->data & AX25_SEG_REM; skb_pull(skb, 1); /* skip fragno */ ax25->fraglen = skb->len; @@ -416,7 +417,8 @@ /* * Sort out any digipeated paths. */ - if (dp.ndigi != 0 && ax25->digipeat == NULL && (ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) { + if (dp.ndigi && !ax25->digipeat && + (ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) { kfree_skb(skb); ax25_destroy_socket(ax25); return 0; @@ -468,7 +470,8 @@ /* * Receive an AX.25 frame via a SLIP interface. */ -int ax25_kiss_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype) +int ax25_kiss_rcv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *ptype) { skb->sk = NULL; /* Initially we don't know who it's for */ skb->destructor = NULL; /* Who initializes this, dammit?! */ diff -u --recursive --new-file v2.4.5/linux/net/ax25/ax25_ip.c linux/net/ax25/ax25_ip.c --- v2.4.5/linux/net/ax25/ax25_ip.c Fri Dec 29 14:35:47 2000 +++ linux/net/ax25/ax25_ip.c Mon Jul 2 13:56:40 2001 @@ -160,7 +160,7 @@ dst_c = *dst; skb_pull(ourskb, AX25_HEADER_LEN - 1); /* Keep PID */ - skb->nh.raw = skb->data; + ourskb->nh.raw = ourskb->data; ax25_send_frame(ourskb, ax25_dev->values[AX25_VALUES_PACLEN], &src_c, &dst_c, route->digipeat, dev); diff -u --recursive --new-file v2.4.5/linux/net/ax25/ax25_subr.c linux/net/ax25/ax25_subr.c --- v2.4.5/linux/net/ax25/ax25_subr.c Fri Dec 29 14:35:47 2000 +++ linux/net/ax25/ax25_subr.c Fri Jun 29 19:38:26 2001 @@ -59,19 +59,10 @@ */ void ax25_clear_queues(ax25_cb *ax25) { - struct sk_buff *skb; - - while ((skb = skb_dequeue(&ax25->write_queue)) != NULL) - kfree_skb(skb); - - while ((skb = skb_dequeue(&ax25->ack_queue)) != NULL) - kfree_skb(skb); - - while ((skb = skb_dequeue(&ax25->reseq_queue)) != NULL) - kfree_skb(skb); - - while ((skb = skb_dequeue(&ax25->frag_queue)) != NULL) - kfree_skb(skb); + skb_queue_purge(&ax25->write_queue); + skb_queue_purge(&ax25->ack_queue); + skb_queue_purge(&ax25->reseq_queue); + skb_queue_purge(&ax25->frag_queue); } /* diff -u --recursive --new-file v2.4.5/linux/net/bluetooth/Config.in linux/net/bluetooth/Config.in --- v2.4.5/linux/net/bluetooth/Config.in Wed Dec 31 16:00:00 1969 +++ linux/net/bluetooth/Config.in Mon Jun 11 19:15:27 2001 @@ -0,0 +1,16 @@ +# +# Bluetooth configuration +# + +if [ "$CONFIG_NET" != "n" ]; then + mainmenu_option next_comment + comment 'Bluetooth support' + dep_tristate 'Bluetooth subsystem support' CONFIG_BLUEZ $CONFIG_NET + + if [ "$CONFIG_BLUEZ" != "n" ]; then + dep_tristate 'L2CAP protocol support' CONFIG_BLUEZ_L2CAP $CONFIG_BLUEZ + source drivers/bluetooth/Config.in + fi + endmenu +fi + diff -u --recursive --new-file v2.4.5/linux/net/bluetooth/Makefile linux/net/bluetooth/Makefile --- v2.4.5/linux/net/bluetooth/Makefile Wed Dec 31 16:00:00 1969 +++ linux/net/bluetooth/Makefile Mon Jun 11 19:15:27 2001 @@ -0,0 +1,20 @@ +# +# Makefile for the Bluetooth subsystem +# +O_TARGET := bluetooth.o + +list-multi := hci.o l2cap.o +export-objs := syms.o +hci-objs := af_bluetooth.o hci_core.o hci_sock.o lib.o syms.o +l2cap-objs := l2cap_core.o l2cap_proc.o + +obj-$(CONFIG_BLUEZ) += hci.o +obj-$(CONFIG_BLUEZ_L2CAP) += l2cap.o + +include $(TOPDIR)/Rules.make + +hci.o: $(hci-objs) + $(LD) -r -o $@ $(hci-objs) + +l2cap.o: $(l2cap-objs) + $(LD) -r -o $@ $(l2cap-objs) diff -u --recursive --new-file v2.4.5/linux/net/bluetooth/af_bluetooth.c linux/net/bluetooth/af_bluetooth.c --- v2.4.5/linux/net/bluetooth/af_bluetooth.c Wed Dec 31 16:00:00 1969 +++ linux/net/bluetooth/af_bluetooth.c Mon Jun 11 19:15:27 2001 @@ -0,0 +1,164 @@ +/* + BlueZ - Bluetooth protocol stack for Linux + Copyright (C) 2000-2001 Qualcomm Incorporated + + Written 2000,2001 by Maxim Krasnyansky + + 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; + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY + CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, + COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS + SOFTWARE IS DISCLAIMED. +*/ + +/* + * BlueZ Bluetooth address family and sockets. + * + * $Id: af_bluetooth.c,v 1.1 2001/06/01 08:12:11 davem Exp $ + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_KMOD) +#include +#endif + +#include +#include + +/* Bluetooth sockets */ +static struct net_proto_family *bluez_sock[BLUEZ_MAX_PROTO]; + +int bluez_sock_register(int proto, struct net_proto_family *ops) +{ + if (proto > BLUEZ_MAX_PROTO) + return -EINVAL; + + if (bluez_sock[proto]) + return -EEXIST; + + bluez_sock[proto] = ops; + return 0; +} + +int bluez_sock_unregister(int proto) +{ + if (proto > BLUEZ_MAX_PROTO) + return -EINVAL; + + if (!bluez_sock[proto]) + return -ENOENT; + + bluez_sock[proto] = NULL; + return 0; +} + +static int bluez_sock_create(struct socket *sock, int proto) +{ + if (proto > BLUEZ_MAX_PROTO) + return -EINVAL; + +#if defined(CONFIG_KMOD) + if (!bluez_sock[proto]) { + char module_name[30]; + sprintf(module_name, "bt-proto-%d", proto); + request_module(module_name); + } +#endif + + if (!bluez_sock[proto]) + return -ENOENT; + + return bluez_sock[proto]->create(sock, proto); +} + +void bluez_sock_link(struct bluez_sock_list *l, struct sock *sk) +{ + write_lock(&l->lock); + + sk->next = l->head; + l->head = sk; + sock_hold(sk); + + write_unlock(&l->lock); +} + +void bluez_sock_unlink(struct bluez_sock_list *l, struct sock *sk) +{ + struct sock **skp; + + write_lock(&l->lock); + for (skp = &l->head; *skp; skp = &((*skp)->next)) { + if (*skp == sk) { + *skp = sk->next; + __sock_put(sk); + break; + } + } + write_unlock(&l->lock); +} + +struct net_proto_family bluez_sock_family_ops = +{ + PF_BLUETOOTH, bluez_sock_create +}; + +int bluez_init(void) +{ + INF("BlueZ HCI Core ver %s Copyright (C) 2000,2001 Qualcomm Inc", + BLUEZ_VER); + INF("Written 2000,2001 by Maxim Krasnyansky "); + + proc_mkdir("bluetooth", NULL); + + sock_register(&bluez_sock_family_ops); + + /* Init HCI Core */ + hci_core_init(); + + /* Init sockets */ + hci_sock_init(); + + return 0; +} + +void bluez_cleanup(void) +{ + /* Release socket */ + hci_sock_cleanup(); + + /* Release core */ + hci_core_cleanup(); + + sock_unregister(PF_BLUETOOTH); + + remove_proc_entry("bluetooth", NULL); +} + +#ifdef MODULE +module_init(bluez_init); +module_exit(bluez_cleanup); +#endif diff -u --recursive --new-file v2.4.5/linux/net/bluetooth/hci_core.c linux/net/bluetooth/hci_core.c --- v2.4.5/linux/net/bluetooth/hci_core.c Wed Dec 31 16:00:00 1969 +++ linux/net/bluetooth/hci_core.c Mon Jun 11 19:15:27 2001 @@ -0,0 +1,1870 @@ +/* + BlueZ - Bluetooth protocol stack for Linux + Copyright (C) 2000-2001 Qualcomm Incorporated + + Written 2000,2001 by Maxim Krasnyansky + + 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; + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY + CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, + COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS + SOFTWARE IS DISCLAIMED. +*/ + +/* + * BlueZ HCI Core. + * + * $Id: hci_core.c,v 1.2 2001/06/01 16:57:03 davem Exp $ + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#ifndef HCI_CORE_DEBUG +#undef DBG +#define DBG( A... ) +#endif + +static void hci_cmd_task(unsigned long arg); +static void hci_rx_task(unsigned long arg); +static void hci_tx_task(unsigned long arg); +static void hci_notify(struct hci_dev *hdev, int event); + +static rwlock_t hci_task_lock = RW_LOCK_UNLOCKED; + +/* HCI device list */ +struct hci_dev *hdev_list[HCI_MAX_DEV]; +spinlock_t hdev_list_lock; +#define GET_HDEV(a) (hdev_list[a]) + +/* HCI protocol list */ +struct hci_proto *hproto_list[HCI_MAX_PROTO]; +#define GET_HPROTO(a) (hproto_list[a]) + +/* HCI notifiers list */ +struct notifier_block *hci_dev_notifier; + +/* HCI device notifications */ +int hci_register_notifier(struct notifier_block *nb) +{ + int err, i; + struct hci_dev *hdev; + + if ((err = notifier_chain_register(&hci_dev_notifier, nb))) + return err; + + /* Notify about already registered devices */ + spin_lock(&hdev_list_lock); + for (i = 0; i < HCI_MAX_DEV; i++) { + if (!(hdev = GET_HDEV(i))) + continue; + if (hdev->flags & HCI_UP) + (*nb->notifier_call)(nb, HCI_DEV_UP, hdev); + } + spin_unlock(&hdev_list_lock); + + return 0; +} + +int hci_unregister_notifier(struct notifier_block *nb) +{ + return notifier_chain_unregister(&hci_dev_notifier, nb); +} + +static __inline__ void hci_notify(struct hci_dev *hdev, int event) +{ + notifier_call_chain(&hci_dev_notifier, event, hdev); +} + +/* Get HCI device by index (device is locked on return)*/ +struct hci_dev *hci_dev_get(int index) +{ + struct hci_dev *hdev; + DBG("%d", index); + + if (index < 0 || index >= HCI_MAX_DEV) + return NULL; + + spin_lock(&hdev_list_lock); + if ((hdev = GET_HDEV(index))) + hci_dev_hold(hdev); + spin_unlock(&hdev_list_lock); + + return hdev; +} + +/* Flush inquiry cache */ +void inquiry_cache_flush(struct inquiry_cache *cache) +{ + struct inquiry_entry *next = cache->list, *e; + + DBG("cache %p", cache); + + cache->list = NULL; + while ((e = next)) { + next = e->next; + kfree(e); + } +} + +/* Lookup by bdaddr. + * Cache must be locked. */ +static struct inquiry_entry * __inquiry_cache_lookup(struct inquiry_cache *cache, bdaddr_t *bdaddr) +{ + struct inquiry_entry *e; + + DBG("cache %p, %s", cache, batostr(bdaddr)); + + for (e = cache->list; e; e = e->next) + if (!bacmp(&e->info.bdaddr, bdaddr)) + break; + + return e; +} + +static void inquiry_cache_update(struct inquiry_cache *cache, inquiry_info *info) +{ + struct inquiry_entry *e; + + DBG("cache %p, %s", cache, batostr(&info->bdaddr)); + + inquiry_cache_lock(cache); + + if (!(e = __inquiry_cache_lookup(cache, &info->bdaddr))) { + /* Entry not in the cache. Add new one. */ + if (!(e = kmalloc(sizeof(struct inquiry_entry), GFP_ATOMIC))) + goto unlock; + memset(e, 0, sizeof(struct inquiry_entry)); + e->next = cache->list; + cache->list = e; + } + + memcpy(&e->info, info, sizeof(inquiry_info)); + e->timestamp = jiffies; + cache->timestamp = jiffies; +unlock: + inquiry_cache_unlock(cache); +} + +static int inquiry_cache_dump(struct inquiry_cache *cache, int num, __u8 *buf) +{ + inquiry_info *info = (inquiry_info *) buf; + struct inquiry_entry *e; + int copied = 0; + + inquiry_cache_lock(cache); + + for (e = cache->list; e && copied < num; e = e->next, copied++) + memcpy(info++, &e->info, sizeof(inquiry_info)); + + inquiry_cache_unlock(cache); + + DBG("cache %p, copied %d", cache, copied); + return copied; +} + +/* --------- BaseBand connections --------- */ +static struct hci_conn *hci_conn_add(struct hci_dev *hdev, __u16 handle, bdaddr_t *dst) +{ + struct hci_conn *conn; + + DBG("%s handle %d dst %s", hdev->name, handle, batostr(dst)); + + if (handle > HCI_MAX_CONN) { + ERR("%s BUG handle %d is to large", hdev->name, handle); + return NULL; + } + + if (!(conn = kmalloc(sizeof(struct hci_conn), GFP_ATOMIC))) + return NULL; + memset(conn, 0, sizeof(struct hci_conn)); + + bacpy(&conn->dst, dst); + conn->handle = handle; + conn->hdev = hdev; + + skb_queue_head_init(&conn->acl_q); + skb_queue_head_init(&conn->sco_q); + + if (conn_hash_add(&hdev->conn_hash, handle, conn)) { + hci_dev_hold(hdev); + return conn; + } else { + kfree(conn); + return NULL; + } +} + +static int hci_conn_del(struct hci_dev *hdev, struct hci_conn *conn) +{ + DBG("%s conn %p handle %d", hdev->name, conn, conn->handle); + + if (conn_hash_del(&hdev->conn_hash, conn->handle)) { + hci_dev_put(hdev); + + /* Unacked frames */ + hdev->acl_cnt += conn->acl_sent; + } + + bluez_skb_queue_purge(&conn->acl_q); + bluez_skb_queue_purge(&conn->sco_q); + + kfree(conn); + return 0; +} + +/* Drop all connection on the device */ +static void hci_conn_hash_flush(struct hci_dev *hdev) +{ + struct hci_proto *hp = GET_HPROTO(HCI_PROTO_L2CAP); + struct conn_hash *h = &hdev->conn_hash; + int i; + + DBG("hdev %s", hdev->name); + + for (i = 0; i < HCI_MAX_CONN; i++) { + struct hci_conn *conn; + + if (!(conn = conn_hash_lookup(h, i))) + continue; + + if (hp && hp->disconn_ind) + hp->disconn_ind(conn, 0x16); + + hci_conn_del(hdev, conn); + } +} + +int hci_connect(struct hci_dev *hdev, bdaddr_t *bdaddr) +{ + struct inquiry_cache *cache = &hdev->inq_cache; + struct inquiry_entry *e; + create_conn_cp cc; + __u16 clock_offset; + + DBG("%s bdaddr %s", hdev->name, batostr(bdaddr)); + + if (!(hdev->flags & HCI_UP)) + return -ENODEV; + + inquiry_cache_lock_bh(cache); + + if (!(e = __inquiry_cache_lookup(cache, bdaddr)) || inquiry_entry_age(e) > INQUIRY_ENTRY_AGE_MAX) { + cc.pscan_rep_mode = 0; + cc.pscan_mode = 0; + clock_offset = 0; + } else { + cc.pscan_rep_mode = e->info.pscan_rep_mode; + cc.pscan_mode = e->info.pscan_mode; + clock_offset = __le16_to_cpu(e->info.clock_offset) & 0x8000; + } + + inquiry_cache_unlock_bh(cache); + + bacpy(&cc.bdaddr, bdaddr); + cc.pkt_type = __cpu_to_le16(HCI_DM1 | HCI_DM3 | HCI_DM5 | HCI_DH1 | HCI_DH3 | HCI_DH5); + cc.clock_offset = __cpu_to_le16(clock_offset); + cc.role_switch = 0; + hci_send_cmd(hdev, OGF_LINK_CTL, OCF_CREATE_CONN, CREATE_CONN_CP_SIZE, &cc); + + return 0; +} + +int hci_disconnect(struct hci_conn *conn, __u8 reason) +{ + disconnect_cp dc; + + DBG("conn %p handle %d", conn, conn->handle); + + dc.handle = __cpu_to_le16(conn->handle); + dc.reason = reason; + hci_send_cmd(conn->hdev, OGF_LINK_CTL, OCF_DISCONNECT, DISCONNECT_CP_SIZE, &dc); + + return 0; +} + +/* --------- HCI request handling ------------ */ +static __inline__ void hci_req_lock(struct hci_dev *hdev) +{ + down(&hdev->req_lock); +} + +static __inline__ void hci_req_unlock(struct hci_dev *hdev) +{ + up(&hdev->req_lock); +} + +static __inline__ void hci_req_complete(struct hci_dev *hdev, int result) +{ + DBG("%s result 0x%2.2x", hdev->name, result); + + if (hdev->req_status == HCI_REQ_PEND) { + hdev->req_result = result; + hdev->req_status = HCI_REQ_DONE; + wake_up_interruptible(&hdev->req_wait_q); + } +} + +static __inline__ void hci_req_cancel(struct hci_dev *hdev, int err) +{ + DBG("%s err 0x%2.2x", hdev->name, err); + + if (hdev->req_status == HCI_REQ_PEND) { + hdev->req_result = err; + hdev->req_status = HCI_REQ_CANCELED; + wake_up_interruptible(&hdev->req_wait_q); + } +} + +/* Execute request and wait for completion. */ +static int __hci_request(struct hci_dev *hdev, void (*req)(struct hci_dev *hdev, unsigned long opt), + unsigned long opt, __u32 timeout) +{ + DECLARE_WAITQUEUE(wait, current); + int err = 0; + + DBG("%s start", hdev->name); + + hdev->req_status = HCI_REQ_PEND; + + add_wait_queue(&hdev->req_wait_q, &wait); + current->state = TASK_INTERRUPTIBLE; + + req(hdev, opt); + schedule_timeout(timeout); + + current->state = TASK_RUNNING; + remove_wait_queue(&hdev->req_wait_q, &wait); + + if (signal_pending(current)) + return -EINTR; + + switch (hdev->req_status) { + case HCI_REQ_DONE: + err = -bterr(hdev->req_result); + break; + + case HCI_REQ_CANCELED: + err = -hdev->req_result; + break; + + default: + err = -ETIMEDOUT; + break; + }; + + hdev->req_status = hdev->req_result = 0; + + DBG("%s end: err %d", hdev->name, err); + + return err; +} + +static __inline__ int hci_request(struct hci_dev *hdev, void (*req)(struct hci_dev *hdev, unsigned long opt), + unsigned long opt, __u32 timeout) +{ + int ret; + + /* Serialize all requests */ + hci_req_lock(hdev); + ret = __hci_request(hdev, req, opt, timeout); + hci_req_unlock(hdev); + + return ret; +} + +/* --------- HCI requests ---------- */ +static void hci_reset_req(struct hci_dev *hdev, unsigned long opt) +{ + DBG("%s %ld", hdev->name, opt); + + /* Reset device */ + hci_send_cmd(hdev, OGF_HOST_CTL, OCF_RESET, 0, NULL); +} + +static void hci_init_req(struct hci_dev *hdev, unsigned long opt) +{ + set_event_flt_cp ec; + __u16 param; + + DBG("%s %ld", hdev->name, opt); + + /* Mandatory initialization */ + + /* Read Buffer Size (ACL mtu, max pkt, etc.) */ + hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_BUFFER_SIZE, 0, NULL); + + /* Read BD Address */ + hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_BD_ADDR, 0, NULL); + + /* Optional initialization */ + + /* Clear Event Filters */ + ec.flt_type = FLT_CLEAR_ALL; + ec.cond_type = 0; + hci_send_cmd(hdev, OGF_HOST_CTL, OCF_SET_EVENT_FLT, SET_EVENT_FLT_CP_SIZE, &ec); + + /* Page timeout ~ 20 secs */ + param = __cpu_to_le16(0x8000); + hci_send_cmd(hdev, OGF_HOST_CTL, OCF_WRITE_PG_TIMEOUT, 2, ¶m); + + /* Connection accept timeout ~20 secs */ + param = __cpu_to_le16(0x7d00); + hci_send_cmd(hdev, OGF_HOST_CTL, OCF_WRITE_CA_TIMEOUT, 2, ¶m); +} + +static void hci_scan_req(struct hci_dev *hdev, unsigned long opt) +{ + __u8 scan = opt; + + DBG("%s %x", hdev->name, scan); + + /* Inquiry and Page scans */ + hci_send_cmd(hdev, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE, 1, &scan); +} + +static void hci_auth_req(struct hci_dev *hdev, unsigned long opt) +{ + __u8 auth = opt; + + DBG("%s %x", hdev->name, auth); + + /* Authentication */ + hci_send_cmd(hdev, OGF_HOST_CTL, OCF_WRITE_AUTH_ENABLE, 1, &auth); +} + +static void hci_inq_req(struct hci_dev *hdev, unsigned long opt) +{ + struct hci_inquiry_req *ir = (struct hci_inquiry_req *) opt; + inquiry_cp ic; + + DBG("%s", hdev->name); + + /* Start Inquiry */ + memcpy(&ic.lap, &ir->lap, 3); + ic.lenght = ir->length; + ic.num_rsp = ir->num_rsp; + hci_send_cmd(hdev, OGF_LINK_CTL, OCF_INQUIRY, INQUIRY_CP_SIZE, &ic); +} + +/* Open HCI device */ +int hci_dev_open(__u16 dev) +{ + struct hci_dev *hdev; + int ret = 0; + + if (!(hdev = hci_dev_get(dev))) + return -ENODEV; + + DBG("%s %p", hdev->name, hdev); + + hci_req_lock(hdev); + + if (hdev->flags & HCI_UP) { + ret = -EALREADY; + goto done; + } + + /* Initialize device */ + if (hdev->open(hdev)) { + ret = -EIO; + goto done; + } + + atomic_set(&hdev->cmd_cnt, 1); + hdev->cmd_sent= NULL; + hdev->flags |= HCI_INIT; + + __hci_request(hdev, hci_reset_req, 0, HZ); + + if (!(ret = __hci_request(hdev, hci_init_req, 0, HCI_INIT_TIMEOUT))) { + hdev->flags |= HCI_UP; + hci_notify(hdev, HCI_DEV_UP); + } + + hdev->flags &= ~HCI_INIT; + +done: + hci_req_unlock(hdev); + hci_dev_put(hdev); + + return ret; +} + +/* Close HCI device */ +int hci_dev_close(__u16 dev) +{ + struct hci_dev *hdev; + + if (!(hdev = hci_dev_get(dev))) + return -ENODEV; + + DBG("%s %p", hdev->name, hdev); + + hci_req_cancel(hdev, ENODEV); + hci_req_lock(hdev); + + if (!(hdev->flags & HCI_UP)) + goto done; + + /* Kill RX and TX tasks */ + tasklet_kill(&hdev->rx_task); + tasklet_kill(&hdev->tx_task); + + inquiry_cache_flush(&hdev->inq_cache); + + hci_conn_hash_flush(hdev); + + /* Clear flags */ + hdev->flags &= (HCI_NORMAL | HCI_SOCK); + + hci_notify(hdev, HCI_DEV_DOWN); + + if (hdev->flush) + hdev->flush(hdev); + + /* Reset device */ + bluez_skb_queue_purge(&hdev->cmd_q); + atomic_set(&hdev->cmd_cnt, 1); + hdev->flags |= HCI_INIT; + __hci_request(hdev, hci_reset_req, 0, HZ); + hdev->flags &= ~HCI_INIT; + + /* Kill cmd task */ + tasklet_kill(&hdev->cmd_task); + + /* Drop queues */ + bluez_skb_queue_purge(&hdev->rx_q); + bluez_skb_queue_purge(&hdev->cmd_q); + bluez_skb_queue_purge(&hdev->raw_q); + + /* Drop last sent command */ + if (hdev->cmd_sent) { + bluez_skb_free(hdev->cmd_sent); + hdev->cmd_sent = NULL; + } + + /* After this point our queues are empty + * and no tasks are scheduled. + */ + hdev->close(hdev); + +done: + hci_req_unlock(hdev); + hci_dev_put(hdev); + + return 0; +} + +/* Interface to HCI drivers */ + +/* Register HCI device */ +int hci_register_dev(struct hci_dev *hdev) +{ + int i; + + DBG("%p name %s type %d", hdev, hdev->name, hdev->type); + + /* Find free slot */ + spin_lock_bh(&hdev_list_lock); + for (i = 0; i < HCI_MAX_DEV; i++) { + if (!hdev_list[i]) { + hdev_list[i] = hdev; + + sprintf(hdev->name, "hci%d", i); + atomic_set(&hdev->refcnt, 0); + hdev->id = i; + hdev->flags = HCI_NORMAL; + + tasklet_init(&hdev->cmd_task, hci_cmd_task, (unsigned long) hdev); + tasklet_init(&hdev->rx_task, hci_rx_task, (unsigned long) hdev); + tasklet_init(&hdev->tx_task, hci_tx_task, (unsigned long) hdev); + + skb_queue_head_init(&hdev->rx_q); + skb_queue_head_init(&hdev->cmd_q); + skb_queue_head_init(&hdev->raw_q); + + init_waitqueue_head(&hdev->req_wait_q); + init_MUTEX(&hdev->req_lock); + + inquiry_cache_init(&hdev->inq_cache); + + conn_hash_init(&hdev->conn_hash); + + memset(&hdev->stat, 0, sizeof(struct hci_dev_stats)); + + hci_notify(hdev, HCI_DEV_REG); + + MOD_INC_USE_COUNT; + break; + } + } + spin_unlock_bh(&hdev_list_lock); + + return (i == HCI_MAX_DEV) ? -1 : i; +} + +/* Unregister HCI device */ +int hci_unregister_dev(struct hci_dev *hdev) +{ + int i; + + DBG("%p name %s type %d", hdev, hdev->name, hdev->type); + + if (hdev->flags & HCI_UP) + hci_dev_close(hdev->id); + + /* Find device slot */ + spin_lock(&hdev_list_lock); + for (i = 0; i < HCI_MAX_DEV; i++) { + if (hdev_list[i] == hdev) { + hdev_list[i] = NULL; + MOD_DEC_USE_COUNT; + break; + } + } + spin_unlock(&hdev_list_lock); + + hci_notify(hdev, HCI_DEV_UNREG); + + /* Sleep while device is in use */ + while (atomic_read(&hdev->refcnt)) { + int sleep_cnt = 100; + + DBG("%s sleeping on lock %d", hdev->name, atomic_read(&hdev->refcnt)); + + sleep_on_timeout(&hdev->req_wait_q, HZ*10); + if (!(--sleep_cnt)) + break; + } + + return 0; +} + +/* Interface to upper protocols */ + +/* Register/Unregister protocols. + * hci_task_lock is used to ensure that no tasks are running. + */ +int hci_register_proto(struct hci_proto *hproto) +{ + int err = 0; + + DBG("%p name %s", hproto, hproto->name); + + if (hproto->id >= HCI_MAX_PROTO) + return -EINVAL; + + write_lock_bh(&hci_task_lock); + + if (!hproto_list[hproto->id]) + hproto_list[hproto->id] = hproto; + else + err = -1; + + write_unlock_bh(&hci_task_lock); + + return err; +} + +int hci_unregister_proto(struct hci_proto *hproto) +{ + int err = 0; + + DBG("%p name %s", hproto, hproto->name); + + if (hproto->id > HCI_MAX_PROTO) + return -EINVAL; + + write_lock_bh(&hci_task_lock); + + if (hproto_list[hproto->id]) + hproto_list[hproto->id] = NULL; + else + err = -ENOENT; + + write_unlock_bh(&hci_task_lock); + + return err; +} + +static int hci_send_frame(struct sk_buff *skb) +{ + struct hci_dev *hdev = (struct hci_dev *) skb->dev; + + if (!hdev) { + bluez_skb_free(skb); + return -ENODEV; + } + + DBG("%s type %d len %d", hdev->name, skb->pkt_type, skb->len); + + if (hdev->flags & HCI_SOCK) + hci_send_to_sock(hdev, skb); + + /* Get rid of skb owner, prior to sending to the driver. */ + skb_orphan(skb); + + return hdev->send(skb); +} + +/* ACL scheduler */ +static __inline__ struct hci_conn *hci_low_acl_sent(struct hci_dev *hdev, int *quote) +{ + struct conn_hash *h = &hdev->conn_hash; + struct hci_conn *conn = NULL; + int i, num = 0, min = 0xffff; + + conn_hash_lock(h); + for (i = 0; i < HCI_MAX_CONN; i++) { + struct hci_conn *c; + + if (!(c = __conn_hash_lookup(h,i)) || !skb_queue_len(&c->acl_q)) + continue; + num++; + + if (c->acl_sent < min) { + min = c->acl_sent; + conn = c; + } + } + conn_hash_unlock(h); + + if (conn) { + int q = hdev->acl_cnt / num; + *quote = q ? q : 1; + } else + *quote = 0; + + DBG("conn %p quote %d", conn, *quote); + + return conn; +} + +static __inline__ void hci_sched_acl(struct hci_dev *hdev) +{ + struct hci_conn *conn; + struct sk_buff *skb, *frag; + int quote; + + DBG("%s", hdev->name); + + while (hdev->acl_cnt) { + if (!(conn = hci_low_acl_sent(hdev, "e))) + break; + + while (quote && (skb = skb_peek(&conn->acl_q))) { + if (bluez_skb_frags(skb)+1 > hdev->acl_cnt) { + /* FIXME: Schedule next connection */ + goto done; + } + + if (!(frag = bluez_skb_clone(skb, GFP_ATOMIC))) + break; + + skb_unlink(skb); + do { + DBG("frag %p len %d", frag, frag->len); + + hci_send_frame(frag); + + conn->acl_sent++; + hdev->acl_cnt--; + quote--; + } while ((frag = bluez_skb_get_frag(skb))); + kfree_skb(skb); + } + } +done: + return; +} + +/* Schedule SCO */ +static __inline__ void hci_sched_sco(struct hci_dev *hdev) +{ + struct conn_hash *h = &hdev->conn_hash; + struct sk_buff *skb; + int i; + + DBG("%s", hdev->name); + + conn_hash_lock(h); + for (i = 0; i< HCI_MAX_CONN; i++) { + struct hci_conn *conn; + + if (!(conn = __conn_hash_lookup(h, i))) + continue; + + while (hdev->sco_cnt && (skb = skb_dequeue(&conn->sco_q))) { + hci_send_frame(skb); + conn->sco_sent++; + hdev->sco_cnt--; + } + } + conn_hash_unlock(h); +} + +/* Send raw HCI frame */ +int hci_send_raw(struct sk_buff *skb) +{ + struct hci_dev *hdev = (struct hci_dev *) skb->dev; + + if (!hdev) { + bluez_skb_free(skb); + return -ENODEV; + } + + DBG("%s type %d len %d", hdev->name, skb->pkt_type, skb->len); + + /* Queue frame according it's type */ + switch (skb->pkt_type) { + case HCI_COMMAND_PKT: + skb_queue_tail(&hdev->cmd_q, skb); + hci_sched_cmd(hdev); + break; + + case HCI_ACLDATA_PKT: + case HCI_SCODATA_PKT: + /* FIXME: + * Check header here and queue to aproptiate connection. + */ + default: + skb_queue_tail(&hdev->raw_q, skb); + hci_sched_tx(hdev); + + return 0; + }; + + return 0; +} + +/* Send HCI command */ +int hci_send_cmd(struct hci_dev *hdev, __u16 ogf, __u16 ocf, __u32 plen, void *param) +{ + int len = HCI_COMMAND_HDR_SIZE + plen; + hci_command_hdr *hc; + struct sk_buff *skb; + + DBG("%s ogf 0x%x ocf 0x%x plen %d", hdev->name, ogf, ocf, plen); + + if (!(skb = bluez_skb_alloc(len, GFP_ATOMIC))) { + ERR("%s Can't allocate memory for HCI command", hdev->name); + return -ENOMEM; + } + + hc = (hci_command_hdr *) skb_put(skb, HCI_COMMAND_HDR_SIZE); + hc->opcode = __cpu_to_le16(cmd_opcode_pack(ocf, ogf)); + hc->plen = plen; + + if (plen) + memcpy(skb_put(skb, plen), param, plen); + + DBG("skb len %d", skb->len); + + skb->pkt_type = HCI_COMMAND_PKT; + skb->dev = (void *) hdev; + skb_queue_tail(&hdev->cmd_q, skb); + hci_sched_cmd(hdev); + + return 0; +} + +/* Send ACL data */ + +static void hci_add_acl_hdr(struct sk_buff *skb, __u16 handle, __u16 flags) +{ + int len = skb->len; + hci_acl_hdr *ah; + + ah = (hci_acl_hdr *) skb_push(skb, HCI_ACL_HDR_SIZE); + ah->handle = __cpu_to_le16(acl_handle_pack(handle, flags)); + ah->dlen = __cpu_to_le16(len); + + skb->h.raw = (void *) ah; +} + +int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags) +{ + struct hci_dev *hdev = conn->hdev; + struct sk_buff *frag; + int sent = 0; + + DBG("%s conn %p len %d flags 0x%x", hdev->name, conn, skb->len, flags); + DBG("frags %d", bluez_skb_frags(skb)); + + /* Add ACL header to all fragments */ + flags |= ACL_START; + frag = skb; + do { + DBG("frag %p len %d", frag, frag->len); + sent += frag->len; + + hci_add_acl_hdr(frag, conn->handle, flags); + frag->pkt_type = HCI_ACLDATA_PKT; + frag->dev = (void *) hdev; + + flags = ACL_CONT; + } while ((frag = bluez_skb_next_frag(frag))); + + skb_queue_tail(&conn->acl_q, skb); + hci_sched_tx(hdev); + + return sent; +} + +/* Send SCO data */ +int hci_send_sco(struct hci_conn *conn, struct sk_buff *skb) +{ + struct hci_dev *hdev = conn->hdev; + hci_sco_hdr hs; + + DBG("%s len %d", hdev->name, skb->len); + + if (skb->len > hdev->sco_mtu) { + bluez_skb_free(skb); + return -EINVAL; + } + + hs.handle = __cpu_to_le16(conn->handle); + hs.dlen = skb->len; + + skb->h.raw = skb_push(skb, HCI_SCO_HDR_SIZE); + memcpy(skb->h.raw, &hs, HCI_SCO_HDR_SIZE); + + skb->dev = (void *) hdev; + skb->pkt_type = HCI_SCODATA_PKT; + skb_queue_tail(&conn->sco_q, skb); + hci_sched_tx(hdev); + + return 0; +} + +/* Handle HCI Event packets */ + +/* Command Complete OGF LINK_CTL */ +static void hci_cc_link_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb) +{ + DBG("%s ocf 0x%x", hdev->name, ocf); + + switch (ocf) { + default: + DBG("%s Command complete: ogf LINK_CTL ocf %x", hdev->name, ocf); + break; + }; +} + +/* Command Complete OGF LINK_POLICY */ +static void hci_cc_link_policy(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb) +{ + DBG("%s ocf 0x%x", hdev->name, ocf); + + switch (ocf) { + default: + DBG("%s: Command complete: ogf LINK_POLICY ocf %x", hdev->name, ocf); + break; + }; +} + +/* Command Complete OGF HOST_CTL */ +static void hci_cc_host_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb) +{ + __u8 status, param; + + DBG("%s ocf 0x%x", hdev->name, ocf); + + switch (ocf) { + case OCF_RESET: + status = *((__u8 *) skb->data); + + hci_req_complete(hdev, status); + break; + + case OCF_SET_EVENT_FLT: + status = *((__u8 *) skb->data); + + if (status) { + DBG("%s SET_EVENT_FLT failed %d", hdev->name, status); + } else { + DBG("%s SET_EVENT_FLT succeseful", hdev->name); + } + break; + + case OCF_WRITE_AUTH_ENABLE: + status = *((__u8 *) skb->data); + param = *(SENT_CMD_PARAM(hdev)); + + if (!status) { + if (param == AUTH_ENABLED) + hdev->flags |= HCI_AUTH; + else + hdev->flags &= ~HCI_AUTH; + } + hci_req_complete(hdev, status); + break; + + case OCF_WRITE_CA_TIMEOUT: + status = *((__u8 *) skb->data); + + if (status) { + DBG("%s OCF_WRITE_CA_TIMEOUT failed %d", hdev->name, status); + } else { + DBG("%s OCF_WRITE_CA_TIMEOUT succeseful", hdev->name); + } + break; + + case OCF_WRITE_PG_TIMEOUT: + status = *((__u8 *) skb->data); + + if (status) { + DBG("%s OCF_WRITE_PG_TIMEOUT failed %d", hdev->name, status); + } else { + DBG("%s: OCF_WRITE_PG_TIMEOUT succeseful", hdev->name); + } + break; + + case OCF_WRITE_SCAN_ENABLE: + status = *((__u8 *) skb->data); + param = *(SENT_CMD_PARAM(hdev)); + + if (!status) { + switch (param) { + case IS_ENA_PS_ENA: + hdev->flags |= HCI_PSCAN | HCI_ISCAN; + break; + + case IS_ENA_PS_DIS: + hdev->flags &= ~HCI_PSCAN; + hdev->flags |= HCI_ISCAN; + break; + + case IS_DIS_PS_ENA: + hdev->flags &= ~HCI_ISCAN; + hdev->flags |= HCI_PSCAN; + break; + + default: + hdev->flags &= ~(HCI_ISCAN | HCI_PSCAN); + break; + }; + } + hci_req_complete(hdev, status); + break; + + default: + DBG("%s Command complete: ogf HOST_CTL ocf %x", hdev->name, ocf); + break; + }; +} + +/* Command Complete OGF INFO_PARAM */ +static void hci_cc_info_param(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb) +{ + read_buffer_size_rp *rsp; + read_bd_addr_rp *rap; + + DBG("%s ocf 0x%x", hdev->name, ocf); + + switch (ocf) { + case OCF_READ_BUFFER_SIZE: + rsp = (read_buffer_size_rp *) skb->data; + + if (rsp->status) { + DBG("%s READ_BUFFER_SIZE failed %d", hdev->name, rsp->status); + break; + } + + hdev->acl_mtu = __le16_to_cpu(rsp->acl_mtu); + hdev->sco_mtu = rsp->sco_mtu; + hdev->acl_max = hdev->acl_cnt = __le16_to_cpu(rsp->acl_max_pkt); + hdev->sco_max = hdev->sco_cnt = __le16_to_cpu(rsp->sco_max_pkt); + + DBG("%s mtu: acl %d, sco %d max_pkt: acl %d, sco %d", hdev->name, + hdev->acl_mtu, hdev->sco_mtu, hdev->acl_max, hdev->sco_max); + + break; + + case OCF_READ_BD_ADDR: + rap = (read_bd_addr_rp *) skb->data; + + if (!rap->status) { + bacpy(&hdev->bdaddr, &rap->bdaddr); + } else { + DBG("%s: READ_BD_ADDR failed %d", hdev->name, rap->status); + } + + hci_req_complete(hdev, rap->status); + break; + + default: + DBG("%s Command complete: ogf INFO_PARAM ocf %x", hdev->name, ocf); + break; + }; +} + +/* Command Status OGF LINK_CTL */ +static void hci_cs_link_ctl(struct hci_dev *hdev, __u16 ocf, __u8 status) +{ + struct hci_proto * hp; + + DBG("%s ocf 0x%x", hdev->name, ocf); + + switch (ocf) { + case OCF_CREATE_CONN: + if (status) { + create_conn_cp *cc = (void *) SENT_CMD_PARAM(hdev); + DBG("%s Create connection error: status 0x%x %s", hdev->name, + status, batostr(&cc->bdaddr)); + + /* Notify upper protocols */ + if ((hp = GET_HPROTO(HCI_PROTO_L2CAP)) && hp->connect_cfm) { + tasklet_disable(&hdev->tx_task); + hp->connect_cfm(hdev, &cc->bdaddr, status, NULL); + tasklet_enable(&hdev->tx_task); + } + } + break; + + case OCF_INQUIRY: + if (status) { + DBG("%s Inquiry error: status 0x%x", hdev->name, status); + hci_req_complete(hdev, status); + } + break; + + default: + DBG("%s Command status: ogf LINK_CTL ocf %x", hdev->name, ocf); + break; + }; +} + +/* Command Status OGF LINK_POLICY */ +static void hci_cs_link_policy(struct hci_dev *hdev, __u16 ocf, __u8 status) +{ + DBG("%s ocf 0x%x", hdev->name, ocf); + + switch (ocf) { + default: + DBG("%s Command status: ogf HOST_POLICY ocf %x", hdev->name, ocf); + break; + }; +} + +/* Command Status OGF HOST_CTL */ +static void hci_cs_host_ctl(struct hci_dev *hdev, __u16 ocf, __u8 status) +{ + DBG("%s ocf 0x%x", hdev->name, ocf); + + switch (ocf) { + default: + DBG("%s Command status: ogf HOST_CTL ocf %x", hdev->name, ocf); + break; + }; +} + +/* Command Status OGF INFO_PARAM */ +static void hci_cs_info_param(struct hci_dev *hdev, __u16 ocf, __u8 status) +{ + DBG("%s: hci_cs_info_param: ocf 0x%x", hdev->name, ocf); + + switch (ocf) { + default: + DBG("%s Command status: ogf INFO_PARAM ocf %x", hdev->name, ocf); + break; + }; +} + +/* Inquiry Complete */ +static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) +{ + __u8 status = *((__u8 *) skb->data); + + DBG("%s status %d", hdev->name, status); + + hci_req_complete(hdev, status); +} + +/* Inquiry Result */ +static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) +{ + inquiry_info *info = (inquiry_info *) (skb->data + 1); + int num_rsp = *((__u8 *) skb->data); + + DBG("%s num_rsp %d", hdev->name, num_rsp); + + for (; num_rsp; num_rsp--) + inquiry_cache_update(&hdev->inq_cache, info++); +} + +/* Connect Request */ +static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) +{ + evt_conn_request *cr = (evt_conn_request *) skb->data; + struct hci_proto *hp; + accept_conn_req_cp ac; + int accept = 0; + + DBG("%s Connection request: %s type 0x%x", hdev->name, batostr(&cr->bdaddr), cr->type); + + /* Notify upper protocols */ + if ((hp = GET_HPROTO(HCI_PROTO_L2CAP)) && hp->connect_ind) { + tasklet_disable(&hdev->tx_task); + accept = hp->connect_ind(hdev, &cr->bdaddr); + tasklet_enable(&hdev->tx_task); + } + + if (accept) { + /* Connection accepted by upper layer */ + bacpy(&ac.bdaddr, &cr->bdaddr); + ac.role = 0x01; /* Remain slave */ + hci_send_cmd(hdev, OGF_LINK_CTL, OCF_ACCEPT_CONN_REQ, ACCEPT_CONN_REQ_CP_SIZE, &ac); + } else { + /* Connection rejected by upper layer */ + /* FIXME: + * Should we use HCI reject here ? + */ + return; + } +} + +/* Connect Complete */ +static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) +{ + evt_conn_complete *cc = (evt_conn_complete *) skb->data; + struct hci_conn *conn = NULL; + struct hci_proto *hp; + + DBG("%s", hdev->name); + + tasklet_disable(&hdev->tx_task); + + if (!cc->status) + conn = hci_conn_add(hdev, __le16_to_cpu(cc->handle), &cc->bdaddr); + + /* Notify upper protocols */ + if ((hp = GET_HPROTO(HCI_PROTO_L2CAP)) && hp->connect_cfm) + hp->connect_cfm(hdev, &cc->bdaddr, cc->status, conn); + + tasklet_enable(&hdev->tx_task); +} + +/* Disconnect Complete */ +static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) +{ + evt_disconn_complete *dc = (evt_disconn_complete *) skb->data; + struct hci_conn *conn = NULL; + struct hci_proto *hp; + __u16 handle = __le16_to_cpu(dc->handle); + + DBG("%s", hdev->name); + + if (!dc->status && (conn = conn_hash_lookup(&hdev->conn_hash, handle))) { + tasklet_disable(&hdev->tx_task); + + /* Notify upper protocols */ + if ((hp = GET_HPROTO(HCI_PROTO_L2CAP)) && hp->disconn_ind) + hp->disconn_ind(conn, dc->reason); + + hci_conn_del(hdev, conn); + + tasklet_enable(&hdev->tx_task); + } +} + +/* Number of completed packets */ +static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) +{ + evt_num_comp_pkts *nc = (evt_num_comp_pkts *) skb->data; + __u16 *ptr; + int i; + + skb_pull(skb, EVT_NUM_COMP_PKTS_SIZE); + + DBG("%s num_hndl %d", hdev->name, nc->num_hndl); + + if (skb->len < nc->num_hndl * 4) { + DBG("%s bad parameters", hdev->name); + return; + } + + tasklet_disable(&hdev->tx_task); + + for (i = 0, ptr = (__u16 *) skb->data; i < nc->num_hndl; i++) { + struct hci_conn *conn; + __u16 handle, count; + + handle = __le16_to_cpu(*ptr++); + count = __le16_to_cpu(*ptr++); + + hdev->acl_cnt += count; + + if ((conn = conn_hash_lookup(&hdev->conn_hash, handle))) + conn->acl_sent -= count; + } + + tasklet_enable(&hdev->tx_task); + + hci_sched_tx(hdev); +} + +static __inline__ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) +{ + hci_event_hdr *he = (hci_event_hdr *) skb->data; + evt_cmd_status *cs; + evt_cmd_complete *ec; + __u16 opcode, ocf, ogf; + + skb_pull(skb, HCI_EVENT_HDR_SIZE); + + DBG("%s evt 0x%x", hdev->name, he->evt); + + switch (he->evt) { + case EVT_NUM_COMP_PKTS: + hci_num_comp_pkts_evt(hdev, skb); + break; + + case EVT_INQUIRY_COMPLETE: + hci_inquiry_complete_evt(hdev, skb); + break; + + case EVT_INQUIRY_RESULT: + hci_inquiry_result_evt(hdev, skb); + break; + + case EVT_CONN_REQUEST: + hci_conn_request_evt(hdev, skb); + break; + + case EVT_CONN_COMPLETE: + hci_conn_complete_evt(hdev, skb); + break; + + case EVT_DISCONN_COMPLETE: + hci_disconn_complete_evt(hdev, skb); + break; + + case EVT_CMD_STATUS: + cs = (evt_cmd_status *) skb->data; + skb_pull(skb, EVT_CMD_STATUS_SIZE); + + opcode = __le16_to_cpu(cs->opcode); + ogf = cmd_opcode_ogf(opcode); + ocf = cmd_opcode_ocf(opcode); + + if (cs->ncmd) { + atomic_set(&hdev->cmd_cnt, 1); + hci_sched_cmd(hdev); + } + + switch (ogf) { + case OGF_INFO_PARAM: + hci_cs_info_param(hdev, ocf, cs->status); + break; + + case OGF_HOST_CTL: + hci_cs_host_ctl(hdev, ocf, cs->status); + break; + + case OGF_LINK_CTL: + hci_cs_link_ctl(hdev, ocf, cs->status); + break; + + case OGF_LINK_POLICY: + hci_cs_link_policy(hdev, ocf, cs->status); + break; + + default: + DBG("%s Command Status OGF %x", hdev->name, ogf); + break; + }; + + break; + + case EVT_CMD_COMPLETE: + ec = (evt_cmd_complete *) skb->data; + skb_pull(skb, EVT_CMD_COMPLETE_SIZE); + + opcode = __le16_to_cpu(ec->opcode); + ogf = cmd_opcode_ogf(opcode); + ocf = cmd_opcode_ocf(opcode); + + if (ec->ncmd) { + atomic_set(&hdev->cmd_cnt, 1); + hci_sched_cmd(hdev); + } + + switch (ogf) { + case OGF_INFO_PARAM: + hci_cc_info_param(hdev, ocf, skb); + break; + + case OGF_HOST_CTL: + hci_cc_host_ctl(hdev, ocf, skb); + break; + + case OGF_LINK_CTL: + hci_cc_link_ctl(hdev, ocf, skb); + break; + + case OGF_LINK_POLICY: + hci_cc_link_policy(hdev, ocf, skb); + break; + + default: + DBG("%s Command Completed OGF %x", hdev->name, ogf); + break; + }; + + break; + }; + + bluez_skb_free(skb); + hdev->stat.evt_rx++; +} + +/* ACL data packet */ +static __inline__ void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb) +{ + hci_acl_hdr *ah = (void *) skb->data; + struct hci_conn *conn; + __u16 handle, flags; + + skb_pull(skb, HCI_ACL_HDR_SIZE); + + handle = __le16_to_cpu(ah->handle); + flags = acl_flags(handle); + handle = acl_handle(handle); + + DBG("%s len %d handle 0x%x flags 0x%x", hdev->name, skb->len, handle, flags); + + if ((conn = conn_hash_lookup(&hdev->conn_hash, handle))) { + struct hci_proto *hp; + + /* Send to upper protocol */ + if ((hp = GET_HPROTO(HCI_PROTO_L2CAP)) && hp->recv_acldata) + hp->recv_acldata(conn, skb, flags); + else + bluez_skb_free(skb); + } + + hdev->stat.acl_rx++; +} + +/* SCO data packet */ +static __inline__ void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb) +{ + hci_sco_hdr *sh = (void *) skb->data; + struct hci_conn *conn; + + skb_pull(skb, HCI_SCO_HDR_SIZE); + + DBG("%s len %d", hdev->name, skb->len); + + if ((conn = conn_hash_lookup(&hdev->conn_hash, __le16_to_cpu(sh->handle)))) { + struct hci_proto *hp; + + /* Send to upper protocol */ + if ((hp = GET_HPROTO(HCI_PROTO_L2CAP)) && hp->recv_acldata) + hp->recv_scodata(conn, skb); + else + bluez_skb_free(skb); + } + + hdev->stat.sco_rx++; +} + +/* ----- HCI tasks ----- */ +void hci_rx_task(unsigned long arg) +{ + struct hci_dev *hdev = (struct hci_dev *) arg; + struct sk_buff *skb; + + DBG("%s", hdev->name); + + read_lock(&hci_task_lock); + + while ((skb = skb_dequeue(&hdev->rx_q))) { + if (hdev->flags & HCI_SOCK) { + /* Send copy to the sockets */ + hci_send_to_sock(hdev, skb); + } + + if (hdev->flags & HCI_INIT) { + /* Don't process data packets in this states. */ + switch (skb->pkt_type) { + case HCI_ACLDATA_PKT: + case HCI_SCODATA_PKT: + bluez_skb_free(skb); + continue; + }; + } + + if (hdev->flags & HCI_NORMAL) { + /* Handle frame */ + switch (skb->pkt_type) { + case HCI_EVENT_PKT: + hci_event_packet(hdev, skb); + break; + + case HCI_ACLDATA_PKT: + DBG("%s ACL data packet", hdev->name); + hci_acldata_packet(hdev, skb); + break; + + case HCI_SCODATA_PKT: + DBG("%s SCO data packet", hdev->name); + hci_scodata_packet(hdev, skb); + break; + + default: + bluez_skb_free(skb); + break; + }; + } else { + bluez_skb_free(skb); + } + } + + read_unlock(&hci_task_lock); +} + +static void hci_tx_task(unsigned long arg) +{ + struct hci_dev *hdev = (struct hci_dev *) arg; + struct sk_buff *skb; + + read_lock(&hci_task_lock); + + DBG("%s acl %d sco %d", hdev->name, hdev->acl_cnt, hdev->sco_cnt); + + /* Schedule queues and send stuff to HCI driver */ + + hci_sched_acl(hdev); + + hci_sched_sco(hdev); + + /* Send next queued raw(unknown type) packet */ + while ((skb = skb_dequeue(&hdev->raw_q))) + hci_send_frame(skb); + + read_unlock(&hci_task_lock); +} + +static void hci_cmd_task(unsigned long arg) +{ + struct hci_dev *hdev = (struct hci_dev *) arg; + struct sk_buff *skb; + + DBG("%s cmd %d", hdev->name, atomic_read(&hdev->cmd_cnt)); + + /* Send queued commands */ + if (atomic_read(&hdev->cmd_cnt) && (skb = skb_dequeue(&hdev->cmd_q))) { + if (hdev->cmd_sent) + bluez_skb_free(hdev->cmd_sent); + + if ((hdev->cmd_sent = bluez_skb_clone(skb, GFP_ATOMIC))) { + atomic_dec(&hdev->cmd_cnt); + hci_send_frame(skb); + } else { + skb_queue_head(&hdev->cmd_q, skb); + hci_sched_cmd(hdev); + } + } +} + +/* Receive frame from HCI drivers */ +int hci_recv_frame(struct sk_buff *skb) +{ + struct hci_dev *hdev = (struct hci_dev *) skb->dev; + + if (!hdev || !(hdev->flags & (HCI_UP | HCI_INIT))) { + bluez_skb_free(skb); + return -1; + } + + DBG("%s type %d len %d", hdev->name, skb->pkt_type, skb->len); + + /* Incomming skb */ + bluez_cb(skb)->incomming = 1; + + /* Queue frame for rx task */ + skb_queue_tail(&hdev->rx_q, skb); + hci_sched_rx(hdev); + + return 0; +} + +/* ----- HCI Ioctl helpers ----- */ +int hci_dev_reset(__u16 dev) +{ + struct hci_dev *hdev; + int ret = 0; + + if (!(hdev = hci_dev_get(dev))) + return -ENODEV; + + hci_req_lock(hdev); + tasklet_disable(&hdev->tx_task); + + if (!(hdev->flags & HCI_UP)) + goto done; + + /* Drop queues */ + bluez_skb_queue_purge(&hdev->rx_q); + bluez_skb_queue_purge(&hdev->cmd_q); + + inquiry_cache_flush(&hdev->inq_cache); + + hci_conn_hash_flush(hdev); + + if (hdev->flush) + hdev->flush(hdev); + + atomic_set(&hdev->cmd_cnt, 1); + hdev->acl_cnt = 0; hdev->sco_cnt = 0; + + ret = __hci_request(hdev, hci_reset_req, 0, HCI_INIT_TIMEOUT); + +done: + tasklet_enable(&hdev->tx_task); + hci_req_unlock(hdev); + hci_dev_put(hdev); + + return ret; +} + +int hci_dev_reset_stat(__u16 dev) +{ + struct hci_dev *hdev; + int ret = 0; + + if (!(hdev = hci_dev_get(dev))) + return -ENODEV; + + memset(&hdev->stat, 0, sizeof(struct hci_dev_stats)); + + hci_dev_put(hdev); + + return ret; +} + +int hci_dev_setauth(unsigned long arg) +{ + struct hci_dev *hdev; + struct hci_dev_req dr; + int ret = 0; + + if (copy_from_user(&dr, (void *) arg, sizeof(dr))) + return -EFAULT; + + if (!(hdev = hci_dev_get(dr.dev_id))) + return -ENODEV; + + ret = hci_request(hdev, hci_auth_req, dr.dev_opt, HCI_INIT_TIMEOUT); + + hci_dev_put(hdev); + + return ret; +} + +int hci_dev_setscan(unsigned long arg) +{ + struct hci_dev *hdev; + struct hci_dev_req dr; + int ret = 0; + + if (copy_from_user(&dr, (void *) arg, sizeof(dr))) + return -EFAULT; + + if (!(hdev = hci_dev_get(dr.dev_id))) + return -ENODEV; + + ret = hci_request(hdev, hci_scan_req, dr.dev_opt, HCI_INIT_TIMEOUT); + + hci_dev_put(hdev); + + return ret; +} + +int hci_dev_list(unsigned long arg) +{ + struct hci_dev_list_req *dl; + struct hci_dev_req *dr; + struct hci_dev *hdev; + int i, n, size; + __u16 dev_num; + + if (get_user(dev_num, (__u16 *) arg)) + return -EFAULT; + + size = dev_num * sizeof(struct hci_dev_req) + sizeof(__u16); + + if (verify_area(VERIFY_WRITE, (void *) arg, size)) + return -EFAULT; + + if (!(dl = kmalloc(size, GFP_KERNEL))) + return -ENOMEM; + dr = dl->dev_req; + + spin_lock_bh(&hdev_list_lock); + for (i = 0, n = 0; i < HCI_MAX_DEV && n < dev_num; i++) { + if ((hdev = hdev_list[i])) { + (dr + n)->dev_id = hdev->id; + (dr + n)->dev_opt = hdev->flags; + n++; + } + } + spin_unlock_bh(&hdev_list_lock); + + dl->dev_num = n; + size = n * sizeof(struct hci_dev_req) + sizeof(__u16); + + copy_to_user((void *) arg, dl, size); + + return 0; +} + +int hci_dev_info(unsigned long arg) +{ + struct hci_dev *hdev; + struct hci_dev_info di; + int err = 0; + + if (copy_from_user(&di, (void *) arg, sizeof(di))) + return -EFAULT; + + if (!(hdev = hci_dev_get(di.dev_id))) + return -ENODEV; + + strcpy(di.name, hdev->name); + di.type = hdev->type; + di.flags = hdev->flags; + di.acl_mtu = hdev->acl_mtu; + di.acl_max = hdev->acl_max; + di.sco_mtu = hdev->sco_mtu; + di.sco_max = hdev->sco_max; + di.bdaddr = hdev->bdaddr; + + memcpy(&di.stat, &hdev->stat, sizeof(di.stat)); + + if (copy_to_user((void *) arg, &di, sizeof(di))) + err = -EFAULT; + + hci_dev_put(hdev); + + return err; +} + +__u32 hci_dev_setmode(struct hci_dev *hdev, __u32 mode) +{ + __u32 omode = hdev->flags & HCI_MODE_MASK; + + hdev->flags &= ~HCI_MODE_MASK; + hdev->flags |= (mode & HCI_MODE_MASK); + + return omode; +} + +__u32 hci_dev_getmode(struct hci_dev *hdev) +{ + return hdev->flags & HCI_MODE_MASK; +} + +int hci_inquiry(unsigned long arg) +{ + struct inquiry_cache *cache; + struct hci_inquiry_req ir; + struct hci_dev *hdev; + int err = 0, do_inquiry = 0; + long timeo; + __u8 *buf, *ptr; + + ptr = (void *) arg; + if (copy_from_user(&ir, ptr, sizeof(ir))) + return -EFAULT; + + if (!(hdev = hci_dev_get(ir.dev_id))) + return -ENODEV; + + cache = &hdev->inq_cache; + + inquiry_cache_lock(cache); + if (inquiry_cache_age(cache) > INQUIRY_CACHE_AGE_MAX || ir.flags & IREQ_CACHE_FLUSH) { + inquiry_cache_flush(cache); + do_inquiry = 1; + } + inquiry_cache_unlock(cache); + + timeo = ir.length * 2 * HZ; + if (do_inquiry && (err = hci_request(hdev, hci_inq_req, (unsigned long)&ir, timeo)) < 0) + goto done; + + /* cache_dump can't sleep. Therefore we allocate temp buffer and then + * copy it to the user space. + */ + if (!(buf = kmalloc(sizeof(inquiry_info) * ir.num_rsp, GFP_KERNEL))) { + err = -ENOMEM; + goto done; + } + ir.num_rsp = inquiry_cache_dump(cache, ir.num_rsp, buf); + + DBG("num_rsp %d", ir.num_rsp); + + if (!verify_area(VERIFY_WRITE, ptr, sizeof(ir) + (sizeof(inquiry_info) * ir.num_rsp))) { + copy_to_user(ptr, &ir, sizeof(ir)); + ptr += sizeof(ir); + copy_to_user(ptr, buf, sizeof(inquiry_info) * ir.num_rsp); + } else + err = -EFAULT; + + kfree(buf); + +done: + hci_dev_put(hdev); + + return err; +} + +int hci_core_init(void) +{ + /* Init locks */ + spin_lock_init(&hdev_list_lock); + + return 0; +} + +int hci_core_cleanup(void) +{ + return 0; +} diff -u --recursive --new-file v2.4.5/linux/net/bluetooth/hci_sock.c linux/net/bluetooth/hci_sock.c --- v2.4.5/linux/net/bluetooth/hci_sock.c Wed Dec 31 16:00:00 1969 +++ linux/net/bluetooth/hci_sock.c Mon Jun 11 19:15:27 2001 @@ -0,0 +1,511 @@ +/* + BlueZ - Bluetooth protocol stack for Linux + Copyright (C) 2000-2001 Qualcomm Incorporated + + Written 2000,2001 by Maxim Krasnyansky + + 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; + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY + CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, + COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS + SOFTWARE IS DISCLAIMED. +*/ + +/* + * BlueZ HCI socket layer. + * + * $Id: hci_sock.c,v 1.1 2001/06/01 08:12:11 davem Exp $ + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#ifndef HCI_SOCK_DEBUG +#undef DBG +#define DBG( A... ) +#endif + +/* HCI socket interface */ + +static struct bluez_sock_list hci_sk_list = { + lock: RW_LOCK_UNLOCKED +}; + +static struct sock *hci_sock_lookup(struct hci_dev *hdev) +{ + struct sock *sk; + + read_lock(&hci_sk_list.lock); + for (sk = hci_sk_list.head; sk; sk = sk->next) { + if (hci_pi(sk)->hdev == hdev) + break; + } + read_unlock(&hci_sk_list.lock); + return sk; +} + +/* Send frame to RAW socket */ +void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct sk_buff *nskb; + struct sock * sk; + + DBG("hdev %p len %d", hdev, skb->len); + + read_lock(&hci_sk_list.lock); + for (sk = hci_sk_list.head; sk; sk = sk->next) { + if (sk->state != BT_BOUND || hci_pi(sk)->hdev != hdev) + continue; + + /* Don't send frame to the socket it came from */ + if (skb->sk == sk) + continue; + + if (!(nskb = bluez_skb_clone(skb, GFP_ATOMIC))) + continue; + + /* Put type byte before the data */ + memcpy(skb_push(nskb, 1), &nskb->pkt_type, 1); + + skb_queue_tail(&sk->receive_queue, nskb); + sk->data_ready(sk, nskb->len); + } + read_unlock(&hci_sk_list.lock); +} + +static int hci_sock_release(struct socket *sock) +{ + struct sock *sk = sock->sk; + struct hci_dev *hdev = hci_pi(sk)->hdev; + + DBG("sock %p sk %p", sock, sk); + + if (!sk) + return 0; + + bluez_sock_unlink(&hci_sk_list, sk); + + if (hdev) { + if (!hci_sock_lookup(hdev)) + hdev->flags &= ~HCI_SOCK; + + hci_dev_put(hdev); + } + + sock_orphan(sk); + + bluez_skb_queue_purge(&sk->receive_queue); + bluez_skb_queue_purge(&sk->write_queue); + + sock_put(sk); + + MOD_DEC_USE_COUNT; + + return 0; +} + +static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) +{ + struct sock *sk = sock->sk; + struct hci_dev *hdev = hci_pi(sk)->hdev; + __u32 mode; + + DBG("cmd %x", cmd); + + switch (cmd) { + case HCIGETINFO: + return hci_dev_info(arg); + + case HCIGETDEVLIST: + return hci_dev_list(arg); + + case HCIDEVUP: + if (!capable(CAP_NET_ADMIN)) + return -EACCES; + + return hci_dev_open(arg); + + case HCIDEVDOWN: + if (!capable(CAP_NET_ADMIN)) + return -EACCES; + + return hci_dev_close(arg); + + case HCIDEVRESET: + if (!capable(CAP_NET_ADMIN)) + return -EACCES; + + return hci_dev_reset(arg); + + case HCIRESETSTAT: + if (!capable(CAP_NET_ADMIN)) + return -EACCES; + + return hci_dev_reset_stat(arg); + + case HCISETSCAN: + if (!capable(CAP_NET_ADMIN)) + return -EACCES; + + return hci_dev_setscan(arg); + + case HCISETAUTH: + if (!capable(CAP_NET_ADMIN)) + return -EACCES; + + return hci_dev_setauth(arg); + + case HCISETRAW: + if (!capable(CAP_NET_ADMIN)) + return -EACCES; + + if (!hdev) + return -EBADFD; + + if (arg) + mode = HCI_RAW; + else + mode = HCI_NORMAL; + + return hci_dev_setmode(hdev, mode); + + case HCIINQUIRY: + return hci_inquiry(arg); + + default: + return -EINVAL; + }; +} + +static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len) +{ + struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr; + struct sock *sk = sock->sk; + struct hci_dev *hdev = NULL; + + DBG("sock %p sk %p", sock, sk); + + if (!haddr || haddr->hci_family != AF_BLUETOOTH) + return -EINVAL; + + if (hci_pi(sk)->hdev) { + /* Already bound */ + return 0; + } + + if (haddr->hci_dev != HCI_DEV_NONE) { + if (!(hdev = hci_dev_get(haddr->hci_dev))) + return -ENODEV; + + hdev->flags |= HCI_SOCK; + } + + hci_pi(sk)->hdev = hdev; + sk->state = BT_BOUND; + + return 0; +} + +static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, int *addr_len, int peer) +{ + struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr; + struct sock *sk = sock->sk; + + DBG("sock %p sk %p", sock, sk); + + *addr_len = sizeof(*haddr); + haddr->hci_family = AF_BLUETOOTH; + haddr->hci_dev = hci_pi(sk)->hdev->id; + + return 0; +} + +static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, int len, + struct scm_cookie *scm) +{ + struct sock *sk = sock->sk; + struct hci_dev *hdev = hci_pi(sk)->hdev; + struct sk_buff *skb; + int err; + + DBG("sock %p sk %p", sock, sk); + + if (msg->msg_flags & MSG_OOB) + return -EOPNOTSUPP; + + if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE)) + return -EINVAL; + + if (!hdev) + return -EBADFD; + + if (!(skb = bluez_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err))) + return err; + + if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { + kfree_skb(skb); + return -EFAULT; + } + + skb->dev = (void *) hdev; + skb->pkt_type = *((unsigned char *) skb->data); + skb_pull(skb, 1); + + /* Send frame to HCI core */ + hci_send_raw(skb); + + return len; +} + +static __inline__ void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) +{ + __u32 flags = hci_pi(sk)->cmsg_flags; + + if (flags & HCI_CMSG_DIR) + put_cmsg(msg, SOL_HCI, HCI_CMSG_DIR, sizeof(int), &bluez_cb(skb)->incomming); +} + +static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg, int len, + int flags, struct scm_cookie *scm) +{ + int noblock = flags & MSG_DONTWAIT; + struct sock *sk = sock->sk; + struct sk_buff *skb; + int copied, err; + + DBG("sock %p sk %p", sock, sk); + + if (flags & (MSG_OOB | MSG_PEEK)) + return -EOPNOTSUPP; + + if (!(skb = skb_recv_datagram(sk, flags, noblock, &err))) + return err; + + msg->msg_namelen = 0; + + copied = skb->len; + if (len < copied) { + msg->msg_flags |= MSG_TRUNC; + copied = len; + } + + skb->h.raw = skb->data; + err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); + + if (hci_pi(sk)->cmsg_flags) + hci_sock_cmsg(sk, msg, skb); + + skb_free_datagram(sk, skb); + + return err ? : copied; +} + +int hci_sock_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen) +{ + struct sock *sk = sock->sk; + int err = 0, opt; + + if (get_user(opt, (int *)optval)) + return -EFAULT; + + DBG("sk %p, opt %d", sk, opt); + + lock_sock(sk); + + switch (optname) { + case HCI_DATA_DIR: + if (opt) + hci_pi(sk)->cmsg_flags |= HCI_CMSG_DIR; + else + hci_pi(sk)->cmsg_flags &= ~HCI_CMSG_DIR; + break; + + default: + err = -ENOPROTOOPT; + break; + }; + + release_sock(sk); + return err; +} + +int hci_sock_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen) +{ + struct sock *sk = sock->sk; + int len, opt; + + if (get_user(len, optlen)) + return -EFAULT; + + switch (optname) { + case HCI_DATA_DIR: + if (hci_pi(sk)->cmsg_flags & HCI_CMSG_DIR) + opt = 1; + else + opt = 0; + + if (put_user(opt, optval)) + return -EFAULT; + break; + + default: + return -ENOPROTOOPT; + break; + }; + + return 0; +} + +struct proto_ops hci_sock_ops = { + family: PF_BLUETOOTH, + release: hci_sock_release, + bind: hci_sock_bind, + getname: hci_sock_getname, + sendmsg: hci_sock_sendmsg, + recvmsg: hci_sock_recvmsg, + ioctl: hci_sock_ioctl, + poll: datagram_poll, + listen: sock_no_listen, + shutdown: sock_no_shutdown, + setsockopt: hci_sock_setsockopt, + getsockopt: hci_sock_getsockopt, + connect: sock_no_connect, + socketpair: sock_no_socketpair, + accept: sock_no_accept, + mmap: sock_no_mmap +}; + +static int hci_sock_create(struct socket *sock, int protocol) +{ + struct sock *sk; + + DBG("sock %p", sock); + + if (sock->type != SOCK_RAW) + return -ESOCKTNOSUPPORT; + + sock->ops = &hci_sock_ops; + + if (!(sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, 1))) + return -ENOMEM; + + sock->state = SS_UNCONNECTED; + sock_init_data(sock, sk); + + memset(&sk->protinfo, 0, sizeof(struct hci_pinfo)); + sk->destruct = NULL; + sk->protocol = protocol; + sk->state = BT_OPEN; + + bluez_sock_link(&hci_sk_list, sk); + + MOD_INC_USE_COUNT; + + return 0; +} + +static int hci_sock_dev_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct hci_dev *hdev = (struct hci_dev *) ptr; + struct sk_buff *skb; + + DBG("hdev %s event %ld", hdev->name, event); + + /* Send event to sockets */ + if ((skb = bluez_skb_alloc(HCI_EVENT_HDR_SIZE + EVT_HCI_DEV_EVENT_SIZE, GFP_ATOMIC))) { + hci_event_hdr eh = { EVT_HCI_DEV_EVENT, EVT_HCI_DEV_EVENT_SIZE }; + evt_hci_dev_event he = { event, hdev->id }; + + skb->pkt_type = HCI_EVENT_PKT; + memcpy(skb_put(skb, HCI_EVENT_HDR_SIZE), &eh, HCI_EVENT_HDR_SIZE); + memcpy(skb_put(skb, EVT_HCI_DEV_EVENT_SIZE), &he, EVT_HCI_DEV_EVENT_SIZE); + + hci_send_to_sock(NULL, skb); + bluez_skb_free(skb); + } + + if (event == HCI_DEV_UNREG) { + struct sock *sk; + + /* Detach sockets from device */ + read_lock(&hci_sk_list.lock); + for (sk = hci_sk_list.head; sk; sk = sk->next) { + if (hci_pi(sk)->hdev == hdev) { + hci_pi(sk)->hdev = NULL; + sk->err = EPIPE; + sk->state = BT_OPEN; + sk->state_change(sk); + + hci_dev_put(hdev); + } + } + read_unlock(&hci_sk_list.lock); + } + + return NOTIFY_DONE; +} + +struct net_proto_family hci_sock_family_ops = { + family: PF_BLUETOOTH, + create: hci_sock_create +}; + +struct notifier_block hci_sock_nblock = { + notifier_call: hci_sock_dev_event +}; + +int hci_sock_init(void) +{ + if (bluez_sock_register(BTPROTO_HCI, &hci_sock_family_ops)) { + ERR("Can't register HCI socket"); + return -EPROTO; + } + + hci_register_notifier(&hci_sock_nblock); + + return 0; +} + +int hci_sock_cleanup(void) +{ + if (bluez_sock_unregister(BTPROTO_HCI)) + ERR("Can't unregister HCI socket"); + + hci_unregister_notifier(&hci_sock_nblock); + + return 0; +} diff -u --recursive --new-file v2.4.5/linux/net/bluetooth/l2cap_core.c linux/net/bluetooth/l2cap_core.c --- v2.4.5/linux/net/bluetooth/l2cap_core.c Wed Dec 31 16:00:00 1969 +++ linux/net/bluetooth/l2cap_core.c Mon Jun 11 19:15:27 2001 @@ -0,0 +1,2202 @@ +/* + BlueZ - Bluetooth protocol stack for Linux + Copyright (C) 2000-2001 Qualcomm Incorporated + + Written 2000,2001 by Maxim Krasnyansky + + 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; + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY + CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, + COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS + SOFTWARE IS DISCLAIMED. +*/ + +/* + * BlueZ L2CAP core and sockets. + * + * $Id: l2cap_core.c,v 1.1 2001/06/01 08:12:11 davem Exp $ + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#ifndef L2CAP_DEBUG +#undef DBG +#define DBG( A... ) +#endif + +struct proto_ops l2cap_sock_ops; + +struct bluez_sock_list l2cap_sk_list = { + lock: RW_LOCK_UNLOCKED +}; + +struct list_head l2cap_iff_list = LIST_HEAD_INIT(l2cap_iff_list); +rwlock_t l2cap_rt_lock = RW_LOCK_UNLOCKED; + +static int l2cap_conn_del(struct l2cap_conn *conn, int err); + +static __inline__ void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent); +static void l2cap_chan_del(struct sock *sk, int err); +static int l2cap_chan_send(struct sock *sk, struct msghdr *msg, int len); + +static void l2cap_sock_close(struct sock *sk); +static void l2cap_sock_kill(struct sock *sk); + +static int l2cap_send_req(struct l2cap_conn *conn, __u8 code, __u16 len, void *data); +static int l2cap_send_rsp(struct l2cap_conn *conn, __u8 ident, __u8 code, __u16 len, void *data); + +/* -------- L2CAP interfaces & routing --------- */ +/* Add/delete L2CAP interface. + * Must be called with locked rt_lock + */ + +static void l2cap_iff_add(struct hci_dev *hdev) +{ + struct l2cap_iff *iff; + + DBG("%s", hdev->name); + + DBG("iff_list %p next %p prev %p", &l2cap_iff_list, l2cap_iff_list.next, l2cap_iff_list.prev); + + /* Allocate new interface and lock HCI device */ + if (!(iff = kmalloc(sizeof(struct l2cap_iff), GFP_KERNEL))) { + ERR("Can't allocate new interface %s", hdev->name); + return; + } + memset(iff, 0, sizeof(struct l2cap_iff)); + + hci_dev_hold(hdev); + hdev->l2cap_data = iff; + iff->hdev = hdev; + iff->mtu = hdev->acl_mtu - HCI_ACL_HDR_SIZE; + iff->bdaddr = &hdev->bdaddr; + + spin_lock_init(&iff->lock); + INIT_LIST_HEAD(&iff->conn_list); + + list_add(&iff->list, &l2cap_iff_list); +} + +static void l2cap_iff_del(struct hci_dev *hdev) +{ + struct l2cap_iff *iff; + + if (!(iff = hdev->l2cap_data)) + return; + + DBG("%s iff %p", hdev->name, iff); + + list_del(&iff->list); + + l2cap_iff_lock(iff); + + /* Drop connections */ + while (!list_empty(&iff->conn_list)) { + struct l2cap_conn *c; + + c = list_entry(iff->conn_list.next, struct l2cap_conn, list); + l2cap_conn_del(c, ENODEV); + } + + l2cap_iff_unlock(iff); + + /* Unlock HCI device */ + hdev->l2cap_data = NULL; + hci_dev_put(hdev); + + kfree(iff); +} + +/* Get route. Returns L2CAP interface. + * Must be called with locked rt_lock + */ +static struct l2cap_iff *l2cap_get_route(bdaddr_t *src, bdaddr_t *dst) +{ + struct list_head *p; + int use_src; + + DBG("%s -> %s", batostr(src), batostr(dst)); + + use_src = bacmp(src, BDADDR_ANY) ? 0 : 1; + + /* Simple routing: + * No source address - find interface with bdaddr != dst + * Source address - find interface with bdaddr == src + */ + + list_for_each(p, &l2cap_iff_list) { + struct l2cap_iff *iff; + + iff = list_entry(p, struct l2cap_iff, list); + + if (use_src && !bacmp(iff->bdaddr, src)) + return iff; + else if (bacmp(iff->bdaddr, dst)) + return iff; + } + return NULL; +} + +/* ----- L2CAP timers ------ */ +static void l2cap_timeout(unsigned long arg) +{ + struct sock *sk = (struct sock *) arg; + + DBG("sock %p state %d", sk, sk->state); + + bh_lock_sock(sk); + switch (sk->state) { + case BT_DISCONN: + l2cap_chan_del(sk, ETIMEDOUT); + break; + + default: + sk->err = ETIMEDOUT; + sk->state_change(sk); + break; + }; + bh_unlock_sock(sk); + + l2cap_sock_kill(sk); + sock_put(sk); +} + +static void l2cap_set_timer(struct sock *sk, long timeout) +{ + DBG("sock %p state %d timeout %ld", sk, sk->state, timeout); + + if (!mod_timer(&sk->timer, jiffies + timeout)) + sock_hold(sk); +} + +static void l2cap_clear_timer(struct sock *sk) +{ + DBG("sock %p state %d", sk, sk->state); + + if (timer_pending(&sk->timer) && del_timer(&sk->timer)) + __sock_put(sk); +} + +static void l2cap_init_timer(struct sock *sk) +{ + init_timer(&sk->timer); + sk->timer.function = l2cap_timeout; + sk->timer.data = (unsigned long)sk; +} + +/* -------- L2CAP connections --------- */ +/* Add new connection to the interface. + * Interface must be locked + */ +static struct l2cap_conn *l2cap_conn_add(struct l2cap_iff *iff, bdaddr_t *dst) +{ + struct l2cap_conn *conn; + bdaddr_t *src = iff->bdaddr; + + if (!(conn = kmalloc(sizeof(struct l2cap_conn), GFP_KERNEL))) + return NULL; + + memset(conn, 0, sizeof(struct l2cap_conn)); + + conn->state = BT_OPEN; + conn->iff = iff; + bacpy(&conn->src, src); + bacpy(&conn->dst, dst); + + spin_lock_init(&conn->lock); + conn->chan_list.lock = RW_LOCK_UNLOCKED; + + __l2cap_conn_link(iff, conn); + + DBG("%s -> %s, %p", batostr(src), batostr(dst), conn); + + MOD_INC_USE_COUNT; + + return conn; +} + +/* Delete connection on the interface. + * Interface must be locked + */ +static int l2cap_conn_del(struct l2cap_conn *conn, int err) +{ + struct sock *sk; + + DBG("conn %p, state %d, err %d", conn, conn->state, err); + + __l2cap_conn_unlink(conn->iff, conn); + + conn->state = BT_CLOSED; + + if (conn->rx_skb) + bluez_skb_free(conn->rx_skb); + + /* Kill channels */ + while ((sk = conn->chan_list.head)) { + bh_lock_sock(sk); + l2cap_clear_timer(sk); + l2cap_chan_del(sk, err); + bh_unlock_sock(sk); + + l2cap_sock_kill(sk); + } + + kfree(conn); + + MOD_DEC_USE_COUNT; + return 0; +} + +static __inline__ struct l2cap_conn *l2cap_get_conn_by_addr(struct l2cap_iff *iff, bdaddr_t *dst) +{ + struct list_head *p; + + list_for_each(p, &iff->conn_list){ + struct l2cap_conn *c; + + c = list_entry(p, struct l2cap_conn, list); + if (!bacmp(&c->dst, dst)) + return c; + } + return NULL; +} + +int l2cap_connect(struct sock *sk) +{ + bdaddr_t *src = &l2cap_pi(sk)->src; + bdaddr_t *dst = &l2cap_pi(sk)->dst; + struct l2cap_conn *conn; + struct l2cap_iff *iff; + int err = 0; + + DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst), l2cap_pi(sk)->psm); + + read_lock_bh(&l2cap_rt_lock); + + /* Get route to remote BD address */ + if (!(iff = l2cap_get_route(src, dst))) { + err = -EHOSTUNREACH; + goto done; + } + + /* Update source addr of the socket */ + bacpy(src, iff->bdaddr); + + l2cap_iff_lock(iff); + + if (!(conn = l2cap_get_conn_by_addr(iff, dst))) { + /* Connection doesn't exist */ + if (!(conn = l2cap_conn_add(iff, dst))) { + l2cap_iff_unlock(iff); + err = -ENOMEM; + goto done; + } + conn->out = 1; + } + + l2cap_iff_unlock(iff); + + l2cap_chan_add(conn, sk, NULL); + + sk->state = BT_CONNECT; + l2cap_set_timer(sk, sk->sndtimeo); + + switch (conn->state) { + case BT_CONNECTED: + if (sk->type == SOCK_SEQPACKET) { + l2cap_conn_req req; + req.scid = __cpu_to_le16(l2cap_pi(sk)->scid); + req.psm = l2cap_pi(sk)->psm; + l2cap_send_req(conn, L2CAP_CONN_REQ, L2CAP_CONN_REQ_SIZE, &req); + } else { + sk->state = BT_CONNECTED; + l2cap_clear_timer(sk); + } + break; + + case BT_CONNECT: + break; + + default: + /* Create ACL connection */ + conn->state = BT_CONNECT; + hci_connect(iff->hdev, dst); + break; + }; + +done: + read_unlock_bh(&l2cap_rt_lock); + + return err; +} + +/* ------ Channel queues for listening sockets ------ */ +void l2cap_accept_queue(struct sock *parent, struct sock *sk) +{ + struct l2cap_accept_q *q = &l2cap_pi(parent)->accept_q; + + DBG("parent %p, sk %p", parent, sk); + + sock_hold(sk); + l2cap_pi(sk)->parent = parent; + l2cap_pi(sk)->next_q = NULL; + + if (!q->head) { + q->head = q->tail = sk; + } else { + struct sock *tail = q->tail; + + l2cap_pi(sk)->prev_q = tail; + l2cap_pi(tail)->next_q = sk; + q->tail = sk; + } + + parent->ack_backlog++; +} + +void l2cap_accept_unlink(struct sock *sk) +{ + struct sock *parent = l2cap_pi(sk)->parent; + struct l2cap_accept_q *q = &l2cap_pi(parent)->accept_q; + struct sock *next, *prev; + + DBG("sk %p", sk); + + next = l2cap_pi(sk)->next_q; + prev = l2cap_pi(sk)->prev_q; + + if (sk == q->head) + q->head = next; + if (sk == q->tail) + q->tail = prev; + + if (next) + l2cap_pi(next)->prev_q = prev; + if (prev) + l2cap_pi(prev)->next_q = next; + + l2cap_pi(sk)->parent = NULL; + + parent->ack_backlog--; + __sock_put(sk); +} + +/* Get next connected channel in queue. */ +struct sock *l2cap_accept_dequeue(struct sock *parent, int state) +{ + struct l2cap_accept_q *q = &l2cap_pi(parent)->accept_q; + struct sock *sk; + + for (sk = q->head; sk; sk = l2cap_pi(sk)->next_q){ + if (!state || sk->state == state) { + l2cap_accept_unlink(sk); + break; + } + } + + DBG("parent %p, sk %p", parent, sk); + + return sk; +} + +/* -------- Socket interface ---------- */ +static struct sock *__l2cap_get_sock_by_addr(struct sockaddr_l2 *addr) +{ + bdaddr_t *src = &addr->l2_bdaddr; + __u16 psm = addr->l2_psm; + struct sock *sk; + + for (sk = l2cap_sk_list.head; sk; sk = sk->next) { + if (l2cap_pi(sk)->psm == psm && + !bacmp(&l2cap_pi(sk)->src, src)) + break; + } + + return sk; +} + +/* Find socket listening on psm and source bdaddr. + * Returns closest match. + */ +static struct sock *l2cap_get_sock_listen(bdaddr_t *src, __u16 psm) +{ + struct sock *sk, *sk1 = NULL; + + read_lock(&l2cap_sk_list.lock); + + for (sk = l2cap_sk_list.head; sk; sk = sk->next) { + struct l2cap_pinfo *pi; + + if (sk->state != BT_LISTEN) + continue; + + pi = l2cap_pi(sk); + + if (pi->psm == psm) { + /* Exact match. */ + if (!bacmp(&pi->src, src)) + break; + + /* Closest match */ + if (!bacmp(&pi->src, BDADDR_ANY)) + sk1 = sk; + } + } + + read_unlock(&l2cap_sk_list.lock); + + return sk ? sk : sk1; +} + +static void l2cap_sock_destruct(struct sock *sk) +{ + DBG("sk %p", sk); + + bluez_skb_queue_purge(&sk->receive_queue); + bluez_skb_queue_purge(&sk->write_queue); + + MOD_DEC_USE_COUNT; +} + +static void l2cap_sock_cleanup_listen(struct sock *parent) +{ + struct sock *sk; + + DBG("parent %p", parent); + + /* Close not yet accepted channels */ + while ((sk = l2cap_accept_dequeue(parent, 0))) + l2cap_sock_close(sk); + + parent->state = BT_CLOSED; + parent->zapped = 1; +} + +/* Kill socket (only if zapped and orphan) + * Must be called on unlocked socket. + */ +static void l2cap_sock_kill(struct sock *sk) +{ + if (!sk->zapped || sk->socket) + return; + + DBG("sk %p state %d", sk, sk->state); + + /* Kill poor orphan */ + bluez_sock_unlink(&l2cap_sk_list, sk); + sk->dead = 1; + sock_put(sk); +} + +/* Close socket. + * Must be called on unlocked socket. + */ +static void l2cap_sock_close(struct sock *sk) +{ + struct l2cap_conn *conn; + + lock_sock(sk); + + conn = l2cap_pi(sk)->conn; + + DBG("sk %p state %d conn %p socket %p", sk, sk->state, conn, sk->socket); + + switch (sk->state) { + case BT_LISTEN: + l2cap_sock_cleanup_listen(sk); + break; + + case BT_CONNECTED: + case BT_CONFIG: + if (sk->type == SOCK_SEQPACKET) { + l2cap_disconn_req req; + + sk->state = BT_DISCONN; + + req.dcid = __cpu_to_le16(l2cap_pi(sk)->dcid); + req.scid = __cpu_to_le16(l2cap_pi(sk)->scid); + l2cap_send_req(conn, L2CAP_DISCONN_REQ, L2CAP_DISCONN_REQ_SIZE, &req); + + l2cap_set_timer(sk, sk->sndtimeo); + } else { + l2cap_chan_del(sk, ECONNRESET); + } + break; + + case BT_CONNECT: + case BT_DISCONN: + l2cap_chan_del(sk, ECONNRESET); + break; + + default: + sk->zapped = 1; + break; + }; + + release_sock(sk); + + l2cap_sock_kill(sk); +} + +static void l2cap_sock_init(struct sock *sk, struct sock *parent) +{ + struct l2cap_pinfo *pi = l2cap_pi(sk); + + DBG("sk %p", sk); + + if (parent) { + sk->type = parent->type; + + pi->imtu = l2cap_pi(parent)->imtu; + pi->omtu = l2cap_pi(parent)->omtu; + } else { + pi->imtu = L2CAP_DEFAULT_MTU; + pi->omtu = 0; + } + + /* Default config options */ + pi->conf_mtu = L2CAP_DEFAULT_MTU; + pi->flush_to = L2CAP_DEFAULT_FLUSH_TO; +} + +static struct sock *l2cap_sock_alloc(struct socket *sock, int proto, int prio) +{ + struct sock *sk; + + if (!(sk = sk_alloc(PF_BLUETOOTH, prio, 1))) + return NULL; + + sock_init_data(sock, sk); + + sk->zapped = 0; + + sk->destruct = l2cap_sock_destruct; + sk->sndtimeo = L2CAP_CONN_TIMEOUT; + + sk->protocol = proto; + sk->state = BT_OPEN; + + l2cap_init_timer(sk); + + bluez_sock_link(&l2cap_sk_list, sk); + + MOD_INC_USE_COUNT; + + return sk; +} + +static int l2cap_sock_create(struct socket *sock, int protocol) +{ + struct sock *sk; + + DBG("sock %p", sock); + + sock->state = SS_UNCONNECTED; + + if (sock->type != SOCK_SEQPACKET && sock->type != SOCK_RAW) + return -ESOCKTNOSUPPORT; + + sock->ops = &l2cap_sock_ops; + + if (!(sk = l2cap_sock_alloc(sock, protocol, GFP_KERNEL))) + return -ENOMEM; + + l2cap_sock_init(sk, NULL); + + return 0; +} + +static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len) +{ + struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr; + struct sock *sk = sock->sk; + int err = 0; + + DBG("sk %p, %s %d", sk, batostr(&la->l2_bdaddr), la->l2_psm); + + if (!addr || addr->sa_family != AF_BLUETOOTH) + return -EINVAL; + + lock_sock(sk); + + if (sk->state != BT_OPEN) { + err = -EBADFD; + goto done; + } + + write_lock(&l2cap_sk_list.lock); + + if (la->l2_psm && __l2cap_get_sock_by_addr(la)) { + err = -EADDRINUSE; + goto unlock; + } + + /* Save source address */ + bacpy(&l2cap_pi(sk)->src, &la->l2_bdaddr); + l2cap_pi(sk)->psm = la->l2_psm; + sk->state = BT_BOUND; + +unlock: + write_unlock(&l2cap_sk_list.lock); + +done: + release_sock(sk); + + return err; +} + +static int l2cap_sock_w4_connect(struct sock *sk, int flags) +{ + DECLARE_WAITQUEUE(wait, current); + long timeo = sock_sndtimeo(sk, flags & O_NONBLOCK); + int err = 0; + + add_wait_queue(sk->sleep, &wait); + current->state = TASK_INTERRUPTIBLE; + + while (sk->state != BT_CONNECTED) { + if (!timeo) { + err = -EAGAIN; + break; + } + + release_sock(sk); + timeo = schedule_timeout(timeo); + lock_sock(sk); + + err = 0; + if (sk->state == BT_CONNECTED) + break; + + if (sk->err) { + err = sock_error(sk); + break; + } + + if (signal_pending(current)) { + err = sock_intr_errno(timeo); + break; + } + } + current->state = TASK_RUNNING; + remove_wait_queue(sk->sleep, &wait); + + return err; +} + +static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags) +{ + struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr; + struct sock *sk = sock->sk; + int err = 0; + + lock_sock(sk); + + DBG("sk %p", sk); + + if (addr->sa_family != AF_BLUETOOTH || alen < sizeof(struct sockaddr_l2)) { + err = -EINVAL; + goto done; + } + + if (sk->state != BT_OPEN && sk->state != BT_BOUND) { + err = -EBADFD; + goto done; + } + + if (sk->type == SOCK_SEQPACKET && !la->l2_psm) { + err = -EINVAL; + goto done; + } + + /* Set destination address and psm */ + bacpy(&l2cap_pi(sk)->dst, &la->l2_bdaddr); + l2cap_pi(sk)->psm = la->l2_psm; + + if ((err = l2cap_connect(sk))) + goto done; + + err = l2cap_sock_w4_connect(sk, flags); + +done: + release_sock(sk); + return err; +} + +int l2cap_sock_listen(struct socket *sock, int backlog) +{ + struct sock *sk = sock->sk; + int err = 0; + + DBG("sk %p backlog %d", sk, backlog); + + lock_sock(sk); + + if (sk->state != BT_BOUND || sock->type != SOCK_SEQPACKET) { + err = -EBADFD; + goto done; + } + + if (!l2cap_pi(sk)->psm) { + err = -EINVAL; + goto done; + } + + sk->max_ack_backlog = backlog; + sk->ack_backlog = 0; + sk->state = BT_LISTEN; + +done: + release_sock(sk); + return err; +} + +int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int flags) +{ + DECLARE_WAITQUEUE(wait, current); + struct sock *sk = sock->sk, *ch; + long timeo; + int err = 0; + + lock_sock(sk); + + if (sk->state != BT_LISTEN) { + err = -EBADFD; + goto done; + } + + timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); + + DBG("sk %p timeo %ld", sk, timeo); + + /* Wait for an incoming connection. (wake-one). */ + add_wait_queue_exclusive(sk->sleep, &wait); + current->state = TASK_INTERRUPTIBLE; + while (!(ch = l2cap_accept_dequeue(sk, BT_CONNECTED))) { + if (!timeo) { + err = -EAGAIN; + break; + } + + release_sock(sk); + timeo = schedule_timeout(timeo); + lock_sock(sk); + + if (sk->state != BT_LISTEN) { + err = -EBADFD; + break; + } + + if (signal_pending(current)) { + err = sock_intr_errno(timeo); + break; + } + } + current->state = TASK_RUNNING; + remove_wait_queue(sk->sleep, &wait); + + if (err) + goto done; + + sock_graft(ch, newsock); + newsock->state = SS_CONNECTED; + + DBG("new socket %p", ch); + +done: + release_sock(sk); + + return err; +} + +static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer) +{ + struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr; + struct sock *sk = sock->sk; + + DBG("sock %p, sk %p", sock, sk); + + addr->sa_family = AF_BLUETOOTH; + *len = sizeof(struct sockaddr_l2); + + if (peer) + bacpy(&la->l2_bdaddr, &l2cap_pi(sk)->dst); + else + bacpy(&la->l2_bdaddr, &l2cap_pi(sk)->src); + + la->l2_psm = l2cap_pi(sk)->psm; + + return 0; +} + +static int l2cap_sock_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm) +{ + struct sock *sk = sock->sk; + int err = 0; + + DBG("sock %p, sk %p", sock, sk); + + if (sk->err) + return sock_error(sk); + + if (msg->msg_flags & MSG_OOB) + return -EOPNOTSUPP; + + lock_sock(sk); + + if (sk->state == BT_CONNECTED) + err = l2cap_chan_send(sk, msg, len); + else + err = -ENOTCONN; + + release_sock(sk); + return err; +} + +static int l2cap_sock_recvmsg(struct socket *sock, struct msghdr *msg, int len, int flags, struct scm_cookie *scm) +{ + struct sock *sk = sock->sk; + int noblock = flags & MSG_DONTWAIT; + int copied, err; + struct sk_buff *skb; + + DBG("sock %p, sk %p", sock, sk); + + if (flags & (MSG_OOB)) + return -EOPNOTSUPP; + + if (sk->state == BT_CLOSED) + return 0; + + if (!(skb = skb_recv_datagram(sk, flags, noblock, &err))) + return err; + + msg->msg_namelen = 0; + + copied = skb->len; + if (len < copied) { + msg->msg_flags |= MSG_TRUNC; + copied = len; + } + + skb->h.raw = skb->data; + err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); + + skb_free_datagram(sk, skb); + + return err ? : copied; +} + +int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen) +{ + struct sock *sk = sock->sk; + struct l2cap_options opts; + int err = 0; + + DBG("sk %p", sk); + + lock_sock(sk); + + switch (optname) { + case L2CAP_OPTIONS: + if (copy_from_user((char *)&opts, optval, optlen)) { + err = -EFAULT; + break; + } + l2cap_pi(sk)->imtu = opts.imtu; + l2cap_pi(sk)->omtu = opts.omtu; + break; + + default: + err = -ENOPROTOOPT; + break; + }; + + release_sock(sk); + + return err; +} + +int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen) +{ + struct sock *sk = sock->sk; + struct l2cap_options opts; + int len; + + if (get_user(len, optlen)) + return -EFAULT; + + switch (optname) { + case L2CAP_OPTIONS: + opts.imtu = l2cap_pi(sk)->imtu; + opts.omtu = l2cap_pi(sk)->omtu; + opts.flush_to = l2cap_pi(sk)->flush_to; + + len = MIN(len, sizeof(opts)); + if (copy_to_user(optval, (char *)&opts, len)) + return -EFAULT; + + break; + + default: + return -ENOPROTOOPT; + break; + }; + + return 0; +} + +static int l2cap_sock_release(struct socket *sock) +{ + struct sock *sk = sock->sk; + + DBG("sock %p, sk %p", sock, sk); + + if (!sk) + return 0; + + sock_orphan(sk); + + l2cap_sock_close(sk); + + return 0; +} + +/* --------- L2CAP channels --------- */ +static struct sock * __l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, __u16 cid) +{ + struct sock *s; + + for (s = l->head; s; s = l2cap_pi(s)->next_c) { + if (l2cap_pi(s)->dcid == cid) + break; + } + + return s; +} + +static __inline__ struct sock *l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, __u16 cid) +{ + struct sock *s; + + read_lock(&l->lock); + s = __l2cap_get_chan_by_dcid(l, cid); + read_unlock(&l->lock); + + return s; +} + +static struct sock *__l2cap_get_chan_by_scid(struct l2cap_chan_list *l, __u16 cid) +{ + struct sock *s; + + for (s = l->head; s; s = l2cap_pi(s)->next_c) { + if (l2cap_pi(s)->scid == cid) + break; + } + + return s; +} +static __inline__ struct sock *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, __u16 cid) +{ + struct sock *s; + + read_lock(&l->lock); + s = __l2cap_get_chan_by_scid(l, cid); + read_unlock(&l->lock); + + return s; +} + +static struct sock *__l2cap_get_chan_by_ident(struct l2cap_chan_list *l, __u8 ident) +{ + struct sock *s; + + for (s = l->head; s; s = l2cap_pi(s)->next_c) { + if (l2cap_pi(s)->ident == ident) + break; + } + + return s; +} + +static __inline__ struct sock *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, __u8 ident) +{ + struct sock *s; + + read_lock(&l->lock); + s = __l2cap_get_chan_by_ident(l, ident); + read_unlock(&l->lock); + + return s; +} + +static __u16 l2cap_alloc_cid(struct l2cap_chan_list *l) +{ + __u16 cid = 0x0040; + + for (; cid < 0xffff; cid++) { + if(!__l2cap_get_chan_by_scid(l, cid)) + return cid; + } + + return 0; +} + +static __inline__ void __l2cap_chan_link(struct l2cap_chan_list *l, struct sock *sk) +{ + sock_hold(sk); + + if (l->head) + l2cap_pi(l->head)->prev_c = sk; + + l2cap_pi(sk)->next_c = l->head; + l2cap_pi(sk)->prev_c = NULL; + l->head = sk; +} + +static __inline__ void l2cap_chan_unlink(struct l2cap_chan_list *l, struct sock *sk) +{ + struct sock *next = l2cap_pi(sk)->next_c, *prev = l2cap_pi(sk)->prev_c; + + write_lock(&l->lock); + if (sk == l->head) + l->head = next; + + if (next) + l2cap_pi(next)->prev_c = prev; + if (prev) + l2cap_pi(prev)->next_c = next; + write_unlock(&l->lock); + + __sock_put(sk); +} + +static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent) +{ + struct l2cap_chan_list *l = &conn->chan_list; + + DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid); + + atomic_inc(&conn->refcnt); + l2cap_pi(sk)->conn = conn; + + if (sk->type == SOCK_SEQPACKET) { + /* Alloc CID for normal socket */ + l2cap_pi(sk)->scid = l2cap_alloc_cid(l); + } else { + /* Raw socket can send only signalling messages */ + l2cap_pi(sk)->scid = 0x0001; + l2cap_pi(sk)->dcid = 0x0001; + l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU; + } + + __l2cap_chan_link(l, sk); + + if (parent) + l2cap_accept_queue(parent, sk); +} + +static __inline__ void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent) +{ + struct l2cap_chan_list *l = &conn->chan_list; + + write_lock(&l->lock); + __l2cap_chan_add(conn, sk, parent); + write_unlock(&l->lock); +} + +/* Delete channel. Must be called on the locked socket. */ +static void l2cap_chan_del(struct sock *sk, int err) +{ + struct l2cap_conn *conn; + struct sock *parent; + + conn = l2cap_pi(sk)->conn; + parent = l2cap_pi(sk)->parent; + + DBG("sk %p, conn %p, err %d", sk, conn, err); + + if (parent) { + /* Unlink from parent accept queue */ + bh_lock_sock(parent); + l2cap_accept_unlink(sk); + bh_unlock_sock(parent); + } + + if (conn) { + /* Unlink from channel list */ + l2cap_chan_unlink(&conn->chan_list, sk); + l2cap_pi(sk)->conn = NULL; + + if (conn->out && + conn->state == BT_CONNECTED && + atomic_dec_and_test(&conn->refcnt)) { + /* Disconnect baseband */ + hci_disconnect(conn->hconn, 0x13); + } + } + + sk->state = BT_CLOSED; + sk->err = err; + sk->state_change(sk); + + sk->zapped = 1; +} + +static void l2cap_conn_ready(struct l2cap_conn *conn) +{ + struct l2cap_chan_list *l = &conn->chan_list; + struct sock *sk; + + DBG("conn %p", conn); + + read_lock(&l->lock); + + for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { + bh_lock_sock(sk); + + if (sk->type != SOCK_SEQPACKET) { + sk->state = BT_CONNECTED; + sk->state_change(sk); + l2cap_clear_timer(sk); + } else if (sk->state == BT_CONNECT) { + l2cap_conn_req req; + req.scid = __cpu_to_le16(l2cap_pi(sk)->scid); + req.psm = l2cap_pi(sk)->psm; + l2cap_send_req(conn, L2CAP_CONN_REQ, L2CAP_CONN_REQ_SIZE, &req); + + l2cap_set_timer(sk, sk->sndtimeo); + } + + bh_unlock_sock(sk); + } + + read_unlock(&l->lock); +} + +static void l2cap_chan_ready(struct sock *sk) +{ + struct sock *parent = l2cap_pi(sk)->parent; + + DBG("sk %p, parent %p", sk, parent); + + l2cap_pi(sk)->conf_state = 0; + l2cap_clear_timer(sk); + + if (!parent) { + /* Outgoing channel. + * Wake up socket sleeping on connect. + */ + sk->state = BT_CONNECTED; + sk->state_change(sk); + } else { + /* Incomming channel. + * Wake up socket sleeping on accept. + */ + parent->state_change(parent); + } +} + +/* Copy frame to all raw sockets on that connection */ +void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) +{ + struct l2cap_chan_list *l = &conn->chan_list; + struct sk_buff *nskb; + struct sock * sk; + + DBG("conn %p", conn); + + read_lock(&l->lock); + for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { + if (sk->type != SOCK_RAW) + continue; + + /* Don't send frame to the socket it came from */ + if (skb->sk == sk) + continue; + + if (!(nskb = bluez_skb_clone(skb, GFP_ATOMIC))) + continue; + + skb_queue_tail(&sk->receive_queue, nskb); + sk->data_ready(sk, nskb->len); + } + read_unlock(&l->lock); +} + +static int l2cap_chan_send(struct sock *sk, struct msghdr *msg, int len) +{ + struct l2cap_conn *conn = l2cap_pi(sk)->conn; + struct l2cap_iff *iff = conn->iff; + struct sk_buff *skb, *frag; + int err, size, count, sent=0; + l2cap_hdr * lh; + + /* Check outgoing MTU */ + if (len > l2cap_pi(sk)->omtu) + return -EINVAL; + + /* First fragment (with L2CAP header) */ + count = MIN(iff->mtu - L2CAP_HDR_SIZE, len); + size = L2CAP_HDR_SIZE + count; + if (!(skb = bluez_skb_send_alloc(sk, size, msg->msg_flags & MSG_DONTWAIT, &err))) + return err; + + /* Create L2CAP header */ + lh = (l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); + lh->len = __cpu_to_le16(len); + lh->cid = __cpu_to_le16(l2cap_pi(sk)->dcid); + + if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) { + err = -EFAULT; + goto fail; + } + + sent += count; + len -= count; + + /* Continuation fragments (no L2CAP header) */ + while (len) { + count = MIN(iff->mtu, len); + + if (!(frag = bluez_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err))) + goto fail; + + bluez_skb_add_frag(skb, frag); + + if (memcpy_fromiovec(skb_put(frag, count), msg->msg_iov, count)) { + err = -EFAULT; + goto fail; + } + + sent += count; + len -= count; + } + + if ((err = hci_send_acl(conn->hconn, skb, 0)) < 0) + goto fail; + + return sent; + +fail: + bluez_skb_free(skb); + + return err; +} +/* --------- L2CAP signalling commands --------- */ +static __inline__ __u8 l2cap_get_ident(struct l2cap_conn *conn) +{ + __u8 id; + + /* Get next available identificator. + * 1 - 199 are used by kernel. + * 200 - 254 are used by utilities like l2ping, etc + */ + + spin_lock(&conn->lock); + + if (++conn->tx_ident > 199) + conn->tx_ident = 1; + + id = conn->tx_ident; + + spin_unlock(&conn->lock); + + return id; +} + +static __inline__ struct sk_buff *l2cap_build_cmd(__u8 code, __u8 ident, __u16 len, void *data) +{ + struct sk_buff *skb; + l2cap_cmd_hdr *cmd; + l2cap_hdr *lh; + int size; + + DBG("code 0x%2.2x, ident 0x%2.2x, len %d", code, ident, len); + + size = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + len; + if (!(skb = bluez_skb_alloc(size, GFP_ATOMIC))) + return NULL; + + lh = (l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); + lh->len = __cpu_to_le16(L2CAP_CMD_HDR_SIZE + len); + lh->cid = __cpu_to_le16(0x0001); + + cmd = (l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE); + cmd->code = code; + cmd->ident = ident; + cmd->len = __cpu_to_le16(len); + + if (len) + memcpy(skb_put(skb, len), data, len); + + return skb; +} + +static int l2cap_send_req(struct l2cap_conn *conn, __u8 code, __u16 len, void *data) +{ + struct sk_buff *skb; + __u8 ident; + + DBG("code 0x%2.2x", code); + + ident = l2cap_get_ident(conn); + if (!(skb = l2cap_build_cmd(code, ident, len, data))) + return -ENOMEM; + skb->dev = (void *) conn->iff->hdev; + return hci_send_acl(conn->hconn, skb, 0); +} + +static int l2cap_send_rsp(struct l2cap_conn *conn, __u8 ident, __u8 code, __u16 len, void *data) +{ + struct sk_buff *skb; + + DBG("code 0x%2.2x", code); + + if (!(skb = l2cap_build_cmd(code, ident, len, data))) + return -ENOMEM; + + skb->dev = (void *) conn->iff->hdev; + + return hci_send_acl(conn->hconn, skb, 0); +} + +static __inline__ int l2cap_get_conf_opt(__u8 **ptr, __u8 *type, __u32 *val) +{ + l2cap_conf_opt *opt = (l2cap_conf_opt *) (*ptr); + int len; + + *type = opt->type; + switch (opt->len) { + case 1: + *val = *((__u8 *) opt->val); + break; + + case 2: + *val = __le16_to_cpu(*((__u16 *)opt->val)); + break; + + case 4: + *val = __le32_to_cpu(*((__u32 *)opt->val)); + break; + + default: + *val = 0L; + break; + }; + + DBG("type 0x%2.2x len %d val 0x%8.8x", *type, opt->len, *val); + + len = L2CAP_CONF_OPT_SIZE + opt->len; + + *ptr += len; + + return len; +} + +static __inline__ void l2cap_parse_conf_req(struct sock *sk, char *data, int len) +{ + __u8 type; __u32 val; + __u8 *ptr = data; + + DBG("sk %p len %d", sk, len); + + while (len >= L2CAP_CONF_OPT_SIZE) { + len -= l2cap_get_conf_opt(&ptr, &type, &val); + + switch (type) { + case L2CAP_CONF_MTU: + l2cap_pi(sk)->conf_mtu = val; + break; + + case L2CAP_CONF_FLUSH_TO: + l2cap_pi(sk)->flush_to = val; + break; + + case L2CAP_CONF_QOS: + break; + }; + } +} + +static __inline__ void l2cap_add_conf_opt(__u8 **ptr, __u8 type, __u8 len, __u32 val) +{ + register l2cap_conf_opt *opt = (l2cap_conf_opt *) (*ptr); + + DBG("type 0x%2.2x len %d val 0x%8.8x", type, len, val); + + opt->type = type; + opt->len = len; + switch (len) { + case 1: + *((__u8 *) opt->val) = val; + break; + + case 2: + *((__u16 *) opt->val) = __cpu_to_le16(val); + break; + + case 4: + *((__u32 *) opt->val) = __cpu_to_le32(val); + break; + }; + + *ptr += L2CAP_CONF_OPT_SIZE + len; +} + +static int l2cap_build_conf_req(struct sock *sk, __u8 *data) +{ + struct l2cap_pinfo *pi = l2cap_pi(sk); + l2cap_conf_req *req = (l2cap_conf_req *) data; + __u8 *ptr = req->data; + + DBG("sk %p", sk); + + if (pi->imtu != L2CAP_DEFAULT_MTU) + l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu); + + /* FIXME. Need actual value of the flush timeout */ + //if (flush_to != L2CAP_DEFAULT_FLUSH_TO) + // l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2, pi->flush_to); + + req->dcid = __cpu_to_le16(pi->dcid); + req->flags = __cpu_to_le16(0); + + return ptr - data; +} + +static int l2cap_conf_output(struct sock *sk, __u8 **ptr) +{ + struct l2cap_pinfo *pi = l2cap_pi(sk); + int result = 0; + + /* Configure output options and let other side know + * which ones we don't like. + */ + if (pi->conf_mtu < pi->omtu) { + l2cap_add_conf_opt(ptr, L2CAP_CONF_MTU, 2, l2cap_pi(sk)->omtu); + result = L2CAP_CONF_UNACCEPT; + } else { + pi->omtu = pi->conf_mtu; + } + + DBG("sk %p result %d", sk, result); + return result; +} + +static int l2cap_build_conf_rsp(struct sock *sk, __u8 *data, int *result) +{ + l2cap_conf_rsp *rsp = (l2cap_conf_rsp *) data; + __u8 *ptr = rsp->data; + + DBG("sk %p complete %d", sk, result ? 1 : 0); + + if (result) + *result = l2cap_conf_output(sk, &ptr); + + rsp->scid = __cpu_to_le16(l2cap_pi(sk)->dcid); + rsp->result = __cpu_to_le16(result ? *result : 0); + rsp->flags = __cpu_to_le16(0); + + return ptr - data; +} + +static __inline__ int l2cap_connect_req(struct l2cap_conn *conn, l2cap_cmd_hdr *cmd, __u8 *data) +{ + struct l2cap_chan_list *list = &conn->chan_list; + l2cap_conn_req *req = (l2cap_conn_req *) data; + l2cap_conn_rsp rsp; + struct sock *sk, *parent; + + __u16 scid = __le16_to_cpu(req->scid); + __u16 psm = req->psm; + + DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid); + + /* Check if we have socket listening on psm */ + if (!(parent = l2cap_get_sock_listen(&conn->src, psm))) + goto reject; + + bh_lock_sock(parent); + write_lock(&list->lock); + + /* Check if we already have channel with that dcid */ + if (__l2cap_get_chan_by_dcid(list, scid)) + goto unlock; + + /* Check for backlog size */ + if (parent->ack_backlog > parent->max_ack_backlog) + goto unlock; + + if (!(sk = l2cap_sock_alloc(NULL, BTPROTO_L2CAP, GFP_ATOMIC))) + goto unlock; + + l2cap_sock_init(sk, parent); + + bacpy(&l2cap_pi(sk)->src, &conn->src); + bacpy(&l2cap_pi(sk)->dst, &conn->dst); + l2cap_pi(sk)->psm = psm; + l2cap_pi(sk)->dcid = scid; + + __l2cap_chan_add(conn, sk, parent); + sk->state = BT_CONFIG; + + write_unlock(&list->lock); + bh_unlock_sock(parent); + + rsp.dcid = __cpu_to_le16(l2cap_pi(sk)->scid); + rsp.scid = __cpu_to_le16(l2cap_pi(sk)->dcid); + rsp.result = __cpu_to_le16(0); + rsp.status = __cpu_to_le16(0); + l2cap_send_rsp(conn, cmd->ident, L2CAP_CONN_RSP, L2CAP_CONN_RSP_SIZE, &rsp); + + return 0; + +unlock: + write_unlock(&list->lock); + bh_unlock_sock(parent); + +reject: + rsp.scid = __cpu_to_le16(scid); + rsp.dcid = __cpu_to_le16(0); + rsp.status = __cpu_to_le16(0); + rsp.result = __cpu_to_le16(L2CAP_CONN_NO_MEM); + l2cap_send_rsp(conn, cmd->ident, L2CAP_CONN_RSP, L2CAP_CONN_RSP_SIZE, &rsp); + + return 0; +} + +static __inline__ int l2cap_connect_rsp(struct l2cap_conn *conn, l2cap_cmd_hdr *cmd, __u8 *data) +{ + l2cap_conn_rsp *rsp = (l2cap_conn_rsp *) data; + __u16 scid, dcid, result, status; + struct sock *sk; + + scid = __le16_to_cpu(rsp->scid); + dcid = __le16_to_cpu(rsp->dcid); + result = __le16_to_cpu(rsp->result); + status = __le16_to_cpu(rsp->status); + + DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status); + + if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, scid))) + return -ENOENT; + + bh_lock_sock(sk); + + if (!result) { + char req[64]; + + l2cap_pi(sk)->dcid = dcid; + sk->state = BT_CONFIG; + + l2cap_send_req(conn, L2CAP_CONF_REQ, l2cap_build_conf_req(sk, req), req); + } else { + l2cap_chan_del(sk, ECONNREFUSED); + } + + bh_unlock_sock(sk); + return 0; +} + +static __inline__ int l2cap_config_req(struct l2cap_conn *conn, l2cap_cmd_hdr *cmd, __u8 *data) +{ + l2cap_conf_req * req = (l2cap_conf_req *) data; + __u16 dcid, flags; + __u8 rsp[64]; + struct sock *sk; + int result; + + dcid = __le16_to_cpu(req->dcid); + flags = __le16_to_cpu(req->flags); + + DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); + + if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid))) + return -ENOENT; + + bh_lock_sock(sk); + + l2cap_parse_conf_req(sk, req->data, cmd->len - L2CAP_CONF_REQ_SIZE); + + if (flags & 0x01) { + /* Incomplete config. Send empty response. */ + l2cap_send_rsp(conn, cmd->ident, L2CAP_CONF_RSP, l2cap_build_conf_rsp(sk, rsp, NULL), rsp); + goto unlock; + } + + /* Complete config. */ + l2cap_send_rsp(conn, cmd->ident, L2CAP_CONF_RSP, l2cap_build_conf_rsp(sk, rsp, &result), rsp); + + if (result) + goto unlock; + + /* Output config done */ + l2cap_pi(sk)->conf_state |= CONF_OUTPUT; + + if (l2cap_pi(sk)->conf_state == CONF_DONE) { + sk->state = BT_CONNECTED; + l2cap_chan_ready(sk); + } else { + char req[64]; + l2cap_send_req(conn, L2CAP_CONF_REQ, l2cap_build_conf_req(sk, req), req); + } + +unlock: + bh_unlock_sock(sk); + + return 0; +} + +static __inline__ int l2cap_config_rsp(struct l2cap_conn *conn, l2cap_cmd_hdr *cmd, __u8 *data) +{ + l2cap_conf_rsp *rsp = (l2cap_conf_rsp *)data; + __u16 scid, flags, result; + struct sock *sk; + int err = 0; + + scid = __le16_to_cpu(rsp->scid); + flags = __le16_to_cpu(rsp->flags); + result = __le16_to_cpu(rsp->result); + + DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x", scid, flags, result); + + if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, scid))) + return -ENOENT; + + bh_lock_sock(sk); + + if (sk->state != BT_CONFIG) { + err = -EINVAL; + goto done; + } + + if (result) { + l2cap_disconn_req req; + + /* They didn't like our options. Well... we do not negotiate. + * Close channel. + */ + sk->state = BT_DISCONN; + + req.dcid = __cpu_to_le16(l2cap_pi(sk)->dcid); + req.scid = __cpu_to_le16(l2cap_pi(sk)->scid); + l2cap_send_req(conn, L2CAP_DISCONN_REQ, L2CAP_DISCONN_REQ_SIZE, &req); + + l2cap_set_timer(sk, sk->sndtimeo); + goto done; + } + + if (flags & 0x01) + goto done; + + /* Input config done */ + l2cap_pi(sk)->conf_state |= CONF_INPUT; + + if (l2cap_pi(sk)->conf_state == CONF_DONE) { + sk->state = BT_CONNECTED; + l2cap_chan_ready(sk); + } + +done: + bh_unlock_sock(sk); + + return err; +} + +static __inline__ int l2cap_disconnect_req(struct l2cap_conn *conn, l2cap_cmd_hdr *cmd, __u8 *data) +{ + l2cap_disconn_req *req = (l2cap_disconn_req *) data; + l2cap_disconn_rsp rsp; + __u16 dcid, scid; + struct sock *sk; + + scid = __le16_to_cpu(req->scid); + dcid = __le16_to_cpu(req->dcid); + + DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); + + if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid))) + return 0; + + bh_lock_sock(sk); + + rsp.dcid = __cpu_to_le16(l2cap_pi(sk)->scid); + rsp.scid = __cpu_to_le16(l2cap_pi(sk)->dcid); + l2cap_send_rsp(conn, cmd->ident, L2CAP_DISCONN_RSP, L2CAP_DISCONN_RSP_SIZE, &rsp); + + l2cap_chan_del(sk, ECONNRESET); + + bh_unlock_sock(sk); + + l2cap_sock_kill(sk); + + return 0; +} + +static __inline__ int l2cap_disconnect_rsp(struct l2cap_conn *conn, l2cap_cmd_hdr *cmd, __u8 *data) +{ + l2cap_disconn_rsp *rsp = (l2cap_disconn_rsp *) data; + __u16 dcid, scid; + struct sock *sk; + + scid = __le16_to_cpu(rsp->scid); + dcid = __le16_to_cpu(rsp->dcid); + + DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); + + if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, scid))) + return -ENOENT; + + bh_lock_sock(sk); + l2cap_clear_timer(sk); + l2cap_chan_del(sk, ECONNABORTED); + bh_unlock_sock(sk); + + l2cap_sock_kill(sk); + + return 0; +} + +static __inline__ void l2cap_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) +{ + __u8 *data = skb->data; + int len = skb->len; + l2cap_cmd_hdr cmd; + int err = 0; + + while (len >= L2CAP_CMD_HDR_SIZE) { + memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE); + data += L2CAP_CMD_HDR_SIZE; + len -= L2CAP_CMD_HDR_SIZE; + + cmd.len = le16_to_cpu(cmd.len); + + DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd.len, cmd.ident); + + if (cmd.len > len || !cmd.ident) { + DBG("corrupted command"); + break; + } + + switch (cmd.code) { + case L2CAP_CONN_REQ: + err = l2cap_connect_req(conn, &cmd, data); + break; + + case L2CAP_CONN_RSP: + err = l2cap_connect_rsp(conn, &cmd, data); + break; + + case L2CAP_CONF_REQ: + err = l2cap_config_req(conn, &cmd, data); + break; + + case L2CAP_CONF_RSP: + err = l2cap_config_rsp(conn, &cmd, data); + break; + + case L2CAP_DISCONN_REQ: + err = l2cap_disconnect_req(conn, &cmd, data); + break; + + case L2CAP_DISCONN_RSP: + err = l2cap_disconnect_rsp(conn, &cmd, data); + break; + + case L2CAP_COMMAND_REJ: + /* FIXME: We should process this */ + l2cap_raw_recv(conn, skb); + break; + + case L2CAP_ECHO_REQ: + l2cap_send_rsp(conn, cmd.ident, L2CAP_ECHO_RSP, cmd.len, data); + break; + + case L2CAP_ECHO_RSP: + case L2CAP_INFO_REQ: + case L2CAP_INFO_RSP: + l2cap_raw_recv(conn, skb); + break; + + default: + ERR("Uknown signaling command 0x%2.2x", cmd.code); + err = -EINVAL; + break; + }; + + if (err) { + l2cap_cmd_rej rej; + DBG("error %d", err); + + /* FIXME: Map err to a valid reason. */ + rej.reason = cpu_to_le16(0); + l2cap_send_rsp(conn, cmd.ident, L2CAP_COMMAND_REJ, L2CAP_CMD_REJ_SIZE, &rej); + } + + data += cmd.len; + len -= cmd.len; + } + + bluez_skb_free(skb); +} + +static __inline__ int l2cap_data_channel(struct l2cap_conn *conn, __u16 cid, struct sk_buff *skb) +{ + struct sock *sk; + + if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, cid))) { + DBG("unknown cid 0x%4.4x", cid); + goto drop; + } + + DBG("sk %p, len %d", sk, skb->len); + + if (sk->state != BT_CONNECTED) + goto drop; + + if (l2cap_pi(sk)->imtu < skb->len) + goto drop; + + skb_queue_tail(&sk->receive_queue, skb); + sk->data_ready(sk, skb->len); + + return 0; + +drop: + bluez_skb_free(skb); + + return 0; +} + +static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) +{ + l2cap_hdr *lh = (l2cap_hdr *) skb->data; + __u16 cid, len; + + skb_pull(skb, L2CAP_HDR_SIZE); + cid = le16_to_cpu(lh->cid); + len = le16_to_cpu(lh->len); + + DBG("len %d, cid 0x%4.4x", len, cid); + + if (cid == 0x0001) + l2cap_sig_channel(conn, skb); + else + l2cap_data_channel(conn, cid, skb); +} + +/* ------------ L2CAP interface with lower layer (HCI) ------------- */ +static int l2cap_dev_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct hci_dev *hdev = (struct hci_dev *) ptr; + + DBG("hdev %s, event %ld", hdev->name, event); + + write_lock(&l2cap_rt_lock); + + switch (event) { + case HCI_DEV_UP: + l2cap_iff_add(hdev); + break; + + case HCI_DEV_DOWN: + l2cap_iff_del(hdev); + break; + }; + + write_unlock(&l2cap_rt_lock); + + return NOTIFY_DONE; +} + +int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) +{ + struct l2cap_iff *iff; + + DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr)); + + if (!(iff = hdev->l2cap_data)) { + ERR("unknown interface"); + return 0; + } + + /* Always accept connection */ + return 1; +} + +int l2cap_connect_cfm(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 status, struct hci_conn *hconn) +{ + struct l2cap_conn *conn; + struct l2cap_iff *iff; + int err = 0; + + DBG("hdev %s bdaddr %s hconn %p", hdev->name, batostr(bdaddr), hconn); + + if (!(iff = hdev->l2cap_data)) { + ERR("unknown interface"); + return 0; + } + + l2cap_iff_lock(iff); + + conn = l2cap_get_conn_by_addr(iff, bdaddr); + + if (conn) { + /* Outgoing connection */ + DBG("Outgoing connection: %s -> %s, %p, %2.2x", batostr(iff->bdaddr), batostr(bdaddr), conn, status); + + if (!status && hconn) { + conn->state = BT_CONNECTED; + conn->hconn = hconn; + + hconn->l2cap_data = (void *)conn; + + /* Establish channels */ + l2cap_conn_ready(conn); + } else { + l2cap_conn_del(conn, bterr(status)); + } + } else { + /* Incomming connection */ + DBG("Incomming connection: %s -> %s, %2.2x", batostr(iff->bdaddr), batostr(bdaddr), status); + + if (status || !hconn) + goto done; + + if (!(conn = l2cap_conn_add(iff, bdaddr))) { + err = -ENOMEM; + goto done; + } + + conn->state = BT_CONNECTED; + conn->hconn = hconn; + + hconn->l2cap_data = (void *)conn; + } + +done: + l2cap_iff_unlock(iff); + + return err; +} + +int l2cap_disconn_ind(struct hci_conn *hconn, __u8 reason) +{ + struct l2cap_conn *conn = hconn->l2cap_data; + + DBG("hconn %p reason %d", hconn, reason); + + if (!conn) { + ERR("unknown connection"); + return 0; + } + conn->hconn = NULL; + + l2cap_iff_lock(conn->iff); + l2cap_conn_del(conn, bterr(reason)); + l2cap_iff_unlock(conn->iff); + + return 0; +} + +int l2cap_recv_acldata(struct hci_conn *hconn, struct sk_buff *skb, __u16 flags) +{ + struct l2cap_conn *conn = hconn->l2cap_data; + + if (!conn) { + ERR("unknown connection"); + goto drop; + } + + DBG("conn %p len %d flags 0x%x", conn, skb->len, flags); + + if (flags & ACL_START) { + int flen, tlen, size; + l2cap_hdr *lh; + + if (skb->len < L2CAP_HDR_SIZE) { + DBG("Corrupted L2CAP frame %d", skb->len); + goto drop; + } + + lh = (l2cap_hdr *)skb->data; + tlen = __le16_to_cpu(lh->len); + flen = skb->len - L2CAP_HDR_SIZE; + + DBG("Start: total len %d, frag len %d", tlen, flen); + + if (flen == tlen) { + /* Complete frame received */ + l2cap_recv_frame(conn, skb); + return 0; + } + + /* Allocate skb for the complete frame (with header) */ + size = L2CAP_HDR_SIZE + tlen; + if (!(conn->rx_skb = bluez_skb_alloc(size, GFP_ATOMIC))) + goto drop; + + memcpy(skb_put(conn->rx_skb, skb->len), skb->data, skb->len); + + conn->rx_len = tlen - flen; + } else { + DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len); + + /* Check length */ + if (skb->len > conn->rx_len) { + if (conn->rx_skb) { + bluez_skb_free(conn->rx_skb); + conn->rx_skb = NULL; + } + goto drop; + } + + memcpy(skb_put(conn->rx_skb, skb->len), skb->data, skb->len); + conn->rx_len -= skb->len; + + if (!conn->rx_len) { + /* Complete frame received */ + l2cap_recv_frame(conn, conn->rx_skb); + conn->rx_skb = NULL; + conn->rx_len = 0; + } + } + +drop: + bluez_skb_free(skb); + + return 0; +} + +struct proto_ops l2cap_sock_ops = { + family: PF_BLUETOOTH, + release: l2cap_sock_release, + bind: l2cap_sock_bind, + connect: l2cap_sock_connect, + listen: l2cap_sock_listen, + accept: l2cap_sock_accept, + getname: l2cap_sock_getname, + sendmsg: l2cap_sock_sendmsg, + recvmsg: l2cap_sock_recvmsg, + poll: datagram_poll, + socketpair: sock_no_socketpair, + ioctl: sock_no_ioctl, + shutdown: sock_no_shutdown, + setsockopt: l2cap_sock_setsockopt, + getsockopt: l2cap_sock_getsockopt, + mmap: sock_no_mmap +}; + +struct net_proto_family l2cap_sock_family_ops = { + family: PF_BLUETOOTH, + create: l2cap_sock_create +}; + +struct hci_proto l2cap_hci_proto = { + name: "L2CAP", + id: HCI_PROTO_L2CAP, + connect_ind: l2cap_connect_ind, + connect_cfm: l2cap_connect_cfm, + disconn_ind: l2cap_disconn_ind, + recv_acldata: l2cap_recv_acldata, +}; + +struct notifier_block l2cap_nblock = { + notifier_call: l2cap_dev_event +}; + +int __init l2cap_init(void) +{ + INF("BlueZ L2CAP ver %s Copyright (C) 2000,2001 Qualcomm Inc", + BLUEZ_VER); + INF("Written 2000,2001 by Maxim Krasnyansky "); + + if (bluez_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops)) { + ERR("Can't register L2CAP socket"); + return -EPROTO; + } + + if (hci_register_proto(&l2cap_hci_proto) < 0) { + ERR("Can't register L2CAP protocol"); + return -EPROTO; + } + + hci_register_notifier(&l2cap_nblock); + + l2cap_register_proc(); + + return 0; +} + +void l2cap_cleanup(void) +{ + l2cap_unregister_proc(); + + /* Unregister socket, protocol and notifier */ + if (bluez_sock_unregister(BTPROTO_L2CAP)) + ERR("Can't unregister L2CAP socket"); + + if (hci_unregister_proto(&l2cap_hci_proto) < 0) + ERR("Can't unregister L2CAP protocol"); + + hci_unregister_notifier(&l2cap_nblock); + + /* We _must_ not have any sockets and/or connections + * at this stage. + */ + + /* Free interface list and unlock HCI devices */ + { + struct list_head *list = &l2cap_iff_list; + + while (!list_empty(list)) { + struct l2cap_iff *iff; + + iff = list_entry(list->next, struct l2cap_iff, list); + l2cap_iff_del(iff->hdev); + } + } +} + +module_init(l2cap_init); +module_exit(l2cap_cleanup); diff -u --recursive --new-file v2.4.5/linux/net/bluetooth/l2cap_proc.c linux/net/bluetooth/l2cap_proc.c --- v2.4.5/linux/net/bluetooth/l2cap_proc.c Wed Dec 31 16:00:00 1969 +++ linux/net/bluetooth/l2cap_proc.c Mon Jun 11 19:15:27 2001 @@ -0,0 +1,165 @@ +/* + BlueZ - Bluetooth protocol stack for Linux + Copyright (C) 2000-2001 Qualcomm Incorporated + + Written 2000,2001 by Maxim Krasnyansky + + 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; + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY + CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, + COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS + SOFTWARE IS DISCLAIMED. +*/ + +/* + * BlueZ L2CAP proc fs support. + * + * $Id: l2cap_proc.c,v 1.1 2001/06/01 08:12:11 davem Exp $ + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#ifndef L2CAP_DEBUG +#undef DBG +#define DBG( A... ) +#endif + +/* ----- PROC fs support ----- */ +static int l2cap_conn_dump(char *buf, struct l2cap_iff *iff) +{ + struct list_head *p; + char *ptr = buf; + + list_for_each(p, &iff->conn_list) { + struct l2cap_conn *c; + + c = list_entry(p, struct l2cap_conn, list); + ptr += sprintf(ptr, " %p %d %p %p %s %s\n", + c, c->state, c->iff, c->hconn, batostr(&c->src), batostr(&c->dst)); + } + + return ptr - buf; +} + +static int l2cap_iff_dump(char *buf) +{ + struct list_head *p; + char *ptr = buf; + + ptr += sprintf(ptr, "Interfaces:\n"); + + write_lock(&l2cap_rt_lock); + + list_for_each(p, &l2cap_iff_list) { + struct l2cap_iff *iff; + + iff = list_entry(p, struct l2cap_iff, list); + + ptr += sprintf(ptr, " %s %p %p\n", iff->hdev->name, iff, iff->hdev); + + l2cap_iff_lock(iff); + ptr += l2cap_conn_dump(ptr, iff); + l2cap_iff_unlock(iff); + } + + write_unlock(&l2cap_rt_lock); + + ptr += sprintf(ptr, "\n"); + + return ptr - buf; +} + +static int l2cap_sock_dump(char *buf, struct bluez_sock_list *list) +{ + struct l2cap_pinfo *pi; + struct sock *sk; + char *ptr = buf; + + ptr += sprintf(ptr, "Sockets:\n"); + + write_lock(&list->lock); + + for (sk = list->head; sk; sk = sk->next) { + pi = l2cap_pi(sk); + ptr += sprintf(ptr, " %p %d %p %d %s %s 0x%4.4x 0x%4.4x %d %d\n", sk, sk->state, pi->conn, pi->psm, + batostr(&pi->src), batostr(&pi->dst), pi->scid, pi->dcid, pi->imtu, pi->omtu ); + } + + write_unlock(&list->lock); + + ptr += sprintf(ptr, "\n"); + + return ptr - buf; +} + +static int l2cap_read_proc(char *buf, char **start, off_t offset, int count, int *eof, void *priv) +{ + char *ptr = buf; + int len; + + DBG("count %d, offset %ld", count, offset); + + ptr += l2cap_iff_dump(ptr); + ptr += l2cap_sock_dump(ptr, &l2cap_sk_list); + len = ptr - buf; + + if (len <= count + offset) + *eof = 1; + + *start = buf + offset; + len -= offset; + + if (len > count) + len = count; + if (len < 0) + len = 0; + + return len; +} + +void l2cap_register_proc(void) +{ + create_proc_read_entry("bluetooth/l2cap", 0, 0, l2cap_read_proc, NULL); +} + +void l2cap_unregister_proc(void) +{ + remove_proc_entry("bluetooth/l2cap", NULL); +} diff -u --recursive --new-file v2.4.5/linux/net/bluetooth/lib.c linux/net/bluetooth/lib.c --- v2.4.5/linux/net/bluetooth/lib.c Wed Dec 31 16:00:00 1969 +++ linux/net/bluetooth/lib.c Mon Jun 11 19:15:27 2001 @@ -0,0 +1,174 @@ +/* + BlueZ - Bluetooth protocol stack for Linux + Copyright (C) 2000-2001 Qualcomm Incorporated + + Written 2000,2001 by Maxim Krasnyansky + + 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; + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY + CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, + COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS + SOFTWARE IS DISCLAIMED. +*/ + +/* + * BlueZ kernel library. + * + * $Id: lib.c,v 1.1 2001/06/01 08:12:11 davem Exp $ + */ + +#include +#include +#include +#include + +#include + +void bluez_dump(char *pref, __u8 *buf, int count) +{ + char *ptr; + char line[100]; + int i; + + printk(KERN_INFO "%s: dump, len %d\n", pref, count); + + ptr = line; + *ptr = 0; + for (i = 0; ib0, ba->b1, ba->b2, ba->b3, ba->b4, ba->b5); + + return str[i]; +} + +/* Bluetooth error codes to Unix errno mapping */ +int bterr(__u16 code) +{ + switch (code) { + case 0: + return 0; + + case 0x01: + return EBADRQC; + + case 0x02: + return ENOTCONN; + + case 0x03: + return EIO; + + case 0x04: + return EHOSTDOWN; + + case 0x05: + return EACCES; + + case 0x06: + return EINVAL; + + case 0x07: + return ENOMEM; + + case 0x08: + return ETIMEDOUT; + + case 0x09: + return EMLINK; + + case 0x0a: + return EMLINK; + + case 0x0b: + return EALREADY; + + case 0x0c: + return EBUSY; + + case 0x0d: + case 0x0e: + case 0x0f: + return ECONNREFUSED; + + case 0x10: + return ETIMEDOUT; + + case 0x11: + case 0x27: + case 0x29: + case 0x20: + return EOPNOTSUPP; + + case 0x12: + return EINVAL; + + case 0x13: + case 0x14: + case 0x15: + return ECONNRESET; + + case 0x16: + return ECONNABORTED; + + case 0x17: + return ELOOP; + + case 0x18: + return EACCES; + + case 0x1a: + return EPROTONOSUPPORT; + + case 0x1b: + return ECONNREFUSED; + + case 0x19: + case 0x1e: + case 0x23: + case 0x24: + case 0x25: + return EPROTO; + + default: + return ENOSYS; + }; +} diff -u --recursive --new-file v2.4.5/linux/net/bluetooth/syms.c linux/net/bluetooth/syms.c --- v2.4.5/linux/net/bluetooth/syms.c Wed Dec 31 16:00:00 1969 +++ linux/net/bluetooth/syms.c Mon Jun 11 19:15:27 2001 @@ -0,0 +1,72 @@ +/* + BlueZ - Bluetooth protocol stack for Linux + Copyright (C) 2000-2001 Qualcomm Incorporated + + Written 2000,2001 by Maxim Krasnyansky + + 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; + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY + CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, + COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS + SOFTWARE IS DISCLAIMED. +*/ + +/* + * BlueZ symbols. + * + * $Id: syms.c,v 1.1 2001/06/01 08:12:11 davem Exp $ + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* HCI Core */ +EXPORT_SYMBOL(hci_register_dev); +EXPORT_SYMBOL(hci_unregister_dev); +EXPORT_SYMBOL(hci_register_proto); +EXPORT_SYMBOL(hci_unregister_proto); +EXPORT_SYMBOL(hci_register_notifier); +EXPORT_SYMBOL(hci_unregister_notifier); + +EXPORT_SYMBOL(hci_connect); +EXPORT_SYMBOL(hci_disconnect); +EXPORT_SYMBOL(hci_dev_get); + +EXPORT_SYMBOL(hci_recv_frame); +EXPORT_SYMBOL(hci_send_acl); +EXPORT_SYMBOL(hci_send_sco); +EXPORT_SYMBOL(hci_send_raw); + +/* BlueZ lib */ +EXPORT_SYMBOL(bluez_dump); +EXPORT_SYMBOL(baswap); +EXPORT_SYMBOL(batostr); +EXPORT_SYMBOL(bterr); + +/* BlueZ sockets */ +EXPORT_SYMBOL(bluez_sock_register); +EXPORT_SYMBOL(bluez_sock_unregister); +EXPORT_SYMBOL(bluez_sock_link); +EXPORT_SYMBOL(bluez_sock_unlink); diff -u --recursive --new-file v2.4.5/linux/net/bridge/br_device.c linux/net/bridge/br_device.c --- v2.4.5/linux/net/bridge/br_device.c Thu Mar 2 11:41:11 2000 +++ linux/net/bridge/br_device.c Mon Jun 11 19:15:27 2001 @@ -5,7 +5,7 @@ * Authors: * Lennert Buytenhek * - * $Id: br_device.c,v 1.3 2000/03/01 02:58:09 davem Exp $ + * $Id: br_device.c,v 1.4 2001/06/01 09:28:28 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -56,17 +56,17 @@ dest = skb->data; if (dest[0] & 1) { - br_flood(br, skb, 0); + br_flood_deliver(br, skb, 0); return 0; } if ((dst = br_fdb_get(br, dest)) != NULL) { - br_forward(dst->dst, skb); + br_deliver(dst->dst, skb); br_fdb_put(dst); return 0; } - br_flood(br, skb, 0); + br_flood_deliver(br, skb, 0); return 0; } diff -u --recursive --new-file v2.4.5/linux/net/bridge/br_forward.c linux/net/bridge/br_forward.c --- v2.4.5/linux/net/bridge/br_forward.c Mon Feb 21 17:35:06 2000 +++ linux/net/bridge/br_forward.c Mon Jun 11 19:15:27 2001 @@ -5,7 +5,7 @@ * Authors: * Lennert Buytenhek * - * $Id: br_forward.c,v 1.2 2000/02/21 15:51:33 davem Exp $ + * $Id: br_forward.c,v 1.3 2001/06/01 09:28:28 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -18,9 +18,10 @@ #include #include #include +#include #include "br_private.h" -static inline int should_forward(struct net_bridge_port *p, struct sk_buff *skb) +static inline int should_deliver(struct net_bridge_port *p, struct sk_buff *skb) { if (skb->dev == p->dev || p->state != BR_STATE_FORWARDING) @@ -29,16 +30,51 @@ return 1; } +static int __br_forward_finish(struct sk_buff *skb) +{ + NF_HOOK(PF_BRIDGE, NF_BR_POST_ROUTING, skb, NULL, skb->dev, + dev_queue_xmit); + + return 0; +} + +static void __br_deliver(struct net_bridge_port *to, struct sk_buff *skb) +{ + struct net_device *indev; + + indev = skb->dev; + skb->dev = to->dev; + + NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, indev, skb->dev, + __br_forward_finish); +} + static void __br_forward(struct net_bridge_port *to, struct sk_buff *skb) { + struct net_device *indev; + + indev = skb->dev; skb->dev = to->dev; - dev_queue_xmit(skb); + + NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, indev, skb->dev, + __br_forward_finish); +} + +/* called under bridge lock */ +void br_deliver(struct net_bridge_port *to, struct sk_buff *skb) +{ + if (should_deliver(to, skb)) { + __br_deliver(to, skb); + return; + } + + kfree_skb(skb); } /* called under bridge lock */ void br_forward(struct net_bridge_port *to, struct sk_buff *skb) { - if (should_forward(to, skb)) { + if (should_deliver(to, skb)) { __br_forward(to, skb); return; } @@ -47,7 +83,8 @@ } /* called under bridge lock */ -void br_flood(struct net_bridge *br, struct sk_buff *skb, int clone) +static void br_flood(struct net_bridge *br, struct sk_buff *skb, int clone, + void (*__packet_hook)(struct net_bridge_port *p, struct sk_buff *skb)) { struct net_bridge_port *p; struct net_bridge_port *prev; @@ -67,7 +104,7 @@ p = br->port_list; while (p != NULL) { - if (should_forward(p, skb)) { + if (should_deliver(p, skb)) { if (prev != NULL) { struct sk_buff *skb2; @@ -77,7 +114,7 @@ return; } - __br_forward(prev, skb2); + __packet_hook(prev, skb2); } prev = p; @@ -87,9 +124,21 @@ } if (prev != NULL) { - __br_forward(prev, skb); + __packet_hook(prev, skb); return; } kfree_skb(skb); +} + +/* called under bridge lock */ +void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb, int clone) +{ + br_flood(br, skb, clone, __br_deliver); +} + +/* called under bridge lock */ +void br_flood_forward(struct net_bridge *br, struct sk_buff *skb, int clone) +{ + br_flood(br, skb, clone, __br_forward); } diff -u --recursive --new-file v2.4.5/linux/net/bridge/br_input.c linux/net/bridge/br_input.c --- v2.4.5/linux/net/bridge/br_input.c Fri Dec 29 14:07:24 2000 +++ linux/net/bridge/br_input.c Mon Jun 11 19:15:27 2001 @@ -5,7 +5,7 @@ * Authors: * Lennert Buytenhek * - * $Id: br_input.c,v 1.7 2000/12/13 16:44:14 davem Exp $ + * $Id: br_input.c,v 1.8 2001/06/01 09:28:28 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -17,20 +17,33 @@ #include #include #include +#include #include "br_private.h" unsigned char bridge_ula[6] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }; +static int br_pass_frame_up_finish(struct sk_buff *skb) +{ + netif_rx(skb); + + return 0; +} + static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb) { + struct net_device *indev; + br->statistics.rx_packets++; br->statistics.rx_bytes += skb->len; + indev = skb->dev; skb->dev = &br->dev; skb->pkt_type = PACKET_HOST; skb_pull(skb, skb->mac.raw - skb->data); skb->protocol = eth_type_trans(skb, &br->dev); - netif_rx(skb); + + NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL, + br_pass_frame_up_finish); } static void __br_handle_frame(struct sk_buff *skb) @@ -91,7 +104,7 @@ goto freeandout; if (dest[0] & 1) { - br_flood(br, skb, 1); + br_flood_forward(br, skb, 1); if (!passedup) br_pass_frame_up(br, skb); else @@ -116,7 +129,7 @@ return; } - br_flood(br, skb, 0); + br_flood_forward(br, skb, 0); return; handle_special_frame: @@ -129,7 +142,7 @@ kfree_skb(skb); } -void br_handle_frame(struct sk_buff *skb) +static int br_handle_frame_finish(struct sk_buff *skb) { struct net_bridge *br; @@ -137,4 +150,12 @@ read_lock(&br->lock); __br_handle_frame(skb); read_unlock(&br->lock); + + return 0; +} + +void br_handle_frame(struct sk_buff *skb) +{ + NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, + br_handle_frame_finish); } diff -u --recursive --new-file v2.4.5/linux/net/bridge/br_private.h linux/net/bridge/br_private.h --- v2.4.5/linux/net/bridge/br_private.h Fri Feb 9 11:34:13 2001 +++ linux/net/bridge/br_private.h Mon Jun 11 19:15:27 2001 @@ -4,7 +4,7 @@ * Authors: * Lennert Buytenhek * - * $Id: br_private.h,v 1.5 2001/02/05 06:03:47 davem Exp $ + * $Id: br_private.h,v 1.6 2001/06/01 09:28:28 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -141,11 +141,16 @@ int is_local); /* br_forward.c */ +extern void br_deliver(struct net_bridge_port *to, + struct sk_buff *skb); extern void br_forward(struct net_bridge_port *to, struct sk_buff *skb); -extern void br_flood(struct net_bridge *br, - struct sk_buff *skb, - int clone); +extern void br_flood_deliver(struct net_bridge *br, + struct sk_buff *skb, + int clone); +extern void br_flood_forward(struct net_bridge *br, + struct sk_buff *skb, + int clone); /* br_if.c */ extern int br_add_bridge(char *name); diff -u --recursive --new-file v2.4.5/linux/net/core/dev.c linux/net/core/dev.c --- v2.4.5/linux/net/core/dev.c Sat May 19 18:11:49 2001 +++ linux/net/core/dev.c Wed Jun 20 21:00:55 2001 @@ -20,6 +20,10 @@ * Pekka Riikonen * * Changes: + * D.J. Barrow : Fixed bug where dev->refcnt gets set to 2 + * if register_netdev gets called before + * net_dev_init & also removed a few lines + * of code in the process. * Alan Cox : device private ioctl copies fields back. * Alan Cox : Transmit queue code does relevant stunts to * keep the queue safe. @@ -1278,7 +1282,7 @@ ret = pt->func(skb, skb->dev, pt); - tasklet_enable(bh_task_vec+TIMER_BH); + tasklet_hi_enable(bh_task_vec+TIMER_BH); spin_unlock(&net_bh_lock); return ret; } @@ -2382,6 +2386,8 @@ * will not get the same name. */ +int net_dev_init(void); + int register_netdevice(struct net_device *dev) { struct net_device *d, **dp; @@ -2396,47 +2402,8 @@ dev->fastpath_lock=RW_LOCK_UNLOCKED; #endif - if (dev_boot_phase) { -#ifdef CONFIG_NET_DIVERT - ret = alloc_divert_blk(dev); - if (ret) - return ret; -#endif /* CONFIG_NET_DIVERT */ - - /* This is NOT bug, but I am not sure, that all the - devices, initialized before netdev module is started - are sane. - - Now they are chained to device boot list - and probed later. If a module is initialized - before netdev, but assumes that dev->init - is really called by register_netdev(), it will fail. - - So that this message should be printed for a while. - */ - printk(KERN_INFO "early initialization of device %s is deferred\n", dev->name); - - /* Check for existence, and append to tail of chain */ - for (dp=&dev_base; (d=*dp) != NULL; dp=&d->next) { - if (d == dev || strcmp(d->name, dev->name) == 0) { - return -EEXIST; - } - } - dev->next = NULL; - write_lock_bh(&dev_base_lock); - *dp = dev; - dev_hold(dev); - write_unlock_bh(&dev_base_lock); - - /* - * Default initial state at registry is that the - * device is present. - */ - - set_bit(__LINK_STATE_PRESENT, &dev->state); - - return 0; - } + if (dev_boot_phase) + net_dev_init(); #ifdef CONFIG_NET_DIVERT ret = alloc_divert_blk(dev); @@ -2679,6 +2646,9 @@ { struct net_device *dev, **dp; int i; + + if (!dev_boot_phase) + return 0; #ifdef CONFIG_NET_SCHED pktsched_init(); diff -u --recursive --new-file v2.4.5/linux/net/core/neighbour.c linux/net/core/neighbour.c --- v2.4.5/linux/net/core/neighbour.c Tue Nov 28 21:53:45 2000 +++ linux/net/core/neighbour.c Mon Jun 11 19:15:27 2001 @@ -308,7 +308,7 @@ } /* Device specific setup. */ - if (n->parms && n->parms->neigh_setup && + if (n->parms->neigh_setup && (error = n->parms->neigh_setup(n)) < 0) { neigh_release(n); return ERR_PTR(error); diff -u --recursive --new-file v2.4.5/linux/net/core/sock.c linux/net/core/sock.c --- v2.4.5/linux/net/core/sock.c Wed Apr 25 14:57:39 2001 +++ linux/net/core/sock.c Fri Jun 29 19:38:26 2001 @@ -7,7 +7,7 @@ * handler for protocols to use and generic option handler. * * - * Version: $Id: sock.c,v 1.110 2001/04/20 20:46:19 davem Exp $ + * Version: $Id: sock.c,v 1.111 2001/06/26 23:29:17 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -80,6 +80,7 @@ * Andi Kleen : Add sock_kmalloc()/sock_kfree_s() * Andi Kleen : Fix write_space callback * Chris Evans : Security fixes - signedness again + * Arnaldo C. Melo : cleanups, use skb_queue_purge * * To Fix: * @@ -172,7 +173,6 @@ #endif int val; int valbool; - int err; struct linger ling; int ret = 0; @@ -192,9 +192,8 @@ if(optlenreceive_queue))!=NULL) - { - kfree_skb(skb); - } + skb_queue_purge(&sk->receive_queue); if(atomic_read(&sk->wmem_alloc) == 0 && atomic_read(&sk->rmem_alloc) == 0 && diff -u --recursive --new-file v2.4.5/linux/net/decnet/af_decnet.c linux/net/decnet/af_decnet.c --- v2.4.5/linux/net/decnet/af_decnet.c Tue May 1 16:05:00 2001 +++ linux/net/decnet/af_decnet.c Wed Jun 27 17:10:55 2001 @@ -1488,7 +1488,11 @@ default: #ifdef CONFIG_NETFILTER { - int val, len = *optlen; + int val, len; + + if(get_user(len, optlen)) + return -EFAULT; + val = nf_getsockopt(sk, PF_DECnet, optname, optval, &len); if (val >= 0) diff -u --recursive --new-file v2.4.5/linux/net/econet/af_econet.c linux/net/econet/af_econet.c --- v2.4.5/linux/net/econet/af_econet.c Thu Apr 19 08:38:50 2001 +++ linux/net/econet/af_econet.c Fri Jun 29 19:38:26 2001 @@ -68,7 +68,7 @@ unsigned long handle; }; -static unsigned long aun_seq = 0; +static unsigned long aun_seq; /* Queue of packets waiting to be transmitted. */ static struct sk_buff_head aun_queue; @@ -172,9 +172,8 @@ * Check legality */ - if (addr_len < sizeof(struct sockaddr_ec)) - return -EINVAL; - if (sec->sec_family != AF_ECONET) + if (addr_len < sizeof(struct sockaddr_ec) || + sec->sec_family != AF_ECONET) return -EINVAL; sk->protinfo.af_econet->cb = sec->cb; @@ -485,7 +484,6 @@ static int econet_release(struct socket *sock) { - struct sk_buff *skb; struct sock *sk = sock->sk; if (!sk) @@ -505,8 +503,7 @@ /* Purge queues */ - while ((skb=skb_dequeue(&sk->receive_queue))!=NULL) - kfree_skb(skb); + skb_queue_purge(&sk->receive_queue); if (atomic_read(&sk->rmem_alloc) || atomic_read(&sk->wmem_alloc)) { sk->timer.data=(unsigned long)sk; diff -u --recursive --new-file v2.4.5/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c --- v2.4.5/linux/net/ipv4/af_inet.c Tue May 1 20:59:24 2001 +++ linux/net/ipv4/af_inet.c Wed Jun 20 21:00:55 2001 @@ -5,7 +5,7 @@ * * PF_INET protocol family socket handler. * - * Version: $Id: af_inet.c,v 1.130 2001/04/29 08:21:32 davem Exp $ + * Version: $Id: af_inet.c,v 1.131 2001/06/13 16:25:03 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -14,6 +14,8 @@ * * Changes (see also sock.c) * + * piggy, + * Karl Knutson : Socket protocol table * A.N.Kuznetsov : Socket death error in accept(). * John Richardson : Fix non blocking error in connect() * so sockets that fail to connect @@ -88,6 +90,7 @@ #include #include #include +#include #include #include #include @@ -142,6 +145,11 @@ int (*br_ioctl_hook)(unsigned long); #endif +/* The inetsw table contains everything that inet_create needs to + * build a new socket. + */ +struct list_head inetsw[SOCK_MAX]; + /* New destruction routine */ void inet_sock_destruct(struct sock *sk) @@ -309,45 +317,54 @@ static int inet_create(struct socket *sock, int protocol) { struct sock *sk; - struct proto *prot; + struct list_head *p; + struct inet_protosw *answer; sock->state = SS_UNCONNECTED; sk = sk_alloc(PF_INET, GFP_KERNEL, 1); if (sk == NULL) goto do_oom; + + /* Look for the requested type/protocol pair. */ + answer = NULL; + br_read_lock_bh(BR_NETPROTO_LOCK); + list_for_each(p, &inetsw[sock->type]) { + answer = list_entry(p, struct inet_protosw, list); + + /* Check the non-wild match. */ + if (protocol == answer->protocol) { + if (protocol != IPPROTO_IP) + break; + } else { + /* Check for the two wild cases. */ + if (IPPROTO_IP == protocol) { + protocol = answer->protocol; + break; + } + if (IPPROTO_IP == answer->protocol) + break; + } + answer = NULL; + } + br_read_unlock_bh(BR_NETPROTO_LOCK); - switch (sock->type) { - case SOCK_STREAM: - if (protocol && protocol != IPPROTO_TCP) - goto free_and_noproto; - protocol = IPPROTO_TCP; - prot = &tcp_prot; - sock->ops = &inet_stream_ops; - break; - case SOCK_SEQPACKET: + if (!answer) goto free_and_badtype; - case SOCK_DGRAM: - if (protocol && protocol != IPPROTO_UDP) - goto free_and_noproto; - protocol = IPPROTO_UDP; - sk->no_check = UDP_CSUM_DEFAULT; - prot=&udp_prot; - sock->ops = &inet_dgram_ops; - break; - case SOCK_RAW: - if (!capable(CAP_NET_RAW)) - goto free_and_badperm; - if (!protocol) - goto free_and_noproto; - prot = &raw_prot; + if (answer->capability > 0 && !capable(answer->capability)) + goto free_and_badperm; + if (!protocol) + goto free_and_noproto; + + sock->ops = answer->ops; + sk->prot = answer->prot; + sk->no_check = answer->no_check; + if (INET_PROTOSW_REUSE & answer->flags) sk->reuse = 1; + + if (SOCK_RAW == sock->type) { sk->num = protocol; - sock->ops = &inet_dgram_ops; - if (protocol == IPPROTO_RAW) + if (IPPROTO_RAW == protocol) sk->protinfo.af_inet.hdrincl = 1; - break; - default: - goto free_and_badtype; } if (ipv4_config.no_pmtu_disc) @@ -365,8 +382,7 @@ sk->family = PF_INET; sk->protocol = protocol; - sk->prot = prot; - sk->backlog_rcv = prot->backlog_rcv; + sk->backlog_rcv = sk->prot->backlog_rcv; sk->protinfo.af_inet.ttl = sysctl_ip_default_ttl; @@ -395,10 +411,10 @@ int err = sk->prot->init(sk); if (err != 0) { inet_sock_release(sk); - return(err); + return err; } } - return(0); + return 0; free_and_badtype: sk_free(sk); @@ -969,6 +985,107 @@ extern void tcp_init(void); extern void tcp_v4_init(struct net_proto_family *); +/* Upon startup we insert all the elements in inetsw_array[] into + * the linked list inetsw. + */ +static struct inet_protosw inetsw_array[] = +{ + { + type: SOCK_STREAM, + protocol: IPPROTO_TCP, + prot: &tcp_prot, + ops: &inet_stream_ops, + capability: -1, + no_check: 0, + flags: INET_PROTOSW_PERMANENT, + }, + + { + type: SOCK_DGRAM, + protocol: IPPROTO_UDP, + prot: &udp_prot, + ops: &inet_dgram_ops, + capability: -1, + no_check: UDP_CSUM_DEFAULT, + flags: INET_PROTOSW_PERMANENT, + }, + + + { + type: SOCK_RAW, + protocol: IPPROTO_IP, /* wild card */ + prot: &raw_prot, + ops: &inet_dgram_ops, + capability: CAP_NET_RAW, + no_check: UDP_CSUM_DEFAULT, + flags: INET_PROTOSW_REUSE, + } +}; + +#define INETSW_ARRAY_LEN (sizeof(inetsw_array) / sizeof(struct inet_protosw)) + +void +inet_register_protosw(struct inet_protosw *p) +{ + struct list_head *lh; + struct inet_protosw *answer; + int protocol = p->protocol; + + br_write_lock_bh(BR_NETPROTO_LOCK); + + if (p->type > SOCK_MAX) + goto out_illegal; + + /* If we are trying to override a permanent protocol, bail. */ + answer = NULL; + list_for_each(lh, &inetsw[p->type]) { + answer = list_entry(lh, struct inet_protosw, list); + + /* Check only the non-wild match. */ + if (protocol == answer->protocol && + (INET_PROTOSW_PERMANENT & answer->flags)) + break; + + answer = NULL; + } + if (answer) + goto out_permanent; + + /* Add to the BEGINNING so that we override any existing + * entry. This means that when we remove this entry, the + * system automatically returns to the old behavior. + */ + list_add(&p->list, &inetsw[p->type]); +out: + br_write_unlock_bh(BR_NETPROTO_LOCK); + return; + +out_permanent: + printk(KERN_ERR "Attempt to override permanent protocol %d.\n", + protocol); + goto out; + +out_illegal: + printk(KERN_ERR + "Ignoring attempt to register illegal socket type %d.\n", + p->type); + goto out; +} + +void +inet_unregister_protosw(struct inet_protosw *p) +{ + if (INET_PROTOSW_PERMANENT & p->flags) { + printk(KERN_ERR + "Attempt to unregister permanent protocol %d.\n", + p->protocol); + } else { + br_write_lock_bh(BR_NETPROTO_LOCK); + list_del(&p->list); + br_write_unlock_bh(BR_NETPROTO_LOCK); + } +} + /* * Called by socket.c on kernel startup. @@ -978,6 +1095,8 @@ { struct sk_buff *dummy_skb; struct inet_protocol *p; + struct inet_protosw *q; + struct list_head *r; printk(KERN_INFO "NET4: Linux TCP/IP 1.0 for NET4.0\n"); @@ -1003,6 +1122,13 @@ printk("%s%s",p->name,tmp?", ":"\n"); p = tmp; } + + /* Register the socket-side information for inet_create. */ + for(r = &inetsw[0]; r < &inetsw[SOCK_MAX]; ++r) + INIT_LIST_HEAD(r); + + for(q = inetsw_array; q < &inetsw_array[INETSW_ARRAY_LEN]; ++q) + inet_register_protosw(q); /* * Set the ARP module up diff -u --recursive --new-file v2.4.5/linux/net/ipv4/fib_frontend.c linux/net/ipv4/fib_frontend.c --- v2.4.5/linux/net/ipv4/fib_frontend.c Wed May 16 10:31:23 2001 +++ linux/net/ipv4/fib_frontend.c Mon Jun 11 19:15:27 2001 @@ -5,7 +5,7 @@ * * IPv4 Forwarding Information Base: FIB frontend. * - * Version: $Id: fib_frontend.c,v 1.24 2001/05/13 18:14:46 davem Exp $ + * Version: $Id: fib_frontend.c,v 1.25 2001/05/29 22:16:25 davem Exp $ * * Authors: Alexey Kuznetsov, * @@ -236,8 +236,7 @@ if (res.type != RTN_UNICAST) goto e_inval_res; *spec_dst = FIB_RES_PREFSRC(res); - if (itag) - fib_combine_itag(itag, &res); + fib_combine_itag(itag, &res); #ifdef CONFIG_IP_ROUTE_MULTIPATH if (FIB_RES_DEV(res) == dev || res.fi->fib_nhs > 1) #else diff -u --recursive --new-file v2.4.5/linux/net/ipv4/icmp.c linux/net/ipv4/icmp.c --- v2.4.5/linux/net/ipv4/icmp.c Wed May 16 10:31:26 2001 +++ linux/net/ipv4/icmp.c Wed Jun 20 21:00:55 2001 @@ -3,7 +3,7 @@ * * Alan Cox, * - * Version: $Id: icmp.c,v 1.76 2001/05/10 01:20:58 davem Exp $ + * Version: $Id: icmp.c,v 1.77 2001/06/14 13:40:46 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -928,11 +928,6 @@ goto drop; } -/* - * A spare long used to speed up statistics updating - */ - -static unsigned long dummy; /* * Configurable rate limits. @@ -954,20 +949,20 @@ static struct icmp_control icmp_pointers[NR_ICMP_TYPES+1] = { /* ECHO REPLY (0) */ { &icmp_statistics[0].IcmpOutEchoReps, &icmp_statistics[0].IcmpInEchoReps, icmp_discard, 0, &sysctl_icmp_echoreply_time}, - { &dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1, }, - { &dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1, }, + { &icmp_statistics[0].dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1, }, + { &icmp_statistics[0].dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1, }, /* DEST UNREACH (3) */ { &icmp_statistics[0].IcmpOutDestUnreachs, &icmp_statistics[0].IcmpInDestUnreachs, icmp_unreach, 1, &sysctl_icmp_destunreach_time }, /* SOURCE QUENCH (4) */ { &icmp_statistics[0].IcmpOutSrcQuenchs, &icmp_statistics[0].IcmpInSrcQuenchs, icmp_unreach, 1, }, /* REDIRECT (5) */ { &icmp_statistics[0].IcmpOutRedirects, &icmp_statistics[0].IcmpInRedirects, icmp_redirect, 1, }, - { &dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1, }, - { &dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1, }, + { &icmp_statistics[0].dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1, }, + { &icmp_statistics[0].dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1, }, /* ECHO (8) */ { &icmp_statistics[0].IcmpOutEchos, &icmp_statistics[0].IcmpInEchos, icmp_echo, 0, }, - { &dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1, }, - { &dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1, }, + { &icmp_statistics[0].dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1, }, + { &icmp_statistics[0].dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1, }, /* TIME EXCEEDED (11) */ { &icmp_statistics[0].IcmpOutTimeExcds, &icmp_statistics[0].IcmpInTimeExcds, icmp_unreach, 1, &sysctl_icmp_timeexceed_time }, /* PARAMETER PROBLEM (12) */ @@ -977,9 +972,9 @@ /* TIMESTAMP REPLY (14) */ { &icmp_statistics[0].IcmpOutTimestampReps, &icmp_statistics[0].IcmpInTimestampReps, icmp_discard, 0, }, /* INFO (15) */ - { &dummy, &dummy, icmp_discard, 0, }, + { &icmp_statistics[0].dummy, &icmp_statistics[0].dummy, icmp_discard, 0, }, /* INFO REPLY (16) */ - { &dummy, &dummy, icmp_discard, 0, }, + { &icmp_statistics[0].dummy, &icmp_statistics[0].dummy, icmp_discard, 0, }, /* ADDR MASK (17) */ { &icmp_statistics[0].IcmpOutAddrMasks, &icmp_statistics[0].IcmpInAddrMasks, icmp_address, 0, }, /* ADDR MASK REPLY (18) */ diff -u --recursive --new-file v2.4.5/linux/net/ipv4/inetpeer.c linux/net/ipv4/inetpeer.c --- v2.4.5/linux/net/ipv4/inetpeer.c Tue Oct 10 10:33:52 2000 +++ linux/net/ipv4/inetpeer.c Fri Jun 29 19:38:26 2001 @@ -3,7 +3,7 @@ * * This source is covered by the GNU GPL, the same as all kernel sources. * - * Version: $Id: inetpeer.c,v 1.3 2000/10/03 07:29:00 anton Exp $ + * Version: $Id: inetpeer.c,v 1.6 2001/06/21 20:30:14 davem Exp $ * * Authors: Andrey V. Savochkin */ @@ -109,11 +109,11 @@ * . I don't have any opinion about the values * myself. --SAW */ - if (si.totalram <= 32768*1024) + if (si.totalram <= (32768*1024)/PAGE_SIZE) inet_peer_threshold >>= 1; /* max pool size about 1MB on IA32 */ - if (si.totalram <= 16384*1024) + if (si.totalram <= (16384*1024)/PAGE_SIZE) inet_peer_threshold >>= 1; /* about 512KB */ - if (si.totalram <= 8192*1024) + if (si.totalram <= (8192*1024)/PAGE_SIZE) inet_peer_threshold >>= 2; /* about 128KB */ peer_cachep = kmem_cache_create("inet_peer_cache", diff -u --recursive --new-file v2.4.5/linux/net/ipv4/ip_output.c linux/net/ipv4/ip_output.c --- v2.4.5/linux/net/ipv4/ip_output.c Thu Apr 12 12:11:39 2001 +++ linux/net/ipv4/ip_output.c Mon Jun 11 19:15:27 2001 @@ -5,7 +5,7 @@ * * The Internet Protocol (IP) output module. * - * Version: $Id: ip_output.c,v 1.91 2001/03/29 06:25:55 davem Exp $ + * Version: $Id: ip_output.c,v 1.93 2001/06/01 14:59:31 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -499,7 +499,7 @@ * Begin outputting the bytes. */ - id = (sk ? sk->protinfo.af_inet.id++ : 0); + id = sk->protinfo.af_inet.id++; do { char *data; @@ -848,6 +848,7 @@ offset += len; #ifdef CONFIG_NETFILTER + skb2->nfmark = skb->nfmark; /* Connection association is same as pre-frag packet */ skb2->nfct = skb->nfct; nf_conntrack_get(skb2->nfct); diff -u --recursive --new-file v2.4.5/linux/net/ipv4/ipmr.c linux/net/ipv4/ipmr.c --- v2.4.5/linux/net/ipv4/ipmr.c Thu Apr 12 12:11:39 2001 +++ linux/net/ipv4/ipmr.c Fri Jun 29 19:38:26 2001 @@ -9,7 +9,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * Version: $Id: ipmr.c,v 1.59 2001/02/23 06:32:11 davem Exp $ + * Version: $Id: ipmr.c,v 1.60 2001/06/29 21:33:22 davem Exp $ * * Fixes: * Michael Chastain : Incorrect size of copying. @@ -83,8 +83,8 @@ #define VIF_EXISTS(idx) (vif_table[idx].dev != NULL) -int mroute_do_assert = 0; /* Set in PIM assert */ -int mroute_do_pim = 0; +int mroute_do_assert; /* Set in PIM assert */ +int mroute_do_pim; static struct mfc_cache *mfc_cache_array[MFC_LINES]; /* Forwarding cache */ diff -u --recursive --new-file v2.4.5/linux/net/ipv4/netfilter/ipfwadm_core.c linux/net/ipv4/netfilter/ipfwadm_core.c --- v2.4.5/linux/net/ipv4/netfilter/ipfwadm_core.c Fri Aug 4 18:18:49 2000 +++ linux/net/ipv4/netfilter/ipfwadm_core.c Mon Jun 11 19:15:27 2001 @@ -20,7 +20,7 @@ * license in recognition of the original copyright. * -- Alan Cox. * - * $Id: ipfwadm_core.c,v 1.4 2000/07/26 01:04:21 davem Exp $ + * $Id: ipfwadm_core.c,v 1.5 2001/06/01 14:56:53 davem Exp $ * * Ported from BSD to Linux, * Alan Cox 22/Nov/1994. @@ -515,7 +515,7 @@ } continue; /* Mismatch */ - ifa_ok: + ifa_ok:; } /* diff -u --recursive --new-file v2.4.5/linux/net/ipv4/netfilter/ipt_REJECT.c linux/net/ipv4/netfilter/ipt_REJECT.c --- v2.4.5/linux/net/ipv4/netfilter/ipt_REJECT.c Fri Apr 27 14:15:01 2001 +++ linux/net/ipv4/netfilter/ipt_REJECT.c Mon Jun 11 19:15:27 2001 @@ -309,9 +309,9 @@ break; case IPT_TCP_RESET: send_reset(*pskb, hooknum == NF_IP_LOCAL_IN); - break; case IPT_ICMP_ECHOREPLY: /* Doesn't happen. */ + break; } return NF_DROP; diff -u --recursive --new-file v2.4.5/linux/net/ipv4/netfilter/ipt_unclean.c linux/net/ipv4/netfilter/ipt_unclean.c --- v2.4.5/linux/net/ipv4/netfilter/ipt_unclean.c Thu Apr 27 15:43:15 2000 +++ linux/net/ipv4/netfilter/ipt_unclean.c Wed Jun 20 16:05:21 2001 @@ -76,7 +76,7 @@ = { 12, 12, ICMP_NOT_ERROR, 0, 0 } }; /* Can't do anything if it's a fragment. */ - if (!offset) + if (offset) return 1; /* Must cover type and code. */ @@ -87,7 +87,7 @@ /* If not embedded. */ if (!embedded) { - /* Bad checksum? Don't print, just drop. */ + /* Bad checksum? Don't print, just ignore. */ if (!more_frags && ip_compute_csum((unsigned char *) icmph, datalen) != 0) return 0; @@ -108,6 +108,8 @@ length of iph + 8 bytes. */ struct iphdr *inner = (void *)icmph + 8; + /* datalen > 8 since all ICMP_IS_ERROR types + have min length > 8 */ if (datalen - 8 < sizeof(struct iphdr)) { limpk("ICMP error internal way too short\n"); return 0; @@ -155,6 +157,8 @@ u_int32_t arg = ntohl(icmph->un.gateway); if (icmph->code == 0) { + /* Code 0 means that upper 8 bits is pointer + to problem. */ if ((arg >> 24) >= iph->ihl*4) { limpk("ICMP PARAMETERPROB ptr = %u\n", ntohl(icmph->un.gateway) >> 24); @@ -196,7 +200,7 @@ int embedded) { /* Can't do anything if it's a fragment. */ - if (!offset) + if (offset) return 1; /* CHECK: Must cover UDP header. */ @@ -205,7 +209,7 @@ return 0; } - /* Bad checksum? Don't print, just drop. */ + /* Bad checksum? Don't print, just say it's unclean. */ /* FIXME: SRC ROUTE packets won't match checksum --RR */ if (!more_frags && !embedded && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_UDP, @@ -263,7 +267,7 @@ int more_frags, int embedded) { - u_int8_t *opt = (u_int8_t *)(tcph + 1); + u_int8_t *opt = (u_int8_t *)tcph; u_int8_t tcpflags; int end_of_options = 0; size_t i; @@ -272,7 +276,7 @@ /* In fact, this is caught below (offset < 516). */ /* Can't do anything if it's a fragment. */ - if (!offset) + if (offset) return 1; /* CHECK: Smaller than minimal TCP hdr. */ @@ -281,7 +285,8 @@ limpk("Packet length %u < TCP header.\n", datalen); return 0; } - /* Must have ports available (datalen >= 8). */ + /* Must have ports available (datalen >= 8), from + check_icmp which set embedded = 1 */ /* CHECK: TCP ports inside ICMP error */ if (!tcph->source || !tcph->dest) { limpk("Zero TCP ports %u/%u.\n", @@ -301,7 +306,7 @@ return 1; } - /* Bad checksum? Don't print, just drop. */ + /* Bad checksum? Don't print, just say it's unclean. */ /* FIXME: SRC ROUTE packets won't match checksum --RR */ if (!more_frags && !embedded && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_TCP, @@ -373,6 +378,8 @@ (unsigned int) opt[i], i); return 0; } + /* Move to next option */ + i += opt[i+1]; } } @@ -384,7 +391,7 @@ static int check_ip(struct iphdr *iph, size_t length, int embedded) { - u_int8_t *opt = (u_int8_t *)(iph + 1); + u_int8_t *opt = (u_int8_t *)iph; int end_of_options = 0; void *protoh; size_t datalen; @@ -430,18 +437,20 @@ opt[i]); return 0; } - /* CHECK: zero-length options. */ - else if (opt[i+1] == 0) { - limpk("IP option %u 0 len\n", - opt[i]); + /* CHECK: zero-length or one-length options. */ + else if (opt[i+1] < 2) { + limpk("IP option %u %u len\n", + opt[i], opt[i+1]); return 0; } /* CHECK: oversize options. */ - else if (opt[i+1] + i >= iph->ihl * 4) { + else if (opt[i+1] + i > iph->ihl * 4) { limpk("IP option %u at %u too long\n", opt[i], i); return 0; } + /* Move to next option */ + i += opt[i+1]; } } @@ -495,10 +504,10 @@ return 0; } - /* CHECK: Min offset of frag = 128 - 60 (max IP hdr len). */ - if (offset && offset * 8 < MIN_LIKELY_MTU - 60) { + /* CHECK: Min offset of frag = 128 - IP hdr len. */ + if (offset && offset * 8 < MIN_LIKELY_MTU - iph->ihl * 4) { limpk("Fragment starts at %u < %u\n", offset * 8, - MIN_LIKELY_MTU-60); + MIN_LIKELY_MTU - iph->ihl * 4); return 0; } diff -u --recursive --new-file v2.4.5/linux/net/ipv4/raw.c linux/net/ipv4/raw.c --- v2.4.5/linux/net/ipv4/raw.c Wed May 16 10:31:27 2001 +++ linux/net/ipv4/raw.c Thu Jun 14 14:16:58 2001 @@ -5,7 +5,7 @@ * * RAW - implementation of IP "raw" sockets. * - * Version: $Id: raw.c,v 1.61 2001/05/03 20:56:04 davem Exp $ + * Version: $Id: raw.c,v 1.62 2001/06/05 10:52:15 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -121,8 +121,11 @@ int type; type = skb->h.icmph->type; - if (type < 32) - return test_bit(type, &sk->tp_pinfo.tp_raw4.filter); + if (type < 32) { + __u32 data = sk->tp_pinfo.tp_raw4.filter.data; + + return ((1 << type) & data) != 0; + } /* Do not block unknown ICMP types */ return 0; diff -u --recursive --new-file v2.4.5/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c --- v2.4.5/linux/net/ipv4/tcp_input.c Thu May 24 15:00:59 2001 +++ linux/net/ipv4/tcp_input.c Mon Jun 11 19:15:27 2001 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_input.c,v 1.231 2001/05/22 05:15:16 davem Exp $ + * Version: $Id: tcp_input.c,v 1.232 2001/05/24 22:32:49 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -2611,10 +2611,10 @@ if (!after(TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt)) { /* A retransmit, 2nd most common case. Force an immediate ack. */ NET_INC_STATS_BH(DelayedACKLost); - tcp_enter_quickack_mode(tp); tcp_dsack_set(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq); out_of_window: + tcp_enter_quickack_mode(tp); tcp_schedule_ack(tp); drop: __kfree_skb(skb); diff -u --recursive --new-file v2.4.5/linux/net/ipv4/tcp_output.c linux/net/ipv4/tcp_output.c --- v2.4.5/linux/net/ipv4/tcp_output.c Thu Apr 12 12:11:39 2001 +++ linux/net/ipv4/tcp_output.c Fri Jun 29 13:38:22 2001 @@ -722,7 +722,7 @@ if (skb->ip_summed != CHECKSUM_HW) { memcpy(skb_put(skb, next_skb_size), next_skb->data, next_skb_size); - skb->csum = csum_block_add(skb->csum, next_skb->csum, skb->len); + skb->csum = csum_block_add(skb->csum, next_skb->csum, skb_size); } /* Update sequence range on original skb. */ diff -u --recursive --new-file v2.4.5/linux/net/ipv6/addrconf.c linux/net/ipv6/addrconf.c --- v2.4.5/linux/net/ipv6/addrconf.c Wed May 16 10:31:27 2001 +++ linux/net/ipv6/addrconf.c Wed Jun 20 21:00:55 2001 @@ -6,7 +6,7 @@ * Pedro Roque * Alexey Kuznetsov * - * $Id: addrconf.c,v 1.65 2001/05/03 07:02:47 davem Exp $ + * $Id: addrconf.c,v 1.66 2001/06/11 00:39:29 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -1389,7 +1389,10 @@ if (ifp->probes++ < ifp->idev->cnf.rtr_solicits) { struct in6_addr all_routers; + /* The wait after the last probe can be shorter */ addrconf_mod_timer(ifp, AC_RS, + (ifp->probes == ifp->idev->cnf.rtr_solicits) ? + ifp->idev->cnf.rtr_solicit_delay : ifp->idev->cnf.rtr_solicit_interval); spin_unlock(&ifp->lock); diff -u --recursive --new-file v2.4.5/linux/net/ipv6/af_inet6.c linux/net/ipv6/af_inet6.c --- v2.4.5/linux/net/ipv6/af_inet6.c Thu Apr 12 12:11:39 2001 +++ linux/net/ipv6/af_inet6.c Wed Jun 20 21:00:55 2001 @@ -7,9 +7,10 @@ * * Adapted from linux/net/ipv4/af_inet.c * - * $Id: af_inet6.c,v 1.63 2001/03/02 03:13:05 davem Exp $ + * $Id: af_inet6.c,v 1.64 2001/06/13 16:25:03 davem Exp $ * * Fixes: + * piggy, Karl Knutson : Socket protocol table * Hideaki YOSHIFUJI : sin6_scope_id support * Arnaldo Melo : check proc_net_create return, cleanups * @@ -44,6 +45,7 @@ #include #include #include +#include #include #include @@ -71,9 +73,6 @@ MODULE_PARM(unloadable, "i"); #endif -extern struct proto_ops inet6_stream_ops; -extern struct proto_ops inet6_dgram_ops; - /* IPv6 procfs goodies... */ #ifdef CONFIG_PROC_FS @@ -93,6 +92,11 @@ atomic_t inet6_sock_nr; #endif +/* The inetsw table contains everything that inet_create needs to + * build a new socket. + */ +struct list_head inetsw6[SOCK_MAX]; + static void inet6_sock_destruct(struct sock *sk) { inet_sock_destruct(sk); @@ -106,47 +110,63 @@ static int inet6_create(struct socket *sock, int protocol) { struct sock *sk; - struct proto *prot; + struct list_head *p; + struct inet_protosw *answer; sk = sk_alloc(PF_INET6, GFP_KERNEL, 1); if (sk == NULL) goto do_oom; - if(sock->type == SOCK_STREAM || sock->type == SOCK_SEQPACKET) { - if (protocol && protocol != IPPROTO_TCP) - goto free_and_noproto; - protocol = IPPROTO_TCP; - prot = &tcpv6_prot; - sock->ops = &inet6_stream_ops; - } else if(sock->type == SOCK_DGRAM) { - if (protocol && protocol != IPPROTO_UDP) - goto free_and_noproto; - protocol = IPPROTO_UDP; - sk->no_check = UDP_CSUM_DEFAULT; - prot=&udpv6_prot; - sock->ops = &inet6_dgram_ops; - } else if(sock->type == SOCK_RAW) { - if (!capable(CAP_NET_RAW)) - goto free_and_badperm; - if (!protocol) - goto free_and_noproto; - prot = &rawv6_prot; - sock->ops = &inet6_dgram_ops; + /* Look for the requested type/protocol pair. */ + answer = NULL; + br_read_lock_bh(BR_NETPROTO_LOCK); + list_for_each(p, &inetsw6[sock->type]) { + answer = list_entry(p, struct inet_protosw, list); + + /* Check the non-wild match. */ + if (protocol == answer->protocol) { + if (protocol != IPPROTO_IP) + break; + } else { + /* Check for the two wild cases. */ + if (IPPROTO_IP == protocol) { + protocol = answer->protocol; + break; + } + if (IPPROTO_IP == answer->protocol) + break; + } + answer = NULL; + } + br_read_unlock_bh(BR_NETPROTO_LOCK); + + if (!answer) + goto free_and_badtype; + if (answer->capability > 0 && !capable(answer->capability)) + goto free_and_badperm; + if (!protocol) + goto free_and_noproto; + + sock->ops = answer->ops; + sock_init_data(sock, sk); + + sk->prot = answer->prot; + sk->no_check = answer->no_check; + if (INET_PROTOSW_REUSE & answer->flags) sk->reuse = 1; + + if (SOCK_RAW == sock->type) { sk->num = protocol; - } else { - goto free_and_badtype; + if (IPPROTO_RAW == protocol) + sk->protinfo.af_inet.hdrincl = 1; } - - sock_init_data(sock, sk); sk->destruct = inet6_sock_destruct; sk->zapped = 0; sk->family = PF_INET6; sk->protocol = protocol; - sk->prot = prot; - sk->backlog_rcv = prot->backlog_rcv; + sk->backlog_rcv = answer->prot->backlog_rcv; sk->net_pinfo.af_inet6.hop_limit = -1; sk->net_pinfo.af_inet6.mcast_hops = -1; @@ -175,9 +195,6 @@ #endif MOD_INC_USE_COUNT; - if (sk->type==SOCK_RAW && protocol==IPPROTO_RAW) - sk->protinfo.af_inet.hdrincl=1; - if (sk->num) { /* It assumes that any protocol which allows * the user to assign a number at socket @@ -186,16 +203,15 @@ sk->sport = ntohs(sk->num); sk->prot->hash(sk); } - if (sk->prot->init) { int err = sk->prot->init(sk); if (err != 0) { MOD_DEC_USE_COUNT; inet_sock_release(sk); - return(err); + return err; } } - return(0); + return 0; free_and_badtype: sk_free(sk); @@ -504,9 +520,76 @@ extern void ipv6_sysctl_unregister(void); #endif +static struct inet_protosw rawv6_protosw = { + type: SOCK_RAW, + protocol: IPPROTO_IP, /* wild card */ + prot: &rawv6_prot, + ops: &inet6_dgram_ops, + capability: CAP_NET_RAW, + no_check: UDP_CSUM_DEFAULT, + flags: INET_PROTOSW_REUSE, +}; + +#define INETSW6_ARRAY_LEN (sizeof(inetsw6_array) / sizeof(struct inet_protosw)) + +void +inet6_register_protosw(struct inet_protosw *p) +{ + struct list_head *lh; + struct inet_protosw *answer; + int protocol = p->protocol; + + br_write_lock_bh(BR_NETPROTO_LOCK); + + if (p->type > SOCK_MAX) + goto out_illegal; + + /* If we are trying to override a permanent protocol, bail. */ + answer = NULL; + list_for_each(lh, &inetsw6[p->type]) { + answer = list_entry(lh, struct inet_protosw, list); + + /* Check only the non-wild match. */ + if (protocol == answer->protocol && + (INET_PROTOSW_PERMANENT & answer->flags)) + break; + + answer = NULL; + } + if (answer) + goto out_permanent; + + /* Add to the BEGINNING so that we override any existing + * entry. This means that when we remove this entry, the + * system automatically returns to the old behavior. + */ + list_add(&p->list, &inetsw6[p->type]); +out: + br_write_unlock_bh(BR_NETPROTO_LOCK); + return; + +out_permanent: + printk(KERN_ERR "Attempt to override permanent protocol %d.\n", + protocol); + goto out; + +out_illegal: + printk(KERN_ERR + "Ignoring attempt to register illegal socket type %d.\n", + p->type); + goto out; +} + +void +inet6_unregister_protosw(struct inet_protosw *p) +{ + inet_unregister_protosw(p); +} + static int __init inet6_init(void) { struct sk_buff *dummy_skb; + struct list_head *r; int err; #ifdef MODULE @@ -523,6 +606,15 @@ printk(KERN_CRIT "inet6_proto_init: size fault\n"); return -EINVAL; } + + /* Register the socket-side information for inet6_create. */ + for(r = &inetsw6[0]; r < &inetsw6[SOCK_MAX]; ++r) + INIT_LIST_HEAD(r); + + /* We MUST register RAW sockets before we create the ICMP6, + * IGMP6, or NDISC control sockets. + */ + inet6_register_protosw(&rawv6_protosw); /* * ipngwg API draft makes clear that the correct semantics diff -u --recursive --new-file v2.4.5/linux/net/ipv6/exthdrs.c linux/net/ipv6/exthdrs.c --- v2.4.5/linux/net/ipv6/exthdrs.c Thu Apr 12 12:11:39 2001 +++ linux/net/ipv6/exthdrs.c Wed Jun 20 21:00:55 2001 @@ -7,7 +7,7 @@ * Andi Kleen * Alexey Kuznetsov * - * $Id: exthdrs.c,v 1.12 2001/01/22 02:36:37 davem Exp $ + * $Id: exthdrs.c,v 1.13 2001/06/19 15:58:56 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -112,6 +112,7 @@ if ((skb->h.raw + len) - skb->data > skb_headlen(skb)) goto bad; + off += 2; len -= 2; while (len > 0) { diff -u --recursive --new-file v2.4.5/linux/net/ipv6/icmp.c linux/net/ipv6/icmp.c --- v2.4.5/linux/net/ipv6/icmp.c Thu Apr 12 12:11:39 2001 +++ linux/net/ipv6/icmp.c Wed Jun 20 21:00:55 2001 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: icmp.c,v 1.31 2001/01/22 02:36:37 davem Exp $ + * $Id: icmp.c,v 1.32 2001/06/10 09:20:07 davem Exp $ * * Based on net/ipv4/icmp.c * @@ -564,7 +564,7 @@ */ if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) goto discard_it; - hdr = (struct icmp6hdr *) skb->data; + hdr = (struct icmp6hdr *) skb->h.raw; orig_hdr = (struct ipv6hdr *) (hdr + 1); rt6_pmtu_discovery(&orig_hdr->daddr, &orig_hdr->saddr, dev, ntohl(hdr->icmp6_mtu)); diff -u --recursive --new-file v2.4.5/linux/net/ipv6/ip6_fib.c linux/net/ipv6/ip6_fib.c --- v2.4.5/linux/net/ipv6/ip6_fib.c Sun Mar 25 18:14:25 2001 +++ linux/net/ipv6/ip6_fib.c Thu Jun 14 14:16:58 2001 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: ip6_fib.c,v 1.23 2001/03/19 20:31:17 davem Exp $ + * $Id: ip6_fib.c,v 1.24 2001/06/05 11:36:55 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -174,7 +174,7 @@ xb = ntohl(xb); - while (test_bit(j, &xb) == 0) + while ((xb & (1 << j)) == 0) j--; return (i * 32 + 31 - j); diff -u --recursive --new-file v2.4.5/linux/net/ipv6/raw.c linux/net/ipv6/raw.c --- v2.4.5/linux/net/ipv6/raw.c Thu Apr 12 12:11:39 2001 +++ linux/net/ipv6/raw.c Thu Jun 14 14:16:58 2001 @@ -7,7 +7,7 @@ * * Adapted from linux/net/ipv4/raw.c * - * $Id: raw.c,v 1.45 2001/02/18 09:10:42 davem Exp $ + * $Id: raw.c,v 1.46 2001/06/05 11:36:55 davem Exp $ * * Fixes: * Hideaki YOSHIFUJI : sin6_scope_id support @@ -117,8 +117,13 @@ opt = &sk->tp_pinfo.tp_raw; if (pskb_may_pull(skb, sizeof(struct icmp6hdr))) { + __u32 *data = &opt->filter.data[0]; + int bit_nr; + icmph = (struct icmp6hdr *) skb->data; - return test_bit(icmph->icmp6_type, &opt->filter); + bit_nr = icmph->icmp6_type; + + return (data[bit_nr >> 5] & (1 << (bit_nr & 31))) != 0; } return 0; } diff -u --recursive --new-file v2.4.5/linux/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c --- v2.4.5/linux/net/ipv6/tcp_ipv6.c Wed Apr 25 14:57:39 2001 +++ linux/net/ipv6/tcp_ipv6.c Wed Jun 20 21:00:55 2001 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: tcp_ipv6.c,v 1.136 2001/04/20 20:46:19 davem Exp $ + * $Id: tcp_ipv6.c,v 1.137 2001/06/13 16:25:03 davem Exp $ * * Based on: * linux/net/ipv4/tcp.c @@ -2125,8 +2125,21 @@ "TCPv6" /* name */ }; +extern struct proto_ops inet6_stream_ops; + +static struct inet_protosw tcpv6_protosw = { + type: SOCK_STREAM, + protocol: IPPROTO_TCP, + prot: &tcpv6_prot, + ops: &inet6_stream_ops, + capability: -1, + no_check: 0, + flags: INET_PROTOSW_PERMANENT, +}; + void __init tcpv6_init(void) { /* register inet6 protocol */ inet6_add_protocol(&tcpv6_protocol); + inet6_register_protosw(&tcpv6_protosw); } diff -u --recursive --new-file v2.4.5/linux/net/ipv6/udp.c linux/net/ipv6/udp.c --- v2.4.5/linux/net/ipv6/udp.c Thu Apr 12 12:11:39 2001 +++ linux/net/ipv6/udp.c Wed Jun 20 21:00:55 2001 @@ -7,7 +7,7 @@ * * Based on linux/ipv4/udp.c * - * $Id: udp.c,v 1.62 2001/03/06 21:15:11 davem Exp $ + * $Id: udp.c,v 1.63 2001/06/13 16:25:03 davem Exp $ * * Fixes: * Hideaki YOSHIFUJI : sin6_scope_id support @@ -992,7 +992,21 @@ get_port: udp_v6_get_port, }; +extern struct proto_ops inet6_dgram_ops; + +static struct inet_protosw udpv6_protosw = { + type: SOCK_DGRAM, + protocol: IPPROTO_UDP, + prot: &udpv6_prot, + ops: &inet6_dgram_ops, + capability: -1, + no_check: UDP_CSUM_DEFAULT, + flags: INET_PROTOSW_PERMANENT, +}; + + void __init udpv6_init(void) { inet6_add_protocol(&udpv6_protocol); + inet6_register_protosw(&udpv6_protosw); } diff -u --recursive --new-file v2.4.5/linux/net/ipx/af_spx.c linux/net/ipx/af_spx.c --- v2.4.5/linux/net/ipx/af_spx.c Wed May 16 10:31:27 2001 +++ linux/net/ipx/af_spx.c Sat Jun 30 10:38:44 2001 @@ -398,7 +398,7 @@ pdata->retransmit.expires = jiffies + spx_calc_rtt(0); add_timer(&pdata->retransmit); - skb2 = skb_clone(skb, GFP_BUFFER); + skb2 = skb_clone(skb, GFP_NOIO); if(skb2 == NULL) return -ENOBUFS; skb_queue_tail(&pdata->retransmit_queue, skb2); diff -u --recursive --new-file v2.4.5/linux/net/irda/irnet/irnet.h linux/net/irda/irnet/irnet.h --- v2.4.5/linux/net/irda/irnet/irnet.h Tue May 1 16:05:00 2001 +++ linux/net/irda/irnet/irnet.h Mon Jun 11 19:15:27 2001 @@ -168,6 +168,23 @@ * (but PPP doesn't read the MTU value :-() * o Declare hashbin HB_NOLOCK instead of HB_LOCAL to avoid * disabling and enabling irq twice + * + * v6 - 31/05/01 - Jean II + * o Print source address in Found, Discovery, Expiry & Request events + * o Print requested source address in /proc/net/irnet + * o Change control channel input. Allow multiple commands in one line. + * o Add saddr command to change ap->rsaddr (and use that in IrDA) + * --- + * o Make the IrDA connection procedure totally asynchronous. + * Heavy rewrite of the IAS query code and the whole connection + * procedure. Now, irnet_connect() no longer need to be called from + * a process context... + * o Enable IrDA connect retries in ppp_irnet_send(). The good thing + * is that IrDA connect retries are directly driven by PPP LCP + * retries (we retry for each LCP packet), so that everything + * is transparently controlled from pppd lcp-max-configure. + * o Add ttp_connect flag to prevent rentry on the connect procedure + * o Test and fixups to eliminate side effects of retries */ /***************************** INCLUDES *****************************/ @@ -181,6 +198,8 @@ #include #include #include +#include +#include /* isspace() */ #include #include @@ -214,7 +233,7 @@ /* PPP side of the business */ #define BLOCK_WHEN_CONNECT /* Block packets when connecting */ -#undef CONNECT_IN_SEND /* Will crash hard your box... */ +#define CONNECT_IN_SEND /* Retry IrDA connection procedure */ #undef FLUSH_TO_PPP /* Not sure about this one, let's play safe */ #undef SECURE_DEVIRNET /* Bah... */ @@ -249,9 +268,11 @@ #define DEBUG_IRDA_SERV_INFO 0 /* various info */ #define DEBUG_IRDA_SERV_ERROR 1 /* problems */ #define DEBUG_IRDA_TCB_TRACE 0 /* IRDA IrTTP callbacks */ -#define DEBUG_IRDA_OCB_TRACE 0 /* IRDA other callbacks */ #define DEBUG_IRDA_CB_INFO 0 /* various info */ #define DEBUG_IRDA_CB_ERROR 1 /* problems */ +#define DEBUG_IRDA_OCB_TRACE 0 /* IRDA other callbacks */ +#define DEBUG_IRDA_OCB_INFO 0 /* various info */ +#define DEBUG_IRDA_OCB_ERROR 1 /* problems */ #define DEBUG_ASSERT 0 /* Verify all assertions */ @@ -351,13 +372,15 @@ /* ------------------------ IrTTP part ------------------------ */ /* We create a pseudo "socket" over the IrDA tranport */ int ttp_open; /* Set when IrTTP is ready */ + int ttp_connect; /* Set when IrTTP is connecting */ struct tsap_cb * tsap; /* IrTTP instance (the connection) */ char rname[NICKNAME_MAX_LEN + 1]; /* IrDA nickname of destination */ - __u32 raddr; /* Requested peer IrDA address */ - __u32 saddr; /* my local IrDA address */ + __u32 rdaddr; /* Requested peer IrDA address */ + __u32 rsaddr; /* Requested local IrDA address */ __u32 daddr; /* actual peer IrDA address */ + __u32 saddr; /* my local IrDA address */ __u8 dtsap_sel; /* Remote TSAP selector */ __u8 stsap_sel; /* Local TSAP selector */ @@ -374,17 +397,14 @@ int nslots; /* Number of slots for discovery */ struct iriap_cb * iriap; /* Used to query remote IAS */ - wait_queue_head_t query_wait; /* Wait for the answer to a query */ - struct ias_value * ias_result; /* Result of remote IAS query */ int errno; /* status of the IAS query */ - /* ---------------------- Optional parts ---------------------- */ -#ifdef INITIAL_DISCOVERY - /* Stuff used to dump discovery log */ + /* -------------------- Discovery log part -------------------- */ + /* Used by initial discovery on the control channel + * and by irnet_discover_daddr_and_lsap_sel() */ struct irda_device_info *discoveries; /* Copy of the discovery log */ int disco_index; /* Last read in the discovery log */ int disco_number; /* Size of the discovery log */ -#endif /* INITIAL_DISCOVERY */ } irnet_socket; @@ -411,8 +431,9 @@ { irnet_event event; int unit; - __u32 addr; - char name[NICKNAME_MAX_LEN + 1]; + __u32 saddr; + __u32 daddr; + char name[NICKNAME_MAX_LEN + 1]; /* 21 + 1 */ } irnet_log; /* diff -u --recursive --new-file v2.4.5/linux/net/irda/irnet/irnet_irda.c linux/net/irda/irnet/irnet_irda.c --- v2.4.5/linux/net/irda/irnet/irnet_irda.c Sat May 19 17:47:55 2001 +++ linux/net/irda/irnet/irnet_irda.c Mon Jun 11 19:15:27 2001 @@ -8,7 +8,6 @@ * and exchange frames with IrTTP. */ -#include #include "irnet_irda.h" /* Private header */ /************************* CONTROL CHANNEL *************************/ @@ -27,14 +26,15 @@ static void irnet_post_event(irnet_socket * ap, irnet_event event, - __u32 addr, + __u32 saddr, + __u32 daddr, char * name) { unsigned long flags; /* For spinlock */ int index; /* In the log */ - DENTER(CTRL_TRACE, "(ap=0x%X, event=%d, addr=%08x, name=``%s'')\n", - (unsigned int) ap, event, addr, name); + DENTER(CTRL_TRACE, "(ap=0x%X, event=%d, daddr=%08x, name=``%s'')\n", + (unsigned int) ap, event, daddr, name); /* Protect this section via spinlock. * Note : as we are the only event producer, we only need to exclude @@ -45,7 +45,8 @@ /* Copy the event in the log */ index = irnet_events.index; irnet_events.log[index].event = event; - irnet_events.log[index].addr = addr; + irnet_events.log[index].daddr = daddr; + irnet_events.log[index].saddr = saddr; /* Try to copy IrDA nickname */ if(name) strcpy(irnet_events.log[index].name, name); @@ -129,6 +130,92 @@ /*------------------------------------------------------------------*/ /* + * Function irnet_ias_to_tsap (self, result, value) + * + * Examine an IAS object and extract TSAP + * + * We do an IAP query to find the TSAP associated with the IrNET service. + * When IrIAP pass us the result of the query, this function look at + * the return values to check for failures and extract the TSAP if + * possible. + * Also deallocate value + * The failure is in self->errno + * Return TSAP or -1 + */ +static inline __u8 +irnet_ias_to_tsap(irnet_socket * self, + int result, + struct ias_value * value) +{ + __u8 dtsap_sel = 0; /* TSAP we are looking for */ + + DENTER(IRDA_SR_TRACE, "(self=0x%X)\n", (unsigned int) self); + + /* By default, no error */ + self->errno = 0; + + /* Check if request succeeded */ + switch(result) + { + /* Standard errors : service not available */ + case IAS_CLASS_UNKNOWN: + case IAS_ATTRIB_UNKNOWN: + DEBUG(IRDA_SR_INFO, "IAS object doesn't exist ! (%d)\n", result); + self->errno = -EADDRNOTAVAIL; + break; + + /* Other errors, most likely IrDA stack failure */ + default : + DEBUG(IRDA_SR_INFO, "IAS query failed ! (%d)\n", result); + self->errno = -EHOSTUNREACH; + break; + + /* Success : we got what we wanted */ + case IAS_SUCCESS: + break; + } + + /* Check what was returned to us */ + if(value != NULL) + { + /* What type of argument have we got ? */ + switch(value->type) + { + case IAS_INTEGER: + DEBUG(IRDA_SR_INFO, "result=%d\n", value->t.integer); + if(value->t.integer != -1) + /* Get the remote TSAP selector */ + dtsap_sel = value->t.integer; + else + self->errno = -EADDRNOTAVAIL; + break; + default: + self->errno = -EADDRNOTAVAIL; + DERROR(IRDA_SR_ERROR, "bad type ! (0x%X)\n", value->type); + break; + } + + /* Cleanup */ + irias_delete_value(value); + } + else /* value == NULL */ + { + /* Nothing returned to us - usually result != SUCCESS */ + if(!(self->errno)) + { + DERROR(IRDA_SR_ERROR, + "IrDA bug : result == SUCCESS && value == NULL\n"); + self->errno = -EHOSTUNREACH; + } + } + DEXIT(IRDA_SR_TRACE, "\n"); + + /* Return the TSAP */ + return(dtsap_sel); +} + +/*------------------------------------------------------------------*/ +/* * Function irnet_find_lsap_sel (self) * * Try to lookup LSAP selector in remote LM-IAS @@ -139,7 +226,7 @@ * Note that in some case, the query fail even before we go to sleep, * creating some races... */ -static int +static inline int irnet_find_lsap_sel(irnet_socket * self) { DENTER(IRDA_SR_TRACE, "(self=0x%X)\n", (unsigned int) self); @@ -155,48 +242,101 @@ self->errno = -EHOSTUNREACH; /* Query remote LM-IAS */ - iriap_getvaluebyclass_request(self->iriap, self->saddr, self->daddr, + iriap_getvaluebyclass_request(self->iriap, self->rsaddr, self->daddr, IRNET_SERVICE_NAME, IRNET_IAS_VALUE); - /* Wait for answer (if not already failed) */ - if(self->iriap != NULL) - interruptible_sleep_on(&self->query_wait); - /* Check what happened */ - if(self->errno) + /* The above request is non-blocking. + * After a while, IrDA will call us back in irnet_getvalue_confirm() + * We will then call irnet_ias_to_tsap() and finish the + * connection procedure */ + + DEXIT(IRDA_SR_TRACE, "\n"); + return 0; +} + +/*------------------------------------------------------------------*/ +/* + * Function irnet_connect_tsap (self) + * + * Initialise the TTP socket and initiate TTP connection + * + */ +static inline int +irnet_connect_tsap(irnet_socket * self) +{ + int err; + + DENTER(IRDA_SR_TRACE, "(self=0x%X)\n", (unsigned int) self); + + /* Open a local TSAP (an IrTTP instance) */ + err = irnet_open_tsap(self); + if(err != 0) { - DEBUG(IRDA_SR_INFO, "IAS query failed! (%d)\n", self->errno); - /* Requested object/attribute doesn't exist */ - if((self->errno == IAS_CLASS_UNKNOWN) || - (self->errno == IAS_ATTRIB_UNKNOWN)) - return (-EADDRNOTAVAIL); - else - return (-EHOSTUNREACH); + self->ttp_connect = 0; + DERROR(IRDA_SR_ERROR, "connect aborted!\n"); + return(err); } - /* Get the remote TSAP selector */ - switch(self->ias_result->type) + /* Connect to remote device */ + err = irttp_connect_request(self->tsap, self->dtsap_sel, + self->rsaddr, self->daddr, NULL, + self->max_sdu_size_rx, NULL); + if(err != 0) { - case IAS_INTEGER: - DEBUG(IRDA_SR_INFO, "result=%d\n", self->ias_result->t.integer); - if(self->ias_result->t.integer != -1) - self->dtsap_sel = self->ias_result->t.integer; - else - self->dtsap_sel = 0; - break; - default: - self->dtsap_sel = 0; - DERROR(IRDA_SR_ERROR, "bad type ! (0x%X)\n", self->ias_result->type); - break; + self->ttp_connect = 0; + DERROR(IRDA_SR_ERROR, "connect aborted!\n"); + return(err); } - /* Cleanup */ - if(self->ias_result) - irias_delete_value(self->ias_result); + + /* The above call is non-blocking. + * After a while, the IrDA stack will either call us back in + * irnet_connect_confirm() or irnet_disconnect_indication() + * See you there ;-) */ DEXIT(IRDA_SR_TRACE, "\n"); - if(self->dtsap_sel) - return 0; + return(err); +} + +/*------------------------------------------------------------------*/ +/* + * Function irnet_discover_next_daddr (self) + * + * Query the IrNET TSAP of the next device in the log. + * + * Used in the TSAP discovery procedure. + */ +static inline int +irnet_discover_next_daddr(irnet_socket * self) +{ + /* Close the last instance of IrIAP, and open a new one. + * We can't reuse the IrIAP instance in the IrIAP callback */ + if(self->iriap) + { + iriap_close(self->iriap); + self->iriap = NULL; + } + /* Create a new IAP instance */ + self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self, + irnet_discovervalue_confirm); - return -EADDRNOTAVAIL; + /* Next discovery - before the call to avoid races */ + self->disco_index++; + + /* Check if we have one more address to try */ + if(self->disco_index < self->disco_number) + { + /* Query remote LM-IAS */ + iriap_getvaluebyclass_request(self->iriap, + self->discoveries[self->disco_index].saddr, + self->discoveries[self->disco_index].daddr, + IRNET_SERVICE_NAME, IRNET_IAS_VALUE); + /* The above request is non-blocking. + * After a while, IrDA will call us back in irnet_discovervalue_confirm() + * We will then call irnet_ias_to_tsap() and come back here again... */ + return(0); + } + else + return(1); } /*------------------------------------------------------------------*/ @@ -205,100 +345,67 @@ * * This try to find a device with the requested service. * + * Initiate a TSAP discovery procedure. * It basically look into the discovery log. For each address in the list, * it queries the LM-IAS of the device to find if this device offer * the requested service. * If there is more than one node supporting the service, we complain * to the user (it should move devices around). - * The, we set both the destination address and the lsap selector to point - * on the service on the unique device we have found. + * If we find one node which have the requested TSAP, we connect to it. * - * Note : this function fails if there is more than one device in range, - * because IrLMP doesn't disconnect the LAP when the last LSAP is closed. - * Moreover, we would need to wait the LAP disconnection... + * This function just start the whole procedure. It request the discovery + * log and submit the first IAS query. + * The bulk of the job is handled in irnet_discovervalue_confirm() + * + * Note : this procedure fails if there is more than one device in range + * on the same dongle, because IrLMP doesn't disconnect the LAP when the + * last LSAP is closed. Moreover, we would need to wait the LAP + * disconnection... */ static inline int irnet_discover_daddr_and_lsap_sel(irnet_socket * self) { - struct irda_device_info *discoveries; /* Copy of the discovery log */ - int number; /* Number of nodes in the log */ - int i; - int err = -ENETUNREACH; - __u32 daddr = DEV_ADDR_ANY; /* Address we found the service on */ - __u8 dtsap_sel = 0x0; /* TSAP associated with it */ + int ret; DENTER(IRDA_SR_TRACE, "(self=0x%X)\n", (unsigned int) self); - /* Ask lmp for the current discovery log - * Note : we have to use irlmp_get_discoveries(), as opposed - * to play with the cachelog directly, because while we are - * making our ias query, le log might change... */ - discoveries = irlmp_get_discoveries(&number, self->mask); - /* Check if the we got some results */ - if (discoveries == NULL) - DRETURN(-ENETUNREACH, IRDA_SR_INFO, "Cachelog empty...\n"); + /* Ask lmp for the current discovery log */ + self->discoveries = irlmp_get_discoveries(&self->disco_number, self->mask); - /* - * Now, check all discovered devices (if any), and connect - * client only about the services that the client is - * interested in... - */ - for(i = 0; i < number; i++) + /* Check if the we got some results */ + if(self->discoveries == NULL) { - /* Try the address in the log */ - self->daddr = discoveries[i].daddr; - self->saddr = 0x0; - DEBUG(IRDA_SR_INFO, "trying daddr = %08x\n", self->daddr); - - /* Query remote LM-IAS for this service */ - err = irnet_find_lsap_sel(self); - switch(err) - { - case 0: - /* We found the requested service */ - if(daddr != DEV_ADDR_ANY) - { - DEBUG(IRDA_SR_INFO, "More than one device in range supports IrNET...\n"); - } - else - { - /* First time we found that one, save it ! */ - daddr = self->daddr; - dtsap_sel = self->dtsap_sel; - } - break; - case -EADDRNOTAVAIL: - /* Requested service simply doesn't exist on this node */ - break; - default: - /* Something bad did happen :-( */ - DERROR(IRDA_SR_ERROR, "unexpected IAS query failure\n"); - self->daddr = DEV_ADDR_ANY; - kfree(discoveries); - return(-EHOSTUNREACH); - break; - } + self->disco_number = -1; + self->ttp_connect = 0; + DRETURN(-ENETUNREACH, IRDA_SR_INFO, "No Cachelog...\n"); } - /* Cleanup our copy of the discovery log */ - kfree(discoveries); + DEBUG(IRDA_SR_INFO, "Got the log (0x%X), size is %d\n", + (unsigned int) self->discoveries, self->disco_number); - /* Check out what we found */ - if(daddr == DEV_ADDR_ANY) + /* Start with the first discovery */ + self->disco_index = -1; + self->daddr = DEV_ADDR_ANY; + + /* This will fail if the log is empty - this is non-blocking */ + ret = irnet_discover_next_daddr(self); + if(ret) { - self->daddr = DEV_ADDR_ANY; - DEXIT(IRDA_SR_INFO, "cannot discover IrNET in any device !!!\n"); - return(-EADDRNOTAVAIL); + /* Close IAP */ + iriap_close(self->iriap); + self->iriap = NULL; + + /* Cleanup our copy of the discovery log */ + kfree(self->discoveries); + self->discoveries = NULL; + + self->ttp_connect = 0; + DRETURN(-ENETUNREACH, IRDA_SR_INFO, "Cachelog empty...\n"); } - /* Revert back to discovered device & service */ - self->daddr = daddr; - self->saddr = 0x0; - self->dtsap_sel = dtsap_sel; + /* Follow me in irnet_discovervalue_confirm() */ - DEBUG(IRDA_SR_INFO, "discovered IrNET at address %08x\n", self->daddr); DEXIT(IRDA_SR_TRACE, "\n"); - - return 0; + return(0); } /*------------------------------------------------------------------*/ @@ -367,13 +474,13 @@ self->magic = IRNET_MAGIC; /* Paranoia */ - init_waitqueue_head(&self->query_wait); - self->ttp_open = 0; /* Prevent higher layer from accessing IrTTP */ + self->ttp_connect = 0; /* Not connecting yet */ self->rname[0] = '\0'; /* May be set via control channel */ - self->raddr = DEV_ADDR_ANY; /* May be set via control channel */ + self->rdaddr = DEV_ADDR_ANY; /* May be set via control channel */ + self->rsaddr = 0x0; /* May be set via control channel */ self->daddr = DEV_ADDR_ANY; /* Until we get connected */ - self->saddr = 0x0; /* so IrLMP assign us any link */ + self->saddr = 0x0; /* Until we get connected */ self->max_sdu_size_rx = TTP_SAR_UNBOUND; /* Register as a client with IrLMP */ @@ -395,6 +502,12 @@ * o convert device name to an address * o find the socket number (dlsap) * o Establish the connection + * + * Note : We no longer mimic af_irda. The IAS query for finding the TSAP + * is done asynchronously, like the TTP connection. This allow us to + * call this function from any context (not only process). + * The downside is that following what's happening in there is tricky + * because it involve various functions all over the place... */ int irda_irnet_connect(irnet_socket * self) @@ -406,8 +519,11 @@ /* Check if we have opened a local TSAP : * If we have already opened a TSAP, it means that either we are already * connected or in the process of doing so... */ - if(self->tsap != NULL) + if(self->ttp_connect) DRETURN(-EBUSY, IRDA_SOCK_INFO, "Already connecting...\n"); + self->ttp_connect = 1; + if((self->iriap != NULL) || (self->tsap != NULL)) + DERROR(IRDA_SOCK_ERROR, "Socket not cleaned up...\n"); /* Insert ourselves in the hashbin so that the IrNET server can find us. * Notes : 4th arg is string of 32 char max and must be null terminated @@ -423,41 +539,34 @@ } /* If we don't have anything (no address, no name) */ - if((self->raddr == DEV_ADDR_ANY) && (self->rname[0] == '\0')) + if((self->rdaddr == DEV_ADDR_ANY) && (self->rname[0] == '\0')) { /* Try to find a suitable address */ - if((err = irnet_discover_daddr_and_lsap_sel(self)) != 0) + if((err = irnet_discover_daddr_and_lsap_sel(self)) != 0) DRETURN(err, IRDA_SOCK_INFO, "auto-connect failed!\n"); + /* In most cases, the call above is non-blocking */ } else { /* If we have only the name (no address), try to get an address */ - if(self->raddr == DEV_ADDR_ANY) + if(self->rdaddr == DEV_ADDR_ANY) { if((err = irnet_dname_to_daddr(self)) != 0) - DRETURN(err, IRDA_SOCK_INFO, "name-connect failed!\n"); + DRETURN(err, IRDA_SOCK_INFO, "name connect failed!\n"); } else /* Use the requested destination address */ - self->daddr = self->raddr; + self->daddr = self->rdaddr; /* Query remote LM-IAS to find LSAP selector */ - if((err = irnet_find_lsap_sel(self)) != 0) - DRETURN(err, IRDA_SOCK_INFO, "connect failed!\n"); + irnet_find_lsap_sel(self); + /* The above call is non blocking */ } - DEBUG(IRDA_SOCK_INFO, "daddr = %08x, lsap = %d, starting IrTTP connection\n", - self->daddr, self->dtsap_sel); - - /* Open a local TSAP (an IrTTP instance) */ - err = irnet_open_tsap(self); - DABORT(err != 0, err, IRDA_SOCK_ERROR, "connect aborted!\n"); - - /* Connect to remote device */ - err = irttp_connect_request(self->tsap, self->dtsap_sel, - self->saddr, self->daddr, NULL, - self->max_sdu_size_rx, NULL); - DABORT(err != 0, err, IRDA_SOCK_ERROR, "connect aborted!\n"); + /* At this point, we are waiting for the IrDA stack to call us back, + * or we have already failed. + * We will finish the connection procedure in irnet_connect_tsap(). + */ DEXIT(IRDA_SOCK_TRACE, "\n"); return(0); } @@ -494,8 +603,21 @@ irlmp_unregister_client(self->ckey); /* Unregister with LM-IAS */ - if(self->iriap) - iriap_close(self->iriap); + if(self->iriap) + { + iriap_close(self->iriap); + self->iriap = NULL; + } + + /* If we were connected, post a message */ + if(self->ttp_open) + { + /* Note : as the disconnect comes from ppp_generic, the unit number + * doesn't exist anymore when we post the event, so we need to pass + * NULL as the first arg... */ + irnet_post_event(NULL, IRNET_DISCONNECT_TO, + self->saddr, self->daddr, self->rname); + } /* Prevent higher layer from accessing IrTTP */ self->ttp_open = 0; @@ -507,10 +629,6 @@ irttp_disconnect_request(self->tsap, NULL, P_NORMAL); irttp_close_tsap(self->tsap); self->tsap = NULL; - /* Note : as the disconnect comes from ppp_generic, the unit number - * doesn't exist anymore when we post the event, so we need to pass - * NULL as the first arg... */ - irnet_post_event(NULL, IRNET_DISCONNECT_TO, self->daddr, self->rname); } self->stsap_sel = 0; @@ -591,8 +709,9 @@ DENTER(IRDA_SERV_TRACE, "(self=0x%X)\n", (unsigned int) self); - /* Get the address of the requester */ + /* Get the addresses of the requester */ self->daddr = irttp_get_daddr(self->tsap); + self->saddr = irttp_get_saddr(self->tsap); /* Try to get the IrDA nickname of the requester */ err = irnet_daddr_to_dname(self); @@ -621,7 +740,7 @@ while(new !=(irnet_socket *) NULL) { /* Does it have the same address ? */ - if((new->raddr == self->daddr) || (new->daddr == self->daddr)) + if((new->rdaddr == self->daddr) || (new->daddr == self->daddr)) { /* Yes !!! Get it.. */ DEBUG(IRDA_SERV_INFO, "Socket 0x%X matches daddr %#08x.\n", @@ -639,7 +758,7 @@ while(new !=(irnet_socket *) NULL) { /* Is it available ? */ - if(!(new->ttp_open) && (new->raddr == DEV_ADDR_ANY) && + if(!(new->ttp_open) && (new->rdaddr == DEV_ADDR_ANY) && (new->rname[0] == '\0') && (new->ppp_open)) { /* Yes !!! Get it.. */ @@ -703,6 +822,7 @@ /* Allow PPP to send its junk over the new socket... */ new->ttp_open = 1; + new->ttp_connect = 0; #ifdef CONNECT_INDIC_KICK /* As currently we don't packets in ppp_irnet_send(), this is not needed... * Also, not doing it give IrDA a chance to finish the setup properly @@ -711,7 +831,8 @@ #endif /* CONNECT_INDIC_KICK */ /* Notify the control channel */ - irnet_post_event(new, IRNET_CONNECT_FROM, new->daddr, self->rname); + irnet_post_event(new, IRNET_CONNECT_FROM, + new->saddr, new->daddr, self->rname); DEXIT(IRDA_SERV_TRACE, "\n"); return 0; @@ -740,13 +861,14 @@ irttp_disconnect_request(self->tsap, NULL, P_NORMAL); #endif /* FAIL_SEND_DISCONNECT */ + /* Notify the control channel (see irnet_find_socket()) */ + irnet_post_event(NULL, IRNET_REQUEST_FROM, + self->saddr, self->daddr, self->rname); + /* Clean up the server to keep it in listen state */ self->tsap->dtsap_sel = self->tsap->lsap->dlsap_sel = LSAP_ANY; self->tsap->lsap->lsap_state = LSAP_DISCONNECTED; - /* Notify the control channel */ - irnet_post_event(NULL, IRNET_REQUEST_FROM, self->daddr, self->rname); - DEXIT(IRDA_SERV_TRACE, "\n"); return; } @@ -934,14 +1056,17 @@ /* If we were active, notify the control channel */ if(self->ttp_open) - irnet_post_event(self, IRNET_DISCONNECT_FROM, self->daddr, self->rname); + irnet_post_event(self, IRNET_DISCONNECT_FROM, + self->saddr, self->daddr, self->rname); else /* If we were trying to connect, notify the control channel */ if((self->tsap) && (self != &irnet_server.s)) - irnet_post_event(self, IRNET_NOANSWER_FROM, self->daddr, self->rname); + irnet_post_event(self, IRNET_NOANSWER_FROM, + self->saddr, self->daddr, self->rname); /* Prevent higher layer from accessing IrTTP */ self->ttp_open = 0; + self->ttp_connect = 0; /* Close our IrTTP connection */ if((self->tsap) && (self != &irnet_server.s)) @@ -1001,6 +1126,7 @@ self->saddr = irttp_get_saddr(self->tsap); /* Allow higher layer to access IrTTP */ + self->ttp_connect = 0; self->ttp_open = 1; /* Give a kick in the ass of ppp_generic so that he sends us some data */ ppp_output_wakeup(&self->chan); @@ -1021,7 +1147,8 @@ kfree_skb(skb); /* Notify the control channel */ - irnet_post_event(self, IRNET_CONNECT_TO, self->daddr, self->rname); + irnet_post_event(self, IRNET_CONNECT_TO, + self->saddr, self->daddr, self->rname); DEXIT(IRDA_TCB_TRACE, "\n"); } @@ -1081,7 +1208,6 @@ LOCK_STATUS lock) { irnet_socket * self = (irnet_socket *) instance; - LOCAL_FLOW oldflow = self->tx_flow; DENTER(IRDA_TCB_TRACE, "(self=0x%X)\n", (unsigned int) self); DASSERT(self != NULL, , IRDA_CB_ERROR, "Self is NULL !!!\n"); @@ -1090,7 +1216,8 @@ switch(link) { case STATUS_NO_ACTIVITY: - irnet_post_event(self, IRNET_BLOCKED_LINK, self->daddr, self->rname); + irnet_post_event(self, IRNET_BLOCKED_LINK, + self->saddr, self->daddr, self->rname); break; default: DEBUG(IRDA_CB_INFO, "Unknown status...\n"); @@ -1199,10 +1326,14 @@ /*------------------------------------------------------------------*/ /* - * Function irnet_getvalue_confirm (obj_id, value, priv) + * Function irnet_getvalue_confirm (result, obj_id, value, priv) * - * Got answer from remote LM-IAS, just pass object to requester... + * Got answer from remote LM-IAS, just connect * + * This is the reply to a IAS query we were doing to find the TSAP of + * the device we want to connect to. + * If we have found a valid TSAP, just initiate the TTP connection + * on this TSAP. */ static void irnet_getvalue_confirm(int result, @@ -1213,27 +1344,146 @@ irnet_socket * self = (irnet_socket *) priv; DENTER(IRDA_OCB_TRACE, "(self=0x%X)\n", (unsigned int) self); - DASSERT(self != NULL, , IRDA_CB_ERROR, "Self is NULL !!!\n"); + DASSERT(self != NULL, , IRDA_OCB_ERROR, "Self is NULL !!!\n"); /* We probably don't need to make any more queries */ iriap_close(self->iriap); self->iriap = NULL; - /* Check if request succeeded */ - if(result != IAS_SUCCESS) + /* Check if already connected (via irnet_connect_socket()) */ + if(self->ttp_open) { - DEBUG(IRDA_CB_INFO, "IAS query failed! (%d)\n", result); - self->errno = result; /* We really need it later */ + DERROR(IRDA_OCB_ERROR, "Socket already connected. Ouch !\n"); + return; } - else + + /* Post process the IAS reply */ + self->dtsap_sel = irnet_ias_to_tsap(self, result, value); + + /* If error, just go out */ + if(self->errno) + { + self->ttp_connect = 0; + DERROR(IRDA_OCB_ERROR, "IAS connect failed ! (0x%X)\n", self->errno); + return; + } + + DEBUG(IRDA_OCB_INFO, "daddr = %08x, lsap = %d, starting IrTTP connection\n", + self->daddr, self->dtsap_sel); + + /* Start up TTP - non blocking */ + irnet_connect_tsap(self); + + DEXIT(IRDA_OCB_TRACE, "\n"); +} + +/*------------------------------------------------------------------*/ +/* + * Function irnet_discovervalue_confirm (result, obj_id, value, priv) + * + * Handle the TSAP discovery procedure state machine. + * Got answer from remote LM-IAS, try next device + * + * We are doing a TSAP discovery procedure, and we got an answer to + * a IAS query we were doing to find the TSAP on one of the address + * in the discovery log. + * + * If we have found a valid TSAP for the first time, save it. If it's + * not the first time we found one, complain. + * + * If we have more addresses in the log, just initiate a new query. + * Note that those query may fail (see irnet_discover_daddr_and_lsap_sel()) + * + * Otherwise, wrap up the procedure (cleanup), check if we have found + * any device and connect to it. + */ +static void +irnet_discovervalue_confirm(int result, + __u16 obj_id, + struct ias_value *value, + void * priv) +{ + irnet_socket * self = (irnet_socket *) priv; + __u8 dtsap_sel; /* TSAP we are looking for */ + + DENTER(IRDA_OCB_TRACE, "(self=0x%X)\n", (unsigned int) self); + DASSERT(self != NULL, , IRDA_OCB_ERROR, "Self is NULL !!!\n"); + + /* Post process the IAS reply */ + dtsap_sel = irnet_ias_to_tsap(self, result, value); + + /* Have we got something ? */ + if(self->errno == 0) + { + /* We found the requested service */ + if(self->daddr != DEV_ADDR_ANY) + { + DERROR(IRDA_OCB_ERROR, "More than one device in range supports IrNET...\n"); + } + else + { + /* First time we found that one, save it ! */ + self->daddr = self->discoveries[self->disco_index].daddr; + self->dtsap_sel = dtsap_sel; + } + } + + /* If no failure */ + if((self->errno == -EADDRNOTAVAIL) || (self->errno == 0)) + { + int ret; + + /* Search the next node */ + ret = irnet_discover_next_daddr(self); + if(!ret) + { + /* In this case, the above request was non-blocking. + * We will return here after a while... */ + return; + } + /* In this case, we have processed the last discovery item */ + } + + /* No more queries to be done (failure or last one) */ + + /* We probably don't need to make any more queries */ + iriap_close(self->iriap); + self->iriap = NULL; + + /* No more items : remove the log and signal termination */ + DEBUG(IRDA_OCB_INFO, "Cleaning up log (0x%X)\n", + (unsigned int) self->discoveries); + if(self->discoveries != NULL) + { + /* Cleanup our copy of the discovery log */ + kfree(self->discoveries); + self->discoveries = NULL; + } + self->disco_number = -1; + + /* Check out what we found */ + if(self->daddr == DEV_ADDR_ANY) { - /* Pass the object to the caller (so the caller must delete it) */ - self->ias_result = value; - self->errno = 0; + self->daddr = DEV_ADDR_ANY; + self->ttp_connect = 0; + DEXIT(IRDA_OCB_TRACE, ": cannot discover IrNET in any device !!!\n"); + return; } - /* Wake up any processes waiting for result */ - wake_up_interruptible(&self->query_wait); + /* Check if already connected (via irnet_connect_socket()) */ + if(self->ttp_open) + { + DERROR(IRDA_OCB_ERROR, "Socket already connected. Ouch !\n"); + return; + } + + /* We have a valid address - just connect */ + + DEBUG(IRDA_OCB_INFO, "daddr = %08x, lsap = %d, starting IrTTP connection\n", + self->daddr, self->dtsap_sel); + + /* Start up TTP - non blocking */ + irnet_connect_tsap(self); DEXIT(IRDA_OCB_TRACE, "\n"); } @@ -1268,7 +1518,7 @@ irnet_socket * self = &irnet_server.s; DENTER(IRDA_OCB_TRACE, "(self=0x%X)\n", (unsigned int) self); - DASSERT(priv == &irnet_server, , IRDA_CB_ERROR, + DASSERT(priv == &irnet_server, , IRDA_OCB_ERROR, "Invalid instance (0x%X) !!!\n", (unsigned int) priv); /* Check if node is discovered is a new one or an old one. @@ -1280,12 +1530,12 @@ return; /* Too old, not interesting -> goodbye */ } - DEBUG(IRDA_CB_INFO, "Discovered new IrNET/IrLAN node %s...\n", + DEBUG(IRDA_OCB_INFO, "Discovered new IrNET/IrLAN node %s...\n", discovery->nickname); /* Notify the control channel */ - irnet_post_event(NULL, IRNET_DISCOVER, discovery->daddr, - discovery->nickname); + irnet_post_event(NULL, IRNET_DISCOVER, + discovery->saddr, discovery->daddr, discovery->nickname); DEXIT(IRDA_OCB_TRACE, "\n"); } @@ -1306,15 +1556,15 @@ irnet_socket * self = &irnet_server.s; DENTER(IRDA_OCB_TRACE, "(self=0x%X)\n", (unsigned int) self); - DASSERT(priv == &irnet_server, , IRDA_CB_ERROR, + DASSERT(priv == &irnet_server, , IRDA_OCB_ERROR, "Invalid instance (0x%X) !!!\n", (unsigned int) priv); - DEBUG(IRDA_CB_INFO, "IrNET/IrLAN node %s expired...\n", + DEBUG(IRDA_OCB_INFO, "IrNET/IrLAN node %s expired...\n", expiry->nickname); /* Notify the control channel */ - irnet_post_event(NULL, IRNET_EXPIRE, expiry->daddr, - expiry->nickname); + irnet_post_event(NULL, IRNET_EXPIRE, + expiry->saddr, expiry->daddr, expiry->nickname); DEXIT(IRDA_OCB_TRACE, "\n"); } @@ -1370,7 +1620,8 @@ /* First, get the requested configuration */ len += sprintf(buf+len, "Requested IrDA name: \"%s\", ", self->rname); - len += sprintf(buf+len, "addr: %08x\n", self->raddr); + len += sprintf(buf+len, "daddr: %08x, ", self->rdaddr); + len += sprintf(buf+len, "saddr: %08x\n", self->rsaddr); /* Second, get all the PPP info */ len += sprintf(buf+len, " PPP state: %s", @@ -1393,7 +1644,13 @@ if(self->tsap != NULL) state = "connecting"; else - state = "idle"; + if(self->iriap != NULL) + state = "searching"; + else + if(self->ttp_connect) + state = "weird"; + else + state = "idle"; len += sprintf(buf+len, "\n IrDA state: %s, ", state); len += sprintf(buf+len, "daddr: %08x, ", self->daddr); len += sprintf(buf+len, "stsap_sel: %02x, ", self->stsap_sel); diff -u --recursive --new-file v2.4.5/linux/net/irda/irnet/irnet_irda.h linux/net/irda/irnet/irnet_irda.h --- v2.4.5/linux/net/irda/irnet/irnet_irda.h Tue May 1 16:05:00 2001 +++ linux/net/irda/irnet/irnet_irda.h Mon Jun 11 19:15:27 2001 @@ -13,7 +13,6 @@ #define IRNET_IRDA_H /***************************** INCLUDES *****************************/ -#include /* Please add other headers in irnet.h */ #include "irnet.h" /* Module global include */ @@ -69,13 +68,22 @@ irnet_post_event(irnet_socket *, irnet_event, __u32, + __u32, char *); /* ----------------------- IRDA SUBROUTINES ----------------------- */ static inline int irnet_open_tsap(irnet_socket *); -static int +static inline __u8 + irnet_ias_to_tsap(irnet_socket *, + int, + struct ias_value *); +static inline int irnet_find_lsap_sel(irnet_socket *); static inline int + irnet_connect_tsap(irnet_socket *); +static inline int + irnet_discover_next_daddr(irnet_socket *); +static inline int irnet_discover_daddr_and_lsap_sel(irnet_socket *); static inline int irnet_dname_to_daddr(irnet_socket *); @@ -135,6 +143,11 @@ __u16, struct ias_value *, void *); +static void + irnet_discovervalue_confirm(int, + __u16, + struct ias_value *, + void *); #ifdef DISCOVERY_EVENTS static void irnet_discovery_indication(discovery_t *, diff -u --recursive --new-file v2.4.5/linux/net/irda/irnet/irnet_ppp.c linux/net/irda/irnet/irnet_ppp.c --- v2.4.5/linux/net/irda/irnet/irnet_ppp.c Tue May 1 16:05:00 2001 +++ linux/net/irda/irnet/irnet_ppp.c Mon Jun 11 19:15:27 2001 @@ -37,13 +37,15 @@ const char * buf, size_t count) { - char command[5 + NICKNAME_MAX_LEN + 2]; - int length = count; + char command[IRNET_MAX_COMMAND]; + char * start; /* Current command beeing processed */ + char * next; /* Next command to process */ + int length; /* Length of current command */ DENTER(CTRL_TRACE, "(ap=0x%X, count=%d)\n", (unsigned int) ap, count); /* Check for overflow... */ - DABORT(count > (5 + NICKNAME_MAX_LEN + 1), -ENOMEM, + DABORT(count >= IRNET_MAX_COMMAND, -ENOMEM, CTRL_ERROR, "Too much data !!!\n"); /* Get the data in the driver */ @@ -53,58 +55,110 @@ return -EFAULT; } - /* Strip out '\n' if needed, and safe terminate the string */ - if(command[length - 1] == '\0') - length--; - if(command[length - 1] == '\n') - length--; - command[length] = '\0'; - DEBUG(CTRL_INFO, "Command received is ``%s'' (%d-%d).\n", - command, length, count); - - /* Check if we recognised the command */ - /* First command : name */ - if(!strncmp(command, "name", 4)) - { - /* Copy the name only if is included and not "any" */ - if((length > 5) && (strcmp(command + 5, "any"))) + /* Safe terminate the string */ + command[count] = '\0'; + DEBUG(CTRL_INFO, "Command line received is ``%s'' (%d).\n", + command, count); + + /* Check every commands in the command line */ + next = command; + while(next != NULL) + { + /* Look at the next command */ + start = next; + + /* Scrap whitespaces before the command */ + while(isspace(*start)) + start++; + + /* ',' is our command separator */ + next = strchr(start, ','); + if(next) { - /* Copy the name for later reuse (including the '/0') */ - memcpy(ap->rname, command + 5, length - 5 + 1); + *next = '\0'; /* Terminate command */ + length = next - start; /* Length */ + next++; /* Skip the '\0' */ } else - ap->rname[0] = '\0'; - DEXIT(CTRL_TRACE, " - rname = ``%s''\n", ap->rname); - return(count); - } + length = strlen(start); - /* Second command : addr */ - if(!strncmp(command, "addr", 4)) - { - /* Copy the address only if is included and not "any" */ - if((length > 5) && (strcmp(command + 5, "any"))) + DEBUG(CTRL_INFO, "Found command ``%s'' (%d).\n", start, length); + + /* Check if we recognised one of the known command + * We can't use "switch" with strings, so hack with "continue" */ + + /* First command : name -> Requested IrDA nickname */ + if(!strncmp(start, "name", 4)) { - char * endp; - __u32 daddr; + /* Copy the name only if is included and not "any" */ + if((length > 5) && (strcmp(start + 5, "any"))) + { + /* Strip out trailing whitespaces */ + while(isspace(start[length - 1])) + length--; + + /* Copy the name for later reuse */ + memcpy(ap->rname, start + 5, length - 5); + ap->rname[length - 5] = '\0'; + } + else + ap->rname[0] = '\0'; + DEBUG(CTRL_INFO, "Got rname = ``%s''\n", ap->rname); - /* Convert argument to a number (last arg is the base) */ - daddr = simple_strtoul(command + 5, &endp, 16); - /* Has it worked ? (endp should be command + count) */ - DABORT(endp <= (command + 5), -EINVAL, - CTRL_ERROR, "Invalid address.\n"); - /* Save it */ - ap->raddr = daddr; + /* Restart the loop */ + continue; + } + + /* Second command : addr, daddr -> Requested IrDA destination address + * Also process : saddr -> Requested IrDA source address */ + if((!strncmp(start, "addr", 4)) || + (!strncmp(start, "daddr", 5)) || + (!strncmp(start, "saddr", 5))) + { + __u32 addr = DEV_ADDR_ANY; + + /* Copy the address only if is included and not "any" */ + if((length > 5) && (strcmp(start + 5, "any"))) + { + char * begp = start + 5; + char * endp; + + /* Scrap whitespaces before the command */ + while(isspace(*begp)) + begp++; + + /* Convert argument to a number (last arg is the base) */ + addr = simple_strtoul(begp, &endp, 16); + /* Has it worked ? (endp should be start + length) */ + DABORT(endp <= (start + 5), -EINVAL, + CTRL_ERROR, "Invalid address.\n"); + } + /* Which type of address ? */ + if(start[0] == 's') + { + /* Save it */ + ap->rsaddr = addr; + DEBUG(CTRL_INFO, "Got rsaddr = %08x\n", ap->rsaddr); + } + else + { + /* Save it */ + ap->rdaddr = addr; + DEBUG(CTRL_INFO, "Got rdaddr = %08x\n", ap->rdaddr); + } + + /* Restart the loop */ + continue; } - else - ap->raddr = DEV_ADDR_ANY; - DEXIT(CTRL_TRACE, " - raddr = %08x\n", ap->raddr); - return(count); - } - /* Other possible command : connect N (number of retries) */ + /* Other possible command : connect N (number of retries) */ - /* Failed... */ - DABORT(1, -EINVAL, CTRL_ERROR, "Not a recognised IrNET command.\n"); + /* No command matched -> Failed... */ + DABORT(1, -EINVAL, CTRL_ERROR, "Not a recognised IrNET command.\n"); + } + + /* Success : we have parsed all commands successfully */ + return(count); } #ifdef INITIAL_DISCOVERY @@ -157,9 +211,10 @@ if(ap->disco_index < ap->disco_number) { /* Write an event */ - sprintf(event, "Found %08x (%s)\n", + sprintf(event, "Found %08x (%s) behind %08x\n", ap->discoveries[ap->disco_index].daddr, - ap->discoveries[ap->disco_index].info); + ap->discoveries[ap->disco_index].info, + ap->discoveries[ap->disco_index].saddr); DEBUG(CTRL_INFO, "Writing discovery %d : %s\n", ap->disco_index, ap->discoveries[ap->disco_index].info); @@ -256,53 +311,56 @@ switch(irnet_events.log[ap->event_index].event) { case IRNET_DISCOVER: - sprintf(event, "Discovered %08x (%s)\n", - irnet_events.log[ap->event_index].addr, - irnet_events.log[ap->event_index].name); + sprintf(event, "Discovered %08x (%s) behind %08x\n", + irnet_events.log[ap->event_index].daddr, + irnet_events.log[ap->event_index].name, + irnet_events.log[ap->event_index].saddr); break; case IRNET_EXPIRE: - sprintf(event, "Expired %08x (%s)\n", - irnet_events.log[ap->event_index].addr, - irnet_events.log[ap->event_index].name); + sprintf(event, "Expired %08x (%s) behind %08x\n", + irnet_events.log[ap->event_index].daddr, + irnet_events.log[ap->event_index].name, + irnet_events.log[ap->event_index].saddr); break; case IRNET_CONNECT_TO: sprintf(event, "Connected to %08x (%s) on ppp%d\n", - irnet_events.log[ap->event_index].addr, + irnet_events.log[ap->event_index].daddr, irnet_events.log[ap->event_index].name, irnet_events.log[ap->event_index].unit); break; case IRNET_CONNECT_FROM: sprintf(event, "Connection from %08x (%s) on ppp%d\n", - irnet_events.log[ap->event_index].addr, + irnet_events.log[ap->event_index].daddr, irnet_events.log[ap->event_index].name, irnet_events.log[ap->event_index].unit); break; case IRNET_REQUEST_FROM: - sprintf(event, "Request from %08x (%s)\n", - irnet_events.log[ap->event_index].addr, - irnet_events.log[ap->event_index].name); + sprintf(event, "Request from %08x (%s) behind %08x\n", + irnet_events.log[ap->event_index].daddr, + irnet_events.log[ap->event_index].name, + irnet_events.log[ap->event_index].saddr); break; case IRNET_NOANSWER_FROM: sprintf(event, "No-answer from %08x (%s) on ppp%d\n", - irnet_events.log[ap->event_index].addr, + irnet_events.log[ap->event_index].daddr, irnet_events.log[ap->event_index].name, irnet_events.log[ap->event_index].unit); break; case IRNET_BLOCKED_LINK: sprintf(event, "Blocked link with %08x (%s) on ppp%d\n", - irnet_events.log[ap->event_index].addr, + irnet_events.log[ap->event_index].daddr, irnet_events.log[ap->event_index].name, irnet_events.log[ap->event_index].unit); break; case IRNET_DISCONNECT_FROM: sprintf(event, "Disconnection from %08x (%s) on ppp%d\n", - irnet_events.log[ap->event_index].addr, + irnet_events.log[ap->event_index].daddr, irnet_events.log[ap->event_index].name, irnet_events.log[ap->event_index].unit); break; case IRNET_DISCONNECT_TO: sprintf(event, "Disconnected to %08x (%s)\n", - irnet_events.log[ap->event_index].addr, + irnet_events.log[ap->event_index].daddr, irnet_events.log[ap->event_index].name); break; default: @@ -794,11 +852,9 @@ { #ifdef CONNECT_IN_SEND /* Let's try to connect one more time... */ - /* Note : we won't connect fully yet, but we should be ready for - * next packet... */ - /* Note : we can't do that, we need to have a process context to - * go through interruptible_sleep_on() in irnet_find_lsap_sel() - * We need to find another way... */ + /* Note : we won't be connected after this call, but we should be + * ready for next packet... */ + /* If we are already connecting, this will fail */ irda_irnet_connect(self); #endif /* CONNECT_IN_SEND */ diff -u --recursive --new-file v2.4.5/linux/net/irda/irnet/irnet_ppp.h linux/net/irda/irnet/irnet_ppp.h --- v2.4.5/linux/net/irda/irnet/irnet_ppp.h Mon Apr 30 16:26:09 2001 +++ linux/net/irda/irnet/irnet_ppp.h Mon Jun 11 19:15:27 2001 @@ -22,13 +22,8 @@ #define IRNET_MAJOR 10 /* Misc range */ #define IRNET_MINOR 187 /* Official allocation */ -#ifdef LINKNAME_IOCTL -/* Compatibility with old ppp drivers - * Should be defined in */ -#ifndef PPPIOCSLINKNAME -#define PPPIOCSLINKNAME _IOW('t', 74, struct ppp_option_data) -#endif /* PPPIOCSLINKNAME */ -#endif /* LINKNAME_IOCTL */ +/* IrNET control channel stuff */ +#define IRNET_MAX_COMMAND 256 /* Max length of a command line */ /* PPP hardcore stuff */ diff -u --recursive --new-file v2.4.5/linux/net/khttpd/security.h linux/net/khttpd/security.h --- v2.4.5/linux/net/khttpd/security.h Wed Aug 18 09:45:10 1999 +++ linux/net/khttpd/security.h Tue Jun 12 11:06:54 2001 @@ -9,4 +9,4 @@ char value[32-sizeof(void*)]; /* fill 1 cache-line */ }; -#endif \ No newline at end of file +#endif diff -u --recursive --new-file v2.4.5/linux/net/lapb/lapb_subr.c linux/net/lapb/lapb_subr.c --- v2.4.5/linux/net/lapb/lapb_subr.c Fri Feb 9 11:34:13 2001 +++ linux/net/lapb/lapb_subr.c Fri Jun 29 19:38:26 2001 @@ -38,13 +38,8 @@ */ void lapb_clear_queues(lapb_cb *lapb) { - struct sk_buff *skb; - - while ((skb = skb_dequeue(&lapb->write_queue)) != NULL) - kfree_skb(skb); - - while ((skb = skb_dequeue(&lapb->ack_queue)) != NULL) - kfree_skb(skb); + skb_queue_purge(&lapb->write_queue); + skb_queue_purge(&lapb->ack_queue); } /* diff -u --recursive --new-file v2.4.5/linux/net/netlink/af_netlink.c linux/net/netlink/af_netlink.c --- v2.4.5/linux/net/netlink/af_netlink.c Thu Apr 12 12:11:39 2001 +++ linux/net/netlink/af_netlink.c Fri Jun 29 19:38:26 2001 @@ -9,6 +9,9 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * + * Tue Jun 26 14:36:48 MEST 2001 Herbert "herp" Rosmanith + * added netlink_proto_exit + * */ #include @@ -985,4 +988,11 @@ return 0; } +static void __exit netlink_proto_exit(void) +{ + sock_unregister(PF_NETLINK); + remove_proc_entry("net/netlink", NULL); +} + module_init(netlink_proto_init); +module_exit(netlink_proto_exit); diff -u --recursive --new-file v2.4.5/linux/net/netrom/nr_dev.c linux/net/netrom/nr_dev.c --- v2.4.5/linux/net/netrom/nr_dev.c Wed Apr 18 14:40:07 2001 +++ linux/net/netrom/nr_dev.c Wed Jun 27 17:10:55 2001 @@ -89,6 +89,7 @@ struct net_device_stats *stats = (struct net_device_stats *)dev->priv; struct sk_buff *skbn; unsigned char *bp = skb->data; + int len; if (arp_find(bp + 7, skb)) { return 1; @@ -113,13 +114,15 @@ kfree_skb(skb); + len = skbn->len; + if (!nr_route_frame(skbn, NULL)) { kfree_skb(skbn); stats->tx_errors++; } stats->tx_packets++; - stats->tx_bytes += skbn->len; + stats->tx_bytes += len; return 1; } diff -u --recursive --new-file v2.4.5/linux/net/netrom/nr_loopback.c linux/net/netrom/nr_loopback.c --- v2.4.5/linux/net/netrom/nr_loopback.c Fri Dec 29 14:44:46 2000 +++ linux/net/netrom/nr_loopback.c Wed Jun 27 17:10:55 2001 @@ -92,10 +92,6 @@ void __exit nr_loopback_clear(void) { - struct sk_buff *skb; - del_timer(&loopback_timer); - - while ((skb = skb_dequeue(&loopback_queue)) != NULL) - kfree_skb(skb); + skb_queue_purge(&loopback_queue); } diff -u --recursive --new-file v2.4.5/linux/net/netrom/nr_subr.c linux/net/netrom/nr_subr.c --- v2.4.5/linux/net/netrom/nr_subr.c Fri Dec 29 14:44:46 2000 +++ linux/net/netrom/nr_subr.c Wed Jun 27 17:10:55 2001 @@ -42,19 +42,10 @@ */ void nr_clear_queues(struct sock *sk) { - struct sk_buff *skb; - - while ((skb = skb_dequeue(&sk->write_queue)) != NULL) - kfree_skb(skb); - - while ((skb = skb_dequeue(&sk->protinfo.nr->ack_queue)) != NULL) - kfree_skb(skb); - - while ((skb = skb_dequeue(&sk->protinfo.nr->reseq_queue)) != NULL) - kfree_skb(skb); - - while ((skb = skb_dequeue(&sk->protinfo.nr->frag_queue)) != NULL) - kfree_skb(skb); + skb_queue_purge(&sk->write_queue); + skb_queue_purge(&sk->protinfo.nr->ack_queue); + skb_queue_purge(&sk->protinfo.nr->reseq_queue); + skb_queue_purge(&sk->protinfo.nr->frag_queue); } /* diff -u --recursive --new-file v2.4.5/linux/net/netsyms.c linux/net/netsyms.c --- v2.4.5/linux/net/netsyms.c Fri Apr 27 14:15:01 2001 +++ linux/net/netsyms.c Wed Jun 20 21:00:55 2001 @@ -234,6 +234,8 @@ EXPORT_SYMBOL(inetdev_lock); EXPORT_SYMBOL(inet_add_protocol); EXPORT_SYMBOL(inet_del_protocol); +EXPORT_SYMBOL(inet_register_protosw); +EXPORT_SYMBOL(inet_unregister_protosw); EXPORT_SYMBOL(ip_route_output_key); EXPORT_SYMBOL(ip_route_input); EXPORT_SYMBOL(icmp_send); diff -u --recursive --new-file v2.4.5/linux/net/packet/af_packet.c linux/net/packet/af_packet.c --- v2.4.5/linux/net/packet/af_packet.c Thu Apr 12 12:11:39 2001 +++ linux/net/packet/af_packet.c Fri Jun 29 19:38:26 2001 @@ -5,7 +5,7 @@ * * PACKET - implements raw packet sockets. * - * Version: $Id: af_packet.c,v 1.54 2001/03/03 01:20:11 davem Exp $ + * Version: $Id: af_packet.c,v 1.55 2001/06/28 01:34:29 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -1407,11 +1407,10 @@ } -static int packet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) +static int packet_ioctl(struct socket *sock, unsigned int cmd, + unsigned long arg) { struct sock *sk = sock->sk; - int err; - int pid; switch(cmd) { @@ -1433,25 +1432,26 @@ return put_user(amount, (int *)arg); } case FIOSETOWN: - case SIOCSPGRP: - err = get_user(pid, (int *) arg); - if (err) - return err; + case SIOCSPGRP: { + int pid; + if (get_user(pid, (int *) arg)) + return -EFAULT; if (current->pid != pid && current->pgrp != -pid && !capable(CAP_NET_ADMIN)) return -EPERM; sk->proc = pid; - return(0); + break; + } case FIOGETOWN: case SIOCGPGRP: return put_user(sk->proc, (int *)arg); case SIOCGSTAMP: if(sk->stamp.tv_sec==0) return -ENOENT; - err = -EFAULT; - if (!copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval))) - err = 0; - return err; + if (copy_to_user((void *)arg, &sk->stamp, + sizeof(struct timeval))) + return -EFAULT; + break; case SIOCGIFFLAGS: #ifndef CONFIG_INET case SIOCSIFFLAGS: @@ -1493,8 +1493,6 @@ case SIOCSIFDIVERT: #ifdef CONFIG_NET_DIVERT return(divert_ioctl(cmd, (struct divert_cf *) arg)); -#else - return -ENOPKG; #endif /* CONFIG_NET_DIVERT */ return -ENOPKG; @@ -1530,8 +1528,7 @@ #endif return -EOPNOTSUPP; } - /*NOTREACHED*/ - return(0); + return 0; } #ifndef CONFIG_PACKET_MMAP diff -u --recursive --new-file v2.4.5/linux/net/rose/rose_dev.c linux/net/rose/rose_dev.c --- v2.4.5/linux/net/rose/rose_dev.c Wed Apr 18 14:40:08 2001 +++ linux/net/rose/rose_dev.c Wed Jun 27 17:10:55 2001 @@ -121,6 +121,7 @@ if (!rose_route_frame(skbn, NULL)) { kfree_skb(skbn); stats->tx_errors++; + return 1; } stats->tx_packets++; diff -u --recursive --new-file v2.4.5/linux/net/rose/rose_route.c linux/net/rose/rose_route.c --- v2.4.5/linux/net/rose/rose_route.c Fri Dec 29 14:44:46 2000 +++ linux/net/rose/rose_route.c Fri Jun 29 19:38:26 2001 @@ -221,13 +221,11 @@ { struct rose_neigh *s; unsigned long flags; - struct sk_buff *skb; rose_stop_ftimer(rose_neigh); rose_stop_t0timer(rose_neigh); - while ((skb = skb_dequeue(&rose_neigh->queue)) != NULL) - kfree_skb(skb); + skb_queue_purge(&rose_neigh->queue); save_flags(flags); cli(); @@ -684,15 +682,13 @@ static void rose_del_route_by_neigh(struct rose_neigh *rose_neigh) { struct rose_route *rose_route, *s; - struct sk_buff *skb; rose_neigh->restarted = 0; rose_stop_t0timer(rose_neigh); rose_start_ftimer(rose_neigh); - while ((skb = skb_dequeue(&rose_neigh->queue)) != NULL) - kfree_skb(skb); + skb_queue_purge(&rose_neigh->queue); rose_route = rose_route_list; diff -u --recursive --new-file v2.4.5/linux/net/rose/rose_subr.c linux/net/rose/rose_subr.c --- v2.4.5/linux/net/rose/rose_subr.c Fri Dec 29 14:44:46 2000 +++ linux/net/rose/rose_subr.c Fri Jun 29 19:38:26 2001 @@ -42,13 +42,8 @@ */ void rose_clear_queues(struct sock *sk) { - struct sk_buff *skb; - - while ((skb = skb_dequeue(&sk->write_queue)) != NULL) - kfree_skb(skb); - - while ((skb = skb_dequeue(&sk->protinfo.rose->ack_queue)) != NULL) - kfree_skb(skb); + skb_queue_purge(&sk->write_queue); + skb_queue_purge(&sk->protinfo.rose->ack_queue); } /* diff -u --recursive --new-file v2.4.5/linux/net/sched/sch_cbq.c linux/net/sched/sch_cbq.c --- v2.4.5/linux/net/sched/sch_cbq.c Sun Mar 25 18:14:25 2001 +++ linux/net/sched/sch_cbq.c Mon Jun 11 19:15:27 2001 @@ -282,6 +282,7 @@ case TC_POLICE_SHOT: return NULL; default: + break; } #endif if (cl->level == 0) diff -u --recursive --new-file v2.4.5/linux/net/sched/sch_gred.c linux/net/sched/sch_gred.c --- v2.4.5/linux/net/sched/sch_gred.c Mon Jan 22 13:30:21 2001 +++ linux/net/sched/sch_gred.c Fri Jun 29 19:38:26 2001 @@ -298,14 +298,11 @@ static void gred_reset(struct Qdisc* sch) { - struct sk_buff *skb; int i; - struct gred_sched_data *q; struct gred_sched *t= (struct gred_sched *)sch->data; - while((skb=__skb_dequeue(&sch->q))!=NULL) - kfree_skb(skb); + __skb_queue_purge(&sch->q); sch->stats.backlog = 0; diff -u --recursive --new-file v2.4.5/linux/net/sched/sch_red.c linux/net/sched/sch_red.c --- v2.4.5/linux/net/sched/sch_red.c Fri Aug 18 10:26:25 2000 +++ linux/net/sched/sch_red.c Fri Jun 29 19:38:26 2001 @@ -363,10 +363,8 @@ static void red_reset(struct Qdisc* sch) { struct red_sched_data *q = (struct red_sched_data *)sch->data; - struct sk_buff *skb; - while((skb=__skb_dequeue(&sch->q))!=NULL) - kfree_skb(skb); + __skb_queue_purge(&sch->q); sch->stats.backlog = 0; PSCHED_SET_PASTPERFECT(q->qidlestart); q->qave = 0; diff -u --recursive --new-file v2.4.5/linux/net/socket.c linux/net/socket.c --- v2.4.5/linux/net/socket.c Wed Apr 25 16:13:50 2001 +++ linux/net/socket.c Mon Jun 11 19:15:27 2001 @@ -1668,6 +1668,10 @@ extern void wanrouter_init(void); #endif +#ifdef CONFIG_BLUEZ +extern void bluez_init(void); +#endif + void __init sock_init(void) { int i; @@ -1726,6 +1730,10 @@ #endif #ifdef CONFIG_NETFILTER netfilter_init(); +#endif + +#ifdef CONFIG_BLUEZ + bluez_init(); #endif } diff -u --recursive --new-file v2.4.5/linux/net/sunrpc/svc.c linux/net/sunrpc/svc.c --- v2.4.5/linux/net/sunrpc/svc.c Wed Jun 21 12:43:37 2000 +++ linux/net/sunrpc/svc.c Wed Jun 20 17:42:19 2001 @@ -368,7 +368,9 @@ err_bad_prog: #ifdef RPC_PARANOIA - printk("svc: unknown program %d (me %d)\n", prog, progp->pg_prog); + if (prog != 100227 || progp->pg_prog != 100003) + printk("svc: unknown program %d (me %d)\n", prog, progp->pg_prog); + /* else it is just a Solaris client seeing if ACLs are supported */ #endif serv->sv_stats->rpcbadfmt++; svc_putlong(resp, rpc_prog_unavail); diff -u --recursive --new-file v2.4.5/linux/net/unix/af_unix.c linux/net/unix/af_unix.c --- v2.4.5/linux/net/unix/af_unix.c Thu Apr 12 12:11:39 2001 +++ linux/net/unix/af_unix.c Fri Jun 29 16:17:10 2001 @@ -1332,7 +1332,7 @@ /* * If you pass two values to the sock_alloc_send_skb - * it tries to grab the large buffer with GFP_BUFFER + * it tries to grab the large buffer with GFP_NOFS * (which can fail easily), and if it fails grab the * fallback size buffer which is under a page and will * succeed. [Alan] diff -u --recursive --new-file v2.4.5/linux/net/unix/garbage.c linux/net/unix/garbage.c --- v2.4.5/linux/net/unix/garbage.c Fri Feb 9 11:29:44 2001 +++ linux/net/unix/garbage.c Fri Jun 29 19:38:26 2001 @@ -296,9 +296,6 @@ * Here we are. Hitlist is filled. Die. */ - while ((skb=__skb_dequeue(&hitlist))!=NULL) { - kfree_skb(skb); - } - + __skb_queue_purge(&hitlist); up(&unix_gc_sem); } diff -u --recursive --new-file v2.4.5/linux/net/wanrouter/af_wanpipe.c linux/net/wanrouter/af_wanpipe.c --- v2.4.5/linux/net/wanrouter/af_wanpipe.c Thu Apr 12 12:11:39 2001 +++ linux/net/wanrouter/af_wanpipe.c Thu Jun 28 14:42:40 2001 @@ -2633,7 +2633,7 @@ return -EINVAL; if (sk->state == WANSOCK_CONNECTED) - return EISCONN; /* No reconnect on a seqpacket socket */ + return -EISCONN; /* No reconnect on a seqpacket socket */ if (sk->state != WAN_DISCONNECTED){ printk(KERN_INFO "wansock: Trying to connect on channel NON DISCONNECT\n"); diff -u --recursive --new-file v2.4.5/linux/net/wanrouter/wanmain.c linux/net/wanrouter/wanmain.c --- v2.4.5/linux/net/wanrouter/wanmain.c Thu Apr 12 12:11:39 2001 +++ linux/net/wanrouter/wanmain.c Wed Jun 27 17:10:55 2001 @@ -611,10 +611,10 @@ if (conf->data_size && conf->data){ if(conf->data_size > 128000 || conf->data_size < 0) { - kfree(conf); printk(KERN_INFO "%s: ERROR, Invalid firmware data size %i !\n", wandev->name, conf->data_size); + kfree(conf); return -EINVAL;; } @@ -764,23 +764,23 @@ { wanif_conf_t conf; netdevice_t *dev=NULL; - #ifdef CONFIG_WANPIPE_MULTPPP +#ifdef CONFIG_WANPIPE_MULTPPP struct ppp_device *pppdev=NULL; - #endif +#endif int err; if ((wandev->state == WAN_UNCONFIGURED) || (wandev->new_if == NULL)) return -ENODEV; - #if defined (LINUX_2_1) || defined (LINUX_2_4) +#if defined (LINUX_2_1) || defined (LINUX_2_4) if(copy_from_user(&conf, u_conf, sizeof(wanif_conf_t))) return -EFAULT; - #else +#else err = verify_area(VERIFY_READ, u_conf, sizeof(wanif_conf_t)); if (err) return err; memcpy_fromfs((void*)&conf, (void*)u_conf, sizeof(wanif_conf_t)); - #endif +#endif if (conf.magic != ROUTER_MAGIC) return -EINVAL; @@ -797,13 +797,14 @@ } memset(pppdev, 0, sizeof(struct ppp_device)); - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,16) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,16) pppdev->dev = kmalloc(sizeof(netdevice_t), GFP_KERNEL); if (pppdev->dev == NULL){ + kfree(pppdev); return -ENOBUFS; } memset(pppdev->dev, 0, sizeof(netdevice_t)); - #endif +#endif err = wandev->new_if(wandev, (netdevice_t *)pppdev, &conf); diff -u --recursive --new-file v2.4.5/linux/net/wanrouter/wanproc.c linux/net/wanrouter/wanproc.c --- v2.4.5/linux/net/wanrouter/wanproc.c Thu May 24 15:01:02 2001 +++ linux/net/wanrouter/wanproc.c Wed Jun 27 17:10:55 2001 @@ -813,8 +813,10 @@ offs = file->f_pos; if (offs < pos) { len = min(pos - offs, count); - if(copy_to_user(buf, (page + offs), len)) + if (copy_to_user(buf, (page + offs), len)) { + kfree(page); return -EFAULT; + } file->f_pos += len; } else diff -u --recursive --new-file v2.4.5/linux/net/x25/x25_link.c linux/net/x25/x25_link.c --- v2.4.5/linux/net/x25/x25_link.c Wed Jan 24 15:28:36 2001 +++ linux/net/x25/x25_link.c Fri Jun 29 19:38:26 2001 @@ -309,10 +309,8 @@ { struct x25_neigh *s; unsigned long flags; - struct sk_buff *skb; - while ((skb = skb_dequeue(&x25_neigh->queue)) != NULL) - kfree_skb(skb); + skb_queue_purge(&x25_neigh->queue); x25_stop_t20timer(x25_neigh); diff -u --recursive --new-file v2.4.5/linux/net/x25/x25_subr.c linux/net/x25/x25_subr.c --- v2.4.5/linux/net/x25/x25_subr.c Wed Jan 24 15:28:36 2001 +++ linux/net/x25/x25_subr.c Fri Jun 29 19:38:26 2001 @@ -17,6 +17,7 @@ * X.25 002 Jonathan Naylor Centralised disconnection processing. * mar/20/00 Daniela Squassoni Disabling/enabling of facilities * negotiation. + * jun/24/01 Arnaldo C. Melo use skb_queue_purge, cleanups */ #include @@ -45,22 +46,11 @@ */ void x25_clear_queues(struct sock *sk) { - struct sk_buff *skb; - - while ((skb = skb_dequeue(&sk->write_queue)) != NULL) - kfree_skb(skb); - - while ((skb = skb_dequeue(&sk->protinfo.x25->ack_queue)) != NULL) - kfree_skb(skb); - - while ((skb = skb_dequeue(&sk->protinfo.x25->interrupt_in_queue)) != NULL) - kfree_skb(skb); - - while ((skb = skb_dequeue(&sk->protinfo.x25->interrupt_out_queue)) != NULL) - kfree_skb(skb); - - while ((skb = skb_dequeue(&sk->protinfo.x25->fragment_queue)) != NULL) - kfree_skb(skb); + skb_queue_purge(&sk->write_queue); + skb_queue_purge(&sk->protinfo.x25->ack_queue); + skb_queue_purge(&sk->protinfo.x25->interrupt_in_queue); + skb_queue_purge(&sk->protinfo.x25->interrupt_out_queue); + skb_queue_purge(&sk->protinfo.x25->fragment_queue); } @@ -72,20 +62,20 @@ void x25_frames_acked(struct sock *sk, unsigned short nr) { struct sk_buff *skb; - int modulus; - - modulus = (sk->protinfo.x25->neighbour->extended) ? X25_EMODULUS : X25_SMODULUS; + int modulus = sk->protinfo.x25->neighbour->extended ? X25_EMODULUS : + X25_SMODULUS; /* * Remove all the ack-ed frames from the ack queue. */ - if (sk->protinfo.x25->va != nr) { - while (skb_peek(&sk->protinfo.x25->ack_queue) != NULL && sk->protinfo.x25->va != nr) { + if (sk->protinfo.x25->va != nr) + while (skb_peek(&sk->protinfo.x25->ack_queue) != NULL && + sk->protinfo.x25->va != nr) { skb = skb_dequeue(&sk->protinfo.x25->ack_queue); kfree_skb(skb); - sk->protinfo.x25->va = (sk->protinfo.x25->va + 1) % modulus; + sk->protinfo.x25->va = (sk->protinfo.x25->va + 1) % + modulus; } - } } void x25_requeue_frames(struct sock *sk) @@ -113,18 +103,15 @@ int x25_validate_nr(struct sock *sk, unsigned short nr) { unsigned short vc = sk->protinfo.x25->va; - int modulus; - - modulus = (sk->protinfo.x25->neighbour->extended) ? X25_EMODULUS : X25_SMODULUS; + int modulus = sk->protinfo.x25->neighbour->extended ? X25_EMODULUS : + X25_SMODULUS; while (vc != sk->protinfo.x25->vs) { if (nr == vc) return 1; vc = (vc + 1) % modulus; } - if (nr == sk->protinfo.x25->vs) return 1; - - return 0; + return nr == sk->protinfo.x25->vs ? 1 : 0; } /* @@ -150,7 +137,8 @@ */ switch (frametype) { case X25_CALL_REQUEST: - len += 1 + X25_ADDR_LEN + X25_MAX_FAC_LEN + X25_MAX_CUD_LEN; + len += 1 + X25_ADDR_LEN + X25_MAX_FAC_LEN + + X25_MAX_CUD_LEN; break; case X25_CALL_ACCEPTED: len += 1 + X25_MAX_FAC_LEN + X25_MAX_CUD_LEN; @@ -167,7 +155,8 @@ case X25_RESET_CONFIRMATION: break; default: - printk(KERN_ERR "X.25: invalid frame type %02X\n", frametype); + printk(KERN_ERR "X.25: invalid frame type %02X\n", + frametype); return; } @@ -262,11 +251,10 @@ /* * Unpick the contents of the passed X.25 Packet Layer frame. */ -int x25_decode(struct sock *sk, struct sk_buff *skb, int *ns, int *nr, int *q, int *d, int *m) +int x25_decode(struct sock *sk, struct sk_buff *skb, int *ns, int *nr, int *q, + int *d, int *m) { - unsigned char *frame; - - frame = skb->data; + unsigned char *frame = skb->data; *ns = *nr = *q = *d = *m = 0; @@ -323,12 +311,14 @@ } } - printk(KERN_DEBUG "X.25: invalid PLP frame %02X %02X %02X\n", frame[0], frame[1], frame[2]); + printk(KERN_DEBUG "X.25: invalid PLP frame %02X %02X %02X\n", + frame[0], frame[1], frame[2]); return X25_ILLEGAL; } -void x25_disconnect(struct sock *sk, int reason, unsigned char cause, unsigned char diagnostic) +void x25_disconnect(struct sock *sk, int reason, unsigned char cause, + unsigned char diagnostic) { x25_clear_queues(sk); x25_stop_timer(sk); diff -u --recursive --new-file v2.4.5/linux/scripts/Configure linux/scripts/Configure --- v2.4.5/linux/scripts/Configure Sat Dec 30 18:16:13 2000 +++ linux/scripts/Configure Mon Jul 2 13:56:40 2001 @@ -92,6 +92,7 @@ /^#/b /^[^ ]/q + /]*\\)>/s//\\1/g p }" Documentation/Configure.help) if [ -z "$text" ] diff -u --recursive --new-file v2.4.5/linux/scripts/Menuconfig linux/scripts/Menuconfig --- v2.4.5/linux/scripts/Menuconfig Sat May 19 17:47:55 2001 +++ linux/scripts/Menuconfig Mon Jul 2 13:56:40 2001 @@ -376,6 +376,7 @@ /^#/b /^[^ ]/q s/^ // + /]*\\)>/s//\\1/g p }" Documentation/Configure.help) diff -u --recursive --new-file v2.4.5/linux/scripts/docgen linux/scripts/docgen --- v2.4.5/linux/scripts/docgen Tue Mar 14 17:54:42 2000 +++ linux/scripts/docgen Wed Jun 20 20:56:24 2001 @@ -1,3 +1,10 @@ #!/bin/sh -X=`$TOPDIR/scripts/gen-all-syms "$*"` -$TOPDIR/scripts/docproc $X +set -e +if [ -z "$scripts_objtree" ] +then + X=`$TOPDIR/scripts/gen-all-syms "$*"` + $TOPDIR/scripts/docproc $X +else + X=`${scripts_objtree}gen-all-syms "$*"` + TOPDIR=. ${scripts_objtree}docproc $X +fi diff -u --recursive --new-file v2.4.5/linux/scripts/docproc.c linux/scripts/docproc.c --- v2.4.5/linux/scripts/docproc.c Wed Apr 12 09:47:30 2000 +++ linux/scripts/docproc.c Wed Jun 20 20:56:24 2001 @@ -18,6 +18,7 @@ char type[64]; int i; int vp=2; + int ret=0; pid_t pid; @@ -96,8 +97,8 @@ perror("exec scripts/kernel-doc"); exit(1); default: - waitpid(pid, NULL,0); + waitpid(pid, &ret ,0); } } - exit(0); + exit(ret); } diff -u --recursive --new-file v2.4.5/linux/scripts/header.tk linux/scripts/header.tk --- v2.4.5/linux/scripts/header.tk Mon Jun 19 13:45:52 2000 +++ linux/scripts/header.tk Mon Jul 2 13:56:40 2001 @@ -466,6 +466,7 @@ /^#/b /^\[^ \]/q s/^ // + /\]*\\)>/s//\\1/g p } " Documentation/Configure.help] diff -u --recursive --new-file v2.4.5/linux/scripts/kernel-doc linux/scripts/kernel-doc --- v2.4.5/linux/scripts/kernel-doc Wed Apr 25 16:31:16 2001 +++ linux/scripts/kernel-doc Mon Jul 2 13:56:40 2001 @@ -18,10 +18,19 @@ # Functions prototyped as foo(void) same as foo() # Stop eval'ing where we don't need to. # -- huggie@earth.li + +# 27/06/2001 - Allowed whitespace after initial "/**" and +# allowed comments before function declarations. +# -- Christian Kreibich + # Still to do: # - add perldoc documentation # - Look more closely at some of the scarier bits :) +# 26/05/2001 - Support for separate source and object trees. +# Return error code. +# Keith Owens + # # This will read a 'c' file and scan for embedded comments in the # style of gnome comments (+minor extensions - see below). @@ -97,6 +106,8 @@ # '@parameter' - name of a parameter # '%CONST' - name of a constant. +my $errors = 0; + # match expressions used to find embedded type information my $type_constant = '\%([-_\w]+)'; my $type_func = '(\w+)\(\)'; @@ -198,6 +209,7 @@ my @parameterlist = (); my %sections = (); my @sectionlist = (); +my %source_map = (); my $contents = ""; my $section_default = "Description"; # default section @@ -776,6 +788,7 @@ if (defined $type && $type && !defined $parameters{$param}) { $parameters{$param} = "-- undescribed --"; print STDERR "Warning($file:$.): Function parameter '$param' not described in '$function_name'\n"; + ++$errors; } push @parameterlist, $param; @@ -784,6 +797,7 @@ } } else { print STDERR "Error($.): cannot understand prototype: '$prototype'\n"; + ++$errors; return; } @@ -816,7 +830,7 @@ $doc_special = "\@\%\$\&"; -$doc_start = "^/\\*\\*\$"; +$doc_start = "^/\\*\\*\\s*\$"; # Allow whitespace at end of comment start. $doc_end = "\\*/"; $doc_com = "\\s*\\*\\s*"; $doc_func = $doc_com."(\\w+):?"; @@ -837,6 +851,19 @@ sub process_file($); +# Read the file that maps relative names to absolute names for +# separate source and object directories and for shadow trees. +if (open(SOURCE_MAP, "<.tmp_filelist.txt")) { + my ($relname, $absname); + while() { + chop(); + ($relname, $absname) = (split())[0..1]; + $relname =~ s:^/+::; + $source_map{$relname} = $absname; + } + close(SOURCE_MAP); +} + if ($filelist) { open(FLIST,"<$filelist") or die "Can't open file list $filelist"; while() { @@ -850,11 +877,17 @@ process_file($_); } +exit($errors); + sub process_file($) { my ($file) = @_; + if (defined($source_map{$file})) { + $file = $source_map{$file}; + } if (!open(IN,"<$file")) { print STDERR "Error: Cannot open file $file\n"; + ++$errors; return; } @@ -887,6 +920,7 @@ } else { print STDERR "WARN($.): Cannot understand $_ on line $.", " - I thought it was a doc line\n"; + ++$errors; $state = 0; } } elsif ($state == 2) { # look for head: lines, and include content @@ -937,6 +971,7 @@ } else { # i dont know - bad line? ignore. print STDERR "WARNING($.): bad line: $_"; + ++$errors; } } elsif ($state == 3) { # scanning for function { (end of prototype) if (m#\s*/\*\s+MACDOC\s*#io) { @@ -945,7 +980,7 @@ elsif (/([^\{]*)/) { $prototype .= $1; } - if (/\{/ || /\#/) { # added for #define AK + if (/\{/ || /\#/ || /;/) { # added for #define AK, ';' added for declarations. $prototype =~ s@/\*.*?\*/@@gos; # strip comments. $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's. $prototype =~ s@^ +@@gos; # strip leading spaces