diff -u --recursive --new-file v2.3.99-pre7/linux/Documentation/Changes linux/Documentation/Changes --- v2.3.99-pre7/linux/Documentation/Changes Thu May 11 15:30:05 2000 +++ linux/Documentation/Changes Fri May 12 11:45:26 2000 @@ -245,8 +245,7 @@ features like IPv6. The IP firewalling and NAT code has been replaced again. The -actual modules (including ipfwadm and ipchains backwards-compatibility -modules) are currently distributed separately: see +userspace tool `iptables' is distributed at: http://antarctica.penguincomputing.com/~netfilter/ http://www.samba.org/netfilter/ http://netfilter.kernelnotes.org @@ -737,12 +736,13 @@ The 2.4.0b1 release: ftp://linuxcare.com.au/pub/ppp/ppp-2.4.0b1.tar.gz -IP Chains +iptables ========= -The 1.3.8 release: -ftp://ftp.rustcorp.com/ipchains/ipchains-1.3.8.tar.gz -ftp://ftp.rustcorp.com/ipchains/ipchains-1.3.8.tar.bz2 +The 1.1.0 release: +http://antarctica.penguincomputing.com/~netfilter/iptables-1.1.0.tar.bz2 +http://www.samba.org/netfilter/iptables-1.1.0.tar.bz2 +http://netfilter.kernelnotes.org/iptables-1.1.0.tar.bz2 IP Masq Adm =========== diff -u --recursive --new-file v2.3.99-pre7/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.3.99-pre7/linux/Documentation/Configure.help Thu May 11 15:30:05 2000 +++ linux/Documentation/Configure.help Fri May 12 11:43:26 2000 @@ -1477,7 +1477,7 @@ If unsure, say Y. RAID-0 (striping) mode -CONFIG_MD_STRIPED +CONFIG_MD_RAID0 If you say Y here, then your multiple devices driver will be able to use the so-called raid0 mode, i.e. it will combine the hard disk partitions into one logical device in such a fashion as to fill them @@ -1496,8 +1496,17 @@ If unsure, say Y. +DANGEROUS! RAID-1/RAID-5 code +CONFIG_RAID15_DANGEROUS + This new RAID1/RAID5 code has been freshly merged, and has not seen + enough testing yet. While there are no known bugs in it, it might + destroy your filesystems, eat your data and start World War III. + You have been warned. + + If unsure, say N. + RAID-1 (mirroring) mode -CONFIG_MD_MIRRORING +CONFIG_MD_RAID1 A RAID-1 set consists of several disk drives which are exact copies of each other. In the event of a mirror failure, the RAID driver will continue to use the operational mirrors in the set, providing @@ -9160,7 +9169,6 @@ Read Documentation/networking/skfp.txt for information about the driver. - WARNING: this driver does currently not support 64 bit systems! Questions concerning this driver can be addressed to: linux@syskonnect.de @@ -15220,6 +15228,17 @@ If you have any questions or comments about the Compaq Personal Server, send e-mail to skiff@crl.dec.com +Include support for the LinkUp Systems L7200 SDB +CONFIG_ARCH_L7200 + Say Y here if you intend to run this kernel on a LinkUp Systems + L7200 Software Development Board which uses an ARM720T processor. + Information on this board can be obtained at: + + http://www.linkupsys.com/ + + If you have any questions or comments about the Linux kernel port + to this board, send e-mail to sjhill@cotw.com + Math emulation CONFIG_NWFPE Say Y to include the NWFPE floating point emulator in the kernel. @@ -15331,6 +15350,18 @@ CONFIG_SERIAL_21285_CONSOLE If you have enabled the serial port on the 21285 footbridge you can make it the console by answering Y to this option. + +L7200 serial port support +CONFIG_SERIAL_L7200 + If you have a LinkUp Systems L7200 board you can enable its two + onboard serial ports by enabling this option. The device numbers + are major ID 4 with minor 64 and 65 respectively. + +Console on L7200 serial port +CONFIG_SERIAL_L7200_CONSOLE + If you have enabled the serial ports on the L7200 development board + you can make the first serial port the console by answering Y to + this option. Footbridge Mode CONFIG_HOST_FOOTBRIDGE diff -u --recursive --new-file v2.3.99-pre7/linux/Documentation/arm/SA1100/Assabet linux/Documentation/arm/SA1100/Assabet --- v2.3.99-pre7/linux/Documentation/arm/SA1100/Assabet Wed Dec 31 16:00:00 1969 +++ linux/Documentation/arm/SA1100/Assabet Fri May 12 11:21:20 2000 @@ -0,0 +1,46 @@ +The Intel Assabet (SA-1110 evaluation) board +============================================ + +Please see: +http://developer.intel.com/design/strong/quicklist/eval-plat/sa-1110.htm +http://developer.intel.com/design/strong/guides/278278.htm + +Also some notes from John G Dorsey : +http://www.cs.cmu.edu/~wearable/software/assabet.html + + +To build the kernel: + + make assabet_config + make config + [accept all defaults] + make dep + make zImage + +Typically, you'll need angelboot to load the kernel. +The following angelboot.opt file should be used: + +----- begin angelboot.opt ----- +base 0xc0008000 +entry 0xc0008000 +r0 0x00000000 +r1 0x00000019 +device /dev/ttyS1 +options "9600 8N1" +baud 115200 +otherfile ramdisk_img.gz +otherbase 0xc0800000 +exec minicom +----- end angelboot.opt ----- + +Then load the kernel and ramdisk with: + + angelboot -f angelboot.opt zImage + +Here it is assumed that your Assabet is connected to ttyS1 and that +minicom is preconfigured with /dev/ttyS1, 9600 baud, 8N1, no flow control +by default. + +This is work in progress... + +Please send any patches to nico@cam.org. diff -u --recursive --new-file v2.3.99-pre7/linux/Documentation/arm/SA1100/Brutus linux/Documentation/arm/SA1100/Brutus --- v2.3.99-pre7/linux/Documentation/arm/SA1100/Brutus Tue Apr 11 15:09:11 2000 +++ linux/Documentation/arm/SA1100/Brutus Fri May 12 11:21:20 2000 @@ -13,11 +13,37 @@ The resulting kernel will end up in linux/arch/arm/boot/zImage. This file must be loaded at 0xc0008000 in Brutus's memory and execution started at -0xc0008000 as well. +0xc0008000 as well with the value of registers r0 = 0 and r1 = 16 upon +entry. But prior to execute the kernel, a ramdisk image must also be loaded in memory. Use memory address 0xd8000000 for this. Note that the file containing the (compressed) ramdisk image must not exceed 4 MB. + +Typically, you'll need angelboot to load the kernel. +The following angelboot.opt file should be used: + +----- begin angelboot.opt ----- +base 0xc0008000 +entry 0xc0008000 +r0 0x00000000 +r1 0x00000010 +device /dev/ttyS0 +options "9600 8N1" +baud 115200 +otherfile ramdisk_img.gz +otherbase 0xd8000000 +----- end angelboot.opt ----- + +Then load the kernel and ramdisk with: + + angelboot -f angelboot.opt zImage + +The first Brutus serial port (assumed to be linked to /dev/ttyS0 on your +host PC) is used by angel to load the kernel and ramdisk image. The serial +console is provided through the second Brutus serial port. To access it, +you may use minicom configured with /dev/ttyS1, 9600 baud, 8N1, no flow +control. Currently supported: - RS232 serial ports diff -u --recursive --new-file v2.3.99-pre7/linux/Documentation/arm/SA1100/LART linux/Documentation/arm/SA1100/LART --- v2.3.99-pre7/linux/Documentation/arm/SA1100/LART Fri Oct 22 13:21:43 1999 +++ linux/Documentation/arm/SA1100/LART Fri May 12 11:21:20 2000 @@ -10,8 +10,6 @@ is under development, with plenty of others in different stages of planning. -The designs for this board are to be released under a GPL-like license; -we're working on the details. +The designs for this board have been released under a GPL-like license; -Contact: J.D. Bakker ; -pictures at http://www-ict.its.tudelft.nl/~erik/open-source/LART/ +For lot more info, see the LART page at http://www.lart.tudelft.nl. diff -u --recursive --new-file v2.3.99-pre7/linux/Documentation/arm/SA1100/ThinClient linux/Documentation/arm/SA1100/ThinClient --- v2.3.99-pre7/linux/Documentation/arm/SA1100/ThinClient Tue Apr 11 15:09:11 2000 +++ linux/Documentation/arm/SA1100/ThinClient Fri May 12 11:21:20 2000 @@ -14,15 +14,50 @@ 'make thinclient_config' before any 'make config'. This will set up defaults for ThinClient support. +The kernel zImage is linked to be loaded and executed at 0xc0200000. +Also the following registers should have the specified values upon entry: + + r0 = 0 + r1 = 24 (this is the ThinClient architecture number) + +Here is a tipical angel.opt option file if the kernel is loaded through +the Angel Debug Monitor: + +----- begin angelboot.opt ----- +base 0xc0200000 +entry 0xc0200000 +r0 0x00000000 +r1 0x00000018 +device /dev/ttyS1 +options "9600 8N1" +baud 115200 +#otherfile ramdisk.gz +#otherbase 0xc0800000 +exec minicom +----- end angelboot.opt ----- + +Then the kernel (and ramdisk if otherfile/otherbase lines above are +uncommented) would be loaded with: + + angelboot -f angelboot.opt zImage + +Here it is assumed that the ThinClient is connected to ttyS1 on your PC +and that minicom is preconfigured with /dev/ttyS1, 9600 baud, 8N1, no flow +control by default. + +If any other bootloader is used, ensure it accomplish the same, especially +for r0/r1 register values before jumping into the kernel. + + Supported peripherals: - SA1100 LCD frame buffer (only 8bpp yet) - on-board SMC 92C94 ethernet NIC - SA1100 serial port +- flash memory access - possibly UCB1200 audio (not tested yet) To do: - touchscreen driver -- flash memory access - 16bpp frame buffer support - extra (external) serial port driver - pcmcia diff -u --recursive --new-file v2.3.99-pre7/linux/Documentation/networking/skfp.txt linux/Documentation/networking/skfp.txt --- v2.3.99-pre7/linux/Documentation/networking/skfp.txt Sun Feb 20 21:12:38 2000 +++ linux/Documentation/networking/skfp.txt Fri May 12 11:43:26 2000 @@ -1,9 +1,9 @@ (C)Copyright 1998-2000 SysKonnect, =========================================================================== -skfp.txt created 17-Feb-2000 +skfp.txt created 11-May-2000 -Readme File for skfp.o v2.05 +Readme File for skfp.o v2.06 This file contains @@ -142,6 +142,12 @@ (6) HISTORY =========== + +v2.06 (20000511) (In-Kernel version) + New features: + - 64 bit support + - new pci dma interface + - in kernel 2.3.99 v2.05 (20000217) (In-Kernel version) New features: diff -u --recursive --new-file v2.3.99-pre7/linux/Documentation/s390/DASD linux/Documentation/s390/DASD --- v2.3.99-pre7/linux/Documentation/s390/DASD Wed Dec 31 16:00:00 1969 +++ linux/Documentation/s390/DASD Fri May 12 11:41:44 2000 @@ -0,0 +1,73 @@ +DASD device driver + +S/390's disk devices (DASDs) are managed by Linux via the DASD device +driver. It is valid for all types of DASDs and represents them to +Linux as block devices, namely "dd". Currently the DASD driver uses a +single major number (254) and 4 minor numbers per volume (1 for the +physical volume and 3 for partitions). With respect to partitions see +below. Thus you may have up to 64 DASD devices in your system. + +The kernel parameter 'dasd=from-to,...' may be issued arbitrary times +in the kernel's parameter line or not at all. The 'from' and 'to' +parameters are to be given in hexadecimal notation without a leading +0x. +If you supply kernel parameters the different instances are processed +in order of appearance and a minor number is reserved for any device +covered by the supplied range up to 64 volumes. Additional DASDs are +ignored. If you do not supply the 'dasd=' kernel parameter at all, the +DASD driver registers all supported DASDs of your system to a minor +number in ascending order of the subchannel number. + +The driver currently supports ECKD-devices and there are stubs for +support of the FBA and CKD architectures. For the FBA architecture +only some smart data structures are missing to make the support +complete. +We performed our testing on 3380 and 3390 type disksof different +sizes, under VM and on the bare hardware (LPAR), using internal disks +of the multiprise as well as a RAMAC virtual array. Disks exported by +an Enterprise Storage Server (Seascape) should work fine as well. + +We currently implement one partition per volume, which is the whole +volume, skipping the first blocks up to the volume label. These are +reserved for IPL records and IBM's volume label to assure +accessability of the DASD from other OSs. In a later stage we will +provide support of partitions, maybe VTOC oriented or using a kind of +partition table in the label record. + +USAGE + +-Low-level format (?CKD only) +For using an ECKD-DASD as a Linux harddisk you have to low-level +format the tracks by issueing the BLKDASDFORMAT-ioctl on that +device. This will erase any data on that volume including IBM volume +labels, VTOCs etc. The ioctl may take a 'struct format_data *' or +'NULL' as an argument. +typedef struct { + int start_unit; + int stop_unit; + int blksize; +} format_data_t; +When a NULL argument is passed to the BLKDASDFORMAT ioctl the whole +disk is formatted to a blocksize of 1024 bytes. Otherwise start_unit +and stop_unit are the first and last track to be formatted. If +stop_unit is -1 it implies that the DASD is formatted from start_unit +up to the last track. blksize can be any power of two between 512 and +4096. We recommend no blksize lower than 1024 because the ext2fs uses +1kB blocks anyway and you gain approx. 50% of capacity increasing your +blksize from 512 byte to 1kB. + +-Make a filesystem +Then you can mk??fs the filesystem of your choice on that volume or +partition. For reasons of sanity you should build your filesystem on +the partition /dev/dd?1 instead of the whole volume. You only lose 3kB +but may be sure that you can reuse your data after introduction of a +real partition table. + +BUGS: +- Performance sometimes is rather low because we don't fully exploit clustering + +TODO-List: +- Add IBM'S Disk layout to genhd +- Enhance driver to use more than one major number +- Enable usage as a module +- Support Cache fast write and DASD fast write (ECKD) diff -u --recursive --new-file v2.3.99-pre7/linux/Documentation/s390/cds.txt linux/Documentation/s390/cds.txt --- v2.3.99-pre7/linux/Documentation/s390/cds.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/s390/cds.txt Fri May 12 11:41:44 2000 @@ -0,0 +1,912 @@ +Linux/390 + +Common Device Support (CDS) +Device Driver I/O Support Routines + +Author : Ingo Adlung + +Copyright, IBM Corp. 1999 + +Introduction + +This document describes the common device support routines for Linux/390. +Different than other hardware architectures, ESA/390 hasdefined a unified +I/O access method. This gives relief to the device drivers as they don't +have to deal with different bus types, polling versus interrupt +processing, shared versus non-shared interrupt processing, DMA versus port +I/O (PIO), and other hardware features more. However, this implies that +either every single device driver needs to implement the hardware I/O +attachment functionality itself, or the operating system provides for a +unified method to access the hardware, providing all the functionality that +every single device driver would have to provide itself. + +The document does not intend to explain the ESA/390 hardware architecture in +every detail.This information can be obtained from the ESA/390 Principles of +Operation manual (IBM Form. No. SA22-7201). + +In order to build common device support for ESA/390 I/O interfaces, a +functional layer was introduced that provides generic I/O access methods to +the hardware. The following figure shows the usage of the common device support +of Linux/390 using a TbCP/IP driven device access an example. Similar figures +could be drawn for other access methods, e.g. file system access to disk +devices. + +The common device support layer shown above comprises the I/O support routines +defined below. Some of them implement common Linux device driver interfaces, +while some of them are ESA/390 platform specific. + +get_dev_info_by_irq() / get_dev_info_by_devno() + allow a device driver to determine the devices attached (visible) to the + system and their current status. + +get_irq_by_devno() / get_devno_by_irq() + get irq (subchannel) from device number and vice versa. + +read_dev_chars() + read device characteristics + +request_irq() + obtain ownership for a specific device. + +free_irq() + release ownership for a specific device. + +disable_irq() + disable a device from presenting interrupts. + +enable_irq() + enable a device, allowing for I/O interrupts. + +do_IO() + initiate an I/O request. + +halt_IO() + terminate the current I/O request processed on the device. + +do_IRQ() + generic interrupt routine. This function is called by the interrupt entry + routine whenever an I/O interrupt is presented to the system. The do_IRQ() + routine determines the interrupt status and calls the device specific + interrupt handler according to the rules (flags) defined during I/O request + initiation with do_IO(). + +The next chapters describe the functions, other than do_IRQ() in more details. +The do_IRQ() interface is not described, as it is called from the Linux/390 +first level interrupt handler only and does not comprise a device driver +callable interface. Instead, the functional description of do_IO() also +describes the input to the device specific interrupt handler. + + +Common Device Support (CDS) for Linux/390 Device Drivers + +General Information + +The following chapters describe the I/O related interface routines the +Linux/390 common device support (CDS) provides to allow for device specific +driver implementations on the IBM ESA/390 hardware platform. Those interfaces +intend to provide the functionality required by every device driver +implementaion to allow to drive a specific hardware device on the ESA/390 +platform. Some of the interface routines are specific to Linux/390 and some +of them can be found on other Linux platforms implementations too. +Miscellaneous function prototypes, data declarations, and macro definitions +can be found in the architecture specific C header file +linux/arch/s390/kernel/irq.h. + +Overview of CDS interface concepts + +Different to other hardware platforms, the ESA/390 architecture doesn't define +interrupt lines managed by a specific interrupt controller and bus systems +that may or may not allow for shared interrupts, DMA processing, etc.. Instead, +the ESA/390 architecture has implemented a so called channel subsystem, that +provides a unified view of the devices physically attached to the systems. +Though the ESA/390 hardware platform knows about a huge variety of different +peripheral attachments like disk devices (aka. DASDs), tapes, communication +controllers, etc. they can all by accessed by a well defined access method and +they are presenting I/O completion a unified way : I/O interruptions. Every +single device is uniquely identified to the system by a so called subchannel, +where the ESA/390 architecture allows for 64k devices be attached. + +Linux, however was first built on the Intel PC architecture, with its two +cascaded 8259 programmable interrupt controllers (PICs), that allow for a +maximum of 15 different interrupt lines. All devices attached to such a system +share those 15 interrupt levels. Devices attached to the ISA bus system must +not share interrupt levels (aka. IRQs), as the ISA bus bases on edge triggered +interrupts. MCA, EISA, PCI and other bus systems base on level triggered +interrupts, and therewith allow for shared IRQs. However, if multiple devices +present their hardware status by the same (shared) IRQ, the operating system +has to call every single device driver registered on this IRQ in order to +determine the device driver owning the device that raised the interrupt. + +In order to not introduce a new I/O concept to the common Linux code, +Linux/390 preserves the IRQ concept and semantically maps the ESA/390 +subchannels to Linux as IRQs. This allows Linux/390 to support up to 64k +different IRQs, uniquely representig a single device each. + +During its startup the Linux/390 system checks for peripheral devices. Each +of those devices is uniquely defined by a so called subchannel by the ESA/390 +channel subsystem. While the subchannel numbers are system generated, each +subchannel also takes a user defined attribute, the so called device number. +Both, subchannel number and device number can not exceed 65535. The +init_IRQ() routine gathers the information about control unit type and device +types that imply specific I/O commands (channel command words - CCWs) in +order to operate the device. Device drivers can retrieve this set of hardware +information during their initialization step to recognize the devices they +support using get_dev_info_by_irq() or get_dev_info_by_devno() respectively. +This methods implies that Linux/390 doesn't require to probe for free (not +armed) interrupt request lines (IRQs) to drive its devices with. Where +applicable, the device drivers can use the read_dev_chars() to retrieve device +characteristics. This can be done without having to request device ownership +previously. + +When a device driver has recognized a device it wants to claim ownership for, +it calls request_irq() with the device's subchannel id serving as pseudo irq +line. One of the required parameters it has to specify is dev_id, defining a +device status block, the CDS layer will use to notify the device driver's +interrupt handler about interrupt information observed. It depends on the +device driver to properly handle those interrupts. + +In order to allow for easy I/O initiation the CDS layer provides a do_IO() +interface that takes a device specific channel program (one or more CCWs) as +input sets up the required architecture specific control blocks and initiates +an I/O request on behalf of the device driver. The do_IO() routine allows for +different I/O methods, synchronous and asynchronous, and allows to specify +whether it expects the CDS layer to notify the device driver for every +interrupt it observes, or with final status only. It also provides a scheme +to allow for overlapped I/O processing. See do_IO() for more details. A device +driver must never issue ESA/390 I/O commands itself, but must use the +Linux/390 CDS interfaces instead. + +For long running I/O request to be canceled, the CDS layer provides the +halt_IO() function. Some devices require to initially issue a HALT SUBCHANNEL +(HSCH) command without having pending I/O requests. This function is also +covered by halt_IO(). + +When done with a device, the device driver calls free_irq() to release its +ownership for the device. During free_irq() processing the CDS layer also +disables the device from presenting further interrupts - the device driver +doesn't need to assure it. The device will be reenabled for interrupts with +the next call to request_irq(). + + + +get_dev_info_by_irq() / get_dev_info_by_devno() - Retrieve Device Information + +During system startup - init_IRQ() processing - the generic I/O device support +checks for the devices available. For all devices found it collects the +SenseID information. For those devices supporting the command it also obtains +extended SenseID information. + +int get_dev_info_by_irq( int irq, + dev_info_t *devinfo); + +int get_dev_info_by_devno( unsigned int irq, + dev_info_t *devinfo); + +irq - defines the subchannel, status information is to be + returned for. +devno - device number. +devinfo - pointer to a user buffer of type dev_info_t that should + be filled with device specific information. + +typedef struct { + unsigned int devno; /* device number */ + unsigned int status; /* device status */ + senseid_t sid_data; /* senseID data */ +} dev_info_t; + +devno - device number as configured in the IOCDS. +status - device status +sid_data - data obtained by a SenseID call + +Possible status values are : + +DEVSTAT_NOT_OPER - device was found not-operational. In this case + the caller should disregard the sid_data + buffer content. + +// +// SenseID response buffer layout +// +typedef struct { + /* common part */ + unsigned char reserved; /* always 0x'FF' */ + unsigned short cu_type; /* control unit type */ + unsigned char cu_model; /* control unit model */ + unsigned short dev_type; /* device type */ + unsigned char dev_model; /* device model */ + unsigned char unused; /* padding byte */ + /* extended part */ + ciw_t ciw[62]; /* variable # of CIWs */ +} senseid_t; + +The ESA/390 I/O architecture defines certain device specific I/O functions. +The device returns the device specific command code together with the SenseID +data in so called Command Information Words (CIW) : + +typedef struct _ciw { + unsigned int et : 2; // entry type + unsigned int reserved : 2; // reserved + unsigned int ct : 4; // command type + unsigned int cmd : 8; // command + unsigned int count : 16; // count +} ciw_t; + +Possible CIW entry types are : + +#define CIW_TYPE_RDC 0x0; // read configuration data +#define CIW_TYPE_SII 0x1; // set interface identifier +#define CIW_TYPE_RNI 0x2; // read node identifier + +The device driver may use these commands as appropriate. + +The get_dev_info_by_irq() / get_dev_info_by_devno() functions return: + + 0 - sucessful completion +-ENODEV - irq or devno don't specify a known subchannel or device + number. +-EINVAL - invalid devinfo value. + +Usage Notes : + +In order to scan for known devices a device driver should scan all irqs by +calling get_dev_info() until it returns -ENODEV as there aren't any more +available devices. + +If a device driver wants to request ownership for a specific device it must +call request_irq() prior to be able to issue any I/O request for it, including +above mentioned device dependent commands. + +Please see the "ESA/390 Common I/O-Commandss and Self Description" manual, +with IBM form number SA22-7204 for more details on how to read the Sense-ID +output, CIWs and device independent commands. + + + +get_irq_by_devno() / get_devno_by_irq() - Convert device identifiers + +While some device drivers act on the irq (subchannel) only, others take user +defined device configurations on device number base, according to the device +numbers configured in the IOCDS. The following routines serve the purpose to +convert irq values into device numbers and vice versa. + +int get_irq_by_devno( unsigned int devno ); + +unsigned int get_devno_by_irq( int irq ); + +The functions return : + +the requested irq/devno values +-1 if the requested conversion can't be accomplished. + +This could either be caused by irq/devno be outside the valid range +( value > 0xffff or value < 0 ) or not identifying a known device. + + +read_dev_chars() - Read Device Characteristics + +This routine returns the characteristics for the device specified. + +The function is meant to be called without an irq handler be in place. +However, the irq for the requested device must not be locked or this will +cause a deadlock situation ! Further, the driver must assure that nobody +else has claimed ownership for the requested irq yet or the owning device +driver's internal accounting may be affected. + +In case of a registered interrupt handler, the interrupt handler must be +able to properly react on interrupts related to the read_dev_chars() I/O +commands. While the request is procesed synchronously, the device interrupt +handler is called for final ending status. In case of error situations the +interrupt handler may recover appropriately. The device irq handler can +recognize the corresponding interrupts by the interruption parameter be +0x00524443. If using the function with an existing device interrupt handler +in place, the irq must be locked prior to call read_dev_chars(). + +The function may be called enabled or disabled. + +int read_dev_chars( int irq, void **buffer, int length ); + +irq - specifies the subchannel the device characteristic + retrieval is requested for +buffer - pointer to a buffer pointer. The buffer pointer itself + may be NULL to have the function allocate a buffer or + must contain a valid buffer area. +length - length of the buffer provided or to be allocated. + +The read_dev_chars() function returns : + + 0 - successful completion +-ENODEV - irq doesn't specify a valid subchannel number +-EINVAL - an invalid parameter was detected +-EBUSY - an irrecoverable I/O error occured or the device is not + operational. + +Usage Notes : + +The function can be used in two ways : + +If the caller doesn't provide a data buffer, read_dev_chars() allocates a +data buffer and provides the device characteristics together. It's the +caller's responsability to release the kernel memory if not longer needed. +This behaviour is triggered by specifying a NULL buffer area (*buffer == NULL). + +Alternatively, if the user specifies a buffer area himself, nothing is +allocated. + +In either case the caller must provide the data area length - for the buffer +he specifies, or the buffer he wants to be allocated. + + +request_irq() - Request Device Ownership + +As previously discussed a device driver will scan for the devices its supports +by calling get_dev_info(). Once it has found a device it will call +request_irq() to request ownership for it. This call causes the subchannel to +be enabled for interrupts if it was found operational. + +int request_irq( unsigned int irq, + int (*handler)( int, + void *, + struct pt_regs *), + unsigned long irqflags, + const char *devname, + void *dev_id); + +irq : specifies the subchannel the ownership is requested for +handler : specifies the device driver's interrupt handler to be + called for interrupt processing +irqflags : IRQ flags, must be 0 (zero) or SA_SAMPLE_RANDOM +devname : device name +dev_id : required pointer to a device specific buffer of type + devstat_t + +typedef struct { + unsigned int devno; /* device number from irb */ + unsigned int intparm; /* interrupt parameter */ + unsigned char cstat; /* channel status - accumulated */ + unsigned char dstat; /* device status - accumulated */ + unsigned char lpum; /* last path used mask from irb */ + unsigned char unused; /* not used - reserved */ + unsigned int flag; /* flag : see below */ + unsigned long cpa; /* CCW addr from irb at prim. status */ + unsigned int rescnt; /* count from irb at primary status */ + unsigned int scnt; /* sense count, if available */ + union { + irb_t irb; /* interruption response block */ + sense_t sense; /* sense information */ + } ii; /* interrupt information */ + } devstat_t; + +During request_irq() processing, the devstat_t layout does not matter as it +won't be used during request_irq() processing. See do_IO() for a functional +description of its usage. + +The request_irq() function returns : + + 0 - successful completion +-EINVAL - an invalid parameter was detected +-EBUSY - device (subchannel) already owned +-ENODEV - the device is not-operational +-ENOMEM - not enough kernel memory to process request + +Usage Notes : + +While Linux for Intel defines dev_id as a unique identifier for shared +interrupt lines it has a totally different purpose on Linux/390. Here it +serves as a shared interrupt status area between the generic device support +layer, and the device specific driver. The value passed to request_irq() +must therefore point to a valid devstat_t type buffer area the device driver +must preserve for later usage. I.e. it must not be released prior to a call +to free_irq() + +The only value parameter irqflags supports is SA_SAMPLE_RANDOM if appropriate. +The Linux/390 kernel does neither know about "fast" interrupt handlers, nor +does it allow for interrupt sharing. Remember, the term interrupt level (irq), +device, and subchannel are used interchangeably in Linux/390. + +If request_irq() was called in enabled state, or if multiple CPUs are present, +the device may present an interrupt to the specified handler prior to +request_irq() return to the caller already ! This includes the possibility +of unsolicited interrupts or a pending interrupt status from an earlier +solicited I/O request. The device driver must be able to handle this situation +properly or the device may become unoperational otherwise ! + +Although the interrupt handler is defined to be called with a pointer to a +struct pt_regs buffer area, this is not implemented by the Linux/390 generic +I/O device driver support layer. The device driver's interrupt handler must +therefore not rely on this parameter on function entry. + + +free_irq() - Release Device Ownership + +A device driver may call free_irq() to release ownership of a previously +aquired device. + +void free_irq( unsigned int irq, + void *dev_id); + +irq : specifies the subchannel the ownership is requested for +dev_id : required pointer to a device specific buffer of type + devstat_t. This must be the same as the one specified + during a previous call to request_irq(). + +Usage Notes : + +Unfortunately the free_irq() is defined not to return error codes. I.e. if +called with wrong parameters a device may still be operational although there +is no device driver available to handle its interrupts. Further, during +free_irq() processing we may possibly find pending interrupt conditions. As +those need to be processed, we have to delay free_irq() returning until a +clean device status is found by synchronously handling them. + +The call to free_irq() will also cause the device (subchannel) be disabled for +interrupts. The device driver must not release any data areas required for +interrupt processing prior to free_irq() return to the caller as interrupts +can occur prior to free_irq() returning. This is also true when called in +disabled state if either multiple CPUs are presents or a pending interrupt +status was found during free_irq() processing. + + +disable_irq() - Disable Interrupts for a given Device + +This function may be called at any time to disable interrupt processing for +the specified irq. However, as Linux/390 maps irqs to the device (subchannel) +one-to-one, this may require more extensive I/O processing than anticipated, +especially if an interrupt status is found pending on the subchannel that +requires synchronous error processing. + +int disable_irq( unsigned int irq ); + +irq : specifies the subchannel to be disabled + +The disable-irq() routine may return : + + 0 - successful completion +-EBUSY - device (subchannel) is currently processing an I/O + request +-ENODEV - the device is not-operational or irq doesn't specify a + valid subchannel + +Usage Notes : + +Unlike the Intel based hardware architecture the ESA/390 architecture does +not have a programmable interrupt controller (PIC) where a specific interrupt +line can be disabled. Instead the subchannel logically representing the device +in the channel subsystem must be disabled for interrupts. However, if there +are still inetrrupt conditions pending they must be processed first in order +to allow for proper processing after reenabling the device at a later time. +This may lead to delayed disable processing. + +As described above the disable processing may require extensive processing. +Therefore disabling and re-enabling the device using disable_irq() / +enable_irq() should be avoided and is not suitable for high frequency +operations. + +Linux for Intel defines this function + +void disable_irq( int irq); + +This is suitable for the Intel PC architecture as this only causes to mask +the requested irq line in the PIC which is not applicable for the ESA/390 +architecture. Therefore we allow for returning error codes. + + +enable_irq() - Enable Interrupts for a given Device + +This function is used to enable a previously disabled device (subchannel). +See disable_irq() for more details. + +int enable_irq( unsigned int irq ); + +irq : specifies the subchannel to be enabled + +The enable-irq() routine may return : + + 0 - successful completion +-EBUSY - device (subchannel) is currently processing an I/O + request. This implies the device is already in enabled + state +-ENODEV - the device is not-operational or irq doesn't specify a + valid subchannel + + + +do_IO() - Initiate I/O Request + +The do_IO() routines is the I/O request front-end processor. All device driver +I/O requests must be issued using this routine. A device driver must not issue +ESA/390 I/O commands itself. Instead the do_IO() routine provides all +interfaces required to drive arbitrary devices. + +This description also covers the status information passed to the device +driver's interrupt handler as this is related to the rules (flags) defined +with the associated I/O request when calling do_IO(). + +int do_IO( int irq, + ccw1_t *cpa, + unsigned long intparm, + unsigned int lpm, + unsigned long flag); + +irq : irq (subchannel) the I/O request is destined for +cpa : logical start address of channel program +intparm : user specific interrupt information; will be presented + back to the device driver's interrupt handler. Allows a + device driver to associate the interrupt with a + particular I/O request. +lpm : defines the channel path to be used for a specific I/O + request. Valid with flag value DOIO_VALID_LPM only. +flag : defines the action to e parformed for I/O processing + +Possible flag values are : + +DOIO_EARLY_NOTIFICATION - allow for early interupt notification +DOIO_VALID_LPM - LPM input parameter is valid (see usage + notes below for details) +DOIO_WAIT_FOR_INTERRUPT - wait synchronously for final status +DOIO_REPORT_ALL - report all interrupt conditions + +The cpa parameter points to the first format 1 CCW of a channel program : + +typedef struct { + char cmd_code; /* command code */ + char flags; /* flags, like IDA adressing, etc. */ + unsigned short count; /* byte count */ + void *cda; /* data address */ +} ccw1_t __attribute__ ((aligned(8))); + +with the following CCW flags values defined : + +CCW_FLAG_DC - data chaining +CCW_FLAG_CC - command chaining +CCW_FLAG_SLI - suppress incorrct length +CCW_FLAG_SKIP - skip +CCW_FLAG_PCI - PCI +CCW_FLAG_IDA - indirect addressing +CCW_FLAG_SUSPEND - suspend + + + +The do_IO() function returns : + + 0 - successful completion or request successfuly initiated +-EBUSY - the do_io() function was caled out of sequence. The + device is currently processing a previous I/O request +-ENODEV - irq doesn't specify a valid subchannel, the device is + not operational (check dev_id.flags) or the irq is not + owned. +-EINVAL - both, DOIO_EARLY_NOTIFICATION and DOIO_REORT_ALL flags + have been specified. The usage of those flags is mutual + exclusive. + +When the I/O request completes, the CDS first level interrupt handler will +setup the dev_id buffer of type devstat_t defined during request_irq() +processing. See request_irq() for the devstat_t data layout. The +dev_id->intparm field in the device status area will contain the value the +device driver has associated with a particular I/O request. If a pending +device status was recognized dev_id->intparm will be set to 0 (zero). This +may happen during I/O initiation or delayed by an alert status notification. +In any case this status is not related to the current (last) I/O request. In +case of a delayed status notification no special interrupt will be presented +to indicate I/O completion as the I/O request was never started, even though +do_IO() returned with successful completion. + +Possible dev_id->flag values are : + +DEVSTAT_FLAG_SENSE_AVAIL - sense data is available +DEVSTAT_NOT_OPER - device is not-operational +DEVSTAT_START_FUNCTION - interrupt is presented as result of a + call to do_IO() +DEVSTAT_HALT_FUNCTION - interrupt is presented as result of a + call to halt_IO() +DEVSTAT_STATUS_PENDING - a pending status was found. The I/O + resquest (if any) was not initiated. + This status might have been presented + delayed, after do_IO() or halt_IO() have + successfully be started previously. +DEVSTAT_FINAL_STATUS - This is a final interrupt status for the + I/O requst identified by intparm. + +If device status DEVSTAT_FLAG_SENSE_AVAIL is indicated in field dev_id->flag, +field dev_id->scnt describes the numer of device specific sense bytes +available in the sense area dev_id->ii.sense. No device sensing by the device +driver itself is required. + +typedef struct { + unsigned char res[32]; /* reserved */ + unsigned char data[32]; /* sense data */ +} sense_t; + +The device interrupt handler can use the following definitions to investigate +the primary unit check source coded in sense byte 0 : + +SNS0_CMD_REJECT 0x80 +SNS0_INTERVENTION_REQ 0x40 +SNS0_BUS_OUT_CHECK 0x20 +SNS0_EQUIPMENT_CHECK 0x10 +SNS0_DATA_CHECK 0x08 +SNS0_OVERRUN 0x04 + +Depending on the device status, multiple of those values may be set together. +Please refer to the device specific documentation for details. + +The devi_id->cstat field provides the (accumulated) subchannel status : + +SCHN_STAT_PCI - program controlled interrupt +SCHN_STAT_INCORR_LEN - incorrect length +SCHN_STAT_PROG_CHECK - program check +SCHN_STAT_PROT_CHECK - protection check +SCHN_STAT_CHN_DATA_CHK - channel data check +SCHN_STAT_CHN_CTRL_CHK - channel control check +SCHN_STAT_INTF_CTRL_CHK - interface control check +SCHN_STAT_CHAIN_CHECK - chaining check + +The dev_id->dstat field provides the (accumulated) device status : + +DEV_STAT_ATTENTION - attention +DEV_STAT_STAT_MOD - status modifier +DEV_STAT_CU_END - control unit end +DEV_STAT_BUSY - busy +DEV_STAT_CHN_END - channel end +DEV_STAT_DEV_END - device end +DEV_STAT_UNIT_CHECK - unit check +DEV_STAT_UNIT_EXCEP - unit exception + +Please see the ESA/390 Principles of Operation manual for details on the +individual flag meanings. + +In rare error situations the device driver may require access to the original +hardware interrupt data beyond the scope of above mentioned infromation. For +those situations the Linux/390 common device support provides the interrupt +response block (IRB) as part of the device status block in dev_id->ii.irb. + +Usage Notes : + +Prior to call do_IO() the device driver must + +assure disabled state, i.e. the I/O mask value in the PSW must be disabled. +This can be accomplished by calling __save_flags( flags). The current PSW +flags are preserved and can be restored by __restore_flags( flags) at a +later time. + +If the device driver violates this rule while running in a uni-processor +environment an interrupt might be presented prior to the do_IO() routine +returning to the device driver main path. In this case we will end in a +deadlock situation as the interrupt handler will try to obtain the irq +lock the device driver still owns (see below) ! + +the driver must assure to hold the device specific lock. This can be +accomplished by + +(i) s390irq_spin_lock( irq), or +(ii) s390irq_spin_lock_irqsave(irq, flags) + +Option (i) should be used if the calling routine is running disabled for +I/O interrupts (see above) already. Option (ii) obtains the device gate und +puts the CPU into I/O disabled state by preserving the current PSW flags. +See the descriptions of s390irq_spin_lock() or s390irq_spin_lock_irqsave() +for more details. + +The device driver is allowed to issue the next do_IO() call from within its +interrupt handler already. It is not required to schedule a bottom-half, +unless an non deterministicly long running error recovery procedure or +similar needs to be scheduled. During I/O processing the Linux/390 generic +I/O device driver support has already obtained the IRQ lock, i.e. the handler +must not try to obtain it again when calling do_IO() or we end in a deadlock +situation ! Anyway, the device driver's interrupt handler must only call +do_IO() if the handler itself can be entered recursively if do_IO() e.g. finds +a status pending and needs to all the interrupt handler itself. + +Device drivers shouldn't heavily rely on DOIO_WAIT_FOR_INTERRUPT synchronous +I/O request processing. All I/O devices, but the console device are driven +using a single shared interrupt subclass (ISC). For sync. processing the +device is temporarily mapped to a special ISC while the calling CPU waits for +I/O completion. As this special ISC is gated, all sync. requests in a SMP +environment are serialized which may cause other CPUs to spin. This service +is therewith primarily meant to be used during device driver initialization +for ease of device setup. + +The lpm input parameter might be used for multipath devices shared among +multiple systems as the Linux/390 CDS isn't grouping channel paths. Therefore +its use might be required if multiple access paths to a device are available +and the device was reserved by means of a reserve device command (for devices +supporting this technique). When issuing this command the device driver needs +needs to extract the dev_id->lpum value and restrict all subsequent channel +programs to this channel path until the device is released by a device release +command. Otherwise a deadlock may occur. + +If a device driver relies on an I/O request to be completed prior to start the +next it can reduce I/O processing overhead by chaining a NoOp I/O command +CCW_CMD_NOOP to the end of the submitted CCW chain. This will force Channel-End +and Device-End status to be presented together, with a single interrupt. +However, this should be used with care as it implies the channel will remain +busy, not being able to process I/O requests for other devices on the same +channel. Therefore e.g. read commands should never use this technique, as the +result will be presented by a single interrupt anyway. + +In order to minimize I/O overhead, a device driver should use the +DOIO_REPORT_ALL only if the device can report intermediate interrupt +information prior to device-end the device driver urgently relies on. In this +case all I/O interruptions are presented to the device driver until final +status is recognized. + +If a device is able to recover from asynchronosly presented I/O errors, it can +perform overlapping I/O using the DOIO_EARLY_NOTIFICATION flag. While some +devices always report channel-end and device-end together, with a single +interrupt, others present primary status (channel-end) when the channel is +ready for the next I/O request and secondary status (device-end) when the data +transmission has been completed at the device. + +Above flag allows to exploit this feature, e.g. for communication devices that +can handle lost data on the network to allow for enhanced I/O processing. + +Unless the channel subsystem at any time presents a secondary status interrupt, +exploiting this feature will cause only primary status interrups to be +presented to the device driver while overlapping I/O is performed. When a +secondary status without error (alert status) is presented, this indicates +successful completion for all overlapping do_IO() requests that have been +issued since the last secondary (final) status. + +During interrupt processing the device specific interrupt handler should avoid +basing its processing decisions on the interruption response block (IRB) that +is part of the dev_id buffer area. The IRB area represents the interruption +parameters from the last interrupt received. Unless the device driver has +specified DOIO_REPORT_ALL or is called with a pending status +(DEVSTAT_STATUS_PENDING), the IRB information may or may not show the complete +interruption status, but the last interrupt only. Therefore the device driver +should usually base its processing decisions on the values of dev_id->cstat +and dev_id->dstat that represent the accumulated subchannel and device status +information gathered since do_IO() request initiation. + + +halt_IO() - Halt I/O Request Processing + +Sometimes a device driver might need a possibility to stop the processing of +a long-running channel program or the device might require to initially issue +a halt subchannel (HSCH) I/O command. For those purposes the halt_IO() command +is provided. + +int halt_IO( int irq, /* subchannel number */ + int intparm, /* dummy intparm */ + unsigned int flag); /* operation mode */ + +irq : irq (subchannel) the halt operation is requested for +intparm : interruption parameter; value is only used if no I/O + is outstanding, otherwise the intparm associated with + the I/O request is returned +flag : 0 (zero) or DOIO_WAIT_FOR_INTERRUPT + +The halt_IO() function returns : + + 0 - successful completion or request successfuly initiated +-EBUSY - the device is currently performing a sysnchonous I/O + operation : do_IO() with flag DOIO_WAIT_FOR_INTERRUPT + or an error was encountered and the device is currently + be sensed +-ENODEV - the irq specified doesn't specify a valid subchannel, the + device is not operational (check dev_id.flags) or the irq + is not owned. + +Usage Notes : + +A device driver may write a never-ending channel program by writing a channel +program that at its end loops back to its beginning by means of a transfer in +channel (TIC) command (CCW_CMD_TIC). Usually this is performed by network +device drivers by setting the PCI CCW flag (CCW_FLAG_PCI). Once this CCW is +executed a program controlled interrupt (PCI) is generated. The device driver +can then perform an appropriate action. Prior to interrupt of an outstanding +read to a network device (with or without PCI flag) a halt_IO() is required +to end the pending operation. + +We don't allow to stop sync. I/O requests by means of a halt_IO() call. The +function will return -EBUSY instead. + + +Miscellaneous Support Routines + +This chapter describes various routines to be used in a Linux/390 device +driver programming environment. + +s390irq_spin_lock() / s390irq_spin_unlock() + +Those two macro definitions are required to obtain the device specific IRQ +lock. The lock needs to be obtained if the device driver intends to call +do_IO() or halt_IO() from anywhere but the device interrupt handler (where +the lock is already owned). Those routines must only be used if running +disabled for interrupts already. Otherwise use s390irq_spin_lock_irqsave() +and the corresponding unlock routine instead (see below). + +s390irq_spin_lock( int irq); +s390irq_spin_unlock( int irq); + + +s390irq_spin_lock_irqsave() / s390_irq_spin_unlock_irqrestore() + +Those two macro definitions are required to obtain the device specific IRQ +lock. The lock needs to be obtained if the device driver intends to call +do_IO() or halt_IO() from anywhere but the device interrupt handler (where +the lock is already owned). Those routines should only be used if running +enabled for interrupts. If running disabled already, the driver should use +s390irq_spin_lock() and the corresponding unlock routine instead (see above). + +s390irq_spin_lock_irqsave( int irq, unsigned long flags); +s390irq_spin_unlock_irqrestore( int irq, unsigned long flags); + + + + +Special Console Interface Routines + +This chapter describes the special interface routines required for system +console processing. Though they are an extension to the Linux/390 device +driver interface concept, they base on the same principles. It was necessary +to build those extensions to assure a deterministic behaviour in critical +situations e.g. printk() messages by other device drivers running disabled +for interrupts during I/O interrupt handling or in case of a panic() message +being raised. + +set_cons_dev - Set Console Device + +This routine allows to specify the system console device. This is necessary +as the console isn't driven by the same ESA/390 interrupt subclass as are +other devices, but it is assigned ist own interrupt subclass. Only one device +can act as system console. See wait_cons_dev() for details. + +int set_cons_dev( int irq); + +irq : subchannel identifying the system console device + +The set_cons_dev() function returns + + 0 - successful completion +-EIO - an unhandled interrupt condition is pending for the + specified subchannel (irq) - status pending +-ENODEV - irq doesn't specify a valid subchannel or the devive is + not operational +-EBUSY - the console device is already defined + +reset_cons_dev - Reset Console Device + +This routine allows for resetting the console device specification. See +set_cons_dev() for details. + +int reset_cons_dev( int irq); + +irq : subchannel identifying the system console device + +The reset_cons_dev() function returns + + 0 - successful completion +-EIO - an unhandled interrupt condition is pending for the + specified subchannel (irq) - status pending +-ENODEV - irq doesn't specify a valid subchannel or the devive is + not operational + +wait_cons_dev - Synchronously Wait for Console Processing + +The wait_cons_dev() routine is used by the console device driver when its +buffer pool for intermediate request queuing is exhausted and a new output +request is received. In this case the console driver uses the wait_cons_dev() +routine to synchronously wait until enough buffer space is gained to enqueue +the current request. Any pending interrupt condition for the console device +found during wait_cons_dev() processing causes its interrupt handler to be +called. + +int wait_cons_dev( int irq); + +irq : subchannel identifying the system console device + +The wait_cons_dev() function returns : + + 0 - successful completion +-EINVAL - the irq specified doesn't match the irq configured for + the console device by set_cons_dev() + +Usage Notes : + +The function should be used carefully. Especially in a SMP environment the +wait_cons_dev() processing requires that all but the special console ISC are +disabled. In a SMP system this requires the other CPUs to be signaled to +disable/enable those ISCs. + + + diff -u --recursive --new-file v2.3.99-pre7/linux/Makefile linux/Makefile --- v2.3.99-pre7/linux/Makefile Thu May 11 15:30:05 2000 +++ linux/Makefile Thu May 11 19:12:05 2000 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 3 SUBLEVEL = 99 -EXTRAVERSION = -pre7 +EXTRAVERSION = -pre8 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) diff -u --recursive --new-file v2.3.99-pre7/linux/arch/arm/Makefile linux/arch/arm/Makefile --- v2.3.99-pre7/linux/arch/arm/Makefile Tue Apr 11 15:09:11 2000 +++ linux/arch/arm/Makefile Fri May 12 11:21:20 2000 @@ -38,7 +38,6 @@ @false endif - # GCC 2.7 uses different options to later compilers; sort out which we have NEW_GCC := $(shell if $(CC) --version 2>&1 | grep '^2\.7' > /dev/null; then echo n; else echo y; fi) @@ -52,13 +51,16 @@ CFLAGS_PROC_CPU_32v4 := -march=armv4 CFLAGS_ARM6 := -mtune=arm6 CFLAGS_ARM7 := -mtune=arm7 +CFLAGS_ARM720 := -mtune=arm7tdmi CFLAGS_SA110 := -mtune=strongarm110 else +CFLAGS += -DNO_TEXT_SECTIONS CFLAGS_PROC_CPU_26 := -m3 CFLAGS_PROC_CPU_32v3 := CFLAGS_PROC_CPU_32v4 := CFLAGS_ARM6 := -m6 CFLAGS_ARM7 := -m6 +CFLAGS_ARM720 := -m6 CFLAGS_SA110 := -m6 endif @@ -91,8 +93,16 @@ ifeq ($(CONFIG_CPU_ARM7),y) CFLAGS += $(CFLAGS_ARM7) else + ifeq ($(CONFIG_CPU_ARM720),y) + CFLAGS += $(CFLAGS_ARM720) + else ifeq ($(CONFIG_CPU_SA110),y) CFLAGS += $(CFLAGS_SA110) + else + ifeq ($(CONFIG_CPU_SA1100),y) + CFLAGS += $(CFLAGS_SA110) + endif + endif endif endif endif @@ -151,6 +161,11 @@ ARCHDIR = sa1100 endif +ifeq ($(CONFIG_ARCH_L7200),y) +MACHINE = l7200 +ARCHDIR = l7200 +endif + HEAD := arch/arm/kernel/head-$(PROCESSOR).o \ arch/arm/kernel/init_task.o SUBDIRS += arch/arm/kernel arch/arm/mm arch/arm/lib \ @@ -261,3 +276,14 @@ $(RM) arch/arm/defconfig cp arch/arm/def-configs/thinclient arch/arm/defconfig +assabet_config: + $(RM) arch/arm/defconfig + cp arch/arm/def-configs/assabet arch/arm/defconfig + +lart_config: + $(RM) arch/arm/defconfig + cp arch/arm/def-configs/lart arch/arm/defconfig + +l7200_config: + $(RM) arch/arm/defconfig + cp arch/arm/def-configs/lusl7200 arch/arm/defconfig diff -u --recursive --new-file v2.3.99-pre7/linux/arch/arm/boot/compressed/Makefile linux/arch/arm/boot/compressed/Makefile --- v2.3.99-pre7/linux/arch/arm/boot/compressed/Makefile Tue Mar 14 19:10:38 2000 +++ linux/arch/arm/boot/compressed/Makefile Fri May 12 11:21:20 2000 @@ -55,6 +55,12 @@ ZTEXTADDR = 0x00002000 ZBSSADDR = 0xc0100000 endif +ifeq ($(CONFIG_SA1100_THINCLIENT),y) + ZTEXTADDR = 0xC0200000 +endif +ifeq ($(CONFIG_SA1100_GRAPHICSCLIENT),y) + ZTEXTADDR = 0xC0200000 +endif endif # diff -u --recursive --new-file v2.3.99-pre7/linux/arch/arm/boot/compressed/head-sa1100.S linux/arch/arm/boot/compressed/head-sa1100.S --- v2.3.99-pre7/linux/arch/arm/boot/compressed/head-sa1100.S Tue Apr 11 15:09:11 2000 +++ linux/arch/arm/boot/compressed/head-sa1100.S Fri May 12 11:21:20 2000 @@ -8,27 +8,31 @@ #include +#ifndef CONFIG_ARCH_SA1100 +#error What am I doing here... +#endif .section ".start", #alloc, #execinstr __SA1100_start: -#ifndef CONFIG_ARCH_SA1100 -#error What am I doing here... -#endif + @ Preserve r0/r1 i.e. kernel entry values + mov r8, r0 + mov r9, r1 -#if defined( CONFIG_SA1100_BRUTUS ) || \ +#if defined( CONFIG_SA1100_ASSABET ) || \ + defined( CONFIG_SA1100_BRUTUS ) || \ defined( CONFIG_SA1100_THINCLIENT ) @ Booting from Angel -- need to enter SVC mode #define angel_SWIreason_EnterSVC 0x17 /* from arm.h, in angel source */ -#define angel_SWI_ARM (0xEF123456 & 0xffffff) +#define angel_SWI_ARM (0x123456) mov r0, #angel_SWIreason_EnterSVC swi #angel_SWI_ARM @ turn off interrupts to prevent the angel from running mrs r0, cpsr orr r0, r0, #0xc0 - msr cpsr, r0 + msr cpsr_c, r0 #endif #ifdef CONFIG_SA1100_VICTOR @@ -55,18 +59,23 @@ mcr p15, 0, r0, c7, c10, 4 @ drain WB mcr p15, 0, r0, c7, c7, 0 @ flush I & D caches - @ disabling MMU, enabling I cache + @ disabling MMU and caches mrc p15, 0, r0, c1, c0, 0 @ read control reg bic r0, r0, #0x0d @ clear WB, DC, MMU - orr r0, r0, #0x1000 @ set Icache + bic r0, r0, #0x1000 @ clear Icache mcr p15, 0, r0, c1, c0, 0 -#ifdef CONFIG_SA1100_BRUTUS +#if defined( CONFIG_SA1100_ASSABET ) || \ + defined( CONFIG_SA1100_BRUTUS ) @ Initialize UART1 for early serial communication @ since UART3 is used by angelboot. It is routed to @ alternate GPIO functions on Brutus. b 1f +#ifdef CONFIG_SA1100_BRUTUS +#define ALT_UART +#endif + GPIO_BASE: .long 0x90040000 #define GPDR 0x04 #define GAFR 0x1c @@ -90,7 +99,9 @@ #define BAUD_DIV_9600 0x017 #define BAUD_DIV BAUD_DIV_9600 -1: ldr r0, GPIO_BASE +1: +#ifdef ALT_UART + ldr r0, GPIO_BASE ldr r1, [r0, #GPDR] bic r1, r1, #1<<15 orr r1, r1, #1<<14 @@ -102,6 +113,7 @@ ldr r1, [r0, #PPAR] orr r1, r1, #1<<12 str r1, [r0, #PPAR] +#endif ldr r0, UART1_BASE 1: ldr r1, [r0, #UTSR1] tst r1, #1<<0 @ TBY @@ -120,8 +132,7 @@ str r1, [r0, #UTSR0] #endif - @ set registers for entry - mov r0, #0 - mov r1, #16 - - + @ Restore initial r0/r1 + @ (r8 preserved) + mov r0, r8 + mov r1, r9 diff -u --recursive --new-file v2.3.99-pre7/linux/arch/arm/boot/compressed/head.S linux/arch/arm/boot/compressed/head.S --- v2.3.99-pre7/linux/arch/arm/boot/compressed/head.S Wed Apr 26 16:34:06 2000 +++ linux/arch/arm/boot/compressed/head.S Fri May 12 11:21:20 2000 @@ -5,7 +5,6 @@ */ #include - .section ".start", #alloc, #execinstr /* * Debugging stuff @@ -47,6 +46,10 @@ #endif .endm +/* + * Note that these macros must not contain any code which is not + * 100% relocatable. Any attempt to do so will result in a crash. + */ #if 0 .macro loadsp, rb mov \rb, #0x7c000000 @@ -66,6 +69,8 @@ .endm #endif + + .section ".start", #alloc, #execinstr /* * sort out different calling conventions */ @@ -79,11 +84,13 @@ b 1f .word 0x016f2818 @ Magic numbers to help the loader .word start -1: +1: adr r8, start @ get the start address of the code + @ (used for locating the page tables) /* - * some architecture specific code can - * be inserted by the linker here + * some architecture specific code can be inserted + * by the linker here, but it should preserve r0, r1 + * and r8. */ .text @@ -142,31 +149,6 @@ bl cache_clean_flush add pc, r5, r0 @ call relocation code -/* - * Page table physical address list - */ - .align 5 - .type pgtable,#object -pgtable: .word 0x00004000 @ 0x00 - .word 0x10004000 @ 0x01 - .word 0x00000000 @ 0x02 - .word 0x40004000 @ 0x03 - .word 0x00004000 @ 0x04 - .word 0x00004000 @ 0x05 - .word 0x00004000 @ 0x06 - .word 0x80004000 @ 0x07 - .word 0x00004000 @ 0x08 - .word 0x00000000 @ 0x09 - .word 0x00000000 @ 0x0a - .word 0x00000000 @ 0x0b - .word 0x00000000 @ 0x0c - .word 0x00000000 @ 0x0d - .word 0x10004000 @ 0x0e - .word 0x08004000 @ 0x0f - .word 0xc0004000 @ 0x10 - .size pgtable,. - pgtable -1: - .type LC0, #object LC0: .word __bss_start .word _end @@ -175,17 +157,33 @@ .word user_stack+4096 .size LC0, . - LC0 +/* + * Turn on the cache. We need to setup some page tables so that we + * can have both the I and D caches on. + * + * We place the page tables 16k down from the kernel execution address, + * and we hope that nothing else is using it. If we're using it, we + * will go pop! + * + * On entry, + * r4 = kernel execution address + * r6 = processor ID + * r7 = architecture number + * r8 = run-time address of "start" + * On exit, + * r0, r1, r2, r3, r8, r9 corrupted + * This routine must preserve: + * r4, r5, r6, r7 + */ .align 5 cache_on: ldr r1, proc_sa110_type eor r1, r1, r6 movs r1, r1, lsr #5 movne pc, lr - cmp r7, #(1b - pgtable) >> 2 - movge pc, lr - adr r3, pgtable - ldr r3, [r3, r7, lsl #2] - teq r3, #0 - moveq pc, lr + + sub r3, r4, #16384 @ Page directory size + bic r3, r3, #0xff @ Align the pointer + bic r3, r3, #0x3f /* * Initialise the page tables */ @@ -220,6 +218,9 @@ mov pc, lr /* + * This code is relocatable. It is relocated by the above code to the end + * of the kernel and executed there. During this time, we have no stacks. + * * r0 = decompressed kernel length * r1-r3 = unused * r4 = kernel execution address @@ -248,13 +249,26 @@ mov r1, r7 @ restore architecture number mov pc, r4 @ call kernel +/* + * Here follow the relocatable cache support functions for + * the various processors. + */ + .type proc_sa110_type,#object proc_sa110_type: .word 0x4401a100 .size proc_sa110_type, . - proc_sa110_type /* - * Turn off StrongARM cache and MMU + * Turn off StrongARM cache and MMU. It is safe to + * leave the I-cache on. + * + * On entry, + * r6 = processor ID + * On exit, + * r0, r1 corrupted + * This routine must preserve: + * r4, r6, r7 */ .align 5 cache_off: ldr r1, proc_sa110_type @@ -268,6 +282,13 @@ /* * Clean and flush the cache to maintain consistency. + * + * On entry, + * r6 = processor ID + * On exit, + * r1, r2, r12 corrupted + * This routine must preserve: + * r4, r6, r7 */ .align 5 cache_clean_flush: @@ -278,7 +299,7 @@ bic r1, pc, #31 add r2, r1, #32768 -1: ldr r12, [r1], #32 +1: ldr r12, [r1], #32 @ s/w flush D cache teq r1, r2 bne 1b @@ -286,6 +307,10 @@ mcr p15, 0, r1, c7, c10, 4 @ drain WB mov pc, lr +/* + * Various debugging routines for printing hex characters and + * memory, which again must be relocatable. + */ #ifdef DEBUG .type phexbuf,#object phexbuf: .space 12 diff -u --recursive --new-file v2.3.99-pre7/linux/arch/arm/config.in linux/arch/arm/config.in --- v2.3.99-pre7/linux/arch/arm/config.in Wed Apr 26 16:34:06 2000 +++ linux/arch/arm/config.in Fri May 12 11:21:20 2000 @@ -14,7 +14,7 @@ endmenu mainmenu_option next_comment -comment 'System and processor type' +comment 'System and Processor Type' choice 'ARM system type' \ "Archimedes CONFIG_ARCH_ARC \ @@ -22,6 +22,8 @@ RiscPC CONFIG_ARCH_RPC \ EBSA-110 CONFIG_ARCH_EBSA110 \ FootBridge-based CONFIG_FOOTBRIDGE" RiscPC +# the following are placeholders for when they are fully integrated +# LinkUp-L7200 CONFIG_ARCH_L7200 # SA1100-based CONFIG_ARCH_SA1100 if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then @@ -34,6 +36,7 @@ fi if [ "$CONFIG_HOST_FOOTBRIDGE" = "y" ]; then + comment 'Footbridge Implementations' bool ' Include support for EBSA285' CONFIG_ARCH_EBSA285 bool ' Include support for CATS' CONFIG_ARCH_CATS bool ' Include support for NetWinder' CONFIG_ARCH_NETWINDER @@ -47,15 +50,19 @@ fi if [ "$CONFIG_ARCH_SA1100" = "y" ]; then - choice 'SA1100 implementation' \ - "Brutus CONFIG_SA1100_BRUTUS \ - Empeg CONFIG_SA1100_EMPEG \ - Itsy CONFIG_SA1100_ITSY \ - LART CONFIG_SA1100_LART \ - PLEB CONFIG_SA1100_PLEB \ - ThinClient CONFIG_SA1100_THINCLIENT \ - Victor CONFIG_SA1100_VICTOR \ - Tifon CONFIG_SA1100_TIFON" Brutus + comment 'SA11x0 Implementations' + bool ' Include support for Assabet' CONFIG_SA110_ASSABET + bool ' Include support for Bitsy' CONFIG_SA1100_BITSY + bool ' Include support for Brutus' CONFIG_SA1100_BRUTUS +# bool ' Include support for Empeg' CONFIG_SA1100_EMPEG +# bool ' Include support for Itsy' CONFIG_SA1100_ITSY + bool ' Include support for LART' CONFIG_SA1100_LART +# bool ' Include support for PLEB' CONFIG_SA1100_PLEB + bool ' Include support for ThinClient' CONFIG_SA1100_THINCLIENT + bool ' Include support for GraphicsClient' CONFIG_SA1100_GRAPHICSCLIENT + bool ' Include support for Victor' CONFIG_SA1100_VICTOR +# bool ' Include support for Tifon' CONFIG_SA1100_TIFON + define_bool CONFIG_DISCONTIGMEM y fi # @@ -87,30 +94,32 @@ else define_bool CONFIG_CPU_32 y define_bool CONFIG_CPU_26 n +fi - # - # Select CPU and optimisation dependent on architecture - # - if [ "$CONFIG_ARCH_EBSA110" = "y" -o \ - "$CONFIG_ARCH_SA1100" = "y" -o \ - "$CONFIG_FOOTBRIDGE" = "y" -o \ - "$CONFIG_ARCH_TBOX" = "y" -o \ - "$CONFIG_ARCH_SHARK" = "y" -o \ - "$CONFIG_ARCH_NEXUSPCI" = "y" ]; then - define_bool CONFIG_CPU_32v4 y - if [ "$CONFIG_ARCH_SA1100" = "y" ]; then - define_bool CONFIG_CPU_SA1100 y - else - define_bool CONFIG_CPU_SA110 y - fi - else - if [ "$CONFIG_ARCH_RPC" = "y" ]; then - define_bool CONFIG_CPU_32v3 y - bool 'Support ARM610' CONFIG_CPU_ARM6 - bool 'Support ARM710' CONFIG_CPU_ARM7 - bool 'Support StrongARM110' CONFIG_CPU_SA110 - fi - fi +# +# Select CPU and optimisation dependent on architecture +# +if [ "$CONFIG_ARCH_RPC" = "y" ]; then + define_bool CONFIG_CPU_32v3 y + bool 'Support ARM610' CONFIG_CPU_ARM6 + bool 'Support ARM710' CONFIG_CPU_ARM7 + bool 'Support StrongARM110' CONFIG_CPU_SA110 +fi +if [ "$CONFIG_ARCH_EBSA110" = "y" -o \ + "$CONFIG_FOOTBRIDGE" = "y" -o \ + "$CONFIG_ARCH_TBOX" = "y" -o \ + "$CONFIG_ARCH_SHARK" = "y" -o \ + "$CONFIG_ARCH_NEXUSPCI" = "y" ]; then + define_bool CONFIG_CPU_32v4 y + define_bool CONFIG_CPU_SA110 y +fi +if [ "$CONFIG_ARCH_L7200" = "y" ]; then + define_bool CONFIG_CPU_32v4 y + define_bool CONFIG_CPU_ARM720 y +fi +if [ "$CONFIG_ARCH_SA1100" = "y" ]; then + define_bool CONFIG_CPU_32v4 y + define_bool CONFIG_CPU_SA1100 y fi # @@ -137,10 +146,12 @@ define_bool CONFIG_ISA_DMA n fi +define_bool CONFIG_SBUS n +define_bool CONFIG_PCMCIA n + if [ "$CONFIG_CPU_32" = "y" -a "$CONFIG_ARCH_EBSA110" != "y" ]; then bool 'Kernel-mode alignment trap handler' CONFIG_ALIGNMENT_TRAP fi -#bool 'Split text into discardable sections' CONFIG_TEXT_SECTIONS endmenu mainmenu_option next_comment diff -u --recursive --new-file v2.3.99-pre7/linux/arch/arm/def-configs/assabet linux/arch/arm/def-configs/assabet --- v2.3.99-pre7/linux/arch/arm/def-configs/assabet Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/def-configs/assabet Fri May 12 11:21:20 2000 @@ -0,0 +1,246 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_ARM=y +CONFIG_UID16=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# System and processor type +# +# CONFIG_ARCH_ARC is not set +# CONFIG_ARCH_A5K is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_FOOTBRIDGE is not set +CONFIG_ARCH_SA1100=y +CONFIG_SA1100_ASSABET=y +# CONFIG_SA1100_BRUTUS is not set +# CONFIG_SA1100_EMPEG is not set +# CONFIG_SA1100_ITSY is not set +# CONFIG_SA1100_BITSY is not set +# CONFIG_SA1100_LART is not set +# CONFIG_SA1100_PLEB is not set +# CONFIG_SA1100_THINCLIENT is not set +# CONFIG_SA1100_VICTOR is not set +# CONFIG_SA1100_TIFON is not set +CONFIG_DISCONTIGMEM=y +# CONFIG_ARCH_ACORN is not set +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set +CONFIG_CPU_32v4=y +CONFIG_CPU_SA1100=y +# CONFIG_PCI is not set +# CONFIG_ISA is not set +# CONFIG_ISA_DMA is not set +# CONFIG_ALIGNMENT_TRAP is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +# CONFIG_KMOD is not set + +# +# General setup +# +# CONFIG_NET is not set +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_SYSCTL is not set +CONFIG_NWFPE=y +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set +CONFIG_BINFMT_AOUT=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set +CONFIG_CMDLINE="" +CONFIG_LEDS=y +CONFIG_LEDS_TIMER=y +CONFIG_LEDS_CPU=y + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_PCI is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# Plug and Play configuration +# +# CONFIG_PNP is not set +# CONFIG_ISAPNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set + +# +# Additional Block Devices +# +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_MD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_BLK_DEV_FLASH is not set + +# +# Character devices +# +CONFIG_VT=y +# CONFIG_VT_CONSOLE is not set +CONFIG_SERIAL_SA1100=y +CONFIG_SERIAL_SA1100_CONSOLE=y +# CONFIG_SERIAL is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=32 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_JOYSTICK is not set +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set + +# +# Video For Linux +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_DRM is not set +# CONFIG_DRM_TDFX is not set +# CONFIG_AGP is not set + +# +# Console drivers +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_FB=y + +# +# Frame-buffer support +# +CONFIG_FB=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_FB_SA1100=y +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FBCON_ADVANCED is not set +CONFIG_FBCON_CFB2=y +CONFIG_FBCON_CFB4=y +CONFIG_FBCON_CFB8=y +CONFIG_FBCON_FONTWIDTH8_ONLY=y +CONFIG_FBCON_FONTS=y +CONFIG_FONT_8x8=y +# CONFIG_FONT_8x16 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set + +# +# ATA/IDE/MFM/RLL support +# +# CONFIG_IDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_MINIX_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set +# CONFIG_UFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_NLS is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_INFO=y +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_LL is not set diff -u --recursive --new-file v2.3.99-pre7/linux/arch/arm/def-configs/brutus linux/arch/arm/def-configs/brutus --- v2.3.99-pre7/linux/arch/arm/def-configs/brutus Thu May 11 15:30:05 2000 +++ linux/arch/arm/def-configs/brutus Fri May 12 11:21:20 2000 @@ -18,12 +18,15 @@ # CONFIG_ARCH_EBSA110 is not set # CONFIG_FOOTBRIDGE is not set CONFIG_ARCH_SA1100=y +# CONFIG_SA1100_ASSABET is not set CONFIG_SA1100_BRUTUS=y # CONFIG_SA1100_EMPEG is not set # CONFIG_SA1100_ITSY is not set +# CONFIG_SA1100_BITSY is not set # CONFIG_SA1100_LART is not set # CONFIG_SA1100_PLEB is not set # CONFIG_SA1100_THINCLIENT is not set +# CONFIG_SA1100_GRAPHICSCLIENT is not set # CONFIG_SA1100_VICTOR is not set # CONFIG_SA1100_TIFON is not set CONFIG_DISCONTIGMEM=y @@ -32,7 +35,11 @@ # CONFIG_CPU_26 is not set CONFIG_CPU_32v4=y CONFIG_CPU_SA1100=y +# CONFIG_PCI is not set +# CONFIG_ISA is not set # CONFIG_ISA_DMA is not set +# CONFIG_SBUS is not set +# CONFIG_PCMCIA is not set # CONFIG_ALIGNMENT_TRAP is not set # @@ -62,12 +69,14 @@ # # CONFIG_PARPORT is not set CONFIG_CMDLINE="" +CONFIG_LEDS=y +CONFIG_LEDS_TIMER=y +CONFIG_LEDS_CPU=y # # I2O device support # # CONFIG_I2O is not set -# CONFIG_I2O_PCI is not set # CONFIG_I2O_BLOCK is not set # CONFIG_I2O_SCSI is not set # CONFIG_I2O_PROC is not set @@ -82,24 +91,23 @@ # Block devices # # CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_IDE is not set - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD_ONLY is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set # # Additional Block Devices # # CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_LVM is not set # CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_STRIPED is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_INITRD=y -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_HD is not set +# CONFIG_BLK_DEV_FLASH is not set # # Character devices @@ -155,11 +163,6 @@ # CONFIG_AGP is not set # -# USB support -# -# CONFIG_USB is not set - -# # Console drivers # # CONFIG_VGA_CONSOLE is not set @@ -171,10 +174,6 @@ CONFIG_FB=y CONFIG_DUMMY_CONSOLE=y CONFIG_FB_SA1100=y -# CONFIG_FB_MATROX is not set -# CONFIG_FB_ATY is not set -# CONFIG_FB_ATY128 is not set -# CONFIG_FB_3DFX is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FBCON_ADVANCED is not set CONFIG_FBCON_CFB2=y @@ -189,6 +188,13 @@ # CONFIG_FONT_ACORN_8x8 is not set # +# ATA/IDE/MFM/RLL support +# +# CONFIG_IDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# # SCSI support # # CONFIG_SCSI is not set @@ -200,6 +206,7 @@ # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set # CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set @@ -232,6 +239,11 @@ # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y # CONFIG_NLS is not set + +# +# USB support +# +# CONFIG_USB is not set # # Kernel hacking diff -u --recursive --new-file v2.3.99-pre7/linux/arch/arm/def-configs/graphicsclient linux/arch/arm/def-configs/graphicsclient --- v2.3.99-pre7/linux/arch/arm/def-configs/graphicsclient Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/def-configs/graphicsclient Fri May 12 11:21:20 2000 @@ -0,0 +1,382 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_ARM=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# System and processor type +# +# CONFIG_ARCH_ARC is not set +# CONFIG_ARCH_A5K is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_FOOTBRIDGE is not set +CONFIG_ARCH_SA1100=y +# CONFIG_SA1100_BRUTUS is not set +# CONFIG_SA1100_EMPEG is not set +# CONFIG_SA1100_ITSY is not set +# CONFIG_SA1100_LART is not set +# CONFIG_SA1100_PLEB is not set +CONFIG_SA1100_GRAPHICSCLIENT=y +# CONFIG_SA1100_VICTOR is not set +# CONFIG_SA1100_TIFON is not set +CONFIG_DISCONTIGMEM=y +# CONFIG_ARCH_ACORN is not set +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set +CONFIG_CPU_32v4=y +CONFIG_CPU_SA1100=y +# CONFIG_ISA_DMA is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +# CONFIG_KMOD is not set + +# +# General setup +# +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_NWFPE=y +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set +CONFIG_BINFMT_AOUT=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set +# CONFIG_PARPORT is not set +CONFIG_CMDLINE="ip=off" + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_PCI is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# Plug and Play configuration +# +# CONFIG_PNP is not set +# CONFIG_ISAPNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_IDE is not set + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD_ONLY is not set + +# +# Additional Block Devices +# +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_MD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_BLK_DEV_XD is not set +CONFIG_PARIDE_PARPORT=y +# CONFIG_PARIDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# +# Character devices +# +CONFIG_VT=y +# CONFIG_VT_CONSOLE is not set +CONFIG_SERIAL_SA1100=y +CONFIG_SERIAL_SA1100_CONSOLE=y +# CONFIG_SERIAL is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=32 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_JOYSTICK is not set +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set + +# +# Video For Linux +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_DRM is not set +# CONFIG_DRM_TDFX is not set + +# +# PCMCIA character device support +# +# CONFIG_AGP is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# Console drivers +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_FB=y + +# +# Frame-buffer support +# +CONFIG_FB=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_FB_SA1100=y +# CONFIG_FB_MATROX is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FBCON_ADVANCED is not set +CONFIG_FBCON_CFB2=y +CONFIG_FBCON_CFB4=y +CONFIG_FBCON_CFB8=y +CONFIG_FBCON_FONTWIDTH8_ONLY=y +CONFIG_FBCON_FONTS=y +# CONFIG_FONT_8x8 is not set +CONFIG_FONT_8x16=y +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set + +# +# Networking options +# +# CONFIG_PACKET is not set +# CONFIG_NETLINK is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_IP_ROUTER is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_ALIAS is not set +# CONFIG_SYN_COOKIES is not set + +# +# (it is safe to leave these untouched) +# +CONFIG_SKB_LARGE=y +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_DECNET is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_BRIDGE is not set +# CONFIG_LLC is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +# CONFIG_NET_SB1000 is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_ARM_AM79C961A is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +CONFIG_NET_VENDOR_SMC=y +# CONFIG_WD80x3 is not set +# CONFIG_ULTRA is not set +# CONFIG_ULTRA32 is not set +CONFIG_SMC9194=y +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_RTL8139 is not set +# CONFIG_DM9102 is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_EISA is not set +# CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_YELLOWFIN is not set +# CONFIG_ACENIC is not set +# CONFIG_SK98LIN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring driver support +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# PCMCIA network device support +# +# CONFIG_NET_PCMCIA is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# Filesystems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_MINIX_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_SGI_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_INFO=y +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_LL is not set diff -u --recursive --new-file v2.3.99-pre7/linux/arch/arm/def-configs/lart linux/arch/arm/def-configs/lart --- v2.3.99-pre7/linux/arch/arm/def-configs/lart Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/def-configs/lart Fri May 12 11:21:20 2000 @@ -0,0 +1,330 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_ARM=y +CONFIG_UID16=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# System and processor type +# +# CONFIG_ARCH_ARC is not set +# CONFIG_ARCH_A5K is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_FOOTBRIDGE is not set +CONFIG_ARCH_SA1100=y +# CONFIG_SA1100_ASSABET is not set +# CONFIG_SA1100_BRUTUS is not set +# CONFIG_SA1100_EMPEG is not set +# CONFIG_SA1100_ITSY is not set +# CONFIG_SA1100_BITSY is not set +CONFIG_SA1100_LART=y +# CONFIG_SA1100_PLEB is not set +# CONFIG_SA1100_THINCLIENT is not set +# CONFIG_SA1100_VICTOR is not set +# CONFIG_SA1100_TIFON is not set +CONFIG_DISCONTIGMEM=y +# CONFIG_ARCH_ACORN is not set +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set +CONFIG_CPU_32v4=y +CONFIG_CPU_SA1100=y +# CONFIG_PCI is not set +# CONFIG_ISA is not set +# CONFIG_ISA_DMA is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODVERSIONS=y +# CONFIG_KMOD is not set + +# +# General setup +# +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_SYSCTL is not set +CONFIG_NWFPE=y +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set +CONFIG_BINFMT_AOUT=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set +CONFIG_CMDLINE="console=ttyS0,9600" +CONFIG_LEDS=y +# CONFIG_LEDS_TIMER is not set +CONFIG_LEDS_CPU=y + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Plug and Play configuration +# +# CONFIG_PNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_XD is not set + +# +# Additional Block Devices +# +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_MD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_BLK_DEV_FLASH is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_SERIAL_SA1100=y +CONFIG_SERIAL_SA1100_CONSOLE=y +# CONFIG_SERIAL is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_UNIX98_PTYS is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_JOYSTICK is not set +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set + +# +# Video For Linux +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_DRM is not set +# CONFIG_AGP is not set + +# +# Networking options +# +# CONFIG_PACKET is not set +# CONFIG_NETLINK is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_IP_ROUTER is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_ALIAS is not set +# CONFIG_SYN_COOKIES is not set + +# +# (it is safe to leave these untouched) +# +# CONFIG_SKB_LARGE is not set +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_DECNET is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_BRIDGE is not set +# CONFIG_LLC is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_NET_SB1000 is not set + +# +# Ethernet (10 or 100Mbit) +# +# CONFIG_NET_ETHERNET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_YELLOWFIN is not set +# CONFIG_ACENIC is not set +# CONFIG_SK98LIN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PPP=y +CONFIG_PPP_ASYNC=y +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_BSDCOMP=m +CONFIG_SLIP=y +CONFIG_SLIP_COMPRESSED=y +# CONFIG_SLIP_SMART is not set +# CONFIG_SLIP_MODE_SLIP6 is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# ATA/IDE/MFM/RLL support +# +# CONFIG_IDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_FAT_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_MINIX_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +CONFIG_NFS_FS=y +# CONFIG_NFSD is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_NLS is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_INFO=y +# CONFIG_MAGIC_SYSRQ is not set +CONFIG_DEBUG_LL=y diff -u --recursive --new-file v2.3.99-pre7/linux/arch/arm/def-configs/lusl7200 linux/arch/arm/def-configs/lusl7200 --- v2.3.99-pre7/linux/arch/arm/def-configs/lusl7200 Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/def-configs/lusl7200 Fri May 12 11:21:20 2000 @@ -0,0 +1,233 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_ARM=y +CONFIG_UID16=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# System and Processor Type +# +# CONFIG_ARCH_ARC is not set +# CONFIG_ARCH_A5K is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_FOOTBRIDGE is not set +CONFIG_ARCH_L7200=y +# CONFIG_ARCH_ACORN is not set +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set +CONFIG_CPU_32v4=y +CONFIG_CPU_ARM720=y +# CONFIG_PCI is not set +# CONFIG_ISA is not set +# CONFIG_ISA_DMA is not set +# CONFIG_SBUS is not set +# CONFIG_PCMCIA is not set +# CONFIG_ALIGNMENT_TRAP is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# +# General setup +# +# CONFIG_NET is not set +CONFIG_SYSVIPC=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_SYSCTL=y +CONFIG_NWFPE=y +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set +CONFIG_BINFMT_AOUT=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# Plug and Play configuration +# +# CONFIG_PNP is not set +# CONFIG_ISAPNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set + +# +# Additional Block Devices +# +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_LVM is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_STRIPED is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_INITRD=y + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL is not set +# CONFIG_SERIAL_EXTENDED is not set +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +# CONFIG_CYCLADES is not set +CONFIG_SERIAL_L7200=y +CONFIG_SERIAL_L7200_CONSOLE=y +# CONFIG_DIGIEPCA is not set +# CONFIG_DIGI is not set +# CONFIG_ESPSERIAL is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +# CONFIG_SYNCLINK is not set +# CONFIG_N_HDLC is not set +# CONFIG_RISCOM8 is not set +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_STALDRV is not set +# CONFIG_UNIX98_PTYS is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_JOYSTICK is not set +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set + +# +# Video For Linux +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_DRM is not set +# CONFIG_DRM_TDFX is not set +# CONFIG_AGP is not set + +# +# ATA/IDE/MFM/RLL support +# +# CONFIG_IDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_RAMFS is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_MINIX_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_DEBUG is not set +# CONFIG_DEVPTS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_SYSV_FS_WRITE is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_NCPFS_NLS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_NLS is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_INFO=y +# CONFIG_MAGIC_SYSRQ is not set +CONFIG_DEBUG_LL=y diff -u --recursive --new-file v2.3.99-pre7/linux/arch/arm/def-configs/thinclient linux/arch/arm/def-configs/thinclient --- v2.3.99-pre7/linux/arch/arm/def-configs/thinclient Thu May 11 15:30:05 2000 +++ linux/arch/arm/def-configs/thinclient Fri May 12 11:21:20 2000 @@ -18,12 +18,15 @@ # CONFIG_ARCH_EBSA110 is not set # CONFIG_FOOTBRIDGE is not set CONFIG_ARCH_SA1100=y +# CONFIG_SA1100_ASSABET is not set # CONFIG_SA1100_BRUTUS is not set # CONFIG_SA1100_EMPEG is not set # CONFIG_SA1100_ITSY is not set +# CONFIG_SA1100_BITSY is not set # CONFIG_SA1100_LART is not set # CONFIG_SA1100_PLEB is not set CONFIG_SA1100_THINCLIENT=y +# CONFIG_SA1100_GRAPHICSCLIENT is not set # CONFIG_SA1100_VICTOR is not set # CONFIG_SA1100_TIFON is not set CONFIG_DISCONTIGMEM=y @@ -32,7 +35,11 @@ # CONFIG_CPU_26 is not set CONFIG_CPU_32v4=y CONFIG_CPU_SA1100=y +# CONFIG_PCI is not set +# CONFIG_ISA is not set # CONFIG_ISA_DMA is not set +# CONFIG_SBUS is not set +# CONFIG_PCMCIA is not set CONFIG_ALIGNMENT_TRAP=y # @@ -56,14 +63,18 @@ CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set # CONFIG_ARTHUR is not set + +# +# Parallel port support +# # CONFIG_PARPORT is not set CONFIG_CMDLINE="root=nfs" +# CONFIG_LEDS is not set # # I2O device support # # CONFIG_I2O is not set -# CONFIG_I2O_PCI is not set # CONFIG_I2O_BLOCK is not set # CONFIG_I2O_LAN is not set # CONFIG_I2O_SCSI is not set @@ -79,25 +90,23 @@ # Block devices # # CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_IDE is not set - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD_ONLY is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set # # Additional Block Devices # # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_LVM is not set # CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_STRIPED is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_INITRD=y -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_FLASH=y # # Character devices @@ -135,7 +144,6 @@ # CONFIG_WATCHDOG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set -# CONFIG_EFI_RTC is not set # # Video For Linux @@ -154,15 +162,6 @@ # CONFIG_AGP is not set # -# USB support -# -# CONFIG_USB is not set - -# -# Misc devices -# - -# # Console drivers # # CONFIG_VGA_CONSOLE is not set @@ -174,10 +173,6 @@ CONFIG_FB=y CONFIG_DUMMY_CONSOLE=y CONFIG_FB_SA1100=y -# CONFIG_FB_MATROX is not set -# CONFIG_FB_ATY is not set -# CONFIG_FB_ATY128 is not set -# CONFIG_FB_3DFX is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FBCON_ADVANCED is not set CONFIG_FBCON_CFB2=y @@ -300,7 +295,7 @@ # CONFIG_NET_RADIO is not set # -# Token Ring driver support +# Token Ring devices # # CONFIG_TR is not set # CONFIG_NET_FC is not set @@ -313,6 +308,13 @@ # CONFIG_WAN is not set # +# ATA/IDE/MFM/RLL support +# +# CONFIG_IDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# # SCSI support # # CONFIG_SCSI is not set @@ -324,6 +326,7 @@ # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set # CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set @@ -368,6 +371,11 @@ # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y # CONFIG_NLS is not set + +# +# USB support +# +# CONFIG_USB is not set # # Kernel hacking diff -u --recursive --new-file v2.3.99-pre7/linux/arch/arm/kernel/Makefile linux/arch/arm/kernel/Makefile --- v2.3.99-pre7/linux/arch/arm/kernel/Makefile Tue Apr 11 15:09:12 2000 +++ linux/arch/arm/kernel/Makefile Fri May 12 11:21:20 2000 @@ -19,6 +19,7 @@ O_OBJS_footbridge = dma.o dma-footbridge.o $(ISA_DMA_OBJS) hw-footbridge.o isa.o O_OBJS_nexuspci = dma-dummy.o O_OBJS_sa1100 = dma-dummy.o fiq.o +O_OBJS_l7200 = dma-dummy.o fiq.o O_TARGET := kernel.o diff -u --recursive --new-file v2.3.99-pre7/linux/arch/arm/kernel/arch.h linux/arch/arm/kernel/arch.h --- v2.3.99-pre7/linux/arch/arm/kernel/arch.h Wed Apr 26 16:34:06 2000 +++ linux/arch/arm/kernel/arch.h Fri May 12 11:21:20 2000 @@ -33,7 +33,8 @@ }; /* - * Set of macros to define architecture features + * Set of macros to define architecture features. This is built into + * a table by the linker. */ #define MACHINE_START(_type,_name) \ const struct machine_desc __mach_desc_##_type \ diff -u --recursive --new-file v2.3.99-pre7/linux/arch/arm/kernel/bios32.c linux/arch/arm/kernel/bios32.c --- v2.3.99-pre7/linux/arch/arm/kernel/bios32.c Wed Apr 26 16:34:06 2000 +++ linux/arch/arm/kernel/bios32.c Fri May 12 11:21:20 2000 @@ -378,6 +378,9 @@ case DEV(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5000): return IRQ_NETWINDER_VGA; + case DEV(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285): + return 0; + default: printk(KERN_ERR "PCI: %02X:%02X [%04X:%04X] unknown device\n", dev->bus->number, dev->devfn, diff -u --recursive --new-file v2.3.99-pre7/linux/arch/arm/kernel/calls.S linux/arch/arm/kernel/calls.S --- v2.3.99-pre7/linux/arch/arm/kernel/calls.S Fri Jan 21 18:19:15 2000 +++ linux/arch/arm/kernel/calls.S Fri May 12 11:21:20 2000 @@ -68,7 +68,7 @@ .long SYMBOL_NAME(sys_ni_syscall) /* was sys_mpx */ .long SYMBOL_NAME(sys_setpgid) .long SYMBOL_NAME(sys_ni_syscall) /* was sys_ulimit */ - .long SYMBOL_NAME(sys_olduname) + .long SYMBOL_NAME(sys_ni_syscall) /* was sys_olduname */ /* 60 */ .long SYMBOL_NAME(sys_umask) .long SYMBOL_NAME(sys_chroot) .long SYMBOL_NAME(sys_ustat) @@ -118,7 +118,7 @@ .long SYMBOL_NAME(sys_newstat) .long SYMBOL_NAME(sys_newlstat) .long SYMBOL_NAME(sys_newfstat) - .long SYMBOL_NAME(sys_uname) + .long SYMBOL_NAME(sys_ni_syscall) /* was sys_uname */ /* 110 */ .long SYMBOL_NAME(sys_iopl) .long SYMBOL_NAME(sys_vhangup) .long SYMBOL_NAME(sys_ni_syscall) diff -u --recursive --new-file v2.3.99-pre7/linux/arch/arm/kernel/debug-armv.S linux/arch/arm/kernel/debug-armv.S --- v2.3.99-pre7/linux/arch/arm/kernel/debug-armv.S Wed Apr 26 16:34:06 2000 +++ linux/arch/arm/kernel/debug-armv.S Fri May 12 11:21:20 2000 @@ -160,6 +160,33 @@ bne 1001b .endm +#elif defined(CONFIG_ARCH_L7200) + + .macro addruart,rx + + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + moveq \rx, #0x80000000 @ physical base address + movne \rx, #0xd0000000 @ virtual address + add \rx, \rx, #0x00044000 @ Ser1 +@ add \rx, \rx, #0x00045000 @ Ser2 + .endm + + .macro senduart,rd,rx + str \rd, [\rx, #0x0] @ UARTDR1 + .endm + + .macro waituart,rd,rx +1001: ldr \rd, [\rx, #0x18] @ UARTFLG + tst \rd, #1 << 5 @ UARTFLGUTXFF - 1 when full + bne 1001b + .endm + + .macro busyuart,rd,rx +1001: ldr \rd, [\rx, #0x18] @ UARTFLG + tst \rd, #1 << 3 @ UARTFLGUBUSY - 1 when busy + bne 1001b + .endm #else #error Unknown architecture #endif diff -u --recursive --new-file v2.3.99-pre7/linux/arch/arm/kernel/entry-armv.S linux/arch/arm/kernel/entry-armv.S --- v2.3.99-pre7/linux/arch/arm/kernel/entry-armv.S Tue Apr 11 15:09:12 2000 +++ linux/arch/arm/kernel/entry-armv.S Fri May 12 11:21:20 2000 @@ -400,6 +400,26 @@ .macro irq_prio_table .endm +#elif defined(CONFIG_ARCH_L7200) +/* Don't use fast interrupts */ + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base + ldr r4, =0xe0001000 @ Virt addr status reg + ldr \irqstat, [r4] @ get interrupts + mov \irqnr, #0 +1001: tst \irqstat, #1 + addeq \irqnr, \irqnr, #1 + moveq \irqstat, \irqstat, lsr #1 + tsteq \irqnr, #32 + beq 1001b + teq \irqnr, #32 + .endm + + .macro irq_prio_table + .endm + #else #error Unknown architecture #endif diff -u --recursive --new-file v2.3.99-pre7/linux/arch/arm/kernel/head-armv.S linux/arch/arm/kernel/head-armv.S --- v2.3.99-pre7/linux/arch/arm/kernel/head-armv.S Wed Apr 26 16:34:06 2000 +++ linux/arch/arm/kernel/head-armv.S Fri May 12 11:21:20 2000 @@ -63,31 +63,39 @@ mov r5, #0 movne pc, r0 + mov r0, #0 @ catch old NeTTroms + mov r1, #5 @ (will go in 2.5) +#endif +#ifdef CONFIG_ARCH_L7200 +/* + * FIXME - No bootloader, so manually set 'r1' with our architecture number. + */ mov r0, #0 - mov r1, #5 + mov r1, #19 #endif /* * Entry point. Entry *must* be called with r0 == 0, with the MMU off. * r1 contains the unique architecture number. See - * linux/arch/arm/kernel/setup.c machine_desc[] array for the complete - * list. If you require a new number, please follow the instructions - * given in Documentation/arm/README. + * linux/arch/arm/kernel/arch.c and linux/include/asm-arm/system.h for + * the complete list. If you require a new number, please follow the + * instructions given towards the end of Documentation/arm/README. */ -__entry: teq r0, #0 - movne r0, #'i' +__entry: teq r0, #0 @ wrong register vals? + movne r0, #'i' @ yes, error 'i' bne __error bl __lookup_processor_type teq r10, #0 @ invalid processor? - moveq r0, #'p' + moveq r0, #'p' @ yes, error 'p' beq __error bl __lookup_architecture_type teq r7, #0 @ invalid architecture? - moveq r0, #'a' + moveq r0, #'a' @ yes, error 'a' beq __error bl __create_page_tables - adr lr, __ret - add pc, r10, #12 @ flush caches (returns ctrl reg) + adr lr, __ret @ return address + add pc, r10, #12 @ initialise processor + @ (return control reg) __switch_data: .long __mmap_switched .long SYMBOL_NAME(__bss_start) @@ -115,7 +123,8 @@ .align 5 __mmap_switched: adr r3, __switch_data + 4 - ldmia r3, {r4, r5, r6, r7, r8, sp} @ Setup stack + ldmia r3, {r4, r5, r6, r7, r8, sp} @ r4 = __bss_start + @ sp = stack pointer mov fp, #0 @ Clear BSS 1: cmp r4, r5 @@ -150,8 +159,8 @@ add r4, r5, #SWAPPER_PGDIR_OFFSET mov r0, r4 mov r3, #0 - add r2, r0, #0x4000 @ Clear page table -1: str r3, [r0], #4 + add r2, r0, #0x4000 @ 16k of page table +1: str r3, [r0], #4 @ Clear page table str r3, [r0], #4 str r3, [r0], #4 str r3, [r0], #4 @@ -164,19 +173,19 @@ * * The identity mapping will be removed by paging_init() */ - mov r3, #0x0c - orr r3, r3, r8 - add r3, r3, r5 + mov r3, #0x0c @ cacheable, bufferable + orr r3, r3, r8 @ | pagetable flags + add r3, r3, r5 @ + start of RAM add r0, r4, r5, lsr #18 - str r3, [r0] - add r0, r4, #(TEXTADDR - 0x8000) >> 18 - str r3, [r0], #4 + str r3, [r0] @ identity mapping + add r0, r4, #(TEXTADDR - 0x8000) >> 18 @ start of kernel + str r3, [r0], #4 @ PAGE_OFFSET + 0MB add r3, r3, #1 << 20 - str r3, [r0], #4 + str r3, [r0], #4 @ PAGE_OFFSET + 1MB add r3, r3, #1 << 20 - str r3, [r0], #4 + str r3, [r0], #4 @ PAGE_OFFSET + 2MB add r3, r3, #1 << 20 - str r3, [r0], #4 + str r3, [r0], #4 @ PAGE_OFFSET + 3MB #ifdef CONFIG_DEBUG_LL /* * Map in IO space for serial debugging. @@ -194,6 +203,10 @@ teq r0, r2 bne 1b #ifdef CONFIG_ARCH_NETWINDER + /* + * If we're using the NetWinder, we need to map in + * the 16550-type serial port for the debug messages + */ teq r1, #5 bne 1f add r0, r4, #0x3fc0 @@ -228,7 +241,10 @@ * proceed. We ought to tell the user, but since we * don't have any guarantee that we're even running on * the right architecture, we do virtually nothing. - * r0 = ascii error character + * r0 = ascii error character: + * a = invalid architecture + * p = invalid processor + * i = invalid calling convention * * Generally, only serious errors cause this. */ @@ -262,8 +278,11 @@ #endif /* - * Read processor ID register (CP#15, CR0), and determine - * processor type. + * Read processor ID register (CP#15, CR0), and look up in the linker-built + * supported processor list. Note that we can't use the absolute addresses + * for the __proc_info lists since we aren't running with the MMU on + * (and therefore, we are not in the correct address space). We have to + * calculate the offset. * * Returns: * r5, r6, r7 corrupted @@ -274,20 +293,24 @@ __lookup_processor_type: adr r5, 2f ldmia r5, {r7, r9, r10} - sub r5, r5, r10 - add r7, r7, r5 + sub r5, r5, r10 @ convert addresses + add r7, r7, r5 @ to our address space add r10, r9, r5 mrc p15, 0, r9, c0, c0 @ get processor id 1: ldmia r10, {r5, r6, r8} @ value, mask, mmuflags - eor r5, r5, r9 - tst r5, r6 + and r6, r6, r9 @ mask wanted bits + teq r5, r6 moveq pc, lr add r10, r10, #36 @ sizeof(proc_info_list) cmp r10, r7 blt 1b - mov r10, #0 + mov r10, #0 @ unknown processor mov pc, lr +/* + * Look in include/asm-arm/procinfo.h and arch/arm/kernel/arch.[ch] for + * more information about the __proc_info and __arch_info structures. + */ 2: .long __proc_info_end .long __proc_info_begin .long 2b @@ -295,10 +318,14 @@ .long __arch_info_end /* - * Lookup machine architecture - * r1 = machine architecture number + * Lookup machine architecture in the linker-build list of architectures. + * Note that we can't use the absolute addresses for the __arch_info + * lists since we aren't running with the MMU on (and therefore, we are + * not in the correct address space). We have to calculate the offset. + * + * r1 = machine architecture number * Returns: - * r4 = unused word + * r2, r3, r4 corrupted * r5 = physical start address of RAM * r6 = physical address of IO * r7 = byte offset into page tables for IO @@ -306,16 +333,17 @@ __lookup_architecture_type: adr r4, 2b ldmia r4, {r2, r3, r5, r6, r7} @ throw away r2, r3 - sub r5, r4, r5 - add r4, r6, r5 + sub r5, r4, r5 @ convert addresses + add r4, r6, r5 @ to our address space add r7, r7, r5 -1: ldr r5, [r4] +1: ldr r5, [r4] @ get machine type teq r5, r1 beq 2f add r4, r4, #SIZEOF_MACHINE_DESC cmp r4, r7 blt 1b - mov r7, #0 + mov r7, #0 @ unknown architecture mov pc, lr -2: ldmib r4, {r5, r6, r7} +2: ldmib r4, {r5, r6, r7} @ found, get results + mov r7, r7, lsr #18 @ pagetable byte offset mov pc, lr diff -u --recursive --new-file v2.3.99-pre7/linux/arch/arm/kernel/sys_arm.c linux/arch/arm/kernel/sys_arm.c --- v2.3.99-pre7/linux/arch/arm/kernel/sys_arm.c Thu Mar 2 14:36:22 2000 +++ linux/arch/arm/kernel/sys_arm.c Fri May 12 11:21:20 2000 @@ -248,66 +248,6 @@ return error; } -/* Compatability functions - we used to pass 5 parameters as r0, r1, r2, *r3, *(r3+4) - * We now use r0 - r4, and return an error if the old style calling standard is used. - * Eventually these functions will disappear. - */ -asmlinkage int sys_uname(struct old_utsname * name) -{ - static int warned = 0; - int err; - - if (warned == 0) { - warned ++; - printk (KERN_NOTICE "%s (%d): obsolete uname call\n", - current->comm, current->pid); - } - - if(!name) - return -EFAULT; - down_read(&uts_sem); - err=copy_to_user (name, &system_utsname, sizeof (*name)); - up_read(&uts_sem); - return err?-EFAULT:0; -} - -asmlinkage int sys_olduname(struct oldold_utsname * name) -{ - int error; - static int warned = 0; - - if (warned == 0) { - warned ++; - printk (KERN_NOTICE "%s (%d): obsolete olduname call\n", - current->comm, current->pid); - } - - if (!name) - return -EFAULT; - - if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname))) - return -EFAULT; - - down_read(&uts_sem); - - error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN); - error |= __put_user(0,name->sysname+__OLD_UTS_LEN); - error |= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN); - error |= __put_user(0,name->nodename+__OLD_UTS_LEN); - error |= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN); - error |= __put_user(0,name->release+__OLD_UTS_LEN); - error |= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN); - error |= __put_user(0,name->version+__OLD_UTS_LEN); - error |= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN); - error |= __put_user(0,name->machine+__OLD_UTS_LEN); - - up_read(&uts_sem); - - error = error ? -EFAULT : 0; - - return error; -} - asmlinkage int sys_pause(void) { current->state = TASK_INTERRUPTIBLE; diff -u --recursive --new-file v2.3.99-pre7/linux/arch/arm/mm/mm-sa1100.c linux/arch/arm/mm/mm-sa1100.c --- v2.3.99-pre7/linux/arch/arm/mm/mm-sa1100.c Wed Apr 26 16:34:06 2000 +++ linux/arch/arm/mm/mm-sa1100.c Fri May 12 11:21:20 2000 @@ -29,12 +29,12 @@ #define SA1100_STD_IO_MAPPING \ /* virtual physical length domain r w c b */ \ - { 0xe0000000, 0x20000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 IO */ \ - { 0xe4000000, 0x30000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 IO */ \ - { 0xe8000000, 0x28000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 attr */ \ - { 0xec000000, 0x38000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 attr */ \ - { 0xf0000000, 0x2c000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 mem */ \ - { 0xf4000000, 0x3c000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 mem */ \ + { 0xe0000000, 0x20000000, 0x04000000, DOMAIN_IO, 1, 1, 0, 0 }, /* PCMCIA0 IO */ \ + { 0xe4000000, 0x30000000, 0x04000000, DOMAIN_IO, 1, 1, 0, 0 }, /* PCMCIA1 IO */ \ + { 0xe8000000, 0x28000000, 0x04000000, DOMAIN_IO, 1, 1, 0, 0 }, /* PCMCIA0 attr */ \ + { 0xec000000, 0x38000000, 0x04000000, DOMAIN_IO, 1, 1, 0, 0 }, /* PCMCIA1 attr */ \ + { 0xf0000000, 0x2c000000, 0x04000000, DOMAIN_IO, 1, 1, 0, 0 }, /* PCMCIA0 mem */ \ + { 0xf4000000, 0x3c000000, 0x04000000, DOMAIN_IO, 1, 1, 0, 0 }, /* PCMCIA1 mem */ \ { 0xf8000000, 0x80000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCM */ \ { 0xfa000000, 0x90000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* SCM */ \ { 0xfc000000, 0xa0000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* MER */ \ @@ -63,16 +63,21 @@ #endif }; +static struct map_desc graphicsclient_io_desc[] __initdata = { +#ifdef CONFIG_SA1100_GRAPHICSCLIENT + { 0xd0000000, 0x08000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 */ + { 0xd0800000, 0x18000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 3 */ + { 0xdc000000, 0x10000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD */ + SA1100_STD_IO_MAPPING +#endif +}; + static struct map_desc thinclient_io_desc[] __initdata = { #ifdef CONFIG_SA1100_THINCLIENT -#if 1 - /* ThinClient: only one of those... */ -// { 0xd0000000, 0x00000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 when JP1 2-4 */ - { 0xd0000000, 0x08000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 when JP1 3-4 */ +#if 0 + { 0xd0000000, 0x00000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 when JP1 2-4 */ #else - /* GraphicsClient: */ - { 0xd0000000, 0x08000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 */ - { 0xd0800000, 0x18000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 3 */ + { 0xd0000000, 0x08000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 when JP1 3-4 */ #endif { 0xdc000000, 0x10000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD */ SA1100_STD_IO_MAPPING @@ -104,7 +109,7 @@ * Here it would be wiser to simply assign a pointer to the appropriate * list, but io_desc is already declared as an array in "map.h". */ -struct map_desc io_desc[20] __initdata = { { 0, }, }; +struct map_desc io_desc[20] __initdata = {}; unsigned int io_desc_size; void __init select_sa1100_io_desc(void) @@ -118,6 +123,9 @@ } else if( machine_is_empeg() ) { memcpy( io_desc, empeg_io_desc, sizeof(empeg_io_desc) ); io_desc_size = SIZE(empeg_io_desc); + } else if( machine_is_graphicsclient() ) { + memcpy( io_desc, graphicsclient_io_desc, sizeof(graphicsclient_io_desc) ); + io_desc_size = SIZE(graphicsclient_io_desc); } else if( machine_is_thinclient() ) { memcpy( io_desc, thinclient_io_desc, sizeof(thinclient_io_desc) ); io_desc_size = SIZE(thinclient_io_desc); diff -u --recursive --new-file v2.3.99-pre7/linux/arch/arm/mm/proc-arm6,7.S linux/arch/arm/mm/proc-arm6,7.S --- v2.3.99-pre7/linux/arch/arm/mm/proc-arm6,7.S Sun Mar 19 18:35:30 2000 +++ linux/arch/arm/mm/proc-arm6,7.S Fri May 12 11:21:20 2000 @@ -254,9 +254,7 @@ ENTRY(cpu_arm6_proc_fin) ENTRY(cpu_arm7_proc_fin) - mrs r0, cpsr - orr r0, r0, #F_BIT | I_BIT - msr cpsr, r0 + msr cpsr_c, #F_BIT | I_BIT | SVC_MODE mov r0, #0x31 @ ....S..DP...M mcr p15, 0, r0, c1, c0, 0 @ disable caches mov pc, lr @@ -366,7 +364,8 @@ .section ".text.init", #alloc, #execinstr -__arm6_setup: mov r0, #0 +__arm6_setup: msr cpsr_c, #F_BIT | I_BIT | SVC_MODE + mov r0, #0 mcr p15, 0, r0, c7, c0 @ flush caches on v3 mcr p15, 0, r0, c5, c0 @ flush TLBs on v3 mcr p15, 0, r4, c2, c0 @ load page table pointer @@ -376,7 +375,8 @@ orr r0, r0, #0x100 mov pc, lr -__arm7_setup: mov r0, #0 +__arm7_setup: msr cpsr_c, #F_BIT | I_BIT | SVC_MODE + mov r0, #0 mcr p15, 0, r0, c7, c0 @ flush caches on v3 mcr p15, 0, r0, c5, c0 @ flush TLBs on v3 mcr p15, 0, r4, c2, c0 @ load page table pointer diff -u --recursive --new-file v2.3.99-pre7/linux/arch/arm/mm/proc-sa110.S linux/arch/arm/mm/proc-sa110.S --- v2.3.99-pre7/linux/arch/arm/mm/proc-sa110.S Wed Apr 26 16:34:06 2000 +++ linux/arch/arm/mm/proc-sa110.S Fri May 12 11:21:20 2000 @@ -423,9 +423,7 @@ ENTRY(cpu_sa110_proc_fin) stmfd sp!, {r1, lr} - mrs r0, cpsr - orr r0, r0, #F_BIT | I_BIT - msr cpsr, r0 + msr cpsr_c, #F_BIT | I_BIT | SVC_MODE bl cpu_sa110_flush_cache_all @ clean caches 1: mov r0, #0 mcr p15, 0, r0, c15, c2, 2 @ Disable clock switching @@ -437,9 +435,7 @@ ENTRY(cpu_sa1100_proc_fin) stmfd sp!, {r1, lr} - mrs r0, cpsr - orr r0, r0, #F_BIT | I_BIT - msr cpsr, r0 + msr cpsr_c, #F_BIT | I_BIT | SVC_MODE bl cpu_sa1100_flush_cache_all @ clean caches b 1b @@ -505,7 +501,8 @@ .section ".text.init", #alloc, #execinstr -__sa110_setup: mov r0, #0 +__sa110_setup: msr cpsr_c, #F_BIT | I_BIT | SVC_MODE + mov r0, #0 mcr p15, 0, r0, c7, c7 @ flush I,D caches on v4 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4 mcr p15, 0, r0, c8, c7 @ flush I,D TLBs on v4 diff -u --recursive --new-file v2.3.99-pre7/linux/arch/i386/defconfig linux/arch/i386/defconfig --- v2.3.99-pre7/linux/arch/i386/defconfig Thu May 11 15:30:05 2000 +++ linux/arch/i386/defconfig Fri May 12 12:15:20 2000 @@ -110,7 +110,8 @@ # CONFIG_BLK_DEV_LVM is not set # CONFIG_BLK_DEV_MD is not set # CONFIG_MD_LINEAR is not set -# CONFIG_MD_STRIPED is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_RAID15_DANGEROUS is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_INITRD is not set diff -u --recursive --new-file v2.3.99-pre7/linux/arch/ia64/tools/Makefile linux/arch/ia64/tools/Makefile --- v2.3.99-pre7/linux/arch/ia64/tools/Makefile Wed Apr 26 16:34:06 2000 +++ linux/arch/ia64/tools/Makefile Fri May 12 11:32:08 2000 @@ -1,8 +1,4 @@ -CFLAGS = -D__KERNEL__ -g -O2 -Wall -I$(TOPDIR)/include - -ifdef CONFIG_SMP - CFLAGS += -D__SMP__ -endif +CFLAGS = -g -O2 -Wall $(CPPFLAGS) TARGET = $(TOPDIR)/include/asm-ia64/offsets.h diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/Makefile linux/arch/s390/Makefile --- v2.3.99-pre7/linux/arch/s390/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/Makefile Fri May 12 11:41:44 2000 @@ -0,0 +1,68 @@ + +# s390/Makefile +# +# This file is included by the global makefile so that you can add your own +# architecture-specific flags and dependencies. Remember to do have actions +# for "archclean" and "archdep" for cleaning up and making dependencies for +# this architecture +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright (C) 1994 by Linus Torvalds +# + +LD=$(CROSS_COMPILE)ld -m elf_s390 +OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S +LDFLAGS=-e start +LINKFLAGS =-T $(TOPDIR)/arch/s390/vmlinux.lds $(LDFLAGS) + +CFLAGS_PIPE := -pipe +CFLAGS_NSR := -fno-strength-reduce +CFLAGS := $(CFLAGS) $(CFLAGS_PIPE) $(CFLAGS_NSR) + +HEAD := arch/s390/kernel/head.o arch/s390/kernel/init_task.o + +SUBDIRS := $(SUBDIRS) arch/s390/mm arch/s390/kernel arch/s390/lib \ + drivers/s390 +CORE_FILES := arch/s390/mm/mm.o arch/s390/kernel/kernel.o $(CORE_FILES) \ + drivers/s390/io.o +LIBS := $(TOPDIR)/arch/s390/lib/lib.a $(LIBS) $(TOPDIR)/arch/s390/lib/lib.a + +all: image listing + +listing: vmlinux + @$(MAKEBOOT) listing + +arch/s390/kernel: dummy + $(MAKE) linuxsubdirs SUBDIRS=arch/s390/kernel + +arch/s390/mm: dummy + $(MAKE) linuxsubdirs SUBDIRS=arch/s390/mm + +drivers/s390: dummy + $(MAKE) linuxsubdirs SUBDIRS=drivers/s390 + +MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot + +MAKESILO = $(MAKE) -C arch/$(ARCH)/tools/silo + +MAKEDASDFMT = $(MAKE) -C arch/$(ARCH)/tools/dasdfmt + +silo: + @$(MAKESILO) silo + +dasdfmt: + @$(MAKEDASDFMT) dasdfmt + +image: vmlinux + @$(MAKEBOOT) image + +archclean: + @$(MAKEBOOT) clean + +archmrproper: + +archdep: + @$(MAKEBOOT) dep diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/boot/Makefile linux/arch/s390/boot/Makefile --- v2.3.99-pre7/linux/arch/s390/boot/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/boot/Makefile Fri May 12 11:41:44 2000 @@ -0,0 +1,38 @@ +# +# Makefile for the linux s390-specific parts of the memory manager. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definition is now in the main makefile... + +OBJCOPY = $(CROSS_COMPILE)objcopy + +O_TARGET := +O_OBJS := + +include $(TOPDIR)/Rules.make + +.S.o: + $(CC) $(AFLAGS) -traditional -c $< -o $*.o + +%.lnk: %.o + $(LD) -Ttext 0x0 -o $@ $< + +%.boot: %.lnk + $(OBJCOPY) -O binary $< $@ + +image: $(CONFIGURE) $(TOPDIR)/vmlinux \ + iplfba.boot ipleckd.boot ipldump.boot + $(OBJCOPY) -O binary $(TOPDIR)/vmlinux image + $(NM) $(TOPDIR)/vmlinux | grep -v '\(compiled\)\|\( [aU] \)\|\(\.\)\|\(LASH[RL]DI\)' | sort > $(TOPDIR)/System.map + +listing: ../../../vmlinux + $(OBJDUMP) --disassemble --disassemble-all --disassemble-zeroes --reloc $(TOPDIR)/vmlinux > listing + +dep: + +clean: + rm -f image listing iplfba.boot ipleckd.boot ipldump.boot + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/boot/ipldump.S linux/arch/s390/boot/ipldump.S --- v2.3.99-pre7/linux/arch/s390/boot/ipldump.S Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/boot/ipldump.S Fri May 12 11:41:44 2000 @@ -0,0 +1,178 @@ +/* + * arch/s390/boot/ipldump.S + * + * S390 version + * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), + * + * Tape dump ipl record. Put it on a tape and ipl from it and it will + * write a dump of the real storage after the ipl record on that tape. + */ + +#include +#include + +#define IPL_BS 1024 + .org 0 + .long 0x00080000,0x80000000+_start # The first 24 bytes are loaded + .long 0x07000000,0x60000001 # by ipl to addresses 0-23. + .long 0x02000000,0x20000000+IPL_BS # (a PSW and two CCWs). + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 # svc old psw + .long 0x00000000,0x00000000 # program check old psw + .long 0x00000000,0x00000000 # machine check old psw + .long 0x00000000,0x00000000 # io old psw + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x000a0000,0x00000058 # external new psw + .long 0x000a0000,0x00000060 # svc new psw + .long 0x000a0000,0x00000068 # program check new psw + .long 0x000a0000,0x00000070 # machine check new psw + .long 0x00080000,0x80000000+.Lioint # io new psw + + .org 0x100 + .globl _start +_start: + l %r1,0xb8 # load ipl subchannel number +# +# find out memory size +# + mvc 104(8,0),.Lpcmem0 # setup program check handler + slr %r3,%r3 + lhi %r2,1 + sll %r2,20 +.Lloop0: + l %r0,0(%r3) # test page + ar %r3,%r2 # add 1M + jnm .Lloop0 # r1 < 0x80000000 -> loop +.Lchkmem0: + n %r3,.L4malign0 # align to multiples of 4M + st %r3,.Lmemsize # store memory size +.Lmemok: + +# +# first write a tape mark +# + bras %r14,.Ltapemark +# +# write real storage to tape +# + slr %r2,%r2 # start at address 0 + bras %r14,.Lwriter # load ramdisk +# +# write another tape mark +# + bras %r14,.Ltapemark +# +# everything written, stop processor +# + lpsw .Lstopped +# +# subroutine for writing to tape +# Paramters: +# R1 = device number +# R2 = start address +# R3 = length +.Lwriter: + st %r14,.Lldret + la %r12,.Lorbread # r12 = address of orb + la %r5,.Lirb # r5 = address of irb + st %r2,.Lccwwrite+4 # initialize CCW data addresses + lctl %c6,%c6,.Lcr6 + slr %r2,%r2 +.Lldlp: + lhi %r6,3 # 3 retries +.Lssch: + ssch 0(%r12) # write chunk of IPL_BS bytes + jnz .Llderr +.Lw4end: + bras %r14,.Lwait4io + tm 8(%r5),0x82 # do we have a problem ? + jnz .Lrecov + l %r0,.Lccwwrite+4 # update CCW data addresses + ahi %r0,IPL_BS + st %r0,.Lccwwrite+4 + clr %r0,%r3 # enough ? + jl .Lldlp +.Ldone: + l %r14,.Lldret + br %r14 # r2 contains the total size +.Lrecov: + bras %r14,.Lsense # do the sensing + brct %r6,.Lssch # dec. retry count & branch + j .Llderr +.Ltapemark: + st %r14,.Lldret + la %r12,.Lorbmark # r12 = address of orb + la %r5,.Lirb # r5 = address of irb + lctl %c6,%c6,.Lcr6 + ssch 0(%r12) # write a tape mark + jnz .Llderr + bras %r14,.Lwait4io + l %r14,.Lldret + br %r14 +# +# Sense subroutine +# +.Lsense: + st %r14,.Lsnsret + la %r7,.Lorbsense + ssch 0(%r7) # start sense command + jnz .Llderr + bras %r14,.Lwait4io + l %r14,.Lsnsret + tm 8(%r5),0x82 # do we have a problem ? + jnz .Llderr + br %r14 +# +# Wait for interrupt subroutine +# +.Lwait4io: + lpsw .Lwaitpsw +.Lioint: + c %r1,0xb8 # compare subchannel number + jne .Lwait4io + tsch 0(%r5) + slr %r0,%r0 + tm 8(%r5),0x82 # do we have a problem ? + jnz .Lwtexit + tm 8(%r5),0x04 # got device end ? + jz .Lwait4io +.Lwtexit: + br %r14 +.Llderr: + lpsw .Lcrash + + .align 8 +.Lorbread: + .long 0x00000000,0x0080ff00,.Lccwwrite + .align 8 +.Lorbsense: + .long 0x00000000,0x0080ff00,.Lccwsense + .align 8 +.Lorbmark: + .long 0x00000000,0x0080ff00,.Lccwmark + .align 8 +.Lccwwrite: + .long 0x01200000+IPL_BS,0x00000000 +.Lccwsense: + .long 0x04200001,0x00000000 +.Lccwmark: + .long 0x1f200001,0x00000000 +.Lwaitpsw: + .long 0x020a0000,0x80000000+.Lioint + +.Lirb: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +.Lcr6: .long 0xff000000 + .align 8 +.Lcrash:.long 0x000a0000,0x00000000 +.Lstopped: .long 0x000a0000,0x00001234 +.Lpcmem0:.long 0x00080000,0x80000000 + .Lchkmem0 +.L4malign0:.long 0xffc00000 +.Lmemsize:.long 0 +.Lldret:.long 0 +.Lsnsret: .long 0 + + .org IPL_BS + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/boot/ipleckd.S linux/arch/s390/boot/ipleckd.S --- v2.3.99-pre7/linux/arch/s390/boot/ipleckd.S Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/boot/ipleckd.S Fri May 12 11:41:44 2000 @@ -0,0 +1,299 @@ +# +# arch/s390/boot/ipleckd.S +# IPL record for 3380/3390 DASD +# +# S390 version +# Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation +# Author(s): Holger Smolinski +# +# +# FIXME: should use the countarea to determine the blocksize +# FIXME: should insert zeroes into memory when filling holes +# FIXME: calculate blkpertrack from rdc data and blksize + +# Usage of registers +# r1: ipl subchannel ( general use, dont overload without save/restore !) +# r10: +# r13: base register index to 0x0000 +# r14: callers address +# r15: temporary save register (we have no stack!) + +# storage layout: + +#include + + .org 0 +.psw: .long 0x00080000,0x80000000+_start +.ccw1: .long 0x06000000,0x00001000 # Re-Read enough of bootsector to start +.ccw2: .long 0x00000000,0x00000000 # read countarea of record 1 to s/w. + + .org 0x58 +.Lextn: .long 0x000a0000,0x00000000+.Lextn +.Lsvcn: .long 0x000a0000,0x00000000+.Lsvcn +.Lprgn: .long 0x00080000,0x00000000+.Lecs +.Lmcn: .long 0x000a0000,0x00000000+.Lmcn +.Lion: .long 0x00080000,0x80000000+.Lionewaddr + + .org 0xe0 +.Llstad:.long 0x00000000,0x00000000 # sectorno + ct of bootlist + + .org 0xf0 # Lets start now... +_start: .globl _start + l %r1,__LC_SUBCHANNEL_ID # get IPL-subchannel from lowcore + st %r1,__LC_IPLDEV # keep it for reipl + stsch .Lrdcdata + oi .Lrdcdata+5,0x84 # enable ssch and multipath mode +.Lecs: xi .Lrdcdata+27,0x01 # enable concurrent sense + msch .Lrdcdata + xi .Lprgn,6 # restore Wait and d/a bit in PCnew PSW + l %r2,.Lparm + mvc 0x0(8,%r2),.Lnull # set parmarea to null + lctl %c6,%c6,.Lc6 # enable all interrupts +.Lrdc: # read device characteristics + la %r6,.Lrdcccw + st %r6,.Lorb+8 # store cp-address to orb + bras %r15,.Lssch # start I/O + oi .Llodata+1,0x80 + lh %r5,.Lcountarea+6 # init r5 from countarea + stcm %r5,3,.Lrdccw+2 # and store into rd template *FIXME* + stcm %r5,3,.Llodata+14 # and store into lodata *FIXME* +.Lbootlist: + l %r2,.Llstad + l %r3,.Lblklst + lhi %r4,1 + bras %r14,.Lreadblks +.Lloader: + l %r10,.Lblklst # r10 is index to bootlist + lhi %r5,4 # r5: skip 4 blocks = firstpage.... +.Lkloop: + clc .Lnull(8),0(%r10) # test blocklist + jz .Lchkparm # end of list? + l %r2,0(%r10) # get startblock to r2 + slr %r4,%r4 # erase r4 + icm %r4,1,7(%r10) # get blockcount + slr %r3,%r3 # get address to r3 + icm %r3,0xe,4(%r10) + chi %r5,0 # still blocks to skip? + jz .Ldoread # no: start reading + cr %r5,%r4 # #skipblocks >= blockct? + jm .L007 # no: skip the blocks one by one +.L006: + sr %r5,%r4 # decrease number of blocks to skip + j .Lkcont # advance to next entry +.L007: + ahi %r2,1 # skip 1 block... + bctr %r4,0 # update blockct + ah %r3,.Lcountarea+6 # increment address + bct %r5,.L007 # 4 blocks skipped? +.Ldoread: + ltr %r2,%r2 # test startblock + jz .Lzeroes # startblocks is zero (hole) +.Ldiskread: + bras %r14,.Lreadblks + j .Lkcont +.Lzeroes: + lr %r2,%r3 +.L001: slr %r3,%r3 + icm %r3,3,.Lcountarea+6 # get blocksize + slr %r5,%r5 # no bytes to move +.L008: mvcle %r2,%r4,0 # fill zeroes to storage + jo .L008 # until block is filled + brct %r4,.L001 # skip to next block +.Lkcont: + ahi %r10,8 + j .Lkloop +.Lchkparm: + lm %r3,%r4,.Lstart # load .Lstart and .Lparm + clc 0x0(4,%r4),.Lnull + je .Lrunkern + mvc 0x480(128,%r3),0(%r4) # move 1k-0x80 to parmarea + mvc 0x500(256,%r3),0x80(%r4) + mvc 0x600(256,%r3),0x180(%r4) + mvc 0x700(256,%r3),0x280(%r4) +.Lrunkern: + lhi %r2,17 + sll %r2,12 + st %r1,0xc6c(%r2) # store iplsubchannel to lowcore + st %r1,0xc6c # store iplsubchannel to lowcore + br %r3 +# This function does the start IO +# r2: number of first block to read ( input by caller ) +# r3: address to read data to ( input by caller ) +# r4: number of blocks to read ( input by caller ) +# r5: destroyed +# r6: blocks per track ( input by caller ) +# r7: number of heads +# r8: +# r9: +# r10: +# r11: temporary register +# r12: local use for base address +# r13: base address for module +# r14: address of caller for subroutine +# r15: temporary save register (since we have no stack) +.Lreadblks: + la %r12,.Ldeccw + st %r12,8+.Lorb # store cpaddr to orb + ahi %r12,0x10 # increment r12 to point to rdccw + oi 1(%r12),0x40 # set CC in rd template + # first setup the read CCWs + lr %r15,%r4 # save number or blocks + slr %r7,%r7 + icm %r7,3,.Lrdcdata+14 # load heads to r7 + clc .Lrdcdata+3(2),.L3390 + jne .L010 # 3380 or 3390 ? + lhi %r6,12 # setup r6 correct! + j .L011 +.L010: + clc .Lrdcdata+3(2),.L9343 + jne .L013 + lhi %r6,9 + j .L011 +.L013: + lhi %r6,10 +.L011: + # loop for nbl times +.Lrdloop: + mvc 0(8,%r12),.Lrdccw # copy template to this ccw + st %r3,4(%r12) # store target address to this ccw + bct %r4,.L005 # decrement no of blks still to do + ni 1(%r12),0x3f # delete CC from last ccw + lr %r4,%r15 # restore number of blocks + # read CCWs are setup now + stcm %r4,3,.Llodata+2 # store blockno to lodata clears r4 + ar %r4,%r2 # r4 (clear): ebl = blk + nbl + bctr %r4,0 # decrement r4 ( last blk touched + srda %r2,32 # trk = blk / bpt, bot = blk % bpt + dr %r2,%r6 # r3: trk, r2: bot + ahi %r2,1 # bot++ ( we start counting at 1 ) + stcm %r2,1,.Llodata+12 # store bot to lodata + xr %r2,%r2 # cy = trk / heads, hd = trk % heads + dr %r2,%r7 # r3: cy, r2: hd + sll %r3,16 # combine to CCHH in r3 + or %r3,%r2 + st %r3,.Ldedata+8 # store cchh to dedata + st %r3,.Llodata+4 # store cchh to lodata + st %r3,.Llodata+8 # store cchh to lodata + lr %r15,%r5 # save r5 + srda %r4,32 # tr2 = ebl / bpt + dr %r4,%r6 # r5: tr2, r4: bot2 + xr %r4,%r4 # cy2 = tr2 / heads, hd2 = hd2 % heads + dr %r4,%r7 # r5: cy2, r4: hd2 + stcm %r5,3,.Ldedata+12 # store cy2,hd2 to dedata + stcm %r4,3,.Ldedata+14 # store cy2,hd2 to dedata + lr %r5,%r15 # restore r5 + # CCWs are setup now, arent they? + bras %r15,.Lssch # start I/O + br %r14 # return to caller +.L005: + ah %r3,.Lcountarea+6 # add blocksize to target address + ahi %r12,8 # add sizeof(ccw) to base address + j .Lrdloop +# end of function +# This function does the start IO +# r1: Subchannel number +# r8: ORB address +# r9: IRB address +.Lssch: + lhi %r13,10 # initialize retries +.L012: + ssch .Lorb # start I/O + jz .Ltpi # ok? + bras %r14,.Ldisab # error +.Ltpi: + lpsw .Lwaitpsw # load wait-PSW +.Lionewaddr: + c %r1,0xb8 # compare to ipl subhchannel + jnz .Ltpi # not equal: loop + clc 0xbc(4),.Lorb # cross check the intparm + jnz .Ltpi # not equal: loop + tsch .Lirb # get status + tm .Lirb+9,0xff # channel status ? + jz .L003 # CS == 0x00 + bras %r14,.Ldisab # error +.L003: + tm .Lirb+8,0xf3 # DS different from CE/DE + jz .L004 # ok ? + bct %r13,.L012 # retries <= 5 ? + bras %r14,.Ldisab # error +.L004: + tm .Lirb+8,0x04 # DE set? + jz .Ltpi # DE not set, loop +.Lsschend: + br %r15 # return to caller +# end of function +# In case of error goto disabled wait with %r14 containing the caller +.Ldisab: + st %r14,.Ldisabpsw+4 + lpsw .Ldisabpsw + +# FIXME pre-initialized data should be listed first +# NULLed storage can be taken from anywhere ;) +.Lblklst: + .long 0x00002000 + .align 8 +.Ldisabpsw: + .long 0x000a0000,0x00000000 +.Lwaitpsw: + .long 0x020a0000,0x00000000+.Ltpi +.Lorb: + .long 0x0049504c,0x0080ff00 # intparm is " IPL" +.Lc6: .long 0xff000000 +.Lstart: + .long 0x00010000 # do not separate .Lstart and .Lparm +.Lparm: + .long 0x00008000 # they are loaded with a LM +.L3390: + .word 0x3390 +.L9343: + .word 0x9343 +.Lnull: + .long 0x00000000,0x00000000 +.Lrdcdata: + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 +.Lirb: + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 +.Lcountarea: + .word 0x0000 # cyl; + .word 0x0000 # head; + .byte 0x00 # record; + .byte 0x00 # key length; + .word 0x0000 # data length == blocksize; +.Ldedata: + .long 0x40c00000,0x00000000 + .long 0x00000000,0x00000000 +.Llodata: + .long 0x06000001,0x00000000 + .long 0x00000000,0x01000000 + .long 0x12345678 + .org 0x7c8 +.Lrdcccw: # CCW read device characteristics + .long 0x64400040,0x00000000+.Lrdcdata + .long 0x63400010,0x00000000+.Ldedata + .long 0x47400010,0x00000000+.Llodata + .long 0x12000008,0x00000000+.Lcountarea +.Ldeccw: + .long 0x63400010,0x00000000+.Ldedata +.Lloccw: + .long 0x47400010,0x00000000+.Llodata +.Lrdccw: + .long 0x86400000,0x00000000 + .org 0x800 +# end of pre initialized data is here CCWarea follows +# from here we load 1k blocklist +# end of function + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/boot/iplfba.S linux/arch/s390/boot/iplfba.S --- v2.3.99-pre7/linux/arch/s390/boot/iplfba.S Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/boot/iplfba.S Fri May 12 11:41:44 2000 @@ -0,0 +1,131 @@ +# +# Ipl block for fba devices +# Copyright (C) 1998 IBM Corporation +# Author(s): Martin Schwidefsky +# +# startup for ipl at address 0 +# start with restart + +# The first 24 byes are loaded by ipl to addresses 0-23 (a PSW and two CCWs). +# The CCWs on 8-23 are used as a continuation of the implicit ipl channel +# program. The fba ipl loader only uses the CCW on 8-15 to load the first 512 +# byte block to location 0-511 (the reading starts again at block 0, byte 0). +# The second CCW is used to store the location of the load list. + .org 0 + .long 0x00080000,0x80000000+_start # The first 24 byte are loaded + .long 0x02000000,0x20000200 # by ipl to addresses 0-23. + .long 0x00000001,0x00000001 # (PSW, one CCW & loadlist info). + + .globl _start +_start: + basr %r13,0 +.LPG0: + l %r1,0xb8 # load ipl subchannel number + lhi %r2,0x200 # location for the loadlist + lm %r3,%r4,0x10 # blocknr and length of loadlist + bras %r14,.Lloader # load loadlist + + lhi %r11,0x400 + lhi %r12,0x200 # load address of loadlist + l %r3,0(%r12) # get first block number + l %r4,4(%r12) # get first block count + la %r12,8(%r12) + j .Llistloop + .org 0x50 +.Llistloop: + lr %r2,%r11 # load address + lr %r5,%r4 # block count + mhi %r5,512 + la %r11,0(%r5,%r11) # update load address + bras %r14,.Lloader # load chunk of the image + l %r3,0(%r12) # get next block number + icm %r4,15,4(%r12) # get next block count + la %r12,8(%r12) + jnz .Llistloop + +# +# everything loaded, go for it +# + l %r1,.Lstart-.LPG0(%r13) + br %r1 + +# +# subroutine for loading a sequence of block from fba +# %r2: load address (24 bit address) +# %r3: number of first block (unsigned long) +# %r4: number of blocks to load (unsigned short) +# + .org 0xC0 +.Lloader: + la %r5,.Llo-.LPG0(%r13) + sth %r4,2(%r5) # initialize block count + st %r3,4(%r5) # initialize block number + la %r5,.Lccws-.LPG0(%r13) + mhi %r4,512 + sth %r4,22(%r5) # initialize byte count + icm %r2,8,16(%r5) + st %r2,16(%r5) # initialize CCW data address + + slr %r2,%r2 + la %r3,.Lorb-.LPG0(%r13) # r2 = address of orb into r2 + la %r4,.Ltinfo-.LPG0(%r13) # r3 = address of tpi info block + la %r5,.Lirb-.LPG0(%r13) # r4 = address of irb + + lctl %c6,%c6,.Lc6-.LPG0(%r13) +.Lldlp: + ssch 0(%r3) # read blocks +.Ltpi: + tpi 0(%r4) # test pending interrupt + jz .Ltpi + c %r1,0(%r4) # compare subchannel number + jne .Ltpi + tsch 0(%r5) + slr %r0,%r0 + tm 8(%r5),0x82 # do we have a problem ? + jnz .Ldwpsw + tm 8(%r5),0x04 # got device end ? + jz .Ltpi +.Lexit: + br %r14 + + .align 8 +.Ldwpsw:.long 0x000a0000,0x00000000 +.Lorb: .long 0x00000000,0x0000ff00,.Lccws +.Ltinfo:.long 0 +.Lirb: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +.Lc6: .long 0xff000000 +.Lloadp:.long 0,0 +.Lparm: .long 0x10400 +.Lstart:.long 0x10000 + .align 8 +.Lccws: .long 0x63000000+.Lde,0x60000010 # define extent + .long 0x43000000+.Llo,0x60000008 # locate +# offset 1 in read CCW: data address (24 bit) +# offset 6 in read CCW: number of bytes (16 bit) + .long 0x42000000,0x20000000 # read +.Lde: .long 0x40000200,0x00000000 + .long 0x00000000,0x00001000 +# offset 2 in .Llo: block count (unsigned short) +# offset 4 in .Llo: block number (unsigned long) +.Llo: .long 0x06000000,0x00000000 + + .org 0x200 + .long 0x00000002,0x0000007f + .long 0x00000081,0x0000007f + .long 0x00000100,0x0000007f + .long 0x0000017f,0x0000007f + .long 0x000001fe,0x0000007f + .long 0x0000027d,0x0000007f + .long 0x000002fc,0x0000007f + .long 0x0000037b,0x0000007f + .long 0x000003fa,0x0000007f + .long 0x00000479,0x0000007f + .long 0x000004f8,0x0000007f + .long 0x00000577,0x0000007f + .long 0x000005f6,0x0000007f + .long 0x00000675,0x0000007f + .long 0x000006f4,0x0000007f + .long 0x00000773,0x0000003f + .long 0x00000000,0x00000000 + .org 0x400 + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/config.in linux/arch/s390/config.in --- v2.3.99-pre7/linux/arch/s390/config.in Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/config.in Fri May 12 11:41:44 2000 @@ -0,0 +1,75 @@ + +# For a description of the syntax of this configuration file, +# see the Configure script. +# + +define_bool CONFIG_UID16 y + +mainmenu_name "Linux Kernel Configuration" +define_bool CONFIG_ARCH_S390 y + +mainmenu_option next_comment +comment 'Code maturity level options' +bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL +endmenu + +mainmenu_option next_comment +comment 'Processor type and features' +bool 'Symmetric multi-processing support' CONFIG_SMP +bool 'IEEE FPU emulation' CONFIG_IEEEFPU_EMULATION +endmenu + +mainmenu_option next_comment +comment 'Loadable module support' +bool 'Enable loadable module support' CONFIG_MODULES +if [ "$CONFIG_MODULES" = "y" ]; then + bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS + bool 'Kernel module loader' CONFIG_KMOD +fi +endmenu + +mainmenu_option next_comment +comment 'General setup' +bool 'Fast IRQ handling' CONFIG_FAST_IRQ +bool 'Builtin IPL record support' CONFIG_IPL +if [ "$CONFIG_IPL" = "y" ]; then + choice 'IPL method generated into head.S' \ + "tape CONFIG_IPL_TAPE \ + vm_reader CONFIG_IPL_VM" tape +fi +bool 'Networking support' CONFIG_NET +bool 'System V IPC' CONFIG_SYSVIPC +bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT +bool 'Sysctl support' CONFIG_SYSCTL +tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF + +endmenu + +source drivers/s390/Config.in +bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS +if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then + int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256 +fi + +if [ "$CONFIG_NET" = "y" ]; then + source net/Config.in +fi + +source fs/Config.in + +# source drivers/char/Config.in + +mainmenu_option next_comment +comment 'Kernel hacking' + +#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC +bool 'Kernel profiling support' CONFIG_PROFILE +if [ "$CONFIG_PROFILE" = "y" ]; then + int ' Profile shift count' CONFIG_PROFILE_SHIFT 2 +fi +if [ "$CONFIG_CTC" = "y" ]; then + bool 'Remote GDB kernel debugging' CONFIG_REMOTE_DEBUG +fi +# this does not work. bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ +endmenu + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/defconfig linux/arch/s390/defconfig --- v2.3.99-pre7/linux/arch/s390/defconfig Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/defconfig Fri May 12 11:41:44 2000 @@ -0,0 +1,178 @@ +# +# Automatically generated by make menuconfig: don't edit +# +CONFIG_UID16=y +CONFIG_ARCH_S390=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# Processor type and features +# +CONFIG_SMP=y +CONFIG_IEEEFPU_EMULATION=y + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +# CONFIG_KMOD is not set + +# +# General setup +# +CONFIG_FAST_IRQ=y +CONFIG_IPL=y +# CONFIG_IPL_TAPE is not set +CONFIG_IPL_VM=y +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_BINFMT_ELF=y + +# +# S/390 block device drivers +# +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_MD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_MDISK is not set +CONFIG_DASD=y +CONFIG_DASD_ECKD=y +# CONFIG_DASD_MDSK is not set + +# +# S/390 Network device support +# +# CONFIG_CHANDEV is not set +CONFIG_NETDEVICES=y +CONFIG_CTC=y +CONFIG_IUCV=y +# CONFIG_DUMMY is not set +CONFIG_NET_ETHERNET=y +CONFIG_TR=y +# CONFIG_FDDI is not set + +# +# S/390 Terminal and Console options +# +CONFIG_3215=y +CONFIG_3215_CONSOLE=y +CONFIG_HWC=y +CONFIG_HWC_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK=y +# CONFIG_RTNETLINK is not set +# CONFIG_NETLINK_DEV is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_IP_ROUTER is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_ALIAS is not set +# CONFIG_SYN_COOKIES is not set +CONFIG_SKB_LARGE=y +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_DECNET is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_BRIDGE is not set +# CONFIG_LLC is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_MINIX_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_DEBUG is not set +# CONFIG_DEVPTS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +CONFIG_NFS_FS=y +# CONFIG_ROOT_NFS is not set +CONFIG_NFSD=y +# CONFIG_NFSD_V3 is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +CONFIG_IBM_PARTITION=y +# CONFIG_MAC_PARTITION is not set +# CONFIG_MSDOS_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_NLS is not set + +# +# Kernel hacking +# +# CONFIG_PROFILE is not set +# CONFIG_REMOTE_DEBUG is not set diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/Makefile linux/arch/s390/kernel/Makefile --- v2.3.99-pre7/linux/arch/s390/kernel/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/Makefile Fri May 12 11:41:44 2000 @@ -0,0 +1,54 @@ +# +# Makefile for the linux kernel. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main makefile... + +.S.o: + $(CC) $(AFLAGS) -traditional -c $< -o $*.o + +all: kernel.o head.o init_task.o + +O_TARGET := kernel.o +O_OBJS := lowcore.o entry.o bitmap.o traps.o time.o process.o irq.o \ + setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ + semaphore.o s390fpu.o s390io.o s390mach.o s390dyn.o reipl.o +OX_OBJS := s390_ksyms.o +MX_OBJS := + +ifdef CONFIG_SMP +O_OBJS += smp.o +endif + +ifdef CONFIG_PCI +O_OBJS += bios32.o +endif + +ifdef CONFIG_MCA +O_OBJS += mca.o +endif + +ifeq ($(CONFIG_MTRR),y) +OX_OBJS += mtrr.o +else + ifeq ($(CONFIG_MTRR),m) + MX_OBJS += mtrr.o + endif +endif + +ifeq ($(CONFIG_IEEEFPU_EMULATION),y) + O_OBJS += mathemu.o floatlib.o +endif + +# +# Kernel debugging +# +ifdef CONFIG_REMOTE_DEBUG +O_OBJS += gdb-stub.o #gdb-low.o +endif + +include $(TOPDIR)/Rules.make + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/bitmap.S linux/arch/s390/kernel/bitmap.S --- v2.3.99-pre7/linux/arch/s390/kernel/bitmap.S Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/bitmap.S Fri May 12 11:41:44 2000 @@ -0,0 +1,37 @@ +/* + * arch/s390/kernel/bitmap.S + * Bitmaps for set_bit, clear_bit, test_and_set_bit, ... + * See include/asm-s390/{bitops.h|posix_types.h} for details + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), + */ + + .globl _oi_bitmap +_oi_bitmap: + .byte 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80 + + .globl _ni_bitmap +_ni_bitmap: + .byte 0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F + + .globl _zb_findmap +_zb_findmap: + .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4 + .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5 + .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4 + .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6 + .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4 + .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5 + .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4 + .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7 + .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4 + .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5 + .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4 + .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6 + .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4 + .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5 + .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4 + .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,8 + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/cpcmd.c linux/arch/s390/kernel/cpcmd.c --- v2.3.99-pre7/linux/arch/s390/kernel/cpcmd.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/cpcmd.c Fri May 12 11:41:44 2000 @@ -0,0 +1,45 @@ +/* + * arch/s390/kernel/cpcmd.c + * + * S390 version + * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), + */ + +#include +#include +#include +#include + +void cpcmd(char *cmd, char *response, int rlen) +{ + const int mask = 0x40000000L; + char obuffer[128]; + int olen; + + olen = strlen(cmd); + strcpy(obuffer, cmd); + ASCEBC(obuffer,olen); + + if (response != NULL && rlen > 0) { + asm volatile ("LRA 2,0(0,%0)\n\t" + "LR 4,%1\n\t" + "O 4,%4\n\t" + "LRA 3,0(0,%2)\n\t" + "LR 5,%3\n\t" + ".long 0x83240008 # Diagnose 83\n\t" + : /* no output */ + : "a" (obuffer), "d" (olen), + "a" (response), "d" (rlen), "m" (mask) + : "2", "3", "4", "5" ); + EBCASC(response, rlen); + } else { + asm volatile ("LRA 2,0(0,%0)\n\t" + "LR 3,%1\n\t" + ".long 0x83230008 # Diagnose 83\n\t" + : /* no output */ + : "a" (obuffer), "d" (olen) + : "2", "3" ); + } +} + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/cpcmd.h linux/arch/s390/kernel/cpcmd.h --- v2.3.99-pre7/linux/arch/s390/kernel/cpcmd.h Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/cpcmd.h Fri May 12 11:41:44 2000 @@ -0,0 +1,14 @@ +/* + * arch/s390/kernel/cpcmd.h + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), + */ + +#ifndef __CPCMD__ +#define __CPCMD__ + +extern void cpcmd(char *cmd, char *response, int rlen); + +#endif diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/ebcdic.c linux/arch/s390/kernel/ebcdic.c --- v2.3.99-pre7/linux/arch/s390/kernel/ebcdic.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/ebcdic.c Fri May 12 11:41:44 2000 @@ -0,0 +1,242 @@ +/* + * arch/s390/kernel/ebcdic.c + * ECBDIC -> ASCII, ASCII -> ECBDIC, + * upper to lower case (EBCDIC) conversion tables. + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Schwidefsky + * Martin Peschke + */ + +#include + +/* + * ASCII (IBM PC 437) -> EBCDIC 037 + */ +__u8 _ascebc[256] = +{ + /*00 NUL SOH STX ETX EOT ENQ ACK BEL */ + 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, + /*08 BS HT LF VT FF CR SO SI */ + /* ->NL */ + 0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + /*10 DLE DC1 DC2 DC3 DC4 NAK SYN ETB */ + 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26, + /*18 CAN EM SUB ESC FS GS RS US */ + /* ->IGS ->IRS ->IUS */ + 0x18, 0x19, 0x3F, 0x27, 0x22, 0x1D, 0x1E, 0x1F, + /*20 SP ! " # $ % & ' */ + 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, + /*28 ( ) * + , - . / */ + 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, + /*30 0 1 2 3 4 5 6 7 */ + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, + /*38 8 9 : ; < = > ? */ + 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F, + /*40 @ A B C D E F G */ + 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + /*48 H I J K L M N O */ + 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, + /*50 P Q R S T U V W */ + 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, + /*58 X Y Z [ \ ] ^ _ */ + 0xE7, 0xE8, 0xE9, 0xBA, 0xE0, 0xBB, 0xB0, 0x6D, + /*60 ` a b c d e f g */ + 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + /*68 h i j k l m n o */ + 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, + /*70 p q r s t u v w */ + 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + /*78 x y z { | } ~ DL */ + 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07, + /*80*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*88*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*90*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*98*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*A0*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*A8*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*B0*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*B8*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*C0*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*C8*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*D0*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*D8*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*E0 sz */ + 0x3F, 0x59, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*E8*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*F0*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*F8*/ + 0x90, 0x3F, 0x3F, 0x3F, 0x3F, 0xEA, 0x3F, 0xFF +}; + +/* + * EBCDIC 037 -> ASCII (IBM PC 437) + */ +__u8 _ebcasc[256] = +{ + /* 0x00 NUL SOH STX ETX *SEL HT *RNL DEL */ + 0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F, + /* 0x08 -GE -SPS -RPT VT FF CR SO SI */ + 0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + /* 0x10 DLE DC1 DC2 DC3 -RES -NL BS -POC + -ENP ->LF */ + 0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07, + /* 0x18 CAN EM -UBS -CU1 -IFS -IGS -IRS -ITB + -IUS */ + 0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + /* 0x20 -DS -SOS FS -WUS -BYP LF ETB ESC + -INP */ + 0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B, + /* 0x28 -SA -SFE -SM -CSP -MFA ENQ ACK BEL + -SW */ + 0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07, + /* 0x30 ---- ---- SYN -IR -PP -TRN -NBS EOT */ + 0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04, + /* 0x38 -SBS -IT -RFF -CU3 DC4 NAK ---- SUB */ + 0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A, + /* 0x40 SP RSP ä ---- */ + 0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86, + /* 0x48 . < ( + | */ + 0x87, 0xA4, 0x9B, 0x2E, 0x3C, 0x28, 0x2B, 0x7C, + /* 0x50 & ---- */ + 0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07, + /* 0x58 ß ! $ * ) ; */ + 0x8D, 0xE1, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAA, + /* 0x60 - / ---- Ä ---- ---- ---- */ + 0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F, + /* 0x68 ---- , % _ > ? */ + 0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, + /* 0x70 ---- ---- ---- ---- ---- ---- ---- */ + 0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + /* 0x78 * ` : # @ ' = " */ + 0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, + /* 0x80 * a b c d e f g */ + 0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + /* 0x88 h i ---- ---- ---- */ + 0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1, + /* 0x90 ° j k l m n o p */ + 0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, + /* 0x98 q r ---- ---- */ + 0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07, + /* 0xA0 ~ s t u v w x */ + 0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + /* 0xA8 y z ---- ---- ---- ---- */ + 0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07, + /* 0xB0 ^ ---- § ---- */ + 0x5E, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC, + /* 0xB8 ---- [ ] ---- ---- ---- ---- */ + 0xAB, 0x07, 0x5B, 0x5D, 0x07, 0x07, 0x07, 0x07, + /* 0xC0 { A B C D E F G */ + 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + /* 0xC8 H I ---- ö ---- */ + 0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07, + /* 0xD0 } J K L M N O P */ + 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, + /* 0xD8 Q R ---- ü */ + 0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98, + /* 0xE0 \ S T U V W X */ + 0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + /* 0xE8 Y Z ---- Ö ---- ---- ---- */ + 0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07, + /* 0xF0 0 1 2 3 4 5 6 7 */ + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + /* 0xF8 8 9 ---- ---- Ü ---- ---- ---- */ + 0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07 +}; + + +/* + * EBCDIC 037 conversion table: + * from upper to lower case + */ +__u8 _ebc_tolower[256] = +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, + 0x60, 0x61, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, + 0x70, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9C, 0x9F, + 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, + 0xA8, 0xA9, 0xAA, 0xAB, 0x8C, 0x8D, 0x8E, 0xAF, + 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, + 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, + 0xC0, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, + 0xD0, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, + 0xE0, 0xE1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, + 0xA8, 0xA9, 0xEA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, + 0xF8, 0xF9, 0xFA, 0xDB, 0xDC, 0xDD, 0xDE, 0xFF +}; + + +/* + * EBCDIC 037 conversion table: + * from lower to upper case + */ +__u8 _ebc_toupper[256] = +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, + 0x40, 0x41, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, + 0x50, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, + 0x80, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0x8A, 0x8B, 0xAC, 0xAD, 0xAE, 0x8F, + 0x90, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, + 0xD8, 0xD9, 0x9A, 0x9B, 0x9E, 0x9D, 0x9E, 0x9F, + 0xA0, 0xA1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, + 0xE8, 0xE9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, + 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, + 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0xCA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, + 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, + 0xD8, 0xD9, 0xDA, 0xFB, 0xFC, 0xFD, 0xFE, 0xDF, + 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, + 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, + 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF +}; diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/entry.S linux/arch/s390/kernel/entry.S --- v2.3.99-pre7/linux/arch/s390/kernel/entry.S Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/entry.S Fri May 12 11:41:44 2000 @@ -0,0 +1,917 @@ +/* + * arch/s390/kernel/entry.S + * S390 low-level entry points. + * + * S390 version + * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), + * Hartmut Penner (hp@de.ibm.com), + * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), + */ + +#include +#include +#include +#include +#include +#define ASSEMBLY +#include +#include + + +/* + * stack layout for the system_call stack entry + * Martin please don't modify these back to hard coded values + * You know how bad I'm at mental arithmetic DJB & it gives + * me grief when I modify the pt_regs + */ +SP_PTREGS = STACK_FRAME_OVERHEAD +SP_PSW = SP_PTREGS +SP_R0 = (SP_PSW+PSW_MASK_SIZE+PSW_ADDR_SIZE) +SP_R1 = (SP_R0+GPR_SIZE) +SP_R2 = (SP_R1+GPR_SIZE) +SP_R3 = (SP_R2+GPR_SIZE) +SP_R4 = (SP_R3+GPR_SIZE) +SP_R5 = (SP_R4+GPR_SIZE) +SP_R6 = (SP_R5+GPR_SIZE) +SP_R7 = (SP_R6+GPR_SIZE) +SP_R8 = (SP_R7+GPR_SIZE) +SP_R9 = (SP_R8+GPR_SIZE) +SP_RA = (SP_R9+GPR_SIZE) +SP_RB = (SP_RA+GPR_SIZE) +SP_RC = (SP_RB+GPR_SIZE) +SP_RD = (SP_RC+GPR_SIZE) +SP_RE = (SP_RD+GPR_SIZE) +SP_RF = (SP_RE+GPR_SIZE) +SP_AREGS = (SP_RF+GPR_SIZE) +SP_ORIG_R2 = (SP_AREGS+(NUM_ACRS*ACR_SIZE)) +SP_TRAP = (SP_ORIG_R2+GPR_SIZE) +#if CONFIG_REMOTE_DEBUG +SP_CRREGS = (SP_TRAP+4) +/* fpu registers are saved & restored by the gdb stub itself */ +SP_FPC = (SP_CRREGS+(NUM_CRS*CR_SIZE)) +SP_FPRS = (SP_FPC+FPC_SIZE+FPC_PAD_SIZE) +/* SP_PGM_OLD_ILC etc are not part of pt_regs & they are not + defined in ptrace.h but space is needed for this too */ +SP_PGM_OLD_ILC= (SP_FPRS+(NUM_FPRS*FPR_SIZE)) +#else +SP_PGM_OLD_ILC= (SP_TRAP+4) +#endif +SP_SVC_STEP = (SP_PGM_OLD_ILC+4) +SP_SIZE = (SP_SVC_STEP+4) +/* + * these defines are offsets into the thread_struct + */ +_TSS_PTREGS = 0 +_TSS_FPRS = (_TSS_PTREGS+8) +_TSS_AR2 = (_TSS_FPRS+136) +_TSS_AR4 = (_TSS_AR2+4) +_TSS_KSP = (_TSS_AR4+4) +_TSS_USERSEG = (_TSS_KSP+4) +_TSS_ERROR = (_TSS_USERSEG+4) +_TSS_PROT = (_TSS_ERROR+4) +_TSS_TRAP = (_TSS_PROT+4) +_TSS_MM = (_TSS_TRAP+4) +_TSS_PER = (_TSS_MM+8) + +/* + * these are offsets into the task-struct. + */ +state = 0 +flags = 4 +sigpending = 8 +need_resched = 24 +processor = 60 + +/* PSW related defines */ +disable = 0xFC +enable = 0x03 +daton = 0x04 + + +#if 0 +/* some code left lying around in case we need a + * printk for debugging purposes + */ + sysc_printk: .long printk + sysc_msg: .string "<2>r15 %X\n" + .align 4 + +# basr %r13,0 + l %r0,SP_PSW+4(%r15) + sll %r0,1 + chi %r0,0 + jnz sysc_dn + l %r9,sysc_printk-sysc_lit(%r13) + la %r2,sysc_msg-sysc_lit(%r13) + lr %r3,%r15 + basr %r14,%r9 +sysc_dn: +#endif + +/* + * Register usage in interrupt handlers: + * R9 - pointer to current task structure + * R13 - pointer to literal pool + * R14 - return register for function calls + * R15 - kernel stack pointer + */ + +#define SAVE_ALL(psworg) \ + st %r15,__LC_SAVE_AREA ; \ + tm psworg+1,0x01 ; /* test problem state bit */ \ + jz 0f ; /* skip stack setup save */ \ + l %r15,__LC_KERNEL_STACK ; /* problem state -> load ksp */ \ +0: ahi %r15,-SP_SIZE ; /* make room for registers & psw */ \ + srl %r15,3 ; \ + sll %r15,3 ; /* align stack pointer to 8 */ \ + stm %r0,%r14,SP_R0(%r15) ; /* store gprs 0-14 to kernel stack */ \ + st %r2,SP_ORIG_R2(%r15) ; /* store original content of gpr 2 */ \ + mvc SP_RF(4,%r15),__LC_SAVE_AREA ; /* move R15 to stack */ \ + stam %a0,%a15,SP_AREGS(%r15) ; /* store access registers to kst. */ \ + mvc SP_PSW(8,%r15),psworg ; /* move user PSW to stack */ \ + lhi %r0,psworg ; /* store trap indication */ \ + st %r0,SP_TRAP(%r15) ; \ + xc 0(4,%r15),0(%r15) ; /* clear back chain */ \ + tm psworg+1,0x01 ; /* kmod.c .wishes the set_fs & gs */ \ + jz 1f ; /* to work across syscalls */ \ + slr %r0,%r0 ; \ + sar %a2,%r0 ; /* set ac.reg. 2 to primary space */ \ + lhi %r0,1 ; \ + sar %a4,%r0 ; /* set access reg. 4 to home space */ \ +1: + +#define RESTORE_ALL \ + mvc __LC_RETURN_PSW(8,0),SP_PSW(%r15) ; /* move user PSW to lowcore */ \ + lam %a0,%a15,SP_AREGS(%r15) ; /* load the access registers */ \ + lm %r0,%r15,SP_R0(%r15) ; /* load gprs 0-15 of user */ \ + ni __LC_RETURN_PSW+1(0),0xfd ; /* clear wait state bit */ \ + lpsw __LC_RETURN_PSW /* back to caller */ + +#define GET_CURRENT /* load pointer to task_struct to R9 */ \ + lhi %r9,-8192 ; \ + nr %r9,15 + + +/* + * Scheduler resume function, called by switch_to + * grp2 = (thread_struct *) prev->tss + * grp3 = (thread_struct *) next->tss + * Returns: + * gpr2 = prev + */ + .globl resume +resume: + l %r4,_TSS_PTREGS(%r3) + tm SP_PSW-SP_PTREGS(%r4),0x40 # is the new process using per ? + jz RES_DN1 # if not we're fine + stctl %r9,%r11,24(%r15) # We are using per stuff + clc _TSS_PER(12,%r3),24(%r15) + je RES_DN1 # we got away without bashing TLB's + lctl %c9,%c11,_TSS_PER(%r3) # Nope we didn't +RES_DN1: + stm %r6,%r15,24(%r15) # store resume registers of prev task + st %r15,_TSS_KSP(%r2) # store kernel stack ptr to prev->tss.ksp + lhi %r0,-8192 + nr %r0,%r15 + l %r15,_TSS_KSP(%r3) # load kernel stack ptr from next->tss.ksp + lhi %r1,8191 + or %r1,%r15 + ahi %r1,1 + st %r1,__LC_KERNEL_STACK # __LC_KERNEL_STACK = new kernel stack + stam %a2,%a2,_TSS_AR2(%r2) # store kernel access reg. 2 + stam %a4,%a4,_TSS_AR4(%r2) # store kernel access reg. 4 + lam %a2,%a2,_TSS_AR2(%r3) # load kernel access reg. 2 + lam %a4,%a4,_TSS_AR4(%r3) # load kernel access reg. 4 + lr %r2,%r0 # return task_struct of last task + lm %r6,%r15,24(%r15) # load resume registers of next task + br %r14 + +/* + * SVC interrupt handler routine. System calls are synchronous events and + * are executed with interrupts enabled. + */ + +sysc_lit: + sysc_softirq_state: .long softirq_state + sysc_do_signal: .long do_signal + sysc_do_softirq: .long do_softirq + sysc_schedule: .long schedule + sysc_trace: .long syscall_trace +#ifdef CONFIG_SMP + sysc_schedtail: .long schedule_tail +#endif + sysc_clone: .long sys_clone + sysc_fork: .long sys_fork + sysc_vfork: .long sys_vfork + sysc_sigreturn: .long sys_sigreturn + sysc_rt_sigreturn: .long sys_rt_sigreturn + sysc_execve: .long sys_execve + sysc_sigsuspend: .long sys_sigsuspend + sysc_rt_sigsuspend: .long sys_rt_sigsuspend + + .globl system_call +system_call: + SAVE_ALL(0x20) + XC SP_SVC_STEP(4,%r15),SP_SVC_STEP(%r15) +pgm_system_call: + basr %r13,0 + ahi %r13,sysc_lit-. # setup base pointer R13 to sysc_lit + slr %r8,%r8 # gpr 8 is call save (-> tracesys) + ic %r8,0x8B # get svc number from lowcore + stosm 24(%r15),0x03 # reenable interrupts + GET_CURRENT # load pointer to task_struct to R9 + sll %r8,2 + l %r8,sys_call_table-sysc_lit(8,%r13) # get address of system call + tm flags+3(%r9),0x20 # PF_TRACESYS + jnz sysc_tracesys + basr %r14,%r8 # call sys_xxxx + st %r2,SP_R2(%r15) # store return value (change R2 on stack) + # ATTENTION: check sys_execve_glue before + # changing anything here !! + +sysc_return: + GET_CURRENT # load pointer to task_struct to R9 + tm SP_PSW+1(%r15),0x01 # returning to user ? + jno sysc_leave # no-> skip bottom half, resched & signal +# +# check, if bottom-half has to be done +# +#ifdef CONFIG_SMP + l %r1,processor(%r9) # get processor index + sll %r1,5 + al %r1,sysc_softirq_state-sysc_lit(%r13) + l %r0,0(%r1) # get softirq_state[cpu].active + n %r0,4(%r1) # and it with softirq_state[cpu].mask +#else + l %r1,sysc_softirq_state-sysc_lit(%r13) + l %r0,0(%r1) # get softirq_state.active + n %r0,4(%r1) # and it with softirq_state.mask +#endif + jnz sysc_handle_bottom_half +# +# check, if reschedule is needed +# +sysc_return_bh: + icm %r0,15,need_resched(%r9) # get need_resched from task_struct + jnz sysc_reschedule + icm %r0,15,sigpending(%r9) # get sigpending from task_struct + jnz sysc_signal_return +sysc_leave: + icm %r0,15,SP_SVC_STEP(%r15) # get sigpending from task_struct + jnz pgm_svcret + stnsm 24(%r15),disable # disable I/O and ext. interrupts + RESTORE_ALL + +# +# call do_signal before return +# +sysc_signal_return: + la %r2,SP_PTREGS(%r15) # load pt_regs + sr %r3,%r3 # clear *oldset + l %r1,sysc_do_signal-sysc_lit(%r13) + la %r14,sysc_leave-sysc_lit(%r13) + br %r1 # return point is sysc_leave + +# +# call trace before and after sys_call +# +sysc_tracesys: + l %r1,sysc_trace-sysc_lit(%r13) + lhi %r2,-ENOSYS + st %r2,SP_R2(%r15) # give sysc_trace an -ENOSYS retval + basr %r14,%r1 + lm %r3,%r6,SP_R3(%r15) + l %r2,SP_ORIG_R2(%r15) + basr %r14,%r8 # call sys_xxx + st %r2,SP_R2(%r15) # store return value + l %r1,sysc_trace-sysc_lit(%r13) + la %r14,sysc_return-sysc_lit(%r13) + br %r1 # return point is sysc_return + + +# +# call do_softirq and return from syscall, if interrupt-level +# is zero +# +sysc_handle_bottom_half: + l %r1,sysc_do_softirq-sysc_lit(%r13) + la %r14,sysc_return_bh-sysc_lit(%r13) + br %r1 # call do_softirq + +# +# call schedule with sysc_return as return-address +# +sysc_reschedule: + l %r1,sysc_schedule-sysc_lit(%r13) + la %r14,sysc_return-sysc_lit(%r13) + br %r1 # call scheduler, return to sysc_return + +# +# a new process exits the kernel with ret_from_fork +# + .globl ret_from_fork +ret_from_fork: + basr %r13,0 + ahi %r13,sysc_lit-. # setup base pointer R13 to $SYSCDAT + GET_CURRENT # load pointer to task_struct to R9 + stosm 24(%r15),0x03 # reenable interrupts + sr %r0,%r0 # child returns 0 + st %r0,SP_R2(%r15) # store return value (change R2 on stack) +#ifdef CONFIG_SMP + l %r1,sysc_schedtail-sysc_lit(%r13) + la %r14,sysc_return-sysc_lit(%r13) + br %r1 # call schedule_tail, return to sysc_return +#else + j sysc_return +#endif + +# +# clone, fork, vfork, exec and sigreturn need glue, +# because they all expect pt_regs as parameter, +# but are called with different parameter. +# return-address is set up above +# +sys_clone_glue: + la %r2,SP_PTREGS(%r15) # load pt_regs + l %r1,sysc_clone-sysc_lit(%r13) + br %r1 # branch to sys_clone + +sys_fork_glue: + la %r2,SP_PTREGS(%r15) # load pt_regs + l %r1,sysc_fork-sysc_lit(%r13) + br %r1 # branch to sys_fork + +sys_vfork_glue: + la %r2,SP_PTREGS(%r15) # load pt_regs + l %r1,sysc_vfork-sysc_lit(%r13) + br %r1 # branch to sys_vfork + +sys_execve_glue: + la %r2,SP_PTREGS(%r15) # load pt_regs + l %r1,sysc_execve-sysc_lit(%r13) + lr %r12,%r14 # save return address + basr %r14,%r1 # call sys_execve + ltr %r2,%r2 # check if execve failed + bnz 0(%r12) # it did fail -> store result in gpr2 + b 4(%r12) # SKIP ST 2,SP_R2(15) after BASR 14,8 + # in system_call/sysc_tracesys + +sys_sigreturn_glue: + la %r2,SP_PTREGS(%r15) # load pt_regs as parameter + l %r1,sysc_sigreturn-sysc_lit(%r13) + br %r1 # branch to sys_sigreturn + +sys_rt_sigreturn_glue: + la %r2,SP_PTREGS(%r15) # load pt_regs as parameter + l %r1,sysc_rt_sigreturn-sysc_lit(%r13) + br %r1 # branch to sys_sigreturn + +# +# sigsuspend and rt_sigsuspend need pt_regs as an additional +# parameter and they have to skip the store of %r2 into the +# user register %r2 because the return value was set in +# sigsuspend and rt_sigsuspend already and must not be overwritten! +# + +sys_sigsuspend_glue: + lr %r5,%r4 # move mask back + lr %r4,%r3 # move history1 parameter + lr %r3,%r2 # move history0 parameter + la %r2,SP_PTREGS(%r15) # load pt_regs as first parameter + l %r1,sysc_sigsuspend-sysc_lit(%r13) + la %r14,4(%r14) # skip store of return value + br %r1 # branch to sys_sigsuspend + +sys_rt_sigsuspend_glue: + lr %r4,%r3 # move sigsetsize parameter + lr %r3,%r2 # move unewset parameter + la %r2,SP_PTREGS(%r15) # load pt_regs as first parameter + l %r1,sysc_rt_sigsuspend-sysc_lit(%r13) + la %r14,4(%r14) # skip store of return value + br %r1 # branch to sys_rt_sigsuspend + + .globl sys_call_table +sys_call_table: + .long sys_ni_syscall /* 0 */ + .long sys_exit + .long sys_fork_glue + .long sys_read + .long sys_write + .long sys_open /* 5 */ + .long sys_close + .long sys_ni_syscall /* old waitpid syscall holder */ + .long sys_creat + .long sys_link + .long sys_unlink /* 10 */ + .long sys_execve_glue + .long sys_chdir + .long sys_time + .long sys_mknod + .long sys_chmod /* 15 */ + .long sys_lchown16 + .long sys_ni_syscall /* old break syscall holder */ + .long sys_ni_syscall /* old stat syscall holder */ + .long sys_lseek + .long sys_getpid /* 20 */ + .long sys_mount + .long sys_oldumount + .long sys_setuid16 + .long sys_getuid16 + .long sys_stime /* 25 */ + .long sys_ptrace + .long sys_alarm + .long sys_ni_syscall /* old fstat syscall holder */ + .long sys_pause + .long sys_utime /* 30 */ + .long sys_ni_syscall /* old stty syscall holder */ + .long sys_ni_syscall /* old gtty syscall holder */ + .long sys_access + .long sys_nice + .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */ + .long sys_sync + .long sys_kill + .long sys_rename + .long sys_mkdir + .long sys_rmdir /* 40 */ + .long sys_dup + .long sys_pipe + .long sys_times + .long sys_ni_syscall /* old prof syscall holder */ + .long sys_brk /* 45 */ + .long sys_setgid16 + .long sys_getgid16 + .long sys_signal + .long sys_geteuid16 + .long sys_getegid16 /* 50 */ + .long sys_acct + .long sys_umount + .long sys_ni_syscall /* old lock syscall holder */ + .long sys_ioctl + .long sys_fcntl /* 55 */ + .long sys_ni_syscall /* old mpx syscall holder */ + .long sys_setpgid + .long sys_ni_syscall /* old ulimit syscall holder */ + .long sys_ni_syscall /* old uname syscall holder */ + .long sys_umask /* 60 */ + .long sys_chroot + .long sys_ustat + .long sys_dup2 + .long sys_getppid + .long sys_getpgrp /* 65 */ + .long sys_setsid + .long sys_sigaction + .long sys_ni_syscall /* old sgetmask syscall holder */ + .long sys_ni_syscall /* old ssetmask syscall holder */ + .long sys_setreuid16 /* 70 */ + .long sys_setregid16 + .long sys_sigsuspend_glue + .long sys_sigpending + .long sys_sethostname + .long sys_setrlimit /* 75 */ + .long sys_getrlimit + .long sys_getrusage + .long sys_gettimeofday + .long sys_settimeofday + .long sys_getgroups16 /* 80 */ + .long sys_setgroups16 + .long sys_ni_syscall /* old select syscall holder */ + .long sys_symlink + .long sys_ni_syscall /* old lstat syscall holder */ + .long sys_readlink /* 85 */ + .long sys_uselib + .long sys_swapon + .long sys_reboot + .long sys_ni_syscall /* old readdir syscall holder */ + .long old_mmap /* 90 */ + .long sys_munmap + .long sys_truncate + .long sys_ftruncate + .long sys_fchmod + .long sys_fchown16 /* 95 */ + .long sys_getpriority + .long sys_setpriority + .long sys_ni_syscall /* old profil syscall holder */ + .long sys_statfs + .long sys_fstatfs /* 100 */ + .long sys_ioperm + .long sys_socketcall + .long sys_syslog + .long sys_setitimer + .long sys_getitimer /* 105 */ + .long sys_newstat + .long sys_newlstat + .long sys_newfstat + .long sys_ni_syscall /* old uname syscall holder */ + .long sys_ni_syscall /* 110 */ /* iopl for i386 */ + .long sys_vhangup + .long sys_ni_syscall /* old "idle" system call */ + .long sys_ni_syscall /* vm86old for i386 */ + .long sys_wait4 + .long sys_swapoff /* 115 */ + .long sys_sysinfo + .long sys_ipc + .long sys_fsync + .long sys_sigreturn_glue + .long sys_clone_glue /* 120 */ + .long sys_setdomainname + .long sys_newuname + .long sys_ni_syscall /* modify_ldt for i386 */ + .long sys_adjtimex + .long sys_mprotect /* 125 */ + .long sys_sigprocmask + .long sys_create_module + .long sys_init_module + .long sys_delete_module + .long sys_get_kernel_syms /* 130 */ + .long sys_quotactl + .long sys_getpgid + .long sys_fchdir + .long sys_bdflush + .long sys_sysfs /* 135 */ + .long sys_personality + .long sys_ni_syscall /* for afs_syscall */ + .long sys_setfsuid16 + .long sys_setfsgid16 + .long sys_llseek /* 140 */ + .long sys_getdents + .long sys_select + .long sys_flock + .long sys_msync + .long sys_readv /* 145 */ + .long sys_writev + .long sys_getsid + .long sys_fdatasync + .long sys_sysctl + .long sys_mlock /* 150 */ + .long sys_munlock + .long sys_mlockall + .long sys_munlockall + .long sys_sched_setparam + .long sys_sched_getparam /* 155 */ + .long sys_sched_setscheduler + .long sys_sched_getscheduler + .long sys_sched_yield + .long sys_sched_get_priority_max + .long sys_sched_get_priority_min /* 160 */ + .long sys_sched_rr_get_interval + .long sys_nanosleep + .long sys_mremap + .long sys_setresuid16 + .long sys_getresuid16 /* 165 */ + .long sys_ni_syscall /* for vm86 */ + .long sys_query_module + .long sys_poll + .long sys_nfsservctl + .long sys_setresgid16 /* 170 */ + .long sys_getresgid16 + .long sys_prctl + .long sys_rt_sigreturn_glue + .long sys_rt_sigaction + .long sys_rt_sigprocmask /* 175 */ + .long sys_rt_sigpending + .long sys_rt_sigtimedwait + .long sys_rt_sigqueueinfo + .long sys_rt_sigsuspend_glue + .long sys_pread /* 180 */ + .long sys_pwrite + .long sys_chown16 + .long sys_getcwd + .long sys_capget + .long sys_capset /* 185 */ + .long sys_sigaltstack + .long sys_sendfile + .long sys_ni_syscall /* streams1 */ + .long sys_ni_syscall /* streams2 */ + .long sys_vfork_glue /* 190 */ + .long sys_getrlimit + .long sys_ni_syscall /* FIXME: problem with sys_mmap2: 6 parms */ + .long sys_truncate64 + .long sys_ftruncate64 + .long sys_stat64 /* 195 */ + .long sys_lstat64 + .long sys_fstat64 + .long sys_lchown + .long sys_getuid + .long sys_getgid /* 200 */ + .long sys_geteuid + .long sys_getegid + .long sys_setreuid + .long sys_setregid + .long sys_getgroups /* 205 */ + .long sys_setgroups + .long sys_fchown + .long sys_setresuid + .long sys_getresuid + .long sys_setresgid /* 210 */ + .long sys_getresgid + .long sys_chown + .long sys_setuid + .long sys_setgid + .long sys_setfsuid /* 215 */ + .long sys_setfsgid + .long sys_pivot_root + .long sys_mincore + .long sys_madvise + .rept 255-219 + .long sys_ni_syscall + .endr + +/* + * Program check handler routine + */ + +pgm_lit: + pgm_handle_per: .long handle_per_exception + pgm_jump_table: .long pgm_check_table + pgm_sysc_ret: .long sysc_return + pgm_sysc_lit: .long sysc_lit + pgm_do_signal: .long do_signal + + .globl pgm_check_handler +pgm_check_handler: +/* + * First we need to check for a special case: + * Single stepping an instruction that disables the PER event mask will + * cause a PER event AFTER the mask has been set. Example: SVC or LPSW. + * For a single stepped SVC the program check handler gets control after + * the SVC new PSW has been loaded. But we want to execute the SVC first and + * then handle the PER event. Therefore we update the SVC old PSW to point + * to the pgm_check_handler and branch to the SVC handler after we checked + * if we have to load the kernel stack register. + * For every other possible cause for PER event without the PER mask set + * we just ignore the PER event (FIXME: is there anything we have to do + * for LPSW?). + */ + tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception + jz pgm_sv # skip if not + tm __LC_PGM_OLD_PSW,0x40 # test if per event recording is on + jnz pgm_sv # skip if it is +# ok its one of the special cases, now we need to find out which one + clc __LC_PGM_OLD_PSW(8),__LC_SVC_NEW_PSW + je pgm_svcper +# no interesting special case, ignore PER event + lpsw 0x28 +# it was a single stepped SVC that is causing all the trouble +pgm_svcper: + SAVE_ALL(0x20) + mvi SP_SVC_STEP(%r15),1 # make SP_SVC_STEP nonzero + mvc SP_PGM_OLD_ILC(4,%r15),__LC_PGM_ILC # save program check information + j pgm_system_call # now do the svc +pgm_svcret: + lh %r7,SP_PGM_OLD_ILC(%r15) # get ilc from stack + lhi %r0,0x28 + st %r0,SP_TRAP(%r15) # set new trap indicator + xc SP_SVC_STEP(4,%r15),SP_SVC_STEP(%r15) + basr %r13,0 + ahi %r13,pgm_lit-. # setup base pointer + j pgm_no_sv +pgm_sv: + SAVE_ALL(0x28) + XC SP_SVC_STEP(4,%r15),SP_SVC_STEP(%r15) + basr %r13,0 + ahi %r13,pgm_lit-. # setup base pointer R13 to $PGMDAT + lh %r7,__LC_PGM_ILC # load instruction length +pgm_no_sv: + lh %r8,__LC_PGM_INT_CODE # N.B. saved int code used later KEEP it + stosm 24(%r15),0x03 # reenable interrupts + lr %r3,%r8 + lhi %r0,0x7f + nr %r3,%r0 # clear per-event-bit + je pgm_dn # none of Martins exceptions occured bypass + l %r9,pgm_jump_table-pgm_lit(%r13) + sll %r3,2 + l %r9,0(%r3,%r9) # load address of handler routine + la %r2,SP_PTREGS(%r15) # address of register-save area + srl %r3,2 + chi %r3,0x4 # protection-exception ? + jne pgm_go # if not, + l %r5,SP_PSW+4(15) # load psw addr + sr %r5,%r7 # substract ilc from psw + st %r5,SP_PSW+4(15) # store corrected psw addr +pgm_go: basr %r14,%r9 # branch to interrupt-handler +pgm_dn: lhi %r0,0x80 + nr %r8,%r0 # check for per exception + je pgm_return + la %r2,SP_PTREGS(15) # address of register-save area + l %r9,pgm_handle_per-pgm_lit(%r13) # load adr. of per handler + l %r14,pgm_sysc_ret-pgm_lit(%r13) # load adr. of system return + l %r13,pgm_sysc_lit-pgm_lit(%r13) + br %r9 # branch to handle_per_exception +# +# the backend code is the same as for sys-call +# +pgm_return: + l %r14,pgm_sysc_ret-pgm_lit(%r13) + l %r13,pgm_sysc_lit-pgm_lit(%r13) + br %r14 + +/* + * IO interrupt handler routine + */ + +io_lit: + io_do_IRQ: .long do_IRQ + io_schedule: .long schedule + io_do_signal: .long do_signal + io_softirq_state: .long softirq_state + io_do_softirq: .long do_softirq + + .globl io_int_handler +io_int_handler: + SAVE_ALL(0x38) + basr %r13,0 + ahi %r13,io_lit-. # setup base pointer R13 to $IODAT + la %r2,SP_PTREGS(%r15) # address of register-save area + sr %r3,%r3 + icm %r3,%r3,__LC_SUBCHANNEL_NR # load subchannel nr & extend to int + l %r4,__LC_IO_INT_PARM # load interuption parm + l %r9,io_do_IRQ-io_lit(%r13) # load address of do_IRQ + basr %r14,%r9 # branch to standard irq handler + +io_return: + GET_CURRENT # load pointer to task_struct to R9 + tm SP_PSW+1(%r15),0x01 # returning to user ? + jz io_leave # no-> skip resched & signal + stosm 24(%r15),0x03 # reenable interrupts +# +# check, if bottom-half has to be done +# +#ifdef CONFIG_SMP + l %r1,processor(%r9) # get processor index + sll %r1,5 + al %r1,io_softirq_state-io_lit(%r13) + l %r0,0(%r1) # get softirq_state[cpu].active + n %r0,4(%r1) # and it with softirq_state[cpu].mask +#else + l %r1,io_softirq_state-io_lit(%r13) + l %r0,0(%r1) # get softirq_state.active + n %r0,4(%r1) # and it with softirq_state.mask +#endif + jnz io_handle_bottom_half +io_return_bh: +# +# check, if reschedule is needed +# + icm %r0,15,need_resched(%r9) # get need_resched from task_struct + jnz io_reschedule + icm %r0,15,sigpending(%r9) # get sigpending from task_struct + jnz io_signal_return +io_leave: + stnsm 24(%r15),disable # disable I/O and ext. interrupts + RESTORE_ALL + +# +# call do_softirq and return from syscall, if interrupt-level +# is zero +# +io_handle_bottom_half: + l %r1,io_do_softirq-io_lit(%r13) + la %r14,io_return_bh-io_lit(%r13) + br %r1 # call do_softirq + +# +# call schedule with io_return as return-address +# +io_reschedule: + l %r1,io_schedule-io_lit(%r13) + la %r14,io_return-io_lit(%r13) + br %r1 # call scheduler, return to io_return + +# +# call do_signal before return +# +io_signal_return: + la %r2,SP_PTREGS(%r15) # load pt_regs + sr %r3,%r3 # clear *oldset + l %r1,io_do_signal-io_lit(%r13) + la %r14,io_leave-io_lit(%r13) + br %r1 # return point is io_leave + +/* + * External interrupt handler routine + */ + +ext_lit: + ext_timer_int: .long do_timer_interrupt +#ifdef CONFIG_SMP + ext_call_int: .long do_ext_call_interrupt +#endif +#ifdef CONFIG_HWC + ext_hwc_int: .long do_hwc_interrupt +#endif +#ifdef CONFIG_MDISK + ext_mdisk_int: .long do_mdisk_interrupt +#endif +#ifdef CONFIG_IUCV + ext_iucv_int: .long do_iucv_interrupt +#endif + ext_io_lit: .long io_lit + ext_io_return: .long io_return + + .globl ext_int_handler +ext_int_handler: + SAVE_ALL(0x18) + basr %r13,0 + ahi %r13,ext_lit-. # setup base pointer R13 to $EXTDAT + la %r2,SP_PTREGS(%r15) # address of register-save area + lh %r3,__LC_EXT_INT_CODE # error code +#ifdef CONFIG_SMP + chi %r3,0x1202 # EXTERNAL_CALL + jne ext_no_extcall + l %r9,ext_call_int-ext_lit(%r13) # load ext_call_interrupt + l %r14,ext_io_return-ext_lit(%r13) + l %r13,ext_io_lit-ext_lit(%r13) + br %r9 # branch to ext call handler +ext_no_extcall: +#endif + chi %r3,0x1004 # CPU_TIMER + jne ext_no_timer + l %r9,ext_timer_int-ext_lit(%r13) # load timer_interrupt + l %r14,ext_io_return-ext_lit(%r13) + l %r13,ext_io_lit-ext_lit(%r13) + br %r9 # branch to ext call handler +ext_no_timer: +#ifdef CONFIG_HWC + chi %r3,0x2401 # HWC interrupt + jne ext_no_hwc + l %r9,ext_hwc_int-ext_lit(%r13) # load addr. of hwc routine + l %r14,ext_io_return-ext_lit(%r13) + l %r13,ext_io_lit-ext_lit(%r13) + br %r9 # branch to ext call handler +ext_no_hwc: +#endif +#ifdef CONFIG_MDISK + chi %r3,0x2603 # diag 250 (VM) interrupt + jne ext_no_mdisk + l %r9,ext_mdisk_int-ext_lit(%r13) + l %r14,ext_io_return-ext_lit(%r13) + l %r13,ext_io_lit-ext_lit(%r13) + br %r9 # branch to ext call handler +ext_no_mdisk: +#endif +#ifdef CONFIG_IUCV + chi %r3,0x4000 # diag 250 (VM) interrupt + jne ext_no_iucv + l %r9,ext_iucv_int-ext_lit(%r13) + l %r14,ext_io_return-ext_lit(%r13) + l %r13,ext_io_lit-ext_lit(%r13) + br %r9 # branch to ext call handler +ext_no_iucv: +#endif + + l %r14,ext_io_return-ext_lit(%r13) + l %r13,ext_io_lit-ext_lit(%r13) + br %r14 # use backend code of io_int_handler + +/* + * Machine check handler routines + */ +mcck_lit: + mcck_crw_pending: .long do_crw_pending + + + .globl mcck_int_handler +mcck_int_handler: + SAVE_ALL(0x30) + basr %r13,0 + ahi %r13,mcck_lit-. # setup base pointer R13 to $MCCKDAT + tm __LC_MCCK_CODE+1,0x40 + jno mcck_no_crw + l %r1,mcck_crw_pending-mcck_lit(%r13) + basr %r14,%r1 # call do_crw_pending +mcck_no_crw: +mcck_return: + RESTORE_ALL + +#ifdef CONFIG_SMP +/* + * Restart interruption handler, kick starter for additional CPUs + */ + .globl restart_int_handler +restart_int_handler: + l %r15,__LC_KERNEL_STACK # load ksp + lctl %c0,%c15,__LC_CREGS_SAVE_AREA # get new ctl regs + lam %a0,%a15,__LC_AREGS_SAVE_AREA + stosm 0(%r15),daton # now we can turn dat on + lm %r6,%r15,24(%r15) # load registers from clone + bras %r14,restart_go + .long start_secondary +restart_go: + l %r14,0(%r14) + br %r14 # branch to start_secondary +#else +/* + * If we do not run with SMP enabled, let the new CPU crash ... + */ + .globl restart_int_handler +restart_int_handler: + basr %r1,0 +restart_base: + lpsw restart_crash-restart_base(%r1) + .align 8 +restart_crash: + .long 0x000a0000,0x00000000 +restart_go: +#endif + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/floatlib.c linux/arch/s390/kernel/floatlib.c --- v2.3.99-pre7/linux/arch/s390/kernel/floatlib.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/floatlib.c Fri May 12 11:41:44 2000 @@ -0,0 +1,1021 @@ +/* +** libgcc support for software floating point. +** Copyright (C) 1991 by Pipeline Associates, Inc. All rights reserved. +** Permission is granted to do *anything* you want with this file, +** commercial or otherwise, provided this message remains intact. So there! +** I would appreciate receiving any updates/patches/changes that anyone +** makes, and am willing to be the repository for said changes (am I +** making a big mistake?). + +Warning! Only single-precision is actually implemented. This file +won't really be much use until double-precision is supported. + +However, once that is done, this file might eventually become a +replacement for libgcc1.c. It might also make possible +cross-compilation for an IEEE target machine from a non-IEEE +host such as a VAX. + +If you'd like to work on completing this, please talk to rms@gnu.ai.mit.edu. + +--> Double precision floating support added by James Carlson on 20 April 1998. + +** +** Pat Wood +** Pipeline Associates, Inc. +** pipeline!phw@motown.com or +** sun!pipeline!phw or +** uunet!motown!pipeline!phw +** +** 05/01/91 -- V1.0 -- first release to gcc mailing lists +** 05/04/91 -- V1.1 -- added float and double prototypes and return values +** -- fixed problems with adding and subtracting zero +** -- fixed rounding in truncdfsf2 +** -- fixed SWAP define and tested on 386 +*/ + +/* +** The following are routines that replace the libgcc soft floating point +** routines that are called automatically when -msoft-float is selected. +** The support single and double precision IEEE format, with provisions +** for byte-swapped machines (tested on 386). Some of the double-precision +** routines work at full precision, but most of the hard ones simply punt +** and call the single precision routines, producing a loss of accuracy. +** long long support is not assumed or included. +** Overall accuracy is close to IEEE (actually 68882) for single-precision +** arithmetic. I think there may still be a 1 in 1000 chance of a bit +** being rounded the wrong way during a multiply. I'm not fussy enough to +** bother with it, but if anyone is, knock yourself out. +** +** Efficiency has only been addressed where it was obvious that something +** would make a big difference. Anyone who wants to do this right for +** best speed should go in and rewrite in assembler. +** +** I have tested this only on a 68030 workstation and 386/ix integrated +** in with -msoft-float. +*/ + +#define float long +#define double long long + +/* the following deal with IEEE single-precision numbers */ +#define EXCESS 126 +#define SIGNBIT 0x80000000 +#define HIDDEN (1 << 23) +#define SIGN(fp) ((fp) & SIGNBIT) +#define EXP(fp) (((fp) >> 23) & 0xFF) +#define MANT(fp) (((fp) & 0x7FFFFF) | HIDDEN) +#define PACK(s,e,m) ((s) | ((e) << 23) | (m)) + +/* the following deal with IEEE double-precision numbers */ +#define EXCESSD 1022 +#define HIDDEND (1 << 20) +#define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF) +#define SIGND(fp) ((fp.l.upper) & SIGNBIT) +#define MANTD(fp) (((((fp.l.upper) & 0xFFFFF) | HIDDEND) << 10) |(fp.l.lower >> 22)) +#define HIDDEND_LL ((long long)1 << 52) +#define MANTD_LL(fp) ((fp.ll & (HIDDEND_LL-1)) | HIDDEND_LL) +#define PACKD_LL(s,e,m) (((long long)((s)+((e)<<20))<<32)|(m)) + +/* define SWAP for 386/960 reverse-byte-order brain-damaged CPUs */ +union double_long { + double d; +#ifdef SWAP + struct { + unsigned long lower; + long upper; + } l; +#else + struct { + long upper; + unsigned long lower; + } l; +#endif + long long ll; +}; + +union float_long + { + float f; + long l; + }; + +long long +__negdi2 (long long u) +{ + + union lll { + long long ll; + long s[2]; + }; + + union lll w,uu; + + uu.ll = u; + + w.s[1] = -uu.s[1]; + w.s[0] = -uu.s[0] - ((int) w.s[1] != 0); + + return w.ll; +} + + + +/* add two floats */ +float +__addsf3 (float a1, float a2) +{ + register long mant1, mant2; + register union float_long fl1, fl2; + register int exp1, exp2; + int sign = 0; + + fl1.f = a1; + fl2.f = a2; + + /* check for zero args */ + if (!fl1.l) { + fl1.f = fl2.f; + goto test_done; + } + if (!fl2.l) + goto test_done; + + exp1 = EXP (fl1.l); + exp2 = EXP (fl2.l); + + if (exp1 > exp2 + 25) + goto test_done; + if (exp2 > exp1 + 25) { + fl1.f = fl2.f; + goto test_done; + } + + /* do everything in excess precision so's we can round later */ + mant1 = MANT (fl1.l) << 6; + mant2 = MANT (fl2.l) << 6; + + if (SIGN (fl1.l)) + mant1 = -mant1; + if (SIGN (fl2.l)) + mant2 = -mant2; + + if (exp1 > exp2) + { + mant2 >>= exp1 - exp2; + } + else + { + mant1 >>= exp2 - exp1; + exp1 = exp2; + } + mant1 += mant2; + + if (mant1 < 0) + { + mant1 = -mant1; + sign = SIGNBIT; + } + else if (!mant1) { + fl1.f = 0; + goto test_done; + } + + /* normalize up */ + while (!(mant1 & 0xE0000000)) + { + mant1 <<= 1; + exp1--; + } + + /* normalize down? */ + if (mant1 & (1 << 30)) + { + mant1 >>= 1; + exp1++; + } + + /* round to even */ + mant1 += (mant1 & 0x40) ? 0x20 : 0x1F; + + /* normalize down? */ + if (mant1 & (1 << 30)) + { + mant1 >>= 1; + exp1++; + } + + /* lose extra precision */ + mant1 >>= 6; + + /* turn off hidden bit */ + mant1 &= ~HIDDEN; + + /* pack up and go home */ + fl1.l = PACK (sign, exp1, mant1); +test_done: + return (fl1.f); +} + +/* subtract two floats */ +float +__subsf3 (float a1, float a2) +{ + register union float_long fl1, fl2; + + fl1.f = a1; + fl2.f = a2; + + /* check for second arg zero */ + if (!fl2.l) + return (fl1.f); + /* twiddle sign bit */ + fl2.l ^= SIGNBIT; + /* check for first arg zero */ + if (!fl1.l) + return (fl2.f); + /* add values */ + return __addsf3 (a1, fl2.f); +} + +/* compare two floats */ +long +__cmpsf2 (float a1, float a2) +{ + register union float_long fl1, fl2; + + fl1.f = a1; + fl2.f = a2; + + if (SIGN (fl1.l) && SIGN (fl2.l)) + { + fl1.l ^= SIGNBIT; + fl2.l ^= SIGNBIT; + if (fl1.l < fl2.l) + return (-1); + if (fl1.l > fl2.l) + return (1); + return 0; + } else { + if (fl1.l < fl2.l) + return (-1); + if (fl1.l > fl2.l) + return (1); + return (0); + } +} + +/* multiply two floats */ +float +__mulsf3 (float a1, float a2) +{ + register union float_long fl1, fl2; + register unsigned long result; + register int exp; + int sign; + + fl1.f = a1; + fl2.f = a2; + + if (!fl1.l || !fl2.l) { + fl1.f = 0; + goto test_done; + } + + /* compute sign and exponent */ + sign = SIGN (fl1.l) ^ SIGN (fl2.l); + exp = EXP (fl1.l) - EXCESS; + exp += EXP (fl2.l); + + fl1.l = MANT (fl1.l); + fl2.l = MANT (fl2.l); + + /* the multiply is done as one 16x16 multiply and two 16x8 multiples */ + result = (fl1.l >> 8) * (fl2.l >> 8); + result += ((fl1.l & 0xFF) * (fl2.l >> 8)) >> 8; + result += ((fl2.l & 0xFF) * (fl1.l >> 8)) >> 8; + + result >>= 2; + if (result & 0x20000000) + { + /* round */ + result += 0x20; + result >>= 6; + } + else + { + /* round */ + result += 0x10; + result >>= 5; + exp--; + } + if (result & (HIDDEN<<1)) { + result >>= 1; + exp++; + } + + result &= ~HIDDEN; + + /* pack up and go home */ + fl1.l = PACK (sign, exp, result); +test_done: + return (fl1.f); +} + +/* divide two floats */ +float +__divsf3 (float a1, float a2) +{ + register union float_long fl1, fl2; + register int result; + register int mask; + register int exp, sign; + + fl1.f = a1; + fl2.f = a2; + + /* subtract exponents */ + exp = EXP (fl1.l) - EXP (fl2.l) + EXCESS; + + /* compute sign */ + sign = SIGN (fl1.l) ^ SIGN (fl2.l); + + /* divide by zero??? */ + if (!fl2.l) + /* return NaN or -NaN */ + return (sign ? 0xFFFFFFFF : 0x7FFFFFFF); + + /* numerator zero??? */ + if (!fl1.l) + return (0); + + /* now get mantissas */ + fl1.l = MANT (fl1.l); + fl2.l = MANT (fl2.l); + + /* this assures we have 25 bits of precision in the end */ + if (fl1.l < fl2.l) + { + fl1.l <<= 1; + exp--; + } + + /* now we perform repeated subtraction of fl2.l from fl1.l */ + mask = 0x1000000; + result = 0; + while (mask) + { + if (fl1.l >= fl2.l) + { + result |= mask; + fl1.l -= fl2.l; + } + fl1.l <<= 1; + mask >>= 1; + } + + /* round */ + result += 1; + + /* normalize down */ + exp++; + result >>= 1; + + result &= ~HIDDEN; + + /* pack up and go home */ + fl1.l = PACK (sign, exp, result); + return (fl1.f); +} + +/* convert double to float */ +float +__truncdfsf2 (double a1) +{ + register int exp; + register long mant; + register union float_long fl; + register union double_long dl1; + + dl1.d = a1; + + if (!dl1.l.upper && !dl1.l.lower) + return (float)(0); + + exp = EXPD (dl1) - EXCESSD + EXCESS; + + /* shift double mantissa 6 bits so we can round */ + mant = MANTD (dl1) >> 6; + + /* now round and shift down */ + mant += 1; + mant >>= 1; + + /* did the round overflow? */ + if (mant & 0xFF000000) + { + mant >>= 1; + exp++; + } + + mant &= ~HIDDEN; + + /* pack up and go home */ + fl.l = PACK (SIGND (dl1), exp, mant); + return (fl.f); +} + +/* convert int to double */ +double +__floatsidf (register long a1) +{ + register int sign = 0, exp = 31 + EXCESSD; + union double_long dl; + + if (a1 == 0x80000000) + { + /* + * -a1 would be 0 ! + */ + dl.l.upper = 0xc1e00000; + dl.l.lower = 0x0; + return (dl.d); + } + + if (!a1) + { + dl.l.upper = dl.l.lower = 0; + return (dl.d); + } + + if (a1 < 0) + { + sign = SIGNBIT; + a1 = -a1; + } + + while (a1 < 0x1000000) + { + a1 <<= 4; + exp -= 4; + } + + while (a1 < 0x40000000) + { + a1 <<= 1; + exp--; + } + + /* pack up and go home */ + dl.l.upper = sign; + dl.l.upper |= exp << 20; + dl.l.upper |= (a1 >> 10) & ~HIDDEND; + dl.l.lower = a1 << 22; + + return (dl.d); +} + +double +__floatdidf (register long long a1) +{ + register int exp = 63 + EXCESSD; + union double_long dl; + + dl.l.upper = dl.l.lower = 0; + if (a1 == 0) + return (dl.d); + + if (a1 < 0) { + dl.l.upper = SIGNBIT; + a1 = -a1; + } + + while (a1 < (long long)1<<54) { + a1 <<= 8; + exp -= 8; + } + while (a1 < (long long)1<<62) { + a1 <<= 1; + exp -= 1; + } + /* pack up and go home */ + dl.ll |= (a1 >> 10) & ~HIDDEND_LL; + dl.l.upper |= exp << 20; + + return (dl.d); +} + +float +__floatsisf (register long a1) +{ + return __truncdfsf2(__floatsidf(a1)); +} + +float +__floatdisf (register long long a1) +{ + return (float)__floatdidf(a1); +} +/* negate a float */ +float +__negsf2 (float a1) +{ + register union float_long fl1; + + fl1.f = a1; + if (!fl1.l) + return (0); + + fl1.l ^= SIGNBIT; + return (fl1.f); +} + +/* negate a double */ +double +__negdf2 (double a1) +{ + register union double_long dl1; + + dl1.d = a1; + + if (!dl1.l.upper && !dl1.l.lower) + return (dl1.d); + + dl1.l.upper ^= SIGNBIT; + return (dl1.d); +} + +/* convert float to double */ +double +__extendsfdf2 (float a1) +{ + register union float_long fl1; + register union double_long dl; + register int exp; + + fl1.f = a1; + + if (!fl1.l) + { + dl.l.upper = dl.l.lower = 0; + return (dl.d); + } + + dl.l.upper = SIGN (fl1.l); + exp = EXP (fl1.l) - EXCESS + EXCESSD; + dl.l.upper |= exp << 20; + dl.l.upper |= (MANT (fl1.l) & ~HIDDEN) >> 3; + dl.l.lower = MANT (fl1.l) << 29; + + return (dl.d); +} + + +/* compare two doubles */ +long +__cmpdf2 (double a1, double a2) +{ + register union double_long dl1, dl2; + + dl1.d = a1; + dl2.d = a2; + + if (SIGND (dl1) && SIGND (dl2)) + { + dl1.l.upper ^= SIGNBIT; + dl2.l.upper ^= SIGNBIT; + if (dl1.l.upper < dl2.l.upper) + return (1); + if (dl1.l.upper > dl2.l.upper) + return (-1); + if (dl1.l.lower < dl2.l.lower) + return (1); + if (dl1.l.lower > dl2.l.lower) + return (-1); + return (0); + } else { + if (dl1.l.upper < dl2.l.upper) + return (-1); + if (dl1.l.upper > dl2.l.upper) + return (1); + if (dl1.l.lower < dl2.l.lower) + return (-1); + if (dl1.l.lower > dl2.l.lower) + return (1); + return (0); + } +} + +/* convert double to int */ +long +__fixdfsi (double a1) +{ + register union double_long dl1; + register int exp; + register long l; + + dl1.d = a1; + + if (!dl1.l.upper && !dl1.l.lower) + return (0); + + exp = EXPD (dl1) - EXCESSD - 31; + l = MANTD (dl1); + + if (exp > 0) + return SIGND(dl1) ? (1<<31) : ((1ul<<31)-1); + + /* shift down until exp = 0 or l = 0 */ + if (exp <= 0 && exp > -32 && l) + l >>= -exp; + else + return (0); + + return (SIGND (dl1) ? -l : l); +} + +/* convert float to int */ +long +__fixsfsi (float a1) +{ + return __fixdfsi(__extendsfdf2(a1)); +} + +/* convert double to int */ +long long +__fixdfdi (double a1) +{ + register union double_long dl1; + register int exp; + register long long l; + + dl1.d = a1; + + if (!dl1.l.upper && !dl1.l.lower) + return (0); + + exp = EXPD (dl1) - EXCESSD - 64; + l = MANTD_LL(dl1); + + if (exp > 0) { + l = (long long)1<<63; + if (!SIGND(dl1)) + l--; + return l; + } + + /* shift down until exp = 0 or l = 0 */ + if (exp <= 0 && exp > -64 && l) + l >>= -exp; + else + return (0); + + return (SIGND (dl1) ? -l : l); +} + +/* convert double to unsigned int */ +unsigned long +__fixunsdfsi (double a1) +{ + register union double_long dl1; + register int exp; + register unsigned long l; + + dl1.d = a1; + + if (!dl1.l.upper && !dl1.l.lower) + return (0); + + exp = EXPD (dl1) - EXCESSD - 32; + l = (((((dl1.l.upper) & 0xFFFFF) | HIDDEND) << 11) | (dl1.l.lower >> 21)); + + if (exp > 0) + return (0xFFFFFFFFul); /* largest integer */ + + /* shift down until exp = 0 or l = 0 */ + if (exp < 0 && exp > -32 && l) + l >>= -exp; + else + return (0); + + return (l); +} + +/* convert double to unsigned int */ +unsigned long long +__fixunsdfdi (double a1) +{ + register union double_long dl1; + register int exp; + register unsigned long long l; + + dl1.d = a1; + + if (dl1.ll == 0) + return (0); + + exp = EXPD (dl1) - EXCESSD - 64; + + l = dl1.ll; + + if (exp > 0) + return (unsigned long long)-1; + + /* shift down until exp = 0 or l = 0 */ + if (exp < 0 && exp > -64 && l) + l >>= -exp; + else + return (0); + + return (l); +} + +/* addtwo doubles */ +double +__adddf3 (double a1, double a2) +{ + register long long mant1, mant2; + register union double_long fl1, fl2; + register int exp1, exp2; + int sign = 0; + + fl1.d = a1; + fl2.d = a2; + + /* check for zero args */ + if (!fl2.ll) + goto test_done; + if (!fl1.ll) { + fl1.d = fl2.d; + goto test_done; + } + + exp1 = EXPD(fl1); + exp2 = EXPD(fl2); + + if (exp1 > exp2 + 54) + goto test_done; + if (exp2 > exp1 + 54) { + fl1.d = fl2.d; + goto test_done; + } + + /* do everything in excess precision so's we can round later */ + mant1 = MANTD_LL(fl1) << 9; + mant2 = MANTD_LL(fl2) << 9; + + if (SIGND(fl1)) + mant1 = -mant1; + if (SIGND(fl2)) + mant2 = -mant2; + + if (exp1 > exp2) + mant2 >>= exp1 - exp2; + else { + mant1 >>= exp2 - exp1; + exp1 = exp2; + } + mant1 += mant2; + + if (mant1 < 0) { + mant1 = -mant1; + sign = SIGNBIT; + } else if (!mant1) { + fl1.d = 0; + goto test_done; + } + + /* normalize up */ + while (!(mant1 & ((long long)7<<61))) { + mant1 <<= 1; + exp1--; + } + + /* normalize down? */ + if (mant1 & ((long long)3<<62)) { + mant1 >>= 1; + exp1++; + } + + /* round to even */ + mant1 += (mant1 & (1<<9)) ? (1<<8) : ((1<<8)-1); + + /* normalize down? */ + if (mant1 & ((long long)3<<62)) { + mant1 >>= 1; + exp1++; + } + + /* lose extra precision */ + mant1 >>= 9; + + /* turn off hidden bit */ + mant1 &= ~HIDDEND_LL; + + /* pack up and go home */ + fl1.ll = PACKD_LL(sign,exp1,mant1); + +test_done: + return (fl1.d); +} + +/* subtract two doubles */ +double +__subdf3 (double a1, double a2) +{ + register union double_long fl1, fl2; + + fl1.d = a1; + fl2.d = a2; + + /* check for zero args */ + if (!fl2.ll) + return (fl1.d); + /* twiddle sign bit and add */ + fl2.l.upper ^= SIGNBIT; + if (!fl1.ll) + return (fl2.d); + return __adddf3 (a1, fl2.d); +} + +/* multiply two doubles */ +double +__muldf3 (double a1, double a2) +{ + register union double_long fl1, fl2; + register unsigned long long result=0ULL; + register int exp; + int sign; + + fl1.d = a1; + fl2.d = a2; + + if (!fl1.ll || !fl2.ll) { + fl1.d = 0; + goto test_done; + } + + /* compute sign and exponent */ + sign = SIGND(fl1) ^ SIGND(fl2); + exp = EXPD(fl1) - EXCESSD; + exp += EXPD(fl2); + + fl1.ll = MANTD_LL(fl1); + fl2.ll = MANTD_LL(fl2); + + /* the multiply is done as one 31x31 multiply and two 31x21 multiples */ + result = (fl1.ll >> 21) * (fl2.ll >> 21); + result += ((fl1.ll & 0x1FFFFF) * (fl2.ll >> 21)) >> 21; + result += ((fl2.ll & 0x1FFFFF) * (fl1.ll >> 21)) >> 21; + + result >>= 2; + if (result & ((long long)1<<61)) { + /* round */ + result += 1<<8; + result >>= 9; + } else { + /* round */ + result += 1<<7; + result >>= 8; + exp--; + } + if (result & (HIDDEND_LL<<1)) { + result >>= 1; + exp++; + } + + result &= ~HIDDEND_LL; + + /* pack up and go home */ + fl1.ll = PACKD_LL(sign,exp,result); +test_done: + return (fl1.d); +} + +/* divide two doubles */ +double +__divdf3 (double a1, double a2) +{ + register union double_long fl1, fl2; + register long long mask,result; + register int exp, sign; + + fl1.d = a1; + fl2.d = a2; + + /* subtract exponents */ + exp = EXPD(fl1) - EXPD(fl2) + EXCESSD; + + /* compute sign */ + sign = SIGND(fl1) ^ SIGND(fl2); + + /* numerator zero??? */ + if (fl1.ll == 0) { + /* divide by zero??? */ + if (fl2.ll == 0) + fl1.ll = ((unsigned long long)1<<63)-1; /* NaN */ + else + fl1.ll = 0; + goto test_done; + } + + /* return +Inf or -Inf */ + if (fl2.ll == 0) { + fl1.ll = PACKD_LL(SIGND(fl1),2047,0); + goto test_done; + } + + + /* now get mantissas */ + fl1.ll = MANTD_LL(fl1); + fl2.ll = MANTD_LL(fl2); + + /* this assures we have 54 bits of precision in the end */ + if (fl1.ll < fl2.ll) { + fl1.ll <<= 1; + exp--; + } + + /* now we perform repeated subtraction of fl2.ll from fl1.ll */ + mask = (long long)1<<53; + result = 0; + while (mask) { + if (fl1.ll >= fl2.ll) + { + result |= mask; + fl1.ll -= fl2.ll; + } + fl1.ll <<= 1; + mask >>= 1; + } + + /* round */ + result += 1; + + /* normalize down */ + exp++; + result >>= 1; + + result &= ~HIDDEND_LL; + + /* pack up and go home */ + fl1.ll = PACKD_LL(sign, exp, result); + +test_done: + return (fl1.d); +} + +int +__gtdf2 (double a1, double a2) +{ + return __cmpdf2 ((float) a1, (float) a2) > 0; +} + +int +__gedf2 (double a1, double a2) +{ + return (__cmpdf2 ((float) a1, (float) a2) >= 0) - 1; +} + +int +__ltdf2 (double a1, double a2) +{ + return - (__cmpdf2 ((float) a1, (float) a2) < 0); +} + +int +__ledf2 (double a1, double a2) +{ + return __cmpdf2 ((float) a1, (float) a2) > 0; +} + +int +__eqdf2 (double a1, double a2) +{ + return *(long long *) &a1 == *(long long *) &a2; +} + +int +__nedf2 (double a1, double a2) +{ + return *(long long *) &a1 != *(long long *) &a2; +} + +/* absolute value of double */ +double +__absdf2(double a1) +{ + if (__cmpdf2(a1,0.0) < 0) + return __negdf2(a1); + else + return a1; +} + +/* absolute value of float */ +float +__abssf2(float a1) +{ + if (__cmpsf2(a1,0.0) < 0) + return __negsf2(a1); + else + return a1; +} diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/gdb-stub.c linux/arch/s390/kernel/gdb-stub.c --- v2.3.99-pre7/linux/arch/s390/kernel/gdb-stub.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/gdb-stub.c Fri May 12 11:41:44 2000 @@ -0,0 +1,575 @@ +/* + * arch/s390/kernel/gdb-stub.c + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), + * + * Originally written by Glenn Engel, Lake Stevens Instrument Division + * + * Contributed by HP Systems + * + * Modified for SPARC by Stu Grossman, Cygnus Support. + * + * Modified for Linux/MIPS (and MIPS in general) by Andreas Busse + * Send complaints, suggestions etc. to + * + * Copyright (C) 1995 Andreas Busse + */ + +/* + * To enable debugger support, two things need to happen. One, a + * call to set_debug_traps() is necessary in order to allow any breakpoints + * or error conditions to be properly intercepted and reported to gdb. + * Two, a breakpoint needs to be generated to begin communication. This + * is most easily accomplished by a call to breakpoint(). Breakpoint() + * simulates a breakpoint by executing a BREAK instruction. + * + * + * The following gdb commands are supported: + * + * command function Return value + * + * g return the value of the CPU registers hex data or ENN + * G set the value of the CPU registers OK or ENN + * + * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN + * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN + * + * c Resume at current address SNN ( signal NN) + * cAA..AA Continue at address AA..AA SNN + * + * s Step one instruction SNN + * sAA..AA Step one instruction from AA..AA SNN + * + * k kill + * + * ? What was the last sigval ? SNN (signal NN) + * + * + * All commands and responses are sent with a packet which includes a + * checksum. A packet consists of + * + * $#. + * + * where + * :: + * :: < two hex digits computed as modulo 256 sum of > + * + * When a packet is received, it is first acknowledged with either '+' or '-'. + * '+' indicates a successful transfer. '-' indicates a failed transfer. + * + * Example: + * + * Host: Reply: + * $m0,10#2a +$00010203040506070809101112131415#42 + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +/* + * external low-level support routines + */ + +extern int putDebugChar(char c); /* write a single character */ +extern char getDebugChar(void); /* read and return a single char */ +extern void fltr_set_mem_err(void); +extern void trap_low(void); + +/* + * breakpoint and test functions + */ +extern void breakpoint(void); +extern void breakinst(void); + +/* + * local prototypes + */ + +static void getpacket(char *buffer); +static void putpacket(char *buffer); +static int hex(unsigned char ch); +static int hexToInt(char **ptr, int *intValue); +static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault); + + +/* + * BUFMAX defines the maximum number of characters in inbound/outbound buffers + * at least NUMREGBYTES*2 are needed for register packets + */ +#define BUFMAX 2048 + +static char input_buffer[BUFMAX]; +static char output_buffer[BUFMAX]; +int gdb_stub_initialised = FALSE; +static const char hexchars[]="0123456789abcdef"; + + +/* + * Convert ch from a hex digit to an int + */ +static int hex(unsigned char ch) +{ + if (ch >= 'a' && ch <= 'f') + return ch-'a'+10; + if (ch >= '0' && ch <= '9') + return ch-'0'; + if (ch >= 'A' && ch <= 'F') + return ch-'A'+10; + return -1; +} + +/* + * scan for the sequence $# + */ +static void getpacket(char *buffer) +{ + unsigned char checksum; + unsigned char xmitcsum; + int i; + int count; + unsigned char ch; + + do { + /* + * wait around for the start character, + * ignore all other characters + */ + while ((ch = (getDebugChar() & 0x7f)) != '$') ; + + checksum = 0; + xmitcsum = -1; + count = 0; + + /* + * now, read until a # or end of buffer is found + */ + while (count < BUFMAX) { + ch = getDebugChar() & 0x7f; + if (ch == '#') + break; + checksum = checksum + ch; + buffer[count] = ch; + count = count + 1; + } + + if (count >= BUFMAX) + continue; + + buffer[count] = 0; + + if (ch == '#') { + xmitcsum = hex(getDebugChar() & 0x7f) << 4; + xmitcsum |= hex(getDebugChar() & 0x7f); + + if (checksum != xmitcsum) + putDebugChar('-'); /* failed checksum */ + else { + putDebugChar('+'); /* successful transfer */ + + /* + * if a sequence char is present, + * reply the sequence ID + */ + if (buffer[2] == ':') { + putDebugChar(buffer[0]); + putDebugChar(buffer[1]); + + /* + * remove sequence chars from buffer + */ + count = strlen(buffer); + for (i=3; i <= count; i++) + buffer[i-3] = buffer[i]; + } + } + } + } + while (checksum != xmitcsum); +} + +/* + * send the packet in buffer. + */ +static void putpacket(char *buffer) +{ + unsigned char checksum; + int count; + unsigned char ch; + + /* + * $#. + */ + + do { + putDebugChar('$'); + checksum = 0; + count = 0; + + while ((ch = buffer[count]) != 0) { + if (!(putDebugChar(ch))) + return; + checksum += ch; + count += 1; + } + + putDebugChar('#'); + putDebugChar(hexchars[checksum >> 4]); + putDebugChar(hexchars[checksum & 0xf]); + + } + while ((getDebugChar() & 0x7f) != '+'); +} + + + +/* + * Convert the memory pointed to by mem into hex, placing result in buf. + * Return a pointer to the last char put in buf (null), in case of mem fault, + * return 0. + * If MAY_FAULT is non-zero, then we will handle memory faults by returning + * a 0, else treat a fault like any other fault in the stub. + */ +static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault) +{ + unsigned char ch; + +/* set_mem_fault_trap(may_fault); */ + + while (count-- > 0) { + ch = *(mem++); + if (mem_err) + return 0; + *buf++ = hexchars[ch >> 4]; + *buf++ = hexchars[ch & 0xf]; + } + + *buf = 0; + +/* set_mem_fault_trap(0); */ + + return buf; +} + +/* + * convert the hex array pointed to by buf into binary to be placed in mem + * return a pointer to the character AFTER the last byte written + */ +static char *hex2mem(char *buf, char *mem, int count, int may_fault) +{ + int i; + unsigned char ch; + +/* set_mem_fault_trap(may_fault); */ + + for (i=0; ifp_regs; + int has_ieee=save_fp_regs1(fpregs); + + if(!has_ieee) + { + fpregs->fpc=0; + fpregs->fprs[1].d= + fpregs->fprs[3].d= + fpregs->fprs[5].d= + fpregs->fprs[7].d=0; + memset(&fpregs->fprs[8].d,0,sizeof(freg_t)*8); + } +} + +void gdb_stub_set_non_pt_regs(gdb_pt_regs *regs) +{ + restore_fp_regs1(®s->fp_regs); +} + +void gdb_stub_send_signal(int sigval) +{ + char *ptr; + ptr = output_buffer; + + /* + * Send trap type (converted to signal) + */ + *ptr++ = 'S'; + *ptr++ = hexchars[sigval >> 4]; + *ptr++ = hexchars[sigval & 0xf]; + *ptr++ = 0; + putpacket(output_buffer); /* send it off... */ +} + +/* + * This function does all command processing for interfacing to gdb. It + * returns 1 if you should skip the instruction at the trap address, 0 + * otherwise. + */ +void gdb_stub_handle_exception(gdb_pt_regs *regs,int sigval) +{ + int trap; /* Trap type */ + int addr; + int length; + char *ptr; + unsigned long *stack; + + + /* + * reply to host that an exception has occurred + */ + send_signal(sigval); + + /* + * Wait for input from remote GDB + */ + while (1) { + output_buffer[0] = 0; + getpacket(input_buffer); + + switch (input_buffer[0]) + { + case '?': + send_signal(sigval); + continue; + + case 'd': + /* toggle debug flag */ + break; + + /* + * Return the value of the CPU registers + */ + case 'g': + gdb_stub_get_non_pt_regs(regs); + ptr = output_buffer; + ptr= mem2hex((char *)regs,ptr,sizeof(s390_regs_common),FALSE); + ptr= mem2hex((char *)®s->crs[0],ptr,NUM_CRS*CR_SIZE,FALSE); + ptr = mem2hex((char *)®s->fp_regs, ptr,sizeof(s390_fp_regs)); + break; + + /* + * set the value of the CPU registers - return OK + * FIXME: Needs to be written + */ + case 'G': + ptr=input_buffer; + hex2mem (ptr, (char *)regs,sizeof(s390_regs_common), FALSE); + ptr+=sizeof(s390_regs_common)*2; + hex2mem (ptr, (char *)regs->crs[0],NUM_CRS*CR_SIZE, FALSE); + ptr+=NUM_CRS*CR_SIZE*2; + hex2mem (ptr, (char *)regs->fp_regs,sizeof(s390_fp_regs), FALSE); + gdb_stub_set_non_pt_regs(regs); + strcpy(output_buffer,"OK"); + break; + + /* + * mAA..AA,LLLL Read LLLL bytes at address AA..AA + */ + case 'm': + ptr = &input_buffer[1]; + + if (hexToInt(&ptr, &addr) + && *ptr++ == ',' + && hexToInt(&ptr, &length)) { + if (mem2hex((char *)addr, output_buffer, length, 1)) + break; + strcpy (output_buffer, "E03"); + } else + strcpy(output_buffer,"E01"); + break; + + /* + * MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK + */ + case 'M': + ptr = &input_buffer[1]; + + if (hexToInt(&ptr, &addr) + && *ptr++ == ',' + && hexToInt(&ptr, &length) + && *ptr++ == ':') { + if (hex2mem(ptr, (char *)addr, length, 1)) + strcpy(output_buffer, "OK"); + else + strcpy(output_buffer, "E03"); + } + else + strcpy(output_buffer, "E02"); + break; + + /* + * cAA..AA Continue at address AA..AA(optional) + */ + case 'c': + /* try to read optional parameter, pc unchanged if no parm */ + + ptr = &input_buffer[1]; + if (hexToInt(&ptr, &addr)) + regs->cp0_epc = addr; + + /* + * Need to flush the instruction cache here, as we may + * have deposited a breakpoint, and the icache probably + * has no way of knowing that a data ref to some location + * may have changed something that is in the instruction + * cache. + * NB: We flush both caches, just to be sure... + */ + + flush_cache_all(); + return; + /* NOTREACHED */ + break; + + + /* + * kill the program + */ + case 'k' : + break; /* do nothing */ + + + /* + * Reset the whole machine (FIXME: system dependent) + */ + case 'r': + break; + + + /* + * Step to next instruction + */ + case 's': + /* + * There is no single step insn in the MIPS ISA, so we + * use breakpoints and continue, instead. + */ + single_step(regs); + flush_cache_all(); + return; + /* NOTREACHED */ + + } + break; + + } /* switch */ + + /* + * reply to the request + */ + + putpacket(output_buffer); + + } /* while */ +} + +/* + * This function will generate a breakpoint exception. It is used at the + * beginning of a program to sync up with a debugger and can be used + * otherwise as a quick means to stop program execution and "break" into + * the debugger. + */ +void breakpoint(void) +{ + if (!gdb_stub_initialised) + return; + __asm__ __volatile__( + ".globl breakinst\n" + "breakinst:\t.word %0\n\t" + : + : "i" (S390_BREAKPOINT_U16) + : + ); +} + + + + + + + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/head.S linux/arch/s390/kernel/head.S --- v2.3.99-pre7/linux/arch/s390/kernel/head.S Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/head.S Fri May 12 11:41:44 2000 @@ -0,0 +1,668 @@ +/* + * arch/s390/kernel/head.S + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Hartmut Penner (hp@de.ibm.com), + * Martin Schwidefsky (schwidefsky@de.ibm.com), + * + * There are 4 different IPL methods + * 1) load the image directly into ram at address 0 and do an PSW restart + * 2) linload will load the image from address 0x10000 to memory 0x10000 + * and start the code thru LPSW 0x0008000080010000 (VM only, deprecated) + * 3) generate the tape ipl header, store the generated image on a tape + * and ipl from it + * 4) generate the vm reader ipl header, move the generated image to the + * VM reader (use option NOH!) and do a ipl from reader (VM only) + * We use the cpuid to distinguish between VM and native ipl + * params for kernel are pushed to 0x10400 (see setup.h) + */ + +#include +#include +#include + +#ifndef CONFIG_IPL + .org 0 + .long 0x00080000,0x80000000+iplstart # Just a restart PSW + +iplstart: + l %r12,.Lparm # pointer to parameter area +# +# find out memory size +# + mvc 104(8,0),.Lpcmem0 # setup program check handler + slr %r2,%r2 + lhi %r3,1 + sll %r3,20 +.Lloop0: + l %r0,0(%r2) # test page + ar %r2,%r3 # add 1M + jnm .Lloop0 # r1 < 0x80000000 -> loop +.Lchkmem0: + n %r2,.L4malign0 # align to multiples of 4M + st %r2,MEMORY_SIZE-PARMAREA(%r12) # store memory size + slr %r2,%r2 + st %r2,INITRD_SIZE-PARMAREA(%r12) # null ramdisk + st %r2,INITRD_START-PARMAREA(%r12) + j start + +.Lparm: .long PARMAREA +.L4malign0:.long 0xffc00000 + .align 8 +.Lpcmem0:.long 0x00080000,0x80000000 + .Lchkmem0 + +#else +#ifdef CONFIG_IPL_TAPE +#define IPL_BS 1024 + .org 0 + .long 0x00080000,0x80000000+iplstart # The first 24 bytes are loaded + .long 0x07000000,0x60000001 # by ipl to addresses 0-23. + .long 0x02000000,0x20000000+IPL_BS # (a PSW and two CCWs). + .long 0x00000000,0x00000000 # external old psw + .long 0x00000000,0x00000000 # svc old psw + .long 0x00000000,0x00000000 # program check old psw + .long 0x00000000,0x00000000 # machine check old psw + .long 0x00000000,0x00000000 # io old psw + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x000a0000,0x00000058 # external new psw + .long 0x000a0000,0x00000060 # svc new psw + .long 0x000a0000,0x00000068 # program check new psw + .long 0x000a0000,0x00000070 # machine check new psw + .long 0x00080000,0x80000000+.Lioint # io new psw + + .org 0x100 +iplstart: + l %r1,0xb8 # load ipl subchannel number + lhi %r2,IPL_BS # load start address + bras %r14,.Lloader # load rest of ipl image + st %r1,__LC_IPLDEV # store ipl device number + l %r12,.Lparm # pointer to parameter area + +# +# find out memory size +# + mvc 104(8,0),.Lpcmem0 # setup program check handler + slr %r2,%r2 + lhi %r3,1 + sll %r3,20 +.Lloop0: + l %r0,0(%r2) # test page + ar %r2,%r3 # add 1M + jnm .Lloop0 # r1 < 0x80000000 -> loop +.Lchkmem0: + n %r2,.L4malign0 # align to multiples of 4M + st %r2,MEMORY_SIZE-PARMAREA(%r12) # store memory size + c %r2,.Lbigmem # more than 64 MB of memory ? + jl .Lmemok # if yes load ramdisk to 32 MB + mvc INITRD_START-PARMAREA(4,%r12),.Lrdstart +.Lmemok: + +# +# load parameter file from tape +# + l %r2,INITRD_START-PARMAREA(%r12) # use ramdisk location as temp + bras %r14,.Lloader # load parameter file + ltr %r2,%r2 # got anything ? + jz .Lnopf + chi %r2,895 + jnh .Lnotrunc + lhi %r2,895 +.Lnotrunc: + l %r4,INITRD_START-PARMAREA(%r12) + la %r5,0(%r4,%r2) + lr %r3,%r2 +.Lidebc: + tm 0(%r5),0x80 # high order bit set ? + jo .Ldocv # yes -> convert from EBCDIC + ahi %r5,-1 + brct %r3,.Lidebc + j .Lnocv +.Ldocv: + l %r3,.Lcvtab + tr 0(256,%r4),0(%r3) # convert parameters to ascii + tr 256(256,%r4),0(%r3) + tr 512(256,%r4),0(%r3) + tr 768(122,%r4),0(%r3) +.Lnocv: la %r3,COMMAND_LINE-PARMAREA(%r12) # load adr. of command line + mvc 0(256,%r3),0(%r4) + mvc 256(256,%r3),256(%r4) + mvc 512(256,%r3),512(%r4) + mvc 768(122,%r3),768(%r4) + slr %r0,%r0 + j .Lcntlp +.Ldelspc: + ic %r0,0(%r2,%r3) + chi %r0,0x20 # is it a space ? + je .Lcntlp + ahi %r2,1 + j .Leolp +.Lcntlp: + brct %r2,.Ldelspc +.Leolp: + slr %r0,%r0 + stc %r0,0(%r2,%r3) # terminate buffer +.Lnopf: + +# +# load ramdisk from tape +# + l %r2,INITRD_START-PARMAREA(%r12) # load adr. of ramdisk + bras %r14,.Lloader # load ramdisk + st %r2,INITRD_SIZE-PARMAREA(%r12) # store size of ramdisk + ltr %r2,%r2 + jnz .Lrdcont + st %r2,INITRD_START-PARMAREA(%r12) # no ramdisk found, null it +.Lrdcont: +# +# everything loaded, go for it +# + j start +# +# subroutine for loading from tape +# Paramters: +# R1 = device number +# R2 = load address +.Lloader: + st %r14,.Lldret + la %r3,.Lorbread # r3 = address of orb + la %r5,.Lirb # r5 = address of irb + st %r2,.Lccwread+4 # initialize CCW data addresses + lctl %c6,%c6,.Lcr6 + slr %r2,%r2 +.Lldlp: + lhi %r6,3 # 3 retries +.Lssch: + ssch 0(%r3) # load chunk of IPL_BS bytes + jnz .Llderr +.Lw4end: + bras %r14,.Lwait4io + tm 8(%r5),0x82 # do we have a problem ? + jnz .Lrecov + slr %r7,%r7 + icm %r7,3,10(%r5) # get residual count + lcr %r7,%r7 + ahi %r7,IPL_BS # IPL_BS-residual=#bytes read + ar %r2,%r7 # add to total size + tm 8(%r5),0x01 # found a tape mark ? + jnz .Ldone + l %r0,.Lccwread+4 # update CCW data addresses + ar %r0,%r7 + st %r0,.Lccwread+4 + j .Lldlp +.Ldone: + l %r14,.Lldret + br %r14 # r2 contains the total size +.Lrecov: + bras %r14,.Lsense # do the sensing + brct %r6,.Lssch # dec. retry count & branch + j .Llderr +# +# Sense subroutine +# +.Lsense: + st %r14,.Lsnsret + la %r7,.Lorbsense + ssch 0(%r7) # start sense command + jnz .Llderr + bras %r14,.Lwait4io + l %r14,.Lsnsret + tm 8(%r5),0x82 # do we have a problem ? + jnz .Llderr + br %r14 +# +# Wait for interrupt subroutine +# +.Lwait4io: + lpsw .Lwaitpsw +.Lioint: + c %r1,0xb8 # compare subchannel number + jne .Lwait4io + tsch 0(%r5) + slr %r0,%r0 + tm 8(%r5),0x82 # do we have a problem ? + jnz .Lwtexit + tm 8(%r5),0x04 # got device end ? + jz .Lwait4io +.Lwtexit: + br %r14 +.Llderr: + lpsw .Lcrash + + .align 8 +.Lorbread: + .long 0x00000000,0x0080ff00,.Lccwread + .align 8 +.Lorbsense: + .long 0x00000000,0x0080ff00,.Lccwsense + .align 8 +.Lccwread: + .long 0x02200000+IPL_BS,0x00000000 +.Lccwsense: + .long 0x04200001,0x00000000 +.Lwaitpsw: + .long 0x020a0000,0x80000000+.Lioint + +.Lirb: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +.Lcr6: .long 0xff000000 + .align 8 +.Lcrash:.long 0x000a0000,0x00000000 +.Lpcmem0:.long 0x00080000,0x80000000 + .Lchkmem0 +.Lparm: .long PARMAREA +.L4malign0:.long 0xffc00000 +.Lbigmem:.long 0x04000000 +.Lrdstart:.long 0x02000000 +.Lldret:.long 0 +.Lsnsret: .long 0 +.Lcvtab:.long _ebcasc # ebcdic to ascii table + +#endif /* CONFIG_IPL_TAPE */ + +#ifdef CONFIG_IPL_VM + .org 0 + .long 0x00080000,0x80000000+iplstart # The first 24 bytes are loaded + .long 0x02000018,0x60000050 # by ipl to addresses 0-23. + .long 0x02000068,0x60000050 # (a PSW and two CCWs). + .fill 80-24,1,0x40 # bytes 24-79 are discarded !! + .long 0x020000f0,0x60000050 # The next 160 byte are loaded + .long 0x02000140,0x60000050 # to addresses 0x18-0xb7 + .long 0x02000190,0x60000050 # They form the continuation + .long 0x020001e0,0x60000050 # of the CCW program started + .long 0x02000230,0x60000050 # by ipl and load the range + .long 0x02000280,0x60000050 # 0x0f0-0x730 from the image + .long 0x020002d0,0x60000050 # to the range 0x0f0-0x730 + .long 0x02000320,0x60000050 # in memory. At the end of + .long 0x02000370,0x60000050 # the channel program the PSW + .long 0x020003c0,0x60000050 # at location 0 is loaded. + .long 0x02000410,0x60000050 # Initial processing starts + .long 0x02000460,0x60000050 # at 0xf0 = iplstart. + .long 0x020004b0,0x60000050 + .long 0x02000500,0x60000050 + .long 0x02000550,0x60000050 + .long 0x020005a0,0x60000050 + .long 0x020005f0,0x60000050 + .long 0x02000640,0x60000050 + .long 0x02000690,0x60000050 + .long 0x020006e0,0x20000050 + + + .org 0xf0 +iplstart: + l %r1,0xb8 # load ipl subchannel number + lhi %r2,0x730 # load start address + bras %r14,.Lloader # load rest of ipl image + st %r1,__LC_IPLDEV # store ipl device number + l %r12,.Lparm # pointer to parameter area + +# +# find out memory size +# + mvc 104(8,0),.Lpcmem0 # setup program check handler + slr %r2,%r2 + lhi %r3,1 + sll %r3,20 +.Lloop0: + l %r0,0(%r2) # test page + ar %r2,%r3 # add 1M + jnm .Lloop0 # r1 < 0x80000000 -> loop +.Lchkmem0: + n %r2,.L4malign0 # align to multiples of 4M + st %r2,MEMORY_SIZE-PARMAREA(%r12) # store memory size + c %r2,.Lbigmem # more than 64 MB of memory ? + jl .Lmemok # if yes load ramdisk to 32 MB + mvc INITRD_START-PARMAREA(4,%r12),.Lrdstart +.Lmemok: + +# +# load parameter file from reader +# + l %r2,INITRD_START-PARMAREA(%r12) # use ramdisk location as temp + bras %r14,.Lloader # load parameter file + ltr %r2,%r2 # got anything ? + jz .Lnopf + chi %r2,895 + jnh .Lnotrunc + lhi %r2,895 +.Lnotrunc: + l %r4,INITRD_START-PARMAREA(%r12) + la %r5,0(%r4,%r2) + lr %r3,%r2 +.Lidebc: + tm 0(%r5),0x80 # high order bit set ? + jo .Ldocv # yes -> convert from EBCDIC + ahi %r5,-1 + brct %r3,.Lidebc + j .Lnocv +.Ldocv: + l %r3,.Lcvtab + tr 0(256,%r4),0(%r3) # convert parameters to ascii + tr 256(256,%r4),0(%r3) + tr 512(256,%r4),0(%r3) + tr 768(122,%r4),0(%r3) +.Lnocv: la %r3,COMMAND_LINE-PARMAREA(%r12) # load adr. of command line + mvc 0(256,%r3),0(%r4) + mvc 256(256,%r3),256(%r4) + mvc 512(256,%r3),512(%r4) + mvc 768(122,%r3),768(%r4) + slr %r0,%r0 + j .Lcntlp +.Ldelspc: + ic %r0,0(%r2,%r3) + chi %r0,0x20 # is it a space ? + je .Lcntlp + ahi %r2,1 + j .Leolp +.Lcntlp: + brct %r2,.Ldelspc +.Leolp: + slr %r0,%r0 + stc %r0,0(%r2,%r3) # terminate buffer +.Lnopf: + +# +# load ramdisk from reader +# + l %r2,INITRD_START-PARMAREA(%r12) # load adr. of ramdisk + bras %r14,.Lloader # load ramdisk + st %r2,INITRD_SIZE-PARMAREA(%r12) # store size of ramdisk + ltr %r2,%r2 + jnz .Lrdcont + st %r2,INITRD_START-PARMAREA(%r12) # no ramdisk found, null it +.Lrdcont: + +# +# everything loaded, reset files in reader, then go for it +# + stidp __LC_CPUID # store cpuid + lh %r0,__LC_CPUID+4 # get cpu version + chi %r0,0x7490 # running on P/390 ? + je start # no -> skip reset + la %r2,.Lreset + lhi %r3,26 + .long 0x83230008 + j start + +# +# subroutine for loading cards from the reader +# +.Lloader: + la %r3,.Lorb # r2 = address of orb into r2 + la %r5,.Lirb # r4 = address of irb + la %r6,.Lccws + la %r7,20 +.Linit: + st %r2,4(%r6) # initialize CCW data addresses + ahi %r2,0x50 + ahi %r6,8 + brct 7,.Linit + + lctl %c6,%c6,.Lcr6 # set IO subclass mask + slr %r2,%r2 +.Lldlp: + ssch 0(%r3) # load chunk of 1600 bytes + jnz .Llderr +.Lwait4irq: + mvc __LC_IO_NEW_PSW(8),.Lnewpsw # set up IO interrupt psw + lpsw .Lwaitpsw +.Lioint: + c %r1,0xb8 # compare subchannel number + jne .Lwait4irq + tsch 0(%r5) + + slr %r0,%r0 + ic %r0,8(%r5) # get device status + chi %r0,8 # channel end ? + je .Lcont + chi %r0,12 # channel end + device end ? + je .Lcont + + l %r0,4(%r5) + s %r0,8(%r3) # r0/8 = number of ccws executed + mhi %r0,10 # *10 = number of bytes in ccws + lh %r3,10(%r5) # get residual count + sr %r0,%r3 # #ccws*80-residual=#bytes read + ar %r2,%r0 + + br %r14 # r2 contains the total size + +.Lcont: + ahi %r2,0x640 # add 0x640 to total size + la %r6,.Lccws + la %r7,20 +.Lincr: + l %r0,4(%r6) # update CCW data addresses + ahi %r0,0x640 + st %r0,4(%r6) + ahi %r6,8 + brct 7,.Lincr + + j .Lldlp +.Llderr: + lpsw .Lcrash + + .align 8 +.Lorb: .long 0x00000000,0x0080ff00,.Lccws +.Lirb: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +.Lcr6: .long 0xff000000 +.Lloadp:.long 0,0 +.Lparm: .long PARMAREA +.L4malign0:.long 0xffc00000 +.Lbigmem:.long 0x04000000 +.Lrdstart:.long 0x02000000 +.Lcvtab:.long _ebcasc # ebcdic to ascii table +.Lreset:.byte 0xc3,0xc8,0xc1,0xd5,0xc7,0xc5,0x40,0xd9,0xc4,0xd9,0x40 + .byte 0xc1,0xd3,0xd3,0x40,0xd2,0xc5,0xc5,0xd7,0x40,0xd5,0xd6 + .byte 0xc8,0xd6,0xd3,0xc4 # "change rdr all keep nohold" + .align 8 +.Lpcmem0:.long 0x00080000,0x80000000 + .Lchkmem0 +.Lcrash:.long 0x000a0000,0x00000000 +.Lnewpsw: + .long 0x00080000,0x80000000+.Lioint +.Lwaitpsw: + .long 0x020a0000,0x80000000+.Lioint + + .align 8 +.Lccws: .rept 19 + .long 0x02600050,0x00000000 + .endr + .long 0x02200050,0x00000000 + + .org 0x730 # end of the area loaded by the ipl channel program +#endif /* CONFIG_IPL_VM */ + +#endif /* CONFIG_IPL */ + +# +# startup-code at 0x10000, running in real mode +# this is called either by the ipl loader or directly by PSW restart or linload +# + .org 0x10000 + .globl start +start: basr %r13,0 # get base +.LPG1: lctl %c1,%c1,.Lpstd-.LPG1(%r13) # load pstd + lctl %c7,%c7,.Lpstd-.LPG1(%r13) # load sstd + lctl %c13,%c13,.Lpstd-.LPG1(%r13) # load hstd + lctl %c0,%c0,.Lcr0-.LPG1(%r13) # set CR0 + l %r12,.Lparm1-.LPG1(%r13) # pointer to parameter area + +# +# find out memory size. That is done in the ipl loader too but for +# ipl from dasd the size of the memory has to be detected too... +# + icm %r0,15,MEMORY_SIZE-PARMAREA(%r12) + jnz .Lsizeok + mvc 104(8,0),.Lpcmem-.LPG1(%r13) # setup program check handler + slr %r1,%r1 + lhi %r2,1 + sll %r2,20 +.Lloop: + l %r0,0(%r1) # test page + ar %r1,%r2 # add 1M + jnm .Lloop # r1 < 0x80000000 -> loop +.Lchkmem: + n %r1,.L4malign-.LPG1(%r13) # align to multiples of 4M + st %r1,MEMORY_SIZE-PARMAREA(%r12) # store memory size +.Lsizeok: + +# +# find out if we are running under VM +# + stidp __LC_CPUID # store cpuid + tm __LC_CPUID,0xff # running under VM ? + jno .Lnovm + oi MACHINE_FLAGS+3-PARMAREA(%r12),1 # set VM flag +.Lnovm: + lh %r0,__LC_CPUID+4 # get cpu version + chi %r0,0x7490 # running on a P/390 ? + jne .Lnop390 + oi MACHINE_FLAGS+3-PARMAREA(%r12),4 # set P/390 flag +.Lnop390: + +# +# find out if we have an IEEE fpu +# + mvc 104(8,0),.Lpcfpu-.LPG1(%r13) # setup program check handler + ld %f0,.Lflt0-.LPG1(%r13) # load (float) 0.0 + ldr %f2,%f0 + adbr %f0,%f2 # test IEEE add instruction + oi MACHINE_FLAGS+3-PARMAREA(%r12),2 # set IEEE fpu flag +.Lchkfpu: + + lpsw .Lentry-.LPG1(13) # jump to _stext in primary-space, + # virtual and never return ... + .align 8 +.Lentry:.long 0x04080000,0x80000000 + _stext +.Lpstd: .long .Lpgd+0x7F # segment-table +.Lcr0: .long 0x04b50002 +.Lpcmem:.long 0x00080000,0x80000000 + .Lchkmem +.Lpcfpu:.long 0x00080000,0x80000000 + .Lchkfpu +.Lflt0: .double 0 +.Lparm1:.long PARMAREA +.L4malign:.long 0xffc00000 + +# +# params at 10400 (setup.h) +# + .org PARMAREA + .long 0x0100 # ORIG_ROOT_DEV: ramdisk major/minor + .word 0 # MOUNT_ROOT_RDONLY: no + .long 0 # MEMORY_SIZE + .long 0 # MACHINE_FLAGS (bit 0:VM, bit 1:IEEE) + .long RAMDISK_ORIGIN # INITRD_START + .long 0x800000 # INITRD_SIZE + .word 0 # RAMDISK_FLAGS + + .org COMMAND_LINE +# .byte "root=/dev/nfs rw nfsroot=9.164.160.7:/home/mschwide/nfsboot " +# .byte "ip=9.164.147.12:9.164.160.7:9.164.147.1:255.255.255.0:vmlinux:tr0:off" +# .byte "root=/dev/nfs nfsroot=9.164.160.7:/home/mschwide/nfsboot " +# .byte "ip=9.164.181.228:9.164.160.7:9.164.181.1:255.255.224.0:vmlinux:tr0:off" +# .byte "root=/dev/nfs nfsroot=9.164.160.7:/home/pasch/nfsboot " +# .byte "ip=9.164.185.120:9.164.160.7:9.164.181.1:255.255.224.0:vmlinux:tr0:off" +# .byte "mdisk=402:65536:1229,403:131072:2780 root=/dev/mnda ro" +# .byte "root=/dev/nfs rw nfsroot=9.164.160.209:/usr/local/nfsboot " +# .byte "ip=9.164.181.228:9.164.160.209:9.164.181.1:255.255.224.0:vmlinux:tr0:off" + .byte "root=/dev/ram0 ro" +# .byte 0 + +# +# startup-code, running in virtual mode +# + .org 0x10800 + .globl _stext +_stext: basr %r13,0 # get base +.LPG2: +# +# Setup lowcore +# + l %r1,__LC_IPLDEV # load ipl device number + spx .Lprefix-.LPG2(%r13) # set prefix to linux lowcore + st %r1,__LC_IPLDEV # store ipl device number + l %r15,.Linittu-.LPG2(%r13) + ahi %r15,8192 # init_task_union + 8191 + st %r15,__LC_KERNEL_STACK # set end of kernel stack + ahi %r15,-96 + xc 0(4,%r15),0(%r15) # set backchain to zero + lhi %r0,-1 + st %r0,__LC_KERNEL_LEVEL # set interrupt count to -1 +# +# clear bss memory +# + l %r2,.Lbss_bgn-.LPG2(%r13) # start of bss + l %r3,.Lbss_end-.LPG2(%r13) # end of bss + sr %r3,%r2 # length of bss + sr %r4,%r4 # + sr %r5,%r5 # set src,length and pad to zero + sr %r0,%r0 # + mvcle %r2,%r4,0 # clear mem + jo .-4 # branch back, if not finish +# check control registers + stctl %c0,%c15,0(%r15) + oc 2(1,%r15),.Locbits+5-.LPG2(%r13) # enable sigp external ints. + oc 0(1,%r15),.Locbits+4-.LPG2(%r13) # low addresss proctection + lctl %c0,%c15,0(%r15) + +# + lam 0,15,.Laregs-.LPG2(%r13) # load access regs needed by uaccess + l %r14,.Lstart-.LPG2(%r13) + basr %r14,%r14 # call start_kernel +# +# We returned from start_kernel ?!? PANIK +# + basr %r13,0 + lpsw .Ldw-.(%r13) # load disabled wait psw +# +.Lstart: .long start_kernel + .align 8 +.Lprefix: .long init_S390_lowcore +.Linittu: .long init_task_union +.Lbss_bgn: .long __bss_start +.Lbss_end: .long _end +.Locbits: .long 0x01020408,0x10204080 + .align 4 +.Laregs: .long 0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0 + .align 8 +.Ldw: .long 0x000a0000,0x00000000 + +# +# tempory segment-table at 0x11000 +# + .org 0x11000 +.Lpgd: .long .Lpt0+0x1f # 00000000-000fffff + .long .Lpt1+0x1f # 00100000-001fffff + .long .Lpt2+0x1f # 00200000-002fffff + .long .Lpt3+0x1f # 00300000-003fffff + .fill 2044,4,0x20 # 00400000-7fffffff + +# +# tempory page-tables at 0x12000-0x15fff +# + .macro mktable from,to + .long \from*0x10000 + .long \from*0x10000+0x1000 + .long \from*0x10000+0x2000 + .long \from*0x10000+0x3000 + .long \from*0x10000+0x4000 + .long \from*0x10000+0x5000 + .long \from*0x10000+0x6000 + .long \from*0x10000+0x7000 + .long \from*0x10000+0x8000 + .long \from*0x10000+0x9000 + .long \from*0x10000+0xa000 + .long \from*0x10000+0xb000 + .long \from*0x10000+0xc000 + .long \from*0x10000+0xd000 + .long \from*0x10000+0xe000 + .long \from*0x10000+0xf000 + .if \to-\from + mktable "(\from+1)",\to + .endif + .endm + +.Lpt0: mktable 0,15 +.Lpt1: mktable 16,31 +.Lpt2: mktable 32,47 +.Lpt3: mktable 48,63 + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/ieee.h linux/arch/s390/kernel/ieee.h --- v2.3.99-pre7/linux/arch/s390/kernel/ieee.h Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/ieee.h Fri May 12 11:41:44 2000 @@ -0,0 +1,90 @@ +/* + * arch/s390/kernel/ieee.h + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), + */ + +#include + +static inline void _adddf(int R1,int R2) +{ + current->tss.fprs[R1].fd = current->tss.fprs[R1].fd + + current->tss.fprs[R2].fd; +} + +static inline void _subdf(int R1,int R2) +{ + current->tss.fprs[R1].fd = current->tss.fprs[R1].fd - + current->tss.fprs[R2].fd; +} + +static inline void _muldf(int R1,int R2) +{ + current->tss.fprs[R1].fd = current->tss.fprs[R1].fd * + current->tss.fprs[R2].fd; +} + +static inline void _divdf(int R1,int R2) +{ + current->tss.fprs[R1].fd = current->tss.fprs[R1].fd / + current->tss.fprs[R2].fd; +} + +static inline void _negdf(int R1,int R2) +{ + current->tss.fprs[R1].fd = -current->tss.fprs[R1].fd; +} + +static inline void _fixdfsi(int R1,int R2) +{ + current->tss.regs->gprs[R1] = (__u32) current->tss.fprs[R2].fd; +} + +static inline void _extendsidf(int R1,int R2) +{ + current->tss.fprs[R1].fd = (double) current->tss.regs->gprs[R2]; +} + + +static inline void _addsf(int R1,int R2) +{ + current->tss.fprs[R1].ff = current->tss.fprs[R1].ff + + current->tss.fprs[R2].ff; +} + +static inline void _subsf(int R1,int R2) +{ + current->tss.fprs[R1].ff = current->tss.fprs[R1].ff - + current->tss.fprs[R2].ff; +} + +static inline void _mulsf(int R1,int R2) +{ + current->tss.fprs[R1].ff = current->tss.fprs[R1].ff * + current->tss.fprs[R2].ff; +} + +static inline void _divsf(int R1,int R2) +{ + current->tss.fprs[R1].ff = current->tss.fprs[R1].ff / + current->tss.fprs[R2].ff; +} + +static inline void _negsf(int R1,int R2) +{ + current->tss.fprs[R1].ff = -current->tss.fprs[R1].ff; +} + +static inline void _fixsfsi(int R1,int R2) +{ + current->tss.regs->gprs[R1] = (__u32) current->tss.fprs[R2].ff; +} + +static inline void _extendsisf(int R1,int R2) +{ + current->tss.fprs[R1].ff = (double) current->tss.regs->gprs[R2]; +} + + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/init_task.c linux/arch/s390/kernel/init_task.c --- v2.3.99-pre7/linux/arch/s390/kernel/init_task.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/init_task.c Fri May 12 11:41:44 2000 @@ -0,0 +1,32 @@ +/* + * arch/s390/kernel/init_task.c + * + * S390 version + * + * Derived from "arch/i386/kernel/init_task.c" + */ + +#include +#include + +#include +#include + +static struct vm_area_struct init_mmap = INIT_MMAP; +static struct fs_struct init_fs = INIT_FS; +static struct files_struct init_files = INIT_FILES; +static struct signal_struct init_signals = INIT_SIGNALS; +struct mm_struct init_mm = INIT_MM(init_mm); + +/* + * Initial task structure. + * + * We need to make sure that this is 8192-byte aligned due to the + * way process stacks are handled. This is done by making sure + * the linker maps this in the .text segment right after head.S, + * and making head.S ensure the proper alignment. + * + * The things we do for performance.. + */ +union task_union init_task_union __attribute__((aligned(8192))) = + { INIT_TASK(init_task_union.task) }; diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/irq.c linux/arch/s390/kernel/irq.c --- v2.3.99-pre7/linux/arch/s390/kernel/irq.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/irq.c Fri May 12 11:41:44 2000 @@ -0,0 +1,427 @@ +/* + * arch/s390/kernel/irq.c + * + * S390 version + * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Ingo Adlung (adlung@de.ibm.com) + * + * Derived from "arch/i386/kernel/irq.c" + * Copyright (C) 1992, 1999 Linus Torvalds, Ingo Molnar + * + * S/390 I/O interrupt processing and I/O request processing is + * implemented in arch/s390/kernel/s390io.c + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +void s390_init_IRQ ( void ); +void s390_free_irq ( unsigned int irq, void *dev_id); +int s390_request_irq( unsigned int irq, + void (*handler)(int, void *, struct pt_regs *), + unsigned long irqflags, + const char *devname, + void *dev_id); + +atomic_t nmi_counter; + +#if 0 +/* + * The following vectors are part of the Linux architecture, there + * is no hardware IRQ pin equivalent for them, they are triggered + * through the ICC by us (IPIs), via smp_message_pass(): + */ +BUILD_SMP_INTERRUPT(reschedule_interrupt) +BUILD_SMP_INTERRUPT(invalidate_interrupt) +BUILD_SMP_INTERRUPT(stop_cpu_interrupt) +BUILD_SMP_INTERRUPT(mtrr_interrupt) +BUILD_SMP_INTERRUPT(spurious_interrupt) +#endif + +#if 0 +int get_irq_list(char *buf) +{ + int i, j; + struct irqaction * action; + char *p = buf; + + p += sprintf(p, " "); + + for (j=0; jirq_desc.action; + + if (!action) + continue; + + p += sprintf(p, "%3d: ",i); +#ifndef CONFIG_SMP + p += sprintf(p, "%10u ", kstat_irqs(i)); +#else + for (j=0; jirq_desc.handler->typename); + p += sprintf(p, " %s", action->name); + + for (action=action->next; action; action = action->next) + { + p += sprintf(p, ", %s", action->name); + + } /* endfor */ + + *p++ = '\n'; + + } /* endfor */ + + p += sprintf(p, "NMI: %10u\n", atomic_read(&nmi_counter)); +#ifdef CONFIG_SMP + p += sprintf(p, "IPI: %10u\n", atomic_read(&ipi_count)); +#endif + + return p - buf; +} +#endif + +/* + * Global interrupt locks for SMP. Allow interrupts to come in on any + * CPU, yet make cli/sti act globally to protect critical regions.. + */ +#ifdef CONFIG_SMP +atomic_t global_irq_holder = ATOMIC_INIT(NO_PROC_ID); +atomic_t global_irq_lock; +atomic_t global_irq_count = ATOMIC_INIT(0); +atomic_t global_bh_count; + +/* + * "global_cli()" is a special case, in that it can hold the + * interrupts disabled for a longish time, and also because + * we may be doing TLB invalidates when holding the global + * IRQ lock for historical reasons. Thus we may need to check + * SMP invalidate events specially by hand here (but not in + * any normal spinlocks) + * + * Thankfully we don't need this as we can deliver flush tlbs with + * interrupts disabled DJB :-) + */ +#define check_smp_invalidate(cpu) + +static void show(char * str) +{ + int i; + unsigned long *stack; + int cpu = smp_processor_id(); + + printk("\n%s, CPU %d:\n", str, cpu); + printk("irq: %d [%d]\n", + atomic_read(&global_irq_count),atomic_read(&S390_lowcore.local_irq_count)); + printk("bh: %d [%d]\n", + atomic_read(&global_bh_count),atomic_read(&S390_lowcore.local_bh_count)); + stack = (unsigned long *) &str; + for (i = 40; i ; i--) { + unsigned long x = *++stack; + if (x > (unsigned long) &init_task_union && x < (unsigned long) &vsprintf) { + printk("<[%08lx]> ", x); + } + } +} + +#define MAXCOUNT 100000000 + +static inline void wait_on_bh(void) +{ + int count = MAXCOUNT; + do { + if (!--count) { + show("wait_on_bh"); + count = ~0; + } + /* nothing .. wait for the other bh's to go away */ + } while (atomic_read(&global_bh_count) != 0); +} + +static inline void wait_on_irq(int cpu) +{ + int count = MAXCOUNT; + + for (;;) { + + /* + * Wait until all interrupts are gone. Wait + * for bottom half handlers unless we're + * already executing in one.. + */ + if (!atomic_read(&global_irq_count)) { + if (atomic_read(&safe_get_cpu_lowcore(cpu).local_bh_count)|| + !atomic_read(&global_bh_count)) + break; + } + + /* Duh, we have to loop. Release the lock to avoid deadlocks */ + clear_bit(0,&global_irq_lock); + + for (;;) { + if (!--count) { + show("wait_on_irq"); + count = ~0; + } + __sti(); + SYNC_OTHER_CORES(cpu); + __cli(); + check_smp_invalidate(cpu); + if (atomic_read(&global_irq_count)) + continue; + if (atomic_read(&global_irq_lock)) + continue; + if (!(atomic_read(&safe_get_cpu_lowcore(cpu).local_bh_count)) + && atomic_read(&global_bh_count)) + continue; + if (!test_and_set_bit(0,&global_irq_lock)) + break; + } + } +} + +/* + * This is called when we want to synchronize with + * bottom half handlers. We need to wait until + * no other CPU is executing any bottom half handler. + * + * Don't wait if we're already running in an interrupt + * context or are inside a bh handler. + */ +void synchronize_bh(void) +{ + if (atomic_read(&global_bh_count) && !in_interrupt()) + wait_on_bh(); +} + +/* + * This is called when we want to synchronize with + * interrupts. We may for example tell a device to + * stop sending interrupts: but to make sure there + * are no interrupts that are executing on another + * CPU we need to call this function. + */ +void synchronize_irq(void) +{ + if (atomic_read(&global_irq_count)) { + /* Stupid approach */ + cli(); + sti(); + } +} + +static inline void get_irqlock(int cpu) +{ + if (test_and_set_bit(0,&global_irq_lock)) { + /* do we already hold the lock? */ + if ( cpu == atomic_read(&global_irq_holder)) + return; + /* Uhhuh.. Somebody else got it. Wait.. */ + do { + do { + check_smp_invalidate(cpu); + } while (test_bit(0,&global_irq_lock)); + } while (test_and_set_bit(0,&global_irq_lock)); + } + /* + * We also to make sure that nobody else is running + * in an interrupt context. + */ + wait_on_irq(cpu); + + /* + * Ok, finally.. + */ + atomic_set(&global_irq_holder,cpu); +} + +#define EFLAGS_I_SHIFT 25 + +/* + * A global "cli()" while in an interrupt context + * turns into just a local cli(). Interrupts + * should use spinlocks for the (very unlikely) + * case that they ever want to protect against + * each other. + * + * If we already have local interrupts disabled, + * this will not turn a local disable into a + * global one (problems with spinlocks: this makes + * save_flags+cli+sti usable inside a spinlock). + */ +void __global_cli(void) +{ + unsigned int flags; + + __save_flags(flags); + if (flags & (1 << EFLAGS_I_SHIFT)) { + int cpu = smp_processor_id(); + __cli(); + if (!atomic_read(&S390_lowcore.local_irq_count)) + get_irqlock(cpu); + } +} + +void __global_sti(void) +{ + + if (!atomic_read(&S390_lowcore.local_irq_count)) + release_irqlock(smp_processor_id()); + __sti(); +} + +/* + * SMP flags value to restore to: + * 0 - global cli + * 1 - global sti + * 2 - local cli + * 3 - local sti + */ +unsigned long __global_save_flags(void) +{ + int retval; + int local_enabled; + unsigned long flags; + + __save_flags(flags); + local_enabled = (flags >> EFLAGS_I_SHIFT) & 1; + /* default to local */ + retval = 2 + local_enabled; + + /* check for global flags if we're not in an interrupt */ + if (!atomic_read(&S390_lowcore.local_irq_count)) + { + if (local_enabled) + retval = 1; + if (atomic_read(&global_irq_holder)== smp_processor_id()) + retval = 0; + } + return retval; +} + +void __global_restore_flags(unsigned long flags) +{ + switch (flags) { + case 0: + __global_cli(); + break; + case 1: + __global_sti(); + break; + case 2: + __cli(); + break; + case 3: + __sti(); + break; + default: + printk("global_restore_flags: %08lx (%08lx)\n", + flags, (&flags)[-1]); + } +} + +#endif + +/* + * Note : This fuction should be eliminated as it doesn't comply with the + * S/390 irq scheme we have implemented ... + */ +int handle_IRQ_event( unsigned int irq, int cpu, struct pt_regs * regs) +{ + struct irqaction * action; + int status; + + status = 0; + + if ( ioinfo[irq] == INVALID_STORAGE_AREA ) + return( -ENODEV); + + action = ioinfo[irq]->irq_desc.action; + + if (action) + { + status |= 1; + + if (!(action->flags & SA_INTERRUPT)) + __sti(); + + do + { + status |= action->flags; + action->handler(irq, action->dev_id, regs); + action = action->next; + } while (action); + + if (status & SA_SAMPLE_RANDOM) + add_interrupt_randomness(irq); + __cli(); + + } /* endif */ + + return status; +} + +void enable_nop(int irq) +{ +} + +void __init init_IRQ(void) +{ + s390_init_IRQ(); +} + + +void free_irq(unsigned int irq, void *dev_id) +{ + s390_free_irq( irq, dev_id); +} + + +int request_irq( unsigned int irq, + void (*handler)(int, void *, struct pt_regs *), + unsigned long irqflags, + const char *devname, + void *dev_id) +{ + return( s390_request_irq( irq, handler, irqflags, devname, dev_id ) ); + +} + +void init_irq_proc(void) +{ + /* For now, nothing... */ +} + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/irqextras390.c linux/arch/s390/kernel/irqextras390.c --- v2.3.99-pre7/linux/arch/s390/kernel/irqextras390.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/irqextras390.c Fri May 12 11:41:44 2000 @@ -0,0 +1,35 @@ +/* + * arch/s390/kernel/irqextras390.c + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), + * + * Some channel code by D.J. Barrow + */ + +/* + +*/ +#include +#include + +#if 0 +// fixchannelprogram is now obselete +void fixchannelprogram(orb_bits_t *orbptr) +{ + __u32 newAddress=orbptr->ccw_program_address; + fixccws(orbptr->ccw_program_address); + orbptr->ccw_program_address=newAddress; + orbptr->ccw_program_address=(ccw1_t *)(((__u32)orbptr->ccw_program_address)); +} +#endif + +void fixccws(ccw1_bits_t *ccwptr) +{ + for(;;ccwptr++) + { // Just hope nobody starts doing prefixing + if(!ccwptr->cc) + break; + } +} diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/lowcore.S linux/arch/s390/kernel/lowcore.S --- v2.3.99-pre7/linux/arch/s390/kernel/lowcore.S Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/lowcore.S Fri May 12 11:41:44 2000 @@ -0,0 +1,60 @@ +/* + * arch/s390/kernel/lowcore.S + * S390 lowcore definition. + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Hartmut Penner (hp@de.ibm.com) + * Martin Schwidefsky (schwidefsky@de.ibm.com), + */ + +#include + .align 4096 + .globl init_S390_lowcore +init_S390_lowcore: + .long _RESTART_PSW_MASK + .long restart_int_handler + _ADDR_31 + .long 0,0 + .long 0,0 +EXT_OLD: .long 0,0 +SVC_OLD: .long 0,0 +PGM_OLD: .long 0,0 +MCCK_OLD:.long 0,0 +IO_OLD: .long 0,0 + .long 0,0,0,0,0,0 +# +# new psws need all to be physical +# because we start with dat off +# +EXT_PSW: .long _EXT_PSW_MASK + .long ext_int_handler + _ADDR_31 +# +SVC_PSW: .long _SVC_PSW_MASK + .long system_call + _ADDR_31 +# +PGM_PSW: .long _PGM_PSW_MASK + .long pgm_check_handler + _ADDR_31 +# +MCCK_PSW:.long _MCCK_PSW_MASK + .long mcck_int_handler + _ADDR_31 +# +IO_PSW: .long _IO_PSW_MASK + .long io_int_handler + _ADDR_31 +# +# +# +EXTERNAL_PARAMETER: .long 0 +CPU_ADDRESS: .word 0 +EXT_INTERRUPT_CODE: .word 0 +SVC_ILC: .word 0 +SVC_CODE: .word 0 +PGM_ILC: .word 0 +PGM_CODE: .word 0 +TRANS_EXC_ADDR: .long 0 # 090 + .fill 0xC00-0x094,1,0 +SAVE_AREA: .fill 0x40,1,0 # C00 +KERNEL_STACK: .long 0 # C40 +KERNEL_LEVEL: .long 0 # C44 +CPUID: .long 0,0 # C48 + .fill 0x1000-0xC50,1,0 + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/mathemu.c linux/arch/s390/kernel/mathemu.c --- v2.3.99-pre7/linux/arch/s390/kernel/mathemu.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/mathemu.c Fri May 12 11:41:45 2000 @@ -0,0 +1,894 @@ +/* + * arch/s390/kernel/mathemu.c + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), + * + * 'mathemu.c' handles IEEE instructions on a S390 processor + * that does not have the IEEE fpu + */ + +#include +#include +#include + +#include +#include + +static void set_CC_df(__u64 val1,__u64 val2) { + int rc; + rc = __cmpdf2(val1,val2); + current->thread.regs->psw.mask &= 0xFFFFCFFF; + switch (rc) { + case -1: + current->thread.regs->psw.mask |= 0x00001000; + break; + case 1: + current->thread.regs->psw.mask |= 0x00002000; + break; + } +} + +static void set_CC_sf(__u32 val1,__u32 val2) { + int rc; + rc = __cmpsf2(val1,val2); + current->thread.regs->psw.mask &= 0xFFFFCFFF; + switch (rc) { + case -1: + current->thread.regs->psw.mask |= 0x00001000; + break; + case 1: + current->thread.regs->psw.mask |= 0x00002000; + break; + } +} + + +static void emu_adb (int rx, __u64 val) { + current->thread.fp_regs.fprs[rx].d = __adddf3(current->thread.fp_regs.fprs[rx].d,val); + set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL); +} + +static void emu_adbr (int rx, int ry) { + current->thread.fp_regs.fprs[rx].d = __adddf3(current->thread.fp_regs.fprs[rx].d, + current->thread.fp_regs.fprs[ry].d); + set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL); +} + +static void emu_aeb (int rx, __u32 val) { + current->thread.fp_regs.fprs[rx].f = __addsf3(current->thread.fp_regs.fprs[rx].f,val); + set_CC_sf(current->thread.fp_regs.fprs[rx].f,0); +} + +static void emu_aebr (int rx, int ry) { + current->thread.fp_regs.fprs[rx].f = __addsf3(current->thread.fp_regs.fprs[rx].f, + current->thread.fp_regs.fprs[ry].f); + set_CC_sf(current->thread.fp_regs.fprs[rx].f,0); +} + +static void emu_axbr (int rx, int ry) { + printk("axbr emulation not implemented!\n"); +} + +static void emu_cdb (int rx, __u64 val) { + set_CC_df(current->thread.fp_regs.fprs[rx].d,val); +} + +static void emu_cdbr (int rx, int ry) { + set_CC_df(current->thread.fp_regs.fprs[rx].d,current->thread.fp_regs.fprs[ry].d); +} + +static void emu_cdfbr (int rx, int ry) { + current->thread.fp_regs.fprs[rx].d = + __floatsidf(current->thread.regs->gprs[ry]); +} + +static void emu_ceb (int rx, __u32 val) { + set_CC_sf(current->thread.fp_regs.fprs[rx].f,val); +} + +static void emu_cebr (int rx, int ry) { + set_CC_sf(current->thread.fp_regs.fprs[rx].f,current->thread.fp_regs.fprs[ry].f); +} + +static void emu_cefbr (int rx, int ry) { + current->thread.fp_regs.fprs[rx].f = + __floatsisf(current->thread.regs->gprs[ry]); +} + +static void emu_cfdbr (int rx, int ry, int mask) { + current->thread.regs->gprs[rx] = + __fixdfsi(current->thread.fp_regs.fprs[ry].d); +} + +static void emu_cfebr (int rx, int ry, int mask) { + current->thread.regs->gprs[rx] = + __fixsfsi(current->thread.fp_regs.fprs[ry].f); +} + +static void emu_cfxbr (int rx, int ry, int mask) { + printk("cfxbr emulation not implemented!\n"); +} + +static void emu_cxbr (int rx, int ry) { + printk("cxbr emulation not implemented!\n"); +} + +static void emu_cxfbr (int rx, int ry) { + printk("cxfbr emulation not implemented!\n"); +} + +static void emu_ddb (int rx, __u64 val) { + current->thread.fp_regs.fprs[rx].d = __divdf3(current->thread.fp_regs.fprs[rx].d,val); + set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL); +} + +static void emu_ddbr (int rx, int ry) { + current->thread.fp_regs.fprs[rx].d = __divdf3(current->thread.fp_regs.fprs[rx].d, + current->thread.fp_regs.fprs[ry].d); + set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL); +} + +static void emu_deb (int rx, __u32 val) { + current->thread.fp_regs.fprs[rx].f = __divsf3(current->thread.fp_regs.fprs[rx].f,val); + set_CC_sf(current->thread.fp_regs.fprs[rx].f,0); +} + +static void emu_debr (int rx, int ry) { + current->thread.fp_regs.fprs[rx].f = __divsf3(current->thread.fp_regs.fprs[rx].f, + current->thread.fp_regs.fprs[ry].f); + set_CC_sf(current->thread.fp_regs.fprs[rx].f,0); +} + +static void emu_didbr (int rx, int ry, int mask) { + printk("didbr emulation not implemented!\n"); +} + +static void emu_diebr (int rx, int ry, int mask) { + printk("diebr emulation not implemented!\n"); +} + +static void emu_dxbr (int rx, int ry) { + printk("dxbr emulation not implemented!\n"); +} + +static void emu_efpc (int rx, int ry) { + printk("efpc emulation not implemented!\n"); +} + +static void emu_fidbr (int rx, int ry, int mask) { + printk("fidbr emulation not implemented!\n"); +} + +static void emu_fiebr (int rx, int ry, int mask) { + printk("fiebr emulation not implemented!\n"); +} + +static void emu_fixbr (int rx, int ry, int mask) { + printk("fixbr emulation not implemented!\n"); +} + +static void emu_kdb (int rx, __u64 val) { + printk("kdb emulation not implemented!\n"); +} + +static void emu_kdbr (int rx, int ry) { + printk("kdbr emulation not implemented!\n"); +} + +static void emu_keb (int rx, __u32 val) { + printk("keb emulation not implemented!\n"); +} + +static void emu_kebr (int rx, int ry) { + printk("kebr emulation not implemented!\n"); +} + +static void emu_kxbr (int rx, int ry) { + printk("kxbr emulation not implemented!\n"); +} + +static void emu_lcdbr (int rx, int ry) { + current->thread.fp_regs.fprs[rx].d = + __negdf2(current->thread.fp_regs.fprs[ry].d); + set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL); +} + +static void emu_lcebr (int rx, int ry) { + current->thread.fp_regs.fprs[rx].f = + __negsf2(current->thread.fp_regs.fprs[ry].f); + set_CC_sf(current->thread.fp_regs.fprs[rx].f,0); +} + +static void emu_lcxbr (int rx, int ry) { + printk("lcxbr emulation not implemented!\n"); +} + +static void emu_ldeb (int rx, __u32 val) { + current->thread.fp_regs.fprs[rx].d = __extendsfdf2(val); +} + +static void emu_ldebr (int rx, int ry) { + current->thread.fp_regs.fprs[rx].d = + __extendsfdf2(current->thread.fp_regs.fprs[ry].f); +} + +static void emu_ldxbr (int rx, int ry) { + printk("ldxbr emulation not implemented!\n"); +} + +static void emu_ledbr (int rx, int ry) { + current->thread.fp_regs.fprs[rx].f = __truncdfsf2(current->thread.fp_regs.fprs[ry].d); + set_CC_sf(current->thread.fp_regs.fprs[rx].f,0); +} + +static void emu_lexbr (int rx, int ry) { + printk("lexbr emulation not implemented!\n"); +} + +static void emu_lndbr (int rx, int ry) { + printk("lndbr emulation not implemented!\n"); +} + +static void emu_lnebr (int rx, int ry) { + printk("lnebr emulation not implemented!\n"); +} + +static void emu_lnxbr (int rx, int ry) { + printk("lnxbr emulation not implemented!\n"); +} + +static void emu_lpdbr (int rx, int ry) { + current->thread.fp_regs.fprs[rx].d = __absdf2(current->thread.fp_regs.fprs[ry].d); + set_CC_df(current->thread.fp_regs.fprs[rx].d,0); +} + +static void emu_lpebr (int rx, int ry) { + current->thread.fp_regs.fprs[rx].f = __abssf2(current->thread.fp_regs.fprs[ry].f); + set_CC_sf(current->thread.fp_regs.fprs[rx].f,0); +} + +static void emu_lpxbr (int rx, int ry) { + printk("lpxbr emulation not implemented!\n"); +} + +static void emu_ltdbr (int rx, int ry) { + current->thread.fp_regs.fprs[rx].d = current->thread.fp_regs.fprs[ry].d; + set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL); +} + +static void emu_ltebr (int rx, int ry) { + current->thread.fp_regs.fprs[rx].f = current->thread.fp_regs.fprs[ry].f; + set_CC_sf(current->thread.fp_regs.fprs[rx].f,0); +} + +static void emu_ltxbr (int rx, int ry) { + printk("ltxbr emulation not implemented!\n"); +} + +static void emu_lxdb (int rx, __u64 val) { + printk("lxdb emulation not implemented!\n"); +} + +static void emu_lxdbr (int rx, int ry) { + printk("lxdbr emulation not implemented!\n"); +} + +static void emu_lxeb (int rx, __u32 val) { + printk("lxeb emulation not implemented!\n"); +} + +static void emu_lxebr (int rx, int ry) { + printk("lxebr emulation not implemented!\n"); +} + +static void emu_madb (int rx, __u64 val, int mask) { + printk("madb emulation not implemented!\n"); +} + +static void emu_madbr (int rx, int ry, int mask) { + printk(" emulation not implemented!\n"); +} + +static void emu_maeb (int rx, __u32 val, int mask) { + printk("maeb emulation not implemented!\n"); +} + +static void emu_maebr (int rx, int ry, int mask) { + printk("maebr emulation not implemented!\n"); +} + +static void emu_mdb (int rx, __u64 val) { + current->thread.fp_regs.fprs[rx].d = __muldf3(current->thread.fp_regs.fprs[rx].d,val); + set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL); +} + +static void emu_mdbr (int rx, int ry) { + current->thread.fp_regs.fprs[rx].d = __muldf3(current->thread.fp_regs.fprs[rx].d, + current->thread.fp_regs.fprs[ry].d); + set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL); +} + +static void emu_mdeb (int rx, __u32 val) { + printk("mdeb emulation not implemented!\n"); +} + +static void emu_mdebr (int rx, int ry) { + printk("mdebr emulation not implemented!\n"); +} + +static void emu_meeb (int rx, __u32 val) { + current->thread.fp_regs.fprs[rx].f = __mulsf3(current->thread.fp_regs.fprs[rx].f, + val); + set_CC_sf(current->thread.fp_regs.fprs[rx].f,0); +} + +static void emu_meebr (int rx, int ry) { + current->thread.fp_regs.fprs[rx].f = __mulsf3(current->thread.fp_regs.fprs[rx].f, + current->thread.fp_regs.fprs[ry].f); + set_CC_sf(current->thread.fp_regs.fprs[rx].f,0); +} + +static void emu_msdb (int rx, __u64 val, int mask) { + printk("msdb emulation not implemented!\n"); +} + +static void emu_msdbr (int rx, int ry, int mask) { + printk("msdbr emulation not implemented!\n"); +} + +static void emu_mseb (int rx, __u32 val, int mask) { + printk("mseb emulation not implemented!\n"); +} + +static void emu_msebr (int rx, int ry, int mask) { + printk("msebr emulation not implemented!\n"); +} + +static void emu_mxbr (int rx, int ry) { + printk("mxbr emulation not implemented!\n"); +} + +static void emu_mxdb (int rx, __u64 val) { + printk("mxdb emulation not implemented!\n"); +} + +static void emu_mxdbr (int rx, int ry) { + printk("mxdbr emulation not implemented!\n"); +} + +static void emu_sdb (int rx, __u64 val) { + current->thread.fp_regs.fprs[rx].d = __subdf3(current->thread.fp_regs.fprs[rx].d, + val); + set_CC_sf(current->thread.fp_regs.fprs[rx].d,0ULL); +} + +static void emu_sdbr (int rx, int ry) { + current->thread.fp_regs.fprs[rx].d = __subdf3(current->thread.fp_regs.fprs[rx].d, + current->thread.fp_regs.fprs[ry].d); + set_CC_sf(current->thread.fp_regs.fprs[rx].d,0ULL); +} + +static void emu_seb (int rx, __u32 val) { + current->thread.fp_regs.fprs[rx].f = __subsf3(current->thread.fp_regs.fprs[rx].f, + val); + set_CC_sf(current->thread.fp_regs.fprs[rx].f,0); +} + +static void emu_sebr (int rx, int ry) { + current->thread.fp_regs.fprs[rx].f = __subsf3(current->thread.fp_regs.fprs[rx].f, + current->thread.fp_regs.fprs[ry].f); + set_CC_sf(current->thread.fp_regs.fprs[rx].f,0); +} + +static void emu_sfpc (int rx, int ry) { + printk("sfpc emulation not implemented!\n"); +} + +static void emu_sqdb (int rx, __u64 val) { + printk("sqdb emulation not implemented!\n"); +} + +static void emu_sqdbr (int rx, int ry) { + printk("sqdbr emulation not implemented!\n"); +} + +static void emu_sqeb (int rx, __u32 val) { + printk("sqeb emulation not implemented!\n"); +} + +static void emu_sqebr (int rx, int ry) { + printk("sqebr emulation not implemented!\n"); +} + +static void emu_sqxbr (int rx, int ry) { + printk("sqxbr emulation not implemented!\n"); +} + +static void emu_sxbr (int rx, int ry) { + printk("sxbr emulation not implemented!\n"); +} + +static void emu_tcdb (int rx, __u64 val) { + printk("tcdb emulation not implemented!\n"); +} + +static void emu_tceb (int rx, __u32 val) { + printk("tceb emulation not implemented!\n"); +} + +static void emu_tcxb (int rx, __u64 val) { + printk("tcxb emulation not implemented!\n"); +} + + +static inline void emu_load_regd(int reg) { + if ((reg&9) == 0) { /* test if reg in {0,2,4,6} */ + __asm__ __volatile ( /* load reg from fp_regs.fprs[reg] */ + " bras 1,0f\n" + " ld 0,0(%1)\n" + "0: ex %0,0(1)" + : /* no output */ + : "a" (reg<<4), "a" (¤t->thread.fp_regs.fprs[reg].d) + : "1" ); + } +} + +static inline void emu_load_rege(int reg) { + if ((reg&9) == 0) { /* test if reg in {0,2,4,6} */ + __asm__ __volatile ( /* load reg from fp_regs.fprs[reg] */ + " bras 1,0f\n" + " le 0,0(%1)\n" + "0: ex %0,0(1)" + : /* no output */ + : "a" (reg<<4), "a" (¤t->thread.fp_regs.fprs[reg].f) + : "1" ); + } +} + +static inline void emu_store_regd(int reg) { + if ((reg&9) == 0) { /* test if reg in {0,2,4,6} */ + __asm__ __volatile ( /* store reg to fp_regs.fprs[reg] */ + " bras 1,0f\n" + " std 0,0(%1)\n" + "0: ex %0,0(1)" + : /* no output */ + : "a" (reg<<4), "a" (¤t->thread.fp_regs.fprs[reg].d) + : "1" ); + } +} + + +static inline void emu_store_rege(int reg) { + if ((reg&9) == 0) { /* test if reg in {0,2,4,6} */ + __asm__ __volatile ( /* store reg to fp_regs.fprs[reg] */ + " bras 1,0f\n" + " ste 0,0(%1)\n" + "0: ex %0,0(1)" + : /* no output */ + : "a" (reg<<4), "a" (¤t->thread.fp_regs.fprs[reg].f) + : "1" ); + } +} + +int math_emu_b3(__u8 *opcode, struct pt_regs * regs) { + static const __u8 format_table[] = { + 2, 2, 2, 2, 9, 1, 2, 1, 2, 2, 2, 2, 9, 2, 4, 4, + 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 3, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1,10, 1, 1, 3, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 3, 0, 0, 0, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 5, 6, 6, 0, 7, 8, 8, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + static const void *jump_table[]= { + emu_lpebr, emu_lnebr, emu_ltebr, emu_lcebr, + emu_ldebr, emu_lxdbr, emu_lxebr, emu_mxdbr, + emu_kebr, emu_cebr, emu_aebr, emu_sebr, + emu_mdebr, emu_debr, emu_maebr, emu_msebr, + emu_lpdbr, emu_lndbr, emu_ltdbr, emu_lcdbr, + emu_sqebr, emu_sqdbr, emu_sqxbr, emu_meebr, + emu_kdbr, emu_cdbr, emu_adbr, emu_sdbr, + emu_mdbr, emu_ddbr, emu_madbr, emu_msdbr, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + emu_lpxbr, emu_lnxbr, emu_ltxbr, emu_lcxbr, + emu_ledbr, emu_ldxbr, emu_lexbr, emu_fixbr, + emu_kxbr, emu_cxbr, emu_axbr, emu_sxbr, + emu_mxbr, emu_dxbr, NULL, NULL, + NULL, NULL, NULL, emu_diebr, + NULL, NULL, NULL, emu_fiebr, + NULL, NULL, NULL, emu_didbr, + NULL, NULL, NULL, emu_fidbr, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + emu_sfpc, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + emu_efpc, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + emu_cefbr, emu_cdfbr, emu_cxfbr, NULL, + emu_cfebr, emu_cfdbr, emu_cfxbr + }; + + switch (format_table[opcode[1]]) { + case 1: /* RRE format, double operation */ + emu_store_regd((opcode[3]>>4)&15); + emu_store_regd(opcode[3]&15); + /* call the emulation function */ + ((void (*)(int, int))jump_table[opcode[1]]) + (opcode[3]>>4,opcode[3]&15); + emu_load_regd((opcode[3]>>4)&15); + emu_load_regd(opcode[3]&15); + return 0; + case 2: /* RRE format, float operation */ + emu_store_rege((opcode[3]>>4)&15); + emu_store_rege(opcode[3]&15); + /* call the emulation function */ + ((void (*)(int, int))jump_table[opcode[1]]) + (opcode[3]>>4,opcode[3]&15); + emu_load_rege((opcode[3]>>4)&15); + emu_load_rege(opcode[3]&15); + return 0; + case 3: /* RRF format, double operation */ + emu_store_regd((opcode[3]>>4)&15); + emu_store_regd(opcode[3]&15); + /* call the emulation function */ + ((void (*)(int, int, int))jump_table[opcode[1]]) + (opcode[3]>>4,opcode[3]&15,opcode[2]>>4); + emu_load_regd((opcode[3]>>4)&15); + emu_load_regd(opcode[3]&15); + return 0; + case 4: /* RRF format, float operation */ + emu_store_rege((opcode[3]>>4)&15); + emu_store_rege(opcode[3]&15); + /* call the emulation function */ + ((void (*)(int, int, int))jump_table[opcode[1]]) + (opcode[3]>>4,opcode[3]&15,opcode[2]>>4); + emu_load_rege((opcode[3]>>4)&15); + emu_load_rege(opcode[3]&15); + return 0; + case 5: /* RRE format, cefbr instruction */ + emu_store_rege((opcode[3]>>4)&15); + /* call the emulation function */ + ((void (*)(int, int))jump_table[opcode[1]]) + (opcode[3]>>4,opcode[3]&15); + emu_load_rege((opcode[3]>>4)&15); + return 0; + case 6: /* RRE format, cdfbr & cxfbr instruction */ + emu_store_regd((opcode[3]>>4)&15); + /* call the emulation function */ + ((void (*)(int, int))jump_table[opcode[1]]) + (opcode[3]>>4,opcode[3]&15); + emu_load_regd((opcode[3]>>4)&15); + return 0; + /* FIXME !! */ + return 0; + case 7: /* RRF format, cfebr instruction */ + emu_store_rege(opcode[3]&15); + /* call the emulation function */ + ((void (*)(int, int, int))jump_table[opcode[1]]) + (opcode[3]>>4,opcode[3]&15,opcode[2]>>4); + return 0; + case 8: /* RRF format, cfdbr & cfxbr instruction */ + emu_store_regd(opcode[3]&15); + /* call the emulation function */ + ((void (*)(int, int, int))jump_table[opcode[1]]) + (opcode[3]>>4,opcode[3]&15,opcode[2]>>4); + return 0; + case 9: /* RRE format, ldebr & mdebr instruction */ + /* float store but double load */ + emu_store_rege((opcode[3]>>4)&15); + emu_store_rege(opcode[3]&15); + /* call the emulation function */ + ((void (*)(int, int))jump_table[opcode[1]]) + (opcode[3]>>4,opcode[3]&15); + emu_load_regd((opcode[3]>>4)&15); + return 0; + case 10: /* RRE format, ledbr instruction */ + /* double store but float load */ + emu_store_regd((opcode[3]>>4)&15); + emu_store_regd(opcode[3]&15); + /* call the emulation function */ + ((void (*)(int, int))jump_table[opcode[1]]) + (opcode[3]>>4,opcode[3]&15); + emu_load_rege((opcode[3]>>4)&15); + return 0; + default: + return 1; + } +} + +static void* calc_addr(struct pt_regs *regs,int rx,int rb,int disp) +{ + rx &= 0xf; + rb &= 0xf; + disp &= 0xfff; + return (void*) ((rx != 0 ? regs->gprs[rx] : 0) + /* index */ + (rb != 0 ? regs->gprs[rb] : 0) + /* base */ + disp); +} + +int math_emu_ed(__u8 *opcode, struct pt_regs * regs) { + static const __u8 format_table[] = { + 0, 0, 0, 0, 5, 1, 2, 1, 2, 2, 2, 2, 5, 2, 4, 4, + 2, 1, 1, 0, 2, 1, 0, 2, 1, 1, 1, 1, 1, 1, 3, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + static const void *jump_table[]= { + NULL, NULL, NULL, NULL, + emu_ldeb, emu_lxdb, emu_lxeb, emu_mxdb, + emu_keb, emu_ceb, emu_aeb, emu_seb, + emu_mdeb, emu_deb, emu_maeb, emu_mseb, + emu_tceb, emu_tcdb, emu_tcxb, NULL, + emu_sqeb, emu_sqdb, NULL, emu_meeb, + emu_kdb, emu_cdb, emu_adb, emu_sdb, + emu_mdb, emu_ddb, emu_madb, emu_msdb + }; + + switch (format_table[opcode[5]]) { + case 1: /* RXE format, __u64 constant */ { + __u64 *dxb, temp; + __u32 opc; + + emu_store_regd((opcode[1]>>4)&15); + opc = *((__u32 *) opcode); + dxb = (__u64 *) calc_addr(regs,opc>>16,opc>>12,opc); + /* FIXME: how to react if copy_from_user fails ? */ + copy_from_user(&temp, dxb, 8); + /* call the emulation function */ + ((void (*)(int, __u64))jump_table[opcode[5]]) + (opcode[1]>>4,temp); + emu_load_regd((opcode[1]>>4)&15); + return 0; + } + case 2: /* RXE format, __u32 constant */ { + __u32 *dxb, temp; + __u32 opc; + + emu_store_rege((opcode[1]>>4)&15); + opc = *((__u32 *) opcode); + dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc); + /* FIXME: how to react if get_user fails ? */ + get_user(temp, dxb); + /* call the emulation function */ + ((void (*)(int, __u32))jump_table[opcode[5]]) + (opcode[1]>>4,temp); + emu_load_rege((opcode[1]>>4)&15); + return 0; + } + case 3: /* RXF format, __u64 constant */ { + __u32 *dxb, temp; + __u32 opc; + + emu_store_regd((opcode[1]>>4)&15); + opc = *((__u32 *) opcode); + dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc); + /* FIXME: how to react if copy_from_user fails ? */ + copy_from_user(&temp, dxb, 8); + /* call the emulation function */ + ((void (*)(int, __u32, int))jump_table[opcode[5]]) + (opcode[1]>>4,temp,opcode[4]>>4); + emu_load_regd((opcode[1]>>4)&15); + return 0; + } + case 4: /* RXF format, __u32 constant */ { + __u32 *dxb, temp; + __u32 opc; + + emu_store_rege((opcode[1]>>4)&15); + opc = *((__u32 *) opcode); + dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc); + /* FIXME: how to react if get_user fails ? */ + get_user(temp, dxb); + /* call the emulation function */ + ((void (*)(int, __u32, int))jump_table[opcode[5]]) + (opcode[1]>>4,temp,opcode[4]>>4); + emu_load_rege((opcode[1]>>4)&15); + return 0; + } + case 5: /* RXE format, __u32 constant */ + /* store_rege and load_regd */ + { + __u32 *dxb, temp; + __u32 opc; + emu_store_rege((opcode[1]>>4)&15); + opc = *((__u32 *) opcode); + dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc); + /* FIXME: how to react if get_user fails ? */ + get_user(temp, dxb); + /* call the emulation function */ + ((void (*)(int, __u32))jump_table[opcode[5]]) + (opcode[1]>>4,temp); + emu_load_regd((opcode[1]>>4)&15); + return 0; + } + default: + return 1; + } +} + +/* + * Emulate LDR Rx,Ry with Rx or Ry not in {0, 2, 4, 6} + */ +void math_emu_ldr(__u8 *opcode) { + __u16 opc = *((__u16 *) opcode); + + if ((opc & 0x0090) == 0) { /* test if rx in {0,2,4,6} */ + /* we got an exception therfore ry can't be in {0,2,4,6} */ + __asm__ __volatile ( /* load rx from fp_regs.fprs[ry] */ + " bras 1,0f\n" + " ld 0,0(%1)\n" + "0: ex %0,0(1)" + : /* no output */ + : "a" (opc&0x00f0), + "a" (¤t->thread.fp_regs.fprs[opc&0x000f].d) + : "1" ); + } else if ((opc & 0x0009) == 0) { /* test if ry in {0,2,4,6} */ + __asm__ __volatile ( /* store ry to fp_regs.fprs[rx] */ + " bras 1,0f\n" + " std 0,0(%1)\n" + "0: ex %0,0(1)" + : /* no output */ + : "a" ((opc&0x000f)<<4), + "a" (¤t->thread.fp_regs.fprs[(opc&0x00f0)>>4].d) + : "1" ); + } else { /* move fp_regs.fprs[ry] to fp_regs.fprs[rx] */ + current->thread.fp_regs.fprs[(opc&0x00f0)>>4] = + current->thread.fp_regs.fprs[opc&0x000f]; + } +} + +/* + * Emulate LER Rx,Ry with Rx or Ry not in {0, 2, 4, 6} + */ +void math_emu_ler(__u8 *opcode) { + __u16 opc = *((__u16 *) opcode); + + if ((opc & 0x0090) == 0) { /* test if rx in {0,2,4,6} */ + /* we got an exception therfore ry can't be in {0,2,4,6} */ + __asm__ __volatile ( /* load rx from fp_regs.fprs[ry] */ + " bras 1,0f\n" + " le 0,0(%1)\n" + "0: ex %0,0(1)" + : /* no output */ + : "a" (opc&0x00f0), + "a" (¤t->thread.fp_regs.fprs[opc&0x000f].f) + : "1" ); + } else if ((opc & 0x0009) == 0) { /* test if ry in {0,2,4,6} */ + __asm__ __volatile ( /* store ry to fp_regs.fprs[rx] */ + " bras 1,0f\n" + " ste 0,0(%1)\n" + "0: ex %0,0(1)" + : /* no output */ + : "a" ((opc&0x000f)<<4), + "a" (¤t->thread.fp_regs.fprs[(opc&0x00f0)>>4].f) + : "1" ); + } else { /* move fp_regs.fprs[ry] to fp_regs.fprs[rx] */ + current->thread.fp_regs.fprs[(opc&0x00f0)>>4] = + current->thread.fp_regs.fprs[opc&0x000f]; + } +} + +/* + * Emulate LD R,D(X,B) with R not in {0, 2, 4, 6} + */ +void math_emu_ld(__u8 *opcode, struct pt_regs * regs) { + __u32 opc = *((__u32 *) opcode); + __u64 *dxb; + + dxb = (__u64 *) calc_addr(regs,opc>>16,opc>>12,opc); + /* FIXME: how to react if copy_from_user fails ? */ + copy_from_user(¤t->thread.fp_regs.fprs[(opc>>20)&15].d, dxb, 8); +} + +/* + * Emulate LE R,D(X,B) with R not in {0, 2, 4, 6} + */ +void math_emu_le(__u8 *opcode, struct pt_regs * regs) { + __u32 opc = *((__u32 *) opcode); + __u32 *mem, *dxb; + + dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc); + /* FIXME: how to react if get_user fails ? */ + mem = (__u32 *) (¤t->thread.fp_regs.fprs[(opc>>20)&15].f); + get_user(mem[0], dxb); +} + +/* + * Emulate STD R,D(X,B) with R not in {0, 2, 4, 6} + */ +void math_emu_std(__u8 *opcode, struct pt_regs * regs) { + __u32 opc = *((__u32 *) opcode); + __u64 *dxb; + dxb = (__u64 *) calc_addr(regs,opc>>16,opc>>12,opc); + /* FIXME: how to react if copy_to_user fails ? */ + copy_to_user(dxb, ¤t->thread.fp_regs.fprs[(opc>>20)&15].d, 8); +} + +/* + * Emulate STE R,D(X,B) with R not in {0, 2, 4, 6} + */ +void math_emu_ste(__u8 *opcode, struct pt_regs * regs) { + __u32 opc = *((__u32 *) opcode); + __u32 *mem, *dxb; + dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc); + /* FIXME: how to react if put_user fails ? */ + mem = (__u32 *) (¤t->thread.fp_regs.fprs[(opc>>20)&15].f); + put_user(mem[0], dxb); +} + +/* + * Emulate LFPC D(B) + */ +int math_emu_lfpc(__u8 *opcode, struct pt_regs *regs) { + /* FIXME: how to do that ?!? */ + return 0; +} + +/* + * Emulate STFPC D(B) + */ +int math_emu_stfpc(__u8 *opcode, struct pt_regs *regs) { + /* FIXME: how to do that ?!? */ + return 0; +} + +/* + * Emulate SRNM D(B) + */ +int math_emu_srnm(__u8 *opcode, struct pt_regs *regs) { + /* FIXME: how to do that ?!? */ + return 0; +} + + + + + + + + + + + + + + + + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/process.c linux/arch/s390/kernel/process.c --- v2.3.99-pre7/linux/arch/s390/kernel/process.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/process.c Fri May 12 11:41:45 2000 @@ -0,0 +1,431 @@ +/* + * arch/s390/kernel/process.c + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), + * Hartmut Penner (hp@de.ibm.com), + * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), + * + * Derived from "arch/i386/kernel/process.c" + * Copyright (C) 1995, Linus Torvalds + */ + +/* + * This file handles the architecture-dependent parts of process handling.. + */ + +#define __KERNEL_SYSCALLS__ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +spinlock_t semaphore_wake_lock = SPIN_LOCK_UNLOCKED; + +asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); + +/* + * The idle loop on a S390... + */ + +static psw_t wait_psw; + +int cpu_idle(void *unused) +{ + /* endless idle loop with no priority at all */ + init_idle(); + current->priority = 0; + current->counter = -100; + wait_psw.mask = _WAIT_PSW_MASK; + wait_psw.addr = (unsigned long) &&idle_wakeup | 0x80000000L; + while(1) { + if (softirq_state[smp_processor_id()].active & + softirq_state[smp_processor_id()].mask) { + do_softirq(); + continue; + } + if (current->need_resched) { + schedule(); + check_pgt_cache(); + continue; + } + + /* load wait psw */ + asm volatile ( + "lpsw %0" + : : "m" (wait_psw) ); +idle_wakeup: + } +} + +/* + As all the register will only be made displayable to the root + user ( via printk ) or checking if the uid of the user is 0 from + the /proc filesystem please god this will be secure enough DJB. + The lines are given one at a time so as not to chew stack space in + printk on a crash & also for the proc filesystem when you get + 0 returned you know you've got all the lines + */ + +int sprintf_regs(int line, char *buff, struct task_struct * task, + struct thread_struct *thread, struct pt_regs * regs) +{ + int linelen=0; + int regno,chaincnt; + u32 backchain,prev_backchain,endchain; + + enum + { + sp_linefeed, + sp_psw, + sp_ksp, + sp_gprs, + sp_gprs1, + sp_gprs2, + sp_gprs3, + sp_gprs4, + sp_acrs, + sp_acrs1, + sp_acrs2, + sp_acrs3, + sp_acrs4, + sp_kern_backchain, + sp_kern_backchain1 + }; + + if(task) + thread = &task->thread; + if(thread) + regs = thread->regs; + switch (line) { + case sp_linefeed: + linelen=sprintf(buff,"\n"); + break; + case sp_psw: + if(regs) + linelen = sprintf(buff,"User PSW: %08lx %08lx\n", + (unsigned long) regs->psw.mask, + (unsigned long) regs->psw.addr); + else + linelen = sprintf(buff,"pt_regs=NULL some info unavailable\n"); + break; + case sp_ksp: + if (task) + linelen += sprintf(&buff[linelen], + "task: %08x ", (addr_t)task); + if (thread) + linelen += sprintf(&buff[linelen], + "thread: %08x ksp: %08x ", + (addr_t)thread,(addr_t)thread->ksp); + if (regs) + linelen += sprintf(&buff[linelen], + "pt_regs: %08x\n", (addr_t)regs); + break; + case sp_gprs: + if (regs) + linelen = sprintf(buff,"User GPRS:\n"); + break; + case sp_gprs1 ... sp_gprs4: + if (regs) { + regno = (line-sp_gprs1)*4; + linelen = sprintf(buff,"%08x %08x %08x %08x\n", + regs->gprs[regno], + regs->gprs[regno+1], + regs->gprs[regno+2], + regs->gprs[regno+3]); + } + break; + case sp_acrs: + if (regs) + linelen = sprintf(buff,"User ACRS:\n"); + break; + case sp_acrs1 ... sp_acrs4: + if (regs) { + regno = (line-sp_acrs1)*4; + linelen = sprintf(buff,"%08x %08x %08x %08x\n", + regs->acrs[regno], + regs->acrs[regno+1], + regs->acrs[regno+2], + regs->acrs[regno+3]); + } + break; + case sp_kern_backchain: + if (thread && thread->ksp && regs) + linelen = sprintf(buff,"Kernel BackChain CallChain BackChain CallChain\n"); + break; + default: + if(thread && thread->ksp && regs) { + backchain = (thread->ksp & PSW_ADDR_MASK); + endchain = ((backchain & (-8192)) + 8192); + prev_backchain = backchain - 1; + line -= sp_kern_backchain1; + for (chaincnt = 0; ; chaincnt++) { + if ((backchain == 0) || + (backchain >= endchain) || + (chaincnt >= 8) || + (prev_backchain >= backchain)) + break; + if ((chaincnt >> 1) == line) { + linelen += sprintf(&buff[linelen],"%s%08x %08x ", + (chaincnt&1) ? "":" ", + backchain,*(u32 *)(backchain+56)); + } + if ((chaincnt >> 1) > line) + break; + prev_backchain = backchain; + backchain = (*((u32 *)backchain)) & PSW_ADDR_MASK; + } + if (linelen) + linelen += sprintf(&buff[linelen],"\n"); + } + } + return linelen; +} + + +void show_regs(struct task_struct *task, struct thread_struct *thread, + struct pt_regs *regs) +{ + char buff[80]; + int line; + + for (line = 0; sprintf_regs(line,buff,task,thread,regs); line++) + printk(buff); +} + +int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) +{ + int clone_arg = flags | CLONE_VM; + int retval; + + __asm__ __volatile__( + " sr 2,2\n" + " lr 3,%1\n" + " l 4,%6\n" /* load kernel stack ptr of parent */ + " svc %b2\n" /* Linux system call*/ + " cl 4,%6\n" /* compare ksp's: child or parent ? */ + " je 0f\n" /* parent - jump*/ + " l 15,%6\n" /* fix kernel stack pointer*/ + " ahi 15,%7\n" + " xc 0(96,15),0(15)\n" /* clear save area */ + " lr 2,%4\n" /* load argument*/ + " lr 14,%5\n" /* get fn-pointer*/ + " basr 14,14\n" /* call fn*/ + " svc %b3\n" /* Linux system call*/ + "0: lr %0,2" + : "=a" (retval) + : "d" (clone_arg), "i" (__NR_clone), "i" (__NR_exit), + "d" (arg), "d" (fn), "i" (__LC_KERNEL_STACK) , "i" (-STACK_FRAME_OVERHEAD) + : "2", "3", "4" ); + return retval; +} + +/* + * Free current thread data structures etc.. + */ +void exit_thread(void) +{ +} + +void flush_thread(void) +{ + + current->used_math = 0; + current->flags &= ~PF_USEDFPU; +} + +void release_thread(struct task_struct *dead_task) +{ +} + +int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp, + struct task_struct * p, struct pt_regs * regs) +{ + struct stack_frame + { + unsigned long back_chain; + unsigned long eos; + unsigned long glue1; + unsigned long glue2; + unsigned long scratch[2]; + unsigned long gprs[10]; /* gprs 6 -15 */ + unsigned long fprs[4]; /* fpr 4 and 6 */ + unsigned long empty[4]; +#if CONFIG_REMOTE_DEBUG + gdb_pt_regs childregs; +#else + pt_regs childregs; +#endif + __u32 pgm_old_ilc; /* single step magic from entry.S */ + __u32 pgm_svc_step; + } *frame; + + frame = (struct stack_frame *) (2*PAGE_SIZE + (unsigned long) p) -1; + frame = (struct stack_frame *) (((unsigned long) frame)&-8L); + p->thread.regs = &frame->childregs; + p->thread.ksp = (unsigned long) frame; + frame->childregs = *regs; + frame->childregs.gprs[15] = new_stackp; + frame->eos = 0; + + /* new return point is ret_from_sys_call */ + frame->gprs[8] = ((unsigned long) &ret_from_fork) | 0x80000000; + + /* fake return stack for resume(), don't go back to schedule */ + frame->gprs[9] = (unsigned long) frame; + frame->pgm_svc_step = 0; /* Nope we aren't single stepping an svc */ + /* save fprs, if used in last task */ + save_fp_regs(&p->thread.fp_regs); + p->thread.user_seg = __pa((unsigned long) p->mm->pgd) | _SEGMENT_TABLE; + p->thread.fs = USER_DS; + /* Don't copy debug registers */ + memset(&p->thread.per_info,0,sizeof(p->thread.per_info)); + return 0; +} + +asmlinkage int sys_fork(struct pt_regs regs) +{ + int ret; + + lock_kernel(); + ret = do_fork(SIGCHLD, regs.gprs[15], ®s); + unlock_kernel(); + return ret; +} + +asmlinkage int sys_clone(struct pt_regs regs) +{ + unsigned long clone_flags; + unsigned long newsp; + int ret; + + lock_kernel(); + clone_flags = regs.gprs[3]; + newsp = regs.gprs[2]; + if (!newsp) + newsp = regs.gprs[15]; + ret = do_fork(clone_flags, newsp, ®s); + unlock_kernel(); + return ret; +} + +/* + * This is trivial, and on the face of it looks like it + * could equally well be done in user mode. + * + * Not so, for quite unobvious reasons - register pressure. + * In user mode vfork() cannot have a stack frame, and if + * done by calling the "clone()" system call directly, you + * do not have enough call-clobbered registers to hold all + * the information you need. + */ +asmlinkage int sys_vfork(struct pt_regs regs) +{ + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, + regs.gprs[15], ®s); +} + +/* + * sys_execve() executes a new program. + */ +asmlinkage int sys_execve(struct pt_regs regs) +{ + int error; + char * filename; + + filename = getname((char *) regs.orig_gpr2); + error = PTR_ERR(filename); + if (IS_ERR(filename)) + goto out; + error = do_execve(filename, (char **) regs.gprs[3], (char **) regs.gprs[4], ®s); + if (error == 0) + current->flags &= ~PF_DTRACE; + putname(filename); +out: + return error; +} + + +/* + * fill in the FPU structure for a core dump. + */ +int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs) +{ + save_fp_regs(fpregs); + return 1; +} + +/* + * fill in the user structure for a core dump.. + */ +void dump_thread(struct pt_regs * regs, struct user * dump) +{ + +/* changed the size calculations - should hopefully work better. lbt */ + dump->magic = CMAGIC; + dump->start_code = 0; + dump->start_stack = regs->gprs[15] & ~(PAGE_SIZE - 1); + dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT; + dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT; + dump->u_dsize -= dump->u_tsize; + dump->u_ssize = 0; + if (dump->start_stack < TASK_SIZE) + dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT; + memcpy(&dump->regs.gprs[0],regs,sizeof(s390_regs)); + dump_fpu (regs, &dump->regs.fp_regs); + memcpy(&dump->regs.per_info,¤t->thread.per_info,sizeof(per_struct)); +} + +/* + * These bracket the sleeping functions.. + */ +extern void scheduling_functions_start_here(void); +extern void scheduling_functions_end_here(void); +#define first_sched ((unsigned long) scheduling_functions_start_here) +#define last_sched ((unsigned long) scheduling_functions_end_here) + +unsigned long get_wchan(struct task_struct *p) +{ + unsigned long r14, r15; + unsigned long stack_page; + int count = 0; + if (!p || p == current || p->state == TASK_RUNNING) + return 0; + stack_page = (unsigned long) p; + r15 = p->thread.ksp; + do { + r14 = *(unsigned long *) (r15+56); + if (r14 < first_sched || r14 >= last_sched) + return r14; + r15 = *(unsigned long *) (r15+60); + } while (count++ < 16); + return 0; +} +#undef last_sched +#undef first_sched + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/ptrace.c linux/arch/s390/kernel/ptrace.c --- v2.3.99-pre7/linux/arch/s390/kernel/ptrace.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/ptrace.c Fri May 12 11:41:45 2000 @@ -0,0 +1,395 @@ +/* + * arch/s390/kernel/ptrace.c + * + * S390 version + * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), + * + * Based on PowerPC version + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Derived from "arch/m68k/kernel/ptrace.c" + * Copyright (C) 1994 by Hamish Macdonald + * Taken from linux/kernel/ptrace.c and modified for M680x0. + * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds + * + * Modified by Cort Dougan (cort@cs.nmt.edu) + * + * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file README.legal in the main directory of + * this archive for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +void FixPerRegisters(struct task_struct *task) +{ + struct pt_regs *regs = task->thread.regs; + per_struct *per_info= + (per_struct *)&task->thread.per_info; + + per_info->control_regs.bits.em_instruction_fetch= + per_info->single_step|per_info->instruction_fetch; + + if(per_info->single_step) + { + per_info->control_regs.bits.starting_addr=0; + per_info->control_regs.bits.ending_addr=0x7fffffffUL; + } + else + { + per_info->control_regs.bits.starting_addr= + per_info->starting_addr; + per_info->control_regs.bits.ending_addr= + per_info->ending_addr; + } + /* if any of the control reg tracing bits are on + we switch on per in the psw */ + if(per_info->control_regs.words.cr[0]&PER_EM_MASK) + regs->psw.mask |=PSW_PER_MASK; + else + regs->psw.mask &= ~PSW_PER_MASK; + if(per_info->control_regs.bits.storage_alt_space_ctl) + task->thread.user_seg|=USER_STD_MASK; + else + task->thread.user_seg&=~USER_STD_MASK; +} + +void set_single_step(struct task_struct *task) +{ + per_struct *per_info= + (per_struct *)&task->thread.per_info; + + per_info->single_step=1; /* Single step */ + FixPerRegisters(task); +} + +void clear_single_step(struct task_struct *task) +{ + per_struct *per_info= + (per_struct *)&task->thread.per_info; + + per_info->single_step=0; + FixPerRegisters(task); +} + +int ptrace_usercopy(addr_t realuseraddr,addr_t copyaddr,int len,int tofromuser,int writeuser,u32 mask) +{ + u32 tempuser; + int retval=0; + + if(writeuser&&realuseraddr==(addr_t)NULL) + return(0); + if(mask!=0xffffffff) + { + tempuser=*((u32 *)realuseraddr); + if(!writeuser) + { + tempuser&=mask; + realuseraddr=(addr_t)&tempuser; + } + } + if(tofromuser) + { + if(writeuser) + { + retval=copy_from_user((void *)realuseraddr,(void *)copyaddr,len); + } + else + { + if(realuseraddr==(addr_t)NULL) + retval=(clear_user((void *)copyaddr,len)==-EFAULT ? -EIO:0); + else + retval=(copy_to_user((void *)copyaddr,(void *)realuseraddr,len)==-EFAULT ? -EIO:0); + } + } + else + { + if(writeuser) + memcpy((void *)realuseraddr,(void *)copyaddr,len); + else + memcpy((void *)copyaddr,(void *)realuseraddr,len); + } + if(mask!=0xffffffff&&writeuser) + (*((u32 *)realuseraddr))=(((*((u32 *)realuseraddr))&mask)|(tempuser&~mask)); + return(retval); +} + +int copy_user(struct task_struct *task,saddr_t useraddr,addr_t copyaddr,int len,int tofromuser,int writingtouser) +{ + int copylen=0,copymax; + addr_t realuseraddr; + saddr_t enduseraddr=useraddr+len; + + u32 mask; + + if (useraddr < 0 || enduseraddr > sizeof(struct user)|| + (useraddr < PT_ENDREGS && (useraddr&3))|| + (enduseraddr < PT_ENDREGS && (enduseraddr&3))) + return (-EIO); + while(len>0) + { + mask=0xffffffff; + if(useraddrthread.regs)[useraddr]); + if(useraddrthread.fp_regs)[useraddr-PT_FPC]); + } + else if(useraddrthread.per_info)[useraddr-PT_CR_9]); + } + else + { + copymax=sizeof(struct user); + realuseraddr=(addr_t)NULL; + } + copylen=copymax-useraddr; + copylen=(copylen>len ? len:copylen); + if(ptrace_usercopy(realuseraddr,copyaddr,copylen,tofromuser,writingtouser,mask)) + return (-EIO); + copyaddr+=copylen; + len-=copylen; + useraddr+=copylen; + } + FixPerRegisters(task); + return(0); +} + +asmlinkage int sys_ptrace(long request, long pid, long addr, long data) +{ + struct task_struct *child; + int ret = -EPERM; + unsigned long flags; + unsigned long tmp; + int copied; + ptrace_area parea; + + lock_kernel(); + if (request == PTRACE_TRACEME) + { + /* are we already being traced? */ + if (current->flags & PF_PTRACED) + goto out; + /* set the ptrace bit in the process flags. */ + current->flags |= PF_PTRACED; + ret = 0; + goto out; + } + ret = -ESRCH; + read_lock(&tasklist_lock); + child = find_task_by_pid(pid); + read_unlock(&tasklist_lock); + if (!child) + goto out; + ret = -EPERM; + if (pid == 1) /* you may not mess with init */ + goto out; + if (request == PTRACE_ATTACH) + { + if (child == current) + goto out; + if ((!child->dumpable || + (current->uid != child->euid) || + (current->uid != child->suid) || + (current->uid != child->uid) || + (current->gid != child->egid) || + (current->gid != child->sgid)) && !capable(CAP_SYS_PTRACE)) + goto out; + /* the same process cannot be attached many times */ + if (child->flags & PF_PTRACED) + goto out; + child->flags |= PF_PTRACED; + + write_lock_irqsave(&tasklist_lock, flags); + if (child->p_pptr != current) + { + REMOVE_LINKS(child); + child->p_pptr = current; + SET_LINKS(child); + } + write_unlock_irqrestore(&tasklist_lock, flags); + + send_sig(SIGSTOP, child, 1); + ret = 0; + goto out; + } + ret = -ESRCH; + // printk("child=%lX child->flags=%lX",child,child->flags); + if (!(child->flags & PF_PTRACED)) + goto out; + if (child->state != TASK_STOPPED) + { + if (request != PTRACE_KILL) + goto out; + } + if (child->p_pptr != current) + goto out; + + switch (request) + { + /* If I and D space are separate, these will need to be fixed. */ + case PTRACE_PEEKTEXT: /* read word at location addr. */ + case PTRACE_PEEKDATA: + copied = access_process_vm(child,ADDR_BITS_REMOVE(addr), &tmp, sizeof(tmp), 0); + ret = -EIO; + if (copied != sizeof(tmp)) + goto out; + ret = put_user(tmp,(unsigned long *) data); + goto out; + + /* read the word at location addr in the USER area. */ + case PTRACE_PEEKUSR: + ret=copy_user(child,addr,data,sizeof(unsigned long),1,0); + break; + + /* If I and D space are separate, this will have to be fixed. */ + case PTRACE_POKETEXT: /* write the word at location addr. */ + case PTRACE_POKEDATA: + ret = 0; + if (access_process_vm(child,ADDR_BITS_REMOVE(addr), &data, sizeof(data), 1) == sizeof(data)) + goto out; + ret = -EIO; + goto out; + break; + + case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ + ret=copy_user(child,addr,(addr_t)&data,sizeof(unsigned long),0,1); + break; + + case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ + case PTRACE_CONT: /* restart after signal. */ + ret = -EIO; + if ((unsigned long) data >= _NSIG) + break; + if (request == PTRACE_SYSCALL) + child->flags |= PF_TRACESYS; + else + child->flags &= ~PF_TRACESYS; + child->exit_code = data; + /* make sure the single step bit is not set. */ + clear_single_step(child); + wake_up_process(child); + ret = 0; + break; + +/* + * make the child exit. Best I can do is send it a sigkill. + * perhaps it should be put in the status that it wants to + * exit. + */ + case PTRACE_KILL: + ret = 0; + if (child->state == TASK_ZOMBIE) /* already dead */ + break; + child->exit_code = SIGKILL; + clear_single_step(child); + wake_up_process(child); + /* make sure the single step bit is not set. */ + break; + + case PTRACE_SINGLESTEP: /* set the trap flag. */ + ret = -EIO; + if ((unsigned long) data >= _NSIG) + break; + child->flags &= ~PF_TRACESYS; + child->exit_code = data; + set_single_step(child); + /* give it a chance to run. */ + wake_up_process(child); + ret = 0; + break; + + case PTRACE_DETACH: /* detach a process that was attached. */ + ret = -EIO; + if ((unsigned long) data >= _NSIG) + break; + child->flags &= ~(PF_PTRACED|PF_TRACESYS); + child->exit_code = data; + write_lock_irqsave(&tasklist_lock, flags); + REMOVE_LINKS(child); + child->p_pptr = child->p_opptr; + SET_LINKS(child); + write_unlock_irqrestore(&tasklist_lock, flags); + /* make sure the single step bit is not set. */ + clear_single_step(child); + wake_up_process(child); + ret = 0; + break; + case PTRACE_PEEKUSR_AREA: + case PTRACE_POKEUSR_AREA: + if((ret=copy_from_user(&parea,(void *)addr,sizeof(parea)))==0) + ret=copy_user(child,parea.kernel_addr,parea.process_addr, + parea.len,1,(request==PTRACE_POKEUSR_AREA)); + break; + default: + ret = -EIO; + break; + } + out: + unlock_kernel(); + return ret; +} + +asmlinkage void syscall_trace(void) +{ + lock_kernel(); + if ((current->flags & (PF_PTRACED|PF_TRACESYS)) + != (PF_PTRACED|PF_TRACESYS)) + goto out; + current->exit_code = SIGTRAP; + current->state = TASK_STOPPED; + notify_parent(current, SIGCHLD); + schedule(); + /* + * this isn't the same as continuing with a signal, but it will do + * for normal use. strace only continues with a signal if the + * stopping signal is not SIGTRAP. -brl + */ + if (current->exit_code) { + send_sig(current->exit_code, current, 1); + current->exit_code = 0; + } + out: + unlock_kernel(); +} diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/reipl.S linux/arch/s390/kernel/reipl.S --- v2.3.99-pre7/linux/arch/s390/kernel/reipl.S Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/reipl.S Fri May 12 11:41:45 2000 @@ -0,0 +1,67 @@ +#include + .globl do_reipl +do_reipl: basr %r13,0 +.Lpg0: lpsw .Lnewpsw-.Lpg0(%r13) +.Lpg1: lctl %c6,%c6,.Lall-.Lpg0(%r13) + stctl %c0,%c0,.Lctlsave-.Lpg0(%r13) + ni .Lctlsave-.Lpg0(%r13),0xef + lctl %c0,%c0,.Lctlsave-.Lpg0(%r13) + lr %r1,%r2 + mvc __LC_PGM_NEW_PSW(8,0),.Lpcnew-.Lpg0(%r13) + stsch .Lschib-.Lpg0(%r13) + oi .Lschib+5-.Lpg0(%r13),0x84 +.Lecs: xi .Lschib+27-.Lpg0(%r13),0x01 + msch .Lschib-.Lpg0(%r13) + ssch .Liplorb-.Lpg0(%r13) + jz .L001 + bas %r14,.Ldisab-.Lpg0(%r13) +.L001: mvc __LC_IO_NEW_PSW(8,0),.Lionew-.Lpg0(%r13) +.Ltpi: lpsw .Lwaitpsw-.Lpg0(%r13) +.Lcont: c %r1,__LC_SUBCHANNEL_ID(%r0) + jnz .Ltpi + clc __LC_IO_INT_PARM(4),.Liplorb-.Lpg0(%r13) + jnz .Ltpi + tsch .Liplirb-.Lpg0(%r13) + tm .Liplirb+9-.Lpg0(%r13),0xbf + jz .L002 + bas %r14,.Ldisab-.Lpg0(%r13) +.L002: tm .Liplirb+8-.Lpg0(%r13),0xf3 + jz .L003 + bas %r14,.Ldisab-.Lpg0(%r13) +.L003: spx .Lnull-.Lpg0(%r13) + st %r1,__LC_SUBCHANNEL_ID(%r0) + lpsw 0 + sigp 0,0,0(6) +.Ldisab: st %r14,.Ldispsw+4-.Lpg0(%r13) + lpsw .Ldispsw-.Lpg0(%r13) + .align 8 +.Lall: .long 0xff000000 +.Lnull: .long 0x00000000 +.Lctlsave: .long 0x00000000 + .align 8 +.Lnewpsw: .long 0x00080000,0x80000000+.Lpg1 +.Lpcnew: .long 0x00080000,0x80000000+.Lecs +.Lionew: .long 0x00080000,0x80000000+.Lcont +.Lwaitpsw: .long 0x020a0000,0x00000000+.Ltpi +.Ldispsw: .long 0x000a0000,0x00000000 +.Liplccws: .long 0x02000000,0x60000018 + .long 0x08000008,0x20000001 +.Liplorb: .long 0x0049504c,0x0000ff80 + .long 0x00000000+.Liplccws +.Lschib: .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 +.Liplirb: .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + .long 0x00000000,0x00000000 + + + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/s390_ksyms.c linux/arch/s390/kernel/s390_ksyms.c --- v2.3.99-pre7/linux/arch/s390/kernel/s390_ksyms.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/s390_ksyms.c Fri May 12 11:41:45 2000 @@ -0,0 +1,64 @@ +/* + * arch/s390/kernel/s390_ksyms.c + * + * S390 version + */ +#include +#include +#include +#include +#include + +/* + * I/O subsystem + */ +EXPORT_SYMBOL(halt_IO); +EXPORT_SYMBOL(do_IO); +EXPORT_SYMBOL(resume_IO); +EXPORT_SYMBOL(ioinfo); +EXPORT_SYMBOL(get_dev_info_by_irq); +EXPORT_SYMBOL(get_dev_info_by_devno); +EXPORT_SYMBOL(get_irq_by_devno); +EXPORT_SYMBOL(get_devno_by_irq); +EXPORT_SYMBOL(get_irq_first); +EXPORT_SYMBOL(get_irq_next); + +/* + * memory management + */ +EXPORT_SYMBOL(_oi_bitmap); +EXPORT_SYMBOL(_ni_bitmap); +EXPORT_SYMBOL(_zb_findmap); + +/* + * string functions + */ +EXPORT_SYMBOL_NOVERS(memcmp); +EXPORT_SYMBOL_NOVERS(memset); +EXPORT_SYMBOL_NOVERS(memmove); +EXPORT_SYMBOL_NOVERS(strchr); +EXPORT_SYMBOL_NOVERS(strcmp); +EXPORT_SYMBOL_NOVERS(strncat); +EXPORT_SYMBOL_NOVERS(strncmp); +EXPORT_SYMBOL_NOVERS(strncpy); +EXPORT_SYMBOL_NOVERS(strnlen); +EXPORT_SYMBOL_NOVERS(strrchr); +EXPORT_SYMBOL_NOVERS(strtok); +EXPORT_SYMBOL_NOVERS(strpbrk); + +/* + * misc. + */ +#ifdef CONFIG_SMP +#include +EXPORT_SYMBOL(__global_cli); +EXPORT_SYMBOL(__global_sti); +EXPORT_SYMBOL(__global_save_flags); +EXPORT_SYMBOL(__global_restore_flags); +EXPORT_SYMBOL(global_bh_lock); +EXPORT_SYMBOL(kernel_flag); +#endif +EXPORT_SYMBOL(kernel_thread); +EXPORT_SYMBOL(csum_fold); + + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/s390dyn.c linux/arch/s390/kernel/s390dyn.c --- v2.3.99-pre7/linux/arch/s390/kernel/s390dyn.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/s390dyn.c Fri May 12 11:41:45 2000 @@ -0,0 +1,36 @@ +/* + * arch/s390/kernel/s390dyn.c + * S/390 dynamic device attachment + * + * S390 version + * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Ingo Adlung (adlung@de.ibm.com) + */ + +#include + +#include +#include +#include + +int s390_device_register( devreg_t *drinfo ) +{ + return -EOPNOTSUPP; +} + + +int s390_device_deregister ( devreg_t *dreg ) +{ + return -EOPNOTSUPP; +} + +int s390_request_irq_special( int irq, + io_handler_func_t io_handler, + not_oper_handler_func_t not_oper_handler, + unsigned long irqflags, + const char *devname, + void *dev_id) +{ + return -EOPNOTSUPP; +} + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/s390fpu.c linux/arch/s390/kernel/s390fpu.c --- v2.3.99-pre7/linux/arch/s390/kernel/s390fpu.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/s390fpu.c Fri May 12 11:41:45 2000 @@ -0,0 +1,147 @@ +/* + * arch/s390/kernel/s390fpu.c + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) + * + * s390fpu.h functions for saving & restoring the fpu state. + * + * I couldn't inline these as linux/sched.h included half the world + * & was required to at the task structure. + * & the functions were too complex to make macros from. + * ( & as usual I didn't feel like debugging inline code ). + */ + +#include +#include + +int save_fp_regs1(s390_fp_regs *fpregs) +{ + int has_ieee=MACHINE_HAS_IEEE; +/* + I don't think we can use STE here as this would load + fp registers 0 & 2 into memory locations 0 & 1 etc. + */ + asm volatile ("STD 0,8(%0)\n\t" + "STD 2,24(%0)\n\t" + "STD 4,40(%0)\n\t" + "STD 6,56(%0)" + : + : "a" (fpregs) + : "memory" + ); + if(has_ieee) + { + asm volatile ("STFPC 0(%0)\n\t" + "STD 1,16(%0)\n\t" + "STD 3,32(%0)\n\t" + "STD 5,48(%0)\n\t" + "STD 7,64(%0)\n\t" + "STD 8,72(%0)\n\t" + "STD 9,80(%0)\n\t" + "STD 10,88(%0)\n\t" + "STD 11,96(%0)\n\t" + "STD 12,104(%0)\n\t" + "STD 13,112(%0)\n\t" + "STD 14,120(%0)\n\t" + "STD 15,128(%0)\n\t" + : + : "a" (fpregs) + : "memory" + ); + } + return(has_ieee); +} + + +void save_fp_regs(s390_fp_regs *fpregs) +{ +#if CONFIG_IEEEFPU_EMULATION + s390_fp_regs *currentfprs; +#endif +#if CONFIG_IEEEFPU_EMULATION + if(!save_fp_regs1(fpregs)) + { + currentfprs=¤t->thread.fp_regs; + fpregs->fpc=currentfprs->fpc; + fpregs->fprs[1].d=currentfprs->fprs[1].d; + fpregs->fprs[3].d=currentfprs->fprs[3].d; + fpregs->fprs[5].d=currentfprs->fprs[5].d; + fpregs->fprs[7].d=currentfprs->fprs[7].d; + memcpy(&fpregs->fprs[8].d,¤tfprs->fprs[8].d,sizeof(freg_t)*8); + } +#else + save_fp_regs1(fpregs); +#endif +} + + +int restore_fp_regs1(s390_fp_regs *fpregs) +{ + int has_ieee=MACHINE_HAS_IEEE; + + asm volatile ("LD 0,8(%0)\n\t" + "LD 2,24(%0)\n\t" + "LD 4,40(%0)\n\t" + "LD 6,56(%0)" + : + : "a" (fpregs) + : "memory" + ); + if(has_ieee) + { + asm volatile ("LFPC 0(%0)\n\t" + "LD 1,16(%0)\n\t" + "LD 3,32(%0)\n\t" + "LD 5,48(%0)\n\t" + "LD 7,64(%0)\n\t" + "LD 8,72(%0)\n\t" + "LD 9,80(%0)\n\t" + "LD 10,88(%0)\n\t" + "LD 11,96(%0)\n\t" + "LD 12,104(%0)\n\t" + "LD 13,112(%0)\n\t" + "LD 14,120(%0)\n\t" + "LD 15,128(%0)\n\t" + : + : "a" (fpregs) + : "memory" + ); + } + return(has_ieee); +} + +void restore_fp_regs(s390_fp_regs *fpregs) +{ +#if CONFIG_IEEEFPU_EMULATION + s390_fp_regs *currentfprs; +#endif + +#if CONFIG_IEEEFPU_EMULATION + if(!restore_fp_regs1(fpregs)) + { + currentfprs=¤t->thread.fp_regs; + currentfprs->fpc=fpregs->fpc; + currentfprs->fprs[1].d=fpregs->fprs[1].d; + currentfprs->fprs[3].d=fpregs->fprs[3].d; + currentfprs->fprs[5].d=fpregs->fprs[5].d; + currentfprs->fprs[7].d=fpregs->fprs[7].d; + memcpy(¤tfprs->fprs[8].d,&fpregs->fprs[8].d,sizeof(freg_t)*8); + } +#else + restore_fp_regs1(fpregs); +#endif +} + + + + + + + + + + + + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/s390io.c linux/arch/s390/kernel/s390io.c --- v2.3.99-pre7/linux/arch/s390/kernel/s390io.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/s390io.c Fri May 12 11:41:45 2000 @@ -0,0 +1,4602 @@ +/* + * arch/s390/kernel/s390io.c + * S/390 common I/O routines + * + * S390 version + * Copyright (C) 1999, 2000 IBM Deutschland Entwicklung GmbH, + * IBM Corporation + * Author(s): Ingo Adlung (adlung@de.ibm.com) + */ + +#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 TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +#undef CONFIG_DEBUG_IO + +#define REIPL_DEVID_MAGIC 0x87654321 + +struct irqaction init_IRQ_action; +unsigned int highest_subchannel; +ioinfo_t *ioinfo_head = NULL; +ioinfo_t *ioinfo_tail = NULL; +ioinfo_t *ioinfo[__MAX_SUBCHANNELS] = { + [0 ... (__MAX_SUBCHANNELS-1)] = INVALID_STORAGE_AREA +}; + +static spinlock_t sync_isc; // synchronous irq processing lock +static psw_t io_sync_wait; // wait PSW for sync IO, prot. by sync_isc +static psw_t io_new_psw; // save I/O new PSW, prot. by sync_isc +static int cons_dev = -1; // identify console device +static int init_IRQ_complete = 0; +static schib_t init_schib; +static __u64 irq_IPL_TOD; + +/* + * Dummy controller type for unused interrupts + */ +int do_none(unsigned int irq, int cpu, struct pt_regs * regs) { return 0;} +int enable_none(unsigned int irq) { return(-ENODEV); } +int disable_none(unsigned int irq) { return(-ENODEV); } + +struct hw_interrupt_type no_irq_type = { + "none", + do_none, + enable_none, + disable_none +}; + +static void init_IRQ_handler( int irq, void *dev_id, struct pt_regs *regs); +static int s390_setup_irq(unsigned int irq, struct irqaction * new); +static void s390_process_subchannels( void); +static void s390_device_recognition( void); +static int s390_validate_subchannel( int irq); +static int s390_SenseID( int irq, senseid_t *sid); +static int s390_SetPGID( int irq, __u8 lpm, pgid_t *pgid); +static int s390_SensePGID( int irq, __u8 lpm, pgid_t *pgid); +static int s390_process_IRQ( unsigned int irq ); +static int s390_DevicePathVerification( int irq ); + +extern int do_none(unsigned int irq, int cpu, struct pt_regs * regs); +extern int enable_none(unsigned int irq); +extern int disable_none(unsigned int irq); +extern void tod_wait(unsigned long usecs); + +asmlinkage void do_IRQ( struct pt_regs regs, + unsigned int irq, + __u32 s390_intparm ); + +void s390_displayhex(char *str,void *ptr,s32 cnt); + +void s390_displayhex(char *str,void *ptr,s32 cnt) +{ + s32 cnt1,cnt2,maxcnt2; + u32 *currptr=(__u32 *)ptr; + + printk("\n%s\n",str); + + for(cnt1=0;cnt116) + maxcnt2=16; + for(cnt2=0;cnt2= __MAX_SUBCHANNELS) + return -EINVAL; + + if ( !handler || !dev_id ) + return -EINVAL; + + /* + * during init_IRQ() processing we don't have memory + * management yet, thus need to use a statically + * allocated irqaction control block + */ + if ( init_IRQ_complete ) + { + action = (struct irqaction *) + kmalloc(sizeof(struct irqaction), GFP_KERNEL); + } + else + { + action = &init_IRQ_action; + + } /* endif */ + + if (!action) + { + return -ENOMEM; + + } /* endif */ + + action->handler = handler; + action->flags = irqflags; + action->mask = 0; + action->name = devname; + action->next = NULL; + action->dev_id = dev_id; + + retval = s390_setup_irq( irq, action); + + if ( !retval ) + { + retval = s390_DevicePathVerification( irq ); + } + else if ( retval && init_IRQ_complete ) + { + kfree(action); + + } /* endif */ + + return retval; +} + +void s390_free_irq(unsigned int irq, void *dev_id) +{ + unsigned int flags; + int ret; + + unsigned int count = 0; + + if ( irq >= __MAX_SUBCHANNELS || ioinfo[irq] == INVALID_STORAGE_AREA ) + { + return; + + } /* endif */ + + s390irq_spin_lock_irqsave( irq, flags); + +#ifdef CONFIG_KERNEL_DEBUG + if ( irq != cons_dev ) + { + printk("Trying to free IRQ%d\n",irq); + + } /* endif */ +#endif + + /* + * disable the device and reset all IRQ info if + * the IRQ is actually owned by the handler ... + */ + if ( ioinfo[irq]->irq_desc.action ) + { + if ( (dev_id == ioinfo[irq]->irq_desc.action->dev_id ) + || (dev_id == (devstat_t *)REIPL_DEVID_MAGIC) ) + { + /* start deregister */ + ioinfo[irq]->ui.flags.unready = 1; + + do + { + ret = ioinfo[irq]->irq_desc.handler->disable(irq); + + count++; + + if ( ret == -EBUSY ) + { + int iret; + + /* + * kill it ! + * ... we first try sync and eventually + * try terminating the current I/O by + * an async request, twice halt, then + * clear. + */ + if ( count < 3 ) + { + iret = halt_IO( irq, + 0xC8C1D3E3, + DOIO_WAIT_FOR_INTERRUPT ); + + if ( iret == -EBUSY ) + { + halt_IO( irq, 0xC8C1D3E3, 0); + s390irq_spin_unlock_irqrestore( irq, flags); + tod_wait( 200000 ); /* 200 ms */ + s390irq_spin_lock_irqsave( irq, flags); + + } /* endif */ + } + else + { + iret = clear_IO( irq, + 0x40C3D3D9, + DOIO_WAIT_FOR_INTERRUPT ); + + if ( iret == -EBUSY ) + { + clear_IO( irq, 0xC8C1D3E3, 0); + s390irq_spin_unlock_irqrestore( irq, flags); + tod_wait( 1000000 ); /* 1000 ms */ + s390irq_spin_lock_irqsave( irq, flags); + + } /* endif */ + + } /* endif */ + + if ( count == 3 ) + { + /* give it a very last try ... */ + ioinfo[irq]->irq_desc.handler->disable(irq); + + if ( ioinfo[irq]->ui.flags.busy ) + { + printk( KERN_CRIT"free_irq(%04X) " + "- device %04X busy, retry " + "count exceeded\n", + irq, + ioinfo[irq]->devstat.devno); + + } /* endif */ + + break; /* sigh, let's give up ... */ + + } /* endif */ + + } /* endif */ + + } while ( ret == -EBUSY ); + + if ( init_IRQ_complete ) + kfree( ioinfo[irq]->irq_desc.action ); + + ioinfo[irq]->irq_desc.action = NULL; + ioinfo[irq]->ui.flags.ready = 0; + + ioinfo[irq]->irq_desc.handler->enable = &enable_none; + ioinfo[irq]->irq_desc.handler->disable = &disable_none; + + ioinfo[irq]->ui.flags.unready = 0; /* deregister ended */ + + s390irq_spin_unlock_irqrestore( irq, flags); + } + else + { + s390irq_spin_unlock_irqrestore( irq, flags); + + printk("free_irq() : error, dev_id does not match !"); + + } /* endif */ + + } + else + { + s390irq_spin_unlock_irqrestore( irq, flags); + + printk("free_irq() : error, no action block ... !"); + + } /* endif */ + +} + +/* + * Generic enable/disable code + */ +int disable_irq(unsigned int irq) +{ + unsigned long flags; + int ret; + + if ( ioinfo[irq] == INVALID_STORAGE_AREA ) + return( -ENODEV); + + s390irq_spin_lock_irqsave(irq, flags); + + /* + * At this point we may actually have a pending interrupt being active + * on another CPU. So don't touch the IRQ_INPROGRESS bit.. + */ + ioinfo[irq]->irq_desc.status |= IRQ_DISABLED; + ret = ioinfo[irq]->irq_desc.handler->disable(irq); + s390irq_spin_unlock_irqrestore(irq, flags); + + synchronize_irq(); + + return( ret); +} + +int enable_irq(unsigned int irq) +{ + unsigned long flags; + int ret; + + if ( ioinfo[irq] == INVALID_STORAGE_AREA ) + return( -ENODEV); + + s390irq_spin_lock_irqsave(irq, flags); + + ioinfo[irq]->irq_desc.status = 0; + ret = ioinfo[irq]->irq_desc.handler->enable(irq); + + s390irq_spin_unlock_irqrestore(irq, flags); + + return(ret); +} + +/* + * Enable IRQ by modifying the subchannel + */ +static int enable_subchannel( unsigned int irq) +{ + int ret; + int ccode; + int retry = 5; + + if ( irq > highest_subchannel || irq < 0 ) + { + return( -ENODEV ); + + } /* endif */ + + if ( ioinfo[irq] == INVALID_STORAGE_AREA ) + return( -ENODEV); + + /* + * If a previous disable request is pending we reset it. However, this + * status implies that the device may (still) be not-operational. + */ + if ( ioinfo[irq]->ui.flags.d_disable ) + { + ioinfo[irq]->ui.flags.d_disable = 0; + ret = 0; + } + else + { + + ccode = stsch(irq, &(ioinfo[irq]->schib) ); + + if ( ccode ) + { + ret = -ENODEV; + } + else + { + ioinfo[irq]->schib.pmcw.ena = 1; + + do + { + ccode = msch( irq, &(ioinfo[irq]->schib) ); + + switch (ccode) { + case 0: + ret = 0; + break; + + case 1: + /* + * very bad, requires interrupt alike + * processing, where "rbh" is a dummy + * parameter for interface compatibility + * only. Bottom-half handling cannot be + * required as this must be an + * unsolicited interrupt (!busy). + */ + + ioinfo[irq]->ui.flags.s_pend = 1; + + s390_process_IRQ( irq ); + + ioinfo[irq]->ui.flags.s_pend = 0; + + ret = -EIO; /* might be overwritten */ + /* ... on re-driving */ + /* ... the msch() */ + retry--; + break; + + case 3: + ioinfo[irq]->ui.flags.oper = 0; + ret = -ENODEV; + break; + + default: + printk( KERN_CRIT"enable_subchannel(%04X) " + " : ccode 2 on msch() for device " + "%04X received !\n", + irq, + ioinfo[irq]->devstat.devno); + ret = -ENODEV; // never reached + } + + } while ( (ccode == 1) && retry ); + + } /* endif */ + + } /* endif */ + + return( ret ); +} + + +/* + * Disable IRQ by modifying the subchannel + */ +static int disable_subchannel( unsigned int irq) +{ + int cc; /* condition code */ + int ret; /* function return value */ + int retry = 5; + + if ( irq > highest_subchannel ) + { + ret = -ENODEV; + } + if ( ioinfo[irq] == INVALID_STORAGE_AREA ) + { + return( -ENODEV); + } + else if ( ioinfo[irq]->ui.flags.busy ) + { + /* + * the disable function must not be called while there are + * requests pending for completion ! + */ + ret = -EBUSY; + } + else + { + /* + * If device isn't operational we have to perform delayed + * disabling when the next interrupt occurs - unless the + * irq is re-requested prior to the interrupt to occur. + */ + cc = stsch(irq, &(ioinfo[irq]->schib) ); + + if ( cc == 3 ) + { + ioinfo[irq]->ui.flags.oper = 0; + ioinfo[irq]->ui.flags.d_disable = 1; + + ret = 0; + } + else // cc == 0 + { + ioinfo[irq]->schib.pmcw.ena = 0; + + do + { + cc = msch( irq, &(ioinfo[irq]->schib) ); + + switch (cc) { + case 0 : + ret = 0; /* done */ + break; + + case 1 : + /* + * very bad, requires interrupt alike + * processing, where "rbh" is a dummy + * parm for interface compatibility + * only. Bottom-half handling cannot + * be required as this must be an + * unsolicited interrupt (!busy). + */ + ioinfo[irq]->ui.flags.s_pend = 1; + s390_process_IRQ( irq ); + ioinfo[irq]->ui.flags.s_pend = 0; + + ret = -EBUSY; /* might be overwritten */ + /* ... on re-driving the */ + /* ... msch() call */ + retry--; + break; + + case 2 : + /* + * *** must not occur ! *** + * *** *** + * *** indicates our internal *** + * *** interrupt accounting is out *** + * *** of sync ===> panic() *** + */ + printk( KERN_CRIT"disable_subchannel(%04X) " + "- unexpected busy condition for " + "device %04X received !\n", + irq, + ioinfo[irq]->devstat.devno); + + ret = -ENODEV; // never reached + break; + + case 3 : + /* + * should hardly occur ?! + */ + ioinfo[irq]->ui.flags.oper = 0; + ioinfo[irq]->ui.flags.d_disable = 1; + + ret = 0; /* if the device has gone we */ + /* ... don't need to disable */ + /* ... it anymore ! */ + break; + + default : + ret = -ENODEV; // never reached ... + break; + + } /* endswitch */ + + } while ( (cc == 1) && retry ); + + } /* endif */ + + } /* endif */ + + return( ret); +} + + + +int s390_setup_irq( unsigned int irq, struct irqaction * new) +{ + unsigned long flags; + int rc = 0; + + if ( ioinfo[irq] == INVALID_STORAGE_AREA ) + { + return( -ENODEV); + } + + /* + * The following block of code has to be executed atomically + */ + s390irq_spin_lock_irqsave( irq, flags); + + if ( ioinfo[irq]->irq_desc.action == NULL ) + { + ioinfo[irq]->irq_desc.action = new; + ioinfo[irq]->irq_desc.status = 0; + ioinfo[irq]->irq_desc.handler->enable = &enable_subchannel; + ioinfo[irq]->irq_desc.handler->disable = &disable_subchannel; + ioinfo[irq]->irq_desc.handler->handle = &handle_IRQ_event; + + ioinfo[irq]->ui.flags.ready = 1; + + ioinfo[irq]->irq_desc.handler->enable(irq); + } + else + { + /* + * interrupt already owned, and shared interrupts + * aren't supported on S/390. + */ + rc = -EBUSY; + + } /* endif */ + + s390irq_spin_unlock_irqrestore(irq,flags); + + return( rc); +} + +void s390_init_IRQ( void ) +{ + unsigned long flags; /* PSW flags */ + long cr6 __attribute__ ((aligned (8))); + + // Hopefully bh_count's will get set when we copy the prefix lowcore + // structure to other CPI's ( DJB ) + atomic_set(&S390_lowcore.local_bh_count,0); + atomic_set(&S390_lowcore.local_irq_count,0); + + asm volatile ("STCK %0" : "=m" (irq_IPL_TOD)); + + /* + * As we don't know about the calling environment + * we assure running disabled. Before leaving the + * function we resestablish the old environment. + * + * Note : as we don't need a system wide lock, therefore + * we shouldn't use cli(), but __cli() as this + * affects the current CPU only. + */ + __save_flags(flags); + __cli(); + + /* + * disable all interrupts + */ + cr6 = 0; + asm volatile ("LCTL 6,6,%0":: "m" (cr6):"memory"); + + s390_process_subchannels(); + + /* + * enable default I/O-interrupt sublass 3 + */ + cr6 = 0x10000000; + asm volatile ("LCTL 6,6,%0":: "m" (cr6):"memory"); + + s390_device_recognition(); + + init_IRQ_complete = 1; + + s390_init_machine_check(); + + __restore_flags(flags); + + return; +} + + +/* + * dummy handler, used during init_IRQ() processing for compatibility only + */ +void init_IRQ_handler( int irq, void *dev_id, struct pt_regs *regs) +{ + /* this is a dummy handler only ... */ +} + + +int s390_start_IO( int irq, /* IRQ */ + ccw1_t *cpa, /* logical channel prog addr */ + unsigned long user_intparm, /* interruption parameter */ + __u8 lpm, /* logical path mask */ + unsigned long flag) /* flags */ +{ + int ccode; + unsigned long psw_flags; + + int sync_isc_locked = 0; + int ret = 0; + + /* + * The flag usage is mutal exclusive ... + */ + if ( (flag & DOIO_RETURN_CHAN_END) + && (flag & DOIO_REPORT_ALL ) ) + { + return( -EINVAL ); + + } /* endif */ + + memset( &(ioinfo[irq]->orb), '\0', sizeof( orb_t) ); + + /* + * setup ORB + */ + ioinfo[irq]->orb.intparm = (__u32)&ioinfo[irq]->u_intparm; + ioinfo[irq]->orb.fmt = 1; + + ioinfo[irq]->orb.pfch = !(flag & DOIO_DENY_PREFETCH); + ioinfo[irq]->orb.spnd = (flag & DOIO_ALLOW_SUSPEND); + ioinfo[irq]->orb.ssic = ( (flag & DOIO_ALLOW_SUSPEND ) + && (flag & DOIO_SUPPRESS_INTER) ); + + if ( flag & DOIO_VALID_LPM ) + { + ioinfo[irq]->orb.lpm = lpm; + } + else + { + ioinfo[irq]->orb.lpm = ioinfo[irq]->opm; + + } /* endif */ + + ioinfo[irq]->orb.cpa = (__u32)virt_to_phys( cpa); + + /* + * If sync processing was requested we lock the sync ISC, modify the + * device to present interrupts for this ISC only and switch the + * CPU to handle this ISC + the console ISC exclusively. + */ + if ( flag & DOIO_WAIT_FOR_INTERRUPT ) + { + // + // check whether we run recursively (sense processing) + // + if ( !ioinfo[irq]->ui.flags.syncio ) + { + spin_lock_irqsave( &sync_isc, psw_flags); + + ret = enable_cpu_sync_isc( irq); + + if ( ret ) + { + spin_unlock_irqrestore( &sync_isc, psw_flags); + return( ret); + } + else + { + sync_isc_locked = 1; // local + ioinfo[irq]->ui.flags.syncio = 1; // global + + } /* endif */ + + } /* endif */ + + } /* endif */ + + /* + * Issue "Start subchannel" and process condition code + */ + ccode = ssch( irq, &(ioinfo[irq]->orb) ); + + switch ( ccode ) { + case 0: + + if ( !ioinfo[irq]->ui.flags.w4sense ) + { + /* + * init the device driver specific devstat irb area + * + * Note : don´t clear saved irb info in case of sense ! + */ + memset( &((devstat_t *)ioinfo[irq]->irq_desc.action->dev_id)->ii.irb, + '\0', sizeof( irb_t) ); + } /* endif */ + + /* + * initialize device status information + */ + ioinfo[irq]->ui.flags.busy = 1; + ioinfo[irq]->ui.flags.doio = 1; + + ioinfo[irq]->u_intparm = user_intparm; + ioinfo[irq]->devstat.cstat = 0; + ioinfo[irq]->devstat.dstat = 0; + ioinfo[irq]->devstat.lpum = 0; + ioinfo[irq]->devstat.flag = DEVSTAT_START_FUNCTION; + ioinfo[irq]->devstat.scnt = 0; + + ioinfo[irq]->ui.flags.fast = 0; + ioinfo[irq]->ui.flags.repall = 0; + + /* + * Check for either early (FAST) notification requests + * or if we are to return all interrupt info. + * Default is to call IRQ handler at secondary status only + */ + if ( flag & DOIO_RETURN_CHAN_END ) + { + ioinfo[irq]->ui.flags.fast = 1; + } + else if ( flag & DOIO_REPORT_ALL ) + { + ioinfo[irq]->ui.flags.repall = 1; + + } /* endif */ + + ioinfo[irq]->ulpm = ioinfo[irq]->orb.lpm; + + /* + * If synchronous I/O processing is requested, we have + * to wait for the corresponding interrupt to occur by + * polling the interrupt condition. However, as multiple + * interrupts may be outstanding, we must not just wait + * for the first interrupt, but must poll until ours + * pops up. + */ + if ( flag & DOIO_WAIT_FOR_INTERRUPT ) + { + // __u32 io_parm; + psw_t io_new_psw; + int ccode; + + int ready = 0; + int io_sub = -1; + struct _lowcore *lc = NULL; + int count = 30000; + + /* + * We shouldn't perform a TPI loop, waiting for an + * interrupt to occur, but should load a WAIT PSW + * instead. Otherwise we may keep the channel subsystem + * busy, not able to present the interrupt. When our + * sync. interrupt arrived we reset the I/O old PSW to + * its original value. + */ + memcpy( &io_new_psw, &lc->io_new_psw, sizeof(psw_t)); + + ccode = iac(); + + switch (ccode) { + case 0: // primary-space + io_sync_wait.mask = _IO_PSW_MASK + | _PSW_PRIM_SPACE_MODE + | _PSW_IO_WAIT; + break; + case 1: // secondary-space + io_sync_wait.mask = _IO_PSW_MASK + | _PSW_SEC_SPACE_MODE + | _PSW_IO_WAIT; + break; + case 2: // access-register + io_sync_wait.mask = _IO_PSW_MASK + | _PSW_ACC_REG_MODE + | _PSW_IO_WAIT; + break; + case 3: // home-space + io_sync_wait.mask = _IO_PSW_MASK + | _PSW_HOME_SPACE_MODE + | _PSW_IO_WAIT; + break; + default: + panic( "start_IO() : unexpected " + "address-space-control %d\n", + ccode); + break; + } /* endswitch */ + + io_sync_wait.addr = FIX_PSW(&&io_wakeup); + + /* + * Martin didn't like modifying the new PSW, now we take + * a fast exit in do_IRQ() instead + */ + *(__u32 *)__LC_SYNC_IO_WORD = 1; + + do + { + if ( flag & DOIO_TIMEOUT ) + { + tpi_info_t tpi_info; + + do + { + if ( tpi(&tpi_info) == 1 ) + { + io_sub = tpi_info.irq; + break; + } + else + { + count--; + tod_wait(100); /* usecs */ + + } /* endif */ + + } while ( count ); + } + else + { + asm volatile ("lpsw %0" : : "m" (io_sync_wait)); + +io_wakeup: + io_sub = (__u32)*(__u16 *)__LC_SUBCHANNEL_NR; + + } /* endif */ + + if ( count ) + ready = s390_process_IRQ( io_sub ); + + /* + * surrender when retry count's exceeded ... + */ + + } while ( !( ( io_sub == irq ) + && ( ready == 1 )) + && count ); + + *(__u32 *)__LC_SYNC_IO_WORD = 0; + + if ( !count ) + ret = -ETIMEDOUT; + + } /* endif */ + + break; + + case 1 : /* status pending */ + + ioinfo[irq]->devstat.flag |= DEVSTAT_STATUS_PENDING; + + /* + * initialize the device driver specific devstat irb area + */ + memset( &((devstat_t *) ioinfo[irq]->irq_desc.action->dev_id)->ii.irb, + '\0', sizeof( irb_t) ); + + /* + * Let the common interrupt handler process the pending status. + * However, we must avoid calling the user action handler, as + * it won't be prepared to handle a pending status during + * do_IO() processing inline. This also implies that process_IRQ + * must terminate synchronously - especially if device sensing + * is required. + */ + ioinfo[irq]->ui.flags.s_pend = 1; + ioinfo[irq]->ui.flags.busy = 1; + ioinfo[irq]->ui.flags.doio = 1; + + s390_process_IRQ( irq ); + + ioinfo[irq]->ui.flags.s_pend = 0; + ioinfo[irq]->ui.flags.busy = 0; + ioinfo[irq]->ui.flags.doio = 0; + ioinfo[irq]->ui.flags.repall = 0; + ioinfo[irq]->ui.flags.w4final = 0; + + ioinfo[irq]->devstat.flag |= DEVSTAT_FINAL_STATUS; + + /* + * In multipath mode a condition code 3 implies the last path + * has gone, except we have previously restricted the I/O to + * a particular path. A condition code 1 (0 won't occur) + * results in return code EIO as well as 3 with another path + * than the one used (i.e. path available mask is non-zero). + */ + if ( ioinfo[irq]->devstat.ii.irb.scsw.cc == 3 ) + { + ret = -ENODEV; + ioinfo[irq]->devstat.flag |= DEVSTAT_NOT_OPER; + ioinfo[irq]->ui.flags.oper = 0; + +#if CONFIG_DEBUG_IO + { + char buffer[80]; + + stsch(irq, &(ioinfo[irq]->schib) ); + + sprintf( buffer, "s390_start_IO(%04X) - irb for " + "device %04X, after status pending\n", + irq, + ioinfo[irq]->devstat.devno ); + + s390_displayhex( buffer, + &(ioinfo[irq]->devstat.ii.irb) , + sizeof(irb_t)); + + sprintf( buffer, "s390_start_IO(%04X) - schib for " + "device %04X, after status pending\n", + irq, + ioinfo[irq]->devstat.devno ); + + s390_displayhex( buffer, + &(ioinfo[irq]->schib) , + sizeof(schib_t)); + + + if (ioinfo[irq]->devstat.flag & DEVSTAT_FLAG_SENSE_AVAIL) + { + sprintf( buffer, "s390_start_IO(%04X) - sense " + "data for " + "device %04X, after status pending\n", + irq, + ioinfo[irq]->devstat.devno ); + + s390_displayhex( buffer, + ((devstat_t *)(ioinfo[irq]->irq_desc.action->dev_id))->ii.sense.data, + ((devstat_t *)(ioinfo[irq]->irq_desc.action->dev_id))->rescnt); + + } + } +#endif + } + else + { + ret = -EIO; + ioinfo[irq]->devstat.flag &= ~DEVSTAT_NOT_OPER; + ioinfo[irq]->ui.flags.oper = 1; + + } /* endif */ + + break; + + case 2 : /* busy */ + + ret = -EBUSY; + break; + + default: /* device not operational */ + + ret = -ENODEV; + ioinfo[irq]->ui.flags.oper = 0; + + ioinfo[irq]->devstat.flag |= DEVSTAT_NOT_OPER; + + memcpy( ioinfo[irq]->irq_desc.action->dev_id, + &(ioinfo[irq]->devstat), + sizeof( devstat_t) ); + +#if CONFIG_DEBUG_IO + { + char buffer[80]; + + stsch(irq, &(ioinfo[irq]->schib) ); + + sprintf( buffer, "s390_start_IO(%04X) - schib for " + "device %04X, after 'not oper' status\n", + irq, + ioinfo[irq]->devstat.devno ); + + s390_displayhex( buffer, + &(ioinfo[irq]->schib), + sizeof(schib_t)); + } +#endif + break; + + } /* endswitch */ + + if ( ( flag & DOIO_WAIT_FOR_INTERRUPT ) + && ( sync_isc_locked ) ) + { + disable_cpu_sync_isc( irq ); + + spin_unlock_irqrestore( &sync_isc, psw_flags); + + sync_isc_locked = 0; // local setting + ioinfo[irq]->ui.flags.syncio = 0; // global setting + + } /* endif */ + + return( ret); +} + +int do_IO( int irq, /* IRQ */ + ccw1_t *cpa, /* channel program address */ + unsigned long user_intparm, /* interruption parameter */ + __u8 lpm, /* logical path mask */ + unsigned long flag) /* flags : see above */ +{ + int ret = 0; + + if ( irq > highest_subchannel || irq < 0 ) + { + return( -ENODEV ); + + } /* endif */ + + if ( ioinfo[irq] == INVALID_STORAGE_AREA ) + { + return( -ENODEV); + } + + /* handler registered ? or free_irq() in process already ? */ + if ( !ioinfo[irq]->ui.flags.ready || ioinfo[irq]->ui.flags.unready ) + { + return( -ENODEV ); + + } /* endif */ + + /* + * Note: We ignore the device operational status - if not operational, + * the SSCH will lead to an -ENODEV condition ... + */ + if ( !ioinfo[irq]->ui.flags.busy ) /* last I/O completed ? */ + { + ret = s390_start_IO( irq, cpa, user_intparm, lpm, flag); + } + else if ( ioinfo[irq]->ui.flags.fast ) + { + /* + * If primary status was received and ending status is missing, + * the device driver won't be notified on the ending status + * if early (fast) interrupt notification was requested. + * Therefore we have to queue the next incoming request. If + * halt_IO() is issued while there is a request queued, a HSCH + * needs to be issued and the queued request must be deleted + * but its intparm must be returned (see halt_IO() processing) + */ + if ( ioinfo[irq]->ui.flags.w4final + && !ioinfo[irq]->ui.flags.doio_q ) + { + ioinfo[irq]->qflag = flag; + ioinfo[irq]->qcpa = cpa; + ioinfo[irq]->qintparm = user_intparm; + ioinfo[irq]->qlpm = lpm; + } + else + { + ret = -EBUSY; + + } /* endif */ + } + else + { + ret = -EBUSY; + + } /* endif */ + + return( ret ); + +} + +/* + * resume suspended I/O operation + */ +int resume_IO( int irq) +{ + int ret = 0; + + if ( irq > highest_subchannel || irq < 0 ) + { + return( -ENODEV ); + + } /* endif */ + + if ( ioinfo[irq] == INVALID_STORAGE_AREA ) + { + return( -ENODEV); + } + + /* + * We allow for 'resume' requests only for active I/O operations + */ + if ( ioinfo[irq]->ui.flags.busy ) + { + int ccode; + + ccode = rsch( irq); + + switch (ccode) { + case 0 : + break; + + case 1 : + s390_process_IRQ( irq ); + ret = -EBUSY; + break; + + case 2 : + ret = -EINVAL; + break; + + case 3 : + /* + * useless to wait for request completion + * as device is no longer operational ! + */ + ioinfo[irq]->ui.flags.oper = 0; + ioinfo[irq]->ui.flags.busy = 0; + ret = -ENODEV; + break; + + } /* endswitch */ + + } + else + { + ret = -ENOTCONN; + + } /* endif */ + + return( ret); +} + +/* + * Note: The "intparm" parameter is not used by the halt_IO() function + * itself, as no ORB is built for the HSCH instruction. However, + * it allows the device interrupt handler to associate the upcoming + * interrupt with the halt_IO() request. + */ +int halt_IO( int irq, + unsigned long user_intparm, + unsigned long flag) /* possible DOIO_WAIT_FOR_INTERRUPT */ +{ + int ret; + int ccode; + unsigned long psw_flags; + + int sync_isc_locked = 0; + + if ( irq > highest_subchannel || irq < 0 ) + { + ret = -ENODEV; + } + + if ( ioinfo[irq] == INVALID_STORAGE_AREA ) + { + return( -ENODEV); + } + + /* + * we only allow for halt_IO if the device has an I/O handler associated + */ + else if ( !ioinfo[irq]->ui.flags.ready ) + { + ret = -ENODEV; + } + /* + * we ignore the halt_io() request if ending_status was received but + * a SENSE operation is waiting for completion. + */ + else if ( ioinfo[irq]->ui.flags.w4sense ) + { + ret = 0; + } + /* + * We don't allow for halt_io with a sync do_IO() requests pending. + */ + else if ( ioinfo[irq]->ui.flags.syncio ) + { + ret = -EBUSY; + } + else + { + /* + * If sync processing was requested we lock the sync ISC, + * modify the device to present interrupts for this ISC only + * and switch the CPU to handle this ISC + the console ISC + * exclusively. + */ + if ( flag & DOIO_WAIT_FOR_INTERRUPT ) + { + // + // check whether we run recursively (sense processing) + // + if ( !ioinfo[irq]->ui.flags.syncio ) + { + spin_lock_irqsave( &sync_isc, psw_flags); + + ret = enable_cpu_sync_isc( irq); + + if ( ret ) + { + spin_unlock_irqrestore( &sync_isc, + psw_flags); + return( ret); + } + else + { + sync_isc_locked = 1; // local + ioinfo[irq]->ui.flags.syncio = 1; // global + + } /* endif */ + + } /* endif */ + + } /* endif */ + + /* + * Issue "Halt subchannel" and process condition code + */ + ccode = hsch( irq ); + + switch ( ccode ) { + case 0: + + ioinfo[irq]->ui.flags.haltio = 1; + + if ( !ioinfo[irq]->ui.flags.doio ) + { + ioinfo[irq]->ui.flags.busy = 1; + ioinfo[irq]->u_intparm = user_intparm; + ioinfo[irq]->devstat.cstat = 0; + ioinfo[irq]->devstat.dstat = 0; + ioinfo[irq]->devstat.lpum = 0; + ioinfo[irq]->devstat.flag = DEVSTAT_HALT_FUNCTION; + ioinfo[irq]->devstat.scnt = 0; + + } + else + { + ioinfo[irq]->devstat.flag |= DEVSTAT_HALT_FUNCTION; + + } /* endif */ + + /* + * If synchronous I/O processing is requested, we have + * to wait for the corresponding interrupt to occur by + * polling the interrupt condition. However, as multiple + * interrupts may be outstanding, we must not just wait + * for the first interrupt, but must poll until ours + * pops up. + */ + if ( flag & DOIO_WAIT_FOR_INTERRUPT ) + { + int io_sub; + __u32 io_parm; + psw_t io_new_psw; + int ccode; + + int ready = 0; + struct _lowcore *lc = NULL; + + /* + * We shouldn't perform a TPI loop, waiting for + * an interrupt to occur, but should load a + * WAIT PSW instead. Otherwise we may keep the + * channel subsystem busy, not able to present + * the interrupt. When our sync. interrupt + * arrived we reset the I/O old PSW to its + * original value. + */ + memcpy( &io_new_psw, + &lc->io_new_psw, + sizeof(psw_t)); + + ccode = iac(); + + switch (ccode) { + case 0: // primary-space + io_sync_wait.mask = _IO_PSW_MASK + | _PSW_PRIM_SPACE_MODE + | _PSW_IO_WAIT; + break; + case 1: // secondary-space + io_sync_wait.mask = _IO_PSW_MASK + | _PSW_SEC_SPACE_MODE + | _PSW_IO_WAIT; + break; + case 2: // access-register + io_sync_wait.mask = _IO_PSW_MASK + | _PSW_ACC_REG_MODE + | _PSW_IO_WAIT; + break; + case 3: // home-space + io_sync_wait.mask = _IO_PSW_MASK + | _PSW_HOME_SPACE_MODE + | _PSW_IO_WAIT; + break; + default: + panic( "halt_IO() : unexpected " + "address-space-control %d\n", + ccode); + break; + } /* endswitch */ + + io_sync_wait.addr = FIX_PSW(&&hio_wakeup); + + /* + * Martin didn't like modifying the new PSW, now we take + * a fast exit in do_IRQ() instead + */ + *(__u32 *)__LC_SYNC_IO_WORD = 1; + + do + { + + asm volatile ( "lpsw %0" : : "m" (io_sync_wait) ); +hio_wakeup: + io_parm = *(__u32 *)__LC_IO_INT_PARM; + io_sub = (__u32)*(__u16 *)__LC_SUBCHANNEL_NR; + + ready = s390_process_IRQ( io_sub ); + + } while ( !((io_sub == irq) && (ready == 1)) ); + + *(__u32 *)__LC_SYNC_IO_WORD = 0; + + } /* endif */ + + ret = 0; + break; + + case 1 : /* status pending */ + + ioinfo[irq]->devstat.flag |= DEVSTAT_STATUS_PENDING; + + /* + * initialize the device driver specific devstat irb area + */ + memset( &((devstat_t *) ioinfo[irq]->irq_desc.action->dev_id)->ii.irb, + '\0', sizeof( irb_t) ); + + /* + * Let the common interrupt handler process the pending + * status. However, we must avoid calling the user + * action handler, as it won't be prepared to handle + * a pending status during do_IO() processing inline. + * This also implies that s390_process_IRQ must + * terminate synchronously - especially if device + * sensing is required. + */ + ioinfo[irq]->ui.flags.s_pend = 1; + ioinfo[irq]->ui.flags.busy = 1; + ioinfo[irq]->ui.flags.doio = 1; + + s390_process_IRQ( irq ); + + ioinfo[irq]->ui.flags.s_pend = 0; + ioinfo[irq]->ui.flags.busy = 0; + ioinfo[irq]->ui.flags.doio = 0; + ioinfo[irq]->ui.flags.repall = 0; + ioinfo[irq]->ui.flags.w4final = 0; + + ioinfo[irq]->devstat.flag |= DEVSTAT_FINAL_STATUS; + + /* + * In multipath mode a condition code 3 implies the last + * path has gone, except we have previously restricted + * the I/O to a particular path. A condition code 1 + * (0 won't occur) results in return code EIO as well + * as 3 with another path than the one used (i.e. path available mask is non-zero). + */ + if ( ioinfo[irq]->devstat.ii.irb.scsw.cc == 3 ) + { + ret = -ENODEV; + ioinfo[irq]->devstat.flag |= DEVSTAT_NOT_OPER; + ioinfo[irq]->ui.flags.oper = 0; + } + else + { + ret = -EIO; + ioinfo[irq]->devstat.flag &= ~DEVSTAT_NOT_OPER; + ioinfo[irq]->ui.flags.oper = 1; + + } /* endif */ + + break; + + case 2 : /* busy */ + + ret = -EBUSY; + break; + + default: /* device not operational */ + + ret = -ENODEV; + break; + + } /* endswitch */ + + if ( ( flag & DOIO_WAIT_FOR_INTERRUPT ) + && ( sync_isc_locked ) ) + { + sync_isc_locked = 0; // local setting + ioinfo[irq]->ui.flags.syncio = 0; // global setting + + disable_cpu_sync_isc( irq ); + + spin_unlock_irqrestore( &sync_isc, psw_flags); + + } /* endif */ + + } /* endif */ + + return( ret ); +} + +/* + * Note: The "intparm" parameter is not used by the clear_IO() function + * itself, as no ORB is built for the CSCH instruction. However, + * it allows the device interrupt handler to associate the upcoming + * interrupt with the clear_IO() request. + */ +int clear_IO( int irq, + unsigned long user_intparm, + unsigned long flag) /* possible DOIO_WAIT_FOR_INTERRUPT */ +{ + int ret; + int ccode; + unsigned long psw_flags; + + int sync_isc_locked = 0; + + if ( irq > highest_subchannel || irq < 0 ) + { + ret = -ENODEV; + } + + if ( ioinfo[irq] == INVALID_STORAGE_AREA ) + { + return( -ENODEV); + } + + /* + * we only allow for halt_IO if the device has an I/O handler associated + */ + else if ( !ioinfo[irq]->ui.flags.ready ) + { + ret = -ENODEV; + } + /* + * we ignore the halt_io() request if ending_status was received but + * a SENSE operation is waiting for completion. + */ + else if ( ioinfo[irq]->ui.flags.w4sense ) + { + ret = 0; + } + /* + * We don't allow for halt_io with a sync do_IO() requests pending. + * Concurrent I/O is possible in SMP environments only, but the + * sync. I/O request can be gated to one CPU at a time only. + */ + else if ( ioinfo[irq]->ui.flags.syncio ) + { + ret = -EBUSY; + } + else + { + /* + * If sync processing was requested we lock the sync ISC, + * modify the device to present interrupts for this ISC only + * and switch the CPU to handle this ISC + the console ISC + * exclusively. + */ + if ( flag & DOIO_WAIT_FOR_INTERRUPT ) + { + // + // check whether we run recursively (sense processing) + // + if ( !ioinfo[irq]->ui.flags.syncio ) + { + spin_lock_irqsave( &sync_isc, psw_flags); + + ret = enable_cpu_sync_isc( irq); + + if ( ret ) + { + spin_unlock_irqrestore( &sync_isc, + psw_flags); + return( ret); + } + else + { + sync_isc_locked = 1; // local + ioinfo[irq]->ui.flags.syncio = 1; // global + + } /* endif */ + + } /* endif */ + + } /* endif */ + + /* + * Issue "Halt subchannel" and process condition code + */ + ccode = csch( irq ); + + switch ( ccode ) { + case 0: + + ioinfo[irq]->ui.flags.haltio = 1; + + if ( !ioinfo[irq]->ui.flags.doio ) + { + ioinfo[irq]->ui.flags.busy = 1; + ioinfo[irq]->u_intparm = user_intparm; + ioinfo[irq]->devstat.cstat = 0; + ioinfo[irq]->devstat.dstat = 0; + ioinfo[irq]->devstat.lpum = 0; + ioinfo[irq]->devstat.flag = DEVSTAT_CLEAR_FUNCTION; + ioinfo[irq]->devstat.scnt = 0; + + } + else + { + ioinfo[irq]->devstat.flag |= DEVSTAT_CLEAR_FUNCTION; + + } /* endif */ + + /* + * If synchronous I/O processing is requested, we have + * to wait for the corresponding interrupt to occur by + * polling the interrupt condition. However, as multiple + * interrupts may be outstanding, we must not just wait + * for the first interrupt, but must poll until ours + * pops up. + */ + if ( flag & DOIO_WAIT_FOR_INTERRUPT ) + { + int io_sub; + __u32 io_parm; + psw_t io_new_psw; + int ccode; + + int ready = 0; + struct _lowcore *lc = NULL; + + /* + * We shouldn't perform a TPI loop, waiting for + * an interrupt to occur, but should load a + * WAIT PSW instead. Otherwise we may keep the + * channel subsystem busy, not able to present + * the interrupt. When our sync. interrupt + * arrived we reset the I/O old PSW to its + * original value. + */ + memcpy( &io_new_psw, + &lc->io_new_psw, + sizeof(psw_t)); + + ccode = iac(); + + switch (ccode) { + case 0: // primary-space + io_sync_wait.mask = _IO_PSW_MASK + | _PSW_PRIM_SPACE_MODE + | _PSW_IO_WAIT; + break; + case 1: // secondary-space + io_sync_wait.mask = _IO_PSW_MASK + | _PSW_SEC_SPACE_MODE + | _PSW_IO_WAIT; + break; + case 2: // access-register + io_sync_wait.mask = _IO_PSW_MASK + | _PSW_ACC_REG_MODE + | _PSW_IO_WAIT; + break; + case 3: // home-space + io_sync_wait.mask = _IO_PSW_MASK + | _PSW_HOME_SPACE_MODE + | _PSW_IO_WAIT; + break; + default: + panic( "halt_IO() : unexpected " + "address-space-control %d\n", + ccode); + break; + } /* endswitch */ + + io_sync_wait.addr = FIX_PSW(&&cio_wakeup); + + /* + * Martin didn't like modifying the new PSW, now we take + * a fast exit in do_IRQ() instead + */ + *(__u32 *)__LC_SYNC_IO_WORD = 1; + + do + { + + asm volatile ( "lpsw %0" : : "m" (io_sync_wait) ); +cio_wakeup: + io_parm = *(__u32 *)__LC_IO_INT_PARM; + io_sub = (__u32)*(__u16 *)__LC_SUBCHANNEL_NR; + + ready = s390_process_IRQ( io_sub ); + + } while ( !((io_sub == irq) && (ready == 1)) ); + + *(__u32 *)__LC_SYNC_IO_WORD = 0; + + } /* endif */ + + ret = 0; + break; + + case 1 : /* status pending */ + + ioinfo[irq]->devstat.flag |= DEVSTAT_STATUS_PENDING; + + /* + * initialize the device driver specific devstat irb area + */ + memset( &((devstat_t *) ioinfo[irq]->irq_desc.action->dev_id)->ii.irb, + '\0', sizeof( irb_t) ); + + /* + * Let the common interrupt handler process the pending + * status. However, we must avoid calling the user + * action handler, as it won't be prepared to handle + * a pending status during do_IO() processing inline. + * This also implies that s390_process_IRQ must + * terminate synchronously - especially if device + * sensing is required. + */ + ioinfo[irq]->ui.flags.s_pend = 1; + ioinfo[irq]->ui.flags.busy = 1; + ioinfo[irq]->ui.flags.doio = 1; + + s390_process_IRQ( irq ); + + ioinfo[irq]->ui.flags.s_pend = 0; + ioinfo[irq]->ui.flags.busy = 0; + ioinfo[irq]->ui.flags.doio = 0; + ioinfo[irq]->ui.flags.repall = 0; + ioinfo[irq]->ui.flags.w4final = 0; + + ioinfo[irq]->devstat.flag |= DEVSTAT_FINAL_STATUS; + + /* + * In multipath mode a condition code 3 implies the last + * path has gone, except we have previously restricted + * the I/O to a particular path. A condition code 1 + * (0 won't occur) results in return code EIO as well + * as 3 with another path than the one used (i.e. path available mask is non-zero). + */ + if ( ioinfo[irq]->devstat.ii.irb.scsw.cc == 3 ) + { + ret = -ENODEV; + ioinfo[irq]->devstat.flag |= DEVSTAT_NOT_OPER; + ioinfo[irq]->ui.flags.oper = 0; + } + else + { + ret = -EIO; + ioinfo[irq]->devstat.flag &= ~DEVSTAT_NOT_OPER; + ioinfo[irq]->ui.flags.oper = 1; + + } /* endif */ + + break; + + case 2 : /* busy */ + + ret = -EBUSY; + break; + + default: /* device not operational */ + + ret = -ENODEV; + break; + + } /* endswitch */ + + if ( ( flag & DOIO_WAIT_FOR_INTERRUPT ) + && ( sync_isc_locked ) ) + { + sync_isc_locked = 0; // local setting + ioinfo[irq]->ui.flags.syncio = 0; // global setting + + disable_cpu_sync_isc( irq ); + + spin_unlock_irqrestore( &sync_isc, psw_flags); + + } /* endif */ + + } /* endif */ + + return( ret ); +} + + +/* + * do_IRQ() handles all normal I/O device IRQ's (the special + * SMP cross-CPU interrupts have their own specific + * handlers). + * + * Returns: 0 - no ending status received, no further action taken + * 1 - interrupt handler was called with ending status + */ +asmlinkage void do_IRQ( struct pt_regs regs, + unsigned int irq, + __u32 s390_intparm ) +{ +#ifdef CONFIG_FAST_IRQ + int ccode; + tpi_info_t tpi_info; + int new_irq; +#endif + int use_irq = irq; +// __u32 use_intparm = s390_intparm; + + // + // fix me !!! + // + // We need to schedule device recognition, the interrupt stays + // pending. We need to dynamically allocate an ioinfo structure. + // + if ( ioinfo[irq] == INVALID_STORAGE_AREA ) + { + return; /* this keeps the device boxed ... */ + } + + /* + * take fast exit if CPU is in sync. I/O state + * + * Note: we have to turn off the WAIT bit and re-disable + * interrupts prior to return as this was the initial + * entry condition to synchronous I/O. + */ + if ( *(__u32 *)__LC_SYNC_IO_WORD ) + { + regs.psw.mask &= ~(_PSW_WAIT_MASK_BIT | _PSW_IO_MASK_BIT); + + return; + + } /* endif */ + + s390irq_spin_lock(use_irq); + +#ifdef CONFIG_FAST_IRQ + do { +#endif /* CONFIG_FAST_IRQ */ + + s390_process_IRQ( use_irq ); + +#ifdef CONFIG_FAST_IRQ + + /* + * more interrupts pending ? + */ + ccode = tpi( &tpi_info ); + + if ( ! ccode ) + break; // no, leave ... + + new_irq = tpi_info.irq; +// use_intparm = tpi_info.intparm; + + /* + * if the interrupt is for a different irq we + * release the current irq lock and obtain + * a new one ... + */ + if ( new_irq != use_irq ) + { + s390irq_spin_unlock(use_irq); + use_irq = new_irq; + s390irq_spin_lock(use_irq); + + } /* endif */ + + } while ( 1 ); + +#endif /* CONFIG_FAST_IRQ */ + + s390irq_spin_unlock(use_irq); + + return; +} + +/* + * s390_process_IRQ() handles status pending situations and interrupts + * + * Called by : do_IRQ() - for "real" interrupts + * s390_start_IO, halt_IO() + * - status pending cond. after SSCH, or HSCH + * disable_subchannel() - status pending conditions (after MSCH) + * + * Returns: 0 - no ending status received, no further action taken + * 1 - interrupt handler was called with ending status + */ +int s390_process_IRQ( unsigned int irq ) +{ + int ccode; /* condition code from tsch() operation */ + int irb_cc; /* condition code from irb */ + int sdevstat; /* effective struct devstat size to copy */ + unsigned int fctl; /* function control */ + unsigned int stctl; /* status control */ + unsigned int actl; /* activity control */ + struct irqaction *action; + struct pt_regs regs; /* for interface compatibility only */ + + int issense = 0; + int ending_status = 0; + int allow4handler = 1; + int chnchk = 0; +#if 0 + int cpu = smp_processor_id(); + + kstat.irqs[cpu][irq]++; +#endif + action = ioinfo[irq]->irq_desc.action; + + /* + * It might be possible that a device was not-oper. at the time + * of free_irq() processing. This means the handler is no longer + * available when the device possibly becomes ready again. In + * this case we perform delayed disable_subchannel() processing. + */ + if ( action == NULL ) + { + if ( !ioinfo[irq]->ui.flags.d_disable ) + { + printk( KERN_CRIT"s390_process_IRQ(%04X) " + "- no interrupt handler registered" + "for device %04X !\n", + irq, + ioinfo[irq]->devstat.devno); + + } /* endif */ + + } /* endif */ + + /* + * retrieve the i/o interrupt information (irb), + * update the device specific status information + * and possibly call the interrupt handler. + * + * Note 1: At this time we don't process the resulting + * condition code (ccode) from tsch(), although + * we probably should. + * + * Note 2: Here we will have to check for channel + * check conditions and call a channel check + * handler. + * + * Note 3: If a start function was issued, the interruption + * parameter relates to it. If a halt function was + * issued for an idle device, the intparm must not + * be taken from lowcore, but from the devstat area. + */ + ccode = tsch( irq, &(ioinfo[irq]->devstat.ii.irb) ); + + // + // We must only accumulate the status if initiated by do_IO() or halt_IO() + // + if ( ioinfo[irq]->ui.flags.busy ) + { + ioinfo[irq]->devstat.dstat |= ioinfo[irq]->devstat.ii.irb.scsw.dstat; + ioinfo[irq]->devstat.cstat |= ioinfo[irq]->devstat.ii.irb.scsw.cstat; + } + else + { + ioinfo[irq]->devstat.dstat = ioinfo[irq]->devstat.ii.irb.scsw.dstat; + ioinfo[irq]->devstat.cstat = ioinfo[irq]->devstat.ii.irb.scsw.cstat; + + ioinfo[irq]->devstat.flag = 0; // reset status flags + + } /* endif */ + + ioinfo[irq]->devstat.lpum = ioinfo[irq]->devstat.ii.irb.esw.esw1.lpum; + + if ( ioinfo[irq]->ui.flags.busy) + { + ioinfo[irq]->devstat.intparm = ioinfo[irq]->u_intparm; + + } /* endif */ + + /* + * reset device-busy bit if no longer set in irb + */ + if ( (ioinfo[irq]->devstat.dstat & DEV_STAT_BUSY ) + && ((ioinfo[irq]->devstat.ii.irb.scsw.dstat & DEV_STAT_BUSY) == 0)) + { + ioinfo[irq]->devstat.dstat &= ~DEV_STAT_BUSY; + + } /* endif */ + + /* + * Save residual count and CCW information in case primary and + * secondary status are presented with different interrupts. + */ + if ( ioinfo[irq]->devstat.ii.irb.scsw.stctl & SCSW_STCTL_PRIM_STATUS ) + { + ioinfo[irq]->devstat.rescnt = ioinfo[irq]->devstat.ii.irb.scsw.count; + +#if CONFIG_DEBUG_IO + if ( irq != cons_dev ) + printk( "s390_process_IRQ( %04X ) : " + "residual count from irb after tsch() %d\n", + irq, ioinfo[irq]->devstat.rescnt ); +#endif + } /* endif */ + + if ( ioinfo[irq]->devstat.ii.irb.scsw.cpa != 0 ) + { + ioinfo[irq]->devstat.cpa = ioinfo[irq]->devstat.ii.irb.scsw.cpa; + + } /* endif */ + + irb_cc = ioinfo[irq]->devstat.ii.irb.scsw.cc; + + // + // check for any kind of channel or interface control check but don't + // issue the message for the console device + // + if ( (ioinfo[irq]->devstat.ii.irb.scsw.cstat + & ( SCHN_STAT_CHN_DATA_CHK + | SCHN_STAT_CHN_CTRL_CHK + | SCHN_STAT_INTF_CTRL_CHK ) ) + && (irq != cons_dev ) ) + { + printk( "Channel-Check or Interface-Control-Check " + "received\n" + " ... device %04X on subchannel %04X, dev_stat " + ": %02X sch_stat : %02X\n", + ioinfo[irq]->devstat.devno, + irq, + ioinfo[irq]->devstat.dstat, + ioinfo[irq]->devstat.cstat); + + chnchk = 1; + + } /* endif */ + + issense = ioinfo[irq]->devstat.ii.irb.esw.esw0.erw.cons; + + if ( issense ) + { + ioinfo[irq]->devstat.scnt = + ioinfo[irq]->devstat.ii.irb.esw.esw0.erw.scnt; + ioinfo[irq]->devstat.flag |= + DEVSTAT_FLAG_SENSE_AVAIL; + + sdevstat = sizeof( devstat_t); + +#if CONFIG_DEBUG_IO + if ( irq != cons_dev ) + printk( "s390_process_IRQ( %04X ) : " + "concurrent sense bytes avail %d\n", + irq, ioinfo[irq]->devstat.scnt ); +#endif + } + else + { + /* don't copy the sense data area ! */ + sdevstat = sizeof( devstat_t) - SENSE_MAX_COUNT; + + } /* endif */ + + switch ( irb_cc ) { + case 1: /* status pending */ + + ioinfo[irq]->devstat.flag |= DEVSTAT_STATUS_PENDING; + + case 0: /* normal i/o interruption */ + + fctl = ioinfo[irq]->devstat.ii.irb.scsw.fctl; + stctl = ioinfo[irq]->devstat.ii.irb.scsw.stctl; + actl = ioinfo[irq]->devstat.ii.irb.scsw.actl; + + if ( chnchk && (ioinfo[irq]->senseid.cu_type == 0x3088)) + { + char buffer[80]; + + sprintf( buffer, "s390_process_IRQ(%04X) - irb for " + "device %04X after channel check\n", + irq, + ioinfo[irq]->devstat.devno ); + + s390_displayhex( buffer, + &(ioinfo[irq]->devstat.ii.irb) , + sizeof(irb_t)); + } /* endif */ + + ioinfo[irq]->stctl |= stctl; + + ending_status = ( stctl & SCSW_STCTL_SEC_STATUS ) + || ( stctl == (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND) ) + || ( (fctl == SCSW_FCTL_HALT_FUNC) && (stctl == SCSW_STCTL_STATUS_PEND) ); + + /* + * Check for unsolicited interrupts - for debug purposes only + * + * We only consider an interrupt as unsolicited, if the device was not + * actively in use (busy) and an interrupt other than an ALERT status + * was received. + * + * Note: We must not issue a message to the console, if the + * unsolicited interrupt applies to the console device + * itself ! + */ +#if CONFIG_DEBUG_IO + if ( ( irq != cons_dev ) + && !( stctl & SCSW_STCTL_ALERT_STATUS ) + && ( ioinfo[irq]->ui.flags.busy == 0 ) ) + { + char buffer[80]; + + printk( "Unsolicited interrupt received for device %04X on subchannel %04X\n" + " ... device status : %02X subchannel status : %02X\n", + ioinfo[irq]->devstat.devno, + irq, + ioinfo[irq]->devstat.dstat, + ioinfo[irq]->devstat.cstat); + + sprintf( buffer, "s390_process_IRQ(%04X) - irb for " + "device %04X, ending_status %d\n", + irq, + ioinfo[irq]->devstat.devno, + ending_status); + + s390_displayhex( buffer, + &(ioinfo[irq]->devstat.ii.irb) , + sizeof(irb_t)); + + } /* endif */ + + /* + * take fast exit if no handler is available + */ + if ( !action ) + return( ending_status ); + +#endif + /* + * Check whether we must issue a SENSE CCW ourselves if there is no + * concurrent sense facility installed for the subchannel. + * + * Note: We should check for ioinfo[irq]->ui.flags.consns but VM + * violates the ESA/390 architecture and doesn't present an + * operand exception for virtual devices without concurrent + * sense facility available/supported when enabling the + * concurrent sense facility. + */ + if ( ( ( ioinfo[irq]->devstat.ii.irb.scsw.dstat & DEV_STAT_UNIT_CHECK ) + && ( !issense ) ) + || ( ioinfo[irq]->ui.flags.delsense && ending_status ) ) + { + int ret_io; + ccw1_t *s_ccw = &ioinfo[irq]->senseccw; + unsigned long s_flag = 0; + + if ( ending_status ) + { + /* + * We copy the current status information into the device driver + * status area. Then we can use the local devstat area for device + * sensing. When finally calling the IRQ handler we must not overlay + * the original device status but copy the sense data only. + */ + memcpy( action->dev_id, + &(ioinfo[irq]->devstat), + sizeof( devstat_t) ); + + s_ccw->cmd_code = CCW_CMD_BASIC_SENSE; + s_ccw->cda = (__u32)virt_to_phys( ioinfo[irq]->devstat.ii.sense.data); + s_ccw->count = SENSE_MAX_COUNT; + s_ccw->flags = CCW_FLAG_SLI; + + /* + * If free_irq() or a sync do_IO/s390_start_IO() is in + * process we have to sense synchronously + */ + if ( ioinfo[irq]->ui.flags.unready || ioinfo[irq]->ui.flags.syncio ) + { + s_flag = DOIO_WAIT_FOR_INTERRUPT; + + } /* endif */ + + /* + * Reset status info + * + * It does not matter whether this is a sync. or async. + * SENSE request, but we have to assure we don't call + * the irq handler now, but keep the irq in busy state. + * In sync. mode s390_process_IRQ() is called recursively, + * while in async. mode we re-enter do_IRQ() with the + * next interrupt. + * + * Note : this may be a delayed sense request ! + */ + allow4handler = 0; + + ioinfo[irq]->ui.flags.fast = 0; + ioinfo[irq]->ui.flags.repall = 0; + ioinfo[irq]->ui.flags.w4final = 0; + ioinfo[irq]->ui.flags.delsense = 0; + + ioinfo[irq]->devstat.cstat = 0; + ioinfo[irq]->devstat.dstat = 0; + ioinfo[irq]->devstat.rescnt = SENSE_MAX_COUNT; + + ioinfo[irq]->ui.flags.w4sense = 1; + + ret_io = s390_start_IO( irq, + s_ccw, + 0xE2C5D5E2, // = SENSe + 0, // n/a + s_flag); + } + else + { + /* + * we received an Unit Check but we have no final + * status yet, therefore we must delay the SENSE + * processing. However, we must not report this + * intermediate status to the device interrupt + * handler. + */ + ioinfo[irq]->ui.flags.fast = 0; + ioinfo[irq]->ui.flags.repall = 0; + + ioinfo[irq]->ui.flags.delsense = 1; + allow4handler = 0; + + } /* endif */ + + } /* endif */ + + /* + * we allow for the device action handler if . + * - we received ending status + * - the action handler requested to see all interrupts + * - we received a PCI + * - fast notification was requested (primary status) + * - unsollicited interrupts + * + */ + if ( allow4handler ) + { + allow4handler = ending_status + || ( ioinfo[irq]->ui.flags.repall ) + || ( ioinfo[irq]->devstat.ii.irb.scsw.cstat & SCHN_STAT_PCI ) + || ( (ioinfo[irq]->ui.flags.fast ) && (stctl & SCSW_STCTL_PRIM_STATUS) ) + || ( ioinfo[irq]->ui.flags.oper == 0 ); + + } /* endif */ + + /* + * We used to copy the device status information right before + * calling the device action handler. However, in status + * pending situations during do_IO() or halt_IO(), as well as + * enable_subchannel/disable_subchannel processing we must + * synchronously return the status information and must not + * call the device action handler. + * + */ + if ( allow4handler ) + { + /* + * if we were waiting for sense data we copy the sense + * bytes only as the original status information was + * saved prior to sense already. + */ + if ( ioinfo[irq]->ui.flags.w4sense ) + { + int sense_count = SENSE_MAX_COUNT-ioinfo[irq]->devstat.rescnt; + +#if CONFIG_DEBUG_IO + if ( irq != cons_dev ) + printk( "s390_process_IRQ( %04X ) : " + "BASIC SENSE bytes avail %d\n", + irq, sense_count ); +#endif + ioinfo[irq]->ui.flags.w4sense = 0; + ((devstat_t *)(action->dev_id))->flag |= DEVSTAT_FLAG_SENSE_AVAIL; + ((devstat_t *)(action->dev_id))->scnt = sense_count; + + if ( sense_count >= 0 ) + { + memcpy( ((devstat_t *)(action->dev_id))->ii.sense.data, + &(ioinfo[irq]->devstat.ii.sense.data), + sense_count); + } + else + { +#if 1 + panic( "s390_process_IRQ(%04x) encountered " + "negative sense count\n", + irq); +#else + printk( KERN_CRIT"s390_process_IRQ(%04x) encountered " + "negative sense count\n", + irq); +#endif + } /* endif */ + } + else + { + memcpy( action->dev_id, &(ioinfo[irq]->devstat), sdevstat ); + + } /* endif */ + + } /* endif */ + + /* + * for status pending situations other than deferred interrupt + * conditions detected by s390_process_IRQ() itself we must not + * call the handler. This will synchronously be reported back + * to the caller instead, e.g. when detected during do_IO(). + */ + if ( ioinfo[irq]->ui.flags.s_pend || ioinfo[irq]->ui.flags.unready ) + allow4handler = 0; + + /* + * Call device action handler if applicable + */ + if ( allow4handler ) + { + + /* + * We only reset the busy condition when we are sure that no further + * interrupt is pending for the current I/O request (ending_status). + */ + if ( ending_status || !ioinfo[irq]->ui.flags.oper ) + { + ioinfo[irq]->ui.flags.oper = 1; /* dev IS oper */ + + ioinfo[irq]->ui.flags.busy = 0; + ioinfo[irq]->ui.flags.doio = 0; + ioinfo[irq]->ui.flags.haltio = 0; + ioinfo[irq]->ui.flags.fast = 0; + ioinfo[irq]->ui.flags.repall = 0; + ioinfo[irq]->ui.flags.w4final = 0; + + ioinfo[irq]->devstat.flag |= DEVSTAT_FINAL_STATUS; + ((devstat_t *)(action->dev_id))->flag |= DEVSTAT_FINAL_STATUS; + + action->handler( irq, action->dev_id, ®s); + + // + // reset intparm after final status or we will badly present unsolicited + // interrupts with a intparm value possibly no longer valid. + // + ioinfo[irq]->devstat.intparm = 0; + + // + // Was there anything queued ? Start the pending channel program + // if there is one. + // + if ( ioinfo[irq]->ui.flags.doio_q ) + { + int ret; + + ret = s390_start_IO( irq, + ioinfo[irq]->qcpa, + ioinfo[irq]->qintparm, + ioinfo[irq]->qlpm, + ioinfo[irq]->qflag); + + ioinfo[irq]->ui.flags.doio_q = 0; + + /* + * If s390_start_IO() failed call the device's interrupt + * handler, the IRQ related devstat area was setup by + * s390_start_IO() accordingly already (status pending + * condition). + */ + if ( ret ) + { + action->handler( irq, action->dev_id, ®s); + + } /* endif */ + + } /* endif */ + + } + else + { + ioinfo[irq]->ui.flags.w4final = 1; + action->handler( irq, action->dev_id, ®s); + + } /* endif */ + + } /* endif */ + + break; + + case 3: /* device not operational */ + + ioinfo[irq]->ui.flags.oper = 0; + + ioinfo[irq]->ui.flags.busy = 0; + ioinfo[irq]->ui.flags.doio = 0; + ioinfo[irq]->ui.flags.haltio = 0; + + ioinfo[irq]->devstat.cstat = 0; + ioinfo[irq]->devstat.dstat = 0; + ioinfo[irq]->devstat.flag |= DEVSTAT_NOT_OPER; + ioinfo[irq]->devstat.flag |= DEVSTAT_FINAL_STATUS; + + /* + * When we find a device "not oper" we save the status + * information into the device status area and call the + * device specific interrupt handler. + * + * Note: currently we don't have any way to reenable + * the device unless an unsolicited interrupt + * is presented. We don't check for spurious + * interrupts on "not oper" conditions. + */ + + if ( ( ioinfo[irq]->ui.flags.fast ) + && ( ioinfo[irq]->ui.flags.w4final ) ) + { + /* + * If a new request was queued already, we have + * to simulate the "not oper" status for the + * queued request by switching the "intparm" value + * and notify the interrupt handler. + */ + if ( ioinfo[irq]->ui.flags.doio_q ) + { + ioinfo[irq]->devstat.intparm = ioinfo[irq]->qintparm; + + } /* endif */ + + } /* endif */ + + ioinfo[irq]->ui.flags.fast = 0; + ioinfo[irq]->ui.flags.repall = 0; + ioinfo[irq]->ui.flags.w4final = 0; + + memcpy( action->dev_id, &(ioinfo[irq]->devstat), sdevstat ); + + ioinfo[irq]->devstat.intparm = 0; + + if ( !ioinfo[irq]->ui.flags.s_pend ) + action->handler( irq, action->dev_id, ®s); + + ending_status = 1; + + break; + + } /* endswitch */ + + return( ending_status ); +} + +/* + * Set the special i/o-interruption sublass 7 for the + * device specified by parameter irq. There can only + * be a single device been operated on this special + * isc. This function is aimed being able to check + * on special device interrupts in disabled state, + * without having to delay I/O processing (by queueing) + * for non-console devices. + * + * Setting of this isc is done by set_cons_dev(), while + * reset_cons_dev() resets this isc and re-enables the + * default isc3 for this device. wait_cons_dev() allows + * to actively wait on an interrupt for this device in + * disabed state. When the interrupt condition is + * encountered, wait_cons_dev(9 calls do_IRQ() to have + * the console device driver processing the interrupt. + */ +int set_cons_dev( int irq ) +{ + int ccode; + unsigned long cr6 __attribute__ ((aligned (8))); + int rc = 0; + + if ( cons_dev != -1 ) + { + rc = -EBUSY; + } + else if ( (irq > highest_subchannel) || (irq < 0) ) + { + rc = -ENODEV; + } + else if ( ioinfo[irq] == INVALID_STORAGE_AREA ) + { + return( -ENODEV); + } + else + { + /* + * modify the indicated console device to operate + * on special console interrupt sublass 7 + */ + ccode = stsch( irq, &(ioinfo[irq]->schib) ); + + if (ccode) + { + rc = -ENODEV; + ioinfo[irq]->devstat.flag |= DEVSTAT_NOT_OPER; + } + else + { + ioinfo[irq]->schib.pmcw.isc = 7; + + ccode = msch( irq, &(ioinfo[irq]->schib) ); + + if (ccode) + { + rc = -EIO; + } + else + { + cons_dev = irq; + + /* + * enable console I/O-interrupt sublass 7 + */ + asm volatile ("STCTL 6,6,%0": "=m" (cr6)); + cr6 |= 0x01000000; + asm volatile ("LCTL 6,6,%0":: "m" (cr6):"memory"); + + } /* endif */ + + } /* endif */ + + } /* endif */ + + return( rc); +} + +int reset_cons_dev( int irq) +{ + int rc = 0; + int ccode; + long cr6 __attribute__ ((aligned (8))); + + if ( cons_dev != -1 ) + { + rc = -EBUSY; + } + else if ( (irq > highest_subchannel) || (irq < 0) ) + { + rc = -ENODEV; + } + else if ( ioinfo[irq] == INVALID_STORAGE_AREA ) + { + return( -ENODEV); + } + else + { + /* + * reset the indicated console device to operate + * on default console interrupt sublass 3 + */ + ccode = stsch( irq, &(ioinfo[irq]->schib) ); + + if (ccode) + { + rc = -ENODEV; + ioinfo[irq]->devstat.flag |= DEVSTAT_NOT_OPER; + } + else + { + + ioinfo[irq]->schib.pmcw.isc = 3; + + ccode = msch( irq, &(ioinfo[irq]->schib) ); + + if (ccode) + { + rc = -EIO; + } + else + { + cons_dev = -1; + + /* + * disable special console I/O-interrupt sublass 7 + */ + asm volatile ("STCTL 6,6,%0": "=m" (cr6)); + cr6 &= 0xFEFFFFFF; + asm volatile ("LCTL 6,6,%0":: "m" (cr6):"memory"); + + } /* endif */ + + } /* endif */ + + } /* endif */ + + return( rc); +} + +int wait_cons_dev( int irq ) +{ + int rc = 0; + long save_cr6; + + if ( irq == cons_dev ) + { + + /* + * before entering the spinlock we may already have + * processed the interrupt on a different CPU ... + */ + if ( ioinfo[irq]->ui.flags.busy == 1 ) + { + long cr6 __attribute__ ((aligned (8))); + + /* + * disable all, but isc 7 (console device) + */ + asm volatile ("STCTL 6,6,%0": "=m" (cr6)); + save_cr6 = cr6; + cr6 &= 0x01FFFFFF; + asm volatile ("LCTL 6,6,%0":: "m" (cr6):"memory"); + + do { + tpi_info_t tpi_info; + if (tpi(&tpi_info) == 1) { + s390_process_IRQ( tpi_info.irq ); + } else { + s390irq_spin_unlock(irq); + tod_wait(100); + s390irq_spin_lock(irq); + } + eieio(); + } while (ioinfo[irq]->ui.flags.busy == 1); + + /* + * restore previous isc value + */ + asm volatile ("STCTL 6,6,%0": "=m" (cr6)); + cr6 = save_cr6; + asm volatile ("LCTL 6,6,%0":: "m" (cr6):"memory"); + + } /* endif */ + + } + else + { + rc = EINVAL; + + } /* endif */ + + + return(rc); +} + + +int enable_cpu_sync_isc( int irq ) +{ + int ccode; + long cr6 __attribute__ ((aligned (8))); + + int count = 0; + int rc = 0; + + if ( irq <= highest_subchannel && ioinfo[irq] != INVALID_STORAGE_AREA ) + { + ccode = stsch( irq, &(ioinfo[irq]->schib) ); + + if ( !ccode ) + { + ioinfo[irq]->schib.pmcw.isc = 5; + + do + { + ccode = msch( irq, &(ioinfo[irq]->schib) ); + + if (ccode == 0 ) + { + /* + * enable interrupt subclass in CPU + */ + asm volatile ("STCTL 6,6,%0": "=m" (cr6)); + cr6 |= 0x04000000; // enable sync isc 5 + cr6 &= 0xEFFFFFFF; // disable standard isc 3 + asm volatile ("LCTL 6,6,%0":: "m" (cr6):"memory"); + } + else if (ccode == 3) + { + rc = -ENODEV; // device not-oper - very unlikely + + } + else if (ccode == 2) + { + rc = -EBUSY; // device busy - should not happen + + } + else if (ccode == 1) + { + // + // process pending status + // + ioinfo[irq]->ui.flags.s_pend = 1; + + s390_process_IRQ( irq ); + + ioinfo[irq]->ui.flags.s_pend = 0; + + count++; + + } /* endif */ + + } while ( ccode == 1 && count < 3 ); + + if ( count == 3) + { + rc = -EIO; + + } /* endif */ + } + else + { + rc = -ENODEV; // device is not-operational + + } /* endif */ + } + else + { + rc = -EINVAL; + + } /* endif */ + + return( rc); +} + +int disable_cpu_sync_isc( int irq) +{ + int rc = 0; + int ccode; + long cr6 __attribute__ ((aligned (8))); + + if ( irq <= highest_subchannel && ioinfo[irq] != INVALID_STORAGE_AREA ) + { + ccode = stsch( irq, &(ioinfo[irq]->schib) ); + + ioinfo[irq]->schib.pmcw.isc = 3; + + ccode = msch( irq, &(ioinfo[irq]->schib) ); + + if (ccode) + { + rc = -EIO; + } + else + { + + /* + * enable interrupt subclass in CPU + */ + asm volatile ("STCTL 6,6,%0": "=m" (cr6)); + cr6 &= 0xFBFFFFFF; // disable sync isc 5 + cr6 |= 0x10000000; // enable standard isc 3 + asm volatile ("LCTL 6,6,%0":: "m" (cr6):"memory"); + + } /* endif */ + + } + else + { + rc = -EINVAL; + + } /* endif */ + + return( rc); +} + +// +// Input : +// devno - device number +// ps - pointer to sense ID data area +// +// Output : none +// +void VM_virtual_device_info( __u16 devno, + senseid_t *ps ) +{ + diag210_t diag_data; + int ccode; + + int error = 0; + + diag_data.vrdcdvno = devno; + diag_data.vrdclen = sizeof( diag210_t); + ccode = diag210( (diag210_t *)virt_to_phys( &diag_data ) ); + ps->reserved = 0xff; + + switch (diag_data.vrdcvcla) { + case 0x80: + + switch (diag_data.vrdcvtyp) { + case 00: + + ps->cu_type = 0x3215; + + break; + + default: + + error = 1; + + break; + + } /* endswitch */ + + break; + + case 0x40: + + switch (diag_data.vrdcvtyp) { + case 0xC0: + + ps->cu_type = 0x5080; + + break; + + case 0x80: + + ps->cu_type = 0x2250; + + break; + + case 0x04: + + ps->cu_type = 0x3277; + + break; + + case 0x01: + + ps->cu_type = 0x3278; + + break; + + default: + + error = 1; + + break; + + } /* endswitch */ + + break; + + case 0x20: + + switch (diag_data.vrdcvtyp) { + case 0x84: + + ps->cu_type = 0x3505; + + break; + + case 0x82: + + ps->cu_type = 0x2540; + + break; + + case 0x81: + + ps->cu_type = 0x2501; + + break; + + default: + + error = 1; + + break; + + } /* endswitch */ + + break; + + case 0x10: + + switch (diag_data.vrdcvtyp) { + case 0x84: + + ps->cu_type = 0x3525; + + break; + + case 0x82: + + ps->cu_type = 0x2540; + + break; + + case 0x4F: + case 0x4E: + case 0x48: + + ps->cu_type = 0x3820; + + break; + + case 0x4D: + case 0x49: + case 0x45: + + ps->cu_type = 0x3800; + + break; + + case 0x4B: + + ps->cu_type = 0x4248; + + break; + + case 0x4A: + + ps->cu_type = 0x4245; + + break; + + case 0x47: + + ps->cu_type = 0x3262; + + break; + + case 0x43: + + ps->cu_type = 0x3203; + + break; + + case 0x42: + + ps->cu_type = 0x3211; + + break; + + case 0x41: + + ps->cu_type = 0x1403; + + break; + + default: + + error = 1; + + break; + + } /* endswitch */ + + break; + + case 0x08: + + switch (diag_data.vrdcvtyp) { + case 0x82: + + ps->cu_type = 0x3422; + + break; + + case 0x81: + + ps->cu_type = 0x3490; + + break; + + case 0x10: + + ps->cu_type = 0x3420; + + break; + + case 0x02: + + ps->cu_type = 0x3430; + + break; + + case 0x01: + + ps->cu_type = 0x3480; + + break; + + case 0x42: + + ps->cu_type = 0x3424; + + break; + + case 0x44: + + ps->cu_type = 0x9348; + + break; + + default: + + error = 1; + + break; + + } /* endswitch */ + + break; + + default: + + error = 1; + + break; + + } /* endswitch */ + + if ( error ) + {printk( "DIAG X'210' for device %04X returned (cc = %d): vdev class : %02X, " + "vdev type : %04X \n ... rdev class : %02X, rdev type : %04X, rdev model: %02X\n", + devno, + ccode, + diag_data.vrdcvcla, + diag_data.vrdcvtyp, + diag_data.vrdcrccl, + diag_data.vrdccrty, + diag_data.vrdccrmd ); + + } /* endif */ + +} + +/* + * This routine returns the characteristics for the device + * specified. Some old devices might not provide the necessary + * command code information during SenseID processing. In this + * case the function returns -EINVAL. Otherwise the function + * allocates a decice specific data buffer and provides the + * device characteristics together with the buffer size. Its + * the callers responability to release the kernel memory if + * not longer needed. In case of persistent I/O problems -EBUSY + * is returned. + * + * The function may be called enabled or disabled. However, the + * caller must have locked the irq it is requesting data for. + * + * Note : It would have been nice to collect this information + * during init_IRQ() processing but this is not possible + * + * a) without statically pre-allocation fixed size buffers + * as virtual memory management isn't available yet. + * + * b) without unnecessarily increase system startup by + * evaluating devices eventually not used at all. + */ +int read_dev_chars( int irq, void **buffer, int length ) +{ + unsigned int flags; + ccw1_t *rdc_ccw; + devstat_t devstat; + char *rdc_buf; + int devflag; + + int ret = 0; + int emulated = 0; + int retry = 5; + + if ( !buffer || !length ) + { + return( -EINVAL ); + + } /* endif */ + + if ( (irq > highest_subchannel) || (irq < 0 ) ) + { + return( -ENODEV ); + + } + else if ( ioinfo[irq] == INVALID_STORAGE_AREA ) + { + return( -ENODEV); + } + + if ( ioinfo[irq]->ui.flags.oper == 0 ) + { + return( -ENODEV ); + + } /* endif */ + + /* + * Before playing around with irq locks we should assure + * running disabled on (just) our CPU. Sync. I/O requests + * also require to run disabled. + * + * Note : as no global lock is required, we must not use + * cli(), but __cli() instead. + */ + __save_flags(flags); + __cli(); + + rdc_ccw = &ioinfo[irq]->senseccw; + + if ( !ioinfo[irq]->ui.flags.ready ) + { + ret = request_irq( irq, + init_IRQ_handler, + 0, "RDC", &devstat ); + + if ( !ret ) + { + emulated = 1; + + } /* endif */ + + } /* endif */ + + if ( !ret ) + { + if ( ! *buffer ) + { + rdc_buf = kmalloc( length, GFP_KERNEL); + } + else + { + rdc_buf = *buffer; + + } /* endif */ + + if ( !rdc_buf ) + { + ret = -ENOMEM; + } + else + { + do + { + rdc_ccw->cmd_code = CCW_CMD_RDC; + rdc_ccw->cda = (__u32)virt_to_phys( rdc_buf ); + rdc_ccw->count = length; + rdc_ccw->flags = CCW_FLAG_SLI; + + ret = s390_start_IO( irq, + rdc_ccw, + 0x00524443, // RDC + 0, // n/a + DOIO_WAIT_FOR_INTERRUPT ); + retry--; + devflag = ((devstat_t *)(ioinfo[irq]->irq_desc.action->dev_id))->flag; + + } while ( ( retry ) + && ( ret || (devflag & DEVSTAT_STATUS_PENDING) ) ); + + } /* endif */ + + if ( !retry ) + { + ret = -EBUSY; + + } /* endif */ + + __restore_flags(flags); + + /* + * on success we update the user input parms + */ + if ( !ret ) + { + *buffer = rdc_buf; + + } /* endif */ + + if ( emulated ) + { + free_irq( irq, &devstat); + + } /* endif */ + + } /* endif */ + + return( ret ); +} + +/* + * Read Configuration data + */ +int read_conf_data( int irq, void **buffer, int *length ) +{ + int found = 0; + int ciw_cnt = 0; + unsigned int flags; + + int ret = 0; + + if ( (irq > highest_subchannel) || (irq < 0 ) ) + { + return( -ENODEV ); + } + else if ( ioinfo[irq] == INVALID_STORAGE_AREA ) + { + return( -ENODEV); + + } /* endif */ + + if ( ioinfo[irq]->ui.flags.oper == 0 ) + { + return( -ENODEV ); + + } /* endif */ + + /* + * scan for RCD command in extended SenseID data + */ + for ( ; (found == 0) && (ciw_cnt < 62); ciw_cnt++ ) + { + if ( ioinfo[irq]->senseid.ciw[ciw_cnt].ct == CIW_TYPE_RCD ) + { + found = 1; + break; + } /* endif */ + + } /* endfor */ + + if ( found ) + { + ccw1_t *rcd_ccw = &ioinfo[irq]->senseccw; + devstat_t devstat; + char *rcd_buf; + int devflag; + + int emulated = 0; + int retry = 5; + + __save_flags(flags); + __cli(); + + if ( !ioinfo[irq]->ui.flags.ready ) + { + ret = request_irq( irq, + init_IRQ_handler, + 0, "RCD", &devstat ); + + if ( !ret ) + { + emulated = 1; + + } /* endif */ + + } /* endif */ + + if ( !ret ) + { + rcd_buf = kmalloc( ioinfo[irq]->senseid.ciw[ciw_cnt].count, + GFP_KERNEL); + + do + { + rcd_ccw->cmd_code = ioinfo[irq]->senseid.ciw[ciw_cnt].cmd; + rcd_ccw->cda = (__u32)virt_to_phys( rcd_buf ); + rcd_ccw->count = ioinfo[irq]->senseid.ciw[ciw_cnt].count; + rcd_ccw->flags = CCW_FLAG_SLI; + + ret = s390_start_IO( irq, + rcd_ccw, + 0x00524344, // == RCD + 0, // n/a + DOIO_WAIT_FOR_INTERRUPT ); + + retry--; + + devflag = ((devstat_t *)(ioinfo[irq]->irq_desc.action->dev_id))->flag; + + } while ( ( retry ) + && ( ret || (devflag & DEVSTAT_STATUS_PENDING) ) ); + + if ( !retry ) + ret = -EBUSY; + + __restore_flags(flags); + + } /* endif */ + + /* + * on success we update the user input parms + */ + if ( !ret ) + { + *length = ioinfo[irq]->senseid.ciw[ciw_cnt].count; + *buffer = rcd_buf; + + } /* endif */ + + if ( emulated ) + free_irq( irq, &devstat); + } + else + { + ret = -EINVAL; + + } /* endif */ + + return( ret ); + +} + +int get_dev_info( int irq, dev_info_t * pdi) +{ + return( get_dev_info_by_irq( irq, pdi)); +} + +static int __inline__ get_next_available_irq( ioinfo_t *pi) +{ + int ret_val; + + while ( TRUE ) + { + if ( pi->ui.flags.oper ) + { + ret_val = pi->irq; + break; + } + else + { + pi = pi->next; + + // + // leave at end of list unconditionally + // + if ( pi == NULL ) + { + ret_val = -ENODEV; + break; + } + + } /* endif */ + + } /* endwhile */ + + return ret_val; +} + + +int get_irq_first( void ) +{ + int ret_irq; + + if ( ioinfo_head ) + { + if ( ioinfo_head->ui.flags.oper ) + { + ret_irq = ioinfo_head->irq; + } + else if ( ioinfo_head->next ) + { + ret_irq = get_next_available_irq( ioinfo_head->next ); + + } + else + { + ret_irq = -ENODEV; + + } /* endif */ + } + else + { + ret_irq = -ENODEV; + + } /* endif */ + + return ret_irq; +} + +int get_irq_next( int irq ) +{ + int ret_irq; + + if ( ioinfo[irq] != INVALID_STORAGE_AREA ) + { + if ( ioinfo[irq]->next ) + { + if ( ioinfo[irq]->next->ui.flags.oper ) + { + ret_irq = ioinfo[irq]->next->irq; + } + else + { + ret_irq = get_next_available_irq( ioinfo[irq]->next ); + + } /* endif */ + } + else + { + ret_irq = -ENODEV; + + } /* endif */ + } + else + { + ret_irq = -EINVAL; + + } /* endif */ + + return ret_irq; +} + +int get_dev_info_by_irq( int irq, dev_info_t *pdi) +{ + + if ( irq > highest_subchannel || irq < 0 ) + { + return -ENODEV; + } + else if ( pdi == NULL ) + { + return -EINVAL; + } + else if ( ioinfo[irq] == INVALID_STORAGE_AREA ) + { + return( -ENODEV); + } + else + { + pdi->devno = ioinfo[irq]->schib.pmcw.dev; + pdi->irq = irq; + + if ( ioinfo[irq]->ui.flags.oper ) + { + pdi->status = 0; + memcpy( &(pdi->sid_data), + &ioinfo[irq]->senseid, + sizeof( senseid_t)); + } + else + { + pdi->status = DEVSTAT_NOT_OPER; + memcpy( &(pdi->sid_data), + '\0', + sizeof( senseid_t)); + pdi->sid_data.cu_type = 0xFFFF; + + } /* endif */ + + if ( ioinfo[irq]->ui.flags.ready ) + pdi->status |= DEVSTAT_DEVICE_OWNED; + + return 0; + + } /* endif */ + +} + + +int get_dev_info_by_devno( __u16 devno, dev_info_t *pdi) +{ + int i; + int rc = -ENODEV; + + if ( devno > 0x0000ffff ) + { + return -ENODEV; + } + else if ( pdi == NULL ) + { + return -EINVAL; + } + else + { + + for ( i=0; i <= highest_subchannel; i++ ) + { + + if ( ioinfo[i] != INVALID_STORAGE_AREA + && ioinfo[i]->schib.pmcw.dev == devno ) + { + if ( ioinfo[i]->ui.flags.oper ) + { + pdi->status = 0; + pdi->irq = i; + pdi->devno = devno; + + memcpy( &(pdi->sid_data), + &ioinfo[i]->senseid, + sizeof( senseid_t)); + } + else + { + pdi->status = DEVSTAT_NOT_OPER; + pdi->irq = i; + pdi->devno = devno; + + memcpy( &(pdi->sid_data), '\0', sizeof( senseid_t)); + pdi->sid_data.cu_type = 0xFFFF; + + } /* endif */ + + if ( ioinfo[i]->ui.flags.ready ) + pdi->status |= DEVSTAT_DEVICE_OWNED; + + rc = 0; /* found */ + break; + + } /* endif */ + + } /* endfor */ + + return( rc); + + } /* endif */ + +} + +int get_irq_by_devno( __u16 devno ) +{ + int i; + int rc = -1; + + if ( devno <= 0x0000ffff ) + { + for ( i=0; i <= highest_subchannel; i++ ) + { + if ( (ioinfo[i] != INVALID_STORAGE_AREA ) + && (ioinfo[i]->schib.pmcw.dev == devno) + && (ioinfo[i]->schib.pmcw.dnv == 1 ) ) + { + rc = i; + break; + + } /* endif */ + + } /* endfor */ + + } /* endif */ + + return( rc); +} + +unsigned int get_devno_by_irq( int irq ) +{ + + if ( ( irq > highest_subchannel ) + || ( irq < 0 ) + || ( ioinfo[irq] == INVALID_STORAGE_AREA ) ) + { + return -1; + + } /* endif */ + + /* + * we don't need to check for the device be operational + * as the initial STSCH will always present the device + * number defined by the IOCDS regardless of the device + * existing or not. However, there could be subchannels + * defined who's device number isn't valid ... + */ + if ( ioinfo[irq]->schib.pmcw.dnv ) + return( ioinfo[irq]->schib.pmcw.dev ); + else + return -1; +} + +/* + * s390_device_recognition + * + * Used for system wide device recognition. Issues the device + * independant SenseID command to obtain info the device type. + * + */ +void s390_device_recognition( void) +{ + + int irq = 0; /* let's start with subchannel 0 ... */ + + do + { + /* + * We issue the SenseID command on I/O subchannels we think are + * operational only. + */ + if ( ( ioinfo[irq] != INVALID_STORAGE_AREA ) + && ( ioinfo[irq]->schib.pmcw.st == 0 ) + && ( ioinfo[irq]->ui.flags.oper == 1 ) ) + { + s390_SenseID( irq, &ioinfo[irq]->senseid ); + + } /* endif */ + + irq ++; + + } while ( irq <= highest_subchannel ); + +} + + +/* + * s390_search_devices + * + * Determines all subchannels available to the system. + * + */ +void s390_process_subchannels( void) +{ + int isValid; + int irq = 0; /* Evaluate all subchannels starting with 0 ... */ + + do + { + isValid = s390_validate_subchannel( irq); + + irq++; + + } while ( isValid && irq < __MAX_SUBCHANNELS ); + + highest_subchannel = --irq; + + printk( "\nHighest subchannel number detected: %u\n", + highest_subchannel); +} + +/* + * s390_validate_subchannel() + * + * Process the subchannel for the requested irq. Returns 1 for valid + * subchannels, otherwise 0. + */ +int s390_validate_subchannel( int irq ) +{ + + int retry; /* retry count for status pending conditions */ + int ccode; /* condition code for stsch() only */ + int ccode2; /* condition code for other I/O routines */ + schib_t *p_schib; + + /* + * The first subchannel that is not-operational (ccode==3) + * indicates that there aren't any more devices available. + */ + if ( ( init_IRQ_complete ) + && ( ioinfo[irq] != INVALID_STORAGE_AREA ) ) + { + p_schib = &ioinfo[irq]->schib; + } + else + { + p_schib = &init_schib; + + } /* endif */ + + ccode = stsch( irq, p_schib); + + if ( ccode == 0) + { + /* + * ... just being curious we check for non I/O subchannels + */ + if ( p_schib->pmcw.st ) + { + printk( "Subchannel %04X reports " + "non-I/O subchannel type %04X\n", + irq, + p_schib->pmcw.st); + + if ( ioinfo[irq] != INVALID_STORAGE_AREA ) + ioinfo[irq]->ui.flags.oper = 0; + + } /* endif */ + + if ( p_schib->pmcw.dnv ) + { + if ( ioinfo[irq] == INVALID_STORAGE_AREA ) + { + + if ( !init_IRQ_complete ) + { + ioinfo[irq] = + (ioinfo_t *)alloc_bootmem( sizeof(ioinfo_t)); + } + else + { + ioinfo[irq] = + (ioinfo_t *)kmalloc( sizeof(ioinfo_t), + GFP_KERNEL ); + + } /* endif */ + + memset( ioinfo[irq], '\0', sizeof( ioinfo_t)); + memcpy( &ioinfo[irq]->schib, + &init_schib, + sizeof( schib_t)); + ioinfo[irq]->irq_desc.status = IRQ_DISABLED; + ioinfo[irq]->irq_desc.handler = &no_irq_type; + + /* + * We have to insert the new ioinfo element + * into the linked list, either at its head, + * its tail or insert it. + */ + if ( ioinfo_head == NULL ) /* first element */ + { + ioinfo_head = ioinfo[irq]; + ioinfo_tail = ioinfo[irq]; + } + else if ( irq < ioinfo_head->irq ) /* new head */ + { + ioinfo[irq]->next = ioinfo_head; + ioinfo_head->prev = ioinfo[irq]; + ioinfo_head = ioinfo[irq]; + } + else if ( irq > ioinfo_tail->irq ) /* new tail */ + { + ioinfo_tail->next = ioinfo[irq]; + ioinfo[irq]->prev = ioinfo_tail; + ioinfo_tail = ioinfo[irq]; + } + else /* insert element */ + { + ioinfo_t *pi = ioinfo_head; + + do + { + if ( irq < pi->next->irq ) + { + ioinfo[irq]->next = pi->next; + ioinfo[irq]->prev = pi; + pi->next->prev = ioinfo[irq]; + pi->next = ioinfo[irq]; + break; + + } /* endif */ + + pi = pi->next; + + } while ( 1 ); + + } /* endif */ + + } /* endif */ + + // initialize some values ... + ioinfo[irq]->ui.flags.pgid_supp = 1; + + ioinfo[irq]->opm = ioinfo[irq]->schib.pmcw.pam + & ioinfo[irq]->schib.pmcw.pom; + + printk( "Detected device %04X on subchannel %04X" + " - PIM = %02X, PAM = %02X, POM = %02X\n", + ioinfo[irq]->schib.pmcw.dev, + irq, + ioinfo[irq]->schib.pmcw.pim, + ioinfo[irq]->schib.pmcw.pam, + ioinfo[irq]->schib.pmcw.pom); + + /* + * We should have at least one CHPID ... + */ + if ( ioinfo[irq]->schib.pmcw.pim + & ioinfo[irq]->schib.pmcw.pam + & ioinfo[irq]->schib.pmcw.pom ) + { + ioinfo[irq]->ui.flags.oper = 0; + + /* + * We now have to initially ... + * ... set "interruption sublass" + * ... enable "concurrent sense" + * ... enable "multipath mode" if more than one + * CHPID is available. This is done regardless + * whether multiple paths are available for us. + * + * Note : we don't enable the device here, this is temporarily + * done during device sensing below. + */ + ioinfo[irq]->schib.pmcw.isc = 3; /* could be smth. else */ + ioinfo[irq]->schib.pmcw.csense = 1; /* concurrent sense */ + ioinfo[irq]->schib.pmcw.ena = 0; /* force disable it */ + ioinfo[irq]->schib.pmcw.intparm = + ioinfo[irq]->schib.pmcw.dev; + + if ( ( ioinfo[irq]->schib.pmcw.pim != 0 ) + && ( ioinfo[irq]->schib.pmcw.pim != 0x80 ) ) + { + ioinfo[irq]->schib.pmcw.mp = 1; /* multipath mode */ + + } /* endif */ + + /* + * initialize ioinfo structure + */ + ioinfo[irq]->irq = irq; + ioinfo[irq]->ui.flags.busy = 0; + ioinfo[irq]->ui.flags.ready = 0; + ioinfo[irq]->ui.flags.oper = 1; + ioinfo[irq]->devstat.intparm = 0; + ioinfo[irq]->devstat.devno = ioinfo[irq]->schib.pmcw.dev; + + retry = 5; + + do + { + ccode2 = msch_err( irq, &ioinfo[irq]->schib); + + switch (ccode2) { + case 0: // successful completion + // + // concurrent sense facility available ... + // + ioinfo[irq]->ui.flags.consns = 1; + break; + + case 1: // status pending + // + // How can we have a pending status as device is + // disabled for interrupts ? Anyway, clear it ... + // + tsch( irq, &(ioinfo[irq]->devstat.ii.irb) ); + retry--; + break; + + case 2: // busy + retry--; + break; + + case 3: // not operational + ioinfo[irq]->ui.flags.oper = 0; + retry = 0; + break; + + default: +#define PGMCHK_OPERAND_EXC 0x15 + + if ( (ccode2 & PGMCHK_OPERAND_EXC) == PGMCHK_OPERAND_EXC ) + { + /* + * re-issue the modify subchannel without trying to + * enable the concurrent sense facility + */ + ioinfo[irq]->schib.pmcw.csense = 0; + + ccode2 = msch_err( irq, &ioinfo[irq]->schib); + + if ( ccode2 != 0 ) + { + printk( " ... modify subchannel (2) failed with CC = %X\n", + ccode2 ); + ioinfo[irq]->ui.flags.oper = 0; + } + else + { + ioinfo[irq]->ui.flags.consns = 0; + + } /* endif */ + } + else + { + printk( " ... modify subchannel (1) failed with CC = %X\n", + ccode2); + ioinfo[irq]->ui.flags.oper = 0; + + } /* endif */ + + retry = 0; + break; + + } /* endswitch */ + + } while ( ccode2 && retry ); + + if ( (ccode2 < 3) && (!retry) ) + { + printk( " ... msch() retry count for " + "subchannel %04X exceeded, CC = %d\n", + irq, + ccode2); + + } /* endif */ + + } + else + { + ioinfo[irq]->ui.flags.oper = 0; + + } /* endif */ + + } /* endif */ + + } /* endif */ + + /* + * indicate whether the subchannel is valid + */ + if ( ccode == 3) + return(0); + else + return(1); +} + +/* + * s390_SenseID + * + * Try to obtain the 'control unit'/'device type' information + * associated with the subchannel. + * + * The function is primarily meant to be called without irq + * action handler in place. However, it also allows for + * use with an action handler in place. If there is already + * an action handler registered assure it can handle the + * s390_SenseID() related device interrupts - interruption + * parameter used is 0x00E2C9C4 ( SID ). + */ +int s390_SenseID( int irq, senseid_t *sid ) +{ + ccw1_t sense_ccw; /* ccw area for SenseID command */ + devstat_t devstat; /* required by request_irq() */ + + int irq_ret = 0; /* return code */ + int retry = 5; /* retry count */ + int inlreq = 0; /* inline request_irq() */ + + if ( (irq > highest_subchannel) || (irq < 0 ) ) + { + return( -ENODEV ); + + } + else if ( ioinfo[irq] == INVALID_STORAGE_AREA ) + { + return( -ENODEV); + } /* endif */ + + if ( ioinfo[irq]->ui.flags.oper == 0 ) + { + return( -ENODEV ); + + } /* endif */ + + if ( !ioinfo[irq]->ui.flags.ready ) + { + /* + * Perform SENSE ID command processing. We have to request device + * ownership and provide a dummy I/O handler. We issue sync. I/O + * requests and evaluate the devstat area on return therefore + * we don't need a real I/O handler in place. + */ + irq_ret = request_irq( irq, init_IRQ_handler, 0, "SID", &devstat); + + if ( irq_ret == 0 ) + inlreq = 1; + + } /* endif */ + + if ( irq_ret == 0 ) + { + s390irq_spin_lock( irq); + + sense_ccw.cmd_code = CCW_CMD_SENSE_ID; + sense_ccw.cda = (__u32)virt_to_phys( sid ); + sense_ccw.count = sizeof( senseid_t); + sense_ccw.flags = CCW_FLAG_SLI; + + ioinfo[irq]->senseid.cu_type = 0xFFFF; /* initialize fields ... */ + ioinfo[irq]->senseid.cu_model = 0; + ioinfo[irq]->senseid.dev_type = 0; + ioinfo[irq]->senseid.dev_model = 0; + + /* + * We now issue a SenseID request. In case of BUSY + * or STATUS PENDING conditions we retry 5 times. + */ + do + { + memset( &devstat, '\0', sizeof( devstat_t) ); + + irq_ret = s390_start_IO( irq, + &sense_ccw, + 0x00E2C9C4, // == SID + 0, // n/a + DOIO_WAIT_FOR_INTERRUPT + | DOIO_TIMEOUT ); + + if ( irq_ret == -ETIMEDOUT ) + { + halt_IO( irq, + 0x80E2C9C4, + DOIO_WAIT_FOR_INTERRUPT); + devstat.flag |= DEVSTAT_NOT_OPER; + + } /* endif */ + + if ( sid->cu_type == 0xFFFF && devstat.flag != DEVSTAT_NOT_OPER ) + { + if ( devstat.flag & DEVSTAT_STATUS_PENDING ) + { +#if CONFIG_DEBUG_IO + printk( "Device %04X on Subchannel %04X " + "reports pending status, retry : %d\n", + ioinfo[irq]->schib.pmcw.dev, + irq, + retry); +#endif + } /* endif */ + + if ( devstat.flag & DEVSTAT_FLAG_SENSE_AVAIL ) + { + /* + * if the device doesn't support the SenseID + * command further retries wouldn't help ... + */ + if ( devstat.ii.sense.data[0] & SNS0_CMD_REJECT ) + { + retry = 0; + } +#if CONFIG_DEBUG_IO + else + { + printk( "Device %04X," + " UC/SenseID," + " retry %d, cnt %02d," + " sns :" + " %02X%02X%02X%02X %02X%02X%02X%02X ...\n", + ioinfo[irq]->schib.pmcw.dev, + retry, + devstat.scnt, + devstat.ii.sense.data[0], + devstat.ii.sense.data[1], + devstat.ii.sense.data[2], + devstat.ii.sense.data[3], + devstat.ii.sense.data[4], + devstat.ii.sense.data[5], + devstat.ii.sense.data[6], + devstat.ii.sense.data[7]); + + } /* endif */ +#endif + } + else if ( devstat.flag & DEVSTAT_NOT_OPER ) + { + printk( "Device %04X on Subchannel %04X " + "became 'not operational'\n", + ioinfo[irq]->schib.pmcw.dev, + irq); + + retry = 0; + + } /* endif */ + } + else // we got it or the device is not-operational ... + { + retry = 0; + + } /* endif */ + + retry--; + + } while ( retry > 0 ); + + s390irq_spin_unlock( irq); + + /* + * If we installed the irq action handler we have to + * release it too. + */ + if ( inlreq ) + free_irq( irq, &devstat); + + /* + * if running under VM check there ... perhaps we should do + * only if we suffered a command reject, but it doesn't harm + */ + if ( ( sid->cu_type == 0xFFFF ) + && ( MACHINE_IS_VM ) ) + { + VM_virtual_device_info( ioinfo[irq]->schib.pmcw.dev, + sid ); + } /* endif */ + + if ( sid->cu_type == 0xFFFF ) + { + /* + * SenseID CU-type of 0xffff indicates that no device + * information could be retrieved (pre-init value). + * + * If we can't couldn't identify the device type we + * consider the device "not operational". + */ + printk( "Unknown device %04X on subchannel %04X\n", + ioinfo[irq]->schib.pmcw.dev, + irq); + ioinfo[irq]->ui.flags.oper = 0; + + } /* endif */ + + /* + * Issue device info message if unit was operational . + */ + if ( ioinfo[irq]->ui.flags.oper ) + { + if ( sid->dev_type != 0 ) + { + printk( "Device %04X reports: CU Type/Mod = %04X/%02X," + " Dev Type/Mod = %04X/%02X\n", + ioinfo[irq]->schib.pmcw.dev, + sid->cu_type, + sid->cu_model, + sid->dev_type, + sid->dev_model); + } + else + { + printk( "Device %04X reports:" + " Dev Type/Mod = %04X/%02X\n", + ioinfo[irq]->schib.pmcw.dev, + sid->cu_type, + sid->cu_model); + + } /* endif */ + + } /* endif */ + + if ( ioinfo[irq]->ui.flags.oper ) + irq_ret = 0; + else + irq_ret = -ENODEV; + + } /* endif */ + + return( irq_ret ); +} + +static int __inline__ s390_SetMultiPath( int irq ) +{ + int cc; + + cc = stsch( irq, &ioinfo[irq]->schib ); + + if ( !cc ) + { + ioinfo[irq]->schib.pmcw.mp = 1; /* multipath mode */ + + cc = msch( irq, &ioinfo[irq]->schib ); + + } /* endif */ + + return( cc); +} + +/* + * Device Path Verification + * + * Path verification is accomplished by checking which paths (CHPIDs) are + * available. Further, a path group ID is set, if possible in multipath + * mode, otherwise in single path mode. + * + */ +int s390_DevicePathVerification( int irq ) +{ +#if 0 + int ccode; + __u8 pathmask; + + int ret = 0; + + if ( ioinfo[irq]->ui.flags.pgid_supp == 0 ) + { + ret = -EOPNOTSUPP; + + } /* endif */ + + ccode = stsch( irq, &(ioinfo[irq]->schib) ); + + if ( ccode ) + { + ret = -ENODEV; + } + else + { + int i; + pgid_t pgid; + + int first = 1; + __u8 dev_path = ioinfo[irq]->schib.pmcw.pam + & ioinfo[irq]->schib.pmcw.pom; + + /* + * let's build a path group ID if we don't have one yet + */ + if ( ioinfo[irq]->ui.flags.pgid == 0) + { + struct _lowcore *lowcore = &get_cpu_lowcore(cpu); + + ioinfo->pgid.cpu_addr = lowcore->cpu_data.cpu_addr; + ioinfo->pgid.cpu_id = lowcore->cpu_data.cpu_id.ident; + ioinfo->pgid.cpu_model = lowcore->cpu_data.cpu_id.machine; + ioinfo->pgid.tod_high = *(__u32 *)&irq_IPL_TOD; + + ioinfo[irq]->ui.flags.pgid = 1; + + } /* endif */ + + memcpy( &pgid, ioinfo[irq]->pgid, sizeof(pgid_t)); + + for ( i = 0; i < 8 && !ret ; i++) + { + pathmask = 0x80 >> i; + + if ( dev_path & pathmask ) + { + ret = s390_SetPGID( irq, pathmask, &pgid ); + + /* + * For the *first* path we are prepared + * for recovery + * + * - If we fail setting the PGID we assume its + * using a different PGID already (VM) we + * try to sense. + */ + if ( ret == -EOPNOTSUPP && first ) + { + *(int *)&pgid = 0; + + ret = s390_SensePGID( irq, pathmask, &pgid); + first = 0; + + if ( !ret ) + { + /* + * Check whether we retrieved + * a reasonable PGID ... + */ + if ( !ret && (*(int *)&pgid == 0) ) + { + ret = -EOPNOTSUPP; + } + else + { + ret = s390_SetPGID( irq, pathmask, &pgid ); + + } /* endif */ + + } /* endif */ + + if ( ret ) + { + ioinfo[irq]->ui.flags.pgid_supp = 0; + + printk( "PathVerification(%04X) " + "- Device %04X doesn't " + " support path grouping", + irq, + ioinfo[irq]->schib.pmcw.dev); + + } /* endif */ + } + else if ( ret ) + { + ioinfo[irq]->ui.flags.pgid_supp = 0; + + } /* endif */ + + } /* endif */ + + } /* endfor */ + + } /* endif */ + + return ret; +#else + return 0; +#endif +} + +/* + * s390_SetPGID + * + * Set Path Group ID + * + */ +int s390_SetPGID( int irq, __u8 lpm, pgid_t *pgid ) +{ + ccw1_t spid_ccw; /* ccw area for SPID command */ + devstat_t devstat; /* required by request_irq() */ + + int irq_ret = 0; /* return code */ + int retry = 5; /* retry count */ + int inlreq = 0; /* inline request_irq() */ + int mpath = 1; /* try multi-path first */ + + if ( (irq > highest_subchannel) || (irq < 0 ) ) + { + return( -ENODEV ); + + } + else if ( ioinfo[irq] == INVALID_STORAGE_AREA ) + { + return( -ENODEV); + + } /* endif */ + + if ( ioinfo[irq]->ui.flags.oper == 0 ) + { + return( -ENODEV ); + + } /* endif */ + + if ( !ioinfo[irq]->ui.flags.ready ) + { + /* + * Perform SENSE ID command processing. We have to request device + * ownership and provide a dummy I/O handler. We issue sync. I/O + * requests and evaluate the devstat area on return therefore + * we don't need a real I/O handler in place. + */ + irq_ret = request_irq( irq, init_IRQ_handler, 0, "SPID", &devstat); + + if ( irq_ret == 0 ) + inlreq = 1; + + } /* endif */ + + if ( irq_ret == 0 ) + { + s390irq_spin_lock( irq); + + spid_ccw.cmd_code = CCW_CMD_SET_PGID; + spid_ccw.cda = (__u32)virt_to_phys( pgid ); + spid_ccw.count = sizeof( pgid_t); + spid_ccw.flags = CCW_FLAG_SLI; + + + /* + * We now issue a SenseID request. In case of BUSY + * or STATUS PENDING conditions we retry 5 times. + */ + do + { + memset( &devstat, '\0', sizeof( devstat_t) ); + + irq_ret = s390_start_IO( irq, + &spid_ccw, + 0xE2D7C9C4, // == SPID + lpm, // n/a + DOIO_WAIT_FOR_INTERRUPT + | DOIO_VALID_LPM ); + + if ( !irq_ret ) + { + if ( devstat.flag & DEVSTAT_STATUS_PENDING ) + { +#if CONFIG_DEBUG_IO + printk( "SPID - Device %04X " + "on Subchannel %04X " + "reports pending status, " + "retry : %d\n", + ioinfo[irq]->schib.pmcw.dev, + irq, + retry); +#endif + } /* endif */ + + if ( devstat.flag == ( DEVSTAT_START_FUNCTION + | DEVSTAT_FINAL_STATUS ) ) + { + retry = 0; // successfully set ... + } + else if ( devstat.flag & DEVSTAT_FLAG_SENSE_AVAIL ) + { + /* + * If the device doesn't support the + * Sense Path Group ID command + * further retries wouldn't help ... + */ + if ( devstat.ii.sense.data[0] & SNS0_CMD_REJECT ) + { + if ( mpath ) + { + pgid->inf.fc = SPID_FUNC_ESTABLISH; + mpath = 0; + retry--; + } + else + { + irq_ret = -EOPNOTSUPP; + retry = 0; + + } /* endif */ + } +#if CONFIG_DEBUG_IO + else + { + printk( "SPID - device %04X," + " unit check," + " retry %d, cnt %02d," + " sns :" + " %02X%02X%02X%02X %02X%02X%02X%02X ...\n", + ioinfo[irq]->schib.pmcw.dev, + retry, + devstat.scnt, + devstat.ii.sense.data[0], + devstat.ii.sense.data[1], + devstat.ii.sense.data[2], + devstat.ii.sense.data[3], + devstat.ii.sense.data[4], + devstat.ii.sense.data[5], + devstat.ii.sense.data[6], + devstat.ii.sense.data[7]); + + } /* endif */ +#endif + } + else if ( devstat.flag & DEVSTAT_NOT_OPER ) + { + printk( "SPID - Device %04X " + "on Subchannel %04X " + "became 'not operational'\n", + ioinfo[irq]->schib.pmcw.dev, + irq); + + retry = 0; + + } /* endif */ + } + else if ( irq_ret != -ENODEV ) + { + retry--; + } + else + { + retry = 0; + + } /* endif */ + + } while ( retry > 0 ); + + s390irq_spin_unlock( irq); + + /* + * If we installed the irq action handler we have to + * release it too. + */ + if ( inlreq ) + free_irq( irq, &devstat); + + } /* endif */ + + return( irq_ret ); +} + + +/* + * s390_SensePGID + * + * Sense Path Group ID + * + */ +int s390_SensePGID( int irq, __u8 lpm, pgid_t *pgid ) +{ + ccw1_t snid_ccw; /* ccw area for SNID command */ + devstat_t devstat; /* required by request_irq() */ + + int irq_ret = 0; /* return code */ + int retry = 5; /* retry count */ + int inlreq = 0; /* inline request_irq() */ + + if ( (irq > highest_subchannel) || (irq < 0 ) ) + { + return( -ENODEV ); + + } + else if ( ioinfo[irq] == INVALID_STORAGE_AREA ) + { + return( -ENODEV); + + } /* endif */ + + if ( ioinfo[irq]->ui.flags.oper == 0 ) + { + return( -ENODEV ); + + } /* endif */ + + if ( !ioinfo[irq]->ui.flags.ready ) + { + /* + * Perform SENSE ID command processing. We have to request device + * ownership and provide a dummy I/O handler. We issue sync. I/O + * requests and evaluate the devstat area on return therefore + * we don't need a real I/O handler in place. + */ + irq_ret = request_irq( irq, init_IRQ_handler, 0, "SNID", &devstat); + + if ( irq_ret == 0 ) + inlreq = 1; + + } /* endif */ + + if ( irq_ret == 0 ) + { + s390irq_spin_lock( irq); + + snid_ccw.cmd_code = CCW_CMD_SENSE_PGID; + snid_ccw.cda = (__u32)virt_to_phys( pgid ); + snid_ccw.count = sizeof( pgid_t); + snid_ccw.flags = CCW_FLAG_SLI; + + /* + * We now issue a SenseID request. In case of BUSY + * or STATUS PENDING conditions we retry 5 times. + */ + do + { + memset( &devstat, '\0', sizeof( devstat_t) ); + + irq_ret = s390_start_IO( irq, + &snid_ccw, + 0xE2D5C9C4, // == SNID + lpm, // n/a + DOIO_WAIT_FOR_INTERRUPT + | DOIO_VALID_LPM ); + + if ( !irq_ret ) + { + if ( devstat.flag & DEVSTAT_STATUS_PENDING ) + { +#if CONFIG_DEBUG_IO + printk( "SNID - Device %04X " + "on Subchannel %04X " + "reports pending status, " + "retry : %d\n", + ioinfo[irq]->schib.pmcw.dev, + irq, + retry); +#endif + } /* endif */ + + if ( devstat.flag & DEVSTAT_FLAG_SENSE_AVAIL ) + { + /* + * If the device doesn't support the + * Sense Path Group ID command + * further retries wouldn't help ... + */ + if ( devstat.ii.sense.data[0] & SNS0_CMD_REJECT ) + { + retry = 0; + irq_ret = -EOPNOTSUPP; + } +#if CONFIG_DEBUG_IO + else + { + printk( "SNID - device %04X," + " unit check," + " retry %d, cnt %02d," + " sns :" + " %02X%02X%02X%02X %02X%02X%02X%02X ...\n", + ioinfo[irq]->schib.pmcw.dev, + retry, + devstat.scnt, + devstat.ii.sense.data[0], + devstat.ii.sense.data[1], + devstat.ii.sense.data[2], + devstat.ii.sense.data[3], + devstat.ii.sense.data[4], + devstat.ii.sense.data[5], + devstat.ii.sense.data[6], + devstat.ii.sense.data[7]); + + } /* endif */ +#endif + } + else if ( devstat.flag & DEVSTAT_NOT_OPER ) + { + printk( "SNID - Device %04X " + "on Subchannel %04X " + "became 'not operational'\n", + ioinfo[irq]->schib.pmcw.dev, + irq); + + retry = 0; + + } /* endif */ + } + else if ( irq_ret != -ENODEV ) + { + retry--; + } + else + { + retry = 0; + + } /* endif */ + + } while ( retry > 0 ); + + s390irq_spin_unlock( irq); + + /* + * If we installed the irq action handler we have to + * release it too. + */ + if ( inlreq ) + free_irq( irq, &devstat); + + } /* endif */ + + return( irq_ret ); +} + + +void do_crw_pending( void ) +{ + return; +} + + +/* added by Holger Smolinski for reipl support in reipl.S */ +void +reipl ( int sch ) +{ + int i; + + for ( i = 0; i < highest_subchannel; i ++ ) { + free_irq ( i, (void*)REIPL_DEVID_MAGIC ); + } + do_reipl( 0x10000 | sch ); +} + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/s390mach.c linux/arch/s390/kernel/s390mach.c --- v2.3.99-pre7/linux/arch/s390/kernel/s390mach.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/s390mach.c Fri May 12 11:41:45 2000 @@ -0,0 +1,157 @@ +/* + * arch/s390/kernel/s390mach.c + * S/390 machine check handler, + * currently only channel-reports are supported + * + * S390 version + * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Ingo Adlung (adlung@de.ibm.com) + */ + +#include + +#include +#include +#include +#include +#include +#include + +#define S390_MACHCHK_DEBUG + +static mchchk_queue_element_t *mchchk_queue_head = NULL; +static mchchk_queue_element_t *mchchk_queue_tail = NULL; +static mchchk_queue_element_t *mchchk_queue_free = NULL; +static spinlock_t mchchk_queue_lock; +static struct semaphore s_sem[2]; + +// +// initialize machine check handling +// +void s390_init_machine_check( void ) +{ + init_MUTEX_LOCKED( &s_sem[0] ); + init_MUTEX_LOCKED( &s_sem[1] ); + +#if 0 + // + // fix me ! initialize a machine check queue with 100 elements + // +#ifdef S390_MACHCHK_DEBUG + printk( "init_mach : starting kernel thread\n"); +#endif + + kernel_thread( s390_machine_check_handler, s_sem, 0); + + // + // wait for the machine check handler to be ready + // +#ifdef S390_MACHCHK_DEBUG + printk( "init_mach : waiting for kernel thread\n"); +#endif + + down( &sem[0]); + +#ifdef S390_MACHCHK_DEBUG + printk( "init_mach : kernel thread ready\n"); +#endif + + // + // fix me ! we have to initialize CR14 to allow for CRW pending + // conditions + + // + // fix me ! enable machine checks in the PSW + // +#endif + return; +} + +// +// machine check pre-processor +// +void __init s390_do_machine_check( void ) +{ + // fix me ! we have to check for machine check and + // post the handler eventually + + return; +} + +// +// machine check handler +// +static void __init s390_machine_check_handler( struct semaphore *sem ) +{ +#ifdef S390_MACHCHK_DEBUG + printk( "mach_handler : kernel thread up\n"); +#endif + + up( &sem[0] ); + +#ifdef S390_MACHCHK_DEBUG + printk( "mach_handler : kernel thread ready\n"); +#endif + + do { + +#ifdef S390_MACHCHK_DEBUG + printk( "mach_handler : waiting for wakeup\n"); +#endif + + down_interruptible( &sem[1] ); +#ifdef S390_MACHCHK_DEBUG + printk( "mach_handler : wakeup\n"); +#endif + + break; // fix me ! unconditional surrender ... + + // fix me ! check for machine checks and + // call do_crw_pending() eventually + + } while (1); + + return; +} + +mchchk_queue_element_t *s390_get_mchchk( void ) +{ + unsigned long flags; + mchchk_queue_element_t *qe; + + spin_lock_irqsave( &mchchk_queue_lock, flags ); + + // fix me ! dequeue first element if available + qe = NULL; + + spin_unlock_irqrestore( &mchchk_queue_lock, flags ); + + return qe; +} + +void s390_free_mchchk( mchchk_queue_element_t *mchchk ) +{ + unsigned long flags; + + if ( mchchk != NULL) + { + spin_lock_irqsave( &mchchk_queue_lock, flags ); + + mchchk->next = mchchk_queue_free; + + if ( mchchk_queue_free != NULL ) + { + mchchk_queue_free->prev = mchchk; + + } /* endif */ + + mchchk->prev = NULL; + mchchk_queue_free = mchchk; + + spin_unlock_irqrestore( &mchchk_queue_lock, flags ); + + } /* endif */ + + return; +} + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/semaphore.c linux/arch/s390/kernel/semaphore.c --- v2.3.99-pre7/linux/arch/s390/kernel/semaphore.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/semaphore.c Fri May 12 11:41:45 2000 @@ -0,0 +1,302 @@ +/* + * linux/arch/S390/kernel/semaphore.c + * + * S390 version + * Copyright (C) 1998 IBM Corporation + * Author(s): Martin Schwidefsky + * + * Derived from "linux/arch/i386/kernel/semaphore.c + * Copyright (C) 1999, Linus Torvalds + * + */ +#include + +#include + +/* + * Semaphores are implemented using a two-way counter: + * The "count" variable is decremented for each process + * that tries to aquire the semaphore, while the "sleeping" + * variable is a count of such aquires. + * + * Notably, the inline "up()" and "down()" functions can + * efficiently test if they need to do any extra work (up + * needs to do something only if count was negative before + * the increment operation. + * + * "sleeping" and the contention routine ordering is + * protected by the semaphore spinlock. + * + * Note that these functions are only called when there is + * contention on the lock, and as such all this is the + * "non-critical" part of the whole semaphore business. The + * critical part is the inline stuff in + * where we want to avoid any extra jumps and calls. + */ + +/* + * Logic: + * - only on a boundary condition do we need to care. When we go + * from a negative count to a non-negative, we wake people up. + * - when we go from a non-negative count to a negative do we + * (a) synchronize with the "sleeper" count and (b) make sure + * that we're on the wakeup list before we synchronize so that + * we cannot lose wakeup events. + */ + +void __up(struct semaphore *sem) +{ + wake_up(&sem->wait); +} + +static spinlock_t semaphore_lock = SPIN_LOCK_UNLOCKED; + +void __down(struct semaphore * sem) +{ + struct task_struct *tsk = current; + DECLARE_WAITQUEUE(wait, tsk); + tsk->state = TASK_UNINTERRUPTIBLE|TASK_EXCLUSIVE; + add_wait_queue_exclusive(&sem->wait, &wait); + + spin_lock_irq(&semaphore_lock); + sem->sleepers++; + for (;;) { + int sleepers = sem->sleepers; + + /* + * Add "everybody else" into it. They aren't + * playing, because we own the spinlock. + */ + if (!atomic_add_negative(sleepers - 1, &sem->count)) { + sem->sleepers = 0; + break; + } + sem->sleepers = 1; /* us - see -1 above */ + spin_unlock_irq(&semaphore_lock); + + schedule(); + tsk->state = TASK_UNINTERRUPTIBLE|TASK_EXCLUSIVE; + spin_lock_irq(&semaphore_lock); + } + spin_unlock_irq(&semaphore_lock); + remove_wait_queue(&sem->wait, &wait); + tsk->state = TASK_RUNNING; + wake_up(&sem->wait); +} + +int __down_interruptible(struct semaphore * sem) +{ + int retval = 0; + struct task_struct *tsk = current; + DECLARE_WAITQUEUE(wait, tsk); + tsk->state = TASK_INTERRUPTIBLE|TASK_EXCLUSIVE; + add_wait_queue_exclusive(&sem->wait, &wait); + + spin_lock_irq(&semaphore_lock); + sem->sleepers ++; + for (;;) { + int sleepers = sem->sleepers; + + /* + * With signals pending, this turns into + * the trylock failure case - we won't be + * sleeping, and we* can't get the lock as + * it has contention. Just correct the count + * and exit. + */ + if (signal_pending(current)) { + retval = -EINTR; + sem->sleepers = 0; + atomic_add(sleepers, &sem->count); + break; + } + + /* + * Add "everybody else" into it. They aren't + * playing, because we own the spinlock. The + * "-1" is because we're still hoping to get + * the lock. + */ + if (!atomic_add_negative(sleepers - 1, &sem->count)) { + sem->sleepers = 0; + break; + } + sem->sleepers = 1; /* us - see -1 above */ + spin_unlock_irq(&semaphore_lock); + + schedule(); + tsk->state = TASK_INTERRUPTIBLE|TASK_EXCLUSIVE; + spin_lock_irq(&semaphore_lock); + } + spin_unlock_irq(&semaphore_lock); + tsk->state = TASK_RUNNING; + remove_wait_queue(&sem->wait, &wait); + wake_up(&sem->wait); + return retval; +} + +/* + * Trylock failed - make sure we correct for + * having decremented the count. + */ +int __down_trylock(struct semaphore * sem) +{ + unsigned long flags; + int sleepers; + + spin_lock_irqsave(&semaphore_lock, flags); + sleepers = sem->sleepers + 1; + sem->sleepers = 0; + + /* + * Add "everybody else" and us into it. They aren't + * playing, because we own the spinlock. + */ + if (!atomic_add_negative(sleepers, &sem->count)) + wake_up(&sem->wait); + + spin_unlock_irqrestore(&semaphore_lock, flags); + return 1; +} + +void down_read_failed_biased(struct rw_semaphore *sem) +{ + struct task_struct *tsk = current; + DECLARE_WAITQUEUE(wait, tsk); + + add_wait_queue(&sem->wait, &wait); /* put ourselves at the head of the list */ + + for (;;) { + if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0)) + break; + set_task_state(tsk, TASK_UNINTERRUPTIBLE); + if (!sem->read_bias_granted) + schedule(); + } + + remove_wait_queue(&sem->wait, &wait); + tsk->state = TASK_RUNNING; +} + +void down_write_failed_biased(struct rw_semaphore *sem) +{ + struct task_struct *tsk = current; + DECLARE_WAITQUEUE(wait, tsk); + + add_wait_queue_exclusive(&sem->write_bias_wait, &wait); /* put ourselves at the end of the list */ + + for (;;) { + if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0)) + break; + set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); + if (!sem->write_bias_granted) + schedule(); + } + + remove_wait_queue(&sem->write_bias_wait, &wait); + tsk->state = TASK_RUNNING; + + /* if the lock is currently unbiased, awaken the sleepers + * FIXME: this wakes up the readers early in a bit of a + * stampede -> bad! + */ + if (atomic_read(&sem->count) >= 0) + wake_up(&sem->wait); +} + +/* Wait for the lock to become unbiased. Readers + * are non-exclusive. =) + */ +void down_read_failed(struct rw_semaphore *sem) +{ + struct task_struct *tsk = current; + DECLARE_WAITQUEUE(wait, tsk); + + up_read(sem); /* this takes care of granting the lock */ + + add_wait_queue(&sem->wait, &wait); + + while (atomic_read(&sem->count) < 0) { + set_task_state(tsk, TASK_UNINTERRUPTIBLE); + if (atomic_read(&sem->count) >= 0) + break; + schedule(); + } + + remove_wait_queue(&sem->wait, &wait); + tsk->state = TASK_RUNNING; +} + +/* Wait for the lock to become unbiased. Since we're + * a writer, we'll make ourselves exclusive. + */ +void down_write_failed(struct rw_semaphore *sem) +{ + struct task_struct *tsk = current; + DECLARE_WAITQUEUE(wait, tsk); + + up_write(sem); /* this takes care of granting the lock */ + + add_wait_queue_exclusive(&sem->wait, &wait); + + while (atomic_read(&sem->count) < 0) { + set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); + if (atomic_read(&sem->count) >= 0) + break; /* we must attempt to aquire or bias the lock */ + schedule(); + } + + remove_wait_queue(&sem->wait, &wait); + tsk->state = TASK_RUNNING; +} + +/* Called when someone has done an up that transitioned from + * negative to non-negative, meaning that the lock has been + * granted to whomever owned the bias. + */ +void rwsem_wake_readers(struct rw_semaphore *sem) +{ + if (xchg(&sem->read_bias_granted, 1)) + BUG(); + wake_up(&sem->wait); +} + +void rwsem_wake_writers(struct rw_semaphore *sem) +{ + if (xchg(&sem->write_bias_granted, 1)) + BUG(); + wake_up(&sem->write_bias_wait); +} + +void __down_read_failed(int count, struct rw_semaphore *sem) +{ + do { + if (count == -1) { + down_read_failed_biased(sem); + break; + } + down_read_failed(sem); + count = atomic_dec_return(&sem->count); + } while (count != 0); +} + +void __down_write_failed(int count, struct rw_semaphore *sem) +{ + do { + if (count < 0 && count > -RW_LOCK_BIAS) { + down_write_failed_biased(sem); + break; + } + down_write_failed(sem); + count = atomic_add_return(-RW_LOCK_BIAS, &sem->count); + } while (count != 0); +} + +void __rwsem_wake(int count, struct rw_semaphore *sem) +{ + if (count == 0) + rwsem_wake_readers(sem); + else + rwsem_wake_writers(sem); +} + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/setup.c linux/arch/s390/kernel/setup.c --- v2.3.99-pre7/linux/arch/s390/kernel/setup.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/setup.c Fri May 12 11:41:45 2000 @@ -0,0 +1,385 @@ +/* + * arch/s390/kernel/setup.c + * + * S390 version + * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Hartmut Penner (hp@de.ibm.com), + * Martin Schwidefsky (schwidefsky@de.ibm.com) + * + * Derived from "arch/i386/kernel/setup.c" + * Copyright (C) 1995, Linus Torvalds + */ + +/* + * This file handles the architecture-dependent parts of initialization + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_BLK_DEV_RAM +#include +#endif +#include +#include +#include +#include +#include +#include + +/* + * Machine setup.. + */ +__u16 boot_cpu_addr; +int cpus_initialized = 0; +unsigned long cpu_initialized = 0; + +/* + * Setup options + */ + +#ifdef CONFIG_BLK_DEV_RAM +extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */ +extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt*/ +extern int rd_image_start; /* starting block # of image */ +#endif + +extern int root_mountflags; +extern int _text,_etext, _edata, _end; + + +/* + * This is set up by the setup-routine at boot-time + * for S390 need to find out, what we have to setup + * using address 0x10400 ... + */ + +#include + +static char command_line[COMMAND_LINE_SIZE] = { 0, }; + char saved_command_line[COMMAND_LINE_SIZE]; + +static struct resource code_resource = { "Kernel code", 0x100000, 0 }; +static struct resource data_resource = { "Kernel data", 0, 0 }; + +/* + * cpu_init() initializes state that is per-CPU. + */ +void __init cpu_init (void) +{ + int nr = smp_processor_id(); + + if (test_and_set_bit(nr,&cpu_initialized)) { + printk("CPU#%d ALREADY INITIALIZED!!!!!!!!!\n", nr); + for (;;) __sti(); + } + cpus_initialized++; + + /* + * Store processor id in lowcore (used e.g. in timer_interrupt) + */ + asm volatile ("stidp %0": "=m" (S390_lowcore.cpu_data.cpu_id)); + S390_lowcore.cpu_data.cpu_addr = hard_smp_processor_id(); + S390_lowcore.cpu_data.cpu_nr = nr; + + /* + * Force FPU initialization: + */ + current->flags &= ~PF_USEDFPU; + current->used_math = 0; + + /* Setup active_mm for idle_task */ + atomic_inc(&init_mm.mm_count); + current->active_mm = &init_mm; + if (current->mm) + BUG(); + enter_lazy_tlb(&init_mm, current, nr); +} + +/* + * VM halt and poweroff setup routines + */ +char vmhalt_cmd[128] = ""; +char vmpoff_cmd[128] = ""; + +static inline void strncpy_skip_quote(char *dst, char *src, int n) +{ + int sx, dx; + + dx = 0; + for (sx = 0; src[sx] != 0; sx++) { + if (src[sx] == '"') continue; + dst[dx++] = src[sx]; + if (dx >= n) break; + } +} + +static int __init vmhalt_setup(char *str) +{ + strncpy_skip_quote(vmhalt_cmd, str, 127); + vmhalt_cmd[127] = 0; + return 1; +} + +__setup("vmhalt=", vmhalt_setup); + +static int __init vmpoff_setup(char *str) +{ + strncpy_skip_quote(vmpoff_cmd, str, 127); + vmpoff_cmd[127] = 0; + return 1; +} + +__setup("vmpoff=", vmpoff_setup); + +/* + * Reboot, halt and power_off routines for non SMP. + */ + +#ifndef CONFIG_SMP +void machine_restart(char * __unused) +{ + reipl(S390_lowcore.ipl_device); +} + +void machine_halt(void) +{ + if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0) + cpcmd(vmhalt_cmd, NULL, 0); + disabled_wait(0); +} + +void machine_power_off(void) +{ + if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0) + cpcmd(vmpoff_cmd, NULL, 0); + disabled_wait(0); +} +#endif + +/* + * Waits for 'delay' microseconds using the tod clock + */ +void tod_wait(unsigned long delay) +{ + uint64_t start_cc, end_cc; + + if (delay == 0) + return; + asm volatile ("STCK %0" : "=m" (start_cc)); + do { + asm volatile ("STCK %0" : "=m" (end_cc)); + } while (((end_cc - start_cc)/4096) < delay); +} + +/* + * Setup function called from init/main.c just after the banner + * was printed. + */ +void __init setup_arch(char **cmdline_p) +{ + unsigned long bootmap_size; + unsigned long memory_start, memory_end; + char c = ' ', *to = command_line, *from = COMMAND_LINE; + struct resource *res; + unsigned long start_pfn, end_pfn; + static unsigned int smptrap=0; + unsigned long delay = 0; + int len = 0; + + if (smptrap) + return; + smptrap=1; + + printk("Command line is: %s\n", COMMAND_LINE); + + /* + * Setup lowcore information for boot cpu + */ + cpu_init(); + boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr; + + /* + * print what head.S has found out about the machine + */ + printk((MACHINE_IS_VM) ? + "We are running under VM\n" : + "We are running native\n"); + printk((MACHINE_HAS_IEEE) ? + "This machine has an IEEE fpu\n" : + "This machine has no IEEE fpu\n"); + + ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV); +#ifdef CONFIG_BLK_DEV_RAM + rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK; + rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0); + rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0); +#endif + /* nasty stuff with PARMAREAs. we use head.S or parameterline + if (!MOUNT_ROOT_RDONLY) + root_mountflags &= ~MS_RDONLY; + */ + memory_start = (unsigned long) &_end; /* fixit if use $CODELO etc*/ + memory_end = MEMORY_SIZE; /* detected in head.s */ + init_mm.start_code = PAGE_OFFSET; + init_mm.end_code = (unsigned long) &_etext; + init_mm.end_data = (unsigned long) &_edata; + init_mm.brk = (unsigned long) &_end; + + code_resource.start = (unsigned long) &_text; + code_resource.end = (unsigned long) &_etext - 1; + data_resource.start = (unsigned long) &_etext; + data_resource.end = (unsigned long) &_edata - 1; + + /* Save unparsed command line copy for /proc/cmdline */ + memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE); + saved_command_line[COMMAND_LINE_SIZE-1] = '\0'; + + for (;;) { + /* + * "mem=XXX[kKmM]" sets memsize + */ + if (c == ' ' && strncmp(from, "mem=", 4) == 0) { + if (to != command_line) to--; + memory_end = simple_strtoul(from+4, &from, 0); + if ( *from == 'K' || *from == 'k' ) { + memory_end = memory_end << 10; + from++; + } else if ( *from == 'M' || *from == 'm' ) { + memory_end = memory_end << 20; + from++; + } + } + /* + * "ipldelay=XXX[sm]" sets ipl delay in seconds or minutes + */ + if (c == ' ' && strncmp(from, "ipldelay=", 9) == 0) { + if (to != command_line) to--; + delay = simple_strtoul(from+9, &from, 0); + if (*from == 's' || *from == 'S') { + delay = delay*1000000; + from++; + } else if (*from == 'm' || *from == 'M') { + delay = delay*60*1000000; + from++; + } + /* now wait for the requestion amount of time */ + tod_wait(delay); + } + c = *(from++); + if (!c) + break; + if (COMMAND_LINE_SIZE <= ++len) + break; + *(to++) = c; + } + *to = '\0'; + *cmdline_p = command_line; + + /* + * partially used pages are not usable - thus + * we are rounding upwards: + */ + start_pfn = (__pa(&_end) + PAGE_SIZE - 1) >> PAGE_SHIFT; + end_pfn = memory_end >> PAGE_SHIFT; + + /* + * Initialize the boot-time allocator (with low memory only): + */ + bootmap_size = init_bootmem(start_pfn, end_pfn); + + /* + * Register RAM pages with the bootmem allocator. + */ + free_bootmem(start_pfn << PAGE_SHIFT, + (end_pfn - start_pfn) << PAGE_SHIFT); + + /* + * Reserve the bootmem bitmap itself as well. We do this in two + * steps (first step was init_bootmem()) because this catches + * the (very unlikely) case of us accidentally initializing the + * bootmem allocator with an invalid RAM area. + */ + reserve_bootmem(start_pfn << PAGE_SHIFT, bootmap_size); + + paging_init(); +#ifdef CONFIG_BLK_DEV_INITRD + if (INITRD_START) { + if (INITRD_START + INITRD_SIZE < memory_end) { + reserve_bootmem(INITRD_START, INITRD_SIZE); + initrd_start = INITRD_START; + initrd_end = initrd_start + INITRD_SIZE; + } else { + printk("initrd extends beyond end of memory " + "(0x%08lx > 0x%08lx)\ndisabling initrd\n", + initrd_start + INITRD_SIZE, memory_end); + initrd_start = initrd_end = 0; + } + } +#endif + res = alloc_bootmem_low(sizeof(struct resource)); + res->start = 0; + res->end = memory_end; + res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; + request_resource(&iomem_resource, res); + request_resource(res, &code_resource); + request_resource(res, &data_resource); +} + +void print_cpu_info(struct cpuinfo_S390 *cpuinfo) +{ + printk("cpu %d " +#ifdef CONFIG_SMP + "phys_idx=%d " +#endif + "vers=%02X ident=%06X machine=%04X unused=%04X\n", + cpuinfo->cpu_nr, +#ifdef CONFIG_SMP + cpuinfo->cpu_addr, +#endif + cpuinfo->cpu_id.version, + cpuinfo->cpu_id.ident, + cpuinfo->cpu_id.machine, + cpuinfo->cpu_id.unused); +} + +/* + * Get CPU information for use by the procfs. + */ + +int get_cpuinfo(char * buffer) +{ + struct cpuinfo_S390 *cpuinfo; + char *p = buffer; + int i; + + p += sprintf(p,"vendor_id : IBM/S390\n" + "# processors : %i\n" + "bogomips per cpu: %lu.%02lu\n", + smp_num_cpus, loops_per_sec/500000, + (loops_per_sec/5000)%100); + for (i = 0; i < smp_num_cpus; i++) { + cpuinfo = &safe_get_cpu_lowcore(i).cpu_data; + p += sprintf(p,"processor %i: " + "version = %02X, " + "identification = %06X, " + "machine = %04X\n", + i, cpuinfo->cpu_id.version, + cpuinfo->cpu_id.ident, + cpuinfo->cpu_id.machine); + } + return p - buffer; +} + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/signal.c linux/arch/s390/kernel/signal.c --- v2.3.99-pre7/linux/arch/s390/kernel/signal.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/signal.c Fri May 12 11:41:45 2000 @@ -0,0 +1,555 @@ +/* + * arch/s390/kernel/signal.c + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) + * + * Based on Intel version + * + * Copyright (C) 1991, 1992 Linus Torvalds + * + * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG_SIG 0 + +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + +/* pretcode & sig are used to store the return addr on Intel + & the signal no as the first parameter we do this differently + using gpr14 & gpr2. */ + +#define SIGFRAME_COMMON \ +__u8 callee_used_stack[__SIGNAL_FRAMESIZE]; \ +struct sigcontext sc; \ +sigregs sregs; \ +__u8 retcode[S390_SYSCALL_SIZE]; + +typedef struct +{ + SIGFRAME_COMMON +} sigframe; + +typedef struct +{ + SIGFRAME_COMMON + struct siginfo info; + struct ucontext uc; +} rt_sigframe; + +asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr, + int options, unsigned long *ru); +asmlinkage int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset)); + +/* + * Atomically swap in the new signal mask, and wait for a signal. + */ +asmlinkage int +sys_sigsuspend(struct pt_regs * regs,int history0, int history1, old_sigset_t mask) +{ + sigset_t saveset; + + mask &= _BLOCKABLE; + spin_lock_irq(¤t->sigmask_lock); + saveset = current->blocked; + siginitset(¤t->blocked, mask); + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + regs->gprs[2] = -EINTR; + + while (1) { + current->state = TASK_INTERRUPTIBLE; + schedule(); + if (do_signal(regs, &saveset)) + return -EINTR; + } +} + +asmlinkage int +sys_rt_sigsuspend(struct pt_regs * regs,sigset_t *unewset, size_t sigsetsize) +{ + sigset_t saveset, newset; + + /* XXX: Don't preclude handling different sized sigset_t's. */ + if (sigsetsize != sizeof(sigset_t)) + return -EINVAL; + + if (copy_from_user(&newset, unewset, sizeof(newset))) + return -EFAULT; + sigdelsetmask(&newset, ~_BLOCKABLE); + + spin_lock_irq(¤t->sigmask_lock); + saveset = current->blocked; + current->blocked = newset; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + regs->gprs[2] = -EINTR; + + while (1) { + current->state = TASK_INTERRUPTIBLE; + schedule(); + if (do_signal(regs, &saveset)) + return -EINTR; + } +} + +asmlinkage int +sys_sigaction(int sig, const struct old_sigaction *act, + struct old_sigaction *oact) +{ + struct k_sigaction new_ka, old_ka; + int ret; + + if (act) { + old_sigset_t mask; + if (verify_area(VERIFY_READ, act, sizeof(*act)) || + __get_user(new_ka.sa.sa_handler, &act->sa_handler) || + __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) + return -EFAULT; + __get_user(new_ka.sa.sa_flags, &act->sa_flags); + __get_user(mask, &act->sa_mask); + siginitset(&new_ka.sa.sa_mask, mask); + } + + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + + if (!ret && oact) { + if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || + __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || + __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) + return -EFAULT; + __put_user(old_ka.sa.sa_flags, &oact->sa_flags); + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); + } + + return ret; +} + +asmlinkage int +sys_sigaltstack(const stack_t *uss, stack_t *uoss) +{ + struct pt_regs *regs = (struct pt_regs *) &uss; + return do_sigaltstack(uss, uoss, regs->gprs[15]); +} + + + + +static int save_sigregs(struct pt_regs *regs,sigregs *sregs) +{ + int err; + s390_fp_regs fpregs; + + err = __copy_to_user(&sregs->regs,regs,sizeof(s390_regs_common)); + if(!err) + { + save_fp_regs(&fpregs); + err=__copy_to_user(&sregs->fpregs,&fpregs,sizeof(fpregs)); + } + return(err); + +} + +static int restore_sigregs(struct pt_regs *regs,sigregs *sregs) +{ + int err; + s390_fp_regs fpregs; + psw_t saved_psw=regs->psw; + err=__copy_from_user(regs,&sregs->regs,sizeof(s390_regs_common)); + if(!err) + { + regs->orig_gpr2 = -1; /* disable syscall checks */ + regs->psw.mask=(saved_psw.mask&~PSW_MASK_DEBUGCHANGE)| + (regs->psw.mask&PSW_MASK_DEBUGCHANGE); + regs->psw.addr=(saved_psw.addr&~PSW_ADDR_DEBUGCHANGE)| + (regs->psw.addr&PSW_ADDR_DEBUGCHANGE); + err=__copy_from_user(&fpregs,&sregs->fpregs,sizeof(fpregs)); + if(!err) + restore_fp_regs(&fpregs); + } + return(err); +} + +static int +restore_sigcontext(struct sigcontext *sc, pt_regs *regs, + sigregs *sregs,sigset_t *set) +{ + unsigned int err; + + err=restore_sigregs(regs,sregs); + if(!err) + err=__copy_from_user(&set->sig,&sc->oldmask,SIGMASK_COPY_SIZE); + return(err); +} + +int sigreturn_common(struct pt_regs *regs,int framesize) +{ + sigframe *frame = (sigframe *)regs->gprs[15]; + sigset_t set; + + if (verify_area(VERIFY_READ, frame, sizeof(*frame))) + return -1; + if (restore_sigcontext(&frame->sc,regs,&frame->sregs,&set)) + return -1; + sigdelsetmask(&set, ~_BLOCKABLE); + spin_lock_irq(¤t->sigmask_lock); + current->blocked = set; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + return 0; +} + +asmlinkage int sys_sigreturn(struct pt_regs *regs) +{ + + if (sigreturn_common(regs,sizeof(sigframe))) + goto badframe; + return regs->gprs[2]; + +badframe: + force_sig(SIGSEGV, current); + return 0; +} + +asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) +{ + rt_sigframe *frame = (rt_sigframe *)regs->gprs[15]; + stack_t st; + + if (sigreturn_common(regs,sizeof(rt_sigframe))) + goto badframe; + if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st))) + goto badframe; + /* It is more difficult to avoid calling this function than to + call it and ignore errors. */ + do_sigaltstack(&st, NULL, regs->gprs[15]); + return regs->gprs[2]; + +badframe: + force_sig(SIGSEGV, current); + return 0; +} + +/* + * Set up a signal frame. + */ + + +/* + * Determine which stack to use.. + */ +static inline void * +get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) +{ + unsigned long sp; + + /* Default to using normal stack */ + sp = regs->gprs[15]; + + /* This is the X/Open sanctioned signal stack switching. */ + if (ka->sa.sa_flags & SA_ONSTACK) { + if (! on_sig_stack(sp)) + sp = current->sas_ss_sp + current->sas_ss_size; + } + + /* This is the legacy signal stack switching. */ + else if (!user_mode(regs) && + !(ka->sa.sa_flags & SA_RESTORER) && + ka->sa.sa_restorer) { + sp = (unsigned long) ka->sa.sa_restorer; + } + + return (void *)((sp - frame_size) & -8ul); +} + +static void *setup_frame_common(int sig, struct k_sigaction *ka, + sigset_t *set, struct pt_regs * regs, + int frame_size,u16 retcode) +{ + sigframe *frame; + int err; + + frame = get_sigframe(ka, regs,frame_size); + if (!access_ok(VERIFY_WRITE, frame,frame_size)) + return 0; + err = save_sigregs(regs,&frame->sregs); + if(!err) + err=__put_user(&frame->sregs,&frame->sc.sregs); + if(!err) + + err=__copy_to_user(&frame->sc.oldmask,&set->sig,SIGMASK_COPY_SIZE); + if(!err) + { + regs->gprs[2]=(current->exec_domain + && current->exec_domain->signal_invmap + && sig < 32 + ? current->exec_domain->signal_invmap[sig] + : sig); + /* Set up registers for signal handler */ + regs->gprs[15] = (addr_t)frame; + regs->psw.addr = FIX_PSW(ka->sa.sa_handler); + } + /* Set up to return from userspace. If provided, use a stub + already in userspace. */ + if (ka->sa.sa_flags & SA_RESTORER) { + regs->gprs[14] = FIX_PSW(ka->sa.sa_restorer); + } else { + regs->gprs[14] = FIX_PSW(frame->retcode); + err |= __put_user(retcode, (u16 *)(frame->retcode)); + } + return(err ? 0:frame); +} + +static void setup_frame(int sig, struct k_sigaction *ka, + sigset_t *set, struct pt_regs * regs) +{ + + if(!setup_frame_common(sig,ka,set,regs,sizeof(sigframe), + (S390_SYSCALL_OPCODE|__NR_sigreturn))) + goto give_sigsegv; +#if DEBUG_SIG + printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", + current->comm, current->pid, frame, regs->eip, frame->pretcode); +#endif + return; + +give_sigsegv: + if (sig == SIGSEGV) + ka->sa.sa_handler = SIG_DFL; + force_sig(SIGSEGV, current); +} + +static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *set, struct pt_regs * regs) +{ + rt_sigframe *frame; + addr_t orig_sp=regs->gprs[15]; + int err; + + if((frame=setup_frame_common(sig,ka,set,regs,sizeof(rt_sigframe), + (S390_SYSCALL_OPCODE|__NR_rt_sigreturn)))==0) + goto give_sigsegv; + + err = __copy_to_user(&frame->info, info, sizeof(*info)); + + /* Create the ucontext. */ + err |= __put_user(0, &frame->uc.uc_flags); + err |= __put_user(0, &frame->uc.uc_link); + err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); + err |= __put_user(sas_ss_flags(orig_sp), + &frame->uc.uc_stack.ss_flags); + err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); + regs->gprs[3] = (u32)&frame->info; + regs->gprs[4] = (u32)&frame->uc; + + if (err) + goto give_sigsegv; + +#if DEBUG_SIG + printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", + current->comm, current->pid, frame, regs->eip, frame->pretcode); +#endif + return; + +give_sigsegv: + if (sig == SIGSEGV) + ka->sa.sa_handler = SIG_DFL; + force_sig(SIGSEGV, current); +} + +/* + * OK, we're invoking a handler + */ + +static void +handle_signal(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) +{ + /* Are we from a system call? */ + if (regs->orig_gpr2 >= 0) { + /* If so, check system call restarting.. */ + switch (regs->gprs[2]) { + case -ERESTARTNOHAND: + regs->gprs[2] = -EINTR; + break; + + case -ERESTARTSYS: + if (!(ka->sa.sa_flags & SA_RESTART)) { + regs->gprs[2] = -EINTR; + break; + } + /* fallthrough */ + case -ERESTARTNOINTR: + regs->gprs[2] = regs->orig_gpr2; + regs->psw.addr -= 2; + } + } + + /* Set up the stack frame */ + if (ka->sa.sa_flags & SA_SIGINFO) + setup_rt_frame(sig, ka, info, oldset, regs); + else + setup_frame(sig, ka, oldset, regs); + + if (ka->sa.sa_flags & SA_ONESHOT) + ka->sa.sa_handler = SIG_DFL; + + if (!(ka->sa.sa_flags & SA_NODEFER)) { + spin_lock_irq(¤t->sigmask_lock); + sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigaddset(¤t->blocked,sig); + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + } +} + +/* + * Note that 'init' is a special process: it doesn't get signals it doesn't + * want to handle. Thus you cannot kill init even with a SIGKILL even by + * mistake. + * + * Note that we go through the signals twice: once to check the signals that + * the kernel can handle, and then we build all the user-level signal handling + * stack-frames in one go after that. + */ +int do_signal(struct pt_regs *regs, sigset_t *oldset) +{ + siginfo_t info; + struct k_sigaction *ka; + + /* + * We want the common case to go fast, which + * is why we may in certain cases get here from + * kernel mode. Just return without doing anything + * if so. + */ + if (!user_mode(regs)) + return 1; + + if (!oldset) + oldset = ¤t->blocked; + + for (;;) { + unsigned long signr; + + spin_lock_irq(¤t->sigmask_lock); + signr = dequeue_signal(¤t->blocked, &info); + spin_unlock_irq(¤t->sigmask_lock); + + if (!signr) + break; + + if ((current->flags & PF_PTRACED) && signr != SIGKILL) { + /* Let the debugger run. */ + current->exit_code = signr; + current->state = TASK_STOPPED; + notify_parent(current, SIGCHLD); + schedule(); + + /* We're back. Did the debugger cancel the sig? */ + if (!(signr = current->exit_code)) + continue; + current->exit_code = 0; + + /* The debugger continued. Ignore SIGSTOP. */ + if (signr == SIGSTOP) + continue; + + /* Update the siginfo structure. Is this good? */ + if (signr != info.si_signo) { + info.si_signo = signr; + info.si_errno = 0; + info.si_code = SI_USER; + info.si_pid = current->p_pptr->pid; + info.si_uid = current->p_pptr->uid; + } + + /* If the (new) signal is now blocked, requeue it. */ + if (sigismember(¤t->blocked, signr)) { + send_sig_info(signr, &info, current); + continue; + } + } + + ka = ¤t->sig->action[signr-1]; + if (ka->sa.sa_handler == SIG_IGN) { + if (signr != SIGCHLD) + continue; + /* Check for SIGCHLD: it's special. */ + while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0) + /* nothing */; + continue; + } + + if (ka->sa.sa_handler == SIG_DFL) { + int exit_code = signr; + + /* Init gets no signals it doesn't want. */ + if (current->pid == 1) + continue; + + switch (signr) { + case SIGCONT: case SIGCHLD: case SIGWINCH: + continue; + + case SIGTSTP: case SIGTTIN: case SIGTTOU: + if (is_orphaned_pgrp(current->pgrp)) + continue; + /* FALLTHRU */ + + case SIGSTOP: + current->state = TASK_STOPPED; + current->exit_code = signr; + if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) + notify_parent(current, SIGCHLD); + schedule(); + continue; + + case SIGQUIT: case SIGILL: case SIGTRAP: + case SIGABRT: case SIGFPE: case SIGSEGV: + if (do_coredump(signr, regs)) + exit_code |= 0x80; + /* FALLTHRU */ + + default: + lock_kernel(); + sigaddset(¤t->signal, signr); + recalc_sigpending(current); + current->flags |= PF_SIGNALED; + do_exit(exit_code); + /* NOTREACHED */ + } + } + + /* Whee! Actually deliver the signal. */ + handle_signal(signr, ka, &info, oldset, regs); + return 1; + } + + /* Did we come from a system call? */ + if ( regs->trap == 0x20 /* System Call! */ ) { + /* Restart the system call - no handlers present */ + if (regs->gprs[2] == -ERESTARTNOHAND || + regs->gprs[2] == -ERESTARTSYS || + regs->gprs[2] == -ERESTARTNOINTR) { + regs->gprs[2] = regs->orig_gpr2; + regs->psw.addr -= 2; + } + } + return 0; +} diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/smp.c linux/arch/s390/kernel/smp.c --- v2.3.99-pre7/linux/arch/s390/kernel/smp.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/smp.c Fri May 12 11:41:45 2000 @@ -0,0 +1,729 @@ +/* + * arch/s390/kernel/smp.c + * + * S390 version + * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), + * Martin Schwidefsky (schwidefsky@de.ibm.com) + * + * based on other smp stuff by + * (c) 1995 Alan Cox, CymruNET Ltd + * (c) 1998 Ingo Molnar + * + * We work with logical cpu numbering everywhere we can. The only + * functions using the real cpu address (got from STAP) are the sigp + * functions. For all other functions we use the identity mapping. + * That means that cpu_number_map[i] == i for every cpu. cpu_number_map is + * used e.g. to find the idle task belonging to a logical cpu. Every array + * in the kernel is sorted by the logical cpu number and not by the physical + * one which is causing all the confusion with __cpu_logical_map and + * cpu_number_map in other architectures. + */ + +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "cpcmd.h" + +/* prototypes */ +extern void update_one_process( struct task_struct *p, + unsigned long ticks, unsigned long user, + unsigned long system, int cpu); +extern int cpu_idle(void * unused); + +extern __u16 boot_cpu_addr; + +/* + * An array with a pointer the lowcore of every CPU. + */ +static int max_cpus = NR_CPUS; /* Setup configured maximum number of CPUs to activate */ +int smp_num_cpus; +struct _lowcore *lowcore_ptr[NR_CPUS]; +unsigned int prof_multiplier[NR_CPUS]; +unsigned int prof_old_multiplier[NR_CPUS]; +unsigned int prof_counter[NR_CPUS]; +volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */ +cycles_t cacheflush_time=0; +int smp_threads_ready=0; /* Set when the idlers are all forked. */ +unsigned long ipi_count=0; /* Number of IPIs delivered. */ +static atomic_t smp_commenced = ATOMIC_INIT(0); + +spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED; + +/* + * Setup routine for controlling SMP activation + * + * Command-line option of "nosmp" or "maxcpus=0" will disable SMP + * activation entirely (the MPS table probe still happens, though). + * + * Command-line option of "maxcpus=", where is an integer + * greater than 0, limits the maximum number of CPUs activated in + * SMP mode to . + */ + +static int __init nosmp(char *str) +{ + max_cpus = 0; + return 1; +} + +__setup("nosmp", nosmp); + +static int __init maxcpus(char *str) +{ + get_option(&str, &max_cpus); + return 1; +} + +__setup("maxcpus=", maxcpus); + +/* + * Reboot, halt and power_off routines for SMP. + */ +extern char vmhalt_cmd[]; +extern char vmpoff_cmd[]; + +extern void reipl(unsigned long devno); + +void do_machine_restart(void) +{ + smp_send_stop(); + reipl(S390_lowcore.ipl_device); +} + +void machine_restart(char * __unused) +{ + if (smp_processor_id() != 0) { + smp_ext_call_async(0, ec_restart); + for (;;); + } else + do_machine_restart(); +} + +void do_machine_halt(void) +{ + smp_send_stop(); + if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0) + cpcmd(vmhalt_cmd, NULL, 0); + disabled_wait(0); +} + +void machine_halt(void) +{ + if (smp_processor_id() != 0) { + smp_ext_call_async(0, ec_halt); + for (;;); + } else + do_machine_halt(); +} + +void do_machine_power_off(void) +{ + smp_send_stop(); + if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0) + cpcmd(vmpoff_cmd, NULL, 0); + disabled_wait(0); +} + +void machine_power_off(void) +{ + if (smp_processor_id() != 0) { + smp_ext_call_async(0, ec_power_off); + for (;;); + } else + do_machine_power_off(); +} + +/* + * This is the main routine where commands issued by other + * cpus are handled. + */ + +void do_ext_call_interrupt(__u16 source_cpu_addr) +{ + ec_ext_call *ec, *next; + int bits; + + /* + * handle bit signal external calls + * + * For the ec_schedule signal we have to do nothing. All the work + * is done automatically when we return from the interrupt. + * For the ec_restart, ec_halt and ec_power_off we call the + * appropriate routine. + */ + do { + bits = atomic_read(&S390_lowcore.ext_call_fast); + } while (atomic_compare_and_swap(bits,0,&S390_lowcore.ext_call_fast)); + + if (test_bit(ec_restart, &bits)) + do_machine_restart(); + if (test_bit(ec_halt, &bits)) + do_machine_halt(); + if (test_bit(ec_power_off, &bits)) + do_machine_power_off(); + + /* + * Handle external call commands with a parameter area + */ + do { + ec = (ec_ext_call *) atomic_read(&S390_lowcore.ext_call_queue); + } while (atomic_compare_and_swap((int) ec, 0, + &S390_lowcore.ext_call_queue)); + if (ec == NULL) + return; /* no command signals */ + + /* Make a fifo out of the lifo */ + next = ec; + ec->next = NULL; + while (next != NULL) { + ec_ext_call *tmp = next->next; + next->next = ec; + ec = next; + next = tmp; + } + + /* Execute every sigp command on the queue */ + while (ec != NULL) { + switch (ec->cmd) { + case ec_get_ctl: { + ec_creg_parms *pp; + pp = (ec_creg_parms *) ec->parms; + atomic_set(&ec->status,ec_executing); + asm volatile ( + " bras 1,0f\n" + " stctl 0,0,0(%0)\n" + "0: ex %1,0(1)\n" + : : "a" (pp->cregs+pp->start_ctl), + "a" ((pp->start_ctl<<4) + pp->end_ctl) + : "memory", "1" ); + atomic_set(&ec->status,ec_done); + return; + } + case ec_set_ctl: { + ec_creg_parms *pp; + pp = (ec_creg_parms *) ec->parms; + atomic_set(&ec->status,ec_executing); + asm volatile ( + " bras 1,0f\n" + " lctl 0,0,0(%0)\n" + "0: ex %1,0(1)\n" + : : "a" (pp->cregs+pp->start_ctl), + "a" ((pp->start_ctl<<4) + pp->end_ctl) + : "memory", "1" ); + atomic_set(&ec->status,ec_done); + return; + } + case ec_set_ctl_masked: { + ec_creg_mask_parms *pp; + u32 cregs[16]; + int i; + + pp = (ec_creg_mask_parms *) ec->parms; + atomic_set(&ec->status,ec_executing); + asm volatile ( + " bras 1,0f\n" + " stctl 0,0,0(%0)\n" + "0: ex %1,0(1)\n" + : : "a" (cregs+pp->start_ctl), + "a" ((pp->start_ctl<<4) + pp->end_ctl) + : "memory", "1" ); + for (i = pp->start_ctl; i <= pp->end_ctl; i++) + cregs[i] = (cregs[i] & pp->andvals[i]) + | pp->orvals[i]; + asm volatile ( + " bras 1,0f\n" + " lctl 0,0,0(%0)\n" + "0: ex %1,0(1)\n" + : : "a" (cregs+pp->start_ctl), + "a" ((pp->start_ctl<<4) + pp->end_ctl) + : "memory", "1" ); + atomic_set(&ec->status,ec_done); + return; + } + default: + } + ec = ec->next; + } +} + +/* + * Send an external call sigp to another cpu and wait for its completion. + */ +sigp_ccode smp_ext_call_sync(int cpu, ec_cmd_sig cmd, void *parms) +{ + struct _lowcore *lowcore = &get_cpu_lowcore(cpu); + sigp_ccode ccode; + ec_ext_call ec; + + ec.cmd = cmd; + atomic_set(&ec.status, ec_pending); + ec.parms = parms; + do { + ec.next = (ec_ext_call*) atomic_read(&lowcore->ext_call_queue); + } while (atomic_compare_and_swap((int) ec.next, (int)(&ec), + &lowcore->ext_call_queue)); + /* + * We try once to deliver the signal. There are four possible + * return codes: + * 0) Order code accepted - can't show up on an external call + * 1) Status stored - fine, wait for completion. + * 2) Busy - there is another signal pending. Thats fine too, because + * do_ext_call from the pending signal will execute all signals on + * the queue. We wait for completion. + * 3) Not operational - something very bad has happened to the cpu. + * do not wait for completion. + */ + ccode = signal_processor(cpu, sigp_external_call); + + if (ccode != sigp_not_operational) + /* wait for completion, FIXME: possible seed of a deadlock */ + while (atomic_read(&ec.status) != ec_done); + + return ccode; +} + +/* + * Send an external call sigp to another cpu and return without waiting + * for its completion. Currently we do not support parameters with + * asynchronous sigps. + */ +sigp_ccode smp_ext_call_async(int cpu, ec_bit_sig sig) +{ + struct _lowcore *lowcore = &get_cpu_lowcore(cpu); + sigp_ccode ccode; + + /* + * Set signaling bit in lowcore of target cpu and kick it + */ + atomic_set_mask(1<ext_call_fast); + ccode = signal_processor(cpu, sigp_external_call); + return ccode; +} + +/* + * Send an external call sigp to every other cpu in the system and + * wait for the completion of the sigps. + */ +void smp_ext_call_sync_others(ec_cmd_sig cmd, void *parms) +{ + struct _lowcore *lowcore; + ec_ext_call ec[NR_CPUS]; + sigp_ccode ccode; + int i; + + for (i = 0; i < smp_num_cpus; i++) { + if (smp_processor_id() == i) + continue; + lowcore = &get_cpu_lowcore(i); + ec[i].cmd = cmd; + atomic_set(&ec[i].status, ec_pending); + ec[i].parms = parms; + do { + ec[i].next = (ec_ext_call *) + atomic_read(&lowcore->ext_call_queue); + } while (atomic_compare_and_swap((int) ec[i].next, (int)(ec+i), + &lowcore->ext_call_queue)); + ccode = signal_processor(i, sigp_external_call); + } + + /* wait for completion, FIXME: possible seed of a deadlock */ + for (i = 0; i < smp_num_cpus; i++) { + if (smp_processor_id() == i) + continue; + while (atomic_read(&ec[i].status) != ec_done); + } +} + +/* + * Send an external call sigp to every other cpu in the system and + * return without waiting for the completion of the sigps. Currently + * we do not support parameters with asynchronous sigps. + */ +void smp_ext_call_async_others(ec_bit_sig sig) +{ + struct _lowcore *lowcore; + sigp_ccode ccode; + int i; + + for (i = 0; i < smp_num_cpus; i++) { + if (smp_processor_id() == i) + continue; + lowcore = &get_cpu_lowcore(i); + /* + * Set signaling bit in lowcore of target cpu and kick it + */ + atomic_set_mask(1<ext_call_fast); + ccode = signal_processor(i, sigp_external_call); + } +} + +/* + * cycles through all the cpus, + * returns early if info is not NULL & the processor has something + * of intrest to report in the info structure. + * it returns the next cpu to check if it returns early. + * i.e. it should be used as follows if you wish to receive info. + * next_cpu=0; + * do + * { + * info->cpu=next_cpu; + * next_cpu=smp_signal_others(order_code,parameter,1,info); + * ... check info here + * } while(next_cpu<=smp_num_cpus) + * + * if you are lazy just use it like + * smp_signal_others(order_code,parameter,0,1,NULL); + */ +int smp_signal_others(sigp_order_code order_code, u32 parameter, + int spin, sigp_info *info) +{ + sigp_ccode ccode; + u32 dummy; + u16 i; + + if (info) + info->intresting = 0; + for (i = (info ? info->cpu : 0); i < smp_num_cpus; i++) { + if (smp_processor_id() != i) { + do { + ccode = signal_processor_ps( + (info ? &info->status : &dummy), + parameter, i, order_code); + } while(spin && ccode == sigp_busy); + if (info && ccode != sigp_order_code_accepted) { + info->intresting = 1; + info->cpu = i; + info->ccode = ccode; + i++; + break; + } + } + } + return i; +} + +/* + * this function sends a 'stop' sigp to all other CPUs in the system. + * it goes straight through. + */ + +void smp_send_stop(void) +{ + smp_signal_others(sigp_stop, 0, 1, NULL); +} + +/* + * this function sends a 'reschedule' IPI to another CPU. + * it goes straight through and wastes no time serializing + * anything. Worst case is that we lose a reschedule ... + */ + +void smp_send_reschedule(int cpu) +{ + smp_ext_call_async(cpu, ec_schedule); +} + +/* + * Set a bit in a control register of all cpus + */ +void smp_ctl_set_bit(int cr, int bit) { + ec_creg_mask_parms parms; + + if (atomic_read(&smp_commenced) != 0) { + parms.start_ctl = cr; + parms.end_ctl = cr; + parms.orvals[cr] = 1 << bit; + parms.andvals[cr] = 0xFFFFFFFF; + smp_ext_call_sync_others(ec_set_ctl_masked,&parms); + } + __ctl_set_bit(cr, bit); +} + +/* + * Clear a bit in a control register of all cpus + */ +void smp_ctl_clear_bit(int cr, int bit) { + ec_creg_mask_parms parms; + + if (atomic_read(&smp_commenced) != 0) { + parms.start_ctl = cr; + parms.end_ctl = cr; + parms.orvals[cr] = 0x00000000; + parms.andvals[cr] = ~(1 << bit); + smp_ext_call_sync_others(ec_set_ctl_masked,&parms); + } + __ctl_clear_bit(cr, bit); +} + + +/* + * Lets check how many CPUs we have. + */ + +void smp_count_cpus(void) +{ + int curr_cpu; + + __cpu_logical_map[0] = boot_cpu_addr; + current->processor = 0; + smp_num_cpus = 1; + for (curr_cpu = 0; + curr_cpu <= 65535 && smp_num_cpus < max_cpus; curr_cpu++) { + if ((__u16) curr_cpu == boot_cpu_addr) + continue; + __cpu_logical_map[smp_num_cpus] = (__u16) curr_cpu; + if (signal_processor(smp_num_cpus, sigp_sense) == + sigp_not_operational) + continue; + smp_num_cpus++; + } + printk("Detected %d CPU's\n",(int) smp_num_cpus); + printk("Boot cpu address %2X\n", boot_cpu_addr); +} + + +/* + * Activate a secondary processor. + */ +extern void init_100hz_timer(void); + +int __init start_secondary(void *cpuvoid) +{ + /* Setup the cpu */ + cpu_init(); + /* Print info about this processor */ + print_cpu_info(&safe_get_cpu_lowcore(smp_processor_id()).cpu_data); + /* Wait for completion of smp startup */ + while (!atomic_read(&smp_commenced)) + /* nothing */ ; + /* init per CPU 100 hz timer */ + init_100hz_timer(); + /* cpu_idle will call schedule for us */ + return cpu_idle(NULL); +} + +/* + * The restart interrupt handler jumps to start_secondary directly + * without the detour over initialize_secondary. We defined it here + * so that the linker doesn't complain. + */ +void __init initialize_secondary(void) +{ +} + +static int __init fork_by_hand(void) +{ + struct pt_regs regs; + /* don't care about the psw and regs settings since we'll never + reschedule the forked task. */ + memset(®s,sizeof(pt_regs),0); + return do_fork(CLONE_VM|CLONE_PID, 0, ®s); +} + +static void __init do_boot_cpu(int cpu) +{ + struct task_struct *idle; + struct _lowcore *cpu_lowcore; + + /* We can't use kernel_thread since we must _avoid_ to reschedule + the child. */ + if (fork_by_hand() < 0) + panic("failed fork for CPU %d", cpu); + + /* + * We remove it from the pidhash and the runqueue + * once we got the process: + */ + idle = init_task.prev_task; + if (!idle) + panic("No idle process for CPU %d",cpu); + idle->processor = cpu; + idle->has_cpu = 1; /* we schedule the first task manually */ + + del_from_runqueue(idle); + unhash_process(idle); + init_tasks[cpu] = idle; + + cpu_lowcore=&get_cpu_lowcore(cpu); + cpu_lowcore->kernel_stack=idle->thread.ksp; + __asm__ __volatile__("stctl 0,15,%0\n\t" + "stam 0,15,%1" + : "=m" (cpu_lowcore->cregs_save_area[0]), + "=m" (cpu_lowcore->access_regs_save_area[0]) + : : "memory"); + + eieio(); + signal_processor(cpu,sigp_restart); +} + +/* + * Architecture specific routine called by the kernel just before init is + * fired off. This allows the BP to have everything in order [we hope]. + * At the end of this all the APs will hit the system scheduling and off + * we go. Each AP will load the system gdt's and jump through the kernel + * init into idle(). At this point the scheduler will one day take over + * and give them jobs to do. smp_callin is a standard routine + * we use to track CPUs as they power up. + */ + +void __init smp_commence(void) +{ + /* + * Lets the callins below out of their loop. + */ + atomic_set(&smp_commenced,1); +} + +/* + * Cycle through the processors sending APIC IPIs to boot each. + */ + +void __init smp_boot_cpus(void) +{ + struct _lowcore *curr_lowcore; + sigp_ccode ccode; + int i; + + smp_count_cpus(); + memset(lowcore_ptr,0,sizeof(lowcore_ptr)); + + /* + * Initialize the logical to physical CPU number mapping + * and the per-CPU profiling counter/multiplier + */ + + for (i = 0; i < NR_CPUS; i++) { + prof_counter[i] = 1; + prof_old_multiplier[i] = 1; + prof_multiplier[i] = 1; + } + + print_cpu_info(&safe_get_cpu_lowcore(0).cpu_data); + + for(i = 0; i < smp_num_cpus; i++) + { + curr_lowcore = (struct _lowcore *) + __get_free_page(GFP_KERNEL|GFP_DMA); + if (curr_lowcore == NULL) { + printk("smp_boot_cpus failed to allocate prefix memory\n"); + break; + } + lowcore_ptr[i] = curr_lowcore; + memcpy(curr_lowcore, &S390_lowcore, sizeof(struct _lowcore)); + /* + * Most of the parameters are set up when the cpu is + * started up. + */ + if (smp_processor_id() == i) + set_prefix((u32) curr_lowcore); + else { + ccode = signal_processor_p((u32)(curr_lowcore), + i, sigp_set_prefix); + if(ccode) { + /* if this gets troublesome I'll have to do + * something about it. */ + printk("ccode %d for cpu %d returned when " + "setting prefix in smp_boot_cpus not good.\n", + (int) ccode, (int) i); + } + else + do_boot_cpu(i); + } + } +} + +/* + * the frequency of the profiling timer can be changed + * by writing a multiplier value into /proc/profile. + * + * usually you want to run this on all CPUs ;) + */ +int setup_profiling_timer(unsigned int multiplier) +{ + return 0; +} + +/* + * Local timer interrupt handler. It does both profiling and + * process statistics/rescheduling. + * + * We do profiling in every local tick, statistics/rescheduling + * happen only every 'profiling multiplier' ticks. The default + * multiplier is 1 and it can be changed by writing the new multiplier + * value into /proc/profile. + */ + +void smp_local_timer_interrupt(struct pt_regs * regs) +{ + int user = (user_mode(regs) != 0); + int cpu = smp_processor_id(); + + /* + * The profiling function is SMP safe. (nothing can mess + * around with "current", and the profiling counters are + * updated with atomic operations). This is especially + * useful with a profiling multiplier != 1 + */ + if (!user_mode(regs)) + s390_do_profile(regs->psw.addr); + + if (!--prof_counter[cpu]) { + int system = 1-user; + struct task_struct * p = current; + + /* + * The multiplier may have changed since the last time we got + * to this point as a result of the user writing to + * /proc/profile. In this case we need to adjust the APIC + * timer accordingly. + * + * Interrupts are already masked off at this point. + */ + prof_counter[cpu] = prof_multiplier[cpu]; + if (prof_counter[cpu] != prof_old_multiplier[cpu]) { + /* FIXME setup_APIC_timer(calibration_result/prof_counter[cpu] + ); */ + prof_old_multiplier[cpu] = prof_counter[cpu]; + } + + /* + * After doing the above, we need to make like + * a normal interrupt - otherwise timer interrupts + * ignore the global interrupt lock, which is the + * WrongThing (tm) to do. + */ + + irq_enter(cpu, 0); + update_one_process(p, 1, user, system, cpu); + if (p->pid) { + p->counter -= 1; + if (p->counter <= 0) { + p->counter = 0; + p->need_resched = 1; + } + if (p->priority < DEF_PRIORITY) { + kstat.cpu_nice += user; + kstat.per_cpu_nice[cpu] += user; + } else { + kstat.cpu_user += user; + kstat.per_cpu_user[cpu] += user; + } + kstat.cpu_system += system; + kstat.per_cpu_system[cpu] += system; + + } + irq_exit(cpu, 0); + } +} + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/sys_s390.c linux/arch/s390/kernel/sys_s390.c --- v2.3.99-pre7/linux/arch/s390/kernel/sys_s390.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/sys_s390.c Fri May 12 11:41:45 2000 @@ -0,0 +1,257 @@ +/* + * arch/s390/kernel/sys_s390.c + * + * S390 version + * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), + * + * Derived from "arch/i386/kernel/sys_i386.c" + * + * This file contains various random system calls that + * have a non-standard calling sequence on the Linux/s390 + * platform. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* + * sys_pipe() is the normal C calling standard for creating + * a pipe. It's not the way Unix traditionally does this, though. + */ +asmlinkage int sys_pipe(unsigned long * fildes) +{ + int fd[2]; + int error; + + lock_kernel(); + error = do_pipe(fd); + unlock_kernel(); + if (!error) { + if (copy_to_user(fildes, fd, 2*sizeof(int))) + error = -EFAULT; + } + return error; +} + +/* common code for old and new mmaps */ +static inline long do_mmap2( + unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long pgoff) +{ + int error = -EBADF; + struct file * file = NULL; + + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); + if (!(flags & MAP_ANONYMOUS)) { + file = fget(fd); + if (!file) + goto out; + } + + down(¤t->mm->mmap_sem); + lock_kernel(); + + error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); + + unlock_kernel(); + up(¤t->mm->mmap_sem); + + if (file) + fput(file); +out: + return error; +} + +/* FIXME: 6 parameters is one too much ... */ +asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long pgoff) +{ + return do_mmap2(addr, len, prot, flags, fd, pgoff); +} + +/* + * Perform the select(nd, in, out, ex, tv) and mmap() system + * calls. Linux/i386 didn't use to be able to handle more than + * 4 system call parameters, so these system calls used a memory + * block for parameter passing.. + */ + +struct mmap_arg_struct { + unsigned long addr; + unsigned long len; + unsigned long prot; + unsigned long flags; + unsigned long fd; + unsigned long offset; +}; + +asmlinkage int old_mmap(struct mmap_arg_struct *arg) +{ + struct mmap_arg_struct a; + int error = -EFAULT; + + if (copy_from_user(&a, arg, sizeof(a))) + goto out; + + error = -EINVAL; + if (a.offset & ~PAGE_MASK) + goto out; + + error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); +out: + return error; +} + +extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *); + +struct sel_arg_struct { + unsigned long n; + fd_set *inp, *outp, *exp; + struct timeval *tvp; +}; + +asmlinkage int old_select(struct sel_arg_struct *arg) +{ + struct sel_arg_struct a; + + if (copy_from_user(&a, arg, sizeof(a))) + return -EFAULT; + /* sys_select() does the appropriate kernel locking */ + return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); +} + +/* + * sys_ipc() is the de-multiplexer for the SysV IPC calls.. + * + * This is really horribly ugly. + */ +asmlinkage int sys_ipc (uint call, int first, int second, + int third, void *ptr) +{ + struct ipc_kludge tmp; + int ret; + + switch (call) { + case SEMOP: + return sys_semop (first, (struct sembuf *)ptr, second); + case SEMGET: + return sys_semget (first, second, third); + case SEMCTL: { + union semun fourth; + if (!ptr) + return -EINVAL; + if (get_user(fourth.__pad, (void **) ptr)) + return -EFAULT; + return sys_semctl (first, second, third, fourth); + } + case MSGSND: + return sys_msgsnd (first, (struct msgbuf *) ptr, + second, third); + break; + case MSGRCV: + if (!ptr) + return -EINVAL; + if (copy_from_user (&tmp, (struct ipc_kludge *) ptr, + sizeof (struct ipc_kludge))) + return -EFAULT; + return sys_msgrcv (first, tmp.msgp, + second, tmp.msgtyp, third); + case MSGGET: + return sys_msgget ((key_t) first, second); + case MSGCTL: + return sys_msgctl (first, second, (struct msqid_ds *) ptr); + + case SHMAT: { + ulong raddr; + ret = sys_shmat (first, (char *) ptr, second, &raddr); + if (ret) + return ret; + return put_user (raddr, (ulong *) third); + break; + } + case SHMDT: + return sys_shmdt ((char *)ptr); + case SHMGET: + return sys_shmget (first, second, third); + case SHMCTL: + return sys_shmctl (first, second, + (struct shmid_ds *) ptr); + default: + return -EINVAL; + + } + + return -EINVAL; +} + +/* + * Old cruft + */ +asmlinkage int sys_uname(struct old_utsname * name) +{ + int err; + if (!name) + return -EFAULT; + down_read(&uts_sem); + err=copy_to_user(name, &system_utsname, sizeof (*name)); + up_read(&uts_sem); + return err?-EFAULT:0; +} + +asmlinkage int sys_olduname(struct oldold_utsname * name) +{ + int error; + + if (!name) + return -EFAULT; + if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname))) + return -EFAULT; + + down_read(&uts_sem); + + error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN); + error |= __put_user(0,name->sysname+__OLD_UTS_LEN); + error |= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN); + error |= __put_user(0,name->nodename+__OLD_UTS_LEN); + error |= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN); + error |= __put_user(0,name->release+__OLD_UTS_LEN); + error |= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN); + error |= __put_user(0,name->version+__OLD_UTS_LEN); + error |= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN); + error |= __put_user(0,name->machine+__OLD_UTS_LEN); + + up_read(&uts_sem); + + error = error ? -EFAULT : 0; + + return error; +} + +asmlinkage int sys_pause(void) +{ + current->state = TASK_INTERRUPTIBLE; + schedule(); + return -ERESTARTNOHAND; +} + +asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on) +{ + return -ENOSYS; +} + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/time.c linux/arch/s390/kernel/time.c --- v2.3.99-pre7/linux/arch/s390/kernel/time.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/time.c Fri May 12 11:41:45 2000 @@ -0,0 +1,250 @@ +/* + * arch/s390/kernel/time.c + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Hartmut Penner (hp@de.ibm.com), + * Martin Schwidefsky (schwidefsky@de.ibm.com), + * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) + * + * Derived from "arch/i386/kernel/time.c" + * Copyright (C) 1991, 1992, 1995 Linus Torvalds + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include + + +extern volatile unsigned long lost_ticks; + +/* change this if you have some constant time drift */ +#define USECS_PER_JIFFY ((signed long)1000000/HZ) +#define CLK_TICKS_PER_JIFFY ((signed long)USECS_PER_JIFFY<<12) + +#define TICK_SIZE tick + +static uint64_t init_timer_cc, last_timer_cc; + +extern rwlock_t xtime_lock; + +void tod_to_timeval(uint64_t todval, struct timeval *xtime) +{ + const int high_bit = 0x80000000L; + const int c_f4240 = 0xf4240L; + const int c_7a120 = 0x7a120; + /* We have to divide the 64 bit value todval by 4096 + * (because the 2^12 bit is the one that changes every + * microsecond) and then split it into seconds and + * microseconds. A value of max (2^52-1) divided by + * the value 0xF4240 can yield a max result of approx + * (2^32.068). Thats to big to fit into a signed int + * ... hacking time! + */ + asm volatile ("L 2,%1\n\t" + "LR 3,2\n\t" + "SRL 2,12\n\t" + "SLL 3,20\n\t" + "L 4,%O1+4(%R1)\n\t" + "SRL 4,12\n\t" + "OR 3,4\n\t" /* now R2/R3 contain (todval >> 12) */ + "SR 4,4\n\t" + "CL 2,%2\n\t" + "JL .+12\n\t" + "S 2,%2\n\t" + "L 4,%3\n\t" + "D 2,%4\n\t" + "OR 3,4\n\t" + "ST 2,%O0+4(%R0)\n\t" + "ST 3,%0" + : "=m" (*xtime) : "m" (todval), + "m" (c_7a120), "m" (high_bit), "m" (c_f4240) + : "cc", "memory", "2", "3", "4" ); +} + +unsigned long do_gettimeoffset(void) +{ + __u64 timer_cc; + + asm volatile ("STCK %0" : "=m" (timer_cc)); + /* We require the offset from the previous interrupt */ + return ((unsigned long)((timer_cc - last_timer_cc)>>12)); +} + +/* + * This version of gettimeofday has microsecond resolution. + */ +void do_gettimeofday(struct timeval *tv) +{ + extern volatile unsigned long lost_ticks; + unsigned long flags; + unsigned long usec, sec; + + read_lock_irqsave(&xtime_lock, flags); + usec = do_gettimeoffset(); + if (lost_ticks) + usec +=(USECS_PER_JIFFY*lost_ticks); + sec = xtime.tv_sec; + usec += xtime.tv_usec; + read_unlock_irqrestore(&xtime_lock, flags); + + while (usec >= 1000000) { + usec -= 1000000; + sec++; + } + + tv->tv_sec = sec; + tv->tv_usec = usec; +} + +void do_settimeofday(struct timeval *tv) +{ + + write_lock_irq(&xtime_lock); + /* This is revolting. We need to set the xtime.tv_usec + * correctly. However, the value in this location is + * is value at the last tick. + * Discover what correction gettimeofday + * would have done, and then undo it! + */ + tv->tv_usec -= do_gettimeoffset(); + + while (tv->tv_usec < 0) { + tv->tv_usec += 1000000; + tv->tv_sec--; + } + + xtime = *tv; + time_adjust = 0; /* stop active adjtime() */ + time_status |= STA_UNSYNC; + time_maxerror = NTP_PHASE_LIMIT; + time_esterror = NTP_PHASE_LIMIT; + write_unlock_irq(&xtime_lock); +} + +/* + * timer_interrupt() needs to keep up the real-time clock, + * as well as call the "do_timer()" routine every clocktick + */ + +#ifdef CONFIG_SMP +extern __u16 boot_cpu_addr; +#endif + +void do_timer_interrupt(struct pt_regs *regs,int error_code) +{ + unsigned long flags; + + /* + * reset timer to 10ms minus time already elapsed + * since timer-interrupt pending + */ + + save_flags(flags); + cli(); +#ifdef CONFIG_SMP + if(S390_lowcore.cpu_data.cpu_addr==boot_cpu_addr) { + write_lock(&xtime_lock); + last_timer_cc = S390_lowcore.jiffy_timer_cc; + } +#else + last_timer_cc = S390_lowcore.jiffy_timer_cc; +#endif + /* set clock comparator */ + S390_lowcore.jiffy_timer_cc += CLK_TICKS_PER_JIFFY; + asm volatile ("SCKC %0" : : "m" (S390_lowcore.jiffy_timer_cc)); + +/* + * In the SMP case we use the local timer interrupt to do the + * profiling, except when we simulate SMP mode on a uniprocessor + * system, in that case we have to call the local interrupt handler. + */ +#ifdef CONFIG_SMP + /* when SMP, do smp_local_timer_interrupt for *all* CPUs, + but only do the rest for the boot CPU */ + smp_local_timer_interrupt(regs); +#else + if (!user_mode(regs)) + s390_do_profile(regs->psw.addr); +#endif + +#ifdef CONFIG_SMP + if(S390_lowcore.cpu_data.cpu_addr==boot_cpu_addr) +#endif + { + do_timer(regs); +#ifdef CONFIG_SMP + write_unlock(&xtime_lock); +#endif + } + restore_flags(flags); + +} + +/* + * Start the clock comparator on the current CPU + */ +static long cr0 __attribute__ ((aligned (8))); + +void init_100hz_timer(void) +{ + /* allow clock comparator timer interrupt */ + asm volatile ("STCTL 0,0,%0" : "=m" (cr0) : : "memory"); + cr0 |= 0x800; + asm volatile ("LCTL 0,0,%0" : : "m" (cr0) : "memory"); + /* set clock comparator */ + /* read the TOD clock */ + asm volatile ("STCK %0" : "=m" (S390_lowcore.jiffy_timer_cc)); + S390_lowcore.jiffy_timer_cc += CLK_TICKS_PER_JIFFY; + asm volatile ("SCKC %0" : : "m" (S390_lowcore.jiffy_timer_cc)); +} + +/* + * Initialize the TOD clock and the CPU timer of + * the boot cpu. + */ +void __init time_init(void) +{ + int cc; + + /* kick the TOD clock */ + asm volatile ("STCK %1\n\t" + "IPM %0\n\t" + "SRL %0,28" : "=r" (cc), "=m" (init_timer_cc)); + switch (cc) { + case 0: /* clock in set state: all is fine */ + break; + case 1: /* clock in non-set state: FIXME */ + printk("time_init: TOD clock in non-set state\n"); + break; + case 2: /* clock in error state: FIXME */ + printk("time_init: TOD clock in error state\n"); + break; + case 3: /* clock in stopped or not-operational state: FIXME */ + printk("time_init: TOD clock stopped/non-operational\n"); + break; + } + init_100hz_timer(); + init_timer_cc = S390_lowcore.jiffy_timer_cc; + init_timer_cc -= 0x8126d60e46000000LL - + (0x3c26700LL*1000000*4096); + tod_to_timeval(init_timer_cc, &xtime); +} diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/traps.c linux/arch/s390/kernel/traps.c --- v2.3.99-pre7/linux/arch/s390/kernel/traps.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/kernel/traps.c Fri May 12 11:41:45 2000 @@ -0,0 +1,480 @@ +/* + * arch/s390/kernel/traps.c + * + * S390 version + * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), + * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), + * + * Derived from "arch/i386/kernel/traps.c" + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* + * 'Traps.c' handles hardware traps and faults after we have saved some + * state in 'asm.s'. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#if CONFIG_REMOTE_DEBUG +#include +#endif + +/* Called from entry.S only */ +extern void handle_per_exception(struct pt_regs *regs); + +typedef void pgm_check_handler_t(struct pt_regs *, long); +pgm_check_handler_t *pgm_check_table[128]; + +extern pgm_check_handler_t default_trap_handler; +extern pgm_check_handler_t do_page_fault; + +asmlinkage int system_call(void); + +static inline void console_verbose(void) +{ + extern int console_loglevel; + console_loglevel = 15; +} + +#define DO_ERROR(trapnr, signr, str, name, tsk) \ +asmlinkage void name(struct pt_regs * regs, long error_code) \ +{ \ + tsk->thread.error_code = error_code; \ + tsk->thread.trap_no = trapnr; \ + die_if_no_fixup(str,regs,error_code); \ + force_sig(signr, tsk); \ +} + + +void page_exception(void); + +/* TODO: define these as 'pgm_check_handler_t xxx;' +asmlinkage void divide_error(void); +asmlinkage void debug(void); +asmlinkage void nmi(void); +asmlinkage void int3(void); +asmlinkage void overflow(void); +asmlinkage void bounds(void); +asmlinkage void invalid_op(void); +asmlinkage void device_not_available(void); +asmlinkage void double_fault(void); +asmlinkage void coprocessor_segment_overrun(void); +asmlinkage void invalid_TSS(void); +asmlinkage void segment_not_present(void); +asmlinkage void stack_segment(void); +asmlinkage void general_protection(void); +asmlinkage void coprocessor_error(void); +asmlinkage void reserved(void); +asmlinkage void alignment_check(void); +asmlinkage void spurious_interrupt_bug(void); +*/ + +int kstack_depth_to_print = 24; + +/* + * These constants are for searching for possible module text + * segments. VMALLOC_OFFSET comes from mm/vmalloc.c; MODULE_RANGE is + * a guess of how much space is likely to be vmalloced. + */ +#define VMALLOC_OFFSET (8*1024*1024) +#define MODULE_RANGE (8*1024*1024) + +void show_crashed_task_info(void) +{ + printk("CPU: %d\n",smp_processor_id()); + printk("Process %s (pid: %d, stackpage=%08X)\n", + current->comm, current->pid, 4096+(addr_t)current); + show_regs(current,NULL,NULL); +} +#if 0 +static void show_registers(struct pt_regs *regs) +{ + printk("CPU: %d\nPSW: %08lx %08lx\n", + smp_processor_id(), (unsigned long) regs->psw.mask, + (unsigned long) regs->psw.addr); + printk("GPRS:\n"); + + printk("%08lx %08lx %08lx %08lx\n", + regs->gprs[0], regs->gprs[1], + regs->gprs[2], regs->gprs[3]); + printk("%08lx %08lx %08lx %08lx\n", + regs->gprs[4], regs->gprs[5], + regs->gprs[6], regs->gprs[7]); + printk("%08lx %08lx %08lx %08lx\n", + regs->gprs[8], regs->gprs[9], + regs->gprs[10], regs->gprs[11]); + printk("%08lx %08lx %08lx %08lx\n", + regs->gprs[12], regs->gprs[13], + regs->gprs[14], regs->gprs[15]); + printk("Process %s (pid: %d, stackpage=%08lx)\nStack: ", + current->comm, current->pid, 4096+(unsigned long)current); +/* + stack = (unsigned long *) esp; + for(i=0; i < kstack_depth_to_print; i++) { + if (((long) stack & 4095) == 0) + break; + if (i && ((i % 8) == 0)) + printk("\n "); + printk("%08lx ", get_seg_long(ss,stack++)); + } + printk("\nCall Trace: "); + stack = (unsigned long *) esp; + i = 1; + module_start = PAGE_OFFSET + (max_mapnr << PAGE_SHIFT); + module_start = ((module_start + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)); + module_end = module_start + MODULE_RANGE; + while (((long) stack & 4095) != 0) { + addr = get_seg_long(ss, stack++); */ + /* + * If the address is either in the text segment of the + * kernel, or in the region which contains vmalloc'ed + * memory, it *may* be the address of a calling + * routine; if so, print it so that someone tracing + * down the cause of the crash will be able to figure + * out the call path that was taken. + */ +/* if (((addr >= (unsigned long) &_stext) && + (addr <= (unsigned long) &_etext)) || + ((addr >= module_start) && (addr <= module_end))) { + if (i && ((i % 8) == 0)) + printk("\n "); + printk("[<%08lx>] ", addr); + i++; + } + } + printk("\nCode: "); + for(i=0;i<20;i++) + printk("%02x ",0xff & get_seg_byte(regs->xcs & 0xffff,(i+(char *)regs->eip))); + printk("\n"); +*/ +} +#endif + + +spinlock_t die_lock; + +void die(const char * str, struct pt_regs * regs, long err) +{ + console_verbose(); + spin_lock_irq(&die_lock); + printk("%s: %04lx\n", str, err & 0xffff); + show_crashed_task_info(); + spin_unlock_irq(&die_lock); + do_exit(SIGSEGV); +} + +int check_for_fixup(struct pt_regs * regs) +{ + if (!(regs->psw.mask & PSW_PROBLEM_STATE)) { + unsigned long fixup; + fixup = search_exception_table(regs->psw.addr); + if (fixup) { + regs->psw.addr = fixup; + return 1; + } + } + return 0; +} + +int do_debugger_trap(struct pt_regs *regs,int signal) +{ + if(regs->psw.mask&PSW_PROBLEM_STATE) + { + if(current->flags & PF_PTRACED) + force_sig(signal,current); + else + return 1; + } + else + { +#if CONFIG_REMOTE_DEBUG + if(gdb_stub_initialised) + { + gdb_stub_handle_exception((gdb_pt_regs *)regs,signal); + return 0; + } +#endif + return 1; + } + return 0; +} + +static void die_if_no_fixup(const char * str, struct pt_regs * regs, long err) +{ + if (!(regs->psw.mask & PSW_PROBLEM_STATE)) { + unsigned long fixup; + fixup = search_exception_table(regs->psw.addr); + if (fixup) { + regs->psw.addr = fixup; + return; + } + die(str, regs, err); + } +} + +asmlinkage void default_trap_handler(struct pt_regs * regs, long error_code) +{ + current->thread.error_code = error_code; + current->thread.trap_no = error_code; + die_if_no_fixup("Unknown program exception",regs,error_code); + force_sig(SIGSEGV, current); +} + +DO_ERROR(2, SIGILL, "privileged operation", privileged_op, current) +DO_ERROR(3, SIGILL, "execute exception", execute_exception, current) +DO_ERROR(5, SIGSEGV, "addressing exception", addressing_exception, current) +DO_ERROR(9, SIGFPE, "fixpoint divide exception", divide_exception, current) +DO_ERROR(0x12, SIGILL, "translation exception", translation_exception, current) +DO_ERROR(0x13, SIGILL, "special operand exception", special_op_exception, current) +DO_ERROR(0x15, SIGILL, "operand exception", operand_exception, current) + +/* need to define +DO_ERROR( 6, SIGILL, "invalid operand", invalid_op, current) +DO_ERROR( 8, SIGSEGV, "double fault", double_fault, current) +DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun, last_task_used_math) +DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS, current) +DO_ERROR(11, SIGBUS, "segment not present", segment_not_present, current) +DO_ERROR(12, SIGBUS, "stack segment", stack_segment, current) +DO_ERROR(17, SIGSEGV, "alignment check", alignment_check, current) +DO_ERROR(18, SIGSEGV, "reserved", reserved, current) +DO_ERROR(19, SIGSEGV, "cache flush denied", cache_flush_denied, current) +*/ + +#ifdef CONFIG_IEEEFPU_EMULATION + +asmlinkage void illegal_op(struct pt_regs * regs, long error_code) +{ + __u8 opcode[6]; + __u16 *location; + int do_sig = 0; + int problem_state=(regs->psw.mask & PSW_PROBLEM_STATE); + + lock_kernel(); + location = (__u16 *)(regs->psw.addr-S390_lowcore.pgm_ilc); + if(problem_state) + get_user(*((__u16 *) opcode), location); + else + *((__u16 *)opcode)=*((__u16 *)location); + if(*((__u16 *)opcode)==S390_BREAKPOINT_U16) + { + if(do_debugger_trap(regs,SIGTRAP)) + do_sig=1; + } + else if (problem_state ) + { + if (opcode[0] == 0xb3) { + get_user(*((__u16 *) (opcode+2)), location+1); + do_sig = math_emu_b3(opcode, regs); + } else if (opcode[0] == 0xed) { + get_user(*((__u32 *) (opcode+2)), + (__u32 *)(location+1)); + do_sig = math_emu_ed(opcode, regs); + } else if (*((__u16 *) opcode) == 0xb299) { + get_user(*((__u16 *) (opcode+2)), location+1); + do_sig = math_emu_srnm(opcode, regs); + } else if (*((__u16 *) opcode) == 0xb29c) { + get_user(*((__u16 *) (opcode+2)), location+1); + do_sig = math_emu_stfpc(opcode, regs); + } else if (*((__u16 *) opcode) == 0xb29d) { + get_user(*((__u16 *) (opcode+2)), location+1); + do_sig = math_emu_lfpc(opcode, regs); + } else + do_sig = 1; + } else + do_sig = 1; + if (do_sig) { + current->thread.error_code = error_code; + current->thread.trap_no = 1; + force_sig(SIGILL, current); + die_if_no_fixup("illegal operation", regs, error_code); + } + unlock_kernel(); +} + +asmlinkage void specification_exception(struct pt_regs * regs, long error_code) +{ + __u8 opcode[6]; + __u16 *location; + int do_sig = 0; + + lock_kernel(); + if (regs->psw.mask & 0x00010000L) { + location = (__u16 *)(regs->psw.addr-S390_lowcore.pgm_ilc); + get_user(*((__u16 *) opcode), location); + switch (opcode[0]) { + case 0x28: /* LDR Rx,Ry */ + math_emu_ldr(opcode); + break; + case 0x38: /* LER Rx,Ry */ + math_emu_ler(opcode); + break; + case 0x60: /* STD R,D(X,B) */ + get_user(*((__u16 *) (opcode+2)), location+1); + math_emu_std(opcode, regs); + break; + case 0x68: /* LD R,D(X,B) */ + get_user(*((__u16 *) (opcode+2)), location+1); + math_emu_ld(opcode, regs); + break; + case 0x70: /* STE R,D(X,B) */ + get_user(*((__u16 *) (opcode+2)), location+1); + math_emu_ste(opcode, regs); + break; + case 0x78: /* LE R,D(X,B) */ + get_user(*((__u16 *) (opcode+2)), location+1); + math_emu_le(opcode, regs); + break; + default: + do_sig = 1; + break; + } + } else + do_sig = 1; + if (do_sig) { + current->thread.error_code = error_code; + current->thread.trap_no = 1; + force_sig(SIGILL, current); + die_if_no_fixup("illegal operation", regs, error_code); + } + unlock_kernel(); +} + +asmlinkage void data_exception(struct pt_regs * regs, long error_code) +{ + __u8 opcode[6]; + __u16 *location; + int do_sig = 0; + + lock_kernel(); + if (regs->psw.mask & 0x00010000L) { + location = (__u16 *)(regs->psw.addr-S390_lowcore.pgm_ilc); + get_user(*((__u16 *) opcode), location); + switch (opcode[0]) { + case 0x28: /* LDR Rx,Ry */ + math_emu_ldr(opcode); + break; + case 0x38: /* LER Rx,Ry */ + math_emu_ler(opcode); + break; + case 0x60: /* STD R,D(X,B) */ + get_user(*((__u16 *) (opcode+2)), location+1); + math_emu_std(opcode, regs); + break; + case 0x68: /* LD R,D(X,B) */ + get_user(*((__u16 *) (opcode+2)), location+1); + math_emu_ld(opcode, regs); + break; + case 0x70: /* STE R,D(X,B) */ + get_user(*((__u16 *) (opcode+2)), location+1); + math_emu_ste(opcode, regs); + break; + case 0x78: /* LE R,D(X,B) */ + get_user(*((__u16 *) (opcode+2)), location+1); + math_emu_le(opcode, regs); + break; + case 0xb3: + get_user(*((__u16 *) (opcode+2)), location+1); + do_sig = math_emu_b3(opcode, regs); + break; + case 0xed: + get_user(*((__u32 *) (opcode+2)), + (__u32 *)(location+1)); + do_sig = math_emu_ed(opcode, regs); + break; + case 0xb2: + if (opcode[1] == 0x99) { + get_user(*((__u16 *) (opcode+2)), location+1); + do_sig = math_emu_srnm(opcode, regs); + } else if (opcode[1] == 0x9c) { + get_user(*((__u16 *) (opcode+2)), location+1); + do_sig = math_emu_stfpc(opcode, regs); + } else if (opcode[1] == 0x9d) { + get_user(*((__u16 *) (opcode+2)), location+1); + do_sig = math_emu_lfpc(opcode, regs); + } else + do_sig = 1; + break; + default: + do_sig = 1; + break; + } + } else + do_sig = 1; + if (do_sig) { + current->thread.error_code = error_code; + current->thread.trap_no = 1; + force_sig(SIGILL, current); + die_if_no_fixup("illegal operation", regs, error_code); + } + unlock_kernel(); +} + +#else +DO_ERROR(1, SIGILL, "illegal operation", illegal_op, current) +DO_ERROR(6, SIGILL, "specification exception", specification_exception, current) +DO_ERROR(7, SIGILL, "data exception", data_exception, current) +#endif /* CONFIG_IEEEFPU_EMULATION */ + + +/* init is done in lowcore.S and head.S */ + +void __init trap_init(void) +{ + int i; + + for (i = 0; i < 128; i++) + pgm_check_table[i] = &default_trap_handler; + pgm_check_table[1] = &illegal_op; + pgm_check_table[2] = &privileged_op; + pgm_check_table[3] = &execute_exception; + pgm_check_table[5] = &addressing_exception; + pgm_check_table[6] = &specification_exception; + pgm_check_table[7] = &data_exception; + pgm_check_table[9] = ÷_exception; + pgm_check_table[0x12] = &translation_exception; + pgm_check_table[0x13] = &special_op_exception; + pgm_check_table[0x15] = &operand_exception; + pgm_check_table[4] = &do_page_fault; + pgm_check_table[0x10] = &do_page_fault; + pgm_check_table[0x11] = &do_page_fault; + pgm_check_table[0x1C] = &privileged_op; +} + + +void handle_per_exception(struct pt_regs *regs) +{ + if(regs->psw.mask&PSW_PROBLEM_STATE) + { + per_struct *per_info=¤t->thread.per_info; + per_info->lowcore.words.perc_atmid=S390_lowcore.per_perc_atmid; + per_info->lowcore.words.address=S390_lowcore.per_address; + per_info->lowcore.words.access_id=S390_lowcore.per_access_id; + } + if(do_debugger_trap(regs,SIGTRAP)) + { + /* I've seen this possibly a task structure being reused ? */ + printk("Spurious per exception detected\n"); + printk("switching off per tracing for this task.\n"); + show_crashed_task_info(); + /* Hopefully switching off per tracing will help us survive */ + regs->psw.mask &= ~PSW_PER_MASK; + } +} + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/lib/Makefile linux/arch/s390/lib/Makefile --- v2.3.99-pre7/linux/arch/s390/lib/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/lib/Makefile Fri May 12 11:41:45 2000 @@ -0,0 +1,12 @@ +# +# Makefile for s390-specific library files.. +# + +.S.o: + $(CC) $(AFLAGS) -traditional -c $< -o $*.o + +L_TARGET = lib.a +L_OBJS = checksum.o delay.o memset.o strcmp.o strncpy.o + +include $(TOPDIR)/Rules.make + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/lib/checksum.c linux/arch/s390/lib/checksum.c --- v2.3.99-pre7/linux/arch/s390/lib/checksum.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/lib/checksum.c Fri May 12 11:41:45 2000 @@ -0,0 +1,56 @@ +/* + * arch/s390/lib/checksum.c + * S390 fast network checksum routines + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Ulrich Hild (first version), + * Martin Schwidefsky (schwidefsky@de.ibm.com), + * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), + * + * This file contains network checksum routines + */ + +#include +#include +#include +#include +#include + +/* + * computes a partial checksum, e.g. for TCP/UDP fragments + */ +unsigned int +csum_partial (const unsigned char *buff, int len, unsigned int sum) +{ + /* + * Experiments with ethernet and slip connections show that buff + * is aligned on either a 2-byte or 4-byte boundary. + */ + __asm__ __volatile__ ( + " lr 2,%1\n" /* address in gpr 2 */ + " lr 3,%2\n" /* length in gpr 3 */ + "0: cksm %0,2\n" /* do checksum on longs */ + " jo 0b\n" + : "+&d" (sum) + : "d" (buff), "d" (len) + : "cc", "2", "3" ); + return sum; +} + +/* + * Fold a partial checksum without adding pseudo headers + */ +unsigned short csum_fold(unsigned int sum) +{ + __asm__ __volatile__ ( + " sr 3,3\n" /* %0 = H*65536 + L */ + " lr 2,%0\n" /* %0 = H L, R2/R3 = H L / 0 0 */ + " srdl 2,16\n" /* %0 = H L, R2/R3 = 0 H / L 0 */ + " alr 2,3\n" /* %0 = H L, R2/R3 = L H / L 0 */ + " alr %0,2\n" /* %0 = H+L+C L+H */ + " srl %0,16\n" /* %0 = H+L+C */ + : "+d" (sum) : : "cc", "2", "3"); + return ((unsigned short) ~sum); +} + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/lib/delay.c linux/arch/s390/lib/delay.c --- v2.3.99-pre7/linux/arch/s390/lib/delay.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/lib/delay.c Fri May 12 11:41:45 2000 @@ -0,0 +1,45 @@ +/* + * arch/s390/kernel/delay.c + * Precise Delay Loops for S390 + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), + * + * Derived from "arch/i386/lib/delay.c" + * Copyright (C) 1993 Linus Torvalds + * Copyright (C) 1997 Martin Mares + */ + +#include +#include +#include + +#ifdef CONFIG_SMP +#include +#endif + +void __delay(unsigned long loops) +{ + __asm__ __volatile__( + "0: ahi %0,-1\n" + " jnm 0b" + : /* no outputs */ : "r" (loops) ); +} + +inline void __const_udelay(unsigned long xloops) +{ + + __asm__("LR 3,%1\n\t" + "MR 2,%2\n\t" + "LR %0,2\n\t" + : "=r" (xloops) + : "r" (xloops) , "r" (loops_per_sec) + : "2" , "3"); + __delay(xloops); +} + +void __udelay(unsigned long usecs) +{ + __const_udelay(usecs * 0x000010c6); /* 2**32 / 1000000 */ +} diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/lib/memset.S linux/arch/s390/lib/memset.S --- v2.3.99-pre7/linux/arch/s390/lib/memset.S Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/lib/memset.S Fri May 12 11:41:45 2000 @@ -0,0 +1,30 @@ +/* + * arch/s390/lib/memset.S + * S390 fast memset routine + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), + */ + +/* + * R2 = address to memory area + * R3 = byte to fill memory with + * R4 = number of bytes to fill + */ + .globl memset +memset: + LTR 4,4 + JZ memset_end + LR 0,2 # save pointer to memory area + LR 1,3 # move pad byte to R1 + LR 3,4 + SR 4,4 # no source for MVCLE, only a pad byte + SR 5,5 + MVCLE 2,4,0(1) # thats it, MVCLE is your friend + JO .-4 + LR 2,0 # return pointer to mem. +memset_end: + BR 14 + + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/lib/strcmp.S linux/arch/s390/lib/strcmp.S --- v2.3.99-pre7/linux/arch/s390/lib/strcmp.S Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/lib/strcmp.S Fri May 12 11:41:45 2000 @@ -0,0 +1,27 @@ +/* + * arch/s390/lib/strcmp.S + * S390 strcmp routine + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), + */ + +/* + * R2 = address of compare string + * R3 = address of test string + */ + .globl strcmp +strcmp: + SR 0,0 + SR 1,1 + CLST 2,3 + JO .-4 + JE strcmp_equal + IC 0,0(0,3) + IC 1,0(0,2) + SR 1,0 +strcmp_equal: + LR 2,1 + BR 14 + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/lib/strncpy.S linux/arch/s390/lib/strncpy.S --- v2.3.99-pre7/linux/arch/s390/lib/strncpy.S Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/lib/strncpy.S Fri May 12 11:41:45 2000 @@ -0,0 +1,30 @@ +/* + * arch/s390/kernel/strncpy.S + * S390 strncpy routine + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), + */ + +/* + * R2 = address of destination + * R3 = address of source string + * R4 = max number of bytes to copy + */ + .globl strncpy +strncpy: + LR 1,2 # don't touch address in R2 + LTR 4,4 + JZ strncpy_exit # 0 bytes -> nothing to do + SR 0,0 +strncpy_loop: + ICM 0,1,0(3) # ICM sets the cc, IC does not + LA 3,1(0,3) + STC 0,0(0,1) + LA 1,1(0,1) + JZ strncpy_exit # ICM inserted a 0x00 + BRCT 4,strncpy_loop # R4 -= 1, jump to strncpy_loop if > 0 +strncpy_exit: + BR 14 + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/mm/Makefile linux/arch/s390/mm/Makefile --- v2.3.99-pre7/linux/arch/s390/mm/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/mm/Makefile Fri May 12 11:41:45 2000 @@ -0,0 +1,13 @@ +# +# Makefile for the linux i386-specific parts of the memory manager. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definition is now in the main makefile... + +O_TARGET := mm.o +O_OBJS := init.o fault.o ioremap.o extable.o + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/mm/extable.c linux/arch/s390/mm/extable.c --- v2.3.99-pre7/linux/arch/s390/mm/extable.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/mm/extable.c Fri May 12 11:41:45 2000 @@ -0,0 +1,63 @@ +/* + * arch/s390/mm/extable.c + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Hartmut Penner (hp@de.ibm.com) + * + * Derived from "arch/i386/mm/extable.c" + */ + +#include +#include +#include + +extern const struct exception_table_entry __start___ex_table[]; +extern const struct exception_table_entry __stop___ex_table[]; + +static inline unsigned long +search_one_table(const struct exception_table_entry *first, + const struct exception_table_entry *last, + unsigned long value) +{ + while (first <= last) { + const struct exception_table_entry *mid; + long diff; + + mid = (last - first) / 2 + first; + diff = mid->insn - value; + if (diff == 0) + return mid->fixup; + else if (diff < 0) + first = mid+1; + else + last = mid-1; + } + return 0; +} + +unsigned long +search_exception_table(unsigned long addr) +{ + unsigned long ret; + +#ifndef CONFIG_MODULES + addr &= 0x7fffffff; /* remove amode bit from address */ + /* There is only the kernel to search. */ + ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr); + if (ret) return FIX_PSW(ret); +#else + /* The kernel is the last "module" -- no need to treat it special. */ + struct module *mp; + addr &= 0x7fffffff; /* remove amode bit from address */ + for (mp = module_list; mp != NULL; mp = mp->next) { + if (mp->ex_table_start == NULL) + continue; + ret = search_one_table(mp->ex_table_start, + mp->ex_table_end - 1, addr); + if (ret) return FIX_PSW(ret); + } +#endif + + return 0; +} diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/mm/fault.c linux/arch/s390/mm/fault.c --- v2.3.99-pre7/linux/arch/s390/mm/fault.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/mm/fault.c Fri May 12 11:41:45 2000 @@ -0,0 +1,203 @@ +/* + * arch/s390/mm/fault.c + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Hartmut Penner (hp@de.ibm.com) + * + * Derived from "arch/i386/mm/fault.c" + * Copyright (C) 1995 Linus Torvalds + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +extern void die(const char *,struct pt_regs *,long); + +/* + * This routine handles page faults. It determines the address, + * and the problem, and then passes it off to one of the appropriate + * routines. + * + * error_code: + * ****0004 Protection -> Write-Protection (suprression) + * ****0010 Segment translation -> Not present (nullification) + * ****0011 Page translation -> Not present (nullification) + */ +asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) +{ + struct task_struct *tsk; + struct mm_struct *mm; + struct vm_area_struct * vma; + unsigned long address; + unsigned long fixup; + int write; + unsigned long psw_mask; + unsigned long psw_addr; + + /* + * get psw mask of Program old psw to find out, + * if user or kernel mode + */ + + psw_mask = S390_lowcore.program_old_psw.mask; + psw_addr = S390_lowcore.program_old_psw.addr; + + /* + * get the failing address + * more specific the segment and page table portion of + * the address + */ + + address = S390_lowcore.trans_exc_code&0x7ffff000; + + if (atomic_read(&S390_lowcore.local_irq_count)) + die("page fault from irq handler",regs,error_code); + + tsk = current; + mm = tsk->mm; + + down(&mm->mmap_sem); + + vma = find_vma(mm, address); + if (!vma) { + printk("no vma for address %lX\n",address); + goto bad_area; + } + if (vma->vm_start <= address) + goto good_area; + if (!(vma->vm_flags & VM_GROWSDOWN)) { + printk("VM_GROWSDOWN not set, but address %lX \n",address); + printk("not in vma %p (start %lX end %lX)\n",vma, + vma->vm_start,vma->vm_end); + goto bad_area; + } + if (expand_stack(vma, address)) { + printk("expand of vma failed address %lX\n",address); + printk("vma %p (start %lX end %lX)\n",vma, + vma->vm_start,vma->vm_end); + goto bad_area; + } +/* + * Ok, we have a good vm_area for this memory access, so + * we can handle it.. + */ +good_area: + write = 0; + switch (error_code & 0xFF) { + case 0x04: /* write, present*/ + write = 1; + break; + case 0x10: /* not present*/ + case 0x11: /* not present*/ + if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))) { + printk("flags %X of vma for address %lX wrong \n", + vma->vm_flags,address); + printk("vma %p (start %lX end %lX)\n",vma, + vma->vm_start,vma->vm_end); + goto bad_area; + } + break; + default: + printk("code should be 4, 10 or 11 (%lX) \n",error_code&0xFF); + goto bad_area; + } + handle_mm_fault(tsk, vma, address, write); + + up(&mm->mmap_sem); + return; + +/* + * Something tried to access memory that isn't in our memory map.. + * Fix it, but check if it's kernel or user first.. + */ +bad_area: + up(&mm->mmap_sem); + + /* User mode accesses just cause a SIGSEGV */ + if (psw_mask & PSW_PROBLEM_STATE) { + tsk->thread.prot_addr = address; + tsk->thread.error_code = error_code; + tsk->thread.trap_no = 14; + + printk("User process fault: interruption code 0x%lX\n",error_code); + printk("failing address: %lX\n",address); + show_crashed_task_info(); + force_sig(SIGSEGV, tsk); + return; + } + + /* Are we prepared to handle this kernel fault? */ + + if ((fixup = search_exception_table(regs->psw.addr)) != 0) { + regs->psw.addr = fixup; + return; + } + +/* + * Oops. The kernel tried to access some bad page. We'll have to + * terminate things with extreme prejudice. + * + * First we check if it was the bootup rw-test, though.. + */ + if (address < PAGE_SIZE) + printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference"); + else + printk(KERN_ALERT "Unable to handle kernel paging request"); + printk(" at virtual address %08lx\n",address); +/* + * need to define, which information is useful here + */ + + lock_kernel(); + die("Oops", regs, error_code); + do_exit(SIGKILL); + unlock_kernel(); +} + +/* + { + char c; + int i,j; + char *addr; + addr = ((char*) psw_addr)-0x20; + for (i=0;i<16;i++) { + if (i == 2) + printk("\n"); + printk ("%08X: ",(unsigned long) addr); + for (j=0;j<4;j++) { + printk("%08X ",*(unsigned long*)addr); + addr += 4; + } + addr -=0x10; + printk(" | "); + for (j=0;j<16;j++) { + printk("%c",(c=*addr++) < 0x20 ? '.' : c ); + } + + printk("\n"); + } + printk("\n"); + } + +*/ + + + + + + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/mm/init.c linux/arch/s390/mm/init.c --- v2.3.99-pre7/linux/arch/s390/mm/init.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/mm/init.c Fri May 12 11:41:45 2000 @@ -0,0 +1,385 @@ +/* + * arch/s390/mm/init.c + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Hartmut Penner (hp@de.ibm.com) + * + * Derived from "arch/i386/mm/init.c" + * Copyright (C) 1995 Linus Torvalds + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_BLK_DEV_INITRD +#include +#endif +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +static unsigned long totalram_pages = 0; + +/* + * BAD_PAGE is the page that is used for page faults when linux + * is out-of-memory. Older versions of linux just did a + * do_exit(), but using this instead means there is less risk + * for a process dying in kernel mode, possibly leaving an inode + * unused etc.. + * + * BAD_PAGETABLE is the accompanying page-table: it is initialized + * to point to BAD_PAGE entries. + * + * ZERO_PAGE is a special page that is used for zero-initialized + * data and COW. + */ + +pgd_t swapper_pg_dir[512] __attribute__ ((__aligned__ (4096))); +unsigned long empty_bad_page[1024] __attribute__ ((__aligned__ (4096))); +unsigned long empty_zero_page[1024] __attribute__ ((__aligned__ (4096))); +pte_t empty_bad_pte_table[1024] __attribute__ ((__aligned__ (4096))); + +static int test_access(unsigned long loc) +{ + static const int ssm_mask = 0x07000000L; + int rc, i; + + rc = 0; + for (i=0; i<4; i++) { + __asm__ __volatile__( + " slr %0,%0\n" + " ssm %1\n" + " tprot 0(%2),0\n" + "0: jne 1f\n" + " lhi %0,1\n" + "1: ssm %3\n" + ".section __ex_table,\"a\"\n" + " .align 4\n" + " .long 0b,1b\n" + ".previous" + : "+&d" (rc) : "i" (0), "a" (loc), "m" (ssm_mask) + : "cc"); + if (rc == 0) + break; + loc += 0x100000; + } + return rc; +} + +static pte_t * get_bad_pte_table(void) +{ + pte_t v; + int i; + + v = pte_mkdirty(mk_pte_phys(__pa(empty_bad_page), PAGE_SHARED)); + + for (i = 0; i < PAGE_SIZE/sizeof(pte_t); i++) + empty_bad_pte_table[i] = v; + + return empty_bad_pte_table; +} + +static inline void invalidate_page(pte_t *pte) +{ + int i; + for (i=0;i high) { + do { + if(pgd_quicklist) + free_pgd_slow(get_pgd_fast()), freed++; + if(pmd_quicklist) + free_pmd_slow(get_pmd_fast()), freed++; + if(pte_quicklist) + free_pte_slow(get_pte_fast()), freed++; + } while(pgtable_cache_size > low); + } + return freed; +} + +void show_mem(void) +{ + int i,free = 0,total = 0,reserved = 0; + int shared = 0, cached = 0; + + printk("Mem-info:\n"); + show_free_areas(); + printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); + i = max_mapnr; + while (i-- > 0) { + total++; + if (PageReserved(mem_map+i)) + reserved++; + else if (PageSwapCache(mem_map+i)) + cached++; + else if (!atomic_read(&mem_map[i].count)) + free++; + else + shared += atomic_read(&mem_map[i].count) - 1; + } + printk("%d pages of RAM\n",total); + printk("%d reserved pages\n",reserved); + printk("%d pages shared\n",shared); + printk("%d pages swap cached\n",cached); + printk("%ld pages in page table cache\n",pgtable_cache_size); + show_buffers(); +} + +/* References to section boundaries */ + +extern unsigned long _text; +extern unsigned long _etext; +extern unsigned long _edata; +extern unsigned long __bss_start; +extern unsigned long _end; + +extern unsigned long __init_begin; +extern unsigned long __init_end; + +/* + * paging_init() sets up the page tables - note that the first 4MB are + * already mapped by head.S. + * paging_init will erase this initial mapping + */ + +unsigned long last_valid_pfn; + +void __init paging_init(void) +{ + pgd_t * pg_dir; + pte_t * pg_table; + pte_t pte; + int i; + unsigned long tmp; + unsigned long address=0; + unsigned long pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERNSEG_TABLE; + unsigned long end_mem = (unsigned long) __va(max_low_pfn*PAGE_SIZE); + + /* unmap whole virtual address space */ + + pg_dir = swapper_pg_dir; + + for (i=0;ipgd0 = (_PAGE_TABLE | __pa(pg_table)); + pg_dir->pgd1 = (_PAGE_TABLE | (__pa(pg_table)+1024)); + pg_dir->pgd2 = (_PAGE_TABLE | (__pa(pg_table)+2048)); + pg_dir->pgd3 = (_PAGE_TABLE | (__pa(pg_table)+3072)); + pg_dir++; + + for (tmp = 0 ; tmp < PTRS_PER_PTE ; tmp++,pg_table++) { + pte = mk_pte_phys(address, PAGE_KERNEL); + if (address >= end_mem) + pte_clear(&pte); + set_pte(pg_table, pte); + address += PAGE_SIZE; + } + } + + /* enable virtual mapping in kernel mode */ + __asm__ __volatile__(" LCTL 1,1,%0\n" + " LCTL 7,7,%0\n" + " LCTL 13,13,%0" + : :"m" (pgdir_k)); + + local_flush_tlb(); + + { + unsigned long zones_size[MAX_NR_ZONES] = { 0, 0, 0}; + + zones_size[ZONE_DMA] = max_low_pfn; + free_area_init(zones_size); + } + + return; +} + +void __init mem_init(void) +{ + int codesize, reservedpages, datasize, initsize; + int tmp; + + max_mapnr = num_physpages = max_low_pfn; + high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); + + /* clear the zero-page */ + memset(empty_zero_page, 0, PAGE_SIZE); + + /* this will put all low memory onto the freelists */ + totalram_pages += free_all_bootmem(); + + /* mark usable pages in the mem_map[] and count reserved pages */ + reservedpages = 0; + tmp = 0; + do { + if (tmp && (tmp & 0x3ff) == 0 && + test_access(tmp * PAGE_SIZE) == 0) { + printk("4M Segment %lX not available\n",tmp*PAGE_SIZE); + do { + set_bit(PG_reserved, &mem_map[tmp].flags); + reservedpages++; + tmp++; + } while (tmp < max_low_pfn && (tmp & 0x3ff)); + } else { + if (PageReserved(mem_map+tmp)) + reservedpages++; + tmp++; + } + } while (tmp < max_low_pfn); + + codesize = (unsigned long) &_etext - (unsigned long) &_text; + datasize = (unsigned long) &_edata - (unsigned long) &_etext; + initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; + printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n", + (unsigned long) nr_free_pages() << (PAGE_SHIFT-10), + max_mapnr << (PAGE_SHIFT-10), + codesize >> 10, + reservedpages << (PAGE_SHIFT-10), + datasize >>10, + initsize >> 10); +} + +void free_initmem(void) +{ + unsigned long addr; + + addr = (unsigned long)(&__init_begin); + for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { + ClearPageReserved(mem_map + MAP_NR(addr)); + set_page_count(mem_map+MAP_NR(addr), 1); + free_page(addr); + totalram_pages++; + } + printk ("Freeing unused kernel memory: %dk freed\n", + (&__init_end - &__init_begin) >> 10); +} + +#ifdef CONFIG_BLK_DEV_INITRD +void free_initrd_mem(unsigned long start, unsigned long end) +{ + if (start < end) + printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); + for (; start < end; start += PAGE_SIZE) { + ClearPageReserved(mem_map + MAP_NR(start)); + set_page_count(mem_map+MAP_NR(start), 1); + free_page(start); + totalram_pages++; + } +} +#endif + +void si_meminfo(struct sysinfo *val) +{ + val->totalram = totalram_pages; + val->sharedram = 0; + val->freeram = nr_free_pages(); + val->bufferram = atomic_read(&buffermem_pages); + val->mem_unit = PAGE_SIZE; + return; +} diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/mm/ioremap.c linux/arch/s390/mm/ioremap.c --- v2.3.99-pre7/linux/arch/s390/mm/ioremap.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/mm/ioremap.c Fri May 12 11:41:45 2000 @@ -0,0 +1,129 @@ +/* + * arch/s390/mm/ioremap.c + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Hartmut Penner (hp@de.ibm.com) + * + * Derived from "arch/i386/mm/extable.c" + * (C) Copyright 1995 1996 Linus Torvalds + * + * Re-map IO memory to kernel address space so that we can access it. + * This is needed for high PCI addresses that aren't mapped in the + * 640k-1MB IO memory area on PC's + */ + +#include +#include +#include + +static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, + unsigned long phys_addr, unsigned long flags) +{ + unsigned long end; + + address &= ~PMD_MASK; + end = address + size; + if (end > PMD_SIZE) + end = PMD_SIZE; + if (address >= end) + BUG(); + do { + if (!pte_none(*pte)) { + printk("remap_area_pte: page already exists\n"); + BUG(); + } + set_pte(pte, mk_pte_phys(phys_addr, __pgprot(_PAGE_PRESENT | + _PAGE_DIRTY | _PAGE_ACCESSED | flags))); + address += PAGE_SIZE; + phys_addr += PAGE_SIZE; + pte++; + } while (address && (address < end)); +} + +static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, + unsigned long phys_addr, unsigned long flags) +{ + unsigned long end; + + address &= ~PGDIR_MASK; + end = address + size; + if (end > PGDIR_SIZE) + end = PGDIR_SIZE; + phys_addr -= address; + if (address >= end) + BUG(); + do { + pte_t * pte = pte_alloc_kernel(pmd, address); + if (!pte) + return -ENOMEM; + remap_area_pte(pte, address, end - address, address + phys_addr, flags); + address = (address + PMD_SIZE) & PMD_MASK; + pmd++; + } while (address && (address < end)); + return 0; +} + +static int remap_area_pages(unsigned long address, unsigned long phys_addr, + unsigned long size, unsigned long flags) +{ + pgd_t * dir; + unsigned long end = address + size; + + phys_addr -= address; + dir = pgd_offset(&init_mm, address); + flush_cache_all(); + if (address >= end) + BUG(); + do { + pmd_t *pmd = pmd_alloc_kernel(dir, address); + if (!pmd) + return -ENOMEM; + if (remap_area_pmd(pmd, address, end - address, + phys_addr + address, flags)) + return -ENOMEM; + set_pgdir(address, *dir); + address = (address + PGDIR_SIZE) & PGDIR_MASK; + dir++; + } while (address && (address < end)); + flush_tlb_all(); + return 0; +} + +/* + * Generic mapping function (not visible outside): + */ + +/* + * Remap an arbitrary physical address space into the kernel virtual + * address space. Needed when the kernel wants to access high addresses + * directly. + */ +void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags) +{ + void * addr; + struct vm_struct * area; + + if (phys_addr < virt_to_phys(high_memory)) + return phys_to_virt(phys_addr); + if (phys_addr & ~PAGE_MASK) + return NULL; + size = PAGE_ALIGN(size); + if (!size || size > phys_addr + size) + return NULL; + area = get_vm_area(size, VM_IOREMAP); + if (!area) + return NULL; + addr = area->addr; + if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) { + vfree(addr); + return NULL; + } + return addr; +} + +void iounmap(void *addr) +{ + if (addr > high_memory) + return vfree(addr); +} diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/tools/dasdfmt/Makefile linux/arch/s390/tools/dasdfmt/Makefile --- v2.3.99-pre7/linux/arch/s390/tools/dasdfmt/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/tools/dasdfmt/Makefile Fri May 12 11:41:45 2000 @@ -0,0 +1,9 @@ +all: dasdfmt + +dasdfmt: dasdfmt.c + $(CROSS_COMPILE)gcc -o $@ $^ + $(STRIP) $@ + +clean: + rm -f dasdfmt + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/tools/dasdfmt/dasdfmt.8 linux/arch/s390/tools/dasdfmt/dasdfmt.8 --- v2.3.99-pre7/linux/arch/s390/tools/dasdfmt/dasdfmt.8 Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/tools/dasdfmt/dasdfmt.8 Fri May 12 11:41:45 2000 @@ -0,0 +1,74 @@ +.TH DASDFMT 8 "Tue Jan 25 2000" +.UC 4 +.SH NAME +dasdfmt \- formatting of DSAD (ECKD) disk drives. +.SH SYNOPSIS +\fBdasdfmt\fR [-tvyV] [-b \fIblockSize\fR] [\fIblockRange\fI] + \fIdiskSpec\fR +.SH DESCRIPTION +\fBdasdfmt\fR formats a DASD (ECKD) disk drive to prepare it +for usage with Linux for S/390. \fBWARNING\fR: Incautious usage of +\fBdasdfmt\fR can result in \fBLOSS OF DATA\fR. + +.SH OPTIONS +.TP +\fB-t\fR +Disables any modification of the disk drive. \fBdasdfmt\fR just prints +out, what it \fBwould\fR do. + +.TP +\fB-v\fR +Increases verbosity. + +.TP +\fB-y\fR +Start formatting without further user-confirmation. + +.TP +\fB-V\fR +Print version number and exit. + +.TP +\fB-b\fR \fIblockSize\fR +Specify blocksize to be used. \fIblocksize\fR must be a positive integer +and always be a power of two. Due due some limitations in the driver, +it is \fBstrongly\fR recommended to use a \fIblockSize\fR of \fI4096\fR. + +.TP +\fIblockRange\fR +This parameter specifies the number of the first and last block to be +formatted. If this parameter is \fBomitted\fR, formatting the \fBwhole\fR disk +is assumed. The \fIblockRange\fR can be specified in two different formats: +.sp + \fB-s\fR \fIstartBlock\fR \fB-e\fR \fIendBlock\fR +.br +or +.br + \fB-r\fR \fIstartBlock\fR-\fIendBlock\fR +.sp +If \fIstartBlock\fR is omitted, block \fB0\fR is assumed. If +\fIendBlock\fR is omitted, the last block of the disk is assumed. + +.TP +\fIdiskSpec\fR +This parameter specified the device to be formatted. It also can be +given in two variants: +.sp + \fB-f\fR \fB/dev/dd\fR\fIX\fR +.br +or +.br + \fB-n\fR \fIdevnum\fR +.sp +The first form uses the commonly used +.SM UNIX +device notation where \fIX\fR is a single lowercase letter. +The second form uses simply the VM vdev number. + +.SH BUGS +None so far ;-) + +.SH AUTHOR +.nf +This man-page was written by Fritz Elfert +.fi diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/tools/dasdfmt/dasdfmt.c linux/arch/s390/tools/dasdfmt/dasdfmt.c --- v2.3.99-pre7/linux/arch/s390/tools/dasdfmt/dasdfmt.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/tools/dasdfmt/dasdfmt.c Fri May 12 11:41:45 2000 @@ -0,0 +1,638 @@ +/* + * + * dasdfmt.c + * + * S390 version + * Copyright (C) 1999,2000 IBM Corporation + * Author(s): Utz Bacher, + * + * Device-in-use-checks by Fritz Elfert, + * + * Still to do: + * detect non-switch parameters ("dasdfmt -n 170 XY") and complain about them + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../../drivers/s390/block/dasd.h" /* uses DASD_PARTN_BITS */ +#define __KERNEL__ /* we want to use kdev_t and not have to define it */ +#include +#undef __KERNEL__ + +#define EXIT_MISUSE 1 +#define EXIT_BUSY 2 +#define TEMPFILENAME "/tmp/ddfXXXXXX" +#define TEMPFILENAMECHARS 8 /* 8 characters are fixed in all temp filenames */ +#define IOCTL_COMMAND 'D' << 8 +#define SLASHDEV "/dev/" +#define PROC_DASD_DEVICES "/proc/dasd/devices" +#define DASD_DRIVER_NAME "dasd" +#define PROC_LINE_LENGTH 80 +#define ERR_LENGTH 80 + +#define MAX_FILELEN NAME_MAX+PATH_MAX + +#define GIVEN_DEVNO 1 +#define GIVEN_MAJOR 2 +#define GIVEN_MINOR 4 + +#define CHECK_START 1 +#define CHECK_END 2 +#define CHECK_BLKSIZE 4 +#define CHECK_ALL ~0 + +#define ERRMSG(x...) {fflush(stdout);fprintf(stderr,x);} +#define ERRMSG_EXIT(ec,x...) {fflush(stdout);fprintf(stderr,x);exit(ec);} + +#define CHECK_SPEC_MAX_ONCE(i,str) \ + {if (i>1) \ + ERRMSG_EXIT(EXIT_MISUSE,"%s: " str " " \ + "can only be specified once\n",prog_name);} + +#define PARSE_PARAM_INTO(x,param,base,str) \ + {x=(int)strtol(param,&endptr,base); \ + if (*endptr) \ + ERRMSG_EXIT(EXIT_MISUSE,"%s: " str " " \ + "is in invalid format\n",prog_name);} + +typedef struct { + int start_unit; + int stop_unit; + int blksize; +} format_data_t; + +char prog_name[]="dasd_format"; +char tempfilename[]=TEMPFILENAME; + +void +exit_usage(int exitcode) +{ + printf("Usage: %s [-htvyV] [-b blocksize] \n\n", + prog_name); + printf(" where is either\n"); + printf(" -s start_track -e end_track\n"); + printf(" or\n"); + printf(" -r start_track-end_track\n"); + printf(" and is either\n"); + printf(" -f /dev/dasdX\n"); + printf(" or\n"); + printf(" -n \n"); + exit(exitcode); +} + +void +get_xno_from_xno(int *devno,kdev_t *major_no,kdev_t *minor_no,int mode) +{ + FILE *file; + int d,rc; + kdev_t mi,ma; + int mi_i,ma_i; /* for scanf :-( */ + char line[PROC_LINE_LENGTH]; + + file=fopen(PROC_DASD_DEVICES,"r"); + if (file==NULL) + ERRMSG_EXIT(EXIT_FAILURE,"%s: failed to open " \ + PROC_DASD_DEVICES ": %s (do you have the /proc " \ + "filesystem enabled?)\n",prog_name,strerror(errno)); + + fgets(line,sizeof(line),file); /* omit first line */ + while (fgets(line,sizeof(line),file)!=NULL) { + rc=sscanf(line,"%X%d%d",&d,&ma_i,&mi_i); + ma=ma_i; + mi=mi_i; + if ( (rc==3) && + !((d!=*devno)&&(mode&GIVEN_DEVNO)) && + !((ma!=*major_no)&&(mode&GIVEN_MAJOR)) && + !((mi!=*minor_no)&&(mode&GIVEN_MINOR)) ) { + *devno=d; + *major_no=ma; + *minor_no=mi; + /* yes, this is a quick exit, but the easiest way */ + fclose(file); + return; + } + } + fclose(file); + + ERRMSG_EXIT(EXIT_FAILURE,"%s: failed to find device in the /proc " \ + "filesystem (are you sure to have the right param line?)\n", + prog_name); +} + +char * +get_devname_from_devno(int devno,int verbosity) +{ + kdev_t major_no,minor_no; + kdev_t file_major,file_minor; + struct stat stat_buf; + int rc; + int found; + char *devname; + char tmpname[MAX_FILELEN]; + + DIR *dp; + struct dirent *direntp; + + /**** get minor number ****/ + get_xno_from_xno(&devno,&major_no,&minor_no,GIVEN_DEVNO); + + /**** get device file ****/ + if ((dp=opendir(SLASHDEV)) == NULL) + ERRMSG_EXIT(EXIT_FAILURE,"%s: unable to read " SLASHDEV \ + "\n",prog_name); + found=0; + while ((direntp=readdir(dp)) != NULL) { + strcpy(tmpname,SLASHDEV); + strcat(tmpname,direntp->d_name); + rc=stat(tmpname,&stat_buf); + if (!rc) { + file_major=MAJOR(stat_buf.st_rdev); + file_minor=MINOR(stat_buf.st_rdev); + if ((file_major==major_no) && (file_minor==minor_no)) { + found=1; + break; + } + } + } + if (found) { + devname=malloc(strlen(direntp->d_name)); + strcpy(devname,tmpname); + } + rc=closedir(dp); + if (rc<0) ERRMSG("%s: unable to close directory " SLASHDEV \ + "; continuing\n",prog_name); + if (found) + return devname; + + if (verbosity>=1) + printf("I didn't find device node in " SLASHDEV \ + "; trying to create a temporary node\n"); + + /**** get temp file and create device node *****/ + rc=mkstemp(tempfilename); + if (rc==-1) + ERRMSG_EXIT(EXIT_FAILURE,"%s: failed to get temporary " \ + "filename: %s\n",prog_name,strerror(errno)); + close(rc); + rc=unlink(tempfilename); + + rc=mknod(tempfilename,S_IFBLK|0600,MKDEV(major_no,minor_no)); + if (rc) + ERRMSG_EXIT(EXIT_FAILURE,"%s: failed to create temporary " \ + "device node %s: %s\n",prog_name,tempfilename, + strerror(errno)); + return tempfilename; +} + +char * +check_param(int mode,format_data_t data) +{ + char *s; + + if (NULL==(s=malloc(ERR_LENGTH))) + ERRMSG_EXIT(EXIT_FAILURE,"%s: not enough memory.\n",prog_name); + + if ((mode&CHECK_START)&&(data.start_unit<0)) { + strcpy(s,"start track must be greater than zero"); + goto exit; + } + if ((mode&CHECK_END)&&(data.stop_unit<-1)) { + strcpy(s,"end track must be -1 or greater than zero"); + goto exit; + } + if ((mode&CHECK_END)&&(data.start_unit>data.stop_unit)&& + (data.stop_unit!=-1)) { + strcpy(s,"end track must be higher than start track"); + goto exit; + } + + if ((mode&CHECK_BLKSIZE)&&(data.blksize<1)) { + strcpy(s,"blocksize must be a positive integer"); + goto exit; + } + if (mode&CHECK_BLKSIZE) while (data.blksize>0) { + if ((data.blksize%2)&&(data.blksize!=1)) { + strcpy(s,"blocksize must be a power of 2"); + goto exit; + } + data.blksize/=2; + } + + free(s); + return NULL; +exit: + return s; +} + +#define ASK_PRINTOUT printf("Please enter %s",output) +#define ASK_GETBUFFER fgets(buffer,sizeof(buffer),stdin) +#define ASK_SCANFORNUMBER(var) rc=sscanf(buffer,"%d%c",&var,&c) +#define ASK_COMPLAIN_FORMAT if ((rc==2)&&(c=='\n')) rc=1; \ + if (rc==-1) rc=1; /* this happens, if enter is pressed */ \ + if (rc!=1) printf(" -- wrong input, try again.\n") +#define ASK_CHECK_PARAM(mode) str=check_param(mode,params); \ + if (str!=NULL) { printf(" -- %s\n",str); rc=0; free(str); } + +format_data_t +ask_user_for_data(format_data_t params) +{ + char buffer[20]; /* should be enough for inputing track numbers */ + char c; + int i,rc; + char *str; + char output[60],o2[12]; + + i=params.start_unit; + do { + params.start_unit=i; + sprintf(output,"the start track of the range to format " \ + "[%d]: ",i); + ASK_PRINTOUT; + ASK_GETBUFFER; + ASK_SCANFORNUMBER(params.start_unit); + ASK_COMPLAIN_FORMAT; + ASK_CHECK_PARAM(CHECK_START); + } while (rc!=1); + + i=params.stop_unit; + do { + params.stop_unit=i; + sprintf(output,"the end track of the range to format ["); + if (i==-1) sprintf(o2,"END]: "); else + sprintf(o2,"%d]: ",i); + strcat(output,o2); + ASK_PRINTOUT; + ASK_GETBUFFER; + if ( (!strcasecmp(buffer,"end")) || + (!strcasecmp(buffer,"end\n")) ) { + rc=1; + params.stop_unit=-1; + } else { + ASK_SCANFORNUMBER(params.stop_unit); + ASK_COMPLAIN_FORMAT; + ASK_CHECK_PARAM(CHECK_END); + } + } while (rc!=1); + + i=params.blksize; + do { + params.blksize=i; + sprintf(output,"the blocksize of the formatting [%d]: ",i); + ASK_PRINTOUT; + ASK_GETBUFFER; + ASK_SCANFORNUMBER(params.blksize); + ASK_COMPLAIN_FORMAT; + ASK_CHECK_PARAM(CHECK_BLKSIZE); + } while (rc!=1); + + return params; +} + +/* Check if the device we are going to format is mounted. + * If true, complain and exit. + */ +void +check_mounted(int major, int minor) +{ + FILE *f; + int ishift = 0; + struct mntent *ment; + struct stat stbuf; + char line[128]; + + /* If whole disk to be formatted ... */ + if ((minor % (1U << DASD_PARTN_BITS)) == 0) { + /* ... ignore partition-selector */ + minor >>= DASD_PARTN_BITS; + ishift = DASD_PARTN_BITS; + } + /* + * first, check filesystems + */ + if (!(f = fopen(_PATH_MOUNTED, "r"))) + ERRMSG_EXIT(EXIT_FAILURE, "%s: %s\n", _PATH_MOUNTED, + strerror(errno)); + while ((ment = getmntent(f))) { + if (stat(ment->mnt_fsname, &stbuf) == 0) + if ((major == MAJOR(stbuf.st_rdev)) && + (minor == (MINOR(stbuf.st_rdev)>>ishift))) { + ERRMSG("%s: device is mounted on %s!!\n", + prog_name,ment->mnt_dir); + ERRMSG_EXIT(EXIT_BUSY, "If you really want to " + "format it, please unmount it.\n"); + } + } + fclose(f); + /* + * second, check active swap spaces + */ + if (!(f = fopen("/proc/swaps", "r"))) + ERRMSG_EXIT(EXIT_FAILURE, "/proc/swaps: %s", strerror(errno)); + /* + * skip header line + */ + fgets(line, sizeof(line), f); + while (fgets(line, sizeof(line), f)) { + char *p; + for (p = line; *p && (!isspace(*p)); p++) ; + *p = '\0'; + if (stat(line, &stbuf) == 0) + if ((major == MAJOR(stbuf.st_rdev)) && + (minor == (MINOR(stbuf.st_rdev)>>ishift))) { + ERRMSG("%s: the device is in use for " + "swapping!!\n",prog_name); + ERRMSG_EXIT(EXIT_BUSY, "If you really want to " + "format it, please use swapoff %s.\n", + line); + } + } + fclose(f); +} + +void +do_format_dasd(char *dev_name,format_data_t format_params,int testmode, + int verbosity,int withoutprompt) +{ + int fd,rc; + struct stat stat_buf; + kdev_t minor_no,major_no; + int devno; + char inp_buffer[5]; /* to contain yes */ + + fd=open(dev_name,O_RDWR); + if (fd==-1) + ERRMSG_EXIT(EXIT_FAILURE,"%s: error opening device %s: " \ + "%s\n",prog_name,dev_name,strerror(errno)); + + if (verbosity>=1) { + } + + rc=stat(dev_name,&stat_buf); + if (rc) { + ERRMSG_EXIT(EXIT_FAILURE,"%s: error occured during stat: " \ + "%s\n",prog_name,strerror(errno)); + } else { + if (!S_ISBLK(stat_buf.st_mode)) + ERRMSG_EXIT(EXIT_FAILURE,"%s: file is not a " \ + "blockdevice.\n",prog_name); + major_no=MAJOR(stat_buf.st_rdev); + minor_no=MINOR(stat_buf.st_rdev); + } + check_mounted(major_no, minor_no); + + if ( ((withoutprompt)&&(verbosity>=1)) || + (!withoutprompt) ) { + get_xno_from_xno(&devno,&major_no,&minor_no, + GIVEN_MAJOR|GIVEN_MINOR); + printf("\nI am going to format the device %s in the " \ + "following way:\n",dev_name); + printf(" Device number of device : 0x%x\n",devno); + printf(" Major number of device : %u\n",major_no); + printf(" Minor number of device : %u\n",minor_no); + printf(" Start track : %d\n" \ + ,format_params.start_unit); + printf(" End track : "); + if (format_params.stop_unit==-1) + printf("last track of disk\n"); + else + printf("%d\n",format_params.stop_unit); + printf(" Blocksize : %d\n" \ + ,format_params.blksize); + if (testmode) printf("Test mode active, omitting ioctl.\n"); + } + + while (!testmode) { + if (!withoutprompt) { + printf("\n--->> ATTENTION! <<---\n"); + printf("All data in the specified range of that " \ + "device will be lost.\nType yes to continue" \ + ", no will leave the disk untouched: "); + fgets(inp_buffer,sizeof(inp_buffer),stdin); + if (strcasecmp(inp_buffer,"yes") && + strcasecmp(inp_buffer,"yes\n")) { + printf("Omitting ioctl call (disk will " \ + "NOT be formatted).\n"); + break; + } + } + + if ( !( (withoutprompt)&&(verbosity<1) )) + printf("Formatting the device. This may take a " \ + "while (get yourself a coffee).\n"); + rc=ioctl(fd,IOCTL_COMMAND,format_params); + if (rc) + ERRMSG_EXIT(EXIT_FAILURE,"%s: the dasd driver " \ + "returned with the following error " \ + "message:\n%s\n",prog_name,strerror(errno)); + printf("Finished formatting the device.\n"); + + break; + } + + rc=close(fd); + if (rc) + ERRMSG("%s: error during close: " \ + "%s; continuing.\n",prog_name,strerror(errno)); +} + + + +int main(int argc,char *argv[]) { + int verbosity; + int testmode; + int withoutprompt; + + char *dev_name; + int devno; + char *dev_filename,*devno_param_str,*range_param_str; + char *start_param_str,*end_param_str,*blksize_param_str; + + format_data_t format_params; + + int rc; + int oc; + char *endptr; + + char c1,c2,cbuffer[6]; /* should be able to contain -end plus 1 char */ + int i1,i2; + char *str; + + int start_specified,end_specified,blksize_specified; + int devfile_specified,devno_specified,range_specified; + + /******************* initialization ********************/ + + endptr=NULL; + + /* set default values */ + format_params.start_unit=0; + format_params.stop_unit=-1; + format_params.blksize=4096; + testmode=0; + verbosity=0; + withoutprompt=0; + start_specified=end_specified=blksize_specified=0; + devfile_specified=devno_specified=range_specified=0; + + /*************** parse parameters **********************/ + + /* avoid error message generated by getopt */ + opterr=0; + + while ( (oc=getopt(argc,argv,"r:s:e:b:n:f:hty?vV")) !=EOF) { + switch (oc) { + case 'y': + withoutprompt=1; + break; + + case 't': + testmode=1; + break; + + case 'v': + verbosity++; + break; + + case '?': /* fall-through */ + case ':': + exit_usage(EXIT_MISUSE); + + case 'h': + exit_usage(0); + + case 'V': + printf("%s version 0.99\n",prog_name); + exit(0); + + case 's' : + start_param_str=optarg; + start_specified++; + break; + + case 'e' : + end_param_str=optarg; + end_specified++; + break; + + case 'b' : + blksize_param_str=optarg; + blksize_specified++; + break; + + case 'n' : + devno_param_str=optarg; + devno_specified++; + break; + + case 'f' : + dev_filename=optarg; + devfile_specified++; + break; + case 'r' : + range_param_str=optarg; + range_specified++; + break; + } + } + + /******************** checking of parameters **************/ + + /* convert range into -s and -e */ + CHECK_SPEC_MAX_ONCE(range_specified,"formatting range"); + + while (range_specified) { + start_specified++; + end_specified++; + + /* scan for 1 or 2 integers, separated by a dash */ + rc=sscanf(range_param_str,"%d%c%d%c",&i1,&c1,&i2,&c2); + if ((rc==3)&&(c1=='-')) { + format_params.start_unit=i1; + format_params.stop_unit=i2; + break; + } + if (rc==1) { + format_params.start_unit=i1; + break; + } + + /* scan for integer and -END */ + rc=sscanf(range_param_str,"%d%s",&i1,cbuffer); + if ((rc==2)&&(!strcasecmp(cbuffer,"-END"))) { + format_params.start_unit=i1; + format_params.stop_unit=-1; + break; + } + ERRMSG_EXIT(EXIT_MISUSE,"%s: specified range " \ + "is in invalid format\n",prog_name); + } + + if ((!devfile_specified)&&(!devno_specified)) + ERRMSG_EXIT(EXIT_MISUSE,"%s: device to format " \ + "not specified\n",prog_name); + + if ((devfile_specified+devno_specified)>1) + ERRMSG_EXIT(EXIT_MISUSE,"%s: device to format " \ + "can only be specified once\n",prog_name); + + if ((!start_specified)&&(!end_specified)&&(!range_specified)&& + (!blksize_specified)) { + format_params=ask_user_for_data(format_params); + } + + CHECK_SPEC_MAX_ONCE(start_specified,"start track"); + CHECK_SPEC_MAX_ONCE(end_specified,"end track"); + CHECK_SPEC_MAX_ONCE(blksize_specified,"blocksize"); + + if (devno_specified) + PARSE_PARAM_INTO(devno,devno_param_str,16,"device number"); + if (start_specified&&!range_specified) + PARSE_PARAM_INTO(format_params.start_unit,start_param_str,10, + "start track"); + if (end_specified&&!range_specified) + PARSE_PARAM_INTO(format_params.stop_unit,end_param_str,10, + "end track"); + if (blksize_specified) + PARSE_PARAM_INTO(format_params.blksize,blksize_param_str,10, + "blocksize"); + + /***********get dev_name *********************/ + dev_name=(devno_specified)? + get_devname_from_devno(devno,verbosity): + dev_filename; + + /*** range checking *********/ + str=check_param(CHECK_ALL,format_params); + if (str!=NULL) ERRMSG_EXIT(EXIT_MISUSE,"%s: %s\n",prog_name,str); + + /*************** issue the real command *****************/ + do_format_dasd(dev_name,format_params,testmode,verbosity, + withoutprompt); + + /*************** cleanup ********************************/ + if (strncmp(dev_name,TEMPFILENAME,TEMPFILENAMECHARS)==0) { + rc=unlink(dev_name); + if ((rc)&&(verbosity>=1)) + ERRMSG("%s: temporary device node %s could not be " \ + "removed: %s\n",prog_name,dev_name, + strerror(errno)); + } else { + if (devno_specified) { + /* so we have allocated space for the filename */ + free(dev_name); + } + } + + return 0; +} diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/tools/silo/Makefile linux/arch/s390/tools/silo/Makefile --- v2.3.99-pre7/linux/arch/s390/tools/silo/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/tools/silo/Makefile Fri May 12 11:41:45 2000 @@ -0,0 +1,15 @@ +all: silo + +silo.o: silo.c + $(CROSS_COMPILE)gcc -c -o silo.o -O2 silo.c + +cfg.o: cfg.c + $(CROSS_COMPILE)gcc -c -o cfg.o -O2 cfg.c + +silo: silo.o cfg.o + $(CROSS_COMPILE)gcc -o $@ $^ + $(STRIP) $@ + +clean: + rm -f *.o silo + diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/tools/silo/cfg.c linux/arch/s390/tools/silo/cfg.c --- v2.3.99-pre7/linux/arch/s390/tools/silo/cfg.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/tools/silo/cfg.c Fri May 12 11:41:45 2000 @@ -0,0 +1,373 @@ +/* cfg.c - Configuration file parser */ + +/* Copyright 1992-1997 Werner Almesberger. See file COPYING for details. */ + + +#include +#include +#include +#include +#include + +#include "cfg.h" + +#define MAX_TOKEN 200 +#define MAX_VAR_NAME MAX_TOKEN + +static FILE *file; +static char flag_set; +static char *last_token = NULL,*last_item = NULL,*last_value = NULL; +static int line_num; +static char *file_name = NULL; +static int back = 0; /* can go back by one char */ + + +void pdie(char *msg) +{ + fflush(stdout); + perror(msg); + exit(1); +} + + +void die(char *fmt,...) +{ + va_list ap; + + fflush(stdout); + va_start(ap,fmt); + vfprintf(stderr,fmt,ap); + va_end(ap); + fputc('\n',stderr); + exit(1); +} + +char *pstrdup(const char *str) +{ + char *this; + + if ((this = strdup(str)) == NULL) pdie("Out of memory"); + return this; +} + +int cfg_open(char *name) +{ + if (!strcmp(name,"-")) file = stdin; + else if (!(file = fopen(file_name = name,"r"))) pdie(name); + line_num = 1; + return fileno(file); +} + +void cfg_error(char *msg,...) +{ + va_list ap; + + fflush(stdout); + va_start(ap,msg); + vfprintf(stderr,msg,ap); + va_end(ap); + if (!file_name) fputc('\n',stderr); + else fprintf(stderr," near line %d in file %s\n",line_num,file_name); + exit(1); +} + + +static int next_raw(void) +{ + int ch; + + if (!back) return getc(file); + ch = back; + back = 0; + return ch; +} + + +static int next(void) +{ + static char *var; + char buffer[MAX_VAR_NAME+1]; + int ch,braced; + char *put; + + if (back) { + ch = back; + back = 0; + return ch; + } + if (var && *var) return *var++; + ch = getc(file); + if (ch == '\\') { + ch = getc(file); + if (ch == '$') return ch; + ungetc(ch,file); + return '\\'; + } + if (ch != '$') return ch; + ch = getc(file); + braced = ch == '{'; + put = buffer; + if (!braced) *put++ = ch; + while (1) { + ch = getc(file); +#if 0 + if (!braced && ch < ' ') { + ungetc(ch,file); + break; + } +#endif + if (ch == EOF) cfg_error("EOF in variable name"); + if (ch < ' ') cfg_error("control character in variable name"); + if (braced && ch == '}') break; + if (!braced && !isalpha(ch) && !isdigit(ch) && ch != '_') { + ungetc(ch,file); + break; + } + if (put-buffer == MAX_VAR_NAME) cfg_error("variable name too long"); + *put++ = ch; + } + *put = 0; + if (!(var = getenv(buffer))) cfg_error("unknown variable \"%s\"",buffer); + return next(); +} + + +static void again(int ch) +{ + if (back) die("internal error: again invoked twice"); + back = ch; +} + + +static char *cfg_get_token(void) +{ + char buf[MAX_TOKEN+1]; + char *here; + int ch,escaped; + + if (last_token) { + here = last_token; + last_token = NULL; + return here; + } + while (1) { + while ((ch = next()), ch == ' ' || ch == '\t' || ch == '\n') + if (ch == '\n') line_num++; + if (ch == EOF) return NULL; + if (ch != '#') break; + while ((ch = next_raw()), ch != '\n') + if (ch == EOF) return NULL; + line_num++; + } + if (ch == '=') return pstrdup("="); + if (ch == '"') { + here = buf; + while (here-buf < MAX_TOKEN) { + if ((ch = next()) == EOF) cfg_error("EOF in quoted string"); + if (ch == '"') { + *here = 0; + return pstrdup(buf); + } + if (ch == '\\') { + ch = next(); + if (ch != '"' && ch != '\\' && ch != '\n') + cfg_error("Bad use of \\ in quoted string"); + if (ch == '\n') { + while ((ch = next()), ch == ' ' || ch == '\t'); + if (!ch) continue; + again(ch); + ch = ' '; + } + } + if (ch == '\n' || ch == '\t') + cfg_error("\\n and \\t are not allowed in quoted strings"); + *here++ = ch; + } + cfg_error("Quoted string is too long"); + return 0; /* not reached */ + } + here = buf; + escaped = 0; + while (here-buf < MAX_TOKEN) { + if (escaped) { + if (ch == EOF) cfg_error("\\ precedes EOF"); + if (ch == '\n') line_num++; + else *here++ = ch == '\t' ? ' ' : ch; + escaped = 0; + } + else { + if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '#' || + ch == '=' || ch == EOF) { + again(ch); + *here = 0; + return pstrdup(buf); + } + if (!(escaped = (ch == '\\'))) *here++ = ch; + } + ch = next(); + } + cfg_error("Token is too long"); + return 0; /* not reached */ +} + + +static void cfg_return_token(char *token) +{ + last_token = token; +} + + +static int cfg_next(char **item,char **value) +{ + char *this; + + if (last_item) { + *item = last_item; + *value = last_value; + last_item = NULL; + return 1; + } + *value = NULL; + if (!(*item = cfg_get_token())) return 0; + if (!strcmp(*item,"=")) cfg_error("Syntax error"); + if (!(this = cfg_get_token())) return 1; + if (strcmp(this,"=")) { + cfg_return_token(this); + return 1; + } + if (!(*value = cfg_get_token())) cfg_error("Value expected at EOF"); + if (!strcmp(*value,"=")) cfg_error("Syntax error after %s",*item); + return 1; +} + + +static void cfg_return(char *item,char *value) +{ + last_item = item; + last_value = value; +} + + +void cfg_init(CONFIG *table) +{ + while (table->type != cft_end) { + switch (table->type) { + case cft_strg: + if (table->data) free(table->data); + case cft_flag: + table->data = NULL; + break; + case cft_link: + table = ((CONFIG *) table->action)-1; + break; + default: + die("Unknown syntax code %d",table->type); + } + table++; + } +} + + +static int cfg_do_set(CONFIG *table,char *item,char *value,int copy, + void *context) +{ + CONFIG *walk; + + for (walk = table; walk->type != cft_end; walk++) { + if (walk->name && !strcasecmp(walk->name,item)) { + if (value && walk->type != cft_strg) + cfg_error("'%s' doesn't have a value",walk->name); + if (!value && walk->type == cft_strg) + cfg_error("Value expected for '%s'",walk->name); + if (walk->data) { + if (walk->context == context) + cfg_error("Duplicate entry '%s'",walk->name); + else { + fprintf(stderr,"Ignoring entry '%s'\n",walk->name); + if (!copy) free(value); + return 1; + } + } + if (walk->type == cft_flag) walk->data = &flag_set; + else if (walk->type == cft_strg) { + if (copy) walk->data = pstrdup(value); + else walk->data = value; + } + walk->context = context; + if (walk->action) ((void (*)(void)) walk->action)(); + break; + } + if (walk->type == cft_link) walk = ((CONFIG *) walk->action)-1; + } + if (walk->type != cft_end) return 1; + cfg_return(item,value); + return 0; +} + + +void cfg_set(CONFIG *table,char *item,char *value,void *context) +{ + if (!cfg_do_set(table,item,value,1,context)) + cfg_error("cfg_set: Can't set %s",item); +} + + +void cfg_unset(CONFIG *table,char *item) +{ + CONFIG *walk; + + for (walk = table; walk->type != cft_end; walk++) + if (walk->name && !strcasecmp(walk->name,item)) { + if (!walk->data) die("internal error (cfg_unset %s, unset)",item); + if (walk->type == cft_strg) free(walk->data); + walk->data = NULL; + return; + } + die("internal error (cfg_unset %s, unknown",item); +} + + +int cfg_parse(CONFIG *table) +{ + char *item,*value; + + while (1) { + if (!cfg_next(&item,&value)) return 0; + if (!cfg_do_set(table,item,value,0,table)) return 1; + free(item); + } +} + + +int cfg_get_flag(CONFIG *table,char *item) +{ + CONFIG *walk; + + for (walk = table; walk->type != cft_end; walk++) { + if (walk->name && !strcasecmp(walk->name,item)) { + if (walk->type != cft_flag) + die("cfg_get_flag: operating on non-flag %s",item); + return !!walk->data; + } + if (walk->type == cft_link) walk = ((CONFIG *) walk->action)-1; + } + die("cfg_get_flag: unknown item %s",item); + return 0; /* not reached */ +} + + +char *cfg_get_strg(CONFIG *table,char *item) +{ + CONFIG *walk; + + for (walk = table; walk->type != cft_end; walk++) { + if (walk->name && !strcasecmp(walk->name,item)) { + if (walk->type != cft_strg) + die("cfg_get_strg: operating on non-string %s",item); + return walk->data; + } + if (walk->type == cft_link) walk = ((CONFIG *) walk->action)-1; + } + die("cfg_get_strg: unknown item %s",item); + return 0; /* not reached */ +} diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/tools/silo/cfg.h linux/arch/s390/tools/silo/cfg.h --- v2.3.99-pre7/linux/arch/s390/tools/silo/cfg.h Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/tools/silo/cfg.h Fri May 12 11:41:45 2000 @@ -0,0 +1,58 @@ +/* cfg.h - Configuration file parser */ + +/* Copyright 1992-1996 Werner Almesberger. See file COPYING for details. */ + + +#ifndef CFG_H +#define CFG_H + +typedef enum { cft_strg, cft_flag, cft_link, cft_end } CFG_TYPE; + +typedef struct { + CFG_TYPE type; + char *name; + void *action; + void *data; + void *context; +} CONFIG; + +extern int cfg_open(char *name); + +/* Opens the configuration file. Returns the file descriptor of the open + file. */ + +extern void cfg_error(char *msg,...); + +/* Signals an error while parsing the configuration file and terminates the + program. */ + +extern void cfg_init(CONFIG *table); + +/* Initializes the specified table. */ + +extern void cfg_set(CONFIG *table,char *item,char *value,void *context); + +/* Sets the specified variable in table. If the variable has already been set + since the last call to cfg_init, a warning message is issued if the context + keys don't match or a fatal error is reported if they do. */ + +extern void cfg_unset(CONFIG *table,char *item); + +/* Unsets the specified variable in table. It is a fatal error if the variable + was not set. */ + +extern int cfg_parse(CONFIG *table); + +/* Parses the configuration file for variables contained in table. A non-zero + value is returned if a variable not found in table has been met. Zero is + returned if EOF has been reached. */ + +extern int cfg_get_flag(CONFIG *table,char *item); + +/* Returns one if the specified variable is set, zero if it isn't. */ + +extern char *cfg_get_strg(CONFIG *table,char *item); + +/* Returns the value of the specified variable if it is set, NULL otherwise. */ + +#endif diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/tools/silo/silo.c linux/arch/s390/tools/silo/silo.c --- v2.3.99-pre7/linux/arch/s390/tools/silo/silo.c Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/tools/silo/silo.c Fri May 12 11:41:45 2000 @@ -0,0 +1,573 @@ +/* + * arch/s390/boot/silo.c + * + * S390 version + * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * + * Report bugs to: + * + * Author(s): Holger Smolinski + * Fritz Elfert contributed support for + * /etc/silo.conf based on Intel's lilo + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cfg.h" + +CONFIG cf_options[] = { + { cft_strg, "append", NULL, NULL,NULL }, + { cft_strg, "image", NULL, NULL,NULL }, + { cft_strg, "ipldevice", NULL, NULL,NULL }, + { cft_strg, "bootsect", NULL, NULL,NULL }, + { cft_strg, "map", NULL, NULL,NULL }, + { cft_strg, "parmfile", NULL, NULL,NULL }, + { cft_strg, "ramdisk", NULL, NULL,NULL }, + { cft_strg, "root", NULL, NULL,NULL }, + { cft_flag, "readonly", NULL, NULL,NULL }, + { cft_strg, "verbose", NULL, NULL,NULL }, + { cft_strg, "testlevel", NULL, NULL,NULL }, + { cft_end, NULL, NULL, NULL,NULL } +}; + +/* from dasd.h */ +#define DASD_PARTN_BITS 2 +#define BIODASDRWTB _IOWR('D',5,int) +/* end */ + +#define SILO_CFG "/etc/silo.conf" +#define SILO_IMAGE "./image" +#define SILO_BOOTMAP "./boot.map" +#define SILO_PARMFILE "./parmfile" +#define SILO_BOOTSECT "/boot/ipleckd.boot" + +#define PRINT_LEVEL(x,y...) if ( silo_options.verbosity >= x ) printf(y) +#define ERROR_LEVEL(x,y...) if ( silo_options.verbosity >= x ) fprintf(stderr,y) +#define TOGGLE(x) ((x)=((x)?(0):(1))) +#define GETARG(x) {int len=strlen(optarg);x=malloc(len);strncpy(x,optarg,len);PRINT_LEVEL(1,"%s set to %s\n",#x,optarg);} + +#define ITRY(x) if ( (x) == -1 ) { ERROR_LEVEL(0,"%s (line:%d) '%s' returned %d='%s'\n", __FILE__,__LINE__,#x,errno,strerror(errno)); usage(); exit(1); } +#define NTRY(x) if ( (x) == 0 ) { ERROR_LEVEL(0,"%s (line:%d) '%s' returned %d='%s'\n", __FILE__,__LINE__,#x,errno,strerror(errno)); usage(); exit(1); } + +#define MAX_CLUSTERS 256 +#define PARTN_MASK ((1 << DASD_PARTN_BITS) - 1) + +#define SILO_VERSION "1.1" + +struct silo_options + { + short int verbosity; + short int testlevel; + char *image; + char *ipldevice; + char *parmfile; + char *ramdisk; + char *bootsect; + char *conffile; + char *bootmap; + } +silo_options = +{ + 1, /* verbosity */ + 2, /* testlevel */ + SILO_IMAGE, /* image */ + NULL, /* ipldevice */ + SILO_PARMFILE, /* parmfile */ + NULL, /* initrd */ + SILO_BOOTSECT, /* bootsector */ + SILO_CFG, /* silo.conf file */ + SILO_BOOTMAP, /* boot.map */ +}; + +struct blockdesc + { + unsigned long off; + unsigned short ct; + unsigned long addr; + }; + +struct blocklist + { + struct blockdesc blk[MAX_CLUSTERS]; + unsigned short ix; + }; + +void +usage (void) +{ + printf ("Usage:\n"); + printf ("silo -d ipldevice [additional options]\n"); + printf ("-d /dev/node : set ipldevice to /dev/node\n"); + printf ("-f image : set image to image\n"); + printf ("-F conffile : specify configuration file (/etc/silo.conf)\n"); + printf ("-p parmfile : set parameter file to parmfile\n"); + printf ("-b bootsect : set bootsector to bootsect\n"); + printf ("Additional options\n"); + printf ("-B bootmap:\n"); + printf ("-v: increase verbosity level\n"); + printf ("-v#: set verbosity level to #\n"); + printf ("-t: decrease testing level\n"); + printf ("-h: print this message\n"); + printf ("-?: print this message\n"); + printf ("-V: print version\n"); +} + +int +read_cfg(struct silo_options *o) +{ + char *tmp; + if (access(o->conffile, R_OK) && (errno == ENOENT)) + return 0; + /* If errno != ENOENT, let cfg_open report an error */ + cfg_open(o->conffile); + cfg_parse(cf_options); + tmp = cfg_get_strg(cf_options, "ipldevice"); + if ( ! o->ipldevice && tmp ) + o->ipldevice = tmp; + tmp = cfg_get_strg(cf_options, "image"); + if ( ! strncmp(o-> image,SILO_IMAGE,strlen(SILO_IMAGE)) && tmp ) + o->image = tmp; + tmp = cfg_get_strg(cf_options, "parmfile"); + if ( !strncmp(o->parmfile,SILO_PARMFILE,strlen(SILO_PARMFILE)) && tmp) + o->parmfile = tmp; + if ( ! o -> ramdisk ) + o->ramdisk = cfg_get_strg(cf_options, "ramdisk"); + tmp = cfg_get_strg(cf_options, "bootsect"); + if ( !strncmp(o -> bootsect,SILO_BOOTSECT,strlen(SILO_BOOTSECT))&&tmp) + o->bootsect = tmp; + tmp = cfg_get_strg(cf_options, "map") ; + if ( !strncmp(o -> bootmap,SILO_BOOTMAP,strlen(SILO_BOOTMAP)) && tmp) + o->bootmap = tmp; + tmp = cfg_get_strg(cf_options, "verbose"); + if ( tmp ) { + unsigned short v; + sscanf (tmp, "%hu", &v); + o->verbosity = v; + } + tmp = cfg_get_strg(cf_options, "testlevel"); + if ( tmp ) { + unsigned short t; + sscanf (tmp, "%hu", &t); + o->testlevel += t; + } + return 1; +} + +char * +gen_tmpparm( char *pfile ) +{ + char *append = cfg_get_strg(cf_options, "append"); + char *root = cfg_get_strg(cf_options, "root"); + int ro = cfg_get_flag(cf_options, "readonly"); + FILE *f,*of; + char *fn; + char c; + char *tmpdir=NULL,*save=NULL; + + if (!append && !root && !ro) + return pfile; + of = fopen(pfile, "r"); + if ( of ) { + NTRY( fn = tempnam(NULL,"parm.")); + } else { + fn = pfile; + } + NTRY( f = fopen(fn, "a+")); + if ( of ) { + while ( ! feof (of) ) { + c=fgetc(of); + fputc(c,f); + } + } + if (root) + fprintf(f, " root=%s", root); + if (ro) + fprintf(f, " ro"); + if (append) + fprintf(f, " %s", append); + fprintf(f, "\n"); + fclose(f); + fclose(of); + printf ("tempfile is %s\n",fn); + return strdup(fn); +} + +int +parse_options (struct silo_options *o, int argc, char *argv[]) +{ + int rc = 0; + int oc; + + while ((oc = getopt (argc, argv, "Vf:F:d:p:r:b:B:h?v::t::")) != -1) + { + switch (oc) + { + case 'V': + printf("silo version: %s\n",SILO_VERSION); + exit(0); + case 'v': + { + unsigned short v; + if (optarg && sscanf (optarg, "%hu", &v)) + o->verbosity = v; + else + o->verbosity++; + PRINT_LEVEL (1, "Verbosity value is now %hu\n", o->verbosity); + break; + } + case 't': + { + unsigned short t; + if (optarg && sscanf (optarg, "%hu", &t)) + o->testlevel -= t; + else + o->testlevel--; + PRINT_LEVEL (1, "Testonly flag is now %d\n", o->testlevel); + break; + } + case 'h': + case '?': + usage (); + exit(0); + case 'd': + GETARG (o->ipldevice); + break; + case 'f': + GETARG (o->image); + break; + case 'F': + GETARG (o->conffile); + break; + case 'p': + GETARG (o->parmfile); + break; + case 'r': + GETARG (o->ramdisk); + break; + case 'b': + GETARG (o->bootsect); + break; + case 'B': + GETARG (o->bootmap); + default: + rc = EINVAL; + break; + } + } + read_cfg(o); + return rc; +} + +int +verify_device (char *name) +{ + int rc = 0; + struct stat dst; + struct stat st; + ITRY (stat (name, &dst)); + if (S_ISBLK (dst.st_mode)) + { + if (!(MINOR (dst.st_rdev) & PARTN_MASK)) + { + rc = dst.st_rdev; + } + else + /* invalid MINOR & PARTN_MASK */ + { + ERROR_LEVEL (1, "Cannot boot from partition %d %d %d", + (int) PARTN_MASK, (int) MINOR (dst.st_rdev), (int) (PARTN_MASK & MINOR (dst.st_rdev))); + rc = -1; + errno = EINVAL; + } + } + else + /* error S_ISBLK */ + { + ERROR_LEVEL (1, "%s is no block device\n", name); + rc = -1; + errno = EINVAL; + } + return rc; +} + +int +verify_file (char *name, int dev) +{ + int rc = 0; + struct stat dst; + struct stat st; + int bs = 1024; + int l; + + ITRY(stat ( name, &dst )); + if (S_ISREG (dst.st_mode)) + { + if ((unsigned) MAJOR (dev) == (unsigned) MAJOR (dst.st_dev) && (unsigned) MINOR (dev) == (unsigned) (MINOR (dst.st_dev) & ~PARTN_MASK)) + { + /* whatever to do if all is ok... */ + } + else + /* devicenumber doesn't match */ + { + ERROR_LEVEL (1, "%s is not on device (%d/%d) but on (%d/%d)\n", name, (unsigned) MAJOR (dev), (unsigned) MINOR (dev), (unsigned) MAJOR (dst.st_dev), (unsigned) (MINOR (dst.st_dev) & ~PARTN_MASK)); + rc = -1; + errno = EINVAL; + } + } + else + /* error S_ISREG */ + { + ERROR_LEVEL (1, "%s is neither regular file nor linkto one\n", name); + rc = -1; + errno = EINVAL; + } + return rc; +} + +int +verify_options (struct silo_options *o) +{ + int rc = 0; + int dev = 0; + int crc = 0; + if (!o->ipldevice || !o->image || !o->bootsect) + { + if (!o->ipldevice) + fprintf(stderr,"ipldevice\n"); + if (!o->image) + fprintf(stderr,"image\n"); + if (!o->bootsect) + fprintf(stderr,"bootsect\n"); + + usage (); + exit (1); + } + PRINT_LEVEL (1, "Testlevel is set to %d\n",o->testlevel); + + PRINT_LEVEL (1, "IPL device is: '%s'", o->ipldevice); + ITRY (dev = verify_device (o->ipldevice)); + PRINT_LEVEL (2, "...ok...(%d/%d)", (unsigned short) MAJOR (dev), (unsigned short) MINOR (dev)); + PRINT_LEVEL (1, "\n"); + + PRINT_LEVEL (0, "bootsector is: '%s'", o->bootsect); + ITRY (verify_file (o->bootsect, dev)); + PRINT_LEVEL (1, "...ok..."); + PRINT_LEVEL (0, "\n"); + + if ( o -> testlevel > 0 && + ! strncmp( o->bootmap, SILO_BOOTMAP,strlen(SILO_BOOTMAP) )) { + NTRY( o -> bootmap = tempnam(NULL,"boot.")); + } + PRINT_LEVEL (0, "bootmap is set to: '%s'", o->bootmap); + if ( access ( o->bootmap, O_RDWR ) == -1 ) { + if ( errno == ENOENT ) { + ITRY (creat ( o-> bootmap, O_RDWR )); + } else { + PRINT_LEVEL(1,"Cannot acces bootmap file '%s': %s\n",o->bootmap, + strerror(errno)); + } + } + ITRY (verify_file (o->bootmap, dev)); + PRINT_LEVEL (1, "...ok..."); + PRINT_LEVEL (0, "\n"); + + PRINT_LEVEL (0, "Kernel image is: '%s'", o->image); + ITRY (verify_file (o->image, dev)); + PRINT_LEVEL (1, "...ok..."); + PRINT_LEVEL (0, "\n"); + + PRINT_LEVEL (0, "original parameterfile is: '%s'", o->parmfile); + ITRY (verify_file (o->parmfile, dev)); + PRINT_LEVEL (1, "...ok..."); + o->parmfile = gen_tmpparm(o->parmfile); + PRINT_LEVEL (0, "final parameterfile is: '%s'", o->parmfile); + ITRY (verify_file (o->parmfile, dev)); + PRINT_LEVEL (1, "...ok..."); + PRINT_LEVEL (0, "\n"); + + if (o->ramdisk) + { + PRINT_LEVEL (0, "initialramdisk is: '%s'", o->ramdisk); + ITRY (verify_file (o->ramdisk, dev)); + PRINT_LEVEL (1, "...ok..."); + PRINT_LEVEL (0, "\n"); + } + + return crc; +} + + +int +add_file_to_blocklist (char *name, struct blocklist *lst, long addr) +{ + int fd; + int devfd; + struct stat fst; + int i; + int blk; + int bs; + int blocks; + + int rc = 0; + + ITRY (fd = open (name, O_RDONLY)); + ITRY (fstat (fd, &fst)); + ITRY (mknod ("/tmp/silodev", S_IFBLK | S_IRUSR | S_IWUSR, fst.st_dev)); + ITRY (devfd = open ("/tmp/silodev", O_RDONLY)); + ITRY (ioctl (fd, FIGETBSZ, &bs)); + blocks = (fst.st_size + bs - 1) / bs; + for (i = 0; i < blocks; i++) + { + blk = i; + ITRY (ioctl (fd, FIBMAP, &blk)); + if (blk) + { + int oldblk = blk; + ITRY (ioctl (devfd, BIODASDRWTB, &blk)); + if (blk <= 0) + { + ERROR_LEVEL (0, "BIODASDRWTB on blk %d returned %d\n", oldblk, blk); + break; + } + } + else + { + PRINT_LEVEL (1, "Filled hole on blk %d\n", i); + } + if (lst->ix == 0 || i == 0 || + lst->blk[lst->ix - 1].ct >= 128 || + (lst->blk[lst->ix - 1].off + lst->blk[lst->ix - 1].ct != blk && + !(lst->blk[lst->ix - 1].off == 0 && blk == 0))) + { + if (lst->ix >= MAX_CLUSTERS) + { + rc = 1; + errno = ENOMEM; + break; + } + lst->blk[lst->ix].off = blk; + lst->blk[lst->ix].ct = 1; + lst->blk[lst->ix].addr = addr + i * bs; + lst->ix++; + } + else + { + lst->blk[lst->ix - 1].ct++; + } + } + ITRY(unlink("/tmp/silodev")); + return rc; +} + +int +write_bootsect (struct silo_options *o, struct blocklist *blklst) +{ + int i; + int s_fd, d_fd, b_fd, bd_fd; + struct stat s_st, d_st, b_st; + int rc=0; + int bs, boots; + char *tmpdev; + char buffer[4096]={0,}; + ITRY (d_fd = open (o->ipldevice, O_RDWR | O_SYNC)); + ITRY (fstat (d_fd, &d_st)); + ITRY (s_fd = open (o->bootmap, O_RDWR | O_TRUNC | O_CREAT | O_SYNC)); + ITRY (verify_file (o->bootsect, d_st.st_rdev)); + for (i = 0; i < blklst->ix; i++) + { + int offset = blklst->blk[i].off; + int addrct = blklst->blk[i].addr | (blklst->blk[i].ct & 0xff); + PRINT_LEVEL (1, "ix %i: offset: %06x count: %02x address: 0x%08x\n", i, offset, blklst->blk[i].ct & 0xff, blklst->blk[i].addr); + if ( o->testlevel <= 1 ) { + NTRY (write (s_fd, &offset, sizeof (int))); + NTRY (write (s_fd, &addrct, sizeof (int))); + } + } + ITRY (ioctl (s_fd,FIGETBSZ, &bs)); + ITRY (stat (o->bootmap, &s_st)); + if (s_st.st_size > bs ) + { + ERROR_LEVEL (0,"%s is larger than one block\n", o->bootmap); + rc = -1; + errno = EINVAL; + } + boots=0; + NTRY ( tmpdev = tmpnam(NULL) ); + ITRY (mknod (tmpdev, S_IFBLK | S_IRUSR | S_IWUSR, s_st.st_dev)); + ITRY (bd_fd = open (tmpdev, O_RDONLY)); + ITRY (ioctl(s_fd,FIBMAP,&boots)); + ITRY (ioctl (bd_fd, BIODASDRWTB, &boots)); + PRINT_LEVEL (1, "Bootmap is in block no: 0x%08x\n", boots); + close (bd_fd); + close(s_fd); + ITRY (unlink(tmpdev)); + /* Now patch the bootsector */ + ITRY (b_fd = open (o->bootsect, O_RDONLY)); + NTRY (read (b_fd, buffer, 4096)); + memset (buffer + 0xe0, 0, 8); + *(int *) (buffer + 0xe0) = boots; + if ( o -> testlevel <= 0 ) { + NTRY (write (d_fd, buffer, 4096)); + NTRY (write (d_fd, buffer, 4096)); + } + close (b_fd); + close (d_fd); + return rc; +} + +int +do_silo (struct silo_options *o) +{ + int rc = 0; + + int device_fd; + int image_fd; + struct blocklist blklist; + memset (&blklist, 0, sizeof (struct blocklist)); + ITRY (add_file_to_blocklist (o->image, &blklist, 0x00000000)); + if (o->parmfile) + { + ITRY (add_file_to_blocklist (o->parmfile, &blklist, 0x00008000)); + } + if (o->ramdisk) + { + ITRY (add_file_to_blocklist (o->ramdisk, &blklist, 0x00800000)); + } + ITRY (write_bootsect (o, &blklist)); + return rc; +} + +int +main (int argct, char *argv[]) +{ + int rc = 0; + char *save; + char *tmpdir=getenv("TMPDIR"); + if (tmpdir) { + NTRY( save=(char*)malloc(strlen(tmpdir))); + NTRY( strncpy(save,tmpdir,strlen(tmpdir))); + } + ITRY( setenv("TMPDIR",".",1)); + ITRY (parse_options (&silo_options, argct, argv)); + ITRY (verify_options (&silo_options)); + if ( silo_options.testlevel > 0 ) { + printf ("WARNING: silo does not modify your volume. Use -t2 to change IPL records\n"); + } + ITRY (do_silo (&silo_options)); + if ( save ) + ITRY( setenv("TMPDIR",save,1)); + return rc; +} diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/tools/silo/silo.conf linux/arch/s390/tools/silo/silo.conf --- v2.3.99-pre7/linux/arch/s390/tools/silo/silo.conf Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/tools/silo/silo.conf Fri May 12 11:41:45 2000 @@ -0,0 +1,7 @@ +ipldevice = /dev/dasda +image = /boot/image +bootsect = /boot/ipleckd.boot +map = /boot/boot.map +root = /dev/dasd01 +readonly +append = "dasd=200-20f noinitrd" diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/vmlinux.lds linux/arch/s390/vmlinux.lds --- v2.3.99-pre7/linux/arch/s390/vmlinux.lds Wed Dec 31 16:00:00 1969 +++ linux/arch/s390/vmlinux.lds Fri May 12 11:41:45 2000 @@ -0,0 +1,78 @@ +/* ld script to make s390 Linux kernel + * Written by Martin Schwidefsky (schwidefsky@de.ibm.com) + */ +OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390") +OUTPUT_ARCH(s390) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + _text = .; /* Text and read-only data */ + .text : { + *(.text) + *(.fixup) + *(.gnu.warning) + } = 0x0700 + .text.lock : { *(.text.lock) } /* out-of-line lock text */ + .rodata : { *(.rodata) } + .kstrtab : { *(.kstrtab) } + + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + __start___ksymtab = .; /* Kernel symbol table */ + __ksymtab : { *(__ksymtab) } + __stop___ksymtab = .; + + _etext = .; /* End of text section */ + + .data : { /* Data */ + *(.data) + CONSTRUCTORS + } + + _edata = .; /* End of data section */ + + . = ALIGN(8192); /* init_task */ + .data.init_task : { *(.data.init_task) } + + . = ALIGN(4096); /* Init code and data */ + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + __setup_start = .; + .setup.init : { *(.setup.init) } + __setup_end = .; + __initcall_start = .; + .initcall.init : { *(.initcall.init) } + __initcall_end = .; + . = ALIGN(4096); + __init_end = .; + + . = ALIGN(32); + .data.cacheline_aligned : { *(.data.cacheline_aligned) } + + . = ALIGN(4096); + .data.page_aligned : { *(.data.idt) } + + + __bss_start = .; /* BSS */ + .bss : { + *(.bss) + } + _end = . ; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } +} diff -u --recursive --new-file v2.3.99-pre7/linux/arch/sparc/kernel/Makefile linux/arch/sparc/kernel/Makefile --- v2.3.99-pre7/linux/arch/sparc/kernel/Makefile Wed Apr 26 16:34:07 2000 +++ linux/arch/sparc/kernel/Makefile Fri May 12 11:32:08 2000 @@ -87,7 +87,7 @@ @echo "#undef CONFIG_SMP" >> tmp.c @echo "#define CONFIG_SMP 1" >> tmp.c @echo "#include " >> tmp.c - $(CPP) $(CPPFLAGS) -D__SMP__ tmp.c -o tmp.i + $(CPP) $(CPPFLAGS) tmp.c -o tmp.i @echo "/* Automatically generated. Do not edit. */" > check_asm.c @echo "#include " >> check_asm.c @echo "#undef CONFIG_SMP" >> check_asm.c @@ -102,7 +102,7 @@ $(SH) ./check_asm.sh thread tmp.i check_asm.c @echo 'return 0; }' >> check_asm.c @rm -f tmp.[ci] - $(CC) $(CFLAGS) -D__SMP__ -o check_asm check_asm.c + $(CC) $(CFLAGS) -o check_asm check_asm.c ./check_asm >> asm_offsets.h @rm -f check_asm check_asm.c @echo "" >> asm_offsets.h diff -u --recursive --new-file v2.3.99-pre7/linux/arch/sparc64/config.in linux/arch/sparc64/config.in --- v2.3.99-pre7/linux/arch/sparc64/config.in Thu May 11 15:30:06 2000 +++ linux/arch/sparc64/config.in Fri May 12 11:43:26 2000 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.108 2000/04/18 05:20:45 davem Exp $ +# $Id: config.in,v 1.109 2000/05/02 06:35:59 davem Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -255,9 +255,10 @@ tristate 'MyriCOM Gigabit Ethernet support' CONFIG_MYRI_SBUS endmenu -# bool ' FDDI driver support' CONFIG_FDDI -# if [ "$CONFIG_FDDI" = "y" ]; then -# fi + bool 'FDDI driver support' CONFIG_FDDI + if [ "$CONFIG_FDDI" = "y" ]; then + tristate ' SysKonnect FDDI PCI support' CONFIG_SKFP + fi if [ "$CONFIG_ATM" = "y" ]; then source drivers/atm/Config.in diff -u --recursive --new-file v2.3.99-pre7/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig --- v2.3.99-pre7/linux/arch/sparc64/defconfig Thu May 11 15:30:06 2000 +++ linux/arch/sparc64/defconfig Fri May 12 11:43:26 2000 @@ -353,6 +353,8 @@ # CONFIG_ACENIC_OMIT_TIGON_I is not set CONFIG_SK98LIN=m CONFIG_MYRI_SBUS=m +CONFIG_FDDI=y +CONFIG_SKFP=m # # Unix 98 PTY support diff -u --recursive --new-file v2.3.99-pre7/linux/arch/sparc64/kernel/Makefile linux/arch/sparc64/kernel/Makefile --- v2.3.99-pre7/linux/arch/sparc64/kernel/Makefile Wed Apr 26 16:34:07 2000 +++ linux/arch/sparc64/kernel/Makefile Fri May 12 11:32:08 2000 @@ -113,7 +113,7 @@ @echo "#undef CONFIG_SMP" >> tmp.c @echo "#define CONFIG_SMP 1" >> tmp.c @echo "#include " >> tmp.c - $(CPP) $(CPPFLAGS) -D__SMP__ tmp.c -o tmp.i + $(CPP) $(CPPFLAGS) tmp.c -o tmp.i @echo "/* Automatically generated. Do not edit. */" > check_asm.c @echo "#include " >> check_asm.c @echo "#undef CONFIG_SMP" >> check_asm.c @@ -130,7 +130,7 @@ @rm -f tmp.[ci] #$(CC) -D__SMP__ -o check_asm check_asm.c # Until we can do this natively, a hack has to take place - $(CC) $(CPPFLAGS) -D__SMP__ $(CMODEL_CFLAG) -ffixed-g4 -S -o check_asm.s check_asm.c + $(CC) $(CPPFLAGS) $(CMODEL_CFLAG) -ffixed-g4 -S -o check_asm.s check_asm.c $(HOSTCC) -Wa,-Av9a -o check_asm check_asm.s @rm -f check_asm.s # @@ -138,7 +138,7 @@ @rm -f check_asm check_asm.c @echo -e "\n#else /* SPIN_LOCK_DEBUG */\n" >> asm_offsets.h @echo "#include " > tmp.c - $(CPP) $(CPPFLAGS) -D__SMP__ -DSPIN_LOCK_DEBUG tmp.c -o tmp.i + $(CPP) $(CPPFLAGS) -DSPIN_LOCK_DEBUG tmp.c -o tmp.i @echo "/* Automatically generated. Do not edit. */" > check_asm.c @echo "#include " >> check_asm.c @echo "#undef CONFIG_SMP" >> check_asm.c @@ -155,7 +155,7 @@ @rm -f tmp.[ci] #$(CC) -D__SMP__ -DSPIN_LOCK_DEBUG -o check_asm check_asm.c # Until we can do this natively, a hack has to take place - $(CC) $(CPPFLAGS) -D__SMP__ -DSPIN_LOCK_DEBUG $(CMODEL_CFLAG) -ffixed-g4 -S -o check_asm.s check_asm.c + $(CC) $(CPPFLAGS) -DSPIN_LOCK_DEBUG $(CMODEL_CFLAG) -ffixed-g4 -S -o check_asm.s check_asm.c $(HOSTCC) -Wa,-Av9a -o check_asm check_asm.s @rm -f check_asm.s # diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/acorn/scsi/arxescsi.c linux/drivers/acorn/scsi/arxescsi.c --- v2.3.99-pre7/linux/drivers/acorn/scsi/arxescsi.c Tue Apr 11 15:09:15 2000 +++ linux/drivers/acorn/scsi/arxescsi.c Fri May 12 11:21:20 2000 @@ -1,7 +1,7 @@ /* * linux/arch/arm/drivers/scsi/arxescsi.c * - * Copyright (C) 1997-2000 Russell King + * Copyright (C) 1997-2000 Russell King, Stefan Hanske * * This driver is based on experimentation. Hence, it may have made * assumptions about the particular card that I have available, and @@ -11,9 +11,11 @@ * 30-08-1997 RMK 0.0.0 Created, READONLY version as cumana_2.c * 22-01-1998 RMK 0.0.1 Updated to 2.1.80 * 15-04-1998 RMK 0.0.1 Only do PIO if FAS216 will allow it. - * 11-06-1998 0.0.2 Changed to support ARXE 16-bit SCSI card, enabled writing - * by Stefan Hanske - * 02-04-2000 RMK 0.0.3 Updated for new error handling code. + * 11-06-1998 SH 0.0.2 Changed to support ARXE 16-bit SCSI card + * enabled writing + * 01-01-2000 SH 0.1.0 Added *real* pseudo dma writing + * (arxescsi_pseudo_dma_write) + * 02-04-2000 RMK 0.1.1 Updated for new error handling code. */ #include @@ -54,8 +56,8 @@ * Version */ #define VER_MAJOR 0 -#define VER_MINOR 0 -#define VER_PATCH 3 +#define VER_MINOR 1 +#define VER_PATCH 1 static struct expansion_card *ecs[MAX_ECARDS]; @@ -115,6 +117,33 @@ : "r" (value), "r" (address), "r" (reg) ); } +void arxescsi_pseudo_dma_write(unsigned char *addr, unsigned int io) +{ + __asm__ __volatile__( + " stmdb sp!, {r0-r12}\n" + " mov r3, %0\n" + " mov r1, %1\n" + " add r2, r1, #512\n" + " mov r4, #256\n" + ".loop_1: ldmia r3!, {r6, r8, r10, r12}\n" + " mov r5, r6, lsl #16\n" + " mov r7, r8, lsl #16\n" + ".loop_2: ldrb r0, [r1, #1536]\n" + " tst r0, #1\n" + " beq .loop_2\n" + " stmia r2, {r5-r8}\n\t" + " mov r9, r10, lsl #16\n" + " mov r11, r12, lsl #16\n" + ".loop_3: ldrb r0, [r1, #1536]\n" + " tst r0, #1\n" + " beq .loop_3\n" + " stmia r2, {r9-r12}\n" + " subs r4, r4, #16\n" + " bne .loop_1\n" + " ldmia sp!, {r0-r12}\n" + : + : "r" (addr), "r" (io) ); +} /* * Function: int arxescsi_dma_pseudo(host, SCpnt, direction, transfer) @@ -136,26 +165,36 @@ io = __ioaddr(host->io_port); if (direction == DMA_OUT) { - while (length > 0) { - unsigned long word; - - - word = *addr | *(addr + 1) << 8; - if (getb(io, 4) & STAT_INT) + unsigned int word; + while (length > 256) { + if (getb(io, 4) & STAT_INT) { + error=1; break; - - if (!(getb(io, 48) & CSTATUS_IRQ)) - continue; - - putw(io, 16, word); - if (length > 1) { - addr += 2; - length -= 2; - } else { - addr += 1; - length -= 1; } + arxescsi_pseudo_dma_write(addr, io); + addr += 256; + length -= 256; } + + if (!error) + while (length > 0) { + if (getb(io, 4) & STAT_INT) + break; + + if (!(getb(io, 48) & CSTATUS_IRQ)) + continue; + + word = *addr | *(addr + 1) << 8; + + putw(io, 16, word); + if (length > 1) { + addr += 2; + length -= 2; + } else { + addr += 1; + length -= 1; + } + } } else { if (transfer && (transfer & 255)) { diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/acorn/scsi/arxescsi.h linux/drivers/acorn/scsi/arxescsi.h --- v2.3.99-pre7/linux/drivers/acorn/scsi/arxescsi.h Tue Apr 11 15:09:15 2000 +++ linux/drivers/acorn/scsi/arxescsi.h Fri May 12 11:21:20 2000 @@ -41,9 +41,7 @@ #include -#ifndef HOSTS_C #include "fas216.h" -#endif #define ARXEScsi { \ proc_info: arxescsi_proc_info, \ diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/acorn/scsi/cumana_2.h linux/drivers/acorn/scsi/cumana_2.h --- v2.3.99-pre7/linux/drivers/acorn/scsi/cumana_2.h Tue Apr 11 15:09:16 2000 +++ linux/drivers/acorn/scsi/cumana_2.h Fri May 12 11:21:20 2000 @@ -39,9 +39,7 @@ #include -#ifndef HOSTS_C #include "fas216.h" -#endif #define CUMANASCSI_2 { \ proc_info: cumanascsi_2_proc_info, \ diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/block/Config.in linux/drivers/block/Config.in --- v2.3.99-pre7/linux/drivers/block/Config.in Wed Apr 26 16:34:07 2000 +++ linux/drivers/block/Config.in Fri May 12 11:36:30 2000 @@ -48,9 +48,12 @@ bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD dep_tristate ' Linear (append) mode' CONFIG_MD_LINEAR $CONFIG_BLK_DEV_MD -dep_tristate ' RAID-0 (striping) mode' CONFIG_MD_STRIPED $CONFIG_BLK_DEV_MD -#dep_tristate ' RAID-1 (mirroring) mode' CONFIG_MD_MIRRORING $CONFIG_BLK_DEV_MD -#dep_tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5 $CONFIG_BLK_DEV_MD +dep_tristate ' RAID-0 (striping) mode' CONFIG_MD_RAID0 $CONFIG_BLK_DEV_MD +bool ' DANGEROUS! RAID1/RAID5 code' CONFIG_RAID15_DANGEROUS +if [ "$CONFIG_RAID15_DANGEROUS" = "y" ]; then + dep_tristate ' RAID-1 (mirroring) mode' CONFIG_MD_RAID1 $CONFIG_BLK_DEV_MD + dep_tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5 $CONFIG_BLK_DEV_MD +fi tristate 'RAM disk support' CONFIG_BLK_DEV_RAM dep_bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD $CONFIG_BLK_DEV_RAM diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/block/Makefile linux/drivers/block/Makefile --- v2.3.99-pre7/linux/drivers/block/Makefile Tue Mar 14 19:10:39 2000 +++ linux/drivers/block/Makefile Fri May 12 11:36:30 2000 @@ -149,43 +149,29 @@ endif endif -ifeq ($(CONFIG_MD_STRIPED),y) +ifeq ($(CONFIG_MD_RAID0),y) L_OBJS += raid0.o else - ifeq ($(CONFIG_MD_STRIPED),m) + ifeq ($(CONFIG_MD_RAID0),m) M_OBJS += raid0.o endif endif -ifeq ($(CONFIG_MD_MIRRORING),y) +ifeq ($(CONFIG_MD_RAID1),y) L_OBJS += raid1.o else - ifeq ($(CONFIG_MD_MIRRORING),m) + ifeq ($(CONFIG_MD_RAID1),m) M_OBJS += raid1.o endif endif ifeq ($(CONFIG_MD_RAID5),y) +LX_OBJS += xor.o L_OBJS += raid5.o else ifeq ($(CONFIG_MD_RAID5),m) + LX_OBJS += xor.o M_OBJS += raid5.o - endif -endif - -ifeq ($(CONFIG_MD_TRANSLUCENT),y) -L_OBJS += translucent.o -else - ifeq ($(CONFIG_MD_TRANSLUCENT),m) - M_OBJS += translucent.o - endif -endif - -ifeq ($(CONFIG_MD_HSM),y) -L_OBJS += hsm.o -else - ifeq ($(CONFIG_MD_HSM),m) - M_OBJS += hsm.o endif endif diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/block/linear.c linux/drivers/block/linear.c --- v2.3.99-pre7/linux/drivers/block/linear.c Sat Feb 26 22:31:44 2000 +++ linux/drivers/block/linear.c Fri May 12 11:36:30 2000 @@ -184,13 +184,11 @@ static mdk_personality_t linear_personality= { "linear", - NULL, linear_make_request, NULL, linear_run, linear_stop, linear_status, - NULL, 0, NULL, NULL, diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c --- v2.3.99-pre7/linux/drivers/block/ll_rw_blk.c Wed Apr 26 16:34:07 2000 +++ linux/drivers/block/ll_rw_blk.c Fri May 12 11:36:27 2000 @@ -373,40 +373,23 @@ else ro_bits[major][minor >> 5] &= ~(1 << (minor & 31)); } -static inline void drive_stat_acct(struct request *req, +inline void drive_stat_acct (kdev_t dev, int rw, unsigned long nr_sectors, int new_io) { - int major = MAJOR(req->rq_dev); - int minor = MINOR(req->rq_dev); - unsigned int disk_index; - - switch (major) { - case DAC960_MAJOR+0: - disk_index = (minor & 0x00f8) >> 3; - break; - case SCSI_DISK0_MAJOR: - disk_index = (minor & 0x00f0) >> 4; - break; - case IDE0_MAJOR: /* same as HD_MAJOR */ - case XT_DISK_MAJOR: - disk_index = (minor & 0x0040) >> 6; - break; - case IDE1_MAJOR: - disk_index = ((minor & 0x0040) >> 6) + 2; - break; - default: - return; - } - if (disk_index >= DK_NDRIVE) + unsigned int major = MAJOR(dev); + unsigned int index; + + index = disk_index(dev); + if ((index >= DK_MAX_DISK) || (major >= DK_MAX_MAJOR)) return; - kstat.dk_drive[disk_index] += new_io; - if (req->cmd == READ) { - kstat.dk_drive_rio[disk_index] += new_io; - kstat.dk_drive_rblk[disk_index] += nr_sectors; - } else if (req->cmd == WRITE) { - kstat.dk_drive_wio[disk_index] += new_io; - kstat.dk_drive_wblk[disk_index] += nr_sectors; + kstat.dk_drive[major][index] += new_io; + if (rw == READ) { + kstat.dk_drive_rio[major][index] += new_io; + kstat.dk_drive_rblk[major][index] += nr_sectors; + } else if (rw == WRITE) { + kstat.dk_drive_wio[major][index] += new_io; + kstat.dk_drive_wblk[major][index] += nr_sectors; } else printk(KERN_ERR "drive_stat_acct: cmd not R/W?\n"); } @@ -426,7 +409,7 @@ { int major; - drive_stat_acct(req, req->nr_sectors, 1); + drive_stat_acct(req->rq_dev, req->cmd, req->nr_sectors, 1); if (list_empty(head)) { req->elevator_sequence = elevator_sequence(&q->elevator, latency); @@ -686,7 +669,7 @@ req->bhtail->b_reqnext = bh; req->bhtail = bh; req->nr_sectors = req->hard_nr_sectors += count; - drive_stat_acct(req, count, 0); + drive_stat_acct(req->rq_dev, req->cmd, count, 0); elevator_merge_after(elevator, req, latency); @@ -716,7 +699,7 @@ req->current_nr_sectors = count; req->sector = req->hard_sector = sector; req->nr_sectors = req->hard_nr_sectors += count; - drive_stat_acct(req, count, 0); + drive_stat_acct(req->rq_dev, req->cmd, count, 0); elevator_merge_before(elevator, req, latency); @@ -1090,6 +1073,7 @@ EXPORT_SYMBOL(end_that_request_first); EXPORT_SYMBOL(end_that_request_last); EXPORT_SYMBOL(blk_init_queue); +EXPORT_SYMBOL(blk_get_queue); EXPORT_SYMBOL(blk_cleanup_queue); EXPORT_SYMBOL(blk_queue_headactive); EXPORT_SYMBOL(blk_queue_pluggable); diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/block/md.c linux/drivers/block/md.c --- v2.3.99-pre7/linux/drivers/block/md.c Wed Apr 26 16:34:07 2000 +++ linux/drivers/block/md.c Fri May 12 11:36:47 2000 @@ -1,6 +1,6 @@ /* md.c : Multiple Devices driver for Linux - Copyright (C) 1998, 1999, 2000 Ingo Molnar + Copyright (C) 1998, 1999, 2000 Ingo Molnar completely rewritten, based on the MD driver code from Marc Zyngier @@ -13,6 +13,11 @@ - RAID0 bugfixes: Mark Anthony Lisher - Devfs support by Richard Gooch + - lots of fixes and improvements to the RAID1/RAID5 and generic + RAID code (such as request based resynchronization): + + Neil Brown . + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) @@ -25,6 +30,7 @@ #include #include +#include #include #ifdef CONFIG_KMOD @@ -39,8 +45,6 @@ extern asmlinkage int sys_sched_yield(void); extern asmlinkage int sys_setsid(void); -extern unsigned long io_events[MAX_BLKDEV]; - #define MAJOR_NR MD_MAJOR #define MD_DRIVER @@ -56,6 +60,41 @@ static mdk_personality_t *pers[MAX_PERSONALITY] = {NULL, }; /* + * Current RAID-1,4,5 parallel reconstruction 'guaranteed speed limit' + * is 100 KB/sec, so the extra system load does not show up that much. + * Increase it if you want to have more _guaranteed_ speed. Note that + * the RAID driver will use the maximum available bandwith if the IO + * subsystem is idle. There is also an 'absolute maximum' reconstruction + * speed limit - in case reconstruction slows down your system despite + * idle IO detection. + * + * you can change it via /proc/sys/dev/raid/speed_limit_min and _max. + */ + +static int sysctl_speed_limit_min = 100; +static int sysctl_speed_limit_max = 100000; + +static struct ctl_table_header *raid_table_header; + +static ctl_table raid_table[] = { + {DEV_RAID_SPEED_LIMIT_MIN, "speed_limit_min", + &sysctl_speed_limit_min, sizeof(int), 0644, NULL, &proc_dointvec}, + {DEV_RAID_SPEED_LIMIT_MAX, "speed_limit_max", + &sysctl_speed_limit_max, sizeof(int), 0644, NULL, &proc_dointvec}, + {0} +}; + +static ctl_table raid_dir_table[] = { + {DEV_RAID, "raid", NULL, 0, 0555, raid_table}, + {0} +}; + +static ctl_table raid_root_table[] = { + {CTL_DEV, "dev", NULL, 0, 0555, raid_dir_table}, + {0} +}; + +/* * these have to be allocated separately because external * subsystems want to have a pre-defined structure */ @@ -215,8 +254,8 @@ blk_queue_make_request(q, md_make_request); q->plug_tq.sync = 0; - q->plug_tq.routine = &md_unplug_device; - q->plug_tq.data = mddev; + q->plug_tq.routine = &md_unplug_device; + q->plug_tq.data = mddev; /* * The 'base' mddev is the one with data NULL. @@ -504,7 +543,7 @@ struct buffer_head *bh = NULL; kdev_t dev = rdev->dev; mdp_super_t *sb; - u32 sb_offset; + unsigned long sb_offset; if (!rdev->sb) { MD_BUG(); @@ -517,8 +556,7 @@ */ sb_offset = calc_dev_sboffset(rdev->dev, rdev->mddev, 1); rdev->sb_offset = sb_offset; - printk("(read) %s's sb offset: %d", partition_name(dev), - sb_offset); + printk("(read) %s's sb offset: %ld", partition_name(dev), sb_offset); fsync_dev(dev); set_blocksize (dev, MD_SB_BYTES); bh = bread (dev, sb_offset / MD_SB_BLOCKS, MD_SB_BYTES); @@ -606,6 +644,18 @@ return NULL; } +static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2) +{ + struct md_list_head *tmp; + mdk_rdev_t *rdev; + + ITERATE_RDEV(mddev1,rdev,tmp) + if (match_dev_unit(mddev2, rdev->dev)) + return 1; + + return 0; +} + static MD_LIST_HEAD(all_raid_disks); static MD_LIST_HEAD(pending_raid_disks); @@ -798,7 +848,7 @@ static void print_rdev(mdk_rdev_t *rdev) { - printk(" rdev %s: O:%s, SZ:%08d F:%d DN:%d ", + printk(" 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) { @@ -815,9 +865,9 @@ mddev_t *mddev; printk("\n"); - printk(" **********************************\n"); - printk(" * *\n"); - printk(" **********************************\n"); + printk(" **********************************\n"); + printk(" * *\n"); + printk(" **********************************\n"); ITERATE_MDDEV(mddev,tmp) { printk("md%d: ", mdidx(mddev)); @@ -833,7 +883,7 @@ ITERATE_RDEV(mddev,rdev,tmp2) print_rdev(rdev); } - printk(" **********************************\n"); + printk(" **********************************\n"); printk("\n"); } @@ -907,7 +957,7 @@ { struct buffer_head *bh; kdev_t dev; - u32 sb_offset, size; + unsigned long sb_offset, size; mdp_super_t *sb; if (!rdev->sb) { @@ -926,7 +976,7 @@ dev = rdev->dev; sb_offset = calc_dev_sboffset(dev, rdev->mddev, 1); if (rdev->sb_offset != sb_offset) { - printk("%s's sb offset has changed from %d to %d, skipping\n", partition_name(dev), rdev->sb_offset, sb_offset); + printk("%s's sb offset has changed from %ld to %ld, skipping\n", partition_name(dev), rdev->sb_offset, sb_offset); goto skip; } /* @@ -936,11 +986,11 @@ */ size = calc_dev_size(dev, rdev->mddev, 1); if (size != rdev->size) { - printk("%s's size has changed from %d to %d since import, skipping\n", partition_name(dev), rdev->size, size); + printk("%s's size has changed from %ld to %ld since import, skipping\n", partition_name(dev), rdev->size, size); goto skip; } - printk("(write) %s's sb offset: %d\n", partition_name(dev), sb_offset); + printk("(write) %s's sb offset: %ld\n", partition_name(dev), sb_offset); fsync_dev(dev); set_blocksize(dev, MD_SB_BYTES); bh = getblk(dev, sb_offset / MD_SB_BLOCKS, MD_SB_BYTES); @@ -1053,7 +1103,7 @@ printk("%s ", partition_name(rdev->dev)); if (!rdev->faulty) { printk("[events: %08lx]", - (unsigned long)get_unaligned(&rdev->sb->events)); + (unsigned long)get_unaligned(&rdev->sb->events)); err += write_disk_sb(rdev); } else printk(")\n"); @@ -1244,7 +1294,7 @@ } printk("%s's event counter: %08lx\n", partition_name(rdev->dev), - (unsigned long)get_unaligned(&rdev->sb->events)); + (unsigned long)get_unaligned(&rdev->sb->events)); if (!freshest) { freshest = rdev; continue; @@ -1488,7 +1538,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: %dk < %dk\n", + "Dev %s smaller than chunk_size: %ldk < %dk\n", partition_name(rdev->dev), rdev->size, sb->chunk_size / 1024); return -EINVAL; @@ -2640,7 +2690,7 @@ case STOP_ARRAY: err = do_md_stop (mddev, 0); - goto done_unlock; + goto done; case STOP_ARRAY_RO: err = do_md_stop (mddev, 1); @@ -2817,13 +2867,13 @@ DECLARE_WAITQUEUE(wait, current); add_wait_queue(&thread->wqueue, &wait); + set_task_state(current, TASK_INTERRUPTIBLE); if (!test_bit(THREAD_WAKEUP, &thread->flags)) { - set_task_state(current, TASK_INTERRUPTIBLE); dprintk("thread %p went to sleep.\n", thread); schedule(); dprintk("thread %p woke up.\n", thread); - current->state = TASK_RUNNING; } + current->state = TASK_RUNNING; remove_wait_queue(&thread->wqueue, &wait); clear_bit(THREAD_WAKEUP, &thread->flags); @@ -2914,12 +2964,13 @@ int md_error (kdev_t dev, kdev_t rdev) { - mddev_t *mddev = kdev_to_mddev(dev); + mddev_t *mddev; mdk_rdev_t * rrdev; int rc; - printk("md_error dev:(%d:%d), rdev:(%d:%d), (caller: %p,%p,%p,%p).\n",MAJOR(dev),MINOR(dev),MAJOR(rdev),MINOR(rdev), __builtin_return_address(0),__builtin_return_address(1),__builtin_return_address(2),__builtin_return_address(3)); - + mddev = kdev_to_mddev(dev); +/* printk("md_error dev:(%d:%d), rdev:(%d:%d), (caller: %p,%p,%p,%p).\n",MAJOR(dev),MINOR(dev),MAJOR(rdev),MINOR(rdev), __builtin_return_address(0),__builtin_return_address(1),__builtin_return_address(2),__builtin_return_address(3)); + */ if (!mddev) { MD_BUG(); return 0; @@ -2970,11 +3021,10 @@ static int status_resync (char * page, mddev_t * mddev) { int sz = 0; - unsigned int blocksize, max_blocks, resync, res, dt, tt, et; + unsigned int max_blocks, resync, res, dt, tt, et; resync = mddev->curr_resync; - blocksize = blksize_size[MD_MAJOR][mdidx(mddev)]; - max_blocks = blk_size[MD_MAJOR][mdidx(mddev)] / (blocksize >> 10); + max_blocks = mddev->sb->size; /* * Should not happen. @@ -3093,7 +3143,7 @@ sz += status_resync (page+sz, mddev); } else { if (md_atomic_read(&mddev->resync_sem.count) != 1) - sz += sprintf(page + sz, " resync=DELAYED"); + sz += sprintf(page + sz, " resync=DELAYED"); } sz += sprintf(page + sz, "\n"); } @@ -3125,6 +3175,298 @@ return 0; } +static mdp_disk_t *get_spare(mddev_t *mddev) +{ + mdp_super_t *sb = mddev->sb; + mdp_disk_t *disk; + mdk_rdev_t *rdev; + struct md_list_head *tmp; + + ITERATE_RDEV(mddev,rdev,tmp) { + if (rdev->faulty) + continue; + if (!rdev->sb) { + MD_BUG(); + continue; + } + disk = &sb->disks[rdev->desc_nr]; + if (disk_faulty(disk)) { + MD_BUG(); + continue; + } + if (disk_active(disk)) + continue; + return disk; + } + return NULL; +} + +static int is_mddev_idle (mddev_t *mddev) +{ + mdk_rdev_t * rdev; + struct md_list_head *tmp; + int idle; + unsigned long curr_events; + + idle = 1; + ITERATE_RDEV(mddev,rdev,tmp) { + int major = MAJOR(rdev->dev); + int idx = disk_index(rdev->dev); + + curr_events = kstat.dk_drive_rblk[major][idx] + + kstat.dk_drive_wblk[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); + rdev->last_events = curr_events; + idle = 0; + } + } + return idle; +} + +MD_DECLARE_WAIT_QUEUE_HEAD(resync_wait); + +void md_done_sync(mddev_t *mddev, int blocks, int ok) +{ + /* another "blocks" (1K) blocks have been synced */ + atomic_sub(blocks, &mddev->recovery_active); + wake_up(&mddev->recovery_wait); + if (!ok) { + // stop recovery, signal do_sync .... + } +} + +int md_do_sync(mddev_t *mddev, mdp_disk_t *spare) +{ + mddev_t *mddev2; + unsigned int max_blocks, currspeed, + j, window, err, serialize; + kdev_t read_disk = mddev_to_kdev(mddev); + unsigned long starttime; + struct md_list_head *tmp; + unsigned long last_check; + + + err = down_interruptible(&mddev->resync_sem); + if (err) + goto out_nolock; + +recheck: + serialize = 0; + ITERATE_MDDEV(mddev2,tmp) { + if (mddev2 == mddev) + continue; + if (mddev2->curr_resync && match_mddev_units(mddev,mddev2)) { + printk(KERN_INFO "md: serializing resync, md%d has overlapping physical units with md%d!\n", mdidx(mddev), mdidx(mddev2)); + serialize = 1; + break; + } + } + if (serialize) { + interruptible_sleep_on(&resync_wait); + if (md_signal_pending(current)) { + md_flush_signals(); + err = -EINTR; + goto out; + } + goto recheck; + } + + mddev->curr_resync = 1; + + max_blocks = mddev->sb->size; + + printk(KERN_INFO "md: syncing RAID array md%d\n", mdidx(mddev)); + printk(KERN_INFO "md: minimum _guaranteed_ reconstruction speed: %d KB/sec/disc.\n", + sysctl_speed_limit_min); + printk(KERN_INFO "md: using maximum available idle IO bandwith (but not more than %d KB/sec) for reconstruction.\n", sysctl_speed_limit_max); + + /* + * Resync has low priority. + */ + current->priority = 1; + + is_mddev_idle(mddev); /* this also initializes IO event counters */ + starttime = jiffies; + mddev->resync_start = starttime; + + /* + * Tune reconstruction: + */ + window = md_maxreadahead[mdidx(mddev)]/1024; + printk(KERN_INFO "md: using %dk window, over a total of %d blocks.\n",window,max_blocks); + + atomic_set(&mddev->recovery_active, 0); + init_waitqueue_head(&mddev->recovery_wait); + last_check = 0; + for (j = 0; j < max_blocks;) { + int blocks; + if (j) + mddev->curr_resync = j; + +/* wait_event(mddev->recovery_wait, + atomic_read(&mddev->recovery_active) < window); +*/ + blocks = mddev->pers->sync_request(mddev, j); + + if (blocks < 0) { + err = blocks; + goto out; + } + atomic_add(blocks, &mddev->recovery_active); + j += blocks; + + if (last_check + window > j) + continue; + + run_task_queue(&tq_disk); //?? + + + if (md_signal_pending(current)) { + /* + * got a signal, exit. + */ + mddev->curr_resync = 0; + printk("md_do_sync() got signal ... exiting\n"); + md_flush_signals(); + err = -EINTR; + goto out; + } + + /* + * this loop exits only if either when we are slower than + * the 'hard' speed limit, or the system was IO-idle for + * a jiffy. + * the system might be non-idle CPU-wise, but we only care + * about not overloading the IO subsystem. (things like an + * e2fsck being done on the RAID array should execute fast) + */ +repeat: + if (md_need_resched(current)) + schedule(); + + currspeed = j/((jiffies-starttime)/HZ + 1) + 1; + if (currspeed > sysctl_speed_limit_min) { + current->priority = 1; + + if ((currspeed > sysctl_speed_limit_max) || + !is_mddev_idle(mddev)) { + current->state = TASK_INTERRUPTIBLE; + md_schedule_timeout(HZ/4); + if (!md_signal_pending(current)) + goto repeat; + } + } else + current->priority = 40; + } + wait_event(mddev->recovery_wait, atomic_read(&mddev->recovery_active)==0); + fsync_dev(read_disk); + printk(KERN_INFO "md: md%d: sync done.\n",mdidx(mddev)); + err = 0; + /* + * this also signals 'finished resyncing' to md_stop + */ +out: + up(&mddev->resync_sem); +out_nolock: + mddev->curr_resync = 0; + wake_up(&resync_wait); + return err; +} + + +/* + * This is a kernel thread which syncs a spare disk with the active array + * + * the amount of foolproofing might seem to be a tad excessive, but an + * early (not so error-safe) version of raid1syncd synced the first 0.5 gigs + * of my root partition with the first 0.5 gigs of my /home partition ... so + * i'm a bit nervous ;) + */ +void md_do_recovery (void *data) +{ + int err; + mddev_t *mddev; + mdp_super_t *sb; + mdp_disk_t *spare; + struct md_list_head *tmp; + + printk(KERN_INFO "md: recovery thread got woken up ...\n"); +restart: + ITERATE_MDDEV(mddev,tmp) { + sb = mddev->sb; + if (!sb) + continue; + if (mddev->recovery_running) + continue; + if (sb->active_disks == sb->raid_disks) + continue; + if (!sb->spare_disks) { + printk(KERN_ERR "md%d: no spare disk to reconstruct array! -- continuing in degraded mode\n", mdidx(mddev)); + continue; + } + /* + * now here we get the spare and resync it. + */ + if ((spare = get_spare(mddev)) == NULL) + continue; + printk(KERN_INFO "md%d: resyncing spare disk %s to replace failed disk\n", mdidx(mddev), partition_name(MKDEV(spare->major,spare->minor))); + if (!mddev->pers->diskop) + continue; + if (mddev->pers->diskop(mddev, &spare, DISKOP_SPARE_WRITE)) + continue; + down(&mddev->recovery_sem); + mddev->recovery_running = 1; + err = md_do_sync(mddev, spare); + if (err == -EIO) { + printk(KERN_INFO "md%d: spare disk %s failed, skipping to next spare.\n", mdidx(mddev), partition_name(MKDEV(spare->major,spare->minor))); + if (!disk_faulty(spare)) { + mddev->pers->diskop(mddev,&spare,DISKOP_SPARE_INACTIVE); + mark_disk_faulty(spare); + mark_disk_nonsync(spare); + mark_disk_inactive(spare); + sb->spare_disks--; + sb->working_disks--; + sb->failed_disks++; + } + } else + if (disk_faulty(spare)) + mddev->pers->diskop(mddev, &spare, + DISKOP_SPARE_INACTIVE); + if (err == -EINTR) { + /* + * Recovery got interrupted ... + * signal back that we have finished using the array. + */ + mddev->pers->diskop(mddev, &spare, + DISKOP_SPARE_INACTIVE); + up(&mddev->recovery_sem); + mddev->recovery_running = 0; + continue; + } else { + mddev->recovery_running = 0; + up(&mddev->recovery_sem); + } + if (!disk_faulty(spare)) { + /* + * the SPARE_ACTIVE diskop possibly changes the + * pointer too + */ + mddev->pers->diskop(mddev, &spare, DISKOP_SPARE_ACTIVE); + mark_disk_sync(spare); + mark_disk_active(spare); + sb->active_disks++; + sb->spare_disks--; + } + mddev->sb_dirty = 1; + md_update_sb(mddev); + goto restart; + } + printk(KERN_INFO "md: recovery thread finished ...\n"); + +} + int md_notify_reboot(struct notifier_block *this, unsigned long code, void *x) { @@ -3211,6 +3553,8 @@ int md__init md_init (void) { + static char * name = "mdrecoveryd"; + printk (KERN_INFO "md driver %d.%d.%d MAX_MD_DEVS=%d, MAX_REAL=%d\n", MD_MAJOR_VERSION, MD_MINOR_VERSION, MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MAX_REAL); @@ -3222,8 +3566,8 @@ } devfs_handle = devfs_mk_dir (NULL, "md", 0, NULL); devfs_register_series (devfs_handle, "%u",MAX_MD_DEVS,DEVFS_FL_DEFAULT, - MAJOR_NR, 0, S_IFBLK | S_IRUSR | S_IWUSR, 0, 0, - &md_fops, NULL); + MAJOR_NR, 0, S_IFBLK | S_IRUSR | S_IWUSR, 0, 0, + &md_fops, NULL); blk_dev[MD_MAJOR].queue = md_get_queue; @@ -3232,24 +3576,29 @@ gendisk_head = &md_gendisk; + 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"); + md_register_reboot_notifier(&md_notifier); + raid_table_header = register_sysctl_table(raid_root_table, 1); #ifdef CONFIG_MD_LINEAR linear_init (); #endif -#ifdef CONFIG_MD_STRIPED +#ifdef CONFIG_MD_RAID0 raid0_init (); #endif -#ifdef CONFIG_MD_MIRRORING +#ifdef CONFIG_MD_RAID1 raid1_init (); #endif #ifdef CONFIG_MD_RAID5 raid5_init (); #endif #if defined(CONFIG_MD_RAID5) || defined(CONFIG_MD_RAID5_MODULE) - /* - * pick a XOR routine, runtime. - */ + /* + * pick a XOR routine, runtime. + */ calibrate_xor_block(); #endif md_geninit(); @@ -3261,6 +3610,8 @@ MD_EXPORT_SYMBOL(unregister_md_personality); MD_EXPORT_SYMBOL(partition_name); MD_EXPORT_SYMBOL(md_error); +MD_EXPORT_SYMBOL(md_do_sync); +MD_EXPORT_SYMBOL(md_done_sync); MD_EXPORT_SYMBOL(md_recover_arrays); MD_EXPORT_SYMBOL(md_register_thread); MD_EXPORT_SYMBOL(md_unregister_thread); diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/block/raid0.c linux/drivers/block/raid0.c --- v2.3.99-pre7/linux/drivers/block/raid0.c Sat Feb 26 22:31:44 2000 +++ linux/drivers/block/raid0.c Fri May 12 11:36:30 2000 @@ -41,7 +41,7 @@ printk("raid0: looking at %s\n", partition_name(rdev1->dev)); c = 0; ITERATE_RDEV_ORDERED(mddev,rdev2,j2) { - printk("raid0: comparing %s(%d) with %s(%d)\n", partition_name(rdev1->dev), rdev1->size, partition_name(rdev2->dev), rdev2->size); + printk("raid0: comparing %s(%ld) with %s(%ld)\n", partition_name(rdev1->dev), rdev1->size, partition_name(rdev2->dev), rdev2->size); if (rdev2 == rdev1) { printk("raid0: END\n"); break; @@ -95,7 +95,7 @@ c++; if (!smallest || (rdev->size size)) { smallest = rdev; - printk(" (%d) is smallest!.\n", rdev->size); + printk(" (%ld) is smallest!.\n", rdev->size); } } else printk(" nope.\n"); @@ -326,13 +326,11 @@ static mdk_personality_t raid0_personality= { "raid0", - NULL, /* no special map */ raid0_make_request, NULL, /* no special end_request */ raid0_run, raid0_stop, raid0_status, - NULL, /* no ioctls */ 0, NULL, /* no error_handler */ NULL, /* no diskop */ diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/block/raid1.c linux/drivers/block/raid1.c --- v2.3.99-pre7/linux/drivers/block/raid1.c Sun Feb 20 21:12:38 2000 +++ linux/drivers/block/raid1.c Fri May 12 11:36:30 2000 @@ -1,6 +1,9 @@ -/************************************************************************ +/* * raid1.c : Multiple Devices driver for Linux - * Copyright (C) 1996 Ingo Molnar, Miguel de Icaza, Gadi Oxman + * + * Copyright (C) 1999, 2000 Ingo Molnar, Red Hat + * + * Copyright (C) 1996, 1997, 1998 Ingo Molnar, Miguel de Icaza, Gadi Oxman * * RAID-1 management functions. * @@ -15,50 +18,86 @@ */ #include -#include #include -#include -#include -#include +#include #include #define MAJOR_NR MD_MAJOR #define MD_DRIVER #define MD_PERSONALITY +#define MAX_LINEAR_SECTORS 128 + +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + /* * The following can be used to debug the driver */ -/*#define RAID1_DEBUG*/ -#ifdef RAID1_DEBUG -#define PRINTK(x) do { printk x; } while (0); +#define RAID1_DEBUG 0 + +#if RAID1_DEBUG +#define PRINTK(x...) printk(x) +#define inline +#define __inline__ #else -#define PRINTK(x) do { ; } while (0); +#define inline +#define __inline__ +#define PRINTK(x...) do { } while (0) #endif -#define MAX(a,b) ((a) > (b) ? (a) : (b)) -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -static struct md_personality raid1_personality; -static struct md_thread *raid1_thread = NULL; -struct buffer_head *raid1_retry_list = NULL; +static mdk_personality_t raid1_personality; +static md_spinlock_t retry_list_lock = MD_SPIN_LOCK_UNLOCKED; +struct buffer_head *raid1_retry_list = NULL, **raid1_retry_tail; -static int __raid1_map (struct md_dev *mddev, kdev_t *rdev, - unsigned long *rsector, unsigned long size) +static void * raid1_kmalloc (int size) { - struct raid1_data *raid_conf = (struct raid1_data *) mddev->private; - int i, n = raid_conf->raid_disks; + void * ptr; + /* + * now we are rather fault tolerant than nice, but + * there are a couple of places in the RAID code where we + * simply can not afford to fail an allocation because + * there is no failure return path (eg. make_request()) + */ + while (!(ptr = kmalloc (size, GFP_KERNEL))) + printk ("raid1: out of memory, retrying...\n"); + + memset(ptr, 0, size); + return ptr; +} + +static struct page * raid1_gfp (void) +{ + struct page *page; + /* + * now we are rather fault tolerant than nice, but + * there are a couple of places in the RAID code where we + * simply can not afford to fail an allocation because + * there is no failure return path (eg. make_request()) + * FIXME: be nicer here. + */ + while (!(page = (void*)alloc_page(GFP_KERNEL))) { + printk ("raid1: GFP out of memory, retrying...\n"); + schedule_timeout(2); + } + + return page; +} + +static int raid1_map (mddev_t *mddev, kdev_t *rdev, unsigned long size) +{ + raid1_conf_t *conf = mddev_to_conf(mddev); + int i, disks = MD_SB_DISKS; /* * Later we do read balancing on the read side * now we use the first available disk. */ - PRINTK(("raid1_map().\n")); - - for (i=0; imirrors[i].operational) { - *rdev = raid_conf->mirrors[i].dev; + for (i = 0; i < disks; i++) { + if (conf->mirrors[i].operational) { + *rdev = conf->mirrors[i].dev; return (0); } } @@ -67,59 +106,80 @@ return (-1); } -static int raid1_map (struct md_dev *mddev, kdev_t *rdev, - unsigned long *rsector, unsigned long size) +static void raid1_reschedule_retry (struct buffer_head *bh) { - return 0; + unsigned long flags; + struct raid1_bh * r1_bh = (struct raid1_bh *)(bh->b_dev_id); + mddev_t *mddev = r1_bh->mddev; + raid1_conf_t *conf = mddev_to_conf(mddev); + + md_spin_lock_irqsave(&retry_list_lock, flags); + if (raid1_retry_list == NULL) + raid1_retry_tail = &raid1_retry_list; + *raid1_retry_tail = bh; + raid1_retry_tail = &r1_bh->next_retry; + r1_bh->next_retry = NULL; + md_spin_unlock_irqrestore(&retry_list_lock, flags); + md_wakeup_thread(conf->thread); } -void raid1_reschedule_retry (struct buffer_head *bh) + +static void inline io_request_done(unsigned long sector, raid1_conf_t *conf, int phase) { - struct raid1_bh * r1_bh = (struct raid1_bh *)(bh->b_dev_id); + unsigned long flags; + spin_lock_irqsave(&conf->segment_lock, flags); + if (sector < conf->start_active) + conf->cnt_done--; + else if (sector >= conf->start_future && conf->phase == phase) + conf->cnt_future--; + else if (!--conf->cnt_pending) + wake_up(&conf->wait_ready); - PRINTK(("raid1_reschedule_retry().\n")); + spin_unlock_irqrestore(&conf->segment_lock, flags); +} - r1_bh->next_retry = raid1_retry_list; - raid1_retry_list = bh; - md_wakeup_thread(raid1_thread); +static void inline sync_request_done (unsigned long sector, raid1_conf_t *conf) +{ + unsigned long flags; + spin_lock_irqsave(&conf->segment_lock, flags); + if (sector >= conf->start_ready) + --conf->cnt_ready; + else if (sector >= conf->start_active) { + if (!--conf->cnt_active) { + conf->start_active = conf->start_ready; + wake_up(&conf->wait_done); + } + } + spin_unlock_irqrestore(&conf->segment_lock, flags); } /* - * raid1_end_buffer_io() is called when we have finished servicing a mirrored + * raid1_end_bh_io() is called when we have finished servicing a mirrored * operation and are ready to return a success/failure code to the buffer * cache layer. */ -static inline void raid1_end_buffer_io(struct raid1_bh *r1_bh, int uptodate) +static void raid1_end_bh_io (struct raid1_bh *r1_bh, int uptodate) { struct buffer_head *bh = r1_bh->master_bh; + io_request_done(bh->b_rsector, mddev_to_conf(r1_bh->mddev), + test_bit(R1BH_SyncPhase, &r1_bh->state)); + bh->b_end_io(bh, uptodate); kfree(r1_bh); } - -int raid1_one_error=0; - void raid1_end_request (struct buffer_head *bh, int uptodate) { struct raid1_bh * r1_bh = (struct raid1_bh *)(bh->b_dev_id); - unsigned long flags; - save_flags(flags); - cli(); - PRINTK(("raid1_end_request().\n")); - - if (raid1_one_error) { - raid1_one_error=0; - uptodate=0; - } /* * this branch is our 'one mirror IO has finished' event handler: */ if (!uptodate) md_error (bh->b_dev, bh->b_rdev); - else { + else /* - * Set BH_Uptodate in our master buffer_head, so that + * Set R1BH_Uptodate in our master buffer_head, so that * we will return a good error code for to the higher * levels even if IO on some other mirrored buffer fails. * @@ -127,8 +187,7 @@ * user-side. So if something waits for IO, then it will * wait for the 'master' buffer_head. */ - set_bit (BH_Uptodate, &r1_bh->state); - } + set_bit (R1BH_Uptodate, &r1_bh->state); /* * We split up the read and write side, imho they are @@ -136,239 +195,253 @@ */ if ( (r1_bh->cmd == READ) || (r1_bh->cmd == READA) ) { - - PRINTK(("raid1_end_request(), read branch.\n")); - /* * we have only one buffer_head on the read side */ + if (uptodate) { - PRINTK(("raid1_end_request(), read branch, uptodate.\n")); - raid1_end_buffer_io(r1_bh, uptodate); - restore_flags(flags); + raid1_end_bh_io(r1_bh, uptodate); return; } /* * oops, read error: */ printk(KERN_ERR "raid1: %s: rescheduling block %lu\n", - kdevname(bh->b_dev), bh->b_blocknr); - raid1_reschedule_retry (bh); - restore_flags(flags); + partition_name(bh->b_dev), bh->b_blocknr); + raid1_reschedule_retry(bh); return; } /* - * WRITE. - */ - PRINTK(("raid1_end_request(), write branch.\n")); - - /* + * WRITE: + * * Let's see if all mirrored write operations have finished - * already [we have irqs off, so we can decrease]: + * already. */ - if (!--r1_bh->remaining) { - struct md_dev *mddev = r1_bh->mddev; - struct raid1_data *raid_conf = (struct raid1_data *) mddev->private; - int i, n = raid_conf->raid_disks; + if (atomic_dec_and_test(&r1_bh->remaining)) { + int i, disks = MD_SB_DISKS; - PRINTK(("raid1_end_request(), remaining == 0.\n")); - - for ( i=0; imirror_bh[i]) kfree(r1_bh->mirror_bh[i]); + for ( i = 0; i < disks; i++) { + struct buffer_head *bh = r1_bh->mirror_bh[i]; + if (bh) { + // FIXME: make us a regular bcache member + kfree(bh); + } + } - raid1_end_buffer_io(r1_bh, test_bit(BH_Uptodate, &r1_bh->state)); + raid1_end_bh_io(r1_bh, test_bit(R1BH_Uptodate, &r1_bh->state)); } - else PRINTK(("raid1_end_request(), remaining == %u.\n", r1_bh->remaining)); - restore_flags(flags); } -/* This routine checks if the undelying device is an md device and in that - * case it maps the blocks before putting the request on the queue - */ -static inline void -map_and_make_request (int rw, struct buffer_head *bh) -{ - if (MAJOR (bh->b_rdev) == MD_MAJOR) - md_map (MINOR (bh->b_rdev), &bh->b_rdev, &bh->b_rsector, bh->b_size >> 9); - clear_bit(BH_Lock, &bh->b_state); - make_request (MAJOR (bh->b_rdev), rw, bh); -} - -static int -raid1_make_request (struct md_dev *mddev, int rw, struct buffer_head * bh) +static int raid1_make_request (request_queue_t *q, mddev_t *mddev, int rw, + struct buffer_head * bh) { - - struct raid1_data *raid_conf = (struct raid1_data *) mddev->private; + raid1_conf_t *conf = mddev_to_conf(mddev); struct buffer_head *mirror_bh[MD_SB_DISKS], *bh_req; struct raid1_bh * r1_bh; - int n = raid_conf->raid_disks, i, sum_bhs = 0, switch_disks = 0, sectors; + int disks = MD_SB_DISKS; + int i, sum_bhs = 0, switch_disks = 0, sectors; struct mirror_info *mirror; + DECLARE_WAITQUEUE(wait, current); - PRINTK(("raid1_make_request().\n")); - - while (!( /* FIXME: now we are rather fault tolerant than nice */ - r1_bh = kmalloc (sizeof (struct raid1_bh), GFP_KERNEL) - ) ) - { - printk ("raid1_make_request(#1): out of memory\n"); - current->policy |= SCHED_YIELD; - schedule(); - } - memset (r1_bh, 0, sizeof (struct raid1_bh)); - + if (!buffer_locked(bh)) + BUG(); + /* * make_request() can abort the operation when READA is being * used and no empty request is available. * * Currently, just replace the command with READ/WRITE. */ - if (rw == READA) rw = READ; + if (rw == READA) + rw = READ; - if (rw == WRITE) - mark_buffer_clean(bh); /* Too early ? */ + if (rw == WRITE) { + rw = WRITERAW; + /* + * we first clean the bh, then we start the IO, then + * when the IO has finished, we end_io the bh and + * mark it uptodate. This way we do not miss the + * case when the bh got dirty again during the IO. + * + * We do an important optimization here - if the + * buffer was not dirty and we are during resync or + * reconstruction, then we can skip writing it back + * to the master disk! (we still have to write it + * back to the other disks, because we are not sync + * yet.) + */ + if (atomic_set_buffer_clean(bh)) + __mark_buffer_clean(bh); + else { + bh->b_end_io(bh, test_bit(BH_Uptodate, &bh->b_state)); + return 0; + } + } + r1_bh = raid1_kmalloc (sizeof (struct raid1_bh)); -/* - * i think the read and write branch should be separated completely, since we want - * to do read balancing on the read side for example. Comments? :) --mingo - */ - r1_bh->master_bh=bh; - r1_bh->mddev=mddev; + spin_lock_irq(&conf->segment_lock); + wait_event_lock_irq(conf->wait_done, + bh->b_rsector < conf->start_active || + bh->b_rsector >= conf->start_future, + conf->segment_lock); + if (bh->b_rsector < conf->start_active) + conf->cnt_done++; + else { + conf->cnt_future++; + if (conf->phase) + set_bit(R1BH_SyncPhase, &r1_bh->state); + } + spin_unlock_irq(&conf->segment_lock); + + /* + * i think the read and write branch should be separated completely, + * since we want to do read balancing on the read side for example. + * Alternative implementations? :) --mingo + */ + + r1_bh->master_bh = bh; + r1_bh->mddev = mddev; r1_bh->cmd = rw; + bh->b_rsector = bh->b_blocknr * (bh->b_size>>9); + + if (rw == READ) { + int last_used = conf->last_used; - if (rw==READ || rw==READA) { - int last_used = raid_conf->last_used; - PRINTK(("raid1_make_request(), read branch.\n")); - mirror = raid_conf->mirrors + last_used; + /* + * read balancing logic: + */ + mirror = conf->mirrors + last_used; bh->b_rdev = mirror->dev; sectors = bh->b_size >> 9; - if (bh->b_blocknr * sectors == raid_conf->next_sect) { - raid_conf->sect_count += sectors; - if (raid_conf->sect_count >= mirror->sect_limit) + + switch_disks = 0; + if (bh->b_blocknr * sectors == conf->next_sect) { + conf->sect_count += sectors; + if (conf->sect_count >= mirror->sect_limit) switch_disks = 1; } else switch_disks = 1; - raid_conf->next_sect = (bh->b_blocknr + 1) * sectors; - if (switch_disks) { - PRINTK(("read-balancing: switching %d -> %d (%d sectors)\n", last_used, mirror->next, raid_conf->sect_count)); - raid_conf->sect_count = 0; - last_used = raid_conf->last_used = mirror->next; + conf->next_sect = (bh->b_blocknr + 1) * sectors; + /* + * Do not switch disks if full resync is in progress ... + */ + if (switch_disks && !conf->resync_mirrors) { + conf->sect_count = 0; + last_used = conf->last_used = mirror->next; /* - * Do not switch to write-only disks ... resyncing - * is in progress + * Do not switch to write-only disks ... + * reconstruction is in progress */ - while (raid_conf->mirrors[last_used].write_only) - raid_conf->last_used = raid_conf->mirrors[last_used].next; + while (conf->mirrors[last_used].write_only) + conf->last_used = conf->mirrors[last_used].next; } - PRINTK (("raid1 read queue: %d %d\n", MAJOR (bh->b_rdev), MINOR (bh->b_rdev))); bh_req = &r1_bh->bh_req; memcpy(bh_req, bh, sizeof(*bh)); bh_req->b_end_io = raid1_end_request; bh_req->b_dev_id = r1_bh; - map_and_make_request (rw, bh_req); + q = blk_get_queue(bh_req->b_rdev); + generic_make_request (q, rw, bh_req); return 0; } /* - * WRITE. + * WRITE: */ - PRINTK(("raid1_make_request(n=%d), write branch.\n",n)); - for (i = 0; i < n; i++) { + for (i = 0; i < disks; i++) { - if (!raid_conf->mirrors [i].operational) { + if (!conf->mirrors[i].operational) { /* * the r1_bh->mirror_bh[i] pointer remains NULL */ mirror_bh[i] = NULL; continue; } - + /* * We should use a private pool (size depending on NR_REQUEST), * to avoid writes filling up the memory with bhs * - * Such pools are much faster than kmalloc anyways (so we waste almost - * nothing by not using the master bh when writing and win alot of cleanness) - * - * but for now we are cool enough. --mingo - * + * Such pools are much faster than kmalloc anyways (so we waste + * almost nothing by not using the master bh when writing and + * win alot of cleanness) but for now we are cool enough. --mingo + * * It's safe to sleep here, buffer heads cannot be used in a shared - * manner in the write branch. Look how we lock the buffer at the beginning - * of this function to grok the difference ;) + * manner in the write branch. Look how we lock the buffer at the + * beginning of this function to grok the difference ;) */ - while (!( /* FIXME: now we are rather fault tolerant than nice */ - mirror_bh[i] = kmalloc (sizeof (struct buffer_head), GFP_KERNEL) - ) ) - { - printk ("raid1_make_request(#2): out of memory\n"); - current->policy |= SCHED_YIELD; - schedule(); - } - memset (mirror_bh[i], 0, sizeof (struct buffer_head)); - - /* - * prepare mirrored bh (fields ordered for max mem throughput): - */ - mirror_bh [i]->b_blocknr = bh->b_blocknr; - mirror_bh [i]->b_dev = bh->b_dev; - mirror_bh [i]->b_rdev = raid_conf->mirrors [i].dev; - mirror_bh [i]->b_rsector = bh->b_rsector; - mirror_bh [i]->b_state = (1<b_count, 1); - mirror_bh [i]->b_size = bh->b_size; - mirror_bh [i]->b_data = bh->b_data; - mirror_bh [i]->b_list = BUF_LOCKED; - mirror_bh [i]->b_end_io = raid1_end_request; - mirror_bh [i]->b_dev_id = r1_bh; - - r1_bh->mirror_bh[i] = mirror_bh[i]; + mirror_bh[i] = raid1_kmalloc(sizeof(struct buffer_head)); + mirror_bh[i]->b_this_page = (struct buffer_head *)1; + + /* + * prepare mirrored bh (fields ordered for max mem throughput): + */ + mirror_bh[i]->b_blocknr = bh->b_blocknr; + mirror_bh[i]->b_dev = bh->b_dev; + mirror_bh[i]->b_rdev = conf->mirrors[i].dev; + mirror_bh[i]->b_rsector = bh->b_rsector; + mirror_bh[i]->b_state = (1<b_count, 1); + mirror_bh[i]->b_size = bh->b_size; + mirror_bh[i]->b_data = bh->b_data; + mirror_bh[i]->b_list = BUF_LOCKED; + mirror_bh[i]->b_end_io = raid1_end_request; + mirror_bh[i]->b_dev_id = r1_bh; + + r1_bh->mirror_bh[i] = mirror_bh[i]; sum_bhs++; } - r1_bh->remaining = sum_bhs; - - PRINTK(("raid1_make_request(), write branch, sum_bhs=%d.\n",sum_bhs)); + md_atomic_set(&r1_bh->remaining, sum_bhs); /* - * We have to be a bit careful about the semaphore above, thats why we - * start the requests separately. Since kmalloc() could fail, sleep and - * make_request() can sleep too, this is the safer solution. Imagine, - * end_request decreasing the semaphore before we could have set it up ... - * We could play tricks with the semaphore (presetting it and correcting - * at the end if sum_bhs is not 'n' but we have to do end_request by hand - * if all requests finish until we had a chance to set up the semaphore - * correctly ... lots of races). - */ - for (i = 0; i < n; i++) - if (mirror_bh [i] != NULL) - map_and_make_request (rw, mirror_bh [i]); - + * We have to be a bit careful about the semaphore above, thats + * why we start the requests separately. Since kmalloc() could + * fail, sleep and make_request() can sleep too, this is the + * safer solution. Imagine, end_request decreasing the semaphore + * before we could have set it up ... We could play tricks with + * the semaphore (presetting it and correcting at the end if + * sum_bhs is not 'n' but we have to do end_request by hand if + * all requests finish until we had a chance to set up the + * semaphore correctly ... lots of races). + */ + for (i = 0; i < disks; i++) { + struct buffer_head *mbh = mirror_bh[i]; + if (mbh) { + q = blk_get_queue(mbh->b_rdev); + generic_make_request(q, rw, mbh); + } + } return (0); } - -static int raid1_status (char *page, int minor, struct md_dev *mddev) + +static int raid1_status (char *page, mddev_t *mddev) { - struct raid1_data *raid_conf = (struct raid1_data *) mddev->private; + raid1_conf_t *conf = mddev_to_conf(mddev); int sz = 0, i; - sz += sprintf (page+sz, " [%d/%d] [", raid_conf->raid_disks, raid_conf->working_disks); - for (i = 0; i < raid_conf->raid_disks; i++) - sz += sprintf (page+sz, "%s", raid_conf->mirrors [i].operational ? "U" : "_"); + sz += sprintf (page+sz, " [%d/%d] [", conf->raid_disks, + conf->working_disks); + for (i = 0; i < conf->raid_disks; i++) + sz += sprintf (page+sz, "%s", + conf->mirrors[i].operational ? "U" : "_"); sz += sprintf (page+sz, "]"); return sz; } -static void raid1_fix_links (struct raid1_data *raid_conf, int failed_index) +static void unlink_disk (raid1_conf_t *conf, int target) { - int disks = raid_conf->raid_disks; - int j; + int disks = MD_SB_DISKS; + int i; - for (j = 0; j < disks; j++) - if (raid_conf->mirrors [j].next == failed_index) - raid_conf->mirrors [j].next = raid_conf->mirrors [failed_index].next; + for (i = 0; i < disks; i++) + if (conf->mirrors[i].next == target) + conf->mirrors[i].next = conf->mirrors[target].next; } #define LAST_DISK KERN_ALERT \ @@ -379,7 +452,7 @@ #define DISK_FAILED KERN_ALERT \ "raid1: Disk failure on %s, disabling device. \n" \ -" Operation continuing on %d devices\n" +" Operation continuing on %d devices\n" #define START_SYNCING KERN_ALERT \ "raid1: start syncing spare disk.\n" @@ -387,48 +460,53 @@ #define ALREADY_SYNCING KERN_INFO \ "raid1: syncing already in progress.\n" -static int raid1_error (struct md_dev *mddev, kdev_t dev) +static void mark_disk_bad (mddev_t *mddev, int failed) { - struct raid1_data *raid_conf = (struct raid1_data *) mddev->private; - struct mirror_info *mirror; - md_superblock_t *sb = mddev->sb; - int disks = raid_conf->raid_disks; - int i; + raid1_conf_t *conf = mddev_to_conf(mddev); + struct mirror_info *mirror = conf->mirrors+failed; + mdp_super_t *sb = mddev->sb; + + mirror->operational = 0; + unlink_disk(conf, failed); + mark_disk_faulty(sb->disks+mirror->number); + mark_disk_nonsync(sb->disks+mirror->number); + mark_disk_inactive(sb->disks+mirror->number); + sb->active_disks--; + sb->working_disks--; + sb->failed_disks++; + mddev->sb_dirty = 1; + md_wakeup_thread(conf->thread); + conf->working_disks--; + printk (DISK_FAILED, partition_name (mirror->dev), + conf->working_disks); +} - PRINTK(("raid1_error called\n")); +static int raid1_error (mddev_t *mddev, kdev_t dev) +{ + raid1_conf_t *conf = mddev_to_conf(mddev); + struct mirror_info * mirrors = conf->mirrors; + int disks = MD_SB_DISKS; + int i; - if (raid_conf->working_disks == 1) { + if (conf->working_disks == 1) { /* * Uh oh, we can do nothing if this is our last disk, but * first check if this is a queued request for a device * which has just failed. */ - for (i = 0, mirror = raid_conf->mirrors; i < disks; - i++, mirror++) - if (mirror->dev == dev && !mirror->operational) + for (i = 0; i < disks; i++) { + if (mirrors[i].dev==dev && !mirrors[i].operational) return 0; + } printk (LAST_DISK); } else { - /* Mark disk as unusable */ - for (i = 0, mirror = raid_conf->mirrors; i < disks; - i++, mirror++) { - if (mirror->dev == dev && mirror->operational){ - mirror->operational = 0; - raid1_fix_links (raid_conf, i); - sb->disks[mirror->number].state |= - (1 << MD_FAULTY_DEVICE); - sb->disks[mirror->number].state &= - ~(1 << MD_SYNC_DEVICE); - sb->disks[mirror->number].state &= - ~(1 << MD_ACTIVE_DEVICE); - sb->active_disks--; - sb->working_disks--; - sb->failed_disks++; - mddev->sb_dirty = 1; - md_wakeup_thread(raid1_thread); - raid_conf->working_disks--; - printk (DISK_FAILED, kdevname (dev), - raid_conf->working_disks); + /* + * Mark disk as unusable + */ + for (i = 0; i < disks; i++) { + if (mirrors[i].dev==dev && mirrors[i].operational) { + mark_disk_bad(mddev, i); + break; } } } @@ -441,219 +519,658 @@ #undef START_SYNCING /* - * This is the personality-specific hot-addition routine + * Insert the spare disk into the drive-ring */ +static void link_disk(raid1_conf_t *conf, struct mirror_info *mirror) +{ + int j, next; + int disks = MD_SB_DISKS; + struct mirror_info *p = conf->mirrors; -#define NO_SUPERBLOCK KERN_ERR \ -"raid1: cannot hot-add disk to the array with no RAID superblock\n" + for (j = 0; j < disks; j++, p++) + if (p->operational && !p->write_only) { + next = p->next; + p->next = mirror->raid_disk; + mirror->next = next; + return; + } -#define WRONG_LEVEL KERN_ERR \ -"raid1: hot-add: level of disk is not RAID-1\n" + printk("raid1: bug: no read-operational devices\n"); +} -#define HOT_ADD_SUCCEEDED KERN_INFO \ -"raid1: device %s hot-added\n" +static void print_raid1_conf (raid1_conf_t *conf) +{ + int i; + struct mirror_info *tmp; -static int raid1_hot_add_disk (struct md_dev *mddev, kdev_t dev) + printk("RAID1 conf printout:\n"); + if (!conf) { + printk("(conf==NULL)\n"); + return; + } + printk(" --- wd:%d rd:%d nd:%d\n", conf->working_disks, + conf->raid_disks, conf->nr_disks); + + for (i = 0; i < MD_SB_DISKS; i++) { + tmp = conf->mirrors + i; + printk(" disk %d, s:%d, o:%d, n:%d rd:%d us:%d dev:%s\n", + i, tmp->spare,tmp->operational, + tmp->number,tmp->raid_disk,tmp->used_slot, + partition_name(tmp->dev)); + } +} + +static int raid1_diskop(mddev_t *mddev, mdp_disk_t **d, int state) { - unsigned long flags; - struct raid1_data *raid_conf = (struct raid1_data *) mddev->private; - struct mirror_info *mirror; - md_superblock_t *sb = mddev->sb; - struct real_dev * realdev; - int n; + int err = 0; + int i, failed_disk=-1, spare_disk=-1, removed_disk=-1, added_disk=-1; + raid1_conf_t *conf = mddev->private; + struct mirror_info *tmp, *sdisk, *fdisk, *rdisk, *adisk; + mdp_super_t *sb = mddev->sb; + mdp_disk_t *failed_desc, *spare_desc, *added_desc; + print_raid1_conf(conf); + md_spin_lock_irq(&conf->device_lock); /* - * The device has its superblock already read and it was found - * to be consistent for generic RAID usage. Now we check whether - * it's usable for RAID-1 hot addition. + * find the disk ... */ + switch (state) { - n = mddev->nb_dev++; - realdev = &mddev->devices[n]; - if (!realdev->sb) { - printk (NO_SUPERBLOCK); - return -EINVAL; - } - if (realdev->sb->level != 1) { - printk (WRONG_LEVEL); - return -EINVAL; + case DISKOP_SPARE_ACTIVE: + + /* + * Find the failed disk within the RAID1 configuration ... + * (this can only be in the first conf->working_disks part) + */ + for (i = 0; i < conf->raid_disks; i++) { + tmp = conf->mirrors + i; + if ((!tmp->operational && !tmp->spare) || + !tmp->used_slot) { + failed_disk = i; + break; + } + } + /* + * When we activate a spare disk we _must_ have a disk in + * the lower (active) part of the array to replace. + */ + if ((failed_disk == -1) || (failed_disk >= conf->raid_disks)) { + MD_BUG(); + err = 1; + goto abort; + } + /* fall through */ + + case DISKOP_SPARE_WRITE: + case DISKOP_SPARE_INACTIVE: + + /* + * Find the spare disk ... (can only be in the 'high' + * area of the array) + */ + for (i = conf->raid_disks; i < MD_SB_DISKS; i++) { + tmp = conf->mirrors + i; + if (tmp->spare && tmp->number == (*d)->number) { + spare_disk = i; + break; + } + } + if (spare_disk == -1) { + MD_BUG(); + err = 1; + goto abort; + } + break; + + case DISKOP_HOT_REMOVE_DISK: + + for (i = 0; i < MD_SB_DISKS; i++) { + tmp = conf->mirrors + i; + if (tmp->used_slot && (tmp->number == (*d)->number)) { + if (tmp->operational) { + err = -EBUSY; + goto abort; + } + removed_disk = i; + break; + } + } + if (removed_disk == -1) { + MD_BUG(); + err = 1; + goto abort; + } + break; + + case DISKOP_HOT_ADD_DISK: + + for (i = conf->raid_disks; i < MD_SB_DISKS; i++) { + tmp = conf->mirrors + i; + if (!tmp->used_slot) { + added_disk = i; + break; + } + } + if (added_disk == -1) { + MD_BUG(); + err = 1; + goto abort; + } + break; } - /* FIXME: are there other things left we could sanity-check? */ + switch (state) { + /* + * Switch the spare disk to write-only mode: + */ + case DISKOP_SPARE_WRITE: + sdisk = conf->mirrors + spare_disk; + sdisk->operational = 1; + sdisk->write_only = 1; + break; /* - * We have to disable interrupts, as our RAID-1 state is used - * from irq handlers as well. + * Deactivate a spare disk: */ - save_flags(flags); - cli(); + case DISKOP_SPARE_INACTIVE: + sdisk = conf->mirrors + spare_disk; + sdisk->operational = 0; + sdisk->write_only = 0; + break; + /* + * Activate (mark read-write) the (now sync) spare disk, + * which means we switch it's 'raid position' (->raid_disk) + * with the failed disk. (only the first 'conf->nr_disks' + * slots are used for 'real' disks and we must preserve this + * property) + */ + case DISKOP_SPARE_ACTIVE: - raid_conf->raid_disks++; - mirror = raid_conf->mirrors+n; + sdisk = conf->mirrors + spare_disk; + fdisk = conf->mirrors + failed_disk; - mirror->number=n; - mirror->raid_disk=n; - mirror->dev=dev; - mirror->next=0; /* FIXME */ - mirror->sect_limit=128; + spare_desc = &sb->disks[sdisk->number]; + failed_desc = &sb->disks[fdisk->number]; - mirror->operational=0; - mirror->spare=1; - mirror->write_only=0; + if (spare_desc != *d) { + MD_BUG(); + err = 1; + goto abort; + } - sb->disks[n].state |= (1 << MD_FAULTY_DEVICE); - sb->disks[n].state &= ~(1 << MD_SYNC_DEVICE); - sb->disks[n].state &= ~(1 << MD_ACTIVE_DEVICE); - sb->nr_disks++; - sb->spare_disks++; + if (spare_desc->raid_disk != sdisk->raid_disk) { + MD_BUG(); + err = 1; + goto abort; + } + + if (sdisk->raid_disk != spare_disk) { + MD_BUG(); + err = 1; + goto abort; + } - restore_flags(flags); + if (failed_desc->raid_disk != fdisk->raid_disk) { + MD_BUG(); + err = 1; + goto abort; + } - md_update_sb(MINOR(dev)); + if (fdisk->raid_disk != failed_disk) { + MD_BUG(); + err = 1; + goto abort; + } - printk (HOT_ADD_SUCCEEDED, kdevname(realdev->dev)); + /* + * do the switch finally + */ + xchg_values(*spare_desc, *failed_desc); + xchg_values(*fdisk, *sdisk); - return 0; -} + /* + * (careful, 'failed' and 'spare' are switched from now on) + * + * we want to preserve linear numbering and we want to + * give the proper raid_disk number to the now activated + * disk. (this means we switch back these values) + */ + + xchg_values(spare_desc->raid_disk, failed_desc->raid_disk); + xchg_values(sdisk->raid_disk, fdisk->raid_disk); + xchg_values(spare_desc->number, failed_desc->number); + xchg_values(sdisk->number, fdisk->number); -#undef NO_SUPERBLOCK -#undef WRONG_LEVEL -#undef HOT_ADD_SUCCEEDED + *d = failed_desc; -/* - * Insert the spare disk into the drive-ring - */ -static void add_ring(struct raid1_data *raid_conf, struct mirror_info *mirror) -{ - int j, next; - struct mirror_info *p = raid_conf->mirrors; + if (sdisk->dev == MKDEV(0,0)) + sdisk->used_slot = 0; + /* + * this really activates the spare. + */ + fdisk->spare = 0; + fdisk->write_only = 0; + link_disk(conf, fdisk); - for (j = 0; j < raid_conf->raid_disks; j++, p++) - if (p->operational && !p->write_only) { - next = p->next; - p->next = mirror->raid_disk; - mirror->next = next; - return; + /* + * if we activate a spare, we definitely replace a + * non-operational disk slot in the 'low' area of + * the disk array. + */ + + conf->working_disks++; + + break; + + case DISKOP_HOT_REMOVE_DISK: + rdisk = conf->mirrors + removed_disk; + + if (rdisk->spare && (removed_disk < conf->raid_disks)) { + MD_BUG(); + err = 1; + goto abort; } - printk("raid1: bug: no read-operational devices\n"); + rdisk->dev = MKDEV(0,0); + rdisk->used_slot = 0; + conf->nr_disks--; + break; + + case DISKOP_HOT_ADD_DISK: + adisk = conf->mirrors + added_disk; + added_desc = *d; + + if (added_disk != added_desc->number) { + MD_BUG(); + err = 1; + goto abort; + } + + adisk->number = added_desc->number; + adisk->raid_disk = added_desc->raid_disk; + adisk->dev = MKDEV(added_desc->major,added_desc->minor); + + adisk->operational = 0; + adisk->write_only = 0; + adisk->spare = 1; + adisk->used_slot = 1; + conf->nr_disks++; + + break; + + default: + MD_BUG(); + err = 1; + goto abort; + } +abort: + md_spin_unlock_irq(&conf->device_lock); + print_raid1_conf(conf); + return err; } -static int raid1_mark_spare(struct md_dev *mddev, md_descriptor_t *spare, - int state) -{ - int i = 0, failed_disk = -1; - struct raid1_data *raid_conf = mddev->private; - struct mirror_info *mirror = raid_conf->mirrors; - md_descriptor_t *descriptor; - unsigned long flags; - for (i = 0; i < MD_SB_DISKS; i++, mirror++) { - if (mirror->spare && mirror->number == spare->number) - goto found; - } - return 1; -found: - for (i = 0, mirror = raid_conf->mirrors; i < raid_conf->raid_disks; - i++, mirror++) - if (!mirror->operational) - failed_disk = i; +#define IO_ERROR KERN_ALERT \ +"raid1: %s: unrecoverable I/O read error for block %lu\n" - save_flags(flags); - cli(); - switch (state) { - case SPARE_WRITE: - mirror->operational = 1; - mirror->write_only = 1; - raid_conf->raid_disks = MAX(raid_conf->raid_disks, - mirror->raid_disk + 1); - break; - case SPARE_INACTIVE: - mirror->operational = 0; - mirror->write_only = 0; - break; - case SPARE_ACTIVE: - mirror->spare = 0; - mirror->write_only = 0; - raid_conf->working_disks++; - add_ring(raid_conf, mirror); - - if (failed_disk != -1) { - descriptor = &mddev->sb->disks[raid_conf->mirrors[failed_disk].number]; - i = spare->raid_disk; - spare->raid_disk = descriptor->raid_disk; - descriptor->raid_disk = i; - } - break; - default: - printk("raid1_mark_spare: bug: state == %d\n", state); - restore_flags(flags); - return 1; - } - restore_flags(flags); - return 0; -} +#define REDIRECT_SECTOR KERN_ERR \ +"raid1: %s: redirecting sector %lu to another mirror\n" /* * This is a kernel thread which: * * 1. Retries failed read operations on working mirrors. * 2. Updates the raid superblock when problems encounter. + * 3. Performs writes following reads for array syncronising. */ -void raid1d (void *data) +static void end_sync_write(struct buffer_head *bh, int uptodate); +static void end_sync_read(struct buffer_head *bh, int uptodate); + +static void raid1d (void *data) { + struct raid1_bh *r1_bh; struct buffer_head *bh; - kdev_t dev; unsigned long flags; - struct raid1_bh * r1_bh; - struct md_dev *mddev; + request_queue_t *q; + mddev_t *mddev; + kdev_t dev; - PRINTK(("raid1d() active\n")); - save_flags(flags); - cli(); - while (raid1_retry_list) { + + for (;;) { + md_spin_lock_irqsave(&retry_list_lock, flags); bh = raid1_retry_list; + if (!bh) + break; r1_bh = (struct raid1_bh *)(bh->b_dev_id); raid1_retry_list = r1_bh->next_retry; - restore_flags(flags); + md_spin_unlock_irqrestore(&retry_list_lock, flags); - mddev = md_dev + MINOR(bh->b_dev); + mddev = kdev_to_mddev(bh->b_dev); if (mddev->sb_dirty) { - printk("dirty sb detected, updating.\n"); + printk(KERN_INFO "dirty sb detected, updating.\n"); mddev->sb_dirty = 0; - md_update_sb(MINOR(bh->b_dev)); + md_update_sb(mddev); } - dev = bh->b_rdev; - __raid1_map (md_dev + MINOR(bh->b_dev), &bh->b_rdev, &bh->b_rsector, bh->b_size >> 9); - if (bh->b_rdev == dev) { - printk (KERN_ALERT - "raid1: %s: unrecoverable I/O read error for block %lu\n", - kdevname(bh->b_dev), bh->b_blocknr); - raid1_end_buffer_io(r1_bh, 0); - } else { - printk (KERN_ERR "raid1: %s: redirecting sector %lu to another mirror\n", - kdevname(bh->b_dev), bh->b_blocknr); - map_and_make_request (r1_bh->cmd, bh); + switch(r1_bh->cmd) { + case SPECIAL: + /* have to allocate lots of bh structures and + * schedule writes + */ + if (test_bit(R1BH_Uptodate, &r1_bh->state)) { + int i, sum_bhs = 0; + int disks = MD_SB_DISKS; + struct buffer_head *mirror_bh[MD_SB_DISKS]; + raid1_conf_t *conf; + + conf = mddev_to_conf(mddev); + for (i = 0; i < disks ; i++) { + if (!conf->mirrors[i].operational) { + mirror_bh[i] = NULL; + continue; + } + if (i==conf->last_used) { + /* we read from here, no need to write */ + mirror_bh[i] = NULL; + continue; + } + if (i < conf->raid_disks + && !conf->resync_mirrors) { + /* don't need to write this, + * we are just rebuilding */ + mirror_bh[i] = NULL; + continue; + } + + mirror_bh[i] = raid1_kmalloc(sizeof(struct buffer_head)); + mirror_bh[i]->b_this_page = (struct buffer_head *)1; + + /* + * prepare mirrored bh (fields ordered for max mem throughput): + */ + mirror_bh[i]->b_blocknr = bh->b_blocknr; + mirror_bh[i]->b_dev = bh->b_dev; + mirror_bh[i]->b_rdev = conf->mirrors[i].dev; + mirror_bh[i]->b_rsector = bh->b_rsector; + mirror_bh[i]->b_state = (1<b_count, 1); + mirror_bh[i]->b_size = bh->b_size; + mirror_bh[i]->b_data = bh->b_data; + mirror_bh[i]->b_list = BUF_LOCKED; + mirror_bh[i]->b_end_io = end_sync_write; + mirror_bh[i]->b_dev_id = r1_bh; + + r1_bh->mirror_bh[i] = mirror_bh[i]; + sum_bhs++; + } + md_atomic_set(&r1_bh->remaining, sum_bhs); + for ( i = 0; i < disks ; i++) { + struct buffer_head *mbh = mirror_bh[i]; + if (mbh) { + q = blk_get_queue(mbh->b_rdev); + generic_make_request(q, WRITE, mbh); + } + } + } else { + dev = bh->b_rdev; + raid1_map (mddev, &bh->b_rdev, bh->b_size >> 9); + if (bh->b_rdev == dev) { + printk (IO_ERROR, partition_name(bh->b_dev), bh->b_blocknr); + md_done_sync(mddev, bh->b_size>>10, 0); + } else { + printk (REDIRECT_SECTOR, + partition_name(bh->b_dev), bh->b_blocknr); + q = blk_get_queue(bh->b_rdev); + generic_make_request (q, READ, bh); + } + } + + break; + case READ: + case READA: + dev = bh->b_rdev; + + raid1_map (mddev, &bh->b_rdev, bh->b_size >> 9); + if (bh->b_rdev == dev) { + printk (IO_ERROR, partition_name(bh->b_dev), bh->b_blocknr); + raid1_end_bh_io(r1_bh, 0); + } else { + printk (REDIRECT_SECTOR, + partition_name(bh->b_dev), bh->b_blocknr); + q = blk_get_queue(bh->b_rdev); + generic_make_request (q, r1_bh->cmd, bh); + } + break; } - cli(); } - restore_flags(flags); + md_spin_unlock_irqrestore(&retry_list_lock, flags); +} +#undef IO_ERROR +#undef REDIRECT_SECTOR + +/* + * Private kernel thread to reconstruct mirrors after an unclean + * shutdown. + */ +static void raid1syncd (void *data) +{ + raid1_conf_t *conf = data; + mddev_t *mddev = conf->mddev; + + if (!conf->resync_mirrors) + return; + if (conf->resync_mirrors == 2) + return; + down(&mddev->recovery_sem); + if (md_do_sync(mddev, NULL)) { + up(&mddev->recovery_sem); + return; + } + /* + * Only if everything went Ok. + */ + conf->resync_mirrors = 0; + up(&mddev->recovery_sem); +} + +/* + * perform a "sync" on one "block" + * + * We need to make sure that no normal I/O request - particularly write + * requests - conflict with active sync requests. + * This is achieved by conceptually dividing the device space into a + * number of sections: + * DONE: 0 .. a-1 These blocks are in-sync + * ACTIVE: a.. b-1 These blocks may have active sync requests, but + * no normal IO requests + * READY: b .. c-1 These blocks have no normal IO requests - sync + * request may be happening + * PENDING: c .. d-1 These blocks may have IO requests, but no new + * ones will be added + * FUTURE: d .. end These blocks are not to be considered yet. IO may + * be happening, but not sync + * + * We keep a + * phase which flips (0 or 1) each time d moves and + * a count of: + * z = active io requests in FUTURE since d moved - marked with + * current phase + * y = active io requests in FUTURE before d moved, or PENDING - + * marked with previous phase + * x = active sync requests in READY + * w = active sync requests in ACTIVE + * v = active io requests in DONE + * + * Normally, a=b=c=d=0 and z= active io requests + * or a=b=c=d=END and v= active io requests + * Allowed changes to a,b,c,d: + * A: c==d && y==0 -> d+=window, y=z, z=0, phase=!phase + * B: y==0 -> c=d + * C: b=c, w+=x, x=0 + * D: w==0 -> a=b + * E: a==b==c==d==end -> a=b=c=d=0, z=v, v=0 + * + * At start of sync we apply A. + * When y reaches 0, we apply B then A then being sync requests + * When sync point reaches c-1, we wait for y==0, and W==0, and + * then apply apply B then A then D then C. + * Finally, we apply E + * + * The sync request simply issues a "read" against a working drive + * This is marked so that on completion the raid1d thread is woken to + * issue suitable write requests + */ + +static int raid1_sync_request (mddev_t *mddev, unsigned long block_nr) +{ + raid1_conf_t *conf = mddev_to_conf(mddev); + struct mirror_info *mirror; + request_queue_t *q; + struct raid1_bh *r1_bh; + struct buffer_head *bh; + int bsize; + + spin_lock_irq(&conf->segment_lock); + if (!block_nr) { + /* initialize ...*/ + conf->start_active = 0; + conf->start_ready = 0; + conf->start_pending = 0; + conf->start_future = 0; + conf->phase = 0; + conf->window = 128; + conf->cnt_future += conf->cnt_done+conf->cnt_pending; + conf->cnt_done = conf->cnt_pending = 0; + if (conf->cnt_ready || conf->cnt_active) + MD_BUG(); + } + while ((block_nr<<1) >= conf->start_pending) { + PRINTK("wait .. sect=%lu start_active=%d ready=%d pending=%d future=%d, cnt_done=%d active=%d ready=%d pending=%d future=%d\n", + block_nr<<1, conf->start_active, conf->start_ready, conf->start_pending, conf->start_future, + conf->cnt_done, conf->cnt_active, conf->cnt_ready, conf->cnt_pending, conf->cnt_future); + wait_event_lock_irq(conf->wait_done, + !conf->cnt_active, + conf->segment_lock); + wait_event_lock_irq(conf->wait_ready, + !conf->cnt_pending, + conf->segment_lock); + conf->start_active = conf->start_ready; + conf->start_ready = conf->start_pending; + conf->start_pending = conf->start_future; + conf->start_future = conf->start_future+conf->window; + // Note: falling of the end is not a problem + conf->phase = conf->phase ^1; + conf->cnt_active = conf->cnt_ready; + conf->cnt_ready = 0; + conf->cnt_pending = conf->cnt_future; + conf->cnt_future = 0; + wake_up(&conf->wait_done); + } + conf->cnt_ready++; + spin_unlock_irq(&conf->segment_lock); + + + /* If reconstructing, and >1 working disc, + * could dedicate one to rebuild and others to + * service read requests .. + */ + mirror = conf->mirrors+conf->last_used; + + r1_bh = raid1_kmalloc (sizeof (struct raid1_bh)); + r1_bh->master_bh = NULL; + r1_bh->mddev = mddev; + r1_bh->cmd = SPECIAL; + bh = &r1_bh->bh_req; + memset(bh, 0, sizeof(*bh)); + + bh->b_blocknr = block_nr; + bsize = 1024; + while (!(bh->b_blocknr & 1) && bsize < PAGE_SIZE + && (bh->b_blocknr+2)*(bsize>>10) < mddev->sb->size) { + bh->b_blocknr >>= 1; + bsize <<= 1; + } + bh->b_size = bsize; + bh->b_list = BUF_LOCKED; + bh->b_dev = mddev_to_kdev(mddev); + bh->b_rdev = mirror->dev; + bh->b_state = (1<b_page = raid1_gfp(); + bh->b_data = (char *) page_address(bh->b_page); + bh->b_end_io = end_sync_read; + bh->b_dev_id = (void *) r1_bh; + bh->b_rsector = block_nr<<1; + init_waitqueue_head(&bh->b_wait); + + q = blk_get_queue(bh->b_rdev); + generic_make_request(q, READ, bh); + drive_stat_acct(bh->b_rdev, READ, -bh->b_size/512, 0); + + return (bsize >> 10); +} + +static void end_sync_read(struct buffer_head *bh, int uptodate) +{ + struct raid1_bh * r1_bh = (struct raid1_bh *)(bh->b_dev_id); + + /* we have read a block, now it needs to be re-written, + * or re-read if the read failed. + * We don't do much here, just schedule handling by raid1d + */ + if (!uptodate) + md_error (bh->b_dev, bh->b_rdev); + else + set_bit(R1BH_Uptodate, &r1_bh->state); + raid1_reschedule_retry(bh); +} + +static void end_sync_write(struct buffer_head *bh, int uptodate) +{ + struct raid1_bh * r1_bh = (struct raid1_bh *)(bh->b_dev_id); + + if (!uptodate) + md_error (bh->b_dev, bh->b_rdev); + if (atomic_dec_and_test(&r1_bh->remaining)) { + int i, disks = MD_SB_DISKS; + mddev_t *mddev = r1_bh->mddev; + unsigned long sect = bh->b_rsector; + int size = bh->b_size; + + free_page((unsigned long)bh->b_data); + for ( i = 0; i < disks; i++) { + struct buffer_head *bh = r1_bh->mirror_bh[i]; + if (bh) { + // FIXME: make us a regular bcache member + kfree(bh); + } + } + kfree(r1_bh); + sync_request_done(sect, mddev_to_conf(mddev)); + md_done_sync(mddev,size>>10, uptodate); + } } /* * This will catch the scenario in which one of the mirrors was * mounted as a normal device rather than as a part of a raid set. + * + * check_consistency is very personality-dependent, eg. RAID5 cannot + * do this check, it uses another method. */ -static int __check_consistency (struct md_dev *mddev, int row) +static int __check_consistency (mddev_t *mddev, int row) { - struct raid1_data *raid_conf = mddev->private; + raid1_conf_t *conf = mddev_to_conf(mddev); + int disks = MD_SB_DISKS; kdev_t dev; struct buffer_head *bh = NULL; int i, rc = 0; char *buffer = NULL; - for (i = 0; i < raid_conf->raid_disks; i++) { - if (!raid_conf->mirrors[i].operational) + for (i = 0; i < disks; i++) { + printk("(checking disk %d)\n",i); + if (!conf->mirrors[i].operational) continue; - dev = raid_conf->mirrors[i].dev; + printk("(really checking disk %d)\n",i); + dev = conf->mirrors[i].dev; set_blocksize(dev, 4096); if ((bh = bread(dev, row / 4, 4096)) == NULL) break; @@ -682,187 +1199,389 @@ return rc; } -static int check_consistency (struct md_dev *mddev) +static int check_consistency (mddev_t *mddev) { - int size = mddev->sb->size; - int row; + if (__check_consistency(mddev, 0)) +/* + * we do not do this currently, as it's perfectly possible to + * have an inconsistent array when it's freshly created. Only + * newly written data has to be consistent. + */ + return 0; - for (row = 0; row < size; row += size / 8) - if (__check_consistency(mddev, row)) - return 1; return 0; } -static int raid1_run (int minor, struct md_dev *mddev) +#define INVALID_LEVEL KERN_WARNING \ +"raid1: md%d: raid level not set to mirroring (%d)\n" + +#define NO_SB KERN_ERR \ +"raid1: disabled mirror %s (couldn't access raid superblock)\n" + +#define ERRORS KERN_ERR \ +"raid1: disabled mirror %s (errors detected)\n" + +#define NOT_IN_SYNC KERN_ERR \ +"raid1: disabled mirror %s (not in sync)\n" + +#define INCONSISTENT KERN_ERR \ +"raid1: disabled mirror %s (inconsistent descriptor)\n" + +#define ALREADY_RUNNING KERN_ERR \ +"raid1: disabled mirror %s (mirror %d already operational)\n" + +#define OPERATIONAL KERN_INFO \ +"raid1: device %s operational as mirror %d\n" + +#define MEM_ERROR KERN_ERR \ +"raid1: couldn't allocate memory for md%d\n" + +#define SPARE KERN_INFO \ +"raid1: spare disk %s\n" + +#define NONE_OPERATIONAL KERN_ERR \ +"raid1: no operational mirrors for md%d\n" + +#define RUNNING_CKRAID KERN_ERR \ +"raid1: detected mirror differences -- running resync\n" + +#define ARRAY_IS_ACTIVE KERN_INFO \ +"raid1: raid set md%d active with %d out of %d mirrors\n" + +#define THREAD_ERROR KERN_ERR \ +"raid1: couldn't allocate thread for md%d\n" + +#define START_RESYNC KERN_WARNING \ +"raid1: raid set md%d not clean; reconstructing mirrors\n" + +static int raid1_run (mddev_t *mddev) { - struct raid1_data *raid_conf; - int i, j, raid_disk; - md_superblock_t *sb = mddev->sb; - md_descriptor_t *descriptor; - struct real_dev *realdev; + raid1_conf_t *conf; + int i, j, disk_idx; + struct mirror_info *disk; + mdp_super_t *sb = mddev->sb; + mdp_disk_t *descriptor; + mdk_rdev_t *rdev; + struct md_list_head *tmp; + int start_recovery = 0; MOD_INC_USE_COUNT; if (sb->level != 1) { - printk("raid1: %s: raid level not set to mirroring (%d)\n", - kdevname(MKDEV(MD_MAJOR, minor)), sb->level); - MOD_DEC_USE_COUNT; - return -EIO; - } - /**** - * copy the now verified devices into our private RAID1 bookkeeping - * area. [whatever we allocate in raid1_run(), should be freed in - * raid1_stop()] + printk(INVALID_LEVEL, mdidx(mddev), sb->level); + goto out; + } + /* + * copy the already verified devices into our private RAID1 + * bookkeeping area. [whatever we allocate in raid1_run(), + * should be freed in raid1_stop()] */ - while (!( /* FIXME: now we are rather fault tolerant than nice */ - mddev->private = kmalloc (sizeof (struct raid1_data), GFP_KERNEL) - ) ) - { - printk ("raid1_run(): out of memory\n"); - current->policy |= SCHED_YIELD; - schedule(); - } - raid_conf = mddev->private; - memset(raid_conf, 0, sizeof(*raid_conf)); - - PRINTK(("raid1_run(%d) called.\n", minor)); - - for (i = 0; i < mddev->nb_dev; i++) { - realdev = &mddev->devices[i]; - if (!realdev->sb) { - printk(KERN_ERR "raid1: disabled mirror %s (couldn't access raid superblock)\n", kdevname(realdev->dev)); + conf = raid1_kmalloc(sizeof(raid1_conf_t)); + mddev->private = conf; + if (!conf) { + printk(MEM_ERROR, mdidx(mddev)); + goto out; + } + + ITERATE_RDEV(mddev,rdev,tmp) { + if (rdev->faulty) { + printk(ERRORS, partition_name(rdev->dev)); + } else { + if (!rdev->sb) { + MD_BUG(); + continue; + } + } + if (rdev->desc_nr == -1) { + MD_BUG(); continue; } - - /* - * This is important -- we are using the descriptor on - * the disk only to get a pointer to the descriptor on - * the main superblock, which might be more recent. - */ - descriptor = &sb->disks[realdev->sb->descriptor.number]; - if (descriptor->state & (1 << MD_FAULTY_DEVICE)) { - printk(KERN_ERR "raid1: disabled mirror %s (errors detected)\n", kdevname(realdev->dev)); + descriptor = &sb->disks[rdev->desc_nr]; + disk_idx = descriptor->raid_disk; + disk = conf->mirrors + disk_idx; + + if (disk_faulty(descriptor)) { + disk->number = descriptor->number; + disk->raid_disk = disk_idx; + disk->dev = rdev->dev; + disk->sect_limit = MAX_LINEAR_SECTORS; + disk->operational = 0; + disk->write_only = 0; + disk->spare = 0; + disk->used_slot = 1; continue; } - if (descriptor->state & (1 << MD_ACTIVE_DEVICE)) { - if (!(descriptor->state & (1 << MD_SYNC_DEVICE))) { - printk(KERN_ERR "raid1: disabled mirror %s (not in sync)\n", kdevname(realdev->dev)); + if (disk_active(descriptor)) { + if (!disk_sync(descriptor)) { + printk(NOT_IN_SYNC, + partition_name(rdev->dev)); continue; } - raid_disk = descriptor->raid_disk; - if (descriptor->number > sb->nr_disks || raid_disk > sb->raid_disks) { - printk(KERN_ERR "raid1: disabled mirror %s (inconsistent descriptor)\n", kdevname(realdev->dev)); + if ((descriptor->number > MD_SB_DISKS) || + (disk_idx > sb->raid_disks)) { + + printk(INCONSISTENT, + partition_name(rdev->dev)); continue; } - if (raid_conf->mirrors[raid_disk].operational) { - printk(KERN_ERR "raid1: disabled mirror %s (mirror %d already operational)\n", kdevname(realdev->dev), raid_disk); + if (disk->operational) { + printk(ALREADY_RUNNING, + partition_name(rdev->dev), + disk_idx); continue; } - printk(KERN_INFO "raid1: device %s operational as mirror %d\n", kdevname(realdev->dev), raid_disk); - raid_conf->mirrors[raid_disk].number = descriptor->number; - raid_conf->mirrors[raid_disk].raid_disk = raid_disk; - raid_conf->mirrors[raid_disk].dev = mddev->devices [i].dev; - raid_conf->mirrors[raid_disk].operational = 1; - raid_conf->mirrors[raid_disk].sect_limit = 128; - raid_conf->working_disks++; + printk(OPERATIONAL, partition_name(rdev->dev), + disk_idx); + disk->number = descriptor->number; + disk->raid_disk = disk_idx; + disk->dev = rdev->dev; + disk->sect_limit = MAX_LINEAR_SECTORS; + disk->operational = 1; + disk->write_only = 0; + disk->spare = 0; + disk->used_slot = 1; + conf->working_disks++; } else { /* * Must be a spare disk .. */ - printk(KERN_INFO "raid1: spare disk %s\n", kdevname(realdev->dev)); - raid_disk = descriptor->raid_disk; - raid_conf->mirrors[raid_disk].number = descriptor->number; - raid_conf->mirrors[raid_disk].raid_disk = raid_disk; - raid_conf->mirrors[raid_disk].dev = mddev->devices [i].dev; - raid_conf->mirrors[raid_disk].sect_limit = 128; - - raid_conf->mirrors[raid_disk].operational = 0; - raid_conf->mirrors[raid_disk].write_only = 0; - raid_conf->mirrors[raid_disk].spare = 1; - } - } - if (!raid_conf->working_disks) { - printk(KERN_ERR "raid1: no operational mirrors for %s\n", kdevname(MKDEV(MD_MAJOR, minor))); - kfree(raid_conf); - mddev->private = NULL; - MOD_DEC_USE_COUNT; - return -EIO; - } - - raid_conf->raid_disks = sb->raid_disks; - raid_conf->mddev = mddev; - - for (j = 0; !raid_conf->mirrors[j].operational; j++); - raid_conf->last_used = j; - for (i = raid_conf->raid_disks - 1; i >= 0; i--) { - if (raid_conf->mirrors[i].operational) { - PRINTK(("raid_conf->mirrors[%d].next == %d\n", i, j)); - raid_conf->mirrors[i].next = j; + printk(SPARE, partition_name(rdev->dev)); + disk->number = descriptor->number; + disk->raid_disk = disk_idx; + disk->dev = rdev->dev; + disk->sect_limit = MAX_LINEAR_SECTORS; + disk->operational = 0; + disk->write_only = 0; + disk->spare = 1; + disk->used_slot = 1; + } + } + if (!conf->working_disks) { + printk(NONE_OPERATIONAL, mdidx(mddev)); + goto out_free_conf; + } + + conf->raid_disks = sb->raid_disks; + conf->nr_disks = sb->nr_disks; + conf->mddev = mddev; + conf->device_lock = MD_SPIN_LOCK_UNLOCKED; + + conf->segment_lock = MD_SPIN_LOCK_UNLOCKED; + init_waitqueue_head(&conf->wait_done); + init_waitqueue_head(&conf->wait_ready); + + + for (i = 0; i < MD_SB_DISKS; i++) { + + descriptor = sb->disks+i; + disk_idx = descriptor->raid_disk; + disk = conf->mirrors + disk_idx; + + if (disk_faulty(descriptor) && (disk_idx < conf->raid_disks) && + !disk->used_slot) { + + disk->number = descriptor->number; + disk->raid_disk = disk_idx; + disk->dev = MKDEV(0,0); + + disk->operational = 0; + disk->write_only = 0; + disk->spare = 0; + disk->used_slot = 1; + } + } + + /* + * find the first working one and use it as a starting point + * to read balancing. + */ + for (j = 0; !conf->mirrors[j].operational; j++) + /* nothing */; + conf->last_used = j; + + /* + * initialize the 'working disks' list. + */ + for (i = conf->raid_disks - 1; i >= 0; i--) { + if (conf->mirrors[i].operational) { + conf->mirrors[i].next = j; j = i; } } - if (check_consistency(mddev)) { - printk(KERN_ERR "raid1: detected mirror differences -- run ckraid\n"); - sb->state |= 1 << MD_SB_ERRORS; - kfree(raid_conf); - mddev->private = NULL; - MOD_DEC_USE_COUNT; - return -EIO; + if (conf->working_disks != sb->raid_disks) { + printk(KERN_ALERT "raid1: md%d, not all disks are operational -- trying to recover array\n", mdidx(mddev)); + start_recovery = 1; + } + + if (!start_recovery && (sb->state & (1 << MD_SB_CLEAN))) { + /* + * we do sanity checks even if the device says + * it's clean ... + */ + if (check_consistency(mddev)) { + printk(RUNNING_CKRAID); + sb->state &= ~(1 << MD_SB_CLEAN); + } + } + + { + const char * name = "raid1d"; + + conf->thread = md_register_thread(raid1d, conf, name); + if (!conf->thread) { + printk(THREAD_ERROR, mdidx(mddev)); + goto out_free_conf; + } + } + + if (!start_recovery && !(sb->state & (1 << MD_SB_CLEAN))) { + const char * name = "raid1syncd"; + + conf->resync_thread = md_register_thread(raid1syncd, conf,name); + if (!conf->resync_thread) { + printk(THREAD_ERROR, mdidx(mddev)); + goto out_free_conf; + } + + printk(START_RESYNC, mdidx(mddev)); + conf->resync_mirrors = 1; + md_wakeup_thread(conf->resync_thread); } /* * Regenerate the "device is in sync with the raid set" bit for * each device. */ - for (i = 0; i < sb->nr_disks ; i++) { - sb->disks[i].state &= ~(1 << MD_SYNC_DEVICE); + for (i = 0; i < MD_SB_DISKS; i++) { + mark_disk_nonsync(sb->disks+i); for (j = 0; j < sb->raid_disks; j++) { - if (!raid_conf->mirrors[j].operational) + if (!conf->mirrors[j].operational) continue; - if (sb->disks[i].number == raid_conf->mirrors[j].number) - sb->disks[i].state |= 1 << MD_SYNC_DEVICE; + if (sb->disks[i].number == conf->mirrors[j].number) + mark_disk_sync(sb->disks+i); } } - sb->active_disks = raid_conf->working_disks; + sb->active_disks = conf->working_disks; - printk("raid1: raid set %s active with %d out of %d mirrors\n", kdevname(MKDEV(MD_MAJOR, minor)), sb->active_disks, sb->raid_disks); - /* Ok, everything is just fine now */ - return (0); + if (start_recovery) + md_recover_arrays(); + + + printk(ARRAY_IS_ACTIVE, mdidx(mddev), sb->active_disks, sb->raid_disks); + /* + * Ok, everything is just fine now + */ + return 0; + +out_free_conf: + kfree(conf); + mddev->private = NULL; +out: + MOD_DEC_USE_COUNT; + return -EIO; +} + +#undef INVALID_LEVEL +#undef NO_SB +#undef ERRORS +#undef NOT_IN_SYNC +#undef INCONSISTENT +#undef ALREADY_RUNNING +#undef OPERATIONAL +#undef SPARE +#undef NONE_OPERATIONAL +#undef RUNNING_CKRAID +#undef ARRAY_IS_ACTIVE + +static int raid1_stop_resync (mddev_t *mddev) +{ + raid1_conf_t *conf = mddev_to_conf(mddev); + + if (conf->resync_thread) { + if (conf->resync_mirrors) { + conf->resync_mirrors = 2; + md_interrupt_thread(conf->resync_thread); + + /* this is really needed when recovery stops too... */ + spin_lock_irq(&conf->segment_lock); + wait_event_lock_irq(conf->wait_done, !conf->cnt_active, conf->segment_lock); + conf->start_active = conf->start_ready; + conf->start_ready = conf->start_pending; + conf->cnt_active = conf->cnt_ready; + conf->cnt_ready = 0; + wait_event_lock_irq(conf->wait_done, !conf->cnt_active, conf->segment_lock); + conf->start_active = conf->start_ready; + conf->cnt_ready = 0; + wait_event_lock_irq(conf->wait_ready, !conf->cnt_pending, conf->segment_lock); + conf->start_active =conf->start_ready = conf->start_pending = conf->start_future; + conf->start_future = mddev->sb->size+1; + conf->cnt_pending = conf->cnt_future; + conf->cnt_future = 0; + conf->phase = conf->phase ^1; + wait_event_lock_irq(conf->wait_ready, !conf->cnt_pending, conf->segment_lock); + conf->start_active = conf->start_ready = conf->start_pending = conf->start_future = 0; + conf->phase = 0; + conf->cnt_done = conf->cnt_future; + conf->cnt_future = 0; + wake_up(&conf->wait_done); + + printk(KERN_INFO "raid1: mirror resync was not fully finished, restarting next time.\n"); + return 1; + } + return 0; + } + return 0; +} + +static int raid1_restart_resync (mddev_t *mddev) +{ + raid1_conf_t *conf = mddev_to_conf(mddev); + + if (conf->resync_mirrors) { + if (!conf->resync_thread) { + MD_BUG(); + return 0; + } + conf->resync_mirrors = 1; + md_wakeup_thread(conf->resync_thread); + return 1; + } + return 0; } -static int raid1_stop (int minor, struct md_dev *mddev) +static int raid1_stop (mddev_t *mddev) { - struct raid1_data *raid_conf = (struct raid1_data *) mddev->private; + raid1_conf_t *conf = mddev_to_conf(mddev); - kfree (raid_conf); + md_unregister_thread(conf->thread); + if (conf->resync_thread) + md_unregister_thread(conf->resync_thread); + kfree(conf); mddev->private = NULL; MOD_DEC_USE_COUNT; return 0; } -static struct md_personality raid1_personality= +static mdk_personality_t raid1_personality= { "raid1", - raid1_map, raid1_make_request, raid1_end_request, raid1_run, raid1_stop, raid1_status, - NULL, /* no ioctls */ 0, raid1_error, - raid1_hot_add_disk, - /* raid1_hot_remove_drive */ NULL, - raid1_mark_spare + raid1_diskop, + raid1_stop_resync, + raid1_restart_resync, + raid1_sync_request }; int raid1_init (void) { - if ((raid1_thread = md_register_thread(raid1d, NULL)) == NULL) - return -EBUSY; return register_md_personality (RAID1, &raid1_personality); } @@ -874,7 +1593,6 @@ void cleanup_module (void) { - md_unregister_thread (raid1_thread); unregister_md_personality (RAID1); } #endif diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/block/raid5.c linux/drivers/block/raid5.c --- v2.3.99-pre7/linux/drivers/block/raid5.c Tue Aug 31 17:29:13 1999 +++ linux/drivers/block/raid5.c Fri May 12 11:36:30 2000 @@ -1,6 +1,7 @@ -/***************************************************************************** +/* * raid5.c : Multiple Devices driver for Linux - * Copyright (C) 1996, 1997 Ingo Molnar, Miguel de Icaza, Gadi Oxman + * Copyright (C) 1996, 1997 Ingo Molnar, Miguel de Icaza, Gadi Oxman + * Copyright (C) 1999, 2000 Ingo Molnar * * RAID-5 management functions. * @@ -14,130 +15,108 @@ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include #include #include -#include -#include +#include #include #include -#include -static struct md_personality raid5_personality; +static mdk_personality_t raid5_personality; /* * Stripe cache */ + #define NR_STRIPES 128 #define HASH_PAGES 1 #define HASH_PAGES_ORDER 0 #define NR_HASH (HASH_PAGES * PAGE_SIZE / sizeof(struct stripe_head *)) #define HASH_MASK (NR_HASH - 1) -#define stripe_hash(raid_conf, sect, size) ((raid_conf)->stripe_hashtbl[((sect) / (size >> 9)) & HASH_MASK]) +#define stripe_hash(conf, sect, size) ((conf)->stripe_hashtbl[((sect) / (size >> 9)) & HASH_MASK]) /* * The following can be used to debug the driver */ #define RAID5_DEBUG 0 +#define RAID5_PARANOIA 1 +#define CHECK_DEVLOCK() if (!spin_is_locked(&conf->device_lock)) BUG() +#define CHECK_SHLOCK(sh) if (!stripe_locked(sh)) BUG() #if RAID5_DEBUG -#define PRINTK(x) do { printk x; } while (0); +#define PRINTK(x...) printk(x) +#define inline +#define __inline__ #else -#define PRINTK(x) do { ; } while (0) +#define inline +#define __inline__ +#define PRINTK(x...) do { } while (0) #endif +static void print_raid5_conf (raid5_conf_t *conf); + static inline int stripe_locked(struct stripe_head *sh) { return test_bit(STRIPE_LOCKED, &sh->state); } -static inline int stripe_error(struct stripe_head *sh) -{ - return test_bit(STRIPE_ERROR, &sh->state); -} - -/* - * Stripes are locked whenever new buffers can't be added to them. - */ -static inline void lock_stripe(struct stripe_head *sh) -{ - struct raid5_data *raid_conf = sh->raid_conf; - if (!test_and_set_bit(STRIPE_LOCKED, &sh->state)) { - PRINTK(("locking stripe %lu\n", sh->sector)); - raid_conf->nr_locked_stripes++; - } -} - -static inline void unlock_stripe(struct stripe_head *sh) +static void __unlock_stripe(struct stripe_head *sh) { - struct raid5_data *raid_conf = sh->raid_conf; - if (test_and_clear_bit(STRIPE_LOCKED, &sh->state)) { - PRINTK(("unlocking stripe %lu\n", sh->sector)); - raid_conf->nr_locked_stripes--; - wake_up(&sh->wait); - } + if (!md_test_and_clear_bit(STRIPE_LOCKED, &sh->state)) + BUG(); + PRINTK("unlocking stripe %lu\n", sh->sector); + wake_up(&sh->wait); } -static inline void finish_stripe(struct stripe_head *sh) +static void finish_unlock_stripe(struct stripe_head *sh) { - struct raid5_data *raid_conf = sh->raid_conf; - unlock_stripe(sh); + raid5_conf_t *conf = sh->raid_conf; sh->cmd = STRIPE_NONE; sh->phase = PHASE_COMPLETE; - raid_conf->nr_pending_stripes--; - raid_conf->nr_cached_stripes++; - wake_up(&raid_conf->wait_for_stripe); -} - -void __wait_on_stripe(struct stripe_head *sh) -{ - DECLARE_WAITQUEUE(wait, current); - - PRINTK(("wait_on_stripe %lu\n", sh->sector)); - sh->count++; - add_wait_queue(&sh->wait, &wait); -repeat: - set_current_state(TASK_UNINTERRUPTIBLE); - if (stripe_locked(sh)) { - schedule(); - goto repeat; - } - PRINTK(("wait_on_stripe %lu done\n", sh->sector)); - remove_wait_queue(&sh->wait, &wait); - sh->count--; - current->state = TASK_RUNNING; -} - -static inline void wait_on_stripe(struct stripe_head *sh) -{ - if (stripe_locked(sh)) - __wait_on_stripe(sh); + atomic_dec(&conf->nr_pending_stripes); + atomic_inc(&conf->nr_cached_stripes); + __unlock_stripe(sh); + atomic_dec(&sh->count); + wake_up(&conf->wait_for_stripe); } -static inline void remove_hash(struct raid5_data *raid_conf, struct stripe_head *sh) +static void remove_hash(raid5_conf_t *conf, struct stripe_head *sh) { - PRINTK(("remove_hash(), stripe %lu\n", sh->sector)); + PRINTK("remove_hash(), stripe %lu\n", sh->sector); + CHECK_DEVLOCK(); + CHECK_SHLOCK(sh); if (sh->hash_pprev) { if (sh->hash_next) sh->hash_next->hash_pprev = sh->hash_pprev; *sh->hash_pprev = sh->hash_next; sh->hash_pprev = NULL; - raid_conf->nr_hashed_stripes--; + atomic_dec(&conf->nr_hashed_stripes); } } -static inline void insert_hash(struct raid5_data *raid_conf, struct stripe_head *sh) +static void lock_get_bh (struct buffer_head *bh) +{ + while (md_test_and_set_bit(BH_Lock, &bh->b_state)) + __wait_on_buffer(bh); + atomic_inc(&bh->b_count); +} + +static __inline__ void insert_hash(raid5_conf_t *conf, struct stripe_head *sh) { - struct stripe_head **shp = &stripe_hash(raid_conf, sh->sector, sh->size); + struct stripe_head **shp = &stripe_hash(conf, sh->sector, sh->size); - PRINTK(("insert_hash(), stripe %lu, nr_hashed_stripes %d\n", sh->sector, raid_conf->nr_hashed_stripes)); + PRINTK("insert_hash(), stripe %lu, nr_hashed_stripes %d\n", + sh->sector, atomic_read(&conf->nr_hashed_stripes)); + CHECK_DEVLOCK(); + CHECK_SHLOCK(sh); if ((sh->hash_next = *shp) != NULL) (*shp)->hash_pprev = &sh->hash_next; *shp = sh; sh->hash_pprev = shp; - raid_conf->nr_hashed_stripes++; + atomic_inc(&conf->nr_hashed_stripes); } static struct buffer_head *get_free_buffer(struct stripe_head *sh, int b_size) @@ -145,13 +124,18 @@ struct buffer_head *bh; unsigned long flags; - save_flags(flags); - cli(); - if ((bh = sh->buffer_pool) == NULL) - return NULL; + CHECK_SHLOCK(sh); + md_spin_lock_irqsave(&sh->stripe_lock, flags); + bh = sh->buffer_pool; + if (!bh) + goto out_unlock; sh->buffer_pool = bh->b_next; bh->b_size = b_size; - restore_flags(flags); + if (atomic_read(&bh->b_count)) + BUG(); +out_unlock: + md_spin_unlock_irqrestore(&sh->stripe_lock, flags); + return bh; } @@ -160,12 +144,17 @@ struct buffer_head *bh; unsigned long flags; - save_flags(flags); - cli(); - if ((bh = sh->bh_pool) == NULL) - return NULL; + CHECK_SHLOCK(sh); + md_spin_lock_irqsave(&sh->stripe_lock, flags); + bh = sh->bh_pool; + if (!bh) + goto out_unlock; sh->bh_pool = bh->b_next; - restore_flags(flags); + if (atomic_read(&bh->b_count)) + BUG(); +out_unlock: + md_spin_unlock_irqrestore(&sh->stripe_lock, flags); + return bh; } @@ -173,55 +162,58 @@ { unsigned long flags; - save_flags(flags); - cli(); + if (atomic_read(&bh->b_count)) + BUG(); + CHECK_SHLOCK(sh); + md_spin_lock_irqsave(&sh->stripe_lock, flags); bh->b_next = sh->buffer_pool; sh->buffer_pool = bh; - restore_flags(flags); + md_spin_unlock_irqrestore(&sh->stripe_lock, flags); } static void put_free_bh(struct stripe_head *sh, struct buffer_head *bh) { unsigned long flags; - save_flags(flags); - cli(); + if (atomic_read(&bh->b_count)) + BUG(); + CHECK_SHLOCK(sh); + md_spin_lock_irqsave(&sh->stripe_lock, flags); bh->b_next = sh->bh_pool; sh->bh_pool = bh; - restore_flags(flags); + md_spin_unlock_irqrestore(&sh->stripe_lock, flags); } -static struct stripe_head *get_free_stripe(struct raid5_data *raid_conf) +static struct stripe_head *get_free_stripe(raid5_conf_t *conf) { struct stripe_head *sh; - unsigned long flags; - save_flags(flags); - cli(); - if ((sh = raid_conf->free_sh_list) == NULL) { - restore_flags(flags); - return NULL; - } - raid_conf->free_sh_list = sh->free_next; - raid_conf->nr_free_sh--; - if (!raid_conf->nr_free_sh && raid_conf->free_sh_list) - printk ("raid5: bug: free_sh_list != NULL, nr_free_sh == 0\n"); - restore_flags(flags); - if (sh->hash_pprev || sh->nr_pending || sh->count) - printk("get_free_stripe(): bug\n"); + md_spin_lock_irq(&conf->device_lock); + sh = conf->free_sh_list; + if (!sh) + goto out; + conf->free_sh_list = sh->free_next; + atomic_dec(&conf->nr_free_sh); + if (!atomic_read(&conf->nr_free_sh) && conf->free_sh_list) + BUG(); + if (sh->hash_pprev || md_atomic_read(&sh->nr_pending) || + atomic_read(&sh->count)) + BUG(); +out: + md_spin_unlock_irq(&conf->device_lock); return sh; } -static void put_free_stripe(struct raid5_data *raid_conf, struct stripe_head *sh) +static void __put_free_stripe (raid5_conf_t *conf, struct stripe_head *sh) { - unsigned long flags; - - save_flags(flags); - cli(); - sh->free_next = raid_conf->free_sh_list; - raid_conf->free_sh_list = sh; - raid_conf->nr_free_sh++; - restore_flags(flags); + if (atomic_read(&sh->count) != 0) + BUG(); + CHECK_DEVLOCK(); + CHECK_SHLOCK(sh); + clear_bit(STRIPE_LOCKED, &sh->state); + sh->free_next = conf->free_sh_list; + conf->free_sh_list = sh; + atomic_inc(&conf->nr_free_sh); } static void shrink_buffers(struct stripe_head *sh, int num) @@ -229,7 +221,8 @@ struct buffer_head *bh; while (num--) { - if ((bh = get_free_buffer(sh, -1)) == NULL) + bh = get_free_buffer(sh, -1); + if (!bh) return; free_page((unsigned long) bh->b_data); kfree(bh); @@ -241,26 +234,33 @@ struct buffer_head *bh; while (num--) { - if ((bh = get_free_bh(sh)) == NULL) + bh = get_free_bh(sh); + if (!bh) return; kfree(bh); } } -static int grow_buffers(struct stripe_head *sh, int num, int b_size, int priority) +static int grow_raid5_buffers(struct stripe_head *sh, int num, int b_size, int priority) { struct buffer_head *bh; while (num--) { - if ((bh = kmalloc(sizeof(struct buffer_head), priority)) == NULL) + struct page *page; + bh = kmalloc(sizeof(struct buffer_head), priority); + if (!bh) return 1; memset(bh, 0, sizeof (struct buffer_head)); - bh->b_data = (char *) __get_free_page(priority); + init_waitqueue_head(&bh->b_wait); + page = alloc_page(priority); + bh->b_data = (char *) page_address(page); if (!bh->b_data) { kfree(bh); return 1; } bh->b_size = b_size; + atomic_set(&bh->b_count, 0); + set_bh_page(bh, page, 0); put_free_buffer(sh, bh); } return 0; @@ -271,259 +271,314 @@ struct buffer_head *bh; while (num--) { - if ((bh = kmalloc(sizeof(struct buffer_head), priority)) == NULL) + bh = kmalloc(sizeof(struct buffer_head), priority); + if (!bh) return 1; memset(bh, 0, sizeof (struct buffer_head)); + init_waitqueue_head(&bh->b_wait); put_free_bh(sh, bh); } return 0; } -static void raid5_kfree_buffer(struct stripe_head *sh, struct buffer_head *bh) +static void raid5_free_buffer(struct stripe_head *sh, struct buffer_head *bh) { - unsigned long flags; - - save_flags(flags); - cli(); put_free_buffer(sh, bh); - restore_flags(flags); } -static void raid5_kfree_bh(struct stripe_head *sh, struct buffer_head *bh) +static void raid5_free_bh(struct stripe_head *sh, struct buffer_head *bh) { - unsigned long flags; - - save_flags(flags); - cli(); put_free_bh(sh, bh); - restore_flags(flags); } -static void raid5_kfree_old_bh(struct stripe_head *sh, int i) +static void raid5_free_old_bh(struct stripe_head *sh, int i) { - if (!sh->bh_old[i]) { - printk("raid5_kfree_old_bh: bug: sector %lu, index %d not present\n", sh->sector, i); - return; - } - raid5_kfree_buffer(sh, sh->bh_old[i]); + CHECK_SHLOCK(sh); + if (!sh->bh_old[i]) + BUG(); + raid5_free_buffer(sh, sh->bh_old[i]); sh->bh_old[i] = NULL; } static void raid5_update_old_bh(struct stripe_head *sh, int i) { - PRINTK(("stripe %lu, idx %d, updating cache copy\n", sh->sector, i)); - if (!sh->bh_copy[i]) { - printk("raid5_update_old_bh: bug: sector %lu, index %d not present\n", sh->sector, i); - return; - } + CHECK_SHLOCK(sh); + PRINTK("stripe %lu, idx %d, updating cache copy\n", sh->sector, i); + if (!sh->bh_copy[i]) + BUG(); if (sh->bh_old[i]) - raid5_kfree_old_bh(sh, i); + raid5_free_old_bh(sh, i); sh->bh_old[i] = sh->bh_copy[i]; sh->bh_copy[i] = NULL; } -static void kfree_stripe(struct stripe_head *sh) +static void free_stripe(struct stripe_head *sh) { - struct raid5_data *raid_conf = sh->raid_conf; - int disks = raid_conf->raid_disks, j; + raid5_conf_t *conf = sh->raid_conf; + int disks = conf->raid_disks, j; - PRINTK(("kfree_stripe called, stripe %lu\n", sh->sector)); - if (sh->phase != PHASE_COMPLETE || stripe_locked(sh) || sh->count) { - printk("raid5: kfree_stripe(), sector %lu, phase %d, locked %d, count %d\n", sh->sector, sh->phase, stripe_locked(sh), sh->count); + if (atomic_read(&sh->count) != 0) + BUG(); + CHECK_DEVLOCK(); + CHECK_SHLOCK(sh); + PRINTK("free_stripe called, stripe %lu\n", sh->sector); + if (sh->phase != PHASE_COMPLETE || atomic_read(&sh->count)) { + PRINTK("raid5: free_stripe(), sector %lu, phase %d, count %d\n", sh->sector, sh->phase, atomic_read(&sh->count)); return; } for (j = 0; j < disks; j++) { if (sh->bh_old[j]) - raid5_kfree_old_bh(sh, j); + raid5_free_old_bh(sh, j); if (sh->bh_new[j] || sh->bh_copy[j]) - printk("raid5: bug: sector %lu, new %p, copy %p\n", sh->sector, sh->bh_new[j], sh->bh_copy[j]); + BUG(); } - remove_hash(raid_conf, sh); - put_free_stripe(raid_conf, sh); + remove_hash(conf, sh); + __put_free_stripe(conf, sh); } -static int shrink_stripe_cache(struct raid5_data *raid_conf, int nr) +static int shrink_stripe_cache(raid5_conf_t *conf, int nr) { struct stripe_head *sh; int i, count = 0; - PRINTK(("shrink_stripe_cache called, %d/%d, clock %d\n", nr, raid_conf->nr_hashed_stripes, raid_conf->clock)); + PRINTK("shrink_stripe_cache called, %d/%d, clock %d\n", nr, atomic_read(&conf->nr_hashed_stripes), conf->clock); + md_spin_lock_irq(&conf->device_lock); for (i = 0; i < NR_HASH; i++) { -repeat: - sh = raid_conf->stripe_hashtbl[(i + raid_conf->clock) & HASH_MASK]; + sh = conf->stripe_hashtbl[(i + conf->clock) & HASH_MASK]; for (; sh; sh = sh->hash_next) { if (sh->phase != PHASE_COMPLETE) continue; - if (stripe_locked(sh)) + if (atomic_read(&sh->count)) continue; - if (sh->count) + /* + * Try to lock this stripe: + */ + if (md_test_and_set_bit(STRIPE_LOCKED, &sh->state)) continue; - kfree_stripe(sh); + free_stripe(sh); if (++count == nr) { - PRINTK(("shrink completed, nr_hashed_stripes %d\n", raid_conf->nr_hashed_stripes)); - raid_conf->clock = (i + raid_conf->clock) & HASH_MASK; - return nr; + conf->clock = (i + conf->clock) & HASH_MASK; + goto out; } - goto repeat; } } - PRINTK(("shrink completed, nr_hashed_stripes %d\n", raid_conf->nr_hashed_stripes)); +out: + md_spin_unlock_irq(&conf->device_lock); + PRINTK("shrink completed, nr_hashed_stripes %d, nr_pending_strips %d\n", + atomic_read(&conf->nr_hashed_stripes), + atomic_read(&conf->nr_pending_stripes)); return count; } -static struct stripe_head *find_stripe(struct raid5_data *raid_conf, unsigned long sector, int size) +void __wait_lock_stripe(struct stripe_head *sh) { - struct stripe_head *sh; + MD_DECLARE_WAITQUEUE(wait, current); - if (raid_conf->buffer_size != size) { - PRINTK(("switching size, %d --> %d\n", raid_conf->buffer_size, size)); - shrink_stripe_cache(raid_conf, raid_conf->max_nr_stripes); - raid_conf->buffer_size = size; + PRINTK("wait_lock_stripe %lu\n", sh->sector); + if (!atomic_read(&sh->count)) + BUG(); + add_wait_queue(&sh->wait, &wait); +repeat: + set_current_state(TASK_UNINTERRUPTIBLE); + if (md_test_and_set_bit(STRIPE_LOCKED, &sh->state)) { + schedule(); + goto repeat; } + PRINTK("wait_lock_stripe %lu done\n", sh->sector); + remove_wait_queue(&sh->wait, &wait); + current->state = TASK_RUNNING; +} - PRINTK(("find_stripe, sector %lu\n", sector)); - for (sh = stripe_hash(raid_conf, sector, size); sh; sh = sh->hash_next) - if (sh->sector == sector && sh->raid_conf == raid_conf) { - if (sh->size == size) { - PRINTK(("found stripe %lu\n", sector)); - return sh; - } else { - PRINTK(("switching size for %lu, %d --> %d\n", sector, sh->size, size)); - kfree_stripe(sh); - break; - } +static struct stripe_head *__find_stripe(raid5_conf_t *conf, unsigned long sector, int size) +{ + struct stripe_head *sh; + + PRINTK("__find_stripe, sector %lu\n", sector); + for (sh = stripe_hash(conf, sector, size); sh; sh = sh->hash_next) { + if (sh->sector == sector && sh->raid_conf == conf) { + if (sh->size != size) + BUG(); + return sh; } - PRINTK(("stripe %lu not in cache\n", sector)); + } + PRINTK("__stripe %lu not in cache\n", sector); return NULL; } -static int grow_stripes(struct raid5_data *raid_conf, int num, int priority) +static inline struct stripe_head *alloc_stripe(raid5_conf_t *conf, unsigned long sector, int size) +{ + struct stripe_head *sh; + struct buffer_head *buffer_pool, *bh_pool; + MD_DECLARE_WAITQUEUE(wait, current); + + PRINTK("alloc_stripe called\n"); + + + while ((sh = get_free_stripe(conf)) == NULL) { + int cnt; + add_wait_queue(&conf->wait_for_stripe, &wait); + set_current_state(TASK_UNINTERRUPTIBLE); + cnt = shrink_stripe_cache(conf, conf->max_nr_stripes / 8); + sh = get_free_stripe(conf); + if (!sh && cnt < (conf->max_nr_stripes/8)) { + md_wakeup_thread(conf->thread); + PRINTK("waiting for some stripes to complete - %d %d\n", cnt, conf->max_nr_stripes/8); + schedule(); + } + remove_wait_queue(&conf->wait_for_stripe, &wait); + current->state = TASK_RUNNING; + if (sh) + break; + } + + buffer_pool = sh->buffer_pool; + bh_pool = sh->bh_pool; + memset(sh, 0, sizeof(*sh)); + sh->stripe_lock = MD_SPIN_LOCK_UNLOCKED; + md_init_waitqueue_head(&sh->wait); + sh->buffer_pool = buffer_pool; + sh->bh_pool = bh_pool; + sh->phase = PHASE_COMPLETE; + sh->cmd = STRIPE_NONE; + sh->raid_conf = conf; + sh->sector = sector; + sh->size = size; + atomic_inc(&conf->nr_cached_stripes); + + return sh; +} + +static struct stripe_head *get_lock_stripe(raid5_conf_t *conf, unsigned long sector, int size) +{ + struct stripe_head *sh, *new = NULL; + + PRINTK("get_stripe, sector %lu\n", sector); + + /* + * Do this in set_blocksize()! + */ + if (conf->buffer_size != size) { + PRINTK("switching size, %d --> %d\n", conf->buffer_size, size); + shrink_stripe_cache(conf, conf->max_nr_stripes); + conf->buffer_size = size; + } + +repeat: + md_spin_lock_irq(&conf->device_lock); + sh = __find_stripe(conf, sector, size); + if (!sh) { + if (!new) { + md_spin_unlock_irq(&conf->device_lock); + new = alloc_stripe(conf, sector, size); + goto repeat; + } + sh = new; + new = NULL; + if (md_test_and_set_bit(STRIPE_LOCKED, &sh->state)) + BUG(); + insert_hash(conf, sh); + atomic_inc(&sh->count); + md_spin_unlock_irq(&conf->device_lock); + } else { + atomic_inc(&sh->count); + if (new) { + if (md_test_and_set_bit(STRIPE_LOCKED, &new->state)) + BUG(); + __put_free_stripe(conf, new); + } + md_spin_unlock_irq(&conf->device_lock); + PRINTK("get_stripe, waiting, sector %lu\n", sector); + if (md_test_and_set_bit(STRIPE_LOCKED, &sh->state)) + __wait_lock_stripe(sh); + } + return sh; +} + +static int grow_stripes(raid5_conf_t *conf, int num, int priority) { struct stripe_head *sh; while (num--) { - if ((sh = kmalloc(sizeof(struct stripe_head), priority)) == NULL) + sh = kmalloc(sizeof(struct stripe_head), priority); + if (!sh) return 1; memset(sh, 0, sizeof(*sh)); - if (grow_buffers(sh, 2 * raid_conf->raid_disks, PAGE_SIZE, priority)) { - shrink_buffers(sh, 2 * raid_conf->raid_disks); + sh->raid_conf = conf; + sh->stripe_lock = MD_SPIN_LOCK_UNLOCKED; + md_init_waitqueue_head(&sh->wait); + + if (md_test_and_set_bit(STRIPE_LOCKED, &sh->state)) + BUG(); + if (grow_raid5_buffers(sh, 2 * conf->raid_disks, PAGE_SIZE, priority)) { + shrink_buffers(sh, 2 * conf->raid_disks); kfree(sh); return 1; } - if (grow_bh(sh, raid_conf->raid_disks, priority)) { - shrink_buffers(sh, 2 * raid_conf->raid_disks); - shrink_bh(sh, raid_conf->raid_disks); + if (grow_bh(sh, conf->raid_disks, priority)) { + shrink_buffers(sh, 2 * conf->raid_disks); + shrink_bh(sh, conf->raid_disks); kfree(sh); return 1; } - put_free_stripe(raid_conf, sh); - raid_conf->nr_stripes++; + md_spin_lock_irq(&conf->device_lock); + __put_free_stripe(conf, sh); + atomic_inc(&conf->nr_stripes); + md_spin_unlock_irq(&conf->device_lock); } return 0; } -static void shrink_stripes(struct raid5_data *raid_conf, int num) +static void shrink_stripes(raid5_conf_t *conf, int num) { struct stripe_head *sh; while (num--) { - sh = get_free_stripe(raid_conf); + sh = get_free_stripe(conf); if (!sh) break; - shrink_buffers(sh, raid_conf->raid_disks * 2); - shrink_bh(sh, raid_conf->raid_disks); + if (md_test_and_set_bit(STRIPE_LOCKED, &sh->state)) + BUG(); + shrink_buffers(sh, conf->raid_disks * 2); + shrink_bh(sh, conf->raid_disks); kfree(sh); - raid_conf->nr_stripes--; + atomic_dec(&conf->nr_stripes); } } -static struct stripe_head *kmalloc_stripe(struct raid5_data *raid_conf, unsigned long sector, int size) -{ - struct stripe_head *sh = NULL, *tmp; - struct buffer_head *buffer_pool, *bh_pool; - - PRINTK(("kmalloc_stripe called\n")); - - while ((sh = get_free_stripe(raid_conf)) == NULL) { - shrink_stripe_cache(raid_conf, raid_conf->max_nr_stripes / 8); - if ((sh = get_free_stripe(raid_conf)) != NULL) - break; - if (!raid_conf->nr_pending_stripes) - printk("raid5: bug: nr_free_sh == 0, nr_pending_stripes == 0\n"); - md_wakeup_thread(raid_conf->thread); - PRINTK(("waiting for some stripes to complete\n")); - sleep_on(&raid_conf->wait_for_stripe); - } - - /* - * The above might have slept, so perhaps another process - * already created the stripe for us.. - */ - if ((tmp = find_stripe(raid_conf, sector, size)) != NULL) { - put_free_stripe(raid_conf, sh); - wait_on_stripe(tmp); - return tmp; - } - if (sh) { - buffer_pool = sh->buffer_pool; - bh_pool = sh->bh_pool; - memset(sh, 0, sizeof(*sh)); - sh->buffer_pool = buffer_pool; - sh->bh_pool = bh_pool; - sh->phase = PHASE_COMPLETE; - sh->cmd = STRIPE_NONE; - sh->raid_conf = raid_conf; - sh->sector = sector; - sh->size = size; - raid_conf->nr_cached_stripes++; - insert_hash(raid_conf, sh); - } else printk("raid5: bug: kmalloc_stripe() == NULL\n"); - return sh; -} - -static struct stripe_head *get_stripe(struct raid5_data *raid_conf, unsigned long sector, int size) -{ - struct stripe_head *sh; - - PRINTK(("get_stripe, sector %lu\n", sector)); - sh = find_stripe(raid_conf, sector, size); - if (sh) - wait_on_stripe(sh); - else - sh = kmalloc_stripe(raid_conf, sector, size); - return sh; -} - -static struct buffer_head *raid5_kmalloc_buffer(struct stripe_head *sh, int b_size) +static struct buffer_head *raid5_alloc_buffer(struct stripe_head *sh, int b_size) { struct buffer_head *bh; - if ((bh = get_free_buffer(sh, b_size)) == NULL) - printk("raid5: bug: raid5_kmalloc_buffer() == NULL\n"); + bh = get_free_buffer(sh, b_size); + if (!bh) + BUG(); return bh; } -static struct buffer_head *raid5_kmalloc_bh(struct stripe_head *sh) +static struct buffer_head *raid5_alloc_bh(struct stripe_head *sh) { struct buffer_head *bh; - if ((bh = get_free_bh(sh)) == NULL) - printk("raid5: bug: raid5_kmalloc_bh() == NULL\n"); + bh = get_free_bh(sh); + if (!bh) + BUG(); return bh; } -static inline void raid5_end_buffer_io (struct stripe_head *sh, int i, int uptodate) +static void raid5_end_buffer_io (struct stripe_head *sh, int i, int uptodate) { struct buffer_head *bh = sh->bh_new[i]; + PRINTK("raid5_end_buffer_io %lu, uptodate: %d.\n", bh->b_rsector, uptodate); sh->bh_new[i] = NULL; - raid5_kfree_bh(sh, sh->bh_req[i]); + raid5_free_bh(sh, sh->bh_req[i]); sh->bh_req[i] = NULL; + PRINTK("calling %p->end_io: %p.\n", bh, bh->b_end_io); bh->b_end_io(bh, uptodate); if (!uptodate) printk(KERN_ALERT "raid5: %s: unrecoverable I/O error for " - "block %lu\n", kdevname(bh->b_dev), bh->b_blocknr); + "block %lu\n", partition_name(bh->b_dev), bh->b_blocknr); } static inline void raid5_mark_buffer_uptodate (struct buffer_head *bh, int uptodate) @@ -537,61 +592,55 @@ static void raid5_end_request (struct buffer_head * bh, int uptodate) { struct stripe_head *sh = bh->b_dev_id; - struct raid5_data *raid_conf = sh->raid_conf; - int disks = raid_conf->raid_disks, i; + raid5_conf_t *conf = sh->raid_conf; + int disks = conf->raid_disks, i; unsigned long flags; - PRINTK(("end_request %lu, nr_pending %d\n", sh->sector, sh->nr_pending)); - save_flags(flags); - cli(); + PRINTK("end_request %lu, nr_pending %d, uptodate: %d, (caller: %p,%p,%p,%p).\n", sh->sector, atomic_read(&sh->nr_pending), uptodate, __builtin_return_address(0),__builtin_return_address(1),__builtin_return_address(2), __builtin_return_address(3)); + md_spin_lock_irqsave(&sh->stripe_lock, flags); raid5_mark_buffer_uptodate(bh, uptodate); - --sh->nr_pending; - if (!sh->nr_pending) { - md_wakeup_thread(raid_conf->thread); - atomic_inc(&raid_conf->nr_handle); - } if (!uptodate) md_error(bh->b_dev, bh->b_rdev); - if (raid_conf->failed_disks) { + if (conf->failed_disks) { for (i = 0; i < disks; i++) { - if (raid_conf->disks[i].operational) + if (conf->disks[i].operational) continue; if (bh != sh->bh_old[i] && bh != sh->bh_req[i] && bh != sh->bh_copy[i]) continue; - if (bh->b_rdev != raid_conf->disks[i].dev) + if (bh->b_rdev != conf->disks[i].dev) continue; set_bit(STRIPE_ERROR, &sh->state); } } - restore_flags(flags); -} + md_spin_unlock_irqrestore(&sh->stripe_lock, flags); -static int raid5_map (struct md_dev *mddev, kdev_t *rdev, - unsigned long *rsector, unsigned long size) -{ - /* No complex mapping used: the core of the work is done in the - * request routine - */ - return 0; + if (atomic_dec_and_test(&sh->nr_pending)) { + atomic_inc(&conf->nr_handle); + md_wakeup_thread(conf->thread); + } } static void raid5_build_block (struct stripe_head *sh, struct buffer_head *bh, int i) { - struct raid5_data *raid_conf = sh->raid_conf; - struct md_dev *mddev = raid_conf->mddev; - int minor = (int) (mddev - md_dev); + raid5_conf_t *conf = sh->raid_conf; + mddev_t *mddev = conf->mddev; char *b_data; - kdev_t dev = MKDEV(MD_MAJOR, minor); + struct page *b_page; + kdev_t dev = mddev_to_kdev(mddev); int block = sh->sector / (sh->size >> 9); - b_data = ((volatile struct buffer_head *) bh)->b_data; + b_data = bh->b_data; + b_page = bh->b_page; memset (bh, 0, sizeof (struct buffer_head)); + init_waitqueue_head(&bh->b_wait); init_buffer(bh, raid5_end_request, sh); bh->b_dev = dev; bh->b_blocknr = block; - ((volatile struct buffer_head *) bh)->b_data = b_data; - bh->b_rdev = raid_conf->disks[i].dev; + bh->b_data = b_data; + bh->b_page = b_page; + + bh->b_rdev = conf->disks[i].dev; bh->b_rsector = sh->sector; bh->b_state = (1 << BH_Req) | (1 << BH_Mapped); @@ -599,49 +648,77 @@ bh->b_list = BUF_LOCKED; } -static int raid5_error (struct md_dev *mddev, kdev_t dev) +static int raid5_error (mddev_t *mddev, kdev_t dev) { - struct raid5_data *raid_conf = (struct raid5_data *) mddev->private; - md_superblock_t *sb = mddev->sb; + raid5_conf_t *conf = (raid5_conf_t *) mddev->private; + mdp_super_t *sb = mddev->sb; struct disk_info *disk; int i; - PRINTK(("raid5_error called\n")); - raid_conf->resync_parity = 0; - for (i = 0, disk = raid_conf->disks; i < raid_conf->raid_disks; i++, disk++) + PRINTK("raid5_error called\n"); + conf->resync_parity = 0; + for (i = 0, disk = conf->disks; i < conf->raid_disks; i++, disk++) { if (disk->dev == dev && disk->operational) { disk->operational = 0; - sb->disks[disk->number].state |= (1 << MD_FAULTY_DEVICE); - sb->disks[disk->number].state &= ~(1 << MD_SYNC_DEVICE); - sb->disks[disk->number].state &= ~(1 << MD_ACTIVE_DEVICE); + mark_disk_faulty(sb->disks+disk->number); + mark_disk_nonsync(sb->disks+disk->number); + mark_disk_inactive(sb->disks+disk->number); sb->active_disks--; sb->working_disks--; sb->failed_disks++; mddev->sb_dirty = 1; - raid_conf->working_disks--; - raid_conf->failed_disks++; - md_wakeup_thread(raid_conf->thread); + conf->working_disks--; + conf->failed_disks++; + md_wakeup_thread(conf->thread); printk (KERN_ALERT - "RAID5: Disk failure on %s, disabling device." - "Operation continuing on %d devices\n", - kdevname (dev), raid_conf->working_disks); + "raid5: Disk failure on %s, disabling device." + " Operation continuing on %d devices\n", + partition_name (dev), conf->working_disks); + return 0; } - return 0; + } + /* + * handle errors in spares (during reconstruction) + */ + if (conf->spare) { + disk = conf->spare; + if (disk->dev == dev) { + printk (KERN_ALERT + "raid5: Disk failure on spare %s\n", + partition_name (dev)); + if (!conf->spare->operational) { + MD_BUG(); + return -EIO; + } + disk->operational = 0; + disk->write_only = 0; + conf->spare = NULL; + mark_disk_faulty(sb->disks+disk->number); + mark_disk_nonsync(sb->disks+disk->number); + mark_disk_inactive(sb->disks+disk->number); + sb->spare_disks--; + sb->working_disks--; + sb->failed_disks++; + + return 0; + } + } + MD_BUG(); + return -EIO; } /* * Input: a 'big' sector number, * Output: index of the data and parity disk, and the sector # in them. */ -static inline unsigned long -raid5_compute_sector (int r_sector, unsigned int raid_disks, unsigned int data_disks, - unsigned int * dd_idx, unsigned int * pd_idx, - struct raid5_data *raid_conf) +static unsigned long raid5_compute_sector(int r_sector, unsigned int raid_disks, + unsigned int data_disks, unsigned int * dd_idx, + unsigned int * pd_idx, raid5_conf_t *conf) { unsigned int stripe; int chunk_number, chunk_offset; unsigned long new_sector; - int sectors_per_chunk = raid_conf->chunk_size >> 9; + int sectors_per_chunk = conf->chunk_size >> 9; /* First compute the information on this sector */ @@ -664,9 +741,9 @@ /* * Select the parity disk based on the user selected algorithm. */ - if (raid_conf->level == 4) + if (conf->level == 4) *pd_idx = data_disks; - else switch (raid_conf->algorithm) { + else switch (conf->algorithm) { case ALGORITHM_LEFT_ASYMMETRIC: *pd_idx = data_disks - stripe % raid_disks; if (*dd_idx >= *pd_idx) @@ -686,7 +763,7 @@ *dd_idx = (*pd_idx + 1 + *dd_idx) % raid_disks; break; default: - printk ("raid5: unsupported algorithm %d\n", raid_conf->algorithm); + printk ("raid5: unsupported algorithm %d\n", conf->algorithm); } /* @@ -707,16 +784,16 @@ static unsigned long compute_blocknr(struct stripe_head *sh, int i) { - struct raid5_data *raid_conf = sh->raid_conf; - int raid_disks = raid_conf->raid_disks, data_disks = raid_disks - 1; + raid5_conf_t *conf = sh->raid_conf; + int raid_disks = conf->raid_disks, data_disks = raid_disks - 1; unsigned long new_sector = sh->sector, check; - int sectors_per_chunk = raid_conf->chunk_size >> 9; + int sectors_per_chunk = conf->chunk_size >> 9; unsigned long stripe = new_sector / sectors_per_chunk; int chunk_offset = new_sector % sectors_per_chunk; int chunk_number, dummy1, dummy2, dd_idx = i; unsigned long r_sector, blocknr; - switch (raid_conf->algorithm) { + switch (conf->algorithm) { case ALGORITHM_LEFT_ASYMMETRIC: case ALGORITHM_RIGHT_ASYMMETRIC: if (i > sh->pd_idx) @@ -729,14 +806,14 @@ i -= (sh->pd_idx + 1); break; default: - printk ("raid5: unsupported algorithm %d\n", raid_conf->algorithm); + printk ("raid5: unsupported algorithm %d\n", conf->algorithm); } chunk_number = stripe * data_disks + i; r_sector = chunk_number * sectors_per_chunk + chunk_offset; blocknr = r_sector / (sh->size >> 9); - check = raid5_compute_sector (r_sector, raid_disks, data_disks, &dummy1, &dummy2, raid_conf); + check = raid5_compute_sector (r_sector, raid_disks, data_disks, &dummy1, &dummy2, conf); if (check != sh->sector || dummy1 != dd_idx || dummy2 != sh->pd_idx) { printk("compute_blocknr: map not correct\n"); return 0; @@ -744,144 +821,153 @@ return blocknr; } -#ifdef HAVE_ARCH_XORBLOCK -static void xor_block(struct buffer_head *dest, struct buffer_head *source) -{ - __xor_block((char *) dest->b_data, (char *) source->b_data, dest->b_size); -} -#else -static void xor_block(struct buffer_head *dest, struct buffer_head *source) -{ - long lines = dest->b_size / (sizeof (long)) / 8, i; - long *destp = (long *) dest->b_data, *sourcep = (long *) source->b_data; - - for (i = lines; i > 0; i--) { - *(destp + 0) ^= *(sourcep + 0); - *(destp + 1) ^= *(sourcep + 1); - *(destp + 2) ^= *(sourcep + 2); - *(destp + 3) ^= *(sourcep + 3); - *(destp + 4) ^= *(sourcep + 4); - *(destp + 5) ^= *(sourcep + 5); - *(destp + 6) ^= *(sourcep + 6); - *(destp + 7) ^= *(sourcep + 7); - destp += 8; - sourcep += 8; - } -} -#endif - static void compute_block(struct stripe_head *sh, int dd_idx) { - struct raid5_data *raid_conf = sh->raid_conf; - int i, disks = raid_conf->raid_disks; + raid5_conf_t *conf = sh->raid_conf; + int i, count, disks = conf->raid_disks; + struct buffer_head *bh_ptr[MAX_XOR_BLOCKS]; - PRINTK(("compute_block, stripe %lu, idx %d\n", sh->sector, dd_idx)); + PRINTK("compute_block, stripe %lu, idx %d\n", sh->sector, dd_idx); if (sh->bh_old[dd_idx] == NULL) - sh->bh_old[dd_idx] = raid5_kmalloc_buffer(sh, sh->size); + sh->bh_old[dd_idx] = raid5_alloc_buffer(sh, sh->size); raid5_build_block(sh, sh->bh_old[dd_idx], dd_idx); memset(sh->bh_old[dd_idx]->b_data, 0, sh->size); + bh_ptr[0] = sh->bh_old[dd_idx]; + count = 1; for (i = 0; i < disks; i++) { if (i == dd_idx) continue; if (sh->bh_old[i]) { - xor_block(sh->bh_old[dd_idx], sh->bh_old[i]); - continue; - } else + bh_ptr[count++] = sh->bh_old[i]; + } else { printk("compute_block() %d, stripe %lu, %d not present\n", dd_idx, sh->sector, i); + } + if (count == MAX_XOR_BLOCKS) { + xor_block(count, &bh_ptr[0]); + count = 1; + } + } + if(count != 1) { + xor_block(count, &bh_ptr[0]); } raid5_mark_buffer_uptodate(sh->bh_old[dd_idx], 1); } static void compute_parity(struct stripe_head *sh, int method) { - struct raid5_data *raid_conf = sh->raid_conf; - int i, pd_idx = sh->pd_idx, disks = raid_conf->raid_disks; + raid5_conf_t *conf = sh->raid_conf; + int i, pd_idx = sh->pd_idx, disks = conf->raid_disks, count; + struct buffer_head *bh_ptr[MAX_XOR_BLOCKS]; - PRINTK(("compute_parity, stripe %lu, method %d\n", sh->sector, method)); + PRINTK("compute_parity, stripe %lu, method %d\n", sh->sector, method); for (i = 0; i < disks; i++) { if (i == pd_idx || !sh->bh_new[i]) continue; if (!sh->bh_copy[i]) - sh->bh_copy[i] = raid5_kmalloc_buffer(sh, sh->size); + sh->bh_copy[i] = raid5_alloc_buffer(sh, sh->size); raid5_build_block(sh, sh->bh_copy[i], i); - mark_buffer_clean(sh->bh_new[i]); + if (atomic_set_buffer_clean(sh->bh_new[i])) + atomic_set_buffer_dirty(sh->bh_copy[i]); memcpy(sh->bh_copy[i]->b_data, sh->bh_new[i]->b_data, sh->size); } - if (sh->bh_copy[pd_idx] == NULL) - sh->bh_copy[pd_idx] = raid5_kmalloc_buffer(sh, sh->size); + if (sh->bh_copy[pd_idx] == NULL) { + sh->bh_copy[pd_idx] = raid5_alloc_buffer(sh, sh->size); + atomic_set_buffer_dirty(sh->bh_copy[pd_idx]); + } raid5_build_block(sh, sh->bh_copy[pd_idx], sh->pd_idx); if (method == RECONSTRUCT_WRITE) { memset(sh->bh_copy[pd_idx]->b_data, 0, sh->size); + bh_ptr[0] = sh->bh_copy[pd_idx]; + count = 1; for (i = 0; i < disks; i++) { if (i == sh->pd_idx) continue; if (sh->bh_new[i]) { - xor_block(sh->bh_copy[pd_idx], sh->bh_copy[i]); - continue; + bh_ptr[count++] = sh->bh_copy[i]; + } else if (sh->bh_old[i]) { + bh_ptr[count++] = sh->bh_old[i]; } - if (sh->bh_old[i]) { - xor_block(sh->bh_copy[pd_idx], sh->bh_old[i]); - continue; + if (count == MAX_XOR_BLOCKS) { + xor_block(count, &bh_ptr[0]); + count = 1; } } + if (count != 1) { + xor_block(count, &bh_ptr[0]); + } } else if (method == READ_MODIFY_WRITE) { memcpy(sh->bh_copy[pd_idx]->b_data, sh->bh_old[pd_idx]->b_data, sh->size); + bh_ptr[0] = sh->bh_copy[pd_idx]; + count = 1; for (i = 0; i < disks; i++) { if (i == sh->pd_idx) continue; if (sh->bh_new[i] && sh->bh_old[i]) { - xor_block(sh->bh_copy[pd_idx], sh->bh_copy[i]); - xor_block(sh->bh_copy[pd_idx], sh->bh_old[i]); - continue; + bh_ptr[count++] = sh->bh_copy[i]; + bh_ptr[count++] = sh->bh_old[i]; + } + if (count >= (MAX_XOR_BLOCKS - 1)) { + xor_block(count, &bh_ptr[0]); + count = 1; } } + if (count != 1) { + xor_block(count, &bh_ptr[0]); + } } raid5_mark_buffer_uptodate(sh->bh_copy[pd_idx], 1); } static void add_stripe_bh (struct stripe_head *sh, struct buffer_head *bh, int dd_idx, int rw) { - struct raid5_data *raid_conf = sh->raid_conf; + raid5_conf_t *conf = sh->raid_conf; struct buffer_head *bh_req; - if (sh->bh_new[dd_idx]) { - printk("raid5: bug: stripe->bh_new[%d], sector %lu exists\n", dd_idx, sh->sector); - printk("forcing oops.\n"); - *(int*)0=0; - } - - set_bit(BH_Lock, &bh->b_state); + PRINTK("adding bh b#%lu to stripe s#%lu\n", bh->b_blocknr, sh->sector); + CHECK_SHLOCK(sh); + if (sh->bh_new[dd_idx]) + BUG(); - bh_req = raid5_kmalloc_bh(sh); + bh_req = raid5_alloc_bh(sh); raid5_build_block(sh, bh_req, dd_idx); bh_req->b_data = bh->b_data; + bh_req->b_page = bh->b_page; + md_spin_lock_irq(&conf->device_lock); if (sh->phase == PHASE_COMPLETE && sh->cmd == STRIPE_NONE) { + PRINTK("stripe s#%lu => PHASE_BEGIN (%s)\n", sh->sector, rw == READ ? "read" : "write"); sh->phase = PHASE_BEGIN; sh->cmd = (rw == READ) ? STRIPE_READ : STRIPE_WRITE; - raid_conf->nr_pending_stripes++; - atomic_inc(&raid_conf->nr_handle); + atomic_inc(&conf->nr_pending_stripes); + atomic_inc(&conf->nr_handle); + PRINTK("# of pending stripes: %u, # of handle: %u\n", atomic_read(&conf->nr_pending_stripes), atomic_read(&conf->nr_handle)); } sh->bh_new[dd_idx] = bh; sh->bh_req[dd_idx] = bh_req; sh->cmd_new[dd_idx] = rw; sh->new[dd_idx] = 1; + md_spin_unlock_irq(&conf->device_lock); + + PRINTK("added bh b#%lu to stripe s#%lu, disk %d.\n", bh->b_blocknr, sh->sector, dd_idx); } static void complete_stripe(struct stripe_head *sh) { - struct raid5_data *raid_conf = sh->raid_conf; - int disks = raid_conf->raid_disks; + raid5_conf_t *conf = sh->raid_conf; + int disks = conf->raid_disks; int i, new = 0; - PRINTK(("complete_stripe %lu\n", sh->sector)); + PRINTK("complete_stripe %lu\n", sh->sector); for (i = 0; i < disks; i++) { + if (sh->cmd == STRIPE_SYNC && sh->bh_copy[i]) + raid5_update_old_bh(sh, i); if (sh->cmd == STRIPE_WRITE && i == sh->pd_idx) raid5_update_old_bh(sh, i); if (sh->bh_new[i]) { + PRINTK("stripe %lu finishes new bh, sh->new == %d\n", sh->sector, sh->new[i]); if (!sh->new[i]) { #if 0 if (sh->cmd == STRIPE_WRITE) { @@ -903,349 +989,599 @@ if (new && sh->cmd == STRIPE_WRITE) printk("raid5: bug, completed STRIPE_WRITE with new == %d\n", new); } + if (sh->cmd == STRIPE_SYNC) + md_done_sync(conf->mddev, (sh->size>>10) - sh->sync_redone,1); if (!new) - finish_stripe(sh); + finish_unlock_stripe(sh); else { - PRINTK(("stripe %lu, new == %d\n", sh->sector, new)); + PRINTK("stripe %lu, new == %d\n", sh->sector, new); sh->phase = PHASE_BEGIN; } } -/* - * handle_stripe() is our main logic routine. Note that: - * - * 1. lock_stripe() should be used whenever we can't accept additonal - * buffers, either during short sleeping in handle_stripe() or - * during io operations. - * - * 2. We should be careful to set sh->nr_pending whenever we sleep, - * to prevent re-entry of handle_stripe() for the same sh. - * - * 3. raid_conf->failed_disks and disk->operational can be changed - * from an interrupt. This complicates things a bit, but it allows - * us to stop issuing requests for a failed drive as soon as possible. - */ -static void handle_stripe(struct stripe_head *sh) -{ - struct raid5_data *raid_conf = sh->raid_conf; - struct md_dev *mddev = raid_conf->mddev; - int minor = (int) (mddev - md_dev); - struct buffer_head *bh; - int disks = raid_conf->raid_disks; - int i, nr = 0, nr_read = 0, nr_write = 0; - int nr_cache = 0, nr_cache_other = 0, nr_cache_overwrite = 0, parity = 0; - int nr_failed_other = 0, nr_failed_overwrite = 0, parity_failed = 0; - int reading = 0, nr_writing = 0; - int method1 = INT_MAX, method2 = INT_MAX; - int block; - unsigned long flags; - int operational[MD_SB_DISKS], failed_disks = raid_conf->failed_disks; - - PRINTK(("handle_stripe(), stripe %lu\n", sh->sector)); - if (sh->nr_pending) { - printk("handle_stripe(), stripe %lu, io still pending\n", sh->sector); - return; - } - if (sh->phase == PHASE_COMPLETE) { - printk("handle_stripe(), stripe %lu, already complete\n", sh->sector); - return; - } - atomic_dec(&raid_conf->nr_handle); +static int is_stripe_allclean(struct stripe_head *sh, int disks) +{ + int i; - if (test_and_clear_bit(STRIPE_ERROR, &sh->state)) { - printk("raid5: restarting stripe %lu\n", sh->sector); - sh->phase = PHASE_BEGIN; + return 0; + for (i = 0; i < disks; i++) { + if (sh->bh_new[i]) + if (test_bit(BH_Dirty, &sh->bh_new[i])) + return 0; + if (sh->bh_old[i]) + if (test_bit(BH_Dirty, &sh->bh_old[i])) + return 0; } + return 1; +} - if ((sh->cmd == STRIPE_WRITE && sh->phase == PHASE_WRITE) || - (sh->cmd == STRIPE_READ && sh->phase == PHASE_READ)) { - /* - * Completed - */ - complete_stripe(sh); - if (sh->phase == PHASE_COMPLETE) - return; - } +static void handle_stripe_write (mddev_t *mddev , raid5_conf_t *conf, + struct stripe_head *sh, int nr_write, int * operational, int disks, + int parity, int parity_failed, int nr_cache, int nr_cache_other, + int nr_failed_other, int nr_cache_overwrite, int nr_failed_overwrite) +{ + int i, allclean; + request_queue_t *q; + unsigned int block; + struct buffer_head *bh; + int method1 = INT_MAX, method2 = INT_MAX; - save_flags(flags); - cli(); - for (i = 0; i < disks; i++) { - operational[i] = raid_conf->disks[i].operational; - if (i == sh->pd_idx && raid_conf->resync_parity) - operational[i] = 0; + /* + * Attempt to add entries :-) + */ + if (nr_write != disks - 1) { + for (i = 0; i < disks; i++) { + if (i == sh->pd_idx) + continue; + if (sh->bh_new[i]) + continue; + block = (int) compute_blocknr(sh, i); + bh = get_hash_table(mddev_to_kdev(mddev), block, sh->size); + if (!bh) + continue; + if (buffer_dirty(bh) && !md_test_and_set_bit(BH_Lock, &bh->b_state)) { + PRINTK("Whee.. sector %lu, index %d (%d) found in the buffer cache!\n", sh->sector, i, block); + add_stripe_bh(sh, bh, i, WRITE); + sh->new[i] = 0; + nr_write++; + if (sh->bh_old[i]) { + nr_cache_overwrite++; + nr_cache_other--; + } else + if (!operational[i]) { + nr_failed_overwrite++; + nr_failed_other--; + } + } + atomic_dec(&bh->b_count); + } } - failed_disks = raid_conf->failed_disks; - restore_flags(flags); + PRINTK("handle_stripe() -- begin writing, stripe %lu\n", sh->sector); + /* + * Writing, need to update parity buffer. + * + * Compute the number of I/O requests in the "reconstruct + * write" and "read modify write" methods. + */ + if (!nr_failed_other) + method1 = (disks - 1) - (nr_write + nr_cache_other); + if (!nr_failed_overwrite && !parity_failed) + method2 = nr_write - nr_cache_overwrite + (1 - parity); + + if (method1 == INT_MAX && method2 == INT_MAX) + BUG(); + PRINTK("handle_stripe(), sector %lu, nr_write %d, method1 %d, method2 %d\n", sh->sector, nr_write, method1, method2); + + if (!method1 || !method2) { + allclean = is_stripe_allclean(sh, disks); + sh->phase = PHASE_WRITE; + compute_parity(sh, method1 <= method2 ? RECONSTRUCT_WRITE : READ_MODIFY_WRITE); - if (failed_disks > 1) { for (i = 0; i < disks; i++) { - if (sh->bh_new[i]) { - raid5_end_buffer_io(sh, i, 0); + if (!operational[i] && !conf->spare && !conf->resync_parity) continue; + bh = sh->bh_copy[i]; + if (i != sh->pd_idx && ((bh == NULL) ^ (sh->bh_new[i] == NULL))) + printk("raid5: bug: bh == %p, bh_new[%d] == %p\n", bh, i, sh->bh_new[i]); + if (i == sh->pd_idx && !bh) + printk("raid5: bug: bh == NULL, i == pd_idx == %d\n", i); + if (bh) { + PRINTK("making request for buffer %d\n", i); + lock_get_bh(bh); + if (!operational[i] && !conf->resync_parity) { + PRINTK("writing spare %d\n", i); + atomic_inc(&sh->nr_pending); + bh->b_rdev = conf->spare->dev; + q = blk_get_queue(bh->b_rdev); + generic_make_request(q, WRITERAW, bh); + } else { +#if 0 + atomic_inc(&sh->nr_pending); + bh->b_rdev = conf->disks[i].dev; + q = blk_get_queue(bh->b_rdev); + generic_make_request(q, WRITERAW, bh); +#else + if (!allclean || (i==sh->pd_idx)) { + PRINTK("writing dirty %d\n", i); + atomic_inc(&sh->nr_pending); + bh->b_rdev = conf->disks[i].dev; + q = blk_get_queue(bh->b_rdev); + generic_make_request(q, WRITERAW, bh); + } else { + PRINTK("not writing clean %d\n", i); + raid5_end_request(bh, 1); + sh->new[i] = 0; + } +#endif + } + atomic_dec(&bh->b_count); } } - finish_stripe(sh); + PRINTK("handle_stripe() %lu, writing back %d buffers\n", sh->sector, md_atomic_read(&sh->nr_pending)); return; } - for (i = 0; i < disks; i++) { - if (sh->bh_old[i]) - nr_cache++; - if (i == sh->pd_idx) { - if (sh->bh_old[i]) - parity = 1; - else if(!operational[i]) - parity_failed = 1; - continue; + if (method1 < method2) { + sh->write_method = RECONSTRUCT_WRITE; + for (i = 0; i < disks; i++) { + if (i == sh->pd_idx) + continue; + if (sh->bh_new[i] || sh->bh_old[i]) + continue; + sh->bh_old[i] = raid5_alloc_buffer(sh, sh->size); + raid5_build_block(sh, sh->bh_old[i], i); } - if (!sh->bh_new[i]) { + } else { + sh->write_method = READ_MODIFY_WRITE; + for (i = 0; i < disks; i++) { if (sh->bh_old[i]) - nr_cache_other++; - else if (!operational[i]) - nr_failed_other++; - continue; + continue; + if (!sh->bh_new[i] && i != sh->pd_idx) + continue; + sh->bh_old[i] = raid5_alloc_buffer(sh, sh->size); + raid5_build_block(sh, sh->bh_old[i], i); } - sh->new[i] = 0; - nr++; - if (sh->cmd_new[i] == READ) - nr_read++; - if (sh->cmd_new[i] == WRITE) - nr_write++; - if (sh->bh_old[i]) - nr_cache_overwrite++; - else if (!operational[i]) - nr_failed_overwrite++; } - - if (nr_write && nr_read) - printk("raid5: bug, nr_write == %d, nr_read == %d, sh->cmd == %d\n", nr_write, nr_read, sh->cmd); - - if (nr_write) { - /* - * Attempt to add entries :-) - */ - if (nr_write != disks - 1) { - for (i = 0; i < disks; i++) { - if (i == sh->pd_idx) - continue; - if (sh->bh_new[i]) - continue; - block = (int) compute_blocknr(sh, i); - bh = get_hash_table(MKDEV(MD_MAJOR, minor), block, sh->size); - if (bh) { - if (atomic_read(&bh->b_count) == 1 && - buffer_dirty(bh) && - !buffer_locked(bh)) { - PRINTK(("Whee.. sector %lu, index %d (%d) found in the buffer cache!\n", sh->sector, i, block)); - add_stripe_bh(sh, bh, i, WRITE); - sh->new[i] = 0; - nr++; nr_write++; - if (sh->bh_old[i]) { - nr_cache_overwrite++; - nr_cache_other--; - } else if (!operational[i]) { - nr_failed_overwrite++; - nr_failed_other--; - } - } - atomic_dec(&bh->b_count); - } - } + sh->phase = PHASE_READ_OLD; + for (i = 0; i < disks; i++) { + if (!sh->bh_old[i]) + continue; + if (test_bit(BH_Uptodate, &sh->bh_old[i]->b_state)) + continue; + lock_get_bh(sh->bh_old[i]); + atomic_inc(&sh->nr_pending); + sh->bh_old[i]->b_rdev = conf->disks[i].dev; + q = blk_get_queue(sh->bh_old[i]->b_rdev); + generic_make_request(q, READ, sh->bh_old[i]); + atomic_dec(&sh->bh_old[i]->b_count); + } + PRINTK("handle_stripe() %lu, reading %d old buffers\n", sh->sector, md_atomic_read(&sh->nr_pending)); +} + +/* + * Reading + */ +static void handle_stripe_read (mddev_t *mddev , raid5_conf_t *conf, + struct stripe_head *sh, int nr_read, int * operational, int disks, + int parity, int parity_failed, int nr_cache, int nr_cache_other, + int nr_failed_other, int nr_cache_overwrite, int nr_failed_overwrite) +{ + int i; + request_queue_t *q; + int method1 = INT_MAX; + + method1 = nr_read - nr_cache_overwrite; + + PRINTK("handle_stripe(), sector %lu, nr_read %d, nr_cache %d, method1 %d\n", sh->sector, nr_read, nr_cache, method1); + + if (!method1 || (method1 == 1 && nr_cache == disks - 1)) { + PRINTK("read %lu completed from cache\n", sh->sector); + for (i = 0; i < disks; i++) { + if (!sh->bh_new[i]) + continue; + if (!sh->bh_old[i]) + compute_block(sh, i); + memcpy(sh->bh_new[i]->b_data, sh->bh_old[i]->b_data, sh->size); } - PRINTK(("handle_stripe() -- begin writing, stripe %lu\n", sh->sector)); - /* - * Writing, need to update parity buffer. - * - * Compute the number of I/O requests in the "reconstruct - * write" and "read modify write" methods. - */ - if (!nr_failed_other) - method1 = (disks - 1) - (nr_write + nr_cache_other); - if (!nr_failed_overwrite && !parity_failed) - method2 = nr_write - nr_cache_overwrite + (1 - parity); - - if (method1 == INT_MAX && method2 == INT_MAX) - printk("raid5: bug: method1 == method2 == INT_MAX\n"); - PRINTK(("handle_stripe(), sector %lu, nr_write %d, method1 %d, method2 %d\n", sh->sector, nr_write, method1, method2)); - - if (!method1 || !method2) { - lock_stripe(sh); - sh->nr_pending++; - sh->phase = PHASE_WRITE; - compute_parity(sh, method1 <= method2 ? RECONSTRUCT_WRITE : READ_MODIFY_WRITE); - for (i = 0; i < disks; i++) { - if (!operational[i] && !raid_conf->spare && !raid_conf->resync_parity) - continue; - if (i == sh->pd_idx || sh->bh_new[i]) - nr_writing++; - } - - sh->nr_pending = nr_writing; - PRINTK(("handle_stripe() %lu, writing back %d\n", sh->sector, sh->nr_pending)); - - for (i = 0; i < disks; i++) { - if (!operational[i] && !raid_conf->spare && !raid_conf->resync_parity) - continue; - bh = sh->bh_copy[i]; - if (i != sh->pd_idx && ((bh == NULL) ^ (sh->bh_new[i] == NULL))) - printk("raid5: bug: bh == %p, bh_new[%d] == %p\n", bh, i, sh->bh_new[i]); - if (i == sh->pd_idx && !bh) - printk("raid5: bug: bh == NULL, i == pd_idx == %d\n", i); - if (bh) { - bh->b_state |= (1<b_state); - if (!operational[i] && !raid_conf->resync_parity) { - bh->b_rdev = raid_conf->spare->dev; - make_request(MAJOR(raid_conf->spare->dev), WRITE, bh); - } else - make_request(MAJOR(raid_conf->disks[i].dev), WRITE, bh); - } - } - return; + complete_stripe(sh); + return; + } + if (nr_failed_overwrite) { + sh->phase = PHASE_READ_OLD; + for (i = 0; i < disks; i++) { + if (sh->bh_old[i]) + continue; + if (!operational[i]) + continue; + sh->bh_old[i] = raid5_alloc_buffer(sh, sh->size); + raid5_build_block(sh, sh->bh_old[i], i); + lock_get_bh(sh->bh_old[i]); + atomic_inc(&sh->nr_pending); + sh->bh_old[i]->b_rdev = conf->disks[i].dev; + q = blk_get_queue(sh->bh_old[i]->b_rdev); + generic_make_request(q, READ, sh->bh_old[i]); + atomic_dec(&sh->bh_old[i]->b_count); } - - lock_stripe(sh); - sh->nr_pending++; - if (method1 < method2) { - sh->write_method = RECONSTRUCT_WRITE; - for (i = 0; i < disks; i++) { - if (i == sh->pd_idx) - continue; - if (sh->bh_new[i] || sh->bh_old[i]) - continue; - sh->bh_old[i] = raid5_kmalloc_buffer(sh, sh->size); - raid5_build_block(sh, sh->bh_old[i], i); - reading++; - } - } else { - sh->write_method = READ_MODIFY_WRITE; - for (i = 0; i < disks; i++) { - if (sh->bh_old[i]) - continue; - if (!sh->bh_new[i] && i != sh->pd_idx) - continue; - sh->bh_old[i] = raid5_kmalloc_buffer(sh, sh->size); - raid5_build_block(sh, sh->bh_old[i], i); - reading++; + PRINTK("handle_stripe() %lu, phase READ_OLD, pending %d buffers\n", sh->sector, md_atomic_read(&sh->nr_pending)); + return; + } + sh->phase = PHASE_READ; + for (i = 0; i < disks; i++) { + if (!sh->bh_new[i]) + continue; + if (sh->bh_old[i]) { + memcpy(sh->bh_new[i]->b_data, sh->bh_old[i]->b_data, sh->size); + continue; + } +#if RAID5_PARANOIA + if (sh->bh_req[i] == NULL || test_bit(BH_Lock, &sh->bh_req[i]->b_state)) { + int j; + printk("req %d is NULL! or locked \n", i); + for (j=0; jbh_new[j], sh->bh_old[j], sh->bh_req[j], + sh->new[j], sh->cmd_new[j]); } + } +#endif + lock_get_bh(sh->bh_req[i]); + atomic_inc(&sh->nr_pending); + sh->bh_req[i]->b_rdev = conf->disks[i].dev; + q = blk_get_queue(sh->bh_req[i]->b_rdev); + generic_make_request(q, READ, sh->bh_req[i]); + atomic_dec(&sh->bh_req[i]->b_count); + } + PRINTK("handle_stripe() %lu, phase READ, pending %d\n", sh->sector, md_atomic_read(&sh->nr_pending)); +} + +/* + * Syncing + */ +static void handle_stripe_sync (mddev_t *mddev , raid5_conf_t *conf, + struct stripe_head *sh, int * operational, int disks, + int parity, int parity_failed, int nr_cache, int nr_cache_other, + int nr_failed_other, int nr_cache_overwrite, int nr_failed_overwrite) +{ + request_queue_t *q; + struct buffer_head *bh; + int i, pd_idx; + + /* firstly, we want to have data from all non-failed drives + * in bh_old + */ + PRINTK("handle_stripe_sync: sec=%lu disks=%d nr_cache=%d\n", sh->sector, disks, nr_cache); + if (nr_cache < disks-1 + || (nr_cache==disks-1 && !(parity_failed+nr_failed_other+nr_failed_overwrite)) + ) { sh->phase = PHASE_READ_OLD; - sh->nr_pending = reading; - PRINTK(("handle_stripe() %lu, reading %d old buffers\n", sh->sector, sh->nr_pending)); for (i = 0; i < disks; i++) { - if (!sh->bh_old[i]) + if (sh->bh_old[i]) continue; - if (buffer_uptodate(sh->bh_old[i])) + if (!conf->disks[i].operational) continue; - clear_bit(BH_Lock, &sh->bh_old[i]->b_state); - make_request(MAJOR(raid_conf->disks[i].dev), READ, sh->bh_old[i]); + + bh = raid5_alloc_buffer(sh, sh->size); + sh->bh_old[i] = bh; + raid5_build_block(sh, bh, i); + lock_get_bh(bh); + atomic_inc(&sh->nr_pending); + bh->b_rdev = conf->disks[i].dev; + q = blk_get_queue(bh->b_rdev); + generic_make_request(q, READ, bh); + drive_stat_acct(bh->b_rdev, READ, -bh->b_size/512, 0); + atomic_dec(&sh->bh_old[i]->b_count); + } + PRINTK("handle_stripe_sync() %lu, phase READ_OLD, pending %d buffers\n", sh->sector, md_atomic_read(&sh->nr_pending)); + + return; + } + /* now, if there is a failed drive, rebuild and write to spare */ + if (nr_cache == disks-1) { + sh->phase = PHASE_WRITE; + /* we can generate the missing block, which will be on the failed drive */ + for (i=0; ispare) { + bh = sh->bh_copy[i]; + if (bh) { + memcpy(bh->b_data, sh->bh_old[i]->b_data, sh->size); + set_bit(BH_Uptodate, &bh->b_state); + } else { + bh = sh->bh_old[i]; + sh->bh_old[i] = NULL; + sh->bh_copy[i] = bh; + } + atomic_inc(&sh->nr_pending); + lock_get_bh(bh); + bh->b_rdev = conf->spare->dev; + q = blk_get_queue(bh->b_rdev); + generic_make_request(q, WRITERAW, bh); + drive_stat_acct(bh->b_rdev, WRITE, -bh->b_size/512, 0); + atomic_dec(&bh->b_count); + PRINTK("handle_stripe_sync() %lu, phase WRITE, pending %d buffers\n", sh->sector, md_atomic_read(&sh->nr_pending)); + } + break; } + return; + } + + /* nr_cache == disks: + * check parity and compute/write if needed + */ + + compute_parity(sh, RECONSTRUCT_WRITE); + pd_idx = sh->pd_idx; + if (!memcmp(sh->bh_copy[pd_idx]->b_data, sh->bh_old[pd_idx]->b_data, sh->size)) { + /* the parity is correct - Yay! */ + complete_stripe(sh); } else { + sh->phase = PHASE_WRITE; + bh = sh->bh_copy[pd_idx]; + atomic_set_buffer_dirty(bh); + lock_get_bh(bh); + atomic_inc(&sh->nr_pending); + bh->b_rdev = conf->disks[pd_idx].dev; + q = blk_get_queue(bh->b_rdev); + generic_make_request(q, WRITERAW, bh); + drive_stat_acct(bh->b_rdev, WRITE, -bh->b_size/512, 0); + atomic_dec(&bh->b_count); + PRINTK("handle_stripe_sync() %lu phase WRITE, pending %d buffers\n", + sh->sector, md_atomic_read(&sh->nr_pending)); + } +} + +/* + * handle_stripe() is our main logic routine. Note that: + * + * 1. lock_stripe() should be used whenever we can't accept additonal + * buffers, either during short sleeping in handle_stripe() or + * during io operations. + * + * 2. We should be careful to set sh->nr_pending whenever we sleep, + * to prevent re-entry of handle_stripe() for the same sh. + * + * 3. conf->failed_disks and disk->operational can be changed + * from an interrupt. This complicates things a bit, but it allows + * us to stop issuing requests for a failed drive as soon as possible. + */ +static void handle_stripe(struct stripe_head *sh) +{ + raid5_conf_t *conf = sh->raid_conf; + mddev_t *mddev = conf->mddev; + int disks = conf->raid_disks; + int i, nr_read = 0, nr_write = 0, parity = 0; + int nr_cache = 0, nr_cache_other = 0, nr_cache_overwrite = 0; + int nr_failed_other = 0, nr_failed_overwrite = 0, parity_failed = 0; + int operational[MD_SB_DISKS], failed_disks = conf->failed_disks; + + PRINTK("handle_stripe(), stripe %lu\n", sh->sector); + if (!stripe_locked(sh)) + BUG(); + if (md_atomic_read(&sh->nr_pending)) + BUG(); + if (sh->phase == PHASE_COMPLETE) + BUG(); + + atomic_dec(&conf->nr_handle); + + if (md_test_and_clear_bit(STRIPE_ERROR, &sh->state)) { + printk("raid5: restarting stripe %lu\n", sh->sector); + sh->phase = PHASE_BEGIN; + } + + if ((sh->cmd == STRIPE_WRITE && sh->phase == PHASE_WRITE) || + (sh->cmd == STRIPE_READ && sh->phase == PHASE_READ) || + (sh->cmd == STRIPE_SYNC && sh->phase == PHASE_WRITE) + ) { /* - * Reading + * Completed */ - method1 = nr_read - nr_cache_overwrite; - lock_stripe(sh); - sh->nr_pending++; + complete_stripe(sh); + if (sh->phase == PHASE_COMPLETE) + return; + } + + md_spin_lock_irq(&conf->device_lock); + for (i = 0; i < disks; i++) { + operational[i] = conf->disks[i].operational; + if (i == sh->pd_idx && conf->resync_parity) + operational[i] = 0; + } + failed_disks = conf->failed_disks; + md_spin_unlock_irq(&conf->device_lock); - PRINTK(("handle_stripe(), sector %lu, nr_read %d, nr_cache %d, method1 %d\n", sh->sector, nr_read, nr_cache, method1)); - if (!method1 || (method1 == 1 && nr_cache == disks - 1)) { - PRINTK(("read %lu completed from cache\n", sh->sector)); - for (i = 0; i < disks; i++) { - if (!sh->bh_new[i]) - continue; - if (!sh->bh_old[i]) - compute_block(sh, i); - memcpy(sh->bh_new[i]->b_data, sh->bh_old[i]->b_data, sh->size); + /* + * Make this one more graceful? + */ + if (failed_disks > 1) { + for (i = 0; i < disks; i++) { + if (sh->bh_new[i]) { + raid5_end_buffer_io(sh, i, 0); + continue; } - sh->nr_pending--; - complete_stripe(sh); - return; } - if (nr_failed_overwrite) { - sh->phase = PHASE_READ_OLD; - sh->nr_pending = (disks - 1) - nr_cache; - PRINTK(("handle_stripe() %lu, phase READ_OLD, pending %d\n", sh->sector, sh->nr_pending)); - for (i = 0; i < disks; i++) { - if (sh->bh_old[i]) - continue; - if (!operational[i]) - continue; - sh->bh_old[i] = raid5_kmalloc_buffer(sh, sh->size); - raid5_build_block(sh, sh->bh_old[i], i); - clear_bit(BH_Lock, &sh->bh_old[i]->b_state); - make_request(MAJOR(raid_conf->disks[i].dev), READ, sh->bh_old[i]); + if (sh->cmd == STRIPE_SYNC) + md_done_sync(conf->mddev, (sh->size>>10) - sh->sync_redone,1); + finish_unlock_stripe(sh); + return; + } + + PRINTK("=== stripe index START ===\n"); + for (i = 0; i < disks; i++) { + PRINTK("disk %d, ", i); + if (sh->bh_old[i]) { + nr_cache++; + PRINTK(" (old cached, %d)", nr_cache); + } + if (i == sh->pd_idx) { + PRINTK(" PARITY."); + if (sh->bh_old[i]) { + PRINTK(" CACHED."); + parity = 1; + } else { + PRINTK(" UNCACHED."); + if (!operational[i]) { + PRINTK(" FAILED."); + parity_failed = 1; + } + } + PRINTK("\n"); + continue; + } + if (!sh->bh_new[i]) { + PRINTK(" (no new data block) "); + if (sh->bh_old[i]) { + PRINTK(" (but old block cached) "); + nr_cache_other++; + } else { + if (!operational[i]) { + PRINTK(" (because failed disk) "); + nr_failed_other++; + } else + PRINTK(" (no old block either) "); } + PRINTK("\n"); + continue; + } + sh->new[i] = 0; + if (sh->cmd_new[i] == READ) { + nr_read++; + PRINTK(" (new READ %d)", nr_read); + } + if (sh->cmd_new[i] == WRITE) { + nr_write++; + PRINTK(" (new WRITE %d)", nr_write); + } + if (sh->bh_old[i]) { + nr_cache_overwrite++; + PRINTK(" (overwriting old %d)", nr_cache_overwrite); } else { - sh->phase = PHASE_READ; - sh->nr_pending = nr_read - nr_cache_overwrite; - PRINTK(("handle_stripe() %lu, phase READ, pending %d\n", sh->sector, sh->nr_pending)); - for (i = 0; i < disks; i++) { - if (!sh->bh_new[i]) - continue; - if (sh->bh_old[i]) { - memcpy(sh->bh_new[i]->b_data, sh->bh_old[i]->b_data, sh->size); - continue; - } - make_request(MAJOR(raid_conf->disks[i].dev), READ, sh->bh_req[i]); + if (!operational[i]) { + nr_failed_overwrite++; + PRINTK(" (overwriting failed %d)", nr_failed_overwrite); } } + PRINTK("\n"); } + PRINTK("=== stripe index END ===\n"); + + if (nr_write && nr_read) + BUG(); + + if (nr_write) + handle_stripe_write( + mddev, conf, sh, nr_write, operational, disks, + parity, parity_failed, nr_cache, nr_cache_other, + nr_failed_other, nr_cache_overwrite, + nr_failed_overwrite + ); + else if (nr_read) + handle_stripe_read( + mddev, conf, sh, nr_read, operational, disks, + parity, parity_failed, nr_cache, nr_cache_other, + nr_failed_other, nr_cache_overwrite, + nr_failed_overwrite + ); + else if (sh->cmd == STRIPE_SYNC) + handle_stripe_sync( + mddev, conf, sh, operational, disks, + parity, parity_failed, nr_cache, nr_cache_other, + nr_failed_other, nr_cache_overwrite, nr_failed_overwrite + ); } -static int raid5_make_request (struct md_dev *mddev, int rw, struct buffer_head * bh) + +static int raid5_make_request (request_queue_t *q, mddev_t *mddev, int rw, struct buffer_head * bh) { - struct raid5_data *raid_conf = (struct raid5_data *) mddev->private; - const unsigned int raid_disks = raid_conf->raid_disks; + raid5_conf_t *conf = (raid5_conf_t *) mddev->private; + const unsigned int raid_disks = conf->raid_disks; const unsigned int data_disks = raid_disks - 1; unsigned int dd_idx, pd_idx; unsigned long new_sector; struct stripe_head *sh; - if (rw == READA) rw = READ; + if (rw == READA) + rw = READ; - new_sector = raid5_compute_sector(bh->b_rsector, raid_disks, data_disks, - &dd_idx, &pd_idx, raid_conf); + new_sector = raid5_compute_sector(bh->b_blocknr*(bh->b_size>>9), + raid_disks, data_disks, &dd_idx, &pd_idx, conf); - PRINTK(("raid5_make_request, sector %lu\n", new_sector)); -repeat: - sh = get_stripe(raid_conf, new_sector, bh->b_size); + PRINTK("raid5_make_request, sector %lu\n", new_sector); + sh = get_lock_stripe(conf, new_sector, bh->b_size); +#if 0 if ((rw == READ && sh->cmd == STRIPE_WRITE) || (rw == WRITE && sh->cmd == STRIPE_READ)) { - PRINTK(("raid5: lock contention, rw == %d, sh->cmd == %d\n", rw, sh->cmd)); + PRINTK("raid5: lock contention, rw == %d, sh->cmd == %d\n", rw, sh->cmd); lock_stripe(sh); - if (!sh->nr_pending) + if (!md_atomic_read(&sh->nr_pending)) handle_stripe(sh); goto repeat; } +#endif sh->pd_idx = pd_idx; if (sh->phase != PHASE_COMPLETE && sh->phase != PHASE_BEGIN) - PRINTK(("stripe %lu catching the bus!\n", sh->sector)); - if (sh->bh_new[dd_idx]) { - printk("raid5: bug: stripe->bh_new[%d], sector %lu exists\n", dd_idx, sh->sector); - printk("raid5: bh %p, bh_new %p\n", bh, sh->bh_new[dd_idx]); - lock_stripe(sh); - md_wakeup_thread(raid_conf->thread); - wait_on_stripe(sh); - goto repeat; - } + PRINTK("stripe %lu catching the bus!\n", sh->sector); + if (sh->bh_new[dd_idx]) + BUG(); add_stripe_bh(sh, bh, dd_idx, rw); - md_wakeup_thread(raid_conf->thread); + md_wakeup_thread(conf->thread); return 0; } -static void unplug_devices(struct stripe_head *sh) +/* + * Determine correct block size for this device. + */ +unsigned int device_bsize (kdev_t dev) { -#if 0 - struct raid5_data *raid_conf = sh->raid_conf; - int i; + unsigned int i, correct_size; - for (i = 0; i < raid_conf->raid_disks; i++) - unplug_device(blk_dev + MAJOR(raid_conf->disks[i].dev)); -#endif + correct_size = BLOCK_SIZE; + if (blksize_size[MAJOR(dev)]) { + i = blksize_size[MAJOR(dev)][MINOR(dev)]; + if (i) + correct_size = i; + } + + return correct_size; +} + +static int raid5_sync_request (mddev_t *mddev, unsigned long block_nr) +{ + raid5_conf_t *conf = (raid5_conf_t *) mddev->private; + struct stripe_head *sh; + int sectors_per_chunk = conf->chunk_size >> 9; + unsigned long stripe = (block_nr<<2)/sectors_per_chunk; + int chunk_offset = (block_nr<<2) % sectors_per_chunk; + int dd_idx, pd_idx; + unsigned long first_sector; + int raid_disks = conf->raid_disks; + int data_disks = raid_disks-1; + int redone = 0; + int bufsize; + + if (!conf->buffer_size) + conf->buffer_size = /* device_bsize(mddev_to_kdev(mddev))*/ PAGE_SIZE; + bufsize = conf->buffer_size; + /* Hmm... race on buffer_size ?? */ + redone = block_nr% (bufsize>>10); + block_nr -= redone; + sh = get_lock_stripe(conf, block_nr<<1, bufsize); + first_sector = raid5_compute_sector(stripe*data_disks*sectors_per_chunk+chunk_offset, + raid_disks, data_disks, + &dd_idx, &pd_idx, conf); + sh->pd_idx = pd_idx; + sh->cmd = STRIPE_SYNC; + sh->phase = PHASE_BEGIN; + sh->sync_redone = redone; + atomic_inc(&conf->nr_pending_stripes); + atomic_inc(&conf->nr_handle); + md_wakeup_thread(conf->thread); + return (bufsize>>10)-redone; } /* @@ -1258,56 +1594,53 @@ static void raid5d (void *data) { struct stripe_head *sh; - struct raid5_data *raid_conf = data; - struct md_dev *mddev = raid_conf->mddev; - int i, handled = 0, unplug = 0; - unsigned long flags; - - PRINTK(("+++ raid5d active\n")); - + raid5_conf_t *conf = data; + mddev_t *mddev = conf->mddev; + int i, handled; + + PRINTK("+++ raid5d active\n"); + + handled = 0; + md_spin_lock_irq(&conf->device_lock); + clear_bit(THREAD_WAKEUP, &conf->thread->flags); +repeat_pass: if (mddev->sb_dirty) { + md_spin_unlock_irq(&conf->device_lock); mddev->sb_dirty = 0; - md_update_sb((int) (mddev - md_dev)); + md_update_sb(mddev); + md_spin_lock_irq(&conf->device_lock); } for (i = 0; i < NR_HASH; i++) { repeat: - sh = raid_conf->stripe_hashtbl[i]; + sh = conf->stripe_hashtbl[i]; for (; sh; sh = sh->hash_next) { - if (sh->raid_conf != raid_conf) + if (sh->raid_conf != conf) continue; if (sh->phase == PHASE_COMPLETE) continue; - if (sh->nr_pending) + if (md_atomic_read(&sh->nr_pending)) continue; - if (sh->sector == raid_conf->next_sector) { - raid_conf->sector_count += (sh->size >> 9); - if (raid_conf->sector_count >= 128) - unplug = 1; - } else - unplug = 1; - if (unplug) { - PRINTK(("unplugging devices, sector == %lu, count == %d\n", sh->sector, raid_conf->sector_count)); - unplug_devices(sh); - unplug = 0; - raid_conf->sector_count = 0; - } - raid_conf->next_sector = sh->sector + (sh->size >> 9); + md_spin_unlock_irq(&conf->device_lock); + if (!atomic_read(&sh->count)) + BUG(); + handled++; handle_stripe(sh); + md_spin_lock_irq(&conf->device_lock); goto repeat; } } - if (raid_conf) { - PRINTK(("%d stripes handled, nr_handle %d\n", handled, atomic_read(&raid_conf->nr_handle))); - save_flags(flags); - cli(); - if (!atomic_read(&raid_conf->nr_handle)) - clear_bit(THREAD_WAKEUP, &raid_conf->thread->flags); + if (conf) { + PRINTK("%d stripes handled, nr_handle %d\n", handled, md_atomic_read(&conf->nr_handle)); + if (test_and_clear_bit(THREAD_WAKEUP, &conf->thread->flags) && + md_atomic_read(&conf->nr_handle)) + goto repeat_pass; } - PRINTK(("--- raid5d inactive\n")); + md_spin_unlock_irq(&conf->device_lock); + + PRINTK("--- raid5d inactive\n"); } -#if SUPPORT_RECONSTRUCTION /* * Private kernel thread for parity reconstruction after an unclean * shutdown. Reconstruction on spare drives in case of a failed drive @@ -1315,44 +1648,68 @@ */ static void raid5syncd (void *data) { - struct raid5_data *raid_conf = data; - struct md_dev *mddev = raid_conf->mddev; + raid5_conf_t *conf = data; + mddev_t *mddev = conf->mddev; - if (!raid_conf->resync_parity) + if (!conf->resync_parity) + return; + if (conf->resync_parity == 2) return; - md_do_sync(mddev); - raid_conf->resync_parity = 0; + down(&mddev->recovery_sem); + if (md_do_sync(mddev,NULL)) { + up(&mddev->recovery_sem); + printk("raid5: resync aborted!\n"); + return; + } + conf->resync_parity = 0; + up(&mddev->recovery_sem); + printk("raid5: resync finished.\n"); } -#endif /* SUPPORT_RECONSTRUCTION */ -static int __check_consistency (struct md_dev *mddev, int row) +static int __check_consistency (mddev_t *mddev, int row) { - struct raid5_data *raid_conf = mddev->private; + raid5_conf_t *conf = mddev->private; kdev_t dev; - struct buffer_head *bh[MD_SB_DISKS], tmp; - int i, rc = 0, nr = 0; - - if (raid_conf->working_disks != raid_conf->raid_disks) - return 0; - tmp.b_size = 4096; - if ((tmp.b_data = (char *) get_free_page(GFP_KERNEL)) == NULL) - return 0; + struct buffer_head *bh[MD_SB_DISKS], *tmp = NULL; + int i, ret = 0, nr = 0, count; + struct buffer_head *bh_ptr[MAX_XOR_BLOCKS]; + + if (conf->working_disks != conf->raid_disks) + goto out; + tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); + tmp->b_size = 4096; + tmp->b_page = alloc_page(GFP_KERNEL); + tmp->b_data = (char *)page_address(tmp->b_page); + if (!tmp->b_data) + goto out; + md_clear_page((unsigned long)tmp->b_data); memset(bh, 0, MD_SB_DISKS * sizeof(struct buffer_head *)); - for (i = 0; i < raid_conf->raid_disks; i++) { - dev = raid_conf->disks[i].dev; + for (i = 0; i < conf->raid_disks; i++) { + dev = conf->disks[i].dev; set_blocksize(dev, 4096); - if ((bh[i] = bread(dev, row / 4, 4096)) == NULL) + bh[i] = bread(dev, row / 4, 4096); + if (!bh[i]) break; nr++; } - if (nr == raid_conf->raid_disks) { - for (i = 1; i < nr; i++) - xor_block(&tmp, bh[i]); - if (memcmp(tmp.b_data, bh[0]->b_data, 4096)) - rc = 1; + if (nr == conf->raid_disks) { + bh_ptr[0] = tmp; + count = 1; + for (i = 1; i < nr; i++) { + bh_ptr[count++] = bh[i]; + if (count == MAX_XOR_BLOCKS) { + xor_block(count, &bh_ptr[0]); + count = 1; + } + } + if (count != 1) { + xor_block(count, &bh_ptr[0]); + } + if (memcmp(tmp->b_data, bh[0]->b_data, 4096)) + ret = 1; } - for (i = 0; i < raid_conf->raid_disks; i++) { - dev = raid_conf->disks[i].dev; + for (i = 0; i < conf->raid_disks; i++) { + dev = conf->disks[i].dev; if (bh[i]) { bforget(bh[i]); bh[i] = NULL; @@ -1360,308 +1717,691 @@ fsync_dev(dev); invalidate_buffers(dev); } - free_page((unsigned long) tmp.b_data); - return rc; + free_page((unsigned long) tmp->b_data); +out: + if (tmp) + kfree(tmp); + return ret; } -static int check_consistency (struct md_dev *mddev) +static int check_consistency (mddev_t *mddev) { - int size = mddev->sb->size; - int row; + if (__check_consistency(mddev, 0)) +/* + * We are not checking this currently, as it's legitimate to have + * an inconsistent array, at creation time. + */ + return 0; - for (row = 0; row < size; row += size / 8) - if (__check_consistency(mddev, row)) - return 1; return 0; } -static int raid5_run (int minor, struct md_dev *mddev) +static int raid5_run (mddev_t *mddev) { - struct raid5_data *raid_conf; + raid5_conf_t *conf; int i, j, raid_disk, memory; - md_superblock_t *sb = mddev->sb; - md_descriptor_t *descriptor; - struct real_dev *realdev; + mdp_super_t *sb = mddev->sb; + mdp_disk_t *desc; + mdk_rdev_t *rdev; + struct disk_info *disk; + struct md_list_head *tmp; + int start_recovery = 0; MOD_INC_USE_COUNT; if (sb->level != 5 && sb->level != 4) { - printk("raid5: %s: raid level not set to 4/5 (%d)\n", kdevname(MKDEV(MD_MAJOR, minor)), sb->level); + printk("raid5: md%d: raid level not set to 4/5 (%d)\n", mdidx(mddev), sb->level); MOD_DEC_USE_COUNT; return -EIO; } - mddev->private = kmalloc (sizeof (struct raid5_data), GFP_KERNEL); - if ((raid_conf = mddev->private) == NULL) + mddev->private = kmalloc (sizeof (raid5_conf_t), GFP_KERNEL); + if ((conf = mddev->private) == NULL) goto abort; - memset (raid_conf, 0, sizeof (*raid_conf)); - raid_conf->mddev = mddev; + memset (conf, 0, sizeof (*conf)); + conf->mddev = mddev; - if ((raid_conf->stripe_hashtbl = (struct stripe_head **) __get_free_pages(GFP_ATOMIC, HASH_PAGES_ORDER)) == NULL) + if ((conf->stripe_hashtbl = (struct stripe_head **) md__get_free_pages(GFP_ATOMIC, HASH_PAGES_ORDER)) == NULL) goto abort; - memset(raid_conf->stripe_hashtbl, 0, HASH_PAGES * PAGE_SIZE); - - init_waitqueue_head(&raid_conf->wait_for_stripe); - PRINTK(("raid5_run(%d) called.\n", minor)); + memset(conf->stripe_hashtbl, 0, HASH_PAGES * PAGE_SIZE); - for (i = 0; i < mddev->nb_dev; i++) { - realdev = &mddev->devices[i]; - if (!realdev->sb) { - printk(KERN_ERR "raid5: disabled device %s (couldn't access raid superblock)\n", kdevname(realdev->dev)); - continue; - } + conf->device_lock = MD_SPIN_LOCK_UNLOCKED; + md_init_waitqueue_head(&conf->wait_for_stripe); + PRINTK("raid5_run(md%d) called.\n", mdidx(mddev)); + ITERATE_RDEV(mddev,rdev,tmp) { /* * This is important -- we are using the descriptor on * the disk only to get a pointer to the descriptor on * the main superblock, which might be more recent. */ - descriptor = &sb->disks[realdev->sb->descriptor.number]; - if (descriptor->state & (1 << MD_FAULTY_DEVICE)) { - printk(KERN_ERR "raid5: disabled device %s (errors detected)\n", kdevname(realdev->dev)); + desc = sb->disks + rdev->desc_nr; + raid_disk = desc->raid_disk; + disk = conf->disks + raid_disk; + + if (disk_faulty(desc)) { + printk(KERN_ERR "raid5: disabled device %s (errors detected)\n", partition_name(rdev->dev)); + if (!rdev->faulty) { + MD_BUG(); + goto abort; + } + disk->number = desc->number; + disk->raid_disk = raid_disk; + disk->dev = rdev->dev; + + disk->operational = 0; + disk->write_only = 0; + disk->spare = 0; + disk->used_slot = 1; continue; } - if (descriptor->state & (1 << MD_ACTIVE_DEVICE)) { - if (!(descriptor->state & (1 << MD_SYNC_DEVICE))) { - printk(KERN_ERR "raid5: disabled device %s (not in sync)\n", kdevname(realdev->dev)); - continue; + if (disk_active(desc)) { + if (!disk_sync(desc)) { + printk(KERN_ERR "raid5: disabled device %s (not in sync)\n", partition_name(rdev->dev)); + MD_BUG(); + goto abort; } - raid_disk = descriptor->raid_disk; - if (descriptor->number > sb->nr_disks || raid_disk > sb->raid_disks) { - printk(KERN_ERR "raid5: disabled device %s (inconsistent descriptor)\n", kdevname(realdev->dev)); + if (raid_disk > sb->raid_disks) { + printk(KERN_ERR "raid5: disabled device %s (inconsistent descriptor)\n", partition_name(rdev->dev)); continue; } - if (raid_conf->disks[raid_disk].operational) { - printk(KERN_ERR "raid5: disabled device %s (device %d already operational)\n", kdevname(realdev->dev), raid_disk); + if (disk->operational) { + printk(KERN_ERR "raid5: disabled device %s (device %d already operational)\n", partition_name(rdev->dev), raid_disk); continue; } - printk(KERN_INFO "raid5: device %s operational as raid disk %d\n", kdevname(realdev->dev), raid_disk); + printk(KERN_INFO "raid5: device %s operational as raid disk %d\n", partition_name(rdev->dev), raid_disk); - raid_conf->disks[raid_disk].number = descriptor->number; - raid_conf->disks[raid_disk].raid_disk = raid_disk; - raid_conf->disks[raid_disk].dev = mddev->devices[i].dev; - raid_conf->disks[raid_disk].operational = 1; + disk->number = desc->number; + disk->raid_disk = raid_disk; + disk->dev = rdev->dev; + disk->operational = 1; + disk->used_slot = 1; - raid_conf->working_disks++; + conf->working_disks++; } else { /* * Must be a spare disk .. */ - printk(KERN_INFO "raid5: spare disk %s\n", kdevname(realdev->dev)); - raid_disk = descriptor->raid_disk; - raid_conf->disks[raid_disk].number = descriptor->number; - raid_conf->disks[raid_disk].raid_disk = raid_disk; - raid_conf->disks[raid_disk].dev = mddev->devices [i].dev; - - raid_conf->disks[raid_disk].operational = 0; - raid_conf->disks[raid_disk].write_only = 0; - raid_conf->disks[raid_disk].spare = 1; - } - } - raid_conf->raid_disks = sb->raid_disks; - raid_conf->failed_disks = raid_conf->raid_disks - raid_conf->working_disks; - raid_conf->mddev = mddev; - raid_conf->chunk_size = sb->chunk_size; - raid_conf->level = sb->level; - raid_conf->algorithm = sb->parity_algorithm; - raid_conf->max_nr_stripes = NR_STRIPES; + printk(KERN_INFO "raid5: spare disk %s\n", partition_name(rdev->dev)); + disk->number = desc->number; + disk->raid_disk = raid_disk; + disk->dev = rdev->dev; - if (raid_conf->working_disks != sb->raid_disks && sb->state != (1 << MD_SB_CLEAN)) { - printk(KERN_ALERT "raid5: raid set %s not clean and not all disks are operational -- run ckraid\n", kdevname(MKDEV(MD_MAJOR, minor))); - goto abort; + disk->operational = 0; + disk->write_only = 0; + disk->spare = 1; + disk->used_slot = 1; + } + } + + for (i = 0; i < MD_SB_DISKS; i++) { + desc = sb->disks + i; + raid_disk = desc->raid_disk; + disk = conf->disks + raid_disk; + + if (disk_faulty(desc) && (raid_disk < sb->raid_disks) && + !conf->disks[raid_disk].used_slot) { + + disk->number = desc->number; + disk->raid_disk = raid_disk; + disk->dev = MKDEV(0,0); + + disk->operational = 0; + disk->write_only = 0; + disk->spare = 0; + disk->used_slot = 1; + } } - if (!raid_conf->chunk_size || raid_conf->chunk_size % 4) { - printk(KERN_ERR "raid5: invalid chunk size %d for %s\n", raid_conf->chunk_size, kdevname(MKDEV(MD_MAJOR, minor))); + + conf->raid_disks = sb->raid_disks; + /* + * 0 for a fully functional array, 1 for a degraded array. + */ + conf->failed_disks = conf->raid_disks - conf->working_disks; + conf->mddev = mddev; + conf->chunk_size = sb->chunk_size; + conf->level = sb->level; + conf->algorithm = sb->layout; + conf->max_nr_stripes = NR_STRIPES; + +#if 0 + for (i = 0; i < conf->raid_disks; i++) { + if (!conf->disks[i].used_slot) { + MD_BUG(); + goto abort; + } + } +#endif + if (!conf->chunk_size || conf->chunk_size % 4) { + printk(KERN_ERR "raid5: invalid chunk size %d for md%d\n", conf->chunk_size, mdidx(mddev)); goto abort; } - if (raid_conf->algorithm > ALGORITHM_RIGHT_SYMMETRIC) { - printk(KERN_ERR "raid5: unsupported parity algorithm %d for %s\n", raid_conf->algorithm, kdevname(MKDEV(MD_MAJOR, minor))); + if (conf->algorithm > ALGORITHM_RIGHT_SYMMETRIC) { + printk(KERN_ERR "raid5: unsupported parity algorithm %d for md%d\n", conf->algorithm, mdidx(mddev)); goto abort; } - if (raid_conf->failed_disks > 1) { - printk(KERN_ERR "raid5: not enough operational devices for %s (%d/%d failed)\n", kdevname(MKDEV(MD_MAJOR, minor)), raid_conf->failed_disks, raid_conf->raid_disks); + if (conf->failed_disks > 1) { + printk(KERN_ERR "raid5: not enough operational devices for md%d (%d/%d failed)\n", mdidx(mddev), conf->failed_disks, conf->raid_disks); goto abort; } - if ((sb->state & (1 << MD_SB_CLEAN)) && check_consistency(mddev)) { - printk(KERN_ERR "raid5: detected raid-5 xor inconsistenty -- run ckraid\n"); - sb->state |= 1 << MD_SB_ERRORS; - goto abort; + if (conf->working_disks != sb->raid_disks) { + printk(KERN_ALERT "raid5: md%d, not all disks are operational -- trying to recover array\n", mdidx(mddev)); + start_recovery = 1; } - if ((raid_conf->thread = md_register_thread(raid5d, raid_conf)) == NULL) { - printk(KERN_ERR "raid5: couldn't allocate thread for %s\n", kdevname(MKDEV(MD_MAJOR, minor))); - goto abort; + if (!start_recovery && (sb->state & (1 << MD_SB_CLEAN)) && + check_consistency(mddev)) { + printk(KERN_ERR "raid5: detected raid-5 superblock xor inconsistency -- running resync\n"); + sb->state &= ~(1 << MD_SB_CLEAN); } -#if SUPPORT_RECONSTRUCTION - if ((raid_conf->resync_thread = md_register_thread(raid5syncd, raid_conf)) == NULL) { - printk(KERN_ERR "raid5: couldn't allocate thread for %s\n", kdevname(MKDEV(MD_MAJOR, minor))); - goto abort; + { + const char * name = "raid5d"; + + conf->thread = md_register_thread(raid5d, conf, name); + if (!conf->thread) { + printk(KERN_ERR "raid5: couldn't allocate thread for md%d\n", mdidx(mddev)); + goto abort; + } } -#endif /* SUPPORT_RECONSTRUCTION */ - memory = raid_conf->max_nr_stripes * (sizeof(struct stripe_head) + - raid_conf->raid_disks * (sizeof(struct buffer_head) + + memory = conf->max_nr_stripes * (sizeof(struct stripe_head) + + conf->raid_disks * (sizeof(struct buffer_head) + 2 * (sizeof(struct buffer_head) + PAGE_SIZE))) / 1024; - if (grow_stripes(raid_conf, raid_conf->max_nr_stripes, GFP_KERNEL)) { + if (grow_stripes(conf, conf->max_nr_stripes, GFP_KERNEL)) { printk(KERN_ERR "raid5: couldn't allocate %dkB for buffers\n", memory); - shrink_stripes(raid_conf, raid_conf->max_nr_stripes); + shrink_stripes(conf, conf->max_nr_stripes); goto abort; } else - printk(KERN_INFO "raid5: allocated %dkB for %s\n", memory, kdevname(MKDEV(MD_MAJOR, minor))); + printk(KERN_INFO "raid5: allocated %dkB for md%d\n", memory, mdidx(mddev)); /* * Regenerate the "device is in sync with the raid set" bit for * each device. */ - for (i = 0; i < sb->nr_disks ; i++) { - sb->disks[i].state &= ~(1 << MD_SYNC_DEVICE); + for (i = 0; i < MD_SB_DISKS ; i++) { + mark_disk_nonsync(sb->disks + i); for (j = 0; j < sb->raid_disks; j++) { - if (!raid_conf->disks[j].operational) + if (!conf->disks[j].operational) continue; - if (sb->disks[i].number == raid_conf->disks[j].number) - sb->disks[i].state |= 1 << MD_SYNC_DEVICE; + if (sb->disks[i].number == conf->disks[j].number) + mark_disk_sync(sb->disks + i); } } - sb->active_disks = raid_conf->working_disks; + sb->active_disks = conf->working_disks; if (sb->active_disks == sb->raid_disks) - printk("raid5: raid level %d set %s active with %d out of %d devices, algorithm %d\n", raid_conf->level, kdevname(MKDEV(MD_MAJOR, minor)), sb->active_disks, sb->raid_disks, raid_conf->algorithm); + printk("raid5: raid level %d set md%d active with %d out of %d devices, algorithm %d\n", conf->level, mdidx(mddev), sb->active_disks, sb->raid_disks, conf->algorithm); else - printk(KERN_ALERT "raid5: raid level %d set %s active with %d out of %d devices, algorithm %d\n", raid_conf->level, kdevname(MKDEV(MD_MAJOR, minor)), sb->active_disks, sb->raid_disks, raid_conf->algorithm); + printk(KERN_ALERT "raid5: raid level %d set md%d active with %d out of %d devices, algorithm %d\n", conf->level, mdidx(mddev), sb->active_disks, sb->raid_disks, conf->algorithm); + + if (!start_recovery && !(sb->state & (1 << MD_SB_CLEAN))) { + const char * name = "raid5syncd"; - if ((sb->state & (1 << MD_SB_CLEAN)) == 0) { - printk("raid5: raid set %s not clean; re-constructing parity\n", kdevname(MKDEV(MD_MAJOR, minor))); - raid_conf->resync_parity = 1; -#if SUPPORT_RECONSTRUCTION - md_wakeup_thread(raid_conf->resync_thread); -#endif /* SUPPORT_RECONSTRUCTION */ + conf->resync_thread = md_register_thread(raid5syncd, conf,name); + if (!conf->resync_thread) { + printk(KERN_ERR "raid5: couldn't allocate thread for md%d\n", mdidx(mddev)); + goto abort; + } + + printk("raid5: raid set md%d not clean; reconstructing parity\n", mdidx(mddev)); + conf->resync_parity = 1; + md_wakeup_thread(conf->resync_thread); } + print_raid5_conf(conf); + if (start_recovery) + md_recover_arrays(); + print_raid5_conf(conf); + /* Ok, everything is just fine now */ return (0); abort: - if (raid_conf) { - if (raid_conf->stripe_hashtbl) - free_pages((unsigned long) raid_conf->stripe_hashtbl, HASH_PAGES_ORDER); - kfree(raid_conf); + if (conf) { + print_raid5_conf(conf); + if (conf->stripe_hashtbl) + free_pages((unsigned long) conf->stripe_hashtbl, + HASH_PAGES_ORDER); + kfree(conf); } mddev->private = NULL; - printk(KERN_ALERT "raid5: failed to run raid set %s\n", kdevname(MKDEV(MD_MAJOR, minor))); + printk(KERN_ALERT "raid5: failed to run raid set md%d\n", mdidx(mddev)); MOD_DEC_USE_COUNT; return -EIO; } -static int raid5_stop (int minor, struct md_dev *mddev) +static int raid5_stop_resync (mddev_t *mddev) +{ + raid5_conf_t *conf = mddev_to_conf(mddev); + mdk_thread_t *thread = conf->resync_thread; + + if (thread) { + if (conf->resync_parity) { + conf->resync_parity = 2; + md_interrupt_thread(thread); + printk(KERN_INFO "raid5: parity resync was not fully finished, restarting next time.\n"); + return 1; + } + return 0; + } + return 0; +} + +static int raid5_restart_resync (mddev_t *mddev) +{ + raid5_conf_t *conf = mddev_to_conf(mddev); + + if (conf->resync_parity) { + if (!conf->resync_thread) { + MD_BUG(); + return 0; + } + printk("raid5: waking up raid5resync.\n"); + conf->resync_parity = 1; + md_wakeup_thread(conf->resync_thread); + return 1; + } else + printk("raid5: no restart-resync needed.\n"); + return 0; +} + + +static int raid5_stop (mddev_t *mddev) { - struct raid5_data *raid_conf = (struct raid5_data *) mddev->private; + raid5_conf_t *conf = (raid5_conf_t *) mddev->private; - shrink_stripe_cache(raid_conf, raid_conf->max_nr_stripes); - shrink_stripes(raid_conf, raid_conf->max_nr_stripes); - md_unregister_thread(raid_conf->thread); -#if SUPPORT_RECONSTRUCTION - md_unregister_thread(raid_conf->resync_thread); -#endif /* SUPPORT_RECONSTRUCTION */ - free_pages((unsigned long) raid_conf->stripe_hashtbl, HASH_PAGES_ORDER); - kfree(raid_conf); + shrink_stripe_cache(conf, conf->max_nr_stripes); + shrink_stripes(conf, conf->max_nr_stripes); + md_unregister_thread(conf->thread); + if (conf->resync_thread) + md_unregister_thread(conf->resync_thread); + free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER); + kfree(conf); mddev->private = NULL; MOD_DEC_USE_COUNT; return 0; } -static int raid5_status (char *page, int minor, struct md_dev *mddev) +#if RAID5_DEBUG +static void print_sh (struct stripe_head *sh) +{ + int i; + + printk("sh %lu, phase %d, size %d, pd_idx %d, state %ld, cmd %d.\n", sh->sector, sh->phase, sh->size, sh->pd_idx, sh->state, sh->cmd); + printk("sh %lu, write_method %d, nr_pending %d, count %d.\n", sh->sector, sh->write_method, atomic_read(&sh->nr_pending), atomic_read(&sh->count)); + printk("sh %lu, ", sh->sector); + for (i = 0; i < MD_SB_DISKS; i++) { + if (sh->bh_old[i]) + printk("(old%d: %p) ", i, sh->bh_old[i]); + if (sh->bh_new[i]) + printk("(new%d: %p) ", i, sh->bh_new[i]); + if (sh->bh_copy[i]) + printk("(copy%d: %p) ", i, sh->bh_copy[i]); + if (sh->bh_req[i]) + printk("(req%d: %p) ", i, sh->bh_req[i]); + } + printk("\n"); + for (i = 0; i < MD_SB_DISKS; i++) + printk("%d(%d/%d) ", i, sh->cmd_new[i], sh->new[i]); + printk("\n"); +} + +static void printall (raid5_conf_t *conf) { - struct raid5_data *raid_conf = (struct raid5_data *) mddev->private; - md_superblock_t *sb = mddev->sb; + struct stripe_head *sh; + int i; + + md_spin_lock_irq(&conf->device_lock); + for (i = 0; i < NR_HASH; i++) { + sh = conf->stripe_hashtbl[i]; + for (; sh; sh = sh->hash_next) { + if (sh->raid_conf != conf) + continue; + print_sh(sh); + } + } + md_spin_unlock_irq(&conf->device_lock); + + PRINTK("--- raid5d inactive\n"); +} +#endif + +static int raid5_status (char *page, mddev_t *mddev) +{ + raid5_conf_t *conf = (raid5_conf_t *) mddev->private; + mdp_super_t *sb = mddev->sb; int sz = 0, i; - sz += sprintf (page+sz, " level %d, %dk chunk, algorithm %d", sb->level, sb->chunk_size >> 10, sb->parity_algorithm); - sz += sprintf (page+sz, " [%d/%d] [", raid_conf->raid_disks, raid_conf->working_disks); - for (i = 0; i < raid_conf->raid_disks; i++) - sz += sprintf (page+sz, "%s", raid_conf->disks[i].operational ? "U" : "_"); + sz += sprintf (page+sz, " level %d, %dk chunk, algorithm %d", sb->level, sb->chunk_size >> 10, sb->layout); + sz += sprintf (page+sz, " [%d/%d] [", conf->raid_disks, conf->working_disks); + for (i = 0; i < conf->raid_disks; i++) + sz += sprintf (page+sz, "%s", conf->disks[i].operational ? "U" : "_"); sz += sprintf (page+sz, "]"); +#if RAID5_DEBUG +#define D(x) \ + sz += sprintf (page+sz, "<"#x":%d>", atomic_read(&conf->x)) + D(nr_handle); + D(nr_stripes); + D(nr_hashed_stripes); + D(nr_locked_stripes); + D(nr_pending_stripes); + D(nr_cached_stripes); + D(nr_free_sh); + printall(conf); +#endif return sz; } -static int raid5_mark_spare(struct md_dev *mddev, md_descriptor_t *spare, int state) +static void print_raid5_conf (raid5_conf_t *conf) { - int i = 0, failed_disk = -1; - struct raid5_data *raid_conf = mddev->private; - struct disk_info *disk = raid_conf->disks; - unsigned long flags; - md_superblock_t *sb = mddev->sb; - md_descriptor_t *descriptor; + int i; + struct disk_info *tmp; - for (i = 0; i < MD_SB_DISKS; i++, disk++) { - if (disk->spare && disk->number == spare->number) - goto found; + printk("RAID5 conf printout:\n"); + if (!conf) { + printk("(conf==NULL)\n"); + return; } - return 1; -found: - for (i = 0, disk = raid_conf->disks; i < raid_conf->raid_disks; i++, disk++) - if (!disk->operational) - failed_disk = i; - if (failed_disk == -1) - return 1; - save_flags(flags); - cli(); + printk(" --- rd:%d wd:%d fd:%d\n", conf->raid_disks, + conf->working_disks, conf->failed_disks); + + for (i = 0; i < MD_SB_DISKS; i++) { + tmp = conf->disks + i; + printk(" disk %d, s:%d, o:%d, n:%d rd:%d us:%d dev:%s\n", + i, tmp->spare,tmp->operational, + tmp->number,tmp->raid_disk,tmp->used_slot, + partition_name(tmp->dev)); + } +} + +static int raid5_diskop(mddev_t *mddev, mdp_disk_t **d, int state) +{ + int err = 0; + int i, failed_disk=-1, spare_disk=-1, removed_disk=-1, added_disk=-1; + raid5_conf_t *conf = mddev->private; + struct disk_info *tmp, *sdisk, *fdisk, *rdisk, *adisk; + mdp_super_t *sb = mddev->sb; + mdp_disk_t *failed_desc, *spare_desc, *added_desc; + + print_raid5_conf(conf); + md_spin_lock_irq(&conf->device_lock); + /* + * find the disk ... + */ switch (state) { - case SPARE_WRITE: - disk->operational = 1; - disk->write_only = 1; - raid_conf->spare = disk; - break; - case SPARE_INACTIVE: - disk->operational = 0; - disk->write_only = 0; - raid_conf->spare = NULL; - break; - case SPARE_ACTIVE: - disk->spare = 0; - disk->write_only = 0; - descriptor = &sb->disks[raid_conf->disks[failed_disk].number]; - i = spare->raid_disk; - disk->raid_disk = spare->raid_disk = descriptor->raid_disk; - if (disk->raid_disk != failed_disk) - printk("raid5: disk->raid_disk != failed_disk"); - descriptor->raid_disk = i; - - raid_conf->spare = NULL; - raid_conf->working_disks++; - raid_conf->failed_disks--; - raid_conf->disks[failed_disk] = *disk; - break; - default: - printk("raid5_mark_spare: bug: state == %d\n", state); - restore_flags(flags); - return 1; + case DISKOP_SPARE_ACTIVE: + + /* + * Find the failed disk within the RAID5 configuration ... + * (this can only be in the first conf->raid_disks part) + */ + for (i = 0; i < conf->raid_disks; i++) { + tmp = conf->disks + i; + if ((!tmp->operational && !tmp->spare) || + !tmp->used_slot) { + failed_disk = i; + break; + } + } + /* + * When we activate a spare disk we _must_ have a disk in + * the lower (active) part of the array to replace. + */ + if ((failed_disk == -1) || (failed_disk >= conf->raid_disks)) { + MD_BUG(); + err = 1; + goto abort; + } + /* fall through */ + + case DISKOP_SPARE_WRITE: + case DISKOP_SPARE_INACTIVE: + + /* + * Find the spare disk ... (can only be in the 'high' + * area of the array) + */ + for (i = conf->raid_disks; i < MD_SB_DISKS; i++) { + tmp = conf->disks + i; + if (tmp->spare && tmp->number == (*d)->number) { + spare_disk = i; + break; + } + } + if (spare_disk == -1) { + MD_BUG(); + err = 1; + goto abort; + } + break; + + case DISKOP_HOT_REMOVE_DISK: + + for (i = 0; i < MD_SB_DISKS; i++) { + tmp = conf->disks + i; + if (tmp->used_slot && (tmp->number == (*d)->number)) { + if (tmp->operational) { + err = -EBUSY; + goto abort; + } + removed_disk = i; + break; + } + } + if (removed_disk == -1) { + MD_BUG(); + err = 1; + goto abort; + } + break; + + case DISKOP_HOT_ADD_DISK: + + for (i = conf->raid_disks; i < MD_SB_DISKS; i++) { + tmp = conf->disks + i; + if (!tmp->used_slot) { + added_disk = i; + break; + } + } + if (added_disk == -1) { + MD_BUG(); + err = 1; + goto abort; + } + break; } - restore_flags(flags); - return 0; + + switch (state) { + /* + * Switch the spare disk to write-only mode: + */ + case DISKOP_SPARE_WRITE: + if (conf->spare) { + MD_BUG(); + err = 1; + goto abort; + } + sdisk = conf->disks + spare_disk; + sdisk->operational = 1; + sdisk->write_only = 1; + conf->spare = sdisk; + break; + /* + * Deactivate a spare disk: + */ + case DISKOP_SPARE_INACTIVE: + sdisk = conf->disks + spare_disk; + sdisk->operational = 0; + sdisk->write_only = 0; + /* + * Was the spare being resynced? + */ + if (conf->spare == sdisk) + conf->spare = NULL; + break; + /* + * Activate (mark read-write) the (now sync) spare disk, + * which means we switch it's 'raid position' (->raid_disk) + * with the failed disk. (only the first 'conf->raid_disks' + * slots are used for 'real' disks and we must preserve this + * property) + */ + case DISKOP_SPARE_ACTIVE: + if (!conf->spare) { + MD_BUG(); + err = 1; + goto abort; + } + sdisk = conf->disks + spare_disk; + fdisk = conf->disks + failed_disk; + + spare_desc = &sb->disks[sdisk->number]; + failed_desc = &sb->disks[fdisk->number]; + + if (spare_desc != *d) { + MD_BUG(); + err = 1; + goto abort; + } + + if (spare_desc->raid_disk != sdisk->raid_disk) { + MD_BUG(); + err = 1; + goto abort; + } + + if (sdisk->raid_disk != spare_disk) { + MD_BUG(); + err = 1; + goto abort; + } + + if (failed_desc->raid_disk != fdisk->raid_disk) { + MD_BUG(); + err = 1; + goto abort; + } + + if (fdisk->raid_disk != failed_disk) { + MD_BUG(); + err = 1; + goto abort; + } + + /* + * do the switch finally + */ + xchg_values(*spare_desc, *failed_desc); + xchg_values(*fdisk, *sdisk); + + /* + * (careful, 'failed' and 'spare' are switched from now on) + * + * we want to preserve linear numbering and we want to + * give the proper raid_disk number to the now activated + * disk. (this means we switch back these values) + */ + + xchg_values(spare_desc->raid_disk, failed_desc->raid_disk); + xchg_values(sdisk->raid_disk, fdisk->raid_disk); + xchg_values(spare_desc->number, failed_desc->number); + xchg_values(sdisk->number, fdisk->number); + + *d = failed_desc; + + if (sdisk->dev == MKDEV(0,0)) + sdisk->used_slot = 0; + + /* + * this really activates the spare. + */ + fdisk->spare = 0; + fdisk->write_only = 0; + + /* + * if we activate a spare, we definitely replace a + * non-operational disk slot in the 'low' area of + * the disk array. + */ + conf->failed_disks--; + conf->working_disks++; + conf->spare = NULL; + + break; + + case DISKOP_HOT_REMOVE_DISK: + rdisk = conf->disks + removed_disk; + + if (rdisk->spare && (removed_disk < conf->raid_disks)) { + MD_BUG(); + err = 1; + goto abort; + } + rdisk->dev = MKDEV(0,0); + rdisk->used_slot = 0; + + break; + + case DISKOP_HOT_ADD_DISK: + adisk = conf->disks + added_disk; + added_desc = *d; + + if (added_disk != added_desc->number) { + MD_BUG(); + err = 1; + goto abort; + } + + adisk->number = added_desc->number; + adisk->raid_disk = added_desc->raid_disk; + adisk->dev = MKDEV(added_desc->major,added_desc->minor); + + adisk->operational = 0; + adisk->write_only = 0; + adisk->spare = 1; + adisk->used_slot = 1; + + + break; + + default: + MD_BUG(); + err = 1; + goto abort; + } +abort: + md_spin_unlock_irq(&conf->device_lock); + print_raid5_conf(conf); + return err; } -static struct md_personality raid5_personality= +static mdk_personality_t raid5_personality= { "raid5", - raid5_map, raid5_make_request, raid5_end_request, raid5_run, raid5_stop, raid5_status, - NULL, /* no ioctls */ 0, raid5_error, - /* raid5_hot_add_disk, */ NULL, - /* raid1_hot_remove_drive */ NULL, - raid5_mark_spare + raid5_diskop, + raid5_stop_resync, + raid5_restart_resync, + raid5_sync_request }; int raid5_init (void) { - return register_md_personality (RAID5, &raid5_personality); + int err; + + err = register_md_personality (RAID5, &raid5_personality); + if (err) + return err; + return 0; } #ifdef MODULE diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/block/xor.c linux/drivers/block/xor.c --- v2.3.99-pre7/linux/drivers/block/xor.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/block/xor.c Fri May 12 11:36:30 2000 @@ -0,0 +1,1894 @@ +/* + * xor.c : Multiple Devices driver for Linux + * + * Copyright (C) 1996, 1997, 1998, 1999 Ingo Molnar, Matti Aarnio, Jakub Jelinek + * + * + * optimized RAID-5 checksumming functions. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * You should have received a copy of the GNU General Public License + * (for example /usr/src/linux/COPYING); if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#define BH_TRACE 0 +#include +#include +#ifdef __sparc_v9__ +#include +#include +#include +#endif + +/* + * we use the 'XOR function template' to register multiple xor + * functions runtime. The kernel measures their speed upon bootup + * and decides which one to use. (compile-time registration is + * not enough as certain CPU features like MMX can only be detected + * runtime) + * + * this architecture makes it pretty easy to add new routines + * that are faster on certain CPUs, without killing other CPU's + * 'native' routine. Although the current routines are belived + * to be the physically fastest ones on all CPUs tested, but + * feel free to prove me wrong and add yet another routine =B-) + * --mingo + */ + +#define MAX_XOR_BLOCKS 5 + +#define XOR_ARGS (unsigned int count, struct buffer_head **bh_ptr) + +typedef void (*xor_block_t) XOR_ARGS; +xor_block_t xor_block = NULL; + +#ifndef __sparc_v9__ + +struct xor_block_template; + +struct xor_block_template { + char * name; + xor_block_t xor_block; + int speed; + struct xor_block_template * next; +}; + +struct xor_block_template * xor_functions = NULL; + +#define XORBLOCK_TEMPLATE(x) \ +static void xor_block_##x XOR_ARGS; \ +static struct xor_block_template t_xor_block_##x = \ + { #x, xor_block_##x, 0, NULL }; \ +static void xor_block_##x XOR_ARGS + +#ifdef __i386__ + +#ifdef CONFIG_X86_XMM +/* + * Cache avoiding checksumming functions utilizing KNI instructions + * Copyright (C) 1999 Zach Brown (with obvious credit due Ingo) + */ + +XORBLOCK_TEMPLATE(pIII_kni) +{ + char xmm_save[16*4]; + int cr0; + int lines = (bh_ptr[0]->b_size>>8); + + __asm__ __volatile__ ( + "movl %%cr0,%0 ;\n\t" + "clts ;\n\t" + "movups %%xmm0,(%1) ;\n\t" + "movups %%xmm1,0x10(%1) ;\n\t" + "movups %%xmm2,0x20(%1) ;\n\t" + "movups %%xmm3,0x30(%1) ;\n\t" + : "=r" (cr0) + : "r" (xmm_save) + : "memory" ); + +#define OFFS(x) "8*("#x"*2)" +#define PF0(x) \ + " prefetcht0 "OFFS(x)"(%1) ;\n" +#define LD(x,y) \ + " movaps "OFFS(x)"(%1), %%xmm"#y" ;\n" +#define ST(x,y) \ + " movaps %%xmm"#y", "OFFS(x)"(%1) ;\n" +#define PF1(x) \ + " prefetchnta "OFFS(x)"(%2) ;\n" +#define PF2(x) \ + " prefetchnta "OFFS(x)"(%3) ;\n" +#define PF3(x) \ + " prefetchnta "OFFS(x)"(%4) ;\n" +#define PF4(x) \ + " prefetchnta "OFFS(x)"(%5) ;\n" +#define PF5(x) \ + " prefetchnta "OFFS(x)"(%6) ;\n" +#define XO1(x,y) \ + " xorps "OFFS(x)"(%2), %%xmm"#y" ;\n" +#define XO2(x,y) \ + " xorps "OFFS(x)"(%3), %%xmm"#y" ;\n" +#define XO3(x,y) \ + " xorps "OFFS(x)"(%4), %%xmm"#y" ;\n" +#define XO4(x,y) \ + " xorps "OFFS(x)"(%5), %%xmm"#y" ;\n" +#define XO5(x,y) \ + " xorps "OFFS(x)"(%6), %%xmm"#y" ;\n" + + switch(count) { + case 2: + __asm__ __volatile__ ( +#undef BLOCK +#define BLOCK(i) \ + LD(i,0) \ + LD(i+1,1) \ + PF1(i) \ + PF1(i+2) \ + LD(i+2,2) \ + LD(i+3,3) \ + PF0(i+4) \ + PF0(i+6) \ + XO1(i,0) \ + XO1(i+1,1) \ + XO1(i+2,2) \ + XO1(i+3,3) \ + ST(i,0) \ + ST(i+1,1) \ + ST(i+2,2) \ + ST(i+3,3) \ + + + PF0(0) + PF0(2) + + " .align 32,0x90 ;\n" + " 1: ;\n" + + BLOCK(0) + BLOCK(4) + BLOCK(8) + BLOCK(12) + + " addl $256, %1 ;\n" + " addl $256, %2 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data) + : "memory" ); + break; + case 3: + __asm__ __volatile__ ( +#undef BLOCK +#define BLOCK(i) \ + PF1(i) \ + PF1(i+2) \ + LD(i,0) \ + LD(i+1,1) \ + LD(i+2,2) \ + LD(i+3,3) \ + PF2(i) \ + PF2(i+2) \ + PF0(i+4) \ + PF0(i+6) \ + XO1(i,0) \ + XO1(i+1,1) \ + XO1(i+2,2) \ + XO1(i+3,3) \ + XO2(i,0) \ + XO2(i+1,1) \ + XO2(i+2,2) \ + XO2(i+3,3) \ + ST(i,0) \ + ST(i+1,1) \ + ST(i+2,2) \ + ST(i+3,3) \ + + + PF0(0) + PF0(2) + + " .align 32,0x90 ;\n" + " 1: ;\n" + + BLOCK(0) + BLOCK(4) + BLOCK(8) + BLOCK(12) + + " addl $256, %1 ;\n" + " addl $256, %2 ;\n" + " addl $256, %3 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data), + "r" (bh_ptr[2]->b_data) + : "memory" ); + break; + case 4: + __asm__ __volatile__ ( +#undef BLOCK +#define BLOCK(i) \ + PF1(i) \ + PF1(i+2) \ + LD(i,0) \ + LD(i+1,1) \ + LD(i+2,2) \ + LD(i+3,3) \ + PF2(i) \ + PF2(i+2) \ + XO1(i,0) \ + XO1(i+1,1) \ + XO1(i+2,2) \ + XO1(i+3,3) \ + PF3(i) \ + PF3(i+2) \ + PF0(i+4) \ + PF0(i+6) \ + XO2(i,0) \ + XO2(i+1,1) \ + XO2(i+2,2) \ + XO2(i+3,3) \ + XO3(i,0) \ + XO3(i+1,1) \ + XO3(i+2,2) \ + XO3(i+3,3) \ + ST(i,0) \ + ST(i+1,1) \ + ST(i+2,2) \ + ST(i+3,3) \ + + + PF0(0) + PF0(2) + + " .align 32,0x90 ;\n" + " 1: ;\n" + + BLOCK(0) + BLOCK(4) + BLOCK(8) + BLOCK(12) + + " addl $256, %1 ;\n" + " addl $256, %2 ;\n" + " addl $256, %3 ;\n" + " addl $256, %4 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data), + "r" (bh_ptr[2]->b_data), + "r" (bh_ptr[3]->b_data) + : "memory" ); + break; + case 5: + __asm__ __volatile__ ( +#undef BLOCK +#define BLOCK(i) \ + PF1(i) \ + PF1(i+2) \ + LD(i,0) \ + LD(i+1,1) \ + LD(i+2,2) \ + LD(i+3,3) \ + PF2(i) \ + PF2(i+2) \ + XO1(i,0) \ + XO1(i+1,1) \ + XO1(i+2,2) \ + XO1(i+3,3) \ + PF3(i) \ + PF3(i+2) \ + XO2(i,0) \ + XO2(i+1,1) \ + XO2(i+2,2) \ + XO2(i+3,3) \ + PF4(i) \ + PF4(i+2) \ + PF0(i+4) \ + PF0(i+6) \ + XO3(i,0) \ + XO3(i+1,1) \ + XO3(i+2,2) \ + XO3(i+3,3) \ + XO4(i,0) \ + XO4(i+1,1) \ + XO4(i+2,2) \ + XO4(i+3,3) \ + ST(i,0) \ + ST(i+1,1) \ + ST(i+2,2) \ + ST(i+3,3) \ + + + PF0(0) + PF0(2) + + " .align 32,0x90 ;\n" + " 1: ;\n" + + BLOCK(0) + BLOCK(4) + BLOCK(8) + BLOCK(12) + + " addl $256, %1 ;\n" + " addl $256, %2 ;\n" + " addl $256, %3 ;\n" + " addl $256, %4 ;\n" + " addl $256, %5 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data), + "r" (bh_ptr[2]->b_data), + "r" (bh_ptr[3]->b_data), + "r" (bh_ptr[4]->b_data) + : "memory"); + break; + } + + __asm__ __volatile__ ( + "sfence ;\n\t" + "movups (%1),%%xmm0 ;\n\t" + "movups 0x10(%1),%%xmm1 ;\n\t" + "movups 0x20(%1),%%xmm2 ;\n\t" + "movups 0x30(%1),%%xmm3 ;\n\t" + "movl %0,%%cr0 ;\n\t" + : + : "r" (cr0), "r" (xmm_save) + : "memory" ); +} + +#undef OFFS +#undef LD +#undef ST +#undef PF0 +#undef PF1 +#undef PF2 +#undef PF3 +#undef PF4 +#undef PF5 +#undef XO1 +#undef XO2 +#undef XO3 +#undef XO4 +#undef XO5 +#undef BLOCK + +#endif /* CONFIG_X86_XMM */ + +/* + * high-speed RAID5 checksumming functions utilizing MMX instructions + * Copyright (C) 1998 Ingo Molnar + */ +XORBLOCK_TEMPLATE(pII_mmx) +{ + char fpu_save[108]; + int lines = (bh_ptr[0]->b_size>>7); + + if (!(current->flags & PF_USEDFPU)) + __asm__ __volatile__ ( " clts;\n"); + + __asm__ __volatile__ ( " fsave %0; fwait\n"::"m"(fpu_save[0]) ); + +#define LD(x,y) \ + " movq 8*("#x")(%1), %%mm"#y" ;\n" +#define ST(x,y) \ + " movq %%mm"#y", 8*("#x")(%1) ;\n" +#define XO1(x,y) \ + " pxor 8*("#x")(%2), %%mm"#y" ;\n" +#define XO2(x,y) \ + " pxor 8*("#x")(%3), %%mm"#y" ;\n" +#define XO3(x,y) \ + " pxor 8*("#x")(%4), %%mm"#y" ;\n" +#define XO4(x,y) \ + " pxor 8*("#x")(%5), %%mm"#y" ;\n" + + switch(count) { + case 2: + __asm__ __volatile__ ( +#undef BLOCK +#define BLOCK(i) \ + LD(i,0) \ + LD(i+1,1) \ + LD(i+2,2) \ + LD(i+3,3) \ + XO1(i,0) \ + ST(i,0) \ + XO1(i+1,1) \ + ST(i+1,1) \ + XO1(i+2,2) \ + ST(i+2,2) \ + XO1(i+3,3) \ + ST(i+3,3) + + " .align 32,0x90 ;\n" + " 1: ;\n" + + BLOCK(0) + BLOCK(4) + BLOCK(8) + BLOCK(12) + + " addl $128, %1 ;\n" + " addl $128, %2 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data) + : "memory"); + break; + case 3: + __asm__ __volatile__ ( +#undef BLOCK +#define BLOCK(i) \ + LD(i,0) \ + LD(i+1,1) \ + LD(i+2,2) \ + LD(i+3,3) \ + XO1(i,0) \ + XO1(i+1,1) \ + XO1(i+2,2) \ + XO1(i+3,3) \ + XO2(i,0) \ + ST(i,0) \ + XO2(i+1,1) \ + ST(i+1,1) \ + XO2(i+2,2) \ + ST(i+2,2) \ + XO2(i+3,3) \ + ST(i+3,3) + + " .align 32,0x90 ;\n" + " 1: ;\n" + + BLOCK(0) + BLOCK(4) + BLOCK(8) + BLOCK(12) + + " addl $128, %1 ;\n" + " addl $128, %2 ;\n" + " addl $128, %3 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data), + "r" (bh_ptr[2]->b_data) + : "memory"); + break; + case 4: + __asm__ __volatile__ ( +#undef BLOCK +#define BLOCK(i) \ + LD(i,0) \ + LD(i+1,1) \ + LD(i+2,2) \ + LD(i+3,3) \ + XO1(i,0) \ + XO1(i+1,1) \ + XO1(i+2,2) \ + XO1(i+3,3) \ + XO2(i,0) \ + XO2(i+1,1) \ + XO2(i+2,2) \ + XO2(i+3,3) \ + XO3(i,0) \ + ST(i,0) \ + XO3(i+1,1) \ + ST(i+1,1) \ + XO3(i+2,2) \ + ST(i+2,2) \ + XO3(i+3,3) \ + ST(i+3,3) + + " .align 32,0x90 ;\n" + " 1: ;\n" + + BLOCK(0) + BLOCK(4) + BLOCK(8) + BLOCK(12) + + " addl $128, %1 ;\n" + " addl $128, %2 ;\n" + " addl $128, %3 ;\n" + " addl $128, %4 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data), + "r" (bh_ptr[2]->b_data), + "r" (bh_ptr[3]->b_data) + : "memory"); + break; + case 5: + __asm__ __volatile__ ( +#undef BLOCK +#define BLOCK(i) \ + LD(i,0) \ + LD(i+1,1) \ + LD(i+2,2) \ + LD(i+3,3) \ + XO1(i,0) \ + XO1(i+1,1) \ + XO1(i+2,2) \ + XO1(i+3,3) \ + XO2(i,0) \ + XO2(i+1,1) \ + XO2(i+2,2) \ + XO2(i+3,3) \ + XO3(i,0) \ + XO3(i+1,1) \ + XO3(i+2,2) \ + XO3(i+3,3) \ + XO4(i,0) \ + ST(i,0) \ + XO4(i+1,1) \ + ST(i+1,1) \ + XO4(i+2,2) \ + ST(i+2,2) \ + XO4(i+3,3) \ + ST(i+3,3) + + " .align 32,0x90 ;\n" + " 1: ;\n" + + BLOCK(0) + BLOCK(4) + BLOCK(8) + BLOCK(12) + + " addl $128, %1 ;\n" + " addl $128, %2 ;\n" + " addl $128, %3 ;\n" + " addl $128, %4 ;\n" + " addl $128, %5 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + : + : "g" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data), + "r" (bh_ptr[2]->b_data), + "r" (bh_ptr[3]->b_data), + "r" (bh_ptr[4]->b_data) + : "memory"); + break; + } + + __asm__ __volatile__ ( " frstor %0;\n"::"m"(fpu_save[0]) ); + + if (!(current->flags & PF_USEDFPU)) + stts(); +} + +#undef LD +#undef XO1 +#undef XO2 +#undef XO3 +#undef XO4 +#undef ST +#undef BLOCK + +XORBLOCK_TEMPLATE(p5_mmx) +{ + char fpu_save[108]; + int lines = (bh_ptr[0]->b_size>>6); + + if (!(current->flags & PF_USEDFPU)) + __asm__ __volatile__ ( " clts;\n"); + + __asm__ __volatile__ ( " fsave %0; fwait\n"::"m"(fpu_save[0]) ); + + switch(count) { + case 2: + __asm__ __volatile__ ( + + " .align 32,0x90 ;\n" + " 1: ;\n" + " movq (%1), %%mm0 ;\n" + " movq 8(%1), %%mm1 ;\n" + " pxor (%2), %%mm0 ;\n" + " movq 16(%1), %%mm2 ;\n" + " movq %%mm0, (%1) ;\n" + " pxor 8(%2), %%mm1 ;\n" + " movq 24(%1), %%mm3 ;\n" + " movq %%mm1, 8(%1) ;\n" + " pxor 16(%2), %%mm2 ;\n" + " movq 32(%1), %%mm4 ;\n" + " movq %%mm2, 16(%1) ;\n" + " pxor 24(%2), %%mm3 ;\n" + " movq 40(%1), %%mm5 ;\n" + " movq %%mm3, 24(%1) ;\n" + " pxor 32(%2), %%mm4 ;\n" + " movq 48(%1), %%mm6 ;\n" + " movq %%mm4, 32(%1) ;\n" + " pxor 40(%2), %%mm5 ;\n" + " movq 56(%1), %%mm7 ;\n" + " movq %%mm5, 40(%1) ;\n" + " pxor 48(%2), %%mm6 ;\n" + " pxor 56(%2), %%mm7 ;\n" + " movq %%mm6, 48(%1) ;\n" + " movq %%mm7, 56(%1) ;\n" + + " addl $64, %1 ;\n" + " addl $64, %2 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data) + : "memory" ); + break; + case 3: + __asm__ __volatile__ ( + + " .align 32,0x90 ;\n" + " 1: ;\n" + " movq (%1), %%mm0 ;\n" + " movq 8(%1), %%mm1 ;\n" + " pxor (%2), %%mm0 ;\n" + " movq 16(%1), %%mm2 ;\n" + " pxor 8(%2), %%mm1 ;\n" + " pxor (%3), %%mm0 ;\n" + " pxor 16(%2), %%mm2 ;\n" + " movq %%mm0, (%1) ;\n" + " pxor 8(%3), %%mm1 ;\n" + " pxor 16(%3), %%mm2 ;\n" + " movq 24(%1), %%mm3 ;\n" + " movq %%mm1, 8(%1) ;\n" + " movq 32(%1), %%mm4 ;\n" + " movq 40(%1), %%mm5 ;\n" + " pxor 24(%2), %%mm3 ;\n" + " movq %%mm2, 16(%1) ;\n" + " pxor 32(%2), %%mm4 ;\n" + " pxor 24(%3), %%mm3 ;\n" + " pxor 40(%2), %%mm5 ;\n" + " movq %%mm3, 24(%1) ;\n" + " pxor 32(%3), %%mm4 ;\n" + " pxor 40(%3), %%mm5 ;\n" + " movq 48(%1), %%mm6 ;\n" + " movq %%mm4, 32(%1) ;\n" + " movq 56(%1), %%mm7 ;\n" + " pxor 48(%2), %%mm6 ;\n" + " movq %%mm5, 40(%1) ;\n" + " pxor 56(%2), %%mm7 ;\n" + " pxor 48(%3), %%mm6 ;\n" + " pxor 56(%3), %%mm7 ;\n" + " movq %%mm6, 48(%1) ;\n" + " movq %%mm7, 56(%1) ;\n" + + " addl $64, %1 ;\n" + " addl $64, %2 ;\n" + " addl $64, %3 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data), + "r" (bh_ptr[2]->b_data) + : "memory" ); + break; + case 4: + __asm__ __volatile__ ( + + " .align 32,0x90 ;\n" + " 1: ;\n" + " movq (%1), %%mm0 ;\n" + " movq 8(%1), %%mm1 ;\n" + " pxor (%2), %%mm0 ;\n" + " movq 16(%1), %%mm2 ;\n" + " pxor 8(%2), %%mm1 ;\n" + " pxor (%3), %%mm0 ;\n" + " pxor 16(%2), %%mm2 ;\n" + " pxor 8(%3), %%mm1 ;\n" + " pxor (%4), %%mm0 ;\n" + " movq 24(%1), %%mm3 ;\n" + " pxor 16(%3), %%mm2 ;\n" + " pxor 8(%4), %%mm1 ;\n" + " movq %%mm0, (%1) ;\n" + " movq 32(%1), %%mm4 ;\n" + " pxor 24(%2), %%mm3 ;\n" + " pxor 16(%4), %%mm2 ;\n" + " movq %%mm1, 8(%1) ;\n" + " movq 40(%1), %%mm5 ;\n" + " pxor 32(%2), %%mm4 ;\n" + " pxor 24(%3), %%mm3 ;\n" + " movq %%mm2, 16(%1) ;\n" + " pxor 40(%2), %%mm5 ;\n" + " pxor 32(%3), %%mm4 ;\n" + " pxor 24(%4), %%mm3 ;\n" + " movq %%mm3, 24(%1) ;\n" + " movq 56(%1), %%mm7 ;\n" + " movq 48(%1), %%mm6 ;\n" + " pxor 40(%3), %%mm5 ;\n" + " pxor 32(%4), %%mm4 ;\n" + " pxor 48(%2), %%mm6 ;\n" + " movq %%mm4, 32(%1) ;\n" + " pxor 56(%2), %%mm7 ;\n" + " pxor 40(%4), %%mm5 ;\n" + " pxor 48(%3), %%mm6 ;\n" + " pxor 56(%3), %%mm7 ;\n" + " movq %%mm5, 40(%1) ;\n" + " pxor 48(%4), %%mm6 ;\n" + " pxor 56(%4), %%mm7 ;\n" + " movq %%mm6, 48(%1) ;\n" + " movq %%mm7, 56(%1) ;\n" + + " addl $64, %1 ;\n" + " addl $64, %2 ;\n" + " addl $64, %3 ;\n" + " addl $64, %4 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data), + "r" (bh_ptr[2]->b_data), + "r" (bh_ptr[3]->b_data) + : "memory" ); + break; + case 5: + __asm__ __volatile__ ( + + " .align 32,0x90 ;\n" + " 1: ;\n" + " movq (%1), %%mm0 ;\n" + " movq 8(%1), %%mm1 ;\n" + " pxor (%2), %%mm0 ;\n" + " pxor 8(%2), %%mm1 ;\n" + " movq 16(%1), %%mm2 ;\n" + " pxor (%3), %%mm0 ;\n" + " pxor 8(%3), %%mm1 ;\n" + " pxor 16(%2), %%mm2 ;\n" + " pxor (%4), %%mm0 ;\n" + " pxor 8(%4), %%mm1 ;\n" + " pxor 16(%3), %%mm2 ;\n" + " movq 24(%1), %%mm3 ;\n" + " pxor (%5), %%mm0 ;\n" + " pxor 8(%5), %%mm1 ;\n" + " movq %%mm0, (%1) ;\n" + " pxor 16(%4), %%mm2 ;\n" + " pxor 24(%2), %%mm3 ;\n" + " movq %%mm1, 8(%1) ;\n" + " pxor 16(%5), %%mm2 ;\n" + " pxor 24(%3), %%mm3 ;\n" + " movq 32(%1), %%mm4 ;\n" + " movq %%mm2, 16(%1) ;\n" + " pxor 24(%4), %%mm3 ;\n" + " pxor 32(%2), %%mm4 ;\n" + " movq 40(%1), %%mm5 ;\n" + " pxor 24(%5), %%mm3 ;\n" + " pxor 32(%3), %%mm4 ;\n" + " pxor 40(%2), %%mm5 ;\n" + " movq %%mm3, 24(%1) ;\n" + " pxor 32(%4), %%mm4 ;\n" + " pxor 40(%3), %%mm5 ;\n" + " movq 48(%1), %%mm6 ;\n" + " movq 56(%1), %%mm7 ;\n" + " pxor 32(%5), %%mm4 ;\n" + " pxor 40(%4), %%mm5 ;\n" + " pxor 48(%2), %%mm6 ;\n" + " pxor 56(%2), %%mm7 ;\n" + " movq %%mm4, 32(%1) ;\n" + " pxor 48(%3), %%mm6 ;\n" + " pxor 56(%3), %%mm7 ;\n" + " pxor 40(%5), %%mm5 ;\n" + " pxor 48(%4), %%mm6 ;\n" + " pxor 56(%4), %%mm7 ;\n" + " movq %%mm5, 40(%1) ;\n" + " pxor 48(%5), %%mm6 ;\n" + " pxor 56(%5), %%mm7 ;\n" + " movq %%mm6, 48(%1) ;\n" + " movq %%mm7, 56(%1) ;\n" + + " addl $64, %1 ;\n" + " addl $64, %2 ;\n" + " addl $64, %3 ;\n" + " addl $64, %4 ;\n" + " addl $64, %5 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + + : + : "g" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data), + "r" (bh_ptr[2]->b_data), + "r" (bh_ptr[3]->b_data), + "r" (bh_ptr[4]->b_data) + : "memory" ); + break; + } + + __asm__ __volatile__ ( " frstor %0;\n"::"m"(fpu_save[0]) ); + + if (!(current->flags & PF_USEDFPU)) + stts(); +} +#endif /* __i386__ */ +#endif /* !__sparc_v9__ */ + +#ifdef __sparc_v9__ +/* + * High speed xor_block operation for RAID4/5 utilizing the + * UltraSparc Visual Instruction Set. + * + * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz) + * + * Requirements: + * !(((long)dest | (long)sourceN) & (64 - 1)) && + * !(len & 127) && len >= 256 + * + * It is done in pure assembly, as otherwise gcc makes it + * a non-leaf function, which is not what we want. + * Also, we don't measure the speeds as on other architectures, + * as the measuring routine does not take into account cold caches + * and the fact that xor_block_VIS bypasses the caches. + * xor_block_32regs might be 5% faster for count 2 if caches are hot + * and things just right (for count 3 VIS is about as fast as 32regs for + * hot caches and for count 4 and 5 VIS is faster by good margin always), + * but I think it is better not to pollute the caches. + * Actually, if I'd just fight for speed for hot caches, I could + * write a hybrid VIS/integer routine, which would do always two + * 64B blocks in VIS and two in IEUs, but I really care more about + * caches. + */ +extern void *VISenter(void); +extern void xor_block_VIS XOR_ARGS; + +void __xor_block_VIS(void) +{ +__asm__ (" + .globl xor_block_VIS +xor_block_VIS: + ldx [%%o1 + 0], %%o4 + ldx [%%o1 + 8], %%o3 + ldx [%%o4 + %1], %%g5 + ldx [%%o4 + %0], %%o4 + ldx [%%o3 + %0], %%o3 + rd %%fprs, %%o5 + andcc %%o5, %2, %%g0 + be,pt %%icc, 297f + sethi %%hi(%5), %%g1 + jmpl %%g1 + %%lo(%5), %%g7 + add %%g7, 8, %%g7 +297: wr %%g0, %4, %%fprs + membar #LoadStore|#StoreLoad|#StoreStore + sub %%g5, 64, %%g5 + ldda [%%o4] %3, %%f0 + ldda [%%o3] %3, %%f16 + cmp %%o0, 4 + bgeu,pt %%xcc, 10f + cmp %%o0, 3 + be,pn %%xcc, 13f + mov -64, %%g1 + sub %%g5, 64, %%g5 + rd %%asi, %%g1 + wr %%g0, %3, %%asi + +2: ldda [%%o4 + 64] %%asi, %%f32 + fxor %%f0, %%f16, %%f16 + fxor %%f2, %%f18, %%f18 + fxor %%f4, %%f20, %%f20 + fxor %%f6, %%f22, %%f22 + fxor %%f8, %%f24, %%f24 + fxor %%f10, %%f26, %%f26 + fxor %%f12, %%f28, %%f28 + fxor %%f14, %%f30, %%f30 + stda %%f16, [%%o4] %3 + ldda [%%o3 + 64] %%asi, %%f48 + ldda [%%o4 + 128] %%asi, %%f0 + fxor %%f32, %%f48, %%f48 + fxor %%f34, %%f50, %%f50 + add %%o4, 128, %%o4 + fxor %%f36, %%f52, %%f52 + add %%o3, 128, %%o3 + fxor %%f38, %%f54, %%f54 + subcc %%g5, 128, %%g5 + fxor %%f40, %%f56, %%f56 + fxor %%f42, %%f58, %%f58 + fxor %%f44, %%f60, %%f60 + fxor %%f46, %%f62, %%f62 + stda %%f48, [%%o4 - 64] %%asi + bne,pt %%xcc, 2b + ldda [%%o3] %3, %%f16 + + ldda [%%o4 + 64] %%asi, %%f32 + fxor %%f0, %%f16, %%f16 + fxor %%f2, %%f18, %%f18 + fxor %%f4, %%f20, %%f20 + fxor %%f6, %%f22, %%f22 + fxor %%f8, %%f24, %%f24 + fxor %%f10, %%f26, %%f26 + fxor %%f12, %%f28, %%f28 + fxor %%f14, %%f30, %%f30 + stda %%f16, [%%o4] %3 + ldda [%%o3 + 64] %%asi, %%f48 + membar #Sync + fxor %%f32, %%f48, %%f48 + fxor %%f34, %%f50, %%f50 + fxor %%f36, %%f52, %%f52 + fxor %%f38, %%f54, %%f54 + fxor %%f40, %%f56, %%f56 + fxor %%f42, %%f58, %%f58 + fxor %%f44, %%f60, %%f60 + fxor %%f46, %%f62, %%f62 + stda %%f48, [%%o4 + 64] %%asi + membar #Sync|#StoreStore|#StoreLoad + wr %%g0, 0, %%fprs + retl + wr %%g1, %%g0, %%asi + +13: ldx [%%o1 + 16], %%o2 + ldx [%%o2 + %0], %%o2 + +3: ldda [%%o2] %3, %%f32 + fxor %%f0, %%f16, %%f48 + fxor %%f2, %%f18, %%f50 + add %%o4, 64, %%o4 + fxor %%f4, %%f20, %%f52 + fxor %%f6, %%f22, %%f54 + add %%o3, 64, %%o3 + fxor %%f8, %%f24, %%f56 + fxor %%f10, %%f26, %%f58 + fxor %%f12, %%f28, %%f60 + fxor %%f14, %%f30, %%f62 + ldda [%%o4] %3, %%f0 + fxor %%f48, %%f32, %%f48 + fxor %%f50, %%f34, %%f50 + fxor %%f52, %%f36, %%f52 + fxor %%f54, %%f38, %%f54 + add %%o2, 64, %%o2 + fxor %%f56, %%f40, %%f56 + fxor %%f58, %%f42, %%f58 + subcc %%g5, 64, %%g5 + fxor %%f60, %%f44, %%f60 + fxor %%f62, %%f46, %%f62 + stda %%f48, [%%o4 + %%g1] %3 + bne,pt %%xcc, 3b + ldda [%%o3] %3, %%f16 + + ldda [%%o2] %3, %%f32 + fxor %%f0, %%f16, %%f48 + fxor %%f2, %%f18, %%f50 + fxor %%f4, %%f20, %%f52 + fxor %%f6, %%f22, %%f54 + fxor %%f8, %%f24, %%f56 + fxor %%f10, %%f26, %%f58 + fxor %%f12, %%f28, %%f60 + fxor %%f14, %%f30, %%f62 + membar #Sync + fxor %%f48, %%f32, %%f48 + fxor %%f50, %%f34, %%f50 + fxor %%f52, %%f36, %%f52 + fxor %%f54, %%f38, %%f54 + fxor %%f56, %%f40, %%f56 + fxor %%f58, %%f42, %%f58 + fxor %%f60, %%f44, %%f60 + fxor %%f62, %%f46, %%f62 + stda %%f48, [%%o4] %3 + membar #Sync|#StoreStore|#StoreLoad + retl + wr %%g0, 0, %%fprs + +10: cmp %%o0, 5 + be,pt %%xcc, 15f + mov -64, %%g1 + +14: ldx [%%o1 + 16], %%o2 + ldx [%%o1 + 24], %%o0 + ldx [%%o2 + %0], %%o2 + ldx [%%o0 + %0], %%o0 + +4: ldda [%%o2] %3, %%f32 + fxor %%f0, %%f16, %%f16 + fxor %%f2, %%f18, %%f18 + add %%o4, 64, %%o4 + fxor %%f4, %%f20, %%f20 + fxor %%f6, %%f22, %%f22 + add %%o3, 64, %%o3 + fxor %%f8, %%f24, %%f24 + fxor %%f10, %%f26, %%f26 + fxor %%f12, %%f28, %%f28 + fxor %%f14, %%f30, %%f30 + ldda [%%o0] %3, %%f48 + fxor %%f16, %%f32, %%f32 + fxor %%f18, %%f34, %%f34 + fxor %%f20, %%f36, %%f36 + fxor %%f22, %%f38, %%f38 + add %%o2, 64, %%o2 + fxor %%f24, %%f40, %%f40 + fxor %%f26, %%f42, %%f42 + fxor %%f28, %%f44, %%f44 + fxor %%f30, %%f46, %%f46 + ldda [%%o4] %3, %%f0 + fxor %%f32, %%f48, %%f48 + fxor %%f34, %%f50, %%f50 + fxor %%f36, %%f52, %%f52 + add %%o0, 64, %%o0 + fxor %%f38, %%f54, %%f54 + fxor %%f40, %%f56, %%f56 + fxor %%f42, %%f58, %%f58 + subcc %%g5, 64, %%g5 + fxor %%f44, %%f60, %%f60 + fxor %%f46, %%f62, %%f62 + stda %%f48, [%%o4 + %%g1] %3 + bne,pt %%xcc, 4b + ldda [%%o3] %3, %%f16 + + ldda [%%o2] %3, %%f32 + fxor %%f0, %%f16, %%f16 + fxor %%f2, %%f18, %%f18 + fxor %%f4, %%f20, %%f20 + fxor %%f6, %%f22, %%f22 + fxor %%f8, %%f24, %%f24 + fxor %%f10, %%f26, %%f26 + fxor %%f12, %%f28, %%f28 + fxor %%f14, %%f30, %%f30 + ldda [%%o0] %3, %%f48 + fxor %%f16, %%f32, %%f32 + fxor %%f18, %%f34, %%f34 + fxor %%f20, %%f36, %%f36 + fxor %%f22, %%f38, %%f38 + fxor %%f24, %%f40, %%f40 + fxor %%f26, %%f42, %%f42 + fxor %%f28, %%f44, %%f44 + fxor %%f30, %%f46, %%f46 + membar #Sync + fxor %%f32, %%f48, %%f48 + fxor %%f34, %%f50, %%f50 + fxor %%f36, %%f52, %%f52 + fxor %%f38, %%f54, %%f54 + fxor %%f40, %%f56, %%f56 + fxor %%f42, %%f58, %%f58 + fxor %%f44, %%f60, %%f60 + fxor %%f46, %%f62, %%f62 + stda %%f48, [%%o4] %3 + membar #Sync|#StoreStore|#StoreLoad + retl + wr %%g0, 0, %%fprs + +15: ldx [%%o1 + 16], %%o2 + ldx [%%o1 + 24], %%o0 + ldx [%%o1 + 32], %%o1 + ldx [%%o2 + %0], %%o2 + ldx [%%o0 + %0], %%o0 + ldx [%%o1 + %0], %%o1 + +5: ldda [%%o2] %3, %%f32 + fxor %%f0, %%f16, %%f48 + fxor %%f2, %%f18, %%f50 + add %%o4, 64, %%o4 + fxor %%f4, %%f20, %%f52 + fxor %%f6, %%f22, %%f54 + add %%o3, 64, %%o3 + fxor %%f8, %%f24, %%f56 + fxor %%f10, %%f26, %%f58 + fxor %%f12, %%f28, %%f60 + fxor %%f14, %%f30, %%f62 + ldda [%%o0] %3, %%f16 + fxor %%f48, %%f32, %%f48 + fxor %%f50, %%f34, %%f50 + fxor %%f52, %%f36, %%f52 + fxor %%f54, %%f38, %%f54 + add %%o2, 64, %%o2 + fxor %%f56, %%f40, %%f56 + fxor %%f58, %%f42, %%f58 + fxor %%f60, %%f44, %%f60 + fxor %%f62, %%f46, %%f62 + ldda [%%o1] %3, %%f32 + fxor %%f48, %%f16, %%f48 + fxor %%f50, %%f18, %%f50 + add %%o0, 64, %%o0 + fxor %%f52, %%f20, %%f52 + fxor %%f54, %%f22, %%f54 + add %%o1, 64, %%o1 + fxor %%f56, %%f24, %%f56 + fxor %%f58, %%f26, %%f58 + fxor %%f60, %%f28, %%f60 + fxor %%f62, %%f30, %%f62 + ldda [%%o4] %3, %%f0 + fxor %%f48, %%f32, %%f48 + fxor %%f50, %%f34, %%f50 + fxor %%f52, %%f36, %%f52 + fxor %%f54, %%f38, %%f54 + fxor %%f56, %%f40, %%f56 + fxor %%f58, %%f42, %%f58 + subcc %%g5, 64, %%g5 + fxor %%f60, %%f44, %%f60 + fxor %%f62, %%f46, %%f62 + stda %%f48, [%%o4 + %%g1] %3 + bne,pt %%xcc, 5b + ldda [%%o3] %3, %%f16 + + ldda [%%o2] %3, %%f32 + fxor %%f0, %%f16, %%f48 + fxor %%f2, %%f18, %%f50 + fxor %%f4, %%f20, %%f52 + fxor %%f6, %%f22, %%f54 + fxor %%f8, %%f24, %%f56 + fxor %%f10, %%f26, %%f58 + fxor %%f12, %%f28, %%f60 + fxor %%f14, %%f30, %%f62 + ldda [%%o0] %3, %%f16 + fxor %%f48, %%f32, %%f48 + fxor %%f50, %%f34, %%f50 + fxor %%f52, %%f36, %%f52 + fxor %%f54, %%f38, %%f54 + fxor %%f56, %%f40, %%f56 + fxor %%f58, %%f42, %%f58 + fxor %%f60, %%f44, %%f60 + fxor %%f62, %%f46, %%f62 + ldda [%%o1] %3, %%f32 + fxor %%f48, %%f16, %%f48 + fxor %%f50, %%f18, %%f50 + fxor %%f52, %%f20, %%f52 + fxor %%f54, %%f22, %%f54 + fxor %%f56, %%f24, %%f56 + fxor %%f58, %%f26, %%f58 + fxor %%f60, %%f28, %%f60 + fxor %%f62, %%f30, %%f62 + membar #Sync + fxor %%f48, %%f32, %%f48 + fxor %%f50, %%f34, %%f50 + fxor %%f52, %%f36, %%f52 + fxor %%f54, %%f38, %%f54 + fxor %%f56, %%f40, %%f56 + fxor %%f58, %%f42, %%f58 + fxor %%f60, %%f44, %%f60 + fxor %%f62, %%f46, %%f62 + stda %%f48, [%%o4] %3 + membar #Sync|#StoreStore|#StoreLoad + retl + wr %%g0, 0, %%fprs + " : : + "i" (&((struct buffer_head *)0)->b_data), + "i" (&((struct buffer_head *)0)->b_data), + "i" (FPRS_FEF|FPRS_DU), "i" (ASI_BLK_P), + "i" (FPRS_FEF), "i" (VISenter)); +} +#endif /* __sparc_v9__ */ + +#if defined(__sparc__) && !defined(__sparc_v9__) +/* + * High speed xor_block operation for RAID4/5 utilizing the + * ldd/std SPARC instructions. + * + * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz) + * + */ + +XORBLOCK_TEMPLATE(SPARC) +{ + int size = bh_ptr[0]->b_size; + int lines = size / (sizeof (long)) / 8, i; + long *destp = (long *) bh_ptr[0]->b_data; + long *source1 = (long *) bh_ptr[1]->b_data; + long *source2, *source3, *source4; + + switch (count) { + case 2: + for (i = lines; i > 0; i--) { + __asm__ __volatile__(" + ldd [%0 + 0x00], %%g2 + ldd [%0 + 0x08], %%g4 + ldd [%0 + 0x10], %%o0 + ldd [%0 + 0x18], %%o2 + ldd [%1 + 0x00], %%o4 + ldd [%1 + 0x08], %%l0 + ldd [%1 + 0x10], %%l2 + ldd [%1 + 0x18], %%l4 + xor %%g2, %%o4, %%g2 + xor %%g3, %%o5, %%g3 + xor %%g4, %%l0, %%g4 + xor %%g5, %%l1, %%g5 + xor %%o0, %%l2, %%o0 + xor %%o1, %%l3, %%o1 + xor %%o2, %%l4, %%o2 + xor %%o3, %%l5, %%o3 + std %%g2, [%0 + 0x00] + std %%g4, [%0 + 0x08] + std %%o0, [%0 + 0x10] + std %%o2, [%0 + 0x18] + " : : "r" (destp), "r" (source1) : "g2", "g3", "g4", "g5", "o0", + "o1", "o2", "o3", "o4", "o5", "l0", "l1", "l2", "l3", "l4", "l5"); + destp += 8; + source1 += 8; + } + break; + case 3: + source2 = (long *) bh_ptr[2]->b_data; + for (i = lines; i > 0; i--) { + __asm__ __volatile__(" + ldd [%0 + 0x00], %%g2 + ldd [%0 + 0x08], %%g4 + ldd [%0 + 0x10], %%o0 + ldd [%0 + 0x18], %%o2 + ldd [%1 + 0x00], %%o4 + ldd [%1 + 0x08], %%l0 + ldd [%1 + 0x10], %%l2 + ldd [%1 + 0x18], %%l4 + xor %%g2, %%o4, %%g2 + xor %%g3, %%o5, %%g3 + ldd [%2 + 0x00], %%o4 + xor %%g4, %%l0, %%g4 + xor %%g5, %%l1, %%g5 + ldd [%2 + 0x08], %%l0 + xor %%o0, %%l2, %%o0 + xor %%o1, %%l3, %%o1 + ldd [%2 + 0x10], %%l2 + xor %%o2, %%l4, %%o2 + xor %%o3, %%l5, %%o3 + ldd [%2 + 0x18], %%l4 + xor %%g2, %%o4, %%g2 + xor %%g3, %%o5, %%g3 + xor %%g4, %%l0, %%g4 + xor %%g5, %%l1, %%g5 + xor %%o0, %%l2, %%o0 + xor %%o1, %%l3, %%o1 + xor %%o2, %%l4, %%o2 + xor %%o3, %%l5, %%o3 + std %%g2, [%0 + 0x00] + std %%g4, [%0 + 0x08] + std %%o0, [%0 + 0x10] + std %%o2, [%0 + 0x18] + " : : "r" (destp), "r" (source1), "r" (source2) + : "g2", "g3", "g4", "g5", "o0", "o1", "o2", "o3", "o4", "o5", + "l0", "l1", "l2", "l3", "l4", "l5"); + destp += 8; + source1 += 8; + source2 += 8; + } + break; + case 4: + source2 = (long *) bh_ptr[2]->b_data; + source3 = (long *) bh_ptr[3]->b_data; + for (i = lines; i > 0; i--) { + __asm__ __volatile__(" + ldd [%0 + 0x00], %%g2 + ldd [%0 + 0x08], %%g4 + ldd [%0 + 0x10], %%o0 + ldd [%0 + 0x18], %%o2 + ldd [%1 + 0x00], %%o4 + ldd [%1 + 0x08], %%l0 + ldd [%1 + 0x10], %%l2 + ldd [%1 + 0x18], %%l4 + xor %%g2, %%o4, %%g2 + xor %%g3, %%o5, %%g3 + ldd [%2 + 0x00], %%o4 + xor %%g4, %%l0, %%g4 + xor %%g5, %%l1, %%g5 + ldd [%2 + 0x08], %%l0 + xor %%o0, %%l2, %%o0 + xor %%o1, %%l3, %%o1 + ldd [%2 + 0x10], %%l2 + xor %%o2, %%l4, %%o2 + xor %%o3, %%l5, %%o3 + ldd [%2 + 0x18], %%l4 + xor %%g2, %%o4, %%g2 + xor %%g3, %%o5, %%g3 + ldd [%3 + 0x00], %%o4 + xor %%g4, %%l0, %%g4 + xor %%g5, %%l1, %%g5 + ldd [%3 + 0x08], %%l0 + xor %%o0, %%l2, %%o0 + xor %%o1, %%l3, %%o1 + ldd [%3 + 0x10], %%l2 + xor %%o2, %%l4, %%o2 + xor %%o3, %%l5, %%o3 + ldd [%3 + 0x18], %%l4 + xor %%g2, %%o4, %%g2 + xor %%g3, %%o5, %%g3 + xor %%g4, %%l0, %%g4 + xor %%g5, %%l1, %%g5 + xor %%o0, %%l2, %%o0 + xor %%o1, %%l3, %%o1 + xor %%o2, %%l4, %%o2 + xor %%o3, %%l5, %%o3 + std %%g2, [%0 + 0x00] + std %%g4, [%0 + 0x08] + std %%o0, [%0 + 0x10] + std %%o2, [%0 + 0x18] + " : : "r" (destp), "r" (source1), "r" (source2), "r" (source3) + : "g2", "g3", "g4", "g5", "o0", "o1", "o2", "o3", "o4", "o5", + "l0", "l1", "l2", "l3", "l4", "l5"); + destp += 8; + source1 += 8; + source2 += 8; + source3 += 8; + } + break; + case 5: + source2 = (long *) bh_ptr[2]->b_data; + source3 = (long *) bh_ptr[3]->b_data; + source4 = (long *) bh_ptr[4]->b_data; + for (i = lines; i > 0; i--) { + __asm__ __volatile__(" + ldd [%0 + 0x00], %%g2 + ldd [%0 + 0x08], %%g4 + ldd [%0 + 0x10], %%o0 + ldd [%0 + 0x18], %%o2 + ldd [%1 + 0x00], %%o4 + ldd [%1 + 0x08], %%l0 + ldd [%1 + 0x10], %%l2 + ldd [%1 + 0x18], %%l4 + xor %%g2, %%o4, %%g2 + xor %%g3, %%o5, %%g3 + ldd [%2 + 0x00], %%o4 + xor %%g4, %%l0, %%g4 + xor %%g5, %%l1, %%g5 + ldd [%2 + 0x08], %%l0 + xor %%o0, %%l2, %%o0 + xor %%o1, %%l3, %%o1 + ldd [%2 + 0x10], %%l2 + xor %%o2, %%l4, %%o2 + xor %%o3, %%l5, %%o3 + ldd [%2 + 0x18], %%l4 + xor %%g2, %%o4, %%g2 + xor %%g3, %%o5, %%g3 + ldd [%3 + 0x00], %%o4 + xor %%g4, %%l0, %%g4 + xor %%g5, %%l1, %%g5 + ldd [%3 + 0x08], %%l0 + xor %%o0, %%l2, %%o0 + xor %%o1, %%l3, %%o1 + ldd [%3 + 0x10], %%l2 + xor %%o2, %%l4, %%o2 + xor %%o3, %%l5, %%o3 + ldd [%3 + 0x18], %%l4 + xor %%g2, %%o4, %%g2 + xor %%g3, %%o5, %%g3 + ldd [%4 + 0x00], %%o4 + xor %%g4, %%l0, %%g4 + xor %%g5, %%l1, %%g5 + ldd [%4 + 0x08], %%l0 + xor %%o0, %%l2, %%o0 + xor %%o1, %%l3, %%o1 + ldd [%4 + 0x10], %%l2 + xor %%o2, %%l4, %%o2 + xor %%o3, %%l5, %%o3 + ldd [%4 + 0x18], %%l4 + xor %%g2, %%o4, %%g2 + xor %%g3, %%o5, %%g3 + xor %%g4, %%l0, %%g4 + xor %%g5, %%l1, %%g5 + xor %%o0, %%l2, %%o0 + xor %%o1, %%l3, %%o1 + xor %%o2, %%l4, %%o2 + xor %%o3, %%l5, %%o3 + std %%g2, [%0 + 0x00] + std %%g4, [%0 + 0x08] + std %%o0, [%0 + 0x10] + std %%o2, [%0 + 0x18] + " : : "r" (destp), "r" (source1), "r" (source2), "r" (source3), "r" (source4) + : "g2", "g3", "g4", "g5", "o0", "o1", "o2", "o3", "o4", "o5", + "l0", "l1", "l2", "l3", "l4", "l5"); + destp += 8; + source1 += 8; + source2 += 8; + source3 += 8; + source4 += 8; + } + break; + } +} +#endif /* __sparc_v[78]__ */ + +#ifndef __sparc_v9__ + +/* + * this one works reasonably on any x86 CPU + * (send me an assembly version for inclusion if you can make it faster) + * + * this one is just as fast as written in pure assembly on x86. + * the reason for this separate version is that the + * fast open-coded xor routine "32reg" produces suboptimal code + * on x86, due to lack of registers. + */ +XORBLOCK_TEMPLATE(8regs) +{ + int len = bh_ptr[0]->b_size; + long *destp = (long *) bh_ptr[0]->b_data; + long *source1, *source2, *source3, *source4; + long lines = len / (sizeof (long)) / 8, i; + + switch(count) { + case 2: + source1 = (long *) bh_ptr[1]->b_data; + for (i = lines; i > 0; i--) { + *(destp + 0) ^= *(source1 + 0); + *(destp + 1) ^= *(source1 + 1); + *(destp + 2) ^= *(source1 + 2); + *(destp + 3) ^= *(source1 + 3); + *(destp + 4) ^= *(source1 + 4); + *(destp + 5) ^= *(source1 + 5); + *(destp + 6) ^= *(source1 + 6); + *(destp + 7) ^= *(source1 + 7); + source1 += 8; + destp += 8; + } + break; + case 3: + source2 = (long *) bh_ptr[2]->b_data; + source1 = (long *) bh_ptr[1]->b_data; + for (i = lines; i > 0; i--) { + *(destp + 0) ^= *(source1 + 0); + *(destp + 0) ^= *(source2 + 0); + *(destp + 1) ^= *(source1 + 1); + *(destp + 1) ^= *(source2 + 1); + *(destp + 2) ^= *(source1 + 2); + *(destp + 2) ^= *(source2 + 2); + *(destp + 3) ^= *(source1 + 3); + *(destp + 3) ^= *(source2 + 3); + *(destp + 4) ^= *(source1 + 4); + *(destp + 4) ^= *(source2 + 4); + *(destp + 5) ^= *(source1 + 5); + *(destp + 5) ^= *(source2 + 5); + *(destp + 6) ^= *(source1 + 6); + *(destp + 6) ^= *(source2 + 6); + *(destp + 7) ^= *(source1 + 7); + *(destp + 7) ^= *(source2 + 7); + source1 += 8; + source2 += 8; + destp += 8; + } + break; + case 4: + source3 = (long *) bh_ptr[3]->b_data; + source2 = (long *) bh_ptr[2]->b_data; + source1 = (long *) bh_ptr[1]->b_data; + for (i = lines; i > 0; i--) { + *(destp + 0) ^= *(source1 + 0); + *(destp + 0) ^= *(source2 + 0); + *(destp + 0) ^= *(source3 + 0); + *(destp + 1) ^= *(source1 + 1); + *(destp + 1) ^= *(source2 + 1); + *(destp + 1) ^= *(source3 + 1); + *(destp + 2) ^= *(source1 + 2); + *(destp + 2) ^= *(source2 + 2); + *(destp + 2) ^= *(source3 + 2); + *(destp + 3) ^= *(source1 + 3); + *(destp + 3) ^= *(source2 + 3); + *(destp + 3) ^= *(source3 + 3); + *(destp + 4) ^= *(source1 + 4); + *(destp + 4) ^= *(source2 + 4); + *(destp + 4) ^= *(source3 + 4); + *(destp + 5) ^= *(source1 + 5); + *(destp + 5) ^= *(source2 + 5); + *(destp + 5) ^= *(source3 + 5); + *(destp + 6) ^= *(source1 + 6); + *(destp + 6) ^= *(source2 + 6); + *(destp + 6) ^= *(source3 + 6); + *(destp + 7) ^= *(source1 + 7); + *(destp + 7) ^= *(source2 + 7); + *(destp + 7) ^= *(source3 + 7); + source1 += 8; + source2 += 8; + source3 += 8; + destp += 8; + } + break; + case 5: + source4 = (long *) bh_ptr[4]->b_data; + source3 = (long *) bh_ptr[3]->b_data; + source2 = (long *) bh_ptr[2]->b_data; + source1 = (long *) bh_ptr[1]->b_data; + for (i = lines; i > 0; i--) { + *(destp + 0) ^= *(source1 + 0); + *(destp + 0) ^= *(source2 + 0); + *(destp + 0) ^= *(source3 + 0); + *(destp + 0) ^= *(source4 + 0); + *(destp + 1) ^= *(source1 + 1); + *(destp + 1) ^= *(source2 + 1); + *(destp + 1) ^= *(source3 + 1); + *(destp + 1) ^= *(source4 + 1); + *(destp + 2) ^= *(source1 + 2); + *(destp + 2) ^= *(source2 + 2); + *(destp + 2) ^= *(source3 + 2); + *(destp + 2) ^= *(source4 + 2); + *(destp + 3) ^= *(source1 + 3); + *(destp + 3) ^= *(source2 + 3); + *(destp + 3) ^= *(source3 + 3); + *(destp + 3) ^= *(source4 + 3); + *(destp + 4) ^= *(source1 + 4); + *(destp + 4) ^= *(source2 + 4); + *(destp + 4) ^= *(source3 + 4); + *(destp + 4) ^= *(source4 + 4); + *(destp + 5) ^= *(source1 + 5); + *(destp + 5) ^= *(source2 + 5); + *(destp + 5) ^= *(source3 + 5); + *(destp + 5) ^= *(source4 + 5); + *(destp + 6) ^= *(source1 + 6); + *(destp + 6) ^= *(source2 + 6); + *(destp + 6) ^= *(source3 + 6); + *(destp + 6) ^= *(source4 + 6); + *(destp + 7) ^= *(source1 + 7); + *(destp + 7) ^= *(source2 + 7); + *(destp + 7) ^= *(source3 + 7); + *(destp + 7) ^= *(source4 + 7); + source1 += 8; + source2 += 8; + source3 += 8; + source4 += 8; + destp += 8; + } + break; + } +} + +/* + * platform independent RAID5 checksum calculation, this should + * be very fast on any platform that has a decent amount of + * registers. (32 or more) + */ +XORBLOCK_TEMPLATE(32regs) +{ + int size = bh_ptr[0]->b_size; + int lines = size / (sizeof (long)) / 8, i; + long *destp = (long *) bh_ptr[0]->b_data; + long *source1, *source2, *source3, *source4; + + /* LOTS of registers available... + We do explicite loop-unrolling here for code which + favours RISC machines. In fact this is almoast direct + RISC assembly on Alpha and SPARC :-) */ + + + switch(count) { + case 2: + source1 = (long *) bh_ptr[1]->b_data; + for (i = lines; i > 0; i--) { + register long d0, d1, d2, d3, d4, d5, d6, d7; + d0 = destp[0]; /* Pull the stuff into registers */ + d1 = destp[1]; /* ... in bursts, if possible. */ + d2 = destp[2]; + d3 = destp[3]; + d4 = destp[4]; + d5 = destp[5]; + d6 = destp[6]; + d7 = destp[7]; + d0 ^= source1[0]; + d1 ^= source1[1]; + d2 ^= source1[2]; + d3 ^= source1[3]; + d4 ^= source1[4]; + d5 ^= source1[5]; + d6 ^= source1[6]; + d7 ^= source1[7]; + destp[0] = d0; /* Store the result (in burts) */ + destp[1] = d1; + destp[2] = d2; + destp[3] = d3; + destp[4] = d4; /* Store the result (in burts) */ + destp[5] = d5; + destp[6] = d6; + destp[7] = d7; + source1 += 8; + destp += 8; + } + break; + case 3: + source2 = (long *) bh_ptr[2]->b_data; + source1 = (long *) bh_ptr[1]->b_data; + for (i = lines; i > 0; i--) { + register long d0, d1, d2, d3, d4, d5, d6, d7; + d0 = destp[0]; /* Pull the stuff into registers */ + d1 = destp[1]; /* ... in bursts, if possible. */ + d2 = destp[2]; + d3 = destp[3]; + d4 = destp[4]; + d5 = destp[5]; + d6 = destp[6]; + d7 = destp[7]; + d0 ^= source1[0]; + d1 ^= source1[1]; + d2 ^= source1[2]; + d3 ^= source1[3]; + d4 ^= source1[4]; + d5 ^= source1[5]; + d6 ^= source1[6]; + d7 ^= source1[7]; + d0 ^= source2[0]; + d1 ^= source2[1]; + d2 ^= source2[2]; + d3 ^= source2[3]; + d4 ^= source2[4]; + d5 ^= source2[5]; + d6 ^= source2[6]; + d7 ^= source2[7]; + destp[0] = d0; /* Store the result (in burts) */ + destp[1] = d1; + destp[2] = d2; + destp[3] = d3; + destp[4] = d4; /* Store the result (in burts) */ + destp[5] = d5; + destp[6] = d6; + destp[7] = d7; + source1 += 8; + source2 += 8; + destp += 8; + } + break; + case 4: + source3 = (long *) bh_ptr[3]->b_data; + source2 = (long *) bh_ptr[2]->b_data; + source1 = (long *) bh_ptr[1]->b_data; + for (i = lines; i > 0; i--) { + register long d0, d1, d2, d3, d4, d5, d6, d7; + d0 = destp[0]; /* Pull the stuff into registers */ + d1 = destp[1]; /* ... in bursts, if possible. */ + d2 = destp[2]; + d3 = destp[3]; + d4 = destp[4]; + d5 = destp[5]; + d6 = destp[6]; + d7 = destp[7]; + d0 ^= source1[0]; + d1 ^= source1[1]; + d2 ^= source1[2]; + d3 ^= source1[3]; + d4 ^= source1[4]; + d5 ^= source1[5]; + d6 ^= source1[6]; + d7 ^= source1[7]; + d0 ^= source2[0]; + d1 ^= source2[1]; + d2 ^= source2[2]; + d3 ^= source2[3]; + d4 ^= source2[4]; + d5 ^= source2[5]; + d6 ^= source2[6]; + d7 ^= source2[7]; + d0 ^= source3[0]; + d1 ^= source3[1]; + d2 ^= source3[2]; + d3 ^= source3[3]; + d4 ^= source3[4]; + d5 ^= source3[5]; + d6 ^= source3[6]; + d7 ^= source3[7]; + destp[0] = d0; /* Store the result (in burts) */ + destp[1] = d1; + destp[2] = d2; + destp[3] = d3; + destp[4] = d4; /* Store the result (in burts) */ + destp[5] = d5; + destp[6] = d6; + destp[7] = d7; + source1 += 8; + source2 += 8; + source3 += 8; + destp += 8; + } + break; + case 5: + source4 = (long *) bh_ptr[4]->b_data; + source3 = (long *) bh_ptr[3]->b_data; + source2 = (long *) bh_ptr[2]->b_data; + source1 = (long *) bh_ptr[1]->b_data; + for (i = lines; i > 0; i--) { + register long d0, d1, d2, d3, d4, d5, d6, d7; + d0 = destp[0]; /* Pull the stuff into registers */ + d1 = destp[1]; /* ... in bursts, if possible. */ + d2 = destp[2]; + d3 = destp[3]; + d4 = destp[4]; + d5 = destp[5]; + d6 = destp[6]; + d7 = destp[7]; + d0 ^= source1[0]; + d1 ^= source1[1]; + d2 ^= source1[2]; + d3 ^= source1[3]; + d4 ^= source1[4]; + d5 ^= source1[5]; + d6 ^= source1[6]; + d7 ^= source1[7]; + d0 ^= source2[0]; + d1 ^= source2[1]; + d2 ^= source2[2]; + d3 ^= source2[3]; + d4 ^= source2[4]; + d5 ^= source2[5]; + d6 ^= source2[6]; + d7 ^= source2[7]; + d0 ^= source3[0]; + d1 ^= source3[1]; + d2 ^= source3[2]; + d3 ^= source3[3]; + d4 ^= source3[4]; + d5 ^= source3[5]; + d6 ^= source3[6]; + d7 ^= source3[7]; + d0 ^= source4[0]; + d1 ^= source4[1]; + d2 ^= source4[2]; + d3 ^= source4[3]; + d4 ^= source4[4]; + d5 ^= source4[5]; + d6 ^= source4[6]; + d7 ^= source4[7]; + destp[0] = d0; /* Store the result (in burts) */ + destp[1] = d1; + destp[2] = d2; + destp[3] = d3; + destp[4] = d4; /* Store the result (in burts) */ + destp[5] = d5; + destp[6] = d6; + destp[7] = d7; + source1 += 8; + source2 += 8; + source3 += 8; + source4 += 8; + destp += 8; + } + break; + } +} + +/* + * (the -6*32 shift factor colors the cache) + */ +#define SIZE (PAGE_SIZE-6*32) + +static void xor_speed ( struct xor_block_template * func, + struct buffer_head *b1, struct buffer_head *b2) +{ + int speed; + unsigned long now; + int i, count, max; + struct buffer_head *bh_ptr[6]; + + func->next = xor_functions; + xor_functions = func; + bh_ptr[0] = b1; + bh_ptr[1] = b2; + + /* + * count the number of XORs done during a whole jiffy. + * calculate the speed of checksumming from this. + * (we use a 2-page allocation to have guaranteed + * color L1-cache layout) + */ + max = 0; + for (i = 0; i < 5; i++) { + now = jiffies; + count = 0; + while (jiffies == now) { + mb(); + func->xor_block(2,bh_ptr); + mb(); + count++; + mb(); + } + if (count > max) + max = count; + } + + speed = max * (HZ*SIZE/1024); + func->speed = speed; + + printk( " %-10s: %5d.%03d MB/sec\n", func->name, + speed / 1000, speed % 1000); +} + +static inline void pick_fastest_function(void) +{ + struct xor_block_template *f, *fastest; + + fastest = xor_functions; + for (f = fastest; f; f = f->next) { + if (f->speed > fastest->speed) + fastest = f; + } +#ifdef CONFIG_X86_XMM + if (boot_cpu_data.mmu_cr4_features & X86_CR4_OSXMMEXCPT) { + fastest = &t_xor_block_pIII_kni; + } +#endif + xor_block = fastest->xor_block; + printk( "using fastest function: %s (%d.%03d MB/sec)\n", fastest->name, + fastest->speed / 1000, fastest->speed % 1000); +} + +static struct buffer_head b1, b2; + +void calibrate_xor_block(void) +{ + memset(&b1,0,sizeof(b1)); + b2 = b1; + + b1.b_data = (char *) md__get_free_pages(GFP_KERNEL,2); + if (!b1.b_data) { + pick_fastest_function(); + return; + } + b2.b_data = b1.b_data + 2*PAGE_SIZE + SIZE; + + b1.b_size = SIZE; + + printk(KERN_INFO "raid5: measuring checksumming speed\n"); + + sti(); /* should be safe */ + +#if defined(__sparc__) && !defined(__sparc_v9__) + printk(KERN_INFO "raid5: trying high-speed SPARC checksum routine\n"); + xor_speed(&t_xor_block_SPARC,&b1,&b2); +#endif + +#ifdef CONFIG_X86_XMM + if (boot_cpu_data.mmu_cr4_features & X86_CR4_OSXMMEXCPT) { + printk(KERN_INFO + "raid5: KNI detected, trying cache-avoiding KNI checksum routine\n"); + /* we force the use of the KNI xor block because it + can write around l2. we may also be able + to load into the l1 only depending on how + the cpu deals with a load to a line that is + being prefetched. + */ + xor_speed(&t_xor_block_pIII_kni,&b1,&b2); + } +#endif /* CONFIG_X86_XMM */ + +#ifdef __i386__ + + if (md_cpu_has_mmx()) { + printk(KERN_INFO + "raid5: MMX detected, trying high-speed MMX checksum routines\n"); + xor_speed(&t_xor_block_pII_mmx,&b1,&b2); + xor_speed(&t_xor_block_p5_mmx,&b1,&b2); + } + +#endif /* __i386__ */ + + + xor_speed(&t_xor_block_8regs,&b1,&b2); + xor_speed(&t_xor_block_32regs,&b1,&b2); + + free_pages((unsigned long)b1.b_data,2); + pick_fastest_function(); +} + +#else /* __sparc_v9__ */ + +void calibrate_xor_block(void) +{ + printk(KERN_INFO "raid5: using high-speed VIS checksum routine\n"); + xor_block = xor_block_VIS; +} + +#endif /* __sparc_v9__ */ + +MD_EXPORT_SYMBOL(xor_block); + diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/char/cyclades.c linux/drivers/char/cyclades.c --- v2.3.99-pre7/linux/drivers/char/cyclades.c Thu May 11 15:30:06 2000 +++ linux/drivers/char/cyclades.c Fri May 12 11:22:31 2000 @@ -1,12 +1,12 @@ #undef BLOCKMOVE #define Z_WAKE static char rcsid[] = -"$Revision: 2.3.2.4 $$Date: 2000/01/17 09:19:40 $"; +"$Revision: 2.3.2.6 $$Date: 2000/05/05 13:56:05 $"; /* * linux/drivers/char/cyclades.c * - * This file contains the driver for the Cyclades Cyclom-Y multiport + * This file contains the driver for the Cyclades async multiport * serial boards. * * Initially written by Randolph Bentson . @@ -23,14 +23,22 @@ * * This version supports shared IRQ's (only for PCI boards). * - * This module exports the following rs232 io functions: - * int cy_init(void); - * int cy_open(struct tty_struct *tty, struct file *filp); - * and the following functions for modularization. - * int init_module(void); - * void cleanup_module(void); - * * $Log: cyclades.c,v $ + * Revision 2.3.2.6 2000/05/05 13:56:05 ivan + * Driver now reports physical instead of virtual memory addresses. + * Masks were added to some Cyclades-Z read accesses. + * Implemented workaround for PLX9050 bug that would cause a system lockup + * in certain systems, depending on the MMIO addresses allocated to the + * board. + * Changed the Tx interrupt programming in the CD1400 chips to boost up + * performance (Cyclom-Y only). + * Code is now compliant with the new module interface (module_[init|exit]). + * Make use of the PCI helper functions to access PCI resources. + * Did some code "housekeeping". + * + * Revision 2.3.2.5 2000/01/19 14:35:33 ivan + * Fixed bug in cy_set_termios on CRTSCTS flag turnoff. + * * Revision 2.3.2.4 2000/01/17 09:19:40 ivan * Fixed SMP locking in Cyclom-Y interrupt handler. * @@ -695,7 +703,7 @@ #ifndef SERIAL_XMIT_SIZE #define SERIAL_XMIT_SIZE (MIN(PAGE_SIZE, 4096)) #endif -#define WAKEUP_CHARS (SERIAL_XMIT_SIZE-256) +#define WAKEUP_CHARS 256 #define STD_COM_FLAGS (0) @@ -706,7 +714,7 @@ static struct tty_driver cy_serial_driver, cy_callout_driver; static int serial_refcount; -#ifndef CONFIG_COBALT_27 +#ifdef CONFIG_ISA /* This is the address lookup table. The driver will probe for Cyclom-Y/ISA boards at all addresses in here. If you want the driver to probe addresses at a different address, add it to @@ -737,7 +745,7 @@ MODULE_PARM(irq, "1-" __MODULE_STRING(NR_CARDS) "i"); #endif -#endif /* CONFIG_COBALT_27 */ +#endif /* CONFIG_ISA */ /* This is the per-card data structure containing address, irq, number of channels, etc. This driver supports a maximum of NR_CARDS cards. @@ -861,12 +869,9 @@ static void cy_start(struct tty_struct *); static void set_line_char(struct cyclades_port *); static int cyz_issue_cmd(struct cyclades_card *, uclong, ucchar, uclong); -#ifndef CONFIG_COBALT_27 +#ifdef CONFIG_ISA static unsigned detect_isa_irq (volatile ucchar *); -#endif /* CONFIG_COBALT_27 */ -#ifdef CYCLOM_SHOW_STATUS -static void show_status(int); -#endif +#endif /* CONFIG_ISA */ static int cyclades_get_proc_info(char *, char **, off_t , int , int *, void *); @@ -877,23 +882,15 @@ static long cyz_polling_cycle = CZ_DEF_POLL; static int cyz_timeron = 0; -static struct timer_list cyz_timerlist = { - function: cyz_poll +static struct timer_list +cyz_timerlist = { + NULL, NULL, 0, 0, cyz_poll }; #else /* CONFIG_CYZ_INTR */ static void cyz_rx_restart(unsigned long); static struct timer_list cyz_rx_full_timer[NR_PORTS]; #endif /* CONFIG_CYZ_INTR */ -/************************************************** -error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned long)); -copy_to_user (to, from, count); -*************************************************************** -error = verify_area(VERIFY_READ, (void *) arg, sizeof(unsigned long *)); -copy_from_user(to, from, count); -**************************************************/ - - static inline int serial_paranoia_check(struct cyclades_port *info, kdev_t device, const char *routine) @@ -1047,7 +1044,8 @@ return(0); } /* cyy_issue_cmd */ -#ifndef CONFIG_COBALT_27 /* ISA interrupt detection code */ +#ifdef CONFIG_ISA +/* ISA interrupt detection code */ static unsigned detect_isa_irq (volatile ucchar *address) { @@ -1074,7 +1072,7 @@ cy_writeb((u_long)address + (CyCAR< 0)? irq : 0; } -#endif /* CONFIG_COBALT_27 */ +#endif /* CONFIG_ISA */ /* The real interrupt service routine is called whenever the card wants its hand held--chars @@ -1319,14 +1317,14 @@ /* validate the port# (as configured and open) */ if( (i < 0) || (NR_PORTS <= i) ){ cy_writeb((u_long)base_addr+(CySRER<last_active = jiffies; if(info->tty == 0){ cy_writeb((u_long)base_addr+(CySRER<xmit_cnt){ cy_writeb((u_long)base_addr+(CySRER<xmit_buf == 0){ cy_writeb((u_long)base_addr+(CySRER<tty->stopped || info->tty->hw_stopped){ cy_writeb((u_long)base_addr+(CySRER<tty->hw_stopped = 0; cy_writeb((u_long)base_addr+(CySRER<tty->hw_stopped = 1; cy_writeb((u_long)base_addr+(CySRER<base_addr + cy_readl(&firm_id->zfwctrl_addr)); + (cinfo->base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); board_ctrl = &zfw_ctrl->board_ctrl; loc_doorbell = cy_readl(&((struct RUNTIME_9060 *) @@ -1557,7 +1556,8 @@ return (-1); } zfw_ctrl = (struct ZFW_CTRL *) - (cinfo->base_addr + cy_readl(&firm_id->zfwctrl_addr)); + (cinfo->base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); board_ctrl = &zfw_ctrl->board_ctrl; index = 0; @@ -1774,7 +1774,8 @@ firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS); zfw_ctrl = (struct ZFW_CTRL *) - (cinfo->base_addr + cy_readl(&firm_id->zfwctrl_addr)); + (cinfo->base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); board_ctrl = &(zfw_ctrl->board_ctrl); fw_ver = cy_readl(&board_ctrl->fw_version); hw_ver = cy_readl(&((struct RUNTIME_9060 *)(cinfo->ctl_addr))->mail_box_0); @@ -1951,7 +1952,8 @@ firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS); zfw_ctrl = (struct ZFW_CTRL *) - (cinfo->base_addr + cy_readl(&firm_id->zfwctrl_addr)); + (cinfo->base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); board_ctrl = &(zfw_ctrl->board_ctrl); /* Skip first polling cycle to avoid racing conditions with the FW */ @@ -2091,9 +2093,9 @@ return -ENODEV; } - zfw_ctrl = - (struct ZFW_CTRL *) - (cy_card[card].base_addr + cy_readl(&firm_id->zfwctrl_addr)); + zfw_ctrl = (struct ZFW_CTRL *) + (cy_card[card].base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); board_ctrl = &zfw_ctrl->board_ctrl; ch_ctrl = zfw_ctrl->ch_ctrl; @@ -2201,7 +2203,7 @@ CY_LOCK(info, flags); cy_writeb((u_long)base_addr+(CyCAR<zfwctrl_addr)); + zfw_ctrl = (struct ZFW_CTRL *) + (cy_card[card].base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); board_ctrl = &(zfw_ctrl->board_ctrl); ch_ctrl = zfw_ctrl->ch_ctrl; @@ -2499,9 +2501,8 @@ return -EINVAL; } - zfw_ctrl = - (struct ZFW_CTRL *) - (base_addr + cy_readl(&firm_id->zfwctrl_addr)); + zfw_ctrl = (struct ZFW_CTRL *) + (base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); board_ctrl = &zfw_ctrl->board_ctrl; ch_ctrl = zfw_ctrl->ch_ctrl; @@ -2758,7 +2759,7 @@ index = cy_card[card].bus_index; base_addr = (unsigned char *) (cy_card[card].base_addr + (cy_chip_offset[chip]<card].base_addr; struct FIRM_ID *firm_id = (struct FIRM_ID *) (base_addr + ID_ADDRESS); - struct ZFW_CTRL *zfw_ctrl = - (struct ZFW_CTRL *) (base_addr + cy_readl(&firm_id->zfwctrl_addr)); + struct ZFW_CTRL *zfw_ctrl = (struct ZFW_CTRL *) + (base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); struct CH_CTRL *ch_ctrl = zfw_ctrl->ch_ctrl; int channel = info->line - cy_card[info->card].first_line; int retval; @@ -3136,8 +3137,9 @@ volatile uclong tx_put, tx_get, tx_bufsize; firm_id = (struct FIRM_ID *)(cy_card[card].base_addr + ID_ADDRESS); - zfw_ctrl = (struct ZFW_CTRL *) (cy_card[card].base_addr + - cy_readl(&firm_id->zfwctrl_addr)); + zfw_ctrl = (struct ZFW_CTRL *) + (cy_card[card].base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]); @@ -3427,7 +3429,8 @@ } zfw_ctrl = (struct ZFW_CTRL *) - (cy_card[card].base_addr + cy_readl(&firm_id->zfwctrl_addr)); + (cy_card[card].base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); board_ctrl = &zfw_ctrl->board_ctrl; ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); buf_ctrl = &zfw_ctrl->buf_ctrl[channel]; @@ -3660,7 +3663,8 @@ (cy_card[card].base_addr + ID_ADDRESS); if (ISZLOADED(cy_card[card])) { zfw_ctrl = (struct ZFW_CTRL *) - (cy_card[card].base_addr + cy_readl(&firm_id->zfwctrl_addr)); + (cy_card[card].base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); board_ctrl = &zfw_ctrl->board_ctrl; ch_ctrl = zfw_ctrl->ch_ctrl; lstatus = cy_readl(&ch_ctrl[channel].rs_status); @@ -3825,7 +3829,8 @@ (cy_card[card].base_addr + ID_ADDRESS); if (ISZLOADED(cy_card[card])) { zfw_ctrl = (struct ZFW_CTRL *) - (cy_card[card].base_addr + cy_readl(&firm_id->zfwctrl_addr)); + (cy_card[card].base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); board_ctrl = &zfw_ctrl->board_ctrl; ch_ctrl = zfw_ctrl->ch_ctrl; @@ -4337,7 +4342,7 @@ if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) { - tty->stopped = 0; + tty->hw_stopped = 0; cy_start(tty); } #if 0 @@ -4502,7 +4507,7 @@ cy_writeb((u_long)base_addr+(CyCAR<irq; - cy_pci_addr0 = pci_resource_start(pdev, 0); - cy_pci_addr1 = pci_resource_start(pdev, 1); - cy_pci_addr2 = pci_resource_start(pdev, 2); - pci_read_config_byte(pdev, PCI_REVISION_ID, &cyy_rev_id); + cy_pci_phys0 = pci_resource_start(pdev, 0); + cy_pci_phys2 = pci_resource_start(pdev, 2); + pci_read_config_byte(pdev, PCI_REVISION_ID, &cyy_rev_id); device_id &= ~PCI_DEVICE_ID_MASK; @@ -4892,13 +4898,13 @@ printk("rev_id=%d) IRQ%d\n", cyy_rev_id, (int)cy_pci_irq); printk("Cyclom-Y/PCI:found winaddr=0x%lx ctladdr=0x%lx\n", - (ulong)cy_pci_addr2, (ulong)cy_pci_addr0); + (ulong)cy_pci_phys2, (ulong)cy_pci_phys0); #endif - if (pdev->resource[2].flags & ~PCI_BASE_ADDRESS_IO_MASK) { + if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) { printk(" Warning: PCI I/O bit incorrectly set. " "Ignoring it...\n"); - pdev->resource[2].flags &= PCI_BASE_ADDRESS_IO_MASK; + pdev->resource[2].flags &= ~IORESOURCE_IO; } #if defined(__alpha__) @@ -4908,15 +4914,15 @@ printk("rev_id=%d) IRQ%d\n", cyy_rev_id, (int)cy_pci_irq); printk("Cyclom-Y/PCI:found winaddr=0x%lx ctladdr=0x%lx\n", - (ulong)cy_pci_addr2, (ulong)cy_pci_addr0); + (ulong)cy_pci_phys2, (ulong)cy_pci_phys0); printk("Cyclom-Y/PCI not supported for low addresses in " "Alpha systems.\n"); i--; continue; } #else - cy_pci_addr0 = (ulong)ioremap(cy_pci_addr0, CyPCI_Yctl); - cy_pci_addr2 = (ulong)ioremap(cy_pci_addr2, CyPCI_Ywin); + cy_pci_addr0 = (ulong)ioremap(cy_pci_phys0, CyPCI_Yctl); + cy_pci_addr2 = (ulong)ioremap(cy_pci_phys2, CyPCI_Ywin); #endif #ifdef CY_PCI_DEBUG @@ -4928,13 +4934,13 @@ if(cy_pci_nchan == 0) { printk("Cyclom-Y PCI host card with "); printk("no Serial-Modules at 0x%lx.\n", - (ulong) cy_pci_addr2); + (ulong) cy_pci_phys2); i--; continue; } if((cy_next_channel+cy_pci_nchan) > NR_PORTS) { printk("Cyclom-Y/PCI found at 0x%lx ", - (ulong) cy_pci_addr2); + (ulong) cy_pci_phys2); printk("but no channels are available.\n"); printk("Change NR_PORTS in cyclades.c and recompile kernel.\n"); return(i); @@ -4945,7 +4951,7 @@ } if (j == NR_CARDS) { /* no more cy_cards available */ printk("Cyclom-Y/PCI found at 0x%lx ", - (ulong) cy_pci_addr2); + (ulong) cy_pci_phys2); printk("but no more cards can be used.\n"); printk("Change NR_CARDS in cyclades.c and recompile kernel.\n"); return(i); @@ -4956,13 +4962,15 @@ SA_SHIRQ, "Cyclom-Y", &cy_card[j])) { printk("Cyclom-Y/PCI found at 0x%lx ", - (ulong) cy_pci_addr2); + (ulong) cy_pci_phys2); printk("but could not allocate IRQ%d.\n", cy_pci_irq); return(i); } /* set cy_card */ + cy_card[j].base_phys = (ulong)cy_pci_phys2; + cy_card[j].ctl_phys = (ulong)cy_pci_phys0; cy_card[j].base_addr = (ulong)cy_pci_addr2; cy_card[j].ctl_addr = (ulong)cy_pci_addr0; cy_card[j].irq = (int) cy_pci_irq; @@ -4975,10 +4983,7 @@ switch (plx_ver) { case PLX_9050: - plx_init(cy_pci_addr0, 0x50); - - cy_writew(cy_pci_addr0+0x4c, - cy_readw(cy_pci_addr0+0x4c)|0x0040); + cy_writeb(cy_pci_addr0+0x4c, 0x43); break; case PLX_9060: @@ -5000,8 +5005,8 @@ /* print message */ printk("Cyclom-Y/PCI #%d: 0x%lx-0x%lx, IRQ%d, ", j+1, - (ulong)cy_pci_addr2, - (ulong)(cy_pci_addr2 + CyPCI_Ywin - 1), + (ulong)cy_pci_phys2, + (ulong)(cy_pci_phys2 + CyPCI_Ywin - 1), (int)cy_pci_irq); printk("%d channels starting from port %d.\n", cy_pci_nchan, cy_next_channel); @@ -5014,7 +5019,7 @@ printk("rev_id=%d) IRQ%d\n", cyy_rev_id, (int)cy_pci_irq); printk("Cyclades-Z/PCI: found winaddr=0x%lx ctladdr=0x%lx\n", - (ulong)cy_pci_addr2, (ulong)cy_pci_addr0); + (ulong)cy_pci_phys2, (ulong)cy_pci_phys0); printk("Cyclades-Z/PCI not supported for low addresses\n"); break; }else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi){ @@ -5024,10 +5029,10 @@ printk("rev_id=%d) IRQ%d\n", cyy_rev_id, (int)cy_pci_irq); printk("Cyclades-Z/PCI: found winaddr=0x%lx ctladdr=0x%lx\n", - (ulong)cy_pci_addr2, (ulong)cy_pci_addr0); + (ulong)cy_pci_phys2, (ulong)cy_pci_phys0); #endif #if !defined(__alpha__) - cy_pci_addr0 = (ulong)ioremap(cy_pci_addr0, CyPCI_Zctl); + cy_pci_addr0 = (ulong)ioremap(cy_pci_phys0, CyPCI_Zctl); #endif /* Disable interrupts on the PLX before resetting it */ @@ -5044,21 +5049,23 @@ mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 *) cy_pci_addr0)->mail_box_0); - if (pdev->resource[2].flags & ~PCI_BASE_ADDRESS_IO_MASK) { + if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) { printk(" Warning: PCI I/O bit incorrectly set. " "Ignoring it...\n"); - pdev->resource[2].flags &= PCI_BASE_ADDRESS_IO_MASK; + pdev->resource[2].flags &= ~IORESOURCE_IO; } if (mailbox == ZE_V1) { #if !defined(__alpha__) - cy_pci_addr2 = (ulong)ioremap(cy_pci_addr2, CyPCI_Ze_win); + cy_pci_addr2 = (ulong)ioremap(cy_pci_phys2, CyPCI_Ze_win); #endif if (ZeIndex == NR_CARDS) { printk("Cyclades-Ze/PCI found at 0x%lx ", - (ulong)cy_pci_addr2); + (ulong)cy_pci_phys2); printk("but no more cards can be used.\n"); printk("Change NR_CARDS in cyclades.c and recompile kernel.\n"); } else { + Ze_phys0[ZeIndex] = cy_pci_phys0; + Ze_phys2[ZeIndex] = cy_pci_phys2; Ze_addr0[ZeIndex] = cy_pci_addr0; Ze_addr2[ZeIndex] = cy_pci_addr2; Ze_irq[ZeIndex] = cy_pci_irq; @@ -5068,7 +5075,7 @@ continue; } else { #if !defined(__alpha__) - cy_pci_addr2 = (ulong)ioremap(cy_pci_addr2, CyPCI_Zwin); + cy_pci_addr2 = (ulong)ioremap(cy_pci_phys2, CyPCI_Zwin); #endif } @@ -5105,7 +5112,7 @@ if((cy_next_channel+cy_pci_nchan) > NR_PORTS) { printk("Cyclades-8Zo/PCI found at 0x%lx ", - (ulong)cy_pci_addr2); + (ulong)cy_pci_phys2); printk("but no channels are available.\n"); printk("Change NR_PORTS in cyclades.c and recompile kernel.\n"); return(i); @@ -5117,7 +5124,7 @@ } if (j == NR_CARDS) { /* no more cy_cards available */ printk("Cyclades-8Zo/PCI found at 0x%lx ", - (ulong)cy_pci_addr2); + (ulong)cy_pci_phys2); printk("but no more cards can be used.\n"); printk("Change NR_CARDS in cyclades.c and recompile kernel.\n"); return(i); @@ -5129,10 +5136,10 @@ if(request_irq(cy_pci_irq, cyz_interrupt, SA_SHIRQ, "Cyclades-Z", &cy_card[j])) { - printk("Could not allocate IRQ%d ", + printk("Cyclom-8Zo/PCI found at 0x%lx ", + (ulong) cy_pci_phys2); + printk("but could not allocate IRQ%d.\n", cy_pci_irq); - printk("for Cyclades-8Zo/PCI at 0x%lx.\n", - (ulong)cy_pci_addr2); return(i); } } @@ -5140,6 +5147,8 @@ /* set cy_card */ + cy_card[j].base_phys = cy_pci_phys2; + cy_card[j].ctl_phys = cy_pci_phys0; cy_card[j].base_addr = cy_pci_addr2; cy_card[j].ctl_addr = cy_pci_addr0; cy_card[j].irq = (int) cy_pci_irq; @@ -5152,14 +5161,14 @@ /* don't report IRQ if board is no IRQ */ if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, IRQ%d, ", - j+1,(ulong)cy_pci_addr2, - (ulong)(cy_pci_addr2 + CyPCI_Zwin - 1), + j+1,(ulong)cy_pci_phys2, + (ulong)(cy_pci_phys2 + CyPCI_Zwin - 1), (int)cy_pci_irq); else #endif /* CONFIG_CYZ_INTR */ printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, ", - j+1,(ulong)cy_pci_addr2, - (ulong)(cy_pci_addr2 + CyPCI_Zwin - 1)); + j+1,(ulong)cy_pci_phys2, + (ulong)(cy_pci_phys2 + CyPCI_Zwin - 1)); printk("%d channels starting from port %d.\n", cy_pci_nchan,cy_next_channel); @@ -5168,10 +5177,14 @@ } for (; ZeIndex != 0 && i < NR_CARDS; i++) { + cy_pci_phys0 = Ze_phys0[0]; + cy_pci_phys2 = Ze_phys2[0]; cy_pci_addr0 = Ze_addr0[0]; cy_pci_addr2 = Ze_addr2[0]; cy_pci_irq = Ze_irq[0]; for (j = 0 ; j < ZeIndex-1 ; j++) { + Ze_phys0[j] = Ze_phys0[j+1]; + Ze_phys2[j] = Ze_phys2[j+1]; Ze_addr0[j] = Ze_addr0[j+1]; Ze_addr2[j] = Ze_addr2[j+1]; Ze_irq[j] = Ze_irq[j+1]; @@ -5190,7 +5203,7 @@ if((cy_next_channel+cy_pci_nchan) > NR_PORTS) { printk("Cyclades-Ze/PCI found at 0x%lx ", - (ulong)cy_pci_addr2); + (ulong)cy_pci_phys2); printk("but no channels are available.\n"); printk("Change NR_PORTS in cyclades.c and recompile kernel.\n"); return(i); @@ -5202,7 +5215,7 @@ } if (j == NR_CARDS) { /* no more cy_cards available */ printk("Cyclades-Ze/PCI found at 0x%lx ", - (ulong)cy_pci_addr2); + (ulong)cy_pci_phys2); printk("but no more cards can be used.\n"); printk("Change NR_CARDS in cyclades.c and recompile kernel.\n"); return(i); @@ -5214,16 +5227,18 @@ if(request_irq(cy_pci_irq, cyz_interrupt, SA_SHIRQ, "Cyclades-Z", &cy_card[j])) { - printk("Could not allocate IRQ%d ", + printk("Cyclom-Ze/PCI found at 0x%lx ", + (ulong) cy_pci_phys2); + printk("but could not allocate IRQ%d.\n", cy_pci_irq); - printk("for Cyclades-Ze/PCI at 0x%lx.\n", - (ulong) cy_pci_addr2); return(i); } } #endif /* CONFIG_CYZ_INTR */ /* set cy_card */ + cy_card[j].base_phys = cy_pci_phys2; + cy_card[j].ctl_phys = cy_pci_phys0; cy_card[j].base_addr = cy_pci_addr2; cy_card[j].ctl_addr = cy_pci_addr0; cy_card[j].irq = (int) cy_pci_irq; @@ -5236,14 +5251,14 @@ /* don't report IRQ if board is no IRQ */ if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, IRQ%d, ", - j+1,(ulong)cy_pci_addr2, - (ulong)(cy_pci_addr2 + CyPCI_Ze_win - 1), + j+1,(ulong)cy_pci_phys2, + (ulong)(cy_pci_phys2 + CyPCI_Ze_win - 1), (int)cy_pci_irq); else #endif /* CONFIG_CYZ_INTR */ printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, ", - j+1,(ulong)cy_pci_addr2, - (ulong)(cy_pci_addr2 + CyPCI_Ze_win - 1)); + j+1,(ulong)cy_pci_phys2, + (ulong)(cy_pci_phys2 + CyPCI_Ze_win - 1)); printk("%d channels starting from port %d.\n", cy_pci_nchan,cy_next_channel); @@ -5251,7 +5266,7 @@ } if (ZeIndex != 0) { printk("Cyclades-Ze/PCI found at 0x%x ", - (unsigned int) Ze_addr2[0]); + (unsigned int) Ze_phys2[0]); printk("but no more cards can be used.\n"); printk("Change NR_CARDS in cyclades.c and recompile kernel.\n"); } @@ -5438,10 +5453,8 @@ availability of cy_card and cy_port data structures and updating the cy_next_channel. */ -#ifndef CONFIG_COBALT_27 /* look for isa boards */ cy_isa_nboard = cy_detect_isa(); -#endif /* CONFIG_COBALT_27 */ /* look for pci boards */ cy_pci_nboard = cy_detect_pci(); @@ -5568,9 +5581,10 @@ info->icount.frame = info->icount.parity = 0; info->icount.overrun = info->icount.brk = 0; chip_number = (port - cinfo->first_line) / 4; - if ((info->chip_rev = cy_readb(cinfo->base_addr + - (cy_chip_offset[chip_number]<= CD1400_REV_J) { + if ((info->chip_rev = + cy_readb(cinfo->base_addr + + (cy_chip_offset[chip_number]<= CD1400_REV_J) { /* It is a CD1400 rev. J or later */ info->tbpr = baud_bpr_60[13]; /* Tx BPR */ info->tco = baud_co_60[13]; /* Tx CO */ @@ -5628,16 +5642,8 @@ } /* cy_init */ #ifdef MODULE -/* See linux/drivers/char/riscom.c for ideas on how to - pass additional base addresses to the driver!!! */ -int -init_module(void) -{ - return(cy_init()); -} /* init_module */ - void -cleanup_module(void) +cy_cleanup_module(void) { int i; int e1, e2; @@ -5679,13 +5685,18 @@ free_page((unsigned long) tmp_buf); tmp_buf = NULL; } -} /* cleanup_module */ -#else +} /* cy_cleanup_module */ + +/* Module entry-points */ +module_init(cy_init); +module_exit(cy_cleanup_module); + +#else /* MODULE */ /* called by linux/init/main.c to parse command line options */ void cy_setup(char *str, int *ints) { -#ifndef CONFIG_COBALT_27 +#ifdef CONFIG_ISA int i, j; for (i = 0 ; i < NR_ISA_ADDRS ; i++) { @@ -5696,110 +5707,7 @@ cy_isa_addresses[i++] = (unsigned char *)(ints[j]); } } -#endif /* CONFIG_COBALT_27 */ - +#endif /* CONFIG_ISA */ } /* cy_setup */ -#endif - - -#ifdef CYCLOM_SHOW_STATUS -static void -show_status(int line_num) -{ - unsigned char *base_addr; - int card,chip,channel,index; - struct cyclades_port * info; - unsigned long flags; - - info = &cy_port[line_num]; - card = info->card; - index = cy_card[card].bus_index; - channel = (info->line) - (cy_card[card].first_line); - chip = channel>>2; - channel &= 0x03; - printk(" card %d, chip %d, channel %d\n", card, chip, channel);/**/ - - printk(" cy_card\n"); - printk(" irq base_addr num_chips first_line = %d %lx %d %d\n", - cy_card[card].irq, (long)cy_card[card].base_addr, - cy_card[card].num_chips, cy_card[card].first_line); - - printk(" cy_port\n"); - printk(" card line flags = %d %d %x\n", - info->card, info->line, info->flags); - printk(" *tty read_status_mask timeout xmit_fifo_size ", - printk("= %lx %x %x %x\n", - (long)info->tty, info->read_status_mask, - info->timeout, info->xmit_fifo_size); - printk(" cor1,cor2,cor3,cor4,cor5 = %x %x %x %x %x\n", - info->cor1, info->cor2, info->cor3, info->cor4, info->cor5); - printk(" tbpr,tco,rbpr,rco = %d %d %d %d\n", - info->tbpr, info->tco, info->rbpr, info->rco); - printk(" close_delay event count = %d %d %d\n", - info->close_delay, info->event, info->count); - printk(" x_char blocked_open = %x %x\n", - info->x_char, info->blocked_open); - printk(" session pgrp open_wait = %lx %lx %lx\n", - info->session, info->pgrp, (long)info->open_wait); - - CY_LOCK(info, flags); - - base_addr = (unsigned char*) - (cy_card[card].base_addr - + (cy_chip_offset[chip]<: Detect 1000baseT cards */ #include @@ -70,7 +71,10 @@ #ifndef PCI_VENDOR_ID_ALTEON #define PCI_VENDOR_ID_ALTEON 0x12ae -#define PCI_DEVICE_ID_ALTEON_ACENIC 0x0001 +#endif +#ifndef PCI_DEVICE_ID_ALTEON_ACENIC_FIBRE +#define PCI_DEVICE_ID_ALTEON_ACENIC_FIBRE 0x0001 +#define PCI_DEVICE_ID_ALTEON_ACENIC_COPPER 0x0002 #endif #ifndef PCI_DEVICE_ID_3COM_3C985 #define PCI_DEVICE_ID_3COM_3C985 0x0001 @@ -105,6 +109,12 @@ #endif +#if (LINUX_VERSION_CODE < 0x02030d) +#define pci_resource_start(dev, bar) dev->base_address[bar] +#elif (LINUX_VERSION_CODE < 0x02032c) +#define pci_resource_start(dev, bar) dev->resource[bar].start +#endif + #if (LINUX_VERSION_CODE < 0x02030e) #define net_device device #endif @@ -379,7 +389,7 @@ static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1}; static const char __initdata *version = - "acenic.c: v0.42 03/02/2000 Jes Sorensen, linux-acenic@SunSITE.auc.dk\n" + "acenic.c: v0.44 05/11/2000 Jes Sorensen, linux-acenic@SunSITE.auc.dk\n" " http://home.cern.ch/~jes/gige/acenic.html\n"; static struct net_device *root_dev = NULL; @@ -414,7 +424,8 @@ while ((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET<<8, pdev))) { if (!((pdev->vendor == PCI_VENDOR_ID_ALTEON) && - (pdev->device == PCI_DEVICE_ID_ALTEON_ACENIC)) && + ((pdev->device == PCI_DEVICE_ID_ALTEON_ACENIC_FIBRE) || + (pdev->device == PCI_DEVICE_ID_ALTEON_ACENIC_COPPER)) ) && !((pdev->vendor == PCI_VENDOR_ID_3COM) && (pdev->device == PCI_DEVICE_ID_3COM_3C985)) && !((pdev->vendor == PCI_VENDOR_ID_NETGEAR) && @@ -494,11 +505,7 @@ * dev->base_addr since it was means for I/O port * addresses but who gives a damn. */ -#if (LINUX_VERSION_CODE < 0x02030d) - dev->base_addr = pdev->base_address[0]; -#else - dev->base_addr = pdev->resource[0].start; -#endif + dev->base_addr = pci_resource_start(pdev, 0); ap->regs = (struct ace_regs *)ioremap(dev->base_addr, 0x4000); if (!ap->regs) { printk(KERN_ERR "%s: Unable to map I/O register, " @@ -717,10 +724,7 @@ { ace_module_cleanup(); } -#endif - - -#if (LINUX_VERSION_CODE >= 0x02032a) +#else module_init(ace_module_init); module_exit(ace_module_cleanup); #endif @@ -1087,11 +1091,17 @@ #endif writel(tmp, ®s->PciState); +#if 0 + /* + * I have received reports from people having problems when this + * bit is enabled. + */ if (!(ap->pci_command & PCI_COMMAND_FAST_BACK)) { printk(KERN_INFO " Enabling PCI Fast Back to Back\n"); ap->pci_command |= PCI_COMMAND_FAST_BACK; pci_write_config_word(ap->pdev, PCI_COMMAND, ap->pci_command); } +#endif /* * Initialize the generic info block and the command+event rings @@ -1760,16 +1770,23 @@ case E_LNK_STATE: { u16 code = ap->evt_ring[evtcsm].code; - if (code == E_C_LINK_UP) { + switch (code) { + case E_C_LINK_UP: printk(KERN_WARNING "%s: Optical link UP\n", dev->name); - } - else if (code == E_C_LINK_DOWN) + break; + case E_C_LINK_DOWN: printk(KERN_WARNING "%s: Optical link DOWN\n", dev->name); - else + break; + case E_C_LINK_10_100: + printk(KERN_WARNING "%s: 10/100BaseT link " + "UP\n", dev->name); + break; + default: printk(KERN_ERR "%s: Unknown optical link " "state %02x\n", dev->name, code); + } break; } case E_ERROR: @@ -2949,6 +2966,6 @@ /* * Local variables: - * compile-command: "gcc -D__KERNEL__ -DMODULE -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -DMODVERSIONS -include ../../include/linux/modversions.h -c -o acenic.o acenic.c" + * compile-command: "gcc -D__SMP__ -D__KERNEL__ -DMODULE -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -DMODVERSIONS -include ../../include/linux/modversions.h -c -o acenic.o acenic.c" * End: */ diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/net/acenic.h linux/drivers/net/acenic.h --- v2.3.99-pre7/linux/drivers/net/acenic.h Tue Mar 7 14:32:26 2000 +++ linux/drivers/net/acenic.h Fri May 12 11:38:35 2000 @@ -324,7 +324,7 @@ #define E_LNK_STATE 0x06 #define E_C_LINK_UP 0x01 #define E_C_LINK_DOWN 0x02 -#define E_C_LINK_UP_FAST 0x03 +#define E_C_LINK_10_100 0x03 #define E_ERROR 0x07 #define E_C_ERR_INVAL_CMD 0x01 diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/net/acenic_firmware.h linux/drivers/net/acenic_firmware.h --- v2.3.99-pre7/linux/drivers/net/acenic_firmware.h Sat Feb 12 11:22:10 2000 +++ linux/drivers/net/acenic_firmware.h Fri May 12 11:38:35 2000 @@ -5,17 +5,17 @@ */ #define tigonFwReleaseMajor 0xc #define tigonFwReleaseMinor 0x4 -#define tigonFwReleaseFix 0x5 +#define tigonFwReleaseFix 0xb #define tigonFwStartAddr 0x00004000 #define tigonFwTextAddr 0x00004000 -#define tigonFwTextLen 0x11190 -#define tigonFwRodataAddr 0x00015190 +#define tigonFwTextLen 0x11140 +#define tigonFwRodataAddr 0x00015140 #define tigonFwRodataLen 0xac0 -#define tigonFwDataAddr 0x00015c80 +#define tigonFwDataAddr 0x00015c20 #define tigonFwDataLen 0x170 -#define tigonFwSbssAddr 0x00015df0 -#define tigonFwSbssLen 0x34 -#define tigonFwBssAddr 0x00015e30 +#define tigonFwSbssAddr 0x00015d90 +#define tigonFwSbssLen 0x38 +#define tigonFwBssAddr 0x00015dd0 #define tigonFwBssLen 0x2080 u32 tigonFwText[]; u32 tigonFwData[]; @@ -25,16 +25,16 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x10000003, 0x0, 0xd, 0xd, 0x3c1d0001, -0x8fbd5cb4, 0x3a0f021, 0x3c100000, 0x26104000, +0x8fbd5c54, 0x3a0f021, 0x3c100000, 0x26104000, 0xc00100c, 0x0, 0xd, 0x27bdffd8, 0x3c1cc000, 0x3c1b0013, 0x377bd800, 0xd021, 0x3c170013, 0x36f75418, 0x2e02021, 0x340583e8, 0xafbf0024, 0xc002488, 0xafb00020, 0xc0023e8, -0x0, 0x3c040001, 0x248451f4, 0x24050001, -0x2e03021, 0x3821, 0x3c100001, 0x26107eb0, +0x0, 0x3c040001, 0x248451a4, 0x24050001, +0x2e03021, 0x3821, 0x3c100001, 0x26107e50, 0xafb00010, 0xc002403, 0xafbb0014, 0x3c02000f, 0x3442ffff, 0x2021024, 0x362102b, 0x10400009, -0x24050003, 0x3c040001, 0x24845200, 0x2003021, +0x24050003, 0x3c040001, 0x248451b0, 0x2003021, 0x3603821, 0x3c020010, 0xafa20010, 0xc002403, 0xafa00014, 0x2021, 0x3405c000, 0x3c010001, 0x370821, 0xa02083b0, 0x3c010001, 0x370821, @@ -72,7 +72,7 @@ 0x0, 0x8ee20450, 0x8ee30454, 0xaee304fc, 0x8ee204fc, 0x2442e000, 0x2c422001, 0x1440000d, 0x26e40030, 0x8ee20450, 0x8ee30454, 0x3c040001, -0x2484520c, 0x3c050001, 0xafa00010, 0xafa00014, +0x248451bc, 0x3c050001, 0xafa00010, 0xafa00014, 0x8ee704fc, 0x34a5f000, 0xc002403, 0x603021, 0x26e40030, 0xc002488, 0x24050400, 0x27440080, 0xc002488, 0x24050080, 0x26e4777c, 0xc002488, @@ -82,7 +82,7 @@ 0x3442ca00, 0x2021, 0x24030002, 0xaee30074, 0xaee30070, 0xaee2006c, 0x240203e8, 0xaee20104, 0x24020001, 0xaee30100, 0xaee2010c, 0x3c030001, -0x641821, 0x90635c80, 0x2e41021, 0x24840001, +0x641821, 0x90635c20, 0x2e41021, 0x24840001, 0xa043009c, 0x2c82000f, 0x1440fff8, 0x0, 0x8f820040, 0x2e41821, 0x24840001, 0x21702, 0x24420030, 0xa062009c, 0x2e41021, 0xa040009c, @@ -128,7 +128,7 @@ 0x8ee24e30, 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x54c0000c, -0xaee90608, 0x3c040001, 0x24845218, 0xafa00010, +0xaee90608, 0x3c040001, 0x248451c8, 0xafa00010, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f000, 0x8001223, 0x0, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, @@ -154,21 +154,21 @@ 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, 0x14c0001b, 0x0, -0x3c040001, 0x24845220, 0xafa00010, 0xafa00014, +0x3c040001, 0x248451d0, 0xafa00010, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f001, 0x8ee201b0, 0x24420001, 0xaee201b0, -0x8001223, 0x8ee201b0, 0x3c040001, 0x2484522c, +0x8001223, 0x8ee201b0, 0x3c040001, 0x248451dc, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f005, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x8ee201ac, 0x8ee20160, 0x3c040001, -0x24845238, 0x3405f001, 0x24420001, 0xaee20160, +0x248451e8, 0x3405f001, 0x24420001, 0xaee20160, 0x8ee20160, 0x3021, 0x3821, 0xafa00010, 0xc002403, 0xafa00014, 0x8001238, 0x0, 0x3c020001, 0x2442f5a8, 0x21100, 0x21182, 0x431025, 0x3c010001, 0xac221278, 0x96e2045a, 0x30420003, 0x10400025, 0x3c050fff, 0x8ee204c8, 0x34a5ffff, 0x34420a00, 0xaee204c8, 0x8ee304c8, -0x3c040001, 0x24845244, 0x24020001, 0xa2e204ec, +0x3c040001, 0x248451f4, 0x24020001, 0xa2e204ec, 0xa2e204ed, 0x3c020002, 0x621825, 0x3c020001, 0x2442a390, 0x451024, 0x21082, 0xaee304c8, 0x3c030800, 0x431025, 0x3c010001, 0xac221220, @@ -211,7 +211,7 @@ 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x54c0000c, 0xaee90608, 0x3c040001, -0x24845218, 0xafa00010, 0xafa00014, 0x8ee60608, +0x248451c8, 0xafa00010, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f000, 0x800136d, 0x0, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, @@ -236,17 +236,17 @@ 0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, -0x14c0001b, 0x0, 0x3c040001, 0x24845220, +0x14c0001b, 0x0, 0x3c040001, 0x248451d0, 0xafa00010, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f001, 0x8ee201b0, 0x24420001, 0xaee201b0, 0x800136d, 0x8ee201b0, -0x3c040001, 0x2484522c, 0xafa00014, 0x8ee60608, +0x3c040001, 0x248451dc, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f005, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x8ee201ac, -0x8ee20160, 0x3c040001, 0x24845238, 0x3405f002, +0x8ee20160, 0x3c040001, 0x248451e8, 0x3405f002, 0x24420001, 0xaee20160, 0x8ee20160, 0x3021, 0x3821, 0xafa00010, 0xc002403, 0xafa00014, -0x96e6047a, 0x96e7046a, 0x3c040001, 0x24845250, +0x96e6047a, 0x96e7046a, 0x3c040001, 0x24845200, 0x24050012, 0xafa00010, 0xc002403, 0xafa00014, 0xc004500, 0x0, 0xc002318, 0x0, 0x3c060001, 0x34c63800, 0xaee00608, 0xaf400228, @@ -289,7 +289,7 @@ 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x54c0000c, 0xaee90608, 0x3c040001, -0x24845218, 0xafa00010, 0xafa00014, 0x8ee60608, +0x248451c8, 0xafa00010, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f000, 0x80014a5, 0x0, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, @@ -314,11 +314,11 @@ 0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, -0x14c0001b, 0x0, 0x3c040001, 0x24845220, +0x14c0001b, 0x0, 0x3c040001, 0x248451d0, 0xafa00010, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f001, 0x8ee201b0, 0x24420001, 0xaee201b0, 0x80014a5, 0x8ee201b0, -0x3c040001, 0x2484522c, 0xafa00014, 0x8ee60608, +0x3c040001, 0x248451dc, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f005, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x8ee201ac, 0x8ee20154, 0x24420001, 0xaee20154, 0xc0014dc, @@ -340,7 +340,7 @@ 0xaee07b8c, 0xaee07b84, 0x3c010001, 0x370821, 0xac2083bc, 0x3c010001, 0x370821, 0x3e00008, 0xa02083b9, 0x27bdffd8, 0xafbf0024, 0xafb00020, -0x8f820054, 0x3c030001, 0x8c635d38, 0x24420067, +0x8f820054, 0x3c030001, 0x8c635cd8, 0x24420067, 0x1060000d, 0xaf820058, 0x3c020001, 0x571021, 0x904283b8, 0x10400005, 0x3c030200, 0x3c010001, 0x370821, 0x8001503, 0xa02083b8, 0x8ee20000, @@ -358,7 +358,7 @@ 0x0, 0x3c030001, 0x771821, 0x8c6383d4, 0x8f8200b4, 0x1462007c, 0x0, 0x3c070001, 0xf73821, 0x8ce783d0, 0x8f8200b0, 0x3c040001, -0x248452c0, 0xafa00014, 0xafa20010, 0x8f8600b0, +0x24845270, 0xafa00014, 0xafa20010, 0x8f8600b0, 0x3c050005, 0xc002403, 0x34a50900, 0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830104, 0x8f8200b0, 0x34420001, 0xaf8200b0, 0xaf830104, 0x8f830120, @@ -386,10 +386,10 @@ 0xac820000, 0x24020001, 0xac820004, 0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201e4, 0x3c070001, 0xf73821, 0x8ce783d0, 0x24420001, -0xaee201e4, 0x8ee201e4, 0x3c040001, 0x248452cc, +0xaee201e4, 0x8ee201e4, 0x3c040001, 0x2484527c, 0x80015bd, 0xafa00010, 0x8f820104, 0x3c010001, 0x370821, 0xac2283d0, 0x8f8200b4, 0x3c070001, -0xf73821, 0x8ce783d0, 0x3c040001, 0x248452d4, +0xf73821, 0x8ce783d0, 0x3c040001, 0x24845284, 0x3c010001, 0x370821, 0xac2283d4, 0xafa00010, 0xafa00014, 0x8f8600b0, 0x3c050005, 0xc002403, 0x34a50900, 0x80015cc, 0x0, 0x8f820104, @@ -422,7 +422,7 @@ 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, 0x5600000b, 0x24100001, -0x8ee204e4, 0x3c040001, 0x248452dc, 0xafa00014, +0x8ee204e4, 0x3c040001, 0x2484528c, 0xafa00014, 0xafa20010, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f006, 0x16000003, 0x24020001, 0x8001650, 0xa2e204f4, 0x8ee20170, 0x24420001, @@ -452,7 +452,7 @@ 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, 0x5600000b, 0x24100001, 0x8ee2724c, 0x3c040001, -0x248452e8, 0xafa00014, 0xafa20010, 0x8ee6724c, +0x24845298, 0xafa00014, 0xafa20010, 0x8ee6724c, 0x8f470280, 0x3c050009, 0xc002403, 0x34a5f008, 0x56000001, 0xaee00e1c, 0x8ee20174, 0x24420001, 0xaee20174, 0x8ee20174, 0x8ee24e24, 0x10400019, @@ -563,11 +563,11 @@ 0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa6, 0x0, 0x316300ff, 0x24020001, 0x14620003, 0x3c050009, 0x800197c, 0x24100001, 0x3c040001, -0x248452f4, 0xafa00010, 0xafa00014, 0x8f860120, +0x248452a4, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x800187b, 0x34a5f011, 0x3c040001, -0x24845300, 0xafa00010, 0xafa00014, 0x8f860120, +0x248452b0, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x34a5f010, 0xc002403, 0x8021, -0x800197c, 0x0, 0x3c040001, 0x2484530c, +0x800197c, 0x0, 0x3c040001, 0x248452bc, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0x8001975, 0x34a5f00f, 0x8ee20608, 0x8f430228, 0x24420001, 0x304900ff, 0x512300e2, 0xafa00010, @@ -598,7 +598,7 @@ 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x5600000c, 0xaee90608, -0x3c040001, 0x24845318, 0xafa00010, 0xafa00014, +0x3c040001, 0x248452c8, 0xafa00010, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f000, 0x800197c, 0x0, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, @@ -624,10 +624,10 @@ 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, 0x5600001d, 0x24100001, 0x3c040001, -0x24845320, 0xafa00010, 0xafa00014, 0x8ee60608, +0x248452d0, 0xafa00010, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f001, 0x8ee201b0, 0x24420001, 0xaee201b0, 0x800197c, -0x8ee201b0, 0x3c040001, 0x2484532c, 0xafa00014, +0x8ee201b0, 0x3c040001, 0x248452dc, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0x34a5f005, 0xc002403, 0x0, 0x8ee201ac, 0x8021, 0x24420001, 0xaee201ac, 0x8ee201ac, 0x1200000c, @@ -635,7 +635,7 @@ 0x8f420238, 0x8ee30158, 0x24630001, 0xaee30158, 0x8ee30158, 0x800198c, 0xaee27278, 0x24020001, 0x3c010001, 0x370821, 0xa02283b0, 0x3c020001, -0x8c425d38, 0x10400187, 0x0, 0x8ee27b84, +0x8c425cd8, 0x10400187, 0x0, 0x8ee27b84, 0x24430001, 0x284200c9, 0x144001a4, 0xaee37b84, 0x8ee204d4, 0x30420002, 0x14400119, 0xaee07b84, 0x8ee204d4, 0x3c030600, 0x34631000, 0x34420002, @@ -699,12 +699,12 @@ 0x56000006, 0x240b0001, 0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa6, 0x0, 0x316300ff, 0x24020001, 0x10620022, 0x0, 0x3c040001, -0x248452f4, 0xafa00010, 0xafa00014, 0x8f860120, +0x248452a4, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc002403, 0x34a5f011, -0x8001aad, 0x0, 0x3c040001, 0x24845300, +0x8001aad, 0x0, 0x3c040001, 0x248452b0, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc002403, 0x34a5f010, 0x8001aad, 0x0, -0x3c040001, 0x2484530c, 0xafa00014, 0x8ee60608, +0x3c040001, 0x248452bc, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f00f, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x8ee201ac, 0x8ee2015c, 0x24420001, 0xaee2015c, 0x8ee2015c, @@ -741,7 +741,7 @@ 0xaf820044, 0x8f820044, 0x34420040, 0xaf820044, 0x8ee27b88, 0x24430001, 0x28421389, 0x14400005, 0xaee37b88, 0x8f820044, 0x38420020, 0xaf820044, -0xaee07b88, 0xc0045f4, 0x0, 0x8fbf0024, +0xaee07b88, 0xc004603, 0x0, 0x8fbf0024, 0x8fb00020, 0x3e00008, 0x27bd0028, 0x27bdffb8, 0xafbf0044, 0xafb60040, 0xafb5003c, 0xafb40038, 0xafb30034, 0xafb20030, 0xafb1002c, 0xafb00028, @@ -751,18 +751,18 @@ 0xaee2016c, 0x80022f4, 0x8ee2016c, 0x32c20001, 0x10400004, 0x24020001, 0xaf820064, 0x80022f4, 0x0, 0x32c20002, 0x1440000c, 0x3c050003, -0x3c040001, 0x248453a4, 0x34a50001, 0x2c03021, +0x3c040001, 0x24845354, 0x34a50001, 0x2c03021, 0x3821, 0xafa00010, 0xc002403, 0xafa00014, 0x2402fff8, 0x80022f4, 0xaf820064, 0x8f43022c, 0x8f42010c, 0x5062000c, 0xafa00010, 0x8f42022c, 0x21080, 0x5a1021, 0x8c420300, 0xafa20020, 0x8f42022c, 0x24070001, 0x24420001, 0x3042003f, -0x8001b80, 0xaf42022c, 0x3c040001, 0x248453b0, +0x8001b80, 0xaf42022c, 0x3c040001, 0x24845360, 0xafa00014, 0x8f46022c, 0x8f47010c, 0x3c050003, 0xc002403, 0x34a5f01f, 0x3821, 0x14e00003, 0x0, 0x80022ed, 0xaf960064, 0x93a20020, 0x2443ffff, 0x2c620011, 0x10400658, 0x31080, -0x3c010001, 0x220821, 0x8c225468, 0x400008, +0x3c010001, 0x220821, 0x8c225418, 0x400008, 0x0, 0x8fa20020, 0x30420fff, 0xaee20e0c, 0x8f820060, 0x34420200, 0xaf820060, 0x8ee20118, 0x24420001, 0xaee20118, 0x80022e8, 0x8ee20118, @@ -778,7 +778,7 @@ 0x8f840054, 0x41442, 0x41c82, 0x431021, 0x41cc2, 0x431023, 0x41d02, 0x431021, 0x41d42, 0x431023, 0x8001bd0, 0xaee20078, -0x3c040001, 0x248453bc, 0xafa00014, 0x8fa60020, +0x3c040001, 0x2484536c, 0xafa00014, 0x8fa60020, 0x3c050003, 0xc002403, 0x34a50004, 0x8ee20110, 0x24420001, 0xaee20110, 0x80022e8, 0x8ee20110, 0x27440212, 0xc0022fe, 0x24050006, 0x3049001f, @@ -794,7 +794,7 @@ 0x2c820080, 0x1440fff8, 0x410c0, 0x4c10010, 0x618c0, 0x610c0, 0x571821, 0x8c63737c, 0x571021, 0xafa30010, 0x8c427380, 0x3c040001, -0x248453c8, 0xafa20014, 0x8f470214, 0x3c050003, +0x24845378, 0xafa20014, 0x8f470214, 0x3c050003, 0xc002403, 0x34a50013, 0x8001c90, 0x3c020800, 0x97440212, 0x771021, 0xa444737e, 0x8f440214, 0x771021, 0x2e31821, 0xac447380, 0x34028000, @@ -812,7 +812,7 @@ 0x24840001, 0x2c820080, 0x1440fff8, 0x410c0, 0x4c10023, 0x618c0, 0x910c0, 0x571821, 0x8c63727c, 0x571021, 0xafa30010, 0x8c427280, -0x3c040001, 0x248453d4, 0xafa20014, 0x8f470214, +0x3c040001, 0x24845384, 0xafa20014, 0x8f470214, 0x3c050003, 0xc002403, 0x34a5f017, 0x8001c90, 0x3c020800, 0x8f430210, 0xb71021, 0xac43777c, 0x8f430214, 0xb71021, 0xac437780, 0x3c020001, @@ -887,13 +887,13 @@ 0x2e22021, 0xac8a0000, 0xac8c0004, 0x54e00006, 0x240b0001, 0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa6, 0x0, 0x316300ff, 0x24020001, -0x10620022, 0x0, 0x3c040001, 0x248453e0, +0x10620022, 0x0, 0x3c040001, 0x24845390, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc002403, 0x34a5f011, 0x8001da0, -0x0, 0x3c040001, 0x248453ec, 0xafa00014, +0x0, 0x3c040001, 0x2484539c, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc002403, 0x34a5f010, 0x8001da0, 0x0, 0x3c040001, -0x248453f8, 0xafa00014, 0x8ee60608, 0x8f470228, +0x248453a8, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f00f, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x8ee201ac, 0x8ee20124, 0x24420001, 0xaee20124, 0x8001f97, 0x8ee20124, @@ -908,7 +908,7 @@ 0x1221004, 0x21027, 0x621824, 0xaf830228, 0x910c0, 0x2e21821, 0x3402c000, 0x8001e4e, 0xa462727c, 0x8f420214, 0xafa20010, 0x910c0, -0x571021, 0x8c42727c, 0x3c040001, 0x24845404, +0x571021, 0x8c42727c, 0x3c040001, 0x248453b4, 0x3c050003, 0xafa20014, 0x8f470210, 0x34a5f01c, 0xc002403, 0x1203021, 0x8001e83, 0x3c020800, 0xb71021, 0x9443727e, 0x97420212, 0x14620019, @@ -936,7 +936,7 @@ 0x910c0, 0x2e41821, 0x3402c000, 0x15000015, 0xa462737c, 0x910c0, 0x2e21821, 0x34028000, 0x8001e4e, 0xa462727c, 0x571021, 0x8c42727c, -0x3c040001, 0x24845410, 0x3c050003, 0xafa20010, +0x3c040001, 0x248453c0, 0x3c050003, 0xafa20010, 0x710c0, 0x571021, 0x8c42737c, 0x34a5001e, 0x1203021, 0xc002403, 0xafa20014, 0x8001e83, 0x3c020800, 0x2021, 0x428c0, 0xb71021, @@ -1012,12 +1012,12 @@ 0xac8a0000, 0xac8c0004, 0x54e00006, 0x240b0001, 0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa6, 0x0, 0x316300ff, 0x24020001, 0x10620022, -0x0, 0x3c040001, 0x248453e0, 0xafa00010, +0x0, 0x3c040001, 0x24845390, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc002403, 0x34a5f011, 0x8001f93, 0x0, -0x3c040001, 0x248453ec, 0xafa00014, 0x8f860120, +0x3c040001, 0x2484539c, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc002403, 0x34a5f010, -0x8001f93, 0x0, 0x3c040001, 0x248453f8, +0x8001f93, 0x0, 0x3c040001, 0x248453a8, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f00f, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x8ee201ac, 0x8ee20128, 0x24420001, @@ -1029,7 +1029,7 @@ 0x8f820228, 0xaee204dc, 0x2402ffff, 0xaf820228, 0x24020001, 0x8001fbe, 0xa2e204d8, 0x92e204d8, 0x5040000c, 0xa2e004d8, 0x8ee204dc, 0xaf820228, -0x8001fbe, 0xa2e004d8, 0x3c040001, 0x24845418, +0x8001fbe, 0xa2e004d8, 0x3c040001, 0x248453c8, 0xafa00014, 0x8fa60020, 0x3c050003, 0xc002403, 0x34a5f009, 0x8ee2013c, 0x24420001, 0xaee2013c, 0x80022e8, 0x8ee2013c, 0x8fa20020, 0x21200, @@ -1040,7 +1040,7 @@ 0x370821, 0xa02283b2, 0x8001fea, 0xaee40108, 0x8f820220, 0x3c0308ff, 0x3463fff7, 0x431024, 0xaf820220, 0x3c010001, 0x370821, 0xa02083b2, -0x8001fea, 0xaee40108, 0x3c040001, 0x24845424, +0x8001fea, 0xaee40108, 0x3c040001, 0x248453d4, 0xafa00014, 0x8fa60020, 0x3c050003, 0xc002403, 0x34a5f00a, 0x8ee2012c, 0x24420001, 0xaee2012c, 0x80022e8, 0x8ee2012c, 0x8fa20020, 0x21200, @@ -1052,13 +1052,13 @@ 0x571021, 0x904283b2, 0x3c010001, 0x370821, 0x1440000e, 0xa02083b3, 0x8f820220, 0x3c0308ff, 0x3463fff7, 0x431024, 0x8002018, 0xaf820220, -0x3c040001, 0x24845430, 0xafa00014, 0x8fa60020, +0x3c040001, 0x248453e0, 0xafa00014, 0x8fa60020, 0x3c050003, 0xc002403, 0x34a5f00b, 0x8ee20114, 0x24420001, 0xaee20114, 0x80022e8, 0x8ee20114, 0x27840208, 0x27450200, 0xc00249a, 0x24060008, 0x26e40094, 0x27450200, 0xc00249a, 0x24060008, 0x8ee20134, 0x24420001, 0xaee20134, 0x80022e8, -0x8ee20134, 0x8f460248, 0x2021, 0xc0050e0, +0x8ee20134, 0x8f460248, 0x2021, 0xc005108, 0x24050004, 0x8ee20130, 0x24420001, 0xaee20130, 0x80022e8, 0x8ee20130, 0x8ef301cc, 0x8ef401d0, 0x8ef501d8, 0x8ee20140, 0x26e40030, 0x24420001, @@ -1072,7 +1072,7 @@ 0xaee20104, 0xaee40100, 0xaee3010c, 0x8f820220, 0x30420008, 0x10400004, 0x0, 0xaee30108, 0x8002061, 0x2021, 0xaee40108, 0x2021, -0x3c030001, 0x641821, 0x90635c90, 0x2e41021, +0x3c030001, 0x641821, 0x90635c30, 0x2e41021, 0x24840001, 0xa043009c, 0x2c82000f, 0x1440fff8, 0x0, 0x8f820040, 0x2e41821, 0x24840001, 0x21702, 0x24420030, 0xa062009c, 0x2e41021, @@ -1152,13 +1152,13 @@ 0x2e22021, 0xac8a0000, 0xac8c0004, 0x54e00006, 0x240b0001, 0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa6, 0x0, 0x316300ff, 0x24020001, -0x10620022, 0x0, 0x3c040001, 0x248453e0, +0x10620022, 0x0, 0x3c040001, 0x24845390, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc002403, 0x34a5f011, 0x80021c4, -0x0, 0x3c040001, 0x248453ec, 0xafa00014, +0x0, 0x3c040001, 0x2484539c, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc002403, 0x34a5f010, 0x80021c4, 0x0, 0x3c040001, -0x248453f8, 0xafa00014, 0x8ee60608, 0x8f470228, +0x248453a8, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f00f, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x8ee201ac, 0x8ee20120, 0x24420001, 0xaee20120, 0x8ee20120, 0x8ee20168, @@ -1168,7 +1168,7 @@ 0x8f820220, 0x30420008, 0x14400002, 0x24020001, 0x24020002, 0xaee20108, 0x8ee2011c, 0x24420001, 0xaee2011c, 0x80022e8, 0x8ee2011c, 0x3c040001, -0x2484543c, 0xafa00010, 0xafa00014, 0x8fa60020, +0x248453ec, 0xafa00010, 0xafa00014, 0x8fa60020, 0x3c050003, 0xc002403, 0x34a5f00f, 0x93a20020, 0x3c030700, 0x34631000, 0x431025, 0xafa20018, 0x8ee20608, 0x8f430228, 0x24420001, 0x304900ff, @@ -1199,7 +1199,7 @@ 0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, -0x54e0000c, 0xaee90608, 0x3c040001, 0x24845444, +0x54e0000c, 0xaee90608, 0x3c040001, 0x248453f4, 0xafa00010, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f000, 0x80022e0, 0x0, 0x8f830120, 0x27623800, 0x24660020, @@ -1225,11 +1225,11 @@ 0x8ee24e30, 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, 0x14e0001b, -0x0, 0x3c040001, 0x2484544c, 0xafa00010, +0x0, 0x3c040001, 0x248453fc, 0xafa00010, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f001, 0x8ee201b0, 0x24420001, 0xaee201b0, 0x80022e0, 0x8ee201b0, 0x3c040001, -0x24845458, 0xafa00014, 0x8ee60608, 0x8f470228, +0x24845408, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f005, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x8ee201ac, 0x8ee20150, 0x24420001, 0xaee20150, 0x8ee20150, 0x8ee20160, @@ -1256,7 +1256,7 @@ 0xaf82011c, 0x8fbf0010, 0x3e00008, 0x27bd0018, 0x27bdffe0, 0xafbf0018, 0x8f820104, 0xafa20010, 0x8f820100, 0x3c050002, 0xafa20014, 0x8f8600b0, -0x8f87011c, 0x3c040001, 0x24845510, 0xc002403, +0x8f87011c, 0x3c040001, 0x248454c0, 0xc002403, 0x34a5f000, 0x8f8300b0, 0x3c027f00, 0x621824, 0x3c020400, 0x10620029, 0x43102b, 0x14400008, 0x3c022000, 0x3c020100, 0x10620024, 0x3c020200, @@ -1273,7 +1273,7 @@ 0x27bd0020, 0x27bdffe0, 0xafbf001c, 0xafb00018, 0x8f820120, 0xafa20010, 0x8f820124, 0x3c050001, 0xafa20014, 0x8f8600a0, 0x8f87011c, 0x3c040001, -0x2484551c, 0xc002403, 0x34a5f000, 0x8f8300a0, +0x248454cc, 0xc002403, 0x34a5f000, 0x8f8300a0, 0x3c027f00, 0x621824, 0x3c020400, 0x10620053, 0x8021, 0x43102b, 0x14400008, 0x3c042000, 0x3c020100, 0x1062004d, 0x3c020200, 0x1062003a, @@ -1298,43 +1298,43 @@ 0xaee2019c, 0x80023e3, 0x8ee2019c, 0x8f8200a0, 0x34420001, 0xaf8200a0, 0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020, 0x0, 0x3c020001, -0x8c425cb8, 0x27bdffe8, 0xafbf0014, 0x14400012, -0xafb00010, 0x3c100001, 0x26105e30, 0x2002021, +0x8c425c58, 0x27bdffe8, 0xafbf0014, 0x14400012, +0xafb00010, 0x3c100001, 0x26105dd0, 0x2002021, 0xc002488, 0x24052000, 0x26021fe0, 0x3c010001, -0xac225df4, 0x3c010001, 0xac225df0, 0xaf420250, +0xac225d94, 0x3c010001, 0xac225d90, 0xaf420250, 0x24022000, 0xaf500254, 0xaf420258, 0x24020001, -0x3c010001, 0xac225cb8, 0x8fbf0014, 0x8fb00010, -0x3e00008, 0x27bd0018, 0x3c030001, 0x8c635df4, +0x3c010001, 0xac225c58, 0x8fbf0014, 0x8fb00010, +0x3e00008, 0x27bd0018, 0x3c030001, 0x8c635d94, 0x8c820000, 0x8fa80010, 0x8fa90014, 0xac620000, -0x3c020001, 0x8c425df4, 0x8c830004, 0xac430004, +0x3c020001, 0x8c425d94, 0x8c830004, 0xac430004, 0xac450008, 0x8f840054, 0x2443ffe0, 0xac460010, 0xac470014, 0xac480018, 0xac49001c, 0x3c010001, -0xac235df4, 0xac44000c, 0x3c020001, 0x24425e30, +0xac235d94, 0xac44000c, 0x3c020001, 0x24425dd0, 0x62182b, 0x10600005, 0x0, 0x3c020001, -0x8c425df0, 0x3c010001, 0xac225df4, 0x3c030001, -0x8c635df4, 0x3c020001, 0x8c425ca0, 0xac620000, -0x3c030001, 0x8c635df4, 0x3c020001, 0x8c425ca0, +0x8c425d90, 0x3c010001, 0xac225d94, 0x3c030001, +0x8c635d94, 0x3c020001, 0x8c425c40, 0xac620000, +0x3c030001, 0x8c635d94, 0x3c020001, 0x8c425c40, 0xac620004, 0x3e00008, 0xaf430250, 0x3c030001, -0x8c635df4, 0x3c020001, 0x8c425ca0, 0x27bdffd0, +0x8c635d94, 0x3c020001, 0x8c425c40, 0x27bdffd0, 0xafb40020, 0x8fb40040, 0xafb00010, 0x808021, 0xafb50024, 0x8fb50044, 0x8fa40048, 0xafb10014, 0xa08821, 0xafbf0028, 0xafb3001c, 0xafb20018, -0xac620000, 0x3c050001, 0x8ca55df4, 0x3c020001, -0x8c425ca0, 0xc09021, 0xe09821, 0x10800006, +0xac620000, 0x3c050001, 0x8ca55d94, 0x3c020001, +0x8c425c40, 0xc09021, 0xe09821, 0x10800006, 0xaca20004, 0x24a50008, 0xc002490, 0x24060018, 0x800244e, 0x0, 0x24a40008, 0xc002488, -0x24050018, 0x3c020001, 0x8c425df4, 0x3c050001, -0x24a55e30, 0x2442ffe0, 0x3c010001, 0xac225df4, +0x24050018, 0x3c020001, 0x8c425d94, 0x3c050001, +0x24a55dd0, 0x2442ffe0, 0x3c010001, 0xac225d94, 0x45102b, 0x10400005, 0x0, 0x3c020001, -0x8c425df0, 0x3c010001, 0xac225df4, 0x3c030001, -0x8c635df4, 0x8e020000, 0xac620000, 0x3c030001, -0x8c635df4, 0x8e020004, 0xac620004, 0xac710008, -0x8f840054, 0x2462ffe0, 0x3c010001, 0xac225df4, +0x8c425d90, 0x3c010001, 0xac225d94, 0x3c030001, +0x8c635d94, 0x8e020000, 0xac620000, 0x3c030001, +0x8c635d94, 0x8e020004, 0xac620004, 0xac710008, +0x8f840054, 0x2462ffe0, 0x3c010001, 0xac225d94, 0x45102b, 0xac720010, 0xac730014, 0xac740018, 0xac75001c, 0x10400005, 0xac64000c, 0x3c020001, -0x8c425df0, 0x3c010001, 0xac225df4, 0x3c030001, -0x8c635df4, 0x3c020001, 0x8c425ca0, 0xac620000, -0x3c030001, 0x8c635df4, 0x3c020001, 0x8c425ca0, +0x8c425d90, 0x3c010001, 0xac225d94, 0x3c030001, +0x8c635d94, 0x3c020001, 0x8c425c40, 0xac620000, +0x3c030001, 0x8c635d94, 0x3c020001, 0x8c425c40, 0xac620004, 0xaf430250, 0x8fbf0028, 0x8fb50024, 0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0030, 0x10a00005, @@ -1380,7 +1380,7 @@ 0x210c0, 0x24424e38, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1520000a, 0x3c040001, 0xafab0010, 0x8ee27264, 0x3c040001, -0x24845780, 0x3c050004, 0xafa20014, 0x8ee604e4, +0x24845730, 0x3c050004, 0xafa20014, 0x8ee604e4, 0x80028be, 0x34a5f114, 0x8ee27264, 0x34843800, 0x3641821, 0x24420010, 0x43102b, 0x14400073, 0x0, 0x8ee27264, 0x24480010, 0x3641021, @@ -1409,7 +1409,7 @@ 0x210c0, 0x24424e38, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1520000a, 0x2508fffc, 0xafab0010, 0x8ee27264, 0x3c040001, -0x24845780, 0x3c050004, 0xafa20014, 0x8ee604e4, +0x24845730, 0x3c050004, 0xafa20014, 0x8ee604e4, 0x80028be, 0x34a5f125, 0x34028100, 0xa5020000, 0x9582000e, 0x800261d, 0xa5020002, 0x8f850100, 0x27623000, 0x24a60020, 0xc2102b, 0x50400001, @@ -1436,7 +1436,7 @@ 0x8ee24e28, 0x210c0, 0x24424e38, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1520000a, 0x34028100, 0xafab0010, 0x8ee27264, -0x3c040001, 0x24845780, 0x3c050004, 0xafa20014, +0x3c040001, 0x24845730, 0x3c050004, 0xafa20014, 0x8ee604e4, 0x80028be, 0x34a5f015, 0x8ee37264, 0xa462000c, 0x8ee37264, 0x9582000e, 0xa462000e, 0x8002681, 0x24e70004, 0x8f840100, 0x27623000, @@ -1462,7 +1462,7 @@ 0x24420001, 0xaee24e28, 0x8ee24e28, 0x210c0, 0x24424e38, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x15200009, 0x3c050004, -0xafab0010, 0x8ee27264, 0x3c040001, 0x24845780, +0xafab0010, 0x8ee27264, 0x3c040001, 0x24845730, 0xafa20014, 0x8ee604e4, 0x80028be, 0x34a5f004, 0x8ee2725c, 0x30e7ffff, 0x471021, 0xaee2725c, 0x8ee204e4, 0x8ee304fc, 0x8ee47258, 0x21100, @@ -1482,7 +1482,7 @@ 0x8f8200f0, 0x24090001, 0x8fa30018, 0x8fa4001c, 0xac430000, 0xac440004, 0xaf8700f0, 0x15200012, 0xd1142, 0x8f8200f0, 0xafa20010, 0x8f8200f4, -0x3c040001, 0x2484578c, 0xafa20014, 0x8fa60018, +0x3c040001, 0x2484573c, 0xafa20014, 0x8fa60018, 0x8fa7001c, 0x3c050004, 0xc002403, 0x34a5f005, 0x8ee20088, 0x24420001, 0xaee20088, 0x8ee20088, 0x80028d3, 0xaee0725c, 0x30430003, 0x24020002, @@ -1524,7 +1524,7 @@ 0xaee24e28, 0x8ee24e28, 0x210c0, 0x24424e38, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1520000a, 0x3c040001, 0xafab0010, -0x8ee27264, 0x3c040001, 0x24845780, 0x3c050004, +0x8ee27264, 0x3c040001, 0x24845730, 0x3c050004, 0xafa20014, 0x8ee604e4, 0x80028be, 0x34a5f014, 0x8ee27264, 0x34843800, 0x3641821, 0x24420010, 0x43102b, 0x14400073, 0x0, 0x8ee27264, @@ -1553,7 +1553,7 @@ 0xaee24e28, 0x8ee24e28, 0x210c0, 0x24424e38, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1520000a, 0x2508fffc, 0xafab0010, -0x8ee27264, 0x3c040001, 0x24845780, 0x3c050004, +0x8ee27264, 0x3c040001, 0x24845730, 0x3c050004, 0xafa20014, 0x8ee604e4, 0x80028be, 0x34a5f015, 0x34028100, 0xa5020000, 0x9582000e, 0x800285f, 0xa5020002, 0x8f850100, 0x27623000, 0x24a60020, @@ -1580,7 +1580,7 @@ 0x24420001, 0xaee24e28, 0x8ee24e28, 0x210c0, 0x24424e38, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1520000a, 0x34028100, -0xafab0010, 0x8ee27264, 0x3c040001, 0x24845780, +0xafab0010, 0x8ee27264, 0x3c040001, 0x24845730, 0x3c050004, 0xafa20014, 0x8ee604e4, 0x80028be, 0x34a5f016, 0x8ee37264, 0xa462000c, 0x8ee37264, 0x9582000e, 0xa462000e, 0x80028c2, 0x24e70004, @@ -1606,7 +1606,7 @@ 0xaee24e28, 0x8ee24e28, 0x210c0, 0x24424e38, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1520000b, 0x3c050004, 0x3c040001, -0x24845798, 0xafab0010, 0xafa00014, 0x8ee604e4, +0x24845748, 0xafab0010, 0xafa00014, 0x8ee604e4, 0x34a5f017, 0xc002403, 0x30e7ffff, 0x80028e1, 0x0, 0x8ee27264, 0x3c050001, 0x30e4ffff, 0x441021, 0xaee27264, 0x8ee2725c, 0x8ee37264, @@ -1672,7 +1672,7 @@ 0x24420001, 0xaee24e28, 0x8ee24e28, 0x210c0, 0x24424e38, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1540000a, 0x24020001, -0xafa90010, 0x8ee27264, 0x3c040001, 0x24845780, +0xafa90010, 0x8ee27264, 0x3c040001, 0x24845730, 0x3c050004, 0xafa20014, 0x8ee604e4, 0x8002a4f, 0x34a5f204, 0xa2e204ed, 0x8ee204e8, 0x8ee304fc, 0x8ee47258, 0x3c060001, 0x34c63800, 0x3c010001, @@ -1706,7 +1706,7 @@ 0xaee24e28, 0x8ee24e28, 0x210c0, 0x24424e38, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1540000c, 0x30e5ffff, 0x3c040001, -0x24845798, 0x3c050004, 0xafa90010, 0xafa00014, +0x24845748, 0x3c050004, 0xafa90010, 0xafa00014, 0x8ee604e4, 0x34a5f237, 0xc002403, 0x30e7ffff, 0x8002a72, 0x0, 0x8ee27264, 0x451021, 0xaee27264, 0x8ee2726c, 0x8ee37264, 0x3c040001, @@ -1730,7 +1730,7 @@ 0x8f830108, 0x21140, 0x621821, 0xaf830108, 0xac800000, 0x8cc20018, 0x2443fffe, 0x2c620013, 0x104000c1, 0x31080, 0x3c010001, 0x220821, -0x8c2257c0, 0x400008, 0x0, 0x8ee204f0, +0x8c225770, 0x400008, 0x0, 0x8ee204f0, 0x471021, 0xaee204f0, 0x8ee204f0, 0x8f43023c, 0x43102b, 0x144000be, 0x0, 0x8ee304e4, 0x8ee204f8, 0x506200ba, 0xa2e004f4, 0x8f830120, @@ -1757,7 +1757,7 @@ 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, 0x5600000b, 0x24100001, 0x8ee204e4, -0x3c040001, 0x248457a4, 0xafa00014, 0xafa20010, +0x3c040001, 0x24845754, 0xafa00014, 0xafa20010, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f006, 0x16000003, 0x24020001, 0x8002b71, 0xa2e204f4, 0x8ee20170, 0x24420001, 0xaee20170, @@ -1778,7 +1778,7 @@ 0x8002b71, 0xaee20000, 0x8ee2014c, 0x3c010001, 0x370821, 0xa02083e0, 0x24420001, 0xaee2014c, 0x8002b71, 0x8ee2014c, 0x94c7000e, 0x8cc2001c, -0x3c040001, 0x248457b0, 0xafa60014, 0xafa20010, +0x3c040001, 0x24845760, 0xafa60014, 0xafa20010, 0x8cc60018, 0x3c050008, 0xc002403, 0x34a50910, 0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020, 0x27bdff98, 0xafbf0060, 0xafbe005c, 0xafb60058, @@ -1787,7 +1787,7 @@ 0xafa00024, 0x106203e7, 0xafa0002c, 0x3c1e0001, 0x37de3800, 0x3c0bffff, 0x8f930108, 0x8e620018, 0x8f830104, 0x2443fffe, 0x2c620014, 0x104003cf, -0x31080, 0x3c010001, 0x220821, 0x8c225810, +0x31080, 0x3c010001, 0x220821, 0x8c2257c0, 0x400008, 0x0, 0x9663000e, 0x8ee2725c, 0x8ee404f0, 0x431021, 0xaee2725c, 0x8e63001c, 0x96e20458, 0x24840001, 0xaee404f0, 0x24630001, @@ -1816,7 +1816,7 @@ 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020012, 0x240c0001, 0xac820000, 0xac8c0004, 0x5600000d, 0x24100001, 0x8ee204e4, -0x3c040001, 0x248457a4, 0xafa00014, 0xafa20010, +0x3c040001, 0x24845754, 0xafa00014, 0xafa20010, 0x8ee60608, 0x8f470228, 0x3c050009, 0x34a5f006, 0xc002403, 0xafab0038, 0x8fab0038, 0x1200030a, 0x240c0001, 0x8002f19, 0x0, 0x966c001c, @@ -2010,7 +2010,7 @@ 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020012, 0x240c0001, 0xac820000, 0xac8c0004, 0x5600000d, 0x24100001, -0x8ee204e4, 0x3c040001, 0x248457a4, 0xafa00014, +0x8ee204e4, 0x3c040001, 0x24845754, 0xafa00014, 0xafa20010, 0x8ee60608, 0x8f470228, 0x3c050009, 0x34a5f006, 0xc002403, 0xafab0038, 0x8fab0038, 0x16000003, 0x240c0001, 0x8002f5c, 0xa2ec04f4, @@ -2065,7 +2065,7 @@ 0x8821, 0x8f8200e4, 0x24110001, 0x8c430000, 0x8c440004, 0xafa30018, 0xafa4001c, 0x1620000e, 0x3c02ffff, 0x8f8200c4, 0xafa20010, 0x8f8200c8, -0x3c040001, 0x248458c0, 0xafa20014, 0x8f8600e0, +0x3c040001, 0x24845870, 0xafa20014, 0x8f8600e0, 0x8f8700e4, 0x3c050006, 0xc002403, 0x34a5f000, 0x80034cc, 0x0, 0x8fa3001c, 0x8fb20018, 0x3074ffff, 0x2694fffc, 0x621024, 0x10400058, @@ -2163,11 +2163,11 @@ 0x862021, 0xaee400c0, 0xaee500c4, 0x8ee20058, 0x24420001, 0xaee20058, 0x8ee20058, 0x8ee2007c, 0x24420001, 0xaee2007c, 0x8ee2007c, 0x8f8200e0, -0xafa20010, 0x8f8200e4, 0x3c040001, 0x248458c8, +0xafa20010, 0x8f8200e4, 0x3c040001, 0x24845878, 0xafa20014, 0x8fa60018, 0x8fa7001c, 0x3c050006, 0xc002403, 0x34a5f003, 0x80034cc, 0x0, 0x8ee25240, 0xafa20010, 0x8ee25244, 0x3c040001, -0x248458d4, 0xafa20014, 0x8ee60e10, 0x8ee70e18, +0x24845884, 0xafa20014, 0x8ee60e10, 0x8ee70e18, 0x3c050006, 0xc002403, 0x34a5f002, 0x8ee201c0, 0x24420001, 0xaee201c0, 0x8ee20000, 0x8ee301c0, 0x2403ffbf, 0x431024, 0x8003470, 0xaee20000, @@ -2219,7 +2219,7 @@ 0x50550003, 0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0xac960000, 0xac9e0004, 0x16200018, -0x3c050006, 0x8e020018, 0x3c040001, 0x248458e0, +0x3c050006, 0x8e020018, 0x3c040001, 0x24845890, 0xafa20010, 0x8e020000, 0x8e030004, 0x34a5f009, 0x2003021, 0xc002403, 0xafa30014, 0x93a20037, 0x10400216, 0x340f8100, 0x8e420004, 0x8e430008, @@ -2252,7 +2252,7 @@ 0x210c0, 0x24425038, 0x2e22021, 0xac960000, 0xac9e0004, 0x1620000d, 0x0, 0xa60c000a, 0xa60a000e, 0x8f820100, 0xafa20010, 0x8f820104, -0x3c040001, 0x248458ec, 0x3c050006, 0xafa20014, +0x3c040001, 0x2484589c, 0x3c050006, 0xafa20014, 0x8ee6724c, 0x800343b, 0x34a5f00b, 0x3c010001, 0x370821, 0xa02083c0, 0xadab0000, 0x8ee201d8, 0x8ee3724c, 0x2442ffff, 0xaee201d8, 0x8ee201d8, @@ -2284,7 +2284,7 @@ 0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0xac8e0000, 0xac9e0004, 0x5620000d, 0x24110001, -0x8ee2724c, 0x3c040001, 0x248458f8, 0xafa00014, +0x8ee2724c, 0x3c040001, 0x248458a8, 0xafa00014, 0xafa20010, 0x8ee6724c, 0x8f470280, 0x3c050009, 0x34a5f008, 0xc002403, 0xafae0048, 0x8fae0048, 0x56200001, 0xaee00e1c, 0x8ee20188, 0x24420001, @@ -2311,7 +2311,7 @@ 0x8ee24e30, 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0xac8e0000, 0xac9e0004, 0x1620000d, 0x0, 0x8ee2724c, -0x3c040001, 0x248458f8, 0xafa00014, 0xafa20010, +0x3c040001, 0x248458a8, 0xafa00014, 0xafa20010, 0x8ee6724c, 0x8f470280, 0x3c050009, 0x34a5f008, 0xc002403, 0xafae0048, 0x8fae0048, 0x8ee20174, 0x24420001, 0xaee20174, 0x8ee20174, 0x800346e, @@ -2341,7 +2341,7 @@ 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0xac960000, 0xac9e0004, 0x1620001d, 0x0, 0xa60c000a, 0x8f820100, 0xafa20010, 0x8f820104, -0x3c040001, 0x248458ec, 0x3c050006, 0xafa20014, +0x3c040001, 0x2484589c, 0x3c050006, 0xafa20014, 0x8ee6724c, 0x34a5f00d, 0xc002403, 0x2003821, 0x93a20037, 0x10400031, 0x340f8100, 0x8e420004, 0x8e430008, 0x8e44000c, 0xa64f000c, 0xae420000, @@ -2403,7 +2403,7 @@ 0x10430007, 0x4821, 0x8f8200e4, 0x24090001, 0x8c430000, 0x8c440004, 0xafa30018, 0xafa4001c, 0x1520000e, 0x3c02ffff, 0x8f8200c4, 0xafa20010, -0x8f8200c8, 0x3c040001, 0x248458c0, 0xafa20014, +0x8f8200c8, 0x3c040001, 0x24845870, 0xafa20014, 0x8f8600e0, 0x8f8700e4, 0x3c050006, 0xc002403, 0x34a5f000, 0x8003850, 0x0, 0x8fa3001c, 0x8fb20018, 0x3073ffff, 0x2673fffc, 0x621024, @@ -2501,15 +2501,15 @@ 0x862021, 0xaee400c0, 0xaee500c4, 0x8ee20058, 0x24420001, 0xaee20058, 0x8ee20058, 0x8ee2007c, 0x24420001, 0xaee2007c, 0x8ee2007c, 0x8f8200e0, -0xafa20010, 0x8f8200e4, 0x3c040001, 0x248458c8, +0xafa20010, 0x8f8200e4, 0x3c040001, 0x24845878, 0xafa20014, 0x8fa60018, 0x8fa7001c, 0x3c050006, 0xc002403, 0x34a5f003, 0x8003850, 0x0, 0x8ee25240, 0xafa20010, 0x8ee25244, 0x3c040001, -0x248458d4, 0xafa20014, 0x8ee60e10, 0x8ee70e18, +0x24845884, 0xafa20014, 0x8ee60e10, 0x8ee70e18, 0xc002403, 0x34a5f002, 0x8ee201c0, 0x24420001, 0xaee201c0, 0x8ee20000, 0x8ee301c0, 0x2403ffbf, 0x431024, 0x80037f8, 0xaee20000, 0x8ee25240, -0xafa20010, 0x8ee25244, 0x3c040001, 0x248458d4, +0xafa20010, 0x8ee25244, 0x3c040001, 0x24845884, 0xafa20014, 0x8ee60e10, 0x8ee70e18, 0x3c050006, 0xc002403, 0x34a5f002, 0x8ee201c0, 0x24420001, 0xaee201c0, 0x80037f8, 0x8ee201c0, 0x96e20468, @@ -2568,7 +2568,7 @@ 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x15200018, 0x3c050006, -0x8e020018, 0x3c040001, 0x248458e0, 0xafa20010, +0x8e020018, 0x3c040001, 0x24845890, 0xafa20010, 0x8e020000, 0x8e030004, 0x34a5f009, 0x2003021, 0xc002403, 0xafa30014, 0x32c200ff, 0x1040002b, 0x34028100, 0x8e430004, 0x8e440008, 0x8e45000c, @@ -2628,7 +2628,7 @@ 0x10430007, 0x3821, 0x8f8200e4, 0x24070001, 0x8c430000, 0x8c440004, 0xafa30018, 0xafa4001c, 0x14e0000e, 0x3c02ffff, 0x8f8200c4, 0xafa20010, -0x8f8200c8, 0x3c040001, 0x24845904, 0xafa20014, +0x8f8200c8, 0x3c040001, 0x248458b4, 0xafa20014, 0x8f8600e0, 0x8f8700e4, 0x3c050006, 0xc002403, 0x34a5f200, 0x8003c5b, 0x0, 0x8fa3001c, 0x8fb20018, 0x3073ffff, 0x2673fffc, 0x621024, @@ -2726,11 +2726,11 @@ 0x862021, 0xaee400c0, 0xaee500c4, 0x8ee20058, 0x24420001, 0xaee20058, 0x8ee20058, 0x8ee2007c, 0x24420001, 0xaee2007c, 0x8ee2007c, 0x8f8200e0, -0xafa20010, 0x8f8200e4, 0x3c040001, 0x24845910, +0xafa20010, 0x8f8200e4, 0x3c040001, 0x248458c0, 0xafa20014, 0x8fa60018, 0x8fa7001c, 0x3c050006, 0xc002403, 0x34a5f203, 0x8003c5b, 0x0, 0x8ee25240, 0xafa20010, 0x8ee25244, 0x3c040001, -0x2484591c, 0xafa20014, 0x8ee60e10, 0x8ee70e18, +0x248458cc, 0xafa20014, 0x8ee60e10, 0x8ee70e18, 0x3c050006, 0xc002403, 0x34a5f202, 0x8ee201c0, 0x24420001, 0xaee201c0, 0x8003c02, 0x8ee201c0, 0x96e20468, 0x53102b, 0x54400001, 0x3c168000, @@ -2826,7 +2826,7 @@ 0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, -0x14e00019, 0x3c050006, 0x3c040001, 0x248458e0, +0x14e00019, 0x3c050006, 0x3c040001, 0x24845890, 0x8e220018, 0x34a5f209, 0xafa20010, 0x8e220000, 0x8e230004, 0x2203021, 0x1603821, 0xc002403, 0xafa30014, 0x93a2002f, 0x1040002a, 0x34028100, @@ -2890,7 +2890,7 @@ 0x24020001, 0xac620004, 0x1480000e, 0x24030040, 0x8ee20e14, 0xafa20010, 0x8ee20e18, 0x3c050007, 0xafa20014, 0x8ee60e0c, 0x8ee70e10, 0x3c040001, -0x24845924, 0xc002403, 0x34a5f001, 0x8003cdd, +0x248458d4, 0xc002403, 0x34a5f001, 0x8003cdd, 0x0, 0x8ee20500, 0x24420001, 0x50430003, 0x1021, 0x8ee20500, 0x24420001, 0xaee20500, 0x8ee20500, 0x21080, 0x571021, 0xac490508, @@ -2922,7 +2922,7 @@ 0x24020003, 0xac620000, 0x24020001, 0xac620004, 0x1480000e, 0x24030040, 0x8ee2523c, 0xafa20010, 0x8ee25244, 0x3c050007, 0xafa20014, 0x8ee65238, -0x8ee75240, 0x3c040001, 0x24845930, 0xc002403, +0x8ee75240, 0x3c040001, 0x248458e0, 0xc002403, 0x34a5f010, 0x8003d5f, 0x0, 0x8ee20500, 0x24420001, 0x50430003, 0x1021, 0x8ee20500, 0x24420001, 0xaee20500, 0x8ee20500, 0x21080, @@ -2942,7 +2942,7 @@ 0x8f830128, 0x21140, 0x621821, 0xaf830128, 0xaca00000, 0x8cc20018, 0x2443fffe, 0x2c620012, 0x10400008, 0x31080, 0x3c010001, 0x220821, -0x8c225940, 0x400008, 0x0, 0x24020001, +0x8c2258f0, 0x400008, 0x0, 0x24020001, 0xaee24e24, 0x3e00008, 0x0, 0x27bdffc8, 0xafbf0030, 0xafb5002c, 0xafb40028, 0xafb30024, 0xafb20020, 0xafb1001c, 0xafb00018, 0x8f830128, @@ -2951,7 +2951,7 @@ 0x24140040, 0x8f8c0128, 0x8f820128, 0x24420020, 0xaf820128, 0x9182001b, 0x8f830128, 0x2443fffe, 0x2c620012, 0x1040029c, 0x31080, 0x3c010001, -0x220821, 0x8c225998, 0x400008, 0x0, +0x220821, 0x8c225948, 0x400008, 0x0, 0x8f420218, 0x30420100, 0x10400007, 0x0, 0x95830016, 0x95820018, 0x621823, 0x31402, 0x431021, 0xa5820016, 0x8d82001c, 0x3c038000, @@ -3052,7 +3052,7 @@ 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x1600000d, 0x0, -0x8f820120, 0x3c040001, 0x24845988, 0xafa00014, +0x8f820120, 0x3c040001, 0x24845938, 0xafa00014, 0xafa20010, 0x8d86001c, 0x8f870124, 0x3c050008, 0xc002403, 0x34a50001, 0x8004057, 0x0, 0x8ee2724c, 0x24420001, 0x304207ff, 0x11a00006, @@ -3087,7 +3087,7 @@ 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020001, 0xac950000, 0xac820004, 0x5600000b, 0x24100001, 0x8ee2724c, -0x3c040001, 0x248458f8, 0xafa00014, 0xafa20010, +0x3c040001, 0x248458a8, 0xafa00014, 0xafa20010, 0x8ee6724c, 0x8f470280, 0x3c050009, 0xc002403, 0x34a5f008, 0x56000001, 0xaee00e1c, 0x8ee20188, 0x24420001, 0xaee20188, 0x8004050, 0x8ee20188, @@ -3113,7 +3113,7 @@ 0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020001, 0xac950000, 0xac820004, 0x1600000b, -0x0, 0x8ee2724c, 0x3c040001, 0x248458f8, +0x0, 0x8ee2724c, 0x3c040001, 0x248458a8, 0xafa00014, 0xafa20010, 0x8ee6724c, 0x8f470280, 0x3c050009, 0xc002403, 0x34a5f008, 0x8ee20174, 0x24420001, 0xaee20174, 0x8004057, 0x8ee20174, @@ -3125,16 +3125,16 @@ 0xc00249a, 0xafb00010, 0x2021, 0x24100001, 0x2402241f, 0xaf900210, 0xaf900200, 0xaf800204, 0xaf820214, 0x8f460248, 0x24030004, 0x3c020040, -0x3c010001, 0xac235d24, 0x3c010001, 0xac235d28, -0x3c010001, 0xac205dfc, 0x3c010001, 0xac225d20, -0x3c010001, 0xac235d28, 0xc0050e0, 0x24050004, -0xc0047fc, 0x0, 0x8ee20000, 0x3c03feff, +0x3c010001, 0xac235cc4, 0x3c010001, 0xac235cc8, +0x3c010001, 0xac205d9c, 0x3c010001, 0xac225cc0, +0x3c010001, 0xac235cc8, 0xc005108, 0x24050004, +0xc004822, 0x0, 0x8ee20000, 0x3c03feff, 0x3463fffd, 0x431024, 0xaee20000, 0x3c023c00, 0xaf82021c, 0x3c010001, 0x370821, 0xac3083ac, 0x8fbf0014, 0x8fb00010, 0x3e00008, 0x27bd0018, 0x27bdffe0, 0x3c050008, 0x34a50400, 0xafbf0018, 0xafa00010, 0xafa00014, 0x8f860200, 0x3c040001, -0x24845a40, 0xc002403, 0x3821, 0x8ee20280, +0x248459f0, 0xc002403, 0x3821, 0x8ee20280, 0x24420001, 0xaee20280, 0x8ee20280, 0x8f830200, 0x3c023f00, 0x621824, 0x8fbf0018, 0x3c020400, 0x3e00008, 0x27bd0020, 0x27bdffd8, 0xafbf0020, @@ -3146,16 +3146,16 @@ 0xaee20218, 0x8ee20218, 0x80040c6, 0x3c03fdff, 0x8ee2021c, 0x24420001, 0xaee2021c, 0x8ee2021c, 0x3c03fdff, 0x3463ffff, 0x3c0808ff, 0x3508ffff, -0x8ee20000, 0x3c040001, 0x24845a4c, 0x3c050008, +0x8ee20000, 0x3c040001, 0x248459fc, 0x3c050008, 0x2003021, 0x431024, 0xaee20000, 0x8f820220, 0x3821, 0x3c030300, 0x481024, 0x431025, 0xaf820220, 0xafa00010, 0xc002403, 0xafa00014, 0x8004296, 0x0, 0x2111024, 0x1040001f, 0x3c024000, 0x8f830224, 0x24021402, 0x1462000b, -0x3c03fdff, 0x3c040001, 0x24845a58, 0x3c050008, +0x3c03fdff, 0x3c040001, 0x24845a08, 0x3c050008, 0xafa00010, 0xafa00014, 0x8f860224, 0x34a5ffff, 0xc002403, 0x3821, 0x3c03fdff, 0x8ee20000, -0x3463ffff, 0x2002021, 0x431024, 0xc004e2c, +0x3463ffff, 0x2002021, 0x431024, 0xc004e54, 0xaee20000, 0x8ee20220, 0x24420001, 0xaee20220, 0x8ee20220, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x8004295, 0x511025, 0x2021024, @@ -3226,7 +3226,7 @@ 0x431025, 0xaf820220, 0x8f8600e0, 0x8f8400e4, 0x10c4002a, 0x0, 0x8ee2007c, 0x24420001, 0xaee2007c, 0x8ee2007c, 0x24c2fff8, 0xaf8200e0, -0x3c020001, 0x8c427e90, 0x3c030008, 0x8f8600e0, +0x3c020001, 0x8c427e30, 0x3c030008, 0x8f8600e0, 0x431024, 0x1040001d, 0x0, 0x10c4001b, 0x240dfff8, 0x3c0a000a, 0x354af000, 0x3c0c0080, 0x24850008, 0x27622800, 0x50a20001, 0x27651800, @@ -3262,12 +3262,12 @@ 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820220, 0x3c0308ff, 0x3463fffb, 0x431024, 0xaf820220, 0x8fbf0020, 0x8fb1001c, 0x8fb00018, -0x3e00008, 0x27bd0028, 0x3c020001, 0x8c425d38, +0x3e00008, 0x27bd0028, 0x3c020001, 0x8c425cd8, 0x27bdffd8, 0x10400012, 0xafbf0020, 0x3c040001, -0x24845a64, 0x3c050008, 0x24020001, 0x3c010001, +0x24845a14, 0x3c050008, 0x24020001, 0x3c010001, 0x370821, 0xac2283ac, 0xafa00010, 0xafa00014, -0x8f860220, 0x34a50498, 0x3c010001, 0xac205d38, -0x3c010001, 0xac225d2c, 0xc002403, 0x3821, +0x8f860220, 0x34a50498, 0x3c010001, 0xac205cd8, +0x3c010001, 0xac225ccc, 0xc002403, 0x3821, 0x8f420268, 0x3c037fff, 0x3463ffff, 0x431024, 0xaf420268, 0x8ee204d0, 0x8ee404d4, 0x2403fffe, 0x431024, 0x30840002, 0x1080011e, 0xaee204d0, @@ -3333,24 +3333,24 @@ 0x54a00006, 0x240b0001, 0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa6, 0x0, 0x316300ff, 0x24020001, 0x54620003, 0xafa00010, 0x80043d6, -0x0, 0x3c040001, 0x24845a70, 0xafa00014, +0x0, 0x3c040001, 0x24845a20, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc002403, 0x34a5f011, 0x80043d6, 0x0, 0x3c040001, -0x24845a7c, 0xafa00014, 0x8f860120, 0x8f870124, +0x24845a2c, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc002403, 0x34a5f010, 0x80043d6, -0x0, 0x3c040001, 0x24845a88, 0xafa00014, +0x0, 0x3c040001, 0x24845a38, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f00f, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x8ee201ac, 0x8ee2015c, 0x24420001, 0xaee2015c, 0x8ee2015c, 0x8fbf0020, 0x3e00008, 0x27bd0028, -0x3c020001, 0x8c425d38, 0x27bdffe0, 0x1440000d, -0xafbf0018, 0x3c040001, 0x24845a94, 0x3c050008, +0x3c020001, 0x8c425cd8, 0x27bdffe0, 0x1440000d, +0xafbf0018, 0x3c040001, 0x24845a44, 0x3c050008, 0xafa00010, 0xafa00014, 0x8f860220, 0x34a50499, -0x24020001, 0x3c010001, 0xac225d38, 0xc002403, +0x24020001, 0x3c010001, 0xac225cd8, 0xc002403, 0x3821, 0x8ee204d0, 0x3c030001, 0x771821, 0x946383b2, 0x34420001, 0x10600007, 0xaee204d0, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, -0x34420008, 0xaf820220, 0x2021, 0xc005276, +0x34420008, 0xaf820220, 0x2021, 0xc0052a2, 0x24050004, 0xaf420268, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, @@ -3368,7 +3368,7 @@ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c120001, -0x26521200, 0x3c140001, 0x8e945cb0, 0x3c100001, +0x26521200, 0x3c140001, 0x8e945c50, 0x3c100001, 0x26101120, 0x3c15c000, 0x36b50060, 0x8e8a0000, 0x8eb30000, 0x26a400b, 0x248000a, 0x200f821, 0x0, 0xd, 0x0, 0x0, @@ -3429,978 +3429,973 @@ 0x1062000c, 0x43102b, 0x14400006, 0x3c026000, 0x3c024000, 0x10620008, 0x24020800, 0x8004539, 0x0, 0x10620004, 0x24020800, 0x8004539, -0x0, 0x24020700, 0x3c010001, 0xac225d3c, -0x3e00008, 0x0, 0x27bdffd0, 0xafbf0028, -0x8f830054, 0x8f820054, 0x3c010001, 0xac205d24, -0x8004544, 0x24630064, 0x8f820054, 0x621023, -0x2c420065, 0x1440fffc, 0x0, 0xc004d49, -0x0, 0x24040001, 0x2821, 0x27a60020, -0x34028000, 0xc004966, 0xa7a20020, 0x8f830054, -0x8f820054, 0x8004555, 0x24630064, 0x8f820054, -0x621023, 0x2c420065, 0x1440fffc, 0x24040001, -0x24050001, 0xc004924, 0x27a60020, 0x8f830054, -0x8f820054, 0x8004561, 0x24630064, 0x8f820054, -0x621023, 0x2c420065, 0x1440fffc, 0x24040001, -0x24050001, 0xc004924, 0x27a60020, 0x8f830054, -0x8f820054, 0x800456d, 0x24630064, 0x8f820054, -0x621023, 0x2c420065, 0x1440fffc, 0x24040001, -0x24050002, 0xc004924, 0x27a60018, 0x8f830054, -0x8f820054, 0x8004579, 0x24630064, 0x8f820054, -0x621023, 0x2c420065, 0x1440fffc, 0x24040001, -0x24050003, 0xc004924, 0x27a6001a, 0x3c040001, -0x24845b00, 0x97a60020, 0x97a70018, 0x97a2001a, -0x3c05000d, 0x34a50100, 0xafa00014, 0xc002403, -0xafa20010, 0x97a20020, 0x10400045, 0x24036040, -0x97a2001a, 0x3042fff0, 0x14430009, 0x24020020, -0x97a30018, 0x54620008, 0x24027830, 0x24020003, -0x3c010001, 0xac225d24, 0x80045a4, 0x24020005, -0x97a30018, 0x24027830, 0x1462000e, 0x24030010, -0x97a2001a, 0x3042fff0, 0x1443000a, 0x24020003, -0x3c010001, 0xac225d24, 0x24020006, 0x3c010001, -0xac225e0c, 0x3c010001, 0xac225e18, 0x80045da, -0x3c09fff0, 0x3c020001, 0x8c425d24, 0x97a30018, -0x34420001, 0x3c010001, 0xac225d24, 0x24020015, -0x1462000e, 0x0, 0x97a2001a, 0x3042fff0, -0x3843f420, 0x2c630001, 0x3842f430, 0x2c420001, -0x621825, 0x10600005, 0x24020003, 0x3c010001, -0xac225e18, 0x80045da, 0x3c09fff0, 0x97a30018, -0x24027810, 0x1462000a, 0x24020002, 0x97a2001a, +0x0, 0x24020700, 0x3c010001, 0xac225cdc, +0x3e00008, 0x0, 0x27bdffd8, 0xafbf0024, +0xafb00020, 0x8f830054, 0x8f820054, 0x3c010001, +0xac205cc4, 0x8004545, 0x24630064, 0x8f820054, +0x621023, 0x2c420065, 0x1440fffc, 0x0, +0xc004d71, 0x0, 0x24040001, 0x2821, +0x27a60018, 0x34028000, 0xc00498e, 0xa7a20018, +0x8f830054, 0x8f820054, 0x8004556, 0x24630064, +0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, +0x24040001, 0x24050001, 0xc00494c, 0x27a60018, +0x8f830054, 0x8f820054, 0x8004562, 0x24630064, +0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, +0x24040001, 0x24050001, 0xc00494c, 0x27a60018, +0x8f830054, 0x8f820054, 0x800456e, 0x24630064, +0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, +0x24040001, 0x3c060001, 0x24c65da0, 0xc00494c, +0x24050002, 0x8f830054, 0x8f820054, 0x800457b, +0x24630064, 0x8f820054, 0x621023, 0x2c420065, +0x1440fffc, 0x24040001, 0x24050003, 0x3c100001, +0x26105da2, 0xc00494c, 0x2003021, 0x97a60018, +0x3c070001, 0x94e75da0, 0x3c040001, 0x24845ab0, +0xafa00014, 0x96020000, 0x3c05000d, 0x34a50100, +0xc002403, 0xafa20010, 0x97a20018, 0x1040004c, +0x24036040, 0x96020000, 0x3042fff0, 0x1443000a, +0x24020020, 0x3c030001, 0x94635da0, 0x54620009, +0x24027830, 0x24020003, 0x3c010001, 0xac225cc4, +0x80045ac, 0x24020005, 0x3c030001, 0x94635da0, +0x24027830, 0x1462000f, 0x24030010, 0x3c020001, +0x94425da2, 0x3042fff0, 0x1443000a, 0x24020003, +0x3c010001, 0xac225cc4, 0x24020006, 0x3c010001, +0xac225db0, 0x3c010001, 0xac225dbc, 0x80045e6, +0x3c09fff0, 0x3c020001, 0x8c425cc4, 0x3c030001, +0x94635da0, 0x34420001, 0x3c010001, 0xac225cc4, +0x24020015, 0x1462000f, 0x0, 0x3c020001, +0x94425da2, 0x3042fff0, 0x3843f420, 0x2c630001, +0x3842f430, 0x2c420001, 0x621825, 0x10600005, +0x24020003, 0x3c010001, 0xac225dbc, 0x80045e6, +0x3c09fff0, 0x3c030001, 0x94635da0, 0x24027810, +0x1462000b, 0x24020002, 0x3c020001, 0x94425da2, 0x3042fff0, 0x14400006, 0x24020002, 0x24020004, -0x3c010001, 0xac225e18, 0x80045da, 0x3c09fff0, -0x3c010001, 0xac225e18, 0x80045da, 0x3c09fff0, -0x3c020001, 0x8c425d24, 0x24030001, 0x3c010001, -0xac235e18, 0x34420004, 0x3c010001, 0xac225d24, -0x3c09fff0, 0x3529bdc0, 0x8f830054, 0x3c060001, -0x8cc65d24, 0x3c070001, 0x8ce75e18, 0x97a80018, -0x3c040001, 0x24845b00, 0x24020001, 0x3c010001, -0xac225d2c, 0xafa80010, 0x97a2001a, 0x3c05000d, -0x34a50100, 0x3c010001, 0xac205d28, 0x691821, -0x3c010001, 0xac235e08, 0xc002403, 0xafa20014, -0x8fbf0028, 0x3e00008, 0x27bd0030, 0x27bdffe8, -0x3c050001, 0x8ca55d28, 0x24060004, 0x24020001, -0x14a20014, 0xafbf0010, 0x3c020001, 0x8c427e9c, -0x30428000, 0x10400005, 0x3c04000f, 0x3c030001, -0x8c635e18, 0x8004608, 0x34844240, 0x3c040004, -0x3c030001, 0x8c635e18, 0x348493e0, 0x24020005, -0x14620016, 0x0, 0x3c04003d, 0x8004620, -0x34840900, 0x3c020001, 0x8c427e98, 0x30428000, -0x10400005, 0x3c04001e, 0x3c030001, 0x8c635e18, -0x800461b, 0x34848480, 0x3c04000f, 0x3c030001, -0x8c635e18, 0x34844240, 0x24020005, 0x14620003, -0x0, 0x3c04007a, 0x34841200, 0x3c020001, -0x8c425e08, 0x8f830054, 0x441021, 0x431023, -0x44102b, 0x14400037, 0x0, 0x3c020001, -0x8c425d30, 0x14400033, 0x0, 0x3c010001, -0x10c00025, 0xac205d40, 0x3c090001, 0x8d295d24, -0x24070001, 0x3c044000, 0x3c080001, 0x25087e9c, -0x250afffc, 0x52842, 0x14a00002, 0x24c6ffff, -0x24050008, 0xa91024, 0x10400010, 0x0, -0x14a70008, 0x0, 0x8d020000, 0x441024, -0x1040000a, 0x0, 0x3c010001, 0x800464c, -0xac255d40, 0x8d420000, 0x441024, 0x10400003, -0x0, 0x3c010001, 0xac275d40, 0x3c020001, -0x8c425d40, 0x6182b, 0x2c420001, 0x431024, -0x5440ffe5, 0x52842, 0x8f820054, 0x3c030001, -0x8c635d40, 0x3c010001, 0xac225e08, 0x1060002a, -0x24020001, 0x3c010001, 0xac255d28, 0x3c010001, -0xac225d2c, 0x3c020001, 0x8c425d40, 0x10400022, -0x0, 0x3c020001, 0x8c425d2c, 0x1040000a, -0x24020001, 0x3c010001, 0xac205d2c, 0x3c010001, -0x370821, 0xac2283ac, 0x3c010001, 0xac205dac, -0x3c010001, 0xac225d64, 0x3c030001, 0x771821, -0x8c6383ac, 0x24020008, 0x10620005, 0x24020001, -0xc004686, 0x0, 0x8004683, 0x0, -0x3c030001, 0x8c635d28, 0x10620007, 0x2402000e, -0x3c030001, 0x8c637e30, 0x10620003, 0x0, -0xc004e2c, 0x8f840220, 0x8fbf0010, 0x3e00008, -0x27bd0018, 0x27bdffe0, 0x3c02fdff, 0xafbf001c, -0xafb00018, 0x8ee30000, 0x3c050001, 0x8ca55d28, -0x3c040001, 0x8c845d50, 0x3442ffff, 0x621824, -0x14a40008, 0xaee30000, 0x3c030001, 0x771821, -0x8c6383ac, 0x3c020001, 0x8c425d54, 0x10620008, -0x0, 0x3c020001, 0x571021, 0x8c4283ac, -0x3c010001, 0xac255d50, 0x3c010001, 0xac225d54, -0x3c030001, 0x8c635d28, 0x24020002, 0x10620150, -0x2c620003, 0x10400005, 0x24020001, 0x10620008, -0x0, 0x80047f5, 0x0, 0x24020004, -0x10620098, 0x24020001, 0x80047f6, 0x0, -0x3c020001, 0x571021, 0x8c4283ac, 0x2443ffff, -0x2c620008, 0x10400141, 0x31080, 0x3c010001, -0x220821, 0x8c225b18, 0x400008, 0x0, -0x3c030001, 0x8c635e18, 0x24020005, 0x14620014, -0x0, 0x3c020001, 0x8c425d34, 0x1040000a, -0x24020003, 0xc0047fc, 0x0, 0x24020002, +0x3c010001, 0xac225dbc, 0x80045e6, 0x3c09fff0, +0x3c010001, 0xac225dbc, 0x80045e6, 0x3c09fff0, +0x3c020001, 0x8c425cc4, 0x24030001, 0x3c010001, +0xac235dbc, 0x34420004, 0x3c010001, 0xac225cc4, +0x3c09fff0, 0x3529bdc0, 0x3c060001, 0x8cc65cc4, +0x3c040001, 0x24845ab0, 0x24020001, 0x3c010001, +0xac225ccc, 0x8f820054, 0x3c070001, 0x8ce75dbc, +0x3c030001, 0x94635da0, 0x3c080001, 0x95085da2, +0x3c05000d, 0x34a50100, 0x3c010001, 0xac205cc8, +0x491021, 0x3c010001, 0xac225dac, 0xafa30010, +0xc002403, 0xafa80014, 0x8fbf0024, 0x8fb00020, +0x3e00008, 0x27bd0028, 0x27bdffe8, 0x3c050001, +0x8ca55cc8, 0x24060004, 0x24020001, 0x14a20014, +0xafbf0010, 0x3c020001, 0x8c427e3c, 0x30428000, +0x10400005, 0x3c04000f, 0x3c030001, 0x8c635dbc, +0x8004617, 0x34844240, 0x3c040004, 0x3c030001, +0x8c635dbc, 0x348493e0, 0x24020005, 0x14620016, +0x0, 0x3c04003d, 0x800462f, 0x34840900, +0x3c020001, 0x8c427e38, 0x30428000, 0x10400005, +0x3c04001e, 0x3c030001, 0x8c635dbc, 0x800462a, +0x34848480, 0x3c04000f, 0x3c030001, 0x8c635dbc, +0x34844240, 0x24020005, 0x14620003, 0x0, +0x3c04007a, 0x34841200, 0x3c020001, 0x8c425dac, +0x8f830054, 0x441021, 0x431023, 0x44102b, +0x14400037, 0x0, 0x3c020001, 0x8c425cd0, +0x14400033, 0x0, 0x3c010001, 0x10c00025, +0xac205ce0, 0x3c090001, 0x8d295cc4, 0x24070001, +0x3c044000, 0x3c080001, 0x25087e3c, 0x250afffc, +0x52842, 0x14a00002, 0x24c6ffff, 0x24050008, +0xa91024, 0x10400010, 0x0, 0x14a70008, +0x0, 0x8d020000, 0x441024, 0x1040000a, +0x0, 0x3c010001, 0x800465b, 0xac255ce0, +0x8d420000, 0x441024, 0x10400003, 0x0, +0x3c010001, 0xac275ce0, 0x3c020001, 0x8c425ce0, +0x6182b, 0x2c420001, 0x431024, 0x5440ffe5, +0x52842, 0x8f820054, 0x3c030001, 0x8c635ce0, +0x3c010001, 0xac225dac, 0x1060002a, 0x24020001, +0x3c010001, 0xac255cc8, 0x3c010001, 0xac225ccc, +0x3c020001, 0x8c425ce0, 0x10400022, 0x0, +0x3c020001, 0x8c425ccc, 0x1040000a, 0x24020001, +0x3c010001, 0xac205ccc, 0x3c010001, 0x370821, +0xac2283ac, 0x3c010001, 0xac205d4c, 0x3c010001, +0xac225d04, 0x3c030001, 0x771821, 0x8c6383ac, +0x24020008, 0x10620005, 0x24020001, 0xc004695, +0x0, 0x8004692, 0x0, 0x3c030001, +0x8c635cc8, 0x10620007, 0x2402000e, 0x3c030001, +0x8c637dd0, 0x10620003, 0x0, 0xc004e54, +0x8f840220, 0x8fbf0010, 0x3e00008, 0x27bd0018, +0x27bdffe0, 0x3c02fdff, 0xafbf0018, 0x8ee30000, +0x3c050001, 0x8ca55cc8, 0x3c040001, 0x8c845cf0, +0x3442ffff, 0x621824, 0x14a40008, 0xaee30000, +0x3c030001, 0x771821, 0x8c6383ac, 0x3c020001, +0x8c425cf4, 0x10620008, 0x0, 0x3c020001, +0x571021, 0x8c4283ac, 0x3c010001, 0xac255cf0, +0x3c010001, 0xac225cf4, 0x3c030001, 0x8c635cc8, +0x24020002, 0x10620169, 0x2c620003, 0x10400005, +0x24020001, 0x10620008, 0x0, 0x800481c, +0x0, 0x24020004, 0x106200b1, 0x24020001, +0x800481d, 0x0, 0x3c020001, 0x571021, +0x8c4283ac, 0x2443ffff, 0x2c620008, 0x1040015a, +0x31080, 0x3c010001, 0x220821, 0x8c225ac8, +0x400008, 0x0, 0x3c030001, 0x8c635dbc, +0x24020005, 0x14620014, 0x0, 0x3c020001, +0x8c425cd4, 0x1040000a, 0x24020003, 0xc004822, +0x0, 0x24020002, 0x3c010001, 0x370821, +0xac2283ac, 0x3c010001, 0x80046e0, 0xac205cd4, 0x3c010001, 0x370821, 0xac2283ac, 0x3c010001, -0x80046d2, 0xac205d34, 0x3c010001, 0x370821, -0xac2283ac, 0x3c010001, 0x80047f8, 0xac205cc0, -0xc0047fc, 0x0, 0x3c020001, 0x8c425d34, -0x3c010001, 0xac205cc0, 0x104000c4, 0x24020002, +0x800481f, 0xac205c60, 0xc004822, 0x0, +0x3c020001, 0x8c425cd4, 0x3c010001, 0xac205c60, +0x104000dd, 0x24020002, 0x3c010001, 0x370821, +0xac2283ac, 0x3c010001, 0x800481f, 0xac205cd4, +0x3c030001, 0x8c635dbc, 0x24020005, 0x14620003, +0x24020001, 0x3c010001, 0xac225d00, 0xc0049cf, +0x0, 0x3c030001, 0x8c635d00, 0x800478e, +0x24020011, 0x3c050001, 0x8ca55cc8, 0x3c060001, +0x8cc67e3c, 0xc005108, 0x2021, 0x24020005, +0x3c010001, 0xac205cd4, 0x3c010001, 0x370821, +0x800481f, 0xac2283ac, 0x3c040001, 0x24845abc, +0x3c05000f, 0x34a50100, 0x3021, 0x3821, +0xafa00010, 0xc002403, 0xafa00014, 0x800481f, +0x0, 0x8f820220, 0x3c03f700, 0x431025, +0x80047b7, 0xaf820220, 0x8f820220, 0x3c030004, +0x431024, 0x144000a9, 0x24020007, 0x8f830054, +0x3c020001, 0x8c425da4, 0x2463d8f0, 0x431023, +0x2c422710, 0x144000f8, 0x24020001, 0x800481d, +0x0, 0x3c050001, 0x8ca55cc8, 0xc0052a2, +0x2021, 0xc005386, 0x2021, 0x3c030001, +0x8c637e34, 0x46100ea, 0x24020001, 0x3c020008, +0x621024, 0x10400006, 0x0, 0x8f820214, +0x3c03ffff, 0x431024, 0x8004741, 0x3442251f, +0x8f820214, 0x3c03ffff, 0x431024, 0x3442241f, +0xaf820214, 0x8ee20000, 0x3c030200, 0x431025, +0xaee20000, 0x8f820220, 0x2403fffb, 0x431024, +0xaf820220, 0x8f820220, 0x34420002, 0xaf820220, +0x24020008, 0x3c010001, 0x370821, 0xac2283ac, +0x8f820220, 0x3c030004, 0x431024, 0x14400005, +0x0, 0x8f820220, 0x3c03f700, 0x431025, +0xaf820220, 0x3c030001, 0x8c635dbc, 0x24020005, +0x1462000a, 0x0, 0x3c020001, 0x94425da2, +0x24429fbc, 0x2c420004, 0x10400004, 0x24040018, +0x24050002, 0xc004d93, 0x24060020, 0xc0043dd, +0x0, 0x3c010001, 0x800481f, 0xac205d50, +0x3c020001, 0x571021, 0x8c4283ac, 0x2443ffff, +0x2c620008, 0x104000ac, 0x31080, 0x3c010001, +0x220821, 0x8c225ae8, 0x400008, 0x0, +0xc00429b, 0x0, 0x3c010001, 0xac205ccc, +0xaf800204, 0x3c010001, 0xc004822, 0xac207e20, +0x24020001, 0x3c010001, 0xac225ce4, 0x24020002, +0x3c010001, 0x370821, 0x800481f, 0xac2283ac, +0xc00489f, 0x0, 0x3c030001, 0x8c635ce4, +0x24020009, 0x14620090, 0x24020003, 0x3c010001, +0x370821, 0x800481f, 0xac2283ac, 0x3c020001, +0x8c427e38, 0x30424000, 0x10400005, 0x0, +0x8f820044, 0x3c03ffff, 0x800479f, 0x34637fff, +0x8f820044, 0x2403ff7f, 0x431024, 0xaf820044, +0x8f830054, 0x80047b9, 0x24020004, 0x8f830054, +0x3c020001, 0x8c425da4, 0x2463d8f0, 0x431023, +0x2c422710, 0x14400074, 0x24020005, 0x3c010001, +0x370821, 0x800481f, 0xac2283ac, 0x8f820220, +0x3c03f700, 0x431025, 0xaf820220, 0xaf800204, +0x3c010001, 0xac207e20, 0x8f830054, 0x24020006, 0x3c010001, 0x370821, 0xac2283ac, 0x3c010001, -0x80047f8, 0xac205d34, 0x24020001, 0x3c010001, -0xc0049a7, 0xac225d60, 0x3c030001, 0x8c635d60, -0x8004767, 0x24020011, 0x3c020001, 0x8c425e18, -0x24100005, 0x10500007, 0x0, 0x3c050001, -0x8ca55d28, 0x3c060001, 0x8cc67e9c, 0xc0050e0, -0x2021, 0x3c010001, 0xac205d34, 0x3c010001, -0x370821, 0x80047f8, 0xac3083ac, 0x3c040001, -0x24845b0c, 0x3c05000f, 0x34a50100, 0x3021, -0x3821, 0xafa00010, 0xc002403, 0xafa00014, -0x80047f8, 0x0, 0x8f820220, 0x3c03f700, -0x431025, 0x8004790, 0xaf820220, 0x8f820220, -0x3c030004, 0x431024, 0x14400091, 0x24020007, -0x8f830054, 0x3c020001, 0x8c425e00, 0x2463d8f0, -0x431023, 0x2c422710, 0x144000e0, 0x24020001, -0x80047f6, 0x0, 0x3c050001, 0x8ca55d28, -0xc005276, 0x2021, 0xc005397, 0x2021, -0x3c030001, 0x8c637e94, 0x46100d2, 0x24020001, -0x3c020008, 0x621024, 0x10400006, 0x0, -0x8f820214, 0x3c03ffff, 0x431024, 0x8004732, -0x3442251f, 0x8f820214, 0x3c03ffff, 0x431024, -0x3442241f, 0xaf820214, 0x8ee20000, 0x3c030200, -0x431025, 0xaee20000, 0x8f820220, 0x2403fffb, -0x431024, 0xaf820220, 0x8f820220, 0x34420002, -0xaf820220, 0x24020008, 0x3c010001, 0x370821, -0xc0043dd, 0xac2283ac, 0x3c010001, 0x80047f8, -0xac205db0, 0x3c020001, 0x571021, 0x8c4283ac, -0x2443ffff, 0x2c620008, 0x104000ac, 0x31080, -0x3c010001, 0x220821, 0x8c225b38, 0x400008, -0x0, 0xc00429b, 0x0, 0x3c010001, -0xac205d2c, 0xaf800204, 0x3c010001, 0xc0047fc, -0xac207e80, 0x24020001, 0x3c010001, 0xac225d44, -0x24020002, 0x3c010001, 0x370821, 0x80047f8, -0xac2283ac, 0xc004879, 0x0, 0x3c030001, -0x8c635d44, 0x24020009, 0x14620090, 0x24020003, -0x3c010001, 0x370821, 0x80047f8, 0xac2283ac, -0x3c020001, 0x8c427e98, 0x30424000, 0x10400005, -0x0, 0x8f820044, 0x3c03ffff, 0x8004778, -0x34637fff, 0x8f820044, 0x2403ff7f, 0x431024, -0xaf820044, 0x8f830054, 0x8004792, 0x24020004, -0x8f830054, 0x3c020001, 0x8c425e00, 0x2463d8f0, -0x431023, 0x2c422710, 0x14400074, 0x24020005, -0x3c010001, 0x370821, 0x80047f8, 0xac2283ac, +0x800481f, 0xac235da4, 0x8f830054, 0x3c020001, +0x8c425da4, 0x2463fff6, 0x431023, 0x2c42000a, +0x14400059, 0x0, 0x24020007, 0x3c010001, +0x370821, 0x800481f, 0xac2283ac, 0x8f820220, +0x3c04f700, 0x441025, 0xaf820220, 0x8f820220, +0x3c030300, 0x431024, 0x14400005, 0x1821, +0x8f820220, 0x24030001, 0x441025, 0xaf820220, +0x10600043, 0x24020001, 0x8f820214, 0x3c03ffff, +0x3c040001, 0x8c845d98, 0x431024, 0x3442251f, +0xaf820214, 0x24020008, 0x3c010001, 0x370821, +0x1080000b, 0xac2283ac, 0x3c020001, 0x8c425d74, +0x14400007, 0x24020001, 0x3c010001, 0xac227dd0, +0xc004e54, 0x8f840220, 0x800480c, 0x0, +0x8f820220, 0x3c030008, 0x431024, 0x14400017, +0x2402000e, 0x3c010001, 0xac227dd0, 0x8ee20000, +0x2021, 0x3c030200, 0x431025, 0xc005386, +0xaee20000, 0x8f820220, 0x2403fffb, 0x431024, +0xaf820220, 0x8f820220, 0x34420002, 0xc0043dd, +0xaf820220, 0x3c050001, 0x8ca55cc8, 0xc0052a2, +0x2021, 0x800481f, 0x0, 0x3c020001, +0x8c425d74, 0x10400010, 0x0, 0x3c020001, +0x8c425d70, 0x2442ffff, 0x3c010001, 0xac225d70, +0x14400009, 0x24020002, 0x3c010001, 0xac205d74, +0x3c010001, 0x800481f, 0xac225d70, 0x24020001, +0x3c010001, 0xac225ccc, 0x8fbf0018, 0x3e00008, +0x27bd0020, 0x8f820200, 0x8f820220, 0x8f820220, +0x34420004, 0xaf820220, 0x8f820200, 0x3c060001, +0x8cc65cc8, 0x34420004, 0xaf820200, 0x24020002, +0x10c2003a, 0x2cc20003, 0x10400005, 0x24020001, +0x10c20008, 0x0, 0x8004868, 0x0, +0x24020004, 0x10c20013, 0x24020001, 0x8004868, +0x0, 0x3c030001, 0x8c635cb8, 0x3c020001, +0x8c425cc0, 0x3c040001, 0x8c845cdc, 0x3c050001, +0x8ca55cbc, 0xaf860200, 0xaf860220, 0x34630022, +0x441025, 0x451025, 0x34420002, 0x8004867, +0xaf830200, 0x3c030001, 0x8c635d98, 0xaf820200, +0x10600009, 0xaf820220, 0x3c020001, 0x8c425d74, +0x14400005, 0x3c033f00, 0x3c020001, 0x8c425cb0, +0x800485b, 0x346300e0, 0x3c020001, 0x8c425cb0, +0x3c033f00, 0x346300e2, 0x431025, 0xaf820200, +0x3c030001, 0x8c635cb4, 0x3c04f700, 0x3c020001, +0x8c425cc0, 0x3c050001, 0x8ca55cdc, 0x641825, +0x431025, 0x451025, 0xaf820220, 0x3e00008, +0x0, 0x8f820220, 0x3c030001, 0x8c635cc8, +0x34420004, 0xaf820220, 0x24020001, 0x1062000f, +0x0, 0x8f830054, 0x8f820054, 0x24630002, +0x621023, 0x2c420003, 0x10400011, 0x0, +0x8f820054, 0x621023, 0x2c420003, 0x1040000c, +0x0, 0x8004879, 0x0, 0x8f830054, +0x8f820054, 0x8004885, 0x24630007, 0x8f820054, +0x621023, 0x2c420008, 0x1440fffc, 0x0, +0x8f8400e0, 0x30820007, 0x1040000d, 0x0, +0x8f820054, 0x8f8300e0, 0x14830009, 0x24450032, +0x8f820054, 0xa21023, 0x2c420033, 0x10400004, +0x0, 0x8f8200e0, 0x1082fff9, 0x0, +0x8f820220, 0x2403fffd, 0x431024, 0xaf820220, +0x3e00008, 0x0, 0x3c030001, 0x8c635ce4, +0x3c020001, 0x8c425ce8, 0x50620004, 0x2463ffff, +0x3c010001, 0xac235ce8, 0x2463ffff, 0x2c620009, +0x1040009d, 0x31080, 0x3c010001, 0x220821, +0x8c225b08, 0x400008, 0x0, 0x8f820044, +0x34428080, 0xaf820044, 0x8f830054, 0x8004938, +0x24020002, 0x8f830054, 0x3c020001, 0x8c425da8, +0x2463d8f0, 0x431023, 0x2c422710, 0x1440008a, +0x24020003, 0x8004945, 0x0, 0x8f820044, +0x3c03ffff, 0x34637fff, 0x431024, 0xaf820044, +0x8f830054, 0x8004938, 0x24020004, 0x8f830054, +0x3c020001, 0x8c425da8, 0x2463fff6, 0x431023, +0x2c42000a, 0x14400078, 0x24020005, 0x8004945, +0x0, 0x8f820220, 0x3c03f700, 0x431025, +0xaf820220, 0x8f820220, 0x2403fffb, 0x431024, +0xaf820220, 0x8f820220, 0x34420002, 0xaf820220, +0x3c023f00, 0x344200e0, 0xaf820200, 0x8f820200, +0x2403fffd, 0x431024, 0xaf820200, 0x24040001, +0x3405ffff, 0xaf840204, 0x8f830054, 0x8f820054, +0x80048ec, 0x24630001, 0x8f820054, 0x621023, +0x2c420002, 0x1440fffc, 0x0, 0x8f820224, +0x42040, 0xa4102b, 0x1040fff2, 0x0, 0x8f820220, 0x3c03f700, 0x431025, 0xaf820220, -0xaf800204, 0x3c010001, 0xac207e80, 0x8f830054, -0x24020006, 0x3c010001, 0x370821, 0xac2283ac, -0x3c010001, 0x80047f8, 0xac235e00, 0x8f830054, -0x3c020001, 0x8c425e00, 0x2463fff6, 0x431023, -0x2c42000a, 0x14400059, 0x0, 0x24020007, -0x3c010001, 0x370821, 0x80047f8, 0xac2283ac, -0x8f820220, 0x3c04f700, 0x441025, 0xaf820220, -0x8f820220, 0x3c030300, 0x431024, 0x14400005, -0x1821, 0x8f820220, 0x24030001, 0x441025, -0xaf820220, 0x10600043, 0x24020001, 0x8f820214, -0x3c03ffff, 0x3c040001, 0x8c845df8, 0x431024, -0x3442251f, 0xaf820214, 0x24020008, 0x3c010001, -0x370821, 0x1080000b, 0xac2283ac, 0x3c020001, -0x8c425dd4, 0x14400007, 0x24020001, 0x3c010001, -0xac227e30, 0xc004e2c, 0x8f840220, 0x80047e5, -0x0, 0x8f820220, 0x3c030008, 0x431024, -0x14400017, 0x2402000e, 0x3c010001, 0xac227e30, -0x8ee20000, 0x2021, 0x3c030200, 0x431025, -0xc005397, 0xaee20000, 0x8f820220, 0x2403fffb, -0x431024, 0xaf820220, 0x8f820220, 0x34420002, -0xc0043dd, 0xaf820220, 0x3c050001, 0x8ca55d28, -0xc005276, 0x2021, 0x80047f8, 0x0, -0x3c020001, 0x8c425dd4, 0x10400010, 0x0, -0x3c020001, 0x8c425dd0, 0x2442ffff, 0x3c010001, -0xac225dd0, 0x14400009, 0x24020002, 0x3c010001, -0xac205dd4, 0x3c010001, 0x80047f8, 0xac225dd0, -0x24020001, 0x3c010001, 0xac225d2c, 0x8fbf001c, -0x8fb00018, 0x3e00008, 0x27bd0020, 0x8f820200, -0x8f820220, 0x8f820220, 0x34420004, 0xaf820220, -0x8f820200, 0x3c060001, 0x8cc65d28, 0x34420004, -0xaf820200, 0x24020002, 0x10c2003a, 0x2cc20003, -0x10400005, 0x24020001, 0x10c20008, 0x0, -0x8004842, 0x0, 0x24020004, 0x10c20013, -0x24020001, 0x8004842, 0x0, 0x3c030001, -0x8c635d18, 0x3c020001, 0x8c425d20, 0x3c040001, -0x8c845d3c, 0x3c050001, 0x8ca55d1c, 0xaf860200, -0xaf860220, 0x34630022, 0x441025, 0x451025, -0x34420002, 0x8004841, 0xaf830200, 0x3c030001, -0x8c635df8, 0xaf820200, 0x10600009, 0xaf820220, -0x3c020001, 0x8c425dd4, 0x14400005, 0x3c033f00, -0x3c020001, 0x8c425d10, 0x8004835, 0x346300e0, -0x3c020001, 0x8c425d10, 0x3c033f00, 0x346300e2, -0x431025, 0xaf820200, 0x3c030001, 0x8c635d14, -0x3c04f700, 0x3c020001, 0x8c425d20, 0x3c050001, -0x8ca55d3c, 0x641825, 0x431025, 0x451025, -0xaf820220, 0x3e00008, 0x0, 0x8f820220, -0x3c030001, 0x8c635d28, 0x34420004, 0xaf820220, -0x24020001, 0x1062000f, 0x0, 0x8f830054, -0x8f820054, 0x24630002, 0x621023, 0x2c420003, -0x10400011, 0x0, 0x8f820054, 0x621023, -0x2c420003, 0x1040000c, 0x0, 0x8004853, -0x0, 0x8f830054, 0x8f820054, 0x800485f, -0x24630007, 0x8f820054, 0x621023, 0x2c420008, -0x1440fffc, 0x0, 0x8f8400e0, 0x30820007, -0x1040000d, 0x0, 0x8f820054, 0x8f8300e0, -0x14830009, 0x24450032, 0x8f820054, 0xa21023, -0x2c420033, 0x10400004, 0x0, 0x8f8200e0, -0x1082fff9, 0x0, 0x8f820220, 0x2403fffd, -0x431024, 0xaf820220, 0x3e00008, 0x0, -0x3c030001, 0x8c635d44, 0x3c020001, 0x8c425d48, -0x50620004, 0x2463ffff, 0x3c010001, 0xac235d48, -0x2463ffff, 0x2c620009, 0x1040009d, 0x31080, -0x3c010001, 0x220821, 0x8c225b58, 0x400008, -0x0, 0x8f820044, 0x34428080, 0xaf820044, -0x8f830054, 0x8004912, 0x24020002, 0x8f830054, -0x3c020001, 0x8c425e04, 0x2463d8f0, 0x431023, -0x2c422710, 0x1440008a, 0x24020003, 0x800491f, -0x0, 0x8f820044, 0x3c03ffff, 0x34637fff, -0x431024, 0xaf820044, 0x8f830054, 0x8004912, -0x24020004, 0x8f830054, 0x3c020001, 0x8c425e04, -0x2463fff6, 0x431023, 0x2c42000a, 0x14400078, -0x24020005, 0x800491f, 0x0, 0x8f820220, -0x3c03f700, 0x431025, 0xaf820220, 0x8f820220, -0x2403fffb, 0x431024, 0xaf820220, 0x8f820220, -0x34420002, 0xaf820220, 0x3c023f00, 0x344200e0, -0xaf820200, 0x8f820200, 0x2403fffd, 0x431024, -0xaf820200, 0x24040001, 0x3405ffff, 0xaf840204, -0x8f830054, 0x8f820054, 0x80048c6, 0x24630001, -0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, -0x0, 0x8f820224, 0x42040, 0xa4102b, -0x1040fff2, 0x0, 0x8f820220, 0x3c03f700, -0x431025, 0xaf820220, 0x8f820214, 0x3c03ffff, -0x431024, 0x3442251f, 0xaf820214, 0x8f820220, -0x2403fffb, 0x431024, 0xaf820220, 0x8f820220, -0x3c04f700, 0x34840008, 0x34420002, 0xaf820220, -0x8f820220, 0x3c033f00, 0x346300e2, 0x441025, -0xaf820220, 0xaf830200, 0x8f8400f0, 0x276217f8, -0x14820002, 0x24850008, 0x27651000, 0x8f8200f4, -0x10a20007, 0x3c038000, 0x34630040, 0x3c020001, -0x24425cd0, 0xac820000, 0xac830004, 0xaf8500f0, -0x8f830054, 0x8004912, 0x24020006, 0x8f830054, -0x3c020001, 0x8c425e04, 0x2463fff6, 0x431023, -0x2c42000a, 0x14400022, 0x24020007, 0x800491f, -0x0, 0x8f8200e0, 0xaf8200e4, 0x8f8200e0, -0xaf8200e8, 0x8f820220, 0x34420004, 0xaf820220, -0x8f820220, 0x2403fff7, 0x431024, 0xaf820220, -0x8f820044, 0x34428080, 0xaf820044, 0x8f830054, -0x24020008, 0x3c010001, 0xac225d44, 0x3c010001, -0x8004921, 0xac235e04, 0x8f830054, 0x3c020001, -0x8c425e04, 0x2463d8f0, 0x431023, 0x2c422710, -0x14400003, 0x24020009, 0x3c010001, 0xac225d44, -0x3e00008, 0x0, 0x0, 0x27bdffd8, +0x8f820214, 0x3c03ffff, 0x431024, 0x3442251f, +0xaf820214, 0x8f820220, 0x2403fffb, 0x431024, +0xaf820220, 0x8f820220, 0x3c04f700, 0x34840008, +0x34420002, 0xaf820220, 0x8f820220, 0x3c033f00, +0x346300e2, 0x441025, 0xaf820220, 0xaf830200, +0x8f8400f0, 0x276217f8, 0x14820002, 0x24850008, +0x27651000, 0x8f8200f4, 0x10a20007, 0x3c038000, +0x34630040, 0x3c020001, 0x24425c70, 0xac820000, +0xac830004, 0xaf8500f0, 0x8f830054, 0x8004938, +0x24020006, 0x8f830054, 0x3c020001, 0x8c425da8, +0x2463fff6, 0x431023, 0x2c42000a, 0x14400022, +0x24020007, 0x8004945, 0x0, 0x8f8200e0, +0xaf8200e4, 0x8f8200e0, 0xaf8200e8, 0x8f820220, +0x34420004, 0xaf820220, 0x8f820220, 0x2403fff7, +0x431024, 0xaf820220, 0x8f820044, 0x34428080, +0xaf820044, 0x8f830054, 0x24020008, 0x3c010001, +0xac225ce4, 0x3c010001, 0x8004947, 0xac235da8, +0x8f830054, 0x3c020001, 0x8c425da8, 0x2463d8f0, +0x431023, 0x2c422710, 0x14400003, 0x24020009, +0x3c010001, 0xac225ce4, 0x3e00008, 0x0, +0x0, 0x0, 0x0, 0x27bdffd8, 0xafb20018, 0x809021, 0xafb3001c, 0xa09821, 0xafb10014, 0xc08821, 0xafb00010, 0x8021, -0xafbf0020, 0xa6200000, 0xc004d23, 0x24040001, +0xafbf0020, 0xa6200000, 0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, -0xc004d23, 0x2021, 0xc004d23, 0x24040001, -0xc004d23, 0x24040001, 0xc004d23, 0x2021, +0xc004d4b, 0x2021, 0xc004d4b, 0x24040001, +0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, 0x24100010, 0x2501024, 0x10400002, 0x2021, -0x24040001, 0xc004d23, 0x108042, 0x1600fffa, +0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x2501024, 0x24100010, 0x2701024, 0x10400002, -0x2021, 0x24040001, 0xc004d23, 0x108042, -0x1600fffa, 0x2701024, 0xc004d49, 0x34108000, -0xc004d49, 0x0, 0xc004d03, 0x0, +0x2021, 0x24040001, 0xc004d4b, 0x108042, +0x1600fffa, 0x2701024, 0xc004d71, 0x34108000, +0xc004d71, 0x0, 0xc004d2b, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, 0x1600fff7, 0x0, -0xc004d49, 0x0, 0x8fbf0020, 0x8fb3001c, +0xc004d71, 0x0, 0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0028, 0x27bdffd8, 0xafb10014, 0x808821, 0xafb20018, 0xa09021, 0xafb3001c, 0xc09821, -0xafb00010, 0x8021, 0xafbf0020, 0xc004d23, +0xafb00010, 0x8021, 0xafbf0020, 0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004d23, 0x2021, 0xc004d23, -0x24040001, 0xc004d23, 0x2021, 0xc004d23, +0x0, 0xc004d4b, 0x2021, 0xc004d4b, +0x24040001, 0xc004d4b, 0x2021, 0xc004d4b, 0x24040001, 0x24100010, 0x2301024, 0x10400002, -0x2021, 0x24040001, 0xc004d23, 0x108042, +0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x2301024, 0x24100010, 0x2501024, -0x10400002, 0x2021, 0x24040001, 0xc004d23, -0x108042, 0x1600fffa, 0x2501024, 0xc004d23, -0x24040001, 0xc004d23, 0x2021, 0x34108000, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, +0x108042, 0x1600fffa, 0x2501024, 0xc004d4b, +0x24040001, 0xc004d4b, 0x2021, 0x34108000, 0x96620000, 0x501024, 0x10400002, 0x2021, -0x24040001, 0xc004d23, 0x108042, 0x1600fff8, -0x0, 0xc004d49, 0x0, 0x8fbf0020, +0x24040001, 0xc004d4b, 0x108042, 0x1600fff8, +0x0, 0xc004d71, 0x0, 0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, -0x3e00008, 0x27bd0028, 0x3c030001, 0x8c635d60, -0x3c020001, 0x8c425da8, 0x27bdffd8, 0xafbf0020, +0x3e00008, 0x27bd0028, 0x3c030001, 0x8c635d00, +0x3c020001, 0x8c425d48, 0x27bdffd8, 0xafbf0020, 0xafb1001c, 0x10620003, 0xafb00018, 0x3c010001, -0xac235da8, 0x2463ffff, 0x2c620013, 0x10400349, -0x31080, 0x3c010001, 0x220821, 0x8c225b80, -0x400008, 0x0, 0xc004d49, 0x8021, -0x34028000, 0xa7a20010, 0x27b10010, 0xc004d23, +0xac235d48, 0x2463ffff, 0x2c620013, 0x10400349, +0x31080, 0x3c010001, 0x220821, 0x8c225b30, +0x400008, 0x0, 0xc004d71, 0x8021, +0x34028000, 0xa7a20010, 0x27b10010, 0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004d23, 0x2021, 0xc004d23, -0x24040001, 0xc004d23, 0x2021, 0xc004d23, +0x0, 0xc004d4b, 0x2021, 0xc004d4b, +0x24040001, 0xc004d4b, 0x2021, 0xc004d4b, 0x24040001, 0x24100010, 0x32020001, 0x10400002, -0x2021, 0x24040001, 0xc004d23, 0x108042, -0x1600fffa, 0x32020001, 0x24100010, 0xc004d23, +0x2021, 0x24040001, 0xc004d4b, 0x108042, +0x1600fffa, 0x32020001, 0x24100010, 0xc004d4b, 0x2021, 0x108042, 0x1600fffc, 0x0, -0xc004d23, 0x24040001, 0xc004d23, 0x2021, +0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, -0x2021, 0x24040001, 0xc004d23, 0x108042, -0x1600fff8, 0x0, 0xc004d49, 0x0, -0x8004cfc, 0x24020002, 0x27b10010, 0xa7a00010, -0x8021, 0xc004d23, 0x24040001, 0x26100001, -0x2e020020, 0x1440fffb, 0x0, 0xc004d23, -0x2021, 0xc004d23, 0x24040001, 0xc004d23, -0x24040001, 0xc004d23, 0x2021, 0x24100010, +0x2021, 0x24040001, 0xc004d4b, 0x108042, +0x1600fff8, 0x0, 0xc004d71, 0x0, +0x8004d24, 0x24020002, 0x27b10010, 0xa7a00010, +0x8021, 0xc004d4b, 0x24040001, 0x26100001, +0x2e020020, 0x1440fffb, 0x0, 0xc004d4b, +0x2021, 0xc004d4b, 0x24040001, 0xc004d4b, +0x24040001, 0xc004d4b, 0x2021, 0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, -0xc004d23, 0x108042, 0x1600fffa, 0x32020001, -0x24100010, 0xc004d23, 0x2021, 0x108042, -0x1600fffc, 0x0, 0xc004d49, 0x34108000, -0xc004d49, 0x0, 0xc004d03, 0x0, +0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, +0x24100010, 0xc004d4b, 0x2021, 0x108042, +0x1600fffc, 0x0, 0xc004d71, 0x34108000, +0xc004d71, 0x0, 0xc004d2b, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, 0x1600fff7, 0x0, -0xc004d49, 0x0, 0x97a20010, 0x30428000, -0x144002dc, 0x24020003, 0x8004cfc, 0x0, +0xc004d71, 0x0, 0x97a20010, 0x30428000, +0x144002dc, 0x24020003, 0x8004d24, 0x0, 0x24021200, 0xa7a20010, 0x27b10010, 0x8021, -0xc004d23, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004d23, +0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, -0xc004d23, 0x2021, 0x108042, 0x1600fffc, -0x0, 0xc004d23, 0x24040001, 0xc004d23, +0xc004d4b, 0x2021, 0x108042, 0x1600fffc, +0x0, 0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, 0x34108000, 0x96220000, 0x501024, -0x10400002, 0x2021, 0x24040001, 0xc004d23, -0x108042, 0x1600fff8, 0x0, 0xc004d49, -0x0, 0x8f830054, 0x8004cee, 0x24020004, -0x8f830054, 0x3c020001, 0x8c425e14, 0x2463ff9c, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, +0x108042, 0x1600fff8, 0x0, 0xc004d71, +0x0, 0x8f830054, 0x8004d16, 0x24020004, +0x8f830054, 0x3c020001, 0x8c425db8, 0x2463ff9c, 0x431023, 0x2c420064, 0x1440029e, 0x24020002, -0x3c030001, 0x8c635e18, 0x10620297, 0x2c620003, +0x3c030001, 0x8c635dbc, 0x10620297, 0x2c620003, 0x14400296, 0x24020011, 0x24020003, 0x10620005, -0x24020004, 0x10620291, 0x2402000f, 0x8004cfc, -0x24020011, 0x8004cfc, 0x24020005, 0x24020014, -0xa7a20010, 0x27b10010, 0x8021, 0xc004d23, +0x24020004, 0x10620291, 0x2402000f, 0x8004d24, +0x24020011, 0x8004d24, 0x24020005, 0x24020014, +0xa7a20010, 0x27b10010, 0x8021, 0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004d23, 0x2021, 0xc004d23, -0x24040001, 0xc004d23, 0x2021, 0xc004d23, +0x0, 0xc004d4b, 0x2021, 0xc004d4b, +0x24040001, 0xc004d4b, 0x2021, 0xc004d4b, 0x24040001, 0x24100010, 0x32020001, 0x10400002, -0x2021, 0x24040001, 0xc004d23, 0x108042, +0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020012, -0x10400002, 0x2021, 0x24040001, 0xc004d23, -0x108042, 0x1600fffa, 0x32020012, 0xc004d23, -0x24040001, 0xc004d23, 0x2021, 0x34108000, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, +0x108042, 0x1600fffa, 0x32020012, 0xc004d4b, +0x24040001, 0xc004d4b, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, 0x2021, -0x24040001, 0xc004d23, 0x108042, 0x1600fff8, -0x0, 0xc004d49, 0x0, 0x8f830054, -0x8004cee, 0x24020006, 0x8f830054, 0x3c020001, -0x8c425e14, 0x2463ff9c, 0x431023, 0x2c420064, -0x14400250, 0x24020007, 0x8004cfc, 0x0, +0x24040001, 0xc004d4b, 0x108042, 0x1600fff8, +0x0, 0xc004d71, 0x0, 0x8f830054, +0x8004d16, 0x24020006, 0x8f830054, 0x3c020001, +0x8c425db8, 0x2463ff9c, 0x431023, 0x2c420064, +0x14400250, 0x24020007, 0x8004d24, 0x0, 0x24020006, 0xa7a20010, 0x27b10010, 0x8021, -0xc004d23, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004d23, +0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020013, 0x10400002, 0x2021, 0x24040001, -0xc004d23, 0x108042, 0x1600fffa, 0x32020013, -0xc004d23, 0x24040001, 0xc004d23, 0x2021, +0xc004d4b, 0x108042, 0x1600fffa, 0x32020013, +0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, -0x2021, 0x24040001, 0xc004d23, 0x108042, -0x1600fff8, 0x0, 0xc004d49, 0x0, -0x8f830054, 0x8004cee, 0x24020008, 0x8f830054, -0x3c020001, 0x8c425e14, 0x2463ff9c, 0x431023, -0x2c420064, 0x1440020f, 0x24020009, 0x8004cfc, +0x2021, 0x24040001, 0xc004d4b, 0x108042, +0x1600fff8, 0x0, 0xc004d71, 0x0, +0x8f830054, 0x8004d16, 0x24020008, 0x8f830054, +0x3c020001, 0x8c425db8, 0x2463ff9c, 0x431023, +0x2c420064, 0x1440020f, 0x24020009, 0x8004d24, 0x0, 0x27b10010, 0xa7a00010, 0x8021, -0xc004d23, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0xc004d23, 0x24040001, -0xc004d23, 0x2021, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004d23, +0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0xc004d4b, 0x24040001, +0xc004d4b, 0x2021, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 0x10400002, 0x2021, 0x24040001, -0xc004d23, 0x108042, 0x1600fffa, 0x32020018, -0xc004d49, 0x34108000, 0xc004d49, 0x0, -0xc004d03, 0x0, 0x50400005, 0x108042, +0xc004d4b, 0x108042, 0x1600fffa, 0x32020018, +0xc004d71, 0x34108000, 0xc004d71, 0x0, +0xc004d2b, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, -0x1600fff7, 0x0, 0xc004d49, 0x8021, +0x1600fff7, 0x0, 0xc004d71, 0x8021, 0x97a20010, 0x27b10010, 0x34420001, 0xa7a20010, -0xc004d23, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004d23, +0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 0x10400002, 0x2021, 0x24040001, -0xc004d23, 0x108042, 0x1600fffa, 0x32020018, -0xc004d23, 0x24040001, 0xc004d23, 0x2021, +0xc004d4b, 0x108042, 0x1600fffa, 0x32020018, +0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, -0x2021, 0x24040001, 0xc004d23, 0x108042, -0x1600fff8, 0x0, 0xc004d49, 0x0, -0x8f830054, 0x8004cee, 0x2402000a, 0x8f830054, -0x3c020001, 0x8c425e14, 0x2463ff9c, 0x431023, -0x2c420064, 0x1440019b, 0x2402000b, 0x8004cfc, +0x2021, 0x24040001, 0xc004d4b, 0x108042, +0x1600fff8, 0x0, 0xc004d71, 0x0, +0x8f830054, 0x8004d16, 0x2402000a, 0x8f830054, +0x3c020001, 0x8c425db8, 0x2463ff9c, 0x431023, +0x2c420064, 0x1440019b, 0x2402000b, 0x8004d24, 0x0, 0x27b10010, 0xa7a00010, 0x8021, -0xc004d23, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0xc004d23, 0x24040001, -0xc004d23, 0x2021, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004d23, +0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0xc004d4b, 0x24040001, +0xc004d4b, 0x2021, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020017, 0x10400002, 0x2021, 0x24040001, -0xc004d23, 0x108042, 0x1600fffa, 0x32020017, -0xc004d49, 0x34108000, 0xc004d49, 0x0, -0xc004d03, 0x0, 0x50400005, 0x108042, +0xc004d4b, 0x108042, 0x1600fffa, 0x32020017, +0xc004d71, 0x34108000, 0xc004d71, 0x0, +0xc004d2b, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, -0x1600fff7, 0x0, 0xc004d49, 0x8021, +0x1600fff7, 0x0, 0xc004d71, 0x8021, 0x97a20010, 0x27b10010, 0x34420700, 0xa7a20010, -0xc004d23, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004d23, +0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020017, 0x10400002, 0x2021, 0x24040001, -0xc004d23, 0x108042, 0x1600fffa, 0x32020017, -0xc004d23, 0x24040001, 0xc004d23, 0x2021, +0xc004d4b, 0x108042, 0x1600fffa, 0x32020017, +0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, -0x2021, 0x24040001, 0xc004d23, 0x108042, -0x1600fff8, 0x0, 0xc004d49, 0x0, -0x8f830054, 0x8004cee, 0x2402000c, 0x8f830054, -0x3c020001, 0x8c425e14, 0x2463ff9c, 0x431023, -0x2c420064, 0x14400127, 0x24020012, 0x8004cfc, +0x2021, 0x24040001, 0xc004d4b, 0x108042, +0x1600fff8, 0x0, 0xc004d71, 0x0, +0x8f830054, 0x8004d16, 0x2402000c, 0x8f830054, +0x3c020001, 0x8c425db8, 0x2463ff9c, 0x431023, +0x2c420064, 0x14400127, 0x24020012, 0x8004d24, 0x0, 0x27b10010, 0xa7a00010, 0x8021, -0xc004d23, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0xc004d23, 0x24040001, -0xc004d23, 0x2021, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004d23, +0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0xc004d4b, 0x24040001, +0xc004d4b, 0x2021, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020014, 0x10400002, 0x2021, 0x24040001, -0xc004d23, 0x108042, 0x1600fffa, 0x32020014, -0xc004d49, 0x34108000, 0xc004d49, 0x0, -0xc004d03, 0x0, 0x50400005, 0x108042, +0xc004d4b, 0x108042, 0x1600fffa, 0x32020014, +0xc004d71, 0x34108000, 0xc004d71, 0x0, +0xc004d2b, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, -0x1600fff7, 0x0, 0xc004d49, 0x8021, +0x1600fff7, 0x0, 0xc004d71, 0x8021, 0x97a20010, 0x27b10010, 0x34420010, 0xa7a20010, -0xc004d23, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004d23, +0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020014, 0x10400002, 0x2021, 0x24040001, -0xc004d23, 0x108042, 0x1600fffa, 0x32020014, -0xc004d23, 0x24040001, 0xc004d23, 0x2021, +0xc004d4b, 0x108042, 0x1600fffa, 0x32020014, +0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, -0x2021, 0x24040001, 0xc004d23, 0x108042, -0x1600fff8, 0x0, 0xc004d49, 0x0, -0x8f830054, 0x8004cee, 0x24020013, 0x8f830054, -0x3c020001, 0x8c425e14, 0x2463ff9c, 0x431023, -0x2c420064, 0x144000b3, 0x2402000d, 0x8004cfc, +0x2021, 0x24040001, 0xc004d4b, 0x108042, +0x1600fff8, 0x0, 0xc004d71, 0x0, +0x8f830054, 0x8004d16, 0x24020013, 0x8f830054, +0x3c020001, 0x8c425db8, 0x2463ff9c, 0x431023, +0x2c420064, 0x144000b3, 0x2402000d, 0x8004d24, 0x0, 0x27b10010, 0xa7a00010, 0x8021, -0xc004d23, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0xc004d23, 0x24040001, -0xc004d23, 0x2021, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004d23, +0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0xc004d4b, 0x24040001, +0xc004d4b, 0x2021, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 0x10400002, 0x2021, 0x24040001, -0xc004d23, 0x108042, 0x1600fffa, 0x32020018, -0xc004d49, 0x34108000, 0xc004d49, 0x0, -0xc004d03, 0x0, 0x50400005, 0x108042, +0xc004d4b, 0x108042, 0x1600fffa, 0x32020018, +0xc004d71, 0x34108000, 0xc004d71, 0x0, +0xc004d2b, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, -0x1600fff7, 0x0, 0xc004d49, 0x8021, +0x1600fff7, 0x0, 0xc004d71, 0x8021, 0x97a20010, 0x27b10010, 0x3042fffe, 0xa7a20010, -0xc004d23, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004d23, +0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 0x10400002, 0x2021, 0x24040001, -0xc004d23, 0x108042, 0x1600fffa, 0x32020018, -0xc004d23, 0x24040001, 0xc004d23, 0x2021, +0xc004d4b, 0x108042, 0x1600fffa, 0x32020018, +0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, -0x2021, 0x24040001, 0xc004d23, 0x108042, -0x1600fff8, 0x0, 0xc004d49, 0x0, -0x8f830054, 0x8004cee, 0x2402000e, 0x24020840, -0xa7a20010, 0x27b10010, 0x8021, 0xc004d23, +0x2021, 0x24040001, 0xc004d4b, 0x108042, +0x1600fff8, 0x0, 0xc004d71, 0x0, +0x8f830054, 0x8004d16, 0x2402000e, 0x24020840, +0xa7a20010, 0x27b10010, 0x8021, 0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004d23, 0x2021, 0xc004d23, -0x24040001, 0xc004d23, 0x2021, 0xc004d23, +0x0, 0xc004d4b, 0x2021, 0xc004d4b, +0x24040001, 0xc004d4b, 0x2021, 0xc004d4b, 0x24040001, 0x24100010, 0x32020001, 0x10400002, -0x2021, 0x24040001, 0xc004d23, 0x108042, +0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020013, -0x10400002, 0x2021, 0x24040001, 0xc004d23, -0x108042, 0x1600fffa, 0x32020013, 0xc004d23, -0x24040001, 0xc004d23, 0x2021, 0x34108000, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, +0x108042, 0x1600fffa, 0x32020013, 0xc004d4b, +0x24040001, 0xc004d4b, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, 0x2021, -0x24040001, 0xc004d23, 0x108042, 0x1600fff8, -0x0, 0xc004d49, 0x0, 0x8f830054, -0x24020010, 0x3c010001, 0xac225d60, 0x3c010001, -0x8004cfe, 0xac235e14, 0x8f830054, 0x3c020001, -0x8c425e14, 0x2463ff9c, 0x431023, 0x2c420064, +0x24040001, 0xc004d4b, 0x108042, 0x1600fff8, +0x0, 0xc004d71, 0x0, 0x8f830054, +0x24020010, 0x3c010001, 0xac225d00, 0x3c010001, +0x8004d26, 0xac235db8, 0x8f830054, 0x3c020001, +0x8c425db8, 0x2463ff9c, 0x431023, 0x2c420064, 0x14400004, 0x0, 0x24020011, 0x3c010001, -0xac225d60, 0x8fbf0020, 0x8fb1001c, 0x8fb00018, +0xac225d00, 0x8fbf0020, 0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0028, 0x8f850044, 0x8f820044, 0x3c030001, 0x431025, 0x3c030008, 0xaf820044, -0x8f840054, 0x8f820054, 0xa32824, 0x8004d0f, +0x8f840054, 0x8f820054, 0xa32824, 0x8004d37, 0x24840001, 0x8f820054, 0x821023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044, 0x8f830054, -0x8f820054, 0x8004d1d, 0x24630001, 0x8f820054, +0x8f820054, 0x8004d45, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x3e00008, 0xa01021, 0x8f830044, 0x3c02fff0, 0x3442ffff, 0x42480, 0x621824, 0x3c020002, 0x822025, 0x641825, 0xaf830044, 0x8f820044, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044, -0x8f830054, 0x8f820054, 0x8004d36, 0x24630001, +0x8f830054, 0x8f820054, 0x8004d5e, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 0x3c030001, 0x431025, -0xaf820044, 0x8f830054, 0x8f820054, 0x8004d43, +0xaf820044, 0x8f830054, 0x8f820054, 0x8004d6b, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x3e00008, 0x0, 0x8f820044, 0x3c03fff0, 0x3463ffff, 0x431024, 0xaf820044, 0x8f820044, 0x3c030001, 0x431025, -0xaf820044, 0x8f830054, 0x8f820054, 0x8004d57, +0xaf820044, 0x8f830054, 0x8f820054, 0x8004d7f, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044, 0x8f830054, -0x8f820054, 0x8004d65, 0x24630001, 0x8f820054, +0x8f820054, 0x8004d8d, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x3e00008, 0x0, 0x27bdffc8, 0xafb30024, 0x809821, 0xafb5002c, 0xa0a821, 0xafb20020, 0xc09021, 0x32a2ffff, 0xafbf0030, 0xafb40028, 0xafb1001c, 0xafb00018, 0x14400034, 0xa7b20010, -0x3271ffff, 0x27b20010, 0x8021, 0xc004d23, +0x3271ffff, 0x27b20010, 0x8021, 0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004d23, 0x2021, 0xc004d23, -0x24040001, 0xc004d23, 0x2021, 0xc004d23, +0x0, 0xc004d4b, 0x2021, 0xc004d4b, +0x24040001, 0xc004d4b, 0x2021, 0xc004d4b, 0x24040001, 0x24100010, 0x32020001, 0x10400002, -0x2021, 0x24040001, 0xc004d23, 0x108042, +0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x2301024, -0x10400002, 0x2021, 0x24040001, 0xc004d23, -0x108042, 0x1600fffa, 0x2301024, 0xc004d23, -0x24040001, 0xc004d23, 0x2021, 0x34108000, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, +0x108042, 0x1600fffa, 0x2301024, 0xc004d4b, +0x24040001, 0xc004d4b, 0x2021, 0x34108000, 0x96420000, 0x501024, 0x10400002, 0x2021, -0x24040001, 0xc004d23, 0x108042, 0x12000075, -0x0, 0x8004da1, 0x0, 0x3274ffff, -0x27b10010, 0xa7a00010, 0x8021, 0xc004d23, +0x24040001, 0xc004d4b, 0x108042, 0x12000075, +0x0, 0x8004dc9, 0x0, 0x3274ffff, +0x27b10010, 0xa7a00010, 0x8021, 0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004d23, 0x2021, 0xc004d23, -0x24040001, 0xc004d23, 0x24040001, 0xc004d23, +0x0, 0xc004d4b, 0x2021, 0xc004d4b, +0x24040001, 0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, 0x24100010, 0x32020001, 0x10400002, -0x2021, 0x24040001, 0xc004d23, 0x108042, +0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x2901024, -0x10400002, 0x2021, 0x24040001, 0xc004d23, -0x108042, 0x1600fffa, 0x2901024, 0xc004d49, -0x34108000, 0xc004d49, 0x0, 0xc004d03, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, +0x108042, 0x1600fffa, 0x2901024, 0xc004d71, +0x34108000, 0xc004d71, 0x0, 0xc004d2b, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, 0x1600fff7, -0x0, 0xc004d49, 0x0, 0x32a5ffff, +0x0, 0xc004d71, 0x0, 0x32a5ffff, 0x24020001, 0x54a20004, 0x24020002, 0x97a20010, -0x8004dec, 0x521025, 0x14a20006, 0x3271ffff, +0x8004e14, 0x521025, 0x14a20006, 0x3271ffff, 0x97a20010, 0x121827, 0x431024, 0xa7a20010, -0x3271ffff, 0x27b20010, 0x8021, 0xc004d23, +0x3271ffff, 0x27b20010, 0x8021, 0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004d23, 0x2021, 0xc004d23, -0x24040001, 0xc004d23, 0x2021, 0xc004d23, +0x0, 0xc004d4b, 0x2021, 0xc004d4b, +0x24040001, 0xc004d4b, 0x2021, 0xc004d4b, 0x24040001, 0x24100010, 0x32020001, 0x10400002, -0x2021, 0x24040001, 0xc004d23, 0x108042, +0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x2301024, -0x10400002, 0x2021, 0x24040001, 0xc004d23, -0x108042, 0x1600fffa, 0x2301024, 0xc004d23, -0x24040001, 0xc004d23, 0x2021, 0x34108000, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, +0x108042, 0x1600fffa, 0x2301024, 0xc004d4b, +0x24040001, 0xc004d4b, 0x2021, 0x34108000, 0x96420000, 0x501024, 0x10400002, 0x2021, -0x24040001, 0xc004d23, 0x108042, 0x1600fff8, -0x0, 0xc004d49, 0x0, 0x8fbf0030, +0x24040001, 0xc004d4b, 0x108042, 0x1600fff8, +0x0, 0xc004d71, 0x0, 0x8fbf0030, 0x8fb5002c, 0x8fb40028, 0x8fb30024, 0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0038, 0x0, 0x0, 0x0, 0x27bdffe8, 0xafbf0010, 0x3c030001, 0x771821, 0x8c6383ac, 0x24020008, 0x1462022c, 0x803021, 0x3c020001, -0x8c425df8, 0x14400033, 0x0, 0x8f850224, +0x8c425d98, 0x14400033, 0x0, 0x8f850224, 0x38a30020, 0x2c630001, 0x38a20010, 0x2c420001, 0x621825, 0x1460000d, 0x38a30030, 0x2c630001, 0x38a20400, 0x2c420001, 0x621825, 0x14600007, 0x38a30402, 0x2c630001, 0x38a20404, 0x2c420001, 0x621825, 0x10600005, 0x0, 0xc00429b, -0x0, 0x8004e65, 0x2402000e, 0xc0043dd, -0x0, 0x3c050001, 0x8ca55d28, 0xc005276, -0x2021, 0x3c030001, 0x8c635d28, 0x24020004, -0x14620005, 0x2403fffb, 0x3c020001, 0x8c425d24, -0x8004e61, 0x2403fff7, 0x3c020001, 0x8c425d24, -0x431024, 0x3c010001, 0xac225d24, 0x2402000e, -0x3c010001, 0xc00429b, 0xac227e30, 0x800505f, +0x0, 0x8004e8d, 0x2402000e, 0xc0043dd, +0x0, 0x3c050001, 0x8ca55cc8, 0xc0052a2, +0x2021, 0x3c030001, 0x8c635cc8, 0x24020004, +0x14620005, 0x2403fffb, 0x3c020001, 0x8c425cc4, +0x8004e89, 0x2403fff7, 0x3c020001, 0x8c425cc4, +0x431024, 0x3c010001, 0xac225cc4, 0x2402000e, +0x3c010001, 0xc00429b, 0xac227dd0, 0x8005087, 0x0, 0x8f820220, 0x3c030400, 0x431024, 0x10400027, 0x2403ffbf, 0x8f850224, 0x3c020001, -0x8c427e3c, 0xa32024, 0x431024, 0x1482000c, -0x0, 0x3c020001, 0x8c427e40, 0x24420001, -0x3c010001, 0xac227e40, 0x2c420002, 0x14400008, -0x24020001, 0x3c010001, 0x8004e85, 0xac227e60, -0x3c010001, 0xac207e40, 0x3c010001, 0xac207e60, -0x3c020001, 0x8c427e60, 0x10400006, 0x30a20040, -0x10400004, 0x24020001, 0x3c010001, 0x8004e90, -0xac227e64, 0x3c010001, 0xac207e64, 0x3c010001, -0xac257e3c, 0x3c010001, 0x8004ea0, 0xac207e70, -0x24020001, 0x3c010001, 0xac227e70, 0x3c010001, -0xac207e60, 0x3c010001, 0xac207e40, 0x3c010001, -0xac207e64, 0x3c010001, 0xac207e3c, 0x3c030001, -0x8c637e30, 0x3c020001, 0x8c427e34, 0x10620003, -0x3c020200, 0x3c010001, 0xac237e34, 0xc21024, +0x8c427ddc, 0xa32024, 0x431024, 0x1482000c, +0x0, 0x3c020001, 0x8c427de0, 0x24420001, +0x3c010001, 0xac227de0, 0x2c420002, 0x14400008, +0x24020001, 0x3c010001, 0x8004ead, 0xac227e00, +0x3c010001, 0xac207de0, 0x3c010001, 0xac207e00, +0x3c020001, 0x8c427e00, 0x10400006, 0x30a20040, +0x10400004, 0x24020001, 0x3c010001, 0x8004eb8, +0xac227e04, 0x3c010001, 0xac207e04, 0x3c010001, +0xac257ddc, 0x3c010001, 0x8004ec8, 0xac207e10, +0x24020001, 0x3c010001, 0xac227e10, 0x3c010001, +0xac207e00, 0x3c010001, 0xac207de0, 0x3c010001, +0xac207e04, 0x3c010001, 0xac207ddc, 0x3c030001, +0x8c637dd0, 0x3c020001, 0x8c427dd4, 0x10620003, +0x3c020200, 0x3c010001, 0xac237dd4, 0xc21024, 0x10400007, 0x2463ffff, 0x8f820220, 0x24030001, -0x3c010001, 0xac235d2c, 0x800505d, 0x3c03f700, +0x3c010001, 0xac235ccc, 0x8005085, 0x3c03f700, 0x2c62000e, 0x104001a8, 0x31080, 0x3c010001, -0x220821, 0x8c225bd0, 0x400008, 0x0, -0x3c010001, 0xac207e60, 0x3c010001, 0xac207e40, -0x3c010001, 0xac207e3c, 0x3c010001, 0xac207e64, -0x3c010001, 0xac207e58, 0x3c010001, 0xac207e50, -0xc004844, 0xaf800224, 0x24020002, 0x3c010001, -0xac227e30, 0x3c020001, 0x8c427e70, 0x14400056, +0x220821, 0x8c225b80, 0x400008, 0x0, +0x3c010001, 0xac207e00, 0x3c010001, 0xac207de0, +0x3c010001, 0xac207ddc, 0x3c010001, 0xac207e04, +0x3c010001, 0xac207df8, 0x3c010001, 0xac207df0, +0xc00486a, 0xaf800224, 0x24020002, 0x3c010001, +0xac227dd0, 0x3c020001, 0x8c427e10, 0x14400056, 0x3c03fdff, 0x8ee20000, 0x3463ffff, 0x431024, 0xc00429b, 0xaee20000, 0xaf800204, 0x8f820200, 0x2403fffd, 0x431024, 0xaf820200, 0x3c010001, -0xac207e80, 0x8f830054, 0x3c020001, 0x8c427e58, -0x24040001, 0x3c010001, 0xac247e6c, 0x24420001, -0x3c010001, 0xac227e58, 0x2c420004, 0x3c010001, -0xac237e54, 0x14400006, 0x24020003, 0x3c010001, -0xac245d2c, 0x3c010001, 0x800505b, 0xac207e58, -0x3c010001, 0x800505b, 0xac227e30, 0x8f830054, -0x3c020001, 0x8c427e54, 0x2463d8f0, 0x431023, +0xac207e20, 0x8f830054, 0x3c020001, 0x8c427df8, +0x24040001, 0x3c010001, 0xac247e0c, 0x24420001, +0x3c010001, 0xac227df8, 0x2c420004, 0x3c010001, +0xac237df4, 0x14400006, 0x24020003, 0x3c010001, +0xac245ccc, 0x3c010001, 0x8005083, 0xac207df8, +0x3c010001, 0x8005083, 0xac227dd0, 0x8f830054, +0x3c020001, 0x8c427df4, 0x2463d8f0, 0x431023, 0x2c422710, 0x14400003, 0x24020004, 0x3c010001, -0xac227e30, 0x3c020001, 0x8c427e70, 0x14400026, +0xac227dd0, 0x3c020001, 0x8c427e10, 0x14400026, 0x3c03fdff, 0x8ee20000, 0x3463ffff, 0x431024, -0x800505b, 0xaee20000, 0x3c040001, 0x8c845dfc, -0x3c010001, 0xc005062, 0xac207e48, 0x3c020001, -0x8c427e7c, 0xaf820204, 0x3c020001, 0x8c427e70, +0x8005083, 0xaee20000, 0x3c040001, 0x8c845d9c, +0x3c010001, 0xc00508a, 0xac207de8, 0x3c020001, +0x8c427e1c, 0xaf820204, 0x3c020001, 0x8c427e10, 0x14400015, 0x3c03fdff, 0x8ee20000, 0x3463ffff, 0x431024, 0xaee20000, 0x8f820204, 0x30420030, -0x1440013c, 0x24020002, 0x3c030001, 0x8c637e7c, -0x24020005, 0x3c010001, 0xac227e30, 0x3c010001, -0x800505b, 0xac237e80, 0x3c020001, 0x8c427e70, -0x10400010, 0x3c03fdff, 0x3c020001, 0x8c425dcc, -0x24420001, 0x3c010001, 0xac225dcc, 0x2c420002, -0x14400131, 0x24020001, 0x3c010001, 0xac225dd4, -0x3c010001, 0xac205dcc, 0x3c010001, 0x800505b, -0xac225d2c, 0x8ee20000, 0x3463ffff, 0x431024, -0xaee20000, 0x3c020001, 0x8c427e60, 0x10400122, -0x0, 0x3c020001, 0x8c427e3c, 0x1040011e, -0x0, 0x3c010001, 0xac227e68, 0x24020003, -0x3c010001, 0xac227e40, 0x8004ffc, 0x24020006, -0x3c010001, 0xac207e48, 0x8f820204, 0x34420040, -0xaf820204, 0x3c020001, 0x8c427e80, 0x24030007, -0x3c010001, 0xac237e30, 0x34420040, 0x3c010001, -0xac227e80, 0x3c020001, 0x8c427e60, 0x10400005, -0x0, 0x3c020001, 0x8c427e3c, 0x104000f9, -0x24020002, 0x3c050001, 0x24a57e40, 0x8ca20000, +0x1440013c, 0x24020002, 0x3c030001, 0x8c637e1c, +0x24020005, 0x3c010001, 0xac227dd0, 0x3c010001, +0x8005083, 0xac237e20, 0x3c020001, 0x8c427e10, +0x10400010, 0x3c03fdff, 0x3c020001, 0x8c425d6c, +0x24420001, 0x3c010001, 0xac225d6c, 0x2c420002, +0x14400131, 0x24020001, 0x3c010001, 0xac225d74, +0x3c010001, 0xac205d6c, 0x3c010001, 0x8005083, +0xac225ccc, 0x8ee20000, 0x3463ffff, 0x431024, +0xaee20000, 0x3c020001, 0x8c427e00, 0x10400122, +0x0, 0x3c020001, 0x8c427ddc, 0x1040011e, +0x0, 0x3c010001, 0xac227e08, 0x24020003, +0x3c010001, 0xac227de0, 0x8005024, 0x24020006, +0x3c010001, 0xac207de8, 0x8f820204, 0x34420040, +0xaf820204, 0x3c020001, 0x8c427e20, 0x24030007, +0x3c010001, 0xac237dd0, 0x34420040, 0x3c010001, +0xac227e20, 0x3c020001, 0x8c427e00, 0x10400005, +0x0, 0x3c020001, 0x8c427ddc, 0x104000f9, +0x24020002, 0x3c050001, 0x24a57de0, 0x8ca20000, 0x2c424e21, 0x104000f3, 0x24020002, 0x3c020001, -0x8c427e64, 0x104000f8, 0x2404ffbf, 0x3c020001, -0x8c427e3c, 0x3c030001, 0x8c637e68, 0x441024, +0x8c427e04, 0x104000f8, 0x2404ffbf, 0x3c020001, +0x8c427ddc, 0x3c030001, 0x8c637e08, 0x441024, 0x641824, 0x10430004, 0x24020001, 0x3c010001, -0x800505b, 0xac227e30, 0x24020003, 0xaca20000, -0x24020008, 0x3c010001, 0xac227e30, 0x3c020001, -0x8c427e6c, 0x1040000c, 0x24020001, 0x3c040001, -0xc00506f, 0x8c847e3c, 0x3c020001, 0x8c427e88, -0x14400005, 0x24020001, 0x3c020001, 0x8c427e84, -0x10400006, 0x24020001, 0x3c010001, 0xac225d2c, -0x3c010001, 0x800505b, 0xac207e58, 0x3c020001, -0x8c427e50, 0x3c030001, 0x8c637e3c, 0x2c420001, -0x210c0, 0x30630008, 0x3c010001, 0xac227e50, -0x3c010001, 0xac237e4c, 0x8f830054, 0x24020009, -0x3c010001, 0xac227e30, 0x3c010001, 0x800505b, -0xac237e54, 0x8f830054, 0x3c020001, 0x8c427e54, +0x8005083, 0xac227dd0, 0x24020003, 0xaca20000, +0x24020008, 0x3c010001, 0xac227dd0, 0x3c020001, +0x8c427e0c, 0x1040000c, 0x24020001, 0x3c040001, +0xc005097, 0x8c847ddc, 0x3c020001, 0x8c427e28, +0x14400005, 0x24020001, 0x3c020001, 0x8c427e24, +0x10400006, 0x24020001, 0x3c010001, 0xac225ccc, +0x3c010001, 0x8005083, 0xac207df8, 0x3c020001, +0x8c427df0, 0x3c030001, 0x8c637ddc, 0x2c420001, +0x210c0, 0x30630008, 0x3c010001, 0xac227df0, +0x3c010001, 0xac237dec, 0x8f830054, 0x24020009, +0x3c010001, 0xac227dd0, 0x3c010001, 0x8005083, +0xac237df4, 0x8f830054, 0x3c020001, 0x8c427df4, 0x2463d8f0, 0x431023, 0x2c422710, 0x144000a8, -0x0, 0x3c020001, 0x8c427e60, 0x10400005, -0x0, 0x3c020001, 0x8c427e3c, 0x104000a9, -0x24020002, 0x3c030001, 0x24637e40, 0x8c620000, +0x0, 0x3c020001, 0x8c427e00, 0x10400005, +0x0, 0x3c020001, 0x8c427ddc, 0x104000a9, +0x24020002, 0x3c030001, 0x24637de0, 0x8c620000, 0x2c424e21, 0x104000a3, 0x24020002, 0x3c020001, -0x8c427e6c, 0x1040000e, 0x0, 0x3c020001, -0x8c427e3c, 0x3c010001, 0xac207e6c, 0x30420080, +0x8c427e0c, 0x1040000e, 0x0, 0x3c020001, +0x8c427ddc, 0x3c010001, 0xac207e0c, 0x30420080, 0x1040002f, 0x2402000c, 0x8f820204, 0x30420080, -0x1440000c, 0x24020003, 0x8004fe9, 0x2402000c, -0x3c020001, 0x8c427e3c, 0x30420080, 0x14400005, +0x1440000c, 0x24020003, 0x8005011, 0x2402000c, +0x3c020001, 0x8c427ddc, 0x30420080, 0x14400005, 0x24020003, 0x8f820204, 0x30420080, 0x1040001f, 0x24020003, 0xac620000, 0x2402000a, 0x3c010001, -0xac227e30, 0x3c040001, 0x24847e78, 0x8c820000, -0x3c030001, 0x8c637e50, 0x431025, 0xaf820204, -0x8c830000, 0x3c040001, 0x8c847e50, 0x2402000b, -0x3c010001, 0xac227e30, 0x641825, 0x3c010001, -0xac237e80, 0x3c050001, 0x24a57e40, 0x8ca20000, +0xac227dd0, 0x3c040001, 0x24847e18, 0x8c820000, +0x3c030001, 0x8c637df0, 0x431025, 0xaf820204, +0x8c830000, 0x3c040001, 0x8c847df0, 0x2402000b, +0x3c010001, 0xac227dd0, 0x641825, 0x3c010001, +0xac237e20, 0x3c050001, 0x24a57de0, 0x8ca20000, 0x2c424e21, 0x1040006f, 0x24020002, 0x3c020001, -0x8c427e70, 0x10400005, 0x0, 0x2402000c, -0x3c010001, 0x800505b, 0xac227e30, 0x3c020001, -0x8c427e60, 0x1040006c, 0x0, 0x3c040001, -0x8c847e3c, 0x1080005e, 0x30820008, 0x3c030001, -0x8c637e4c, 0x10620064, 0x24020003, 0x3c010001, -0xac247e68, 0xaca20000, 0x24020006, 0x3c010001, -0x800505b, 0xac227e30, 0x8f820200, 0x34420002, +0x8c427e10, 0x10400005, 0x0, 0x2402000c, +0x3c010001, 0x8005083, 0xac227dd0, 0x3c020001, +0x8c427e00, 0x1040006c, 0x0, 0x3c040001, +0x8c847ddc, 0x1080005e, 0x30820008, 0x3c030001, +0x8c637dec, 0x10620064, 0x24020003, 0x3c010001, +0xac247e08, 0xaca20000, 0x24020006, 0x3c010001, +0x8005083, 0xac227dd0, 0x8f820200, 0x34420002, 0xaf820200, 0x8f830054, 0x2402000d, 0x3c010001, -0xac227e30, 0x3c010001, 0xac237e54, 0x8f830054, -0x3c020001, 0x8c427e54, 0x2463d8f0, 0x431023, +0xac227dd0, 0x3c010001, 0xac237df4, 0x8f830054, +0x3c020001, 0x8c427df4, 0x2463d8f0, 0x431023, 0x2c422710, 0x1440003a, 0x0, 0x3c020001, -0x8c427e70, 0x10400029, 0x2402000e, 0x3c030001, -0x8c637e84, 0x3c010001, 0x14600015, 0xac227e30, -0xc0043dd, 0x0, 0x3c050001, 0x8ca55d28, -0xc005276, 0x2021, 0x3c030001, 0x8c635d28, +0x8c427e10, 0x10400029, 0x2402000e, 0x3c030001, +0x8c637e24, 0x3c010001, 0x14600015, 0xac227dd0, +0xc0043dd, 0x0, 0x3c050001, 0x8ca55cc8, +0xc0052a2, 0x2021, 0x3c030001, 0x8c635cc8, 0x24020004, 0x14620005, 0x2403fffb, 0x3c020001, -0x8c425d24, 0x800502a, 0x2403fff7, 0x3c020001, -0x8c425d24, 0x431024, 0x3c010001, 0xac225d24, +0x8c425cc4, 0x8005052, 0x2403fff7, 0x3c020001, +0x8c425cc4, 0x431024, 0x3c010001, 0xac225cc4, 0x8ee20000, 0x3c030200, 0x431025, 0xaee20000, -0x8f820224, 0x3c010001, 0xac227e8c, 0x8f820220, +0x8f820224, 0x3c010001, 0xac227e2c, 0x8f820220, 0x2403fffb, 0x431024, 0xaf820220, 0x8f820220, -0x34420002, 0x800505b, 0xaf820220, 0x3c020001, -0x8c427e60, 0x10400005, 0x0, 0x3c020001, -0x8c427e3c, 0x1040000f, 0x24020002, 0x3c020001, -0x8c427e40, 0x2c424e21, 0x1040000a, 0x24020002, -0x3c020001, 0x8c427e60, 0x1040000f, 0x0, -0x3c020001, 0x8c427e3c, 0x1440000b, 0x0, -0x24020002, 0x3c010001, 0x800505b, 0xac227e30, -0x3c020001, 0x8c427e60, 0x10400003, 0x0, +0x34420002, 0x8005083, 0xaf820220, 0x3c020001, +0x8c427e00, 0x10400005, 0x0, 0x3c020001, +0x8c427ddc, 0x1040000f, 0x24020002, 0x3c020001, +0x8c427de0, 0x2c424e21, 0x1040000a, 0x24020002, +0x3c020001, 0x8c427e00, 0x1040000f, 0x0, +0x3c020001, 0x8c427ddc, 0x1440000b, 0x0, +0x24020002, 0x3c010001, 0x8005083, 0xac227dd0, +0x3c020001, 0x8c427e00, 0x10400003, 0x0, 0xc00429b, 0x0, 0x8f820220, 0x3c03f700, 0x431025, 0xaf820220, 0x8fbf0010, 0x3e00008, -0x27bd0018, 0x3c030001, 0x24637e88, 0x8c620000, -0x10400005, 0x34422000, 0x3c010001, 0xac227e7c, -0x800506d, 0xac600000, 0x3c010001, 0xac247e7c, +0x27bd0018, 0x3c030001, 0x24637e28, 0x8c620000, +0x10400005, 0x34422000, 0x3c010001, 0xac227e1c, +0x8005095, 0xac600000, 0x3c010001, 0xac247e1c, 0x3e00008, 0x0, 0x27bdffe0, 0x30820030, -0xafbf0018, 0x3c010001, 0xac227e84, 0x14400067, +0xafbf0018, 0x3c010001, 0xac227e24, 0x14400067, 0x3c02ffff, 0x34421f0e, 0x821024, 0x14400061, 0x24020030, 0x30822000, 0x1040005d, 0x30838000, 0x31a02, 0x30820001, 0x21200, 0x3c040001, -0x8c845dfc, 0x621825, 0x331c2, 0x3c030001, -0x24635dd8, 0x30828000, 0x21202, 0x30840001, +0x8c845d9c, 0x621825, 0x331c2, 0x3c030001, +0x24635d78, 0x30828000, 0x21202, 0x30840001, 0x42200, 0x441025, 0x239c2, 0x61080, 0x431021, 0x471021, 0x90430000, 0x24020001, 0x10620025, 0x0, 0x10600007, 0x24020002, 0x10620013, 0x24020003, 0x1062002c, 0x3c05000f, -0x80050d1, 0x0, 0x8f820200, 0x2403feff, +0x80050f9, 0x0, 0x8f820200, 0x2403feff, 0x431024, 0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820220, 0x3c010001, -0xac207ea4, 0x3c010001, 0x80050dc, 0xac207eac, +0xac207e44, 0x3c010001, 0x8005104, 0xac207e4c, 0x8f820200, 0x34420100, 0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820220, -0x24020100, 0x3c010001, 0xac227ea4, 0x3c010001, -0x80050dc, 0xac207eac, 0x8f820200, 0x2403feff, +0x24020100, 0x3c010001, 0xac227e44, 0x3c010001, +0x8005104, 0xac207e4c, 0x8f820200, 0x2403feff, 0x431024, 0xaf820200, 0x8f820220, 0x3c030001, -0x431025, 0xaf820220, 0x3c010001, 0xac207ea4, -0x3c010001, 0x80050dc, 0xac237eac, 0x8f820200, +0x431025, 0xaf820220, 0x3c010001, 0xac207e44, +0x3c010001, 0x8005104, 0xac237e4c, 0x8f820200, 0x34420100, 0xaf820200, 0x8f820220, 0x3c030001, 0x431025, 0xaf820220, 0x24020100, 0x3c010001, -0xac227ea4, 0x3c010001, 0x80050dc, 0xac237eac, -0x34a5ffff, 0x3c040001, 0x24845c08, 0xafa30010, -0xc002403, 0xafa00014, 0x80050dc, 0x0, -0x24020030, 0x3c010001, 0xac227e88, 0x8fbf0018, +0xac227e44, 0x3c010001, 0x8005104, 0xac237e4c, +0x34a5ffff, 0x3c040001, 0x24845bb8, 0xafa30010, +0xc002403, 0xafa00014, 0x8005104, 0x0, +0x24020030, 0x3c010001, 0xac227e28, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x0, 0x27bdffc8, 0xafb20028, 0x809021, 0xafb3002c, 0xa09821, -0xafb00020, 0xc08021, 0x3c040001, 0x24845c20, -0x3c050009, 0x3c020001, 0x8c425d28, 0x34a59001, +0xafb00020, 0xc08021, 0x3c040001, 0x24845bd0, +0x3c050009, 0x3c020001, 0x8c425cc8, 0x34a59001, 0x2403021, 0x2603821, 0xafbf0030, 0xafb10024, 0xa7a0001a, 0xafb00014, 0xc002403, 0xafa20010, -0x24020002, 0x1262007f, 0x2e620003, 0x10400005, -0x24020001, 0x1262000a, 0x0, 0x800526f, -0x0, 0x24020004, 0x126200f6, 0x24020008, -0x126200f5, 0x3c02ffec, 0x800526f, 0x0, -0x3c020001, 0x8c425d24, 0x30420002, 0x14400004, +0x24020002, 0x12620083, 0x2e620003, 0x10400005, +0x24020001, 0x1262000a, 0x0, 0x800529b, +0x0, 0x24020004, 0x126200fa, 0x24020008, +0x126200f9, 0x3c02ffec, 0x800529b, 0x0, +0x3c020001, 0x8c425cc4, 0x30420002, 0x14400004, 0x128940, 0x3c02fffb, 0x3442ffff, 0x2028024, -0x3c010001, 0x310821, 0xac307e9c, 0x3c024000, -0x2021024, 0x1040004a, 0x1023c2, 0x30840030, -0x101382, 0x3042001c, 0x3c030001, 0x24635d68, +0x3c010001, 0x310821, 0xac307e3c, 0x3c024000, +0x2021024, 0x1040004e, 0x1023c2, 0x30840030, +0x101382, 0x3042001c, 0x3c030001, 0x24635d08, 0x431021, 0x823821, 0x3c020020, 0x2021024, 0x10400006, 0x24020100, 0x3c010001, 0x310821, -0xac227ea0, 0x8005128, 0x3c020080, 0x3c010001, -0x310821, 0xac207ea0, 0x3c020080, 0x2021024, +0xac227e40, 0x8005150, 0x3c020080, 0x3c010001, +0x310821, 0xac207e40, 0x3c020080, 0x2021024, 0x10400006, 0x121940, 0x3c020001, 0x3c010001, -0x230821, 0x8005134, 0xac227ea8, 0x121140, -0x3c010001, 0x220821, 0xac207ea8, 0x94e30000, -0x32024000, 0x10400003, 0xa7a30018, 0x34624000, +0x230821, 0x800515c, 0xac227e48, 0x121140, +0x3c010001, 0x220821, 0xac207e48, 0x94e40000, +0x3c030001, 0x8c635dbc, 0x24020005, 0x10620010, +0xa7a40018, 0x32024000, 0x10400002, 0x34824000, 0xa7a20018, 0x24040001, 0x94e20002, 0x24050004, -0x24e60002, 0x34420001, 0xc004966, 0xa4e20002, -0x24040001, 0x2821, 0xc004966, 0x27a60018, -0x3c020001, 0x8c425d28, 0x24110001, 0x3c010001, -0xac315d34, 0x14530004, 0x32028000, 0xc00429b, +0x24e60002, 0x34420001, 0xc00498e, 0xa4e20002, +0x24040001, 0x2821, 0xc00498e, 0x27a60018, +0x3c020001, 0x8c425cc8, 0x24110001, 0x3c010001, +0xac315cd4, 0x14530004, 0x32028000, 0xc00429b, 0x0, 0x32028000, 0x1040011f, 0x0, -0xc00429b, 0x0, 0x3c030001, 0x8c635e18, +0xc00429b, 0x0, 0x3c030001, 0x8c635dbc, 0x24020005, 0x10620118, 0x24020002, 0x3c010001, -0xac315d2c, 0x3c010001, 0x800526f, 0xac225d28, -0x24040001, 0x24050004, 0x27b0001a, 0xc004966, -0x2003021, 0x24040001, 0x2821, 0xc004966, -0x2003021, 0x3c020001, 0x511021, 0x8c427e94, -0x3c040001, 0x8c845d28, 0x3c03bfff, 0x3463ffff, -0x3c010001, 0xac335d34, 0x431024, 0x3c010001, -0x310821, 0x109300fa, 0xac227e94, 0x800526f, +0xac315ccc, 0x3c010001, 0x800529b, 0xac225cc8, +0x24040001, 0x24050004, 0x27b0001a, 0xc00498e, +0x2003021, 0x24040001, 0x2821, 0xc00498e, +0x2003021, 0x3c020001, 0x511021, 0x8c427e34, +0x3c040001, 0x8c845cc8, 0x3c03bfff, 0x3463ffff, +0x3c010001, 0xac335cd4, 0x431024, 0x3c010001, +0x310821, 0x109300fa, 0xac227e34, 0x800529b, 0x0, 0x3c022000, 0x2021024, 0x10400005, -0x24020001, 0x3c010001, 0xac225df8, 0x8005181, -0x128940, 0x3c010001, 0xac205df8, 0x128940, -0x3c010001, 0x310821, 0xac307e98, 0x3c024000, +0x24020001, 0x3c010001, 0xac225d98, 0x80051ad, +0x128940, 0x3c010001, 0xac205d98, 0x128940, +0x3c010001, 0x310821, 0xac307e38, 0x3c024000, 0x2021024, 0x14400016, 0x0, 0x3c020001, -0x8c425df8, 0x10400008, 0x24040004, 0x24050001, -0xc004d6b, 0x24062000, 0x24020001, 0x3c010001, +0x8c425d98, 0x10400008, 0x24040004, 0x24050001, +0xc004d93, 0x24062000, 0x24020001, 0x3c010001, 0x370821, 0xac2283ac, 0x3c020001, 0x511021, -0x8c427e90, 0x3c03bfff, 0x3463ffff, 0x431024, -0x3c010001, 0x310821, 0x800526d, 0xac227e90, -0x3c020001, 0x8c425df8, 0x10400028, 0x3c0300a0, +0x8c427e30, 0x3c03bfff, 0x3463ffff, 0x431024, +0x3c010001, 0x310821, 0x8005299, 0xac227e30, +0x3c020001, 0x8c425d98, 0x10400028, 0x3c0300a0, 0x2031024, 0x5443000d, 0x3c020020, 0x3c020001, -0x8c425dfc, 0x24030100, 0x3c010001, 0x310821, -0xac237ea4, 0x3c030001, 0x3c010001, 0x310821, -0xac237eac, 0x80051c4, 0x34420400, 0x2021024, -0x10400008, 0x24030100, 0x3c020001, 0x8c425dfc, -0x3c010001, 0x310821, 0xac237ea4, 0x80051c4, +0x8c425d9c, 0x24030100, 0x3c010001, 0x310821, +0xac237e44, 0x3c030001, 0x3c010001, 0x310821, +0xac237e4c, 0x80051f0, 0x34420400, 0x2021024, +0x10400008, 0x24030100, 0x3c020001, 0x8c425d9c, +0x3c010001, 0x310821, 0xac237e44, 0x80051f0, 0x34420800, 0x3c020080, 0x2021024, 0x1040002e, -0x3c030001, 0x3c020001, 0x8c425dfc, 0x3c010001, -0x310821, 0xac237eac, 0x34420c00, 0x3c010001, -0xac225dfc, 0x80051ec, 0x24040001, 0x3c020020, +0x3c030001, 0x3c020001, 0x8c425d9c, 0x3c010001, +0x310821, 0xac237e4c, 0x34420c00, 0x3c010001, +0xac225d9c, 0x8005218, 0x24040001, 0x3c020020, 0x2021024, 0x10400006, 0x24020100, 0x3c010001, -0x310821, 0xac227ea4, 0x80051d5, 0x3c020080, -0x3c010001, 0x310821, 0xac207ea4, 0x3c020080, +0x310821, 0xac227e44, 0x8005201, 0x3c020080, +0x3c010001, 0x310821, 0xac207e44, 0x3c020080, 0x2021024, 0x10400007, 0x121940, 0x3c020001, -0x3c010001, 0x230821, 0xac227eac, 0x80051e3, +0x3c010001, 0x230821, 0xac227e4c, 0x800520f, 0x24040001, 0x121140, 0x3c010001, 0x220821, -0xac207eac, 0x24040001, 0x2821, 0x27b0001e, -0xc004924, 0x2003021, 0x24040001, 0x2821, -0xc004924, 0x2003021, 0x24040001, 0x24050001, -0x27b0001c, 0xc004924, 0x2003021, 0x24040001, -0x24050001, 0xc004924, 0x2003021, 0x800526d, +0xac207e4c, 0x24040001, 0x2821, 0x27b0001e, +0xc00494c, 0x2003021, 0x24040001, 0x2821, +0xc00494c, 0x2003021, 0x24040001, 0x24050001, +0x27b0001c, 0xc00494c, 0x2003021, 0x24040001, +0x24050001, 0xc00494c, 0x2003021, 0x8005299, 0x0, 0x3c02ffec, 0x3442ffff, 0x2028024, 0x3c020008, 0x2028025, 0x121140, 0x3c010001, -0x220821, 0xac307e98, 0x3c022000, 0x2021024, -0x10400009, 0x0, 0x3c020001, 0x8c425dd4, -0x14400005, 0x24020001, 0x3c010001, 0xac225df8, -0x800520e, 0x3c024000, 0x3c010001, 0xac205df8, +0x220821, 0xac307e38, 0x3c022000, 0x2021024, +0x10400009, 0x0, 0x3c020001, 0x8c425d74, +0x14400005, 0x24020001, 0x3c010001, 0xac225d98, +0x800523a, 0x3c024000, 0x3c010001, 0xac205d98, 0x3c024000, 0x2021024, 0x1440001e, 0x0, -0x3c020001, 0x8c425df8, 0x3c010001, 0xac205d40, -0x10400007, 0x24022020, 0x3c010001, 0xac225dfc, +0x3c020001, 0x8c425d98, 0x3c010001, 0xac205ce0, +0x10400007, 0x24022020, 0x3c010001, 0xac225d9c, 0x24020001, 0x3c010001, 0x370821, 0xac2283ac, 0x3c04bfff, 0x121940, 0x3c020001, 0x431021, -0x8c427e90, 0x3c050001, 0x8ca55d28, 0x3484ffff, -0x441024, 0x3c010001, 0x230821, 0xac227e90, -0x24020001, 0x10a20044, 0x0, 0x800526d, -0x0, 0x3c020001, 0x8c425df8, 0x1040001c, -0x24022000, 0x3c010001, 0xac225dfc, 0x3c0300a0, +0x8c427e30, 0x3c050001, 0x8ca55cc8, 0x3484ffff, +0x441024, 0x3c010001, 0x230821, 0xac227e30, +0x24020001, 0x10a20044, 0x0, 0x8005299, +0x0, 0x3c020001, 0x8c425d98, 0x1040001c, +0x24022000, 0x3c010001, 0xac225d9c, 0x3c0300a0, 0x2031024, 0x14430005, 0x121140, 0x3402a000, -0x3c010001, 0x8005268, 0xac225dfc, 0x3c030001, -0x621821, 0x8c637e98, 0x3c020020, 0x621024, -0x10400004, 0x24022001, 0x3c010001, 0x8005268, -0xac225dfc, 0x3c020080, 0x621024, 0x1040001f, -0x3402a001, 0x3c010001, 0x8005268, 0xac225dfc, +0x3c010001, 0x8005294, 0xac225d9c, 0x3c030001, +0x621821, 0x8c637e38, 0x3c020020, 0x621024, +0x10400004, 0x24022001, 0x3c010001, 0x8005294, +0xac225d9c, 0x3c020080, 0x621024, 0x1040001f, +0x3402a001, 0x3c010001, 0x8005294, 0xac225d9c, 0x3c020020, 0x2021024, 0x10400007, 0x121940, -0x24020100, 0x3c010001, 0x230821, 0xac227ea4, -0x800525c, 0x3c020080, 0x121140, 0x3c010001, -0x220821, 0xac207ea4, 0x3c020080, 0x2021024, +0x24020100, 0x3c010001, 0x230821, 0xac227e44, +0x8005288, 0x3c020080, 0x121140, 0x3c010001, +0x220821, 0xac207e44, 0x3c020080, 0x2021024, 0x10400006, 0x121940, 0x3c020001, 0x3c010001, -0x230821, 0x8005268, 0xac227eac, 0x121140, -0x3c010001, 0x220821, 0xac207eac, 0x3c030001, -0x8c635d28, 0x24020001, 0x10620003, 0x0, +0x230821, 0x8005294, 0xac227e4c, 0x121140, +0x3c010001, 0x220821, 0xac207e4c, 0x3c030001, +0x8c635cc8, 0x24020001, 0x10620003, 0x0, 0xc00429b, 0x0, 0x8fbf0030, 0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020, 0x3e00008, -0x27bd0038, 0x27bdffc0, 0xafb40038, 0x80a021, -0xafb20030, 0x9021, 0xafb1002c, 0x8821, -0x24020002, 0xafbf003c, 0xafb30034, 0xafb00028, -0xa7a00020, 0xa7a00018, 0xa7a0001a, 0xa7a0001c, -0x10a20108, 0xa7a0001e, 0x2ca20003, 0x10400005, -0x24020001, 0x10a2000a, 0x149940, 0x800538f, -0x2201021, 0x24020004, 0x10a200b2, 0x24020008, -0x10a200b1, 0x142940, 0x800538f, 0x2201021, -0x3c030001, 0x731821, 0x8c637e9c, 0x3c024000, -0x621024, 0x14400009, 0x24040001, 0x3c027fff, -0x3442ffff, 0x628824, 0x3c010001, 0x330821, -0xac317e94, 0x800538f, 0x2201021, 0x2821, -0xc004924, 0x27a60018, 0x24040001, 0x2821, -0xc004924, 0x27a60018, 0x24040001, 0x24050001, -0x27b0001a, 0xc004924, 0x2003021, 0x24040001, -0x24050001, 0xc004924, 0x2003021, 0x24040001, -0x24050004, 0x27b0001c, 0xc004924, 0x2003021, -0x24040001, 0x24050004, 0xc004924, 0x2003021, -0x24040001, 0x24050005, 0x27b0001e, 0xc004924, -0x2003021, 0x24040001, 0x24050005, 0xc004924, -0x2003021, 0x24040001, 0x24050009, 0xc004924, -0x2003021, 0x24040001, 0x24050009, 0xc004924, -0x2003021, 0x24040001, 0x24050001, 0xc004924, -0x27a60018, 0x24040001, 0x24050001, 0xc004924, -0x27a60018, 0x97a20018, 0x30420004, 0x10400034, -0x3c114000, 0x3c020001, 0x8c425e18, 0x2443ffff, -0x2c620006, 0x10400034, 0x31080, 0x3c010001, -0x220821, 0x8c225c38, 0x400008, 0x0, -0x24040001, 0x24050011, 0x27b00020, 0xc004924, -0x2003021, 0x24040001, 0x24050011, 0xc004924, -0x2003021, 0x97a40020, 0x30824000, 0x10400002, -0x3c030010, 0x3c030008, 0x3c120001, 0x8005306, -0x30828000, 0x24040001, 0x24050014, 0x27b00020, -0xc004924, 0x2003021, 0x24040001, 0x24050014, -0xc004924, 0x2003021, 0x97a40020, 0x30821000, -0x10400002, 0x3c030010, 0x3c030008, 0x3c120001, -0x30820800, 0x54400001, 0x3c120002, 0x3c028000, -0x2221025, 0x2431825, 0x8005313, 0x438825, -0x3c110001, 0x2338821, 0x8e317e9c, 0x3c027fff, -0x3442ffff, 0x2228824, 0x3c020001, 0x8c425d38, -0x1040001c, 0x0, 0x3c020001, 0x8c425df8, -0x10400002, 0x3c022000, 0x2228825, 0x141140, -0x3c010001, 0x220821, 0x8c227ea0, 0x10400003, -0x3c020020, 0x8005327, 0x2228825, 0x3c02ffdf, -0x3442ffff, 0x2228824, 0x141140, 0x3c010001, -0x220821, 0x8c227ea8, 0x10400003, 0x3c020080, -0x8005332, 0x2228825, 0x3c02ff7f, 0x3442ffff, -0x2228824, 0x3c040001, 0x24845c2c, 0x3c05000c, -0x34a50326, 0x3c070001, 0x8ce75d28, 0x3021, -0x141140, 0x3c010001, 0x220821, 0xac317e94, -0xafb20010, 0xc002403, 0xafb10014, 0x800538f, -0x2201021, 0x142940, 0x3c030001, 0x651821, -0x8c637e98, 0x3c024000, 0x621024, 0x14400008, -0x3c027fff, 0x3442ffff, 0x628824, 0x3c010001, -0x250821, 0xac317e90, 0x800538f, 0x2201021, -0x3c020001, 0x8c425d38, 0x10400033, 0x3c11c00c, -0x3c020001, 0x8c425dd4, 0x3c04c00c, 0x34842000, -0x3c030001, 0x8c635df8, 0x2102b, 0x21023, -0x441024, 0x10600003, 0x518825, 0x3c022000, -0x2228825, 0x3c020001, 0x451021, 0x8c427ea4, -0x10400003, 0x3c020020, 0x800536c, 0x2228825, -0x3c02ffdf, 0x3442ffff, 0x2228824, 0x141140, -0x3c010001, 0x220821, 0x8c227eac, 0x10400003, -0x3c020080, 0x8005377, 0x2228825, 0x3c02ff7f, -0x3442ffff, 0x2228824, 0x3c020001, 0x8c425dc0, -0x10400002, 0x3c020800, 0x2228825, 0x3c020001, -0x8c425dc4, 0x10400002, 0x3c020400, 0x2228825, -0x3c020001, 0x8c425dc8, 0x10400006, 0x3c020100, -0x800538a, 0x2228825, 0x3c027fff, 0x3442ffff, -0x628824, 0x141140, 0x3c010001, 0x220821, -0xac317e90, 0x2201021, 0x8fbf003c, 0x8fb40038, -0x8fb30034, 0x8fb20030, 0x8fb1002c, 0x8fb00028, -0x3e00008, 0x27bd0040, 0x27bdffd8, 0xafb40020, -0x80a021, 0xafbf0024, 0xafb3001c, 0xafb20018, -0xafb10014, 0xafb00010, 0x8f900200, 0x3c030001, -0x8c635d28, 0x8f930220, 0x24020002, 0x10620063, -0x2c620003, 0x10400005, 0x24020001, 0x1062000a, -0x141940, 0x8005459, 0x0, 0x24020004, -0x1062005a, 0x24020008, 0x10620059, 0x149140, -0x8005459, 0x0, 0x3c040001, 0x832021, -0x8c847e9c, 0x3c110001, 0x2238821, 0x8e317e94, -0x3c024000, 0x821024, 0x1040003e, 0x3c020008, -0x2221024, 0x10400020, 0x36100002, 0x3c020001, -0x431021, 0x8c427ea0, 0x10400005, 0x36100020, -0x36100100, 0x3c020020, 0x80053ce, 0x2228825, -0x2402feff, 0x2028024, 0x3c02ffdf, 0x3442ffff, +0x27bd0038, 0x27bdffd8, 0xafb20020, 0x809021, +0xafb1001c, 0x8821, 0x24020002, 0xafbf0024, +0xafb00018, 0xa7a00012, 0x10a200d3, 0xa7a00010, +0x2ca20003, 0x10400005, 0x24020001, 0x10a2000a, +0x128140, 0x8005380, 0x2201021, 0x24020004, +0x10a2007d, 0x24020008, 0x10a2007c, 0x122940, +0x8005380, 0x2201021, 0x3c030001, 0x701821, +0x8c637e3c, 0x3c024000, 0x621024, 0x14400009, +0x24040001, 0x3c027fff, 0x3442ffff, 0x628824, +0x3c010001, 0x300821, 0xac317e34, 0x8005380, +0x2201021, 0x24050001, 0xc00494c, 0x27a60010, +0x24040001, 0x24050001, 0xc00494c, 0x27a60010, +0x97a20010, 0x30420004, 0x10400034, 0x3c114000, +0x3c020001, 0x8c425dbc, 0x2443ffff, 0x2c620006, +0x10400034, 0x31080, 0x3c010001, 0x220821, +0x8c225be0, 0x400008, 0x0, 0x24040001, +0x24050011, 0x27b00012, 0xc00494c, 0x2003021, +0x24040001, 0x24050011, 0xc00494c, 0x2003021, +0x97a50012, 0x30a24000, 0x10400002, 0x3c040010, +0x3c040008, 0x3c030001, 0x8005301, 0x30a28000, +0x24040001, 0x24050014, 0x27b00012, 0xc00494c, +0x2003021, 0x24040001, 0x24050014, 0xc00494c, +0x2003021, 0x97a50012, 0x30a21000, 0x10400002, +0x3c040010, 0x3c040008, 0x3c030001, 0x30a20800, +0x54400001, 0x3c030002, 0x3c028000, 0x2221025, +0x641825, 0x800530e, 0x438825, 0x3c110001, +0x2308821, 0x8e317e3c, 0x3c027fff, 0x3442ffff, +0x2228824, 0x3c020001, 0x8c425cd8, 0x1040001d, +0x121140, 0x3c020001, 0x8c425d98, 0x10400002, +0x3c022000, 0x2228825, 0x121140, 0x3c010001, +0x220821, 0x8c227e40, 0x10400003, 0x3c020020, +0x8005322, 0x2228825, 0x3c02ffdf, 0x3442ffff, +0x2228824, 0x121140, 0x3c010001, 0x220821, +0x8c227e48, 0x10400003, 0x3c020080, 0x800532d, +0x2228825, 0x3c02ff7f, 0x3442ffff, 0x2228824, +0x121140, 0x3c010001, 0x220821, 0xac317e34, +0x8005380, 0x2201021, 0x122940, 0x3c030001, +0x651821, 0x8c637e38, 0x3c024000, 0x621024, +0x14400008, 0x3c027fff, 0x3442ffff, 0x628824, +0x3c010001, 0x250821, 0xac317e30, 0x8005380, +0x2201021, 0x3c020001, 0x8c425cd8, 0x10400033, +0x3c11c00c, 0x3c020001, 0x8c425d74, 0x3c04c00c, +0x34842000, 0x3c030001, 0x8c635d98, 0x2102b, +0x21023, 0x441024, 0x10600003, 0x518825, +0x3c022000, 0x2228825, 0x3c020001, 0x451021, +0x8c427e44, 0x10400003, 0x3c020020, 0x800535d, +0x2228825, 0x3c02ffdf, 0x3442ffff, 0x2228824, +0x121140, 0x3c010001, 0x220821, 0x8c227e4c, +0x10400003, 0x3c020080, 0x8005368, 0x2228825, +0x3c02ff7f, 0x3442ffff, 0x2228824, 0x3c020001, +0x8c425d60, 0x10400002, 0x3c020800, 0x2228825, +0x3c020001, 0x8c425d64, 0x10400002, 0x3c020400, +0x2228825, 0x3c020001, 0x8c425d68, 0x10400006, +0x3c020100, 0x800537b, 0x2228825, 0x3c027fff, +0x3442ffff, 0x628824, 0x121140, 0x3c010001, +0x220821, 0xac317e30, 0x2201021, 0x8fbf0024, +0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x3e00008, +0x27bd0028, 0x27bdffd8, 0xafb40020, 0x80a021, +0xafbf0024, 0xafb3001c, 0xafb20018, 0xafb10014, +0xafb00010, 0x8f900200, 0x3c030001, 0x8c635cc8, +0x8f930220, 0x24020002, 0x10620063, 0x2c620003, +0x10400005, 0x24020001, 0x1062000a, 0x141940, +0x8005448, 0x0, 0x24020004, 0x1062005a, +0x24020008, 0x10620059, 0x149140, 0x8005448, +0x0, 0x3c040001, 0x832021, 0x8c847e3c, +0x3c110001, 0x2238821, 0x8e317e34, 0x3c024000, +0x821024, 0x1040003e, 0x3c020008, 0x2221024, +0x10400020, 0x36100002, 0x3c020001, 0x431021, +0x8c427e40, 0x10400005, 0x36100020, 0x36100100, +0x3c020020, 0x80053bd, 0x2228825, 0x2402feff, +0x2028024, 0x3c02ffdf, 0x3442ffff, 0x2228824, +0x141140, 0x3c010001, 0x220821, 0x8c227e48, +0x10400005, 0x3c020001, 0x2629825, 0x3c020080, +0x80053dc, 0x2228825, 0x3c02fffe, 0x3442ffff, +0x2629824, 0x3c02ff7f, 0x3442ffff, 0x80053dc, +0x2228824, 0x2402fedf, 0x2028024, 0x3c02fffe, +0x3442ffff, 0x2629824, 0x3c02ff5f, 0x3442ffff, +0x2228824, 0x3c010001, 0x230821, 0xac207e40, +0x3c010001, 0x230821, 0xac207e48, 0xc00486a, +0x0, 0xaf900200, 0xaf930220, 0x8f820220, +0x2403fffb, 0x431024, 0xaf820220, 0x8f820220, +0x34420002, 0xaf820220, 0x80053f3, 0x141140, +0x8f820200, 0x2403fffd, 0x431024, 0xc00486a, +0xaf820200, 0x3c02bfff, 0x3442ffff, 0xc00429b, 0x2228824, 0x141140, 0x3c010001, 0x220821, -0x8c227ea8, 0x10400005, 0x3c020001, 0x2629825, -0x3c020080, 0x80053ed, 0x2228825, 0x3c02fffe, -0x3442ffff, 0x2629824, 0x3c02ff7f, 0x3442ffff, -0x80053ed, 0x2228824, 0x2402fedf, 0x2028024, -0x3c02fffe, 0x3442ffff, 0x2629824, 0x3c02ff5f, -0x3442ffff, 0x2228824, 0x3c010001, 0x230821, -0xac207ea0, 0x3c010001, 0x230821, 0xac207ea8, -0xc004844, 0x0, 0xaf900200, 0xaf930220, +0x8005448, 0xac317e34, 0x149140, 0x3c040001, +0x922021, 0x8c847e38, 0x3c110001, 0x2328821, +0x8e317e30, 0x3c024000, 0x821024, 0x14400011, +0x0, 0x3c020001, 0x8c425d98, 0x14400006, +0x3c02bfff, 0x8f820200, 0x34420002, 0xc00486a, +0xaf820200, 0x3c02bfff, 0x3442ffff, 0xc00429b, +0x2228824, 0x3c010001, 0x320821, 0x8005448, +0xac317e30, 0x3c020001, 0x8c425d98, 0x10400005, +0x3c020020, 0x3c020001, 0x8c425d74, 0x1040002b, +0x3c020020, 0x821024, 0x10400007, 0x36100020, +0x24020100, 0x3c010001, 0x320821, 0xac227e44, +0x8005428, 0x36100100, 0x3c010001, 0x320821, +0xac207e44, 0x2402feff, 0x2028024, 0x3c020080, +0x821024, 0x10400007, 0x141940, 0x3c020001, +0x3c010001, 0x230821, 0xac227e4c, 0x8005439, +0x2629825, 0x141140, 0x3c010001, 0x220821, +0xac207e4c, 0x3c02fffe, 0x3442ffff, 0x2629824, +0xc00486a, 0x0, 0xaf900200, 0xaf930220, 0x8f820220, 0x2403fffb, 0x431024, 0xaf820220, -0x8f820220, 0x34420002, 0xaf820220, 0x8005404, -0x141140, 0x8f820200, 0x2403fffd, 0x431024, -0xc004844, 0xaf820200, 0x3c02bfff, 0x3442ffff, -0xc00429b, 0x2228824, 0x141140, 0x3c010001, -0x220821, 0x8005459, 0xac317e94, 0x149140, -0x3c040001, 0x922021, 0x8c847e98, 0x3c110001, -0x2328821, 0x8e317e90, 0x3c024000, 0x821024, -0x14400011, 0x0, 0x3c020001, 0x8c425df8, -0x14400006, 0x3c02bfff, 0x8f820200, 0x34420002, -0xc004844, 0xaf820200, 0x3c02bfff, 0x3442ffff, -0xc00429b, 0x2228824, 0x3c010001, 0x320821, -0x8005459, 0xac317e90, 0x3c020001, 0x8c425df8, -0x10400005, 0x3c020020, 0x3c020001, 0x8c425dd4, -0x1040002b, 0x3c020020, 0x821024, 0x10400007, -0x36100020, 0x24020100, 0x3c010001, 0x320821, -0xac227ea4, 0x8005439, 0x36100100, 0x3c010001, -0x320821, 0xac207ea4, 0x2402feff, 0x2028024, -0x3c020080, 0x821024, 0x10400007, 0x141940, -0x3c020001, 0x3c010001, 0x230821, 0xac227eac, -0x800544a, 0x2629825, 0x141140, 0x3c010001, -0x220821, 0xac207eac, 0x3c02fffe, 0x3442ffff, -0x2629824, 0xc004844, 0x0, 0xaf900200, -0xaf930220, 0x8f820220, 0x2403fffb, 0x431024, -0xaf820220, 0x8f820220, 0x34420002, 0xaf820220, -0x141140, 0x3c010001, 0x220821, 0xac317e90, -0x8fbf0024, 0x8fb40020, 0x8fb3001c, 0x8fb20018, -0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0028, -0x0, 0x0, 0x0, 0x0 }; +0x8f820220, 0x34420002, 0xaf820220, 0x141140, +0x3c010001, 0x220821, 0xac317e30, 0x8fbf0024, +0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, +0x8fb00010, 0x3e00008, 0x27bd0028, 0x0 }; u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = { 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, @@ -4473,10 +4468,10 @@ 0x32203139, 0x39382f30, 0x342f3237, 0x2032323a, 0x31333a34, 0x30207368, 0x75616e67, 0x20457870, 0x20240000, 0x46575f56, 0x45525349, 0x4f4e3a20, -0x23312053, 0x61742044, 0x65632031, 0x31203136, -0x3a30333a, 0x31392050, 0x53542031, 0x39393900, +0x23312046, 0x72692041, 0x70722037, 0x2031373a, +0x35353a34, 0x38205044, 0x54203230, 0x30300000, 0x46575f43, 0x4f4d5049, 0x4c455f54, 0x494d453a, -0x2031363a, 0x30333a31, 0x39000000, 0x46575f43, +0x2031373a, 0x35353a34, 0x38000000, 0x46575f43, 0x4f4d5049, 0x4c455f42, 0x593a2064, 0x65767263, 0x73000000, 0x46575f43, 0x4f4d5049, 0x4c455f48, 0x4f53543a, 0x20636f6d, 0x70757465, 0x0, @@ -4554,27 +4549,27 @@ 0x2e322031, 0x3939382f, 0x30342f32, 0x37203232, 0x3a31333a, 0x33392073, 0x6875616e, 0x67204578, 0x70202400, 0x50726f62, 0x65506879, 0x0, -0x6c6e6b41, 0x53535254, 0x0, 0x11af4, -0x11b8c, 0x11bac, 0x11bf0, 0x11c1c, -0x11c30, 0x11c6c, 0x11fe0, 0x11d48, -0x11d88, 0x11db4, 0x11df4, 0x11e24, -0x11e60, 0x11e94, 0x11fe0, 0x12228, -0x12240, 0x12268, 0x12288, 0x122b0, -0x123e0, 0x12408, 0x1245c, 0x12484, -0x0, 0x126ec, 0x127bc, 0x12894, -0x12964, 0x129c0, 0x12a9c, 0x12ac4, -0x12ba0, 0x12bc8, 0x12d70, 0x12d98, -0x12f40, 0x13138, 0x133cc, 0x132e0, -0x133cc, 0x133f8, 0x12f68, 0x13110, -0x0, 0x13ae4, 0x13b28, 0x13bc0, -0x13c0c, 0x13c7c, 0x13d14, 0x13d48, -0x13dd0, 0x13e68, 0x13f38, 0x13f78, -0x13ffc, 0x14020, 0x14154, 0x646f4261, +0x6c6e6b41, 0x53535254, 0x0, 0x11b2c, +0x11bc4, 0x11bf8, 0x11c2c, 0x11c58, +0x11c6c, 0x11ca8, 0x1207c, 0x11de4, +0x11e24, 0x11e50, 0x11e90, 0x11ec0, +0x11efc, 0x11f30, 0x1207c, 0x122c0, +0x122d8, 0x12300, 0x12320, 0x12348, +0x12478, 0x124a0, 0x124f4, 0x1251c, +0x0, 0x1278c, 0x1285c, 0x12934, +0x12a04, 0x12a60, 0x12b3c, 0x12b64, +0x12c40, 0x12c68, 0x12e10, 0x12e38, +0x12fe0, 0x131d8, 0x1346c, 0x13380, +0x1346c, 0x13498, 0x13008, 0x131b0, +0x0, 0x13b84, 0x13bc8, 0x13c60, +0x13cac, 0x13d1c, 0x13db4, 0x13de8, +0x13e70, 0x13f08, 0x13fd8, 0x14018, +0x1409c, 0x140c0, 0x141f4, 0x646f4261, 0x73655067, 0x0, 0x0, 0x0, 0x0, 0x73746d61, 0x634c4e4b, 0x0, -0x6765746d, 0x636c6e6b, 0x0, 0x14c4c, -0x14c4c, 0x14b94, 0x14bd8, 0x14c4c, -0x14c4c, 0x0 }; +0x0, 0x14c38, 0x14c38, 0x14b80, +0x14bc4, 0x14c38, 0x14c38, 0x0, +0x0, 0x0 }; u32 tigonFwData[(MAX_DATA_LEN/4) + 1] __initdata = { 0x416c7465, 0x6f6e2041, 0x63654e49, 0x43205600, 0x416c7465, @@ -4604,25 +4599,25 @@ /* Generated by genfw.c */ #define tigon2FwReleaseMajor 0xc #define tigon2FwReleaseMinor 0x4 -#define tigon2FwReleaseFix 0x5 +#define tigon2FwReleaseFix 0xb #define tigon2FwStartAddr 0x00004000 #define tigon2FwTextAddr 0x00004000 -#define tigon2FwTextLen 0x11c50 -#define tigon2FwRodataAddr 0x00015c50 -#define tigon2FwRodataLen 0x10c0 -#define tigon2FwDataAddr 0x00016d40 +#define tigon2FwTextLen 0x11bc0 +#define tigon2FwRodataAddr 0x00015bc0 +#define tigon2FwRodataLen 0x10d0 +#define tigon2FwDataAddr 0x00016cc0 #define tigon2FwDataLen 0x1c0 -#define tigon2FwSbssAddr 0x00016f00 -#define tigon2FwSbssLen 0xc4 -#define tigon2FwBssAddr 0x00016fd0 +#define tigon2FwSbssAddr 0x00016e80 +#define tigon2FwSbssLen 0xcc +#define tigon2FwBssAddr 0x00016f50 #define tigon2FwBssLen 0x20c0 u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x0, 0x10000003, 0x0, 0xd, 0xd, -0x3c1d0001, 0x8fbd6da0, 0x3a0f021, 0x3c100000, +0x3c1d0001, 0x8fbd6d20, 0x3a0f021, 0x3c100000, 0x26104000, 0xc0010c0, 0x0, 0xd, -0x3c1d0001, 0x8fbd6da4, 0x3a0f021, 0x3c100000, -0x26104000, 0xc0017c8, 0x0, 0xd, +0x3c1d0001, 0x8fbd6d24, 0x3a0f021, 0x3c100000, +0x26104000, 0xc0017e0, 0x0, 0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, @@ -4634,22 +4629,22 @@ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2000008, -0x0, 0x8001717, 0x3c0a0001, 0x8001717, -0x3c0a0002, 0x8001717, 0x0, 0x8002c68, -0x0, 0x8002c0b, 0x0, 0x8001717, -0x3c0a0004, 0x8003272, 0x0, 0x8001a3a, -0x0, 0x8003925, 0x0, 0x80038cc, -0x0, 0x8001717, 0x3c0a0006, 0x8003993, -0x3c0a0007, 0x8001717, 0x3c0a0008, 0x8001717, -0x3c0a0009, 0x80039eb, 0x0, 0x8002e62, -0x0, 0x8001717, 0x3c0a000b, 0x8001717, -0x3c0a000c, 0x8001717, 0x3c0a000d, 0x80028d7, -0x0, 0x800286c, 0x0, 0x8001717, -0x3c0a000e, 0x8002074, 0x0, 0x800194c, -0x0, 0x80019ec, 0x0, 0x8003c7e, -0x0, 0x8003c6c, 0x0, 0x8001717, -0x0, 0x8001902, 0x0, 0x8001717, -0x0, 0x8001717, 0x3c0a0013, 0x8001717, +0x0, 0x800172f, 0x3c0a0001, 0x800172f, +0x3c0a0002, 0x800172f, 0x0, 0x8002cac, +0x0, 0x8002c4f, 0x0, 0x800172f, +0x3c0a0004, 0x800328a, 0x0, 0x8001a52, +0x0, 0x800394d, 0x0, 0x80038f4, +0x0, 0x800172f, 0x3c0a0006, 0x80039bb, +0x3c0a0007, 0x800172f, 0x3c0a0008, 0x800172f, +0x3c0a0009, 0x8003a13, 0x0, 0x8002ea6, +0x0, 0x800172f, 0x3c0a000b, 0x800172f, +0x3c0a000c, 0x800172f, 0x3c0a000d, 0x80028fb, +0x0, 0x8002890, 0x0, 0x800172f, +0x3c0a000e, 0x800208c, 0x0, 0x8001964, +0x0, 0x8001a04, 0x0, 0x8003ca6, +0x0, 0x8003c94, 0x0, 0x800172f, +0x0, 0x800191a, 0x0, 0x800172f, +0x0, 0x800172f, 0x3c0a0013, 0x800172f, 0x3c0a0014, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, @@ -4667,335 +4662,341 @@ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x27bdffe0, 0x3c1cc000, 0xafbf001c, 0xafb00018, 0x8f820140, -0x24030003, 0xaf8300ec, 0x34420004, 0xc002afc, -0xaf820140, 0x3c0100c0, 0xc00174b, 0xac203ffc, -0x403021, 0x3c020008, 0x3c010001, 0xac266f18, -0x50c2000d, 0x24020008, 0x3c100010, 0x10d00009, -0x24050100, 0x3c040001, 0x24845d04, 0x3821, -0xafa00010, 0xc002b17, 0xafa00014, 0x3c010001, -0xac306f18, 0x24020008, 0x3c010001, 0xac226f30, -0x2402001f, 0x3c010001, 0xac226f40, 0x24020016, -0x3c010001, 0xac226f14, 0x3c05fffe, 0x34a56f08, -0x3c020001, 0x8c426f18, 0x3c030002, 0x24639090, -0x3c040001, 0x8c846d44, 0x431023, 0x14800002, -0x458021, 0x2610fa38, 0x2402f000, 0x2028024, -0xc00176d, 0x2002021, 0x2022823, 0x3c040020, -0x821823, 0x651823, 0x247bb000, 0x3c03fffe, -0x3463bf08, 0x363b821, 0x3c0600bf, 0x34c6f000, -0x3c070001, 0x8ce76d40, 0x3c0300bf, 0x3463e000, -0x852023, 0x3c010001, 0xac246f24, 0x822023, -0x3c010001, 0xac256f0c, 0x52842, 0x3c010001, -0xac226f00, 0x27620ffc, 0x3c010001, 0xac226da0, -0x27621ffc, 0xdb3023, 0x7b1823, 0x3c010001, -0xac246f04, 0x3c010001, 0xac256f28, 0x3c010001, -0xac226da4, 0xaf860150, 0x10e00011, 0xaf830250, -0x3c1d0001, 0x8fbd6d4c, 0x3a0f021, 0xc001731, -0x0, 0x3c020001, 0x8c426d50, 0x3c030001, -0x8c636d54, 0x2442fe00, 0x24630200, 0x3c010001, -0xac226d50, 0x3c010001, 0x10000004, 0xac236d54, -0x3c1d0001, 0x8fbd6da0, 0x3a0f021, 0x3c020001, -0x8c426d44, 0x1040000d, 0x26fafa38, 0x3c020001, -0x8c426d50, 0x3c030001, 0x8c636d54, 0x3c1a0001, -0x8f5a6d54, 0x2442fa38, 0x246305c8, 0x3c010001, -0xac226d50, 0x3c010001, 0xac236d54, 0x3c020001, -0x8c426d48, 0x14400003, 0x0, 0x3c010001, -0xac206d50, 0xc00114c, 0x0, 0x8fbf001c, -0x8fb00018, 0x3e00008, 0x27bd0020, 0x3c020001, -0x8c426d50, 0x3c030001, 0x8c636d54, 0x27bdffa0, -0xafb00040, 0x3c100001, 0x8e106748, 0x3c040001, -0x24845d10, 0xafbf0058, 0xafbe0054, 0xafb50050, -0xafb3004c, 0xafb20048, 0xafb10044, 0xafa20034, -0xafa30030, 0xafa00010, 0xafa00014, 0x8f860040, -0x24050200, 0xc002b17, 0x2003821, 0x8f830040, -0x3c02f000, 0x621824, 0x3c026000, 0x1062000b, -0xa3a0003f, 0x240e0001, 0x3c040001, 0x24845d18, -0xa3ae003f, 0xafa00010, 0xafa00014, 0x8f860040, -0x24050300, 0xc002b17, 0x2003821, 0x8f820240, -0x3c030001, 0x431025, 0xaf820240, 0xaf800048, -0x8f820048, 0x14400005, 0x0, 0xaf800048, -0x8f820048, 0x10400004, 0x0, 0xaf800048, -0x10000003, 0x2e02021, 0xaf80004c, 0x2e02021, -0x3c050001, 0xc002b84, 0x34a540f8, 0x3402021, -0xc002b84, 0x240505c8, 0x3c020001, 0x8c426f24, -0x3c0d0001, 0x8dad6f04, 0x3c030001, 0x8c636f00, -0x3c080001, 0x8d086f0c, 0x3c090001, 0x8d296f28, -0x3c0a0001, 0x8d4a6f30, 0x3c0b0001, 0x8d6b6f40, -0x3c0c0001, 0x8d8c6f14, 0x3c040001, 0x24845d24, -0x24050400, 0xaf42013c, 0x8f42013c, 0x24060001, -0x24070001, 0xaf400000, 0xaf4d0138, 0xaf430144, -0xaf480148, 0xaf49014c, 0xaf4a0150, 0xaf4b0154, -0xaf4c0158, 0x2442ff80, 0xaf420140, 0x24020001, -0xafa20010, 0xc002b17, 0xafa00014, 0x8f420138, -0xafa20010, 0x8f42013c, 0xafa20014, 0x8f460144, -0x8f470148, 0x3c040001, 0x24845d30, 0xc002b17, -0x24050500, 0xafb70010, 0xafba0014, 0x8f46014c, -0x8f470150, 0x3c040001, 0x24845d3c, 0xc002b17, -0x24050600, 0x3c020001, 0x8c426f18, 0x3603821, -0x3c060002, 0x24c69090, 0x2448ffff, 0x1061824, -0xe81024, 0x43102b, 0x10400006, 0x24050900, -0x3c040001, 0x24845d48, 0xafa80010, 0xc002b17, -0xafa00014, 0x8f82000c, 0xafa20010, 0x8f82003c, -0xafa20014, 0x8f860000, 0x8f870004, 0x3c040001, -0x24845d54, 0xc002b17, 0x24051000, 0x8c020220, -0x8c030224, 0x8c060218, 0x8c07021c, 0x3c040001, -0x24845d5c, 0x24051100, 0xafa20010, 0xc002b17, -0xafa30014, 0xaf800054, 0xaf80011c, 0x8c020218, -0x30420002, 0x10400009, 0x0, 0x8c020220, -0x3c030002, 0x34630004, 0x431025, 0xaf42000c, -0x8c02021c, 0x10000008, 0x34420004, 0x8c020220, -0x3c030002, 0x34630006, 0x431025, 0xaf42000c, -0x8c02021c, 0x34420006, 0xaf420014, 0x8c020218, -0x30420010, 0x1040000a, 0x0, 0x8c02021c, -0x34420004, 0xaf420010, 0x8c020220, 0x3c03000a, -0x34630004, 0x431025, 0x10000009, 0xaf420008, -0x8c020220, 0x3c03000a, 0x34630006, 0x431025, -0xaf420008, 0x8c02021c, 0x34420006, 0xaf420010, -0x24020001, 0xaf8200a0, 0xaf8200b0, 0x8f830054, -0x8f820054, 0x10000002, 0x24630064, 0x8f820054, -0x621023, 0x2c420065, 0x1440fffc, 0x0, -0x8c040208, 0x8c05020c, 0x26e20028, 0xaee20020, -0x24020490, 0xaee20010, 0xaee40008, 0xaee5000c, -0x26e40008, 0x8c820000, 0x8c830004, 0xaf820090, -0xaf830094, 0x8c820018, 0xaf8200b4, 0x9482000a, -0xaf82009c, 0x8f420014, 0xaf8200b0, 0x8f8200b0, -0x30420004, 0x1440fffd, 0x0, 0x8f8200b0, -0x3c03ef00, 0x431024, 0x10400021, 0x0, -0x8f8200b4, 0xafa20010, 0x8f820090, 0x8f830094, -0x3c040001, 0x24845d64, 0xafa30014, 0x8f8600b0, -0x8f87009c, 0x3c050001, 0xc002b17, 0x34a5200d, -0x3c040001, 0x24845d70, 0x240203ac, 0xafa20010, -0xafa00014, 0x8f860144, 0x3c070001, 0x24e75d78, -0xc002b17, 0x3405dead, 0x8f82011c, 0x34420002, -0xaf82011c, 0x8f820220, 0x34420004, 0xaf820220, -0x8f820140, 0x3c030001, 0x431025, 0xaf820140, -0x96e20472, 0x96e60452, 0x96e70462, 0xafa20010, -0x96e20482, 0x3c040001, 0x24845da4, 0x24051200, -0xc002b17, 0xafa20014, 0x96f00452, 0x32020001, -0x10400002, 0xb021, 0x24160001, 0x32020002, -0x54400001, 0x36d60002, 0x32020008, 0x54400001, -0x36d60004, 0x32020010, 0x54400001, 0x36d60008, -0x32020020, 0x54400001, 0x36d60010, 0x32020040, -0x54400001, 0x36d60020, 0x32020080, 0x54400001, -0x36d60040, 0x96e60482, 0x30c20200, 0x54400001, -0x36d64000, 0x96e30472, 0x30620200, 0x10400003, -0x30620100, 0x10000003, 0x36d62000, 0x54400001, -0x36d61000, 0x96f00462, 0x32c24000, 0x14400004, -0x3207009b, 0x30c2009b, 0x14e20007, 0x240e0001, -0x32c22000, 0x1440000d, 0x32020001, 0x3062009b, -0x10e20009, 0x240e0001, 0x3c040001, 0x24845db0, -0x24051300, 0x2003821, 0xa3ae003f, 0xafa30010, -0xc002b17, 0xafa00014, 0x32020001, 0x54400001, -0x36d60080, 0x32020002, 0x54400001, 0x36d60100, -0x32020008, 0x54400001, 0x36d60200, 0x32020010, -0x54400001, 0x36d60400, 0x32020080, 0x54400001, -0x36d60800, 0x8c020218, 0x30420200, 0x10400002, -0x3c020008, 0x2c2b025, 0x8c020218, 0x30420800, -0x10400002, 0x3c020080, 0x2c2b025, 0x8c020218, -0x30420400, 0x10400002, 0x3c020100, 0x2c2b025, -0x8c020218, 0x30420100, 0x10400002, 0x3c020200, -0x2c2b025, 0x8c020218, 0x30420080, 0x10400002, -0x3c020400, 0x2c2b025, 0x8c020218, 0x30422000, -0x10400002, 0x3c020010, 0x2c2b025, 0x8c020218, -0x30424000, 0x10400002, 0x3c020020, 0x2c2b025, -0x8c020218, 0x30421000, 0x10400002, 0x3c020040, -0x2c2b025, 0x8ee20498, 0x8ee3049c, 0xaf420160, -0xaf430164, 0x8ee204a0, 0x8ee304a4, 0xaf420168, -0xaf43016c, 0x8ee204a8, 0x8ee304ac, 0xaf420170, -0xaf430174, 0x8ee20428, 0x8ee3042c, 0xaf420178, -0xaf43017c, 0x8ee20448, 0x8ee3044c, 0xaf420180, -0xaf430184, 0x8ee20458, 0x8ee3045c, 0xaf420188, -0xaf43018c, 0x8ee20468, 0x8ee3046c, 0xaf420190, -0xaf430194, 0x8ee20478, 0x8ee3047c, 0xaf420198, -0xaf43019c, 0x8ee20488, 0x8ee3048c, 0xaf4201a0, -0xaf4301a4, 0x8ee204b0, 0x8ee304b4, 0x24040080, -0xaf4201a8, 0xaf4301ac, 0xc002b84, 0x24050080, -0x8c02025c, 0x27440224, 0xaf4201f0, 0x8c020260, -0x24050200, 0x24060008, 0xc002b9b, 0xaf4201f8, -0x3c043b9a, 0x3484ca00, 0x3821, 0x24020006, -0x24030002, 0xaf4201f4, 0x240203e8, 0xaf430204, -0xaf430200, 0xaf4401fc, 0xaf420294, 0x24020001, -0xaf430290, 0xaf42029c, 0x3c030001, 0x671821, -0x90636d58, 0x3471021, 0x24e70001, 0xa043022c, -0x2ce2000f, 0x1440fff8, 0x3471821, 0x24e70001, -0x3c080001, 0x350840f8, 0x8f820040, 0x3c040001, -0x24845dbc, 0x24051400, 0x21702, 0x24420030, -0xa062022c, 0x3471021, 0xa040022c, 0x8c070218, -0x2c03021, 0x240205c8, 0xafa20010, 0xc002b17, -0xafa80014, 0x3c040001, 0x24845dc8, 0x3c050000, -0x24a55c20, 0x24060010, 0x27b10030, 0x2203821, -0x27b30034, 0xc00178b, 0xafb30010, 0x3c030001, -0x8c636d48, 0x1060000a, 0x408021, 0x8fa30030, -0x2405ff00, 0x8fa20034, 0x246400ff, 0x852024, -0x831823, 0x431023, 0xafa20034, 0xafa40030, -0xafb30010, 0x3c040001, 0x24845dd4, 0x3c050000, -0x24a54100, 0x24060108, 0xc00178b, 0x2203821, -0x409021, 0x32c20003, 0x50400045, 0x2203821, -0x8f820050, 0x3c030010, 0x431024, 0x10400016, -0x0, 0x8c020218, 0x30420040, 0x1040000f, -0x24020001, 0x8f820050, 0x8c030218, 0x240e0001, -0x3c040001, 0x24845de0, 0xa3ae003f, 0xafa20010, -0xafa30014, 0x8f870040, 0x24051500, 0xc002b17, -0x2c03021, 0x10000004, 0x0, 0x3c010001, -0x370821, 0xa02240f4, 0x3c040001, 0x24845dec, -0x3c050001, 0x24a55bd0, 0x3c060001, 0x24c65c3c, -0xc53023, 0x8f420010, 0x27b30030, 0x2603821, -0x27b10034, 0x34420a00, 0xaf420010, 0xc00178b, -0xafb10010, 0x3c040001, 0x24845e00, 0x3c050001, -0x24a5b604, 0x3c060001, 0x24c6b980, 0xc53023, -0x2603821, 0xaf420108, 0xc00178b, 0xafb10010, -0x3c040001, 0x24845e1c, 0x3c050001, 0x24a5bda0, -0x3c060001, 0x24c6c8a0, 0xc53023, 0x2603821, -0x3c010001, 0xac226f70, 0xc00178b, 0xafb10010, -0x3c040001, 0x24845e34, 0x10000024, 0x24051600, -0x3c040001, 0x24845e3c, 0x3c050001, 0x24a5a07c, -0x3c060001, 0x24c6a1a8, 0xc53023, 0xc00178b, -0xafb30010, 0x3c040001, 0x24845e4c, 0x3c050001, -0x24a5b1a0, 0x3c060001, 0x24c6b5fc, 0xc53023, -0x2203821, 0xaf420108, 0xc00178b, 0xafb30010, -0x3c040001, 0x24845e60, 0x3c050001, 0x24a5b988, -0x3c060001, 0x24c6bd98, 0xc53023, 0x2203821, -0x3c010001, 0xac226f70, 0xc00178b, 0xafb30010, -0x3c040001, 0x24845e74, 0x24051650, 0x2c03021, -0x3821, 0x3c010001, 0xac226f74, 0xafa00010, -0xc002b17, 0xafa00014, 0x32c20020, 0x10400021, -0x27a70030, 0x3c040001, 0x24845e80, 0x3c050001, -0x24a5b02c, 0x3c060001, 0x24c6b198, 0xc53023, -0x24022000, 0xaf42001c, 0x27a20034, 0xc00178b, -0xafa20010, 0x21900, 0x31982, 0x3c040800, -0x641825, 0xae430028, 0x24030010, 0xaf43003c, -0x96e30450, 0xaf430040, 0x8f430040, 0x3c040001, -0x24845e94, 0xafa00014, 0xafa30010, 0x8f47001c, -0x24051660, 0x3c010001, 0xac226f6c, 0x10000025, -0x32c60020, 0x8ee20448, 0x8ee3044c, 0xaf43001c, -0x8f42001c, 0x2442e000, 0x2c422001, 0x1440000a, -0x240e0001, 0x3c040001, 0x24845ea0, 0xa3ae003f, -0xafa00010, 0xafa00014, 0x8f46001c, 0x24051700, -0xc002b17, 0x3821, 0x3c020000, 0x24425c5c, -0x21100, 0x21182, 0x3c030800, 0x431025, -0xae420028, 0x24020008, 0xaf42003c, 0x96e20450, -0xaf420040, 0x8f420040, 0x3c040001, 0x24845eac, -0xafa00014, 0xafa20010, 0x8f47001c, 0x24051800, -0x32c60020, 0xc002b17, 0x0, 0x3c030001, -0x8c636f70, 0x3c050fff, 0x34a5ffff, 0x3c020001, -0x8c426f74, 0x3c040800, 0x651824, 0x31882, -0x641825, 0x451024, 0x21082, 0x441025, -0xae420080, 0x32c20180, 0x10400056, 0xae430020, -0x8f82005c, 0x3c030080, 0x431024, 0x1040000d, -0x0, 0x8f820050, 0xafa20010, 0x8f82005c, -0x240e0001, 0x3c040001, 0x24845eb8, 0xa3ae003f, -0xafa20014, 0x8f870040, 0x24051900, 0xc002b17, -0x2c03021, 0x8f820050, 0x3c030010, 0x431024, +0x24030003, 0xaf8300ec, 0x34420004, 0xc002b20, +0xaf820140, 0x3c0100c0, 0xc001763, 0xac203ffc, +0x401821, 0x3c020010, 0x3c010001, 0xac236e9c, +0x10620011, 0x43102b, 0x14400002, 0x3c020020, +0x3c020008, 0x1062000c, 0x24050100, 0x3c060001, +0x8cc66e9c, 0x3c040001, 0x24845c74, 0x3821, +0xafa00010, 0xc002b3b, 0xafa00014, 0x3c020020, +0x3c010001, 0xac226e9c, 0x24020008, 0x3c010001, +0xac226eb4, 0x2402001f, 0x3c010001, 0xac226ec4, +0x24020016, 0x3c010001, 0xac226e98, 0x3c05fffe, +0x34a56f08, 0x3c020001, 0x8c426e9c, 0x3c030002, +0x24639010, 0x3c040001, 0x8c846cc4, 0x431023, +0x14800002, 0x458021, 0x2610fa38, 0x2402f000, +0x2028024, 0xc001785, 0x2002021, 0x2022823, +0x3c040020, 0x821823, 0x651823, 0x247bb000, +0x3c03fffe, 0x3463bf08, 0x363b821, 0x3c0600bf, +0x34c6f000, 0x3c070001, 0x8ce76cc0, 0x3c0300bf, +0x3463e000, 0x852023, 0x3c010001, 0xac246ea8, +0x822023, 0x3c010001, 0xac256e90, 0x52842, +0x3c010001, 0xac226e84, 0x27620ffc, 0x3c010001, +0xac226d20, 0x27621ffc, 0xdb3023, 0x7b1823, +0x3c010001, 0xac246e88, 0x3c010001, 0xac256eac, +0x3c010001, 0xac226d24, 0xaf860150, 0x10e00011, +0xaf830250, 0x3c1d0001, 0x8fbd6ccc, 0x3a0f021, +0xc001749, 0x0, 0x3c020001, 0x8c426cd0, +0x3c030001, 0x8c636cd4, 0x2442fe00, 0x24630200, +0x3c010001, 0xac226cd0, 0x3c010001, 0x10000004, +0xac236cd4, 0x3c1d0001, 0x8fbd6d20, 0x3a0f021, +0x3c020001, 0x8c426cc4, 0x1040000d, 0x26fafa38, +0x3c020001, 0x8c426cd0, 0x3c030001, 0x8c636cd4, +0x3c1a0001, 0x8f5a6cd4, 0x2442fa38, 0x246305c8, +0x3c010001, 0xac226cd0, 0x3c010001, 0xac236cd4, +0x3c020001, 0x8c426cc8, 0x14400003, 0x0, +0x3c010001, 0xac206cd0, 0xc001151, 0x0, +0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020, +0x3c020001, 0x8c426cd0, 0x3c030001, 0x8c636cd4, +0x27bdff98, 0xafb00048, 0x3c100001, 0x8e1066b8, +0xafb20050, 0x3c120000, 0x26524100, 0xafbf0060, +0xafbe005c, 0xafb50058, 0xafb30054, 0xafb1004c, +0xafa20034, 0xafa30030, 0xafa00010, 0xafa00014, +0x8f860040, 0x3c040001, 0x24845c80, 0x24050200, +0x3c010001, 0xac326e80, 0xc002b3b, 0x2003821, +0x8f830040, 0x3c02f000, 0x621824, 0x3c026000, +0x1062000b, 0xa3a0003f, 0x240e0001, 0x3c040001, +0x24845c88, 0xa3ae003f, 0xafa00010, 0xafa00014, +0x8f860040, 0x24050300, 0xc002b3b, 0x2003821, +0x8f820240, 0x3c030001, 0x431025, 0xaf820240, +0xaf800048, 0x8f820048, 0x14400005, 0x0, +0xaf800048, 0x8f820048, 0x10400004, 0x0, +0xaf800048, 0x10000003, 0x2e02021, 0xaf80004c, +0x2e02021, 0x3c050001, 0xc002ba8, 0x34a540f8, +0x3402021, 0xc002ba8, 0x240505c8, 0x3c020001, +0x8c426ea8, 0x3c0d0001, 0x8dad6e88, 0x3c030001, +0x8c636e84, 0x3c080001, 0x8d086e90, 0x3c090001, +0x8d296eac, 0x3c0a0001, 0x8d4a6eb4, 0x3c0b0001, +0x8d6b6ec4, 0x3c0c0001, 0x8d8c6e98, 0x3c040001, +0x24845c94, 0x24050400, 0xaf42013c, 0x8f42013c, +0x24060001, 0x24070001, 0xaf400000, 0xaf4d0138, +0xaf430144, 0xaf480148, 0xaf49014c, 0xaf4a0150, +0xaf4b0154, 0xaf4c0158, 0x2442ff80, 0xaf420140, +0x24020001, 0xafa20010, 0xc002b3b, 0xafa00014, +0x8f420138, 0xafa20010, 0x8f42013c, 0xafa20014, +0x8f460144, 0x8f470148, 0x3c040001, 0x24845ca0, +0xc002b3b, 0x24050500, 0xafb70010, 0xafba0014, +0x8f46014c, 0x8f470150, 0x3c040001, 0x24845cac, +0xc002b3b, 0x24050600, 0x3c020001, 0x8c426e9c, +0x3603821, 0x3c060002, 0x24c69010, 0x2448ffff, +0x1061824, 0xe81024, 0x43102b, 0x10400006, +0x24050900, 0x3c040001, 0x24845cb8, 0xafa80010, +0xc002b3b, 0xafa00014, 0x8f82000c, 0xafa20010, +0x8f82003c, 0xafa20014, 0x8f860000, 0x8f870004, +0x3c040001, 0x24845cc4, 0xc002b3b, 0x24051000, +0x8c020220, 0x8c030224, 0x8c060218, 0x8c07021c, +0x3c040001, 0x24845ccc, 0x24051100, 0xafa20010, +0xc002b3b, 0xafa30014, 0xaf800054, 0xaf80011c, +0x8c020218, 0x30420002, 0x10400009, 0x0, +0x8c020220, 0x3c030002, 0x34630004, 0x431025, +0xaf42000c, 0x8c02021c, 0x10000008, 0x34420004, +0x8c020220, 0x3c030002, 0x34630006, 0x431025, +0xaf42000c, 0x8c02021c, 0x34420006, 0xaf420014, +0x8c020218, 0x30420010, 0x1040000a, 0x0, +0x8c02021c, 0x34420004, 0xaf420010, 0x8c020220, +0x3c03000a, 0x34630004, 0x431025, 0x10000009, +0xaf420008, 0x8c020220, 0x3c03000a, 0x34630006, +0x431025, 0xaf420008, 0x8c02021c, 0x34420006, +0xaf420010, 0x24020001, 0xaf8200a0, 0xaf8200b0, +0x8f830054, 0x8f820054, 0xaf8000d0, 0xaf8000c0, +0x10000002, 0x24630064, 0x8f820054, 0x621023, +0x2c420065, 0x1440fffc, 0x0, 0x8c040208, +0x8c05020c, 0x26e20028, 0xaee20020, 0x24020490, +0xaee20010, 0xaee40008, 0xaee5000c, 0x26e40008, +0x8c820000, 0x8c830004, 0xaf820090, 0xaf830094, +0x8c820018, 0xaf8200b4, 0x9482000a, 0xaf82009c, +0x8f420014, 0xaf8200b0, 0x8f8200b0, 0x30420004, +0x1440fffd, 0x0, 0x8f8200b0, 0x3c03ef00, +0x431024, 0x10400021, 0x0, 0x8f8200b4, +0xafa20010, 0x8f820090, 0x8f830094, 0x3c040001, +0x24845cd4, 0xafa30014, 0x8f8600b0, 0x8f87009c, +0x3c050001, 0xc002b3b, 0x34a5200d, 0x3c040001, +0x24845ce0, 0x240203c0, 0xafa20010, 0xafa00014, +0x8f860144, 0x3c070001, 0x24e75ce8, 0xc002b3b, +0x3405dead, 0x8f82011c, 0x34420002, 0xaf82011c, +0x8f820220, 0x34420004, 0xaf820220, 0x8f820140, +0x3c030001, 0x431025, 0xaf820140, 0x96e20472, +0x96e60452, 0x96e70462, 0xafa20010, 0x96e20482, +0x3c040001, 0x24845d14, 0x24051200, 0xc002b3b, +0xafa20014, 0x96f00452, 0x32020001, 0x10400002, +0xb021, 0x24160001, 0x32020002, 0x54400001, +0x36d60002, 0x32020008, 0x54400001, 0x36d60004, +0x32020010, 0x54400001, 0x36d60008, 0x32020020, +0x54400001, 0x36d60010, 0x32020040, 0x54400001, +0x36d60020, 0x32020080, 0x54400001, 0x36d60040, +0x96e60482, 0x30c20200, 0x54400001, 0x36d64000, +0x96e30472, 0x30620200, 0x10400003, 0x30620100, +0x10000003, 0x36d62000, 0x54400001, 0x36d61000, +0x96f00462, 0x32c24000, 0x14400004, 0x3207009b, +0x30c2009b, 0x14e20007, 0x240e0001, 0x32c22000, +0x1440000d, 0x32020001, 0x3062009b, 0x10e20009, +0x240e0001, 0x3c040001, 0x24845d20, 0x24051300, +0x2003821, 0xa3ae003f, 0xafa30010, 0xc002b3b, +0xafa00014, 0x32020001, 0x54400001, 0x36d60080, +0x32020002, 0x54400001, 0x36d60100, 0x32020008, +0x54400001, 0x36d60200, 0x32020010, 0x54400001, +0x36d60400, 0x32020080, 0x54400001, 0x36d60800, +0x8c020218, 0x30420200, 0x10400002, 0x3c020008, +0x2c2b025, 0x8c020218, 0x30420800, 0x10400002, +0x3c020080, 0x2c2b025, 0x8c020218, 0x30420400, +0x10400002, 0x3c020100, 0x2c2b025, 0x8c020218, +0x30420100, 0x10400002, 0x3c020200, 0x2c2b025, +0x8c020218, 0x30420080, 0x10400002, 0x3c020400, +0x2c2b025, 0x8c020218, 0x30422000, 0x10400002, +0x3c020010, 0x2c2b025, 0x8c020218, 0x30424000, +0x10400002, 0x3c020020, 0x2c2b025, 0x8c020218, +0x30421000, 0x10400002, 0x3c020040, 0x2c2b025, +0x8ee20498, 0x8ee3049c, 0xaf420160, 0xaf430164, +0x8ee204a0, 0x8ee304a4, 0xaf420168, 0xaf43016c, +0x8ee204a8, 0x8ee304ac, 0xaf420170, 0xaf430174, +0x8ee20428, 0x8ee3042c, 0xaf420178, 0xaf43017c, +0x8ee20448, 0x8ee3044c, 0xaf420180, 0xaf430184, +0x8ee20458, 0x8ee3045c, 0xaf420188, 0xaf43018c, +0x8ee20468, 0x8ee3046c, 0xaf420190, 0xaf430194, +0x8ee20478, 0x8ee3047c, 0xaf420198, 0xaf43019c, +0x8ee20488, 0x8ee3048c, 0xaf4201a0, 0xaf4301a4, +0x8ee204b0, 0x8ee304b4, 0x24040080, 0xaf4201a8, +0xaf4301ac, 0xc002ba8, 0x24050080, 0x8c02025c, +0x27440224, 0xaf4201f0, 0x8c020260, 0x24050200, +0x24060008, 0xc002bbf, 0xaf4201f8, 0x3c043b9a, +0x3484ca00, 0x3821, 0x24020006, 0x24030002, +0xaf4201f4, 0x240203e8, 0xaf430204, 0xaf430200, +0xaf4401fc, 0xaf420294, 0x24020001, 0xaf430290, +0xaf42029c, 0x3c030001, 0x671821, 0x90636cd8, +0x3471021, 0x24e70001, 0xa043022c, 0x2ce2000f, +0x1440fff8, 0x3471821, 0x24e70001, 0x3c080001, +0x350840f8, 0x8f820040, 0x3c040001, 0x24845d2c, +0x24051400, 0x21702, 0x24420030, 0xa062022c, +0x3471021, 0xa040022c, 0x8c070218, 0x2c03021, +0x240205c8, 0xafa20010, 0xc002b3b, 0xafa80014, +0x3c040001, 0x24845d38, 0x3c050000, 0x24a55c80, +0x24060010, 0x27b10030, 0x2203821, 0x27b30034, +0xc0017a3, 0xafb30010, 0x3c030001, 0x8c636cc8, +0x1060000a, 0x408021, 0x8fa30030, 0x2405ff00, +0x8fa20034, 0x246400ff, 0x852024, 0x831823, +0x431023, 0xafa20034, 0xafa40030, 0x3c040001, +0x24845d44, 0x3c050000, 0x24a54100, 0x24060108, +0x2203821, 0xc0017a3, 0xafb30010, 0x409021, +0x32c20003, 0x3c010001, 0xac326e80, 0x10400045, +0x2203821, 0x8f820050, 0x3c030010, 0x431024, 0x10400016, 0x0, 0x8c020218, 0x30420040, 0x1040000f, 0x24020001, 0x8f820050, 0x8c030218, -0x240e0001, 0x3c040001, 0x24845de0, 0xa3ae003f, -0xafa20010, 0xafa30014, 0x8f870040, 0x24052000, -0xc002b17, 0x2c03021, 0x10000004, 0x0, +0x240e0001, 0x3c040001, 0x24845d50, 0xa3ae003f, +0xafa20010, 0xafa30014, 0x8f870040, 0x24051500, +0xc002b3b, 0x2c03021, 0x10000004, 0x0, +0x3c010001, 0x370821, 0xa02240f4, 0x3c040001, +0x24845d5c, 0x3c050001, 0x24a55b40, 0x3c060001, +0x24c65bac, 0xc53023, 0x8f420010, 0x27b30030, +0x2603821, 0x27b10034, 0x34420a00, 0xaf420010, +0xc0017a3, 0xafb10010, 0x3c040001, 0x24845d70, +0x3c050001, 0x24a5b714, 0x3c060001, 0x24c6ba90, +0xc53023, 0x2603821, 0xaf420108, 0xc0017a3, +0xafb10010, 0x3c040001, 0x24845d8c, 0x3c050001, +0x24a5be58, 0x3c060001, 0x24c6c900, 0xc53023, +0x2603821, 0x3c010001, 0xac226ef4, 0xc0017a3, +0xafb10010, 0x3c040001, 0x24845da4, 0x10000024, +0x24051600, 0x3c040001, 0x24845dac, 0x3c050001, +0x24a5a10c, 0x3c060001, 0x24c6a238, 0xc53023, +0xc0017a3, 0xafb30010, 0x3c040001, 0x24845dbc, +0x3c050001, 0x24a5b2b0, 0x3c060001, 0x24c6b70c, +0xc53023, 0x2203821, 0xaf420108, 0xc0017a3, +0xafb30010, 0x3c040001, 0x24845dd0, 0x3c050001, +0x24a5ba98, 0x3c060001, 0x24c6be50, 0xc53023, +0x2203821, 0x3c010001, 0xac226ef4, 0xc0017a3, +0xafb30010, 0x3c040001, 0x24845de4, 0x24051650, +0x2c03021, 0x3821, 0x3c010001, 0xac226ef8, +0xafa00010, 0xc002b3b, 0xafa00014, 0x32c20020, +0x10400021, 0x27a70030, 0x3c040001, 0x24845df0, +0x3c050001, 0x24a5b13c, 0x3c060001, 0x24c6b2a8, +0xc53023, 0x24022000, 0xaf42001c, 0x27a20034, +0xc0017a3, 0xafa20010, 0x21900, 0x31982, +0x3c040800, 0x641825, 0xae430028, 0x24030010, +0xaf43003c, 0x96e30450, 0xaf430040, 0x8f430040, +0x3c040001, 0x24845e04, 0xafa00014, 0xafa30010, +0x8f47001c, 0x24051660, 0x3c010001, 0xac226ef0, +0x10000025, 0x32c60020, 0x8ee20448, 0x8ee3044c, +0xaf43001c, 0x8f42001c, 0x2442e000, 0x2c422001, +0x1440000a, 0x240e0001, 0x3c040001, 0x24845e10, +0xa3ae003f, 0xafa00010, 0xafa00014, 0x8f46001c, +0x24051700, 0xc002b3b, 0x3821, 0x3c020000, +0x24425cbc, 0x21100, 0x21182, 0x3c030800, +0x431025, 0xae420028, 0x24020008, 0xaf42003c, +0x96e20450, 0xaf420040, 0x8f420040, 0x3c040001, +0x24845e1c, 0xafa00014, 0xafa20010, 0x8f47001c, +0x24051800, 0x32c60020, 0xc002b3b, 0x0, +0x3c050fff, 0x3c030001, 0x8c636ef4, 0x34a5ffff, +0x2403021, 0x3c020001, 0x8c426ef8, 0x3c040800, +0x651824, 0x31882, 0x641825, 0x451024, +0x21082, 0x441025, 0xacc20080, 0x32c20180, +0x10400056, 0xacc30020, 0x8f82005c, 0x3c030080, +0x431024, 0x1040000d, 0x0, 0x8f820050, +0xafa20010, 0x8f82005c, 0x240e0001, 0x3c040001, +0x24845e28, 0xa3ae003f, 0xafa20014, 0x8f870040, +0x24051900, 0xc002b3b, 0x2c03021, 0x8f820050, +0x3c030010, 0x431024, 0x10400016, 0x0, +0x8c020218, 0x30420040, 0x1040000f, 0x24020001, +0x8f820050, 0x8c030218, 0x240e0001, 0x3c040001, +0x24845d50, 0xa3ae003f, 0xafa20010, 0xafa30014, +0x8f870040, 0x24052000, 0xc002b3b, 0x2c03021, +0x10000004, 0x0, 0x3c010001, 0x370821, +0xa02240f4, 0x3c040001, 0x24845e34, 0x3c050001, +0x24a55ac0, 0x3c060001, 0x24c65b38, 0xc53023, +0x8f420008, 0x27b30030, 0x2603821, 0x27b10034, +0x34420e00, 0xaf420008, 0xc0017a3, 0xafb10010, +0x3c040001, 0x24845e4c, 0x3c050001, 0x24a5d8b4, +0x3c060001, 0x24c6e3c8, 0xc53023, 0x2603821, +0xaf42010c, 0xc0017a3, 0xafb10010, 0x3c040001, +0x24845e64, 0x3c050001, 0x24a5e9ac, 0x3c060001, +0x24c6f0f0, 0xc53023, 0x2603821, 0x3c010001, +0xac226f04, 0xc0017a3, 0xafb10010, 0x3c040001, +0x24845e7c, 0x10000027, 0x24052100, 0x3c040001, +0x24845e84, 0x3c050001, 0x24a59fc8, 0x3c060001, +0x24c6a104, 0xc53023, 0x27b10030, 0x2203821, +0x27b30034, 0xc0017a3, 0xafb30010, 0x3c040001, +0x24845e94, 0x3c050001, 0x24a5cad4, 0x3c060001, +0x24c6d8ac, 0xc53023, 0x2203821, 0xaf42010c, +0xc0017a3, 0xafb30010, 0x3c040001, 0x24845ea4, +0x3c050001, 0x24a5e84c, 0x3c060001, 0x24c6e9a4, +0xc53023, 0x2203821, 0x3c010001, 0xac226f04, +0xc0017a3, 0xafb30010, 0x3c040001, 0x24845eb8, +0x24052150, 0x2c03021, 0x3821, 0x3c010001, +0xac226f10, 0xafa00010, 0xc002b3b, 0xafa00014, +0x3c110fff, 0x3c030001, 0x8c636f04, 0x3631ffff, +0x2409821, 0x3c020001, 0x8c426f10, 0x3c0e0800, +0x711824, 0x31882, 0x6e1825, 0x511024, +0x21082, 0x4e1025, 0xae630038, 0xae620078, +0x8c020218, 0x30420040, 0x14400004, 0x24020001, 0x3c010001, 0x370821, 0xa02240f4, 0x3c040001, -0x24845ec4, 0x3c050001, 0x24a55b50, 0x3c060001, -0x24c65bc8, 0xc53023, 0x8f420008, 0x27b30030, -0x2603821, 0x27b10034, 0x34420e00, 0xaf420008, -0xc00178b, 0xafb10010, 0x3c040001, 0x24845edc, -0x3c050001, 0x24a5d814, 0x3c060001, 0x24c6e328, -0xc53023, 0x2603821, 0xaf42010c, 0xc00178b, -0xafb10010, 0x3c040001, 0x24845ef4, 0x3c050001, -0x24a5e90c, 0x3c060001, 0x24c6f050, 0xc53023, -0x2603821, 0x3c010001, 0xac226f80, 0xc00178b, -0xafb10010, 0x3c040001, 0x24845f0c, 0x10000027, -0x24052100, 0x3c040001, 0x24845f14, 0x3c050001, -0x24a59f38, 0x3c060001, 0x24c6a074, 0xc53023, -0x27b10030, 0x2203821, 0x27b30034, 0xc00178b, -0xafb30010, 0x3c040001, 0x24845f24, 0x3c050001, -0x24a5ca74, 0x3c060001, 0x24c6d80c, 0xc53023, -0x2203821, 0xaf42010c, 0xc00178b, 0xafb30010, -0x3c040001, 0x24845f34, 0x3c050001, 0x24a5e7ac, -0x3c060001, 0x24c6e904, 0xc53023, 0x2203821, -0x3c010001, 0xac226f80, 0xc00178b, 0xafb30010, -0x3c040001, 0x24845f48, 0x24052150, 0x2c03021, -0x3821, 0x3c010001, 0xac226f8c, 0xafa00010, -0xc002b17, 0xafa00014, 0x3c030001, 0x8c636f80, -0x3c110fff, 0x3631ffff, 0x3c020001, 0x8c426f8c, -0x3c1e0800, 0x711824, 0x31882, 0x7e1825, -0x511024, 0x21082, 0x5e1025, 0xae430038, -0xae420078, 0x8c020218, 0x30420040, 0x14400004, -0x24020001, 0x3c010001, 0x370821, 0xa02240f4, -0x3c040001, 0x24845f54, 0x3c050001, 0x24a5e330, -0x3c060001, 0x24c6e48c, 0xc53023, 0x27b50030, -0x2a03821, 0x27b30034, 0xc00178b, 0xafb30010, -0x3c010001, 0xac226f78, 0x511024, 0x21082, -0x5e1025, 0xae420050, 0x32c22000, 0x10400005, -0x2a03821, 0x3c020000, 0x24425c5c, 0x1000000d, -0x511024, 0x3c040001, 0x24845f68, 0x3c050001, -0x24a5e494, 0x3c060001, 0x24c6e644, 0xc53023, -0xc00178b, 0xafb30010, 0x3c010001, 0xac226f90, -0x511024, 0x21082, 0x5e1025, 0xae420048, -0x32c24000, 0x10400005, 0x27a70030, 0x3c020000, -0x24425c5c, 0x1000000e, 0x21100, 0x3c040001, -0x24845f80, 0x3c050001, 0x24a5e64c, 0x3c060001, -0x24c6e7a4, 0xc53023, 0x27a20034, 0xc00178b, -0xafa20010, 0x3c010001, 0xac226f84, 0x21100, -0x21182, 0x3c030800, 0x431025, 0xae420060, -0x3c040001, 0x24845f98, 0x3c050001, 0x24a581d0, -0x3c060001, 0x24c685f0, 0xc53023, 0x27b10030, -0x2203821, 0x27b30034, 0xc00178b, 0xafb30010, -0x3c1e0fff, 0x37deffff, 0x3c040001, 0x24845fa4, -0x3c050000, 0x24a56408, 0x3c060000, 0x24c66528, -0xc53023, 0x2203821, 0x3c010001, 0xac226f58, -0x5e1024, 0x21082, 0x3c150800, 0x551025, -0xae4200b8, 0xc00178b, 0xafb30010, 0x3c040001, -0x24845fb0, 0x3c050000, 0x24a56530, 0x3c060000, -0x24c667a8, 0xc53023, 0x2203821, 0x3c010001, -0xac226f4c, 0x5e1024, 0x21082, 0x551025, -0xae4200e8, 0xc00178b, 0xafb30010, 0x3c040001, -0x24845fc8, 0x3c050000, 0x24a567b0, 0x3c060000, -0x24c668e0, 0xc53023, 0x2203821, 0x3c010001, -0xac226f44, 0x5e1024, 0x21082, 0x551025, -0xae4200c0, 0xc00178b, 0xafb30010, 0x3c040001, -0x24845fe0, 0x3c050001, 0x24a5fa30, 0x3c060001, -0x24c6fb08, 0xc53023, 0x2203821, 0x3c010001, -0xac226f50, 0x5e1024, 0x21082, 0x551025, -0xae4200c8, 0xc00178b, 0xafb30010, 0x3c040001, -0x24845fec, 0x3c050001, 0x24a5c8dc, 0x3c060001, -0x24c6c9c0, 0xc53023, 0x2203821, 0xaf420110, -0xc00178b, 0xafb30010, 0x3c040001, 0x24845ffc, -0x3c050001, 0x24a5c8b0, 0x3c060001, 0x24c6c8d4, -0xc53023, 0x2203821, 0xaf420124, 0xc00178b, -0xafb30010, 0x3c040001, 0x2484600c, 0x3c050001, -0x24a55b10, 0x3c060001, 0x24c65b3c, 0xc53023, -0x2203821, 0xaf420120, 0xaf420114, 0xc00178b, -0xafb30010, 0x3c040001, 0x24846018, 0x3c050001, -0x24a5f1f8, 0x3c060001, 0x24c6f614, 0xc53023, -0x2203821, 0xaf420118, 0xc00178b, 0xafb30010, -0x3c010001, 0xac226f94, 0x5e1024, 0x21082, -0x551025, 0xc003f9b, 0xae4200d0, 0xc003c18, -0x0, 0xc002784, 0x0, 0xac000228, +0x24845ec4, 0x3c050001, 0x24a5e3d0, 0x3c060001, +0x24c6e52c, 0xc53023, 0x27be0030, 0x3c03821, +0x27b50034, 0xc0017a3, 0xafb50010, 0x3c010001, +0xac226efc, 0x511024, 0x21082, 0x3c0e0800, +0x4e1025, 0xae620050, 0x32c22000, 0x10400006, +0x3c03821, 0x3c020000, 0x24425cbc, 0x2221024, +0x1000000f, 0x21082, 0x3c040001, 0x24845ed8, +0x3c050001, 0x24a5e534, 0x3c060001, 0x24c6e6e4, +0xc53023, 0xc0017a3, 0xafb50010, 0x3c010001, +0xac226f14, 0x511024, 0x21082, 0x3c0e0800, +0x4e1025, 0xae620048, 0x32c24000, 0x10400005, +0x27a70030, 0x3c020000, 0x24425cbc, 0x1000000e, +0x21100, 0x3c040001, 0x24845ef0, 0x3c050001, +0x24a5e6ec, 0x3c060001, 0x24c6e844, 0xc53023, +0x27a20034, 0xc0017a3, 0xafa20010, 0x3c010001, +0xac226f08, 0x21100, 0x21182, 0x3c030800, +0x431025, 0xae420060, 0x3c040001, 0x24845f08, +0x3c050001, 0x24a58230, 0x3c060001, 0x24c68650, +0xc53023, 0x27b10030, 0x2203821, 0x27b30034, +0xc0017a3, 0xafb30010, 0x3c0e0fff, 0x35ceffff, +0x3c040001, 0x24845f14, 0x3c050000, 0x24a56468, +0x3c060000, 0x24c66588, 0xc53023, 0x2203821, +0x240f021, 0x3c010001, 0xac226edc, 0x4e1024, +0x21082, 0x3c150800, 0x551025, 0xafae0044, +0xafc200b8, 0xc0017a3, 0xafb30010, 0x3c040001, +0x24845f20, 0x3c050000, 0x24a56590, 0x3c060000, +0x24c66808, 0x8fae0044, 0xc53023, 0x2203821, +0x3c010001, 0xac226ed0, 0x4e1024, 0x21082, +0x551025, 0xafc200e8, 0xc0017a3, 0xafb30010, +0x3c040001, 0x24845f38, 0x3c050000, 0x24a56810, +0x3c060000, 0x24c66940, 0x8fae0044, 0xc53023, +0x2203821, 0x3c010001, 0xac226ec8, 0x4e1024, +0x21082, 0x551025, 0xafc200c0, 0xc0017a3, +0xafb30010, 0x3c040001, 0x24845f50, 0x3c050001, +0x24a5fad0, 0x3c060001, 0x24c6fba8, 0x8fae0044, +0xc53023, 0x2203821, 0x3c010001, 0xac226ed4, +0x4e1024, 0x21082, 0x551025, 0xafc200c8, +0xc0017a3, 0xafb30010, 0x3c040001, 0x24845f5c, +0x3c050001, 0x24a5c93c, 0x3c060001, 0x24c6ca20, +0xc53023, 0x2203821, 0xaf420110, 0xc0017a3, +0xafb30010, 0x3c040001, 0x24845f6c, 0x3c050001, +0x24a5c910, 0x3c060001, 0x24c6c934, 0xc53023, +0x2203821, 0xaf420124, 0xc0017a3, 0xafb30010, +0x3c040001, 0x24845f7c, 0x3c050001, 0x24a55a80, +0x3c060001, 0x24c65aac, 0xc53023, 0x2203821, +0xaf420120, 0xaf420114, 0xc0017a3, 0xafb30010, +0x3c040001, 0x24845f88, 0x3c050001, 0x24a5f298, +0x3c060001, 0x24c6f6b4, 0xc53023, 0x2203821, +0xaf420118, 0xc0017a3, 0xafb30010, 0x8fae0044, +0x3c010001, 0xac226f18, 0x4e1024, 0x21082, +0x551025, 0xc003fc3, 0xafc200d0, 0xc003c40, +0x0, 0xc0027a8, 0x0, 0xac000228, 0xac00022c, 0x96e20450, 0x2442ffff, 0xaf420038, 0x96e20460, 0xaf420080, 0x32c24000, 0x14400003, 0x0, 0x96e20480, 0xaf420084, 0x96e70490, 0x50e00001, 0x24070800, 0x24e2ffff, 0xaf420088, 0xaf42007c, 0x24020800, 0x10e2000f, 0x32c24000, 0x10400003, 0x24020400, 0x10e2000b, 0x0, -0x240e0001, 0x3c040001, 0x24846028, 0xa3ae003f, +0x240e0001, 0x3c040001, 0x24845f98, 0xa3ae003f, 0x96e60490, 0x24052170, 0x2c03821, 0xafa00010, -0xc002b17, 0xafa00014, 0x8f430138, 0x8f440138, +0xc002b3b, 0xafa00014, 0x8f430138, 0x8f440138, 0x24020001, 0xa34205c2, 0xaf430094, 0xaf440098, 0xafa00010, 0xafa00014, 0x8f460080, 0x8f470084, -0x3c040001, 0x24846034, 0xc002b17, 0x24052200, -0xc002480, 0x3c110800, 0x3c1433d8, 0x3694cb58, -0x3c020800, 0x34420080, 0x3c040001, 0x24846040, -0x3c050000, 0x24a55ca0, 0x3c060000, 0x24c65cbc, +0x3c040001, 0x24845fa4, 0xc002b3b, 0x24052200, +0xc0024a4, 0x3c110800, 0x3c1433d8, 0x3694cb58, +0x3c020800, 0x34420080, 0x3c040001, 0x24845fb0, +0x3c050000, 0x24a55d00, 0x3c060000, 0x24c65d1c, 0xc53023, 0x27a70030, 0xaf820060, 0x2402ffff, -0xaf820064, 0x27a20034, 0xc00178b, 0xafa20010, -0x3c010001, 0xac226f34, 0x21100, 0x21182, -0x511025, 0xc0018e4, 0xae420000, 0x8f820240, +0xaf820064, 0x27a20034, 0xc0017a3, 0xafa20010, +0x3c010001, 0xac226eb8, 0x21100, 0x21182, +0x511025, 0xc0018fc, 0xae420000, 0x8f820240, 0x3c030001, 0x431025, 0xaf820240, 0x3c020000, 0x24424034, 0xaf820244, 0xaf800240, 0x8f820060, 0x511024, 0x14400005, 0x3c030800, 0x8f820060, -0x431024, 0x1040fffd, 0x0, 0xc003c25, +0x431024, 0x1040fffd, 0x0, 0xc003c4d, 0x8821, 0x3c020100, 0xafa20020, 0x8f530018, 0x240200ff, 0x56620001, 0x26710001, 0x8c020228, 0x1622000e, 0x1330c0, 0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001, -0x24845cb4, 0x3c050009, 0xafa00014, 0xafa20010, +0x24845c24, 0x3c050009, 0xafa00014, 0xafa20010, 0x8fa60020, 0x1000003f, 0x34a50100, 0xd71021, 0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, 0xc01821, 0x8f440178, 0x8f45017c, 0x1021, @@ -5004,21 +5005,21 @@ 0x24070008, 0xa32821, 0xa3482b, 0x822021, 0x100f809, 0x892021, 0x1440000b, 0x24070008, 0x8f820120, 0xafa20010, 0x8f820124, 0x3c040001, -0x24845cbc, 0x3c050009, 0xafa20014, 0x8fa60020, +0x24845c2c, 0x3c050009, 0xafa20014, 0x8fa60020, 0x1000001c, 0x34a50200, 0x8f440160, 0x8f450164, 0x8f43000c, 0xaf510018, 0x8f860120, 0x24020010, 0xafa20010, 0xafb10014, 0xafa30018, 0x8f42010c, 0x40f809, 0x24c6001c, 0x14400010, 0x0, 0x8f420340, 0x24420001, 0xaf420340, 0x8f420340, 0x8f820120, 0xafa20010, 0x8f820124, 0x3c040001, -0x24845cc4, 0x3c050009, 0xafa20014, 0x8fa60020, -0x34a50300, 0xc002b17, 0x2603821, 0x8f4202e4, +0x24845c34, 0x3c050009, 0xafa20014, 0x8fa60020, +0x34a50300, 0xc002b3b, 0x2603821, 0x8f4202e4, 0x24420001, 0xaf4202e4, 0x8f4202e4, 0x93a2003f, 0x10400069, 0x3c020700, 0x34423000, 0xafa20028, 0x8f530018, 0x240200ff, 0x12620002, 0x8821, 0x26710001, 0x8c020228, 0x1622000e, 0x1330c0, 0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, -0x8c020228, 0x3c040001, 0x24845cb4, 0x3c050009, +0x8c020228, 0x3c040001, 0x24845c24, 0x3c050009, 0xafa00014, 0xafa20010, 0x8fa60028, 0x1000003f, 0x34a50100, 0xd71021, 0x8fa30028, 0x8fa4002c, 0xac4304c0, 0xac4404c4, 0xc01821, 0x8f440178, @@ -5027,18 +5028,18 @@ 0xafa80018, 0x8f48010c, 0x24070008, 0xa32821, 0xa3482b, 0x822021, 0x100f809, 0x892021, 0x1440000b, 0x24070008, 0x8f820120, 0xafa20010, -0x8f820124, 0x3c040001, 0x24845cbc, 0x3c050009, +0x8f820124, 0x3c040001, 0x24845c2c, 0x3c050009, 0xafa20014, 0x8fa60028, 0x1000001c, 0x34a50200, 0x8f440160, 0x8f450164, 0x8f43000c, 0xaf510018, 0x8f860120, 0x24020010, 0xafa20010, 0xafb10014, 0xafa30018, 0x8f42010c, 0x40f809, 0x24c6001c, 0x14400010, 0x0, 0x8f420340, 0x24420001, 0xaf420340, 0x8f420340, 0x8f820120, 0xafa20010, -0x8f820124, 0x3c040001, 0x24845cc4, 0x3c050009, -0xafa20014, 0x8fa60028, 0x34a50300, 0xc002b17, +0x8f820124, 0x3c040001, 0x24845c34, 0x3c050009, +0xafa20014, 0x8fa60028, 0x34a50300, 0xc002b3b, 0x2603821, 0x8f4202f0, 0x24420001, 0xaf4202f0, -0x8f4202f0, 0x3c040001, 0x24846050, 0xafa00010, -0xafa00014, 0x8fa60028, 0x24052300, 0xc002b17, +0x8f4202f0, 0x3c040001, 0x24845fc0, 0xafa00010, +0xafa00014, 0x8fa60028, 0x24052300, 0xc002b3b, 0x3821, 0x10000004, 0x0, 0x8c020264, 0x10400005, 0x0, 0x8f8200a0, 0x30420004, 0x1440fffa, 0x0, 0x8f820044, 0x34420004, @@ -5049,31 +5050,31 @@ 0x431021, 0xaf420090, 0x24020001, 0xaf42008c, 0x32c20008, 0x10400006, 0x0, 0x8f820214, 0x3c038100, 0x3042ffff, 0x431025, 0xaf820214, -0x3c030001, 0x8c636e14, 0x30620002, 0x10400009, -0x30620001, 0x3c040001, 0x2484605c, 0x3c050000, -0x24a56cf0, 0x3c060000, 0x24c67168, 0x10000012, +0x3c030001, 0x8c636d94, 0x30620002, 0x10400009, +0x30620001, 0x3c040001, 0x24845fcc, 0x3c050000, +0x24a56d50, 0x3c060000, 0x24c671c8, 0x10000012, 0xc53023, 0x10400009, 0x0, 0x3c040001, -0x2484606c, 0x3c050000, 0x24a57170, 0x3c060000, -0x24c67618, 0x10000008, 0xc53023, 0x3c040001, -0x2484607c, 0x3c050000, 0x24a568e8, 0x3c060000, -0x24c66ce8, 0xc53023, 0x27a70030, 0x27a20034, -0xc00178b, 0xafa20010, 0x3c010001, 0xac226f48, -0x3c020001, 0x8c426f48, 0x3c030800, 0x21100, +0x24845fdc, 0x3c050000, 0x24a571d0, 0x3c060000, +0x24c67678, 0x10000008, 0xc53023, 0x3c040001, +0x24845fec, 0x3c050000, 0x24a56948, 0x3c060000, +0x24c66d48, 0xc53023, 0x27a70030, 0x27a20034, +0xc0017a3, 0xafa20010, 0x3c010001, 0xac226ecc, +0x3c020001, 0x8c426ecc, 0x3c030800, 0x21100, 0x21182, 0x431025, 0xae420040, 0x8f8200a0, 0xafa20010, 0x8f8200b0, 0xafa20014, 0x8f86005c, -0x8f87011c, 0x3c040001, 0x2484608c, 0x3c010001, -0xac366f20, 0x3c010001, 0xac206f10, 0x3c010001, -0xac3c6f08, 0x3c010001, 0xac3b6f38, 0x3c010001, -0xac376f3c, 0x3c010001, 0xac3a6f1c, 0xc002b17, +0x8f87011c, 0x3c040001, 0x24845ffc, 0x3c010001, +0xac366ea4, 0x3c010001, 0xac206e94, 0x3c010001, +0xac3c6e8c, 0x3c010001, 0xac3b6ebc, 0x3c010001, +0xac376ec0, 0x3c010001, 0xac3a6ea0, 0xc002b3b, 0x24052400, 0x8f820200, 0xafa20010, 0x8f820220, 0xafa20014, 0x8f860044, 0x8f870050, 0x3c040001, -0x24846098, 0xc002b17, 0x24052500, 0x8f830060, +0x24846008, 0xc002b3b, 0x24052500, 0x8f830060, 0x74100b, 0x242000a, 0x200f821, 0x0, -0xd, 0x8fbf0058, 0x8fbe0054, 0x8fb50050, -0x8fb3004c, 0x8fb20048, 0x8fb10044, 0x8fb00040, -0x3e00008, 0x27bd0060, 0x27bdffe0, 0x3c040001, -0x248460a4, 0x24052600, 0x3021, 0x3821, -0xafbf0018, 0xafa00010, 0xc002b17, 0xafa00014, +0xd, 0x8fbf0060, 0x8fbe005c, 0x8fb50058, +0x8fb30054, 0x8fb20050, 0x8fb1004c, 0x8fb00048, +0x3e00008, 0x27bd0068, 0x27bdffe0, 0x3c040001, +0x24846014, 0x24052600, 0x3021, 0x3821, +0xafbf0018, 0xafa00010, 0xc002b3b, 0xafa00014, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x3e00008, 0x0, 0x3e00008, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, @@ -5083,15 +5084,15 @@ 0xafa40018, 0xa22823, 0xa32824, 0x8ca20000, 0x1044000a, 0x0, 0xafa50010, 0x8ca20000, 0xafa20014, 0x8f860150, 0x8f870250, 0x3c040001, -0x248460ac, 0xc002b17, 0x24052700, 0x8fbf0218, +0x2484601c, 0xc002b3b, 0x24052700, 0x8fbf0218, 0x3e00008, 0x27bd0220, 0x27bdffe0, 0x3c06abba, 0x34c6babe, 0xafb00018, 0x3c100004, 0x3c07007f, 0x34e7ffff, 0xafbf001c, 0x102840, 0x8e040000, 0x8ca30000, 0xaca00000, 0xae060000, 0x8ca20000, 0xaca30000, 0x10460005, 0xae040000, 0xa08021, 0xf0102b, 0x1040fff5, 0x102840, 0x3c040001, -0x248460b8, 0x24052800, 0x2003021, 0x3821, -0xafa00010, 0xc002b17, 0xafa00014, 0x2001021, +0x24846028, 0x24052800, 0x2003021, 0x3821, +0xafa00010, 0xc002b3b, 0xafa00014, 0x2001021, 0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020, 0x8c020224, 0x3047003f, 0x10e00010, 0x803021, 0x2821, 0x24030020, 0xe31024, 0x10400002, @@ -5106,84 +5107,84 @@ 0x8ea20000, 0x2403fffc, 0xc38024, 0x50102b, 0x1440001b, 0xe08821, 0x8e330000, 0xafb00010, 0x8ea20000, 0xafa20014, 0x8e270000, 0x24053000, -0xc002b17, 0x2403021, 0x8e230000, 0x702021, +0xc002b3b, 0x2403021, 0x8e230000, 0x702021, 0x64102b, 0x10400007, 0x2402821, 0x8ca20000, 0xac620000, 0x24630004, 0x64102b, 0x1440fffb, 0x24a50004, 0x8ea20000, 0x501023, 0xaea20000, 0x8e220000, 0x501021, 0x1000000b, 0xae220000, 0x2402002d, 0xa0820000, 0xafb00010, 0x8ea20000, 0x2409821, 0xafa20014, 0x8e270000, 0x24053100, -0xc002b17, 0x2603021, 0x2601021, 0x8fbf002c, +0xc002b3b, 0x2603021, 0x2601021, 0x8fbf002c, 0x8fb50028, 0x8fb30024, 0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0030, 0x27bdffe8, -0x3c1cc000, 0x3c05fffe, 0x3c030001, 0x8c636f00, -0x3c040001, 0x8c846f0c, 0x34a5bf08, 0x24021ffc, -0x3c010001, 0xac226d50, 0x3c0200c0, 0x3c010001, -0xac226d54, 0x3c020020, 0xafbf0010, 0x3c0100c0, +0x3c1cc000, 0x3c05fffe, 0x3c030001, 0x8c636e84, +0x3c040001, 0x8c846e90, 0x34a5bf08, 0x24021ffc, +0x3c010001, 0xac226cd0, 0x3c0200c0, 0x3c010001, +0xac226cd4, 0x3c020020, 0xafbf0010, 0x3c0100c0, 0xac201ffc, 0x431023, 0x441023, 0x245bb000, -0x365b821, 0x3c1d0001, 0x8fbd6d4c, 0x3a0f021, +0x365b821, 0x3c1d0001, 0x8fbd6ccc, 0x3a0f021, 0x3c0400c0, 0x34840200, 0x3c1a00c0, 0x3c0300c0, -0x346307c8, 0x24021dfc, 0x3c010001, 0xac226d50, -0x24021834, 0x3c010001, 0xac246d54, 0x3c010001, -0xac226d50, 0x3c010001, 0xac236d54, 0xc0017f5, +0x346307c8, 0x24021dfc, 0x3c010001, 0xac226cd0, +0x24021834, 0x3c010001, 0xac246cd4, 0x3c010001, +0xac226cd0, 0x3c010001, 0xac236cd4, 0xc00180d, 0x375a0200, 0x8fbf0010, 0x3e00008, 0x27bd0018, -0x27bdffc8, 0x3c040001, 0x248460c4, 0x24053200, -0x3c020001, 0x8c426d50, 0x3c030001, 0x8c636d54, +0x27bdffc8, 0x3c040001, 0x24846034, 0x24053200, +0x3c020001, 0x8c426cd0, 0x3c030001, 0x8c636cd4, 0x3021, 0x3603821, 0xafbf0030, 0xafb3002c, 0xafb20028, 0xafb10024, 0xafb00020, 0xafa2001c, -0xafa30018, 0xafb70010, 0xc002b17, 0xafba0014, -0xc0018fe, 0x0, 0x8f820240, 0x34420004, +0xafa30018, 0xafb70010, 0xc002b3b, 0xafba0014, +0xc001916, 0x0, 0x8f820240, 0x34420004, 0xaf820240, 0x24020001, 0xaf420000, 0x3c020001, 0x571021, 0x904240f4, 0x10400092, 0x2403fffc, -0x3c100001, 0x2610abe3, 0x3c120001, 0x2652a7bc, +0x3c100001, 0x2610ac73, 0x3c120001, 0x2652a84c, 0x2121023, 0x438024, 0x8fa3001c, 0x3c040001, -0x248460d0, 0x70102b, 0x1440001a, 0x27b30018, +0x24846040, 0x70102b, 0x1440001a, 0x27b30018, 0x8fb10018, 0x24053000, 0x2403021, 0xafb00010, -0xafa30014, 0xc002b17, 0x2203821, 0x8fa30018, +0xafa30014, 0xc002b3b, 0x2203821, 0x8fa30018, 0x702021, 0x64102b, 0x10400007, 0x2403021, 0x8cc20000, 0xac620000, 0x24630004, 0x64102b, 0x1440fffb, 0x24c60004, 0x8fa2001c, 0x501023, 0xafa2001c, 0x8e620000, 0x501021, 0x1000000a, 0xae620000, 0x2408821, 0x24053100, 0xafb00010, 0xafa30014, 0x8fa70018, 0x2203021, 0x2402002d, -0xc002b17, 0xa0820000, 0x24070020, 0x8fa3001c, -0x3c040001, 0x248460ec, 0x24120020, 0x3c010001, -0xac316f2c, 0x2c620020, 0x1440001d, 0x27b10018, -0x8fb00018, 0x24053000, 0x3c060001, 0x24c66fd0, -0xafa70010, 0xafa30014, 0xc002b17, 0x2003821, -0x8fa30018, 0x3c040001, 0x24846fd0, 0x24650020, +0xc002b3b, 0xa0820000, 0x24070020, 0x8fa3001c, +0x3c040001, 0x2484605c, 0x24120020, 0x3c010001, +0xac316eb0, 0x2c620020, 0x1440001d, 0x27b10018, +0x8fb00018, 0x24053000, 0x3c060001, 0x24c66f50, +0xafa70010, 0xafa30014, 0xc002b3b, 0x2003821, +0x8fa30018, 0x3c040001, 0x24846f50, 0x24650020, 0x65102b, 0x10400007, 0x0, 0x8c820000, 0xac620000, 0x24630004, 0x65102b, 0x1440fffb, 0x24840004, 0x8fa2001c, 0x521023, 0xafa2001c, 0x8e220000, 0x521021, 0x1000000b, 0xae220000, -0x3c100001, 0x26106fd0, 0x24053100, 0xafa70010, +0x3c100001, 0x26106f50, 0x24053100, 0xafa70010, 0xafa30014, 0x8fa70018, 0x2003021, 0x2402002d, -0xc002b17, 0xa0820000, 0x24070020, 0x3c040001, -0x24846100, 0x8fa3001c, 0x24120020, 0x3c010001, -0xac306f60, 0x2c620020, 0x1440001d, 0x27b10018, -0x8fb00018, 0x24053000, 0x3c060001, 0x24c66ff0, -0xafa70010, 0xafa30014, 0xc002b17, 0x2003821, -0x8fa30018, 0x3c040001, 0x24846ff0, 0x24650020, +0xc002b3b, 0xa0820000, 0x24070020, 0x3c040001, +0x24846070, 0x8fa3001c, 0x24120020, 0x3c010001, +0xac306ee4, 0x2c620020, 0x1440001d, 0x27b10018, +0x8fb00018, 0x24053000, 0x3c060001, 0x24c66f70, +0xafa70010, 0xafa30014, 0xc002b3b, 0x2003821, +0x8fa30018, 0x3c040001, 0x24846f70, 0x24650020, 0x65102b, 0x10400007, 0x0, 0x8c820000, 0xac620000, 0x24630004, 0x65102b, 0x1440fffb, 0x24840004, 0x8fa2001c, 0x521023, 0xafa2001c, 0x8e220000, 0x521021, 0x1000000b, 0xae220000, -0x3c100001, 0x26106ff0, 0x24053100, 0xafa70010, +0x3c100001, 0x26106f70, 0x24053100, 0xafa70010, 0xafa30014, 0x8fa70018, 0x2003021, 0x2402002d, -0xc002b17, 0xa0820000, 0x3c010001, 0x10000031, -0xac306f5c, 0x3c100001, 0x261081bf, 0x3c120001, -0x2652803c, 0x2121023, 0x438024, 0x8fa3001c, -0x3c040001, 0x24846114, 0x70102b, 0x1440001a, +0xc002b3b, 0xa0820000, 0x3c010001, 0x10000031, +0xac306ee0, 0x3c100001, 0x2610821f, 0x3c120001, +0x2652809c, 0x2121023, 0x438024, 0x8fa3001c, +0x3c040001, 0x24846084, 0x70102b, 0x1440001a, 0x27b30018, 0x8fb10018, 0x24053000, 0x2403021, -0xafb00010, 0xafa30014, 0xc002b17, 0x2203821, +0xafb00010, 0xafa30014, 0xc002b3b, 0x2203821, 0x8fa30018, 0x702021, 0x64102b, 0x10400007, 0x2403021, 0x8cc20000, 0xac620000, 0x24630004, 0x64102b, 0x1440fffb, 0x24c60004, 0x8fa2001c, 0x501023, 0xafa2001c, 0x8e620000, 0x501021, 0x1000000a, 0xae620000, 0x2408821, 0x24053100, 0xafb00010, 0xafa30014, 0x8fa70018, 0x2203021, -0x2402002d, 0xc002b17, 0xa0820000, 0x3c010001, -0xac316f2c, 0x3c030001, 0x8c636f2c, 0x24020400, +0x2402002d, 0xc002b3b, 0xa0820000, 0x3c010001, +0xac316eb0, 0x3c030001, 0x8c636eb0, 0x24020400, 0x60f809, 0xaf820070, 0x8fbf0030, 0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020, 0x3e00008, 0x27bd0038, 0x0, 0x0, 0x8f820040, @@ -5197,21 +5198,21 @@ 0xaf820078, 0x27bdffe8, 0xafbf0010, 0x8f820054, 0x244203e8, 0xaf820058, 0x3c020800, 0x2c21024, 0x10400004, 0x3c02f7ff, 0x3442ffff, 0x2c2b024, -0x36940040, 0x3c020001, 0x8c426e28, 0x10400017, -0x3c020200, 0x3c030001, 0x8c636f98, 0x10600016, -0x282a025, 0x3c020001, 0x8c426ec4, 0x14400012, -0x3c020200, 0x3c020001, 0x8c426e14, 0x30420003, +0x36940040, 0x3c020001, 0x8c426da8, 0x10400017, +0x3c020200, 0x3c030001, 0x8c636f1c, 0x10600016, +0x282a025, 0x3c020001, 0x8c426e44, 0x14400012, +0x3c020200, 0x3c020001, 0x8c426d94, 0x30420003, 0x1440000d, 0x3c020200, 0x8f830224, 0x3c020002, -0x8c42906c, 0x10620008, 0x3c020200, 0xc003d87, -0x0, 0x10000004, 0x3c020200, 0xc004161, +0x8c428fec, 0x10620008, 0x3c020200, 0xc003daf, +0x0, 0x10000004, 0x3c020200, 0xc004196, 0x0, 0x3c020200, 0x2c21024, 0x10400003, -0x0, 0xc001f33, 0x0, 0x8f4200d8, +0x0, 0xc001f4b, 0x0, 0x8f4200d8, 0x8f4300dc, 0x24420001, 0xaf4200d8, 0x43102b, 0x14400003, 0x0, 0xaf4000d8, 0x36940080, 0x8c030238, 0x1060000c, 0x0, 0x8f4201b0, 0x244203e8, 0xaf4201b0, 0x43102b, 0x14400006, 0x0, 0x934205c5, 0x14400003, 0x0, -0xc001d88, 0x0, 0x8fbf0010, 0x3e00008, +0xc001da0, 0x0, 0x8fbf0010, 0x3e00008, 0x27bd0018, 0x3e00008, 0x0, 0x27bdffd8, 0xafbf0020, 0x8f43002c, 0x8f420038, 0x10620059, 0x0, 0x3c020001, 0x571021, 0x904240f0, @@ -5220,8 +5221,8 @@ 0xafa30014, 0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011, 0x24020001, 0x3c010001, 0x370821, 0xa02240f0, 0x8f820124, 0xafa20010, -0x8f820128, 0x3c040001, 0x248461b8, 0xafa20014, -0x8f46002c, 0x8f870120, 0x3c050009, 0xc002b17, +0x8f820128, 0x3c040001, 0x24846128, 0xafa20014, +0x8f46002c, 0x8f870120, 0x3c050009, 0xc002b3b, 0x34a50900, 0x1000005c, 0x0, 0x8f420300, 0x24420001, 0xaf420300, 0x8f420300, 0x8f42002c, 0xa34005c1, 0x10000027, 0xaf420038, 0x8f440170, @@ -5230,8 +5231,8 @@ 0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011, 0x24020001, 0x3c010001, 0x370821, 0xa02240f1, 0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001, -0x248461c4, 0xafa20014, 0x8f46002c, 0x8f870120, -0x3c050009, 0xc002b17, 0x34a51100, 0x10000036, +0x24846134, 0xafa20014, 0x8f46002c, 0x8f870120, +0x3c050009, 0xc002b3b, 0x34a51100, 0x10000036, 0x0, 0x8f420300, 0x8f43002c, 0x24420001, 0xaf420300, 0x8f420300, 0x24020001, 0xa34205c1, 0xaf430038, 0x3c010001, 0x370821, 0xa02040f1, @@ -5259,8 +5260,8 @@ 0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011, 0x24020001, 0x3c010001, 0x370821, 0xa02240f2, 0x8f820124, 0xafa20010, 0x8f820128, -0x3c040001, 0x248461cc, 0xafa20014, 0x8f460044, -0x8f870120, 0x3c050009, 0xc002b17, 0x34a51300, +0x3c040001, 0x2484613c, 0xafa20014, 0x8f460044, +0x8f870120, 0x3c050009, 0xc002b3b, 0x34a51300, 0x1000000f, 0x0, 0x8f420304, 0x24420001, 0xaf420304, 0x8f420304, 0x8f420044, 0xaf42007c, 0x3c010001, 0x370821, 0xa02040f2, 0x10000004, @@ -5272,20 +5273,20 @@ 0x431024, 0xaf820060, 0x8f420000, 0x10400003, 0x0, 0x10000002, 0xaf80004c, 0xaf800048, 0x8fbf0020, 0x3e00008, 0x27bd0028, 0x3e00008, -0x0, 0x3c020001, 0x8c426e28, 0x27bdffa8, +0x0, 0x3c020001, 0x8c426da8, 0x27bdffa8, 0xafbf0050, 0xafbe004c, 0xafb50048, 0xafb30044, 0xafb20040, 0xafb1003c, 0xafb00038, 0x104000d5, 0x8f900044, 0x8f4200d0, 0x24430001, 0x2842000b, 0x144000e4, 0xaf4300d0, 0x8f420004, 0x30420002, 0x1440009c, 0xaf4000d0, 0x8f420004, 0x3c030001, -0x8c636e18, 0x34420002, 0xaf420004, 0x24020001, +0x8c636d98, 0x34420002, 0xaf420004, 0x24020001, 0x14620003, 0x3c020600, 0x10000002, 0x34423000, 0x34421000, 0xafa20020, 0x8f4a0018, 0xafaa0034, 0x27aa0020, 0xafaa002c, 0x8faa0034, 0x240200ff, 0x11420002, 0x1821, 0x25430001, 0x8c020228, 0x609821, 0x1662000e, 0x3c050009, 0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, 0x8c020228, -0x8fa70034, 0x3c040001, 0x2484619c, 0xafa00014, +0x8fa70034, 0x3c040001, 0x2484610c, 0xafa00014, 0xafa20010, 0x8fa60020, 0x10000070, 0x34a50500, 0x8faa0034, 0xa38c0, 0xf71021, 0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, 0x8f830054, @@ -5300,7 +5301,7 @@ 0x32a200ff, 0x54400018, 0xaf530018, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, 0x8fa70034, 0xafa20010, 0x8f820124, -0x3c040001, 0x248461a8, 0xafa20014, 0x8d460000, +0x3c040001, 0x24846118, 0xafa20014, 0x8d460000, 0x3c050009, 0x10000035, 0x34a50600, 0x8f420308, 0x24150001, 0x24420001, 0xaf420308, 0x8f420308, 0x1000001e, 0x32a200ff, 0x8f830054, 0x8f820054, @@ -5313,8 +5314,8 @@ 0x1440ffee, 0x0, 0x32a200ff, 0x14400011, 0x3c050009, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, 0x8fa70034, -0xafa20010, 0x8f820124, 0x3c040001, 0x248461b0, -0xafa20014, 0x8d460000, 0x34a50700, 0xc002b17, +0xafa20010, 0x8f820124, 0x3c040001, 0x24846120, +0xafa20014, 0x8d460000, 0x34a50700, 0xc002b3b, 0x0, 0x8f4202ec, 0x24420001, 0xaf4202ec, 0x8f4202ec, 0x8f420004, 0x30420001, 0x50400029, 0x36100040, 0x3c020400, 0x2c21024, 0x10400013, @@ -5337,19 +5338,19 @@ 0x8fbf0050, 0x8fbe004c, 0x8fb50048, 0x8fb30044, 0x8fb20040, 0x8fb1003c, 0x8fb00038, 0x3e00008, 0x27bd0058, 0x3e00008, 0x0, 0x3c020001, -0x8c426e28, 0x27bdffb0, 0xafbf0048, 0xafbe0044, +0x8c426da8, 0x27bdffb0, 0xafbf0048, 0xafbe0044, 0xafb50040, 0xafb3003c, 0xafb20038, 0xafb10034, 0x104000c7, 0xafb00030, 0x8f4200d0, 0x24430001, 0x2842000b, 0x144000da, 0xaf4300d0, 0x8f420004, 0x30420002, 0x14400097, 0xaf4000d0, 0x8f420004, -0x3c030001, 0x8c636e18, 0x34420002, 0xaf420004, +0x3c030001, 0x8c636d98, 0x34420002, 0xaf420004, 0x24020001, 0x14620003, 0x3c020600, 0x10000002, 0x34423000, 0x34421000, 0xafa20020, 0x1821, 0x8f5e0018, 0x27aa0020, 0x240200ff, 0x13c20002, 0xafaa002c, 0x27c30001, 0x8c020228, 0x609021, 0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001, -0x2484619c, 0x3c050009, 0xafa00014, 0xafa20010, +0x2484610c, 0x3c050009, 0xafa00014, 0xafa20010, 0x8fa60020, 0x1000006d, 0x34a50500, 0xf71021, 0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054, 0x247003e8, 0x2021023, @@ -5363,7 +5364,7 @@ 0x0, 0x326200ff, 0x54400017, 0xaf520018, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010, 0x8f820124, -0x3c040001, 0x248461a8, 0x3c050009, 0xafa20014, +0x3c040001, 0x24846118, 0x3c050009, 0xafa20014, 0x8d460000, 0x10000035, 0x34a50600, 0x8f420308, 0x24130001, 0x24420001, 0xaf420308, 0x8f420308, 0x1000001e, 0x326200ff, 0x8f830054, 0x8f820054, @@ -5376,43 +5377,43 @@ 0x1440ffee, 0x0, 0x326200ff, 0x14400011, 0x0, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010, -0x8f820124, 0x3c040001, 0x248461b0, 0x3c050009, -0xafa20014, 0x8d460000, 0x34a50700, 0xc002b17, +0x8f820124, 0x3c040001, 0x24846120, 0x3c050009, +0xafa20014, 0x8d460000, 0x34a50700, 0xc002b3b, 0x3c03821, 0x8f4202ec, 0x24420001, 0xaf4202ec, 0x8f4202ec, 0x8f420004, 0x30420001, 0x10400018, 0x24040001, 0x8f420250, 0x8f430254, 0x8f4501b4, -0x3c010001, 0x14650006, 0xa0246d71, 0x8f420270, +0x3c010001, 0x14650006, 0xa0246cf1, 0x8f420270, 0x8f430274, 0x8f4401b8, 0x10640021, 0x0, -0x8f420250, 0x8f430254, 0x3c040001, 0x90846d70, +0x8f420250, 0x8f430254, 0x3c040001, 0x90846cf0, 0x8f460270, 0x8f470274, 0x38840001, 0xaf4301b4, -0xaf4701b8, 0x3c010001, 0x10000025, 0xa0246d70, -0x8f4200d4, 0x3c010001, 0xa0206d70, 0x24430001, +0xaf4701b8, 0x3c010001, 0x10000025, 0xa0246cf0, +0x8f4200d4, 0x3c010001, 0xa0206cf0, 0x24430001, 0x28420033, 0x1440001e, 0xaf4300d4, 0x3c020001, -0x90426d71, 0xaf4000d4, 0x10000017, 0x38420001, +0x90426cf1, 0xaf4000d4, 0x10000017, 0x38420001, 0x8f420004, 0x30420001, 0x10400008, 0x0, -0xc00567e, 0x2021, 0x3c010001, 0xa0206d71, -0x3c010001, 0x1000000e, 0xa0206d70, 0x8f4200d4, -0x3c010001, 0xa0206d70, 0x24430001, 0x284201f5, -0x14400007, 0xaf4300d4, 0x3c020001, 0x90426d71, -0xaf4000d4, 0x421026, 0x3c010001, 0xa0226d71, -0x3c030001, 0x8c636e18, 0x24020002, 0x1462000c, -0x3c030002, 0x3c030001, 0x90636d71, 0x24020001, -0x5462001f, 0x2021, 0x3c020001, 0x90426d70, +0xc00565a, 0x2021, 0x3c010001, 0xa0206cf1, +0x3c010001, 0x1000000e, 0xa0206cf0, 0x8f4200d4, +0x3c010001, 0xa0206cf0, 0x24430001, 0x284201f5, +0x14400007, 0xaf4300d4, 0x3c020001, 0x90426cf1, +0xaf4000d4, 0x421026, 0x3c010001, 0xa0226cf1, +0x3c030001, 0x8c636d98, 0x24020002, 0x1462000c, +0x3c030002, 0x3c030001, 0x90636cf1, 0x24020001, +0x5462001f, 0x2021, 0x3c020001, 0x90426cf0, 0x1443001b, 0x24040005, 0x10000019, 0x24040006, -0x3c020002, 0x8c429074, 0x431024, 0x1040000b, -0x24020001, 0x3c030001, 0x90636d71, 0x54620010, -0x2021, 0x3c020001, 0x90426d70, 0x1443000c, +0x3c020002, 0x8c428ff4, 0x431024, 0x1040000b, +0x24020001, 0x3c030001, 0x90636cf1, 0x54620010, +0x2021, 0x3c020001, 0x90426cf0, 0x1443000c, 0x24040003, 0x1000000a, 0x24040004, 0x3c030001, -0x90636d71, 0x14620006, 0x2021, 0x3c020001, -0x90426d70, 0x24040001, 0x50440001, 0x24040002, -0xc00567e, 0x0, 0x2402ff7f, 0x282a024, +0x90636cf1, 0x14620006, 0x2021, 0x3c020001, +0x90426cf0, 0x24040001, 0x50440001, 0x24040002, +0xc00565a, 0x0, 0x2402ff7f, 0x282a024, 0x8fbf0048, 0x8fbe0044, 0x8fb50040, 0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008, 0x27bd0050, 0x3e00008, 0x0, 0x3c020001, -0x8c426e28, 0x27bdffb0, 0xafbf0048, 0xafbe0044, +0x8c426da8, 0x27bdffb0, 0xafbf0048, 0xafbe0044, 0xafb50040, 0xafb3003c, 0xafb20038, 0xafb10034, 0x104000de, 0xafb00030, 0x8f4200d0, 0x3c040001, -0x8c846e18, 0x24430001, 0x2842000b, 0xaf4400e8, +0x8c846d98, 0x24430001, 0x2842000b, 0xaf4400e8, 0x144000fe, 0xaf4300d0, 0x8f420004, 0x30420002, 0x14400095, 0xaf4000d0, 0x8f420004, 0x34420002, 0xaf420004, 0x24020001, 0x14820003, 0x3c020600, @@ -5421,7 +5422,7 @@ 0x13c20002, 0xafaa002c, 0x27c30001, 0x8c020228, 0x609021, 0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, 0x8c020228, -0x3c040001, 0x2484619c, 0x3c050009, 0xafa00014, +0x3c040001, 0x2484610c, 0x3c050009, 0xafa00014, 0xafa20010, 0x8fa60020, 0x1000006d, 0x34a50500, 0xf71021, 0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054, 0x247003e8, @@ -5435,7 +5436,7 @@ 0x1440ffe9, 0x0, 0x326200ff, 0x54400017, 0xaf520018, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010, -0x8f820124, 0x3c040001, 0x248461a8, 0x3c050009, +0x8f820124, 0x3c040001, 0x24846118, 0x3c050009, 0xafa20014, 0x8d460000, 0x10000035, 0x34a50600, 0x8f420308, 0x24130001, 0x24420001, 0xaf420308, 0x8f420308, 0x1000001e, 0x326200ff, 0x8f830054, @@ -5448,9 +5449,9 @@ 0x2c4203e9, 0x1440ffee, 0x0, 0x326200ff, 0x14400011, 0x0, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, -0xafa20010, 0x8f820124, 0x3c040001, 0x248461b0, +0xafa20010, 0x8f820124, 0x3c040001, 0x24846120, 0x3c050009, 0xafa20014, 0x8d460000, 0x34a50700, -0xc002b17, 0x3c03821, 0x8f4202ec, 0x24420001, +0xc002b3b, 0x3c03821, 0x8f4202ec, 0x24420001, 0xaf4202ec, 0x8f4202ec, 0x8f420004, 0x30420001, 0x10400033, 0x3c020400, 0x2c21024, 0x10400017, 0x0, 0x934205c0, 0x8f440250, 0x8f450254, @@ -5480,7 +5481,7 @@ 0x8f4300e8, 0x3042007f, 0xa34205c0, 0x24020001, 0x14620005, 0x0, 0x934405c0, 0x42102, 0x10000003, 0x348400f0, 0x934405c0, 0x3484000f, -0xc005664, 0x0, 0x2402ff7f, 0x282a024, +0xc005640, 0x0, 0x2402ff7f, 0x282a024, 0x8fbf0048, 0x8fbe0044, 0x8fb50040, 0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008, 0x27bd0050, 0x3e00008, 0x0, 0x27bdffb0, @@ -5533,7 +5534,7 @@ 0xafaa002c, 0x27c30001, 0x8c020228, 0x609021, 0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001, -0x2484619c, 0x3c050009, 0xafa00014, 0xafa20010, +0x2484610c, 0x3c050009, 0xafa00014, 0xafa20010, 0x8fa60020, 0x1000006b, 0x34a50500, 0xf71021, 0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054, 0x247003e8, 0x2021023, @@ -5547,7 +5548,7 @@ 0x0, 0x326200ff, 0x54400017, 0xaf520018, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010, 0x8f820124, -0x3c040001, 0x248461a8, 0x3c050009, 0xafa20014, +0x3c040001, 0x24846118, 0x3c050009, 0xafa20014, 0x8d460000, 0x10000033, 0x34a50600, 0x8f420308, 0x24130001, 0x24420001, 0xaf420308, 0x8f420308, 0x1000001c, 0x326200ff, 0x8f830054, 0x8f820054, @@ -5560,13 +5561,13 @@ 0x326200ff, 0x54400012, 0x24020001, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010, 0x8f820124, 0x3c040001, -0x248461b0, 0x3c050009, 0xafa20014, 0x8d460000, -0x34a50700, 0xc002b17, 0x3c03821, 0x1021, +0x24846120, 0x3c050009, 0xafa20014, 0x8d460000, +0x34a50700, 0xc002b3b, 0x3c03821, 0x1021, 0x1440005b, 0x24020001, 0x10000065, 0x0, 0x8f510018, 0x240200ff, 0x12220002, 0x8021, 0x26300001, 0x8c020228, 0x1602000e, 0x1130c0, 0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, -0x8c020228, 0x3c040001, 0x24846184, 0x3c050009, +0x8c020228, 0x3c040001, 0x248460f4, 0x3c050009, 0xafa00014, 0xafa20010, 0x8fa60020, 0x1000003f, 0x34a50100, 0xd71021, 0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, 0xc01821, 0x8f440178, @@ -5575,15 +5576,15 @@ 0xafa80018, 0x8f48010c, 0x24070008, 0xa32821, 0xa3482b, 0x822021, 0x100f809, 0x892021, 0x1440000b, 0x24070008, 0x8f820120, 0xafa20010, -0x8f820124, 0x3c040001, 0x2484618c, 0x3c050009, +0x8f820124, 0x3c040001, 0x248460fc, 0x3c050009, 0xafa20014, 0x8fa60020, 0x1000001c, 0x34a50200, 0x8f440160, 0x8f450164, 0x8f43000c, 0xaf500018, 0x8f860120, 0x24020010, 0xafa20010, 0xafb00014, 0xafa30018, 0x8f42010c, 0x40f809, 0x24c6001c, 0x54400011, 0x24020001, 0x8f420340, 0x24420001, 0xaf420340, 0x8f420340, 0x8f820120, 0xafa20010, -0x8f820124, 0x3c040001, 0x24846194, 0x3c050009, -0xafa20014, 0x8fa60020, 0x34a50300, 0xc002b17, +0x8f820124, 0x3c040001, 0x24846104, 0x3c050009, +0xafa20014, 0x8fa60020, 0x34a50300, 0xc002b3b, 0x2203821, 0x1021, 0x1040000d, 0x24020001, 0x8f4202e8, 0xa34005c6, 0xaf4001b0, 0x24420001, 0xaf4202e8, 0x8f4202e8, 0x8ee20150, 0x24420001, @@ -5603,11 +5604,11 @@ 0x14620005, 0x0, 0x8f430130, 0x8f8200b4, 0x10620010, 0x0, 0x8f820104, 0xaf420128, 0x8f8200b4, 0x8f430128, 0xaf420130, 0xafa30010, -0x8f420130, 0x3c040001, 0x248461d4, 0xafa20014, +0x8f420130, 0x3c040001, 0x24846144, 0xafa20014, 0x8f86011c, 0x8f8700b0, 0x3c050005, 0x10000031, 0x34a50900, 0x8f420128, 0xafa20010, 0x8f420130, -0x3c040001, 0x248461e0, 0xafa20014, 0x8f86011c, -0x8f8700b0, 0x3c050005, 0xc002b17, 0x34a51000, +0x3c040001, 0x24846150, 0xafa20014, 0x8f86011c, +0x8f8700b0, 0x3c050005, 0xc002b3b, 0x34a51000, 0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830104, 0x8f8200b0, 0x34420001, 0xaf8200b0, 0x24020008, 0xaf830104, 0xafa20010, 0xafa00014, 0x8f42000c, @@ -5615,9 +5616,9 @@ 0x26e60028, 0x40f809, 0x24070400, 0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201dc, 0x24420001, 0xaee201dc, 0x8ee201dc, 0x8f420128, -0xafa20010, 0x8f420130, 0x3c040001, 0x248461ec, +0xafa20010, 0x8f420130, 0x3c040001, 0x2484615c, 0xafa20014, 0x8f86011c, 0x8f8700b0, 0x3c050005, -0x34a51100, 0xc002b17, 0x0, 0x8f8200a0, +0x34a51100, 0xc002b3b, 0x0, 0x8f8200a0, 0x30420004, 0x10400069, 0x0, 0x8f43012c, 0x8f820124, 0x14620005, 0x0, 0x8f430134, 0x8f8200a4, 0x10620006, 0x0, 0x8f820124, @@ -5630,21 +5631,21 @@ 0x0, 0x8f430134, 0x8f8200a4, 0x10620010, 0x0, 0x8f820124, 0xaf42012c, 0x8f8200a4, 0x8f43012c, 0xaf420134, 0xafa30010, 0x8f420134, -0x3c040001, 0x248461f8, 0xafa20014, 0x8f86011c, +0x3c040001, 0x24846168, 0xafa20014, 0x8f86011c, 0x8f8700a0, 0x3c050005, 0x10000032, 0x34a51200, 0x8f42012c, 0xafa20010, 0x8f420134, 0x3c040001, -0x24846204, 0xafa20014, 0x8f86011c, 0x8f8700a0, -0x3c050005, 0xc002b17, 0x34a51300, 0x8f82011c, +0x24846174, 0xafa20014, 0x8f86011c, 0x8f8700a0, +0x3c050005, 0xc002b3b, 0x34a51300, 0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830124, 0x8f8200a0, 0x34420001, 0xaf8200a0, 0x24020080, 0xaf830124, 0xafa20010, 0xafa00014, 0x8f420014, 0x8c040208, 0x8c05020c, 0xafa20018, 0x8f420108, 0x3c060001, -0x24c66f54, 0x40f809, 0x24070004, 0x8f82011c, +0x24c66ed8, 0x40f809, 0x24070004, 0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201dc, 0x24420001, 0xaee201dc, 0x8ee201dc, 0x8f42012c, -0xafa20010, 0x8f420134, 0x3c040001, 0x24846210, +0xafa20010, 0x8f420134, 0x3c040001, 0x24846180, 0xafa20014, 0x8f86011c, 0x8f8700a0, 0x3c050005, -0x34a51400, 0xc002b17, 0x0, 0x8fbf0020, +0x34a51400, 0xc002b3b, 0x0, 0x8fbf0020, 0x3e00008, 0x27bd0028, 0x3c081000, 0x24070001, 0x3c060080, 0x3c050100, 0x8f820070, 0x481024, 0x1040fffd, 0x0, 0x8f820054, 0x24420005, @@ -5712,8 +5713,8 @@ 0xaf80004c, 0x1000006a, 0xaf800048, 0x30c20001, 0x10400004, 0x24020001, 0xaf820064, 0x10000064, 0x0, 0x30c20002, 0x1440000b, 0x3c050003, -0x3c040001, 0x248462d4, 0x34a50500, 0x3821, -0xafa00010, 0xc002b17, 0xafa00014, 0x2402ffc0, +0x3c040001, 0x24846244, 0x34a50500, 0x3821, +0xafa00010, 0xc002b3b, 0xafa00014, 0x2402ffc0, 0x10000057, 0xaf820064, 0x8c05022c, 0x8c02010c, 0x10a20048, 0x51080, 0x8c460300, 0x24a20001, 0x3045003f, 0x24020003, 0xac05022c, 0x61e02, @@ -5732,7 +5733,7 @@ 0xaf800048, 0x8f820048, 0x1040fffd, 0x0, 0x8f820060, 0x34420100, 0xaf820060, 0x8f420000, 0x10400003, 0x0, 0x10000006, 0xaf80004c, -0x10000004, 0xaf800048, 0xc00217e, 0xc02021, +0x10000004, 0xaf800048, 0xc002196, 0xc02021, 0x402821, 0x8c02010c, 0x14a20002, 0x24020002, 0xaf820064, 0x8f820064, 0x30420002, 0x14400004, 0x0, 0x8c02010c, 0x14a2ffac, 0x0, @@ -5740,196 +5741,199 @@ 0x0, 0x27bdffa0, 0xafb00040, 0x808021, 0x101602, 0x2442ffff, 0x304300ff, 0x2c620013, 0xafbf0058, 0xafbe0054, 0xafb50050, 0xafb3004c, -0xafb20048, 0xafb10044, 0x104001ec, 0xafa50034, -0x31080, 0x3c010001, 0x220821, 0x8c226318, +0xafb20048, 0xafb10044, 0x104001f3, 0xafa50034, +0x31080, 0x3c010001, 0x220821, 0x8c226288, 0x400008, 0x0, 0x101302, 0x30440fff, -0x24020001, 0x10820005, 0x24020002, 0x1082000a, -0x2402fffe, 0x10000021, 0x3c050003, 0x8f430004, -0x3c020001, 0x8c426f80, 0xaf440200, 0xaf440204, -0x10000007, 0x34630001, 0x8f430004, 0xaf440200, -0xaf440204, 0x621824, 0x3c020001, 0x2442c9c8, +0x24020001, 0x10820005, 0x24020002, 0x1082000c, +0x2402fffe, 0x10000024, 0x3c050003, 0x8f430004, +0x3c020001, 0x8c426f04, 0xaf440200, 0xaf440204, +0x3c040001, 0x8c846e80, 0x10000009, 0x34630001, +0x8f430004, 0xaf440200, 0xaf440204, 0x3c040001, +0x8c846e80, 0x621824, 0x3c020001, 0x2442ca28, 0x21100, 0x21182, 0xaf430004, 0x3c030800, -0x431025, 0x3c010000, 0xac224138, 0x8f840054, -0x41442, 0x41c82, 0x431021, 0x41cc2, -0x431023, 0x41d02, 0x431021, 0x41d42, -0x431023, 0x10000009, 0xaf420208, 0x3c040001, -0x248462e0, 0x34a51000, 0x2003021, 0x3821, -0xafa00010, 0xc002b17, 0xafa00014, 0x8f4202a0, -0x24420001, 0xaf4202a0, 0x1000021b, 0x8f4202a0, -0x27b00028, 0x2002021, 0x24050210, 0xc002b9b, -0x24060008, 0xc0024f4, 0x2002021, 0x10000212, -0x0, 0x8faa0034, 0x27a40028, 0xa1880, -0x25420001, 0x3042003f, 0xafa20034, 0x8c650300, -0x8faa0034, 0x21080, 0x8c430300, 0x25420001, -0x3042003f, 0xafa20034, 0xac02022c, 0xafa50028, -0xc0024f4, 0xafa3002c, 0x100001ff, 0x0, -0x27b00028, 0x2002021, 0x24050210, 0xc002b9b, -0x24060008, 0xc002633, 0x2002021, 0x100001f6, -0x0, 0x8faa0034, 0x27a40028, 0xa1880, -0x25420001, 0x3042003f, 0xafa20034, 0x8c650300, -0x8faa0034, 0x21080, 0x8c430300, 0x25420001, -0x3042003f, 0xafa20034, 0xac02022c, 0xafa50028, -0xc002633, 0xafa3002c, 0x100001e3, 0x0, -0x101302, 0x30430fff, 0x24020001, 0x10620005, -0x24020002, 0x1062001e, 0x3c020002, 0x10000033, -0x3c050003, 0x3c030002, 0x2c31024, 0x54400037, -0x2c3b025, 0x8f820228, 0x3c010001, 0x370821, -0xac2238d8, 0x8f82022c, 0x3c010001, 0x370821, -0xac2238dc, 0x8f820230, 0x3c010001, 0x370821, -0xac2238e0, 0x8f820234, 0x3c010001, 0x370821, -0xac2238e4, 0x2402ffff, 0xaf820228, 0xaf82022c, -0xaf820230, 0xaf820234, 0x10000020, 0x2c3b025, -0x2c21024, 0x10400012, 0x3c02fffd, 0x3c020001, -0x571021, 0x8c4238d8, 0xaf820228, 0x3c020001, -0x571021, 0x8c4238dc, 0xaf82022c, 0x3c020001, -0x571021, 0x8c4238e0, 0xaf820230, 0x3c020001, -0x571021, 0x8c4238e4, 0xaf820234, 0x3c02fffd, -0x3442ffff, 0x10000009, 0x2c2b024, 0x3c040001, -0x248462ec, 0x34a51100, 0x2003021, 0x3821, -0xafa00010, 0xc002b17, 0xafa00014, 0x8f4202cc, -0x24420001, 0xaf4202cc, 0x1000019b, 0x8f4202cc, -0x101302, 0x30450fff, 0x24020001, 0x10a20005, -0x24020002, 0x10a2000d, 0x3c0408ff, 0x10000014, -0x3c050003, 0x3c0208ff, 0x3442ffff, 0x8f830220, -0x3c040004, 0x2c4b025, 0x621824, 0x34630008, -0xaf830220, 0x10000012, 0xaf450298, 0x3484fff7, -0x3c03fffb, 0x8f820220, 0x3463ffff, 0x2c3b024, -0x441024, 0xaf820220, 0x10000009, 0xaf450298, -0x3c040001, 0x248462f8, 0x34a51200, 0x2003021, -0x3821, 0xafa00010, 0xc002b17, 0xafa00014, -0x8f4202bc, 0x24420001, 0xaf4202bc, 0x10000172, -0x8f4202bc, 0x27840208, 0x24050200, 0xc002b9b, -0x24060008, 0x27440224, 0x24050200, 0xc002b9b, -0x24060008, 0x8f4202c4, 0x24420001, 0xaf4202c4, -0x10000165, 0x8f4202c4, 0x101302, 0x30430fff, -0x24020001, 0x10620011, 0x28620002, 0x50400005, -0x24020002, 0x10600007, 0x0, 0x10000017, -0x0, 0x1062000f, 0x0, 0x10000013, -0x0, 0x8c060248, 0x2021, 0xc005134, -0x24050004, 0x10000007, 0x0, 0x8c060248, -0x2021, 0xc005134, 0x24050004, 0x10000010, -0x0, 0x8c06024c, 0x2021, 0xc005134, -0x24050001, 0x1000000a, 0x0, 0x3c040001, -0x24846304, 0x3c050003, 0x34a51300, 0x2003021, -0x3821, 0xafa00010, 0xc002b17, 0xafa00014, -0x8f4202c0, 0x24420001, 0xaf4202c0, 0x10000136, -0x8f4202c0, 0xc002407, 0x0, 0x10000132, -0x0, 0x24020001, 0xa34205c5, 0x24100100, -0x8f4401a8, 0x8f4501ac, 0xafb00010, 0xafa00014, -0x8f420014, 0xafa20018, 0x8f420108, 0x26e60028, -0x40f809, 0x24070400, 0x1040fff5, 0x0, -0x10000121, 0x0, 0x3c02ffff, 0x34427fff, -0x2c2b024, 0x1821, 0x3c020900, 0xaf400058, -0xaf40005c, 0xaf400060, 0xaf400064, 0xaf400360, -0xafa20020, 0x8f5e0018, 0x27aa0020, 0x240200ff, -0x13c20002, 0xafaa003c, 0x27c30001, 0x8c020228, -0x609021, 0x1642000e, 0x1e38c0, 0x8f42033c, -0x24420001, 0xaf42033c, 0x8f42033c, 0x8c020228, -0x3c040001, 0x2484629c, 0x3c050009, 0xafa00014, -0xafa20010, 0x8fa60020, 0x1000006b, 0x34a50500, -0xf71021, 0x8fa30020, 0x8fa40024, 0xac4304c0, -0xac4404c4, 0x8f830054, 0x8f820054, 0x247003e8, -0x2021023, 0x2c4203e9, 0x1040001b, 0x9821, -0xe08821, 0x263504c0, 0x8f440178, 0x8f45017c, -0x2201821, 0x240a0004, 0xafaa0010, 0xafb20014, -0x8f48000c, 0x1021, 0x2f53021, 0xafa80018, -0x8f48010c, 0x24070008, 0xa32821, 0xa3482b, -0x822021, 0x100f809, 0x892021, 0x54400006, -0x24130001, 0x8f820054, 0x2021023, 0x2c4203e9, -0x1440ffe9, 0x0, 0x326200ff, 0x54400017, -0xaf520018, 0x8f420378, 0x24420001, 0xaf420378, -0x8f420378, 0x8f820120, 0x8faa003c, 0xafa20010, -0x8f820124, 0x3c040001, 0x248462a8, 0x3c050009, -0xafa20014, 0x8d460000, 0x10000033, 0x34a50600, -0x8f420308, 0x24130001, 0x24420001, 0xaf420308, -0x8f420308, 0x1000001c, 0x326200ff, 0x8f830054, -0x8f820054, 0x247003e8, 0x2021023, 0x2c4203e9, -0x10400014, 0x9821, 0x24110010, 0x8f42000c, -0x8f440160, 0x8f450164, 0x8f860120, 0xafb10010, -0xafb20014, 0xafa20018, 0x8f42010c, 0x24070008, -0x40f809, 0x24c6001c, 0x1440ffe5, 0x0, -0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffef, -0x0, 0x326200ff, 0x14400011, 0x0, +0x431025, 0xac820038, 0x8f840054, 0x41442, +0x41c82, 0x431021, 0x41cc2, 0x431023, +0x41d02, 0x431021, 0x41d42, 0x431023, +0x10000009, 0xaf420208, 0x3c040001, 0x24846250, +0x34a51000, 0x2003021, 0x3821, 0xafa00010, +0xc002b3b, 0xafa00014, 0x8f4202a0, 0x24420001, +0xaf4202a0, 0x1000021f, 0x8f4202a0, 0x27b00028, +0x2002021, 0x24050210, 0xc002bbf, 0x24060008, +0xc002518, 0x2002021, 0x10000216, 0x0, +0x8faa0034, 0x27a40028, 0xa1880, 0x25420001, +0x3042003f, 0xafa20034, 0x8c650300, 0x8faa0034, +0x21080, 0x8c430300, 0x25420001, 0x3042003f, +0xafa20034, 0xac02022c, 0xafa50028, 0xc002518, +0xafa3002c, 0x10000203, 0x0, 0x27b00028, +0x2002021, 0x24050210, 0xc002bbf, 0x24060008, +0xc002657, 0x2002021, 0x100001fa, 0x0, +0x8faa0034, 0x27a40028, 0xa1880, 0x25420001, +0x3042003f, 0xafa20034, 0x8c650300, 0x8faa0034, +0x21080, 0x8c430300, 0x25420001, 0x3042003f, +0xafa20034, 0xac02022c, 0xafa50028, 0xc002657, +0xafa3002c, 0x100001e7, 0x0, 0x101302, +0x30430fff, 0x24020001, 0x10620005, 0x24020002, +0x1062001e, 0x3c020002, 0x10000033, 0x3c050003, +0x3c030002, 0x2c31024, 0x54400037, 0x2c3b025, +0x8f820228, 0x3c010001, 0x370821, 0xac2238d8, +0x8f82022c, 0x3c010001, 0x370821, 0xac2238dc, +0x8f820230, 0x3c010001, 0x370821, 0xac2238e0, +0x8f820234, 0x3c010001, 0x370821, 0xac2238e4, +0x2402ffff, 0xaf820228, 0xaf82022c, 0xaf820230, +0xaf820234, 0x10000020, 0x2c3b025, 0x2c21024, +0x10400012, 0x3c02fffd, 0x3c020001, 0x571021, +0x8c4238d8, 0xaf820228, 0x3c020001, 0x571021, +0x8c4238dc, 0xaf82022c, 0x3c020001, 0x571021, +0x8c4238e0, 0xaf820230, 0x3c020001, 0x571021, +0x8c4238e4, 0xaf820234, 0x3c02fffd, 0x3442ffff, +0x10000009, 0x2c2b024, 0x3c040001, 0x2484625c, +0x34a51100, 0x2003021, 0x3821, 0xafa00010, +0xc002b3b, 0xafa00014, 0x8f4202cc, 0x24420001, +0xaf4202cc, 0x1000019f, 0x8f4202cc, 0x101302, +0x30450fff, 0x24020001, 0x10a20005, 0x24020002, +0x10a2000d, 0x3c0408ff, 0x10000014, 0x3c050003, +0x3c0208ff, 0x3442ffff, 0x8f830220, 0x3c040004, +0x2c4b025, 0x621824, 0x34630008, 0xaf830220, +0x10000012, 0xaf450298, 0x3484fff7, 0x3c03fffb, +0x8f820220, 0x3463ffff, 0x2c3b024, 0x441024, +0xaf820220, 0x10000009, 0xaf450298, 0x3c040001, +0x24846268, 0x34a51200, 0x2003021, 0x3821, +0xafa00010, 0xc002b3b, 0xafa00014, 0x8f4202bc, +0x24420001, 0xaf4202bc, 0x10000176, 0x8f4202bc, +0x27840208, 0x24050200, 0xc002bbf, 0x24060008, +0x27440224, 0x24050200, 0xc002bbf, 0x24060008, +0x8f4202c4, 0x24420001, 0xaf4202c4, 0x10000169, +0x8f4202c4, 0x101302, 0x30430fff, 0x24020001, +0x10620011, 0x28620002, 0x50400005, 0x24020002, +0x10600007, 0x0, 0x10000017, 0x0, +0x1062000f, 0x0, 0x10000013, 0x0, +0x8c060248, 0x2021, 0xc005104, 0x24050004, +0x10000007, 0x0, 0x8c060248, 0x2021, +0xc005104, 0x24050004, 0x10000010, 0x0, +0x8c06024c, 0x2021, 0xc005104, 0x24050001, +0x1000000a, 0x0, 0x3c040001, 0x24846274, +0x3c050003, 0x34a51300, 0x2003021, 0x3821, +0xafa00010, 0xc002b3b, 0xafa00014, 0x8f4202c0, +0x24420001, 0xaf4202c0, 0x1000013a, 0x8f4202c0, +0xc002426, 0x0, 0x10000136, 0x0, +0x24020001, 0xa34205c5, 0x24100100, 0x8f4401a8, +0x8f4501ac, 0xafb00010, 0xafa00014, 0x8f420014, +0xafa20018, 0x8f420108, 0x26e60028, 0x40f809, +0x24070400, 0x1040fff5, 0x0, 0x10000125, +0x0, 0x3c03ffff, 0x34637fff, 0x8f420368, +0x8f440360, 0x2c3b024, 0x1821, 0xaf400058, +0xaf40005c, 0xaf400060, 0xaf400064, 0x441023, +0xaf420368, 0x3c020900, 0xaf400360, 0xafa20020, +0x8f5e0018, 0x27aa0020, 0x240200ff, 0x13c20002, +0xafaa003c, 0x27c30001, 0x8c020228, 0x609021, +0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001, +0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001, +0x2484620c, 0x3c050009, 0xafa00014, 0xafa20010, +0x8fa60020, 0x1000006b, 0x34a50500, 0xf71021, +0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, +0x8f830054, 0x8f820054, 0x247003e8, 0x2021023, +0x2c4203e9, 0x1040001b, 0x9821, 0xe08821, +0x263504c0, 0x8f440178, 0x8f45017c, 0x2201821, +0x240a0004, 0xafaa0010, 0xafb20014, 0x8f48000c, +0x1021, 0x2f53021, 0xafa80018, 0x8f48010c, +0x24070008, 0xa32821, 0xa3482b, 0x822021, +0x100f809, 0x892021, 0x54400006, 0x24130001, +0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffe9, +0x0, 0x326200ff, 0x54400017, 0xaf520018, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8faa003c, 0xafa20010, 0x8f820124, -0x3c040001, 0x248462b0, 0x3c050009, 0xafa20014, -0x8d460000, 0x34a50700, 0xc002b17, 0x3c03821, -0x8f4202b0, 0x24420001, 0xaf4202b0, 0x8f4202b0, -0x8f4202f8, 0x24420001, 0xaf4202f8, 0x1000008a, -0x8f4202f8, 0x8c02025c, 0x27440224, 0xaf4201f0, -0x8c020260, 0x24050200, 0x24060008, 0xc002b9b, -0xaf4201f8, 0x8f820220, 0x30420008, 0x14400002, -0x24020001, 0x24020002, 0xaf420298, 0x8f4202ac, -0x24420001, 0xaf4202ac, 0x10000077, 0x8f4202ac, -0x3c0200ff, 0x3442ffff, 0x2021824, 0x32c20180, -0x14400006, 0x3402fffb, 0x43102b, 0x14400003, -0x0, 0x1000006c, 0xaf4300bc, 0x3c040001, -0x24846310, 0x3c050003, 0x34a51500, 0x2003021, -0x3821, 0xafa00010, 0xc002b17, 0xafa00014, -0x3c020700, 0x34421000, 0x101e02, 0x621825, -0xafa30020, 0x8f510018, 0x240200ff, 0x12220002, -0x8021, 0x26300001, 0x8c020228, 0x1602000e, -0x1130c0, 0x8f42033c, 0x24420001, 0xaf42033c, -0x8f42033c, 0x8c020228, 0x3c040001, 0x24846284, -0x3c050009, 0xafa00014, 0xafa20010, 0x8fa60020, -0x1000003f, 0x34a50100, 0xd71021, 0x8fa30020, -0x8fa40024, 0xac4304c0, 0xac4404c4, 0xc01821, -0x8f440178, 0x8f45017c, 0x1021, 0x24070004, -0xafa70010, 0xafb00014, 0x8f48000c, 0x24c604c0, -0x2e63021, 0xafa80018, 0x8f48010c, 0x24070008, -0xa32821, 0xa3482b, 0x822021, 0x100f809, -0x892021, 0x1440000b, 0x24070008, 0x8f820120, -0xafa20010, 0x8f820124, 0x3c040001, 0x2484628c, -0x3c050009, 0xafa20014, 0x8fa60020, 0x1000001c, -0x34a50200, 0x8f440160, 0x8f450164, 0x8f43000c, -0xaf500018, 0x8f860120, 0x24020010, 0xafa20010, -0xafb00014, 0xafa30018, 0x8f42010c, 0x40f809, -0x24c6001c, 0x14400010, 0x0, 0x8f420340, -0x24420001, 0xaf420340, 0x8f420340, 0x8f820120, -0xafa20010, 0x8f820124, 0x3c040001, 0x24846294, -0x3c050009, 0xafa20014, 0x8fa60020, 0x34a50300, -0xc002b17, 0x2203821, 0x8f4202e0, 0x24420001, -0xaf4202e0, 0x8f4202e0, 0x8f4202f0, 0x24420001, -0xaf4202f0, 0x8f4202f0, 0x8fa20034, 0x8fbf0058, -0x8fbe0054, 0x8fb50050, 0x8fb3004c, 0x8fb20048, -0x8fb10044, 0x8fb00040, 0x3e00008, 0x27bd0060, -0x27bdfff8, 0x2408ffff, 0x10a00014, 0x4821, -0x3c0aedb8, 0x354a8320, 0x90870000, 0x24840001, -0x3021, 0x1071026, 0x30420001, 0x10400002, -0x81842, 0x6a1826, 0x604021, 0x24c60001, -0x2cc20008, 0x1440fff7, 0x73842, 0x25290001, -0x125102b, 0x1440fff0, 0x0, 0x1001021, -0x3e00008, 0x27bd0008, 0x27bdffb8, 0xafbf0040, -0xafbe003c, 0xafb50038, 0xafb30034, 0xafb20030, -0xafb1002c, 0xafb00028, 0x8f870220, 0xafa7001c, -0x8f870200, 0xafa70024, 0x8f820220, 0x3c0308ff, -0x3463ffff, 0x431024, 0x34420004, 0xaf820220, -0x8f820200, 0x3c03c0ff, 0x3463ffff, 0x431024, -0x34420004, 0xaf820200, 0x8f53035c, 0x8f550360, -0x8f5e0364, 0x8f470368, 0xafa70014, 0x8f4202d0, -0x274401c0, 0x24420001, 0xaf4202d0, 0x8f5002d0, -0x8f510204, 0x8f520200, 0xc002b84, 0x24050400, -0xaf53035c, 0xaf550360, 0xaf5e0364, 0x8fa70014, -0xaf470368, 0xaf5002d0, 0xaf510204, 0xaf520200, +0x3c040001, 0x24846218, 0x3c050009, 0xafa20014, +0x8d460000, 0x10000033, 0x34a50600, 0x8f420308, +0x24130001, 0x24420001, 0xaf420308, 0x8f420308, +0x1000001c, 0x326200ff, 0x8f830054, 0x8f820054, +0x247003e8, 0x2021023, 0x2c4203e9, 0x10400014, +0x9821, 0x24110010, 0x8f42000c, 0x8f440160, +0x8f450164, 0x8f860120, 0xafb10010, 0xafb20014, +0xafa20018, 0x8f42010c, 0x24070008, 0x40f809, +0x24c6001c, 0x1440ffe5, 0x0, 0x8f820054, +0x2021023, 0x2c4203e9, 0x1440ffef, 0x0, +0x326200ff, 0x14400011, 0x0, 0x8f420378, +0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, +0x8faa003c, 0xafa20010, 0x8f820124, 0x3c040001, +0x24846220, 0x3c050009, 0xafa20014, 0x8d460000, +0x34a50700, 0xc002b3b, 0x3c03821, 0x8f4202b0, +0x24420001, 0xaf4202b0, 0x8f4202b0, 0x8f4202f8, +0x24420001, 0xaf4202f8, 0x1000008a, 0x8f4202f8, 0x8c02025c, 0x27440224, 0xaf4201f0, 0x8c020260, -0x24050200, 0x24060008, 0xaf4201f8, 0x24020006, -0xc002b9b, 0xaf4201f4, 0x3c023b9a, 0x3442ca00, -0xaf4201fc, 0x240203e8, 0x24040002, 0x24030001, -0xaf420294, 0xaf440290, 0xaf43029c, 0x8f820220, -0x30420008, 0x10400004, 0x0, 0xaf430298, -0x10000003, 0x3021, 0xaf440298, 0x3021, -0x3c030001, 0x661821, 0x90636d80, 0x3461021, -0x24c60001, 0xa043022c, 0x2cc2000f, 0x1440fff8, -0x3461821, 0x24c60001, 0x8f820040, 0x24040080, -0x24050080, 0x21702, 0x24420030, 0xa062022c, -0x3461021, 0xc002b84, 0xa040022c, 0x8fa7001c, -0x30e20004, 0x14400006, 0x0, 0x8f820220, -0x3c0308ff, 0x3463fffb, 0x431024, 0xaf820220, -0x8fa70024, 0x30e20004, 0x14400006, 0x0, -0x8f820200, 0x3c03c0ff, 0x3463fffb, 0x431024, -0xaf820200, 0x8fbf0040, 0x8fbe003c, 0x8fb50038, -0x8fb30034, 0x8fb20030, 0x8fb1002c, 0x8fb00028, -0x3e00008, 0x27bd0048, 0x0, 0xaf400104, +0x24050200, 0x24060008, 0xc002bbf, 0xaf4201f8, +0x8f820220, 0x30420008, 0x14400002, 0x24020001, +0x24020002, 0xaf420298, 0x8f4202ac, 0x24420001, +0xaf4202ac, 0x10000077, 0x8f4202ac, 0x3c0200ff, +0x3442ffff, 0x2021824, 0x32c20180, 0x14400006, +0x3402fffb, 0x43102b, 0x14400003, 0x0, +0x1000006c, 0xaf4300bc, 0x3c040001, 0x24846280, +0x3c050003, 0x34a51500, 0x2003021, 0x3821, +0xafa00010, 0xc002b3b, 0xafa00014, 0x3c020700, +0x34421000, 0x101e02, 0x621825, 0xafa30020, +0x8f510018, 0x240200ff, 0x12220002, 0x8021, +0x26300001, 0x8c020228, 0x1602000e, 0x1130c0, +0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, +0x8c020228, 0x3c040001, 0x248461f4, 0x3c050009, +0xafa00014, 0xafa20010, 0x8fa60020, 0x1000003f, +0x34a50100, 0xd71021, 0x8fa30020, 0x8fa40024, +0xac4304c0, 0xac4404c4, 0xc01821, 0x8f440178, +0x8f45017c, 0x1021, 0x24070004, 0xafa70010, +0xafb00014, 0x8f48000c, 0x24c604c0, 0x2e63021, +0xafa80018, 0x8f48010c, 0x24070008, 0xa32821, +0xa3482b, 0x822021, 0x100f809, 0x892021, +0x1440000b, 0x24070008, 0x8f820120, 0xafa20010, +0x8f820124, 0x3c040001, 0x248461fc, 0x3c050009, +0xafa20014, 0x8fa60020, 0x1000001c, 0x34a50200, +0x8f440160, 0x8f450164, 0x8f43000c, 0xaf500018, +0x8f860120, 0x24020010, 0xafa20010, 0xafb00014, +0xafa30018, 0x8f42010c, 0x40f809, 0x24c6001c, +0x14400010, 0x0, 0x8f420340, 0x24420001, +0xaf420340, 0x8f420340, 0x8f820120, 0xafa20010, +0x8f820124, 0x3c040001, 0x24846204, 0x3c050009, +0xafa20014, 0x8fa60020, 0x34a50300, 0xc002b3b, +0x2203821, 0x8f4202e0, 0x24420001, 0xaf4202e0, +0x8f4202e0, 0x8f4202f0, 0x24420001, 0xaf4202f0, +0x8f4202f0, 0x8fa20034, 0x8fbf0058, 0x8fbe0054, +0x8fb50050, 0x8fb3004c, 0x8fb20048, 0x8fb10044, +0x8fb00040, 0x3e00008, 0x27bd0060, 0x27bdfff8, +0x2408ffff, 0x10a00014, 0x4821, 0x3c0aedb8, +0x354a8320, 0x90870000, 0x24840001, 0x3021, +0x1071026, 0x30420001, 0x10400002, 0x81842, +0x6a1826, 0x604021, 0x24c60001, 0x2cc20008, +0x1440fff7, 0x73842, 0x25290001, 0x125102b, +0x1440fff0, 0x0, 0x1001021, 0x3e00008, +0x27bd0008, 0x27bdffb0, 0xafbf0048, 0xafbe0044, +0xafb50040, 0xafb3003c, 0xafb20038, 0xafb10034, +0xafb00030, 0x8f870220, 0xafa70024, 0x8f870200, +0xafa7002c, 0x8f820220, 0x3c0308ff, 0x3463ffff, +0x431024, 0x34420004, 0xaf820220, 0x8f820200, +0x3c03c0ff, 0x3463ffff, 0x431024, 0x34420004, +0xaf820200, 0x8f530358, 0x8f55035c, 0x8f5e0360, +0x8f470364, 0xafa70014, 0x8f470368, 0xafa7001c, +0x8f4202d0, 0x274401c0, 0x24420001, 0xaf4202d0, +0x8f5002d0, 0x8f510204, 0x8f520200, 0xc002ba8, +0x24050400, 0xaf530358, 0xaf55035c, 0xaf5e0360, +0x8fa70014, 0xaf470364, 0x8fa7001c, 0xaf470368, +0xaf5002d0, 0xaf510204, 0xaf520200, 0x8c02025c, +0x27440224, 0xaf4201f0, 0x8c020260, 0x24050200, +0x24060008, 0xaf4201f8, 0x24020006, 0xc002bbf, +0xaf4201f4, 0x3c023b9a, 0x3442ca00, 0xaf4201fc, +0x240203e8, 0x24040002, 0x24030001, 0xaf420294, +0xaf440290, 0xaf43029c, 0x8f820220, 0x30420008, +0x10400004, 0x0, 0xaf430298, 0x10000003, +0x3021, 0xaf440298, 0x3021, 0x3c030001, +0x661821, 0x90636d00, 0x3461021, 0x24c60001, +0xa043022c, 0x2cc2000f, 0x1440fff8, 0x3461821, +0x24c60001, 0x8f820040, 0x24040080, 0x24050080, +0x21702, 0x24420030, 0xa062022c, 0x3461021, +0xc002ba8, 0xa040022c, 0x8fa70024, 0x30e20004, +0x14400006, 0x0, 0x8f820220, 0x3c0308ff, +0x3463fffb, 0x431024, 0xaf820220, 0x8fa7002c, +0x30e20004, 0x14400006, 0x0, 0x8f820200, +0x3c03c0ff, 0x3463fffb, 0x431024, 0xaf820200, +0x8fbf0048, 0x8fbe0044, 0x8fb50040, 0x8fb3003c, +0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008, +0x27bd0050, 0x0, 0x0, 0xaf400104, 0x24040001, 0x410c0, 0x2e21821, 0x24820001, 0x3c010001, 0x230821, 0xa42234d0, 0x402021, 0x2c820080, 0x1440fff8, 0x410c0, 0x24020001, @@ -5946,7 +5950,7 @@ 0x2c450001, 0xa01021, 0x14400009, 0x24840008, 0x86102b, 0x1440fff0, 0x1021, 0x304200ff, 0x14400030, 0x24020001, 0x1000002e, 0x1021, -0x1000fffa, 0x24020001, 0x2002021, 0xc0023ed, +0x1000fffa, 0x24020001, 0x2002021, 0xc00240c, 0x24050006, 0x3042007f, 0x218c0, 0x2e31021, 0x3c010001, 0x220821, 0x942230d0, 0x1040fff2, 0x2e31021, 0x3c060001, 0xc23021, 0x94c630d0, @@ -5961,7 +5965,7 @@ 0x27bd0018, 0x3e00008, 0x0, 0x27bdffb0, 0x801021, 0xafb00030, 0x24500002, 0x2002021, 0x24050006, 0xafb10034, 0x408821, 0xafbf0048, -0xafbe0044, 0xafb50040, 0xafb3003c, 0xc0023ed, +0xafbe0044, 0xafb50040, 0xafb3003c, 0xc00240c, 0xafb20038, 0x3047007f, 0x710c0, 0x2e21021, 0x3c050001, 0xa22821, 0x94a530d0, 0x50a0001c, 0xa03021, 0x3c090001, 0x352934d2, 0x96280002, @@ -5974,15 +5978,15 @@ 0x10c00014, 0x610c0, 0x571821, 0x3c010001, 0x230821, 0x8c2334d0, 0x571021, 0xafa30010, 0x3c010001, 0x220821, 0x8c2234d4, 0x3c040001, -0x24846424, 0xafa20014, 0x8e260000, 0x8e270004, -0x3c050004, 0xc002b17, 0x34a50400, 0x10000063, +0x24846394, 0xafa20014, 0x8e260000, 0x8e270004, +0x3c050004, 0xc002b3b, 0x34a50400, 0x10000063, 0x3c020800, 0x8f450100, 0x10a00006, 0x510c0, 0x2e21021, 0x3c010001, 0x220821, 0x942234d0, 0xaf420100, 0xa03021, 0x14c00011, 0x628c0, 0x710c0, 0x2e21021, 0xafa70010, 0x3c010001, -0x220821, 0x942230d0, 0x3c040001, 0x24846430, +0x220821, 0x942230d0, 0x3c040001, 0x248463a0, 0xafa20014, 0x8e260000, 0x8e270004, 0x3c050004, -0xc002b17, 0x34a50500, 0x10000048, 0x3c020800, +0xc002b3b, 0x34a50500, 0x10000048, 0x3c020800, 0xb71821, 0x3c020001, 0x96040000, 0x344234d2, 0x621821, 0xa4640000, 0x8e020002, 0x720c0, 0xac620002, 0x2e41021, 0x3c030001, 0x621821, @@ -6005,7 +6009,7 @@ 0x240200ff, 0x13c20002, 0xafaa002c, 0x27c30001, 0x8c020228, 0x609021, 0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, -0x8c020228, 0x3c040001, 0x248463ec, 0x3c050009, +0x8c020228, 0x3c040001, 0x2484635c, 0x3c050009, 0xafa00014, 0xafa20010, 0x8fa60020, 0x1000006b, 0x34a50500, 0xf71021, 0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054, @@ -6019,7 +6023,7 @@ 0x2c4203e9, 0x1440ffe9, 0x0, 0x326200ff, 0x54400017, 0xaf520018, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, -0xafa20010, 0x8f820124, 0x3c040001, 0x248463f8, +0xafa20010, 0x8f820124, 0x3c040001, 0x24846368, 0x3c050009, 0xafa20014, 0x8d460000, 0x10000033, 0x34a50600, 0x8f420308, 0x24130001, 0x24420001, 0xaf420308, 0x8f420308, 0x1000001c, 0x326200ff, @@ -6032,8 +6036,8 @@ 0x1440ffef, 0x0, 0x326200ff, 0x14400011, 0x0, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010, -0x8f820124, 0x3c040001, 0x24846400, 0x3c050009, -0xafa20014, 0x8d460000, 0x34a50700, 0xc002b17, +0x8f820124, 0x3c040001, 0x24846370, 0x3c050009, +0xafa20014, 0x8d460000, 0x34a50700, 0xc002b3b, 0x3c03821, 0x8f4202b4, 0x24420001, 0xaf4202b4, 0x8f4202b4, 0x8f4202f4, 0x24420001, 0xaf4202f4, 0x8f4202f4, 0x8fbf0048, 0x8fbe0044, 0x8fb50040, @@ -6041,7 +6045,7 @@ 0x3e00008, 0x27bd0050, 0x27bdffa0, 0x801021, 0xafb00040, 0x24500002, 0x2002021, 0x24050006, 0xafb10044, 0x408821, 0xafbf0058, 0xafbe0054, -0xafb50050, 0xafb3004c, 0xc0023ed, 0xafb20048, +0xafb50050, 0xafb3004c, 0xc00240c, 0xafb20048, 0x3048007f, 0x810c0, 0x2e21021, 0x3c060001, 0xc23021, 0x94c630d0, 0x10c0001c, 0x3821, 0x3c0a0001, 0x354a34d2, 0x96290002, 0x610c0, @@ -6053,8 +6057,8 @@ 0x94c634d0, 0x14c0ffea, 0x610c0, 0x14c00011, 0xafa70028, 0x810c0, 0x2e21021, 0xafa80010, 0x3c010001, 0x220821, 0x942230d0, 0x3c040001, -0x2484643c, 0xafa20014, 0x8e260000, 0x8e270004, -0x3c050004, 0xc002b17, 0x34a50900, 0x10000075, +0x248463ac, 0xafa20014, 0x8e260000, 0x8e270004, +0x3c050004, 0xc002b3b, 0x34a50900, 0x10000075, 0x3c020800, 0x10e0000c, 0x610c0, 0x2e21021, 0x3c030001, 0x621821, 0x946334d0, 0x710c0, 0x2e21021, 0x3c010001, 0x220821, 0xa42334d0, @@ -6089,7 +6093,7 @@ 0xafab0034, 0x27c30001, 0x8c020228, 0x609021, 0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001, -0x248463ec, 0x3c050009, 0xafa00014, 0xafa20010, +0x2484635c, 0x3c050009, 0xafa00014, 0xafa20010, 0x8fa60020, 0x1000006b, 0x34a50500, 0xf71021, 0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054, 0x247003e8, 0x2021023, @@ -6103,7 +6107,7 @@ 0x0, 0x326200ff, 0x54400017, 0xaf520018, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8fab0034, 0xafa20010, 0x8f820124, -0x3c040001, 0x248463f8, 0x3c050009, 0xafa20014, +0x3c040001, 0x24846368, 0x3c050009, 0xafa20014, 0x8d660000, 0x10000033, 0x34a50600, 0x8f420308, 0x24130001, 0x24420001, 0xaf420308, 0x8f420308, 0x1000001c, 0x326200ff, 0x8f830054, 0x8f820054, @@ -6116,14 +6120,14 @@ 0x326200ff, 0x14400011, 0x0, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8fab0034, 0xafa20010, 0x8f820124, 0x3c040001, -0x24846400, 0x3c050009, 0xafa20014, 0x8d660000, -0x34a50700, 0xc002b17, 0x3c03821, 0x8f4202b8, +0x24846370, 0x3c050009, 0xafa20014, 0x8d660000, +0x34a50700, 0xc002b3b, 0x3c03821, 0x8f4202b8, 0x24420001, 0xaf4202b8, 0x8f4202b8, 0x8f4202f4, 0x24420001, 0xaf4202f4, 0x8f4202f4, 0x8fbf0058, 0x8fbe0054, 0x8fb50050, 0x8fb3004c, 0x8fb20048, 0x8fb10044, 0x8fb00040, 0x3e00008, 0x27bd0060, 0x0, 0x0, 0x0, 0x27bdffe0, -0x27644000, 0xafbf0018, 0xc002b84, 0x24051000, +0x27644000, 0xafbf0018, 0xc002ba8, 0x24051000, 0x3c030001, 0x34632cc0, 0x3c040001, 0x34842ec8, 0x24020020, 0xaf82011c, 0x2e31021, 0xaf800100, 0xaf800104, 0xaf800108, 0xaf800110, 0xaf800114, @@ -6132,15 +6136,15 @@ 0x2e31021, 0xaf4200f0, 0x2e41021, 0xaf4200f4, 0x2e41021, 0xaf4200f8, 0x3c020001, 0x571021, 0x904240f4, 0x1440001c, 0x3c050001, 0x8f82011c, -0x3c040001, 0x24846500, 0x3c050001, 0x34420001, +0x3c040001, 0x24846470, 0x3c050001, 0x34420001, 0xaf82011c, 0xafa00010, 0xafa00014, 0x8f86011c, -0x34a50100, 0xc002b17, 0x3821, 0x8c020218, +0x34a50100, 0xc002b3b, 0x3821, 0x8c020218, 0x30420040, 0x10400014, 0x0, 0x8f82011c, -0x3c040001, 0x2484650c, 0x3c050001, 0x34420004, +0x3c040001, 0x2484647c, 0x3c050001, 0x34420004, 0xaf82011c, 0xafa00010, 0xafa00014, 0x8f86011c, -0x10000007, 0x34a50200, 0x3c040001, 0x24846514, +0x10000007, 0x34a50200, 0x3c040001, 0x24846484, 0xafa00010, 0xafa00014, 0x8f86011c, 0x34a50300, -0xc002b17, 0x3821, 0x8fbf0018, 0x3e00008, +0xc002b3b, 0x3821, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x8fa90010, 0x8f83012c, 0x8faa0014, 0x8fab0018, 0x1060000a, 0x27624fe0, 0x14620002, 0x24680020, 0x27684800, 0x8f820128, 0x11020004, @@ -6181,55 +6185,55 @@ 0x2e21021, 0x402021, 0x24020001, 0xaf4400ec, 0xac890000, 0xac820004, 0x24020001, 0x3e00008, 0x0, 0x3e00008, 0x0, 0x27bdffd8, -0x3c040001, 0x2484651c, 0x3c050001, 0xafbf0024, +0x3c040001, 0x2484648c, 0x3c050001, 0xafbf0024, 0xafb20020, 0xafb1001c, 0xafb00018, 0x8f900104, 0x8f9100b0, 0x8f92011c, 0x34a52500, 0x8f820100, -0x2403021, 0x2203821, 0xafa20010, 0xc002b17, +0x2403021, 0x2203821, 0xafa20010, 0xc002b3b, 0xafb00014, 0x8e020008, 0xafa20010, 0x8e02000c, -0x3c040001, 0x24846528, 0xafa20014, 0x8e060000, -0x8e070004, 0x3c050001, 0xc002b17, 0x34a52510, +0x3c040001, 0x24846498, 0xafa20014, 0x8e060000, +0x8e070004, 0x3c050001, 0xc002b3b, 0x34a52510, 0x8e020018, 0xafa20010, 0x8e02001c, 0x3c040001, -0x24846534, 0xafa20014, 0x8e060010, 0x8e070014, -0x3c050001, 0xc002b17, 0x34a52520, 0x3c027f00, +0x248464a4, 0xafa20014, 0x8e060010, 0x8e070014, +0x3c050001, 0xc002b3b, 0x34a52520, 0x3c027f00, 0x2221024, 0x3c030800, 0x54430016, 0x3c030200, 0x8f82009c, 0x3042ffff, 0x14400012, 0x3c030200, -0x3c040001, 0x24846540, 0x3c050002, 0x34a5f030, +0x3c040001, 0x248464b0, 0x3c050002, 0x34a5f030, 0x3021, 0x3821, 0x36420002, 0xaf82011c, 0x36220001, 0xaf8200b0, 0xaf900104, 0xaf92011c, -0xafa00010, 0xc002b17, 0xafa00014, 0x10000024, +0xafa00010, 0xc002b3b, 0xafa00014, 0x10000024, 0x0, 0x2c31024, 0x1040000d, 0x2231024, 0x1040000b, 0x36420002, 0xaf82011c, 0x36220001, 0xaf8200b0, 0xaf900104, 0xaf92011c, 0x8f420330, 0x24420001, 0xaf420330, 0x10000015, 0x8f420330, -0x3c040001, 0x24846548, 0x240202a9, 0xafa20010, -0xafa00014, 0x8f860144, 0x3c070001, 0x24e76550, -0xc002b17, 0x3405dead, 0x8f82011c, 0x34420002, +0x3c040001, 0x248464b8, 0x240202a9, 0xafa20010, +0xafa00014, 0x8f860144, 0x3c070001, 0x24e764c0, +0xc002b3b, 0x3405dead, 0x8f82011c, 0x34420002, 0xaf82011c, 0x8f820220, 0x34420004, 0xaf820220, 0x8f820140, 0x3c030001, 0x431025, 0xaf820140, 0x8fbf0024, 0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0028, 0x27bdffd8, 0x3c040001, -0x24846578, 0x3c050001, 0xafbf0024, 0xafb20020, +0x248464e8, 0x3c050001, 0xafbf0024, 0xafb20020, 0xafb1001c, 0xafb00018, 0x8f900124, 0x8f9100a0, 0x8f92011c, 0x34a52600, 0x8f820120, 0x2403021, -0x2203821, 0xafa20010, 0xc002b17, 0xafb00014, +0x2203821, 0xafa20010, 0xc002b3b, 0xafb00014, 0x8e020008, 0xafa20010, 0x8e02000c, 0x3c040001, -0x24846584, 0xafa20014, 0x8e060000, 0x8e070004, -0x3c050001, 0xc002b17, 0x34a52610, 0x8e020018, -0xafa20010, 0x8e02001c, 0x3c040001, 0x24846590, +0x248464f4, 0xafa20014, 0x8e060000, 0x8e070004, +0x3c050001, 0xc002b3b, 0x34a52610, 0x8e020018, +0xafa20010, 0x8e02001c, 0x3c040001, 0x24846500, 0xafa20014, 0x8e060010, 0x8e070014, 0x3c050001, -0xc002b17, 0x34a52620, 0x3c027f00, 0x2221024, +0xc002b3b, 0x34a52620, 0x3c027f00, 0x2221024, 0x3c030800, 0x54430016, 0x3c030200, 0x8f8200ac, 0x3042ffff, 0x14400012, 0x3c030200, 0x3c040001, -0x2484659c, 0x3c050001, 0x34a5f030, 0x3021, +0x2484650c, 0x3c050001, 0x34a5f030, 0x3021, 0x3821, 0x36420002, 0xaf82011c, 0x36220001, 0xaf8200a0, 0xaf900124, 0xaf92011c, 0xafa00010, -0xc002b17, 0xafa00014, 0x10000024, 0x0, +0xc002b3b, 0xafa00014, 0x10000024, 0x0, 0x2c31024, 0x1040000d, 0x2231024, 0x1040000b, 0x36420002, 0xaf82011c, 0x36220001, 0xaf8200a0, 0xaf900124, 0xaf92011c, 0x8f42032c, 0x24420001, 0xaf42032c, 0x10000015, 0x8f42032c, 0x3c040001, -0x24846548, 0x240202e2, 0xafa20010, 0xafa00014, -0x8f860144, 0x3c070001, 0x24e76550, 0xc002b17, +0x248464b8, 0x240202e2, 0xafa20010, 0xafa00014, +0x8f860144, 0x3c070001, 0x24e764c0, 0xc002b3b, 0x3405dead, 0x8f82011c, 0x34420002, 0xaf82011c, 0x8f820220, 0x34420004, 0xaf820220, 0x8f820140, 0x3c030001, 0x431025, 0xaf820140, 0x8fbf0024, @@ -6238,24 +6242,24 @@ 0x2821, 0x6821, 0x4821, 0x7821, 0x7021, 0x8f880124, 0x8f870104, 0x1580002e, 0x8f8b011c, 0x11a00014, 0x31620800, 0x8f820120, -0x10460029, 0x0, 0x3c040001, 0x8c846f60, +0x10460029, 0x0, 0x3c040001, 0x8c846ee4, 0x8cc20000, 0x8cc30004, 0xac820000, 0xac830004, 0x8cc20008, 0xac820008, 0x94c2000e, 0xa482000e, 0x8cc20010, 0x240c0001, 0xac820010, 0x8cc20014, 0x10000012, 0x24c60020, 0x10400017, 0x0, -0x3c040001, 0x8c846f60, 0x8d020000, 0x8d030004, +0x3c040001, 0x8c846ee4, 0x8d020000, 0x8d030004, 0xac820000, 0xac830004, 0x8d020008, 0xac820008, 0x9502000e, 0xa482000e, 0x8d020010, 0x25060020, 0xac820010, 0x8d020014, 0x240c0001, 0xc01821, 0xac820014, 0x27624fe0, 0x43102b, 0x54400001, 0x27634800, 0x603021, 0x1540002f, 0x31620100, 0x11200014, 0x31628000, 0x8f820100, 0x1045002a, -0x31620100, 0x3c040001, 0x8c846f5c, 0x8ca20000, +0x31620100, 0x3c040001, 0x8c846ee0, 0x8ca20000, 0x8ca30004, 0xac820000, 0xac830004, 0x8ca20008, 0xac820008, 0x94a2000e, 0xa482000e, 0x8ca20010, 0x240a0001, 0xac820010, 0x8ca20014, 0x10000012, 0x24a50020, 0x10400018, 0x31620100, 0x3c040001, -0x8c846f5c, 0x8ce20000, 0x8ce30004, 0xac820000, +0x8c846ee0, 0x8ce20000, 0x8ce30004, 0xac820000, 0xac830004, 0x8ce20008, 0xac820008, 0x94e2000e, 0xa482000e, 0x8ce20010, 0x24e50020, 0xac820010, 0x8ce20014, 0x240a0001, 0xa01821, 0xac820014, @@ -6264,7 +6268,7 @@ 0x11a00009, 0x31a20800, 0x10400004, 0x25020020, 0x8f8200a8, 0xa5e20000, 0x25020020, 0xaf820124, 0x8f880124, 0x6821, 0x11800011, 0x31621000, -0x3c040001, 0x8c846f60, 0x8c820000, 0x8c830004, +0x3c040001, 0x8c846ee4, 0x8c820000, 0x8c830004, 0xaf820080, 0xaf830084, 0x8c820008, 0xaf8200a4, 0x9482000e, 0xaf8200ac, 0x8c820010, 0x6021, 0xaf8200a0, 0x8c8d0010, 0x8c8f0014, 0x31621000, @@ -6273,7 +6277,7 @@ 0x3c020002, 0x1221024, 0x10400004, 0x24e20020, 0x8f8200b4, 0xaf8200d4, 0x24e20020, 0xaf820104, 0x8f870104, 0x4821, 0x1140ff70, 0x0, -0x3c040001, 0x8c846f5c, 0x8c820000, 0x8c830004, +0x3c040001, 0x8c846ee0, 0x8c820000, 0x8c830004, 0xaf820090, 0xaf830094, 0x8c820008, 0xaf8200b4, 0x9482000e, 0xaf82009c, 0x8c820010, 0x5021, 0xaf8200b0, 0x8c890010, 0x1000ff60, 0x8c8e0014, @@ -6282,11 +6286,11 @@ 0x7821, 0x7021, 0x8f880124, 0x8f870104, 0x3c180100, 0x1580002e, 0x8f89011c, 0x11a00014, 0x31220800, 0x8f820120, 0x10460029, 0x0, -0x3c040001, 0x8c846f60, 0x8cc20000, 0x8cc30004, +0x3c040001, 0x8c846ee4, 0x8cc20000, 0x8cc30004, 0xac820000, 0xac830004, 0x8cc20008, 0xac820008, 0x94c2000e, 0xa482000e, 0x8cc20010, 0x240c0001, 0xac820010, 0x8cc20014, 0x10000012, 0x24c60020, -0x10400017, 0x0, 0x3c040001, 0x8c846f60, +0x10400017, 0x0, 0x3c040001, 0x8c846ee4, 0x8d020000, 0x8d030004, 0xac820000, 0xac830004, 0x8d020008, 0xac820008, 0x9502000e, 0xa482000e, 0x8d020010, 0x25060020, 0xac820010, 0x8d020014, @@ -6294,11 +6298,11 @@ 0x43102b, 0x54400001, 0x27634800, 0x603021, 0x1560002f, 0x31220100, 0x11400014, 0x31228000, 0x8f820100, 0x1045002a, 0x31220100, 0x3c040001, -0x8c846f5c, 0x8ca20000, 0x8ca30004, 0xac820000, +0x8c846ee0, 0x8ca20000, 0x8ca30004, 0xac820000, 0xac830004, 0x8ca20008, 0xac820008, 0x94a2000e, 0xa482000e, 0x8ca20010, 0x240b0001, 0xac820010, 0x8ca20014, 0x10000012, 0x24a50020, 0x10400018, -0x31220100, 0x3c040001, 0x8c846f5c, 0x8ce20000, +0x31220100, 0x3c040001, 0x8c846ee0, 0x8ce20000, 0x8ce30004, 0xac820000, 0xac830004, 0x8ce20008, 0xac820008, 0x94e2000e, 0xa482000e, 0x8ce20010, 0x24e50020, 0xac820010, 0x8ce20014, 0x240b0001, @@ -6307,7 +6311,7 @@ 0x5440001d, 0x31221000, 0x11a00009, 0x31a20800, 0x10400004, 0x25020020, 0x8f8200a8, 0xa5e20000, 0x25020020, 0xaf820124, 0x8f880124, 0x6821, -0x11800011, 0x31221000, 0x3c040001, 0x8c846f60, +0x11800011, 0x31221000, 0x3c040001, 0x8c846ee4, 0x8c820000, 0x8c830004, 0xaf820080, 0xaf830084, 0x8c820008, 0xaf8200a4, 0x9482000e, 0xaf8200ac, 0x8c820010, 0x6021, 0xaf8200a0, 0x8c8d0010, @@ -6316,7 +6320,7 @@ 0x8f8200b8, 0xa5c20000, 0x3c020002, 0x1421024, 0x10400004, 0x24e20020, 0x8f8200b4, 0xaf8200d4, 0x24e20020, 0xaf820104, 0x8f870104, 0x5021, -0x11600010, 0x0, 0x3c040001, 0x8c846f5c, +0x11600010, 0x0, 0x3c040001, 0x8c846ee0, 0x8c820000, 0x8c830004, 0xaf820090, 0xaf830094, 0x8c820008, 0xaf8200b4, 0x9482000e, 0xaf82009c, 0x8c820010, 0x5821, 0xaf8200b0, 0x8c8a0010, @@ -6345,37 +6349,37 @@ 0x8f420000, 0x10400003, 0x0, 0x1000ff05, 0xaf80004c, 0x1000ff03, 0xaf800048, 0x3e00008, 0x0, 0x0, 0x0, 0x3c020001, -0x8c426da8, 0x27bdffe8, 0xafbf0014, 0x14400012, -0xafb00010, 0x3c100001, 0x26107010, 0x2002021, -0xc002b84, 0x24052000, 0x26021fe0, 0x3c010001, -0xac226f68, 0x3c010001, 0xac226f64, 0xac020250, +0x8c426d28, 0x27bdffe8, 0xafbf0014, 0x14400012, +0xafb00010, 0x3c100001, 0x26106f90, 0x2002021, +0xc002ba8, 0x24052000, 0x26021fe0, 0x3c010001, +0xac226eec, 0x3c010001, 0xac226ee8, 0xac020250, 0x24022000, 0xac100254, 0xac020258, 0x24020001, -0x3c010001, 0xac226da8, 0x8fbf0014, 0x8fb00010, -0x3e00008, 0x27bd0018, 0x3c090001, 0x8d296f68, +0x3c010001, 0xac226d28, 0x8fbf0014, 0x8fb00010, +0x3e00008, 0x27bd0018, 0x3c090001, 0x8d296eec, 0x8c820000, 0x8fa30010, 0x8fa80014, 0xad220000, 0x8c820004, 0xad250008, 0xad220004, 0x8f820054, 0xad260010, 0xad270014, 0xad230018, 0xad28001c, -0xad22000c, 0x2529ffe0, 0x3c020001, 0x24427010, +0xad22000c, 0x2529ffe0, 0x3c020001, 0x24426f90, 0x122102b, 0x10400003, 0x0, 0x3c090001, -0x8d296f64, 0x3c020001, 0x8c426d90, 0xad220000, -0x3c020001, 0x8c426d90, 0x3c010001, 0xac296f68, +0x8d296ee8, 0x3c020001, 0x8c426d10, 0xad220000, +0x3c020001, 0x8c426d10, 0x3c010001, 0xac296eec, 0xad220004, 0xac090250, 0x3e00008, 0x0, -0x27bdffd0, 0xafb00010, 0x3c100001, 0x8e106f68, -0x3c020001, 0x8c426d90, 0xafb10014, 0x808821, +0x27bdffd0, 0xafb00010, 0x3c100001, 0x8e106eec, +0x3c020001, 0x8c426d10, 0xafb10014, 0x808821, 0xafbe0024, 0x8fbe0040, 0x8fa40048, 0xafb20018, 0xa09021, 0xafbf0028, 0xafb50020, 0xafb3001c, -0xae020000, 0x3c020001, 0x8c426d90, 0xc09821, +0xae020000, 0x3c020001, 0x8c426d10, 0xc09821, 0xe0a821, 0x10800006, 0xae020004, 0x26050008, -0xc002b8f, 0x24060018, 0x10000005, 0x2610ffe0, -0x26040008, 0xc002b84, 0x24050018, 0x2610ffe0, -0x3c030001, 0x24637010, 0x203102b, 0x10400003, -0x0, 0x3c100001, 0x8e106f64, 0x8e220000, +0xc002bb3, 0x24060018, 0x10000005, 0x2610ffe0, +0x26040008, 0xc002ba8, 0x24050018, 0x2610ffe0, +0x3c030001, 0x24636f90, 0x203102b, 0x10400003, +0x0, 0x3c100001, 0x8e106ee8, 0x8e220000, 0xae020000, 0x8e220004, 0xae120008, 0xae020004, 0x8f820054, 0xae130010, 0xae150014, 0xae1e0018, 0x8fa80044, 0xae08001c, 0xae02000c, 0x2610ffe0, 0x203102b, 0x10400003, 0x0, 0x3c100001, -0x8e106f64, 0x3c020001, 0x8c426d90, 0xae020000, -0x3c020001, 0x8c426d90, 0x3c010001, 0xac306f68, +0x8e106ee8, 0x3c020001, 0x8c426d10, 0xae020000, +0x3c020001, 0x8c426d10, 0x3c010001, 0xac306eec, 0xae020004, 0xac100250, 0x8fbf0028, 0x8fbe0024, 0x8fb50020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0030, 0x851821, @@ -6390,28 +6394,36 @@ 0x3e00008, 0x0, 0x63080, 0x861821, 0x83102b, 0x10400006, 0x0, 0xac850000, 0x24840004, 0x83102b, 0x5440fffd, 0xac850000, -0x3e00008, 0x0, 0x0, 0x3c0208ff, -0x3442ffff, 0x3c03c0ff, 0x8f850220, 0x3463ffff, -0x8f860200, 0xa21024, 0x34420004, 0xc31824, -0x34630004, 0xaf820220, 0xaf830200, 0x8c820214, -0xac020084, 0x8c820218, 0xac020088, 0x8c82021c, -0xac02008c, 0x8c820220, 0xac020090, 0x8c820224, -0xac020094, 0x8c820228, 0xac020098, 0x8c82022c, -0xac02009c, 0x8c820230, 0xac0200a0, 0x8c820234, -0xac0200a4, 0x8c820238, 0xac0200a8, 0x8c82023c, -0xac0200ac, 0x8c820240, 0xac0200b0, 0x8c820244, -0xac0200b4, 0x8c820248, 0xac0200b8, 0x8c82024c, -0xac0200bc, 0x8c82001c, 0xac020080, 0x8c820018, -0xac0200c0, 0x8c820020, 0xac0200cc, 0x8c820024, -0xac0200d0, 0x8c8201d0, 0xac0200e0, 0x8c8201d4, -0xac0200e4, 0x8c8201d8, 0xac0200e8, 0x8c8201dc, -0xac0200ec, 0x8c8201e0, 0xac0200f0, 0x8c820098, -0x8c83009c, 0xac0300fc, 0x8c8200a8, 0x8c8300ac, -0xac0300f4, 0x8c8200a0, 0x8c8300a4, 0x30a50004, -0xac0300f8, 0x14a00007, 0x30c20004, 0x8f820220, -0x3c0308ff, 0x3463fffb, 0x431024, 0xaf820220, -0x30c20004, 0x14400006, 0x0, 0x8f820200, -0x3c03c0ff, 0x3463fffb, 0x431024, 0xaf820200, +0x3e00008, 0x0, 0x0, 0x26e50028, +0xa03021, 0x274301c0, 0x8f4d0358, 0x8f47035c, +0x8f480360, 0x8f490364, 0x8f4a0368, 0x8f4b0204, +0x8f4c0200, 0x24640400, 0x64102b, 0x10400008, +0x3c0208ff, 0x8cc20000, 0xac620000, 0x24630004, +0x64102b, 0x1440fffb, 0x24c60004, 0x3c0208ff, +0x3442ffff, 0x3c03c0ff, 0xaf4d0358, 0xaf47035c, +0xaf480360, 0xaf490364, 0xaf4a0368, 0xaf4b0204, +0xaf4c0200, 0x8f840220, 0x3463ffff, 0x8f860200, +0x821024, 0x34420004, 0xc31824, 0x34630004, +0xaf820220, 0xaf830200, 0x8ca20214, 0xac020084, +0x8ca20218, 0xac020088, 0x8ca2021c, 0xac02008c, +0x8ca20220, 0xac020090, 0x8ca20224, 0xac020094, +0x8ca20228, 0xac020098, 0x8ca2022c, 0xac02009c, +0x8ca20230, 0xac0200a0, 0x8ca20234, 0xac0200a4, +0x8ca20238, 0xac0200a8, 0x8ca2023c, 0xac0200ac, +0x8ca20240, 0xac0200b0, 0x8ca20244, 0xac0200b4, +0x8ca20248, 0xac0200b8, 0x8ca2024c, 0xac0200bc, +0x8ca2001c, 0xac020080, 0x8ca20018, 0xac0200c0, +0x8ca20020, 0xac0200cc, 0x8ca20024, 0xac0200d0, +0x8ca201d0, 0xac0200e0, 0x8ca201d4, 0xac0200e4, +0x8ca201d8, 0xac0200e8, 0x8ca201dc, 0xac0200ec, +0x8ca201e0, 0xac0200f0, 0x8ca20098, 0x8ca3009c, +0xac0300fc, 0x8ca200a8, 0x8ca300ac, 0xac0300f4, +0x8ca200a0, 0x8ca300a4, 0x30840004, 0xac0300f8, +0x14800007, 0x30c20004, 0x8f820220, 0x3c0308ff, +0x3463fffb, 0x431024, 0xaf820220, 0x30c20004, +0x14400006, 0x0, 0x8f820200, 0x3c03c0ff, +0x3463fffb, 0x431024, 0xaf820200, 0x8f4202dc, +0xa34005c5, 0x24420001, 0xaf4202dc, 0x8f4202dc, 0x3e00008, 0x0, 0x27bdffd8, 0xafbf0024, 0xafb00020, 0x8f430024, 0x8f420020, 0x10620038, 0x0, 0x8f430020, 0x8f420024, 0x622023, @@ -6443,7 +6455,7 @@ 0x8e040000, 0x8e050004, 0x96120008, 0x8f420090, 0x9611000a, 0x3246ffff, 0x46102a, 0x10400017, 0x0, 0x8f8200d8, 0x8f430098, 0x431023, -0x2442fff8, 0xaf420090, 0x8f420090, 0x2842fff9, +0x2442dcbe, 0xaf420090, 0x8f420090, 0x2842dcbf, 0x10400005, 0x0, 0x8f420090, 0x8f430144, 0x431021, 0xaf420090, 0x8f420090, 0x46102a, 0x10400006, 0x0, 0x8f420348, 0x24420001, @@ -6513,7 +6525,7 @@ 0x8e040000, 0x8e050004, 0x96110008, 0x8f420090, 0x9607000a, 0x3226ffff, 0x46102a, 0x10400017, 0x0, 0x8f8200d8, 0x8f430098, 0x431023, -0x2442ff80, 0xaf420090, 0x8f420090, 0x2842ff81, +0x2442dc46, 0xaf420090, 0x8f420090, 0x2842dc47, 0x10400005, 0x0, 0x8f420090, 0x8f430144, 0x431021, 0xaf420090, 0x8f420090, 0x46102a, 0x10400006, 0x0, 0x8f420348, 0x24420001, @@ -6575,15 +6587,15 @@ 0x30a20001, 0x8c82001c, 0x8f430040, 0x8f440034, 0x24420001, 0x2463ffff, 0x431024, 0x862021, 0xaf42002c, 0x30a20030, 0x14400006, 0xaf440034, -0x8f420034, 0x8c03023c, 0x43102b, 0x144000ca, +0x8f420034, 0x8c03023c, 0x43102b, 0x144000b4, 0x0, 0x32c20010, 0x10400028, 0x24070008, 0x8f440170, 0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120, 0x24020080, 0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011, 0x24020001, 0x3c010001, 0x370821, 0xa02240f1, 0x8f820124, 0xafa20010, 0x8f820128, -0x3c040001, 0x24846854, 0xafa20014, 0x8f46002c, -0x8f870120, 0x3c050009, 0xc002b17, 0x34a51100, +0x3c040001, 0x248467c4, 0xafa20014, 0x8f46002c, +0x8f870120, 0x3c050009, 0xc002b3b, 0x34a51100, 0x10000036, 0x0, 0x8f420300, 0x8f43002c, 0x24420001, 0xaf420300, 0x8f420300, 0x24020001, 0xa34205c1, 0x10000026, 0xaf430038, 0x8f440170, @@ -6592,13 +6604,13 @@ 0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011, 0x24020001, 0x3c010001, 0x370821, 0xa02240f0, 0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001, -0x24846848, 0xafa20014, 0x8f46002c, 0x8f870120, -0x3c050009, 0xc002b17, 0x34a50900, 0x1000000f, +0x248467b8, 0xafa20014, 0x8f46002c, 0x8f870120, +0x3c050009, 0xc002b3b, 0x34a50900, 0x1000000f, 0x0, 0x8f420300, 0x24420001, 0xaf420300, 0x8f420300, 0x8f42002c, 0xa34005c1, 0xaf420038, 0x3c010001, 0x370821, 0xa02040f1, 0x3c010001, 0x370821, 0xa02040f0, 0xaf400034, 0x8f420314, -0x24420001, 0xaf420314, 0x1000006f, 0x8f420314, +0x24420001, 0xaf420314, 0x10000059, 0x8f420314, 0x10400022, 0x30a27000, 0x8c85001c, 0x8f420028, 0xa22023, 0x4810003, 0x0, 0x8f420040, 0x822021, 0x8f420358, 0x8f430000, 0xaf450028, @@ -6606,8 +6618,8 @@ 0x8f82004c, 0x1040fffd, 0x0, 0x10000005, 0x0, 0xaf800048, 0x8f820048, 0x1040fffd, 0x0, 0x8f820060, 0x34420008, 0xaf820060, -0x8f420000, 0x10400003, 0x0, 0x1000004e, -0xaf80004c, 0x1000004c, 0xaf800048, 0x1040002f, +0x8f420000, 0x10400003, 0x0, 0x10000038, +0xaf80004c, 0x10000036, 0xaf800048, 0x1040002f, 0x30a21000, 0x1040000c, 0x30a24000, 0x8c83001c, 0x8f420050, 0x622023, 0x4820001, 0x24840200, 0x8f42035c, 0x441021, 0xaf42035c, 0x8f420368, @@ -6618,190 +6630,179 @@ 0x3c020800, 0x8c83001c, 0x8f420060, 0x622023, 0x4820001, 0x24840100, 0x8f420360, 0x441021, 0xaf420360, 0x8f420368, 0xaf430060, 0x441021, -0xaf420368, 0x3c020800, 0x2c21024, 0x5040001e, -0x36940040, 0x1000001c, 0x0, 0x30a20100, -0x10400019, 0x0, 0x3c020001, 0x8c426d44, -0x1040000d, 0x274301c0, 0x24650400, 0x65102b, -0x10400007, 0x26e40028, 0x8c820000, 0xac620000, -0x24630004, 0x65102b, 0x1440fffb, 0x24840004, -0x10000002, 0x274401c0, 0x26e40028, 0xc002bb4, -0x0, 0x8f4202dc, 0xa34005c5, 0x24420001, -0xaf4202dc, 0x8f4202dc, 0x8fbf0020, 0x3e00008, -0x27bd0028, 0x3e00008, 0x0, 0x27bdffa8, -0xafbf0050, 0xafbe004c, 0xafb50048, 0xafb30044, -0xafb20040, 0xafb1003c, 0xafb00038, 0x8f910108, -0x26220020, 0xaf820108, 0x8e320018, 0xa821, -0x32420024, 0x104001ba, 0xf021, 0x8e26001c, -0x8f43001c, 0x61100, 0x621821, 0x8c70000c, -0x9604000c, 0x962d0016, 0x9473000a, 0x2c8305dd, -0x38828870, 0x2c420001, 0x621825, 0x10600015, -0x2821, 0x32c20040, 0x10400015, 0x24020800, -0x96030014, 0x14620012, 0x3402aaaa, 0x9603000e, -0x14620007, 0x2021, 0x96030010, 0x24020300, -0x14620004, 0x801021, 0x96020012, 0x2c440001, -0x801021, 0x54400006, 0x24050016, 0x10000004, -0x0, 0x24020800, 0x50820001, 0x2405000e, -0x934205c3, 0x14400008, 0x5821, 0x240b0001, -0x32620180, 0xaf4500a8, 0xaf5000a0, 0x10400002, -0xaf4600a4, 0xa34b05c3, 0x10a00085, 0x2054021, -0x91020000, 0x3821, 0x3042000f, 0x25080, -0x32c20002, 0x10400012, 0x10a1821, 0x32620002, -0x10400010, 0x32c20001, 0x1002021, 0x94820000, -0x24840002, 0xe23821, 0x83102b, 0x1440fffb, -0x30e2ffff, 0x71c02, 0x623821, 0x71c02, -0x30e2ffff, 0x623821, 0x71027, 0xa502000a, -0x32c20001, 0x1040006a, 0x32620001, 0x10400068, -0x0, 0x8f4200a8, 0x10400065, 0x0, -0x8f4200a0, 0x8f4300a8, 0x431021, 0x904c0009, -0x318900ff, 0x39230006, 0x3182b, 0x39220011, -0x2102b, 0x621824, 0x1060000c, 0x3c050006, -0x8f4200a4, 0x3c040001, 0x24846864, 0xafa20010, -0x8f4200a0, 0x34a54600, 0x1203821, 0xc002b17, -0xafa20014, 0x1000004e, 0x0, 0x32c20004, -0x14400013, 0x2821, 0x316200ff, 0x14400004, -0x0, 0x95020002, 0x1000000d, 0x4a2823, -0x9505000c, 0x9502000e, 0x95030010, 0xa22821, -0xa32821, 0x95030012, 0x91040009, 0x95020002, -0xa32821, 0xa42821, 0x4a1023, 0xa22821, -0x2002021, 0x94820000, 0x24840002, 0xe23821, -0x88102b, 0x1440fffb, 0x71c02, 0x30e2ffff, +0xaf420368, 0x3c020800, 0x2c21024, 0x50400008, +0x36940040, 0x10000006, 0x0, 0x30a20100, +0x10400003, 0x0, 0xc002bd8, 0x0, +0x8fbf0020, 0x3e00008, 0x27bd0028, 0x3e00008, +0x0, 0x27bdffa8, 0xafbf0050, 0xafbe004c, +0xafb50048, 0xafb30044, 0xafb20040, 0xafb1003c, +0xafb00038, 0x8f910108, 0x26220020, 0xaf820108, +0x8e320018, 0xa821, 0x32420024, 0x104001ba, +0xf021, 0x8e26001c, 0x8f43001c, 0x61100, +0x621821, 0x8c70000c, 0x9604000c, 0x962d0016, +0x9473000a, 0x2c8305dd, 0x38828870, 0x2c420001, +0x621825, 0x10600015, 0x2821, 0x32c20040, +0x10400015, 0x24020800, 0x96030014, 0x14620012, +0x3402aaaa, 0x9603000e, 0x14620007, 0x2021, +0x96030010, 0x24020300, 0x14620004, 0x801021, +0x96020012, 0x2c440001, 0x801021, 0x54400006, +0x24050016, 0x10000004, 0x0, 0x24020800, +0x50820001, 0x2405000e, 0x934205c3, 0x14400008, +0x5821, 0x240b0001, 0x32620180, 0xaf4500a8, +0xaf5000a0, 0x10400002, 0xaf4600a4, 0xa34b05c3, +0x10a00085, 0x2054021, 0x91020000, 0x3821, +0x3042000f, 0x25080, 0x32c20002, 0x10400012, +0x10a1821, 0x32620002, 0x10400010, 0x32c20001, +0x1002021, 0x94820000, 0x24840002, 0xe23821, +0x83102b, 0x1440fffb, 0x30e2ffff, 0x71c02, 0x623821, 0x71c02, 0x30e2ffff, 0x623821, -0x1a52821, 0x51c02, 0x30a2ffff, 0x622821, -0x51c02, 0x30a2ffff, 0x622821, 0xa72823, -0x51402, 0xa22821, 0x30a5ffff, 0x50a00001, -0x3405ffff, 0x316200ff, 0x14400008, 0x318300ff, -0x8f4300a0, 0x8f4200a8, 0x624021, 0x91020000, -0x3042000f, 0x25080, 0x318300ff, 0x24020006, -0x14620003, 0x10a1021, 0x10000002, 0x24440010, -0x24440006, 0x316200ff, 0x14400006, 0x0, -0x94820000, 0xa22821, 0x51c02, 0x30a2ffff, -0x622821, 0x934205c3, 0x10400003, 0x32620100, -0x50400003, 0xa4850000, 0x52827, 0xa4850000, -0x9622000e, 0x8f43009c, 0x621821, 0x32a200ff, -0x10400007, 0xaf43009c, 0x3c024000, 0x2021025, -0xafa20020, 0x8f42009c, 0x10000003, 0x5e1025, -0xafb00020, 0x8f42009c, 0xafa20024, 0x32620080, -0x10400010, 0x32620100, 0x8f4200b4, 0x24430001, -0x210c0, 0x571021, 0xaf4300b4, 0x8fa30020, -0x8fa40024, 0x3c010001, 0x220821, 0xac2338e8, -0x3c010001, 0x220821, 0xac2438ec, 0x100000a5, -0x32c20020, 0x10400064, 0x0, 0x8f4200b4, -0x24430001, 0x210c0, 0x571021, 0xaf4300b4, -0x8fa30020, 0x8fa40024, 0x3c010001, 0x220821, -0xac2338e8, 0x3c010001, 0x220821, 0xac2438ec, -0x8f4200b4, 0x10400051, 0x3821, 0x3c090001, -0x352938e8, 0x3c08001f, 0x3508ffff, 0x240bffff, -0x340affff, 0x710c0, 0x571021, 0x491021, -0x8c430000, 0x8c440004, 0xafa30028, 0xafa4002c, -0x8f8200fc, 0x8fa30028, 0x8fa4002c, 0xac430000, -0xac440004, 0x24420008, 0xaf8200f0, 0x8f42008c, -0x2442ffff, 0xaf42008c, 0x97a2002e, 0x8f440270, -0x8f450274, 0x401821, 0x1021, 0xa32821, -0xa3302b, 0x822021, 0x862021, 0xaf440270, -0xaf450274, 0x8fa20028, 0x481024, 0x90430000, -0x30630001, 0x1460000b, 0x402021, 0x8f420278, -0x8f43027c, 0x24630001, 0x2c640001, 0x441021, -0xaf420278, 0xaf43027c, 0x8f420278, 0x1000001a, -0x8f43027c, 0x8c820000, 0x144b000e, 0x0, -0x94820004, 0x144a000b, 0x0, 0x8f420288, -0x8f43028c, 0x24630001, 0x2c640001, 0x441021, -0xaf420288, 0xaf43028c, 0x8f420288, 0x1000000a, -0x8f43028c, 0x8f420280, 0x8f430284, 0x24630001, -0x2c640001, 0x441021, 0xaf420280, 0xaf430284, -0x8f420280, 0x8f430284, 0x8f4200b4, 0x24e70001, -0xe2102b, 0x1440ffb8, 0x710c0, 0xa34005c3, -0x1000003f, 0xaf4000b4, 0x8f8200fc, 0x8fa30020, -0x8fa40024, 0xac430000, 0xac440004, 0x24420008, -0xaf8200f0, 0x8f42009c, 0x8f46008c, 0x8f440270, -0x8f450274, 0x401821, 0x1021, 0x24c6ffff, -0xaf46008c, 0xa32821, 0xa3302b, 0x822021, -0x862021, 0xaf440270, 0xaf450274, 0x92020000, -0x30420001, 0x1440000c, 0x2402ffff, 0x8f420278, -0x8f43027c, 0x24630001, 0x2c640001, 0x441021, -0xaf420278, 0xaf43027c, 0x8f420278, 0x8f43027c, -0x1000001c, 0x32c20020, 0x8e030000, 0x1462000f, -0x3402ffff, 0x96030004, 0x1462000c, 0x0, -0x8f420288, 0x8f43028c, 0x24630001, 0x2c640001, -0x441021, 0xaf420288, 0xaf43028c, 0x8f420288, -0x8f43028c, 0x1000000b, 0x32c20020, 0x8f420280, +0x71027, 0xa502000a, 0x32c20001, 0x1040006a, +0x32620001, 0x10400068, 0x0, 0x8f4200a8, +0x10400065, 0x0, 0x8f4200a0, 0x8f4300a8, +0x431021, 0x904c0009, 0x318900ff, 0x39230006, +0x3182b, 0x39220011, 0x2102b, 0x621824, +0x1060000c, 0x3c050006, 0x8f4200a4, 0x3c040001, +0x248467d4, 0xafa20010, 0x8f4200a0, 0x34a54600, +0x1203821, 0xc002b3b, 0xafa20014, 0x1000004e, +0x0, 0x32c20004, 0x14400013, 0x2821, +0x316200ff, 0x14400004, 0x0, 0x95020002, +0x1000000d, 0x4a2823, 0x9505000c, 0x9502000e, +0x95030010, 0xa22821, 0xa32821, 0x95030012, +0x91040009, 0x95020002, 0xa32821, 0xa42821, +0x4a1023, 0xa22821, 0x2002021, 0x94820000, +0x24840002, 0xe23821, 0x88102b, 0x1440fffb, +0x71c02, 0x30e2ffff, 0x623821, 0x71c02, +0x30e2ffff, 0x623821, 0x1a52821, 0x51c02, +0x30a2ffff, 0x622821, 0x51c02, 0x30a2ffff, +0x622821, 0xa72823, 0x51402, 0xa22821, +0x30a5ffff, 0x50a00001, 0x3405ffff, 0x316200ff, +0x14400008, 0x318300ff, 0x8f4300a0, 0x8f4200a8, +0x624021, 0x91020000, 0x3042000f, 0x25080, +0x318300ff, 0x24020006, 0x14620003, 0x10a1021, +0x10000002, 0x24440010, 0x24440006, 0x316200ff, +0x14400006, 0x0, 0x94820000, 0xa22821, +0x51c02, 0x30a2ffff, 0x622821, 0x934205c3, +0x10400003, 0x32620100, 0x50400003, 0xa4850000, +0x52827, 0xa4850000, 0x9622000e, 0x8f43009c, +0x621821, 0x32a200ff, 0x10400007, 0xaf43009c, +0x3c024000, 0x2021025, 0xafa20020, 0x8f42009c, +0x10000003, 0x5e1025, 0xafb00020, 0x8f42009c, +0xafa20024, 0x32620080, 0x10400010, 0x32620100, +0x8f4200b4, 0x24430001, 0x210c0, 0x571021, +0xaf4300b4, 0x8fa30020, 0x8fa40024, 0x3c010001, +0x220821, 0xac2338e8, 0x3c010001, 0x220821, +0xac2438ec, 0x100000a5, 0x32c20020, 0x10400064, +0x0, 0x8f4200b4, 0x24430001, 0x210c0, +0x571021, 0xaf4300b4, 0x8fa30020, 0x8fa40024, +0x3c010001, 0x220821, 0xac2338e8, 0x3c010001, +0x220821, 0xac2438ec, 0x8f4200b4, 0x10400051, +0x3821, 0x3c090001, 0x352938e8, 0x3c08001f, +0x3508ffff, 0x240bffff, 0x340affff, 0x710c0, +0x571021, 0x491021, 0x8c430000, 0x8c440004, +0xafa30028, 0xafa4002c, 0x8f8200fc, 0x8fa30028, +0x8fa4002c, 0xac430000, 0xac440004, 0x24420008, +0xaf8200f0, 0x8f42008c, 0x2442ffff, 0xaf42008c, +0x97a2002e, 0x8f440270, 0x8f450274, 0x401821, +0x1021, 0xa32821, 0xa3302b, 0x822021, +0x862021, 0xaf440270, 0xaf450274, 0x8fa20028, +0x481024, 0x90430000, 0x30630001, 0x1460000b, +0x402021, 0x8f420278, 0x8f43027c, 0x24630001, +0x2c640001, 0x441021, 0xaf420278, 0xaf43027c, +0x8f420278, 0x1000001a, 0x8f43027c, 0x8c820000, +0x144b000e, 0x0, 0x94820004, 0x144a000b, +0x0, 0x8f420288, 0x8f43028c, 0x24630001, +0x2c640001, 0x441021, 0xaf420288, 0xaf43028c, +0x8f420288, 0x1000000a, 0x8f43028c, 0x8f420280, 0x8f430284, 0x24630001, 0x2c640001, 0x441021, 0xaf420280, 0xaf430284, 0x8f420280, 0x8f430284, -0x32c20020, 0x10400005, 0xaf40009c, 0x8f420358, +0x8f4200b4, 0x24e70001, 0xe2102b, 0x1440ffb8, +0x710c0, 0xa34005c3, 0x1000003f, 0xaf4000b4, +0x8f8200fc, 0x8fa30020, 0x8fa40024, 0xac430000, +0xac440004, 0x24420008, 0xaf8200f0, 0x8f42009c, +0x8f46008c, 0x8f440270, 0x8f450274, 0x401821, +0x1021, 0x24c6ffff, 0xaf46008c, 0xa32821, +0xa3302b, 0x822021, 0x862021, 0xaf440270, +0xaf450274, 0x92020000, 0x30420001, 0x1440000c, +0x2402ffff, 0x8f420278, 0x8f43027c, 0x24630001, +0x2c640001, 0x441021, 0xaf420278, 0xaf43027c, +0x8f420278, 0x8f43027c, 0x1000001c, 0x32c20020, +0x8e030000, 0x1462000f, 0x3402ffff, 0x96030004, +0x1462000c, 0x0, 0x8f420288, 0x8f43028c, +0x24630001, 0x2c640001, 0x441021, 0xaf420288, +0xaf43028c, 0x8f420288, 0x8f43028c, 0x1000000b, +0x32c20020, 0x8f420280, 0x8f430284, 0x24630001, +0x2c640001, 0x441021, 0xaf420280, 0xaf430284, +0x8f420280, 0x8f430284, 0x32c20020, 0x10400005, +0xaf40009c, 0x8f420358, 0x2442ffff, 0xaf420358, +0x8f420358, 0x8e22001c, 0x8f430040, 0x24420001, +0x2463ffff, 0x431024, 0xaf42002c, 0x32420060, +0x14400008, 0x32c20010, 0x8f420034, 0x24420001, +0xaf420034, 0x8c03023c, 0x43102b, 0x14400102, +0x32c20010, 0x10400018, 0x24070008, 0x8f440170, +0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120, +0x24020080, 0xafa20010, 0xafa30014, 0xafa80018, +0x8f42010c, 0x40f809, 0x24c6001c, 0x10400047, +0x24020001, 0x8f420300, 0x8f43002c, 0x24420001, +0xaf420300, 0x8f420300, 0x24020001, 0xa34205c1, +0x1000007c, 0xaf430038, 0x8f440170, 0x8f450174, +0x8f43002c, 0x8f48000c, 0x8f860120, 0x24020020, +0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c, +0x40f809, 0x24c6001c, 0x10400057, 0x24020001, +0x10000065, 0x0, 0x32420012, 0x10400075, +0x32420001, 0x9622000e, 0x8f43009c, 0x621821, +0x32c20020, 0x10400005, 0xaf43009c, 0x8f420358, 0x2442ffff, 0xaf420358, 0x8f420358, 0x8e22001c, 0x8f430040, 0x24420001, 0x2463ffff, 0x431024, -0xaf42002c, 0x32420060, 0x14400008, 0x32c20010, +0xaf42002c, 0x32420010, 0x14400008, 0x32c20010, 0x8f420034, 0x24420001, 0xaf420034, 0x8c03023c, -0x43102b, 0x14400118, 0x32c20010, 0x10400018, +0x43102b, 0x144000bc, 0x32c20010, 0x10400028, 0x24070008, 0x8f440170, 0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120, 0x24020080, 0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c, 0x40f809, -0x24c6001c, 0x10400047, 0x24020001, 0x8f420300, +0x24c6001c, 0x14400011, 0x24020001, 0x3c010001, +0x370821, 0xa02240f1, 0x8f820124, 0xafa20010, +0x8f820128, 0x3c040001, 0x248467c4, 0xafa20014, +0x8f46002c, 0x8f870120, 0x3c050009, 0xc002b3b, +0x34a51100, 0x10000036, 0x0, 0x8f420300, 0x8f43002c, 0x24420001, 0xaf420300, 0x8f420300, -0x24020001, 0xa34205c1, 0x1000007c, 0xaf430038, +0x24020001, 0xa34205c1, 0x10000026, 0xaf430038, 0x8f440170, 0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120, 0x24020020, 0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c, -0x10400057, 0x24020001, 0x10000065, 0x0, -0x32420012, 0x10400075, 0x32420001, 0x9622000e, -0x8f43009c, 0x621821, 0x32c20020, 0x10400005, -0xaf43009c, 0x8f420358, 0x2442ffff, 0xaf420358, -0x8f420358, 0x8e22001c, 0x8f430040, 0x24420001, -0x2463ffff, 0x431024, 0xaf42002c, 0x32420010, -0x14400008, 0x32c20010, 0x8f420034, 0x24420001, -0xaf420034, 0x8c03023c, 0x43102b, 0x144000d2, -0x32c20010, 0x10400028, 0x24070008, 0x8f440170, -0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120, -0x24020080, 0xafa20010, 0xafa30014, 0xafa80018, -0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011, -0x24020001, 0x3c010001, 0x370821, 0xa02240f1, -0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001, -0x24846854, 0xafa20014, 0x8f46002c, 0x8f870120, -0x3c050009, 0xc002b17, 0x34a51100, 0x10000036, -0x0, 0x8f420300, 0x8f43002c, 0x24420001, -0xaf420300, 0x8f420300, 0x24020001, 0xa34205c1, -0x10000026, 0xaf430038, 0x8f440170, 0x8f450174, -0x8f43002c, 0x8f48000c, 0x8f860120, 0x24020020, -0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c, -0x40f809, 0x24c6001c, 0x14400011, 0x24020001, -0x3c010001, 0x370821, 0xa02240f0, 0x8f820124, -0xafa20010, 0x8f820128, 0x3c040001, 0x24846848, -0xafa20014, 0x8f46002c, 0x8f870120, 0x3c050009, -0xc002b17, 0x34a50900, 0x1000000f, 0x0, -0x8f420300, 0x24420001, 0xaf420300, 0x8f420300, -0x8f42002c, 0xa34005c1, 0xaf420038, 0x3c010001, -0x370821, 0xa02040f1, 0x3c010001, 0x370821, -0xa02040f0, 0xaf400034, 0x8f420314, 0x24420001, -0xaf420314, 0x10000078, 0x8f420314, 0x10400022, -0x32427000, 0x8e25001c, 0x8f420028, 0xa22023, -0x4810003, 0x0, 0x8f420040, 0x822021, -0x8f420358, 0x8f430000, 0xaf450028, 0x441021, -0x10600007, 0xaf420358, 0xaf80004c, 0x8f82004c, -0x1040fffd, 0x0, 0x10000005, 0x0, -0xaf800048, 0x8f820048, 0x1040fffd, 0x0, -0x8f820060, 0x34420008, 0xaf820060, 0x8f420000, -0x10400003, 0x0, 0x10000057, 0xaf80004c, -0x10000055, 0xaf800048, 0x1040002f, 0x32421000, -0x1040000c, 0x32424000, 0x8e23001c, 0x8f420050, -0x622023, 0x4820001, 0x24840200, 0x8f42035c, -0x441021, 0xaf42035c, 0x8f420368, 0x1000001a, -0xaf430050, 0x1040000c, 0x32c28000, 0x8e23001c, -0x8f420070, 0x622023, 0x4820001, 0x24840400, -0x8f420364, 0x441021, 0xaf420364, 0x8f420368, -0x1000000d, 0xaf430070, 0x1040000e, 0x3c020800, -0x8e23001c, 0x8f420060, 0x622023, 0x4820001, -0x24840100, 0x8f420360, 0x441021, 0xaf420360, -0x8f420368, 0xaf430060, 0x441021, 0xaf420368, -0x3c020800, 0x2c21024, 0x50400027, 0x36940040, -0x10000025, 0x0, 0x32420048, 0x10400007, -0x24150001, 0x8e22001c, 0x3c03ffff, 0x43f024, -0x3042ffff, 0x1000fd75, 0xae22001c, 0x32420100, -0x10400019, 0x0, 0x3c020001, 0x8c426d44, -0x1040000d, 0x274301c0, 0x24650400, 0x65102b, -0x10400007, 0x26e40028, 0x8c820000, 0xac620000, -0x24630004, 0x65102b, 0x1440fffb, 0x24840004, -0x10000002, 0x274401c0, 0x26e40028, 0xc002bb4, -0x0, 0x8f4202dc, 0xa34005c5, 0x24420001, -0xaf4202dc, 0x8f4202dc, 0x8fbf0050, 0x8fbe004c, +0x14400011, 0x24020001, 0x3c010001, 0x370821, +0xa02240f0, 0x8f820124, 0xafa20010, 0x8f820128, +0x3c040001, 0x248467b8, 0xafa20014, 0x8f46002c, +0x8f870120, 0x3c050009, 0xc002b3b, 0x34a50900, +0x1000000f, 0x0, 0x8f420300, 0x24420001, +0xaf420300, 0x8f420300, 0x8f42002c, 0xa34005c1, +0xaf420038, 0x3c010001, 0x370821, 0xa02040f1, +0x3c010001, 0x370821, 0xa02040f0, 0xaf400034, +0x8f420314, 0x24420001, 0xaf420314, 0x10000062, +0x8f420314, 0x10400022, 0x32427000, 0x8e25001c, +0x8f420028, 0xa22023, 0x4810003, 0x0, +0x8f420040, 0x822021, 0x8f420358, 0x8f430000, +0xaf450028, 0x441021, 0x10600007, 0xaf420358, +0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0, +0x10000005, 0x0, 0xaf800048, 0x8f820048, +0x1040fffd, 0x0, 0x8f820060, 0x34420008, +0xaf820060, 0x8f420000, 0x10400003, 0x0, +0x10000041, 0xaf80004c, 0x1000003f, 0xaf800048, +0x1040002f, 0x32421000, 0x1040000c, 0x32424000, +0x8e23001c, 0x8f420050, 0x622023, 0x4820001, +0x24840200, 0x8f42035c, 0x441021, 0xaf42035c, +0x8f420368, 0x1000001a, 0xaf430050, 0x1040000c, +0x32c28000, 0x8e23001c, 0x8f420070, 0x622023, +0x4820001, 0x24840400, 0x8f420364, 0x441021, +0xaf420364, 0x8f420368, 0x1000000d, 0xaf430070, +0x1040000e, 0x3c020800, 0x8e23001c, 0x8f420060, +0x622023, 0x4820001, 0x24840100, 0x8f420360, +0x441021, 0xaf420360, 0x8f420368, 0xaf430060, +0x441021, 0xaf420368, 0x3c020800, 0x2c21024, +0x50400011, 0x36940040, 0x1000000f, 0x0, +0x32420048, 0x10400007, 0x24150001, 0x8e22001c, +0x3c03ffff, 0x43f024, 0x3042ffff, 0x1000fd75, +0xae22001c, 0x32420100, 0x10400003, 0x0, +0xc002bd8, 0x0, 0x8fbf0050, 0x8fbe004c, 0x8fb50048, 0x8fb30044, 0x8fb20040, 0x8fb1003c, 0x8fb00038, 0x3e00008, 0x27bd0058, 0x3e00008, 0x0, 0x0, 0x0, 0x8f8300e4, @@ -6818,7 +6819,7 @@ 0x10400003, 0x0, 0x8f420148, 0x621821, 0x94a20006, 0x24420050, 0x62102b, 0x1440000f, 0xa01021, 0xafa40010, 0xafa30014, 0x8ca60000, -0x8ca70004, 0x3c040001, 0xc002b17, 0x24846924, +0x8ca70004, 0x3c040001, 0xc002b3b, 0x24846894, 0x8f42020c, 0x24420001, 0xaf42020c, 0x8f42020c, 0x1021, 0xaf9000e8, 0xaf9000e4, 0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020, 0x3e00008, @@ -6840,15 +6841,15 @@ 0x8f4b00c4, 0xafab0064, 0x8f4a00c0, 0xafaa006c, 0x8f4b00cc, 0xafab0074, 0x8f4a00c8, 0x10000129, 0xafaa007c, 0x8f420114, 0x40f809, 0x0, -0x403021, 0x10c0033f, 0x0, 0x8cc20000, +0x403021, 0x10c0034f, 0x0, 0x8cc20000, 0x8cc30004, 0xafa20020, 0xafa30024, 0x8fab0024, 0x8faa0020, 0x3162ffff, 0x2442fffc, 0xafa2006c, 0x3c020006, 0x2c21024, 0xafab007c, 0x14400015, 0xafaa0064, 0x91420000, 0x30420001, 0x10400011, 0x2402ffff, 0x8d430000, 0x14620004, 0x3402ffff, -0x95430004, 0x1062000b, 0x0, 0xc002497, +0x95430004, 0x1062000b, 0x0, 0xc0024bb, 0x8fa40064, 0x304200ff, 0x14400006, 0x0, -0x8f420118, 0x40f809, 0x0, 0x1000031d, +0x8f420118, 0x40f809, 0x0, 0x1000032d, 0x0, 0x8fa20024, 0x3c03ffbf, 0x3463ffff, 0x431024, 0x3c03ffff, 0x431824, 0x14600003, 0xafa20024, 0x10000040, 0x1821, 0x3c020080, @@ -6871,13 +6872,13 @@ 0x4b102b, 0x10400014, 0x307000ff, 0x8f4201e8, 0x24420001, 0xaf4201e8, 0x8f4201e8, 0x8faa007c, 0x8f8200e0, 0x354a0100, 0xafaa007c, 0xafa20010, -0x8f8200e4, 0x24100001, 0x3c040001, 0x24846930, +0x8f8200e4, 0x24100001, 0x3c040001, 0x248468a0, 0xafa20014, 0x8fa60020, 0x8fa70024, 0x3c050007, -0xc002b17, 0x34a50800, 0x12000010, 0x3c020080, +0xc002b3b, 0x34a50800, 0x12000010, 0x3c020080, 0x2c21024, 0x1440000e, 0x32c20400, 0x8fab007c, 0x3c020080, 0x34420100, 0x1621024, 0x10400005, 0x0, 0x8f42020c, 0x24420001, 0xaf42020c, -0x8f42020c, 0x100002a0, 0x8fa3006c, 0x32c20400, +0x8f42020c, 0x100002b0, 0x8fa3006c, 0x32c20400, 0x10400015, 0x34028100, 0x8faa0064, 0x9543000c, 0x14620012, 0x3c020100, 0x240b0200, 0xa7ab008e, 0x9542000e, 0x8d430008, 0x8d440004, 0x8d450000, @@ -6892,66 +6893,66 @@ 0x10400056, 0x32c28000, 0x1040005e, 0x240a0003, 0x32c21000, 0x1040005b, 0xafaa005c, 0x10000058, 0x240b0004, 0x8f420350, 0x2403ffbf, 0x283a024, -0x24420001, 0xaf420350, 0x1000023f, 0x8f420350, +0x24420001, 0xaf420350, 0x1000024f, 0x8f420350, 0x2c2b025, 0x2402ffbf, 0x282a024, 0x8f830128, -0x3c040001, 0x24846960, 0x26620001, 0xafa20014, +0x3c040001, 0x248468d0, 0x26620001, 0xafa20014, 0xafa30010, 0x8f860120, 0x8f870124, 0x3c050007, -0xc002b17, 0x34a52250, 0x1000022f, 0x0, +0xc002b3b, 0x34a52250, 0x1000023f, 0x0, 0x2c2b025, 0x2402ffbf, 0x282a024, 0x8f830128, -0x3c040001, 0x24846960, 0x24020002, 0xafa20014, +0x3c040001, 0x248468d0, 0x24020002, 0xafa20014, 0xafa30010, 0x8f860120, 0x8f870124, 0x3c050007, -0xc002b17, 0x34a52450, 0x1000021f, 0x0, -0x8ea20000, 0x8ea30004, 0x3c040001, 0x24846978, +0xc002b3b, 0x34a52450, 0x1000022f, 0x0, +0x8ea20000, 0x8ea30004, 0x3c040001, 0x248468e8, 0xafb00010, 0xafbe0014, 0x8ea70018, 0x34a52800, -0xc002b17, 0x603021, 0x10000213, 0x0, -0xa6b1000a, 0x8f820124, 0x3c040001, 0x24846980, +0xc002b3b, 0x603021, 0x10000223, 0x0, +0xa6b1000a, 0x8f820124, 0x3c040001, 0x248468f0, 0xafbe0014, 0xafa20010, 0x8f460044, 0x8f870120, -0x3c050007, 0xc002b17, 0x34a53000, 0x10000206, +0x3c050007, 0xc002b3b, 0x34a53000, 0x10000216, 0x0, 0xa6b1000a, 0xa6b2000e, 0x8f820124, -0x3c040001, 0x2484698c, 0xafbe0014, 0xafa20010, -0x8f460044, 0x8f870120, 0x3c050007, 0xc002b17, -0x34a53200, 0x100001f8, 0x0, 0x8f420084, +0x3c040001, 0x248468fc, 0xafbe0014, 0xafa20010, +0x8f460044, 0x8f870120, 0x3c050007, 0xc002b3b, +0x34a53200, 0x10000208, 0x0, 0x8f420084, 0x8faa006c, 0x4a102b, 0x14400007, 0x3c020001, 0x2c21024, 0x10400004, 0x0, 0x240b0002, -0xafab005c, 0x8faa006c, 0x1140020b, 0x27ab0020, +0xafab005c, 0x8faa006c, 0x1140021b, 0x27ab0020, 0xafab00a4, 0x3c0a001f, 0x354affff, 0xafaa009c, -0x8fab005c, 0x240a0001, 0x156a0021, 0x24020002, +0x8fab005c, 0x240a0001, 0x556a0021, 0x240a0002, 0x8f430054, 0x8f420050, 0x1062000b, 0x274b0054, 0x8f5e0054, 0x3403ecc0, 0xafab004c, 0x27c20001, 0x304201ff, 0xafa20054, 0x1e1140, 0x431021, 0x1000006b, 0x2e2a821, 0x8f420044, 0x8faa006c, -0x3c040001, 0x2484693c, 0xafaa0014, 0xafa20010, -0x8f460054, 0x8f470050, 0x3c050007, 0xc002b17, +0x3c040001, 0x248468ac, 0xafaa0014, 0xafa20010, +0x8f460054, 0x8f470050, 0x3c050007, 0xc002b3b, 0x34a51300, 0x8f430350, 0x2402ffbf, 0x282a024, -0x24630001, 0xaf430350, 0x100001c3, 0x8f420350, -0x1562001d, 0x0, 0x8f430074, 0x8f420070, -0x1062000a, 0x274a0074, 0x8f5e0074, 0xafaa004c, +0x24630001, 0xaf430350, 0x100001d3, 0x8f420350, +0x156a001d, 0x0, 0x8f430074, 0x8f420070, +0x1062000a, 0x274b0074, 0x8f5e0074, 0xafab004c, 0x27c20001, 0x304203ff, 0xafa20054, 0x1e1140, 0x24426cc0, 0x1000004a, 0x2e2a821, 0x8f420044, -0x8fab006c, 0x3c040001, 0x24846948, 0x3c050007, -0xafab0014, 0xafa20010, 0x8f460074, 0x8f470070, -0x34a51500, 0x240a0001, 0xc002b17, 0xafaa005c, +0x8faa006c, 0x3c040001, 0x248468b8, 0x3c050007, +0xafaa0014, 0xafa20010, 0x8f460074, 0x8f470070, +0x34a51500, 0x240b0001, 0xc002b3b, 0xafab005c, 0x1000ffc3, 0x0, 0x8f430064, 0x8f420060, -0x1062001a, 0x274b0064, 0x8f5e0064, 0x8faa005c, -0xafab004c, 0x27c20001, 0x304200ff, 0xafa20054, -0x24020004, 0x1542000e, 0x1e1140, 0x1e1180, +0x1062001a, 0x274a0064, 0x8f5e0064, 0x8fab005c, +0xafaa004c, 0x27c20001, 0x304200ff, 0xafa20054, +0x24020004, 0x1562000e, 0x1e1140, 0x1e1180, 0x24420cc0, 0x2e21021, 0xafa20044, 0x9442002a, -0x8fab0044, 0x8faa006c, 0x4a102b, 0x10400024, -0x25750020, 0x240b0001, 0x10000021, 0xa3ab0097, +0x8faa0044, 0x8fab006c, 0x4b102b, 0x10400024, +0x25550020, 0x240a0001, 0x10000021, 0xa3aa0097, 0x24424cc0, 0x1000001e, 0x2e2a821, 0x8f420044, -0x8faa006c, 0x3c040001, 0x24846954, 0xafaa0014, +0x8fab006c, 0x3c040001, 0x248468c4, 0xafab0014, 0xafa20010, 0x8f460064, 0x8f470060, 0x3c050007, -0xc002b17, 0x34a51800, 0x3c020008, 0x2c21024, -0x1440ff34, 0x0, 0x8f420370, 0x240b0001, -0xafab005c, 0x24420001, 0xaf420370, 0x1000ff90, +0xc002b3b, 0x34a51800, 0x3c020008, 0x2c21024, +0x1440ff34, 0x0, 0x8f420370, 0x240a0001, +0xafaa005c, 0x24420001, 0xaf420370, 0x1000ff90, 0x8f420370, 0x27a30036, 0x131040, 0x621821, 0x94620000, 0x441021, 0x10000020, 0xa4620000, -0x8faa0064, 0xaeaa0018, 0x93a20097, 0x10400072, -0x9821, 0x8fab0044, 0x8fa4006c, 0x8fa300a4, -0x25620020, 0xafa20028, 0x25620008, 0xafa20030, -0x25620010, 0xafab002c, 0xafa20034, 0x9562002a, -0xa7a20038, 0x95620018, 0xa7a2003a, 0x9562001a, -0xa7a2003c, 0x9562001c, 0xa7a2003e, 0x94620018, +0x8fab0064, 0xaeab0018, 0x93a20097, 0x10400072, +0x9821, 0x8faa0044, 0x8fa4006c, 0x8fa300a4, +0x25420020, 0xafa20028, 0x25420008, 0xafa20030, +0x25420010, 0xafaa002c, 0xafa20034, 0x9542002a, +0xa7a20038, 0x95420018, 0xa7a2003a, 0x9542001a, +0xa7a2003c, 0x9542001c, 0xa7a2003e, 0x94620018, 0x24630002, 0x822023, 0x1880ffde, 0x26730001, 0x2e620004, 0x1440fff9, 0x0, 0x8f4200fc, 0x26650001, 0xa2102a, 0x1440002b, 0x24030001, @@ -6960,20 +6961,20 @@ 0x8f820128, 0x431023, 0x21943, 0x58600001, 0x24630040, 0x64102a, 0x54400001, 0x602021, 0xaf4400fc, 0x8f4200fc, 0xa2102a, 0x10400011, -0x24030001, 0x10000015, 0x306200ff, 0x8faa0064, -0x96070018, 0xafaa0010, 0x8e220008, 0x3c040001, -0x2484696c, 0x8c430004, 0x8c420000, 0x34a52400, -0x2403021, 0xc002b17, 0xafa30014, 0x1000002b, +0x24030001, 0x10000015, 0x306200ff, 0x8fab0064, +0x96070018, 0xafab0010, 0x8e220008, 0x3c040001, +0x248468dc, 0x8c430004, 0x8c420000, 0x34a52400, +0x2403021, 0xc002b3b, 0xafa30014, 0x1000002b, 0x0, 0x8f420334, 0x1821, 0x24420001, 0xaf420334, 0x8f420334, 0x306200ff, 0x5040fedc, 0x3c020800, 0x12600021, 0x9021, 0x8fb100a4, 0x2208021, 0x8e220008, 0x96070018, 0x8fa60064, -0x8c440000, 0x8c450004, 0x240b0001, 0xafab0010, +0x8c440000, 0x8c450004, 0x240a0001, 0xafaa0010, 0xafbe0014, 0x8f420008, 0xafa20018, 0x8f42010c, 0x40f809, 0x0, 0x1040ffd8, 0x3c050007, -0x96020018, 0x8faa0064, 0x8fab009c, 0x1425021, -0x16a102b, 0x10400004, 0xafaa0064, 0x8f420148, -0x1425023, 0xafaa0064, 0x26100002, 0x26520001, +0x96020018, 0x8fab0064, 0x8faa009c, 0x1625821, +0x14b102b, 0x10400004, 0xafab0064, 0x8f420148, +0x1625823, 0xafab0064, 0x26100002, 0x26520001, 0x253102b, 0x1440ffe3, 0x26310004, 0x8fb0006c, 0x10000036, 0x97b10038, 0x8f4200fc, 0x24050002, 0xa2102a, 0x1440001b, 0x24030001, 0x8f83012c, @@ -6986,42 +6987,42 @@ 0x8f420334, 0x306200ff, 0x1040fea5, 0x3c020800, 0x96b1000a, 0x8fb0006c, 0x3223ffff, 0x70102b, 0x54400001, 0x608021, 0x8ea40000, 0x8ea50004, -0x240a0001, 0xafaa0010, 0xafbe0014, 0x8f420008, +0x240b0001, 0xafab0010, 0xafbe0014, 0x8f420008, 0x8fa60064, 0xafa20018, 0x8f42010c, 0x40f809, 0x2003821, 0x1040fea2, 0x3c050007, 0x96a3000e, -0x97ab008e, 0x11600007, 0x609021, 0x934205c4, -0x14400004, 0x0, 0x97aa0086, 0x6b1825, -0xa6aa0016, 0x8fab007c, 0x3c02ffff, 0x1621024, -0x10400003, 0xb1402, 0x34630400, 0xa6a20014, -0x8faa006c, 0x560a0072, 0xa6a3000e, 0x34620004, -0xa6a2000e, 0x8fab0074, 0x14b1021, 0xa6a2000a, +0x97aa008e, 0x11400007, 0x609021, 0x934205c4, +0x14400004, 0x0, 0x97ab0086, 0x6a1825, +0xa6ab0016, 0x8faa007c, 0x3c02ffff, 0x1421024, +0x10400003, 0xa1402, 0x34630400, 0xa6a20014, +0x8fab006c, 0x560b0072, 0xa6a3000e, 0x34620004, +0xa6a2000e, 0x8faa0074, 0x16a1021, 0xa6a2000a, 0x8f430044, 0x8f4401a0, 0x8f4501a4, 0x34028000, 0xafa20010, 0x8f420044, 0x2a03021, 0x24070020, 0xafa20014, 0x8f42000c, 0x31940, 0x604821, 0xafa20018, 0x8f42010c, 0x4021, 0xa92821, 0xa9182b, 0x882021, 0x40f809, 0x832021, 0x5040fe7f, 0xa6b2000e, 0x8f420368, 0xafa0006c, -0xa34005c4, 0x2442ffff, 0xaf420368, 0x8faa005c, -0x240b0001, 0x8f420368, 0x154b0006, 0x24020002, +0xa34005c4, 0x2442ffff, 0xaf420368, 0x8fab005c, +0x240a0001, 0x8f420368, 0x156a0006, 0x240a0002, 0x8f42035c, 0x2442ffff, 0xaf42035c, 0x1000000c, -0x8f42035c, 0x15420006, 0x0, 0x8f420364, +0x8f42035c, 0x156a0006, 0x0, 0x8f420364, 0x2442ffff, 0xaf420364, 0x10000005, 0x8f420364, 0x8f420360, 0x2442ffff, 0xaf420360, 0x8f420360, 0x8faa0054, 0x8fab004c, 0xad6a0000, 0x8f420044, 0x8f440088, 0x8f430078, 0x24420001, 0x441024, 0x24630001, 0xaf420044, 0xaf430078, 0x8c020240, -0x62182b, 0x14600065, 0x24070008, 0x8f440168, +0x62182b, 0x14600075, 0x24070008, 0x8f440168, 0x8f45016c, 0x8f430044, 0x8f48000c, 0x8f860120, 0x24020040, 0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011, 0x240b0001, 0x3c010001, 0x370821, 0xa02b40f2, 0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001, -0x2484691c, 0xafa20014, 0x8f460044, 0x8f870120, -0x3c050009, 0xc002b17, 0x34a51300, 0x1000000b, +0x2484688c, 0xafa20014, 0x8f460044, 0x8f870120, +0x3c050009, 0xc002b3b, 0x34a51300, 0x1000000b, 0x0, 0x8f420304, 0x24420001, 0xaf420304, 0x8f420304, 0x8f420044, 0xaf42007c, 0x3c010001, 0x370821, 0xa02040f2, 0xaf400078, 0x8f420318, -0x24420001, 0xaf420318, 0x10000038, 0x8f420318, +0x24420001, 0xaf420318, 0x10000048, 0x8f420318, 0xa6b0000a, 0x8f430044, 0x8f4401a0, 0x8f4501a4, 0x34028000, 0xafa20010, 0x8f420044, 0x2a03021, 0x24070020, 0xafa20014, 0x8f42000c, 0x31940, @@ -7031,12 +7032,16 @@ 0x8fab006c, 0x8faa0064, 0x1705823, 0xafab006c, 0x8fab009c, 0x1505021, 0x16a102b, 0x10400004, 0xafaa0064, 0x8f420148, 0x1425023, 0xafaa0064, -0x8f420368, 0x2442ffff, 0xaf420368, 0x8f420368, -0x8f42035c, 0x2442ffff, 0xaf42035c, 0x8fab0054, -0x8faa004c, 0x8f42035c, 0xad4b0000, 0x8f420044, +0x8f420368, 0x2442ffff, 0xaf420368, 0x8faa005c, +0x240b0001, 0x8f420368, 0x154b0006, 0x240b0002, +0x8f42035c, 0x2442ffff, 0xaf42035c, 0x1000000c, +0x8f42035c, 0x114b0006, 0x0, 0x8f420360, +0x2442ffff, 0xaf420360, 0x10000005, 0x8f420360, +0x8f420364, 0x2442ffff, 0xaf420364, 0x8f420364, +0x8fab0054, 0x8faa004c, 0xad4b0000, 0x8f420044, 0x8f440088, 0x8f430078, 0x24420001, 0x441024, 0x24630001, 0xaf420044, 0xaf430078, 0x8faa006c, -0x1540fe1b, 0x0, 0x8fab006c, 0x1160001e, +0x1540fe0b, 0x0, 0x8fab006c, 0x1160001e, 0x0, 0x934205c4, 0x10400009, 0x0, 0x8faa0064, 0xaf4a00c4, 0xaf4b00c0, 0x8fab007c, 0xaf4b00c8, 0x8faa0074, 0x1000000e, 0xaf4a00cc, @@ -7063,7 +7068,7 @@ 0xafa20064, 0x3c020006, 0x2c21024, 0x14400015, 0xafac006c, 0x93c20000, 0x30420001, 0x10400011, 0x2402ffff, 0x8fc30000, 0x14620004, 0x3402ffff, -0x97c30004, 0x1062000b, 0x0, 0xc002497, +0x97c30004, 0x1062000b, 0x0, 0xc0024bb, 0x3c02021, 0x304200ff, 0x14400006, 0x0, 0x8f420118, 0x40f809, 0x0, 0x10000280, 0x0, 0x8fa20024, 0x3c03ffbf, 0x3463ffff, @@ -7088,9 +7093,9 @@ 0x4b102b, 0x10400015, 0x320200ff, 0x8f4201e8, 0x24420001, 0xaf4201e8, 0x8f4201e8, 0x8fac006c, 0x8f8200e0, 0x358c0100, 0xafac006c, 0xafa20010, -0x8f8200e4, 0x24100001, 0x3c040001, 0x24846930, +0x8f8200e4, 0x24100001, 0x3c040001, 0x248468a0, 0xafa20014, 0x8fa60020, 0x8fa70024, 0x3c050007, -0xc002b17, 0x34a53600, 0x320200ff, 0x10400010, +0xc002b3b, 0x34a53600, 0x320200ff, 0x10400010, 0x3c020080, 0x2c21024, 0x1440000e, 0x32c20400, 0x8fab006c, 0x3c020080, 0x34420100, 0x1621024, 0x10400005, 0x0, 0x8f42020c, 0x24420001, @@ -7115,8 +7120,8 @@ 0x2c420001, 0x621825, 0x10600004, 0x3c020100, 0x94820002, 0x453821, 0x3c020100, 0x2c21024, 0x5040000e, 0xafa70064, 0x8fac0064, 0x10ec0008, -0x3c050007, 0x3c040001, 0x24846998, 0x8fa60064, -0x34a54000, 0xafa00010, 0xc002b17, 0xafa00014, +0x3c050007, 0x3c040001, 0x24846908, 0x8fa60064, +0x34a54000, 0xafa00010, 0xc002b3b, 0xafa00014, 0x8fab0064, 0x256b0004, 0xafab0064, 0x8f420080, 0x8fac0064, 0x4c102b, 0x1040002c, 0x32c28000, 0x10400034, 0x240b0003, 0x32c21000, 0x10400031, @@ -7124,11 +7129,11 @@ 0x2403ffbf, 0x283a024, 0x24420001, 0xaf420350, 0x10000173, 0x8f420350, 0x3c020800, 0x2c2b025, 0x2402ffbf, 0x282a024, 0x8f830128, 0x3c040001, -0x24846960, 0x26620001, 0xafa20014, 0xafa30010, -0x8f860120, 0x8f870124, 0x3c050007, 0xc002b17, +0x248468d0, 0x26620001, 0xafa20014, 0xafa30010, +0x8f860120, 0x8f870124, 0x3c050007, 0xc002b3b, 0x34a55300, 0x10000162, 0x0, 0x8ea20000, -0x8ea30004, 0x3c040001, 0x24846978, 0xafb00010, -0xafb10014, 0x8ea70018, 0x34a55900, 0xc002b17, +0x8ea30004, 0x3c040001, 0x248468e8, 0xafb00010, +0xafb10014, 0x8ea70018, 0x34a55900, 0xc002b3b, 0x603021, 0x10000156, 0x0, 0x8f420084, 0x8fab0064, 0x4b102b, 0x14400007, 0x3c020001, 0x2c21024, 0x10400004, 0x0, 0x240c0002, @@ -7138,17 +7143,17 @@ 0x274b0054, 0x8f510054, 0x3403ecc0, 0xafab004c, 0x26220001, 0x304201ff, 0xafa20054, 0x111140, 0x431021, 0x1000006b, 0x2e2a821, 0x8f420044, -0x8fac0064, 0x3c040001, 0x2484693c, 0xafac0014, +0x8fac0064, 0x3c040001, 0x248468ac, 0xafac0014, 0xafa20010, 0x8f460054, 0x8f470050, 0x3c050007, -0xc002b17, 0x34a54300, 0x8f430350, 0x2402ffbf, +0xc002b3b, 0x34a54300, 0x8f430350, 0x2402ffbf, 0x282a024, 0x24630001, 0xaf430350, 0x10000124, 0x8f420350, 0x156c001d, 0x0, 0x8f430074, 0x8f420070, 0x1062000a, 0x274b0074, 0x8f510074, 0xafab004c, 0x26220001, 0x304203ff, 0xafa20054, 0x111140, 0x24426cc0, 0x1000004a, 0x2e2a821, -0x8f420044, 0x8fac0064, 0x3c040001, 0x24846948, +0x8f420044, 0x8fac0064, 0x3c040001, 0x248468b8, 0x3c050007, 0xafac0014, 0xafa20010, 0x8f460074, -0x8f470070, 0x34a54500, 0x240b0001, 0xc002b17, +0x8f470070, 0x34a54500, 0x240b0001, 0xc002b3b, 0xafab005c, 0x1000ffc3, 0x0, 0x8f430064, 0x8f420060, 0x1062001a, 0x274c0064, 0x8f510064, 0x8fab005c, 0xafac004c, 0x26220001, 0x304200ff, @@ -7157,9 +7162,9 @@ 0x9442002a, 0x8fac0044, 0x8fab0064, 0x4b102b, 0x10400024, 0x25950020, 0x240c0001, 0x10000021, 0xa3ac0087, 0x24424cc0, 0x1000001e, 0x2e2a821, -0x8f420044, 0x8fab0064, 0x3c040001, 0x24846954, +0x8f420044, 0x8fab0064, 0x3c040001, 0x248468c4, 0xafab0014, 0xafa20010, 0x8f460064, 0x8f470060, -0x3c050007, 0xc002b17, 0x34a54800, 0x3c020008, +0x3c050007, 0xc002b3b, 0x34a54800, 0x3c020008, 0x2c21024, 0x1440ff61, 0x0, 0x8f420370, 0x240c0001, 0xafac005c, 0x24420001, 0xaf420370, 0x1000ff90, 0x8f420370, 0x27a30036, 0x131040, @@ -7180,9 +7185,9 @@ 0x8f4200fc, 0x262102a, 0x10400016, 0x24030001, 0x1000001a, 0x306200ff, 0x8fac008c, 0x101040, 0x4c1021, 0x94470018, 0x101080, 0x4c1021, -0xafbe0010, 0x8c420008, 0x3c040001, 0x2484696c, +0xafbe0010, 0x8c420008, 0x3c040001, 0x248468dc, 0x3c050007, 0x8c430004, 0x8c420000, 0x34a55500, -0x2003021, 0xc002b17, 0xafa30014, 0x10000039, +0x2003021, 0xc002b3b, 0xafa30014, 0x10000039, 0x0, 0x8f420334, 0x1821, 0x24420001, 0xaf420334, 0x8f420334, 0x306200ff, 0x1040ff06, 0x8021, 0x8f430008, 0x2402fbff, 0x1260002d, @@ -7399,7 +7404,7 @@ 0x822023, 0x94820000, 0x2028021, 0x3c020100, 0x2c21024, 0x1040000e, 0x0, 0x8faa002c, 0x31420004, 0x1040000a, 0x0, 0x9504000e, -0x2642021, 0xc003ec4, 0x2484fffc, 0x3042ffff, +0x2642021, 0xc003eec, 0x2484fffc, 0x3042ffff, 0x2228821, 0x111c02, 0x3222ffff, 0x628821, 0x8faa0024, 0x1518823, 0x111402, 0x2228821, 0x2308821, 0x111402, 0x2228821, 0x3231ffff, @@ -7412,8 +7417,8 @@ 0xafa80018, 0x8f48010c, 0x1021, 0xa32821, 0xa3482b, 0x822021, 0x100f809, 0x892021, 0x1440000b, 0x0, 0x8f820128, 0x3c040001, -0x248469a4, 0xafbe0014, 0xafa20010, 0x8f860124, -0x8f870120, 0x3c050007, 0xc002b17, 0x34a59920, +0x24846914, 0xafbe0014, 0xafa20010, 0x8f860124, +0x8f870120, 0x3c050007, 0xc002b3b, 0x34a59920, 0x8f420368, 0x2442ffff, 0xaf420368, 0x8f420044, 0x8f430088, 0x24420001, 0x431024, 0xaf420044, 0x8faa0034, 0x8f440368, 0x24020001, 0x15420006, @@ -7430,9 +7435,9 @@ 0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011, 0x24020001, 0x3c010001, 0x370821, 0xa02240f2, 0x8f820124, -0xafa20010, 0x8f820128, 0x3c040001, 0x2484691c, +0xafa20010, 0x8f820128, 0x3c040001, 0x2484688c, 0xafa20014, 0x8f460044, 0x8f870120, 0x3c050009, -0xc002b17, 0x34a51300, 0x1000000b, 0x0, +0xc002b3b, 0x34a51300, 0x1000000b, 0x0, 0x8f420304, 0x24420001, 0xaf420304, 0x8f420304, 0x8f420044, 0xaf42007c, 0x3c010001, 0x370821, 0xa02040f2, 0xaf400078, 0x8f420318, 0x24420001, @@ -7444,32 +7449,32 @@ 0xaf8200c8, 0x8f420138, 0xaf8200d0, 0x8f420138, 0xaf8200d4, 0x8f420138, 0x3e00008, 0xaf8200d8, 0x27bdffe0, 0x27840208, 0x24050200, 0xafbf0018, -0xc002b9b, 0x24060008, 0x8c020204, 0xc003fea, -0xaf820210, 0x3c020001, 0x8c426e14, 0x30420002, +0xc002bbf, 0x24060008, 0x8c020204, 0xc004012, +0xaf820210, 0x3c020001, 0x8c426d94, 0x30420002, 0x1040000e, 0x2021, 0x8c060248, 0x24020002, -0x3c010001, 0xac226e18, 0xc005134, 0x24050002, +0x3c010001, 0xac226d98, 0xc005104, 0x24050002, 0x2021, 0x8c060248, 0x24020001, 0x3c010001, -0xac226e18, 0x10000011, 0x24050001, 0x8c060248, -0x24020004, 0x3c010001, 0xac226e18, 0xc005134, -0x24050004, 0x3c020001, 0x8c426e14, 0x30420001, -0x10400008, 0x24020001, 0x3c010001, 0xac226e18, -0x2021, 0x24050001, 0x3c06601b, 0xc005134, -0x0, 0x3c040001, 0x24846a60, 0x8f420150, +0xac226d98, 0x10000011, 0x24050001, 0x8c060248, +0x24020004, 0x3c010001, 0xac226d98, 0xc005104, +0x24050004, 0x3c020001, 0x8c426d94, 0x30420001, +0x10400008, 0x24020001, 0x3c010001, 0xac226d98, +0x2021, 0x24050001, 0x3c06601b, 0xc005104, +0x0, 0x3c040001, 0x248469d0, 0x8f420150, 0x8f430154, 0x3c050008, 0x8f460158, 0x21640, 0x31940, 0x34630403, 0x431025, 0x633c0, 0x461025, 0xaf82021c, 0xafa00010, 0xafa00014, -0x8f86021c, 0x34a50200, 0xc002b17, 0x3821, -0x3c010001, 0xac206e10, 0x3c010001, 0xac206e28, +0x8f86021c, 0x34a50200, 0xc002b3b, 0x3821, +0x3c010001, 0xac206d90, 0x3c010001, 0xac206da8, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x27bdffe0, 0x3c050008, 0x34a50300, 0xafbf0018, 0xafa00010, -0xafa00014, 0x8f860200, 0x3c040001, 0x24846a6c, -0xc002b17, 0x3821, 0x8f420410, 0x24420001, +0xafa00014, 0x8f860200, 0x3c040001, 0x248469dc, +0xc002b3b, 0x3821, 0x8f420410, 0x24420001, 0xaf420410, 0x8f420410, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x27bdffd8, 0xafbf0020, 0xafb1001c, 0xafb00018, 0x8f4203a4, 0x24420001, 0xaf4203a4, 0x8f4203a4, 0x8f900220, 0x8f8200e0, 0xafa20010, 0x8f8200e4, 0xafa20014, 0x8f8600c4, 0x8f8700c8, -0x3c040001, 0x24846a78, 0xc002b17, 0x2002821, +0x3c040001, 0x248469e8, 0xc002b3b, 0x2002821, 0x3c044000, 0x2041024, 0x504000b4, 0x3c040100, 0x8f4203bc, 0x24420001, 0xaf4203bc, 0x8f4203bc, 0x8f8700c4, 0x8f8300c8, 0x8f420148, 0x671823, @@ -7518,26 +7523,26 @@ 0xaf4303cc, 0x10000039, 0x8f4203cc, 0x2041024, 0x1040000e, 0x3c110200, 0x8f4203a8, 0x24420001, 0xaf4203a8, 0x8f4203a8, 0x8f820220, 0x3c0308ff, -0x3463ffff, 0x431024, 0x441025, 0xc003d87, +0x3463ffff, 0x431024, 0x441025, 0xc003daf, 0xaf820220, 0x10000029, 0x0, 0x2111024, 0x50400008, 0x3c110400, 0x8f4203ac, 0x24420001, -0xaf4203ac, 0xc003d87, 0x8f4203ac, 0x10000019, +0xaf4203ac, 0xc003daf, 0x8f4203ac, 0x10000019, 0x0, 0x2111024, 0x1040001c, 0x0, 0x8f830224, 0x24021402, 0x14620009, 0x3c050008, -0x3c040001, 0x24846a84, 0xafa00010, 0xafa00014, -0x8f860224, 0x34a50500, 0xc002b17, 0x3821, +0x3c040001, 0x248469f4, 0xafa00010, 0xafa00014, +0x8f860224, 0x34a50500, 0xc002b3b, 0x3821, 0x8f4203b0, 0x24420001, 0xaf4203b0, 0x8f4203b0, -0x8f820220, 0x2002021, 0x34420002, 0xc004ecc, +0x8f820220, 0x2002021, 0x34420002, 0xc004e9c, 0xaf820220, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x511025, 0xaf820220, 0x8fbf0020, 0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0028, -0x3e00008, 0x0, 0x3c020001, 0x8c426e28, +0x3e00008, 0x0, 0x3c020001, 0x8c426da8, 0x27bdffb0, 0xafbf0048, 0xafbe0044, 0xafb50040, 0xafb3003c, 0xafb20038, 0xafb10034, 0x1040000f, -0xafb00030, 0x3c040001, 0x24846a90, 0x3c050008, +0xafb00030, 0x3c040001, 0x24846a00, 0x3c050008, 0xafa00010, 0xafa00014, 0x8f860220, 0x34a50600, -0x24020001, 0x3c010001, 0xac206e28, 0x3c010001, -0xac226e1c, 0xc002b17, 0x3821, 0x3c037fff, +0x24020001, 0x3c010001, 0xac206da8, 0x3c010001, +0xac226d9c, 0xc002b3b, 0x3821, 0x3c037fff, 0x8c020268, 0x3463ffff, 0x3c04fdff, 0x431024, 0xac020268, 0x8f420004, 0x3484ffff, 0x30420002, 0x10400092, 0x284a024, 0x3c040600, 0x34842000, @@ -7546,7 +7551,7 @@ 0x240200ff, 0x13c20002, 0xafaa002c, 0x27c50001, 0x8c020228, 0xa09021, 0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, -0x8c020228, 0x3c040001, 0x24846a28, 0x3c050009, +0x8c020228, 0x3c040001, 0x24846998, 0x3c050009, 0xafa00014, 0xafa20010, 0x8fa60020, 0x1000006d, 0x34a50500, 0xf71021, 0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054, @@ -7560,7 +7565,7 @@ 0x2c4203e9, 0x1440ffe9, 0x0, 0x326200ff, 0x54400017, 0xaf520018, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, -0xafa20010, 0x8f820124, 0x3c040001, 0x24846a34, +0xafa20010, 0x8f820124, 0x3c040001, 0x248469a4, 0x3c050009, 0xafa20014, 0x8d460000, 0x10000035, 0x34a50600, 0x8f420308, 0x24130001, 0x24420001, 0xaf420308, 0x8f420308, 0x1000001e, 0x326200ff, @@ -7574,21 +7579,21 @@ 0x326200ff, 0x14400011, 0x0, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010, 0x8f820124, 0x3c040001, -0x24846a3c, 0x3c050009, 0xafa20014, 0x8d460000, -0x34a50700, 0xc002b17, 0x3c03821, 0x8f4202ec, +0x248469ac, 0x3c050009, 0xafa20014, 0x8d460000, +0x34a50700, 0xc002b3b, 0x3c03821, 0x8f4202ec, 0x24420001, 0xaf4202ec, 0x8f4202ec, 0x8fbf0048, 0x8fbe0044, 0x8fb50040, 0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008, 0x27bd0050, -0x3c020001, 0x8c426e28, 0x27bdffe0, 0x1440000d, -0xafbf0018, 0x3c040001, 0x24846a9c, 0x3c050008, +0x3c020001, 0x8c426da8, 0x27bdffe0, 0x1440000d, +0xafbf0018, 0x3c040001, 0x24846a0c, 0x3c050008, 0xafa00010, 0xafa00014, 0x8f860220, 0x34a50700, -0x24020001, 0x3c010001, 0xac226e28, 0xc002b17, +0x24020001, 0x3c010001, 0xac226da8, 0xc002b3b, 0x3821, 0x3c020004, 0x2c21024, 0x10400007, 0x0, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x34420008, 0xaf820220, 0x3c050001, -0x8ca56e18, 0x24020001, 0x14a20007, 0x2021, -0xc0052c7, 0x24050001, 0xac02026c, 0x8c03026c, -0x10000006, 0x3c020007, 0xc0052c7, 0x2021, +0x8ca56d98, 0x24020001, 0x14a20007, 0x2021, +0xc00529b, 0x24050001, 0xac02026c, 0x8c03026c, +0x10000006, 0x3c020007, 0xc00529b, 0x2021, 0xac020268, 0x8c030268, 0x3c020007, 0x621824, 0x3c020002, 0x5062000d, 0x3c0205f5, 0x43102b, 0x14400006, 0x3c020004, 0x3c020001, 0x10620009, @@ -7636,7 +7641,7 @@ 0x90a20000, 0x822021, 0x41c02, 0x3082ffff, 0x622021, 0x41c02, 0x3082ffff, 0x622021, 0x3e00008, 0x3082ffff, 0x0, 0x8f820220, -0x34420002, 0xaf820220, 0x3c020002, 0x8c429078, +0x34420002, 0xaf820220, 0x3c020002, 0x8c428ff8, 0x30424000, 0x10400054, 0x24040001, 0x8f820200, 0x24067fff, 0x8f830200, 0x30450002, 0x2402fffd, 0x621824, 0xaf830200, 0xaf840204, 0x8f830054, @@ -7683,1091 +7688,1069 @@ 0x43102b, 0x14400006, 0x3c026000, 0x3c024000, 0x10620008, 0x24020800, 0x10000008, 0x0, 0x10620004, 0x24020800, 0x10000004, 0x0, -0x24020700, 0x3c010001, 0xac226e2c, 0x3e00008, -0x0, 0x3c020001, 0x8c426e3c, 0x27bdffc8, -0xafbf0034, 0xafb20030, 0xafb1002c, 0xafb00028, -0x3c010001, 0x10400005, 0xac206e14, 0xc004dd1, -0x0, 0x3c010001, 0xac206e3c, 0x8f830054, +0x24020700, 0x3c010001, 0xac226dac, 0x3e00008, +0x0, 0x3c020001, 0x8c426dbc, 0x27bdffd0, +0xafbf002c, 0xafb20028, 0xafb10024, 0xafb00020, +0x3c010001, 0x10400005, 0xac206d94, 0xc004d9e, +0x0, 0x3c010001, 0xac206dbc, 0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 0x0, -0xc004dec, 0x0, 0x24040001, 0x2821, -0x27a60020, 0x34028000, 0xc00450e, 0xa7a20020, +0xc004db9, 0x0, 0x24040001, 0x2821, +0x27a60018, 0x34028000, 0xc0045be, 0xa7a20018, 0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, -0x24040001, 0x24050001, 0xc0044cc, 0x27a60020, +0x24040001, 0x24050001, 0xc00457c, 0x27a60018, 0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, -0x24040001, 0x24050001, 0xc0044cc, 0x27a60020, +0x24040001, 0x24050001, 0xc00457c, 0x27a60018, 0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, -0x24040001, 0x24050002, 0xc0044cc, 0x27a60018, -0x8f830054, 0x8f820054, 0x10000002, 0x24630064, -0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, -0x24040001, 0x24050003, 0xc0044cc, 0x27a6001a, -0x3c040001, 0x24846b70, 0x97a60020, 0x97a70018, -0x97a2001a, 0x3c05000d, 0x34a50100, 0xafa00014, -0xc002b17, 0xafa20010, 0x97a20020, 0x10400046, -0x24036040, 0x97a2001a, 0x3042fff0, 0x1443000b, -0x24020020, 0x97a30018, 0x1462000a, 0x24027830, -0x24020003, 0x3c010001, 0xac226e14, 0x24020005, -0x3c010001, 0x10000039, 0xac226fac, 0x97a30018, -0x24027830, 0x1462000b, 0x24030010, 0x97a2001a, -0x3042fff0, 0x14430007, 0x24020003, 0x3c010001, -0xac226e14, 0x24020006, 0x3c010001, 0x1000002b, -0xac226fac, 0x3c020001, 0x8c426e14, 0x97a30018, -0x34420001, 0x3c010001, 0xac226e14, 0x24020015, -0x1462000a, 0x0, 0x97a2001a, 0x3042fff0, -0x3843f420, 0x2c630001, 0x3842f430, 0x2c420001, -0x621825, 0x14600019, 0x24020003, 0x97a30018, -0x24027810, 0x14620015, 0x24020002, 0x97a2001a, -0x3042fff0, 0x14400011, 0x24020002, 0x1000000f, -0x24020004, 0x3c020001, 0x8c426e14, 0x34420008, -0x3c010001, 0xac226e14, 0x1000005e, 0x24020004, -0x3c020001, 0x8c426e14, 0x34420004, 0x3c010001, -0x100000af, 0xac226e14, 0x24020001, 0x3c010001, -0xac226fb8, 0x3c020001, 0x8c426e14, 0x30420002, -0x144000b2, 0x3c09fff0, 0x24020e00, 0xaf820238, -0x8f840054, 0x8f820054, 0x24030008, 0x3c010001, -0xac236e18, 0x10000002, 0x248401f4, 0x8f820054, -0x821023, 0x2c4201f5, 0x1440fffc, 0x3c0200c8, -0x344201fb, 0xaf820238, 0x8f830054, 0x8f820054, -0x10000002, 0x246301f4, 0x8f820054, 0x621023, -0x2c4201f5, 0x1440fffc, 0x8021, 0x24120001, -0x24110009, 0xc0043d3, 0x0, 0x3c010001, -0xac326e34, 0xc004498, 0x0, 0x3c020001, -0x8c426e34, 0x1451fffb, 0x3c0200c8, 0x344201f6, +0x24040001, 0x3c060001, 0x24c66f24, 0xc00457c, +0x24050002, 0x8f830054, 0x8f820054, 0x10000002, +0x24630064, 0x8f820054, 0x621023, 0x2c420065, +0x1440fffc, 0x24040001, 0x24050003, 0x3c100001, +0x26106f26, 0xc00457c, 0x2003021, 0x97a60018, +0x3c070001, 0x94e76f24, 0x3c040001, 0x24846ae0, +0xafa00014, 0x96020000, 0x3c05000d, 0x34a50100, +0xc002b3b, 0xafa20010, 0x97a20018, 0x1040004d, +0x24036040, 0x96020000, 0x3042fff0, 0x1443000c, +0x24020020, 0x3c030001, 0x94636f24, 0x1462000b, +0x24027830, 0x24020003, 0x3c010001, 0xac226d94, +0x24020005, 0x3c010001, 0x1000003f, 0xac226f34, +0x3c030001, 0x94636f24, 0x24027830, 0x1462000c, +0x24030010, 0x3c020001, 0x94426f26, 0x3042fff0, +0x14430007, 0x24020003, 0x3c010001, 0xac226d94, +0x24020006, 0x3c010001, 0x1000002f, 0xac226f34, +0x3c020001, 0x8c426d94, 0x3c030001, 0x94636f24, +0x34420001, 0x3c010001, 0xac226d94, 0x24020015, +0x1462000b, 0x0, 0x3c020001, 0x94426f26, +0x3042fff0, 0x3843f420, 0x2c630001, 0x3842f430, +0x2c420001, 0x621825, 0x1460001b, 0x24020003, +0x3c030001, 0x94636f24, 0x24027810, 0x14620016, +0x24020002, 0x3c020001, 0x94426f26, 0x3042fff0, +0x14400011, 0x24020002, 0x1000000f, 0x24020004, +0x3c020001, 0x8c426d94, 0x34420008, 0x3c010001, +0xac226d94, 0x1000005e, 0x24020004, 0x3c020001, +0x8c426d94, 0x34420004, 0x3c010001, 0x100000af, +0xac226d94, 0x24020001, 0x3c010001, 0xac226f40, +0x3c020001, 0x8c426d94, 0x30420002, 0x144000b2, +0x3c09fff0, 0x24020e00, 0xaf820238, 0x8f840054, +0x8f820054, 0x24030008, 0x3c010001, 0xac236d98, +0x10000002, 0x248401f4, 0x8f820054, 0x821023, +0x2c4201f5, 0x1440fffc, 0x3c0200c8, 0x344201fb, 0xaf820238, 0x8f830054, 0x8f820054, 0x10000002, -0x2463000a, 0x8f820054, 0x621023, 0x2c42000b, -0x1440fffc, 0x0, 0x8f820220, 0x24040001, -0x34420002, 0xaf820220, 0x8f830200, 0x24057fff, -0x2402fffd, 0x621824, 0xaf830200, 0xaf840204, -0x8f830054, 0x8f820054, 0x10000002, 0x24630001, -0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, -0x0, 0x8f820224, 0x14440005, 0x34028000, -0x42040, 0xa4102b, 0x1040fff0, 0x34028000, -0x1082ffa0, 0x26100001, 0x2e020014, 0x1440ffcd, -0x24020004, 0x3c010001, 0xac226e18, 0x8021, -0x24120009, 0x3c11ffff, 0x36313f7f, 0xc0043d3, -0x0, 0x24020001, 0x3c010001, 0xac226e34, -0xc004498, 0x0, 0x3c020001, 0x8c426e34, -0x1452fffb, 0x0, 0x8f820044, 0x511024, -0x34425080, 0xaf820044, 0x8f830054, 0x8f820054, -0x10000002, 0x2463000a, 0x8f820054, 0x621023, -0x2c42000b, 0x1440fffc, 0x0, 0x8f820044, -0x511024, 0x3442f080, 0xaf820044, 0x8f830054, -0x8f820054, 0x10000002, 0x2463000a, 0x8f820054, -0x621023, 0x2c42000b, 0x1440fffc, 0x0, -0x8f820220, 0x3c03f700, 0x431025, 0xaf820220, -0x8f830054, 0x8f820054, 0x10000002, 0x24630064, -0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, +0x246301f4, 0x8f820054, 0x621023, 0x2c4201f5, +0x1440fffc, 0x8021, 0x24120001, 0x24110009, +0xc004482, 0x0, 0x3c010001, 0xac326db4, +0xc004547, 0x0, 0x3c020001, 0x8c426db4, +0x1451fffb, 0x3c0200c8, 0x344201f6, 0xaf820238, +0x8f830054, 0x8f820054, 0x10000002, 0x2463000a, +0x8f820054, 0x621023, 0x2c42000b, 0x1440fffc, 0x0, 0x8f820220, 0x24040001, 0x34420002, 0xaf820220, 0x8f830200, 0x24057fff, 0x2402fffd, 0x621824, 0xaf830200, 0xaf840204, 0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820224, 0x14440005, 0x34028000, 0x42040, -0xa4102b, 0x1040fff0, 0x34028000, 0x1082ff50, -0x26100001, 0x2e020064, 0x1440ffb0, 0x0, -0x3c020001, 0x8c426e14, 0x30420004, 0x14400007, -0x3c09fff0, 0x8f820044, 0x3c03ffff, 0x34633f7f, -0x431024, 0xaf820044, 0x3c09fff0, 0x3529bdc0, -0x8f830054, 0x3c060001, 0x8cc66e14, 0x3c070001, -0x8ce76fb8, 0x97a80018, 0x3c040001, 0x24846b70, -0x24020001, 0x3c010001, 0xac226e1c, 0xafa80010, -0x97a2001a, 0x3c05000d, 0x34a50100, 0x3c010001, -0xac206e18, 0x691821, 0x3c010001, 0xac236fa8, -0xc002b17, 0xafa20014, 0x8fbf0034, 0x8fb20030, -0x8fb1002c, 0x8fb00028, 0x3e00008, 0x27bd0038, -0x27bdffe8, 0x3c050001, 0x8ca56e18, 0x24060004, -0x24020001, 0x14a20014, 0xafbf0010, 0x3c020002, -0x8c42907c, 0x30428000, 0x10400005, 0x3c04000f, -0x3c030001, 0x8c636fb8, 0x10000005, 0x34844240, -0x3c040004, 0x3c030001, 0x8c636fb8, 0x348493e0, -0x24020005, 0x14620016, 0x0, 0x3c04003d, -0x10000013, 0x34840900, 0x3c020002, 0x8c429078, -0x30428000, 0x10400005, 0x3c04001e, 0x3c030001, -0x8c636fb8, 0x10000005, 0x34848480, 0x3c04000f, -0x3c030001, 0x8c636fb8, 0x34844240, 0x24020005, -0x14620003, 0x0, 0x3c04007a, 0x34841200, -0x3c020001, 0x8c426fa8, 0x8f830054, 0x441021, -0x431023, 0x44102b, 0x1440004b, 0x0, -0x3c020001, 0x8c426e20, 0x14400047, 0x0, -0x3c010001, 0x10c00025, 0xac206e30, 0x3c090001, -0x8d296e14, 0x24070001, 0x3c044000, 0x3c080002, -0x2508907c, 0x250afffc, 0x52842, 0x14a00002, -0x24c6ffff, 0x24050008, 0xa91024, 0x10400010, -0x0, 0x14a70008, 0x0, 0x8d020000, -0x441024, 0x1040000a, 0x0, 0x3c010001, -0x10000007, 0xac256e30, 0x8d420000, 0x441024, -0x10400003, 0x0, 0x3c010001, 0xac276e30, -0x3c020001, 0x8c426e30, 0x6182b, 0x2c420001, -0x431024, 0x5440ffe5, 0x52842, 0x8f820054, -0x3c030001, 0x8c636e30, 0x3c010001, 0xac226fa8, -0x1060003a, 0x24020005, 0x3c030001, 0x8c636fb8, -0x3c010001, 0xac256e18, 0x14620011, 0x24020001, -0x3c020002, 0x8c429078, 0x3c032000, 0x431024, -0x14400006, 0x24020001, 0x3c010001, 0xac206f98, -0x3c010001, 0xac226e18, 0x24020001, 0x3c010001, -0xac226ea4, 0x3c010001, 0xac226e24, 0x24020001, -0x3c010001, 0xac226e1c, 0x3c020001, 0x8c426e30, -0x1040001e, 0x0, 0x3c020001, 0x8c426e1c, -0x10400008, 0x24020001, 0x3c010001, 0xac206e1c, -0xaee204b8, 0x3c010001, 0xac206e9c, 0x3c010001, -0xac226e54, 0x8ee304b8, 0x24020008, 0x10620005, -0x24020001, 0xc004203, 0x0, 0x1000000b, -0x0, 0x3c030001, 0x8c636e18, 0x10620007, -0x2402000e, 0x3c030002, 0x8c639010, 0x10620003, -0x0, 0xc004ecc, 0x8f840220, 0x8fbf0010, -0x3e00008, 0x27bd0018, 0x27bdffe0, 0x3c03fdff, -0x3c040001, 0x8c846e18, 0x3c020001, 0x8c426e40, -0x3463ffff, 0x283a024, 0xafbf001c, 0x14820006, -0xafb00018, 0x8ee304b8, 0x3c020001, 0x8c426e44, -0x10620006, 0x0, 0x8ee204b8, 0x3c010001, -0xac246e40, 0x3c010001, 0xac226e44, 0x3c030001, -0x8c636e18, 0x24020002, 0x10620167, 0x2c620003, -0x10400005, 0x24020001, 0x1062000a, 0x0, -0x100001ab, 0x0, 0x24020004, 0x10620081, -0x24020008, 0x106200d5, 0x24020001, 0x100001a4, -0x0, 0x8ee204b8, 0x2443ffff, 0x2c620008, -0x104001a1, 0x31080, 0x3c010001, 0x220821, -0x8c226b88, 0x400008, 0x0, 0x3c030001, -0x8c636fb8, 0x24020005, 0x14620010, 0x0, -0x3c020001, 0x8c426e24, 0x10400008, 0x24020003, -0xc0043d3, 0x0, 0x24020002, 0xaee204b8, -0x3c010001, 0x10000002, 0xac206e24, 0xaee204b8, -0x3c010001, 0x10000188, 0xac206db0, 0xc0043d3, -0x0, 0x3c020001, 0x8c426e24, 0x3c010001, -0xac206db0, 0x14400145, 0x24020002, 0x10000163, -0x24020007, 0x24020001, 0x3c010001, 0xc00454f, -0xac226e50, 0x3c030001, 0x8c636e50, 0x10000144, -0x24020011, 0x3c020001, 0x8c426fb8, 0x24100005, -0x10500007, 0x0, 0x3c050001, 0x8ca56e18, -0x3c060002, 0x8cc6907c, 0xc005134, 0x2021, -0x3c010001, 0xac206e24, 0x10000167, 0xaef004b8, -0x3c040001, 0x24846b7c, 0x3c05000f, 0x34a50100, -0x3021, 0x3821, 0xafa00010, 0xc002b17, -0xafa00014, 0x1000015c, 0x0, 0x8f820220, -0x3c030004, 0x431024, 0x1440013c, 0x24020007, -0x8f830054, 0x3c020001, 0x8c426fa0, 0x2463d8f0, -0x431023, 0x2c422710, 0x1440014f, 0x24020001, -0x1000014b, 0x0, 0x3c050001, 0x8ca56e18, -0xc0052c7, 0x2021, 0xc00553d, 0x2021, -0x3c030002, 0x8c639074, 0x4610141, 0x24020001, -0x3c020008, 0x621024, 0x10400006, 0x0, -0x8f820214, 0x3c03ffff, 0x431024, 0x10000005, -0x3442251f, 0x8f820214, 0x3c03ffff, 0x431024, -0x3442241f, 0xaf820214, 0x8f820220, 0x3c030200, -0x283a025, 0x34420002, 0xaf820220, 0x24020008, -0xc003e45, 0xaee204b8, 0x3c010001, 0x1000012a, -0xac206ea0, 0x8ee204b8, 0x2443ffff, 0x2c620008, -0x10400125, 0x31080, 0x3c010001, 0x220821, -0x8c226ba8, 0x400008, 0x0, 0xc004498, -0x0, 0x3c030001, 0x8c636e34, 0x100000e8, -0x24020009, 0x3c020002, 0x8c429078, 0x30424000, -0x10400004, 0x0, 0x8f820044, 0x10000006, -0x3442f080, 0x8f820044, 0x3c03ffff, 0x34633f7f, -0x431024, 0x3442a080, 0xaf820044, 0x8f830054, -0x100000ea, 0x24020004, 0x8f830054, 0x3c020001, -0x8c426fa0, 0x2463d8f0, 0x431023, 0x2c422710, -0x14400101, 0x24020005, 0x100000d8, 0x0, +0xa4102b, 0x1040fff0, 0x34028000, 0x1082ffa0, +0x26100001, 0x2e020014, 0x1440ffcd, 0x24020004, +0x3c010001, 0xac226d98, 0x8021, 0x24120009, +0x3c11ffff, 0x36313f7f, 0xc004482, 0x0, +0x24020001, 0x3c010001, 0xac226db4, 0xc004547, +0x0, 0x3c020001, 0x8c426db4, 0x1452fffb, +0x0, 0x8f820044, 0x511024, 0x34425080, +0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, +0x2463000a, 0x8f820054, 0x621023, 0x2c42000b, +0x1440fffc, 0x0, 0x8f820044, 0x511024, +0x3442f080, 0xaf820044, 0x8f830054, 0x8f820054, +0x10000002, 0x2463000a, 0x8f820054, 0x621023, +0x2c42000b, 0x1440fffc, 0x0, 0x8f820220, +0x3c03f700, 0x431025, 0xaf820220, 0x8f830054, +0x8f820054, 0x10000002, 0x24630064, 0x8f820054, +0x621023, 0x2c420065, 0x1440fffc, 0x0, +0x8f820220, 0x24040001, 0x34420002, 0xaf820220, +0x8f830200, 0x24057fff, 0x2402fffd, 0x621824, +0xaf830200, 0xaf840204, 0x8f830054, 0x8f820054, +0x10000002, 0x24630001, 0x8f820054, 0x621023, +0x2c420002, 0x1440fffc, 0x0, 0x8f820224, +0x14440005, 0x34028000, 0x42040, 0xa4102b, +0x1040fff0, 0x34028000, 0x1082ff50, 0x26100001, +0x2e020064, 0x1440ffb0, 0x0, 0x3c020001, +0x8c426d94, 0x30420004, 0x14400007, 0x3c09fff0, +0x8f820044, 0x3c03ffff, 0x34633f7f, 0x431024, +0xaf820044, 0x3c09fff0, 0x3529bdc0, 0x3c060001, +0x8cc66d94, 0x3c040001, 0x24846ae0, 0x24020001, +0x3c010001, 0xac226d9c, 0x8f820054, 0x3c070001, +0x8ce76f40, 0x3c030001, 0x94636f24, 0x3c080001, +0x95086f26, 0x3c05000d, 0x34a50100, 0x3c010001, +0xac206d98, 0x491021, 0x3c010001, 0xac226f30, +0xafa30010, 0xc002b3b, 0xafa80014, 0x8fbf002c, +0x8fb20028, 0x8fb10024, 0x8fb00020, 0x3e00008, +0x27bd0030, 0x27bdffe8, 0x3c050001, 0x8ca56d98, +0x24060004, 0x24020001, 0x14a20014, 0xafbf0010, +0x3c020002, 0x8c428ffc, 0x30428000, 0x10400005, +0x3c04000f, 0x3c030001, 0x8c636f40, 0x10000005, +0x34844240, 0x3c040004, 0x3c030001, 0x8c636f40, +0x348493e0, 0x24020005, 0x14620016, 0x0, +0x3c04003d, 0x10000013, 0x34840900, 0x3c020002, +0x8c428ff8, 0x30428000, 0x10400005, 0x3c04001e, +0x3c030001, 0x8c636f40, 0x10000005, 0x34848480, +0x3c04000f, 0x3c030001, 0x8c636f40, 0x34844240, +0x24020005, 0x14620003, 0x0, 0x3c04007a, +0x34841200, 0x3c020001, 0x8c426f30, 0x8f830054, +0x441021, 0x431023, 0x44102b, 0x1440004c, +0x0, 0x3c020001, 0x8c426da0, 0x14400048, +0x0, 0x3c010001, 0x10c00025, 0xac206db0, +0x3c090001, 0x8d296d94, 0x24070001, 0x3c044000, +0x3c080002, 0x25088ffc, 0x250afffc, 0x52842, +0x14a00002, 0x24c6ffff, 0x24050008, 0xa91024, +0x10400010, 0x0, 0x14a70008, 0x0, +0x8d020000, 0x441024, 0x1040000a, 0x0, +0x3c010001, 0x10000007, 0xac256db0, 0x8d420000, +0x441024, 0x10400003, 0x0, 0x3c010001, +0xac276db0, 0x3c020001, 0x8c426db0, 0x6182b, +0x2c420001, 0x431024, 0x5440ffe5, 0x52842, +0x8f820054, 0x3c030001, 0x8c636db0, 0x3c010001, +0xac226f30, 0x1060003b, 0x24020005, 0x3c030001, +0x8c636f40, 0x3c010001, 0xac256d98, 0x14620012, +0x24020001, 0x3c020002, 0x8c428ff8, 0x3c032000, +0x34635000, 0x431024, 0x14400006, 0x24020001, +0x3c010001, 0xac206f1c, 0x3c010001, 0xac226d98, +0x24020001, 0x3c010001, 0xac226e24, 0x3c010001, +0xac226da4, 0x24020001, 0x3c010001, 0xac226d9c, +0x3c020001, 0x8c426db0, 0x1040001e, 0x0, +0x3c020001, 0x8c426d9c, 0x10400008, 0x24020001, +0x3c010001, 0xac206d9c, 0xaee204b8, 0x3c010001, +0xac206e1c, 0x3c010001, 0xac226dd4, 0x8ee304b8, +0x24020008, 0x10620005, 0x24020001, 0xc004239, +0x0, 0x1000000b, 0x0, 0x3c030001, +0x8c636d98, 0x10620007, 0x2402000e, 0x3c030002, +0x8c638f90, 0x10620003, 0x0, 0xc004e9c, +0x8f840220, 0x8fbf0010, 0x3e00008, 0x27bd0018, +0x27bdffe0, 0x3c03fdff, 0x3c040001, 0x8c846d98, +0x3c020001, 0x8c426dc0, 0x3463ffff, 0x283a024, +0x14820006, 0xafbf0018, 0x8ee304b8, 0x3c020001, +0x8c426dc4, 0x10620006, 0x0, 0x8ee204b8, +0x3c010001, 0xac246dc0, 0x3c010001, 0xac226dc4, +0x3c030001, 0x8c636d98, 0x24020002, 0x1062019c, +0x2c620003, 0x10400005, 0x24020001, 0x1062000a, +0x0, 0x10000226, 0x0, 0x24020004, +0x106200b6, 0x24020008, 0x1062010a, 0x24020001, +0x1000021f, 0x0, 0x8ee204b8, 0x2443ffff, +0x2c620008, 0x1040021c, 0x31080, 0x3c010001, +0x220821, 0x8c226af8, 0x400008, 0x0, +0x3c030001, 0x8c636f40, 0x24020005, 0x14620010, +0x0, 0x3c020001, 0x8c426da4, 0x10400008, +0x24020003, 0xc004482, 0x0, 0x24020002, +0xaee204b8, 0x3c010001, 0x10000002, 0xac206da4, +0xaee204b8, 0x3c010001, 0x10000203, 0xac206d30, +0xc004482, 0x0, 0x3c020001, 0x8c426da4, +0x3c010001, 0xac206d30, 0x1440017a, 0x24020002, +0x1000019d, 0x24020007, 0x3c030001, 0x8c636f40, +0x24020005, 0x14620003, 0x24020001, 0x3c010001, +0xac226dd0, 0xc0045ff, 0x0, 0x3c030001, +0x8c636dd0, 0x10000174, 0x24020011, 0x3c050001, +0x8ca56d98, 0x3c060002, 0x8cc68ffc, 0xc005104, +0x2021, 0x24020005, 0x3c010001, 0xac206da4, +0x100001e1, 0xaee204b8, 0x3c040001, 0x24846aec, +0x3c05000f, 0x34a50100, 0x3021, 0x3821, +0xafa00010, 0xc002b3b, 0xafa00014, 0x100001d6, +0x0, 0x8f820220, 0x3c030004, 0x431024, +0x14400175, 0x24020007, 0x8f830054, 0x3c020001, +0x8c426f28, 0x2463d8f0, 0x431023, 0x2c422710, +0x14400003, 0x24020001, 0x3c010001, 0xac226d9c, +0x3c020002, 0x8c428ffc, 0x30425000, 0x104001c2, +0x0, 0x8f820220, 0x30428000, 0x1040017d, +0x0, 0x10000175, 0x0, 0x3c050001, +0x8ca56d98, 0xc00529b, 0x2021, 0xc00551b, +0x2021, 0x3c030002, 0x8c638ff4, 0x46101b0, +0x24020001, 0x3c020008, 0x621024, 0x10400006, +0x0, 0x8f820214, 0x3c03ffff, 0x431024, +0x10000005, 0x3442251f, 0x8f820214, 0x3c03ffff, +0x431024, 0x3442241f, 0xaf820214, 0x8f820220, +0x3c030200, 0x34420002, 0xaf820220, 0x24020008, +0xaee204b8, 0x8f820220, 0x283a025, 0x3c030004, +0x431024, 0x14400016, 0x0, 0x3c020002, +0x8c428ffc, 0x30425000, 0x1040000d, 0x0, +0x8f820220, 0x30428000, 0x10400006, 0x0, +0x8f820220, 0x3c03ffff, 0x34637fff, 0x10000003, +0x431024, 0x8f820220, 0x34428000, 0xaf820220, 0x8f820220, 0x3c03f700, 0x431025, 0xaf820220, -0xaf800204, 0x3c010002, 0x100000d6, 0xac209060, -0x8f830054, 0x3c020001, 0x8c426fa0, 0x2463fff6, -0x431023, 0x2c42000a, 0x144000ef, 0x24020007, -0x100000d2, 0x0, 0xc003f28, 0x0, -0x104000e7, 0x24020001, 0x8f820214, 0x3c03ffff, -0x3c040001, 0x8c846f98, 0x431024, 0x3442251f, -0xaf820214, 0x24020008, 0x10800005, 0xaee204b8, -0x3c020001, 0x8c426ec4, 0x10400064, 0x24020001, -0x8f820220, 0x3c030008, 0x431024, 0x1040006a, -0x3c020200, 0x10000078, 0x0, 0x8ee204b8, -0x2443ffff, 0x2c620007, 0x104000cf, 0x31080, -0x3c010001, 0x220821, 0x8c226bc8, 0x400008, -0x0, 0xc003d87, 0x0, 0x3c010001, -0xac206e1c, 0xaf800204, 0x3c010002, 0xc0043d3, -0xac209060, 0x24020001, 0x3c010001, 0xac226e34, -0x24020002, 0x100000bc, 0xaee204b8, 0xc004498, -0x0, 0x3c030001, 0x8c636e34, 0x10000084, -0x24020009, 0x3c020002, 0x8c429078, 0x30424000, -0x10400003, 0x3c0200c8, 0x10000002, 0x344201f6, -0x344201fe, 0xaf820238, 0x8f830054, 0x1000008b, -0x24020004, 0x8f830054, 0x3c020001, 0x8c426fa0, -0x2463d8f0, 0x431023, 0x2c422710, 0x144000a2, -0x24020005, 0x10000079, 0x0, 0x8f820220, -0x3c03f700, 0x431025, 0xaf820220, 0xaf800204, -0x3c010002, 0x10000077, 0xac209060, 0x8f830054, -0x3c020001, 0x8c426fa0, 0x2463fff6, 0x431023, -0x2c42000a, 0x14400090, 0x24020007, 0x10000073, -0x0, 0xc003f28, 0x0, 0x10400088, -0x24020001, 0x8f820214, 0x3c03ffff, 0x3c040001, -0x8c846f98, 0x431024, 0x3442251f, 0xaf820214, -0x24020008, 0x1080000f, 0xaee204b8, 0x3c020001, -0x8c426ec4, 0x1440000b, 0x0, 0x8f820220, -0x34420002, 0xaf820220, 0x24020001, 0x3c010002, -0xac229010, 0xc004ecc, 0x8f840220, 0x10000016, -0x0, 0x8f820220, 0x3c030008, 0x431024, -0x14400011, 0x3c020200, 0x282a025, 0x2402000e, -0x3c010002, 0xac229010, 0xc00553d, 0x2021, -0x8f820220, 0x34420002, 0xc003e45, 0xaf820220, -0x3c050001, 0x8ca56e18, 0xc0052c7, 0x2021, -0x1000005d, 0x0, 0x3c020001, 0x8c426ec4, -0x10400059, 0x0, 0x3c020001, 0x8c426ec0, -0x2442ffff, 0x3c010001, 0xac226ec0, 0x14400052, -0x24020002, 0x3c010001, 0xac206ec4, 0x3c010001, -0x1000004d, 0xac226ec0, 0x8ee204b8, 0x2443ffff, -0x2c620007, 0x10400048, 0x31080, 0x3c010001, -0x220821, 0x8c226be8, 0x400008, 0x0, -0x3c020001, 0x8c426e24, 0x10400024, 0x24020007, -0xc0043d3, 0x0, 0x24020002, 0xaee204b8, -0x3c010001, 0x10000038, 0xac206e24, 0xc0048b3, -0x0, 0x3c030001, 0x8c636e54, 0x24020006, -0x14620031, 0x24020003, 0x1000002f, 0xaee204b8, -0x3c050001, 0x8ca56e18, 0x3c060002, 0x8cc69078, -0xc005134, 0x2021, 0x24020005, 0x10000026, -0xaee204b8, 0x8f820220, 0x3c03f700, 0x431025, -0xaf820220, 0x8f830054, 0x24020006, 0xaee204b8, -0x3c010001, 0x1000001c, 0xac236fa0, 0x1000001a, -0xaee204b8, 0x3c050001, 0x8ca56e18, 0xc0052c7, -0x2021, 0xc00553d, 0x2021, 0x3c020002, -0x8c429070, 0x441000e, 0x24020001, 0x8f820214, +0x3c030001, 0x8c636f40, 0x24020005, 0x1462000a, +0x0, 0x3c020001, 0x94426f26, 0x24429fbc, +0x2c420004, 0x10400004, 0x24040018, 0x24050002, +0xc004ddb, 0x24060020, 0xc003e6d, 0x0, +0x3c010001, 0x10000170, 0xac206e20, 0x8ee204b8, +0x2443ffff, 0x2c620008, 0x1040016b, 0x31080, +0x3c010001, 0x220821, 0x8c226b18, 0x400008, +0x0, 0xc004547, 0x0, 0x3c030001, +0x8c636db4, 0x100000e8, 0x24020009, 0x3c020002, +0x8c428ff8, 0x30424000, 0x10400004, 0x0, +0x8f820044, 0x10000006, 0x3442f080, 0x8f820044, +0x3c03ffff, 0x34633f7f, 0x431024, 0x3442a080, +0xaf820044, 0x8f830054, 0x100000ea, 0x24020004, +0x8f830054, 0x3c020001, 0x8c426f28, 0x2463d8f0, +0x431023, 0x2c422710, 0x14400147, 0x24020005, +0x100000d8, 0x0, 0x8f820220, 0x3c03f700, +0x431025, 0xaf820220, 0xaf800204, 0x3c010002, +0x100000d6, 0xac208fe0, 0x8f830054, 0x3c020001, +0x8c426f28, 0x2463fff6, 0x431023, 0x2c42000a, +0x14400135, 0x24020007, 0x100000d7, 0x0, +0xc003f50, 0x0, 0x1040012d, 0x24020001, +0x8f820214, 0x3c03ffff, 0x3c040001, 0x8c846f1c, +0x431024, 0x3442251f, 0xaf820214, 0x24020008, +0x10800005, 0xaee204b8, 0x3c020001, 0x8c426e44, +0x10400064, 0x24020001, 0x8f820220, 0x3c030008, +0x431024, 0x1040006a, 0x3c020200, 0x10000078, +0x0, 0x8ee204b8, 0x2443ffff, 0x2c620007, +0x10400115, 0x31080, 0x3c010001, 0x220821, +0x8c226b38, 0x400008, 0x0, 0xc003daf, +0x0, 0x3c010001, 0xac206d9c, 0xaf800204, +0x3c010002, 0xc004482, 0xac208fe0, 0x24020001, +0x3c010001, 0xac226db4, 0x24020002, 0x10000102, +0xaee204b8, 0xc004547, 0x0, 0x3c030001, +0x8c636db4, 0x10000084, 0x24020009, 0x3c020002, +0x8c428ff8, 0x30424000, 0x10400003, 0x3c0200c8, +0x10000002, 0x344201f6, 0x344201fe, 0xaf820238, +0x8f830054, 0x1000008b, 0x24020004, 0x8f830054, +0x3c020001, 0x8c426f28, 0x2463d8f0, 0x431023, +0x2c422710, 0x144000e8, 0x24020005, 0x10000079, +0x0, 0x8f820220, 0x3c03f700, 0x431025, +0xaf820220, 0xaf800204, 0x3c010002, 0x10000077, +0xac208fe0, 0x8f830054, 0x3c020001, 0x8c426f28, +0x2463fff6, 0x431023, 0x2c42000a, 0x144000d6, +0x24020007, 0x10000078, 0x0, 0xc003f50, +0x0, 0x104000ce, 0x24020001, 0x8f820214, +0x3c03ffff, 0x3c040001, 0x8c846f1c, 0x431024, +0x3442251f, 0xaf820214, 0x24020008, 0x1080000f, +0xaee204b8, 0x3c020001, 0x8c426e44, 0x1440000b, +0x0, 0x8f820220, 0x34420002, 0xaf820220, +0x24020001, 0x3c010002, 0xac228f90, 0xc004e9c, +0x8f840220, 0x10000016, 0x0, 0x8f820220, +0x3c030008, 0x431024, 0x14400011, 0x3c020200, +0x282a025, 0x2402000e, 0x3c010002, 0xac228f90, +0xc00551b, 0x2021, 0x8f820220, 0x34420002, +0xc003e6d, 0xaf820220, 0x3c050001, 0x8ca56d98, +0xc00529b, 0x2021, 0x100000a3, 0x0, +0x3c020001, 0x8c426e44, 0x1040009f, 0x0, +0x3c020001, 0x8c426e40, 0x2442ffff, 0x3c010001, +0xac226e40, 0x14400098, 0x24020002, 0x3c010001, +0xac206e44, 0x3c010001, 0x10000093, 0xac226e40, +0x8ee204b8, 0x2443ffff, 0x2c620007, 0x1040008e, +0x31080, 0x3c010001, 0x220821, 0x8c226b58, +0x400008, 0x0, 0x3c020001, 0x8c426da4, +0x10400018, 0x24020005, 0xc004482, 0x0, +0x24020002, 0xaee204b8, 0x3c010001, 0x1000007e, +0xac206da4, 0xc004963, 0x0, 0x3c030001, +0x8c636dd4, 0x24020006, 0x14620077, 0x24020003, +0x10000075, 0xaee204b8, 0x3c050001, 0x8ca56d98, +0x3c060002, 0x8cc68ff8, 0xc005104, 0x2021, +0x24020005, 0x1000006c, 0xaee204b8, 0x8f820220, +0x3c03f700, 0x431025, 0xaf820220, 0x8f830054, +0x24020006, 0xaee204b8, 0x3c010001, 0x10000062, +0xac236f28, 0x8f820220, 0x3c030004, 0x431024, +0x10400003, 0x24020007, 0x1000005b, 0xaee204b8, +0x8f830054, 0x3c020001, 0x8c426f28, 0x2463d8f0, +0x431023, 0x2c422710, 0x14400003, 0x24020001, +0x3c010001, 0xac226d9c, 0x3c020002, 0x8c428ff8, +0x30425000, 0x1040004c, 0x0, 0x8f820220, +0x30428000, 0x10400007, 0x0, 0x8f820220, +0x3c03ffff, 0x34637fff, 0x431024, 0x10000042, +0xaf820220, 0x8f820220, 0x34428000, 0x1000003e, +0xaf820220, 0x3c050001, 0x8ca56d98, 0xc00529b, +0x2021, 0xc00551b, 0x2021, 0x3c020002, +0x8c428ff0, 0x4410032, 0x24020001, 0x8f820214, 0x3c03ffff, 0x431024, 0x3442251f, 0xaf820214, 0x24020008, 0xaee204b8, 0x8f820220, 0x34420002, -0xc003e45, 0xaf820220, 0x10000003, 0x0, -0x3c010001, 0xac226e1c, 0x8fbf001c, 0x8fb00018, -0x3e00008, 0x27bd0020, 0x8f820200, 0x8f820220, -0x8f820220, 0x34420004, 0xaf820220, 0x8f820200, -0x3c050001, 0x8ca56e18, 0x34420004, 0xaf820200, -0x24020002, 0x10a2004b, 0x2ca20003, 0x10400005, -0x24020001, 0x10a2000a, 0x0, 0x100000b1, -0x0, 0x24020004, 0x10a20072, 0x24020008, -0x10a20085, 0x3c02f0ff, 0x100000aa, 0x0, +0xaf820220, 0x8f820220, 0x3c030004, 0x431024, +0x14400016, 0x0, 0x3c020002, 0x8c428ff8, +0x30425000, 0x1040000d, 0x0, 0x8f820220, +0x30428000, 0x10400006, 0x0, 0x8f820220, +0x3c03ffff, 0x34637fff, 0x10000003, 0x431024, +0x8f820220, 0x34428000, 0xaf820220, 0x8f820220, +0x3c03f700, 0x431025, 0xaf820220, 0x3c020001, +0x94426f26, 0x24429fbc, 0x2c420004, 0x10400004, +0x24040018, 0x24050002, 0xc004ddb, 0x24060020, +0xc003e6d, 0x0, 0x10000003, 0x0, +0x3c010001, 0xac226d9c, 0x8fbf0018, 0x3e00008, +0x27bd0020, 0x8f820200, 0x8f820220, 0x8f820220, +0x34420004, 0xaf820220, 0x8f820200, 0x3c050001, +0x8ca56d98, 0x34420004, 0xaf820200, 0x24020002, +0x10a2004b, 0x2ca20003, 0x10400005, 0x24020001, +0x10a2000a, 0x0, 0x100000b1, 0x0, +0x24020004, 0x10a20072, 0x24020008, 0x10a20085, +0x3c02f0ff, 0x100000aa, 0x0, 0x8f830050, +0x3c02f0ff, 0x3442ffff, 0x3c040001, 0x8c846f40, +0x621824, 0x3c020700, 0x621825, 0x24020e00, +0x2484fffb, 0x2c840002, 0xaf830050, 0xaf850200, +0xaf850220, 0x14800006, 0xaf820238, 0x8f820044, +0x3c03ffff, 0x34633f7f, 0x431024, 0xaf820044, +0x3c030001, 0x8c636f40, 0x24020005, 0x14620004, +0x0, 0x8f820044, 0x34425000, 0xaf820044, +0x3c020001, 0x8c426d88, 0x3c030001, 0x8c636f40, +0x34420022, 0x2463fffc, 0x2c630002, 0x1460000c, +0xaf820200, 0x3c020001, 0x8c426dac, 0x3c030001, +0x8c636d90, 0x3c040001, 0x8c846d8c, 0x34428000, +0x621825, 0x641825, 0x1000000a, 0x34620002, +0x3c020001, 0x8c426d90, 0x3c030001, 0x8c636dac, +0x3c040001, 0x8c846d8c, 0x431025, 0x441025, +0x34420002, 0xaf820220, 0x1000002f, 0x24020001, +0x24020e01, 0xaf820238, 0x8f830050, 0x3c02f0ff, +0x3442ffff, 0x3c040001, 0x8c846f1c, 0x621824, +0x3c020d00, 0x621825, 0x24020001, 0xaf830050, +0xaf820200, 0xaf820220, 0x10800005, 0x3c033f00, +0x3c020001, 0x8c426d80, 0x10000004, 0x34630070, +0x3c020001, 0x8c426d80, 0x34630072, 0x431025, +0xaf820200, 0x3c030001, 0x8c636d84, 0x3c02f700, +0x621825, 0x3c020001, 0x8c426d90, 0x3c040001, +0x8c846dac, 0x3c050001, 0x8ca56f40, 0x431025, +0x441025, 0xaf820220, 0x24020005, 0x14a20006, +0x24020001, 0x8f820044, 0x2403afff, 0x431024, +0xaf820044, 0x24020001, 0x1000003d, 0xaf820238, 0x8f830050, 0x3c02f0ff, 0x3442ffff, 0x3c040001, -0x8c846fb8, 0x621824, 0x3c020700, 0x621825, -0x24020e00, 0x2484fffb, 0x2c840002, 0xaf830050, -0xaf850200, 0xaf850220, 0x14800006, 0xaf820238, -0x8f820044, 0x3c03ffff, 0x34633f7f, 0x431024, -0xaf820044, 0x3c030001, 0x8c636fb8, 0x24020005, -0x14620004, 0x0, 0x8f820044, 0x34425000, -0xaf820044, 0x3c020001, 0x8c426e08, 0x3c030001, -0x8c636fb8, 0x34420022, 0x2463fffc, 0x2c630002, -0x1460000c, 0xaf820200, 0x3c020001, 0x8c426e2c, -0x3c030001, 0x8c636e10, 0x3c040001, 0x8c846e0c, -0x34428000, 0x621825, 0x641825, 0x1000000a, -0x34620002, 0x3c020001, 0x8c426e10, 0x3c030001, -0x8c636e2c, 0x3c040001, 0x8c846e0c, 0x431025, -0x441025, 0x34420002, 0xaf820220, 0x1000002f, -0x24020001, 0x24020e01, 0xaf820238, 0x8f830050, -0x3c02f0ff, 0x3442ffff, 0x3c040001, 0x8c846f98, -0x621824, 0x3c020d00, 0x621825, 0x24020001, -0xaf830050, 0xaf820200, 0xaf820220, 0x10800005, -0x3c033f00, 0x3c020001, 0x8c426e00, 0x10000004, -0x34630070, 0x3c020001, 0x8c426e00, 0x34630072, -0x431025, 0xaf820200, 0x3c030001, 0x8c636e04, -0x3c02f700, 0x621825, 0x3c020001, 0x8c426e10, -0x3c040001, 0x8c846e2c, 0x3c050001, 0x8ca56fb8, -0x431025, 0x441025, 0xaf820220, 0x24020005, -0x14a20006, 0x24020001, 0x8f820044, 0x2403afff, -0x431024, 0xaf820044, 0x24020001, 0x1000003d, -0xaf820238, 0x8f830050, 0x3c02f0ff, 0x3442ffff, -0x3c040001, 0x8c846f98, 0x621824, 0x3c020a00, -0x621825, 0x24020001, 0xaf830050, 0xaf820200, -0x1080001e, 0xaf820220, 0x3c020001, 0x8c426ec4, -0x1440001a, 0x3c033f00, 0x3c020001, 0x8c426e00, -0x1000001a, 0x346300e0, 0x8f830050, 0x3c040001, -0x8c846f98, 0x3442ffff, 0x621824, 0x1080000f, -0xaf830050, 0x3c020001, 0x8c426ec4, 0x1440000b, -0x3c043f00, 0x3c030001, 0x8c636e00, 0x348400e0, -0x24020001, 0xaf820200, 0xaf820220, 0x641825, -0xaf830200, 0x10000008, 0x3c05f700, 0x3c020001, -0x8c426e00, 0x3c033f00, 0x346300e2, 0x431025, -0xaf820200, 0x3c05f700, 0x34a58000, 0x3c030001, -0x8c636e04, 0x3c020001, 0x8c426e10, 0x3c040001, -0x8c846e2c, 0x651825, 0x431025, 0x441025, -0xaf820220, 0x3e00008, 0x0, 0x3c030001, -0x8c636e34, 0x3c020001, 0x8c426e38, 0x10620003, -0x24020002, 0x3c010001, 0xac236e38, 0x1062001d, -0x2c620003, 0x10400025, 0x24020001, 0x14620023, -0x24020004, 0x3c030001, 0x8c636e18, 0x10620006, -0x24020008, 0x1462000c, 0x3c0200c8, 0x344201fb, -0x10000009, 0xaf820238, 0x24020e01, 0xaf820238, -0x8f820044, 0x3c03ffff, 0x34633f7f, 0x431024, -0x34420080, 0xaf820044, 0x8f830054, 0x24020002, -0x3c010001, 0xac226e34, 0x3c010001, 0x1000000b, -0xac236fa4, 0x8f830054, 0x3c020001, 0x8c426fa4, -0x2463d8f0, 0x431023, 0x2c422710, 0x14400003, -0x24020009, 0x3c010001, 0xac226e34, 0x3e00008, +0x8c846f1c, 0x621824, 0x3c020a00, 0x621825, +0x24020001, 0xaf830050, 0xaf820200, 0x1080001e, +0xaf820220, 0x3c020001, 0x8c426e44, 0x1440001a, +0x3c033f00, 0x3c020001, 0x8c426d80, 0x1000001a, +0x346300e0, 0x8f830050, 0x3c040001, 0x8c846f1c, +0x3442ffff, 0x621824, 0x1080000f, 0xaf830050, +0x3c020001, 0x8c426e44, 0x1440000b, 0x3c043f00, +0x3c030001, 0x8c636d80, 0x348400e0, 0x24020001, +0xaf820200, 0xaf820220, 0x641825, 0xaf830200, +0x10000008, 0x3c05f700, 0x3c020001, 0x8c426d80, +0x3c033f00, 0x346300e2, 0x431025, 0xaf820200, +0x3c05f700, 0x34a58000, 0x3c030001, 0x8c636d84, +0x3c020001, 0x8c426d90, 0x3c040001, 0x8c846dac, +0x651825, 0x431025, 0x441025, 0xaf820220, +0x3e00008, 0x0, 0x3c030001, 0x8c636db4, +0x3c020001, 0x8c426db8, 0x10620003, 0x24020002, +0x3c010001, 0xac236db8, 0x1062001d, 0x2c620003, +0x10400025, 0x24020001, 0x14620023, 0x24020004, +0x3c030001, 0x8c636d98, 0x10620006, 0x24020008, +0x1462000c, 0x3c0200c8, 0x344201fb, 0x10000009, +0xaf820238, 0x24020e01, 0xaf820238, 0x8f820044, +0x3c03ffff, 0x34633f7f, 0x431024, 0x34420080, +0xaf820044, 0x8f830054, 0x24020002, 0x3c010001, +0xac226db4, 0x3c010001, 0x1000000b, 0xac236f2c, +0x8f830054, 0x3c020001, 0x8c426f2c, 0x2463d8f0, +0x431023, 0x2c422710, 0x14400003, 0x24020009, +0x3c010001, 0xac226db4, 0x3e00008, 0x0, 0x0, 0x0, 0x0, 0x27bdffd8, 0xafb20018, 0x809021, 0xafb3001c, 0xa09821, 0xafb10014, 0xc08821, 0xafb00010, 0x8021, -0xafbf0020, 0xa6200000, 0xc004dab, 0x24040001, +0xafbf0020, 0xa6200000, 0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, -0xc004dab, 0x2021, 0xc004dab, 0x24040001, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, +0xc004d78, 0x2021, 0xc004d78, 0x24040001, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, 0x24100010, 0x2501024, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fffa, +0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x2501024, 0x24100010, 0x2701024, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fffa, 0x2701024, 0xc004dec, 0x34108000, -0xc004dec, 0x0, 0xc004d8b, 0x0, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fffa, 0x2701024, 0xc004db9, 0x34108000, +0xc004db9, 0x0, 0xc004d58, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, 0x1600fff7, 0x0, -0xc004dec, 0x0, 0x8fbf0020, 0x8fb3001c, +0xc004db9, 0x0, 0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0028, 0x27bdffd8, 0xafb10014, 0x808821, 0xafb20018, 0xa09021, 0xafb3001c, 0xc09821, -0xafb00010, 0x8021, 0xafbf0020, 0xc004dab, +0xafb00010, 0x8021, 0xafbf0020, 0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004dab, 0x2021, 0xc004dab, -0x24040001, 0xc004dab, 0x2021, 0xc004dab, +0x0, 0xc004d78, 0x2021, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0xc004d78, 0x24040001, 0x24100010, 0x2301024, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, +0x2021, 0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x2301024, 0x24100010, 0x2501024, -0x10400002, 0x2021, 0x24040001, 0xc004dab, -0x108042, 0x1600fffa, 0x2501024, 0xc004dab, -0x24040001, 0xc004dab, 0x2021, 0x34108000, +0x10400002, 0x2021, 0x24040001, 0xc004d78, +0x108042, 0x1600fffa, 0x2501024, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0x34108000, 0x96620000, 0x501024, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fff8, -0x0, 0xc004dec, 0x0, 0x8fbf0020, +0x24040001, 0xc004d78, 0x108042, 0x1600fff8, +0x0, 0xc004db9, 0x0, 0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, -0x3e00008, 0x27bd0028, 0x3c040001, 0x8c846e50, -0x3c020001, 0x8c426e98, 0x27bdffd8, 0xafbf0020, +0x3e00008, 0x27bd0028, 0x3c040001, 0x8c846dd0, +0x3c020001, 0x8c426e18, 0x27bdffd8, 0xafbf0020, 0xafb1001c, 0x10820003, 0xafb00018, 0x3c010001, -0xac246e98, 0x3c030001, 0x8c636fb8, 0x24020005, -0x14620005, 0x2483ffff, 0xc0048b3, 0x0, +0xac246e18, 0x3c030001, 0x8c636f40, 0x24020005, +0x14620005, 0x2483ffff, 0xc004963, 0x0, 0x1000034c, 0x0, 0x2c620013, 0x10400349, -0x31080, 0x3c010001, 0x220821, 0x8c226c10, -0x400008, 0x0, 0xc004dec, 0x8021, -0x34028000, 0xa7a20010, 0x27b10010, 0xc004dab, +0x31080, 0x3c010001, 0x220821, 0x8c226b80, +0x400008, 0x0, 0xc004db9, 0x8021, +0x34028000, 0xa7a20010, 0x27b10010, 0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004dab, 0x2021, 0xc004dab, -0x24040001, 0xc004dab, 0x2021, 0xc004dab, +0x0, 0xc004d78, 0x2021, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0xc004d78, 0x24040001, 0x24100010, 0x32020001, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fffa, 0x32020001, 0x24100010, 0xc004dab, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fffa, 0x32020001, 0x24100010, 0xc004d78, 0x2021, 0x108042, 0x1600fffc, 0x0, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fff8, 0x0, 0xc004dec, 0x0, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fff8, 0x0, 0xc004db9, 0x0, 0x1000030e, 0x24020002, 0x27b10010, 0xa7a00010, -0x8021, 0xc004dab, 0x24040001, 0x26100001, -0x2e020020, 0x1440fffb, 0x0, 0xc004dab, -0x2021, 0xc004dab, 0x24040001, 0xc004dab, -0x24040001, 0xc004dab, 0x2021, 0x24100010, +0x8021, 0xc004d78, 0x24040001, 0x26100001, +0x2e020020, 0x1440fffb, 0x0, 0xc004d78, +0x2021, 0xc004d78, 0x24040001, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020001, -0x24100010, 0xc004dab, 0x2021, 0x108042, -0x1600fffc, 0x0, 0xc004dec, 0x34108000, -0xc004dec, 0x0, 0xc004d8b, 0x0, +0xc004d78, 0x108042, 0x1600fffa, 0x32020001, +0x24100010, 0xc004d78, 0x2021, 0x108042, +0x1600fffc, 0x0, 0xc004db9, 0x34108000, +0xc004db9, 0x0, 0xc004d58, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, 0x1600fff7, 0x0, -0xc004dec, 0x0, 0x97a20010, 0x30428000, +0xc004db9, 0x0, 0x97a20010, 0x30428000, 0x144002dc, 0x24020003, 0x100002d8, 0x0, 0x24021200, 0xa7a20010, 0x27b10010, 0x8021, -0xc004dab, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004dab, +0xc004d78, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, -0xc004dab, 0x2021, 0x108042, 0x1600fffc, -0x0, 0xc004dab, 0x24040001, 0xc004dab, +0xc004d78, 0x2021, 0x108042, 0x1600fffc, +0x0, 0xc004d78, 0x24040001, 0xc004d78, 0x2021, 0x34108000, 0x96220000, 0x501024, -0x10400002, 0x2021, 0x24040001, 0xc004dab, -0x108042, 0x1600fff8, 0x0, 0xc004dec, +0x10400002, 0x2021, 0x24040001, 0xc004d78, +0x108042, 0x1600fff8, 0x0, 0xc004db9, 0x0, 0x8f830054, 0x10000296, 0x24020004, -0x8f830054, 0x3c020001, 0x8c426fb4, 0x2463ff9c, +0x8f830054, 0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023, 0x2c420064, 0x1440029e, 0x24020002, -0x3c030001, 0x8c636fb8, 0x10620297, 0x2c620003, +0x3c030001, 0x8c636f40, 0x10620297, 0x2c620003, 0x14400296, 0x24020011, 0x24020003, 0x10620005, 0x24020004, 0x10620291, 0x2402000f, 0x1000028f, 0x24020011, 0x1000028d, 0x24020005, 0x24020014, -0xa7a20010, 0x27b10010, 0x8021, 0xc004dab, +0xa7a20010, 0x27b10010, 0x8021, 0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004dab, 0x2021, 0xc004dab, -0x24040001, 0xc004dab, 0x2021, 0xc004dab, +0x0, 0xc004d78, 0x2021, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0xc004d78, 0x24040001, 0x24100010, 0x32020001, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, +0x2021, 0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020012, -0x10400002, 0x2021, 0x24040001, 0xc004dab, -0x108042, 0x1600fffa, 0x32020012, 0xc004dab, -0x24040001, 0xc004dab, 0x2021, 0x34108000, +0x10400002, 0x2021, 0x24040001, 0xc004d78, +0x108042, 0x1600fffa, 0x32020012, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fff8, -0x0, 0xc004dec, 0x0, 0x8f830054, +0x24040001, 0xc004d78, 0x108042, 0x1600fff8, +0x0, 0xc004db9, 0x0, 0x8f830054, 0x10000248, 0x24020006, 0x8f830054, 0x3c020001, -0x8c426fb4, 0x2463ff9c, 0x431023, 0x2c420064, +0x8c426f3c, 0x2463ff9c, 0x431023, 0x2c420064, 0x14400250, 0x24020007, 0x1000024c, 0x0, 0x24020006, 0xa7a20010, 0x27b10010, 0x8021, -0xc004dab, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004dab, +0xc004d78, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020013, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020013, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, +0xc004d78, 0x108042, 0x1600fffa, 0x32020013, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fff8, 0x0, 0xc004dec, 0x0, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fff8, 0x0, 0xc004db9, 0x0, 0x8f830054, 0x10000207, 0x24020008, 0x8f830054, -0x3c020001, 0x8c426fb4, 0x2463ff9c, 0x431023, +0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023, 0x2c420064, 0x1440020f, 0x24020009, 0x1000020b, 0x0, 0x27b10010, 0xa7a00010, 0x8021, -0xc004dab, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0xc004dab, 0x24040001, -0xc004dab, 0x2021, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004dab, +0xc004d78, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0xc004d78, 0x24040001, +0xc004d78, 0x2021, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020018, -0xc004dec, 0x34108000, 0xc004dec, 0x0, -0xc004d8b, 0x0, 0x50400005, 0x108042, +0xc004d78, 0x108042, 0x1600fffa, 0x32020018, +0xc004db9, 0x34108000, 0xc004db9, 0x0, +0xc004d58, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, -0x1600fff7, 0x0, 0xc004dec, 0x8021, +0x1600fff7, 0x0, 0xc004db9, 0x8021, 0x97a20010, 0x27b10010, 0x34420001, 0xa7a20010, -0xc004dab, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004dab, +0xc004d78, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020018, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, +0xc004d78, 0x108042, 0x1600fffa, 0x32020018, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fff8, 0x0, 0xc004dec, 0x0, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fff8, 0x0, 0xc004db9, 0x0, 0x8f830054, 0x10000193, 0x2402000a, 0x8f830054, -0x3c020001, 0x8c426fb4, 0x2463ff9c, 0x431023, +0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023, 0x2c420064, 0x1440019b, 0x2402000b, 0x10000197, 0x0, 0x27b10010, 0xa7a00010, 0x8021, -0xc004dab, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0xc004dab, 0x24040001, -0xc004dab, 0x2021, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004dab, +0xc004d78, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0xc004d78, 0x24040001, +0xc004d78, 0x2021, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020017, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020017, -0xc004dec, 0x34108000, 0xc004dec, 0x0, -0xc004d8b, 0x0, 0x50400005, 0x108042, +0xc004d78, 0x108042, 0x1600fffa, 0x32020017, +0xc004db9, 0x34108000, 0xc004db9, 0x0, +0xc004d58, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, -0x1600fff7, 0x0, 0xc004dec, 0x8021, +0x1600fff7, 0x0, 0xc004db9, 0x8021, 0x97a20010, 0x27b10010, 0x34420700, 0xa7a20010, -0xc004dab, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004dab, +0xc004d78, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020017, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020017, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, +0xc004d78, 0x108042, 0x1600fffa, 0x32020017, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fff8, 0x0, 0xc004dec, 0x0, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fff8, 0x0, 0xc004db9, 0x0, 0x8f830054, 0x1000011f, 0x2402000c, 0x8f830054, -0x3c020001, 0x8c426fb4, 0x2463ff9c, 0x431023, +0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023, 0x2c420064, 0x14400127, 0x24020012, 0x10000123, 0x0, 0x27b10010, 0xa7a00010, 0x8021, -0xc004dab, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0xc004dab, 0x24040001, -0xc004dab, 0x2021, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004dab, +0xc004d78, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0xc004d78, 0x24040001, +0xc004d78, 0x2021, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020014, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020014, -0xc004dec, 0x34108000, 0xc004dec, 0x0, -0xc004d8b, 0x0, 0x50400005, 0x108042, +0xc004d78, 0x108042, 0x1600fffa, 0x32020014, +0xc004db9, 0x34108000, 0xc004db9, 0x0, +0xc004d58, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, -0x1600fff7, 0x0, 0xc004dec, 0x8021, +0x1600fff7, 0x0, 0xc004db9, 0x8021, 0x97a20010, 0x27b10010, 0x34420010, 0xa7a20010, -0xc004dab, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004dab, +0xc004d78, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020014, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020014, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, +0xc004d78, 0x108042, 0x1600fffa, 0x32020014, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fff8, 0x0, 0xc004dec, 0x0, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fff8, 0x0, 0xc004db9, 0x0, 0x8f830054, 0x100000ab, 0x24020013, 0x8f830054, -0x3c020001, 0x8c426fb4, 0x2463ff9c, 0x431023, +0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023, 0x2c420064, 0x144000b3, 0x2402000d, 0x100000af, 0x0, 0x27b10010, 0xa7a00010, 0x8021, -0xc004dab, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0xc004dab, 0x24040001, -0xc004dab, 0x2021, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004dab, +0xc004d78, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0xc004d78, 0x24040001, +0xc004d78, 0x2021, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020018, -0xc004dec, 0x34108000, 0xc004dec, 0x0, -0xc004d8b, 0x0, 0x50400005, 0x108042, +0xc004d78, 0x108042, 0x1600fffa, 0x32020018, +0xc004db9, 0x34108000, 0xc004db9, 0x0, +0xc004d58, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, -0x1600fff7, 0x0, 0xc004dec, 0x8021, +0x1600fff7, 0x0, 0xc004db9, 0x8021, 0x97a20010, 0x27b10010, 0x3042fffe, 0xa7a20010, -0xc004dab, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004dab, +0xc004d78, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020018, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, +0xc004d78, 0x108042, 0x1600fffa, 0x32020018, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fff8, 0x0, 0xc004dec, 0x0, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fff8, 0x0, 0xc004db9, 0x0, 0x8f830054, 0x10000037, 0x2402000e, 0x24020840, -0xa7a20010, 0x27b10010, 0x8021, 0xc004dab, +0xa7a20010, 0x27b10010, 0x8021, 0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004dab, 0x2021, 0xc004dab, -0x24040001, 0xc004dab, 0x2021, 0xc004dab, +0x0, 0xc004d78, 0x2021, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0xc004d78, 0x24040001, 0x24100010, 0x32020001, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, +0x2021, 0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020013, -0x10400002, 0x2021, 0x24040001, 0xc004dab, -0x108042, 0x1600fffa, 0x32020013, 0xc004dab, -0x24040001, 0xc004dab, 0x2021, 0x34108000, +0x10400002, 0x2021, 0x24040001, 0xc004d78, +0x108042, 0x1600fffa, 0x32020013, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fff8, -0x0, 0xc004dec, 0x0, 0x8f830054, -0x24020010, 0x3c010001, 0xac226e50, 0x3c010001, -0x1000000c, 0xac236fb4, 0x8f830054, 0x3c020001, -0x8c426fb4, 0x2463ff9c, 0x431023, 0x2c420064, +0x24040001, 0xc004d78, 0x108042, 0x1600fff8, +0x0, 0xc004db9, 0x0, 0x8f830054, +0x24020010, 0x3c010001, 0xac226dd0, 0x3c010001, +0x1000000c, 0xac236f3c, 0x8f830054, 0x3c020001, +0x8c426f3c, 0x2463ff9c, 0x431023, 0x2c420064, 0x14400004, 0x0, 0x24020011, 0x3c010001, -0xac226e50, 0x8fbf0020, 0x8fb1001c, 0x8fb00018, -0x3e00008, 0x27bd0028, 0x3c030001, 0x8c636e18, +0xac226dd0, 0x8fbf0020, 0x8fb1001c, 0x8fb00018, +0x3e00008, 0x27bd0028, 0x3c030001, 0x8c636d98, 0x27bdffc8, 0x24020002, 0xafbf0034, 0xafb20030, 0xafb1002c, 0x14620004, 0xafb00028, 0x3c120002, -0x10000003, 0x8e529078, 0x3c120002, 0x8e52907c, -0x3c030001, 0x8c636e54, 0x3c020001, 0x8c426e9c, -0x50620004, 0x2463ffff, 0x3c010001, 0xac236e9c, -0x2463ffff, 0x2c620006, 0x104004b9, 0x31080, -0x3c010001, 0x220821, 0x8c226c68, 0x400008, -0x0, 0x2021, 0x2821, 0xc004e0e, +0x10000003, 0x8e528ff8, 0x3c120002, 0x8e528ffc, +0x3c030001, 0x8c636dd4, 0x3c020001, 0x8c426e1c, +0x50620004, 0x2463ffff, 0x3c010001, 0xac236e1c, +0x2463ffff, 0x2c620006, 0x10400377, 0x31080, +0x3c010001, 0x220821, 0x8c226bd8, 0x400008, +0x0, 0x2021, 0x2821, 0xc004ddb, 0x34068000, 0x24040010, 0x24050002, 0x24060002, -0x24020002, 0xc004e0e, 0xa7a20018, 0x24020002, -0x3c010001, 0x100004a6, 0xac226e54, 0x27b10018, -0xa7a00018, 0x8021, 0xc004dab, 0x24040001, +0x24020002, 0xc004ddb, 0xa7a20018, 0x24020002, +0x3c010001, 0x10000364, 0xac226dd4, 0x27b10018, +0xa7a00018, 0x8021, 0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, -0xc004dab, 0x2021, 0xc004dab, 0x24040001, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, +0xc004d78, 0x2021, 0xc004d78, 0x24040001, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, 0x24100010, 0x32020001, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fffa, -0x32020001, 0x24100010, 0xc004dab, 0x2021, -0x108042, 0x1600fffc, 0x0, 0xc004dec, -0x34108000, 0xc004dec, 0x0, 0xc004d8b, +0x24040001, 0xc004d78, 0x108042, 0x1600fffa, +0x32020001, 0x24100010, 0xc004d78, 0x2021, +0x108042, 0x1600fffc, 0x0, 0xc004db9, +0x34108000, 0xc004db9, 0x0, 0xc004d58, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, 0x1600fff7, -0x0, 0xc004dec, 0x0, 0x97a20018, +0x0, 0xc004db9, 0x0, 0x97a20018, 0x30428000, 0x14400004, 0x24020003, 0x3c010001, -0xac226e54, 0x24020003, 0x3c010001, 0x1000046c, -0xac226e54, 0x24040010, 0x24050002, 0x24060002, -0x24020002, 0xc004e0e, 0xa7a20018, 0x3c030001, -0x8c636ea0, 0x24020001, 0x146201e2, 0x0, -0x27b10018, 0xa7a00018, 0x8021, 0xc004dab, -0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004dab, 0x2021, 0xc004dab, -0x24040001, 0xc004dab, 0x24040001, 0xc004dab, -0x2021, 0x24100010, 0x32020001, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fffa, 0x32020001, 0x24100010, 0x32020018, -0x10400002, 0x2021, 0x24040001, 0xc004dab, -0x108042, 0x1600fffa, 0x32020018, 0xc004dec, -0x34108000, 0xc004dec, 0x0, 0xc004d8b, -0x0, 0x50400005, 0x108042, 0x96220000, -0x501025, 0xa6220000, 0x108042, 0x1600fff7, -0x0, 0xc004dec, 0x8021, 0x27b10018, -0xa7a00018, 0xc004dab, 0x24040001, 0x26100001, -0x2e020020, 0x1440fffb, 0x0, 0xc004dab, -0x2021, 0xc004dab, 0x24040001, 0xc004dab, -0x24040001, 0xc004dab, 0x2021, 0x24100010, +0xac226dd4, 0x24020003, 0x3c010001, 0x1000032a, +0xac226dd4, 0x24040010, 0x24050002, 0x24060002, +0x24020002, 0xc004ddb, 0xa7a20018, 0x3c030001, +0x8c636e20, 0x24020001, 0x146201e1, 0x8021, +0x27b10018, 0xa7a00018, 0xc004d78, 0x24040001, +0x26100001, 0x2e020020, 0x1440fffb, 0x0, +0xc004d78, 0x2021, 0xc004d78, 0x24040001, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, +0x24100010, 0x32020001, 0x10400002, 0x2021, +0x24040001, 0xc004d78, 0x108042, 0x1600fffa, +0x32020001, 0x24100010, 0x32020018, 0x10400002, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fffa, 0x32020018, 0xc004db9, 0x34108000, +0xc004db9, 0x0, 0xc004d58, 0x0, +0x50400005, 0x108042, 0x96220000, 0x501025, +0xa6220000, 0x108042, 0x1600fff7, 0x0, +0xc004db9, 0x8021, 0x27b10018, 0xa7a00018, +0xc004d78, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0xc004d78, 0x24040001, +0xc004d78, 0x2021, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d78, +0x108042, 0x1600fffa, 0x32020001, 0x24100010, +0x32020018, 0x10400002, 0x2021, 0x24040001, +0xc004d78, 0x108042, 0x1600fffa, 0x32020018, +0xc004db9, 0x34108000, 0xc004db9, 0x0, +0xc004d58, 0x0, 0x50400005, 0x108042, +0x96220000, 0x501025, 0xa6220000, 0x108042, +0x1600fff7, 0x0, 0xc004db9, 0x8021, +0x24040018, 0x2821, 0xc004ddb, 0x24060404, +0xa7a0001a, 0xc004d78, 0x24040001, 0x26100001, +0x2e020020, 0x1440fffb, 0x0, 0xc004d78, +0x2021, 0xc004d78, 0x24040001, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020001, +0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fffa, -0x32020018, 0xc004dec, 0x34108000, 0xc004dec, -0x0, 0xc004d8b, 0x0, 0x50400005, -0x108042, 0x96220000, 0x501025, 0xa6220000, -0x108042, 0x1600fff7, 0x0, 0xc004dec, -0x8021, 0x24040018, 0x2821, 0xc004e0e, -0x24060404, 0xa7a0001a, 0xc004dab, 0x24040001, +0x24040001, 0xc004d78, 0x108042, 0x1600fffa, +0x32020018, 0xc004db9, 0x34108000, 0xc004db9, +0x0, 0xc004d58, 0x0, 0x50400005, +0x108042, 0x97a2001a, 0x501025, 0xa7a2001a, +0x108042, 0x1600fff7, 0x0, 0xc004db9, +0x8021, 0xa7a0001a, 0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, -0xc004dab, 0x2021, 0xc004dab, 0x24040001, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, +0xc004d78, 0x2021, 0xc004d78, 0x24040001, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, 0x24100010, 0x32020001, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fffa, +0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fffa, 0x32020018, 0xc004dec, 0x34108000, -0xc004dec, 0x0, 0xc004d8b, 0x0, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fffa, 0x32020018, 0xc004db9, 0x34108000, +0xc004db9, 0x0, 0xc004d58, 0x0, 0x50400005, 0x108042, 0x97a2001a, 0x501025, 0xa7a2001a, 0x108042, 0x1600fff7, 0x0, -0xc004dec, 0x8021, 0xa7a0001a, 0xc004dab, +0xc004db9, 0x8021, 0xa7a0001c, 0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004dab, 0x2021, 0xc004dab, -0x24040001, 0xc004dab, 0x24040001, 0xc004dab, -0x2021, 0x24100010, 0x32020001, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fffa, 0x32020001, 0x24100010, 0x32020018, -0x10400002, 0x2021, 0x24040001, 0xc004dab, -0x108042, 0x1600fffa, 0x32020018, 0xc004dec, -0x34108000, 0xc004dec, 0x0, 0xc004d8b, -0x0, 0x50400005, 0x108042, 0x97a2001a, -0x501025, 0xa7a2001a, 0x108042, 0x1600fff7, -0x0, 0xc004dec, 0x8021, 0xa7a0001c, -0xc004dab, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0xc004dab, 0x24040001, -0xc004dab, 0x2021, 0x24100010, 0xc004dab, +0x0, 0xc004d78, 0x2021, 0xc004d78, +0x24040001, 0xc004d78, 0x24040001, 0xc004d78, +0x2021, 0x24100010, 0xc004d78, 0x2021, +0x108042, 0x1600fffc, 0x0, 0x24100010, +0x3202001e, 0x10400002, 0x2021, 0x24040001, +0xc004d78, 0x108042, 0x1600fffa, 0x3202001e, +0xc004db9, 0x34108000, 0xc004db9, 0x0, +0xc004d58, 0x0, 0x50400005, 0x108042, +0x97a2001c, 0x501025, 0xa7a2001c, 0x108042, +0x1600fff7, 0x0, 0xc004db9, 0x8021, +0xa7a0001c, 0xc004d78, 0x24040001, 0x26100001, +0x2e020020, 0x1440fffb, 0x0, 0xc004d78, +0x2021, 0xc004d78, 0x24040001, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0x24100010, +0xc004d78, 0x2021, 0x108042, 0x1600fffc, +0x0, 0x24100010, 0x3202001e, 0x10400002, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fffa, 0x3202001e, 0xc004db9, 0x34108000, +0xc004db9, 0x0, 0xc004d58, 0x0, +0x50400005, 0x108042, 0x97a2001c, 0x501025, +0xa7a2001c, 0x108042, 0x1600fff7, 0x0, +0xc004db9, 0x8021, 0x24020002, 0xa7a2001e, +0xc004d78, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0x24100010, 0xc004d78, 0x2021, 0x108042, 0x1600fffc, 0x0, 0x24100010, 0x3202001e, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fffa, -0x3202001e, 0xc004dec, 0x34108000, 0xc004dec, -0x0, 0xc004d8b, 0x0, 0x50400005, -0x108042, 0x97a2001c, 0x501025, 0xa7a2001c, -0x108042, 0x1600fff7, 0x0, 0xc004dec, -0x8021, 0xa7a0001c, 0xc004dab, 0x24040001, +0x24040001, 0xc004d78, 0x108042, 0x1600fffa, +0x3202001e, 0xc004d78, 0x24040001, 0xc004d78, +0x2021, 0x34108000, 0x97a2001e, 0x501024, +0x10400002, 0x2021, 0x24040001, 0xc004d78, +0x108042, 0x1600fff8, 0x0, 0xc004db9, +0x8021, 0xa7a00020, 0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, -0xc004dab, 0x2021, 0xc004dab, 0x24040001, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, -0x24100010, 0xc004dab, 0x2021, 0x108042, +0xc004d78, 0x2021, 0xc004d78, 0x24040001, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, +0x24100010, 0xc004d78, 0x2021, 0x108042, 0x1600fffc, 0x0, 0x24100010, 0x3202001e, -0x10400002, 0x2021, 0x24040001, 0xc004dab, -0x108042, 0x1600fffa, 0x3202001e, 0xc004dec, -0x34108000, 0xc004dec, 0x0, 0xc004d8b, -0x0, 0x50400005, 0x108042, 0x97a2001c, -0x501025, 0xa7a2001c, 0x108042, 0x1600fff7, -0x0, 0xc004dec, 0x8021, 0x24020002, -0xa7a2001e, 0xc004dab, 0x24040001, 0x26100001, -0x2e020020, 0x1440fffb, 0x0, 0xc004dab, -0x2021, 0xc004dab, 0x24040001, 0xc004dab, -0x2021, 0xc004dab, 0x24040001, 0x24100010, -0xc004dab, 0x2021, 0x108042, 0x1600fffc, -0x0, 0x24100010, 0x3202001e, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fffa, 0x3202001e, 0xc004dab, 0x24040001, -0xc004dab, 0x2021, 0x34108000, 0x97a2001e, -0x501024, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fff8, 0x0, -0xc004dec, 0x8021, 0xa7a00020, 0xc004dab, -0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004dab, 0x2021, 0xc004dab, -0x24040001, 0xc004dab, 0x24040001, 0xc004dab, -0x2021, 0x24100010, 0xc004dab, 0x2021, -0x108042, 0x1600fffc, 0x0, 0x24100010, -0x3202001e, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x3202001e, -0xc004dec, 0x34108000, 0xc004dec, 0x0, -0xc004d8b, 0x0, 0x50400005, 0x108042, -0x97a20020, 0x501025, 0xa7a20020, 0x108042, -0x1600fff7, 0x0, 0xc004dec, 0x8021, -0xa7a00020, 0xc004dab, 0x24040001, 0x26100001, -0x2e020020, 0x1440fffb, 0x0, 0xc004dab, -0x2021, 0xc004dab, 0x24040001, 0xc004dab, -0x24040001, 0xc004dab, 0x2021, 0x24100010, -0xc004dab, 0x2021, 0x108042, 0x1600fffc, -0x0, 0x24100010, 0x3202001e, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fffa, 0x3202001e, 0xc004dec, 0x34108000, -0xc004dec, 0x0, 0xc004d8b, 0x0, -0x50400005, 0x108042, 0x97a20020, 0x501025, -0xa7a20020, 0x108042, 0x1600fff7, 0x0, -0xc004dec, 0x8021, 0xa7a00022, 0xc004dab, -0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004dab, 0x2021, 0xc004dab, -0x24040001, 0xc004dab, 0x2021, 0xc004dab, -0x24040001, 0x24100010, 0xc004dab, 0x2021, -0x108042, 0x1600fffc, 0x0, 0x24100010, -0xc004dab, 0x2021, 0x108042, 0x1600fffc, -0x0, 0xc004dab, 0x24040001, 0xc004dab, -0x2021, 0x34108000, 0x97a20022, 0x501024, -0x10400002, 0x2021, 0x24040001, 0xc004dab, -0x108042, 0x1600fff8, 0x0, 0xc004dec, -0x0, 0x24040018, 0x24050002, 0xc004e0e, -0x24060004, 0x3c030001, 0x8c636ea4, 0x24020001, -0x146200fc, 0x3c024000, 0x3c010001, 0xac206ea4, -0x2421024, 0x10400276, 0x3c022000, 0x2421024, -0x10400004, 0x0, 0x3c010001, 0x10000003, -0xac236f98, 0x3c010001, 0xac206f98, 0x3c030001, -0x8c636fac, 0x24020005, 0x146200ea, 0x0, -0x3c020001, 0x8c426f98, 0x1040005f, 0x3c020004, -0x2421024, 0x10400011, 0xa7a00018, 0x3c020008, -0x2421024, 0x10400002, 0x24020200, 0xa7a20018, -0x3c020010, 0x2421024, 0x10400004, 0x0, -0x97a20018, 0x34420100, 0xa7a20018, 0x97a60018, -0x24040009, 0x10000004, 0x2821, 0x24040009, -0x2821, 0x3021, 0xc004e0e, 0x0, -0x24020001, 0xa7a2001a, 0x3c020008, 0x2421024, -0x1040000c, 0x3c020002, 0x2421024, 0x10400002, -0x24020101, 0xa7a2001a, 0x3c020001, 0x2421024, -0x10400005, 0x3c020010, 0x97a2001a, 0x34420040, -0xa7a2001a, 0x3c020010, 0x2421024, 0x1040000e, -0x3c020002, 0x2421024, 0x10400005, 0x3c020001, -0x97a2001a, 0x34420080, 0xa7a2001a, 0x3c020001, -0x2421024, 0x10400005, 0x3c0300a0, 0x97a2001a, -0x34420020, 0xa7a2001a, 0x3c0300a0, 0x2431024, -0x54430004, 0x3c020020, 0x97a2001a, 0x1000000c, -0x34420400, 0x2421024, 0x50400004, 0x3c020080, -0x97a2001a, 0x10000006, 0x34420800, 0x2421024, -0x10400004, 0x0, 0x97a2001a, 0x34420c00, -0xa7a2001a, 0x97a6001a, 0x24040004, 0xc004e0e, -0x2821, 0x32424000, 0x10400003, 0xa7a0001c, -0x24024000, 0xa7a2001c, 0x97a6001c, 0x2021, -0x2821, 0x34c61200, 0xc004e0e, 0xa7a6001c, -0x10000088, 0x0, 0x32424000, 0x10400003, -0xa7a00018, 0x24024000, 0xa7a20018, 0x3c020010, +0x10400002, 0x2021, 0x24040001, 0xc004d78, +0x108042, 0x1600fffa, 0x3202001e, 0xc004db9, +0x34108000, 0xc004db9, 0x0, 0xc004d58, +0x0, 0x50400005, 0x108042, 0x97a20020, +0x501025, 0xa7a20020, 0x108042, 0x1600fff7, +0x0, 0xc004db9, 0x8021, 0xa7a00020, +0xc004d78, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0xc004d78, 0x24040001, +0xc004d78, 0x2021, 0x24100010, 0xc004d78, +0x2021, 0x108042, 0x1600fffc, 0x0, +0x24100010, 0x3202001e, 0x10400002, 0x2021, +0x24040001, 0xc004d78, 0x108042, 0x1600fffa, +0x3202001e, 0xc004db9, 0x34108000, 0xc004db9, +0x0, 0xc004d58, 0x0, 0x50400005, +0x108042, 0x97a20020, 0x501025, 0xa7a20020, +0x108042, 0x1600fff7, 0x0, 0xc004db9, +0x8021, 0xa7a00022, 0xc004d78, 0x24040001, +0x26100001, 0x2e020020, 0x1440fffb, 0x0, +0xc004d78, 0x2021, 0xc004d78, 0x24040001, +0xc004d78, 0x2021, 0xc004d78, 0x24040001, +0x24100010, 0xc004d78, 0x2021, 0x108042, +0x1600fffc, 0x0, 0x24100010, 0xc004d78, +0x2021, 0x108042, 0x1600fffc, 0x0, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, +0x34108000, 0x97a20022, 0x501024, 0x10400002, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fff8, 0x0, 0xc004db9, 0x0, +0x24040018, 0x24050002, 0xc004ddb, 0x24060004, +0x3c100001, 0x8e106e24, 0x24020001, 0x1602011d, +0x0, 0x3c020001, 0x94426f26, 0x3c010001, +0xac206e24, 0x24429fbc, 0x2c420004, 0x1040000c, +0x24040009, 0x24050001, 0xc004ddb, 0x24060400, +0x24040018, 0x24050001, 0xc004ddb, 0x24060020, +0x24040018, 0x24050001, 0xc004ddb, 0x24062000, +0x3c024000, 0x2421024, 0x10400123, 0x3c022000, +0x2421024, 0x10400004, 0x0, 0x3c010001, +0x10000003, 0xac306f1c, 0x3c010001, 0xac206f1c, +0x3c030001, 0x8c636f34, 0x24020005, 0x146200f9, +0x0, 0x3c020001, 0x8c426f1c, 0x10400067, +0x3c020004, 0x2421024, 0x10400011, 0xa7a00018, +0x3c020008, 0x2421024, 0x10400002, 0x24020200, +0xa7a20018, 0x3c020010, 0x2421024, 0x10400004, +0x0, 0x97a20018, 0x34420100, 0xa7a20018, +0x97a60018, 0x24040009, 0x10000004, 0x2821, +0x24040009, 0x2821, 0x3021, 0xc004ddb, +0x0, 0x24020001, 0xa7a2001a, 0x3c020008, +0x2421024, 0x1040000c, 0x3c020002, 0x2421024, +0x10400002, 0x24020101, 0xa7a2001a, 0x3c020001, +0x2421024, 0x10400005, 0x3c020010, 0x97a2001a, +0x34420040, 0xa7a2001a, 0x3c020010, 0x2421024, +0x1040000e, 0x3c020002, 0x2421024, 0x10400005, +0x3c020001, 0x97a2001a, 0x34420080, 0xa7a2001a, +0x3c020001, 0x2421024, 0x10400005, 0x3c0300a0, +0x97a2001a, 0x34420020, 0xa7a2001a, 0x3c0300a0, +0x2431024, 0x54430004, 0x3c020020, 0x97a2001a, +0x1000000c, 0x34420400, 0x2421024, 0x50400004, +0x3c020080, 0x97a2001a, 0x10000006, 0x34420800, +0x2421024, 0x10400004, 0x0, 0x97a2001a, +0x34420c00, 0xa7a2001a, 0x97a6001a, 0x24040004, +0xc004ddb, 0x2821, 0x3c020004, 0x2421024, +0x10400004, 0xa7a0001c, 0x32425000, 0x14400004, +0x0, 0x32424000, 0x10400005, 0x2021, +0xc004cf9, 0x2402021, 0x10000096, 0x0, +0x97a6001c, 0x2821, 0x34c61200, 0xc004ddb, +0xa7a6001c, 0x1000008f, 0x0, 0x2421024, +0x10400004, 0xa7a00018, 0x32425000, 0x14400004, +0x0, 0x32424000, 0x10400005, 0x3c020010, +0xc004cf9, 0x2402021, 0x10000019, 0xa7a0001a, 0x2421024, 0x10400004, 0x0, 0x97a20018, 0x10000004, 0xa7a20018, 0x97a20018, 0x34420100, 0xa7a20018, 0x3c020001, 0x2421024, 0x10400004, 0x0, 0x97a20018, 0x10000004, 0xa7a20018, -0x97a20018, 0x34422000, 0xa7a20018, 0x2021, -0x97a60018, 0x2821, 0xc004e0e, 0x8021, -0xa7a0001a, 0xc004dab, 0x24040001, 0x26100001, -0x2e020020, 0x1440fffb, 0x0, 0xc004dab, -0x2021, 0xc004dab, 0x24040001, 0xc004dab, -0x24040001, 0xc004dab, 0x2021, 0x24100010, +0x97a20018, 0x34422000, 0xa7a20018, 0x97a60018, +0x2021, 0xc004ddb, 0x2821, 0xa7a0001a, +0x8021, 0xc004d78, 0x24040001, 0x26100001, +0x2e020020, 0x1440fffb, 0x0, 0xc004d78, +0x2021, 0xc004d78, 0x24040001, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020001, -0x24100010, 0xc004dab, 0x2021, 0x108042, -0x1600fffc, 0x0, 0xc004dec, 0x34108000, -0xc004dec, 0x0, 0xc004d8b, 0x0, +0xc004d78, 0x108042, 0x1600fffa, 0x32020001, +0x24100010, 0xc004d78, 0x2021, 0x108042, +0x1600fffc, 0x0, 0xc004db9, 0x34108000, +0xc004db9, 0x0, 0xc004d58, 0x0, 0x50400005, 0x108042, 0x97a2001a, 0x501025, 0xa7a2001a, 0x108042, 0x1600fff7, 0x0, -0xc004dec, 0x8021, 0xa7a0001a, 0xc004dab, +0xc004db9, 0x8021, 0xa7a0001a, 0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004dab, 0x2021, 0xc004dab, -0x24040001, 0xc004dab, 0x24040001, 0xc004dab, +0x0, 0xc004d78, 0x2021, 0xc004d78, +0x24040001, 0xc004d78, 0x24040001, 0xc004d78, 0x2021, 0x24100010, 0x32020001, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fffa, 0x32020001, 0x24100010, 0xc004dab, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fffa, 0x32020001, 0x24100010, 0xc004d78, 0x2021, 0x108042, 0x1600fffc, 0x0, -0xc004dec, 0x34108000, 0xc004dec, 0x0, -0xc004d8b, 0x0, 0x50400005, 0x108042, +0xc004db9, 0x34108000, 0xc004db9, 0x0, +0xc004d58, 0x0, 0x50400005, 0x108042, 0x97a2001a, 0x501025, 0xa7a2001a, 0x108042, -0x1600fff7, 0x0, 0xc004dec, 0x0, -0x3c040001, 0x24846c5c, 0x97a60018, 0x97a7001a, -0x3c020001, 0x8c426e18, 0x3c030001, 0x8c636f98, -0x3c05000d, 0x34a50205, 0xafa20010, 0xc002b17, +0x1600fff7, 0x0, 0xc004db9, 0x0, +0x3c040001, 0x24846bcc, 0x97a60018, 0x97a7001a, +0x3c020001, 0x8c426d98, 0x3c030001, 0x8c636f1c, +0x3c05000d, 0x34a50205, 0xafa20010, 0xc002b3b, 0xafa30014, 0x8f830054, 0x24020004, 0x3c010001, -0xac226e54, 0x3c010001, 0x10000179, 0xac236fb0, -0x8f830054, 0x3c020001, 0x8c426fb0, 0x2463ff9c, -0x431023, 0x2c420064, 0x14400009, 0x27b10018, -0x8f820220, 0x24030005, 0x3c010001, 0xac236e54, -0x3c03f700, 0x431025, 0xaf820220, 0x27b10018, -0xa7a00018, 0x8021, 0xc004dab, 0x24040001, -0x26100001, 0x2e020020, 0x1440fffb, 0x0, -0xc004dab, 0x2021, 0xc004dab, 0x24040001, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, -0x24100010, 0x32020001, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fffa, -0x32020001, 0x24100010, 0xc004dab, 0x2021, -0x108042, 0x1600fffc, 0x0, 0xc004dec, -0x34108000, 0xc004dec, 0x0, 0xc004d8b, -0x0, 0x50400005, 0x108042, 0x96220000, -0x501025, 0xa6220000, 0x108042, 0x1600fff7, -0x0, 0xc004dec, 0x8021, 0xa7a0001a, -0xc004dab, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0xc004dab, 0x24040001, -0xc004dab, 0x2021, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004dab, -0x108042, 0x1600fffa, 0x32020001, 0x24100010, -0x32020001, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020001, -0xc004dec, 0x34108000, 0xc004dec, 0x0, -0xc004d8b, 0x0, 0x50400005, 0x108042, -0x97a2001a, 0x501025, 0xa7a2001a, 0x108042, -0x1600fff7, 0x0, 0xc004dec, 0x8021, -0xa7a0001a, 0xc004dab, 0x24040001, 0x26100001, -0x2e020020, 0x1440fffb, 0x0, 0xc004dab, -0x2021, 0xc004dab, 0x24040001, 0xc004dab, -0x24040001, 0xc004dab, 0x2021, 0x24100010, -0x32020001, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020001, -0x24100010, 0x32020001, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fffa, -0x32020001, 0xc004dec, 0x34108000, 0xc004dec, -0x0, 0xc004d8b, 0x0, 0x50400005, -0x108042, 0x97a2001a, 0x501025, 0xa7a2001a, -0x108042, 0x1600fff7, 0x0, 0xc004dec, -0x8021, 0xa7a0001c, 0xc004dab, 0x24040001, -0x26100001, 0x2e020020, 0x1440fffb, 0x0, -0xc004dab, 0x2021, 0xc004dab, 0x24040001, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, -0x24100010, 0x32020001, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fffa, -0x32020001, 0x24100010, 0x32020004, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fffa, 0x32020004, 0xc004dec, 0x34108000, -0xc004dec, 0x0, 0xc004d8b, 0x0, -0x50400005, 0x108042, 0x97a2001c, 0x501025, -0xa7a2001c, 0x108042, 0x1600fff7, 0x0, -0xc004dec, 0x8021, 0xa7a0001c, 0xc004dab, -0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004dab, 0x2021, 0xc004dab, -0x24040001, 0xc004dab, 0x24040001, 0xc004dab, -0x2021, 0x24100010, 0x32020001, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fffa, 0x32020001, 0x24100010, 0x32020004, -0x10400002, 0x2021, 0x24040001, 0xc004dab, -0x108042, 0x1600fffa, 0x32020004, 0xc004dec, -0x34108000, 0xc004dec, 0x0, 0xc004d8b, -0x0, 0x50400005, 0x108042, 0x97a2001c, -0x501025, 0xa7a2001c, 0x108042, 0x1600fff7, -0x0, 0xc004dec, 0x8021, 0xa7a00020, -0xc004dab, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0xc004dab, 0x24040001, -0xc004dab, 0x2021, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004dab, -0x108042, 0x1600fffa, 0x32020001, 0x24100010, -0x32020019, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020019, -0xc004dec, 0x34108000, 0xc004dec, 0x0, -0xc004d8b, 0x0, 0x50400005, 0x108042, -0x97a20020, 0x501025, 0xa7a20020, 0x108042, -0x1600fff7, 0x0, 0xc004dec, 0x8021, -0xa7a00020, 0xc004dab, 0x24040001, 0x26100001, -0x2e020020, 0x1440fffb, 0x0, 0xc004dab, -0x2021, 0xc004dab, 0x24040001, 0xc004dab, -0x24040001, 0xc004dab, 0x2021, 0x24100010, -0x32020001, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020001, -0x24100010, 0x32020019, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fffa, -0x32020019, 0xc004dec, 0x34108000, 0xc004dec, -0x0, 0xc004d8b, 0x0, 0x50400005, -0x108042, 0x97a20020, 0x501025, 0xa7a20020, -0x108042, 0x1600fff7, 0x0, 0xc004dec, -0x0, 0x97a60018, 0x97a7001a, 0x97a2001c, -0x3c040001, 0x24846c5c, 0xafa20010, 0x97a20020, -0x3c05000d, 0x34a50204, 0xc002b17, 0xafa20014, -0x10000007, 0x0, 0x24020006, 0x3c010001, -0xac226e54, 0x24020011, 0x3c010001, 0xac226e50, -0x8fbf0034, 0x8fb20030, 0x8fb1002c, 0x8fb00028, -0x3e00008, 0x27bd0038, 0x8f850044, 0x8f820044, -0x3c030001, 0x431025, 0x3c030008, 0xaf820044, -0x8f840054, 0x8f820054, 0xa32824, 0x10000002, -0x24840001, 0x8f820054, 0x821023, 0x2c420002, -0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe, -0x3463ffff, 0x431024, 0xaf820044, 0x8f830054, -0x8f820054, 0x10000002, 0x24630001, 0x8f820054, -0x621023, 0x2c420002, 0x1440fffc, 0x0, -0x3e00008, 0xa01021, 0x8f830044, 0x3c02fff0, -0x3442ffff, 0x42480, 0x621824, 0x3c020002, -0x822025, 0x641825, 0xaf830044, 0x8f820044, +0xac226dd4, 0x3c010001, 0x10000017, 0xac236f38, +0x8f830054, 0x3c020001, 0x8c426f38, 0x2463ff9c, +0x431023, 0x2c420064, 0x1440000f, 0x0, +0x8f820220, 0x24030005, 0x3c010001, 0xac236dd4, +0x3c03f700, 0x431025, 0x10000007, 0xaf820220, +0x24020006, 0x3c010001, 0xac226dd4, 0x24020011, +0x3c010001, 0xac226dd0, 0x8fbf0034, 0x8fb20030, +0x8fb1002c, 0x8fb00028, 0x3e00008, 0x27bd0038, +0x27bdffd8, 0xafb00018, 0x808021, 0xafb1001c, +0x8821, 0x32024000, 0x10400013, 0xafbf0020, +0x3c020010, 0x2021024, 0x2c420001, 0x21023, +0x30434100, 0x3c020001, 0x2021024, 0x14400006, +0x34714000, 0x3c020002, 0x2021024, 0x14400002, +0x34716000, 0x34714040, 0x2021, 0x2821, +0x10000036, 0x2203021, 0x32021000, 0x10400035, +0x2021, 0x2821, 0xc004ddb, 0x24060040, +0x24040018, 0x2821, 0xc004ddb, 0x24060c00, +0x24040017, 0x2821, 0xc004ddb, 0x24060400, +0x24040016, 0x2821, 0xc004ddb, 0x24060006, +0x24040017, 0x2821, 0xc004ddb, 0x24062500, +0x24040016, 0x2821, 0xc004ddb, 0x24060006, +0x24040017, 0x2821, 0xc004ddb, 0x24064600, +0x24040016, 0x2821, 0xc004ddb, 0x24060006, +0x24040017, 0x2821, 0xc004ddb, 0x24066700, +0x24040016, 0x2821, 0xc004ddb, 0x24060006, +0x2404001f, 0x2821, 0xc004ddb, 0x24060010, +0x24040009, 0x2821, 0xc004ddb, 0x24061500, +0x24040009, 0x2821, 0x24061d00, 0xc004ddb, +0x0, 0x3c040001, 0x24846bf0, 0x3c05000e, +0x34a50100, 0x2003021, 0x2203821, 0xafa00010, +0xc002b3b, 0xafa00014, 0x8fbf0020, 0x8fb1001c, +0x8fb00018, 0x3e00008, 0x27bd0028, 0x8f850044, +0x8f820044, 0x3c030001, 0x431025, 0x3c030008, +0xaf820044, 0x8f840054, 0x8f820054, 0xa32824, +0x10000002, 0x24840001, 0x8f820054, 0x821023, +0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, -0x0, 0x8f820044, 0x3c030001, 0x431025, +0x0, 0x3e00008, 0xa01021, 0x8f830044, +0x3c02fff0, 0x3442ffff, 0x42480, 0x621824, +0x3c020002, 0x822025, 0x641825, 0xaf830044, +0x8f820044, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, -0x1440fffc, 0x0, 0x3e00008, 0x0, -0x8f820044, 0x2403ff7f, 0x431024, 0xaf820044, -0x8f830054, 0x8f820054, 0x10000002, 0x24630001, -0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, -0x0, 0x8f820044, 0x34420080, 0xaf820044, -0x8f830054, 0x8f820054, 0x10000002, 0x24630001, -0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, -0x0, 0x3e00008, 0x0, 0x8f820044, -0x3c03fff0, 0x3463ffff, 0x431024, 0xaf820044, -0x8f820044, 0x3c030001, 0x431025, 0xaf820044, -0x8f830054, 0x8f820054, 0x10000002, 0x24630001, -0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, -0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff, -0x431024, 0xaf820044, 0x8f830054, 0x8f820054, +0x1440fffc, 0x0, 0x8f820044, 0x3c030001, +0x431025, 0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x3e00008, -0x0, 0x27bdffc8, 0xafb30024, 0x809821, -0xafbe002c, 0xa0f021, 0xafb20020, 0xc09021, -0x33c2ffff, 0xafbf0030, 0xafb50028, 0xafb1001c, -0xafb00018, 0x14400034, 0xa7b20010, 0x3271ffff, -0x27b20010, 0x8021, 0xc004dab, 0x24040001, -0x26100001, 0x2e020020, 0x1440fffb, 0x0, -0xc004dab, 0x2021, 0xc004dab, 0x24040001, -0xc004dab, 0x2021, 0xc004dab, 0x24040001, -0x24100010, 0x32020001, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fffa, -0x32020001, 0x24100010, 0x2301024, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fffa, 0x2301024, 0xc004dab, 0x24040001, -0xc004dab, 0x2021, 0x34108000, 0x96420000, -0x501024, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x12000075, 0x0, -0x1000fff6, 0x0, 0x3275ffff, 0x27b10010, -0xa7a00010, 0x8021, 0xc004dab, 0x24040001, -0x26100001, 0x2e020020, 0x1440fffb, 0x0, -0xc004dab, 0x2021, 0xc004dab, 0x24040001, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, -0x24100010, 0x32020001, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fffa, -0x32020001, 0x24100010, 0x2b01024, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fffa, 0x2b01024, 0xc004dec, 0x34108000, -0xc004dec, 0x0, 0xc004d8b, 0x0, -0x50400005, 0x108042, 0x96220000, 0x501025, -0xa6220000, 0x108042, 0x1600fff7, 0x0, -0xc004dec, 0x0, 0x33c5ffff, 0x24020001, -0x54a20004, 0x24020002, 0x97a20010, 0x10000006, -0x521025, 0x14a20006, 0x3271ffff, 0x97a20010, -0x121827, 0x431024, 0xa7a20010, 0x3271ffff, -0x27b20010, 0x8021, 0xc004dab, 0x24040001, -0x26100001, 0x2e020020, 0x1440fffb, 0x0, -0xc004dab, 0x2021, 0xc004dab, 0x24040001, -0xc004dab, 0x2021, 0xc004dab, 0x24040001, -0x24100010, 0x32020001, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fffa, -0x32020001, 0x24100010, 0x2301024, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fffa, 0x2301024, 0xc004dab, 0x24040001, -0xc004dab, 0x2021, 0x34108000, 0x96420000, -0x501024, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fff8, 0x0, -0xc004dec, 0x0, 0x8fbf0030, 0x8fbe002c, -0x8fb50028, 0x8fb30024, 0x8fb20020, 0x8fb1001c, -0x8fb00018, 0x3e00008, 0x27bd0038, 0x27bdffe8, +0x0, 0x8f820044, 0x2403ff7f, 0x431024, +0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, +0x24630001, 0x8f820054, 0x621023, 0x2c420002, +0x1440fffc, 0x0, 0x8f820044, 0x34420080, +0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, +0x24630001, 0x8f820054, 0x621023, 0x2c420002, +0x1440fffc, 0x0, 0x3e00008, 0x0, +0x8f820044, 0x3c03fff0, 0x3463ffff, 0x431024, +0xaf820044, 0x8f820044, 0x3c030001, 0x431025, +0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, +0x24630001, 0x8f820054, 0x621023, 0x2c420002, +0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe, +0x3463ffff, 0x431024, 0xaf820044, 0x8f830054, +0x8f820054, 0x10000002, 0x24630001, 0x8f820054, +0x621023, 0x2c420002, 0x1440fffc, 0x0, +0x3e00008, 0x0, 0x27bdffc8, 0xafb30024, +0x809821, 0xafbe002c, 0xa0f021, 0xafb20020, +0xc09021, 0x33c2ffff, 0xafbf0030, 0xafb50028, +0xafb1001c, 0xafb00018, 0x14400034, 0xa7b20010, +0x3271ffff, 0x27b20010, 0x8021, 0xc004d78, +0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, +0x0, 0xc004d78, 0x2021, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0xc004d78, +0x24040001, 0x24100010, 0x32020001, 0x10400002, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fffa, 0x32020001, 0x24100010, 0x2301024, +0x10400002, 0x2021, 0x24040001, 0xc004d78, +0x108042, 0x1600fffa, 0x2301024, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0x34108000, +0x96420000, 0x501024, 0x10400002, 0x2021, +0x24040001, 0xc004d78, 0x108042, 0x12000075, +0x0, 0x1000fff6, 0x0, 0x3275ffff, +0x27b10010, 0xa7a00010, 0x8021, 0xc004d78, +0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, +0x0, 0xc004d78, 0x2021, 0xc004d78, +0x24040001, 0xc004d78, 0x24040001, 0xc004d78, +0x2021, 0x24100010, 0x32020001, 0x10400002, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fffa, 0x32020001, 0x24100010, 0x2b01024, +0x10400002, 0x2021, 0x24040001, 0xc004d78, +0x108042, 0x1600fffa, 0x2b01024, 0xc004db9, +0x34108000, 0xc004db9, 0x0, 0xc004d58, +0x0, 0x50400005, 0x108042, 0x96220000, +0x501025, 0xa6220000, 0x108042, 0x1600fff7, +0x0, 0xc004db9, 0x0, 0x33c5ffff, +0x24020001, 0x54a20004, 0x24020002, 0x97a20010, +0x10000006, 0x521025, 0x14a20006, 0x3271ffff, +0x97a20010, 0x121827, 0x431024, 0xa7a20010, +0x3271ffff, 0x27b20010, 0x8021, 0xc004d78, +0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, +0x0, 0xc004d78, 0x2021, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0xc004d78, +0x24040001, 0x24100010, 0x32020001, 0x10400002, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fffa, 0x32020001, 0x24100010, 0x2301024, +0x10400002, 0x2021, 0x24040001, 0xc004d78, +0x108042, 0x1600fffa, 0x2301024, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0x34108000, +0x96420000, 0x501024, 0x10400002, 0x2021, +0x24040001, 0xc004d78, 0x108042, 0x1600fff8, +0x0, 0xc004db9, 0x0, 0x8fbf0030, +0x8fbe002c, 0x8fb50028, 0x8fb30024, 0x8fb20020, +0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0038, +0x0, 0x0, 0x0, 0x27bdffe8, 0xafbf0010, 0x8ee304b8, 0x24020008, 0x146201e0, -0x0, 0x3c020001, 0x8c426f98, 0x14400005, -0x0, 0xc003d87, 0x8f840224, 0x100001d8, +0x0, 0x3c020001, 0x8c426f1c, 0x14400005, +0x0, 0xc003daf, 0x8f840224, 0x100001d8, 0x0, 0x8f820220, 0x3c030008, 0x431024, 0x10400026, 0x24020001, 0x8f840224, 0x8f820220, 0x3c030400, 0x431024, 0x10400006, 0x0, -0x3c010002, 0xac209020, 0x3c010002, 0x1000000b, -0xac209040, 0x3c030002, 0x24639020, 0x8c620000, +0x3c010002, 0xac208fa0, 0x3c010002, 0x1000000b, +0xac208fc0, 0x3c030002, 0x24638fa0, 0x8c620000, 0x24420001, 0xac620000, 0x2c420002, 0x14400003, -0x24020001, 0x3c010002, 0xac229040, 0x3c020002, -0x8c429040, 0x10400006, 0x30820040, 0x10400004, -0x24020001, 0x3c010002, 0x10000003, 0xac229044, -0x3c010002, 0xac209044, 0x3c010002, 0xac24901c, -0x3c010002, 0x1000000b, 0xac209050, 0x3c010002, -0xac229050, 0x3c010002, 0xac209040, 0x3c010002, -0xac209020, 0x3c010002, 0xac209044, 0x3c010002, -0xac20901c, 0x3c030002, 0x8c639010, 0x3c020002, -0x8c429014, 0x50620004, 0x2463ffff, 0x3c010002, -0xac239014, 0x2463ffff, 0x2c62000e, 0x10400194, -0x31080, 0x3c010001, 0x220821, 0x8c226c80, +0x24020001, 0x3c010002, 0xac228fc0, 0x3c020002, +0x8c428fc0, 0x10400006, 0x30820040, 0x10400004, +0x24020001, 0x3c010002, 0x10000003, 0xac228fc4, +0x3c010002, 0xac208fc4, 0x3c010002, 0xac248f9c, +0x3c010002, 0x1000000b, 0xac208fd0, 0x3c010002, +0xac228fd0, 0x3c010002, 0xac208fc0, 0x3c010002, +0xac208fa0, 0x3c010002, 0xac208fc4, 0x3c010002, +0xac208f9c, 0x3c030002, 0x8c638f90, 0x3c020002, +0x8c428f94, 0x50620004, 0x2463ffff, 0x3c010002, +0xac238f94, 0x2463ffff, 0x2c62000e, 0x10400194, +0x31080, 0x3c010001, 0x220821, 0x8c226c00, 0x400008, 0x0, 0x24020002, 0x3c010002, -0xac209040, 0x3c010002, 0xac209020, 0x3c010002, -0xac20901c, 0x3c010002, 0xac209044, 0x3c010002, -0xac209038, 0x3c010002, 0xac209030, 0xaf800224, -0x3c010002, 0xac229010, 0x3c020002, 0x8c429050, -0x1440004f, 0x3c02fdff, 0x3442ffff, 0xc003d87, +0xac208fc0, 0x3c010002, 0xac208fa0, 0x3c010002, +0xac208f9c, 0x3c010002, 0xac208fc4, 0x3c010002, +0xac208fb8, 0x3c010002, 0xac208fb0, 0xaf800224, +0x3c010002, 0xac228f90, 0x3c020002, 0x8c428fd0, +0x1440004f, 0x3c02fdff, 0x3442ffff, 0xc003daf, 0x282a024, 0xaf800204, 0x8f820200, 0x2403fffd, -0x431024, 0xaf820200, 0x3c010002, 0xac209060, -0x8f830054, 0x3c020002, 0x8c429038, 0x24040001, -0x3c010002, 0xac24904c, 0x24420001, 0x3c010002, -0xac229038, 0x2c420004, 0x3c010002, 0xac239034, -0x14400006, 0x24020003, 0x3c010001, 0xac246e1c, -0x3c010002, 0x1000015e, 0xac209038, 0x3c010002, -0x1000015b, 0xac229010, 0x8f830054, 0x3c020002, -0x8c429034, 0x2463d8f0, 0x431023, 0x2c422710, -0x14400003, 0x24020004, 0x3c010002, 0xac229010, -0x3c020002, 0x8c429050, 0x14400021, 0x3c02fdff, +0x431024, 0xaf820200, 0x3c010002, 0xac208fe0, +0x8f830054, 0x3c020002, 0x8c428fb8, 0x24040001, +0x3c010002, 0xac248fcc, 0x24420001, 0x3c010002, +0xac228fb8, 0x2c420004, 0x3c010002, 0xac238fb4, +0x14400006, 0x24020003, 0x3c010001, 0xac246d9c, +0x3c010002, 0x1000015e, 0xac208fb8, 0x3c010002, +0x1000015b, 0xac228f90, 0x8f830054, 0x3c020002, +0x8c428fb4, 0x2463d8f0, 0x431023, 0x2c422710, +0x14400003, 0x24020004, 0x3c010002, 0xac228f90, +0x3c020002, 0x8c428fd0, 0x14400021, 0x3c02fdff, 0x3442ffff, 0x1000014a, 0x282a024, 0x3c040001, -0x8c846f9c, 0x3c010002, 0xc0050b4, 0xac209028, -0x3c020002, 0x8c42905c, 0xaf820204, 0x3c020002, -0x8c429050, 0x14400012, 0x3c03fdff, 0x8f820204, +0x8c846f20, 0x3c010002, 0xc005084, 0xac208fa8, +0x3c020002, 0x8c428fdc, 0xaf820204, 0x3c020002, +0x8c428fd0, 0x14400012, 0x3c03fdff, 0x8f820204, 0x3463ffff, 0x30420030, 0x1440012f, 0x283a024, -0x3c030002, 0x8c63905c, 0x24020005, 0x3c010002, -0xac229010, 0x3c010002, 0x10000131, 0xac239060, -0x3c020002, 0x8c429050, 0x10400010, 0x3c02fdff, -0x3c020001, 0x8c426ebc, 0x24420001, 0x3c010001, -0xac226ebc, 0x2c420002, 0x14400125, 0x24020001, -0x3c010001, 0xac226ec4, 0x3c010001, 0xac206ebc, -0x3c010001, 0x1000011e, 0xac226e1c, 0x3c030002, -0x8c639040, 0x3442ffff, 0x10600119, 0x282a024, -0x3c020002, 0x8c42901c, 0x10400115, 0x0, -0x3c010002, 0xac229048, 0x24020003, 0x3c010002, -0xac229020, 0x100000b8, 0x24020006, 0x3c010002, -0xac209028, 0x8f820204, 0x34420040, 0xaf820204, -0x3c020002, 0x8c429060, 0x24030007, 0x3c010002, -0xac239010, 0x34420040, 0x3c010002, 0xac229060, -0x3c020002, 0x8c429040, 0x10400005, 0x0, -0x3c020002, 0x8c42901c, 0x104000f0, 0x24020002, -0x3c050002, 0x24a59020, 0x8ca20000, 0x2c424e21, -0x104000ea, 0x24020002, 0x3c020002, 0x8c429044, -0x104000ef, 0x2404ffbf, 0x3c020002, 0x8c42901c, -0x3c030002, 0x8c639048, 0x441024, 0x641824, +0x3c030002, 0x8c638fdc, 0x24020005, 0x3c010002, +0xac228f90, 0x3c010002, 0x10000131, 0xac238fe0, +0x3c020002, 0x8c428fd0, 0x10400010, 0x3c02fdff, +0x3c020001, 0x8c426e3c, 0x24420001, 0x3c010001, +0xac226e3c, 0x2c420002, 0x14400125, 0x24020001, +0x3c010001, 0xac226e44, 0x3c010001, 0xac206e3c, +0x3c010001, 0x1000011e, 0xac226d9c, 0x3c030002, +0x8c638fc0, 0x3442ffff, 0x10600119, 0x282a024, +0x3c020002, 0x8c428f9c, 0x10400115, 0x0, +0x3c010002, 0xac228fc8, 0x24020003, 0x3c010002, +0xac228fa0, 0x100000b8, 0x24020006, 0x3c010002, +0xac208fa8, 0x8f820204, 0x34420040, 0xaf820204, +0x3c020002, 0x8c428fe0, 0x24030007, 0x3c010002, +0xac238f90, 0x34420040, 0x3c010002, 0xac228fe0, +0x3c020002, 0x8c428fc0, 0x10400005, 0x0, +0x3c020002, 0x8c428f9c, 0x104000f0, 0x24020002, +0x3c050002, 0x24a58fa0, 0x8ca20000, 0x2c424e21, +0x104000ea, 0x24020002, 0x3c020002, 0x8c428fc4, +0x104000ef, 0x2404ffbf, 0x3c020002, 0x8c428f9c, +0x3c030002, 0x8c638fc8, 0x441024, 0x641824, 0x10430004, 0x24020001, 0x3c010002, 0x100000e4, -0xac229010, 0x24020003, 0xaca20000, 0x24020008, -0x3c010002, 0xac229010, 0x3c020002, 0x8c42904c, -0x1040000c, 0x24020001, 0x3c040002, 0xc0050c1, -0x8c84901c, 0x3c020002, 0x8c429068, 0x14400005, -0x24020001, 0x3c020002, 0x8c429064, 0x10400006, -0x24020001, 0x3c010001, 0xac226e1c, 0x3c010002, -0x100000cb, 0xac209038, 0x3c020002, 0x8c429030, -0x3c030002, 0x8c63901c, 0x2c420001, 0x210c0, -0x30630008, 0x3c010002, 0xac229030, 0x3c010002, -0xac23902c, 0x8f830054, 0x24020009, 0x3c010002, -0xac229010, 0x3c010002, 0x100000b9, 0xac239034, -0x8f830054, 0x3c020002, 0x8c429034, 0x2463d8f0, +0xac228f90, 0x24020003, 0xaca20000, 0x24020008, +0x3c010002, 0xac228f90, 0x3c020002, 0x8c428fcc, +0x1040000c, 0x24020001, 0x3c040002, 0xc005091, +0x8c848f9c, 0x3c020002, 0x8c428fe8, 0x14400005, +0x24020001, 0x3c020002, 0x8c428fe4, 0x10400006, +0x24020001, 0x3c010001, 0xac226d9c, 0x3c010002, +0x100000cb, 0xac208fb8, 0x3c020002, 0x8c428fb0, +0x3c030002, 0x8c638f9c, 0x2c420001, 0x210c0, +0x30630008, 0x3c010002, 0xac228fb0, 0x3c010002, +0xac238fac, 0x8f830054, 0x24020009, 0x3c010002, +0xac228f90, 0x3c010002, 0x100000b9, 0xac238fb4, +0x8f830054, 0x3c020002, 0x8c428fb4, 0x2463d8f0, 0x431023, 0x2c422710, 0x1440009f, 0x0, -0x3c020002, 0x8c429040, 0x10400005, 0x0, -0x3c020002, 0x8c42901c, 0x104000a0, 0x24020002, -0x3c030002, 0x24639020, 0x8c620000, 0x2c424e21, -0x1040009a, 0x24020002, 0x3c020002, 0x8c42904c, -0x1040000e, 0x0, 0x3c020002, 0x8c42901c, -0x3c010002, 0xac20904c, 0x30420080, 0x1040002f, +0x3c020002, 0x8c428fc0, 0x10400005, 0x0, +0x3c020002, 0x8c428f9c, 0x104000a0, 0x24020002, +0x3c030002, 0x24638fa0, 0x8c620000, 0x2c424e21, +0x1040009a, 0x24020002, 0x3c020002, 0x8c428fcc, +0x1040000e, 0x0, 0x3c020002, 0x8c428f9c, +0x3c010002, 0xac208fcc, 0x30420080, 0x1040002f, 0x2402000c, 0x8f820204, 0x30420080, 0x1440000c, 0x24020003, 0x10000029, 0x2402000c, 0x3c020002, -0x8c42901c, 0x30420080, 0x14400005, 0x24020003, +0x8c428f9c, 0x30420080, 0x14400005, 0x24020003, 0x8f820204, 0x30420080, 0x1040001f, 0x24020003, -0xac620000, 0x2402000a, 0x3c010002, 0xac229010, -0x3c040002, 0x24849058, 0x8c820000, 0x3c030002, -0x8c639030, 0x431025, 0xaf820204, 0x8c830000, -0x3c040002, 0x8c849030, 0x2402000b, 0x3c010002, -0xac229010, 0x641825, 0x3c010002, 0xac239060, -0x3c050002, 0x24a59020, 0x8ca20000, 0x2c424e21, -0x10400066, 0x24020002, 0x3c020002, 0x8c429050, +0xac620000, 0x2402000a, 0x3c010002, 0xac228f90, +0x3c040002, 0x24848fd8, 0x8c820000, 0x3c030002, +0x8c638fb0, 0x431025, 0xaf820204, 0x8c830000, +0x3c040002, 0x8c848fb0, 0x2402000b, 0x3c010002, +0xac228f90, 0x641825, 0x3c010002, 0xac238fe0, +0x3c050002, 0x24a58fa0, 0x8ca20000, 0x2c424e21, +0x10400066, 0x24020002, 0x3c020002, 0x8c428fd0, 0x10400005, 0x0, 0x2402000c, 0x3c010002, -0x10000067, 0xac229010, 0x3c020002, 0x8c429040, -0x10400063, 0x0, 0x3c040002, 0x8c84901c, -0x10800055, 0x30820008, 0x3c030002, 0x8c63902c, -0x1062005b, 0x24020003, 0x3c010002, 0xac249048, +0x10000067, 0xac228f90, 0x3c020002, 0x8c428fc0, +0x10400063, 0x0, 0x3c040002, 0x8c848f9c, +0x10800055, 0x30820008, 0x3c030002, 0x8c638fac, +0x1062005b, 0x24020003, 0x3c010002, 0xac248fc8, 0xaca20000, 0x24020006, 0x3c010002, 0x10000054, -0xac229010, 0x8f820200, 0x34420002, 0xaf820200, -0x8f830054, 0x2402000d, 0x3c010002, 0xac229010, -0x3c010002, 0xac239034, 0x8f830054, 0x3c020002, -0x8c429034, 0x2463d8f0, 0x431023, 0x2c422710, -0x14400031, 0x0, 0x3c020002, 0x8c429050, -0x10400020, 0x2402000e, 0x3c030002, 0x8c639064, -0x3c010002, 0x14600015, 0xac229010, 0xc003e45, -0x0, 0x3c050001, 0x8ca56e18, 0xc0052c7, -0x2021, 0x3c030001, 0x8c636e18, 0x24020004, -0x14620005, 0x2403fffb, 0x3c020001, 0x8c426e14, -0x10000003, 0x2403fff7, 0x3c020001, 0x8c426e14, -0x431024, 0x3c010001, 0xac226e14, 0x8f830224, -0x3c020200, 0x3c010002, 0xac23906c, 0x10000020, -0x282a025, 0x3c020002, 0x8c429040, 0x10400005, -0x0, 0x3c020002, 0x8c42901c, 0x1040000f, -0x24020002, 0x3c020002, 0x8c429020, 0x2c424e21, -0x1040000a, 0x24020002, 0x3c020002, 0x8c429040, -0x1040000f, 0x0, 0x3c020002, 0x8c42901c, +0xac228f90, 0x8f820200, 0x34420002, 0xaf820200, +0x8f830054, 0x2402000d, 0x3c010002, 0xac228f90, +0x3c010002, 0xac238fb4, 0x8f830054, 0x3c020002, +0x8c428fb4, 0x2463d8f0, 0x431023, 0x2c422710, +0x14400031, 0x0, 0x3c020002, 0x8c428fd0, +0x10400020, 0x2402000e, 0x3c030002, 0x8c638fe4, +0x3c010002, 0x14600015, 0xac228f90, 0xc003e6d, +0x0, 0x3c050001, 0x8ca56d98, 0xc00529b, +0x2021, 0x3c030001, 0x8c636d98, 0x24020004, +0x14620005, 0x2403fffb, 0x3c020001, 0x8c426d94, +0x10000003, 0x2403fff7, 0x3c020001, 0x8c426d94, +0x431024, 0x3c010001, 0xac226d94, 0x8f830224, +0x3c020200, 0x3c010002, 0xac238fec, 0x10000020, +0x282a025, 0x3c020002, 0x8c428fc0, 0x10400005, +0x0, 0x3c020002, 0x8c428f9c, 0x1040000f, +0x24020002, 0x3c020002, 0x8c428fa0, 0x2c424e21, +0x1040000a, 0x24020002, 0x3c020002, 0x8c428fc0, +0x1040000f, 0x0, 0x3c020002, 0x8c428f9c, 0x1440000b, 0x0, 0x24020002, 0x3c010002, -0x10000007, 0xac229010, 0x3c020002, 0x8c429040, -0x10400003, 0x0, 0xc003d87, 0x0, +0x10000007, 0xac228f90, 0x3c020002, 0x8c428fc0, +0x10400003, 0x0, 0xc003daf, 0x0, 0x8f820220, 0x3c03f700, 0x431025, 0xaf820220, 0x8fbf0010, 0x3e00008, 0x27bd0018, 0x3c030002, -0x24639068, 0x8c620000, 0x10400005, 0x34422000, -0x3c010002, 0xac22905c, 0x10000003, 0xac600000, -0x3c010002, 0xac24905c, 0x3e00008, 0x0, +0x24638fe8, 0x8c620000, 0x10400005, 0x34422000, +0x3c010002, 0xac228fdc, 0x10000003, 0xac600000, +0x3c010002, 0xac248fdc, 0x3e00008, 0x0, 0x27bdffe0, 0x30820030, 0xafbf0018, 0x3c010002, -0xac229064, 0x14400067, 0x3c02ffff, 0x34421f0e, +0xac228fe4, 0x14400067, 0x3c02ffff, 0x34421f0e, 0x821024, 0x14400061, 0x24020030, 0x30822000, 0x1040005d, 0x30838000, 0x31a02, 0x30820001, -0x21200, 0x3c040001, 0x8c846f9c, 0x621825, -0x331c2, 0x3c030001, 0x24636ec8, 0x30828000, +0x21200, 0x3c040001, 0x8c846f20, 0x621825, +0x331c2, 0x3c030001, 0x24636e48, 0x30828000, 0x21202, 0x30840001, 0x42200, 0x441025, 0x239c2, 0x61080, 0x431021, 0x471021, 0x90430000, 0x24020001, 0x10620025, 0x0, @@ -8775,354 +8758,357 @@ 0x1062002c, 0x3c05000f, 0x10000037, 0x0, 0x8f820200, 0x2403feff, 0x431024, 0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024, -0xaf820220, 0x3c010002, 0xac209084, 0x3c010002, -0x10000034, 0xac20908c, 0x8f820200, 0x34420100, +0xaf820220, 0x3c010002, 0xac209004, 0x3c010002, +0x10000034, 0xac20900c, 0x8f820200, 0x34420100, 0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820220, 0x24020100, 0x3c010002, -0xac229084, 0x3c010002, 0x10000026, 0xac20908c, +0xac229004, 0x3c010002, 0x10000026, 0xac20900c, 0x8f820200, 0x2403feff, 0x431024, 0xaf820200, 0x8f820220, 0x3c030001, 0x431025, 0xaf820220, -0x3c010002, 0xac209084, 0x3c010002, 0x10000019, -0xac23908c, 0x8f820200, 0x34420100, 0xaf820200, +0x3c010002, 0xac209004, 0x3c010002, 0x10000019, +0xac23900c, 0x8f820200, 0x34420100, 0xaf820200, 0x8f820220, 0x3c030001, 0x431025, 0xaf820220, -0x24020100, 0x3c010002, 0xac229084, 0x3c010002, -0x1000000c, 0xac23908c, 0x34a5ffff, 0x3c040001, -0x24846cb8, 0xafa30010, 0xc002b17, 0xafa00014, +0x24020100, 0x3c010002, 0xac229004, 0x3c010002, +0x1000000c, 0xac23900c, 0x34a5ffff, 0x3c040001, +0x24846c38, 0xafa30010, 0xc002b3b, 0xafa00014, 0x10000004, 0x0, 0x24020030, 0x3c010002, -0xac229068, 0x8fbf0018, 0x3e00008, 0x27bd0020, +0xac228fe8, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x0, 0x0, 0x0, 0x27bdffc8, 0xafb20028, 0x809021, 0xafb3002c, 0xa09821, -0xafb00020, 0xc08021, 0x3c040001, 0x24846cd0, -0x3c050009, 0x3c020001, 0x8c426e18, 0x34a59001, +0xafb00020, 0xc08021, 0x3c040001, 0x24846c50, +0x3c050009, 0x3c020001, 0x8c426d98, 0x34a59001, 0x2403021, 0x2603821, 0xafbf0030, 0xafb10024, -0xa7a0001a, 0xafb00014, 0xc002b17, 0xafa20010, -0x24020002, 0x1262007f, 0x2e620003, 0x10400005, -0x24020001, 0x1262000a, 0x0, 0x1000016f, -0x0, 0x24020004, 0x126200f4, 0x24020008, -0x126200f3, 0x3c02ffec, 0x10000168, 0x0, -0x3c020001, 0x8c426e14, 0x30420002, 0x14400004, +0xa7a0001a, 0xafb00014, 0xc002b3b, 0xafa20010, +0x24020002, 0x12620083, 0x2e620003, 0x10400005, +0x24020001, 0x1262000a, 0x0, 0x10000173, +0x0, 0x24020004, 0x126200f8, 0x24020008, +0x126200f7, 0x3c02ffec, 0x1000016c, 0x0, +0x3c020001, 0x8c426d94, 0x30420002, 0x14400004, 0x128940, 0x3c02fffb, 0x3442ffff, 0x2028024, -0x3c010002, 0x310821, 0xac30907c, 0x3c024000, -0x2021024, 0x1040004a, 0x1023c2, 0x30840030, -0x101382, 0x3042001c, 0x3c030001, 0x24636e58, +0x3c010002, 0x310821, 0xac308ffc, 0x3c024000, +0x2021024, 0x1040004e, 0x1023c2, 0x30840030, +0x101382, 0x3042001c, 0x3c030001, 0x24636dd8, 0x431021, 0x823821, 0x3c020020, 0x2021024, 0x10400006, 0x24020100, 0x3c010002, 0x310821, -0xac229080, 0x10000005, 0x3c020080, 0x3c010002, -0x310821, 0xac209080, 0x3c020080, 0x2021024, +0xac229000, 0x10000005, 0x3c020080, 0x3c010002, +0x310821, 0xac209000, 0x3c020080, 0x2021024, 0x10400006, 0x121940, 0x3c020001, 0x3c010002, -0x230821, 0x10000005, 0xac229088, 0x121140, -0x3c010002, 0x220821, 0xac209088, 0x94e30000, -0x32024000, 0x10400003, 0xa7a30018, 0x34624000, +0x230821, 0x10000005, 0xac229008, 0x121140, +0x3c010002, 0x220821, 0xac209008, 0x94e40000, +0x3c030001, 0x8c636f40, 0x24020005, 0x10620010, +0xa7a40018, 0x32024000, 0x10400002, 0x34824000, 0xa7a20018, 0x24040001, 0x94e20002, 0x24050004, -0x24e60002, 0x34420001, 0xc00450e, 0xa4e20002, -0x24040001, 0x2821, 0xc00450e, 0x27a60018, -0x3c020001, 0x8c426e18, 0x24110001, 0x3c010001, -0xac316e24, 0x14530004, 0x32028000, 0xc003d87, +0x24e60002, 0x34420001, 0xc0045be, 0xa4e20002, +0x24040001, 0x2821, 0xc0045be, 0x27a60018, +0x3c020001, 0x8c426d98, 0x24110001, 0x3c010001, +0xac316da4, 0x14530004, 0x32028000, 0xc003daf, 0x0, 0x32028000, 0x1040011c, 0x0, -0xc003d87, 0x0, 0x3c030001, 0x8c636fb8, +0xc003daf, 0x0, 0x3c030001, 0x8c636f40, 0x24020005, 0x10620115, 0x24020002, 0x3c010001, -0xac316e1c, 0x3c010001, 0x10000110, 0xac226e18, -0x24040001, 0x24050004, 0x27b0001a, 0xc00450e, -0x2003021, 0x24040001, 0x2821, 0xc00450e, -0x2003021, 0x3c020002, 0x511021, 0x8c429074, -0x3c040001, 0x8c846e18, 0x3c03bfff, 0x3463ffff, -0x3c010001, 0xac336e24, 0x431024, 0x3c010002, -0x310821, 0x109300f7, 0xac229074, 0x100000f7, +0xac316d9c, 0x3c010001, 0x10000110, 0xac226d98, +0x24040001, 0x24050004, 0x27b0001a, 0xc0045be, +0x2003021, 0x24040001, 0x2821, 0xc0045be, +0x2003021, 0x3c020002, 0x511021, 0x8c428ff4, +0x3c040001, 0x8c846d98, 0x3c03bfff, 0x3463ffff, +0x3c010001, 0xac336da4, 0x431024, 0x3c010002, +0x310821, 0x109300f7, 0xac228ff4, 0x100000f7, 0x0, 0x3c022000, 0x2021024, 0x10400005, -0x24020001, 0x3c010001, 0xac226f98, 0x10000004, -0x128940, 0x3c010001, 0xac206f98, 0x128940, -0x3c010002, 0x310821, 0xac309078, 0x3c024000, +0x24020001, 0x3c010001, 0xac226f1c, 0x10000004, +0x128940, 0x3c010001, 0xac206f1c, 0x128940, +0x3c010002, 0x310821, 0xac308ff8, 0x3c024000, 0x2021024, 0x14400014, 0x0, 0x3c020001, -0x8c426f98, 0x10400006, 0x24040004, 0x24050001, -0xc004e0e, 0x24062000, 0x24020001, 0xaee204b8, -0x3c020002, 0x511021, 0x8c429070, 0x3c03bfff, +0x8c426f1c, 0x10400006, 0x24040004, 0x24050001, +0xc004ddb, 0x24062000, 0x24020001, 0xaee204b8, +0x3c020002, 0x511021, 0x8c428ff0, 0x3c03bfff, 0x3463ffff, 0x431024, 0x3c010002, 0x310821, -0x100000d0, 0xac229070, 0x3c020001, 0x8c426f98, +0x100000d0, 0xac228ff0, 0x3c020001, 0x8c426f1c, 0x10400028, 0x3c0300a0, 0x2031024, 0x5443000d, -0x3c020020, 0x3c020001, 0x8c426f9c, 0x24030100, -0x3c010002, 0x310821, 0xac239084, 0x3c030001, -0x3c010002, 0x310821, 0xac23908c, 0x10000015, +0x3c020020, 0x3c020001, 0x8c426f20, 0x24030100, +0x3c010002, 0x310821, 0xac239004, 0x3c030001, +0x3c010002, 0x310821, 0xac23900c, 0x10000015, 0x34420400, 0x2021024, 0x10400008, 0x24030100, -0x3c020001, 0x8c426f9c, 0x3c010002, 0x310821, -0xac239084, 0x1000000b, 0x34420800, 0x3c020080, +0x3c020001, 0x8c426f20, 0x3c010002, 0x310821, +0xac239004, 0x1000000b, 0x34420800, 0x3c020080, 0x2021024, 0x1040002e, 0x3c030001, 0x3c020001, -0x8c426f9c, 0x3c010002, 0x310821, 0xac23908c, -0x34420c00, 0x3c010001, 0xac226f9c, 0x10000025, +0x8c426f20, 0x3c010002, 0x310821, 0xac23900c, +0x34420c00, 0x3c010001, 0xac226f20, 0x10000025, 0x24040001, 0x3c020020, 0x2021024, 0x10400006, -0x24020100, 0x3c010002, 0x310821, 0xac229084, +0x24020100, 0x3c010002, 0x310821, 0xac229004, 0x10000005, 0x3c020080, 0x3c010002, 0x310821, -0xac209084, 0x3c020080, 0x2021024, 0x10400007, +0xac209004, 0x3c020080, 0x2021024, 0x10400007, 0x121940, 0x3c020001, 0x3c010002, 0x230821, -0xac22908c, 0x10000006, 0x24040001, 0x121140, -0x3c010002, 0x220821, 0xac20908c, 0x24040001, -0x2821, 0x27b0001e, 0xc0044cc, 0x2003021, -0x24040001, 0x2821, 0xc0044cc, 0x2003021, -0x24040001, 0x24050001, 0x27b0001c, 0xc0044cc, -0x2003021, 0x24040001, 0x24050001, 0xc0044cc, +0xac22900c, 0x10000006, 0x24040001, 0x121140, +0x3c010002, 0x220821, 0xac20900c, 0x24040001, +0x2821, 0x27b0001e, 0xc00457c, 0x2003021, +0x24040001, 0x2821, 0xc00457c, 0x2003021, +0x24040001, 0x24050001, 0x27b0001c, 0xc00457c, +0x2003021, 0x24040001, 0x24050001, 0xc00457c, 0x2003021, 0x10000077, 0x0, 0x3c02ffec, 0x3442ffff, 0x2028024, 0x3c020008, 0x2028025, -0x121140, 0x3c010002, 0x220821, 0xac309078, +0x121140, 0x3c010002, 0x220821, 0xac308ff8, 0x3c022000, 0x2021024, 0x10400009, 0x0, -0x3c020001, 0x8c426ec4, 0x14400005, 0x24020001, -0x3c010001, 0xac226f98, 0x10000004, 0x3c024000, -0x3c010001, 0xac206f98, 0x3c024000, 0x2021024, -0x1440001d, 0x24020e01, 0x3c030001, 0x8c636f98, -0xaf820238, 0x3c010001, 0xac206e30, 0x10600005, -0x24022020, 0x3c010001, 0xac226f9c, 0x24020001, +0x3c020001, 0x8c426e44, 0x14400005, 0x24020001, +0x3c010001, 0xac226f1c, 0x10000004, 0x3c024000, +0x3c010001, 0xac206f1c, 0x3c024000, 0x2021024, +0x1440001d, 0x24020e01, 0x3c030001, 0x8c636f1c, +0xaf820238, 0x3c010001, 0xac206db0, 0x10600005, +0x24022020, 0x3c010001, 0xac226f20, 0x24020001, 0xaee204b8, 0x3c04bfff, 0x121940, 0x3c020002, -0x431021, 0x8c429070, 0x3c050001, 0x8ca56e18, +0x431021, 0x8c428ff0, 0x3c050001, 0x8ca56d98, 0x3484ffff, 0x441024, 0x3c010002, 0x230821, -0xac229070, 0x24020001, 0x10a20044, 0x0, -0x10000040, 0x0, 0x3c020001, 0x8c426f98, -0x1040001c, 0x24022000, 0x3c010001, 0xac226f9c, +0xac228ff0, 0x24020001, 0x10a20044, 0x0, +0x10000040, 0x0, 0x3c020001, 0x8c426f1c, +0x1040001c, 0x24022000, 0x3c010001, 0xac226f20, 0x3c0300a0, 0x2031024, 0x14430005, 0x121140, -0x3402a000, 0x3c010001, 0x1000002d, 0xac226f9c, -0x3c030002, 0x621821, 0x8c639078, 0x3c020020, +0x3402a000, 0x3c010001, 0x1000002d, 0xac226f20, +0x3c030002, 0x621821, 0x8c638ff8, 0x3c020020, 0x621024, 0x10400004, 0x24022001, 0x3c010001, -0x10000023, 0xac226f9c, 0x3c020080, 0x621024, +0x10000023, 0xac226f20, 0x3c020080, 0x621024, 0x1040001f, 0x3402a001, 0x3c010001, 0x1000001c, -0xac226f9c, 0x3c020020, 0x2021024, 0x10400007, +0xac226f20, 0x3c020020, 0x2021024, 0x10400007, 0x121940, 0x24020100, 0x3c010002, 0x230821, -0xac229084, 0x10000006, 0x3c020080, 0x121140, -0x3c010002, 0x220821, 0xac209084, 0x3c020080, +0xac229004, 0x10000006, 0x3c020080, 0x121140, +0x3c010002, 0x220821, 0xac209004, 0x3c020080, 0x2021024, 0x10400006, 0x121940, 0x3c020001, -0x3c010002, 0x230821, 0x10000005, 0xac22908c, -0x121140, 0x3c010002, 0x220821, 0xac20908c, -0x3c030001, 0x8c636e18, 0x24020001, 0x10620003, -0x0, 0xc003d87, 0x0, 0x8fbf0030, +0x3c010002, 0x230821, 0x10000005, 0xac22900c, +0x121140, 0x3c010002, 0x220821, 0xac20900c, +0x3c030001, 0x8c636d98, 0x24020001, 0x10620003, +0x0, 0xc003daf, 0x0, 0x8fbf0030, 0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020, -0x3e00008, 0x27bd0038, 0x27bdffb8, 0xafbe003c, -0x80f021, 0xafb30034, 0x9821, 0xafb20030, -0x9021, 0xafb1002c, 0x8821, 0x24020002, -0xafbf0040, 0xafb50038, 0xafb00028, 0xa7a00020, -0xa7a00018, 0xa7a0001a, 0xa7a0001c, 0xa7a0001e, -0x10a20142, 0xa7a00022, 0x2ca20003, 0x10400005, -0x24020001, 0x10a2000a, 0x1ea940, 0x10000253, -0x2201021, 0x24020004, 0x10a20203, 0x24020008, -0x10a20202, 0x1e2940, 0x1000024c, 0x2201021, -0x3c030002, 0x751821, 0x8c63907c, 0x3c024000, -0x621024, 0x14400009, 0x24040001, 0x3c027fff, -0x3442ffff, 0x628824, 0x3c010002, 0x350821, -0xac319074, 0x1000023d, 0x2201021, 0x2821, -0xc0044cc, 0x27a60018, 0x24040001, 0x2821, -0xc0044cc, 0x27a60018, 0x24040001, 0x24050001, -0x27b0001a, 0xc0044cc, 0x2003021, 0x24040001, -0x24050001, 0xc0044cc, 0x2003021, 0x24040001, -0x24050004, 0x27b0001c, 0xc0044cc, 0x2003021, -0x24040001, 0x24050004, 0xc0044cc, 0x2003021, -0x24040001, 0x24050005, 0x27b0001e, 0xc0044cc, -0x2003021, 0x24040001, 0x24050005, 0xc0044cc, -0x2003021, 0x24040001, 0x24050009, 0xc0044cc, -0x2003021, 0x24040001, 0x24050009, 0xc0044cc, -0x2003021, 0x24040001, 0x24050001, 0xc0044cc, -0x27a60018, 0x24040001, 0x24050001, 0xc0044cc, -0x27a60018, 0x97a20018, 0x30420004, 0x104000ba, -0x3c114000, 0x3c020001, 0x8c426fb8, 0x2443ffff, -0x2c620006, 0x104000ba, 0x31080, 0x3c010001, -0x220821, 0x8c226ce8, 0x400008, 0x0, -0x24040001, 0x24050011, 0x27b00020, 0xc0044cc, -0x2003021, 0x24040001, 0x24050011, 0xc0044cc, -0x2003021, 0x97a30020, 0x30624000, 0x10400002, -0x3c120010, 0x3c120008, 0x3c130001, 0x30628000, -0x54400098, 0x3c130002, 0x10000097, 0x3c028000, -0x24040001, 0x24050014, 0x27b00020, 0xc0044cc, -0x2003021, 0x24040001, 0x24050014, 0xc0044cc, -0x2003021, 0x97a30020, 0x30621000, 0x10400002, -0x3c120010, 0x3c120008, 0x3c130001, 0x1000ffec, -0x30620800, 0x24040001, 0x24050019, 0x27b00022, -0xc0044cc, 0x2003021, 0x24040001, 0x24050019, -0xc0044cc, 0x2003021, 0x97a20022, 0x30430700, -0x24020400, 0x10620027, 0x28620401, 0x1040000e, -0x24020200, 0x1062001f, 0x28620201, 0x10400005, -0x24020100, 0x5062001e, 0x3c130001, 0x1000001e, -0x24040001, 0x24020300, 0x50620019, 0x3c130002, -0x10000019, 0x24040001, 0x24020600, 0x1062000d, -0x28620601, 0x10400005, 0x24020500, 0x5062000b, -0x3c130002, 0x10000010, 0x24040001, 0x24020700, -0x1462000d, 0x24040001, 0x3c130004, 0x1000000a, -0x3c120008, 0x10000006, 0x3c130004, 0x10000005, -0x3c120008, 0x3c130001, 0x10000002, 0x3c120008, -0x3c120010, 0x24040001, 0x24050010, 0x27b0001c, -0xc0044cc, 0x2003021, 0x24040001, 0x24050010, -0xc0044cc, 0x2003021, 0x3c020004, 0x16620010, -0x3c020001, 0x8f840054, 0x24030001, 0x24020002, -0x3c010001, 0xac236e1c, 0x3c010001, 0xac226e18, -0x3c010001, 0xac236e24, 0x3c010001, 0xac236ea4, -0x3c010001, 0xac246fa8, 0x10000041, 0x2538825, -0x16620035, 0x3c028000, 0x3c020001, 0x8c426ea0, -0x1440001e, 0x24040018, 0x2021, 0x2821, -0xc004e0e, 0x34068000, 0x8f830054, 0x8f820054, -0x2538825, 0x10000002, 0x24630032, 0x8f820054, -0x621023, 0x2c420033, 0x1440fffc, 0x0, -0x8f830054, 0x24020001, 0x3c010001, 0xac226ea0, -0x3c010001, 0xac226e1c, 0x3c010001, 0xac226e18, -0x3c010001, 0xac226e24, 0x3c010001, 0xac226ea4, -0x3c010001, 0x1000001e, 0xac236fa8, 0x2821, -0xc004e0e, 0x24060404, 0x2021, 0x2405001e, -0x27a60018, 0x24020002, 0xc00450e, 0xa7a20018, -0x2021, 0x2821, 0x27a60018, 0xc00450e, -0xa7a00018, 0x24040018, 0x24050002, 0xc004e0e, -0x24060004, 0x3c028000, 0x2221025, 0x2721825, -0x10000007, 0x438825, 0x3c110002, 0x2358821, -0x8e31907c, 0x3c027fff, 0x3442ffff, 0x2228824, -0x3c020001, 0x8c426e28, 0x1040001c, 0x0, -0x3c020001, 0x8c426f98, 0x10400002, 0x3c022000, -0x2228825, 0x1e1140, 0x3c010002, 0x220821, -0x8c229080, 0x10400003, 0x3c020020, 0x10000004, +0x3e00008, 0x27bd0038, 0x27bdffb0, 0xafb3003c, +0x9821, 0xafb50040, 0xa821, 0xafb10034, +0x8821, 0x24020002, 0xafbf0048, 0xafbe0044, +0xafb20038, 0xafb00030, 0xafa4002c, 0xa7a0001a, +0xa7a00018, 0xa7a00020, 0xa7a0001e, 0xa7a00022, +0x10a20130, 0xa7a0001c, 0x2ca20003, 0x10400005, +0x24020001, 0x10a2000a, 0x3c024000, 0x1000025d, +0x2201021, 0x24020004, 0x10a2020a, 0x24020008, +0x10a20208, 0x2201021, 0x10000256, 0x0, +0x8fa8002c, 0x88140, 0x3c030002, 0x701821, +0x8c638ffc, 0x621024, 0x14400009, 0x24040001, +0x3c027fff, 0x3442ffff, 0x628824, 0x3c010002, +0x300821, 0xac318ff4, 0x10000246, 0x2201021, +0x24050001, 0xc00457c, 0x27a60018, 0x24040001, +0x24050001, 0xc00457c, 0x27a60018, 0x97a20018, +0x30420004, 0x104000d9, 0x3c114000, 0x3c020001, +0x8c426f40, 0x2443ffff, 0x2c620006, 0x104000d9, +0x31080, 0x3c010001, 0x220821, 0x8c226c68, +0x400008, 0x0, 0x24040001, 0x24050011, +0x27b0001a, 0xc00457c, 0x2003021, 0x24040001, +0x24050011, 0xc00457c, 0x2003021, 0x97a3001a, +0x30624000, 0x10400002, 0x3c150010, 0x3c150008, +0x30628000, 0x104000aa, 0x3c130001, 0x100000a8, +0x3c130002, 0x24040001, 0x24050014, 0x27b0001a, +0xc00457c, 0x2003021, 0x24040001, 0x24050014, +0xc00457c, 0x2003021, 0x97a3001a, 0x30621000, +0x10400002, 0x3c150010, 0x3c150008, 0x30620800, +0x10400097, 0x3c130001, 0x10000095, 0x3c130002, +0x24040001, 0x24050019, 0x27b0001c, 0xc00457c, +0x2003021, 0x24040001, 0x24050019, 0xc00457c, +0x2003021, 0x97a2001c, 0x30430700, 0x24020400, +0x10620027, 0x28620401, 0x1040000e, 0x24020200, +0x1062001f, 0x28620201, 0x10400005, 0x24020100, +0x5062001e, 0x3c130001, 0x1000001e, 0x24040001, +0x24020300, 0x50620019, 0x3c130002, 0x10000019, +0x24040001, 0x24020600, 0x1062000d, 0x28620601, +0x10400005, 0x24020500, 0x5062000b, 0x3c130002, +0x10000010, 0x24040001, 0x24020700, 0x1462000d, +0x24040001, 0x3c130004, 0x1000000a, 0x3c150008, +0x10000006, 0x3c130004, 0x10000005, 0x3c150008, +0x3c130001, 0x10000002, 0x3c150008, 0x3c150010, +0x24040001, 0x24050018, 0x27b0001e, 0xc00457c, +0x2003021, 0x24040001, 0x24050018, 0xc00457c, +0x2003021, 0x8fa8002c, 0x97a7001e, 0x81140, +0x3c060002, 0xc23021, 0x8cc68ff4, 0x97a20022, +0x3c100001, 0x26106c5c, 0x2002021, 0xafa20010, +0x97a2001c, 0x3c05000c, 0x34a50303, 0xc002b3b, +0xafa20014, 0x3c020004, 0x16620010, 0x3c020001, +0x8f840054, 0x24030001, 0x24020002, 0x3c010001, +0xac236d9c, 0x3c010001, 0xac226d98, 0x3c010001, +0xac236da4, 0x3c010001, 0xac236e24, 0x3c010001, +0xac246f30, 0x1000004f, 0x2b38825, 0x16620039, +0x3c028000, 0x3c020001, 0x8c426e20, 0x1440001e, +0x24040018, 0x2021, 0x2821, 0xc004ddb, +0x34068000, 0x8f830054, 0x8f820054, 0x2b38825, +0x10000002, 0x24630032, 0x8f820054, 0x621023, +0x2c420033, 0x1440fffc, 0x0, 0x8f830054, +0x24020001, 0x3c010001, 0xac226e20, 0x3c010001, +0xac226d9c, 0x3c010001, 0xac226d98, 0x3c010001, +0xac226da4, 0x3c010001, 0xac226e24, 0x3c010001, +0x1000002c, 0xac236f30, 0x2821, 0xc004ddb, +0x24060404, 0x2021, 0x2405001e, 0x27a60018, +0x24020002, 0xc0045be, 0xa7a20018, 0x2021, +0x2821, 0x27a60018, 0xc0045be, 0xa7a00018, +0x24040018, 0x24050002, 0xc004ddb, 0x24060004, +0x3c028000, 0x2221025, 0x2b31825, 0x10000015, +0x438825, 0x2221025, 0x2751825, 0x438825, +0x2002021, 0x97a6001c, 0x3c070001, 0x8ce76d98, +0x3c05000c, 0x34a50326, 0xafb30010, 0xc002b3b, +0xafb10014, 0x10000007, 0x0, 0x3c110002, +0x2308821, 0x8e318ffc, 0x3c027fff, 0x3442ffff, +0x2228824, 0x3c020001, 0x8c426da8, 0x1040001e, +0x0, 0x3c020001, 0x8c426f1c, 0x10400002, +0x3c022000, 0x2228825, 0x8fa8002c, 0x81140, +0x3c010002, 0x220821, 0x8c229000, 0x10400003, +0x3c020020, 0x10000005, 0x2228825, 0x3c02ffdf, +0x3442ffff, 0x2228824, 0x8fa8002c, 0x81140, +0x3c010002, 0x220821, 0x8c229008, 0x10400003, +0x3c020080, 0x10000004, 0x2228825, 0x3c02ff7f, +0x3442ffff, 0x2228824, 0x8fa8002c, 0x81140, +0x3c010002, 0x220821, 0xac318ff4, 0x10000135, +0x2201021, 0x8fa8002c, 0x8f140, 0x3c030002, +0x7e1821, 0x8c638ff8, 0x3c024000, 0x621024, +0x14400009, 0x24040001, 0x3c027fff, 0x3442ffff, +0x628824, 0x3c010002, 0x3e0821, 0xac318ff0, +0x10000124, 0x2201021, 0x2821, 0xc00457c, +0x27a60018, 0x24040001, 0x2821, 0xc00457c, +0x27a60018, 0x24040001, 0x24050001, 0x27b20020, +0xc00457c, 0x2403021, 0x24040001, 0x24050001, +0xc00457c, 0x2403021, 0x24040001, 0x24050004, +0x27b1001e, 0xc00457c, 0x2203021, 0x24040001, +0x24050004, 0xc00457c, 0x2203021, 0x24040001, +0x24050005, 0x27b00022, 0xc00457c, 0x2003021, +0x24040001, 0x24050005, 0xc00457c, 0x2003021, +0x24040001, 0x24050010, 0xc00457c, 0x27a60018, +0x24040001, 0x24050010, 0xc00457c, 0x27a60018, +0x24040001, 0x2405000a, 0xc00457c, 0x2403021, +0x24040001, 0x2405000a, 0xc00457c, 0x2403021, +0x24040001, 0x24050018, 0xc00457c, 0x2203021, +0x24040001, 0x24050018, 0xc00457c, 0x2203021, +0x24040001, 0x24050001, 0xc00457c, 0x27a60018, +0x24040001, 0x24050001, 0xc00457c, 0x27a60018, +0x97a20018, 0x30420004, 0x10400066, 0x3c114000, +0x3c030001, 0x8c636f34, 0x24020005, 0x14620067, +0x24040001, 0x24050019, 0x27b0001c, 0xc00457c, +0x2003021, 0x24040001, 0x24050019, 0xc00457c, +0x2003021, 0x97a2001c, 0x30430700, 0x24020400, +0x10620027, 0x28620401, 0x1040000e, 0x24020200, +0x1062001f, 0x28620201, 0x10400005, 0x24020100, +0x5062001e, 0x3c130001, 0x1000001e, 0x3c020004, +0x24020300, 0x50620019, 0x3c130002, 0x10000019, +0x3c020004, 0x24020600, 0x1062000d, 0x28620601, +0x10400005, 0x24020500, 0x5062000b, 0x3c130002, +0x10000010, 0x3c020004, 0x24020700, 0x1462000d, +0x3c020004, 0x3c130004, 0x1000000a, 0x3c150008, +0x10000006, 0x3c130004, 0x10000005, 0x3c150008, +0x3c130001, 0x10000002, 0x3c150008, 0x3c150010, +0x3c020004, 0x12620017, 0x3c028000, 0x8f820054, +0x24100001, 0x3c010001, 0xac306d9c, 0x3c010001, +0xac306d98, 0x3c010001, 0xac306da4, 0x3c010001, +0xac306e24, 0x3c010001, 0xac226f30, 0x3c020001, +0x16620022, 0x2758825, 0x2021, 0x2821, +0xc004ddb, 0x34068000, 0x3c010001, 0x1000001b, +0xac306e20, 0x2221025, 0x2b31825, 0x438825, +0x97a6001c, 0x3c020001, 0x8c426f1c, 0x3c070001, +0x8ce76d98, 0x3c040001, 0x24846c5c, 0xafa20010, +0x97a2001e, 0x3c05000c, 0x34a50323, 0x3c010001, +0xac206e20, 0xc002b3b, 0xafa20014, 0x10000007, +0x0, 0x3c110002, 0x23e8821, 0x8e318ff0, +0x3c027fff, 0x3442ffff, 0x2228824, 0x3c020001, +0x8c426da8, 0x10400069, 0x0, 0x3c020001, +0x8c426f1c, 0x10400002, 0x3c022000, 0x2228825, +0x8fa8002c, 0x81140, 0x3c010002, 0x220821, +0x8c229004, 0x10400003, 0x3c020020, 0x10000005, 0x2228825, 0x3c02ffdf, 0x3442ffff, 0x2228824, -0x1e1140, 0x3c010002, 0x220821, 0x8c229088, -0x10400003, 0x3c020080, 0x10000004, 0x2228825, -0x3c02ff7f, 0x3442ffff, 0x2228824, 0x3c040001, -0x24846cdc, 0x3c05000c, 0x97a60022, 0x3c070001, -0x8ce76e18, 0x34a50326, 0x1e1140, 0x3c010002, -0x220821, 0xac319074, 0xafb30010, 0xc002b17, -0xafb10014, 0x10000119, 0x2201021, 0x1ea940, -0x3c030002, 0x751821, 0x8c639078, 0x3c024000, -0x621024, 0x14400009, 0x24040001, 0x3c027fff, -0x3442ffff, 0x628824, 0x3c010002, 0x350821, -0xac319070, 0x10000109, 0x2201021, 0x2821, -0xc0044cc, 0x27a60018, 0x24040001, 0x2821, -0xc0044cc, 0x27a60018, 0x24040001, 0x24050001, -0x27b1001a, 0xc0044cc, 0x2203021, 0x24040001, -0x24050001, 0xc0044cc, 0x2203021, 0x24040001, -0x24050004, 0x27b0001c, 0xc0044cc, 0x2003021, -0x24040001, 0x24050004, 0xc0044cc, 0x2003021, -0x24040001, 0x24050005, 0x27b0001e, 0xc0044cc, -0x2003021, 0x24040001, 0x24050005, 0xc0044cc, -0x2003021, 0x24040001, 0x24050010, 0xc0044cc, -0x27a60018, 0x24040001, 0x24050010, 0xc0044cc, -0x27a60018, 0x24040001, 0x2405000a, 0xc0044cc, -0x2203021, 0x24040001, 0x2405000a, 0xc0044cc, -0x2203021, 0x24040001, 0x24050001, 0xc0044cc, -0x27a60018, 0x24040001, 0x24050001, 0xc0044cc, -0x27a60018, 0x97a20018, 0x30420004, 0x10400058, -0x3c114000, 0x3c030001, 0x8c636fac, 0x24020005, -0x14620059, 0x24040001, 0x24050019, 0x27b00022, -0xc0044cc, 0x2003021, 0x24040001, 0x24050019, -0xc0044cc, 0x2003021, 0x97a20022, 0x30430700, -0x24020400, 0x10620027, 0x28620401, 0x1040000e, -0x24020200, 0x1062001f, 0x28620201, 0x10400005, -0x24020100, 0x5062001e, 0x3c130001, 0x1000001e, -0x3c020004, 0x24020300, 0x50620019, 0x3c130002, -0x10000019, 0x3c020004, 0x24020600, 0x1062000d, -0x28620601, 0x10400005, 0x24020500, 0x5062000b, -0x3c130002, 0x10000010, 0x3c020004, 0x24020700, -0x1462000d, 0x3c020004, 0x3c130004, 0x1000000a, -0x3c120008, 0x10000006, 0x3c130004, 0x10000005, -0x3c120008, 0x3c130001, 0x10000002, 0x3c120008, -0x3c120010, 0x3c020004, 0x12620017, 0x3c028000, -0x8f820054, 0x24100001, 0x3c010001, 0xac306e1c, -0x3c010001, 0xac306e18, 0x3c010001, 0xac306e24, -0x3c010001, 0xac306ea4, 0x3c010001, 0xac226fa8, -0x3c020001, 0x16620014, 0x2728825, 0x2021, -0x2821, 0xc004e0e, 0x34068000, 0x3c010001, -0x1000000d, 0xac306ea0, 0x2221025, 0x2531825, -0x3c010001, 0xac206ea0, 0x10000007, 0x438825, -0x3c110002, 0x2358821, 0x8e319070, 0x3c027fff, -0x3442ffff, 0x2228824, 0x3c020001, 0x8c426e28, -0x10400066, 0x1e1140, 0x3c020001, 0x8c426f98, -0x10400002, 0x3c022000, 0x2228825, 0x1e1140, -0x3c010002, 0x220821, 0x8c229084, 0x10400003, -0x3c020020, 0x10000004, 0x2228825, 0x3c02ffdf, -0x3442ffff, 0x2228824, 0x1e1140, 0x3c010002, -0x220821, 0x8c22908c, 0x10400003, 0x3c020080, -0x1000004d, 0x2228825, 0x3c02ff7f, 0x3442ffff, -0x10000049, 0x2228824, 0x1e2940, 0x3c030002, -0x651821, 0x8c639078, 0x3c024000, 0x621024, +0x8fa8002c, 0x81140, 0x3c010002, 0x220821, +0x8c22900c, 0x10400003, 0x3c020080, 0x1000004f, +0x2228825, 0x3c02ff7f, 0x3442ffff, 0x1000004b, +0x2228824, 0x8fa8002c, 0x82940, 0x3c030002, +0x651821, 0x8c638ff8, 0x3c024000, 0x621024, 0x14400008, 0x3c027fff, 0x3442ffff, 0x628824, -0x3c010002, 0x250821, 0xac319070, 0x1000003f, -0x2201021, 0x3c020001, 0x8c426e28, 0x10400033, -0x3c11c00c, 0x3c020001, 0x8c426ec4, 0x3c04c00c, -0x34842000, 0x3c030001, 0x8c636f98, 0x2102b, +0x3c010002, 0x250821, 0xac318ff0, 0x10000041, +0x2201021, 0x3c020001, 0x8c426da8, 0x10400034, +0x3c11c00c, 0x3c020001, 0x8c426e44, 0x3c04c00c, +0x34842000, 0x3c030001, 0x8c636f1c, 0x2102b, 0x21023, 0x441024, 0x10600003, 0x518825, 0x3c022000, 0x2228825, 0x3c020002, 0x451021, -0x8c429084, 0x10400003, 0x3c020020, 0x10000004, +0x8c429004, 0x10400003, 0x3c020020, 0x10000004, 0x2228825, 0x3c02ffdf, 0x3442ffff, 0x2228824, -0x1e1140, 0x3c010002, 0x220821, 0x8c22908c, -0x10400003, 0x3c020080, 0x10000004, 0x2228825, -0x3c02ff7f, 0x3442ffff, 0x2228824, 0x3c020001, -0x8c426eb0, 0x10400002, 0x3c020800, 0x2228825, -0x3c020001, 0x8c426eb4, 0x10400002, 0x3c020400, -0x2228825, 0x3c020001, 0x8c426eb8, 0x10400006, -0x3c020100, 0x10000004, 0x2228825, 0x3c027fff, -0x3442ffff, 0x628824, 0x1e1140, 0x3c010002, -0x220821, 0xac319070, 0x2201021, 0x8fbf0040, -0x8fbe003c, 0x8fb50038, 0x8fb30034, 0x8fb20030, -0x8fb1002c, 0x8fb00028, 0x3e00008, 0x27bd0048, -0x27bdffd0, 0xafb20028, 0x809021, 0xafbf002c, -0xafb10024, 0xafb00020, 0x8f840200, 0x3c100001, -0x8e106e18, 0x8f860220, 0x24020002, 0x1202005c, -0x2e020003, 0x10400005, 0x24020001, 0x1202000a, -0x121940, 0x1000010c, 0x0, 0x24020004, -0x120200bf, 0x24020008, 0x120200be, 0x128940, -0x10000105, 0x0, 0x3c050002, 0xa32821, -0x8ca5907c, 0x3c100002, 0x2038021, 0x8e109074, -0x3c024000, 0xa21024, 0x10400038, 0x3c020008, -0x2021024, 0x10400020, 0x34840002, 0x3c020002, -0x431021, 0x8c429080, 0x10400005, 0x34840020, -0x34840100, 0x3c020020, 0x10000006, 0x2028025, -0x2402feff, 0x822024, 0x3c02ffdf, 0x3442ffff, -0x2028024, 0x121140, 0x3c010002, 0x220821, -0x8c229088, 0x10400005, 0x3c020001, 0xc23025, -0x3c020080, 0x10000016, 0x2028025, 0x3c02fffe, -0x3442ffff, 0xc23024, 0x3c02ff7f, 0x3442ffff, -0x1000000f, 0x2028024, 0x2402fedf, 0x822024, -0x3c02fffe, 0x3442ffff, 0xc23024, 0x3c02ff5f, -0x3442ffff, 0x2028024, 0x3c010002, 0x230821, -0xac209080, 0x3c010002, 0x230821, 0xac209088, -0xaf840200, 0xaf860220, 0x8f820220, 0x34420002, -0xaf820220, 0x1000000a, 0x121140, 0x3c02bfff, -0x3442ffff, 0x8f830200, 0x2028024, 0x2402fffd, -0x621824, 0xc003d87, 0xaf830200, 0x121140, -0x3c010002, 0x220821, 0x100000b7, 0xac309074, -0x3c020001, 0x8c426f98, 0x10400069, 0x24050004, -0x24040001, 0xc0044cc, 0x27a60018, 0x24040001, -0x24050005, 0xc0044cc, 0x27a6001a, 0x97a30018, -0x97a2001a, 0x3c040001, 0x24846ec8, 0x30630c00, -0x31a82, 0x30420c00, 0x21282, 0xa7a2001a, -0x21080, 0x441021, 0x431021, 0xa7a30018, -0x90480000, 0x24020001, 0x3103ffff, 0x10620029, -0x28620002, 0x10400005, 0x0, 0x10600009, -0x0, 0x1000003d, 0x0, 0x10700013, -0x24020003, 0x1062002c, 0x0, 0x10000037, -0x0, 0x8f820200, 0x2403feff, 0x431024, -0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff, -0x431024, 0xaf820220, 0x3c010002, 0xac209084, -0x3c010002, 0x10000032, 0xac20908c, 0x8f820200, -0x34420100, 0xaf820200, 0x8f820220, 0x3c03fffe, -0x3463ffff, 0x431024, 0xaf820220, 0x24020100, -0x3c010002, 0xac229084, 0x3c010002, 0x10000024, -0xac20908c, 0x8f820200, 0x2403feff, 0x431024, -0xaf820200, 0x8f820220, 0x3c030001, 0x431025, -0xaf820220, 0x3c010002, 0xac209084, 0x3c010002, -0x10000017, 0xac23908c, 0x8f820200, 0x34420100, -0xaf820200, 0x8f820220, 0x3c030001, 0x431025, -0xaf820220, 0x24020100, 0x3c010002, 0xac229084, -0x3c010002, 0x1000000a, 0xac23908c, 0x3c040001, -0x24846d00, 0x97a6001a, 0x97a70018, 0x3c050001, -0x34a5ffff, 0xafa80010, 0xc002b17, 0xafa00014, -0x8f820200, 0x34420002, 0x1000004b, 0xaf820200, -0x128940, 0x3c050002, 0xb12821, 0x8ca59078, -0x3c100002, 0x2118021, 0x8e109070, 0x3c024000, -0xa21024, 0x14400010, 0x0, 0x3c020001, -0x8c426f98, 0x14400005, 0x3c02bfff, 0x8f820200, -0x34420002, 0xaf820200, 0x3c02bfff, 0x3442ffff, -0xc003d87, 0x2028024, 0x3c010002, 0x310821, -0x10000031, 0xac309070, 0x3c020001, 0x8c426f98, -0x10400005, 0x3c020020, 0x3c020001, 0x8c426ec4, -0x10400025, 0x3c020020, 0xa21024, 0x10400007, -0x34840020, 0x24020100, 0x3c010002, 0x310821, -0xac229084, 0x10000006, 0x34840100, 0x3c010002, -0x310821, 0xac209084, 0x2402feff, 0x822024, -0x3c020080, 0xa21024, 0x10400007, 0x121940, -0x3c020001, 0x3c010002, 0x230821, 0xac22908c, -0x10000008, 0xc23025, 0x121140, 0x3c010002, -0x220821, 0xac20908c, 0x3c02fffe, 0x3442ffff, -0xc23024, 0xaf840200, 0xaf860220, 0x8f820220, -0x34420002, 0xaf820220, 0x121140, 0x3c010002, -0x220821, 0xac309070, 0x8fbf002c, 0x8fb20028, -0x8fb10024, 0x8fb00020, 0x3e00008, 0x27bd0030, -0x0, 0x0, 0x0, 0x1821, +0x8fa8002c, 0x81140, 0x3c010002, 0x220821, +0x8c22900c, 0x10400003, 0x3c020080, 0x10000004, +0x2228825, 0x3c02ff7f, 0x3442ffff, 0x2228824, +0x3c020001, 0x8c426e30, 0x10400002, 0x3c020800, +0x2228825, 0x3c020001, 0x8c426e34, 0x10400002, +0x3c020400, 0x2228825, 0x3c020001, 0x8c426e38, +0x10400006, 0x3c020100, 0x10000004, 0x2228825, +0x3c027fff, 0x3442ffff, 0x628824, 0x8fa8002c, +0x81140, 0x3c010002, 0x220821, 0xac318ff0, +0x2201021, 0x8fbf0048, 0x8fbe0044, 0x8fb50040, +0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030, +0x3e00008, 0x27bd0050, 0x27bdffd0, 0xafb20028, +0x809021, 0xafbf002c, 0xafb10024, 0xafb00020, +0x8f840200, 0x3c100001, 0x8e106d98, 0x8f860220, +0x24020002, 0x1202005c, 0x2e020003, 0x10400005, +0x24020001, 0x1202000a, 0x121940, 0x1000010c, +0x0, 0x24020004, 0x120200bf, 0x24020008, +0x120200be, 0x128940, 0x10000105, 0x0, +0x3c050002, 0xa32821, 0x8ca58ffc, 0x3c100002, +0x2038021, 0x8e108ff4, 0x3c024000, 0xa21024, +0x10400038, 0x3c020008, 0x2021024, 0x10400020, +0x34840002, 0x3c020002, 0x431021, 0x8c429000, +0x10400005, 0x34840020, 0x34840100, 0x3c020020, +0x10000006, 0x2028025, 0x2402feff, 0x822024, +0x3c02ffdf, 0x3442ffff, 0x2028024, 0x121140, +0x3c010002, 0x220821, 0x8c229008, 0x10400005, +0x3c020001, 0xc23025, 0x3c020080, 0x10000016, +0x2028025, 0x3c02fffe, 0x3442ffff, 0xc23024, +0x3c02ff7f, 0x3442ffff, 0x1000000f, 0x2028024, +0x2402fedf, 0x822024, 0x3c02fffe, 0x3442ffff, +0xc23024, 0x3c02ff5f, 0x3442ffff, 0x2028024, +0x3c010002, 0x230821, 0xac209000, 0x3c010002, +0x230821, 0xac209008, 0xaf840200, 0xaf860220, +0x8f820220, 0x34420002, 0xaf820220, 0x1000000a, +0x121140, 0x3c02bfff, 0x3442ffff, 0x8f830200, +0x2028024, 0x2402fffd, 0x621824, 0xc003daf, +0xaf830200, 0x121140, 0x3c010002, 0x220821, +0x100000b7, 0xac308ff4, 0x3c020001, 0x8c426f1c, +0x10400069, 0x24050004, 0x24040001, 0xc00457c, +0x27a60018, 0x24040001, 0x24050005, 0xc00457c, +0x27a6001a, 0x97a30018, 0x97a2001a, 0x3c040001, +0x24846e48, 0x30630c00, 0x31a82, 0x30420c00, +0x21282, 0xa7a2001a, 0x21080, 0x441021, +0x431021, 0xa7a30018, 0x90480000, 0x24020001, +0x3103ffff, 0x10620029, 0x28620002, 0x10400005, +0x0, 0x10600009, 0x0, 0x1000003d, +0x0, 0x10700013, 0x24020003, 0x1062002c, +0x0, 0x10000037, 0x0, 0x8f820200, +0x2403feff, 0x431024, 0xaf820200, 0x8f820220, +0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820220, +0x3c010002, 0xac209004, 0x3c010002, 0x10000032, +0xac20900c, 0x8f820200, 0x34420100, 0xaf820200, +0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024, +0xaf820220, 0x24020100, 0x3c010002, 0xac229004, +0x3c010002, 0x10000024, 0xac20900c, 0x8f820200, +0x2403feff, 0x431024, 0xaf820200, 0x8f820220, +0x3c030001, 0x431025, 0xaf820220, 0x3c010002, +0xac209004, 0x3c010002, 0x10000017, 0xac23900c, +0x8f820200, 0x34420100, 0xaf820200, 0x8f820220, +0x3c030001, 0x431025, 0xaf820220, 0x24020100, +0x3c010002, 0xac229004, 0x3c010002, 0x1000000a, +0xac23900c, 0x3c040001, 0x24846c80, 0x97a6001a, +0x97a70018, 0x3c050001, 0x34a5ffff, 0xafa80010, +0xc002b3b, 0xafa00014, 0x8f820200, 0x34420002, +0x1000004b, 0xaf820200, 0x128940, 0x3c050002, +0xb12821, 0x8ca58ff8, 0x3c100002, 0x2118021, +0x8e108ff0, 0x3c024000, 0xa21024, 0x14400010, +0x0, 0x3c020001, 0x8c426f1c, 0x14400005, +0x3c02bfff, 0x8f820200, 0x34420002, 0xaf820200, +0x3c02bfff, 0x3442ffff, 0xc003daf, 0x2028024, +0x3c010002, 0x310821, 0x10000031, 0xac308ff0, +0x3c020001, 0x8c426f1c, 0x10400005, 0x3c020020, +0x3c020001, 0x8c426e44, 0x10400025, 0x3c020020, +0xa21024, 0x10400007, 0x34840020, 0x24020100, +0x3c010002, 0x310821, 0xac229004, 0x10000006, +0x34840100, 0x3c010002, 0x310821, 0xac209004, +0x2402feff, 0x822024, 0x3c020080, 0xa21024, +0x10400007, 0x121940, 0x3c020001, 0x3c010002, +0x230821, 0xac22900c, 0x10000008, 0xc23025, +0x121140, 0x3c010002, 0x220821, 0xac20900c, +0x3c02fffe, 0x3442ffff, 0xc23024, 0xaf840200, +0xaf860220, 0x8f820220, 0x34420002, 0xaf820220, +0x121140, 0x3c010002, 0x220821, 0xac308ff0, +0x8fbf002c, 0x8fb20028, 0x8fb10024, 0x8fb00020, +0x3e00008, 0x27bd0030, 0x0, 0x1821, 0x308400ff, 0x2405ffdf, 0x2406ffbf, 0x641007, 0x30420001, 0x10400004, 0x0, 0x8f820044, 0x10000003, 0x34420040, 0x8f820044, 0x461024, @@ -9131,7 +9117,7 @@ 0x28620008, 0x5440ffee, 0x641007, 0x3e00008, 0x0, 0x2c820008, 0x1040001b, 0x0, 0x2405ffdf, 0x2406ffbf, 0x41880, 0x3c020001, -0x24426ee0, 0x621821, 0x24640004, 0x90620000, +0x24426e60, 0x621821, 0x24640004, 0x90620000, 0x10400004, 0x0, 0x8f820044, 0x10000003, 0x34420040, 0x8f820044, 0x461024, 0xaf820044, 0x8f820044, 0x34420020, 0xaf820044, 0x8f820044, @@ -9180,7 +9166,7 @@ 0x74460000, 0x4d516576, 0x505f4600, 0x5173436f, 0x6e495f46, 0x0, 0x5173436f, 0x6e734600, 0x51725072, 0x6f644600, 0x6261644d, 0x656d537a, -0x0, 0x68774677, 0x56657200, 0x62616448, +0x0, 0x68775665, 0x72000000, 0x62616448, 0x77566572, 0x0, 0x2a2a4441, 0x574e5f41, 0x0, 0x74785278, 0x4266537a, 0x0, 0x62664174, 0x6e4d726b, 0x0, 0x7265645a, @@ -9276,12 +9262,12 @@ 0x0, 0x3f636d64, 0x48737453, 0x0, 0x3f636d64, 0x4d634d64, 0x0, 0x3f636d64, 0x50726f6d, 0x0, 0x3f636d64, 0x4c696e6b, -0x0, 0x3f636d64, 0x45727200, 0x864c, -0x8de0, 0x8de0, 0x8d68, 0x8b0c, -0x8db4, 0x8de0, 0x8724, 0x8794, -0x8924, 0x89fc, 0x89c8, 0x8de0, -0x8804, 0x8ab8, 0x8de0, 0x8ac8, -0x8748, 0x87b8, 0x0, 0x0, +0x0, 0x3f636d64, 0x45727200, 0x86ac, +0x8e5c, 0x8e5c, 0x8de4, 0x8b78, +0x8e30, 0x8e5c, 0x8790, 0x8800, +0x8990, 0x8a68, 0x8a34, 0x8e5c, +0x8870, 0x8b24, 0x8e5c, 0x8b34, +0x87b4, 0x8824, 0x0, 0x0, 0x0, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, @@ -9332,10 +9318,10 @@ 0x2e313220, 0x31393939, 0x2f30312f, 0x32302031, 0x393a3439, 0x3a353120, 0x73687561, 0x6e672045, 0x78702024, 0x0, 0x46575f56, 0x45525349, -0x4f4e3a20, 0x23312053, 0x61742044, 0x65632031, -0x31203136, 0x3a30353a, 0x30332050, 0x53542031, -0x39393900, 0x46575f43, 0x4f4d5049, 0x4c455f54, -0x494d453a, 0x2031363a, 0x30353a30, 0x33000000, +0x4f4e3a20, 0x23312046, 0x72692041, 0x70722037, +0x2031373a, 0x35373a35, 0x32205044, 0x54203230, +0x30300000, 0x46575f43, 0x4f4d5049, 0x4c455f54, +0x494d453a, 0x2031373a, 0x35373a35, 0x32000000, 0x46575f43, 0x4f4d5049, 0x4c455f42, 0x593a2064, 0x65767263, 0x73000000, 0x46575f43, 0x4f4d5049, 0x4c455f48, 0x4f53543a, 0x20636f6d, 0x70757465, @@ -9343,7 +9329,7 @@ 0x4f4d4149, 0x4e3a2065, 0x6e672e61, 0x6374656f, 0x6e2e636f, 0x6d000000, 0x46575f43, 0x4f4d5049, 0x4c45523a, 0x20676363, 0x20766572, 0x73696f6e, -0x20322e37, 0x2e320000, 0x0, 0x12040100, +0x20322e37, 0x2e320000, 0x0, 0x12041100, 0x0, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, @@ -9411,31 +9397,32 @@ 0x6e495f46, 0x0, 0x5173436f, 0x6e734600, 0x51725072, 0x6f644600, 0x0, 0x0, 0x0, 0x50726f62, 0x65506879, 0x0, -0x6c6e6b41, 0x53535254, 0x0, 0x108d0, -0x10948, 0x10968, 0x109a4, 0x10ea8, -0x109d0, 0x10a0c, 0x10f3c, 0x10c18, -0x10ac0, 0x10ad8, 0x10b1c, 0x10b44, -0x10b64, 0x10b8c, 0x10f3c, 0x10c18, -0x10c50, 0x10c68, 0x10c98, 0x10cc0, -0x10ce0, 0x10d08, 0x0, 0x10e34, -0x10e60, 0x10e84, 0x10f3c, 0x10ea8, -0x109d0, 0x10ed8, 0x0, 0x0, -0x0, 0x115ac, 0x1167c, 0x11754, -0x11824, 0x11880, 0x1195c, 0x11984, -0x11a60, 0x11a88, 0x11c30, 0x11c58, -0x11e00, 0x11ff8, 0x1228c, 0x121a0, -0x1228c, 0x122b8, 0x11e28, 0x11fd0, -0x7273745f, 0x676d6969, 0x0, 0x12348, -0x12380, 0x12468, 0x13034, 0x135fc, -0x13614, 0x13c7c, 0x13cbc, 0x13d4c, -0x13d90, 0x13df4, 0x13e80, 0x13eb4, -0x13f3c, 0x13fd4, 0x140a4, 0x140e4, -0x14168, 0x1418c, 0x1429c, 0x646f4261, +0x6c6e6b41, 0x53535254, 0x0, 0x109a4, +0x10a1c, 0x10a50, 0x10a7c, 0x11050, +0x10aa8, 0x10b10, 0x111fc, 0x10dc0, +0x10c68, 0x10c80, 0x10cc4, 0x10cec, +0x10d0c, 0x10d34, 0x111fc, 0x10dc0, +0x10df8, 0x10e10, 0x10e40, 0x10e68, +0x10e88, 0x10eb0, 0x0, 0x10fdc, +0x11008, 0x1102c, 0x111fc, 0x11050, +0x11078, 0x11108, 0x0, 0x0, +0x0, 0x1186c, 0x1193c, 0x11a14, +0x11ae4, 0x11b40, 0x11c1c, 0x11c44, +0x11d20, 0x11d48, 0x11ef0, 0x11f18, +0x120c0, 0x122b8, 0x1254c, 0x12460, +0x1254c, 0x12578, 0x120e8, 0x12290, +0x7273745f, 0x676d6969, 0x0, 0x12608, +0x12640, 0x12728, 0x13374, 0x133b4, +0x133cc, 0x7365746c, 0x6f6f7000, 0x0, +0x0, 0x13bbc, 0x13bfc, 0x13c8c, +0x13cd0, 0x13d34, 0x13dc0, 0x13df4, +0x13e7c, 0x13f14, 0x13fe4, 0x14024, +0x140a8, 0x140cc, 0x141dc, 0x646f4261, 0x73655067, 0x0, 0x0, 0x0, 0x0, 0x73746d61, 0x634c4e4b, 0x0, -0x6765746d, 0x636c6e6b, 0x0, 0x14fb4, -0x14fb4, 0x14ce4, 0x14d34, 0x14d78, -0x14fb4, 0x7365746d, 0x61636163, 0x74000000, +0x6765746d, 0x636c6e6b, 0x0, 0x14ed8, +0x14ed8, 0x14b8c, 0x14bd8, 0x14c24, +0x14ed8, 0x7365746d, 0x61636163, 0x74000000, 0x0, 0x0 }; u32 tigon2FwData[(MAX_DATA_LEN/4) + 1] __initdata = { 0x1, diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/net/bsd_comp.c linux/drivers/net/bsd_comp.c --- v2.3.99-pre7/linux/drivers/net/bsd_comp.c Tue Mar 14 19:10:39 2000 +++ linux/drivers/net/bsd_comp.c Fri May 12 11:29:52 2000 @@ -1,3 +1,11 @@ +/* + * Update: The Berkeley copyright was changed, and the change + * is retroactive to all "true" BSD software (ie everything + * from UCB as opposed to other peoples code that just carried + * the same license). The new copyright doesn't clash with the + * GPL, so the module-only restriction has been removed.. + */ + /* Because this code is derived from the 4.3BSD compress source: * * Copyright (c) 1985, 1986 The Regents of the University of California. @@ -52,10 +60,6 @@ * * From: bsd_comp.c,v 1.3 1994/12/08 01:59:58 paulus Exp */ - -#ifndef MODULE -#error This file must be compiled as a module. -#endif #include #include diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/net/pcmcia/Config.in linux/drivers/net/pcmcia/Config.in --- v2.3.99-pre7/linux/drivers/net/pcmcia/Config.in Thu May 11 15:30:07 2000 +++ linux/drivers/net/pcmcia/Config.in Fri May 12 13:21:16 2000 @@ -15,7 +15,7 @@ dep_tristate ' SMC 91Cxx PCMCIA support' CONFIG_PCMCIA_SMC91C92 $CONFIG_PCMCIA dep_tristate ' Xircom 16-bit PCMCIA support' CONFIG_PCMCIA_XIRC2PS $CONFIG_PCMCIA dep_tristate ' COM20020 ARCnet PCMCIA support' CONFIG_ARCNET_COM20020_CS $CONFIG_ARCNET_COM20020 $CONFIG_ARCNET $CONFIG_PCMCIA - dep_tristate ' IBM PCMCIA tokenring adapter support' CONFIG_PCMCIA_IBMTR $CONFIG_PCMCIA_IBMTR $CONFIG_TR $CONFIG_PCMCIA + dep_tristate ' IBM PCMCIA tokenring adapter support' CONFIG_PCMCIA_IBMTR $CONFIG_TR $CONFIG_PCMCIA if [ "$CONFIG_CARDBUS" = "y" ]; then tristate ' Xircom Tulip-like CardBus support' CONFIG_PCMCIA_XIRTULIP diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/net/pppoe.c linux/drivers/net/pppoe.c --- v2.3.99-pre7/linux/drivers/net/pppoe.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/pppoe.c Fri May 12 11:32:08 2000 @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/net/pppox.c linux/drivers/net/pppox.c --- v2.3.99-pre7/linux/drivers/net/pppox.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/pppox.c Fri May 12 11:32:08 2000 @@ -17,6 +17,7 @@ * */ +#include #include #include diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/net/skfp/fplustm.c linux/drivers/net/skfp/fplustm.c --- v2.3.99-pre7/linux/drivers/net/skfp/fplustm.c Sun Feb 20 21:12:39 2000 +++ linux/drivers/net/skfp/fplustm.c Fri May 12 11:43:26 2000 @@ -390,9 +390,9 @@ outpw(FM_A(FM_TREQ0),(unsigned)t_requ) ; } -void set_long(p,l) +void set_int(p,l) char *p; -long l; +int l; { p[0] = (char)(l >> 24) ; p[1] = (char)(l >> 16) ; @@ -416,12 +416,12 @@ int len ; /* lenght of the frame including the FC */ { int i ; - u_long *p ; + u_int *p ; CHECK_NPP() ; MARW(off) ; /* set memory address reg for writes */ - p = (u_long *) mac ; + p = (u_int *) mac ; for (i = (len + 3)/4 ; i ; i--) { if (i == 1) { /* last word, set the tag bit */ @@ -460,7 +460,7 @@ static void directed_beacon(smc) struct s_smc *smc ; { - SK_LOC_DECL(u_long,a[2]) ; + SK_LOC_DECL(u_int,a[2]) ; /* * set UNA in frame @@ -491,7 +491,7 @@ struct s_smc *smc ; u_long t_request; { - u_long td ; + u_int td ; int len ; struct fddi_mac_sf *mac ; @@ -499,13 +499,13 @@ * build claim packet */ len = 17 ; - td = TX_DESCRIPTOR | ((((u_long)len-1)&3)<<27) ; + td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ; mac = &smc->hw.fp.mac_sfb ; mac->mac_fc = FC_CLAIM ; /* DA == SA in claim frame */ mac->mac_source = mac->mac_dest = MA ; /* 2's complement */ - set_long((char *)mac->mac_info,(long)t_request) ; + set_int((char *)mac->mac_info,(int)t_request) ; copy_tx_mac(smc,td,(struct fddi_mac *)mac, smc->hw.fp.fifo.rbc_ram_start + CLAIM_FRAME_OFF,len) ; @@ -516,11 +516,11 @@ * build beacon packet */ len = 17 ; - td = TX_DESCRIPTOR | ((((u_long)len-1)&3)<<27) ; + td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ; mac->mac_fc = FC_BEACON ; mac->mac_source = MA ; mac->mac_dest = null_addr ; /* DA == 0 in beacon frame */ - set_long((char *) mac->mac_info,((long)BEACON_INFO<<24L) + 0 ) ; + set_int((char *) mac->mac_info,((int)BEACON_INFO<<24) + 0 ) ; copy_tx_mac(smc,td,(struct fddi_mac *)mac, smc->hw.fp.fifo.rbc_ram_start + BEACON_FRAME_OFF,len) ; @@ -532,13 +532,13 @@ * contains optional UNA */ len = 23 ; - td = TX_DESCRIPTOR | ((((u_long)len-1)&3)<<27) ; + td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ; mac->mac_fc = FC_BEACON ; mac->mac_source = MA ; mac->mac_dest = dbeacon_multi ; /* multicast */ - set_long((char *) mac->mac_info,((long)DBEACON_INFO<<24L) + 0 ) ; - set_long((char *) mac->mac_info+4,0L) ; - set_long((char *) mac->mac_info+8,0L) ; + set_int((char *) mac->mac_info,((int)DBEACON_INFO<<24) + 0 ) ; + set_int((char *) mac->mac_info+4,0) ; + set_int((char *) mac->mac_info+8,0) ; copy_tx_mac(smc,td,(struct fddi_mac *)mac, smc->hw.fp.fifo.rbc_ram_start + DBEACON_FRAME_OFF,len) ; diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/net/skfp/h/fplustm.h linux/drivers/net/skfp/h/fplustm.h --- v2.3.99-pre7/linux/drivers/net/skfp/h/fplustm.h Sun Feb 20 21:12:39 2000 +++ linux/drivers/net/skfp/h/fplustm.h Fri May 12 11:43:26 2000 @@ -54,12 +54,12 @@ * Transmit Descriptor struct */ struct s_smt_fp_txd { - u_long txd_tbctrl ; /* transmit buffer control */ - u_long txd_txdscr ; /* transmit frame status word */ - u_long txd_tbadr ; /* physical tx buffer address */ - u_long txd_ntdadr ; /* physical pointer to the next TxD */ + u_int txd_tbctrl ; /* transmit buffer control */ + u_int txd_txdscr ; /* transmit frame status word */ + u_int txd_tbadr ; /* physical tx buffer address */ + u_int txd_ntdadr ; /* physical pointer to the next TxD */ #ifdef ENA_64BIT_SUP - u_long txd_tbadr_hi ; /* physical tx buffer addr (high dword)*/ + u_int txd_tbadr_hi ; /* physical tx buffer addr (high dword)*/ #endif char far *txd_virt ; /* virtual pointer to the data frag */ /* virt pointer to the next TxD */ @@ -71,12 +71,12 @@ * Receive Descriptor struct */ struct s_smt_fp_rxd { - u_long rxd_rbctrl ; /* receive buffer control */ - u_long rxd_rfsw ; /* receive frame status word */ - u_long rxd_rbadr ; /* physical rx buffer address */ - u_long rxd_nrdadr ; /* physical pointer to the next RxD */ + u_int rxd_rbctrl ; /* receive buffer control */ + u_int rxd_rfsw ; /* receive frame status word */ + u_int rxd_rbadr ; /* physical rx buffer address */ + u_int rxd_nrdadr ; /* physical pointer to the next RxD */ #ifdef ENA_64BIT_SUP - u_long rxd_rbadr_hi ; /* physical tx buffer addr (high dword)*/ + u_int rxd_rbadr_hi ; /* physical tx buffer addr (high dword)*/ #endif char far *rxd_virt ; /* virtual pointer to the data frag */ /* virt pointer to the next RxD */ @@ -259,8 +259,10 @@ (((x)>> 8L)&0x0000ff00L) + \ (((x)>>24L)&0x000000ffL)) #else +#ifndef AIX_REVERSE #define AIX_REVERSE(x) (x) #endif +#endif #ifdef MDR_REV #define MDR_REVERSE(x) ((((x)<<24L)&0xff000000L) + \ @@ -268,7 +270,9 @@ (((x)>> 8L)&0x0000ff00L) + \ (((x)>>24L)&0x000000ffL)) #else +#ifndef MDR_REVERSE #define MDR_REVERSE(x) (x) +#endif #endif #endif diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/net/skfp/h/osdef1st.h linux/drivers/net/skfp/h/osdef1st.h --- v2.3.99-pre7/linux/drivers/net/skfp/h/osdef1st.h Sun Feb 20 21:12:39 2000 +++ linux/drivers/net/skfp/h/osdef1st.h Fri May 12 11:43:26 2000 @@ -97,22 +97,27 @@ * * Note: The size of these structures must follow this rule: * - * size = 8 + n * 16, n >= 0 + * sizeof(struct) + 2*sizeof(void*) == n * 16, n >= 1 * - * NOTE: The size of this structures may not be changed, because - * libskfddi.a depends on it. But the dummy fields can be - * used freely. + * We use the dma_addr fields under Linux to keep track of the + * DMA address of the packet data, for later pci_unmap_single. -DaveM */ struct s_txd_os { // os-specific part of transmit descriptor struct sk_buff *skb; - long dummy; + dma_addr_t dma_addr; } ; struct s_rxd_os { // os-specific part of receive descriptor struct sk_buff *skb; - long dummy; + dma_addr_t dma_addr; } ; +/* + * So we do not need to make too many modifications to the generic driver + * parts, we take advantage of the AIX byte swapping macro interface. + */ +#define AIX_REVERSE(x) ((u32)le32_to_cpu((u32)(x))) +#define MDR_REVERSE(x) ((u32)le32_to_cpu((u32)(x))) diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/net/skfp/h/smt.h linux/drivers/net/skfp/h/smt.h --- v2.3.99-pre7/linux/drivers/net/skfp/h/smt.h Sun Feb 20 21:12:39 2000 +++ linux/drivers/net/skfp/h/smt.h Fri May 12 11:43:26 2000 @@ -53,7 +53,7 @@ u_char smt_class ; /* NIF, SIF ... */ u_char smt_type ; /* req., response .. */ u_short smt_version ; /* version id */ - u_long smt_tid ; /* transaction ID */ + u_int smt_tid ; /* transaction ID */ struct smt_sid smt_sid ; /* station ID */ u_short smt_pad ; /* pad with 0 */ u_short smt_len ; /* length of info field */ @@ -278,15 +278,15 @@ struct smt_para para ; /* generic parameter header */ u_short st_mib_index ; /* MIB index */ u_short st_mac_index ; /* n+1 .. n+m */ - u_long st_t_req ; /* T_Req */ - u_long st_t_neg ; /* T_Neg */ - u_long st_t_max ; /* T_Max */ - u_long st_tvx_value ; /* TVX_Value */ - u_long st_t_min ; /* T_Min */ - u_long st_sba ; /* synchr. bandwidth alloc */ - u_long st_frame_ct ; /* frame counter */ - u_long st_error_ct ; /* error counter */ - u_long st_lost_ct ; /* lost frames counter */ + u_int st_t_req ; /* T_Req */ + u_int st_t_neg ; /* T_Neg */ + u_int st_t_max ; /* T_Max */ + u_int st_tvx_value ; /* TVX_Value */ + u_int st_t_min ; /* T_Min */ + u_int st_sba ; /* synchr. bandwidth alloc */ + u_int st_frame_ct ; /* frame counter */ + u_int st_error_ct ; /* error counter */ + u_int st_lost_ct ; /* lost frames counter */ } ; /* @@ -305,8 +305,8 @@ u_char lem_cutoff ; /* 0x4 .. 0xf, default 0x7 */ u_char lem_alarm ; /* 0x4 .. 0xf, default 0x8 */ u_char lem_estimate ; /* 0x0 .. 0xff */ - u_long lem_reject_ct ; /* 0x00000000 .. 0xffffffff */ - u_long lem_ct ; /* 0x00000000 .. 0xffffffff */ + u_int lem_reject_ct ; /* 0x00000000 .. 0xffffffff */ + u_int lem_ct ; /* 0x00000000 .. 0xffffffff */ } ; /* @@ -319,8 +319,8 @@ struct smt_para para ; /* generic parameter header */ u_short mc_mib_index ; /* MIB index */ u_short mc_index ; /* mac index */ - u_long mc_receive_ct ; /* receive counter */ - u_long mc_transmit_ct ; /* transmit counter */ + u_int mc_receive_ct ; /* receive counter */ + u_int mc_transmit_ct ; /* transmit counter */ } ; /* @@ -333,7 +333,7 @@ struct smt_para para ; /* generic parameter header */ u_short nc_mib_index ; /* MIB index */ u_short nc_index ; /* mac index */ - u_long nc_counter ; /* not copied counter */ + u_int nc_counter ; /* not copied counter */ } ; @@ -347,7 +347,7 @@ struct smt_para para ; /* generic parameter header */ u_short pr_mib_index ; /* MIB index */ u_short pr_index ; /* mac index */ - u_long pr_priority[7] ; /* priority values */ + u_int pr_priority[7] ; /* priority values */ } ; /* @@ -360,7 +360,7 @@ struct smt_para para ; /* generic parameter header */ u_short eb_mib_index ; /* MIB index */ u_short eb_index ; /* phy index */ - u_long eb_error_ct ; /* # of eb overflows */ + u_int eb_error_ct ; /* # of eb overflows */ } ; /* @@ -406,7 +406,7 @@ struct smt_p_reason { struct smt_para para ; /* generic parameter header */ - u_long rdf_reason ; /* CLASS/VERSION */ + u_int rdf_reason ; /* CLASS/VERSION */ } ; #define SMT_RDF_CLASS 0x00000001 /* class not supported */ #define SMT_RDF_VERSION 0x00000002 /* version not supported */ @@ -428,7 +428,7 @@ struct smt_p_refused { struct smt_para para ; /* generic parameter header */ - u_long ref_fc ; /* 3 bytes 0 + FC */ + u_int ref_fc ; /* 3 bytes 0 + FC */ struct smt_header ref_header ; /* refused header */ } ; @@ -454,7 +454,7 @@ struct smt_p_0015 { struct smt_para para ; /* generic parameter header */ - u_long res_type ; /* recsource type */ + u_int res_type ; /* recsource type */ } ; #define SYNC_BW 0x00000001L /* Synchronous Bandwidth */ @@ -466,7 +466,7 @@ struct smt_p_0016 { struct smt_para para ; /* generic parameter header */ - u_long sba_cmd ; /* command for the SBA */ + u_int sba_cmd ; /* command for the SBA */ } ; #define REQUEST_ALLOCATION 0x1 /* req allocation of sync bandwidth */ @@ -482,7 +482,7 @@ struct smt_p_0017 { struct smt_para para ; /* generic parameter header */ - long sba_pl_req ; /* total sync bandwidth measured in */ + int sba_pl_req ; /* total sync bandwidth measured in */ } ; /* bytes per 125 us */ /* @@ -492,7 +492,7 @@ struct smt_p_0018 { struct smt_para para ; /* generic parameter header */ - long sba_ov_req ; /* total sync bandwidth req for overhead*/ + int sba_ov_req ; /* total sync bandwidth req for overhead*/ } ; /* measuered in bytes per T_Neg */ /* @@ -513,7 +513,7 @@ struct smt_p_001a { struct smt_para para ; /* generic parameter header */ - u_long category ; /* Allocator defined classification */ + u_int category ; /* Allocator defined classification */ } ; /* @@ -523,7 +523,7 @@ struct smt_p_001b { struct smt_para para ; /* generic parameter header */ - u_long max_t_neg ; /* longest T_NEG for the sync service*/ + u_int max_t_neg ; /* longest T_NEG for the sync service*/ } ; /* @@ -533,7 +533,7 @@ struct smt_p_001c { struct smt_para para ; /* generic parameter header */ - u_long min_seg_siz ; /* smallest number of bytes per frame*/ + u_int min_seg_siz ; /* smallest number of bytes per frame*/ } ; /* @@ -543,7 +543,7 @@ struct smt_p_001d { struct smt_para para ; /* generic parameter header */ - u_long allocatable ; /* total sync bw availabel for alloc */ + u_int allocatable ; /* total sync bw availabel for alloc */ } ; /* @@ -575,8 +575,8 @@ */ #define SWAP_SMT_P1048 "ll" struct smt_p_1048 { - u_long p1048_flag ; - u_long p1048_cf_state ; + u_int p1048_flag ; + u_int p1048_cf_state ; } ; /* @@ -586,7 +586,7 @@ */ #define SWAP_SMT_P208C "4lss66" struct smt_p_208c { - u_long p208c_flag ; + u_int p208c_flag ; u_short p208c_pad ; u_short p208c_dupcondition ; struct fddi_addr p208c_fddilong ; @@ -595,26 +595,26 @@ #define SWAP_SMT_P208D "4lllll" struct smt_p_208d { - u_long p208d_flag ; - u_long p208d_frame_ct ; - u_long p208d_error_ct ; - u_long p208d_lost_ct ; - u_long p208d_ratio ; + u_int p208d_flag ; + u_int p208d_frame_ct ; + u_int p208d_error_ct ; + u_int p208d_lost_ct ; + u_int p208d_ratio ; } ; #define SWAP_SMT_P208E "4llll" struct smt_p_208e { - u_long p208e_flag ; - u_long p208e_not_copied ; - u_long p208e_copied ; - u_long p208e_not_copied_ratio ; + u_int p208e_flag ; + u_int p208e_not_copied ; + u_int p208e_copied ; + u_int p208e_not_copied_ratio ; } ; #define SWAP_SMT_P208F "4ll6666s6" struct smt_p_208f { - u_long p208f_multiple ; - u_long p208f_nacondition ; + u_int p208f_multiple ; + u_int p208f_nacondition ; struct fddi_addr p208f_old_una ; struct fddi_addr p208f_new_una ; struct fddi_addr p208f_old_dna ; @@ -626,10 +626,10 @@ #define SWAP_SMT_P2090 "4lssl" struct smt_p_2090 { - u_long p2090_multiple ; + u_int p2090_multiple ; u_short p2090_availablepaths ; u_short p2090_currentpath ; - u_long p2090_requestedpaths ; + u_int p2090_requestedpaths ; } ; /* @@ -649,7 +649,7 @@ struct smt_p_320b { struct smt_para para ; /* generic parameter header */ - u_long mib_index ; + u_int mib_index ; u_short path_pad ; u_short path_index ; } ; @@ -658,33 +658,33 @@ struct smt_p_320f { struct smt_para para ; /* generic parameter header */ - u_long mib_index ; - u_long mib_payload ; + u_int mib_index ; + u_int mib_payload ; } ; #define SWAP_SMT_P3210 "4l" struct smt_p_3210 { struct smt_para para ; /* generic parameter header */ - u_long mib_index ; - u_long mib_overhead ; + u_int mib_index ; + u_int mib_overhead ; } ; #define SWAP_SMT_P4050 "4l1111ll" struct smt_p_4050 { - u_long p4050_flag ; + u_int p4050_flag ; u_char p4050_pad ; u_char p4050_cutoff ; u_char p4050_alarm ; u_char p4050_estimate ; - u_long p4050_reject_ct ; - u_long p4050_ct ; + u_int p4050_reject_ct ; + u_int p4050_ct ; } ; #define SWAP_SMT_P4051 "4lssss" struct smt_p_4051 { - u_long p4051_multiple ; + u_int p4051_multiple ; u_short p4051_porttype ; u_short p4051_connectstate ; u_short p4051_pc_neighbor ; @@ -693,17 +693,17 @@ #define SWAP_SMT_P4052 "4ll" struct smt_p_4052 { - u_long p4052_flag ; - u_long p4052_eberrorcount ; + u_int p4052_flag ; + u_int p4052_eberrorcount ; } ; #define SWAP_SMT_P4053 "4lsslss" struct smt_p_4053 { - u_long p4053_multiple ; + u_int p4053_multiple ; u_short p4053_availablepaths ; u_short p4053_currentpath ; - u_long p4053_requestedpaths ; + u_int p4053_requestedpaths ; u_short p4053_mytype ; u_short p4053_neighbortype ; } ; @@ -714,7 +714,7 @@ struct smt_p_setcount { struct smt_para para ; /* generic parameter header */ - u_long count ; + u_int count ; u_char timestamp[8] ; } ; diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/net/skfp/h/targetos.h linux/drivers/net/skfp/h/targetos.h --- v2.3.99-pre7/linux/drivers/net/skfp/h/targetos.h Sun Feb 20 21:12:39 2000 +++ linux/drivers/net/skfp/h/targetos.h Fri May 12 11:43:26 2000 @@ -93,7 +93,7 @@ #define u8 unsigned char #define u16 unsigned short -#define u32 unsigned long +#define u32 unsigned int #define MAX_TX_QUEUE_LEN 20 // number of packets queued by driver #define MAX_FRAME_SIZE 4550 @@ -127,11 +127,12 @@ u32 bus_type; /* bus type (0 == PCI, 1 == EISA) */ struct pci_dev pdev; /* PCI device structure */ - u32 base_addr; + unsigned long base_addr; unsigned char factory_mac_addr[8]; ulong SharedMemSize; ulong SharedMemHeap; void* SharedMemAddr; + dma_addr_t SharedMemDMA; ulong QueueSkb; struct sk_buff_head SendSkbQueue; @@ -144,8 +145,10 @@ // receive into this local buffer if no skb available // data will be not valid, because multiple RxDs can - // point here at the same time - unsigned char LocalRxBuffer[MAX_FRAME_SIZE]; + // point here at the same time, it must be at least + // MAX_FRAME_SIZE bytes in size + unsigned char *LocalRxBuffer; + dma_addr_t LocalRxBufferDMA; // Version (required by SMT module). u_long smc_version ; diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/net/skfp/hwmtm.c linux/drivers/net/skfp/hwmtm.c --- v2.3.99-pre7/linux/drivers/net/skfp/hwmtm.c Sun Feb 20 21:12:39 2000 +++ linux/drivers/net/skfp/hwmtm.c Fri May 12 11:43:26 2000 @@ -456,7 +456,7 @@ /* * make sure that the start pointer is 16 byte aligned */ - i = 16 - ((int)smc->os.hwm.descr_p & 0xf) ; + i = 16 - ((long)smc->os.hwm.descr_p & 0xf) ; if (i != 16) { DB_GEN("i = %d",i,0,3) ; smc->os.hwm.descr_p = (union s_fp_descr volatile *) @@ -1087,9 +1087,8 @@ DB_RX("Check RxD %x for OWN and EOF",(void *)r,0,5) ; DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ; rbctrl = CR_READ(r->rxd_rbctrl) ; -#ifdef AIX rbctrl = AIX_REVERSE(rbctrl) ; -#endif + if (rbctrl & BMU_OWN) { NDD_TRACE("RHxE",r,rfsw,rbctrl) ; DB_RX("End of RxDs",0,0,4) ; @@ -1425,26 +1424,19 @@ int frame_status ; { struct s_smt_fp_rxd volatile *r ; -#ifdef AIX - u_long rbctrl ; -#endif + u_int rbctrl ; NDD_TRACE("RHfB",virt,len,frame_status) ; DB_RX("hwm_rx_frag: len = %d, frame_status = %x\n",len,frame_status,2) ; r = smc->hw.fp.rx_q[QUEUE_R1].rx_curr_put ; r->rxd_virt = virt ; r->rxd_rbadr = AIX_REVERSE(phys) ; -#ifndef AIX - r->rxd_rbctrl = (((u_long)frame_status & (FIRST_FRAG|LAST_FRAG))<<26) | - (((u_long) frame_status & FIRST_FRAG) << 21) | - BMU_OWN | BMU_CHECK | BMU_EN_IRQ_EOF | len ; -#else rbctrl = AIX_REVERSE( (((u_long)frame_status & (FIRST_FRAG|LAST_FRAG))<<26) | (((u_long) frame_status & FIRST_FRAG) << 21) | BMU_OWN | BMU_CHECK | BMU_EN_IRQ_EOF | len) ; r->rxd_rbctrl = rbctrl ; -#endif + DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ; outpd(ADDR(B0_R1_CSR),CSR_START) ; smc->hw.fp.rx_q[QUEUE_R1].rx_free-- ; @@ -1687,9 +1679,7 @@ { struct s_smt_fp_txd volatile *t ; struct s_smt_tx_queue *queue ; -#ifdef AIX - u_long tbctrl ; -#endif + u_int tbctrl ; queue = smc->os.hwm.tx_p ; @@ -1708,19 +1698,15 @@ t->txd_virt = virt ; t->txd_txdscr = AIX_REVERSE(smc->os.hwm.tx_descr) ; t->txd_tbadr = AIX_REVERSE(phys) ; -#ifndef AIX - t->txd_tbctrl = (((u_long)frame_status & - (FIRST_FRAG|LAST_FRAG|EN_IRQ_EOF))<< 26) | - BMU_OWN|BMU_CHECK |len ; - DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ; - outpd(queue->tx_bmu_ctl,CSR_START) ; - -#else /* ifndef AIX */ tbctrl = AIX_REVERSE((((u_long)frame_status & (FIRST_FRAG|LAST_FRAG|EN_IRQ_EOF))<< 26) | BMU_OWN|BMU_CHECK |len) ; t->txd_tbctrl = tbctrl ; +#ifndef AIX + DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ; + outpd(queue->tx_bmu_ctl,CSR_START) ; +#else /* ifndef AIX */ DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ; if (frame_status & QUEUE_A0) { outpd(ADDR(B0_XA_CSR),CSR_START) ; @@ -1888,9 +1874,7 @@ struct s_smt_tx_queue *queue ; struct s_smt_fp_txd volatile *t ; u_long phys ; -#ifdef AIX - u_long tbctrl ; -#endif + u_int tbctrl ; NDD_TRACE("THSB",mb,fc,0) ; DB_TX("smt_send_mbuf: mb = 0x%x, fc = 0x%x",mb,fc,4) ; @@ -1908,7 +1892,7 @@ frag_count = 0 ; len = mb->sm_len ; while (len) { - n = SMT_PAGESIZE - ((int)data & (SMT_PAGESIZE-1)) ; + n = SMT_PAGESIZE - ((long)data & (SMT_PAGESIZE-1)) ; if (n >= len) { n = len ; } @@ -1964,17 +1948,14 @@ phys = dma_master(smc, (void far *)virt[i], frag_len[i], DMA_RD|SMT_BUF) ; t->txd_tbadr = AIX_REVERSE(phys) ; -#ifndef AIX - t->txd_tbctrl = (((u_long) frame_status & - (FIRST_FRAG|LAST_FRAG)) << 26) | - BMU_OWN | BMU_CHECK | BMU_SMT_TX |frag_len[i] ; - DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ; - outpd(queue->tx_bmu_ctl,CSR_START) ; -#else tbctrl = AIX_REVERSE((((u_long) frame_status & (FIRST_FRAG|LAST_FRAG)) << 26) | BMU_OWN | BMU_CHECK | BMU_SMT_TX |frag_len[i]) ; t->txd_tbctrl = tbctrl ; +#ifndef AIX + DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ; + outpd(queue->tx_bmu_ctl,CSR_START) ; +#else DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ; outpd(ADDR(B0_XA_CSR),CSR_START) ; #endif @@ -2039,9 +2020,8 @@ DRV_BUF_FLUSH(t1,DDI_DMA_SYNC_FORCPU) ; DB_TX("check OWN/EOF bit of TxD 0x%x",t1,0,5) ; tbctrl = CR_READ(t1->txd_tbctrl) ; -#ifdef AIX tbctrl = AIX_REVERSE(tbctrl) ; -#endif + if (tbctrl & BMU_OWN || !queue->tx_used){ DB_TX("End of TxDs queue %d",i,0,4) ; goto free_next_queue ; /* next queue */ diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/net/skfp/skfddi.c linux/drivers/net/skfp/skfddi.c --- v2.3.99-pre7/linux/drivers/net/skfp/skfddi.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/skfp/skfddi.c Fri May 12 11:43:26 2000 @@ -19,6 +19,9 @@ * Maintainers: * CG Christoph Goos (cgoos@syskonnect.de) * + * Contributors: + * DM David S. Miller + * * Address all question to: * linux@syskonnect.de * @@ -52,20 +55,20 @@ * 26-Oct-99 CG Fixed compilation error on 2.2.13 * 12-Nov-99 CG Source code release * 22-Nov-99 CG Included in kernel source. + * 07-May-00 DM 64 bit fixes, new dma interface * * Compilation options (-Dxxx): * DRIVERDEBUG print lots of messages to log file * DUMPPACKETS print received/transmitted packets to logfile * - * Limitations: - * I changed the driver to support memory mapped I/O, so it - * might run on non-x86 architectures (not tested). - * But the hardware module does not yet support 64 bit OS'es. + * Tested cpu architectures: + * - i386 + * - sparc64 */ /* Version information string - should be updated prior to */ /* each new release!!! */ -#define VERSION "2.05" +#define VERSION "2.06" static const char *boot_msg = "SysKonnect FDDI PCI Adapter driver v" VERSION " for\n" @@ -666,18 +669,28 @@ spin_lock_init(&bp->DriverLock); + // Allocate invalid frame + bp->LocalRxBuffer = pci_alloc_consistent(&bp->pdev, MAX_FRAME_SIZE, &bp->LocalRxBufferDMA); + if (!bp->LocalRxBuffer) { + printk("could not allocate mem for "); + printk("LocalRxBuffer: %d byte\n", MAX_FRAME_SIZE); + goto fail; + } + // Determine the required size of the 'shared' memory area. bp->SharedMemSize = mac_drv_check_space(); PRINTK(KERN_INFO "Memory for HWM: %ld\n", bp->SharedMemSize); if (bp->SharedMemSize > 0) { bp->SharedMemSize += 16; // for descriptor alignment - bp->SharedMemAddr = kmalloc(bp->SharedMemSize, GFP_KERNEL); + bp->SharedMemAddr = pci_alloc_consistent(&bp->pdev, + bp->SharedMemSize, + &bp->SharedMemDMA); if (!bp->SharedMemSize) { printk("could not allocate mem for "); printk("hardware module: %ld byte\n", bp->SharedMemSize); - return (-1); + goto fail; } bp->SharedMemHeap = 0; // Nothing used yet. @@ -693,7 +706,7 @@ PRINTK(KERN_INFO "mac_drv_init()..\n"); if (mac_drv_init(smc) != 0) { PRINTK(KERN_INFO "mac_drv_init() failed.\n"); - return (-1); + goto fail; } read_address(smc, NULL); PRINTK(KERN_INFO "HW-Addr: %02x %02x %02x %02x %02x %02x\n", @@ -708,6 +721,21 @@ smt_reset_defaults(smc, 0); return (0); + +fail: + if (bp->SharedMemAddr) { + pci_free_consistent(&bp->pdev, + bp->SharedMemSize, + bp->SharedMemAddr, + bp->SharedMemDMA); + bp->SharedMemAddr = NULL; + } + if (bp->LocalRxBuffer) { + pci_free_consistent(&bp->pdev, MAX_FRAME_SIZE, + bp->LocalRxBuffer, bp->LocalRxBufferDMA); + bp->LocalRxBuffer = NULL; + } + return (-1); } // skfp_driver_init @@ -1282,7 +1310,7 @@ * is contained in a single physically contiguous buffer * in which the virtual address of the start of packet * (skb->data) can be converted to a physical address - * by using virt_to_bus(). + * by using pci_map_single(). * * We have an internal queue for packets we can not send * immediately. Packets in this queue can be given to the @@ -1378,6 +1406,7 @@ unsigned char fc; int queue; struct s_smt_fp_txd *txd; // Current TxD. + dma_addr_t dma_address; unsigned long Flags; int frame_status; // HWM tx frame status. @@ -1442,13 +1471,18 @@ txd = (struct s_smt_fp_txd *) HWM_GET_CURR_TXD(smc, queue); + dma_address = pci_map_single(&bp->pdev, skb->data, + skb->len, PCI_DMA_TODEVICE); if (frame_status & LAN_TX) { - txd->txd_os.skb = skb; // save skb + txd->txd_os.skb = skb; // save skb + txd->txd_os.dma_addr = dma_address; // save dma mapping } - hwm_tx_frag(smc, skb->data, virt_to_bus(skb->data), skb->len, + hwm_tx_frag(smc, skb->data, dma_address, skb->len, frame_status | FIRST_FRAG | LAST_FRAG | EN_IRQ_EOF); if (!(frame_status & LAN_TX)) { // local only frame + pci_unmap_single(&bp->pdev, dma_address, + skb->len, PCI_DMA_TODEVICE); dev_kfree_skb_irq(skb); } spin_unlock_irqrestore(&bp->DriverLock, Flags); @@ -1571,7 +1605,7 @@ { void *virt; - PRINTK(KERN_INFO "mac_drv_get_space\n"); + PRINTK(KERN_INFO "mac_drv_get_space (%d bytes), ", size); virt = (void *) (smc->os.SharedMemAddr + smc->os.SharedMemHeap); if ((smc->os.SharedMemHeap + size) > smc->os.SharedMemSize) { @@ -1581,8 +1615,10 @@ smc->os.SharedMemHeap += size; // Move heap pointer. PRINTK(KERN_INFO "mac_drv_get_space end\n"); - PRINTK(KERN_INFO "virt addr: %08lx\n", (ulong) virt); - PRINTK(KERN_INFO "bus addr: %08lx\n", (ulong) virt_to_bus(virt)); + PRINTK(KERN_INFO "virt addr: %lx\n", (ulong) virt); + PRINTK(KERN_INFO "bus addr: %lx\n", (ulong) + (smc->os.SharedMemDMA + + ((char *) virt - (char *)smc->os.SharedMemAddr))); return (virt); } // mac_drv_get_space @@ -1616,7 +1652,7 @@ virt = mac_drv_get_space(smc, size); - size = (u_int) ((0 - (unsigned int) virt) & 15); + size = (u_int) ((0 - (unsigned long) virt) & 15UL); PRINTK("Allocate %u bytes alignment gap ", size); PRINTK("for descriptor memory.\n"); @@ -1644,7 +1680,8 @@ ************************/ unsigned long mac_drv_virt2phys(struct s_smc *smc, void *virt) { - return virt_to_bus(virt); + return (smc->os.SharedMemDMA + + ((char *) virt - (char *)smc->os.SharedMemAddr)); } // mac_drv_virt2phys @@ -1657,7 +1694,8 @@ * for the DMA transfer, it should do it in this function. * * The hardware module calls this dma_master if it wants to send an SMT - * frame. + * frame. This means that the virt address passed in here is part of + * the 'shared' memory area. * Args * smc - A pointer to the SMT context struct. * @@ -1677,7 +1715,8 @@ ************************/ u_long dma_master(struct s_smc * smc, void *virt, int len, int flag) { - return (virt_to_bus(virt)); + return (smc->os.SharedMemDMA + + ((char *) virt - (char *)smc->os.SharedMemAddr)); } // dma_master @@ -1704,7 +1743,31 @@ ************************/ void dma_complete(struct s_smc *smc, volatile union s_fp_descr *descr, int flag) { - return; + /* For TX buffers, there are two cases. If it is an SMT transmit + * buffer, there is nothing to do since we use consistent memory + * for the 'shared' memory area. The other case is for normal + * transmit packets given to us by the networking stack, and in + * that case we cleanup the PCI DMA mapping in mac_drv_tx_complete + * below. + * + * For RX buffers, we have to unmap dynamic PCI DMA mappings here + * because the hardware module is about to potentially look at + * the contents of the buffer. If we did not call the PCI DMA + * unmap first, the hardware module could read inconsistent data. + */ + if (flag & DMA_WR) { + skfddi_priv *bp = (skfddi_priv *) & smc->os; + volatile struct s_smt_fp_rxd *r = &descr->r; + + /* If SKB is NULL, we used the local buffer. */ + if (r->rxd_os.skb && r->rxd_os.dma_addr) { + int MaxFrameSize = bp->MaxFrameSize; + + pci_unmap_single(&bp->pdev, r->rxd_os.dma_addr, + MaxFrameSize, PCI_DMA_FROMDEVICE); + r->rxd_os.dma_addr = 0; + } + } } // dma_complete @@ -1735,6 +1798,11 @@ } txd->txd_os.skb = NULL; + // release the DMA mapping + pci_unmap_single(&smc->os.pdev, txd->txd_os.dma_addr, + skb->len, PCI_DMA_TODEVICE); + txd->txd_os.dma_addr = 0; + smc->os.MacStat.tx_packets++; // Count transmitted packets. smc->os.MacStat.tx_bytes+=skb->len; // Count bytes @@ -1823,6 +1891,8 @@ } virt = skb->data; + // The DMA mapping was released in dma_complete above. + dump_data(skb->data, len); /* @@ -1923,7 +1993,7 @@ struct sk_buff *skb; int MaxFrameSize; unsigned char *v_addr; - unsigned long b_addr; + dma_addr_t b_addr; if (frag_count != 1) // This is not allowed to happen. @@ -1939,25 +2009,34 @@ if (skb == NULL) { // this should not happen PRINTK("Requeue with no skb in rxd!\n"); - skb = alloc_skb(MaxFrameSize, GFP_ATOMIC); + skb = alloc_skb(MaxFrameSize + 3, GFP_ATOMIC); if (skb) { // we got a skb rxd->rxd_os.skb = skb; + skb_reserve(skb, 3); skb_put(skb, MaxFrameSize); v_addr = skb->data; - b_addr = virt_to_bus(v_addr); + b_addr = pci_map_single(&smc->os.pdev, + v_addr, + MaxFrameSize, + PCI_DMA_FROMDEVICE); + rxd->rxd_os.dma_addr = b_addr; } else { // no skb available, use local buffer PRINTK("Queueing invalid buffer!\n"); rxd->rxd_os.skb = NULL; v_addr = smc->os.LocalRxBuffer; - b_addr = virt_to_bus(v_addr); + b_addr = smc->os.LocalRxBufferDMA; } } else { // we use skb from old rxd rxd->rxd_os.skb = skb; v_addr = skb->data; - b_addr = virt_to_bus(v_addr); + b_addr = pci_map_single(&smc->os.pdev, + v_addr, + MaxFrameSize, + PCI_DMA_FROMDEVICE); + rxd->rxd_os.dma_addr = b_addr; } hwm_rx_frag(smc, v_addr, b_addr, MaxFrameSize, FIRST_FRAG | LAST_FRAG); @@ -2002,12 +2081,17 @@ PRINTK(KERN_INFO ".\n"); rxd = HWM_GET_CURR_RXD(smc); - skb = alloc_skb(MaxFrameSize, GFP_ATOMIC); + skb = alloc_skb(MaxFrameSize + 3, GFP_ATOMIC); if (skb) { // we got a skb + skb_reserve(skb, 3); skb_put(skb, MaxFrameSize); v_addr = skb->data; - b_addr = virt_to_bus(v_addr); + b_addr = pci_map_single(&smc->os.pdev, + v_addr, + MaxFrameSize, + PCI_DMA_FROMDEVICE); + rxd->rxd_os.dma_addr = b_addr; } else { // no skb available, use local buffer // System has run out of buffer memory, but we want to @@ -2016,7 +2100,7 @@ // so data in it must be considered invalid. PRINTK("Queueing invalid buffer!\n"); v_addr = smc->os.LocalRxBuffer; - b_addr = virt_to_bus(v_addr); + b_addr = smc->os.LocalRxBufferDMA; } rxd->rxd_os.skb = skb; @@ -2060,6 +2144,12 @@ for (; frag_count > 0; frag_count--) { skb = rxd->rxd_os.skb; if (skb != NULL) { + skfddi_priv *bp = (skfddi_priv *) & smc->os; + int MaxFrameSize = bp->MaxFrameSize; + + pci_unmap_single(&bp->pdev, rxd->rxd_os.dma_addr, + MaxFrameSize, PCI_DMA_FROMDEVICE); + dev_kfree_skb(skb); rxd->rxd_os.skb = NULL; } @@ -2111,11 +2201,12 @@ len, la_len, (unsigned long) look_ahead); return (0); } - skb = alloc_skb(len, GFP_ATOMIC); + skb = alloc_skb(len + 3, GFP_ATOMIC); if (!skb) { PRINTK("fddi: Local SMT: skb memory exhausted.\n"); return (0); } + skb_reserve(skb, 3); skb_put(skb, len); memcpy(skb->data, look_ahead, len); @@ -2162,7 +2253,40 @@ ************************/ void ring_status_indication(struct s_smc *smc, u_long status) { - PRINTK("ring_status_indication(%08lXh)\n", (unsigned long) status); + PRINTK("ring_status_indication( "); + if (status & RS_RES15) + PRINTK("RS_RES15 "); + if (status & RS_HARDERROR) + PRINTK("RS_HARDERROR "); + if (status & RS_SOFTERROR) + PRINTK("RS_SOFTERROR "); + if (status & RS_BEACON) + PRINTK("RS_BEACON "); + if (status & RS_PATHTEST) + PRINTK("RS_PATHTEST "); + if (status & RS_SELFTEST) + PRINTK("RS_SELFTEST "); + if (status & RS_RES9) + PRINTK("RS_RES9 "); + if (status & RS_DISCONNECT) + PRINTK("RS_DISCONNECT "); + if (status & RS_RES7) + PRINTK("RS_RES7 "); + if (status & RS_DUPADDR) + PRINTK("RS_DUPADDR "); + if (status & RS_NORINGOP) + PRINTK("RS_NORINGOP "); + if (status & RS_VERSION) + PRINTK("RS_VERSION "); + if (status & RS_STUCKBYPASSS) + PRINTK("RS_STUCKBYPASSS "); + if (status & RS_EVENT) + PRINTK("RS_EVENT "); + if (status & RS_RINGOPCHANGE) + PRINTK("RS_RINGOPCHANGE "); + if (status & RS_RES0) + PRINTK("RS_RES0 "); + PRINTK("]\n"); } // ring_status_indication @@ -2261,9 +2385,18 @@ case SC7_WRAP_S: s = "SC7_WRAP_S"; break; - default: - s = "unknown"; + case SC9_C_WRAP_A: + s = "SC9_C_WRAP_A"; + break; + case SC10_C_WRAP_B: + s = "SC10_C_WRAP_B"; + break; + case SC11_C_WRAP_S: + s = "SC11_C_WRAP_S"; break; + default: + PRINTK(KERN_INFO "cfm_state_change: unknown %d\n", c_state); + return; } PRINTK(KERN_INFO "cfm_state_change: %s\n", s); #endif // DRIVERDEBUG @@ -2478,7 +2611,18 @@ next = lp->os.next_module; if (lp->os.SharedMemAddr) { - kfree(lp->os.SharedMemAddr); + pci_free_consistent(&lp->os.pdev, + lp->os.SharedMemSize, + lp->os.SharedMemAddr, + lp->os.SharedMemDMA); + lp->os.SharedMemAddr = NULL; + } + if (lp->os.LocalRxBuffer) { + pci_free_consistent(&lp->os.pdev, + MAX_FRAME_SIZE, + lp->os.LocalRxBuffer, + lp->os.LocalRxBufferDMA); + lp->os.LocalRxBuffer = NULL; } release_region(p->base_addr, (lp->os.bus_type == SK_BUS_TYPE_PCI ? FP_IO_LEN : 0)); diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/net/tokenring/ibmtr.c linux/drivers/net/tokenring/ibmtr.c --- v2.3.99-pre7/linux/drivers/net/tokenring/ibmtr.c Tue Apr 11 15:09:18 2000 +++ linux/drivers/net/tokenring/ibmtr.c Fri May 12 13:21:16 2000 @@ -1750,9 +1750,9 @@ /* Copy the payload... */ for (;;) { if (IPv4_p) - chksum = csum_partial_copy(bus_to_virt(rbufdata), data, + chksum = csum_partial_copy_generic(bus_to_virt(rbufdata), data, length < rbuffer_len ? length : rbuffer_len, - chksum); + chksum, NULL, NULL); else isa_memcpy_fromio(data, rbufdata, rbuffer_len); rbuffer = ntohs(isa_readw(rbuffer)); diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/s390/Config.in linux/drivers/s390/Config.in --- v2.3.99-pre7/linux/drivers/s390/Config.in Wed Dec 31 16:00:00 1969 +++ linux/drivers/s390/Config.in Fri May 12 11:41:44 2000 @@ -0,0 +1,70 @@ +mainmenu_option next_comment +comment 'S/390 block device drivers' + +tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP +if [ "$CONFIG_NET" = "y" ]; then + tristate 'Network block device support' CONFIG_BLK_DEV_NBD +fi +bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD +if [ "$CONFIG_BLK_DEV_MD" = "y" ]; then + tristate ' Linear (append) mode' CONFIG_MD_LINEAR + tristate ' RAID-0 (striping) mode' CONFIG_MD_STRIPED + tristate ' RAID-1 (mirroring) mode' CONFIG_MD_MIRRORING + tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5 +fi +if [ "$CONFIG_MD_LINEAR" = "y" -o "$CONFIG_MD_STRIPED" = "y" ]; then + bool ' Boot support (linear, striped)' CONFIG_MD_BOOT +fi +tristate 'RAM disk support' CONFIG_BLK_DEV_RAM +if [ "$CONFIG_BLK_DEV_RAM" = "y" ]; then + bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD +fi + +bool 'Support for VM minidisk (VM only)' CONFIG_MDISK +if [ "$CONFIG_MDISK" = "y" ]; then + bool ' Support for synchronous read-write' CONFIG_MDISK_SYNC +fi + +tristate 'Support for DASD devices' CONFIG_DASD +if [ "$CONFIG_DASD" != "n" ]; then + comment 'DASD disciplines' + bool ' Support for ECKD Disks' CONFIG_DASD_ECKD +# bool ' Support for CKD Disks' CONFIG_DASD_CKD + bool ' Support for DIAG access to CMS reserved Disks' CONFIG_DASD_MDSK +fi + +#menu_option next_comment +#endmenu + +if [ "$CONFIG_NET" = "y" ]; then + mainmenu_option next_comment + comment 'S/390 Network device support' + bool 'Channel Device Configuration (Temporary Option)' CONFIG_CHANDEV + bool 'Network device support' CONFIG_NETDEVICES + if [ "$CONFIG_NETDEVICES" = "y" ]; then + menu_option next_comment + comment 'S390 Network devices' + bool 'CTC device support' CONFIG_CTC + bool 'IUCV device support (VM only)' CONFIG_IUCV + tristate 'Dummy net driver support' CONFIG_DUMMY + bool 'Ethernet (10 or 100Mbit)' CONFIG_NET_ETHERNET + bool 'Token Ring driver support' CONFIG_TR + bool 'FDDI driver support' CONFIG_FDDI + fi + endmenu +fi + +mainmenu_option next_comment +comment 'S/390 Terminal and Console options' + +bool 'Support for 3215 line mode terminal' CONFIG_3215 +if [ "$CONFIG_3215" = "y" ]; then + bool 'Support for console on 3215 line mode terminal' CONFIG_3215_CONSOLE +fi + +bool 'Support for HWC line mode terminal' CONFIG_HWC +if [ "$CONFIG_HWC" = "y" ]; then + bool 'console on HWC line mode terminal' CONFIG_HWC_CONSOLE +fi +endmenu + diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/s390/Makefile linux/drivers/s390/Makefile --- v2.3.99-pre7/linux/drivers/s390/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/s390/Makefile Fri May 12 11:41:44 2000 @@ -0,0 +1,40 @@ +# +# Makefile for the linux i386-specific parts of the memory manager. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definition is now in the main makefile... + +all: io.o + +CFLAGS += +O_TARGET := io.o +O_OBJS := +M_OBJS := + +SUBDIRS := $(SUBDIRS) arch/s390/drivers/block arch/s390/drivers/char \ + arch/s390/drivers/misc arch/s390/drivers/net +MOD_SUB_DIRS += ./net + +O_OBJS := block/s390-block.o \ + char/s390-char.o \ + misc/s390-misc.o \ + net/s390-net.o + +io.o: $(O_OBJS) + +block/s390-block.o: dummy + $(MAKE) -C block + +char/s390-char.o: dummy + $(MAKE) -C char + +misc/s390-misc.o: dummy + $(MAKE) -C misc + +net/s390-net.o: dummy + $(MAKE) -C net + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/s390/block/Makefile linux/drivers/s390/block/Makefile --- v2.3.99-pre7/linux/drivers/s390/block/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/s390/block/Makefile Fri May 12 11:41:44 2000 @@ -0,0 +1,31 @@ +all: s390-block.o + +CFLAGS += +O_TARGET := s390-block.o +O_OBJS := +M_OBJS := + +ifeq ($(CONFIG_DASD),y) + O_OBJS += dasd.o dasd_ccwstuff.o dasd_erp.o + ifeq ($(CONFIG_PROC_FS),y) + O_OBJS += dasd_proc.o dasd_profile.o + endif + ifeq ($(CONFIG_DASD_ECKD),y) + O_OBJS += dasd_eckd.o + endif + ifeq ($(CONFIG_DASD_MDSK),y) + O_OBJS += dasd_mdsk.o + endif +# ifeq ($(CONFIG_DASD_CKD),y) +# O_OBJS += dasd_ckd.o +# endif +endif + +ifeq ($(CONFIG_MDISK),y) + O_OBJS += mdisk.o +endif + +dasd_mod.o: $(D_OBJS) + $(LD) $(LD_RFLAG) -r -o $@ $+ + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/s390/block/dasd.c linux/drivers/s390/block/dasd.c --- v2.3.99-pre7/linux/drivers/s390/block/dasd.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/s390/block/dasd.c Fri May 12 11:41:44 2000 @@ -0,0 +1,1560 @@ +/* + * File...........: linux/drivers/s390/block/dasd.c + * Author(s)......: Holger Smolinski + * : Utz Bacher + * Bugreports.to..: + * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 + */ + +#include +#include +#include +#include + +#ifdef MODULE +#include +#endif /* MODULE */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "dasd_erp.h" +#include "dasd_types.h" +#include "dasd_ccwstuff.h" + +#define PRINTK_HEADER DASD_NAME":" + +#define CCW_READ_DEVICE_CHARACTERISTICS 0x64 + +#define DASD_SSCH_RETRIES 2 + +/* This macro is a little tricky, but makes the code more easy to read... */ +#define MATCH(info,ct,cm,dt,dm) ( \ +(( info -> sid_data.cu_type ct ) && ( info -> sid_data.cu_model cm )) && \ +(( info -> sid_data.dev_type dt ) && ( info -> sid_data.dev_model dm )) ) + +/* Prototypes for the functions called from external */ +static int dasd_ioctl (struct inode *, struct file *, unsigned int, unsigned long); +static int dasd_open (struct inode *, struct file *); +static int dasd_release (struct inode *, struct file *); + +void dasd_debug (unsigned long tag); +void dasd_profile_add (cqr_t *cqr); +void dasd_proc_init (void); + +static int dasd_format( int, format_data_t * ); + +static struct block_device_operations dasd_device_operations; + +spinlock_t dasd_lock; /* general purpose lock for the dasd driver */ + +/* All asynchronous I/O should waint on this wait_queue */ +wait_queue_head_t dasd_waitq; + +static int dasd_autodetect = 1; +static int dasd_devno[DASD_MAX_DEVICES] = +{0,}; +static int dasd_count = 0; + +extern dasd_chanq_t *cq_head; + +static int +dasd_get_hexdigit (char c) +{ + if ((c >= '0') && (c <= '9')) + return c - '0'; + if ((c >= 'a') && (c <= 'f')) + return c + 10 - 'a'; + if ((c >= 'A') && (c <= 'F')) + return c + 10 - 'A'; + return -1; +} + +/* sets the string pointer after the next comma */ +static void +dasd_scan_for_next_comma (char **strptr) +{ + while (((**strptr) != ',') && ((**strptr)++)) + (*strptr)++; + + /* set the position AFTER the comma */ + if (**strptr == ',') + (*strptr)++; +} + +/*sets the string pointer after the next comma, if a parse error occured */ +static int +dasd_get_next_int (char **strptr) +{ + int j, i = -1; /* for cosmetic reasons first -1, then 0 */ + if (isxdigit (**strptr)) { + for (i = 0; isxdigit (**strptr);) { + i <<= 4; + j = dasd_get_hexdigit (**strptr); + if (j == -1) { + PRINT_ERR ("no integer: skipping range.\n"); + dasd_scan_for_next_comma (strptr); + i = -1; + break; + } + i += j; + (*strptr)++; + if (i > 0xffff) { + PRINT_ERR (" value too big, skipping range.\n"); + dasd_scan_for_next_comma (strptr); + i = -1; + break; + } + } + } + return i; +} + +static inline int +devindex_from_devno (int devno) +{ + int i; + for (i = 0; i < dasd_count; i++) { + if (dasd_devno[i] == devno) + return i; + } + if (dasd_autodetect) { + if (dasd_count < DASD_MAX_DEVICES) { + dasd_devno[dasd_count] = devno; + return dasd_count++; + } + return -EOVERFLOW; + } + return -ENODEV; +} + +/* returns 1, if dasd_no is in the specified ranges, otherwise 0 */ +static inline int +dasd_is_accessible (int devno) +{ + return (devindex_from_devno (devno) >= 0); +} + +/* dasd_insert_range skips ranges, if the start or the end is -1 */ +static void +dasd_insert_range (int start, int end) +{ + int curr; + FUNCTION_ENTRY ("dasd_insert_range"); + if (dasd_count >= DASD_MAX_DEVICES) { + PRINT_ERR (" too many devices specified, ignoring some.\n"); + FUNCTION_EXIT ("dasd_insert_range"); + return; + } + if ((start == -1) || (end == -1)) { + PRINT_ERR + ("invalid format of parameter, skipping range\n"); + FUNCTION_EXIT ("dasd_insert_range"); + return; + } + if (end < start) { + PRINT_ERR (" ignoring range from %x to %x - start value " \ + "must be less than end value.\n", start, end); + FUNCTION_EXIT ("dasd_insert_range"); + return; + } +/* concurrent execution would be critical, but will not occur here */ + for (curr = start; curr <= end; curr++) { + if (dasd_is_accessible (curr)) { + PRINT_WARN (" %x is already in list as device %d\n", + curr, devindex_from_devno (curr)); + } + dasd_devno[dasd_count] = curr; + dasd_count++; + if (dasd_count >= DASD_MAX_DEVICES) { + PRINT_ERR (" too many devices specified, ignoring some.\n"); + break; + } + } + PRINT_INFO (" added dasd range from %x to %x.\n", + start, dasd_devno[dasd_count - 1]); + + FUNCTION_EXIT ("dasd_insert_range"); +} + +static int __init +dasd_setup (char *str) +{ + int devno, devno2; + + FUNCTION_ENTRY ("dasd_setup"); + dasd_autodetect = 0; + while (*str && *str != 1) { + if (!isxdigit (*str)) { + str++; /* to avoid looping on two commas */ + PRINT_ERR (" kernel parameter in invalid format.\n"); + continue; + } + devno = dasd_get_next_int (&str); + + /* range was skipped? -> scan for comma has been done */ + if (devno == -1) + continue; + + if (*str == ',') { + str++; + dasd_insert_range (devno, devno); + continue; + } + if (*str == '-') { + str++; + devno2 = dasd_get_next_int (&str); + if (devno2 == -1) { + PRINT_ERR (" invalid character in " \ + "kernel parameters."); + } else { + dasd_insert_range (devno, devno2); + } + dasd_scan_for_next_comma (&str); + continue; + } + if (*str == 0) { + dasd_insert_range (devno, devno); + break; + } + PRINT_ERR (" unexpected character in kernel parameter, " \ + "skipping range.\n"); + } + FUNCTION_EXIT ("dasd_setup"); + return 1; +} + +__setup("dasd=", dasd_setup); + +dasd_information_t *dasd_info[DASD_MAX_DEVICES] = {NULL,}; +static struct hd_struct dd_hdstruct[DASD_MAX_DEVICES << PARTN_BITS]; +static int dasd_blks[256] = {0,}; +static int dasd_secsize[256] = {0,}; +static int dasd_blksize[256] = {0,}; +static int dasd_maxsecs[256] = {0,}; + +struct gendisk dd_gendisk = +{ + MAJOR_NR, /* Major number */ + "dasd", /* Major name */ + PARTN_BITS, /* Bits to shift to get real from partn */ + 1 << PARTN_BITS, /* Number of partitions per real */ + dd_hdstruct, /* hd struct */ + dasd_blks, /* sizes in blocks */ + DASD_MAX_DEVICES, /* number */ + NULL, /* internal */ + NULL /* next */ + +}; + +static atomic_t bh_scheduled = ATOMIC_INIT (0); + +static inline void +schedule_bh (void (*func) (void)) +{ + static struct tq_struct dasd_tq = + {0,}; + /* Protect against rescheduling, when already running */ + if (atomic_compare_and_swap (0, 1, &bh_scheduled)) + return; + dasd_tq.routine = (void *) (void *) func; + queue_task (&dasd_tq, &tq_immediate); + mark_bh (IMMEDIATE_BH); + return; +} + +void +sleep_done (struct semaphore *sem) +{ + if (sem != NULL) { + up (sem); + } +} + +void +sleep (int timeout) +{ + struct semaphore sem; + struct timer_list timer; + + init_MUTEX_LOCKED (&sem); + init_timer (&timer); + timer.data = (unsigned long) &sem; + timer.expires = jiffies + timeout; + timer.function = (void (*)(unsigned long)) sleep_done; + printk (KERN_DEBUG PRINTK_HEADER + "Sleeping for timer tics %d\n", timeout); + add_timer (&timer); + down (&sem); + del_timer (&timer); +} + +#ifdef CONFIG_DASD_ECKD +extern dasd_operations_t dasd_eckd_operations; +#endif /* CONFIG_DASD_ECKD */ +#ifdef CONFIG_DASD_MDSK +extern dasd_operations_t dasd_mdsk_operations; +#endif /* CONFIG_DASD_MDSK */ + +dasd_operations_t *dasd_disciplines[] = +{ +#ifdef CONFIG_DASD_ECKD + &dasd_eckd_operations, +#endif /* CONFIG_DASD_ECKD */ +#ifdef CONFIG_DASD_MDSK + &dasd_mdsk_operations, +#endif /* CONFIG_DASD_MDSK */ +#ifdef CONFIG_DASD_CKD + &dasd_ckd_operations, +#endif /* CONFIG_DASD_CKD */ + NULL +}; + +char *dasd_name[] = +{ +#ifdef CONFIG_DASD_ECKD + "ECKD", +#endif /* CONFIG_DASD_ECKD */ +#ifdef CONFIG_DASD_MDSK + "MDSK", +#endif /* CONFIG_DASD_MDSK */ +#ifdef CONFIG_DASD_CKD + "CKD", +#endif /* CONFIG_DASD_CKD */ + "END" +}; + + +static inline int +do_dasd_ioctl (struct inode *inp, unsigned int no, unsigned long data) +{ + int rc; + int di; + dasd_information_t *dev; + + di = DEVICE_NR (inp->i_rdev); + if (!dasd_info[di]) { + PRINT_WARN ("No device registered as %d\n", inp->i_rdev); + return -EINVAL; + } + if ((_IOC_DIR (no) != _IOC_NONE) && (data == 0)) { + PRINT_DEBUG ("empty data ptr"); + return -EINVAL; + } + dev = dasd_info[di]; + if (!dev) { + PRINT_WARN ("No device registered as %d\n", inp->i_rdev); + return -EINVAL; + } + PRINT_INFO ("ioctl 0x%08x %s'0x%x'%d(%d) on dev %d/%d (%d) with data %8lx\n", no, + _IOC_DIR (no) == _IOC_NONE ? "0" : + _IOC_DIR (no) == _IOC_READ ? "r" : + _IOC_DIR (no) == _IOC_WRITE ? "w" : + _IOC_DIR (no) == (_IOC_READ | _IOC_WRITE) ? "rw" : "u", + _IOC_TYPE (no), _IOC_NR (no), _IOC_SIZE (no), + MAJOR (inp->i_rdev), MINOR (inp->i_rdev), di, data); + + switch (no) { + case BLKGETSIZE:{ /* Return device size */ + unsigned long blocks; + if (inp->i_rdev & 0x01) { + blocks = (dev->sizes.blocks - 3) << + dev->sizes.s2b_shift; + } else { + blocks = dev->sizes.kbytes << dev->sizes.s2b_shift; + } + rc = copy_to_user ((long *) data, &blocks, sizeof (long)); + break; + } + case BLKFLSBUF:{ + rc = fsync_dev (inp->i_rdev); + break; + } + case BLKRAGET:{ + rc = copy_to_user ((long *) data, + read_ahead + MAJOR_NR, sizeof (long)); + break; + } + case BLKRASET:{ + rc = copy_from_user (read_ahead + MAJOR_NR, + (long *) data, sizeof (long)); + break; + } + case BLKRRPART:{ + INTERNAL_CHECK ("BLKRPART not implemented%s", ""); + rc = -EINVAL; + break; + } + case HDIO_GETGEO:{ + INTERNAL_CHECK ("HDIO_GETGEO not implemented%s", ""); + rc = -EINVAL; + break; + } + + case BIODASDRSID:{ + rc = copy_to_user ((void *) data, + &(dev->info.sid_data), + sizeof (senseid_t)); + break; + } + case BIODASDRWTB:{ + int offset = 0; + int xlt; + rc = copy_from_user (&xlt, (void *) data, + sizeof (int)); + PRINT_INFO("Xlating %d to",xlt); + if (rc) + break; + if (MINOR (inp->i_rdev) & 1) + offset = 3; + xlt += offset; + printk(" %d \n",xlt); + rc = copy_to_user ((void *) data, &xlt, + sizeof (int)); + break; + } + case BIODASDFORMAT:{ + /* fdata == NULL is a valid arg to dasd_format ! */ + format_data_t *fdata = NULL; + if (data) { + fdata = kmalloc (sizeof (format_data_t), + GFP_ATOMIC); + if (!fdata) { + rc = -ENOMEM; + break; + } + rc = copy_from_user (fdata, (void *) data, + sizeof (format_data_t)); + if (rc) + break; + } + rc = dasd_format (inp->i_rdev, fdata); + if (fdata) { + kfree (fdata); + } + break; + } + default: + rc = -EINVAL; + break; + } + return rc; +} + +static void +dasd_end_request (struct request *req, int uptodate) +{ + struct buffer_head *bh; + FUNCTION_ENTRY ("dasd_end_request"); +#if DASD_PARANOIA > 2 + if (!req) { + INTERNAL_CHECK ("end_request called with zero arg%s\n", ""); + } +#endif /* DASD_PARANOIA */ + while ((bh = req->bh) != NULL) { + req->bh = bh->b_reqnext; + bh->b_reqnext = NULL; + bh->b_end_io (bh, uptodate); + } + if (!end_that_request_first (req, uptodate, DEVICE_NAME)) { +#ifndef DEVICE_NO_RANDOM + add_blkdev_randomness (MAJOR (req->rq_dev)); +#endif + DEVICE_OFF (req->rq_dev); + end_that_request_last (req); + } + FUNCTION_EXIT ("dasd_end_request"); + return; +} + +void +dasd_wakeup (void) +{ + wake_up (&dasd_waitq); +} + +int +dasd_unregister_dasd (int irq, dasd_type_t dt, dev_info_t * info) +{ + int rc = 0; + FUNCTION_ENTRY ("dasd_unregister_dasd"); + INTERNAL_CHECK ("dasd_unregister_dasd not implemented%s\n", ""); + FUNCTION_EXIT ("dasd_unregister_dasd"); + return rc; +} + +/* Below you find the functions already cleaned up */ +static dasd_type_t +check_type (dev_info_t * info) +{ + dasd_type_t type = dasd_none; + + FUNCTION_ENTRY ("check_type"); +#ifdef CONFIG_DASD_ECKD + if (MATCH (info, == 0x3990, ||1, == 0x3390, ||1) || + MATCH (info, == 0x9343, ||1, == 0x9345, ||1) || + MATCH (info, == 0x3990, ||1, == 0x3380, ||1)) { + type = dasd_eckd; + } else +#endif /* CONFIG_DASD_ECKD */ +#ifdef CONFIG_DASD_MDSK + if ( MACHINE_IS_VM ) { + type = dasd_mdsk; + } else +#endif /* CONFIG_DASD_MDSK */ + { + type = dasd_none; + } + + FUNCTION_EXIT ("check_type"); + return type; +} + +static int +dasd_read_characteristics (dasd_information_t * info) +{ + int rc; + int ct = 0; + dev_info_t *di; + dasd_type_t dt; + + FUNCTION_ENTRY ("read_characteristics"); + if (info == NULL) { + return -ENODEV; + } + di = &(info->info); + if (di == NULL) { + return -ENODEV; + } + dt = check_type (di); + /* Some cross-checks, if the cu supports RDC */ + if (MATCH (di, == 0x2835, ||1, ||1, ||1) || + MATCH (di, == 0x3830, ||1, ||1, ||1) || + MATCH (di, == 0x3830, ||1, ||1, ||1) || + MATCH (di, == 0x3990, <=0x03, == 0x3380, <=0x0d)) { + PRINT_WARN ("Device %d (%x/%x at %x/%x) supports no RDC\n", + info->info.irq, + di->sid_data.dev_type, + di->sid_data.dev_model, + di->sid_data.cu_type, + di->sid_data.cu_model); + return -EINVAL; + } + switch (dt) { +#ifdef CONFIG_DASD_ECKD + case dasd_eckd: + ct = 64; + rc = read_dev_chars (info->info.irq, + (void *) &(info->rdc_data), ct); + break; +#endif /* CONFIG_DASD_ECKD */ +#ifdef CONFIG_DASD_MDSK + case dasd_mdsk: + ct = 0; + break; +#endif /* CONFIG_DASD_MDSK */ + default: + INTERNAL_ERROR ("don't know dasd type %d\n", dt); + } + if (rc) { + PRINT_WARN ("RDC resulted in rc=%d\n", rc); + } + FUNCTION_EXIT ("read_characteristics"); + return rc; +} + +/* How many sectors must be in a request to dequeue it ? */ +#define QUEUE_BLOCKS 25 +#define QUEUE_SECTORS (QUEUE_BLOCKS << dasd_info[di]->sizes.s2b_shift) + +/* How often to retry an I/O before raising an error */ +#define DASD_MAX_RETRIES 5 + + +static inline + cqr_t * +dasd_cqr_from_req (struct request *req) +{ + cqr_t *cqr = NULL; + int di; + dasd_information_t *info; + + if (!req) { + PRINT_ERR ("No request passed!"); + return NULL; + } + di = DEVICE_NR (req->rq_dev); + info = dasd_info[di]; + if (!info) + return NULL; + /* if applicable relocate block */ + if (MINOR (req->rq_dev) & ((1 << PARTN_BITS) - 1) ) { + req->sector += + dd_gendisk.part[MINOR(req->rq_dev)].start_sect; + } + /* Now check for consistency */ + if (!req->nr_sectors) { + PRINT_WARN ("req: %p dev: %08x sector: %ld nr_sectors: %ld bh: %p\n", + req, req->rq_dev, req->sector, req->nr_sectors, req->bh); + return NULL; + } + if (((req->sector + req->nr_sectors) >> 1) > info->sizes.kbytes) { + printk (KERN_ERR PRINTK_HEADER + "Requesting I/O past end of device %d\n", + di); + return NULL; + } + cqr = dasd_disciplines[info->type]->get_req_ccw (di, req); + if (!cqr) { + PRINT_WARN ("empty CQR generated\n"); + } else { + cqr->req = req; + cqr->int4cqr = cqr; + cqr->devindex = di; +#ifdef DASD_PROFILE + asm volatile ("STCK %0":"=m" (cqr->buildclk)); +#endif /* DASD_PROFILE */ + if (atomic_compare_and_swap (CQR_STATUS_EMPTY, + CQR_STATUS_FILLED, + &cqr->status)) { + PRINT_WARN ("cqr from req stat changed %d\n", + atomic_read (&cqr->status)); + } + } + return cqr; +} + +int +dasd_start_IO (cqr_t * cqr) +{ + int rc = 0; + int retries = DASD_SSCH_RETRIES; + int di, irq; + + dasd_debug ((unsigned long) cqr); /* cqr */ + + if (!cqr) { + PRINT_WARN ("(start_IO) no cqr passed\n"); + return -EINVAL; + } + if (cqr->magic != DASD_MAGIC) { + PRINT_WARN ("(start_IO) magic number mismatch\n"); + return -EINVAL; + } + if (atomic_compare_and_swap (CQR_STATUS_QUEUED, + CQR_STATUS_IN_IO, + &cqr->status)) { + PRINT_WARN ("start_IO: status changed %d\n", + atomic_read (&cqr->status)); + atomic_set (&cqr->status, CQR_STATUS_ERROR); + return -EINVAL; + } + di = cqr->devindex; + irq = dasd_info[di]->info.irq; + do { + asm volatile ("STCK %0":"=m" (cqr->startclk)); + rc = do_IO (irq, cqr->cpaddr, (long) cqr, 0x00, cqr->options); + switch (rc) { + case 0: + if (!(cqr->options & DOIO_WAIT_FOR_INTERRUPT)) + atomic_set_mask (DASD_CHANQ_BUSY, + &dasd_info[di]->queue.flags); + break; + case -ENODEV: + PRINT_WARN ("cqr %p: 0x%04x error, %d retries left\n", + cqr, dasd_info[di]->info.devno, retries); + break; + case -EIO: + PRINT_WARN ("cqr %p: 0x%04x I/O, %d retries left\n", + cqr, dasd_info[di]->info.devno, retries); + break; + case -EBUSY: /* set up timer, try later */ + + PRINT_WARN ("cqr %p: 0x%04x busy, %d retries left\n", + cqr, dasd_info[di]->info.devno, retries); + break; + default: + + PRINT_WARN ("cqr %p: 0x%04x %d, %d retries left\n", + cqr, rc, dasd_info[di]->info.devno, + retries); + break; + } + } while (rc && --retries); + if (rc) { + if (atomic_compare_and_swap (CQR_STATUS_IN_IO, + CQR_STATUS_ERROR, + &cqr->status)) { + PRINT_WARN ("start_IO:(done) status changed %d\n", + atomic_read (&cqr->status)); + atomic_set (&cqr->status, CQR_STATUS_ERROR); + } + } + return rc; +} + +static inline +void +dasd_end_cqr (cqr_t * cqr, int uptodate) +{ + struct request *req = cqr->req; + asm volatile ("STCK %0":"=m" (cqr->endclk)); +#ifdef DASD_PROFILE + dasd_profile_add (cqr); +#endif /* DASD_PROFILE */ + dasd_chanq_deq (&dasd_info[cqr->devindex]->queue, cqr); + if (req) { + dasd_end_request (req, uptodate); + } +} + +void +dasd_dump_sense (devstat_t * stat) +{ + int sl, sct; + if ( ! stat->flag | DEVSTAT_FLAG_SENSE_AVAIL) { + PRINT_INFO("I/O status w/o sense data"); + } else { + printk (KERN_INFO PRINTK_HEADER + "-------------------I/O result:-----------\n"); + for (sl = 0; sl < 4; sl++) { + printk (KERN_INFO PRINTK_HEADER "Sense:"); + for (sct = 0; sct < 8; sct++) { + printk (" %2d:0x%02X", 8 * sl + sct, + stat->ii.sense.data[8 * sl + sct]); + } + printk ("\n"); + } + } +} + +static int +register_dasd_last (int di) +{ + int rc = 0; + int minor; + struct buffer_head *bh; + rc = dasd_disciplines[dasd_info[di]->type]->fill_sizes_last (di); + switch (rc) { + case -EMEDIUMTYPE: + dasd_info[di]->flags |= DASD_INFO_FLAGS_NOT_FORMATTED; + break; + } + PRINT_INFO ("%ld kB <- 'soft'-block: %d, hardsect %d Bytes\n", + dasd_info[di]->sizes.kbytes, + dasd_info[di]->sizes.bp_block, + dasd_info[di]->sizes.bp_sector); + switch (dasd_info[di]->type) { +#ifdef CONFIG_DASD_ECKD + case dasd_eckd: + dasd_info[di]->sizes.label_block = 2; + break; +#endif /* CONFIG_DASD_ECKD */ +#ifdef CONFIG_DASD_MDSK + case dasd_mdsk: + dasd_info[di]->sizes.label_block = -1; + break; +#endif /* CONFIG_DASD_ECKD */ + + default: + INTERNAL_CHECK ("Unknown dasd type %d\n", dasd_info[di]->type); + } + minor = di << PARTN_BITS; + dasd_blks[minor] = dasd_info[di]->sizes.kbytes; + dasd_secsize[minor] = dasd_info[di]->sizes.bp_sector; + dasd_blksize[minor] = dasd_info[di]->sizes.bp_block; + dasd_maxsecs[minor] = 252<sizes.s2b_shift; + dasd_secsize[minor+1] = dasd_info[di]->sizes.bp_sector; + dasd_blksize[minor+1] = dasd_info[di]->sizes.bp_block; + dasd_maxsecs[minor+1] = 252<sizes.s2b_shift; + + { +#define DASD_NAME_PREFIX "dasd_" + char * name = (char *) kmalloc ( 1+strlen (DASD_NAME_PREFIX) + + 2 /* 0x */ + 4 /* devno */, + GFP_KERNEL); + sprintf ( name , DASD_NAME_PREFIX "%04x%c", + dasd_info[di]->info.devno,'\0' ); + dasd_info[di] -> devfs_entry = + devfs_register ( NULL /* dir */, + name, strlen(name), + 0 /* flags */, + DASD_MAJOR, minor, + 0755 /* mode */, + 0 /* uid */ , 0 /* gid */, + &dasd_device_operations, + (void *)dasd_info[di]); + } + /* end of that stuff */ + return rc; +} + +void +dasd_partn_detect ( int di ) +{ + int minor = di << PARTN_BITS; + LOOP_CONTROL ("Setting partitions of DASD %d\n", di); + register_disk (&dd_gendisk, + MKDEV(DASD_MAJOR,minor), + 1 << PARTN_BITS, + &dasd_device_operations, + dasd_info[di]->sizes.kbytes << 1); +} + +void +dasd_do_chanq (void) +{ + dasd_chanq_t *qp = NULL; + cqr_t *cqr; + long flags; + int irq; + int tasks; + atomic_set (&bh_scheduled, 0); + dasd_debug (0xc4c40000); /* DD */ + while ((tasks = atomic_read(&chanq_tasks)) != 0) { +/* initialization and wraparound */ + if (qp == NULL) { + dasd_debug (0xc4c46df0); /* DD_0 */ + qp = cq_head; + if (!qp) { + dasd_debug (0xc4c46ff1); /* DD?1 */ + dasd_debug (tasks); + PRINT_ERR("Mismatch of NULL queue pointer and " + "still %d chanq_tasks to do!!\n" + "Please send output of /proc/dasd/debug " + "to Linux390@de.ibm.com\n", tasks); + atomic_set(&chanq_tasks,0); + break; + } + } +/* Get first request */ + dasd_debug ((unsigned long) qp); + cqr = (cqr_t *) (qp->head); +/* empty queue -> dequeue and proceed */ + if (!cqr) { + dasd_chanq_t *nqp = qp->next_q; + cql_deq (qp); + qp = nqp; + continue; + } +/* process all requests on that queue */ + do { + cqr_t *next; + dasd_debug ((unsigned long) cqr); /* cqr */ + if (cqr->magic != DASD_MAGIC) { + dasd_debug (0xc4c46ff2); /* DD?2 */ + panic ( PRINTK_HEADER "do_cq:" + "magic mismatch %p -> %x\n", + cqr, cqr -> magic); + break; + } + irq = dasd_info[cqr->devindex]->info.irq; + s390irq_spin_lock_irqsave (irq, flags); + switch (atomic_read (&cqr->status)) { + case CQR_STATUS_IN_IO: + dasd_debug (0xc4c4c9d6); /* DDIO */ + cqr = NULL; + break; + case CQR_STATUS_QUEUED: + dasd_debug (0xc4c4e2e3); /* DDST */ + if (dasd_start_IO (cqr) == 0) { + atomic_dec (&chanq_tasks); + cqr = NULL; + } + break; + case CQR_STATUS_ERROR: + dasd_debug (0xc4c4c5d9); /* DDER */ + dasd_dump_sense (cqr->dstat); + if ( ++ cqr->retries < 2 ) { + atomic_set (&cqr->status, + CQR_STATUS_QUEUED); + dasd_debug (0xc4c4e2e3); /* DDST */ + if (dasd_start_IO (cqr) == 0) { + atomic_dec ( &qp -> + dirty_requests); + atomic_dec (&chanq_tasks); + cqr = NULL; + } + } else { + atomic_set (&cqr->status, + CQR_STATUS_FAILED); + } + break; + case CQR_STATUS_DONE: + next = cqr->next; + dasd_debug (0xc4c49692); /* DDok */ + dasd_end_cqr (cqr, 1); + atomic_dec (&chanq_tasks); + cqr = next; + break; + case CQR_STATUS_FAILED: + next = cqr->next; + dasd_debug (0xc4c47a7a); /* DD:: */ + if ( ! ( dasd_info[cqr->devindex]-> flags & + DASD_INFO_FLAGS_INITIALIZED ) ) { + dasd_info[cqr->devindex]-> flags |= + DASD_INFO_FLAGS_INITIALIZED | + DASD_INFO_FLAGS_NOT_FORMATTED; + } + dasd_end_cqr (cqr, 0); + atomic_dec ( &qp -> dirty_requests ); + atomic_dec (&chanq_tasks); + cqr = next; + break; + default: + PRINT_WARN ("unknown cqrstatus\n"); + cqr = NULL; + } + s390irq_spin_unlock_irqrestore (irq, flags); + } while (cqr); + qp = qp->next_q; + } + spin_lock (&io_request_lock); + do_dasd_request (&blk_dev[DASD_MAJOR].request_queue); + spin_unlock (&io_request_lock); + dasd_debug (0xc4c46d6d); /* DD__ */ +} + +/* + The request_fn is called from ll_rw_blk for any new request. + We use it to feed the chanqs. + This implementation assumes we are serialized by the io_request_lock. + */ + +#define QUEUE_THRESHOLD 5 + +void +do_dasd_request (request_queue_t *queue) +{ + struct request *req; + cqr_t *cqr; + dasd_chanq_t *q; + long flags; + int di, irq, go; + int broken, busy; + + dasd_debug (0xc4d90000); /* DR */ + dasd_debug ((unsigned long) __builtin_return_address(0)); + go = 1; + while (go && !list_empty(&queue->queue_head)) { + req = blkdev_entry_next_request(&queue->queue_head); + req = blkdev_entry_next_request(&queue->queue_head); + di = DEVICE_NR (req->rq_dev); + dasd_debug ((unsigned long) req); /* req */ + dasd_debug (0xc4d90000 + /* DR## */ + ((((di/16)<9?(di/16)+0xf0:(di/16)+0xc1))<<8) + + (((di%16)<9?(di%16)+0xf0:(di%16)+0xc1))); + irq = dasd_info[di]->info.irq; + s390irq_spin_lock_irqsave (irq, flags); + q = &dasd_info[di]->queue; + busy = atomic_read(&q->flags) & DASD_CHANQ_BUSY; + broken = atomic_read(&q->flags)&DASD_REQUEST_Q_BROKEN; + if ( ! busy || + ( ! broken && + (req->nr_sectors >= QUEUE_SECTORS))) { + blkdev_dequeue_request(req); + /* + printk ( KERN_INFO "0x%04x %c %d %d\n", + req->rq_dev,req->cmd ?'w':'r', + req->sector,req->nr_sectors); + */ + cqr = dasd_cqr_from_req (req); + if (!cqr) { + dasd_debug (0xc4d96ff1); /* DR?1 */ + dasd_end_request (req, 0); + goto cont; + } + dasd_debug ((unsigned long) cqr); /* cqr */ + dasd_chanq_enq (q, cqr); + if (!(atomic_read (&q->flags) & + DASD_CHANQ_ACTIVE)) { + cql_enq_head (q); + } + if ( ! busy ) { + atomic_clear_mask (DASD_REQUEST_Q_BROKEN, + &q->flags ); + if (atomic_read( &q->dirty_requests) == 0 ) { + if ( dasd_start_IO (cqr) == 0 ) { + } else { + atomic_inc (&chanq_tasks); + schedule_bh (dasd_do_chanq); + } + } + } + } else { + dasd_debug (0xc4d9c2d9); /* DRBR */ + atomic_set_mask (DASD_REQUEST_Q_BROKEN, &q->flags ); + go = 0; + } + cont: + s390irq_spin_unlock_irqrestore (irq, flags); + } + dasd_debug (0xc4d96d6d); /* DR__ */ +} + +void +dasd_handler (int irq, void *ds, struct pt_regs *regs) +{ + devstat_t *stat = (devstat_t *) ds; + int ip; + cqr_t *cqr; + int done_fast_io = 0; + + dasd_debug (0xc4c80000); /* DH */ + if (!stat) + PRINT_ERR ("handler called without devstat"); + ip = stat->intparm; + dasd_debug (ip); /* intparm */ + switch (ip) { /* filter special intparms... */ + case 0x00000000: /* no intparm: unsolicited interrupt */ + dasd_debug (0xc4c8a489); /* DHui */ + PRINT_INFO ("Unsolicited interrupt on device %04X\n", + stat->devno); + dasd_dump_sense (stat); + return; + default: + if (ip & 0x80000001) { + dasd_debug (0xc4c8a489); /* DHui */ + PRINT_INFO ("Spurious interrupt %08x on device %04X\n", + ip, stat->devno); + return; + } + cqr = (cqr_t *) ip; + if (cqr->magic != DASD_MAGIC) { + dasd_debug (0xc4c86ff1); /* DH?1 */ + PRINT_ERR ("handler:magic mismatch on %p %08x\n", + cqr, cqr->magic); + return; + } + asm volatile ("STCK %0":"=m" (cqr->stopclk)); + if ( ( stat->cstat == 0x00 && + stat->dstat == (DEV_STAT_CHN_END|DEV_STAT_DEV_END) ) || + dasd_erp_examine ( cqr ) == dasd_era_none ) { + dasd_debug (0xc4c89692); /* DHok */ + if (atomic_compare_and_swap (CQR_STATUS_IN_IO, + CQR_STATUS_DONE, + &cqr->status)) { + PRINT_WARN ("handler: cqrstat changed%d\n", + atomic_read (&cqr->status)); + atomic_set(&cqr->status, CQR_STATUS_DONE); + } + if ( ! ( dasd_info[cqr->devindex]-> flags & + DASD_INFO_FLAGS_INITIALIZED ) ) { + int rc = register_dasd_last ( cqr->devindex ); + dasd_info[cqr->devindex]-> flags |= + DASD_INFO_FLAGS_INITIALIZED; + if ( rc ) { + dasd_info[cqr->devindex]->flags &= + ~DASD_INFO_FLAGS_NOT_FORMATTED; + } else { + dasd_info[cqr->devindex]->flags |= + DASD_INFO_FLAGS_NOT_FORMATTED; + } + } + if (cqr->next) { + dasd_debug (0xc4c8e2e3); /* DHST */ + if (dasd_start_IO (cqr->next) == 0) { + done_fast_io = 1; + } else { + atomic_inc (&chanq_tasks); + } + } + break; + } + /* only visited in case of error ! */ + dasd_debug (0xc4c8c5d9); /* DHER */ + if (!cqr->dstat) + cqr->dstat = kmalloc (sizeof (devstat_t), + GFP_ATOMIC); + if (cqr->dstat) { + memcpy (cqr->dstat, stat, sizeof (devstat_t)); + } else { + PRINT_ERR ("no memory for dstat\n"); + } + /* errorprocessing */ + atomic_set (&cqr->status, CQR_STATUS_ERROR); + atomic_inc (&dasd_info[cqr->devindex]->queue.dirty_requests); + } + if (done_fast_io == 0) + atomic_clear_mask (DASD_CHANQ_BUSY, + &dasd_info[cqr->devindex]->queue.flags); + + if (cqr->flags & DASD_DO_IO_SLEEP) { + dasd_debug (0xc4c8a6a4); /* DHwu */ + dasd_wakeup (); + } else if (! (cqr->options & DOIO_WAIT_FOR_INTERRUPT) ){ + dasd_debug (0xc4c8a293); /* DHsl */ + atomic_inc (&chanq_tasks); + schedule_bh (dasd_do_chanq); + } else { + dasd_debug (0x64686f6f); /* DH_g */ + dasd_debug (cqr->flags); /* DH_g */ + } + dasd_debug (0xc4c86d6d); /* DHwu */ +} + +static int +dasd_format (int dev, format_data_t * fdata) +{ + int rc; + int devindex = DEVICE_NR (dev); + dasd_chanq_t *q; + cqr_t *cqr; + int irq; + long flags; + PRINT_INFO ("Format called with devno %x\n", dev); + if (MINOR (dev) & (0xff >> (8 - PARTN_BITS))) { + PRINT_WARN ("Can't format partition! minor %x %x\n", + MINOR (dev), 0xff >> (8 - PARTN_BITS)); + return -EINVAL; + } + down (&dasd_info[devindex]->sem); + if (dasd_info[devindex]->open_count == 1) { + rc = dasd_disciplines[dasd_info[devindex]->type]-> + dasd_format (devindex, fdata); + if (rc) { + PRINT_WARN ("Formatting failed rc=%d\n", rc); + } + } else { + PRINT_WARN ("device is open! %d\n", dasd_info[devindex]->open_count); + rc = -EINVAL; + } + if (!rc) { +#if DASD_PARANOIA > 1 + if (!dasd_disciplines[dasd_info[devindex]->type]->fill_sizes_first) { + INTERNAL_CHECK ("No fill_sizes for dt=%d\n", dasd_info[devindex]->type); + } else +#endif /* DASD_PARANOIA */ + { + dasd_info[devindex]->flags &= ~DASD_INFO_FLAGS_INITIALIZED; + irq = dasd_info[devindex]->info.irq; + PRINT_INFO ("Trying to access DASD %x, irq %x, index %d\n", + get_devno_by_irq(irq), irq, devindex); + s390irq_spin_lock_irqsave (irq, flags); + q = &dasd_info[devindex]->queue; + cqr = dasd_disciplines[dasd_info[devindex]->type]-> + fill_sizes_first (devindex); + dasd_chanq_enq (q, cqr); + schedule_bh(dasd_do_chanq); + s390irq_spin_unlock_irqrestore (irq, flags); + } + } + up (&dasd_info[devindex]->sem); + return rc; +} + + +static int +register_dasd (int irq, dasd_type_t dt, dev_info_t * info) +{ + int rc = 0; + int di; + unsigned long flags; + dasd_chanq_t *q; + cqr_t * cqr; + static spinlock_t register_lock = SPIN_LOCK_UNLOCKED; + spin_lock (®ister_lock); + FUNCTION_ENTRY ("register_dasd"); + di = devindex_from_devno (info->devno); + if (di < 0) { + INTERNAL_CHECK ("Can't get index for devno %d\n", info->devno); + return -ENODEV; + } + if (dasd_info[di]) { /* devindex is not free */ + INTERNAL_CHECK ("reusing allocated deviceindex %d\n", di); + return -ENODEV; + } + dasd_info[di] = (dasd_information_t *) + kmalloc (sizeof (dasd_information_t), GFP_ATOMIC); + if (dasd_info[di] == NULL) { + PRINT_WARN ("No memory for dasd_info_t on irq %d\n", irq); + return -ENOMEM; + } + memset (dasd_info[di], 0, sizeof (dasd_information_t)); + memcpy (&(dasd_info[di]->info), info, sizeof (dev_info_t)); + spin_lock_init (&dasd_info[di]->queue.f_lock); + spin_lock_init (&dasd_info[di]->queue.q_lock); + dasd_info[di]->type = dt; + dasd_info[di]->irq = irq; + init_MUTEX (&dasd_info[di]->sem); + rc = dasd_read_characteristics (dasd_info[di]); + if (rc) { + PRINT_WARN ("RDC returned error %d\n", rc); + rc = -ENODEV; + goto unalloc; + } +#if DASD_PARANOIA > 1 + if (dasd_disciplines[dt]->ck_characteristics) +#endif /* DASD_PARANOIA */ + rc = dasd_disciplines[dt]-> + ck_characteristics (dasd_info[di]->rdc_data); + + if (rc) { + INTERNAL_CHECK ("Discipline returned non-zero when" + "checking device characteristics%s\n", ""); + rc = -ENODEV; + goto unalloc; + } + rc = request_irq (irq, dasd_handler, 0, "dasd", + &(dasd_info[di]->dev_status)); + if (rc) { +#if DASD_PARANOIA > 0 + printk (KERN_WARNING PRINTK_HEADER + "Cannot register irq %d, rc=%d\n", + irq, rc); +#endif /* DASD_PARANOIA */ + rc = -ENODEV; + goto unalloc; + } +#if DASD_PARANOIA > 1 + if (!dasd_disciplines[dt]->fill_sizes_first) { + INTERNAL_CHECK ("No fill_sizes for dt=%d\n", dt); + goto unregister; + } +#endif /* DASD_PARANOIA */ + irq = dasd_info[di]->info.irq; + PRINT_INFO ("Trying to access DASD %x, irq %x, index %d\n", + get_devno_by_irq(irq), irq, di); + s390irq_spin_lock_irqsave (irq, flags); + q = &dasd_info[di]->queue; + cqr = dasd_disciplines[dt]->fill_sizes_first (di); + dasd_chanq_enq (q, cqr); + cql_enq_head(q); + if (dasd_start_IO(cqr) != 0) { + atomic_inc(&chanq_tasks); + } + s390irq_spin_unlock_irqrestore (irq, flags); + + goto exit; + + unregister: + free_irq (irq, &(dasd_info[di]->dev_status)); + unalloc: + kfree (dasd_info[di]); + exit: + spin_unlock (®ister_lock); + FUNCTION_EXIT ("register_dasd"); + return rc; +} + +static int +probe_for_dasd (int irq) +{ + int rc; + dev_info_t info; + dasd_type_t dt; + + FUNCTION_ENTRY ("probe_for_dasd"); + + rc = get_dev_info_by_irq (irq, &info); + if (rc == -ENODEV) { /* end of device list */ + return rc; + } +#if DASD_PARANOIA > 2 + if (rc) { + INTERNAL_CHECK ("unknown rc %d of get_dev_info", rc); + return rc; + } +#endif /* DASD_PARANOIA */ + if ((info.status & DEVSTAT_NOT_OPER)) { + return -ENODEV; + } + dt = check_type (&info); + switch (dt) { +#ifdef CONFIG_DASD_ECKD + case dasd_eckd: +#endif /* CONFIG_DASD_ECKD */ + FUNCTION_CONTROL ("Probing devno %d...\n", info.devno); + if (!dasd_is_accessible (info.devno)) { + FUNCTION_CONTROL ("out of range...skip%s\n", ""); + return -ENODEV; + } + if (dasd_disciplines[dt]->ck_devinfo) { + rc = dasd_disciplines[dt]->ck_devinfo (&info); + } +#if DASD_PARANOIA > 1 + else { + INTERNAL_ERROR ("no ck_devinfo function%s\n", ""); + return -ENODEV; + } +#endif /* DASD_PARANOIA */ + if (rc == -ENODEV) { + return rc; + } +#if DASD_PARANOIA > 2 + if (rc) { + INTERNAL_CHECK ("unknown error rc=%d\n", rc); + return -ENODEV; + } +#endif /* DASD_PARANOIA */ + rc = register_dasd (irq, dt, &info); + if (rc) { + PRINT_INFO ("devno %x not enabled as minor %d due to errors\n", + info.devno, + devindex_from_devno (info.devno) << + PARTN_BITS); + } else { + PRINT_INFO ("devno %x added as minor %d (%s)\n", + info.devno, + devindex_from_devno (info.devno) << PARTN_BITS, + dasd_name[dt]); + } + case dasd_none: + break; + default: + PRINT_DEBUG ("unknown device type\n"); + break; + } + FUNCTION_EXIT ("probe_for_dasd"); + return rc; +} + +static int +register_major (int major) +{ + request_queue_t *q; + int rc = 0; + + FUNCTION_ENTRY ("register_major"); + rc = devfs_register_blkdev (major, DASD_NAME, &dasd_device_operations); +#if DASD_PARANOIA > 1 + if (rc) { + PRINT_WARN ("registering major -> rc=%d aborting... \n", rc); + return rc; + } +#endif /* DASD_PARANOIA */ + q = BLK_DEFAULT_QUEUE(major); + blk_init_queue(q, do_dasd_request); + blk_queue_headactive(BLK_DEFAULT_QUEUE(major), 0); + FUNCTION_CONTROL ("successfully registered major: %d\n", major); + FUNCTION_EXIT ("register_major"); + return rc; +} + +/* + Below you find functions which are called from outside. Some of them may be + static, because they are called by their function pointers only. Thus static + modifier is to make sure, that they are only called via the kernel's methods + */ + +static int +dasd_ioctl (struct inode *inp, struct file *filp, + unsigned int no, unsigned long data) +{ + int rc = 0; + FUNCTION_ENTRY ("dasd_ioctl"); + if ((!inp) || !(inp->i_rdev)) { + return -EINVAL; + } + rc = do_dasd_ioctl (inp, no, data); + FUNCTION_EXIT ("dasd_ioctl"); + return rc; +} + +static int +dasd_open (struct inode *inp, struct file *filp) +{ + int rc = 0; + dasd_information_t *dev; + FUNCTION_ENTRY ("dasd_open"); + if ((!inp) || !(inp->i_rdev)) { + return -EINVAL; + } + dev = dasd_info[DEVICE_NR (inp->i_rdev)]; + if (!dev) { + PRINT_DEBUG ("No device registered as %d (%d)\n", + inp->i_rdev, DEVICE_NR (inp->i_rdev)); + return -EINVAL; + } + down (&dev->sem); + up (&dev->sem); +#ifdef MODULE + MOD_INC_USE_COUNT; +#endif /* MODULE */ +#if DASD_PARANOIA > 2 + if (dev->open_count < 0) { + INTERNAL_ERROR ("open count cannot be less than 0: %d", + dev->open_count); + return -EINVAL; + } +#endif /* DASD_PARANOIA */ + dev->open_count++; + FUNCTION_EXIT ("dasd_open"); + return rc; +} + +static int +dasd_release (struct inode *inp, struct file *filp) +{ + int rc = 0; + dasd_information_t *dev; + FUNCTION_ENTRY ("dasd_release"); + if ((!inp) || !(inp->i_rdev)) { + return -EINVAL; + } + dev = dasd_info[DEVICE_NR (inp->i_rdev)]; + if (!dev) { + PRINT_WARN ("No device registered as %d\n", inp->i_rdev); + return -EINVAL; + } +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif /* MODULE */ +#if DASD_PARANOIA > 2 + if (!dev->open_count) { + PRINT_WARN ("device %d has not been opened before:\n", + inp->i_rdev); + } +#endif /* DASD_PARANOIA */ + dev->open_count--; +#if DASD_PARANOIA > 2 + if (dev->open_count < 0) { + INTERNAL_ERROR ("open count cannot be less than 0: %d", + dev->open_count); + return -EINVAL; + } +#endif /* DASD_PARANOIA */ + FUNCTION_EXIT ("dasd_release"); + return rc; +} + +static struct +block_device_operations dasd_device_operations = +{ + ioctl: dasd_ioctl, + open: dasd_open, + release: dasd_release, +}; + +int +dasd_init (void) +{ + int rc = 0; + int i; + + FUNCTION_ENTRY ("dasd_init"); + PRINT_INFO ("initializing...\n"); + atomic_set (&chanq_tasks, 0); + atomic_set (&bh_scheduled, 0); + spin_lock_init (&dasd_lock); + init_waitqueue_head(&dasd_waitq); + /* First register to the major number */ + rc = register_major (MAJOR_NR); +#if DASD_PARANOIA > 1 + if (rc) { + PRINT_WARN ("registering major_nr returned rc=%d\n", rc); + return rc; + } +#endif /* DASD_PARANOIA */ + read_ahead[MAJOR_NR] = 8; + blk_size[MAJOR_NR] = dasd_blks; + hardsect_size[MAJOR_NR] = dasd_secsize; + blksize_size[MAJOR_NR] = dasd_blksize; + max_sectors[MAJOR_NR] = dasd_maxsecs; +#ifdef CONFIG_PROC_FS + dasd_proc_init (); +#endif /* CONFIG_PROC_FS */ + /* Now scan the device list for DASDs */ + FUNCTION_CONTROL ("entering detection loop%s\n", ""); + for (i = 0; i < NR_IRQS; i++) { + int irc; /* Internal return code */ + LOOP_CONTROL ("Probing irq %d...\n", i); + irc = probe_for_dasd (i); + switch (irc) { + case 0: + LOOP_CONTROL ("Added DASD%s\n", ""); + break; + case -ENODEV: + LOOP_CONTROL ("No DASD%s\n", ""); + break; + case -EMEDIUMTYPE: + PRINT_WARN ("DASD not formatted%s\n", ""); + break; + default: + INTERNAL_CHECK ("probe_for_dasd: unknown rc=%d", irc); + break; + } + } + FUNCTION_CONTROL ("detection loop completed %s partn check...\n", ""); +/* Finally do the genhd stuff */ + dd_gendisk.next = gendisk_head; + gendisk_head = &dd_gendisk; + for ( i = 0; i < DASD_MAX_DEVICES; i ++ ) + if ( dasd_info[i] ) + dasd_partn_detect ( i ); + + FUNCTION_EXIT ("dasd_init"); + return rc; +} + +#ifdef MODULE +int +init_module (void) +{ + int rc = 0; + + FUNCTION_ENTRY ("init_module"); + PRINT_INFO ("trying to load module\n"); + rc = dasd_init (); + if (rc == 0) { + PRINT_INFO ("module loaded successfully\n"); + } else { + PRINT_WARN ("warning: Module load returned rc=%d\n", rc); + } + FUNCTION_EXIT ("init_module"); + return rc; +} + +void +cleanup_module (void) +{ + int rc = 0; + + FUNCTION_ENTRY ("cleanup_module"); + PRINT_INFO ("trying to unload module \n"); + + /* FIXME: replace by proper unload functionality */ + INTERNAL_ERROR ("Modules not yet implemented %s", ""); + + if (rc == 0) { + PRINT_INFO ("module unloaded successfully\n"); + } else { + PRINT_WARN ("module unloaded with errors\n"); + } + FUNCTION_EXIT ("cleanup_module"); +} +#endif /* MODULE */ + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 4 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -4 + * c-argdecl-indent: 4 + * c-label-offset: -4 + * c-continued-statement-offset: 4 + * c-continued-brace-offset: 0 + * indent-tabs-mode: nil + * tab-width: 8 + * End: + */ diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/s390/block/dasd_ccwstuff.c linux/drivers/s390/block/dasd_ccwstuff.c --- v2.3.99-pre7/linux/drivers/s390/block/dasd_ccwstuff.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/s390/block/dasd_ccwstuff.c Fri May 12 11:41:44 2000 @@ -0,0 +1,419 @@ +/* + * File...........: linux/drivers/s390/block/dasd_ccwstuff.c + * Author(s)......: Holger Smolinski + * Bugreports.to..: + * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 + */ + +#include +#include +#include +#include +#include + +#include "dasd_types.h" + +#define PRINTK_HEADER "dasd_ccw:" +#define MAX_CP_POWER 9 /* Maximum allowed index */ +#define CP_PER_PAGE_POWER 9 /* Maximum index, fitting on page */ + +#define get_free_pages __get_free_pages + +/* Stuff for the handling task_list */ +dasd_chanq_t *cq_head = NULL; /* head of task_list */ +atomic_t chanq_tasks; + +/* Array of freelists for the channel programs' -space */ +static ccw1_t *ccwarea[CP_PER_PAGE_POWER + 1] = +{NULL,}; + +/* array of pages retrieved for internal use */ +#define MAX_DASD_PAGES 64 +static int dasd_page_count = 0; +static long dasd_page[MAX_DASD_PAGES]; + +static spinlock_t ccw_lock=SPIN_LOCK_UNLOCKED; /* spinlock for ccwareas */ +static spinlock_t cq_lock=SPIN_LOCK_UNLOCKED; /* spinlock for cq_head */ + +void +ccwarea_enq (int index, ccw1_t * area) +{ + FUNCTION_ENTRY ("ccwarea_enq"); +#if DASD_PARANOIA > 2 + if (!area) { + INTERNAL_CHECK ("zero area %s\n", ""); + } + if (index > CP_PER_PAGE_POWER) { + INTERNAL_CHECK ("index too large %d\n", index); + } +#endif + *(ccw1_t **) area = ccwarea[index]; + ccwarea[index] = area; + FUNCTION_EXIT ("ccwarea_enq"); + return; +} + +ccw1_t * +ccwarea_deq (int index) +{ + ccw1_t *cp; + FUNCTION_ENTRY ("ccwarea_deq"); +#if DASD_PARANOIA > 2 + if (index > CP_PER_PAGE_POWER) { + INTERNAL_CHECK ("index too large %d\n", index); + } +#endif + cp = ccwarea[index]; + ccwarea[index] = *(ccw1_t **) ccwarea[index]; +#if DASD_PARANOIA > 2 + if (!cp) { + INTERNAL_CHECK ("returning NULL %s\n", ""); + } +#endif + FUNCTION_EXIT ("ccwarea_deq"); + return cp; +} + +ccw1_t * +request_cpa (int index) +{ + ccw1_t *freeblk; + FUNCTION_ENTRY ("request_cpa"); + if (index > MAX_CP_POWER) { + INTERNAL_ERROR ("index too large %d\n", index); + freeblk = NULL; + goto exit; + } + if (index > CP_PER_PAGE_POWER) { + int pc = 1 << (index - CP_PER_PAGE_POWER); + do { + freeblk = (ccw1_t *) get_free_pages (GFP_ATOMIC, index - CP_PER_PAGE_POWER); + if (dasd_page_count + pc >= MAX_DASD_PAGES) { + PRINT_WARN ("Requesting too many pages..."); + } else { + int i; + for (i = 0; i < pc; i++) + dasd_page[dasd_page_count++] = + (long) freeblk + i * PAGE_SIZE; + } + FUNCTION_CONTROL ("requesting index %d", index); + if ( ! freeblk ) { + panic ("No memory received\n"); + } + } while (!freeblk); + memset(freeblk,0,PAGE_SIZE<<(index-CP_PER_PAGE_POWER)); + goto exit; + } + while (ccwarea[index] == NULL) { + ccw1_t *blk; + if (index == CP_PER_PAGE_POWER) { + do { + blk = (ccw1_t *) get_free_page (GFP_ATOMIC); + if (dasd_page_count + 1 >= MAX_DASD_PAGES) { + PRINT_WARN ("Requesting too many pages..."); + } else { + dasd_page[dasd_page_count++] = + (long) blk; + } + if (blk == NULL) { + PRINT_WARN ("Can't allocate page!\n"); + } + } while ( ! blk ); + memset(blk,0,PAGE_SIZE); + ccwarea_enq (CP_PER_PAGE_POWER, blk); + continue; + } + blk = request_cpa (index + 1); +#if DASD_PARANOIA > 1 + if (!blk) { + PRINT_WARN ("retrieved NULL"); + } +#endif /* DASD_PARANOIA */ + ccwarea_enq (index, blk); + ccwarea_enq (index, blk + (1 << index)); + } +#if DASD_PARANOIA > 2 + if (!ccwarea[index]) { + INTERNAL_ERROR ("ccwarea is NULL\n%s", ""); + } +#endif /* DASD_PARANOIA */ + + freeblk = ccwarea_deq (index); +#if DASD_PARANOIA > 1 + if (!freeblk) { + INTERNAL_ERROR ("freeblk is NULL\n%s", ""); + } +#endif /* DASD_PARANOIA */ + exit: + FUNCTION_EXIT ("request_cpa"); + return freeblk; +} + +ccw1_t * +request_cp (int size) +{ + ccw1_t *freeblk; + int index; + int blksize; + /* Determine the index of ccwarea to look at */ + for (index = 0, blksize = 1; + size > blksize; + index++, blksize = blksize << 1) { + } + if (index > MAX_CP_POWER) { + INTERNAL_ERROR ("index too large %d\n", index); + } + spin_lock (&ccw_lock); + freeblk = request_cpa (index); + spin_unlock (&ccw_lock); + if (freeblk == NULL) { + printk (KERN_WARNING PRINTK_HEADER + "No way to deliver free ccw space\n"); + } + return freeblk; +} + +void +release_cp (int size, ccw1_t * area) +{ + int index; + int blksize; + /* Determine the index of ccwarea to look at */ + for (index = 0, blksize = 1; + size > blksize; + index++, blksize = blksize << 1) { + } + if (index > MAX_CP_POWER) { + INTERNAL_ERROR ("index too large %d\n", index); + } else if (index > CP_PER_PAGE_POWER) { + free_pages ((unsigned long) area, + index - CP_PER_PAGE_POWER); + INTERNAL_CHECK ("large index used: %d\n", index); + } else { + spin_lock (&ccw_lock); + ccwarea_enq (index, area); + spin_unlock (&ccw_lock); + } + return; +} + +/* ---------------------------------------------------------- */ + +static cqr_t *cqrp = NULL; +static spinlock_t cqr_lock=SPIN_LOCK_UNLOCKED; + +void +cqf_enq (cqr_t * cqf) +{ + *(cqr_t **) cqf = cqrp; + cqrp = cqf; +} + +cqr_t * +cqf_deq (void) +{ + cqr_t *cqr = cqrp; + cqrp = *(cqr_t **) cqrp; + return cqr; +} + +cqr_t * +request_cq (void) +{ + cqr_t *cqr = NULL; + int i; + cqr_t *area; + + spin_lock (&cqr_lock); + while (cqrp == NULL) { + do { + area = (cqr_t *) get_free_page (GFP_ATOMIC); + if (area == NULL) { + printk (KERN_WARNING PRINTK_HEADER + "No memory for chanq area\n"); + } + } while ( ! area ); + memset(area,0,PAGE_SIZE); + if (dasd_page_count + 1 >= MAX_DASD_PAGES) { + PRINT_WARN ("Requesting too many pages..."); + } else { + dasd_page[dasd_page_count++] = + (long) area; + } + for (i = 0; i < 4096 / sizeof (cqr_t); i++) { + cqf_enq (area + i); + } + } + cqr = cqf_deq (); + spin_unlock (&cqr_lock); + return cqr; +} + +void +release_cq (cqr_t * cqr) +{ + spin_lock (&cqr_lock); + cqf_enq (cqr); + spin_unlock (&cqr_lock); + return; +} + +/* ----------------------------------------------------------- */ +cqr_t * +request_cqr (int cpsize, int datasize) +{ + cqr_t *cqr = NULL; + cqr = request_cq (); + if (cqr == NULL) { + printk (KERN_WARNING PRINTK_HEADER __FILE__ + "No memory for chanq request\n"); + goto exit; + } + memset (cqr, 0, sizeof (cqr_t)); + cqr -> magic = DASD_MAGIC; + if (cpsize) { + cqr->cpaddr = request_cp (cpsize); + if (cqr->cpaddr == NULL) { + printk (KERN_WARNING PRINTK_HEADER __FILE__ + "No memory for channel program\n"); + goto nocp; + } + cqr->cplength = cpsize; + } + if (datasize) { + do { + cqr->data = (char *) kmalloc (datasize, GFP_ATOMIC); + if (cqr->data == NULL) { + printk (KERN_WARNING PRINTK_HEADER __FILE__ + "No memory for cqr data area\n"); + } + } while (!cqr->data); + memset (cqr->data,0,datasize); + } + goto exit; + nocp: + release_cq (cqr); + cqr = NULL; + exit: + return cqr; +} + +int +release_cqr (cqr_t * cqr) +{ + int rc = 0; + if (cqr == NULL) { + rc = -ENOENT; + return rc; + } + if (cqr->data) { + kfree (cqr->data); + } + if (cqr->dstat) { + kfree (cqr->dstat); + } + if (cqr->cpaddr) { + release_cp (cqr->cplength, cqr->cpaddr); + } + cqr -> magic = dasd_MAGIC; + release_cq (cqr); + return rc; +} + +/* -------------------------------------------------------------- */ +void +dasd_chanq_enq (dasd_chanq_t * q, cqr_t * cqr) +{ + if (q->head != NULL) { + q->tail->next = cqr; + } else + q->head = cqr; + cqr->next = NULL; + q->tail = cqr; + q->queued_requests ++; + if (atomic_compare_and_swap(CQR_STATUS_FILLED, + CQR_STATUS_QUEUED, + &cqr->status)) { + PRINT_WARN ("q_cqr: %p status changed %d\n", + cqr,atomic_read(&cqr->status)); + atomic_set(&cqr->status,CQR_STATUS_QUEUED); + } +} + +int +dasd_chanq_deq (dasd_chanq_t * q, cqr_t * cqr) +{ + cqr_t *prev; + + if (cqr == NULL) + return -ENOENT; + if (cqr == (cqr_t *) q->head) { + q->head = cqr->next; + if (q->head == NULL) + q->tail = NULL; + } else { + prev = (cqr_t *) q->head; + while (prev && prev->next != cqr) + prev = prev->next; + if (prev == NULL) + return -ENOENT; + prev->next = cqr->next; + if (prev->next == NULL) + q->tail = prev; + } + cqr->next = NULL; + q->queued_requests --; + return release_cqr(cqr); +} + +/* -------------------------------------------------------------------------- */ +void +cql_enq_head (dasd_chanq_t * q) +{ + if (q == NULL) { + INTERNAL_ERROR ("NULL queue passed%s\n", ""); + return; + } + if (atomic_read(&q->flags) & DASD_CHANQ_ACTIVE) { + PRINT_WARN("Queue already active"); + return; + } + spin_lock(&cq_lock); + atomic_set_mask(DASD_CHANQ_ACTIVE,&q->flags); + q->next_q = cq_head; + cq_head = q; + spin_unlock(&cq_lock); +} + +void +cql_deq (dasd_chanq_t * q) +{ + dasd_chanq_t *c; + + if (cq_head == NULL) { + INTERNAL_ERROR ("Channel queue is empty%s\n", ""); + return; + } + if (q == NULL) { + INTERNAL_ERROR ("NULL queue passed%s\n", ""); + return; + } + spin_lock(&cq_lock); + if (! (atomic_read(&q->flags) & DASD_CHANQ_ACTIVE)) { + PRINT_WARN("Queue not active\n"); + } + else if (cq_head == q) { + cq_head = q->next_q; + } else { + c = cq_head; + while (c->next_q && c->next_q != q) + c = c->next_q; + if (c->next_q != q) + INTERNAL_ERROR ("Entry not in queue%s\n", ""); + else + c->next_q = q->next_q; + } + q->next_q = NULL; + atomic_clear_mask(DASD_CHANQ_ACTIVE,&q->flags); + spin_unlock(&cq_lock); +} diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/s390/block/dasd_ccwstuff.h linux/drivers/s390/block/dasd_ccwstuff.h --- v2.3.99-pre7/linux/drivers/s390/block/dasd_ccwstuff.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/s390/block/dasd_ccwstuff.h Fri May 12 11:41:44 2000 @@ -0,0 +1,9 @@ +extern atomic_t chanq_tasks; +extern dasd_chanq_t *cq_head; + +cqr_t *request_cqr (int, int); +int release_cqr (cqr_t *); +int dasd_chanq_enq (dasd_chanq_t *, cqr_t *); +int dasd_chanq_deq (dasd_chanq_t *, cqr_t *); +void cql_enq_head (dasd_chanq_t * q); +void cql_deq (dasd_chanq_t * q); diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/s390/block/dasd_eckd.c linux/drivers/s390/block/dasd_eckd.c --- v2.3.99-pre7/linux/drivers/s390/block/dasd_eckd.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/s390/block/dasd_eckd.c Fri May 12 11:41:44 2000 @@ -0,0 +1,973 @@ +/* + * File...........: linux/drivers/s390/block/dasd_eckd.c + * Author(s)......: Holger Smolinski + * Bugreports.to..: + * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 + */ + +#include +#include + +#ifdef MODULE +#include +#endif /* MODULE */ + +#include +#include +#include + +#include + +#include "dasd_types.h" +#include "dasd_ccwstuff.h" + + +#ifdef PRINTK_HEADER +#undef PRINTK_HEADER +#endif /* PRINTK_HEADER */ +#define PRINTK_HEADER "dasd(eckd):" + +#define ECKD_C0(i) (i->home_bytes) +#define ECKD_F(i) (i -> formula) +#define ECKD_F1(i) (ECKD_F(i)==0x01?(i->factors.f_0x01.f1):(i->factors.f_0x02.f1)) +#define ECKD_F2(i) (ECKD_F(i)==0x01?(i->factors.f_0x01.f2):(i->factors.f_0x02.f2)) +#define ECKD_F3(i) (ECKD_F(i)==0x01?(i->factors.f_0x01.f3):(i->factors.f_0x02.f3)) +#define ECKD_F4(i) (ECKD_F(i)==0x02?(i->factors.f_0x02.f4):0) +#define ECKD_F5(i) (ECKD_F(i)==0x02?(i->factors.f_0x02.f5):0) +#define ECKD_F6(i) (i -> factor6) +#define ECKD_F7(i) (i -> factor7) +#define ECKD_F8(i) (i -> factor8) + +#define DASD_ECKD_CCW_LOCATE_RECORD 0x47 + +#define DASD_ECKD_CCW_READ_HOME_ADDRESS 0x0a +#define DASD_ECKD_CCW_WRITE_HOME_ADDRESS 0x09 + +#define DASD_ECKD_CCW_READ_RECORD_ZERO 0x16 +#define DASD_ECKD_CCW_WRITE_RECORD_ZERO 0x15 + +#define DASD_ECKD_CCW_READ_COUNT 0x12 +#define DASD_ECKD_CCW_READ 0x06 +#define DASD_ECKD_CCW_READ_MT 0x86 +#define DASD_ECKD_CCW_WRITE 0x05 +#define DASD_ECKD_CCW_WRITE_MT 0x85 +#define DASD_ECKD_CCW_READ_CKD 0x1e +#define DASD_ECKD_CCW_READ_CKD_MT 0x9e +#define DASD_ECKD_CCW_WRITE_CKD 0x1d +#define DASD_ECKD_CCW_WRITE_CKD_MT 0x9d + +typedef +struct { + __u16 cyl; + __u16 head; +} __attribute__ ((packed)) + +ch_t; + +typedef +struct { + __u16 cyl; + __u16 head; + __u32 sector; +} __attribute__ ((packed)) + +chs_t; + +typedef +struct { + __u16 cyl; + __u16 head; + __u8 record; +} __attribute__ ((packed)) + +chr_t; + +typedef +struct { + __u16 cyl; + __u16 head; + __u32 sector; +} geom_t; + +typedef struct { + struct { + struct { + unsigned char identifier:2; + unsigned char token_id:1; + unsigned char sno_valid:1; + unsigned char subst_sno:1; + unsigned char recNED:1; + unsigned char emuNED:1; + unsigned char reserved:1; + } __attribute__ ((packed)) flags; + __u8 descriptor; + __u8 dev_class; + __u8 reserved; + unsigned char dev_type[6]; + unsigned char dev_model[3]; + unsigned char HDA_manufacturer[3]; + unsigned char HDA_location[2]; + unsigned char HDA_seqno[12]; + __u16 ID; + } __attribute__ ((packed)) ned1; + struct { + struct { + unsigned char identifier:2; + unsigned char token_id:1; + unsigned char sno_valid:1; + unsigned char subst_sno:1; + unsigned char recNED:1; + unsigned char emuNED:1; + unsigned char reserved:1; + } __attribute__ ((packed)) flags; + __u8 descriptor; + __u8 reserved[2]; + unsigned char dev_type[6]; + unsigned char dev_model[3]; + unsigned char DASD_manufacturer[3]; + unsigned char DASD_location[2]; + unsigned char DASD_seqno[12]; + __u16 ID; + } __attribute__ ((packed)) ned2; + struct { + struct { + unsigned char identifier:2; + unsigned char token_id:1; + unsigned char sno_valid:1; + unsigned char subst_sno:1; + unsigned char recNED:1; + unsigned char emuNED:1; + unsigned char reserved:1; + } __attribute__ ((packed)) flags; + __u8 descriptor; + __u8 reserved[2]; + unsigned char cont_type[6]; + unsigned char cont_model[3]; + unsigned char cont_manufacturer[3]; + unsigned char cont_location[2]; + unsigned char cont_seqno[12]; + __u16 ID; + } __attribute__ ((packed)) ned3; + struct { + struct { + unsigned char identifier:2; + unsigned char token_id:1; + unsigned char sno_valid:1; + unsigned char subst_sno:1; + unsigned char recNED:1; + unsigned char emuNED:1; + unsigned char reserved:1; + } __attribute__ ((packed)) flags; + __u8 descriptor; + __u8 reserved[2]; + unsigned char cont_type[6]; + unsigned char empty[3]; + unsigned char cont_manufacturer[3]; + unsigned char cont_location[2]; + unsigned char cont_seqno[12]; + __u16 ID; + } __attribute__ ((packed)) ned4; + unsigned char ned5[32]; + unsigned char ned6[32]; + unsigned char ned7[32]; + struct { + struct { + unsigned char identifier:2; + unsigned char reserved:6; + } __attribute__ ((packed)) flags; + __u8 selector; + __u16 interfaceID; + __u32 reserved; + __u16 subsystemID; + struct { + unsigned char sp0:1; + unsigned char sp1:1; + unsigned char reserved:5; + unsigned char scluster:1; + } __attribute__ ((packed)) spathID; + __u8 unit_address; + __u8 dev_ID; + __u8 dev_address; + __u8 adapterID; + __u16 link_address; + struct { + unsigned char parallel:1; + unsigned char escon:1; + unsigned char reserved:1; + unsigned char ficon:1; + unsigned char reserved2:4; + } __attribute__ ((packed)) protocol_type; + struct { + unsigned char PID_in_236:1; + unsigned char reserved:7; + } __attribute__ ((packed)) format_flags; + __u8 log_dev_address; + unsigned char reserved2[12]; + } __attribute__ ((packed)) neq; + +} __attribute__ ((packed)) + +eckd_confdata_t; + +typedef +struct { + struct { + unsigned char perm:2; /* Permissions on this extent */ + unsigned char reserved:1; + unsigned char seek:2; /* Seek control */ + unsigned char auth:2; /* Access authorization */ + unsigned char pci:1; /* PCI Fetch mode */ + } __attribute__ ((packed)) mask; + struct { + unsigned char mode:2; /* Architecture mode */ + unsigned char ckd:1; /* CKD Conversion */ + unsigned char operation:3; /* Operation mode */ + unsigned char cfw:1; /* Cache fast write */ + unsigned char dfw:1; /* DASD fast write */ + } __attribute__ ((packed)) attributes; + __u16 short blk_size; /* Blocksize */ + __u16 fast_write_id; + __u8 unused; + __u8 reserved; + ch_t beg_ext; + ch_t end_ext; +} __attribute__ ((packed, aligned (32))) + +DE_eckd_data_t; + +typedef +struct { + struct { + unsigned char orientation:2; + unsigned char operation:6; + } __attribute__ ((packed)) operation; + struct { + unsigned char last_bytes_used:1; + unsigned char reserved:6; + unsigned char read_count_suffix:1; + } __attribute__ ((packed)) auxiliary; + __u8 unused; + __u8 count; + ch_t seek_addr; + chr_t search_arg; + __u8 sector; + __u16 length; +} __attribute__ ((packed, aligned (32))) + +LO_eckd_data_t; + +/* Stuff for handling home addresses */ +typedef struct { + __u8 skip_control[14]; + __u16 cell_number; + __u8 physical_addr[3]; + __u8 flag; + ch_t track_addr; + __u8 reserved; + __u8 key_length; + __u8 reserved2[2]; +} __attribute__ ((packed, aligned (32))) + +eckd_home_t; + + +static unsigned int +round_up_multiple (unsigned int no, unsigned int mult) +{ + int rem = no % mult; + return (rem ? no - rem + mult : no); +/* return (no % mult ? no - (no % mult) + mult : no); */ +} + +static unsigned int +ceil_quot (unsigned int d1, unsigned int d2) +{ + return (d1 + (d2 - 1)) / d2; +} + +static int +bytes_per_record (dasd_eckd_characteristics_t * rdc, + int kl, /* key length */ + int dl /* data length */ ) +{ + int bpr = 0; + switch (rdc->formula) { + case 0x01:{ + unsigned int fl1, fl2; + fl1 = round_up_multiple (ECKD_F2 (rdc) + dl, + ECKD_F1 (rdc)); + fl2 = round_up_multiple (kl ? ECKD_F2 (rdc) + kl : 0, + ECKD_F1 (rdc)); + bpr = fl1 + fl2; + break; + } + case 0x02:{ + unsigned int fl1, fl2, int1, int2; + int1 = ceil_quot (dl + ECKD_F6 (rdc), + ECKD_F5 (rdc) << 1); + int2 = ceil_quot (kl + ECKD_F6 (rdc), + ECKD_F5 (rdc) << 1); + fl1 = round_up_multiple (ECKD_F1 (rdc) * + ECKD_F2 (rdc) + + (dl + ECKD_F6 (rdc) + + ECKD_F4 (rdc) * int1), + ECKD_F1 (rdc)); + fl2 = round_up_multiple (ECKD_F1 (rdc) * + ECKD_F3 (rdc) + + (kl + ECKD_F6 (rdc) + + ECKD_F4 (rdc) * int2), + ECKD_F1 (rdc)); + bpr = fl1 + fl2; + break; + } + default: + INTERNAL_ERROR ("unknown formula%d\n", rdc->formula); + } + return bpr; +} + +static inline unsigned int +bytes_per_track (dasd_eckd_characteristics_t * rdc) +{ + return *(unsigned int *) (rdc->byte_per_track) >> 8; +} + +static unsigned int +recs_per_track (dasd_eckd_characteristics_t * rdc, + unsigned int kl, unsigned int dl) +{ + int rpt = 0; + int dn; + switch ( rdc -> dev_type ) { + case 0x3380: + if (kl) + return 1499 / (15 + + 7 + ceil_quot (kl + 12, 32) + + ceil_quot (dl + 12, 32)); + else + return 1499 / (15 + ceil_quot (dl + 12, 32)); + case 0x3390: + dn = ceil_quot (dl + 6, 232) + 1; + if (kl) { + int kn = ceil_quot (kl + 6, 232) + 1; + return 1729 / (10 + + 9 + ceil_quot (kl + 6 * kn, 34) + + 9 + ceil_quot (dl + 6 * dn, 34)); + } else + return 1729 / (10 + + 9 + ceil_quot (dl + 6 * dn, 34)); + case 0x9345: + dn = ceil_quot (dl + 6, 232) + 1; + if (kl) { + int kn = ceil_quot (kl + 6, 232) + 1; + return 1420 / (18 + + 7 + ceil_quot (kl + 6 * kn, 34) + + ceil_quot (dl + 6 * dn, 34)); + } else + return 1420 / (18 + + 7 + ceil_quot (dl + 6 * dn, 34)); + } + return rpt; +} + +static +void +define_extent (ccw1_t * de_ccw, + DE_eckd_data_t * data, + int trk, + int totrk, + int cmd, + dasd_information_t * info) +{ + ch_t geo, beg, end; + + geo.cyl = info->rdc_data->eckd.no_cyl; + geo.head = info->rdc_data->eckd.trk_per_cyl; + beg.cyl = trk / geo.head; + beg.head = trk % geo.head; + end.cyl = totrk / geo.head; + end.head = totrk % geo.head; + + memset (de_ccw, 0, sizeof (ccw1_t)); + de_ccw->cmd_code = CCW_DEFINE_EXTENT; + de_ccw->count = 16; + de_ccw->cda = (void *) virt_to_phys (data); + + memset (data, 0, sizeof (DE_eckd_data_t)); + switch (cmd) { + case DASD_ECKD_CCW_READ_HOME_ADDRESS: + case DASD_ECKD_CCW_READ_RECORD_ZERO: + case DASD_ECKD_CCW_READ: + case DASD_ECKD_CCW_READ_MT: + case DASD_ECKD_CCW_READ_CKD: /* Fallthrough */ + case DASD_ECKD_CCW_READ_CKD_MT: + case DASD_ECKD_CCW_READ_COUNT: + data->mask.perm = 0x1; + data->attributes.operation = 0x3; /* enable seq. caching */ + break; + case DASD_ECKD_CCW_WRITE: + case DASD_ECKD_CCW_WRITE_MT: + data->attributes.operation = 0x3; /* enable seq. caching */ + break; + case DASD_ECKD_CCW_WRITE_CKD: + case DASD_ECKD_CCW_WRITE_CKD_MT: + data->attributes.operation = 0x1; /* format through cache */ + break; + case DASD_ECKD_CCW_WRITE_HOME_ADDRESS: + case DASD_ECKD_CCW_WRITE_RECORD_ZERO: + data->mask.perm = 0x3; + data->mask.auth = 0x1; + data->attributes.operation = 0x1; /* format through cache */ + break; + default: + INTERNAL_ERROR ("unknown opcode 0x%x\n", cmd); + break; + } + data->attributes.mode = 0x3; + data->beg_ext.cyl = beg.cyl; + data->beg_ext.head = beg.head; + data->end_ext.cyl = end.cyl; + data->end_ext.head = end.head; +} + +static inline void +locate_record (ccw1_t * lo_ccw, + LO_eckd_data_t * data, + int trk, + int rec_on_trk, + int no_rec, + int cmd, + dasd_information_t * info) +{ + ch_t geo = + {info->rdc_data->eckd.no_cyl, + info->rdc_data->eckd.trk_per_cyl}; + ch_t seek = + {trk / (geo.head), trk % (geo.head)}; + int reclen = info->sizes.bp_block; + memset (lo_ccw, 0, sizeof (ccw1_t)); + lo_ccw->cmd_code = DASD_ECKD_CCW_LOCATE_RECORD; + lo_ccw->count = 16; + lo_ccw->cda = (void *) virt_to_phys (data); + + memset (data, 0, sizeof (LO_eckd_data_t)); + switch (cmd) { + case DASD_ECKD_CCW_WRITE_HOME_ADDRESS: + data->operation.orientation = 0x3; + data->operation.operation = 0x03; + break; + case DASD_ECKD_CCW_READ_HOME_ADDRESS: + data->operation.orientation = 0x3; + data->operation.operation = 0x16; + break; + case DASD_ECKD_CCW_WRITE_RECORD_ZERO: + data->operation.orientation = 0x3; + data->operation.operation = 0x03; + data->count++; + break; + case DASD_ECKD_CCW_READ_RECORD_ZERO: + data->operation.orientation = 0x3; + data->operation.operation = 0x16; + data->count++; + break; + case DASD_ECKD_CCW_WRITE: + case DASD_ECKD_CCW_WRITE_MT: + data->auxiliary.last_bytes_used = 0x1; + data->length = reclen; + data->operation.operation = 0x01; + break; + case DASD_ECKD_CCW_WRITE_CKD: + case DASD_ECKD_CCW_WRITE_CKD_MT: + data->auxiliary.last_bytes_used = 0x1; + data->length = reclen; + data->operation.operation = 0x03; + break; + case DASD_ECKD_CCW_READ: + case DASD_ECKD_CCW_READ_MT: + data->auxiliary.last_bytes_used = 0x1; + data->length = reclen; + data->operation.operation = 0x06; + break; + case DASD_ECKD_CCW_READ_CKD: + case DASD_ECKD_CCW_READ_CKD_MT: + data->auxiliary.last_bytes_used = 0x1; + data->length = reclen; + data->operation.operation = 0x16; + break; + case DASD_ECKD_CCW_READ_COUNT: + data->operation.operation = 0x06; + break; + default: + INTERNAL_ERROR ("unknown opcode 0x%x\n", cmd); + } + memcpy (&(data->seek_addr), &seek, sizeof (ch_t)); + memcpy (&(data->search_arg), &seek, sizeof (ch_t)); + data->search_arg.record = rec_on_trk; + data->count += no_rec; +} + +void +dasd_eckd_print_error (devstat_t * stat) +{ + int sct, sl; + char *sense = stat->ii.sense.data; + PRINT_WARN ("IRQ on devno %x: with intparm:%x DS:0x%02x CS:0x%02x\n", + stat->devno, stat->intparm, stat->dstat, stat->cstat); + PRINT_WARN ("Failing CCW: %p\n", (ccw1_t *) stat->cpa); + for (sl = 0; sl < 4; sl++) { + PRINT_DEBUG ("Sense:"); + for (sct = 0; sct < 8; sct++) { + printk (" %2d:0x%02x", + 8 * sl + sct, sense[8 * sl + sct]); + } + printk ("\n"); + } + if (sense[27] & 0x80) { /* 32 Byte Sense Data */ + PRINT_INFO ("Sense Data is 32 Byte information\n"); + PRINT_INFO ("Format: %x Exception class %x\n", + sense[6] & 0x0f, sense[22] >> 4); + } else { /* 24 Byte Sense Data */ + PRINT_INFO ("Sense Data is 24 Byte information\n"); + PRINT_INFO ("FMT: %x MSG %x, %s MSGb to SYSOP\n", + sense[7] >> 4, sense[7] & 0x0f, + sense[1] & 0x10 ? "" : "no"); + } +} + +int +dasd_eckd_format_track (int di, int trk, int bs) +{ + int rc = 0; + int i; + int flags = 0x00; /* FORMAT_R0 = 0x01, FORMAT_HA = 0x03 */ + dasd_information_t * info=dasd_info[di]; + cqr_t *fcp; + DE_eckd_data_t *DE_data; + LO_eckd_data_t *LO_data; + eckd_count_t *ct_data; + eckd_count_t *r0_data; + ccw1_t *last_ccw; + int retries = 5; + + int rpt = recs_per_track (&(info->rdc_data->eckd), 0, bs); + int cyl = trk / info->rdc_data->eckd.trk_per_cyl; + int head = trk % info->rdc_data->eckd.trk_per_cyl; + + fcp = request_cqr (2 + 1 + rpt, + sizeof (DE_eckd_data_t) + + sizeof (LO_eckd_data_t) + + (rpt + 1) * sizeof (eckd_count_t)); + fcp -> devindex=di; + DE_data = (DE_eckd_data_t *) fcp->data; + LO_data = (LO_eckd_data_t *) (((long) DE_data) + + sizeof (DE_eckd_data_t)); + r0_data = (eckd_count_t *) (((long) LO_data) + + sizeof (LO_eckd_data_t)); + ct_data = (eckd_count_t *) (((long) r0_data) + + sizeof (eckd_count_t)); + last_ccw = fcp->cpaddr; + switch (flags) { + case 0x03: + define_extent (last_ccw, DE_data, trk, trk, + DASD_ECKD_CCW_WRITE_HOME_ADDRESS, info); + last_ccw->flags = CCW_FLAG_CC; + last_ccw++; + locate_record (last_ccw, LO_data, trk, 0, rpt, + DASD_ECKD_CCW_WRITE_HOME_ADDRESS, info); + last_ccw->flags = CCW_FLAG_CC; + last_ccw++; + break; + case 0x01: + define_extent (last_ccw, DE_data, trk, trk, + DASD_ECKD_CCW_WRITE_RECORD_ZERO, info); + last_ccw->flags = CCW_FLAG_CC; + last_ccw++; + locate_record (last_ccw, LO_data, trk, 0, rpt, + DASD_ECKD_CCW_WRITE_RECORD_ZERO, info); + last_ccw->flags = CCW_FLAG_CC; + last_ccw++; + break; + case 0x00: + define_extent (last_ccw, DE_data, trk, trk, + DASD_ECKD_CCW_WRITE_CKD, info); + last_ccw->flags = CCW_FLAG_CC; + last_ccw++; + locate_record (last_ccw, LO_data, trk, 0, rpt, + DASD_ECKD_CCW_WRITE_CKD, info); + LO_data->length = bs; + last_ccw->flags = CCW_FLAG_CC; + last_ccw++; + break; + default: + PRINT_WARN ("Unknown format flags...%d\n", flags); + return -EINVAL; + } + if (flags & 0x02) { + PRINT_WARN ("Unsupported format flag...%d\n", flags); + return -EINVAL; + } + if (flags & 0x01) { /* write record zero */ + memset (r0_data, 0, sizeof (eckd_count_t)); + r0_data->cyl = cyl; + r0_data->head = head; + r0_data->record = 0; + r0_data->kl = 0; + r0_data->dl = 8; + last_ccw->cmd_code = 0x03; + last_ccw->count = 8; + last_ccw->flags = CCW_FLAG_CC | CCW_FLAG_SLI; + last_ccw->cda = (void *) virt_to_phys (r0_data); + last_ccw++; + } + /* write remaining records */ + for (i = 0; i < rpt; i++, last_ccw++) { + memset (ct_data + i, 0, sizeof (eckd_count_t)); + (ct_data + i)->cyl = cyl; + (ct_data + i)->head = head; + (ct_data + i)->record = i + 1; + (ct_data + i)->kl = 0; + (ct_data + i)->dl = bs; + last_ccw->cmd_code = DASD_ECKD_CCW_WRITE_CKD; + last_ccw->flags = CCW_FLAG_CC | CCW_FLAG_SLI; + last_ccw->count = 8; + last_ccw->cda = (void *) + virt_to_phys (ct_data + i); + } + (last_ccw - 1)->flags &= ~(CCW_FLAG_CC | CCW_FLAG_DC); + fcp -> devindex = di; + fcp -> flags = DASD_DO_IO_SLEEP; + do { + DECLARE_WAITQUEUE(wait, current); + unsigned long flags; + int irq; + int cs; + + irq = dasd_info[fcp->devindex]->info.irq; + s390irq_spin_lock_irqsave (irq, flags); + atomic_set(&fcp->status,CQR_STATUS_QUEUED); + rc = dasd_start_IO ( fcp ); + add_wait_queue (&dasd_waitq, &wait); + do { + current->state = TASK_UNINTERRUPTIBLE; + s390irq_spin_unlock_irqrestore (irq, flags); + schedule (); + s390irq_spin_lock_irqsave (irq, flags); + } while (((cs = atomic_read (&fcp->status)) != + CQR_STATUS_DONE) && + (cs != CQR_STATUS_ERROR)); + remove_wait_queue (&dasd_waitq, &wait); + s390irq_spin_unlock_irqrestore (irq, flags); + + retries --; + } while ( (rc || (atomic_read(&fcp->status) != CQR_STATUS_DONE)) && + retries); + if ((rc || (atomic_read(&fcp->status) != CQR_STATUS_DONE))) + rc = -EIO; + release_cqr (fcp); + return rc; +} + +int +dasd_eckd_ck_devinfo (dev_info_t * info) +{ + return 0; +} + +cqr_t * +dasd_eckd_build_req (int devindex, + struct request * req) +{ + cqr_t *rw_cp = NULL; + ccw1_t *ccw; + + DE_eckd_data_t *DE_data; + LO_eckd_data_t *LO_data; + struct buffer_head *bh; + int rw_cmd; + dasd_information_t *info = dasd_info[devindex]; + int blk_per_trk = recs_per_track (&(info->rdc_data->eckd), + 0, info->sizes.bp_block); + int byt_per_blk = info->sizes.bp_block; + int noblk = req-> nr_sectors >> info->sizes.s2b_shift; + int btrk = (req->sector >> info->sizes.s2b_shift) / blk_per_trk; + int etrk = ((req->sector + req->nr_sectors - 1) >> + info->sizes.s2b_shift) / blk_per_trk; + + if ( ! noblk ) { + PRINT_ERR("No blocks to write...returning\n"); + return NULL; + } + + if (req->cmd == READ) { + rw_cmd = DASD_ECKD_CCW_READ_MT; + } else +#if DASD_PARANOIA > 2 + if (req->cmd == WRITE) +#endif /* DASD_PARANOIA */ + { + rw_cmd = DASD_ECKD_CCW_WRITE_MT; + } +#if DASD_PARANOIA > 2 + else { + PRINT_ERR ("Unknown command %d\n", req->cmd); + return NULL; + } +#endif /* DASD_PARANOIA */ + /* Build the request */ + rw_cp = request_cqr (2 + noblk, + sizeof (DE_eckd_data_t) + + sizeof (LO_eckd_data_t)); + if ( ! rw_cp ) { + return NULL; + } + DE_data = rw_cp->data; + LO_data = rw_cp->data + sizeof (DE_eckd_data_t); + ccw = rw_cp->cpaddr; + + define_extent (ccw, DE_data, btrk, etrk, rw_cmd, info); + ccw->flags = CCW_FLAG_CC; + ccw++; + locate_record (ccw, LO_data, btrk, + (req->sector >> info->sizes.s2b_shift) % + blk_per_trk + 1, + req->nr_sectors >> info->sizes.s2b_shift, + rw_cmd, info); + ccw->flags = CCW_FLAG_CC; + for (bh = req->bh; bh; bh = bh->b_reqnext) { + long size; + for (size = 0; size < bh->b_size; size += byt_per_blk) { + ccw++; + ccw->flags = CCW_FLAG_CC; + ccw->cmd_code = rw_cmd; + ccw->count = byt_per_blk; + ccw->cda = (void *) virt_to_phys (bh->b_data + size); + } + } + ccw->flags &= ~(CCW_FLAG_DC | CCW_FLAG_CC); + return rw_cp; +} + +cqr_t * +dasd_eckd_rw_label (int devindex, int rw, char *buffer) +{ + int cmd_code = 0x03; + dasd_information_t *info = dasd_info[devindex]; + cqr_t *cqr; + ccw1_t *ccw; + + switch (rw) { + case READ: + cmd_code = DASD_ECKD_CCW_READ; + break; + case WRITE: + cmd_code = DASD_ECKD_CCW_WRITE; + break; +#if DASD_PARANOIA > 2 + default: + INTERNAL_ERROR ("unknown cmd %d", rw); + return NULL; +#endif /* DASD_PARANOIA */ + } + cqr = request_cqr (3, sizeof (DE_eckd_data_t) + + sizeof (LO_eckd_data_t)); + ccw = cqr->cpaddr; + define_extent (ccw, cqr->data, 0, 0, cmd_code, info); + ccw->flags |= CCW_FLAG_CC; + ccw++; + locate_record (ccw, cqr->data + 1, 0, 2, 1, cmd_code, info); + ccw->flags |= CCW_FLAG_CC; + ccw++; + ccw->cmd_code = cmd_code; + ccw->flags |= CCW_FLAG_SLI; + ccw->count = sizeof (dasd_volume_label_t); + ccw->cda = (void *) virt_to_phys ((void *) buffer); + return cqr; + +} + +void +dasd_eckd_print_char (dasd_characteristics_t * i) +{ + dasd_eckd_characteristics_t * c = + (dasd_eckd_characteristics_t *)i; + PRINT_INFO ("%x/%x (%x/%x) Cyl: %d Head: %d Sec: %d \n", + c->dev_type, c->dev_model, + c->cu_type, c->cu_model.model, + c->no_cyl, c->trk_per_cyl, + c->sec_per_trk); + PRINT_INFO ("Estimate: %d Byte/trk %d byte/kByte %d kByte/trk \n", + bytes_per_track (c), + bytes_per_record (c, 0, 1024), + recs_per_track (c, 0, 1024)); +}; + +int +dasd_eckd_ck_char (dasd_characteristics_t * i) +{ + int rc = 0; + dasd_eckd_print_char (i); + return rc; +} + +int +dasd_eckd_format (int devindex, format_data_t * fdata) +{ + int rc = 0; + int i; + dasd_information_t *info = dasd_info[devindex]; + format_data_t fd; + + if (!fdata) { + fd.start_unit = 0; + fd.stop_unit = info->rdc_data->eckd.no_cyl * + info->rdc_data->eckd.trk_per_cyl - 1; + fd.blksize = 4096; + } else { + memcpy (&fd, fdata, sizeof (format_data_t)); + if ( fd.stop_unit == -1 ) { + fd.stop_unit = info->rdc_data->eckd.no_cyl * + info->rdc_data->eckd.trk_per_cyl - 1; + } + if ( fd.blksize == 0 ) { + fd.blksize = 4096; + } + } + PRINT_INFO("Formatting device %d from %d to %d with bs %d\n", + devindex,fd.start_unit,fd.stop_unit,fd.blksize); + if ( fd.start_unit > fd.stop_unit ) { + PRINT_WARN ("start unit .gt. stop unit\n"); + return -EINVAL; + } + if ( (fd.start_unit > info->rdc_data->eckd.no_cyl * + info->rdc_data->eckd.trk_per_cyl - 1) ) { + PRINT_WARN ("start unit beyond end of disk\n"); + return -EINVAL; + } + if ( (fd.stop_unit > info->rdc_data->eckd.no_cyl * + info->rdc_data->eckd.trk_per_cyl - 1) ) { + PRINT_WARN ("stop unit beyond end of disk\n"); + return -EINVAL; + } + switch (fd.blksize) { + case 512: + case 1024: + case 2048: + case 4096: + break; + default: + PRINT_WARN ("invalid blocksize\n"); + return -EINVAL; + } + for (i = fd.start_unit; i <= fd.stop_unit; i++) { + /* print 20 messages per disk at all */ + if ( ! ( i % (info->rdc_data->eckd.trk_per_cyl * + (info->rdc_data->eckd.no_cyl / 20 ) ))) { + PRINT_INFO ("Format %d Cylinder: %d\n",devindex, + i/info->rdc_data->eckd.trk_per_cyl); + } + rc = dasd_eckd_format_track (devindex, i, fd.blksize); + if (rc) { + PRINT_WARN ("Formatting of Track %d failed...exiting\n", i); + break; + } + } + PRINT_INFO("Formated device %d from %d to %d with bs %d\n", + devindex,fd.start_unit,fd.stop_unit,fd.blksize); + return rc; +} + +cqr_t * +dasd_eckd_fill_sizes_first (int di) +{ + cqr_t *rw_cp = NULL; + ccw1_t *ccw; + DE_eckd_data_t *DE_data; + LO_eckd_data_t *LO_data; + dasd_information_t *info = dasd_info[di]; + eckd_count_t *count_data= &(info->private.eckd.count_data); + rw_cp = request_cqr (3, + sizeof (DE_eckd_data_t) + + sizeof (LO_eckd_data_t)); + DE_data = rw_cp->data; + LO_data = rw_cp->data + sizeof (DE_eckd_data_t); + ccw = rw_cp->cpaddr; + define_extent (ccw, DE_data, 0, 0, DASD_ECKD_CCW_READ_COUNT, info); + ccw->flags = CCW_FLAG_CC; + ccw++; + locate_record (ccw, LO_data, 0, 1, 1, DASD_ECKD_CCW_READ_COUNT, info); + ccw->flags = CCW_FLAG_CC; + ccw++; + ccw->cmd_code = DASD_ECKD_CCW_READ_COUNT; + ccw->count = 8; + ccw->cda = (void *) __pa (count_data); + rw_cp->devindex = di; + atomic_set(&rw_cp->status,CQR_STATUS_FILLED); + return rw_cp; +} + +int dasd_eckd_fill_sizes_last (int devindex) +{ + int sb; + dasd_information_t *in = dasd_info[devindex]; + int bs = in->private.eckd.count_data.dl; + if (bs <= 0) { + PRINT_INFO("Cannot figure out blocksize. did you format the disk?\n"); + memset (&(in -> sizes), 0, sizeof(dasd_sizes_t )); + return -EMEDIUMTYPE; + } else { + in->sizes.bp_block = bs; + } + in->sizes.bp_sector = in->sizes.bp_block; + + in->sizes.b2k_shift = 0; /* bits to shift a block to get 1k */ + for (sb = 1024; sb < bs; sb = sb << 1) + in->sizes.b2k_shift++; + + in->sizes.s2b_shift = 0; /* bits to shift 512 to get a block */ + for (sb = 512; sb < bs; sb = sb << 1) + in->sizes.s2b_shift++; + + in->sizes.blocks = in->rdc_data->eckd.no_cyl * + in->rdc_data->eckd.trk_per_cyl * + recs_per_track (&(in->rdc_data->eckd), 0, bs); + in->sizes.kbytes = in->sizes.blocks << in->sizes.b2k_shift; + + PRINT_INFO ("Verified: %d B/trk %d B/Blk(%d B) %d Blks/trk %d kB/trk \n", + bytes_per_track (&(in->rdc_data->eckd)), + bytes_per_record (&(in->rdc_data->eckd), 0, in->sizes.bp_block), + in->sizes.bp_block, + recs_per_track (&(in->rdc_data->eckd), 0, in->sizes.bp_block), + (recs_per_track (&(in->rdc_data->eckd), 0, in->sizes.bp_block) << + in->sizes.b2k_shift )); + return 0; +} + +dasd_operations_t dasd_eckd_operations = +{ + ck_devinfo: dasd_eckd_ck_devinfo, + get_req_ccw: dasd_eckd_build_req, + rw_label: dasd_eckd_rw_label, + ck_characteristics: dasd_eckd_ck_char, + fill_sizes_first: dasd_eckd_fill_sizes_first, + fill_sizes_last: dasd_eckd_fill_sizes_last, + dasd_format: dasd_eckd_format, +}; + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 4 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -4 + * c-argdecl-indent: 4 + * c-label-offset: -4 + * c-continued-statement-offset: 4 + * c-continued-brace-offset: 0 + * indent-tabs-mode: nil + * tab-width: 8 + * End: + */ diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/s390/block/dasd_erp.c linux/drivers/s390/block/dasd_erp.c --- v2.3.99-pre7/linux/drivers/s390/block/dasd_erp.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/s390/block/dasd_erp.c Fri May 12 11:41:44 2000 @@ -0,0 +1,21 @@ +/* + * File...........: linux/drivers/s390/block/dasd_erp.c + * Author(s)......: Holger Smolinski + * Bugreports.to..: + * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000 + */ + +#include +#include +#include "dasd_erp.h" +#include "dasd_types.h" + +dasd_era_t +dasd_erp_examine ( cqr_t * cqr) +{ + devstat_t *stat = cqr->dstat ; + if ( stat->cstat == 0x00 && + stat->dstat == (DEV_STAT_CHN_END|DEV_STAT_DEV_END ) ) + return dasd_era_none; + return dasd_era_fatal; +} diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/s390/block/dasd_erp.h linux/drivers/s390/block/dasd_erp.h --- v2.3.99-pre7/linux/drivers/s390/block/dasd_erp.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/s390/block/dasd_erp.h Fri May 12 11:41:44 2000 @@ -0,0 +1,15 @@ +/* + * File...........: linux/drivers/s390/block/dasd_erp.h + * Author(s)......: Holger Smolinski + * Bugreports.to..: + * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000 + */ + +#include "dasd_types.h" + +typedef enum { + dasd_era_fatal = -1, + dasd_era_none = 0 +} dasd_era_t; + +dasd_era_t dasd_erp_examine ( cqr_t * ); diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/s390/block/dasd_mdsk.c linux/drivers/s390/block/dasd_mdsk.c --- v2.3.99-pre7/linux/drivers/s390/block/dasd_mdsk.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/s390/block/dasd_mdsk.c Fri May 12 11:41:44 2000 @@ -0,0 +1,14 @@ +#include +#include "dasd_types.h" +#include "dasd_erp.h" + +dasd_operations_t dasd_mdsk_operations = +{ + NULL, + /* dasd_mdsk_ck_devinfo, + dasd_mdsk_build_req, + dasd_mdsk_rw_label, + dasd_mdsk_ck_char, + dasd_mdsk_fill_sizes, + dasd_mdsk_format, */ +}; diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/s390/block/dasd_proc.c linux/drivers/s390/block/dasd_proc.c --- v2.3.99-pre7/linux/drivers/s390/block/dasd_proc.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/s390/block/dasd_proc.c Fri May 12 11:41:44 2000 @@ -0,0 +1,116 @@ +/* + Structure of the proc filesystem: + /proc/dasd/ + /proc/dasd/devices # List of devices + /proc/dasd/ddabcd # Device node for devno abcd + /proc/dasd/ddabcd1 # Device node for partition abcd + /proc/dasd/abcd # Device information for devno abcd +*/ + +#include + +#include + +#include "dasd_types.h" + +int dasd_proc_read_devices ( char *, char **, off_t, int); +#ifdef DASD_PROFILE +extern int dasd_proc_read_statistics ( char *, char **, off_t, int); +extern int dasd_proc_read_debug ( char *, char **, off_t, int); +#endif /* DASD_PROFILE */ + +struct proc_dir_entry dasd_proc_root_entry = { + 0, + 4,"dasd", + S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR | S_IWGRP, + 1,0,0, + 0, + NULL, +}; + +struct proc_dir_entry dasd_proc_devices_entry = { + 0, + 7,"devices", + S_IFREG | S_IRUGO | S_IXUGO | S_IWUSR | S_IWGRP, + 1,0,0, + 0, + NULL, + &dasd_proc_read_devices, +}; + +#ifdef DASD_PROFILE +struct proc_dir_entry dasd_proc_stats_entry = { + 0, + 10,"statistics", + S_IFREG | S_IRUGO | S_IXUGO | S_IWUSR | S_IWGRP, + 1,0,0, + 0, + NULL, + &dasd_proc_read_statistics, +}; + +struct proc_dir_entry dasd_proc_debug_entry = { + 0, + 5,"debug", + S_IFREG | S_IRUGO | S_IXUGO | S_IWUSR | S_IWGRP, + 1,0,0, + 0, + NULL, + &dasd_proc_read_debug, +}; +#endif /* DASD_PROFILE */ + +struct proc_dir_entry dasd_proc_device_template = { + 0, + 6,"dd????", + S_IFBLK | S_IRUGO | S_IWUSR | S_IWGRP, + 1,0,0, + 0, + NULL, +}; + +void +dasd_proc_init ( void ) +{ + proc_register( & proc_root, & dasd_proc_root_entry); + proc_register( & dasd_proc_root_entry, & dasd_proc_devices_entry); +#ifdef DASD_PROFILE + proc_register( & dasd_proc_root_entry, & dasd_proc_stats_entry); + proc_register( & dasd_proc_root_entry, & dasd_proc_debug_entry); +#endif /* DASD_PROFILE */ +} + + +int +dasd_proc_read_devices ( char * buf, char **start, off_t off, int len) +{ + int i; + len = sprintf ( buf, "dev# MAJ minor node Format\n"); + for ( i = 0; i < DASD_MAX_DEVICES; i++ ) { + dasd_information_t *info = dasd_info[i]; + if ( ! info ) + continue; + if ( len >= PAGE_SIZE - 80 ) + len += sprintf ( buf + len, "terminated...\n"); + len += sprintf ( buf + len, + "%04X %3d %5d /dev/dasd%c", + dasd_info[i]->info.devno, + DASD_MAJOR, + i << PARTN_BITS, + 'a' + i ); + if (info->flags == DASD_INFO_FLAGS_NOT_FORMATTED) { + len += sprintf ( buf + len, " n/a"); + } else { + len += sprintf ( buf + len, " %6d", + info->sizes.bp_block); + } + len += sprintf ( buf + len, "\n"); + } + return len; +} + + +void +dasd_proc_add_node (int di) +{ +} diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/s390/block/dasd_profile.c linux/drivers/s390/block/dasd_profile.c --- v2.3.99-pre7/linux/drivers/s390/block/dasd_profile.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/s390/block/dasd_profile.c Fri May 12 11:41:44 2000 @@ -0,0 +1,208 @@ +#include + +#include + +#include "dasd_types.h" + +#define PRINTK_HEADER "dasd_profile:" + +static long dasd_io_reqs=0; /* number of requests processed at all */ +static long dasd_io_secs[16]; /* histogram of request's sizes */ +static long dasd_io_times[16]; /* histogram of requests's times */ +static long dasd_io_timps[16]; /* histogram of requests's times per sector */ +static long dasd_io_time1[16]; /* histogram of time from build to start */ +static long dasd_io_time2[16]; /* histogram of time from start to irq */ +static long dasd_io_time2ps[16]; /* histogram of time from start to irq */ +static long dasd_io_time3[16]; /* histogram of time from irq to end */ + +void +dasd_profile_add ( cqr_t *cqr ) +{ + int ind; + long strtime,irqtime,endtime,tottime; + long tottimeps,sectors; + long help; + if ( ! cqr -> req ) + return; + sectors = cqr -> req -> nr_sectors; + strtime = ((cqr->startclk - cqr->buildclk) >> 12); + irqtime = ((cqr->stopclk - cqr->startclk) >> 12); + endtime = ((cqr->endclk - cqr->stopclk) >> 12); + tottime = ((cqr->endclk - cqr->buildclk) >> 12); + tottimeps = tottime / sectors; + + if (! dasd_io_reqs ++){ + for ( ind = 0; ind < 16; ind ++) { + dasd_io_secs[ind] = 0; + dasd_io_times[ind]=0; + dasd_io_timps[ind]=0; + dasd_io_time1[ind]=0; + dasd_io_time2[ind]=0; + dasd_io_time2ps[ind]=0; + dasd_io_time3[ind]=0; + } + }; + + for ( ind = 0, help = sectors >> 3; + ind < 15 && help; + help = help >> 1,ind ++); + dasd_io_secs[ind] ++; + + for ( ind = 0, help = tottime >> 3; + ind < 15 && help; + help = help >> 1,ind ++); + dasd_io_times[ind] ++; + + for ( ind = 0, help = tottimeps >> 3; + ind < 15 && help; + help = help >> 1,ind ++); + dasd_io_timps[ind] ++; + + for ( ind = 0, help = strtime >> 3; + ind < 15 && help; + help = help >> 1,ind ++); + dasd_io_time1[ind] ++; + + for ( ind = 0, help = irqtime >> 3; + ind < 15 && help; + help = help >> 1,ind ++); + dasd_io_time2[ind] ++; + + for ( ind = 0, help = (irqtime/sectors) >> 3; + ind < 15 && help; + help = help >> 1,ind ++); + dasd_io_time2ps[ind] ++; + + for ( ind = 0, help = endtime >> 3; + ind < 15 && help; + help = help >> 1,ind ++); + dasd_io_time3[ind] ++; +} + +int +dasd_proc_read_statistics ( char * buf, char **start, + off_t off, int len, int d) +{ + int i; + int shift, help; + + for ( shift = 0, help = dasd_io_reqs; + help > 8192; + help = help >> 1,shift ++); + len = sprintf ( buf, "%ld dasd I/O requests\n", dasd_io_reqs); + len += sprintf ( buf+len, "__<4 ___8 __16 __32 __64 _128 _256 _512 __1k __2k __4k __8k _16k _32k _64k >64k\n"); + len += sprintf ( buf+len, "Histogram of sizes (512B secs)\n"); + for ( i = 0; i < 16; i ++) { + len += sprintf ( buf+len, "%4ld ",dasd_io_secs[i] >> shift ); + } + len += sprintf ( buf+len, "\n"); + len += sprintf ( buf+len, "Histogram of I/O times\n"); + for ( i = 0; i < 16; i ++) { + len += sprintf ( buf+len, "%4ld ",dasd_io_times[i] >> shift ); + } + len += sprintf ( buf+len, "\n"); + len += sprintf ( buf+len, "Histogram of I/O times per sector\n"); + for ( i = 0; i < 16; i ++) { + len += sprintf ( buf+len, "%4ld ",dasd_io_timps[i] >> shift ); + } + len += sprintf ( buf+len, "\n"); + len += sprintf ( buf+len, "Histogram of I/O time till ssch\n"); + for ( i = 0; i < 16; i ++) { + len += sprintf ( buf+len, "%4ld ",dasd_io_time1[i] >> shift ); + } + len += sprintf ( buf+len, "\n"); + len += sprintf ( buf+len, "Histogram of I/O time between ssch and irq\n"); + for ( i = 0; i < 16; i ++) { + len += sprintf ( buf+len, "%4ld ",dasd_io_time2[i] >> shift ); + } + len += sprintf ( buf+len, "\n"); + len += sprintf ( buf+len, "Histogram of I/O time between ssch and irq per sector\n"); + for ( i = 0; i < 16; i ++) { + len += sprintf ( buf+len, "%4ld ",dasd_io_time2ps[i] >> shift ); + } + len += sprintf ( buf+len, "\n"); + len += sprintf ( buf+len, "Histogram of I/O time between irq and end\n"); + for ( i = 0; i < 16; i ++) { + len += sprintf ( buf+len, "%4ld ",dasd_io_time3[i] >> shift ); + } + len += sprintf ( buf+len, "\n"); + return len; +} +typedef +struct { + union { + unsigned long long clock; + struct { + unsigned int ts1; + unsigned int ts2 : 20; + unsigned int unused : 8; + unsigned int cpu : 4; + } __attribute__ ((packed)) s; + } __attribute__ ((packed)) u; + unsigned long caller_address; + unsigned long tag; +} __attribute__ ((packed)) dasd_debug_entry; + +static dasd_debug_entry *dasd_debug_area = NULL; +static dasd_debug_entry *dasd_debug_actual; +static spinlock_t debug_lock = SPIN_LOCK_UNLOCKED; + +void +dasd_debug ( unsigned long tag ) +{ + long flags; + dasd_debug_entry *d; + /* initialize in first call ... */ + if ( ! dasd_debug_area ) { + dasd_debug_actual = dasd_debug_area = + (dasd_debug_entry *) get_free_page (GFP_ATOMIC); + if ( ! dasd_debug_area ) { + PRINT_WARN("No debug area allocated\n"); + return; + } + memset (dasd_debug_area,0,PAGE_SIZE); + } + /* renormalize to page */ + spin_lock_irqsave(&debug_lock,flags); + dasd_debug_actual = (dasd_debug_entry *) + ( (unsigned long) dasd_debug_area + + ( ( (unsigned long)dasd_debug_actual - + (unsigned long)dasd_debug_area ) % PAGE_SIZE ) ); + d = dasd_debug_actual ++; + spin_unlock_irqrestore(&debug_lock,flags); + /* write CPUID to lowest 12 bits of clock... */ + __asm__ __volatile__ ( "STCK %0" + :"=m" (d->u.clock)); + d->tag = tag; + d -> caller_address = (unsigned long) __builtin_return_address(0); + d->u.s.cpu = smp_processor_id(); +} + +int +dasd_proc_read_debug ( char * buf, char **start, + off_t off, int len, int dd) +{ + dasd_debug_entry *d; + char tag[9] = { 0, }; + long flags; + spin_lock_irqsave(&debug_lock,flags); + len = 0; + for( d = dasd_debug_area; + len < 4068 ; + d ++ ) { + if ( *(char*)(&d->tag) == 'D' ) { + memcpy(tag,&(d->tag),4); + tag[4]=0; + } + else { + sprintf(tag,"%08lx", d->tag); + tag[8]=0; + } + len += sprintf ( buf+len, + "%x %08x%05x %08lx (%8s)\n", + d->u.s.cpu, d->u.s.ts1, d->u.s.ts2, + d->caller_address,tag); + } + spin_unlock_irqrestore(&debug_lock,flags); + return len; +} diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/s390/block/dasd_types.h linux/drivers/s390/block/dasd_types.h --- v2.3.99-pre7/linux/drivers/s390/block/dasd_types.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/s390/block/dasd_types.h Fri May 12 11:41:44 2000 @@ -0,0 +1,284 @@ +/* + * File...........: linux/drivers/s390/block/dasd_types.h + * Author.........: Holger Smolinski + * Created........: 08/31/1999 + * Last Modified..: 09/29/1999 + * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 + + * List of Changes: + - Initial Release as of 09/29/1999 + + * Description + + * Restrictions + + * Known Bugs + + * Todo-List + + */ + +#ifndef DASD_TYPES_H +#define DASD_TYPES_H + +#include +#include +#include + +#include + +#define CCW_DEFINE_EXTENT 0x63 +#define CCW_LOCATE_RECORD 0x43 +#define CCW_READ_DEVICE_CHARACTERISTICS 0x64 + +typedef +enum { + dasd_none = -1, +#ifdef CONFIG_DASD_ECKD + dasd_eckd, +#endif /* CONFIG_DASD_ECKD */ +#ifdef CONFIG_DASD_MDSK + dasd_mdsk, +#endif /* CONFIG_DASD_MDSK */ +#ifdef CONFIG_DASD_CKD + dasd_ckd, +#endif /* CONFIG_DASD_CKD */ + dasd_end +} dasd_type_t; + +typedef +struct { + __u16 cu_type; + struct { + unsigned char support:2; + unsigned char async:1; + unsigned char reserved:1; + unsigned char cache_info:1; + unsigned char model:3; + } __attribute__ ((packed)) cu_model; + __u16 dev_type; + __u8 dev_model; + struct { + unsigned char mult_burst:1; + unsigned char RT_in_LR:1; + unsigned char reserved1:1; + unsigned char RD_IN_LR:1; + unsigned char reserved2:4; + unsigned char reserved3:8; + unsigned char defect_wr:1; + unsigned char reserved4:2; + unsigned char striping:1; + unsigned char reserved5:4; + unsigned char cfw:1; + unsigned char reserved6:2; + unsigned char cache:1; + unsigned char dual_copy:1; + unsigned char dfw:1; + unsigned char reset_alleg:1; + unsigned char sense_down:1; + } __attribute__ ((packed)) facilities; + __u8 dev_class; + __u8 unit_type; + __u16 no_cyl; + __u16 trk_per_cyl; + __u8 sec_per_trk; + __u8 byte_per_track[3]; + __u16 home_bytes; + __u8 formula; + union { + struct { + __u8 f1; + __u16 f2; + __u16 f3; + } __attribute__ ((packed)) f_0x01; + struct { + __u8 f1; + __u8 f2; + __u8 f3; + __u8 f4; + __u8 f5; + } __attribute__ ((packed)) f_0x02; + } __attribute__ ((packed)) factors; + __u16 first_alt_trk; + __u16 no_alt_trk; + __u16 first_dia_trk; + __u16 no_dia_trk; + __u16 first_sup_trk; + __u16 no_sup_trk; + __u8 MDR_ID; + __u8 OBR_ID; + __u8 director; + __u8 rd_trk_set; + __u16 max_rec_zero; + __u8 reserved1; + __u8 RWANY_in_LR; + __u8 factor6; + __u8 factor7; + __u8 factor8; + __u8 reserved2[3]; + __u8 reserved3[10]; +} __attribute__ ((packed, aligned (32))) + +dasd_eckd_characteristics_t; + +/* eckd count area */ +typedef struct { + __u16 cyl; + __u16 head; + __u8 record; + __u8 kl; + __u16 dl; +} __attribute__ ((packed)) + +eckd_count_t; + +#ifdef CONFIG_DASD_CKD +struct dasd_ckd_characteristics { + char info[64]; +}; + +#endif /* CONFIG_DASD_CKD */ + +#ifdef CONFIG_DASD_ECKD +struct dasd_eckd_characteristics { + char info[64]; +}; + +#endif /* CONFIG_DASD_ECKD */ + +typedef +union { + char __attribute__ ((aligned (32))) bytes[64]; +#ifdef CONFIG_DASD_CKD + struct dasd_ckd_characteristics ckd; +#endif /* CONFIG_DASD_CKD */ +#ifdef CONFIG_DASD_ECKD + dasd_eckd_characteristics_t eckd; +#endif /* CONFIG_DASD_ECKD */ +} __attribute__ ((aligned (32))) + +dasd_characteristics_t; + +#define CQR_STATUS_EMPTY 0x00 +#define CQR_STATUS_FILLED 0x01 +#define CQR_STATUS_QUEUED 0x02 +#define CQR_STATUS_IN_IO 0x04 +#define CQR_STATUS_DONE 0x08 +#define CQR_STATUS_RETRY 0x10 +#define CQR_STATUS_ERROR 0x20 +#define CQR_STATUS_FAILED 0x40 +#define CQR_STATUS_SLEEP 0x80 + +#define CQR_FLAGS_SLEEP 0x01 +#define CQR_FLAGS_WAIT 0x02 +#define CQR_FLAGS_NOLOCK 0x04 +#define CQR_FLAGS_NORETRY 0x08 + +typedef +struct cqr_t { + unsigned int magic; /* magic number should be "DASD" */ + atomic_t status; /* current status of request */ + unsigned short retries; /* counter for retry in error case */ + unsigned short cplength;/* Length of channel program (CP) */ + unsigned short devindex;/* device number */ + unsigned short flags; /* Flags for execution */ + + void * data; /* additional data area for CP */ + ccw1_t *cpaddr; /* Address of CP */ + struct request *req; /* backpointer to struct request */ + struct cqr_t *next; /* forward chain in chanq */ + struct cqr_t *int4cqr; /* which cqr ist the nect PCI for? */ + unsigned long long buildclk; + unsigned long long startclk; + unsigned long long stopclk; + unsigned long long endclk; + devstat_t *dstat; /* savearea for devstat */ + spinlock_t lock; + int options; +} __attribute__ ((packed)) +cqr_t; + +typedef +struct { + unsigned long int kbytes; + unsigned int bp_sector; + unsigned int bp_block; + unsigned int blocks; + unsigned int s2b_shift; + unsigned int b2k_shift; + unsigned int label_block; +} dasd_sizes_t; + +#define DASD_CHANQ_ACTIVE 0x01 +#define DASD_CHANQ_BUSY 0x02 +#define DASD_REQUEST_Q_BROKEN 0x04 + +typedef +struct dasd_chanq_t { + volatile cqr_t *head; + volatile cqr_t *tail; + spinlock_t q_lock; /* lock for queue operations */ + spinlock_t f_lock; /* lock for flag operations */ + int queued_requests; + atomic_t flags; + atomic_t dirty_requests; + struct dasd_chanq_t *next_q; /* pointer to next queue */ +} __attribute__ ((packed, aligned (16))) +dasd_chanq_t; + +#define DASD_INFO_FLAGS_INITIALIZED 0x01 +#define DASD_INFO_FLAGS_NOT_FORMATTED 0x02 +#define DASD_INFO_FLAGS_PARTNS_DETECTED 0x04 + +typedef +struct dasd_information_t { + devstat_t dev_status; + dasd_characteristics_t *rdc_data; + dasd_volume_label_t *label; + dasd_type_t type; + dev_info_t info; + dasd_sizes_t sizes; + dasd_chanq_t queue; + int open_count; + spinlock_t lock; + struct semaphore sem; + unsigned long flags; + int irq; + struct proc_dir_entry *proc_device; + devfs_handle_t devfs_entry; + union { + struct { + eckd_count_t count_data; + } eckd; + struct { + char dummy; + } fba; + struct { + char dummy; + } mdsk; + struct { + char dummy; + } ckd; + } private; +} dasd_information_t; + +typedef struct { + int start_unit; + int stop_unit; + int blksize; +} format_data_t; + +typedef +struct { + int (*ck_devinfo) (dev_info_t *); + cqr_t *(*get_req_ccw) (int, struct request *); + cqr_t *(*rw_label) (int, int, char *); + int (*ck_characteristics) (dasd_characteristics_t *); + cqr_t *(*fill_sizes_first) (int); + int (*fill_sizes_last) (int); + int (*dasd_format) (int, format_data_t *); +} dasd_operations_t; + +extern dasd_information_t *dasd_info[]; + +#endif /* DASD_TYPES_H */ diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/s390/block/mdisk.c linux/drivers/s390/block/mdisk.c --- v2.3.99-pre7/linux/drivers/s390/block/mdisk.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/s390/block/mdisk.c Fri May 12 11:41:44 2000 @@ -0,0 +1,790 @@ +/* + * drivers/s390/block/mdisk.c + * VM minidisk device driver. + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Hartmut Penner (hp@de.ibm.com) + */ + + +#ifndef __KERNEL__ +# define __KERNEL__ +#endif + +#define __NO_VERSION__ +#include +#include + +char kernel_version [] = UTS_RELEASE; + +#include +#include +#include /* printk() */ +#include /* kmalloc() */ +#include /* vmalloc() */ +#include /* everything... */ +#include /* error codes */ +#include +#include /* size_t */ +#include /* O_ACCMODE */ +#include /* HDIO_GETGEO */ +#include /* initfunc */ +#include +#include + +#include /* cli(), *_flags */ +#include /* access_ok */ +#include /* virt_to_phys */ + + /* Added statement HSM 12/03/99 */ +#include + +#define MAJOR_NR MDISK_MAJOR /* force definitions on in blk.h */ + +#include + + +#include "mdisk.h" /* local definitions */ + +/* + * structure for all device specific information + */ + +typedef struct mdisk_Dev { + u32 vdev; /* vdev of mindisk */ + u32 size; /* size in blocks */ + u32 status; /* status of last io operation */ + u32 nr_bhs; /* number of buffer of last io operation */ + u32 blksize; /* blksize from minidisk */ + u32 blkmult; /* multiplier between blksize and 512 HARDSECT */ + u32 blkshift; /* loe2 of multiplier above */ + /* + * each device has own iob and bio, + * it's possible to run io in parallel + * not used yet due to only one CURRENT per MAJOR + */ + + mdisk_rw_io_t* iob; /* each device has it own iob and bio */ + mdisk_bio_t* bio; + /* Added statement HSM 12/03/99 */ + devstat_t dev_status; /* Here we hold the I/O status */ + + int usage; /* usage counter */ + + struct tq_struct tqueue; /* per device task queue */ +} mdisk_Dev; + + +/* + * appended to global structures in mdisk_init; + */ + +static int mdisk_blksizes[MDISK_DEVS]; +static int mdisk_sizes[MDISK_DEVS] = { 0 }; +static int mdisk_hardsects[MDISK_DEVS]; +static int mdisk_maxsectors[MDISK_DEVS]; + +/* + * structure hold device specific information + */ + +static mdisk_Dev mdisk_devices[MDISK_DEVS]; +static mdisk_rw_io_t mdisk_iob[MDISK_DEVS] __attribute__ ((aligned(8))); +static mdisk_bio_t mdisk_bio[MDISK_DEVS][256]__attribute__ ((aligned(8))); + + +/* + * Parameter parsing + */ +struct { + long vdev[MDISK_DEVS]; + long size[MDISK_DEVS]; + long offset[MDISK_DEVS]; + long blksize[MDISK_DEVS]; +} mdisk_setup_data; + +/* + * Parameter parsing function, called from init/main.c + * vdev : virtual device number + * size : size in kbyte + * offset : offset after which minidisk is available + * blksize : blocksize minidisk is formated + * Format is: mdisk=:::,::... + * ::: can be shortened to : with offset=0,blksize=512 + */ +int __init mdisk_setup(char *str) +{ + char *cur = str; + int vdev, size, offset=0,blksize; + static int i = 0; + if (!i) + memset(&mdisk_setup_data,0,sizeof(mdisk_setup_data)); + + while (*cur != 0) { + blksize=MDISK_HARDSECT; + vdev = size = offset = 0; + if (!isxdigit(*cur)) goto syntax_error; + vdev = simple_strtoul(cur,&cur,16); + if (*cur != 0 && *cur != ',') { + if (*cur++ != ':') goto syntax_error; + if (!isxdigit(*cur)) goto syntax_error; + size = simple_strtoul(cur,&cur,16); + if (*cur == ':') { /* another colon -> offset specified */ + cur++; + if (!isxdigit(*cur)) goto syntax_error; + offset = simple_strtoul(cur,&cur,16); + if (*cur == ':') { /* another colon -> blksize */ + cur++; + if (!isxdigit(*cur)) goto syntax_error; + blksize = simple_strtoul(cur,&cur,16); + } + } + if (*cur != ',' && *cur != 0) goto syntax_error; + } + if (*cur == ',') cur++; + if (i >= MDISK_DEVS) { + printk(KERN_WARNING "mnd: too many devices\n"); + return 1; + } + mdisk_setup_data.vdev[i] = vdev; + mdisk_setup_data.size[i] = size; + mdisk_setup_data.offset[i] = offset; + mdisk_setup_data.blksize[i] = blksize; + + i++; + } + + return 1; + +syntax_error: + printk(KERN_WARNING "mnd: syntax error in parameter string: %s\n", str); + return 0; +} + +__setup("mdisk=", mdisk_setup); + +/* + * Open and close + */ + +static int mdisk_open (struct inode *inode, struct file *filp) +{ + mdisk_Dev *dev; /* device information */ + int num = MINOR(inode->i_rdev); + + /* + * size 0 means device not installed + */ + if ((num >= MDISK_DEVS) || (mdisk_sizes[num] == 0)) + return -ENODEV; + MOD_INC_USE_COUNT; + dev = &mdisk_devices[num]; + dev->usage++; + return 0; /* success */ +} + +static int mdisk_release (struct inode *inode, struct file *filp) +{ + mdisk_Dev *dev = &mdisk_devices[MINOR(inode->i_rdev)]; + + /* + * flush device + */ + + fsync_dev(inode->i_rdev); + dev->usage--; + MOD_DEC_USE_COUNT; + return 0; +} + + +/* + * The mdisk() implementation + */ + +static int mdisk_ioctl (struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + int err,rc, size=0; + struct hd_geometry *geo = (struct hd_geometry *)arg; + mdisk_Dev *dev = mdisk_devices + MINOR(inode->i_rdev); + + switch(cmd) { + + case BLKGETSIZE: + rc = copy_to_user ((long *) arg, &dev->size, sizeof (long)); + printk(KERN_WARNING "mnd: ioctl BLKGETSIZE %d\n",dev->size); + return rc; + case BLKFLSBUF: /* flush */ + if (!suser()) return -EACCES; /* only root */ + fsync_dev(inode->i_rdev); + invalidate_buffers(inode->i_rdev); + return 0; + + case BLKRAGET: /* return the readahead value */ + if (!arg) return -EINVAL; + err = access_ok(VERIFY_WRITE, (long *) arg, sizeof(long)); + if (err) return err; + put_user(read_ahead[MAJOR(inode->i_rdev)],(long *) arg); + return 0; + + case BLKRASET: /* set the readahead value */ + if (!suser()) return -EACCES; + if (arg > 0xff) return -EINVAL; /* limit it */ + read_ahead[MAJOR(inode->i_rdev)] = arg; + return 0; + + case BLKRRPART: /* re-read partition table: can't do it */ + return -EINVAL; + + case HDIO_GETGEO: + /* + * get geometry of device -> linear + */ + size = dev->size; + if (geo==NULL) return -EINVAL; + err = access_ok(VERIFY_WRITE, geo, sizeof(*geo)); + if (err) return err; + put_user(1, &geo->cylinders); + put_user(1, &geo->heads); + put_user(size, &geo->sectors); + put_user(0, &geo->start); + return 0; + } + + return -EINVAL; /* unknown command */ +} + +/* + * The file operations + */ + +static struct block_device_operations mdisk_fops = { + ioctl: mdisk_ioctl, + open: mdisk_open, + release: mdisk_release, +}; + +/* + * The 'low level' IO function + */ + + +static __inline__ int +dia250(void* iob,int cmd) +{ + int rc; + + iob = (void*) virt_to_phys(iob); + + asm volatile (" lr 2,%1\n" + " lr 3,%2\n" + " .long 0x83230250\n" + " lr %0,3" + : "=d" (rc) + : "d" (iob) , "d" (cmd) + : "2", "3" ); + return rc; +} +/* + * Init of minidisk device + */ + +static __inline__ int +mdisk_init_io(mdisk_Dev *dev,int blocksize,int offset,int size) +{ + mdisk_init_io_t *iob = (mdisk_init_io_t*) dev->iob; + int rc; + + memset(iob,0,sizeof(mdisk_init_io_t)); + + iob->dev_nr = dev->vdev; + iob->block_size = blocksize; + iob->offset = offset; + iob->start_block= 0; + iob->end_block = size; + + rc = dia250(iob,INIT_BIO); + + /* + * clear for following io once + */ + + memset(iob,0,sizeof(mdisk_rw_io_t)); + + return rc; +} + +/* + * release of minidisk device + */ + +static __inline__ int +mdisk_term_io(mdisk_Dev *dev) +{ + mdisk_init_io_t *iob = (mdisk_init_io_t*) dev->iob; + + memset(iob,0,sizeof(mdisk_init_io_t)); + + iob->dev_nr = dev->vdev; + + return dia250(iob,TERM_BIO); +} + +/* + * setup and start of minidisk io request + */ + +static __inline__ int +mdisk_rw_io_clustered (mdisk_Dev *dev, + mdisk_bio_t* bio_array, + int length, + int req, + int sync) +{ + int rc; + mdisk_rw_io_t *iob = dev->iob; + + iob->dev_nr = dev->vdev; + iob->key = 0; + iob->flags = sync; + + iob->block_count = length; + iob->interrupt_params = req; + iob->bio_list = virt_to_phys(bio_array); + + rc = dia250(iob,RW_BIO); + return rc; +} + + + +/* + * The device characteristics function + */ + +static __inline__ int +dia210(void* devchar) +{ + int rc; + + devchar = (void*) virt_to_phys(devchar); + + asm volatile (" lr 2,%1\n" + " .long 0x83200210\n" + " ipm %0\n" + " srl %0,28" + : "=d" (rc) + : "d" (devchar) + : "2" ); + return rc; +} +/* + * read the label of a minidisk and extract its characteristics + */ + +static __inline__ int +mdisk_read_label (mdisk_Dev *dev, int i) +{ + static mdisk_dev_char_t devchar; + static long label[1024]; + int block, b; + int rc; + mdisk_bio_t *bio; + + devchar.dev_nr = dev -> vdev; + devchar.rdc_len = sizeof(mdisk_dev_char_t); + + if (dia210(&devchar) == 0) { + if (devchar.vdev_class == DEV_CLASS_FBA) { + block = 2; + } + else { + block = 3; + } + bio = dev->bio; + for (b=512;b<4097;b=b*2) { + rc = mdisk_init_io(dev, b, 0, 64); + if (rc > 4) { + continue; + } + memset(&bio[0], 0, sizeof(mdisk_bio_t)); + bio[0].type = MDISK_READ_REQ; + bio[0].block_number = block; + bio[0].buffer = virt_to_phys(&label); + dev->nr_bhs = 1; + if (mdisk_rw_io_clustered(dev, + &bio[0], + 1, + (unsigned long) dev, + MDISK_SYNC) + == 0 ) { + if (label[0] != 0xc3d4e2f1) { /* CMS1 */ + printk ( KERN_WARNING "mnd: %4lX " + "is not CMS format\n", + mdisk_setup_data.vdev[i]); + rc = mdisk_term_io(dev); + return 1; + } + if (label[13] == 0) { + printk ( KERN_WARNING "mnd: %4lX " + "is not reserved\n", + mdisk_setup_data.vdev[i]); + rc = mdisk_term_io(dev); + return 2; + } + mdisk_setup_data.size[i] = + (label[7] - 1 - label[13]) * + (label[3] >> 9) >> 1; + mdisk_setup_data.blksize[i] = label[3]; + mdisk_setup_data.offset[i] = label[13] + 1; + rc = mdisk_term_io(dev); + return rc; + } + rc = mdisk_term_io(dev); + } + printk ( KERN_WARNING "mnd: Cannot read label of %4lX " + "- is it formatted?\n", + mdisk_setup_data.vdev[i]); + return 3; + } + return 4; +} + + + + + +/* + * this handles a clustered request in success case + * all buffers are detach and marked uptodate to the kernel + * then CURRENT->bh is set to the last processed but not + * update buffer + */ + +static __inline__ void +mdisk_end_request(int nr_bhs) +{ + int i; + struct buffer_head *bh; + struct request *req; + + if (nr_bhs > 1) { + req = CURRENT; + bh = req->bh; + + for (i=0; i < nr_bhs-1; i++) { + req->bh = bh->b_reqnext; + bh->b_reqnext = NULL; + bh->b_end_io(bh,1); + bh = req->bh; + } + + /* + * set CURRENT to last processed, not marked buffer + */ + req->buffer = bh->b_data; + req->current_nr_sectors = bh->b_size >> 9; + CURRENT = req; + } + end_request(1); +} + + + +/* + * Block-driver specific functions + */ + +void mdisk_request(request_queue_t *queue) +{ + mdisk_Dev *dev; + mdisk_bio_t *bio; + struct buffer_head *bh; + unsigned int sector, nr, offset; + int rc,rw,i; + + i = 0; + while(CURRENT) { + INIT_REQUEST; + + /* Check if the minor number is in range */ + if (DEVICE_NR(CURRENT_DEV) > MDISK_DEVS) { + static int count = 0; + if (count++ < 5) /* print the message at most five times */ + printk(KERN_WARNING "mnd: request for minor %d out of range\n", + DEVICE_NR(CURRENT_DEV) ) ; + end_request(0); + continue; + } + + /* + * Pointer to device structure, from the static array + */ + dev = mdisk_devices + DEVICE_NR(CURRENT_DEV); + + /* + * check, if operation is past end of devices + */ + if (CURRENT->nr_sectors + CURRENT->sector > dev->size) { + static int count = 0; + if (count++ < 5) + printk(KERN_WARNING "mnd%c: request past end of device\n", + DEVICE_NR(CURRENT_DEV)); + end_request(0); + continue; + } + + /* + * do command (read or write) + */ + switch(CURRENT->cmd) { + case READ: + rw = MDISK_READ_REQ; + break; + case WRITE: + rw = MDISK_WRITE_REQ; + break; + default: + /* can't happen */ + end_request(0); + continue; + } + + /* + * put the clustered requests in mdisk_bio array + * nr_sectors is checked against max_sectors in make_request + * nr_sectors and sector are always blocks of 512 + * but bh_size depends on the filesystems size + */ + sector = CURRENT->sector>>dev->blkshift; + bh = CURRENT->bh; + bio = dev->bio; + dev->nr_bhs = 0; + + /* + * sector is translated to block in minidisk context + * + */ + offset = 0; + + + + for (nr = 0,i = 0; + nr < CURRENT->nr_sectors && bh; + nr+=dev->blkmult, sector++,i++) { + memset(&bio[i], 0, sizeof(mdisk_bio_t)); + bio[i].type = rw; + bio[i].block_number = sector; + bio[i].buffer = virt_to_phys(bh->b_data+offset); + offset += dev->blksize; + if (bh->b_size <= offset) { + offset = 0; + bh = bh->b_reqnext; + dev->nr_bhs++; + } + } + + if (( rc = mdisk_rw_io_clustered(dev, &bio[0], i, + (unsigned long) dev, +#ifdef CONFIG_MDISK_SYNC + MDISK_SYNC +#else + MDISK_ASYNC +#endif + )) > 8 ) { + printk(KERN_WARNING "mnd%c: %s request failed rc %d" + " sector %ld nr_sectors %ld \n", + DEVICE_NR(CURRENT_DEV), + rw == MDISK_READ_REQ ? "read" : "write", + rc, CURRENT->sector, CURRENT->nr_sectors); + end_request(0); + continue; + } + i = 0; + /* + * Synchron: looping to end of request (INIT_REQUEST has return) + * Asynchron: end_request done in bottom half + */ +#ifdef CONFIG_MDISK_SYNC + mdisk_end_request(dev->nr_bhs); +#else + if (rc == 0) + mdisk_end_request(dev->nr_bhs); + else + return; +#endif + } +} + + +/* + * mdisk interrupt handler called when read/write request finished + * queues and marks a bottom half. + * + */ +void do_mdisk_interrupt(void) +{ + u16 code; + mdisk_Dev *dev; + + code = S390_lowcore.cpu_addr; + + if ((code >> 8) != 0x03) { + printk("mnd: wrong sub-interruption code %d",code>>8); + return; + } + + /* + * pointer to devives structure given as external interruption + * parameter + */ + dev = (mdisk_Dev*) S390_lowcore.ext_params; + dev->status = code & 0x00ff; + + queue_task(&dev->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); +} + +/* + * the bottom half checks the status of request + * on success it calls end_request and calls mdisk_request + * if more transfer to do + */ + +static void +do_mdisk_bh(void *data) +{ + mdisk_Dev *dev = (mdisk_Dev*) data; + unsigned long flags; + + spin_lock_irqsave(&io_request_lock, flags); + /* + * check for status of asynchronous rw + */ + if (dev->status != 0x00) { + printk("mnd: status of async rw %d",dev->status); + end_request(0); + } else { + /* + * end request for clustered requests + */ + if (CURRENT) + mdisk_end_request(dev->nr_bhs); + } + + /* + * if more to do, call mdisk_request + */ + if (CURRENT) + mdisk_request(NULL); + spin_unlock_irqrestore(&io_request_lock, flags); +} + +void /* Added fuction HSM 12/03/99 */ +mdisk_handler (int cpu, void *ds, struct pt_regs *regs) +{ + printk (KERN_ERR "mnd: received I/O interrupt... shouldn't happen\n"); +} + +int __init mdisk_init(void) +{ + int rc,i; + mdisk_Dev *dev; + request_queue_t *q; + + /* + * register block device + */ + if (register_blkdev(MAJOR_NR,"mnd",&mdisk_fops) < 0) { + printk("mnd: unable to get major %d for mini disk\n" + ,MAJOR_NR); + return MAJOR_NR; + } + q = BLK_DEFAULT_QUEUE(MAJOR_NR); + blk_init_queue(q, mdisk_request); + blk_queue_headactive(BLK_DEFAULT_QUEUE(major), 0); + + /* + * setup sizes for available devices + */ + read_ahead[MAJOR_NR] = MDISK_RAHEAD; /* 8 sector (4kB) read-ahead */ + blk_size[MAJOR_NR] = mdisk_sizes; /* size of reserved mdisk */ + blksize_size[MAJOR_NR] = mdisk_blksizes; /* blksize of device */ + hardsect_size[MAJOR_NR] = mdisk_hardsects; + max_sectors[MAJOR_NR] = mdisk_maxsectors; + blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST); + + for (i=0;ibio=mdisk_bio[i]; + dev->iob=&mdisk_iob[i]; + dev->vdev = mdisk_setup_data.vdev[i]; + + if ( mdisk_setup_data.size[i] == 0 ) + rc = mdisk_read_label(dev, i); + dev->size = mdisk_setup_data.size[i] * 2; /* buffer 512 b */ + dev->blksize = mdisk_setup_data.blksize[i]; + dev->tqueue.routine = do_mdisk_bh; + dev->tqueue.data = dev; + dev->blkmult = dev->blksize/512; + dev->blkshift = + dev->blkmult==1?0: + dev->blkmult==2?1: + dev->blkmult==4?2: + dev->blkmult==8?3:-1; + + mdisk_sizes[i] = mdisk_setup_data.size[i]; + mdisk_blksizes[i] = mdisk_setup_data.blksize[i]; + mdisk_hardsects[i] = mdisk_setup_data.blksize[i]; + + /* + * max sectors for one clustered req + */ + mdisk_maxsectors[i] = MDISK_MAXSECTORS*dev->blkmult; + + rc = mdisk_init_io(dev, + mdisk_setup_data.blksize[i], + mdisk_setup_data.offset[i],/* offset in vdev*/ + dev->size>>dev->blkshift /* size in blocks */ + ); + if (rc > 4) { + printk("mnd%c: init failed (rc: %d)\n",'a'+i,rc); + mdisk_sizes[i] = 0; + continue; + } + + /* + * set vdev in device structure for further rw access + * vdev and size given by linload + */ + printk("mnd%c: register device at major %X with %d blocks %d blksize \n", + 'a' + i, MAJOR_NR, dev->size>>dev->blkshift,dev->blkmult*512); + } + + /* + * enable service-signal external interruptions, + * Control Register 0 bit 22 := 1 + * (besides PSW bit 7 must be set to 1 somewhere for external + * interruptions) + */ + ctl_set_bit(0, 9); + + return 0; +} diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/s390/block/mdisk.h linux/drivers/s390/block/mdisk.h --- v2.3.99-pre7/linux/drivers/s390/block/mdisk.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/s390/block/mdisk.h Fri May 12 11:41:44 2000 @@ -0,0 +1,94 @@ +/* + * drivers/s390/block/mdisk.h + * VM minidisk device driver. + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Hartmut Penner (hp@de.ibm.com) + */ + +#include +#include + +#define MDISK_DEVS 8 /* for disks */ +#define MDISK_RAHEAD 8 /* read ahead */ +#define MDISK_BLKSIZE 1024 /* 1k blocks */ +#define MDISK_HARDSECT 512 /* FIXME -- 512 byte blocks */ +#define MDISK_MAXSECTORS 256 /* max sectors for one request */ + + + +/* + * low level io defines for diagnose 250 + */ + +#define MDISK_WRITE_REQ 0x01 +#define MDISK_READ_REQ 0x02 + +#define MDISK_SYNC 0x00 +#define MDISK_ASYNC 0x02 +#define INIT_BIO 0x00 +#define RW_BIO 0x01 +#define TERM_BIO 0x02 + +/* + * This stucture is used for clustered request + * up to 256 different request can be handled with one invocation + */ + +typedef struct { + u8 type; + u8 status; + u16 spare1; + u32 block_number; + u32 alet; + u32 buffer; +} mdisk_bio_t; + +typedef struct { + u16 dev_nr; + u16 spare1[11]; + u32 block_size; + u32 offset; + u32 start_block; + u32 end_block; + u32 spare2[6]; +} mdisk_init_io_t; + +typedef struct { + u16 dev_nr; + u16 spare1[11]; + u8 key; + u8 flags; + u16 spare2; + u32 block_count; + u32 alet; + u32 bio_list; + u32 interrupt_params; + u32 spare3[5]; +} mdisk_rw_io_t; + +/* + * low level definitions for Diagnose 210 + */ + +#define DEV_CLASS_FBA 0x01 + +/* + * Data structures for Diagnose 210 + */ + +typedef struct { + u16 dev_nr; + u16 rdc_len; + u8 vdev_class; + u8 vdev_type; + u8 vdev_status; + u8 vdev_flags; + u8 rdev_class; + u8 rdev_type; + u8 rdev_model; + u8 rdev_features; +} mdisk_dev_char_t; + + diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/s390/char/Makefile linux/drivers/s390/char/Makefile --- v2.3.99-pre7/linux/drivers/s390/char/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/s390/char/Makefile Fri May 12 11:41:44 2000 @@ -0,0 +1,16 @@ +all: s390-char.o + +CFLAFS += +O_TARGET := s390-char.o +O_OBJS := +M_OBJS := + +ifeq ($(CONFIG_3215_CONSOLE),y) + O_OBJS += con3215.o +endif + +ifeq ($(CONFIG_HWC),y) + O_OBJS += hwc_con.o hwc_rw.o hwc_tty.o +endif + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/s390/char/con3215.c linux/drivers/s390/char/con3215.c --- v2.3.99-pre7/linux/drivers/s390/char/con3215.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/s390/char/con3215.c Fri May 12 11:41:44 2000 @@ -0,0 +1,1129 @@ +/* + * drivers/s390/char/con3215.c + * 3215 line mode terminal driver. + * + * S390 version + * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "../../../arch/s390/kernel/cpcmd.h" +#include + +#define NR_3215 1 +#define NR_3215_REQ (4*NR_3215) +#define RAW3215_BUFFER_SIZE 65536 /* output buffer size */ +#define RAW3215_INBUF_SIZE 256 /* input buffer size */ +#define RAW3215_MIN_SPACE 128 /* minimum free space for wakeup */ +#define RAW3215_MIN_WRITE 1024 /* min. length for immediate output */ +#define RAW3215_MAX_CCWLEN 3968 /* max. bytes to write with one ccw */ +#define RAW3215_NR_CCWS ((RAW3215_BUFFER_SIZE/RAW3215_MAX_CCWLEN)+2) +#define RAW3215_TIMEOUT HZ/10 /* time for delayed output */ + +#define RAW3215_FIXED 1 /* 3215 console device is not be freed */ +#define RAW3215_ACTIVE 2 /* set if the device is in use */ +#define RAW3215_WORKING 4 /* set if a request is being worked on */ +#define RAW3215_THROTTLED 8 /* set if reading is disabled */ +#define RAW3215_STOPPED 16 /* set if writing is disabled */ +#define RAW3215_CLOSING 32 /* set while in close process */ +#define RAW3215_TIMER_RUNS 64 /* set if the output delay timer is on */ +#define RAW3215_FLUSHING 128 /* set to flush buffer (no delay) */ +#define RAW3215_BH_PENDING 256 /* indication for bh scheduling */ + +struct _raw3215_info; /* forward declaration ... */ + +int raw3215_condevice = -1; /* preset console device */ + +/* + * Request types for a 3215 device + */ +typedef enum { + RAW3215_FREE, RAW3215_READ, RAW3215_WRITE +} raw3215_type; + +/* + * Request structure for a 3215 device + */ +typedef struct _raw3215_req { + raw3215_type type; /* type of the request */ + int start, end; /* start/end index into output buffer */ + int residual; /* residual count for read request */ + ccw1_t ccws[RAW3215_NR_CCWS]; /* space for the channel program */ + struct _raw3215_info *info; /* pointer to main structure */ + struct _raw3215_req *next; /* pointer to next request */ +} raw3215_req __attribute__ ((aligned(8))); + +typedef struct _raw3215_info { + int flags; /* state flags */ + int irq; /* interrupt number to do_IO */ + char *buffer; /* pointer to output buffer */ + char *inbuf; /* pointer to input buffer */ + int head; /* first free byte in output buffer */ + int count; /* number of bytes in output buffer */ + devstat_t devstat; /* device status structure for do_IO */ + struct tty_struct *tty; /* pointer to tty structure if present */ + struct tq_struct tqueue; /* task queue to bottom half */ + raw3215_req *queued_read; /* pointer to queued read requests */ + raw3215_req *queued_write; /* pointer to queued write requests */ + wait_queue_head_t empty_wait; /* wait queue for flushing */ + struct timer_list timer; /* timer for delayed output */ + char *message; /* pending message from raw3215_irq */ + int msg_dstat; /* dstat for pending message */ + int msg_cstat; /* cstat for pending message */ +} raw3215_info; + +static raw3215_info *raw3215[NR_3215]; /* array of 3215 devices structures */ +static raw3215_req *raw3215_freelist; /* list of free request structures */ +static spinlock_t raw3215_freelist_lock;/* spinlock to protect free list */ + +static struct tty_driver tty3215_driver; +static struct tty_struct *tty3215_table[NR_3215]; +static struct termios *tty3215_termios[NR_3215]; +static struct termios *tty3215_termios_locked[NR_3215]; +static int tty3215_refcount; + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +static int __init con3215_setup(char *str) +{ + int vdev; + + vdev = simple_strtoul(str,&str,16); + if (vdev >= 0 && vdev < 65536) + raw3215_condevice = vdev; + return 1; +} + +__setup("condev=", con3215_setup); + +/* + * Get a request structure from the free list + */ +extern inline raw3215_req *raw3215_alloc_req(void) { + raw3215_req *req; + unsigned long flags; + + spin_lock_irqsave(&raw3215_freelist_lock, flags); + req = raw3215_freelist; + raw3215_freelist = req->next; + spin_unlock_irqrestore(&raw3215_freelist_lock, flags); + return req; +} + +/* + * Put a request structure back to the free list + */ +extern inline void raw3215_free_req(raw3215_req *req) { + unsigned long flags; + + if (req->type == RAW3215_FREE) + return; /* don't free a free request */ + req->type = RAW3215_FREE; + spin_lock_irqsave(&raw3215_freelist_lock, flags); + req->next = raw3215_freelist; + raw3215_freelist = req; + spin_unlock_irqrestore(&raw3215_freelist_lock, flags); +} + +/* + * Get a write request structure. That is either a new or the last + * queued write request. The request structure is set up in + * raw3215_mk_write_ccw. + */ +static raw3215_req *raw3215_mk_write_req(raw3215_info *raw) +{ + raw3215_req *req; + + /* check if there is a queued write request */ + req = raw->queued_write; + if (req == NULL) { + /* no queued write request, use new req structure */ + req = raw3215_alloc_req(); + req->type = RAW3215_WRITE; + req->info = raw; + req->start = raw->head; + } else + raw->queued_write = NULL; + return req; +} + +/* + * Get a read request structure. If there is a queued read request + * it is used, but that shouldn't happen because a 3215 terminal + * won't accept a new read before the old one is completed. + */ +static raw3215_req *raw3215_mk_read_req(raw3215_info *raw) +{ + raw3215_req *req; + + /* there can only be ONE read request at a time */ + req = raw->queued_read; + if (req == NULL) { + /* no queued read request, use new req structure */ + req = raw3215_alloc_req(); + req->type = RAW3215_READ; + req->info = raw; + } else + raw->queued_read = NULL; + return req; +} + +/* + * Set up a write request with the information from the main structure. + * A ccw chain is created that writes everything in the output buffer + * to the 3215 device. + */ +static int raw3215_mk_write_ccw(raw3215_info *raw, raw3215_req *req) +{ + ccw1_t *ccw; + int len, count, ix; + + ccw = req->ccws; + req->end = (raw->head - 1) & (RAW3215_BUFFER_SIZE - 1); + len = ((req->end - req->start) & (RAW3215_BUFFER_SIZE - 1)) + 1; + ix = req->start; + while (len > 0) { + if (ccw > req->ccws) + ccw[-1].flags |= 0x40; /* use command chaining */ + ccw->cmd_code = 0x01; /* write, auto carrier return */ + ccw->flags = 0x20; /* ignore incorrect length ind. */ + ccw->cda = + (void *) virt_to_phys(raw->buffer + ix); + count = (len > RAW3215_MAX_CCWLEN) ? + RAW3215_MAX_CCWLEN : len; + if (ix + count > RAW3215_BUFFER_SIZE) + count = RAW3215_BUFFER_SIZE-ix; + ccw->count = count; + len -= count; + ix = (ix + count) & (RAW3215_BUFFER_SIZE - 1); + ccw++; + } + return len; +} + +/* + * Set up a read request that reads up to 160 byte from the 3215 device. + */ +static void raw3215_mk_read_ccw(raw3215_info *raw, raw3215_req *req) +{ + ccw1_t *ccw; + + ccw = req->ccws; + ccw->cmd_code = 0x0A; /* read inquiry */ + ccw->flags = 0x20; /* ignore incorrect length */ + ccw->count = 160; + ccw->cda = (void *) virt_to_phys(raw->inbuf); +} + +/* + * Start a read or a write request + */ +static void raw3215_start_io(raw3215_info *raw) +{ + raw3215_req *req; + int res; + + req = raw->queued_read; + if (req != NULL && + !(raw->flags & (RAW3215_WORKING | RAW3215_THROTTLED))) { + /* dequeue request */ + raw->queued_read = NULL; + res = do_IO(raw->irq, req->ccws, (__u32) req, 0, 0); + if (res != 0) { + /* do_IO failed, put request back to queue */ + raw->queued_read = req; + } else { + raw->flags |= RAW3215_WORKING; + } + } + req = raw->queued_write; + if (req != NULL && + !(raw->flags & (RAW3215_WORKING | RAW3215_STOPPED))) { + /* dequeue request */ + raw->queued_write = NULL; + res = do_IO(raw->irq, req->ccws, (__u32) req, 0, 0); + if (res != 0) { + /* do_IO failed, put request back to queue */ + raw->queued_write = req; + } else { + raw->flags |= RAW3215_WORKING; + } + } +} + +/* + * Function to start a delayed output after RAW3215_TIMEOUT seconds + */ +static void raw3215_timeout(unsigned long __data) +{ + raw3215_info *raw = (raw3215_info *) __data; + unsigned long flags; + + s390irq_spin_lock_irqsave(raw->irq, flags); + if (raw->flags & RAW3215_TIMER_RUNS) { + del_timer(&raw->timer); + raw->flags &= ~RAW3215_TIMER_RUNS; + raw3215_start_io(raw); + } + s390irq_spin_unlock_irqrestore(raw->irq, flags); +} + +/* + * Function to conditionally start an IO. A read is started immediatly, + * a write is only started immediatly if the flush flag is on or the + * amount of data is bigger than RAW3215_MIN_WRITE. If a write is not + * done immediatly a timer is started with a delay of RAW3215_TIMEOUT. + */ +extern inline void raw3215_try_io(raw3215_info *raw) +{ + if (!(raw->flags & RAW3215_ACTIVE)) + return; + if (raw->queued_read != NULL) + raw3215_start_io(raw); + else if (raw->queued_write != NULL) { + if (raw->count >= RAW3215_MIN_WRITE || + (raw->flags & RAW3215_FLUSHING)) { + /* execute write requests bigger than minimum size */ + raw3215_start_io(raw); + if (raw->flags & RAW3215_TIMER_RUNS) { + del_timer(&raw->timer); + raw->flags &= ~RAW3215_TIMER_RUNS; + } + } else if (!(raw->flags & RAW3215_TIMER_RUNS)) { + /* delay small writes */ + init_timer(&raw->timer); + raw->timer.expires = RAW3215_TIMEOUT + jiffies; + raw->timer.data = (unsigned long) raw; + raw->timer.function = raw3215_timeout; + add_timer(&raw->timer); + raw->flags |= RAW3215_TIMER_RUNS; + } + } +} + +/* + * The bottom half handler routine for 3215 devices. It tries to start + * the next IO and wakes up processes waiting on the tty. + */ +static void raw3215_softint(void *data) +{ + raw3215_info *raw; + struct tty_struct *tty; + unsigned long flags; + + raw = (raw3215_info *) data; + s390irq_spin_lock_irqsave(raw->irq, flags); + raw3215_try_io((raw3215_info *) data); + raw->flags &= ~RAW3215_BH_PENDING; + s390irq_spin_unlock_irqrestore(raw->irq, flags); + /* Check for pending message from raw3215_irq */ + if (raw->message != NULL) { + printk(raw->message, raw->irq, raw->msg_dstat, raw->msg_cstat); + raw->message = NULL; + } + tty = raw->tty; + if (tty != NULL && + RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE) { + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); + wake_up_interruptible(&tty->write_wait); + } +} + +/* + * Function to safely add raw3215_softint to tq_immediate. + * The s390irq spinlock must be held. + */ +static inline void raw3215_sched_bh(raw3215_info *raw) +{ + if (raw->flags & RAW3215_BH_PENDING) + return; /* already pending */ + raw->flags |= RAW3215_BH_PENDING; + raw->tqueue.routine = raw3215_softint; + raw->tqueue.data = raw; + queue_task(&raw->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); +} + +/* + * Find the raw3215_info structure associated with irq + */ +static inline raw3215_info *raw3215_find_info(int irq) { + raw3215_info *raw; + int i; + + for (i = 0; i < NR_3215; i++) { + raw = raw3215[i]; + if (raw != NULL && raw->irq == irq && + (raw->flags & RAW3215_ACTIVE)) + break; + } + return (i >= NR_3215) ? NULL : raw; +} + +/* + * Interrupt routine, called from Ingo's I/O layer + */ +static void raw3215_irq(int irq, void *int_parm, struct pt_regs *regs) +{ + raw3215_info *raw; + raw3215_req *req; + struct tty_struct *tty; + devstat_t *stat; + int cstat, dstat; + int count, slen; + + stat = (devstat_t *) int_parm; + req = (raw3215_req *) stat->intparm; + cstat = stat->cstat; + dstat = stat->dstat; + if (cstat != 0) { + raw = raw3215_find_info(irq); + if (raw != NULL) { + raw->message = KERN_WARNING + "Got nonzero channel status in raw3215_irq " + "(dev %i, dev sts 0x%2x, sch sts 0x%2x)"; + raw->msg_dstat = dstat; + raw->msg_cstat = cstat; + raw3215_sched_bh(raw); + } + } + if (dstat & 0x01) { /* we got a unit exception */ + dstat &= ~0x01; /* we can ignore it */ + } + switch (dstat) { + case 0x80: + if (cstat != 0) + break; + /* Attention interrupt, someone hit the enter key */ + if ((raw = raw3215_find_info(irq)) == NULL) + return; /* That shouldn't happen ... */ + /* Setup a read request */ + req = raw3215_mk_read_req(raw); + raw3215_mk_read_ccw(raw, req); + raw->queued_read = req; + if (MACHINE_IS_P390) + memset(raw->inbuf, 0, RAW3215_INBUF_SIZE); + raw3215_sched_bh(raw); + break; + case 0x08: + case 0x0C: + /* Channel end interrupt. */ + raw = req->info; + if (req->type == RAW3215_READ) { + /* store residual count, then wait for device end */ + req->residual = stat->rescnt; + } + if (dstat == 0x08) + break; + case 0x04: + /* Device end interrupt. */ + raw = req->info; + if (req->type == RAW3215_READ && raw->tty != NULL) { + tty = raw->tty; + count = 160 - req->residual; + if (MACHINE_IS_P390) { + slen = strnlen(raw->inbuf, RAW3215_INBUF_SIZE); + if (count > slen) + count = slen; + } else + if (count >= TTY_FLIPBUF_SIZE - tty->flip.count) + count = TTY_FLIPBUF_SIZE - tty->flip.count - 1; + EBCASC(raw->inbuf, count); + if (count == 2 && ( + /* hat is 0xb0 in codepage 037 (US etc.) and thus */ + /* converted to 0x5e in ascii ('^') */ + strncmp(raw->inbuf, "^c", 2) == 0 || + /* hat is 0xb0 in several other codepages (German,*/ + /* UK, ...) and thus converted to ascii octal 252 */ + strncmp(raw->inbuf, "\252c", 2) == 0) ) { + /* emulate a control C = break */ + tty->flip.count++; + *tty->flip.flag_buf_ptr++ = TTY_NORMAL; + *tty->flip.char_buf_ptr++ = INTR_CHAR(tty); + tty_flip_buffer_push(raw->tty); + } else if (count == 2 && ( + strncmp(raw->inbuf, "^d", 2) == 0 || + strncmp(raw->inbuf, "\252d", 2) == 0) ) { + /* emulate a control D = end of file */ + tty->flip.count++; + *tty->flip.flag_buf_ptr++ = TTY_NORMAL; + *tty->flip.char_buf_ptr++ = EOF_CHAR(tty); + tty_flip_buffer_push(raw->tty); + } else if (count == 2 && ( + strncmp(raw->inbuf, "^z", 2) == 0 || + strncmp(raw->inbuf, "\252z", 2) == 0) ) { + /* emulate a control Z = suspend */ + tty->flip.count++; + *tty->flip.flag_buf_ptr++ = TTY_NORMAL; + *tty->flip.char_buf_ptr++ = SUSP_CHAR(tty); + tty_flip_buffer_push(raw->tty); + } else { + memcpy(tty->flip.char_buf_ptr, + raw->inbuf, count); + if (count < 2 || + (strncmp(raw->inbuf+count-2, "^n", 2) || + strncmp(raw->inbuf+count-2, "\252n", 2)) ) { /* don't add the auto \n */ + tty->flip.char_buf_ptr[count] = '\n'; + memset(tty->flip.flag_buf_ptr, + TTY_NORMAL, count + 1); + count++; + } else + count-=2; + tty->flip.char_buf_ptr += count; + tty->flip.flag_buf_ptr += count; + tty->flip.count += count; + tty_flip_buffer_push(raw->tty); + } + } else if (req->type == RAW3215_WRITE) { + raw->count -= ((req->end - req->start) & + (RAW3215_BUFFER_SIZE - 1)) + 1; + } + raw->flags &= ~RAW3215_WORKING; + raw3215_free_req(req); + /* check for empty wait */ + if (waitqueue_active(&raw->empty_wait) && + raw->queued_write == NULL && + raw->queued_read == NULL) { + wake_up_interruptible(&raw->empty_wait); + } + raw3215_sched_bh(raw); + break; + default: + /* Strange interrupt, I'll do my best to clean up */ + if ((raw = raw3215_find_info(irq)) == NULL) + return; /* That shouldn't happen ... */ + if (raw == NULL) break; + if (req != NULL && req->type != RAW3215_FREE) { + if (req->type == RAW3215_WRITE) + raw->count -= ((req->end - req->start) & + (RAW3215_BUFFER_SIZE-1))+1; + raw->flags &= ~RAW3215_WORKING; + raw3215_free_req(req); + } + raw->message = KERN_WARNING + "Spurious interrupt in in raw3215_irq " + "(dev %i, dev sts 0x%2x, sch sts 0x%2x)"; + raw->msg_dstat = dstat; + raw->msg_cstat = cstat; + raw3215_sched_bh(raw); + } + return; +} + +/* + * String write routine for 3215 devices + */ +static int +raw3215_write(raw3215_info *raw, const char *str, + int from_user, unsigned int length) +{ + raw3215_req *req; + unsigned long flags; + int ret, c; + int count; + + ret = 0; + while (length > 0) { + s390irq_spin_lock_irqsave(raw->irq, flags); + count = (length > RAW3215_BUFFER_SIZE) ? + RAW3215_BUFFER_SIZE : length; + length -= count; + + while (RAW3215_BUFFER_SIZE - raw->count < count) { + /* there might be a request pending */ + raw3215_try_io(raw); + if (wait_cons_dev(raw->irq) != 0) { + /* that shouldn't happen */ + raw->count = 0; + } + } + + req = raw3215_mk_write_req(raw); + /* copy string to output buffer and convert it to EBCDIC */ + if (from_user) { + while (1) { + c = MIN(count, + MIN(RAW3215_BUFFER_SIZE - raw->count, + RAW3215_BUFFER_SIZE - raw->head)); + if (c <= 0) + break; + c -= copy_from_user(raw->buffer + raw->head, + str, c); + if (c == 0) { + if (!ret) + ret = -EFAULT; + break; + } + ASCEBC(raw->buffer + raw->head, c); + raw->head = (raw->head + c) & + (RAW3215_BUFFER_SIZE - 1); + raw->count += c; + str += c; + count -= c; + ret += c; + } + } else { + while (1) { + c = MIN(count, + MIN(RAW3215_BUFFER_SIZE - raw->count, + RAW3215_BUFFER_SIZE - raw->head)); + if (c <= 0) + break; + memcpy(raw->buffer + raw->head, str, c); + ASCEBC(raw->buffer + raw->head, c); + raw->head = (raw->head + c) & + (RAW3215_BUFFER_SIZE - 1); + raw->count += c; + str += c; + count -= c; + ret += c; + } + } + raw3215_mk_write_ccw(raw, req); + raw->queued_write = req; + /* start or queue request */ + raw3215_try_io(raw); + s390irq_spin_unlock_irqrestore(raw->irq, flags); + + } + + return ret; +} + +/* + * Put character routine for 3215 devices + */ +static void raw3215_putchar(raw3215_info *raw, unsigned char ch) +{ + raw3215_req *req; + unsigned long flags; + + s390irq_spin_lock_irqsave(raw->irq, flags); + while (RAW3215_BUFFER_SIZE - raw->count < 1) { + /* there might be a request pending */ + raw3215_try_io(raw); + if (wait_cons_dev(raw->irq) != 0) { + /* that shouldn't happen */ + raw->count = 0; + } + } + + req = raw3215_mk_write_req(raw); + raw->buffer[raw->head] = (char) _ascebc[(int) ch]; + raw->head = (raw->head + 1) & (RAW3215_BUFFER_SIZE - 1); + raw->count++; + raw3215_mk_write_ccw(raw, req); + raw->queued_write = req; + /* start or queue request */ + raw3215_try_io(raw); + s390irq_spin_unlock_irqrestore(raw->irq, flags); +} + +/* + * Flush routine, it simply sets the flush flag and tries to start + * pending IO. + */ +static void raw3215_flush_buffer(raw3215_info *raw) +{ + unsigned long flags; + + s390irq_spin_lock_irqsave(raw->irq, flags); + if (raw->count > 0) { + raw->flags |= RAW3215_FLUSHING; + raw3215_try_io(raw); + raw->flags &= ~RAW3215_FLUSHING; + } + s390irq_spin_unlock_irqrestore(raw->irq, flags); +} + +/* + * Fire up a 3215 device. + */ +static int raw3215_startup(raw3215_info *raw) +{ + unsigned long flags; + + if (raw->flags & RAW3215_ACTIVE) + return 0; + if (request_irq(raw->irq, raw3215_irq, SA_INTERRUPT, + "3215 terminal driver", &raw->devstat) != 0) + return -1; + raw->flags |= RAW3215_ACTIVE; + s390irq_spin_lock_irqsave(raw->irq, flags); + raw3215_try_io(raw); + s390irq_spin_unlock_irqrestore(raw->irq, flags); + + return 0; +} + +/* + * Shutdown a 3215 device. + */ +static void raw3215_shutdown(raw3215_info *raw) +{ + DECLARE_WAITQUEUE(wait, current); + unsigned long flags; + + if (!(raw->flags & RAW3215_ACTIVE) || (raw->flags & RAW3215_FIXED)) + return; + /* Wait for outstanding requests, then free irq */ + s390irq_spin_lock_irqsave(raw->irq, flags); + if ((raw->flags & RAW3215_WORKING) || + raw->queued_write != NULL || + raw->queued_read != NULL) { + raw->flags |= RAW3215_CLOSING; + add_wait_queue(&raw->empty_wait, &wait); + current->state = TASK_INTERRUPTIBLE; + s390irq_spin_unlock_irqrestore(raw->irq, flags); + schedule(); + s390irq_spin_lock_irqsave(raw->irq, flags); + current->state = TASK_RUNNING; + raw->flags &= ~(RAW3215_ACTIVE | RAW3215_CLOSING); + } + free_irq(raw->irq, NULL); + s390irq_spin_unlock_irqrestore(raw->irq, flags); +} + +static int +raw3215_find_dev(int number) +{ + dev_info_t dinfo; + int irq; + int count; + + irq = get_irq_first(); + count = 0; + while (count <= number && irq != -ENODEV) { + if (get_dev_info(irq, &dinfo) == -ENODEV) + break; + if (dinfo.devno == raw3215_condevice || + dinfo.sid_data.cu_type == 0x3215) { + count++; + if (count > number) + return irq; + } + irq = get_irq_next(irq); + } + return -1; /* console not found */ +} + +#ifdef CONFIG_3215_CONSOLE + +/* + * Try to request the console IRQ. Called from init/main.c + */ +int con3215_activate(void) +{ + raw3215_info *raw; + + if (!MACHINE_IS_VM && !MACHINE_IS_P390) + return 0; + raw = raw3215[0]; /* 3215 console is the first one */ + if (raw->irq == -1) /* now console device found in con3215_init */ + return -1; + return raw3215_startup(raw); +} + +/* + * Write a string to the 3215 console + */ +static void +con3215_write(struct console *co, const char *str, unsigned int count) +{ + raw3215_info *raw; + + if (count <= 0) + return; + raw = raw3215[0]; /* console 3215 is the first one */ + raw3215_write(raw, str, 0, count); +} + +kdev_t con3215_device(struct console *c) +{ + return MKDEV(TTY_MAJOR, c->index); +} + +/* + * panic() calls console_unblank before the system enters a + * disabled, endless loop. + */ +void con3215_unblank(void) +{ + raw3215_info *raw; + unsigned long flags; + + raw = raw3215[0]; /* console 3215 is the first one */ + s390irq_spin_lock_irqsave(raw->irq, flags); + while (raw->count > 0) { + /* there might be a request pending */ + raw->flags |= RAW3215_FLUSHING; + raw3215_try_io(raw); + if (wait_cons_dev(raw->irq) != 0) { + /* that shouldn't happen */ + raw->count = 0; + } + raw->flags &= ~RAW3215_FLUSHING; + } + s390irq_spin_unlock_irqrestore(raw->irq, flags); +} + +static int __init con3215_consetup(struct console *co, char *options) +{ + return 0; +} + +/* + * The console structure for the 3215 console + */ +static struct console con3215 = { + "tty3215", + con3215_write, + NULL, + con3215_device, + NULL, + con3215_unblank, + con3215_consetup, + CON_PRINTBUFFER, + 0, + 0, + NULL +}; + +#endif + +/* + * tty3215_open + * + * This routine is called whenever a 3215 tty is opened. + */ +static int tty3215_open(struct tty_struct *tty, struct file * filp) +{ + raw3215_info *raw; + int retval, line; + + line = MINOR(tty->device) - tty->driver.minor_start; + if ((line < 0) || (line >= NR_3215)) + return -ENODEV; + + raw = raw3215[line]; + if (raw == NULL) { + raw = kmalloc(sizeof(raw3215_info) + + RAW3215_INBUF_SIZE, GFP_KERNEL); + if (raw == NULL) + return -ENOMEM; + raw->irq = raw3215_find_dev(line); + if (raw->irq == -1) { + kfree(raw); + return -ENODEV; + } + raw->inbuf = (char *) raw + sizeof(raw3215_info); + memset(raw, 0, sizeof(raw3215_info)); + raw->buffer = (char *) kmalloc(RAW3215_BUFFER_SIZE, GFP_KERNEL); + if (raw->buffer == NULL) { + kfree_s(raw, sizeof(raw3215_info)); + return -ENOMEM; + } + raw->tqueue.routine = raw3215_softint; + raw->tqueue.data = raw; + init_waitqueue_head(&raw->empty_wait); + raw3215[line] = raw; + } + + tty->driver_data = raw; + raw->tty = tty; + + tty->low_latency = 0; /* don't use bottom half for pushing chars */ + /* + * Start up 3215 device + */ + retval = raw3215_startup(raw); + if (retval) + return retval; + + return 0; +} + +/* + * tty3215_close() + * + * This routine is called when the 3215 tty is closed. We wait + * for the remaining request to be completed. Then we clean up. + */ +static void tty3215_close(struct tty_struct *tty, struct file * filp) +{ + raw3215_info *raw; + + raw = (raw3215_info *) tty->driver_data; + if (raw == NULL || tty->count > 1) + return; + tty->closing = 1; + /* Shutdown the terminal */ + raw3215_shutdown(raw); + tty->closing = 0; + raw->tty = NULL; +} + +/* + * Returns the amount of free space in the output buffer. + */ +static int tty3215_write_room(struct tty_struct *tty) +{ + raw3215_info *raw; + + raw = (raw3215_info *) tty->driver_data; + return RAW3215_BUFFER_SIZE - raw->count; +} + +/* + * String write routine for 3215 ttys + */ +static int tty3215_write(struct tty_struct * tty, int from_user, + const unsigned char *buf, int count) +{ + raw3215_info *raw; + int ret; + + if (!tty) + return 0; + raw = (raw3215_info *) tty->driver_data; + ret = raw3215_write(raw, buf, from_user, count); + return ret; +} + +/* + * Put character routine for 3215 ttys + */ +static void tty3215_put_char(struct tty_struct *tty, unsigned char ch) +{ + raw3215_info *raw; + + if (!tty) + return; + raw = (raw3215_info *) tty->driver_data; + raw3215_putchar(raw, ch); +} + +static void tty3215_flush_chars(struct tty_struct *tty) +{ +} + +/* + * Returns the number of characters in the output buffer + */ +static int tty3215_chars_in_buffer(struct tty_struct *tty) +{ + raw3215_info *raw; + + raw = (raw3215_info *) tty->driver_data; + return raw->count; +} + +static void tty3215_flush_buffer(struct tty_struct *tty) +{ + raw3215_info *raw; + + raw = (raw3215_info *) tty->driver_data; + raw3215_flush_buffer(raw); + wake_up_interruptible(&tty->write_wait); + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); +} + +/* + * Currently we don't have any io controls for 3215 ttys + */ +static int tty3215_ioctl(struct tty_struct *tty, struct file * file, + unsigned int cmd, unsigned long arg) +{ + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + + switch (cmd) { + default: + return -ENOIOCTLCMD; + } + return 0; +} + +/* + * Disable reading from a 3215 tty + */ +static void tty3215_throttle(struct tty_struct * tty) +{ + raw3215_info *raw; + + raw = (raw3215_info *) tty->driver_data; + raw->flags |= RAW3215_THROTTLED; +} + +/* + * Enable reading from a 3215 tty + */ +static void tty3215_unthrottle(struct tty_struct * tty) +{ + raw3215_info *raw; + unsigned long flags; + + raw = (raw3215_info *) tty->driver_data; + if (raw->flags & RAW3215_THROTTLED) { + s390irq_spin_lock_irqsave(raw->irq, flags); + raw->flags &= ~RAW3215_THROTTLED; + raw3215_try_io(raw); + s390irq_spin_unlock_irqrestore(raw->irq, flags); + } +} + +/* + * Disable writing to a 3215 tty + */ +static void tty3215_stop(struct tty_struct *tty) +{ + raw3215_info *raw; + + raw = (raw3215_info *) tty->driver_data; + raw->flags |= RAW3215_STOPPED; +} + +/* + * Enable writing to a 3215 tty + */ +static void tty3215_start(struct tty_struct *tty) +{ + raw3215_info *raw; + unsigned long flags; + + raw = (raw3215_info *) tty->driver_data; + if (raw->flags & RAW3215_STOPPED) { + s390irq_spin_lock_irqsave(raw->irq, flags); + raw->flags &= ~RAW3215_STOPPED; + raw3215_try_io(raw); + s390irq_spin_unlock_irqrestore(raw->irq, flags); + } +} + +/* + * 3215 console driver boottime initialization code. + * Register console. We can't request the IRQ here, because + * it's too early (kmalloc isn't working yet). We'll have to + * buffer all the console requests until we can request the + * irq. For this purpose we use some pages of fixed memory. + */ +void __init con3215_init(void) +{ + raw3215_info *raw; + raw3215_req *req; + int i; + + if (!MACHINE_IS_VM && !MACHINE_IS_P390) + return; + if (MACHINE_IS_VM) { + cpcmd("TERM CONMODE 3215", NULL, 0); + cpcmd("TERM AUTOCR OFF", NULL, 0); + } + + /* allocate 3215 request structures */ + raw3215_freelist = NULL; + spin_lock_init(&raw3215_freelist_lock); + for (i = 0; i < NR_3215_REQ; i++) { + req = (raw3215_req *) alloc_bootmem(sizeof(raw3215_req)); + req->next = raw3215_freelist; + raw3215_freelist = req; + } + +#ifdef CONFIG_3215_CONSOLE + raw3215[0] = raw = (raw3215_info *) + alloc_bootmem(sizeof(raw3215_info)); + memset(raw, 0, sizeof(raw3215_info)); + raw->buffer = (char *) alloc_bootmem(RAW3215_BUFFER_SIZE); + raw->inbuf = (char *) alloc_bootmem(RAW3215_INBUF_SIZE); + /* Find the first console */ + raw->irq = raw3215_find_dev(0); + raw->flags |= RAW3215_FIXED; + raw->tqueue.routine = raw3215_softint; + raw->tqueue.data = raw; + init_waitqueue_head(&raw->empty_wait); + + if (raw->irq != -1) { + register_console(&con3215); + s390irq_spin_lock(raw->irq); + set_cons_dev(raw->irq); + s390irq_spin_unlock(raw->irq); + } else { + free_bootmem((unsigned long) raw->inbuf, RAW3215_INBUF_SIZE); + free_bootmem((unsigned long) raw->buffer, RAW3215_BUFFER_SIZE); + free_bootmem((unsigned long) raw, sizeof(raw3215_info)); + raw3215[0] = NULL; + printk("Couldn't find a 3215 console device\n"); + } +#endif + + /* + * Initialize the tty_driver structure + * Entries in tty3215_driver that are NOT initialized: + * proc_entry, set_termios, flush_buffer, set_ldisc, write_proc + */ + + memset(&tty3215_driver, 0, sizeof(struct tty_driver)); + tty3215_driver.magic = TTY_DRIVER_MAGIC; + tty3215_driver.driver_name = "tty3215"; + tty3215_driver.name = "ttyS"; + tty3215_driver.name_base = 0; + tty3215_driver.major = TTY_MAJOR; + tty3215_driver.minor_start = 64; + tty3215_driver.num = NR_3215; + tty3215_driver.type = TTY_DRIVER_TYPE_SYSTEM; + tty3215_driver.subtype = SYSTEM_TYPE_TTY; + tty3215_driver.init_termios = tty_std_termios; + tty3215_driver.init_termios.c_iflag = IGNBRK | IGNPAR; + tty3215_driver.init_termios.c_oflag = ONLCR; + tty3215_driver.init_termios.c_lflag = ISIG; + tty3215_driver.flags = TTY_DRIVER_REAL_RAW; + tty3215_driver.refcount = &tty3215_refcount; + tty3215_driver.table = tty3215_table; + tty3215_driver.termios = tty3215_termios; + tty3215_driver.termios_locked = tty3215_termios_locked; + + tty3215_driver.open = tty3215_open; + tty3215_driver.close = tty3215_close; + tty3215_driver.write = tty3215_write; + tty3215_driver.put_char = tty3215_put_char; + tty3215_driver.flush_chars = tty3215_flush_chars; + tty3215_driver.write_room = tty3215_write_room; + tty3215_driver.chars_in_buffer = tty3215_chars_in_buffer; + tty3215_driver.flush_buffer = tty3215_flush_buffer; + tty3215_driver.ioctl = tty3215_ioctl; + tty3215_driver.throttle = tty3215_throttle; + tty3215_driver.unthrottle = tty3215_unthrottle; + tty3215_driver.send_xchar = NULL; + tty3215_driver.set_termios = NULL; + tty3215_driver.stop = tty3215_stop; + tty3215_driver.start = tty3215_start; + tty3215_driver.hangup = NULL; + tty3215_driver.break_ctl = NULL; + tty3215_driver.wait_until_sent = NULL; + tty3215_driver.read_proc = NULL; + + if (tty_register_driver(&tty3215_driver)) + panic("Couldn't register tty3215 driver\n"); + +} diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/s390/char/hwc.h linux/drivers/s390/char/hwc.h --- v2.3.99-pre7/linux/drivers/s390/char/hwc.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/s390/char/hwc.h Fri May 12 11:41:44 2000 @@ -0,0 +1,249 @@ +/* + * drivers/s390/char/hwc.h + * + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Peschke + * + * + * + */ + +#ifndef __HWC_H__ +#define __HWC_H__ + +#define ET_OpCmd 0x01 +#define ET_Msg 0x02 +#define ET_StateChange 0x08 +#define ET_PMsgCmd 0x09 +#define ET_CntlProgOpCmd 0x20 + +#define ET_OpCmd_Mask 0x80000000 +#define ET_Msg_Mask 0x40000000 +#define ET_StateChange_Mask 0x01000000 +#define ET_PMsgCmd_Mask 0x00800000 +#define ET_CtlProgOpCmd_Mask 0x00000001 + +#define GMF_DOM 0x8000 +#define GMF_SndAlrm 0x4000 +#define GMF_HoldMsg 0x2000 + +#define LTF_CntlText 0x8000 +#define LTF_LabelText 0x4000 +#define LTF_DataText 0x2000 +#define LTF_EndText 0x1000 +#define LTF_PromptText 0x0800 + +#define HWC_COMMAND_INITIATED 0 +#define HWC_BUSY 2 +#define HWC_NOT_OPERATIONAL 3 + +#define HWC_CMDW_READDATA 0x00770005 + +#define HWC_CMDW_WRITEDATA 0x00760005 + +#define HWC_CMDW_WRITEMASK 0x00780005 + +#define GDS_ID_MDSMU 0x1310 + +#define GDS_ID_MDSRouteInfo 0x1311 + +#define GDS_ID_AgUnWrkCorr 0x1549 + +#define GDS_ID_SNACondReport 0x1532 + +#define GDS_ID_CPMSU 0x1212 + +#define GDS_ID_RoutTargInstr 0x154D + +#define GDS_ID_OpReq 0x8070 + +#define GDS_ID_TextCmd 0x1320 + +#define GDS_KEY_SelfDefTextMsg 0x31 + +#define _HWCB_HEADER u16 length; \ + u8 function_code; \ + u8 control_mask[3]; \ + u16 response_code; + +#define _EBUF_HEADER u16 length; \ + u8 type; \ + u8 flags; \ + u16 _reserved; + +typedef struct { + _EBUF_HEADER +} __attribute__ ((packed)) + +evbuf_t; + +#define _MDB_HEADER u16 length; \ + u16 type; \ + u32 tag; \ + u32 revision_code; + +#define _GO_HEADER u16 length; \ + u16 type; \ + u32 domid; \ + u8 hhmmss_time[8]; \ + u8 th_time[3]; \ + u8 _reserved_0; \ + u8 dddyyyy_date[7]; \ + u8 _reserved_1; \ + u16 general_msg_flags; \ + u8 _reserved_2[10]; \ + u8 originating_system_name[8]; \ + u8 job_guest_name[8]; + +#define _MTO_HEADER u16 length; \ + u16 type; \ + u16 line_type_flags; \ + u8 alarm_control; \ + u8 _reserved[3]; + +typedef struct { + _GO_HEADER +} __attribute__ ((packed)) + +go_t; + +typedef struct { + go_t go; +} __attribute__ ((packed)) + +mdb_body_t; + +typedef struct { + _MDB_HEADER + mdb_body_t mdb_body; +} __attribute__ ((packed)) + +mdb_t; + +typedef struct { + _EBUF_HEADER + mdb_t mdb; +} __attribute__ ((packed)) + +msgbuf_t; + +typedef struct { + _HWCB_HEADER + msgbuf_t msgbuf; +} __attribute__ ((packed)) + +write_hwcb_t; + +typedef struct { + _MTO_HEADER +} __attribute__ ((packed)) + +mto_t; + +static write_hwcb_t write_hwcb_template = +{ + sizeof (write_hwcb_t), + 0x00, + { + 0x00, + 0x00, + 0x00 + }, + 0x0000, + { + sizeof (msgbuf_t), + ET_Msg, + 0x00, + 0x0000, + { + sizeof (mdb_t), + 0x0001, + 0xD4C4C240, + 0x00000001, + { + { + sizeof (go_t), + 0x0001 + + } + } + } + } +}; + +static mto_t mto_template = +{ + sizeof (mto_t), + 0x0004, + LTF_EndText, + 0x00 +}; + +typedef u32 _hwcb_mask_t; + +typedef struct { + _HWCB_HEADER + u16 _reserved; + u16 mask_length; + _hwcb_mask_t cp_receive_mask; + _hwcb_mask_t cp_send_mask; + _hwcb_mask_t hwc_receive_mask; + _hwcb_mask_t hwc_send_mask; +} __attribute__ ((packed)) + +init_hwcb_t; + +static init_hwcb_t init_hwcb_template = +{ + sizeof (init_hwcb_t), + 0x00, + { + 0x00, + 0x00, + 0x00 + }, + 0x0000, + 0x0000, + sizeof (_hwcb_mask_t), + ET_OpCmd_Mask | ET_PMsgCmd_Mask, + ET_Msg_Mask +}; + +#define _GDS_VECTOR_HEADER u16 length; \ + u16 gds_id; + +#define _GDS_SUBVECTOR_HEADER u8 length; \ + u8 key; + +typedef struct { + _GDS_VECTOR_HEADER +} __attribute__ ((packed)) + +gds_vector_t; + +typedef struct { + _GDS_SUBVECTOR_HEADER +} __attribute__ ((packed)) + +gds_subvector_t; + +typedef struct { + _HWCB_HEADER +} __attribute__ ((packed)) + +read_hwcb_t; + +static read_hwcb_t read_hwcb_template = +{ + PAGE_SIZE, + 0x00, + { + 0x00, + 0x00, + 0x80 + } +}; + +#endif /* __HWC_H__ */ diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/s390/char/hwc_con.c linux/drivers/s390/char/hwc_con.c --- v2.3.99-pre7/linux/drivers/s390/char/hwc_con.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/s390/char/hwc_con.c Fri May 12 11:41:44 2000 @@ -0,0 +1,99 @@ +/* + * drivers/s390/char/hwc_con.c + * HWC line mode console driver + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Peschke + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hwc_rw.h" + +extern void hwc_tty_init (void); + +#ifdef CONFIG_HWC_CONSOLE + +#define hwc_console_major 4 +#define hwc_console_minor 0 +#define hwc_console_name "console" + +void hwc_console_write (struct console *, const char *, unsigned int); +kdev_t hwc_console_device (struct console *); + +#define HWC_CON_PRINT_HEADER "hwc console driver: " + +struct console hwc_console = +{ + + hwc_console_name, + hwc_console_write, + NULL, + hwc_console_device, + NULL, + NULL, + NULL, + CON_PRINTBUFFER, + 0, + 0, + NULL +}; + +void +hwc_console_write ( + struct console *console, + const char *message, + unsigned int count) +{ + + if (console->device (console) != hwc_console.device (&hwc_console)) { + + hwc_printk (KERN_WARNING HWC_CON_PRINT_HEADER + "hwc_console_write() called with wrong " + "device number"); + return; + } + hwc_write (0, message, count); +} + +kdev_t +hwc_console_device (struct console * c) +{ + return MKDEV (hwc_console_major, hwc_console_minor); +} + +#endif + +void __init +hwc_console_init (void) +{ + +#ifdef CONFIG_3215 + if (MACHINE_IS_VM) + return; +#endif + if (MACHINE_IS_P390) + return; + + if (hwc_init () == 0) { + +#ifdef CONFIG_HWC_CONSOLE + + register_console (&hwc_console); +#endif + + hwc_tty_init (); + } else + panic (HWC_CON_PRINT_HEADER "hwc initialisation failed !"); + + return; +} diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/s390/char/hwc_rw.c linux/drivers/s390/char/hwc_rw.c --- v2.3.99-pre7/linux/drivers/s390/char/hwc_rw.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/s390/char/hwc_rw.c Fri May 12 11:41:44 2000 @@ -0,0 +1,2016 @@ +/* + * drivers/s390/char/hwc_rw.c + * driver: reading from and writing to system console on S/390 via HWC + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Peschke + * + * + * + * + * + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifndef MIN +#define MIN(a,b) ((amto_char_sum) + +#define _HWCB_MTO(hwcb) (_LIST(hwcb)->mto_number) + +#define _HWCB_CHAR_LOST(hwcb) (_LIST(hwcb)->mto_char_sum_lost) + +#define _HWCB_MTO_LOST(hwcb) (_LIST(hwcb)->mto_number_lost) + +#define _HWCB_TIMES_LOST(hwcb) (_LIST(hwcb)->times_lost) + +#define _HWCB_NEXT(hwcb) (_LIST(hwcb)->next) + +#define BUF_HWCB_CHAR _HWCB_CHAR(BUF_HWCB) + +#define BUF_HWCB_MTO _HWCB_MTO(BUF_HWCB) + +#define BUF_HWCB_NEXT _HWCB_NEXT(BUF_HWCB) + +#define OUT_HWCB_CHAR _HWCB_CHAR(OUT_HWCB) + +#define OUT_HWCB_MTO _HWCB_MTO(OUT_HWCB) + +#define OUT_HWCB_NEXT _HWCB_NEXT(OUT_HWCB) + +#define BUF_HWCB_CHAR_LOST _HWCB_CHAR_LOST(BUF_HWCB) + +#define BUF_HWCB_MTO_LOST _HWCB_MTO_LOST(BUF_HWCB) + +#define OUT_HWCB_CHAR_LOST _HWCB_CHAR_LOST(OUT_HWCB) + +#define OUT_HWCB_MTO_LOST _HWCB_MTO_LOST(OUT_HWCB) + +#define BUF_HWCB_TIMES_LOST _HWCB_TIMES_LOST(BUF_HWCB) + +#include "hwc.h" + +#define __HWC_RW_C__ +#include "hwc_rw.h" +#undef __HWC_RW_C__ + +static unsigned char _obuf[MAX_HWCB_ROOM]; + +static unsigned char + _page[PAGE_SIZE] __attribute__ ((aligned (PAGE_SIZE))); + +typedef u32 kmem_pages_t; + +#define MAX_KMEM_PAGES (sizeof(kmem_pages_t) << 3) + +#define HWC_TIMER_RUNS 1 +#define FLUSH_HWCBS 2 + +static struct { + + hwc_ioctls_t ioctls; + + hwc_ioctls_t init_ioctls; + + unsigned char *hwcb_list_head; + + unsigned char *hwcb_list_tail; + + unsigned short int mto_number; + + unsigned int mto_char_sum; + + unsigned char hwcb_count; + + unsigned long kmem_start; + + unsigned long kmem_end; + + kmem_pages_t kmem_pages; + + unsigned char *obuf; + + unsigned short int obuf_cursor; + + unsigned short int obuf_count; + + unsigned short int obuf_start; + + unsigned char *page; + + u32 current_servc; + + unsigned char *current_hwcb; + + unsigned char write_nonprio:1; + unsigned char write_prio:1; + unsigned char read_nonprio:1; + unsigned char read_prio:1; + + unsigned char flags; + + spinlock_t lock; + + struct timer_list write_timer; +} hwc_data = +{ + { + }, + { + 8, + 0, + 80, + CODE_ASCII, + 1, + 50, + MAX_KMEM_PAGES, + + 0, + + 0x6c + + }, + NULL, + NULL, + 0, + 0, + 0, + 0, + 0, + 0, + _obuf, + 0, + 0, + 0, + _page, + 0, + NULL, + 0, + 0, + 0, + 0, + 0 + +}; + +#define DELAYED_WRITE 0 +#define IMMEDIATE_WRITE 1 + +static signed int do_hwc_write (int from_user, unsigned char *, + unsigned int, + unsigned char, + unsigned char); + +static asmlinkage int +internal_print (char write_time, const char *fmt,...) +{ + va_list args; + int i; + unsigned char buf[512]; + + va_start (args, fmt); + i = vsprintf (buf, fmt, args); + va_end (args); + return do_hwc_write (0, buf, i, CODE_ASCII, write_time); +} + +int +hwc_printk (const char *fmt,...) +{ + va_list args; + int i; + unsigned char buf[512]; + unsigned long flags; + int retval; + + spin_lock_irqsave (&hwc_data.lock, flags); + + i = vsprintf (buf, fmt, args); + va_end (args); + retval = do_hwc_write (0, buf, i, CODE_ASCII, IMMEDIATE_WRITE); + + spin_unlock_irqrestore (&hwc_data.lock, flags); + + return retval; +} + +#ifdef DUMP_HWCB_INPUT + +static void +dump_storage_area (unsigned char *area, unsigned short int count) +{ + unsigned short int index; + ioctl_nl_t old_final_nl; + + if (!area || !count) + return; + + old_final_nl = hwc_data.ioctls.final_nl; + hwc_data.ioctls.final_nl = 1; + + internal_print (DELAYED_WRITE, "\n%8x ", area); + + for (index = 0; index < count; index++) { + + if (area[index] <= 0xF) + internal_print (DELAYED_WRITE, "0%x", area[index]); + else + internal_print (DELAYED_WRITE, "%x", area[index]); + + if ((index & 0xF) == 0xF) + internal_print (DELAYED_WRITE, "\n%8x ", + &area[index + 1]); + else if ((index & 3) == 3) + internal_print (DELAYED_WRITE, " "); + } + + internal_print (IMMEDIATE_WRITE, "\n"); + + hwc_data.ioctls.final_nl = old_final_nl; +} +#endif + +static inline u32 +service_call ( + u32 hwc_command_word, + unsigned char hwcb[]) +{ + unsigned int condition_code = 1; + + __asm__ __volatile__ ("L 1, 0(0,%0) \n\t" + "LRA 2, 0(0,%1) \n\t" + ".long 0xB2200012 \n\t" + : + :"a" (&hwc_command_word), "a" (hwcb) + :"1", "2", "memory"); + + __asm__ __volatile__ ("IPM %0 \n\t" + "SRL %0, 28 \n\t" + :"=r" (condition_code)); + + return condition_code; +} + +static inline unsigned char * +ext_int_param (void) +{ + u32 param; + + __asm__ __volatile__ ("L %0,128(0,0)\n\t" + :"=r" (param)); + + return ((unsigned char *) param); +} + +static int +prepare_write_hwcb (void) +{ + write_hwcb_t *hwcb; + + if (!BUF_HWCB) + return -ENOMEM; + + BUF_HWCB_MTO = 0; + BUF_HWCB_CHAR = 0; + + hwcb = (write_hwcb_t *) BUF_HWCB; + + memcpy (hwcb, &write_hwcb_template, sizeof (write_hwcb_t)); + + if (!hwc_data.write_nonprio && hwc_data.write_prio) + hwcb->msgbuf.type = ET_PMsgCmd; + + return 0; +} + +static int +sane_write_hwcb (void) +{ + unsigned short int lost_msg; + unsigned int lost_char; + unsigned char lost_hwcb; + unsigned char *bad_addr; + unsigned long page; + int page_nr; + + if (!OUT_HWCB) + return -ENOMEM; + + if ((unsigned long) OUT_HWCB & 0xFFF) { + + bad_addr = OUT_HWCB; + +#ifdef DUMP_HWC_WRITE_LIST_ERROR + __asm__ ("LHI 1,0xe30\n\t" + "LRA 2,0(0,%0) \n\t" + "J .+0 \n\t" + : + : "a" (bad_addr) + : "1", "2"); +#endif + + hwc_data.kmem_pages = 0; + if ((unsigned long) BUF_HWCB & 0xFFF) { + + lost_hwcb = hwc_data.hwcb_count; + lost_msg = ALL_HWCB_MTO; + lost_char = ALL_HWCB_CHAR; + + OUT_HWCB = NULL; + BUF_HWCB = NULL; + ALL_HWCB_MTO = 0; + ALL_HWCB_CHAR = 0; + hwc_data.hwcb_count = 0; + } else { + + lost_hwcb = hwc_data.hwcb_count - 1; + lost_msg = ALL_HWCB_MTO - BUF_HWCB_MTO; + lost_char = ALL_HWCB_CHAR - BUF_HWCB_CHAR; + OUT_HWCB = BUF_HWCB; + ALL_HWCB_MTO = BUF_HWCB_MTO; + ALL_HWCB_CHAR = BUF_HWCB_CHAR; + hwc_data.hwcb_count = 1; + page = (unsigned long) BUF_HWCB; + + if (page >= hwc_data.kmem_start && + page < hwc_data.kmem_end) { + + page_nr = (int) + ((page - hwc_data.kmem_start) >> 12); + set_bit (page_nr, &hwc_data.kmem_pages); + } + } + + internal_print ( + DELAYED_WRITE, + HWC_RW_PRINT_HEADER + "found invalid HWCB at address 0x%x. List corrupted. " + "Lost %i HWCBs with %i characters within up to %i " + "messages. Saved %i HWCB with last %i characters i" + "within up to %i messages.\n", + (unsigned int) bad_addr, + lost_hwcb, lost_char, lost_msg, + hwc_data.hwcb_count, + ALL_HWCB_CHAR, ALL_HWCB_MTO); + } + return 0; +} + +static int +reuse_write_hwcb (void) +{ + int retval; + + if (hwc_data.hwcb_count < 2) +#ifdef DUMP_HWC_WRITE_LIST_ERROR + __asm__ ("LHI 1,0xe31\n\t" + "LRA 2,0(0,%0)\n\t" + "LRA 3,0(0,%1)\n\t" + "J .+0 \n\t" + : + : "a" (BUF_HWCB), "a" (OUT_HWCB) + : "1", "2", "3"); +#else + return -EPERM; +#endif + + if (hwc_data.current_hwcb == OUT_HWCB) { + + if (hwc_data.hwcb_count > 2) { + + BUF_HWCB_NEXT = OUT_HWCB_NEXT; + + BUF_HWCB = OUT_HWCB_NEXT; + + OUT_HWCB_NEXT = BUF_HWCB_NEXT; + + BUF_HWCB_NEXT = NULL; + } + } else { + + BUF_HWCB_NEXT = OUT_HWCB; + + BUF_HWCB = OUT_HWCB; + + OUT_HWCB = OUT_HWCB_NEXT; + + BUF_HWCB_NEXT = NULL; + } + + BUF_HWCB_TIMES_LOST += 1; + BUF_HWCB_CHAR_LOST += BUF_HWCB_CHAR; + BUF_HWCB_MTO_LOST += BUF_HWCB_MTO; + ALL_HWCB_MTO -= BUF_HWCB_MTO; + ALL_HWCB_CHAR -= BUF_HWCB_CHAR; + + retval = prepare_write_hwcb (); + + if (hwc_data.hwcb_count == hwc_data.ioctls.max_hwcb) + internal_print ( + DELAYED_WRITE, + HWC_RW_PRINT_HEADER + "reached my own limit of " + "allowed buffer space for output (%i HWCBs = %li " + "bytes), skipped content of oldest HWCB %i time(s) " + "(%i lines = %i characters)\n", + hwc_data.ioctls.max_hwcb, + hwc_data.ioctls.max_hwcb * PAGE_SIZE, + BUF_HWCB_TIMES_LOST, + BUF_HWCB_MTO_LOST, + BUF_HWCB_CHAR_LOST); + else + internal_print ( + DELAYED_WRITE, + HWC_RW_PRINT_HEADER + "page allocation failed, " + "could not expand buffer for output (currently in " + "use: %i HWCBs = %li bytes), skipped content of " + "oldest HWCB %i time(s) (%i lines = %i characters)\n", + hwc_data.hwcb_count, + hwc_data.hwcb_count * PAGE_SIZE, + BUF_HWCB_TIMES_LOST, + BUF_HWCB_MTO_LOST, + BUF_HWCB_CHAR_LOST); + + return retval; +} + +static int +allocate_write_hwcb (void) +{ + unsigned char *page; + int page_nr; + + if (hwc_data.hwcb_count == hwc_data.ioctls.max_hwcb) + return -ENOMEM; + + page_nr = find_first_zero_bit (&hwc_data.kmem_pages, MAX_KMEM_PAGES); + if (page_nr < hwc_data.ioctls.kmem_hwcb) { + + page = (unsigned char *) + (hwc_data.kmem_start + (page_nr << 12)); + set_bit (page_nr, &hwc_data.kmem_pages); + } else + page = (unsigned char *) __get_free_page (GFP_ATOMIC); + + if (!page) + return -ENOMEM; + + if (!OUT_HWCB) + OUT_HWCB = page; + else + BUF_HWCB_NEXT = page; + + BUF_HWCB = page; + + BUF_HWCB_NEXT = NULL; + + hwc_data.hwcb_count++; + + prepare_write_hwcb (); + + BUF_HWCB_TIMES_LOST = 0; + BUF_HWCB_MTO_LOST = 0; + BUF_HWCB_CHAR_LOST = 0; + +#ifdef BUFFER_STRESS_TEST + + internal_print ( + DELAYED_WRITE, + "*** " HWC_RW_PRINT_HEADER + "page #%i at 0x%x for buffering allocated. ***\n", + hwc_data.hwcb_count, page); + +#endif + + return 0; +} + +static int +release_write_hwcb (void) +{ + unsigned long page; + int page_nr; + + if (!hwc_data.hwcb_count) + return -ENODATA; + + if (hwc_data.hwcb_count == 1) { + + prepare_write_hwcb (); + + ALL_HWCB_CHAR = 0; + ALL_HWCB_MTO = 0; + BUF_HWCB_TIMES_LOST = 0; + BUF_HWCB_MTO_LOST = 0; + BUF_HWCB_CHAR_LOST = 0; + } else { + page = (unsigned long) OUT_HWCB; + + ALL_HWCB_MTO -= OUT_HWCB_MTO; + ALL_HWCB_CHAR -= OUT_HWCB_CHAR; + hwc_data.hwcb_count--; + + OUT_HWCB = OUT_HWCB_NEXT; + + if (page >= hwc_data.kmem_start && + page < hwc_data.kmem_end) { + + memset ((void *) page, 0, PAGE_SIZE); + + page_nr = (int) ((page - hwc_data.kmem_start) >> 12); + clear_bit (page_nr, &hwc_data.kmem_pages); + } else + free_page (page); +#ifdef BUFFER_STRESS_TEST + + internal_print ( + DELAYED_WRITE, + "*** " HWC_RW_PRINT_HEADER + "page at 0x%x released, %i pages still in use ***\n", + page, hwc_data.hwcb_count); + +#endif + } + return 0; +} + +static int +add_mto ( + unsigned char *message, + unsigned short int count) +{ + unsigned short int mto_size; + write_hwcb_t *hwcb; + mto_t *mto; + void *dest; + + if (!BUF_HWCB) + return -ENOMEM; + + if (BUF_HWCB == hwc_data.current_hwcb) + return -ENOMEM; + + mto_size = sizeof (mto_t) + count; + + hwcb = (write_hwcb_t *) BUF_HWCB; + + if ((MAX_HWCB_ROOM - hwcb->length) < mto_size) + return -ENOMEM; + + mto = (mto_t *) (((unsigned long) hwcb) + hwcb->length); + + memcpy (mto, &mto_template, sizeof (mto_t)); + + dest = (void *) (((unsigned long) mto) + sizeof (mto_t)); + + memcpy (dest, message, count); + + mto->length += count; + + hwcb->length += mto_size; + hwcb->msgbuf.length += mto_size; + hwcb->msgbuf.mdb.length += mto_size; + + BUF_HWCB_MTO++; + ALL_HWCB_MTO++; + BUF_HWCB_CHAR += count; + ALL_HWCB_CHAR += count; + + return count; +} + +static int +write_event_data_1 (void) +{ + unsigned short int condition_code; + int retval; + + if ((!hwc_data.write_prio) && (!hwc_data.write_nonprio)) + return -EPERM; + + if (hwc_data.current_servc) + return -EBUSY; + + retval = sane_write_hwcb (); + if (retval < 0) + return retval; + + if (!OUT_HWCB_MTO) + return -ENODATA; + + condition_code = service_call (HWC_CMDW_WRITEDATA, OUT_HWCB); + +#ifdef DUMP_HWC_WRITE_ERROR + if (condition_code != HWC_COMMAND_INITIATED) + __asm__ ("LHI 1,0xe20\n\t" + "L 2,0(0,%0)\n\t" + "LRA 3,0(0,%1)\n\t" + "J .+0 \n\t" + : + : "a" (&condition_code), "a" (OUT_HWCB) + : "1", "2", "3"); +#endif + + switch (condition_code) { + case HWC_COMMAND_INITIATED: + hwc_data.current_servc = HWC_CMDW_WRITEDATA; + hwc_data.current_hwcb = OUT_HWCB; + retval = condition_code; + break; + case HWC_BUSY: + retval = -EBUSY; + break; + default: + retval = -EIO; + } + + return retval; +} + +static void +flush_hwcbs (void) +{ + while (hwc_data.hwcb_count > 1) + release_write_hwcb (); + + release_write_hwcb (); + + hwc_data.flags &= ~FLUSH_HWCBS; +} + +static int +write_event_data_2 (void) +{ + write_hwcb_t *hwcb; + int retval; + unsigned char *param; + + param = ext_int_param (); + if (param != hwc_data.current_hwcb) + return -EINVAL; + + hwcb = (write_hwcb_t *) OUT_HWCB; + +#ifdef DUMP_HWC_WRITE_ERROR +#if 0 + if (((unsigned char *) hwcb) != param) + __asm__ ("LHI 1,0xe22\n\t" + "LRA 2,0(0,%0)\n\t" + "LRA 3,0(0,%1)\n\t" + "LRA 4,0(0,%2)\n\t" + "LRA 5,0(0,%3)\n\t" + "J .+0 \n\t" + : + : "a" (OUT_HWCB), + "a" (hwc_data.current_hwcb), + "a" (BUF_HWCB), + "a" (param) + : "1", "2", "3", "4", "5"); +#endif + if (hwcb->response_code != 0x0020) +#if 0 + internal_print (DELAYED_WRITE, HWC_RW_PRINT_HEADER + "\n************************ error in write_event_data_2()\n" + "OUT_HWCB: 0x%x\n" + "BUF_HWCB: 0x%x\n" + "response_code: 0x%x\n" + "hwc_data.hwcb_count: %d\n" + "hwc_data.kmem_pages: 0x%x\n" + "hwc_data.ioctls.kmem_hwcb: %d\n" + "hwc_data.ioctls.max_hwcb: %d\n" + "hwc_data.kmem_start: 0x%x\n" + "hwc_data.kmem_end: 0x%x\n" + "*****************************************************\n", + OUT_HWCB, + BUF_HWCB, + hwcb->response_code, + hwc_data.hwcb_count, + hwc_data.kmem_pages, + hwc_data.ioctls.kmem_hwcb, + hwc_data.ioctls.max_hwcb, + hwc_data.kmem_start, + hwc_data.kmem_end); +#endif + __asm__ ("LHI 1,0xe21\n\t" + "LRA 2,0(0,%0)\n\t" + "LRA 3,0(0,%1)\n\t" + "LRA 4,0(0,%2)\n\t" + "LH 5,0(0,%3)\n\t" + "SRL 5,8(0)\n\t" + "J .+0 \n\t" + : + : "a" (OUT_HWCB), "a" (hwc_data.current_hwcb), + "a" (BUF_HWCB), + "a" (&(hwc_data.hwcb_count)) + : "1", "2", "3", "4", "5"); +#endif + + if (hwcb->response_code == 0x0020) { + + retval = OUT_HWCB_CHAR; + release_write_hwcb (); + } else + retval = -EIO; + + hwc_data.current_servc = 0; + hwc_data.current_hwcb = NULL; + + if (hwc_data.flags & FLUSH_HWCBS) + flush_hwcbs (); + + return retval; +} + +static void +do_put_line ( + unsigned char *message, + unsigned short count) +{ + + if (add_mto (message, count) != count) { + + if (allocate_write_hwcb () < 0) + reuse_write_hwcb (); + +#ifdef DUMP_HWC_WRITE_LIST_ERROR + if (add_mto (message, count) != count) + __asm__ ("LHI 1,0xe32\n\t" + "LRA 2,0(0,%0)\n\t" + "L 3,0(0,%1)\n\t" + "LRA 4,0(0,%2)\n\t" + "LRA 5,0(0,%3)\n\t" + "J .+0 \n\t" + : + : "a" (message), "a" (&hwc_data.kmem_pages), + "a" (BUF_HWCB), "a" (OUT_HWCB) + : "1", "2", "3", "4", "5"); +#else + add_mto (message, count); +#endif + } +} + +static void +put_line ( + unsigned char *message, + unsigned short count) +{ + + if ((!hwc_data.obuf_start) && (hwc_data.flags & HWC_TIMER_RUNS)) { + del_timer (&hwc_data.write_timer); + hwc_data.flags &= ~HWC_TIMER_RUNS; + } + hwc_data.obuf_start += count; + + do_put_line (message, count); + + hwc_data.obuf_start -= count; +} + +static void +set_alarm (void) +{ + write_hwcb_t *hwcb; + + if ((!BUF_HWCB) || (BUF_HWCB == hwc_data.current_hwcb)) + allocate_write_hwcb (); + + hwcb = (write_hwcb_t *) BUF_HWCB; + hwcb->msgbuf.mdb.mdb_body.go.general_msg_flags |= GMF_SndAlrm; +} + +static void +hwc_write_timeout (unsigned long data) +{ + unsigned long flags; + + spin_lock_irqsave (&hwc_data.lock, flags); + + hwc_data.obuf_start = hwc_data.obuf_count; + if (hwc_data.obuf_count) + put_line (hwc_data.obuf, hwc_data.obuf_count); + hwc_data.obuf_start = 0; + + hwc_data.obuf_cursor = 0; + hwc_data.obuf_count = 0; + + write_event_data_1 (); + + spin_unlock_irqrestore (&hwc_data.lock, flags); +} + +static int +do_hwc_write ( + int from_user, + unsigned char *msg, + unsigned int count, + unsigned char code, + unsigned char write_time) +{ + unsigned int i_msg = 0; + unsigned short int spaces = 0; + unsigned int processed_characters = 0; + unsigned char ch, orig_ch; + unsigned short int obuf_count; + unsigned short int obuf_cursor; + unsigned short int obuf_columns; + + if (hwc_data.obuf_start) { + obuf_cursor = 0; + obuf_count = 0; + obuf_columns = MIN (hwc_data.ioctls.columns, + MAX_MESSAGE_SIZE - hwc_data.obuf_start); + } else { + obuf_cursor = hwc_data.obuf_cursor; + obuf_count = hwc_data.obuf_count; + obuf_columns = hwc_data.ioctls.columns; + } + + for (i_msg = 0; i_msg < count; i_msg++) { + + if (from_user) + get_user (orig_ch, msg + i_msg); + else + orig_ch = msg[i_msg]; + if (code == CODE_EBCDIC) + ch = _ebcasc[orig_ch]; + else + ch = orig_ch; + + processed_characters++; + + if ((obuf_cursor == obuf_columns) && + + (ch != '\n') && + + (ch != '\t')) { + put_line (&hwc_data.obuf[hwc_data.obuf_start], + obuf_columns); + obuf_cursor = 0; + obuf_count = 0; + } + switch (ch) { + + case '\n': + + put_line (&hwc_data.obuf[hwc_data.obuf_start], + obuf_count); + obuf_cursor = 0; + obuf_count = 0; + break; + + case '\a': + + hwc_data.obuf_start += obuf_count; + set_alarm (); + hwc_data.obuf_start -= obuf_count; + + break; + + case '\t': + + do { + if (obuf_cursor < obuf_columns) { + hwc_data.obuf[hwc_data.obuf_start + + obuf_cursor] + = 0x20; + obuf_cursor++; + } else + break; + } while (obuf_cursor % hwc_data.ioctls.width_htab); + + break; + + case '\f': + case '\v': + + spaces = obuf_cursor; + put_line (&hwc_data.obuf[hwc_data.obuf_start], + obuf_count); + obuf_count = obuf_cursor; + while (spaces) { + hwc_data.obuf[hwc_data.obuf_start + + obuf_cursor - spaces] + = 0x20; + spaces--; + } + + break; + + case '\b': + + if (obuf_cursor) + obuf_cursor--; + break; + + case '\r': + + obuf_cursor = 0; + break; + + case 0x00: + + put_line (&hwc_data.obuf[hwc_data.obuf_start], + obuf_count); + obuf_cursor = 0; + obuf_count = 0; + goto out; + + default: + + if (isprint (ch)) + hwc_data.obuf[hwc_data.obuf_start + + obuf_cursor++] + = (code == CODE_ASCII) ? + _ascebc[orig_ch] : orig_ch; + } + if (obuf_cursor > obuf_count) + obuf_count = obuf_cursor; + } + + if (obuf_cursor) { + + if (hwc_data.obuf_start || + (hwc_data.ioctls.final_nl == 0)) { + + put_line (&hwc_data.obuf[hwc_data.obuf_start], + obuf_count); + obuf_cursor = 0; + obuf_count = 0; + } else { + + if (hwc_data.ioctls.final_nl > 0) { + + if (hwc_data.flags & HWC_TIMER_RUNS) { + + hwc_data.write_timer.expires = + jiffies + + hwc_data.ioctls.final_nl * HZ / 10; + } else { + + init_timer (&hwc_data.write_timer); + hwc_data.write_timer.function = + hwc_write_timeout; + hwc_data.write_timer.data = + (unsigned long) NULL; + hwc_data.write_timer.expires = + jiffies + + hwc_data.ioctls.final_nl * HZ / 10; + add_timer (&hwc_data.write_timer); + hwc_data.flags |= HWC_TIMER_RUNS; + } + } else; + + } + } else; + + out: + + if (!hwc_data.obuf_start) { + hwc_data.obuf_cursor = obuf_cursor; + hwc_data.obuf_count = obuf_count; + } + if (write_time == IMMEDIATE_WRITE) + write_event_data_1 (); + + return processed_characters; +} + +signed int +hwc_write (int from_user, const unsigned char *msg, unsigned int count) +{ + unsigned long flags; + int retval; + + spin_lock_irqsave (&hwc_data.lock, flags); + + retval = do_hwc_write (from_user, msg, count, hwc_data.ioctls.code, + IMMEDIATE_WRITE); + + spin_unlock_irqrestore (&hwc_data.lock, flags); + + return retval; +} + +unsigned int +hwc_chars_in_buffer (unsigned char flag) +{ + unsigned short int number = 0; + unsigned long flags; + + spin_lock_irqsave (&hwc_data.lock, flags); + + if (flag & IN_HWCB) + number += ALL_HWCB_CHAR; + + if (flag & IN_WRITE_BUF) + number += hwc_data.obuf_cursor; + + spin_unlock_irqrestore (&hwc_data.lock, flags); + + return number; +} + +static inline int +nr_setbits (kmem_pages_t arg) +{ + int i; + int nr = 0; + + for (i = 0; i < (sizeof (arg) << 3); i++) { + if (arg & 1) + nr++; + arg >>= 1; + } + + return nr; +} + +unsigned int +hwc_write_room (unsigned char flag) +{ + unsigned int number = 0; + unsigned long flags; + write_hwcb_t *hwcb; + + spin_lock_irqsave (&hwc_data.lock, flags); + + if (flag & IN_HWCB) { + + if (BUF_HWCB) { + hwcb = (write_hwcb_t *) BUF_HWCB; + number += MAX_HWCB_ROOM - hwcb->length; + } + number += (hwc_data.ioctls.kmem_hwcb - + nr_setbits (hwc_data.kmem_pages)) * + (MAX_HWCB_ROOM - + (sizeof (write_hwcb_t) + sizeof (mto_t))); + } + if (flag & IN_WRITE_BUF) + number += MAX_HWCB_ROOM - hwc_data.obuf_cursor; + + spin_unlock_irqrestore (&hwc_data.lock, flags); + + return number; +} + +void +hwc_flush_buffer (unsigned char flag) +{ + unsigned long flags; + + spin_lock_irqsave (&hwc_data.lock, flags); + + if (flag & IN_HWCB) { + if (hwc_data.current_servc != HWC_CMDW_WRITEDATA) + flush_hwcbs (); + else + hwc_data.flags |= FLUSH_HWCBS; + } + if (flag & IN_WRITE_BUF) { + hwc_data.obuf_cursor = 0; + hwc_data.obuf_count = 0; + } + spin_unlock_irqrestore (&hwc_data.lock, flags); +} + +unsigned short int +seperate_cases (unsigned char *buf, unsigned short int count) +{ + + unsigned short int i_in; + + unsigned short int i_out = 0; + + unsigned char _case = 0; + + for (i_in = 0; i_in < count; i_in++) { + + if (buf[i_in] == hwc_data.ioctls.delim) { + + if ((i_in + 1 < count) && + (buf[i_in + 1] == hwc_data.ioctls.delim)) { + + buf[i_out] = hwc_data.ioctls.delim; + + i_out++; + + i_in++; + + } else + _case = ~_case; + + } else { + + if (_case) { + + if (hwc_data.ioctls.tolower) + buf[i_out] = _ebc_toupper[buf[i_in]]; + + else + buf[i_out] = _ebc_tolower[buf[i_in]]; + + } else + buf[i_out] = buf[i_in]; + + i_out++; + } + } + + return i_out; +} + +#ifdef DUMP_HWCB_INPUT + +static int +gds_vector_name (u16 id, unsigned char name[]) +{ + int retval = 0; + + switch (id) { + case GDS_ID_MDSMU: + name = "Multiple Domain Support Message Unit"; + break; + case GDS_ID_MDSRouteInfo: + name = "MDS Routing Information"; + break; + case GDS_ID_AgUnWrkCorr: + name = "Agent Unit of Work Correlator"; + break; + case GDS_ID_SNACondReport: + name = "SNA Condition Report"; + break; + case GDS_ID_CPMSU: + name = "CP Management Services Unit"; + break; + case GDS_ID_RoutTargInstr: + name = "Routing and Targeting Instructions"; + break; + case GDS_ID_OpReq: + name = "Operate Request"; + break; + case GDS_ID_TextCmd: + name = "Text Command"; + break; + + default: + name = "unknown GDS variable"; + retval = -EINVAL; + } + + return retval; +} +#endif + +inline static gds_vector_t * +find_gds_vector ( + gds_vector_t * start, void *end, u16 id) +{ + gds_vector_t *vec; + gds_vector_t *retval = NULL; + + vec = start; + + while (((void *) vec) < end) { + if (vec->gds_id == id) { + +#ifdef DUMP_HWCB_INPUT + int retval_name; + unsigned char name[64]; + + retval_name = gds_vector_name (id, name); + internal_print ( + DELAYED_WRITE, + HWC_RW_PRINT_HEADER + "%s at 0x%x up to 0x%x, length: %d", + name, + (unsigned long) vec, + ((unsigned long) vec) + vec->length - 1, + vec->length); + if (retval_name < 0) + internal_print ( + IMMEDIATE_WRITE, + ", id: 0x%x\n", + vec->gds_id); + else + internal_print ( + IMMEDIATE_WRITE, + "\n"); +#endif + + retval = vec; + break; + } + vec = (gds_vector_t *) (((unsigned long) vec) + vec->length); + } + + return retval; +} + +inline static gds_subvector_t * +find_gds_subvector ( + gds_subvector_t * start, void *end, u8 key) +{ + gds_subvector_t *subvec; + gds_subvector_t *retval = NULL; + + subvec = start; + + while (((void *) subvec) < end) { + if (subvec->key == key) { + retval = subvec; + break; + } + subvec = (gds_subvector_t *) + (((unsigned long) subvec) + subvec->length); + } + + return retval; +} + +inline static int +get_input (void *start, void *end) +{ + int count; + + count = ((unsigned long) end) - ((unsigned long) start); + + if (hwc_data.ioctls.tolower) + EBC_TOLOWER (start, count); + + if (hwc_data.ioctls.delim) + count = seperate_cases (start, count); + + if (hwc_data.ioctls.echo) + do_hwc_write (0, start, count, CODE_EBCDIC, IMMEDIATE_WRITE); + + if (hwc_data.ioctls.code == CODE_ASCII) + EBCASC (start, count); + + store_hwc_input (start, count); + + return count; +} + +inline static int +eval_selfdeftextmsg (gds_subvector_t * start, void *end) +{ + gds_subvector_t *subvec; + void *subvec_data; + void *subvec_end; + int retval = 0; + + subvec = start; + + while (((void *) subvec) < end) { + subvec = find_gds_subvector (subvec, end, 0x30); + if (!subvec) + break; + subvec_data = (void *) + (((unsigned long) subvec) + + sizeof (gds_subvector_t)); + subvec_end = (void *) + (((unsigned long) subvec) + subvec->length); + retval += get_input (subvec_data, subvec_end); + subvec = (gds_subvector_t *) subvec_end; + } + + return retval; +} + +inline static int +eval_textcmd (gds_subvector_t * start, void *end) +{ + gds_subvector_t *subvec; + gds_subvector_t *subvec_data; + void *subvec_end; + int retval = 0; + + subvec = start; + + while (((void *) subvec) < end) { + subvec = find_gds_subvector ( + subvec, end, GDS_KEY_SelfDefTextMsg); + if (!subvec) + break; + subvec_data = (gds_subvector_t *) + (((unsigned long) subvec) + + sizeof (gds_subvector_t)); + subvec_end = (void *) + (((unsigned long) subvec) + subvec->length); + retval += eval_selfdeftextmsg (subvec_data, subvec_end); + subvec = (gds_subvector_t *) subvec_end; + } + + return retval; +} + +inline static int +eval_cpmsu (gds_vector_t * start, void *end) +{ + gds_vector_t *vec; + gds_subvector_t *vec_data; + void *vec_end; + int retval = 0; + + vec = start; + + while (((void *) vec) < end) { + vec = find_gds_vector (vec, end, GDS_ID_TextCmd); + if (!vec) + break; + vec_data = (gds_subvector_t *) + (((unsigned long) vec) + sizeof (gds_vector_t)); + vec_end = (void *) (((unsigned long) vec) + vec->length); + retval += eval_textcmd (vec_data, vec_end); + vec = (gds_vector_t *) vec_end; + } + + return retval; +} + +inline static int +eval_mdsmu (gds_vector_t * start, void *end) +{ + gds_vector_t *vec; + gds_vector_t *vec_data; + void *vec_end; + int retval = 0; + + vec = find_gds_vector (start, end, GDS_ID_CPMSU); + if (vec) { + vec_data = (gds_vector_t *) + (((unsigned long) vec) + sizeof (gds_vector_t)); + vec_end = (void *) (((unsigned long) vec) + vec->length); + retval = eval_cpmsu (vec_data, vec_end); + } + return retval; +} + +inline static int +eval_evbuf (gds_vector_t * start, void *end) +{ + gds_vector_t *vec; + gds_vector_t *vec_data; + void *vec_end; + int retval = 0; + + vec = find_gds_vector (start, end, GDS_ID_MDSMU); + if (vec) { + vec_data = (gds_vector_t *) + (((unsigned long) vec) + sizeof (gds_vector_t)); + vec_end = (void *) (((unsigned long) vec) + vec->length); + retval = eval_mdsmu (vec_data, vec_end); + } + return retval; +} + +static int +process_evbufs (void *start, void *end) +{ + int retval = 0; + evbuf_t *evbuf; + void *evbuf_end; + gds_vector_t *evbuf_data; + + evbuf = (evbuf_t *) start; + while (((void *) evbuf) < end) { + evbuf_data = (gds_vector_t *) + (((unsigned long) evbuf) + sizeof (evbuf_t)); + evbuf_end = (void *) (((unsigned long) evbuf) + evbuf->length); + switch (evbuf->type) { + case ET_OpCmd: + case ET_CntlProgOpCmd: + case ET_PMsgCmd: +#ifdef DUMP_HWCB_INPUT + + internal_print ( + DELAYED_WRITE, + HWC_RW_PRINT_HEADER + "event buffer " + "at 0x%x up to 0x%x, length: %d\n", + (unsigned long) evbuf, + (unsigned long) (evbuf_end - 1), + evbuf->length); + dump_storage_area ((void *) evbuf, evbuf->length); +#endif + retval += eval_evbuf (evbuf_data, evbuf_end); + break; + case ET_StateChange: + + retval = -ENOSYS; + break; + default: + printk ( + KERN_WARNING + HWC_RW_PRINT_HEADER + "unconditional read: " + "unknown event buffer found, " + "type 0x%x", + evbuf->type); + retval = -ENOSYS; + } + evbuf = (evbuf_t *) evbuf_end; + } + return retval; +} + +static int +unconditional_read_1 (void) +{ + unsigned short int condition_code; + read_hwcb_t *hwcb = (read_hwcb_t *) hwc_data.page; + int retval; + + if ((!hwc_data.read_prio) && (!hwc_data.read_nonprio)) + return -EOPNOTSUPP; + + if (hwc_data.current_servc) + return -EBUSY; + + memset (hwcb, 0x00, PAGE_SIZE); + memcpy (hwcb, &read_hwcb_template, sizeof (read_hwcb_t)); + + condition_code = service_call (HWC_CMDW_READDATA, hwc_data.page); + +#ifdef DUMP_HWC_READ_ERROR + if (condition_code == HWC_NOT_OPERATIONAL) + __asm__ ("LHI 1,0xe40\n\t" + "L 2,0(0,%0)\n\t" + "LRA 3,0(0,%1)\n\t" + "J .+0 \n\t" + : + : "a" (&condition_code), "a" (hwc_data.page) + : "1", "2", "3"); +#endif + + switch (condition_code) { + case HWC_COMMAND_INITIATED: + hwc_data.current_servc = HWC_CMDW_READDATA; + hwc_data.current_hwcb = hwc_data.page; + retval = condition_code; + break; + case HWC_BUSY: + retval = -EBUSY; + break; + default: + retval = -EIO; + } + + return retval; +} + +static int +unconditional_read_2 (void) +{ + read_hwcb_t *hwcb = (read_hwcb_t *) hwc_data.page; + +#ifdef DUMP_HWC_READ_ERROR + if ((hwcb->response_code != 0x0020) && + (hwcb->response_code != 0x0220) && + (hwcb->response_code != 0x60F0) && + (hwcb->response_code != 0x62F0)) + __asm__ ("LHI 1,0xe41\n\t" + "LRA 2,0(0,%0)\n\t" + "L 3,0(0,%1)\n\t" + "J .+0\n\t" + : + : "a" (hwc_data.page), "a" (&(hwcb->response_code)) + : "1", "2", "3"); +#endif + + hwc_data.current_servc = 0; + hwc_data.current_hwcb = NULL; + + switch (hwcb->response_code) { + + case 0x0020: + case 0x0220: + return process_evbufs ( + (void *) (((unsigned long) hwcb) + sizeof (read_hwcb_t)), + (void *) (((unsigned long) hwcb) + hwcb->length)); + + case 0x60F0: + case 0x62F0: + return 0; + + case 0x0100: + internal_print ( + IMMEDIATE_WRITE, + HWC_RW_PRINT_HEADER + "unconditional read: HWCB boundary violation - this " + "must not occur in a correct driver, please contact " + "author\n"); + return -EIO; + + case 0x0300: + internal_print ( + IMMEDIATE_WRITE, + HWC_RW_PRINT_HEADER + "unconditional read: " + "insufficient HWCB length - this must not occur in a " + "correct driver, please contact author\n"); + return -EIO; + + case 0x01F0: + internal_print ( + IMMEDIATE_WRITE, + HWC_RW_PRINT_HEADER + "unconditional read: " + "invalid command - this must not occur in a correct " + "driver, please contact author\n"); + return -EIO; + + case 0x40F0: + internal_print ( + IMMEDIATE_WRITE, + HWC_RW_PRINT_HEADER + "unconditional read: invalid function code - this " + "must not occur in a correct driver, please contact " + "author\n"); + return -EIO; + + case 0x70F0: + internal_print ( + IMMEDIATE_WRITE, + HWC_RW_PRINT_HEADER + "unconditional read: invalid selection mask - this " + "must not occur in a correct driver, please contact " + "author\n"); + return -EIO; + + case 0x0040: + internal_print ( + IMMEDIATE_WRITE, + HWC_RW_PRINT_HEADER + "unconditional read: HWC equipment check - don't " + "know how to handle this case\n"); + return -EIO; + + default: + internal_print ( + IMMEDIATE_WRITE, + HWC_RW_PRINT_HEADER + "unconditional read: invalid response code %x - this " + "must not occur in a correct driver, please contact " + "author\n", + hwcb->response_code); + return -EIO; + } +} + +static int +write_event_mask_1 (void) +{ + unsigned int condition_code; + int retval; + + memcpy (hwc_data.page, &init_hwcb_template, sizeof (init_hwcb_t)); + + condition_code = service_call (HWC_CMDW_WRITEMASK, hwc_data.page); + +#ifdef DUMP_HWC_INIT_ERROR + + if (condition_code != HWC_COMMAND_INITIATED) + __asm__ ("LHI 1,0xe10\n\t" + "L 2,0(0,%0)\n\t" + "LRA 3,0(0,%1)\n\t" + "J .+0\n\t" + : + : "a" (&condition_code), "a" (hwc_data.page) + : "1", "2", "3"); +#endif + + switch (condition_code) { + case HWC_COMMAND_INITIATED: + hwc_data.current_servc = HWC_CMDW_WRITEMASK; + hwc_data.current_hwcb = hwc_data.page; + retval = condition_code; + break; + case HWC_BUSY: + retval = -EBUSY; + break; + default: + retval = -EIO; + } + + return retval; +} + +static int +write_event_mask_2 (void) +{ + init_hwcb_t *hwcb = (init_hwcb_t *) hwc_data.page; + int retval = 0; + + if (hwcb->hwc_receive_mask & ET_Msg_Mask) + hwc_data.write_nonprio = 1; + + if (hwcb->hwc_receive_mask & ET_PMsgCmd_Mask) + hwc_data.write_prio = 1; + + if (hwcb->hwc_send_mask & ET_OpCmd_Mask) + hwc_data.read_nonprio = 1; + + if (hwcb->hwc_send_mask & ET_PMsgCmd_Mask) + hwc_data.read_nonprio = 1; + + if ((hwcb->response_code != 0x0020) || + (!hwc_data.write_nonprio) || + ((!hwc_data.read_nonprio) && (!hwc_data.read_prio))) +#ifdef DUMP_HWC_INIT_ERROR + __asm__ ("LHI 1,0xe11\n\t" + "LRA 2,0(0,%0)\n\t" + "L 3,0(0,%1)\n\t" + "J .+0\n\t" + : + : "a" (hwcb), "a" (&(hwcb->response_code)) + : "1", "2", "3"); +#else + retval = -EIO +#endif + + hwc_data.current_servc = 0; + hwc_data.current_hwcb = NULL; + + return retval; +} + +static int +set_hwc_ioctls (hwc_ioctls_t * ioctls, char correct) +{ + int retval = 0; + hwc_ioctls_t tmp; + + if (ioctls->width_htab > MAX_MESSAGE_SIZE) { + if (correct) + tmp.width_htab = MAX_MESSAGE_SIZE; + else + retval = -EINVAL; + } else + tmp.width_htab = ioctls->width_htab; + + tmp.echo = ioctls->echo; + + if (ioctls->columns > MAX_MESSAGE_SIZE) { + if (correct) + tmp.columns = MAX_MESSAGE_SIZE; + else + retval = -EINVAL; + } else + tmp.columns = ioctls->columns; + + switch (ioctls->code) { + case CODE_EBCDIC: + case CODE_ASCII: + tmp.code = ioctls->code; + break; + default: + if (correct) + tmp.code = CODE_ASCII; + else + retval = -EINVAL; + } + + tmp.final_nl = ioctls->final_nl; + + if (ioctls->max_hwcb < 2) { + if (correct) + tmp.max_hwcb = 2; + else + retval = -EINVAL; + } else + tmp.max_hwcb = ioctls->max_hwcb; + + tmp.tolower = ioctls->tolower; + + if (ioctls->kmem_hwcb > ioctls->max_hwcb) { + if (correct) + tmp.kmem_hwcb = ioctls->max_hwcb; + else + retval = -EINVAL; + } else + tmp.kmem_hwcb = ioctls->kmem_hwcb; + + if (ioctls->kmem_hwcb > MAX_KMEM_PAGES) { + if (correct) + ioctls->kmem_hwcb = MAX_KMEM_PAGES; + else + retval = -EINVAL; + } + if (ioctls->kmem_hwcb < 2) { + if (correct) + ioctls->kmem_hwcb = 2; + else + retval = -EINVAL; + } + tmp.delim = ioctls->delim; + + if (!(retval < 0)) + hwc_data.ioctls = tmp; + + return retval; +} + +int +hwc_init (void) +{ + int retval; +#ifdef BUFFER_STRESS_TEST + + init_hwcb_t *hwcb; + int i; + +#endif + +#ifdef CONFIG_3215 + if (MACHINE_IS_VM) + return 0; +#endif + + spin_lock_init (&hwc_data.lock); + + retval = write_event_mask_1 (); + if (retval < 0) + return retval; + +#ifdef USE_VM_DETECTION + + if (MACHINE_IS_VM) { + + if (hwc_data.init_ioctls.columns > 76) + hwc_data.init_ioctls.columns = 76; + hwc_data.init_ioctls.tolower = 1; + if (!hwc_data.init_ioctls.delim) + hwc_data.init_ioctls.delim = DEFAULT_CASE_DELIMITER; + } else { + hwc_data.init_ioctls.tolower = 0; + hwc_data.init_ioctls.delim = 0; + } +#endif + retval = set_hwc_ioctls (&hwc_data.init_ioctls, 1); + + hwc_data.kmem_start = (unsigned long) + alloc_bootmem_pages (hwc_data.ioctls.kmem_hwcb * PAGE_SIZE); + hwc_data.kmem_end = hwc_data.kmem_start + + hwc_data.ioctls.kmem_hwcb * PAGE_SIZE - 1; + + ctl_set_bit (0, 9); + +#ifdef BUFFER_STRESS_TEST + + internal_print ( + DELAYED_WRITE, + HWC_RW_PRINT_HEADER + "use %i bytes for buffering.\n", + hwc_data.ioctls.kmem_hwcb * PAGE_SIZE); + for (i = 0; i < 500; i++) { + hwcb = (init_hwcb_t *) BUF_HWCB; + internal_print ( + DELAYED_WRITE, + HWC_RW_PRINT_HEADER + "This is stress test message #%i, free: %i bytes\n", + i, + MAX_HWCB_ROOM - (hwcb->length + sizeof (mto_t))); + } + +#endif + + return retval; +} + +void +do_hwc_interrupt (void) +{ + + spin_lock (&hwc_data.lock); + + if (!hwc_data.current_servc) { + + unconditional_read_1 (); + + } else { + + switch (hwc_data.current_servc) { + + case HWC_CMDW_WRITEMASK: + + write_event_mask_2 (); + break; + + case HWC_CMDW_WRITEDATA: + + write_event_data_2 (); + break; + + case HWC_CMDW_READDATA: + + unconditional_read_2 (); + break; + } + + write_event_data_1 (); + } + + wake_up_hwc_tty (); + + spin_unlock (&hwc_data.lock); +} + +int +hwc_ioctl (unsigned int cmd, unsigned long arg) +{ + hwc_ioctls_t tmp = hwc_data.ioctls; + int retval = 0; + unsigned long flags; + unsigned int obuf; + + spin_lock_irqsave (&hwc_data.lock, flags); + + switch (cmd) { + + case TIOCHWCSHTAB: + if (get_user (tmp.width_htab, (ioctl_htab_t *) arg)) + goto fault; + break; + + case TIOCHWCSECHO: + if (get_user (tmp.echo, (ioctl_echo_t *) arg)) + goto fault; + break; + + case TIOCHWCSCOLS: + if (get_user (tmp.columns, (ioctl_cols_t *) arg)) + goto fault; + break; + + case TIOCHWCSCODE: + if (get_user (tmp.code, (ioctl_code_t *) arg)) + goto fault; + + break; + + case TIOCHWCSNL: + if (get_user (tmp.final_nl, (ioctl_nl_t *) arg)) + goto fault; + break; + + case TIOCHWCSOBUF: + if (get_user (obuf, (unsigned int *) arg)) + goto fault; + if (obuf & 0xFFF) + tmp.max_hwcb = (((obuf | 0xFFF) + 1) >> 12); + else + tmp.max_hwcb = (obuf >> 12); + break; + + case TIOCHWCSCASE: + if (get_user (tmp.tolower, (ioctl_case_t *) arg)) + goto fault; + break; + + case TIOCHWCSDELIM: + if (get_user (tmp.delim, (ioctl_delim_t *) arg)) + goto fault; + break; + + case TIOCHWCSINIT: + retval = set_hwc_ioctls (&hwc_data.init_ioctls, 1); + break; + + case TIOCHWCGHTAB: + if (put_user (tmp.width_htab, (ioctl_htab_t *) arg)) + goto fault; + break; + + case TIOCHWCGECHO: + if (put_user (tmp.echo, (ioctl_echo_t *) arg)) + goto fault; + break; + + case TIOCHWCGCOLS: + if (put_user (tmp.columns, (ioctl_cols_t *) arg)) + goto fault; + break; + + case TIOCHWCGCODE: + if (put_user (tmp.code, (ioctl_code_t *) arg)) + goto fault; + + break; + + case TIOCHWCGNL: + if (put_user (tmp.final_nl, (ioctl_nl_t *) arg)) + goto fault; + break; + + case TIOCHWCGOBUF: + if (put_user (tmp.max_hwcb, (ioctl_obuf_t *) arg)) + goto fault; + break; + + case TIOCHWCGKBUF: + if (put_user (tmp.kmem_hwcb, (ioctl_obuf_t *) arg)) + goto fault; + break; + + case TIOCHWCGCASE: + if (put_user (tmp.tolower, (ioctl_case_t *) arg)) + goto fault; + break; + + case TIOCHWCGDELIM: + if (put_user (tmp.delim, (ioctl_delim_t *) arg)) + goto fault; + break; +#if 0 + + case TIOCHWCGINIT: + if (put_user (&hwc_data.init_ioctls, (hwc_ioctls_t *) arg)) + goto fault; + break; + + case TIOCHWCGCURR: + if (put_user (&hwc_data.ioctls, (hwc_ioctls_t *) arg)) + goto fault; + break; +#endif + + default: + goto noioctlcmd; + } + + if (_IOC_DIR (cmd) == _IOC_WRITE) + retval = set_hwc_ioctls (&tmp, 0); + + goto out; + + fault: + retval = -EFAULT; + goto out; + noioctlcmd: + retval = -ENOIOCTLCMD; + out: + spin_unlock_irqrestore (&hwc_data.lock, flags); + return retval; +} diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/s390/char/hwc_rw.h linux/drivers/s390/char/hwc_rw.h --- v2.3.99-pre7/linux/drivers/s390/char/hwc_rw.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/s390/char/hwc_rw.h Fri May 12 11:41:44 2000 @@ -0,0 +1,113 @@ +/* + * drivers/s390/char/hwc_rw.h + * interface to the HWC-read/write driver + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Peschke + */ + +#ifndef __HWC_RW_H__ +#define __HWC_RW_H__ + +#include + +#ifndef __HWC_RW_C__ + +extern int hwc_init (void); + +extern int hwc_write (int from_user, const unsigned char *, unsigned int); + +extern unsigned int hwc_chars_in_buffer (unsigned char); + +extern unsigned int hwc_write_room (unsigned char); + +extern void hwc_flush_buffer (unsigned char); + +extern signed int hwc_ioctl (unsigned int, unsigned long); + +extern void do_hwc_interrupt (void); + +extern int hwc_printk (const char *,...); + +#else + +extern void store_hwc_input (unsigned char *, unsigned int); + +extern void wake_up_hwc_tty (void); + +#endif + +#define IN_HWCB 1 +#define IN_WRITE_BUF 2 +#define IN_BUFS_TOTAL (IN_HWCB | IN_WRITE_BUF) + +typedef unsigned short int ioctl_htab_t; +typedef unsigned char ioctl_echo_t; +typedef unsigned short int ioctl_cols_t; +typedef unsigned char ioctl_code_t; +typedef signed char ioctl_nl_t; +typedef unsigned short int ioctl_obuf_t; +typedef unsigned char ioctl_case_t; +typedef unsigned char ioctl_delim_t; + +typedef struct { + ioctl_htab_t width_htab; + ioctl_echo_t echo; + ioctl_cols_t columns; + ioctl_code_t code; + ioctl_nl_t final_nl; + ioctl_obuf_t max_hwcb; + ioctl_obuf_t kmem_hwcb; + ioctl_case_t tolower; + ioctl_delim_t delim; +} hwc_ioctls_t; + +static hwc_ioctls_t _hwc_ioctls; + +#define HWC_IOCTL_LETTER 'B' + +#define TIOCHWCSHTAB _IOW(HWC_IOCTL_LETTER, 0, _hwc_ioctls.width_htab) + +#define TIOCHWCSECHO _IOW(HWC_IOCTL_LETTER, 1, _hwc_ioctls.echo) + +#define TIOCHWCSCOLS _IOW(HWC_IOCTL_LETTER, 2, _hwc_ioctls.columns) + +#define TIOCHWCSCODE _IOW(HWC_IOCTL_LETTER, 3, _hwc_ioctls.code) + +#define TIOCHWCSNL _IOW(HWC_IOCTL_LETTER, 4, _hwc_ioctls.final_nl) + +#define TIOCHWCSOBUF _IOW(HWC_IOCTL_LETTER, 5, _hwc_ioctls.max_hwcb) + +#define TIOCHWCSINIT _IO(HWC_IOCTL_LETTER, 6) + +#define TIOCHWCSCASE _IOW(HWC_IOCTL_LETTER, 7, _hwc_ioctls.tolower) + +#define TIOCHWCSDELIM _IOW(HWC_IOCTL_LETTER, 9, _hwc_ioctls.delim) + +#define TIOCHWCGHTAB _IOR(HWC_IOCTL_LETTER, 10, _hwc_ioctls.width_htab) + +#define TIOCHWCGECHO _IOR(HWC_IOCTL_LETTER, 11, _hwc_ioctls.echo) + +#define TIOCHWCGCOLS _IOR(HWC_IOCTL_LETTER, 12, _hwc_ioctls.columns) + +#define TIOCHWCGCODE _IOR(HWC_IOCTL_LETTER, 13, _hwc_ioctls.code) + +#define TIOCHWCGNL _IOR(HWC_IOCTL_LETTER, 14, _hwc_ioctls.final_nl) + +#define TIOCHWCGOBUF _IOR(HWC_IOCTL_LETTER, 15, _hwc_ioctls.max_hwcb) + +#define TIOCHWCGINIT _IOR(HWC_IOCTL_LETTER, 16, _hwc_ioctls) + +#define TIOCHWCGCASE _IOR(HWC_IOCTL_LETTER, 17, _hwc_ioctls.tolower) + +#define TIOCHWCGDELIM _IOR(HWC_IOCTL_LETTER, 19, _hwc_ioctls.delim) + +#define TIOCHWCGKBUF _IOR(HWC_IOCTL_LETTER, 20, _hwc_ioctls.max_hwcb) + +#define TIOCHWCGCURR _IOR(HWC_IOCTL_LETTER, 21, _hwc_ioctls) + +#define CODE_ASCII 0x0 +#define CODE_EBCDIC 0x1 + +#endif diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/s390/char/hwc_tty.c linux/drivers/s390/char/hwc_tty.c --- v2.3.99-pre7/linux/drivers/s390/char/hwc_tty.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/s390/char/hwc_tty.c Fri May 12 11:41:44 2000 @@ -0,0 +1,265 @@ +/* + * drivers/s390/char/hwc_tty.c + * HWC line mode terminal driver. + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Peschke + * + * Thanks to Martin Schwidefsky. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "hwc_rw.h" + +#define HWC_TTY_PRINT_HEADER "hwc tty driver: " + +#define HWC_TTY_BUF_SIZE 512 + +typedef struct { + + struct tty_struct *tty; + + unsigned char buf[HWC_TTY_BUF_SIZE]; + + unsigned short int buf_count; + + spinlock_t lock; +} hwc_tty_data_struct; + +static hwc_tty_data_struct hwc_tty_data; +static struct tty_driver hwc_tty_driver; +static struct tty_struct *hwc_tty_table[1]; +static struct termios *hwc_tty_termios[1]; +static struct termios *hwc_tty_termios_locked[1]; +static int hwc_tty_refcount = 0; + +extern struct termios tty_std_termios; + +static int +hwc_tty_open (struct tty_struct *tty, + struct file *filp) +{ + + if (MINOR (tty->device) - tty->driver.minor_start) + return -ENODEV; + + tty->driver_data = &hwc_tty_data; + hwc_tty_data.buf_count = 0; + hwc_tty_data.tty = tty; + tty->low_latency = 0; + + return 0; +} + +void +wake_up_hwc_tty (void) +{ + if (hwc_tty_data.tty == NULL) + return; + if ((hwc_tty_data.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + hwc_tty_data.tty->ldisc.write_wakeup) + (hwc_tty_data.tty->ldisc.write_wakeup) (hwc_tty_data.tty); + wake_up_interruptible (&hwc_tty_data.tty->write_wait); +} + +static void +hwc_tty_close (struct tty_struct *tty, + struct file *filp) +{ + if (MINOR (tty->device) != tty->driver.minor_start) { + printk (KERN_WARNING HWC_TTY_PRINT_HEADER + "do not close hwc tty because of wrong device number"); + return; + } + hwc_tty_data.tty = NULL; +} + +static int +hwc_tty_write_room (struct tty_struct *tty) +{ + int retval; + + retval = hwc_write_room (IN_BUFS_TOTAL); + return retval; +} + +static int +hwc_tty_write (struct tty_struct *tty, + int from_user, + const unsigned char *buf, + int count) +{ + int retval; + + if (hwc_tty_data.buf_count > 0) { + hwc_write (0, hwc_tty_data.buf, hwc_tty_data.buf_count); + hwc_tty_data.buf_count = 0; + } + retval = hwc_write (from_user, buf, count); + return retval; +} + +static void +hwc_tty_put_char (struct tty_struct *tty, + unsigned char ch) +{ + unsigned long flags; + + spin_lock_irqsave (&hwc_tty_data.lock, flags); + if (hwc_tty_data.buf_count >= HWC_TTY_BUF_SIZE) { + hwc_write (0, hwc_tty_data.buf, hwc_tty_data.buf_count); + hwc_tty_data.buf_count = 0; + } + hwc_tty_data.buf[hwc_tty_data.buf_count] = ch; + hwc_tty_data.buf_count++; + spin_unlock_irqrestore (&hwc_tty_data.lock, flags); +} + +static void +hwc_tty_flush_chars (struct tty_struct *tty) +{ + unsigned long flags; + + spin_lock_irqsave (&hwc_tty_data.lock, flags); + hwc_write (0, hwc_tty_data.buf, hwc_tty_data.buf_count); + hwc_tty_data.buf_count = 0; + spin_unlock_irqrestore (&hwc_tty_data.lock, flags); +} + +static int +hwc_tty_chars_in_buffer (struct tty_struct *tty) +{ + int retval; + + retval = hwc_chars_in_buffer (IN_BUFS_TOTAL); + return retval; +} + +static void +hwc_tty_flush_buffer (struct tty_struct *tty) +{ + wake_up_hwc_tty (); +} + +static int +hwc_tty_ioctl ( + struct tty_struct *tty, + struct file *file, + unsigned int cmd, + unsigned long arg) +{ + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + + return hwc_ioctl (cmd, arg); +} + +void +store_hwc_input (unsigned char *buf, unsigned int count) +{ + struct tty_struct *tty = hwc_tty_data.tty; + + if (tty != NULL) { + + if (count == 2 && ( + /* hat is 0xb0 in codepage 037 (US etc.) and thus */ + /* converted to 0x5e in ascii ('^') */ + strncmp (buf, "^c", 2) == 0 || + /* hat is 0xb0 in several other codepages (German, */ + /* UK, ...) and thus converted to ascii octal 252 */ + strncmp (buf, "\0252c", 2) == 0)) { + tty->flip.count++; + *tty->flip.flag_buf_ptr++ = TTY_NORMAL; + *tty->flip.char_buf_ptr++ = INTR_CHAR (tty); + } else if (count == 2 && ( + strncmp (buf, "^d", 2) == 0 || + strncmp (buf, "\0252d", 2) == 0)) { + tty->flip.count++; + *tty->flip.flag_buf_ptr++ = TTY_NORMAL; + *tty->flip.char_buf_ptr++ = EOF_CHAR (tty); + } else if (count == 2 && ( + strncmp (buf, "^z", 2) == 0 || + strncmp (buf, "\0252z", 2) == 0)) { + tty->flip.count++; + *tty->flip.flag_buf_ptr++ = TTY_NORMAL; + *tty->flip.char_buf_ptr++ = SUSP_CHAR (tty); + } else { + + memcpy (tty->flip.char_buf_ptr, buf, count); + if (count < 2 || ( + strncmp (buf + count - 2, "^n", 2) || + strncmp (buf + count - 2, "\0252n", 2))) { + tty->flip.char_buf_ptr[count] = '\n'; + count++; + } else + count -= 2; + memset (tty->flip.flag_buf_ptr, TTY_NORMAL, count); + tty->flip.char_buf_ptr += count; + tty->flip.flag_buf_ptr += count; + tty->flip.count += count; + } + tty_flip_buffer_push (tty); + wake_up_hwc_tty (); + } +} + +void +hwc_tty_init (void) +{ + memset (&hwc_tty_driver, 0, sizeof (struct tty_driver)); + memset (&hwc_tty_data, 0, sizeof (hwc_tty_data_struct)); + hwc_tty_driver.magic = TTY_DRIVER_MAGIC; + hwc_tty_driver.driver_name = "tty_hwc"; + hwc_tty_driver.name = "ttyS"; + hwc_tty_driver.name_base = 0; + hwc_tty_driver.major = TTY_MAJOR; + hwc_tty_driver.minor_start = 64; + hwc_tty_driver.num = 1; + hwc_tty_driver.type = TTY_DRIVER_TYPE_SYSTEM; + hwc_tty_driver.subtype = SYSTEM_TYPE_TTY; + hwc_tty_driver.init_termios = tty_std_termios; + hwc_tty_driver.init_termios.c_iflag = IGNBRK | IGNPAR; + hwc_tty_driver.init_termios.c_oflag = ONLCR; + hwc_tty_driver.init_termios.c_lflag = ISIG | ECHO; + hwc_tty_driver.flags = TTY_DRIVER_REAL_RAW; + hwc_tty_driver.refcount = &hwc_tty_refcount; + + hwc_tty_driver.table = hwc_tty_table; + hwc_tty_driver.termios = hwc_tty_termios; + hwc_tty_driver.termios_locked = hwc_tty_termios_locked; + + hwc_tty_driver.open = hwc_tty_open; + hwc_tty_driver.close = NULL /* hwc_tty_close */ ; + hwc_tty_driver.write = hwc_tty_write; + hwc_tty_driver.put_char = hwc_tty_put_char; + hwc_tty_driver.flush_chars = hwc_tty_flush_chars; + hwc_tty_driver.write_room = hwc_tty_write_room; + hwc_tty_driver.chars_in_buffer = hwc_tty_chars_in_buffer; + hwc_tty_driver.flush_buffer = hwc_tty_flush_buffer; + hwc_tty_driver.ioctl = hwc_tty_ioctl; + + hwc_tty_driver.throttle = NULL; + hwc_tty_driver.unthrottle = NULL; + hwc_tty_driver.send_xchar = NULL; + hwc_tty_driver.set_termios = NULL; + hwc_tty_driver.set_ldisc = NULL; + hwc_tty_driver.stop = NULL; + hwc_tty_driver.start = NULL; + hwc_tty_driver.hangup = NULL; + hwc_tty_driver.break_ctl = NULL; + hwc_tty_driver.wait_until_sent = NULL; + hwc_tty_driver.read_proc = NULL; + hwc_tty_driver.write_proc = NULL; + + if (tty_register_driver (&hwc_tty_driver)) + panic ("Couldn't register hwc_tty driver\n"); +} diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/s390/misc/Makefile linux/drivers/s390/misc/Makefile --- v2.3.99-pre7/linux/drivers/s390/misc/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/s390/misc/Makefile Fri May 12 11:41:44 2000 @@ -0,0 +1,13 @@ +all: s390-misc.o + +CFLAFS += +O_TARGET := s390-misc.o +O_OBJS := +M_OBJS := + +ifeq ($(CONFIG_CHANDEV),y) + O_OBJS += chandev.o +endif + +include $(TOPDIR)/Rules.make + diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/s390/misc/chandev.c linux/drivers/s390/misc/chandev.c --- v2.3.99-pre7/linux/drivers/s390/misc/chandev.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/s390/misc/chandev.c Fri May 12 11:41:44 2000 @@ -0,0 +1,759 @@ +/* + * drivers/s390/misc/chandev.c + * common channel device layer + * + * S390 version + * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) + */ + +#define __KERNEL_SYSCALLS__ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static chandev_model_info *chandev_models_head=NULL; +static chandev *chandev_head=NULL; +static chandev_noauto_range *chandev_noauto_head=NULL; +static chandev_force *chandev_force_head=NULL; +static chandev_probelist *chandev_probelist_head=NULL; +static int use_devno_names=FALSE; +static int chandev_conf_read=FALSE; + +static void *chandev_alloc_listmember(list **listhead,size_t size) +{ + void *newmember=kmalloc(GFP_KERNEL,size); + if(newmember) + add_to_list(listhead,newmember); + return(newmember); +} + +void chandev_free_listmember(list **listhead,list *member) +{ + if(remove_from_list(listhead,member)) + kfree(member); + else + printk(KERN_CRIT"chandev_free_listmember detected nonexistant" + "listmember listhead=%p member %p\n",listhead,member); +} + +void chandev_free_all(list **listhead) +{ + while(*listhead) + chandev_free_listmember(listhead,*listhead); +} + +void chandev_add_model(chandev_type chan_type,u16 cu_type,u8 cu_model,u8 max_port_no) +{ + chandev_model_info *newmodel; + + if((newmodel=chandev_alloc_listmember( + (list **)&chandev_models_head,sizeof(chandev_model_info)))) + { + newmodel->chan_type=chan_type; + newmodel->cu_type=cu_type; + newmodel->cu_model=cu_model; + newmodel->max_port_no=max_port_no; + } +} + + +void chandev_remove(chandev *member) +{ + chandev_free_listmember((list **)&chandev_head,(list *)member); +} + + +void chandev_remove_all(void) +{ + chandev_free_all((list **)&chandev_head); +} + +void chandev_remove_model(chandev_model_info *model) +{ + chandev *curr_chandev; + for(curr_chandev=chandev_head;curr_chandev!=NULL; + curr_chandev=curr_chandev->next) + if(curr_chandev->model_info==model) + chandev_remove(curr_chandev); + chandev_free_listmember((list **)&chandev_models_head,(list *)model); +} + +void chandev_remove_all_models(void) +{ + while(chandev_models_head) + chandev_remove_model(chandev_models_head); +} + +void chandev_del_model(u16 cu_type,u8 cu_model) +{ + chandev_model_info *curr_model; + for(curr_model=chandev_models_head;curr_model!=NULL; + curr_model=curr_model->next) + if(curr_model->cu_type==cu_type&&curr_model->cu_model==cu_model) + chandev_remove_model(curr_model); +} + +static void chandev_init_default_models(void) +{ + /* P390/Planter 3172 emulation assume maximum 16 to be safe. */ + chandev_add_model(lcs,0x3088,0x1,15); + + /* 3172/2216 Paralell the 2216 allows 16 ports per card the */ + /* the original 3172 only allows 4 we will assume the max of 16 */ + chandev_add_model(lcs|ctc,0x3088,0x8,15); + + /* 3172/2216 Escon serial the 2216 allows 16 ports per card the */ + /* the original 3172 only allows 4 we will assume the max of 16 */ + chandev_add_model(lcs|escon,0x3088,0x1F,15); + + /* Only 2 ports allowed on OSA2 cards model 0x60 */ + chandev_add_model(lcs,0x3088,0x60,1); + + /* Osa-D we currently aren't too emotionally involved with this */ + chandev_add_model(osad,0x3088,0x62,0); +} + +void chandev_add(dev_info_t *newdevinfo,chandev_model_info *newmodelinfo) +{ + chandev *new_chandev; + + if((new_chandev=chandev_alloc_listmember( + (list **)&chandev_head,sizeof(chandev)))) + { + new_chandev->model_info=newmodelinfo; + new_chandev->devno=newdevinfo->devno; + new_chandev->irq=newdevinfo->irq; + } +} + + +void chandev_collect_devices(void) +{ + int curr_irq,loopcnt=0,err; + dev_info_t curr_devinfo; + chandev_model_info *curr_model; + + + for(curr_irq=get_irq_first();curr_irq>=0; curr_irq=get_irq_next(curr_irq)) + { + /* check read chandev + * we had to do the cu_model check also because ctc devices + * have the same cutype & after asking some people + * the model numbers are given out pseudo randomly so + * we can't just take a range of them also the dev_type & models are 0 + */ + loopcnt++; + if(loopcnt>0x10000) + { + printk(KERN_ERR"chandev_collect_devices detected infinite loop bug in get_irq_next\n"); + break; + } + if((err=get_dev_info_by_irq(curr_irq,&curr_devinfo))) + { + printk("chandev_collect_devices get_dev_info_by_irq reported err=%X on irq %d\n" + "should not happen\n",err,curr_irq); + continue; + } + for(curr_model=chandev_models_head;curr_model!=NULL; + curr_model=curr_model->next) + { + if((curr_model->cu_type==curr_devinfo.sid_data.cu_type)&& + (curr_model->cu_model==curr_devinfo.sid_data.cu_model) + &&((curr_devinfo.status&DEVSTAT_DEVICE_OWNED)==0)) + chandev_add(&curr_devinfo,curr_model); + } + } +} + +void chandev_add_force(chandev_type chan_type,s32 devif_num,u16 read_devno, +u16 write_devno,s16 port_no,u8 do_ip_checksumming,u8 use_hw_stats) + +{ + chandev_force *new_chandev_force; + + if((new_chandev_force=chandev_alloc_listmember( + (list **)&chandev_force_head,sizeof(chandev_force)))) + { + new_chandev_force->chan_type=chan_type; + new_chandev_force->devif_num=devif_num; + new_chandev_force->read_devno=read_devno; + new_chandev_force->write_devno=write_devno; + new_chandev_force->port_no=port_no; + new_chandev_force->do_ip_checksumming=do_ip_checksumming; + new_chandev_force->use_hw_stats=use_hw_stats; + } +} + +void chandev_del_force(u16 read_devno) +{ + chandev_force *curr_force; + for(curr_force=chandev_force_head;curr_force!=NULL; + curr_force=curr_force->next) + { + if(curr_force->read_devno==read_devno) + chandev_free_listmember((list **)&chandev_force_head, + (list *)curr_force); + } +} + +void chandev_pack_args(char *str) +{ + char *newstr=str; + while(*str) + { + if(isspace(*str)) + str++; + else + *newstr++=*str++; + } + *newstr=0; +} + +typedef enum +{ + isnull=0, + isstr=1, + isnum=2, + iscomma=4, +} chandev_strval; + +chandev_strval chandev_strcmp(char *teststr,char **str,long *endlong) +{ + char *cur=*str; + chandev_strval retval=isnull; + + int len=strlen(teststr); + if(strncmp(teststr,*str,len)==0) + { + *str+=len; + retval=isstr; + *endlong=simple_strtol(cur,str,0); + if(cur!=*str) + retval|=isnum; + if(**str==',') + retval|=iscomma; + } + return(retval); +} + +static char *argstrs[]= +{ + "noauto", + "lcs", + "ctc", + "escon", + "del_force", + "use_devno_names" + "dont_use_devno_names", + "add_model" + "del_model" + "del_all_models" +}; + +typedef enum +{ + stridx_mult=16, + first_stridx=0, + noauto_stridx=first_stridx, + lcs_stridx, + ctc_stridx, + escon_stridx, + del_force_stridx, + use_devno_names_stridx, + dont_use_devno_names_stridx, + add_model_stridx, + del_model_stridx, + del_all_models_stridx, + last_stridx, +} chandev_str_enum; + +void chandev_add_noauto(u16 lo_devno,u16 hi_devno) +{ + chandev_noauto_range *new_range; + + if((new_range=chandev_alloc_listmember( + (list **)&chandev_noauto_head,sizeof(chandev_noauto_range)))) + { + new_range->lo_devno=lo_devno; + new_range->hi_devno=hi_devno; + } +} + +static char chandev_keydescript[]= +"chan_type key bitfield\nctc=0x1,escon=0x2,lcs=0x4,lcs=0x4,osad=0x8,claw=0x16\n"; + +static void chandev_print_args(void) +{ + printk("valid chandev arguments are" + "<> indicate optional parameters | indicate a choice.\n"); + printk("noauto,,\n" + "don't probe a range of device numbers for channel devices\n"); + printk("lcs|ctc|escon,read_devno,write_devno,," + ",\n"); + printk("e.g. ctc0,0x7c00,0x7c01,-1,0,0\n"); + printk(" tells the channel layer to force ctc0 if detected to use\n" + " cuu's 7c00 & 7c01 port ( rel adapter no ) is invalid for\n" + " ctc's so use -1 don't do checksumming on received ip\n" + " packets & as ctc doesn't have hardware stats ignore this\n" + " parameter\n\n"); + printk("del_force read_devno\n" + "delete a forced channel device from force list.\n"); + printk("use_devno_names, tells the channel layer to assign device\n" + "names based on the read channel cuu number\n" + "e.g. a token ring read channel 0x7c00 would have an interface" + "called tr0x7c00 this avoids name collisions on devices."); + printk("add_model chan_type cu_model max_port no\n" + "tells the channel layer to probe for the device described\n"); + printk("%s use max_port_no of 0 for devices where this field " + "is invalid.\n",chandev_keydescript); + printk("del_model cu_type cu_model\n"); + printk("del_all_models\n"); +} + + +static int chandev_setup(char *str) +{ + chandev_strval val=isnull; + chandev_str_enum stridx; + long endlong; + chandev_type chan_type; +#define CHANDEV_MAX_EXTRA_INTS 5 + int ints[CHANDEV_MAX_EXTRA_INTS+1]; + memset(ints,0,sizeof(ints)); + chandev_pack_args(str); + for(stridx=first_stridx;stridx0) + { + curr+=len; + left-=len; + } + close(fd); + } + set_fs(USER_DS); + chandev_do_setup(buff,statbuf.st_size); + vfree(buff); + } + } + set_fs(USER_DS); +} + +void chandev_register_and_probe(chandev_probefunc probefunc,chandev_type chan_type) +{ + chandev_probelist *new_probe; + if(!chandev_conf_read) + chandev_read_conf(); + if((new_probe=chandev_alloc_listmember((list **)& + chandev_probelist_head,sizeof(chandev_probelist)))) + { + new_probe->probefunc=probefunc; + new_probe->chan_type=chan_type; + chandev_probe(); + } +} + +void chandev_unregister(chandev_probefunc probefunc) +{ + chandev_probelist *curr_probe=NULL; + + for(curr_probe=chandev_probelist_head;curr_probe!=NULL; + curr_probe=curr_probe->next) + { + if(curr_probe->probefunc==probefunc) + chandev_free_listmember((list **)&chandev_probelist_head, + (list *)curr_probe); + } +} + + +#ifdef CONFIG_PROC_FS +#define chandev_printf(exitchan,args...) \ +splen=sprintf(spbuff,##args); \ +spoffset+=splen; \ +if(spoffset>offset) { \ + spbuff+=splen; \ + currlen+=splen; \ +} \ +if(currlen>=length) \ + goto exitchan; + + + +static int chandev_read_proc(char *page, char **start, off_t offset, + int length, int *eof, void *data) +{ + char *spbuff=*start=page; + int currlen=0,splen; + off_t spoffset=0; + chandev_model_info *curr_model; + chandev_noauto_range *curr_noauto; + chandev_force *curr_force; + + + chandev_printf(chan_exit,"Channels enabled for detection\n"); + chandev_printf(chan_exit,"chan_type cu_type cu_model max_port_no\n"); + chandev_printf(chan_exit,"=================================================\n"); + for(curr_model=chandev_models_head;curr_model!=NULL; + curr_model=curr_model->next) + { + chandev_printf(chan_exit,"0x%02x 0x%04x 0x%02x %d\n", + curr_model->chan_type,(int)curr_model->cu_type, + (int)curr_model->cu_model,(int)curr_model->max_port_no); + } + + chandev_printf(chan_exit,"%s",chandev_keydescript); + chandev_printf(chan_exit,"No auto devno ranges\n"); + chandev_printf(chan_exit," From To \n"); + chandev_printf(chan_exit,"====================\n"); + for(curr_noauto=chandev_noauto_head;curr_noauto!=NULL; + curr_noauto=curr_noauto->next) + { + chandev_printf(chan_exit,"0x%4x 0x%4x\n", + curr_noauto->lo_devno, + curr_noauto->hi_devno); + } + chandev_printf(chan_exit,"\nForced devices\n"); + chandev_printf(chan_exit,"chan_type defif_num read_devno write_devno port_no ip_cksum hw_stats\n"); + chandev_printf(chan_exit,"====================================================================\n"); + for(curr_force=chandev_force_head;curr_force!=NULL; + curr_force=curr_force->next) + { + chandev_printf(chan_exit,"0x%2x %d 0x%4x 0x%4x %4d %1d %1d\n", + curr_force->chan_type,curr_force->devif_num, + curr_force->read_devno,curr_force->write_devno, + curr_force->port_no,curr_force->do_ip_checksumming, + curr_force->use_hw_stats); + } + *eof=TRUE; + chan_exit: + if(currlen>length) { + /* rewind to previous printf so that we are correctly + * aligned if we get called to print another page. + */ + currlen-=splen; + } + return(currlen); +} + + +static int chandev_write_proc(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + int rc; + char *buff; + + buff=vmalloc(count+1); + if(buff) + { + rc = copy_from_user(buff,buffer,count); + if (rc) + goto chandev_write_exit; + chandev_do_setup(buff,count); + rc=count; + chandev_write_exit: + vfree(buff); + return rc; + } + else + return -ENOMEM; + return(0); +} + +static void __init chandev_create_proc(void) +{ + struct proc_dir_entry *dir_entry= + create_proc_entry("chandev",0644, + &proc_root); + if(dir_entry) + { + dir_entry->read_proc=&chandev_read_proc; + dir_entry->write_proc=&chandev_write_proc; + } +} + + +#endif +static int __init chandev_init(void) +{ + chandev_init_default_models(); +#if CONFIG_PROC_FS + chandev_create_proc(); +#endif + return(0); +} +__initcall(chandev_init); + + + + + + + diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/s390/net/Makefile linux/drivers/s390/net/Makefile --- v2.3.99-pre7/linux/drivers/s390/net/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/s390/net/Makefile Fri May 12 11:41:44 2000 @@ -0,0 +1,16 @@ +all: s390-net.o + +CFLAFS += +O_TARGET := s390-net.o +O_OBJS := +M_OBJS := + +ifeq ($(CONFIG_CTC),y) + O_OBJS += ctc.o +endif + +ifeq ($(CONFIG_IUCV),y) + O_OBJS += iucv.o +endif + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/s390/net/ctc.c linux/drivers/s390/net/ctc.c --- v2.3.99-pre7/linux/drivers/s390/net/ctc.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/s390/net/ctc.c Fri May 12 11:41:44 2000 @@ -0,0 +1,1581 @@ +/* + * drivers/s390/net/ctc.c + * CTC / ESCON network driver + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Dieter Wellerdiek (wel@de.ibm.com) + * + * 2.3 Updates Martin Schwidefsky (schwidefsky@de.ibm.com) + * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) + * + * + * Description of the Kernel Parameter + * Normally the CTC driver selects the channels in order (automatic channel + * selection). If your installation needs to use the channels in a different + * order or doesn't want to have automatic channel selection on, you can do + * this with the "ctc= kernel keyword". + * + * ctc=0,0xrrrr,0xwwww,ddddd + * + * Where: + * + * "rrrr" is the read channel address + * "wwww" is the write channel address + * "dddd" is the network device (ctc0 to ctc7 for a parallel channel, escon0 + * to escon7 for ESCON channels). + * + * To switch the automatic channel selection off use the ctc= keyword with + * parameter "noauto". This may be necessary if you 3271 devices or other devices + * which use the ctc device type and model, but operate with a different protocol. + * + * ctc=noauto + * + * Change History + * 0.50 Initial release shipped + * 0.51 Bug fixes + * - CTC / ESCON network device can now handle up to 64 channels + * - 3088-61 info message supperssed - CISCO 7206 - CLAW - ESCON + * - 3088-62 info message suppressed - OSA/D + * - channel: def ffffffed ... error message suppressed + * - CTC / ESCON device was not recoverable after a lost connection with + * IFCONFIG dev DOWN and IFCONFIG dev UP + * - Possibility to switch the automatic selection off + * - Minor bug fixes + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + + +//#define DEBUG + +/* Redefine message level, so that all messages occur on 3215 console in DEBUG mode */ +#ifdef DEBUG + #undef KERN_INFO + #undef KERN_WARNING + #undef KERN_DEBUG + #define KERN_INFO KERN_EMERG + #define KERN_WARNING KERN_EMERG + #define KERN_DEBUG KERN_EMERG +#endif +//#undef DEBUG + +#define CCW_CMD_WRITE 0x01 +#define CCW_CMD_READ 0x02 +#define CCW_CMD_SET_EXTENDED 0xc3 +#define CCW_CMD_PREPARE 0xe3 + +#define MAX_CHANNEL_DEVICES 64 +#define MAX_ADAPTERS 8 +#define CTC_DEFAULT_MTU_SIZE 1500 +#define READ 0 +#define WRITE 1 +#define CTC 0 +#define ESCON 1 +#define CHANNEL_MEDIA 2 +#define CTC_BLOCKS 8 /* 8 blocks * 2 times * 64k = 1M */ + +#define TB_TX 0 /* sk buffer handling in process */ +#define TB_STOP 1 /* network device stop in process */ +#define TB_RETRY 2 /* retry in process */ +#define TB_NOBUFFER 3 /* no buffer on free queue */ + +/* state machine codes used in ctc_irq_handler */ +#define CTC_STOP 0 +#define CTC_START_HALT_IO 1 +#define CTC_START_SET_X_MODE 2 +#define CTC_START_SELECT 4 +#define CTC_START_READ_TEST 32 +#define CTC_START_READ 33 +#define CTC_START_WRITE_TEST 64 +#define CTC_START_WRITE 65 + + +typedef enum { + channel_type_none, /* Device is not a channel */ + channel_type_undefined, /* Device is a channel but we don't know anything about it */ + channel_type_ctca, /* Device is a CTC/A and we can deal with it */ + channel_type_escon, /* Device is a ESCON channel and we can deal with it */ + channel_type_unsupported /* Device is a unsupported model */ +} channel_type_t; + + + +/* + * Structures needed in the initial phase + * + */ + +static int channel_tab_initialized = 0; /* channel[] structure initialized */ + +struct devicelist { + unsigned int devno; + __u8 flag; +#define CHANNEL_IN_USE 0x08 /* - Show that channel is in use */ +}; + +static struct { + struct devicelist list[MAX_CHANNEL_DEVICES]; + int count; + int left; +} channel[CHANNEL_MEDIA]; + + + +static int ctc_no_auto = 0; + +struct adapterlist{ + unsigned int devno[2]; + __u16 protocol; +}; + +static struct adapterlist ctc_adapter[CHANNEL_MEDIA][MAX_ADAPTERS]; /* 0 = CTC / 1 = ESCON */ + + +/* + * Structure used after the initial phase + * + */ + +struct buffer { + struct buffer *next; + int packets; + struct block *block; +}; + +#if LINUX_VERSION_CODE>=0x020300 +typedef struct net_device net_device; +#else +typedef struct device net_device; +typedef struct wait_queue* wait_queue_head_t; +#define DECLARE_WAITQUEUE(waitqname,waitqtask) struct wait_queue waitqname = {waitqtask, NULL } +#define init_waitqueue_head(nothing) +#endif + + +struct channel { + unsigned int devno; + int irq; + unsigned long IO_active; + ccw1_t ccw[3]; + __u32 state; + int buffer_count; + struct buffer *free_anchor; + struct buffer *proc_anchor; + devstat_t *devstat; + net_device *dev; /* backward pointer to the network device */ + wait_queue_head_t wait; + struct tq_struct tq; + struct timer_list timer; + unsigned long flag_a; /* atomic flags */ +#define CTC_BH_ACTIVE 0 + __u8 last_dstat; + __u8 flag; +#define CTC_WRITE 0x01 /* - Set if this is a write channel */ +#define CTC_TIMER 0x80 /* - Set if timer made the wake_up */ +}; + + +struct ctc_priv { + struct net_device_stats stats; +#if LINUX_VERSION_CODE>=0x02032D + int tbusy; +#endif + struct channel channel[2]; + __u16 protocol; +}; + +/* + * This structure works as shuttle between two systems + * - A block can contain one or more packets + */ + +#define PACKET_HEADER_LENGTH 6 +struct packet { + __u16 length; + __u16 type; + __u16 unused; + __u8 data; +}; + +#define BLOCK_HEADER_LENGTH 2 +struct block { + __u16 length; + struct packet data; +}; + +#if LINUX_VERSION_CODE>=0x02032D +#define ctc_protect_busy(dev) \ +s390irq_spin_lock(((struct ctc_priv *)dev->priv)->channel[WRITE].irq) +#define ctc_unprotect_busy(dev) \ +s390irq_spin_unlock(((struct ctc_priv *)dev->priv)->channel[WRITE].irq) + +#define ctc_protect_busy_irqsave(dev,flags) \ +s390irq_spin_lock_irqsave(((struct ctc_priv *)dev->priv)->channel[WRITE].irq,flags) +#define ctc_unprotect_busy_irqrestore(dev,flags) \ +s390irq_spin_unlock_irqrestore(((struct ctc_priv *)dev->priv)->channel[WRITE].irq,flags) + +static __inline__ void ctc_set_busy(net_device *dev) +{ + ((struct ctc_priv *)dev->priv)->tbusy=1; + netif_stop_queue(dev); +} + +static __inline__ void ctc_clear_busy(net_device *dev) +{ + ((struct ctc_priv *)dev->priv)->tbusy=0; + netif_start_queue(dev); +} + +static __inline__ int ctc_check_busy(net_device *dev) +{ + eieio(); + return(((struct ctc_priv *)dev->priv)->tbusy); +} + + +static __inline__ void ctc_setbit_busy(int nr,net_device *dev) +{ + set_bit(nr,&(((struct ctc_priv *)dev->priv)->tbusy)); + netif_stop_queue(dev); +} + +static __inline__ void ctc_clearbit_busy(int nr,net_device *dev) +{ + clear_bit(nr,&(((struct ctc_priv *)dev->priv)->tbusy)); + if(((struct ctc_priv *)dev->priv)->tbusy==0) + netif_start_queue(dev); +} + +static __inline__ int ctc_test_and_setbit_busy(int nr,net_device *dev) +{ + netif_stop_queue(dev); + return(test_and_set_bit(nr,&((struct ctc_priv *)dev->priv)->tbusy)); +} +#else + +#define ctc_protect_busy(dev) +#define ctc_unprotect_busy(dev) +#define ctc_protect_busy_irqsave(dev,flags) +#define ctc_unprotect_busy_irqrestore(dev,flags) + +static __inline__ void ctc_set_busy(net_device *dev) +{ + dev->tbusy=1; + eieio(); +} + +static __inline__ void ctc_clear_busy(net_device *dev) +{ + dev->tbusy=0; + eieio(); +} + +static __inline__ int ctc_check_busy(net_device *dev) +{ + eieio(); + return(dev->tbusy); +} + + +static __inline__ void ctc_setbit_busy(int nr,net_device *dev) +{ + set_bit(nr,(void *)&dev->tbusy); +} + +static __inline__ void ctc_clearbit_busy(int nr,net_device *dev) +{ + clear_bit(nr,(void *)&dev->tbusy); +} + +static __inline__ int ctc_test_and_setbit_busy(int nr,net_device *dev) +{ + return(test_and_set_bit(nr,(void *)&dev->tbusy)); +} +#endif + + + + + +/* Interrupt handler */ +static void ctc_irq_handler(int irq, void *initparm, struct pt_regs *regs); +static void ctc_irq_bh(struct channel *ctc); +static void ctc_read_retry (struct channel *ctc); +static void ctc_write_retry (struct channel *ctc); + + +/* Functions for the DEV methods */ +int ctc_probe(net_device *dev); + + +static int ctc_open(net_device *dev); +static void ctc_timer (struct channel *ctc); +static int ctc_release(net_device *dev); +static int ctc_tx(struct sk_buff *skb, net_device *dev); +static int ctc_change_mtu(net_device *dev, int new_mtu); +struct net_device_stats* ctc_stats(net_device *dev); + + +/* + * Channel Routines + * + */ + +static void channel_init(void); +static void channel_scan(void); +static int channel_get(int media, int devno); +static int channel_get_next(int media); +static int channel_free(int media, int devno); +static channel_type_t channel_check_for_type (senseid_t *id); +static void channel_sort(struct devicelist list[], int n); + + +/* + * initialize the channel[].list + */ +static void channel_init(void) +{ + int m; +#ifdef DEBUG + int c; +#endif + + if (!test_and_set_bit(0, (void *)& channel_tab_initialized)){ + channel_scan(); + for (m = 0; m < CHANNEL_MEDIA; m++) { + channel_sort (channel[m].list, MAX_CHANNEL_DEVICES); + channel[m].left = channel[m].count; + } + if (channel[CTC].count == 0 && channel[ESCON].count == 0) + printk(KERN_INFO "channel: no Channel devices recognized\n"); + else + printk(KERN_INFO "channel: %d Parallel channel found - %d ESCON channel found\n", + channel[CTC].count, channel[ESCON].count); +#ifdef DEBUG + for (m = 0; m < CHANNEL_MEDIA; m++) { + for (c = 0; c < MAX_CHANNEL_DEVICES; c++){ + printk(KERN_DEBUG "channel: Adapter=%x Entry=%x devno=%04x\n", + m, c, channel[m].list[c].devno); + } + } +#endif + } +} + + +/* +* scan for all channels and put the device numbers into the channel[].list +*/ +static void channel_scan(void) +{ + int m; + int c; + int irq; + dev_info_t temp; + + for (m = 0; m < CHANNEL_MEDIA; m++) { + for (c = 0; c < MAX_CHANNEL_DEVICES; c++){ + channel[m].list[c].devno = -ENODEV; + } + } + + for (irq = 0; irq < NR_IRQS; irq++) { + /* CTC/A */ + if (channel[CTC].count < MAX_CHANNEL_DEVICES ) { + if (get_dev_info(irq, &temp) == 0 && + channel_check_for_type(&temp.sid_data) == channel_type_ctca) { + channel[CTC].list[channel[CTC].count].devno = temp.devno; + channel[CTC].count++; + } + } + + /* ESCON */ + if (channel[ESCON].count < MAX_CHANNEL_DEVICES ) { + if (get_dev_info(irq, &temp) == 0 && + channel_check_for_type(&temp.sid_data) == channel_type_escon) { + channel[ESCON].list[channel[ESCON].count].devno = temp.devno; + channel[ESCON].count++; + + } + } + } +} + + +/* + * free specific channel from the channel[].list + */ +static int channel_free(int media, int devno) +{ + int i; + + for (i = 0; i < channel[media].count; i++) { + if ((devno == channel[media].list[i].devno) && + ((channel[media].list[i].flag & CHANNEL_IN_USE) != 0x00)) { + channel[media].list[i].flag &= ~CHANNEL_IN_USE; + return 0; + } + } + printk(KERN_WARNING "channel: dev %04x is not a channel or in use\n", devno); + return -ENODEV; +} + + +/* + * get specific channel from the channel[].list + */ +static int channel_get(int media, int devno) +{ + int i; + + for (i = 0; i < channel[media].count; i++) { + if ((devno == channel[media].list[i].devno) && + ((channel[media].list[i].flag & CHANNEL_IN_USE) == 0x00)) { + channel[media].list[i].flag |= CHANNEL_IN_USE; + return channel[media].list[i].devno; + } + } + printk(KERN_WARNING "channel: dev %04x is not a channel or in use\n", devno); + return -ENODEV; + +} + + +/* + * get the next free channel from the channel[].list + */ +static int channel_get_next(int media) +{ + int i; + + for (i = 0; i < channel[media].count; i++) { + if ((channel[media].list[i].flag & CHANNEL_IN_USE) == 0x00) { +#ifdef DEBUG + printk(KERN_DEBUG "channel: picked=%04x\n", channel[media].list[i].devno); +#endif + channel[media].list[i].flag |= CHANNEL_IN_USE; + return channel[media].list[i].devno; + } + } + return -ENODEV; +} + + +/* + * picks the next free channel from the channel[].list + */ +static int channel_left(int media) +{ + return channel[media].left; +} + + +/* + * defines all devices which are channels + */ +static channel_type_t channel_check_for_type (senseid_t *id) + { + channel_type_t type; + + switch (id->cu_type) { + case 0x3088: + + switch (id->cu_model) { + case 0x08: + type = channel_type_ctca; /* 3088-08 ==> CTCA */ + break; + + case 0x1F: + type = channel_type_escon; /* 3088-1F ==> ESCON channel */ + break; + + case 0x01: /* 3088-01 ==> P390 OSA emulation */ + case 0x60: /* 3088-60 ==> OSA/2 adapter */ + case 0x61: /* 3088-61 ==> CISCO 7206 CLAW protocol ESCON connected */ + case 0x62: /* 3088-62 ==> OSA/D device */ + type = channel_type_unsupported; + break; + + default: + type = channel_type_undefined; + printk(KERN_INFO "channel: Unknown model found 3088-%02x\n",id->cu_model); + } + break; + + default: + type = channel_type_none; + + } + return type; +} + + +/* + * sort the channel[].list + */ +static void channel_sort(struct devicelist list[], int n) +{ + int i; + int sorted = 0; + struct devicelist tmp; + + while (!sorted) { + sorted = 1; + + for (i = 0; i < n-1; i++) { + if (list[i].devno > list[i+1].devno) { + tmp = list[i]; + list[i] = list[i+1]; + list[i+1] = tmp; + sorted = 0; + } + } + } +} + + +/* + * General routines + * + */ + +static int inline extract_channel_id(char *name) +{ + if (name[0] == 'c') + return (name[3]-'0'); + else + return (name[5]-'0'); +} + + +static int inline extract_channel_media(char *name) +{ + if (name[0] == 'c') + return CTC; + else + return ESCON; +} + + +static void ctc_tab_init(void) +{ + int m; + int i; + static int t; + + if (t == 0){ + for (m = 0; m < CHANNEL_MEDIA; m++) { + for (i = 0; i < MAX_ADAPTERS; i++) { + ctc_adapter[m][i].devno[WRITE] = -ENODEV; + ctc_adapter[m][i].devno[READ] = -ENODEV; + } + } + t = 1; + } +} + + +static int ctc_buffer_alloc(struct channel *ctc) { + + struct buffer *p; + struct buffer *q; + + p = kmalloc(sizeof(p), GFP_KERNEL); + if (p == NULL) + return -ENOMEM; + else { + p->next = NULL; + p->packets = 0; + p->block = (struct block *) __get_free_pages(GFP_KERNEL+GFP_DMA, 4); + if (p->block == NULL) { + kfree(p); + return -ENOMEM; + } + } + + if (ctc->free_anchor == NULL) + ctc->free_anchor = p; + else { + q = ctc->free_anchor; + while (q->next != NULL) + q = q->next; + q->next = p; + } + ctc->buffer_count++; + return 0; +} + + +static int ctc_buffer_free(struct channel *ctc) { + + struct buffer *p; + + + if (ctc->free_anchor == NULL) + return -ENOMEM; + + p = ctc->free_anchor; + ctc->free_anchor = p->next; + free_pages((__u32)p->block, 4); + kfree(p); + + return 0; +} + + +static int inline ctc_buffer_swap(struct buffer **from, struct buffer **to) { + + struct buffer *p = NULL; + struct buffer *q = NULL; + + if (*from == NULL) + return -ENOMEM; + + p = *from; + *from = p->next; + p->next = NULL; + + if (*to == NULL) + *to = p; + else { + q = *to; + while (q->next != NULL) + q = q->next; + q->next = p; + + } + return 0; +} + + +/* + * ctc_setup function + * this function is called for each ctc= keyword passed into the kernel + * + * valid parameter are: ctc=n,0xnnnn,0xnnnn,ctcx + * where n is the channel protocol always 0 + * 0xnnnn is the cu number read + * 0xnnnn is the cu number write + * ctcx can be ctc0 to ctc7 or escon0 to escon7 + */ +#if LINUX_VERSION_CODE>=0x020300 +static int __init ctc_setup(char *dev_name) +#else +__initfunc(void ctc_setup(char *dev_name,int *ints)) +#endif +{ + struct adapterlist tmp; +#if LINUX_VERSION_CODE>=0x020300 + #define CTC_MAX_PARMS 4 + int ints[CTC_MAX_PARMS+1]; + get_options(dev_name,CTC_MAX_PARMS,ints); + #define ctc_setup_return return(1) +#else + #define ctc_setup_return return +#endif + ctc_tab_init(); + + ctc_no_auto = 1; + + if (!strcmp(dev_name,"noauto")) { + printk(KERN_INFO "ctc: automatic channel selection deactivated\n"); + ctc_setup_return; + } + + tmp.devno[WRITE] = -ENODEV; + tmp.devno[READ] = -ENODEV; + + switch (ints[0]) { + + case 3: /* write channel passed */ + tmp.devno[WRITE] = ints[3]; + + case 2: /* read channel passed */ + tmp.devno[READ] = ints[2]; + if (tmp.devno[WRITE] == -ENODEV) + tmp.devno[WRITE] = tmp.devno[READ] + 1; + + case 1: /* protocol type passed */ + tmp.protocol = ints[1]; + if (tmp.protocol == 0) { + break; + } else { + printk(KERN_WARNING "%s: wrong Channel protocol type passed\n", dev_name); + ctc_setup_return; + } + break; + + default: + printk(KERN_WARNING "ctc: wrong number of parameter passed\n"); + ctc_setup_return; + } + ctc_adapter[extract_channel_media(dev_name)][extract_channel_id(dev_name)] = tmp; +#ifdef DEBUG + printk(DEBUG "%s: protocol=%x read=%04x write=%04x\n", + dev_name, tmp.protocol, tmp.devno[READ], tmp.devno[WRITE]); +#endif + ctc_setup_return; + +} +#if LINUX_VERSION_CODE>=0x020300 +__setup("ctc=", ctc_setup); +#endif + +/* + * ctc_probe + * this function is called for each channel network device, + * which is defined in the /init/main.c + */ +int ctc_probe(net_device *dev) +{ + int rc; + int c; + int i; + int m; + + struct ctc_priv *privptr; + + /* Only the first time the ctc_probe gets control */ + if (channel_tab_initialized == 0) { + channel_init(); + + + } + + ctc_tab_init(); + + m = extract_channel_media(dev->name); + i = extract_channel_id(dev->name); + + if (channel_left(m) <=1) + return -ENODEV; + + if (ctc_no_auto == 1 && (ctc_adapter[m][i].devno[READ] == -ENODEV || ctc_adapter[m][i].devno[WRITE] == -ENODEV)) + return -ENODEV; + + dev->priv = kmalloc(sizeof(struct ctc_priv), GFP_KERNEL); + if (dev->priv == NULL) + return -ENOMEM; + memset(dev->priv, 0, sizeof(struct ctc_priv)); + privptr = (struct ctc_priv *) (dev->priv); + + + for (c = 0; c < 2; c++) { + + privptr->channel[c].devstat = kmalloc(sizeof(devstat_t), GFP_KERNEL); + if (privptr->channel[c].devstat == NULL){ + if (i == WRITE) + kfree(privptr->channel[READ].devstat); + return -ENOMEM; + } + memset(privptr->channel[c].devstat, 0, sizeof(devstat_t)); + + if (ctc_no_auto == 0) + ctc_adapter[m][i].devno[c] = channel_get_next(m); + else + ctc_adapter[m][i].devno[c] = channel_get(m, ctc_adapter[m][i].devno[c]); + + if ( ctc_adapter[m][i].devno[c] != -ENODEV){ + rc = request_irq(get_irq_by_devno(ctc_adapter[m][i].devno[c]), + (void *)ctc_irq_handler, SA_INTERRUPT, dev->name, + privptr->channel[c].devstat); + if (rc) { + printk(KERN_WARNING "%s: requested device busy %02x\n", dev->name, rc); + return -EBUSY; + } + } else { + if (i == WRITE) { + free_irq(get_irq_by_devno(ctc_adapter[m][i].devno[c]), privptr->channel[i].devstat); + channel_free(m, ctc_adapter[m][i].devno[READ]); + kfree(privptr->channel[READ].devstat); + } + kfree(privptr->channel[i].devstat); + return -ENODEV; + } + } + + privptr->channel[READ].devno = ctc_adapter[m][i].devno[READ]; + privptr->channel[READ].irq = get_irq_by_devno(ctc_adapter[m][i].devno[READ]); + privptr->channel[WRITE].devno = ctc_adapter[m][i].devno[WRITE]; + privptr->channel[WRITE].irq = get_irq_by_devno(ctc_adapter[m][i].devno[WRITE]); + privptr->protocol = ctc_adapter[m][i].protocol; + channel[m].left = channel[m].left - 2; + + printk(KERN_INFO "%s: read dev: %04x irq: %04x - write dev: %04x irq: %04x \n", + dev->name, privptr->channel[READ].devno, privptr->channel[READ].irq, + privptr->channel[WRITE].devno, privptr->channel[WRITE].irq); + + dev->mtu = CTC_DEFAULT_MTU_SIZE; + dev->hard_start_xmit = ctc_tx; + dev->open = ctc_open; + dev->stop = ctc_release; + dev->get_stats = ctc_stats; + dev->change_mtu = ctc_change_mtu; + dev->hard_header_len = 0; + dev->addr_len = 0; + dev->type = ARPHRD_SLIP; + dev->tx_queue_len = 100; + dev_init_buffers(dev); + dev->flags = IFF_POINTOPOINT | IFF_NOARP; + + return 0; +} + + +/* + * Interrupt processing + * + */ + +static void inline ccw_check_return_code (net_device *dev, int return_code) +{ + if (return_code != 0) { + switch (return_code) { + case -EBUSY: + printk(KERN_INFO "%s: Busy !\n", dev->name); + break; + case -ENODEV: + printk(KERN_EMERG "%s: Invalid device called for IO\n", dev->name); + break; + case -EIO: + printk(KERN_EMERG "%s: Status pending... \n", dev->name); + break; + default: + printk(KERN_EMERG "%s: Unknown error in Do_IO %04x\n", + dev->name, return_code); + } + } +} + + +static void inline ccw_check_unit_check (net_device *dev, char sense) +{ +#ifdef DEBUG + printk(KERN_INFO "%s: Unit Check with sense code: %02x\n", + dev->name, sense); +#endif + + if (sense & 0x40) { +#ifdef DEBUG + if (sense & 0x01) + printk(KERN_DEBUG "%s: Interface disconnect or Selective reset occurred (remote side)\n", dev->name); + else + printk(KERN_DEBUG "%s: System reset occured (remote side)\n", dev->name); +#endif + } else if (sense & 0x20) { + if (sense & 0x04) + printk(KERN_WARNING "%s: Data-streaming timeout)\n", dev->name); + else + printk(KERN_WARNING "%s: Data-transfer parity error\n", dev->name); + } else if (sense & 0x10) { + if (sense & 0x20) + printk(KERN_WARNING "%s: Hardware malfunction (remote side)\n", dev->name); + else + printk(KERN_WARNING "%s: Read-data parity error (remote side)\n", dev->name); + } + +} + + +static void ctc_irq_handler (int irq, void *initparm, struct pt_regs *regs) +{ + int rc = 0; + __u32 parm; + __u8 flags = 0x00; + struct channel *ctc = NULL; + struct ctc_priv *privptr = NULL; + net_device *dev = NULL; + + ccw1_t ccw_set_x_mode[2] = {{CCW_CMD_SET_EXTENDED, CCW_FLAG_SLI | CCW_FLAG_CC, 0, NULL}, + {CCW_CMD_NOOP, CCW_FLAG_SLI, 0, NULL}}; + + devstat_t *devstat = ((devstat_t *)initparm); + + /* Bypass all 'unsolited interrupts' */ + if (devstat->intparm == 0) { +#ifdef DEBUG + printk(KERN_DEBUG "ctc: unsolited interrupt for device: %04x received c-%02x d-%02x f-%02x\n", + devstat->devno, devstat->cstat, devstat->dstat, devstat->flag); +#endif + /* FIXME - find the related intparm!!! No IO outstanding!!!! */ + return; + } + + ctc = (struct channel *) (devstat->intparm); + dev = (net_device *) ctc->dev; + privptr = dev->priv; + +#ifdef DEBUG + printk(KERN_DEBUG "%s: interrupt for device: %04x received c-%02x d-%02x f-%02x state-%02x\n", + dev->name, ctc->devno, devstat->cstat, devstat->dstat, devstat->flag, ctc->state); +#endif + + /* Check for good subchannel return code, otherwise error message */ + if (devstat->cstat) { + printk(KERN_WARNING "%s: subchannel check for device: %04x - %02x\n", + dev->name, ctc->devno, devstat->cstat); + return; + } + + + /* Check the reason-code of a unit check */ + if (devstat->dstat & DEV_STAT_UNIT_CHECK) + ccw_check_unit_check(dev, devstat->ii.sense.data[0]); + + + /* State machine to bring the connection up / down and to restart */ + + ctc->last_dstat = devstat->dstat; + + switch (ctc->state) { + + case CTC_STOP: /* HALT_IO issued by ctc_release (halt sequence) */ + if (!devstat->flag & DEVSTAT_FINAL_STATUS) + return; + wake_up(&ctc->wait); /* wake up ctc_release */ + return; + + + case CTC_START_HALT_IO: /* HALT_IO issued by ctc_open (start sequence) */ + if (!devstat->flag & DEVSTAT_FINAL_STATUS) + return; + + ctc->state = CTC_START_SET_X_MODE; + parm = (__u32) ctc; + rc = do_IO (ctc->irq, &ccw_set_x_mode[0], parm, 0xff, flags); + if (rc != 0) + ccw_check_return_code(dev, rc); + return; + + + case CTC_START_SET_X_MODE: + if (devstat->dstat & DEV_STAT_UNIT_CHECK) { + if ((devstat->ii.sense.data[0] & 0x41) != 0x41 || + (devstat->ii.sense.data[0] & 0x40) != 0x40) { + wake_up(&ctc->wait); /* wake up ctc_open (READ or WRITE) */ + return; + } + } + if (!devstat->flag & DEVSTAT_FINAL_STATUS) + return; + ctc->state = CTC_START_SELECT; + + + case CTC_START_SELECT: + if (!ctc->flag & CTC_WRITE) { + ctc->state = CTC_START_READ_TEST; + ctc->ccw[1].cda = (char *)virt_to_phys(ctc->free_anchor->block); + parm = (__u32) ctc; + rc = do_IO (ctc->irq, &ctc->ccw[0], parm, 0xff, flags ); + if (rc != 0) + ccw_check_return_code(dev, rc); + wake_up(&ctc->wait); /* wake up ctc_open (READ) */ + + } else { + ctc->state = CTC_START_WRITE_TEST; + /* ADD HERE THE RIGHT PACKET TO ISSUE A ROUND TRIP - PART 1 */ + ctc->ccw[1].count = 0; + ctc->ccw[1].cda = (char *)virt_to_phys(ctc->free_anchor->block); + parm = (__u32) ctc; + rc = do_IO (ctc->irq, &ctc->ccw[0], parm, 0xff, flags); + if (rc != 0) + ccw_check_return_code(dev, rc); + } + return; + + + case CTC_START_READ_TEST: + if (devstat->dstat & DEV_STAT_UNIT_CHECK) { + if ((devstat->ii.sense.data[0] & 0x41) == 0x41 || + (devstat->ii.sense.data[0] & 0x40) == 0x40 || + devstat->ii.sense.data[0] == 0 ) { + init_timer(&ctc->timer); + ctc->timer.function = (void *)ctc_read_retry; + ctc->timer.data = (__u32)ctc; + ctc->timer.expires = jiffies + 10*HZ; + add_timer(&ctc->timer); +#ifdef DEBUG + printk(KERN_DEBUG "%s: read connection restarted\n",dev->name); +#endif + } + return; + } + + if ((devstat->dstat & ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) != 0x00) { + if ((devstat->dstat & DEV_STAT_ATTENTION) && + (devstat->dstat & DEV_STAT_BUSY)) { + printk(KERN_WARNING "%s: read channel is connected with the remote side read channel\n", dev->name); + } + wake_up(&privptr->channel[WRITE].wait); /* wake up ctc_open (WRITE) */ + return; + } + + ctc->state = CTC_START_READ; + set_bit(0, (void *)&ctc->IO_active); + + /* ADD HERE THE RIGHT PACKET TO ISSUE A ROUND TRIP - PART 2 */ + /* wake_up(&privptr->channel[WRITE].wait);*/ /* wake up ctc_open (WRITE) */ + + + case CTC_START_READ: + if (devstat->dstat & DEV_STAT_UNIT_CHECK) { + if ((devstat->ii.sense.data[0] & 0x41) == 0x41 || + (devstat->ii.sense.data[0] & 0x40) == 0x40 || + devstat->ii.sense.data[0] == 0 ) { + privptr->stats.rx_errors++; + /* Need protection here cos we are in the read irq */ + /* handler the tbusy is for the write subchannel */ + ctc_protect_busy(dev); + ctc_setbit_busy(TB_RETRY,dev); + ctc_unprotect_busy(dev); + init_timer(&ctc->timer); + ctc->timer.function = (void *)ctc_read_retry; + ctc->timer.data = (__u32)ctc; + ctc->timer.expires = jiffies + 30*HZ; + add_timer(&ctc->timer); + printk(KERN_INFO "%s: connection restarted!! problem on remote side\n",dev->name); + } + return; + } + + if(!devstat->flag & DEVSTAT_FINAL_STATUS) + return; + ctc_protect_busy(dev); + ctc_clearbit_busy(TB_RETRY,dev); + ctc_unprotect_busy(dev); + ctc_buffer_swap(&ctc->free_anchor, &ctc->proc_anchor); + + if (ctc->free_anchor != NULL) { + ctc->ccw[1].cda = (char *)virt_to_phys(ctc->free_anchor->block); + parm = (__u32) ctc; + rc = do_IO (ctc->irq, &ctc->ccw[0], parm, 0xff, flags ); + if (rc != 0) + ccw_check_return_code(dev, rc); + } else { + clear_bit(0, (void *)&ctc->IO_active); +#ifdef DEBUG + printk(KERN_DEBUG "%s: No HOT READ started in IRQ\n",dev->name); +#endif + } + + if (test_and_set_bit(CTC_BH_ACTIVE, (void *)&ctc->flag_a) == 0) { + queue_task(&ctc->tq, &tq_immediate); + mark_bh(IMMEDIATE_BH); + } + return; + + + case CTC_START_WRITE_TEST: + if (devstat->dstat & DEV_STAT_UNIT_CHECK) { + if ((devstat->ii.sense.data[0] & 0x41) == 0x41 || + (devstat->ii.sense.data[0] & 0x40) == 0x40 || + devstat->ii.sense.data[0] == 0 ) { + init_timer(&ctc->timer); + ctc->timer.function = (void *)ctc_write_retry; + ctc->timer.data = (__u32)ctc; + ctc->timer.expires = jiffies + 10*HZ; + add_timer(&ctc->timer); +#ifdef DEBUG + printk(KERN_DEBUG "%s: write connection restarted\n",dev->name); +#endif + } + return; + } + + ctc->state = CTC_START_WRITE; + wake_up(&ctc->wait); /* wake up ctc_open (WRITE) */ + return; + + + case CTC_START_WRITE: + if (devstat->dstat & DEV_STAT_UNIT_CHECK) { + privptr->stats.tx_errors += ctc->proc_anchor->packets; +#ifdef DEBUG + printk(KERN_DEBUG "%s: Unit Check on write channel\n",dev->name); +#endif + } else { + if (!devstat->flag & DEVSTAT_FINAL_STATUS) + return; + privptr->stats.tx_packets += ctc->proc_anchor->packets; + } + + ctc->proc_anchor->block->length = 0; + ctc_buffer_swap(&ctc->proc_anchor, &ctc->free_anchor); + ctc_clearbit_busy(TB_NOBUFFER,dev); + if (ctc->proc_anchor != NULL) { +#ifdef DEBUG + printk(KERN_DEBUG "%s: IRQ early swap buffer\n",dev->name); +#endif + ctc->ccw[1].count = ctc->proc_anchor->block->length; + ctc->ccw[1].cda = (char *)virt_to_phys(ctc->proc_anchor->block); + parm = (__u32) ctc; + rc = do_IO (ctc->irq, &ctc->ccw[0], parm, 0xff, flags ); + if (rc != 0) + ccw_check_return_code(dev, rc); + dev->trans_start = jiffies; + return; + + } + + if (ctc->free_anchor->block->length != 0) { + if (ctc_test_and_setbit_busy(TB_TX,dev) == 0) { + /* set transmission to busy */ + ctc_buffer_swap(&ctc->free_anchor, &ctc->proc_anchor); + ctc_clearbit_busy(TB_TX,dev); +#ifdef DEBUG + printk(KERN_DEBUG "%s: last buffer move in IRQ\n",dev->name); +#endif + ctc->ccw[1].count = ctc->proc_anchor->block->length; + ctc->ccw[1].cda = (char *)virt_to_phys(ctc->proc_anchor->block); + parm = (__u32) ctc; + rc = do_IO (ctc->irq, &ctc->ccw[0], parm, 0xff, flags ); + if (rc != 0) + ccw_check_return_code(dev, rc); + dev->trans_start = jiffies; + return; + } + } + + clear_bit(0, (void *)&ctc->IO_active); /* set by ctc_tx or ctc_bh */ + return; + + + default: + printk(KERN_WARNING "%s: wrong selection code - irq\n",dev->name); + return; + } +} + + +static void ctc_irq_bh (struct channel *ctc) +{ + int rc = 0; + __u16 data_len; + __u32 parm; + + __u8 flags = 0x00; + __u32 saveflags; + net_device *dev; + struct ctc_priv *privptr; + struct packet *lp; + struct sk_buff *skb; + + dev = (net_device *) ctc->dev; + privptr = (struct ctc_priv *) dev->priv; + +#ifdef DEBUG + printk(KERN_DEBUG "%s: bh routine - state-%02x\n" ,dev->name, ctc->state); +#endif + + while (ctc->proc_anchor != NULL) { + + lp = &ctc->proc_anchor->block->data; + + while ((__u8 *) lp < (__u8 *) &ctc->proc_anchor->block->length + ctc->proc_anchor->block->length) { + data_len = lp->length - PACKET_HEADER_LENGTH; + skb = dev_alloc_skb(data_len); + if (skb) { + memcpy(skb_put(skb, data_len),&lp->data, data_len); + skb->mac.raw = skb->data; + skb->dev = dev; + skb->protocol = htons(ETH_P_IP); + skb->ip_summed = CHECKSUM_UNNECESSARY; /* no UC happened!!! */ + netif_rx(skb); + privptr->stats.rx_packets++; + } else { + privptr->stats.rx_dropped++; + printk(KERN_WARNING "%s: is low on memory\n",dev->name); + } + (__u8 *)lp += lp->length; + } + + s390irq_spin_lock_irqsave(ctc->irq, saveflags); + ctc_buffer_swap(&ctc->proc_anchor, &ctc->free_anchor); + + if (test_and_set_bit(0, (void *)&ctc->IO_active) == 0) { +#ifdef DEBUG + printk(KERN_DEBUG "%s: HOT READ started in bh routine\n" ,dev->name); +#endif + ctc->ccw[1].cda = (char *)virt_to_phys(ctc->free_anchor->block); + parm = (__u32) ctc; + rc = do_IO (ctc->irq, &ctc->ccw[0], parm, 0xff, flags ); + if (rc != 0) + ccw_check_return_code(dev, rc); + } + s390irq_spin_unlock_irqrestore(ctc->irq, saveflags); + } + clear_bit(CTC_BH_ACTIVE, (void *)&ctc->flag_a); + return; +} + + +static void ctc_read_retry (struct channel *ctc) +{ + int rc = 0; + __u32 parm; + __u8 flags = 0x00; + __u32 saveflags; + net_device *dev; + + dev = (net_device *) ctc->dev; + +#ifdef DEBUG + printk(KERN_DEBUG "%s: read retry - state-%02x\n" ,dev->name, ctc->state); +#endif + s390irq_spin_lock_irqsave(ctc->irq, saveflags); + ctc->ccw[1].cda = (char *)virt_to_phys(ctc->free_anchor->block); + parm = (__u32) ctc; + rc = do_IO (ctc->irq, &ctc->ccw[0], parm, 0xff, flags ); + s390irq_spin_unlock_irqrestore(ctc->irq, saveflags); + if (rc != 0) + ccw_check_return_code(dev, rc); + return; +} + + +static void ctc_write_retry (struct channel *ctc) +{ + int rc = 0; + __u32 parm; + __u8 flags = 0x00; + __u32 saveflags; + net_device *dev; + + dev = (net_device *) ctc->dev; + +#ifdef DEBUG + printk(KERN_DEBUG "%s: write retry - state-%02x\n" ,dev->name, ctc->state); +#endif + s390irq_spin_lock_irqsave(ctc->irq, saveflags); + ctc->ccw[1].count = 0; + ctc->ccw[1].cda = (char *)virt_to_phys(ctc->proc_anchor->block); + parm = (__u32) ctc; + rc = do_IO (ctc->irq, &ctc->ccw[0], parm, 0xff, flags ); + s390irq_spin_unlock_irqrestore(ctc->irq, saveflags); + if (rc != 0) + ccw_check_return_code(dev, rc); + return; +} + + + +/* + * ctc_open + * + */ +static int ctc_open(net_device *dev) +{ + int rc; + int i; + int j; + __u8 flags = 0x00; + __u32 saveflags; + __u32 parm; + struct ctc_priv *privptr; + DECLARE_WAITQUEUE(wait, current); + struct timer_list timer; + + + ctc_set_busy(dev); + + privptr = (struct ctc_priv *) (dev->priv); + + privptr->channel[READ].flag = 0x00; + privptr->channel[WRITE].flag = CTC_WRITE; + + for (i = 0; i < 2; i++) { + for (j = 0; j < CTC_BLOCKS; j++) { + rc = ctc_buffer_alloc(&privptr->channel[i]); + if (rc != 0) + return -ENOMEM; + } + init_waitqueue_head(&privptr->channel[i].wait); + privptr->channel[i].tq.next = NULL; + privptr->channel[i].tq.sync = 0; + privptr->channel[i].tq.routine = (void *)(void *)ctc_irq_bh; + privptr->channel[i].tq.data = &privptr->channel[i]; + + privptr->channel[i].dev = dev; + + privptr->channel[i].flag_a = 0; + privptr->channel[i].IO_active = 0; + + privptr->channel[i].ccw[0].cmd_code = CCW_CMD_PREPARE; + privptr->channel[i].ccw[0].flags = CCW_FLAG_SLI | CCW_FLAG_CC; + privptr->channel[i].ccw[0].count = 0; + privptr->channel[i].ccw[0].cda = NULL; + if (i == READ) { + privptr->channel[i].ccw[1].cmd_code = CCW_CMD_READ; + privptr->channel[i].ccw[1].flags = CCW_FLAG_SLI; + privptr->channel[i].ccw[1].count = 0xffff; /* MAX size */ + privptr->channel[i].ccw[1].cda = NULL; + } else { + privptr->channel[i].ccw[1].cmd_code = CCW_CMD_WRITE; + privptr->channel[i].ccw[1].flags = CCW_FLAG_SLI | CCW_FLAG_CC; + privptr->channel[i].ccw[1].count = 0; + privptr->channel[i].ccw[1].cda = NULL; + } + privptr->channel[i].ccw[2].cmd_code = CCW_CMD_NOOP; /* jointed CE+DE */ + privptr->channel[i].ccw[2].flags = CCW_FLAG_SLI; + privptr->channel[i].ccw[2].count = 0; + privptr->channel[i].ccw[2].cda = NULL; + + privptr->channel[i].flag &= ~CTC_TIMER; + init_timer(&timer); + timer.function = (void *)ctc_timer; + timer.data = (__u32)&privptr->channel[i]; + timer.expires = jiffies + 150*HZ; /* time to connect with the remote side */ + add_timer(&timer); + + s390irq_spin_lock_irqsave(privptr->channel[i].irq, saveflags); + parm = (unsigned long) &privptr->channel[i]; + privptr->channel[i].state = CTC_START_HALT_IO; + rc = halt_IO(privptr->channel[i].irq, parm, flags); + add_wait_queue(&privptr->channel[i].wait, &wait); + current->state = TASK_INTERRUPTIBLE; + s390irq_spin_unlock_irqrestore(privptr->channel[i].irq, saveflags); + schedule(); + remove_wait_queue(&privptr->channel[i].wait, &wait); + if(rc != 0) + ccw_check_return_code(dev, rc); + if((privptr->channel[i].flag & CTC_TIMER) == 0x00) + del_timer(&timer); + } + + if ((((privptr->channel[READ].last_dstat | privptr->channel[WRITE].last_dstat) & + ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) != 0x00) || + (((privptr->channel[READ].flag | privptr->channel[WRITE].flag) & CTC_TIMER) != 0x00)) { +#ifdef DEBUG + printk(KERN_DEBUG "%s: channel problems during open - read: %02x - write: %02x\n", + dev->name, privptr->channel[READ].last_dstat, privptr->channel[WRITE].last_dstat); +#endif + printk(KERN_INFO "%s: remote side is currently not ready\n", dev->name); + + for (i = 0; i < 2; i++) { + s390irq_spin_lock_irqsave(privptr->channel[i].irq, saveflags); + parm = (unsigned long) &privptr->channel[i]; + privptr->channel[i].state = CTC_STOP; + rc = halt_IO(privptr->channel[i].irq, parm, flags); + s390irq_spin_unlock_irqrestore(privptr->channel[i].irq, saveflags); + if (rc != 0) + ccw_check_return_code(dev, rc); + for (j = 0; j < CTC_BLOCKS; j++) + ctc_buffer_free(&privptr->channel[i]); + } + return -EIO; + } + + printk(KERN_INFO "%s: connected with remote side\n",dev->name); + ctc_clear_busy(dev); + return 0; +} + + +static void ctc_timer (struct channel *ctc) +{ +#ifdef DEBUG + net_device *dev; + + dev = (net_device *) ctc->dev; + printk(KERN_DEBUG "%s: timer return\n" ,dev->name); +#endif + ctc->flag |= CTC_TIMER; + wake_up(&ctc->wait); + return; +} + +/* + * ctc_release + * + */ +static int ctc_release(net_device *dev) +{ + int rc; + int i; + int j; + __u8 flags = 0x00; + __u32 saveflags; + __u32 parm; + struct ctc_priv *privptr; + DECLARE_WAITQUEUE(wait, current); + + privptr = (struct ctc_priv *) dev->priv; + + ctc_protect_busy_irqsave(dev,saveflags); + ctc_setbit_busy(TB_STOP,dev); + ctc_unprotect_busy_irqrestore(dev,flags); + for (i = 0; i < 2; i++) { + s390irq_spin_lock_irqsave(privptr->channel[i].irq, saveflags); + privptr->channel[i].state = CTC_STOP; + parm = (__u32) &privptr->channel[i]; + rc = halt_IO (privptr->channel[i].irq, parm, flags ); + add_wait_queue(&privptr->channel[i].wait, &wait); + current->state = TASK_INTERRUPTIBLE; + s390irq_spin_unlock_irqrestore(privptr->channel[i].irq, saveflags); + schedule(); + remove_wait_queue(&privptr->channel[i].wait, &wait); + if (rc != 0) { + ccw_check_return_code(dev, rc); + } + + for (j = 0; j < CTC_BLOCKS; j++) { + ctc_buffer_swap(&privptr->channel[i].proc_anchor, &privptr->channel[i].free_anchor); + ctc_buffer_free(&privptr->channel[i]); + } + } + + if (((privptr->channel[READ].last_dstat | privptr->channel[WRITE].last_dstat) & + ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) != 0x00) { + printk(KERN_WARNING "%s: channel problems during close - read: %02x - write: %02x\n", + dev->name, privptr->channel[READ].last_dstat, privptr->channel[WRITE].last_dstat); + return -EIO; + } + + return 0; +} + + +/* + * ctc_tx + * + * + */ +static int ctc_tx(struct sk_buff *skb, net_device *dev) +{ + int rc=0,rc2; + __u32 parm; + __u8 flags = 0x00; + __u32 saveflags; + struct ctc_priv *privptr; + struct packet *lp; + + + privptr = (struct ctc_priv *) (dev->priv); + + if (skb == NULL) { + printk(KERN_WARNING "%s: NULL pointer as sk_buffer passed\n", dev->name); + privptr->stats.tx_dropped++; + return -EIO; + } + + s390irq_spin_lock_irqsave(privptr->channel[WRITE].irq, saveflags); + if (ctc_check_busy(dev)) { + rc=-EBUSY; + goto Done; + } + + if (ctc_test_and_setbit_busy(TB_TX,dev)) { /* set transmission to busy */ + rc=-EBUSY; + goto Done; + } + + if (65535 - privptr->channel[WRITE].free_anchor->block->length - PACKET_HEADER_LENGTH <= skb->len + PACKET_HEADER_LENGTH + 2) { +#ifdef DEBUG + printk(KERN_DEBUG "%s: early swap\n", dev->name); +#endif + + ctc_buffer_swap(&privptr->channel[WRITE].free_anchor, &privptr->channel[WRITE].proc_anchor); + if (privptr->channel[WRITE].free_anchor == NULL){ + ctc_setbit_busy(TB_NOBUFFER,dev); + rc=-EBUSY; + goto Done2; + } + } + + if (privptr->channel[WRITE].free_anchor->block->length == 0) { + privptr->channel[WRITE].free_anchor->block->length = BLOCK_HEADER_LENGTH; + privptr->channel[WRITE].free_anchor->packets = 0; + } + + + (__u8 *)lp = (__u8 *) &privptr->channel[WRITE].free_anchor->block->length + privptr->channel[WRITE].free_anchor->block->length; + privptr->channel[WRITE].free_anchor->block->length += skb->len + PACKET_HEADER_LENGTH; + lp->length = skb->len + PACKET_HEADER_LENGTH; + lp->type = 0x0800; + lp->unused = 0; + memcpy(&lp->data, skb->data, skb->len); + (__u8 *) lp += lp->length; + lp->length = 0; + dev_kfree_skb(skb); + privptr->channel[WRITE].free_anchor->packets++; + + if (test_and_set_bit(0, (void *)&privptr->channel[WRITE].IO_active) == 0) { + ctc_buffer_swap(&privptr->channel[WRITE].free_anchor,&privptr->channel[WRITE].proc_anchor); + privptr->channel[WRITE].ccw[1].count = privptr->channel[WRITE].proc_anchor->block->length; + privptr->channel[WRITE].ccw[1].cda = (char *)virt_to_phys(privptr->channel[WRITE].proc_anchor->block); + parm = (__u32) &privptr->channel[WRITE]; + rc2 = do_IO (privptr->channel[WRITE].irq, &privptr->channel[WRITE].ccw[0], parm, 0xff, flags ); + if (rc2 != 0) + ccw_check_return_code(dev, rc2); + dev->trans_start = jiffies; + } + if (privptr->channel[WRITE].free_anchor == NULL) + ctc_setbit_busy(TB_NOBUFFER,dev); +Done2: + ctc_clearbit_busy(TB_TX,dev); +Done: + s390irq_spin_unlock_irqrestore(privptr->channel[WRITE].irq, saveflags); + return(rc); +} + + +/* + * ctc_change_mtu + * + * S/390 can handle MTU sizes from 576 to 32760 for VM, VSE + * 576 to 65527 for OS/390 + * + */ +static int ctc_change_mtu(net_device *dev, int new_mtu) +{ + if ((new_mtu < 576) || (new_mtu > 65528)) + return -EINVAL; + dev->mtu = new_mtu; + return 0; +} + + +/* + * ctc_stats + * + */ +struct net_device_stats *ctc_stats(net_device *dev) +{ + struct ctc_priv *privptr; + + privptr = dev->priv; + return &privptr->stats; +} + + +/* Module code goes here */ + +/* + free_irq(privptr->channel[i].irq, privptr->channel[i].devstat); + kfree(privptr->channel[i].devstat); + +*/ +/* --- This is the END my friend --- */ diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/s390/net/iucv.c linux/drivers/s390/net/iucv.c --- v2.3.99-pre7/linux/drivers/s390/net/iucv.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/s390/net/iucv.c Fri May 12 11:41:44 2000 @@ -0,0 +1,1178 @@ +/* + * drivers/s390/net/iucv.c + * Network driver for VM using iucv + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Stefan Hegewald + * Hartmut Penner + * + * 2.3 Updates Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) + * Martin Schwidefsky (schwidefsky@de.ibm.com) + * + + */ + +#ifndef __KERNEL__ +#define __KERNEL__ +#endif + +#include +#include +#include /* printk() */ +#include /* kmalloc() */ +#include /* error codes */ +#include /* size_t */ +#include /* mark_bh */ +#include /* struct net_device, and other headers */ +#include /* struct net_device, and other headers */ +#include +#include +#include /* struct iphdr */ +#include /* struct tcphdr */ +#include +#include +#include +#include +#include +#include + +#include "iucv.h" + + + + +#define DEBUG123 +#define MAX_DEVICES 10 + +extern char _ascebc[]; + +/* + * global structures + */ +static char iucv_userid[MAX_DEVICES][8]; +static char iucv_ascii_userid[MAX_DEVICES][8]; +static int iucv_pathid[MAX_DEVICES] = {0}; +static unsigned char iucv_ext_int_buffer[40] __attribute__((aligned (8))) ={0}; +static unsigned char glob_command_buffer[40] __attribute__((aligned (8))); + +#if LINUX_VERSION_CODE>=0x20300 +typedef struct net_device net_device; +#else +typedef struct device net_device; +#endif +net_device iucv_devs[]; + + +/* This structure is private to each device. It is used to pass */ +/* packets in and out, so there is place for a packet */ +struct iucv_priv { + struct net_device_stats stats; + int packetlen; + int status; + u8 *packetdata; + int pathid; /* used device */ + unsigned char command_buffer[40] __attribute__((aligned (8))); + unsigned char ext_int_buffer[40] __attribute__((aligned (8))); + u8* receive_buffer; + int receive_buffer_len; + u8* send_buffer; + int send_buffer_len; + char * new_send_buf; /* send buffer ptr */ + unsigned char recv_buf[2048]; /* size is just a guess */ + unsigned char userid[8]; +}; + +struct iucv_header { + short len; +}; + + + +static __inline__ int netif_is_busy(net_device *dev) +{ +#if LINUX_VERSION_CODE<0x02032D + return(dev->tbusy); +#else + return(test_bit(__LINK_STATE_XOFF,&dev->flags)); +#endif +} + + + +#if LINUX_VERSION_CODE<0x02032D +#define netif_enter_interrupt(dev) dev->interrupt=1 +#define netif_exit_interrupt(dev) dev->interrupt=0 +#define netif_start(dev) dev->start=1 +#define netif_stop(dev) dev->start=0 + +static __inline__ void netif_stop_queue(net_device *dev) +{ + dev->tbusy=1; +} + +static __inline__ void netif_start_queue(net_device *dev) +{ + dev->tbusy=0; +} + +static __inline__ void netif_wake_queue(net_device *dev) +{ + dev->tbusy=0; + mark_bh(NET_BH); +} + +#else +#define netif_enter_interrupt(dev) +#define netif_exit_interrupt(dev) +#define netif_start(dev) +#define netif_stop(dev) +#endif + + + +/* + * Following the iucv primitives + */ + + +extern inline void b2f0(int code,void* parm) +{ + asm volatile ("LR 1,%1\n\tLR 0,%0\n\t.long 0xb2f01000" :: + "d" (code) ,"a" (parm) :"0", "1"); +} + +int iucv_enable(void *parms) +{ + MASK_T *parm = parms; + memset(parms,0,sizeof(parm)); + parm->ipmask = 0xF8; + b2f0(SETMASK,parm); + memset(parms,0,sizeof(parm)); + parm->ipmask = 0xF8; + b2f0(SETCMASK,parm); + return parm->iprcode; +} + + +int iucv_declare_buffer(void *parms, DCLBFR_T *buffer) +{ + DCLBFR_T *parm = parms; + memset(parms,0,sizeof(parm)); + parm->ipflags1= 0x00; + parm->ipbfadr1 = virt_to_phys(buffer); + b2f0(DECLARE_BUFFER, parm); + return parm->iprcode; +} + + +int iucv_retrieve_buffer(void *parms) +{ + DCLBFR_T *parm = parms; + memset(parms,0x0,sizeof(parm)); + parm->iprcode = 0x0; + b2f0(RETRIEVE_BUFFER, parm); + return parm->iprcode; +} + + +int iucv_connect(void *parms, + const char *userid, + const char *host, + const char *ipusr, + unsigned short * used_pathid) +{ + CONNECT_T *parm = parms; /* ipflags was 0x60*/ + memset(parms,0x0,sizeof(parm)); + parm->ipflags1 = 0x80; + parm->ipmsglim = 0x0a; + memcpy(parm->ipvmid,userid,8); + if (ipusr) + memcpy(parm->ipuser,ipusr,16); + memcpy(parm->iptarget,host,8); + b2f0(CONNECT, parm); + *used_pathid = parm->ippathid; + return parm->iprcode; +} + + + +int iucv_accept(void *parms,int pathid) +{ +#ifdef DEBUG + int i=0; +#endif + ACCEPT_T *parm = parms; + memset(parms,0,sizeof(parm)); + parm->ippathid = pathid; + parm->ipflags1 = 0x80; + parm->ipmsglim = 0x0a; +#ifdef DEBUG + printk("iucv: iucv_accept input.\n"); + for (i=0;i<40; i++) + { + printk("%02x ",((char *)parms)[i]); + } + printk("\n"); +#endif + b2f0(ACCEPT, parm); + return parm->iprcode; +} + + + +int iucv_receive(void *parms,void *bufferarray,int len) +{ +#ifdef DEBUG + int i=0; +#endif + RECEIVE_T *parm = parms; + memset(parms,0x0,sizeof(parm)); + /*parm->ipflags1 = 0x42;*/ + parm->ipflags1 = 0x0; + parm->ipmsgid = 0x0; + parm->iptrgcls = 0x0; + parm->ipbfadr1 = (ULONG) virt_to_phys(bufferarray); + parm->ipbfln1f = len; + parm->ipbfln2f = 0x0; + b2f0(RECEIVE, parm); + if (parm->iprcode == 0) + len = parm->ipbfln1f; +// len = len-parm->ipbfln1f; +#ifdef DEBUG + printk("iucv: iucv_receive command input:\n"); + for (i=0;i<40;i++) /* show iucv buffer before send */ + { + printk("%02x ",((char *)parms)[i]); + } + printk("\n"); + + printk("iucv: iucv_receive data buffer:\n"); + for (i=0;iiprcode; +} + + +int iucv_send(void *parms,int pathid,void *bufferarray,int len, + void *recv_buf, int recv_len) +{ +#ifdef DEBUG + int i=0; +#endif + SEND_T *parm = parms; + memset(parms,0x0,sizeof(parm)); + /* parm->ipflags1 = 0x48; ??*/ + parm->ippathid = pathid; + parm->ipflags1 = 0x14; /* any options ?? */ + parm->ipmsgid = 0x0; + parm->iptrgcls = 0x0; + parm->ipbfadr1 = virt_to_phys(bufferarray); + parm->ipbfln1f = len; + parm->ipsrccls = 0x0; + parm->ipmsgtag = 0x0; + parm->ipbfadr2 = virt_to_phys(recv_buf); + parm->ipbfln2f = recv_len; + + +#ifdef DEBUG + printk("iucv: iucv_send command input:\n"); + for (i=0;i<40;i++) /* show iucv buffer before send */ + { + printk("%02x ",((char *)parms)[i]); + } + printk("\n"); + + printk("iucv: iucv_send data buffer:\n"); + for (i=0;iiprcode; +} + + + +int iucv_sever(void *parms) +{ + SEVER_T *parm = parms; + memset(parms,0x0,sizeof(parm)); + parm->ippathid = 0x0; + parm->ipflags1 = 0x0; + parm->iprcode = 0xF; + memset(parm->ipuser,0,16); + b2f0(SEVER, parm); + return parm->iprcode; +} + + +#ifdef DEBUG +/*--------------------------*/ +/* Dump buffer formatted */ +/*--------------------------*/ +static void dumpit(char* buf, int len) +{ + int i; + for (i=0;ipriv); + if (memcmp(privptr->userid,userid,8)==0) + return &iucv_devs[i]; + } + printk("iucv: get_device_from_uid: no device for userid %s\n",userid); + return 0; +} + + +/*--------------------------*/ +/* Open iucv Device Driver */ +/*--------------------------*/ +int iucv_open(net_device *dev) +{ + int rc; + unsigned short iucv_used_pathid; + struct iucv_priv *privptr; + char iucv_host[8] ={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + char vmident[16] ={0xf0,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0xf0,0x40,0x40,0x40,0x40,0x40,0x40,0x40}; + +#ifdef DEBUG + printk( "iucv: iucv_open, device: %s\n",dev->name); +#endif + + privptr = (struct iucv_priv *)(dev->priv); + if(privptr->pathid != -1) { + netif_start(dev); + netif_start_queue(dev); + return 0; + } + if ((rc = iucv_connect(privptr->command_buffer, + privptr->userid, + iucv_host, + vmident, + &iucv_used_pathid))!=0) { + printk( "iucv: iucv connect failed with rc %X\n",rc); + iucv_retrieve_buffer(privptr->command_buffer); + return -ENODEV; + } + + privptr->pathid = iucv_used_pathid; + iucv_pathid[dev-iucv_devs]=privptr->pathid; + +#ifdef DEBUG + printk( "iucv: iucv_connect ended with rc: %X\n",rc); + printk( "iucv[%d] pathid %X \n",(int)(dev-iucv_devs),privptr->pathid); +#endif + netif_start(dev); + netif_start_queue(dev); + return 0; +} + + + +/*-----------------------------------------------------------------------*/ +/* Receive a packet: retrieve, encapsulate and pass over to upper levels */ +/*-----------------------------------------------------------------------*/ +void iucv_rx(net_device *dev, int len, unsigned char *buf) +{ + + struct sk_buff *skb; + struct iucv_priv *privptr = (struct iucv_priv *)dev->priv; + +#ifdef DEBUG + printk( "iucv: iucv_rx len: %X, device %s\n",len,dev->name); + printk( "iucv rx: received orig:\n"); + dumpit(buf,len); +#endif + + /* strip iucv header now */ + len = len - 2; /* short header */ + buf = buf + 2; /* short header */ + + skb = dev_alloc_skb(len+2); /* why +2 ? alignment ? */ + if (!skb) { + printk( "iucv rx: low on mem, returning...\n"); + return; + } + skb_reserve(skb, 2); /* align IP on 16B boundary*/ + memcpy(skb_put(skb, len), buf, len); +#ifdef DEBUG + printk( "iucv rx: data before netif_rx()\n"); + dumpit(buf,len); +#endif + + /* Write metadata, and then pass to the receive level */ + skb->mac.raw = skb->data; + skb->pkt_type = PACKET_HOST; + skb->dev = dev; + skb->protocol = htons(ETH_P_IP); + skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it*/ + privptr->stats.rx_packets++; + netif_rx(skb); + + return; +} /* end iucv_rx() */ + + + + +/*----------------------------*/ +/* handle interrupts */ +/*----------------------------*/ +void do_iucv_interrupt(void) +{ + int rc; + struct in_device *indev; + struct in_ifaddr *inaddr; + unsigned long len=0; + net_device *dev=0; + struct iucv_priv *privptr; + INTERRUPT_T * extern_int_buffer; + unsigned short iucv_data_len=0; + unsigned short iucv_next=0; + unsigned char * rcvptr; + + /* get own buffer: */ + extern_int_buffer = (INTERRUPT_T*) iucv_ext_int_buffer; + + netif_enter_interrupt(dev); /* lock ! */ + +#ifdef DEBUG + printk( "iucv: do_iucv_interrupt %x received; pathid: %02X\n", + extern_int_buffer->iptype,extern_int_buffer->ippathid); + printk( "iucv: extern_int_buffer:\n"); + dumpit((char *)&extern_int_buffer[0],40); +#endif + + switch (extern_int_buffer->iptype) + { + case 0x01: /* connection pending ext interrrupt */ +#ifdef DEBUG + printk( "iucv: connection pending IRQ.\n"); +#endif + + rc = iucv_accept(glob_command_buffer, + extern_int_buffer->ippathid); + if (rc != 0) { + printk( "iucv: iucv_accept failed with rc: %X\n",rc); + iucv_retrieve_buffer(glob_command_buffer); + break; + } +#ifdef DEBUG + dumpit(&((char *)extern_int_buffer)[8],8); +#endif + dev = get_device_from_userid(&((char*)extern_int_buffer)[8]); + privptr = (struct iucv_priv *)(dev->priv); + privptr->pathid = extern_int_buffer->ippathid; + +#ifdef DEBUG + printk( "iucv: iucv_accept ended with rc: %X\n",rc); + printk( "iucv: device %s found.\n",dev->name); +#endif + break; + + case 0x02: /* connection completed ext interrrupt */ + /* set own global IP address */ + /* & set global routing addr */ +#ifdef DEBUG + printk( "connection completed.\n"); +#endif + + if( extern_int_buffer->ipmsgtag !=0) + { + /* get ptr's to kernel struct with local & broadcast address */ + dev = get_device_from_pathid(extern_int_buffer->ippathid); + privptr = (struct iucv_priv *)(dev->priv); + indev = dev->ip_ptr; + inaddr = (struct in_ifaddr*) indev->ifa_list; + } + break; + + + case 0x03: /* connection severed ext interrrupt */ + /* we do not handle this one at this time */ +#ifdef DEBUG + printk( "connection severed.\n"); +#endif + break; + + + case 0x04: /* connection quiesced ext interrrupt */ + /* we do not handle this one at this time */ +#ifdef DEBUG + printk( "connection quiesced.\n"); +#endif + break; + + + case 0x05: /* connection resumed ext interrrupt */ + /* we do not handle this one at this time */ +#ifdef DEBUG + printk( "connection resumed.\n"); +#endif + break; + + + case 0x06: /* priority message complete ext interrupt */ + case 0x07: /* non priority message complete ext interrupt */ + /* send it to iucv_rx for handling */ +#ifdef DEBUG + printk( "message completed.\n"); +#endif + + if (extern_int_buffer->ipaudit ==0) /* ok case */ + { +#ifdef DEBUG + printk( "iucv: msg complete interrupt successful, rc: %X\n", + (unsigned int)extern_int_buffer->ipaudit); +#endif + ; + } + else + { + printk( "iucv: msg complete interrupt error, rc: %X\n", + (unsigned int)extern_int_buffer->ipaudit); + } + /* a transmission is over: tell we are no more busy */ + dev = get_device_from_pathid(extern_int_buffer->ippathid); + privptr = (struct iucv_priv *)(dev->priv); + privptr->stats.tx_packets++; + netif_wake_queue(dev); /* transmission is no longer busy*/ + break; + + + case 0x08: /* priority message pending */ + case 0x09: /* non priority message pending */ +#ifdef DEBUG + printk( "message pending.\n"); +#endif + dev = get_device_from_pathid(extern_int_buffer->ippathid); + privptr = (struct iucv_priv *)(dev->priv); + rcvptr = &privptr->receive_buffer[0]; + + /* re-set receive buffer */ + memset(privptr->receive_buffer,0,privptr->receive_buffer_len); + len = privptr->receive_buffer_len; + + /* get data now */ + if (extern_int_buffer->ipflags1 & 0x80) + { /* data is in the message */ +#ifdef DEBUG + printk( "iucv: iucv_receive data is in header!\n"); +#endif + memcpy(privptr->receive_buffer, + (char *)extern_int_buffer->iprmmsg1, + (unsigned long)(extern_int_buffer->iprmmsg2)); + } + else /* data is in buffer, do a receive */ + { + rc = iucv_receive(privptr->command_buffer,rcvptr,len); + if (rc != 0 || len == 0) + { + printk( "iucv: iucv_receive failed with rc: %X, length: %lX\n",rc,len); + iucv_retrieve_buffer(privptr->command_buffer); + break; + } + } /* end else */ + + iucv_next = 0; + /* get next packet offset */ + iucv_data_len= *((unsigned short*)rcvptr); + do{ /* until receive buffer is empty, i.e. iucv_next == 0 ! */ + + /* get data length: */ + iucv_data_len= iucv_data_len - iucv_next; + +#ifdef DEBUG + printk( "iucv: iucv_receive: len is %02X, last: %02X\n", + iucv_data_len,iucv_next); +#endif + /* transmit upstairs */ + iucv_rx(dev,(iucv_data_len),rcvptr); + +#ifdef DEBUG + printk( "iucv: transaction complete now.\n"); +#endif + iucv_next = *((unsigned short*)rcvptr); + rcvptr = rcvptr + iucv_data_len; + /* get next packet offset */ + iucv_data_len= *((unsigned short*)rcvptr); + + } while (iucv_data_len != 0); + netif_start_queue(dev); /* transmission is no longer busy*/ + break; + + default: + printk( "unknown iucv interrupt \n"); + break; + + } /* end switch */ + netif_exit_interrupt(dev); /* release lock*/ + +#ifdef DEBUG + printk( "iucv: leaving do_iucv_interrupt.\n"); +#endif + +} /* end do_iucv_interrupt() */ + + + +/*-------------------------------------------*/ +/* Transmit a packet (low level interface) */ +/*-------------------------------------------*/ +int iucv_hw_tx(char *send_buf, int len,net_device *dev) +{ + /* This function deals with hw details. */ + /* This interface strips off the ethernet header details. */ + /* In other words, this function implements the iucv behaviour,*/ + /* while all other procedures are rather device-independent */ + struct iucv_priv *privptr; + int rc, recv_len=2000; + + privptr = (struct iucv_priv *)(dev->priv); + +#ifdef DEBUG + printk( "iucv: iucv_hw_tx, device %s\n",dev->name); + printk( "iucv: hw_TX_data len: %X\n",len); + dumpit(send_buf,len); +#endif + + /* I am paranoid. Ain't I? */ + if (len < sizeof(struct iphdr)) + { + printk( "iucv: Hmm... packet too short (%i octets)\n",len); + return -EINVAL; + } + + /* + * build IUCV header (preceeding halfword offset) + * works as follows: Each packet is preceded by the + * halfword offset to the next one. + * The last packet is followed by an offset of zero. + * E.g., AL2(12),10-byte packet, AL2(34), 32-byte packet, AL2(0) + */ + + memcpy(&privptr->send_buffer[2],send_buf,len+2); + privptr->send_buffer[len+2] = 0; + privptr->send_buffer[len+3] = 0; + *((unsigned short*) &privptr->send_buffer[0]) = len + 2; + +#ifdef DEBUG + printk( "iucv: iucv_hw_tx, device %s\n",dev->name); + printk( "iucv: send len: %X\n",len+4); + dumpit(privptr->send_buffer,len+4); +#endif + *((unsigned short*) &privptr->send_buffer[0]) = len + 2; + + /* Ok, now the packet is ready for transmission: send it. */ + if ((rc = iucv_send(privptr->command_buffer, + privptr->pathid, + &privptr->send_buffer[0],len+4, + privptr->recv_buf,recv_len))!=0) { + printk( "iucv: send_iucv failed, rc: %X\n",rc); + iucv_retrieve_buffer(privptr->command_buffer); + } +#ifdef DEBUG + printk( "iucv: send_iucv ended, rc: %X\n",rc); +#endif + return rc; +} /* end iucv_hw_tx() */ + + + + + + +/*------------------------------------------*/ +/* Transmit a packet (called by the kernel) */ +/*------------------------------------------*/ +int iucv_tx(struct sk_buff *skb, net_device *dev) +{ + int retval=0; + + struct iucv_priv *privptr; + + if (dev == NULL) + { + printk("iucv: NULL dev passed\n"); + return 0; + } + + privptr = (struct iucv_priv *) (dev->priv); + + if (skb == NULL) + { + printk("iucv: %s: NULL buffer passed\n", dev->name); + privptr->stats.tx_errors++; + return 0; + } + +#ifdef DEBUG + printk( "iucv: enter iucv_tx, using %s\n",dev->name); +#endif + + if (netif_is_busy(dev)) /* shouldn't happen */ + { + privptr->stats.tx_errors++; + dev_kfree_skb(skb); + printk("iucv: %s: transmit access conflict ! leaving iucv_tx.\n", dev->name); + } + + netif_stop_queue(dev); /* transmission is busy*/ + dev->trans_start = jiffies; /* save the timestamp*/ + + /* actual deliver of data is device-specific, and not shown here */ + retval = iucv_hw_tx(skb->data, skb->len, dev); + + dev_kfree_skb(skb); /* release it*/ + +#ifdef DEBUG + printk( "iucv:leaving iucv_tx, device %s\n",dev->name); +#endif + + return retval; /* zero == done; nonzero == fail*/ +} /* end iucv_tx( struct sk_buff *skb, struct device *dev) */ + + + + + + +/*---------------*/ +/* iucv_release */ +/*---------------*/ +int iucv_release(net_device *dev) +{ + int rc =0; + struct iucv_priv *privptr; + privptr = (struct iucv_priv *) (dev->priv); + + netif_stop(dev); + netif_stop_queue(dev); /* can't transmit any more*/ + rc = iucv_sever(privptr->command_buffer); + if (rc!=0) + { + printk("iucv: %s: iucv_release pending...rc:%02x\n",dev->name,rc); + } + +#ifdef DEBUG + printk("iucv: iucv_sever ended with rc: %X\n",rc); +#endif + + return rc; +} /* end iucv_release() */ + + + + + +/*-----------------------------------------------*/ +/* Configuration changes (passed on by ifconfig) */ +/*-----------------------------------------------*/ +int iucv_config(net_device *dev, struct ifmap *map) +{ + if (dev->flags & IFF_UP) /* can't act on a running interface*/ + return -EBUSY; + + /* ignore other fields */ + return 0; +} +/* end iucv_config() */ + + + + + +/*----------------*/ +/* Ioctl commands */ +/*----------------*/ +int iucv_ioctl(net_device *dev, struct ifreq *rq, int cmd) +{ +#ifdef DEBUG + printk( "iucv: device %s; iucv_ioctl\n",dev->name); +#endif + return 0; +} + +/*---------------------------------*/ +/* Return statistics to the caller */ +/*---------------------------------*/ +struct net_device_stats *iucv_stats(net_device *dev) +{ + struct iucv_priv *priv = (struct iucv_priv *)dev->priv; +#ifdef DEBUG + printk( "iucv: device %s; iucv_stats\n",dev->name); +#endif + return &priv->stats; +} + + +/* + * iucv_change_mtu + * IUCV can handle MTU sizes from 576 to approx. 32000 + */ + +static int iucv_change_mtu(net_device *dev, int new_mtu) +{ +#ifdef DEBUG + printk( "iucv: device %s; iucv_change_mtu\n",dev->name); +#endif + if ((new_mtu < 64) || (new_mtu > 32000)) + return -EINVAL; + dev->mtu = new_mtu; + return 0; +} + + + + +/*--------------------------------------------*/ +/* The init function (sometimes called probe).*/ +/* It is invoked by register_netdev() */ +/*--------------------------------------------*/ +int iucv_init(net_device *dev) +{ + int rc; + struct iucv_priv *privptr; + +#ifdef DEBUG + printk( "iucv: iucv_init, device: %s\n",dev->name); +#endif + + dev->open = iucv_open; + dev->stop = iucv_release; + dev->set_config = iucv_config; + dev->hard_start_xmit = iucv_tx; + dev->do_ioctl = iucv_ioctl; + dev->get_stats = iucv_stats; + dev->change_mtu = iucv_change_mtu; + + /* keep the default flags, just add NOARP */ + + dev->hard_header_len = 0; + dev->addr_len = 0; + dev->type = ARPHRD_SLIP; + dev->tx_queue_len = 100; + dev->flags = IFF_NOARP|IFF_POINTOPOINT; + dev->mtu = 4092; + + dev_init_buffers(dev); + + /* Then, allocate the priv field. This encloses the statistics */ + /* and a few private fields.*/ + dev->priv = kmalloc(sizeof(struct iucv_priv), GFP_KERNEL); + if (dev->priv == NULL){ + printk( "iucv: no memory for dev->priv.\n"); + return -ENOMEM; + } + memset(dev->priv, 0, sizeof(struct iucv_priv)); + privptr = (struct iucv_priv *)(dev->priv); + + + privptr->send_buffer = (u8*) __get_free_pages(GFP_KERNEL+GFP_DMA,8); + if (privptr->send_buffer == NULL) { + printk(KERN_INFO "%s: could not get pages for send buffer\n", + dev->name); + return -ENOMEM; + } + memset(privptr->send_buffer, 0, 8*PAGE_SIZE); + privptr->send_buffer_len=8*PAGE_SIZE; + + privptr->receive_buffer = (u8*) __get_free_pages(GFP_KERNEL+GFP_DMA,8); + if (privptr->receive_buffer == NULL) { + printk(KERN_INFO "%s: could not get pages for receive buffer\n", + dev->name); + return -ENOMEM; + } + memset(privptr->receive_buffer, 0, 8*PAGE_SIZE); + privptr->receive_buffer_len=8*PAGE_SIZE; + + /* now use the private fields ... */ + /* init pathid */ + privptr->pathid = -1; + + /* init private userid from global userid */ + memcpy(privptr->userid,iucv_userid[dev-iucv_devs],8); + + + /* we can use only ONE buffer for external interrupt ! */ + rc=iucv_declare_buffer(privptr->command_buffer, + (DCLBFR_T *)iucv_ext_int_buffer); + if (rc!=0 && rc!=19) /* ignore existing buffer */ + { + printk( "iucv:iucv_declare failed, rc: %X\n",rc); + return -ENODEV; + } + + rc = iucv_enable(privptr->command_buffer); + if (rc!=0) + { + printk( "iucv:iucv_enable failed, rc: %x\n",rc); + iucv_retrieve_buffer(privptr->command_buffer); + return -ENODEV; + } +#ifdef DEBUG + printk( "iucv: iucv_init endend OK for device %s.\n",dev->name); +#endif + return 0; +} + + +/* + * setup iucv devices + * + * string passed: iucv=userid1,...,useridn + */ +#if LINUX_VERSION_CODE>=0x020300 +static int __init iucv_setup(char *str) +#else +__initfunc(void iucv_setup(char *str,int *ints)) +#endif +{ + int result=0, i=0,j=0, k=0, device_present=0; + char *s = str; + net_device * dev ={0}; + +#ifdef DEBUG + printk( "iucv: start registering device(s)... \n"); +#endif + + /* + * scan device userids + */ + + while(*s != 0x20 && *s != '\0'){ + if(*s == ','){ + /* fill userid up to 8 chars */ + for(k=i;k<8;k++){ + iucv_userid[j][k] = 0x40; + } /* end for */ + /* new device */ + j++; + s++; /* ignore current char */ + i=0; + if (j>MAX_DEVICES) { + printk("iucv: setup devices: max devices %d reached.\n", + MAX_DEVICES); + break; + } /* end if */ + continue; + } /* end if */ + iucv_ascii_userid[j][i] = (int)*s; + iucv_userid[j][i] = _ascebc[(int)*s++]; + i++; + } /* end while */ + + /* + * fill last userid up to 8 chars + */ + for(k=i;k<8;k++) { + iucv_userid[j][k] = 0x40; + } + + /* + * set device name and register + */ + + for (k=0;k<=j;k++) { + memcpy(iucv_devs[k].name, "iucv0", 4); + dev = &iucv_devs[k]; + dev->name[4] = k + '0'; + +#ifdef DEBUGX + printk("iucv: (ASCII- )Userid:%s\n",&iucv_ascii_userid[k][0]); + printk("iucv: (ASCII-)Userid: "); + for (i=0;i<8;i++) { + printk( "%02X ",(int)iucv_ascii_userid[k][i]); + } + printk("\n"); + printk("iucv: (EBCDIC-)Userid: "); + for (i=0;i<8;i++) { + printk( "%02X ",(int)iucv_userid[k][i]); + } + printk("\n"); + printk("iucv: device name :%s\n",iucv_devs[k].name); +#endif + + if ( (result = register_netdev(iucv_devs + k)) ) + printk("iucv: error %i registering device \"%s\"\n", + result, iucv_devs[k].name); + else + { + device_present++; + } + } /* end for */ + +#ifdef DEBUG + printk( "iucv: end register devices, %d devices present\n",device_present); +#endif + /* return device_present ? 0 : -ENODEV; */ +#if LINUX_VERSION_CODE>=0x020300 + return 1; +#else + return; +#endif +} + +#if LINUX_VERSION_CODE>=0x020300 +__setup("iucv=", iucv_setup); +#endif + + +/*-------------*/ +/* The devices */ +/*-------------*/ +char iucv_names[MAX_DEVICES*8]; /* MAX_DEVICES eight-byte buffers */ +net_device iucv_devs[MAX_DEVICES] = { + { + iucv_names, /* name -- set at load time */ + 0, 0, 0, 0, /* shmem addresses */ + 0x000, /* ioport */ + 0, /* irq line */ + 0, 0, 0, /* various flags: init to 0 */ + NULL, /* next ptr */ + iucv_init, /* init function, fill other fields with NULL's */ + }, + { + iucv_names+8,/* name -- set at load time */ + 0, 0, 0, 0, /* shmem addresses */ + 0x000, /* ioport */ + 0, /* irq line */ + 0, 0, 0, /* various flags: init to 0 */ + NULL, /* next ptr */ + iucv_init, /* init function, fill other fields with NULL's */ + }, + { + iucv_names+16,/* name -- set at load time */ + 0, 0, 0, 0, /* shmem addresses */ + 0x000, /* ioport */ + 0, /* irq line */ + 0, 0, 0, /* various flags: init to 0 */ + NULL, /* next ptr */ + iucv_init, /* init function, fill other fields with NULL's */ + }, + { + iucv_names+24,/* name -- set at load time */ + 0, 0, 0, 0, /* shmem addresses */ + 0x000, /* ioport */ + 0, /* irq line */ + 0, 0, 0, /* various flags: init to 0 */ + NULL, /* next ptr */ + iucv_init, /* init function, fill other fields with NULL's */ + }, + { + iucv_names+32,/* name -- set at load time */ + 0, 0, 0, 0, /* shmem addresses */ + 0x000, /* ioport */ + 0, /* irq line */ + 0, 0, 0, /* various flags: init to 0 */ + NULL, /* next ptr */ + iucv_init, /* init function, fill other fields with NULL's */ + }, + { + iucv_names+40,/* name -- set at load time */ + 0, 0, 0, 0, /* shmem addresses */ + 0x000, /* ioport */ + 0, /* irq line */ + 0, 0, 0, /* various flags: init to 0 */ + NULL, /* next ptr */ + iucv_init, /* init function, fill other fields with NULL's */ + }, + { + iucv_names+48,/* name -- set at load time */ + 0, 0, 0, 0, /* shmem addresses */ + 0x000, /* ioport */ + 0, /* irq line */ + 0, 0, 0, /* various flags: init to 0 */ + NULL, /* next ptr */ + iucv_init, /* init function, fill other fields with NULL's */ + }, + { + iucv_names+56,/* name -- set at load time */ + 0, 0, 0, 0, /* shmem addresses */ + 0x000, /* ioport */ + 0, /* irq line */ + 0, 0, 0, /* various flags: init to 0 */ + NULL, /* next ptr */ + iucv_init, /* init function, fill other fields with NULL's */ + }, + { + iucv_names+64,/* name -- set at load time */ + 0, 0, 0, 0, /* shmem addresses */ + 0x000, /* ioport */ + 0, /* irq line */ + 0, 0, 0, /* various flags: init to 0 */ + NULL, /* next ptr */ + iucv_init, /* init function, fill other fields with NULL's */ + }, + { + iucv_names+72,/* name -- set at load time */ + 0, 0, 0, 0, /* shmem addresses */ + 0x000, /* ioport */ + 0, /* irq line */ + 0, 0, 0, /* various flags: init to 0 */ + NULL, /* next ptr */ + iucv_init, /* init function, fill other fields with NULL's */ + } +}; + diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/s390/net/iucv.h linux/drivers/s390/net/iucv.h --- v2.3.99-pre7/linux/drivers/s390/net/iucv.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/s390/net/iucv.h Fri May 12 11:41:44 2000 @@ -0,0 +1,146 @@ +/* + * drivers/s390/net/iucv.h + * Network driver for VM using iucv + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Stefan Hegewald + * Hartmut Penner + */ + +#ifndef _IUCV_H +#define _IUCV_H + + +#define UCHAR unsigned char +#define USHORT unsigned short +#define ULONG unsigned long + +#define DEFAULT_BUFFERSIZE 2048 +#define DEFAULT_FN_LENGTH 27 +#define TRANSFERLENGTH 10 + + + +/* function ID's */ +#define RETRIEVE_BUFFER 2 +#define REPLY 3 +#define SEND 4 +#define RECEIVE 5 +#define ACCEPT 10 +#define CONNECT 11 +#define DECLARE_BUFFER 12 +#define SEVER 15 +#define SETMASK 16 +#define SETCMASK 17 +#define PURGE 9999 + +/* structures */ +typedef struct { + USHORT res0; + UCHAR ipflags1; + UCHAR iprcode; + ULONG res1; + ULONG res2; + ULONG ipbfadr1; + ULONG res[6]; +} DCLBFR_T; + +typedef struct { + USHORT ippathid; + UCHAR ipflags1; + UCHAR iprcode; + USHORT ipmsglim; + USHORT res1; + UCHAR ipvmid[8]; + UCHAR ipuser[16]; + UCHAR iptarget[8]; +} CONNECT_T; + +typedef struct { + USHORT ippathid; + UCHAR ipflags1; + UCHAR iprcode; + USHORT ipmsglim; + USHORT res1; + UCHAR res2[8]; + UCHAR ipuser[16]; + UCHAR res3[8]; +} ACCEPT_T; + +typedef struct { + USHORT ippathid; + UCHAR ipflags1; + UCHAR iprcode; + ULONG ipmsgid; + ULONG iptrgcls; + ULONG ipbfadr1; + ULONG ipbfln1f; + ULONG ipsrccls; + ULONG ipmsgtag; + ULONG ipbfadr2; + ULONG ipbfln2f; + ULONG res; +} SEND_T; + +typedef struct { + USHORT ippathid; + UCHAR ipflags1; + UCHAR iprcode; + ULONG ipmsgid; + ULONG iptrgcls; + ULONG iprmmsg1; + ULONG iprmmsg2; + ULONG res1[2]; + ULONG ipbfadr2; + ULONG ipbfln2f; + ULONG res2; +} REPLY_T; + +typedef struct { + USHORT ippathid; + UCHAR ipflags1; + UCHAR iprcode; + ULONG ipmsgid; + ULONG iptrgcls; + ULONG ipbfadr1; + ULONG ipbfln1f; + ULONG res1[3]; + ULONG ipbfln2f; + ULONG res2; +} RECEIVE_T; + +typedef struct { + USHORT ippathid; + UCHAR ipflags1; + UCHAR iprcode; + ULONG res1[3]; + UCHAR ipuser[16]; + ULONG res2[2]; +} SEVER_T; + +typedef struct { + UCHAR ipmask; + UCHAR res1[2]; + UCHAR iprcode; + ULONG res2[9]; +} MASK_T; + +typedef struct { + USHORT ippathid; + UCHAR ipflags1; + UCHAR iptype; + ULONG ipmsgid; + ULONG ipaudit; + ULONG iprmmsg1; + ULONG iprmmsg2; + ULONG ipsrccls; + ULONG ipmsgtag; + ULONG ipbfadr2; + ULONG ipbfln2f; + UCHAR ippollfg; + UCHAR res2[3]; +} INTERRUPT_T; + + +#endif diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/sound/maestro.c linux/drivers/sound/maestro.c --- v2.3.99-pre7/linux/drivers/sound/maestro.c Wed Apr 26 16:34:08 2000 +++ linux/drivers/sound/maestro.c Fri May 12 12:07:06 2000 @@ -2381,8 +2381,20 @@ struct ess_state *s = (struct ess_state *)file->private_data; unsigned long flags; unsigned int mask = 0; + int ret; VALIDATE_STATE(s); + +/* In 0.14 prog_dmabuf always returns success anyway ... */ + if (file->f_mode & FMODE_WRITE) { + if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0))) + return POLLERR; + } + if (file->f_mode & FMODE_READ) { + if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1))) + return POLLERR; + } + if (file->f_mode & FMODE_WRITE) poll_wait(file, &s->dma_dac.wait, wait); if (file->f_mode & FMODE_READ) diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/sound/via82cxxx_audio.c linux/drivers/sound/via82cxxx_audio.c --- v2.3.99-pre7/linux/drivers/sound/via82cxxx_audio.c Thu May 11 15:30:08 2000 +++ linux/drivers/sound/via82cxxx_audio.c Fri May 12 11:59:06 2000 @@ -11,7 +11,7 @@ */ -#define VIA_VERSION "1.1.5" +#define VIA_VERSION "1.1.6" #include @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -30,8 +31,9 @@ #include #include -#include "sound_config.h" -#include "soundmodule.h" +/* much better to duplicate this value than include + * drivers/sound/sound_config.h just for this definition */ +#define SND_DEV_DSP16 5 #undef VIA_DEBUG /* define to enable debugging output and checks */ @@ -286,7 +288,6 @@ static u16 via_ac97_read_reg (struct ac97_codec *codec, u8 reg); static void via_ac97_write_reg (struct ac97_codec *codec, u8 reg, u16 value); static u8 via_ac97_wait_idle (struct via_info *card); -static u32 via_ac97_wait_valid (struct via_info *card); static void via_chan_free (struct via_info *card, struct via_channel *chan); static void via_chan_clear (struct via_channel *chan); @@ -403,11 +404,6 @@ static int via_set_rate (struct via_info *card, unsigned rate, int inhale_deeply) { -#if 0 - unsigned long flags; - u32 status; - u8 status8; -#endif DPRINTK ("ENTER, rate = %d, inhale = %s\n", rate, inhale_deeply ? "yes" : "no"); @@ -415,37 +411,12 @@ if (rate > 48000) rate = 48000; if (rate < 4000) rate = 4000; -#if 0 - status8 = via_ac97_wait_idle (card); - if (status8 & VIA_CR83_BUSY) { - DPRINTK ("EXIT, status=0x%X, returning -EIO\n", status); - return -EIO; - } - - if (inhale_deeply) { - card->ch_in.rate = rate; - - spin_lock_irqsave (&card->lock, flags); - outl (VIA_SET_RATE_IN + rate, - card->baseaddr + VIA_BASE0_AC97_CTRL); - spin_unlock_irqrestore (&card->lock, flags); - } else { - card->ch_out.rate = rate; - - spin_lock_irqsave (&card->lock, flags); - outl (VIA_SET_RATE_OUT + rate, - card->baseaddr + VIA_BASE0_AC97_CTRL); - spin_unlock_irqrestore (&card->lock, flags); - } - -#else via_ac97_write_reg (&card->ac97, AC97_POWER_CONTROL, (via_ac97_read_reg (&card->ac97, AC97_POWER_CONTROL) & ~0x0200) | 0x0200); via_ac97_write_reg (&card->ac97, AC97_PCM_FRONT_DAC_RATE, rate); via_ac97_write_reg (&card->ac97, AC97_POWER_CONTROL, via_ac97_read_reg (&card->ac97, AC97_POWER_CONTROL) & ~0x0200); -#endif DPRINTK ("EXIT, returning 0\n"); return rate; @@ -769,38 +740,6 @@ } -static u32 via_ac97_wait_valid (struct via_info *card) -{ - u32 tmp; - int counter = VIA_COUNTER_LIMIT; - - DPRINTK ("ENTER\n"); - - assert (card != NULL); - assert (card->pdev != NULL); - - do { - if (current->need_resched) - schedule (); - - spin_lock_irq (&card->lock); - tmp = inl (card->baseaddr + VIA_BASE0_AC97_CTRL); - spin_unlock_irq (&card->lock); - - udelay (10); - - if (tmp & VIA_CR80_FIRST_CODEC_VALID) { - DPRINTK ("EXIT valid, tmp=0x%X, cnt=%d\n", tmp, counter); - return tmp; - } - } while ((tmp & VIA_CR80_BUSY) && (counter-- > 0)); - - DPRINTK ("EXIT, tmp=0x%X, cnt=%d%s\n", tmp, counter, - counter > 0 ? "" : ", counter limit reached"); - return tmp; -} - - static u16 via_ac97_read_reg (struct ac97_codec *codec, u8 reg) { u32 data; @@ -957,6 +896,7 @@ }; +#if 0 /* values reasoned from debugging dumps of via's driver */ static struct { u8 reg; u16 data; @@ -976,6 +916,7 @@ { 0x2, 0x808 }, { 0x18, 0x808 }, }; +#endif static int __init via_ac97_reset (struct via_info *card) @@ -983,7 +924,6 @@ struct pci_dev *pdev = card->pdev; u8 tmp8; u16 tmp16; - size_t idx; DPRINTK ("ENTER\n"); @@ -1015,8 +955,6 @@ } #endif -#if 1 - /* * reset AC97 controller: enable, disable, enable * pause after each command for good luck @@ -1032,35 +970,6 @@ VIA_CR41_AC97_ENABLE | VIA_CR41_PCM_ENABLE | VIA_CR41_VRA | VIA_CR41_AC97_RESET); udelay (100); -#endif - -#if 0 - /* - * reset AC97 controller - */ - pci_read_config_byte(pdev, 0x08, &tmp8); - if ((tmp8 & 0xff) >= 0x20 ) { - pci_read_config_byte(pdev, 0x42, &tmp8); - pci_write_config_byte(pdev, 0x42,(tmp8 & 0x3f)); - } - udelay (100); - - /* init other mixer defaults */ - for (idx = 0; idx < arraysize(mixer_init_vals); idx++) { - via_ac97_write_reg (&card->ac97, - mixer_init_vals[idx].reg, - mixer_init_vals[idx].data); - udelay (20); - } - - pci_write_config_byte (pdev, 0x41, 0xc0); - udelay (10); - pci_read_config_byte (pdev, 0x41, &tmp8); - udelay (10); - pci_write_config_byte (pdev, 0x41, tmp8 | 0x0f); - udelay (10); - -#endif /* disable legacy stuff */ pci_write_config_byte (pdev, 0x42, 0x00); @@ -1073,16 +982,6 @@ /* disable all codec GPI interrupts */ outl (0, pci_resource_start (pdev, 0) + 0x8C); -#if 0 /* ALSA */ - via_ac97_write_reg (&card->ac97, AC97_EXTENDED_STATUS, 0x0009); -#if 0 - via_ac97_write_reg (&card->ac97, AC97_POWER_CONTROL, - via_ac97_read_reg (&card->ac97, AC97_POWER_CONTROL) | 0x0300); -#endif - via_ac97_write_reg (&card->ac97, AC97_EXTENDED_STATUS, - via_ac97_read_reg (&card->ac97, AC97_EXTENDED_STATUS) | 0xe800); -#endif - /* enable variable rate */ tmp16 = via_ac97_read_reg (&card->ac97, 0x2A); via_ac97_write_reg (&card->ac97, 0x2A, tmp16 | 0x01); @@ -1836,24 +1735,24 @@ return -EINVAL; if (val > 0) { rc = 0; - spin_lock_irqsave (&card->lock, flags); + spin_lock_irq (&card->lock); if (rc == 0 && rd) rc = via_chan_set_speed (card, &card->ch_in, val); if (rc == 0 && wr) rc = via_chan_set_speed (card, &card->ch_out, val); - spin_unlock_irqrestore (&card->lock, flags); + spin_unlock_irq (&card->lock); if (rc <= 0) return rc ? rc : -EINVAL; val = rc; } else { - spin_lock_irqsave (&card->lock, flags); + spin_lock_irq (&card->lock); if (rd) val = card->ch_in.rate; else if (wr) val = card->ch_out.rate; else val = 0; - spin_unlock_irqrestore (&card->lock, flags); + spin_unlock_irq (&card->lock); } DPRINTK("SPEED EXIT, returning %d\n", val); return put_user (val, (int *)arg); @@ -1868,18 +1767,16 @@ /* stop recording/playback immediately */ case SNDCTL_DSP_RESET: + spin_lock_irq (&card->lock); if (rd) { - spin_lock_irqsave (&card->lock, flags); via_chan_clear (&card->ch_in); via_chan_pcm_fmt (card, &card->ch_in, 1); - spin_unlock_irqrestore (&card->lock, flags); } if (wr) { - spin_lock_irqsave (&card->lock, flags); via_chan_clear (&card->ch_out); via_chan_pcm_fmt (card, &card->ch_out, 1); - spin_unlock_irqrestore (&card->lock, flags); } + spin_unlock_irq (&card->lock); DPRINTK("RESET EXIT, returning 0\n"); return 0; @@ -2109,7 +2006,6 @@ int len = 0; u8 r40, r41, r42, r44; struct via_info *card = data; - u16 tmp16; DPRINTK ("ENTER\n"); @@ -2306,41 +2202,11 @@ goto err_out; } -#if 0 - /* chipset init copied from via */ - pci_write_config_byte(pdev, 0x41,(0xc0)); - udelay(10); - pci_read_config_byte(pdev, 0x41, &tmp); - udelay(10); - pci_write_config_byte(pdev, 0x41,(tmp | 0x0f)); - udelay(10); - pci_read_config_byte(pdev, 0x42, &tmp); - udelay(10); - pci_write_config_byte(pdev, 0x42,(tmp | 0x3f)); -#endif - if (pci_enable_device (pdev)) { rc = -EIO; goto err_out_none; } -#if 0 - /* chipset init copied from ALSA */ - pci_write_config_byte(pdev, 0x42, 0); - pci_write_config_byte(pdev, 0x41, 0x40); - udelay(100); - pci_write_config_byte(pdev, 0x41, 0x60); - udelay(10); - pci_write_config_byte(pdev, 0x41, 0xCC); - udelay(10); - - { - u32 data = ((AC97_POWER_CONTROL & 0x7F) << 16) | 0x0000; - udelay(100); - outl (data, pci_resource_start (pdev, 0) + VIA_BASE0_AC97_CTRL); - } -#endif - card = kmalloc (sizeof (*card), GFP_KERNEL); if (!card) { printk (KERN_ERR PFX "out of memory, aborting\n"); diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/usb/Config.in linux/drivers/usb/Config.in --- v2.3.99-pre7/linux/drivers/usb/Config.in Thu May 11 15:30:08 2000 +++ linux/drivers/usb/Config.in Fri May 12 11:23:09 2000 @@ -43,7 +43,7 @@ dep_tristate ' USB Kodak DC-2xx Camera support' CONFIG_USB_DC2XX $CONFIG_USB if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then dep_tristate ' USB Mustek MDC800 Digital Camera support (EXPERIMENTAL)' CONFIG_USB_MDC800 $CONFIG_USB - dep_tristate ' USB Mass Storage support (EXPERIMENTAL)' CONFIG_USB_STORAGE $CONFIG_USB m + dep_tristate ' USB Mass Storage support (EXPERIMENTAL)' CONFIG_USB_STORAGE $CONFIG_USB if [ "$CONFIG_USB_STORAGE" != "n" ]; then bool ' USB Mass Storage verbose debug' CONFIG_USB_STORAGE_DEBUG fi diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/usb/uhci.c linux/drivers/usb/uhci.c --- v2.3.99-pre7/linux/drivers/usb/uhci.c Thu May 11 15:30:08 2000 +++ linux/drivers/usb/uhci.c Fri May 12 13:21:55 2000 @@ -289,10 +289,10 @@ if (!list_empty(&td->list)) dbg("td is still in URB list!"); - kmem_cache_free(uhci_td_cachep, td); - if (td->dev) usb_dec_dev_use(td->dev); + + kmem_cache_free(uhci_td_cachep, td); } static struct uhci_qh *uhci_alloc_qh(struct usb_device *dev) @@ -318,10 +318,10 @@ static void uhci_free_qh(struct uhci_qh *qh) { - kmem_cache_free(uhci_qh_cachep, qh); - if (qh->dev) usb_dec_dev_use(qh->dev); + + kmem_cache_free(uhci_qh_cachep, qh); } static void uhci_insert_qh(struct uhci *uhci, struct uhci_qh *skelqh, struct uhci_qh *qh) diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/video/acornfb.c linux/drivers/video/acornfb.c --- v2.3.99-pre7/linux/drivers/video/acornfb.c Wed Apr 26 16:34:08 2000 +++ linux/drivers/video/acornfb.c Fri May 12 11:21:20 2000 @@ -1,7 +1,7 @@ /* * linux/drivers/video/acornfb.c * - * Copyright (C) 1998,1999 Russell King + * Copyright (C) 1998-2000 Russell King * * Frame buffer code for Acorn platforms * @@ -958,9 +958,6 @@ else display = &global_disp; - if (!current_par.allow_modeset && con != -1) - return -EINVAL; - err = acornfb_decode_var(var, con, &visual); if (err) return err; @@ -1088,9 +1085,7 @@ outl(control, IOMD_VIDCR); #endif acornfb_update_dma(var); - - if (current_par.allow_modeset) - acornfb_set_timing(var); + acornfb_set_timing(var); if (display->cmap.len) cmap = &display->cmap; @@ -1375,37 +1370,49 @@ static void __init acornfb_parse_mon(char *opt) { + char *p = opt; + current_par.montype = -2; - fb_info.monspecs.hfmin = simple_strtoul(opt, &opt, 0); - if (*opt == '-') - fb_info.monspecs.hfmax = simple_strtoul(opt + 1, &opt, 0); + fb_info.monspecs.hfmin = simple_strtoul(p, &p, 0); + if (*p == '-') + fb_info.monspecs.hfmax = simple_strtoul(p + 1, &p, 0); else fb_info.monspecs.hfmax = fb_info.monspecs.hfmin; - if (*opt != ':') - return; + if (*p != ':') + goto bad; - fb_info.monspecs.vfmin = simple_strtoul(opt + 1, &opt, 0); - if (*opt == '-') - fb_info.monspecs.vfmax = simple_strtoul(opt + 1, &opt, 0); + fb_info.monspecs.vfmin = simple_strtoul(p + 1, &p, 0); + if (*p == '-') + fb_info.monspecs.vfmax = simple_strtoul(p + 1, &p, 0); else fb_info.monspecs.vfmax = fb_info.monspecs.vfmin; - if (*opt != ':') - return; + if (*p != ':') + goto check_values; - fb_info.monspecs.dpms = simple_strtoul(opt + 1, &opt, 0); + fb_info.monspecs.dpms = simple_strtoul(p + 1, &p, 0); - if (*opt != ':') - return; + if (*p != ':') + goto check_values; - init_var.width = simple_strtoul(opt + 1, &opt, 0); + init_var.width = simple_strtoul(p + 1, &p, 0); - if (*opt != ':') - return; + if (*p != ':') + goto check_values; + + init_var.height = simple_strtoul(p + 1, NULL, 0); - init_var.height = simple_strtoul(opt + 1, NULL, 0); +check_values: + if (fb_info.monspecs.hfmax < fb_info.monspecs.hfmin || + fb_info.monspecs.vfmax < fb_info.monspecs.vfmin) + goto bad; + return; + +bad: + printk(KERN_ERR "Acornfb: bad monitor settings: %s\n", opt); + current_par.montype = -1; } static void __init @@ -1574,9 +1581,10 @@ if (current_par.montype == -1 || current_par.montype > NR_MONTYPES) current_par.montype = 4; - if (current_par.montype > 0) + if (current_par.montype > 0) { fb_info.monspecs = monspecs[current_par.montype]; - fb_info.monspecs.dpms = current_par.dpms; + fb_info.monspecs.dpms = current_par.dpms; + } /* * Try to select a suitable default mode @@ -1667,7 +1675,6 @@ current_par.screen_size = size; current_par.palette_size = VIDC_PALETTE_SIZE; - current_par.allow_modeset = 1; /* * Lookup the timing for this resolution. If we can't @@ -1683,13 +1690,6 @@ printk("Acornfb: no valid mode found\n"); } - /* - * Again, if this does not succeed, then we disallow - * changes to the resolution parameters. - */ - if (acornfb_set_var(&init_var, -1, &fb_info)) - current_par.allow_modeset = 0; - h_sync = 1953125000 / init_var.pixclock; h_sync = h_sync * 512 / (init_var.xres + init_var.left_margin + init_var.right_margin + init_var.hsync_len); @@ -1702,6 +1702,15 @@ current_par.using_vram ? 'V' : 'D', VIDC_NAME, init_var.xres, init_var.yres, h_sync / 1000, h_sync % 1000, v_sync); + + printk(KERN_INFO "Acornfb: Monitor: %d.%03d-%d.%03dkHz, %d-%dHz%s\n", + fb_info.monspecs.hfmin / 1000, fb_info.monspecs.hfmin % 1000, + fb_info.monspecs.hfmax / 1000, fb_info.monspecs.hfmax % 1000, + fb_info.monspecs.vfmin, fb_info.monspecs.vfmax, + fb_info.monspecs.dpms ? ", DPMS" : ""); + + if (acornfb_set_var(&init_var, -1, &fb_info)) + printk(KERN_ERR "Acornfb: unable to set display parameters\n"); if (register_framebuffer(&fb_info) < 0) return -EINVAL; diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/video/acornfb.h linux/drivers/video/acornfb.h --- v2.3.99-pre7/linux/drivers/video/acornfb.h Mon Nov 1 13:56:26 1999 +++ linux/drivers/video/acornfb.h Fri May 12 11:21:20 2000 @@ -52,7 +52,6 @@ unsigned int palette_size; signed int montype; signed int currcon; - unsigned int allow_modeset : 1; unsigned int using_vram : 1; unsigned int dpms : 1; diff -u --recursive --new-file v2.3.99-pre7/linux/drivers/video/cyber2000fb.c linux/drivers/video/cyber2000fb.c --- v2.3.99-pre7/linux/drivers/video/cyber2000fb.c Wed Apr 26 16:34:08 2000 +++ linux/drivers/video/cyber2000fb.c Fri May 12 11:21:20 2000 @@ -1,11 +1,19 @@ /* - * linux/drivers/video/cyber2000fb.c + * Linux/drivers/video/cyber2000fb.c * * Copyright (C) 1998-2000 Russell King * - * Integraphics Cyber2000 frame buffer device + * Integraphics CyberPro 2000, 2010 and 5000 frame buffer device * - * Based on cyberfb.c + * Based on cyberfb.c. + * + * Note that we now use the new fbcon fix, var and cmap scheme. We do still + * have to check which console is the currently displayed one however, since + * especially for the colourmap stuff. Once fbcon has been fully migrated, + * we can kill the last 5 references to cfb->currcon. + * + * We also use the new hotplug PCI subsystem. This doesn't work fully in + * the case of multiple CyberPro cards yet however. */ #include #include @@ -31,34 +39,41 @@ #include