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 Tue Jun 12 10:57:05 2001 @@ -1356,13 +1356,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 +1520,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 @@ -2697,9 +2710,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á 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 Mon Jun 11 19:15:27 2001 @@ -320,7 +320,7 @@ LVM toolset ----------- -o +o Pcmcia-cs --------- 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 Wed Jun 20 17:51:24 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 @@ -10182,91 +10216,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 +10370,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 +10511,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 +10530,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 +10546,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 +10554,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 +10644,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 +11110,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). @@ -10972,6 +11374,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 +11544,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 @@ -13241,8 +13658,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 +14147,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 +14177,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 +15351,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 @@ -16711,11 +17182,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 +17196,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/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/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 Wed Jun 20 11:15:44 2001 @@ -14,12 +14,3 @@ * 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. - 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/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/MAINTAINERS linux/MAINTAINERS --- v2.4.5/linux/MAINTAINERS Sun May 20 12:11:38 2001 +++ linux/MAINTAINERS Wed Jun 20 20:56:24 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 @@ -804,9 +799,9 @@ 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 +1082,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 +1164,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 +1189,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 +1336,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 @@ -1571,6 +1560,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 Wed Jun 20 16:25:55 2001 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 -SUBLEVEL = 5 -EXTRAVERSION = +SUBLEVEL = 6 +EXTRAVERSION =-pre5 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) # @@ -155,7 +156,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 @@ -177,6 +179,7 @@ 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/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/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_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/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/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/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 Wed Jun 20 11:30:44 2001 @@ -103,6 +103,64 @@ # CONFIG_MTD is not set # +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_CFI_INTELEXT is not set +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_AMDSTD is not set +# CONFIG_MTD_SHARP is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_JEDEC is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_SUN_UFLASH is not set +# CONFIG_MTD_NORA is not set +# CONFIG_MTD_PNC2000 is not set +# CONFIG_MTD_RPXLITE is not set +# CONFIG_MTD_SC520CDP is not set +# CONFIG_MTD_NETSC520 is not set +# CONFIG_MTD_SBC_GXX is not set +# CONFIG_MTD_ELAN_104NC is not set +# CONFIG_MTD_SA1100 is not set +# CONFIG_MTD_SA1100_REDBOOT_PARTITIONS is not set +# CONFIG_MTD_SA1100_BOOTLDR_PARTITIONS is not set +# CONFIG_MTD_DC21285 is not set +# CONFIG_MTD_IQ80310 is not set +# CONFIG_MTD_DBOX2 is not set +# CONFIG_MTD_CSTM_MIPS_IXX is not set +# CONFIG_MTD_CFI_FLAGADM is not set +# CONFIG_MTD_MIXMEM is not set +# CONFIG_MTD_OCTAGON is not set +# CONFIG_MTD_VMAX is not set +# CONFIG_MTD_OCELOT is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_MTDRAM is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC1000 is not set +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOCPROBE is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_NAND_SPIA is not set + +# # Parallel port support # # CONFIG_PARPORT is not set @@ -192,7 +250,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 +275,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 +293,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 +305,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 @@ -445,7 +504,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 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/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/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/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/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/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 Jun 11 19:15:27 2001 @@ -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/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 Jun 11 19:15:27 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.10 06/05/01 20:20:05 paulus */ /* * misc.c @@ -393,7 +393,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 +406,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/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 Jun 11 19:15:27 2001 @@ -365,6 +365,10 @@ 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 Jun 11 19:15:27 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.19 05/26/01 14:48:14 paulus # # # Makefile for the linux kernel. @@ -32,7 +32,7 @@ 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 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 Tue Jun 12 11:07:16 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.15 06/09/01 22:16:38 paulus */ /* * PowerPC version @@ -310,25 +310,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/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 Jun 11 19:15:27 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.26 06/06/01 22:33:09 paulus */ /* * arch/ppc/kernel/irq.c @@ -551,6 +551,9 @@ 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/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 Tue Jun 12 11:07:16 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.34 06/09/01 22:38:13 paulus */ #include #include @@ -357,7 +357,6 @@ #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); 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/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 Jun 11 19:15:27 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.23 06/06/01 22:49:01 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; @@ -670,16 +672,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 +1192,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 +1227,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 +1243,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 +1468,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 +1483,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 +1971,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/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< #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 Wed Jun 20 21:00:55 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.25 2001/06/14 16:57:41 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; @@ -819,6 +883,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/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/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 Wed Jun 20 17:47:40 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; } @@ -265,10 +310,10 @@ 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/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 Tue Jun 12 11:06:54 2001 @@ -439,6 +439,7 @@ case FORE200E_STATE_BLANK: /* nothing to do for that state */ + break; } } 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/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 Tue Jun 12 11:17:17 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 Mon Jun 11 19:15:27 2001 @@ -651,8 +651,8 @@ inode->i_mapping->gfp_mask = GFP_BUFFER; 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/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/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 Wed Jun 20 21:00:55 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 */ 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 Wed Jun 20 21:00:55 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 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/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/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/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 Tue Jun 12 11:49:36 2001 @@ -1793,7 +1793,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 +1810,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/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/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/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/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 20 11:16:01 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}) @@ -343,6 +344,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 }, 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/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 Tue Jun 12 10:35:21 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.8 2001/05/17 21:15:33 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.9 $"; #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/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 Tue Jun 12 13:03:18 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.6 2001/05/17 20:41:51 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 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/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 Tue Jun 12 10:34:48 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.3 2001/05/26 15:19:57 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.3 $"; extern struct IsdnCard cards[]; extern int nrcards; @@ -850,14 +850,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 Tue Jun 12 10:34:48 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.14 2001/05/26 15:19:57 kai Exp $ * * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden @@ -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/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/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 Tue Jun 12 10:34:48 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.5 2001/05/26 15:19:57 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); @@ -1335,19 +1335,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/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 Tue Jun 12 10:36:21 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 Tue Jun 12 10:34:48 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.2 2001/05/26 15:19:57 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.2 $"; static void l2m_debug(struct FsmInst *fi, char *fmt, ...); @@ -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 Tue Jun 12 10:34:48 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.3 2001/05/26 15:19:57 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.3 $"; static struct Fsm l3fsm; @@ -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/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 Tue Jun 12 10:34:48 2001 @@ -8,11 +8,11 @@ # 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 +13c3eed869f5139f44c563e3a8fea1f5 isdnl1.c +64dcc220ae42fe9e4bbc664c9525bd0a isdnl2.c +700aa997e04f5e7e0d32f0d60c8e7fa9 isdnl3.c +51c603829b6cc4f8421f744ad657ceff tei.c +144d646162d83bb5b99095917d131865 callc.c e592db58630c1f1029cc064110108156 cert.c fadeb3b85bb23bc1ac48470c0848d6fa l3dss1.c cf7dec9fac6283716904d26b99188476 l3_1tr6.c @@ -22,12 +22,12 @@ # end of md5sums -----BEGIN PGP SIGNATURE----- -Version: 2.6.3i +Version: 2.6.3in Charset: noconv -iQCVAwUBOt+j/jpxHvX/mS9tAQGXwAP/U4voKzXAcTfo9CqJhHN92GRxunj6mlvn -H+1pxSe0GdtC7BlrPhrokB5dNSwewk89Z5t7kTD76kx2FFuTcXBJxbgH7LZVF3ga -JX92bOWQekHMH7Hk12Qc7zpeTmPzY02pvVc37Eo614BCvJMCk02cpQyo8a5wWRKH -8vpQkQKiSyY= -=FFLG +iQCVAwUBOxFX6zpxHvX/mS9tAQE+bgP7B5FFxU+RQ3l8fBvZoMbu/Mslo9+XgtLg +gK8Xwnp4Ij909fa2i6i2bvFPkzHULMqp2PRdtxBTn9CdhwSZyRByhCvZvDHitsv2 +ZEIRn2Bd1jhhgWcr5KCbjKUaIwcFY7RdSQJw/yCyGsodg1fLI+g+QrnMkICI/RTa +AtYLLWgwEqo= +=3IMV -----END PGP SIGNATURE----- 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/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/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/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 Wed Jun 20 20:55:08 2001 @@ -634,7 +634,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 +646,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 +686,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 +694,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 +777,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 +793,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 +820,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 +838,7 @@ ITERATE_RDEV(mddev,rdev,tmp2) print_rdev(rdev); } - printk(" **********************************\n"); + printk("md: **********************************\n"); printk("\n"); } @@ -917,15 +917,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 +1014,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 +1044,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 +1057,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 +1088,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 +1240,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 +1259,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 +1485,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; @@ -1663,7 +1659,7 @@ err = mddev->pers->run(mddev); if (err) { - printk("pers->run() failed ...\n"); + printk("md: pers->run() failed ...\n"); mddev->pers = NULL; return -EINVAL; } @@ -1705,7 +1701,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 */ @@ -1793,7 +1789,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 +1802,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 +1839,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 +1878,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 +1904,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 +1917,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 +1925,7 @@ } autorun_array(mddev); } - printk("... autorun DONE.\n"); + printk("md: ... autorun DONE.\n"); } /* @@ -1971,7 +1967,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 +1977,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 +1987,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 +2003,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 +2125,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 +2133,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 +2188,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 +2217,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 +2257,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 +2272,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 +2427,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 +2547,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 +2569,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 +2587,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 +2599,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 +2618,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 +2756,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 +2769,7 @@ return err; done: if (err) - printk("huh12?\n"); + printk("md: huh12?\n"); abort: return err; } @@ -2835,7 +2831,7 @@ */ current->policy = SCHED_OTHER; current->nice = -20; -// md_unlock_kernel(); + md_unlock_kernel(); up(thread->sem); @@ -2845,9 +2841,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 +2855,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 +2866,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 +2905,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); } @@ -3132,7 +3128,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 +3137,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 +3199,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; } @@ -3332,7 +3328,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; @@ -3481,7 +3477,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); @@ -3518,7 +3514,7 @@ 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 +3526,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 +3556,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 +3601,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 +3634,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 +3653,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 +3702,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 Wed Jun 20 20:55:08 2001 @@ -82,7 +82,7 @@ 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); } } @@ -1123,7 +1123,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/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/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 Tue Jun 12 10:30:27 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,29 @@ 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 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 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 Jun 12 10:30:27 2001 @@ -0,0 +1,16 @@ +# drivers/mtd/nand/Config.in + +# $Id: Config.in,v 1.1 2001/04/20 15:27:38 dwmw2 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 +dep_tristate ' NAND Flash device on SPIA board' CONFIG_MTD_NAND_SPIA $CONFIG_MTD_NAND + +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 Tue Jun 12 10:30:27 2001 @@ -0,0 +1,14 @@ +# +# linux/drivers/nand/Makefile +# +# $Id: Makefile,v 1.3 2001/04/19 23:54:48 dwmw2 Exp $ + +O_TARGET := nandlink.o + +export-objs := nand.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 Tue Jun 12 10:30:27 2001 @@ -0,0 +1,204 @@ +/* + * 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.4 2001/01/03 20:02:20 mgadbois 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 + +/* + * Pre-calculated 256-way 1 byte column parity + */ +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 + */ +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; +} 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 Jun 12 10:30:27 2001 @@ -0,0 +1,129 @@ +/* + * drivers/mtd/spia.c + * + * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com) + * + * $Id: spia.c,v 1.9 2001/06/02 14:47:16 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 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; + +/* + * Module stuff + */ +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) + #define spia_init init_module + #define spia_cleanup cleanup_module +#endif + +/* + * 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 *) (IO_BASE + PEDDR)) = 0x07; + + /* Set address of NAND IO lines */ + this->IO_ADDR = FIO_BASE; + this->CTRL_ADDR = IO_BASE + 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 20 11:10:53 2001 @@ -1007,9 +1007,12 @@ MODULE_PARM(irq,"1-8i"); MODULE_PARM(xcvr,"1-8i"); MODULE_PARM(max_interrupt_work, "i"); -#ifdef CONFIG_ISAPNP +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"); MODULE_PARM(nopnp, "i"); -#endif +MODULE_PARM_DESC(nopnp, "EtherLink III disable ISA PnP support (0-1)"); 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 Wed Jun 20 11:15:44 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 @@ -208,9 +222,11 @@ #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 +235,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 +253,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 +280,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 +834,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 +849,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 +865,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 +884,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 +953,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 +961,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 +972,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 +996,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 +1015,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 +1145,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 +1268,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 +1279,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 +1292,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 +1764,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 +1772,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 +2336,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,6 +2613,35 @@ 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; @@ -2580,6 +2651,8 @@ int retval; 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] = phy; case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ @@ -2774,9 +2847,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 Wed Jun 20 11:10:52 2001 @@ -136,6 +136,10 @@ */ +#define DRV_NAME "8139too" +#define DRV_VERSION "0.9.18-pre3" + + #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); @@ -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) @@ -1691,6 +1707,10 @@ unsigned int entry; unsigned long flags; + /* XXX paranoid + sledgehammer == temporary system crash fix */ + wmb(); + spin_lock_irqsave (&tp->lock, flags); + /* Calculate the next Tx descriptor entry. */ entry = tp->cur_tx % NUM_TX_DESC; @@ -1701,13 +1721,14 @@ 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)); + RTL_W32_F (TxAddr0 + (entry * 4), + 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); + RTL_W32_F (TxAddr0 + (entry * 4), tp->tx_info[entry].mapping); } /* Note: the chip doesn't have auto-pad! */ @@ -1716,8 +1737,6 @@ dev->trans_start = jiffies; - spin_lock_irqsave (&tp->lock, flags); - tp->cur_tx++; if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) netif_stop_queue (dev); @@ -1760,7 +1779,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); } if (txstatus & TxCarrierLost) tp->stats.tx_carrier_errors++; @@ -1865,11 +1884,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 +1901,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 +1908,6 @@ unsigned int pkt_size; struct sk_buff *skb; - mb(); - /* 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); } @@ -2059,26 +2069,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 +2083,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,8 +2092,7 @@ rtl8139_weird_interrupt (dev, tp, ioaddr, status, link_changed); - if (netif_running (dev) && - status & (TxOK | TxErr)) { + if (netif_running (dev) && (status & (TxOK | TxErr))) { spin_lock (&tp->lock); rtl8139_tx_interrupt (dev, tp, ioaddr); spin_unlock (&tp->lock); @@ -2110,10 +2102,8 @@ } 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); @@ -2216,7 +2206,7 @@ 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]); @@ -2308,8 +2298,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 +2314,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 +2322,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 +2332,7 @@ unsigned long flags; if (!netif_running (dev)) - return; + return 0; netif_device_detach (dev); @@ -2354,27 +2347,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 Wed Jun 20 11:10:52 2001 @@ -177,7 +177,9 @@ 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 + if [ "$CONFIG_ISA" = "y" -a "$CONFIG_X86" = "y" ]; then + tristate ' AT-LAN-TEC/RealTek pocket adapter support' CONFIG_ATP + fi tristate ' D-Link DE600 pocket adapter support' CONFIG_DE600 tristate ' D-Link DE620 pocket adapter support' CONFIG_DE620 fi 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 Wed Jun 20 11:10:53 2001 @@ -740,7 +740,6 @@ } -#ifdef MODULE MODULE_AUTHOR("Jes Sorensen "); MODULE_DESCRIPTION("AceNIC/3C985/GA620 Gigabit Ethernet driver"); MODULE_PARM(link, "1-" __MODULE_STRING(8) "i"); @@ -749,7 +748,12 @@ MODULE_PARM(max_tx_desc, "1-" __MODULE_STRING(8) "i"); MODULE_PARM(rx_coal_tick, "1-" __MODULE_STRING(8) "i"); MODULE_PARM(max_rx_desc, "1-" __MODULE_STRING(8) "i"); -#endif +MODULE_PARM_DESC(link, "Acenic/3C985/NetGear link state"); +MODULE_PARM_DESC(trace, "Acenic/3C985/NetGear firmware trace level"); +MODULE_PARM_DESC(tx_coal_tick, "Acenic/3C985/NetGear maximum clock ticks to wait for packets"); +MODULE_PARM_DESC(max_tx_desc, "Acenic/3C985/NetGear maximum number of transmit descriptors"); +MODULE_PARM_DESC(rx_coal_tick, "Acenic/3C985/NetGear maximum clock ticks to wait for packets"); +MODULE_PARM_DESC(max_rx_desc, "Acenic/3C985/NetGear maximum number of receive descriptors"); static void __exit ace_module_cleanup(void) 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/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/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 Wed Jun 20 11:10:53 2001 @@ -2014,7 +2014,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/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 Wed Jun 20 11:16:01 2001 @@ -124,18 +124,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, "epro100: Bits 0-3: tranceiver type, bit 4: full duplex, bit 5: 100Mbps"); +MODULE_PARM_DESC(full_duplex, "epro100 full duplex setting(s) (1)"); +MODULE_PARM_DESC(congenb, "epro100 Enable congestion control (1)"); +MODULE_PARM_DESC(txfifo, "epro100 Tx FIFO threshold in 4 byte units, (0-15)"); +MODULE_PARM_DESC(rxfifo, "epro100 Rx FIFO threshold in 4 byte units, (0-15)"); +MODULE_PARM_DESC(txdmaccount, "epro100 Tx DMA burst length; 128 - disable (0-128)"); +MODULE_PARM_DESC(rxdmaccount, "epro100 Rx DMA burst length; 128 - disable (0-128)"); +MODULE_PARM_DESC(rx_copybreak, "epro100 copy breakpoint for copy-only-tiny-frames"); +MODULE_PARM_DESC(max_interrupt_work, "epro100 maximum events handled per interrupt"); +MODULE_PARM_DESC(multicast_filter_limit, "epro100 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) @@ -470,7 +481,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 +523,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); @@ -1910,7 +1921,7 @@ 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[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f); if (t) add_timer(&sp->timer); /* may be set to the past --SAW */ pci_set_power_state(sp->pdev, saved_acpi); @@ -2129,8 +2140,8 @@ 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; long ioaddr = dev->base_addr; @@ -2139,9 +2150,10 @@ 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 speedo_private *sp = (struct speedo_private *)dev->priv; @@ -2160,8 +2172,9 @@ 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) { @@ -2192,7 +2205,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 +2216,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 Wed Jun 20 11:13:18 2001 @@ -100,6 +100,7 @@ #error You must compile this driver with "-O". #endif +#include #include #include #include @@ -116,6 +117,7 @@ #include #include #include +#include #include #include #include @@ -135,6 +137,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 +1176,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 @@ -1445,38 +1452,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 20 11:10:53 2001 @@ -1849,6 +1849,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 Wed Jun 20 11:13:18 2001 @@ -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. */ @@ -107,12 +109,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 +371,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 +472,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 +541,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 +652,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 +662,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 +680,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 +868,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. @@ -1077,7 +1117,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; } @@ -1168,14 +1209,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 +1231,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 +1245,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 +1264,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 +1284,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 +1299,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 +1308,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 +1358,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 +1472,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 +1607,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 +1621,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 +1649,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; } @@ -1727,16 +1785,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 Wed Jun 20 11:10:53 2001 @@ -535,7 +535,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); 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 Wed Jun 20 11:10:53 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). 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 Wed Jun 20 11:13:18 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); } @@ -758,18 +845,29 @@ 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 +883,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 +897,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 +964,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 +998,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 +1053,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 +1066,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 +1085,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 +1131,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 +1142,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 +1170,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 +1180,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 +1187,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 +1221,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 +1253,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 +1271,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 +1326,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 +1393,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 +1406,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 +1428,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 +1444,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 +1468,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/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 Wed Jun 20 11:13:18 2001 @@ -85,6 +85,7 @@ */ +#include #include #include #include @@ -480,11 +481,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); @@ -1790,7 +1795,7 @@ case SIOCDEVPRIVATE + 1: /* Read the specified MII register. */ spin_lock_irqsave (&tp->lock, flags); - data[3] = mdio_read (dev, data[0], data[1] & 0x1f); + data[3] = mdio_read (dev, data[0] & 0x1f, data[1] & 0x1f); spin_unlock_irqrestore (&tp->lock, flags); break; @@ -1801,7 +1806,7 @@ } spin_lock_irqsave (&tp->lock, flags); - mdio_write (dev, data[0], data[1] & 0x1f, data[2]); + mdio_write (dev, data[0] & 0x1f, data[1] & 0x1f, data[2]); spin_unlock_irqrestore (&tp->lock, flags); break; @@ -1918,7 +1923,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 +1949,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 +1963,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/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/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 Wed Jun 20 11:10:53 2001 @@ -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 20 11:10:53 2001 @@ -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 Wed Jun 20 11:13:18 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 @@ -63,7 +64,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 +111,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 +160,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 +380,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 +398,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); @@ -1243,6 +1249,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 +1265,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 ? 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 Wed Jun 20 21:00:55 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. */ +#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 mii_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,28 +702,27 @@ 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; @@ -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,7 +1659,10 @@ 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; @@ -1260,15 +1698,17 @@ switch (data[1]) { 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]); return 0; @@ -1284,8 +1724,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 +1744,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 +1771,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 +1805,7 @@ { struct net_device *dev = pci_get_drvdata(pdev); struct netdev_private *np; - + if (!dev) BUG(); @@ -1358,7 +1813,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 +1835,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 +1864,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 Wed Jun 20 11:13:18 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,8 @@ #include #include #include +#include +#include #include /* Processor type for cache alignment. */ #include #include @@ -93,7 +100,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 +116,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 +359,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 +380,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 +414,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 +436,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 +462,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); @@ -1156,11 +1171,37 @@ 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) +{ + 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; 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 netdev_private *)dev->priv)->phys[0] & 0x1f; /* Fall Through */ @@ -1258,7 +1299,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 Wed Jun 20 11:10:53 2001 @@ -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 Wed Jun 20 11:13:18 2001 @@ -194,6 +194,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 */ @@ -917,13 +922,13 @@ data[0] = phy; case SIOCDEVPRIVATE+1: /* Read MII register */ - TLan_MiiReadReg(dev, data[0], data[1], &data[3]); + TLan_MiiReadReg(dev, data[0] & 0x1f, data[1] & 0x1f, &data[3]); return 0; case SIOCDEVPRIVATE+2: /* Write MII register */ if (!capable(CAP_NET_ADMIN)) return -EPERM; - TLan_MiiWriteReg(dev, data[0], data[1], data[2]); + TLan_MiiWriteReg(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]); return 0; default: return -EOPNOTSUPP; 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 Wed Jun 20 11:13:18 2001 @@ -26,6 +26,10 @@ * 1. Multicast support. */ +#if defined(__alpha__) || defined(__ia64__) +#error FIXME: driver does not support 64-bit platforms +#endif + #ifdef MODULE #include #include 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 Wed Jun 20 11:19:02 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-pre5" +#define DRV_RELDATE "June 16, 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. */ @@ -1108,7 +1153,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 +1238,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 + /* read cache line size again, hardware may not have accepted + * our cache line size change */ - 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 - */ - 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 +1448,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 +1470,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 +1482,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 +1658,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 +1689,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 +1705,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 +1716,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 +1744,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 +1777,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 +1793,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 +1815,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 +1831,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 Wed Jun 20 11:15:44 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! @@ -132,9 +146,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 +180,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 +263,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 +278,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 +341,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 +469,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 +541,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 +559,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 +625,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 +676,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 +973,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 +1080,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 +1471,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); @@ -1445,7 +1530,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/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/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/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 Wed Jun 20 11:13:18 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,15 @@ #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 +146,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 +379,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 +412,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 +466,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; @@ -1312,11 +1325,37 @@ 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; 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 netdev_private *)dev->priv)->phys[0] & 0x1f; /* Fall Through */ @@ -1403,7 +1442,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 Wed Jun 20 11:10:53 2001 @@ -0,0 +1,4321 @@ +/*====================================================================== + + 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 + + /* arguably, we should clean up and error exit if pci_module_init + * fails with an error other than -ENODEV, instead of proceeding, + * if ISA devs are present. + */ + if (have_isa_dev) + return 0; + if (rc && (rc != -ENODEV)) + return rc; + 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 Wed Jun 20 11:13:18 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)"; /*====================================================================*/ @@ -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 Wed Jun 20 11:13:18 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,13 +1345,39 @@ 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; 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] = np->phys[0] & 0x1f; /* Fall Through */ @@ -1390,7 +1431,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/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 Tue Jun 12 16:47:56 2001 @@ -229,49 +229,120 @@ } /** - * 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, since we can't access the + * PCI config space for the device + */ + 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; } /** @@ -314,6 +385,48 @@ } } +/** + * 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 (!pm) return -EIO; /* this device cannot poweroff - up to bridge to cut power */ + + /* make sure device supports wake events (from any state) */ + pci_read_config_word(dev,pm+PCI_PM_PMC,&value); + + if (!(value & PCI_PM_CAP_PME_MASK)) return -EINVAL; /* doesn't support wake events */ + + /* + * XXX - We're assuming that device can generate wake events from whatever + * state it may be entering. + * We're not actually checking what state we're going into to. + */ + pci_read_config_word(dev, pm + PCI_PM_CTRL, &value); + + if (enable) value |= PCI_PM_CTRL_PME_STATUS; + else value &= ~PCI_PM_CTRL_PME_STATUS; + + 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 +1385,41 @@ * 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_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; } - /* take care to suspend/resume bridges only once */ -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 +1437,15 @@ return 0; } -static int pci_pm_suspend(void) +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,14 +1463,16 @@ 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) { switch (rqst) { case PM_SUSPEND: - return pci_pm_suspend(); + return pci_pm_suspend((u32)data); case PM_RESUME: return pci_pm_resume(); - } + default: break; + } return 0; } #endif @@ -1741,7 +1857,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 +1876,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 +1888,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 Wed Jun 20 21:00:55 2001 @@ -3893,6 +3893,7 @@ 14e2 INFOLIBRIA 14e3 AMTELCO 14e4 BROADCOM Corporation + 1644 Tigon3 14e5 Pixelfusion Ltd 14e6 SHINING Technology Inc 14e7 3CX @@ -4599,13 +4600,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 Wed Jun 20 11:21:33 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: 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 Wed Jun 20 21:00:55 2001 @@ -1,8 +1,11 @@ -/* $Id: sab82532.c,v 1.58 2001/04/17 06:30:36 davem Exp $ +/* $Id: sab82532.c,v 1.62 2001/06/10 06:48:47 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); } @@ -1523,8 +1574,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 +1709,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 +1724,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 +1741,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 +2212,7 @@ static inline void __init show_serial_version(void) { - char *revision = "$Revision: 1.58 $"; + char *revision = "$Revision: 1.62 $"; char *version, *p; version = strchr(revision, ' '); diff -u --recursive --new-file v2.4.5/linux/drivers/scsi/NCR53c406a.c linux/drivers/scsi/NCR53c406a.c --- v2.4.5/linux/drivers/scsi/NCR53c406a.c Tue May 22 10:23:16 2001 +++ linux/drivers/scsi/NCR53c406a.c Tue Jun 12 11:06:54 2001 @@ -221,7 +221,7 @@ (void *)0xc8000 }; #define ADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned )) -#endif USE_BIOS +#endif /* USE_BIOS */ /* possible i/o port addresses */ static unsigned short ports[] = @@ -244,7 +244,7 @@ { "Copyright (C) Acculogic, Inc.\r\n2.8M Diskette Extension Bios ver 4.04.03 03/01/1993", 61, 82 }, }; #define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature )) -#endif USE_BIOS +#endif /* USE_BIOS */ /* ============================================================ */ @@ -347,7 +347,7 @@ return tmp; } -#endif USE_DMA +#endif /* USE_DMA */ #if USE_PIO static __inline__ int NCR53c406a_pio_read(unsigned char *request, @@ -455,7 +455,7 @@ } return 0; } -#endif USE_PIO +#endif /* USE_PIO */ int __init NCR53c406a_detect(Scsi_Host_Template * tpnt){ @@ -481,7 +481,7 @@ } DEB(printk("NCR53c406a BIOS found at %X\n", (unsigned int) bios_base);); -#endif USE_BIOS +#endif /* USE_BIOS */ #ifdef PORT_BASE if (!request_region(port_base, 0x10, "NCR53c406a")) /* ports already snatched */ @@ -512,7 +512,7 @@ } } } -#endif PORT_BASE +#endif /* PORT_BASE */ if(!port_base){ /* no ports found */ printk("NCR53c406a: no available ports found\n"); @@ -550,7 +550,7 @@ #if USE_DMA printk("NCR53c406a: No interrupts found and DMA mode defined. Giving up.\n"); goto err_release; -#endif USE_DMA +#endif /* USE_DMA */ } else { DEB(printk("NCR53c406a: Shouldn't get here!\n")); @@ -565,7 +565,7 @@ } DEB(printk("Allocated DMA channel %d\n", dma_chan)); -#endif USE_DMA +#endif /* USE_DMA */ tpnt->present = 1; tpnt->proc_name = "NCR53c406a"; @@ -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; @@ -1011,7 +1011,7 @@ return irq; } -#endif IRQ_LEV +#endif /* IRQ_LEV */ static void chip_init() { 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/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/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/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_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/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/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/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/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 20 11:19:02 2001 @@ -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;iirq) { - 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", 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 Tue Jun 12 11:06:54 2001 @@ -231,6 +231,7 @@ break; default: + break; } } else { mi->m_prev_status = midic; 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 20 11:10:27 2001 @@ -6261,20 +6261,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 20 17:51:24 2001 @@ -53,7 +53,7 @@ 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 @@ -65,6 +65,7 @@ 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 20 17:51:24 2001 @@ -63,6 +63,7 @@ obj-$(CONFIG_USB_PLUSB) += plusb.o obj-$(CONFIG_USB_OV511) += ov511.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 Tue Jun 12 15:53:37 2001 @@ -127,8 +127,16 @@ static int get_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data) { int ret; + unsigned char *buffer; DECLARE_WAITQUEUE(wait, current); + 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 ) { pegasus->flags |= CTRL_URB_SLEEP; interruptible_sleep_on( &pegasus->ctrl_wait ); @@ -143,7 +151,7 @@ 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 ); @@ -157,6 +165,8 @@ schedule(); remove_wait_queue( &pegasus->ctrl_wait, &wait ); out: + memcpy(data,buffer,size); + kfree(buffer); return ret; } @@ -164,8 +174,16 @@ static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data) { int ret; + unsigned char *buffer; DECLARE_WAITQUEUE(wait, current); + 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 ) { pegasus->flags |= CTRL_URB_SLEEP ; interruptible_sleep_on( &pegasus->ctrl_wait ); @@ -180,7 +198,7 @@ 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 ); @@ -188,12 +206,14 @@ if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) ) { err( __FUNCTION__ " BAD CTRL %d", ret); + kfree(buffer); return ret; } schedule(); remove_wait_queue( &pegasus->ctrl_wait, &wait ); + kfree(buffer); return ret; } @@ -201,9 +221,17 @@ static int set_register( pegasus_t *pegasus, __u16 indx, __u8 data ) { int ret; + unsigned char *buffer; __u16 dat = data; DECLARE_WAITQUEUE(wait, current); + 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 ) { pegasus->flags |= CTRL_URB_SLEEP; interruptible_sleep_on( &pegasus->ctrl_wait ); @@ -218,7 +246,7 @@ 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 ); @@ -226,12 +254,14 @@ if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) ) { err( __FUNCTION__ " BAD CTRL %d", ret); + kfree(buffer); return ret; } schedule(); remove_wait_queue( &pegasus->ctrl_wait, &wait ); + kfree(buffer); return ret; } @@ -905,8 +935,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/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/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/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.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 Tue Jun 12 15:53:37 2001 @@ -2774,8 +2774,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 Tue Jun 12 15:53:37 2001 @@ -3108,8 +3108,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 Wed Jun 20 21:00:55 2001 @@ -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 */ @@ -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; @@ -1833,7 +1833,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 +1885,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 +1931,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: @@ -2622,7 +2622,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/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/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 Mon Jun 11 19:15:27 2001 @@ -2483,7 +2483,7 @@ return 0; } -static int __init initialized = 0; +static int initialized __initdata = 0; int __init matroxfb_init(void) { 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 Wed Jun 20 11:10:27 2001 @@ -104,9 +104,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/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/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 Tue Jun 12 10:21:14 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 */ @@ -646,8 +646,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 +711,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); @@ -1348,11 +1351,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; } 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 Mon Jun 11 19:15:27 2001 @@ -199,10 +199,15 @@ 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 +215,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)) 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/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/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 Jun 12 11:09:28 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; 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 Tue Jun 12 11:16:41 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 Tue Jun 12 11:12:47 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; } 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 Tue Jun 12 11:12:47 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; 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 Mon Jun 11 19:27:15 2001 @@ -635,15 +635,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/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 Tue Jun 12 10:44:57 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; } @@ -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 Thu Jun 14 14:16:58 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 @@ -1421,6 +1482,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 +1786,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 Tue Jun 12 10:44:57 2001 @@ -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 { 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 Tue Jun 12 11:12:47 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 */ 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/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 Tue Jun 12 11:06:54 2001 @@ -442,7 +442,7 @@ brelse(bh); printk("SysV FS: cannot read superblock in %d byte mode\n", sb->sv_block_size); goto failed; - superblock_ok: + superblock_ok:; } } else { /* Switch to 512 block size. Unfortunately, we have to 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 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 @@ -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; 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 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 @@ -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), @@ -199,7 +204,7 @@ 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 +250,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 +276,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 +284,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 +298,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 +372,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 +396,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 +421,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 +450,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 +468,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 +488,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 +515,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 +526,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 +554,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 +655,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 +700,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 +818,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 +834,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 +845,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 +958,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 +1037,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 +1066,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,8 +1074,6 @@ 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) << @@ -1171,11 +1246,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 +1296,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 +1309,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 +1318,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 +1389,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); } @@ -1305,7 +1402,10 @@ if (udf_time_to_stamp(&cpu_time, inode->i_atime, UDF_I_UATIME(inode))) 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); + 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; @@ -1327,7 +1427,10 @@ 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))) + { efe->createTime = cpu_to_lets(cpu_time); + 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 +1466,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 +1547,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 +1606,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 +1668,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 +1693,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 +1721,8 @@ return -1; } } + else + atomic_inc(&bh->b_count); if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_SHORT) adsize = sizeof(short_ad); @@ -1609,39 +1735,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 +1791,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 +1978,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 +2000,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 +2016,7 @@ struct buffer_head *obh; lb_addr obloc; int oextoffset, adsize; - int type; + char type; struct AllocExtDesc *aed; if (!(nbh)) @@ -1901,7 +2050,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 +2066,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 +2078,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 +2098,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 +2114,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 +2136,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 +2171,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 Jun 11 19:15:27 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 ) 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/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/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-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/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 Wed Jun 20 16:33:07 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 Wed Jun 20 16:33:07 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 Wed Jun 20 16:33:07 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 Wed Jun 20 16:33:37 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 Wed Jun 20 20:56:24 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-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/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/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 Wed Jun 20 21:00:55 2001 @@ -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/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 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-mips64/linux_logo.h linux/include/asm-mips64/linux_logo.h --- v2.4.5/linux/include/asm-mips64/linux_logo.h Sat May 13 08:31:25 2000 +++ linux/include/asm-mips64/linux_logo.h Mon Jun 11 19:15:27 2001 @@ -24,918 +24,897 @@ #define linux_logo_banner "Linux/MIPS64 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-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/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/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/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-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/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/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/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-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 Tue Jun 12 11:08:46 2001 @@ -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 Wed Jun 20 16:33:07 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 Wed Jun 20 16:33:07 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 Wed Jun 20 16:33:07 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.. */ @@ -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 Wed Jun 20 16:33:56 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 Wed Jun 20 21:00:55 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 Wed Jun 20 16:33:07 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 Wed Jun 20 16:33:07 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 Wed Jun 20 16:33:07 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/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/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 Wed Jun 20 16:33:09 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,18 +528,17 @@ /* * 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 +#define __GFP_HIGH 0x20 +#define __GFP_IO 0x40 +#define __GFP_BUFFER 0x80 - -#define GFP_BUFFER (__GFP_HIGH | __GFP_WAIT) +#define GFP_BUFFER (__GFP_HIGH | __GFP_WAIT | __GFP_BUFFER) #define GFP_ATOMIC (__GFP_HIGH) #define GFP_USER ( __GFP_WAIT | __GFP_IO) #define GFP_HIGHUSER ( __GFP_WAIT | __GFP_IO | __GFP_HIGHMEM) @@ -533,11 +589,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 Wed Jun 20 16:33:07 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/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 Wed Jun 20 16:33:37 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,11 @@ 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 (*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,13 +555,17 @@ 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) */ 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 Wed Jun 20 21:00:55 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 @@ -1135,6 +1152,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 @@ -1366,6 +1384,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 +1497,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 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 Wed Jun 20 16:33:26 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 Wed Jun 20 16:33:09 2001 @@ -22,7 +22,7 @@ #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_BUFFER) #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 Wed Jun 20 16:33:07 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 Wed Jun 20 16:33:07 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/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 Wed Jun 20 16:33:57 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 Wed Jun 20 16:33:07 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; @@ -200,6 +201,16 @@ ZERO_PAGE_BUG \ SetPageInactiveDirty(page); \ list_add(&(page)->lru, &inactive_dirty_list); \ + nr_inactive_dirty_pages++; \ + page->zone->inactive_dirty_pages++; \ +} + +/* Like the above, but add us after the bookmark. */ +#define add_page_to_inactive_dirty_list_marker(page) { \ + DEBUG_ADD_PAGE \ + ZERO_PAGE_BUG \ + SetPageInactiveDirty(page); \ + list_add(&(page)->lru, marker_lru); \ nr_inactive_dirty_pages++; \ page->zone->inactive_dirty_pages++; \ } 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 Jun 11 19:15:27 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/06" +#define UDFFS_VERSION "0.9.4" + +#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 Jun 11 19:15:27 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 @@ -38,6 +38,7 @@ __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 +55,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 Wed Jun 20 16:33:05 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 Jun 11 19:15:27 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 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 Wed Jun 20 21:00: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 Wed Jun 20 21:00: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/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 Mon Jun 11 19:15:27 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: 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 Mon Jun 11 19:15:27 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 */ 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/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 Jun 11 19:15:27 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(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 Wed Jun 20 20:53:12 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,31 @@ } /* * 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_BUFFER allocations; because they + * do not have __GFP_IO 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_IO)) + 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 +690,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 Tue Jun 12 16:02:38 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; } @@ -411,7 +407,7 @@ /** * 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,18 +424,18 @@ * go out to Matthew Dillon. */ #define MAX_LAUNDER (4 * (1 << page_cluster)) +#define CAN_DO_IO (gfp_mask & __GFP_IO) +#define CAN_DO_BUFFERS (gfp_mask & __GFP_BUFFER) +#define marker_lru (&marker_page_struct.lru) int page_launder(int gfp_mask, int sync) { + static int cannot_free_pages; 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; + /* Our bookmark of where we are in the inactive_dirty list. */ + struct page marker_page_struct = { zone: NULL }; launder_loop = 0; maxlaunder = 0; @@ -447,11 +443,44 @@ dirty_page_rescan: spin_lock(&pagemap_lru_lock); - maxscan = nr_inactive_dirty_pages; - while ((page_lru = inactive_dirty_list.prev) != &inactive_dirty_list && - maxscan-- > 0) { + /* + * By not scanning all inactive dirty pages we'll write out + * really old dirty pages before evicting newer clean pages. + * This should cause some LRU behaviour if we have a large + * amount of inactive pages (due to eg. drop behind). + * + * It also makes us accumulate dirty pages until we have enough + * to be worth writing to disk without causing excessive disk + * seeks and eliminates the infinite penalty clean pages incurred + * vs. dirty pages. + */ + maxscan = nr_inactive_dirty_pages / 4; + if (launder_loop) + maxscan *= 2; + list_add_tail(marker_lru, &inactive_dirty_list); + for (;;) { + page_lru = marker_lru->prev; + if (page_lru == &inactive_dirty_list) + break; + if (--maxscan < 0) + break; + if (!free_shortage()) + break; + page = list_entry(page_lru, struct page, lru); + /* Move the bookmark backwards.. */ + list_del(marker_lru); + list_add_tail(marker_lru, page_lru); + + /* Don't waste CPU if chances are we cannot free anything. */ + if (launder_loop && maxlaunder < 0 && cannot_free_pages) + break; + + /* Skip other people's marker pages. */ + if (!page->zone) + continue; + /* Wrong page on list?! (list corruption, should not happen) */ if (!PageInactiveDirty(page)) { printk("VM: page_launder, wrong page on list.\n"); @@ -472,11 +501,9 @@ /* * The page is locked. IO in progress? - * Move it to the back of the list. + * Skip the page, we'll take a look when it unlocks. */ if (TryLockPage(page)) { - list_del(page_lru); - list_add(page_lru, &inactive_dirty_list); continue; } @@ -490,10 +517,8 @@ if (!writepage) goto page_active; - /* First time through? Move it to the back of the list */ - if (!launder_loop) { - list_del(page_lru); - list_add(page_lru, &inactive_dirty_list); + /* First time through? Skip the page. */ + if (!launder_loop || !CAN_DO_IO) { UnlockPage(page); continue; } @@ -506,6 +531,8 @@ writepage(page); page_cache_release(page); + maxlaunder--; + /* And re-start the thing.. */ spin_lock(&pagemap_lru_lock); continue; @@ -533,9 +560,9 @@ spin_unlock(&pagemap_lru_lock); /* Will we do (asynchronous) IO? */ - if (launder_loop && maxlaunder == 0 && sync) + if (launder_loop && maxlaunder-- == 0 && sync) wait = 2; /* Synchrounous IO */ - else if (launder_loop && maxlaunder-- > 0) + else if (launder_loop && maxlaunder > 0) wait = 1; /* Async IO */ else wait = 0; /* No IO */ @@ -552,7 +579,7 @@ /* The buffers were not freed. */ if (!clearedbuf) { - add_page_to_inactive_dirty_list(page); + add_page_to_inactive_dirty_list_marker(page); /* The page was only in the buffer cache. */ } else if (!page->mapping) { @@ -608,6 +635,8 @@ UnlockPage(page); } } + /* Remove our marker. */ + list_del(marker_lru); spin_unlock(&pagemap_lru_lock); /* @@ -621,18 +650,31 @@ * 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_BUFFERS) && !launder_loop && free_shortage()) { launder_loop = 1; - /* If we cleaned pages, never do synchronous IO. */ - if (cleaned_pages) + /* + * If we, or the previous process running page_launder(), + * managed to free any pages we never do synchronous IO. + */ + if (cleaned_pages || !cannot_free_pages) sync = 0; + /* Else, do synchronous IO (if we are allowed to). */ + else if (sync) + sync = 1; /* We only do a few "out of order" flushes. */ maxlaunder = MAX_LAUNDER; - /* Kflushd takes care of the rest. */ + /* Let bdflush take care of the rest. */ wakeup_bdflush(0); goto dirty_page_rescan; } + /* + * If we failed to free pages (because all pages are dirty) + * we remember this for the next time. This will prevent us + * from wasting too much CPU here. + */ + cannot_free_pages = !cleaned_pages; + /* Return the number of pages moved to the inactive_clean list. */ return cleaned_pages; } @@ -655,24 +697,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 +820,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,13 +873,13 @@ 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; @@ -872,7 +902,7 @@ * list, so this is a relatively cheap operation. */ if (free_shortage()) { - ret += page_launder(gfp_mask, user); + ret += page_launder(gfp_mask, 1); shrink_dcache_memory(DEF_PRIORITY, gfp_mask); shrink_icache_memory(DEF_PRIORITY, gfp_mask); } 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/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/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/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/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/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/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/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/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/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/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/kernel-doc linux/scripts/kernel-doc --- v2.4.5/linux/scripts/kernel-doc Wed Apr 25 16:31:16 2001 +++ linux/scripts/kernel-doc Wed Jun 20 20:56:24 2001 @@ -22,6 +22,10 @@ # - 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 +101,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 +204,7 @@ my @parameterlist = (); my %sections = (); my @sectionlist = (); +my %source_map = (); my $contents = ""; my $section_default = "Description"; # default section @@ -776,6 +783,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 +792,7 @@ } } else { print STDERR "Error($.): cannot understand prototype: '$prototype'\n"; + ++$errors; return; } @@ -837,6 +846,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 +872,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 +915,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 +966,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) {